diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index a328682..a7ed8d4 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -1,10 +1,31 @@ --- + ## Summary -- -## Changes -- [ ] Web build/tests pass -- [ ] Android build/tests pass + + +## Type of Change + +- [ ] Bug fix +- [ ] New feature +- [ ] Dependency update +- [ ] Documentation update +- [ ] Refactor / code quality + +## Platforms Affected + +- [ ] Web (TypeScript) +- [ ] Android (Kotlin) +- [ ] Flutter (Dart) + +## Checklist + +- [ ] Web build/tests pass (`npm run test:web && npm run build:web`) +- [ ] Android build/tests pass (`cd packages/core/android && ./gradlew test`) +- [ ] Flutter build/tests pass (`cd packages/core/flutter && flutter test`) +- [ ] API parity maintained across all affected platforms - [ ] Docs updated (if needed) +- [ ] CHANGELOG updated (if needed) +- [ ] Version bumped (if releasing) Closes # diff --git a/.github/workflows/flutter.yml b/.github/workflows/flutter.yml new file mode 100644 index 0000000..0251a59 --- /dev/null +++ b/.github/workflows/flutter.yml @@ -0,0 +1,72 @@ +name: Flutter CI + +on: + push: + branches: [release, develop] + paths: + - "packages/core/flutter/**" + - ".github/workflows/flutter.yml" + pull_request: + branches: [release, develop] + paths: + - "packages/core/flutter/**" + - ".github/workflows/flutter.yml" + workflow_dispatch: + +permissions: + contents: read + pull-requests: read + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + +jobs: + flutter: + name: Flutter (lint+build+test+docs) + runs-on: ubuntu-latest + if: ${{ !contains(github.event.head_commit.message, '[skip flutter]') }} + + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + - name: Setup Flutter + uses: subosito/flutter-action@v2 + with: + flutter-version: "3.27.4" + channel: "stable" + + - name: Verify Flutter installation + run: flutter --version + + - name: Get dependencies + working-directory: packages/core/flutter + run: flutter pub get + + - name: Analyze code + working-directory: packages/core/flutter + run: flutter analyze + + - name: Run tests + working-directory: packages/core/flutter + run: flutter test --coverage + + - name: Upload coverage to Codecov + uses: codecov/codecov-action@v5 + with: + file: packages/core/flutter/coverage/lcov.info + flags: flutter + name: flutter-coverage + + - name: Generate docs (dart doc) + working-directory: packages/core/flutter + run: dart doc --output ../../../docs/api/flutter || echo "Dart doc generation failed" + + - name: Upload flutter docs + uses: actions/upload-artifact@v4 + with: + name: flutter-docs-${{ github.run_id }} + path: docs/api/flutter + if-no-files-found: ignore + retention-days: 30 diff --git a/.github/workflows/web.yml b/.github/workflows/web.yml index 0d54a86..1c9e6c9 100644 --- a/.github/workflows/web.yml +++ b/.github/workflows/web.yml @@ -3,20 +3,22 @@ name: Web CI on: push: branches: [release, develop] - paths: - - 'packages/**' - - '!packages/core/android/**' - - 'package*.json' - - 'lerna.json' - - '.github/workflows/web.yml' + paths: + - "packages/**" + - "!packages/core/android/**" + - "!packages/core/flutter/**" + - "package*.json" + - "lerna.json" + - ".github/workflows/web.yml" pull_request: branches: [release, develop] paths: - - 'packages/**' - - '!packages/core/android/**' - - 'package*.json' - - 'lerna.json' - - '.github/workflows/web.yml' + - "packages/**" + - "!packages/core/android/**" + - "!packages/core/flutter/**" + - "package*.json" + - "lerna.json" + - ".github/workflows/web.yml" workflow_dispatch: permissions: @@ -32,7 +34,7 @@ jobs: name: Web (lint+build+test+docs) runs-on: ubuntu-latest if: ${{ !contains(github.event.head_commit.message, '[skip web]') }} - + steps: - name: Checkout code uses: actions/checkout@v4 @@ -40,8 +42,8 @@ jobs: - name: Setup Node.js uses: actions/setup-node@v4 with: - node-version: '20.x' - cache: 'npm' + node-version: "20.x" + cache: "npm" - name: Install dependencies run: npm ci diff --git a/.gitignore b/.gitignore index 75a5e9d..c8fc506 100644 --- a/.gitignore +++ b/.gitignore @@ -7,6 +7,7 @@ node_modules dist build lib +!packages/core/flutter/lib .next out @@ -48,4 +49,17 @@ build/ captures/ .externalNativeBuild .cxx -local.properties \ No newline at end of file +local.properties + +# Flutter/Dart specific +.dart_tool/ +.flutter-plugins +.flutter-plugins-dependencies +.packages +.pub-cache/ +.pub/ +pubspec.lock +*.g.dart + +# Generated documentation (regenerated by CI) +docs/api/ \ No newline at end of file diff --git a/README.md b/README.md index 3078360..c826e69 100644 --- a/README.md +++ b/README.md @@ -3,26 +3,29 @@ [![Version](https://img.shields.io/badge/version-0.1.0--alpha-orange.svg)](https://github.com/Kompkit/KompKit/releases) [![Web CI](https://github.com/Kompkit/KompKit/actions/workflows/web.yml/badge.svg?branch=develop)](https://github.com/Kompkit/KompKit/actions/workflows/web.yml) [![Kotlin CI](https://github.com/Kompkit/KompKit/actions/workflows/android.yml/badge.svg?branch=develop)](https://github.com/Kompkit/KompKit/actions/workflows/android.yml) +[![Flutter CI](https://github.com/Kompkit/KompKit/actions/workflows/flutter.yml/badge.svg?branch=develop)](https://github.com/Kompkit/KompKit/actions/workflows/flutter.yml) [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT) [![TypeScript](https://img.shields.io/badge/TypeScript-007ACC?logo=typescript&logoColor=white)](https://www.typescriptlang.org/) [![Kotlin](https://img.shields.io/badge/Kotlin-0095D5?logo=kotlin&logoColor=white)](https://kotlinlang.org/) +[![Dart](https://img.shields.io/badge/Dart-0175C2?logo=dart&logoColor=white)](https://dart.dev/) > **⚠️ Alpha Release**: This is an early alpha version. APIs may change before stable release. -A lightweight cross-platform utility kit providing essential functions for Android (Kotlin) and Web (TypeScript) development. Built as a monorepo with identical APIs across platforms. +A lightweight cross-platform utility kit providing essential functions for Web (TypeScript), Android (Kotlin), and Flutter (Dart) development. Built as a monorepo with identical APIs across platforms. ## Overview -KompKit provides essential utility functions that work seamlessly across web (TypeScript) and Android (Kotlin) platforms. Built with developer experience in mind, it offers identical APIs across platforms while leveraging platform-specific optimizations. +KompKit provides essential utility functions that work seamlessly across Web (TypeScript), Android (Kotlin), and Flutter (Dart) platforms. Built with developer experience in mind, it offers identical APIs across platforms while leveraging platform-specific optimizations. ### Monorepo Structure -| Module | Platform | Description | Status | -|--------|----------|-------------|--------| -| `packages/core/web` | TypeScript | Web utilities with Node.js support | ✅ Alpha | -| `packages/core/android` | Kotlin JVM | Android utilities with coroutines | ✅ Alpha | -| `docs/` | Documentation | API docs, guides, and examples | ✅ Alpha | -| `.github/workflows/` | CI/CD | Automated testing and validation | ✅ Active | +| Module | Platform | Description | Status | +| ----------------------- | ------------- | ----------------------------------------- | --------- | +| `packages/core/web` | TypeScript | Web utilities with Node.js support | ✅ Alpha | +| `packages/core/android` | Kotlin JVM | Android utilities with coroutines | ✅ Alpha | +| `packages/core/flutter` | Dart | Flutter/Dart utilities with async support | ✅ Alpha | +| `docs/` | Documentation | API docs, guides, and examples | ✅ Alpha | +| `.github/workflows/` | CI/CD | Automated testing and validation | ✅ Active | ### Core Utilities @@ -32,11 +35,11 @@ KompKit provides essential utility functions that work seamlessly across web (Ty ### Key Features -- ✅ **Cross-platform compatibility** - Identical APIs for web and Android +- ✅ **Cross-platform compatibility** - Identical APIs for Web, Android, and Flutter - ✅ **TypeScript support** - Full type safety and IntelliSense - ✅ **Zero dependencies** - Lightweight with no external dependencies - ✅ **Comprehensive testing** - 100% test coverage across platforms -- ✅ **Modern tooling** - Built with latest TypeScript 5.6+ and Kotlin 2.1+ +- ✅ **Modern tooling** - Built with latest TypeScript 5.7+ and Kotlin 2.3+ - ✅ **Rich documentation** - Auto-generated API docs with examples - ✅ **CI/CD Ready** - Automated testing with GitHub Actions @@ -45,7 +48,8 @@ KompKit provides essential utility functions that work seamlessly across web (Ty ### Prerequisites - **Web**: Node.js 20+ and npm/yarn -- **Android**: JDK 17+ and Kotlin 2.1+ +- **Android**: JDK 17+ and Kotlin 2.3+ +- **Flutter**: Flutter 3.0+ and Dart 3.0+ ### Installation @@ -85,23 +89,43 @@ dependencies { } ``` +#### Flutter Development + +```bash +# Clone the repository +git clone https://github.com/Kompkit/KompKit.git + +# Add to your Flutter project's pubspec.yaml +dependencies: + kompkit_core: + path: path/to/KompKit/packages/core/flutter + +# Get dependencies +flutter pub get + +# Run tests +flutter test +``` + ### Quick Start Once installed, you can import and use KompKit utilities: **TypeScript/JavaScript:** + ```typescript -import { debounce, isEmail, formatCurrency } from '@kompkit/core'; +import { debounce, isEmail, formatCurrency } from "@kompkit/core"; const search = debounce((query: string) => { - console.log('Searching:', query); + console.log("Searching:", query); }, 300); -console.log(isEmail('user@example.com')); // true +console.log(isEmail("user@example.com")); // true console.log(formatCurrency(1234.56)); // "1.234,56 €" ``` **Kotlin:** + ```kotlin import com.kompkit.core.* @@ -113,6 +137,19 @@ println(isEmail("user@example.com")) // true println(formatCurrency(1234.56)) // "1.234,56 €" ``` +**Dart/Flutter:** + +```dart +import 'package:kompkit_core/kompkit_core.dart'; + +final search = debounce((String query) { + print('Searching: $query'); +}, const Duration(milliseconds: 300)); + +print(isEmail('user@example.com')); // true +print(formatCurrency(1234.56)); // "1.234,56 €" +``` + ## Documentation ### 📚 Detailed Guides @@ -136,16 +173,21 @@ println(formatCurrency(1234.56)) // "1.234,56 €" KompKit/ ├── .github/workflows/ # CI/CD pipelines │ ├── web.yml # Web package testing -│ └── android.yml # Kotlin package testing +│ ├── android.yml # Kotlin package testing +│ └── flutter.yml # Flutter/Dart package testing ├── packages/core/ │ ├── web/ # TypeScript package │ │ ├── src/ # Source files -│ │ ├── tests/ # Test files +│ │ ├── tests/ # Test files │ │ └── package.json -│ └── android/ # Kotlin JVM package -│ ├── src/main/kotlin/ # Source files -│ ├── src/test/kotlin/ # Test files -│ └── build.gradle.kts +│ ├── android/ # Kotlin JVM package +│ │ ├── src/main/kotlin/ # Source files +│ │ ├── src/test/kotlin/ # Test files +│ │ └── build.gradle.kts +│ └── flutter/ # Dart package +│ ├── src/ # Source files +│ ├── test/ # Test files +│ └── pubspec.yaml ├── docs/ # Documentation │ ├── api/ # Generated API docs │ └── *.md # Guides and references @@ -154,19 +196,21 @@ KompKit/ ## Version Information -- **Current Version**: `0.1.0-alpha` -- **Minimum Requirements**: +- **Current Version**: `0.2.0-alpha` +- **Minimum Requirements**: - Node.js 20+ (Web) - JDK 17+ (Android) - - TypeScript 5.6+ - - Kotlin 2.1+ + - Flutter 3.0+ (Flutter) + - TypeScript 5.7+ + - Kotlin 2.3+ + - Dart 3.0+ ## Contributing We welcome contributions! Please see our [Contributing Guide](./docs/CONTRIBUTING.md) for details on: - Development setup -- Code style and conventions +- Code style and conventions - Testing requirements - Pull request process @@ -183,4 +227,3 @@ This project is licensed under the MIT License - see the [LICENSE](LICENSE) file --- > **Alpha Notice**: This project is in active development. APIs may change before the stable 1.0 release. We recommend pinning to specific versions in production applications. - diff --git a/VERSION b/VERSION index 388bb06..e7a2edf 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -0.1.0-alpha +0.2.0-alpha diff --git a/docs/ARCHITECTURE.md b/docs/ARCHITECTURE.md index 78c09df..ee7e678 100644 --- a/docs/ARCHITECTURE.md +++ b/docs/ARCHITECTURE.md @@ -1,6 +1,6 @@ # Architecture Overview -This document describes the architecture and design decisions behind KompKit, a cross-platform utility library for TypeScript and Kotlin. +This document describes the architecture and design decisions behind KompKit, a cross-platform utility library for TypeScript, Kotlin, and Dart. ## Design Philosophy @@ -8,7 +8,7 @@ This document describes the architecture and design decisions behind KompKit, a KompKit is designed with cross-platform compatibility as the primary goal. Every utility function must: -1. **Maintain API parity** across TypeScript and Kotlin implementations +1. **Maintain API parity** across TypeScript, Kotlin, and Dart implementations 2. **Provide identical behavior** regardless of platform 3. **Use platform-native patterns** while maintaining consistency 4. **Minimize dependencies** to reduce bundle size and complexity @@ -21,7 +21,8 @@ We use a monorepo approach to ensure consistency and simplify development: KompKit/ ├── packages/core/ # Core utility packages │ ├── web/ # TypeScript/JavaScript implementation -│ └── android/ # Kotlin JVM implementation +│ ├── android/ # Kotlin JVM implementation +│ └── flutter/ # Dart/Flutter implementation ├── docs/ # Documentation and guides ├── .github/workflows/ # CI/CD pipelines └── [root configuration] # Lerna, npm, Git configuration @@ -31,14 +32,15 @@ KompKit/ ### Core Modules -| Module | Platform | Purpose | Technology Stack | -|--------|----------|---------|------------------| -| `packages/core/web` | Web/Node.js | TypeScript utilities | TypeScript 5.6+, Vitest, TypeDoc | -| `packages/core/android` | JVM/Android | Kotlin utilities | Kotlin 2.1.0, JUnit, Dokka | +| Module | Platform | Purpose | Technology Stack | +| ----------------------- | ------------ | -------------------- | -------------------------------- | +| `packages/core/web` | Web/Node.js | TypeScript utilities | TypeScript 5.7+, Vitest, TypeDoc | +| `packages/core/android` | JVM/Android | Kotlin utilities | Kotlin 2.3.0, JUnit, Dokka | +| `packages/core/flutter` | Flutter/Dart | Dart utilities | Dart 3.0+, Flutter Test, DartDoc | ### Shared Concepts -Both modules implement identical functionality: +All modules implement identical functionality: - **debounce**: Function execution delay with cancellation - **isEmail**: Email validation using regex patterns @@ -51,54 +53,87 @@ Both modules implement identical functionality: We maintain strict API consistency across platforms: **TypeScript:** + ```typescript export function debounce any>( - fn: T, - wait: number = 250 + fn: T, + wait: number = 250, ): T; export function isEmail(value: string): boolean; export function formatCurrency( - amount: number, - currency: string = 'EUR', - locale: string = 'es-ES' + amount: number, + currency: string = "EUR", + locale: string = "es-ES", ): string; ``` **Kotlin:** + ```kotlin fun debounce( - waitMs: Long = 250L, - scope: CoroutineScope, + waitMs: Long = 250L, + scope: CoroutineScope, dest: (T) -> Unit ): (T) -> Unit fun isEmail(value: String): Boolean fun formatCurrency( - amount: Double, - currency: String = "EUR", + amount: Double, + currency: String = "EUR", locale: Locale = Locale("es", "ES") ): String ``` +**Dart:** + +```dart +Function debounce( + Function fn, + [Duration wait = const Duration(milliseconds: 250)] +); + +VoidCallback debounceVoid( + VoidCallback fn, + [Duration wait = const Duration(milliseconds: 250)] +); + +bool isEmail(String value); + +String formatCurrency( + num amount, { + String currency = "EUR", + String locale = "es_ES", +}); +``` + ### Platform-Specific Adaptations While maintaining API consistency, we leverage platform strengths: #### TypeScript Implementation + - **Closures** for debounce state management - **setTimeout/clearTimeout** for timing control - **Intl.NumberFormat** for currency formatting - **RegExp** for email validation #### Kotlin Implementation + - **Coroutines** for asynchronous debounce operations - **Job cancellation** for timing control - **NumberFormat/Currency** for localized formatting - **Regex** for email validation +#### Dart/Flutter Implementation + +- **Timer** for debounce scheduling and cancellation +- **intl package** (`NumberFormat.currency`) for localized formatting +- **RegExp** for email validation +- **Null safety** with full type-safe APIs + ## Build System Architecture ### Monorepo Management @@ -109,25 +144,27 @@ While maintaining API consistency, we leverage platform strengths: { "workspaces": ["packages/core/web"], "devDependencies": { - "lerna": "^8.0.0", - "tsup": "^8.0.0", - "typescript": "^5.6.0", - "typedoc": "^0.28.14", - "vitest": "^1.6.0" + "lerna": "^8.2.4", + "tsup": "^8.5.0", + "typescript": "^5.7.0", + "typedoc": "^0.28.16", + "vitest": "^3.0.0" } } ``` ### Build Targets -| Platform | Build Tool | Output | Documentation | -|----------|------------|--------|---------------| -| Web | tsup | ESM + CJS + Types | TypeDoc → `docs/api/web/` | -| Kotlin | Gradle | JAR | Dokka → `docs/api/android/` | +| Platform | Build Tool | Output | Documentation | +| -------- | ------------ | ----------------- | ----------------------------- | +| Web | tsup | ESM + CJS + Types | TypeDoc → `docs/api/web/` | +| Kotlin | Gradle | JAR | Dokka → `docs/api/android/` | +| Flutter | Flutter/Dart | Dart package | DartDoc → `docs/api/flutter/` | ### Dependency Strategy **Zero Runtime Dependencies:** + - Web utilities use only browser/Node.js built-ins - Kotlin utilities use only JDK/Kotlin stdlib - Development dependencies isolated to build process @@ -147,7 +184,7 @@ web.yml: - TypeDoc generation - Artifact upload -# Kotlin CI - packages/core/android/** +# Kotlin CI - packages/core/android/** android.yml: - JDK 17 setup - Gradle build (with caching) @@ -174,19 +211,22 @@ android.yml: ``` packages/core/web/tests/ -├── debounce.test.ts -├── validate.test.ts -└── format.test.ts - -packages/core/android/src/test/kotlin/ -├── DebounceTest.kt -├── ValidateTest.kt -└── FormatTest.kt +└── core.test.ts # All utility tests + +packages/core/android/src/test/kotlin/com/kompkit/core/ +└── CoreTests.kt # All utility tests + +packages/core/flutter/test/ +├── kompkit_core_test.dart # Integration tests +├── debounce_test.dart # Debounce unit tests +├── validate_test.dart # Validation unit tests +└── format_test.dart # Formatting unit tests ``` ### Test Coverage **100% coverage requirement** across both platforms: + - Unit tests for all public APIs - Edge case validation - Error condition handling @@ -201,20 +241,21 @@ packages/core/android/src/test/kotlin/ ``` docs/ ├── README_CI.md # CI/CD processes -├── CONTRIBUTING.md # Development guidelines +├── CONTRIBUTING.md # Development guidelines ├── CHANGELOG.md # Version history ├── ARCHITECTURE.md # This document └── api/ # Generated API docs ├── web/ # TypeDoc output - └── android/ # Dokka output + ├── android/ # Dokka output + └── flutter/ # DartDoc output ``` ### Documentation Generation **Automated documentation pipeline:** -1. **Source comments**: JSDoc (TypeScript) + KDoc (Kotlin) -2. **Build process**: TypeDoc + Dokka generation +1. **Source comments**: JSDoc (TypeScript) + KDoc (Kotlin) + DartDoc (Dart) +2. **Build process**: TypeDoc + Dokka + DartDoc generation 3. **CI integration**: Docs updated on every build 4. **Artifact storage**: 30-day retention for documentation @@ -236,7 +277,6 @@ docs/ - **React Native**: Potential TypeScript reuse - **iOS**: Swift implementation following same patterns -- **Flutter**: Dart implementation with API parity - **Python**: Additional server-side support ### Performance Optimization diff --git a/docs/CHANGELOG.md b/docs/CHANGELOG.md index 023d8cd..1a9887c 100644 --- a/docs/CHANGELOG.md +++ b/docs/CHANGELOG.md @@ -7,27 +7,66 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +## [0.2.0-alpha] - 2026-02-09 + +### Changed + +#### Dependency Updates + +- **Kotlin**: `2.1.0` → `2.3.0` +- **ktlint-gradle**: `12.1.2` → `14.0.1` +- **detekt**: `1.23.7` → `1.23.8` +- **Vitest**: `^1.6.0` → `^3.0.0` +- **tsup**: `^8.0.0` → `^8.5.0` +- **TypeDoc**: `^0.28.14` → `^0.28.16` +- **TypeScript**: `^5.6.0` → `^5.7.0` +- **intl** (Dart): `^0.19.0` → `^0.20.0` +- **flutter_lints**: `^3.0.0` → `^5.0.0` +- **codecov-action**: `v3` → `v5` +- **Flutter CI**: `3.24.0` → `3.27.4` + +#### Documentation + +- Added Flutter platform references across all documentation (ARCHITECTURE, CHANGELOG, README_CI, contributing, roadmap) +- Updated outdated coroutines version references (`1.8.1` → `1.10.2`) in docs +- Fixed Web CI path filter to exclude Flutter changes +- Updated API signatures and platform-specific adaptations in ARCHITECTURE.md + +### Fixed + +- Web CI workflow now correctly excludes `packages/core/flutter/**` from triggers +- Documentation inconsistencies where Flutter was missing from cross-platform references +- Stale version numbers across documentation files + +--- + ## [0.1.0-alpha] - 2025-11-10 ### Added #### Core Features -- **Cross-platform utility library** with identical APIs for TypeScript and Kotlin + +- **Cross-platform utility library** with identical APIs for TypeScript, Kotlin, and Dart - **debounce** function for delaying function execution - Web: `debounce(fn: T, wait?: number): T` - Kotlin: `debounce(waitMs: Long, scope: CoroutineScope, dest: (T) -> Unit): (T) -> Unit` + - Dart: `debounce(Function fn, [Duration wait])` and `debounceVoid(VoidCallback fn, [Duration wait])` - **isEmail** function for email validation - Web: `isEmail(value: string): boolean` - Kotlin: `isEmail(value: String): Boolean` + - Dart: `isEmail(String value): bool` - **formatCurrency** function for localized currency formatting - Web: `formatCurrency(amount: number, currency?: string, locale?: string): string` - Kotlin: `formatCurrency(amount: Double, currency: String, locale: Locale): String` + - Dart: `formatCurrency(num amount, {String currency, String locale}): String` #### Development Infrastructure + - **Monorepo structure** with Lerna and npm workspaces -- **Separate CI workflows** for Web and Kotlin platforms - - Web CI: Node.js 20, TypeScript 5.6+, Vitest testing, TypeDoc documentation - - Kotlin CI: JDK 17, Kotlin 2.1.0, JUnit testing, Dokka documentation +- **Separate CI workflows** for Web, Kotlin, and Flutter platforms + - Web CI: Node.js 20, TypeScript 5.7+, Vitest testing, TypeDoc documentation + - Kotlin CI: JDK 17, Kotlin 2.3.0, JUnit testing, Dokka documentation + - Flutter CI: Flutter 3.27, Dart 3.0+, flutter_test, DartDoc documentation - **Code quality tools** - Kotlin: ktlint formatting, detekt static analysis - Web: ESLint, Prettier (configured) @@ -35,6 +74,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - **Automated artifact generation** (JARs, documentation, test reports) #### Documentation + - **Comprehensive README** with installation and usage examples - **API documentation** auto-generated for both platforms - **Contributing guidelines** with development workflow @@ -42,6 +82,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - **Architecture overview** explaining monorepo structure #### Build & Testing + - **100% test coverage** across both platforms - **Automated builds** with caching for optimal performance - **Cross-platform compatibility** testing @@ -50,15 +91,19 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Technical Details #### Supported Platforms + - **Web**: TypeScript/JavaScript with Node.js 20+ -- **Kotlin**: JVM with Kotlin 2.1.0 and JDK 17+ +- **Kotlin**: JVM with Kotlin 2.3.0 and JDK 17+ +- **Flutter/Dart**: Dart 3.0+ with Flutter 3.0+ (all platforms) #### Dependencies + - **Zero runtime dependencies** for core utilities - **Minimal development dependencies** (testing, documentation, build tools) - **Coroutines support** for Kotlin debounce functionality #### Performance + - **Lightweight bundle size** with tree-shaking support - **Optimized CI builds** (< 5 min web, < 8 min Kotlin) - **Efficient caching** strategies for dependencies and builds @@ -80,26 +125,33 @@ This is the initial alpha release. No migration is required. For future releases, we follow this format: ### Added + - New features and functionality ### Changed + - Changes in existing functionality ### Deprecated + - Soon-to-be removed features ### Removed + - Removed features ### Fixed + - Bug fixes ### Security + - Security improvements --- **Legend:** + - 🎉 **Major feature** - ✨ **Enhancement** - 🐛 **Bug fix** diff --git a/docs/README_CI.md b/docs/README_CI.md index 1c83656..b1ec6a9 100644 --- a/docs/README_CI.md +++ b/docs/README_CI.md @@ -6,10 +6,11 @@ KompKit uses GitHub Actions for continuous integration with separate workflows o ## Current Workflows Status -| Workflow | Status | Platform | Triggers | Path Filters | -|----------|--------|----------|----------|--------------| -| **Web CI** | ✅ Active | TypeScript/Node.js | `develop`, `release` | `packages/core/web/**` | -| **Kotlin CI** | ✅ Active | Kotlin JVM | `develop`, `release` | `packages/core/android/**` | +| Workflow | Status | Platform | Triggers | Path Filters | +| -------------- | --------- | ------------------ | -------------------- | -------------------------- | +| **Web CI** | ✅ Active | TypeScript/Node.js | `develop`, `release` | `packages/core/web/**` | +| **Kotlin CI** | ✅ Active | Kotlin JVM | `develop`, `release` | `packages/core/android/**` | +| **Flutter CI** | ✅ Active | Dart/Flutter | `develop`, `release` | `packages/core/flutter/**` | ## Workflow Details @@ -18,12 +19,14 @@ KompKit uses GitHub Actions for continuous integration with separate workflows o **Purpose:** Build, test, and validate TypeScript/JavaScript packages **Triggers:** + - Push/PR to `release` or `develop` branches - Changes in `packages/core/web/**` - Changes in `.github/workflows/web.yml` - Manual dispatch (`workflow_dispatch`) **Jobs:** + - **web**: Lint, typecheck, build, test, and generate documentation - Node.js 20.x with npm caching - Lerna-based monorepo management @@ -37,12 +40,14 @@ KompKit uses GitHub Actions for continuous integration with separate workflows o **Purpose:** Build, test, and validate Kotlin JVM packages **Triggers:** + - Push/PR to `release` or `develop` branches - Changes in `packages/core/android/**` - Changes in `.github/workflows/android.yml` - Manual dispatch (`workflow_dispatch`) **Jobs:** + - **kotlin**: Lint, static analysis, build, test, and generate documentation - JDK 17 (Temurin distribution) - Gradle build with caching @@ -53,32 +58,60 @@ KompKit uses GitHub Actions for continuous integration with separate workflows o **Path Filters:** Optimized to run only when Kotlin-related files change +### 3. Flutter CI (`flutter.yml`) + +**Purpose:** Build, test, and validate Dart/Flutter packages + +**Triggers:** + +- Push/PR to `release` or `develop` branches +- Changes in `packages/core/flutter/**` +- Changes in `.github/workflows/flutter.yml` +- Manual dispatch (`workflow_dispatch`) + +**Jobs:** + +- **flutter**: Analyze, test, and generate documentation + - Flutter 3.24.0 (stable channel) + - `flutter analyze` for static analysis + - `flutter test --coverage` with coverage reporting + - Codecov integration for coverage uploads + - DartDoc documentation generation + - Artifact uploads (docs) + +**Path Filters:** Optimized to run only when Flutter-related files change + ## Technology Stack ### Pinned Action Versions -| Action | Version | Purpose | Used In | -|--------|---------|---------|---------| -| `actions/checkout` | v4 | Repository checkout | Both workflows | -| `actions/setup-node` | v4 | Node.js 20.x setup | Web CI | -| `actions/setup-java` | v4 | JDK 17 setup | Kotlin CI | -| `gradle/actions/setup-gradle` | v4 | Gradle with caching | Kotlin CI | -| `actions/upload-artifact` | v4 | Artifact storage | Both workflows | +| Action | Version | Purpose | Used In | +| ----------------------------- | ------- | ------------------- | ------------- | +| `actions/checkout` | v4 | Repository checkout | All workflows | +| `actions/setup-node` | v4 | Node.js 20.x setup | Web CI | +| `actions/setup-java` | v4 | JDK 17 setup | Kotlin CI | +| `gradle/actions/setup-gradle` | v4 | Gradle with caching | Kotlin CI | +| `subosito/flutter-action` | v2 | Flutter setup | Flutter CI | +| `codecov/codecov-action` | v5 | Coverage upload | Flutter CI | +| `actions/upload-artifact` | v4 | Artifact storage | All workflows | ### Build Requirements -| Platform | Requirements | Version | -|----------|-------------|---------| -| **Web** | Node.js | 20.x | -| **Web** | npm | Latest | -| **Web** | TypeScript | 5.6+ | -| **Kotlin** | JDK | 17 (Temurin) | -| **Kotlin** | Kotlin | 2.1.0 | -| **Kotlin** | Gradle | 8.5 | +| Platform | Requirements | Version | +| ----------- | ------------ | ------------ | +| **Web** | Node.js | 20.x | +| **Web** | npm | Latest | +| **Web** | TypeScript | 5.7+ | +| **Kotlin** | JDK | 17 (Temurin) | +| **Kotlin** | Kotlin | 2.3.0 | +| **Kotlin** | Gradle | 8.5 | +| **Flutter** | Flutter | 3.27.4 | +| **Flutter** | Dart | 3.0+ | ## Security & Permissions **Minimal Permissions:** + - `contents: read` - Repository access - `pull-requests: read` - PR information access @@ -87,6 +120,7 @@ KompKit uses GitHub Actions for continuous integration with separate workflows o ## Local Development ### Web Development + ```bash # Install dependencies npm ci @@ -102,6 +136,7 @@ npm run docs:web ``` ### Kotlin Development + ```bash # Navigate to Kotlin module cd packages/core/android @@ -137,26 +172,35 @@ chmod +x gradlew ## Artifacts ### Web Artifacts + - `web-docs-{run_id}`: Generated TypeDoc documentation (30 days) - `web-build-{run_id}`: Built packages from dist/ directories (7 days) -### Kotlin Artifacts +### Kotlin Artifacts + - `android-test-reports-{run_id}`: JUnit test reports (7 days) - `android-lint-reports-{run_id}`: ktlint and detekt reports (7 days) - `kotlin-jar-{run_id}`: Built JAR files (7 days) - `kotlin-docs-{run_id}`: Dokka-generated documentation (30 days) +### Flutter Artifacts + +- `flutter-docs-{run_id}`: DartDoc-generated documentation (30 days) + ## Skip Flags Use commit message flags to skip specific builds: + - `[skip web]`: Skip web CI workflow - `[skip android]`: Skip Kotlin CI workflow +- `[skip flutter]`: Skip Flutter CI workflow ## Troubleshooting ### Common Issues **1. Gradle Permission Denied** + ```bash chmod +x packages/core/android/gradlew git add packages/core/android/gradlew @@ -164,28 +208,32 @@ git commit -m "fix: make gradlew executable" ``` **2. Node.js Build Failures** + - Check Node.js version compatibility (using 20.x) - Verify `package-lock.json` is committed - Clear npm cache: `npm ci --cache .npm --prefer-offline` **3. Kotlin Build Failures** + - Verify JDK 17 compatibility -- Check Kotlin version compatibility (2.1.0) +- Check Kotlin version compatibility (2.3.0) - Review ktlint/detekt reports for code quality issues - Ensure Gradle wrapper is executable **4. Path Filters Not Working** + - Ensure file changes match the path patterns in workflow triggers - Check that both `push` and `pull_request` events have same path filters ### Debug Commands **Check workflow status:** + ```bash # View recent workflow runs gh run list --limit 10 -# View specific run details +# View specific run details gh run view # Download artifacts @@ -193,6 +241,7 @@ gh run download ``` **Local debugging:** + ```bash # Simulate CI environment export CI=true @@ -207,7 +256,7 @@ npm test --workspaces --if-present || npm test || echo "No tests found" ## Performance Targets - **Web builds**: < 5 minutes for typical changes -- **Kotlin builds**: < 8 minutes for typical changes +- **Kotlin builds**: < 8 minutes for typical changes - **First-time builds**: May take longer due to dependency downloads - **Concurrent builds**: Path filters prevent unnecessary parallel execution @@ -220,6 +269,7 @@ npm test --workspaces --if-present || npm test || echo "No tests found" ## Monitoring Monitor CI health via: + - GitHub Actions dashboard - README badges showing build status - Artifact retention and storage usage diff --git a/docs/android.md b/docs/android.md index 9cd40b9..b49a958 100644 --- a/docs/android.md +++ b/docs/android.md @@ -2,19 +2,21 @@ KompKit Core provides small utilities for Android applications written in Kotlin. -Status: `0.0.x-alpha`. +Status: `V0.2.0-alpha`. ## Installation Add the dependency to your module `build.gradle.kts`: + ```kotlin dependencies { implementation("com.kompkit:core:") - implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.8.1") + implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.10.2") } ``` ## Imports + ```kotlin import com.kompkit.core.debounce import com.kompkit.core.isEmail @@ -24,6 +26,7 @@ import com.kompkit.core.formatCurrency ## Usage examples ### debounce + ```kotlin import com.kompkit.core.debounce import kotlinx.coroutines.CoroutineScope @@ -40,6 +43,7 @@ onType("kompkit") // only this call will execute after ~300ms ``` ### isEmail + ```kotlin import com.kompkit.core.isEmail @@ -48,6 +52,7 @@ isEmail("invalid@") // false ``` ### formatCurrency + ```kotlin import com.kompkit.core.formatCurrency import java.util.Locale @@ -57,6 +62,7 @@ formatCurrency(1234.56, "USD", Locale.US) // "$1,234.56" ``` ## Jetpack Compose integration + ```kotlin import androidx.compose.material3.TextField import androidx.compose.runtime.* @@ -85,6 +91,7 @@ fun SearchBox() { ``` ## Notes + - Requires `kotlinx-coroutines-core` for the `debounce` utility. - All utilities are top-level functions in the `com.kompkit.core` package. - Compatible with Android API 21+. diff --git a/docs/api/android/images/anchor-copy-button.svg b/docs/api/android/images/anchor-copy-button.svg deleted file mode 100644 index 19c1fa3..0000000 --- a/docs/api/android/images/anchor-copy-button.svg +++ /dev/null @@ -1,8 +0,0 @@ - - - - - - diff --git a/docs/api/android/images/arrow_down.svg b/docs/api/android/images/arrow_down.svg deleted file mode 100644 index 639aaf1..0000000 --- a/docs/api/android/images/arrow_down.svg +++ /dev/null @@ -1,7 +0,0 @@ - - - - - diff --git a/docs/api/android/images/burger.svg b/docs/api/android/images/burger.svg deleted file mode 100644 index fcca732..0000000 --- a/docs/api/android/images/burger.svg +++ /dev/null @@ -1,9 +0,0 @@ - - - - - - - diff --git a/docs/api/android/images/copy-icon.svg b/docs/api/android/images/copy-icon.svg deleted file mode 100644 index 2cb02ec..0000000 --- a/docs/api/android/images/copy-icon.svg +++ /dev/null @@ -1,7 +0,0 @@ - - - - - diff --git a/docs/api/android/images/copy-successful-icon.svg b/docs/api/android/images/copy-successful-icon.svg deleted file mode 100644 index c4b9538..0000000 --- a/docs/api/android/images/copy-successful-icon.svg +++ /dev/null @@ -1,7 +0,0 @@ - - - - - diff --git a/docs/api/android/images/footer-go-to-link.svg b/docs/api/android/images/footer-go-to-link.svg deleted file mode 100644 index a87add7..0000000 --- a/docs/api/android/images/footer-go-to-link.svg +++ /dev/null @@ -1,7 +0,0 @@ - - - - - diff --git a/docs/api/android/images/go-to-top-icon.svg b/docs/api/android/images/go-to-top-icon.svg deleted file mode 100644 index abc3d1c..0000000 --- a/docs/api/android/images/go-to-top-icon.svg +++ /dev/null @@ -1,8 +0,0 @@ - - - - - - diff --git a/docs/api/android/images/homepage.svg b/docs/api/android/images/homepage.svg deleted file mode 100644 index e3c83b1..0000000 --- a/docs/api/android/images/homepage.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/docs/api/android/images/logo-icon.svg b/docs/api/android/images/logo-icon.svg deleted file mode 100644 index e42f957..0000000 --- a/docs/api/android/images/logo-icon.svg +++ /dev/null @@ -1,14 +0,0 @@ - - - - - - - - - - - - diff --git a/docs/api/android/images/nav-icons/abstract-class-kotlin.svg b/docs/api/android/images/nav-icons/abstract-class-kotlin.svg deleted file mode 100644 index 19d6148..0000000 --- a/docs/api/android/images/nav-icons/abstract-class-kotlin.svg +++ /dev/null @@ -1,26 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/docs/api/android/images/nav-icons/abstract-class.svg b/docs/api/android/images/nav-icons/abstract-class.svg deleted file mode 100644 index 6018203..0000000 --- a/docs/api/android/images/nav-icons/abstract-class.svg +++ /dev/null @@ -1,20 +0,0 @@ - - - - - - - - - - - - - - - - - - - - diff --git a/docs/api/android/images/nav-icons/annotation-kotlin.svg b/docs/api/android/images/nav-icons/annotation-kotlin.svg deleted file mode 100644 index b90f508..0000000 --- a/docs/api/android/images/nav-icons/annotation-kotlin.svg +++ /dev/null @@ -1,13 +0,0 @@ - - - - - - - - - - - diff --git a/docs/api/android/images/nav-icons/annotation.svg b/docs/api/android/images/nav-icons/annotation.svg deleted file mode 100644 index b80c54b..0000000 --- a/docs/api/android/images/nav-icons/annotation.svg +++ /dev/null @@ -1,7 +0,0 @@ - - - - - - - diff --git a/docs/api/android/images/nav-icons/class-kotlin.svg b/docs/api/android/images/nav-icons/class-kotlin.svg deleted file mode 100644 index 797a242..0000000 --- a/docs/api/android/images/nav-icons/class-kotlin.svg +++ /dev/null @@ -1,13 +0,0 @@ - - - - - - - - - - - diff --git a/docs/api/android/images/nav-icons/class.svg b/docs/api/android/images/nav-icons/class.svg deleted file mode 100644 index 3f1ad16..0000000 --- a/docs/api/android/images/nav-icons/class.svg +++ /dev/null @@ -1,7 +0,0 @@ - - - - - - - diff --git a/docs/api/android/images/nav-icons/enum-kotlin.svg b/docs/api/android/images/nav-icons/enum-kotlin.svg deleted file mode 100644 index 775a7cc..0000000 --- a/docs/api/android/images/nav-icons/enum-kotlin.svg +++ /dev/null @@ -1,13 +0,0 @@ - - - - - - - - - - - diff --git a/docs/api/android/images/nav-icons/enum.svg b/docs/api/android/images/nav-icons/enum.svg deleted file mode 100644 index fa7f247..0000000 --- a/docs/api/android/images/nav-icons/enum.svg +++ /dev/null @@ -1,7 +0,0 @@ - - - - - - - diff --git a/docs/api/android/images/nav-icons/exception-class.svg b/docs/api/android/images/nav-icons/exception-class.svg deleted file mode 100644 index c0b2bde..0000000 --- a/docs/api/android/images/nav-icons/exception-class.svg +++ /dev/null @@ -1,7 +0,0 @@ - - - - - - - diff --git a/docs/api/android/images/nav-icons/field-value.svg b/docs/api/android/images/nav-icons/field-value.svg deleted file mode 100644 index 2771ee5..0000000 --- a/docs/api/android/images/nav-icons/field-value.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - diff --git a/docs/api/android/images/nav-icons/field-variable.svg b/docs/api/android/images/nav-icons/field-variable.svg deleted file mode 100644 index e2d2bbd..0000000 --- a/docs/api/android/images/nav-icons/field-variable.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - diff --git a/docs/api/android/images/nav-icons/function.svg b/docs/api/android/images/nav-icons/function.svg deleted file mode 100644 index f0da64a..0000000 --- a/docs/api/android/images/nav-icons/function.svg +++ /dev/null @@ -1,7 +0,0 @@ - - - - - - - diff --git a/docs/api/android/images/nav-icons/interface-kotlin.svg b/docs/api/android/images/nav-icons/interface-kotlin.svg deleted file mode 100644 index 5e16326..0000000 --- a/docs/api/android/images/nav-icons/interface-kotlin.svg +++ /dev/null @@ -1,13 +0,0 @@ - - - - - - - - - - - diff --git a/docs/api/android/images/nav-icons/interface.svg b/docs/api/android/images/nav-icons/interface.svg deleted file mode 100644 index 32063ba..0000000 --- a/docs/api/android/images/nav-icons/interface.svg +++ /dev/null @@ -1,7 +0,0 @@ - - - - - - - diff --git a/docs/api/android/images/nav-icons/object.svg b/docs/api/android/images/nav-icons/object.svg deleted file mode 100644 index 31f0ee3..0000000 --- a/docs/api/android/images/nav-icons/object.svg +++ /dev/null @@ -1,13 +0,0 @@ - - - - - - - - - - - diff --git a/docs/api/android/images/nav-icons/typealias-kotlin.svg b/docs/api/android/images/nav-icons/typealias-kotlin.svg deleted file mode 100644 index f4bb238..0000000 --- a/docs/api/android/images/nav-icons/typealias-kotlin.svg +++ /dev/null @@ -1,13 +0,0 @@ - - - - - - - - - - - diff --git a/docs/api/android/images/theme-toggle.svg b/docs/api/android/images/theme-toggle.svg deleted file mode 100644 index df86202..0000000 --- a/docs/api/android/images/theme-toggle.svg +++ /dev/null @@ -1,7 +0,0 @@ - - - - - diff --git a/docs/api/android/index.html b/docs/api/android/index.html deleted file mode 100644 index 2100167..0000000 --- a/docs/api/android/index.html +++ /dev/null @@ -1,99 +0,0 @@ - - - - - kompkit-core-android - - - - - - - - - - - - - - - - - - - -
- -
- -
-
- -
-

