diff --git a/src/main/kotlin/de/moritzruth/lampenfieber/Main.kt b/src/main/kotlin/de/moritzruth/lampenfieber/Main.kt
index 4e0829c..e7c7616 100644
--- a/src/main/kotlin/de/moritzruth/lampenfieber/Main.kt
+++ b/src/main/kotlin/de/moritzruth/lampenfieber/Main.kt
@@ -12,6 +12,7 @@ import de.moritzruth.theaterdsl.value.Color
import de.moritzruth.theaterdsl.value.degrees
import de.moritzruth.theaterdsl.value.percent
import kotlinx.collections.immutable.persistentSetOf
+import kotlin.time.Duration.Companion.milliseconds
import kotlin.time.Duration.Companion.seconds
val bar = StairvilleTriLedBar(DmxAddress(400u))
@@ -315,10 +316,291 @@ val show = createShow {
trigger = StepCue.Custom("Vorhang auf, Musik Ende")
onRun {
+ // irgendwann Musik
spotRight.brightness.static(100.percent)
}
}
}
+
+ scene("III.7") {
+ step {
+ trigger = StepCue.Stub
+
+ onRun {
+ // Musik wird hektischer
+ FrontLights.all.forEach { it.brightness.fade(100.percent, 30.seconds) }
+ }
+ }
+ }
+
+ scene("III.8") {
+ step {
+ trigger = StepCue.MusicEnd
+
+ onRun {
+ FrontLights.all.forEach { it.brightness.static(50.percent) }
+ }
+ }
+
+ step {
+ trigger = StepCue.Custom("Auftritt Paula")
+
+ onRun {
+ (FrontLights.right + FrontLights.left).forEach { it.brightness.fade(0.percent, 5.seconds) }
+ // kühle Farben
+ }
+ }
+
+ step {
+ trigger = StepCue.Custom("Auftritt weitere Schüler")
+
+ onRun {
+ (FrontLights.right + FrontLights.left).forEach { it.brightness.fade(50.percent, 40.seconds) }
+ // buntere Farben
+ }
+ }
+
+ step {
+ trigger = StepCue.MusicEnd
+
+ onRun {
+ FrontLights.all.forEach { it.brightness.off() }
+ // Vorhang zu, Pause
+ }
+ }
+ }
+
+ // RnR entfällt
+
+ scene("IV.1") {
+ step {
+ trigger = StepCue.MusicStart("Pause", 69.seconds)
+ }
+
+ step {
+ trigger = StepCue.MusicEnd
+
+ onRun {
+ // Badezimmer-Licht, zweigeteilt
+ FrontLights.right.forEach { it.brightness.fade(75.percent, 8.seconds) }
+ }
+ }
+
+ step {
+ trigger = StepCue.Stub
+
+ onRun {
+ // Badezimmer-Licht, zweigeteilt
+ FrontLights.right.forEach { it.brightness.fade(0.percent, 3.seconds) }
+ FrontLights.left.forEach { it.brightness.fade(75.percent, 3.seconds) }
+ }
+ }
+
+ step {
+ trigger = StepCue.MusicStart("Schau mich mit anderen Augen an", 69.seconds)
+
+ onRun {
+ // beide beleuchten
+ }
+ }
+
+ step {
+ trigger = StepCue.MusicEnd
+
+ onRun {
+ // Umbau
+ }
+ }
+ }
+
+ scene("IV.2") {
+ step {
+ trigger = StepCue.Stub
+
+ onRun {
+ // vor dem Vorhang
+ FrontLights.center.forEach { it.brightness.fade(75.percent, 5.seconds) }
+ }
+ }
+
+ step {
+ trigger = StepCue.MusicStart("Und jetzt", 69.seconds)
+
+ onRun {
+ // wütend, entgeistert
+ }
+ }
+ }
+
+ scene("IV.3") {
+ step {
+ trigger = StepCue.Stub
+
+ onRun {
+ FrontLights.all.forEach { it.brightness.fade(75.percent, 8.seconds) }
+ // warmes Licht
+ }
+ }
+ }
+
+ scene("IV.4") {
+ step {
+ trigger = StepCue.Custom("Auftritt David")
+
+ onRun {
+ // Vorhang bleibt auf
+ FrontLights.all.forEach { it.brightness.fade(50.percent, 8.seconds) }
+ spotRight.brightness.fade(100.percent, 4.seconds)
+ }
+ }
+
+ step {
+ trigger = StepCue.MusicStart("Wenn Du da bist (Duett)", 69.seconds)
+
+ onRun {
+ (FrontLights.right + FrontLights.center).forEach { it.brightness.fade(0.percent, 8.seconds) }
+ spotRight.brightness.fade(100.percent, 10.seconds)
+ // romantisch
+ }
+ }
+
+ step {
+ trigger = StepCue.MusicEnd
+
+ onRun {
+ FrontLights.left.forEach { it.brightness.fade(0.percent, 2.seconds) }
+ spotRight.brightness.fade(0.percent, 2.seconds)
+ // romantisch
+ }
+ }
+ }
+
+ scene("IV.5") {
+ step {
+ trigger = StepCue.Stub
+
+ onRun {
+ (FrontLights.left + FrontLights.center).forEach { it.brightness.fade(75.percent, 8.seconds) }
+ }
+ }
+
+ step {
+ trigger = StepCue.MusicStart("Richy", 69.seconds)
+
+ onRun {
+ // bunt, verspielt
+ }
+ }
+ }
+
+ scene("IV.6") {
+ step {
+ trigger = StepCue.MusicEnd
+
+ onRun {
+ // Vorhang zu, rechts davor
+ // rotes Licht
+
+ spotRight.brightness.fade(100.percent, 10.seconds)
+ }
+ }
+
+ step {
+ trigger = StepCue.Custom("Störung, Ruf")
+
+ onRun {
+ FrontLights.left.forEach { it.brightness.static(100.percent) }
+ spotLeft.brightness.static(100.percent)
+ // romantisches Licht schlagartig aus
+ }
+ }
+ }
+
+ scene("IV.7") {
+ step {
+ trigger = StepCue.Stub
+
+ onRun {
+ // Vorhang auf, Spot immer noch auf Paula
+ spotLeft.brightness.fade(0.percent, 8.seconds)
+ FrontLights.all.forEach { it.brightness.fade(75.percent, 5.seconds) }
+ }
+ }
+
+ step {
+ trigger = StepCue.MusicStart("Paulas Monolog", 69.seconds)
+
+ onRun {
+ FrontLights.all.forEach { it.brightness.fade(20.percent, 15.seconds) }
+ // blaues Licht
+ }
+ }
+
+ step {
+ trigger = StepCue.MusicEnd
+
+ onRun {
+ // Vorhang zu
+ }
+ }
+ }
+
+ scene("IV.8") {
+ step {
+ trigger = StepCue.MusicStart("Angstballet", 69.seconds)
+
+ onRun {
+ // passend zur Musik
+ }
+ }
+
+ step {
+ trigger = StepCue.MusicEnd
+ }
+ }
+
+ scene("IV.9") {
+ step {
+ trigger = StepCue.Stub
+
+ onRun {
+ spotRight.brightness.fade(100.percent, 5.seconds)
+ }
+ }
+
+ step {
+ trigger = StepCue.Custom("Bühne erreicht")
+
+ onRun {
+ // Vorhang auf
+ }
+ }
+ }
+
+ scene("IV.10") {
+ step {
+ trigger = StepCue.Stub
+
+ onRun {
+ // Paula steht mit dem Rücken zum Publikum in der Mitte der Bühne, relativ weit hinten
+ // Sie wird von oben weiß beleuchtet
+ }
+ }
+
+ step {
+ trigger = StepCue.Custom("Bühne erreicht")
+
+ onRun {
+ // Vorhang auf
+ bar.color.static(Color(40.degrees, 50.percent))
+
+ val steps = mutableListOf(75.percent)
+ steps.addAll((0..30).map { 0.percent })
+
+ bar.brightness.steps(steps, 100.milliseconds)
+ }
+ }
+ }
}
}
diff --git a/src/main/kotlin/de/moritzruth/lampenfieber/Test.kt b/src/main/kotlin/de/moritzruth/lampenfieber/Test.kt
index 6a2eb21..adbd2ab 100644
--- a/src/main/kotlin/de/moritzruth/lampenfieber/Test.kt
+++ b/src/main/kotlin/de/moritzruth/lampenfieber/Test.kt
@@ -23,4 +23,5 @@ suspend fun main() {
}
fun test() {
+
}
\ No newline at end of file
diff --git a/src/main/kotlin/de/moritzruth/theaterdsl/show/Runner.kt b/src/main/kotlin/de/moritzruth/theaterdsl/show/Runner.kt
index 7b5fc60..ab4300c 100644
--- a/src/main/kotlin/de/moritzruth/theaterdsl/show/Runner.kt
+++ b/src/main/kotlin/de/moritzruth/theaterdsl/show/Runner.kt
@@ -13,6 +13,7 @@ import io.ktor.serialization.kotlinx.json.*
import io.ktor.server.application.*
import io.ktor.server.cio.*
import io.ktor.server.engine.*
+import io.ktor.server.http.content.*
import io.ktor.server.plugins.contentnegotiation.*
import io.ktor.server.request.*
import io.ktor.server.response.*
@@ -225,6 +226,10 @@ private fun CoroutineScope.startWebsocketServer(context: ShowContext) = launch(D
}
}
}
+
+ staticResources("/", "ui") {
+ enableAutoHeadResponse()
+ }
}
}.start(wait = true)
}
\ No newline at end of file
diff --git a/ui/.gitignore b/ui/.gitignore
new file mode 100755
index 0000000..50eea25
--- /dev/null
+++ b/ui/.gitignore
@@ -0,0 +1,4 @@
+.idea/
+node_modules/
+*.env
+dist/
diff --git a/ui/.nvmrc b/ui/.nvmrc
new file mode 100644
index 0000000..25bf17f
--- /dev/null
+++ b/ui/.nvmrc
@@ -0,0 +1 @@
+18
\ No newline at end of file
diff --git a/ui/LICENSE b/ui/LICENSE
new file mode 100755
index 0000000..261eeb9
--- /dev/null
+++ b/ui/LICENSE
@@ -0,0 +1,201 @@
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
+
+ APPENDIX: How to apply the Apache License to your work.
+
+ To apply the Apache License to your work, attach the following
+ boilerplate notice, with the fields enclosed by brackets "[]"
+ replaced with your own identifying information. (Don't include
+ the brackets!) The text should be enclosed in the appropriate
+ comment syntax for the file format. We also recommend that a
+ file or class name and description of purpose be included on the
+ same "printed page" as the copyright notice for easier
+ identification within third-party archives.
+
+ Copyright [yyyy] [name of copyright owner]
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
diff --git a/ui/index.html b/ui/index.html
new file mode 100755
index 0000000..3da1f25
--- /dev/null
+++ b/ui/index.html
@@ -0,0 +1,13 @@
+
+
+
+
+ Moira
+
+
+
+
+
+
+
+
diff --git a/ui/package.json b/ui/package.json
new file mode 100755
index 0000000..bc3f99a
--- /dev/null
+++ b/ui/package.json
@@ -0,0 +1,31 @@
+{
+ "name": "moira",
+ "version": "1.0.0",
+ "author": "Moritz Ruth ",
+ "license": "Apache-2.0",
+ "scripts": {
+ "dev": "vite --port 3000 --host",
+ "build": "vite build",
+ "start": "vite preview --port 3000 --host"
+ },
+ "devDependencies": {
+ "@iconify-json/ph": "^1.1.5",
+ "@types/lodash-es": "^4.17.7",
+ "@vitejs/plugin-vue": "^4.2.3",
+ "typescript": "^5.0.4",
+ "unplugin-icons": "^0.16.1",
+ "vite": "^4.3.8",
+ "vite-plugin-pages": "^0.30.1",
+ "vite-plugin-windicss": "^1.9.0",
+ "windicss": "^3.5.6"
+ },
+ "dependencies": {
+ "@fontsource-variable/manrope": "^5.0.0",
+ "@vueuse/core": "^10.1.2",
+ "lodash-es": "^4.17.21",
+ "reconnecting-websocket": "^4.4.0",
+ "sass": "^1.62.1",
+ "vue": "^3.3.4",
+ "vue-router": "^4.2.1"
+ }
+}
diff --git a/ui/pnpm-lock.yaml b/ui/pnpm-lock.yaml
new file mode 100755
index 0000000..2050742
--- /dev/null
+++ b/ui/pnpm-lock.yaml
@@ -0,0 +1,1430 @@
+lockfileVersion: '6.0'
+
+dependencies:
+ '@fontsource-variable/manrope':
+ specifier: ^5.0.0
+ version: 5.0.0
+ '@vueuse/core':
+ specifier: ^10.1.2
+ version: 10.1.2(vue@3.3.4)
+ lodash-es:
+ specifier: ^4.17.21
+ version: 4.17.21
+ reconnecting-websocket:
+ specifier: ^4.4.0
+ version: 4.4.0
+ sass:
+ specifier: ^1.62.1
+ version: 1.62.1
+ vue:
+ specifier: ^3.3.4
+ version: 3.3.4
+ vue-router:
+ specifier: ^4.2.1
+ version: 4.2.1(vue@3.3.4)
+
+devDependencies:
+ '@iconify-json/ph':
+ specifier: ^1.1.5
+ version: 1.1.5
+ '@types/lodash-es':
+ specifier: ^4.17.7
+ version: 4.17.7
+ '@vitejs/plugin-vue':
+ specifier: ^4.2.3
+ version: 4.2.3(vite@4.3.8)(vue@3.3.4)
+ typescript:
+ specifier: ^5.0.4
+ version: 5.0.4
+ unplugin-icons:
+ specifier: ^0.16.1
+ version: 0.16.1
+ vite:
+ specifier: ^4.3.8
+ version: 4.3.8(sass@1.62.1)
+ vite-plugin-pages:
+ specifier: ^0.30.1
+ version: 0.30.1(vite@4.3.8)
+ vite-plugin-windicss:
+ specifier: ^1.9.0
+ version: 1.9.0(vite@4.3.8)
+ windicss:
+ specifier: ^3.5.6
+ version: 3.5.6
+
+packages:
+
+ /@antfu/install-pkg@0.1.1:
+ resolution: {integrity: sha512-LyB/8+bSfa0DFGC06zpCEfs89/XoWZwws5ygEa5D+Xsm3OfI+aXQ86VgVG7Acyef+rSZ5HE7J8rrxzrQeM3PjQ==}
+ dependencies:
+ execa: 5.1.1
+ find-up: 5.0.0
+ dev: true
+
+ /@antfu/utils@0.7.2:
+ resolution: {integrity: sha512-vy9fM3pIxZmX07dL+VX1aZe7ynZ+YyB0jY+jE6r3hOK6GNY2t6W8rzpFC4tgpbXUYABkFQwgJq2XYXlxbXAI0g==}
+ dev: true
+
+ /@babel/helper-string-parser@7.21.5:
+ resolution: {integrity: sha512-5pTUx3hAJaZIdW99sJ6ZUUgWq/Y+Hja7TowEnLNMm1VivRgZQL3vpBY3qUACVsvw+yQU6+YgfBVmcbLaZtrA1w==}
+ engines: {node: '>=6.9.0'}
+
+ /@babel/helper-validator-identifier@7.19.1:
+ resolution: {integrity: sha512-awrNfaMtnHUr653GgGEs++LlAvW6w+DcPrOliSMXWCKo597CwL5Acf/wWdNkf/tfEQE3mjkeD1YOVZOUV/od1w==}
+ engines: {node: '>=6.9.0'}
+
+ /@babel/parser@7.21.9:
+ resolution: {integrity: sha512-q5PNg/Bi1OpGgx5jYlvWZwAorZepEudDMCLtj967aeS7WMont7dUZI46M2XwcIQqvUlMxWfdLFu4S/qSxeUu5g==}
+ engines: {node: '>=6.0.0'}
+ hasBin: true
+ dependencies:
+ '@babel/types': 7.21.5
+
+ /@babel/types@7.21.5:
+ resolution: {integrity: sha512-m4AfNvVF2mVC/F7fDEdH2El3HzUg9It/XsCxZiOTTA3m3qYfcSVSbTfM6Q9xG+hYDniZssYhlXKKUMD5m8tF4Q==}
+ engines: {node: '>=6.9.0'}
+ dependencies:
+ '@babel/helper-string-parser': 7.21.5
+ '@babel/helper-validator-identifier': 7.19.1
+ to-fast-properties: 2.0.0
+
+ /@esbuild/android-arm64@0.17.19:
+ resolution: {integrity: sha512-KBMWvEZooR7+kzY0BtbTQn0OAYY7CsiydT63pVEaPtVYF0hXbUaOyZog37DKxK7NF3XacBJOpYT4adIJh+avxA==}
+ engines: {node: '>=12'}
+ cpu: [arm64]
+ os: [android]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /@esbuild/android-arm@0.17.19:
+ resolution: {integrity: sha512-rIKddzqhmav7MSmoFCmDIb6e2W57geRsM94gV2l38fzhXMwq7hZoClug9USI2pFRGL06f4IOPHHpFNOkWieR8A==}
+ engines: {node: '>=12'}
+ cpu: [arm]
+ os: [android]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /@esbuild/android-x64@0.17.19:
+ resolution: {integrity: sha512-uUTTc4xGNDT7YSArp/zbtmbhO0uEEK9/ETW29Wk1thYUJBz3IVnvgEiEwEa9IeLyvnpKrWK64Utw2bgUmDveww==}
+ engines: {node: '>=12'}
+ cpu: [x64]
+ os: [android]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /@esbuild/darwin-arm64@0.17.19:
+ resolution: {integrity: sha512-80wEoCfF/hFKM6WE1FyBHc9SfUblloAWx6FJkFWTWiCoht9Mc0ARGEM47e67W9rI09YoUxJL68WHfDRYEAvOhg==}
+ engines: {node: '>=12'}
+ cpu: [arm64]
+ os: [darwin]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /@esbuild/darwin-x64@0.17.19:
+ resolution: {integrity: sha512-IJM4JJsLhRYr9xdtLytPLSH9k/oxR3boaUIYiHkAawtwNOXKE8KoU8tMvryogdcT8AU+Bflmh81Xn6Q0vTZbQw==}
+ engines: {node: '>=12'}
+ cpu: [x64]
+ os: [darwin]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /@esbuild/freebsd-arm64@0.17.19:
+ resolution: {integrity: sha512-pBwbc7DufluUeGdjSU5Si+P3SoMF5DQ/F/UmTSb8HXO80ZEAJmrykPyzo1IfNbAoaqw48YRpv8shwd1NoI0jcQ==}
+ engines: {node: '>=12'}
+ cpu: [arm64]
+ os: [freebsd]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /@esbuild/freebsd-x64@0.17.19:
+ resolution: {integrity: sha512-4lu+n8Wk0XlajEhbEffdy2xy53dpR06SlzvhGByyg36qJw6Kpfk7cp45DR/62aPH9mtJRmIyrXAS5UWBrJT6TQ==}
+ engines: {node: '>=12'}
+ cpu: [x64]
+ os: [freebsd]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /@esbuild/linux-arm64@0.17.19:
+ resolution: {integrity: sha512-ct1Tg3WGwd3P+oZYqic+YZF4snNl2bsnMKRkb3ozHmnM0dGWuxcPTTntAF6bOP0Sp4x0PjSF+4uHQ1xvxfRKqg==}
+ engines: {node: '>=12'}
+ cpu: [arm64]
+ os: [linux]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /@esbuild/linux-arm@0.17.19:
+ resolution: {integrity: sha512-cdmT3KxjlOQ/gZ2cjfrQOtmhG4HJs6hhvm3mWSRDPtZ/lP5oe8FWceS10JaSJC13GBd4eH/haHnqf7hhGNLerA==}
+ engines: {node: '>=12'}
+ cpu: [arm]
+ os: [linux]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /@esbuild/linux-ia32@0.17.19:
+ resolution: {integrity: sha512-w4IRhSy1VbsNxHRQpeGCHEmibqdTUx61Vc38APcsRbuVgK0OPEnQ0YD39Brymn96mOx48Y2laBQGqgZ0j9w6SQ==}
+ engines: {node: '>=12'}
+ cpu: [ia32]
+ os: [linux]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /@esbuild/linux-loong64@0.17.19:
+ resolution: {integrity: sha512-2iAngUbBPMq439a+z//gE+9WBldoMp1s5GWsUSgqHLzLJ9WoZLZhpwWuym0u0u/4XmZ3gpHmzV84PonE+9IIdQ==}
+ engines: {node: '>=12'}
+ cpu: [loong64]
+ os: [linux]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /@esbuild/linux-mips64el@0.17.19:
+ resolution: {integrity: sha512-LKJltc4LVdMKHsrFe4MGNPp0hqDFA1Wpt3jE1gEyM3nKUvOiO//9PheZZHfYRfYl6AwdTH4aTcXSqBerX0ml4A==}
+ engines: {node: '>=12'}
+ cpu: [mips64el]
+ os: [linux]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /@esbuild/linux-ppc64@0.17.19:
+ resolution: {integrity: sha512-/c/DGybs95WXNS8y3Ti/ytqETiW7EU44MEKuCAcpPto3YjQbyK3IQVKfF6nbghD7EcLUGl0NbiL5Rt5DMhn5tg==}
+ engines: {node: '>=12'}
+ cpu: [ppc64]
+ os: [linux]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /@esbuild/linux-riscv64@0.17.19:
+ resolution: {integrity: sha512-FC3nUAWhvFoutlhAkgHf8f5HwFWUL6bYdvLc/TTuxKlvLi3+pPzdZiFKSWz/PF30TB1K19SuCxDTI5KcqASJqA==}
+ engines: {node: '>=12'}
+ cpu: [riscv64]
+ os: [linux]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /@esbuild/linux-s390x@0.17.19:
+ resolution: {integrity: sha512-IbFsFbxMWLuKEbH+7sTkKzL6NJmG2vRyy6K7JJo55w+8xDk7RElYn6xvXtDW8HCfoKBFK69f3pgBJSUSQPr+4Q==}
+ engines: {node: '>=12'}
+ cpu: [s390x]
+ os: [linux]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /@esbuild/linux-x64@0.17.19:
+ resolution: {integrity: sha512-68ngA9lg2H6zkZcyp22tsVt38mlhWde8l3eJLWkyLrp4HwMUr3c1s/M2t7+kHIhvMjglIBrFpncX1SzMckomGw==}
+ engines: {node: '>=12'}
+ cpu: [x64]
+ os: [linux]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /@esbuild/netbsd-x64@0.17.19:
+ resolution: {integrity: sha512-CwFq42rXCR8TYIjIfpXCbRX0rp1jo6cPIUPSaWwzbVI4aOfX96OXY8M6KNmtPcg7QjYeDmN+DD0Wp3LaBOLf4Q==}
+ engines: {node: '>=12'}
+ cpu: [x64]
+ os: [netbsd]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /@esbuild/openbsd-x64@0.17.19:
+ resolution: {integrity: sha512-cnq5brJYrSZ2CF6c35eCmviIN3k3RczmHz8eYaVlNasVqsNY+JKohZU5MKmaOI+KkllCdzOKKdPs762VCPC20g==}
+ engines: {node: '>=12'}
+ cpu: [x64]
+ os: [openbsd]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /@esbuild/sunos-x64@0.17.19:
+ resolution: {integrity: sha512-vCRT7yP3zX+bKWFeP/zdS6SqdWB8OIpaRq/mbXQxTGHnIxspRtigpkUcDMlSCOejlHowLqII7K2JKevwyRP2rg==}
+ engines: {node: '>=12'}
+ cpu: [x64]
+ os: [sunos]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /@esbuild/win32-arm64@0.17.19:
+ resolution: {integrity: sha512-yYx+8jwowUstVdorcMdNlzklLYhPxjniHWFKgRqH7IFlUEa0Umu3KuYplf1HUZZ422e3NU9F4LGb+4O0Kdcaag==}
+ engines: {node: '>=12'}
+ cpu: [arm64]
+ os: [win32]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /@esbuild/win32-ia32@0.17.19:
+ resolution: {integrity: sha512-eggDKanJszUtCdlVs0RB+h35wNlb5v4TWEkq4vZcmVt5u/HiDZrTXe2bWFQUez3RgNHwx/x4sk5++4NSSicKkw==}
+ engines: {node: '>=12'}
+ cpu: [ia32]
+ os: [win32]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /@esbuild/win32-x64@0.17.19:
+ resolution: {integrity: sha512-lAhycmKnVOuRYNtRtatQR1LPQf2oYCkRGkSFnseDAKPl8lu5SOsK/e1sXe5a0Pc5kHIHe6P2I/ilntNv2xf3cA==}
+ engines: {node: '>=12'}
+ cpu: [x64]
+ os: [win32]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /@fontsource-variable/manrope@5.0.0:
+ resolution: {integrity: sha512-CEXggedJ8Wxrc+wptmUZcArmdoVQ42qMKJbBQPQsEtw81EPHgEnHjRESzeWoSFSkUWlj3g6zxiWsvqECc4Z5jA==}
+ dev: false
+
+ /@iconify-json/ph@1.1.5:
+ resolution: {integrity: sha512-iLXq3nohfGge22gL2tZmQ2WHBKkKkIbGWrkuyC8arckS4PWaONyh4A+uDPtSek9QbYDvi9AE2+NxWkNZhANotA==}
+ dependencies:
+ '@iconify/types': 2.0.0
+ dev: true
+
+ /@iconify/types@2.0.0:
+ resolution: {integrity: sha512-+wluvCrRhXrhyOmRDJ3q8mux9JkKy5SJ/v8ol2tu4FVjyYvtEzkc/3pK15ET6RKg4b4w4BmTk1+gsCUhf21Ykg==}
+ dev: true
+
+ /@iconify/utils@2.1.5:
+ resolution: {integrity: sha512-6MvDI+I6QMvXn5rK9KQGdpEE4mmLTcuQdLZEiX5N+uZB+vc4Yw9K1OtnOgkl8mp4d9X0UrILREyZgF1NUwUt+Q==}
+ dependencies:
+ '@antfu/install-pkg': 0.1.1
+ '@antfu/utils': 0.7.2
+ '@iconify/types': 2.0.0
+ debug: 4.3.4
+ kolorist: 1.8.0
+ local-pkg: 0.4.3
+ transitivePeerDependencies:
+ - supports-color
+ dev: true
+
+ /@jridgewell/sourcemap-codec@1.4.15:
+ resolution: {integrity: sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==}
+
+ /@nodelib/fs.scandir@2.1.5:
+ resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==}
+ engines: {node: '>= 8'}
+ dependencies:
+ '@nodelib/fs.stat': 2.0.5
+ run-parallel: 1.2.0
+ dev: true
+
+ /@nodelib/fs.stat@2.0.5:
+ resolution: {integrity: sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==}
+ engines: {node: '>= 8'}
+ dev: true
+
+ /@nodelib/fs.walk@1.2.8:
+ resolution: {integrity: sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==}
+ engines: {node: '>= 8'}
+ dependencies:
+ '@nodelib/fs.scandir': 2.1.5
+ fastq: 1.15.0
+ dev: true
+
+ /@types/debug@4.1.8:
+ resolution: {integrity: sha512-/vPO1EPOs306Cvhwv7KfVfYvOJqA/S/AXjaHQiJboCZzcNDb+TIJFN9/2C9DZ//ijSKWioNyUxD792QmDJ+HKQ==}
+ dependencies:
+ '@types/ms': 0.7.31
+ dev: true
+
+ /@types/lodash-es@4.17.7:
+ resolution: {integrity: sha512-z0ptr6UI10VlU6l5MYhGwS4mC8DZyYer2mCoyysZtSF7p26zOX8UpbrV0YpNYLGS8K4PUFIyEr62IMFFjveSiQ==}
+ dependencies:
+ '@types/lodash': 4.14.194
+ dev: true
+
+ /@types/lodash@4.14.194:
+ resolution: {integrity: sha512-r22s9tAS7imvBt2lyHC9B8AGwWnXaYb1tY09oyLkXDs4vArpYJzw09nj8MLx5VfciBPGIb+ZwG0ssYnEPJxn/g==}
+ dev: true
+
+ /@types/ms@0.7.31:
+ resolution: {integrity: sha512-iiUgKzV9AuaEkZqkOLDIvlQiL6ltuZd9tGcW3gwpnX8JbuiuhFlEGmmFXEXkN50Cvq7Os88IY2v0dkDqXYWVgA==}
+ dev: true
+
+ /@types/web-bluetooth@0.0.17:
+ resolution: {integrity: sha512-4p9vcSmxAayx72yn70joFoL44c9MO/0+iVEBIQXe3v2h2SiAsEIo/G5v6ObFWvNKRFjbrVadNf9LqEEZeQPzdA==}
+ dev: false
+
+ /@vitejs/plugin-vue@4.2.3(vite@4.3.8)(vue@3.3.4):
+ resolution: {integrity: sha512-R6JDUfiZbJA9cMiguQ7jxALsgiprjBeHL5ikpXfJCH62pPHtI+JdJ5xWj6Ev73yXSlYl86+blXn1kZHQ7uElxw==}
+ engines: {node: ^14.18.0 || >=16.0.0}
+ peerDependencies:
+ vite: ^4.0.0
+ vue: ^3.2.25
+ dependencies:
+ vite: 4.3.8(sass@1.62.1)
+ vue: 3.3.4
+ dev: true
+
+ /@vue/compiler-core@3.3.4:
+ resolution: {integrity: sha512-cquyDNvZ6jTbf/+x+AgM2Arrp6G4Dzbb0R64jiG804HRMfRiFXWI6kqUVqZ6ZR0bQhIoQjB4+2bhNtVwndW15g==}
+ dependencies:
+ '@babel/parser': 7.21.9
+ '@vue/shared': 3.3.4
+ estree-walker: 2.0.2
+ source-map-js: 1.0.2
+
+ /@vue/compiler-dom@3.3.4:
+ resolution: {integrity: sha512-wyM+OjOVpuUukIq6p5+nwHYtj9cFroz9cwkfmP9O1nzH68BenTTv0u7/ndggT8cIQlnBeOo6sUT/gvHcIkLA5w==}
+ dependencies:
+ '@vue/compiler-core': 3.3.4
+ '@vue/shared': 3.3.4
+
+ /@vue/compiler-sfc@3.3.4:
+ resolution: {integrity: sha512-6y/d8uw+5TkCuzBkgLS0v3lSM3hJDntFEiUORM11pQ/hKvkhSKZrXW6i69UyXlJQisJxuUEJKAWEqWbWsLeNKQ==}
+ dependencies:
+ '@babel/parser': 7.21.9
+ '@vue/compiler-core': 3.3.4
+ '@vue/compiler-dom': 3.3.4
+ '@vue/compiler-ssr': 3.3.4
+ '@vue/reactivity-transform': 3.3.4
+ '@vue/shared': 3.3.4
+ estree-walker: 2.0.2
+ magic-string: 0.30.0
+ postcss: 8.4.23
+ source-map-js: 1.0.2
+
+ /@vue/compiler-ssr@3.3.4:
+ resolution: {integrity: sha512-m0v6oKpup2nMSehwA6Uuu+j+wEwcy7QmwMkVNVfrV9P2qE5KshC6RwOCq8fjGS/Eak/uNb8AaWekfiXxbBB6gQ==}
+ dependencies:
+ '@vue/compiler-dom': 3.3.4
+ '@vue/shared': 3.3.4
+
+ /@vue/devtools-api@6.5.0:
+ resolution: {integrity: sha512-o9KfBeaBmCKl10usN4crU53fYtC1r7jJwdGKjPT24t348rHxgfpZ0xL3Xm/gLUYnc0oTp8LAmrxOeLyu6tbk2Q==}
+ dev: false
+
+ /@vue/reactivity-transform@3.3.4:
+ resolution: {integrity: sha512-MXgwjako4nu5WFLAjpBnCj/ieqcjE2aJBINUNQzkZQfzIZA4xn+0fV1tIYBJvvva3N3OvKGofRLvQIwEQPpaXw==}
+ dependencies:
+ '@babel/parser': 7.21.9
+ '@vue/compiler-core': 3.3.4
+ '@vue/shared': 3.3.4
+ estree-walker: 2.0.2
+ magic-string: 0.30.0
+
+ /@vue/reactivity@3.3.4:
+ resolution: {integrity: sha512-kLTDLwd0B1jG08NBF3R5rqULtv/f8x3rOFByTDz4J53ttIQEDmALqKqXY0J+XQeN0aV2FBxY8nJDf88yvOPAqQ==}
+ dependencies:
+ '@vue/shared': 3.3.4
+
+ /@vue/runtime-core@3.3.4:
+ resolution: {integrity: sha512-R+bqxMN6pWO7zGI4OMlmvePOdP2c93GsHFM/siJI7O2nxFRzj55pLwkpCedEY+bTMgp5miZ8CxfIZo3S+gFqvA==}
+ dependencies:
+ '@vue/reactivity': 3.3.4
+ '@vue/shared': 3.3.4
+
+ /@vue/runtime-dom@3.3.4:
+ resolution: {integrity: sha512-Aj5bTJ3u5sFsUckRghsNjVTtxZQ1OyMWCr5dZRAPijF/0Vy4xEoRCwLyHXcj4D0UFbJ4lbx3gPTgg06K/GnPnQ==}
+ dependencies:
+ '@vue/runtime-core': 3.3.4
+ '@vue/shared': 3.3.4
+ csstype: 3.1.2
+
+ /@vue/server-renderer@3.3.4(vue@3.3.4):
+ resolution: {integrity: sha512-Q6jDDzR23ViIb67v+vM1Dqntu+HUexQcsWKhhQa4ARVzxOY2HbC7QRW/ggkDBd5BU+uM1sV6XOAP0b216o34JQ==}
+ peerDependencies:
+ vue: 3.3.4
+ dependencies:
+ '@vue/compiler-ssr': 3.3.4
+ '@vue/shared': 3.3.4
+ vue: 3.3.4
+
+ /@vue/shared@3.3.4:
+ resolution: {integrity: sha512-7OjdcV8vQ74eiz1TZLzZP4JwqM5fA94K6yntPS5Z25r9HDuGNzaGdgvwKYq6S+MxwF0TFRwe50fIR/MYnakdkQ==}
+
+ /@vueuse/core@10.1.2(vue@3.3.4):
+ resolution: {integrity: sha512-roNn8WuerI56A5uiTyF/TEYX0Y+VKlhZAF94unUfdhbDUI+NfwQMn4FUnUscIRUhv3344qvAghopU4bzLPNFlA==}
+ dependencies:
+ '@types/web-bluetooth': 0.0.17
+ '@vueuse/metadata': 10.1.2
+ '@vueuse/shared': 10.1.2(vue@3.3.4)
+ vue-demi: 0.14.5(vue@3.3.4)
+ transitivePeerDependencies:
+ - '@vue/composition-api'
+ - vue
+ dev: false
+
+ /@vueuse/metadata@10.1.2:
+ resolution: {integrity: sha512-3mc5BqN9aU2SqBeBuWE7ne4OtXHoHKggNgxZR2K+zIW4YLsy6xoZ4/9vErQs6tvoKDX6QAqm3lvsrv0mczAwIQ==}
+ dev: false
+
+ /@vueuse/shared@10.1.2(vue@3.3.4):
+ resolution: {integrity: sha512-1uoUTPBlgyscK9v6ScGeVYDDzlPSFXBlxuK7SfrDGyUTBiznb3mNceqhwvZHjtDRELZEN79V5uWPTF1VDV8svA==}
+ dependencies:
+ vue-demi: 0.14.5(vue@3.3.4)
+ transitivePeerDependencies:
+ - '@vue/composition-api'
+ - vue
+ dev: false
+
+ /@windicss/config@1.9.0:
+ resolution: {integrity: sha512-QO4+udbmDIgZwAi89tqUt5nGwBq3IgyELjLn83twZXiIqzOw+77ecCuM0oPSbzWmIbCqXq3wRQHd6Z1u5E/5zQ==}
+ dependencies:
+ debug: 4.3.4
+ jiti: 1.18.2
+ windicss: 3.5.6
+ transitivePeerDependencies:
+ - supports-color
+ dev: true
+
+ /@windicss/plugin-utils@1.9.0:
+ resolution: {integrity: sha512-omAacM5ExIr9XBUI2z47CyCXJBke4imJZqXW41YgHhRLbahTngbScFk5yxa6dXivDXUpUKqasOPXBJgA4bhHCg==}
+ dependencies:
+ '@antfu/utils': 0.7.2
+ '@windicss/config': 1.9.0
+ debug: 4.3.4
+ fast-glob: 3.2.12
+ magic-string: 0.30.0
+ micromatch: 4.0.5
+ windicss: 3.5.6
+ transitivePeerDependencies:
+ - supports-color
+ dev: true
+
+ /acorn@8.8.2:
+ resolution: {integrity: sha512-xjIYgE8HBrkpd/sJqOGNspf8uHG+NOHGOw6a/Urj8taM2EXfdNAH2oFcPeIFfsv3+kz/mJrS5VuMqbNLjCa2vw==}
+ engines: {node: '>=0.4.0'}
+ hasBin: true
+ dev: true
+
+ /anymatch@3.1.3:
+ resolution: {integrity: sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==}
+ engines: {node: '>= 8'}
+ dependencies:
+ normalize-path: 3.0.0
+ picomatch: 2.3.1
+
+ /array-buffer-byte-length@1.0.0:
+ resolution: {integrity: sha512-LPuwb2P+NrQw3XhxGc36+XSvuBPopovXYTR9Ew++Du9Yb/bx5AzBfrIsBoj0EZUifjQU+sHL21sseZ3jerWO/A==}
+ dependencies:
+ call-bind: 1.0.2
+ is-array-buffer: 3.0.2
+ dev: true
+
+ /available-typed-arrays@1.0.5:
+ resolution: {integrity: sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw==}
+ engines: {node: '>= 0.4'}
+ dev: true
+
+ /binary-extensions@2.2.0:
+ resolution: {integrity: sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==}
+ engines: {node: '>=8'}
+
+ /braces@3.0.2:
+ resolution: {integrity: sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==}
+ engines: {node: '>=8'}
+ dependencies:
+ fill-range: 7.0.1
+
+ /call-bind@1.0.2:
+ resolution: {integrity: sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==}
+ dependencies:
+ function-bind: 1.1.1
+ get-intrinsic: 1.2.1
+ dev: true
+
+ /chokidar@3.5.3:
+ resolution: {integrity: sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==}
+ engines: {node: '>= 8.10.0'}
+ dependencies:
+ anymatch: 3.1.3
+ braces: 3.0.2
+ glob-parent: 5.1.2
+ is-binary-path: 2.1.0
+ is-glob: 4.0.3
+ normalize-path: 3.0.0
+ readdirp: 3.6.0
+ optionalDependencies:
+ fsevents: 2.3.2
+
+ /cross-spawn@7.0.3:
+ resolution: {integrity: sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==}
+ engines: {node: '>= 8'}
+ dependencies:
+ path-key: 3.1.1
+ shebang-command: 2.0.0
+ which: 2.0.2
+ dev: true
+
+ /csstype@3.1.2:
+ resolution: {integrity: sha512-I7K1Uu0MBPzaFKg4nI5Q7Vs2t+3gWWW648spaF+Rg7pI9ds18Ugn+lvg4SHczUdKlHI5LWBXyqfS8+DufyBsgQ==}
+
+ /debug@4.3.4:
+ resolution: {integrity: sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==}
+ engines: {node: '>=6.0'}
+ peerDependencies:
+ supports-color: '*'
+ peerDependenciesMeta:
+ supports-color:
+ optional: true
+ dependencies:
+ ms: 2.1.2
+ dev: true
+
+ /deep-equal@2.2.1:
+ resolution: {integrity: sha512-lKdkdV6EOGoVn65XaOsPdH4rMxTZOnmFyuIkMjM1i5HHCbfjC97dawgTAy0deYNfuqUqW+Q5VrVaQYtUpSd6yQ==}
+ dependencies:
+ array-buffer-byte-length: 1.0.0
+ call-bind: 1.0.2
+ es-get-iterator: 1.1.3
+ get-intrinsic: 1.2.1
+ is-arguments: 1.1.1
+ is-array-buffer: 3.0.2
+ is-date-object: 1.0.5
+ is-regex: 1.1.4
+ is-shared-array-buffer: 1.0.2
+ isarray: 2.0.5
+ object-is: 1.1.5
+ object-keys: 1.1.1
+ object.assign: 4.1.4
+ regexp.prototype.flags: 1.5.0
+ side-channel: 1.0.4
+ which-boxed-primitive: 1.0.2
+ which-collection: 1.0.1
+ which-typed-array: 1.1.9
+ dev: true
+
+ /define-properties@1.2.0:
+ resolution: {integrity: sha512-xvqAVKGfT1+UAvPwKTVw/njhdQ8ZhXK4lI0bCIuCMrp2up9nPnaDftrLtmpTazqd1o+UY4zgzU+avtMbDP+ldA==}
+ engines: {node: '>= 0.4'}
+ dependencies:
+ has-property-descriptors: 1.0.0
+ object-keys: 1.1.1
+ dev: true
+
+ /es-get-iterator@1.1.3:
+ resolution: {integrity: sha512-sPZmqHBe6JIiTfN5q2pEi//TwxmAFHwj/XEuYjTuse78i8KxaqMTTzxPoFKuzRpDpTJ+0NAbpfenkmH2rePtuw==}
+ dependencies:
+ call-bind: 1.0.2
+ get-intrinsic: 1.2.1
+ has-symbols: 1.0.3
+ is-arguments: 1.1.1
+ is-map: 2.0.2
+ is-set: 2.0.2
+ is-string: 1.0.7
+ isarray: 2.0.5
+ stop-iteration-iterator: 1.0.0
+ dev: true
+
+ /esbuild@0.17.19:
+ resolution: {integrity: sha512-XQ0jAPFkK/u3LcVRcvVHQcTIqD6E2H1fvZMA5dQPSOWb3suUbWbfbRf94pjc0bNzRYLfIrDRQXr7X+LHIm5oHw==}
+ engines: {node: '>=12'}
+ hasBin: true
+ requiresBuild: true
+ optionalDependencies:
+ '@esbuild/android-arm': 0.17.19
+ '@esbuild/android-arm64': 0.17.19
+ '@esbuild/android-x64': 0.17.19
+ '@esbuild/darwin-arm64': 0.17.19
+ '@esbuild/darwin-x64': 0.17.19
+ '@esbuild/freebsd-arm64': 0.17.19
+ '@esbuild/freebsd-x64': 0.17.19
+ '@esbuild/linux-arm': 0.17.19
+ '@esbuild/linux-arm64': 0.17.19
+ '@esbuild/linux-ia32': 0.17.19
+ '@esbuild/linux-loong64': 0.17.19
+ '@esbuild/linux-mips64el': 0.17.19
+ '@esbuild/linux-ppc64': 0.17.19
+ '@esbuild/linux-riscv64': 0.17.19
+ '@esbuild/linux-s390x': 0.17.19
+ '@esbuild/linux-x64': 0.17.19
+ '@esbuild/netbsd-x64': 0.17.19
+ '@esbuild/openbsd-x64': 0.17.19
+ '@esbuild/sunos-x64': 0.17.19
+ '@esbuild/win32-arm64': 0.17.19
+ '@esbuild/win32-ia32': 0.17.19
+ '@esbuild/win32-x64': 0.17.19
+ dev: true
+
+ /esprima-extract-comments@1.1.0:
+ resolution: {integrity: sha512-sBQUnvJwpeE9QnPrxh7dpI/dp67erYG4WXEAreAMoelPRpMR7NWb4YtwRPn9b+H1uLQKl/qS8WYmyaljTpjIsw==}
+ engines: {node: '>=4'}
+ dependencies:
+ esprima: 4.0.1
+ dev: true
+
+ /esprima@4.0.1:
+ resolution: {integrity: sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==}
+ engines: {node: '>=4'}
+ hasBin: true
+ dev: true
+
+ /estree-walker@2.0.2:
+ resolution: {integrity: sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==}
+
+ /execa@5.1.1:
+ resolution: {integrity: sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==}
+ engines: {node: '>=10'}
+ dependencies:
+ cross-spawn: 7.0.3
+ get-stream: 6.0.1
+ human-signals: 2.1.0
+ is-stream: 2.0.1
+ merge-stream: 2.0.0
+ npm-run-path: 4.0.1
+ onetime: 5.1.2
+ signal-exit: 3.0.7
+ strip-final-newline: 2.0.0
+ dev: true
+
+ /extract-comments@1.1.0:
+ resolution: {integrity: sha512-dzbZV2AdSSVW/4E7Ti5hZdHWbA+Z80RJsJhr5uiL10oyjl/gy7/o+HI1HwK4/WSZhlq4SNKU3oUzXlM13Qx02Q==}
+ engines: {node: '>=6'}
+ dependencies:
+ esprima-extract-comments: 1.1.0
+ parse-code-context: 1.0.0
+ dev: true
+
+ /fast-glob@3.2.12:
+ resolution: {integrity: sha512-DVj4CQIYYow0BlaelwK1pHl5n5cRSJfM60UA0zK891sVInoPri2Ekj7+e1CT3/3qxXenpI+nBBmQAcJPJgaj4w==}
+ engines: {node: '>=8.6.0'}
+ dependencies:
+ '@nodelib/fs.stat': 2.0.5
+ '@nodelib/fs.walk': 1.2.8
+ glob-parent: 5.1.2
+ merge2: 1.4.1
+ micromatch: 4.0.5
+ dev: true
+
+ /fastq@1.15.0:
+ resolution: {integrity: sha512-wBrocU2LCXXa+lWBt8RoIRD89Fi8OdABODa/kEnyeyjS5aZO5/GNvI5sEINADqP/h8M29UHTHUb53sUu5Ihqdw==}
+ dependencies:
+ reusify: 1.0.4
+ dev: true
+
+ /fill-range@7.0.1:
+ resolution: {integrity: sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==}
+ engines: {node: '>=8'}
+ dependencies:
+ to-regex-range: 5.0.1
+
+ /find-up@5.0.0:
+ resolution: {integrity: sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==}
+ engines: {node: '>=10'}
+ dependencies:
+ locate-path: 6.0.0
+ path-exists: 4.0.0
+ dev: true
+
+ /for-each@0.3.3:
+ resolution: {integrity: sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==}
+ dependencies:
+ is-callable: 1.2.7
+ dev: true
+
+ /fsevents@2.3.2:
+ resolution: {integrity: sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==}
+ engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0}
+ os: [darwin]
+ requiresBuild: true
+ optional: true
+
+ /function-bind@1.1.1:
+ resolution: {integrity: sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==}
+ dev: true
+
+ /functions-have-names@1.2.3:
+ resolution: {integrity: sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==}
+ dev: true
+
+ /get-intrinsic@1.2.1:
+ resolution: {integrity: sha512-2DcsyfABl+gVHEfCOaTrWgyt+tb6MSEGmKq+kI5HwLbIYgjgmMcV8KQ41uaKz1xxUcn9tJtgFbQUEVcEbd0FYw==}
+ dependencies:
+ function-bind: 1.1.1
+ has: 1.0.3
+ has-proto: 1.0.1
+ has-symbols: 1.0.3
+ dev: true
+
+ /get-stream@6.0.1:
+ resolution: {integrity: sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==}
+ engines: {node: '>=10'}
+ dev: true
+
+ /glob-parent@5.1.2:
+ resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==}
+ engines: {node: '>= 6'}
+ dependencies:
+ is-glob: 4.0.3
+
+ /gopd@1.0.1:
+ resolution: {integrity: sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==}
+ dependencies:
+ get-intrinsic: 1.2.1
+ dev: true
+
+ /has-bigints@1.0.2:
+ resolution: {integrity: sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ==}
+ dev: true
+
+ /has-property-descriptors@1.0.0:
+ resolution: {integrity: sha512-62DVLZGoiEBDHQyqG4w9xCuZ7eJEwNmJRWw2VY84Oedb7WFcA27fiEVe8oUQx9hAUJ4ekurquucTGwsyO1XGdQ==}
+ dependencies:
+ get-intrinsic: 1.2.1
+ dev: true
+
+ /has-proto@1.0.1:
+ resolution: {integrity: sha512-7qE+iP+O+bgF9clE5+UoBFzE65mlBiVj3tKCrlNQ0Ogwm0BjpT/gK4SlLYDMybDh5I3TCTKnPPa0oMG7JDYrhg==}
+ engines: {node: '>= 0.4'}
+ dev: true
+
+ /has-symbols@1.0.3:
+ resolution: {integrity: sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==}
+ engines: {node: '>= 0.4'}
+ dev: true
+
+ /has-tostringtag@1.0.0:
+ resolution: {integrity: sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ==}
+ engines: {node: '>= 0.4'}
+ dependencies:
+ has-symbols: 1.0.3
+ dev: true
+
+ /has@1.0.3:
+ resolution: {integrity: sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==}
+ engines: {node: '>= 0.4.0'}
+ dependencies:
+ function-bind: 1.1.1
+ dev: true
+
+ /human-signals@2.1.0:
+ resolution: {integrity: sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==}
+ engines: {node: '>=10.17.0'}
+ dev: true
+
+ /immutable@4.3.0:
+ resolution: {integrity: sha512-0AOCmOip+xgJwEVTQj1EfiDDOkPmuyllDuTuEX+DDXUgapLAsBIfkg3sxCYyCEA8mQqZrrxPUGjcOQ2JS3WLkg==}
+
+ /internal-slot@1.0.5:
+ resolution: {integrity: sha512-Y+R5hJrzs52QCG2laLn4udYVnxsfny9CpOhNhUvk/SSSVyF6T27FzRbF0sroPidSu3X8oEAkOn2K804mjpt6UQ==}
+ engines: {node: '>= 0.4'}
+ dependencies:
+ get-intrinsic: 1.2.1
+ has: 1.0.3
+ side-channel: 1.0.4
+ dev: true
+
+ /is-arguments@1.1.1:
+ resolution: {integrity: sha512-8Q7EARjzEnKpt/PCD7e1cgUS0a6X8u5tdSiMqXhojOdoV9TsMsiO+9VLC5vAmO8N7/GmXn7yjR8qnA6bVAEzfA==}
+ engines: {node: '>= 0.4'}
+ dependencies:
+ call-bind: 1.0.2
+ has-tostringtag: 1.0.0
+ dev: true
+
+ /is-array-buffer@3.0.2:
+ resolution: {integrity: sha512-y+FyyR/w8vfIRq4eQcM1EYgSTnmHXPqaF+IgzgraytCFq5Xh8lllDVmAZolPJiZttZLeFSINPYMaEJ7/vWUa1w==}
+ dependencies:
+ call-bind: 1.0.2
+ get-intrinsic: 1.2.1
+ is-typed-array: 1.1.10
+ dev: true
+
+ /is-bigint@1.0.4:
+ resolution: {integrity: sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==}
+ dependencies:
+ has-bigints: 1.0.2
+ dev: true
+
+ /is-binary-path@2.1.0:
+ resolution: {integrity: sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==}
+ engines: {node: '>=8'}
+ dependencies:
+ binary-extensions: 2.2.0
+
+ /is-boolean-object@1.1.2:
+ resolution: {integrity: sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==}
+ engines: {node: '>= 0.4'}
+ dependencies:
+ call-bind: 1.0.2
+ has-tostringtag: 1.0.0
+ dev: true
+
+ /is-callable@1.2.7:
+ resolution: {integrity: sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==}
+ engines: {node: '>= 0.4'}
+ dev: true
+
+ /is-date-object@1.0.5:
+ resolution: {integrity: sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==}
+ engines: {node: '>= 0.4'}
+ dependencies:
+ has-tostringtag: 1.0.0
+ dev: true
+
+ /is-extglob@2.1.1:
+ resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==}
+ engines: {node: '>=0.10.0'}
+
+ /is-glob@4.0.3:
+ resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==}
+ engines: {node: '>=0.10.0'}
+ dependencies:
+ is-extglob: 2.1.1
+
+ /is-map@2.0.2:
+ resolution: {integrity: sha512-cOZFQQozTha1f4MxLFzlgKYPTyj26picdZTx82hbc/Xf4K/tZOOXSCkMvU4pKioRXGDLJRn0GM7Upe7kR721yg==}
+ dev: true
+
+ /is-number-object@1.0.7:
+ resolution: {integrity: sha512-k1U0IRzLMo7ZlYIfzRu23Oh6MiIFasgpb9X76eqfFZAqwH44UI4KTBvBYIZ1dSL9ZzChTB9ShHfLkR4pdW5krQ==}
+ engines: {node: '>= 0.4'}
+ dependencies:
+ has-tostringtag: 1.0.0
+ dev: true
+
+ /is-number@7.0.0:
+ resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==}
+ engines: {node: '>=0.12.0'}
+
+ /is-regex@1.1.4:
+ resolution: {integrity: sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==}
+ engines: {node: '>= 0.4'}
+ dependencies:
+ call-bind: 1.0.2
+ has-tostringtag: 1.0.0
+ dev: true
+
+ /is-set@2.0.2:
+ resolution: {integrity: sha512-+2cnTEZeY5z/iXGbLhPrOAaK/Mau5k5eXq9j14CpRTftq0pAJu2MwVRSZhyZWBzx3o6X795Lz6Bpb6R0GKf37g==}
+ dev: true
+
+ /is-shared-array-buffer@1.0.2:
+ resolution: {integrity: sha512-sqN2UDu1/0y6uvXyStCOzyhAjCSlHceFoMKJW8W9EU9cvic/QdsZ0kEU93HEy3IUEFZIiH/3w+AH/UQbPHNdhA==}
+ dependencies:
+ call-bind: 1.0.2
+ dev: true
+
+ /is-stream@2.0.1:
+ resolution: {integrity: sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==}
+ engines: {node: '>=8'}
+ dev: true
+
+ /is-string@1.0.7:
+ resolution: {integrity: sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==}
+ engines: {node: '>= 0.4'}
+ dependencies:
+ has-tostringtag: 1.0.0
+ dev: true
+
+ /is-symbol@1.0.4:
+ resolution: {integrity: sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==}
+ engines: {node: '>= 0.4'}
+ dependencies:
+ has-symbols: 1.0.3
+ dev: true
+
+ /is-typed-array@1.1.10:
+ resolution: {integrity: sha512-PJqgEHiWZvMpaFZ3uTc8kHPM4+4ADTlDniuQL7cU/UDA0Ql7F70yGfHph3cLNe+c9toaigv+DFzTJKhc2CtO6A==}
+ engines: {node: '>= 0.4'}
+ dependencies:
+ available-typed-arrays: 1.0.5
+ call-bind: 1.0.2
+ for-each: 0.3.3
+ gopd: 1.0.1
+ has-tostringtag: 1.0.0
+ dev: true
+
+ /is-weakmap@2.0.1:
+ resolution: {integrity: sha512-NSBR4kH5oVj1Uwvv970ruUkCV7O1mzgVFO4/rev2cLRda9Tm9HrL70ZPut4rOHgY0FNrUu9BCbXA2sdQ+x0chA==}
+ dev: true
+
+ /is-weakset@2.0.2:
+ resolution: {integrity: sha512-t2yVvttHkQktwnNNmBQ98AhENLdPUTDTE21uPqAQ0ARwQfGeQKRVS0NNurH7bTf7RrvcVn1OOge45CnBeHCSmg==}
+ dependencies:
+ call-bind: 1.0.2
+ get-intrinsic: 1.2.1
+ dev: true
+
+ /isarray@2.0.5:
+ resolution: {integrity: sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==}
+ dev: true
+
+ /isexe@2.0.0:
+ resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==}
+ dev: true
+
+ /jiti@1.18.2:
+ resolution: {integrity: sha512-QAdOptna2NYiSSpv0O/BwoHBSmz4YhpzJHyi+fnMRTXFjp7B8i/YG5Z8IfusxB1ufjcD2Sre1F3R+nX3fvy7gg==}
+ hasBin: true
+ dev: true
+
+ /json5@2.2.3:
+ resolution: {integrity: sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==}
+ engines: {node: '>=6'}
+ hasBin: true
+ dev: true
+
+ /kolorist@1.8.0:
+ resolution: {integrity: sha512-Y+60/zizpJ3HRH8DCss+q95yr6145JXZo46OTpFvDZWLfRCE4qChOyk1b26nMaNpfHHgxagk9dXT5OP0Tfe+dQ==}
+ dev: true
+
+ /local-pkg@0.4.3:
+ resolution: {integrity: sha512-SFppqq5p42fe2qcZQqqEOiVRXl+WCP1MdT6k7BDEW1j++sp5fIY+/fdRQitvKgB5BrBcmrs5m/L0v2FrU5MY1g==}
+ engines: {node: '>=14'}
+ dev: true
+
+ /locate-path@6.0.0:
+ resolution: {integrity: sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==}
+ engines: {node: '>=10'}
+ dependencies:
+ p-locate: 5.0.0
+ dev: true
+
+ /lodash-es@4.17.21:
+ resolution: {integrity: sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw==}
+ dev: false
+
+ /magic-string@0.30.0:
+ resolution: {integrity: sha512-LA+31JYDJLs82r2ScLrlz1GjSgu66ZV518eyWT+S8VhyQn/JL0u9MeBOvQMGYiPk1DBiSN9DDMOcXvigJZaViQ==}
+ engines: {node: '>=12'}
+ dependencies:
+ '@jridgewell/sourcemap-codec': 1.4.15
+
+ /merge-stream@2.0.0:
+ resolution: {integrity: sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==}
+ dev: true
+
+ /merge2@1.4.1:
+ resolution: {integrity: sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==}
+ engines: {node: '>= 8'}
+ dev: true
+
+ /micromatch@4.0.5:
+ resolution: {integrity: sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==}
+ engines: {node: '>=8.6'}
+ dependencies:
+ braces: 3.0.2
+ picomatch: 2.3.1
+ dev: true
+
+ /mimic-fn@2.1.0:
+ resolution: {integrity: sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==}
+ engines: {node: '>=6'}
+ dev: true
+
+ /ms@2.1.2:
+ resolution: {integrity: sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==}
+ dev: true
+
+ /nanoid@3.3.6:
+ resolution: {integrity: sha512-BGcqMMJuToF7i1rt+2PWSNVnWIkGCU78jBG3RxO/bZlnZPK2Cmi2QaffxGO/2RvWi9sL+FAiRiXMgsyxQ1DIDA==}
+ engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1}
+ hasBin: true
+
+ /normalize-path@3.0.0:
+ resolution: {integrity: sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==}
+ engines: {node: '>=0.10.0'}
+
+ /npm-run-path@4.0.1:
+ resolution: {integrity: sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==}
+ engines: {node: '>=8'}
+ dependencies:
+ path-key: 3.1.1
+ dev: true
+
+ /object-inspect@1.12.3:
+ resolution: {integrity: sha512-geUvdk7c+eizMNUDkRpW1wJwgfOiOeHbxBR/hLXK1aT6zmVSO0jsQcs7fj6MGw89jC/cjGfLcNOrtMYtGqm81g==}
+ dev: true
+
+ /object-is@1.1.5:
+ resolution: {integrity: sha512-3cyDsyHgtmi7I7DfSSI2LDp6SK2lwvtbg0p0R1e0RvTqF5ceGx+K2dfSjm1bKDMVCFEDAQvy+o8c6a7VujOddw==}
+ engines: {node: '>= 0.4'}
+ dependencies:
+ call-bind: 1.0.2
+ define-properties: 1.2.0
+ dev: true
+
+ /object-keys@1.1.1:
+ resolution: {integrity: sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==}
+ engines: {node: '>= 0.4'}
+ dev: true
+
+ /object.assign@4.1.4:
+ resolution: {integrity: sha512-1mxKf0e58bvyjSCtKYY4sRe9itRk3PJpquJOjeIkz885CczcI4IvJJDLPS72oowuSh+pBxUFROpX+TU++hxhZQ==}
+ engines: {node: '>= 0.4'}
+ dependencies:
+ call-bind: 1.0.2
+ define-properties: 1.2.0
+ has-symbols: 1.0.3
+ object-keys: 1.1.1
+ dev: true
+
+ /onetime@5.1.2:
+ resolution: {integrity: sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==}
+ engines: {node: '>=6'}
+ dependencies:
+ mimic-fn: 2.1.0
+ dev: true
+
+ /p-limit@3.1.0:
+ resolution: {integrity: sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==}
+ engines: {node: '>=10'}
+ dependencies:
+ yocto-queue: 0.1.0
+ dev: true
+
+ /p-locate@5.0.0:
+ resolution: {integrity: sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==}
+ engines: {node: '>=10'}
+ dependencies:
+ p-limit: 3.1.0
+ dev: true
+
+ /parse-code-context@1.0.0:
+ resolution: {integrity: sha512-OZQaqKaQnR21iqhlnPfVisFjBWjhnMl5J9MgbP8xC+EwoVqbXrq78lp+9Zb3ahmLzrIX5Us/qbvBnaS3hkH6OA==}
+ engines: {node: '>=6'}
+ dev: true
+
+ /path-exists@4.0.0:
+ resolution: {integrity: sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==}
+ engines: {node: '>=8'}
+ dev: true
+
+ /path-key@3.1.1:
+ resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==}
+ engines: {node: '>=8'}
+ dev: true
+
+ /picocolors@1.0.0:
+ resolution: {integrity: sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==}
+
+ /picomatch@2.3.1:
+ resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==}
+ engines: {node: '>=8.6'}
+
+ /postcss@8.4.23:
+ resolution: {integrity: sha512-bQ3qMcpF6A/YjR55xtoTr0jGOlnPOKAIMdOWiv0EIT6HVPEaJiJB4NLljSbiHoC2RX7DN5Uvjtpbg1NPdwv1oA==}
+ engines: {node: ^10 || ^12 || >=14}
+ dependencies:
+ nanoid: 3.3.6
+ picocolors: 1.0.0
+ source-map-js: 1.0.2
+
+ /queue-microtask@1.2.3:
+ resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==}
+ dev: true
+
+ /readdirp@3.6.0:
+ resolution: {integrity: sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==}
+ engines: {node: '>=8.10.0'}
+ dependencies:
+ picomatch: 2.3.1
+
+ /reconnecting-websocket@4.4.0:
+ resolution: {integrity: sha512-D2E33ceRPga0NvTDhJmphEgJ7FUYF0v4lr1ki0csq06OdlxKfugGzN0dSkxM/NfqCxYELK4KcaTOUOjTV6Dcng==}
+ dev: false
+
+ /regexp.prototype.flags@1.5.0:
+ resolution: {integrity: sha512-0SutC3pNudRKgquxGoRGIz946MZVHqbNfPjBdxeOhBrdgDKlRoXmYLQN9xRbrR09ZXWeGAdPuif7egofn6v5LA==}
+ engines: {node: '>= 0.4'}
+ dependencies:
+ call-bind: 1.0.2
+ define-properties: 1.2.0
+ functions-have-names: 1.2.3
+ dev: true
+
+ /reusify@1.0.4:
+ resolution: {integrity: sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==}
+ engines: {iojs: '>=1.0.0', node: '>=0.10.0'}
+ dev: true
+
+ /rollup@3.23.0:
+ resolution: {integrity: sha512-h31UlwEi7FHihLe1zbk+3Q7z1k/84rb9BSwmBSr/XjOCEaBJ2YyedQDuM0t/kfOS0IxM+vk1/zI9XxYj9V+NJQ==}
+ engines: {node: '>=14.18.0', npm: '>=8.0.0'}
+ hasBin: true
+ optionalDependencies:
+ fsevents: 2.3.2
+ dev: true
+
+ /run-parallel@1.2.0:
+ resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==}
+ dependencies:
+ queue-microtask: 1.2.3
+ dev: true
+
+ /sass@1.62.1:
+ resolution: {integrity: sha512-NHpxIzN29MXvWiuswfc1W3I0N8SXBd8UR26WntmDlRYf0bSADnwnOjsyMZ3lMezSlArD33Vs3YFhp7dWvL770A==}
+ engines: {node: '>=14.0.0'}
+ hasBin: true
+ dependencies:
+ chokidar: 3.5.3
+ immutable: 4.3.0
+ source-map-js: 1.0.2
+
+ /shebang-command@2.0.0:
+ resolution: {integrity: sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==}
+ engines: {node: '>=8'}
+ dependencies:
+ shebang-regex: 3.0.0
+ dev: true
+
+ /shebang-regex@3.0.0:
+ resolution: {integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==}
+ engines: {node: '>=8'}
+ dev: true
+
+ /side-channel@1.0.4:
+ resolution: {integrity: sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==}
+ dependencies:
+ call-bind: 1.0.2
+ get-intrinsic: 1.2.1
+ object-inspect: 1.12.3
+ dev: true
+
+ /signal-exit@3.0.7:
+ resolution: {integrity: sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==}
+ dev: true
+
+ /source-map-js@1.0.2:
+ resolution: {integrity: sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==}
+ engines: {node: '>=0.10.0'}
+
+ /stop-iteration-iterator@1.0.0:
+ resolution: {integrity: sha512-iCGQj+0l0HOdZ2AEeBADlsRC+vsnDsZsbdSiH1yNSjcfKM7fdpCMfqAL/dwF5BLiw/XhRft/Wax6zQbhq2BcjQ==}
+ engines: {node: '>= 0.4'}
+ dependencies:
+ internal-slot: 1.0.5
+ dev: true
+
+ /strip-final-newline@2.0.0:
+ resolution: {integrity: sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==}
+ engines: {node: '>=6'}
+ dev: true
+
+ /to-fast-properties@2.0.0:
+ resolution: {integrity: sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==}
+ engines: {node: '>=4'}
+
+ /to-regex-range@5.0.1:
+ resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==}
+ engines: {node: '>=8.0'}
+ dependencies:
+ is-number: 7.0.0
+
+ /typescript@5.0.4:
+ resolution: {integrity: sha512-cW9T5W9xY37cc+jfEnaUvX91foxtHkza3Nw3wkoF4sSlKn0MONdkdEndig/qPBWXNkmplh3NzayQzCiHM4/hqw==}
+ engines: {node: '>=12.20'}
+ hasBin: true
+ dev: true
+
+ /unplugin-icons@0.16.1:
+ resolution: {integrity: sha512-qTunFUkpAyDnwzwV7YV1ZgCWRYfLuURcCurhhXOWMy2ipY88qx1pADvral2hJu4Xymh0X0t3Zcll3BIru2AVLQ==}
+ peerDependencies:
+ '@svgr/core': '>=7.0.0'
+ '@vue/compiler-sfc': ^3.0.2 || ^2.7.0
+ vue-template-compiler: ^2.6.12
+ vue-template-es2015-compiler: ^1.9.0
+ peerDependenciesMeta:
+ '@svgr/core':
+ optional: true
+ '@vue/compiler-sfc':
+ optional: true
+ vue-template-compiler:
+ optional: true
+ vue-template-es2015-compiler:
+ optional: true
+ dependencies:
+ '@antfu/install-pkg': 0.1.1
+ '@antfu/utils': 0.7.2
+ '@iconify/utils': 2.1.5
+ debug: 4.3.4
+ kolorist: 1.8.0
+ local-pkg: 0.4.3
+ unplugin: 1.3.1
+ transitivePeerDependencies:
+ - supports-color
+ dev: true
+
+ /unplugin@1.3.1:
+ resolution: {integrity: sha512-h4uUTIvFBQRxUKS2Wjys6ivoeofGhxzTe2sRWlooyjHXVttcVfV/JiavNd3d4+jty0SVV0dxGw9AkY9MwiaCEw==}
+ dependencies:
+ acorn: 8.8.2
+ chokidar: 3.5.3
+ webpack-sources: 3.2.3
+ webpack-virtual-modules: 0.5.0
+ dev: true
+
+ /vite-plugin-pages@0.30.1(vite@4.3.8):
+ resolution: {integrity: sha512-PHneaWBKA4MaUn0/KTBG+dGT+5V5VhTnOnMCE+HJmixxEkFj7PrgSVGFJjWvgHUflrRE7p2O67iC5cIWLzPDyQ==}
+ peerDependencies:
+ '@vue/compiler-sfc': ^2.7.0 || ^3.0.0
+ vite: ^2.0.0 || ^3.0.0-0 || ^4.0.0
+ peerDependenciesMeta:
+ '@vue/compiler-sfc':
+ optional: true
+ dependencies:
+ '@types/debug': 4.1.8
+ debug: 4.3.4
+ deep-equal: 2.2.1
+ extract-comments: 1.1.0
+ fast-glob: 3.2.12
+ json5: 2.2.3
+ local-pkg: 0.4.3
+ picocolors: 1.0.0
+ vite: 4.3.8(sass@1.62.1)
+ yaml: 2.2.2
+ transitivePeerDependencies:
+ - supports-color
+ dev: true
+
+ /vite-plugin-windicss@1.9.0(vite@4.3.8):
+ resolution: {integrity: sha512-w0unPfcbVU5eaISAsFTLgIb41SLhmXoUF75Othu8NqFioe8+DEqiuvJ7/k/LRuEuvI8Rt/OKrY6cNzrB+dykaA==}
+ peerDependencies:
+ vite: ^2.0.1 || ^3.0.0 || ^4.0.0
+ dependencies:
+ '@windicss/plugin-utils': 1.9.0
+ debug: 4.3.4
+ kolorist: 1.8.0
+ vite: 4.3.8(sass@1.62.1)
+ windicss: 3.5.6
+ transitivePeerDependencies:
+ - supports-color
+ dev: true
+
+ /vite@4.3.8(sass@1.62.1):
+ resolution: {integrity: sha512-uYB8PwN7hbMrf4j1xzGDk/lqjsZvCDbt/JC5dyfxc19Pg8kRm14LinK/uq+HSLNswZEoKmweGdtpbnxRtrAXiQ==}
+ engines: {node: ^14.18.0 || >=16.0.0}
+ hasBin: true
+ peerDependencies:
+ '@types/node': '>= 14'
+ less: '*'
+ sass: '*'
+ stylus: '*'
+ sugarss: '*'
+ terser: ^5.4.0
+ peerDependenciesMeta:
+ '@types/node':
+ optional: true
+ less:
+ optional: true
+ sass:
+ optional: true
+ stylus:
+ optional: true
+ sugarss:
+ optional: true
+ terser:
+ optional: true
+ dependencies:
+ esbuild: 0.17.19
+ postcss: 8.4.23
+ rollup: 3.23.0
+ sass: 1.62.1
+ optionalDependencies:
+ fsevents: 2.3.2
+ dev: true
+
+ /vue-demi@0.14.5(vue@3.3.4):
+ resolution: {integrity: sha512-o9NUVpl/YlsGJ7t+xuqJKx8EBGf1quRhCiT6D/J0pfwmk9zUwYkC7yrF4SZCe6fETvSM3UNL2edcbYrSyc4QHA==}
+ engines: {node: '>=12'}
+ hasBin: true
+ requiresBuild: true
+ peerDependencies:
+ '@vue/composition-api': ^1.0.0-rc.1
+ vue: ^3.0.0-0 || ^2.6.0
+ peerDependenciesMeta:
+ '@vue/composition-api':
+ optional: true
+ dependencies:
+ vue: 3.3.4
+ dev: false
+
+ /vue-router@4.2.1(vue@3.3.4):
+ resolution: {integrity: sha512-nW28EeifEp8Abc5AfmAShy5ZKGsGzjcnZ3L1yc2DYUo+MqbBClrRP9yda3dIekM4I50/KnEwo1wkBLf7kHH5Cw==}
+ peerDependencies:
+ vue: ^3.2.0
+ dependencies:
+ '@vue/devtools-api': 6.5.0
+ vue: 3.3.4
+ dev: false
+
+ /vue@3.3.4:
+ resolution: {integrity: sha512-VTyEYn3yvIeY1Py0WaYGZsXnz3y5UnGi62GjVEqvEGPl6nxbOrCXbVOTQWBEJUqAyTUk2uJ5JLVnYJ6ZzGbrSw==}
+ dependencies:
+ '@vue/compiler-dom': 3.3.4
+ '@vue/compiler-sfc': 3.3.4
+ '@vue/runtime-dom': 3.3.4
+ '@vue/server-renderer': 3.3.4(vue@3.3.4)
+ '@vue/shared': 3.3.4
+
+ /webpack-sources@3.2.3:
+ resolution: {integrity: sha512-/DyMEOrDgLKKIG0fmvtz+4dUX/3Ghozwgm6iPp8KRhvn+eQf9+Q7GWxVNMk3+uCPWfdXYC4ExGBckIXdFEfH1w==}
+ engines: {node: '>=10.13.0'}
+ dev: true
+
+ /webpack-virtual-modules@0.5.0:
+ resolution: {integrity: sha512-kyDivFZ7ZM0BVOUteVbDFhlRt7Ah/CSPwJdi8hBpkK7QLumUqdLtVfm/PX/hkcnrvr0i77fO5+TjZ94Pe+C9iw==}
+ dev: true
+
+ /which-boxed-primitive@1.0.2:
+ resolution: {integrity: sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==}
+ dependencies:
+ is-bigint: 1.0.4
+ is-boolean-object: 1.1.2
+ is-number-object: 1.0.7
+ is-string: 1.0.7
+ is-symbol: 1.0.4
+ dev: true
+
+ /which-collection@1.0.1:
+ resolution: {integrity: sha512-W8xeTUwaln8i3K/cY1nGXzdnVZlidBcagyNFtBdD5kxnb4TvGKR7FfSIS3mYpwWS1QUCutfKz8IY8RjftB0+1A==}
+ dependencies:
+ is-map: 2.0.2
+ is-set: 2.0.2
+ is-weakmap: 2.0.1
+ is-weakset: 2.0.2
+ dev: true
+
+ /which-typed-array@1.1.9:
+ resolution: {integrity: sha512-w9c4xkx6mPidwp7180ckYWfMmvxpjlZuIudNtDf4N/tTAUB8VJbX25qZoAsrtGuYNnGw3pa0AXgbGKRB8/EceA==}
+ engines: {node: '>= 0.4'}
+ dependencies:
+ available-typed-arrays: 1.0.5
+ call-bind: 1.0.2
+ for-each: 0.3.3
+ gopd: 1.0.1
+ has-tostringtag: 1.0.0
+ is-typed-array: 1.1.10
+ dev: true
+
+ /which@2.0.2:
+ resolution: {integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==}
+ engines: {node: '>= 8'}
+ hasBin: true
+ dependencies:
+ isexe: 2.0.0
+ dev: true
+
+ /windicss@3.5.6:
+ resolution: {integrity: sha512-P1mzPEjgFMZLX0ZqfFht4fhV/FX8DTG7ERG1fBLiWvd34pTLVReS5CVsewKn9PApSgXnVfPWwvq+qUsRwpnwFA==}
+ engines: {node: '>= 12'}
+ hasBin: true
+ dev: true
+
+ /yaml@2.2.2:
+ resolution: {integrity: sha512-CBKFWExMn46Foo4cldiChEzn7S7SRV+wqiluAb6xmueD/fGyRHIhX8m14vVGgeFWjN540nKCNVj6P21eQjgTuA==}
+ engines: {node: '>= 14'}
+ dev: true
+
+ /yocto-queue@0.1.0:
+ resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==}
+ engines: {node: '>=10'}
+ dev: true
diff --git a/ui/server/package.json b/ui/server/package.json
new file mode 100755
index 0000000..df182c5
--- /dev/null
+++ b/ui/server/package.json
@@ -0,0 +1,17 @@
+{
+ "main": "index.js",
+ "scripts": {
+ "dev": "tsx watch src/main.ts"
+ },
+ "devDependencies": {
+ "@types/node": "^18.0.1",
+ "@types/ws": "^8.5.3",
+ "tsx": "^3.7.1",
+ "typescript": "^4.7.4"
+ },
+ "dependencies": {
+ "bufferutil": "^4.0.6",
+ "utf-8-validate": "^5.0.9",
+ "ws": "^8.8.0"
+ }
+}
diff --git a/ui/server/pnpm-lock.yaml b/ui/server/pnpm-lock.yaml
new file mode 100755
index 0000000..92a22f2
--- /dev/null
+++ b/ui/server/pnpm-lock.yaml
@@ -0,0 +1,344 @@
+lockfileVersion: 5.4
+
+specifiers:
+ '@types/node': ^18.0.1
+ '@types/ws': ^8.5.3
+ bufferutil: ^4.0.6
+ tsx: ^3.7.1
+ typescript: ^4.7.4
+ utf-8-validate: ^5.0.9
+ ws: ^8.8.0
+
+dependencies:
+ bufferutil: 4.0.6
+ utf-8-validate: 5.0.9
+ ws: 8.8.0_22kvxa7zeyivx4jp72v2w3pkvy
+
+devDependencies:
+ '@types/node': 18.0.1
+ '@types/ws': 8.5.3
+ tsx: 3.7.1
+ typescript: 4.7.4
+
+packages:
+
+ /@esbuild-kit/cjs-loader/2.3.0:
+ resolution: {integrity: sha512-KInrVt8wlKLhWy7+y4a+E+0uBJoWgdx6Xupy+rrF4MFHA/dEt22ACvvChOZSyiqtQieYPtbPkVYSjbC7mOrFVw==}
+ dependencies:
+ '@esbuild-kit/core-utils': 2.0.2
+ get-tsconfig: 4.1.0
+ dev: true
+
+ /@esbuild-kit/core-utils/2.0.2:
+ resolution: {integrity: sha512-clNYQUsqtc36pzW5EufMsahcbLG45EaW3YDyf0DlaS0eCMkDXpxIlHwPC0rndUwG6Ytk9sMSD5k1qHbwYEC/OQ==}
+ dependencies:
+ esbuild: 0.14.48
+ source-map-support: 0.5.21
+ dev: true
+
+ /@esbuild-kit/esm-loader/2.4.0:
+ resolution: {integrity: sha512-zS720jXh06nfg5yAzm6oob4sWN9VTP2E1SonhFgEb6zCBswa4S8fOQ/4Bksz1flDgn56NPqoTTDn2XmWRyMG9Q==}
+ dependencies:
+ '@esbuild-kit/core-utils': 2.0.2
+ get-tsconfig: 4.1.0
+ dev: true
+
+ /@types/node/18.0.1:
+ resolution: {integrity: sha512-CmR8+Tsy95hhwtZBKJBs0/FFq4XX7sDZHlGGf+0q+BRZfMbOTkzkj0AFAuTyXbObDIoanaBBW0+KEW+m3N16Wg==}
+ dev: true
+
+ /@types/ws/8.5.3:
+ resolution: {integrity: sha512-6YOoWjruKj1uLf3INHH7D3qTXwFfEsg1kf3c0uDdSBJwfa/llkwIjrAGV7j7mVgGNbzTQ3HiHKKDXl6bJPD97w==}
+ dependencies:
+ '@types/node': 18.0.1
+ dev: true
+
+ /buffer-from/1.1.2:
+ resolution: {integrity: sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==}
+ dev: true
+
+ /bufferutil/4.0.6:
+ resolution: {integrity: sha512-jduaYOYtnio4aIAyc6UbvPCVcgq7nYpVnucyxr6eCYg/Woad9Hf/oxxBRDnGGjPfjUm6j5O/uBWhIu4iLebFaw==}
+ engines: {node: '>=6.14.2'}
+ requiresBuild: true
+ dependencies:
+ node-gyp-build: 4.5.0
+ dev: false
+
+ /esbuild-android-64/0.14.48:
+ resolution: {integrity: sha512-3aMjboap/kqwCUpGWIjsk20TtxVoKck8/4Tu19rubh7t5Ra0Yrpg30Mt1QXXlipOazrEceGeWurXKeFJgkPOUg==}
+ engines: {node: '>=12'}
+ cpu: [x64]
+ os: [android]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /esbuild-android-arm64/0.14.48:
+ resolution: {integrity: sha512-vptI3K0wGALiDq+EvRuZotZrJqkYkN5282iAfcffjI5lmGG9G1ta/CIVauhY42MBXwEgDJkweiDcDMRLzBZC4g==}
+ engines: {node: '>=12'}
+ cpu: [arm64]
+ os: [android]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /esbuild-darwin-64/0.14.48:
+ resolution: {integrity: sha512-gGQZa4+hab2Va/Zww94YbshLuWteyKGD3+EsVon8EWTWhnHFRm5N9NbALNbwi/7hQ/hM1Zm4FuHg+k6BLsl5UA==}
+ engines: {node: '>=12'}
+ cpu: [x64]
+ os: [darwin]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /esbuild-darwin-arm64/0.14.48:
+ resolution: {integrity: sha512-bFjnNEXjhZT+IZ8RvRGNJthLWNHV5JkCtuOFOnjvo5pC0sk2/QVk0Qc06g2PV3J0TcU6kaPC3RN9yy9w2PSLEA==}
+ engines: {node: '>=12'}
+ cpu: [arm64]
+ os: [darwin]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /esbuild-freebsd-64/0.14.48:
+ resolution: {integrity: sha512-1NOlwRxmOsnPcWOGTB10JKAkYSb2nue0oM1AfHWunW/mv3wERfJmnYlGzL3UAOIUXZqW8GeA2mv+QGwq7DToqA==}
+ engines: {node: '>=12'}
+ cpu: [x64]
+ os: [freebsd]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /esbuild-freebsd-arm64/0.14.48:
+ resolution: {integrity: sha512-gXqKdO8wabVcYtluAbikDH2jhXp+Klq5oCD5qbVyUG6tFiGhrC9oczKq3vIrrtwcxDQqK6+HDYK8Zrd4bCA9Gw==}
+ engines: {node: '>=12'}
+ cpu: [arm64]
+ os: [freebsd]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /esbuild-linux-32/0.14.48:
+ resolution: {integrity: sha512-ghGyDfS289z/LReZQUuuKq9KlTiTspxL8SITBFQFAFRA/IkIvDpnZnCAKTCjGXAmUqroMQfKJXMxyjJA69c/nQ==}
+ engines: {node: '>=12'}
+ cpu: [ia32]
+ os: [linux]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /esbuild-linux-64/0.14.48:
+ resolution: {integrity: sha512-vni3p/gppLMVZLghI7oMqbOZdGmLbbKR23XFARKnszCIBpEMEDxOMNIKPmMItQrmH/iJrL1z8Jt2nynY0bE1ug==}
+ engines: {node: '>=12'}
+ cpu: [x64]
+ os: [linux]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /esbuild-linux-arm/0.14.48:
+ resolution: {integrity: sha512-+VfSV7Akh1XUiDNXgqgY1cUP1i2vjI+BmlyXRfVz5AfV3jbpde8JTs5Q9sYgaoq5cWfuKfoZB/QkGOI+QcL1Tw==}
+ engines: {node: '>=12'}
+ cpu: [arm]
+ os: [linux]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /esbuild-linux-arm64/0.14.48:
+ resolution: {integrity: sha512-3CFsOlpoxlKPRevEHq8aAntgYGYkE1N9yRYAcPyng/p4Wyx0tPR5SBYsxLKcgPB9mR8chHEhtWYz6EZ+H199Zw==}
+ engines: {node: '>=12'}
+ cpu: [arm64]
+ os: [linux]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /esbuild-linux-mips64le/0.14.48:
+ resolution: {integrity: sha512-cs0uOiRlPp6ymknDnjajCgvDMSsLw5mST2UXh+ZIrXTj2Ifyf2aAP3Iw4DiqgnyYLV2O/v/yWBJx+WfmKEpNLA==}
+ engines: {node: '>=12'}
+ cpu: [mips64el]
+ os: [linux]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /esbuild-linux-ppc64le/0.14.48:
+ resolution: {integrity: sha512-+2F0vJMkuI0Wie/wcSPDCqXvSFEELH7Jubxb7mpWrA/4NpT+/byjxDz0gG6R1WJoeDefcrMfpBx4GFNN1JQorQ==}
+ engines: {node: '>=12'}
+ cpu: [ppc64]
+ os: [linux]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /esbuild-linux-riscv64/0.14.48:
+ resolution: {integrity: sha512-BmaK/GfEE+5F2/QDrIXteFGKnVHGxlnK9MjdVKMTfvtmudjY3k2t8NtlY4qemKSizc+QwyombGWTBDc76rxePA==}
+ engines: {node: '>=12'}
+ cpu: [riscv64]
+ os: [linux]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /esbuild-linux-s390x/0.14.48:
+ resolution: {integrity: sha512-tndw/0B9jiCL+KWKo0TSMaUm5UWBLsfCKVdbfMlb3d5LeV9WbijZ8Ordia8SAYv38VSJWOEt6eDCdOx8LqkC4g==}
+ engines: {node: '>=12'}
+ cpu: [s390x]
+ os: [linux]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /esbuild-netbsd-64/0.14.48:
+ resolution: {integrity: sha512-V9hgXfwf/T901Lr1wkOfoevtyNkrxmMcRHyticybBUHookznipMOHoF41Al68QBsqBxnITCEpjjd4yAos7z9Tw==}
+ engines: {node: '>=12'}
+ cpu: [x64]
+ os: [netbsd]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /esbuild-openbsd-64/0.14.48:
+ resolution: {integrity: sha512-+IHf4JcbnnBl4T52egorXMatil/za0awqzg2Vy6FBgPcBpisDWT2sVz/tNdrK9kAqj+GZG/jZdrOkj7wsrNTKA==}
+ engines: {node: '>=12'}
+ cpu: [x64]
+ os: [openbsd]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /esbuild-sunos-64/0.14.48:
+ resolution: {integrity: sha512-77m8bsr5wOpOWbGi9KSqDphcq6dFeJyun8TA+12JW/GAjyfTwVtOnN8DOt6DSPUfEV+ltVMNqtXUeTeMAxl5KA==}
+ engines: {node: '>=12'}
+ cpu: [x64]
+ os: [sunos]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /esbuild-windows-32/0.14.48:
+ resolution: {integrity: sha512-EPgRuTPP8vK9maxpTGDe5lSoIBHGKO/AuxDncg5O3NkrPeLNdvvK8oywB0zGaAZXxYWfNNSHskvvDgmfVTguhg==}
+ engines: {node: '>=12'}
+ cpu: [ia32]
+ os: [win32]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /esbuild-windows-64/0.14.48:
+ resolution: {integrity: sha512-YmpXjdT1q0b8ictSdGwH3M8VCoqPpK1/UArze3X199w6u8hUx3V8BhAi1WjbsfDYRBanVVtduAhh2sirImtAvA==}
+ engines: {node: '>=12'}
+ cpu: [x64]
+ os: [win32]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /esbuild-windows-arm64/0.14.48:
+ resolution: {integrity: sha512-HHaOMCsCXp0rz5BT2crTka6MPWVno121NKApsGs/OIW5QC0ggC69YMGs1aJct9/9FSUF4A1xNE/cLvgB5svR4g==}
+ engines: {node: '>=12'}
+ cpu: [arm64]
+ os: [win32]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /esbuild/0.14.48:
+ resolution: {integrity: sha512-w6N1Yn5MtqK2U1/WZTX9ZqUVb8IOLZkZ5AdHkT6x3cHDMVsYWC7WPdiLmx19w3i4Rwzy5LqsEMtVihG3e4rFzA==}
+ engines: {node: '>=12'}
+ hasBin: true
+ requiresBuild: true
+ optionalDependencies:
+ esbuild-android-64: 0.14.48
+ esbuild-android-arm64: 0.14.48
+ esbuild-darwin-64: 0.14.48
+ esbuild-darwin-arm64: 0.14.48
+ esbuild-freebsd-64: 0.14.48
+ esbuild-freebsd-arm64: 0.14.48
+ esbuild-linux-32: 0.14.48
+ esbuild-linux-64: 0.14.48
+ esbuild-linux-arm: 0.14.48
+ esbuild-linux-arm64: 0.14.48
+ esbuild-linux-mips64le: 0.14.48
+ esbuild-linux-ppc64le: 0.14.48
+ esbuild-linux-riscv64: 0.14.48
+ esbuild-linux-s390x: 0.14.48
+ esbuild-netbsd-64: 0.14.48
+ esbuild-openbsd-64: 0.14.48
+ esbuild-sunos-64: 0.14.48
+ esbuild-windows-32: 0.14.48
+ esbuild-windows-64: 0.14.48
+ esbuild-windows-arm64: 0.14.48
+ dev: true
+
+ /fsevents/2.3.2:
+ resolution: {integrity: sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==}
+ engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0}
+ os: [darwin]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /get-tsconfig/4.1.0:
+ resolution: {integrity: sha512-bhshxJhpfmeQ8x4fAvDqJV2VfGp5TfHdLpmBpNZZhMoVyfIrOippBW4mayC3DT9Sxuhcyl56Efw61qL28hG4EQ==}
+ dev: true
+
+ /node-gyp-build/4.5.0:
+ resolution: {integrity: sha512-2iGbaQBV+ITgCz76ZEjmhUKAKVf7xfY1sRl4UiKQspfZMH2h06SyhNsnSVy50cwkFQDGLyif6m/6uFXHkOZ6rg==}
+ hasBin: true
+ dev: false
+
+ /source-map-support/0.5.21:
+ resolution: {integrity: sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==}
+ dependencies:
+ buffer-from: 1.1.2
+ source-map: 0.6.1
+ dev: true
+
+ /source-map/0.6.1:
+ resolution: {integrity: sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==}
+ engines: {node: '>=0.10.0'}
+ dev: true
+
+ /tsx/3.7.1:
+ resolution: {integrity: sha512-dwl1GBdkwVQ9zRxTmETGi+ck8pewNm2QXh+HK6jHxdHmeCjfCL+Db3b4VX/dOMDSS2hle1j5LzQoo8OpVXu6XQ==}
+ hasBin: true
+ dependencies:
+ '@esbuild-kit/cjs-loader': 2.3.0
+ '@esbuild-kit/core-utils': 2.0.2
+ '@esbuild-kit/esm-loader': 2.4.0
+ optionalDependencies:
+ fsevents: 2.3.2
+ dev: true
+
+ /typescript/4.7.4:
+ resolution: {integrity: sha512-C0WQT0gezHuw6AdY1M2jxUO83Rjf0HP7Sk1DtXj6j1EwkQNZrHAg2XPWlq62oqEhYvONq5pkC2Y9oPljWToLmQ==}
+ engines: {node: '>=4.2.0'}
+ hasBin: true
+ dev: true
+
+ /utf-8-validate/5.0.9:
+ resolution: {integrity: sha512-Yek7dAy0v3Kl0orwMlvi7TPtiCNrdfHNd7Gcc/pLq4BLXqfAmd0J7OWMizUQnTTJsyjKn02mU7anqwfmUP4J8Q==}
+ engines: {node: '>=6.14.2'}
+ requiresBuild: true
+ dependencies:
+ node-gyp-build: 4.5.0
+ dev: false
+
+ /ws/8.8.0_22kvxa7zeyivx4jp72v2w3pkvy:
+ resolution: {integrity: sha512-JDAgSYQ1ksuwqfChJusw1LSJ8BizJ2e/vVu5Lxjq3YvNJNlROv1ui4i+c/kUUrPheBvQl4c5UbERhTwKa6QBJQ==}
+ engines: {node: '>=10.0.0'}
+ peerDependencies:
+ bufferutil: ^4.0.1
+ utf-8-validate: ^5.0.2
+ peerDependenciesMeta:
+ bufferutil:
+ optional: true
+ utf-8-validate:
+ optional: true
+ dependencies:
+ bufferutil: 4.0.6
+ utf-8-validate: 5.0.9
+ dev: false
diff --git a/ui/server/src/main.ts b/ui/server/src/main.ts
new file mode 100755
index 0000000..c9aba23
--- /dev/null
+++ b/ui/server/src/main.ts
@@ -0,0 +1,46 @@
+import { WebSocketServer } from "ws"
+
+const server = new WebSocketServer({
+ clientTracking: true,
+ host: "0.0.0.0",
+ port: 8000
+})
+
+let state = {
+ music: null,
+ message: "",
+ position: {
+ scene: 0,
+ step: 0
+ }
+}
+
+server.on("connection", (client, request) => {
+ const address = request.connection.remoteAddress
+ console.log(`Connected: ${address}`)
+ client.send(JSON.stringify({
+ state,
+ timestamp: Date.now()
+ }))
+
+ client.on("message", rawData => {
+ state = JSON.parse(rawData.toString())
+
+ console.log("Update: ", state)
+
+ server.clients.forEach(c => {
+ if (c !== client) {
+ c.send(JSON.stringify({
+ state,
+ timestamp: Date.now()
+ }))
+ }
+ })
+ })
+
+ client.on("close", () => {
+ console.log(`Disconnected: ${address}`)
+ })
+})
+
+console.log("Listening on ws://0.0.0.0:8000")
diff --git a/ui/src/App.vue b/ui/src/App.vue
new file mode 100755
index 0000000..863c39a
--- /dev/null
+++ b/ui/src/App.vue
@@ -0,0 +1,52 @@
+
+
+
+
Connecting...
+
Created by Moritz Ruth
+
+
+
+
+
+
+
+
+
diff --git a/ui/src/components/ActorsOnStageBox.vue b/ui/src/components/ActorsOnStageBox.vue
new file mode 100755
index 0000000..a38b9cd
--- /dev/null
+++ b/ui/src/components/ActorsOnStageBox.vue
@@ -0,0 +1,23 @@
+
+
+
+
+ auf der Bühne
+
+
+
+
+
+
+
+
+
+
+
diff --git a/ui/src/components/CueBox.vue b/ui/src/components/CueBox.vue
new file mode 100755
index 0000000..c1cd26b
--- /dev/null
+++ b/ui/src/components/CueBox.vue
@@ -0,0 +1,81 @@
+
+
+
+
+
diff --git a/ui/src/components/EntrancesList.vue b/ui/src/components/EntrancesList.vue
new file mode 100755
index 0000000..116b3db
--- /dev/null
+++ b/ui/src/components/EntrancesList.vue
@@ -0,0 +1,54 @@
+
+
+
+
+ {{ parseStringWithDetails(actor).main }}
+
+
+ {{ parseStringWithDetails(actor).details }}
+
+
+
+
+
+
+
+
diff --git a/ui/src/components/MessageDisplay.vue b/ui/src/components/MessageDisplay.vue
new file mode 100755
index 0000000..2b40ea2
--- /dev/null
+++ b/ui/src/components/MessageDisplay.vue
@@ -0,0 +1,46 @@
+
+
+ {{ message }}
+
+
+
+
+
+
diff --git a/ui/src/components/MessageEdit.vue b/ui/src/components/MessageEdit.vue
new file mode 100755
index 0000000..bfda10f
--- /dev/null
+++ b/ui/src/components/MessageEdit.vue
@@ -0,0 +1,23 @@
+
+
+
+
+
+
+
+
diff --git a/ui/src/components/MotionsList.vue b/ui/src/components/MotionsList.vue
new file mode 100755
index 0000000..8187b0f
--- /dev/null
+++ b/ui/src/components/MotionsList.vue
@@ -0,0 +1,35 @@
+
+
+
+
+ {{ scene.name }}
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/ui/src/components/MotionsListScene.vue b/ui/src/components/MotionsListScene.vue
new file mode 100644
index 0000000..d0e7cdb
--- /dev/null
+++ b/ui/src/components/MotionsListScene.vue
@@ -0,0 +1,7 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/ui/src/components/MotionsListStep.vue b/ui/src/components/MotionsListStep.vue
new file mode 100644
index 0000000..77964dd
--- /dev/null
+++ b/ui/src/components/MotionsListStep.vue
@@ -0,0 +1,78 @@
+
+
+
+
+
+
+
+
+
+
+
+ {{ parseStringWithDetails(motion).main }}
+
+
+ {{ parseStringWithDetails(motion).details }}
+
+
+
+
+
+
+
+ {{ parseStringWithDetails(motion).main }}
+
+
+ {{ parseStringWithDetails(motion).details }}
+
+
+
+
+
+
+
+
+ Umbau
+
+
+
+
+
+
\ No newline at end of file
diff --git a/ui/src/components/MusicProgressBar.vue b/ui/src/components/MusicProgressBar.vue
new file mode 100755
index 0000000..3691cc2
--- /dev/null
+++ b/ui/src/components/MusicProgressBar.vue
@@ -0,0 +1,73 @@
+
+
+
+
+
+ {{ lastMusic?.title ?? "" }}
+
+
+ {{ formatSeconds(remainingSeconds) }}
+
+
+
+
+
+
+
+
diff --git a/ui/src/components/PropBox.vue b/ui/src/components/PropBox.vue
new file mode 100755
index 0000000..49b918b
--- /dev/null
+++ b/ui/src/components/PropBox.vue
@@ -0,0 +1,73 @@
+
+
+
+ {{ positionName }}
+
+
+
+
+
+
+ {{ parseStringWithDetails(prop).main }}
+
+
+ {{ parseStringWithDetails(prop).details }}
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/ui/src/components/StageTopDownView.vue b/ui/src/components/StageTopDownView.vue
new file mode 100755
index 0000000..5614294
--- /dev/null
+++ b/ui/src/components/StageTopDownView.vue
@@ -0,0 +1,39 @@
+
+
+
+
+
+
+
diff --git a/ui/src/components/StepSelection.vue b/ui/src/components/StepSelection.vue
new file mode 100755
index 0000000..54005b8
--- /dev/null
+++ b/ui/src/components/StepSelection.vue
@@ -0,0 +1,16 @@
+
+
+
+
+
+
+
+
+
+
diff --git a/ui/src/components/StepSelectionAct.vue b/ui/src/components/StepSelectionAct.vue
new file mode 100644
index 0000000..00c9b2f
--- /dev/null
+++ b/ui/src/components/StepSelectionAct.vue
@@ -0,0 +1,18 @@
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/ui/src/components/StepSelectionScene.vue b/ui/src/components/StepSelectionScene.vue
new file mode 100644
index 0000000..d2af36e
--- /dev/null
+++ b/ui/src/components/StepSelectionScene.vue
@@ -0,0 +1,26 @@
+
+
+
+ {{ scene.name }}
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/ui/src/components/StepSelectionStep.vue b/ui/src/components/StepSelectionStep.vue
new file mode 100644
index 0000000..58779d6
--- /dev/null
+++ b/ui/src/components/StepSelectionStep.vue
@@ -0,0 +1,46 @@
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/ui/src/components/TimeDisplay.vue b/ui/src/components/TimeDisplay.vue
new file mode 100755
index 0000000..e8277ac
--- /dev/null
+++ b/ui/src/components/TimeDisplay.vue
@@ -0,0 +1,21 @@
+
+
+
+ {{ format.format(syncedTime) }}
+
+
+
+
+
+
diff --git a/ui/src/helpers.ts b/ui/src/helpers.ts
new file mode 100755
index 0000000..cd94a9c
--- /dev/null
+++ b/ui/src/helpers.ts
@@ -0,0 +1,28 @@
+import { Ref, ComputedRef, computed, UnwrapRef, ref, watchEffect } from "vue"
+
+export const computedIfPresent = (object: Ref, access: (value: Exclude) => V): ComputedRef => computed(() => {
+ if (object.value === null) return null
+ else if (object.value === undefined) return undefined
+
+ return access(object.value as Exclude)
+})
+
+export const computedOrNull = (object: Ref, access: (value: T) => V): ComputedRef => computed(() => {
+ if (object.value === null) return null
+ return access(object.value)
+})
+
+export function avoidNull(originRef: Ref | null>): ComputedRef | null> {
+ const nullAvoidingRef = ref(null)
+
+ watchEffect(() => {
+ if (originRef.value !== null) nullAvoidingRef.value = originRef.value
+ })
+
+ return computed(() => nullAvoidingRef.value)
+}
+
+export function formatSeconds(seconds: number) {
+ const duration = new Date(seconds * 1000)
+ return `${duration.getMinutes().toFixed()}:${duration.getSeconds().toFixed().padStart(2, '0')}`
+}
diff --git a/ui/src/main.ts b/ui/src/main.ts
new file mode 100755
index 0000000..b6d7435
--- /dev/null
+++ b/ui/src/main.ts
@@ -0,0 +1,22 @@
+import "virtual:windi.css"
+import { createApp } from "vue"
+import { createRouter, createWebHistory, RouteRecordRaw } from "vue-router"
+import App from "./App.vue"
+import originalRoutes from "~pages"
+
+const routes = originalRoutes.map(route => {
+ if (typeof route.component !== "function") return route
+ return {
+ ...route,
+ props: false
+ }
+}) as RouteRecordRaw[]
+
+const router = createRouter({
+ routes,
+ history: createWebHistory()
+})
+
+const app = createApp(App)
+app.use(router)
+app.mount("#app")
diff --git a/ui/src/pages/control-m.vue b/ui/src/pages/control-m.vue
new file mode 100755
index 0000000..d38b5f5
--- /dev/null
+++ b/ui/src/pages/control-m.vue
@@ -0,0 +1,35 @@
+
+
+
+ {{ current.scene.name }}
+
+
+
+
+
+
diff --git a/ui/src/pages/control.vue b/ui/src/pages/control.vue
new file mode 100755
index 0000000..a686be3
--- /dev/null
+++ b/ui/src/pages/control.vue
@@ -0,0 +1,35 @@
+
+
+
+ {{ current.scene.name }}
+
+
+
+
+
+
+
diff --git a/ui/src/pages/kiosk/stage.vue b/ui/src/pages/kiosk/stage.vue
new file mode 100755
index 0000000..0422496
--- /dev/null
+++ b/ui/src/pages/kiosk/stage.vue
@@ -0,0 +1,29 @@
+
+
+
+ {{ current.scene.name }}
+
+
+
+
+
+
+
+
+
diff --git a/ui/src/pages/microphones.vue b/ui/src/pages/microphones.vue
new file mode 100755
index 0000000..f9a42f4
--- /dev/null
+++ b/ui/src/pages/microphones.vue
@@ -0,0 +1,23 @@
+
+
+
+ {{ current.scene.name }}
+
+
+
+
+
+
+
diff --git a/ui/src/pages/rein.vue b/ui/src/pages/rein.vue
new file mode 100755
index 0000000..7a99ff6
--- /dev/null
+++ b/ui/src/pages/rein.vue
@@ -0,0 +1,40 @@
+
+
+
+ {{ current.scene.name }}
+
+
+
+
+
+
+
+
+
diff --git a/ui/src/state.ts b/ui/src/state.ts
new file mode 100755
index 0000000..81f3466
--- /dev/null
+++ b/ui/src/state.ts
@@ -0,0 +1,218 @@
+import { reactive, shallowRef } from "vue"
+import { reactiveComputed } from "@vueuse/core"
+
+export interface Act {
+ name: string
+ scenes: Scene[]
+}
+
+export interface Scene {
+ name: string
+ steps: Step[]
+}
+
+export interface Step {
+ position: ShowPosition
+ cue: StepCue
+ actorEntrances: string[]
+ actorExits: string[]
+ actorsOnStage: string[]
+ props: PropMap
+ hasChangedProps: boolean
+}
+
+export type StepCue = {
+ type: "TEXT",
+ speaker: string
+ text: string
+ clarification?: string
+} | {
+ type: "MUSIC_START",
+ title: string
+ duration: number
+} | {
+ type: "MUSIC_END"
+} | {
+ type: "CURTAIN",
+ state: "open" | "closed"
+ whileMoving: boolean
+} | {
+ type: "LIGHTS"
+ state: "on" | "off"
+ whileFading: boolean
+} | {
+ type: "CUSTOM"
+ text: string
+}
+
+export type PropMap = Record
+export type PropPosition =
+ | "PROSCENIUM_LEFT"
+ | "PROSCENIUM_CENTER"
+ | "PROSCENIUM_RIGHT"
+ | "CENTER"
+ | "LEFT"
+ | "RIGHT"
+ | "BACKDROP"
+
+export interface ShowState {
+ position: ShowPosition
+ message: string
+ activeMusic: ShowMusic | null
+ musicStartTime: number
+}
+
+export interface ShowMusic {
+ title: string
+ duration: number
+}
+
+export interface ShowPosition {
+ act: number
+ scene: number
+ step: number
+}
+
+export interface Show {
+ acts: Act[]
+}
+
+export const START_STEP: Step = {
+ position: { act: -1, scene: 0, step: 0 },
+ actorsOnStage: [],
+ cue: {
+ type: "CUSTOM",
+ text: "Start"
+ },
+ props: {
+ BACKDROP: null,
+ LEFT: null,
+ CENTER: null,
+ RIGHT: null,
+ PROSCENIUM_LEFT: null,
+ PROSCENIUM_CENTER: null,
+ PROSCENIUM_RIGHT: null
+ },
+ hasChangedProps: false,
+ actorEntrances: [],
+ actorExits: []
+}
+
+const START_SCENE: Scene = {
+ name: "Start",
+ steps: [START_STEP]
+}
+
+export const show = shallowRef({
+ acts: []
+})
+
+export const state = reactive({
+ position: START_STEP.position,
+ message: "",
+ activeMusic: null,
+ musicStartTime: 0
+})
+
+export function getStep(position: ShowPosition) {
+ if (position.act === -1) return START_STEP
+ return getScene(position).steps[position.step]
+}
+
+export function getScene(position: ShowPosition) {
+ if (position.act === -1) return START_SCENE
+ return show.value.acts[position.act].scenes[position.scene]
+}
+
+export function getActiveMusicAt(position: ShowPosition): ShowMusic | null {
+ let activeMusic: ShowMusic | null = null
+
+ for (let actIndex = 0; actIndex < show.value.acts.length; actIndex++) {
+ const scenes = show.value.acts[actIndex].scenes
+
+ for (let sceneIndex = 0; sceneIndex < scenes.length; sceneIndex++) {
+ const scene = scenes[sceneIndex]
+
+ for (let stepIndex = 0; stepIndex < scene.steps.length; stepIndex++) {
+ const step = scene.steps[stepIndex]
+
+ // SONG
+ if (step.cue.type === "MUSIC_START") {
+ activeMusic = {
+ title: step.cue.title,
+ duration: step.cue.duration
+ }
+ } else if (step.cue.type === "MUSIC_END") {
+ activeMusic = null
+ }
+
+ if (sceneIndex == position.scene && stepIndex == position.step) return activeMusic
+ }
+ }
+ }
+
+ return null
+}
+
+export const current = reactiveComputed<{
+ scene: Scene
+ step: Step
+ activeMusic: ShowMusic | null
+}>(() => ({
+ scene: getScene(state.position),
+ step: getStep(state.position),
+ activeMusic: state.activeMusic
+}))
+
+export function parseStringWithDetails(string: string) {
+ const parts = string.split(" / ")
+ if (parts.length === 1) return { main: parts[0], details: "" }
+ return { main: parts[0], details: parts.slice(1).join(" / ") }
+}
+
+export function getNextValidPosition(start: ShowPosition): ShowPosition | null {
+ if (start.act === START_STEP.position.act) return { act: 0, scene: 0, step: 0 }
+ const acts = show.value.acts
+ let { act, scene, step } = start
+
+ step++
+
+ if (step >= acts[start.act].scenes[start.scene].steps.length) {
+ step = 0
+ scene++
+
+ if (scene >= acts[start.act].scenes.length) {
+ scene = 0
+ act++
+
+ if (act >= acts.length) {
+ return null
+ }
+ }
+ }
+
+ return { act, scene, step }
+}
+
+export function getPreviousValidPosition(start: ShowPosition): ShowPosition | null {
+ let { act, scene, step } = start
+ step--
+
+ if (step < 0) {
+ scene--
+
+ if (scene < 0) {
+ act--
+
+ if (act < 0) {
+ return START_STEP.position
+ }
+
+ scene = show.value.acts[act].scenes.length - 1
+ }
+
+ step = show.value.acts[act].scenes[scene].steps.length - 1
+ }
+
+ return { act, scene, step }
+}
diff --git a/ui/src/syncing.ts b/ui/src/syncing.ts
new file mode 100755
index 0000000..feb4c40
--- /dev/null
+++ b/ui/src/syncing.ts
@@ -0,0 +1,58 @@
+import ReconnectingWebSocket from "reconnecting-websocket"
+import { show, ShowPosition, state } from "./state"
+import { ref, toRaw } from "vue"
+
+let socket: ReconnectingWebSocket | null = null
+let timeDifference = 0
+
+export const getSyncedTime = () => Date.now() - timeDifference
+export const syncedTime = ref(Date.now())
+
+const setSyncedTimeRef = () => {
+ syncedTime.value = getSyncedTime()
+ requestAnimationFrame(setSyncedTimeRef)
+}
+
+requestAnimationFrame(setSyncedTimeRef)
+
+export const connect = () => new Promise(resolve => {
+ if (socket !== null) return
+
+ const url = new URL(window.location.toString())
+ url.protocol = "ws"
+ url.pathname = "/api/ws"
+ socket = new ReconnectingWebSocket(url.toString(), [], {
+ reconnectionDelayGrowFactor: 1,
+ minReconnectionDelay: 1000
+ })
+
+ let isFirstMessage = true
+
+ socket.addEventListener("open", () => {
+ isFirstMessage = true
+ })
+
+ socket.addEventListener("message", event => {
+ const data = JSON.parse(event.data as string)
+
+ if (isFirstMessage) {
+ isFirstMessage = false
+ show.value = data
+ console.log("Show:", data)
+ } else {
+ Object.assign(state, data.state)
+ timeDifference = Date.now() - data.timestamp
+ console.log("New state:", data.state)
+ console.log("New time difference:", timeDifference)
+ resolve()
+ }
+ })
+})
+
+export async function goToPosition(position: ShowPosition) {
+ await fetch("/api/go", { method: "POST", body: JSON.stringify(position), headers: { "Content-Type": "application/json" } })
+}
+
+export async function setMessage(message: string) {
+ await fetch("/api/message", { method: "POST", body: message })
+}
diff --git a/ui/src/vite-env.d.ts b/ui/src/vite-env.d.ts
new file mode 100755
index 0000000..a40b464
--- /dev/null
+++ b/ui/src/vite-env.d.ts
@@ -0,0 +1,3 @@
+///
+///
+///
diff --git a/ui/tsconfig.json b/ui/tsconfig.json
new file mode 100755
index 0000000..032ba81
--- /dev/null
+++ b/ui/tsconfig.json
@@ -0,0 +1,20 @@
+{
+ "compilerOptions": {
+ "baseUrl": ".",
+ "module": "ESNext",
+ "target": "ES2021",
+ "lib": ["DOM", "ESNext"],
+ "strict": true,
+ "esModuleInterop": true,
+ "skipLibCheck": false,
+ "moduleResolution": "node",
+ "resolveJsonModule": true,
+ "strictNullChecks": true,
+ "downlevelIteration": true,
+ "forceConsistentCasingInFileNames": true
+ },
+ "include": [
+ "node_modules",
+ "src/**/*"
+ ]
+}
diff --git a/ui/vite.config.ts b/ui/vite.config.ts
new file mode 100755
index 0000000..d61a37d
--- /dev/null
+++ b/ui/vite.config.ts
@@ -0,0 +1,25 @@
+import { defineConfig, splitVendorChunkPlugin } from "vite"
+import vuePlugin from "@vitejs/plugin-vue"
+import windicssPlugin from "vite-plugin-windicss"
+import pagesPlugin from "vite-plugin-pages"
+import iconsPlugin from "unplugin-icons/vite"
+
+export default defineConfig({
+ plugins: [
+ splitVendorChunkPlugin(),
+ vuePlugin(),
+ pagesPlugin({
+ syncIndex: false
+ }),
+ windicssPlugin(),
+ iconsPlugin()
+ ],
+ server: {
+ proxy: {
+ "/api": {
+ target: "http://localhost:8000",
+ ws: true
+ }
+ }
+ }
+})
diff --git a/ui/windi.config.ts b/ui/windi.config.ts
new file mode 100755
index 0000000..8d4511d
--- /dev/null
+++ b/ui/windi.config.ts
@@ -0,0 +1,44 @@
+import { defineConfig } from "windicss/helpers"
+import colors from "windicss/colors"
+import lineClampPlugin from "windicss/plugin/line-clamp"
+
+const generateValues = (max: number, fn: (step: number) => any) => {
+ const object: Record = {}
+
+ for (let i = 1; i <= max; i++) {
+ object[i] = fn(i)
+ }
+
+ return object
+}
+
+export default defineConfig({
+ theme: {
+ colors: {
+ black: colors.black,
+ white: colors.white,
+ gray: colors.stone,
+ red: colors.red,
+ yellow: colors.amber,
+ orange: colors.orange,
+ green: colors.green,
+ blue: colors.blue,
+ violet: colors.fuchsia,
+ light: colors.light,
+ dark: colors.dark,
+ transparent: colors.transparent
+ },
+ fontSize: {
+ ...generateValues(30, step => `${step * 0.25}rem`),
+ 4: "1.2rem",
+ 3: "1.1rem",
+ 2: "1rem",
+ s1: "0.9rem",
+ s2: "0.8rem",
+ s3: "0.7rem"
+ }
+ },
+ plugins: [
+ lineClampPlugin
+ ]
+})