├── .editorconfig ├── .github └── workflows │ ├── publish.yml │ └── release.yml ├── .gitignore ├── LICENSE ├── README-CN.md ├── README.md ├── build.gradle.kts ├── gradle.properties ├── gradle ├── libs.versions.toml └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── kotlin-js-store └── yarn.lock ├── modules ├── viform-compose │ ├── build.gradle.kts │ ├── gradle.properties │ └── src │ │ ├── androidMain │ │ └── AndroidManifest.xml │ │ └── commonMain │ │ └── kotlin │ │ └── Composable.kt ├── viform-core │ ├── build.gradle.kts │ ├── gradle.properties │ └── src │ │ ├── androidMain │ │ └── AndroidManifest.xml │ │ └── commonMain │ │ └── kotlin │ │ └── io │ │ └── github.windedge.viform.core │ │ ├── FieldValidator.kt │ │ ├── Form.kt │ │ ├── FormField.kt │ │ ├── FormHost.kt │ │ ├── FormSchema.kt │ │ ├── String.kt │ │ ├── ValidateResult.kt │ │ ├── ValidatorContainer.kt │ │ └── ValidatorContainerExtension.kt └── viform-orbitmvi │ ├── build.gradle.kts │ ├── gradle.properties │ └── src │ └── commonMain │ └── kotlin │ └── FormContainerHost.kt ├── renovate.json ├── sandbox ├── build.gradle.kts ├── gradle.properties ├── gradle │ └── wrapper │ │ ├── gradle-wrapper.jar │ │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── kotlin-js-store │ └── yarn.lock ├── settings.gradle.kts └── signupapp │ ├── build.gradle.kts │ └── src │ ├── androidMain │ ├── AndroidManifest.xml │ ├── kotlin │ │ └── MainActivity.kt │ └── res │ │ ├── drawable-v24 │ │ └── ic_launcher_foreground.xml │ │ ├── drawable │ │ └── ic_launcher_background.xml │ │ ├── mipmap-anydpi-v26 │ │ ├── ic_launcher.xml │ │ └── ic_launcher_round.xml │ │ ├── mipmap-hdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-mdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-xhdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-xxhdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-xxxhdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ └── values │ │ └── strings.xml │ ├── commonMain │ └── kotlin │ │ ├── Signup.kt │ │ └── SignupApp.kt │ ├── desktopMain │ └── kotlin │ │ └── main.kt │ └── wasmJsMain │ ├── kotlin │ └── main.kt │ └── resources │ └── index.html └── settings.gradle.kts /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*.kt] 4 | indent_size = 4 5 | continuation_indent_size = 4 6 | ij_kotlin_name_count_to_use_star_import = unset 7 | disabled_rules = no-wildcard-imports 8 | 9 | [*.kts] 10 | indent_size = 2 11 | continuation_indent_size = 4 12 | ij_kotlin_name_count_to_use_star_import = unset 13 | disabled_rules = no-wildcard-imports 14 | -------------------------------------------------------------------------------- /.github/workflows/publish.yml: -------------------------------------------------------------------------------- 1 | name: Publish to Maven Central 2 | 3 | on: 4 | workflow_dispatch: # Allows manual triggering of the workflow 5 | release: 6 | types: [published] # Triggers when a new release is published 7 | 8 | jobs: 9 | publish: 10 | runs-on: macos-latest # Or ubuntu-latest, depending on your needs 11 | 12 | steps: 13 | - name: Checkout 14 | uses: actions/checkout@v4 # Use a newer version of the checkout action 15 | 16 | - name: Set up JDK 17 # Consistent with KopyBuilder; change if viform-multiplatform needs a different version 17 | uses: actions/setup-java@v4 18 | with: 19 | java-version: '17' # Consistent with KopyBuilder; change if viform-multiplatform needs a different version 20 | distribution: 'temurin' 21 | cache: gradle 22 | 23 | - name: Grant execute permission for gradlew 24 | run: chmod +x gradlew 25 | 26 | - name: Setup Gradle 27 | uses: gradle/actions/setup-gradle@v3 # Use the new Gradle action path 28 | 29 | - name: Import GPG key 30 | run: | 31 | # Create GPG directory 32 | mkdir -p ~/.gnupg/ 33 | chmod 700 ~/.gnupg/ 34 | 35 | # Set GPG agent and conf for loopback pinentry 36 | echo "allow-loopback-pinentry" >> ~/.gnupg/gpg-agent.conf 37 | echo "pinentry-mode loopback" >> ~/.gnupg/gpg.conf 38 | 39 | # Import key 40 | echo "${{ secrets.GPG_KEY_CONTENTS }}" | base64 --decode | gpg --batch --import 41 | gpg --list-secret-keys --keyid-format LONG 42 | env: 43 | GPG_KEY_CONTENTS: ${{ secrets.GPG_KEY_CONTENTS }} # Needs to be configured in GitHub secrets 44 | 45 | - name: Publish to Maven Central 46 | env: 47 | ORG_GRADLE_PROJECT_mavenCentralUsername: ${{ secrets.OSSRH_USERNAME }} 48 | ORG_GRADLE_PROJECT_mavenCentralPassword: ${{ secrets.OSSRH_PASSWORD }} 49 | ORG_GRADLE_PROJECT_signingInMemoryKey: ${{ secrets.GPG_KEY_CONTENTS }} 50 | ORG_GRADLE_PROJECT_signingInMemoryKeyId: ${{ secrets.SIGNING_KEY_ID }} 51 | ORG_GRADLE_PROJECT_signingInMemoryKeyPassword: ${{ secrets.SIGNING_PASSWORD }} 52 | # ORG_GRADLE_PROJECT_sonatypeStagingProfileId: ${{ secrets.SONATYPE_STAGING_PROFILE_ID }} 53 | run: | 54 | ./gradlew publishAllPublicationsToMavenCentral --no-daemon --no-parallel 55 | -------------------------------------------------------------------------------- /.github/workflows/release.yml: -------------------------------------------------------------------------------- 1 | name: Create Release 2 | 3 | on: 4 | push: 5 | tags: 6 | - 'v*' # Tags starting with 'v' will trigger this workflow 7 | 8 | jobs: 9 | release: 10 | runs-on: ubuntu-latest 11 | steps: 12 | - name: Checkout 13 | uses: actions/checkout@v3 14 | with: 15 | fetch-depth: 0 # Fetch full history to support version calculation 16 | 17 | - name: Get tag version 18 | id: get_version 19 | run: echo "VERSION=${GITHUB_REF#refs/tags/v}" >> $GITHUB_OUTPUT 20 | 21 | - name: Update version in gradle.properties 22 | run: | 23 | # Ensure we have the latest code 24 | git fetch origin 25 | git checkout main 26 | 27 | # Update version number 28 | sed -i "s/^version=.*/version=${{ steps.get_version.outputs.VERSION }}/" gradle.properties 29 | 30 | # Commit and push changes 31 | git config --local user.email "action@github.com" 32 | git config --local user.name "GitHub Action" 33 | # Update version in README.md and README-CN.md 34 | for file in README.md README-CN.md; do 35 | if [ -f "$file" ]; then 36 | sed -i "s/implementation(\"io.github.windedge.viform:viform-core:.*\")/implementation(\"io.github.windedge.viform:viform-core:${{ steps.get_version.outputs.VERSION }}\")/g" "$file" 37 | sed -i "s/implementation(\"io.github.windedge.viform:viform-compose:.*\")/implementation(\"io.github.windedge.viform:viform-compose:${{ steps.get_version.outputs.VERSION }}\")/g" "$file" 38 | fi 39 | done 40 | 41 | # Commit and push changes 42 | git add README.md README-CN.md 43 | git commit -m "Update version to ${{ steps.get_version.outputs.VERSION }}" -a || echo "No changes to commit" 44 | git push origin HEAD:main 45 | 46 | - name: Create GitHub Release 47 | uses: softprops/action-gh-release@v2 48 | with: 49 | name: Release ${{ steps.get_version.outputs.VERSION }} 50 | body: | 51 | Release version ${{ steps.get_version.outputs.VERSION }} 52 | draft: false 53 | prerelease: false 54 | env: 55 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 56 | # files: | # Optional: Attach build artifacts to the release 57 | # build/libs/*.jar 58 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .gradle/ 2 | .idea/ 3 | .vscode/ 4 | .kotlin/ 5 | build/ 6 | out/ 7 | dist/ 8 | local.properties 9 | lint.xml 10 | *.hprof 11 | *.out 12 | *.log 13 | *.bak.* 14 | *.cmd 15 | .aider.* 16 | .excludes.txt 17 | tasks.py 18 | fabfile.py 19 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018 windedge 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. -------------------------------------------------------------------------------- /README-CN.md: -------------------------------------------------------------------------------- 1 | # ViForm 2 | 3 | ViForm是一个用于表单验证的Kotlin库,主要目标是用在Compose Multiplatform项目,它具有下面几个特点: 4 | * 支持Kotlin多平台(android, jvm, js, wasmjs, ios) 5 | * 类型安全的验证规则,同时支持DSL风格和链式风格的验证规则写法 6 | * 表单状态管理 7 | * Compose Multiplatform的集成支持(android, desktop, wasmjs, ios) 8 | 9 | 10 | ## 前提条件 11 | - Kotlin Coroutine 12 | - KopyBuilder 13 | - Compose Multiplatform(可选) 14 | 15 | ## 安装 16 | 17 | 添加KopyBuilder的Gradle插件 18 | ```kotlin 19 | plugins { 20 | id("io.github.windedge.kopybuilder") version "0.2.4" 21 | } 22 | ``` 23 | 24 | 在Multiplatform项目添加依赖 25 | ```Kotlin 26 | kotlin { 27 | sourceSets { 28 | commonMain { 29 | dependencies { 30 | implementation("io.github.windedge.viform:viform-core:0.2.2") 31 | 32 | // 可选 33 | implementation("io.github.windedge.viform:viform-compose:0.2.2") 34 | } 35 | } 36 | } 37 | } 38 | ``` 39 | 40 | 在JVM项目添加依赖 41 | ```Kotlin 42 | dependencies { 43 | implementation("io.github.windedge.viform:viform-core:0.2.2") 44 | 45 | // 可选 46 | implementation("io.github.windedge.viform:viform-compose:0.2.2") 47 | } 48 | ``` 49 | 50 | ## 快速开始 51 | 52 | 定义验证规则: 53 | 54 | ```kotlin 55 | import io.github.windedge.copybuilder.KopyBuilder 56 | import io.github.windedge.viform.core.* 57 | 58 | 59 | @KopyBuilder 60 | data class Signup( 61 | val name: String = "", 62 | val email: String? = null, 63 | val password: String = "", 64 | val confirmPassword: String = "", 65 | ) 66 | 67 | 68 | val schema = FormSchema.create { 69 | field(Signup::name) { 70 | required("User name is required.") 71 | isAlphaNumeric() 72 | } 73 | 74 | field(Signup::email).optional { 75 | isEmail() 76 | } 77 | 78 | // 链式风格 79 | field(Signup::password).required().lengthBetween(8, 20) 80 | 81 | // 自定义规则 82 | field(Signup::confirmPassword).required().lengthBetween(8, 20) 83 | .custom("Passwords must be the same.") { 84 | it == field(Signup::password).currentValue 85 | } 86 | } 87 | ``` 88 | 89 | 在Jetpack Compose项目中使用: 90 | 91 | ```kotlin 92 | import io.github.windedge.viform.compose.use 93 | 94 | @Compose 95 | fun SignupApp() { 96 | val form = schema.buildForm(Signup()) 97 | Column { 98 | form.use() { 99 | field(it::name) { 100 | TextInput("User Name: ", currentValue, hasError, errorMessage, onValueChange = { 101 | setValue(it, validate = true) // 实时验证 102 | }) 103 | } 104 | 105 | field(it::email) { 106 | watchLazily { validate() } // 延迟验证 107 | TextInput("Email:", currentValue ?: "", hasError, errorMessage), onValueChange=::setValue) 108 | } 109 | 110 | field(it::password) { 111 | watchLazily { if (it.isNotEmpty()) validate() } 112 | TextInput("Password:", currentValue, hasError, errorMessage, onValueChange=::setValue) 113 | } 114 | 115 | field(it::confirmPassword) { 116 | watchLazily { if (it.isNotEmpty()) validate() } 117 | TextInput("Confirm Password:", currentValue, hasError, errorMessage, onValueChange=::setValue) 118 | } 119 | 120 | // 提交时验证 121 | Button(onClick = { 122 | if(form.validate()) { 123 | val data = form.pop() // 获取数据 124 | // ... 125 | } 126 | }) { Text("Sign up") } 127 | } 128 | } 129 | } 130 | ``` 131 | 132 | 133 | ## 已知问题 134 | 135 | 在编译 WebAssembly (WASM) 目标时,可能会遇到 `Can't link symbol kotlin.internal.ir/ANDAND` 错误。 136 | 137 | ## 许可证 138 | [MIT License](./LICENSE) 139 | 140 | ## 作者 141 | 142 | [Ken Xu](https://github.com/windedge) -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | English | [中文](README-CN.md) 2 | 3 | # ViForm 4 | 5 | ViForm is a Kotlin library for form validation, mainly aimed at Compose Multiplatform projects. It has the following features: 6 | * Supports Kotlin Multiplatform(android, jvm, js/wasmjs, ios) 7 | * Type-safe validation rules, supporting both DSL style and chained style validation declaration 8 | * Form state management 9 | * Integrated support for Compose Multiplatform(android, desktop, wasmjs, ios) 10 | 11 | 12 | ## Prerequisites 13 | - Kotlin Coroutine 14 | - KopyBuilder 15 | - Compose Multiplatform (optional) 16 | 17 | ## Installation 18 | 19 | Apply the KopyBuilder Gradle plugin 20 | ```kotlin 21 | plugins { 22 | id("io.github.windedge.kopybuilder") version "0.2.4" 23 | } 24 | ``` 25 | 26 | Add dependency to Multiplatform project 27 | ```Kotlin 28 | kotlin { 29 | sourceSets { 30 | commonMain { 31 | dependencies { 32 | implementation("io.github.windedge.viform:viform-core:0.2.2") 33 | 34 | // Optional 35 | implementation("io.github.windedge.viform:viform-compose:0.2.2") 36 | } 37 | } 38 | } 39 | } 40 | ``` 41 | 42 | Add dependency to JVM project 43 | ```Kotlin 44 | dependencies { 45 | implementation("io.github.windedge.viform:viform-core:0.2.2") 46 | 47 | // Optional 48 | implementation("io.github.windedge.viform:viform-compose:0.2.2") 49 | } 50 | ``` 51 | 52 | ## Quick Start 53 | 54 | Define validation rules: 55 | 56 | ```kotlin 57 | import io.github.windedge.copybuilder.KopyBuilder 58 | import io.github.windedge.viform.core.* 59 | 60 | 61 | @KopyBuilder 62 | data class Signup( 63 | val name: String = "", 64 | val email: String? = null, 65 | val password: String = "", 66 | val confirmPassword: String = "", 67 | ) 68 | 69 | 70 | val schema = FormSchema.create { 71 | field(Signup::name) { 72 | required("User name is required.") 73 | isAlphaNumeric() 74 | } 75 | 76 | field(Signup::email).optional { 77 | isEmail() 78 | } 79 | 80 | // Chain style 81 | field(Signup::password).required().lengthBetween(8, 20) 82 | 83 | // Custom rule 84 | field(Signup::confirmPassword).required().lengthBetween(8, 20) 85 | .custom("Passwords must be the same.") { 86 | it == field(Signup::password).currentValue 87 | } 88 | } 89 | ``` 90 | 91 | Use in Jetpack Compose project: 92 | 93 | ```kotlin 94 | import io.github.windedge.viform.compose.use 95 | 96 | @Compose 97 | fun SignupApp() { 98 | val form = schema.buildForm(Signup()) 99 | Column { 100 | form.use { 101 | field(it::name) { 102 | TextInput("User Name: ", currentValue, hasError, errorMessage, onValueChange = { 103 | setValue(it, validate = true) // validate synchronously 104 | }) 105 | } 106 | 107 | field(it::email) { 108 | watchLazily { validate() } // validate asynchronously 109 | TextInput("Email:", currentValue ?: "", hasError, errorMessage, onValueChange=::setValue) 110 | } 111 | 112 | field(it::password) { 113 | watchLazily { if (it.isNotEmpty()) validate() } 114 | TextInput("Password:", currentValue, hasError, errorMessage, onValueChange=::setValue) 115 | } 116 | 117 | field(it::confirmPassword) { 118 | watchLazily { if (it.isNotEmpty()) validate() } 119 | TextInput("Confirm Password:", currentValue, hasError, errorMessage, onValueChange=::setValue) 120 | } 121 | 122 | // validate on submit 123 | Button(onClick = { 124 | if(form.validate()) { 125 | val signup = form.pop() // get form data 126 | // ... 127 | } 128 | }) { Text("Sign up") } 129 | } 130 | } 131 | } 132 | ``` 133 | 134 | 135 | ## Known Issues 136 | 137 | When compiling the WebAssembly (WASM) target, you may encounter the error `Can't link symbol kotlin.internal.ir/ANDAND`. 138 | 139 | ## License 140 | [MIT License](./LICENSE) 141 | 142 | ## Author 143 | 144 | [Ken Xu](https://github.com/windedge) 145 | -------------------------------------------------------------------------------- /build.gradle.kts: -------------------------------------------------------------------------------- 1 | import com.android.build.api.dsl.LibraryExtension 2 | import org.jetbrains.kotlin.gradle.ExperimentalWasmDsl 3 | import org.jetbrains.kotlin.gradle.dsl.KotlinMultiplatformExtension 4 | import org.jetbrains.kotlin.gradle.plugin.KotlinBasePlugin 5 | 6 | plugins { 7 | alias(libs.plugins.kotlin.kmp) apply false 8 | alias(libs.plugins.android.library) apply false 9 | alias(libs.plugins.maven.publish) apply false 10 | alias(libs.plugins.compose) apply false 11 | alias(libs.plugins.kotlin.compose) apply false 12 | } 13 | 14 | 15 | repositories { 16 | mavenCentral() 17 | } 18 | 19 | subprojects { 20 | repositories { 21 | mavenCentral() 22 | google() 23 | mavenLocal() 24 | } 25 | 26 | plugins.withType { 27 | extensions.configure { 28 | jvmToolchain(17) 29 | 30 | jvm() 31 | 32 | plugins.withId("com.android.library") { 33 | androidTarget { 34 | publishLibraryVariants("release") 35 | } 36 | } 37 | 38 | iosArm64() 39 | iosX64() 40 | iosSimulatorArm64() 41 | } 42 | } 43 | 44 | afterEvaluate { 45 | plugins.withId("java") { 46 | extensions.configure { 47 | sourceCompatibility = JavaVersion.VERSION_17 48 | targetCompatibility = JavaVersion.VERSION_17 49 | } 50 | } 51 | 52 | extensions.findByType()?.apply { 53 | compileSdk = 35 54 | sourceSets["main"].manifest.srcFile("src/androidMain/AndroidManifest.xml") 55 | defaultConfig { 56 | minSdk = 21 57 | } 58 | compileOptions { 59 | this.sourceCompatibility = JavaVersion.VERSION_17 60 | this.targetCompatibility = JavaVersion.VERSION_17 61 | } 62 | namespace = "io.github.windedge.viform" 63 | } 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /gradle.properties: -------------------------------------------------------------------------------- 1 | #======================================== Gradle ======================================== 2 | org.gradle.project.sourceCompatibility=11 3 | org.gradle.project.targetCompatibility=11 4 | org.gradle.vfs.watch=true 5 | org.gradle.cache=true 6 | #org.gradle.parallel=true 7 | org.gradle.jvmargs=-XX:MaxMetaspaceSize=2g -Xmx2g 8 | 9 | #======================================== Kotlin ======================================== 10 | kotlin.style=official 11 | kotlin.stdlib.default.dependency=true 12 | kotlin.js.generate.externals=false 13 | kotlin.js.browser.karma.browsers=chromium-headless 14 | kotlin.incremental.js=true 15 | kotlin.mpp.stability.nowarn=true 16 | 17 | kotlin.wasm.js.generate.types=true 18 | kotlin.wasm.js.ir.memoryModel=unlimited 19 | kotlin.wasm.js.ir.optimize=true 20 | kotlin.incremental.wasm=false 21 | kotlin.native.ignoreDisabledTargets=true 22 | kotlin.mpp.androidSourceSetLayoutVersion=2 23 | # https://youtrack.jetbrains.com/issue/KT-51293/Unresolved-references-with-hierarchical-project-structure-when-building-KotlinMetadata-from-native-common-source-set#focus=Comments-27-6220848.0-0 24 | kotlin.mpp.import.enableKgpDependencyResolution=true 25 | 26 | kotlin.mpp.androidSourceSetLayoutV2AndroidStyleDirs.nowarn=true 27 | 28 | # Makes sure we can debug our Kotlin plugin with breakpoints 29 | kotlin.compiler.execution.strategy=in-process 30 | #======================================== Android ======================================= 31 | android.useAndroidX=true 32 | android.enableJetifier=true 33 | 34 | #======================================= Project ======================================== 35 | group=io.github.windedge.viform 36 | version=0.2.2 37 | 38 | #======================================= Maven Publish ================================= 39 | SONATYPE_HOST=S01 40 | RELEASE_SIGNING_ENABLED=true 41 | SONATYPE_AUTOMATIC_RELEASE=true 42 | 43 | POM_DESCRIPTION=A kotlin multiplatform form validation library, primarily used for jetpack compose and orbit-mvi 44 | POM_URL=https://github.com/windedge/viform-multiplatform 45 | 46 | POM_LICENSE_NAME=MIT License 47 | POM_LICENSE_URL=https://github.com/windedge/viform-multiplatform/blob/main/LICENSE 48 | POM_LICENSE_DIST=repo 49 | 50 | POM_SCM_URL=https://github.com/windedge/viform-multiplatform/tree/main 51 | POM_SCM_CONNECTION=scm:git:github.com/windedge/viform-multiplatform.git 52 | POM_SCM_DEV_CONNECTION=scm:git:ssh://github.com/windedge/viform-multiplatform.git 53 | 54 | POM_DEVELOPER_ID=windedge 55 | POM_DEVELOPER_NAME=xujl 56 | POM_DEVELOPER_EMAIL=windedge99@gmail.com 57 | -------------------------------------------------------------------------------- /gradle/libs.versions.toml: -------------------------------------------------------------------------------- 1 | [versions] 2 | viform = "0.0.0" 3 | 4 | kotlin = "2.1.21" 5 | agp = "8.2.0" 6 | java = "17" 7 | compose = "1.8.0" 8 | androidx-activity-compose = "1.9.3" 9 | kotlinx-coroutines = "1.9.0" 10 | kotlinx-serilization = "1.7.3" 11 | orbitmvi = "6.1.0" 12 | kotlinpoet = "1.12.0" 13 | ksp = "2.1.0-1.0.29" 14 | kopybuilder = "0.2.4" 15 | maven-publish = "0.25.2" 16 | 17 | 18 | [libraries] 19 | kotlinx-coroutines-core = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-core", version.ref = "kotlinx-coroutines" } 20 | kotlinx-coroutines-test = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-test", version.ref = "kotlinx-coroutines" } 21 | kotlinx-serilization-json = { module = "org.jetbrains.kotlinx:kotlinx-serialization-json", version.ref = "kotlinx-serilization" } 22 | orbitmvi-core = { module = "org.orbit-mvi:orbit-core", version.ref = "orbitmvi" } 23 | ksp = { module = "com.google.devtools.ksp:symbol-processing-api", version.ref = "ksp" } 24 | kotlinpoet-ksp = { module = "com.squareup:kotlinpoet-ksp", version.ref = "kotlinpoet" } 25 | kopybuilder-runtime = { module = "io.github.windedge.copybuilder:copybuilder-runtime", version.ref = "kopybuilder" } 26 | 27 | viform-core = { module = "io.github.windedge.viform:viform-core", version.ref = "viform" } 28 | viform-compose = { module = "io.github.windedge.viform:viform-compose", version.ref = "viform" } 29 | 30 | androidx-activity-compose = { module = "androidx.activity:activity-compose", version.ref = "androidx-activity-compose" } 31 | 32 | 33 | [plugins] 34 | maven-publish = { id = "com.vanniktech.maven.publish", version.ref = "maven-publish" } 35 | android-application = { id = "com.android.application", version.ref = "agp" } 36 | android-library = { id = "com.android.library", version.ref = "agp" } 37 | compose = { id = "org.jetbrains.compose", version.ref = "compose" } 38 | kotlin-kmp = { id = "org.jetbrains.kotlin.multiplatform", version.ref = "kotlin" } 39 | kotlin-compose = { id = "org.jetbrains.kotlin.plugin.compose", version.ref = "kotlin" } 40 | kopybuilder = { id = "io.github.windedge.kopybuilder", version.ref = "kopybuilder" } 41 | -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/windedge/viform-multiplatform/d721ad2d3281c1ed16d49639e965f5ff3d2dfb98/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionBase=GRADLE_USER_HOME 2 | distributionPath=wrapper/dists 3 | distributionUrl=https\://services.gradle.org/distributions/gradle-8.5-bin.zip 4 | networkTimeout=10000 5 | validateDistributionUrl=true 6 | zipStoreBase=GRADLE_USER_HOME 7 | zipStorePath=wrapper/dists 8 | -------------------------------------------------------------------------------- /gradlew: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # 4 | # Copyright © 2015-2021 the original authors. 5 | # 6 | # Licensed under the Apache License, Version 2.0 (the "License"); 7 | # you may not use this file except in compliance with the License. 8 | # You may obtain a copy of the License at 9 | # 10 | # https://www.apache.org/licenses/LICENSE-2.0 11 | # 12 | # Unless required by applicable law or agreed to in writing, software 13 | # distributed under the License is distributed on an "AS IS" BASIS, 14 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | # See the License for the specific language governing permissions and 16 | # limitations under the License. 17 | # 18 | 19 | ############################################################################## 20 | # 21 | # Gradle start up script for POSIX generated by Gradle. 22 | # 23 | # Important for running: 24 | # 25 | # (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is 26 | # noncompliant, but you have some other compliant shell such as ksh or 27 | # bash, then to run this script, type that shell name before the whole 28 | # command line, like: 29 | # 30 | # ksh Gradle 31 | # 32 | # Busybox and similar reduced shells will NOT work, because this script 33 | # requires all of these POSIX shell features: 34 | # * functions; 35 | # * expansions «$var», «${var}», «${var:-default}», «${var+SET}», 36 | # «${var#prefix}», «${var%suffix}», and «$( cmd )»; 37 | # * compound commands having a testable exit status, especially «case»; 38 | # * various built-in commands including «command», «set», and «ulimit». 39 | # 40 | # Important for patching: 41 | # 42 | # (2) This script targets any POSIX shell, so it avoids extensions provided 43 | # by Bash, Ksh, etc; in particular arrays are avoided. 44 | # 45 | # The "traditional" practice of packing multiple parameters into a 46 | # space-separated string is a well documented source of bugs and security 47 | # problems, so this is (mostly) avoided, by progressively accumulating 48 | # options in "$@", and eventually passing that to Java. 49 | # 50 | # Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS, 51 | # and GRADLE_OPTS) rely on word-splitting, this is performed explicitly; 52 | # see the in-line comments for details. 53 | # 54 | # There are tweaks for specific operating systems such as AIX, CygWin, 55 | # Darwin, MinGW, and NonStop. 56 | # 57 | # (3) This script is generated from the Groovy template 58 | # https://github.com/gradle/gradle/blob/HEAD/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt 59 | # within the Gradle project. 60 | # 61 | # You can find Gradle at https://github.com/gradle/gradle/. 62 | # 63 | ############################################################################## 64 | 65 | # Attempt to set APP_HOME 66 | 67 | # Resolve links: $0 may be a link 68 | app_path=$0 69 | 70 | # Need this for daisy-chained symlinks. 71 | while 72 | APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path 73 | [ -h "$app_path" ] 74 | do 75 | ls=$( ls -ld "$app_path" ) 76 | link=${ls#*' -> '} 77 | case $link in #( 78 | /*) app_path=$link ;; #( 79 | *) app_path=$APP_HOME$link ;; 80 | esac 81 | done 82 | 83 | # This is normally unused 84 | # shellcheck disable=SC2034 85 | APP_BASE_NAME=${0##*/} 86 | # Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036) 87 | APP_HOME=$( cd "${APP_HOME:-./}" > /dev/null && pwd -P ) || exit 88 | 89 | # Use the maximum available, or set MAX_FD != -1 to use that value. 90 | MAX_FD=maximum 91 | 92 | warn () { 93 | echo "$*" 94 | } >&2 95 | 96 | die () { 97 | echo 98 | echo "$*" 99 | echo 100 | exit 1 101 | } >&2 102 | 103 | # OS specific support (must be 'true' or 'false'). 104 | cygwin=false 105 | msys=false 106 | darwin=false 107 | nonstop=false 108 | case "$( uname )" in #( 109 | CYGWIN* ) cygwin=true ;; #( 110 | Darwin* ) darwin=true ;; #( 111 | MSYS* | MINGW* ) msys=true ;; #( 112 | NONSTOP* ) nonstop=true ;; 113 | esac 114 | 115 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar 116 | 117 | 118 | # Determine the Java command to use to start the JVM. 119 | if [ -n "$JAVA_HOME" ] ; then 120 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then 121 | # IBM's JDK on AIX uses strange locations for the executables 122 | JAVACMD=$JAVA_HOME/jre/sh/java 123 | else 124 | JAVACMD=$JAVA_HOME/bin/java 125 | fi 126 | if [ ! -x "$JAVACMD" ] ; then 127 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME 128 | 129 | Please set the JAVA_HOME variable in your environment to match the 130 | location of your Java installation." 131 | fi 132 | else 133 | JAVACMD=java 134 | if ! command -v java >/dev/null 2>&1 135 | then 136 | die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 137 | 138 | Please set the JAVA_HOME variable in your environment to match the 139 | location of your Java installation." 140 | fi 141 | fi 142 | 143 | # Increase the maximum file descriptors if we can. 144 | if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then 145 | case $MAX_FD in #( 146 | max*) 147 | # In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked. 148 | # shellcheck disable=SC2039,SC3045 149 | MAX_FD=$( ulimit -H -n ) || 150 | warn "Could not query maximum file descriptor limit" 151 | esac 152 | case $MAX_FD in #( 153 | '' | soft) :;; #( 154 | *) 155 | # In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked. 156 | # shellcheck disable=SC2039,SC3045 157 | ulimit -n "$MAX_FD" || 158 | warn "Could not set maximum file descriptor limit to $MAX_FD" 159 | esac 160 | fi 161 | 162 | # Collect all arguments for the java command, stacking in reverse order: 163 | # * args from the command line 164 | # * the main class name 165 | # * -classpath 166 | # * -D...appname settings 167 | # * --module-path (only if needed) 168 | # * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables. 169 | 170 | # For Cygwin or MSYS, switch paths to Windows format before running java 171 | if "$cygwin" || "$msys" ; then 172 | APP_HOME=$( cygpath --path --mixed "$APP_HOME" ) 173 | CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" ) 174 | 175 | JAVACMD=$( cygpath --unix "$JAVACMD" ) 176 | 177 | # Now convert the arguments - kludge to limit ourselves to /bin/sh 178 | for arg do 179 | if 180 | case $arg in #( 181 | -*) false ;; # don't mess with options #( 182 | /?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath 183 | [ -e "$t" ] ;; #( 184 | *) false ;; 185 | esac 186 | then 187 | arg=$( cygpath --path --ignore --mixed "$arg" ) 188 | fi 189 | # Roll the args list around exactly as many times as the number of 190 | # args, so each arg winds up back in the position where it started, but 191 | # possibly modified. 192 | # 193 | # NB: a `for` loop captures its iteration list before it begins, so 194 | # changing the positional parameters here affects neither the number of 195 | # iterations, nor the values presented in `arg`. 196 | shift # remove old arg 197 | set -- "$@" "$arg" # push replacement arg 198 | done 199 | fi 200 | 201 | 202 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 203 | DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' 204 | 205 | # Collect all arguments for the java command: 206 | # * DEFAULT_JVM_OPTS, JAVA_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments, 207 | # and any embedded shellness will be escaped. 208 | # * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be 209 | # treated as '${Hostname}' itself on the command line. 210 | 211 | set -- \ 212 | "-Dorg.gradle.appname=$APP_BASE_NAME" \ 213 | -classpath "$CLASSPATH" \ 214 | org.gradle.wrapper.GradleWrapperMain \ 215 | "$@" 216 | 217 | # Stop when "xargs" is not available. 218 | if ! command -v xargs >/dev/null 2>&1 219 | then 220 | die "xargs is not available" 221 | fi 222 | 223 | # Use "xargs" to parse quoted args. 224 | # 225 | # With -n1 it outputs one arg per line, with the quotes and backslashes removed. 226 | # 227 | # In Bash we could simply go: 228 | # 229 | # readarray ARGS < <( xargs -n1 <<<"$var" ) && 230 | # set -- "${ARGS[@]}" "$@" 231 | # 232 | # but POSIX shell has neither arrays nor command substitution, so instead we 233 | # post-process each arg (as a line of input to sed) to backslash-escape any 234 | # character that might be a shell metacharacter, then use eval to reverse 235 | # that process (while maintaining the separation between arguments), and wrap 236 | # the whole thing up as a single "set" statement. 237 | # 238 | # This will of course break if any of these variables contains a newline or 239 | # an unmatched quote. 240 | # 241 | 242 | eval "set -- $( 243 | printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" | 244 | xargs -n1 | 245 | sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' | 246 | tr '\n' ' ' 247 | )" '"$@"' 248 | 249 | exec "$JAVACMD" "$@" 250 | -------------------------------------------------------------------------------- /gradlew.bat: -------------------------------------------------------------------------------- 1 | @rem 2 | @rem Copyright 2015 the original author or authors. 3 | @rem 4 | @rem Licensed under the Apache License, Version 2.0 (the "License"); 5 | @rem you may not use this file except in compliance with the License. 6 | @rem You may obtain a copy of the License at 7 | @rem 8 | @rem https://www.apache.org/licenses/LICENSE-2.0 9 | @rem 10 | @rem Unless required by applicable law or agreed to in writing, software 11 | @rem distributed under the License is distributed on an "AS IS" BASIS, 12 | @rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | @rem See the License for the specific language governing permissions and 14 | @rem limitations under the License. 15 | @rem 16 | 17 | @if "%DEBUG%"=="" @echo off 18 | @rem ########################################################################## 19 | @rem 20 | @rem Gradle startup script for Windows 21 | @rem 22 | @rem ########################################################################## 23 | 24 | @rem Set local scope for the variables with windows NT shell 25 | if "%OS%"=="Windows_NT" setlocal 26 | 27 | set DIRNAME=%~dp0 28 | if "%DIRNAME%"=="" set DIRNAME=. 29 | @rem This is normally unused 30 | set APP_BASE_NAME=%~n0 31 | set APP_HOME=%DIRNAME% 32 | 33 | @rem Resolve any "." and ".." in APP_HOME to make it shorter. 34 | for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi 35 | 36 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 37 | set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" 38 | 39 | @rem Find java.exe 40 | if defined JAVA_HOME goto findJavaFromJavaHome 41 | 42 | set JAVA_EXE=java.exe 43 | %JAVA_EXE% -version >NUL 2>&1 44 | if %ERRORLEVEL% equ 0 goto execute 45 | 46 | echo. 47 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 48 | echo. 49 | echo Please set the JAVA_HOME variable in your environment to match the 50 | echo location of your Java installation. 51 | 52 | goto fail 53 | 54 | :findJavaFromJavaHome 55 | set JAVA_HOME=%JAVA_HOME:"=% 56 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 57 | 58 | if exist "%JAVA_EXE%" goto execute 59 | 60 | echo. 61 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 62 | echo. 63 | echo Please set the JAVA_HOME variable in your environment to match the 64 | echo location of your Java installation. 65 | 66 | goto fail 67 | 68 | :execute 69 | @rem Setup the command line 70 | 71 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 72 | 73 | 74 | @rem Execute Gradle 75 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* 76 | 77 | :end 78 | @rem End local scope for the variables with windows NT shell 79 | if %ERRORLEVEL% equ 0 goto mainEnd 80 | 81 | :fail 82 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 83 | rem the _cmd.exe /c_ return code! 84 | set EXIT_CODE=%ERRORLEVEL% 85 | if %EXIT_CODE% equ 0 set EXIT_CODE=1 86 | if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE% 87 | exit /b %EXIT_CODE% 88 | 89 | :mainEnd 90 | if "%OS%"=="Windows_NT" endlocal 91 | 92 | :omega 93 | -------------------------------------------------------------------------------- /kotlin-js-store/yarn.lock: -------------------------------------------------------------------------------- 1 | # THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. 2 | # yarn lockfile v1 3 | 4 | 5 | "@colors/colors@1.5.0": 6 | version "1.5.0" 7 | resolved "https://registry.npmmirror.com/@colors/colors/-/colors-1.5.0.tgz#bb504579c1cae923e6576a4f5da43d25f97bdbd9" 8 | integrity sha512-ooWCrlZP11i8GImSjTHYHLkvFDP48nS4+204nGb1RiX/WXYHmJA2III9/e2DWVabCESdW7hBAEzHRqUn9OUVvQ== 9 | 10 | "@discoveryjs/json-ext@^0.5.0": 11 | version "0.5.7" 12 | resolved "https://registry.npmmirror.com/@discoveryjs/json-ext/-/json-ext-0.5.7.tgz#1d572bfbbe14b7704e0ba0f39b74815b84870d70" 13 | integrity sha512-dBVuXR082gk3jsFp7Rd/JI4kytwGHecnCoTtXFb7DB6CNHp4rg5k1bhg0nWdLGLnOV71lmDzGQaLMy8iPLY0pw== 14 | 15 | "@jridgewell/gen-mapping@^0.3.0": 16 | version "0.3.3" 17 | resolved "https://registry.yarnpkg.com/@jridgewell/gen-mapping/-/gen-mapping-0.3.3.tgz#7e02e6eb5df901aaedb08514203b096614024098" 18 | integrity sha512-HLhSWOLRi875zjjMG/r+Nv0oCW8umGb0BgEhyX3dDX3egwZtB8PqLnjz3yedt8R5StBrzcg4aBpnh8UA9D1BoQ== 19 | dependencies: 20 | "@jridgewell/set-array" "^1.0.1" 21 | "@jridgewell/sourcemap-codec" "^1.4.10" 22 | "@jridgewell/trace-mapping" "^0.3.9" 23 | 24 | "@jridgewell/resolve-uri@3.1.0": 25 | version "3.1.0" 26 | resolved "https://registry.yarnpkg.com/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz#2203b118c157721addfe69d47b70465463066d78" 27 | integrity sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w== 28 | 29 | "@jridgewell/resolve-uri@^3.1.0": 30 | version "3.1.1" 31 | resolved "https://registry.npmmirror.com/@jridgewell/resolve-uri/-/resolve-uri-3.1.1.tgz#c08679063f279615a3326583ba3a90d1d82cc721" 32 | integrity sha512-dSYZh7HhCDtCKm4QakX0xFpsRDqjjtZf/kjI/v3T3Nwt5r8/qz/M19F9ySyOqU94SXBmeG9ttTul+YnR4LOxFA== 33 | 34 | "@jridgewell/set-array@^1.0.1": 35 | version "1.1.2" 36 | resolved "https://registry.yarnpkg.com/@jridgewell/set-array/-/set-array-1.1.2.tgz#7c6cf998d6d20b914c0a55a91ae928ff25965e72" 37 | integrity sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw== 38 | 39 | "@jridgewell/source-map@^0.3.3": 40 | version "0.3.5" 41 | resolved "https://registry.npmmirror.com/@jridgewell/source-map/-/source-map-0.3.5.tgz#a3bb4d5c6825aab0d281268f47f6ad5853431e91" 42 | integrity sha512-UTYAUj/wviwdsMfzoSJspJxbkH5o1snzwX0//0ENX1u/55kkZZkcTZP6u9bwKGkv+dkk9at4m1Cpt0uY80kcpQ== 43 | dependencies: 44 | "@jridgewell/gen-mapping" "^0.3.0" 45 | "@jridgewell/trace-mapping" "^0.3.9" 46 | 47 | "@jridgewell/sourcemap-codec@1.4.14": 48 | version "1.4.14" 49 | resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz#add4c98d341472a289190b424efbdb096991bb24" 50 | integrity sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw== 51 | 52 | "@jridgewell/sourcemap-codec@^1.4.10", "@jridgewell/sourcemap-codec@^1.4.14": 53 | version "1.4.15" 54 | resolved "https://registry.npmmirror.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz#d7c6e6755c78567a951e04ab52ef0fd26de59f32" 55 | integrity sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg== 56 | 57 | "@jridgewell/trace-mapping@^0.3.17": 58 | version "0.3.20" 59 | resolved "https://registry.npmmirror.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.20.tgz#72e45707cf240fa6b081d0366f8265b0cd10197f" 60 | integrity sha512-R8LcPeWZol2zR8mmH3JeKQ6QRCFb7XgUhV9ZlGhHLGyg4wpPiPZNQOOWhFZhxKw8u//yTbNGI42Bx/3paXEQ+Q== 61 | dependencies: 62 | "@jridgewell/resolve-uri" "^3.1.0" 63 | "@jridgewell/sourcemap-codec" "^1.4.14" 64 | 65 | "@jridgewell/trace-mapping@^0.3.9": 66 | version "0.3.18" 67 | resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.18.tgz#25783b2086daf6ff1dcb53c9249ae480e4dd4cd6" 68 | integrity sha512-w+niJYzMHdd7USdiH2U6869nqhD2nbfZXND5Yp93qIbEmnDNk7PD48o+YchRVpzMU7M6jVCbenTR7PA1FLQ9pA== 69 | dependencies: 70 | "@jridgewell/resolve-uri" "3.1.0" 71 | "@jridgewell/sourcemap-codec" "1.4.14" 72 | 73 | "@socket.io/component-emitter@~3.1.0": 74 | version "3.1.0" 75 | resolved "https://registry.npmmirror.com/@socket.io/component-emitter/-/component-emitter-3.1.0.tgz#96116f2a912e0c02817345b3c10751069920d553" 76 | integrity sha512-+9jVqKhRSpsc591z5vX+X5Yyw+he/HCB4iQ/RYxw35CEPaY1gnsNE43nf9n9AaYjAQrTiI/mOwKUKdUs9vf7Xg== 77 | 78 | "@types/cookie@^0.4.1": 79 | version "0.4.1" 80 | resolved "https://registry.npmmirror.com/@types/cookie/-/cookie-0.4.1.tgz#bfd02c1f2224567676c1545199f87c3a861d878d" 81 | integrity sha512-XW/Aa8APYr6jSVVA1y/DEIZX0/GMKLEVekNG727R8cs56ahETkRAy/3DR7+fJyh7oUgGwNQaRfXCun0+KbWY7Q== 82 | 83 | "@types/cors@^2.8.12": 84 | version "2.8.17" 85 | resolved "https://registry.npmmirror.com/@types/cors/-/cors-2.8.17.tgz#5d718a5e494a8166f569d986794e49c48b216b2b" 86 | integrity sha512-8CGDvrBj1zgo2qE+oS3pOCyYNqCPryMWY2bGfwA0dcfopWGgxs+78df0Rs3rc9THP4JkOhLsAa+15VdpAqkcUA== 87 | dependencies: 88 | "@types/node" "*" 89 | 90 | "@types/eslint-scope@^3.7.3": 91 | version "3.7.7" 92 | resolved "https://registry.npmmirror.com/@types/eslint-scope/-/eslint-scope-3.7.7.tgz#3108bd5f18b0cdb277c867b3dd449c9ed7079ac5" 93 | integrity sha512-MzMFlSLBqNF2gcHWO0G1vP/YQyfvrxZ0bF+u7mzUdZ1/xK4A4sru+nraZz5i3iEIk1l1uyicaDVTB4QbbEkAYg== 94 | dependencies: 95 | "@types/eslint" "*" 96 | "@types/estree" "*" 97 | 98 | "@types/eslint@*": 99 | version "8.56.0" 100 | resolved "https://registry.npmmirror.com/@types/eslint/-/eslint-8.56.0.tgz#e28d045b8e530a33c9cbcfbf02332df0d1380a2c" 101 | integrity sha512-FlsN0p4FhuYRjIxpbdXovvHQhtlG05O1GG/RNWvdAxTboR438IOTwmrY/vLA+Xfgg06BTkP045M3vpFwTMv1dg== 102 | dependencies: 103 | "@types/estree" "*" 104 | "@types/json-schema" "*" 105 | 106 | "@types/estree@*": 107 | version "1.0.1" 108 | resolved "https://registry.yarnpkg.com/@types/estree/-/estree-1.0.1.tgz#aa22750962f3bf0e79d753d3cc067f010c95f194" 109 | integrity sha512-LG4opVs2ANWZ1TJoKc937iMmNstM/d0ae1vNbnBvBhqCSezgVUOzcLCqbI5elV8Vy6WKwKjaqR+zO9VKirBBCA== 110 | 111 | "@types/estree@^1.0.0": 112 | version "1.0.5" 113 | resolved "https://registry.npmmirror.com/@types/estree/-/estree-1.0.5.tgz#a6ce3e556e00fd9895dd872dd172ad0d4bd687f4" 114 | integrity sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw== 115 | 116 | "@types/json-schema@*", "@types/json-schema@^7.0.8": 117 | version "7.0.15" 118 | resolved "https://registry.npmmirror.com/@types/json-schema/-/json-schema-7.0.15.tgz#596a1747233694d50f6ad8a7869fcb6f56cf5841" 119 | integrity sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA== 120 | 121 | "@types/node@*": 122 | version "18.16.3" 123 | resolved "https://registry.yarnpkg.com/@types/node/-/node-18.16.3.tgz#6bda7819aae6ea0b386ebc5b24bdf602f1b42b01" 124 | integrity sha512-OPs5WnnT1xkCBiuQrZA4+YAV4HEJejmHneyraIaxsbev5yCEr6KMwINNFP9wQeFIw8FWcoTqF3vQsa5CDaI+8Q== 125 | 126 | "@types/node@>=10.0.0": 127 | version "20.10.5" 128 | resolved "https://registry.npmmirror.com/@types/node/-/node-20.10.5.tgz#47ad460b514096b7ed63a1dae26fad0914ed3ab2" 129 | integrity sha512-nNPsNE65wjMxEKI93yOP+NPGGBJz/PoN3kZsVLee0XMiJolxSekEVD8wRwBUBqkwc7UWop0edW50yrCQW4CyRw== 130 | dependencies: 131 | undici-types "~5.26.4" 132 | 133 | "@webassemblyjs/ast@1.11.6", "@webassemblyjs/ast@^1.11.5": 134 | version "1.11.6" 135 | resolved "https://registry.npmmirror.com/@webassemblyjs/ast/-/ast-1.11.6.tgz#db046555d3c413f8966ca50a95176a0e2c642e24" 136 | integrity sha512-IN1xI7PwOvLPgjcf180gC1bqn3q/QaOCwYUahIOhbYUu8KA/3tw2RT/T0Gidi1l7Hhj5D/INhJxiICObqpMu4Q== 137 | dependencies: 138 | "@webassemblyjs/helper-numbers" "1.11.6" 139 | "@webassemblyjs/helper-wasm-bytecode" "1.11.6" 140 | 141 | "@webassemblyjs/floating-point-hex-parser@1.11.6": 142 | version "1.11.6" 143 | resolved "https://registry.npmmirror.com/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.11.6.tgz#dacbcb95aff135c8260f77fa3b4c5fea600a6431" 144 | integrity sha512-ejAj9hfRJ2XMsNHk/v6Fu2dGS+i4UaXBXGemOfQ/JfQ6mdQg/WXtwleQRLLS4OvfDhv8rYnVwH27YJLMyYsxhw== 145 | 146 | "@webassemblyjs/helper-api-error@1.11.6": 147 | version "1.11.6" 148 | resolved "https://registry.npmmirror.com/@webassemblyjs/helper-api-error/-/helper-api-error-1.11.6.tgz#6132f68c4acd59dcd141c44b18cbebbd9f2fa768" 149 | integrity sha512-o0YkoP4pVu4rN8aTJgAyj9hC2Sv5UlkzCHhxqWj8butaLvnpdc2jOwh4ewE6CX0txSfLn/UYaV/pheS2Txg//Q== 150 | 151 | "@webassemblyjs/helper-buffer@1.11.6": 152 | version "1.11.6" 153 | resolved "https://registry.npmmirror.com/@webassemblyjs/helper-buffer/-/helper-buffer-1.11.6.tgz#b66d73c43e296fd5e88006f18524feb0f2c7c093" 154 | integrity sha512-z3nFzdcp1mb8nEOFFk8DrYLpHvhKC3grJD2ardfKOzmbmJvEf/tPIqCY+sNcwZIY8ZD7IkB2l7/pqhUhqm7hLA== 155 | 156 | "@webassemblyjs/helper-numbers@1.11.6": 157 | version "1.11.6" 158 | resolved "https://registry.npmmirror.com/@webassemblyjs/helper-numbers/-/helper-numbers-1.11.6.tgz#cbce5e7e0c1bd32cf4905ae444ef64cea919f1b5" 159 | integrity sha512-vUIhZ8LZoIWHBohiEObxVm6hwP034jwmc9kuq5GdHZH0wiLVLIPcMCdpJzG4C11cHoQ25TFIQj9kaVADVX7N3g== 160 | dependencies: 161 | "@webassemblyjs/floating-point-hex-parser" "1.11.6" 162 | "@webassemblyjs/helper-api-error" "1.11.6" 163 | "@xtuc/long" "4.2.2" 164 | 165 | "@webassemblyjs/helper-wasm-bytecode@1.11.6": 166 | version "1.11.6" 167 | resolved "https://registry.npmmirror.com/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.11.6.tgz#bb2ebdb3b83aa26d9baad4c46d4315283acd51e9" 168 | integrity sha512-sFFHKwcmBprO9e7Icf0+gddyWYDViL8bpPjJJl0WHxCdETktXdmtWLGVzoHbqUcY4Be1LkNfwTmXOJUFZYSJdA== 169 | 170 | "@webassemblyjs/helper-wasm-section@1.11.6": 171 | version "1.11.6" 172 | resolved "https://registry.npmmirror.com/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.11.6.tgz#ff97f3863c55ee7f580fd5c41a381e9def4aa577" 173 | integrity sha512-LPpZbSOwTpEC2cgn4hTydySy1Ke+XEu+ETXuoyvuyezHO3Kjdu90KK95Sh9xTbmjrCsUwvWwCOQQNta37VrS9g== 174 | dependencies: 175 | "@webassemblyjs/ast" "1.11.6" 176 | "@webassemblyjs/helper-buffer" "1.11.6" 177 | "@webassemblyjs/helper-wasm-bytecode" "1.11.6" 178 | "@webassemblyjs/wasm-gen" "1.11.6" 179 | 180 | "@webassemblyjs/ieee754@1.11.6": 181 | version "1.11.6" 182 | resolved "https://registry.npmmirror.com/@webassemblyjs/ieee754/-/ieee754-1.11.6.tgz#bb665c91d0b14fffceb0e38298c329af043c6e3a" 183 | integrity sha512-LM4p2csPNvbij6U1f19v6WR56QZ8JcHg3QIJTlSwzFcmx6WSORicYj6I63f9yU1kEUtrpG+kjkiIAkevHpDXrg== 184 | dependencies: 185 | "@xtuc/ieee754" "^1.2.0" 186 | 187 | "@webassemblyjs/leb128@1.11.6": 188 | version "1.11.6" 189 | resolved "https://registry.npmmirror.com/@webassemblyjs/leb128/-/leb128-1.11.6.tgz#70e60e5e82f9ac81118bc25381a0b283893240d7" 190 | integrity sha512-m7a0FhE67DQXgouf1tbN5XQcdWoNgaAuoULHIfGFIEVKA6tu/edls6XnIlkmS6FrXAquJRPni3ZZKjw6FSPjPQ== 191 | dependencies: 192 | "@xtuc/long" "4.2.2" 193 | 194 | "@webassemblyjs/utf8@1.11.6": 195 | version "1.11.6" 196 | resolved "https://registry.npmmirror.com/@webassemblyjs/utf8/-/utf8-1.11.6.tgz#90f8bc34c561595fe156603be7253cdbcd0fab5a" 197 | integrity sha512-vtXf2wTQ3+up9Zsg8sa2yWiQpzSsMyXj0qViVP6xKGCUT8p8YJ6HqI7l5eCnWx1T/FYdsv07HQs2wTFbbof/RA== 198 | 199 | "@webassemblyjs/wasm-edit@^1.11.5": 200 | version "1.11.6" 201 | resolved "https://registry.npmmirror.com/@webassemblyjs/wasm-edit/-/wasm-edit-1.11.6.tgz#c72fa8220524c9b416249f3d94c2958dfe70ceab" 202 | integrity sha512-Ybn2I6fnfIGuCR+Faaz7YcvtBKxvoLV3Lebn1tM4o/IAJzmi9AWYIPWpyBfU8cC+JxAO57bk4+zdsTjJR+VTOw== 203 | dependencies: 204 | "@webassemblyjs/ast" "1.11.6" 205 | "@webassemblyjs/helper-buffer" "1.11.6" 206 | "@webassemblyjs/helper-wasm-bytecode" "1.11.6" 207 | "@webassemblyjs/helper-wasm-section" "1.11.6" 208 | "@webassemblyjs/wasm-gen" "1.11.6" 209 | "@webassemblyjs/wasm-opt" "1.11.6" 210 | "@webassemblyjs/wasm-parser" "1.11.6" 211 | "@webassemblyjs/wast-printer" "1.11.6" 212 | 213 | "@webassemblyjs/wasm-gen@1.11.6": 214 | version "1.11.6" 215 | resolved "https://registry.npmmirror.com/@webassemblyjs/wasm-gen/-/wasm-gen-1.11.6.tgz#fb5283e0e8b4551cc4e9c3c0d7184a65faf7c268" 216 | integrity sha512-3XOqkZP/y6B4F0PBAXvI1/bky7GryoogUtfwExeP/v7Nzwo1QLcq5oQmpKlftZLbT+ERUOAZVQjuNVak6UXjPA== 217 | dependencies: 218 | "@webassemblyjs/ast" "1.11.6" 219 | "@webassemblyjs/helper-wasm-bytecode" "1.11.6" 220 | "@webassemblyjs/ieee754" "1.11.6" 221 | "@webassemblyjs/leb128" "1.11.6" 222 | "@webassemblyjs/utf8" "1.11.6" 223 | 224 | "@webassemblyjs/wasm-opt@1.11.6": 225 | version "1.11.6" 226 | resolved "https://registry.npmmirror.com/@webassemblyjs/wasm-opt/-/wasm-opt-1.11.6.tgz#d9a22d651248422ca498b09aa3232a81041487c2" 227 | integrity sha512-cOrKuLRE7PCe6AsOVl7WasYf3wbSo4CeOk6PkrjS7g57MFfVUF9u6ysQBBODX0LdgSvQqRiGz3CXvIDKcPNy4g== 228 | dependencies: 229 | "@webassemblyjs/ast" "1.11.6" 230 | "@webassemblyjs/helper-buffer" "1.11.6" 231 | "@webassemblyjs/wasm-gen" "1.11.6" 232 | "@webassemblyjs/wasm-parser" "1.11.6" 233 | 234 | "@webassemblyjs/wasm-parser@1.11.6", "@webassemblyjs/wasm-parser@^1.11.5": 235 | version "1.11.6" 236 | resolved "https://registry.npmmirror.com/@webassemblyjs/wasm-parser/-/wasm-parser-1.11.6.tgz#bb85378c527df824004812bbdb784eea539174a1" 237 | integrity sha512-6ZwPeGzMJM3Dqp3hCsLgESxBGtT/OeCvCZ4TA1JUPYgmhAx38tTPR9JaKy0S5H3evQpO/h2uWs2j6Yc/fjkpTQ== 238 | dependencies: 239 | "@webassemblyjs/ast" "1.11.6" 240 | "@webassemblyjs/helper-api-error" "1.11.6" 241 | "@webassemblyjs/helper-wasm-bytecode" "1.11.6" 242 | "@webassemblyjs/ieee754" "1.11.6" 243 | "@webassemblyjs/leb128" "1.11.6" 244 | "@webassemblyjs/utf8" "1.11.6" 245 | 246 | "@webassemblyjs/wast-printer@1.11.6": 247 | version "1.11.6" 248 | resolved "https://registry.npmmirror.com/@webassemblyjs/wast-printer/-/wast-printer-1.11.6.tgz#a7bf8dd7e362aeb1668ff43f35cb849f188eff20" 249 | integrity sha512-JM7AhRcE+yW2GWYaKeHL5vt4xqee5N2WcezptmgyhNS+ScggqcT1OtXykhAb13Sn5Yas0j2uv9tHgrjwvzAP4A== 250 | dependencies: 251 | "@webassemblyjs/ast" "1.11.6" 252 | "@xtuc/long" "4.2.2" 253 | 254 | "@webpack-cli/configtest@^2.1.0": 255 | version "2.1.1" 256 | resolved "https://registry.npmmirror.com/@webpack-cli/configtest/-/configtest-2.1.1.tgz#3b2f852e91dac6e3b85fb2a314fb8bef46d94646" 257 | integrity sha512-wy0mglZpDSiSS0XHrVR+BAdId2+yxPSoJW8fsna3ZpYSlufjvxnP4YbKTCBZnNIcGN4r6ZPXV55X4mYExOfLmw== 258 | 259 | "@webpack-cli/info@^2.0.1": 260 | version "2.0.2" 261 | resolved "https://registry.npmmirror.com/@webpack-cli/info/-/info-2.0.2.tgz#cc3fbf22efeb88ff62310cf885c5b09f44ae0fdd" 262 | integrity sha512-zLHQdI/Qs1UyT5UBdWNqsARasIA+AaF8t+4u2aS2nEpBQh2mWIVb8qAklq0eUENnC5mOItrIB4LiS9xMtph18A== 263 | 264 | "@webpack-cli/serve@^2.0.3": 265 | version "2.0.5" 266 | resolved "https://registry.npmmirror.com/@webpack-cli/serve/-/serve-2.0.5.tgz#325db42395cd49fe6c14057f9a900e427df8810e" 267 | integrity sha512-lqaoKnRYBdo1UgDX8uF24AfGMifWK19TxPmM5FHc2vAGxrJ/qtyUyFBWoY1tISZdelsQ5fBcOusifo5o5wSJxQ== 268 | 269 | "@xtuc/ieee754@^1.2.0": 270 | version "1.2.0" 271 | resolved "https://registry.npmmirror.com/@xtuc/ieee754/-/ieee754-1.2.0.tgz#eef014a3145ae477a1cbc00cd1e552336dceb790" 272 | integrity sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA== 273 | 274 | "@xtuc/long@4.2.2": 275 | version "4.2.2" 276 | resolved "https://registry.npmmirror.com/@xtuc/long/-/long-4.2.2.tgz#d291c6a4e97989b5c61d9acf396ae4fe133a718d" 277 | integrity sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ== 278 | 279 | abab@^2.0.6: 280 | version "2.0.6" 281 | resolved "https://registry.npmmirror.com/abab/-/abab-2.0.6.tgz#41b80f2c871d19686216b82309231cfd3cb3d291" 282 | integrity sha512-j2afSsaIENvHZN2B8GOpF566vZ5WVk5opAiMTvWgaQT8DkbOqsTfvNAvHoRGU2zzP8cPoqys+xHTRDWW8L+/BA== 283 | 284 | accepts@~1.3.4: 285 | version "1.3.8" 286 | resolved "https://registry.npmmirror.com/accepts/-/accepts-1.3.8.tgz#0bf0be125b67014adcb0b0921e62db7bffe16b2e" 287 | integrity sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw== 288 | dependencies: 289 | mime-types "~2.1.34" 290 | negotiator "0.6.3" 291 | 292 | acorn-import-assertions@^1.7.6: 293 | version "1.9.0" 294 | resolved "https://registry.npmmirror.com/acorn-import-assertions/-/acorn-import-assertions-1.9.0.tgz#507276249d684797c84e0734ef84860334cfb1ac" 295 | integrity sha512-cmMwop9x+8KFhxvKrKfPYmN6/pKTYYHBqLa0DfvVZcKMJWNyWLnaqND7dx/qn66R7ewM1UX5XMaDVP5wlVTaVA== 296 | 297 | acorn@^8.7.1, acorn@^8.8.2: 298 | version "8.11.2" 299 | resolved "https://registry.npmmirror.com/acorn/-/acorn-8.11.2.tgz#ca0d78b51895be5390a5903c5b3bdcdaf78ae40b" 300 | integrity sha512-nc0Axzp/0FILLEVsm4fNwLCwMttvhEI263QtVPQcbpfZZ3ts0hLsZGOpE6czNlid7CJ9MlyH8reXkpsf3YUY4w== 301 | 302 | ajv-keywords@^3.5.2: 303 | version "3.5.2" 304 | resolved "https://registry.npmmirror.com/ajv-keywords/-/ajv-keywords-3.5.2.tgz#31f29da5ab6e00d1c2d329acf7b5929614d5014d" 305 | integrity sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ== 306 | 307 | ajv@^6.12.5: 308 | version "6.12.6" 309 | resolved "https://registry.npmmirror.com/ajv/-/ajv-6.12.6.tgz#baf5a62e802b07d977034586f8c3baf5adf26df4" 310 | integrity sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g== 311 | dependencies: 312 | fast-deep-equal "^3.1.1" 313 | fast-json-stable-stringify "^2.0.0" 314 | json-schema-traverse "^0.4.1" 315 | uri-js "^4.2.2" 316 | 317 | ansi-colors@4.1.1: 318 | version "4.1.1" 319 | resolved "https://registry.npmmirror.com/ansi-colors/-/ansi-colors-4.1.1.tgz#cbb9ae256bf750af1eab344f229aa27fe94ba348" 320 | integrity sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA== 321 | 322 | ansi-regex@^5.0.1: 323 | version "5.0.1" 324 | resolved "https://registry.npmmirror.com/ansi-regex/-/ansi-regex-5.0.1.tgz#082cb2c89c9fe8659a311a53bd6a4dc5301db304" 325 | integrity sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ== 326 | 327 | ansi-styles@^4.0.0, ansi-styles@^4.1.0: 328 | version "4.3.0" 329 | resolved "https://registry.npmmirror.com/ansi-styles/-/ansi-styles-4.3.0.tgz#edd803628ae71c04c85ae7a0906edad34b648937" 330 | integrity sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg== 331 | dependencies: 332 | color-convert "^2.0.1" 333 | 334 | anymatch@~3.1.2: 335 | version "3.1.3" 336 | resolved "https://registry.npmmirror.com/anymatch/-/anymatch-3.1.3.tgz#790c58b19ba1720a84205b57c618d5ad8524973e" 337 | integrity sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw== 338 | dependencies: 339 | normalize-path "^3.0.0" 340 | picomatch "^2.0.4" 341 | 342 | argparse@^2.0.1: 343 | version "2.0.1" 344 | resolved "https://registry.npmmirror.com/argparse/-/argparse-2.0.1.tgz#246f50f3ca78a3240f6c997e8a9bd1eac49e4b38" 345 | integrity sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q== 346 | 347 | balanced-match@^1.0.0: 348 | version "1.0.2" 349 | resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee" 350 | integrity sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw== 351 | 352 | base64id@2.0.0, base64id@~2.0.0: 353 | version "2.0.0" 354 | resolved "https://registry.npmmirror.com/base64id/-/base64id-2.0.0.tgz#2770ac6bc47d312af97a8bf9a634342e0cd25cb6" 355 | integrity sha512-lGe34o6EHj9y3Kts9R4ZYs/Gr+6N7MCaMlIFA3F1R2O5/m7K06AxfSeO5530PEERE6/WyEg3lsuyw4GHlPZHog== 356 | 357 | binary-extensions@^2.0.0: 358 | version "2.2.0" 359 | resolved "https://registry.npmmirror.com/binary-extensions/-/binary-extensions-2.2.0.tgz#75f502eeaf9ffde42fc98829645be4ea76bd9e2d" 360 | integrity sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA== 361 | 362 | body-parser@^1.19.0: 363 | version "1.20.2" 364 | resolved "https://registry.npmmirror.com/body-parser/-/body-parser-1.20.2.tgz#6feb0e21c4724d06de7ff38da36dad4f57a747fd" 365 | integrity sha512-ml9pReCu3M61kGlqoTm2umSXTlRTuGTx0bfYj+uIUKKYycG5NtSbeetV3faSU6R7ajOPw0g/J1PvK4qNy7s5bA== 366 | dependencies: 367 | bytes "3.1.2" 368 | content-type "~1.0.5" 369 | debug "2.6.9" 370 | depd "2.0.0" 371 | destroy "1.2.0" 372 | http-errors "2.0.0" 373 | iconv-lite "0.4.24" 374 | on-finished "2.4.1" 375 | qs "6.11.0" 376 | raw-body "2.5.2" 377 | type-is "~1.6.18" 378 | unpipe "1.0.0" 379 | 380 | brace-expansion@^1.1.7: 381 | version "1.1.11" 382 | resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd" 383 | integrity sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA== 384 | dependencies: 385 | balanced-match "^1.0.0" 386 | concat-map "0.0.1" 387 | 388 | brace-expansion@^2.0.1: 389 | version "2.0.1" 390 | resolved "https://registry.npmmirror.com/brace-expansion/-/brace-expansion-2.0.1.tgz#1edc459e0f0c548486ecf9fc99f2221364b9a0ae" 391 | integrity sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA== 392 | dependencies: 393 | balanced-match "^1.0.0" 394 | 395 | braces@^3.0.2, braces@~3.0.2: 396 | version "3.0.2" 397 | resolved "https://registry.npmmirror.com/braces/-/braces-3.0.2.tgz#3454e1a462ee8d599e236df336cd9ea4f8afe107" 398 | integrity sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A== 399 | dependencies: 400 | fill-range "^7.0.1" 401 | 402 | browser-stdout@1.3.1: 403 | version "1.3.1" 404 | resolved "https://registry.npmmirror.com/browser-stdout/-/browser-stdout-1.3.1.tgz#baa559ee14ced73452229bad7326467c61fabd60" 405 | integrity sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw== 406 | 407 | browserslist@^4.14.5: 408 | version "4.22.2" 409 | resolved "https://registry.npmmirror.com/browserslist/-/browserslist-4.22.2.tgz#704c4943072bd81ea18997f3bd2180e89c77874b" 410 | integrity sha512-0UgcrvQmBDvZHFGdYUehrCNIazki7/lUP3kkoi/r3YB2amZbFM9J43ZRkJTXBUZK4gmx56+Sqk9+Vs9mwZx9+A== 411 | dependencies: 412 | caniuse-lite "^1.0.30001565" 413 | electron-to-chromium "^1.4.601" 414 | node-releases "^2.0.14" 415 | update-browserslist-db "^1.0.13" 416 | 417 | buffer-from@^1.0.0: 418 | version "1.1.2" 419 | resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.2.tgz#2b146a6fd72e80b4f55d255f35ed59a3a9a41bd5" 420 | integrity sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ== 421 | 422 | bytes@3.1.2: 423 | version "3.1.2" 424 | resolved "https://registry.npmmirror.com/bytes/-/bytes-3.1.2.tgz#8b0beeb98605adf1b128fa4386403c009e0221a5" 425 | integrity sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg== 426 | 427 | call-bind@^1.0.0: 428 | version "1.0.5" 429 | resolved "https://registry.npmmirror.com/call-bind/-/call-bind-1.0.5.tgz#6fa2b7845ce0ea49bf4d8b9ef64727a2c2e2e513" 430 | integrity sha512-C3nQxfFZxFRVoJoGKKI8y3MOEo129NQ+FgQ08iye+Mk4zNZZGdjfs06bVTr+DBSlA66Q2VEcMki/cUCP4SercQ== 431 | dependencies: 432 | function-bind "^1.1.2" 433 | get-intrinsic "^1.2.1" 434 | set-function-length "^1.1.1" 435 | 436 | camelcase@^6.0.0: 437 | version "6.3.0" 438 | resolved "https://registry.npmmirror.com/camelcase/-/camelcase-6.3.0.tgz#5685b95eb209ac9c0c177467778c9c84df58ba9a" 439 | integrity sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA== 440 | 441 | caniuse-lite@^1.0.30001565: 442 | version "1.0.30001570" 443 | resolved "https://registry.npmmirror.com/caniuse-lite/-/caniuse-lite-1.0.30001570.tgz#b4e5c1fa786f733ab78fc70f592df6b3f23244ca" 444 | integrity sha512-+3e0ASu4sw1SWaoCtvPeyXp+5PsjigkSt8OXZbF9StH5pQWbxEjLAZE3n8Aup5udop1uRiKA7a4utUk/uoSpUw== 445 | 446 | chalk@^4.1.0: 447 | version "4.1.2" 448 | resolved "https://registry.npmmirror.com/chalk/-/chalk-4.1.2.tgz#aac4e2b7734a740867aeb16bf02aad556a1e7a01" 449 | integrity sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA== 450 | dependencies: 451 | ansi-styles "^4.1.0" 452 | supports-color "^7.1.0" 453 | 454 | chokidar@3.5.3, "chokidar@>=3.0.0 <4.0.0", chokidar@^3.5.1: 455 | version "3.5.3" 456 | resolved "https://registry.npmmirror.com/chokidar/-/chokidar-3.5.3.tgz#1cf37c8707b932bd1af1ae22c0432e2acd1903bd" 457 | integrity sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw== 458 | dependencies: 459 | anymatch "~3.1.2" 460 | braces "~3.0.2" 461 | glob-parent "~5.1.2" 462 | is-binary-path "~2.1.0" 463 | is-glob "~4.0.1" 464 | normalize-path "~3.0.0" 465 | readdirp "~3.6.0" 466 | optionalDependencies: 467 | fsevents "~2.3.2" 468 | 469 | chrome-trace-event@^1.0.2: 470 | version "1.0.3" 471 | resolved "https://registry.npmmirror.com/chrome-trace-event/-/chrome-trace-event-1.0.3.tgz#1015eced4741e15d06664a957dbbf50d041e26ac" 472 | integrity sha512-p3KULyQg4S7NIHixdwbGX+nFHkoBiA4YQmyWtjb8XngSKV124nJmRysgAeujbUVb15vh+RvFUfCPqU7rXk+hZg== 473 | 474 | cliui@^7.0.2: 475 | version "7.0.4" 476 | resolved "https://registry.npmmirror.com/cliui/-/cliui-7.0.4.tgz#a0265ee655476fc807aea9df3df8df7783808b4f" 477 | integrity sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ== 478 | dependencies: 479 | string-width "^4.2.0" 480 | strip-ansi "^6.0.0" 481 | wrap-ansi "^7.0.0" 482 | 483 | clone-deep@^4.0.1: 484 | version "4.0.1" 485 | resolved "https://registry.npmmirror.com/clone-deep/-/clone-deep-4.0.1.tgz#c19fd9bdbbf85942b4fd979c84dcf7d5f07c2387" 486 | integrity sha512-neHB9xuzh/wk0dIHweyAXv2aPGZIVk3pLMe+/RNzINf17fe0OG96QroktYAUm7SM1PBnzTabaLboqqxDyMU+SQ== 487 | dependencies: 488 | is-plain-object "^2.0.4" 489 | kind-of "^6.0.2" 490 | shallow-clone "^3.0.0" 491 | 492 | color-convert@^2.0.1: 493 | version "2.0.1" 494 | resolved "https://registry.npmmirror.com/color-convert/-/color-convert-2.0.1.tgz#72d3a68d598c9bdb3af2ad1e84f21d896abd4de3" 495 | integrity sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ== 496 | dependencies: 497 | color-name "~1.1.4" 498 | 499 | color-name@~1.1.4: 500 | version "1.1.4" 501 | resolved "https://registry.npmmirror.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2" 502 | integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA== 503 | 504 | colorette@^2.0.14: 505 | version "2.0.20" 506 | resolved "https://registry.npmmirror.com/colorette/-/colorette-2.0.20.tgz#9eb793e6833067f7235902fcd3b09917a000a95a" 507 | integrity sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w== 508 | 509 | commander@^10.0.1: 510 | version "10.0.1" 511 | resolved "https://registry.npmmirror.com/commander/-/commander-10.0.1.tgz#881ee46b4f77d1c1dccc5823433aa39b022cbe06" 512 | integrity sha512-y4Mg2tXshplEbSGzx7amzPwKKOCGuoSRP/CjEdwwk0FOGlUbq6lKuoyDZTNZkmxHdJtp54hdfY/JUrdL7Xfdug== 513 | 514 | commander@^2.20.0: 515 | version "2.20.3" 516 | resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.3.tgz#fd485e84c03eb4881c20722ba48035e8531aeb33" 517 | integrity sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ== 518 | 519 | concat-map@0.0.1: 520 | version "0.0.1" 521 | resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" 522 | integrity sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg== 523 | 524 | connect@^3.7.0: 525 | version "3.7.0" 526 | resolved "https://registry.npmmirror.com/connect/-/connect-3.7.0.tgz#5d49348910caa5e07a01800b030d0c35f20484f8" 527 | integrity sha512-ZqRXc+tZukToSNmh5C2iWMSoV3X1YUcPbqEM4DkEG5tNQXrQUZCNVGGv3IuicnkMtPfGf3Xtp8WCXs295iQ1pQ== 528 | dependencies: 529 | debug "2.6.9" 530 | finalhandler "1.1.2" 531 | parseurl "~1.3.3" 532 | utils-merge "1.0.1" 533 | 534 | content-type@~1.0.5: 535 | version "1.0.5" 536 | resolved "https://registry.npmmirror.com/content-type/-/content-type-1.0.5.tgz#8b773162656d1d1086784c8f23a54ce6d73d7918" 537 | integrity sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA== 538 | 539 | cookie@~0.4.1: 540 | version "0.4.2" 541 | resolved "https://registry.npmmirror.com/cookie/-/cookie-0.4.2.tgz#0e41f24de5ecf317947c82fc789e06a884824432" 542 | integrity sha512-aSWTXFzaKWkvHO1Ny/s+ePFpvKsPnjc551iI41v3ny/ow6tBG5Vd+FuqGNhh1LxOmVzOlGUriIlOaokOvhaStA== 543 | 544 | cors@~2.8.5: 545 | version "2.8.5" 546 | resolved "https://registry.npmmirror.com/cors/-/cors-2.8.5.tgz#eac11da51592dd86b9f06f6e7ac293b3df875d29" 547 | integrity sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g== 548 | dependencies: 549 | object-assign "^4" 550 | vary "^1" 551 | 552 | cross-spawn@^7.0.3: 553 | version "7.0.3" 554 | resolved "https://registry.npmmirror.com/cross-spawn/-/cross-spawn-7.0.3.tgz#f73a85b9d5d41d045551c177e2882d4ac85728a6" 555 | integrity sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w== 556 | dependencies: 557 | path-key "^3.1.0" 558 | shebang-command "^2.0.0" 559 | which "^2.0.1" 560 | 561 | css-loader@6.7.3: 562 | version "6.7.3" 563 | resolved "https://registry.npmmirror.com/css-loader/-/css-loader-6.7.3.tgz#1e8799f3ccc5874fdd55461af51137fcc5befbcd" 564 | integrity sha512-qhOH1KlBMnZP8FzRO6YCH9UHXQhVMcEGLyNdb7Hv2cpcmJbW0YrddO+tG1ab5nT41KpHIYGsbeHqxB9xPu1pKQ== 565 | dependencies: 566 | icss-utils "^5.1.0" 567 | postcss "^8.4.19" 568 | postcss-modules-extract-imports "^3.0.0" 569 | postcss-modules-local-by-default "^4.0.0" 570 | postcss-modules-scope "^3.0.0" 571 | postcss-modules-values "^4.0.0" 572 | postcss-value-parser "^4.2.0" 573 | semver "^7.3.8" 574 | 575 | cssesc@^3.0.0: 576 | version "3.0.0" 577 | resolved "https://registry.npmmirror.com/cssesc/-/cssesc-3.0.0.tgz#37741919903b868565e1c09ea747445cd18983ee" 578 | integrity sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg== 579 | 580 | custom-event@~1.0.0: 581 | version "1.0.1" 582 | resolved "https://registry.npmmirror.com/custom-event/-/custom-event-1.0.1.tgz#5d02a46850adf1b4a317946a3928fccb5bfd0425" 583 | integrity sha512-GAj5FOq0Hd+RsCGVJxZuKaIDXDf3h6GQoNEjFgbLLI/trgtavwUbSnZ5pVfg27DVCaWjIohryS0JFwIJyT2cMg== 584 | 585 | date-format@^4.0.14: 586 | version "4.0.14" 587 | resolved "https://registry.npmmirror.com/date-format/-/date-format-4.0.14.tgz#7a8e584434fb169a521c8b7aa481f355810d9400" 588 | integrity sha512-39BOQLs9ZjKh0/patS9nrT8wc3ioX3/eA/zgbKNopnF2wCqJEoxywwwElATYvRsXdnOxA/OQeQoFZ3rFjVajhg== 589 | 590 | debug@2.6.9: 591 | version "2.6.9" 592 | resolved "https://registry.npmmirror.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f" 593 | integrity sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA== 594 | dependencies: 595 | ms "2.0.0" 596 | 597 | debug@4.3.4, debug@^4.3.4, debug@~4.3.1, debug@~4.3.2: 598 | version "4.3.4" 599 | resolved "https://registry.npmmirror.com/debug/-/debug-4.3.4.tgz#1319f6579357f2338d3337d2cdd4914bb5dcc865" 600 | integrity sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ== 601 | dependencies: 602 | ms "2.1.2" 603 | 604 | decamelize@^4.0.0: 605 | version "4.0.0" 606 | resolved "https://registry.npmmirror.com/decamelize/-/decamelize-4.0.0.tgz#aa472d7bf660eb15f3494efd531cab7f2a709837" 607 | integrity sha512-9iE1PgSik9HeIIw2JO94IidnE3eBoQrFJ3w7sFuzSX4DpmZ3v5sZpUiV5Swcf6mQEF+Y0ru8Neo+p+nyh2J+hQ== 608 | 609 | define-data-property@^1.1.1: 610 | version "1.1.1" 611 | resolved "https://registry.npmmirror.com/define-data-property/-/define-data-property-1.1.1.tgz#c35f7cd0ab09883480d12ac5cb213715587800b3" 612 | integrity sha512-E7uGkTzkk1d0ByLeSc6ZsFS79Axg+m1P/VsgYsxHgiuc3tFSj+MjMIwe90FC4lOAZzNBdY7kkO2P2wKdsQ1vgQ== 613 | dependencies: 614 | get-intrinsic "^1.2.1" 615 | gopd "^1.0.1" 616 | has-property-descriptors "^1.0.0" 617 | 618 | depd@2.0.0: 619 | version "2.0.0" 620 | resolved "https://registry.npmmirror.com/depd/-/depd-2.0.0.tgz#b696163cc757560d09cf22cc8fad1571b79e76df" 621 | integrity sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw== 622 | 623 | destroy@1.2.0: 624 | version "1.2.0" 625 | resolved "https://registry.npmmirror.com/destroy/-/destroy-1.2.0.tgz#4803735509ad8be552934c67df614f94e66fa015" 626 | integrity sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg== 627 | 628 | di@^0.0.1: 629 | version "0.0.1" 630 | resolved "https://registry.npmmirror.com/di/-/di-0.0.1.tgz#806649326ceaa7caa3306d75d985ea2748ba913c" 631 | integrity sha512-uJaamHkagcZtHPqCIHZxnFrXlunQXgBOsZSUOWwFw31QJCAbyTBoHMW75YOTur5ZNx8pIeAKgf6GWIgaqqiLhA== 632 | 633 | diff@5.0.0: 634 | version "5.0.0" 635 | resolved "https://registry.npmmirror.com/diff/-/diff-5.0.0.tgz#7ed6ad76d859d030787ec35855f5b1daf31d852b" 636 | integrity sha512-/VTCrvm5Z0JGty/BWHljh+BAiw3IK+2j87NGMu8Nwc/f48WoDAC395uomO9ZD117ZOBaHmkX1oyLvkVM/aIT3w== 637 | 638 | dom-serialize@^2.2.1: 639 | version "2.2.1" 640 | resolved "https://registry.npmmirror.com/dom-serialize/-/dom-serialize-2.2.1.tgz#562ae8999f44be5ea3076f5419dcd59eb43ac95b" 641 | integrity sha512-Yra4DbvoW7/Z6LBN560ZwXMjoNOSAN2wRsKFGc4iBeso+mpIA6qj1vfdf9HpMaKAqG6wXTy+1SYEzmNpKXOSsQ== 642 | dependencies: 643 | custom-event "~1.0.0" 644 | ent "~2.2.0" 645 | extend "^3.0.0" 646 | void-elements "^2.0.0" 647 | 648 | ee-first@1.1.1: 649 | version "1.1.1" 650 | resolved "https://registry.npmmirror.com/ee-first/-/ee-first-1.1.1.tgz#590c61156b0ae2f4f0255732a158b266bc56b21d" 651 | integrity sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow== 652 | 653 | electron-to-chromium@^1.4.601: 654 | version "1.4.615" 655 | resolved "https://registry.npmmirror.com/electron-to-chromium/-/electron-to-chromium-1.4.615.tgz#b1c41839962d2e4e63dca05519da9040e34848c2" 656 | integrity sha512-/bKPPcgZVUziECqDc+0HkT87+0zhaWSZHNXqF8FLd2lQcptpmUFwoCSWjCdOng9Gdq+afKArPdEg/0ZW461Eng== 657 | 658 | emoji-regex@^8.0.0: 659 | version "8.0.0" 660 | resolved "https://registry.npmmirror.com/emoji-regex/-/emoji-regex-8.0.0.tgz#e818fd69ce5ccfcb404594f842963bf53164cc37" 661 | integrity sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A== 662 | 663 | encodeurl@~1.0.2: 664 | version "1.0.2" 665 | resolved "https://registry.npmmirror.com/encodeurl/-/encodeurl-1.0.2.tgz#ad3ff4c86ec2d029322f5a02c3a9a606c95b3f59" 666 | integrity sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w== 667 | 668 | engine.io-parser@~5.2.1: 669 | version "5.2.1" 670 | resolved "https://registry.npmmirror.com/engine.io-parser/-/engine.io-parser-5.2.1.tgz#9f213c77512ff1a6cc0c7a86108a7ffceb16fcfb" 671 | integrity sha512-9JktcM3u18nU9N2Lz3bWeBgxVgOKpw7yhRaoxQA3FUDZzzw+9WlA6p4G4u0RixNkg14fH7EfEc/RhpurtiROTQ== 672 | 673 | engine.io@~6.5.2: 674 | version "6.5.4" 675 | resolved "https://registry.npmmirror.com/engine.io/-/engine.io-6.5.4.tgz#6822debf324e781add2254e912f8568508850cdc" 676 | integrity sha512-KdVSDKhVKyOi+r5uEabrDLZw2qXStVvCsEB/LN3mw4WFi6Gx50jTyuxYVCwAAC0U46FdnzP/ScKRBTXb/NiEOg== 677 | dependencies: 678 | "@types/cookie" "^0.4.1" 679 | "@types/cors" "^2.8.12" 680 | "@types/node" ">=10.0.0" 681 | accepts "~1.3.4" 682 | base64id "2.0.0" 683 | cookie "~0.4.1" 684 | cors "~2.8.5" 685 | debug "~4.3.1" 686 | engine.io-parser "~5.2.1" 687 | ws "~8.11.0" 688 | 689 | enhanced-resolve@^5.13.0: 690 | version "5.15.0" 691 | resolved "https://registry.npmmirror.com/enhanced-resolve/-/enhanced-resolve-5.15.0.tgz#1af946c7d93603eb88e9896cee4904dc012e9c35" 692 | integrity sha512-LXYT42KJ7lpIKECr2mAXIaMldcNCh/7E0KBKOu4KSfkHmP+mZmSs+8V5gBAqisWBy0OO4W5Oyys0GO1Y8KtdKg== 693 | dependencies: 694 | graceful-fs "^4.2.4" 695 | tapable "^2.2.0" 696 | 697 | ent@~2.2.0: 698 | version "2.2.0" 699 | resolved "https://registry.npmmirror.com/ent/-/ent-2.2.0.tgz#e964219325a21d05f44466a2f686ed6ce5f5dd1d" 700 | integrity sha512-GHrMyVZQWvTIdDtpiEXdHZnFQKzeO09apj8Cbl4pKWy4i0Oprcq17usfDt5aO63swf0JOeMWjWQE/LzgSRuWpA== 701 | 702 | envinfo@^7.7.3: 703 | version "7.11.0" 704 | resolved "https://registry.npmmirror.com/envinfo/-/envinfo-7.11.0.tgz#c3793f44284a55ff8c82faf1ffd91bc6478ea01f" 705 | integrity sha512-G9/6xF1FPbIw0TtalAMaVPpiq2aDEuKLXM314jPVAO9r2fo2a4BLqMNkmRS7O/xPPZ+COAhGIz3ETvHEV3eUcg== 706 | 707 | es-module-lexer@^1.2.1: 708 | version "1.4.1" 709 | resolved "https://registry.npmmirror.com/es-module-lexer/-/es-module-lexer-1.4.1.tgz#41ea21b43908fe6a287ffcbe4300f790555331f5" 710 | integrity sha512-cXLGjP0c4T3flZJKQSuziYoq7MlT+rnvfZjfp7h+I7K9BNX54kP9nyWvdbwjQ4u1iWbOL4u96fgeZLToQlZC7w== 711 | 712 | escalade@^3.1.1: 713 | version "3.1.1" 714 | resolved "https://registry.npmmirror.com/escalade/-/escalade-3.1.1.tgz#d8cfdc7000965c5a0174b4a82eaa5c0552742e40" 715 | integrity sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw== 716 | 717 | escape-html@~1.0.3: 718 | version "1.0.3" 719 | resolved "https://registry.npmmirror.com/escape-html/-/escape-html-1.0.3.tgz#0258eae4d3d0c0974de1c169188ef0051d1d1988" 720 | integrity sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow== 721 | 722 | escape-string-regexp@4.0.0: 723 | version "4.0.0" 724 | resolved "https://registry.npmmirror.com/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz#14ba83a5d373e3d311e5afca29cf5bfad965bf34" 725 | integrity sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA== 726 | 727 | eslint-scope@5.1.1: 728 | version "5.1.1" 729 | resolved "https://registry.npmmirror.com/eslint-scope/-/eslint-scope-5.1.1.tgz#e786e59a66cb92b3f6c1fb0d508aab174848f48c" 730 | integrity sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw== 731 | dependencies: 732 | esrecurse "^4.3.0" 733 | estraverse "^4.1.1" 734 | 735 | esrecurse@^4.3.0: 736 | version "4.3.0" 737 | resolved "https://registry.npmmirror.com/esrecurse/-/esrecurse-4.3.0.tgz#7ad7964d679abb28bee72cec63758b1c5d2c9921" 738 | integrity sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag== 739 | dependencies: 740 | estraverse "^5.2.0" 741 | 742 | estraverse@^4.1.1: 743 | version "4.3.0" 744 | resolved "https://registry.npmmirror.com/estraverse/-/estraverse-4.3.0.tgz#398ad3f3c5a24948be7725e83d11a7de28cdbd1d" 745 | integrity sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw== 746 | 747 | estraverse@^5.2.0: 748 | version "5.3.0" 749 | resolved "https://registry.npmmirror.com/estraverse/-/estraverse-5.3.0.tgz#2eea5290702f26ab8fe5370370ff86c965d21123" 750 | integrity sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA== 751 | 752 | eventemitter3@^4.0.0: 753 | version "4.0.7" 754 | resolved "https://registry.npmmirror.com/eventemitter3/-/eventemitter3-4.0.7.tgz#2de9b68f6528d5644ef5c59526a1b4a07306169f" 755 | integrity sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw== 756 | 757 | events@^3.2.0: 758 | version "3.3.0" 759 | resolved "https://registry.npmmirror.com/events/-/events-3.3.0.tgz#31a95ad0a924e2d2c419a813aeb2c4e878ea7400" 760 | integrity sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q== 761 | 762 | extend@^3.0.0: 763 | version "3.0.2" 764 | resolved "https://registry.npmmirror.com/extend/-/extend-3.0.2.tgz#f8b1136b4071fbd8eb140aff858b1019ec2915fa" 765 | integrity sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g== 766 | 767 | fast-deep-equal@^3.1.1: 768 | version "3.1.3" 769 | resolved "https://registry.npmmirror.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525" 770 | integrity sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q== 771 | 772 | fast-json-stable-stringify@^2.0.0: 773 | version "2.1.0" 774 | resolved "https://registry.npmmirror.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz#874bf69c6f404c2b5d99c481341399fd55892633" 775 | integrity sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw== 776 | 777 | fastest-levenshtein@^1.0.12: 778 | version "1.0.16" 779 | resolved "https://registry.npmmirror.com/fastest-levenshtein/-/fastest-levenshtein-1.0.16.tgz#210e61b6ff181de91ea9b3d1b84fdedd47e034e5" 780 | integrity sha512-eRnCtTTtGZFpQCwhJiUOuxPQWRXVKYDn0b2PeHfXL6/Zi53SLAzAHfVhVWK2AryC/WH05kGfxhFIPvTF0SXQzg== 781 | 782 | fill-range@^7.0.1: 783 | version "7.0.1" 784 | resolved "https://registry.npmmirror.com/fill-range/-/fill-range-7.0.1.tgz#1919a6a7c75fe38b2c7c77e5198535da9acdda40" 785 | integrity sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ== 786 | dependencies: 787 | to-regex-range "^5.0.1" 788 | 789 | finalhandler@1.1.2: 790 | version "1.1.2" 791 | resolved "https://registry.npmmirror.com/finalhandler/-/finalhandler-1.1.2.tgz#b7e7d000ffd11938d0fdb053506f6ebabe9f587d" 792 | integrity sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA== 793 | dependencies: 794 | debug "2.6.9" 795 | encodeurl "~1.0.2" 796 | escape-html "~1.0.3" 797 | on-finished "~2.3.0" 798 | parseurl "~1.3.3" 799 | statuses "~1.5.0" 800 | unpipe "~1.0.0" 801 | 802 | find-up@5.0.0: 803 | version "5.0.0" 804 | resolved "https://registry.npmmirror.com/find-up/-/find-up-5.0.0.tgz#4c92819ecb7083561e4f4a240a86be5198f536fc" 805 | integrity sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng== 806 | dependencies: 807 | locate-path "^6.0.0" 808 | path-exists "^4.0.0" 809 | 810 | find-up@^4.0.0: 811 | version "4.1.0" 812 | resolved "https://registry.npmmirror.com/find-up/-/find-up-4.1.0.tgz#97afe7d6cdc0bc5928584b7c8d7b16e8a9aa5d19" 813 | integrity sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw== 814 | dependencies: 815 | locate-path "^5.0.0" 816 | path-exists "^4.0.0" 817 | 818 | flat@^5.0.2: 819 | version "5.0.2" 820 | resolved "https://registry.npmmirror.com/flat/-/flat-5.0.2.tgz#8ca6fe332069ffa9d324c327198c598259ceb241" 821 | integrity sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ== 822 | 823 | flatted@^3.2.7: 824 | version "3.2.9" 825 | resolved "https://registry.npmmirror.com/flatted/-/flatted-3.2.9.tgz#7eb4c67ca1ba34232ca9d2d93e9886e611ad7daf" 826 | integrity sha512-36yxDn5H7OFZQla0/jFJmbIKTdZAQHngCedGxiMmpNfEZM0sdEeT+WczLQrjK6D7o2aiyLYDnkw0R3JK0Qv1RQ== 827 | 828 | follow-redirects@^1.0.0: 829 | version "1.15.3" 830 | resolved "https://registry.npmmirror.com/follow-redirects/-/follow-redirects-1.15.3.tgz#fe2f3ef2690afce7e82ed0b44db08165b207123a" 831 | integrity sha512-1VzOtuEM8pC9SFU1E+8KfTjZyMztRsgEfwQl44z8A25uy13jSzTj6dyK2Df52iV0vgHCfBwLhDWevLn95w5v6Q== 832 | 833 | format-util@^1.0.5: 834 | version "1.0.5" 835 | resolved "https://registry.yarnpkg.com/format-util/-/format-util-1.0.5.tgz#1ffb450c8a03e7bccffe40643180918cc297d271" 836 | integrity sha512-varLbTj0e0yVyRpqQhuWV+8hlePAgaoFRhNFj50BNjEIrw1/DphHSObtqwskVCPWNgzwPoQrZAbfa/SBiicNeg== 837 | 838 | fs-extra@^8.1.0: 839 | version "8.1.0" 840 | resolved "https://registry.npmmirror.com/fs-extra/-/fs-extra-8.1.0.tgz#49d43c45a88cd9677668cb7be1b46efdb8d2e1c0" 841 | integrity sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g== 842 | dependencies: 843 | graceful-fs "^4.2.0" 844 | jsonfile "^4.0.0" 845 | universalify "^0.1.0" 846 | 847 | fs.realpath@^1.0.0: 848 | version "1.0.0" 849 | resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" 850 | integrity sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw== 851 | 852 | fsevents@~2.3.2: 853 | version "2.3.2" 854 | resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.2.tgz#8a526f78b8fdf4623b709e0b975c52c24c02fd1a" 855 | integrity sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA== 856 | 857 | function-bind@^1.1.2: 858 | version "1.1.2" 859 | resolved "https://registry.npmmirror.com/function-bind/-/function-bind-1.1.2.tgz#2c02d864d97f3ea6c8830c464cbd11ab6eab7a1c" 860 | integrity sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA== 861 | 862 | get-caller-file@^2.0.5: 863 | version "2.0.5" 864 | resolved "https://registry.npmmirror.com/get-caller-file/-/get-caller-file-2.0.5.tgz#4f94412a82db32f36e3b0b9741f8a97feb031f7e" 865 | integrity sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg== 866 | 867 | get-intrinsic@^1.0.2, get-intrinsic@^1.1.3, get-intrinsic@^1.2.1, get-intrinsic@^1.2.2: 868 | version "1.2.2" 869 | resolved "https://registry.npmmirror.com/get-intrinsic/-/get-intrinsic-1.2.2.tgz#281b7622971123e1ef4b3c90fd7539306da93f3b" 870 | integrity sha512-0gSo4ml/0j98Y3lngkFEot/zhiCeWsbYIlZ+uZOVgzLyLaUw7wxUL+nCTP0XJvJg1AXulJRI3UJi8GsbDuxdGA== 871 | dependencies: 872 | function-bind "^1.1.2" 873 | has-proto "^1.0.1" 874 | has-symbols "^1.0.3" 875 | hasown "^2.0.0" 876 | 877 | glob-parent@~5.1.2: 878 | version "5.1.2" 879 | resolved "https://registry.npmmirror.com/glob-parent/-/glob-parent-5.1.2.tgz#869832c58034fe68a4093c17dc15e8340d8401c4" 880 | integrity sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow== 881 | dependencies: 882 | is-glob "^4.0.1" 883 | 884 | glob-to-regexp@^0.4.1: 885 | version "0.4.1" 886 | resolved "https://registry.npmmirror.com/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz#c75297087c851b9a578bd217dd59a92f59fe546e" 887 | integrity sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw== 888 | 889 | glob@7.2.0: 890 | version "7.2.0" 891 | resolved "https://registry.npmmirror.com/glob/-/glob-7.2.0.tgz#d15535af7732e02e948f4c41628bd910293f6023" 892 | integrity sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q== 893 | dependencies: 894 | fs.realpath "^1.0.0" 895 | inflight "^1.0.4" 896 | inherits "2" 897 | minimatch "^3.0.4" 898 | once "^1.3.0" 899 | path-is-absolute "^1.0.0" 900 | 901 | glob@^7.1.3, glob@^7.1.7: 902 | version "7.2.3" 903 | resolved "https://registry.yarnpkg.com/glob/-/glob-7.2.3.tgz#b8df0fb802bbfa8e89bd1d938b4e16578ed44f2b" 904 | integrity sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q== 905 | dependencies: 906 | fs.realpath "^1.0.0" 907 | inflight "^1.0.4" 908 | inherits "2" 909 | minimatch "^3.1.1" 910 | once "^1.3.0" 911 | path-is-absolute "^1.0.0" 912 | 913 | gopd@^1.0.1: 914 | version "1.0.1" 915 | resolved "https://registry.npmmirror.com/gopd/-/gopd-1.0.1.tgz#29ff76de69dac7489b7c0918a5788e56477c332c" 916 | integrity sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA== 917 | dependencies: 918 | get-intrinsic "^1.1.3" 919 | 920 | graceful-fs@^4.1.2, graceful-fs@^4.1.6, graceful-fs@^4.2.0, graceful-fs@^4.2.10, graceful-fs@^4.2.4, graceful-fs@^4.2.6, graceful-fs@^4.2.9: 921 | version "4.2.11" 922 | resolved "https://registry.npmmirror.com/graceful-fs/-/graceful-fs-4.2.11.tgz#4183e4e8bf08bb6e05bbb2f7d2e0c8f712ca40e3" 923 | integrity sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ== 924 | 925 | has-flag@^4.0.0: 926 | version "4.0.0" 927 | resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-4.0.0.tgz#944771fd9c81c81265c4d6941860da06bb59479b" 928 | integrity sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ== 929 | 930 | has-property-descriptors@^1.0.0: 931 | version "1.0.1" 932 | resolved "https://registry.npmmirror.com/has-property-descriptors/-/has-property-descriptors-1.0.1.tgz#52ba30b6c5ec87fd89fa574bc1c39125c6f65340" 933 | integrity sha512-VsX8eaIewvas0xnvinAe9bw4WfIeODpGYikiWYLH+dma0Jw6KHYqWiWfhQlgOVK8D6PvjubK5Uc4P0iIhIcNVg== 934 | dependencies: 935 | get-intrinsic "^1.2.2" 936 | 937 | has-proto@^1.0.1: 938 | version "1.0.1" 939 | resolved "https://registry.npmmirror.com/has-proto/-/has-proto-1.0.1.tgz#1885c1305538958aff469fef37937c22795408e0" 940 | integrity sha512-7qE+iP+O+bgF9clE5+UoBFzE65mlBiVj3tKCrlNQ0Ogwm0BjpT/gK4SlLYDMybDh5I3TCTKnPPa0oMG7JDYrhg== 941 | 942 | has-symbols@^1.0.3: 943 | version "1.0.3" 944 | resolved "https://registry.npmmirror.com/has-symbols/-/has-symbols-1.0.3.tgz#bb7b2c4349251dce87b125f7bdf874aa7c8b39f8" 945 | integrity sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A== 946 | 947 | hasown@^2.0.0: 948 | version "2.0.0" 949 | resolved "https://registry.npmmirror.com/hasown/-/hasown-2.0.0.tgz#f4c513d454a57b7c7e1650778de226b11700546c" 950 | integrity sha512-vUptKVTpIJhcczKBbgnS+RtcuYMB8+oNzPK2/Hp3hanz8JmpATdmmgLgSaadVREkDm+e2giHwY3ZRkyjSIDDFA== 951 | dependencies: 952 | function-bind "^1.1.2" 953 | 954 | he@1.2.0: 955 | version "1.2.0" 956 | resolved "https://registry.npmmirror.com/he/-/he-1.2.0.tgz#84ae65fa7eafb165fddb61566ae14baf05664f0f" 957 | integrity sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw== 958 | 959 | http-errors@2.0.0: 960 | version "2.0.0" 961 | resolved "https://registry.npmmirror.com/http-errors/-/http-errors-2.0.0.tgz#b7774a1486ef73cf7667ac9ae0858c012c57b9d3" 962 | integrity sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ== 963 | dependencies: 964 | depd "2.0.0" 965 | inherits "2.0.4" 966 | setprototypeof "1.2.0" 967 | statuses "2.0.1" 968 | toidentifier "1.0.1" 969 | 970 | http-proxy@^1.18.1: 971 | version "1.18.1" 972 | resolved "https://registry.npmmirror.com/http-proxy/-/http-proxy-1.18.1.tgz#401541f0534884bbf95260334e72f88ee3976549" 973 | integrity sha512-7mz/721AbnJwIVbnaSv1Cz3Am0ZLT/UBwkC92VlxhXv/k/BBQfM2fXElQNC27BVGr0uwUpplYPQM9LnaBMR5NQ== 974 | dependencies: 975 | eventemitter3 "^4.0.0" 976 | follow-redirects "^1.0.0" 977 | requires-port "^1.0.0" 978 | 979 | iconv-lite@0.4.24: 980 | version "0.4.24" 981 | resolved "https://registry.npmmirror.com/iconv-lite/-/iconv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b" 982 | integrity sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA== 983 | dependencies: 984 | safer-buffer ">= 2.1.2 < 3" 985 | 986 | iconv-lite@^0.6.3: 987 | version "0.6.3" 988 | resolved "https://registry.npmmirror.com/iconv-lite/-/iconv-lite-0.6.3.tgz#a52f80bf38da1952eb5c681790719871a1a72501" 989 | integrity sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw== 990 | dependencies: 991 | safer-buffer ">= 2.1.2 < 3.0.0" 992 | 993 | icss-utils@^5.0.0, icss-utils@^5.1.0: 994 | version "5.1.0" 995 | resolved "https://registry.npmmirror.com/icss-utils/-/icss-utils-5.1.0.tgz#c6be6858abd013d768e98366ae47e25d5887b1ae" 996 | integrity sha512-soFhflCVWLfRNOPU3iv5Z9VUdT44xFRbzjLsEzSr5AQmgqPMTHdU3PMT1Cf1ssx8fLNJDA1juftYl+PUcv3MqA== 997 | 998 | immutable@^4.0.0: 999 | version "4.3.4" 1000 | resolved "https://registry.npmmirror.com/immutable/-/immutable-4.3.4.tgz#2e07b33837b4bb7662f288c244d1ced1ef65a78f" 1001 | integrity sha512-fsXeu4J4i6WNWSikpI88v/PcVflZz+6kMhUfIwc5SY+poQRPnaf5V7qds6SUyUN3cVxEzuCab7QIoLOQ+DQ1wA== 1002 | 1003 | import-local@^3.0.2: 1004 | version "3.1.0" 1005 | resolved "https://registry.npmmirror.com/import-local/-/import-local-3.1.0.tgz#b4479df8a5fd44f6cdce24070675676063c95cb4" 1006 | integrity sha512-ASB07uLtnDs1o6EHjKpX34BKYDSqnFerfTOJL2HvMqF70LnxpjkzDB8J44oT9pu4AMPkQwf8jl6szgvNd2tRIg== 1007 | dependencies: 1008 | pkg-dir "^4.2.0" 1009 | resolve-cwd "^3.0.0" 1010 | 1011 | inflight@^1.0.4: 1012 | version "1.0.6" 1013 | resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9" 1014 | integrity sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA== 1015 | dependencies: 1016 | once "^1.3.0" 1017 | wrappy "1" 1018 | 1019 | inherits@2, inherits@2.0.4: 1020 | version "2.0.4" 1021 | resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" 1022 | integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== 1023 | 1024 | interpret@^3.1.1: 1025 | version "3.1.1" 1026 | resolved "https://registry.npmmirror.com/interpret/-/interpret-3.1.1.tgz#5be0ceed67ca79c6c4bc5cf0d7ee843dcea110c4" 1027 | integrity sha512-6xwYfHbajpoF0xLW+iwLkhwgvLoZDfjYfoFNu8ftMoXINzwuymNLd9u/KmwtdT2GbR+/Cz66otEGEVVUHX9QLQ== 1028 | 1029 | is-binary-path@~2.1.0: 1030 | version "2.1.0" 1031 | resolved "https://registry.npmmirror.com/is-binary-path/-/is-binary-path-2.1.0.tgz#ea1f7f3b80f064236e83470f86c09c254fb45b09" 1032 | integrity sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw== 1033 | dependencies: 1034 | binary-extensions "^2.0.0" 1035 | 1036 | is-core-module@^2.13.0: 1037 | version "2.13.1" 1038 | resolved "https://registry.npmmirror.com/is-core-module/-/is-core-module-2.13.1.tgz#ad0d7532c6fea9da1ebdc82742d74525c6273384" 1039 | integrity sha512-hHrIjvZsftOsvKSn2TRYl63zvxsgE0K+0mYMoH6gD4omR5IWB2KynivBQczo3+wF1cCkjzvptnI9Q0sPU66ilw== 1040 | dependencies: 1041 | hasown "^2.0.0" 1042 | 1043 | is-extglob@^2.1.1: 1044 | version "2.1.1" 1045 | resolved "https://registry.npmmirror.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2" 1046 | integrity sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ== 1047 | 1048 | is-fullwidth-code-point@^3.0.0: 1049 | version "3.0.0" 1050 | resolved "https://registry.npmmirror.com/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz#f116f8064fe90b3f7844a38997c0b75051269f1d" 1051 | integrity sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg== 1052 | 1053 | is-glob@^4.0.1, is-glob@~4.0.1: 1054 | version "4.0.3" 1055 | resolved "https://registry.npmmirror.com/is-glob/-/is-glob-4.0.3.tgz#64f61e42cbbb2eec2071a9dac0b28ba1e65d5084" 1056 | integrity sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg== 1057 | dependencies: 1058 | is-extglob "^2.1.1" 1059 | 1060 | is-number@^7.0.0: 1061 | version "7.0.0" 1062 | resolved "https://registry.npmmirror.com/is-number/-/is-number-7.0.0.tgz#7535345b896734d5f80c4d06c50955527a14f12b" 1063 | integrity sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng== 1064 | 1065 | is-plain-obj@^2.1.0: 1066 | version "2.1.0" 1067 | resolved "https://registry.npmmirror.com/is-plain-obj/-/is-plain-obj-2.1.0.tgz#45e42e37fccf1f40da8e5f76ee21515840c09287" 1068 | integrity sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA== 1069 | 1070 | is-plain-object@^2.0.4: 1071 | version "2.0.4" 1072 | resolved "https://registry.npmmirror.com/is-plain-object/-/is-plain-object-2.0.4.tgz#2c163b3fafb1b606d9d17928f05c2a1c38e07677" 1073 | integrity sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og== 1074 | dependencies: 1075 | isobject "^3.0.1" 1076 | 1077 | is-unicode-supported@^0.1.0: 1078 | version "0.1.0" 1079 | resolved "https://registry.npmmirror.com/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz#3f26c76a809593b52bfa2ecb5710ed2779b522a7" 1080 | integrity sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw== 1081 | 1082 | isbinaryfile@^4.0.8: 1083 | version "4.0.10" 1084 | resolved "https://registry.npmmirror.com/isbinaryfile/-/isbinaryfile-4.0.10.tgz#0c5b5e30c2557a2f06febd37b7322946aaee42b3" 1085 | integrity sha512-iHrqe5shvBUcFbmZq9zOQHBoeOhZJu6RQGrDpBgenUm/Am+F3JM2MgQj+rK3Z601fzrL5gLZWtAPH2OBaSVcyw== 1086 | 1087 | isexe@^2.0.0: 1088 | version "2.0.0" 1089 | resolved "https://registry.npmmirror.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" 1090 | integrity sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw== 1091 | 1092 | isobject@^3.0.1: 1093 | version "3.0.1" 1094 | resolved "https://registry.npmmirror.com/isobject/-/isobject-3.0.1.tgz#4e431e92b11a9731636aa1f9c8d1ccbcfdab78df" 1095 | integrity sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg== 1096 | 1097 | jest-worker@^27.4.5: 1098 | version "27.5.1" 1099 | resolved "https://registry.npmmirror.com/jest-worker/-/jest-worker-27.5.1.tgz#8d146f0900e8973b106b6f73cc1e9a8cb86f8db0" 1100 | integrity sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg== 1101 | dependencies: 1102 | "@types/node" "*" 1103 | merge-stream "^2.0.0" 1104 | supports-color "^8.0.0" 1105 | 1106 | js-yaml@4.1.0: 1107 | version "4.1.0" 1108 | resolved "https://registry.npmmirror.com/js-yaml/-/js-yaml-4.1.0.tgz#c1fb65f8f5017901cdd2c951864ba18458a10602" 1109 | integrity sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA== 1110 | dependencies: 1111 | argparse "^2.0.1" 1112 | 1113 | json-parse-even-better-errors@^2.3.1: 1114 | version "2.3.1" 1115 | resolved "https://registry.npmmirror.com/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz#7c47805a94319928e05777405dc12e1f7a4ee02d" 1116 | integrity sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w== 1117 | 1118 | json-schema-traverse@^0.4.1: 1119 | version "0.4.1" 1120 | resolved "https://registry.npmmirror.com/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz#69f6a87d9513ab8bb8fe63bdb0979c448e684660" 1121 | integrity sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg== 1122 | 1123 | jsonfile@^4.0.0: 1124 | version "4.0.0" 1125 | resolved "https://registry.npmmirror.com/jsonfile/-/jsonfile-4.0.0.tgz#8771aae0799b64076b76640fca058f9c10e33ecb" 1126 | integrity sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg== 1127 | optionalDependencies: 1128 | graceful-fs "^4.1.6" 1129 | 1130 | karma-chrome-launcher@3.2.0: 1131 | version "3.2.0" 1132 | resolved "https://registry.npmmirror.com/karma-chrome-launcher/-/karma-chrome-launcher-3.2.0.tgz#eb9c95024f2d6dfbb3748d3415ac9b381906b9a9" 1133 | integrity sha512-rE9RkUPI7I9mAxByQWkGJFXfFD6lE4gC5nPuZdobf/QdTEJI6EU4yIay/cfU/xV4ZxlM5JiTv7zWYgA64NpS5Q== 1134 | dependencies: 1135 | which "^1.2.1" 1136 | 1137 | karma-mocha@2.0.1: 1138 | version "2.0.1" 1139 | resolved "https://registry.npmmirror.com/karma-mocha/-/karma-mocha-2.0.1.tgz#4b0254a18dfee71bdbe6188d9a6861bf86b0cd7d" 1140 | integrity sha512-Tzd5HBjm8his2OA4bouAsATYEpZrp9vC7z5E5j4C5Of5Rrs1jY67RAwXNcVmd/Bnk1wgvQRou0zGVLey44G4tQ== 1141 | dependencies: 1142 | minimist "^1.2.3" 1143 | 1144 | karma-sourcemap-loader@0.4.0: 1145 | version "0.4.0" 1146 | resolved "https://registry.npmmirror.com/karma-sourcemap-loader/-/karma-sourcemap-loader-0.4.0.tgz#b01d73f8f688f533bcc8f5d273d43458e13b5488" 1147 | integrity sha512-xCRL3/pmhAYF3I6qOrcn0uhbQevitc2DERMPH82FMnG+4WReoGcGFZb1pURf2a5apyrOHRdvD+O6K7NljqKHyA== 1148 | dependencies: 1149 | graceful-fs "^4.2.10" 1150 | 1151 | karma-webpack@5.0.0: 1152 | version "5.0.0" 1153 | resolved "https://registry.npmmirror.com/karma-webpack/-/karma-webpack-5.0.0.tgz#2a2c7b80163fe7ffd1010f83f5507f95ef39f840" 1154 | integrity sha512-+54i/cd3/piZuP3dr54+NcFeKOPnys5QeM1IY+0SPASwrtHsliXUiCL50iW+K9WWA7RvamC4macvvQ86l3KtaA== 1155 | dependencies: 1156 | glob "^7.1.3" 1157 | minimatch "^3.0.4" 1158 | webpack-merge "^4.1.5" 1159 | 1160 | karma@6.4.2: 1161 | version "6.4.2" 1162 | resolved "https://registry.npmmirror.com/karma/-/karma-6.4.2.tgz#a983f874cee6f35990c4b2dcc3d274653714de8e" 1163 | integrity sha512-C6SU/53LB31BEgRg+omznBEMY4SjHU3ricV6zBcAe1EeILKkeScr+fZXtaI5WyDbkVowJxxAI6h73NcFPmXolQ== 1164 | dependencies: 1165 | "@colors/colors" "1.5.0" 1166 | body-parser "^1.19.0" 1167 | braces "^3.0.2" 1168 | chokidar "^3.5.1" 1169 | connect "^3.7.0" 1170 | di "^0.0.1" 1171 | dom-serialize "^2.2.1" 1172 | glob "^7.1.7" 1173 | graceful-fs "^4.2.6" 1174 | http-proxy "^1.18.1" 1175 | isbinaryfile "^4.0.8" 1176 | lodash "^4.17.21" 1177 | log4js "^6.4.1" 1178 | mime "^2.5.2" 1179 | minimatch "^3.0.4" 1180 | mkdirp "^0.5.5" 1181 | qjobs "^1.2.0" 1182 | range-parser "^1.2.1" 1183 | rimraf "^3.0.2" 1184 | socket.io "^4.4.1" 1185 | source-map "^0.6.1" 1186 | tmp "^0.2.1" 1187 | ua-parser-js "^0.7.30" 1188 | yargs "^16.1.1" 1189 | 1190 | kind-of@^6.0.2: 1191 | version "6.0.3" 1192 | resolved "https://registry.npmmirror.com/kind-of/-/kind-of-6.0.3.tgz#07c05034a6c349fa06e24fa35aa76db4580ce4dd" 1193 | integrity sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw== 1194 | 1195 | klona@^2.0.6: 1196 | version "2.0.6" 1197 | resolved "https://registry.npmmirror.com/klona/-/klona-2.0.6.tgz#85bffbf819c03b2f53270412420a4555ef882e22" 1198 | integrity sha512-dhG34DXATL5hSxJbIexCft8FChFXtmskoZYnoPWjXQuebWYCNkVeV3KkGegCK9CP1oswI/vQibS2GY7Em/sJJA== 1199 | 1200 | loader-runner@^4.2.0: 1201 | version "4.3.0" 1202 | resolved "https://registry.npmmirror.com/loader-runner/-/loader-runner-4.3.0.tgz#c1b4a163b99f614830353b16755e7149ac2314e1" 1203 | integrity sha512-3R/1M+yS3j5ou80Me59j7F9IMs4PXs3VqRrm0TU3AbKPxlmpoY1TNscJV/oGJXo8qCatFGTfDbY6W6ipGOYXfg== 1204 | 1205 | locate-path@^5.0.0: 1206 | version "5.0.0" 1207 | resolved "https://registry.npmmirror.com/locate-path/-/locate-path-5.0.0.tgz#1afba396afd676a6d42504d0a67a3a7eb9f62aa0" 1208 | integrity sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g== 1209 | dependencies: 1210 | p-locate "^4.1.0" 1211 | 1212 | locate-path@^6.0.0: 1213 | version "6.0.0" 1214 | resolved "https://registry.npmmirror.com/locate-path/-/locate-path-6.0.0.tgz#55321eb309febbc59c4801d931a72452a681d286" 1215 | integrity sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw== 1216 | dependencies: 1217 | p-locate "^5.0.0" 1218 | 1219 | lodash@^4.17.15, lodash@^4.17.21: 1220 | version "4.17.21" 1221 | resolved "https://registry.npmmirror.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c" 1222 | integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg== 1223 | 1224 | log-symbols@4.1.0: 1225 | version "4.1.0" 1226 | resolved "https://registry.npmmirror.com/log-symbols/-/log-symbols-4.1.0.tgz#3fbdbb95b4683ac9fc785111e792e558d4abd503" 1227 | integrity sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg== 1228 | dependencies: 1229 | chalk "^4.1.0" 1230 | is-unicode-supported "^0.1.0" 1231 | 1232 | log4js@^6.4.1: 1233 | version "6.9.1" 1234 | resolved "https://registry.npmmirror.com/log4js/-/log4js-6.9.1.tgz#aba5a3ff4e7872ae34f8b4c533706753709e38b6" 1235 | integrity sha512-1somDdy9sChrr9/f4UlzhdaGfDR2c/SaD2a4T7qEkG4jTS57/B3qmnjLYePwQ8cqWnUHZI0iAKxMBpCZICiZ2g== 1236 | dependencies: 1237 | date-format "^4.0.14" 1238 | debug "^4.3.4" 1239 | flatted "^3.2.7" 1240 | rfdc "^1.3.0" 1241 | streamroller "^3.1.5" 1242 | 1243 | lru-cache@^6.0.0: 1244 | version "6.0.0" 1245 | resolved "https://registry.npmmirror.com/lru-cache/-/lru-cache-6.0.0.tgz#6d6fe6570ebd96aaf90fcad1dafa3b2566db3a94" 1246 | integrity sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA== 1247 | dependencies: 1248 | yallist "^4.0.0" 1249 | 1250 | media-typer@0.3.0: 1251 | version "0.3.0" 1252 | resolved "https://registry.npmmirror.com/media-typer/-/media-typer-0.3.0.tgz#8710d7af0aa626f8fffa1ce00168545263255748" 1253 | integrity sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ== 1254 | 1255 | merge-stream@^2.0.0: 1256 | version "2.0.0" 1257 | resolved "https://registry.yarnpkg.com/merge-stream/-/merge-stream-2.0.0.tgz#52823629a14dd00c9770fb6ad47dc6310f2c1f60" 1258 | integrity sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w== 1259 | 1260 | mime-db@1.52.0: 1261 | version "1.52.0" 1262 | resolved "https://registry.npmmirror.com/mime-db/-/mime-db-1.52.0.tgz#bbabcdc02859f4987301c856e3387ce5ec43bf70" 1263 | integrity sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg== 1264 | 1265 | mime-types@^2.1.27, mime-types@~2.1.24, mime-types@~2.1.34: 1266 | version "2.1.35" 1267 | resolved "https://registry.npmmirror.com/mime-types/-/mime-types-2.1.35.tgz#381a871b62a734450660ae3deee44813f70d959a" 1268 | integrity sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw== 1269 | dependencies: 1270 | mime-db "1.52.0" 1271 | 1272 | mime@^2.5.2: 1273 | version "2.6.0" 1274 | resolved "https://registry.npmmirror.com/mime/-/mime-2.6.0.tgz#a2a682a95cd4d0cb1d6257e28f83da7e35800367" 1275 | integrity sha512-USPkMeET31rOMiarsBNIHZKLGgvKc/LrjofAnBlOttf5ajRvqiRA8QsenbcooctK6d6Ts6aqZXBA+XbkKthiQg== 1276 | 1277 | minimatch@5.0.1: 1278 | version "5.0.1" 1279 | resolved "https://registry.npmmirror.com/minimatch/-/minimatch-5.0.1.tgz#fb9022f7528125187c92bd9e9b6366be1cf3415b" 1280 | integrity sha512-nLDxIFRyhDblz3qMuq+SoRZED4+miJ/G+tdDrjkkkRnjAsBexeGpgjLEQ0blJy7rHhR2b93rhQY4SvyWu9v03g== 1281 | dependencies: 1282 | brace-expansion "^2.0.1" 1283 | 1284 | minimatch@^3.0.4, minimatch@^3.1.1: 1285 | version "3.1.2" 1286 | resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.1.2.tgz#19cd194bfd3e428f049a70817c038d89ab4be35b" 1287 | integrity sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw== 1288 | dependencies: 1289 | brace-expansion "^1.1.7" 1290 | 1291 | minimist@^1.2.3, minimist@^1.2.6: 1292 | version "1.2.8" 1293 | resolved "https://registry.npmmirror.com/minimist/-/minimist-1.2.8.tgz#c1a464e7693302e082a075cee0c057741ac4772c" 1294 | integrity sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA== 1295 | 1296 | mkdirp@^0.5.5: 1297 | version "0.5.6" 1298 | resolved "https://registry.npmmirror.com/mkdirp/-/mkdirp-0.5.6.tgz#7def03d2432dcae4ba1d611445c48396062255f6" 1299 | integrity sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw== 1300 | dependencies: 1301 | minimist "^1.2.6" 1302 | 1303 | mocha@10.2.0: 1304 | version "10.2.0" 1305 | resolved "https://registry.npmmirror.com/mocha/-/mocha-10.2.0.tgz#1fd4a7c32ba5ac372e03a17eef435bd00e5c68b8" 1306 | integrity sha512-IDY7fl/BecMwFHzoqF2sg/SHHANeBoMMXFlS9r0OXKDssYE1M5O43wUY/9BVPeIvfH2zmEbBfseqN9gBQZzXkg== 1307 | dependencies: 1308 | ansi-colors "4.1.1" 1309 | browser-stdout "1.3.1" 1310 | chokidar "3.5.3" 1311 | debug "4.3.4" 1312 | diff "5.0.0" 1313 | escape-string-regexp "4.0.0" 1314 | find-up "5.0.0" 1315 | glob "7.2.0" 1316 | he "1.2.0" 1317 | js-yaml "4.1.0" 1318 | log-symbols "4.1.0" 1319 | minimatch "5.0.1" 1320 | ms "2.1.3" 1321 | nanoid "3.3.3" 1322 | serialize-javascript "6.0.0" 1323 | strip-json-comments "3.1.1" 1324 | supports-color "8.1.1" 1325 | workerpool "6.2.1" 1326 | yargs "16.2.0" 1327 | yargs-parser "20.2.4" 1328 | yargs-unparser "2.0.0" 1329 | 1330 | ms@2.0.0: 1331 | version "2.0.0" 1332 | resolved "https://registry.npmmirror.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8" 1333 | integrity sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A== 1334 | 1335 | ms@2.1.2: 1336 | version "2.1.2" 1337 | resolved "https://registry.npmmirror.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009" 1338 | integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w== 1339 | 1340 | ms@2.1.3: 1341 | version "2.1.3" 1342 | resolved "https://registry.npmmirror.com/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2" 1343 | integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA== 1344 | 1345 | nanoid@3.3.3: 1346 | version "3.3.3" 1347 | resolved "https://registry.npmmirror.com/nanoid/-/nanoid-3.3.3.tgz#fd8e8b7aa761fe807dba2d1b98fb7241bb724a25" 1348 | integrity sha512-p1sjXuopFs0xg+fPASzQ28agW1oHD7xDsd9Xkf3T15H3c/cifrFHVwrh74PdoklAPi+i7MdRsE47vm2r6JoB+w== 1349 | 1350 | nanoid@^3.3.7: 1351 | version "3.3.7" 1352 | resolved "https://registry.npmmirror.com/nanoid/-/nanoid-3.3.7.tgz#d0c301a691bc8d54efa0a2226ccf3fe2fd656bd8" 1353 | integrity sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g== 1354 | 1355 | negotiator@0.6.3: 1356 | version "0.6.3" 1357 | resolved "https://registry.npmmirror.com/negotiator/-/negotiator-0.6.3.tgz#58e323a72fedc0d6f9cd4d31fe49f51479590ccd" 1358 | integrity sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg== 1359 | 1360 | neo-async@^2.6.2: 1361 | version "2.6.2" 1362 | resolved "https://registry.npmmirror.com/neo-async/-/neo-async-2.6.2.tgz#b4aafb93e3aeb2d8174ca53cf163ab7d7308305f" 1363 | integrity sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw== 1364 | 1365 | node-releases@^2.0.14: 1366 | version "2.0.14" 1367 | resolved "https://registry.npmmirror.com/node-releases/-/node-releases-2.0.14.tgz#2ffb053bceb8b2be8495ece1ab6ce600c4461b0b" 1368 | integrity sha512-y10wOWt8yZpqXmOgRo77WaHEmhYQYGNA6y421PKsKYWEK8aW+cqAphborZDhqfyKrbZEN92CN1X2KbafY2s7Yw== 1369 | 1370 | normalize-path@^3.0.0, normalize-path@~3.0.0: 1371 | version "3.0.0" 1372 | resolved "https://registry.npmmirror.com/normalize-path/-/normalize-path-3.0.0.tgz#0dcd69ff23a1c9b11fd0978316644a0388216a65" 1373 | integrity sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA== 1374 | 1375 | object-assign@^4: 1376 | version "4.1.1" 1377 | resolved "https://registry.npmmirror.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863" 1378 | integrity sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg== 1379 | 1380 | object-inspect@^1.9.0: 1381 | version "1.13.1" 1382 | resolved "https://registry.npmmirror.com/object-inspect/-/object-inspect-1.13.1.tgz#b96c6109324ccfef6b12216a956ca4dc2ff94bc2" 1383 | integrity sha512-5qoj1RUiKOMsCCNLV1CBiPYE10sziTsnmNxkAI/rZhiD63CF7IqdFGC/XzjWjpSgLf0LxXX3bDFIh0E18f6UhQ== 1384 | 1385 | on-finished@2.4.1: 1386 | version "2.4.1" 1387 | resolved "https://registry.npmmirror.com/on-finished/-/on-finished-2.4.1.tgz#58c8c44116e54845ad57f14ab10b03533184ac3f" 1388 | integrity sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg== 1389 | dependencies: 1390 | ee-first "1.1.1" 1391 | 1392 | on-finished@~2.3.0: 1393 | version "2.3.0" 1394 | resolved "https://registry.npmmirror.com/on-finished/-/on-finished-2.3.0.tgz#20f1336481b083cd75337992a16971aa2d906947" 1395 | integrity sha512-ikqdkGAAyf/X/gPhXGvfgAytDZtDbr+bkNUJ0N9h5MI/dmdgCs3l6hoHrcUv41sRKew3jIwrp4qQDXiK99Utww== 1396 | dependencies: 1397 | ee-first "1.1.1" 1398 | 1399 | once@^1.3.0: 1400 | version "1.4.0" 1401 | resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" 1402 | integrity sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w== 1403 | dependencies: 1404 | wrappy "1" 1405 | 1406 | p-limit@^2.2.0: 1407 | version "2.3.0" 1408 | resolved "https://registry.npmmirror.com/p-limit/-/p-limit-2.3.0.tgz#3dd33c647a214fdfffd835933eb086da0dc21db1" 1409 | integrity sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w== 1410 | dependencies: 1411 | p-try "^2.0.0" 1412 | 1413 | p-limit@^3.0.2: 1414 | version "3.1.0" 1415 | resolved "https://registry.npmmirror.com/p-limit/-/p-limit-3.1.0.tgz#e1daccbe78d0d1388ca18c64fea38e3e57e3706b" 1416 | integrity sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ== 1417 | dependencies: 1418 | yocto-queue "^0.1.0" 1419 | 1420 | p-locate@^4.1.0: 1421 | version "4.1.0" 1422 | resolved "https://registry.npmmirror.com/p-locate/-/p-locate-4.1.0.tgz#a3428bb7088b3a60292f66919278b7c297ad4f07" 1423 | integrity sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A== 1424 | dependencies: 1425 | p-limit "^2.2.0" 1426 | 1427 | p-locate@^5.0.0: 1428 | version "5.0.0" 1429 | resolved "https://registry.npmmirror.com/p-locate/-/p-locate-5.0.0.tgz#83c8315c6785005e3bd021839411c9e110e6d834" 1430 | integrity sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw== 1431 | dependencies: 1432 | p-limit "^3.0.2" 1433 | 1434 | p-try@^2.0.0: 1435 | version "2.2.0" 1436 | resolved "https://registry.npmmirror.com/p-try/-/p-try-2.2.0.tgz#cb2868540e313d61de58fafbe35ce9004d5540e6" 1437 | integrity sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ== 1438 | 1439 | parseurl@~1.3.3: 1440 | version "1.3.3" 1441 | resolved "https://registry.npmmirror.com/parseurl/-/parseurl-1.3.3.tgz#9da19e7bee8d12dff0513ed5b76957793bc2e8d4" 1442 | integrity sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ== 1443 | 1444 | path-exists@^4.0.0: 1445 | version "4.0.0" 1446 | resolved "https://registry.npmmirror.com/path-exists/-/path-exists-4.0.0.tgz#513bdbe2d3b95d7762e8c1137efa195c6c61b5b3" 1447 | integrity sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w== 1448 | 1449 | path-is-absolute@^1.0.0: 1450 | version "1.0.1" 1451 | resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" 1452 | integrity sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg== 1453 | 1454 | path-key@^3.1.0: 1455 | version "3.1.1" 1456 | resolved "https://registry.npmmirror.com/path-key/-/path-key-3.1.1.tgz#581f6ade658cbba65a0d3380de7753295054f375" 1457 | integrity sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q== 1458 | 1459 | path-parse@^1.0.7: 1460 | version "1.0.7" 1461 | resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.7.tgz#fbc114b60ca42b30d9daf5858e4bd68bbedb6735" 1462 | integrity sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw== 1463 | 1464 | picocolors@^1.0.0: 1465 | version "1.0.0" 1466 | resolved "https://registry.npmmirror.com/picocolors/-/picocolors-1.0.0.tgz#cb5bdc74ff3f51892236eaf79d68bc44564ab81c" 1467 | integrity sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ== 1468 | 1469 | picomatch@^2.0.4, picomatch@^2.2.1: 1470 | version "2.3.1" 1471 | resolved "https://registry.npmmirror.com/picomatch/-/picomatch-2.3.1.tgz#3ba3833733646d9d3e4995946c1365a67fb07a42" 1472 | integrity sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA== 1473 | 1474 | pkg-dir@^4.2.0: 1475 | version "4.2.0" 1476 | resolved "https://registry.npmmirror.com/pkg-dir/-/pkg-dir-4.2.0.tgz#f099133df7ede422e81d1d8448270eeb3e4261f3" 1477 | integrity sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ== 1478 | dependencies: 1479 | find-up "^4.0.0" 1480 | 1481 | postcss-modules-extract-imports@^3.0.0: 1482 | version "3.0.0" 1483 | resolved "https://registry.npmmirror.com/postcss-modules-extract-imports/-/postcss-modules-extract-imports-3.0.0.tgz#cda1f047c0ae80c97dbe28c3e76a43b88025741d" 1484 | integrity sha512-bdHleFnP3kZ4NYDhuGlVK+CMrQ/pqUm8bx/oGL93K6gVwiclvX5x0n76fYMKuIGKzlABOy13zsvqjb0f92TEXw== 1485 | 1486 | postcss-modules-local-by-default@^4.0.0: 1487 | version "4.0.3" 1488 | resolved "https://registry.npmmirror.com/postcss-modules-local-by-default/-/postcss-modules-local-by-default-4.0.3.tgz#b08eb4f083050708998ba2c6061b50c2870ca524" 1489 | integrity sha512-2/u2zraspoACtrbFRnTijMiQtb4GW4BvatjaG/bCjYQo8kLTdevCUlwuBHx2sCnSyrI3x3qj4ZK1j5LQBgzmwA== 1490 | dependencies: 1491 | icss-utils "^5.0.0" 1492 | postcss-selector-parser "^6.0.2" 1493 | postcss-value-parser "^4.1.0" 1494 | 1495 | postcss-modules-scope@^3.0.0: 1496 | version "3.0.0" 1497 | resolved "https://registry.npmmirror.com/postcss-modules-scope/-/postcss-modules-scope-3.0.0.tgz#9ef3151456d3bbfa120ca44898dfca6f2fa01f06" 1498 | integrity sha512-hncihwFA2yPath8oZ15PZqvWGkWf+XUfQgUGamS4LqoP1anQLOsOJw0vr7J7IwLpoY9fatA2qiGUGmuZL0Iqlg== 1499 | dependencies: 1500 | postcss-selector-parser "^6.0.4" 1501 | 1502 | postcss-modules-values@^4.0.0: 1503 | version "4.0.0" 1504 | resolved "https://registry.npmmirror.com/postcss-modules-values/-/postcss-modules-values-4.0.0.tgz#d7c5e7e68c3bb3c9b27cbf48ca0bb3ffb4602c9c" 1505 | integrity sha512-RDxHkAiEGI78gS2ofyvCsu7iycRv7oqw5xMWn9iMoR0N/7mf9D50ecQqUo5BZ9Zh2vH4bCUR/ktCqbB9m8vJjQ== 1506 | dependencies: 1507 | icss-utils "^5.0.0" 1508 | 1509 | postcss-selector-parser@^6.0.2, postcss-selector-parser@^6.0.4: 1510 | version "6.0.13" 1511 | resolved "https://registry.npmmirror.com/postcss-selector-parser/-/postcss-selector-parser-6.0.13.tgz#d05d8d76b1e8e173257ef9d60b706a8e5e99bf1b" 1512 | integrity sha512-EaV1Gl4mUEV4ddhDnv/xtj7sxwrwxdetHdWUGnT4VJQf+4d05v6lHYZr8N573k5Z0BViss7BDhfWtKS3+sfAqQ== 1513 | dependencies: 1514 | cssesc "^3.0.0" 1515 | util-deprecate "^1.0.2" 1516 | 1517 | postcss-value-parser@^4.1.0, postcss-value-parser@^4.2.0: 1518 | version "4.2.0" 1519 | resolved "https://registry.npmmirror.com/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz#723c09920836ba6d3e5af019f92bc0971c02e514" 1520 | integrity sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ== 1521 | 1522 | postcss@^8.4.19: 1523 | version "8.4.32" 1524 | resolved "https://registry.npmmirror.com/postcss/-/postcss-8.4.32.tgz#1dac6ac51ab19adb21b8b34fd2d93a86440ef6c9" 1525 | integrity sha512-D/kj5JNu6oo2EIy+XL/26JEDTlIbB8hw85G8StOE6L74RQAVVP5rej6wxCNqyMbR4RkPfqvezVbPw81Ngd6Kcw== 1526 | dependencies: 1527 | nanoid "^3.3.7" 1528 | picocolors "^1.0.0" 1529 | source-map-js "^1.0.2" 1530 | 1531 | punycode@^2.1.0: 1532 | version "2.3.1" 1533 | resolved "https://registry.npmmirror.com/punycode/-/punycode-2.3.1.tgz#027422e2faec0b25e1549c3e1bd8309b9133b6e5" 1534 | integrity sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg== 1535 | 1536 | qjobs@^1.2.0: 1537 | version "1.2.0" 1538 | resolved "https://registry.npmmirror.com/qjobs/-/qjobs-1.2.0.tgz#c45e9c61800bd087ef88d7e256423bdd49e5d071" 1539 | integrity sha512-8YOJEHtxpySA3fFDyCRxA+UUV+fA+rTWnuWvylOK/NCjhY+b4ocCtmu8TtsWb+mYeU+GCHf/S66KZF/AsteKHg== 1540 | 1541 | qs@6.11.0: 1542 | version "6.11.0" 1543 | resolved "https://registry.npmmirror.com/qs/-/qs-6.11.0.tgz#fd0d963446f7a65e1367e01abd85429453f0c37a" 1544 | integrity sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q== 1545 | dependencies: 1546 | side-channel "^1.0.4" 1547 | 1548 | randombytes@^2.1.0: 1549 | version "2.1.0" 1550 | resolved "https://registry.yarnpkg.com/randombytes/-/randombytes-2.1.0.tgz#df6f84372f0270dc65cdf6291349ab7a473d4f2a" 1551 | integrity sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ== 1552 | dependencies: 1553 | safe-buffer "^5.1.0" 1554 | 1555 | range-parser@^1.2.1: 1556 | version "1.2.1" 1557 | resolved "https://registry.npmmirror.com/range-parser/-/range-parser-1.2.1.tgz#3cf37023d199e1c24d1a55b84800c2f3e6468031" 1558 | integrity sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg== 1559 | 1560 | raw-body@2.5.2: 1561 | version "2.5.2" 1562 | resolved "https://registry.npmmirror.com/raw-body/-/raw-body-2.5.2.tgz#99febd83b90e08975087e8f1f9419a149366b68a" 1563 | integrity sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA== 1564 | dependencies: 1565 | bytes "3.1.2" 1566 | http-errors "2.0.0" 1567 | iconv-lite "0.4.24" 1568 | unpipe "1.0.0" 1569 | 1570 | readdirp@~3.6.0: 1571 | version "3.6.0" 1572 | resolved "https://registry.npmmirror.com/readdirp/-/readdirp-3.6.0.tgz#74a370bd857116e245b29cc97340cd431a02a6c7" 1573 | integrity sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA== 1574 | dependencies: 1575 | picomatch "^2.2.1" 1576 | 1577 | rechoir@^0.8.0: 1578 | version "0.8.0" 1579 | resolved "https://registry.npmmirror.com/rechoir/-/rechoir-0.8.0.tgz#49f866e0d32146142da3ad8f0eff352b3215ff22" 1580 | integrity sha512-/vxpCXddiX8NGfGO/mTafwjq4aFa/71pvamip0++IQk3zG8cbCj0fifNPrjjF1XMXUne91jL9OoxmdykoEtifQ== 1581 | dependencies: 1582 | resolve "^1.20.0" 1583 | 1584 | require-directory@^2.1.1: 1585 | version "2.1.1" 1586 | resolved "https://registry.npmmirror.com/require-directory/-/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42" 1587 | integrity sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q== 1588 | 1589 | requires-port@^1.0.0: 1590 | version "1.0.0" 1591 | resolved "https://registry.npmmirror.com/requires-port/-/requires-port-1.0.0.tgz#925d2601d39ac485e091cf0da5c6e694dc3dcaff" 1592 | integrity sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ== 1593 | 1594 | resolve-cwd@^3.0.0: 1595 | version "3.0.0" 1596 | resolved "https://registry.npmmirror.com/resolve-cwd/-/resolve-cwd-3.0.0.tgz#0f0075f1bb2544766cf73ba6a6e2adfebcb13f2d" 1597 | integrity sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg== 1598 | dependencies: 1599 | resolve-from "^5.0.0" 1600 | 1601 | resolve-from@^5.0.0: 1602 | version "5.0.0" 1603 | resolved "https://registry.npmmirror.com/resolve-from/-/resolve-from-5.0.0.tgz#c35225843df8f776df21c57557bc087e9dfdfc69" 1604 | integrity sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw== 1605 | 1606 | resolve@^1.20.0: 1607 | version "1.22.8" 1608 | resolved "https://registry.npmmirror.com/resolve/-/resolve-1.22.8.tgz#b6c87a9f2aa06dfab52e3d70ac8cde321fa5a48d" 1609 | integrity sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw== 1610 | dependencies: 1611 | is-core-module "^2.13.0" 1612 | path-parse "^1.0.7" 1613 | supports-preserve-symlinks-flag "^1.0.0" 1614 | 1615 | rfdc@^1.3.0: 1616 | version "1.3.0" 1617 | resolved "https://registry.npmmirror.com/rfdc/-/rfdc-1.3.0.tgz#d0b7c441ab2720d05dc4cf26e01c89631d9da08b" 1618 | integrity sha512-V2hovdzFbOi77/WajaSMXk2OLm+xNIeQdMMuB7icj7bk6zi2F8GGAxigcnDFpJHbNyNcgyJDiP+8nOrY5cZGrA== 1619 | 1620 | rimraf@^3.0.0, rimraf@^3.0.2: 1621 | version "3.0.2" 1622 | resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-3.0.2.tgz#f1a5402ba6220ad52cc1282bac1ae3aa49fd061a" 1623 | integrity sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA== 1624 | dependencies: 1625 | glob "^7.1.3" 1626 | 1627 | safe-buffer@^5.1.0: 1628 | version "5.2.1" 1629 | resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6" 1630 | integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ== 1631 | 1632 | "safer-buffer@>= 2.1.2 < 3", "safer-buffer@>= 2.1.2 < 3.0.0": 1633 | version "2.1.2" 1634 | resolved "https://registry.npmmirror.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" 1635 | integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg== 1636 | 1637 | sass-loader@13.2.2: 1638 | version "13.2.2" 1639 | resolved "https://registry.npmmirror.com/sass-loader/-/sass-loader-13.2.2.tgz#f97e803993b24012c10d7ba9676548bf7a6b18b9" 1640 | integrity sha512-nrIdVAAte3B9icfBiGWvmMhT/D+eCDwnk+yA7VE/76dp/WkHX+i44Q/pfo71NYbwj0Ap+PGsn0ekOuU1WFJ2AA== 1641 | dependencies: 1642 | klona "^2.0.6" 1643 | neo-async "^2.6.2" 1644 | 1645 | sass@1.62.1: 1646 | version "1.62.1" 1647 | resolved "https://registry.npmmirror.com/sass/-/sass-1.62.1.tgz#caa8d6bf098935bc92fc73fa169fb3790cacd029" 1648 | integrity sha512-NHpxIzN29MXvWiuswfc1W3I0N8SXBd8UR26WntmDlRYf0bSADnwnOjsyMZ3lMezSlArD33Vs3YFhp7dWvL770A== 1649 | dependencies: 1650 | chokidar ">=3.0.0 <4.0.0" 1651 | immutable "^4.0.0" 1652 | source-map-js ">=0.6.2 <2.0.0" 1653 | 1654 | schema-utils@^3.1.1, schema-utils@^3.1.2: 1655 | version "3.3.0" 1656 | resolved "https://registry.npmmirror.com/schema-utils/-/schema-utils-3.3.0.tgz#f50a88877c3c01652a15b622ae9e9795df7a60fe" 1657 | integrity sha512-pN/yOAvcC+5rQ5nERGuwrjLlYvLTbCibnZ1I7B1LaiAz9BRBlE9GMgE/eqV30P7aJQUf7Ddimy/RsbYO/GrVGg== 1658 | dependencies: 1659 | "@types/json-schema" "^7.0.8" 1660 | ajv "^6.12.5" 1661 | ajv-keywords "^3.5.2" 1662 | 1663 | semver@^7.3.8: 1664 | version "7.5.4" 1665 | resolved "https://registry.npmmirror.com/semver/-/semver-7.5.4.tgz#483986ec4ed38e1c6c48c34894a9182dbff68a6e" 1666 | integrity sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA== 1667 | dependencies: 1668 | lru-cache "^6.0.0" 1669 | 1670 | serialize-javascript@6.0.0: 1671 | version "6.0.0" 1672 | resolved "https://registry.npmmirror.com/serialize-javascript/-/serialize-javascript-6.0.0.tgz#efae5d88f45d7924141da8b5c3a7a7e663fefeb8" 1673 | integrity sha512-Qr3TosvguFt8ePWqsvRfrKyQXIiW+nGbYpy8XK24NQHE83caxWt+mIymTT19DGFbNWNLfEwsrkSmN64lVWB9ag== 1674 | dependencies: 1675 | randombytes "^2.1.0" 1676 | 1677 | serialize-javascript@^6.0.1: 1678 | version "6.0.1" 1679 | resolved "https://registry.npmmirror.com/serialize-javascript/-/serialize-javascript-6.0.1.tgz#b206efb27c3da0b0ab6b52f48d170b7996458e5c" 1680 | integrity sha512-owoXEFjWRllis8/M1Q+Cw5k8ZH40e3zhp/ovX+Xr/vi1qj6QesbyXXViFbpNvWvPNAD62SutwEXavefrLJWj7w== 1681 | dependencies: 1682 | randombytes "^2.1.0" 1683 | 1684 | set-function-length@^1.1.1: 1685 | version "1.1.1" 1686 | resolved "https://registry.npmmirror.com/set-function-length/-/set-function-length-1.1.1.tgz#4bc39fafb0307224a33e106a7d35ca1218d659ed" 1687 | integrity sha512-VoaqjbBJKiWtg4yRcKBQ7g7wnGnLV3M8oLvVWwOk2PdYY6PEFegR1vezXR0tw6fZGF9csVakIRjrJiy2veSBFQ== 1688 | dependencies: 1689 | define-data-property "^1.1.1" 1690 | get-intrinsic "^1.2.1" 1691 | gopd "^1.0.1" 1692 | has-property-descriptors "^1.0.0" 1693 | 1694 | setprototypeof@1.2.0: 1695 | version "1.2.0" 1696 | resolved "https://registry.npmmirror.com/setprototypeof/-/setprototypeof-1.2.0.tgz#66c9a24a73f9fc28cbe66b09fed3d33dcaf1b424" 1697 | integrity sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw== 1698 | 1699 | shallow-clone@^3.0.0: 1700 | version "3.0.1" 1701 | resolved "https://registry.npmmirror.com/shallow-clone/-/shallow-clone-3.0.1.tgz#8f2981ad92531f55035b01fb230769a40e02efa3" 1702 | integrity sha512-/6KqX+GVUdqPuPPd2LxDDxzX6CAbjJehAAOKlNpqqUpAqPM6HeL8f+o3a+JsyGjn2lv0WY8UsTgUJjU9Ok55NA== 1703 | dependencies: 1704 | kind-of "^6.0.2" 1705 | 1706 | shebang-command@^2.0.0: 1707 | version "2.0.0" 1708 | resolved "https://registry.npmmirror.com/shebang-command/-/shebang-command-2.0.0.tgz#ccd0af4f8835fbdc265b82461aaf0c36663f34ea" 1709 | integrity sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA== 1710 | dependencies: 1711 | shebang-regex "^3.0.0" 1712 | 1713 | shebang-regex@^3.0.0: 1714 | version "3.0.0" 1715 | resolved "https://registry.npmmirror.com/shebang-regex/-/shebang-regex-3.0.0.tgz#ae16f1644d873ecad843b0307b143362d4c42172" 1716 | integrity sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A== 1717 | 1718 | side-channel@^1.0.4: 1719 | version "1.0.4" 1720 | resolved "https://registry.npmmirror.com/side-channel/-/side-channel-1.0.4.tgz#efce5c8fdc104ee751b25c58d4290011fa5ea2cf" 1721 | integrity sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw== 1722 | dependencies: 1723 | call-bind "^1.0.0" 1724 | get-intrinsic "^1.0.2" 1725 | object-inspect "^1.9.0" 1726 | 1727 | socket.io-adapter@~2.5.2: 1728 | version "2.5.2" 1729 | resolved "https://registry.npmmirror.com/socket.io-adapter/-/socket.io-adapter-2.5.2.tgz#5de9477c9182fdc171cd8c8364b9a8894ec75d12" 1730 | integrity sha512-87C3LO/NOMc+eMcpcxUBebGjkpMDkNBS9tf7KJqcDsmL936EChtVva71Dw2q4tQcuVC+hAUy4an2NO/sYXmwRA== 1731 | dependencies: 1732 | ws "~8.11.0" 1733 | 1734 | socket.io-parser@~4.2.4: 1735 | version "4.2.4" 1736 | resolved "https://registry.npmmirror.com/socket.io-parser/-/socket.io-parser-4.2.4.tgz#c806966cf7270601e47469ddeec30fbdfda44c83" 1737 | integrity sha512-/GbIKmo8ioc+NIWIhwdecY0ge+qVBSMdgxGygevmdHj24bsfgtCmcUUcQ5ZzcylGFHsN3k4HB4Cgkl96KVnuew== 1738 | dependencies: 1739 | "@socket.io/component-emitter" "~3.1.0" 1740 | debug "~4.3.1" 1741 | 1742 | socket.io@^4.4.1: 1743 | version "4.7.2" 1744 | resolved "https://registry.npmmirror.com/socket.io/-/socket.io-4.7.2.tgz#22557d76c3f3ca48f82e73d68b7add36a22df002" 1745 | integrity sha512-bvKVS29/I5fl2FGLNHuXlQaUH/BlzX1IN6S+NKLNZpBsPZIDH+90eQmCs2Railn4YUiww4SzUedJ6+uzwFnKLw== 1746 | dependencies: 1747 | accepts "~1.3.4" 1748 | base64id "~2.0.0" 1749 | cors "~2.8.5" 1750 | debug "~4.3.2" 1751 | engine.io "~6.5.2" 1752 | socket.io-adapter "~2.5.2" 1753 | socket.io-parser "~4.2.4" 1754 | 1755 | "source-map-js@>=0.6.2 <2.0.0", source-map-js@^1.0.2: 1756 | version "1.0.2" 1757 | resolved "https://registry.npmmirror.com/source-map-js/-/source-map-js-1.0.2.tgz#adbc361d9c62df380125e7f161f71c826f1e490c" 1758 | integrity sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw== 1759 | 1760 | source-map-loader@4.0.1: 1761 | version "4.0.1" 1762 | resolved "https://registry.npmmirror.com/source-map-loader/-/source-map-loader-4.0.1.tgz#72f00d05f5d1f90f80974eda781cbd7107c125f2" 1763 | integrity sha512-oqXpzDIByKONVY8g1NUPOTQhe0UTU5bWUl32GSkqK2LjJj0HmwTMVKxcUip0RgAYhY1mqgOxjbQM48a0mmeNfA== 1764 | dependencies: 1765 | abab "^2.0.6" 1766 | iconv-lite "^0.6.3" 1767 | source-map-js "^1.0.2" 1768 | 1769 | source-map-support@~0.5.20: 1770 | version "0.5.21" 1771 | resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.21.tgz#04fe7c7f9e1ed2d662233c28cb2b35b9f63f6e4f" 1772 | integrity sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w== 1773 | dependencies: 1774 | buffer-from "^1.0.0" 1775 | source-map "^0.6.0" 1776 | 1777 | source-map@^0.6.0, source-map@^0.6.1: 1778 | version "0.6.1" 1779 | resolved "https://registry.npmmirror.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263" 1780 | integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g== 1781 | 1782 | statuses@2.0.1: 1783 | version "2.0.1" 1784 | resolved "https://registry.npmmirror.com/statuses/-/statuses-2.0.1.tgz#55cb000ccf1d48728bd23c685a063998cf1a1b63" 1785 | integrity sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ== 1786 | 1787 | statuses@~1.5.0: 1788 | version "1.5.0" 1789 | resolved "https://registry.npmmirror.com/statuses/-/statuses-1.5.0.tgz#161c7dac177659fd9811f43771fa99381478628c" 1790 | integrity sha512-OpZ3zP+jT1PI7I8nemJX4AKmAX070ZkYPVWV/AaKTJl+tXCTGyVdC1a4SL8RUQYEwk/f34ZX8UTykN68FwrqAA== 1791 | 1792 | streamroller@^3.1.5: 1793 | version "3.1.5" 1794 | resolved "https://registry.npmmirror.com/streamroller/-/streamroller-3.1.5.tgz#1263182329a45def1ffaef58d31b15d13d2ee7ff" 1795 | integrity sha512-KFxaM7XT+irxvdqSP1LGLgNWbYN7ay5owZ3r/8t77p+EtSUAfUgtl7be3xtqtOmGUl9K9YPO2ca8133RlTjvKw== 1796 | dependencies: 1797 | date-format "^4.0.14" 1798 | debug "^4.3.4" 1799 | fs-extra "^8.1.0" 1800 | 1801 | string-width@^4.1.0, string-width@^4.2.0: 1802 | version "4.2.3" 1803 | resolved "https://registry.npmmirror.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" 1804 | integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== 1805 | dependencies: 1806 | emoji-regex "^8.0.0" 1807 | is-fullwidth-code-point "^3.0.0" 1808 | strip-ansi "^6.0.1" 1809 | 1810 | strip-ansi@^6.0.0, strip-ansi@^6.0.1: 1811 | version "6.0.1" 1812 | resolved "https://registry.npmmirror.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" 1813 | integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== 1814 | dependencies: 1815 | ansi-regex "^5.0.1" 1816 | 1817 | strip-json-comments@3.1.1: 1818 | version "3.1.1" 1819 | resolved "https://registry.npmmirror.com/strip-json-comments/-/strip-json-comments-3.1.1.tgz#31f1281b3832630434831c310c01cccda8cbe006" 1820 | integrity sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig== 1821 | 1822 | style-loader@3.3.2: 1823 | version "3.3.2" 1824 | resolved "https://registry.npmmirror.com/style-loader/-/style-loader-3.3.2.tgz#eaebca714d9e462c19aa1e3599057bc363924899" 1825 | integrity sha512-RHs/vcrKdQK8wZliteNK4NKzxvLBzpuHMqYmUVWeKa6MkaIQ97ZTOS0b+zapZhy6GcrgWnvWYCMHRirC3FsUmw== 1826 | 1827 | supports-color@8.1.1, supports-color@^8.0.0: 1828 | version "8.1.1" 1829 | resolved "https://registry.npmmirror.com/supports-color/-/supports-color-8.1.1.tgz#cd6fc17e28500cff56c1b86c0a7fd4a54a73005c" 1830 | integrity sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q== 1831 | dependencies: 1832 | has-flag "^4.0.0" 1833 | 1834 | supports-color@^7.1.0: 1835 | version "7.2.0" 1836 | resolved "https://registry.npmmirror.com/supports-color/-/supports-color-7.2.0.tgz#1b7dcdcb32b8138801b3e478ba6a51caa89648da" 1837 | integrity sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw== 1838 | dependencies: 1839 | has-flag "^4.0.0" 1840 | 1841 | supports-preserve-symlinks-flag@^1.0.0: 1842 | version "1.0.0" 1843 | resolved "https://registry.yarnpkg.com/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz#6eda4bd344a3c94aea376d4cc31bc77311039e09" 1844 | integrity sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w== 1845 | 1846 | tapable@^2.1.1, tapable@^2.2.0: 1847 | version "2.2.1" 1848 | resolved "https://registry.npmmirror.com/tapable/-/tapable-2.2.1.tgz#1967a73ef4060a82f12ab96af86d52fdb76eeca0" 1849 | integrity sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ== 1850 | 1851 | terser-webpack-plugin@^5.3.7: 1852 | version "5.3.9" 1853 | resolved "https://registry.npmmirror.com/terser-webpack-plugin/-/terser-webpack-plugin-5.3.9.tgz#832536999c51b46d468067f9e37662a3b96adfe1" 1854 | integrity sha512-ZuXsqE07EcggTWQjXUj+Aot/OMcD0bMKGgF63f7UxYcu5/AJF53aIpK1YoP5xR9l6s/Hy2b+t1AM0bLNPRuhwA== 1855 | dependencies: 1856 | "@jridgewell/trace-mapping" "^0.3.17" 1857 | jest-worker "^27.4.5" 1858 | schema-utils "^3.1.1" 1859 | serialize-javascript "^6.0.1" 1860 | terser "^5.16.8" 1861 | 1862 | terser@^5.16.8: 1863 | version "5.26.0" 1864 | resolved "https://registry.npmmirror.com/terser/-/terser-5.26.0.tgz#ee9f05d929f4189a9c28a0feb889d96d50126fe1" 1865 | integrity sha512-dytTGoE2oHgbNV9nTzgBEPaqAWvcJNl66VZ0BkJqlvp71IjO8CxdBx/ykCNb47cLnCmCvRZ6ZR0tLkqvZCdVBQ== 1866 | dependencies: 1867 | "@jridgewell/source-map" "^0.3.3" 1868 | acorn "^8.8.2" 1869 | commander "^2.20.0" 1870 | source-map-support "~0.5.20" 1871 | 1872 | tmp@^0.2.1: 1873 | version "0.2.1" 1874 | resolved "https://registry.npmmirror.com/tmp/-/tmp-0.2.1.tgz#8457fc3037dcf4719c251367a1af6500ee1ccf14" 1875 | integrity sha512-76SUhtfqR2Ijn+xllcI5P1oyannHNHByD80W1q447gU3mp9G9PSpGdWmjUOHRDPiHYacIk66W7ubDTuPF3BEtQ== 1876 | dependencies: 1877 | rimraf "^3.0.0" 1878 | 1879 | to-regex-range@^5.0.1: 1880 | version "5.0.1" 1881 | resolved "https://registry.npmmirror.com/to-regex-range/-/to-regex-range-5.0.1.tgz#1648c44aae7c8d988a326018ed72f5b4dd0392e4" 1882 | integrity sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ== 1883 | dependencies: 1884 | is-number "^7.0.0" 1885 | 1886 | toidentifier@1.0.1: 1887 | version "1.0.1" 1888 | resolved "https://registry.npmmirror.com/toidentifier/-/toidentifier-1.0.1.tgz#3be34321a88a820ed1bd80dfaa33e479fbb8dd35" 1889 | integrity sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA== 1890 | 1891 | type-is@~1.6.18: 1892 | version "1.6.18" 1893 | resolved "https://registry.npmmirror.com/type-is/-/type-is-1.6.18.tgz#4e552cd05df09467dcbc4ef739de89f2cf37c131" 1894 | integrity sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g== 1895 | dependencies: 1896 | media-typer "0.3.0" 1897 | mime-types "~2.1.24" 1898 | 1899 | typescript@5.0.4: 1900 | version "5.0.4" 1901 | resolved "https://registry.npmmirror.com/typescript/-/typescript-5.0.4.tgz#b217fd20119bd61a94d4011274e0ab369058da3b" 1902 | integrity sha512-cW9T5W9xY37cc+jfEnaUvX91foxtHkza3Nw3wkoF4sSlKn0MONdkdEndig/qPBWXNkmplh3NzayQzCiHM4/hqw== 1903 | 1904 | ua-parser-js@^0.7.30: 1905 | version "0.7.37" 1906 | resolved "https://registry.npmmirror.com/ua-parser-js/-/ua-parser-js-0.7.37.tgz#e464e66dac2d33a7a1251d7d7a99d6157ec27832" 1907 | integrity sha512-xV8kqRKM+jhMvcHWUKthV9fNebIzrNy//2O9ZwWcfiBFR5f25XVZPLlEajk/sf3Ra15V92isyQqnIEXRDaZWEA== 1908 | 1909 | undici-types@~5.26.4: 1910 | version "5.26.5" 1911 | resolved "https://registry.npmmirror.com/undici-types/-/undici-types-5.26.5.tgz#bcd539893d00b56e964fd2657a4866b221a65617" 1912 | integrity sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA== 1913 | 1914 | universalify@^0.1.0: 1915 | version "0.1.2" 1916 | resolved "https://registry.npmmirror.com/universalify/-/universalify-0.1.2.tgz#b646f69be3942dabcecc9d6639c80dc105efaa66" 1917 | integrity sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg== 1918 | 1919 | unpipe@1.0.0, unpipe@~1.0.0: 1920 | version "1.0.0" 1921 | resolved "https://registry.npmmirror.com/unpipe/-/unpipe-1.0.0.tgz#b2bf4ee8514aae6165b4817829d21b2ef49904ec" 1922 | integrity sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ== 1923 | 1924 | update-browserslist-db@^1.0.13: 1925 | version "1.0.13" 1926 | resolved "https://registry.npmmirror.com/update-browserslist-db/-/update-browserslist-db-1.0.13.tgz#3c5e4f5c083661bd38ef64b6328c26ed6c8248c4" 1927 | integrity sha512-xebP81SNcPuNpPP3uzeW1NYXxI3rxyJzF3pD6sH4jE7o/IX+WtSpwnVU+qIsDPyk0d3hmFQ7mjqc6AtV604hbg== 1928 | dependencies: 1929 | escalade "^3.1.1" 1930 | picocolors "^1.0.0" 1931 | 1932 | uri-js@^4.2.2: 1933 | version "4.4.1" 1934 | resolved "https://registry.npmmirror.com/uri-js/-/uri-js-4.4.1.tgz#9b1a52595225859e55f669d928f88c6c57f2a77e" 1935 | integrity sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg== 1936 | dependencies: 1937 | punycode "^2.1.0" 1938 | 1939 | util-deprecate@^1.0.2: 1940 | version "1.0.2" 1941 | resolved "https://registry.npmmirror.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" 1942 | integrity sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw== 1943 | 1944 | utils-merge@1.0.1: 1945 | version "1.0.1" 1946 | resolved "https://registry.npmmirror.com/utils-merge/-/utils-merge-1.0.1.tgz#9f95710f50a267947b2ccc124741c1028427e713" 1947 | integrity sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA== 1948 | 1949 | vary@^1: 1950 | version "1.1.2" 1951 | resolved "https://registry.npmmirror.com/vary/-/vary-1.1.2.tgz#2299f02c6ded30d4a5961b0b9f74524a18f634fc" 1952 | integrity sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg== 1953 | 1954 | void-elements@^2.0.0: 1955 | version "2.0.1" 1956 | resolved "https://registry.npmmirror.com/void-elements/-/void-elements-2.0.1.tgz#c066afb582bb1cb4128d60ea92392e94d5e9dbec" 1957 | integrity sha512-qZKX4RnBzH2ugr8Lxa7x+0V6XD9Sb/ouARtiasEQCHB1EVU4NXtmHsDDrx1dO4ne5fc3J6EW05BP1Dl0z0iung== 1958 | 1959 | watchpack@^2.4.0: 1960 | version "2.4.0" 1961 | resolved "https://registry.npmmirror.com/watchpack/-/watchpack-2.4.0.tgz#fa33032374962c78113f93c7f2fb4c54c9862a5d" 1962 | integrity sha512-Lcvm7MGST/4fup+ifyKi2hjyIAwcdI4HRgtvTpIUxBRhB+RFtUh8XtDOxUfctVCnhVi+QQj49i91OyvzkJl6cg== 1963 | dependencies: 1964 | glob-to-regexp "^0.4.1" 1965 | graceful-fs "^4.1.2" 1966 | 1967 | webpack-cli@5.1.0: 1968 | version "5.1.0" 1969 | resolved "https://registry.npmmirror.com/webpack-cli/-/webpack-cli-5.1.0.tgz#abc4b1f44b50250f2632d8b8b536cfe2f6257891" 1970 | integrity sha512-a7KRJnCxejFoDpYTOwzm5o21ZXMaNqtRlvS183XzGDUPRdVEzJNImcQokqYZ8BNTnk9DkKiuWxw75+DCCoZ26w== 1971 | dependencies: 1972 | "@discoveryjs/json-ext" "^0.5.0" 1973 | "@webpack-cli/configtest" "^2.1.0" 1974 | "@webpack-cli/info" "^2.0.1" 1975 | "@webpack-cli/serve" "^2.0.3" 1976 | colorette "^2.0.14" 1977 | commander "^10.0.1" 1978 | cross-spawn "^7.0.3" 1979 | envinfo "^7.7.3" 1980 | fastest-levenshtein "^1.0.12" 1981 | import-local "^3.0.2" 1982 | interpret "^3.1.1" 1983 | rechoir "^0.8.0" 1984 | webpack-merge "^5.7.3" 1985 | 1986 | webpack-merge@^4.1.5: 1987 | version "4.2.2" 1988 | resolved "https://registry.npmmirror.com/webpack-merge/-/webpack-merge-4.2.2.tgz#a27c52ea783d1398afd2087f547d7b9d2f43634d" 1989 | integrity sha512-TUE1UGoTX2Cd42j3krGYqObZbOD+xF7u28WB7tfUordytSjbWTIjK/8V0amkBfTYN4/pB/GIDlJZZ657BGG19g== 1990 | dependencies: 1991 | lodash "^4.17.15" 1992 | 1993 | webpack-merge@^5.7.3: 1994 | version "5.10.0" 1995 | resolved "https://registry.npmmirror.com/webpack-merge/-/webpack-merge-5.10.0.tgz#a3ad5d773241e9c682803abf628d4cd62b8a4177" 1996 | integrity sha512-+4zXKdx7UnO+1jaN4l2lHVD+mFvnlZQP/6ljaJVb4SZiwIKeUnrT5l0gkT8z+n4hKpC+jpOv6O9R+gLtag7pSA== 1997 | dependencies: 1998 | clone-deep "^4.0.1" 1999 | flat "^5.0.2" 2000 | wildcard "^2.0.0" 2001 | 2002 | webpack-sources@^3.2.3: 2003 | version "3.2.3" 2004 | resolved "https://registry.npmmirror.com/webpack-sources/-/webpack-sources-3.2.3.tgz#2d4daab8451fd4b240cc27055ff6a0c2ccea0cde" 2005 | integrity sha512-/DyMEOrDgLKKIG0fmvtz+4dUX/3Ghozwgm6iPp8KRhvn+eQf9+Q7GWxVNMk3+uCPWfdXYC4ExGBckIXdFEfH1w== 2006 | 2007 | webpack@5.82.0: 2008 | version "5.82.0" 2009 | resolved "https://registry.npmmirror.com/webpack/-/webpack-5.82.0.tgz#3c0d074dec79401db026b4ba0fb23d6333f88e7d" 2010 | integrity sha512-iGNA2fHhnDcV1bONdUu554eZx+XeldsaeQ8T67H6KKHl2nUSwX8Zm7cmzOA46ox/X1ARxf7Bjv8wQ/HsB5fxBg== 2011 | dependencies: 2012 | "@types/eslint-scope" "^3.7.3" 2013 | "@types/estree" "^1.0.0" 2014 | "@webassemblyjs/ast" "^1.11.5" 2015 | "@webassemblyjs/wasm-edit" "^1.11.5" 2016 | "@webassemblyjs/wasm-parser" "^1.11.5" 2017 | acorn "^8.7.1" 2018 | acorn-import-assertions "^1.7.6" 2019 | browserslist "^4.14.5" 2020 | chrome-trace-event "^1.0.2" 2021 | enhanced-resolve "^5.13.0" 2022 | es-module-lexer "^1.2.1" 2023 | eslint-scope "5.1.1" 2024 | events "^3.2.0" 2025 | glob-to-regexp "^0.4.1" 2026 | graceful-fs "^4.2.9" 2027 | json-parse-even-better-errors "^2.3.1" 2028 | loader-runner "^4.2.0" 2029 | mime-types "^2.1.27" 2030 | neo-async "^2.6.2" 2031 | schema-utils "^3.1.2" 2032 | tapable "^2.1.1" 2033 | terser-webpack-plugin "^5.3.7" 2034 | watchpack "^2.4.0" 2035 | webpack-sources "^3.2.3" 2036 | 2037 | which@^1.2.1: 2038 | version "1.3.1" 2039 | resolved "https://registry.npmmirror.com/which/-/which-1.3.1.tgz#a45043d54f5805316da8d62f9f50918d3da70b0a" 2040 | integrity sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ== 2041 | dependencies: 2042 | isexe "^2.0.0" 2043 | 2044 | which@^2.0.1: 2045 | version "2.0.2" 2046 | resolved "https://registry.npmmirror.com/which/-/which-2.0.2.tgz#7c6a8dd0a636a0327e10b59c9286eee93f3f51b1" 2047 | integrity sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA== 2048 | dependencies: 2049 | isexe "^2.0.0" 2050 | 2051 | wildcard@^2.0.0: 2052 | version "2.0.1" 2053 | resolved "https://registry.npmmirror.com/wildcard/-/wildcard-2.0.1.tgz#5ab10d02487198954836b6349f74fff961e10f67" 2054 | integrity sha512-CC1bOL87PIWSBhDcTrdeLo6eGT7mCFtrg0uIJtqJUFyK+eJnzl8A1niH56uu7KMa5XFrtiV+AQuHO3n7DsHnLQ== 2055 | 2056 | workerpool@6.2.1: 2057 | version "6.2.1" 2058 | resolved "https://registry.npmmirror.com/workerpool/-/workerpool-6.2.1.tgz#46fc150c17d826b86a008e5a4508656777e9c343" 2059 | integrity sha512-ILEIE97kDZvF9Wb9f6h5aXK4swSlKGUcOEGiIYb2OOu/IrDU9iwj0fD//SsA6E5ibwJxpEvhullJY4Sl4GcpAw== 2060 | 2061 | wrap-ansi@^7.0.0: 2062 | version "7.0.0" 2063 | resolved "https://registry.npmmirror.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" 2064 | integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== 2065 | dependencies: 2066 | ansi-styles "^4.0.0" 2067 | string-width "^4.1.0" 2068 | strip-ansi "^6.0.0" 2069 | 2070 | wrappy@1: 2071 | version "1.0.2" 2072 | resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" 2073 | integrity sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ== 2074 | 2075 | ws@~8.11.0: 2076 | version "8.11.0" 2077 | resolved "https://registry.npmmirror.com/ws/-/ws-8.11.0.tgz#6a0d36b8edfd9f96d8b25683db2f8d7de6e8e143" 2078 | integrity sha512-HPG3wQd9sNQoT9xHyNCXoDUa+Xw/VevmY9FoHyQ+g+rrMn4j6FB4np7Z0OhdTgjx6MgQLK7jwSy1YecU1+4Asg== 2079 | 2080 | y18n@^5.0.5: 2081 | version "5.0.8" 2082 | resolved "https://registry.npmmirror.com/y18n/-/y18n-5.0.8.tgz#7f4934d0f7ca8c56f95314939ddcd2dd91ce1d55" 2083 | integrity sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA== 2084 | 2085 | yallist@^4.0.0: 2086 | version "4.0.0" 2087 | resolved "https://registry.npmmirror.com/yallist/-/yallist-4.0.0.tgz#9bb92790d9c0effec63be73519e11a35019a3a72" 2088 | integrity sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A== 2089 | 2090 | yargs-parser@20.2.4: 2091 | version "20.2.4" 2092 | resolved "https://registry.npmmirror.com/yargs-parser/-/yargs-parser-20.2.4.tgz#b42890f14566796f85ae8e3a25290d205f154a54" 2093 | integrity sha512-WOkpgNhPTlE73h4VFAFsOnomJVaovO8VqLDzy5saChRBFQFBoMYirowyW+Q9HB4HFF4Z7VZTiG3iSzJJA29yRA== 2094 | 2095 | yargs-parser@^20.2.2: 2096 | version "20.2.9" 2097 | resolved "https://registry.npmmirror.com/yargs-parser/-/yargs-parser-20.2.9.tgz#2eb7dc3b0289718fc295f362753845c41a0c94ee" 2098 | integrity sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w== 2099 | 2100 | yargs-unparser@2.0.0: 2101 | version "2.0.0" 2102 | resolved "https://registry.npmmirror.com/yargs-unparser/-/yargs-unparser-2.0.0.tgz#f131f9226911ae5d9ad38c432fe809366c2325eb" 2103 | integrity sha512-7pRTIA9Qc1caZ0bZ6RYRGbHJthJWuakf+WmHK0rVeLkNrrGhfoabBNdue6kdINI6r4if7ocq9aD/n7xwKOdzOA== 2104 | dependencies: 2105 | camelcase "^6.0.0" 2106 | decamelize "^4.0.0" 2107 | flat "^5.0.2" 2108 | is-plain-obj "^2.1.0" 2109 | 2110 | yargs@16.2.0, yargs@^16.1.1: 2111 | version "16.2.0" 2112 | resolved "https://registry.npmmirror.com/yargs/-/yargs-16.2.0.tgz#1c82bf0f6b6a66eafce7ef30e376f49a12477f66" 2113 | integrity sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw== 2114 | dependencies: 2115 | cliui "^7.0.2" 2116 | escalade "^3.1.1" 2117 | get-caller-file "^2.0.5" 2118 | require-directory "^2.1.1" 2119 | string-width "^4.2.0" 2120 | y18n "^5.0.5" 2121 | yargs-parser "^20.2.2" 2122 | 2123 | yocto-queue@^0.1.0: 2124 | version "0.1.0" 2125 | resolved "https://registry.npmmirror.com/yocto-queue/-/yocto-queue-0.1.0.tgz#0294eb3dee05028d31ee1a5fa2c556a6aaf10a1b" 2126 | integrity sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q== 2127 | -------------------------------------------------------------------------------- /modules/viform-compose/build.gradle.kts: -------------------------------------------------------------------------------- 1 | plugins { 2 | id(libs.plugins.kotlin.kmp.get().pluginId) 3 | id(libs.plugins.android.library.get().pluginId) 4 | id(libs.plugins.compose.get().pluginId) 5 | id(libs.plugins.kotlin.compose.get().pluginId) 6 | id(libs.plugins.maven.publish.get().pluginId) 7 | } 8 | 9 | android { 10 | namespace = "io.github.windedge.viform.compose" 11 | } 12 | 13 | kotlin { 14 | sourceSets { 15 | val commonMain by getting { 16 | dependencies { 17 | api(project(":modules:viform-core")) 18 | implementation(libs.kotlinx.coroutines.core) 19 | implementation(compose.runtime) 20 | } 21 | } 22 | } 23 | 24 | @OptIn(org.jetbrains.kotlin.gradle.ExperimentalWasmDsl::class) 25 | wasmJs { 26 | browser() 27 | } 28 | } -------------------------------------------------------------------------------- /modules/viform-compose/gradle.properties: -------------------------------------------------------------------------------- 1 | POM_ARTIFACT_ID=viform-compose 2 | POM_NAME=Viform Compose Library 3 | -------------------------------------------------------------------------------- /modules/viform-compose/src/androidMain/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /modules/viform-compose/src/commonMain/kotlin/Composable.kt: -------------------------------------------------------------------------------- 1 | package io.github.windedge.viform.compose 2 | 3 | import androidx.compose.runtime.* 4 | import io.github.windedge.viform.core.* 5 | import kotlinx.coroutines.FlowPreview 6 | import kotlinx.coroutines.flow.* 7 | import kotlin.reflect.* 8 | 9 | @Composable 10 | public fun FormHost.useForm(content: @Composable FormScope.(T) -> Unit) { 11 | val state = this.stateFlow.collectAsState() 12 | FormScope(this).content(state.value) 13 | } 14 | 15 | @Composable 16 | public fun Form.use(content: @Composable FormScope.(T) -> Unit) { 17 | val formHost = DefaultFormHost(this) 18 | formHost.useForm(content) 19 | } 20 | 21 | public class FormScope(private val formHost: FormHost) { 22 | private val form: Form = formHost.form 23 | 24 | public val stateFlow: StateFlow = formHost.stateFlow 25 | 26 | @Composable 27 | public fun field(property: KProperty0): FormField { 28 | return form.getOrRegisterField(property) 29 | } 30 | 31 | @Composable 32 | public inline fun field( 33 | property: KProperty0, noinline content: @Composable FieldScope.() -> Unit 34 | ) { 35 | val wrappedType = typeOf() 36 | field(property).wrapAsType(wrappedType, { it }, { it }, content = content) 37 | } 38 | 39 | @Composable 40 | public inline fun FormField.wrapAs( 41 | noinline wrap: FormField.(V) -> R, 42 | noinline unwrap: FormField.(R) -> V, 43 | noinline constraints: ValidatorContainer.() -> Unit = {}, 44 | noinline content: @Composable FieldScope.() -> Unit, 45 | ) { 46 | val wrappedType = typeOf() 47 | this.wrapAsType(wrappedType, wrap, unwrap, constraints, content) 48 | } 49 | 50 | @Composable 51 | public fun FormField.wrapAsType( 52 | wrappedType: KType, 53 | wrap: FormField.(V) -> R, 54 | unwrap: FormField.(R) -> V, 55 | constraints: ValidatorContainer.() -> Unit = {}, 56 | content: @Composable() (FieldScope.() -> Unit), 57 | ) { 58 | @Suppress("UNCHECKED_CAST") 59 | val wrappedFormField = this as? WrappedFormField ?: remember(this.name) { 60 | WrappedFormField(this, wrappedType, wrap, unwrap).apply { 61 | form.replaceField(this) 62 | applyConstraints(constraints) 63 | } 64 | } 65 | if (wrappedFormField.wrappedType != wrappedType) { 66 | error("Can't wrap as another type!") 67 | } 68 | 69 | DisposableEffect(name) { 70 | onDispose { form.replaceField(wrappedFormField.origin) } 71 | } 72 | 73 | val resultState = this.resultFlow.collectAsState(ValidateResult.None) 74 | val fieldScope: FieldScope = with(wrappedFormField) { 75 | FieldScope( 76 | wrappedState.value, 77 | resultState.value, 78 | ::setWrappedSate, 79 | ::validate, 80 | ::showError, 81 | formHost::pop 82 | ) 83 | } 84 | fieldScope.content() 85 | } 86 | 87 | } 88 | 89 | public class FieldScope( 90 | value: V, 91 | result: ValidateResult, 92 | private val onValueChanged: (V, Boolean) -> Unit, 93 | private val onValidate: () -> Boolean, 94 | private val onShowError: (String) -> Unit, 95 | private val onSubmitted: () -> Unit, 96 | ) { 97 | public val currentValue: V = value 98 | public val hasError: Boolean = result.isError 99 | public val errorMessage: String? = result.errorMessage 100 | 101 | 102 | public fun setValue(value: V, validate: Boolean = false, submit: Boolean = false) { 103 | onValueChanged(value, validate) 104 | if (submit) { 105 | onSubmitted() 106 | } 107 | } 108 | 109 | public fun submit() { 110 | onSubmitted() 111 | } 112 | 113 | public fun validate(): Boolean { 114 | return onValidate() 115 | } 116 | 117 | public fun showError(message: String) { 118 | onShowError(message) 119 | } 120 | 121 | @OptIn(FlowPreview::class) 122 | @Composable 123 | public fun watchLazily(debouncedTimeoutMills: Long = 800, block: (V) -> Unit) { 124 | LaunchedEffect(currentValue) { 125 | snapshotFlow { currentValue }.distinctUntilChanged().debounce(debouncedTimeoutMills).collectLatest { 126 | block(it) 127 | } 128 | } 129 | } 130 | } 131 | 132 | internal class WrappedFormField( 133 | val origin: FormField, 134 | val wrappedType: KType, 135 | val wrap: FormField.(V) -> R, 136 | val unwrap: FormField.(R) -> V 137 | ) : FormField by origin { 138 | 139 | private val wrappedValidators = mutableListOf>() 140 | 141 | private val _wrappedState: MutableState = mutableStateOf(wrap(currentValue)) 142 | val wrappedState: State get() = _wrappedState 143 | 144 | override fun setValue(value: V, validate: Boolean) { 145 | origin.setValue(value, false) 146 | _wrappedState.value = wrap(value) 147 | 148 | if (validate) validate() 149 | } 150 | 151 | override fun validate(): Boolean { 152 | val results = listOf( 153 | origin.getValidators().validateAndGet(unwrap(_wrappedState.value)), 154 | wrappedValidators.validateAndGet(_wrappedState.value) 155 | ) 156 | 157 | return results.find { it.isError }?.also { origin.setResult(it) }?.isSuccess ?: true 158 | } 159 | 160 | fun setWrappedSate(value: R, validate: Boolean = false) { 161 | _wrappedState.value = value 162 | val unwrapValue = unwrap(value) 163 | origin.setValue(unwrapValue, false) 164 | 165 | if (validate) validate() 166 | } 167 | 168 | fun applyConstraints(constraints: ValidatorContainer.() -> Unit) { 169 | val container = SimpleValidatorContainer().apply(constraints) 170 | wrappedValidators.addAll(container.getValidators()) 171 | } 172 | 173 | } 174 | 175 | internal class SimpleValidatorContainer : ValidatorContainer { 176 | private val validators = mutableListOf>() 177 | 178 | override fun addValidator(validator: FieldValidator) { 179 | validators.add(validator) 180 | } 181 | 182 | override fun getValidators(): List> = validators.toList() 183 | override fun clearValidators(): Unit = validators.clear() 184 | 185 | } 186 | 187 | 188 | internal class ValidateException(override val message: String) : Exception(message) -------------------------------------------------------------------------------- /modules/viform-core/build.gradle.kts: -------------------------------------------------------------------------------- 1 | plugins { 2 | id(libs.plugins.kotlin.kmp.get().pluginId) 3 | id(libs.plugins.android.library.get().pluginId) 4 | id(libs.plugins.maven.publish.get().pluginId) 5 | } 6 | 7 | android { 8 | namespace = "io.github.windedge.viform.core" 9 | } 10 | 11 | kotlin { 12 | sourceSets { 13 | val commonMain by getting { 14 | dependencies { 15 | implementation(libs.kotlinx.coroutines.core) 16 | api(libs.kopybuilder.runtime) 17 | } 18 | } 19 | } 20 | 21 | @OptIn(org.jetbrains.kotlin.gradle.ExperimentalWasmDsl::class) 22 | wasmJs { 23 | browser() 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /modules/viform-core/gradle.properties: -------------------------------------------------------------------------------- 1 | POM_ARTIFACT_ID=viform-core 2 | POM_NAME=Viform Core Library 3 | -------------------------------------------------------------------------------- /modules/viform-core/src/androidMain/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /modules/viform-core/src/commonMain/kotlin/io/github.windedge.viform.core/FieldValidator.kt: -------------------------------------------------------------------------------- 1 | package io.github.windedge.viform.core 2 | 3 | 4 | public interface FieldValidator { 5 | public fun preview(input: V): ValidateResult = ValidateResult.None 6 | public fun validate(input: V): ValidateResult = ValidateResult.None 7 | public val errorMessage: String? 8 | } 9 | 10 | public fun List>.validateAndGet(input: V): ValidateResult { 11 | this.map { it.preview(input) }.find { it != ValidateResult.None }?.let { return it } 12 | return this.map { it.validate(input) }.find { it.isError } ?: ValidateResult.Success 13 | } 14 | 15 | public class Nullable(override val errorMessage: String? = null) : FieldValidator { 16 | override fun preview(input: V): ValidateResult { 17 | if (input == null) { 18 | return ValidateResult.Success 19 | } 20 | return ValidateResult.None 21 | } 22 | } 23 | 24 | public abstract class LogicalValidator : FieldValidator { 25 | public abstract fun validateFunc(input: V): ValidateResult 26 | 27 | override fun preview(input: V): ValidateResult = ValidateResult.None 28 | 29 | override fun validate(input: V): ValidateResult = validateFunc(input) 30 | } 31 | 32 | public class Not( 33 | private val validator: FieldValidator, override val errorMessage: String? = null 34 | ) : LogicalValidator() { 35 | 36 | override fun validateFunc(input: V): ValidateResult { 37 | val result = validator.validate(input) 38 | if (result.isSuccess) { 39 | return ValidateResult.Failure(errorMessage ?: "Value: $input do not satisfy the negative validation") 40 | } 41 | return ValidateResult.Success 42 | } 43 | 44 | } 45 | 46 | public class AnyOf( 47 | private vararg val validators: FieldValidator, override val errorMessage: String? = null 48 | ) : LogicalValidator() { 49 | override fun validateFunc(input: V): ValidateResult { 50 | val results = validators.map { it.validate(input) } 51 | val success = results.any { it.isSuccess } 52 | if (success) { 53 | return ValidateResult.Success 54 | } 55 | 56 | return results.first { it.isError } 57 | } 58 | } 59 | 60 | public class AllOf( 61 | private vararg val validators: FieldValidator, override val errorMessage: String? = null 62 | ) : LogicalValidator() { 63 | override fun validateFunc(input: V): ValidateResult { 64 | val results = validators.map { it.validate(input) } 65 | val success = results.all { it.isSuccess } 66 | if (success) { 67 | return ValidateResult.Success 68 | } 69 | 70 | return results.first { it.isError } 71 | } 72 | } 73 | 74 | public class NoneOf( 75 | private vararg val validators: FieldValidator, override val errorMessage: String? = null 76 | ) : LogicalValidator() { 77 | override fun validateFunc(input: V): ValidateResult { 78 | val results = validators.map { it.validate(input) } 79 | val success = results.all { !it.isSuccess } 80 | if (success) { 81 | return ValidateResult.Success 82 | } 83 | 84 | return ValidateResult.Failure(errorMessage ?: "Value: $input do not satisfy all the negative validations") 85 | } 86 | } 87 | 88 | 89 | public class Custom(public val func: (V) -> Boolean, override val errorMessage: String? = null) : FieldValidator { 90 | override fun validate(input: V): ValidateResult { 91 | val success = func(input) 92 | if (success) { 93 | return ValidateResult.Success 94 | } 95 | return ValidateResult.Failure(errorMessage ?: "Validation is failed") 96 | } 97 | } 98 | 99 | public class Required(override val errorMessage: String? = null) : FieldValidator { 100 | override fun validate(input: V): ValidateResult { 101 | if (input == null) { 102 | return ValidateResult.Failure("Value can't be null") 103 | } 104 | if (input is String && input.isEmpty()) { 105 | return ValidateResult.Failure(errorMessage ?: "Should't be empty") 106 | } 107 | return ValidateResult.Success 108 | } 109 | } 110 | 111 | public class Equals(private val value: V, override val errorMessage: String? = null) : FieldValidator { 112 | override fun validate(input: V): ValidateResult { 113 | if (input == value) { 114 | return ValidateResult.Success 115 | } 116 | return ValidateResult.Failure(errorMessage ?: "Should be equals to $value") 117 | } 118 | } 119 | 120 | public class Numeric(override val errorMessage: String? = null) : FieldValidator { 121 | override fun validate(input: String): ValidateResult { 122 | if (input.isNumeric()) { 123 | return ValidateResult.Success 124 | } 125 | return ValidateResult.Failure(errorMessage ?: "Shoud be a number") 126 | } 127 | } 128 | 129 | public class Integer(override val errorMessage: String? = null) : FieldValidator { 130 | override fun validate(input: String): ValidateResult { 131 | if (input.isInt()) { 132 | return ValidateResult.Success 133 | } 134 | return ValidateResult.Failure(errorMessage ?: "Shoud be a integer number") 135 | } 136 | } 137 | 138 | public class Float(override val errorMessage: String? = null) : FieldValidator { 139 | override fun validate(input: String): ValidateResult { 140 | if (input.isFloat()) { 141 | return ValidateResult.Success 142 | } 143 | return ValidateResult.Failure(errorMessage ?: "Shoud be a float number") 144 | } 145 | } 146 | 147 | 148 | public class Checked(override val errorMessage: String? = null) : FieldValidator { 149 | override fun validate(input: Boolean): ValidateResult { 150 | if (input) { 151 | return ValidateResult.Success 152 | } 153 | return ValidateResult.Failure(errorMessage ?: "Should be checked") 154 | } 155 | } 156 | 157 | public class Optional(override val errorMessage: String? = null) : FieldValidator { 158 | override fun preview(input: V): ValidateResult { 159 | if (input.isNullOrEmpty()) { 160 | return ValidateResult.Success 161 | } 162 | return ValidateResult.None 163 | } 164 | } 165 | 166 | public class Blank(override val errorMessage: String?) : FieldValidator { 167 | override fun validate(input: String): ValidateResult { 168 | if (input.isBlank()) { 169 | return ValidateResult.Success 170 | } 171 | return ValidateResult.Failure(errorMessage ?: "Should be blank string") 172 | } 173 | } 174 | 175 | public class NotBlank(override val errorMessage: String?) : FieldValidator { 176 | override fun validate(input: String): ValidateResult { 177 | if (input.isNotBlank()) { 178 | return ValidateResult.Success 179 | } 180 | return ValidateResult.Failure(errorMessage ?: "Should not be blank string") 181 | } 182 | } 183 | 184 | public class Empty(override val errorMessage: String?) : FieldValidator { 185 | override fun validate(input: String): ValidateResult { 186 | if (input.isEmpty()) { 187 | return ValidateResult.Success 188 | } 189 | return ValidateResult.Failure(errorMessage ?: "Should be empty string") 190 | } 191 | } 192 | 193 | public class NotEmpty(override val errorMessage: String?) : FieldValidator { 194 | override fun validate(input: String): ValidateResult { 195 | if (input.isNotEmpty()) { 196 | return ValidateResult.Success 197 | } 198 | return ValidateResult.Failure(errorMessage ?: "Should not be empty string") 199 | } 200 | } 201 | 202 | public class MatchesRegex( 203 | private val regex: Regex, override val errorMessage: String? = null 204 | ) : FieldValidator { 205 | override fun validate(input: String): ValidateResult { 206 | if (input.matches(regex)) { 207 | return ValidateResult.Success 208 | } 209 | return ValidateResult.Failure(errorMessage ?: "`${input}` does not match the specified regular expression") 210 | } 211 | } 212 | 213 | public fun MatchesRegex(regex: String, errorMessage: String? = null): MatchesRegex { 214 | return MatchesRegex(Regex(regex), errorMessage) 215 | } 216 | 217 | public class AlphaNumeric(override val errorMessage: String? = null) : FieldValidator { 218 | override fun validate(input: String): ValidateResult { 219 | if (input.isAlphaNumeric()) { 220 | return ValidateResult.Success 221 | } 222 | return ValidateResult.Failure(errorMessage ?: "Should be an alpha numeric string") 223 | } 224 | } 225 | 226 | public class Url(override val errorMessage: String? = null) : FieldValidator { 227 | override fun validate(input: String): ValidateResult { 228 | if (input.isUrl()) { 229 | return ValidateResult.Success 230 | } 231 | return ValidateResult.Failure(errorMessage ?: "Should be an email") 232 | } 233 | } 234 | 235 | public class Email(override val errorMessage: String? = null) : FieldValidator { 236 | override fun validate(input: String): ValidateResult { 237 | if (input.isEmail()) { 238 | return ValidateResult.Success 239 | } 240 | return ValidateResult.Failure(errorMessage ?: "Should be an email") 241 | } 242 | } 243 | 244 | public class MinLength(private val minLength: Int, override val errorMessage: String? = null) : FieldValidator { 245 | override fun validate(input: String): ValidateResult { 246 | if (input.length < minLength) { 247 | return ValidateResult.Failure("Should be more than $minLength characters") 248 | } 249 | return ValidateResult.Success 250 | } 251 | } 252 | 253 | public class MaxLength(private val maxLength: Int, override val errorMessage: String? = null) : FieldValidator { 254 | override fun validate(input: String): ValidateResult { 255 | if (input.length > maxLength) { 256 | return ValidateResult.Failure("Should be less than $maxLength characters") 257 | } 258 | return ValidateResult.Success 259 | } 260 | } 261 | 262 | public class LengthBetween( 263 | private val minLength: Int, private val maxLength: Int, override val errorMessage: String? = null 264 | ) : FieldValidator { 265 | override fun validate(input: String): ValidateResult { 266 | if (input.length < minLength || input.length > maxLength) { 267 | return ValidateResult.Failure("Should be in $minLength - $maxLength characters") 268 | } 269 | return ValidateResult.Success 270 | } 271 | } 272 | 273 | public class GreaterThan( 274 | private val value: Number, override val errorMessage: String? = null 275 | ) : FieldValidator { 276 | override fun validate(input: V): ValidateResult { 277 | if (input.toDouble() > value.toDouble()) { 278 | return ValidateResult.Success 279 | } 280 | return ValidateResult.Failure(errorMessage ?: "Should be greater than $value") 281 | } 282 | } 283 | 284 | public class GreaterThanOrEquals( 285 | private val value: Number, override val errorMessage: String? = null 286 | ) : FieldValidator { 287 | override fun validate(input: V): ValidateResult { 288 | if (input.toDouble() >= value.toDouble()) { 289 | return ValidateResult.Success 290 | } 291 | return ValidateResult.Failure(errorMessage ?: "Should be greater than or equals to $value") 292 | } 293 | } 294 | 295 | public class LesserThan( 296 | private val value: Number, override val errorMessage: String? = null 297 | ) : FieldValidator { 298 | override fun validate(input: V): ValidateResult { 299 | if (input.toDouble() < value.toDouble()) { 300 | return ValidateResult.Success 301 | } 302 | return ValidateResult.Failure(errorMessage ?: "Should be lesser than $value") 303 | } 304 | } 305 | 306 | public class LesserThanOrEquals( 307 | private val value: Number, override val errorMessage: String? = null 308 | ) : FieldValidator { 309 | override fun validate(input: V): ValidateResult { 310 | if (input.toDouble() <= value.toDouble()) { 311 | return ValidateResult.Success 312 | } 313 | return ValidateResult.Failure(errorMessage ?: "Should be lesser than or equals to $value") 314 | } 315 | } 316 | -------------------------------------------------------------------------------- /modules/viform-core/src/commonMain/kotlin/io/github.windedge.viform.core/Form.kt: -------------------------------------------------------------------------------- 1 | package io.github.windedge.viform.core 2 | 3 | 4 | import io.github.windedge.copybuilder.CopyBuilderHost 5 | import kotlinx.coroutines.sync.Mutex 6 | import kotlin.reflect.* 7 | 8 | 9 | public interface Form { 10 | 11 | public fun getOrRegisterField(property: KProperty): FormField 12 | 13 | public fun getField(name: String): FormField? 14 | 15 | public fun replaceField(formField: FormField): FormField 16 | 17 | public val fields: List> 18 | 19 | public fun validate(): Boolean 20 | 21 | public fun submit(formData: T, validate: Boolean = true): Boolean 22 | 23 | public fun pop(shadowedState: T? = null): T 24 | 25 | public fun reset() 26 | } 27 | 28 | public fun Form(initialState: T): Form { 29 | return FormImpl(initialState) 30 | } 31 | 32 | public fun Form(initialState: T, build: FormBuilder.(T) -> Unit): Form { 33 | val form = FormImpl(initialState) 34 | val builder = FormBuilder(form) 35 | builder.build(initialState) 36 | return form 37 | } 38 | 39 | internal class FormImpl(private val initialState: T) : Form { 40 | private val fieldsMap = mutableMapOf>() 41 | 42 | override val fields: List> get() = fieldsMap.values.toList() 43 | 44 | private fun registerField(property: KProperty): FormField { 45 | if (fieldsMap.containsKey(property.name)) { 46 | error("The field cannot be registered repeatedly, field: ${property.name}") 47 | } 48 | val initialValue = when (property) { 49 | is KProperty0<*> -> (property as KProperty0).get() 50 | is KProperty1<*, *> -> @Suppress("UNCHECKED_CAST") (property as KProperty1).get(initialState) 51 | else -> error("Can't get the value from the property: ${property.name}") 52 | } 53 | val formField = FormFieldImpl(property.name, initialValue) 54 | fieldsMap[property.name] = formField 55 | return formField 56 | } 57 | 58 | override fun getOrRegisterField(property: KProperty): FormField { 59 | if (fieldsMap.containsKey(property.name)) { 60 | @Suppress("UNCHECKED_CAST") 61 | return fieldsMap[property.name] as FormField 62 | } 63 | return registerField(property) 64 | } 65 | 66 | override fun getField(name: String): FormField? { 67 | @Suppress("UNCHECKED_CAST") 68 | return fieldsMap[name] as? FormField 69 | } 70 | 71 | override fun replaceField(formField: FormField): FormField { 72 | if (!fieldsMap.containsKey(formField.name)) { 73 | error("The field is not registered, field: ${formField.name}") 74 | } 75 | 76 | @Suppress("UNCHECKED_CAST") 77 | return fieldsMap.put(formField.name, formField) as FormField 78 | } 79 | 80 | override fun validate(): Boolean { 81 | return fieldsMap.values.map { it.validate() }.all { it } 82 | } 83 | 84 | override fun submit(formData: T, validate: Boolean): Boolean { 85 | @Suppress("UNCHECKED_CAST") 86 | formData as? CopyBuilderHost 87 | ?: error("CopyBuilder is not implemented, please apply the `KopyBuilder` plugin") 88 | 89 | val builder = formData.toCopyBuilder() 90 | fieldsMap.filter { builder.contains(it.key) }.forEach { 91 | @Suppress("UNCHECKED_CAST") 92 | val field = it.value as FormField 93 | val value = builder.get(it.key) 94 | field.setValue(value, false) 95 | } 96 | 97 | if (validate) return validate() 98 | return true 99 | } 100 | 101 | override fun pop(shadowedState: T?): T { 102 | val initialState = shadowedState ?: this.initialState 103 | if (fieldsMap.isEmpty()) return initialState 104 | 105 | @Suppress("UNCHECKED_CAST") 106 | initialState as? CopyBuilderHost 107 | ?: error("CopyBuilder is not implemented, please apply the `KopyBuilder` plugin") 108 | 109 | val result = initialState.copyBuild { 110 | fieldsMap 111 | .filter { contains(it.key) } 112 | .forEach { (name, field) -> 113 | put(name, field.currentValue) 114 | } 115 | } 116 | return result 117 | } 118 | 119 | override fun reset() { 120 | this.submit(this.initialState, validate = false) 121 | } 122 | 123 | } 124 | 125 | 126 | public class FormBuilder(public val form: Form) { 127 | public fun field(property: KProperty1): FormField { 128 | return form.getOrRegisterField(property) 129 | } 130 | 131 | public fun field( 132 | property: KProperty1, 133 | build: FormField.() -> Unit 134 | ): FormField { 135 | val field = form.getOrRegisterField(property) 136 | field.build() 137 | return field 138 | } 139 | 140 | /* 141 | 142 | public fun field(property: KProperty0): FormField { 143 | return form.registerField(property) 144 | } 145 | 146 | public fun field( 147 | property: KProperty0, 148 | build: FormField.() -> Unit 149 | ): FormField { 150 | val field = form.registerField(property) 151 | field.build() 152 | return field 153 | } 154 | */ 155 | } 156 | -------------------------------------------------------------------------------- /modules/viform-core/src/commonMain/kotlin/io/github.windedge.viform.core/FormField.kt: -------------------------------------------------------------------------------- 1 | package io.github.windedge.viform.core 2 | 3 | 4 | import kotlinx.coroutines.flow.* 5 | 6 | public interface FormField : ValidatorContainer { 7 | public val name: String 8 | 9 | public val valueFlow: StateFlow 10 | 11 | public val resultFlow: StateFlow 12 | 13 | public val currentValue: V 14 | 15 | public fun setValue(value: V, validate: Boolean = false) 16 | 17 | public fun setResult(result: ValidateResult) 18 | 19 | public fun showError(message: String) 20 | 21 | public fun validate(): Boolean 22 | } 23 | 24 | public fun FormField(name: String, initialValue: V): FormField { 25 | return FormFieldImpl(name, initialValue) 26 | } 27 | 28 | internal class FormFieldImpl(override val name: String, initialValue: V) : FormField { 29 | private val _valueFlow: MutableStateFlow = MutableStateFlow(initialValue) 30 | override val valueFlow: StateFlow get() = _valueFlow.asStateFlow() 31 | 32 | private val _resultFlow: MutableStateFlow = MutableStateFlow(ValidateResult.None) 33 | override val resultFlow: StateFlow get() = _resultFlow.asStateFlow() 34 | 35 | override val currentValue: V get() = valueFlow.value 36 | 37 | private val validators = mutableListOf>() 38 | 39 | override fun addValidator(validator: FieldValidator) { 40 | validators.add(validator) 41 | } 42 | 43 | override fun clearValidators(): Unit = validators.clear() 44 | 45 | override fun getValidators(): List> = validators.toList() 46 | 47 | override fun setValue(value: V, validate: Boolean) { 48 | _valueFlow.value = value 49 | _resultFlow.value = ValidateResult.None 50 | 51 | if (validate) validate() 52 | } 53 | 54 | override fun setResult(result: ValidateResult) { 55 | _resultFlow.value = result 56 | } 57 | 58 | override fun showError(message: String) { 59 | setResult(ValidateResult.Failure(message)) 60 | } 61 | 62 | override fun validate(): Boolean = 63 | validators.validateAndGet(currentValue).also { _resultFlow.value = it }.isSuccess 64 | } 65 | -------------------------------------------------------------------------------- /modules/viform-core/src/commonMain/kotlin/io/github.windedge.viform.core/FormHost.kt: -------------------------------------------------------------------------------- 1 | package io.github.windedge.viform.core 2 | 3 | 4 | import kotlinx.coroutines.flow.MutableStateFlow 5 | import kotlinx.coroutines.flow.StateFlow 6 | import kotlinx.coroutines.flow.asStateFlow 7 | 8 | public interface FormHost { 9 | 10 | public val form: Form 11 | 12 | public val stateFlow: StateFlow 13 | 14 | public val currentState: T 15 | 16 | public fun submit(formData: T, validate: Boolean = true): Boolean 17 | 18 | public fun validate(): Boolean 19 | 20 | public fun pop(): T 21 | 22 | public fun reset() 23 | } 24 | 25 | public fun FormHost.form(build: FormBuilder.() -> Unit): Form { 26 | val form = FormImpl(currentState) 27 | val builder = FormBuilder(form) 28 | builder.build() 29 | return form 30 | } 31 | 32 | public class DefaultFormHost(override val form: Form) : FormHost { 33 | 34 | private val _stateFlow: MutableStateFlow = MutableStateFlow(form.pop()) 35 | 36 | override val stateFlow: StateFlow get() = _stateFlow.asStateFlow() 37 | 38 | override val currentState: T get() = _stateFlow.value 39 | 40 | override fun submit(formData: T, validate: Boolean): Boolean { 41 | _stateFlow.value = formData 42 | return form.submit(formData, validate) 43 | } 44 | 45 | override fun validate(): Boolean { 46 | return form.validate() 47 | } 48 | 49 | override fun pop(): T { 50 | val newState = form.pop(currentState) 51 | _stateFlow.value = newState 52 | return newState 53 | } 54 | 55 | override fun reset() { 56 | form.reset() 57 | _stateFlow.value = form.pop() 58 | } 59 | 60 | } -------------------------------------------------------------------------------- /modules/viform-core/src/commonMain/kotlin/io/github.windedge.viform.core/FormSchema.kt: -------------------------------------------------------------------------------- 1 | package io.github.windedge.viform.core 2 | 3 | public class FormSchema private constructor(private val builderBlock: FormBuilder.() -> Unit) { 4 | 5 | public companion object { 6 | public fun create(build: FormBuilder.() -> Unit): FormSchema { 7 | val formSchema = FormSchema(build) 8 | return formSchema 9 | } 10 | } 11 | 12 | public fun buildForm(formData: T): Form { 13 | val form = FormImpl(formData).apply { 14 | FormBuilder(this).apply(builderBlock) 15 | } 16 | return form 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /modules/viform-core/src/commonMain/kotlin/io/github.windedge.viform.core/String.kt: -------------------------------------------------------------------------------- 1 | @file:Suppress("unused") 2 | 3 | package io.github.windedge.viform.core 4 | 5 | 6 | internal fun String.isNumeric(): Boolean { 7 | return this.matches(Regex("[+-]?\\d+(\\.\\d+)?")) 8 | } 9 | 10 | internal fun String.isInt(): Boolean { 11 | return this.matches(Regex("[+-]?\\d+")) 12 | } 13 | 14 | internal fun String.isFloat(): Boolean { 15 | return this.matches(Regex("[+-]?\\d+\\.\\d+")) 16 | } 17 | 18 | internal fun String.isEmail(): Boolean { 19 | return this.matches(Regex("^[a-zA-Z0-9_!#$%&’*+/=?`{|}~^-]+(?:\\.[a-zA-Z0-9_!#$%&’*+/=?`{|}~^-]+)*@[a-zA-Z0-9-]+(?:\\.[a-zA-Z0-9-]{2,})*$")) 20 | } 21 | 22 | internal fun String.isUrl(): Boolean { 23 | return this.matches(Regex("^(http|https)://[^\\s$.?#].[^\\s]*$")) 24 | } 25 | 26 | internal fun String.isIPv4(): Boolean { 27 | return this.matches(Regex("^(?:(?:25[0-5]|2[0-4]\\d|[0-1]\\d{2}|[1-9]?\\d)\\.){3}(?:25[0-5]|2[0-4]\\d|[0-1]\\d{2}|[1-9]?\\d)\$")) 28 | } 29 | 30 | internal fun String.isIPv6(): Boolean { 31 | return this.matches(Regex("^(?:[A-F0-9]{1,4}:){7}[A-F0-9]{1,4}\$")) 32 | } 33 | 34 | internal fun String.isHexColor(): Boolean { 35 | return this.matches(Regex("^#?([a-fA-F0-9]{6}|[a-fA-F0-9]{3})\$")) 36 | } 37 | 38 | internal fun String.isHexadecimal(): Boolean { 39 | return this.matches(Regex("^[0-9a-fA-F]+\$")) 40 | } 41 | 42 | internal fun String.isCreditCard(): Boolean { 43 | return this.matches(Regex("^((4\\d{3})|(5[1-5]\\d{2})|(6011)|(7\\d{3}))-?\\d{4}-?\\d{4}-?\\d{4}|3[4,7]\\d{13}\$")) 44 | } 45 | 46 | internal fun String.isAlphaNumeric(): Boolean { 47 | return this.matches(Regex("^[a-zA-Z][a-zA-Z0-9]*$")) 48 | } 49 | 50 | -------------------------------------------------------------------------------- /modules/viform-core/src/commonMain/kotlin/io/github.windedge.viform.core/ValidateResult.kt: -------------------------------------------------------------------------------- 1 | package io.github.windedge.viform.core 2 | 3 | public sealed class ValidateResult { 4 | 5 | public object None : ValidateResult() 6 | 7 | public object Success : ValidateResult() 8 | 9 | public class Failure(public val message: String) : ValidateResult() 10 | 11 | public val isSuccess: Boolean get() = this is None || this is Success 12 | 13 | public val isError: Boolean get() = this is Failure 14 | 15 | public val errorMessage: String? 16 | get() { 17 | if (this is Failure) { 18 | return this.message 19 | } 20 | return null 21 | } 22 | } -------------------------------------------------------------------------------- /modules/viform-core/src/commonMain/kotlin/io/github.windedge.viform.core/ValidatorContainer.kt: -------------------------------------------------------------------------------- 1 | package io.github.windedge.viform.core 2 | 3 | public interface ValidatorContainer { 4 | 5 | public fun addValidator(validator: FieldValidator) 6 | 7 | public fun getValidators(): List> 8 | 9 | public fun clearValidators() 10 | 11 | } 12 | -------------------------------------------------------------------------------- /modules/viform-core/src/commonMain/kotlin/io/github.windedge.viform.core/ValidatorContainerExtension.kt: -------------------------------------------------------------------------------- 1 | package io.github.windedge.viform.core 2 | 3 | public fun ValidatorContainer.addValidator(create: () -> FieldValidator): ValidatorContainer { 4 | val validator = create() 5 | addValidator(validator) 6 | return this 7 | } 8 | 9 | public fun ValidatorContainer.nullable(): ValidatorContainer { 10 | this.addValidator(Nullable()) 11 | @Suppress("UNCHECKED_CAST") 12 | return this as ValidatorContainer 13 | } 14 | 15 | public fun ValidatorContainer.nullable(constrains: ValidatorContainer.() -> ValidatorContainer) { 16 | this.addValidator(Nullable()) 17 | @Suppress("UNCHECKED_CAST") 18 | (this as ValidatorContainer).constrains() 19 | } 20 | 21 | public fun ValidatorContainer.not( 22 | errorMessage: String? = null, 23 | build: () -> FieldValidator 24 | ): ValidatorContainer = 25 | addValidator { Not(build(), errorMessage) } 26 | 27 | public fun ValidatorContainer.anyOf( 28 | errorMessage: String? = null, 29 | vararg validators: FieldValidator 30 | ): ValidatorContainer = 31 | addValidator { AnyOf(*validators, errorMessage = errorMessage) } 32 | 33 | public fun ValidatorContainer.allOf( 34 | errorMessage: String? = null, 35 | validators: Array> 36 | ): ValidatorContainer = 37 | addValidator { AllOf(*validators, errorMessage = errorMessage) } 38 | 39 | public fun ValidatorContainer.noneOf( 40 | errorMessage: String? = null, 41 | vararg validators: FieldValidator 42 | ): ValidatorContainer = 43 | addValidator { NoneOf(*validators, errorMessage = errorMessage) } 44 | 45 | public fun ValidatorContainer.custom( 46 | errorMessage: String? = null, 47 | validation: (V) -> Boolean 48 | ): ValidatorContainer = 49 | addValidator { Custom(validation, errorMessage) } 50 | 51 | public fun ValidatorContainer.required(errorMessage: String? = null): ValidatorContainer = 52 | addValidator { Required(errorMessage) } 53 | 54 | public fun ValidatorContainer.equals(value: V, errorMessage: String? = null): ValidatorContainer = 55 | addValidator { Equals(value, errorMessage) } 56 | 57 | public fun ValidatorContainer.isNumeric(errorMessage: String? = null): ValidatorContainer = 58 | addValidator { Numeric(errorMessage) } 59 | 60 | public fun ValidatorContainer.isInt(errorMessage: String? = null): ValidatorContainer = 61 | addValidator { Integer(errorMessage) } 62 | 63 | public fun ValidatorContainer.isFloat(errorMessage: String? = null): ValidatorContainer = 64 | addValidator { Integer(errorMessage) } 65 | 66 | public fun ValidatorContainer.isChecked(errorMessage: String? = null): ValidatorContainer = 67 | addValidator { Checked(errorMessage) } 68 | 69 | public fun ValidatorContainer.optional(): ValidatorContainer { 70 | addValidator(Optional()) 71 | @Suppress("UNCHECKED_CAST") 72 | return this as ValidatorContainer 73 | } 74 | 75 | public fun ValidatorContainer.optional(constrains: ValidatorContainer.() -> ValidatorContainer): ValidatorContainer { 76 | addValidator(Optional()) 77 | @Suppress("UNCHECKED_CAST") 78 | return (this as ValidatorContainer).constrains() 79 | } 80 | 81 | public fun ValidatorContainer.isBlank(errorMessage: String? = null): ValidatorContainer = 82 | addValidator { Blank(errorMessage) } 83 | 84 | public fun ValidatorContainer.isNotBlank(errorMessage: String? = null): ValidatorContainer = 85 | addValidator { NotBlank(errorMessage) } 86 | 87 | public fun ValidatorContainer.isEmpty(errorMessage: String? = null): ValidatorContainer = 88 | addValidator { Empty(errorMessage) } 89 | 90 | public fun ValidatorContainer.isNotEmpty(errorMessage: String? = null): ValidatorContainer = 91 | addValidator { NotEmpty(errorMessage) } 92 | 93 | public fun ValidatorContainer.matchesRegex( 94 | regex: String, 95 | errorMessage: String? = null 96 | ): ValidatorContainer = 97 | addValidator { MatchesRegex(regex, errorMessage) } 98 | 99 | public fun ValidatorContainer.isAlphaNumeric(errorMessage: String? = null): ValidatorContainer = 100 | addValidator { AlphaNumeric(errorMessage) } 101 | 102 | public fun ValidatorContainer.isUrl(errorMessage: String? = null): ValidatorContainer = 103 | addValidator { Url(errorMessage) } 104 | 105 | public fun ValidatorContainer.isEmail(errorMessage: String? = null): ValidatorContainer = 106 | addValidator { Email(errorMessage) } 107 | 108 | public fun ValidatorContainer.minLength(length: Int, errorMessage: String? = null): ValidatorContainer = 109 | addValidator { MinLength(length, errorMessage) } 110 | 111 | public fun ValidatorContainer.maxLength(length: Int, errorMessage: String? = null): ValidatorContainer = 112 | addValidator { MaxLength(length, errorMessage) } 113 | 114 | public fun ValidatorContainer.lengthBetween( 115 | minLength: Int, maxLength: Int, errorMessage: String? = null 116 | ): ValidatorContainer = addValidator { LengthBetween(minLength, maxLength, errorMessage) } 117 | 118 | public fun ValidatorContainer.greaterThan(value: Number, errMsg: String? = null): ValidatorContainer = 119 | addValidator { GreaterThan(value, errMsg) } 120 | 121 | public fun ValidatorContainer.greaterThanOrEquals( 122 | value: Number, errMsg: String? = null 123 | ): ValidatorContainer = 124 | addValidator { GreaterThanOrEquals(value, errMsg) } 125 | 126 | public fun ValidatorContainer.lesserThan(value: Number, errMsg: String? = null): ValidatorContainer = 127 | addValidator { LesserThan(value, errMsg) } 128 | 129 | public fun ValidatorContainer.lesserThanOrEquals( 130 | value: Number, errMsg: String? = null 131 | ): ValidatorContainer = 132 | addValidator { LesserThanOrEquals(value, errMsg) } 133 | -------------------------------------------------------------------------------- /modules/viform-orbitmvi/build.gradle.kts: -------------------------------------------------------------------------------- 1 | plugins { 2 | id(libs.plugins.kotlin.kmp.get().pluginId) 3 | id(libs.plugins.android.library.get().pluginId) 4 | id(libs.plugins.maven.publish.get().pluginId) 5 | } 6 | 7 | android { 8 | namespace = "io.github.windedge.viform.orbitmvi" 9 | } 10 | 11 | kotlin { 12 | sourceSets { 13 | val commonMain by getting { 14 | dependencies { 15 | api(project(":modules:viform-core")) 16 | implementation(libs.kotlinx.coroutines.core) 17 | api(libs.orbitmvi.core) 18 | } 19 | } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /modules/viform-orbitmvi/gradle.properties: -------------------------------------------------------------------------------- 1 | POM_ARTIFACT_ID=viform-orbitmvi 2 | POM_NAME=Viform OrbitMVI Library 3 | -------------------------------------------------------------------------------- /modules/viform-orbitmvi/src/commonMain/kotlin/FormContainerHost.kt: -------------------------------------------------------------------------------- 1 | package io.github.windedge.viform.mvi 2 | 3 | import io.github.windedge.viform.core.FormHost 4 | import kotlinx.coroutines.flow.StateFlow 5 | import org.orbitmvi.orbit.ContainerHost 6 | import org.orbitmvi.orbit.annotation.OrbitDsl 7 | import org.orbitmvi.orbit.annotation.OrbitInternal 8 | import org.orbitmvi.orbit.syntax.simple.SimpleContext 9 | import org.orbitmvi.orbit.syntax.simple.SimpleSyntax 10 | import org.orbitmvi.orbit.syntax.simple.intent 11 | 12 | 13 | public abstract class FormContainerHost 14 | : ContainerHost, FormHost { 15 | 16 | override val stateFlow: StateFlow get() = container.stateFlow 17 | 18 | override val currentState: STATE get() = container.stateFlow.value 19 | 20 | override fun submit(formData: STATE, validate: Boolean) : Boolean { 21 | intent { reduce { formData } } 22 | return form.submit(formData, validate) 23 | } 24 | 25 | override fun validate(): Boolean = form.validate() 26 | 27 | override fun pop(): STATE { 28 | val state = form.pop(currentState) 29 | intent { reduce { state } } 30 | return state 31 | } 32 | 33 | override fun reset() { 34 | form.reset() 35 | intent { reduce { form.pop() } } 36 | } 37 | 38 | @OptIn(OrbitInternal::class) 39 | @OrbitDsl 40 | public suspend fun SimpleSyntax.reduce( 41 | validate: Boolean = false, 42 | reducer: SimpleContext.() -> STATE 43 | ) { 44 | containerContext.reduce { oldState -> 45 | val newState = SimpleContext(oldState).reducer() 46 | val success = this@FormContainerHost.form.submit(newState, validate) 47 | if (success) newState else oldState 48 | } 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /renovate.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://docs.renovatebot.com/renovate-schema.json", 3 | "extends": [ 4 | "config:base" 5 | ] 6 | } 7 | -------------------------------------------------------------------------------- /sandbox/build.gradle.kts: -------------------------------------------------------------------------------- 1 | description = "Local consumer sandbox" 2 | 3 | subprojects { 4 | repositories { 5 | mavenLocal() 6 | google() 7 | mavenCentral() 8 | maven("https://s01.oss.sonatype.org/content/repositories/snapshots") 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /sandbox/gradle.properties: -------------------------------------------------------------------------------- 1 | # Makes sure we can debug our Kotlin plugin with breakpoints 2 | kotlin.compiler.execution.strategy=in-process 3 | org.gradle.jvmargs=-Xmx3g 4 | kotlin.native.cacheKind=none 5 | kotlin.mpp.androidSourceSetLayoutVersion=2 6 | kotlin.mpp.applyDefaultHierarchyTemplate=false 7 | kotlin.native.useEmbeddableCompilerJar=true 8 | # Enable kotlin/native experimental memory model 9 | kotlin.native.binary.memoryModel=experimental 10 | kotlin.js.ir.output.granularity=whole-program 11 | org.jetbrains.compose.experimental.jscanvas.enabled=true 12 | #Compose for Web is Experimental 13 | org.jetbrains.compose.experimental.wasm.enabled=true 14 | android.useAndroidX=true 15 | android.nonTransitiveRClass=true -------------------------------------------------------------------------------- /sandbox/gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/windedge/viform-multiplatform/d721ad2d3281c1ed16d49639e965f5ff3d2dfb98/sandbox/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /sandbox/gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionBase=GRADLE_USER_HOME 2 | distributionPath=wrapper/dists 3 | distributionUrl=https\://services.gradle.org/distributions/gradle-8.5-bin.zip 4 | networkTimeout=10000 5 | validateDistributionUrl=true 6 | zipStoreBase=GRADLE_USER_HOME 7 | zipStorePath=wrapper/dists 8 | -------------------------------------------------------------------------------- /sandbox/gradlew: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # 4 | # Copyright © 2015-2021 the original authors. 5 | # 6 | # Licensed under the Apache License, Version 2.0 (the "License"); 7 | # you may not use this file except in compliance with the License. 8 | # You may obtain a copy of the License at 9 | # 10 | # https://www.apache.org/licenses/LICENSE-2.0 11 | # 12 | # Unless required by applicable law or agreed to in writing, software 13 | # distributed under the License is distributed on an "AS IS" BASIS, 14 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | # See the License for the specific language governing permissions and 16 | # limitations under the License. 17 | # 18 | 19 | ############################################################################## 20 | # 21 | # Gradle start up script for POSIX generated by Gradle. 22 | # 23 | # Important for running: 24 | # 25 | # (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is 26 | # noncompliant, but you have some other compliant shell such as ksh or 27 | # bash, then to run this script, type that shell name before the whole 28 | # command line, like: 29 | # 30 | # ksh Gradle 31 | # 32 | # Busybox and similar reduced shells will NOT work, because this script 33 | # requires all of these POSIX shell features: 34 | # * functions; 35 | # * expansions «$var», «${var}», «${var:-default}», «${var+SET}», 36 | # «${var#prefix}», «${var%suffix}», and «$( cmd )»; 37 | # * compound commands having a testable exit status, especially «case»; 38 | # * various built-in commands including «command», «set», and «ulimit». 39 | # 40 | # Important for patching: 41 | # 42 | # (2) This script targets any POSIX shell, so it avoids extensions provided 43 | # by Bash, Ksh, etc; in particular arrays are avoided. 44 | # 45 | # The "traditional" practice of packing multiple parameters into a 46 | # space-separated string is a well documented source of bugs and security 47 | # problems, so this is (mostly) avoided, by progressively accumulating 48 | # options in "$@", and eventually passing that to Java. 49 | # 50 | # Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS, 51 | # and GRADLE_OPTS) rely on word-splitting, this is performed explicitly; 52 | # see the in-line comments for details. 53 | # 54 | # There are tweaks for specific operating systems such as AIX, CygWin, 55 | # Darwin, MinGW, and NonStop. 56 | # 57 | # (3) This script is generated from the Groovy template 58 | # https://github.com/gradle/gradle/blob/HEAD/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt 59 | # within the Gradle project. 60 | # 61 | # You can find Gradle at https://github.com/gradle/gradle/. 62 | # 63 | ############################################################################## 64 | 65 | # Attempt to set APP_HOME 66 | 67 | # Resolve links: $0 may be a link 68 | app_path=$0 69 | 70 | # Need this for daisy-chained symlinks. 71 | while 72 | APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path 73 | [ -h "$app_path" ] 74 | do 75 | ls=$( ls -ld "$app_path" ) 76 | link=${ls#*' -> '} 77 | case $link in #( 78 | /*) app_path=$link ;; #( 79 | *) app_path=$APP_HOME$link ;; 80 | esac 81 | done 82 | 83 | # This is normally unused 84 | # shellcheck disable=SC2034 85 | APP_BASE_NAME=${0##*/} 86 | # Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036) 87 | APP_HOME=$( cd "${APP_HOME:-./}" > /dev/null && pwd -P ) || exit 88 | 89 | # Use the maximum available, or set MAX_FD != -1 to use that value. 90 | MAX_FD=maximum 91 | 92 | warn () { 93 | echo "$*" 94 | } >&2 95 | 96 | die () { 97 | echo 98 | echo "$*" 99 | echo 100 | exit 1 101 | } >&2 102 | 103 | # OS specific support (must be 'true' or 'false'). 104 | cygwin=false 105 | msys=false 106 | darwin=false 107 | nonstop=false 108 | case "$( uname )" in #( 109 | CYGWIN* ) cygwin=true ;; #( 110 | Darwin* ) darwin=true ;; #( 111 | MSYS* | MINGW* ) msys=true ;; #( 112 | NONSTOP* ) nonstop=true ;; 113 | esac 114 | 115 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar 116 | 117 | 118 | # Determine the Java command to use to start the JVM. 119 | if [ -n "$JAVA_HOME" ] ; then 120 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then 121 | # IBM's JDK on AIX uses strange locations for the executables 122 | JAVACMD=$JAVA_HOME/jre/sh/java 123 | else 124 | JAVACMD=$JAVA_HOME/bin/java 125 | fi 126 | if [ ! -x "$JAVACMD" ] ; then 127 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME 128 | 129 | Please set the JAVA_HOME variable in your environment to match the 130 | location of your Java installation." 131 | fi 132 | else 133 | JAVACMD=java 134 | if ! command -v java >/dev/null 2>&1 135 | then 136 | die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 137 | 138 | Please set the JAVA_HOME variable in your environment to match the 139 | location of your Java installation." 140 | fi 141 | fi 142 | 143 | # Increase the maximum file descriptors if we can. 144 | if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then 145 | case $MAX_FD in #( 146 | max*) 147 | # In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked. 148 | # shellcheck disable=SC2039,SC3045 149 | MAX_FD=$( ulimit -H -n ) || 150 | warn "Could not query maximum file descriptor limit" 151 | esac 152 | case $MAX_FD in #( 153 | '' | soft) :;; #( 154 | *) 155 | # In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked. 156 | # shellcheck disable=SC2039,SC3045 157 | ulimit -n "$MAX_FD" || 158 | warn "Could not set maximum file descriptor limit to $MAX_FD" 159 | esac 160 | fi 161 | 162 | # Collect all arguments for the java command, stacking in reverse order: 163 | # * args from the command line 164 | # * the main class name 165 | # * -classpath 166 | # * -D...appname settings 167 | # * --module-path (only if needed) 168 | # * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables. 169 | 170 | # For Cygwin or MSYS, switch paths to Windows format before running java 171 | if "$cygwin" || "$msys" ; then 172 | APP_HOME=$( cygpath --path --mixed "$APP_HOME" ) 173 | CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" ) 174 | 175 | JAVACMD=$( cygpath --unix "$JAVACMD" ) 176 | 177 | # Now convert the arguments - kludge to limit ourselves to /bin/sh 178 | for arg do 179 | if 180 | case $arg in #( 181 | -*) false ;; # don't mess with options #( 182 | /?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath 183 | [ -e "$t" ] ;; #( 184 | *) false ;; 185 | esac 186 | then 187 | arg=$( cygpath --path --ignore --mixed "$arg" ) 188 | fi 189 | # Roll the args list around exactly as many times as the number of 190 | # args, so each arg winds up back in the position where it started, but 191 | # possibly modified. 192 | # 193 | # NB: a `for` loop captures its iteration list before it begins, so 194 | # changing the positional parameters here affects neither the number of 195 | # iterations, nor the values presented in `arg`. 196 | shift # remove old arg 197 | set -- "$@" "$arg" # push replacement arg 198 | done 199 | fi 200 | 201 | 202 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 203 | DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' 204 | 205 | # Collect all arguments for the java command: 206 | # * DEFAULT_JVM_OPTS, JAVA_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments, 207 | # and any embedded shellness will be escaped. 208 | # * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be 209 | # treated as '${Hostname}' itself on the command line. 210 | 211 | set -- \ 212 | "-Dorg.gradle.appname=$APP_BASE_NAME" \ 213 | -classpath "$CLASSPATH" \ 214 | org.gradle.wrapper.GradleWrapperMain \ 215 | "$@" 216 | 217 | # Stop when "xargs" is not available. 218 | if ! command -v xargs >/dev/null 2>&1 219 | then 220 | die "xargs is not available" 221 | fi 222 | 223 | # Use "xargs" to parse quoted args. 224 | # 225 | # With -n1 it outputs one arg per line, with the quotes and backslashes removed. 226 | # 227 | # In Bash we could simply go: 228 | # 229 | # readarray ARGS < <( xargs -n1 <<<"$var" ) && 230 | # set -- "${ARGS[@]}" "$@" 231 | # 232 | # but POSIX shell has neither arrays nor command substitution, so instead we 233 | # post-process each arg (as a line of input to sed) to backslash-escape any 234 | # character that might be a shell metacharacter, then use eval to reverse 235 | # that process (while maintaining the separation between arguments), and wrap 236 | # the whole thing up as a single "set" statement. 237 | # 238 | # This will of course break if any of these variables contains a newline or 239 | # an unmatched quote. 240 | # 241 | 242 | eval "set -- $( 243 | printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" | 244 | xargs -n1 | 245 | sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' | 246 | tr '\n' ' ' 247 | )" '"$@"' 248 | 249 | exec "$JAVACMD" "$@" 250 | -------------------------------------------------------------------------------- /sandbox/gradlew.bat: -------------------------------------------------------------------------------- 1 | @rem 2 | @rem Copyright 2015 the original author or authors. 3 | @rem 4 | @rem Licensed under the Apache License, Version 2.0 (the "License"); 5 | @rem you may not use this file except in compliance with the License. 6 | @rem You may obtain a copy of the License at 7 | @rem 8 | @rem https://www.apache.org/licenses/LICENSE-2.0 9 | @rem 10 | @rem Unless required by applicable law or agreed to in writing, software 11 | @rem distributed under the License is distributed on an "AS IS" BASIS, 12 | @rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | @rem See the License for the specific language governing permissions and 14 | @rem limitations under the License. 15 | @rem 16 | 17 | @if "%DEBUG%"=="" @echo off 18 | @rem ########################################################################## 19 | @rem 20 | @rem Gradle startup script for Windows 21 | @rem 22 | @rem ########################################################################## 23 | 24 | @rem Set local scope for the variables with windows NT shell 25 | if "%OS%"=="Windows_NT" setlocal 26 | 27 | set DIRNAME=%~dp0 28 | if "%DIRNAME%"=="" set DIRNAME=. 29 | @rem This is normally unused 30 | set APP_BASE_NAME=%~n0 31 | set APP_HOME=%DIRNAME% 32 | 33 | @rem Resolve any "." and ".." in APP_HOME to make it shorter. 34 | for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi 35 | 36 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 37 | set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" 38 | 39 | @rem Find java.exe 40 | if defined JAVA_HOME goto findJavaFromJavaHome 41 | 42 | set JAVA_EXE=java.exe 43 | %JAVA_EXE% -version >NUL 2>&1 44 | if %ERRORLEVEL% equ 0 goto execute 45 | 46 | echo. 47 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 48 | echo. 49 | echo Please set the JAVA_HOME variable in your environment to match the 50 | echo location of your Java installation. 51 | 52 | goto fail 53 | 54 | :findJavaFromJavaHome 55 | set JAVA_HOME=%JAVA_HOME:"=% 56 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 57 | 58 | if exist "%JAVA_EXE%" goto execute 59 | 60 | echo. 61 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 62 | echo. 63 | echo Please set the JAVA_HOME variable in your environment to match the 64 | echo location of your Java installation. 65 | 66 | goto fail 67 | 68 | :execute 69 | @rem Setup the command line 70 | 71 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 72 | 73 | 74 | @rem Execute Gradle 75 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* 76 | 77 | :end 78 | @rem End local scope for the variables with windows NT shell 79 | if %ERRORLEVEL% equ 0 goto mainEnd 80 | 81 | :fail 82 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 83 | rem the _cmd.exe /c_ return code! 84 | set EXIT_CODE=%ERRORLEVEL% 85 | if %EXIT_CODE% equ 0 set EXIT_CODE=1 86 | if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE% 87 | exit /b %EXIT_CODE% 88 | 89 | :mainEnd 90 | if "%OS%"=="Windows_NT" endlocal 91 | 92 | :omega 93 | -------------------------------------------------------------------------------- /sandbox/settings.gradle.kts: -------------------------------------------------------------------------------- 1 | pluginManagement { 2 | repositories { 3 | mavenLocal() 4 | gradlePluginPortal() 5 | google() 6 | mavenCentral() 7 | maven("https://s01.oss.sonatype.org/content/repositories/snapshots") 8 | } 9 | } 10 | 11 | dependencyResolutionManagement { 12 | versionCatalogs { 13 | create("libs") { 14 | from(files("../gradle/libs.versions.toml")) 15 | } 16 | } 17 | } 18 | 19 | 20 | includeBuild("../") { 21 | 22 | dependencySubstitution { 23 | val group = "io.github.windedge.viform" 24 | substitute(module("$group:viform-core")).using(project(":modules:viform-core")) 25 | substitute(module("$group:viform-compose")).using(project(":modules:viform-compose")) 26 | substitute(module("$group:viform-orbitmvi")).using(project(":modules:viform-orbitmvi")) 27 | } 28 | } 29 | 30 | include( 31 | ":signupapp" 32 | ) -------------------------------------------------------------------------------- /sandbox/signupapp/build.gradle.kts: -------------------------------------------------------------------------------- 1 | @file:OptIn(org.jetbrains.kotlin.gradle.ExperimentalWasmDsl::class) 2 | 3 | plugins { 4 | alias(libs.plugins.kotlin.kmp) 5 | alias(libs.plugins.compose) 6 | alias(libs.plugins.kotlin.compose) 7 | alias(libs.plugins.android.application) 8 | alias(libs.plugins.kopybuilder) 9 | } 10 | 11 | kotlin { 12 | jvmToolchain(17) 13 | 14 | androidTarget("android") { 15 | compilations.all { 16 | kotlinOptions { 17 | jvmTarget = "17" 18 | } 19 | } 20 | } 21 | 22 | jvm("desktop") 23 | 24 | wasmJs { 25 | browser() 26 | binaries.executable() 27 | } 28 | 29 | sourceSets { 30 | all { 31 | languageSettings { 32 | optIn("org.jetbrains.compose.resources.ExperimentalResourceApi") 33 | } 34 | } 35 | 36 | val commonMain by getting { 37 | dependencies { 38 | implementation(libs.kotlinx.coroutines.core) 39 | 40 | implementation(compose.runtime) 41 | implementation(compose.foundation) 42 | implementation(compose.material) 43 | implementation(compose.ui) 44 | @OptIn(org.jetbrains.compose.ExperimentalComposeLibrary::class) 45 | api(compose.components.resources) 46 | 47 | implementation(libs.viform.core) 48 | implementation(libs.viform.compose) 49 | } 50 | } 51 | val androidMain by getting { 52 | dependsOn(commonMain) 53 | 54 | dependencies { 55 | implementation(compose.uiTooling) 56 | implementation(libs.androidx.activity.compose) 57 | } 58 | } 59 | val desktopMain by getting { 60 | dependsOn(commonMain) 61 | 62 | dependencies { 63 | implementation(compose.desktop.currentOs) 64 | } 65 | } 66 | val wasmJsMain by getting { 67 | dependsOn(commonMain) 68 | } 69 | } 70 | } 71 | 72 | compose { 73 | desktop { 74 | application { 75 | mainClass = "local.sandbox.signupapp.MainKt" 76 | } 77 | } 78 | } 79 | 80 | android { 81 | namespace = "local.sandbox.signupapp" 82 | compileSdk = 35 83 | sourceSets["main"].manifest.srcFile("src/androidMain/AndroidManifest.xml") 84 | sourceSets["main"].res.srcDirs("src/androidMain/res") 85 | sourceSets["main"].resources.srcDirs("src/androidMain/resources") 86 | 87 | defaultConfig { 88 | applicationId = "local.sandbox.signupapp" 89 | minSdk = 24 90 | targetSdk = 35 91 | versionCode = 1 92 | versionName = "1.0" 93 | testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner" 94 | } 95 | buildTypes { 96 | getByName("release") { 97 | isMinifyEnabled = true 98 | signingConfig = signingConfigs.getByName("debug") 99 | } 100 | getByName("debug") { 101 | isMinifyEnabled = false 102 | } 103 | } 104 | compileOptions { 105 | sourceCompatibility = JavaVersion.VERSION_17 106 | targetCompatibility = JavaVersion.VERSION_17 107 | } 108 | composeOptions { 109 | kotlinCompilerExtensionVersion = libs.versions.compose.get() 110 | } 111 | } -------------------------------------------------------------------------------- /sandbox/signupapp/src/androidMain/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /sandbox/signupapp/src/androidMain/kotlin/MainActivity.kt: -------------------------------------------------------------------------------- 1 | package local.sandbox.signupapp 2 | 3 | import android.os.Bundle 4 | import androidx.activity.ComponentActivity 5 | import androidx.activity.compose.setContent 6 | import androidx.compose.runtime.Composable 7 | import androidx.compose.ui.tooling.preview.Preview 8 | 9 | class MainActivity : ComponentActivity() { 10 | override fun onCreate(savedInstanceState: Bundle?) { 11 | super.onCreate(savedInstanceState) 12 | 13 | setContent { 14 | SignupApp() 15 | } 16 | } 17 | } 18 | 19 | @Preview 20 | @Composable 21 | fun AppAndroidPreview() { 22 | SignupApp() 23 | } -------------------------------------------------------------------------------- /sandbox/signupapp/src/androidMain/res/drawable-v24/ic_launcher_foreground.xml: -------------------------------------------------------------------------------- 1 | 7 | 8 | 9 | 15 | 18 | 21 | 22 | 23 | 24 | 30 | -------------------------------------------------------------------------------- /sandbox/signupapp/src/androidMain/res/drawable/ic_launcher_background.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 10 | 15 | 20 | 25 | 30 | 35 | 40 | 45 | 50 | 55 | 60 | 65 | 70 | 75 | 80 | 85 | 90 | 95 | 100 | 105 | 110 | 115 | 120 | 125 | 130 | 135 | 140 | 145 | 150 | 155 | 160 | 165 | 170 | 171 | -------------------------------------------------------------------------------- /sandbox/signupapp/src/androidMain/res/mipmap-anydpi-v26/ic_launcher.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /sandbox/signupapp/src/androidMain/res/mipmap-anydpi-v26/ic_launcher_round.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /sandbox/signupapp/src/androidMain/res/mipmap-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/windedge/viform-multiplatform/d721ad2d3281c1ed16d49639e965f5ff3d2dfb98/sandbox/signupapp/src/androidMain/res/mipmap-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /sandbox/signupapp/src/androidMain/res/mipmap-hdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/windedge/viform-multiplatform/d721ad2d3281c1ed16d49639e965f5ff3d2dfb98/sandbox/signupapp/src/androidMain/res/mipmap-hdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /sandbox/signupapp/src/androidMain/res/mipmap-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/windedge/viform-multiplatform/d721ad2d3281c1ed16d49639e965f5ff3d2dfb98/sandbox/signupapp/src/androidMain/res/mipmap-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /sandbox/signupapp/src/androidMain/res/mipmap-mdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/windedge/viform-multiplatform/d721ad2d3281c1ed16d49639e965f5ff3d2dfb98/sandbox/signupapp/src/androidMain/res/mipmap-mdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /sandbox/signupapp/src/androidMain/res/mipmap-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/windedge/viform-multiplatform/d721ad2d3281c1ed16d49639e965f5ff3d2dfb98/sandbox/signupapp/src/androidMain/res/mipmap-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /sandbox/signupapp/src/androidMain/res/mipmap-xhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/windedge/viform-multiplatform/d721ad2d3281c1ed16d49639e965f5ff3d2dfb98/sandbox/signupapp/src/androidMain/res/mipmap-xhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /sandbox/signupapp/src/androidMain/res/mipmap-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/windedge/viform-multiplatform/d721ad2d3281c1ed16d49639e965f5ff3d2dfb98/sandbox/signupapp/src/androidMain/res/mipmap-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /sandbox/signupapp/src/androidMain/res/mipmap-xxhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/windedge/viform-multiplatform/d721ad2d3281c1ed16d49639e965f5ff3d2dfb98/sandbox/signupapp/src/androidMain/res/mipmap-xxhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /sandbox/signupapp/src/androidMain/res/mipmap-xxxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/windedge/viform-multiplatform/d721ad2d3281c1ed16d49639e965f5ff3d2dfb98/sandbox/signupapp/src/androidMain/res/mipmap-xxxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /sandbox/signupapp/src/androidMain/res/mipmap-xxxhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/windedge/viform-multiplatform/d721ad2d3281c1ed16d49639e965f5ff3d2dfb98/sandbox/signupapp/src/androidMain/res/mipmap-xxxhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /sandbox/signupapp/src/androidMain/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | Signup 3 | -------------------------------------------------------------------------------- /sandbox/signupapp/src/commonMain/kotlin/Signup.kt: -------------------------------------------------------------------------------- 1 | package local.sandbox.signupapp 2 | 3 | import io.github.windedge.copybuilder.KopyBuilder 4 | import io.github.windedge.viform.core.* 5 | 6 | @KopyBuilder 7 | data class Signup( 8 | val name: String = "", 9 | val email: String? = null, 10 | val age: Int? = null, 11 | val password: String = "", 12 | val confirmPassword: String = "", 13 | val accept: Boolean = false, 14 | ) 15 | -------------------------------------------------------------------------------- /sandbox/signupapp/src/commonMain/kotlin/SignupApp.kt: -------------------------------------------------------------------------------- 1 | package local.sandbox.signupapp 2 | 3 | import androidx.compose.foundation.clickable 4 | import androidx.compose.foundation.layout.* 5 | import androidx.compose.foundation.rememberScrollState 6 | import androidx.compose.foundation.verticalScroll 7 | import androidx.compose.material.* 8 | import androidx.compose.runtime.* 9 | import androidx.compose.ui.Alignment 10 | import androidx.compose.ui.Modifier 11 | import androidx.compose.ui.composed 12 | import androidx.compose.ui.focus.FocusDirection 13 | import androidx.compose.ui.graphics.Color 14 | import androidx.compose.ui.input.key.* 15 | import androidx.compose.ui.platform.LocalFocusManager 16 | import androidx.compose.ui.text.input.PasswordVisualTransformation 17 | import androidx.compose.ui.text.input.VisualTransformation 18 | import androidx.compose.ui.unit.dp 19 | import io.github.windedge.viform.compose.use 20 | import io.github.windedge.viform.core.* 21 | 22 | val schema = FormSchema.create { 23 | field(Signup::name) { 24 | required("User name is required.") 25 | } 26 | field(Signup::email).optional { 27 | isEmail() 28 | } 29 | field(Signup::age).nullable { 30 | greaterThan(0) 31 | } 32 | 33 | // chained style 34 | field(Signup::password).required().lengthBetween(8, 20) 35 | 36 | //custom rule 37 | field(Signup::confirmPassword).required().lengthBetween(8, 20) 38 | .custom("Passwords must be the same.") { 39 | it == field(Signup::password).currentValue 40 | } 41 | 42 | field(Signup::accept) { 43 | isChecked("Your must accept the terms of agreement.") 44 | } 45 | } 46 | 47 | @Composable 48 | fun SignupApp() { 49 | val form = schema.buildForm(Signup()) 50 | form.use { 51 | Column( 52 | horizontalAlignment = Alignment.CenterHorizontally, 53 | modifier = Modifier.fillMaxSize().padding(horizontal = 10.dp, vertical = 20.dp) 54 | .verticalScroll(rememberScrollState()) 55 | ) { 56 | Surface(elevation = 5.dp) { 57 | Column(modifier = Modifier.padding(horizontal = 20.dp, vertical = 10.dp)) { 58 | field(it::name) { 59 | TextInput("User Name: ", currentValue, hasError, errorMessage, onValueChange = { 60 | setValue(it, validate = true) 61 | }) 62 | } 63 | field(it::email) { 64 | watchLazily { validate() } 65 | TextInput("Email:", currentValue ?: "", hasError, errorMessage) { 66 | setValue(it) 67 | } 68 | } 69 | field(it::age).wrapAs( 70 | wrap = { it?.toString() }, 71 | unwrap = { it?.toIntOrNull() }, 72 | constraints = { optional { isInt() } }, 73 | ) { 74 | TextInput("Age:", currentValue ?: "", hasError, errorMessage) { 75 | setValue(it) 76 | } 77 | } 78 | field(it::password) { 79 | watchLazily { if (it.isNotEmpty()) validate() } 80 | TextInput("Password:", currentValue, hasError, errorMessage, true) { 81 | setValue(it) 82 | } 83 | } 84 | 85 | field(it::confirmPassword) { 86 | watchLazily { if (it.isNotEmpty()) validate() } 87 | TextInput("Confirm Password:", currentValue, hasError, errorMessage, true) { 88 | setValue(it) 89 | } 90 | } 91 | 92 | } 93 | } 94 | 95 | field(it::accept) { 96 | InputLayout(hasError, errorMessage) { 97 | Checkbox(currentValue, onCheckedChange = { setValue(it) }) 98 | Text("I accept the terms of the agreement", 99 | modifier = Modifier.clickable { setValue(!currentValue) }) 100 | } 101 | } 102 | 103 | Spacer(modifier = androidx.compose.ui.Modifier.height(10.dp)) 104 | 105 | var signedUp by remember { mutableStateOf(false) } 106 | if (signedUp) { 107 | Button(onClick = { signedUp = false; form.reset() }) { 108 | Text("Reset", color = Color.White) 109 | } 110 | } else { 111 | Button(onClick = { 112 | signedUp = form.validate() 113 | 114 | 115 | form.pop() 116 | 117 | }) { 118 | Text("Sign up", color = Color.White) 119 | } 120 | } 121 | 122 | if (signedUp) { 123 | val result = form.pop() 124 | Spacer(modifier = androidx.compose.ui.Modifier.height(10.dp)) 125 | Text("Your signup's information is: \n${result}") 126 | } 127 | } 128 | } 129 | } 130 | 131 | @Composable 132 | fun TextInput( 133 | label: String, 134 | text: String, 135 | isError: Boolean, 136 | errorMessage: String? = "", 137 | isPassword: Boolean = false, 138 | onValueChange: (String) -> Unit, 139 | ) { 140 | InputLayout(isError = isError, errorMessage = errorMessage) { 141 | OutlinedTextField( 142 | text, 143 | label = { Text(label) }, 144 | onValueChange = onValueChange, 145 | singleLine = true, 146 | modifier = Modifier.moveFocusOnTab(), 147 | isError = isError, 148 | visualTransformation = if (isPassword) PasswordVisualTransformation() else VisualTransformation.None 149 | ) 150 | } 151 | } 152 | 153 | @Composable 154 | fun InputLayout(isError: Boolean, errorMessage: String? = "", content: @Composable RowScope.() -> Unit) { 155 | Column(modifier = androidx.compose.ui.Modifier.padding(5.dp)) { 156 | Row( 157 | verticalAlignment = Alignment.CenterVertically, 158 | horizontalArrangement = Arrangement.SpaceBetween 159 | ) { 160 | this.content() 161 | } 162 | if (isError) { 163 | Text( 164 | errorMessage ?: "", 165 | color = Color.Red, 166 | modifier = Modifier.padding(top = 5.dp).align(Alignment.End) 167 | ) 168 | } 169 | } 170 | } 171 | 172 | fun Modifier.moveFocusOnTab() = composed { 173 | val focusManager = LocalFocusManager.current 174 | onPreviewKeyEvent { 175 | if (it.type == KeyEventType.KeyDown && it.key == Key.Tab) { 176 | focusManager.moveFocus( 177 | if (it.isShiftPressed) FocusDirection.Previous else FocusDirection.Next 178 | ) 179 | true 180 | } else { 181 | false 182 | } 183 | } 184 | } -------------------------------------------------------------------------------- /sandbox/signupapp/src/desktopMain/kotlin/main.kt: -------------------------------------------------------------------------------- 1 | package local.sandbox.signupapp 2 | 3 | import androidx.compose.material.MaterialTheme 4 | import androidx.compose.ui.unit.dp 5 | import androidx.compose.ui.window.Window 6 | import androidx.compose.ui.window.application 7 | import androidx.compose.ui.window.rememberWindowState 8 | 9 | 10 | fun main() = application { 11 | val winState = rememberWindowState(width = 800.dp, height = 700.dp) 12 | Window(onCloseRequest = ::exitApplication, winState, title = "Sign Up") { 13 | MaterialTheme { 14 | SignupApp() 15 | } 16 | } 17 | } 18 | 19 | -------------------------------------------------------------------------------- /sandbox/signupapp/src/wasmJsMain/kotlin/main.kt: -------------------------------------------------------------------------------- 1 | package local.sandbox.signupapp 2 | 3 | import androidx.compose.ui.ExperimentalComposeUiApi 4 | import androidx.compose.ui.window.CanvasBasedWindow 5 | 6 | @OptIn(ExperimentalComposeUiApi::class) 7 | fun main() { 8 | CanvasBasedWindow(canvasElementId = "root") { 9 | SignupApp() 10 | } 11 | } -------------------------------------------------------------------------------- /sandbox/signupapp/src/wasmJsMain/resources/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Signup 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /settings.gradle.kts: -------------------------------------------------------------------------------- 1 | pluginManagement { 2 | repositories { 3 | gradlePluginPortal() 4 | mavenCentral() 5 | google() 6 | mavenLocal() 7 | } 8 | } 9 | 10 | 11 | rootProject.name = "viform-multiplatform" 12 | 13 | include( 14 | // ":modules:viform-ksp", 15 | ":modules:viform-core", 16 | ":modules:viform-compose", 17 | ":modules:viform-orbitmvi", 18 | ) 19 | --------------------------------------------------------------------------------