kompkit-core-android

-
-

Packages

-
-
-
-
-
- - -
Link copied to clipboard
-
-
-
- -
-
-
-
-
-
-
-
- -
-
-
- - diff --git a/docs/api/android/kompkit-core-android/com.kompkit.core/debounce.html b/docs/api/android/kompkit-core-android/com.kompkit.core/debounce.html deleted file mode 100644 index b95dc03..0000000 --- a/docs/api/android/kompkit-core-android/com.kompkit.core/debounce.html +++ /dev/null @@ -1,80 +0,0 @@ - - - - - debounce - - - - - - - - - - - - - - - - - - - -
- -
- -
-
- -
-

debounce

-
-
fun <T> debounce(waitMs: Long = 250, scope: CoroutineScope, dest: (T) -> Unit): (T) -> Unit

Debounces consecutive calls and emits only the last one after waitMs milliseconds. Subsequent calls within the wait period cancel the previous scheduled execution.

Return

A debounced function that accepts a parameter of type T.

Parameters

T

The type of parameter accepted by the debounced function.

waitMs

Milliseconds to wait before invoking the destination callback. Defaults to 250ms.

scope

Coroutine scope used to schedule the delayed execution.

dest

Destination callback invoked after the debounce period elapses.

Samples

-
- -
-
-
- - diff --git a/docs/api/android/kompkit-core-android/com.kompkit.core/format-currency.html b/docs/api/android/kompkit-core-android/com.kompkit.core/format-currency.html deleted file mode 100644 index 81ebfa1..0000000 --- a/docs/api/android/kompkit-core-android/com.kompkit.core/format-currency.html +++ /dev/null @@ -1,80 +0,0 @@ - - - - - formatCurrency - - - - - - - - - - - - - - - - - - - -
- -
- -
-
- -
-

formatCurrency

-
-
fun formatCurrency(amount: Double, currency: String = "EUR", locale: Locale = Locale("es", "ES")): String

Formats a number as a localized currency string.

Return

A formatted currency string.

Parameters

amount

The numeric amount to format.

currency

The currency code (e.g., "USD", "EUR", "JPY"). Defaults to "EUR".

locale

The locale for formatting. Defaults to Spanish (Spain).

Samples

-
- -
-
-
- - diff --git a/docs/api/android/kompkit-core-android/com.kompkit.core/index.html b/docs/api/android/kompkit-core-android/com.kompkit.core/index.html deleted file mode 100644 index 7d344f5..0000000 --- a/docs/api/android/kompkit-core-android/com.kompkit.core/index.html +++ /dev/null @@ -1,133 +0,0 @@ - - - - - com.kompkit.core - - - - - - - - - - - - - - - - - - - -
- -
- -
-
- -
-

Package-level declarations

-
-
-
-
-
-

Functions

-
-
-
-
- - -
Link copied to clipboard
-
-
-
-
fun <T> debounce(waitMs: Long = 250, scope: CoroutineScope, dest: (T) -> Unit): (T) -> Unit

Debounces consecutive calls and emits only the last one after waitMs milliseconds. Subsequent calls within the wait period cancel the previous scheduled execution.

-
-
-
-
- -
-
-
- - -
Link copied to clipboard
-
-
-
-
fun formatCurrency(amount: Double, currency: String = "EUR", locale: Locale = Locale("es", "ES")): String

Formats a number as a localized currency string.

-
-
-
-
- -
-
-
- - -
Link copied to clipboard
-
-
-
-
fun isEmail(value: String): Boolean

Validates whether a string matches a basic email pattern.

-
-
-
-
-
-
-
-
-
- -
-
-
- - diff --git a/docs/api/android/kompkit-core-android/com.kompkit.core/is-email.html b/docs/api/android/kompkit-core-android/com.kompkit.core/is-email.html deleted file mode 100644 index a7bd154..0000000 --- a/docs/api/android/kompkit-core-android/com.kompkit.core/is-email.html +++ /dev/null @@ -1,80 +0,0 @@ - - - - - isEmail - - - - - - - - - - - - - - - - - - - -
- -
- -
-
- -
-

isEmail

-
-
fun isEmail(value: String): Boolean

Validates whether a string matches a basic email pattern.

Return

true if the string is a valid email format, false otherwise.

Parameters

value

The string to validate.

Samples

-
- -
-
-
- - diff --git a/docs/api/android/kompkit-core-android/package-list b/docs/api/android/kompkit-core-android/package-list deleted file mode 100644 index 1b2505c..0000000 --- a/docs/api/android/kompkit-core-android/package-list +++ /dev/null @@ -1,8 +0,0 @@ -$dokka.format:html-v1 -$dokka.linkExtension:html -$dokka.location:com.kompkit.core////PointingToDeclaration/kompkit-core-android/com.kompkit.core/index.html -$dokka.location:com.kompkit.core//debounce/#kotlin.Long#kotlinx.coroutines.CoroutineScope#kotlin.Function1[TypeParam(bounds=[kotlin.Any?]),kotlin.Unit]/PointingToDeclaration/kompkit-core-android/com.kompkit.core/debounce.html -$dokka.location:com.kompkit.core//formatCurrency/#kotlin.Double#kotlin.String#java.util.Locale/PointingToDeclaration/kompkit-core-android/com.kompkit.core/format-currency.html -$dokka.location:com.kompkit.core//isEmail/#kotlin.String/PointingToDeclaration/kompkit-core-android/com.kompkit.core/is-email.html -com.kompkit.core - diff --git a/docs/api/android/navigation.html b/docs/api/android/navigation.html deleted file mode 100644 index e6cb226..0000000 --- a/docs/api/android/navigation.html +++ /dev/null @@ -1,16 +0,0 @@ - - diff --git a/docs/api/android/scripts/clipboard.js b/docs/api/android/scripts/clipboard.js deleted file mode 100644 index 7a4f33c..0000000 --- a/docs/api/android/scripts/clipboard.js +++ /dev/null @@ -1,56 +0,0 @@ -/* - * Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. - */ - -window.addEventListener('load', () => { - document.querySelectorAll('span.copy-icon').forEach(element => { - element.addEventListener('click', (el) => copyElementsContentToClipboard(element)); - }) - - document.querySelectorAll('span.anchor-icon').forEach(element => { - element.addEventListener('click', (el) => { - if(element.hasAttribute('pointing-to')){ - const location = hrefWithoutCurrentlyUsedAnchor() + '#' + element.getAttribute('pointing-to') - copyTextToClipboard(element, location) - } - }); - }) -}) - -const copyElementsContentToClipboard = (element) => { - const selection = window.getSelection(); - const range = document.createRange(); - range.selectNodeContents(element.parentNode.parentNode); - selection.removeAllRanges(); - selection.addRange(range); - - copyAndShowPopup(element, () => selection.removeAllRanges()) -} - -const copyTextToClipboard = (element, text) => { - var textarea = document.createElement("textarea"); - textarea.textContent = text; - textarea.style.position = "fixed"; - document.body.appendChild(textarea); - textarea.select(); - - copyAndShowPopup(element, () => document.body.removeChild(textarea)) -} - -const copyAndShowPopup = (element, after) => { - try { - document.execCommand('copy'); - element.nextElementSibling.classList.add('active-popup'); - setTimeout(() => { - element.nextElementSibling.classList.remove('active-popup'); - }, 1200); - } catch (e) { - console.error('Failed to write to clipboard:', e) - } - finally { - if(after) after() - } -} - -const hrefWithoutCurrentlyUsedAnchor = () => window.location.href.split('#')[0] - diff --git a/docs/api/android/scripts/main.js b/docs/api/android/scripts/main.js deleted file mode 100644 index ba6c347..0000000 --- a/docs/api/android/scripts/main.js +++ /dev/null @@ -1,44 +0,0 @@ -(()=>{var e={8527:e=>{e.exports=''},5570:e=>{e.exports=''},107:e=>{e.exports=''},7224:e=>{e.exports=''},538:e=>{e.exports=''},1924:(e,n,t)=>{"use strict";var r=t(210),o=t(5559),i=o(r("String.prototype.indexOf"));e.exports=function(e,n){var t=r(e,!!n);return"function"==typeof t&&i(e,".prototype.")>-1?o(t):t}},5559:(e,n,t)=>{"use strict";var r=t(8612),o=t(210),i=o("%Function.prototype.apply%"),a=o("%Function.prototype.call%"),l=o("%Reflect.apply%",!0)||r.call(a,i),c=o("%Object.getOwnPropertyDescriptor%",!0),u=o("%Object.defineProperty%",!0),s=o("%Math.max%");if(u)try{u({},"a",{value:1})}catch(e){u=null}e.exports=function(e){var n=l(r,a,arguments);if(c&&u){var t=c(n,"length");t.configurable&&u(n,"length",{value:1+s(0,e.length-(arguments.length-1))})}return n};var f=function(){return l(r,i,arguments)};u?u(e.exports,"apply",{value:f}):e.exports.apply=f},4184:(e,n)=>{var t; -/*! - Copyright (c) 2018 Jed Watson. - Licensed under the MIT License (MIT), see - http://jedwatson.github.io/classnames -*/!function(){"use strict";var r={}.hasOwnProperty;function o(){for(var e=[],n=0;n{"use strict";e.exports=function(e,n){var t=this,r=t.constructor;return t.options=Object.assign({storeInstancesGlobally:!0},n||{}),t.callbacks={},t.directMap={},t.sequenceLevels={},t.resetTimer=null,t.ignoreNextKeyup=!1,t.ignoreNextKeypress=!1,t.nextExpectedAction=!1,t.element=e,t.addEvents(),t.options.storeInstancesGlobally&&r.instances.push(t),t},e.exports.prototype.bind=t(2207),e.exports.prototype.bindMultiple=t(3396),e.exports.prototype.unbind=t(9208),e.exports.prototype.trigger=t(9855),e.exports.prototype.reset=t(6214),e.exports.prototype.stopCallback=t(3450),e.exports.prototype.handleKey=t(3067),e.exports.prototype.addEvents=t(718),e.exports.prototype.bindSingle=t(8763),e.exports.prototype.getKeyInfo=t(5825),e.exports.prototype.pickBestAction=t(8608),e.exports.prototype.getReverseMap=t(3956),e.exports.prototype.getMatches=t(3373),e.exports.prototype.resetSequences=t(3346),e.exports.prototype.fireCallback=t(2684),e.exports.prototype.bindSequence=t(7103),e.exports.prototype.resetSequenceTimer=t(7309),e.exports.prototype.detach=t(7554),e.exports.instances=[],e.exports.reset=t(1822),e.exports.REVERSE_MAP=null},718:(e,n,t)=>{"use strict";e.exports=function(){var e=this,n=t(4323),r=e.element;e.eventHandler=t(9646).bind(e),n(r,"keypress",e.eventHandler),n(r,"keydown",e.eventHandler),n(r,"keyup",e.eventHandler)}},2207:e=>{"use strict";e.exports=function(e,n,t){return e=e instanceof Array?e:[e],this.bindMultiple(e,n,t),this}},3396:e=>{"use strict";e.exports=function(e,n,t){for(var r=0;r{"use strict";e.exports=function(e,n,r,o){var i=this;function a(n){return function(){i.nextExpectedAction=n,++i.sequenceLevels[e],i.resetSequenceTimer()}}function l(n){var a;i.fireCallback(r,n,e),"keyup"!==o&&(a=t(6770),i.ignoreNextKeyup=a(n)),setTimeout((function(){i.resetSequences()}),10)}i.sequenceLevels[e]=0;for(var c=0;c{"use strict";e.exports=function(e,n,t,r,o){var i=this;i.directMap[e+":"+t]=n;var a,l=(e=e.replace(/\s+/g," ")).split(" ");l.length>1?i.bindSequence(e,l,n,t):(a=i.getKeyInfo(e,t),i.callbacks[a.key]=i.callbacks[a.key]||[],i.getMatches(a.key,a.modifiers,{type:a.action},r,e,o),i.callbacks[a.key][r?"unshift":"push"]({callback:n,modifiers:a.modifiers,action:a.action,seq:r,level:o,combo:e}))}},7554:(e,n,t)=>{var r=t(4323).off;e.exports=function(){var e=this,n=e.element;r(n,"keypress",e.eventHandler),r(n,"keydown",e.eventHandler),r(n,"keyup",e.eventHandler)}},4323:e=>{function n(e,n,t,r){return!e.addEventListener&&(n="on"+n),(e.addEventListener||e.attachEvent).call(e,n,t,r),t}e.exports=n,e.exports.on=n,e.exports.off=function(e,n,t,r){return!e.removeEventListener&&(n="on"+n),(e.removeEventListener||e.detachEvent).call(e,n,t,r),t}},2684:(e,n,t)=>{"use strict";e.exports=function(e,n,r,o){this.stopCallback(n,n.target||n.srcElement,r,o)||!1===e(n,r)&&(t(1350)(n),t(6103)(n))}},5825:(e,n,t)=>{"use strict";e.exports=function(e,n){var r,o,i,a,l,c,u=[];for(r=t(4520)(e),a=t(7549),l=t(5355),c=t(8581),i=0;i{"use strict";e.exports=function(e,n,r,o,i,a){var l,c,u,s,f=this,p=[],d=r.type;"keypress"!==d||r.code&&"Arrow"===r.code.slice(0,5)||(f.callbacks["any-character"]||[]).forEach((function(e){p.push(e)}));if(!f.callbacks[e])return p;for(u=t(8581),"keyup"===d&&u(e)&&(n=[e]),l=0;l{"use strict";e.exports=function(){var e,n=this.constructor;if(!n.REVERSE_MAP)for(var r in n.REVERSE_MAP={},e=t(4766))r>95&&r<112||e.hasOwnProperty(r)&&(n.REVERSE_MAP[e[r]]=r);return n.REVERSE_MAP}},3067:(e,n,t)=>{"use strict";e.exports=function(e,n,r){var o,i,a,l,c=this,u={},s=0,f=!1;for(o=c.getMatches(e,n,r),i=0;i{"use strict";e.exports=function(e){var n,r=this;"number"!=typeof e.which&&(e.which=e.keyCode);var o=t(6770)(e);void 0!==o&&("keyup"!==e.type||r.ignoreNextKeyup!==o?(n=t(4610),r.handleKey(o,n(e),e)):r.ignoreNextKeyup=!1)}},5532:e=>{"use strict";e.exports=function(e,n){return e.sort().join(",")===n.sort().join(",")}},8608:e=>{"use strict";e.exports=function(e,n,t){return t||(t=this.getReverseMap()[e]?"keydown":"keypress"),"keypress"===t&&n.length&&(t="keydown"),t}},6214:e=>{"use strict";e.exports=function(){return this.callbacks={},this.directMap={},this}},7309:e=>{"use strict";e.exports=function(){var e=this;clearTimeout(e.resetTimer),e.resetTimer=setTimeout((function(){e.resetSequences()}),1e3)}},3346:e=>{"use strict";e.exports=function(e){var n=this;e=e||{};var t,r=!1;for(t in n.sequenceLevels)e[t]?r=!0:n.sequenceLevels[t]=0;r||(n.nextExpectedAction=!1)}},3450:e=>{"use strict";e.exports=function(e,n){if((" "+n.className+" ").indexOf(" combokeys ")>-1)return!1;var t=n.tagName.toLowerCase();return"input"===t||"select"===t||"textarea"===t||n.isContentEditable}},9855:e=>{"use strict";e.exports=function(e,n){return this.directMap[e+":"+n]&&this.directMap[e+":"+n]({},e),this}},9208:e=>{"use strict";e.exports=function(e,n){return this.bind(e,(function(){}),n)}},1822:e=>{"use strict";e.exports=function(){this.instances.forEach((function(e){e.reset()}))}},6770:(e,n,t)=>{"use strict";e.exports=function(e){var n,r;if(n=t(4766),r=t(5295),"keypress"===e.type){var o=String.fromCharCode(e.which);return e.shiftKey||(o=o.toLowerCase()),o}return void 0!==n[e.which]?n[e.which]:void 0!==r[e.which]?r[e.which]:String.fromCharCode(e.which).toLowerCase()}},4610:e=>{"use strict";e.exports=function(e){var n=[];return e.shiftKey&&n.push("shift"),e.altKey&&n.push("alt"),e.ctrlKey&&n.push("ctrl"),e.metaKey&&n.push("meta"),n}},8581:e=>{"use strict";e.exports=function(e){return"shift"===e||"ctrl"===e||"alt"===e||"meta"===e}},4520:e=>{"use strict";e.exports=function(e){return"+"===e?["+"]:e.split("+")}},1350:e=>{"use strict";e.exports=function(e){e.preventDefault?e.preventDefault():e.returnValue=!1}},5355:e=>{"use strict";e.exports={"~":"`","!":"1","@":"2","#":"3",$:"4","%":"5","^":"6","&":"7","*":"8","(":"9",")":"0",_:"-","+":"=",":":";",'"':"'","<":",",">":".","?":"/","|":"\\"}},7549:e=>{"use strict";e.exports={option:"alt",command:"meta",return:"enter",escape:"esc",mod:/Mac|iPod|iPhone|iPad/.test(navigator.platform)?"meta":"ctrl"}},5295:e=>{"use strict";e.exports={106:"*",107:"plus",109:"minus",110:".",111:"/",186:";",187:"=",188:",",189:"-",190:".",191:"/",192:"`",219:"[",220:"\\",221:"]",222:"'"}},4766:e=>{"use strict";e.exports={8:"backspace",9:"tab",13:"enter",16:"shift",17:"ctrl",18:"alt",20:"capslock",27:"esc",32:"space",33:"pageup",34:"pagedown",35:"end",36:"home",37:"left",38:"up",39:"right",40:"down",45:"ins",46:"del",91:"meta",93:"meta",173:"minus",187:"plus",189:"minus",224:"meta"};for(var n=1;n<20;++n)e.exports[111+n]="f"+n;for(n=0;n<=9;++n)e.exports[n+96]=n},6103:e=>{"use strict";e.exports=function(e){e.stopPropagation?e.stopPropagation():e.cancelBubble=!0}},3362:()=>{var e;!function(){var e=Math.PI,n=2*e,t=e/180,r=document.createElement("div");document.head.appendChild(r);var o=self.ConicGradient=function(e){o.all.push(this),e=e||{},this.canvas=document.createElement("canvas"),this.context=this.canvas.getContext("2d"),this.repeating=!!e.repeating,this.size=e.size||Math.max(innerWidth,innerHeight),this.canvas.width=this.canvas.height=this.size;var n=e.stops;this.stops=(n||"").split(/\s*,(?![^(]*\))\s*/),this.from=0;for(var t=0;t0){var i=this.stops[0].clone();i.pos=0,this.stops.unshift(i)}if(void 0===this.stops[this.stops.length-1].pos)this.stops[this.stops.length-1].pos=1;else if(!this.repeating&&this.stops[this.stops.length-1].pos<1){var a=this.stops[this.stops.length-1].clone();a.pos=1,this.stops.push(a)}if(this.stops.forEach((function(e,n){if(void 0===e.pos){for(var t=n+1;this[t];t++)if(void 0!==this[t].pos){e.pos=this[n-1].pos+(this[t].pos-this[n-1].pos)/(t-n+1);break}}else n>0&&(e.pos=Math.max(e.pos,this[n-1].pos))}),this.stops),this.repeating){var l=(n=this.stops.slice())[n.length-1].pos-n[0].pos;for(t=0;this.stops[this.stops.length-1].pos<1&&t<1e4;t++)for(var c=0;c'},get png(){return this.canvas.toDataURL()},get r(){return Math.sqrt(2)*this.size/2},paint:function(){var e,n,r,o=this.context,i=this.r,a=this.size/2,l=0,c=this.stops[l];o.translate(this.size/2,this.size/2),o.rotate(-90*t),o.rotate(this.from*t),o.translate(-this.size/2,-this.size/2);for(var u=0;u<360;){if(u/360+1e-5>=c.pos){do{e=c,l++,c=this.stops[l]}while(c&&c!=e&&c.pos===e.pos);if(!c)break;var s=e.color+""==c.color+""&&e!=c;n=e.color.map((function(e,n){return c.color[n]-e}))}r=(u/360-e.pos)/(c.pos-e.pos);var f=s?c.color:n.map((function(n,t){var o=n*r+e.color[t];return t<3?255&o:o}));if(o.fillStyle="rgba("+f.join(",")+")",o.beginPath(),o.moveTo(a,a),s)var p=360*(c.pos-e.pos);else p=.5;var d=u*t,h=(d=Math.min(360*t,d))+p*t;h=Math.min(360*t,h+.02),o.arc(a,a,i,d,h),o.closePath(),o.fill(),u+=p}}},o.ColorStop=function(e,t){if(this.gradient=e,t){var r=t.match(/^(.+?)(?:\s+([\d.]+)(%|deg|turn|grad|rad)?)?(?:\s+([\d.]+)(%|deg|turn|grad|rad)?)?\s*$/);if(this.color=o.ColorStop.colorToRGBA(r[1]),r[2]){var i=r[3];"%"==i||"0"===r[2]&&!i?this.pos=r[2]/100:"turn"==i?this.pos=+r[2]:"deg"==i?this.pos=r[2]/360:"grad"==i?this.pos=r[2]/400:"rad"==i&&(this.pos=r[2]/n)}r[4]&&(this.next=new o.ColorStop(e,r[1]+" "+r[4]+r[5]))}},o.ColorStop.prototype={clone:function(){var e=new o.ColorStop(this.gradient);return e.color=this.color,e.pos=this.pos,e},toString:function(){return"rgba("+this.color.join(", ")+") "+100*this.pos+"%"}},o.ColorStop.colorToRGBA=function(e){if(!Array.isArray(e)&&-1==e.indexOf("from")){r.style.color=e;var n=getComputedStyle(r).color.match(/rgba?\(([\d.]+), ([\d.]+), ([\d.]+)(?:, ([\d.]+))?\)/);return n&&(n.shift(),(n=n.map((function(e){return+e})))[3]=isNaN(n[3])?1:n[3]),n||[0,0,0,0]}return e}}(),self.StyleFix&&((e=document.createElement("p")).style.backgroundImage="conic-gradient(white, black)",e.style.backgroundImage=PrefixFree.prefix+"conic-gradient(white, black)",e.style.backgroundImage||StyleFix.register((function(e,n){return e.indexOf("conic-gradient")>-1&&(e=e.replace(/(?:repeating-)?conic-gradient\(\s*((?:\([^()]+\)|[^;()}])+?)\)/g,(function(e,n){return new ConicGradient({stops:n,repeating:e.indexOf("repeating-")>-1})}))),e})))},9662:(e,n,t)=>{var r=t(7854),o=t(614),i=t(6330),a=r.TypeError;e.exports=function(e){if(o(e))return e;throw a(i(e)+" is not a function")}},9483:(e,n,t)=>{var r=t(7854),o=t(4411),i=t(6330),a=r.TypeError;e.exports=function(e){if(o(e))return e;throw a(i(e)+" is not a constructor")}},6077:(e,n,t)=>{var r=t(7854),o=t(614),i=r.String,a=r.TypeError;e.exports=function(e){if("object"==typeof e||o(e))return e;throw a("Can't set "+i(e)+" as a prototype")}},1223:(e,n,t)=>{var r=t(5112),o=t(30),i=t(3070),a=r("unscopables"),l=Array.prototype;null==l[a]&&i.f(l,a,{configurable:!0,value:o(null)}),e.exports=function(e){l[a][e]=!0}},1530:(e,n,t)=>{"use strict";var r=t(8710).charAt;e.exports=function(e,n,t){return n+(t?r(e,n).length:1)}},5787:(e,n,t)=>{var r=t(7854),o=t(7976),i=r.TypeError;e.exports=function(e,n){if(o(n,e))return e;throw i("Incorrect invocation")}},9670:(e,n,t)=>{var r=t(7854),o=t(111),i=r.String,a=r.TypeError;e.exports=function(e){if(o(e))return e;throw a(i(e)+" is not an object")}},7556:(e,n,t)=>{var r=t(7293);e.exports=r((function(){if("function"==typeof ArrayBuffer){var e=new ArrayBuffer(8);Object.isExtensible(e)&&Object.defineProperty(e,"a",{value:8})}}))},8533:(e,n,t)=>{"use strict";var r=t(2092).forEach,o=t(9341)("forEach");e.exports=o?[].forEach:function(e){return r(this,e,arguments.length>1?arguments[1]:void 0)}},8457:(e,n,t)=>{"use strict";var r=t(7854),o=t(9974),i=t(6916),a=t(7908),l=t(3411),c=t(7659),u=t(4411),s=t(6244),f=t(6135),p=t(8554),d=t(1246),h=r.Array;e.exports=function(e){var n=a(e),t=u(this),r=arguments.length,g=r>1?arguments[1]:void 0,v=void 0!==g;v&&(g=o(g,r>2?arguments[2]:void 0));var A,b,m,y,E,_,C=d(n),w=0;if(!C||this==h&&c(C))for(A=s(n),b=t?new this(A):h(A);A>w;w++)_=v?g(n[w],w):n[w],f(b,w,_);else for(E=(y=p(n,C)).next,b=t?new this:[];!(m=i(E,y)).done;w++)_=v?l(y,g,[m.value,w],!0):m.value,f(b,w,_);return b.length=w,b}},1318:(e,n,t)=>{var r=t(5656),o=t(1400),i=t(6244),a=function(e){return function(n,t,a){var l,c=r(n),u=i(c),s=o(a,u);if(e&&t!=t){for(;u>s;)if((l=c[s++])!=l)return!0}else for(;u>s;s++)if((e||s in c)&&c[s]===t)return e||s||0;return!e&&-1}};e.exports={includes:a(!0),indexOf:a(!1)}},2092:(e,n,t)=>{var r=t(9974),o=t(1702),i=t(8361),a=t(7908),l=t(6244),c=t(5417),u=o([].push),s=function(e){var n=1==e,t=2==e,o=3==e,s=4==e,f=6==e,p=7==e,d=5==e||f;return function(h,g,v,A){for(var b,m,y=a(h),E=i(y),_=r(g,v),C=l(E),w=0,x=A||c,k=n?x(h,C):t||p?x(h,0):void 0;C>w;w++)if((d||w in E)&&(m=_(b=E[w],w,y),e))if(n)k[w]=m;else if(m)switch(e){case 3:return!0;case 5:return b;case 6:return w;case 2:u(k,b)}else switch(e){case 4:return!1;case 7:u(k,b)}return f?-1:o||s?s:k}};e.exports={forEach:s(0),map:s(1),filter:s(2),some:s(3),every:s(4),find:s(5),findIndex:s(6),filterReject:s(7)}},1194:(e,n,t)=>{var r=t(7293),o=t(5112),i=t(7392),a=o("species");e.exports=function(e){return i>=51||!r((function(){var n=[];return(n.constructor={})[a]=function(){return{foo:1}},1!==n[e](Boolean).foo}))}},9341:(e,n,t)=>{"use strict";var r=t(7293);e.exports=function(e,n){var t=[][e];return!!t&&r((function(){t.call(null,n||function(){throw 1},1)}))}},3671:(e,n,t)=>{var r=t(7854),o=t(9662),i=t(7908),a=t(8361),l=t(6244),c=r.TypeError,u=function(e){return function(n,t,r,u){o(t);var s=i(n),f=a(s),p=l(s),d=e?p-1:0,h=e?-1:1;if(r<2)for(;;){if(d in f){u=f[d],d+=h;break}if(d+=h,e?d<0:p<=d)throw c("Reduce of empty array with no initial value")}for(;e?d>=0:p>d;d+=h)d in f&&(u=t(u,f[d],d,s));return u}};e.exports={left:u(!1),right:u(!0)}},206:(e,n,t)=>{var r=t(1702);e.exports=r([].slice)},4362:(e,n,t)=>{var r=t(206),o=Math.floor,i=function(e,n){var t=e.length,c=o(t/2);return t<8?a(e,n):l(e,i(r(e,0,c),n),i(r(e,c),n),n)},a=function(e,n){for(var t,r,o=e.length,i=1;i0;)e[r]=e[--r];r!==i++&&(e[r]=t)}return e},l=function(e,n,t,r){for(var o=n.length,i=t.length,a=0,l=0;a{var r=t(7854),o=t(3157),i=t(4411),a=t(111),l=t(5112)("species"),c=r.Array;e.exports=function(e){var n;return o(e)&&(n=e.constructor,(i(n)&&(n===c||o(n.prototype))||a(n)&&null===(n=n[l]))&&(n=void 0)),void 0===n?c:n}},5417:(e,n,t)=>{var r=t(7475);e.exports=function(e,n){return new(r(e))(0===n?0:n)}},3411:(e,n,t)=>{var r=t(9670),o=t(9212);e.exports=function(e,n,t,i){try{return i?n(r(t)[0],t[1]):n(t)}catch(n){o(e,"throw",n)}}},7072:(e,n,t)=>{var r=t(5112)("iterator"),o=!1;try{var i=0,a={next:function(){return{done:!!i++}},return:function(){o=!0}};a[r]=function(){return this},Array.from(a,(function(){throw 2}))}catch(e){}e.exports=function(e,n){if(!n&&!o)return!1;var t=!1;try{var i={};i[r]=function(){return{next:function(){return{done:t=!0}}}},e(i)}catch(e){}return t}},4326:(e,n,t)=>{var r=t(1702),o=r({}.toString),i=r("".slice);e.exports=function(e){return i(o(e),8,-1)}},648:(e,n,t)=>{var r=t(7854),o=t(1694),i=t(614),a=t(4326),l=t(5112)("toStringTag"),c=r.Object,u="Arguments"==a(function(){return arguments}());e.exports=o?a:function(e){var n,t,r;return void 0===e?"Undefined":null===e?"Null":"string"==typeof(t=function(e,n){try{return e[n]}catch(e){}}(n=c(e),l))?t:u?a(n):"Object"==(r=a(n))&&i(n.callee)?"Arguments":r}},5631:(e,n,t)=>{"use strict";var r=t(3070).f,o=t(30),i=t(2248),a=t(9974),l=t(5787),c=t(408),u=t(654),s=t(6340),f=t(9781),p=t(2423).fastKey,d=t(9909),h=d.set,g=d.getterFor;e.exports={getConstructor:function(e,n,t,u){var s=e((function(e,r){l(e,d),h(e,{type:n,index:o(null),first:void 0,last:void 0,size:0}),f||(e.size=0),null!=r&&c(r,e[u],{that:e,AS_ENTRIES:t})})),d=s.prototype,v=g(n),A=function(e,n,t){var r,o,i=v(e),a=b(e,n);return a?a.value=t:(i.last=a={index:o=p(n,!0),key:n,value:t,previous:r=i.last,next:void 0,removed:!1},i.first||(i.first=a),r&&(r.next=a),f?i.size++:e.size++,"F"!==o&&(i.index[o]=a)),e},b=function(e,n){var t,r=v(e),o=p(n);if("F"!==o)return r.index[o];for(t=r.first;t;t=t.next)if(t.key==n)return t};return i(d,{clear:function(){for(var e=v(this),n=e.index,t=e.first;t;)t.removed=!0,t.previous&&(t.previous=t.previous.next=void 0),delete n[t.index],t=t.next;e.first=e.last=void 0,f?e.size=0:this.size=0},delete:function(e){var n=this,t=v(n),r=b(n,e);if(r){var o=r.next,i=r.previous;delete t.index[r.index],r.removed=!0,i&&(i.next=o),o&&(o.previous=i),t.first==r&&(t.first=o),t.last==r&&(t.last=i),f?t.size--:n.size--}return!!r},forEach:function(e){for(var n,t=v(this),r=a(e,arguments.length>1?arguments[1]:void 0);n=n?n.next:t.first;)for(r(n.value,n.key,this);n&&n.removed;)n=n.previous},has:function(e){return!!b(this,e)}}),i(d,t?{get:function(e){var n=b(this,e);return n&&n.value},set:function(e,n){return A(this,0===e?0:e,n)}}:{add:function(e){return A(this,e=0===e?0:e,e)}}),f&&r(d,"size",{get:function(){return v(this).size}}),s},setStrong:function(e,n,t){var r=n+" Iterator",o=g(n),i=g(r);u(e,n,(function(e,n){h(this,{type:r,target:e,state:o(e),kind:n,last:void 0})}),(function(){for(var e=i(this),n=e.kind,t=e.last;t&&t.removed;)t=t.previous;return e.target&&(e.last=t=t?t.next:e.state.first)?"keys"==n?{value:t.key,done:!1}:"values"==n?{value:t.value,done:!1}:{value:[t.key,t.value],done:!1}:(e.target=void 0,{value:void 0,done:!0})}),t?"entries":"values",!t,!0),s(n)}}},9320:(e,n,t)=>{"use strict";var r=t(1702),o=t(2248),i=t(2423).getWeakData,a=t(9670),l=t(111),c=t(5787),u=t(408),s=t(2092),f=t(2597),p=t(9909),d=p.set,h=p.getterFor,g=s.find,v=s.findIndex,A=r([].splice),b=0,m=function(e){return e.frozen||(e.frozen=new y)},y=function(){this.entries=[]},E=function(e,n){return g(e.entries,(function(e){return e[0]===n}))};y.prototype={get:function(e){var n=E(this,e);if(n)return n[1]},has:function(e){return!!E(this,e)},set:function(e,n){var t=E(this,e);t?t[1]=n:this.entries.push([e,n])},delete:function(e){var n=v(this.entries,(function(n){return n[0]===e}));return~n&&A(this.entries,n,1),!!~n}},e.exports={getConstructor:function(e,n,t,r){var s=e((function(e,o){c(e,p),d(e,{type:n,id:b++,frozen:void 0}),null!=o&&u(o,e[r],{that:e,AS_ENTRIES:t})})),p=s.prototype,g=h(n),v=function(e,n,t){var r=g(e),o=i(a(n),!0);return!0===o?m(r).set(n,t):o[r.id]=t,e};return o(p,{delete:function(e){var n=g(this);if(!l(e))return!1;var t=i(e);return!0===t?m(n).delete(e):t&&f(t,n.id)&&delete t[n.id]},has:function(e){var n=g(this);if(!l(e))return!1;var t=i(e);return!0===t?m(n).has(e):t&&f(t,n.id)}}),o(p,t?{get:function(e){var n=g(this);if(l(e)){var t=i(e);return!0===t?m(n).get(e):t?t[n.id]:void 0}},set:function(e,n){return v(this,e,n)}}:{add:function(e){return v(this,e,!0)}}),s}}},7710:(e,n,t)=>{"use strict";var r=t(2109),o=t(7854),i=t(1702),a=t(4705),l=t(1320),c=t(2423),u=t(408),s=t(5787),f=t(614),p=t(111),d=t(7293),h=t(7072),g=t(8003),v=t(9587);e.exports=function(e,n,t){var A=-1!==e.indexOf("Map"),b=-1!==e.indexOf("Weak"),m=A?"set":"add",y=o[e],E=y&&y.prototype,_=y,C={},w=function(e){var n=i(E[e]);l(E,e,"add"==e?function(e){return n(this,0===e?0:e),this}:"delete"==e?function(e){return!(b&&!p(e))&&n(this,0===e?0:e)}:"get"==e?function(e){return b&&!p(e)?void 0:n(this,0===e?0:e)}:"has"==e?function(e){return!(b&&!p(e))&&n(this,0===e?0:e)}:function(e,t){return n(this,0===e?0:e,t),this})};if(a(e,!f(y)||!(b||E.forEach&&!d((function(){(new y).entries().next()})))))_=t.getConstructor(n,e,A,m),c.enable();else if(a(e,!0)){var x=new _,k=x[m](b?{}:-0,1)!=x,S=d((function(){x.has(1)})),O=h((function(e){new y(e)})),B=!b&&d((function(){for(var e=new y,n=5;n--;)e[m](n,n);return!e.has(-0)}));O||((_=n((function(e,n){s(e,E);var t=v(new y,e,_);return null!=n&&u(n,t[m],{that:t,AS_ENTRIES:A}),t}))).prototype=E,E.constructor=_),(S||B)&&(w("delete"),w("has"),A&&w("get")),(B||k)&&w(m),b&&E.clear&&delete E.clear}return C[e]=_,r({global:!0,forced:_!=y},C),g(_,e),b||t.setStrong(_,e,A),_}},9920:(e,n,t)=>{var r=t(2597),o=t(3887),i=t(1236),a=t(3070);e.exports=function(e,n){for(var t=o(n),l=a.f,c=i.f,u=0;u{var r=t(5112)("match");e.exports=function(e){var n=/./;try{"/./"[e](n)}catch(t){try{return n[r]=!1,"/./"[e](n)}catch(e){}}return!1}},8544:(e,n,t)=>{var r=t(7293);e.exports=!r((function(){function e(){}return e.prototype.constructor=null,Object.getPrototypeOf(new e)!==e.prototype}))},4230:(e,n,t)=>{var r=t(1702),o=t(4488),i=t(1340),a=/"/g,l=r("".replace);e.exports=function(e,n,t,r){var c=i(o(e)),u="<"+n;return""!==t&&(u+=" "+t+'="'+l(i(r),a,""")+'"'),u+">"+c+""}},4994:(e,n,t)=>{"use strict";var r=t(3383).IteratorPrototype,o=t(30),i=t(9114),a=t(8003),l=t(7497),c=function(){return this};e.exports=function(e,n,t){var u=n+" Iterator";return e.prototype=o(r,{next:i(1,t)}),a(e,u,!1,!0),l[u]=c,e}},8880:(e,n,t)=>{var r=t(9781),o=t(3070),i=t(9114);e.exports=r?function(e,n,t){return o.f(e,n,i(1,t))}:function(e,n,t){return e[n]=t,e}},9114:e=>{e.exports=function(e,n){return{enumerable:!(1&e),configurable:!(2&e),writable:!(4&e),value:n}}},6135:(e,n,t)=>{"use strict";var r=t(4948),o=t(3070),i=t(9114);e.exports=function(e,n,t){var a=r(n);a in e?o.f(e,a,i(0,t)):e[a]=t}},8709:(e,n,t)=>{"use strict";var r=t(7854),o=t(9670),i=t(2140),a=r.TypeError;e.exports=function(e){if(o(this),"string"===e||"default"===e)e="string";else if("number"!==e)throw a("Incorrect hint");return i(this,e)}},654:(e,n,t)=>{"use strict";var r=t(2109),o=t(6916),i=t(1913),a=t(6530),l=t(614),c=t(4994),u=t(9518),s=t(7674),f=t(8003),p=t(8880),d=t(1320),h=t(5112),g=t(7497),v=t(3383),A=a.PROPER,b=a.CONFIGURABLE,m=v.IteratorPrototype,y=v.BUGGY_SAFARI_ITERATORS,E=h("iterator"),_="keys",C="values",w="entries",x=function(){return this};e.exports=function(e,n,t,a,h,v,k){c(t,n,a);var S,O,B,I=function(e){if(e===h&&R)return R;if(!y&&e in j)return j[e];switch(e){case _:case C:case w:return function(){return new t(this,e)}}return function(){return new t(this)}},T=n+" Iterator",P=!1,j=e.prototype,z=j[E]||j["@@iterator"]||h&&j[h],R=!y&&z||I(h),M="Array"==n&&j.entries||z;if(M&&(S=u(M.call(new e)))!==Object.prototype&&S.next&&(i||u(S)===m||(s?s(S,m):l(S[E])||d(S,E,x)),f(S,T,!0,!0),i&&(g[T]=x)),A&&h==C&&z&&z.name!==C&&(!i&&b?p(j,"name",C):(P=!0,R=function(){return o(z,this)})),h)if(O={values:I(C),keys:v?R:I(_),entries:I(w)},k)for(B in O)(y||P||!(B in j))&&d(j,B,O[B]);else r({target:n,proto:!0,forced:y||P},O);return i&&!k||j[E]===R||d(j,E,R,{name:h}),g[n]=R,O}},7235:(e,n,t)=>{var r=t(857),o=t(2597),i=t(6061),a=t(3070).f;e.exports=function(e){var n=r.Symbol||(r.Symbol={});o(n,e)||a(n,e,{value:i.f(e)})}},9781:(e,n,t)=>{var r=t(7293);e.exports=!r((function(){return 7!=Object.defineProperty({},1,{get:function(){return 7}})[1]}))},317:(e,n,t)=>{var r=t(7854),o=t(111),i=r.document,a=o(i)&&o(i.createElement);e.exports=function(e){return a?i.createElement(e):{}}},8324:e=>{e.exports={CSSRuleList:0,CSSStyleDeclaration:0,CSSValueList:0,ClientRectList:0,DOMRectList:0,DOMStringList:0,DOMTokenList:1,DataTransferItemList:0,FileList:0,HTMLAllCollection:0,HTMLCollection:0,HTMLFormElement:0,HTMLSelectElement:0,MediaList:0,MimeTypeArray:0,NamedNodeMap:0,NodeList:1,PaintRequestList:0,Plugin:0,PluginArray:0,SVGLengthList:0,SVGNumberList:0,SVGPathSegList:0,SVGPointList:0,SVGStringList:0,SVGTransformList:0,SourceBufferList:0,StyleSheetList:0,TextTrackCueList:0,TextTrackList:0,TouchList:0}},8509:(e,n,t)=>{var r=t(317)("span").classList,o=r&&r.constructor&&r.constructor.prototype;e.exports=o===Object.prototype?void 0:o},8886:(e,n,t)=>{var r=t(8113).match(/firefox\/(\d+)/i);e.exports=!!r&&+r[1]},256:(e,n,t)=>{var r=t(8113);e.exports=/MSIE|Trident/.test(r)},5268:(e,n,t)=>{var r=t(4326),o=t(7854);e.exports="process"==r(o.process)},8113:(e,n,t)=>{var r=t(5005);e.exports=r("navigator","userAgent")||""},7392:(e,n,t)=>{var r,o,i=t(7854),a=t(8113),l=i.process,c=i.Deno,u=l&&l.versions||c&&c.version,s=u&&u.v8;s&&(o=(r=s.split("."))[0]>0&&r[0]<4?1:+(r[0]+r[1])),!o&&a&&(!(r=a.match(/Edge\/(\d+)/))||r[1]>=74)&&(r=a.match(/Chrome\/(\d+)/))&&(o=+r[1]),e.exports=o},8008:(e,n,t)=>{var r=t(8113).match(/AppleWebKit\/(\d+)\./);e.exports=!!r&&+r[1]},748:e=>{e.exports=["constructor","hasOwnProperty","isPrototypeOf","propertyIsEnumerable","toLocaleString","toString","valueOf"]},2109:(e,n,t)=>{var r=t(7854),o=t(1236).f,i=t(8880),a=t(1320),l=t(3505),c=t(9920),u=t(4705);e.exports=function(e,n){var t,s,f,p,d,h=e.target,g=e.global,v=e.stat;if(t=g?r:v?r[h]||l(h,{}):(r[h]||{}).prototype)for(s in n){if(p=n[s],f=e.noTargetGet?(d=o(t,s))&&d.value:t[s],!u(g?s:h+(v?".":"#")+s,e.forced)&&void 0!==f){if(typeof p==typeof f)continue;c(p,f)}(e.sham||f&&f.sham)&&i(p,"sham",!0),a(t,s,p,e)}}},7293:e=>{e.exports=function(e){try{return!!e()}catch(e){return!0}}},7007:(e,n,t)=>{"use strict";t(4916);var r=t(1702),o=t(1320),i=t(2261),a=t(7293),l=t(5112),c=t(8880),u=l("species"),s=RegExp.prototype;e.exports=function(e,n,t,f){var p=l(e),d=!a((function(){var n={};return n[p]=function(){return 7},7!=""[e](n)})),h=d&&!a((function(){var n=!1,t=/a/;return"split"===e&&((t={}).constructor={},t.constructor[u]=function(){return t},t.flags="",t[p]=/./[p]),t.exec=function(){return n=!0,null},t[p](""),!n}));if(!d||!h||t){var g=r(/./[p]),v=n(p,""[e],(function(e,n,t,o,a){var l=r(e),c=n.exec;return c===i||c===s.exec?d&&!a?{done:!0,value:g(n,t,o)}:{done:!0,value:l(t,n,o)}:{done:!1}}));o(String.prototype,e,v[0]),o(s,p,v[1])}f&&c(s[p],"sham",!0)}},6677:(e,n,t)=>{var r=t(7293);e.exports=!r((function(){return Object.isExtensible(Object.preventExtensions({}))}))},2104:e=>{var n=Function.prototype,t=n.apply,r=n.bind,o=n.call;e.exports="object"==typeof Reflect&&Reflect.apply||(r?o.bind(t):function(){return o.apply(t,arguments)})},9974:(e,n,t)=>{var r=t(1702),o=t(9662),i=r(r.bind);e.exports=function(e,n){return o(e),void 0===n?e:i?i(e,n):function(){return e.apply(n,arguments)}}},7065:(e,n,t)=>{"use strict";var r=t(7854),o=t(1702),i=t(9662),a=t(111),l=t(2597),c=t(206),u=r.Function,s=o([].concat),f=o([].join),p={},d=function(e,n,t){if(!l(p,n)){for(var r=[],o=0;o{var n=Function.prototype.call;e.exports=n.bind?n.bind(n):function(){return n.apply(n,arguments)}},6530:(e,n,t)=>{var r=t(9781),o=t(2597),i=Function.prototype,a=r&&Object.getOwnPropertyDescriptor,l=o(i,"name"),c=l&&"something"===function(){}.name,u=l&&(!r||r&&a(i,"name").configurable);e.exports={EXISTS:l,PROPER:c,CONFIGURABLE:u}},1702:e=>{var n=Function.prototype,t=n.bind,r=n.call,o=t&&t.bind(r);e.exports=t?function(e){return e&&o(r,e)}:function(e){return e&&function(){return r.apply(e,arguments)}}},5005:(e,n,t)=>{var r=t(7854),o=t(614),i=function(e){return o(e)?e:void 0};e.exports=function(e,n){return arguments.length<2?i(r[e]):r[e]&&r[e][n]}},1246:(e,n,t)=>{var r=t(648),o=t(8173),i=t(7497),a=t(5112)("iterator");e.exports=function(e){if(null!=e)return o(e,a)||o(e,"@@iterator")||i[r(e)]}},8554:(e,n,t)=>{var r=t(7854),o=t(6916),i=t(9662),a=t(9670),l=t(6330),c=t(1246),u=r.TypeError;e.exports=function(e,n){var t=arguments.length<2?c(e):n;if(i(t))return a(o(t,e));throw u(l(e)+" is not iterable")}},8173:(e,n,t)=>{var r=t(9662);e.exports=function(e,n){var t=e[n];return null==t?void 0:r(t)}},647:(e,n,t)=>{var r=t(1702),o=t(7908),i=Math.floor,a=r("".charAt),l=r("".replace),c=r("".slice),u=/\$([$&'`]|\d{1,2}|<[^>]*>)/g,s=/\$([$&'`]|\d{1,2})/g;e.exports=function(e,n,t,r,f,p){var d=t+e.length,h=r.length,g=s;return void 0!==f&&(f=o(f),g=u),l(p,g,(function(o,l){var u;switch(a(l,0)){case"$":return"$";case"&":return e;case"`":return c(n,0,t);case"'":return c(n,d);case"<":u=f[c(l,1,-1)];break;default:var s=+l;if(0===s)return o;if(s>h){var p=i(s/10);return 0===p?o:p<=h?void 0===r[p-1]?a(l,1):r[p-1]+a(l,1):o}u=r[s-1]}return void 0===u?"":u}))}},7854:(e,n,t)=>{var r=function(e){return e&&e.Math==Math&&e};e.exports=r("object"==typeof globalThis&&globalThis)||r("object"==typeof window&&window)||r("object"==typeof self&&self)||r("object"==typeof t.g&&t.g)||function(){return this}()||Function("return this")()},2597:(e,n,t)=>{var r=t(1702),o=t(7908),i=r({}.hasOwnProperty);e.exports=Object.hasOwn||function(e,n){return i(o(e),n)}},3501:e=>{e.exports={}},490:(e,n,t)=>{var r=t(5005);e.exports=r("document","documentElement")},4664:(e,n,t)=>{var r=t(9781),o=t(7293),i=t(317);e.exports=!r&&!o((function(){return 7!=Object.defineProperty(i("div"),"a",{get:function(){return 7}}).a}))},8361:(e,n,t)=>{var r=t(7854),o=t(1702),i=t(7293),a=t(4326),l=r.Object,c=o("".split);e.exports=i((function(){return!l("z").propertyIsEnumerable(0)}))?function(e){return"String"==a(e)?c(e,""):l(e)}:l},9587:(e,n,t)=>{var r=t(614),o=t(111),i=t(7674);e.exports=function(e,n,t){var a,l;return i&&r(a=n.constructor)&&a!==t&&o(l=a.prototype)&&l!==t.prototype&&i(e,l),e}},2788:(e,n,t)=>{var r=t(1702),o=t(614),i=t(5465),a=r(Function.toString);o(i.inspectSource)||(i.inspectSource=function(e){return a(e)}),e.exports=i.inspectSource},2423:(e,n,t)=>{var r=t(2109),o=t(1702),i=t(3501),a=t(111),l=t(2597),c=t(3070).f,u=t(8006),s=t(1156),f=t(2050),p=t(9711),d=t(6677),h=!1,g=p("meta"),v=0,A=function(e){c(e,g,{value:{objectID:"O"+v++,weakData:{}}})},b=e.exports={enable:function(){b.enable=function(){},h=!0;var e=u.f,n=o([].splice),t={};t[g]=1,e(t).length&&(u.f=function(t){for(var r=e(t),o=0,i=r.length;o{var r,o,i,a=t(8536),l=t(7854),c=t(1702),u=t(111),s=t(8880),f=t(2597),p=t(5465),d=t(6200),h=t(3501),g="Object already initialized",v=l.TypeError,A=l.WeakMap;if(a||p.state){var b=p.state||(p.state=new A),m=c(b.get),y=c(b.has),E=c(b.set);r=function(e,n){if(y(b,e))throw new v(g);return n.facade=e,E(b,e,n),n},o=function(e){return m(b,e)||{}},i=function(e){return y(b,e)}}else{var _=d("state");h[_]=!0,r=function(e,n){if(f(e,_))throw new v(g);return n.facade=e,s(e,_,n),n},o=function(e){return f(e,_)?e[_]:{}},i=function(e){return f(e,_)}}e.exports={set:r,get:o,has:i,enforce:function(e){return i(e)?o(e):r(e,{})},getterFor:function(e){return function(n){var t;if(!u(n)||(t=o(n)).type!==e)throw v("Incompatible receiver, "+e+" required");return t}}}},7659:(e,n,t)=>{var r=t(5112),o=t(7497),i=r("iterator"),a=Array.prototype;e.exports=function(e){return void 0!==e&&(o.Array===e||a[i]===e)}},3157:(e,n,t)=>{var r=t(4326);e.exports=Array.isArray||function(e){return"Array"==r(e)}},614:e=>{e.exports=function(e){return"function"==typeof e}},4411:(e,n,t)=>{var r=t(1702),o=t(7293),i=t(614),a=t(648),l=t(5005),c=t(2788),u=function(){},s=[],f=l("Reflect","construct"),p=/^\s*(?:class|function)\b/,d=r(p.exec),h=!p.exec(u),g=function(e){if(!i(e))return!1;try{return f(u,s,e),!0}catch(e){return!1}};e.exports=!f||o((function(){var e;return g(g.call)||!g(Object)||!g((function(){e=!0}))||e}))?function(e){if(!i(e))return!1;switch(a(e)){case"AsyncFunction":case"GeneratorFunction":case"AsyncGeneratorFunction":return!1}return h||!!d(p,c(e))}:g},4705:(e,n,t)=>{var r=t(7293),o=t(614),i=/#|\.prototype\./,a=function(e,n){var t=c[l(e)];return t==s||t!=u&&(o(n)?r(n):!!n)},l=a.normalize=function(e){return String(e).replace(i,".").toLowerCase()},c=a.data={},u=a.NATIVE="N",s=a.POLYFILL="P";e.exports=a},111:(e,n,t)=>{var r=t(614);e.exports=function(e){return"object"==typeof e?null!==e:r(e)}},1913:e=>{e.exports=!1},7850:(e,n,t)=>{var r=t(111),o=t(4326),i=t(5112)("match");e.exports=function(e){var n;return r(e)&&(void 0!==(n=e[i])?!!n:"RegExp"==o(e))}},2190:(e,n,t)=>{var r=t(7854),o=t(5005),i=t(614),a=t(7976),l=t(3307),c=r.Object;e.exports=l?function(e){return"symbol"==typeof e}:function(e){var n=o("Symbol");return i(n)&&a(n.prototype,c(e))}},408:(e,n,t)=>{var r=t(7854),o=t(9974),i=t(6916),a=t(9670),l=t(6330),c=t(7659),u=t(6244),s=t(7976),f=t(8554),p=t(1246),d=t(9212),h=r.TypeError,g=function(e,n){this.stopped=e,this.result=n},v=g.prototype;e.exports=function(e,n,t){var r,A,b,m,y,E,_,C=t&&t.that,w=!(!t||!t.AS_ENTRIES),x=!(!t||!t.IS_ITERATOR),k=!(!t||!t.INTERRUPTED),S=o(n,C),O=function(e){return r&&d(r,"normal",e),new g(!0,e)},B=function(e){return w?(a(e),k?S(e[0],e[1],O):S(e[0],e[1])):k?S(e,O):S(e)};if(x)r=e;else{if(!(A=p(e)))throw h(l(e)+" is not iterable");if(c(A)){for(b=0,m=u(e);m>b;b++)if((y=B(e[b]))&&s(v,y))return y;return new g(!1)}r=f(e,A)}for(E=r.next;!(_=i(E,r)).done;){try{y=B(_.value)}catch(e){d(r,"throw",e)}if("object"==typeof y&&y&&s(v,y))return y}return new g(!1)}},9212:(e,n,t)=>{var r=t(6916),o=t(9670),i=t(8173);e.exports=function(e,n,t){var a,l;o(e);try{if(!(a=i(e,"return"))){if("throw"===n)throw t;return t}a=r(a,e)}catch(e){l=!0,a=e}if("throw"===n)throw t;if(l)throw a;return o(a),t}},3383:(e,n,t)=>{"use strict";var r,o,i,a=t(7293),l=t(614),c=t(30),u=t(9518),s=t(1320),f=t(5112),p=t(1913),d=f("iterator"),h=!1;[].keys&&("next"in(i=[].keys())?(o=u(u(i)))!==Object.prototype&&(r=o):h=!0),null==r||a((function(){var e={};return r[d].call(e)!==e}))?r={}:p&&(r=c(r)),l(r[d])||s(r,d,(function(){return this})),e.exports={IteratorPrototype:r,BUGGY_SAFARI_ITERATORS:h}},7497:e=>{e.exports={}},6244:(e,n,t)=>{var r=t(7466);e.exports=function(e){return r(e.length)}},133:(e,n,t)=>{var r=t(7392),o=t(7293);e.exports=!!Object.getOwnPropertySymbols&&!o((function(){var e=Symbol();return!String(e)||!(Object(e)instanceof Symbol)||!Symbol.sham&&r&&r<41}))},8536:(e,n,t)=>{var r=t(7854),o=t(614),i=t(2788),a=r.WeakMap;e.exports=o(a)&&/native code/.test(i(a))},3929:(e,n,t)=>{var r=t(7854),o=t(7850),i=r.TypeError;e.exports=function(e){if(o(e))throw i("The method doesn't accept regular expressions");return e}},1574:(e,n,t)=>{"use strict";var r=t(9781),o=t(1702),i=t(6916),a=t(7293),l=t(1956),c=t(5181),u=t(5296),s=t(7908),f=t(8361),p=Object.assign,d=Object.defineProperty,h=o([].concat);e.exports=!p||a((function(){if(r&&1!==p({b:1},p(d({},"a",{enumerable:!0,get:function(){d(this,"b",{value:3,enumerable:!1})}}),{b:2})).b)return!0;var e={},n={},t=Symbol(),o="abcdefghijklmnopqrst";return e[t]=7,o.split("").forEach((function(e){n[e]=e})),7!=p({},e)[t]||l(p({},n)).join("")!=o}))?function(e,n){for(var t=s(e),o=arguments.length,a=1,p=c.f,d=u.f;o>a;)for(var g,v=f(arguments[a++]),A=p?h(l(v),p(v)):l(v),b=A.length,m=0;b>m;)g=A[m++],r&&!i(d,v,g)||(t[g]=v[g]);return t}:p},30:(e,n,t)=>{var r,o=t(9670),i=t(6048),a=t(748),l=t(3501),c=t(490),u=t(317),s=t(6200),f=s("IE_PROTO"),p=function(){},d=function(e){return"
@kompkit/core
    Preparing search index...

    Function debounce

    • Debounces a function call by delaying its execution until after a specified wait period. -Subsequent calls within the wait period reset the timer.

      -

      Type Parameters

      • T extends (...args: any[]) => any

      Parameters

      • fn: T

        The function to debounce.

        -
      • wait: number = 250

        Milliseconds to wait before invoking the function. Defaults to 250ms.

        -

      Returns (...args: Parameters<T>) => void

      A debounced version of the function.

      -
      const search = debounce((query: string) => {
      console.log('Searching:', query);
      }, 300);

      search('hello'); // Will execute after 300ms if no other calls are made -
      - -
    diff --git a/docs/api/web/functions/formatCurrency.html b/docs/api/web/functions/formatCurrency.html deleted file mode 100644 index 6e8247b..0000000 --- a/docs/api/web/functions/formatCurrency.html +++ /dev/null @@ -1,9 +0,0 @@ -formatCurrency | @kompkit/core
    @kompkit/core
      Preparing search index...

      Function formatCurrency

      • Formats a number as a localized currency string.

        -

        Parameters

        • amount: number

          The numeric amount to format.

          -
        • currency: string = "EUR"

          The currency code (e.g., "USD", "EUR", "JPY"). Defaults to "EUR".

          -
        • locale: string = "es-ES"

          The locale string (e.g., "en-US", "es-ES"). Defaults to "es-ES".

          -

        Returns string

        A formatted currency string.

        -
        formatCurrency(1234.56); // "1.234,56 €" (es-ES default)
        formatCurrency(1234.56, "USD", "en-US"); // "$1,234.56"
        formatCurrency(1000, "JPY", "ja-JP"); // "¥1,000" -
        - -
      diff --git a/docs/api/web/functions/isEmail.html b/docs/api/web/functions/isEmail.html deleted file mode 100644 index fe6b7a3..0000000 --- a/docs/api/web/functions/isEmail.html +++ /dev/null @@ -1,7 +0,0 @@ -isEmail | @kompkit/core
      @kompkit/core
        Preparing search index...

        Function isEmail

        • Validates whether a string matches a basic email pattern.

          -

          Parameters

          • v: string

            The string to validate.

            -

          Returns boolean

          true if the string is a valid email format, false otherwise.

          -
          isEmail('user@example.com'); // true
          isEmail('invalid@'); // false
          isEmail(' test@domain.org '); // true (whitespace is trimmed) -
          - -
        diff --git a/docs/api/web/hierarchy.html b/docs/api/web/hierarchy.html deleted file mode 100644 index 03f92ce..0000000 --- a/docs/api/web/hierarchy.html +++ /dev/null @@ -1 +0,0 @@ -@kompkit/core
        @kompkit/core
          Preparing search index...

          @kompkit/core

          Hierarchy Summary

          diff --git a/docs/api/web/index.html b/docs/api/web/index.html deleted file mode 100644 index 8113f66..0000000 --- a/docs/api/web/index.html +++ /dev/null @@ -1 +0,0 @@ -@kompkit/core
          @kompkit/core
            Preparing search index...

            @kompkit/core

            Functions

            debounce
            formatCurrency
            isEmail
            diff --git a/docs/contributing.md b/docs/contributing.md index f5df6e9..2209916 100644 --- a/docs/contributing.md +++ b/docs/contributing.md @@ -8,17 +8,20 @@ We welcome contributions to KompKit! This document provides guidelines for contr - **Node.js** 20+ and npm - **JDK** 17+ (for Kotlin development) +- **Flutter** 3.0+ and Dart 3.0+ (for Flutter development) - **Git** for version control ### Development Setup 1. **Fork and clone the repository** + ```bash git clone https://github.com/YOUR_USERNAME/KompKit.git cd KompKit ``` 2. **Install dependencies** + ```bash npm install ``` @@ -49,6 +52,7 @@ We use [Conventional Commits](https://www.conventionalcommits.org/) for consiste ``` **Types:** + - `feat`: New features - `fix`: Bug fixes - `docs`: Documentation changes @@ -59,6 +63,7 @@ We use [Conventional Commits](https://www.conventionalcommits.org/) for consiste - `ci`: CI/CD changes **Examples:** + ```bash feat(web): add throttle utility function fix(kotlin): resolve debounce memory leak @@ -68,9 +73,9 @@ test(web): add edge cases for email validation ### Code Guidelines -1. **Cross-platform API parity**: Maintain identical APIs across TypeScript and Kotlin implementations +1. **Cross-platform API parity**: Maintain identical APIs across TypeScript, Kotlin, and Dart implementations 2. **Zero dependencies**: Avoid adding runtime dependencies unless absolutely necessary -3. **Comprehensive testing**: Every feature must include tests for both platforms +3. **Comprehensive testing**: Every feature must include tests for all platforms 4. **Documentation**: Update API docs and examples for new features 5. **Type safety**: Use TypeScript and Kotlin type systems effectively @@ -100,6 +105,9 @@ npm run test:web # Run Kotlin tests only npm run test:android + +# Run Flutter tests only +cd packages/core/flutter && flutter test ``` ### Documentation @@ -132,50 +140,72 @@ cd packages/core/android && ./gradlew ktlintFormat When adding a new utility function: -1. **Implement in both platforms**: +1. **Implement in all three platforms**: - TypeScript: `packages/core/web/src/` - Kotlin: `packages/core/android/src/main/kotlin/com/kompkit/core/` + - Dart: `packages/core/flutter/lib/src/` 2. **Maintain API consistency**: + ```typescript // TypeScript export function myUtility(param: string): boolean { ... } ``` + ```kotlin // Kotlin fun myUtility(param: String): Boolean { ... } ``` + ```dart + // Dart + bool myUtility(String param) { ... } + ``` + 3. **Add comprehensive tests**: - Web: `packages/core/web/tests/` - Kotlin: `packages/core/android/src/test/kotlin/` + - Flutter: `packages/core/flutter/test/` 4. **Update exports**: - Add to `packages/core/web/src/index.ts` + - Add to `packages/core/flutter/src/kompkit_core.dart` - Kotlin exports are automatic via package structure 5. **Document with examples**: - Add JSDoc comments (TypeScript) - Add KDoc comments (Kotlin) + - Add DartDoc comments (Dart) ## Code Style ### TypeScript + - Use ESLint and Prettier configurations - Prefer `const` over `let` - Use explicit return types for public APIs - Follow existing naming conventions ### Kotlin + - Follow ktlint formatting rules - Use detekt for static analysis - Prefer `val` over `var` - Use explicit types for public APIs - Follow Kotlin coding conventions +### Dart/Flutter + +- Follow Dart formatting rules (`dart format`) +- Use `flutter analyze` for static analysis +- Prefer `final` over `var` when possible +- Use explicit types for public APIs +- Follow Dart style guide conventions + ## Pull Request Process 1. **Create a feature branch**: + ```bash git checkout develop git pull origin develop @@ -183,23 +213,27 @@ When adding a new utility function: ``` 2. **Make your changes**: - - Implement feature in both platforms + - Implement feature in all platforms (Web, Android, Flutter) - Add comprehensive tests - Update documentation 3. **Test thoroughly**: + ```bash npm test cd packages/core/android && ./gradlew test + cd packages/core/flutter && flutter test ``` 4. **Commit with conventional messages**: + ```bash git add . git commit -m "feat(core): add new utility function" ``` 5. **Push and create PR**: + ```bash git push origin feature/your-feature-name ``` @@ -208,8 +242,8 @@ When adding a new utility function: ### PR Checklist -- [ ] ✅ Feature implemented in both TypeScript and Kotlin -- [ ] ✅ Tests added for both platforms with good coverage +- [ ] ✅ Feature implemented in TypeScript, Kotlin, and Dart +- [ ] ✅ Tests added for all platforms with good coverage - [ ] ✅ All existing tests pass (`npm test`) - [ ] ✅ Code follows style guidelines (ktlint, ESLint) - [ ] ✅ API documentation updated (JSDoc/KDoc) diff --git a/docs/flutter.md b/docs/flutter.md new file mode 100644 index 0000000..01460f1 --- /dev/null +++ b/docs/flutter.md @@ -0,0 +1,320 @@ +# Flutter/Dart Guide + +This guide covers using KompKit Core utilities in Flutter and Dart applications. + +Status: `V0.2.0-alpha`. + +## Installation + +### Flutter Projects + +Add KompKit Core to your `pubspec.yaml`: + +```yaml +dependencies: + kompkit_core: + path: path/to/KompKit/packages/core/flutter +``` + +Then run: + +```bash +flutter pub get +``` + +### Dart Projects + +For server-side Dart projects, add to your `pubspec.yaml`: + +```yaml +dependencies: + kompkit_core: + path: path/to/KompKit/packages/core/flutter +``` + +Then run: + +```bash +dart pub get +``` + +## Usage + +Import the package in your Dart files: + +```dart +import 'package:kompkit_core/kompkit_core.dart'; +``` + +## Utilities + +### Debounce + +Delay function execution to prevent excessive calls: + +```dart +// For functions with parameters +final searchDebounced = debounce((String query) { + print('Searching for: $query'); + // Perform search logic here +}, const Duration(milliseconds: 300)); + +// Usage +searchDebounced('flutter'); +searchDebounced('dart'); // Previous call is cancelled + +// For void functions (no parameters) +final saveDebounced = debounceVoid(() { + print('Saving data...'); + // Perform save logic here +}, const Duration(milliseconds: 500)); + +// Usage +saveDebounced(); +``` + +#### Flutter Widget Example + +```dart +class SearchWidget extends StatefulWidget { + @override + _SearchWidgetState createState() => _SearchWidgetState(); +} + +class _SearchWidgetState extends State { + late final Function(String) _debouncedSearch; + + @override + void initState() { + super.initState(); + _debouncedSearch = debounce((String query) { + // Perform search API call + _performSearch(query); + }, const Duration(milliseconds: 300)); + } + + void _performSearch(String query) { + // Your search logic here + print('Searching for: $query'); + } + + @override + Widget build(BuildContext context) { + return TextField( + onChanged: _debouncedSearch, + decoration: InputDecoration( + hintText: 'Search...', + ), + ); + } +} +``` + +### Email Validation + +Validate email addresses with a simple function: + +```dart +// Basic validation +print(isEmail('user@example.com')); // true +print(isEmail('invalid-email')); // false + +// Handles whitespace +print(isEmail(' test@domain.org ')); // true (trimmed) + +// Form validation example +String? validateEmail(String? value) { + if (value == null || value.isEmpty) { + return 'Email is required'; + } + if (!isEmail(value)) { + return 'Please enter a valid email'; + } + return null; +} + +// Usage in Flutter Form +TextFormField( + validator: validateEmail, + decoration: InputDecoration( + labelText: 'Email', + ), +) +``` + +### Currency Formatting + +Format numbers as localized currency strings: + +```dart +// Default (EUR, es_ES locale) +print(formatCurrency(1234.56)); // "1.234,56 €" + +// US Dollar +print(formatCurrency(1234.56, currency: 'USD', locale: 'en_US')); // "$1,234.56" + +// Japanese Yen +print(formatCurrency(1000, currency: 'JPY', locale: 'ja_JP')); // "¥1,000" + +// British Pound +print(formatCurrency(999.99, currency: 'GBP', locale: 'en_GB')); // "£999.99" +``` + +#### Flutter Widget Example + +```dart +class PriceDisplay extends StatelessWidget { + final double price; + final String currency; + final String locale; + + const PriceDisplay({ + Key? key, + required this.price, + this.currency = 'USD', + this.locale = 'en_US', + }) : super(key: key); + + @override + Widget build(BuildContext context) { + return Text( + formatCurrency(price, currency: currency, locale: locale), + style: Theme.of(context).textTheme.headlineMedium, + ); + } +} + +// Usage +PriceDisplay(price: 29.99, currency: 'USD', locale: 'en_US') +``` + +## Complete Example + +Here's a complete Flutter app example using all KompKit utilities: + +```dart +import 'package:flutter/material.dart'; +import 'package:kompkit_core/kompkit_core.dart'; + +void main() { + runApp(MyApp()); +} + +class MyApp extends StatelessWidget { + @override + Widget build(BuildContext context) { + return MaterialApp( + title: 'KompKit Demo', + home: DemoScreen(), + ); + } +} + +class DemoScreen extends StatefulWidget { + @override + _DemoScreenState createState() => _DemoScreenState(); +} + +class _DemoScreenState extends State { + final _emailController = TextEditingController(); + final _priceController = TextEditingController(); + late final Function(String) _debouncedEmailCheck; + + String _emailStatus = ''; + String _formattedPrice = ''; + + @override + void initState() { + super.initState(); + _debouncedEmailCheck = debounce((String email) { + setState(() { + _emailStatus = isEmail(email) ? 'Valid email ✅' : 'Invalid email ❌'; + }); + }, const Duration(milliseconds: 300)); + } + + void _formatPrice() { + final price = double.tryParse(_priceController.text) ?? 0; + setState(() { + _formattedPrice = formatCurrency(price, currency: 'USD', locale: 'en_US'); + }); + } + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: AppBar(title: Text('KompKit Demo')), + body: Padding( + padding: EdgeInsets.all(16), + child: Column( + children: [ + TextField( + controller: _emailController, + onChanged: _debouncedEmailCheck, + decoration: InputDecoration( + labelText: 'Email', + hintText: 'Enter email address', + ), + ), + SizedBox(height: 8), + Text(_emailStatus), + SizedBox(height: 24), + TextField( + controller: _priceController, + keyboardType: TextInputType.number, + decoration: InputDecoration( + labelText: 'Price', + hintText: 'Enter price', + ), + ), + SizedBox(height: 8), + ElevatedButton( + onPressed: _formatPrice, + child: Text('Format as Currency'), + ), + SizedBox(height: 8), + Text(_formattedPrice, style: TextStyle(fontSize: 18)), + ], + ), + ), + ); + } +} +``` + +## Testing + +Run tests for your Flutter project: + +```bash +flutter test +``` + +For Dart-only projects: + +```bash +dart test +``` + +## Platform Support + +KompKit Core for Flutter/Dart works on: + +- ✅ Flutter iOS +- ✅ Flutter Android +- ✅ Flutter Web +- ✅ Flutter Desktop (Windows, macOS, Linux) +- ✅ Dart VM (Server-side) +- ✅ Dart Web (compiled to JavaScript) + +## Performance Notes + +- **Debounce**: Uses Dart's `Timer` class for efficient scheduling +- **Email Validation**: Compiled regex for fast validation +- **Currency Formatting**: Leverages Dart's `intl` package for optimal localization + +## Next Steps + +- Check out the [API Reference](./api/flutter/) for detailed documentation +- See [Examples](./examples/flutter/) for more usage patterns +- Read the [Contributing Guide](./CONTRIBUTING.md) to contribute improvements diff --git a/docs/getting-started.md b/docs/getting-started.md index 45afab1..4415637 100644 --- a/docs/getting-started.md +++ b/docs/getting-started.md @@ -1,27 +1,42 @@ # Getting started -KompKit Core is a small cross-platform utility library for Web (TypeScript) and Android (Kotlin). +KompKit Core is a small cross-platform utility library for Web (TypeScript), Android (Kotlin), and Flutter (Dart). -Status: `0.0.x-alpha`. +Status: `V0.2.0-alpha`. ## Install ### Web (React/Vue) + ```bash npm i @kompkit/core ``` ### Android (Gradle) + Add the dependency to your module build file: + ```kotlin dependencies { implementation("com.kompkit:core:") - implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.8.1") + implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.10.2") } ``` +### Flutter (pubspec.yaml) + +Add the dependency to your pubspec.yaml: + +```yaml +dependencies: + kompkit_core: + path: path/to/KompKit/packages/core/flutter +``` + ## Build and test locally + Run from the repository root: + ```bash # Build web package npm run build @@ -33,9 +48,9 @@ npm run test ## Utilities | Utility | Description | -|------------------|--------------------------------------------------| +| ---------------- | ------------------------------------------------ | | `debounce` | Debounce a function call by a delay. | | `isEmail` | Validate a string with a basic email regex. | | `formatCurrency` | Format numbers into a localized currency string. | -Next: read the detailed guides for [Web](./web.md), [Android](./android.md), and the [Recipes](./recipes.md). +Next: read the detailed guides for [Web](./web.md), [Android](./android.md), [Flutter](./flutter.md), and the [Recipes](./recipes.md). diff --git a/docs/index.md b/docs/index.md index 151b972..d17af8d 100644 --- a/docs/index.md +++ b/docs/index.md @@ -1,8 +1,8 @@ # KompKit Core -Tiny, cross-platform utilities for **Web (TypeScript)** and **Android (Kotlin)**. +Tiny, cross-platform utilities for **Web (TypeScript)**, **Android (Kotlin)**, and **Flutter (Dart)**. -Status: `0.0.x-alpha` (APIs may change). +Status: `V0.2.0-alpha`. ## Utilities @@ -15,7 +15,9 @@ Status: `0.0.x-alpha` (APIs may change). - Getting started: [docs/getting-started.md](./getting-started.md) - Web guide: [docs/web.md](./web.md) - Android guide: [docs/android.md](./android.md) +- Flutter guide: [docs/flutter.md](./flutter.md) - Recipes: [docs/recipes.md](./recipes.md) - API Reference (Web): [docs/api/web](./api/web/) - API Reference (Android): [docs/api/android](./api/android/) -- Roadmap: [docs/roadmap.md](./roadmap.md) \ No newline at end of file +- API Reference (Flutter): [docs/api/flutter](./api/flutter/) +- Roadmap: [docs/roadmap.md](./roadmap.md) diff --git a/docs/recipes.md b/docs/recipes.md index c2a1867..17f4a1e 100644 --- a/docs/recipes.md +++ b/docs/recipes.md @@ -88,6 +88,74 @@ suspend fun fetchResults(query: String): List { } ``` +## Debounced search input (Flutter) + +```dart +import 'package:flutter/material.dart'; +import 'package:kompkit_core/kompkit_core.dart'; + +class SearchScreen extends StatefulWidget { + @override + _SearchScreenState createState() => _SearchScreenState(); +} + +class _SearchScreenState extends State { + final TextEditingController _controller = TextEditingController(); + late final Function(String) _debouncedSearch; + List _results = []; + + @override + void initState() { + super.initState(); + _debouncedSearch = debounce((String query) async { + if (query.isEmpty) return; + final results = await _fetchResults(query); + setState(() { + _results = results; + }); + }, const Duration(milliseconds: 400)); + } + + Future> _fetchResults(String query) async { + // API call here + await Future.delayed(Duration(milliseconds: 500)); // Simulate API delay + return ['Result 1 for $query', 'Result 2 for $query']; + } + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: AppBar(title: Text('Search')), + body: Column( + children: [ + Padding( + padding: EdgeInsets.all(16), + child: TextField( + controller: _controller, + onChanged: _debouncedSearch, + decoration: InputDecoration( + hintText: 'Search...', + border: OutlineInputBorder(), + ), + ), + ), + Expanded( + child: ListView.builder( + itemCount: _results.length, + itemBuilder: (context, index) { + return ListTile( + title: Text(_results[index]), + ); + }, + ), + ), + ], + ), + ); + } +} +``` + ## Currency formatting with locale switch ```tsx @@ -154,3 +222,131 @@ function ContactForm() { ); } ``` + +## Currency formatting with locale switch (Flutter) + +```dart +import 'package:flutter/material.dart'; +import 'package:kompkit_core/kompkit_core.dart'; + +class PriceDisplay extends StatefulWidget { + final double amount; + + const PriceDisplay({Key? key, required this.amount}) : super(key: key); + + @override + _PriceDisplayState createState() => _PriceDisplayState(); +} + +class _PriceDisplayState extends State { + String _selectedLocale = 'en_US'; + + final Map> _localeConfig = { + 'en_US': {'currency': 'USD', 'locale': 'en_US'}, + 'es_ES': {'currency': 'EUR', 'locale': 'es_ES'}, + 'ja_JP': {'currency': 'JPY', 'locale': 'ja_JP'}, + }; + + @override + Widget build(BuildContext context) { + final config = _localeConfig[_selectedLocale]!; + final formatted = formatCurrency( + widget.amount, + currency: config['currency']!, + locale: config['locale']!, + ); + + return Column( + children: [ + Text( + 'Price: $formatted', + style: Theme.of(context).textTheme.headlineMedium, + ), + SizedBox(height: 16), + DropdownButton( + value: _selectedLocale, + onChanged: (String? newValue) { + setState(() { + _selectedLocale = newValue!; + }); + }, + items: _localeConfig.keys.map>((String value) { + return DropdownMenuItem( + value: value, + child: Text(_localeConfig[value]!['currency']!), + ); + }).toList(), + ), + ], + ); + } +} +``` + +## Email validation on form submission (Flutter) + +```dart +import 'package:flutter/material.dart'; +import 'package:kompkit_core/kompkit_core.dart'; + +class ContactForm extends StatefulWidget { + @override + _ContactFormState createState() => _ContactFormState(); +} + +class _ContactFormState extends State { + final TextEditingController _emailController = TextEditingController(); + final GlobalKey _formKey = GlobalKey(); + + void _handleSubmit() { + if (_formKey.currentState!.validate()) { + // Submit form + print('Submitting: ${_emailController.text}'); + ScaffoldMessenger.of(context).showSnackBar( + SnackBar(content: Text('Form submitted successfully!')), + ); + } + } + + String? _validateEmail(String? value) { + if (value == null || value.isEmpty) { + return 'Email is required'; + } + if (!isEmail(value)) { + return 'Please enter a valid email address'; + } + return null; + } + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: AppBar(title: Text('Contact Form')), + body: Padding( + padding: EdgeInsets.all(16), + child: Form( + key: _formKey, + child: Column( + children: [ + TextFormField( + controller: _emailController, + validator: _validateEmail, + decoration: InputDecoration( + labelText: 'Email', + border: OutlineInputBorder(), + ), + keyboardType: TextInputType.emailAddress, + ), + SizedBox(height: 16), + ElevatedButton( + onPressed: _handleSubmit, + child: Text('Submit'), + ), + ], + ), + ), + ), + ); + } +} +``` diff --git a/docs/roadmap.md b/docs/roadmap.md index 42ee459..502fe3e 100644 --- a/docs/roadmap.md +++ b/docs/roadmap.md @@ -5,7 +5,8 @@ KompKit Core is in early development. This roadmap outlines planned features and ## Current phase: Stability and parity The focus is on: -- Ensuring API consistency between web and android implementations + +- Ensuring API consistency between web, android, and flutter implementations - Expanding test coverage - Fixing bugs and edge cases - Improving documentation @@ -42,6 +43,6 @@ The focus is on: - Optional React hooks package (`@kompkit/react`) - Optional Vue composables package (`@kompkit/vue`) - UI component library (post-1.0) -- Additional platform support (iOS, Flutter) +- Additional platform support (iOS native) Timelines are subject to change based on community feedback and contributions. diff --git a/docs/web.md b/docs/web.md index 46c851f..bfaa9ce 100644 --- a/docs/web.md +++ b/docs/web.md @@ -2,9 +2,10 @@ KompKit Core provides small, framework-agnostic utilities for web applications written in TypeScript. -Status: `0.0.x-alpha`. +Status: `V0.2.0-alpha`. ## Installation + ```bash npm i @kompkit/core ``` @@ -12,11 +13,13 @@ npm i @kompkit/core ## Imports ESM: + ```ts import { debounce, isEmail, formatCurrency } from "@kompkit/core"; ``` CommonJS: + ```js const { debounce, isEmail, formatCurrency } = require("@kompkit/core"); ``` @@ -24,6 +27,7 @@ const { debounce, isEmail, formatCurrency } = require("@kompkit/core"); ## Usage examples ### debounce + ```ts import { debounce } from "@kompkit/core"; @@ -37,6 +41,7 @@ onType("kompkit"); // only this call will execute after ~300ms ``` ### isEmail + ```ts import { isEmail } from "@kompkit/core"; @@ -45,6 +50,7 @@ isEmail("invalid@"); // false ``` ### formatCurrency + ```ts import { formatCurrency } from "@kompkit/core"; @@ -53,6 +59,7 @@ formatCurrency(1234.56, "USD", "en-US"); // "$1,234.56" ``` ## React snippet + ```tsx import { useState } from "react"; import { debounce } from "@kompkit/core"; @@ -63,7 +70,10 @@ export function SearchBox() { return ( { setValue(e.target.value); run(e.target.value); }} + onChange={(e) => { + setValue(e.target.value); + run(e.target.value); + }} placeholder="Search" /> ); @@ -71,6 +81,7 @@ export function SearchBox() { ``` ## Vue snippet + ```vue