diff --git a/.dockerignore b/.dockerignore index f7fcf12934..2ea288d039 100644 --- a/.dockerignore +++ b/.dockerignore @@ -9,5 +9,12 @@ /frontend/dist /frontend/.env.* /frontend/public/environment.* +/frontend-prototype/data +/frontend-prototype/dist +/frontend-prototype/.env.* +/frontend-vue3/data +/frontend-vue3/dist +/frontend-vue3/.env.* +/frontend-vue3/public/environment.* **/vendor/ **/node_modules/ diff --git a/docker-compose.yml b/docker-compose.yml index f17e431786..d755b408c6 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -2,6 +2,28 @@ services: frontend: image: node:24.8.0 container_name: 'ecamp3-frontend' + stdin_open: true + tty: true + user: ${USER_ID:-1000} + volumes: + - ./.prettierrc:/.prettierrc:delegated + - ./frontend:/app:delegated + - ./common:/common:delegated + - ./pdf:/pdf:delegated + - ./.cache/npm:/home/node/.npm/_cacache:delegated + - ./.cache/npm/sentry-cli:/home/node/.npm/sentry-cli:delegated + environment: + - NODE_ENV=development + - NPM_CONFIG_UPDATE_NOTIFIER=false + - NPM_CONFIG_CACHE=/home/node/.npm + - CI=${CI} + working_dir: /app + command: ./docker-setup.sh + depends_on: + - pdf + + frontend-vue3: + image: node:24.5.0 ports: - '9229:9229' # jest debug stdin_open: true @@ -9,7 +31,29 @@ services: user: ${USER_ID:-1000} volumes: - ./.prettierrc:/.prettierrc:delegated - - ./frontend:/app:delegated + - ./frontend-vue3:/app:delegated + - ./common:/common:delegated + - ./pdf:/pdf:delegated + - ./.cache/npm:/home/node/.npm/_cacache:delegated + - ./.cache/npm/sentry-cli:/home/node/.npm/sentry-cli:delegated + environment: + - NODE_ENV=development + - NPM_CONFIG_UPDATE_NOTIFIER=false + - NPM_CONFIG_CACHE=/home/node/.npm + - CI=${CI} + working_dir: /app + command: ./docker-setup.sh + depends_on: + - pdf + + frontend-prototype: + image: node:24.5.0 + stdin_open: true + tty: true + user: ${USER_ID:-1000} + volumes: + - ./.prettierrc:/.prettierrc:delegated + - ./frontend-prototype:/app:delegated - ./common:/common:delegated - ./pdf:/pdf:delegated - ./.cache/npm:/home/node/.npm/_cacache:delegated @@ -201,6 +245,8 @@ services: depends_on: - frontend - api + - frontend-vue3 + - frontend-prototype ports: - target: 3000 published: 3000 diff --git a/frontend-prototype/.browserslistrc b/frontend-prototype/.browserslistrc new file mode 100644 index 0000000000..dc3bc09a24 --- /dev/null +++ b/frontend-prototype/.browserslistrc @@ -0,0 +1,4 @@ +> 1% +last 2 versions +not dead +not ie 11 diff --git a/frontend-prototype/.editorconfig b/frontend-prototype/.editorconfig new file mode 100644 index 0000000000..7053c49a04 --- /dev/null +++ b/frontend-prototype/.editorconfig @@ -0,0 +1,5 @@ +[*.{js,jsx,ts,tsx,vue}] +indent_style = space +indent_size = 2 +trim_trailing_whitespace = true +insert_final_newline = true diff --git a/frontend-prototype/.eslintrc-auto-import.json b/frontend-prototype/.eslintrc-auto-import.json new file mode 100644 index 0000000000..7ea7de726a --- /dev/null +++ b/frontend-prototype/.eslintrc-auto-import.json @@ -0,0 +1,82 @@ +{ + "globals": { + "Component": true, + "ComponentPublicInstance": true, + "ComputedRef": true, + "DirectiveBinding": true, + "EffectScope": true, + "ExtractDefaultPropTypes": true, + "ExtractPropTypes": true, + "ExtractPublicPropTypes": true, + "InjectionKey": true, + "MaybeRef": true, + "MaybeRefOrGetter": true, + "PropType": true, + "Ref": true, + "Slot": true, + "Slots": true, + "VNode": true, + "WritableComputedRef": true, + "computed": true, + "createApp": true, + "customRef": true, + "defineAsyncComponent": true, + "defineComponent": true, + "defineStore": true, + "effectScope": true, + "getCurrentInstance": true, + "getCurrentScope": true, + "h": true, + "inject": true, + "isProxy": true, + "isReactive": true, + "isReadonly": true, + "isRef": true, + "markRaw": true, + "nextTick": true, + "onActivated": true, + "onBeforeMount": true, + "onBeforeRouteLeave": true, + "onBeforeRouteUpdate": true, + "onBeforeUnmount": true, + "onBeforeUpdate": true, + "onDeactivated": true, + "onErrorCaptured": true, + "onMounted": true, + "onRenderTracked": true, + "onRenderTriggered": true, + "onScopeDispose": true, + "onServerPrefetch": true, + "onUnmounted": true, + "onUpdated": true, + "onWatcherCleanup": true, + "provide": true, + "reactive": true, + "readonly": true, + "ref": true, + "resolveComponent": true, + "shallowReactive": true, + "shallowReadonly": true, + "shallowRef": true, + "storeToRefs": true, + "toRaw": true, + "toRef": true, + "toRefs": true, + "toValue": true, + "triggerRef": true, + "unref": true, + "useAttrs": true, + "useCssModule": true, + "useCssVars": true, + "useId": true, + "useModel": true, + "useRoute": true, + "useRouter": true, + "useSlots": true, + "useTemplateRef": true, + "watch": true, + "watchEffect": true, + "watchPostEffect": true, + "watchSyncEffect": true + } +} diff --git a/frontend-prototype/.gitignore b/frontend-prototype/.gitignore new file mode 100644 index 0000000000..11f5d71423 --- /dev/null +++ b/frontend-prototype/.gitignore @@ -0,0 +1,22 @@ +.DS_Store +node_modules +/dist + +# local env files +.env.local +.env.*.local + +# Log files +npm-debug.log* +yarn-debug.log* +yarn-error.log* +pnpm-debug.log* + +# Editor directories and files +.idea +.vscode +*.suo +*.ntvs* +*.njsproj +*.sln +*.sw? diff --git a/frontend-prototype/README.md b/frontend-prototype/README.md new file mode 100644 index 0000000000..f58f67680a --- /dev/null +++ b/frontend-prototype/README.md @@ -0,0 +1,79 @@ +# Vuetify (Default) + +This is the official scaffolding tool for Vuetify, designed to give you a head start in building your new Vuetify application. It sets up a base template with all the necessary configurations and standard directory structure, enabling you to begin development without the hassle of setting up the project from scratch. + +## ❗️ Important Links + +- 📄 [Docs](https://vuetifyjs.com/) +- 🚨 [Issues](https://issues.vuetifyjs.com/) +- 🏬 [Store](https://store.vuetifyjs.com/) +- 🎮 [Playground](https://play.vuetifyjs.com/) +- 💬 [Discord](https://community.vuetifyjs.com) + +## 💿 Install + +Set up your project using your preferred package manager. Use the corresponding command to install the dependencies: + +| Package Manager | Command | +|---------------------------------------------------------------|----------------| +| [yarn](https://yarnpkg.com/getting-started) | `yarn install` | +| [npm](https://docs.npmjs.com/cli/v7/commands/npm-install) | `npm install` | +| [pnpm](https://pnpm.io/installation) | `pnpm install` | +| [bun](https://bun.sh/#getting-started) | `bun install` | + +After completing the installation, your environment is ready for Vuetify development. + +## ✨ Features + +- 🖼️ **Optimized Front-End Stack**: Leverage the latest Vue 3 and Vuetify 3 for a modern, reactive UI development experience. [Vue 3](https://v3.vuejs.org/) | [Vuetify 3](https://vuetifyjs.com/en/) +- 🗃️ **State Management**: Integrated with [Pinia](https://pinia.vuejs.org/), the intuitive, modular state management solution for Vue. +- 🚦 **Routing and Layouts**: Utilizes Vue Router for SPA navigation and vite-plugin-vue-layouts for organizing Vue file layouts. [Vue Router](https://router.vuejs.org/) | [vite-plugin-vue-layouts](https://github.com/JohnCampionJr/vite-plugin-vue-layouts) +- ⚡ **Next-Gen Tooling**: Powered by Vite, experience fast cold starts and instant HMR (Hot Module Replacement). [Vite](https://vitejs.dev/) +- 🧩 **Automated Component Importing**: Streamline your workflow with unplugin-vue-components, automatically importing components as you use them. [unplugin-vue-components](https://github.com/antfu/unplugin-vue-components) + +These features are curated to provide a seamless development experience from setup to deployment, ensuring that your Vuetify application is both powerful and maintainable. + +## 💡 Usage + +This section covers how to start the development server and build your project for production. + +### Starting the Development Server + +To start the development server with hot-reload, run the following command. The server will be accessible at [http://localhost:3000](http://localhost:3000): + +```bash +yarn dev +``` + +(Repeat for npm, pnpm, and bun with respective commands.) + +> Add NODE_OPTIONS='--no-warnings' to suppress the JSON import warnings that happen as part of the Vuetify import mapping. If you are on Node [v21.3.0](https://nodejs.org/en/blog/release/v21.3.0) or higher, you can change this to NODE_OPTIONS='--disable-warning=5401'. If you don't mind the warning, you can remove this from your package.json dev script. + +### Building for Production + +To build your project for production, use: + +```bash +yarn build +``` + +(Repeat for npm, pnpm, and bun with respective commands.) + +Once the build process is completed, your application will be ready for deployment in a production environment. + +## 💪 Support Vuetify Development + +This project is built with [Vuetify](https://vuetifyjs.com/en/), a UI Library with a comprehensive collection of Vue components. Vuetify is an MIT licensed Open Source project that has been made possible due to the generous contributions by our [sponsors and backers](https://vuetifyjs.com/introduction/sponsors-and-backers/). If you are interested in supporting this project, please consider: + +- [Requesting Enterprise Support](https://support.vuetifyjs.com/) +- [Sponsoring John on Github](https://github.com/users/johnleider/sponsorship) +- [Sponsoring Kael on Github](https://github.com/users/kaelwd/sponsorship) +- [Supporting the team on Open Collective](https://opencollective.com/vuetify) +- [Becoming a sponsor on Patreon](https://www.patreon.com/vuetify) +- [Becoming a subscriber on Tidelift](https://tidelift.com/subscription/npm/vuetify) +- [Making a one-time donation with Paypal](https://paypal.me/vuetify) + +## 📑 License +[MIT](http://opensource.org/licenses/MIT) + +Copyright (c) 2016-present Vuetify, LLC diff --git a/frontend-prototype/auto-imports.d.ts b/frontend-prototype/auto-imports.d.ts new file mode 100644 index 0000000000..8f3b17e064 --- /dev/null +++ b/frontend-prototype/auto-imports.d.ts @@ -0,0 +1,147 @@ +/* eslint-disable */ +/* prettier-ignore */ +// @ts-nocheck +// noinspection JSUnusedGlobalSymbols +// Generated by unplugin-auto-import +// biome-ignore lint: disable +export {} +declare global { + const EffectScope: typeof import('vue')['EffectScope'] + const computed: typeof import('vue')['computed'] + const createApp: typeof import('vue')['createApp'] + const customRef: typeof import('vue')['customRef'] + const defineAsyncComponent: typeof import('vue')['defineAsyncComponent'] + const defineComponent: typeof import('vue')['defineComponent'] + const defineStore: typeof import('pinia')['defineStore'] + const effectScope: typeof import('vue')['effectScope'] + const getCurrentInstance: typeof import('vue')['getCurrentInstance'] + const getCurrentScope: typeof import('vue')['getCurrentScope'] + const h: typeof import('vue')['h'] + const inject: typeof import('vue')['inject'] + const isProxy: typeof import('vue')['isProxy'] + const isReactive: typeof import('vue')['isReactive'] + const isReadonly: typeof import('vue')['isReadonly'] + const isRef: typeof import('vue')['isRef'] + const markRaw: typeof import('vue')['markRaw'] + const nextTick: typeof import('vue')['nextTick'] + const onActivated: typeof import('vue')['onActivated'] + const onBeforeMount: typeof import('vue')['onBeforeMount'] + const onBeforeRouteLeave: typeof import('vue-router')['onBeforeRouteLeave'] + const onBeforeRouteUpdate: typeof import('vue-router')['onBeforeRouteUpdate'] + const onBeforeUnmount: typeof import('vue')['onBeforeUnmount'] + const onBeforeUpdate: typeof import('vue')['onBeforeUpdate'] + const onDeactivated: typeof import('vue')['onDeactivated'] + const onErrorCaptured: typeof import('vue')['onErrorCaptured'] + const onMounted: typeof import('vue')['onMounted'] + const onRenderTracked: typeof import('vue')['onRenderTracked'] + const onRenderTriggered: typeof import('vue')['onRenderTriggered'] + const onScopeDispose: typeof import('vue')['onScopeDispose'] + const onServerPrefetch: typeof import('vue')['onServerPrefetch'] + const onUnmounted: typeof import('vue')['onUnmounted'] + const onUpdated: typeof import('vue')['onUpdated'] + const onWatcherCleanup: typeof import('vue')['onWatcherCleanup'] + const provide: typeof import('vue')['provide'] + const reactive: typeof import('vue')['reactive'] + const readonly: typeof import('vue')['readonly'] + const ref: typeof import('vue')['ref'] + const resolveComponent: typeof import('vue')['resolveComponent'] + const shallowReactive: typeof import('vue')['shallowReactive'] + const shallowReadonly: typeof import('vue')['shallowReadonly'] + const shallowRef: typeof import('vue')['shallowRef'] + const storeToRefs: typeof import('pinia')['storeToRefs'] + const toRaw: typeof import('vue')['toRaw'] + const toRef: typeof import('vue')['toRef'] + const toRefs: typeof import('vue')['toRefs'] + const toValue: typeof import('vue')['toValue'] + const triggerRef: typeof import('vue')['triggerRef'] + const unref: typeof import('vue')['unref'] + const useAttrs: typeof import('vue')['useAttrs'] + const useCssModule: typeof import('vue')['useCssModule'] + const useCssVars: typeof import('vue')['useCssVars'] + const useId: typeof import('vue')['useId'] + const useModel: typeof import('vue')['useModel'] + const useRoute: typeof import('vue-router')['useRoute'] + const useRouter: typeof import('vue-router')['useRouter'] + const useSlots: typeof import('vue')['useSlots'] + const useTemplateRef: typeof import('vue')['useTemplateRef'] + const watch: typeof import('vue')['watch'] + const watchEffect: typeof import('vue')['watchEffect'] + const watchPostEffect: typeof import('vue')['watchPostEffect'] + const watchSyncEffect: typeof import('vue')['watchSyncEffect'] +} +// for type re-export +declare global { + // @ts-ignore + export type { Component, Slot, Slots, ComponentPublicInstance, ComputedRef, DirectiveBinding, ExtractDefaultPropTypes, ExtractPropTypes, ExtractPublicPropTypes, InjectionKey, PropType, Ref, MaybeRef, MaybeRefOrGetter, VNode, WritableComputedRef } from 'vue' + import('vue') +} + +// for vue template auto import +import { UnwrapRef } from 'vue' +declare module 'vue' { + interface GlobalComponents {} + interface ComponentCustomProperties { + readonly EffectScope: UnwrapRef + readonly computed: UnwrapRef + readonly createApp: UnwrapRef + readonly customRef: UnwrapRef + readonly defineAsyncComponent: UnwrapRef + readonly defineComponent: UnwrapRef + readonly defineStore: UnwrapRef + readonly effectScope: UnwrapRef + readonly getCurrentInstance: UnwrapRef + readonly getCurrentScope: UnwrapRef + readonly h: UnwrapRef + readonly inject: UnwrapRef + readonly isProxy: UnwrapRef + readonly isReactive: UnwrapRef + readonly isReadonly: UnwrapRef + readonly isRef: UnwrapRef + readonly markRaw: UnwrapRef + readonly nextTick: UnwrapRef + readonly onActivated: UnwrapRef + readonly onBeforeMount: UnwrapRef + readonly onBeforeRouteLeave: UnwrapRef + readonly onBeforeRouteUpdate: UnwrapRef + readonly onBeforeUnmount: UnwrapRef + readonly onBeforeUpdate: UnwrapRef + readonly onDeactivated: UnwrapRef + readonly onErrorCaptured: UnwrapRef + readonly onMounted: UnwrapRef + readonly onRenderTracked: UnwrapRef + readonly onRenderTriggered: UnwrapRef + readonly onScopeDispose: UnwrapRef + readonly onServerPrefetch: UnwrapRef + readonly onUnmounted: UnwrapRef + readonly onUpdated: UnwrapRef + readonly onWatcherCleanup: UnwrapRef + readonly provide: UnwrapRef + readonly reactive: UnwrapRef + readonly readonly: UnwrapRef + readonly ref: UnwrapRef + readonly resolveComponent: UnwrapRef + readonly shallowReactive: UnwrapRef + readonly shallowReadonly: UnwrapRef + readonly shallowRef: UnwrapRef + readonly storeToRefs: UnwrapRef + readonly toRaw: UnwrapRef + readonly toRef: UnwrapRef + readonly toRefs: UnwrapRef + readonly toValue: UnwrapRef + readonly triggerRef: UnwrapRef + readonly unref: UnwrapRef + readonly useAttrs: UnwrapRef + readonly useCssModule: UnwrapRef + readonly useCssVars: UnwrapRef + readonly useId: UnwrapRef + readonly useModel: UnwrapRef + readonly useRoute: UnwrapRef + readonly useRouter: UnwrapRef + readonly useSlots: UnwrapRef + readonly useTemplateRef: UnwrapRef + readonly watch: UnwrapRef + readonly watchEffect: UnwrapRef + readonly watchPostEffect: UnwrapRef + readonly watchSyncEffect: UnwrapRef + } +} \ No newline at end of file diff --git a/frontend-prototype/components.d.ts b/frontend-prototype/components.d.ts new file mode 100644 index 0000000000..46aff5f878 --- /dev/null +++ b/frontend-prototype/components.d.ts @@ -0,0 +1,19 @@ +/* eslint-disable */ +// @ts-nocheck +// Generated by unplugin-vue-components +// Read more: https://github.com/vuejs/core/pull/3399 +// biome-ignore lint: disable +export {} + +/* prettier-ignore */ +declare module 'vue' { + export interface GlobalComponents { + AppBarItem: typeof import('./src/components/AppBarItem.vue')['default'] + AppFooter: typeof import('./src/components/AppFooter.vue')['default'] + HelloWorld: typeof import('./src/components/HelloWorld.vue')['default'] + Logo: typeof import('./src/components/Logo.vue')['default'] + RouterLink: typeof import('vue-router')['RouterLink'] + RouterView: typeof import('vue-router')['RouterView'] + UserMeta: typeof import('./src/components/UserMeta.vue')['default'] + } +} diff --git a/frontend-prototype/docker-setup.sh b/frontend-prototype/docker-setup.sh new file mode 100755 index 0000000000..f0d3b16631 --- /dev/null +++ b/frontend-prototype/docker-setup.sh @@ -0,0 +1,13 @@ +#!/bin/bash +set -euo pipefail + +BASEDIR=$(dirname "$0") + +if [ "$CI" = 'true' ] ; then + npm ci --verbose + npm run build + npm run preview +else + npm install + npm run dev +fi diff --git a/frontend-prototype/eslint.config.js b/frontend-prototype/eslint.config.js new file mode 100644 index 0000000000..bb027414d0 --- /dev/null +++ b/frontend-prototype/eslint.config.js @@ -0,0 +1,3 @@ +import vuetify from 'eslint-config-vuetify' + +export default vuetify() diff --git a/frontend-prototype/index.html b/frontend-prototype/index.html new file mode 100644 index 0000000000..0a84a1cdd1 --- /dev/null +++ b/frontend-prototype/index.html @@ -0,0 +1,13 @@ + + + + + + + Welcome to Vuetify 3 + + +
+ + + diff --git a/frontend-prototype/jsconfig.json b/frontend-prototype/jsconfig.json new file mode 100644 index 0000000000..dad0634ca4 --- /dev/null +++ b/frontend-prototype/jsconfig.json @@ -0,0 +1,20 @@ +{ + "compilerOptions": { + "allowJs": true, + "target": "es5", + "module": "esnext", + "baseUrl": "./", + "moduleResolution": "bundler", + "paths": { + "@/*": [ + "src/*" + ] + }, + "lib": [ + "esnext", + "dom", + "dom.iterable", + "scripthost" + ] + } +} diff --git a/frontend-prototype/package-lock.json b/frontend-prototype/package-lock.json new file mode 100644 index 0000000000..de6fa429bf --- /dev/null +++ b/frontend-prototype/package-lock.json @@ -0,0 +1,5780 @@ +{ + "name": "frontend-prototype", + "version": "0.0.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "frontend-prototype", + "version": "0.0.0", + "dependencies": { + "@fontsource/roboto": "5.2.7", + "@mdi/font": "7.4.47", + "inter-ui": "3.19.3", + "pinia": "^3.0.3", + "vue": "^3.5.21", + "vue-router": "^4.5.1", + "vuetify": "^3.10.1" + }, + "devDependencies": { + "@vitejs/plugin-vue": "^6.0.1", + "eslint": "^9.35.0", + "eslint-config-vuetify": "^4.2.0", + "sass-embedded": "^1.92.1", + "unplugin-auto-import": "^19.3.0", + "unplugin-fonts": "^1.4.0", + "unplugin-vue-components": "^29.0.0", + "unplugin-vue-router": "^0.15.0", + "vite": "^7.1.5", + "vite-plugin-vue-layouts-next": "^1.0.0", + "vite-plugin-vuetify": "^2.1.2" + } + }, + "node_modules/@apidevtools/json-schema-ref-parser": { + "version": "14.2.1", + "resolved": "https://registry.npmjs.org/@apidevtools/json-schema-ref-parser/-/json-schema-ref-parser-14.2.1.tgz", + "integrity": "sha512-HmdFw9CDYqM6B25pqGBpNeLCKvGPlIx1EbLrVL0zPvj50CJQUHyBNBw45Muk0kEIkogo1VZvOKHajdMuAzSxRg==", + "dev": true, + "license": "MIT", + "dependencies": { + "js-yaml": "^4.1.0" + }, + "engines": { + "node": ">= 20" + }, + "funding": { + "url": "https://github.com/sponsors/philsturgeon" + }, + "peerDependencies": { + "@types/json-schema": "^7.0.15" + } + }, + "node_modules/@babel/helper-string-parser": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.27.1.tgz", + "integrity": "sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==", + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-identifier": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.27.1.tgz", + "integrity": "sha512-D2hP9eA+Sqx1kBZgzxZh0y1trbuU+JoDkiEwqhQ36nodYqJwyEIhPSdMNd7lOm/4io72luTPWH20Yda0xOuUow==", + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/parser": { + "version": "7.28.4", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.28.4.tgz", + "integrity": "sha512-yZbBqeM6TkpP9du/I2pUZnJsRMGGvOuIrhjzC1AwHwW+6he4mni6Bp/m8ijn0iOuZuPI2BfkCoSRunpyjnrQKg==", + "license": "MIT", + "dependencies": { + "@babel/types": "^7.28.4" + }, + "bin": { + "parser": "bin/babel-parser.js" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@babel/types": { + "version": "7.28.4", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.28.4.tgz", + "integrity": "sha512-bkFqkLhh3pMBUQQkpVgWDWq/lqzc2678eUyDlTBhRqhCHFguYYGM0Efga7tYk4TogG/3x0EEl66/OQ+WGbWB/Q==", + "license": "MIT", + "dependencies": { + "@babel/helper-string-parser": "^7.27.1", + "@babel/helper-validator-identifier": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@bufbuild/protobuf": { + "version": "2.9.0", + "resolved": "https://registry.npmjs.org/@bufbuild/protobuf/-/protobuf-2.9.0.tgz", + "integrity": "sha512-rnJenoStJ8nvmt9Gzye8nkYd6V22xUAnu4086ER7h1zJ508vStko4pMvDeQ446ilDTFpV5wnoc5YS7XvMwwMqA==", + "devOptional": true, + "license": "(Apache-2.0 AND BSD-3-Clause)" + }, + "node_modules/@clack/core": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/@clack/core/-/core-0.5.0.tgz", + "integrity": "sha512-p3y0FIOwaYRUPRcMO7+dlmLh8PSRcrjuTndsiA0WAFbWES0mLZlrjVoBRZ9DzkPFJZG6KGkJmoEAY0ZcVWTkow==", + "dev": true, + "license": "MIT", + "dependencies": { + "picocolors": "^1.0.0", + "sisteransi": "^1.0.5" + } + }, + "node_modules/@clack/prompts": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/@clack/prompts/-/prompts-0.11.0.tgz", + "integrity": "sha512-pMN5FcrEw9hUkZA4f+zLlzivQSeQf5dRGJjSUbvVYDLvpKCdQx5OaknvKzgbtXOizhP+SJJJjqEbOe55uKKfAw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@clack/core": "0.5.0", + "picocolors": "^1.0.0", + "sisteransi": "^1.0.5" + } + }, + "node_modules/@esbuild/aix-ppc64": { + "version": "0.25.10", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.25.10.tgz", + "integrity": "sha512-0NFWnA+7l41irNuaSVlLfgNT12caWJVLzp5eAVhZ0z1qpxbockccEt3s+149rE64VUI3Ml2zt8Nv5JVc4QXTsw==", + "cpu": [ + "ppc64" + ], + "license": "MIT", + "optional": true, + "os": [ + "aix" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-arm": { + "version": "0.25.10", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.25.10.tgz", + "integrity": "sha512-dQAxF1dW1C3zpeCDc5KqIYuZ1tgAdRXNoZP7vkBIRtKZPYe2xVr/d3SkirklCHudW1B45tGiUlz2pUWDfbDD4w==", + "cpu": [ + "arm" + ], + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-arm64": { + "version": "0.25.10", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.25.10.tgz", + "integrity": "sha512-LSQa7eDahypv/VO6WKohZGPSJDq5OVOo3UoFR1E4t4Gj1W7zEQMUhI+lo81H+DtB+kP+tDgBp+M4oNCwp6kffg==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-x64": { + "version": "0.25.10", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.25.10.tgz", + "integrity": "sha512-MiC9CWdPrfhibcXwr39p9ha1x0lZJ9KaVfvzA0Wxwz9ETX4v5CHfF09bx935nHlhi+MxhA63dKRRQLiVgSUtEg==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/darwin-arm64": { + "version": "0.25.10", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.25.10.tgz", + "integrity": "sha512-JC74bdXcQEpW9KkV326WpZZjLguSZ3DfS8wrrvPMHgQOIEIG/sPXEN/V8IssoJhbefLRcRqw6RQH2NnpdprtMA==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/darwin-x64": { + "version": "0.25.10", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.25.10.tgz", + "integrity": "sha512-tguWg1olF6DGqzws97pKZ8G2L7Ig1vjDmGTwcTuYHbuU6TTjJe5FXbgs5C1BBzHbJ2bo1m3WkQDbWO2PvamRcg==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/freebsd-arm64": { + "version": "0.25.10", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.25.10.tgz", + "integrity": "sha512-3ZioSQSg1HT2N05YxeJWYR+Libe3bREVSdWhEEgExWaDtyFbbXWb49QgPvFH8u03vUPX10JhJPcz7s9t9+boWg==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/freebsd-x64": { + "version": "0.25.10", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.25.10.tgz", + "integrity": "sha512-LLgJfHJk014Aa4anGDbh8bmI5Lk+QidDmGzuC2D+vP7mv/GeSN+H39zOf7pN5N8p059FcOfs2bVlrRr4SK9WxA==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-arm": { + "version": "0.25.10", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.25.10.tgz", + "integrity": "sha512-oR31GtBTFYCqEBALI9r6WxoU/ZofZl962pouZRTEYECvNF/dtXKku8YXcJkhgK/beU+zedXfIzHijSRapJY3vg==", + "cpu": [ + "arm" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-arm64": { + "version": "0.25.10", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.25.10.tgz", + "integrity": "sha512-5luJWN6YKBsawd5f9i4+c+geYiVEw20FVW5x0v1kEMWNq8UctFjDiMATBxLvmmHA4bf7F6hTRaJgtghFr9iziQ==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-ia32": { + "version": "0.25.10", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.25.10.tgz", + "integrity": "sha512-NrSCx2Kim3EnnWgS4Txn0QGt0Xipoumb6z6sUtl5bOEZIVKhzfyp/Lyw4C1DIYvzeW/5mWYPBFJU3a/8Yr75DQ==", + "cpu": [ + "ia32" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-loong64": { + "version": "0.25.10", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.25.10.tgz", + "integrity": "sha512-xoSphrd4AZda8+rUDDfD9J6FUMjrkTz8itpTITM4/xgerAZZcFW7Dv+sun7333IfKxGG8gAq+3NbfEMJfiY+Eg==", + "cpu": [ + "loong64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-mips64el": { + "version": "0.25.10", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.25.10.tgz", + "integrity": "sha512-ab6eiuCwoMmYDyTnyptoKkVS3k8fy/1Uvq7Dj5czXI6DF2GqD2ToInBI0SHOp5/X1BdZ26RKc5+qjQNGRBelRA==", + "cpu": [ + "mips64el" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-ppc64": { + "version": "0.25.10", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.25.10.tgz", + "integrity": "sha512-NLinzzOgZQsGpsTkEbdJTCanwA5/wozN9dSgEl12haXJBzMTpssebuXR42bthOF3z7zXFWH1AmvWunUCkBE4EA==", + "cpu": [ + "ppc64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-riscv64": { + "version": "0.25.10", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.25.10.tgz", + "integrity": "sha512-FE557XdZDrtX8NMIeA8LBJX3dC2M8VGXwfrQWU7LB5SLOajfJIxmSdyL/gU1m64Zs9CBKvm4UAuBp5aJ8OgnrA==", + "cpu": [ + "riscv64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-s390x": { + "version": "0.25.10", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.25.10.tgz", + "integrity": "sha512-3BBSbgzuB9ajLoVZk0mGu+EHlBwkusRmeNYdqmznmMc9zGASFjSsxgkNsqmXugpPk00gJ0JNKh/97nxmjctdew==", + "cpu": [ + "s390x" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-x64": { + "version": "0.25.10", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.25.10.tgz", + "integrity": "sha512-QSX81KhFoZGwenVyPoberggdW1nrQZSvfVDAIUXr3WqLRZGZqWk/P4T8p2SP+de2Sr5HPcvjhcJzEiulKgnxtA==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/netbsd-arm64": { + "version": "0.25.10", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.25.10.tgz", + "integrity": "sha512-AKQM3gfYfSW8XRk8DdMCzaLUFB15dTrZfnX8WXQoOUpUBQ+NaAFCP1kPS/ykbbGYz7rxn0WS48/81l9hFl3u4A==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/netbsd-x64": { + "version": "0.25.10", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.25.10.tgz", + "integrity": "sha512-7RTytDPGU6fek/hWuN9qQpeGPBZFfB4zZgcz2VK2Z5VpdUxEI8JKYsg3JfO0n/Z1E/6l05n0unDCNc4HnhQGig==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openbsd-arm64": { + "version": "0.25.10", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.25.10.tgz", + "integrity": "sha512-5Se0VM9Wtq797YFn+dLimf2Zx6McttsH2olUBsDml+lm0GOCRVebRWUvDtkY4BWYv/3NgzS8b/UM3jQNh5hYyw==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openbsd-x64": { + "version": "0.25.10", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.25.10.tgz", + "integrity": "sha512-XkA4frq1TLj4bEMB+2HnI0+4RnjbuGZfet2gs/LNs5Hc7D89ZQBHQ0gL2ND6Lzu1+QVkjp3x1gIcPKzRNP8bXw==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openharmony-arm64": { + "version": "0.25.10", + "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.25.10.tgz", + "integrity": "sha512-AVTSBhTX8Y/Fz6OmIVBip9tJzZEUcY8WLh7I59+upa5/GPhh2/aM6bvOMQySspnCCHvFi79kMtdJS1w0DXAeag==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "openharmony" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/sunos-x64": { + "version": "0.25.10", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.25.10.tgz", + "integrity": "sha512-fswk3XT0Uf2pGJmOpDB7yknqhVkJQkAQOcW/ccVOtfx05LkbWOaRAtn5SaqXypeKQra1QaEa841PgrSL9ubSPQ==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "sunos" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-arm64": { + "version": "0.25.10", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.25.10.tgz", + "integrity": "sha512-ah+9b59KDTSfpaCg6VdJoOQvKjI33nTaQr4UluQwW7aEwZQsbMCfTmfEO4VyewOxx4RaDT/xCy9ra2GPWmO7Kw==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-ia32": { + "version": "0.25.10", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.25.10.tgz", + "integrity": "sha512-QHPDbKkrGO8/cz9LKVnJU22HOi4pxZnZhhA2HYHez5Pz4JeffhDjf85E57Oyco163GnzNCVkZK0b/n4Y0UHcSw==", + "cpu": [ + "ia32" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-x64": { + "version": "0.25.10", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.25.10.tgz", + "integrity": "sha512-9KpxSVFCu0iK1owoez6aC/s/EdUQLDN3adTxGCqxMVhrPDj6bt5dbrHDXUuq+Bs2vATFBBrQS5vdQ/Ed2P+nbw==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@eslint-community/eslint-utils": { + "version": "4.9.0", + "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.9.0.tgz", + "integrity": "sha512-ayVFHdtZ+hsq1t2Dy24wCmGXGe4q9Gu3smhLYALJrr473ZH27MsnSL+LKUlimp4BWJqMDMLmPpx/Q9R3OAlL4g==", + "dev": true, + "license": "MIT", + "dependencies": { + "eslint-visitor-keys": "^3.4.3" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + }, + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" + } + }, + "node_modules/@eslint-community/eslint-utils/node_modules/eslint-visitor-keys": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", + "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/@eslint-community/regexpp": { + "version": "4.12.1", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.12.1.tgz", + "integrity": "sha512-CCZCDJuduB9OUkFkY2IgppNZMi2lBQgD2qzwXkEia16cge2pijY/aXi96CJMquDMn3nJdlPV1A5KrJEXwfLNzQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^12.0.0 || ^14.0.0 || >=16.0.0" + } + }, + "node_modules/@eslint/compat": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/@eslint/compat/-/compat-1.4.0.tgz", + "integrity": "sha512-DEzm5dKeDBPm3r08Ixli/0cmxr8LkRdwxMRUIJBlSCpAwSrvFEJpVBzV+66JhDxiaqKxnRzCXhtiMiczF7Hglg==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@eslint/core": "^0.16.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "peerDependencies": { + "eslint": "^8.40 || 9" + }, + "peerDependenciesMeta": { + "eslint": { + "optional": true + } + } + }, + "node_modules/@eslint/compat/node_modules/@eslint/core": { + "version": "0.16.0", + "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.16.0.tgz", + "integrity": "sha512-nmC8/totwobIiFcGkDza3GIKfAw1+hLiYVrh3I1nIomQ8PEr5cxg34jnkmGawul/ep52wGRAcyeDCNtWKSOj4Q==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@types/json-schema": "^7.0.15" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@eslint/config-array": { + "version": "0.21.0", + "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.21.0.tgz", + "integrity": "sha512-ENIdc4iLu0d93HeYirvKmrzshzofPw6VkZRKQGe9Nv46ZnWUzcF1xV01dcvEg/1wXUR61OmmlSfyeyO7EvjLxQ==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@eslint/object-schema": "^2.1.6", + "debug": "^4.3.1", + "minimatch": "^3.1.2" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@eslint/config-helpers": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/@eslint/config-helpers/-/config-helpers-0.3.1.tgz", + "integrity": "sha512-xR93k9WhrDYpXHORXpxVL5oHj3Era7wo6k/Wd8/IsQNnZUTzkGS29lyn3nAT05v6ltUuTFVCCYDEGfy2Or/sPA==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@eslint/core": { + "version": "0.15.2", + "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.15.2.tgz", + "integrity": "sha512-78Md3/Rrxh83gCxoUc0EiciuOHsIITzLy53m3d9UyiW8y9Dj2D29FeETqyKA+BRK76tnTp6RXWb3pCay8Oyomg==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@types/json-schema": "^7.0.15" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@eslint/eslintrc": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-3.3.1.tgz", + "integrity": "sha512-gtF186CXhIl1p4pJNGZw8Yc6RlshoePRvE0X91oPGb3vZ8pM3qOS9W9NGPat9LziaBV7XrJWGylNQXkGcnM3IQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "ajv": "^6.12.4", + "debug": "^4.3.2", + "espree": "^10.0.1", + "globals": "^14.0.0", + "ignore": "^5.2.0", + "import-fresh": "^3.2.1", + "js-yaml": "^4.1.0", + "minimatch": "^3.1.2", + "strip-json-comments": "^3.1.1" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/@eslint/js": { + "version": "9.36.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.36.0.tgz", + "integrity": "sha512-uhCbYtYynH30iZErszX78U+nR3pJU3RHGQ57NXy5QupD4SBVwDeU8TNBy+MjMngc1UyIW9noKqsRqfjQTBU2dw==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://eslint.org/donate" + } + }, + "node_modules/@eslint/object-schema": { + "version": "2.1.6", + "resolved": "https://registry.npmjs.org/@eslint/object-schema/-/object-schema-2.1.6.tgz", + "integrity": "sha512-RBMg5FRL0I0gs51M/guSAj5/e14VQ4tpZnQNWwuDT66P14I43ItmPfIZRhO9fUVIPOAQXU47atlywZ/czoqFPA==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@eslint/plugin-kit": { + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.3.5.tgz", + "integrity": "sha512-Z5kJ+wU3oA7MMIqVR9tyZRtjYPr4OC004Q4Rw7pgOKUOKkJfZ3O24nz3WYfGRpMDNmcOi3TwQOmgm7B7Tpii0w==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@eslint/core": "^0.15.2", + "levn": "^0.4.1" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@fontsource/roboto": { + "version": "5.2.7", + "resolved": "https://registry.npmjs.org/@fontsource/roboto/-/roboto-5.2.7.tgz", + "integrity": "sha512-fca6Jtyxn6kPR51+TTTMCFm0FOhnKaLEYYiAQc8P/4iFCKoKGR0aX89QR4CfP+N64RPXJus64UxhJaVENnSM6Q==", + "license": "OFL-1.1", + "funding": { + "url": "https://github.com/sponsors/ayuhito" + } + }, + "node_modules/@humanfs/core": { + "version": "0.19.1", + "resolved": "https://registry.npmjs.org/@humanfs/core/-/core-0.19.1.tgz", + "integrity": "sha512-5DyQ4+1JEUzejeK1JGICcideyfUbGixgS9jNgex5nqkW+cY7WZhxBigmieN5Qnw9ZosSNVC9KQKyb+GUaGyKUA==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=18.18.0" + } + }, + "node_modules/@humanfs/node": { + "version": "0.16.7", + "resolved": "https://registry.npmjs.org/@humanfs/node/-/node-0.16.7.tgz", + "integrity": "sha512-/zUx+yOsIrG4Y43Eh2peDeKCxlRt/gET6aHfaKpuq267qXdYDFViVHfMaLyygZOnl0kGWxFIgsBy8QFuTLUXEQ==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@humanfs/core": "^0.19.1", + "@humanwhocodes/retry": "^0.4.0" + }, + "engines": { + "node": ">=18.18.0" + } + }, + "node_modules/@humanwhocodes/module-importer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", + "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=12.22" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } + }, + "node_modules/@humanwhocodes/retry": { + "version": "0.4.3", + "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.4.3.tgz", + "integrity": "sha512-bV0Tgo9K4hfPCek+aMAn81RppFKv2ySDQeMoSZuvTASywNTnVJCArCZE2FWqpvIatKu7VMRLWlR1EazvVhDyhQ==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=18.18" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } + }, + "node_modules/@jridgewell/gen-mapping": { + "version": "0.3.13", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.13.tgz", + "integrity": "sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/sourcemap-codec": "^1.5.0", + "@jridgewell/trace-mapping": "^0.3.24" + } + }, + "node_modules/@jridgewell/remapping": { + "version": "2.3.5", + "resolved": "https://registry.npmjs.org/@jridgewell/remapping/-/remapping-2.3.5.tgz", + "integrity": "sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.24" + } + }, + "node_modules/@jridgewell/resolve-uri": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", + "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.5.5", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz", + "integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==", + "license": "MIT" + }, + "node_modules/@jridgewell/trace-mapping": { + "version": "0.3.31", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.31.tgz", + "integrity": "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + }, + "node_modules/@mdi/font": { + "version": "7.4.47", + "resolved": "https://registry.npmjs.org/@mdi/font/-/font-7.4.47.tgz", + "integrity": "sha512-43MtGpd585SNzHZPcYowu/84Vz2a2g31TvPMTm9uTiCSWzaheQySUcSyUH/46fPnuPQWof2yd0pGBtzee/IQWw==", + "license": "Apache-2.0" + }, + "node_modules/@nodelib/fs.scandir": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", + "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@nodelib/fs.stat": "2.0.5", + "run-parallel": "^1.1.9" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.stat": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", + "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.walk": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", + "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@nodelib/fs.scandir": "2.1.5", + "fastq": "^1.6.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@parcel/watcher": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/@parcel/watcher/-/watcher-2.5.1.tgz", + "integrity": "sha512-dfUnCxiN9H4ap84DvD2ubjw+3vUNpstxa0TneY/Paat8a3R4uQZDLSvWjmznAY/DoahqTHl9V46HF/Zs3F29pg==", + "hasInstallScript": true, + "license": "MIT", + "optional": true, + "dependencies": { + "detect-libc": "^1.0.3", + "is-glob": "^4.0.3", + "micromatch": "^4.0.5", + "node-addon-api": "^7.0.0" + }, + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + }, + "optionalDependencies": { + "@parcel/watcher-android-arm64": "2.5.1", + "@parcel/watcher-darwin-arm64": "2.5.1", + "@parcel/watcher-darwin-x64": "2.5.1", + "@parcel/watcher-freebsd-x64": "2.5.1", + "@parcel/watcher-linux-arm-glibc": "2.5.1", + "@parcel/watcher-linux-arm-musl": "2.5.1", + "@parcel/watcher-linux-arm64-glibc": "2.5.1", + "@parcel/watcher-linux-arm64-musl": "2.5.1", + "@parcel/watcher-linux-x64-glibc": "2.5.1", + "@parcel/watcher-linux-x64-musl": "2.5.1", + "@parcel/watcher-win32-arm64": "2.5.1", + "@parcel/watcher-win32-ia32": "2.5.1", + "@parcel/watcher-win32-x64": "2.5.1" + } + }, + "node_modules/@parcel/watcher-android-arm64": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/@parcel/watcher-android-arm64/-/watcher-android-arm64-2.5.1.tgz", + "integrity": "sha512-KF8+j9nNbUN8vzOFDpRMsaKBHZ/mcjEjMToVMJOhTozkDonQFFrRcfdLWn6yWKCmJKmdVxSgHiYvTCef4/qcBA==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-darwin-arm64": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/@parcel/watcher-darwin-arm64/-/watcher-darwin-arm64-2.5.1.tgz", + "integrity": "sha512-eAzPv5osDmZyBhou8PoF4i6RQXAfeKL9tjb3QzYuccXFMQU0ruIc/POh30ePnaOyD1UXdlKguHBmsTs53tVoPw==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-darwin-x64": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/@parcel/watcher-darwin-x64/-/watcher-darwin-x64-2.5.1.tgz", + "integrity": "sha512-1ZXDthrnNmwv10A0/3AJNZ9JGlzrF82i3gNQcWOzd7nJ8aj+ILyW1MTxVk35Db0u91oD5Nlk9MBiujMlwmeXZg==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-freebsd-x64": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/@parcel/watcher-freebsd-x64/-/watcher-freebsd-x64-2.5.1.tgz", + "integrity": "sha512-SI4eljM7Flp9yPuKi8W0ird8TI/JK6CSxju3NojVI6BjHsTyK7zxA9urjVjEKJ5MBYC+bLmMcbAWlZ+rFkLpJQ==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-linux-arm-glibc": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-arm-glibc/-/watcher-linux-arm-glibc-2.5.1.tgz", + "integrity": "sha512-RCdZlEyTs8geyBkkcnPWvtXLY44BCeZKmGYRtSgtwwnHR4dxfHRG3gR99XdMEdQ7KeiDdasJwwvNSF5jKtDwdA==", + "cpu": [ + "arm" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-linux-arm-musl": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-arm-musl/-/watcher-linux-arm-musl-2.5.1.tgz", + "integrity": "sha512-6E+m/Mm1t1yhB8X412stiKFG3XykmgdIOqhjWj+VL8oHkKABfu/gjFj8DvLrYVHSBNC+/u5PeNrujiSQ1zwd1Q==", + "cpu": [ + "arm" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-linux-arm64-glibc": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-arm64-glibc/-/watcher-linux-arm64-glibc-2.5.1.tgz", + "integrity": "sha512-LrGp+f02yU3BN9A+DGuY3v3bmnFUggAITBGriZHUREfNEzZh/GO06FF5u2kx8x+GBEUYfyTGamol4j3m9ANe8w==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-linux-arm64-musl": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-arm64-musl/-/watcher-linux-arm64-musl-2.5.1.tgz", + "integrity": "sha512-cFOjABi92pMYRXS7AcQv9/M1YuKRw8SZniCDw0ssQb/noPkRzA+HBDkwmyOJYp5wXcsTrhxO0zq1U11cK9jsFg==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-linux-x64-glibc": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-x64-glibc/-/watcher-linux-x64-glibc-2.5.1.tgz", + "integrity": "sha512-GcESn8NZySmfwlTsIur+49yDqSny2IhPeZfXunQi48DMugKeZ7uy1FX83pO0X22sHntJ4Ub+9k34XQCX+oHt2A==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-linux-x64-musl": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-x64-musl/-/watcher-linux-x64-musl-2.5.1.tgz", + "integrity": "sha512-n0E2EQbatQ3bXhcH2D1XIAANAcTZkQICBPVaxMeaCVBtOpBZpWJuf7LwyWPSBDITb7In8mqQgJ7gH8CILCURXg==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-win32-arm64": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/@parcel/watcher-win32-arm64/-/watcher-win32-arm64-2.5.1.tgz", + "integrity": "sha512-RFzklRvmc3PkjKjry3hLF9wD7ppR4AKcWNzH7kXR7GUe0Igb3Nz8fyPwtZCSquGrhU5HhUNDr/mKBqj7tqA2Vw==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-win32-ia32": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/@parcel/watcher-win32-ia32/-/watcher-win32-ia32-2.5.1.tgz", + "integrity": "sha512-c2KkcVN+NJmuA7CGlaGD1qJh1cLfDnQsHjE89E60vUEMlqduHGCdCLJCID5geFVM0dOtA3ZiIO8BoEQmzQVfpQ==", + "cpu": [ + "ia32" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-win32-x64": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/@parcel/watcher-win32-x64/-/watcher-win32-x64-2.5.1.tgz", + "integrity": "sha512-9lHBdJITeNR++EvSQVUcaZoWupyHfXe1jZvGZ06O/5MflPcuPLtEphScIBL+AiCWBO46tDSHzWyD0uDmmZqsgA==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@pkgr/core": { + "version": "0.2.9", + "resolved": "https://registry.npmjs.org/@pkgr/core/-/core-0.2.9.tgz", + "integrity": "sha512-QNqXyfVS2wm9hweSYD2O7F0G06uurj9kZ96TRQE5Y9hU7+tgdZwIkbAKc5Ocy1HxEY2kuDQa6cQ1WRs/O5LFKA==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^12.20.0 || ^14.18.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/pkgr" + } + }, + "node_modules/@rolldown/pluginutils": { + "version": "1.0.0-beta.29", + "resolved": "https://registry.npmjs.org/@rolldown/pluginutils/-/pluginutils-1.0.0-beta.29.tgz", + "integrity": "sha512-NIJgOsMjbxAXvoGq/X0gD7VPMQ8j9g0BiDaNjVNVjvl+iKXxL3Jre0v31RmBYeLEmkbj2s02v8vFTbUXi5XS2Q==", + "dev": true, + "license": "MIT" + }, + "node_modules/@rollup/rollup-android-arm-eabi": { + "version": "4.52.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.52.4.tgz", + "integrity": "sha512-BTm2qKNnWIQ5auf4deoetINJm2JzvihvGb9R6K/ETwKLql/Bb3Eg2H1FBp1gUb4YGbydMA3jcmQTR73q7J+GAA==", + "cpu": [ + "arm" + ], + "license": "MIT", + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@rollup/rollup-android-arm64": { + "version": "4.52.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.52.4.tgz", + "integrity": "sha512-P9LDQiC5vpgGFgz7GSM6dKPCiqR3XYN1WwJKA4/BUVDjHpYsf3iBEmVz62uyq20NGYbiGPR5cNHI7T1HqxNs2w==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@rollup/rollup-darwin-arm64": { + "version": "4.52.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.52.4.tgz", + "integrity": "sha512-QRWSW+bVccAvZF6cbNZBJwAehmvG9NwfWHwMy4GbWi/BQIA/laTIktebT2ipVjNncqE6GLPxOok5hsECgAxGZg==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@rollup/rollup-darwin-x64": { + "version": "4.52.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.52.4.tgz", + "integrity": "sha512-hZgP05pResAkRJxL1b+7yxCnXPGsXU0fG9Yfd6dUaoGk+FhdPKCJ5L1Sumyxn8kvw8Qi5PvQ8ulenUbRjzeCTw==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@rollup/rollup-freebsd-arm64": { + "version": "4.52.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.52.4.tgz", + "integrity": "sha512-xmc30VshuBNUd58Xk4TKAEcRZHaXlV+tCxIXELiE9sQuK3kG8ZFgSPi57UBJt8/ogfhAF5Oz4ZSUBN77weM+mQ==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ] + }, + "node_modules/@rollup/rollup-freebsd-x64": { + "version": "4.52.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.52.4.tgz", + "integrity": "sha512-WdSLpZFjOEqNZGmHflxyifolwAiZmDQzuOzIq9L27ButpCVpD7KzTRtEG1I0wMPFyiyUdOO+4t8GvrnBLQSwpw==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ] + }, + "node_modules/@rollup/rollup-linux-arm-gnueabihf": { + "version": "4.52.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.52.4.tgz", + "integrity": "sha512-xRiOu9Of1FZ4SxVbB0iEDXc4ddIcjCv2aj03dmW8UrZIW7aIQ9jVJdLBIhxBI+MaTnGAKyvMwPwQnoOEvP7FgQ==", + "cpu": [ + "arm" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm-musleabihf": { + "version": "4.52.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.52.4.tgz", + "integrity": "sha512-FbhM2p9TJAmEIEhIgzR4soUcsW49e9veAQCziwbR+XWB2zqJ12b4i/+hel9yLiD8pLncDH4fKIPIbt5238341Q==", + "cpu": [ + "arm" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm64-gnu": { + "version": "4.52.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.52.4.tgz", + "integrity": "sha512-4n4gVwhPHR9q/g8lKCyz0yuaD0MvDf7dV4f9tHt0C73Mp8h38UCtSCSE6R9iBlTbXlmA8CjpsZoujhszefqueg==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm64-musl": { + "version": "4.52.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.52.4.tgz", + "integrity": "sha512-u0n17nGA0nvi/11gcZKsjkLj1QIpAuPFQbR48Subo7SmZJnGxDpspyw2kbpuoQnyK+9pwf3pAoEXerJs/8Mi9g==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-loong64-gnu": { + "version": "4.52.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-gnu/-/rollup-linux-loong64-gnu-4.52.4.tgz", + "integrity": "sha512-0G2c2lpYtbTuXo8KEJkDkClE/+/2AFPdPAbmaHoE870foRFs4pBrDehilMcrSScrN/fB/1HTaWO4bqw+ewBzMQ==", + "cpu": [ + "loong64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-ppc64-gnu": { + "version": "4.52.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.52.4.tgz", + "integrity": "sha512-teSACug1GyZHmPDv14VNbvZFX779UqWTsd7KtTM9JIZRDI5NUwYSIS30kzI8m06gOPB//jtpqlhmraQ68b5X2g==", + "cpu": [ + "ppc64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-riscv64-gnu": { + "version": "4.52.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.52.4.tgz", + "integrity": "sha512-/MOEW3aHjjs1p4Pw1Xk4+3egRevx8Ji9N6HUIA1Ifh8Q+cg9dremvFCUbOX2Zebz80BwJIgCBUemjqhU5XI5Eg==", + "cpu": [ + "riscv64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-riscv64-musl": { + "version": "4.52.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.52.4.tgz", + "integrity": "sha512-1HHmsRyh845QDpEWzOFtMCph5Ts+9+yllCrREuBR/vg2RogAQGGBRC8lDPrPOMnrdOJ+mt1WLMOC2Kao/UwcvA==", + "cpu": [ + "riscv64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-s390x-gnu": { + "version": "4.52.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.52.4.tgz", + "integrity": "sha512-seoeZp4L/6D1MUyjWkOMRU6/iLmCU2EjbMTyAG4oIOs1/I82Y5lTeaxW0KBfkUdHAWN7j25bpkt0rjnOgAcQcA==", + "cpu": [ + "s390x" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-x64-gnu": { + "version": "4.52.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.52.4.tgz", + "integrity": "sha512-Wi6AXf0k0L7E2gteNsNHUs7UMwCIhsCTs6+tqQ5GPwVRWMaflqGec4Sd8n6+FNFDw9vGcReqk2KzBDhCa1DLYg==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-x64-musl": { + "version": "4.52.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.52.4.tgz", + "integrity": "sha512-dtBZYjDmCQ9hW+WgEkaffvRRCKm767wWhxsFW3Lw86VXz/uJRuD438/XvbZT//B96Vs8oTA8Q4A0AfHbrxP9zw==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-openharmony-arm64": { + "version": "4.52.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-openharmony-arm64/-/rollup-openharmony-arm64-4.52.4.tgz", + "integrity": "sha512-1ox+GqgRWqaB1RnyZXL8PD6E5f7YyRUJYnCqKpNzxzP0TkaUh112NDrR9Tt+C8rJ4x5G9Mk8PQR3o7Ku2RKqKA==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "openharmony" + ] + }, + "node_modules/@rollup/rollup-win32-arm64-msvc": { + "version": "4.52.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.52.4.tgz", + "integrity": "sha512-8GKr640PdFNXwzIE0IrkMWUNUomILLkfeHjXBi/nUvFlpZP+FA8BKGKpacjW6OUUHaNI6sUURxR2U2g78FOHWQ==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-ia32-msvc": { + "version": "4.52.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.52.4.tgz", + "integrity": "sha512-AIy/jdJ7WtJ/F6EcfOb2GjR9UweO0n43jNObQMb6oGxkYTfLcnN7vYYpG+CN3lLxrQkzWnMOoNSHTW54pgbVxw==", + "cpu": [ + "ia32" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-x64-gnu": { + "version": "4.52.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-gnu/-/rollup-win32-x64-gnu-4.52.4.tgz", + "integrity": "sha512-UF9KfsH9yEam0UjTwAgdK0anlQ7c8/pWPU2yVjyWcF1I1thABt6WXE47cI71pGiZ8wGvxohBoLnxM04L/wj8mQ==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-x64-msvc": { + "version": "4.52.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.52.4.tgz", + "integrity": "sha512-bf9PtUa0u8IXDVxzRToFQKsNCRz9qLYfR/MpECxl4mRoWYjAeFjgxj1XdZr2M/GNVpT05p+LgQOHopYDlUu6/w==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@stylistic/eslint-plugin": { + "version": "5.4.0", + "resolved": "https://registry.npmjs.org/@stylistic/eslint-plugin/-/eslint-plugin-5.4.0.tgz", + "integrity": "sha512-UG8hdElzuBDzIbjG1QDwnYH0MQ73YLXDFHgZzB4Zh/YJfnw8XNsloVtytqzx0I2Qky9THSdpTmi8Vjn/pf/Lew==", + "dev": true, + "license": "MIT", + "dependencies": { + "@eslint-community/eslint-utils": "^4.9.0", + "@typescript-eslint/types": "^8.44.0", + "eslint-visitor-keys": "^4.2.1", + "espree": "^10.4.0", + "estraverse": "^5.3.0", + "picomatch": "^4.0.3" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "peerDependencies": { + "eslint": ">=9.0.0" + } + }, + "node_modules/@types/estree": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz", + "integrity": "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==", + "devOptional": true, + "license": "MIT" + }, + "node_modules/@types/json-schema": { + "version": "7.0.15", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", + "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@typescript-eslint/eslint-plugin": { + "version": "8.45.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.45.0.tgz", + "integrity": "sha512-HC3y9CVuevvWCl/oyZuI47dOeDF9ztdMEfMH8/DW/Mhwa9cCLnK1oD7JoTVGW/u7kFzNZUKUoyJEqkaJh5y3Wg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@eslint-community/regexpp": "^4.10.0", + "@typescript-eslint/scope-manager": "8.45.0", + "@typescript-eslint/type-utils": "8.45.0", + "@typescript-eslint/utils": "8.45.0", + "@typescript-eslint/visitor-keys": "8.45.0", + "graphemer": "^1.4.0", + "ignore": "^7.0.0", + "natural-compare": "^1.4.0", + "ts-api-utils": "^2.1.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "@typescript-eslint/parser": "^8.45.0", + "eslint": "^8.57.0 || ^9.0.0", + "typescript": ">=4.8.4 <6.0.0" + } + }, + "node_modules/@typescript-eslint/eslint-plugin/node_modules/ignore": { + "version": "7.0.5", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-7.0.5.tgz", + "integrity": "sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 4" + } + }, + "node_modules/@typescript-eslint/parser": { + "version": "8.45.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.45.0.tgz", + "integrity": "sha512-TGf22kon8KW+DeKaUmOibKWktRY8b2NSAZNdtWh798COm1NWx8+xJ6iFBtk3IvLdv6+LGLJLRlyhrhEDZWargQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/scope-manager": "8.45.0", + "@typescript-eslint/types": "8.45.0", + "@typescript-eslint/typescript-estree": "8.45.0", + "@typescript-eslint/visitor-keys": "8.45.0", + "debug": "^4.3.4" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.57.0 || ^9.0.0", + "typescript": ">=4.8.4 <6.0.0" + } + }, + "node_modules/@typescript-eslint/project-service": { + "version": "8.45.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.45.0.tgz", + "integrity": "sha512-3pcVHwMG/iA8afdGLMuTibGR7pDsn9RjDev6CCB+naRsSYs2pns5QbinF4Xqw6YC/Sj3lMrm/Im0eMfaa61WUg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/tsconfig-utils": "^8.45.0", + "@typescript-eslint/types": "^8.45.0", + "debug": "^4.3.4" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "typescript": ">=4.8.4 <6.0.0" + } + }, + "node_modules/@typescript-eslint/scope-manager": { + "version": "8.45.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.45.0.tgz", + "integrity": "sha512-clmm8XSNj/1dGvJeO6VGH7EUSeA0FMs+5au/u3lrA3KfG8iJ4u8ym9/j2tTEoacAffdW1TVUzXO30W1JTJS7dA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/types": "8.45.0", + "@typescript-eslint/visitor-keys": "8.45.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/tsconfig-utils": { + "version": "8.45.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.45.0.tgz", + "integrity": "sha512-aFdr+c37sc+jqNMGhH+ajxPXwjv9UtFZk79k8pLoJ6p4y0snmYpPA52GuWHgt2ZF4gRRW6odsEj41uZLojDt5w==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "typescript": ">=4.8.4 <6.0.0" + } + }, + "node_modules/@typescript-eslint/type-utils": { + "version": "8.45.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.45.0.tgz", + "integrity": "sha512-bpjepLlHceKgyMEPglAeULX1vixJDgaKocp0RVJ5u4wLJIMNuKtUXIczpJCPcn2waII0yuvks/5m5/h3ZQKs0A==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/types": "8.45.0", + "@typescript-eslint/typescript-estree": "8.45.0", + "@typescript-eslint/utils": "8.45.0", + "debug": "^4.3.4", + "ts-api-utils": "^2.1.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.57.0 || ^9.0.0", + "typescript": ">=4.8.4 <6.0.0" + } + }, + "node_modules/@typescript-eslint/types": { + "version": "8.45.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.45.0.tgz", + "integrity": "sha512-WugXLuOIq67BMgQInIxxnsSyRLFxdkJEJu8r4ngLR56q/4Q5LrbfkFRH27vMTjxEK8Pyz7QfzuZe/G15qQnVRA==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/typescript-estree": { + "version": "8.45.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.45.0.tgz", + "integrity": "sha512-GfE1NfVbLam6XQ0LcERKwdTTPlLvHvXXhOeUGC1OXi4eQBoyy1iVsW+uzJ/J9jtCz6/7GCQ9MtrQ0fml/jWCnA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/project-service": "8.45.0", + "@typescript-eslint/tsconfig-utils": "8.45.0", + "@typescript-eslint/types": "8.45.0", + "@typescript-eslint/visitor-keys": "8.45.0", + "debug": "^4.3.4", + "fast-glob": "^3.3.2", + "is-glob": "^4.0.3", + "minimatch": "^9.0.4", + "semver": "^7.6.0", + "ts-api-utils": "^2.1.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "typescript": ">=4.8.4 <6.0.0" + } + }, + "node_modules/@typescript-eslint/typescript-estree/node_modules/brace-expansion": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz", + "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/@typescript-eslint/typescript-estree/node_modules/minimatch": { + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", + "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/@typescript-eslint/utils": { + "version": "8.45.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.45.0.tgz", + "integrity": "sha512-bxi1ht+tLYg4+XV2knz/F7RVhU0k6VrSMc9sb8DQ6fyCTrGQLHfo7lDtN0QJjZjKkLA2ThrKuCdHEvLReqtIGg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@eslint-community/eslint-utils": "^4.7.0", + "@typescript-eslint/scope-manager": "8.45.0", + "@typescript-eslint/types": "8.45.0", + "@typescript-eslint/typescript-estree": "8.45.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.57.0 || ^9.0.0", + "typescript": ">=4.8.4 <6.0.0" + } + }, + "node_modules/@typescript-eslint/visitor-keys": { + "version": "8.45.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.45.0.tgz", + "integrity": "sha512-qsaFBA3e09MIDAGFUrTk+dzqtfv1XPVz8t8d1f0ybTzrCY7BKiMC5cjrl1O/P7UmHsNyW90EYSkU/ZWpmXelag==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/types": "8.45.0", + "eslint-visitor-keys": "^4.2.1" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@vitejs/plugin-vue": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/@vitejs/plugin-vue/-/plugin-vue-6.0.1.tgz", + "integrity": "sha512-+MaE752hU0wfPFJEUAIxqw18+20euHHdxVtMvbFcOEpjEyfqXH/5DCoTHiVJ0J29EhTJdoTkjEv5YBKU9dnoTw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@rolldown/pluginutils": "1.0.0-beta.29" + }, + "engines": { + "node": "^20.19.0 || >=22.12.0" + }, + "peerDependencies": { + "vite": "^5.0.0 || ^6.0.0 || ^7.0.0", + "vue": "^3.2.25" + } + }, + "node_modules/@volar/language-core": { + "version": "2.4.23", + "resolved": "https://registry.npmjs.org/@volar/language-core/-/language-core-2.4.23.tgz", + "integrity": "sha512-hEEd5ET/oSmBC6pi1j6NaNYRWoAiDhINbT8rmwtINugR39loROSlufGdYMF9TaKGfz+ViGs1Idi3mAhnuPcoGQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@volar/source-map": "2.4.23" + } + }, + "node_modules/@volar/source-map": { + "version": "2.4.23", + "resolved": "https://registry.npmjs.org/@volar/source-map/-/source-map-2.4.23.tgz", + "integrity": "sha512-Z1Uc8IB57Lm6k7q6KIDu/p+JWtf3xsXJqAX/5r18hYOTpJyBn0KXUR8oTJ4WFYOcDzWC9n3IflGgHowx6U6z9Q==", + "dev": true, + "license": "MIT" + }, + "node_modules/@vue-macros/common": { + "version": "3.0.0-beta.16", + "resolved": "https://registry.npmjs.org/@vue-macros/common/-/common-3.0.0-beta.16.tgz", + "integrity": "sha512-8O2gWxWFiaoNkk7PGi0+p7NPGe/f8xJ3/INUufvje/RZOs7sJvlI1jnR4lydtRFa/mU0ylMXUXXjSK0fHDEYTA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@vue/compiler-sfc": "^3.5.17", + "ast-kit": "^2.1.1", + "local-pkg": "^1.1.1", + "magic-string-ast": "^1.0.0", + "unplugin-utils": "^0.2.4" + }, + "engines": { + "node": ">=20.18.0" + }, + "funding": { + "url": "https://github.com/sponsors/vue-macros" + }, + "peerDependencies": { + "vue": "^2.7.0 || ^3.2.25" + }, + "peerDependenciesMeta": { + "vue": { + "optional": true + } + } + }, + "node_modules/@vue/compiler-core": { + "version": "3.5.22", + "resolved": "https://registry.npmjs.org/@vue/compiler-core/-/compiler-core-3.5.22.tgz", + "integrity": "sha512-jQ0pFPmZwTEiRNSb+i9Ow/I/cHv2tXYqsnHKKyCQ08irI2kdF5qmYedmF8si8mA7zepUFmJ2hqzS8CQmNOWOkQ==", + "license": "MIT", + "dependencies": { + "@babel/parser": "^7.28.4", + "@vue/shared": "3.5.22", + "entities": "^4.5.0", + "estree-walker": "^2.0.2", + "source-map-js": "^1.2.1" + } + }, + "node_modules/@vue/compiler-dom": { + "version": "3.5.22", + "resolved": "https://registry.npmjs.org/@vue/compiler-dom/-/compiler-dom-3.5.22.tgz", + "integrity": "sha512-W8RknzUM1BLkypvdz10OVsGxnMAuSIZs9Wdx1vzA3mL5fNMN15rhrSCLiTm6blWeACwUwizzPVqGJgOGBEN/hA==", + "license": "MIT", + "dependencies": { + "@vue/compiler-core": "3.5.22", + "@vue/shared": "3.5.22" + } + }, + "node_modules/@vue/compiler-sfc": { + "version": "3.5.22", + "resolved": "https://registry.npmjs.org/@vue/compiler-sfc/-/compiler-sfc-3.5.22.tgz", + "integrity": "sha512-tbTR1zKGce4Lj+JLzFXDq36K4vcSZbJ1RBu8FxcDv1IGRz//Dh2EBqksyGVypz3kXpshIfWKGOCcqpSbyGWRJQ==", + "license": "MIT", + "dependencies": { + "@babel/parser": "^7.28.4", + "@vue/compiler-core": "3.5.22", + "@vue/compiler-dom": "3.5.22", + "@vue/compiler-ssr": "3.5.22", + "@vue/shared": "3.5.22", + "estree-walker": "^2.0.2", + "magic-string": "^0.30.19", + "postcss": "^8.5.6", + "source-map-js": "^1.2.1" + } + }, + "node_modules/@vue/compiler-ssr": { + "version": "3.5.22", + "resolved": "https://registry.npmjs.org/@vue/compiler-ssr/-/compiler-ssr-3.5.22.tgz", + "integrity": "sha512-GdgyLvg4R+7T8Nk2Mlighx7XGxq/fJf9jaVofc3IL0EPesTE86cP/8DD1lT3h1JeZr2ySBvyqKQJgbS54IX1Ww==", + "license": "MIT", + "dependencies": { + "@vue/compiler-dom": "3.5.22", + "@vue/shared": "3.5.22" + } + }, + "node_modules/@vue/devtools-api": { + "version": "7.7.7", + "resolved": "https://registry.npmjs.org/@vue/devtools-api/-/devtools-api-7.7.7.tgz", + "integrity": "sha512-lwOnNBH2e7x1fIIbVT7yF5D+YWhqELm55/4ZKf45R9T8r9dE2AIOy8HKjfqzGsoTHFbWbr337O4E0A0QADnjBg==", + "license": "MIT", + "dependencies": { + "@vue/devtools-kit": "^7.7.7" + } + }, + "node_modules/@vue/devtools-kit": { + "version": "7.7.7", + "resolved": "https://registry.npmjs.org/@vue/devtools-kit/-/devtools-kit-7.7.7.tgz", + "integrity": "sha512-wgoZtxcTta65cnZ1Q6MbAfePVFxfM+gq0saaeytoph7nEa7yMXoi6sCPy4ufO111B9msnw0VOWjPEFCXuAKRHA==", + "license": "MIT", + "dependencies": { + "@vue/devtools-shared": "^7.7.7", + "birpc": "^2.3.0", + "hookable": "^5.5.3", + "mitt": "^3.0.1", + "perfect-debounce": "^1.0.0", + "speakingurl": "^14.0.1", + "superjson": "^2.2.2" + } + }, + "node_modules/@vue/devtools-shared": { + "version": "7.7.7", + "resolved": "https://registry.npmjs.org/@vue/devtools-shared/-/devtools-shared-7.7.7.tgz", + "integrity": "sha512-+udSj47aRl5aKb0memBvcUG9koarqnxNM5yjuREvqwK6T3ap4mn3Zqqc17QrBFTqSMjr3HK1cvStEZpMDpfdyw==", + "license": "MIT", + "dependencies": { + "rfdc": "^1.4.1" + } + }, + "node_modules/@vue/language-core": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@vue/language-core/-/language-core-3.1.0.tgz", + "integrity": "sha512-a7ns+X9vTbdmk7QLrvnZs8s4E1wwtxG/sELzr6F2j4pU+r/OoAv6jJGSz+5tVTU6e4+3rjepGhSP8jDmBBcb3w==", + "dev": true, + "license": "MIT", + "dependencies": { + "@volar/language-core": "2.4.23", + "@vue/compiler-dom": "^3.5.0", + "@vue/shared": "^3.5.0", + "alien-signals": "^3.0.0", + "muggle-string": "^0.4.1", + "path-browserify": "^1.0.1", + "picomatch": "^4.0.2" + }, + "peerDependencies": { + "typescript": "*" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@vue/reactivity": { + "version": "3.5.22", + "resolved": "https://registry.npmjs.org/@vue/reactivity/-/reactivity-3.5.22.tgz", + "integrity": "sha512-f2Wux4v/Z2pqc9+4SmgZC1p73Z53fyD90NFWXiX9AKVnVBEvLFOWCEgJD3GdGnlxPZt01PSlfmLqbLYzY/Fw4A==", + "license": "MIT", + "dependencies": { + "@vue/shared": "3.5.22" + } + }, + "node_modules/@vue/runtime-core": { + "version": "3.5.22", + "resolved": "https://registry.npmjs.org/@vue/runtime-core/-/runtime-core-3.5.22.tgz", + "integrity": "sha512-EHo4W/eiYeAzRTN5PCextDUZ0dMs9I8mQ2Fy+OkzvRPUYQEyK9yAjbasrMCXbLNhF7P0OUyivLjIy0yc6VrLJQ==", + "license": "MIT", + "dependencies": { + "@vue/reactivity": "3.5.22", + "@vue/shared": "3.5.22" + } + }, + "node_modules/@vue/runtime-dom": { + "version": "3.5.22", + "resolved": "https://registry.npmjs.org/@vue/runtime-dom/-/runtime-dom-3.5.22.tgz", + "integrity": "sha512-Av60jsryAkI023PlN7LsqrfPvwfxOd2yAwtReCjeuugTJTkgrksYJJstg1e12qle0NarkfhfFu1ox2D+cQotww==", + "license": "MIT", + "dependencies": { + "@vue/reactivity": "3.5.22", + "@vue/runtime-core": "3.5.22", + "@vue/shared": "3.5.22", + "csstype": "^3.1.3" + } + }, + "node_modules/@vue/server-renderer": { + "version": "3.5.22", + "resolved": "https://registry.npmjs.org/@vue/server-renderer/-/server-renderer-3.5.22.tgz", + "integrity": "sha512-gXjo+ao0oHYTSswF+a3KRHZ1WszxIqO7u6XwNHqcqb9JfyIL/pbWrrh/xLv7jeDqla9u+LK7yfZKHih1e1RKAQ==", + "license": "MIT", + "dependencies": { + "@vue/compiler-ssr": "3.5.22", + "@vue/shared": "3.5.22" + }, + "peerDependencies": { + "vue": "3.5.22" + } + }, + "node_modules/@vue/shared": { + "version": "3.5.22", + "resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.5.22.tgz", + "integrity": "sha512-F4yc6palwq3TT0u+FYf0Ns4Tfl9GRFURDN2gWG7L1ecIaS/4fCIuFOjMTnCyjsu/OK6vaDKLCrGAa+KvvH+h4w==", + "license": "MIT" + }, + "node_modules/@vuetify/loader-shared": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/@vuetify/loader-shared/-/loader-shared-2.1.1.tgz", + "integrity": "sha512-jSZTzTYaoiv8iwonFCVZQ0YYX/M+Uyl4ng+C4egMJT0Hcmh9gIxJL89qfZICDeo3g0IhqrvipW2FFKKRDMtVcA==", + "devOptional": true, + "license": "MIT", + "dependencies": { + "upath": "^2.0.1" + }, + "peerDependencies": { + "vue": "^3.0.0", + "vuetify": "^3.0.0" + } + }, + "node_modules/acorn": { + "version": "8.15.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz", + "integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==", + "dev": true, + "license": "MIT", + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/acorn-jsx": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", + "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" + } + }, + "node_modules/ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, + "license": "MIT", + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/alien-signals": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/alien-signals/-/alien-signals-3.0.0.tgz", + "integrity": "sha512-JHoRJf18Y6HN4/KZALr3iU+0vW9LKG+8FMThQlbn4+gv8utsLIkwpomjElGPccGeNwh0FI2HN6BLnyFLo6OyLQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/anymatch": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", + "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", + "dev": true, + "license": "ISC", + "dependencies": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/anymatch/node_modules/picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "dev": true, + "license": "Python-2.0" + }, + "node_modules/ast-kit": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ast-kit/-/ast-kit-2.1.2.tgz", + "integrity": "sha512-cl76xfBQM6pztbrFWRnxbrDm9EOqDr1BF6+qQnnDZG2Co2LjyUktkN9GTJfBAfdae+DbT2nJf2nCGAdDDN7W2g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/parser": "^7.28.0", + "pathe": "^2.0.3" + }, + "engines": { + "node": ">=20.18.0" + }, + "funding": { + "url": "https://github.com/sponsors/sxzz" + } + }, + "node_modules/ast-walker-scope": { + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/ast-walker-scope/-/ast-walker-scope-0.8.2.tgz", + "integrity": "sha512-3pYeLyDZ6nJew9QeBhS4Nly02269Dkdk32+zdbbKmL6n4ZuaGorwwA+xx12xgOciA8BF1w9x+dlH7oUkFTW91w==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/parser": "^7.28.3", + "ast-kit": "^2.1.2" + }, + "engines": { + "node": ">=20.18.0" + }, + "funding": { + "url": "https://github.com/sponsors/sxzz" + } + }, + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "dev": true, + "license": "MIT" + }, + "node_modules/baseline-browser-mapping": { + "version": "2.8.11", + "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.8.11.tgz", + "integrity": "sha512-i+sRXGhz4+QW8aACZ3+r1GAKMt0wlFpeA8M5rOQd0HEYw9zhDrlx9Wc8uQ0IdXakjJRthzglEwfB/yqIjO6iDg==", + "dev": true, + "license": "Apache-2.0", + "bin": { + "baseline-browser-mapping": "dist/cli.js" + } + }, + "node_modules/binary-extensions": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz", + "integrity": "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/birpc": { + "version": "2.6.1", + "resolved": "https://registry.npmjs.org/birpc/-/birpc-2.6.1.tgz", + "integrity": "sha512-LPnFhlDpdSH6FJhJyn4M0kFO7vtQ5iPw24FnG0y21q09xC7e8+1LeR31S1MAIrDAHp4m7aas4bEkTDTvMAtebQ==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/antfu" + } + }, + "node_modules/boolbase": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz", + "integrity": "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==", + "dev": true, + "license": "ISC" + }, + "node_modules/brace-expansion": { + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", + "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/braces": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", + "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", + "devOptional": true, + "license": "MIT", + "dependencies": { + "fill-range": "^7.1.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/browserslist": { + "version": "4.26.3", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.26.3.tgz", + "integrity": "sha512-lAUU+02RFBuCKQPj/P6NgjlbCnLBMp4UtgTx7vNHd3XSIJF87s9a5rA3aH2yw3GS9DqZAUbOtZdCCiZeVRqt0w==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "baseline-browser-mapping": "^2.8.9", + "caniuse-lite": "^1.0.30001746", + "electron-to-chromium": "^1.5.227", + "node-releases": "^2.0.21", + "update-browserslist-db": "^1.1.3" + }, + "bin": { + "browserslist": "cli.js" + }, + "engines": { + "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" + } + }, + "node_modules/buffer-builder": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/buffer-builder/-/buffer-builder-0.2.0.tgz", + "integrity": "sha512-7VPMEPuYznPSoR21NE1zvd2Xna6c/CloiZCfcMXR1Jny6PjX0N4Nsa38zcBFo/FMK+BlA+FLKbJCQ0i2yxp+Xg==", + "devOptional": true, + "license": "MIT/X11" + }, + "node_modules/builtin-modules": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-5.0.0.tgz", + "integrity": "sha512-bkXY9WsVpY7CvMhKSR6pZilZu9Ln5WDrKVBUXf2S443etkmEO4V58heTecXcUIsNsi4Rx8JUO4NfX1IcQl4deg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18.20" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/caniuse-lite": { + "version": "1.0.30001747", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001747.tgz", + "integrity": "sha512-mzFa2DGIhuc5490Nd/G31xN1pnBnYMadtkyTjefPI7wzypqgCEpeWu9bJr0OnDsyKrW75zA9ZAt7pbQFmwLsQg==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/caniuse-lite" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "CC-BY-4.0" + }, + "node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/change-case": { + "version": "5.4.4", + "resolved": "https://registry.npmjs.org/change-case/-/change-case-5.4.4.tgz", + "integrity": "sha512-HRQyTk2/YPEkt9TnUPbOpr64Uw3KOicFWPVBb+xiHvd6eBx/qPr9xqfBFDT8P2vWsvvz4jbEkfDe71W3VyNu2w==", + "dev": true, + "license": "MIT" + }, + "node_modules/chokidar": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-4.0.3.tgz", + "integrity": "sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA==", + "devOptional": true, + "license": "MIT", + "dependencies": { + "readdirp": "^4.0.1" + }, + "engines": { + "node": ">= 14.16.0" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/ci-info": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-4.3.0.tgz", + "integrity": "sha512-l+2bNRMiQgcfILUi33labAZYIWlH1kWDp+ecNo5iisRKrbm0xcRyCww71/YU0Fkw0mAFpz9bJayXPjey6vkmaQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/sibiraj-s" + } + ], + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/citty": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/citty/-/citty-0.1.6.tgz", + "integrity": "sha512-tskPPKEs8D2KPafUypv2gxwJP8h/OaJmC82QQGGDQcHvXX43xF2VDACcJVmZ0EuSxkpO9Kc4MlrA3q0+FG58AQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "consola": "^3.2.3" + } + }, + "node_modules/clean-regexp": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/clean-regexp/-/clean-regexp-1.0.0.tgz", + "integrity": "sha512-GfisEZEJvzKrmGWkvfhgzcz/BllN1USeqD2V6tg14OAOgaCD2Z/PUEuxnAZ/nPvmaHRG7a8y77p1T/IRQ4D1Hw==", + "dev": true, + "license": "MIT", + "dependencies": { + "escape-string-regexp": "^1.0.5" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/clean-regexp/node_modules/escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true, + "license": "MIT" + }, + "node_modules/colorjs.io": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/colorjs.io/-/colorjs.io-0.5.2.tgz", + "integrity": "sha512-twmVoizEW7ylZSN32OgKdXRmo1qg+wT5/6C3xu5b9QsWzSFAhHLn2xd8ro0diCsKfCj1RdaTP/nrcW+vAoQPIw==", + "devOptional": true, + "license": "MIT" + }, + "node_modules/comment-parser": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/comment-parser/-/comment-parser-1.4.1.tgz", + "integrity": "sha512-buhp5kePrmda3vhc5B9t7pUQXAb2Tnd0qgpkIhPhkHXxJpiPJ11H0ZEU0oBpJ2QztSbzG/ZxMj/CHsYJqRHmyg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 12.0.0" + } + }, + "node_modules/concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", + "dev": true, + "license": "MIT" + }, + "node_modules/confbox": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/confbox/-/confbox-0.2.2.tgz", + "integrity": "sha512-1NB+BKqhtNipMsov4xI/NnhCKp9XG9NamYp5PVm9klAT0fsrNPjaFICsCFhNhwZJKNh7zB/3q8qXz0E9oaMNtQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/consola": { + "version": "3.4.2", + "resolved": "https://registry.npmjs.org/consola/-/consola-3.4.2.tgz", + "integrity": "sha512-5IKcdX0nnYavi6G7TtOhwkYzyjfJlatbjMjuLSfE2kYT5pMDOilZ4OvMhi637CcDICTmz3wARPoyhqyX1Y+XvA==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^14.18.0 || >=16.10.0" + } + }, + "node_modules/copy-anything": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/copy-anything/-/copy-anything-3.0.5.tgz", + "integrity": "sha512-yCEafptTtb4bk7GLEQoM8KVJpxAfdBJYaXyzQEgQQQgYrZiDp8SJmGKlYza6CYjEDNstAdNdKA3UuoULlEbS6w==", + "license": "MIT", + "dependencies": { + "is-what": "^4.1.8" + }, + "engines": { + "node": ">=12.13" + }, + "funding": { + "url": "https://github.com/sponsors/mesqueeb" + } + }, + "node_modules/core-js-compat": { + "version": "3.45.1", + "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.45.1.tgz", + "integrity": "sha512-tqTt5T4PzsMIZ430XGviK4vzYSoeNJ6CXODi6c/voxOT6IZqBht5/EKaSNnYiEjjRYxjVz7DQIsOsY0XNi8PIA==", + "dev": true, + "license": "MIT", + "dependencies": { + "browserslist": "^4.25.3" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/core-js" + } + }, + "node_modules/cross-spawn": { + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", + "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", + "dev": true, + "license": "MIT", + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/cssesc": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz", + "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==", + "dev": true, + "license": "MIT", + "bin": { + "cssesc": "bin/cssesc" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/csstype": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz", + "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==", + "license": "MIT" + }, + "node_modules/debug": { + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", + "devOptional": true, + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/deep-is": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", + "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/detect-libc": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-1.0.3.tgz", + "integrity": "sha512-pGjwhsmsp4kL2RTz08wcOlGN83otlqHeD/Z5T8GXZB+/YcpQ/dgo+lbU8ZsGxV0HIvqqxo9l7mqYwyYMD9bKDg==", + "license": "Apache-2.0", + "optional": true, + "bin": { + "detect-libc": "bin/detect-libc.js" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/electron-to-chromium": { + "version": "1.5.230", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.230.tgz", + "integrity": "sha512-A6A6Fd3+gMdaed9wX83CvHYJb4UuapPD5X5SLq72VZJzxHSY0/LUweGXRWmQlh2ln7KV7iw7jnwXK7dlPoOnHQ==", + "dev": true, + "license": "ISC" + }, + "node_modules/empathic": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/empathic/-/empathic-2.0.0.tgz", + "integrity": "sha512-i6UzDscO/XfAcNYD75CfICkmfLedpyPDdozrLMmQc5ORaQcdMoc21OnlEylMIqI7U8eniKrPMxxtj8k0vhmJhA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=14" + } + }, + "node_modules/entities": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", + "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==", + "license": "BSD-2-Clause", + "engines": { + "node": ">=0.12" + }, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, + "node_modules/esbuild": { + "version": "0.25.10", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.25.10.tgz", + "integrity": "sha512-9RiGKvCwaqxO2owP61uQ4BgNborAQskMR6QusfWzQqv7AZOg5oGehdY2pRJMTKuwxd1IDBP4rSbI5lHzU7SMsQ==", + "devOptional": true, + "hasInstallScript": true, + "license": "MIT", + "bin": { + "esbuild": "bin/esbuild" + }, + "engines": { + "node": ">=18" + }, + "optionalDependencies": { + "@esbuild/aix-ppc64": "0.25.10", + "@esbuild/android-arm": "0.25.10", + "@esbuild/android-arm64": "0.25.10", + "@esbuild/android-x64": "0.25.10", + "@esbuild/darwin-arm64": "0.25.10", + "@esbuild/darwin-x64": "0.25.10", + "@esbuild/freebsd-arm64": "0.25.10", + "@esbuild/freebsd-x64": "0.25.10", + "@esbuild/linux-arm": "0.25.10", + "@esbuild/linux-arm64": "0.25.10", + "@esbuild/linux-ia32": "0.25.10", + "@esbuild/linux-loong64": "0.25.10", + "@esbuild/linux-mips64el": "0.25.10", + "@esbuild/linux-ppc64": "0.25.10", + "@esbuild/linux-riscv64": "0.25.10", + "@esbuild/linux-s390x": "0.25.10", + "@esbuild/linux-x64": "0.25.10", + "@esbuild/netbsd-arm64": "0.25.10", + "@esbuild/netbsd-x64": "0.25.10", + "@esbuild/openbsd-arm64": "0.25.10", + "@esbuild/openbsd-x64": "0.25.10", + "@esbuild/openharmony-arm64": "0.25.10", + "@esbuild/sunos-x64": "0.25.10", + "@esbuild/win32-arm64": "0.25.10", + "@esbuild/win32-ia32": "0.25.10", + "@esbuild/win32-x64": "0.25.10" + } + }, + "node_modules/escalade": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", + "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint": { + "version": "9.36.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.36.0.tgz", + "integrity": "sha512-hB4FIzXovouYzwzECDcUkJ4OcfOEkXTv2zRY6B9bkwjx/cprAq0uvm1nl7zvQ0/TsUk0zQiN4uPfJpB9m+rPMQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@eslint-community/eslint-utils": "^4.8.0", + "@eslint-community/regexpp": "^4.12.1", + "@eslint/config-array": "^0.21.0", + "@eslint/config-helpers": "^0.3.1", + "@eslint/core": "^0.15.2", + "@eslint/eslintrc": "^3.3.1", + "@eslint/js": "9.36.0", + "@eslint/plugin-kit": "^0.3.5", + "@humanfs/node": "^0.16.6", + "@humanwhocodes/module-importer": "^1.0.1", + "@humanwhocodes/retry": "^0.4.2", + "@types/estree": "^1.0.6", + "@types/json-schema": "^7.0.15", + "ajv": "^6.12.4", + "chalk": "^4.0.0", + "cross-spawn": "^7.0.6", + "debug": "^4.3.2", + "escape-string-regexp": "^4.0.0", + "eslint-scope": "^8.4.0", + "eslint-visitor-keys": "^4.2.1", + "espree": "^10.4.0", + "esquery": "^1.5.0", + "esutils": "^2.0.2", + "fast-deep-equal": "^3.1.3", + "file-entry-cache": "^8.0.0", + "find-up": "^5.0.0", + "glob-parent": "^6.0.2", + "ignore": "^5.2.0", + "imurmurhash": "^0.1.4", + "is-glob": "^4.0.0", + "json-stable-stringify-without-jsonify": "^1.0.1", + "lodash.merge": "^4.6.2", + "minimatch": "^3.1.2", + "natural-compare": "^1.4.0", + "optionator": "^0.9.3" + }, + "bin": { + "eslint": "bin/eslint.js" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://eslint.org/donate" + }, + "peerDependencies": { + "jiti": "*" + }, + "peerDependenciesMeta": { + "jiti": { + "optional": true + } + } + }, + "node_modules/eslint-compat-utils": { + "version": "0.6.5", + "resolved": "https://registry.npmjs.org/eslint-compat-utils/-/eslint-compat-utils-0.6.5.tgz", + "integrity": "sha512-vAUHYzue4YAa2hNACjB8HvUQj5yehAZgiClyFVVom9cP8z5NSFq3PwB/TtJslN2zAMgRX6FCFCjYBbQh71g5RQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "semver": "^7.5.4" + }, + "engines": { + "node": ">=12" + }, + "peerDependencies": { + "eslint": ">=6.0.0" + } + }, + "node_modules/eslint-config-flat-gitignore": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/eslint-config-flat-gitignore/-/eslint-config-flat-gitignore-2.1.0.tgz", + "integrity": "sha512-cJzNJ7L+psWp5mXM7jBX+fjHtBvvh06RBlcweMhKD8jWqQw0G78hOW5tpVALGHGFPsBV+ot2H+pdDGJy6CV8pA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@eslint/compat": "^1.2.5" + }, + "funding": { + "url": "https://github.com/sponsors/antfu" + }, + "peerDependencies": { + "eslint": "^9.5.0" + } + }, + "node_modules/eslint-config-vuetify": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/eslint-config-vuetify/-/eslint-config-vuetify-4.2.0.tgz", + "integrity": "sha512-+Ffgv5IUiobXEbKq2fJpsYeb67XU3ttisyaOeav41P0MJec+JucUIBxvmt36rdI3RrKgWDMBwwuYpyFncUQJag==", + "dev": true, + "license": "MIT", + "dependencies": { + "@clack/prompts": "^0.11.0", + "@eslint/eslintrc": "^3.3.1", + "@eslint/js": "^9.35.0", + "@stylistic/eslint-plugin": "^5.3.1", + "@typescript-eslint/parser": "^8.43.0", + "eslint-config-flat-gitignore": "^2.1.0", + "eslint-flat-config-utils": "^2.1.1", + "eslint-plugin-antfu": "^3.1.1", + "eslint-plugin-import-lite": "^0.3.0", + "eslint-plugin-jsonc": "^2.20.1", + "eslint-plugin-perfectionist": "^4.15.0", + "eslint-plugin-pnpm": "^1.1.1", + "eslint-plugin-regexp": "^2.10.0", + "eslint-plugin-unicorn": "^61.0.2", + "eslint-plugin-vue": "^10.4.0", + "eslint-typegen": "^2.3.0", + "exsolve": "^1.0.7", + "globals": "^16.4.0", + "jsonc-eslint-parser": "^2.4.0", + "kolorist": "^1.8.0", + "local-pkg": "^1.1.2", + "nypm": "^0.6.1", + "package-manager-detector": "^1.3.0", + "tinyexec": "^1.0.1", + "typescript-eslint": "^8.43.0", + "vue-eslint-parser": "^10.2.0", + "yaml-eslint-parser": "^1.3.0" + }, + "bin": { + "eslint-config-vuetify": "bin/cli.mjs" + }, + "peerDependencies": { + "@vitest/eslint-plugin": "^1.1.42", + "eslint": "^9.5.0", + "eslint-plugin-jest": "^29.0.1", + "eslint-plugin-no-only-tests": "^3.3.0", + "eslint-plugin-vuejs-accessibility": "^2.0.0" + }, + "peerDependenciesMeta": { + "@vitest/eslint-plugin": { + "optional": true + }, + "eslint-plugin-jest": { + "optional": true + }, + "eslint-plugin-no-only-tests": { + "optional": true + }, + "eslint-plugin-vuejs-accessibility": { + "optional": true + } + } + }, + "node_modules/eslint-config-vuetify/node_modules/globals": { + "version": "16.4.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-16.4.0.tgz", + "integrity": "sha512-ob/2LcVVaVGCYN+r14cnwnoDPUufjiYgSqRhiFD0Q1iI4Odora5RE8Iv1D24hAz5oMophRGkGz+yuvQmmUMnMw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint-flat-config-utils": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/eslint-flat-config-utils/-/eslint-flat-config-utils-2.1.4.tgz", + "integrity": "sha512-bEnmU5gqzS+4O+id9vrbP43vByjF+8KOs+QuuV4OlqAuXmnRW2zfI/Rza1fQvdihQ5h4DUo0NqFAiViD4mSrzQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "pathe": "^2.0.3" + }, + "funding": { + "url": "https://github.com/sponsors/antfu" + } + }, + "node_modules/eslint-json-compat-utils": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/eslint-json-compat-utils/-/eslint-json-compat-utils-0.2.1.tgz", + "integrity": "sha512-YzEodbDyW8DX8bImKhAcCeu/L31Dd/70Bidx2Qex9OFUtgzXLqtfWL4Hr5fM/aCCB8QUZLuJur0S9k6UfgFkfg==", + "dev": true, + "license": "MIT", + "dependencies": { + "esquery": "^1.6.0" + }, + "engines": { + "node": ">=12" + }, + "peerDependencies": { + "eslint": "*", + "jsonc-eslint-parser": "^2.4.0" + }, + "peerDependenciesMeta": { + "@eslint/json": { + "optional": true + } + } + }, + "node_modules/eslint-plugin-antfu": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-antfu/-/eslint-plugin-antfu-3.1.1.tgz", + "integrity": "sha512-7Q+NhwLfHJFvopI2HBZbSxWXngTwBLKxW1AGXLr2lEGxcEIK/AsDs8pn8fvIizl5aZjBbVbVK5ujmMpBe4Tvdg==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/antfu" + }, + "peerDependencies": { + "eslint": "*" + } + }, + "node_modules/eslint-plugin-import-lite": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-import-lite/-/eslint-plugin-import-lite-0.3.0.tgz", + "integrity": "sha512-dkNBAL6jcoCsXZsQ/Tt2yXmMDoNt5NaBh/U7yvccjiK8cai6Ay+MK77bMykmqQA2bTF6lngaLCDij6MTO3KkvA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@eslint-community/eslint-utils": "^4.7.0", + "@typescript-eslint/types": "^8.34.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "peerDependencies": { + "eslint": ">=9.0.0", + "typescript": ">=4.5" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/eslint-plugin-jsonc": { + "version": "2.20.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-jsonc/-/eslint-plugin-jsonc-2.20.1.tgz", + "integrity": "sha512-gUzIwQHXx7ZPypUoadcyRi4WbHW2TPixDr0kqQ4miuJBU0emJmyGTlnaT3Og9X2a8R1CDayN9BFSq5weGWbTng==", + "dev": true, + "license": "MIT", + "dependencies": { + "@eslint-community/eslint-utils": "^4.5.1", + "eslint-compat-utils": "^0.6.4", + "eslint-json-compat-utils": "^0.2.1", + "espree": "^9.6.1 || ^10.3.0", + "graphemer": "^1.4.0", + "jsonc-eslint-parser": "^2.4.0", + "natural-compare": "^1.4.0", + "synckit": "^0.6.2 || ^0.7.3 || ^0.11.5" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/ota-meshi" + }, + "peerDependencies": { + "eslint": ">=6.0.0" + } + }, + "node_modules/eslint-plugin-perfectionist": { + "version": "4.15.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-perfectionist/-/eslint-plugin-perfectionist-4.15.0.tgz", + "integrity": "sha512-pC7PgoXyDnEXe14xvRUhBII8A3zRgggKqJFx2a82fjrItDs1BSI7zdZnQtM2yQvcyod6/ujmzb7ejKPx8lZTnw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/types": "^8.34.1", + "@typescript-eslint/utils": "^8.34.1", + "natural-orderby": "^5.0.0" + }, + "engines": { + "node": "^18.0.0 || >=20.0.0" + }, + "peerDependencies": { + "eslint": ">=8.45.0" + } + }, + "node_modules/eslint-plugin-pnpm": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-pnpm/-/eslint-plugin-pnpm-1.2.0.tgz", + "integrity": "sha512-HKIFEmRGVxXvPx/hCpZY0qUGCYoaSYO6EVut4Hf9bckC0qP6F23mBgdoIExRZIWoViHuMznSaDU1FpQmc2xpgw==", + "dev": true, + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/antfu" + }, + { + "type": "individual", + "url": "https://github.com/sponsors/sxzz" + } + ], + "license": "MIT", + "dependencies": { + "empathic": "^2.0.0", + "jsonc-eslint-parser": "^2.4.1", + "pathe": "^2.0.3", + "pnpm-workspace-yaml": "1.2.0", + "tinyglobby": "^0.2.15", + "yaml-eslint-parser": "^1.3.0" + }, + "peerDependencies": { + "eslint": "^9.0.0" + } + }, + "node_modules/eslint-plugin-regexp": { + "version": "2.10.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-regexp/-/eslint-plugin-regexp-2.10.0.tgz", + "integrity": "sha512-ovzQT8ESVn5oOe5a7gIDPD5v9bCSjIFJu57sVPDqgPRXicQzOnYfFN21WoQBQF18vrhT5o7UMKFwJQVVjyJ0ng==", + "dev": true, + "license": "MIT", + "dependencies": { + "@eslint-community/eslint-utils": "^4.2.0", + "@eslint-community/regexpp": "^4.11.0", + "comment-parser": "^1.4.0", + "jsdoc-type-pratt-parser": "^4.0.0", + "refa": "^0.12.1", + "regexp-ast-analysis": "^0.7.1", + "scslre": "^0.3.0" + }, + "engines": { + "node": "^18 || >=20" + }, + "peerDependencies": { + "eslint": ">=8.44.0" + } + }, + "node_modules/eslint-plugin-unicorn": { + "version": "61.0.2", + "resolved": "https://registry.npmjs.org/eslint-plugin-unicorn/-/eslint-plugin-unicorn-61.0.2.tgz", + "integrity": "sha512-zLihukvneYT7f74GNbVJXfWIiNQmkc/a9vYBTE4qPkQZswolWNdu+Wsp9sIXno1JOzdn6OUwLPd19ekXVkahRA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-validator-identifier": "^7.27.1", + "@eslint-community/eslint-utils": "^4.7.0", + "@eslint/plugin-kit": "^0.3.3", + "change-case": "^5.4.4", + "ci-info": "^4.3.0", + "clean-regexp": "^1.0.0", + "core-js-compat": "^3.44.0", + "esquery": "^1.6.0", + "find-up-simple": "^1.0.1", + "globals": "^16.3.0", + "indent-string": "^5.0.0", + "is-builtin-module": "^5.0.0", + "jsesc": "^3.1.0", + "pluralize": "^8.0.0", + "regexp-tree": "^0.1.27", + "regjsparser": "^0.12.0", + "semver": "^7.7.2", + "strip-indent": "^4.0.0" + }, + "engines": { + "node": "^20.10.0 || >=21.0.0" + }, + "funding": { + "url": "https://github.com/sindresorhus/eslint-plugin-unicorn?sponsor=1" + }, + "peerDependencies": { + "eslint": ">=9.29.0" + } + }, + "node_modules/eslint-plugin-unicorn/node_modules/globals": { + "version": "16.4.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-16.4.0.tgz", + "integrity": "sha512-ob/2LcVVaVGCYN+r14cnwnoDPUufjiYgSqRhiFD0Q1iI4Odora5RE8Iv1D24hAz5oMophRGkGz+yuvQmmUMnMw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint-plugin-vue": { + "version": "10.5.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-vue/-/eslint-plugin-vue-10.5.0.tgz", + "integrity": "sha512-7BZHsG3kC2vei8F2W8hnfDi9RK+cv5eKPMvzBdrl8Vuc0hR5odGQRli8VVzUkrmUHkxFEm4Iio1r5HOKslO0Aw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@eslint-community/eslint-utils": "^4.4.0", + "natural-compare": "^1.4.0", + "nth-check": "^2.1.1", + "postcss-selector-parser": "^6.0.15", + "semver": "^7.6.3", + "xml-name-validator": "^4.0.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "peerDependencies": { + "@stylistic/eslint-plugin": "^2.0.0 || ^3.0.0 || ^4.0.0 || ^5.0.0", + "@typescript-eslint/parser": "^7.0.0 || ^8.0.0", + "eslint": "^8.57.0 || ^9.0.0", + "vue-eslint-parser": "^10.0.0" + }, + "peerDependenciesMeta": { + "@stylistic/eslint-plugin": { + "optional": true + }, + "@typescript-eslint/parser": { + "optional": true + } + } + }, + "node_modules/eslint-scope": { + "version": "8.4.0", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.4.0.tgz", + "integrity": "sha512-sNXOfKCn74rt8RICKMvJS7XKV/Xk9kA7DyJr8mJik3S7Cwgy3qlkkmyS2uQB3jiJg6VNdZd/pDBJu0nvG2NlTg==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "esrecurse": "^4.3.0", + "estraverse": "^5.2.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint-typegen": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/eslint-typegen/-/eslint-typegen-2.3.0.tgz", + "integrity": "sha512-azYgAvhlz1AyTpeLfVSKcrNJInuIsRrcUrOcHmEl8T9oMKesePVUPrF8gRgE6azV8CAlFzxJDTyaXAAbA/BYiA==", + "dev": true, + "license": "MIT", + "dependencies": { + "json-schema-to-typescript-lite": "^15.0.0", + "ohash": "^2.0.11" + }, + "funding": { + "url": "https://github.com/sponsors/antfu" + }, + "peerDependencies": { + "eslint": "^9.0.0" + } + }, + "node_modules/eslint-visitor-keys": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.1.tgz", + "integrity": "sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/espree": { + "version": "10.4.0", + "resolved": "https://registry.npmjs.org/espree/-/espree-10.4.0.tgz", + "integrity": "sha512-j6PAQ2uUr79PZhBjP5C5fhl8e39FmRnOjsD5lGnWrFU8i2G776tBK7+nP8KuQUTTyAZUwfQqXAgrVH5MbH9CYQ==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "acorn": "^8.15.0", + "acorn-jsx": "^5.3.2", + "eslint-visitor-keys": "^4.2.1" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/esquery": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.6.0.tgz", + "integrity": "sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "estraverse": "^5.1.0" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/esrecurse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", + "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "estraverse": "^5.2.0" + }, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=4.0" + } + }, + "node_modules/estree-walker": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz", + "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==", + "license": "MIT" + }, + "node_modules/esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/exsolve": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/exsolve/-/exsolve-1.0.7.tgz", + "integrity": "sha512-VO5fQUzZtI6C+vx4w/4BWJpg3s/5l+6pRQEHzFRM8WFi4XffSP1Z+4qi7GbjWbvRQEbdIco5mIMq+zX4rPuLrw==", + "dev": true, + "license": "MIT" + }, + "node_modules/fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", + "dev": true, + "license": "MIT" + }, + "node_modules/fast-glob": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.3.tgz", + "integrity": "sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@nodelib/fs.stat": "^2.0.2", + "@nodelib/fs.walk": "^1.2.3", + "glob-parent": "^5.1.2", + "merge2": "^1.3.0", + "micromatch": "^4.0.8" + }, + "engines": { + "node": ">=8.6.0" + } + }, + "node_modules/fast-glob/node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "license": "ISC", + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", + "dev": true, + "license": "MIT" + }, + "node_modules/fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", + "dev": true, + "license": "MIT" + }, + "node_modules/fastq": { + "version": "1.19.1", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.19.1.tgz", + "integrity": "sha512-GwLTyxkCXjXbxqIhTsMI2Nui8huMPtnxg7krajPJAjnEG/iiOS7i+zCtWGZR9G0NBKbXKh6X9m9UIsYX/N6vvQ==", + "dev": true, + "license": "ISC", + "dependencies": { + "reusify": "^1.0.4" + } + }, + "node_modules/fdir": { + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz", + "integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==", + "devOptional": true, + "license": "MIT", + "engines": { + "node": ">=12.0.0" + }, + "peerDependencies": { + "picomatch": "^3 || ^4" + }, + "peerDependenciesMeta": { + "picomatch": { + "optional": true + } + } + }, + "node_modules/file-entry-cache": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-8.0.0.tgz", + "integrity": "sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "flat-cache": "^4.0.0" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/fill-range": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", + "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", + "devOptional": true, + "license": "MIT", + "dependencies": { + "to-regex-range": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/find-up": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "dev": true, + "license": "MIT", + "dependencies": { + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/find-up-simple": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/find-up-simple/-/find-up-simple-1.0.1.tgz", + "integrity": "sha512-afd4O7zpqHeRyg4PfDQsXmlDe2PfdHtJt6Akt8jOWaApLOZk5JXs6VMR29lz03pRe9mpykrRCYIYxaJYcfpncQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/flat-cache": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-4.0.1.tgz", + "integrity": "sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==", + "dev": true, + "license": "MIT", + "dependencies": { + "flatted": "^3.2.9", + "keyv": "^4.5.4" + }, + "engines": { + "node": ">=16" + } + }, + "node_modules/flatted": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.3.tgz", + "integrity": "sha512-GX+ysw4PBCz0PzosHDepZGANEuFCMLrnRTiEy9McGjmkCQYwRq4A/X786G/fjM/+OjsWSU1ZrY5qyARZmO/uwg==", + "dev": true, + "license": "ISC" + }, + "node_modules/fsevents": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "hasInstallScript": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/glob-parent": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", + "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", + "dev": true, + "license": "ISC", + "dependencies": { + "is-glob": "^4.0.3" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/globals": { + "version": "14.0.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-14.0.0.tgz", + "integrity": "sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/graphemer": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz", + "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==", + "dev": true, + "license": "MIT" + }, + "node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "devOptional": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/hookable": { + "version": "5.5.3", + "resolved": "https://registry.npmjs.org/hookable/-/hookable-5.5.3.tgz", + "integrity": "sha512-Yc+BQe8SvoXH1643Qez1zqLRmbA5rCL+sSmk6TVos0LWVfNIB7PGncdlId77WzLGSIB5KaWgTaNTs2lNVEI6VQ==", + "license": "MIT" + }, + "node_modules/ignore": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", + "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 4" + } + }, + "node_modules/immutable": { + "version": "5.1.3", + "resolved": "https://registry.npmjs.org/immutable/-/immutable-5.1.3.tgz", + "integrity": "sha512-+chQdDfvscSF1SJqv2gn4SRO2ZyS3xL3r7IW/wWEEzrzLisnOlKiQu5ytC/BVNcS15C39WT2Hg/bjKjDMcu+zg==", + "devOptional": true, + "license": "MIT" + }, + "node_modules/import-fresh": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.1.tgz", + "integrity": "sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.8.19" + } + }, + "node_modules/indent-string": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-5.0.0.tgz", + "integrity": "sha512-m6FAo/spmsW2Ab2fU35JTYwtOKa2yAwXSwgjSv1TJzh4Mh7mC3lzAOVLBprb72XsTrgkEIsl7YrFNAiDiRhIGg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/inter-ui": { + "version": "3.19.3", + "resolved": "https://registry.npmjs.org/inter-ui/-/inter-ui-3.19.3.tgz", + "integrity": "sha512-5FG9fjuYOXocIfjzcCBhICL5cpvwEetseL3FU6tP3d6Bn7g8wODhB+I9RNGRTizCT7CUG4GOK54OPxqq3msQgg==", + "license": "OFL-1.1" + }, + "node_modules/is-binary-path": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", + "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", + "dev": true, + "license": "MIT", + "dependencies": { + "binary-extensions": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-builtin-module": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/is-builtin-module/-/is-builtin-module-5.0.0.tgz", + "integrity": "sha512-f4RqJKBUe5rQkJ2eJEJBXSticB3hGbN9j0yxxMQFqIW89Jp9WYFtzfTcRlstDKVUTRzSOTLKRfO9vIztenwtxA==", + "dev": true, + "license": "MIT", + "dependencies": { + "builtin-modules": "^5.0.0" + }, + "engines": { + "node": ">=18.20" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "devOptional": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "devOptional": true, + "license": "MIT", + "dependencies": { + "is-extglob": "^2.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "devOptional": true, + "license": "MIT", + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/is-what": { + "version": "4.1.16", + "resolved": "https://registry.npmjs.org/is-what/-/is-what-4.1.16.tgz", + "integrity": "sha512-ZhMwEosbFJkA0YhFnNDgTM4ZxDRsS6HqTo7qsZM08fehyRYIYa0yHu5R6mgo1n/8MgaPBXiPimPD77baVFYg+A==", + "license": "MIT", + "engines": { + "node": ">=12.13" + }, + "funding": { + "url": "https://github.com/sponsors/mesqueeb" + } + }, + "node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", + "dev": true, + "license": "ISC" + }, + "node_modules/js-tokens": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-9.0.1.tgz", + "integrity": "sha512-mxa9E9ITFOt0ban3j6L5MpjwegGz6lBQmM1IJkWeBZGcMxto50+eWdjC/52xDbS2vy0k7vIMK0Fe2wfL9OQSpQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/js-yaml": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", + "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "dev": true, + "license": "MIT", + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/jsdoc-type-pratt-parser": { + "version": "4.8.0", + "resolved": "https://registry.npmjs.org/jsdoc-type-pratt-parser/-/jsdoc-type-pratt-parser-4.8.0.tgz", + "integrity": "sha512-iZ8Bdb84lWRuGHamRXFyML07r21pcwBrLkHEuHgEY5UbCouBwv7ECknDRKzsQIXMiqpPymqtIf8TC/shYKB5rw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12.0.0" + } + }, + "node_modules/jsesc": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.1.0.tgz", + "integrity": "sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==", + "dev": true, + "license": "MIT", + "bin": { + "jsesc": "bin/jsesc" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/json-buffer": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", + "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/json-schema-to-typescript-lite": { + "version": "15.0.0", + "resolved": "https://registry.npmjs.org/json-schema-to-typescript-lite/-/json-schema-to-typescript-lite-15.0.0.tgz", + "integrity": "sha512-5mMORSQm9oTLyjM4mWnyNBi2T042Fhg1/0gCIB6X8U/LVpM2A+Nmj2yEyArqVouDmFThDxpEXcnTgSrjkGJRFA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@apidevtools/json-schema-ref-parser": "^14.1.1", + "@types/json-schema": "^7.0.15" + } + }, + "node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true, + "license": "MIT" + }, + "node_modules/json-stable-stringify-without-jsonify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", + "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", + "dev": true, + "license": "MIT" + }, + "node_modules/json5": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", + "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", + "dev": true, + "license": "MIT", + "bin": { + "json5": "lib/cli.js" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/jsonc-eslint-parser": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/jsonc-eslint-parser/-/jsonc-eslint-parser-2.4.1.tgz", + "integrity": "sha512-uuPNLJkKN8NXAlZlQ6kmUF9qO+T6Kyd7oV4+/7yy8Jz6+MZNyhPq8EdLpdfnPVzUC8qSf1b4j1azKaGnFsjmsw==", + "dev": true, + "license": "MIT", + "dependencies": { + "acorn": "^8.5.0", + "eslint-visitor-keys": "^3.0.0", + "espree": "^9.0.0", + "semver": "^7.3.5" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/ota-meshi" + } + }, + "node_modules/jsonc-eslint-parser/node_modules/eslint-visitor-keys": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", + "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/jsonc-eslint-parser/node_modules/espree": { + "version": "9.6.1", + "resolved": "https://registry.npmjs.org/espree/-/espree-9.6.1.tgz", + "integrity": "sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "acorn": "^8.9.0", + "acorn-jsx": "^5.3.2", + "eslint-visitor-keys": "^3.4.1" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/keyv": { + "version": "4.5.4", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", + "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==", + "dev": true, + "license": "MIT", + "dependencies": { + "json-buffer": "3.0.1" + } + }, + "node_modules/kolorist": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/kolorist/-/kolorist-1.8.0.tgz", + "integrity": "sha512-Y+60/zizpJ3HRH8DCss+q95yr6145JXZo46OTpFvDZWLfRCE4qChOyk1b26nMaNpfHHgxagk9dXT5OP0Tfe+dQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/levn": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", + "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "prelude-ls": "^1.2.1", + "type-check": "~0.4.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/local-pkg": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/local-pkg/-/local-pkg-1.1.2.tgz", + "integrity": "sha512-arhlxbFRmoQHl33a0Zkle/YWlmNwoyt6QNZEIJcqNbdrsix5Lvc4HyyI3EnwxTYlZYc32EbYrQ8SzEZ7dqgg9A==", + "dev": true, + "license": "MIT", + "dependencies": { + "mlly": "^1.7.4", + "pkg-types": "^2.3.0", + "quansync": "^0.2.11" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/antfu" + } + }, + "node_modules/locate-path": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-locate": "^5.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/lodash.merge": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", + "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/magic-string": { + "version": "0.30.19", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.19.tgz", + "integrity": "sha512-2N21sPY9Ws53PZvsEpVtNuSW+ScYbQdp4b9qUaL+9QkHUrGFKo56Lg9Emg5s9V/qrtNBmiR01sYhUOwu3H+VOw==", + "license": "MIT", + "dependencies": { + "@jridgewell/sourcemap-codec": "^1.5.5" + } + }, + "node_modules/magic-string-ast": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/magic-string-ast/-/magic-string-ast-1.0.2.tgz", + "integrity": "sha512-8ngQgLhcT0t3YBdn9CGkZqCYlvwW9pm7aWJwd7AxseVWf1RU8ZHCQvG1mt3N5vvUme+pXTcHB8G/7fE666U8Vw==", + "dev": true, + "license": "MIT", + "dependencies": { + "magic-string": "^0.30.17" + }, + "engines": { + "node": ">=20.18.0" + }, + "funding": { + "url": "https://github.com/sponsors/sxzz" + } + }, + "node_modules/merge2": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", + "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 8" + } + }, + "node_modules/micromatch": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", + "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", + "devOptional": true, + "license": "MIT", + "dependencies": { + "braces": "^3.0.3", + "picomatch": "^2.3.1" + }, + "engines": { + "node": ">=8.6" + } + }, + "node_modules/micromatch/node_modules/picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "devOptional": true, + "license": "MIT", + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/mitt": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/mitt/-/mitt-3.0.1.tgz", + "integrity": "sha512-vKivATfr97l2/QBCYAkXYDbrIWPM2IIKEl7YPhjCvKlG3kE2gm+uBo6nEXK3M5/Ffh/FLpKExzOQ3JJoJGFKBw==", + "license": "MIT" + }, + "node_modules/mlly": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/mlly/-/mlly-1.8.0.tgz", + "integrity": "sha512-l8D9ODSRWLe2KHJSifWGwBqpTZXIXTeo8mlKjY+E2HAakaTeNpqAyBZ8GSqLzHgw4XmHmC8whvpjJNMbFZN7/g==", + "dev": true, + "license": "MIT", + "dependencies": { + "acorn": "^8.15.0", + "pathe": "^2.0.3", + "pkg-types": "^1.3.1", + "ufo": "^1.6.1" + } + }, + "node_modules/mlly/node_modules/confbox": { + "version": "0.1.8", + "resolved": "https://registry.npmjs.org/confbox/-/confbox-0.1.8.tgz", + "integrity": "sha512-RMtmw0iFkeR4YV+fUOSucriAQNb9g8zFR52MWCtl+cCZOFRNL6zeB395vPzFhEjjn4fMxXudmELnl/KF/WrK6w==", + "dev": true, + "license": "MIT" + }, + "node_modules/mlly/node_modules/pkg-types": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/pkg-types/-/pkg-types-1.3.1.tgz", + "integrity": "sha512-/Jm5M4RvtBFVkKWRu2BLUTNP8/M2a+UwuAX+ae4770q1qVGtfjG+WTCupoZixokjmHiry8uI+dlY8KXYV5HVVQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "confbox": "^0.1.8", + "mlly": "^1.7.4", + "pathe": "^2.0.1" + } + }, + "node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "devOptional": true, + "license": "MIT" + }, + "node_modules/muggle-string": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/muggle-string/-/muggle-string-0.4.1.tgz", + "integrity": "sha512-VNTrAak/KhO2i8dqqnqnAHOa3cYBwXEZe9h+D5h/1ZqFSTEFHdM65lR7RoIqq3tBBYavsOXV84NoHXZ0AkPyqQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/nanoid": { + "version": "3.3.11", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.11.tgz", + "integrity": "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "bin": { + "nanoid": "bin/nanoid.cjs" + }, + "engines": { + "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" + } + }, + "node_modules/natural-compare": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", + "dev": true, + "license": "MIT" + }, + "node_modules/natural-orderby": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/natural-orderby/-/natural-orderby-5.0.0.tgz", + "integrity": "sha512-kKHJhxwpR/Okycz4HhQKKlhWe4ASEfPgkSWNmKFHd7+ezuQlxkA5cM3+XkBPvm1gmHen3w53qsYAv+8GwRrBlg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + } + }, + "node_modules/node-addon-api": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-7.1.1.tgz", + "integrity": "sha512-5m3bsyrjFWE1xf7nz7YXdN4udnVtXK6/Yfgn5qnahL6bCkf2yKt4k3nuTKAtT4r3IG8JNR2ncsIMdZuAzJjHQQ==", + "license": "MIT", + "optional": true + }, + "node_modules/node-releases": { + "version": "2.0.21", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.21.tgz", + "integrity": "sha512-5b0pgg78U3hwXkCM8Z9b2FJdPZlr9Psr9V2gQPESdGHqbntyFJKFW4r5TeWGFzafGY3hzs1JC62VEQMbl1JFkw==", + "dev": true, + "license": "MIT" + }, + "node_modules/normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/nth-check": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.1.1.tgz", + "integrity": "sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "boolbase": "^1.0.0" + }, + "funding": { + "url": "https://github.com/fb55/nth-check?sponsor=1" + } + }, + "node_modules/nypm": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/nypm/-/nypm-0.6.2.tgz", + "integrity": "sha512-7eM+hpOtrKrBDCh7Ypu2lJ9Z7PNZBdi/8AT3AX8xoCj43BBVHD0hPSTEvMtkMpfs8FCqBGhxB+uToIQimA111g==", + "dev": true, + "license": "MIT", + "dependencies": { + "citty": "^0.1.6", + "consola": "^3.4.2", + "pathe": "^2.0.3", + "pkg-types": "^2.3.0", + "tinyexec": "^1.0.1" + }, + "bin": { + "nypm": "dist/cli.mjs" + }, + "engines": { + "node": "^14.16.0 || >=16.10.0" + } + }, + "node_modules/ohash": { + "version": "2.0.11", + "resolved": "https://registry.npmjs.org/ohash/-/ohash-2.0.11.tgz", + "integrity": "sha512-RdR9FQrFwNBNXAr4GixM8YaRZRJ5PUWbKYbE5eOsrwAjJW0q2REGcf79oYPsLyskQCZG1PLN+S/K1V00joZAoQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/optionator": { + "version": "0.9.4", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz", + "integrity": "sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==", + "dev": true, + "license": "MIT", + "dependencies": { + "deep-is": "^0.1.3", + "fast-levenshtein": "^2.0.6", + "levn": "^0.4.1", + "prelude-ls": "^1.2.1", + "type-check": "^0.4.0", + "word-wrap": "^1.2.5" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "yocto-queue": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-locate": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-limit": "^3.0.2" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/package-manager-detector": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/package-manager-detector/-/package-manager-detector-1.3.0.tgz", + "integrity": "sha512-ZsEbbZORsyHuO00lY1kV3/t72yp6Ysay6Pd17ZAlNGuGwmWDLCJxFpRs0IzfXfj1o4icJOkUEioexFHzyPurSQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/parent-module": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", + "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", + "dev": true, + "license": "MIT", + "dependencies": { + "callsites": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/path-browserify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-browserify/-/path-browserify-1.0.1.tgz", + "integrity": "sha512-b7uo2UCUOYZcnF/3ID0lulOJi/bafxa1xPe7ZPsammBSpjSWQkjNxlt635YGS2MiR9GjvuXCtz2emr3jbsz98g==", + "dev": true, + "license": "MIT" + }, + "node_modules/path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/pathe": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/pathe/-/pathe-2.0.3.tgz", + "integrity": "sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==", + "dev": true, + "license": "MIT" + }, + "node_modules/perfect-debounce": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/perfect-debounce/-/perfect-debounce-1.0.0.tgz", + "integrity": "sha512-xCy9V055GLEqoFaHoC1SoLIaLmWctgCUaBaWxDZ7/Zx4CTyX7cJQLJOok/orfjZAh9kEYpjJa4d0KcJmCbctZA==", + "license": "MIT" + }, + "node_modules/picocolors": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", + "license": "ISC" + }, + "node_modules/picomatch": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz", + "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", + "devOptional": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/pinia": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/pinia/-/pinia-3.0.3.tgz", + "integrity": "sha512-ttXO/InUULUXkMHpTdp9Fj4hLpD/2AoJdmAbAeW2yu1iy1k+pkFekQXw5VpC0/5p51IOR/jDaDRfRWRnMMsGOA==", + "license": "MIT", + "dependencies": { + "@vue/devtools-api": "^7.7.2" + }, + "funding": { + "url": "https://github.com/sponsors/posva" + }, + "peerDependencies": { + "typescript": ">=4.4.4", + "vue": "^2.7.0 || ^3.5.11" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/pkg-types": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pkg-types/-/pkg-types-2.3.0.tgz", + "integrity": "sha512-SIqCzDRg0s9npO5XQ3tNZioRY1uK06lA41ynBC1YmFTmnY6FjUjVt6s4LoADmwoig1qqD0oK8h1p/8mlMx8Oig==", + "dev": true, + "license": "MIT", + "dependencies": { + "confbox": "^0.2.2", + "exsolve": "^1.0.7", + "pathe": "^2.0.3" + } + }, + "node_modules/pluralize": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/pluralize/-/pluralize-8.0.0.tgz", + "integrity": "sha512-Nc3IT5yHzflTfbjgqWcCPpo7DaKy4FnpB0l/zCAW0Tc7jxAiuqSxHasntB3D7887LSrA93kDJ9IXovxJYxyLCA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/pnpm-workspace-yaml": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/pnpm-workspace-yaml/-/pnpm-workspace-yaml-1.2.0.tgz", + "integrity": "sha512-4CnZHmLSaprRnIm2iQ27Zl1cWPRHdX7Ehw7ckRwujoPKCk2QAz4agsA2MbTodg4sgbqYfJ68ULT+Q5A8dU+Mow==", + "dev": true, + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/antfu" + }, + { + "type": "individual", + "url": "https://github.com/sponsors/sxzz" + } + ], + "license": "MIT", + "dependencies": { + "yaml": "^2.8.1" + } + }, + "node_modules/postcss": { + "version": "8.5.6", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.6.tgz", + "integrity": "sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/postcss" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "nanoid": "^3.3.11", + "picocolors": "^1.1.1", + "source-map-js": "^1.2.1" + }, + "engines": { + "node": "^10 || ^12 || >=14" + } + }, + "node_modules/postcss-selector-parser": { + "version": "6.1.2", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.1.2.tgz", + "integrity": "sha512-Q8qQfPiZ+THO/3ZrOrO0cJJKfpYCagtMUkXbnEfmgUjwXg6z/WBeOyS9APBBPCTSiDV+s4SwQGu8yFsiMRIudg==", + "dev": true, + "license": "MIT", + "dependencies": { + "cssesc": "^3.0.0", + "util-deprecate": "^1.0.2" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/prelude-ls": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", + "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/punycode": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", + "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/quansync": { + "version": "0.2.11", + "resolved": "https://registry.npmjs.org/quansync/-/quansync-0.2.11.tgz", + "integrity": "sha512-AifT7QEbW9Nri4tAwR5M/uzpBuqfZf+zwaEM/QkzEjj7NBuFD2rBuy0K3dE+8wltbezDV7JMA0WfnCPYRSYbXA==", + "dev": true, + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/antfu" + }, + { + "type": "individual", + "url": "https://github.com/sponsors/sxzz" + } + ], + "license": "MIT" + }, + "node_modules/queue-microtask": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", + "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, + "node_modules/readdirp": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-4.1.2.tgz", + "integrity": "sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg==", + "devOptional": true, + "license": "MIT", + "engines": { + "node": ">= 14.18.0" + }, + "funding": { + "type": "individual", + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/refa": { + "version": "0.12.1", + "resolved": "https://registry.npmjs.org/refa/-/refa-0.12.1.tgz", + "integrity": "sha512-J8rn6v4DBb2nnFqkqwy6/NnTYMcgLA+sLr0iIO41qpv0n+ngb7ksag2tMRl0inb1bbO/esUwzW1vbJi7K0sI0g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@eslint-community/regexpp": "^4.8.0" + }, + "engines": { + "node": "^12.0.0 || ^14.0.0 || >=16.0.0" + } + }, + "node_modules/regexp-ast-analysis": { + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/regexp-ast-analysis/-/regexp-ast-analysis-0.7.1.tgz", + "integrity": "sha512-sZuz1dYW/ZsfG17WSAG7eS85r5a0dDsvg+7BiiYR5o6lKCAtUrEwdmRmaGF6rwVj3LcmAeYkOWKEPlbPzN3Y3A==", + "dev": true, + "license": "MIT", + "dependencies": { + "@eslint-community/regexpp": "^4.8.0", + "refa": "^0.12.1" + }, + "engines": { + "node": "^12.0.0 || ^14.0.0 || >=16.0.0" + } + }, + "node_modules/regexp-tree": { + "version": "0.1.27", + "resolved": "https://registry.npmjs.org/regexp-tree/-/regexp-tree-0.1.27.tgz", + "integrity": "sha512-iETxpjK6YoRWJG5o6hXLwvjYAoW+FEZn9os0PD/b6AP6xQwsa/Y7lCVgIixBbUPMfhu+i2LtdeAqVTgGlQarfA==", + "dev": true, + "license": "MIT", + "bin": { + "regexp-tree": "bin/regexp-tree" + } + }, + "node_modules/regjsparser": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.12.0.tgz", + "integrity": "sha512-cnE+y8bz4NhMjISKbgeVJtqNbtf5QpjZP+Bslo+UqkIt9QPnX9q095eiRRASJG1/tz6dlNr6Z5NsBiWYokp6EQ==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "jsesc": "~3.0.2" + }, + "bin": { + "regjsparser": "bin/parser" + } + }, + "node_modules/regjsparser/node_modules/jsesc": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.0.2.tgz", + "integrity": "sha512-xKqzzWXDttJuOcawBt4KnKHHIf5oQ/Cxax+0PWFG+DFDgHNAdi+TXECADI+RYiFUMmx8792xsMbbgXj4CwnP4g==", + "dev": true, + "license": "MIT", + "bin": { + "jsesc": "bin/jsesc" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/resolve-from": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/reusify": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.1.0.tgz", + "integrity": "sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==", + "dev": true, + "license": "MIT", + "engines": { + "iojs": ">=1.0.0", + "node": ">=0.10.0" + } + }, + "node_modules/rfdc": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.4.1.tgz", + "integrity": "sha512-q1b3N5QkRUWUl7iyylaaj3kOpIT0N2i9MqIEQXP73GVsN9cw3fdx8X63cEmWhJGi2PPCF23Ijp7ktmd39rawIA==", + "license": "MIT" + }, + "node_modules/rollup": { + "version": "4.52.4", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.52.4.tgz", + "integrity": "sha512-CLEVl+MnPAiKh5pl4dEWSyMTpuflgNQiLGhMv8ezD5W/qP8AKvmYpCOKRRNOh7oRKnauBZ4SyeYkMS+1VSyKwQ==", + "devOptional": true, + "license": "MIT", + "dependencies": { + "@types/estree": "1.0.8" + }, + "bin": { + "rollup": "dist/bin/rollup" + }, + "engines": { + "node": ">=18.0.0", + "npm": ">=8.0.0" + }, + "optionalDependencies": { + "@rollup/rollup-android-arm-eabi": "4.52.4", + "@rollup/rollup-android-arm64": "4.52.4", + "@rollup/rollup-darwin-arm64": "4.52.4", + "@rollup/rollup-darwin-x64": "4.52.4", + "@rollup/rollup-freebsd-arm64": "4.52.4", + "@rollup/rollup-freebsd-x64": "4.52.4", + "@rollup/rollup-linux-arm-gnueabihf": "4.52.4", + "@rollup/rollup-linux-arm-musleabihf": "4.52.4", + "@rollup/rollup-linux-arm64-gnu": "4.52.4", + "@rollup/rollup-linux-arm64-musl": "4.52.4", + "@rollup/rollup-linux-loong64-gnu": "4.52.4", + "@rollup/rollup-linux-ppc64-gnu": "4.52.4", + "@rollup/rollup-linux-riscv64-gnu": "4.52.4", + "@rollup/rollup-linux-riscv64-musl": "4.52.4", + "@rollup/rollup-linux-s390x-gnu": "4.52.4", + "@rollup/rollup-linux-x64-gnu": "4.52.4", + "@rollup/rollup-linux-x64-musl": "4.52.4", + "@rollup/rollup-openharmony-arm64": "4.52.4", + "@rollup/rollup-win32-arm64-msvc": "4.52.4", + "@rollup/rollup-win32-ia32-msvc": "4.52.4", + "@rollup/rollup-win32-x64-gnu": "4.52.4", + "@rollup/rollup-win32-x64-msvc": "4.52.4", + "fsevents": "~2.3.2" + } + }, + "node_modules/run-parallel": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", + "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT", + "dependencies": { + "queue-microtask": "^1.2.2" + } + }, + "node_modules/rxjs": { + "version": "7.8.2", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.2.tgz", + "integrity": "sha512-dhKf903U/PQZY6boNNtAGdWbG85WAbjT/1xYoZIC7FAY0yWapOBQVsVrDl58W86//e1VpMNBtRV4MaXfdMySFA==", + "devOptional": true, + "license": "Apache-2.0", + "dependencies": { + "tslib": "^2.1.0" + } + }, + "node_modules/sass": { + "version": "1.93.2", + "resolved": "https://registry.npmjs.org/sass/-/sass-1.93.2.tgz", + "integrity": "sha512-t+YPtOQHpGW1QWsh1CHQ5cPIr9lbbGZLZnbihP/D/qZj/yuV68m8qarcV17nvkOX81BCrvzAlq2klCQFZghyTg==", + "license": "MIT", + "optional": true, + "dependencies": { + "chokidar": "^4.0.0", + "immutable": "^5.0.2", + "source-map-js": ">=0.6.2 <2.0.0" + }, + "bin": { + "sass": "sass.js" + }, + "engines": { + "node": ">=14.0.0" + }, + "optionalDependencies": { + "@parcel/watcher": "^2.4.1" + } + }, + "node_modules/sass-embedded": { + "version": "1.93.2", + "resolved": "https://registry.npmjs.org/sass-embedded/-/sass-embedded-1.93.2.tgz", + "integrity": "sha512-FvQdkn2dZ8DGiLgi0Uf4zsj7r/BsiLImNa5QJ10eZalY6NfZyjrmWGFcuCN5jNwlDlXFJnftauv+UtvBKLvepQ==", + "devOptional": true, + "license": "MIT", + "dependencies": { + "@bufbuild/protobuf": "^2.5.0", + "buffer-builder": "^0.2.0", + "colorjs.io": "^0.5.0", + "immutable": "^5.0.2", + "rxjs": "^7.4.0", + "supports-color": "^8.1.1", + "sync-child-process": "^1.0.2", + "varint": "^6.0.0" + }, + "bin": { + "sass": "dist/bin/sass.js" + }, + "engines": { + "node": ">=16.0.0" + }, + "optionalDependencies": { + "sass-embedded-all-unknown": "1.93.2", + "sass-embedded-android-arm": "1.93.2", + "sass-embedded-android-arm64": "1.93.2", + "sass-embedded-android-riscv64": "1.93.2", + "sass-embedded-android-x64": "1.93.2", + "sass-embedded-darwin-arm64": "1.93.2", + "sass-embedded-darwin-x64": "1.93.2", + "sass-embedded-linux-arm": "1.93.2", + "sass-embedded-linux-arm64": "1.93.2", + "sass-embedded-linux-musl-arm": "1.93.2", + "sass-embedded-linux-musl-arm64": "1.93.2", + "sass-embedded-linux-musl-riscv64": "1.93.2", + "sass-embedded-linux-musl-x64": "1.93.2", + "sass-embedded-linux-riscv64": "1.93.2", + "sass-embedded-linux-x64": "1.93.2", + "sass-embedded-unknown-all": "1.93.2", + "sass-embedded-win32-arm64": "1.93.2", + "sass-embedded-win32-x64": "1.93.2" + } + }, + "node_modules/sass-embedded-all-unknown": { + "version": "1.93.2", + "resolved": "https://registry.npmjs.org/sass-embedded-all-unknown/-/sass-embedded-all-unknown-1.93.2.tgz", + "integrity": "sha512-GdEuPXIzmhRS5J7UKAwEvtk8YyHQuFZRcpnEnkA3rwRUI27kwjyXkNeIj38XjUQ3DzrfMe8HcKFaqWGHvblS7Q==", + "cpu": [ + "!arm", + "!arm64", + "!riscv64", + "!x64" + ], + "license": "MIT", + "optional": true, + "dependencies": { + "sass": "1.93.2" + } + }, + "node_modules/sass-embedded-android-arm": { + "version": "1.93.2", + "resolved": "https://registry.npmjs.org/sass-embedded-android-arm/-/sass-embedded-android-arm-1.93.2.tgz", + "integrity": "sha512-I8bpO8meZNo5FvFx5FIiE7DGPVOYft0WjuwcCCdeJ6duwfkl6tZdatex1GrSigvTsuz9L0m4ngDcX/Tj/8yMow==", + "cpu": [ + "arm" + ], + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/sass-embedded-android-arm64": { + "version": "1.93.2", + "resolved": "https://registry.npmjs.org/sass-embedded-android-arm64/-/sass-embedded-android-arm64-1.93.2.tgz", + "integrity": "sha512-346f4iVGAPGcNP6V6IOOFkN5qnArAoXNTPr5eA/rmNpeGwomdb7kJyQ717r9rbJXxOG8OAAUado6J0qLsjnjXQ==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/sass-embedded-android-riscv64": { + "version": "1.93.2", + "resolved": "https://registry.npmjs.org/sass-embedded-android-riscv64/-/sass-embedded-android-riscv64-1.93.2.tgz", + "integrity": "sha512-hSMW1s4yJf5guT9mrdkumluqrwh7BjbZ4MbBW9tmi1DRDdlw1Wh9Oy1HnnmOG8x9XcI1qkojtPL6LUuEJmsiDg==", + "cpu": [ + "riscv64" + ], + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/sass-embedded-android-x64": { + "version": "1.93.2", + "resolved": "https://registry.npmjs.org/sass-embedded-android-x64/-/sass-embedded-android-x64-1.93.2.tgz", + "integrity": "sha512-JqktiHZduvn+ldGBosE40ALgQ//tGCVNAObgcQ6UIZznEJbsHegqStqhRo8UW3x2cgOO2XYJcrInH6cc7wdKbw==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/sass-embedded-darwin-arm64": { + "version": "1.93.2", + "resolved": "https://registry.npmjs.org/sass-embedded-darwin-arm64/-/sass-embedded-darwin-arm64-1.93.2.tgz", + "integrity": "sha512-qI1X16qKNeBJp+M/5BNW7v/JHCDYWr1/mdoJ7+UMHmP0b5AVudIZtimtK0hnjrLnBECURifd6IkulybR+h+4UA==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/sass-embedded-darwin-x64": { + "version": "1.93.2", + "resolved": "https://registry.npmjs.org/sass-embedded-darwin-x64/-/sass-embedded-darwin-x64-1.93.2.tgz", + "integrity": "sha512-4KeAvlkQ0m0enKUnDGQJZwpovYw99iiMb8CTZRSsQm8Eh7halbJZVmx67f4heFY/zISgVOCcxNg19GrM5NTwtA==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/sass-embedded-linux-arm": { + "version": "1.93.2", + "resolved": "https://registry.npmjs.org/sass-embedded-linux-arm/-/sass-embedded-linux-arm-1.93.2.tgz", + "integrity": "sha512-N3+D/ToHtzwLDO+lSH05Wo6/KRxFBPnbjVHASOlHzqJnK+g5cqex7IFAp6ozzlRStySk61Rp6d+YGrqZ6/P0PA==", + "cpu": [ + "arm" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/sass-embedded-linux-arm64": { + "version": "1.93.2", + "resolved": "https://registry.npmjs.org/sass-embedded-linux-arm64/-/sass-embedded-linux-arm64-1.93.2.tgz", + "integrity": "sha512-9ftX6nd5CsShJqJ2WRg+ptaYvUW+spqZfJ88FbcKQBNFQm6L87luj3UI1rB6cP5EWrLwHA754OKxRJyzWiaN6g==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/sass-embedded-linux-musl-arm": { + "version": "1.93.2", + "resolved": "https://registry.npmjs.org/sass-embedded-linux-musl-arm/-/sass-embedded-linux-musl-arm-1.93.2.tgz", + "integrity": "sha512-XBTvx66yRenvEsp3VaJCb3HQSyqCsUh7R+pbxcN5TuzueybZi0LXvn9zneksdXcmjACMlMpIVXi6LyHPQkYc8A==", + "cpu": [ + "arm" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/sass-embedded-linux-musl-arm64": { + "version": "1.93.2", + "resolved": "https://registry.npmjs.org/sass-embedded-linux-musl-arm64/-/sass-embedded-linux-musl-arm64-1.93.2.tgz", + "integrity": "sha512-+3EHuDPkMiAX5kytsjEC1bKZCawB9J6pm2eBIzzLMPWbf5xdx++vO1DpT7hD4bm4ZGn0eVHgSOKIfP6CVz6tVg==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/sass-embedded-linux-musl-riscv64": { + "version": "1.93.2", + "resolved": "https://registry.npmjs.org/sass-embedded-linux-musl-riscv64/-/sass-embedded-linux-musl-riscv64-1.93.2.tgz", + "integrity": "sha512-0sB5kmVZDKTYzmCSlTUnjh6mzOhzmQiW/NNI5g8JS4JiHw2sDNTvt1dsFTuqFkUHyEOY3ESTsfHHBQV8Ip4bEA==", + "cpu": [ + "riscv64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/sass-embedded-linux-musl-x64": { + "version": "1.93.2", + "resolved": "https://registry.npmjs.org/sass-embedded-linux-musl-x64/-/sass-embedded-linux-musl-x64-1.93.2.tgz", + "integrity": "sha512-t3ejQ+1LEVuHy7JHBI2tWHhoMfhedUNDjGJR2FKaLgrtJntGnyD1RyX0xb3nuqL/UXiEAtmTmZY+Uh3SLUe1Hg==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/sass-embedded-linux-riscv64": { + "version": "1.93.2", + "resolved": "https://registry.npmjs.org/sass-embedded-linux-riscv64/-/sass-embedded-linux-riscv64-1.93.2.tgz", + "integrity": "sha512-e7AndEwAbFtXaLy6on4BfNGTr3wtGZQmypUgYpSNVcYDO+CWxatKVY4cxbehMPhxG9g5ru+eaMfynvhZt7fLaA==", + "cpu": [ + "riscv64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/sass-embedded-linux-x64": { + "version": "1.93.2", + "resolved": "https://registry.npmjs.org/sass-embedded-linux-x64/-/sass-embedded-linux-x64-1.93.2.tgz", + "integrity": "sha512-U3EIUZQL11DU0xDDHXexd4PYPHQaSQa2hzc4EzmhHqrAj+TyfYO94htjWOd+DdTPtSwmLp+9cTWwPZBODzC96w==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/sass-embedded-unknown-all": { + "version": "1.93.2", + "resolved": "https://registry.npmjs.org/sass-embedded-unknown-all/-/sass-embedded-unknown-all-1.93.2.tgz", + "integrity": "sha512-7VnaOmyewcXohiuoFagJ3SK5ddP9yXpU0rzz+pZQmS1/+5O6vzyFCUoEt3HDRaLctH4GT3nUGoK1jg0ae62IfQ==", + "license": "MIT", + "optional": true, + "os": [ + "!android", + "!darwin", + "!linux", + "!win32" + ], + "dependencies": { + "sass": "1.93.2" + } + }, + "node_modules/sass-embedded-win32-arm64": { + "version": "1.93.2", + "resolved": "https://registry.npmjs.org/sass-embedded-win32-arm64/-/sass-embedded-win32-arm64-1.93.2.tgz", + "integrity": "sha512-Y90DZDbQvtv4Bt0GTXKlcT9pn4pz8AObEjFF8eyul+/boXwyptPZ/A1EyziAeNaIEIfxyy87z78PUgCeGHsx3Q==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/sass-embedded-win32-x64": { + "version": "1.93.2", + "resolved": "https://registry.npmjs.org/sass-embedded-win32-x64/-/sass-embedded-win32-x64-1.93.2.tgz", + "integrity": "sha512-BbSucRP6PVRZGIwlEBkp+6VQl2GWdkWFMN+9EuOTPrLxCJZoq+yhzmbjspd3PeM8+7WJ7AdFu/uRYdO8tor1iQ==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/sass-embedded/node_modules/supports-color": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", + "devOptional": true, + "license": "MIT", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/supports-color?sponsor=1" + } + }, + "node_modules/scslre": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/scslre/-/scslre-0.3.0.tgz", + "integrity": "sha512-3A6sD0WYP7+QrjbfNA2FN3FsOaGGFoekCVgTyypy53gPxhbkCIjtO6YWgdrfM+n/8sI8JeXZOIxsHjMTNxQ4nQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@eslint-community/regexpp": "^4.8.0", + "refa": "^0.12.0", + "regexp-ast-analysis": "^0.7.0" + }, + "engines": { + "node": "^14.0.0 || >=16.0.0" + } + }, + "node_modules/scule": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/scule/-/scule-1.3.0.tgz", + "integrity": "sha512-6FtHJEvt+pVMIB9IBY+IcCJ6Z5f1iQnytgyfKMhDKgmzYG+TeH/wx1y3l27rshSbLiSanrR9ffZDrEsmjlQF2g==", + "dev": true, + "license": "MIT" + }, + "node_modules/semver": { + "version": "7.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.2.tgz", + "integrity": "sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dev": true, + "license": "MIT", + "dependencies": { + "shebang-regex": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/sisteransi": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.5.tgz", + "integrity": "sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==", + "dev": true, + "license": "MIT" + }, + "node_modules/source-map-js": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", + "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/speakingurl": { + "version": "14.0.1", + "resolved": "https://registry.npmjs.org/speakingurl/-/speakingurl-14.0.1.tgz", + "integrity": "sha512-1POYv7uv2gXoyGFpBCmpDVSNV74IfsWlDW216UPjbWufNf+bSU6GdbDsxdcxtfwb4xlI3yxzOTKClUosxARYrQ==", + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/strip-indent": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-4.1.0.tgz", + "integrity": "sha512-OA95x+JPmL7kc7zCu+e+TeYxEiaIyndRx0OrBcK2QPPH09oAndr2ALvymxWA+Lx1PYYvFUm4O63pRkdJAaW96w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/strip-json-comments": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/strip-literal": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/strip-literal/-/strip-literal-3.1.0.tgz", + "integrity": "sha512-8r3mkIM/2+PpjHoOtiAW8Rg3jJLHaV7xPwG+YRGrv6FP0wwk/toTpATxWYOW0BKdWwl82VT2tFYi5DlROa0Mxg==", + "dev": true, + "license": "MIT", + "dependencies": { + "js-tokens": "^9.0.1" + }, + "funding": { + "url": "https://github.com/sponsors/antfu" + } + }, + "node_modules/superjson": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/superjson/-/superjson-2.2.2.tgz", + "integrity": "sha512-5JRxVqC8I8NuOUjzBbvVJAKNM8qoVuH0O77h4WInc/qC2q5IreqKxYwgkga3PfA22OayK2ikceb/B26dztPl+Q==", + "license": "MIT", + "dependencies": { + "copy-anything": "^3.0.2" + }, + "engines": { + "node": ">=16" + } + }, + "node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "license": "MIT", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/sync-child-process": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/sync-child-process/-/sync-child-process-1.0.2.tgz", + "integrity": "sha512-8lD+t2KrrScJ/7KXCSyfhT3/hRq78rC0wBFqNJXv3mZyn6hW2ypM05JmlSvtqRbeq6jqA94oHbxAr2vYsJ8vDA==", + "devOptional": true, + "license": "MIT", + "dependencies": { + "sync-message-port": "^1.0.0" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/sync-message-port": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/sync-message-port/-/sync-message-port-1.1.3.tgz", + "integrity": "sha512-GTt8rSKje5FilG+wEdfCkOcLL7LWqpMlr2c3LRuKt/YXxcJ52aGSbGBAdI4L3aaqfrBt6y711El53ItyH1NWzg==", + "devOptional": true, + "license": "MIT", + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/synckit": { + "version": "0.11.11", + "resolved": "https://registry.npmjs.org/synckit/-/synckit-0.11.11.tgz", + "integrity": "sha512-MeQTA1r0litLUf0Rp/iisCaL8761lKAZHaimlbGK4j0HysC4PLfqygQj9srcs0m2RdtDYnF8UuYyKpbjHYp7Jw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@pkgr/core": "^0.2.9" + }, + "engines": { + "node": "^14.18.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/synckit" + } + }, + "node_modules/tinyexec": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/tinyexec/-/tinyexec-1.0.1.tgz", + "integrity": "sha512-5uC6DDlmeqiOwCPmK9jMSdOuZTh8bU39Ys6yidB+UTt5hfZUPGAypSgFRiEp+jbi9qH40BLDvy85jIU88wKSqw==", + "dev": true, + "license": "MIT" + }, + "node_modules/tinyglobby": { + "version": "0.2.15", + "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.15.tgz", + "integrity": "sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ==", + "devOptional": true, + "license": "MIT", + "dependencies": { + "fdir": "^6.5.0", + "picomatch": "^4.0.3" + }, + "engines": { + "node": ">=12.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/SuperchupuDev" + } + }, + "node_modules/to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "devOptional": true, + "license": "MIT", + "dependencies": { + "is-number": "^7.0.0" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/ts-api-utils": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-2.1.0.tgz", + "integrity": "sha512-CUgTZL1irw8u29bzrOD/nH85jqyc74D6SshFgujOIA7osm2Rz7dYH77agkx7H4FBNxDq7Cjf+IjaX/8zwFW+ZQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18.12" + }, + "peerDependencies": { + "typescript": ">=4.8.4" + } + }, + "node_modules/tslib": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", + "devOptional": true, + "license": "0BSD" + }, + "node_modules/type-check": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", + "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", + "dev": true, + "license": "MIT", + "dependencies": { + "prelude-ls": "^1.2.1" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/typescript": { + "version": "5.9.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz", + "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==", + "devOptional": true, + "license": "Apache-2.0", + "peer": true, + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=14.17" + } + }, + "node_modules/typescript-eslint": { + "version": "8.45.0", + "resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.45.0.tgz", + "integrity": "sha512-qzDmZw/Z5beNLUrXfd0HIW6MzIaAV5WNDxmMs9/3ojGOpYavofgNAAD/nC6tGV2PczIi0iw8vot2eAe/sBn7zg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/eslint-plugin": "8.45.0", + "@typescript-eslint/parser": "8.45.0", + "@typescript-eslint/typescript-estree": "8.45.0", + "@typescript-eslint/utils": "8.45.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.57.0 || ^9.0.0", + "typescript": ">=4.8.4 <6.0.0" + } + }, + "node_modules/ufo": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/ufo/-/ufo-1.6.1.tgz", + "integrity": "sha512-9a4/uxlTWJ4+a5i0ooc1rU7C7YOw3wT+UGqdeNNHWnOF9qcMBgLRS+4IYUqbczewFx4mLEig6gawh7X6mFlEkA==", + "dev": true, + "license": "MIT" + }, + "node_modules/unimport": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/unimport/-/unimport-4.2.0.tgz", + "integrity": "sha512-mYVtA0nmzrysnYnyb3ALMbByJ+Maosee2+WyE0puXl+Xm2bUwPorPaaeZt0ETfuroPOtG8jj1g/qeFZ6buFnag==", + "dev": true, + "license": "MIT", + "dependencies": { + "acorn": "^8.14.1", + "escape-string-regexp": "^5.0.0", + "estree-walker": "^3.0.3", + "local-pkg": "^1.1.1", + "magic-string": "^0.30.17", + "mlly": "^1.7.4", + "pathe": "^2.0.3", + "picomatch": "^4.0.2", + "pkg-types": "^2.1.0", + "scule": "^1.3.0", + "strip-literal": "^3.0.0", + "tinyglobby": "^0.2.12", + "unplugin": "^2.2.2", + "unplugin-utils": "^0.2.4" + }, + "engines": { + "node": ">=18.12.0" + } + }, + "node_modules/unimport/node_modules/escape-string-regexp": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-5.0.0.tgz", + "integrity": "sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/unimport/node_modules/estree-walker": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-3.0.3.tgz", + "integrity": "sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/estree": "^1.0.0" + } + }, + "node_modules/unplugin": { + "version": "2.3.10", + "resolved": "https://registry.npmjs.org/unplugin/-/unplugin-2.3.10.tgz", + "integrity": "sha512-6NCPkv1ClwH+/BGE9QeoTIl09nuiAt0gS28nn1PvYXsGKRwM2TCbFA2QiilmehPDTXIe684k4rZI1yl3A1PCUw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/remapping": "^2.3.5", + "acorn": "^8.15.0", + "picomatch": "^4.0.3", + "webpack-virtual-modules": "^0.6.2" + }, + "engines": { + "node": ">=18.12.0" + } + }, + "node_modules/unplugin-auto-import": { + "version": "19.3.0", + "resolved": "https://registry.npmjs.org/unplugin-auto-import/-/unplugin-auto-import-19.3.0.tgz", + "integrity": "sha512-iIi0u4Gq2uGkAOGqlPJOAMI8vocvjh1clGTfSK4SOrJKrt+tirrixo/FjgBwXQNNdS7ofcr7OxzmOb/RjWxeEQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "local-pkg": "^1.1.1", + "magic-string": "^0.30.17", + "picomatch": "^4.0.2", + "unimport": "^4.2.0", + "unplugin": "^2.3.4", + "unplugin-utils": "^0.2.4" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/antfu" + }, + "peerDependencies": { + "@nuxt/kit": "^3.2.2", + "@vueuse/core": "*" + }, + "peerDependenciesMeta": { + "@nuxt/kit": { + "optional": true + }, + "@vueuse/core": { + "optional": true + } + } + }, + "node_modules/unplugin-fonts": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/unplugin-fonts/-/unplugin-fonts-1.4.0.tgz", + "integrity": "sha512-TIJqr5rSlK/+3oL5nnrrEJ+Ty2taQ/bTJY1C5abYnksl553Q3HoHVqS4pnRLDkwpZq8AYqywib3kEVvHH+CtRQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "fast-glob": "^3.3.3", + "unplugin": "2.3.5" + }, + "peerDependencies": { + "@nuxt/kit": "^3.0.0 || ^4.0.0", + "vite": "^2.0.0 || ^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0" + }, + "peerDependenciesMeta": { + "@nuxt/kit": { + "optional": true + } + } + }, + "node_modules/unplugin-fonts/node_modules/unplugin": { + "version": "2.3.5", + "resolved": "https://registry.npmjs.org/unplugin/-/unplugin-2.3.5.tgz", + "integrity": "sha512-RyWSb5AHmGtjjNQ6gIlA67sHOsWpsbWpwDokLwTcejVdOjEkJZh7QKu14J00gDDVSh8kGH4KYC/TNBceXFZhtw==", + "dev": true, + "license": "MIT", + "dependencies": { + "acorn": "^8.14.1", + "picomatch": "^4.0.2", + "webpack-virtual-modules": "^0.6.2" + }, + "engines": { + "node": ">=18.12.0" + } + }, + "node_modules/unplugin-utils": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/unplugin-utils/-/unplugin-utils-0.2.5.tgz", + "integrity": "sha512-gwXJnPRewT4rT7sBi/IvxKTjsms7jX7QIDLOClApuZwR49SXbrB1z2NLUZ+vDHyqCj/n58OzRRqaW+B8OZi8vg==", + "dev": true, + "license": "MIT", + "dependencies": { + "pathe": "^2.0.3", + "picomatch": "^4.0.3" + }, + "engines": { + "node": ">=18.12.0" + }, + "funding": { + "url": "https://github.com/sponsors/sxzz" + } + }, + "node_modules/unplugin-vue-components": { + "version": "29.1.0", + "resolved": "https://registry.npmjs.org/unplugin-vue-components/-/unplugin-vue-components-29.1.0.tgz", + "integrity": "sha512-z/9ACPXth199s9aCTCdKZAhe5QGOpvzJYP+Hkd0GN1/PpAmsu+W3UlRY3BJAewPqQxh5xi56+Og6mfiCV1Jzpg==", + "dev": true, + "license": "MIT", + "dependencies": { + "chokidar": "^3.6.0", + "debug": "^4.4.3", + "local-pkg": "^1.1.2", + "magic-string": "^0.30.19", + "mlly": "^1.8.0", + "tinyglobby": "^0.2.15", + "unplugin": "^2.3.10", + "unplugin-utils": "^0.3.0" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/antfu" + }, + "peerDependencies": { + "@babel/parser": "^7.15.8", + "@nuxt/kit": "^3.2.2 || ^4.0.0", + "vue": "2 || 3" + }, + "peerDependenciesMeta": { + "@babel/parser": { + "optional": true + }, + "@nuxt/kit": { + "optional": true + } + } + }, + "node_modules/unplugin-vue-components/node_modules/chokidar": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz", + "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==", + "dev": true, + "license": "MIT", + "dependencies": { + "anymatch": "~3.1.2", + "braces": "~3.0.2", + "glob-parent": "~5.1.2", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.6.0" + }, + "engines": { + "node": ">= 8.10.0" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" + } + }, + "node_modules/unplugin-vue-components/node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "license": "ISC", + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/unplugin-vue-components/node_modules/readdirp": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", + "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", + "dev": true, + "license": "MIT", + "dependencies": { + "picomatch": "^2.2.1" + }, + "engines": { + "node": ">=8.10.0" + } + }, + "node_modules/unplugin-vue-components/node_modules/readdirp/node_modules/picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/unplugin-vue-components/node_modules/unplugin-utils": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/unplugin-utils/-/unplugin-utils-0.3.0.tgz", + "integrity": "sha512-JLoggz+PvLVMJo+jZt97hdIIIZ2yTzGgft9e9q8iMrC4ewufl62ekeW7mixBghonn2gVb/ICjyvlmOCUBnJLQg==", + "dev": true, + "license": "MIT", + "dependencies": { + "pathe": "^2.0.3", + "picomatch": "^4.0.3" + }, + "engines": { + "node": ">=20.19.0" + }, + "funding": { + "url": "https://github.com/sponsors/sxzz" + } + }, + "node_modules/unplugin-vue-router": { + "version": "0.15.0", + "resolved": "https://registry.npmjs.org/unplugin-vue-router/-/unplugin-vue-router-0.15.0.tgz", + "integrity": "sha512-PyGehCjd9Ny9h+Uer4McbBjjib3lHihcyUEILa7pHKl6+rh8N7sFyw4ZkV+N30Oq2zmIUG7iKs3qpL0r+gXAaQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@vue-macros/common": "3.0.0-beta.16", + "@vue/language-core": "^3.0.1", + "ast-walker-scope": "^0.8.1", + "chokidar": "^4.0.3", + "json5": "^2.2.3", + "local-pkg": "^1.1.1", + "magic-string": "^0.30.17", + "mlly": "^1.7.4", + "muggle-string": "^0.4.1", + "pathe": "^2.0.3", + "picomatch": "^4.0.3", + "scule": "^1.3.0", + "tinyglobby": "^0.2.14", + "unplugin": "^2.3.5", + "unplugin-utils": "^0.2.4", + "yaml": "^2.8.0" + }, + "peerDependencies": { + "@vue/compiler-sfc": "^3.5.17", + "vue-router": "^4.5.1" + }, + "peerDependenciesMeta": { + "vue-router": { + "optional": true + } + } + }, + "node_modules/upath": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/upath/-/upath-2.0.1.tgz", + "integrity": "sha512-1uEe95xksV1O0CYKXo8vQvN1JEbtJp7lb7C5U9HMsIp6IVwntkH/oNUzyVNQSd4S1sYk2FpSSW44FqMc8qee5w==", + "devOptional": true, + "license": "MIT", + "engines": { + "node": ">=4", + "yarn": "*" + } + }, + "node_modules/update-browserslist-db": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.3.tgz", + "integrity": "sha512-UxhIZQ+QInVdunkDAaiazvvT/+fXL5Osr0JZlJulepYu6Jd7qJtDZjlur0emRlT71EN3ScPoE7gvsuIKKNavKw==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "escalade": "^3.2.0", + "picocolors": "^1.1.1" + }, + "bin": { + "update-browserslist-db": "cli.js" + }, + "peerDependencies": { + "browserslist": ">= 4.21.0" + } + }, + "node_modules/uri-js": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", + "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "punycode": "^2.1.0" + } + }, + "node_modules/util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", + "dev": true, + "license": "MIT" + }, + "node_modules/varint": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/varint/-/varint-6.0.0.tgz", + "integrity": "sha512-cXEIW6cfr15lFv563k4GuVuW/fiwjknytD37jIOLSdSWuOI6WnO/oKwmP2FQTU2l01LP8/M5TSAJpzUaGe3uWg==", + "devOptional": true, + "license": "MIT" + }, + "node_modules/vite": { + "version": "7.1.9", + "resolved": "https://registry.npmjs.org/vite/-/vite-7.1.9.tgz", + "integrity": "sha512-4nVGliEpxmhCL8DslSAUdxlB6+SMrhB0a1v5ijlh1xB1nEPuy1mxaHxysVucLHuWryAxLWg6a5ei+U4TLn/rFg==", + "devOptional": true, + "license": "MIT", + "dependencies": { + "esbuild": "^0.25.0", + "fdir": "^6.5.0", + "picomatch": "^4.0.3", + "postcss": "^8.5.6", + "rollup": "^4.43.0", + "tinyglobby": "^0.2.15" + }, + "bin": { + "vite": "bin/vite.js" + }, + "engines": { + "node": "^20.19.0 || >=22.12.0" + }, + "funding": { + "url": "https://github.com/vitejs/vite?sponsor=1" + }, + "optionalDependencies": { + "fsevents": "~2.3.3" + }, + "peerDependencies": { + "@types/node": "^20.19.0 || >=22.12.0", + "jiti": ">=1.21.0", + "less": "^4.0.0", + "lightningcss": "^1.21.0", + "sass": "^1.70.0", + "sass-embedded": "^1.70.0", + "stylus": ">=0.54.8", + "sugarss": "^5.0.0", + "terser": "^5.16.0", + "tsx": "^4.8.1", + "yaml": "^2.4.2" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + }, + "jiti": { + "optional": true + }, + "less": { + "optional": true + }, + "lightningcss": { + "optional": true + }, + "sass": { + "optional": true + }, + "sass-embedded": { + "optional": true + }, + "stylus": { + "optional": true + }, + "sugarss": { + "optional": true + }, + "terser": { + "optional": true + }, + "tsx": { + "optional": true + }, + "yaml": { + "optional": true + } + } + }, + "node_modules/vite-plugin-vue-layouts-next": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/vite-plugin-vue-layouts-next/-/vite-plugin-vue-layouts-next-1.0.0.tgz", + "integrity": "sha512-y3oNYcJs5lrv4F/E0EXU7OXi88CH1/b/DOk9nsFAeglxmk4Ps635DTy9R29Nl9Vj7LteBRKaxOkKVSHKOMqo7A==", + "dev": true, + "license": "MIT", + "dependencies": { + "debug": "^4.4.1", + "fast-glob": "^3.3.3" + }, + "peerDependencies": { + "vite": "^5.0.0 || ^6.0.0 || ^7.0.0", + "vue": "^3.2.4", + "vue-router": "^4.0.11" + } + }, + "node_modules/vite-plugin-vuetify": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/vite-plugin-vuetify/-/vite-plugin-vuetify-2.1.2.tgz", + "integrity": "sha512-I/wd6QS+DO6lHmuGoi1UTyvvBTQ2KDzQZ9oowJQEJ6OcjWfJnscYXx2ptm6S7fJSASuZT8jGRBL3LV4oS3LpaA==", + "devOptional": true, + "license": "MIT", + "dependencies": { + "@vuetify/loader-shared": "^2.1.1", + "debug": "^4.3.3", + "upath": "^2.0.1" + }, + "engines": { + "node": "^18.0.0 || >=20.0.0" + }, + "peerDependencies": { + "vite": ">=5", + "vue": "^3.0.0", + "vuetify": "^3.0.0" + } + }, + "node_modules/vue": { + "version": "3.5.22", + "resolved": "https://registry.npmjs.org/vue/-/vue-3.5.22.tgz", + "integrity": "sha512-toaZjQ3a/G/mYaLSbV+QsQhIdMo9x5rrqIpYRObsJ6T/J+RyCSFwN2LHNVH9v8uIcljDNa3QzPVdv3Y6b9hAJQ==", + "license": "MIT", + "dependencies": { + "@vue/compiler-dom": "3.5.22", + "@vue/compiler-sfc": "3.5.22", + "@vue/runtime-dom": "3.5.22", + "@vue/server-renderer": "3.5.22", + "@vue/shared": "3.5.22" + }, + "peerDependencies": { + "typescript": "*" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/vue-eslint-parser": { + "version": "10.2.0", + "resolved": "https://registry.npmjs.org/vue-eslint-parser/-/vue-eslint-parser-10.2.0.tgz", + "integrity": "sha512-CydUvFOQKD928UzZhTp4pr2vWz1L+H99t7Pkln2QSPdvmURT0MoC4wUccfCnuEaihNsu9aYYyk+bep8rlfkUXw==", + "dev": true, + "license": "MIT", + "dependencies": { + "debug": "^4.4.0", + "eslint-scope": "^8.2.0", + "eslint-visitor-keys": "^4.2.0", + "espree": "^10.3.0", + "esquery": "^1.6.0", + "semver": "^7.6.3" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://github.com/sponsors/mysticatea" + }, + "peerDependencies": { + "eslint": "^8.57.0 || ^9.0.0" + } + }, + "node_modules/vue-router": { + "version": "4.5.1", + "resolved": "https://registry.npmjs.org/vue-router/-/vue-router-4.5.1.tgz", + "integrity": "sha512-ogAF3P97NPm8fJsE4by9dwSYtDwXIY1nFY9T6DyQnGHd1E2Da94w9JIolpe42LJGIl0DwOHBi8TcRPlPGwbTtw==", + "license": "MIT", + "dependencies": { + "@vue/devtools-api": "^6.6.4" + }, + "funding": { + "url": "https://github.com/sponsors/posva" + }, + "peerDependencies": { + "vue": "^3.2.0" + } + }, + "node_modules/vue-router/node_modules/@vue/devtools-api": { + "version": "6.6.4", + "resolved": "https://registry.npmjs.org/@vue/devtools-api/-/devtools-api-6.6.4.tgz", + "integrity": "sha512-sGhTPMuXqZ1rVOk32RylztWkfXTRhuS7vgAKv0zjqk8gbsHkJ7xfFf+jbySxt7tWObEJwyKaHMikV/WGDiQm8g==", + "license": "MIT" + }, + "node_modules/vuetify": { + "version": "3.10.4", + "resolved": "https://registry.npmjs.org/vuetify/-/vuetify-3.10.4.tgz", + "integrity": "sha512-aatUQ0RM0i6VdkJaFyj3gydecuFmAgACNO3RwWznvjvIvRENQXxMRiv+vlGFoshbw2UG+zOPPMhO12OCPSa2UQ==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/johnleider" + }, + "peerDependencies": { + "typescript": ">=4.7", + "vite-plugin-vuetify": ">=2.1.0", + "vue": "^3.5.0", + "webpack-plugin-vuetify": ">=3.1.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + }, + "vite-plugin-vuetify": { + "optional": true + }, + "webpack-plugin-vuetify": { + "optional": true + } + } + }, + "node_modules/webpack-virtual-modules": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/webpack-virtual-modules/-/webpack-virtual-modules-0.6.2.tgz", + "integrity": "sha512-66/V2i5hQanC51vBQKPH4aI8NMAcBW59FVBs+rC7eGHupMyfn34q7rZIE+ETlJ+XTevqfUhVVBgSUNSW2flEUQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, + "license": "ISC", + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/word-wrap": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz", + "integrity": "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/xml-name-validator": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/xml-name-validator/-/xml-name-validator-4.0.0.tgz", + "integrity": "sha512-ICP2e+jsHvAj2E2lIHxa5tjXRlKDJo4IdvPvCXbXQGdzSfmSpNVyIKMvoZHjDY9DP0zV17iI85o90vRFXNccRw==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=12" + } + }, + "node_modules/yaml": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.8.1.tgz", + "integrity": "sha512-lcYcMxX2PO9XMGvAJkJ3OsNMw+/7FKes7/hgerGUYWIoWu5j/+YQqcZr5JnPZWzOsEBgMbSbiSTn/dv/69Mkpw==", + "devOptional": true, + "license": "ISC", + "bin": { + "yaml": "bin.mjs" + }, + "engines": { + "node": ">= 14.6" + } + }, + "node_modules/yaml-eslint-parser": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/yaml-eslint-parser/-/yaml-eslint-parser-1.3.0.tgz", + "integrity": "sha512-E/+VitOorXSLiAqtTd7Yqax0/pAS3xaYMP+AUUJGOK1OZG3rhcj9fcJOM5HJ2VrP1FrStVCWr1muTfQCdj4tAA==", + "dev": true, + "license": "MIT", + "dependencies": { + "eslint-visitor-keys": "^3.0.0", + "yaml": "^2.0.0" + }, + "engines": { + "node": "^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/ota-meshi" + } + }, + "node_modules/yaml-eslint-parser/node_modules/eslint-visitor-keys": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", + "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/yocto-queue": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", + "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + } + } +} diff --git a/frontend-prototype/package.json b/frontend-prototype/package.json new file mode 100644 index 0000000000..c688783291 --- /dev/null +++ b/frontend-prototype/package.json @@ -0,0 +1,34 @@ +{ + "name": "frontend-prototype", + "private": true, + "type": "module", + "version": "0.0.0", + "scripts": { + "dev": "vite --host 0.0.0.0", + "build": "vite build", + "preview": "vite preview --host 0.0.0.0 --port 3333", + "lint": "eslint . --fix" + }, + "dependencies": { + "@fontsource/roboto": "5.2.7", + "@mdi/font": "7.4.47", + "inter-ui": "3.19.3", + "pinia": "^3.0.3", + "vue": "^3.5.21", + "vue-router": "^4.5.1", + "vuetify": "^3.10.1" + }, + "devDependencies": { + "@vitejs/plugin-vue": "^6.0.1", + "eslint": "^9.35.0", + "eslint-config-vuetify": "^4.2.0", + "sass-embedded": "^1.92.1", + "unplugin-auto-import": "^19.3.0", + "unplugin-fonts": "^1.4.0", + "unplugin-vue-components": "^29.0.0", + "unplugin-vue-router": "^0.15.0", + "vite": "^7.1.5", + "vite-plugin-vue-layouts-next": "^1.0.0", + "vite-plugin-vuetify": "^2.1.2" + } +} diff --git a/frontend-prototype/public/favicon.ico b/frontend-prototype/public/favicon.ico new file mode 100644 index 0000000000..8fb9f91b3a Binary files /dev/null and b/frontend-prototype/public/favicon.ico differ diff --git a/frontend-prototype/src/App.vue b/frontend-prototype/src/App.vue new file mode 100644 index 0000000000..64618cdf22 --- /dev/null +++ b/frontend-prototype/src/App.vue @@ -0,0 +1,9 @@ + + + diff --git a/frontend-prototype/src/assets/logo.png b/frontend-prototype/src/assets/logo.png new file mode 100644 index 0000000000..a5f23ae7bf Binary files /dev/null and b/frontend-prototype/src/assets/logo.png differ diff --git a/frontend-prototype/src/assets/logo.svg b/frontend-prototype/src/assets/logo.svg new file mode 100644 index 0000000000..d57771c6df --- /dev/null +++ b/frontend-prototype/src/assets/logo.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/frontend-prototype/src/components/AppBarItem.vue b/frontend-prototype/src/components/AppBarItem.vue new file mode 100644 index 0000000000..86bdf2fe21 --- /dev/null +++ b/frontend-prototype/src/components/AppBarItem.vue @@ -0,0 +1,23 @@ + + + + + diff --git a/frontend-prototype/src/components/AppFooter.vue b/frontend-prototype/src/components/AppFooter.vue new file mode 100644 index 0000000000..7444827109 --- /dev/null +++ b/frontend-prototype/src/components/AppFooter.vue @@ -0,0 +1,82 @@ + + + + + diff --git a/frontend-prototype/src/components/HelloWorld.vue b/frontend-prototype/src/components/HelloWorld.vue new file mode 100644 index 0000000000..730485c042 --- /dev/null +++ b/frontend-prototype/src/components/HelloWorld.vue @@ -0,0 +1,90 @@ + + + diff --git a/frontend-prototype/src/components/Logo.vue b/frontend-prototype/src/components/Logo.vue new file mode 100644 index 0000000000..80245ef86b --- /dev/null +++ b/frontend-prototype/src/components/Logo.vue @@ -0,0 +1,31 @@ + + + + + diff --git a/frontend-prototype/src/components/README.md b/frontend-prototype/src/components/README.md new file mode 100644 index 0000000000..d1dc92f5e1 --- /dev/null +++ b/frontend-prototype/src/components/README.md @@ -0,0 +1,35 @@ +# Components + +Vue template files in this folder are automatically imported. + +## 🚀 Usage + +Importing is handled by [unplugin-vue-components](https://github.com/unplugin/unplugin-vue-components). This plugin automatically imports `.vue` files created in the `src/components` directory, and registers them as global components. This means that you can use any component in your application without having to manually import it. + +The following example assumes a component located at `src/components/MyComponent.vue`: + +```vue + + + +``` + +When your template is rendered, the component's import will automatically be inlined, which renders to this: + +```vue + + + +``` diff --git a/frontend-prototype/src/components/UserMeta.vue b/frontend-prototype/src/components/UserMeta.vue new file mode 100644 index 0000000000..e32e5117be --- /dev/null +++ b/frontend-prototype/src/components/UserMeta.vue @@ -0,0 +1,222 @@ + + + + + diff --git a/frontend-prototype/src/layouts/README.md b/frontend-prototype/src/layouts/README.md new file mode 100644 index 0000000000..78f68b6028 --- /dev/null +++ b/frontend-prototype/src/layouts/README.md @@ -0,0 +1,5 @@ +# Layouts + +Layouts are reusable components that wrap around pages. They are used to provide a consistent look and feel across multiple pages. + +Full documentation for this feature can be found in the Official [vite-plugin-vue-layouts-next](https://github.com/loicduong/vite-plugin-vue-layouts-next) repository. diff --git a/frontend-prototype/src/layouts/default.vue b/frontend-prototype/src/layouts/default.vue new file mode 100644 index 0000000000..3037ff7fe0 --- /dev/null +++ b/frontend-prototype/src/layouts/default.vue @@ -0,0 +1,11 @@ + + + diff --git a/frontend-prototype/src/main.js b/frontend-prototype/src/main.js new file mode 100644 index 0000000000..98cac25f29 --- /dev/null +++ b/frontend-prototype/src/main.js @@ -0,0 +1,23 @@ +/** + * main.js + * + * Bootstraps Vuetify and other plugins then mounts the App` + */ + +// Plugins +import { registerPlugins } from '@/plugins' + +// Components +import App from './App.vue' + +// Composables +import { createApp } from 'vue' + +// Styles +import '@/styles/global.scss' + +const app = createApp(App) + +registerPlugins(app) + +app.mount('#app') diff --git a/frontend-prototype/src/pages/README.md b/frontend-prototype/src/pages/README.md new file mode 100644 index 0000000000..341536c2ff --- /dev/null +++ b/frontend-prototype/src/pages/README.md @@ -0,0 +1,5 @@ +# Pages + +Vue components created in this folder will automatically be converted to navigatable routes. + +Full documentation for this feature can be found in the Official [unplugin-vue-router](https://github.com/posva/unplugin-vue-router) repository. diff --git a/frontend-prototype/src/pages/index.vue b/frontend-prototype/src/pages/index.vue new file mode 100644 index 0000000000..993f2e0d37 --- /dev/null +++ b/frontend-prototype/src/pages/index.vue @@ -0,0 +1,45 @@ + + + + + diff --git a/frontend-prototype/src/plugins/README.md b/frontend-prototype/src/plugins/README.md new file mode 100644 index 0000000000..62201c7cfc --- /dev/null +++ b/frontend-prototype/src/plugins/README.md @@ -0,0 +1,3 @@ +# Plugins + +Plugins are a way to extend the functionality of your Vue application. Use this folder for registering plugins that you want to use globally. diff --git a/frontend-prototype/src/plugins/index.js b/frontend-prototype/src/plugins/index.js new file mode 100644 index 0000000000..be6e2daa3d --- /dev/null +++ b/frontend-prototype/src/plugins/index.js @@ -0,0 +1,17 @@ +/** + * plugins/index.js + * + * Automatically included in `./src/main.js` + */ + +// Plugins +import vuetify from './vuetify' +import pinia from '@/stores' +import router from '@/router' + +export function registerPlugins (app) { + app + .use(vuetify) + .use(router) + .use(pinia) +} diff --git a/frontend-prototype/src/plugins/vuetify.js b/frontend-prototype/src/plugins/vuetify.js new file mode 100644 index 0000000000..30a4980832 --- /dev/null +++ b/frontend-prototype/src/plugins/vuetify.js @@ -0,0 +1,19 @@ +/** + * plugins/vuetify.js + * + * Framework documentation: https://vuetifyjs.com` + */ + +// Styles +import '@mdi/font/css/materialdesignicons.css' +import 'vuetify/styles' + +// Composables +import { createVuetify } from 'vuetify' + +// https://vuetifyjs.com/en/introduction/why-vuetify/#feature-guides +export default createVuetify({ + theme: { + defaultTheme: 'system', + }, +}) diff --git a/frontend-prototype/src/router/index.js b/frontend-prototype/src/router/index.js new file mode 100644 index 0000000000..a6f6a863fe --- /dev/null +++ b/frontend-prototype/src/router/index.js @@ -0,0 +1,37 @@ +/** + * router/index.ts + * + * Automatic routes for `./src/pages/*.vue` + */ + +// Composables +import { createRouter, createWebHistory } from 'vue-router' +import { setupLayouts } from 'virtual:generated-layouts' +import { routes } from 'vue-router/auto-routes' + +const router = createRouter({ + history: createWebHistory(import.meta.env.BASE_URL), + routes: setupLayouts(routes), + base: '/prototype', +}) + +// Workaround for https://github.com/vitejs/vite/issues/11804 +router.onError((err, to) => { + if (err?.message?.includes?.('Failed to fetch dynamically imported module')) { + if (localStorage.getItem('vuetify:dynamic-reload')) { + console.error('Dynamic import error, reloading page did not fix it', err) + } else { + console.log('Reloading page to fix dynamic import error') + localStorage.setItem('vuetify:dynamic-reload', 'true') + location.assign(to.fullPath) + } + } else { + console.error(err) + } +}) + +router.isReady().then(() => { + localStorage.removeItem('vuetify:dynamic-reload') +}) + +export default router diff --git a/frontend-prototype/src/stores/README.md b/frontend-prototype/src/stores/README.md new file mode 100644 index 0000000000..54f8e03b69 --- /dev/null +++ b/frontend-prototype/src/stores/README.md @@ -0,0 +1,5 @@ +# Store + +Pinia stores are used to store reactive state and expose actions to mutate it. + +Full documentation for this feature can be found in the Official [Pinia](https://pinia.esm.dev/) repository. diff --git a/frontend-prototype/src/stores/app.js b/frontend-prototype/src/stores/app.js new file mode 100644 index 0000000000..74295436ec --- /dev/null +++ b/frontend-prototype/src/stores/app.js @@ -0,0 +1,8 @@ +// Utilities +import { defineStore } from 'pinia' + +export const useAppStore = defineStore('app', { + state: () => ({ + // + }), +}) diff --git a/frontend-prototype/src/stores/index.js b/frontend-prototype/src/stores/index.js new file mode 100644 index 0000000000..153625250d --- /dev/null +++ b/frontend-prototype/src/stores/index.js @@ -0,0 +1,4 @@ +// Utilities +import { createPinia } from 'pinia' + +export default createPinia() diff --git a/frontend-prototype/src/styles/README.md b/frontend-prototype/src/styles/README.md new file mode 100644 index 0000000000..ea861794d6 --- /dev/null +++ b/frontend-prototype/src/styles/README.md @@ -0,0 +1,3 @@ +# Styles + +This directory is for configuring the styles of the application. diff --git a/frontend-prototype/src/styles/global.scss b/frontend-prototype/src/styles/global.scss new file mode 100644 index 0000000000..6e333f6a3a --- /dev/null +++ b/frontend-prototype/src/styles/global.scss @@ -0,0 +1,11 @@ +@use 'inter-ui/default' as inter-ui with ( + $inter-font-path: 'inter-ui/Inter (web hinted latin)' +); +@include inter-ui.weight-200; +@include inter-ui.weight-400; +@include inter-ui.weight-500; +@include inter-ui.weight-600; + +body { + font-feature-settings: 'ss03', 'calt', 'rlig', 'kern', 'cv05', 'cv07', 'cv08'; +} \ No newline at end of file diff --git a/frontend-prototype/src/styles/settings.scss b/frontend-prototype/src/styles/settings.scss new file mode 100644 index 0000000000..324e2252aa --- /dev/null +++ b/frontend-prototype/src/styles/settings.scss @@ -0,0 +1,29 @@ +/** + * src/styles/settings.scss + * + * Configures SASS variables and Vuetify overwrites + */ + +// https://vuetifyjs.com/features/sass-variables/` +// @use 'vuetify/settings' with ( +// $color-pack: false +// ); + +@use 'vuetify/settings' with ( + $heading-font-family: ('Inter', sans-serif, emoji), + $body-font-family: ('Inter', sans-serif, emoji), + $font-weights: ( + 'light': 200, + 'regular': 400, + 'bold': 600, + ), + + $button-text-letter-spacing: 0.25px, + $button-text-transform: none, + $bottom-navigation-min-width: 60px, + $list-item-icon-margin-end: 20px, + $menu-content-border-radius: 0 0 4px 4px, + $card-actions-padding: 16px, + $expansion-panel-title-padding: 16px, + $expansion-panel-text-padding: 0 16px 16px, +); \ No newline at end of file diff --git a/frontend-prototype/typed-router.d.ts b/frontend-prototype/typed-router.d.ts new file mode 100644 index 0000000000..7e0b732a46 --- /dev/null +++ b/frontend-prototype/typed-router.d.ts @@ -0,0 +1,51 @@ +/* eslint-disable */ +/* prettier-ignore */ +// @ts-nocheck +// Generated by unplugin-vue-router. ‼️ DO NOT MODIFY THIS FILE ‼️ +// It's recommended to commit this file. +// Make sure to add this file to your tsconfig.json file as an "includes" or "files" entry. + +declare module 'vue-router/auto-routes' { + import type { + RouteRecordInfo, + ParamValue, + ParamValueOneOrMore, + ParamValueZeroOrMore, + ParamValueZeroOrOne, + } from 'vue-router' + + /** + * Route name map generated by unplugin-vue-router + */ + export interface RouteNamedMap { + '/': RouteRecordInfo<'/', '/', Record, Record>, + } + + /** + * Route file to route info map by unplugin-vue-router. + * Used by the volar plugin to automatically type useRoute() + * + * Each key is a file path relative to the project root with 2 properties: + * - routes: union of route names of the possible routes when in this page (passed to useRoute<...>()) + * - views: names of nested views (can be passed to ) + * + * @internal + */ + export interface _RouteFileInfoMap { + 'src/pages/index.vue': { + routes: '/' + views: never + } + } + + /** + * Get a union of possible route names in a certain route component file. + * Used by the volar plugin to automatically type useRoute() + * + * @internal + */ + export type _RouteNamesForFilePath = + _RouteFileInfoMap extends Record + ? Info['routes'] + : keyof RouteNamedMap +} diff --git a/frontend-prototype/vite.config.mjs b/frontend-prototype/vite.config.mjs new file mode 100644 index 0000000000..cdc4d5cff4 --- /dev/null +++ b/frontend-prototype/vite.config.mjs @@ -0,0 +1,73 @@ +// Plugins +import AutoImport from 'unplugin-auto-import/vite' +import Components from 'unplugin-vue-components/vite' +import Layouts from 'vite-plugin-vue-layouts-next' +import Vue from '@vitejs/plugin-vue' +import VueRouter from 'unplugin-vue-router/vite' +import { VueRouterAutoImports } from 'unplugin-vue-router' +import Vuetify, { transformAssetUrls } from 'vite-plugin-vuetify' + +// Utilities +import { defineConfig } from 'vite' +import { fileURLToPath, URL } from 'node:url' + +// https://vitejs.dev/config/ +export default defineConfig({ + base: '/prototype', + plugins: [ + VueRouter(), + Layouts(), + Vue({ + template: { transformAssetUrls }, + }), + // https://github.com/vuetifyjs/vuetify-loader/tree/master/packages/vite-plugin#readme + Vuetify({ + autoImport: true, + styles: { + configFile: 'src/styles/settings.scss', + }, + }), + Components(), + AutoImport({ + imports: [ + 'vue', + VueRouterAutoImports, + { + pinia: ['defineStore', 'storeToRefs'], + }, + ], + eslintrc: { + enabled: true, + }, + vueTemplate: true, + }), + ], + optimizeDeps: { + exclude: [ + 'vuetify', + 'vue-router', + 'unplugin-vue-router/runtime', + 'unplugin-vue-router/data-loaders', + 'unplugin-vue-router/data-loaders/basic', + ], + }, + define: { 'process.env': {} }, + resolve: { + alias: { + '@': fileURLToPath(new URL('src', import.meta.url)), + }, + extensions: [ + '.js', + '.json', + '.jsx', + '.mjs', + '.ts', + '.tsx', + '.vue', + ], + }, + server: { + port: 3333, + allowedHosts: ['frontend-prototype', 'localhost:3000'], + }, +}) diff --git a/frontend-vue3/.editorconfig b/frontend-vue3/.editorconfig new file mode 100644 index 0000000000..7053c49a04 --- /dev/null +++ b/frontend-vue3/.editorconfig @@ -0,0 +1,5 @@ +[*.{js,jsx,ts,tsx,vue}] +indent_style = space +indent_size = 2 +trim_trailing_whitespace = true +insert_final_newline = true diff --git a/frontend-vue3/.gitignore b/frontend-vue3/.gitignore new file mode 100644 index 0000000000..fae6461ae2 --- /dev/null +++ b/frontend-vue3/.gitignore @@ -0,0 +1,35 @@ +.DS_Store +node_modules +/components.d.ts +/data +/dist + +selenium-debug.log + +# local env files +.env.local +.env.*.local + +# Auto-generated files +public/twemoji/ + +# Log files +npm-debug.log* +yarn-debug.log* +yarn-error.log* + +# Editor directories and files +.idea +.vscode +*.suo +*.ntvs* +*.njsproj +*.sln +*.sw* + +# yalc +.yalc +yalc.lock + +# Sentry Auth Token +.env.sentry-build-plugin diff --git a/frontend-vue3/.prettierignore b/frontend-vue3/.prettierignore new file mode 100644 index 0000000000..de2f837688 --- /dev/null +++ b/frontend-vue3/.prettierignore @@ -0,0 +1,6 @@ +src/common/locales/ +src/locales/ +/data +/dist +.vscode +/public/twemoji diff --git a/frontend-vue3/README.md b/frontend-vue3/README.md new file mode 100644 index 0000000000..79caff12af --- /dev/null +++ b/frontend-vue3/README.md @@ -0,0 +1,31 @@ +# frontend + +## Project setup + +``` +npm install +``` + +### Compiles and hot-reloads for development + +``` +npm run serve +``` + +### Compiles and minifies for production + +``` +npm run build +``` + +### Lints and fixes files + +``` +npm run lint +``` + +### Run your unit tests + +``` +npm run test:unit +``` diff --git a/frontend-vue3/babel.config.js b/frontend-vue3/babel.config.js new file mode 100644 index 0000000000..2b8a72a2f4 --- /dev/null +++ b/frontend-vue3/babel.config.js @@ -0,0 +1,7 @@ +// noinspection JSUnusedGlobalSymbols +export const presets = ['@vue/app'] +export const env = { + test: { + plugins: ['require-context-hook'], + }, +} diff --git a/frontend-vue3/docker-setup.sh b/frontend-vue3/docker-setup.sh new file mode 100755 index 0000000000..91dd9c4dd9 --- /dev/null +++ b/frontend-vue3/docker-setup.sh @@ -0,0 +1,20 @@ +#!/bin/bash +set -euo pipefail + +BASEDIR=$(dirname "$0") +PDF_DIST=$BASEDIR"/src/pdf" + +if [ ! -f "$PDF_DIST/pdf.js" ] || [ ! -f "$PDF_DIST/prepareInMainThread.js" ]; then + # Copy dummy versions of the pdf build outputs, to make sure there is always something to import + cp "$PDF_DIST/pdf.js.dist" "$PDF_DIST/pdf.js" + cp "$PDF_DIST/prepareInMainThread.js.dist" "$PDF_DIST/prepareInMainThread.js" +fi + +if [ "$CI" = 'true' ] ; then + npm ci --verbose + npm run build + npm run preview +else + npm install + npm run dev +fi diff --git a/frontend-vue3/eslint-local-rules/index.js b/frontend-vue3/eslint-local-rules/index.js new file mode 100644 index 0000000000..0431dd1383 --- /dev/null +++ b/frontend-vue3/eslint-local-rules/index.js @@ -0,0 +1,6 @@ +import utils from 'eslint-plugin-vue/lib/utils/index.js' +// noinspection ES6UnusedImports +import createMatchingTranslationKeys from '../../common/eslint-local-rules/matchingTranslationKeys.js' + +// noinspection JSUnusedGlobalSymbols +export const matchingTranslationKeys = createMatchingTranslationKeys(utils) diff --git a/frontend-vue3/eslint.config.mjs b/frontend-vue3/eslint.config.mjs new file mode 100644 index 0000000000..4680e1ae15 --- /dev/null +++ b/frontend-vue3/eslint.config.mjs @@ -0,0 +1,98 @@ +import vueEslintConfigPrettier from '@vue/eslint-config-prettier' + +import { includeIgnoreFile } from '@eslint/compat' +import localRules from 'eslint-plugin-local-rules' +import globals from 'globals' +import path from 'node:path' +import { fileURLToPath } from 'node:url' +import js from '@eslint/js' +import { FlatCompat } from '@eslint/eslintrc' + +const __filename = fileURLToPath(import.meta.url) +const __dirname = path.dirname(__filename) +const compat = new FlatCompat({ + baseDirectory: __dirname, + recommendedConfig: js.configs.recommended, + allConfig: js.configs.all, +}) +const gitignorePath = path.resolve(__dirname, '.gitignore') +export default [ + ...compat.extends( + 'plugin:vue/vue3-recommended', + 'plugin:vue-scoped-css/vue3-recommended', + 'eslint:recommended' + ), + { + ignores: ['data/', 'dist/', 'public/twemoji/'], + }, + + includeIgnoreFile(gitignorePath), + + vueEslintConfigPrettier, + + { + plugins: { + 'local-rules': localRules, + }, + + languageOptions: { + globals: { + ...globals.node, + }, + + parserOptions: { + ecmaVersion: '6', + parser: '@babel/eslint-parser', + }, + }, + + rules: { + 'prefer-const': 'error', + 'prettier/prettier': 'error', + + 'vue/component-tags-order': [ + 'error', + { + order: ['template', 'script', 'style'], + }, + ], + + 'vue/multi-word-component-names': 'off', + 'vue/no-deprecated-destroyed-lifecycle': 'off', + 'vue/no-deprecated-dollar-listeners-api': 'off', + 'vue/no-deprecated-dollar-scopedslots-api': 'off', + 'vue/no-deprecated-filter': 'warn', + 'vue/no-deprecated-props-default-this': 'off', + 'vue/no-deprecated-slot-attribute': 'off', + 'vue/no-deprecated-slot-scope-attribute': 'off', + 'vue/no-deprecated-v-bind-sync': 'off', + 'vue/no-deprecated-v-on-native-modifier': 'warn', + 'vue/no-v-for-template-key-on-child': 'off', + 'vue/no-v-model-argument': 'warn', + 'vue/require-explicit-emits': 'off', + + 'no-unused-vars': [ + 'error', + { + argsIgnorePattern: '^_$', + }, + ], + + 'local-rules/matchingTranslationKeys': [ + 'error', + { + ignoreKeysRegex: + '^(global|entity|contentNode\\.[a-z][a-zA-Z]+|print\\.(global|activity|cover|picasso|program|config|summary|toc|activityList))\\..+', + translationKeyPropRegex: '[a-zA-Z0-9]-i18n-key$', + }, + ], + + 'vue/no-mutating-props': [ + 'error', + { + shallowOnly: true, + }, + ], + }, + }, +] diff --git a/frontend-vue3/frontend/src/plugins/icons/BigScreen.vue b/frontend-vue3/frontend/src/plugins/icons/BigScreen.vue new file mode 100644 index 0000000000..38b6fcb69d --- /dev/null +++ b/frontend-vue3/frontend/src/plugins/icons/BigScreen.vue @@ -0,0 +1,8 @@ + + + diff --git a/frontend-vue3/frontend/src/plugins/icons/CeviLogo.vue b/frontend-vue3/frontend/src/plugins/icons/CeviLogo.vue new file mode 100644 index 0000000000..891d7aa053 --- /dev/null +++ b/frontend-vue3/frontend/src/plugins/icons/CeviLogo.vue @@ -0,0 +1,8 @@ + + + diff --git a/frontend-vue3/frontend/src/plugins/icons/ColumnLayout.vue b/frontend-vue3/frontend/src/plugins/icons/ColumnLayout.vue new file mode 100644 index 0000000000..13e4da4f70 --- /dev/null +++ b/frontend-vue3/frontend/src/plugins/icons/ColumnLayout.vue @@ -0,0 +1,8 @@ + + + diff --git a/frontend-vue3/frontend/src/plugins/icons/GSLogo.vue b/frontend-vue3/frontend/src/plugins/icons/GSLogo.vue new file mode 100644 index 0000000000..600d2a07f2 --- /dev/null +++ b/frontend-vue3/frontend/src/plugins/icons/GSLogo.vue @@ -0,0 +1,8 @@ + + + diff --git a/frontend-vue3/frontend/src/plugins/icons/GoogleLogo.vue b/frontend-vue3/frontend/src/plugins/icons/GoogleLogo.vue new file mode 100644 index 0000000000..f45efe6854 --- /dev/null +++ b/frontend-vue3/frontend/src/plugins/icons/GoogleLogo.vue @@ -0,0 +1,8 @@ + + + diff --git a/frontend-vue3/frontend/src/plugins/icons/JSLogo.vue b/frontend-vue3/frontend/src/plugins/icons/JSLogo.vue new file mode 100644 index 0000000000..661002f8af --- /dev/null +++ b/frontend-vue3/frontend/src/plugins/icons/JSLogo.vue @@ -0,0 +1,8 @@ + + + diff --git a/frontend-vue3/frontend/src/plugins/icons/JublaLogo.vue b/frontend-vue3/frontend/src/plugins/icons/JublaLogo.vue new file mode 100644 index 0000000000..834c5a61f8 --- /dev/null +++ b/frontend-vue3/frontend/src/plugins/icons/JublaLogo.vue @@ -0,0 +1,8 @@ + + + diff --git a/frontend-vue3/frontend/src/plugins/icons/PaperSize.vue b/frontend-vue3/frontend/src/plugins/icons/PaperSize.vue new file mode 100644 index 0000000000..fd2f1a0506 --- /dev/null +++ b/frontend-vue3/frontend/src/plugins/icons/PaperSize.vue @@ -0,0 +1,8 @@ + + + diff --git a/frontend-vue3/frontend/src/plugins/icons/PbsLogo.vue b/frontend-vue3/frontend/src/plugins/icons/PbsLogo.vue new file mode 100644 index 0000000000..ba808c396b --- /dev/null +++ b/frontend-vue3/frontend/src/plugins/icons/PbsLogo.vue @@ -0,0 +1,8 @@ + + + diff --git a/frontend-vue3/frontend/src/plugins/icons/ResponsiveLayout.vue b/frontend-vue3/frontend/src/plugins/icons/ResponsiveLayout.vue new file mode 100644 index 0000000000..fabf6ea911 --- /dev/null +++ b/frontend-vue3/frontend/src/plugins/icons/ResponsiveLayout.vue @@ -0,0 +1,8 @@ + + + diff --git a/frontend-vue3/frontend/src/plugins/icons/TentDay.vue b/frontend-vue3/frontend/src/plugins/icons/TentDay.vue new file mode 100644 index 0000000000..b673b46eab --- /dev/null +++ b/frontend-vue3/frontend/src/plugins/icons/TentDay.vue @@ -0,0 +1,8 @@ + + + diff --git a/frontend-vue3/frontend/src/plugins/icons/eCampLogo.vue b/frontend-vue3/frontend/src/plugins/icons/eCampLogo.vue new file mode 100644 index 0000000000..25d89d06f9 --- /dev/null +++ b/frontend-vue3/frontend/src/plugins/icons/eCampLogo.vue @@ -0,0 +1,8 @@ + + + diff --git a/frontend-vue3/index.html b/frontend-vue3/index.html new file mode 100644 index 0000000000..34044dc6c4 --- /dev/null +++ b/frontend-vue3/index.html @@ -0,0 +1,61 @@ + + + + + + + + + + + + + + + + + + eCamp v3 + + + + + +
+ + + + + diff --git a/frontend-vue3/jsconfig.json b/frontend-vue3/jsconfig.json new file mode 100644 index 0000000000..abe04df578 --- /dev/null +++ b/frontend-vue3/jsconfig.json @@ -0,0 +1,8 @@ +{ + "compilerOptions": { + "baseUrl": ".", + "paths": { + "@/*": ["./src/*"] + } + } +} diff --git a/frontend-vue3/package-lock.json b/frontend-vue3/package-lock.json new file mode 100644 index 0000000000..a635cf76d9 --- /dev/null +++ b/frontend-vue3/package-lock.json @@ -0,0 +1,12100 @@ +{ + "name": "@ecamp3/frontend", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "@ecamp3/frontend", + "hasInstallScript": true, + "dependencies": { + "@intlify/core": "11.1.11", + "@mdi/font": "7.4.47", + "@react-pdf/font": "4.0.2", + "@react-pdf/layout": "4.4.0", + "@react-pdf/pdfkit": "4.0.3", + "@react-pdf/primitives": "4.1.1", + "@react-pdf/render": "4.3.0", + "@sentry/browser": "9.44.0", + "@sentry/vue": "9.44.0", + "@tiptap/extension-bold": "3.0.9", + "@tiptap/extension-bubble-menu": "3.0.9", + "@tiptap/extension-bullet-list": "3.0.9", + "@tiptap/extension-document": "3.0.9", + "@tiptap/extension-hard-break": "3.0.9", + "@tiptap/extension-heading": "3.0.9", + "@tiptap/extension-history": "3.0.9", + "@tiptap/extension-italic": "3.0.9", + "@tiptap/extension-list-item": "3.0.9", + "@tiptap/extension-ordered-list": "3.0.9", + "@tiptap/extension-paragraph": "3.0.9", + "@tiptap/extension-placeholder": "3.0.9", + "@tiptap/extension-strike": "3.0.9", + "@tiptap/extension-text": "3.0.9", + "@tiptap/extension-underline": "3.0.9", + "@tiptap/vue-3": "3.0.9", + "@unhead/vue": "2.0.14", + "@vee-validate/i18n": "4.15.1", + "@vee-validate/rules": "4.15.1", + "@vue/compat": "3.5.21", + "@zxcvbn-ts/core": "3.0.4", + "@zxcvbn-ts/language-common": "3.0.4", + "@zxcvbn-ts/language-de": "3.0.2", + "@zxcvbn-ts/language-en": "3.0.2", + "@zxcvbn-ts/language-fr": "3.0.2", + "@zxcvbn-ts/language-it": "3.0.2", + "assert": "2.1.0", + "axios": "1.11.0", + "colorjs.io": "0.5.2", + "comlink": "4.4.2", + "dayjs": "1.11.13", + "deepmerge": "4.3.1", + "emoji-regex": "10.4.0", + "file-saver": "2.0.5", + "hal-json-vuex": "3.0.0-alpha.10", + "inter-ui": "3.19.3", + "js-cookie": "3.0.5", + "linkify-it": "5.0.0", + "lodash-es": "4.17.21", + "runes": "0.4.3", + "slugify": "1.6.6", + "url-template": "3.1.1", + "util": "0.12.5", + "v-resize-observer": "2.1.0", + "vee-validate": "4.15.1", + "vue": "3.5.21", + "vue-axios": "3.5.2", + "vue-i18n": "11.1.11", + "vue-recaptcha-v3": "2.0.1", + "vue-router": "4.5.1", + "vue-toastification": "2.0.0-rc.5", + "vuedraggable": "2.24.3", + "vuetify": "3.10.4", + "vuex": "4.0.2", + "xlsx": "https://cdn.sheetjs.com/xlsx-0.20.2/xlsx-0.20.2.tgz" + }, + "devDependencies": { + "@babel/eslint-parser": "7.28.0", + "@eslint/compat": "1.3.1", + "@eslint/eslintrc": "3.3.1", + "@eslint/js": "9.32.0", + "@sentry/vite-plugin": "4.0.2", + "@testing-library/jest-dom": "6.6.4", + "@testing-library/user-event": "14.6.1", + "@testing-library/vue": "8.1.0", + "@vitejs/plugin-vue": "6.0.1", + "@vitest/coverage-v8": "3.2.4", + "@vue/babel-preset-app": "5.0.9", + "@vue/compiler-dom": "3.5.21", + "@vue/compiler-sfc": "3.5.21", + "@vue/eslint-config-prettier": "10.2.0", + "@vue/runtime-dom": "3.5.21", + "@vue/server-renderer": "3.5.21", + "@vue/shared": "3.5.21", + "@vue/test-utils": "2.4.6", + "autoprefixer": "10.4.21", + "babel-plugin-require-context-hook": "1.0.0", + "eslint": "9.32.0", + "eslint-config-prettier": "10.1.8", + "eslint-plugin-local-rules": "3.0.2", + "eslint-plugin-n": "17.21.3", + "eslint-plugin-prettier": "5.5.3", + "eslint-plugin-promise": "7.2.1", + "eslint-plugin-vue": "10.4.0", + "eslint-plugin-vue-scoped-css": "2.11.0", + "flush-promises": "1.0.2", + "globals": "16.3.0", + "jest-serializer-vue-tjw": "4.0.0", + "jsdom": "26.1.0", + "lint-staged": "16.1.4", + "prettier": "3.6.2", + "sass": "1.89.2", + "unplugin-vue-components": "28.8.0", + "vite": "6.3.5", + "vite-plugin-comlink": "5.3.0", + "vite-plugin-vuetify": "2.1.2", + "vite-svg-loader": "5.1.0", + "vitest": "3.2.4", + "vitest-canvas-mock": "0.3.3" + } + }, + "node_modules/@adobe/css-tools": { + "version": "4.4.4", + "resolved": "https://registry.npmjs.org/@adobe/css-tools/-/css-tools-4.4.4.tgz", + "integrity": "sha512-Elp+iwUx5rN5+Y8xLt5/GRoG20WGoDCQ/1Fb+1LiGtvwbDavuSk0jhD/eZdckHAuzcDzccnkv+rEjyWfRx18gg==", + "dev": true + }, + "node_modules/@ampproject/remapping": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.3.0.tgz", + "integrity": "sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==", + "dev": true, + "dependencies": { + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.24" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@asamuzakjp/css-color": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/@asamuzakjp/css-color/-/css-color-3.2.0.tgz", + "integrity": "sha512-K1A6z8tS3XsmCMM86xoWdn7Fkdn9m6RSVtocUrJYIwZnFVkng/PvkEoWtOWmP+Scc6saYWHWZYbndEEXxl24jw==", + "dev": true, + "dependencies": { + "@csstools/css-calc": "^2.1.3", + "@csstools/css-color-parser": "^3.0.9", + "@csstools/css-parser-algorithms": "^3.0.4", + "@csstools/css-tokenizer": "^3.0.3", + "lru-cache": "^10.4.3" + } + }, + "node_modules/@asamuzakjp/css-color/node_modules/lru-cache": { + "version": "10.4.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz", + "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==", + "dev": true + }, + "node_modules/@babel/code-frame": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.27.1.tgz", + "integrity": "sha512-cjQ7ZlQ0Mv3b47hABuTevyTuYN4i+loJKGeV9flcCgIK37cCXRh+L1bd3iBHlynerhQ7BhCkn2BPbQUL+rGqFg==", + "dev": true, + "dependencies": { + "@babel/helper-validator-identifier": "^7.27.1", + "js-tokens": "^4.0.0", + "picocolors": "^1.1.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/compat-data": { + "version": "7.28.4", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.28.4.tgz", + "integrity": "sha512-YsmSKC29MJwf0gF8Rjjrg5LQCmyh+j/nD8/eP7f+BeoQTKYqs9RoWbjGOdy0+1Ekr68RJZMUOPVQaQisnIo4Rw==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/core": { + "version": "7.28.4", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.28.4.tgz", + "integrity": "sha512-2BCOP7TN8M+gVDj7/ht3hsaO/B/n5oDbiAyyvnRlNOs+u1o+JWNYTQrmpuNp1/Wq2gcFrI01JAW+paEKDMx/CA==", + "dev": true, + "dependencies": { + "@babel/code-frame": "^7.27.1", + "@babel/generator": "^7.28.3", + "@babel/helper-compilation-targets": "^7.27.2", + "@babel/helper-module-transforms": "^7.28.3", + "@babel/helpers": "^7.28.4", + "@babel/parser": "^7.28.4", + "@babel/template": "^7.27.2", + "@babel/traverse": "^7.28.4", + "@babel/types": "^7.28.4", + "@jridgewell/remapping": "^2.3.5", + "convert-source-map": "^2.0.0", + "debug": "^4.1.0", + "gensync": "^1.0.0-beta.2", + "json5": "^2.2.3", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/babel" + } + }, + "node_modules/@babel/eslint-parser": { + "version": "7.28.0", + "resolved": "https://registry.npmjs.org/@babel/eslint-parser/-/eslint-parser-7.28.0.tgz", + "integrity": "sha512-N4ntErOlKvcbTt01rr5wj3y55xnIdx1ymrfIr8C2WnM1Y9glFgWaGDEULJIazOX3XM9NRzhfJ6zZnQ1sBNWU+w==", + "dev": true, + "dependencies": { + "@nicolo-ribaudo/eslint-scope-5-internals": "5.1.1-v1", + "eslint-visitor-keys": "^2.1.0", + "semver": "^6.3.1" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || >=14.0.0" + }, + "peerDependencies": { + "@babel/core": "^7.11.0", + "eslint": "^7.5.0 || ^8.0.0 || ^9.0.0" + } + }, + "node_modules/@babel/generator": { + "version": "7.28.3", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.28.3.tgz", + "integrity": "sha512-3lSpxGgvnmZznmBkCRnVREPUFJv2wrv9iAoFDvADJc0ypmdOxdUtcLeBgBJ6zE0PMeTKnxeQzyk0xTBq4Ep7zw==", + "dev": true, + "dependencies": { + "@babel/parser": "^7.28.3", + "@babel/types": "^7.28.2", + "@jridgewell/gen-mapping": "^0.3.12", + "@jridgewell/trace-mapping": "^0.3.28", + "jsesc": "^3.0.2" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-annotate-as-pure": { + "version": "7.27.3", + "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.27.3.tgz", + "integrity": "sha512-fXSwMQqitTGeHLBC08Eq5yXz2m37E4pJX1qAU1+2cNedz/ifv/bVXft90VeSav5nFO61EcNgwr0aJxbyPaWBPg==", + "dev": true, + "dependencies": { + "@babel/types": "^7.27.3" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-compilation-targets": { + "version": "7.27.2", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.27.2.tgz", + "integrity": "sha512-2+1thGUUWWjLTYTHZWK1n8Yga0ijBz1XAhUXcKy81rd5g6yh7hGqMp45v7cadSbEHc9G3OTv45SyneRN3ps4DQ==", + "dev": true, + "dependencies": { + "@babel/compat-data": "^7.27.2", + "@babel/helper-validator-option": "^7.27.1", + "browserslist": "^4.24.0", + "lru-cache": "^5.1.1", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-create-class-features-plugin": { + "version": "7.28.3", + "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.28.3.tgz", + "integrity": "sha512-V9f6ZFIYSLNEbuGA/92uOvYsGCJNsuA8ESZ4ldc09bWk/j8H8TKiPw8Mk1eG6olpnO0ALHJmYfZvF4MEE4gajg==", + "dev": true, + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.27.3", + "@babel/helper-member-expression-to-functions": "^7.27.1", + "@babel/helper-optimise-call-expression": "^7.27.1", + "@babel/helper-replace-supers": "^7.27.1", + "@babel/helper-skip-transparent-expression-wrappers": "^7.27.1", + "@babel/traverse": "^7.28.3", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-create-regexp-features-plugin": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.27.1.tgz", + "integrity": "sha512-uVDC72XVf8UbrH5qQTc18Agb8emwjTiZrQE11Nv3CuBEZmVvTwwE9CBUEvHku06gQCAyYf8Nv6ja1IN+6LMbxQ==", + "dev": true, + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.27.1", + "regexpu-core": "^6.2.0", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-define-polyfill-provider": { + "version": "0.6.5", + "resolved": "https://registry.npmjs.org/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.6.5.tgz", + "integrity": "sha512-uJnGFcPsWQK8fvjgGP5LZUZZsYGIoPeRjSF5PGwrelYgq7Q15/Ft9NGFp1zglwgIv//W0uG4BevRuSJRyylZPg==", + "dev": true, + "dependencies": { + "@babel/helper-compilation-targets": "^7.27.2", + "@babel/helper-plugin-utils": "^7.27.1", + "debug": "^4.4.1", + "lodash.debounce": "^4.0.8", + "resolve": "^1.22.10" + }, + "peerDependencies": { + "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" + } + }, + "node_modules/@babel/helper-globals": { + "version": "7.28.0", + "resolved": "https://registry.npmjs.org/@babel/helper-globals/-/helper-globals-7.28.0.tgz", + "integrity": "sha512-+W6cISkXFa1jXsDEdYA8HeevQT/FULhxzR99pxphltZcVaugps53THCeiWA8SguxxpSp3gKPiuYfSWopkLQ4hw==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-member-expression-to-functions": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.27.1.tgz", + "integrity": "sha512-E5chM8eWjTp/aNoVpcbfM7mLxu9XGLWYise2eBKGQomAk/Mb4XoxyqXTZbuTohbsl8EKqdlMhnDI2CCLfcs9wA==", + "dev": true, + "dependencies": { + "@babel/traverse": "^7.27.1", + "@babel/types": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-module-imports": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.27.1.tgz", + "integrity": "sha512-0gSFWUPNXNopqtIPQvlD5WgXYI5GY2kP2cCvoT8kczjbfcfuIljTbcWrulD1CIPIX2gt1wghbDy08yE1p+/r3w==", + "dev": true, + "dependencies": { + "@babel/traverse": "^7.27.1", + "@babel/types": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-module-transforms": { + "version": "7.28.3", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.28.3.tgz", + "integrity": "sha512-gytXUbs8k2sXS9PnQptz5o0QnpLL51SwASIORY6XaBKF88nsOT0Zw9szLqlSGQDP/4TljBAD5y98p2U1fqkdsw==", + "dev": true, + "dependencies": { + "@babel/helper-module-imports": "^7.27.1", + "@babel/helper-validator-identifier": "^7.27.1", + "@babel/traverse": "^7.28.3" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-optimise-call-expression": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.27.1.tgz", + "integrity": "sha512-URMGH08NzYFhubNSGJrpUEphGKQwMQYBySzat5cAByY1/YgIRkULnIy3tAMeszlL/so2HbeilYloUmSpd7GdVw==", + "dev": true, + "dependencies": { + "@babel/types": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-plugin-utils": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.27.1.tgz", + "integrity": "sha512-1gn1Up5YXka3YYAHGKpbideQ5Yjf1tDa9qYcgysz+cNCXukyLl6DjPXhD3VRwSb8c0J9tA4b2+rHEZtc6R0tlw==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-remap-async-to-generator": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.27.1.tgz", + "integrity": "sha512-7fiA521aVw8lSPeI4ZOD3vRFkoqkJcS+z4hFo82bFSH/2tNd6eJ5qCVMS5OzDmZh/kaHQeBaeyxK6wljcPtveA==", + "dev": true, + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.27.1", + "@babel/helper-wrap-function": "^7.27.1", + "@babel/traverse": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-replace-supers": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.27.1.tgz", + "integrity": "sha512-7EHz6qDZc8RYS5ElPoShMheWvEgERonFCs7IAonWLLUTXW59DP14bCZt89/GKyreYn8g3S83m21FelHKbeDCKA==", + "dev": true, + "dependencies": { + "@babel/helper-member-expression-to-functions": "^7.27.1", + "@babel/helper-optimise-call-expression": "^7.27.1", + "@babel/traverse": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-skip-transparent-expression-wrappers": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.27.1.tgz", + "integrity": "sha512-Tub4ZKEXqbPjXgWLl2+3JpQAYBJ8+ikpQ2Ocj/q/r0LwE3UhENh7EUabyHjz2kCEsrRY83ew2DQdHluuiDQFzg==", + "dev": true, + "dependencies": { + "@babel/traverse": "^7.27.1", + "@babel/types": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-string-parser": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.27.1.tgz", + "integrity": "sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-identifier": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.27.1.tgz", + "integrity": "sha512-D2hP9eA+Sqx1kBZgzxZh0y1trbuU+JoDkiEwqhQ36nodYqJwyEIhPSdMNd7lOm/4io72luTPWH20Yda0xOuUow==", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-option": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.27.1.tgz", + "integrity": "sha512-YvjJow9FxbhFFKDSuFnVCe2WxXk1zWc22fFePVNEaWJEu8IrZVlda6N0uHwzZrUM1il7NC9Mlp4MaJYbYd9JSg==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-wrap-function": { + "version": "7.28.3", + "resolved": "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.28.3.tgz", + "integrity": "sha512-zdf983tNfLZFletc0RRXYrHrucBEg95NIFMkn6K9dbeMYnsgHaSBGcQqdsCSStG2PYwRre0Qc2NNSCXbG+xc6g==", + "dev": true, + "dependencies": { + "@babel/template": "^7.27.2", + "@babel/traverse": "^7.28.3", + "@babel/types": "^7.28.2" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helpers": { + "version": "7.28.4", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.28.4.tgz", + "integrity": "sha512-HFN59MmQXGHVyYadKLVumYsA9dBFun/ldYxipEjzA4196jpLZd8UjEEBLkbEkvfYreDqJhZxYAWFPtrfhNpj4w==", + "dev": true, + "dependencies": { + "@babel/template": "^7.27.2", + "@babel/types": "^7.28.4" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/parser": { + "version": "7.28.4", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.28.4.tgz", + "integrity": "sha512-yZbBqeM6TkpP9du/I2pUZnJsRMGGvOuIrhjzC1AwHwW+6he4mni6Bp/m8ijn0iOuZuPI2BfkCoSRunpyjnrQKg==", + "dependencies": { + "@babel/types": "^7.28.4" + }, + "bin": { + "parser": "bin/babel-parser.js" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@babel/plugin-bugfix-firefox-class-in-computed-class-key": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-firefox-class-in-computed-class-key/-/plugin-bugfix-firefox-class-in-computed-class-key-7.27.1.tgz", + "integrity": "sha512-QPG3C9cCVRQLxAVwmefEmwdTanECuUBMQZ/ym5kiw3XKCGA7qkuQLcjWWHcrD/GKbn/WmJwaezfuuAOcyKlRPA==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1", + "@babel/traverse": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/plugin-bugfix-safari-class-field-initializer-scope": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-safari-class-field-initializer-scope/-/plugin-bugfix-safari-class-field-initializer-scope-7.27.1.tgz", + "integrity": "sha512-qNeq3bCKnGgLkEXUuFry6dPlGfCdQNZbn7yUAPCInwAJHMU7THJfrBSozkcWq5sNM6RcF3S8XyQL2A52KNR9IA==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression/-/plugin-bugfix-safari-id-destructuring-collision-in-function-expression-7.27.1.tgz", + "integrity": "sha512-g4L7OYun04N1WyqMNjldFwlfPCLVkgB54A/YCXICZYBsvJJE3kByKv9c9+R/nAfmIfjl2rKYLNyMHboYbZaWaA==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/-/plugin-bugfix-v8-spread-parameters-in-optional-chaining-7.27.1.tgz", + "integrity": "sha512-oO02gcONcD5O1iTLi/6frMJBIwWEHceWGSGqrpCmEL8nogiS6J9PBlE48CaK20/Jx1LuRml9aDftLgdjXT8+Cw==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1", + "@babel/helper-skip-transparent-expression-wrappers": "^7.27.1", + "@babel/plugin-transform-optional-chaining": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.13.0" + } + }, + "node_modules/@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly": { + "version": "7.28.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly/-/plugin-bugfix-v8-static-class-fields-redefine-readonly-7.28.3.tgz", + "integrity": "sha512-b6YTX108evsvE4YgWyQ921ZAFFQm3Bn+CA3+ZXlNVnPhx+UfsVURoPjfGAPCjBgrqo30yX/C2nZGX96DxvR9Iw==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1", + "@babel/traverse": "^7.28.3" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/plugin-proposal-class-properties": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-class-properties/-/plugin-proposal-class-properties-7.18.6.tgz", + "integrity": "sha512-cumfXOF0+nzZrrN8Rf0t7M+tF6sZc7vhQwYQck9q1/5w2OExlD+b4v4RpMJFaV1Z7WcDRgO6FqvxqxGlwo+RHQ==", + "deprecated": "This proposal has been merged to the ECMAScript standard and thus this plugin is no longer maintained. Please use @babel/plugin-transform-class-properties instead.", + "dev": true, + "dependencies": { + "@babel/helper-create-class-features-plugin": "^7.18.6", + "@babel/helper-plugin-utils": "^7.18.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-proposal-decorators": { + "version": "7.28.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-decorators/-/plugin-proposal-decorators-7.28.0.tgz", + "integrity": "sha512-zOiZqvANjWDUaUS9xMxbMcK/Zccztbe/6ikvUXaG9nsPH3w6qh5UaPGAnirI/WhIbZ8m3OHU0ReyPrknG+ZKeg==", + "dev": true, + "dependencies": { + "@babel/helper-create-class-features-plugin": "^7.27.1", + "@babel/helper-plugin-utils": "^7.27.1", + "@babel/plugin-syntax-decorators": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-proposal-private-property-in-object": { + "version": "7.21.0-placeholder-for-preset-env.2", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-private-property-in-object/-/plugin-proposal-private-property-in-object-7.21.0-placeholder-for-preset-env.2.tgz", + "integrity": "sha512-SOSkfJDddaM7mak6cPEpswyTRnuRltl429hMraQEglW+OkovnCzsiszTmsrlY//qLFjCpQDFRvjdm2wA5pPm9w==", + "dev": true, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-decorators": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-decorators/-/plugin-syntax-decorators-7.27.1.tgz", + "integrity": "sha512-YMq8Z87Lhl8EGkmb0MwYkt36QnxC+fzCgrl66ereamPlYToRpIk5nUjKUY3QKLWq8mwUB1BgbeXcTJhZOCDg5A==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-dynamic-import": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-dynamic-import/-/plugin-syntax-dynamic-import-7.8.3.tgz", + "integrity": "sha512-5gdGbFon+PszYzqs83S3E5mpi7/y/8M9eC90MRTZfduQOYW76ig6SOSPNe41IG5LoP3FGBn2N0RjVDSQiS94kQ==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-import-assertions": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-assertions/-/plugin-syntax-import-assertions-7.27.1.tgz", + "integrity": "sha512-UT/Jrhw57xg4ILHLFnzFpPDlMbcdEicaAtjPQpbj9wa8T4r5KVWCimHcL/460g8Ht0DMxDyjsLgiWSkVjnwPFg==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-import-attributes": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-attributes/-/plugin-syntax-import-attributes-7.27.1.tgz", + "integrity": "sha512-oFT0FrKHgF53f4vOsZGi2Hh3I35PfSmVs4IBFLFj4dnafP+hIWDLg3VyKmUHfLoLHlyxY4C7DGtmHuJgn+IGww==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-jsx": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.27.1.tgz", + "integrity": "sha512-y8YTNIeKoyhGd9O0Jiyzyyqk8gdjnumGTQPsz0xOZOQ2RmkVJeZ1vmmfIvFEKqucBG6axJGBZDE/7iI5suUI/w==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-unicode-sets-regex": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-unicode-sets-regex/-/plugin-syntax-unicode-sets-regex-7.18.6.tgz", + "integrity": "sha512-727YkEAPwSIQTv5im8QHz3upqp92JTWhidIC81Tdx4VJYIte/VndKf1qKrfnnhPLiPghStWfvC/iFaMCQu7Nqg==", + "dev": true, + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.18.6", + "@babel/helper-plugin-utils": "^7.18.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/plugin-transform-arrow-functions": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.27.1.tgz", + "integrity": "sha512-8Z4TGic6xW70FKThA5HYEKKyBpOOsucTOD1DjU3fZxDg+K3zBJcXMFnt/4yQiZnf5+MiOMSXQ9PaEK/Ilh1DeA==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-async-generator-functions": { + "version": "7.28.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-generator-functions/-/plugin-transform-async-generator-functions-7.28.0.tgz", + "integrity": "sha512-BEOdvX4+M765icNPZeidyADIvQ1m1gmunXufXxvRESy/jNNyfovIqUyE7MVgGBjWktCoJlzvFA1To2O4ymIO3Q==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1", + "@babel/helper-remap-async-to-generator": "^7.27.1", + "@babel/traverse": "^7.28.0" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-async-to-generator": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.27.1.tgz", + "integrity": "sha512-NREkZsZVJS4xmTr8qzE5y8AfIPqsdQfRuUiLRTEzb7Qii8iFWCyDKaUV2c0rCuh4ljDZ98ALHP/PetiBV2nddA==", + "dev": true, + "dependencies": { + "@babel/helper-module-imports": "^7.27.1", + "@babel/helper-plugin-utils": "^7.27.1", + "@babel/helper-remap-async-to-generator": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-block-scoped-functions": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.27.1.tgz", + "integrity": "sha512-cnqkuOtZLapWYZUYM5rVIdv1nXYuFVIltZ6ZJ7nIj585QsjKM5dhL2Fu/lICXZ1OyIAFc7Qy+bvDAtTXqGrlhg==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-block-scoping": { + "version": "7.28.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.28.4.tgz", + "integrity": "sha512-1yxmvN0MJHOhPVmAsmoW5liWwoILobu/d/ShymZmj867bAdxGbehIrew1DuLpw2Ukv+qDSSPQdYW1dLNE7t11A==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-class-properties": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-class-properties/-/plugin-transform-class-properties-7.27.1.tgz", + "integrity": "sha512-D0VcalChDMtuRvJIu3U/fwWjf8ZMykz5iZsg77Nuj821vCKI3zCyRLwRdWbsuJ/uRwZhZ002QtCqIkwC/ZkvbA==", + "dev": true, + "dependencies": { + "@babel/helper-create-class-features-plugin": "^7.27.1", + "@babel/helper-plugin-utils": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-class-static-block": { + "version": "7.28.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-class-static-block/-/plugin-transform-class-static-block-7.28.3.tgz", + "integrity": "sha512-LtPXlBbRoc4Njl/oh1CeD/3jC+atytbnf/UqLoqTDcEYGUPj022+rvfkbDYieUrSj3CaV4yHDByPE+T2HwfsJg==", + "dev": true, + "dependencies": { + "@babel/helper-create-class-features-plugin": "^7.28.3", + "@babel/helper-plugin-utils": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.12.0" + } + }, + "node_modules/@babel/plugin-transform-classes": { + "version": "7.28.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.28.4.tgz", + "integrity": "sha512-cFOlhIYPBv/iBoc+KS3M6et2XPtbT2HiCRfBXWtfpc9OAyostldxIf9YAYB6ypURBBbx+Qv6nyrLzASfJe+hBA==", + "dev": true, + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.27.3", + "@babel/helper-compilation-targets": "^7.27.2", + "@babel/helper-globals": "^7.28.0", + "@babel/helper-plugin-utils": "^7.27.1", + "@babel/helper-replace-supers": "^7.27.1", + "@babel/traverse": "^7.28.4" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-computed-properties": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.27.1.tgz", + "integrity": "sha512-lj9PGWvMTVksbWiDT2tW68zGS/cyo4AkZ/QTp0sQT0mjPopCmrSkzxeXkznjqBxzDI6TclZhOJbBmbBLjuOZUw==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1", + "@babel/template": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-destructuring": { + "version": "7.28.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.28.0.tgz", + "integrity": "sha512-v1nrSMBiKcodhsyJ4Gf+Z0U/yawmJDBOTpEB3mcQY52r9RIyPneGyAS/yM6seP/8I+mWI3elOMtT5dB8GJVs+A==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1", + "@babel/traverse": "^7.28.0" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-dotall-regex": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.27.1.tgz", + "integrity": "sha512-gEbkDVGRvjj7+T1ivxrfgygpT7GUd4vmODtYpbs0gZATdkX8/iSnOtZSxiZnsgm1YjTgjI6VKBGSJJevkrclzw==", + "dev": true, + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.27.1", + "@babel/helper-plugin-utils": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-duplicate-keys": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.27.1.tgz", + "integrity": "sha512-MTyJk98sHvSs+cvZ4nOauwTTG1JeonDjSGvGGUNHreGQns+Mpt6WX/dVzWBHgg+dYZhkC4X+zTDfkTU+Vy9y7Q==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-duplicate-named-capturing-groups-regex": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-named-capturing-groups-regex/-/plugin-transform-duplicate-named-capturing-groups-regex-7.27.1.tgz", + "integrity": "sha512-hkGcueTEzuhB30B3eJCbCYeCaaEQOmQR0AdvzpD4LoN0GXMWzzGSuRrxR2xTnCrvNbVwK9N6/jQ92GSLfiZWoQ==", + "dev": true, + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.27.1", + "@babel/helper-plugin-utils": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/plugin-transform-dynamic-import": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dynamic-import/-/plugin-transform-dynamic-import-7.27.1.tgz", + "integrity": "sha512-MHzkWQcEmjzzVW9j2q8LGjwGWpG2mjwaaB0BNQwst3FIjqsg8Ct/mIZlvSPJvfi9y2AC8mi/ktxbFVL9pZ1I4A==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-explicit-resource-management": { + "version": "7.28.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-explicit-resource-management/-/plugin-transform-explicit-resource-management-7.28.0.tgz", + "integrity": "sha512-K8nhUcn3f6iB+P3gwCv/no7OdzOZQcKchW6N389V6PD8NUWKZHzndOd9sPDVbMoBsbmjMqlB4L9fm+fEFNVlwQ==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1", + "@babel/plugin-transform-destructuring": "^7.28.0" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-exponentiation-operator": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.27.1.tgz", + "integrity": "sha512-uspvXnhHvGKf2r4VVtBpeFnuDWsJLQ6MF6lGJLC89jBR1uoVeqM416AZtTuhTezOfgHicpJQmoD5YUakO/YmXQ==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-export-namespace-from": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-export-namespace-from/-/plugin-transform-export-namespace-from-7.27.1.tgz", + "integrity": "sha512-tQvHWSZ3/jH2xuq/vZDy0jNn+ZdXJeM8gHvX4lnJmsc3+50yPlWdZXIc5ay+umX+2/tJIqHqiEqcJvxlmIvRvQ==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-for-of": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.27.1.tgz", + "integrity": "sha512-BfbWFFEJFQzLCQ5N8VocnCtA8J1CLkNTe2Ms2wocj75dd6VpiqS5Z5quTYcUoo4Yq+DN0rtikODccuv7RU81sw==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1", + "@babel/helper-skip-transparent-expression-wrappers": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-function-name": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.27.1.tgz", + "integrity": "sha512-1bQeydJF9Nr1eBCMMbC+hdwmRlsv5XYOMu03YSWFwNs0HsAmtSxxF1fyuYPqemVldVyFmlCU7w8UE14LupUSZQ==", + "dev": true, + "dependencies": { + "@babel/helper-compilation-targets": "^7.27.1", + "@babel/helper-plugin-utils": "^7.27.1", + "@babel/traverse": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-json-strings": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-json-strings/-/plugin-transform-json-strings-7.27.1.tgz", + "integrity": "sha512-6WVLVJiTjqcQauBhn1LkICsR2H+zm62I3h9faTDKt1qP4jn2o72tSvqMwtGFKGTpojce0gJs+76eZ2uCHRZh0Q==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-literals": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-literals/-/plugin-transform-literals-7.27.1.tgz", + "integrity": "sha512-0HCFSepIpLTkLcsi86GG3mTUzxV5jpmbv97hTETW3yzrAij8aqlD36toB1D0daVFJM8NK6GvKO0gslVQmm+zZA==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-logical-assignment-operators": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-logical-assignment-operators/-/plugin-transform-logical-assignment-operators-7.27.1.tgz", + "integrity": "sha512-SJvDs5dXxiae4FbSL1aBJlG4wvl594N6YEVVn9e3JGulwioy6z3oPjx/sQBO3Y4NwUu5HNix6KJ3wBZoewcdbw==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-member-expression-literals": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.27.1.tgz", + "integrity": "sha512-hqoBX4dcZ1I33jCSWcXrP+1Ku7kdqXf1oeah7ooKOIiAdKQ+uqftgCFNOSzA5AMS2XIHEYeGFg4cKRCdpxzVOQ==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-modules-amd": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.27.1.tgz", + "integrity": "sha512-iCsytMg/N9/oFq6n+gFTvUYDZQOMK5kEdeYxmxt91fcJGycfxVP9CnrxoliM0oumFERba2i8ZtwRUCMhvP1LnA==", + "dev": true, + "dependencies": { + "@babel/helper-module-transforms": "^7.27.1", + "@babel/helper-plugin-utils": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-modules-commonjs": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.27.1.tgz", + "integrity": "sha512-OJguuwlTYlN0gBZFRPqwOGNWssZjfIUdS7HMYtN8c1KmwpwHFBwTeFZrg9XZa+DFTitWOW5iTAG7tyCUPsCCyw==", + "dev": true, + "dependencies": { + "@babel/helper-module-transforms": "^7.27.1", + "@babel/helper-plugin-utils": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-modules-systemjs": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.27.1.tgz", + "integrity": "sha512-w5N1XzsRbc0PQStASMksmUeqECuzKuTJer7kFagK8AXgpCMkeDMO5S+aaFb7A51ZYDF7XI34qsTX+fkHiIm5yA==", + "dev": true, + "dependencies": { + "@babel/helper-module-transforms": "^7.27.1", + "@babel/helper-plugin-utils": "^7.27.1", + "@babel/helper-validator-identifier": "^7.27.1", + "@babel/traverse": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-modules-umd": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.27.1.tgz", + "integrity": "sha512-iQBE/xC5BV1OxJbp6WG7jq9IWiD+xxlZhLrdwpPkTX3ydmXdvoCpyfJN7acaIBZaOqTfr76pgzqBJflNbeRK+w==", + "dev": true, + "dependencies": { + "@babel/helper-module-transforms": "^7.27.1", + "@babel/helper-plugin-utils": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-named-capturing-groups-regex": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.27.1.tgz", + "integrity": "sha512-SstR5JYy8ddZvD6MhV0tM/j16Qds4mIpJTOd1Yu9J9pJjH93bxHECF7pgtc28XvkzTD6Pxcm/0Z73Hvk7kb3Ng==", + "dev": true, + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.27.1", + "@babel/helper-plugin-utils": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/plugin-transform-new-target": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.27.1.tgz", + "integrity": "sha512-f6PiYeqXQ05lYq3TIfIDu/MtliKUbNwkGApPUvyo6+tc7uaR4cPjPe7DFPr15Uyycg2lZU6btZ575CuQoYh7MQ==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-nullish-coalescing-operator": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-nullish-coalescing-operator/-/plugin-transform-nullish-coalescing-operator-7.27.1.tgz", + "integrity": "sha512-aGZh6xMo6q9vq1JGcw58lZ1Z0+i0xB2x0XaauNIUXd6O1xXc3RwoWEBlsTQrY4KQ9Jf0s5rgD6SiNkaUdJegTA==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-numeric-separator": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-numeric-separator/-/plugin-transform-numeric-separator-7.27.1.tgz", + "integrity": "sha512-fdPKAcujuvEChxDBJ5c+0BTaS6revLV7CJL08e4m3de8qJfNIuCc2nc7XJYOjBoTMJeqSmwXJ0ypE14RCjLwaw==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-object-rest-spread": { + "version": "7.28.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-rest-spread/-/plugin-transform-object-rest-spread-7.28.4.tgz", + "integrity": "sha512-373KA2HQzKhQCYiRVIRr+3MjpCObqzDlyrM6u4I201wL8Mp2wHf7uB8GhDwis03k2ti8Zr65Zyyqs1xOxUF/Ew==", + "dev": true, + "dependencies": { + "@babel/helper-compilation-targets": "^7.27.2", + "@babel/helper-plugin-utils": "^7.27.1", + "@babel/plugin-transform-destructuring": "^7.28.0", + "@babel/plugin-transform-parameters": "^7.27.7", + "@babel/traverse": "^7.28.4" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-object-super": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.27.1.tgz", + "integrity": "sha512-SFy8S9plRPbIcxlJ8A6mT/CxFdJx/c04JEctz4jf8YZaVS2px34j7NXRrlGlHkN/M2gnpL37ZpGRGVFLd3l8Ng==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1", + "@babel/helper-replace-supers": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-optional-catch-binding": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-catch-binding/-/plugin-transform-optional-catch-binding-7.27.1.tgz", + "integrity": "sha512-txEAEKzYrHEX4xSZN4kJ+OfKXFVSWKB2ZxM9dpcE3wT7smwkNmXo5ORRlVzMVdJbD+Q8ILTgSD7959uj+3Dm3Q==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-optional-chaining": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-chaining/-/plugin-transform-optional-chaining-7.27.1.tgz", + "integrity": "sha512-BQmKPPIuc8EkZgNKsv0X4bPmOoayeu4F1YCwx2/CfmDSXDbp7GnzlUH+/ul5VGfRg1AoFPsrIThlEBj2xb4CAg==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1", + "@babel/helper-skip-transparent-expression-wrappers": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-parameters": { + "version": "7.27.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.27.7.tgz", + "integrity": "sha512-qBkYTYCb76RRxUM6CcZA5KRu8K4SM8ajzVeUgVdMVO9NN9uI/GaVmBg/WKJJGnNokV9SY8FxNOVWGXzqzUidBg==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-private-methods": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-private-methods/-/plugin-transform-private-methods-7.27.1.tgz", + "integrity": "sha512-10FVt+X55AjRAYI9BrdISN9/AQWHqldOeZDUoLyif1Kn05a56xVBXb8ZouL8pZ9jem8QpXaOt8TS7RHUIS+GPA==", + "dev": true, + "dependencies": { + "@babel/helper-create-class-features-plugin": "^7.27.1", + "@babel/helper-plugin-utils": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-private-property-in-object": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-private-property-in-object/-/plugin-transform-private-property-in-object-7.27.1.tgz", + "integrity": "sha512-5J+IhqTi1XPa0DXF83jYOaARrX+41gOewWbkPyjMNRDqgOCqdffGh8L3f/Ek5utaEBZExjSAzcyjmV9SSAWObQ==", + "dev": true, + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.27.1", + "@babel/helper-create-class-features-plugin": "^7.27.1", + "@babel/helper-plugin-utils": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-property-literals": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.27.1.tgz", + "integrity": "sha512-oThy3BCuCha8kDZ8ZkgOg2exvPYUlprMukKQXI1r1pJ47NCvxfkEy8vK+r/hT9nF0Aa4H1WUPZZjHTFtAhGfmQ==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-regenerator": { + "version": "7.28.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.28.4.tgz", + "integrity": "sha512-+ZEdQlBoRg9m2NnzvEeLgtvBMO4tkFBw5SQIUgLICgTrumLoU7lr+Oghi6km2PFj+dbUt2u1oby2w3BDO9YQnA==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-regexp-modifiers": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regexp-modifiers/-/plugin-transform-regexp-modifiers-7.27.1.tgz", + "integrity": "sha512-TtEciroaiODtXvLZv4rmfMhkCv8jx3wgKpL68PuiPh2M4fvz5jhsA7697N1gMvkvr/JTF13DrFYyEbY9U7cVPA==", + "dev": true, + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.27.1", + "@babel/helper-plugin-utils": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/plugin-transform-reserved-words": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.27.1.tgz", + "integrity": "sha512-V2ABPHIJX4kC7HegLkYoDpfg9PVmuWy/i6vUM5eGK22bx4YVFD3M5F0QQnWQoDs6AGsUWTVOopBiMFQgHaSkVw==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-runtime": { + "version": "7.28.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.28.3.tgz", + "integrity": "sha512-Y6ab1kGqZ0u42Zv/4a7l0l72n9DKP/MKoKWaUSBylrhNZO2prYuqFOLbn5aW5SIFXwSH93yfjbgllL8lxuGKLg==", + "dev": true, + "dependencies": { + "@babel/helper-module-imports": "^7.27.1", + "@babel/helper-plugin-utils": "^7.27.1", + "babel-plugin-polyfill-corejs2": "^0.4.14", + "babel-plugin-polyfill-corejs3": "^0.13.0", + "babel-plugin-polyfill-regenerator": "^0.6.5", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-shorthand-properties": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.27.1.tgz", + "integrity": "sha512-N/wH1vcn4oYawbJ13Y/FxcQrWk63jhfNa7jef0ih7PHSIHX2LB7GWE1rkPrOnka9kwMxb6hMl19p7lidA+EHmQ==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-spread": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-spread/-/plugin-transform-spread-7.27.1.tgz", + "integrity": "sha512-kpb3HUqaILBJcRFVhFUs6Trdd4mkrzcGXss+6/mxUd273PfbWqSDHRzMT2234gIg2QYfAjvXLSquP1xECSg09Q==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1", + "@babel/helper-skip-transparent-expression-wrappers": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-sticky-regex": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.27.1.tgz", + "integrity": "sha512-lhInBO5bi/Kowe2/aLdBAawijx+q1pQzicSgnkB6dUPc1+RC8QmJHKf2OjvU+NZWitguJHEaEmbV6VWEouT58g==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-template-literals": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.27.1.tgz", + "integrity": "sha512-fBJKiV7F2DxZUkg5EtHKXQdbsbURW3DZKQUWphDum0uRP6eHGGa/He9mc0mypL680pb+e/lDIthRohlv8NCHkg==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-typeof-symbol": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.27.1.tgz", + "integrity": "sha512-RiSILC+nRJM7FY5srIyc4/fGIwUhyDuuBSdWn4y6yT6gm652DpCHZjIipgn6B7MQ1ITOUnAKWixEUjQRIBIcLw==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-unicode-escapes": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.27.1.tgz", + "integrity": "sha512-Ysg4v6AmF26k9vpfFuTZg8HRfVWzsh1kVfowA23y9j/Gu6dOuahdUVhkLqpObp3JIv27MLSii6noRnuKN8H0Mg==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-unicode-property-regex": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-property-regex/-/plugin-transform-unicode-property-regex-7.27.1.tgz", + "integrity": "sha512-uW20S39PnaTImxp39O5qFlHLS9LJEmANjMG7SxIhap8rCHqu0Ik+tLEPX5DKmHn6CsWQ7j3lix2tFOa5YtL12Q==", + "dev": true, + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.27.1", + "@babel/helper-plugin-utils": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-unicode-regex": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.27.1.tgz", + "integrity": "sha512-xvINq24TRojDuyt6JGtHmkVkrfVV3FPT16uytxImLeBZqW3/H52yN+kM1MGuyPkIQxrzKwPHs5U/MP3qKyzkGw==", + "dev": true, + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.27.1", + "@babel/helper-plugin-utils": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-unicode-sets-regex": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-sets-regex/-/plugin-transform-unicode-sets-regex-7.27.1.tgz", + "integrity": "sha512-EtkOujbc4cgvb0mlpQefi4NTPBzhSIevblFevACNLUspmrALgmEBdL/XfnyyITfd8fKBZrZys92zOWcik7j9Tw==", + "dev": true, + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.27.1", + "@babel/helper-plugin-utils": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/preset-env": { + "version": "7.28.3", + "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.28.3.tgz", + "integrity": "sha512-ROiDcM+GbYVPYBOeCR6uBXKkQpBExLl8k9HO1ygXEyds39j+vCCsjmj7S8GOniZQlEs81QlkdJZe76IpLSiqpg==", + "dev": true, + "dependencies": { + "@babel/compat-data": "^7.28.0", + "@babel/helper-compilation-targets": "^7.27.2", + "@babel/helper-plugin-utils": "^7.27.1", + "@babel/helper-validator-option": "^7.27.1", + "@babel/plugin-bugfix-firefox-class-in-computed-class-key": "^7.27.1", + "@babel/plugin-bugfix-safari-class-field-initializer-scope": "^7.27.1", + "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": "^7.27.1", + "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": "^7.27.1", + "@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly": "^7.28.3", + "@babel/plugin-proposal-private-property-in-object": "7.21.0-placeholder-for-preset-env.2", + "@babel/plugin-syntax-import-assertions": "^7.27.1", + "@babel/plugin-syntax-import-attributes": "^7.27.1", + "@babel/plugin-syntax-unicode-sets-regex": "^7.18.6", + "@babel/plugin-transform-arrow-functions": "^7.27.1", + "@babel/plugin-transform-async-generator-functions": "^7.28.0", + "@babel/plugin-transform-async-to-generator": "^7.27.1", + "@babel/plugin-transform-block-scoped-functions": "^7.27.1", + "@babel/plugin-transform-block-scoping": "^7.28.0", + "@babel/plugin-transform-class-properties": "^7.27.1", + "@babel/plugin-transform-class-static-block": "^7.28.3", + "@babel/plugin-transform-classes": "^7.28.3", + "@babel/plugin-transform-computed-properties": "^7.27.1", + "@babel/plugin-transform-destructuring": "^7.28.0", + "@babel/plugin-transform-dotall-regex": "^7.27.1", + "@babel/plugin-transform-duplicate-keys": "^7.27.1", + "@babel/plugin-transform-duplicate-named-capturing-groups-regex": "^7.27.1", + "@babel/plugin-transform-dynamic-import": "^7.27.1", + "@babel/plugin-transform-explicit-resource-management": "^7.28.0", + "@babel/plugin-transform-exponentiation-operator": "^7.27.1", + "@babel/plugin-transform-export-namespace-from": "^7.27.1", + "@babel/plugin-transform-for-of": "^7.27.1", + "@babel/plugin-transform-function-name": "^7.27.1", + "@babel/plugin-transform-json-strings": "^7.27.1", + "@babel/plugin-transform-literals": "^7.27.1", + "@babel/plugin-transform-logical-assignment-operators": "^7.27.1", + "@babel/plugin-transform-member-expression-literals": "^7.27.1", + "@babel/plugin-transform-modules-amd": "^7.27.1", + "@babel/plugin-transform-modules-commonjs": "^7.27.1", + "@babel/plugin-transform-modules-systemjs": "^7.27.1", + "@babel/plugin-transform-modules-umd": "^7.27.1", + "@babel/plugin-transform-named-capturing-groups-regex": "^7.27.1", + "@babel/plugin-transform-new-target": "^7.27.1", + "@babel/plugin-transform-nullish-coalescing-operator": "^7.27.1", + "@babel/plugin-transform-numeric-separator": "^7.27.1", + "@babel/plugin-transform-object-rest-spread": "^7.28.0", + "@babel/plugin-transform-object-super": "^7.27.1", + "@babel/plugin-transform-optional-catch-binding": "^7.27.1", + "@babel/plugin-transform-optional-chaining": "^7.27.1", + "@babel/plugin-transform-parameters": "^7.27.7", + "@babel/plugin-transform-private-methods": "^7.27.1", + "@babel/plugin-transform-private-property-in-object": "^7.27.1", + "@babel/plugin-transform-property-literals": "^7.27.1", + "@babel/plugin-transform-regenerator": "^7.28.3", + "@babel/plugin-transform-regexp-modifiers": "^7.27.1", + "@babel/plugin-transform-reserved-words": "^7.27.1", + "@babel/plugin-transform-shorthand-properties": "^7.27.1", + "@babel/plugin-transform-spread": "^7.27.1", + "@babel/plugin-transform-sticky-regex": "^7.27.1", + "@babel/plugin-transform-template-literals": "^7.27.1", + "@babel/plugin-transform-typeof-symbol": "^7.27.1", + "@babel/plugin-transform-unicode-escapes": "^7.27.1", + "@babel/plugin-transform-unicode-property-regex": "^7.27.1", + "@babel/plugin-transform-unicode-regex": "^7.27.1", + "@babel/plugin-transform-unicode-sets-regex": "^7.27.1", + "@babel/preset-modules": "0.1.6-no-external-plugins", + "babel-plugin-polyfill-corejs2": "^0.4.14", + "babel-plugin-polyfill-corejs3": "^0.13.0", + "babel-plugin-polyfill-regenerator": "^0.6.5", + "core-js-compat": "^3.43.0", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/preset-modules": { + "version": "0.1.6-no-external-plugins", + "resolved": "https://registry.npmjs.org/@babel/preset-modules/-/preset-modules-0.1.6-no-external-plugins.tgz", + "integrity": "sha512-HrcgcIESLm9aIR842yhJ5RWan/gebQUJ6E/E5+rf0y9o6oj7w0Br+sWuL6kEQ/o/AdfvR1Je9jG18/gnpwjEyA==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.0.0", + "@babel/types": "^7.4.4", + "esutils": "^2.0.2" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0 || ^8.0.0-0 <8.0.0" + } + }, + "node_modules/@babel/runtime": { + "version": "7.28.4", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.28.4.tgz", + "integrity": "sha512-Q/N6JNWvIvPnLDvjlE1OUBLPQHH6l3CltCEsHIujp45zQUSSh8K+gHnaEX45yAT1nyngnINhvWtzN+Nb9D8RAQ==", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/template": { + "version": "7.27.2", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.27.2.tgz", + "integrity": "sha512-LPDZ85aEJyYSd18/DkjNh4/y1ntkE5KwUHWTiqgRxruuZL2F1yuHligVHLvcHY2vMHXttKFpJn6LwfI7cw7ODw==", + "dev": true, + "dependencies": { + "@babel/code-frame": "^7.27.1", + "@babel/parser": "^7.27.2", + "@babel/types": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/traverse": { + "version": "7.28.4", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.28.4.tgz", + "integrity": "sha512-YEzuboP2qvQavAcjgQNVgsvHIDv6ZpwXvcvjmyySP2DIMuByS/6ioU5G9pYrWHM6T2YDfc7xga9iNzYOs12CFQ==", + "dev": true, + "dependencies": { + "@babel/code-frame": "^7.27.1", + "@babel/generator": "^7.28.3", + "@babel/helper-globals": "^7.28.0", + "@babel/parser": "^7.28.4", + "@babel/template": "^7.27.2", + "@babel/types": "^7.28.4", + "debug": "^4.3.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/types": { + "version": "7.28.4", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.28.4.tgz", + "integrity": "sha512-bkFqkLhh3pMBUQQkpVgWDWq/lqzc2678eUyDlTBhRqhCHFguYYGM0Efga7tYk4TogG/3x0EEl66/OQ+WGbWB/Q==", + "dependencies": { + "@babel/helper-string-parser": "^7.27.1", + "@babel/helper-validator-identifier": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@bcoe/v8-coverage": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@bcoe/v8-coverage/-/v8-coverage-1.0.2.tgz", + "integrity": "sha512-6zABk/ECA/QYSCQ1NGiVwwbQerUCZ+TQbp64Q3AgmfNvurHH0j8TtXa1qbShXA6qqkpAj4V5W8pP6mLe1mcMqA==", + "dev": true, + "engines": { + "node": ">=18" + } + }, + "node_modules/@csstools/color-helpers": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/@csstools/color-helpers/-/color-helpers-5.1.0.tgz", + "integrity": "sha512-S11EXWJyy0Mz5SYvRmY8nJYTFFd1LCNV+7cXyAgQtOOuzb4EsgfqDufL+9esx72/eLhsRdGZwaldu/h+E4t4BA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@csstools/css-calc": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/@csstools/css-calc/-/css-calc-2.1.4.tgz", + "integrity": "sha512-3N8oaj+0juUw/1H3YwmDDJXCgTB1gKU6Hc/bB502u9zR0q2vd786XJH9QfrKIEgFlZmhZiq6epXl4rHqhzsIgQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "@csstools/css-parser-algorithms": "^3.0.5", + "@csstools/css-tokenizer": "^3.0.4" + } + }, + "node_modules/@csstools/css-color-parser": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@csstools/css-color-parser/-/css-color-parser-3.1.0.tgz", + "integrity": "sha512-nbtKwh3a6xNVIp/VRuXV64yTKnb1IjTAEEh3irzS+HkKjAOYLTGNb9pmVNntZ8iVBHcWDA2Dof0QtPgFI1BaTA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "dependencies": { + "@csstools/color-helpers": "^5.1.0", + "@csstools/css-calc": "^2.1.4" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "@csstools/css-parser-algorithms": "^3.0.5", + "@csstools/css-tokenizer": "^3.0.4" + } + }, + "node_modules/@csstools/css-parser-algorithms": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/@csstools/css-parser-algorithms/-/css-parser-algorithms-3.0.5.tgz", + "integrity": "sha512-DaDeUkXZKjdGhgYaHNJTV9pV7Y9B3b644jCLs9Upc3VeNGg6LWARAT6O+Q+/COo+2gg/bM5rhpMAtf70WqfBdQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "@csstools/css-tokenizer": "^3.0.4" + } + }, + "node_modules/@csstools/css-tokenizer": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@csstools/css-tokenizer/-/css-tokenizer-3.0.4.tgz", + "integrity": "sha512-Vd/9EVDiu6PPJt9yAh6roZP6El1xHrdvIVGjyBsHR0RYwNHgL7FJPyIIW4fANJNG6FtyZfvlRPpFI4ZM/lubvw==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/aix-ppc64": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.25.9.tgz", + "integrity": "sha512-OaGtL73Jck6pBKjNIe24BnFE6agGl+6KxDtTfHhy1HmhthfKouEcOhqpSL64K4/0WCtbKFLOdzD/44cJ4k9opA==", + "cpu": [ + "ppc64" + ], + "optional": true, + "os": [ + "aix" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-arm": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.25.9.tgz", + "integrity": "sha512-5WNI1DaMtxQ7t7B6xa572XMXpHAaI/9Hnhk8lcxF4zVN4xstUgTlvuGDorBguKEnZO70qwEcLpfifMLoxiPqHQ==", + "cpu": [ + "arm" + ], + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-arm64": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.25.9.tgz", + "integrity": "sha512-IDrddSmpSv51ftWslJMvl3Q2ZT98fUSL2/rlUXuVqRXHCs5EUF1/f+jbjF5+NG9UffUDMCiTyh8iec7u8RlTLg==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-x64": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.25.9.tgz", + "integrity": "sha512-I853iMZ1hWZdNllhVZKm34f4wErd4lMyeV7BLzEExGEIZYsOzqDWDf+y082izYUE8gtJnYHdeDpN/6tUdwvfiw==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/darwin-arm64": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.25.9.tgz", + "integrity": "sha512-XIpIDMAjOELi/9PB30vEbVMs3GV1v2zkkPnuyRRURbhqjyzIINwj+nbQATh4H9GxUgH1kFsEyQMxwiLFKUS6Rg==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/darwin-x64": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.25.9.tgz", + "integrity": "sha512-jhHfBzjYTA1IQu8VyrjCX4ApJDnH+ez+IYVEoJHeqJm9VhG9Dh2BYaJritkYK3vMaXrf7Ogr/0MQ8/MeIefsPQ==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/freebsd-arm64": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.25.9.tgz", + "integrity": "sha512-z93DmbnY6fX9+KdD4Ue/H6sYs+bhFQJNCPZsi4XWJoYblUqT06MQUdBCpcSfuiN72AbqeBFu5LVQTjfXDE2A6Q==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/freebsd-x64": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.25.9.tgz", + "integrity": "sha512-mrKX6H/vOyo5v71YfXWJxLVxgy1kyt1MQaD8wZJgJfG4gq4DpQGpgTB74e5yBeQdyMTbgxp0YtNj7NuHN0PoZg==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-arm": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.25.9.tgz", + "integrity": "sha512-HBU2Xv78SMgaydBmdor38lg8YDnFKSARg1Q6AT0/y2ezUAKiZvc211RDFHlEZRFNRVhcMamiToo7bDx3VEOYQw==", + "cpu": [ + "arm" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-arm64": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.25.9.tgz", + "integrity": "sha512-BlB7bIcLT3G26urh5Dmse7fiLmLXnRlopw4s8DalgZ8ef79Jj4aUcYbk90g8iCa2467HX8SAIidbL7gsqXHdRw==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-ia32": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.25.9.tgz", + "integrity": "sha512-e7S3MOJPZGp2QW6AK6+Ly81rC7oOSerQ+P8L0ta4FhVi+/j/v2yZzx5CqqDaWjtPFfYz21Vi1S0auHrap3Ma3A==", + "cpu": [ + "ia32" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-loong64": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.25.9.tgz", + "integrity": "sha512-Sbe10Bnn0oUAB2AalYztvGcK+o6YFFA/9829PhOCUS9vkJElXGdphz0A3DbMdP8gmKkqPmPcMJmJOrI3VYB1JQ==", + "cpu": [ + "loong64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-mips64el": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.25.9.tgz", + "integrity": "sha512-YcM5br0mVyZw2jcQeLIkhWtKPeVfAerES5PvOzaDxVtIyZ2NUBZKNLjC5z3/fUlDgT6w89VsxP2qzNipOaaDyA==", + "cpu": [ + "mips64el" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-ppc64": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.25.9.tgz", + "integrity": "sha512-++0HQvasdo20JytyDpFvQtNrEsAgNG2CY1CLMwGXfFTKGBGQT3bOeLSYE2l1fYdvML5KUuwn9Z8L1EWe2tzs1w==", + "cpu": [ + "ppc64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-riscv64": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.25.9.tgz", + "integrity": "sha512-uNIBa279Y3fkjV+2cUjx36xkx7eSjb8IvnL01eXUKXez/CBHNRw5ekCGMPM0BcmqBxBcdgUWuUXmVWwm4CH9kg==", + "cpu": [ + "riscv64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-s390x": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.25.9.tgz", + "integrity": "sha512-Mfiphvp3MjC/lctb+7D287Xw1DGzqJPb/J2aHHcHxflUo+8tmN/6d4k6I2yFR7BVo5/g7x2Monq4+Yew0EHRIA==", + "cpu": [ + "s390x" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-x64": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.25.9.tgz", + "integrity": "sha512-iSwByxzRe48YVkmpbgoxVzn76BXjlYFXC7NvLYq+b+kDjyyk30J0JY47DIn8z1MO3K0oSl9fZoRmZPQI4Hklzg==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/netbsd-arm64": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.25.9.tgz", + "integrity": "sha512-9jNJl6FqaUG+COdQMjSCGW4QiMHH88xWbvZ+kRVblZsWrkXlABuGdFJ1E9L7HK+T0Yqd4akKNa/lO0+jDxQD4Q==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/netbsd-x64": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.25.9.tgz", + "integrity": "sha512-RLLdkflmqRG8KanPGOU7Rpg829ZHu8nFy5Pqdi9U01VYtG9Y0zOG6Vr2z4/S+/3zIyOxiK6cCeYNWOFR9QP87g==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openbsd-arm64": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.25.9.tgz", + "integrity": "sha512-YaFBlPGeDasft5IIM+CQAhJAqS3St3nJzDEgsgFixcfZeyGPCd6eJBWzke5piZuZ7CtL656eOSYKk4Ls2C0FRQ==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openbsd-x64": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.25.9.tgz", + "integrity": "sha512-1MkgTCuvMGWuqVtAvkpkXFmtL8XhWy+j4jaSO2wxfJtilVCi0ZE37b8uOdMItIHz4I6z1bWWtEX4CJwcKYLcuA==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openharmony-arm64": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.25.9.tgz", + "integrity": "sha512-4Xd0xNiMVXKh6Fa7HEJQbrpP3m3DDn43jKxMjxLLRjWnRsfxjORYJlXPO4JNcXtOyfajXorRKY9NkOpTHptErg==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "openharmony" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/sunos-x64": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.25.9.tgz", + "integrity": "sha512-WjH4s6hzo00nNezhp3wFIAfmGZ8U7KtrJNlFMRKxiI9mxEK1scOMAaa9i4crUtu+tBr+0IN6JCuAcSBJZfnphw==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "sunos" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-arm64": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.25.9.tgz", + "integrity": "sha512-mGFrVJHmZiRqmP8xFOc6b84/7xa5y5YvR1x8djzXpJBSv/UsNK6aqec+6JDjConTgvvQefdGhFDAs2DLAds6gQ==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-ia32": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.25.9.tgz", + "integrity": "sha512-b33gLVU2k11nVx1OhX3C8QQP6UHQK4ZtN56oFWvVXvz2VkDoe6fbG8TOgHFxEvqeqohmRnIHe5A1+HADk4OQww==", + "cpu": [ + "ia32" + ], + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-x64": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.25.9.tgz", + "integrity": "sha512-PPOl1mi6lpLNQxnGoyAfschAodRFYXJ+9fs6WHXz7CSWKbOqiMZsubC+BQsVKuul+3vKLuwTHsS2c2y9EoKwxQ==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@eslint-community/eslint-utils": { + "version": "4.8.0", + "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.8.0.tgz", + "integrity": "sha512-MJQFqrZgcW0UNYLGOuQpey/oTN59vyWwplvCGZztn1cKz9agZPPYpJB7h2OMmuu7VLqkvEjN8feFZJmxNF9D+Q==", + "dev": true, + "dependencies": { + "eslint-visitor-keys": "^3.4.3" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + }, + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" + } + }, + "node_modules/@eslint-community/eslint-utils/node_modules/eslint-visitor-keys": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", + "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", + "dev": true, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/@eslint-community/regexpp": { + "version": "4.12.1", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.12.1.tgz", + "integrity": "sha512-CCZCDJuduB9OUkFkY2IgppNZMi2lBQgD2qzwXkEia16cge2pijY/aXi96CJMquDMn3nJdlPV1A5KrJEXwfLNzQ==", + "dev": true, + "engines": { + "node": "^12.0.0 || ^14.0.0 || >=16.0.0" + } + }, + "node_modules/@eslint/compat": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/@eslint/compat/-/compat-1.3.1.tgz", + "integrity": "sha512-k8MHony59I5EPic6EQTCNOuPoVBnoYXkP+20xvwFjN7t0qI3ImyvyBgg+hIVPwC8JaxVjjUZld+cLfBLFDLucg==", + "dev": true, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "peerDependencies": { + "eslint": "^8.40 || 9" + }, + "peerDependenciesMeta": { + "eslint": { + "optional": true + } + } + }, + "node_modules/@eslint/config-array": { + "version": "0.21.0", + "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.21.0.tgz", + "integrity": "sha512-ENIdc4iLu0d93HeYirvKmrzshzofPw6VkZRKQGe9Nv46ZnWUzcF1xV01dcvEg/1wXUR61OmmlSfyeyO7EvjLxQ==", + "dev": true, + "dependencies": { + "@eslint/object-schema": "^2.1.6", + "debug": "^4.3.1", + "minimatch": "^3.1.2" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@eslint/config-helpers": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/@eslint/config-helpers/-/config-helpers-0.3.1.tgz", + "integrity": "sha512-xR93k9WhrDYpXHORXpxVL5oHj3Era7wo6k/Wd8/IsQNnZUTzkGS29lyn3nAT05v6ltUuTFVCCYDEGfy2Or/sPA==", + "dev": true, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@eslint/core": { + "version": "0.15.2", + "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.15.2.tgz", + "integrity": "sha512-78Md3/Rrxh83gCxoUc0EiciuOHsIITzLy53m3d9UyiW8y9Dj2D29FeETqyKA+BRK76tnTp6RXWb3pCay8Oyomg==", + "dev": true, + "dependencies": { + "@types/json-schema": "^7.0.15" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@eslint/eslintrc": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-3.3.1.tgz", + "integrity": "sha512-gtF186CXhIl1p4pJNGZw8Yc6RlshoePRvE0X91oPGb3vZ8pM3qOS9W9NGPat9LziaBV7XrJWGylNQXkGcnM3IQ==", + "dev": true, + "dependencies": { + "ajv": "^6.12.4", + "debug": "^4.3.2", + "espree": "^10.0.1", + "globals": "^14.0.0", + "ignore": "^5.2.0", + "import-fresh": "^3.2.1", + "js-yaml": "^4.1.0", + "minimatch": "^3.1.2", + "strip-json-comments": "^3.1.1" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/@eslint/eslintrc/node_modules/globals": { + "version": "14.0.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-14.0.0.tgz", + "integrity": "sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==", + "dev": true, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@eslint/js": { + "version": "9.32.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.32.0.tgz", + "integrity": "sha512-BBpRFZK3eX6uMLKz8WxFOBIFFcGFJ/g8XuwjTHCqHROSIsopI+ddn/d5Cfh36+7+e5edVS8dbSHnBNhrLEX0zg==", + "dev": true, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://eslint.org/donate" + } + }, + "node_modules/@eslint/object-schema": { + "version": "2.1.6", + "resolved": "https://registry.npmjs.org/@eslint/object-schema/-/object-schema-2.1.6.tgz", + "integrity": "sha512-RBMg5FRL0I0gs51M/guSAj5/e14VQ4tpZnQNWwuDT66P14I43ItmPfIZRhO9fUVIPOAQXU47atlywZ/czoqFPA==", + "dev": true, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@eslint/plugin-kit": { + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.3.5.tgz", + "integrity": "sha512-Z5kJ+wU3oA7MMIqVR9tyZRtjYPr4OC004Q4Rw7pgOKUOKkJfZ3O24nz3WYfGRpMDNmcOi3TwQOmgm7B7Tpii0w==", + "dev": true, + "dependencies": { + "@eslint/core": "^0.15.2", + "levn": "^0.4.1" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@floating-ui/core": { + "version": "1.7.3", + "resolved": "https://registry.npmjs.org/@floating-ui/core/-/core-1.7.3.tgz", + "integrity": "sha512-sGnvb5dmrJaKEZ+LDIpguvdX3bDlEllmv4/ClQ9awcmCZrlx5jQyyMWFM5kBI+EyNOCDDiKk8il0zeuX3Zlg/w==", + "dependencies": { + "@floating-ui/utils": "^0.2.10" + } + }, + "node_modules/@floating-ui/dom": { + "version": "1.7.4", + "resolved": "https://registry.npmjs.org/@floating-ui/dom/-/dom-1.7.4.tgz", + "integrity": "sha512-OOchDgh4F2CchOX94cRVqhvy7b3AFb+/rQXyswmzmGakRfkMgoWVjfnLWkRirfLEfuD4ysVW16eXzwt3jHIzKA==", + "dependencies": { + "@floating-ui/core": "^1.7.3", + "@floating-ui/utils": "^0.2.10" + } + }, + "node_modules/@floating-ui/utils": { + "version": "0.2.10", + "resolved": "https://registry.npmjs.org/@floating-ui/utils/-/utils-0.2.10.tgz", + "integrity": "sha512-aGTxbpbg8/b5JfU1HXSrbH3wXZuLPJcNEcZQFMxLs3oSzgtVu6nFPkbbGGUvBcUjKV2YyB9Wxxabo+HEH9tcRQ==" + }, + "node_modules/@humanfs/core": { + "version": "0.19.1", + "resolved": "https://registry.npmjs.org/@humanfs/core/-/core-0.19.1.tgz", + "integrity": "sha512-5DyQ4+1JEUzejeK1JGICcideyfUbGixgS9jNgex5nqkW+cY7WZhxBigmieN5Qnw9ZosSNVC9KQKyb+GUaGyKUA==", + "dev": true, + "engines": { + "node": ">=18.18.0" + } + }, + "node_modules/@humanfs/node": { + "version": "0.16.7", + "resolved": "https://registry.npmjs.org/@humanfs/node/-/node-0.16.7.tgz", + "integrity": "sha512-/zUx+yOsIrG4Y43Eh2peDeKCxlRt/gET6aHfaKpuq267qXdYDFViVHfMaLyygZOnl0kGWxFIgsBy8QFuTLUXEQ==", + "dev": true, + "dependencies": { + "@humanfs/core": "^0.19.1", + "@humanwhocodes/retry": "^0.4.0" + }, + "engines": { + "node": ">=18.18.0" + } + }, + "node_modules/@humanwhocodes/module-importer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", + "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", + "dev": true, + "engines": { + "node": ">=12.22" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } + }, + "node_modules/@humanwhocodes/retry": { + "version": "0.4.3", + "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.4.3.tgz", + "integrity": "sha512-bV0Tgo9K4hfPCek+aMAn81RppFKv2ySDQeMoSZuvTASywNTnVJCArCZE2FWqpvIatKu7VMRLWlR1EazvVhDyhQ==", + "dev": true, + "engines": { + "node": ">=18.18" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } + }, + "node_modules/@intlify/core": { + "version": "11.1.11", + "resolved": "https://registry.npmjs.org/@intlify/core/-/core-11.1.11.tgz", + "integrity": "sha512-cq3NnOQN9KSNJYcKV5YNj9IPEYi4GJbOUBy4gVbGKcxC83msSOcTvkpPq0pdMYZDqx6tPDIcr7xKT9qHjcJASQ==", + "dependencies": { + "@intlify/core-base": "11.1.11", + "@intlify/shared": "11.1.11" + }, + "engines": { + "node": ">= 16" + }, + "funding": { + "url": "https://github.com/sponsors/kazupon" + } + }, + "node_modules/@intlify/core-base": { + "version": "11.1.11", + "resolved": "https://registry.npmjs.org/@intlify/core-base/-/core-base-11.1.11.tgz", + "integrity": "sha512-1Z0N8jTfkcD2Luq9HNZt+GmjpFe4/4PpZF3AOzoO1u5PTtSuXZcfhwBatywbfE2ieB/B5QHIoOFmCXY2jqVKEQ==", + "dependencies": { + "@intlify/message-compiler": "11.1.11", + "@intlify/shared": "11.1.11" + }, + "engines": { + "node": ">= 16" + }, + "funding": { + "url": "https://github.com/sponsors/kazupon" + } + }, + "node_modules/@intlify/message-compiler": { + "version": "11.1.11", + "resolved": "https://registry.npmjs.org/@intlify/message-compiler/-/message-compiler-11.1.11.tgz", + "integrity": "sha512-7PC6neomoc/z7a8JRjPBbu0T2TzR2MQuY5kn2e049MP7+o32Ve7O8husylkA7K9fQRe4iNXZWTPnDJ6vZdtS1Q==", + "dependencies": { + "@intlify/shared": "11.1.11", + "source-map-js": "^1.0.2" + }, + "engines": { + "node": ">= 16" + }, + "funding": { + "url": "https://github.com/sponsors/kazupon" + } + }, + "node_modules/@intlify/shared": { + "version": "11.1.11", + "resolved": "https://registry.npmjs.org/@intlify/shared/-/shared-11.1.11.tgz", + "integrity": "sha512-RIBFTIqxZSsxUqlcyoR7iiC632bq7kkOwYvZlvcVObHfrF4NhuKc4FKvu8iPCrEO+e3XsY7/UVpfgzg+M7ETzA==", + "engines": { + "node": ">= 16" + }, + "funding": { + "url": "https://github.com/sponsors/kazupon" + } + }, + "node_modules/@isaacs/cliui": { + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", + "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==", + "dev": true, + "dependencies": { + "string-width": "^5.1.2", + "string-width-cjs": "npm:string-width@^4.2.0", + "strip-ansi": "^7.0.1", + "strip-ansi-cjs": "npm:strip-ansi@^6.0.1", + "wrap-ansi": "^8.1.0", + "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@isaacs/cliui/node_modules/ansi-styles": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", + "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/@isaacs/cliui/node_modules/emoji-regex": { + "version": "9.2.2", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", + "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", + "dev": true + }, + "node_modules/@isaacs/cliui/node_modules/string-width": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", + "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", + "dev": true, + "dependencies": { + "eastasianwidth": "^0.2.0", + "emoji-regex": "^9.2.2", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@isaacs/cliui/node_modules/wrap-ansi": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz", + "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==", + "dev": true, + "dependencies": { + "ansi-styles": "^6.1.0", + "string-width": "^5.0.1", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/@istanbuljs/schema": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/@istanbuljs/schema/-/schema-0.1.3.tgz", + "integrity": "sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/@jridgewell/gen-mapping": { + "version": "0.3.13", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.13.tgz", + "integrity": "sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==", + "dev": true, + "dependencies": { + "@jridgewell/sourcemap-codec": "^1.5.0", + "@jridgewell/trace-mapping": "^0.3.24" + } + }, + "node_modules/@jridgewell/remapping": { + "version": "2.3.5", + "resolved": "https://registry.npmjs.org/@jridgewell/remapping/-/remapping-2.3.5.tgz", + "integrity": "sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ==", + "dev": true, + "dependencies": { + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.24" + } + }, + "node_modules/@jridgewell/resolve-uri": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", + "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", + "dev": true, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.5.5", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz", + "integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==" + }, + "node_modules/@jridgewell/trace-mapping": { + "version": "0.3.30", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.30.tgz", + "integrity": "sha512-GQ7Nw5G2lTu/BtHTKfXhKHok2WGetd4XYcVKGx00SjAk8GMwgJM3zr6zORiPGuOE+/vkc90KtTosSSvaCjKb2Q==", + "dev": true, + "dependencies": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + }, + "node_modules/@mdi/font": { + "version": "7.4.47", + "resolved": "https://registry.npmjs.org/@mdi/font/-/font-7.4.47.tgz", + "integrity": "sha512-43MtGpd585SNzHZPcYowu/84Vz2a2g31TvPMTm9uTiCSWzaheQySUcSyUH/46fPnuPQWof2yd0pGBtzee/IQWw==" + }, + "node_modules/@nicolo-ribaudo/eslint-scope-5-internals": { + "version": "5.1.1-v1", + "resolved": "https://registry.npmjs.org/@nicolo-ribaudo/eslint-scope-5-internals/-/eslint-scope-5-internals-5.1.1-v1.tgz", + "integrity": "sha512-54/JRvkLIzzDWshCWfuhadfrfZVPiElY8Fcgmg1HroEly/EDSszzhBAsarCux+D/kOslTRquNzuyGSmUSTTHGg==", + "dev": true, + "dependencies": { + "eslint-scope": "5.1.1" + } + }, + "node_modules/@one-ini/wasm": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/@one-ini/wasm/-/wasm-0.1.1.tgz", + "integrity": "sha512-XuySG1E38YScSJoMlqovLru4KTUNSjgVTIjyh7qMX6aNN5HY5Ct5LhRJdxO79JtTzKfzV/bnWpz+zquYrISsvw==", + "dev": true + }, + "node_modules/@parcel/watcher": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/@parcel/watcher/-/watcher-2.5.1.tgz", + "integrity": "sha512-dfUnCxiN9H4ap84DvD2ubjw+3vUNpstxa0TneY/Paat8a3R4uQZDLSvWjmznAY/DoahqTHl9V46HF/Zs3F29pg==", + "hasInstallScript": true, + "optional": true, + "dependencies": { + "detect-libc": "^1.0.3", + "is-glob": "^4.0.3", + "micromatch": "^4.0.5", + "node-addon-api": "^7.0.0" + }, + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + }, + "optionalDependencies": { + "@parcel/watcher-android-arm64": "2.5.1", + "@parcel/watcher-darwin-arm64": "2.5.1", + "@parcel/watcher-darwin-x64": "2.5.1", + "@parcel/watcher-freebsd-x64": "2.5.1", + "@parcel/watcher-linux-arm-glibc": "2.5.1", + "@parcel/watcher-linux-arm-musl": "2.5.1", + "@parcel/watcher-linux-arm64-glibc": "2.5.1", + "@parcel/watcher-linux-arm64-musl": "2.5.1", + "@parcel/watcher-linux-x64-glibc": "2.5.1", + "@parcel/watcher-linux-x64-musl": "2.5.1", + "@parcel/watcher-win32-arm64": "2.5.1", + "@parcel/watcher-win32-ia32": "2.5.1", + "@parcel/watcher-win32-x64": "2.5.1" + } + }, + "node_modules/@parcel/watcher-android-arm64": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/@parcel/watcher-android-arm64/-/watcher-android-arm64-2.5.1.tgz", + "integrity": "sha512-KF8+j9nNbUN8vzOFDpRMsaKBHZ/mcjEjMToVMJOhTozkDonQFFrRcfdLWn6yWKCmJKmdVxSgHiYvTCef4/qcBA==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-darwin-arm64": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/@parcel/watcher-darwin-arm64/-/watcher-darwin-arm64-2.5.1.tgz", + "integrity": "sha512-eAzPv5osDmZyBhou8PoF4i6RQXAfeKL9tjb3QzYuccXFMQU0ruIc/POh30ePnaOyD1UXdlKguHBmsTs53tVoPw==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-darwin-x64": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/@parcel/watcher-darwin-x64/-/watcher-darwin-x64-2.5.1.tgz", + "integrity": "sha512-1ZXDthrnNmwv10A0/3AJNZ9JGlzrF82i3gNQcWOzd7nJ8aj+ILyW1MTxVk35Db0u91oD5Nlk9MBiujMlwmeXZg==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-freebsd-x64": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/@parcel/watcher-freebsd-x64/-/watcher-freebsd-x64-2.5.1.tgz", + "integrity": "sha512-SI4eljM7Flp9yPuKi8W0ird8TI/JK6CSxju3NojVI6BjHsTyK7zxA9urjVjEKJ5MBYC+bLmMcbAWlZ+rFkLpJQ==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-linux-arm-glibc": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-arm-glibc/-/watcher-linux-arm-glibc-2.5.1.tgz", + "integrity": "sha512-RCdZlEyTs8geyBkkcnPWvtXLY44BCeZKmGYRtSgtwwnHR4dxfHRG3gR99XdMEdQ7KeiDdasJwwvNSF5jKtDwdA==", + "cpu": [ + "arm" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-linux-arm-musl": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-arm-musl/-/watcher-linux-arm-musl-2.5.1.tgz", + "integrity": "sha512-6E+m/Mm1t1yhB8X412stiKFG3XykmgdIOqhjWj+VL8oHkKABfu/gjFj8DvLrYVHSBNC+/u5PeNrujiSQ1zwd1Q==", + "cpu": [ + "arm" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-linux-arm64-glibc": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-arm64-glibc/-/watcher-linux-arm64-glibc-2.5.1.tgz", + "integrity": "sha512-LrGp+f02yU3BN9A+DGuY3v3bmnFUggAITBGriZHUREfNEzZh/GO06FF5u2kx8x+GBEUYfyTGamol4j3m9ANe8w==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-linux-arm64-musl": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-arm64-musl/-/watcher-linux-arm64-musl-2.5.1.tgz", + "integrity": "sha512-cFOjABi92pMYRXS7AcQv9/M1YuKRw8SZniCDw0ssQb/noPkRzA+HBDkwmyOJYp5wXcsTrhxO0zq1U11cK9jsFg==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-linux-x64-glibc": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-x64-glibc/-/watcher-linux-x64-glibc-2.5.1.tgz", + "integrity": "sha512-GcESn8NZySmfwlTsIur+49yDqSny2IhPeZfXunQi48DMugKeZ7uy1FX83pO0X22sHntJ4Ub+9k34XQCX+oHt2A==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-linux-x64-musl": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-x64-musl/-/watcher-linux-x64-musl-2.5.1.tgz", + "integrity": "sha512-n0E2EQbatQ3bXhcH2D1XIAANAcTZkQICBPVaxMeaCVBtOpBZpWJuf7LwyWPSBDITb7In8mqQgJ7gH8CILCURXg==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-win32-arm64": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/@parcel/watcher-win32-arm64/-/watcher-win32-arm64-2.5.1.tgz", + "integrity": "sha512-RFzklRvmc3PkjKjry3hLF9wD7ppR4AKcWNzH7kXR7GUe0Igb3Nz8fyPwtZCSquGrhU5HhUNDr/mKBqj7tqA2Vw==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-win32-ia32": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/@parcel/watcher-win32-ia32/-/watcher-win32-ia32-2.5.1.tgz", + "integrity": "sha512-c2KkcVN+NJmuA7CGlaGD1qJh1cLfDnQsHjE89E60vUEMlqduHGCdCLJCID5geFVM0dOtA3ZiIO8BoEQmzQVfpQ==", + "cpu": [ + "ia32" + ], + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-win32-x64": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/@parcel/watcher-win32-x64/-/watcher-win32-x64-2.5.1.tgz", + "integrity": "sha512-9lHBdJITeNR++EvSQVUcaZoWupyHfXe1jZvGZ06O/5MflPcuPLtEphScIBL+AiCWBO46tDSHzWyD0uDmmZqsgA==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@pkgjs/parseargs": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", + "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==", + "dev": true, + "optional": true, + "engines": { + "node": ">=14" + } + }, + "node_modules/@pkgr/core": { + "version": "0.2.9", + "resolved": "https://registry.npmjs.org/@pkgr/core/-/core-0.2.9.tgz", + "integrity": "sha512-QNqXyfVS2wm9hweSYD2O7F0G06uurj9kZ96TRQE5Y9hU7+tgdZwIkbAKc5Ocy1HxEY2kuDQa6cQ1WRs/O5LFKA==", + "dev": true, + "engines": { + "node": "^12.20.0 || ^14.18.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/pkgr" + } + }, + "node_modules/@react-pdf/fns": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@react-pdf/fns/-/fns-3.1.2.tgz", + "integrity": "sha512-qTKGUf0iAMGg2+OsUcp9ffKnKi41RukM/zYIWMDJ4hRVYSr89Q7e3wSDW/Koqx3ea3Uy/z3h2y3wPX6Bdfxk6g==" + }, + "node_modules/@react-pdf/font": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/@react-pdf/font/-/font-4.0.2.tgz", + "integrity": "sha512-/dAWu7Y2RD1RxarDZ9SkYPHgBYOhmcDnet4W/qN/m8k+A2Hr3ja54GymSR7GGxWBtxjKtNauVKrTa9LS1n8WUw==", + "dependencies": { + "@react-pdf/pdfkit": "^4.0.3", + "@react-pdf/types": "^2.9.0", + "fontkit": "^2.0.2", + "is-url": "^1.2.4" + } + }, + "node_modules/@react-pdf/image": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@react-pdf/image/-/image-3.0.3.tgz", + "integrity": "sha512-lvP5ryzYM3wpbO9bvqLZYwEr5XBDX9jcaRICvtnoRqdJOo7PRrMnmB4MMScyb+Xw10mGeIubZAAomNAG5ONQZQ==", + "dependencies": { + "@react-pdf/png-js": "^3.0.0", + "jay-peg": "^1.1.1" + } + }, + "node_modules/@react-pdf/layout": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/@react-pdf/layout/-/layout-4.4.0.tgz", + "integrity": "sha512-Aq+Cc6JYausWLoks2FvHe3PwK9cTuvksB2uJ0AnkKJEUtQbvCq8eCRb1bjbbwIji9OzFRTTzZij7LzkpKHjIeA==", + "dependencies": { + "@react-pdf/fns": "3.1.2", + "@react-pdf/image": "^3.0.3", + "@react-pdf/primitives": "^4.1.1", + "@react-pdf/stylesheet": "^6.1.0", + "@react-pdf/textkit": "^6.0.0", + "@react-pdf/types": "^2.9.0", + "emoji-regex": "^10.3.0", + "queue": "^6.0.1", + "yoga-layout": "^3.2.1" + } + }, + "node_modules/@react-pdf/pdfkit": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/@react-pdf/pdfkit/-/pdfkit-4.0.3.tgz", + "integrity": "sha512-k+Lsuq8vTwWsCqTp+CCB4+2N+sOTFrzwGA7aw3H9ix/PDWR9QksbmNg0YkzGbLAPI6CeawmiLHcf4trZ5ecLPQ==", + "dependencies": { + "@babel/runtime": "^7.20.13", + "@react-pdf/png-js": "^3.0.0", + "browserify-zlib": "^0.2.0", + "crypto-js": "^4.2.0", + "fontkit": "^2.0.2", + "jay-peg": "^1.1.1", + "linebreak": "^1.1.0", + "vite-compatible-readable-stream": "^3.6.1" + } + }, + "node_modules/@react-pdf/png-js": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@react-pdf/png-js/-/png-js-3.0.0.tgz", + "integrity": "sha512-eSJnEItZ37WPt6Qv5pncQDxLJRK15eaRwPT+gZoujP548CodenOVp49GST8XJvKMFt9YqIBzGBV/j9AgrOQzVA==", + "dependencies": { + "browserify-zlib": "^0.2.0" + } + }, + "node_modules/@react-pdf/primitives": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/@react-pdf/primitives/-/primitives-4.1.1.tgz", + "integrity": "sha512-IuhxYls1luJb7NUWy6q5avb1XrNaVj9bTNI40U9qGRuS6n7Hje/8H8Qi99Z9UKFV74bBP3DOf3L1wV2qZVgVrQ==" + }, + "node_modules/@react-pdf/render": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/@react-pdf/render/-/render-4.3.0.tgz", + "integrity": "sha512-MdWfWaqO6d7SZD75TZ2z5L35V+cHpyA43YNRlJNG0RJ7/MeVGDQv12y/BXOJgonZKkeEGdzM3EpAt9/g4E22WA==", + "dependencies": { + "@babel/runtime": "^7.20.13", + "@react-pdf/fns": "3.1.2", + "@react-pdf/primitives": "^4.1.1", + "@react-pdf/textkit": "^6.0.0", + "@react-pdf/types": "^2.9.0", + "abs-svg-path": "^0.1.1", + "color-string": "^1.9.1", + "normalize-svg-path": "^1.1.0", + "parse-svg-path": "^0.1.2", + "svg-arc-to-cubic-bezier": "^3.2.0" + } + }, + "node_modules/@react-pdf/stylesheet": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/@react-pdf/stylesheet/-/stylesheet-6.1.0.tgz", + "integrity": "sha512-BGZ2sYNUp38VJUegjva/jsri3iiRGnVNjWI+G9dTwAvLNOmwFvSJzqaCsEnqQ/DW5mrTBk/577FhDY7pv6AidA==", + "dependencies": { + "@react-pdf/fns": "3.1.2", + "@react-pdf/types": "^2.9.0", + "color-string": "^1.9.1", + "hsl-to-hex": "^1.0.0", + "media-engine": "^1.0.3", + "postcss-value-parser": "^4.1.0" + } + }, + "node_modules/@react-pdf/textkit": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/@react-pdf/textkit/-/textkit-6.0.0.tgz", + "integrity": "sha512-fDt19KWaJRK/n2AaFoVm31hgGmpygmTV7LsHGJNGZkgzXcFyLsx+XUl63DTDPH3iqxj3xUX128t104GtOz8tTw==", + "dependencies": { + "@react-pdf/fns": "3.1.2", + "bidi-js": "^1.0.2", + "hyphen": "^1.6.4", + "unicode-properties": "^1.4.1" + } + }, + "node_modules/@react-pdf/types": { + "version": "2.9.0", + "resolved": "https://registry.npmjs.org/@react-pdf/types/-/types-2.9.0.tgz", + "integrity": "sha512-ckj80vZLlvl9oYrQ4tovEaqKWP3O06Eb1D48/jQWbdwz1Yh7Y9v1cEmwlP8ET+a1Whp8xfdM0xduMexkuPANCQ==", + "dependencies": { + "@react-pdf/font": "^4.0.2", + "@react-pdf/primitives": "^4.1.1", + "@react-pdf/stylesheet": "^6.1.0" + } + }, + "node_modules/@remirror/core-constants": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@remirror/core-constants/-/core-constants-3.0.0.tgz", + "integrity": "sha512-42aWfPrimMfDKDi4YegyS7x+/0tlzaqwPQCULLanv3DMIlu96KTJR0fM5isWX2UViOqlGnX6YFgqWepcX+XMNg==", + "peer": true + }, + "node_modules/@rolldown/pluginutils": { + "version": "1.0.0-beta.29", + "resolved": "https://registry.npmjs.org/@rolldown/pluginutils/-/pluginutils-1.0.0-beta.29.tgz", + "integrity": "sha512-NIJgOsMjbxAXvoGq/X0gD7VPMQ8j9g0BiDaNjVNVjvl+iKXxL3Jre0v31RmBYeLEmkbj2s02v8vFTbUXi5XS2Q==", + "dev": true + }, + "node_modules/@rollup/rollup-android-arm-eabi": { + "version": "4.50.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.50.0.tgz", + "integrity": "sha512-lVgpeQyy4fWN5QYebtW4buT/4kn4p4IJ+kDNB4uYNT5b8c8DLJDg6titg20NIg7E8RWwdWZORW6vUFfrLyG3KQ==", + "cpu": [ + "arm" + ], + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@rollup/rollup-android-arm64": { + "version": "4.50.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.50.0.tgz", + "integrity": "sha512-2O73dR4Dc9bp+wSYhviP6sDziurB5/HCym7xILKifWdE9UsOe2FtNcM+I4xZjKrfLJnq5UR8k9riB87gauiQtw==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@rollup/rollup-darwin-arm64": { + "version": "4.50.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.50.0.tgz", + "integrity": "sha512-vwSXQN8T4sKf1RHr1F0s98Pf8UPz7pS6P3LG9NSmuw0TVh7EmaE+5Ny7hJOZ0M2yuTctEsHHRTMi2wuHkdS6Hg==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@rollup/rollup-darwin-x64": { + "version": "4.50.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.50.0.tgz", + "integrity": "sha512-cQp/WG8HE7BCGyFVuzUg0FNmupxC+EPZEwWu2FCGGw5WDT1o2/YlENbm5e9SMvfDFR6FRhVCBePLqj0o8MN7Vw==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@rollup/rollup-freebsd-arm64": { + "version": "4.50.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.50.0.tgz", + "integrity": "sha512-UR1uTJFU/p801DvvBbtDD7z9mQL8J80xB0bR7DqW7UGQHRm/OaKzp4is7sQSdbt2pjjSS72eAtRh43hNduTnnQ==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "freebsd" + ] + }, + "node_modules/@rollup/rollup-freebsd-x64": { + "version": "4.50.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.50.0.tgz", + "integrity": "sha512-G/DKyS6PK0dD0+VEzH/6n/hWDNPDZSMBmqsElWnCRGrYOb2jC0VSupp7UAHHQ4+QILwkxSMaYIbQ72dktp8pKA==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "freebsd" + ] + }, + "node_modules/@rollup/rollup-linux-arm-gnueabihf": { + "version": "4.50.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.50.0.tgz", + "integrity": "sha512-u72Mzc6jyJwKjJbZZcIYmd9bumJu7KNmHYdue43vT1rXPm2rITwmPWF0mmPzLm9/vJWxIRbao/jrQmxTO0Sm9w==", + "cpu": [ + "arm" + ], + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm-musleabihf": { + "version": "4.50.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.50.0.tgz", + "integrity": "sha512-S4UefYdV0tnynDJV1mdkNawp0E5Qm2MtSs330IyHgaccOFrwqsvgigUD29uT+B/70PDY1eQ3t40+xf6wIvXJyg==", + "cpu": [ + "arm" + ], + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm64-gnu": { + "version": "4.50.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.50.0.tgz", + "integrity": "sha512-1EhkSvUQXJsIhk4msxP5nNAUWoB4MFDHhtc4gAYvnqoHlaL9V3F37pNHabndawsfy/Tp7BPiy/aSa6XBYbaD1g==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm64-musl": { + "version": "4.50.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.50.0.tgz", + "integrity": "sha512-EtBDIZuDtVg75xIPIK1l5vCXNNCIRM0OBPUG+tbApDuJAy9mKago6QxX+tfMzbCI6tXEhMuZuN1+CU8iDW+0UQ==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-loongarch64-gnu": { + "version": "4.50.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loongarch64-gnu/-/rollup-linux-loongarch64-gnu-4.50.0.tgz", + "integrity": "sha512-BGYSwJdMP0hT5CCmljuSNx7+k+0upweM2M4YGfFBjnFSZMHOLYR0gEEj/dxyYJ6Zc6AiSeaBY8dWOa11GF/ppQ==", + "cpu": [ + "loong64" + ], + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-ppc64-gnu": { + "version": "4.50.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.50.0.tgz", + "integrity": "sha512-I1gSMzkVe1KzAxKAroCJL30hA4DqSi+wGc5gviD0y3IL/VkvcnAqwBf4RHXHyvH66YVHxpKO8ojrgc4SrWAnLg==", + "cpu": [ + "ppc64" + ], + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-riscv64-gnu": { + "version": "4.50.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.50.0.tgz", + "integrity": "sha512-bSbWlY3jZo7molh4tc5dKfeSxkqnf48UsLqYbUhnkdnfgZjgufLS/NTA8PcP/dnvct5CCdNkABJ56CbclMRYCA==", + "cpu": [ + "riscv64" + ], + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-riscv64-musl": { + "version": "4.50.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.50.0.tgz", + "integrity": "sha512-LSXSGumSURzEQLT2e4sFqFOv3LWZsEF8FK7AAv9zHZNDdMnUPYH3t8ZlaeYYZyTXnsob3htwTKeWtBIkPV27iQ==", + "cpu": [ + "riscv64" + ], + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-s390x-gnu": { + "version": "4.50.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.50.0.tgz", + "integrity": "sha512-CxRKyakfDrsLXiCyucVfVWVoaPA4oFSpPpDwlMcDFQvrv3XY6KEzMtMZrA+e/goC8xxp2WSOxHQubP8fPmmjOQ==", + "cpu": [ + "s390x" + ], + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-x64-gnu": { + "version": "4.50.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.50.0.tgz", + "integrity": "sha512-8PrJJA7/VU8ToHVEPu14FzuSAqVKyo5gg/J8xUerMbyNkWkO9j2ExBho/68RnJsMGNJq4zH114iAttgm7BZVkA==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-x64-musl": { + "version": "4.50.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.50.0.tgz", + "integrity": "sha512-SkE6YQp+CzpyOrbw7Oc4MgXFvTw2UIBElvAvLCo230pyxOLmYwRPwZ/L5lBe/VW/qT1ZgND9wJfOsdy0XptRvw==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-openharmony-arm64": { + "version": "4.50.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-openharmony-arm64/-/rollup-openharmony-arm64-4.50.0.tgz", + "integrity": "sha512-PZkNLPfvXeIOgJWA804zjSFH7fARBBCpCXxgkGDRjjAhRLOR8o0IGS01ykh5GYfod4c2yiiREuDM8iZ+pVsT+Q==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "openharmony" + ] + }, + "node_modules/@rollup/rollup-win32-arm64-msvc": { + "version": "4.50.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.50.0.tgz", + "integrity": "sha512-q7cIIdFvWQoaCbLDUyUc8YfR3Jh2xx3unO8Dn6/TTogKjfwrax9SyfmGGK6cQhKtjePI7jRfd7iRYcxYs93esg==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-ia32-msvc": { + "version": "4.50.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.50.0.tgz", + "integrity": "sha512-XzNOVg/YnDOmFdDKcxxK410PrcbcqZkBmz+0FicpW5jtjKQxcW1BZJEQOF0NJa6JO7CZhett8GEtRN/wYLYJuw==", + "cpu": [ + "ia32" + ], + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-x64-msvc": { + "version": "4.50.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.50.0.tgz", + "integrity": "sha512-xMmiWRR8sp72Zqwjgtf3QbZfF1wdh8X2ABu3EaozvZcyHJeU0r+XAnXdKgs4cCAp6ORoYoCygipYP1mjmbjrsg==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@sentry-internal/browser-utils": { + "version": "9.44.0", + "resolved": "https://registry.npmjs.org/@sentry-internal/browser-utils/-/browser-utils-9.44.0.tgz", + "integrity": "sha512-ySIXxq3xq2lhY/XPMLUtaUd6HghJUsz+S5GksuRCxv6exY6mRMjsbm7VhcAEPmY4IrhsXjnEzCONP+M7pzAc3A==", + "dependencies": { + "@sentry/core": "9.44.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@sentry-internal/feedback": { + "version": "9.44.0", + "resolved": "https://registry.npmjs.org/@sentry-internal/feedback/-/feedback-9.44.0.tgz", + "integrity": "sha512-ptA74gXPU7qV9eBuz2UUyFv+BroMrVMZD58eIG3IkRu93mAH0dhJiKmd1rhlWheXfhFhiw82WdNH9sTQj7++GA==", + "dependencies": { + "@sentry/core": "9.44.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@sentry-internal/replay": { + "version": "9.44.0", + "resolved": "https://registry.npmjs.org/@sentry-internal/replay/-/replay-9.44.0.tgz", + "integrity": "sha512-IVRbONKaoxcDItpcXV9wpNCL+T5iMnTLJv2glMULMnqU4nplhBynxjSyng1s/rpTU4PwwYYIgwkb4Z0GMIYPlg==", + "dependencies": { + "@sentry-internal/browser-utils": "9.44.0", + "@sentry/core": "9.44.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@sentry-internal/replay-canvas": { + "version": "9.44.0", + "resolved": "https://registry.npmjs.org/@sentry-internal/replay-canvas/-/replay-canvas-9.44.0.tgz", + "integrity": "sha512-JTRBlKsd46tz/bE6FE8bRsapteWwBt+4eviYZlE6Wn/QSirYOqEniibhJ8GIUIpUmHpkrvNAfIRaKJ4tXYaqGQ==", + "dependencies": { + "@sentry-internal/replay": "9.44.0", + "@sentry/core": "9.44.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@sentry/babel-plugin-component-annotate": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/@sentry/babel-plugin-component-annotate/-/babel-plugin-component-annotate-4.0.2.tgz", + "integrity": "sha512-Nr/VamvpQs6w642EI5t+qaCUGnVEro0qqk+S8XO1gc8qSdpc8kkZJFnUk7ozAr+ljYWGfVgWXrxI9lLiriLsRA==", + "dev": true, + "engines": { + "node": ">= 14" + } + }, + "node_modules/@sentry/browser": { + "version": "9.44.0", + "resolved": "https://registry.npmjs.org/@sentry/browser/-/browser-9.44.0.tgz", + "integrity": "sha512-QhZds04ta8m1SGN8jpF22kFu2SyM2FcHM2tFBaFuYTK6b7ouBII6YpYLhXulZvF+xl/pxnYsXHgyeTJ5JseITg==", + "dependencies": { + "@sentry-internal/browser-utils": "9.44.0", + "@sentry-internal/feedback": "9.44.0", + "@sentry-internal/replay": "9.44.0", + "@sentry-internal/replay-canvas": "9.44.0", + "@sentry/core": "9.44.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@sentry/bundler-plugin-core": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/@sentry/bundler-plugin-core/-/bundler-plugin-core-4.0.2.tgz", + "integrity": "sha512-LeARs8qHhEw19tk+KZd9DDV+Rh/UeapIH0+C09fTmff9p8Y82Cj89pEQ2a1rdUiF/oYIjQX45vnZscB7ra42yw==", + "dev": true, + "dependencies": { + "@babel/core": "^7.18.5", + "@sentry/babel-plugin-component-annotate": "4.0.2", + "@sentry/cli": "^2.49.0", + "dotenv": "^16.3.1", + "find-up": "^5.0.0", + "glob": "^9.3.2", + "magic-string": "0.30.8", + "unplugin": "1.0.1" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/@sentry/cli": { + "version": "2.53.0", + "resolved": "https://registry.npmjs.org/@sentry/cli/-/cli-2.53.0.tgz", + "integrity": "sha512-n2ZNb+5Z6AZKQSI0SusQ7ZzFL637mfw3Xh4C3PEyVSn9LiF683fX0TTq8OeGmNZQS4maYfS95IFD+XpydU0dEA==", + "dev": true, + "hasInstallScript": true, + "dependencies": { + "https-proxy-agent": "^5.0.0", + "node-fetch": "^2.6.7", + "progress": "^2.0.3", + "proxy-from-env": "^1.1.0", + "which": "^2.0.2" + }, + "bin": { + "sentry-cli": "bin/sentry-cli" + }, + "engines": { + "node": ">= 10" + }, + "optionalDependencies": { + "@sentry/cli-darwin": "2.53.0", + "@sentry/cli-linux-arm": "2.53.0", + "@sentry/cli-linux-arm64": "2.53.0", + "@sentry/cli-linux-i686": "2.53.0", + "@sentry/cli-linux-x64": "2.53.0", + "@sentry/cli-win32-arm64": "2.53.0", + "@sentry/cli-win32-i686": "2.53.0", + "@sentry/cli-win32-x64": "2.53.0" + } + }, + "node_modules/@sentry/cli-darwin": { + "version": "2.53.0", + "resolved": "https://registry.npmjs.org/@sentry/cli-darwin/-/cli-darwin-2.53.0.tgz", + "integrity": "sha512-NNPfpILMwKgpHiyJubHHuauMKltkrgLQ5tvMdxNpxY60jBNdo5VJtpESp4XmXlnidzV4j1z61V4ozU6ttDgt5Q==", + "dev": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@sentry/cli-linux-arm": { + "version": "2.53.0", + "resolved": "https://registry.npmjs.org/@sentry/cli-linux-arm/-/cli-linux-arm-2.53.0.tgz", + "integrity": "sha512-NdRzQ15Ht83qG0/Lyu11ciy/Hu/oXbbtJUgwzACc7bWvHQA8xEwTsehWexqn1529Kfc5EjuZ0Wmj3MHmp+jOWw==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "linux", + "freebsd", + "android" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@sentry/cli-linux-arm64": { + "version": "2.53.0", + "resolved": "https://registry.npmjs.org/@sentry/cli-linux-arm64/-/cli-linux-arm64-2.53.0.tgz", + "integrity": "sha512-xY/CZ1dVazsSCvTXzKpAgXaRqfljVfdrFaYZRUaRPf1ZJRGa3dcrivoOhSIeG/p5NdYtMvslMPY9Gm2MT0M83A==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "linux", + "freebsd", + "android" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@sentry/cli-linux-i686": { + "version": "2.53.0", + "resolved": "https://registry.npmjs.org/@sentry/cli-linux-i686/-/cli-linux-i686-2.53.0.tgz", + "integrity": "sha512-0REmBibGAB4jtqt9S6JEsFF4QybzcXHPcHtJjgMi5T0ueh952uG9wLzjSxQErCsxTKF+fL8oG0Oz5yKBuCwCCQ==", + "cpu": [ + "x86", + "ia32" + ], + "dev": true, + "optional": true, + "os": [ + "linux", + "freebsd", + "android" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@sentry/cli-linux-x64": { + "version": "2.53.0", + "resolved": "https://registry.npmjs.org/@sentry/cli-linux-x64/-/cli-linux-x64-2.53.0.tgz", + "integrity": "sha512-9UGJL+Vy5N/YL1EWPZ/dyXLkShlNaDNrzxx4G7mTS9ywjg+BIuemo6rnN7w43K1NOjObTVO6zY0FwumJ1pCyLg==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "linux", + "freebsd", + "android" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@sentry/cli-win32-arm64": { + "version": "2.53.0", + "resolved": "https://registry.npmjs.org/@sentry/cli-win32-arm64/-/cli-win32-arm64-2.53.0.tgz", + "integrity": "sha512-G1kjOjrjMBY20rQcJV2GA8KQE74ufmROCDb2GXYRfjvb1fKAsm4Oh8N5+Tqi7xEHdjQoLPkE4CNW0aH68JSUDQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@sentry/cli-win32-i686": { + "version": "2.53.0", + "resolved": "https://registry.npmjs.org/@sentry/cli-win32-i686/-/cli-win32-i686-2.53.0.tgz", + "integrity": "sha512-qbGTZUzesuUaPtY9rPXdNfwLqOZKXrJRC1zUFn52hdo6B+Dmv0m/AHwRVFHZP53Tg1NCa8bDei2K/uzRN0dUZw==", + "cpu": [ + "x86", + "ia32" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@sentry/cli-win32-x64": { + "version": "2.53.0", + "resolved": "https://registry.npmjs.org/@sentry/cli-win32-x64/-/cli-win32-x64-2.53.0.tgz", + "integrity": "sha512-1TXYxYHtwgUq5KAJt3erRzzUtPqg7BlH9T7MdSPHjJatkrr/kwZqnVe2H6Arr/5NH891vOlIeSPHBdgJUAD69g==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@sentry/core": { + "version": "9.44.0", + "resolved": "https://registry.npmjs.org/@sentry/core/-/core-9.44.0.tgz", + "integrity": "sha512-U+KBNGgq/eXIj226CPtRk+n5dx0q1xGVvbLbyfAyeek9C/wxQ3f+mvqeVqF9cx8FfrWIOeDM1F8ISH5uRkjjQg==", + "engines": { + "node": ">=18" + } + }, + "node_modules/@sentry/vite-plugin": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/@sentry/vite-plugin/-/vite-plugin-4.0.2.tgz", + "integrity": "sha512-rStdvDGj0VcJBsl2NANE3OQF5m13VCJ+2Ovs5pb2LAqOW72/1GLmef9Mo3b9BwzCjWOQIcgtllwOfSV5Pse03w==", + "dev": true, + "dependencies": { + "@sentry/bundler-plugin-core": "4.0.2", + "unplugin": "1.0.1" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/@sentry/vue": { + "version": "9.44.0", + "resolved": "https://registry.npmjs.org/@sentry/vue/-/vue-9.44.0.tgz", + "integrity": "sha512-UwO8GrZhtwiI0oWQJq8ZdcjSiK0ZYMbq3z8po49eqd+Li7wCrwImWRUB5rllX96YuWMXFKi4B3vfmuya/AmSQg==", + "dependencies": { + "@sentry/browser": "9.44.0", + "@sentry/core": "9.44.0" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "pinia": "2.x || 3.x", + "vue": "2.x || 3.x" + }, + "peerDependenciesMeta": { + "pinia": { + "optional": true + } + } + }, + "node_modules/@swc/helpers": { + "version": "0.5.17", + "resolved": "https://registry.npmjs.org/@swc/helpers/-/helpers-0.5.17.tgz", + "integrity": "sha512-5IKx/Y13RsYd+sauPb2x+U/xZikHjolzfuDgTAl/Tdf3Q8rslRvC19NKDLgAJQ6wsqADk10ntlv08nPFw/gO/A==", + "dependencies": { + "tslib": "^2.8.0" + } + }, + "node_modules/@testing-library/dom": { + "version": "10.4.1", + "resolved": "https://registry.npmjs.org/@testing-library/dom/-/dom-10.4.1.tgz", + "integrity": "sha512-o4PXJQidqJl82ckFaXUeoAW+XysPLauYI43Abki5hABd853iMhitooc6znOnczgbTYmEP6U6/y1ZyKAIsvMKGg==", + "dev": true, + "peer": true, + "dependencies": { + "@babel/code-frame": "^7.10.4", + "@babel/runtime": "^7.12.5", + "@types/aria-query": "^5.0.1", + "aria-query": "5.3.0", + "dom-accessibility-api": "^0.5.9", + "lz-string": "^1.5.0", + "picocolors": "1.1.1", + "pretty-format": "^27.0.2" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@testing-library/jest-dom": { + "version": "6.6.4", + "resolved": "https://registry.npmjs.org/@testing-library/jest-dom/-/jest-dom-6.6.4.tgz", + "integrity": "sha512-xDXgLjVunjHqczScfkCJ9iyjdNOVHvvCdqHSSxwM9L0l/wHkTRum67SDc020uAlCoqktJplgO2AAQeLP1wgqDQ==", + "dev": true, + "dependencies": { + "@adobe/css-tools": "^4.4.0", + "aria-query": "^5.0.0", + "css.escape": "^1.5.1", + "dom-accessibility-api": "^0.6.3", + "lodash": "^4.17.21", + "picocolors": "^1.1.1", + "redent": "^3.0.0" + }, + "engines": { + "node": ">=14", + "npm": ">=6", + "yarn": ">=1" + } + }, + "node_modules/@testing-library/jest-dom/node_modules/dom-accessibility-api": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/dom-accessibility-api/-/dom-accessibility-api-0.6.3.tgz", + "integrity": "sha512-7ZgogeTnjuHbo+ct10G9Ffp0mif17idi0IyWNVA/wcwcm7NPOD/WEHVP3n7n3MhXqxoIYm8d6MuZohYWIZ4T3w==", + "dev": true + }, + "node_modules/@testing-library/user-event": { + "version": "14.6.1", + "resolved": "https://registry.npmjs.org/@testing-library/user-event/-/user-event-14.6.1.tgz", + "integrity": "sha512-vq7fv0rnt+QTXgPxr5Hjc210p6YKq2kmdziLgnsZGgLJ9e6VAShx1pACLuRjd/AS/sr7phAR58OIIpf0LlmQNw==", + "dev": true, + "engines": { + "node": ">=12", + "npm": ">=6" + }, + "peerDependencies": { + "@testing-library/dom": ">=7.21.4" + } + }, + "node_modules/@testing-library/vue": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/@testing-library/vue/-/vue-8.1.0.tgz", + "integrity": "sha512-ls4RiHO1ta4mxqqajWRh8158uFObVrrtAPoxk7cIp4HrnQUj/ScKzqz53HxYpG3X6Zb7H2v+0eTGLSoy8HQ2nA==", + "dev": true, + "dependencies": { + "@babel/runtime": "^7.23.2", + "@testing-library/dom": "^9.3.3", + "@vue/test-utils": "^2.4.1" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@vue/compiler-sfc": ">= 3", + "vue": ">= 3" + }, + "peerDependenciesMeta": { + "@vue/compiler-sfc": { + "optional": true + } + } + }, + "node_modules/@testing-library/vue/node_modules/@testing-library/dom": { + "version": "9.3.4", + "resolved": "https://registry.npmjs.org/@testing-library/dom/-/dom-9.3.4.tgz", + "integrity": "sha512-FlS4ZWlp97iiNWig0Muq8p+3rVDjRiYE+YKGbAqXOu9nwJFFOdL00kFpz42M+4huzYi86vAK1sOOfyOG45muIQ==", + "dev": true, + "dependencies": { + "@babel/code-frame": "^7.10.4", + "@babel/runtime": "^7.12.5", + "@types/aria-query": "^5.0.1", + "aria-query": "5.1.3", + "chalk": "^4.1.0", + "dom-accessibility-api": "^0.5.9", + "lz-string": "^1.5.0", + "pretty-format": "^27.0.2" + }, + "engines": { + "node": ">=14" + } + }, + "node_modules/@testing-library/vue/node_modules/aria-query": { + "version": "5.1.3", + "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.1.3.tgz", + "integrity": "sha512-R5iJ5lkuHybztUfuOAznmboyjWq8O6sqNqtK7CLOqdydi54VNbORp49mb14KbWgG1QD3JFO9hJdZ+y4KutfdOQ==", + "dev": true, + "dependencies": { + "deep-equal": "^2.0.5" + } + }, + "node_modules/@tiptap/core": { + "version": "3.4.1", + "resolved": "https://registry.npmjs.org/@tiptap/core/-/core-3.4.1.tgz", + "integrity": "sha512-31TFNnejJeOL/Ds9uB2Y7EnldXsTLeM3HQ7vExKU6So1o0gdFIBV67m/CESy84lmdb2O7ZXfQVOqedJgojip6A==", + "peer": true, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/ueberdosis" + }, + "peerDependencies": { + "@tiptap/pm": "^3.4.1" + } + }, + "node_modules/@tiptap/extension-bold": { + "version": "3.0.9", + "resolved": "https://registry.npmjs.org/@tiptap/extension-bold/-/extension-bold-3.0.9.tgz", + "integrity": "sha512-rVULIFt9ZO+fO5ty9zuC3HwY3knxUw7q9JBztpKPfQQCuIJ+iQnOfB8NtI3L8hxVSxhIR1pqr8B3S/8vlpXbVg==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/ueberdosis" + }, + "peerDependencies": { + "@tiptap/core": "^3.0.9" + } + }, + "node_modules/@tiptap/extension-bubble-menu": { + "version": "3.0.9", + "resolved": "https://registry.npmjs.org/@tiptap/extension-bubble-menu/-/extension-bubble-menu-3.0.9.tgz", + "integrity": "sha512-fZQfdSbKJl3J+Yi+s8NrcLBgXHOaGVD4g+vn+orTPUlZdG9FWvEoon8DexOdK9OvYnW6QMM7kS8whOgpogVyUQ==", + "dependencies": { + "@floating-ui/dom": "^1.0.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/ueberdosis" + }, + "peerDependencies": { + "@tiptap/core": "^3.0.9", + "@tiptap/pm": "^3.0.9" + } + }, + "node_modules/@tiptap/extension-bullet-list": { + "version": "3.0.9", + "resolved": "https://registry.npmjs.org/@tiptap/extension-bullet-list/-/extension-bullet-list-3.0.9.tgz", + "integrity": "sha512-Aob5TVfrtoEzfTm3wl7lognmWia6EEilOxLihSGISCvI4FTndJg+mwhumduQeYCLWkF9i/DR87m2/3EbjR3R4Q==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/ueberdosis" + }, + "peerDependencies": { + "@tiptap/extension-list": "^3.0.9" + } + }, + "node_modules/@tiptap/extension-document": { + "version": "3.0.9", + "resolved": "https://registry.npmjs.org/@tiptap/extension-document/-/extension-document-3.0.9.tgz", + "integrity": "sha512-DB/R5e6QvuGhY8EhCkfNjR2xQfz/TOWoxfQGhDuy5U+oK3WBwCcHq9t5+nbSCMHtKfi/i49aHKDvv7TQCpuP0w==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/ueberdosis" + }, + "peerDependencies": { + "@tiptap/core": "^3.0.9" + } + }, + "node_modules/@tiptap/extension-floating-menu": { + "version": "3.4.1", + "resolved": "https://registry.npmjs.org/@tiptap/extension-floating-menu/-/extension-floating-menu-3.4.1.tgz", + "integrity": "sha512-9qGINja20Kz4XI0uESoYiwgGo+ejvDrHiSoRmd3jkDMv6fGMXj1U+HYzqhXZTV30kuQZQN8twNmbmzBu+jltYQ==", + "optional": true, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/ueberdosis" + }, + "peerDependencies": { + "@floating-ui/dom": "^1.0.0", + "@tiptap/core": "^3.4.1", + "@tiptap/pm": "^3.4.1" + } + }, + "node_modules/@tiptap/extension-hard-break": { + "version": "3.0.9", + "resolved": "https://registry.npmjs.org/@tiptap/extension-hard-break/-/extension-hard-break-3.0.9.tgz", + "integrity": "sha512-PWNYsUwVsMWt/R5/OWjfGb+7DQT0DvH+1owBimRq0pWZepg8qkz1jdPGgsRmUFyERRsXeEpgj3VaQfrgbyUfrA==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/ueberdosis" + }, + "peerDependencies": { + "@tiptap/core": "^3.0.9" + } + }, + "node_modules/@tiptap/extension-heading": { + "version": "3.0.9", + "resolved": "https://registry.npmjs.org/@tiptap/extension-heading/-/extension-heading-3.0.9.tgz", + "integrity": "sha512-LRLCIt87fvDZ5CdkinzhkCwRz5ax6FlsjJzG32MJ3wXyvVslqeLXBvH28JFUZEyzgcd/SnYmYxnef5+yvAX61g==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/ueberdosis" + }, + "peerDependencies": { + "@tiptap/core": "^3.0.9" + } + }, + "node_modules/@tiptap/extension-history": { + "version": "3.0.9", + "resolved": "https://registry.npmjs.org/@tiptap/extension-history/-/extension-history-3.0.9.tgz", + "integrity": "sha512-wTSNy85Kla77y9zSUrNEGUVkqCWK9fU+Dsq8wH1A7Xrgi7vBPGkzhy8jpA8+CYtd6xI6c9IiuZrX+x44vjBlSw==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/ueberdosis" + }, + "peerDependencies": { + "@tiptap/extensions": "^3.0.9" + } + }, + "node_modules/@tiptap/extension-italic": { + "version": "3.0.9", + "resolved": "https://registry.npmjs.org/@tiptap/extension-italic/-/extension-italic-3.0.9.tgz", + "integrity": "sha512-Gt4FbMtZerzKpit8+FvIjIQ3CBD559/FFC+kOT9y8JHlINeqWyh/bgHuaA/9/XtHphOQiA7NDwOiuPh4KIKpqA==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/ueberdosis" + }, + "peerDependencies": { + "@tiptap/core": "^3.0.9" + } + }, + "node_modules/@tiptap/extension-list": { + "version": "3.4.1", + "resolved": "https://registry.npmjs.org/@tiptap/extension-list/-/extension-list-3.4.1.tgz", + "integrity": "sha512-HyPvpBoenF+e2EwIrg+/en7axIn9MEcgLzfsm0W0U0XMXY5oAyvvfFDv827Zop6NndDvbdEHLEGE8J9IEpJw3Q==", + "peer": true, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/ueberdosis" + }, + "peerDependencies": { + "@tiptap/core": "^3.4.1", + "@tiptap/pm": "^3.4.1" + } + }, + "node_modules/@tiptap/extension-list-item": { + "version": "3.0.9", + "resolved": "https://registry.npmjs.org/@tiptap/extension-list-item/-/extension-list-item-3.0.9.tgz", + "integrity": "sha512-K+ogk1BH/eYhsK9nSTXNdIXlxQcXzty6h1QFiZNr9XmaLk+q4NZFHR5FVz3EJ7QXyw+Gv/2FQn+T2Q/GpbMxZQ==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/ueberdosis" + }, + "peerDependencies": { + "@tiptap/extension-list": "^3.0.9" + } + }, + "node_modules/@tiptap/extension-ordered-list": { + "version": "3.0.9", + "resolved": "https://registry.npmjs.org/@tiptap/extension-ordered-list/-/extension-ordered-list-3.0.9.tgz", + "integrity": "sha512-ACubdGc/y/rKPEgHTO7hDSg547wRRA+Es7c/rQgjrkpI///LBJQfixyUvNg2UNNPttNsavF/CUwhshCeo9MeBA==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/ueberdosis" + }, + "peerDependencies": { + "@tiptap/extension-list": "^3.0.9" + } + }, + "node_modules/@tiptap/extension-paragraph": { + "version": "3.0.9", + "resolved": "https://registry.npmjs.org/@tiptap/extension-paragraph/-/extension-paragraph-3.0.9.tgz", + "integrity": "sha512-K5zGg4zLxxqAG0BgtRpLvKclYSGoSSuU1Fza0M5MwUgrFA0S2q4JnLB1czQ77S4pfb3hpScIe50fwJzZmIUEQw==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/ueberdosis" + }, + "peerDependencies": { + "@tiptap/core": "^3.0.9" + } + }, + "node_modules/@tiptap/extension-placeholder": { + "version": "3.0.9", + "resolved": "https://registry.npmjs.org/@tiptap/extension-placeholder/-/extension-placeholder-3.0.9.tgz", + "integrity": "sha512-OgDVijDrNFDJpe/1/yMx6VFEmGBt0vE6ZWw5kGkM4NVfOxhRvv6mSZXio269dc9oBSjmyTISKaI1JAYVCfyJIw==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/ueberdosis" + }, + "peerDependencies": { + "@tiptap/extensions": "^3.0.9" + } + }, + "node_modules/@tiptap/extension-strike": { + "version": "3.0.9", + "resolved": "https://registry.npmjs.org/@tiptap/extension-strike/-/extension-strike-3.0.9.tgz", + "integrity": "sha512-2TBQ9P/FGe+/34ckfwP+eCdb4vbxDVZ5qD0piDIR9Ws5QI5IdtW90pNO4roxiPeRdVFrhTbFPEIuL0tg4NQRmg==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/ueberdosis" + }, + "peerDependencies": { + "@tiptap/core": "^3.0.9" + } + }, + "node_modules/@tiptap/extension-text": { + "version": "3.0.9", + "resolved": "https://registry.npmjs.org/@tiptap/extension-text/-/extension-text-3.0.9.tgz", + "integrity": "sha512-yWdz4aW1nu5YGcinxfu3FXiwMnP/7jp+s7dFXhq9m/6zhDUD2+qyUwhJfIU4Tcz+BGdVHqoNgOA3QXLMA6jyFA==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/ueberdosis" + }, + "peerDependencies": { + "@tiptap/core": "^3.0.9" + } + }, + "node_modules/@tiptap/extension-underline": { + "version": "3.0.9", + "resolved": "https://registry.npmjs.org/@tiptap/extension-underline/-/extension-underline-3.0.9.tgz", + "integrity": "sha512-xLR5NbnxlEJmvfb4Aj8wCbTmh/ycnPsSDeP8+TAsdAYxypSA6BP6G0t4d4NWreqAq+tq6QV6Eh0+YDN0G1VZxw==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/ueberdosis" + }, + "peerDependencies": { + "@tiptap/core": "^3.0.9" + } + }, + "node_modules/@tiptap/extensions": { + "version": "3.4.1", + "resolved": "https://registry.npmjs.org/@tiptap/extensions/-/extensions-3.4.1.tgz", + "integrity": "sha512-OFqcI2NwFm0pzik7yyaF/05d/j4ED3UNRVcjqwU+LdHCm7NKOChEuuyMKcqx8G6DNe9419wyKbB9fy6ykLX1lA==", + "peer": true, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/ueberdosis" + }, + "peerDependencies": { + "@tiptap/core": "^3.4.1", + "@tiptap/pm": "^3.4.1" + } + }, + "node_modules/@tiptap/pm": { + "version": "3.4.1", + "resolved": "https://registry.npmjs.org/@tiptap/pm/-/pm-3.4.1.tgz", + "integrity": "sha512-fI5WjxY9NjHdNNlfYuvQ7WBjr5LLTOHg5LQ5/n/2RTbOYwTrhmKpAJiVVFFHB6BdmOF399MtKL1GyEflkln4KQ==", + "peer": true, + "dependencies": { + "prosemirror-changeset": "^2.3.0", + "prosemirror-collab": "^1.3.1", + "prosemirror-commands": "^1.6.2", + "prosemirror-dropcursor": "^1.8.1", + "prosemirror-gapcursor": "^1.3.2", + "prosemirror-history": "^1.4.1", + "prosemirror-inputrules": "^1.4.0", + "prosemirror-keymap": "^1.2.2", + "prosemirror-markdown": "^1.13.1", + "prosemirror-menu": "^1.2.4", + "prosemirror-model": "^1.24.1", + "prosemirror-schema-basic": "^1.2.3", + "prosemirror-schema-list": "^1.5.0", + "prosemirror-state": "^1.4.3", + "prosemirror-tables": "^1.6.4", + "prosemirror-trailing-node": "^3.0.0", + "prosemirror-transform": "^1.10.2", + "prosemirror-view": "^1.38.1" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/ueberdosis" + } + }, + "node_modules/@tiptap/vue-3": { + "version": "3.0.9", + "resolved": "https://registry.npmjs.org/@tiptap/vue-3/-/vue-3-3.0.9.tgz", + "integrity": "sha512-IEhddTn2M0LbatFGkBPxfdbs+kL+xVC2GgYWWxvR/44ptXpKV4axtlH42nqh7sLj4DSBfP9jRlU6U0n6zdeMGg==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/ueberdosis" + }, + "optionalDependencies": { + "@tiptap/extension-bubble-menu": "^3.0.9", + "@tiptap/extension-floating-menu": "^3.0.9" + }, + "peerDependencies": { + "@floating-ui/dom": "^1.0.0", + "@tiptap/core": "^3.0.9", + "@tiptap/pm": "^3.0.9", + "vue": "^3.0.0" + } + }, + "node_modules/@trysound/sax": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/@trysound/sax/-/sax-0.2.0.tgz", + "integrity": "sha512-L7z9BgrNEcYyUYtF+HaEfiS5ebkh9jXqbszz7pC0hRBPaatV0XjSD3+eHrpqFemQfgwiFF0QPIarnIihIDn7OA==", + "dev": true, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/@types/aria-query": { + "version": "5.0.4", + "resolved": "https://registry.npmjs.org/@types/aria-query/-/aria-query-5.0.4.tgz", + "integrity": "sha512-rfT93uj5s0PRL7EzccGMs3brplhcrghnDoV26NqKhCAS1hVo+WdNsPvE/yb6ilfr5hi2MEk6d5EWJTKdxg8jVw==", + "dev": true + }, + "node_modules/@types/chai": { + "version": "5.2.2", + "resolved": "https://registry.npmjs.org/@types/chai/-/chai-5.2.2.tgz", + "integrity": "sha512-8kB30R7Hwqf40JPiKhVzodJs2Qc1ZJ5zuT3uzw5Hq/dhNCl3G3l83jfpdI1e20BP348+fV7VIL/+FxaXkqBmWg==", + "dev": true, + "dependencies": { + "@types/deep-eql": "*" + } + }, + "node_modules/@types/deep-eql": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/@types/deep-eql/-/deep-eql-4.0.2.tgz", + "integrity": "sha512-c9h9dVVMigMPc4bwTvC5dxqtqJZwQPePsWjPlpSOnojbor6pGqdk541lfA7AqFQr5pB1BRdq0juY9db81BwyFw==", + "dev": true + }, + "node_modules/@types/estree": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz", + "integrity": "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==", + "devOptional": true + }, + "node_modules/@types/json-schema": { + "version": "7.0.15", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", + "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==", + "dev": true + }, + "node_modules/@types/linkify-it": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/@types/linkify-it/-/linkify-it-5.0.0.tgz", + "integrity": "sha512-sVDA58zAw4eWAffKOaQH5/5j3XeayukzDk+ewSsnv3p4yJEZHCCzMDiZM8e0OUrRvmpGZ85jf4yDHkHsgBNr9Q==", + "peer": true + }, + "node_modules/@types/markdown-it": { + "version": "14.1.2", + "resolved": "https://registry.npmjs.org/@types/markdown-it/-/markdown-it-14.1.2.tgz", + "integrity": "sha512-promo4eFwuiW+TfGxhi+0x3czqTYJkG8qB17ZUJiVF10Xm7NLVRSLUsfRTU/6h1e24VvRnXCx+hG7li58lkzog==", + "peer": true, + "dependencies": { + "@types/linkify-it": "^5", + "@types/mdurl": "^2" + } + }, + "node_modules/@types/mdurl": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@types/mdurl/-/mdurl-2.0.0.tgz", + "integrity": "sha512-RGdgjQUZba5p6QEFAVx2OGb8rQDL/cPRG7GiedRzMcJ1tYnUANBncjbSB1NRGwbvjcPeikRABz2nshyPk1bhWg==", + "peer": true + }, + "node_modules/@unhead/vue": { + "version": "2.0.14", + "resolved": "https://registry.npmjs.org/@unhead/vue/-/vue-2.0.14.tgz", + "integrity": "sha512-Ym9f+Kd2Afqek2FtUHvYvK+j2uZ2vbZ6Rr9NCnNGGBMdmafAuiZpT117YGyh0ARcueL6Znia0U8ySqPsnHOZIg==", + "dependencies": { + "hookable": "^5.5.3", + "unhead": "2.0.14" + }, + "funding": { + "url": "https://github.com/sponsors/harlan-zw" + }, + "peerDependencies": { + "vue": ">=3.5.18" + } + }, + "node_modules/@vee-validate/i18n": { + "version": "4.15.1", + "resolved": "https://registry.npmjs.org/@vee-validate/i18n/-/i18n-4.15.1.tgz", + "integrity": "sha512-6ogEyxkoTr7IZk4EAUT0rD3pr34Nw/YEToez/c0DSlI1/cBeOpunSmGmoYPh32pmd3imxFPEawCB7IyFvRJSAw==" + }, + "node_modules/@vee-validate/rules": { + "version": "4.15.1", + "resolved": "https://registry.npmjs.org/@vee-validate/rules/-/rules-4.15.1.tgz", + "integrity": "sha512-2TGXq2MYt21nT8ysuxyFY/LBVQDcMPKn1hY0w3uIDmG333vzBkOtXAylmvrS93AsJ7N5coHMJjcCGG4JxCO2hQ==", + "dependencies": { + "vee-validate": "4.15.1" + } + }, + "node_modules/@vitejs/plugin-vue": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/@vitejs/plugin-vue/-/plugin-vue-6.0.1.tgz", + "integrity": "sha512-+MaE752hU0wfPFJEUAIxqw18+20euHHdxVtMvbFcOEpjEyfqXH/5DCoTHiVJ0J29EhTJdoTkjEv5YBKU9dnoTw==", + "dev": true, + "dependencies": { + "@rolldown/pluginutils": "1.0.0-beta.29" + }, + "engines": { + "node": "^20.19.0 || >=22.12.0" + }, + "peerDependencies": { + "vite": "^5.0.0 || ^6.0.0 || ^7.0.0", + "vue": "^3.2.25" + } + }, + "node_modules/@vitest/coverage-v8": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/@vitest/coverage-v8/-/coverage-v8-3.2.4.tgz", + "integrity": "sha512-EyF9SXU6kS5Ku/U82E259WSnvg6c8KTjppUncuNdm5QHpe17mwREHnjDzozC8x9MZ0xfBUFSaLkRv4TMA75ALQ==", + "dev": true, + "dependencies": { + "@ampproject/remapping": "^2.3.0", + "@bcoe/v8-coverage": "^1.0.2", + "ast-v8-to-istanbul": "^0.3.3", + "debug": "^4.4.1", + "istanbul-lib-coverage": "^3.2.2", + "istanbul-lib-report": "^3.0.1", + "istanbul-lib-source-maps": "^5.0.6", + "istanbul-reports": "^3.1.7", + "magic-string": "^0.30.17", + "magicast": "^0.3.5", + "std-env": "^3.9.0", + "test-exclude": "^7.0.1", + "tinyrainbow": "^2.0.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + }, + "peerDependencies": { + "@vitest/browser": "3.2.4", + "vitest": "3.2.4" + }, + "peerDependenciesMeta": { + "@vitest/browser": { + "optional": true + } + } + }, + "node_modules/@vitest/coverage-v8/node_modules/magic-string": { + "version": "0.30.18", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.18.tgz", + "integrity": "sha512-yi8swmWbO17qHhwIBNeeZxTceJMeBvWJaId6dyvTSOwTipqeHhMhOrz6513r1sOKnpvQ7zkhlG8tPrpilwTxHQ==", + "dev": true, + "dependencies": { + "@jridgewell/sourcemap-codec": "^1.5.5" + } + }, + "node_modules/@vitest/expect": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-3.2.4.tgz", + "integrity": "sha512-Io0yyORnB6sikFlt8QW5K7slY4OjqNX9jmJQ02QDda8lyM6B5oNgVWoSoKPac8/kgnCUzuHQKrSLtu/uOqqrig==", + "dev": true, + "dependencies": { + "@types/chai": "^5.2.2", + "@vitest/spy": "3.2.4", + "@vitest/utils": "3.2.4", + "chai": "^5.2.0", + "tinyrainbow": "^2.0.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/mocker": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/@vitest/mocker/-/mocker-3.2.4.tgz", + "integrity": "sha512-46ryTE9RZO/rfDd7pEqFl7etuyzekzEhUbTW3BvmeO/BcCMEgq59BKhek3dXDWgAj4oMK6OZi+vRr1wPW6qjEQ==", + "dev": true, + "dependencies": { + "@vitest/spy": "3.2.4", + "estree-walker": "^3.0.3", + "magic-string": "^0.30.17" + }, + "funding": { + "url": "https://opencollective.com/vitest" + }, + "peerDependencies": { + "msw": "^2.4.9", + "vite": "^5.0.0 || ^6.0.0 || ^7.0.0-0" + }, + "peerDependenciesMeta": { + "msw": { + "optional": true + }, + "vite": { + "optional": true + } + } + }, + "node_modules/@vitest/mocker/node_modules/estree-walker": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-3.0.3.tgz", + "integrity": "sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==", + "dev": true, + "dependencies": { + "@types/estree": "^1.0.0" + } + }, + "node_modules/@vitest/mocker/node_modules/magic-string": { + "version": "0.30.18", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.18.tgz", + "integrity": "sha512-yi8swmWbO17qHhwIBNeeZxTceJMeBvWJaId6dyvTSOwTipqeHhMhOrz6513r1sOKnpvQ7zkhlG8tPrpilwTxHQ==", + "dev": true, + "dependencies": { + "@jridgewell/sourcemap-codec": "^1.5.5" + } + }, + "node_modules/@vitest/pretty-format": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/@vitest/pretty-format/-/pretty-format-3.2.4.tgz", + "integrity": "sha512-IVNZik8IVRJRTr9fxlitMKeJeXFFFN0JaB9PHPGQ8NKQbGpfjlTx9zO4RefN8gp7eqjNy8nyK3NZmBzOPeIxtA==", + "dev": true, + "dependencies": { + "tinyrainbow": "^2.0.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/runner": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-3.2.4.tgz", + "integrity": "sha512-oukfKT9Mk41LreEW09vt45f8wx7DordoWUZMYdY/cyAk7w5TWkTRCNZYF7sX7n2wB7jyGAl74OxgwhPgKaqDMQ==", + "dev": true, + "dependencies": { + "@vitest/utils": "3.2.4", + "pathe": "^2.0.3", + "strip-literal": "^3.0.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/snapshot": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-3.2.4.tgz", + "integrity": "sha512-dEYtS7qQP2CjU27QBC5oUOxLE/v5eLkGqPE0ZKEIDGMs4vKWe7IjgLOeauHsR0D5YuuycGRO5oSRXnwnmA78fQ==", + "dev": true, + "dependencies": { + "@vitest/pretty-format": "3.2.4", + "magic-string": "^0.30.17", + "pathe": "^2.0.3" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/snapshot/node_modules/magic-string": { + "version": "0.30.18", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.18.tgz", + "integrity": "sha512-yi8swmWbO17qHhwIBNeeZxTceJMeBvWJaId6dyvTSOwTipqeHhMhOrz6513r1sOKnpvQ7zkhlG8tPrpilwTxHQ==", + "dev": true, + "dependencies": { + "@jridgewell/sourcemap-codec": "^1.5.5" + } + }, + "node_modules/@vitest/spy": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-3.2.4.tgz", + "integrity": "sha512-vAfasCOe6AIK70iP5UD11Ac4siNUNJ9i/9PZ3NKx07sG6sUxeag1LWdNrMWeKKYBLlzuK+Gn65Yd5nyL6ds+nw==", + "dev": true, + "dependencies": { + "tinyspy": "^4.0.3" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/utils": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-3.2.4.tgz", + "integrity": "sha512-fB2V0JFrQSMsCo9HiSq3Ezpdv4iYaXRG1Sx8edX3MwxfyNn83mKiGzOcH+Fkxt4MHxr3y42fQi1oeAInqgX2QA==", + "dev": true, + "dependencies": { + "@vitest/pretty-format": "3.2.4", + "loupe": "^3.1.4", + "tinyrainbow": "^2.0.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vue/babel-helper-vue-jsx-merge-props": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/@vue/babel-helper-vue-jsx-merge-props/-/babel-helper-vue-jsx-merge-props-1.4.0.tgz", + "integrity": "sha512-JkqXfCkUDp4PIlFdDQ0TdXoIejMtTHP67/pvxlgeY+u5k3LEdKuWZ3LK6xkxo52uDoABIVyRwqVkfLQJhk7VBA==", + "dev": true + }, + "node_modules/@vue/babel-helper-vue-transform-on": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/@vue/babel-helper-vue-transform-on/-/babel-helper-vue-transform-on-1.5.0.tgz", + "integrity": "sha512-0dAYkerNhhHutHZ34JtTl2czVQHUNWv6xEbkdF5W+Yrv5pCWsqjeORdOgbtW2I9gWlt+wBmVn+ttqN9ZxR5tzA==", + "dev": true + }, + "node_modules/@vue/babel-plugin-jsx": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/@vue/babel-plugin-jsx/-/babel-plugin-jsx-1.5.0.tgz", + "integrity": "sha512-mneBhw1oOqCd2247O0Yw/mRwC9jIGACAJUlawkmMBiNmL4dGA2eMzuNZVNqOUfYTa6vqmND4CtOPzmEEEqLKFw==", + "dev": true, + "dependencies": { + "@babel/helper-module-imports": "^7.27.1", + "@babel/helper-plugin-utils": "^7.27.1", + "@babel/plugin-syntax-jsx": "^7.27.1", + "@babel/template": "^7.27.2", + "@babel/traverse": "^7.28.0", + "@babel/types": "^7.28.2", + "@vue/babel-helper-vue-transform-on": "1.5.0", + "@vue/babel-plugin-resolve-type": "1.5.0", + "@vue/shared": "^3.5.18" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + }, + "peerDependenciesMeta": { + "@babel/core": { + "optional": true + } + } + }, + "node_modules/@vue/babel-plugin-resolve-type": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/@vue/babel-plugin-resolve-type/-/babel-plugin-resolve-type-1.5.0.tgz", + "integrity": "sha512-Wm/60o+53JwJODm4Knz47dxJnLDJ9FnKnGZJbUUf8nQRAtt6P+undLUAVU3Ha33LxOJe6IPoifRQ6F/0RrU31w==", + "dev": true, + "dependencies": { + "@babel/code-frame": "^7.27.1", + "@babel/helper-module-imports": "^7.27.1", + "@babel/helper-plugin-utils": "^7.27.1", + "@babel/parser": "^7.28.0", + "@vue/compiler-sfc": "^3.5.18" + }, + "funding": { + "url": "https://github.com/sponsors/sxzz" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@vue/babel-plugin-transform-vue-jsx": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/@vue/babel-plugin-transform-vue-jsx/-/babel-plugin-transform-vue-jsx-1.4.0.tgz", + "integrity": "sha512-Fmastxw4MMx0vlgLS4XBX0XiBbUFzoMGeVXuMV08wyOfXdikAFqBTuYPR0tlk+XskL19EzHc39SgjrPGY23JnA==", + "dev": true, + "dependencies": { + "@babel/helper-module-imports": "^7.0.0", + "@babel/plugin-syntax-jsx": "^7.2.0", + "@vue/babel-helper-vue-jsx-merge-props": "^1.4.0", + "html-tags": "^2.0.0", + "lodash.kebabcase": "^4.1.1", + "svg-tags": "^1.0.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@vue/babel-preset-app": { + "version": "5.0.9", + "resolved": "https://registry.npmjs.org/@vue/babel-preset-app/-/babel-preset-app-5.0.9.tgz", + "integrity": "sha512-0rKOF4s/AhaRMJLybxOCgXfwtYhO3pwDSL/q/W8wRs1LzmHAc77FyTXWlun6VyKiSKwSdtH7CvOiWqq+DfofdA==", + "dev": true, + "dependencies": { + "@babel/core": "^7.12.16", + "@babel/helper-compilation-targets": "^7.12.16", + "@babel/helper-module-imports": "^7.12.13", + "@babel/plugin-proposal-class-properties": "^7.12.13", + "@babel/plugin-proposal-decorators": "^7.12.13", + "@babel/plugin-syntax-dynamic-import": "^7.8.3", + "@babel/plugin-syntax-jsx": "^7.12.13", + "@babel/plugin-transform-runtime": "^7.12.15", + "@babel/preset-env": "^7.12.16", + "@babel/runtime": "^7.12.13", + "@vue/babel-plugin-jsx": "^1.0.3", + "@vue/babel-preset-jsx": "^1.1.2", + "babel-plugin-dynamic-import-node": "^2.3.3", + "core-js": "^3.8.3", + "core-js-compat": "^3.8.3", + "semver": "^7.3.4" + }, + "peerDependencies": { + "@babel/core": "*", + "core-js": "^3", + "vue": "^2 || ^3.2.13" + }, + "peerDependenciesMeta": { + "core-js": { + "optional": true + }, + "vue": { + "optional": true + } + } + }, + "node_modules/@vue/babel-preset-app/node_modules/semver": { + "version": "7.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.2.tgz", + "integrity": "sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@vue/babel-preset-jsx": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/@vue/babel-preset-jsx/-/babel-preset-jsx-1.4.0.tgz", + "integrity": "sha512-QmfRpssBOPZWL5xw7fOuHNifCQcNQC1PrOo/4fu6xlhlKJJKSA3HqX92Nvgyx8fqHZTUGMPHmFA+IDqwXlqkSA==", + "dev": true, + "dependencies": { + "@vue/babel-helper-vue-jsx-merge-props": "^1.4.0", + "@vue/babel-plugin-transform-vue-jsx": "^1.4.0", + "@vue/babel-sugar-composition-api-inject-h": "^1.4.0", + "@vue/babel-sugar-composition-api-render-instance": "^1.4.0", + "@vue/babel-sugar-functional-vue": "^1.4.0", + "@vue/babel-sugar-inject-h": "^1.4.0", + "@vue/babel-sugar-v-model": "^1.4.0", + "@vue/babel-sugar-v-on": "^1.4.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0", + "vue": "*" + }, + "peerDependenciesMeta": { + "vue": { + "optional": true + } + } + }, + "node_modules/@vue/babel-sugar-composition-api-inject-h": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/@vue/babel-sugar-composition-api-inject-h/-/babel-sugar-composition-api-inject-h-1.4.0.tgz", + "integrity": "sha512-VQq6zEddJHctnG4w3TfmlVp5FzDavUSut/DwR0xVoe/mJKXyMcsIibL42wPntozITEoY90aBV0/1d2KjxHU52g==", + "dev": true, + "dependencies": { + "@babel/plugin-syntax-jsx": "^7.2.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@vue/babel-sugar-composition-api-render-instance": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/@vue/babel-sugar-composition-api-render-instance/-/babel-sugar-composition-api-render-instance-1.4.0.tgz", + "integrity": "sha512-6ZDAzcxvy7VcnCjNdHJ59mwK02ZFuP5CnucloidqlZwVQv5CQLijc3lGpR7MD3TWFi78J7+a8J56YxbCtHgT9Q==", + "dev": true, + "dependencies": { + "@babel/plugin-syntax-jsx": "^7.2.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@vue/babel-sugar-functional-vue": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/@vue/babel-sugar-functional-vue/-/babel-sugar-functional-vue-1.4.0.tgz", + "integrity": "sha512-lTEB4WUFNzYt2In6JsoF9sAYVTo84wC4e+PoZWSgM6FUtqRJz7wMylaEhSRgG71YF+wfLD6cc9nqVeXN2rwBvw==", + "dev": true, + "dependencies": { + "@babel/plugin-syntax-jsx": "^7.2.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@vue/babel-sugar-inject-h": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/@vue/babel-sugar-inject-h/-/babel-sugar-inject-h-1.4.0.tgz", + "integrity": "sha512-muwWrPKli77uO2fFM7eA3G1lAGnERuSz2NgAxuOLzrsTlQl8W4G+wwbM4nB6iewlKbwKRae3nL03UaF5ffAPMA==", + "dev": true, + "dependencies": { + "@babel/plugin-syntax-jsx": "^7.2.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@vue/babel-sugar-v-model": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/@vue/babel-sugar-v-model/-/babel-sugar-v-model-1.4.0.tgz", + "integrity": "sha512-0t4HGgXb7WHYLBciZzN5s0Hzqan4Ue+p/3FdQdcaHAb7s5D9WZFGoSxEZHrR1TFVZlAPu1bejTKGeAzaaG3NCQ==", + "dev": true, + "dependencies": { + "@babel/plugin-syntax-jsx": "^7.2.0", + "@vue/babel-helper-vue-jsx-merge-props": "^1.4.0", + "@vue/babel-plugin-transform-vue-jsx": "^1.4.0", + "camelcase": "^5.0.0", + "html-tags": "^2.0.0", + "svg-tags": "^1.0.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@vue/babel-sugar-v-on": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/@vue/babel-sugar-v-on/-/babel-sugar-v-on-1.4.0.tgz", + "integrity": "sha512-m+zud4wKLzSKgQrWwhqRObWzmTuyzl6vOP7024lrpeJM4x2UhQtRDLgYjXAw9xBXjCwS0pP9kXjg91F9ZNo9JA==", + "dev": true, + "dependencies": { + "@babel/plugin-syntax-jsx": "^7.2.0", + "@vue/babel-plugin-transform-vue-jsx": "^1.4.0", + "camelcase": "^5.0.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@vue/compat": { + "version": "3.5.21", + "resolved": "https://registry.npmjs.org/@vue/compat/-/compat-3.5.21.tgz", + "integrity": "sha512-uakoBcdx+7qb1dv+rYJ4Bgex7fz7guWrr5Iv0gHCqdl7ijyNXyDJ0BqpZrvxDej82O+113i5LGZmIxfVMyPy/Q==", + "dependencies": { + "@babel/parser": "^7.28.3", + "estree-walker": "^2.0.2", + "source-map-js": "^1.2.1" + }, + "peerDependencies": { + "vue": "3.5.21" + } + }, + "node_modules/@vue/compiler-core": { + "version": "3.5.21", + "resolved": "https://registry.npmjs.org/@vue/compiler-core/-/compiler-core-3.5.21.tgz", + "integrity": "sha512-8i+LZ0vf6ZgII5Z9XmUvrCyEzocvWT+TeR2VBUVlzIH6Tyv57E20mPZ1bCS+tbejgUgmjrEh7q/0F0bibskAmw==", + "dependencies": { + "@babel/parser": "^7.28.3", + "@vue/shared": "3.5.21", + "entities": "^4.5.0", + "estree-walker": "^2.0.2", + "source-map-js": "^1.2.1" + } + }, + "node_modules/@vue/compiler-dom": { + "version": "3.5.21", + "resolved": "https://registry.npmjs.org/@vue/compiler-dom/-/compiler-dom-3.5.21.tgz", + "integrity": "sha512-jNtbu/u97wiyEBJlJ9kmdw7tAr5Vy0Aj5CgQmo+6pxWNQhXZDPsRr1UWPN4v3Zf82s2H3kF51IbzZ4jMWAgPlQ==", + "dependencies": { + "@vue/compiler-core": "3.5.21", + "@vue/shared": "3.5.21" + } + }, + "node_modules/@vue/compiler-sfc": { + "version": "3.5.21", + "resolved": "https://registry.npmjs.org/@vue/compiler-sfc/-/compiler-sfc-3.5.21.tgz", + "integrity": "sha512-SXlyk6I5eUGBd2v8Ie7tF6ADHE9kCR6mBEuPyH1nUZ0h6Xx6nZI29i12sJKQmzbDyr2tUHMhhTt51Z6blbkTTQ==", + "dependencies": { + "@babel/parser": "^7.28.3", + "@vue/compiler-core": "3.5.21", + "@vue/compiler-dom": "3.5.21", + "@vue/compiler-ssr": "3.5.21", + "@vue/shared": "3.5.21", + "estree-walker": "^2.0.2", + "magic-string": "^0.30.18", + "postcss": "^8.5.6", + "source-map-js": "^1.2.1" + } + }, + "node_modules/@vue/compiler-sfc/node_modules/magic-string": { + "version": "0.30.18", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.18.tgz", + "integrity": "sha512-yi8swmWbO17qHhwIBNeeZxTceJMeBvWJaId6dyvTSOwTipqeHhMhOrz6513r1sOKnpvQ7zkhlG8tPrpilwTxHQ==", + "dependencies": { + "@jridgewell/sourcemap-codec": "^1.5.5" + } + }, + "node_modules/@vue/compiler-ssr": { + "version": "3.5.21", + "resolved": "https://registry.npmjs.org/@vue/compiler-ssr/-/compiler-ssr-3.5.21.tgz", + "integrity": "sha512-vKQ5olH5edFZdf5ZrlEgSO1j1DMA4u23TVK5XR1uMhvwnYvVdDF0nHXJUblL/GvzlShQbjhZZ2uvYmDlAbgo9w==", + "dependencies": { + "@vue/compiler-dom": "3.5.21", + "@vue/shared": "3.5.21" + } + }, + "node_modules/@vue/devtools-api": { + "version": "7.7.7", + "resolved": "https://registry.npmjs.org/@vue/devtools-api/-/devtools-api-7.7.7.tgz", + "integrity": "sha512-lwOnNBH2e7x1fIIbVT7yF5D+YWhqELm55/4ZKf45R9T8r9dE2AIOy8HKjfqzGsoTHFbWbr337O4E0A0QADnjBg==", + "dependencies": { + "@vue/devtools-kit": "^7.7.7" + } + }, + "node_modules/@vue/devtools-kit": { + "version": "7.7.7", + "resolved": "https://registry.npmjs.org/@vue/devtools-kit/-/devtools-kit-7.7.7.tgz", + "integrity": "sha512-wgoZtxcTta65cnZ1Q6MbAfePVFxfM+gq0saaeytoph7nEa7yMXoi6sCPy4ufO111B9msnw0VOWjPEFCXuAKRHA==", + "dependencies": { + "@vue/devtools-shared": "^7.7.7", + "birpc": "^2.3.0", + "hookable": "^5.5.3", + "mitt": "^3.0.1", + "perfect-debounce": "^1.0.0", + "speakingurl": "^14.0.1", + "superjson": "^2.2.2" + } + }, + "node_modules/@vue/devtools-shared": { + "version": "7.7.7", + "resolved": "https://registry.npmjs.org/@vue/devtools-shared/-/devtools-shared-7.7.7.tgz", + "integrity": "sha512-+udSj47aRl5aKb0memBvcUG9koarqnxNM5yjuREvqwK6T3ap4mn3Zqqc17QrBFTqSMjr3HK1cvStEZpMDpfdyw==", + "dependencies": { + "rfdc": "^1.4.1" + } + }, + "node_modules/@vue/eslint-config-prettier": { + "version": "10.2.0", + "resolved": "https://registry.npmjs.org/@vue/eslint-config-prettier/-/eslint-config-prettier-10.2.0.tgz", + "integrity": "sha512-GL3YBLwv/+b86yHcNNfPJxOTtVFJ4Mbc9UU3zR+KVoG7SwGTjPT+32fXamscNumElhcpXW3mT0DgzS9w32S7Bw==", + "dev": true, + "dependencies": { + "eslint-config-prettier": "^10.0.1", + "eslint-plugin-prettier": "^5.2.2" + }, + "peerDependencies": { + "eslint": ">= 8.21.0", + "prettier": ">= 3.0.0" + } + }, + "node_modules/@vue/reactivity": { + "version": "3.5.21", + "resolved": "https://registry.npmjs.org/@vue/reactivity/-/reactivity-3.5.21.tgz", + "integrity": "sha512-3ah7sa+Cwr9iiYEERt9JfZKPw4A2UlbY8RbbnH2mGCE8NwHkhmlZt2VsH0oDA3P08X3jJd29ohBDtX+TbD9AsA==", + "dependencies": { + "@vue/shared": "3.5.21" + } + }, + "node_modules/@vue/runtime-core": { + "version": "3.5.21", + "resolved": "https://registry.npmjs.org/@vue/runtime-core/-/runtime-core-3.5.21.tgz", + "integrity": "sha512-+DplQlRS4MXfIf9gfD1BOJpk5RSyGgGXD/R+cumhe8jdjUcq/qlxDawQlSI8hCKupBlvM+3eS1se5xW+SuNAwA==", + "dependencies": { + "@vue/reactivity": "3.5.21", + "@vue/shared": "3.5.21" + } + }, + "node_modules/@vue/runtime-dom": { + "version": "3.5.21", + "resolved": "https://registry.npmjs.org/@vue/runtime-dom/-/runtime-dom-3.5.21.tgz", + "integrity": "sha512-3M2DZsOFwM5qI15wrMmNF5RJe1+ARijt2HM3TbzBbPSuBHOQpoidE+Pa+XEaVN+czbHf81ETRoG1ltztP2em8w==", + "dependencies": { + "@vue/reactivity": "3.5.21", + "@vue/runtime-core": "3.5.21", + "@vue/shared": "3.5.21", + "csstype": "^3.1.3" + } + }, + "node_modules/@vue/server-renderer": { + "version": "3.5.21", + "resolved": "https://registry.npmjs.org/@vue/server-renderer/-/server-renderer-3.5.21.tgz", + "integrity": "sha512-qr8AqgD3DJPJcGvLcJKQo2tAc8OnXRcfxhOJCPF+fcfn5bBGz7VCcO7t+qETOPxpWK1mgysXvVT/j+xWaHeMWA==", + "dependencies": { + "@vue/compiler-ssr": "3.5.21", + "@vue/shared": "3.5.21" + }, + "peerDependencies": { + "vue": "3.5.21" + } + }, + "node_modules/@vue/shared": { + "version": "3.5.21", + "resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.5.21.tgz", + "integrity": "sha512-+2k1EQpnYuVuu3N7atWyG3/xoFWIVJZq4Mz8XNOdScFI0etES75fbny/oU4lKWk/577P1zmg0ioYvpGEDZ3DLw==" + }, + "node_modules/@vue/test-utils": { + "version": "2.4.6", + "resolved": "https://registry.npmjs.org/@vue/test-utils/-/test-utils-2.4.6.tgz", + "integrity": "sha512-FMxEjOpYNYiFe0GkaHsnJPXFHxQ6m4t8vI/ElPGpMWxZKpmRvQ33OIrvRXemy6yha03RxhOlQuy+gZMC3CQSow==", + "dev": true, + "dependencies": { + "js-beautify": "^1.14.9", + "vue-component-type-helpers": "^2.0.0" + } + }, + "node_modules/@vuetify/loader-shared": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/@vuetify/loader-shared/-/loader-shared-2.1.1.tgz", + "integrity": "sha512-jSZTzTYaoiv8iwonFCVZQ0YYX/M+Uyl4ng+C4egMJT0Hcmh9gIxJL89qfZICDeo3g0IhqrvipW2FFKKRDMtVcA==", + "devOptional": true, + "dependencies": { + "upath": "^2.0.1" + }, + "peerDependencies": { + "vue": "^3.0.0", + "vuetify": "^3.0.0" + } + }, + "node_modules/@zxcvbn-ts/core": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@zxcvbn-ts/core/-/core-3.0.4.tgz", + "integrity": "sha512-aQeiT0F09FuJaAqNrxynlAwZ2mW/1MdXakKWNmGM1Qp/VaY6CnB/GfnMS2T8gB2231Esp1/maCWd8vTG4OuShw==", + "dependencies": { + "fastest-levenshtein": "1.0.16" + } + }, + "node_modules/@zxcvbn-ts/language-common": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@zxcvbn-ts/language-common/-/language-common-3.0.4.tgz", + "integrity": "sha512-viSNNnRYtc7ULXzxrQIVUNwHAPSXRtoIwy/Tq4XQQdIknBzw4vz36lQLF6mvhMlTIlpjoN/Z1GFu/fwiAlUSsw==" + }, + "node_modules/@zxcvbn-ts/language-de": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/@zxcvbn-ts/language-de/-/language-de-3.0.2.tgz", + "integrity": "sha512-CPl2314qWtnJl4EkeEqFbL4unP6yEAHO976ER+df8CQcKsF4FxdZYEahkleWU66dhNI2VKnmJKNMzq8QtHQKcw==" + }, + "node_modules/@zxcvbn-ts/language-en": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/@zxcvbn-ts/language-en/-/language-en-3.0.2.tgz", + "integrity": "sha512-Zp+zL+I6Un2Bj0tRXNs6VUBq3Djt+hwTwUz4dkt2qgsQz47U0/XthZ4ULrT/RxjwJRl5LwiaKOOZeOtmixHnjg==" + }, + "node_modules/@zxcvbn-ts/language-fr": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/@zxcvbn-ts/language-fr/-/language-fr-3.0.2.tgz", + "integrity": "sha512-Tj9jS/Z8mNBAD21pn8Mp4O86CPrwImysO1fM3DG+fsfk8W79/MDzqpFDBHiqpu69Uo3LPPctMHEEteakFWt4Qg==" + }, + "node_modules/@zxcvbn-ts/language-it": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/@zxcvbn-ts/language-it/-/language-it-3.0.2.tgz", + "integrity": "sha512-VMC7JJZ855wPhklADB43kxRVWpbWIsVWjvrC8EACBoNqcFyk2DLD+WeoAtazM08ovM0wi/mN+wc0Sa5iFtOtvQ==" + }, + "node_modules/abbrev": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-2.0.0.tgz", + "integrity": "sha512-6/mh1E2u2YgEsCHdY0Yx5oW+61gZU+1vXaoiHHrpKeuRNNgFvS+/jrwHiQhB5apAf5oB7UB7E19ol2R2LKH8hQ==", + "dev": true, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/abs-svg-path": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/abs-svg-path/-/abs-svg-path-0.1.1.tgz", + "integrity": "sha512-d8XPSGjfyzlXC3Xx891DJRyZfqk5JU0BJrDQcsWomFIV1/BIzPW5HDH5iDdWpqWaav0YVIEzT1RHTwWr0FFshA==" + }, + "node_modules/acorn": { + "version": "8.15.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz", + "integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==", + "dev": true, + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/acorn-jsx": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", + "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", + "dev": true, + "peerDependencies": { + "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" + } + }, + "node_modules/agent-base": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", + "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", + "dev": true, + "dependencies": { + "debug": "4" + }, + "engines": { + "node": ">= 6.0.0" + } + }, + "node_modules/ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/ansi-escapes": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-7.0.0.tgz", + "integrity": "sha512-GdYO7a61mR0fOlAsvC9/rIHf7L96sBc6dEWzeOu+KAea5bZyQRPIpojrVoI4AXGJS/ycu/fBTdLrUkA4ODrvjw==", + "dev": true, + "dependencies": { + "environment": "^1.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/anymatch": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", + "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", + "dev": true, + "dependencies": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==" + }, + "node_modules/aria-query": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.3.0.tgz", + "integrity": "sha512-b0P0sZPKtyu8HkeRAfCq0IfURZK+SuwMjY1UXGBU27wpAiTwQAIlq56IbIO+ytk/JjS1fMR14ee5WBBfKi5J6A==", + "dev": true, + "dependencies": { + "dequal": "^2.0.3" + } + }, + "node_modules/array-buffer-byte-length": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.2.tgz", + "integrity": "sha512-LHE+8BuR7RYGDKvnrmcuSq3tDcKv9OFEXQt/HpbZhY7V6h0zlUXutnAD82GiFx9rdieCMjkvtcsPqBwgUl1Iiw==", + "dev": true, + "dependencies": { + "call-bound": "^1.0.3", + "is-array-buffer": "^3.0.5" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/assert": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/assert/-/assert-2.1.0.tgz", + "integrity": "sha512-eLHpSK/Y4nhMJ07gDaAzoX/XAKS8PSaojml3M0DM4JpV1LAi5JOJ/p6H/XWrl8L+DzVEvVCW1z3vWAaB9oTsQw==", + "dependencies": { + "call-bind": "^1.0.2", + "is-nan": "^1.3.2", + "object-is": "^1.1.5", + "object.assign": "^4.1.4", + "util": "^0.12.5" + } + }, + "node_modules/assertion-error": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-2.0.1.tgz", + "integrity": "sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA==", + "dev": true, + "engines": { + "node": ">=12" + } + }, + "node_modules/ast-v8-to-istanbul": { + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/ast-v8-to-istanbul/-/ast-v8-to-istanbul-0.3.5.tgz", + "integrity": "sha512-9SdXjNheSiE8bALAQCQQuT6fgQaoxJh7IRYrRGZ8/9nv8WhJeC1aXAwN8TbaOssGOukUvyvnkgD9+Yuykvl1aA==", + "dev": true, + "dependencies": { + "@jridgewell/trace-mapping": "^0.3.30", + "estree-walker": "^3.0.3", + "js-tokens": "^9.0.1" + } + }, + "node_modules/ast-v8-to-istanbul/node_modules/estree-walker": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-3.0.3.tgz", + "integrity": "sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==", + "dev": true, + "dependencies": { + "@types/estree": "^1.0.0" + } + }, + "node_modules/ast-v8-to-istanbul/node_modules/js-tokens": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-9.0.1.tgz", + "integrity": "sha512-mxa9E9ITFOt0ban3j6L5MpjwegGz6lBQmM1IJkWeBZGcMxto50+eWdjC/52xDbS2vy0k7vIMK0Fe2wfL9OQSpQ==", + "dev": true + }, + "node_modules/asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==" + }, + "node_modules/atob": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/atob/-/atob-2.1.2.tgz", + "integrity": "sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==", + "devOptional": true, + "bin": { + "atob": "bin/atob.js" + }, + "engines": { + "node": ">= 4.5.0" + } + }, + "node_modules/autoprefixer": { + "version": "10.4.21", + "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.21.tgz", + "integrity": "sha512-O+A6LWV5LDHSJD3LjHYoNi4VLsj/Whi7k6zG12xTYaU4cQ8oxQGckXNX8cRHK5yOZ/ppVHe0ZBXGzSV9jXdVbQ==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/autoprefixer" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "dependencies": { + "browserslist": "^4.24.4", + "caniuse-lite": "^1.0.30001702", + "fraction.js": "^4.3.7", + "normalize-range": "^0.1.2", + "picocolors": "^1.1.1", + "postcss-value-parser": "^4.2.0" + }, + "bin": { + "autoprefixer": "bin/autoprefixer" + }, + "engines": { + "node": "^10 || ^12 || >=14" + }, + "peerDependencies": { + "postcss": "^8.1.0" + } + }, + "node_modules/available-typed-arrays": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.7.tgz", + "integrity": "sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==", + "dependencies": { + "possible-typed-array-names": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/axios": { + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.11.0.tgz", + "integrity": "sha512-1Lx3WLFQWm3ooKDYZD1eXmoGO9fxYQjrycfHFC8P0sCfQVXyROp0p9PFWBehewBOdCwHc+f/b8I0fMto5eSfwA==", + "dependencies": { + "follow-redirects": "^1.15.6", + "form-data": "^4.0.4", + "proxy-from-env": "^1.1.0" + } + }, + "node_modules/babel-plugin-dynamic-import-node": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/babel-plugin-dynamic-import-node/-/babel-plugin-dynamic-import-node-2.3.3.tgz", + "integrity": "sha512-jZVI+s9Zg3IqA/kdi0i6UDCybUI3aSBLnglhYbSSjKlV7yF1F/5LWv8MakQmvYpnbJDS6fcBL2KzHSxNCMtWSQ==", + "dev": true, + "dependencies": { + "object.assign": "^4.1.0" + } + }, + "node_modules/babel-plugin-polyfill-corejs2": { + "version": "0.4.14", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.4.14.tgz", + "integrity": "sha512-Co2Y9wX854ts6U8gAAPXfn0GmAyctHuK8n0Yhfjd6t30g7yvKjspvvOo9yG+z52PZRgFErt7Ka2pYnXCjLKEpg==", + "dev": true, + "dependencies": { + "@babel/compat-data": "^7.27.7", + "@babel/helper-define-polyfill-provider": "^0.6.5", + "semver": "^6.3.1" + }, + "peerDependencies": { + "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" + } + }, + "node_modules/babel-plugin-polyfill-corejs3": { + "version": "0.13.0", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.13.0.tgz", + "integrity": "sha512-U+GNwMdSFgzVmfhNm8GJUX88AadB3uo9KpJqS3FaqNIPKgySuvMb+bHPsOmmuWyIcuqZj/pzt1RUIUZns4y2+A==", + "dev": true, + "dependencies": { + "@babel/helper-define-polyfill-provider": "^0.6.5", + "core-js-compat": "^3.43.0" + }, + "peerDependencies": { + "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" + } + }, + "node_modules/babel-plugin-polyfill-regenerator": { + "version": "0.6.5", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.6.5.tgz", + "integrity": "sha512-ISqQ2frbiNU9vIJkzg7dlPpznPZ4jOiUQ1uSmB0fEHeowtN3COYRsXr/xexn64NpU13P06jc/L5TgiJXOgrbEg==", + "dev": true, + "dependencies": { + "@babel/helper-define-polyfill-provider": "^0.6.5" + }, + "peerDependencies": { + "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" + } + }, + "node_modules/babel-plugin-require-context-hook": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/babel-plugin-require-context-hook/-/babel-plugin-require-context-hook-1.0.0.tgz", + "integrity": "sha512-EMZD1563QUqLhzrqcThk759RhuNVX/ZJdrtGK6drwzgvnR+ARjWyXIHPbu+tUNaMGtPz/gQeAM2M6VUw2UiUeA==", + "dev": true + }, + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "devOptional": true + }, + "node_modules/base64-js": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", + "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/bidi-js": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/bidi-js/-/bidi-js-1.0.3.tgz", + "integrity": "sha512-RKshQI1R3YQ+n9YJz2QQ147P66ELpa1FQEg20Dk8oW9t2KgLbpDLLp9aGZ7y8WHSshDknG0bknqGw5/tyCs5tw==", + "dependencies": { + "require-from-string": "^2.0.2" + } + }, + "node_modules/binary-extensions": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz", + "integrity": "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==", + "dev": true, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/birpc": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/birpc/-/birpc-2.5.0.tgz", + "integrity": "sha512-VSWO/W6nNQdyP520F1mhf+Lc2f8pjGQOtoHHm7Ze8Go1kX7akpVIrtTa0fn+HB0QJEDVacl6aO08YE0PgXfdnQ==", + "funding": { + "url": "https://github.com/sponsors/antfu" + } + }, + "node_modules/boolbase": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz", + "integrity": "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==", + "dev": true + }, + "node_modules/brace-expansion": { + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", + "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", + "devOptional": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/braces": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", + "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", + "devOptional": true, + "dependencies": { + "fill-range": "^7.1.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/brotli": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/brotli/-/brotli-1.3.3.tgz", + "integrity": "sha512-oTKjJdShmDuGW94SyyaoQvAjf30dZaHnjJ8uAF+u2/vGJkJbJPJAT1gDiOJP5v1Zb6f9KEyW/1HpuaWIXtGHPg==", + "dependencies": { + "base64-js": "^1.1.2" + } + }, + "node_modules/browserify-zlib": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/browserify-zlib/-/browserify-zlib-0.2.0.tgz", + "integrity": "sha512-Z942RysHXmJrhqk88FmKBVq/v5tqmSkDz7p54G/MGyjMnCFFnC79XWNbg+Vta8W6Wb2qtSZTSxIGkJrRpCFEiA==", + "dependencies": { + "pako": "~1.0.5" + } + }, + "node_modules/browserslist": { + "version": "4.25.4", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.25.4.tgz", + "integrity": "sha512-4jYpcjabC606xJ3kw2QwGEZKX0Aw7sgQdZCvIK9dhVSPh76BKo+C+btT1RRofH7B+8iNpEbgGNVWiLki5q93yg==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "dependencies": { + "caniuse-lite": "^1.0.30001737", + "electron-to-chromium": "^1.5.211", + "node-releases": "^2.0.19", + "update-browserslist-db": "^1.1.3" + }, + "bin": { + "browserslist": "cli.js" + }, + "engines": { + "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" + } + }, + "node_modules/cac": { + "version": "6.7.14", + "resolved": "https://registry.npmjs.org/cac/-/cac-6.7.14.tgz", + "integrity": "sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/call-bind": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.8.tgz", + "integrity": "sha512-oKlSFMcMwpUg2ednkhQ454wfWiU/ul3CkJe/PEHcTKuiX6RpbehUiFMXu13HalGZxfUwCQzZG747YXBn1im9ww==", + "dependencies": { + "call-bind-apply-helpers": "^1.0.0", + "es-define-property": "^1.0.0", + "get-intrinsic": "^1.2.4", + "set-function-length": "^1.2.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/call-bind-apply-helpers": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz", + "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==", + "dependencies": { + "es-errors": "^1.3.0", + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/call-bound": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/call-bound/-/call-bound-1.0.4.tgz", + "integrity": "sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==", + "dependencies": { + "call-bind-apply-helpers": "^1.0.2", + "get-intrinsic": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/camelcase": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", + "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/caniuse-lite": { + "version": "1.0.30001741", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001741.tgz", + "integrity": "sha512-QGUGitqsc8ARjLdgAfxETDhRbJ0REsP6O3I96TAth/mVjh2cYzN2u+3AzPP3aVSm2FehEItaJw1xd+IGBXWeSw==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/caniuse-lite" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ] + }, + "node_modules/chai": { + "version": "5.3.3", + "resolved": "https://registry.npmjs.org/chai/-/chai-5.3.3.tgz", + "integrity": "sha512-4zNhdJD/iOjSH0A05ea+Ke6MU5mmpQcbQsSOkgdaUMJ9zTlDTD/GYlwohmIE2u0gaxHYiVHEn1Fw9mZ/ktJWgw==", + "dev": true, + "dependencies": { + "assertion-error": "^2.0.1", + "check-error": "^2.1.1", + "deep-eql": "^5.0.1", + "loupe": "^3.1.0", + "pathval": "^2.0.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/check-error": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/check-error/-/check-error-2.1.1.tgz", + "integrity": "sha512-OAlb+T7V4Op9OwdkjmguYRqncdlx5JiofwOAUkmTF+jNdHwzTaTs4sRAGpzLF3oOz5xAyDGrPgeIDFQmDOTiJw==", + "dev": true, + "engines": { + "node": ">= 16" + } + }, + "node_modules/cheerio": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/cheerio/-/cheerio-1.1.2.tgz", + "integrity": "sha512-IkxPpb5rS/d1IiLbHMgfPuS0FgiWTtFIm/Nj+2woXDLTZ7fOT2eqzgYbdMlLweqlHbsZjxEChoVK+7iph7jyQg==", + "dev": true, + "dependencies": { + "cheerio-select": "^2.1.0", + "dom-serializer": "^2.0.0", + "domhandler": "^5.0.3", + "domutils": "^3.2.2", + "encoding-sniffer": "^0.2.1", + "htmlparser2": "^10.0.0", + "parse5": "^7.3.0", + "parse5-htmlparser2-tree-adapter": "^7.1.0", + "parse5-parser-stream": "^7.1.2", + "undici": "^7.12.0", + "whatwg-mimetype": "^4.0.0" + }, + "engines": { + "node": ">=20.18.1" + }, + "funding": { + "url": "https://github.com/cheeriojs/cheerio?sponsor=1" + } + }, + "node_modules/cheerio-select": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/cheerio-select/-/cheerio-select-2.1.0.tgz", + "integrity": "sha512-9v9kG0LvzrlcungtnJtpGNxY+fzECQKhK4EGJX2vByejiMX84MFNQw4UxPJl3bFbTMw+Dfs37XaIkCwTZfLh4g==", + "dev": true, + "dependencies": { + "boolbase": "^1.0.0", + "css-select": "^5.1.0", + "css-what": "^6.1.0", + "domelementtype": "^2.3.0", + "domhandler": "^5.0.3", + "domutils": "^3.0.1" + }, + "funding": { + "url": "https://github.com/sponsors/fb55" + } + }, + "node_modules/cheerio/node_modules/entities": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/entities/-/entities-6.0.1.tgz", + "integrity": "sha512-aN97NXWF6AWBTahfVOIrB/NShkzi5H7F9r1s9mD3cDj4Ko5f2qhhVoYMibXF7GlLveb/D2ioWay8lxI97Ven3g==", + "dev": true, + "engines": { + "node": ">=0.12" + }, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, + "node_modules/cheerio/node_modules/htmlparser2": { + "version": "10.0.0", + "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-10.0.0.tgz", + "integrity": "sha512-TwAZM+zE5Tq3lrEHvOlvwgj1XLWQCtaaibSN11Q+gGBAS7Y1uZSWwXXRe4iF6OXnaq1riyQAPFOBtYc77Mxq0g==", + "dev": true, + "funding": [ + "https://github.com/fb55/htmlparser2?sponsor=1", + { + "type": "github", + "url": "https://github.com/sponsors/fb55" + } + ], + "dependencies": { + "domelementtype": "^2.3.0", + "domhandler": "^5.0.3", + "domutils": "^3.2.1", + "entities": "^6.0.0" + } + }, + "node_modules/chokidar": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-4.0.3.tgz", + "integrity": "sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA==", + "devOptional": true, + "dependencies": { + "readdirp": "^4.0.1" + }, + "engines": { + "node": ">= 14.16.0" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/cli-cursor": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-5.0.0.tgz", + "integrity": "sha512-aCj4O5wKyszjMmDT4tZj93kxyydN/K5zPWSCe6/0AV/AA1pqe5ZBIw0a2ZfPQV7lL5/yb5HsUreJ6UFAF1tEQw==", + "dev": true, + "dependencies": { + "restore-cursor": "^5.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/cli-truncate": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/cli-truncate/-/cli-truncate-4.0.0.tgz", + "integrity": "sha512-nPdaFdQ0h/GEigbPClz11D0v/ZJEwxmeVZGeMo3Z5StPtUTkA9o1lD6QwoirYiSDzbcwn2XcjwmCp68W1IS4TA==", + "dev": true, + "dependencies": { + "slice-ansi": "^5.0.0", + "string-width": "^7.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/clone": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/clone/-/clone-2.1.2.tgz", + "integrity": "sha512-3Pe/CF1Nn94hyhIYpjtiLhdCoEoz0DqQ+988E9gmeEdQZlojxnOb74wctFyuwWQHzqyf9X7C7MG8juUpqBJT8w==", + "engines": { + "node": ">=0.8" + } + }, + "node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + }, + "node_modules/color-string": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/color-string/-/color-string-1.9.1.tgz", + "integrity": "sha512-shrVawQFojnZv6xM40anx4CkoDP+fZsw/ZerEMsW/pyzsRbElpsL/DBVW7q3ExxwusdNXI3lXpuhEZkzs8p5Eg==", + "dependencies": { + "color-name": "^1.0.0", + "simple-swizzle": "^0.2.2" + } + }, + "node_modules/colorette": { + "version": "2.0.20", + "resolved": "https://registry.npmjs.org/colorette/-/colorette-2.0.20.tgz", + "integrity": "sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==", + "dev": true + }, + "node_modules/colorjs.io": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/colorjs.io/-/colorjs.io-0.5.2.tgz", + "integrity": "sha512-twmVoizEW7ylZSN32OgKdXRmo1qg+wT5/6C3xu5b9QsWzSFAhHLn2xd8ro0diCsKfCj1RdaTP/nrcW+vAoQPIw==" + }, + "node_modules/combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "dependencies": { + "delayed-stream": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/comlink": { + "version": "4.4.2", + "resolved": "https://registry.npmjs.org/comlink/-/comlink-4.4.2.tgz", + "integrity": "sha512-OxGdvBmJuNKSCMO4NTl1L47VRp6xn2wG4F/2hYzB6tiCb709otOxtEYCSvK80PtjODfXXZu8ds+Nw5kVCjqd2g==" + }, + "node_modules/commander": { + "version": "10.0.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-10.0.1.tgz", + "integrity": "sha512-y4Mg2tXshplEbSGzx7amzPwKKOCGuoSRP/CjEdwwk0FOGlUbq6lKuoyDZTNZkmxHdJtp54hdfY/JUrdL7Xfdug==", + "dev": true, + "engines": { + "node": ">=14" + } + }, + "node_modules/concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", + "devOptional": true + }, + "node_modules/confbox": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/confbox/-/confbox-0.2.2.tgz", + "integrity": "sha512-1NB+BKqhtNipMsov4xI/NnhCKp9XG9NamYp5PVm9klAT0fsrNPjaFICsCFhNhwZJKNh7zB/3q8qXz0E9oaMNtQ==", + "dev": true + }, + "node_modules/config-chain": { + "version": "1.1.13", + "resolved": "https://registry.npmjs.org/config-chain/-/config-chain-1.1.13.tgz", + "integrity": "sha512-qj+f8APARXHrM0hraqXYb2/bOVSV4PvJQlNZ/DVj0QrmNM2q2euizkeuVckQ57J+W0mRH6Hvi+k50M4Jul2VRQ==", + "dev": true, + "dependencies": { + "ini": "^1.3.4", + "proto-list": "~1.2.1" + } + }, + "node_modules/convert-source-map": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", + "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", + "dev": true + }, + "node_modules/copy-anything": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/copy-anything/-/copy-anything-3.0.5.tgz", + "integrity": "sha512-yCEafptTtb4bk7GLEQoM8KVJpxAfdBJYaXyzQEgQQQgYrZiDp8SJmGKlYza6CYjEDNstAdNdKA3UuoULlEbS6w==", + "dependencies": { + "is-what": "^4.1.8" + }, + "engines": { + "node": ">=12.13" + }, + "funding": { + "url": "https://github.com/sponsors/mesqueeb" + } + }, + "node_modules/core-js": { + "version": "3.45.1", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.45.1.tgz", + "integrity": "sha512-L4NPsJlCfZsPeXukyzHFlg/i7IIVwHSItR0wg0FLNqYClJ4MQYTYLbC7EkjKYRLZF2iof2MUgN0EGy7MdQFChg==", + "dev": true, + "hasInstallScript": true, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/core-js" + } + }, + "node_modules/core-js-compat": { + "version": "3.45.1", + "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.45.1.tgz", + "integrity": "sha512-tqTt5T4PzsMIZ430XGviK4vzYSoeNJ6CXODi6c/voxOT6IZqBht5/EKaSNnYiEjjRYxjVz7DQIsOsY0XNi8PIA==", + "dev": true, + "dependencies": { + "browserslist": "^4.25.3" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/core-js" + } + }, + "node_modules/crelt": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/crelt/-/crelt-1.0.6.tgz", + "integrity": "sha512-VQ2MBenTq1fWZUH9DJNGti7kKv6EeAuYr3cLwxUWhIu1baTaXh4Ib5W2CqHVqib4/MqbYGJqiL3Zb8GJZr3l4g==", + "peer": true + }, + "node_modules/cross-spawn": { + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", + "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", + "dev": true, + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/crypto-js": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/crypto-js/-/crypto-js-4.2.0.tgz", + "integrity": "sha512-KALDyEYgpY+Rlob/iriUtjV6d5Eq+Y191A5g4UqLAi8CyGP9N1+FdVbkc1SxKc2r4YAYqG8JzO2KGL+AizD70Q==" + }, + "node_modules/css": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/css/-/css-3.0.0.tgz", + "integrity": "sha512-DG9pFfwOrzc+hawpmqX/dHYHJG+Bsdb0klhyi1sDneOgGOXy9wQIC8hzyVp1e4NRYDBdxcylvywPkkXCHAzTyQ==", + "devOptional": true, + "dependencies": { + "inherits": "^2.0.4", + "source-map": "^0.6.1", + "source-map-resolve": "^0.6.0" + } + }, + "node_modules/css-select": { + "version": "5.2.2", + "resolved": "https://registry.npmjs.org/css-select/-/css-select-5.2.2.tgz", + "integrity": "sha512-TizTzUddG/xYLA3NXodFM0fSbNizXjOKhqiQQwvhlspadZokn1KDy0NZFS0wuEubIYAV5/c1/lAr0TaaFXEXzw==", + "dev": true, + "dependencies": { + "boolbase": "^1.0.0", + "css-what": "^6.1.0", + "domhandler": "^5.0.2", + "domutils": "^3.0.1", + "nth-check": "^2.0.1" + }, + "funding": { + "url": "https://github.com/sponsors/fb55" + } + }, + "node_modules/css-tree": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-2.3.1.tgz", + "integrity": "sha512-6Fv1DV/TYw//QF5IzQdqsNDjx/wc8TrMBZsqjL9eW01tWb7R7k/mq+/VXfJCl7SoD5emsJop9cOByJZfs8hYIw==", + "dev": true, + "dependencies": { + "mdn-data": "2.0.30", + "source-map-js": "^1.0.1" + }, + "engines": { + "node": "^10 || ^12.20.0 || ^14.13.0 || >=15.0.0" + } + }, + "node_modules/css-what": { + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/css-what/-/css-what-6.2.2.tgz", + "integrity": "sha512-u/O3vwbptzhMs3L1fQE82ZSLHQQfto5gyZzwteVIEyeaY5Fc7R4dapF/BvRoSYFeqfBk4m0V1Vafq5Pjv25wvA==", + "dev": true, + "engines": { + "node": ">= 6" + }, + "funding": { + "url": "https://github.com/sponsors/fb55" + } + }, + "node_modules/css.escape": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/css.escape/-/css.escape-1.5.1.tgz", + "integrity": "sha512-YUifsXXuknHlUsmlgyY0PKzgPOr7/FjCePfHNt0jxm83wHZi44VDMQ7/fGNkjY3/jV1MC+1CmZbaHzugyeRtpg==", + "dev": true + }, + "node_modules/css/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "devOptional": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/cssesc": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz", + "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==", + "dev": true, + "bin": { + "cssesc": "bin/cssesc" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/cssfontparser": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/cssfontparser/-/cssfontparser-1.2.1.tgz", + "integrity": "sha512-6tun4LoZnj7VN6YeegOVb67KBX/7JJsqvj+pv3ZA7F878/eN33AbGa5b/S/wXxS/tcp8nc40xRUrsPlxIyNUPg==", + "dev": true + }, + "node_modules/csso": { + "version": "5.0.5", + "resolved": "https://registry.npmjs.org/csso/-/csso-5.0.5.tgz", + "integrity": "sha512-0LrrStPOdJj+SPCCrGhzryycLjwcgUSHBtxNA8aIDxf0GLsRh1cKYhB00Gd1lDOS4yGH69+SNn13+TWbVHETFQ==", + "dev": true, + "dependencies": { + "css-tree": "~2.2.0" + }, + "engines": { + "node": "^10 || ^12.20.0 || ^14.13.0 || >=15.0.0", + "npm": ">=7.0.0" + } + }, + "node_modules/csso/node_modules/css-tree": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-2.2.1.tgz", + "integrity": "sha512-OA0mILzGc1kCOCSJerOeqDxDQ4HOh+G8NbOJFOTgOCzpw7fCBubk0fEyxp8AgOL/jvLgYA/uV0cMbe43ElF1JA==", + "dev": true, + "dependencies": { + "mdn-data": "2.0.28", + "source-map-js": "^1.0.1" + }, + "engines": { + "node": "^10 || ^12.20.0 || ^14.13.0 || >=15.0.0", + "npm": ">=7.0.0" + } + }, + "node_modules/csso/node_modules/mdn-data": { + "version": "2.0.28", + "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.28.tgz", + "integrity": "sha512-aylIc7Z9y4yzHYAJNuESG3hfhC+0Ibp/MAMiaOZgNv4pmEdFyfZhhhny4MNiAfWdBQ1RQ2mfDWmM1x8SvGyp8g==", + "dev": true + }, + "node_modules/cssstyle": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/cssstyle/-/cssstyle-4.6.0.tgz", + "integrity": "sha512-2z+rWdzbbSZv6/rhtvzvqeZQHrBaqgogqt85sqFNbabZOuFbCVFb8kPeEtZjiKkbrm395irpNKiYeFeLiQnFPg==", + "dev": true, + "dependencies": { + "@asamuzakjp/css-color": "^3.2.0", + "rrweb-cssom": "^0.8.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/csstype": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz", + "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==" + }, + "node_modules/data-urls": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/data-urls/-/data-urls-5.0.0.tgz", + "integrity": "sha512-ZYP5VBHshaDAiVZxjbRVcFJpc+4xGgT0bK3vzy1HLN8jTO975HEbuYzZJcHoQEY5K1a0z8YayJkyVETa08eNTg==", + "dev": true, + "dependencies": { + "whatwg-mimetype": "^4.0.0", + "whatwg-url": "^14.0.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/dayjs": { + "version": "1.11.13", + "resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.13.tgz", + "integrity": "sha512-oaMBel6gjolK862uaPQOVTA7q3TZhuSvuMQAAglQDOWYO9A91IrAOUJEyKVlqJlHE0vq5p5UXxzdPfMH/x6xNg==" + }, + "node_modules/debug": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.1.tgz", + "integrity": "sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ==", + "devOptional": true, + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/decimal.js": { + "version": "10.6.0", + "resolved": "https://registry.npmjs.org/decimal.js/-/decimal.js-10.6.0.tgz", + "integrity": "sha512-YpgQiITW3JXGntzdUmyUR1V812Hn8T1YVXhCu+wO3OpS4eU9l4YdD3qjyiKdV6mvV29zapkMeD390UVEf2lkUg==", + "dev": true + }, + "node_modules/decode-uri-component": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.2.tgz", + "integrity": "sha512-FqUYQ+8o158GyGTrMFJms9qh3CqTKvAqgqsTnkLI8sKu0028orqBhxNMFkFen0zGyg6epACD32pjVk58ngIErQ==", + "devOptional": true, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/deep-eql": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-5.0.2.tgz", + "integrity": "sha512-h5k/5U50IJJFpzfL6nO9jaaumfjO/f2NjK/oYB2Djzm4p9L+3T9qWpZqZ2hAbLPuuYq9wrU08WQyBTL5GbPk5Q==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/deep-equal": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-2.2.3.tgz", + "integrity": "sha512-ZIwpnevOurS8bpT4192sqAowWM76JDKSHYzMLty3BZGSswgq6pBaH3DhCSW5xVAZICZyKdOBPjwww5wfgT/6PA==", + "dev": true, + "dependencies": { + "array-buffer-byte-length": "^1.0.0", + "call-bind": "^1.0.5", + "es-get-iterator": "^1.1.3", + "get-intrinsic": "^1.2.2", + "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.1", + "side-channel": "^1.0.4", + "which-boxed-primitive": "^1.0.2", + "which-collection": "^1.0.1", + "which-typed-array": "^1.1.13" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/deep-is": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", + "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", + "dev": true + }, + "node_modules/deepmerge": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz", + "integrity": "sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/define-data-property": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz", + "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==", + "dependencies": { + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", + "gopd": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/define-properties": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.1.tgz", + "integrity": "sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==", + "dependencies": { + "define-data-property": "^1.0.1", + "has-property-descriptors": "^1.0.0", + "object-keys": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/dequal": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/dequal/-/dequal-2.0.3.tgz", + "integrity": "sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/detect-libc": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-1.0.3.tgz", + "integrity": "sha512-pGjwhsmsp4kL2RTz08wcOlGN83otlqHeD/Z5T8GXZB+/YcpQ/dgo+lbU8ZsGxV0HIvqqxo9l7mqYwyYMD9bKDg==", + "optional": true, + "bin": { + "detect-libc": "bin/detect-libc.js" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/dfa": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/dfa/-/dfa-1.2.0.tgz", + "integrity": "sha512-ED3jP8saaweFTjeGX8HQPjeC1YYyZs98jGNZx6IiBvxW7JG5v492kamAQB3m2wop07CvU/RQmzcKr6bgcC5D/Q==" + }, + "node_modules/dom-accessibility-api": { + "version": "0.5.16", + "resolved": "https://registry.npmjs.org/dom-accessibility-api/-/dom-accessibility-api-0.5.16.tgz", + "integrity": "sha512-X7BJ2yElsnOJ30pZF4uIIDfBEVgF4XEBxL9Bxhy6dnrm5hkzqmsWHGTiHqRiITNhMyFLyAiWndIJP7Z1NTteDg==", + "dev": true + }, + "node_modules/dom-serializer": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-2.0.0.tgz", + "integrity": "sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==", + "dev": true, + "dependencies": { + "domelementtype": "^2.3.0", + "domhandler": "^5.0.2", + "entities": "^4.2.0" + }, + "funding": { + "url": "https://github.com/cheeriojs/dom-serializer?sponsor=1" + } + }, + "node_modules/domelementtype": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.3.0.tgz", + "integrity": "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fb55" + } + ] + }, + "node_modules/domhandler": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-5.0.3.tgz", + "integrity": "sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==", + "dev": true, + "dependencies": { + "domelementtype": "^2.3.0" + }, + "engines": { + "node": ">= 4" + }, + "funding": { + "url": "https://github.com/fb55/domhandler?sponsor=1" + } + }, + "node_modules/domutils": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/domutils/-/domutils-3.2.2.tgz", + "integrity": "sha512-6kZKyUajlDuqlHKVX1w7gyslj9MPIXzIFiz/rGu35uC1wMi+kMhQwGhl4lt9unC9Vb9INnY9Z3/ZA3+FhASLaw==", + "dev": true, + "dependencies": { + "dom-serializer": "^2.0.0", + "domelementtype": "^2.3.0", + "domhandler": "^5.0.3" + }, + "funding": { + "url": "https://github.com/fb55/domutils?sponsor=1" + } + }, + "node_modules/dotenv": { + "version": "16.6.1", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.6.1.tgz", + "integrity": "sha512-uBq4egWHTcTt33a72vpSG0z3HnPuIl6NqYcTrKEg2azoEyl2hpW0zqlxysq2pK9HlDIHyHyakeYaYnSAwd8bow==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://dotenvx.com" + } + }, + "node_modules/dunder-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz", + "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==", + "dependencies": { + "call-bind-apply-helpers": "^1.0.1", + "es-errors": "^1.3.0", + "gopd": "^1.2.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/eastasianwidth": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", + "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==", + "dev": true + }, + "node_modules/editorconfig": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/editorconfig/-/editorconfig-1.0.4.tgz", + "integrity": "sha512-L9Qe08KWTlqYMVvMcTIvMAdl1cDUubzRNYL+WfA4bLDMHe4nemKkpmYzkznE1FwLKu0EEmy6obgQKzMJrg4x9Q==", + "dev": true, + "dependencies": { + "@one-ini/wasm": "0.1.1", + "commander": "^10.0.0", + "minimatch": "9.0.1", + "semver": "^7.5.3" + }, + "bin": { + "editorconfig": "bin/editorconfig" + }, + "engines": { + "node": ">=14" + } + }, + "node_modules/editorconfig/node_modules/brace-expansion": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz", + "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/editorconfig/node_modules/minimatch": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.1.tgz", + "integrity": "sha512-0jWhJpD/MdhPXwPuiRkCbfYfSKp2qnn2eOc279qI7f+osl/l+prKSrvhg157zSYvx/1nmgn2NqdT6k2Z7zSH9w==", + "dev": true, + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/editorconfig/node_modules/semver": { + "version": "7.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.2.tgz", + "integrity": "sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/electron-to-chromium": { + "version": "1.5.214", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.214.tgz", + "integrity": "sha512-TpvUNdha+X3ybfU78NoQatKvQEm1oq3lf2QbnmCEdw+Bd9RuIAY+hJTvq1avzHM0f7EJfnH3vbCnbzKzisc/9Q==", + "dev": true + }, + "node_modules/emoji-regex": { + "version": "10.4.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-10.4.0.tgz", + "integrity": "sha512-EC+0oUMY1Rqm4O6LLrgjtYDvcVYTy7chDnM4Q7030tP4Kwj3u/pR6gP9ygnp2CJMK5Gq+9Q2oqmrFJAz01DXjw==" + }, + "node_modules/encoding-sniffer": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/encoding-sniffer/-/encoding-sniffer-0.2.1.tgz", + "integrity": "sha512-5gvq20T6vfpekVtqrYQsSCFZ1wEg5+wW0/QaZMWkFr6BqD3NfKs0rLCx4rrVlSWJeZb5NBJgVLswK/w2MWU+Gw==", + "dev": true, + "dependencies": { + "iconv-lite": "^0.6.3", + "whatwg-encoding": "^3.1.1" + }, + "funding": { + "url": "https://github.com/fb55/encoding-sniffer?sponsor=1" + } + }, + "node_modules/enhanced-resolve": { + "version": "5.18.3", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.18.3.tgz", + "integrity": "sha512-d4lC8xfavMeBjzGr2vECC3fsGXziXZQyJxD868h2M/mBI3PwAuODxAkLkq5HYuvrPYcUtiLzsTo8U3PgX3Ocww==", + "dev": true, + "dependencies": { + "graceful-fs": "^4.2.4", + "tapable": "^2.2.0" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/entities": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", + "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==", + "engines": { + "node": ">=0.12" + }, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, + "node_modules/environment": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/environment/-/environment-1.1.0.tgz", + "integrity": "sha512-xUtoPkMggbz0MPyPiIWr1Kp4aeWJjDZ6SMvURhimjdZgsRuDplF5/s9hcgGhyXMhs+6vpnuoiZ2kFiu3FMnS8Q==", + "dev": true, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/es-define-property": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz", + "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-errors": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", + "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-get-iterator": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/es-get-iterator/-/es-get-iterator-1.1.3.tgz", + "integrity": "sha512-sPZmqHBe6JIiTfN5q2pEi//TwxmAFHwj/XEuYjTuse78i8KxaqMTTzxPoFKuzRpDpTJ+0NAbpfenkmH2rePtuw==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "get-intrinsic": "^1.1.3", + "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" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/es-module-lexer": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-1.7.0.tgz", + "integrity": "sha512-jEQoCwk8hyb2AZziIOLhDqpm5+2ww5uIE6lkO/6jcOCusfk6LhMHpXXfBLXTZ7Ydyt0j4VoUQv6uGNYbdW+kBA==", + "dev": true + }, + "node_modules/es-object-atoms": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz", + "integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==", + "dependencies": { + "es-errors": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-set-tostringtag": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz", + "integrity": "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==", + "dependencies": { + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.6", + "has-tostringtag": "^1.0.2", + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/esbuild": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.25.9.tgz", + "integrity": "sha512-CRbODhYyQx3qp7ZEwzxOk4JBqmD/seJrzPa/cGjY1VtIn5E09Oi9/dB4JwctnfZ8Q8iT7rioVv5k/FNT/uf54g==", + "devOptional": true, + "hasInstallScript": true, + "bin": { + "esbuild": "bin/esbuild" + }, + "engines": { + "node": ">=18" + }, + "optionalDependencies": { + "@esbuild/aix-ppc64": "0.25.9", + "@esbuild/android-arm": "0.25.9", + "@esbuild/android-arm64": "0.25.9", + "@esbuild/android-x64": "0.25.9", + "@esbuild/darwin-arm64": "0.25.9", + "@esbuild/darwin-x64": "0.25.9", + "@esbuild/freebsd-arm64": "0.25.9", + "@esbuild/freebsd-x64": "0.25.9", + "@esbuild/linux-arm": "0.25.9", + "@esbuild/linux-arm64": "0.25.9", + "@esbuild/linux-ia32": "0.25.9", + "@esbuild/linux-loong64": "0.25.9", + "@esbuild/linux-mips64el": "0.25.9", + "@esbuild/linux-ppc64": "0.25.9", + "@esbuild/linux-riscv64": "0.25.9", + "@esbuild/linux-s390x": "0.25.9", + "@esbuild/linux-x64": "0.25.9", + "@esbuild/netbsd-arm64": "0.25.9", + "@esbuild/netbsd-x64": "0.25.9", + "@esbuild/openbsd-arm64": "0.25.9", + "@esbuild/openbsd-x64": "0.25.9", + "@esbuild/openharmony-arm64": "0.25.9", + "@esbuild/sunos-x64": "0.25.9", + "@esbuild/win32-arm64": "0.25.9", + "@esbuild/win32-ia32": "0.25.9", + "@esbuild/win32-x64": "0.25.9" + } + }, + "node_modules/escalade": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", + "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint": { + "version": "9.32.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.32.0.tgz", + "integrity": "sha512-LSehfdpgMeWcTZkWZVIJl+tkZ2nuSkyyB9C27MZqFWXuph7DvaowgcTvKqxvpLW1JZIk8PN7hFY3Rj9LQ7m7lg==", + "dev": true, + "dependencies": { + "@eslint-community/eslint-utils": "^4.2.0", + "@eslint-community/regexpp": "^4.12.1", + "@eslint/config-array": "^0.21.0", + "@eslint/config-helpers": "^0.3.0", + "@eslint/core": "^0.15.0", + "@eslint/eslintrc": "^3.3.1", + "@eslint/js": "9.32.0", + "@eslint/plugin-kit": "^0.3.4", + "@humanfs/node": "^0.16.6", + "@humanwhocodes/module-importer": "^1.0.1", + "@humanwhocodes/retry": "^0.4.2", + "@types/estree": "^1.0.6", + "@types/json-schema": "^7.0.15", + "ajv": "^6.12.4", + "chalk": "^4.0.0", + "cross-spawn": "^7.0.6", + "debug": "^4.3.2", + "escape-string-regexp": "^4.0.0", + "eslint-scope": "^8.4.0", + "eslint-visitor-keys": "^4.2.1", + "espree": "^10.4.0", + "esquery": "^1.5.0", + "esutils": "^2.0.2", + "fast-deep-equal": "^3.1.3", + "file-entry-cache": "^8.0.0", + "find-up": "^5.0.0", + "glob-parent": "^6.0.2", + "ignore": "^5.2.0", + "imurmurhash": "^0.1.4", + "is-glob": "^4.0.0", + "json-stable-stringify-without-jsonify": "^1.0.1", + "lodash.merge": "^4.6.2", + "minimatch": "^3.1.2", + "natural-compare": "^1.4.0", + "optionator": "^0.9.3" + }, + "bin": { + "eslint": "bin/eslint.js" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://eslint.org/donate" + }, + "peerDependencies": { + "jiti": "*" + }, + "peerDependenciesMeta": { + "jiti": { + "optional": true + } + } + }, + "node_modules/eslint-compat-utils": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/eslint-compat-utils/-/eslint-compat-utils-0.5.1.tgz", + "integrity": "sha512-3z3vFexKIEnjHE3zCMRo6fn/e44U7T1khUjg+Hp0ZQMCigh28rALD0nPFBcGZuiLC5rLZa2ubQHDRln09JfU2Q==", + "dev": true, + "dependencies": { + "semver": "^7.5.4" + }, + "engines": { + "node": ">=12" + }, + "peerDependencies": { + "eslint": ">=6.0.0" + } + }, + "node_modules/eslint-compat-utils/node_modules/semver": { + "version": "7.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.2.tgz", + "integrity": "sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/eslint-config-prettier": { + "version": "10.1.8", + "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-10.1.8.tgz", + "integrity": "sha512-82GZUjRS0p/jganf6q1rEO25VSoHH0hKPCTrgillPjdI/3bgBhAE1QzHrHTizjpRvy6pGAvKjDJtk2pF9NDq8w==", + "dev": true, + "bin": { + "eslint-config-prettier": "bin/cli.js" + }, + "funding": { + "url": "https://opencollective.com/eslint-config-prettier" + }, + "peerDependencies": { + "eslint": ">=7.0.0" + } + }, + "node_modules/eslint-plugin-es-x": { + "version": "7.8.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-es-x/-/eslint-plugin-es-x-7.8.0.tgz", + "integrity": "sha512-7Ds8+wAAoV3T+LAKeu39Y5BzXCrGKrcISfgKEqTS4BDN8SFEDQd0S43jiQ8vIa3wUKD07qitZdfzlenSi8/0qQ==", + "dev": true, + "funding": [ + "https://github.com/sponsors/ota-meshi", + "https://opencollective.com/eslint" + ], + "dependencies": { + "@eslint-community/eslint-utils": "^4.1.2", + "@eslint-community/regexpp": "^4.11.0", + "eslint-compat-utils": "^0.5.1" + }, + "engines": { + "node": "^14.18.0 || >=16.0.0" + }, + "peerDependencies": { + "eslint": ">=8" + } + }, + "node_modules/eslint-plugin-local-rules": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/eslint-plugin-local-rules/-/eslint-plugin-local-rules-3.0.2.tgz", + "integrity": "sha512-IWME7GIYHXogTkFsToLdBCQVJ0U4kbSuVyDT+nKoR4UgtnVrrVeNWuAZkdEu1nxkvi9nsPccGehEEF6dgA28IQ==", + "dev": true + }, + "node_modules/eslint-plugin-n": { + "version": "17.21.3", + "resolved": "https://registry.npmjs.org/eslint-plugin-n/-/eslint-plugin-n-17.21.3.tgz", + "integrity": "sha512-MtxYjDZhMQgsWRm/4xYLL0i2EhusWT7itDxlJ80l1NND2AL2Vi5Mvneqv/ikG9+zpran0VsVRXTEHrpLmUZRNw==", + "dev": true, + "dependencies": { + "@eslint-community/eslint-utils": "^4.5.0", + "enhanced-resolve": "^5.17.1", + "eslint-plugin-es-x": "^7.8.0", + "get-tsconfig": "^4.8.1", + "globals": "^15.11.0", + "globrex": "^0.1.2", + "ignore": "^5.3.2", + "semver": "^7.6.3", + "ts-declaration-location": "^1.0.6" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + }, + "peerDependencies": { + "eslint": ">=8.23.0" + } + }, + "node_modules/eslint-plugin-n/node_modules/globals": { + "version": "15.15.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-15.15.0.tgz", + "integrity": "sha512-7ACyT3wmyp3I61S4fG682L0VA2RGD9otkqGJIwNUMF1SWUombIIk+af1unuDYgMm082aHYwD+mzJvv9Iu8dsgg==", + "dev": true, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint-plugin-n/node_modules/semver": { + "version": "7.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.2.tgz", + "integrity": "sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/eslint-plugin-prettier": { + "version": "5.5.3", + "resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-5.5.3.tgz", + "integrity": "sha512-NAdMYww51ehKfDyDhv59/eIItUVzU0Io9H2E8nHNGKEeeqlnci+1gCvrHib6EmZdf6GxF+LCV5K7UC65Ezvw7w==", + "dev": true, + "dependencies": { + "prettier-linter-helpers": "^1.0.0", + "synckit": "^0.11.7" + }, + "engines": { + "node": "^14.18.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint-plugin-prettier" + }, + "peerDependencies": { + "@types/eslint": ">=8.0.0", + "eslint": ">=8.0.0", + "eslint-config-prettier": ">= 7.0.0 <10.0.0 || >=10.1.0", + "prettier": ">=3.0.0" + }, + "peerDependenciesMeta": { + "@types/eslint": { + "optional": true + }, + "eslint-config-prettier": { + "optional": true + } + } + }, + "node_modules/eslint-plugin-promise": { + "version": "7.2.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-promise/-/eslint-plugin-promise-7.2.1.tgz", + "integrity": "sha512-SWKjd+EuvWkYaS+uN2csvj0KoP43YTu7+phKQ5v+xw6+A0gutVX2yqCeCkC3uLCJFiPfR2dD8Es5L7yUsmvEaA==", + "dev": true, + "dependencies": { + "@eslint-community/eslint-utils": "^4.4.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + }, + "peerDependencies": { + "eslint": "^7.0.0 || ^8.0.0 || ^9.0.0" + } + }, + "node_modules/eslint-plugin-vue": { + "version": "10.4.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-vue/-/eslint-plugin-vue-10.4.0.tgz", + "integrity": "sha512-K6tP0dW8FJVZLQxa2S7LcE1lLw3X8VvB3t887Q6CLrFVxHYBXGANbXvwNzYIu6Ughx1bSJ5BDT0YB3ybPT39lw==", + "dev": true, + "dependencies": { + "@eslint-community/eslint-utils": "^4.4.0", + "natural-compare": "^1.4.0", + "nth-check": "^2.1.1", + "postcss-selector-parser": "^6.0.15", + "semver": "^7.6.3", + "xml-name-validator": "^4.0.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "peerDependencies": { + "@typescript-eslint/parser": "^7.0.0 || ^8.0.0", + "eslint": "^8.57.0 || ^9.0.0", + "vue-eslint-parser": "^10.0.0" + }, + "peerDependenciesMeta": { + "@typescript-eslint/parser": { + "optional": true + } + } + }, + "node_modules/eslint-plugin-vue-scoped-css": { + "version": "2.11.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-vue-scoped-css/-/eslint-plugin-vue-scoped-css-2.11.0.tgz", + "integrity": "sha512-rrJgLY8iroTIUMSyxhyhJzFcRxABbk3gFrOLkl41F9G1VBqNNpDShyf6PmDoBEWDk07/bJlnqYlvnQ3giUrRYQ==", + "dev": true, + "dependencies": { + "@eslint-community/eslint-utils": "^4.4.0", + "eslint-compat-utils": "^0.6.5", + "lodash": "^4.17.21", + "postcss": "^8.4.31", + "postcss-safe-parser": "^6.0.0", + "postcss-scss": "^4.0.3", + "postcss-selector-parser": "^7.0.0", + "postcss-styl": "^0.12.0" + }, + "engines": { + "node": "^12.22 || ^14.17 || >=16" + }, + "funding": { + "url": "https://github.com/sponsors/ota-meshi" + }, + "peerDependencies": { + "eslint": ">=5.0.0", + "vue-eslint-parser": ">=7.1.0" + } + }, + "node_modules/eslint-plugin-vue-scoped-css/node_modules/eslint-compat-utils": { + "version": "0.6.5", + "resolved": "https://registry.npmjs.org/eslint-compat-utils/-/eslint-compat-utils-0.6.5.tgz", + "integrity": "sha512-vAUHYzue4YAa2hNACjB8HvUQj5yehAZgiClyFVVom9cP8z5NSFq3PwB/TtJslN2zAMgRX6FCFCjYBbQh71g5RQ==", + "dev": true, + "dependencies": { + "semver": "^7.5.4" + }, + "engines": { + "node": ">=12" + }, + "peerDependencies": { + "eslint": ">=6.0.0" + } + }, + "node_modules/eslint-plugin-vue-scoped-css/node_modules/postcss-selector-parser": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-7.1.0.tgz", + "integrity": "sha512-8sLjZwK0R+JlxlYcTuVnyT2v+htpdrjDOKuMcOVdYjt52Lh8hWRYpxBPoKx/Zg+bcjc3wx6fmQevMmUztS/ccA==", + "dev": true, + "dependencies": { + "cssesc": "^3.0.0", + "util-deprecate": "^1.0.2" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/eslint-plugin-vue-scoped-css/node_modules/semver": { + "version": "7.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.2.tgz", + "integrity": "sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/eslint-plugin-vue/node_modules/semver": { + "version": "7.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.2.tgz", + "integrity": "sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/eslint-scope": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", + "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", + "dev": true, + "dependencies": { + "esrecurse": "^4.3.0", + "estraverse": "^4.1.1" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/eslint-visitor-keys": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz", + "integrity": "sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw==", + "dev": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/eslint/node_modules/eslint-scope": { + "version": "8.4.0", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.4.0.tgz", + "integrity": "sha512-sNXOfKCn74rt8RICKMvJS7XKV/Xk9kA7DyJr8mJik3S7Cwgy3qlkkmyS2uQB3jiJg6VNdZd/pDBJu0nvG2NlTg==", + "dev": true, + "dependencies": { + "esrecurse": "^4.3.0", + "estraverse": "^5.2.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint/node_modules/eslint-visitor-keys": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.1.tgz", + "integrity": "sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==", + "dev": true, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint/node_modules/estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/espree": { + "version": "10.4.0", + "resolved": "https://registry.npmjs.org/espree/-/espree-10.4.0.tgz", + "integrity": "sha512-j6PAQ2uUr79PZhBjP5C5fhl8e39FmRnOjsD5lGnWrFU8i2G776tBK7+nP8KuQUTTyAZUwfQqXAgrVH5MbH9CYQ==", + "dev": true, + "dependencies": { + "acorn": "^8.15.0", + "acorn-jsx": "^5.3.2", + "eslint-visitor-keys": "^4.2.1" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/espree/node_modules/eslint-visitor-keys": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.1.tgz", + "integrity": "sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==", + "dev": true, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/esquery": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.6.0.tgz", + "integrity": "sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg==", + "dev": true, + "dependencies": { + "estraverse": "^5.1.0" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/esquery/node_modules/estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/esrecurse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", + "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", + "dev": true, + "dependencies": { + "estraverse": "^5.2.0" + }, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/esrecurse/node_modules/estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/estraverse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", + "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", + "dev": true, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/estree-walker": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz", + "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==" + }, + "node_modules/esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/eventemitter3": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-5.0.1.tgz", + "integrity": "sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA==", + "dev": true + }, + "node_modules/expect-type": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/expect-type/-/expect-type-1.2.2.tgz", + "integrity": "sha512-JhFGDVJ7tmDJItKhYgJCGLOWjuK9vPxiXoUFLwLDc99NlmklilbiQJwoctZtt13+xMw91MCk/REan6MWHqDjyA==", + "dev": true, + "engines": { + "node": ">=12.0.0" + } + }, + "node_modules/exsolve": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/exsolve/-/exsolve-1.0.7.tgz", + "integrity": "sha512-VO5fQUzZtI6C+vx4w/4BWJpg3s/5l+6pRQEHzFRM8WFi4XffSP1Z+4qi7GbjWbvRQEbdIco5mIMq+zX4rPuLrw==", + "dev": true + }, + "node_modules/fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==" + }, + "node_modules/fast-diff": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/fast-diff/-/fast-diff-1.3.0.tgz", + "integrity": "sha512-VxPP4NqbUjj6MaAOafWeUn2cXWLcCtljklUtZf0Ind4XQ+QPtmA0b18zZy0jIQx+ExRVCR/ZQpBmik5lXshNsw==", + "dev": true + }, + "node_modules/fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", + "dev": true + }, + "node_modules/fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", + "dev": true + }, + "node_modules/fastest-levenshtein": { + "version": "1.0.16", + "resolved": "https://registry.npmjs.org/fastest-levenshtein/-/fastest-levenshtein-1.0.16.tgz", + "integrity": "sha512-eRnCtTTtGZFpQCwhJiUOuxPQWRXVKYDn0b2PeHfXL6/Zi53SLAzAHfVhVWK2AryC/WH05kGfxhFIPvTF0SXQzg==", + "engines": { + "node": ">= 4.9.1" + } + }, + "node_modules/file-entry-cache": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-8.0.0.tgz", + "integrity": "sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==", + "dev": true, + "dependencies": { + "flat-cache": "^4.0.0" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/file-saver": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/file-saver/-/file-saver-2.0.5.tgz", + "integrity": "sha512-P9bmyZ3h/PRG+Nzga+rbdI4OEpNDzAVyy74uVO9ATgzLK6VtAsYybF/+TOCvrc0MO793d6+42lLyZTw7/ArVzA==" + }, + "node_modules/fill-range": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", + "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", + "devOptional": true, + "dependencies": { + "to-regex-range": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/find-up": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "dev": true, + "dependencies": { + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/flat-cache": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-4.0.1.tgz", + "integrity": "sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==", + "dev": true, + "dependencies": { + "flatted": "^3.2.9", + "keyv": "^4.5.4" + }, + "engines": { + "node": ">=16" + } + }, + "node_modules/flatted": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.3.tgz", + "integrity": "sha512-GX+ysw4PBCz0PzosHDepZGANEuFCMLrnRTiEy9McGjmkCQYwRq4A/X786G/fjM/+OjsWSU1ZrY5qyARZmO/uwg==", + "dev": true + }, + "node_modules/flush-promises": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/flush-promises/-/flush-promises-1.0.2.tgz", + "integrity": "sha512-G0sYfLQERwKz4+4iOZYQEZVpOt9zQrlItIxQAAYAWpfby3gbHrx0osCHz5RLl/XoXevXk0xoN4hDFky/VV9TrA==", + "dev": true + }, + "node_modules/follow-redirects": { + "version": "1.15.11", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.11.tgz", + "integrity": "sha512-deG2P0JfjrTxl50XGCDyfI97ZGVCxIpfKYmfyrQ54n5FO/0gfIES8C/Psl6kWVDolizcaaxZJnTS0QSMxvnsBQ==", + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/RubenVerborgh" + } + ], + "engines": { + "node": ">=4.0" + }, + "peerDependenciesMeta": { + "debug": { + "optional": true + } + } + }, + "node_modules/fontkit": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/fontkit/-/fontkit-2.0.4.tgz", + "integrity": "sha512-syetQadaUEDNdxdugga9CpEYVaQIxOwk7GlwZWWZ19//qW4zE5bknOKeMBDYAASwnpaSHKJITRLMF9m1fp3s6g==", + "dependencies": { + "@swc/helpers": "^0.5.12", + "brotli": "^1.3.2", + "clone": "^2.1.2", + "dfa": "^1.2.0", + "fast-deep-equal": "^3.1.3", + "restructure": "^3.0.0", + "tiny-inflate": "^1.0.3", + "unicode-properties": "^1.4.0", + "unicode-trie": "^2.0.0" + } + }, + "node_modules/for-each": { + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.5.tgz", + "integrity": "sha512-dKx12eRCVIzqCxFGplyFKJMPvLEWgmNtUrpTiJIR5u97zEhRG8ySrtboPHZXx7daLxQVrl643cTzbab2tkQjxg==", + "dependencies": { + "is-callable": "^1.2.7" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/foreground-child": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.3.1.tgz", + "integrity": "sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw==", + "dev": true, + "dependencies": { + "cross-spawn": "^7.0.6", + "signal-exit": "^4.0.1" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/form-data": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.4.tgz", + "integrity": "sha512-KrGhL9Q4zjj0kiUt5OO4Mr/A/jlI2jDYs5eHBpYHPcBEVSiipAvn2Ko2HnPe20rmcuuvMHNdZFp+4IlGTMF0Ow==", + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "es-set-tostringtag": "^2.1.0", + "hasown": "^2.0.2", + "mime-types": "^2.1.12" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/fraction.js": { + "version": "4.3.7", + "resolved": "https://registry.npmjs.org/fraction.js/-/fraction.js-4.3.7.tgz", + "integrity": "sha512-ZsDfxO51wGAXREY55a7la9LScWpwv9RxIrYABrlvOFBlH/ShPnrtsXeuUIfXKKOVicNxQ+o8JTbJvjS4M89yew==", + "dev": true, + "engines": { + "node": "*" + }, + "funding": { + "type": "patreon", + "url": "https://github.com/sponsors/rawify" + } + }, + "node_modules/fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", + "devOptional": true + }, + "node_modules/fsevents": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "hasInstallScript": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/function-bind": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/functions-have-names": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.2.3.tgz", + "integrity": "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/gensync": { + "version": "1.0.0-beta.2", + "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", + "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/get-east-asian-width": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/get-east-asian-width/-/get-east-asian-width-1.3.1.tgz", + "integrity": "sha512-R1QfovbPsKmosqTnPoRFiJ7CF9MLRgb53ChvMZm+r4p76/+8yKDy17qLL2PKInORy2RkZZekuK0efYgmzTkXyQ==", + "dev": true, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/get-intrinsic": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz", + "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==", + "dependencies": { + "call-bind-apply-helpers": "^1.0.2", + "es-define-property": "^1.0.1", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.1.1", + "function-bind": "^1.1.2", + "get-proto": "^1.0.1", + "gopd": "^1.2.0", + "has-symbols": "^1.1.0", + "hasown": "^2.0.2", + "math-intrinsics": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz", + "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==", + "dependencies": { + "dunder-proto": "^1.0.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/get-tsconfig": { + "version": "4.10.1", + "resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.10.1.tgz", + "integrity": "sha512-auHyJ4AgMz7vgS8Hp3N6HXSmlMdUyhSUrfBF16w153rxtLIEOE+HGqaBppczZvnHLqQJfiHotCYpNhl0lUROFQ==", + "dev": true, + "dependencies": { + "resolve-pkg-maps": "^1.0.0" + }, + "funding": { + "url": "https://github.com/privatenumber/get-tsconfig?sponsor=1" + } + }, + "node_modules/glob": { + "version": "9.3.5", + "resolved": "https://registry.npmjs.org/glob/-/glob-9.3.5.tgz", + "integrity": "sha512-e1LleDykUz2Iu+MTYdkSsuWX8lvAjAcs0Xef0lNIu0S2wOAzuTxCJtcd9S3cijlwYF18EsU3rzb8jPVobxDh9Q==", + "dev": true, + "dependencies": { + "fs.realpath": "^1.0.0", + "minimatch": "^8.0.2", + "minipass": "^4.2.4", + "path-scurry": "^1.6.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/glob-parent": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", + "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", + "dev": true, + "dependencies": { + "is-glob": "^4.0.3" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/glob/node_modules/brace-expansion": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz", + "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/glob/node_modules/minimatch": { + "version": "8.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-8.0.4.tgz", + "integrity": "sha512-W0Wvr9HyFXZRGIDgCicunpQ299OKXs9RgZfaukz4qAW/pJhcpUfupc9c+OObPOFueNy8VSrZgEmDtk6Kh4WzDA==", + "dev": true, + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/globals": { + "version": "16.3.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-16.3.0.tgz", + "integrity": "sha512-bqWEnJ1Nt3neqx2q5SFfGS8r/ahumIakg3HcwtNlrVlwXIeNumWn/c7Pn/wKzGhf6SaW6H6uWXLqC30STCMchQ==", + "dev": true, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/globrex": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/globrex/-/globrex-0.1.2.tgz", + "integrity": "sha512-uHJgbwAMwNFf5mLst7IWLNg14x1CkeqglJb/K3doi4dw6q2IvAAmM/Y81kevy83wP+Sst+nutFTYOGg3d1lsxg==", + "dev": true + }, + "node_modules/gopd": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", + "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/graceful-fs": { + "version": "4.2.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", + "dev": true + }, + "node_modules/hal-json-normalizer": { + "version": "5.0.0-alpha.0", + "resolved": "https://registry.npmjs.org/hal-json-normalizer/-/hal-json-normalizer-5.0.0-alpha.0.tgz", + "integrity": "sha512-c/7LnUA63PZ/i+Jx6ueUNzTfr05cWzaiFIO2/aoQ8LCIpY37INfflHtYTlQiSi9FfAQDI/CTeExUrbU6U1uEnw==", + "dependencies": { + "lodash-es": "^4.17.15" + }, + "engines": { + "node": ">= 18.17.0" + } + }, + "node_modules/hal-json-vuex": { + "version": "3.0.0-alpha.10", + "resolved": "https://registry.npmjs.org/hal-json-vuex/-/hal-json-vuex-3.0.0-alpha.10.tgz", + "integrity": "sha512-2uKuvoMXKKFwtbNcs09LU7hOJEqWXNx0yTST0VKw9osYMIT0zQBdllIJUnK10oxtOSHYhmzFs7cF9LwEttSgyw==", + "dependencies": { + "hal-json-normalizer": "^5.0.0-alpha.0", + "url-template": "^3.1.1", + "vue-demi": "^0.14.10" + }, + "engines": { + "node": ">=18.17.0" + }, + "peerDependencies": { + "@vue/composition-api": "^1.0.0-rc.1", + "vue": "^2.0.0 || >=3.0.0" + }, + "peerDependenciesMeta": { + "@vue/composition-api": { + "optional": true + } + } + }, + "node_modules/hal-json-vuex/node_modules/vue-demi": { + "version": "0.14.10", + "resolved": "https://registry.npmjs.org/vue-demi/-/vue-demi-0.14.10.tgz", + "integrity": "sha512-nMZBOwuzabUO0nLgIcc6rycZEebF6eeUfaiQx9+WSk8e29IbLvPU9feI6tqW4kTo3hvoYAJkMh8n8D0fuISphg==", + "hasInstallScript": true, + "bin": { + "vue-demi-fix": "bin/vue-demi-fix.js", + "vue-demi-switch": "bin/vue-demi-switch.js" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/antfu" + }, + "peerDependencies": { + "@vue/composition-api": "^1.0.0-rc.1", + "vue": "^3.0.0-0 || ^2.6.0" + }, + "peerDependenciesMeta": { + "@vue/composition-api": { + "optional": true + } + } + }, + "node_modules/has-bigints": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.1.0.tgz", + "integrity": "sha512-R3pbpkcIqv2Pm3dUwgjclDRVmWpTJW2DcMzcIhEXEx1oh/CEMObMm3KLmRJOdvhM7o4uQBnwr8pzRK2sJWIqfg==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/has-property-descriptors": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz", + "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==", + "dependencies": { + "es-define-property": "^1.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-symbols": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz", + "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-tostringtag": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz", + "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==", + "dependencies": { + "has-symbols": "^1.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/hasown": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", + "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", + "dependencies": { + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/hookable": { + "version": "5.5.3", + "resolved": "https://registry.npmjs.org/hookable/-/hookable-5.5.3.tgz", + "integrity": "sha512-Yc+BQe8SvoXH1643Qez1zqLRmbA5rCL+sSmk6TVos0LWVfNIB7PGncdlId77WzLGSIB5KaWgTaNTs2lNVEI6VQ==" + }, + "node_modules/hsl-to-hex": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/hsl-to-hex/-/hsl-to-hex-1.0.0.tgz", + "integrity": "sha512-K6GVpucS5wFf44X0h2bLVRDsycgJmf9FF2elg+CrqD8GcFU8c6vYhgXn8NjUkFCwj+xDFb70qgLbTUm6sxwPmA==", + "dependencies": { + "hsl-to-rgb-for-reals": "^1.1.0" + } + }, + "node_modules/hsl-to-rgb-for-reals": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/hsl-to-rgb-for-reals/-/hsl-to-rgb-for-reals-1.1.1.tgz", + "integrity": "sha512-LgOWAkrN0rFaQpfdWBQlv/VhkOxb5AsBjk6NQVx4yEzWS923T07X0M1Y0VNko2H52HeSpZrZNNMJ0aFqsdVzQg==" + }, + "node_modules/html-encoding-sniffer": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/html-encoding-sniffer/-/html-encoding-sniffer-4.0.0.tgz", + "integrity": "sha512-Y22oTqIU4uuPgEemfz7NDJz6OeKf12Lsu+QC+s3BVpda64lTiMYCyGwg5ki4vFxkMwQdeZDl2adZoqUgdFuTgQ==", + "dev": true, + "dependencies": { + "whatwg-encoding": "^3.1.1" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/html-escaper": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.2.tgz", + "integrity": "sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==", + "dev": true + }, + "node_modules/html-tags": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/html-tags/-/html-tags-2.0.0.tgz", + "integrity": "sha512-+Il6N8cCo2wB/Vd3gqy/8TZhTD3QvcVeQLCnZiGkGCH3JP28IgGAY41giccp2W4R3jfyJPAP318FQTa1yU7K7g==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/htmlparser2": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-9.1.0.tgz", + "integrity": "sha512-5zfg6mHUoaer/97TxnGpxmbR7zJtPwIYFMZ/H5ucTlPZhKvtum05yiPK3Mgai3a0DyVxv7qYqoweaEd2nrYQzQ==", + "dev": true, + "funding": [ + "https://github.com/fb55/htmlparser2?sponsor=1", + { + "type": "github", + "url": "https://github.com/sponsors/fb55" + } + ], + "dependencies": { + "domelementtype": "^2.3.0", + "domhandler": "^5.0.3", + "domutils": "^3.1.0", + "entities": "^4.5.0" + } + }, + "node_modules/http-proxy-agent": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-7.0.2.tgz", + "integrity": "sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig==", + "dev": true, + "dependencies": { + "agent-base": "^7.1.0", + "debug": "^4.3.4" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/http-proxy-agent/node_modules/agent-base": { + "version": "7.1.4", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.4.tgz", + "integrity": "sha512-MnA+YT8fwfJPgBx3m60MNqakm30XOkyIoH1y6huTQvC0PwZG7ki8NacLBcrPbNoo8vEZy7Jpuk7+jMO+CUovTQ==", + "dev": true, + "engines": { + "node": ">= 14" + } + }, + "node_modules/https-proxy-agent": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", + "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", + "dev": true, + "dependencies": { + "agent-base": "6", + "debug": "4" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/hyphen": { + "version": "1.10.6", + "resolved": "https://registry.npmjs.org/hyphen/-/hyphen-1.10.6.tgz", + "integrity": "sha512-fXHXcGFTXOvZTSkPJuGOQf5Lv5T/R2itiiCVPg9LxAje5D00O0pP83yJShFq5V89Ly//Gt6acj7z8pbBr34stw==" + }, + "node_modules/iconv-lite": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", + "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", + "dev": true, + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ignore": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", + "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==", + "dev": true, + "engines": { + "node": ">= 4" + } + }, + "node_modules/immutable": { + "version": "5.1.3", + "resolved": "https://registry.npmjs.org/immutable/-/immutable-5.1.3.tgz", + "integrity": "sha512-+chQdDfvscSF1SJqv2gn4SRO2ZyS3xL3r7IW/wWEEzrzLisnOlKiQu5ytC/BVNcS15C39WT2Hg/bjKjDMcu+zg==", + "devOptional": true + }, + "node_modules/import-fresh": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.1.tgz", + "integrity": "sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==", + "dev": true, + "dependencies": { + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", + "dev": true, + "engines": { + "node": ">=0.8.19" + } + }, + "node_modules/indent-string": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", + "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "deprecated": "This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.", + "devOptional": true, + "dependencies": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" + }, + "node_modules/ini": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", + "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==", + "dev": true + }, + "node_modules/inter-ui": { + "version": "3.19.3", + "resolved": "https://registry.npmjs.org/inter-ui/-/inter-ui-3.19.3.tgz", + "integrity": "sha512-5FG9fjuYOXocIfjzcCBhICL5cpvwEetseL3FU6tP3d6Bn7g8wODhB+I9RNGRTizCT7CUG4GOK54OPxqq3msQgg==", + "license": "OFL-1.1" + }, + "node_modules/internal-slot": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.1.0.tgz", + "integrity": "sha512-4gd7VpWNQNB4UKKCFFVcp1AVv+FMOgs9NKzjHKusc8jTMhd5eL1NqQqOpE0KzMds804/yHlglp3uxgluOqAPLw==", + "dev": true, + "dependencies": { + "es-errors": "^1.3.0", + "hasown": "^2.0.2", + "side-channel": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/is-arguments": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.2.0.tgz", + "integrity": "sha512-7bVbi0huj/wrIAOzb8U1aszg9kdi3KN/CyU19CTI7tAoZYEZoL9yCDXpbXN+uPsuWnP02cyug1gleqq+TU+YCA==", + "dependencies": { + "call-bound": "^1.0.2", + "has-tostringtag": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-array-buffer": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.5.tgz", + "integrity": "sha512-DDfANUiiG2wC1qawP66qlTugJeL5HyzMpfr8lLK+jMQirGzNod0B12cFB/9q838Ru27sBwfw78/rdoU7RERz6A==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.8", + "call-bound": "^1.0.3", + "get-intrinsic": "^1.2.6" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-arrayish": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.3.2.tgz", + "integrity": "sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ==" + }, + "node_modules/is-bigint": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.1.0.tgz", + "integrity": "sha512-n4ZT37wG78iz03xPRKJrHTdZbe3IicyucEtdRsV5yglwc3GyUfbAfpSeD0FJ41NbUNSt5wbhqfp1fS+BgnvDFQ==", + "dev": true, + "dependencies": { + "has-bigints": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-binary-path": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", + "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", + "dev": true, + "dependencies": { + "binary-extensions": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-boolean-object": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.2.2.tgz", + "integrity": "sha512-wa56o2/ElJMYqjCjGkXri7it5FbebW5usLw/nPmCMs5DeZ7eziSYZhSmPRn0txqeW4LnAmQQU7FgqLpsEFKM4A==", + "dev": true, + "dependencies": { + "call-bound": "^1.0.3", + "has-tostringtag": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-callable": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz", + "integrity": "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-core-module": { + "version": "2.16.1", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.16.1.tgz", + "integrity": "sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w==", + "dev": true, + "dependencies": { + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-date-object": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.1.0.tgz", + "integrity": "sha512-PwwhEakHVKTdRNVOw+/Gyh0+MzlCl4R6qKvkhuvLtPMggI1WAHt9sOwZxQLSGpUaDnrdyDsomoRgNnCfKNSXXg==", + "dev": true, + "dependencies": { + "call-bound": "^1.0.2", + "has-tostringtag": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "devOptional": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-fullwidth-code-point": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-4.0.0.tgz", + "integrity": "sha512-O4L094N2/dZ7xqVdrXhh9r1KODPJpFms8B5sGdJLPy664AgvXsreZUyCQQNItZRDlYug4xStLjNp/sz3HvBowQ==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-generator-function": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.1.0.tgz", + "integrity": "sha512-nPUB5km40q9e8UfN/Zc24eLlzdSf9OfKByBw9CIdw4H1giPMeA0OIJvbchsCu4npfI2QcMVBsGEBHKZ7wLTWmQ==", + "dependencies": { + "call-bound": "^1.0.3", + "get-proto": "^1.0.0", + "has-tostringtag": "^1.0.2", + "safe-regex-test": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "devOptional": true, + "dependencies": { + "is-extglob": "^2.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-map": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/is-map/-/is-map-2.0.3.tgz", + "integrity": "sha512-1Qed0/Hr2m+YqxnM09CjA2d/i6YZNfF6R2oRAOj36eUdS6qIV/huPJNSEpKbupewFs+ZsJlxsjjPbc0/afW6Lw==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-nan": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/is-nan/-/is-nan-1.3.2.tgz", + "integrity": "sha512-E+zBKpQ2t6MEo1VsonYmluk9NxGrbzpeeLC2xIViuO2EjU2xsXsBPwTr3Ykv9l08UYEVEdWeRZNouaZqF6RN0w==", + "dependencies": { + "call-bind": "^1.0.0", + "define-properties": "^1.1.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "devOptional": true, + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/is-number-object": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.1.1.tgz", + "integrity": "sha512-lZhclumE1G6VYD8VHe35wFaIif+CTy5SJIi5+3y4psDgWu4wPDoBhF8NxUOinEc7pHgiTsT6MaBb92rKhhD+Xw==", + "dev": true, + "dependencies": { + "call-bound": "^1.0.3", + "has-tostringtag": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-potential-custom-element-name": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-potential-custom-element-name/-/is-potential-custom-element-name-1.0.1.tgz", + "integrity": "sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ==", + "dev": true + }, + "node_modules/is-regex": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.2.1.tgz", + "integrity": "sha512-MjYsKHO5O7mCsmRGxWcLWheFqN9DJ/2TmngvjKXihe6efViPqc274+Fx/4fYj/r03+ESvBdTXK0V6tA3rgez1g==", + "dependencies": { + "call-bound": "^1.0.2", + "gopd": "^1.2.0", + "has-tostringtag": "^1.0.2", + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-set": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/is-set/-/is-set-2.0.3.tgz", + "integrity": "sha512-iPAjerrse27/ygGLxw+EBR9agv9Y6uLeYVJMu+QNCoouJ1/1ri0mGrcWpfCqFZuzzx3WjtwxG098X+n4OuRkPg==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-shared-array-buffer": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.4.tgz", + "integrity": "sha512-ISWac8drv4ZGfwKl5slpHG9OwPNty4jOWPRIhBpxOoD+hqITiwuipOQ2bNthAzwA3B4fIjO4Nln74N0S9byq8A==", + "dev": true, + "dependencies": { + "call-bound": "^1.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-string": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.1.1.tgz", + "integrity": "sha512-BtEeSsoaQjlSPBemMQIrY1MY0uM6vnS1g5fmufYOtnxLGUZM2178PKbhsk7Ffv58IX+ZtcvoGwccYsh0PglkAA==", + "dev": true, + "dependencies": { + "call-bound": "^1.0.3", + "has-tostringtag": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-symbol": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.1.1.tgz", + "integrity": "sha512-9gGx6GTtCQM73BgmHQXfDmLtfjjTUDSyoxTCbp5WtoixAhfgsDirWIcVQ/IHpvI5Vgd5i/J5F7B9cN/WlVbC/w==", + "dev": true, + "dependencies": { + "call-bound": "^1.0.2", + "has-symbols": "^1.1.0", + "safe-regex-test": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-typed-array": { + "version": "1.1.15", + "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.15.tgz", + "integrity": "sha512-p3EcsicXjit7SaskXHs1hA91QxgTw46Fv6EFKKGS5DRFLD8yKnohjF3hxoju94b/OcMZoQukzpPpBE9uLVKzgQ==", + "dependencies": { + "which-typed-array": "^1.1.16" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-url": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/is-url/-/is-url-1.2.4.tgz", + "integrity": "sha512-ITvGim8FhRiYe4IQ5uHSkj7pVaPDrCTkNd3yq3cV7iZAcJdHTUMPMEHcqSOy9xZ9qFenQCvi+2wjH9a1nXqHww==" + }, + "node_modules/is-weakmap": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/is-weakmap/-/is-weakmap-2.0.2.tgz", + "integrity": "sha512-K5pXYOm9wqY1RgjpL3YTkF39tni1XajUIkawTLUo9EZEVUFga5gSQJF8nNS7ZwJQ02y+1YCNYcMh+HIf1ZqE+w==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-weakset": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/is-weakset/-/is-weakset-2.0.4.tgz", + "integrity": "sha512-mfcwb6IzQyOKTs84CQMrOwW4gQcaTOAWJ0zzJCl2WSPDrWk/OzDaImWFH3djXhb24g4eudZfLRozAvPGw4d9hQ==", + "dev": true, + "dependencies": { + "call-bound": "^1.0.3", + "get-intrinsic": "^1.2.6" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-what": { + "version": "4.1.16", + "resolved": "https://registry.npmjs.org/is-what/-/is-what-4.1.16.tgz", + "integrity": "sha512-ZhMwEosbFJkA0YhFnNDgTM4ZxDRsS6HqTo7qsZM08fehyRYIYa0yHu5R6mgo1n/8MgaPBXiPimPD77baVFYg+A==", + "engines": { + "node": ">=12.13" + }, + "funding": { + "url": "https://github.com/sponsors/mesqueeb" + } + }, + "node_modules/isarray": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", + "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==", + "dev": true + }, + "node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", + "dev": true + }, + "node_modules/istanbul-lib-coverage": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.2.tgz", + "integrity": "sha512-O8dpsF+r0WV/8MNRKfnmrtCWhuKjxrq2w+jpzBL5UZKTi2LeVWnWOmWRxFlesJONmc+wLAGvKQZEOanko0LFTg==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/istanbul-lib-report": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-3.0.1.tgz", + "integrity": "sha512-GCfE1mtsHGOELCU8e/Z7YWzpmybrx/+dSTfLrvY8qRmaY6zXTKWn6WQIjaAFw069icm6GVMNkgu0NzI4iPZUNw==", + "dev": true, + "dependencies": { + "istanbul-lib-coverage": "^3.0.0", + "make-dir": "^4.0.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/istanbul-lib-source-maps": { + "version": "5.0.6", + "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-5.0.6.tgz", + "integrity": "sha512-yg2d+Em4KizZC5niWhQaIomgf5WlL4vOOjZ5xGCmF8SnPE/mDWWXgvRExdcpCgh9lLRRa1/fSYp2ymmbJ1pI+A==", + "dev": true, + "dependencies": { + "@jridgewell/trace-mapping": "^0.3.23", + "debug": "^4.1.1", + "istanbul-lib-coverage": "^3.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/istanbul-reports": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.2.0.tgz", + "integrity": "sha512-HGYWWS/ehqTV3xN10i23tkPkpH46MLCIMFNCaaKNavAXTF1RkqxawEPtnjnGZ6XKSInBKkiOA5BKS+aZiY3AvA==", + "dev": true, + "dependencies": { + "html-escaper": "^2.0.0", + "istanbul-lib-report": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/jackspeak": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-3.4.3.tgz", + "integrity": "sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==", + "dev": true, + "dependencies": { + "@isaacs/cliui": "^8.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + }, + "optionalDependencies": { + "@pkgjs/parseargs": "^0.11.0" + } + }, + "node_modules/jay-peg": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/jay-peg/-/jay-peg-1.1.1.tgz", + "integrity": "sha512-D62KEuBxz/ip2gQKOEhk/mx14o7eiFRaU+VNNSP4MOiIkwb/D6B3G1Mfas7C/Fit8EsSV2/IWjZElx/Gs6A4ww==", + "dependencies": { + "restructure": "^3.0.0" + } + }, + "node_modules/jest-canvas-mock": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/jest-canvas-mock/-/jest-canvas-mock-2.5.2.tgz", + "integrity": "sha512-vgnpPupjOL6+L5oJXzxTxFrlGEIbHdZqFU+LFNdtLxZ3lRDCl17FlTMM7IatoRQkrcyOTMlDinjUguqmQ6bR2A==", + "dev": true, + "dependencies": { + "cssfontparser": "^1.2.1", + "moo-color": "^1.0.2" + } + }, + "node_modules/jest-serializer-vue-tjw": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/jest-serializer-vue-tjw/-/jest-serializer-vue-tjw-4.0.0.tgz", + "integrity": "sha512-VZv8shuNyPbXx96PkKVOAHGPlim86Tl8ie2ehdsjJT/dfQT0fsPl0UtBJdphK6DUAGBSIfltgPlQEYXDwW2EmQ==", + "dev": true, + "hasInstallScript": true, + "dependencies": { + "cheerio": "^1.0.0-rc.3", + "htmlparser2": "^9.0.0", + "js-beautify": "^1.14.8", + "lodash.clonedeep": "^4.5.0" + }, + "engines": { + "node": ">=8.3.0", + "npm": ">=5.0.0" + } + }, + "node_modules/js-beautify": { + "version": "1.15.4", + "resolved": "https://registry.npmjs.org/js-beautify/-/js-beautify-1.15.4.tgz", + "integrity": "sha512-9/KXeZUKKJwqCXUdBxFJ3vPh467OCckSBmYDwSK/EtV090K+iMJ7zx2S3HLVDIWFQdqMIsZWbnaGiba18aWhaA==", + "dev": true, + "dependencies": { + "config-chain": "^1.1.13", + "editorconfig": "^1.0.4", + "glob": "^10.4.2", + "js-cookie": "^3.0.5", + "nopt": "^7.2.1" + }, + "bin": { + "css-beautify": "js/bin/css-beautify.js", + "html-beautify": "js/bin/html-beautify.js", + "js-beautify": "js/bin/js-beautify.js" + }, + "engines": { + "node": ">=14" + } + }, + "node_modules/js-beautify/node_modules/brace-expansion": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz", + "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/js-beautify/node_modules/glob": { + "version": "10.4.5", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.4.5.tgz", + "integrity": "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==", + "dev": true, + "dependencies": { + "foreground-child": "^3.1.0", + "jackspeak": "^3.1.2", + "minimatch": "^9.0.4", + "minipass": "^7.1.2", + "package-json-from-dist": "^1.0.0", + "path-scurry": "^1.11.1" + }, + "bin": { + "glob": "dist/esm/bin.mjs" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/js-beautify/node_modules/minimatch": { + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", + "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", + "dev": true, + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/js-beautify/node_modules/minipass": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz", + "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==", + "dev": true, + "engines": { + "node": ">=16 || 14 >=14.17" + } + }, + "node_modules/js-cookie": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/js-cookie/-/js-cookie-3.0.5.tgz", + "integrity": "sha512-cEiJEAEoIbWfCZYKWhVwFuvPX1gETRYPw6LlaTKoxD3s2AkXzkCjnp6h0V77ozyqj0jakteJ4YqDJT830+lVGw==", + "engines": { + "node": ">=14" + } + }, + "node_modules/js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "dev": true + }, + "node_modules/js-yaml": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", + "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "dev": true, + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/jsdom": { + "version": "26.1.0", + "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-26.1.0.tgz", + "integrity": "sha512-Cvc9WUhxSMEo4McES3P7oK3QaXldCfNWp7pl2NNeiIFlCoLr3kfq9kb1fxftiwk1FLV7CvpvDfonxtzUDeSOPg==", + "dev": true, + "dependencies": { + "cssstyle": "^4.2.1", + "data-urls": "^5.0.0", + "decimal.js": "^10.5.0", + "html-encoding-sniffer": "^4.0.0", + "http-proxy-agent": "^7.0.2", + "https-proxy-agent": "^7.0.6", + "is-potential-custom-element-name": "^1.0.1", + "nwsapi": "^2.2.16", + "parse5": "^7.2.1", + "rrweb-cssom": "^0.8.0", + "saxes": "^6.0.0", + "symbol-tree": "^3.2.4", + "tough-cookie": "^5.1.1", + "w3c-xmlserializer": "^5.0.0", + "webidl-conversions": "^7.0.0", + "whatwg-encoding": "^3.1.1", + "whatwg-mimetype": "^4.0.0", + "whatwg-url": "^14.1.1", + "ws": "^8.18.0", + "xml-name-validator": "^5.0.0" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "canvas": "^3.0.0" + }, + "peerDependenciesMeta": { + "canvas": { + "optional": true + } + } + }, + "node_modules/jsdom/node_modules/agent-base": { + "version": "7.1.4", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.4.tgz", + "integrity": "sha512-MnA+YT8fwfJPgBx3m60MNqakm30XOkyIoH1y6huTQvC0PwZG7ki8NacLBcrPbNoo8vEZy7Jpuk7+jMO+CUovTQ==", + "dev": true, + "engines": { + "node": ">= 14" + } + }, + "node_modules/jsdom/node_modules/https-proxy-agent": { + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.6.tgz", + "integrity": "sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw==", + "dev": true, + "dependencies": { + "agent-base": "^7.1.2", + "debug": "4" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/jsdom/node_modules/xml-name-validator": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/xml-name-validator/-/xml-name-validator-5.0.0.tgz", + "integrity": "sha512-EvGK8EJ3DhaHfbRlETOWAS5pO9MZITeauHKJyb8wyajUfQUenkIg2MvLDTZ4T/TgIcm3HU0TFBgWWboAZ30UHg==", + "dev": true, + "engines": { + "node": ">=18" + } + }, + "node_modules/jsesc": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.1.0.tgz", + "integrity": "sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==", + "dev": true, + "bin": { + "jsesc": "bin/jsesc" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/json-buffer": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", + "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", + "dev": true + }, + "node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true + }, + "node_modules/json-stable-stringify-without-jsonify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", + "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", + "dev": true + }, + "node_modules/json5": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", + "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", + "dev": true, + "bin": { + "json5": "lib/cli.js" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/keyv": { + "version": "4.5.4", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", + "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==", + "dev": true, + "dependencies": { + "json-buffer": "3.0.1" + } + }, + "node_modules/levn": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", + "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", + "dev": true, + "dependencies": { + "prelude-ls": "^1.2.1", + "type-check": "~0.4.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/lilconfig": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-3.1.3.tgz", + "integrity": "sha512-/vlFKAoH5Cgt3Ie+JLhRbwOsCQePABiU3tJ1egGvyQ+33R/vcwM2Zl2QR/LzjsBeItPt3oSVXapn+m4nQDvpzw==", + "dev": true, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/antonk52" + } + }, + "node_modules/linebreak": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/linebreak/-/linebreak-1.1.0.tgz", + "integrity": "sha512-MHp03UImeVhB7XZtjd0E4n6+3xr5Dq/9xI/5FptGk5FrbDR3zagPa2DS6U8ks/3HjbKWG9Q1M2ufOzxV2qLYSQ==", + "dependencies": { + "base64-js": "0.0.8", + "unicode-trie": "^2.0.0" + } + }, + "node_modules/linebreak/node_modules/base64-js": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-0.0.8.tgz", + "integrity": "sha512-3XSA2cR/h/73EzlXXdU6YNycmYI7+kicTxks4eJg2g39biHR84slg2+des+p7iHYhbRg/udIS4TD53WabcOUkw==", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/linkify-it": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/linkify-it/-/linkify-it-5.0.0.tgz", + "integrity": "sha512-5aHCbzQRADcdP+ATqnDuhhJ/MRIqDkZX5pyjFHRRysS8vZ5AbqGEoFIb6pYHPZ+L/OC2Lc+xT8uHVVR5CAK/wQ==", + "dependencies": { + "uc.micro": "^2.0.0" + } + }, + "node_modules/lint-staged": { + "version": "16.1.4", + "resolved": "https://registry.npmjs.org/lint-staged/-/lint-staged-16.1.4.tgz", + "integrity": "sha512-xy7rnzQrhTVGKMpv6+bmIA3C0yET31x8OhKBYfvGo0/byeZ6E0BjGARrir3Kg/RhhYHutpsi01+2J5IpfVoueA==", + "dev": true, + "dependencies": { + "chalk": "^5.4.1", + "commander": "^14.0.0", + "debug": "^4.4.1", + "lilconfig": "^3.1.3", + "listr2": "^9.0.1", + "micromatch": "^4.0.8", + "nano-spawn": "^1.0.2", + "pidtree": "^0.6.0", + "string-argv": "^0.3.2", + "yaml": "^2.8.0" + }, + "bin": { + "lint-staged": "bin/lint-staged.js" + }, + "engines": { + "node": ">=20.17" + }, + "funding": { + "url": "https://opencollective.com/lint-staged" + } + }, + "node_modules/lint-staged/node_modules/chalk": { + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.6.0.tgz", + "integrity": "sha512-46QrSQFyVSEyYAgQ22hQ+zDa60YHA4fBstHmtSApj1Y5vKtG27fWowW03jCk5KcbXEWPZUIR894aARCA/G1kfQ==", + "dev": true, + "engines": { + "node": "^12.17.0 || ^14.13 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/lint-staged/node_modules/commander": { + "version": "14.0.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-14.0.0.tgz", + "integrity": "sha512-2uM9rYjPvyq39NwLRqaiLtWHyDC1FvryJDa2ATTVims5YAS4PupsEQsDvP14FqhFr0P49CYDugi59xaxJlTXRA==", + "dev": true, + "engines": { + "node": ">=20" + } + }, + "node_modules/listr2": { + "version": "9.0.3", + "resolved": "https://registry.npmjs.org/listr2/-/listr2-9.0.3.tgz", + "integrity": "sha512-0aeh5HHHgmq1KRdMMDHfhMWQmIT/m7nRDTlxlFqni2Sp0had9baqsjJRvDGdlvgd6NmPE0nPloOipiQJGFtTHQ==", + "dev": true, + "dependencies": { + "cli-truncate": "^4.0.0", + "colorette": "^2.0.20", + "eventemitter3": "^5.0.1", + "log-update": "^6.1.0", + "rfdc": "^1.4.1", + "wrap-ansi": "^9.0.0" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/local-pkg": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/local-pkg/-/local-pkg-1.1.2.tgz", + "integrity": "sha512-arhlxbFRmoQHl33a0Zkle/YWlmNwoyt6QNZEIJcqNbdrsix5Lvc4HyyI3EnwxTYlZYc32EbYrQ8SzEZ7dqgg9A==", + "dev": true, + "dependencies": { + "mlly": "^1.7.4", + "pkg-types": "^2.3.0", + "quansync": "^0.2.11" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/antfu" + } + }, + "node_modules/locate-path": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", + "dev": true, + "dependencies": { + "p-locate": "^5.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/lodash": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", + "dev": true + }, + "node_modules/lodash-es": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash-es/-/lodash-es-4.17.21.tgz", + "integrity": "sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw==" + }, + "node_modules/lodash.clonedeep": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz", + "integrity": "sha512-H5ZhCF25riFd9uB5UCkVKo61m3S/xZk1x4wA6yp/L3RFP6Z/eHH1ymQcGLo7J3GMPfm0V/7m1tryHuGVxpqEBQ==", + "dev": true + }, + "node_modules/lodash.debounce": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz", + "integrity": "sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow==", + "dev": true + }, + "node_modules/lodash.kebabcase": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/lodash.kebabcase/-/lodash.kebabcase-4.1.1.tgz", + "integrity": "sha512-N8XRTIMMqqDgSy4VLKPnJ/+hpGZN+PHQiJnSenYqPaVV/NCqEogTnAdZLQiGKhxX+JCs8waWq2t1XHWKOmlY8g==", + "dev": true + }, + "node_modules/lodash.merge": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", + "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", + "dev": true + }, + "node_modules/lodash.sortedlastindex": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/lodash.sortedlastindex/-/lodash.sortedlastindex-4.1.0.tgz", + "integrity": "sha512-s8xEQdsp2Tu5zUqVdFSe9C0kR8YlnAJYLqMdkh+pIRBRxF6/apWseLdHl3/+jv2I61dhPwtI/Ff+EqvCpc+N8w==", + "dev": true + }, + "node_modules/log-update": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/log-update/-/log-update-6.1.0.tgz", + "integrity": "sha512-9ie8ItPR6tjY5uYJh8K/Zrv/RMZ5VOlOWvtZdEHYSTFKZfIBPQa9tOAEeAWhd+AnIneLJ22w5fjOYtoutpWq5w==", + "dev": true, + "dependencies": { + "ansi-escapes": "^7.0.0", + "cli-cursor": "^5.0.0", + "slice-ansi": "^7.1.0", + "strip-ansi": "^7.1.0", + "wrap-ansi": "^9.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/log-update/node_modules/ansi-styles": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", + "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/log-update/node_modules/is-fullwidth-code-point": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-5.1.0.tgz", + "integrity": "sha512-5XHYaSyiqADb4RnZ1Bdad6cPp8Toise4TzEjcOYDHZkTCbKgiUl7WTUCpNWHuxmDt91wnsZBc9xinNzopv3JMQ==", + "dev": true, + "dependencies": { + "get-east-asian-width": "^1.3.1" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/log-update/node_modules/slice-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-7.1.0.tgz", + "integrity": "sha512-bSiSngZ/jWeX93BqeIAbImyTbEihizcwNjFoRUIY/T1wWQsfsm2Vw1agPKylXvQTU7iASGdHhyqRlqQzfz+Htg==", + "dev": true, + "dependencies": { + "ansi-styles": "^6.2.1", + "is-fullwidth-code-point": "^5.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/chalk/slice-ansi?sponsor=1" + } + }, + "node_modules/loupe": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/loupe/-/loupe-3.2.1.tgz", + "integrity": "sha512-CdzqowRJCeLU72bHvWqwRBBlLcMEtIvGrlvef74kMnV2AolS9Y8xUv1I0U/MNAWMhBlKIoyuEgoJ0t/bbwHbLQ==", + "dev": true + }, + "node_modules/lru-cache": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", + "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", + "dev": true, + "dependencies": { + "yallist": "^3.0.2" + } + }, + "node_modules/lz-string": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/lz-string/-/lz-string-1.5.0.tgz", + "integrity": "sha512-h5bgJWpxJNswbU7qCrV0tIKQCaS3blPDrqKWx+QxzuzL1zGUzij9XCWLrSLsJPu5t+eWA/ycetzYAO5IOMcWAQ==", + "dev": true, + "bin": { + "lz-string": "bin/bin.js" + } + }, + "node_modules/magic-string": { + "version": "0.30.8", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.8.tgz", + "integrity": "sha512-ISQTe55T2ao7XtlAStud6qwYPZjE4GK1S/BeVPus4jrq6JuOnQ00YKQC581RWhR122W7msZV263KzVeLoqidyQ==", + "dev": true, + "dependencies": { + "@jridgewell/sourcemap-codec": "^1.4.15" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/magicast": { + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/magicast/-/magicast-0.3.5.tgz", + "integrity": "sha512-L0WhttDl+2BOsybvEOLK7fW3UA0OQ0IQ2d6Zl2x/a6vVRs3bAY0ECOSHHeL5jD+SbOpOCUEi0y1DgHEn9Qn1AQ==", + "dev": true, + "dependencies": { + "@babel/parser": "^7.25.4", + "@babel/types": "^7.25.4", + "source-map-js": "^1.2.0" + } + }, + "node_modules/make-dir": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-4.0.0.tgz", + "integrity": "sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw==", + "dev": true, + "dependencies": { + "semver": "^7.5.3" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/make-dir/node_modules/semver": { + "version": "7.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.2.tgz", + "integrity": "sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/markdown-it": { + "version": "14.1.0", + "resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-14.1.0.tgz", + "integrity": "sha512-a54IwgWPaeBCAAsv13YgmALOF1elABB08FxO9i+r4VFk5Vl4pKokRPeX8u5TCgSsPi6ec1otfLjdOpVcgbpshg==", + "peer": true, + "dependencies": { + "argparse": "^2.0.1", + "entities": "^4.4.0", + "linkify-it": "^5.0.0", + "mdurl": "^2.0.0", + "punycode.js": "^2.3.1", + "uc.micro": "^2.1.0" + }, + "bin": { + "markdown-it": "bin/markdown-it.mjs" + } + }, + "node_modules/math-intrinsics": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", + "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/mdn-data": { + "version": "2.0.30", + "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.30.tgz", + "integrity": "sha512-GaqWWShW4kv/G9IEucWScBx9G1/vsFZZJUO+tD26M8J8z3Kw5RDQjaoZe03YAClgeS/SWPOcb4nkFBTEi5DUEA==", + "dev": true + }, + "node_modules/mdurl": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/mdurl/-/mdurl-2.0.0.tgz", + "integrity": "sha512-Lf+9+2r+Tdp5wXDXC4PcIBjTDtq4UKjCPMQhKIuzpJNW0b96kVqSwW0bT7FhRSfmAiFYgP+SCRvdrDozfh0U5w==", + "peer": true + }, + "node_modules/media-engine": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/media-engine/-/media-engine-1.0.3.tgz", + "integrity": "sha512-aa5tG6sDoK+k70B9iEX1NeyfT8ObCKhNDs6lJVpwF6r8vhUfuKMslIcirq6HIUYuuUYLefcEQOn9bSBOvawtwg==" + }, + "node_modules/micromatch": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", + "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", + "devOptional": true, + "dependencies": { + "braces": "^3.0.3", + "picomatch": "^2.3.1" + }, + "engines": { + "node": ">=8.6" + } + }, + "node_modules/mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mimic-function": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/mimic-function/-/mimic-function-5.0.1.tgz", + "integrity": "sha512-VP79XUPxV2CigYP3jWwAUFSku2aKqBH7uTAapFWCBqutsbmDo96KY5o8uh6U+/YSIn5OxJnXp73beVkpqMIGhA==", + "dev": true, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/min-indent": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/min-indent/-/min-indent-1.0.1.tgz", + "integrity": "sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "devOptional": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/minipass": { + "version": "4.2.8", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-4.2.8.tgz", + "integrity": "sha512-fNzuVyifolSLFL4NzpF+wEF4qrgqaaKX0haXPQEdQ7NKAN+WecoKMHV09YcuL/DHxrUsYQOK3MiuDf7Ip2OXfQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/mitt": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/mitt/-/mitt-3.0.1.tgz", + "integrity": "sha512-vKivATfr97l2/QBCYAkXYDbrIWPM2IIKEl7YPhjCvKlG3kE2gm+uBo6nEXK3M5/Ffh/FLpKExzOQ3JJoJGFKBw==" + }, + "node_modules/mlly": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/mlly/-/mlly-1.8.0.tgz", + "integrity": "sha512-l8D9ODSRWLe2KHJSifWGwBqpTZXIXTeo8mlKjY+E2HAakaTeNpqAyBZ8GSqLzHgw4XmHmC8whvpjJNMbFZN7/g==", + "dev": true, + "dependencies": { + "acorn": "^8.15.0", + "pathe": "^2.0.3", + "pkg-types": "^1.3.1", + "ufo": "^1.6.1" + } + }, + "node_modules/mlly/node_modules/confbox": { + "version": "0.1.8", + "resolved": "https://registry.npmjs.org/confbox/-/confbox-0.1.8.tgz", + "integrity": "sha512-RMtmw0iFkeR4YV+fUOSucriAQNb9g8zFR52MWCtl+cCZOFRNL6zeB395vPzFhEjjn4fMxXudmELnl/KF/WrK6w==", + "dev": true + }, + "node_modules/mlly/node_modules/pkg-types": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/pkg-types/-/pkg-types-1.3.1.tgz", + "integrity": "sha512-/Jm5M4RvtBFVkKWRu2BLUTNP8/M2a+UwuAX+ae4770q1qVGtfjG+WTCupoZixokjmHiry8uI+dlY8KXYV5HVVQ==", + "dev": true, + "dependencies": { + "confbox": "^0.1.8", + "mlly": "^1.7.4", + "pathe": "^2.0.1" + } + }, + "node_modules/moo-color": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/moo-color/-/moo-color-1.0.3.tgz", + "integrity": "sha512-i/+ZKXMDf6aqYtBhuOcej71YSlbjT3wCO/4H1j8rPvxDJEifdwgg5MaFyu6iYAT8GBZJg2z0dkgK4YMzvURALQ==", + "dev": true, + "dependencies": { + "color-name": "^1.1.4" + } + }, + "node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "devOptional": true + }, + "node_modules/nano-spawn": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/nano-spawn/-/nano-spawn-1.0.3.tgz", + "integrity": "sha512-jtpsQDetTnvS2Ts1fiRdci5rx0VYws5jGyC+4IYOTnIQ/wwdf6JdomlHBwqC3bJYOvaKu0C2GSZ1A60anrYpaA==", + "dev": true, + "engines": { + "node": ">=20.17" + }, + "funding": { + "url": "https://github.com/sindresorhus/nano-spawn?sponsor=1" + } + }, + "node_modules/nanoid": { + "version": "3.3.11", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.11.tgz", + "integrity": "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "bin": { + "nanoid": "bin/nanoid.cjs" + }, + "engines": { + "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" + } + }, + "node_modules/natural-compare": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", + "dev": true + }, + "node_modules/node-addon-api": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-7.1.1.tgz", + "integrity": "sha512-5m3bsyrjFWE1xf7nz7YXdN4udnVtXK6/Yfgn5qnahL6bCkf2yKt4k3nuTKAtT4r3IG8JNR2ncsIMdZuAzJjHQQ==", + "optional": true + }, + "node_modules/node-fetch": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz", + "integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==", + "dev": true, + "dependencies": { + "whatwg-url": "^5.0.0" + }, + "engines": { + "node": "4.x || >=6.0.0" + }, + "peerDependencies": { + "encoding": "^0.1.0" + }, + "peerDependenciesMeta": { + "encoding": { + "optional": true + } + } + }, + "node_modules/node-fetch/node_modules/tr46": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", + "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==", + "dev": true + }, + "node_modules/node-fetch/node_modules/webidl-conversions": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", + "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==", + "dev": true + }, + "node_modules/node-fetch/node_modules/whatwg-url": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", + "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", + "dev": true, + "dependencies": { + "tr46": "~0.0.3", + "webidl-conversions": "^3.0.0" + } + }, + "node_modules/node-releases": { + "version": "2.0.20", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.20.tgz", + "integrity": "sha512-7gK6zSXEH6neM212JgfYFXe+GmZQM+fia5SsusuBIUgnPheLFBmIPhtFoAQRj8/7wASYQnbDlHPVwY0BefoFgA==", + "dev": true + }, + "node_modules/nopt": { + "version": "7.2.1", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-7.2.1.tgz", + "integrity": "sha512-taM24ViiimT/XntxbPyJQzCG+p4EKOpgD3mxFwW38mGjVUrfERQOeY4EDHjdnptttfHuHQXFx+lTP08Q+mLa/w==", + "dev": true, + "dependencies": { + "abbrev": "^2.0.0" + }, + "bin": { + "nopt": "bin/nopt.js" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/normalize-range": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/normalize-range/-/normalize-range-0.1.2.tgz", + "integrity": "sha512-bdok/XvKII3nUpklnV6P2hxtMNrCboOjAcyBuQnWEhO665FwrSNRxU+AqpsyvO6LgGYPspN+lu5CLtw4jPRKNA==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/normalize-svg-path": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/normalize-svg-path/-/normalize-svg-path-1.1.0.tgz", + "integrity": "sha512-r9KHKG2UUeB5LoTouwDzBy2VxXlHsiM6fyLQvnJa0S5hrhzqElH/CH7TUGhT1fVvIYBIKf3OpY4YJ4CK+iaqHg==", + "dependencies": { + "svg-arc-to-cubic-bezier": "^3.0.0" + } + }, + "node_modules/nth-check": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.1.1.tgz", + "integrity": "sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==", + "dev": true, + "dependencies": { + "boolbase": "^1.0.0" + }, + "funding": { + "url": "https://github.com/fb55/nth-check?sponsor=1" + } + }, + "node_modules/nwsapi": { + "version": "2.2.22", + "resolved": "https://registry.npmjs.org/nwsapi/-/nwsapi-2.2.22.tgz", + "integrity": "sha512-ujSMe1OWVn55euT1ihwCI1ZcAaAU3nxUiDwfDQldc51ZXaB9m2AyOn6/jh1BLe2t/G8xd6uKG1UBF2aZJeg2SQ==", + "dev": true + }, + "node_modules/object-inspect": { + "version": "1.13.4", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.4.tgz", + "integrity": "sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/object-is": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/object-is/-/object-is-1.1.6.tgz", + "integrity": "sha512-F8cZ+KfGlSGi09lJT7/Nd6KJZ9ygtvYC0/UYYLI9nmQKLMnydpB9yvbv9K1uSkEu7FU9vYPmVwLg328tX+ot3Q==", + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/object-keys": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", + "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/object.assign": { + "version": "4.1.7", + "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.7.tgz", + "integrity": "sha512-nK28WOo+QIjBkDduTINE4JkF/UJJKyf2EJxvJKfblDpyg0Q+pkOHNTL0Qwy6NP6FhE/EnzV73BxxqcJaXY9anw==", + "dependencies": { + "call-bind": "^1.0.8", + "call-bound": "^1.0.3", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.0.0", + "has-symbols": "^1.1.0", + "object-keys": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "devOptional": true, + "dependencies": { + "wrappy": "1" + } + }, + "node_modules/onetime": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-7.0.0.tgz", + "integrity": "sha512-VXJjc87FScF88uafS3JllDgvAm+c/Slfz06lorj2uAY34rlUu0Nt+v8wreiImcrgAjjIHp1rXpTDlLOGw29WwQ==", + "dev": true, + "dependencies": { + "mimic-function": "^5.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/optionator": { + "version": "0.9.4", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz", + "integrity": "sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==", + "dev": true, + "dependencies": { + "deep-is": "^0.1.3", + "fast-levenshtein": "^2.0.6", + "levn": "^0.4.1", + "prelude-ls": "^1.2.1", + "type-check": "^0.4.0", + "word-wrap": "^1.2.5" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/orderedmap": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/orderedmap/-/orderedmap-2.1.1.tgz", + "integrity": "sha512-TvAWxi0nDe1j/rtMcWcIj94+Ffe6n7zhow33h40SKxmsmozs6dz/e+EajymfoFcHd7sxNn8yHM8839uixMOV6g==", + "peer": true + }, + "node_modules/p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "dev": true, + "dependencies": { + "yocto-queue": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-locate": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "dev": true, + "dependencies": { + "p-limit": "^3.0.2" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/package-json-from-dist": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.1.tgz", + "integrity": "sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==", + "dev": true + }, + "node_modules/pako": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/pako/-/pako-1.0.11.tgz", + "integrity": "sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw==" + }, + "node_modules/parent-module": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", + "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", + "dev": true, + "dependencies": { + "callsites": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/parse-svg-path": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/parse-svg-path/-/parse-svg-path-0.1.2.tgz", + "integrity": "sha512-JyPSBnkTJ0AI8GGJLfMXvKq42cj5c006fnLz6fXy6zfoVjJizi8BNTpu8on8ziI1cKy9d9DGNuY17Ce7wuejpQ==" + }, + "node_modules/parse5": { + "version": "7.3.0", + "resolved": "https://registry.npmjs.org/parse5/-/parse5-7.3.0.tgz", + "integrity": "sha512-IInvU7fabl34qmi9gY8XOVxhYyMyuH2xUNpb2q8/Y+7552KlejkRvqvD19nMoUW/uQGGbqNpA6Tufu5FL5BZgw==", + "dev": true, + "dependencies": { + "entities": "^6.0.0" + }, + "funding": { + "url": "https://github.com/inikulin/parse5?sponsor=1" + } + }, + "node_modules/parse5-htmlparser2-tree-adapter": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/parse5-htmlparser2-tree-adapter/-/parse5-htmlparser2-tree-adapter-7.1.0.tgz", + "integrity": "sha512-ruw5xyKs6lrpo9x9rCZqZZnIUntICjQAd0Wsmp396Ul9lN/h+ifgVV1x1gZHi8euej6wTfpqX8j+BFQxF0NS/g==", + "dev": true, + "dependencies": { + "domhandler": "^5.0.3", + "parse5": "^7.0.0" + }, + "funding": { + "url": "https://github.com/inikulin/parse5?sponsor=1" + } + }, + "node_modules/parse5-parser-stream": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/parse5-parser-stream/-/parse5-parser-stream-7.1.2.tgz", + "integrity": "sha512-JyeQc9iwFLn5TbvvqACIF/VXG6abODeB3Fwmv/TGdLk2LfbWkaySGY72at4+Ty7EkPZj854u4CrICqNk2qIbow==", + "dev": true, + "dependencies": { + "parse5": "^7.0.0" + }, + "funding": { + "url": "https://github.com/inikulin/parse5?sponsor=1" + } + }, + "node_modules/parse5/node_modules/entities": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/entities/-/entities-6.0.1.tgz", + "integrity": "sha512-aN97NXWF6AWBTahfVOIrB/NShkzi5H7F9r1s9mD3cDj4Ko5f2qhhVoYMibXF7GlLveb/D2ioWay8lxI97Ven3g==", + "dev": true, + "engines": { + "node": ">=0.12" + }, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, + "node_modules/path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", + "devOptional": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/path-parse": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", + "dev": true + }, + "node_modules/path-scurry": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.11.1.tgz", + "integrity": "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==", + "dev": true, + "dependencies": { + "lru-cache": "^10.2.0", + "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" + }, + "engines": { + "node": ">=16 || 14 >=14.18" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/path-scurry/node_modules/lru-cache": { + "version": "10.4.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz", + "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==", + "dev": true + }, + "node_modules/path-scurry/node_modules/minipass": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz", + "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==", + "dev": true, + "engines": { + "node": ">=16 || 14 >=14.17" + } + }, + "node_modules/pathe": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/pathe/-/pathe-2.0.3.tgz", + "integrity": "sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==", + "dev": true + }, + "node_modules/pathval": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/pathval/-/pathval-2.0.1.tgz", + "integrity": "sha512-//nshmD55c46FuFw26xV/xFAaB5HF9Xdap7HJBBnrKdAd6/GxDBaNA1870O79+9ueg61cZLSVc+OaFlfmObYVQ==", + "dev": true, + "engines": { + "node": ">= 14.16" + } + }, + "node_modules/perfect-debounce": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/perfect-debounce/-/perfect-debounce-1.0.0.tgz", + "integrity": "sha512-xCy9V055GLEqoFaHoC1SoLIaLmWctgCUaBaWxDZ7/Zx4CTyX7cJQLJOok/orfjZAh9kEYpjJa4d0KcJmCbctZA==" + }, + "node_modules/picocolors": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==" + }, + "node_modules/picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "devOptional": true, + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/pidtree": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/pidtree/-/pidtree-0.6.0.tgz", + "integrity": "sha512-eG2dWTVw5bzqGRztnHExczNxt5VGsE6OwTeCG3fdUf9KBsZzO3R5OIIIzWR+iZA0NtZ+RDVdaoE2dK1cn6jH4g==", + "dev": true, + "bin": { + "pidtree": "bin/pidtree.js" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/pkg-types": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pkg-types/-/pkg-types-2.3.0.tgz", + "integrity": "sha512-SIqCzDRg0s9npO5XQ3tNZioRY1uK06lA41ynBC1YmFTmnY6FjUjVt6s4LoADmwoig1qqD0oK8h1p/8mlMx8Oig==", + "dev": true, + "dependencies": { + "confbox": "^0.2.2", + "exsolve": "^1.0.7", + "pathe": "^2.0.3" + } + }, + "node_modules/possible-typed-array-names": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/possible-typed-array-names/-/possible-typed-array-names-1.1.0.tgz", + "integrity": "sha512-/+5VFTchJDoVj3bhoqi6UeymcD00DAwb1nJwamzPvHEszJ4FpF6SNNbUbOS8yI56qHzdV8eK0qEfOSiodkTdxg==", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/postcss": { + "version": "8.5.6", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.6.tgz", + "integrity": "sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/postcss" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "dependencies": { + "nanoid": "^3.3.11", + "picocolors": "^1.1.1", + "source-map-js": "^1.2.1" + }, + "engines": { + "node": "^10 || ^12 || >=14" + } + }, + "node_modules/postcss-safe-parser": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/postcss-safe-parser/-/postcss-safe-parser-6.0.0.tgz", + "integrity": "sha512-FARHN8pwH+WiS2OPCxJI8FuRJpTVnn6ZNFiqAM2aeW2LwTHWWmWgIyKC6cUo0L8aeKiF/14MNvnpls6R2PBeMQ==", + "dev": true, + "engines": { + "node": ">=12.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + "peerDependencies": { + "postcss": "^8.3.3" + } + }, + "node_modules/postcss-scss": { + "version": "4.0.9", + "resolved": "https://registry.npmjs.org/postcss-scss/-/postcss-scss-4.0.9.tgz", + "integrity": "sha512-AjKOeiwAitL/MXxQW2DliT28EKukvvbEWx3LBmJIRN8KfBGZbRTxNYW0kSqi1COiTZ57nZ9NW06S6ux//N1c9A==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/postcss-scss" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "engines": { + "node": ">=12.0" + }, + "peerDependencies": { + "postcss": "^8.4.29" + } + }, + "node_modules/postcss-selector-parser": { + "version": "6.1.2", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.1.2.tgz", + "integrity": "sha512-Q8qQfPiZ+THO/3ZrOrO0cJJKfpYCagtMUkXbnEfmgUjwXg6z/WBeOyS9APBBPCTSiDV+s4SwQGu8yFsiMRIudg==", + "dev": true, + "dependencies": { + "cssesc": "^3.0.0", + "util-deprecate": "^1.0.2" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/postcss-styl": { + "version": "0.12.3", + "resolved": "https://registry.npmjs.org/postcss-styl/-/postcss-styl-0.12.3.tgz", + "integrity": "sha512-8I7Cd8sxiEITIp32xBK4K/Aj1ukX6vuWnx8oY/oAH35NfQI4OZaY5nd68Yx8HeN5S49uhQ6DL0rNk0ZBu/TaLg==", + "dev": true, + "dependencies": { + "debug": "^4.1.1", + "fast-diff": "^1.2.0", + "lodash.sortedlastindex": "^4.1.0", + "postcss": "^7.0.27 || ^8.0.0", + "stylus": "^0.57.0" + }, + "engines": { + "node": "^8.10.0 || ^10.13.0 || ^11.10.1 || >=12.13.0" + }, + "funding": { + "url": "https://opencollective.com/stylus" + } + }, + "node_modules/postcss-value-parser": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", + "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==" + }, + "node_modules/prelude-ls": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", + "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", + "dev": true, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/prettier": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.6.2.tgz", + "integrity": "sha512-I7AIg5boAr5R0FFtJ6rCfD+LFsWHp81dolrFD8S79U9tb8Az2nGrJncnMSnys+bpQJfRUzqs9hnA81OAA3hCuQ==", + "dev": true, + "bin": { + "prettier": "bin/prettier.cjs" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/prettier/prettier?sponsor=1" + } + }, + "node_modules/prettier-linter-helpers": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/prettier-linter-helpers/-/prettier-linter-helpers-1.0.0.tgz", + "integrity": "sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w==", + "dev": true, + "dependencies": { + "fast-diff": "^1.1.2" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/pretty-format": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-27.5.1.tgz", + "integrity": "sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ==", + "dev": true, + "dependencies": { + "ansi-regex": "^5.0.1", + "ansi-styles": "^5.0.0", + "react-is": "^17.0.1" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/pretty-format/node_modules/ansi-styles": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", + "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/progress": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz", + "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==", + "dev": true, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/prosemirror-changeset": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/prosemirror-changeset/-/prosemirror-changeset-2.3.1.tgz", + "integrity": "sha512-j0kORIBm8ayJNl3zQvD1TTPHJX3g042et6y/KQhZhnPrruO8exkTgG8X+NRpj7kIyMMEx74Xb3DyMIBtO0IKkQ==", + "peer": true, + "dependencies": { + "prosemirror-transform": "^1.0.0" + } + }, + "node_modules/prosemirror-collab": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/prosemirror-collab/-/prosemirror-collab-1.3.1.tgz", + "integrity": "sha512-4SnynYR9TTYaQVXd/ieUvsVV4PDMBzrq2xPUWutHivDuOshZXqQ5rGbZM84HEaXKbLdItse7weMGOUdDVcLKEQ==", + "peer": true, + "dependencies": { + "prosemirror-state": "^1.0.0" + } + }, + "node_modules/prosemirror-commands": { + "version": "1.7.1", + "resolved": "https://registry.npmjs.org/prosemirror-commands/-/prosemirror-commands-1.7.1.tgz", + "integrity": "sha512-rT7qZnQtx5c0/y/KlYaGvtG411S97UaL6gdp6RIZ23DLHanMYLyfGBV5DtSnZdthQql7W+lEVbpSfwtO8T+L2w==", + "peer": true, + "dependencies": { + "prosemirror-model": "^1.0.0", + "prosemirror-state": "^1.0.0", + "prosemirror-transform": "^1.10.2" + } + }, + "node_modules/prosemirror-dropcursor": { + "version": "1.8.2", + "resolved": "https://registry.npmjs.org/prosemirror-dropcursor/-/prosemirror-dropcursor-1.8.2.tgz", + "integrity": "sha512-CCk6Gyx9+Tt2sbYk5NK0nB1ukHi2ryaRgadV/LvyNuO3ena1payM2z6Cg0vO1ebK8cxbzo41ku2DE5Axj1Zuiw==", + "peer": true, + "dependencies": { + "prosemirror-state": "^1.0.0", + "prosemirror-transform": "^1.1.0", + "prosemirror-view": "^1.1.0" + } + }, + "node_modules/prosemirror-gapcursor": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/prosemirror-gapcursor/-/prosemirror-gapcursor-1.3.2.tgz", + "integrity": "sha512-wtjswVBd2vaQRrnYZaBCbyDqr232Ed4p2QPtRIUK5FuqHYKGWkEwl08oQM4Tw7DOR0FsasARV5uJFvMZWxdNxQ==", + "peer": true, + "dependencies": { + "prosemirror-keymap": "^1.0.0", + "prosemirror-model": "^1.0.0", + "prosemirror-state": "^1.0.0", + "prosemirror-view": "^1.0.0" + } + }, + "node_modules/prosemirror-history": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/prosemirror-history/-/prosemirror-history-1.4.1.tgz", + "integrity": "sha512-2JZD8z2JviJrboD9cPuX/Sv/1ChFng+xh2tChQ2X4bB2HeK+rra/bmJ3xGntCcjhOqIzSDG6Id7e8RJ9QPXLEQ==", + "peer": true, + "dependencies": { + "prosemirror-state": "^1.2.2", + "prosemirror-transform": "^1.0.0", + "prosemirror-view": "^1.31.0", + "rope-sequence": "^1.3.0" + } + }, + "node_modules/prosemirror-inputrules": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/prosemirror-inputrules/-/prosemirror-inputrules-1.5.0.tgz", + "integrity": "sha512-K0xJRCmt+uSw7xesnHmcn72yBGTbY45vm8gXI4LZXbx2Z0jwh5aF9xrGQgrVPu0WbyFVFF3E/o9VhJYz6SQWnA==", + "peer": true, + "dependencies": { + "prosemirror-state": "^1.0.0", + "prosemirror-transform": "^1.0.0" + } + }, + "node_modules/prosemirror-keymap": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/prosemirror-keymap/-/prosemirror-keymap-1.2.3.tgz", + "integrity": "sha512-4HucRlpiLd1IPQQXNqeo81BGtkY8Ai5smHhKW9jjPKRc2wQIxksg7Hl1tTI2IfT2B/LgX6bfYvXxEpJl7aKYKw==", + "peer": true, + "dependencies": { + "prosemirror-state": "^1.0.0", + "w3c-keyname": "^2.2.0" + } + }, + "node_modules/prosemirror-markdown": { + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/prosemirror-markdown/-/prosemirror-markdown-1.13.2.tgz", + "integrity": "sha512-FPD9rHPdA9fqzNmIIDhhnYQ6WgNoSWX9StUZ8LEKapaXU9i6XgykaHKhp6XMyXlOWetmaFgGDS/nu/w9/vUc5g==", + "peer": true, + "dependencies": { + "@types/markdown-it": "^14.0.0", + "markdown-it": "^14.0.0", + "prosemirror-model": "^1.25.0" + } + }, + "node_modules/prosemirror-menu": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/prosemirror-menu/-/prosemirror-menu-1.2.5.tgz", + "integrity": "sha512-qwXzynnpBIeg1D7BAtjOusR+81xCp53j7iWu/IargiRZqRjGIlQuu1f3jFi+ehrHhWMLoyOQTSRx/IWZJqOYtQ==", + "peer": true, + "dependencies": { + "crelt": "^1.0.0", + "prosemirror-commands": "^1.0.0", + "prosemirror-history": "^1.0.0", + "prosemirror-state": "^1.0.0" + } + }, + "node_modules/prosemirror-model": { + "version": "1.25.3", + "resolved": "https://registry.npmjs.org/prosemirror-model/-/prosemirror-model-1.25.3.tgz", + "integrity": "sha512-dY2HdaNXlARknJbrManZ1WyUtos+AP97AmvqdOQtWtrrC5g4mohVX5DTi9rXNFSk09eczLq9GuNTtq3EfMeMGA==", + "peer": true, + "dependencies": { + "orderedmap": "^2.0.0" + } + }, + "node_modules/prosemirror-schema-basic": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/prosemirror-schema-basic/-/prosemirror-schema-basic-1.2.4.tgz", + "integrity": "sha512-ELxP4TlX3yr2v5rM7Sb70SqStq5NvI15c0j9j/gjsrO5vaw+fnnpovCLEGIcpeGfifkuqJwl4fon6b+KdrODYQ==", + "peer": true, + "dependencies": { + "prosemirror-model": "^1.25.0" + } + }, + "node_modules/prosemirror-schema-list": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/prosemirror-schema-list/-/prosemirror-schema-list-1.5.1.tgz", + "integrity": "sha512-927lFx/uwyQaGwJxLWCZRkjXG0p48KpMj6ueoYiu4JX05GGuGcgzAy62dfiV8eFZftgyBUvLx76RsMe20fJl+Q==", + "peer": true, + "dependencies": { + "prosemirror-model": "^1.0.0", + "prosemirror-state": "^1.0.0", + "prosemirror-transform": "^1.7.3" + } + }, + "node_modules/prosemirror-state": { + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/prosemirror-state/-/prosemirror-state-1.4.3.tgz", + "integrity": "sha512-goFKORVbvPuAQaXhpbemJFRKJ2aixr+AZMGiquiqKxaucC6hlpHNZHWgz5R7dS4roHiwq9vDctE//CZ++o0W1Q==", + "peer": true, + "dependencies": { + "prosemirror-model": "^1.0.0", + "prosemirror-transform": "^1.0.0", + "prosemirror-view": "^1.27.0" + } + }, + "node_modules/prosemirror-tables": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/prosemirror-tables/-/prosemirror-tables-1.8.1.tgz", + "integrity": "sha512-DAgDoUYHCcc6tOGpLVPSU1k84kCUWTWnfWX3UDy2Delv4ryH0KqTD6RBI6k4yi9j9I8gl3j8MkPpRD/vWPZbug==", + "peer": true, + "dependencies": { + "prosemirror-keymap": "^1.2.2", + "prosemirror-model": "^1.25.0", + "prosemirror-state": "^1.4.3", + "prosemirror-transform": "^1.10.3", + "prosemirror-view": "^1.39.1" + } + }, + "node_modules/prosemirror-trailing-node": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/prosemirror-trailing-node/-/prosemirror-trailing-node-3.0.0.tgz", + "integrity": "sha512-xiun5/3q0w5eRnGYfNlW1uU9W6x5MoFKWwq/0TIRgt09lv7Hcser2QYV8t4muXbEr+Fwo0geYn79Xs4GKywrRQ==", + "peer": true, + "dependencies": { + "@remirror/core-constants": "3.0.0", + "escape-string-regexp": "^4.0.0" + }, + "peerDependencies": { + "prosemirror-model": "^1.22.1", + "prosemirror-state": "^1.4.2", + "prosemirror-view": "^1.33.8" + } + }, + "node_modules/prosemirror-transform": { + "version": "1.10.4", + "resolved": "https://registry.npmjs.org/prosemirror-transform/-/prosemirror-transform-1.10.4.tgz", + "integrity": "sha512-pwDy22nAnGqNR1feOQKHxoFkkUtepoFAd3r2hbEDsnf4wp57kKA36hXsB3njA9FtONBEwSDnDeCiJe+ItD+ykw==", + "peer": true, + "dependencies": { + "prosemirror-model": "^1.21.0" + } + }, + "node_modules/prosemirror-view": { + "version": "1.41.0", + "resolved": "https://registry.npmjs.org/prosemirror-view/-/prosemirror-view-1.41.0.tgz", + "integrity": "sha512-FatMIIl0vRHMcNc3sPy3cMw5MMyWuO1nWQxqvYpJvXAruucGvmQ2tyyjT2/Lbok77T9a/qZqBVCq4sj43V2ihw==", + "peer": true, + "dependencies": { + "prosemirror-model": "^1.20.0", + "prosemirror-state": "^1.0.0", + "prosemirror-transform": "^1.1.0" + } + }, + "node_modules/proto-list": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/proto-list/-/proto-list-1.2.4.tgz", + "integrity": "sha512-vtK/94akxsTMhe0/cbfpR+syPuszcuwhqVjJq26CuNDgFGj682oRBXOP5MJpv2r7JtE8MsiepGIqvvOTBwn2vA==", + "dev": true + }, + "node_modules/proxy-from-env": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", + "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==" + }, + "node_modules/punycode": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", + "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/punycode.js": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/punycode.js/-/punycode.js-2.3.1.tgz", + "integrity": "sha512-uxFIHU0YlHYhDQtV4R9J6a52SLx28BCjT+4ieh7IGbgwVJWO+km431c4yRlREUAsAmt/uMjQUyQHNEPf0M39CA==", + "peer": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/quansync": { + "version": "0.2.11", + "resolved": "https://registry.npmjs.org/quansync/-/quansync-0.2.11.tgz", + "integrity": "sha512-AifT7QEbW9Nri4tAwR5M/uzpBuqfZf+zwaEM/QkzEjj7NBuFD2rBuy0K3dE+8wltbezDV7JMA0WfnCPYRSYbXA==", + "dev": true, + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/antfu" + }, + { + "type": "individual", + "url": "https://github.com/sponsors/sxzz" + } + ] + }, + "node_modules/queue": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/queue/-/queue-6.0.2.tgz", + "integrity": "sha512-iHZWu+q3IdFZFX36ro/lKBkSvfkztY5Y7HMiPlOUjhupPcG2JMfst2KKEpu5XndviX/3UhFbRngUPNKtgvtZiA==", + "dependencies": { + "inherits": "~2.0.3" + } + }, + "node_modules/react-is": { + "version": "17.0.2", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", + "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==", + "dev": true + }, + "node_modules/readdirp": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-4.1.2.tgz", + "integrity": "sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg==", + "devOptional": true, + "engines": { + "node": ">= 14.18.0" + }, + "funding": { + "type": "individual", + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/recaptcha-v3": { + "version": "1.11.3", + "resolved": "https://registry.npmjs.org/recaptcha-v3/-/recaptcha-v3-1.11.3.tgz", + "integrity": "sha512-sEE6J0RzUkS+sKEBpgCD/AqCU0ffrAVOADGjvAx9vcttN+VLK42SWMkj/J/I6vHu3Kew+xcfbBqDVb65N0QGDw==" + }, + "node_modules/redent": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/redent/-/redent-3.0.0.tgz", + "integrity": "sha512-6tDA8g98We0zd0GvVeMT9arEOnTw9qM03L9cJXaCjrip1OO764RDBLBfrB4cwzNGDj5OA5ioymC9GkizgWJDUg==", + "dev": true, + "dependencies": { + "indent-string": "^4.0.0", + "strip-indent": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/regenerate": { + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.2.tgz", + "integrity": "sha512-zrceR/XhGYU/d/opr2EKO7aRHUeiBI8qjtfHqADTwZd6Szfy16la6kqD0MIUs5z5hx6AaKa+PixpPrR289+I0A==", + "dev": true + }, + "node_modules/regenerate-unicode-properties": { + "version": "10.2.0", + "resolved": "https://registry.npmjs.org/regenerate-unicode-properties/-/regenerate-unicode-properties-10.2.0.tgz", + "integrity": "sha512-DqHn3DwbmmPVzeKj9woBadqmXxLvQoQIwu7nopMc72ztvxVmVk2SBhSnx67zuye5TP+lJsb/TBQsjLKhnDf3MA==", + "dev": true, + "dependencies": { + "regenerate": "^1.4.2" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/regexp.prototype.flags": { + "version": "1.5.4", + "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.4.tgz", + "integrity": "sha512-dYqgNSZbDwkaJ2ceRd9ojCGjBq+mOm9LmtXnAnEGyHhN/5R7iDW2TRw3h+o/jCFxus3P2LfWIIiwowAjANm7IA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.8", + "define-properties": "^1.2.1", + "es-errors": "^1.3.0", + "get-proto": "^1.0.1", + "gopd": "^1.2.0", + "set-function-name": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/regexpu-core": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-6.2.0.tgz", + "integrity": "sha512-H66BPQMrv+V16t8xtmq+UC0CBpiTBA60V8ibS1QVReIp8T1z8hwFxqcGzm9K6lgsN7sB5edVH8a+ze6Fqm4weA==", + "dev": true, + "dependencies": { + "regenerate": "^1.4.2", + "regenerate-unicode-properties": "^10.2.0", + "regjsgen": "^0.8.0", + "regjsparser": "^0.12.0", + "unicode-match-property-ecmascript": "^2.0.0", + "unicode-match-property-value-ecmascript": "^2.1.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/regjsgen": { + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/regjsgen/-/regjsgen-0.8.0.tgz", + "integrity": "sha512-RvwtGe3d7LvWiDQXeQw8p5asZUmfU1G/l6WbUXeHta7Y2PEIvBTwH6E2EfmYUK8pxcxEdEmaomqyp0vZZ7C+3Q==", + "dev": true + }, + "node_modules/regjsparser": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.12.0.tgz", + "integrity": "sha512-cnE+y8bz4NhMjISKbgeVJtqNbtf5QpjZP+Bslo+UqkIt9QPnX9q095eiRRASJG1/tz6dlNr6Z5NsBiWYokp6EQ==", + "dev": true, + "dependencies": { + "jsesc": "~3.0.2" + }, + "bin": { + "regjsparser": "bin/parser" + } + }, + "node_modules/regjsparser/node_modules/jsesc": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.0.2.tgz", + "integrity": "sha512-xKqzzWXDttJuOcawBt4KnKHHIf5oQ/Cxax+0PWFG+DFDgHNAdi+TXECADI+RYiFUMmx8792xsMbbgXj4CwnP4g==", + "dev": true, + "bin": { + "jsesc": "bin/jsesc" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/require-from-string": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", + "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/resize-observer-polyfill": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/resize-observer-polyfill/-/resize-observer-polyfill-1.5.1.tgz", + "integrity": "sha512-LwZrotdHOo12nQuZlHEmtuXdqGoOD0OhaxopaNFxWzInpEgaLWoVuAMbTzixuosCx2nEG58ngzW3vxdWoxIgdg==" + }, + "node_modules/resolve": { + "version": "1.22.10", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.10.tgz", + "integrity": "sha512-NPRy+/ncIMeDlTAsuqwKIiferiawhefFJtkNSW0qZJEqMEb+qBt/77B/jGeeek+F0uOeN05CDa6HXbbIgtVX4w==", + "dev": true, + "dependencies": { + "is-core-module": "^2.16.0", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + }, + "bin": { + "resolve": "bin/resolve" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/resolve-from": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/resolve-pkg-maps": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/resolve-pkg-maps/-/resolve-pkg-maps-1.0.0.tgz", + "integrity": "sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==", + "dev": true, + "funding": { + "url": "https://github.com/privatenumber/resolve-pkg-maps?sponsor=1" + } + }, + "node_modules/restore-cursor": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-5.1.0.tgz", + "integrity": "sha512-oMA2dcrw6u0YfxJQXm342bFKX/E4sG9rbTzO9ptUcR/e8A33cHuvStiYOwH7fszkZlZ1z/ta9AAoPk2F4qIOHA==", + "dev": true, + "dependencies": { + "onetime": "^7.0.0", + "signal-exit": "^4.1.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/restructure": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/restructure/-/restructure-3.0.2.tgz", + "integrity": "sha512-gSfoiOEA0VPE6Tukkrr7I0RBdE0s7H1eFCDBk05l1KIQT1UIKNc5JZy6jdyW6eYH3aR3g5b3PuL77rq0hvwtAw==" + }, + "node_modules/rfdc": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.4.1.tgz", + "integrity": "sha512-q1b3N5QkRUWUl7iyylaaj3kOpIT0N2i9MqIEQXP73GVsN9cw3fdx8X63cEmWhJGi2PPCF23Ijp7ktmd39rawIA==" + }, + "node_modules/rollup": { + "version": "4.50.0", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.50.0.tgz", + "integrity": "sha512-/Zl4D8zPifNmyGzJS+3kVoyXeDeT/GrsJM94sACNg9RtUE0hrHa1bNPtRSrfHTMH5HjRzce6K7rlTh3Khiw+pw==", + "devOptional": true, + "dependencies": { + "@types/estree": "1.0.8" + }, + "bin": { + "rollup": "dist/bin/rollup" + }, + "engines": { + "node": ">=18.0.0", + "npm": ">=8.0.0" + }, + "optionalDependencies": { + "@rollup/rollup-android-arm-eabi": "4.50.0", + "@rollup/rollup-android-arm64": "4.50.0", + "@rollup/rollup-darwin-arm64": "4.50.0", + "@rollup/rollup-darwin-x64": "4.50.0", + "@rollup/rollup-freebsd-arm64": "4.50.0", + "@rollup/rollup-freebsd-x64": "4.50.0", + "@rollup/rollup-linux-arm-gnueabihf": "4.50.0", + "@rollup/rollup-linux-arm-musleabihf": "4.50.0", + "@rollup/rollup-linux-arm64-gnu": "4.50.0", + "@rollup/rollup-linux-arm64-musl": "4.50.0", + "@rollup/rollup-linux-loongarch64-gnu": "4.50.0", + "@rollup/rollup-linux-ppc64-gnu": "4.50.0", + "@rollup/rollup-linux-riscv64-gnu": "4.50.0", + "@rollup/rollup-linux-riscv64-musl": "4.50.0", + "@rollup/rollup-linux-s390x-gnu": "4.50.0", + "@rollup/rollup-linux-x64-gnu": "4.50.0", + "@rollup/rollup-linux-x64-musl": "4.50.0", + "@rollup/rollup-openharmony-arm64": "4.50.0", + "@rollup/rollup-win32-arm64-msvc": "4.50.0", + "@rollup/rollup-win32-ia32-msvc": "4.50.0", + "@rollup/rollup-win32-x64-msvc": "4.50.0", + "fsevents": "~2.3.2" + } + }, + "node_modules/rope-sequence": { + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/rope-sequence/-/rope-sequence-1.3.4.tgz", + "integrity": "sha512-UT5EDe2cu2E/6O4igUr5PSFs23nvvukicWHx6GnOPlHAiiYbzNuCRQCuiUdHJQcqKalLKlrYJnjY0ySGsXNQXQ==", + "peer": true + }, + "node_modules/rrweb-cssom": { + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/rrweb-cssom/-/rrweb-cssom-0.8.0.tgz", + "integrity": "sha512-guoltQEx+9aMf2gDZ0s62EcV8lsXR+0w8915TC3ITdn2YueuNjdAYh/levpU9nFaoChh9RUS5ZdQMrKfVEN9tw==", + "dev": true + }, + "node_modules/runes": { + "version": "0.4.3", + "resolved": "https://registry.npmjs.org/runes/-/runes-0.4.3.tgz", + "integrity": "sha512-K6p9y4ZyL9wPzA+PMDloNQPfoDGTiFYDvdlXznyGKgD10BJpcAosvATKrExRKOrNLgD8E7Um7WGW0lxsnOuNLg==", + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/safe-regex-test": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.1.0.tgz", + "integrity": "sha512-x/+Cz4YrimQxQccJf5mKEbIa1NzeCRNI5Ecl/ekmlYaampdNLPalVyIcCZNNH3MvmqBugV5TMYZXv0ljslUlaw==", + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "is-regex": "^1.2.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", + "devOptional": true + }, + "node_modules/sass": { + "version": "1.89.2", + "resolved": "https://registry.npmjs.org/sass/-/sass-1.89.2.tgz", + "integrity": "sha512-xCmtksBKd/jdJ9Bt9p7nPKiuqrlBMBuuGkQlkhZjjQk3Ty48lv93k5Dq6OPkKt4XwxDJ7tvlfrTa1MPA9bf+QA==", + "devOptional": true, + "dependencies": { + "chokidar": "^4.0.0", + "immutable": "^5.0.2", + "source-map-js": ">=0.6.2 <2.0.0" + }, + "bin": { + "sass": "sass.js" + }, + "engines": { + "node": ">=14.0.0" + }, + "optionalDependencies": { + "@parcel/watcher": "^2.4.1" + } + }, + "node_modules/sax": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz", + "integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==", + "devOptional": true + }, + "node_modules/saxes": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/saxes/-/saxes-6.0.0.tgz", + "integrity": "sha512-xAg7SOnEhrm5zI3puOOKyy1OMcMlIJZYNJY7xLBwSze0UjhPLnWfj2GF2EpT0jmzaJKIWKHLsaSSajf35bcYnA==", + "dev": true, + "dependencies": { + "xmlchars": "^2.2.0" + }, + "engines": { + "node": ">=v12.22.7" + } + }, + "node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/set-function-length": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz", + "integrity": "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==", + "dependencies": { + "define-data-property": "^1.1.4", + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.4", + "gopd": "^1.0.1", + "has-property-descriptors": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/set-function-name": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/set-function-name/-/set-function-name-2.0.2.tgz", + "integrity": "sha512-7PGFlmtwsEADb0WYyvCMa1t+yke6daIG4Wirafur5kcf+MhUnPms1UeR0CKQdTZD81yESwMHbtn+TR+dMviakQ==", + "dev": true, + "dependencies": { + "define-data-property": "^1.1.4", + "es-errors": "^1.3.0", + "functions-have-names": "^1.2.3", + "has-property-descriptors": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dev": true, + "dependencies": { + "shebang-regex": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/side-channel": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.1.0.tgz", + "integrity": "sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==", + "dev": true, + "dependencies": { + "es-errors": "^1.3.0", + "object-inspect": "^1.13.3", + "side-channel-list": "^1.0.0", + "side-channel-map": "^1.0.1", + "side-channel-weakmap": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-list": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/side-channel-list/-/side-channel-list-1.0.0.tgz", + "integrity": "sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA==", + "dev": true, + "dependencies": { + "es-errors": "^1.3.0", + "object-inspect": "^1.13.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-map": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/side-channel-map/-/side-channel-map-1.0.1.tgz", + "integrity": "sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==", + "dev": true, + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.5", + "object-inspect": "^1.13.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-weakmap": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/side-channel-weakmap/-/side-channel-weakmap-1.0.2.tgz", + "integrity": "sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==", + "dev": true, + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.5", + "object-inspect": "^1.13.3", + "side-channel-map": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/siginfo": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/siginfo/-/siginfo-2.0.0.tgz", + "integrity": "sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g==", + "dev": true + }, + "node_modules/signal-exit": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", + "dev": true, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/simple-swizzle": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/simple-swizzle/-/simple-swizzle-0.2.2.tgz", + "integrity": "sha512-JA//kQgZtbuY83m+xT+tXJkmJncGMTFT+C+g2h2R9uxkYIrE2yy9sgmcLhCnw57/WSD+Eh3J97FPEDFnbXnDUg==", + "dependencies": { + "is-arrayish": "^0.3.1" + } + }, + "node_modules/slice-ansi": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-5.0.0.tgz", + "integrity": "sha512-FC+lgizVPfie0kkhqUScwRu1O/lF6NOgJmlCgK+/LYxDCTk8sGelYaHDhFcDN+Sn3Cv+3VSa4Byeo+IMCzpMgQ==", + "dev": true, + "dependencies": { + "ansi-styles": "^6.0.0", + "is-fullwidth-code-point": "^4.0.0" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/slice-ansi?sponsor=1" + } + }, + "node_modules/slice-ansi/node_modules/ansi-styles": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", + "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/slugify": { + "version": "1.6.6", + "resolved": "https://registry.npmjs.org/slugify/-/slugify-1.6.6.tgz", + "integrity": "sha512-h+z7HKHYXj6wJU+AnS/+IH8Uh9fdcX1Lrhg1/VMdf9PwoBQXFcXiAdsy2tSK0P6gKwJLXp02r90ahUCqHk9rrw==", + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/sortablejs": { + "version": "1.10.2", + "resolved": "https://registry.npmjs.org/sortablejs/-/sortablejs-1.10.2.tgz", + "integrity": "sha512-YkPGufevysvfwn5rfdlGyrGjt7/CRHwvRPogD/lC+TnvcN29jDpCifKP+rBqf+LRldfXSTh+0CGLcSg0VIxq3A==" + }, + "node_modules/source-map": { + "version": "0.7.6", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.6.tgz", + "integrity": "sha512-i5uvt8C3ikiWeNZSVZNWcfZPItFQOsYTUAOkcUPGd8DqDy1uOUikjt5dG+uRlwyvR108Fb9DOd4GvXfT0N2/uQ==", + "devOptional": true, + "engines": { + "node": ">= 12" + } + }, + "node_modules/source-map-js": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", + "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/source-map-resolve": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/source-map-resolve/-/source-map-resolve-0.6.0.tgz", + "integrity": "sha512-KXBr9d/fO/bWo97NXsPIAW1bFSBOuCnjbNTBMO7N59hsv5i9yzRDfcYwwt0l04+VqnKC+EwzvJZIP/qkuMgR/w==", + "deprecated": "See https://github.com/lydell/source-map-resolve#deprecated", + "devOptional": true, + "dependencies": { + "atob": "^2.1.2", + "decode-uri-component": "^0.2.0" + } + }, + "node_modules/speakingurl": { + "version": "14.0.1", + "resolved": "https://registry.npmjs.org/speakingurl/-/speakingurl-14.0.1.tgz", + "integrity": "sha512-1POYv7uv2gXoyGFpBCmpDVSNV74IfsWlDW216UPjbWufNf+bSU6GdbDsxdcxtfwb4xlI3yxzOTKClUosxARYrQ==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/stackback": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/stackback/-/stackback-0.0.2.tgz", + "integrity": "sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw==", + "dev": true + }, + "node_modules/std-env": { + "version": "3.9.0", + "resolved": "https://registry.npmjs.org/std-env/-/std-env-3.9.0.tgz", + "integrity": "sha512-UGvjygr6F6tpH7o2qyqR6QYpwraIjKSdtzyBdyytFOHmPZY917kwdwLG0RbOjWOnKmnm3PeHjaoLLMie7kPLQw==", + "dev": true + }, + "node_modules/stop-iteration-iterator": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/stop-iteration-iterator/-/stop-iteration-iterator-1.1.0.tgz", + "integrity": "sha512-eLoXW/DHyl62zxY4SCaIgnRhuMr6ri4juEYARS8E6sCEqzKpOiE521Ucofdx+KnDZl5xmvGYaaKCk5FEOxJCoQ==", + "dev": true, + "dependencies": { + "es-errors": "^1.3.0", + "internal-slot": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/string_decoder": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", + "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", + "dependencies": { + "safe-buffer": "~5.2.0" + } + }, + "node_modules/string-argv": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/string-argv/-/string-argv-0.3.2.tgz", + "integrity": "sha512-aqD2Q0144Z+/RqG52NeHEkZauTAUWJO8c6yTftGJKO3Tja5tUgIfmIl6kExvhtxSDP7fXB6DvzkfMpCd/F3G+Q==", + "dev": true, + "engines": { + "node": ">=0.6.19" + } + }, + "node_modules/string-width": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-7.2.0.tgz", + "integrity": "sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ==", + "dev": true, + "dependencies": { + "emoji-regex": "^10.3.0", + "get-east-asian-width": "^1.0.0", + "strip-ansi": "^7.1.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/string-width-cjs": { + "name": "string-width", + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/string-width-cjs/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true + }, + "node_modules/string-width-cjs/node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/string-width-cjs/node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", + "dev": true, + "dependencies": { + "ansi-regex": "^6.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, + "node_modules/strip-ansi-cjs": { + "name": "strip-ansi", + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-ansi/node_modules/ansi-regex": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.2.0.tgz", + "integrity": "sha512-TKY5pyBkHyADOPYlRT9Lx6F544mPl0vS5Ew7BJ45hA08Q+t3GjbueLliBWN3sMICk6+y7HdyxSzC4bWS8baBdg==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/strip-indent": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-3.0.0.tgz", + "integrity": "sha512-laJTa3Jb+VQpaC6DseHhF7dXVqHTfJPCRDaEbid/drOhgitgYku/letMUqOXFoWV0zIIUbjpdH2t+tYj4bQMRQ==", + "dev": true, + "dependencies": { + "min-indent": "^1.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-json-comments": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", + "dev": true, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/strip-literal": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-literal/-/strip-literal-3.0.0.tgz", + "integrity": "sha512-TcccoMhJOM3OebGhSBEmp3UZ2SfDMZUEBdRA/9ynfLi8yYajyWX3JiXArcJt4Umh4vISpspkQIY8ZZoCqjbviA==", + "dev": true, + "dependencies": { + "js-tokens": "^9.0.1" + }, + "funding": { + "url": "https://github.com/sponsors/antfu" + } + }, + "node_modules/strip-literal/node_modules/js-tokens": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-9.0.1.tgz", + "integrity": "sha512-mxa9E9ITFOt0ban3j6L5MpjwegGz6lBQmM1IJkWeBZGcMxto50+eWdjC/52xDbS2vy0k7vIMK0Fe2wfL9OQSpQ==", + "dev": true + }, + "node_modules/stylus": { + "version": "0.57.0", + "resolved": "https://registry.npmjs.org/stylus/-/stylus-0.57.0.tgz", + "integrity": "sha512-yOI6G8WYfr0q8v8rRvE91wbxFU+rJPo760Va4MF6K0I6BZjO4r+xSynkvyPBP9tV1CIEUeRsiidjIs2rzb1CnQ==", + "devOptional": true, + "dependencies": { + "css": "^3.0.0", + "debug": "^4.3.2", + "glob": "^7.1.6", + "safer-buffer": "^2.1.2", + "sax": "~1.2.4", + "source-map": "^0.7.3" + }, + "bin": { + "stylus": "bin/stylus" + }, + "engines": { + "node": "*" + } + }, + "node_modules/stylus/node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "deprecated": "Glob versions prior to v9 are no longer supported", + "devOptional": true, + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/superjson": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/superjson/-/superjson-2.2.2.tgz", + "integrity": "sha512-5JRxVqC8I8NuOUjzBbvVJAKNM8qoVuH0O77h4WInc/qC2q5IreqKxYwgkga3PfA22OayK2ikceb/B26dztPl+Q==", + "dependencies": { + "copy-anything": "^3.0.2" + }, + "engines": { + "node": ">=16" + } + }, + "node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/supports-preserve-symlinks-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", + "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/svg-arc-to-cubic-bezier": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/svg-arc-to-cubic-bezier/-/svg-arc-to-cubic-bezier-3.2.0.tgz", + "integrity": "sha512-djbJ/vZKZO+gPoSDThGNpKDO+o+bAeA4XQKovvkNCqnIS2t+S4qnLAGQhyyrulhCFRl1WWzAp0wUDV8PpTVU3g==" + }, + "node_modules/svg-tags": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/svg-tags/-/svg-tags-1.0.0.tgz", + "integrity": "sha512-ovssysQTa+luh7A5Weu3Rta6FJlFBBbInjOh722LIt6klpU2/HtdUbszju/G4devcvk8PGt7FCLv5wftu3THUA==", + "dev": true + }, + "node_modules/svgo": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/svgo/-/svgo-3.3.2.tgz", + "integrity": "sha512-OoohrmuUlBs8B8o6MB2Aevn+pRIH9zDALSR+6hhqVfa6fRwG/Qw9VUMSMW9VNg2CFc/MTIfabtdOVl9ODIJjpw==", + "dev": true, + "dependencies": { + "@trysound/sax": "0.2.0", + "commander": "^7.2.0", + "css-select": "^5.1.0", + "css-tree": "^2.3.1", + "css-what": "^6.1.0", + "csso": "^5.0.5", + "picocolors": "^1.0.0" + }, + "bin": { + "svgo": "bin/svgo" + }, + "engines": { + "node": ">=14.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/svgo" + } + }, + "node_modules/svgo/node_modules/commander": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-7.2.0.tgz", + "integrity": "sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==", + "dev": true, + "engines": { + "node": ">= 10" + } + }, + "node_modules/symbol-tree": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/symbol-tree/-/symbol-tree-3.2.4.tgz", + "integrity": "sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==", + "dev": true + }, + "node_modules/synckit": { + "version": "0.11.11", + "resolved": "https://registry.npmjs.org/synckit/-/synckit-0.11.11.tgz", + "integrity": "sha512-MeQTA1r0litLUf0Rp/iisCaL8761lKAZHaimlbGK4j0HysC4PLfqygQj9srcs0m2RdtDYnF8UuYyKpbjHYp7Jw==", + "dev": true, + "dependencies": { + "@pkgr/core": "^0.2.9" + }, + "engines": { + "node": "^14.18.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/synckit" + } + }, + "node_modules/tapable": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.3.tgz", + "integrity": "sha512-ZL6DDuAlRlLGghwcfmSn9sK3Hr6ArtyudlSAiCqQ6IfE+b+HHbydbYDIG15IfS5do+7XQQBdBiubF/cV2dnDzg==", + "dev": true, + "engines": { + "node": ">=6" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + } + }, + "node_modules/test-exclude": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-7.0.1.tgz", + "integrity": "sha512-pFYqmTw68LXVjeWJMST4+borgQP2AyMNbg1BpZh9LbyhUeNkeaPF9gzfPGUAnSMV3qPYdWUwDIjjCLiSDOl7vg==", + "dev": true, + "dependencies": { + "@istanbuljs/schema": "^0.1.2", + "glob": "^10.4.1", + "minimatch": "^9.0.4" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/test-exclude/node_modules/brace-expansion": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz", + "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/test-exclude/node_modules/glob": { + "version": "10.4.5", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.4.5.tgz", + "integrity": "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==", + "dev": true, + "dependencies": { + "foreground-child": "^3.1.0", + "jackspeak": "^3.1.2", + "minimatch": "^9.0.4", + "minipass": "^7.1.2", + "package-json-from-dist": "^1.0.0", + "path-scurry": "^1.11.1" + }, + "bin": { + "glob": "dist/esm/bin.mjs" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/test-exclude/node_modules/minimatch": { + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", + "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", + "dev": true, + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/test-exclude/node_modules/minipass": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz", + "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==", + "dev": true, + "engines": { + "node": ">=16 || 14 >=14.17" + } + }, + "node_modules/tiny-inflate": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/tiny-inflate/-/tiny-inflate-1.0.3.tgz", + "integrity": "sha512-pkY1fj1cKHb2seWDy0B16HeWyczlJA9/WW3u3c4z/NiWDsO3DOU5D7nhTLE9CF0yXv/QZFY7sEJmj24dK+Rrqw==" + }, + "node_modules/tinybench": { + "version": "2.9.0", + "resolved": "https://registry.npmjs.org/tinybench/-/tinybench-2.9.0.tgz", + "integrity": "sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg==", + "dev": true + }, + "node_modules/tinyexec": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/tinyexec/-/tinyexec-0.3.2.tgz", + "integrity": "sha512-KQQR9yN7R5+OSwaK0XQoj22pwHoTlgYqmUscPYoknOoWCWfj/5/ABTMRi69FrKU5ffPVh5QcFikpWJI/P1ocHA==", + "dev": true + }, + "node_modules/tinyglobby": { + "version": "0.2.14", + "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.14.tgz", + "integrity": "sha512-tX5e7OM1HnYr2+a2C/4V0htOcSQcoSTH9KgJnVvNm5zm/cyEWKJ7j7YutsH9CxMdtOkkLFy2AHrMci9IM8IPZQ==", + "devOptional": true, + "dependencies": { + "fdir": "^6.4.4", + "picomatch": "^4.0.2" + }, + "engines": { + "node": ">=12.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/SuperchupuDev" + } + }, + "node_modules/tinyglobby/node_modules/fdir": { + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz", + "integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==", + "devOptional": true, + "engines": { + "node": ">=12.0.0" + }, + "peerDependencies": { + "picomatch": "^3 || ^4" + }, + "peerDependenciesMeta": { + "picomatch": { + "optional": true + } + } + }, + "node_modules/tinyglobby/node_modules/picomatch": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz", + "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", + "devOptional": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/tinypool": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/tinypool/-/tinypool-1.1.1.tgz", + "integrity": "sha512-Zba82s87IFq9A9XmjiX5uZA/ARWDrB03OHlq+Vw1fSdt0I+4/Kutwy8BP4Y/y/aORMo61FQ0vIb5j44vSo5Pkg==", + "dev": true, + "engines": { + "node": "^18.0.0 || >=20.0.0" + } + }, + "node_modules/tinyrainbow": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/tinyrainbow/-/tinyrainbow-2.0.0.tgz", + "integrity": "sha512-op4nsTR47R6p0vMUUoYl/a+ljLFVtlfaXkLQmqfLR1qHma1h/ysYk4hEXZ880bf2CYgTskvTa/e196Vd5dDQXw==", + "dev": true, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/tinyspy": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/tinyspy/-/tinyspy-4.0.3.tgz", + "integrity": "sha512-t2T/WLB2WRgZ9EpE4jgPJ9w+i66UZfDc8wHh0xrwiRNN+UwH98GIJkTeZqX9rg0i0ptwzqW+uYeIF0T4F8LR7A==", + "dev": true, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/tldts": { + "version": "6.1.86", + "resolved": "https://registry.npmjs.org/tldts/-/tldts-6.1.86.tgz", + "integrity": "sha512-WMi/OQ2axVTf/ykqCQgXiIct+mSQDFdH2fkwhPwgEwvJ1kSzZRiinb0zF2Xb8u4+OqPChmyI6MEu4EezNJz+FQ==", + "dev": true, + "dependencies": { + "tldts-core": "^6.1.86" + }, + "bin": { + "tldts": "bin/cli.js" + } + }, + "node_modules/tldts-core": { + "version": "6.1.86", + "resolved": "https://registry.npmjs.org/tldts-core/-/tldts-core-6.1.86.tgz", + "integrity": "sha512-Je6p7pkk+KMzMv2XXKmAE3McmolOQFdxkKw0R8EYNr7sELW46JqnNeTX8ybPiQgvg1ymCoF8LXs5fzFaZvJPTA==", + "dev": true + }, + "node_modules/to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "devOptional": true, + "dependencies": { + "is-number": "^7.0.0" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/tough-cookie": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-5.1.2.tgz", + "integrity": "sha512-FVDYdxtnj0G6Qm/DhNPSb8Ju59ULcup3tuJxkFb5K8Bv2pUXILbf0xZWU8PX8Ov19OXljbUyveOFwRMwkXzO+A==", + "dev": true, + "dependencies": { + "tldts": "^6.1.32" + }, + "engines": { + "node": ">=16" + } + }, + "node_modules/tr46": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-5.1.1.tgz", + "integrity": "sha512-hdF5ZgjTqgAntKkklYw0R03MG2x/bSzTtkxmIRw/sTNV8YXsCJ1tfLAX23lhxhHJlEf3CRCOCGGWw3vI3GaSPw==", + "dev": true, + "dependencies": { + "punycode": "^2.3.1" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/ts-declaration-location": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/ts-declaration-location/-/ts-declaration-location-1.0.7.tgz", + "integrity": "sha512-EDyGAwH1gO0Ausm9gV6T2nUvBgXT5kGoCMJPllOaooZ+4VvJiKBdZE7wK18N1deEowhcUptS+5GXZK8U/fvpwA==", + "dev": true, + "funding": [ + { + "type": "ko-fi", + "url": "https://ko-fi.com/rebeccastevens" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/ts-declaration-location" + } + ], + "dependencies": { + "picomatch": "^4.0.2" + }, + "peerDependencies": { + "typescript": ">=4.0.0" + } + }, + "node_modules/ts-declaration-location/node_modules/picomatch": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz", + "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/tslib": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==" + }, + "node_modules/type-check": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", + "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", + "dev": true, + "dependencies": { + "prelude-ls": "^1.2.1" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/type-fest": { + "version": "4.41.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-4.41.0.tgz", + "integrity": "sha512-TeTSQ6H5YHvpqVwBRcnLDCBnDOHWYu7IvGbHT6N8AOymcr9PJGjc1GTtiWZTYg0NCgYwvnYWEkVChQAr9bjfwA==", + "engines": { + "node": ">=16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/typescript": { + "version": "5.9.2", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.2.tgz", + "integrity": "sha512-CWBzXQrc/qOkhidw1OzBTQuYRbfyxDXJMVJ1XNwUHGROVmuaeiEm3OslpZ1RV96d7SKKjZKrSJu3+t/xlw3R9A==", + "devOptional": true, + "peer": true, + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=14.17" + } + }, + "node_modules/uc.micro": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/uc.micro/-/uc.micro-2.1.0.tgz", + "integrity": "sha512-ARDJmphmdvUk6Glw7y9DQ2bFkKBHwQHLi2lsaH6PPmz/Ka9sFOBsBluozhDltWmnv9u/cF6Rt87znRTPV+yp/A==" + }, + "node_modules/ufo": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/ufo/-/ufo-1.6.1.tgz", + "integrity": "sha512-9a4/uxlTWJ4+a5i0ooc1rU7C7YOw3wT+UGqdeNNHWnOF9qcMBgLRS+4IYUqbczewFx4mLEig6gawh7X6mFlEkA==", + "dev": true + }, + "node_modules/undici": { + "version": "7.15.0", + "resolved": "https://registry.npmjs.org/undici/-/undici-7.15.0.tgz", + "integrity": "sha512-7oZJCPvvMvTd0OlqWsIxTuItTpJBpU1tcbVl24FMn3xt3+VSunwUasmfPJRE57oNO1KsZ4PgA1xTdAX4hq8NyQ==", + "dev": true, + "engines": { + "node": ">=20.18.1" + } + }, + "node_modules/unhead": { + "version": "2.0.14", + "resolved": "https://registry.npmjs.org/unhead/-/unhead-2.0.14.tgz", + "integrity": "sha512-dRP6OCqtShhMVZQe1F4wdt/WsYl2MskxKK+cvfSo0lQnrPJ4oAUQEkxRg7pPP+vJENabhlir31HwAyHUv7wfMg==", + "dependencies": { + "hookable": "^5.5.3" + }, + "funding": { + "url": "https://github.com/sponsors/harlan-zw" + } + }, + "node_modules/unicode-canonical-property-names-ecmascript": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-2.0.1.tgz", + "integrity": "sha512-dA8WbNeb2a6oQzAQ55YlT5vQAWGV9WXOsi3SskE3bcCdM0P4SDd+24zS/OCacdRq5BkdsRj9q3Pg6YyQoxIGqg==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/unicode-match-property-ecmascript": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/unicode-match-property-ecmascript/-/unicode-match-property-ecmascript-2.0.0.tgz", + "integrity": "sha512-5kaZCrbp5mmbz5ulBkDkbY0SsPOjKqVS35VpL9ulMPfSl0J0Xsm+9Evphv9CoIZFwre7aJoa94AY6seMKGVN5Q==", + "dev": true, + "dependencies": { + "unicode-canonical-property-names-ecmascript": "^2.0.0", + "unicode-property-aliases-ecmascript": "^2.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/unicode-match-property-value-ecmascript": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-2.2.0.tgz", + "integrity": "sha512-4IehN3V/+kkr5YeSSDDQG8QLqO26XpL2XP3GQtqwlT/QYSECAwFztxVHjlbh0+gjJ3XmNLS0zDsbgs9jWKExLg==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/unicode-properties": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/unicode-properties/-/unicode-properties-1.4.1.tgz", + "integrity": "sha512-CLjCCLQ6UuMxWnbIylkisbRj31qxHPAurvena/0iwSVbQ2G1VY5/HjV0IRabOEbDHlzZlRdCrD4NhB0JtU40Pg==", + "dependencies": { + "base64-js": "^1.3.0", + "unicode-trie": "^2.0.0" + } + }, + "node_modules/unicode-property-aliases-ecmascript": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-2.1.0.tgz", + "integrity": "sha512-6t3foTQI9qne+OZoVQB/8x8rk2k1eVy1gRXhV3oFQ5T6R1dqQ1xtin3XqSlx3+ATBkliTaR/hHyJBm+LVPNM8w==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/unicode-trie": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/unicode-trie/-/unicode-trie-2.0.0.tgz", + "integrity": "sha512-x7bc76x0bm4prf1VLg79uhAzKw8DVboClSN5VxJuQ+LKDOVEW9CdH+VY7SP+vX7xCYQqzzgQpFqz15zeLvAtZQ==", + "dependencies": { + "pako": "^0.2.5", + "tiny-inflate": "^1.0.0" + } + }, + "node_modules/unicode-trie/node_modules/pako": { + "version": "0.2.9", + "resolved": "https://registry.npmjs.org/pako/-/pako-0.2.9.tgz", + "integrity": "sha512-NUcwaKxUxWrZLpDG+z/xZaCgQITkA/Dv4V/T6bw7VON6l1Xz/VnrBqrYjZQ12TamKHzITTfOEIYUj48y2KXImA==" + }, + "node_modules/unplugin": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/unplugin/-/unplugin-1.0.1.tgz", + "integrity": "sha512-aqrHaVBWW1JVKBHmGo33T5TxeL0qWzfvjWokObHA9bYmN7eNDkwOxmLjhioHl9878qDFMAaT51XNroRyuz7WxA==", + "dev": true, + "dependencies": { + "acorn": "^8.8.1", + "chokidar": "^3.5.3", + "webpack-sources": "^3.2.3", + "webpack-virtual-modules": "^0.5.0" + } + }, + "node_modules/unplugin-utils": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/unplugin-utils/-/unplugin-utils-0.2.5.tgz", + "integrity": "sha512-gwXJnPRewT4rT7sBi/IvxKTjsms7jX7QIDLOClApuZwR49SXbrB1z2NLUZ+vDHyqCj/n58OzRRqaW+B8OZi8vg==", + "dev": true, + "dependencies": { + "pathe": "^2.0.3", + "picomatch": "^4.0.3" + }, + "engines": { + "node": ">=18.12.0" + }, + "funding": { + "url": "https://github.com/sponsors/sxzz" + } + }, + "node_modules/unplugin-utils/node_modules/picomatch": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz", + "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/unplugin-vue-components": { + "version": "28.8.0", + "resolved": "https://registry.npmjs.org/unplugin-vue-components/-/unplugin-vue-components-28.8.0.tgz", + "integrity": "sha512-2Q6ZongpoQzuXDK0ZsVzMoshH0MWZQ1pzVL538G7oIDKRTVzHjppBDS8aB99SADGHN3lpGU7frraCG6yWNoL5Q==", + "dev": true, + "dependencies": { + "chokidar": "^3.6.0", + "debug": "^4.4.1", + "local-pkg": "^1.1.1", + "magic-string": "^0.30.17", + "mlly": "^1.7.4", + "tinyglobby": "^0.2.14", + "unplugin": "^2.3.5", + "unplugin-utils": "^0.2.4" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/antfu" + }, + "peerDependencies": { + "@babel/parser": "^7.15.8", + "@nuxt/kit": "^3.2.2 || ^4.0.0", + "vue": "2 || 3" + }, + "peerDependenciesMeta": { + "@babel/parser": { + "optional": true + }, + "@nuxt/kit": { + "optional": true + } + } + }, + "node_modules/unplugin-vue-components/node_modules/chokidar": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz", + "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==", + "dev": true, + "dependencies": { + "anymatch": "~3.1.2", + "braces": "~3.0.2", + "glob-parent": "~5.1.2", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.6.0" + }, + "engines": { + "node": ">= 8.10.0" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" + } + }, + "node_modules/unplugin-vue-components/node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/unplugin-vue-components/node_modules/magic-string": { + "version": "0.30.18", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.18.tgz", + "integrity": "sha512-yi8swmWbO17qHhwIBNeeZxTceJMeBvWJaId6dyvTSOwTipqeHhMhOrz6513r1sOKnpvQ7zkhlG8tPrpilwTxHQ==", + "dev": true, + "dependencies": { + "@jridgewell/sourcemap-codec": "^1.5.5" + } + }, + "node_modules/unplugin-vue-components/node_modules/readdirp": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", + "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", + "dev": true, + "dependencies": { + "picomatch": "^2.2.1" + }, + "engines": { + "node": ">=8.10.0" + } + }, + "node_modules/unplugin-vue-components/node_modules/unplugin": { + "version": "2.3.10", + "resolved": "https://registry.npmjs.org/unplugin/-/unplugin-2.3.10.tgz", + "integrity": "sha512-6NCPkv1ClwH+/BGE9QeoTIl09nuiAt0gS28nn1PvYXsGKRwM2TCbFA2QiilmehPDTXIe684k4rZI1yl3A1PCUw==", + "dev": true, + "dependencies": { + "@jridgewell/remapping": "^2.3.5", + "acorn": "^8.15.0", + "picomatch": "^4.0.3", + "webpack-virtual-modules": "^0.6.2" + }, + "engines": { + "node": ">=18.12.0" + } + }, + "node_modules/unplugin-vue-components/node_modules/unplugin/node_modules/picomatch": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz", + "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/unplugin-vue-components/node_modules/webpack-virtual-modules": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/webpack-virtual-modules/-/webpack-virtual-modules-0.6.2.tgz", + "integrity": "sha512-66/V2i5hQanC51vBQKPH4aI8NMAcBW59FVBs+rC7eGHupMyfn34q7rZIE+ETlJ+XTevqfUhVVBgSUNSW2flEUQ==", + "dev": true + }, + "node_modules/unplugin/node_modules/chokidar": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz", + "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==", + "dev": true, + "dependencies": { + "anymatch": "~3.1.2", + "braces": "~3.0.2", + "glob-parent": "~5.1.2", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.6.0" + }, + "engines": { + "node": ">= 8.10.0" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" + } + }, + "node_modules/unplugin/node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/unplugin/node_modules/readdirp": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", + "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", + "dev": true, + "dependencies": { + "picomatch": "^2.2.1" + }, + "engines": { + "node": ">=8.10.0" + } + }, + "node_modules/upath": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/upath/-/upath-2.0.1.tgz", + "integrity": "sha512-1uEe95xksV1O0CYKXo8vQvN1JEbtJp7lb7C5U9HMsIp6IVwntkH/oNUzyVNQSd4S1sYk2FpSSW44FqMc8qee5w==", + "devOptional": true, + "engines": { + "node": ">=4", + "yarn": "*" + } + }, + "node_modules/update-browserslist-db": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.3.tgz", + "integrity": "sha512-UxhIZQ+QInVdunkDAaiazvvT/+fXL5Osr0JZlJulepYu6Jd7qJtDZjlur0emRlT71EN3ScPoE7gvsuIKKNavKw==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "dependencies": { + "escalade": "^3.2.0", + "picocolors": "^1.1.1" + }, + "bin": { + "update-browserslist-db": "cli.js" + }, + "peerDependencies": { + "browserslist": ">= 4.21.0" + } + }, + "node_modules/uri-js": { + "name": "uri-js-replace", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/uri-js-replace/-/uri-js-replace-1.0.1.tgz", + "integrity": "sha512-W+C9NWNLFOoBI2QWDp4UT9pv65r2w5Cx+3sTYFvtMdDBxkKt1syCqsUdSFAChbEe1uK5TfS04wt/nGwmaeIQ0g==", + "dev": true + }, + "node_modules/url-template": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/url-template/-/url-template-3.1.1.tgz", + "integrity": "sha512-4oszoaEKE/mQOtAmdMWqIRHmkxWkUZMnXFnjQ5i01CuRSK3uluxcH1MRVVVWmhlnzT1SCDfKxxficm2G37qzCA==", + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + } + }, + "node_modules/util": { + "version": "0.12.5", + "resolved": "https://registry.npmjs.org/util/-/util-0.12.5.tgz", + "integrity": "sha512-kZf/K6hEIrWHI6XqOFUiiMa+79wE/D8Q+NCNAWclkyg3b4d2k7s0QGepNjiABc+aR3N1PAyHL7p6UcLY6LmrnA==", + "dependencies": { + "inherits": "^2.0.3", + "is-arguments": "^1.0.4", + "is-generator-function": "^1.0.7", + "is-typed-array": "^1.1.3", + "which-typed-array": "^1.1.2" + } + }, + "node_modules/util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==" + }, + "node_modules/v-resize-observer": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/v-resize-observer/-/v-resize-observer-2.1.0.tgz", + "integrity": "sha512-QyTdSFAAtsP1/2ISR2hsz8PeEyxhaACqJXIzs5INlHXtu/pkMqyva8tHPWA54YejUyhxmU1bPriDBnW2cqbBcA==", + "dependencies": { + "resize-observer-polyfill": "^1.5.1", + "vue-demi": "latest" + }, + "peerDependencies": { + "@vue/composition-api": "^1.7.0", + "vue": "^2.5.0 || >=3.0.0" + }, + "peerDependenciesMeta": { + "@vue/composition-api": { + "optional": true + } + } + }, + "node_modules/v-resize-observer/node_modules/vue-demi": { + "version": "0.14.10", + "resolved": "https://registry.npmjs.org/vue-demi/-/vue-demi-0.14.10.tgz", + "integrity": "sha512-nMZBOwuzabUO0nLgIcc6rycZEebF6eeUfaiQx9+WSk8e29IbLvPU9feI6tqW4kTo3hvoYAJkMh8n8D0fuISphg==", + "hasInstallScript": true, + "bin": { + "vue-demi-fix": "bin/vue-demi-fix.js", + "vue-demi-switch": "bin/vue-demi-switch.js" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/antfu" + }, + "peerDependencies": { + "@vue/composition-api": "^1.0.0-rc.1", + "vue": "^3.0.0-0 || ^2.6.0" + }, + "peerDependenciesMeta": { + "@vue/composition-api": { + "optional": true + } + } + }, + "node_modules/vee-validate": { + "version": "4.15.1", + "resolved": "https://registry.npmjs.org/vee-validate/-/vee-validate-4.15.1.tgz", + "integrity": "sha512-DkFsiTwEKau8VIxyZBGdO6tOudD+QoUBPuHj3e6QFqmbfCRj1ArmYWue9lEp6jLSWBIw4XPlDLjFIZNLdRAMSg==", + "dependencies": { + "@vue/devtools-api": "^7.5.2", + "type-fest": "^4.8.3" + }, + "peerDependencies": { + "vue": "^3.4.26" + } + }, + "node_modules/vite": { + "version": "6.3.5", + "resolved": "https://registry.npmjs.org/vite/-/vite-6.3.5.tgz", + "integrity": "sha512-cZn6NDFE7wdTpINgs++ZJ4N49W2vRp8LCKrn3Ob1kYNtOo21vfDoaV5GzBfLU4MovSAB8uNRm4jgzVQZ+mBzPQ==", + "devOptional": true, + "dependencies": { + "esbuild": "^0.25.0", + "fdir": "^6.4.4", + "picomatch": "^4.0.2", + "postcss": "^8.5.3", + "rollup": "^4.34.9", + "tinyglobby": "^0.2.13" + }, + "bin": { + "vite": "bin/vite.js" + }, + "engines": { + "node": "^18.0.0 || ^20.0.0 || >=22.0.0" + }, + "funding": { + "url": "https://github.com/vitejs/vite?sponsor=1" + }, + "optionalDependencies": { + "fsevents": "~2.3.3" + }, + "peerDependencies": { + "@types/node": "^18.0.0 || ^20.0.0 || >=22.0.0", + "jiti": ">=1.21.0", + "less": "*", + "lightningcss": "^1.21.0", + "sass": "*", + "sass-embedded": "*", + "stylus": "*", + "sugarss": "*", + "terser": "^5.16.0", + "tsx": "^4.8.1", + "yaml": "^2.4.2" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + }, + "jiti": { + "optional": true + }, + "less": { + "optional": true + }, + "lightningcss": { + "optional": true + }, + "sass": { + "optional": true + }, + "sass-embedded": { + "optional": true + }, + "stylus": { + "optional": true + }, + "sugarss": { + "optional": true + }, + "terser": { + "optional": true + }, + "tsx": { + "optional": true + }, + "yaml": { + "optional": true + } + } + }, + "node_modules/vite-compatible-readable-stream": { + "version": "3.6.1", + "resolved": "https://registry.npmjs.org/vite-compatible-readable-stream/-/vite-compatible-readable-stream-3.6.1.tgz", + "integrity": "sha512-t20zYkrSf868+j/p31cRIGN28Phrjm3nRSLR2fyc2tiWi4cZGVdv68yNlwnIINTkMTmPoMiSlc0OadaO7DXZaQ==", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/vite-node": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/vite-node/-/vite-node-3.2.4.tgz", + "integrity": "sha512-EbKSKh+bh1E1IFxeO0pg1n4dvoOTt0UDiXMd/qn++r98+jPO1xtJilvXldeuQ8giIB5IkpjCgMleHMNEsGH6pg==", + "dev": true, + "dependencies": { + "cac": "^6.7.14", + "debug": "^4.4.1", + "es-module-lexer": "^1.7.0", + "pathe": "^2.0.3", + "vite": "^5.0.0 || ^6.0.0 || ^7.0.0-0" + }, + "bin": { + "vite-node": "vite-node.mjs" + }, + "engines": { + "node": "^18.0.0 || ^20.0.0 || >=22.0.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/vite-plugin-comlink": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/vite-plugin-comlink/-/vite-plugin-comlink-5.3.0.tgz", + "integrity": "sha512-grCxBC8JaCYIHPIvrM5c8Hq+XjFs3nhwSDc0SLpgY3D2LtE5j0wIZTF8zMWMzwMcrFPXWSejZI6MF6yvP/Iq9g==", + "dev": true, + "dependencies": { + "json5": "2.2.3", + "magic-string": "0.30.17", + "source-map": "^0.7.4" + }, + "peerDependencies": { + "comlink": "^4.3.1", + "vite": ">=2.9.6" + } + }, + "node_modules/vite-plugin-comlink/node_modules/magic-string": { + "version": "0.30.17", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.17.tgz", + "integrity": "sha512-sNPKHvyjVf7gyjwS4xGTaW/mCnF8wnjtifKBEhxfZ7E/S8tQ0rssrwGNn6q8JH/ohItJfSQp9mBtQYuTlH5QnA==", + "dev": true, + "dependencies": { + "@jridgewell/sourcemap-codec": "^1.5.0" + } + }, + "node_modules/vite-plugin-vuetify": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/vite-plugin-vuetify/-/vite-plugin-vuetify-2.1.2.tgz", + "integrity": "sha512-I/wd6QS+DO6lHmuGoi1UTyvvBTQ2KDzQZ9oowJQEJ6OcjWfJnscYXx2ptm6S7fJSASuZT8jGRBL3LV4oS3LpaA==", + "devOptional": true, + "dependencies": { + "@vuetify/loader-shared": "^2.1.1", + "debug": "^4.3.3", + "upath": "^2.0.1" + }, + "engines": { + "node": "^18.0.0 || >=20.0.0" + }, + "peerDependencies": { + "vite": ">=5", + "vue": "^3.0.0", + "vuetify": "^3.0.0" + } + }, + "node_modules/vite-svg-loader": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/vite-svg-loader/-/vite-svg-loader-5.1.0.tgz", + "integrity": "sha512-M/wqwtOEjgb956/+m5ZrYT/Iq6Hax0OakWbokj8+9PXOnB7b/4AxESHieEtnNEy7ZpjsjYW1/5nK8fATQMmRxw==", + "dev": true, + "license": "MIT", + "dependencies": { + "svgo": "^3.0.2" + }, + "peerDependencies": { + "vue": ">=3.2.13" + } + }, + "node_modules/vite/node_modules/fdir": { + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz", + "integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==", + "devOptional": true, + "engines": { + "node": ">=12.0.0" + }, + "peerDependencies": { + "picomatch": "^3 || ^4" + }, + "peerDependenciesMeta": { + "picomatch": { + "optional": true + } + } + }, + "node_modules/vite/node_modules/picomatch": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz", + "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", + "devOptional": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/vitest": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/vitest/-/vitest-3.2.4.tgz", + "integrity": "sha512-LUCP5ev3GURDysTWiP47wRRUpLKMOfPh+yKTx3kVIEiu5KOMeqzpnYNsKyOoVrULivR8tLcks4+lga33Whn90A==", + "dev": true, + "dependencies": { + "@types/chai": "^5.2.2", + "@vitest/expect": "3.2.4", + "@vitest/mocker": "3.2.4", + "@vitest/pretty-format": "^3.2.4", + "@vitest/runner": "3.2.4", + "@vitest/snapshot": "3.2.4", + "@vitest/spy": "3.2.4", + "@vitest/utils": "3.2.4", + "chai": "^5.2.0", + "debug": "^4.4.1", + "expect-type": "^1.2.1", + "magic-string": "^0.30.17", + "pathe": "^2.0.3", + "picomatch": "^4.0.2", + "std-env": "^3.9.0", + "tinybench": "^2.9.0", + "tinyexec": "^0.3.2", + "tinyglobby": "^0.2.14", + "tinypool": "^1.1.1", + "tinyrainbow": "^2.0.0", + "vite": "^5.0.0 || ^6.0.0 || ^7.0.0-0", + "vite-node": "3.2.4", + "why-is-node-running": "^2.3.0" + }, + "bin": { + "vitest": "vitest.mjs" + }, + "engines": { + "node": "^18.0.0 || ^20.0.0 || >=22.0.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + }, + "peerDependencies": { + "@edge-runtime/vm": "*", + "@types/debug": "^4.1.12", + "@types/node": "^18.0.0 || ^20.0.0 || >=22.0.0", + "@vitest/browser": "3.2.4", + "@vitest/ui": "3.2.4", + "happy-dom": "*", + "jsdom": "*" + }, + "peerDependenciesMeta": { + "@edge-runtime/vm": { + "optional": true + }, + "@types/debug": { + "optional": true + }, + "@types/node": { + "optional": true + }, + "@vitest/browser": { + "optional": true + }, + "@vitest/ui": { + "optional": true + }, + "happy-dom": { + "optional": true + }, + "jsdom": { + "optional": true + } + } + }, + "node_modules/vitest-canvas-mock": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/vitest-canvas-mock/-/vitest-canvas-mock-0.3.3.tgz", + "integrity": "sha512-3P968tYBpqYyzzOaVtqnmYjqbe13576/fkjbDEJSfQAkHtC5/UjuRHOhFEN/ZV5HVZIkaROBUWgazDKJ+Ibw+Q==", + "dev": true, + "dependencies": { + "jest-canvas-mock": "~2.5.2" + }, + "peerDependencies": { + "vitest": "*" + } + }, + "node_modules/vitest/node_modules/magic-string": { + "version": "0.30.18", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.18.tgz", + "integrity": "sha512-yi8swmWbO17qHhwIBNeeZxTceJMeBvWJaId6dyvTSOwTipqeHhMhOrz6513r1sOKnpvQ7zkhlG8tPrpilwTxHQ==", + "dev": true, + "dependencies": { + "@jridgewell/sourcemap-codec": "^1.5.5" + } + }, + "node_modules/vitest/node_modules/picomatch": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz", + "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/vue": { + "version": "3.5.21", + "resolved": "https://registry.npmjs.org/vue/-/vue-3.5.21.tgz", + "integrity": "sha512-xxf9rum9KtOdwdRkiApWL+9hZEMWE90FHh8yS1+KJAiWYh+iGWV1FquPjoO9VUHQ+VIhsCXNNyZ5Sf4++RVZBA==", + "dependencies": { + "@vue/compiler-dom": "3.5.21", + "@vue/compiler-sfc": "3.5.21", + "@vue/runtime-dom": "3.5.21", + "@vue/server-renderer": "3.5.21", + "@vue/shared": "3.5.21" + }, + "peerDependencies": { + "typescript": "*" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/vue-axios": { + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/vue-axios/-/vue-axios-3.5.2.tgz", + "integrity": "sha512-GP+dct7UlAWkl1qoP3ppw0z6jcSua5/IrMpjB5O8bh089iIiJ+hdxPYH2NPEpajlYgkW5EVMP95ttXWdas1O0g==", + "peerDependencies": { + "axios": "*", + "vue": "^3.0.0 || ^2.0.0" + } + }, + "node_modules/vue-component-type-helpers": { + "version": "2.2.12", + "resolved": "https://registry.npmjs.org/vue-component-type-helpers/-/vue-component-type-helpers-2.2.12.tgz", + "integrity": "sha512-YbGqHZ5/eW4SnkPNR44mKVc6ZKQoRs/Rux1sxC6rdwXb4qpbOSYfDr9DsTHolOTGmIKgM9j141mZbBeg05R1pw==", + "dev": true + }, + "node_modules/vue-eslint-parser": { + "version": "10.2.0", + "resolved": "https://registry.npmjs.org/vue-eslint-parser/-/vue-eslint-parser-10.2.0.tgz", + "integrity": "sha512-CydUvFOQKD928UzZhTp4pr2vWz1L+H99t7Pkln2QSPdvmURT0MoC4wUccfCnuEaihNsu9aYYyk+bep8rlfkUXw==", + "dev": true, + "peer": true, + "dependencies": { + "debug": "^4.4.0", + "eslint-scope": "^8.2.0", + "eslint-visitor-keys": "^4.2.0", + "espree": "^10.3.0", + "esquery": "^1.6.0", + "semver": "^7.6.3" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://github.com/sponsors/mysticatea" + }, + "peerDependencies": { + "eslint": "^8.57.0 || ^9.0.0" + } + }, + "node_modules/vue-eslint-parser/node_modules/eslint-scope": { + "version": "8.4.0", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.4.0.tgz", + "integrity": "sha512-sNXOfKCn74rt8RICKMvJS7XKV/Xk9kA7DyJr8mJik3S7Cwgy3qlkkmyS2uQB3jiJg6VNdZd/pDBJu0nvG2NlTg==", + "dev": true, + "peer": true, + "dependencies": { + "esrecurse": "^4.3.0", + "estraverse": "^5.2.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/vue-eslint-parser/node_modules/eslint-visitor-keys": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.1.tgz", + "integrity": "sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==", + "dev": true, + "peer": true, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/vue-eslint-parser/node_modules/estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true, + "peer": true, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/vue-eslint-parser/node_modules/semver": { + "version": "7.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.2.tgz", + "integrity": "sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA==", + "dev": true, + "peer": true, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/vue-i18n": { + "version": "11.1.11", + "resolved": "https://registry.npmjs.org/vue-i18n/-/vue-i18n-11.1.11.tgz", + "integrity": "sha512-LvyteQoXeQiuILbzqv13LbyBna/TEv2Ha+4ZWK2AwGHUzZ8+IBaZS0TJkCgn5izSPLcgZwXy9yyTrewCb2u/MA==", + "dependencies": { + "@intlify/core-base": "11.1.11", + "@intlify/shared": "11.1.11", + "@vue/devtools-api": "^6.5.0" + }, + "engines": { + "node": ">= 16" + }, + "funding": { + "url": "https://github.com/sponsors/kazupon" + }, + "peerDependencies": { + "vue": "^3.0.0" + } + }, + "node_modules/vue-i18n/node_modules/@vue/devtools-api": { + "version": "6.6.4", + "resolved": "https://registry.npmjs.org/@vue/devtools-api/-/devtools-api-6.6.4.tgz", + "integrity": "sha512-sGhTPMuXqZ1rVOk32RylztWkfXTRhuS7vgAKv0zjqk8gbsHkJ7xfFf+jbySxt7tWObEJwyKaHMikV/WGDiQm8g==" + }, + "node_modules/vue-recaptcha-v3": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/vue-recaptcha-v3/-/vue-recaptcha-v3-2.0.1.tgz", + "integrity": "sha512-isEDtOfHU4wWRrZZuxciAELtQmPOeEEdicPNa0f1AOyLPy3sCcBEcpFt+FOcO3RQv5unJ3Yn5NlsWtXv9rXqjg==", + "dependencies": { + "recaptcha-v3": "^1.8.0" + }, + "peerDependencies": { + "vue": "^3.0.11" + } + }, + "node_modules/vue-router": { + "version": "4.5.1", + "resolved": "https://registry.npmjs.org/vue-router/-/vue-router-4.5.1.tgz", + "integrity": "sha512-ogAF3P97NPm8fJsE4by9dwSYtDwXIY1nFY9T6DyQnGHd1E2Da94w9JIolpe42LJGIl0DwOHBi8TcRPlPGwbTtw==", + "dependencies": { + "@vue/devtools-api": "^6.6.4" + }, + "funding": { + "url": "https://github.com/sponsors/posva" + }, + "peerDependencies": { + "vue": "^3.2.0" + } + }, + "node_modules/vue-router/node_modules/@vue/devtools-api": { + "version": "6.6.4", + "resolved": "https://registry.npmjs.org/@vue/devtools-api/-/devtools-api-6.6.4.tgz", + "integrity": "sha512-sGhTPMuXqZ1rVOk32RylztWkfXTRhuS7vgAKv0zjqk8gbsHkJ7xfFf+jbySxt7tWObEJwyKaHMikV/WGDiQm8g==" + }, + "node_modules/vue-toastification": { + "version": "2.0.0-rc.5", + "resolved": "https://registry.npmjs.org/vue-toastification/-/vue-toastification-2.0.0-rc.5.tgz", + "integrity": "sha512-q73e5jy6gucEO/U+P48hqX+/qyXDozAGmaGgLFm5tXX4wJBcVsnGp4e/iJqlm9xzHETYOilUuwOUje2Qg1JdwA==", + "peerDependencies": { + "vue": "^3.0.2" + } + }, + "node_modules/vuedraggable": { + "version": "2.24.3", + "resolved": "https://registry.npmjs.org/vuedraggable/-/vuedraggable-2.24.3.tgz", + "integrity": "sha512-6/HDXi92GzB+Hcs9fC6PAAozK1RLt1ewPTLjK0anTYguXLAeySDmcnqE8IC0xa7shvSzRjQXq3/+dsZ7ETGF3g==", + "dependencies": { + "sortablejs": "1.10.2" + } + }, + "node_modules/vuetify": { + "version": "3.10.4", + "resolved": "https://registry.npmjs.org/vuetify/-/vuetify-3.10.4.tgz", + "integrity": "sha512-aatUQ0RM0i6VdkJaFyj3gydecuFmAgACNO3RwWznvjvIvRENQXxMRiv+vlGFoshbw2UG+zOPPMhO12OCPSa2UQ==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/johnleider" + }, + "peerDependencies": { + "typescript": ">=4.7", + "vite-plugin-vuetify": ">=2.1.0", + "vue": "^3.5.0", + "webpack-plugin-vuetify": ">=3.1.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + }, + "vite-plugin-vuetify": { + "optional": true + }, + "webpack-plugin-vuetify": { + "optional": true + } + } + }, + "node_modules/vuex": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/vuex/-/vuex-4.0.2.tgz", + "integrity": "sha512-M6r8uxELjZIK8kTKDGgZTYX/ahzblnzC4isU1tpmEuOIIKmV+TRdc+H4s8ds2NuZ7wpUTdGRzJRtoj+lI+pc0Q==", + "dependencies": { + "@vue/devtools-api": "^6.0.0-beta.11" + }, + "peerDependencies": { + "vue": "^3.0.2" + } + }, + "node_modules/vuex/node_modules/@vue/devtools-api": { + "version": "6.6.4", + "resolved": "https://registry.npmjs.org/@vue/devtools-api/-/devtools-api-6.6.4.tgz", + "integrity": "sha512-sGhTPMuXqZ1rVOk32RylztWkfXTRhuS7vgAKv0zjqk8gbsHkJ7xfFf+jbySxt7tWObEJwyKaHMikV/WGDiQm8g==" + }, + "node_modules/w3c-keyname": { + "version": "2.2.8", + "resolved": "https://registry.npmjs.org/w3c-keyname/-/w3c-keyname-2.2.8.tgz", + "integrity": "sha512-dpojBhNsCNN7T82Tm7k26A6G9ML3NkhDsnw9n/eoxSRlVBB4CEtIQ/KTCLI2Fwf3ataSXRhYFkQi3SlnFwPvPQ==", + "peer": true + }, + "node_modules/w3c-xmlserializer": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/w3c-xmlserializer/-/w3c-xmlserializer-5.0.0.tgz", + "integrity": "sha512-o8qghlI8NZHU1lLPrpi2+Uq7abh4GGPpYANlalzWxyWteJOCsr/P+oPBA49TOLu5FTZO4d3F9MnWJfiMo4BkmA==", + "dev": true, + "dependencies": { + "xml-name-validator": "^5.0.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/w3c-xmlserializer/node_modules/xml-name-validator": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/xml-name-validator/-/xml-name-validator-5.0.0.tgz", + "integrity": "sha512-EvGK8EJ3DhaHfbRlETOWAS5pO9MZITeauHKJyb8wyajUfQUenkIg2MvLDTZ4T/TgIcm3HU0TFBgWWboAZ30UHg==", + "dev": true, + "engines": { + "node": ">=18" + } + }, + "node_modules/webidl-conversions": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-7.0.0.tgz", + "integrity": "sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g==", + "dev": true, + "engines": { + "node": ">=12" + } + }, + "node_modules/webpack-sources": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-3.3.3.tgz", + "integrity": "sha512-yd1RBzSGanHkitROoPFd6qsrxt+oFhg/129YzheDGqeustzX0vTZJZsSsQjVQC4yzBQ56K55XU8gaNCtIzOnTg==", + "dev": true, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/webpack-virtual-modules": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/webpack-virtual-modules/-/webpack-virtual-modules-0.5.0.tgz", + "integrity": "sha512-kyDivFZ7ZM0BVOUteVbDFhlRt7Ah/CSPwJdi8hBpkK7QLumUqdLtVfm/PX/hkcnrvr0i77fO5+TjZ94Pe+C9iw==", + "dev": true + }, + "node_modules/whatwg-encoding": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/whatwg-encoding/-/whatwg-encoding-3.1.1.tgz", + "integrity": "sha512-6qN4hJdMwfYBtE3YBTTHhoeuUrDBPZmbQaxWAqSALV/MeEnR5z1xd8UKud2RAkFoPkmB+hli1TZSnyi84xz1vQ==", + "dev": true, + "dependencies": { + "iconv-lite": "0.6.3" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/whatwg-mimetype": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/whatwg-mimetype/-/whatwg-mimetype-4.0.0.tgz", + "integrity": "sha512-QaKxh0eNIi2mE9p2vEdzfagOKHCcj1pJ56EEHGQOVxp8r9/iszLUUV7v89x9O1p/T+NlTM5W7jW6+cz4Fq1YVg==", + "dev": true, + "engines": { + "node": ">=18" + } + }, + "node_modules/whatwg-url": { + "version": "14.2.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-14.2.0.tgz", + "integrity": "sha512-De72GdQZzNTUBBChsXueQUnPKDkg/5A5zp7pFDuQAj5UFoENpiACU0wlCvzpAGnTkj++ihpKwKyYewn/XNUbKw==", + "dev": true, + "dependencies": { + "tr46": "^5.1.0", + "webidl-conversions": "^7.0.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/which-boxed-primitive": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.1.1.tgz", + "integrity": "sha512-TbX3mj8n0odCBFVlY8AxkqcHASw3L60jIuF8jFP78az3C2YhmGvqbHBpAjTRH2/xqYunrJ9g1jSyjCjpoWzIAA==", + "dev": true, + "dependencies": { + "is-bigint": "^1.1.0", + "is-boolean-object": "^1.2.1", + "is-number-object": "^1.1.1", + "is-string": "^1.1.1", + "is-symbol": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/which-collection": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/which-collection/-/which-collection-1.0.2.tgz", + "integrity": "sha512-K4jVyjnBdgvc86Y6BkaLZEN933SwYOuBFkdmBu9ZfkcAbdVbpITnDmjvZ/aQjRXQrv5EPkTnD1s39GiiqbngCw==", + "dev": true, + "dependencies": { + "is-map": "^2.0.3", + "is-set": "^2.0.3", + "is-weakmap": "^2.0.2", + "is-weakset": "^2.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/which-typed-array": { + "version": "1.1.19", + "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.19.tgz", + "integrity": "sha512-rEvr90Bck4WZt9HHFC4DJMsjvu7x+r6bImz0/BrbWb7A2djJ8hnZMrWnHo9F8ssv0OMErasDhftrfROTyqSDrw==", + "dependencies": { + "available-typed-arrays": "^1.0.7", + "call-bind": "^1.0.8", + "call-bound": "^1.0.4", + "for-each": "^0.3.5", + "get-proto": "^1.0.1", + "gopd": "^1.2.0", + "has-tostringtag": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/why-is-node-running": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/why-is-node-running/-/why-is-node-running-2.3.0.tgz", + "integrity": "sha512-hUrmaWBdVDcxvYqnyh09zunKzROWjbZTiNy8dBEjkS7ehEDQibXJ7XvlmtbwuTclUiIyN+CyXQD4Vmko8fNm8w==", + "dev": true, + "dependencies": { + "siginfo": "^2.0.0", + "stackback": "0.0.2" + }, + "bin": { + "why-is-node-running": "cli.js" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/word-wrap": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz", + "integrity": "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/wrap-ansi": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-9.0.0.tgz", + "integrity": "sha512-G8ura3S+3Z2G+mkgNRq8dqaFZAuxfsxpBB8OCTGRTCtp+l/v9nbFNmCUP1BZMts3G1142MsZfn6eeUKrr4PD1Q==", + "dev": true, + "dependencies": { + "ansi-styles": "^6.2.1", + "string-width": "^7.0.0", + "strip-ansi": "^7.1.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/wrap-ansi-cjs": { + "name": "wrap-ansi", + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/wrap-ansi-cjs/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true + }, + "node_modules/wrap-ansi-cjs/node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/wrap-ansi-cjs/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/wrap-ansi-cjs/node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/wrap-ansi/node_modules/ansi-styles": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", + "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", + "devOptional": true + }, + "node_modules/ws": { + "version": "8.18.3", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.18.3.tgz", + "integrity": "sha512-PEIGCY5tSlUt50cqyMXfCzX+oOPqN0vuGqWzbcJ2xvnkzkq46oOpz7dQaTDBdfICb4N14+GARUDw2XV2N4tvzg==", + "dev": true, + "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 + } + } + }, + "node_modules/xlsx": { + "version": "0.20.2", + "resolved": "https://cdn.sheetjs.com/xlsx-0.20.2/xlsx-0.20.2.tgz", + "integrity": "sha512-+nKZ39+nvK7Qq6i0PvWWRA4j/EkfWOtkP/YhMtupm+lJIiHxUrgTr1CcKv1nBk1rHtkRRQ3O2+Ih/q/sA+FXZA==", + "license": "Apache-2.0", + "bin": { + "xlsx": "bin/xlsx.njs" + }, + "engines": { + "node": ">=0.8" + } + }, + "node_modules/xml-name-validator": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/xml-name-validator/-/xml-name-validator-4.0.0.tgz", + "integrity": "sha512-ICP2e+jsHvAj2E2lIHxa5tjXRlKDJo4IdvPvCXbXQGdzSfmSpNVyIKMvoZHjDY9DP0zV17iI85o90vRFXNccRw==", + "dev": true, + "engines": { + "node": ">=12" + } + }, + "node_modules/xmlchars": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/xmlchars/-/xmlchars-2.2.0.tgz", + "integrity": "sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw==", + "dev": true + }, + "node_modules/yallist": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", + "dev": true + }, + "node_modules/yaml": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.8.1.tgz", + "integrity": "sha512-lcYcMxX2PO9XMGvAJkJ3OsNMw+/7FKes7/hgerGUYWIoWu5j/+YQqcZr5JnPZWzOsEBgMbSbiSTn/dv/69Mkpw==", + "devOptional": true, + "bin": { + "yaml": "bin.mjs" + }, + "engines": { + "node": ">= 14.6" + } + }, + "node_modules/yocto-queue": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", + "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/yoga-layout": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/yoga-layout/-/yoga-layout-3.2.1.tgz", + "integrity": "sha512-0LPOt3AxKqMdFBZA3HBAt/t/8vIKq7VaQYbuA8WxCgung+p9TVyKRYdpvCb80HcdTN2NkbIKbhNwKUfm3tQywQ==" + } + } +} diff --git a/frontend-vue3/package.json b/frontend-vue3/package.json new file mode 100644 index 0000000000..d499e40819 --- /dev/null +++ b/frontend-vue3/package.json @@ -0,0 +1,158 @@ +{ + "name": "@ecamp3/frontend", + "private": true, + "type": "module", + "scripts": { + "serve": "vite --host 0.0.0.0", + "preview": "vite preview --host 0.0.0.0 --port 3000", + "build": "vite build", + "lint": "npm run lint:eslint && npm run lint:prettier", + "lint:eslint": "eslint --fix .", + "lint:prettier": "prettier --write --ignore-path .prettierignore **/*.{css,scss,json,md}", + "lint:check": "npm run lint:check:eslint && npm run lint:check:prettier", + "lint:check:eslint": "eslint .", + "lint:check:prettier": "prettier --check --ignore-path .prettierignore **/*.{css,scss,json,md}", + "start": "vite --host 0.0.0.0", + "dev": "vite --host 0.0.0.0", + "test:unit": "vitest run --coverage", + "test:unit:debug": "node --inspect-brk=0.0.0.0:9229 ./node_modules/.bin/vitest --no-cache --runInBand", + "test:unit:watch": "vitest --watch", + "postinstall": "./scripts/install-twemoji.sh" + }, + "dependencies": { + "@intlify/core": "11.1.11", + "@mdi/font": "7.4.47", + "@react-pdf/font": "4.0.2", + "@react-pdf/layout": "4.4.0", + "@react-pdf/pdfkit": "4.0.3", + "@react-pdf/primitives": "4.1.1", + "@react-pdf/render": "4.3.0", + "@sentry/browser": "9.44.0", + "@sentry/vue": "9.44.0", + "@tiptap/extension-bold": "3.0.9", + "@tiptap/extension-bubble-menu": "3.0.9", + "@tiptap/extension-bullet-list": "3.0.9", + "@tiptap/extension-document": "3.0.9", + "@tiptap/extension-hard-break": "3.0.9", + "@tiptap/extension-heading": "3.0.9", + "@tiptap/extension-history": "3.0.9", + "@tiptap/extension-italic": "3.0.9", + "@tiptap/extension-list-item": "3.0.9", + "@tiptap/extension-ordered-list": "3.0.9", + "@tiptap/extension-paragraph": "3.0.9", + "@tiptap/extension-placeholder": "3.0.9", + "@tiptap/extension-strike": "3.0.9", + "@tiptap/extension-text": "3.0.9", + "@tiptap/extension-underline": "3.0.9", + "@tiptap/vue-3": "3.0.9", + "@vee-validate/i18n": "4.15.1", + "@vee-validate/rules": "4.15.1", + "@unhead/vue": "2.0.14", + "@zxcvbn-ts/core": "3.0.4", + "@zxcvbn-ts/language-common": "3.0.4", + "@zxcvbn-ts/language-de": "3.0.2", + "@zxcvbn-ts/language-en": "3.0.2", + "@zxcvbn-ts/language-fr": "3.0.2", + "@zxcvbn-ts/language-it": "3.0.2", + "assert": "2.1.0", + "axios": "1.11.0", + "colorjs.io": "0.5.2", + "comlink": "4.4.2", + "dayjs": "1.11.13", + "deepmerge": "4.3.1", + "emoji-regex": "10.4.0", + "file-saver": "2.0.5", + "hal-json-vuex": "3.0.0-alpha.10", + "inter-ui": "3.19.3", + "js-cookie": "3.0.5", + "linkify-it": "5.0.0", + "lodash-es": "4.17.21", + "runes": "0.4.3", + "slugify": "1.6.6", + "url-template": "3.1.1", + "util": "0.12.5", + "v-resize-observer": "2.1.0", + "vee-validate": "4.15.1", + "vue": "3.5.21", + "@vue/compat": "3.5.21", + "vue-axios": "3.5.2", + "vue-i18n": "11.1.11", + "vue-recaptcha-v3": "2.0.1", + "vue-router": "4.5.1", + "vue-toastification": "2.0.0-rc.5", + "vuedraggable": "2.24.3", + "vuetify": "3.10.4", + "vuex": "4.0.2", + "xlsx": "https://cdn.sheetjs.com/xlsx-0.20.2/xlsx-0.20.2.tgz" + }, + "devDependencies": { + "@babel/eslint-parser": "7.28.0", + "@eslint/compat": "1.3.1", + "@eslint/eslintrc": "3.3.1", + "@eslint/js": "9.32.0", + "@sentry/vite-plugin": "4.0.2", + "@testing-library/jest-dom": "6.6.4", + "@testing-library/user-event": "14.6.1", + "@testing-library/vue": "8.1.0", + "@vitejs/plugin-vue": "6.0.1", + "@vitest/coverage-v8": "3.2.4", + "@vue/babel-preset-app": "5.0.9", + "@vue/compiler-dom": "3.5.21", + "@vue/compiler-sfc": "3.5.21", + "@vue/runtime-dom": "3.5.21", + "@vue/server-renderer": "3.5.21", + "@vue/shared": "3.5.21", + "@vue/eslint-config-prettier": "10.2.0", + "@vue/test-utils": "2.4.6", + "autoprefixer": "10.4.21", + "babel-plugin-require-context-hook": "1.0.0", + "eslint": "9.32.0", + "eslint-config-prettier": "10.1.8", + "eslint-plugin-local-rules": "3.0.2", + "eslint-plugin-n": "17.21.3", + "eslint-plugin-prettier": "5.5.3", + "eslint-plugin-promise": "7.2.1", + "eslint-plugin-vue": "10.4.0", + "eslint-plugin-vue-scoped-css": "2.11.0", + "flush-promises": "1.0.2", + "globals": "16.3.0", + "jest-serializer-vue-tjw": "4.0.0", + "jsdom": "26.1.0", + "lint-staged": "16.1.4", + "prettier": "3.6.2", + "sass": "1.89.2", + "unplugin-vue-components": "28.8.0", + "vite": "6.3.5", + "vite-plugin-comlink": "5.3.0", + "vite-svg-loader": "5.1.0", + "vitest": "3.2.4", + "vitest-canvas-mock": "0.3.3", + "vite-plugin-vuetify": "2.1.2" + }, + "overrides": { + "uri-js": "npm:uri-js-replace" + }, + "postcss": { + "plugins": { + "autoprefixer": {} + } + }, + "browserslist": [ + "> 1%", + "last 2 versions", + "not ie <= 8" + ], + "gitHooks": { + "pre-commit": "lint-staged" + }, + "lint-staged": { + "*.js": [ + "eslint . --ext .vue,.js --fix --ignore-path .gitignore", + "git add" + ], + "*.vue": [ + "eslint . --ext .vue,.js --fix --ignore-path .gitignore", + "git add" + ] + } +} diff --git a/frontend-vue3/public/browserassets/apple-touch-icon.png b/frontend-vue3/public/browserassets/apple-touch-icon.png new file mode 100644 index 0000000000..76e05f775e Binary files /dev/null and b/frontend-vue3/public/browserassets/apple-touch-icon.png differ diff --git a/frontend-vue3/public/browserassets/favicon-16x16.png b/frontend-vue3/public/browserassets/favicon-16x16.png new file mode 100644 index 0000000000..c45a8a1966 Binary files /dev/null and b/frontend-vue3/public/browserassets/favicon-16x16.png differ diff --git a/frontend-vue3/public/browserassets/favicon-32x32.png b/frontend-vue3/public/browserassets/favicon-32x32.png new file mode 100644 index 0000000000..3cce341a4b Binary files /dev/null and b/frontend-vue3/public/browserassets/favicon-32x32.png differ diff --git a/frontend-vue3/public/browserassets/logo@192px.png b/frontend-vue3/public/browserassets/logo@192px.png new file mode 100644 index 0000000000..d275c989c4 Binary files /dev/null and b/frontend-vue3/public/browserassets/logo@192px.png differ diff --git a/frontend-vue3/public/browserassets/logo@512px.png b/frontend-vue3/public/browserassets/logo@512px.png new file mode 100644 index 0000000000..f8778ee95f Binary files /dev/null and b/frontend-vue3/public/browserassets/logo@512px.png differ diff --git a/frontend-vue3/public/browserassets/mstile-150x150.png b/frontend-vue3/public/browserassets/mstile-150x150.png new file mode 100644 index 0000000000..322c49bc50 Binary files /dev/null and b/frontend-vue3/public/browserassets/mstile-150x150.png differ diff --git a/frontend-vue3/public/browserassets/safari-pinned-tab.svg b/frontend-vue3/public/browserassets/safari-pinned-tab.svg new file mode 100644 index 0000000000..0248b1e6bc --- /dev/null +++ b/frontend-vue3/public/browserassets/safari-pinned-tab.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/frontend-vue3/public/browserconfig.xml b/frontend-vue3/public/browserconfig.xml new file mode 100644 index 0000000000..1cd51a1fa2 --- /dev/null +++ b/frontend-vue3/public/browserconfig.xml @@ -0,0 +1,9 @@ + + + + + + #263238 + + + diff --git a/frontend-vue3/public/environment.js b/frontend-vue3/public/environment.js new file mode 100644 index 0000000000..47b91ee3e6 --- /dev/null +++ b/frontend-vue3/public/environment.js @@ -0,0 +1,5 @@ +/** + * This is a placeholder. + * In production, this file is filled with the values for window.environment. + * In development, window.environment is filled in src/dev-environment.js + */ diff --git a/frontend-vue3/public/favicon.ico b/frontend-vue3/public/favicon.ico new file mode 100644 index 0000000000..6c628462f9 Binary files /dev/null and b/frontend-vue3/public/favicon.ico differ diff --git a/frontend-vue3/public/favicon.svg b/frontend-vue3/public/favicon.svg new file mode 100644 index 0000000000..40da9b592e --- /dev/null +++ b/frontend-vue3/public/favicon.svg @@ -0,0 +1,7 @@ + + + + + + + diff --git a/frontend-vue3/public/logo.svg b/frontend-vue3/public/logo.svg new file mode 100644 index 0000000000..d9d26fca25 --- /dev/null +++ b/frontend-vue3/public/logo.svg @@ -0,0 +1,55 @@ + + Logo eCamp v3 + + + + image/svg+xml + + Logo eCamp v3 + 2020-04-02 + Manuel Meister + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/frontend-vue3/public/manifest.webmanifest b/frontend-vue3/public/manifest.webmanifest new file mode 100644 index 0000000000..1b9895dc65 --- /dev/null +++ b/frontend-vue3/public/manifest.webmanifest @@ -0,0 +1,30 @@ +{ + "short_name": "eCamp", + "name": "eCamp v3", + "icons": [ + { + "src": "/favicon.svg", + "type": "image/svg", + "sizes": "16x16" + }, + { + "src": "/logo.svg", + "type": "image/svg", + "sizes": "64x64" + }, + { + "src": "/browserassets/logo@192px.png", + "type": "image/png", + "sizes": "192x192" + }, + { + "src": "/browserassets/logo@512px.png", + "type": "image/png", + "sizes": "512x512" + } + ], + "start_url": "/", + "background_color": "#546e7a", + "display": "minimal-ui", + "theme_color": "#546e7a" +} diff --git a/frontend-vue3/scripts/install-twemoji.sh b/frontend-vue3/scripts/install-twemoji.sh new file mode 100755 index 0000000000..9a1cb6172e --- /dev/null +++ b/frontend-vue3/scripts/install-twemoji.sh @@ -0,0 +1,23 @@ +#!/usr/bin/env sh + +# We need twemoji for emoji support in client-side printing. Since there is no maintained npm package +# which includes the actual emoji images, we use this script to install the images. By default, +# twemoji are usually accessed from CDNs, but for traceability reasons, we self-host them. + +set -euo + +if [ ! -d "public/twemoji" ] +then + echo 'downloading twemoji images from GitHub...' + # Clone as little as possible. No past revisions and only the image files we are interested in. + git clone --depth 1 --no-checkout --filter=blob:none --sparse https://github.com/twitter/twemoji.git public/twemoji + cd public/twemoji + git sparse-checkout set assets/72x72 + git checkout master +else + echo 'twemoji are already present, updating them to the latest version...' + cd public/twemoji + git pull || echo 'Could not update twemoji. Skipping for now...' +fi + +echo 'twemoji images should be up to date now.' diff --git a/frontend-vue3/src/App.vue b/frontend-vue3/src/App.vue new file mode 100644 index 0000000000..52055fc78e --- /dev/null +++ b/frontend-vue3/src/App.vue @@ -0,0 +1,153 @@ + + + + + + + + diff --git a/frontend-vue3/src/assets/080720_lotos_7896.jpg b/frontend-vue3/src/assets/080720_lotos_7896.jpg new file mode 100644 index 0000000000..ba331f6694 Binary files /dev/null and b/frontend-vue3/src/assets/080720_lotos_7896.jpg differ diff --git a/frontend-vue3/src/assets/080720_lotos_7896_small.jpg b/frontend-vue3/src/assets/080720_lotos_7896_small.jpg new file mode 100644 index 0000000000..7e9c9c4847 Binary files /dev/null and b/frontend-vue3/src/assets/080720_lotos_7896_small.jpg differ diff --git a/frontend-vue3/src/assets/140801151550_LOM.jpg b/frontend-vue3/src/assets/140801151550_LOM.jpg new file mode 100644 index 0000000000..be93ebdeda Binary files /dev/null and b/frontend-vue3/src/assets/140801151550_LOM.jpg differ diff --git a/frontend-vue3/src/assets/140801151550_LOM_small.jpg b/frontend-vue3/src/assets/140801151550_LOM_small.jpg new file mode 100644 index 0000000000..640aa99370 Binary files /dev/null and b/frontend-vue3/src/assets/140801151550_LOM_small.jpg differ diff --git a/frontend-vue3/src/assets/CeviLogo.svg b/frontend-vue3/src/assets/CeviLogo.svg new file mode 100644 index 0000000000..a085896ad3 --- /dev/null +++ b/frontend-vue3/src/assets/CeviLogo.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/frontend-vue3/src/assets/FourZeroFour.svg b/frontend-vue3/src/assets/FourZeroFour.svg new file mode 100644 index 0000000000..e4cd16606e --- /dev/null +++ b/frontend-vue3/src/assets/FourZeroFour.svg @@ -0,0 +1,65 @@ + + Error 404 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/frontend-vue3/src/assets/GoogleLogo.svg b/frontend-vue3/src/assets/GoogleLogo.svg new file mode 100644 index 0000000000..3bbcc195cb --- /dev/null +++ b/frontend-vue3/src/assets/GoogleLogo.svg @@ -0,0 +1 @@ + diff --git a/frontend-vue3/src/assets/JublaLogo.svg b/frontend-vue3/src/assets/JublaLogo.svg new file mode 100644 index 0000000000..a13774d235 --- /dev/null +++ b/frontend-vue3/src/assets/JublaLogo.svg @@ -0,0 +1 @@ + diff --git a/frontend-vue3/src/assets/PbsLogo.svg b/frontend-vue3/src/assets/PbsLogo.svg new file mode 100644 index 0000000000..e4086e4f2e --- /dev/null +++ b/frontend-vue3/src/assets/PbsLogo.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/frontend-vue3/src/assets/eCampLogo.svg b/frontend-vue3/src/assets/eCampLogo.svg new file mode 100644 index 0000000000..defa95d10e --- /dev/null +++ b/frontend-vue3/src/assets/eCampLogo.svg @@ -0,0 +1,33 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/frontend-vue3/src/assets/fonts/Inter/InterDisplay-Bold.ttf b/frontend-vue3/src/assets/fonts/Inter/InterDisplay-Bold.ttf new file mode 100644 index 0000000000..9aa4b0b542 Binary files /dev/null and b/frontend-vue3/src/assets/fonts/Inter/InterDisplay-Bold.ttf differ diff --git a/frontend-vue3/src/assets/fonts/Inter/InterDisplay-BoldItalic.ttf b/frontend-vue3/src/assets/fonts/Inter/InterDisplay-BoldItalic.ttf new file mode 100644 index 0000000000..20ce27cbb4 Binary files /dev/null and b/frontend-vue3/src/assets/fonts/Inter/InterDisplay-BoldItalic.ttf differ diff --git a/frontend-vue3/src/assets/fonts/Inter/InterDisplay-Italic.ttf b/frontend-vue3/src/assets/fonts/Inter/InterDisplay-Italic.ttf new file mode 100644 index 0000000000..97da0c0bc1 Binary files /dev/null and b/frontend-vue3/src/assets/fonts/Inter/InterDisplay-Italic.ttf differ diff --git a/frontend-vue3/src/assets/fonts/Inter/InterDisplay-Medium.ttf b/frontend-vue3/src/assets/fonts/Inter/InterDisplay-Medium.ttf new file mode 100644 index 0000000000..64748bd99e Binary files /dev/null and b/frontend-vue3/src/assets/fonts/Inter/InterDisplay-Medium.ttf differ diff --git a/frontend-vue3/src/assets/fonts/Inter/InterDisplay-Regular.ttf b/frontend-vue3/src/assets/fonts/Inter/InterDisplay-Regular.ttf new file mode 100644 index 0000000000..f4ac57f376 Binary files /dev/null and b/frontend-vue3/src/assets/fonts/Inter/InterDisplay-Regular.ttf differ diff --git a/frontend-vue3/src/assets/fonts/Inter/InterDisplay-SemiBold.ttf b/frontend-vue3/src/assets/fonts/Inter/InterDisplay-SemiBold.ttf new file mode 100644 index 0000000000..8abb2a7054 Binary files /dev/null and b/frontend-vue3/src/assets/fonts/Inter/InterDisplay-SemiBold.ttf differ diff --git a/frontend-vue3/src/assets/fonts/Inter/LICENSE.txt b/frontend-vue3/src/assets/fonts/Inter/LICENSE.txt new file mode 100644 index 0000000000..9b2ca37b3f --- /dev/null +++ b/frontend-vue3/src/assets/fonts/Inter/LICENSE.txt @@ -0,0 +1,92 @@ +Copyright (c) 2016 The Inter Project Authors (https://github.com/rsms/inter) + +This Font Software is licensed under the SIL Open Font License, Version 1.1. +This license is copied below, and is also available with a FAQ at: +http://scripts.sil.org/OFL + +----------------------------------------------------------- +SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007 +----------------------------------------------------------- + +PREAMBLE +The goals of the Open Font License (OFL) are to stimulate worldwide +development of collaborative font projects, to support the font creation +efforts of academic and linguistic communities, and to provide a free and +open framework in which fonts may be shared and improved in partnership +with others. + +The OFL allows the licensed fonts to be used, studied, modified and +redistributed freely as long as they are not sold by themselves. The +fonts, including any derivative works, can be bundled, embedded, +redistributed and/or sold with any software provided that any reserved +names are not used by derivative works. The fonts and derivatives, +however, cannot be released under any other type of license. The +requirement for fonts to remain under this license does not apply +to any document created using the fonts or their derivatives. + +DEFINITIONS +"Font Software" refers to the set of files released by the Copyright +Holder(s) under this license and clearly marked as such. This may +include source files, build scripts and documentation. + +"Reserved Font Name" refers to any names specified as such after the +copyright statement(s). + +"Original Version" refers to the collection of Font Software components as +distributed by the Copyright Holder(s). + +"Modified Version" refers to any derivative made by adding to, deleting, +or substituting -- in part or in whole -- any of the components of the +Original Version, by changing formats or by porting the Font Software to a +new environment. + +"Author" refers to any designer, engineer, programmer, technical +writer or other person who contributed to the Font Software. + +PERMISSION AND CONDITIONS +Permission is hereby granted, free of charge, to any person obtaining +a copy of the Font Software, to use, study, copy, merge, embed, modify, +redistribute, and sell modified and unmodified copies of the Font +Software, subject to the following conditions: + +1) Neither the Font Software nor any of its individual components, +in Original or Modified Versions, may be sold by itself. + +2) Original or Modified Versions of the Font Software may be bundled, +redistributed and/or sold with any software, provided that each copy +contains the above copyright notice and this license. These can be +included either as stand-alone text files, human-readable headers or +in the appropriate machine-readable metadata fields within text or +binary files as long as those fields can be easily viewed by the user. + +3) No Modified Version of the Font Software may use the Reserved Font +Name(s) unless explicit written permission is granted by the corresponding +Copyright Holder. This restriction only applies to the primary font name as +presented to the users. + +4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font +Software shall not be used to promote, endorse or advertise any +Modified Version, except to acknowledge the contribution(s) of the +Copyright Holder(s) and the Author(s) or with their explicit written +permission. + +5) The Font Software, modified or unmodified, in part or in whole, +must be distributed entirely under this license, and must not be +distributed under any other license. The requirement for fonts to +remain under this license does not apply to any document created +using the Font Software. + +TERMINATION +This license becomes null and void if any of the above conditions are +not met. + +DISCLAIMER +THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT +OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE +COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL +DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM +OTHER DEALINGS IN THE FONT SOFTWARE. diff --git a/frontend-vue3/src/assets/icons/BigScreen.svg b/frontend-vue3/src/assets/icons/BigScreen.svg new file mode 100644 index 0000000000..88e320bd94 --- /dev/null +++ b/frontend-vue3/src/assets/icons/BigScreen.svg @@ -0,0 +1,4 @@ + + + + diff --git a/frontend-vue3/src/assets/icons/Coffee.vue b/frontend-vue3/src/assets/icons/Coffee.vue new file mode 100644 index 0000000000..ef7ae7f7ef --- /dev/null +++ b/frontend-vue3/src/assets/icons/Coffee.vue @@ -0,0 +1,62 @@ + diff --git a/frontend-vue3/src/assets/icons/ColumnLayout.svg b/frontend-vue3/src/assets/icons/ColumnLayout.svg new file mode 100644 index 0000000000..c640451de1 --- /dev/null +++ b/frontend-vue3/src/assets/icons/ColumnLayout.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/frontend-vue3/src/assets/icons/PaperSize.svg b/frontend-vue3/src/assets/icons/PaperSize.svg new file mode 100644 index 0000000000..5b2ec65313 --- /dev/null +++ b/frontend-vue3/src/assets/icons/PaperSize.svg @@ -0,0 +1,3 @@ + + + diff --git a/frontend-vue3/src/assets/icons/ResponsiveLayout.svg b/frontend-vue3/src/assets/icons/ResponsiveLayout.svg new file mode 100644 index 0000000000..f65d28cce0 --- /dev/null +++ b/frontend-vue3/src/assets/icons/ResponsiveLayout.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/frontend-vue3/src/assets/invitation/edge-left.svg b/frontend-vue3/src/assets/invitation/edge-left.svg new file mode 100644 index 0000000000..5d61de797e --- /dev/null +++ b/frontend-vue3/src/assets/invitation/edge-left.svg @@ -0,0 +1,31 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/frontend-vue3/src/assets/invitation/edge-right.svg b/frontend-vue3/src/assets/invitation/edge-right.svg new file mode 100644 index 0000000000..083701dc30 --- /dev/null +++ b/frontend-vue3/src/assets/invitation/edge-right.svg @@ -0,0 +1,41 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/frontend-vue3/src/assets/invitation/tree-left.svg b/frontend-vue3/src/assets/invitation/tree-left.svg new file mode 100644 index 0000000000..a0a6c8ccfd --- /dev/null +++ b/frontend-vue3/src/assets/invitation/tree-left.svg @@ -0,0 +1,16 @@ + + + + + + + + + + + + + + + + diff --git a/frontend-vue3/src/assets/invitation/tree-right.svg b/frontend-vue3/src/assets/invitation/tree-right.svg new file mode 100644 index 0000000000..443c359e56 --- /dev/null +++ b/frontend-vue3/src/assets/invitation/tree-right.svg @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + diff --git a/frontend-vue3/src/assets/logo.png b/frontend-vue3/src/assets/logo.png new file mode 100644 index 0000000000..f3d2503fc2 Binary files /dev/null and b/frontend-vue3/src/assets/logo.png differ diff --git a/frontend-vue3/src/assets/tents/ShootingStar.vue b/frontend-vue3/src/assets/tents/ShootingStar.vue new file mode 100644 index 0000000000..84acc6e684 --- /dev/null +++ b/frontend-vue3/src/assets/tents/ShootingStar.vue @@ -0,0 +1,37 @@ + + + diff --git a/frontend-vue3/src/assets/tents/TentDay.svg b/frontend-vue3/src/assets/tents/TentDay.svg new file mode 100644 index 0000000000..865ed192d9 --- /dev/null +++ b/frontend-vue3/src/assets/tents/TentDay.svg @@ -0,0 +1,33 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/frontend-vue3/src/assets/tents/TentNight.vue b/frontend-vue3/src/assets/tents/TentNight.vue new file mode 100644 index 0000000000..2bdf6a2fe6 --- /dev/null +++ b/frontend-vue3/src/assets/tents/TentNight.vue @@ -0,0 +1,201 @@ + + + + + diff --git a/frontend-vue3/src/assets/tents/stars.svg b/frontend-vue3/src/assets/tents/stars.svg new file mode 100644 index 0000000000..d794cdcaa9 --- /dev/null +++ b/frontend-vue3/src/assets/tents/stars.svg @@ -0,0 +1,109 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/frontend-vue3/src/common/assets/logos/GSLogo.svg b/frontend-vue3/src/common/assets/logos/GSLogo.svg new file mode 100644 index 0000000000..4903b5e411 --- /dev/null +++ b/frontend-vue3/src/common/assets/logos/GSLogo.svg @@ -0,0 +1,6 @@ + + + \ No newline at end of file diff --git a/frontend-vue3/src/common/assets/logos/JSLogo.svg b/frontend-vue3/src/common/assets/logos/JSLogo.svg new file mode 100644 index 0000000000..f0734b30cf --- /dev/null +++ b/frontend-vue3/src/common/assets/logos/JSLogo.svg @@ -0,0 +1,6 @@ + + + \ No newline at end of file diff --git a/frontend-vue3/src/common/eslint-local-rules/__tests__/matchingTranslationKeys.spec.js b/frontend-vue3/src/common/eslint-local-rules/__tests__/matchingTranslationKeys.spec.js new file mode 100644 index 0000000000..726d30ad18 --- /dev/null +++ b/frontend-vue3/src/common/eslint-local-rules/__tests__/matchingTranslationKeys.spec.js @@ -0,0 +1,358 @@ +import rule from '../matchingTranslationKeys.js' +import { RuleTester } from 'eslint' +import path from 'path' +import fs from 'fs' +import utils from 'eslint-plugin-vue/lib/utils/index.js' +import { describe, it } from 'vitest' +import localRules from 'eslint-plugin-local-rules' +import globals from 'globals' +import eslintParser from 'vue-eslint-parser' + +RuleTester.describe = describe +RuleTester.it = it + +const ruleTester = new RuleTester({ + plugins: { + 'local-rules': localRules, + }, + + languageOptions: { + parser: eslintParser, + globals: { + ...globals.node, + ...globals.jest, + }, + + parserOptions: { + parser: '@babel/eslint-parser', + }, + }, +}) +const ruleInstance = rule(path, utils, fs) + +const options = [ + { + ignoreKeysRegex: '^(global|entity|contentNode\\.[a-z][a-zA-Z]+)\\..+', + translationKeyPropRegex: '[a-zA-Z0-9]-i18n-key$', + }, +] + +ruleTester.run('local-rules/matching-translation-keys', ruleInstance, { + valid: [ + { + name: 'allows correct key in js', + code: '$t("components.hello.world")', + options: options, + filename: '/src/components/hello.js', + }, + { + name: 'allows correct key in vue component js', + code: '', + options: options, + filename: '/src/components/HelloWorld.vue', + }, + { + name: 'allows correct key in vue component setup script', + code: '', + options: options, + filename: '/src/components/HelloWorld.vue', + }, + { + name: 'allows correct key in scoped use in vue component js', + code: '', + options: options, + filename: '/src/components/HelloWorld.vue', + }, + { + name: 'allows correct key in vue component template mustache syntax', + code: '', + options: options, + filename: '/src/components/HelloWorld.vue', + }, + { + name: 'allows correct key in vue component template v-bind', + code: '', + options: options, + filename: '/src/components/HelloWorld.vue', + }, + { + name: 'allows correct key in vue component template i18n prop, based on translationKeyPropRegex', + code: '', + options: options, + filename: '/src/components/HelloWorld.vue', + }, + { + name: 'allows correct key in vue component template v-bind i18n prop, based on translationKeyPropRegex', + code: '', + options: options, + filename: '/src/components/HelloWorld.vue', + }, + { + name: 'ignores valueless prop in vue component template i18n prop, based on translationKeyPropRegex', + code: '', + options: options, + filename: '/src/components/HelloWorld.vue', + }, + { + name: 'allows global key, based on ignoreKeysRegex', + code: '$t("global.something")', + options: options, + filename: '/src/components/hello.js', + }, + { + name: 'allows correct key with complex directory names', + code: '$t("components.camelCase.kebabCase.pascalCase.withPeriod.hello.world")', + options: options, + filename: '/src/components/camelCase/kebab-case/PascalCase/with.period/hello.js', + }, + { + name: 'allows correct key with single quotes', + code: "$t('components.hello.world')", + options: options, + filename: '/src/components/hello.js', + }, + { + name: 'allows correct key with single quotes', + code: '$t(\'components.hello.world\', 0, { test: "foo" })', + options: options, + filename: '/src/components/hello.js', + }, + { + name: 'allows correct key with backticks', + code: '$t(`components.hello.world`)', + options: options, + filename: '/src/components/hello.js', + }, + { + name: 'allows correct key with arguments', + code: '$t("components.hello.world", 0, { test: "foo" })', + options: options, + filename: '/src/components/hello.js', + }, + { + name: 'allows correct key when used without dollar sign', + code: 't(\'components.hello.world\', 0, { test: "foo" })', + options: options, + filename: '/src/components/hello.js', + }, + { + name: 'ignores call without arguments', + code: '$t()', + options: options, + filename: '/src/components/hello.js', + }, + { + name: 'ignores unrelated file type', + code: "$t('hello.world')", + options: options, + filename: '/src/components/hello.json', + }, + { + name: 'ignores test file', + code: "$t('hello.world')", + options: options, + filename: '/src/components/hello.spec.js', + }, + { + name: 'ignores test helper file', + code: "$t('hello.world')", + options: options, + filename: '/src/components/__tests__/hello.js', + }, + { + name: 'ignores e2e test file', + code: "$t('hello.world')", + options: options, + filename: '/src/e2e/hello.js', + }, + { + name: 'accepts source file paths which do not start with /src', + code: '$t("components.hello.world")', + options: options, + filename: '/components/hello.js', + }, + ], + + invalid: [ + { + name: 'lints incorrect key in js', + code: '$t("hello.world")', + options: options, + filename: '/src/components/hello.js', + errors: [ + { + message: + 'Translation key `hello.world` should start with `components.hello.`, based on file path `components/hello`.', + }, + ], + }, + { + name: 'lints incorrect key in vue component js', + code: '', + options: options, + filename: '/src/components/HelloWorld.vue', + errors: [ + { + message: + 'Translation key `hello.world` should start with `components.helloWorld.`, based on file path `components/HelloWorld`.', + }, + ], + }, + { + name: 'lints incorrect key in vue component setup script', + code: '', + options: options, + filename: '/src/components/HelloWorld.vue', + errors: [ + { + message: + 'Translation key `hello.world` should start with `components.helloWorld.`, based on file path `components/HelloWorld`.', + }, + ], + }, + { + name: 'lints correct key in scoped use in vue component js', + code: '', + options: options, + filename: '/src/components/HelloWorld.vue', + errors: [ + { + message: + 'Translation key `hello.world` should start with `components.helloWorld.`, based on file path `components/HelloWorld`.', + }, + ], + }, + { + name: 'lints incorrect key in vue component template mustache syntax', + code: '', + options: options, + filename: '/src/components/HelloWorld.vue', + errors: [ + { + message: + 'Translation key `hello.world` should start with `components.helloWorld.`, based on file path `components/HelloWorld`.', + }, + ], + }, + { + name: 'lints incorrect key in vue component template v-bind', + code: '', + options: options, + filename: '/src/components/HelloWorld.vue', + errors: [ + { + message: + 'Translation key `hello.world` should start with `components.helloWorld.`, based on file path `components/HelloWorld`.', + }, + ], + }, + { + name: 'lints incorrect key in component template i18n prop, based on translationKeyPropRegex', + code: '', + options: options, + filename: '/src/components/HelloWorld.vue', + errors: [ + { + message: + 'Translation key `hello.world` should start with `components.helloWorld.`, based on file path `components/HelloWorld`.', + }, + ], + }, + { + name: 'lints incorrect key in vue component template v-bind i18n prop, based on translationKeyPropRegex', + code: '', + options: options, + filename: '/src/components/HelloWorld.vue', + errors: [ + { + message: + 'Translation key `hello.world` should start with `components.helloWorld.`, based on file path `components/HelloWorld`.', + }, + ], + }, + { + name: 'lints incorrect global key, based on ignoreKeysRegex', + code: '$t("something.containing.global.hello.world")', + options: options, + filename: '/src/components/hello.js', + errors: [ + { + message: + 'Translation key `something.containing.global.hello.world` should start with `components.hello.`, based on file path `components/hello`.', + }, + ], + }, + { + name: 'lints incorrect key with single quotes', + code: "$t('hello.world')", + options: options, + filename: '/src/components/hello.js', + errors: [ + { + message: + 'Translation key `hello.world` should start with `components.hello.`, based on file path `components/hello`.', + }, + ], + }, + { + name: 'lints incorrect key with backticks', + code: '$t(`hello.world`)', + options: options, + filename: '/src/components/hello.js', + errors: [ + { + message: + 'Translation key `hello.world` should start with `components.hello.`, based on file path `components/hello`.', + }, + ], + }, + { + name: 'lints incorrect key with arguments', + code: '$t(\'hello.world\', 0, { test: "foo" })', + options: options, + filename: '/src/components/hello.js', + errors: [ + { + message: + 'Translation key `hello.world` should start with `components.hello.`, based on file path `components/hello`.', + }, + ], + }, + { + name: 'lints incorrect key when used without dollar sign', + code: 't(\'hello.world\', 0, { test: "foo" })', + options: options, + filename: '/src/components/hello.js', + errors: [ + { + message: + 'Translation key `hello.world` should start with `components.hello.`, based on file path `components/hello`.', + }, + ], + }, + { + name: 'lints empty key in js', + code: '$t("")', + options: options, + filename: '/src/components/hello.js', + errors: [ + { + message: + 'Translation key `` should start with `components.hello.`, based on file path `components/hello`.', + }, + ], + }, + { + name: 'lints in file with path which does not start with src/', + code: '$t("hello.world")', + options: options, + filename: '/components/hello.js', + errors: [ + { + message: + 'Translation key `hello.world` should start with `components.hello.`, based on file path `components/hello`.', + }, + ], + }, + ], +}) diff --git a/frontend-vue3/src/common/eslint-local-rules/__tests__/packageDirectory.spec.js b/frontend-vue3/src/common/eslint-local-rules/__tests__/packageDirectory.spec.js new file mode 100644 index 0000000000..49248cb800 --- /dev/null +++ b/frontend-vue3/src/common/eslint-local-rules/__tests__/packageDirectory.spec.js @@ -0,0 +1,13 @@ +import { describe, expect, it } from 'vitest' +import { packageDirectory } from '../packageDirectory.js' +import path from 'path' +import fs from 'fs' + +describe('packageDirectory', () => { + it('resolves the location of the closest package.json', () => { + const packageJsonFile = path.resolve(__dirname, '../../package.json') + fs.writeFileSync(packageJsonFile, '{}') + expect(packageDirectory(__dirname)).toEqual(path.resolve(__dirname, '../..')) + fs.unlinkSync(packageJsonFile) + }) +}) diff --git a/frontend-vue3/src/common/eslint-local-rules/matchingTranslationKeys.js b/frontend-vue3/src/common/eslint-local-rules/matchingTranslationKeys.js new file mode 100644 index 0000000000..ec3dc95289 --- /dev/null +++ b/frontend-vue3/src/common/eslint-local-rules/matchingTranslationKeys.js @@ -0,0 +1,233 @@ +import { packageDirectory } from "./packageDirectory.js" +import path from "path" + +export default function createMatchingTranslationKeys(utils) { + + /** + * Convert a file path to our convention for translation key structures + */ + function pathToTranslationKeyStructure(str) { + return ( + str + // convert words to camel case + .replace(/[-_.](\w)/gu, (_, c) => (c ? c.toUpperCase() : '')) + // convert slashes to dots with lower case letter after them + .replace(/\/(\w)/gu, (_, c) => '.' + (c ? c.toLowerCase() : '')) + ) + } + + /** + * Escape a string for use in a regular expression + */ + function escapeForRegExp(str) { + return str.replace(/[.*+?^${}()|[\]\\]/g, '\\$&') + } + + /** + * Read the value of a string literal + */ + function getStringLiteral(node) { + if (node && utils.isStringLiteral(node)) { + const value = utils.getStringLiteralValue(node) + if (value != null) { + return { name: value, value, loc: node.loc } + } + } + + // cannot check + return null + } + + /** + * Get the first method argument, including source location, from the given CallExpression + */ + function getFirstMethodArgument(node) { + return getStringLiteral(node.arguments[0]) + } + + /** + * Get the called method name from the given CallExpression + */ + function getCalledMethodName(node) { + const callee = utils.skipChainExpression(node.callee) + if (callee.type === 'Identifier') { + return callee.name + } + if (callee.type === 'MemberExpression') { + return utils.getStaticPropertyName(callee) + } + return null + } + + /** + * Gets the key of the given attribute node. + * E.g. given a node which represents the attribute id="my-header", + * this function would return "id" + */ + function getKeyName(attr) { + if (attr.directive) { + if (attr.key.name.name !== 'bind') { + // We are only interested in plain attrs and in v-bind attrs (which start with a colon) + return null + } + return attr.key.argument?.name + } + return attr.key.name + } + + /** + * Gets the value of the given attribute node. + * E.g. given a node which represents the attribute id="my-header", + * this function would return "my-header" + */ + function getPropValue(attr) { + const valueNode = attr.value + let value = null + if (!valueNode) { + return value + } + if (valueNode.type === 'VExpressionContainer') { + // The attribute is probably using v-bind (or prefix : colon), so it has a dynamic value. + // Try to read it as a string literal, and give up otherwise. + value = getStringLiteral(valueNode.expression) + } else if (valueNode.type === 'VLiteral') { + value = valueNode + } + return value + } + + function shouldProcessFile(filename) { + if (!(filename.endsWith('.vue') || filename.endsWith('.js'))) { + // We only process .vue components and .js files + return false + } + if ( + filename.endsWith('.spec.js') || + filename.match(/\/__tests__\//) || + filename.match(/\/e2e\//) + ) { + // ignore test files + return false + } + return true + } + + return { + meta: { + hasSuggestions: false, // We cannot easily auto-fix the translation JSON, so we can't make an automatic fix suggestion + type: 'suggestion', + docs: { + description: + "require translation keys in Vue components to match the component's file name", + }, + schema: [ + { + type: 'object', + properties: { + ignoreKeysRegex: { + type: 'string', + }, + translationKeyPropRegex: { + type: 'string', + }, + }, + additionalProperties: false, + }, + ], + }, + create(context) { + const filename = context.getFilename() + if (!shouldProcessFile(filename)) { + // Return no visitor logic if the file is not of interest to us + return {} + } + + const extension = path.extname(filename) + const filesystemPrefix = packageDirectory(filename) + const filepath = context + .getFilename() + .replace(new RegExp(`^${escapeForRegExp(filesystemPrefix)}/`), '') + // Optionally, remove src/ from the file path. We have this in frontend, but not in print + .replace(/^src\//, '') + .replace(new RegExp(`${escapeForRegExp(extension)}$`), '') + + const ignoreKeysRegex = context.options?.[0]?.ignoreKeysRegex + const _ignoreKeysRegex = new RegExp(ignoreKeysRegex) + + function verifyTranslationKey(methodArgument, filepath) { + const translationKey = methodArgument.value || '' + if (ignoreKeysRegex && translationKey.match(_ignoreKeysRegex)) { + // Some global keys are allowed everywhere + return + } + + const expectedPrefix = pathToTranslationKeyStructure(filepath) + + if (!translationKey.match(new RegExp(`^${escapeForRegExp(expectedPrefix)}\\.`))) { + context.report({ + node: methodArgument, + message: + 'Translation key `{{translationKey}}` should start with `{{expectedPrefix}}.`, based on file path `{{filepath}}`.', + data: { expectedPrefix, translationKey, filepath }, + }) + } + } + + const nodeVisitor = { + CallExpression(node) { + const calledMethodName = getCalledMethodName(node) + if (!['$tc', 'tc'].includes(calledMethodName)) { + // Not a translation call + return + } + + const methodArgument = getFirstMethodArgument(node) + if (!methodArgument) { + // Cannot find the value for the first argument, so we cannot check + return + } + + verifyTranslationKey(methodArgument, filepath) + }, + } + + const translationKeyPropRegex = context.options?.[0]?.translationKeyPropRegex + const _translationKeyPropRegex = new RegExp(translationKeyPropRegex) + + /** + * Some props of some of our components accept a translation key, which they pass into + * the $tc function internally. We can check these translation keys as well. + */ + const attributeVisitor = { + 'VElement > VStartTag > VAttribute': function (attr) { + const keyName = getKeyName(attr) + if (!keyName || !keyName.match(_translationKeyPropRegex)) { + // We are only interested in a very specific selection of props + return + } + + const value = getPropValue(attr) + if (value === null) { + // Could not extract value, or value was null. Either way, there is nothing to verify + return + } + + verifyTranslationKey(value, filepath) + }, + } + + return utils.defineTemplateBodyVisitor( + context, + // template visitor + { + ...nodeVisitor, + ...(translationKeyPropRegex ? attributeVisitor : {}), + }, + // script visitor + utils.isScriptSetup(context) + ? utils.defineScriptSetupVisitor(context, nodeVisitor) + : nodeVisitor + ) + }, + } +} diff --git a/frontend-vue3/src/common/eslint-local-rules/packageDirectory.js b/frontend-vue3/src/common/eslint-local-rules/packageDirectory.js new file mode 100644 index 0000000000..01bdca5468 --- /dev/null +++ b/frontend-vue3/src/common/eslint-local-rules/packageDirectory.js @@ -0,0 +1,21 @@ +import path from "path"; +import fs from "fs"; + +export function packageDirectory(filename) { + const { root } = path.parse(filename) + + let directory = filename + while (directory !== root) { + directory = path.dirname(directory) + + try { + if (fs.statSync(path.resolve(directory, 'package.json')).isFile()) { + return directory + } + } catch { + // Ignore, try going up to the next directory + } + } + + return '' +} diff --git a/frontend-vue3/src/common/helpers/__tests__/activityResponsibles.spec.js b/frontend-vue3/src/common/helpers/__tests__/activityResponsibles.spec.js new file mode 100644 index 0000000000..0010dde01f --- /dev/null +++ b/frontend-vue3/src/common/helpers/__tests__/activityResponsibles.spec.js @@ -0,0 +1,47 @@ +import { describe, expect, it } from "vitest"; +import { activityResponsiblesCommaSeparated } from '../activityResponsibles.js' + +describe('activityResponsibles', () => { + it('resolves camp collaboration with and without user', () => { + expect( + activityResponsiblesCommaSeparated( + { + activityResponsibles: () => ({ + items: [ + { + campCollaboration: () => ({ + inviteEmail: 'test@example.com', + }), + }, + { + campCollaboration: () => ({ + user: () => ({ + displayName: 'dummyUser', + }), + }), + }, + ], + }), + }, + null + ) + ).toEqual('test@example.com, dummyUser') + }) + + it('return empty string if no resonsibles', () => { + expect( + activityResponsiblesCommaSeparated( + { + activityResponsibles: () => ({ + items: [], + }), + }, + null + ) + ).toEqual('') + }) + + it('return empty string for null object', () => { + expect(activityResponsiblesCommaSeparated(null, null)).toEqual('') + }) +}) diff --git a/frontend-vue3/src/common/helpers/__tests__/campCollaborationDisplayName.spec.js b/frontend-vue3/src/common/helpers/__tests__/campCollaborationDisplayName.spec.js new file mode 100644 index 0000000000..fc762ff8ea --- /dev/null +++ b/frontend-vue3/src/common/helpers/__tests__/campCollaborationDisplayName.spec.js @@ -0,0 +1,35 @@ +import { describe, expect, it } from "vitest"; +import campCollaborationDisplayName from '../campCollaborationDisplayName.js' + +describe('campCollaborationDisplayName', () => { + it.each([ + [{}, ''], + [null, ''], + [undefined, ''], + [{ inviteEmail: 'ecamp@ecamp3.ch', user: null }, 'ecamp@ecamp3.ch'], + [{ inviteEmail: null, user: () => ({ displayName: 'Bi-Pi' }) }, 'Bi-Pi'], + [{ inviteEmail: null, _meta: {} }, ''], + [{ inviteEmail: null, _meta: { loading: true } }, ''], + [{ inviteEmail: null, user: () => ({ _meta: { loading: true } }) }, ''], + [ + { inviteEmail: null, status: 'inactive', user: () => ({ displayName: 'Bi-Pi' }) }, + 'Bi-Pi (inaktiv)', + ], + [ + { inviteEmail: 'ecamp@ecamp3.ch', status: 'inactive', user: null }, + 'ecamp@ecamp3.ch (inaktiv)', + ], + ])('maps %p to %p', (input, expected) => { + expect(campCollaborationDisplayName(input, () => 'inaktiv')).toEqual(expected) + }) + + it('does not add inactive indicator', () => { + expect( + campCollaborationDisplayName( + { inviteEmail: null, status: 'inactive', user: () => ({ displayName: 'Bi-Pi' }) }, + null, + false + ) + ).toEqual('Bi-Pi') + }) +}) diff --git a/frontend-vue3/src/common/helpers/__tests__/campCollaborationInitials.spec.js b/frontend-vue3/src/common/helpers/__tests__/campCollaborationInitials.spec.js new file mode 100644 index 0000000000..66cecb956e --- /dev/null +++ b/frontend-vue3/src/common/helpers/__tests__/campCollaborationInitials.spec.js @@ -0,0 +1,30 @@ +import { describe, expect, it } from "vitest"; +import campCollaborationInitials from '../campCollaborationInitials.js' + +describe('campCollaborationInitials', () => { + it.each([ + [{}, ''], + [null, ''], + [undefined, ''], + [{ inviteEmail: 'ecamp@ecamp3.ch', user: null }, 'EC'], + [{ inviteEmail: null, user: () => ({ displayName: 'Bi-Pi' }) }, 'BP'], + [{ inviteEmail: null, _meta: {} }, ''], + [{ inviteEmail: null, _meta: { loading: true } }, ''], + [{ inviteEmail: null, user: () => ({ _meta: { loading: true } }) }, ''], + [ + { inviteEmail: null, status: 'inactive', user: () => ({ displayName: 'Bam' }) }, + 'BA', + ], + [{ inviteEmail: 'ecamp@ecamp3.ch', status: 'inactive', user: null }, 'EC'], + [{ abbreviation: 'B', inviteEmail: null, user: null }, 'B'], + [{ abbreviation: 'AA', user: () => ({ displayName: 'Bi-Pi' }) }, 'AA'], + [ + { abbreviation: 'AA', user: () => ({ abbreviation: 'CC', displayName: 'Bi-Pi' }) }, + 'AA', + ], + [{ user: () => ({ abbreviation: 'QQ' }) }, 'QQ'], + [{ user: () => ({ abbreviation: 'QQ', displayName: 'Bi-Pi' }) }, 'QQ'], + ])('maps %o to "%s"', (input, expected) => { + expect(campCollaborationInitials(input)).toEqual(expected) + }) +}) diff --git a/frontend-vue3/src/common/helpers/__tests__/campCollaborationLegalName.spec.js b/frontend-vue3/src/common/helpers/__tests__/campCollaborationLegalName.spec.js new file mode 100644 index 0000000000..93cd7dda77 --- /dev/null +++ b/frontend-vue3/src/common/helpers/__tests__/campCollaborationLegalName.spec.js @@ -0,0 +1,36 @@ +import { describe, expect, it } from "vitest"; +import campCollaborationLegalName from '../campCollaborationLegalName.js' + +describe('campCollaborationLegalName', () => { + it.each([ + [{}, ''], + [null, ''], + [undefined, ''], + [{ inviteEmail: 'ecamp@ecamp3.ch', user: null }, ''], + [ + { + inviteEmail: null, + user: () => ({ profile: () => ({ legalName: 'Bi-Pi', _meta: {} }) }), + }, + 'Bi-Pi', + ], + [{ inviteEmail: null, _meta: {} }, ''], + [{ inviteEmail: null, _meta: { loading: true } }, ''], + [ + { + inviteEmail: null, + user: () => ({ _meta: { loading: true }, profile: () => ({ _meta: {} }) }), + }, + '', + ], + [ + { + inviteEmail: null, + user: () => ({ profile: () => ({ _meta: { loading: true, _meta: {} } }) }), + }, + '', + ], + ])('maps %p to %p', (input, expected) => { + expect(campCollaborationLegalName(input)).toEqual(expected) + }) +}) diff --git a/frontend-vue3/src/common/helpers/__tests__/campShortTitle.spec.js b/frontend-vue3/src/common/helpers/__tests__/campShortTitle.spec.js new file mode 100644 index 0000000000..ed452cf03f --- /dev/null +++ b/frontend-vue3/src/common/helpers/__tests__/campShortTitle.spec.js @@ -0,0 +1,54 @@ +import { describe, expect, it } from 'vitest' +import { campShortTitle } from '../campShortTitle.js' + +describe('campShortTitle', () => { + it.each([ + [{ shortTitle: null, title: 'Sommerlager Pfadistufe 2024' }, 'SoLa24 Pfadis'], + [{ shortTitle: null, title: 'HeLa Wolfsstufe 2024' }, 'HeLa24 Wölfli'], + [{ shortTitle: null, title: 'Bezirkspfingstlager Rover 2025' }, 'BezPfiLa25 Rover'], + [{ shortTitle: null, title: 'PfiLa Pfadistufe 2024' }, 'PfiLa24 Pfadis'], + [{ shortTitle: null, title: 'Pfingstlager 2024' }, 'PfiLa 2024'], + [{ shortTitle: null, title: 'Pio SoLa 2024' }, 'Pio SoLa 2024'], + [{ shortTitle: null, title: 'Herbstlager 2024' }, 'HeLa 2024'], + [{ shortTitle: null, title: 'Auffahrtslager 2025 Pfadi Olymp' }, 'AufLa25PfadiOlym'], + [{ shortTitle: null, title: 'Sola 2024 Jubla BuechBerg' }, 'SoLa24JublaBuech'], + [{ shortTitle: null, title: 'Pfingstlager PTA Bern 2024' }, 'PfiLa24 PTA Bern'], + [{ shortTitle: null, title: 'PfiLa 24 -Wolfsstufe Falkenstein' }, 'PfiLa24-WölfliFa'], + [{ shortTitle: null, title: 'MoBe Klassenlager 2018 Scuol' }, 'MoBeKlaLa18Scuol'], + [{ shortTitle: null, title: 'Cevilager Thun 2024' }, 'Cevilager24 Thun'], + [{ shortTitle: null, title: 'Sommerlager Blauring 2024' }, 'SoLa24 Blauring'], + [{ shortTitle: null, title: 'Sola24 Pfadistufe und Wölfli' }, 'SoLa24Pfadis&Wöl'], + [{ shortTitle: null, title: 'Dracheburg Pfila 2024' }, 'DracheburgPfiLa2'], + [{ shortTitle: null, title: 'Pio Bezirkspfila 2024' }, 'Pio BezPfiLa24'], + [{ shortTitle: null, title: 'Piostufensola 12.12.2026' }, 'PioSoLa26 12.12.'], + + [{ shortTitle: null, title: "Camp d'été à Thun 2024" }, 'été à Thun 2024'], + [{ shortTitle: null, title: "Campo di Pentecoste 2024" }, 'Pentecoste 2024'], + [{ shortTitle: null, title: "Camp d'hiver PiCos 2025" }, "hiver PiCos 2025"], + [{ shortTitle: null, title: "Camp d'automne Eclais 2025" }, "Aut Eclais 2025"], + [{ shortTitle: null, title: "Camp de pâques 2025 louveteaux" }, "Pâq25louveteaux"], + [{ shortTitle: null, title: "Campo di primavera 2025 esploratori" }, "Prim 2025 esplos"], + [{ shortTitle: null, title: "Campo autunnale 2028" }, "autunnale 2028"], + [{ shortTitle: null, title: "Campo dell'Ascensione 2025 Esploratori" }, "Asc 2025 Esplos"], + + [{ shortTitle: 'Pfila 2024', title: 'Pfingstlager 2024' }, 'Pfila 2024'], + [{ shortTitle: 'Pfila 2024', title: null }, 'Pfila 2024'], + [{ shortTitle: null, title: null }, ''], + [{ shortTitle: undefined, title: null }, ''], + [{ shortTitle: '0', title: 'Sola24' }, '0'], + [{ shortTitle: '', title: 'Sola24' }, 'SoLa24'], + + //error cases + [{ shortTitle: 0, title: 'Sola24' }, '0'], + [{ shortTitle: false, title: 'Sola24' }, 'false'], + [{ shortTitle: true, title: 'Sola24' }, 'true'], + [{ shortTitle: {}, title: 'Sola24' }, '[object Object]'], + [{ shortTitle: Symbol('foo'), title: 'Sola24' }, 'SoLa24'], + [{ shortTitle: [], title: 'Sola24' }, ''], + [{ shortTitle: /test/, title: 'Sola24' }, '/test/'], + [null, ''], + [undefined, ''], + ])('maps "%s" to "%s"', (input, expected) => { + expect(campShortTitle(input)).toEqual(expected) + }) +}) diff --git a/frontend-vue3/src/common/helpers/__tests__/colors.spec.js b/frontend-vue3/src/common/helpers/__tests__/colors.spec.js new file mode 100644 index 0000000000..9eadb357f0 --- /dev/null +++ b/frontend-vue3/src/common/helpers/__tests__/colors.spec.js @@ -0,0 +1,62 @@ +import { describe, expect, it } from "vitest"; +import { campCollaborationColor, idToColor, userColor } from '../colors.js' + +describe('idToColor', () => { + it.each([ + [[undefined, false], '#4d4d4d'], + [[null, false], '#4d4d4d'], + [['', false], '#4d4d4d'], + [['0000000', false], '#900'], + [['0000000', true], '#4d4d4d'], + [['fffffff', false], '#992600'], + [['Wrong input', false], '#900'], + ])('maps %p to %p', (input, expected) => { + expect(idToColor(...input)).toEqual(expected) + }) + + it('uses false as default for inactive', () => { + expect(idToColor('fffffff')).toEqual('#992600') + }) +}) + +describe('userColor', () => { + it.each([ + [{ id: 'fffffff' }, '#992600'], + [{ name: 'test' }, '#4d4d4d'], + [{ _meta: {} }, '#4d4d4d'], + [{ _meta: { loading: true } }, '#4d4d4d'], + [{ color: '#abcdef' }, '#abcdef'], + [{ color: '#abcdef', _meta: { loading: true } }, '#4d4d4d'], + ])('maps %p to %p', (input, expected) => { + expect(userColor(input)).toEqual(expected) + }) +}) + +describe('campCollaborationColor', () => { + it.each([ + [{}, '#4d4d4d'], + [null, '#4d4d4d'], + [undefined, '#4d4d4d'], + [{ id: 'fffffff', user: null }, '#992600'], + [{ id: 'fffffff', user: () => ({ id: '0000000' }) }, '#900'], + [{ id: 'fffffff', _meta: {} }, '#992600'], + [{ _meta: { loading: true } }, '#4d4d4d'], + [{ id: 'fffffff', user: () => ({ _meta: { loading: true } }) }, '#4d4d4d'], + [{ color: '#ECA110' }, '#ECA110'], + [{ color: '#ECA110', _meta: { loading: true } }, '#4d4d4d'], + [ + { id: 'fffffff', user: () => ({ color: '#ECA110', _meta: { loading: true } }) }, + '#4d4d4d', + ], + [ + { + id: 'fffffff', + _meta: { loading: true }, + user: () => ({ color: '#ECA110', _meta: { loading: true } }), + }, + '#4d4d4d', + ], + ])('maps %o to "%s"', (input, expected) => { + expect(campCollaborationColor(input)).toEqual(expected) + }) +}) diff --git a/frontend-vue3/src/common/helpers/__tests__/dateHelperUTCFormatted.spec.js b/frontend-vue3/src/common/helpers/__tests__/dateHelperUTCFormatted.spec.js new file mode 100644 index 0000000000..7d645be2b3 --- /dev/null +++ b/frontend-vue3/src/common/helpers/__tests__/dateHelperUTCFormatted.spec.js @@ -0,0 +1,97 @@ +import { describe, expect, it } from "vitest"; +import { + dateRange, + rangeLongEnd, + rangeShort, + timeDurationShort, +} from '../dateHelperUTCFormatted.js' + +const tcMock = (string, _, obj = {}) => { + return Object.entries(obj).reduce((previous, [key, value]) => { + return previous.replace(`{${key}}`, value) + }, tcMockString(string)) +} + +const tcMockString = (string) => { + switch (string) { + case 'global.datetime.dateLong': + return 'dd L' + case 'global.datetime.dateShort': + return 'dd D.M.' + case 'global.datetime.dateTimeLong': + return 'dd L HH:mm' + case 'global.datetime.hourLong': + return 'HH:mm' + case 'global.datetime.hourShort': + return 'H:mm' + case 'global.datetime.duration.minutesOnly': + return '{minutes}min' + case 'global.datetime.duration.hoursOnly': + return '{hours}h' + case 'global.datetime.duration.daysOnly': + return '{days}d' + case 'global.datetime.duration.daysAndHours': + return '{days}d {hours}h' + case 'global.datetime.duration.daysAndHoursAndMinutes': + return '{days}d {hours}h {minutes}min' + case 'global.datetime.duration.daysAndMinutes': + return '{days}d {minutes}min' + case 'global.datetime.duration.hoursAndMinutes': + return '{hours}h {minutes}min' + } +} + +describe('timeDurationShort', function () { + it.each([ + ['only day(s)', '1d', '2020-06-07T10:00:00.000Z', '2020-06-08T10:00:00.000Z'], + ['only hour(s)', '1h', '2020-06-07T10:00:00.000Z', '2020-06-07T11:00:00.000Z'], + ['only minute(s)', '30min', '2020-06-07T10:00:00.000Z', '2020-06-07T10:30:00.000Z'], + ['all', '2d 1h 30min', '2020-06-07T10:00:00.000Z', '2020-06-09T11:30:00.000Z'], + ['days&minutes', '2d 45min', '2020-06-07T10:00:00.000Z', '2020-06-09T10:45:00.000Z'], + ['hour&minutes', '1h 30min', '2020-06-07T10:00:00.000Z', '2020-06-07T11:30:00.000Z'], + ['leap year', '2d', '2020-02-28T10:00:00.000Z', '2020-03-01T10:00:00.000Z'], + ['year', '730d 1h 30min', '2020-06-07T10:00:00.000Z', '2022-06-07T11:30:00.000Z'], + ['0', '0min', '2020-06-07T10:00:00.000Z', '2020-06-07T10:00:00.000Z'], + ])('should print %s: %s', (_, duration, start, end) => { + expect(timeDurationShort(start, end, tcMock)).toEqual(duration) + }) +}) + +describe('rangeShort', () => { + it('omits end date if it is the same as start date: Tu 1.1. 20:00 - 22:00', () => { + expect( + rangeShort('2019-01-01T20:00:00.000Z', '2019-01-01T22:00:00.000Z', tcMock) + ).toEqual('Tu 1.1. 20:00 - 22:00') + }) + it('prints end date if it another date: Tu 1.1. 14:00 - We 2.1. 10:00', () => { + expect( + rangeShort('2019-01-01T14:00:00.000Z', '2019-01-02T10:00:00.000Z', tcMock) + ).toEqual('Tu 1.1. 14:00 - We 2.1. 10:00') + }) +}) + +describe('rangeLongEnd', () => { + it('omits end date if it is the same as start date: 20:00 - 22:00', () => { + expect( + rangeLongEnd('2019-01-01T20:00:00.000Z', '2019-01-01T22:00:00.000Z', tcMock) + ).toEqual('20:00 - 22:00') + }) + it('prints end date if it another date: 14:00 - We 2.1. 10:00', () => { + expect( + rangeLongEnd('2019-01-01T14:00:00.000Z', '2019-01-02T10:00:00.000Z', tcMock) + ).toEqual('14:00 - We 2.1. 10:00') + }) +}) + +describe('dateRange', () => { + it('omits end date if it is the same as start date: Tu 01/01/2019', () => { + expect( + dateRange('2019-01-01T20:00:00.000Z', '2019-01-01T22:00:00.000Z', tcMock) + ).toEqual('Tu 01/01/2019') + }) + it('prints end date if it another date: Tu 1.1. - We 01/02/2019', () => { + expect( + dateRange('2019-01-01T14:00:00.000Z', '2019-01-02T10:00:00.000Z', tcMock) + ).toEqual('Tu 1.1. - We 01/02/2019') + }) +}) diff --git a/frontend-vue3/src/common/helpers/__tests__/dayResponsibles.spec.js b/frontend-vue3/src/common/helpers/__tests__/dayResponsibles.spec.js new file mode 100644 index 0000000000..e3623c8698 --- /dev/null +++ b/frontend-vue3/src/common/helpers/__tests__/dayResponsibles.spec.js @@ -0,0 +1,83 @@ +import { describe, expect, it } from "vitest"; +import { + dayResponsiblesCommaSeparated, + filterDayResponsiblesByDay, +} from '../dayResponsibles' + +const dayWith2Responsibles = { + _meta: { + self: '/day/1', + }, + period: () => ({ + dayResponsibles: () => ({ + items: [ + { + campCollaboration: () => ({ + inviteEmail: 'test@example.com', + }), + day: () => ({ + _meta: { self: '/day/1' }, + }), + }, + { + campCollaboration: () => ({ + user: () => ({ + displayName: 'dummyUser', + }), + }), + day: () => ({ + _meta: { self: '/day/1' }, + }), + }, + { + campCollaboration: () => ({ + user: () => ({ + displayName: 'responsibleUserOnAnotherDay', + }), + }), + day: () => ({ + _meta: { self: '/day/2' }, + }), + }, + ], + }), + }), +} + +const dayWithoutResponsibles = { + period: () => ({ + dayResponsibles: () => ({ + items: [], + }), + }), +} + +describe('dayResponsiblesCommaSeparated', () => { + it('resolves camp collaboration with and without user', () => { + expect(dayResponsiblesCommaSeparated(dayWith2Responsibles, null)).toEqual( + 'test@example.com, dummyUser' + ) + }) + + it('return empty string if no responsibles', () => { + expect(dayResponsiblesCommaSeparated(dayWithoutResponsibles, null)).toEqual('') + }) + + it('return empty string for null object', () => { + expect(dayResponsiblesCommaSeparated(null, null)).toEqual('') + }) +}) + +describe('filterDayResponsiblesByDay', () => { + it('resolves camp collaboration with and without user', () => { + expect(filterDayResponsiblesByDay(dayWith2Responsibles).length).toEqual(2) + }) + + it('return empty string if no responsibles', () => { + expect(filterDayResponsiblesByDay(dayWithoutResponsibles)).toEqual([]) + }) + + it('return empty string for null object', () => { + expect(filterDayResponsiblesByDay(null)).toEqual([]) + }) +}) diff --git a/frontend-vue3/src/common/helpers/__tests__/filterMatchScheduleEntry.spec.js b/frontend-vue3/src/common/helpers/__tests__/filterMatchScheduleEntry.spec.js new file mode 100644 index 0000000000..783a677edd --- /dev/null +++ b/frontend-vue3/src/common/helpers/__tests__/filterMatchScheduleEntry.spec.js @@ -0,0 +1,142 @@ +import { describe, expect, it } from "vitest"; +import { filterMatchScheduleEntry } from '../filterMatchScheduleEntry.js' + +const scheduleEntry = { + period: () => ({ _meta: { self: '/periods/1a2b3c4d' } }), + day: () => ({ _meta: { self: '/days/1a2b3c4d' } }), + activity: () => ({ + category: () => ({ _meta: { self: '/categories/1a2b3c4d' } }), + activityResponsibles: () => ({ + items: [ + { campCollaboration: () => ({ _meta: { self: '/camp_collaborations/1a2b3c4d' } }) }, + { campCollaboration: () => ({ _meta: { self: '/camp_collaborations/ffffffff' } }) }, + ] + }), + progressLabel: () => ({ _meta: { self: '/progress_labels/1a2b3c4d' } }) + }), +} + +describe('filterMatchScheduleEntry', () => { + it.each([ + [null, true], + [undefined, true], + ['wrong input', true], + [{}, true], + [{ period: undefined }, true], + [{ period: null }, true], + [{ period: '/periods/1a2b3c4d' }, true], + [{ period: '/periods/00000000' }, false], + [{ period: ['/periods/1a2b3c4d'] }, false], // an array of periods is currently not supported + [{ day: undefined }, true], + [{ day: null }, true], + [{ day: '/days/1a2b3c4d' }, true], + [{ day: '/days/00000000' }, false], + [{ day: ['/days/1a2b3c4d'] }, true], + [{ day: ['/days/00000000'] }, false], + [{ day: ['/days/1a2b3c4d', '/days/00000000'] }, true], + [{ day: ['/days/00000000', '/days/1a2b3c4d'] }, true], + [{ category: undefined }, true], + [{ category: null }, true], + [{ category: '/categories/1a2b3c4d' }, true], + [{ category: '/categories/00000000' }, false], + [{ category: ['/categories/1a2b3c4d'] }, true], + [{ category: ['/categories/00000000'] }, false], + [{ category: ['/categories/1a2b3c4d', '/categories/00000000'] }, true], + [{ category: ['/categories/00000000', '/categories/1a2b3c4d'] }, true], + [{ responsible: undefined }, true], + [{ responsible: null }, true], + [{ responsible: ['/camp_collaborations/1a2b3c4d'] }, true], + [{ responsible: ['/camp_collaborations/00000000'] }, false], + [{ responsible: ['/camp_collaborations/1a2b3c4d', '/camp_collaborations/00000000'] }, false], + [{ responsible: ['/camp_collaborations/00000000', '/camp_collaborations/1a2b3c4d'] }, false], + [{ responsible: ['/camp_collaborations/1a2b3c4d', '/camp_collaborations/ffffffff'] }, true], + [{ responsible: ['/camp_collaborations/ffffffff', '/camp_collaborations/1a2b3c4d'] }, true], + [{ progressLabel: undefined }, true], + [{ progressLabel: null }, true], + [{ progressLabel: '/progress_labels/1a2b3c4d' }, true], + [{ progressLabel: '/progress_labels/00000000' }, false], + [{ progressLabel: ['/progress_labels/1a2b3c4d'] }, true], + [{ progressLabel: ['/progress_labels/00000000'] }, false], + [{ progressLabel: ['/progress_labels/1a2b3c4d', '/progress_labels/00000000'] }, true], + [{ progressLabel: ['/progress_labels/00000000', '/progress_labels/1a2b3c4d'] }, true], + [{ + period: '/periods/1a2b3c4d', + day: ['/days/1a2b3c4d'], + category: ['/categories/1a2b3c4d'], + responsible: ['/camp_collaborations/1a2b3c4d'], + progressLabel: ['/progress_labels/1a2b3c4d'], + }, true], + [{ + period: null, + day: ['/days/1a2b3c4d'], + category: ['/categories/1a2b3c4d'], + responsible: ['/camp_collaborations/1a2b3c4d'], + progressLabel: ['/progress_labels/1a2b3c4d'], + }, true], + [{ + period: '/periods/1a2b3c4d', + day: null, + category: ['/categories/1a2b3c4d'], + responsible: ['/camp_collaborations/1a2b3c4d'], + progressLabel: ['/progress_labels/1a2b3c4d'], + }, true], + [{ + period: '/periods/1a2b3c4d', + day: ['/days/1a2b3c4d'], + category: null, + responsible: ['/camp_collaborations/1a2b3c4d'], + progressLabel: ['/progress_labels/1a2b3c4d'], + }, true], + [{ + period: '/periods/1a2b3c4d', + day: ['/days/1a2b3c4d'], + category: ['/categories/1a2b3c4d'], + responsible: null, + progressLabel: ['/progress_labels/1a2b3c4d'], + }, true], + [{ + period: '/periods/1a2b3c4d', + day: ['/days/1a2b3c4d'], + category: ['/categories/1a2b3c4d'], + responsible: ['/camp_collaborations/1a2b3c4d'], + progressLabel: null, + }, true], + [{ + period: '/periods/00000000', + day: ['/days/1a2b3c4d'], + category: ['/categories/1a2b3c4d'], + responsible: ['/camp_collaborations/1a2b3c4d'], + progressLabel: ['/progress_labels/1a2b3c4d'], + }, false], + [{ + period: '/periods/1a2b3c4d', + day: ['/days/00000000'], + category: ['/categories/1a2b3c4d'], + responsible: ['/camp_collaborations/1a2b3c4d'], + progressLabel: ['/progress_labels/1a2b3c4d'], + }, false], + [{ + period: '/periods/1a2b3c4d', + day: ['/days/1a2b3c4d'], + category: ['/categories/00000000'], + responsible: ['/camp_collaborations/1a2b3c4d'], + progressLabel: ['/progress_labels/1a2b3c4d'], + }, false], + [{ + period: '/periods/1a2b3c4d', + day: ['/days/1a2b3c4d'], + category: ['/categories/1a2b3c4d'], + responsible: ['/camp_collaborations/00000000'], + progressLabel: ['/progress_labels/1a2b3c4d'], + }, false], + [{ + period: '/periods/1a2b3c4d', + day: ['/days/1a2b3c4d'], + category: ['/categories/1a2b3c4d'], + responsible: ['/camp_collaborations/1a2b3c4d'], + progressLabel: ['/progress_labels/00000000'], + }, false], + ])('maps %o to %s', (filter, expected) => { + expect(filterMatchScheduleEntry(scheduleEntry, filter)).toEqual(expected) + }) +}) diff --git a/frontend-vue3/src/common/helpers/__tests__/initials.spec.js b/frontend-vue3/src/common/helpers/__tests__/initials.spec.js new file mode 100644 index 0000000000..895b46db75 --- /dev/null +++ b/frontend-vue3/src/common/helpers/__tests__/initials.spec.js @@ -0,0 +1,29 @@ +import { describe, expect, it } from "vitest"; +import initials from '../initials.js' + +describe('initials', () => { + it.each([ + [undefined, ''], + [null, ''], + ['', ''], + [' ', ''], + [' ', ''], + ['.,_', ''], + [':)', ':)'], + ['a', 'A'], + ['ab', 'AB'], + ['Ab', 'AB'], + ['aB', 'AB'], + ['Regulus Arcturus Black', 'RA'], + ['luke skywalker', 'LS'], + ['Luke', 'LU'], + ['eCamp', 'EC'], + ['Bi-Pi', 'BP'], + ['bi-pi@scouts.com', 'BP'], + ['ecamp@scouts.com', 'EC'], + ['Happy 😊', 'H😊'], + ['Ömer Çedille', 'ÖÇ'], + ])('maps %p to %p', (input, expected) => { + expect(initials(input)).toEqual(expected) + }) +}) diff --git a/frontend-vue3/src/common/helpers/__tests__/interpolation.spec.js b/frontend-vue3/src/common/helpers/__tests__/interpolation.spec.js new file mode 100644 index 0000000000..c0ee4cb51b --- /dev/null +++ b/frontend-vue3/src/common/helpers/__tests__/interpolation.spec.js @@ -0,0 +1,66 @@ +import { describe, expect, it } from "vitest"; +import { lerp, clamp, invlerp, range } from '../interpolation.js' + +describe('lerp', () => { + it.each([ + [[0, 50, 0.5], 25], + [[1, 3, 0.5], 2], + [[0, 5, 0.2], 1], + [[2, 7, 1], 7], + [[8, 4, 0.5], 6], + [[5, 4, 1], 4], + [[3, 7, 2], 11], + [[2, 3, 3], 5], + [[-8, -4, 0.5], -6], + [[-2, -4, 0.25], -2.5], + [[0, 10, 0.1], 1], + [[10, 50, 1], 50], + ])('maps %p to %p', (input, expected) => { + expect(lerp(...input)).toEqual(expected) + }) +}) + +describe('clamp', () => { + it.each([ + [[0.5, 0, 50], 0.5], + [[3, 0, 5], 3], + [[2, -5, 10], 2], + [[8, 1, 3], 3], + [[5, -1, 2], 2], + [[3, 5, 10], 5], + [[1, 2, 3], 2], + [[11, 0, 10], 10], + [[1, 10, 50], 10], + ])('maps %p to %p', (input, expected) => { + expect(clamp(...input)).toEqual(expected) + }) +}) + +describe('invlerp', () => { + it.each([ + [[0, 2, 1], 0.5], + [[-10, 0, -5], 0.5], + [[-10, 10, 8], 0.9], + [[3, 7, 5], 0.5], + [[-1, 1, 10], 1], + [[99, 101, 42], 0], + [[-100, 100, -100], 0], + ])('maps %p to %p', (input, expected) => { + expect(invlerp(...input)).toEqual(expected) + }) +}) + +describe('range', () => { + it.each([ + [[0, 1, 10, 20, 0.5], 15], + [[10, 0, 20, 40, 7.5], 25], + [[-10, 10, 8, 96, 5], 74], + [[16, 32, 8, 14, 24], 11], + [[-100, 100, 0, 100, 0], 50], + [[-100, 100, 0, 100, 50], 75], + [[42, 42, 0, 100, 42], NaN], + [[1337, 50, 0, 100, 42], 100], + ])('maps %p to %p', (input, expected) => { + expect(range(...input)).toEqual(expected) + }) +}) diff --git a/frontend-vue3/src/common/helpers/__tests__/materialListsSorted.spec.js b/frontend-vue3/src/common/helpers/__tests__/materialListsSorted.spec.js new file mode 100644 index 0000000000..ca4327cb45 --- /dev/null +++ b/frontend-vue3/src/common/helpers/__tests__/materialListsSorted.spec.js @@ -0,0 +1,22 @@ +import { describe, expect, it } from "vitest"; +import materialListsSorted from '../materialListsSorted.js' + +describe('materialListsSorted', () => { + const list1 = { campCollaboration: '1a2b3c4d', name: 'B2-name' } + const list2 = { campCollaboration: '1a2b3c4d', name: 'b1-name' } + const list3 = { campCollaboration: '1a2b3c4d', name: 'a3-name' } + const list4 = { campCollaboration: null, name: 'B2-name' } + const list5 = { campCollaboration: null, name: 'b1-name' } + const list6 = { campCollaboration: null, name: 'a3-name' } + + it('sorts Non-User bevor User-Lists, then alphabetically', () => { + expect(materialListsSorted([list1, list2, list3, list4, list5, list6])).toEqual([ + list6, + list5, + list4, + list3, + list2, + list1, + ]) + }) +}) diff --git a/frontend-vue3/src/common/helpers/__tests__/picasso.spec.js b/frontend-vue3/src/common/helpers/__tests__/picasso.spec.js new file mode 100644 index 0000000000..ed3c1883cd --- /dev/null +++ b/frontend-vue3/src/common/helpers/__tests__/picasso.spec.js @@ -0,0 +1,259 @@ +import { describe, expect, it } from "vitest"; +import { splitDaysIntoPages, calculateBedtime } from '../picasso.js' +import dayjs from '@/common/helpers/dayjs.js' + +describe('splitPicassoIntoPages', () => { + function daysBetween(start, end) { + // Generates an array [start, start + 1, start + 2, ..., end - 1, end] + return [...Array(end - start + 1).keys()].map((day) => day + start) + } + + it.each([ + [[[], 1], []], + [[[], 8], []], + [[[], 0], []], + [ + [daysBetween(1, 3), 2], + [daysBetween(1, 2), daysBetween(3, 3)], + ], + [ + [daysBetween(1, 15), 8], + [daysBetween(1, 8), daysBetween(9, 15)], + ], + [ + [daysBetween(1, 14), 4], + [daysBetween(1, 4), daysBetween(5, 8), daysBetween(9, 11), daysBetween(12, 14)], + ], + ])('maps %p to %p', (input, expected) => { + expect(splitDaysIntoPages(...input)).toEqual(expected) + }) +}) + +describe('calculateBedtime', () => { + it.each([ + [ + 'no schedule entries', + [ + [], + dayjs, + dayjs.utc('2022-01-02T00:00:00+00:00'), + dayjs.utc('2022-01-03T00:00:00+00:00'), + 1, + ], + { getUpTime: 0, bedtime: 24 }, + ], + [ + 'single schedule entry', + [ + [{ start: '2022-01-02T08:00:00+00:00', end: '2022-01-02T10:00:00+00:00' }], + dayjs, + dayjs.utc('2022-01-02T00:00:00+00:00'), + dayjs.utc('2022-01-03T00:00:00+00:00'), + 1, + ], + { getUpTime: 8, bedtime: 10 }, + ], + [ + 'single schedule entry, not ending on full hours', + [ + [{ start: '2022-01-02T08:15:00+00:00', end: '2022-01-02T09:35:00+00:00' }], + dayjs, + dayjs.utc('2022-01-02T00:00:00+00:00'), + dayjs.utc('2022-01-03T00:00:00+00:00'), + 1, + ], + { getUpTime: 8, bedtime: 10 }, + ], + [ + 'two schedule entries, forcing the gap to end before the first schedule entry even though there is a larger gap during the day', + [ + [ + { start: '2022-01-02T08:00:00+00:00', end: '2022-01-02T10:00:00+00:00' }, + { start: '2022-01-02T20:00:00+00:00', end: '2022-01-02T23:00:00+00:00' }, + ], + dayjs, + dayjs.utc('2022-01-02T00:00:00+00:00'), + dayjs.utc('2022-01-03T00:00:00+00:00'), + 1, + ], + { getUpTime: 8, bedtime: 23 }, + ], + [ + 'schedule entry across midnight', + [ + [ + { start: '2022-01-02T08:00:00+00:00', end: '2022-01-02T17:00:00+00:00' }, + { start: '2022-01-02T20:00:00+00:00', end: '2022-01-02T23:00:00+00:00' }, + { start: '2022-01-02T23:00:00+00:00', end: '2022-01-03T02:00:00+00:00' }, + ], + dayjs, + dayjs.utc('2022-01-02T00:00:00+00:00'), + dayjs.utc('2022-01-04T00:00:00+00:00'), + 1, + ], + { getUpTime: 8, bedtime: 26 }, + ], + [ + 'schedule entry through the night, end is not cut off', + [ + [ + { start: '2022-01-02T08:00:00+00:00', end: '2022-01-02T17:00:00+00:00' }, + { start: '2022-01-02T20:00:00+00:00', end: '2022-01-02T23:00:00+00:00' }, + { start: '2022-01-02T23:00:00+00:00', end: '2022-01-03T06:00:00+00:00' }, + ], + dayjs, + dayjs.utc('2022-01-02T00:00:00+00:00'), + dayjs.utc('2022-01-04T00:00:00+00:00'), + 1, + ], + { getUpTime: 5, bedtime: 24 }, + ], + [ + '24hour schedule entry does not block whole day', + [ + [ + { start: '2022-01-02T08:00:00+00:00', end: '2022-01-02T17:00:00+00:00' }, + { start: '2022-01-02T20:00:00+00:00', end: '2022-01-02T23:00:00+00:00' }, + { start: '2022-01-02T23:00:00+00:00', end: '2022-01-03T02:00:00+00:00' }, + { start: '2022-01-03T12:00:00+00:00', end: '2022-01-04T12:00:00+00:00' }, + ], + dayjs, + dayjs.utc('2022-01-02T00:00:00+00:00'), + dayjs.utc('2022-01-05T00:00:00+00:00'), + 1, + ], + { getUpTime: 8, bedtime: 26 }, + ], + [ + 'schedule entry starting at bedtime on a full hour moves the bedtime later, to avoid hiding the schedule entry completely', + [ + [ + { start: '2022-01-02T08:00:00+00:00', end: '2022-01-02T22:00:00+00:00' }, + { start: '2022-01-02T22:00:00+00:00', end: '2022-01-03T08:30:00+00:00' }, + ], + dayjs, + dayjs.utc('2022-01-02T00:00:00+00:00'), + dayjs.utc('2022-01-04T00:00:00+00:00'), + 1, + ], + { getUpTime: 8, bedtime: 23 }, + ], + [ + 'schedule entry starting around bedtime on a half hour does not move the bedtime, because it is already visible enough', + [ + [ + { start: '2022-01-02T08:00:00+00:00', end: '2022-01-02T22:00:00+00:00' }, + { start: '2022-01-02T21:30:00+00:00', end: '2022-01-03T08:30:00+00:00' }, + ], + dayjs, + dayjs.utc('2022-01-02T00:00:00+00:00'), + dayjs.utc('2022-01-04T00:00:00+00:00'), + 1, + ], + { getUpTime: 8, bedtime: 22 }, + ], + [ + 'schedule entry starting around bedtime on a quarter hour moves the bedtime later, to make sure it is visible for at least half an hour', + [ + [ + { start: '2022-01-02T08:00:00+00:00', end: '2022-01-02T22:00:00+00:00' }, + { start: '2022-01-02T21:45:00+00:00', end: '2022-01-03T08:30:00+00:00' }, + ], + dayjs, + dayjs.utc('2022-01-02T00:00:00+00:00'), + dayjs.utc('2022-01-04T00:00:00+00:00'), + 1, + ], + { getUpTime: 8, bedtime: 23 }, + ], + [ + 'very short schedule entry starting around bedtime does not move the bedtime later, because it would not gain more visibility', + [ + [ + { start: '2022-01-02T08:00:00+00:00', end: '2022-01-02T22:00:00+00:00' }, + { start: '2022-01-02T21:45:00+00:00', end: '2022-01-02T22:00:00+00:00' }, + { start: '2022-01-02T20:00:00+00:00', end: '2022-01-03T08:30:00+00:00' }, + ], + dayjs, + dayjs.utc('2022-01-02T00:00:00+00:00'), + dayjs.utc('2022-01-04T00:00:00+00:00'), + 1, + ], + { getUpTime: 8, bedtime: 22 }, + ], + [ + 'schedule entry ending at getUpTime on a full hour moves the getUpTime earlier, to avoid hiding the schedule entry completely', + [ + [ + { start: '2022-01-02T08:00:00+00:00', end: '2022-01-02T22:00:00+00:00' }, + { start: '2022-01-02T21:30:00+00:00', end: '2022-01-03T08:00:00+00:00' }, + ], + dayjs, + dayjs.utc('2022-01-02T00:00:00+00:00'), + dayjs.utc('2022-01-04T00:00:00+00:00'), + 1, + ], + { getUpTime: 7, bedtime: 22 }, + ], + [ + 'schedule entry ending around getUpTime on a half hour does not move the getUpTime, because it is already visible enough', + [ + [ + { start: '2022-01-02T08:00:00+00:00', end: '2022-01-02T22:00:00+00:00' }, + { start: '2022-01-02T21:30:00+00:00', end: '2022-01-03T08:30:00+00:00' }, + ], + dayjs, + dayjs.utc('2022-01-02T00:00:00+00:00'), + dayjs.utc('2022-01-04T00:00:00+00:00'), + 1, + ], + { getUpTime: 8, bedtime: 22 }, + ], + [ + 'schedule entry ending around getUpTime on a quarter hour moves the getUpTime earlier, to make sure it is visible for at least half an hour', + [ + [ + { start: '2022-01-02T08:00:00+00:00', end: '2022-01-02T22:00:00+00:00' }, + { start: '2022-01-02T21:30:00+00:00', end: '2022-01-03T08:15:00+00:00' }, + ], + dayjs, + dayjs.utc('2022-01-02T00:00:00+00:00'), + dayjs.utc('2022-01-04T00:00:00+00:00'), + 1, + ], + { getUpTime: 7, bedtime: 22 }, + ], + [ + 'very short schedule entry ending around getUpTime does not move the getUpTime earlier, because it would not gain more visibility', + [ + [ + { start: '2022-01-02T08:00:00+00:00', end: '2022-01-02T22:00:00+00:00' }, + { start: '2022-01-03T08:00:00+00:00', end: '2022-01-03T08:15:00+00:00' }, + { start: '2022-01-02T21:30:00+00:00', end: '2022-01-03T09:00:00+00:00' }, + ], + dayjs, + dayjs.utc('2022-01-02T00:00:00+00:00'), + dayjs.utc('2022-01-04T00:00:00+00:00'), + 1, + ], + { getUpTime: 8, bedtime: 22 }, + ], + [ + 'empty first day, schedule entries only towards end of last day, latestGetUpTime falls back to a sensible value', + [ + [ + { start: '2022-01-03T18:00:00+00:00', end: '2022-01-03T19:00:00+00:00' }, + { start: '2022-01-03T20:00:00+00:00', end: '2022-01-03T21:00:00+00:00' }, + { start: '2022-01-03T22:00:00+00:00', end: '2022-01-03T23:00:00+00:00' }, + ], + dayjs, + dayjs.utc('2022-01-02T00:00:00+00:00'), + dayjs.utc('2022-01-04T00:00:00+00:00'), + 1, + ], + { getUpTime: 18, bedtime: 23 }, + ], + ])('%p', (title, input, expected) => { + expect(calculateBedtime(...input)).toEqual(expected) + }) +}) diff --git a/frontend-vue3/src/common/helpers/__tests__/scheduleEntryLayout.spec.js b/frontend-vue3/src/common/helpers/__tests__/scheduleEntryLayout.spec.js new file mode 100644 index 0000000000..298b1e576c --- /dev/null +++ b/frontend-vue3/src/common/helpers/__tests__/scheduleEntryLayout.spec.js @@ -0,0 +1,47 @@ +import { expect, it } from 'vitest' +import { arrange } from '../scheduleEntryLayout.js' + +it('should handle empty list', () => { + expect(arrange([])).toEqual([]) +}) +it('should arrange schedule entries in columns', () => { + const p0 = { + id: '0', + start: '2019-02-13 07:30', + end: '2019-02-13 08:30', + } + const p1 = { + id: '1', + start: '2019-02-13 08:00', + end: '2019-02-13 09:00', + } + const p2 = { + id: '2', + start: '2019-02-13 09:00', + end: '2019-02-13 10:00', + } + const p3 = { + id: '3', + start: '2019-02-10 00:00', + end: '2019-02-13 07:00', + } + const p4 = { + id: '4', + start: '2019-02-13 07:00', + end: '2019-02-13 10:00', + } + const p5 = { + id: '5', + start: '2019-02-13 08:00', + end: '2019-02-13 12:00', + } + + expect(arrange([p0, p1, p2, p3, p4, p5])).toMatchObject([ + { id: '3', left: 0, width: 100 }, + { id: '4', left: 0, width: 25 }, + { id: '0', left: 25, width: 25 }, + { id: '5', left: 50, width: 25 }, + { id: '1', left: 75, width: 25 }, + { id: '2', left: 25, width: 25 }, + ]) +}) diff --git a/frontend-vue3/src/common/helpers/__tests__/userDisplayName.spec.js b/frontend-vue3/src/common/helpers/__tests__/userDisplayName.spec.js new file mode 100644 index 0000000000..72a7a429c4 --- /dev/null +++ b/frontend-vue3/src/common/helpers/__tests__/userDisplayName.spec.js @@ -0,0 +1,13 @@ +import { describe, expect, it } from "vitest"; +import userDisplayName from '../userDisplayName.js' + +describe('userDisplayName', () => { + it.each([ + [{ id: 'fffffff' }, ''], + [{ displayName: 'test' }, 'test'], + [{ displayName: 'test', _meta: {} }, 'test'], + [{ _meta: { loading: true } }, ''], + ])('maps %p to %p', (input, expected) => { + expect(userDisplayName(input)).toEqual(expected) + }) +}) diff --git a/frontend-vue3/src/common/helpers/__tests__/userInitials.spec.js b/frontend-vue3/src/common/helpers/__tests__/userInitials.spec.js new file mode 100644 index 0000000000..9dbb8c9e1d --- /dev/null +++ b/frontend-vue3/src/common/helpers/__tests__/userInitials.spec.js @@ -0,0 +1,17 @@ +import { describe, expect, it } from "vitest"; +import userInitials from '../userInitials.js' + +describe('userInitials', () => { + it.each([ + [{}, ''], + [null, ''], + [undefined, ''], + [{ id: 'fffffff' }, ''], + [{ displayName: 'test' }, 'TE'], + [{ displayName: 'test', _meta: {} }, 'TE'], + [{ _meta: { loading: true } }, ''], + [{ abbreviation: 'V3', displayName: 'test' }, 'V3'], + ])('maps %o to "%s"', (input, expected) => { + expect(userInitials(input)).toEqual(expected) + }) +}) diff --git a/frontend-vue3/src/common/helpers/__tests__/userLegalName.spec.js b/frontend-vue3/src/common/helpers/__tests__/userLegalName.spec.js new file mode 100644 index 0000000000..236bade2fd --- /dev/null +++ b/frontend-vue3/src/common/helpers/__tests__/userLegalName.spec.js @@ -0,0 +1,14 @@ +import { describe, expect, it } from 'vitest' +import userLegalName from '../userLegalName.js' + +describe('userLegalName', () => { + it.each([ + [{ id: 'fffffff', profile: () => ({ _meta: {} }) }, ''], + [{ profile: () => ({ legalName: 'test', _meta: {} }) }, 'test'], + [{ profile: () => ({ legalName: 'test', _meta: {} }), _meta: {} }, 'test'], + [{ profile: () => ({ _meta: {} }), _meta: { loading: true } }, ''], + [{ profile: () => ({ _meta: { loading: true } }) }, ''], + ])('maps %p to %p', (input, expected) => { + expect(userLegalName(input)).toEqual(expected) + }) +}) diff --git a/frontend-vue3/src/common/helpers/activityResponsibles.js b/frontend-vue3/src/common/helpers/activityResponsibles.js new file mode 100644 index 0000000000..b2fd9ab8ec --- /dev/null +++ b/frontend-vue3/src/common/helpers/activityResponsibles.js @@ -0,0 +1,17 @@ +import campCollaborationDisplayName from './campCollaborationDisplayName.js' + +/** + * Returns a display name for a camp collaboration based on its status + */ +const activityResponsiblesCommaSeparated = (activity, tc) => { + if (!activity) return '' + + return activity + .activityResponsibles() + .items.map((activityResponsible) => + campCollaborationDisplayName(activityResponsible.campCollaboration(), tc) + ) + .join(', ') +} + +export { activityResponsiblesCommaSeparated } diff --git a/frontend-vue3/src/common/helpers/campCollaborationDisplayName.js b/frontend-vue3/src/common/helpers/campCollaborationDisplayName.js new file mode 100644 index 0000000000..96a5101c28 --- /dev/null +++ b/frontend-vue3/src/common/helpers/campCollaborationDisplayName.js @@ -0,0 +1,21 @@ +import userDisplayName from './userDisplayName.js' + +/** + * Returns a display name for a camp collaboration based on its status + */ +export default function (campCollaboration, tc, indicateInactive = true) { + if (!campCollaboration) { + return '' + } + + let text = + typeof campCollaboration.user === 'function' + ? userDisplayName(campCollaboration.user()) + : campCollaboration.inviteEmail || '' + + if (campCollaboration.status === 'inactive' && indicateInactive) { + text += ' (' + tc('entity.campCollaboration.status.inactive') + ')' + } + + return text +} diff --git a/frontend-vue3/src/common/helpers/campCollaborationInitials.js b/frontend-vue3/src/common/helpers/campCollaborationInitials.js new file mode 100644 index 0000000000..3ca2823bf5 --- /dev/null +++ b/frontend-vue3/src/common/helpers/campCollaborationInitials.js @@ -0,0 +1,24 @@ +import userDisplayName from './userDisplayName.js' +import initials from './initials.js' + +/** + * Returns two characters to display for a camp collaboration based on its user + */ +export default function (campCollaboration) { + if (!campCollaboration) { + return '' + } + + if (campCollaboration?.abbreviation) { + return campCollaboration.abbreviation + } + + if (typeof campCollaboration.user === 'function') { + if (campCollaboration.user().abbreviation) { + return campCollaboration.user().abbreviation + } + return initials(userDisplayName(campCollaboration.user())) + } + + return initials(campCollaboration.inviteEmail || '') +} diff --git a/frontend-vue3/src/common/helpers/campCollaborationLegalName.js b/frontend-vue3/src/common/helpers/campCollaborationLegalName.js new file mode 100644 index 0000000000..a9e1522fb5 --- /dev/null +++ b/frontend-vue3/src/common/helpers/campCollaborationLegalName.js @@ -0,0 +1,14 @@ +import userLegalName from './userLegalName.js' + +/** + * Returns a legal name for a camp collaboration based on its status + */ +export default function (campCollaboration) { + if (!campCollaboration) { + return '' + } + + return typeof campCollaboration.user === 'function' + ? userLegalName(campCollaboration.user()) + : '' +} diff --git a/frontend-vue3/src/common/helpers/campShortTitle.js b/frontend-vue3/src/common/helpers/campShortTitle.js new file mode 100644 index 0000000000..f173096e03 --- /dev/null +++ b/frontend-vue3/src/common/helpers/campShortTitle.js @@ -0,0 +1,76 @@ +const AUTOMATIC_SHORTNERS = [ + { regex: /So(?:mmer)?la(?:ger)?/gi, text: 'SoLa' }, + { regex: /Pfi(?:ngst)?la(?:ger)?/gi, text: 'PfiLa' }, + { regex: /He(?:rbst)?la(?:ger)?/gi, text: 'HeLa' }, +] + +const ADDITIONAL_SHORTNERS = [ + { regex: /Auslandssola/gi, text: 'AuLa' }, + { regex: /Auffahrtslager/gi, text: 'AufLa' }, + { regex: /Abteilungslager/gi, text: 'AbLa' }, + { regex: /Klassenlager/gi, text: 'KlaLa' }, + { + regex: /(Bez)irks?(So|Ab|Au|Auf|He|Pfi)La|(Ka)ntonslager|(Bu)ndeslager/gi, + text: '$1$2$3$4La', + }, + { + regex: + /(?.*?\b)?(?(?:[A-Za-z]{2,}La)|(?:[A-Za-z]{2,}lager))(?(?:\s(?!19|20))|.*?)\s?(?:(?:19|20)(?\d{2}))(?.*)/g, + text: '$$$$$', + }, + { regex: /(Pfadi|Pio|Rover)stufe(?!n)/g, text: '$1s' }, + { regex: /(B)ie?berstufe(?!n)/gi, text: '$1iberli' }, + { regex: /(W)olfs?stufe(?!n)/gi, text: '$1ölfli' }, + { regex: /(E)sploratori/gi, text: '$1splos' }, + { + regex: /(Bie?ber|Wolfs?|Pfadi|Pio|Rover)stufen(So|Ab|Au|Auf|He|Pfi)La/gi, + text: '$1$2La', + }, + { + regex: /Campo? (.*? ?)(?:(?: ?d[ei] )?(Pentec[ôo]te|Pentecoste|primavera|printemps|p[âa]ques|pasqua)|(?:d')?([ée]t[eé]|automne|hiver)|(estivo|autunnale|invernale)|(?:de[l ]l[' ])?(Ascensione?))? (.*? ?)*?((?:19|20)\d{2})?/gi, + text: '$2$3$4$5 $1$6$7', + }, + { regex: /\bPrintemps/gi, text: 'Prt', }, + { regex: /\bPrimavera/gi, text: 'Prim', }, + { regex: /\bP[aâ]ques/gi, text: 'Pâq', }, + { regex: /\bPasqua/gi, text: 'Pas', }, + { regex: /\bAutomne/gi, text: 'Aut', }, + { regex: /\bAutunno/gi, text: 'Aut', }, + { regex: /\bHiver/gi, text: 'Hiv', }, + { regex: /\bInverno/gi, text: 'Inv', }, + { regex: /\bPentec[oô]s?te/gi, text: 'Pent', }, + { regex: /\bAscensione?/gi, text: 'Asc', }, + { regex: /\bEstate/gi, text: 'Est', }, + + { regex: /\b(?:und|et?)\b/g, text: '&' }, + { regex: /\b(?:19|20)(\d{2})\b/g, text: '$1' }, + { regex: /\s/g, text: '' }, +] + +function campShortTitle(camp) { + if (camp?.shortTitle != null && camp.shortTitle !== '' && typeof camp.shortTitle !== 'symbol') { + return `${camp.shortTitle}`.substring(0, 16) + } + + let title = camp?.title ?? '' + + for (const { regex, text } of AUTOMATIC_SHORTNERS) { + title = title.replace(regex, text) + } + + if (title.length <= 16) { + return title + } + + for (const { regex, text } of ADDITIONAL_SHORTNERS) { + title = title.replace(regex, text) + if (title.length <= 16) { + return title + } + } + return title.substring(0, 16) +} + +export { campShortTitle } + +export default campShortTitle diff --git a/frontend-vue3/src/common/helpers/colors.js b/frontend-vue3/src/common/helpers/colors.js new file mode 100644 index 0000000000..4e654108c2 --- /dev/null +++ b/frontend-vue3/src/common/helpers/colors.js @@ -0,0 +1,76 @@ +import Color from 'colorjs.io' + +/** + * @param color {string} CSS compatible string color + * @returns {string} colorblack or white depending on input color + */ +function contrastColor(color) { + const input = new Color(color) + const black = new Color('#000') + const white = new Color('#fff') + const blackContrast = Math.abs(input.contrast(black, 'APCA')) + const whiteContrast = Math.abs(input.contrast(white, 'APCA')) + return blackContrast > whiteContrast + ? black.toString({ format: 'hex' }) + : white.toString({ format: 'hex' }) +} + +/** + * @param id {string} generated id + * @param inactive {boolean} status + * @returns {string} hsl color + */ +function idToColor(id, inactive = false) { + if (!id) { + return new Color('HSL', [0, 0, 30]).to('srgb').toString({ format: 'hex' }) + } + return new Color('HSL', [parseInt(id, 16) % 360 || 0, inactive ? 0 : 100, 30]) + .to('srgb') + .toString({ format: 'hex' }) +} + +/** + * @returns {string} + */ +function defaultColor() { + return new Color('HSL', [0, 0, 10]).toString({ + format: 'hex', + }) +} + +/** + * @returns {string} color for a user based on their id + */ +function userColor(user, inactive = user._meta?.loading) { + if (user.color && !inactive) { + return user.color + } + return idToColor(user.id, inactive) +} + +/** + * @returns {string} color for a camp collaboration based on its user id and status + */ +function campCollaborationColor(campCollaboration) { + if (!campCollaboration) { + return idToColor('', true) + } + + const inactive = + campCollaboration._meta?.loading || campCollaboration.status === 'inactive' + + if (campCollaboration?.color && !inactive) { + return campCollaboration.color + } + + if (typeof campCollaboration.user === 'function') { + return userColor( + campCollaboration.user(), + inactive || campCollaboration.user()._meta?.loading + ) + } else { + return idToColor(campCollaboration.id, inactive) + } +} + +export { contrastColor, defaultColor, userColor, campCollaborationColor, idToColor } diff --git a/frontend-vue3/src/common/helpers/dateFormat.js b/frontend-vue3/src/common/helpers/dateFormat.js new file mode 100644 index 0000000000..43e34d5c45 --- /dev/null +++ b/frontend-vue3/src/common/helpers/dateFormat.js @@ -0,0 +1,6 @@ +const HTML5_FMT = { + DATE: 'YYYY-MM-DD', + TIME: 'HH:mm', +} + +export { HTML5_FMT } diff --git a/frontend-vue3/src/common/helpers/dateHelperUTCFormatted.js b/frontend-vue3/src/common/helpers/dateHelperUTCFormatted.js new file mode 100644 index 0000000000..2022715fd8 --- /dev/null +++ b/frontend-vue3/src/common/helpers/dateHelperUTCFormatted.js @@ -0,0 +1,111 @@ +import dayjs from './dayjs.js' + +function dateShort(dateTimeString, tc) { + return dayjs.utc(dateTimeString).format(tc('global.datetime.dateShort')) +} + +function dateLong(dateTimeString, tc) { + return dayjs.utc(dateTimeString).format(tc('global.datetime.dateLong')) +} + +function hourShort(dateTimeString, tc) { + return dayjs.utc(dateTimeString).format(tc('global.datetime.hourShort')) +} + +function hourLong(dateTimeString, tc) { + return dayjs.utc(dateTimeString).format(tc('global.datetime.hourLong')) +} + +function timeDurationShort(start, end, tc) { + const startTime = dayjs.utc(start) + const endTime = dayjs.utc(end) + const duration = dayjs.duration(endTime.diff(startTime)) + + return tc( + duration.asDays() >= 1 + ? duration.hours() === 0 + ? duration.minutes() === 0 + ? 'global.datetime.duration.daysOnly' + : 'global.datetime.duration.daysAndMinutes' + : duration.minutes() === 0 + ? 'global.datetime.duration.daysAndHours' + : 'global.datetime.duration.daysAndHoursAndMinutes' + : duration.asMinutes() < 60 + ? 'global.datetime.duration.minutesOnly' + : duration.minutes() === 0 + ? 'global.datetime.duration.hoursOnly' + : 'global.datetime.duration.hoursAndMinutes', + 0, + { + days: Math.floor(duration.asDays()), + hours: duration.hours(), + minutes: duration.minutes(), + } + ) +} + +// short format of dateTime range +// doesn't show any date +function rangeTime(start, end, tc) { + return hourShort(start, tc) + ' - ' + hourShort(end, tc) +} + +// short format of dateTime range +// doesn't repeat end date if on the same day +function rangeShort(start, end, tc) { + let result = '' + + result += dateShort(start, tc) + result += ' ' + result += hourShort(start, tc) + + result += ' - ' + + if (dateShort(start, tc) !== dateShort(end, tc)) { + result += dateShort(end, tc) + result += ' ' + } + + result += hourShort(end, tc) + + return result +} + +// long end part of dateTime range format +// doesn't repeat end date if on the same day +function rangeLongEnd(start, end, tc) { + let result = '' + + result += hourLong(start, tc) + + result += ' - ' + + if (dateShort(start, tc) !== dateShort(end, tc)) { + result += dateShort(end, tc) + result += ' ' + } + + result += hourLong(end, tc) + + return result +} + +// format of date range +function dateRange(start, end, tc) { + if (dateLong(start, tc) === dateLong(end, tc)) { + return dateLong(start, tc) + } + return `${dateShort(start, tc)} - ${dateLong(end, tc)}` +} + +export { + dateShort, + dateLong, + timeDurationShort, + hourShort, + hourLong, + dateRange, + rangeTime, + rangeShort, + rangeLongEnd, +} diff --git a/frontend-vue3/src/common/helpers/dayResponsibles.js b/frontend-vue3/src/common/helpers/dayResponsibles.js new file mode 100644 index 0000000000..43fb3f0a47 --- /dev/null +++ b/frontend-vue3/src/common/helpers/dayResponsibles.js @@ -0,0 +1,26 @@ +import campCollaborationDisplayName from './campCollaborationDisplayName.js' + +/** + * Local filtering of dayResponsibles by day + * (avoids separate network request for each day) + */ +const filterDayResponsiblesByDay = (day) => { + if (!day) return [] + + return day + .period() + .dayResponsibles() + .items.filter((dayResponsible) => dayResponsible.day()._meta.self === day._meta.self) +} + +const dayResponsiblesCommaSeparated = (day, tc) => { + if (!day) return '' + + return filterDayResponsiblesByDay(day) + .map((dayResponsible) => + campCollaborationDisplayName(dayResponsible.campCollaboration(), tc) + ) + .join(', ') +} + +export { filterDayResponsiblesByDay, dayResponsiblesCommaSeparated } diff --git a/frontend-vue3/src/common/helpers/dayjs.js b/frontend-vue3/src/common/helpers/dayjs.js new file mode 100644 index 0000000000..4b2c81b075 --- /dev/null +++ b/frontend-vue3/src/common/helpers/dayjs.js @@ -0,0 +1,45 @@ +import dayjs from 'dayjs' + +import 'dayjs/locale/en-gb' +import 'dayjs/locale/de' +import 'dayjs/locale/de-ch' +import 'dayjs/locale/fr' +import 'dayjs/locale/fr-ch' +import 'dayjs/locale/it' +import 'dayjs/locale/it-ch' + +import utc from 'dayjs/plugin/utc' +import customParseFormat from 'dayjs/plugin/customParseFormat' +import objectSupport from 'dayjs/plugin/objectSupport' +import localizedFormat from 'dayjs/plugin/localizedFormat' +import isBetween from 'dayjs/plugin/isBetween' +import isSameOrBefore from 'dayjs/plugin/isSameOrBefore' +import isSameOrAfter from 'dayjs/plugin/isSameOrAfter' +import duration from 'dayjs/plugin/duration' +import formatDatePeriod from './dayjs/formatDatePeriod.js' +import timezone from 'dayjs/plugin/timezone' + +dayjs.extend(utc) +dayjs.extend(timezone) +dayjs.extend(customParseFormat) +dayjs.extend(objectSupport) +dayjs.extend(localizedFormat) +dayjs.extend(isBetween) +dayjs.extend(isSameOrBefore) +dayjs.extend(isSameOrAfter) +dayjs.extend(duration) +dayjs.extend(formatDatePeriod) + +export const dayjsLocaleMap = { + de: 'de-ch', + en: 'en-gb', + it: 'it-ch', + fr: 'fr-ch', +} + +/** + * @typedef {import('dayjs').Dayjs} Dayjs + * @property {Dayjs} utc + * @property {Dayjs} tz + */ +export default dayjs diff --git a/frontend-vue3/src/common/helpers/dayjs/__tests__/formatDatePeriod.spec.js b/frontend-vue3/src/common/helpers/dayjs/__tests__/formatDatePeriod.spec.js new file mode 100644 index 0000000000..41942d7057 --- /dev/null +++ b/frontend-vue3/src/common/helpers/dayjs/__tests__/formatDatePeriod.spec.js @@ -0,0 +1,19 @@ +import { describe, beforeEach, expect, it } from 'vitest' +import dayjs from '@/common/helpers/dayjs.js' + +describe('formatDatePeriod dayjs plugin', () => { + beforeEach(() => { + dayjs.locale('de') + }) + + it.each([ + ['', ''], + [null, ''], + [undefined, ''], + ['L', '03.04.2023 - 07.04.2023'], + ])('maps %p to %p', (input, expected) => { + const startDate = dayjs('2023-04-03 0:00') + const endDate = dayjs('2023-04-07 0:00') + expect(dayjs.formatDatePeriod(startDate, endDate, input, 'de')).toEqual(expected) + }) +}) diff --git a/frontend-vue3/src/common/helpers/dayjs/__tests__/parseTime.spec.js b/frontend-vue3/src/common/helpers/dayjs/__tests__/parseTime.spec.js new file mode 100644 index 0000000000..a12a3f0987 --- /dev/null +++ b/frontend-vue3/src/common/helpers/dayjs/__tests__/parseTime.spec.js @@ -0,0 +1,103 @@ +import { describe, beforeEach, expect, it } from 'vitest' +import { default as dayjs, dayjsLocaleMap } from '../../dayjs' +import parseTime from '../parseTime' +import { padStart, range } from 'lodash-es' +import { HTML5_FMT } from '../../dateFormat' + +/** + * Source: https://github.com/sbb-design-systems/sbb-angular/blob/24d4a804a55fa671cdf441a4556741ecfa2c638c/src/angular/time-input/time-input.spec.ts#L38 + */ +describe('parseTime', () => { + describe.each(Object.keys(dayjsLocaleMap))('`%s` locale', (locale) => { + beforeEach(() => { + dayjs.locale(locale) + }) + + const numbersFrom1to23 = range(1, 24).map((number) => [ + `${number}`, + `${padStart(number, 2, '0')}:00`, + ]) + + it.each([ + ['00:00', '00:00'], + ['12:00', '12:00'], + ['23:59', '23:59'], + ['01:01', '01:01'], + ['09:59', '09:59'], + ['20:00', '20:00'], + ['10:11', '10:11'], + ['010:11', '10:11', { en: '00:10' }], + ['00010:11', '10:11', { en: '00:01' }], + ['18:30', '18:30'], + ['001:11', '01:11', { en: '00:01' }], + ['000001:11', '01:11', { en: '00:00' }], + ['16:30', '16:30'], + ...numbersFrom1to23, + [0, '00:00'], + [-0, '00:00'], + ['123', '01:23'], + ['1234', '12:34'], + ['13567', '13:56'], + ['407', '04:07'], + ['3.56', '03:56'], + ['23,4', '23:04'], + ['1,30', '01:30'], + ['1:2', '01:02'], + ['1.2', '01:02'], + ['1,2', '01:02'], + ['1-2', '01:02'], + ['1;2', '01:02'], + ['01', '01:00'], + ['18', '18:00'], + ['23', '23:00'], + // not specified like this, but the current behaviour + ['010', '00:10'], + ['023', '00:23'], + ['145', '01:45'], + ['159', '01:59'], + ['200', '02:00'], + ['214', '02:14'], + ['313', '03:13'], + ['659', '06:59'], + ])( + `parses %s to %s (but special case for %s)`, + (input, output, specialCaseForLocale = {}) => { + const { isValid, parsedDateTime } = parseTime(input) + + const expectedOutput = + locale in specialCaseForLocale ? specialCaseForLocale[locale] : output + + expect(parsedDateTime.format('HH:mm')).toEqual(expectedOutput) + // the resulting dayjs object should not flow over to the next day + expect(parsedDateTime.format(HTML5_FMT.DATE)).toEqual( + dayjs().format(HTML5_FMT.DATE) + ) + expect(isValid).toEqual(true) + } + ) + + it.each([ + [null], + [undefined], + [''], + [' '], + ['\t'], + [[]], + [{}], + ['invalid time'], + ['a very long time that the cases are in multiple lines'], + ['24'], + ['99'], + ['2525'], + ['160'], + ['189'], + ['191'], + ['260'], + ['269'], + ['999'], + ])(`rejects %s`, (input) => { + const { isValid } = parseTime(input) + expect(isValid).toEqual(false) + }) + }) +}) diff --git a/frontend-vue3/src/common/helpers/dayjs/formatDatePeriod.js b/frontend-vue3/src/common/helpers/dayjs/formatDatePeriod.js new file mode 100644 index 0000000000..5ec56e4e96 --- /dev/null +++ b/frontend-vue3/src/common/helpers/dayjs/formatDatePeriod.js @@ -0,0 +1,14 @@ +export default (option, dayjsClass, dayjsFactory) => { + // Callable as follows: dayjs.formatDatePeriod(start, end, format, locale) + dayjsFactory.formatDatePeriod = (start, end, format, _ /* locale */) => { + if (!format) return '' + // TODO implement intelligent shortening, e.g. in German, you can write + // Fr 14. - So 16.04.2023 instead of Fr 14.04.2023 - So 16.04.2023. + // But careful, the same may or may not be possible in other locales. + // E.g. in English dates like 4/17/2023, it may not be possible to leave + // out the date. Proper research on this topic is needed. + const startFormatted = start.format(format) + const endFormatted = end.format(format) + return `${startFormatted} - ${endFormatted}` + } +} diff --git a/frontend-vue3/src/common/helpers/dayjs/parseTime.js b/frontend-vue3/src/common/helpers/dayjs/parseTime.js new file mode 100644 index 0000000000..3e8ef075c7 --- /dev/null +++ b/frontend-vue3/src/common/helpers/dayjs/parseTime.js @@ -0,0 +1,55 @@ +import dayjs from '../dayjs' +import { HTML5_FMT } from '../dateFormat' + +/** + * Source: https://github.com/sbb-design-systems/sbb-angular/blob/24d4a804a55fa671cdf441a4556741ecfa2c638c/src/angular/time-input/time-input.ts + */ +const REGEX_WITH_COLON = /([0-9]{1,2})[.:,\-;_hH]?([0-9]{1,2})?/ +const REGEX_WITHOUT_COLON = /([0-9]{1,2})([0-9]{2})/ + +function matchDigitGroups(input) { + if (input.match(/^\d{1,2}$/)) { + return [input, '0'] + } + const matchWithoutColon = input.match(REGEX_WITHOUT_COLON) + if (matchWithoutColon) { + return matchWithoutColon.slice(1) + } + const matchWithColon = input.match(REGEX_WITH_COLON) + if (matchWithColon) { + return matchWithColon.slice(1) + } + return [] +} + +export default (val) => { + const stringVal = `${val}` + let valIgnoringLeadingZero = stringVal.replace(/^0*?([\d]{1,2}):/, '$1:') + const parsedDateTime = dayjs.utc(valIgnoringLeadingZero, 'LT') + const formatted = parsedDateTime.format('LT') + if (!formatted.startsWith('0') && valIgnoringLeadingZero.match(/^0\d/)) { + valIgnoringLeadingZero = valIgnoringLeadingZero.slice(1) + } + const isValid = parsedDateTime.isValid() && formatted === valIgnoringLeadingZero + + if (isValid) { + return { parsedDateTime, isValid } + } + + const digitGroups = matchDigitGroups(stringVal) + if (!digitGroups || digitGroups.length < 2) { + return { parsedDateTime, isValid } + } + + const hours = digitGroups[0] + const minutes = digitGroups[1] + const fuzzyMatchedTime = dayjs.utc(`${hours}:${minutes}`, HTML5_FMT.TIME) + const fuzzyMatchedTimeToday = dayjs.utc( + fuzzyMatchedTime.format(HTML5_FMT.TIME), + HTML5_FMT.TIME + ) + if (hours > 23 || minutes > 59) { + return { parsedDateTime, isValid: false } + } + return { parsedDateTime: fuzzyMatchedTimeToday, isValid: fuzzyMatchedTime.isValid() } +} diff --git a/frontend-vue3/src/common/helpers/filterMatchScheduleEntry.js b/frontend-vue3/src/common/helpers/filterMatchScheduleEntry.js new file mode 100644 index 0000000000..dd3a4f6465 --- /dev/null +++ b/frontend-vue3/src/common/helpers/filterMatchScheduleEntry.js @@ -0,0 +1,50 @@ +/** + * Filtering of schedule entries by various criteria. + * Only the matcher function for matching a single scheduleEntry with + * a set of filter criteria is implemented here, because this can be + * used more flexibly in the application. + */ +const filterMatchScheduleEntry = (scheduleEntry, filter) => { + if (!filter) return true + return ( + // filter by period + (filter.period === null || + filter.period === undefined || + scheduleEntry.period()._meta.self === filter.period) && + // filter by days: OR filter + (filter.day === null || + filter.day === undefined || + filter.day.length === 0 || + filter.day.includes( + scheduleEntry.day()._meta.self + )) && + // filter by categories: OR filter + (filter.category === null || + filter.category === undefined || + filter.category.length === 0 || + filter.category.includes( + scheduleEntry.activity().category()._meta.self + )) && + // filter by responsibles: AND filter + (filter.responsible === null || + filter.responsible === undefined || + filter.responsible.length === 0 || + filter.responsible.every((responsible) => { + return scheduleEntry + .activity() + .activityResponsibles() + .items.map((responsible) => responsible.campCollaboration()._meta.self) + .includes(responsible) + }) || + (filter.responsible[0] === 'none' && + scheduleEntry.activity().activityResponsibles().items.length === 0)) && + (filter.progressLabel === null || + filter.progressLabel === undefined || + filter.progressLabel.length === 0 || + filter.progressLabel.includes( + scheduleEntry.activity().progressLabel?.()._meta.self ?? 'none' + )) + ) +} + +export { filterMatchScheduleEntry } diff --git a/frontend-vue3/src/common/helpers/initials.js b/frontend-vue3/src/common/helpers/initials.js new file mode 100644 index 0000000000..6f7c7c7782 --- /dev/null +++ b/frontend-vue3/src/common/helpers/initials.js @@ -0,0 +1,21 @@ +import runes from 'runes' + +/** + * Returns two characters to display for a display name + */ +export default function (displayName) { + if (!displayName) return '' + + let items = displayName.split(' ', 2) + if (items.length === 1) { + items = items.shift().split(/[,._-]/, 2) + } + if (items.length === 1) { + return runes.substr(displayName, 0, 2).toUpperCase() + } else { + return ( + runes.substr(items[0], 0, 1).toUpperCase() + + runes.substr(items[1], 0, 1).toUpperCase() + ) + } +} diff --git a/frontend-vue3/src/common/helpers/interpolation.js b/frontend-vue3/src/common/helpers/interpolation.js new file mode 100644 index 0000000000..5ea4f7bb09 --- /dev/null +++ b/frontend-vue3/src/common/helpers/interpolation.js @@ -0,0 +1,39 @@ +/** + * Curve fitting + * @param x + * @param y + * @param a + * @returns {number} + */ +export const lerp = (x, y, a) => x * (1 - a) + y * a + +/** + * Clamps value between min and max + * @param a + * @param min + * @param max + * @returns {number} + */ +export const clamp = (a, min = 0, max = 1) => Math.min(max, Math.max(min, a)) + +/** + * Inverse curve fitting function + * @param x + * @param y + * @param a + * @returns {number} + */ +export const invlerp = (x, y, a) => clamp((a - x) / (y - x)) + +/** + * Maps input to output range + * @param inputStart + * @param inputEnd + * @param outputStart + * @param outputEnd + * @param input + * @returns number + */ +export function range(inputStart, inputEnd, outputStart, outputEnd, input) { + return lerp(outputStart, outputEnd, invlerp(inputStart, inputEnd, input)) +} diff --git a/frontend-vue3/src/common/helpers/materialListsSorted.js b/frontend-vue3/src/common/helpers/materialListsSorted.js new file mode 100644 index 0000000000..ee9fd57e11 --- /dev/null +++ b/frontend-vue3/src/common/helpers/materialListsSorted.js @@ -0,0 +1,10 @@ +import sortBy from 'lodash-es/sortBy.js' + +export default function (materialLists) { + return sortBy( + materialLists, + (list) => + (list.campCollaboration == null ? 'NonUserList_' : 'UserList_') + + list.name.toLowerCase() + ) +} diff --git a/frontend-vue3/src/common/helpers/picasso.js b/frontend-vue3/src/common/helpers/picasso.js new file mode 100644 index 0000000000..2931e458cb --- /dev/null +++ b/frontend-vue3/src/common/helpers/picasso.js @@ -0,0 +1,356 @@ +import minBy from 'lodash-es/minBy.js' +import maxBy from 'lodash-es/maxBy.js' +import sortBy from 'lodash-es/sortBy.js' +import keyBy from 'lodash-es/keyBy.js' +import dayjs from './dayjs.js' +import { arrange } from './scheduleEntryLayout.js' + +/** + * @typedef {import('./dayjs.js').dayjs} Dayjs + */ + +/** + * Splits a set of days into pages, such that all pages contain a similar number of days. + * + * @param days {array} set of days to split into pages + * @param maxDaysPerPage {number} maximum number of days to put on one page + * @returns {array} list of pages, each containing a list of the days on the page + */ +export function splitDaysIntoPages(days, maxDaysPerPage) { + if (!maxDaysPerPage) return [] + const numberOfDays = days.length + const numberOfPages = Math.ceil(numberOfDays / maxDaysPerPage) + const daysPerPage = Math.floor(numberOfDays / numberOfPages) + const numLargerPages = numberOfDays % numberOfPages + let nextUnassignedDayIndex = 0 + + return [...Array(numberOfPages).keys()].map((i) => { + const isLargerPage = i < numLargerPages + const numDaysOnCurrentPage = daysPerPage + (isLargerPage ? 1 : 0) + const firstDayIndex = nextUnassignedDayIndex + nextUnassignedDayIndex = firstDayIndex + numDaysOnCurrentPage + + return days.filter((day, index) => { + return index >= firstDayIndex && index < nextUnassignedDayIndex + }) + }) +} + +/** + * Finds the largest consecutive time period during the night, in which no schedule entries start or end. + * This time period can be treated as the common "bedtime" in the camp, during which + * the people in the camp are not active. This time period can be safely hidden on the picasso. + * + * @param scheduleEntries set of schedule entries to consider + * @param dayjs a dayjs helper object, needed to do time calculations + * @param firstDayStart dayjs object describing the start of the first day displayed. Is used to make sure that schedule + * entries starting on this day may not be assigned to the preceding day, because that would mean they would become + * invisible on the picasso + * @param lastDayEnd dayjs object describing the end of the last day displayed. Is used to make sure that schedule + * entries ending on this day may not be assigned to the following day, because that would mean they would become + * invisible on the picasso + * @param timeBucketSize size of the time buckets into which the schedule entry boundaries are quantized, in hours + * @returns {{bedtime: number, getUpTime: number}} + */ +export function calculateBedtime( + scheduleEntries, + dayjs, + firstDayStart, + lastDayEnd, + timeBucketSize = 1 +) { + const scheduleEntryBounds = getScheduleEntryBounds( + scheduleEntries, + dayjs, + firstDayStart.unix(), + lastDayEnd.unix() + ) + if (!scheduleEntryBounds.length) return { bedtime: 24, getUpTime: 0 } + + const gaps = scheduleEntryBounds.reduce((gaps, current, index) => { + if (index === 0) return gaps + const previous = scheduleEntryBounds[index - 1] + const duration = current.hours - previous.hours + if (duration === 0) return gaps + gaps.push({ + start: previous.hours, + end: current.hours, + duration, + }) + return gaps + }, []) + + // The first and last day on our picasso impose some constraints on the range of bedtimes we can choose. + const { earliestBedtime, latestGetUpTime } = bedtimeConstraintsFromFirstAndLastDay( + scheduleEntryBounds, + firstDayStart, + lastDayEnd, + dayjs, + timeBucketSize + ) + + const largestBedtimeGap = maxBy( + gaps.filter((gap) => { + // Prevent bedtimes which would hide some schedule entry on the first or last day + if (gap.start < earliestBedtime || gap.end > latestGetUpTime) return false + // Prevent bedtimes which are not during the night + if (gap.start > 30 || gap.end < 24) return false + return true + }), + (gap) => gap.duration + ) + + return { + bedtime: optimalBedtime(largestBedtimeGap, scheduleEntryBounds, timeBucketSize), + getUpTime: + optimalGetUpTime(largestBedtimeGap, scheduleEntryBounds, timeBucketSize) - 24, + } +} + +function getScheduleEntryBounds( + scheduleEntries, + dayjs, + firstDayStartTimestamp, + lastDayEndTimestamp +) { + const bounds = scheduleEntries + .flatMap((scheduleEntry) => { + const start = dayjs.utc(scheduleEntry.start) + const end = dayjs.utc(scheduleEntry.end) + const startHours = start.hour() + start.minute() / 60 + const endHours = end.hour() + end.minute() / 60 + const duration = end.diff(start, 'minute') / 60 + return [ + { hours: startHours, time: start, type: 'start', duration }, + { hours: endHours, time: end, type: 'end', duration }, + ] + }) + .filter( + (bound) => + bound.time.unix() >= firstDayStartTimestamp && + bound.time.unix() <= lastDayEndTimestamp + ) + // Add a copy of all bounds 24 hours later, to simplify working with the circular characteristics of daytimes + const shifted = bounds.map((bound) => ({ + ...bound, + hours: bound.hours + 24, + time: bound.time.add(24, 'hours'), + })) + return sortBy([...bounds, ...shifted], (bound) => bound.hours) +} + +function bedtimeConstraintsFromFirstAndLastDay( + scheduleEntryBounds, + firstDayStart, + lastDayEnd +) { + // The start of the very first schedule entry on the first day (if any) must always be displayed on the first day. + // We must make sure that our calculated "get up time" lies before this, so we do not accidentally hide a + // schedule entry. + const latestGetUpTime = earliestScheduleEntryBoundOnFirstDay( + scheduleEntryBounds, + firstDayStart + ) + + // Similarly, the end of the very last schedule entry end must always be displayed on the last day. + // So we must make sure that our calculated "go to bed time" lies after this. + const earliestBedtime = latestScheduleEntryBoundOnLastDay( + scheduleEntryBounds, + lastDayEnd.subtract(1, 'second') + ) + + return { + earliestBedtime: earliestBedtime === undefined ? 0 : earliestBedtime, + latestGetUpTime: latestGetUpTime === undefined ? 48 : latestGetUpTime + 24, + } +} + +function earliestScheduleEntryBoundOnFirstDay(scheduleEntryBounds, firstDayStart) { + const earliestBound = minBy(scheduleEntryBounds, (bound) => bound.time.unix()) + if ( + earliestBound.hours < 24 && + earliestBound.time.diff(firstDayStart, 'minute') / 60 < 24 + ) { + return earliestBound.hours + } + return undefined +} + +function latestScheduleEntryBoundOnLastDay(scheduleEntryBounds, lastDayEnd) { + const latestBound = maxBy(scheduleEntryBounds, (bound) => bound.time.unix()) + if (latestBound.hours < 24 && lastDayEnd.diff(latestBound.time, 'minute') / 60 < 24) { + return latestBound.hours + } + return undefined +} + +function optimalBedtime(gap, scheduleEntryBounds, timeBucketSize) { + const bedtime = Math.ceil(gap.start / timeBucketSize) * timeBucketSize + if ( + scheduleEntryBounds.some( + (bound) => + bound.type === 'start' && + bound.hours <= bedtime && + bound.hours > bedtime - timeBucketSize / 2 && + bound.duration > bedtime - bound.hours + ) + ) { + // There exists a schedule entry which starts at the bedtime or less than half a time bucket before it. + // Move the bedtime later, so that this schedule entry is still clearly visible. + return bedtime + timeBucketSize + } + // There is already a large enough margin, or there are no schedule entries starting around the bedtime. + return bedtime +} + +function optimalGetUpTime(gap, scheduleEntryBounds, timeBucketSize) { + const getUpTime = Math.floor(gap.end / timeBucketSize) * timeBucketSize + if ( + scheduleEntryBounds.some( + (bound) => + bound.type === 'end' && + bound.hours >= getUpTime && + bound.hours < getUpTime + timeBucketSize / 2 && + bound.duration > bound.hours - getUpTime + ) + ) { + // There exists a schedule entry which ends at the getUpTime or less than half a time bucket after it. + // Move the getUpTime later, so that this schedule entry is still clearly visible. + return getUpTime - timeBucketSize + } + // There is already a large enough margin, or there are no schedule entries ending around the getUpTime. + return getUpTime +} + +/** + * Generates an array of time row descriptions, used for labeling the vertical axis of the picasso. + * Format of each array element: [hour, weight] where weight determines how tall the time row is rendered. + * + * @typedef {*[[hour: number, weight: number]]} TimeWeights + * @returns TimeWeights + */ +export function times(getUpTime, bedTime, timeStep) { + const times = [[getUpTime - timeStep / 2, 0.5]] + for (let i = 0; getUpTime + i * timeStep < bedTime; i++) { + // TODO The weight could also be generated depending on the schedule entries present in the camp: + // e.g. give less weight to hours that contain no schedule entries. + const weight = 1 + times.push([getUpTime + i * timeStep, weight]) + } + times.push([bedTime, 0.5]) + // this last hour is only needed for defining the length of the day. The weight should be 0. + times.push([bedTime + timeStep / 2, 0]) + + return times +} + +/** + * Returns the total sum of weights in the times array (with times format as generated by times() function) + */ +export function timesWeightsSum(times) { + return times.reduce((sum, [_, weight]) => sum + weight, 0) +} + +/** + * Calculates the relative positioning in percentage of "milliseconds" within the times array + */ +export function positionPercentage(milliseconds, times) { + const hours = milliseconds / (3600.0 * 1000) + let matchingTimeIndex = times.findIndex(([time, _]) => time > hours) - 1 + matchingTimeIndex = Math.min( + Math.max(matchingTimeIndex === -2 ? times.length : matchingTimeIndex, 0), + times.length - 1 + ) + const remainder = + times[matchingTimeIndex][1] !== 0 + ? (hours - times[matchingTimeIndex][0]) / times[matchingTimeIndex][1] + : 0 // avoid division by zero, in case the schedule entry ends on a later day + const positionWeightsSum = + timesWeightsSum(times.slice(0, matchingTimeIndex)) + + remainder * times[Math.min(matchingTimeIndex, times.length)][1] + const totalWeightsSum = timesWeightsSum(times) + if (totalWeightsSum === 0) { + return 0 + } + const result = (positionWeightsSum * 100.0) / totalWeightsSum + return Math.max(0, Math.min(100, result)) +} + +export function filterScheduleEntriesByDay(scheduleEntries, day, times) { + return scheduleEntries.filter((scheduleEntry) => { + return ( + dayjs.utc(scheduleEntry.start).isBefore(dayEnd(day, times)) && + dayjs.utc(scheduleEntry.end).isAfter(dayStart(day, times)) + ) + }) +} + +/** + * @param day a day object of the api + * @param offset {number} the offset hour of the day + * @returns {Dayjs} + */ +function dayOffset(day, offset) { + return dayjs.utc(day.start).add(offset, 'hour') +} + +/** + * Calculates the day start dayjs object according to times + * + * @param day a day object of the api + * @param times {TimeWeights} + * @returns {Dayjs} + */ +export function dayStart(day, times) { + const dayStart = times[0][0] + return dayOffset(day, dayStart) +} + +/** + * Calculates the day end dayjs object according to times + * + * @param day a day object of the api + * @param times {TimeWeights} + * @returns {Dayjs} + */ +export function dayEnd(day, times) { + const dayEnd = times[times.length - 1][0] + return dayOffset(day, dayEnd) +} + +function leftAndWith(scheduleEntries) { + return keyBy(arrange(scheduleEntries), 'id') +} + +/** + * Calculates the positions styles (in percentages) for all scheduleEntries + */ +export function positionStyles(scheduleEntries, day, times) { + const leftAndWidth = leftAndWith(scheduleEntries) + + return keyBy( + scheduleEntries.map((scheduleEntry) => { + const left = leftAndWidth[scheduleEntry.id]?.left || 0 + const width = leftAndWidth[scheduleEntry.id]?.width || 0 + const top = positionPercentage( + dayjs.utc(scheduleEntry.start).valueOf() - dayjs.utc(day.start).valueOf(), + times + ) + const bottom = + 100 - + positionPercentage( + dayjs.utc(scheduleEntry.end).valueOf() - dayjs.utc(day.start).valueOf(), + times + ) + return { + id: scheduleEntry.id, + top: top + '%', + bottom: bottom + '%', + left: left + '%', + right: 100 - width - left + '%', + percentageHeight: 100 - bottom - top, + } + }), + 'id' + ) +} diff --git a/frontend-vue3/src/common/helpers/scheduleEntryLayout.js b/frontend-vue3/src/common/helpers/scheduleEntryLayout.js new file mode 100644 index 0000000000..9e8cf6fc32 --- /dev/null +++ b/frontend-vue3/src/common/helpers/scheduleEntryLayout.js @@ -0,0 +1,119 @@ +// This file contains an algorithm for automatically arranging schedule entries in terms +// of horizontal placement, such that they do not overlap with each other. +// Taken and adapted from Vuetify 2's v-calendar event overlap logic: +// https://github.com/vuetifyjs/vuetify/blob/v2-stable/packages/vuetify/src/components/VCalendar/modes/column.ts + +import dayjs from './dayjs.js' + +const FULL_WIDTH = 100 + +function getVisuals(events) { + const visuals = events.map((event) => ({ + id: event.id, + columnCount: 0, + column: 0, + left: 0, + width: 100, + startTimestamp: dayjs.utc(event.start).unix(), + endTimestamp: dayjs.utc(event.end).unix(), + })) + + visuals.sort((a, b) => { + return a.startTimestamp - b.startTimestamp || b.endTimestamp - a.endTimestamp + }) + + return visuals +} + +function hasOverlap(s0, e0, s1, e1) { + return !(s0 >= e1 || e0 <= s1) +} + +function setColumnCount(groups) { + groups.forEach((group) => { + group.visuals.forEach((groupVisual) => { + groupVisual.columnCount = groups.length + groupVisual.left = (groupVisual.column * FULL_WIDTH) / groupVisual.columnCount + groupVisual.width = FULL_WIDTH / groupVisual.columnCount + }) + }) +} + +function getOpenGroup(groups, eventStart, eventEnd) { + for (let i = 0; i < groups.length; i++) { + const group = groups[i] + let intersected = false + + if (hasOverlap(eventStart, eventEnd, group.start, group.end)) { + for (let k = 0; k < group.visuals.length; k++) { + const groupVisual = group.visuals[k] + const groupStart = groupVisual.startTimestamp + const groupEnd = groupVisual.endTimestamp + + if (hasOverlap(eventStart, eventEnd, groupStart, groupEnd)) { + intersected = true + break + } + } + } + + if (!intersected) { + return i + } + } + + return -1 +} + +/** + * Calculates left and width for each schedule entry, such that no two schedule entries overlap visually. + * For this, schedule entries are sorted by ascending start ascendingly (and descending end time for ties), + * and any sets of overlapping schedule entries are divided into groups. The groups can then be displayed + * besides each other, because the groups are chosen such that no two schedule entries in the same group overlap. + * @param scheduleEntries list of schedule entries to arrange + * @returns list of objects with information about the spatial arrangement + */ +export function arrange(scheduleEntries) { + let groups = [] + let min = -1 + let max = -1 + const visuals = getVisuals(scheduleEntries) + + visuals.forEach((visual) => { + const eventStart = visual.startTimestamp + const eventEnd = visual.endTimestamp + + if (groups.length > 0 && !hasOverlap(eventStart, eventEnd, min, max)) { + setColumnCount(groups) + groups = [] + min = max = -1 + } + + let targetGroup = getOpenGroup(groups, eventStart, eventEnd) + + if (targetGroup === -1) { + targetGroup = groups.length + + groups.push({ start: eventStart, end: eventEnd, visuals: [] }) + } + + const target = groups[targetGroup] + target.visuals.push(visual) + target.start = Math.min(target.start, eventStart) + target.end = Math.max(target.end, eventEnd) + + visual.column = targetGroup + + if (min === -1) { + min = eventStart + max = eventEnd + } else { + min = Math.min(min, eventStart) + max = Math.max(max, eventEnd) + } + }) + + setColumnCount(groups) + + return visuals +} diff --git a/frontend-vue3/src/common/helpers/userDisplayName.js b/frontend-vue3/src/common/helpers/userDisplayName.js new file mode 100644 index 0000000000..7f44be53ce --- /dev/null +++ b/frontend-vue3/src/common/helpers/userDisplayName.js @@ -0,0 +1,6 @@ +/** + * Returns a display name for a user + */ +export default function (user) { + return user.displayName || '' +} diff --git a/frontend-vue3/src/common/helpers/userInitials.js b/frontend-vue3/src/common/helpers/userInitials.js new file mode 100644 index 0000000000..cdb6d9e225 --- /dev/null +++ b/frontend-vue3/src/common/helpers/userInitials.js @@ -0,0 +1,15 @@ +import userDisplayName from './userDisplayName.js' +import initials from './initials.js' + +/** + * Returns two characters to display for a user + */ +export default function (user) { + if (!user) { + return '' + } + if (user.abbreviation) { + return user.abbreviation + } + return initials(userDisplayName(user)) +} diff --git a/frontend-vue3/src/common/helpers/userLegalName.js b/frontend-vue3/src/common/helpers/userLegalName.js new file mode 100644 index 0000000000..23067fd10e --- /dev/null +++ b/frontend-vue3/src/common/helpers/userLegalName.js @@ -0,0 +1,7 @@ +/** + * Returns the legal name for a user + */ +export default function (user) { + if (!user || !user.profile() || user.profile()._meta.loading) return '' + return user.profile().legalName || '' +} diff --git a/frontend-vue3/src/common/locales/de-CH-scout.json b/frontend-vue3/src/common/locales/de-CH-scout.json new file mode 100644 index 0000000000..2dcdd1dbae --- /dev/null +++ b/frontend-vue3/src/common/locales/de-CH-scout.json @@ -0,0 +1,12 @@ +{ + "entity": { + "camp": { + "fields": { + "courseKind": "Kursbezeichnung (bei J+S Kurs: J+S Bezeichnung)", + "courseNumber": "Kursnummer", + "printYSLogoOnPicasso": "J+S-Logo auf Grobprogramm drucken (bei J+S-Kursen aktivieren)", + "trainingAdvisorName": "Bürgerlicher Name von LKB" + } + } + } +} \ No newline at end of file diff --git a/frontend-vue3/src/common/locales/de.json b/frontend-vue3/src/common/locales/de.json new file mode 100644 index 0000000000..0b137def97 --- /dev/null +++ b/frontend-vue3/src/common/locales/de.json @@ -0,0 +1,298 @@ +{ + "components": { + "summary": { + "summaryDay": { + "noContent": "Die Blöcke an diesem Tag enthalten keine {contentType} Inhalte." + } + } + }, + "contentNode": { + "checklist": { + "info": "Wähle die relevanten Checklisten-Einträge aus, die von dieser Aktivität abgedeckt werden (Kursziele, etc.).", + "name": "Checklisten" + }, + "columnLayout": { + "entity": { + "column": { + "name": "Spalte|Spalte {name}" + } + }, + "name": "Spaltenlayout" + }, + "laThematicArea": { + "entity": { + "option": { + "campsiteAndSurroundings": { + "description": "Einrichten von Lagerplatz/Umgebung, Abbau, Erstellen von Spielplatzeinrichtungen und Sportgeräten.", + "name": "Lagerplatz/Umgebung" + }, + "natureAndEnvironment": { + "description": "Tier- und Pflanzenwelt, Umweltschutz im Lager, Wetter- und Sternkunde, Übermittlungstechniken, Feuer machen.", + "name": "Natur und Umwelt" + }, + "outdoorTechnique": { + "description": "Wanderplanung, Kartenlesen (z.B. NORDA), Krokieren, Hilfsmittel (z.B. Kompass, GPS, Höhenmeter usw.), orientieren im Gelände.", + "name": "Outdoortechniken" + }, + "pioneeringTechnique": { + "description": "Biwakbau, Iglubau, Material- und Ausrüstungskunde, Materialpflege, Erstellen und Abbau von Pionierbauten, Seil- und Knotenkunde, Seilbahnen, Seilbrücken, Abseilen.", + "name": "Pioniertechnik" + }, + "preventionAndIntegration": { + "description": "Aktivitäten, welche der Prävention und der Integration dienen und die Kompetenzen der Teilnehmenden in diesem Bereich fördern.", + "name": "Prävention und Integration" + }, + "security": { + "description": "Sicherheit bei Aktivitäten im Lager, Unfallorganisation und Alarmierung, 1. Hilfe, Sicherheitsüberlegungen.", + "name": "Sicherheit" + } + } + }, + "info": "Eine J+S Lageraktivität muss mindestens eines der aufgeführten Themen behandeln.{br}Erfasse, welche Themen in diesem Block behandelt werden.", + "name": "LA Themenbereich" + }, + "learningObjectives": { + "info": "Formuliere die Kompetenzen, über welche die Teilnehmenden nach diesem Block verfügen, in der Form von Lernzielen.", + "name": "Blockziele" + }, + "learningTopics": { + "info": "Liste die Ausbildungs-Themen auf, mit welchen die Teilnehmenden sich in diesem Block auseinandersetzen werden.", + "name": "Blockinhalte" + }, + "material": { + "info": "Hier kannst du den Material-Bedarf für diesen Block erfassen.{br}Die Materiallisten kannst du im Menu 'Admin' verwalten.{br}Eine Zusammenstellung für den Einkauf findest du im Menu 'Material'.", + "name": "Material" + }, + "notes": { + "info": "Hier kannst du beliebige Notizen erfassen.{br}z.B. Ideen, Todo's, offene Fragen, Kontakte, ÖV-Verbindungen, usw.", + "name": "Notizen" + }, + "responsiveLayout": { + "mainContent": "Hauptinhalt", + "name": "Standardlayout", + "printAboveMainContent": "Über dem Hauptinhalt drucken", + "printBelowMainContent": "Unter dem Hauptinhalt drucken" + }, + "safetyConsiderations": { + "info": "Einige Blöcke erfordern, dass ihr euch Gedanken zu den Risiken macht. Hier könnt ihr diese Gedanken erfassen.{br}Haltet fest, welche Risiken ihr erkannt habt - und wie ihr diesen begegnen könnt.", + "name": "Sicherheitsüberlegungen" + }, + "storyboard": { + "entity": { + "section": { + "fields": { + "column1": "Zeit", + "column2Html": "Programm", + "column3": "Verantwortlich" + }, + "name": "Programmpunkt | Programmpunkte" + } + }, + "info": "Hier kannst du den Inhalt von diesem Block planen.{br}In der linken Spalte [Zeit] kannst du die Dauer der einzelnen Elemente erfassen.{br}In der rechten Spalte [Verantwortlich] kannst du Personen zuteilen.", + "name": "Programmabschnitt" + }, + "storycontext": { + "info": "Beschreibe, wie sich dieser Block in die Geschichte vom Lager einbettet.{br}Eine Zusammenstellung aller Geschichts-Elemente findest du im Menu 'Geschichte'.{br}Ihr könnt auch erst im Menu 'Geschichte' zuerst eine durchgängige Geschichte erarbeiten - so dass man den Block-Inhalt perfekt in die Geschichte einbetten kann.", + "name": "Geschichte" + } + }, + "entity": { + "activity": { + "fields": { + "category": "Block-Kategorie", + "location": "Ort", + "progressLabel": "Status", + "responsible": "Verantwortlich", + "title": "Titel" + }, + "name": "Aktivität | Aktivitäten", + "new": "Neue Aktivität" + }, + "activityProgressLabel": { + "fields": { + "title": "Titel" + } + }, + "camp": { + "collaborators": { + "guest": "Gast", + "invite": "Einladen", + "manager": "Administration", + "member": "Mitglied" + }, + "fields": { + "addressCity": "Ort", + "addressName": "Name", + "addressStreet": "Strasse", + "addressZipcode": "PLZ", + "coachName": "Name des J+S-Coachs", + "courseKind": "Kursbezeichnung (bei J+S Kurs: J+S Bezeichnung)", + "courseNumber": "Kursnummer", + "kind": "Lagerart (Haus-, Zelt-, Unterwegslager, Sommer-, Herbstlager)", + "motto": "Motto / Thema", + "organizer": "Organisator", + "printYSLogoOnPicasso": "J+S-Logo auf Grobprogramm drucken (bei J+S-Kursen aktivieren)", + "shortTitle": "Kurzer Lagertitel", + "title": "Lagertitel", + "trainingAdvisorName": "Bürgerlicher Name der Betreuungsperson" + }, + "name": "Lager", + "prototype": "Lagervorlage" + }, + "campCollaboration": { + "fields": { + "abbreviation": "Abkürzung", + "color": "Farbe", + "inviteEmail": "E-Mail", + "role": "Rolle", + "status": "Status" + }, + "status": { + "established": "Aktiv", + "inactive": "Inaktiv", + "invited": "Eingeladen" + } + }, + "category": { + "fields": { + "color": "Farbe", + "name": "Name", + "numberingStyle": "Nummerierung", + "short": "Kürzel" + }, + "name": "Block-Kategorien", + "numberingStyles": { + "-": "keine Nummerierung", + "1": "1, 2, 3 - Zahlen", + "A": "A, B, C - grosse Buchstaben", + "I": "I, II, III - grosse römische Zahlen", + "a": "a, b, c - kleine Buchstaben", + "i": "i, ii, iii - kleine römische Zahlen" + } + }, + "checklist": { + "fields": { + "copyChecklistSource": "Vorlage", + "name": "Name" + }, + "name": "Checkliste | Checklisten" + }, + "checklistItem": { + "fields": { + "text": "Text" + }, + "name": "Checklisten-Eintrag" + }, + "contentType": { + "name": "Inhalttyp | Inhalttypen" + }, + "day": { + "fields": { + "dayResponsibles": "Tagesverantwortliche" + }, + "name": "Tag | Tage" + }, + "materialItem": { + "fields": { + "article": "Artikel", + "list": "Materialliste", + "quantity": "Menge", + "reference": "Aktivität / Lagerabschnitt", + "unit": "Einheit" + } + }, + "materialList": { + "fields": { + "name": "Name" + }, + "name": "Materialliste" + }, + "period": { + "defaultDescription": "Hauptlager", + "fields": { + "description": "Beschreibung", + "end": "Bis", + "start": "Von" + }, + "name": "Lagerabschnitt | Lagerabschnitte" + }, + "profile": { + "fields": { + "abbreviation": "Abkürzung", + "color": "Farbe", + "email": "E-Mail-Adresse", + "firstname": "Vorname", + "language": "Sprache", + "nickname": "Spitzname", + "password": "Passwort", + "surname": "Nachname" + }, + "name": "Profil" + }, + "scheduleEntry": { + "fields": { + "duration": "Dauer", + "endDate": "Enddatum", + "endDatetime": "Endzeit", + "nr": "Nr.", + "startDate": "Startdatum", + "startDatetime": "Startzeit", + "time": "Zeitpunkt" + }, + "name": "Zeitplaneintrag" + } + }, + "global": { + "datetime": { + "dateLong": "dd L", + "dateShort": "dd D.M.", + "dateTimeLong": "dd L LT", + "duration": { + "daysAndHours": "{days} d {hours} h", + "daysAndHoursAndMinutes": "{days} d {hours} h {minutes} min", + "daysAndMinutes": "{days} d {minutes} min", + "hoursAndMinutes": "{hours} h {minutes} min", + "daysOnly": "{days} d", + "hoursOnly": "{hours} h", + "minutesOnly": "{minutes} min" + }, + "hourLong": "LT", + "hourShort": "H:mm" + }, + "shortScheduleEntryDescription": "Tag {dayNumber} {startTime}" + }, + "print": { + "activityList": { + "title": "Aktivitätsliste" + }, + "config": { + "periods": "Lagerabschnitt(e)" + }, + "cover": { + "title": "Titelseite" + }, + "picasso": { + "picassoFooter": { + "coach": "Coach: {coach}", + "courseNumber": "Kursnummer: {courseNumber}", + "leaders": "Leitung: {leaders}", + "trainingAdvisor": "LKB: {trainingAdvisor}" + }, + "title": "Grobprogramm {period}" + }, + "program": { + "title": "Detailprogramm" + }, + "summary": { + "safetyConsiderations": { + "title": "Sicherheitsüberlegungen" + }, + "storycontext": { + "title": "Geschichte" + } + }, + "toc": { + "title": "Inhaltsverzeichnis" + } + } +} diff --git a/frontend-vue3/src/common/locales/en-CH-scout.json b/frontend-vue3/src/common/locales/en-CH-scout.json new file mode 100644 index 0000000000..9e26dfeeb6 --- /dev/null +++ b/frontend-vue3/src/common/locales/en-CH-scout.json @@ -0,0 +1 @@ +{} \ No newline at end of file diff --git a/frontend-vue3/src/common/locales/en.json b/frontend-vue3/src/common/locales/en.json new file mode 100644 index 0000000000..e3d5709ef2 --- /dev/null +++ b/frontend-vue3/src/common/locales/en.json @@ -0,0 +1,298 @@ +{ + "components": { + "summary": { + "summaryDay": { + "noContent": "The activities on this day do not contain any {contentType} content." + } + } + }, + "contentNode": { + "checklist": { + "info": "Select the relevant checklist items, which are covered by this activity (course objectives, etc.).", + "name": "Checklists" + }, + "columnLayout": { + "entity": { + "column": { + "name": "Column|Column {name}" + } + }, + "name": "Column layout" + }, + "laThematicArea": { + "entity": { + "option": { + "campsiteAndSurroundings": { + "description": "Construction of a camp / surroundings, dismantling / setting up of a playground and fabrication of sports equipment.", + "name": "Campsite and Surroundings" + }, + "natureAndEnvironment": { + "description": "Fauna and flora, environmental protection in the camp, meteorology and astronomy, transmission techniques, preparation and making a fire.", + "name": "Nature and Environment" + }, + "outdoorTechnique": { + "description": "Planning a hike, map reading (e.g. NORDA checklist), croquis, use of instruments (e.g. compass, GPS receiver, altimeter, etc.), orientation in the terrain.", + "name": "Outdoor Technique" + }, + "pioneeringTechnique": { + "description": "Setting up a bivouac, building an igloo, knowledge of materials and equipment, equipment maintenance, construction and dismantling of pioneer structures, ropes and knots, zip lines, rope bridges, abseiling.", + "name": "Pioneering Technique" + }, + "preventionAndIntegration": { + "description": "Activities promoting prevention and integration or developing participants' skills in this area.", + "name": "Prevention and Integration" + }, + "security": { + "description": "Safety during camp activities, measures to be taken in case of accident and alert, first aid, safety considerations.", + "name": "Security" + } + } + }, + "info": "A Y+S camp activity must address at least one of the listed topics.{br}Select what topics are covered in this block.", + "name": "LA thematic area" + }, + "learningObjectives": { + "info": "Formulate as goals the competences which the participants will have after this activity.", + "name": "Learning objectives" + }, + "learningTopics": { + "info": "List the topics about which the participants will learn something in this activity.", + "name": "Learning topics" + }, + "material": { + "info": "Here you can enter the material requirements for this block.{br}You can manage the material lists in the menu 'Admin'.{br}You can find a summary for the purchase in the menu 'Material'.", + "name": "Material" + }, + "notes": { + "info": "Here you can enter any notes.{br}e.g. ideas, todo's, open questions, contacts, public transport connections, etc.", + "name": "Notes" + }, + "responsiveLayout": { + "mainContent": "Main content", + "name": "Default layout", + "printAboveMainContent": "Print above main content", + "printBelowMainContent": "Print below main content" + }, + "safetyConsiderations": { + "info": "Some blocks require to think about the risks. Here you can record these thoughts.{br}Record what risks you have identified - and how you can address them.", + "name": "Safety considerations" + }, + "storyboard": { + "entity": { + "section": { + "fields": { + "column1": "Time", + "column2Html": "Program", + "column3": "Responsible" + }, + "name": "Storyboard | Storyboards" + } + }, + "info": "Here you can plan the content of this block.{br}In the left column [Time] you can record the duration of the individual elements.{br}In the right column [Responsible] you can assign persons.", + "name": "Storyboard" + }, + "storycontext": { + "info": "Describe how this block fits into the story of the camp.{br}You can find a summary of all story elements in the menu 'Story'.{br}You can also first work out a continuous story in the 'Story' menu - so that you can perfectly embed the block content into the story.", + "name": "Story" + } + }, + "entity": { + "activity": { + "fields": { + "category": "Category", + "location": "Location", + "progressLabel": "State", + "responsible": "Responsible", + "title": "Title" + }, + "name": "Activity | Activities", + "new": "New activity" + }, + "activityProgressLabel": { + "fields": { + "title": "Title" + } + }, + "camp": { + "collaborators": { + "guest": "Guest", + "invite": "Invite", + "manager": "Administration", + "member": "Member" + }, + "fields": { + "addressCity": "City", + "addressName": "Name", + "addressStreet": "Street", + "addressZipcode": "Zipcode", + "coachName": "Name of Y+S coach", + "courseKind": "Course kind (for Y+S courses: Y+S course term)", + "courseNumber": "Course number", + "kind": "Camp kind (house, tent, traveling, summer, autumn)", + "motto": "Motto / Theme", + "organizer": "Organizer", + "printYSLogoOnPicasso": "Print the Y+S logo on the picasso (required for Y+S courses)", + "shortTitle": "Short camp title", + "title": "Camp title", + "trainingAdvisorName": "Name of training advisor" + }, + "name": "Camp | Camps", + "prototype": "Camp prototype" + }, + "campCollaboration": { + "fields": { + "abbreviation": "Abbreviation", + "color": "Color", + "inviteEmail": "Email", + "role": "Role", + "status": "Status" + }, + "status": { + "established": "Active", + "inactive": "Inactive", + "invited": "Invited" + } + }, + "category": { + "fields": { + "color": "Color", + "name": "Name", + "numberingStyle": "Numbering style", + "short": "Abbreviation" + }, + "name": "Activity categories", + "numberingStyles": { + "-": "no numbering", + "1": "1, 2, 3 - numbers", + "A": "A, B, C - uppercase letters", + "I": "I, II, III - uppercase roman numerals", + "a": "a, b, c - lowercase letters", + "i": "i, ii, iii - lowercase roman numerals" + } + }, + "checklist": { + "fields": { + "copyChecklistSource": "Prototype", + "name": "Name" + }, + "name": "Checklist | Checklists" + }, + "checklistItem": { + "fields": { + "text": "Text" + }, + "name": "Checklist entry" + }, + "contentType": { + "name": "Contenttype | Contenttypes" + }, + "day": { + "fields": { + "dayResponsibles": "Responsible of the day" + }, + "name": "Day | Days" + }, + "materialItem": { + "fields": { + "article": "Article", + "list": "Material list", + "quantity": "Quantity", + "reference": "Activity / Period", + "unit": "Unit" + } + }, + "materialList": { + "fields": { + "name": "Name" + }, + "name": "Material list" + }, + "period": { + "defaultDescription": "Main", + "fields": { + "description": "Description", + "end": "End", + "start": "Start" + }, + "name": "Period | Periods" + }, + "profile": { + "fields": { + "abbreviation": "Abbreviation", + "color": "Color", + "email": "Email address", + "firstname": "Firstname", + "language": "Language", + "nickname": "Nickname", + "password": "Password", + "surname": "Lastname" + }, + "name": "Profile" + }, + "scheduleEntry": { + "fields": { + "duration": "Duration", + "endDate": "Enddate", + "endDatetime": "Endtime", + "nr": "No.", + "startDate": "Startdate", + "startDatetime": "Starttime", + "time": "Time" + }, + "name": "Activity scheduled" + } + }, + "global": { + "datetime": { + "dateLong": "dd L", + "dateShort": "dd M/D", + "dateTimeLong": "dd L LT", + "duration": { + "daysAndHours": "{days} d {hours} h", + "daysAndHoursAndMinutes": "{days} d {hours} h {minutes} min", + "daysAndMinutes": "{days} d {minutes} min", + "hoursAndMinutes": "{hours} h {minutes} m", + "daysOnly": "{days} s", + "hoursOnly": "{hours} h", + "minutesOnly": "{minutes} m" + }, + "hourLong": "LT", + "hourShort": "H:mm" + }, + "shortScheduleEntryDescription": "day {dayNumber} {startTime}" + }, + "print": { + "activityList": { + "title": "Activity list" + }, + "config": { + "periods": "Period(s)" + }, + "cover": { + "title": "Cover page" + }, + "picasso": { + "picassoFooter": { + "coach": "Coach: {coach}", + "courseNumber": "Course number: {courseNumber}", + "leaders": "Lead: {leaders}", + "trainingAdvisor": "Training advisor: {trainingAdvisor}" + }, + "title": "Program overview {period}" + }, + "program": { + "title": "Program" + }, + "summary": { + "safetyConsiderations": { + "title": "Safety considerations" + }, + "storycontext": { + "title": "Story" + } + }, + "toc": { + "title": "Table of contents" + } + } +} diff --git a/frontend-vue3/src/common/locales/fr-CH-scout.json b/frontend-vue3/src/common/locales/fr-CH-scout.json new file mode 100644 index 0000000000..34679437cb --- /dev/null +++ b/frontend-vue3/src/common/locales/fr-CH-scout.json @@ -0,0 +1,7 @@ +{ + "print": { + "story": { + "title": "Fil rouge" + } + } +} \ No newline at end of file diff --git a/frontend-vue3/src/common/locales/fr.json b/frontend-vue3/src/common/locales/fr.json new file mode 100644 index 0000000000..5631aa95ed --- /dev/null +++ b/frontend-vue3/src/common/locales/fr.json @@ -0,0 +1,298 @@ +{ + "components": { + "summary": { + "summaryDay": { + "noContent": "Les activités de cette journée ne contiennent aucun contenu {contentType}." + } + } + }, + "contentNode": { + "checklist": { + "info": "Sélectionnez les éléments pertinents de la check-list qui sont couverts par cette activité (objectifs du cours, etc.).", + "name": "Check-lists" + }, + "columnLayout": { + "entity": { + "column": { + "name": "Colonne|Colonne {name}" + } + }, + "name": "Disposition des colonnes" + }, + "laThematicArea": { + "entity": { + "option": { + "campsiteAndSurroundings": { + "description": "Aménagement d’un camp/des environs, démontage, aménagement d’une place de jeu et fabrication d’engins de sport.", + "name": "Campement/Environs" + }, + "natureAndEnvironment": { + "description": "Faune et flore, protection de l’environnement dans le cadre du camp, météorologie et astronomie, techniques de transmission, préparation et allumage d’un feu.", + "name": "Nature et environment" + }, + "outdoorTechnique": { + "description": "Planification d’une randonnée, lecture de carte (p. ex. check-list NORDA), croquis, utilisation d’instruments (p.ex. boussole, récepteur GPS, alti- mètre, etc.), orientation dans le terrain.", + "name": "Techniques de plein air" + }, + "pioneeringTechnique": { + "description": "Aménagement d’un bivouac, construction d’un igloo, connaissance du matériel et de l’équipement, entretien du matériel, construction et démontage des installations, cordages et nœuds, tyroliennes, ponts de cordes, descentes en rappel.", + "name": "Technique de pionnier" + }, + "preventionAndIntegration": { + "description": "Activités favorisant la prévention et l’intégration ou développant les compétences des participants dans ce domaine.", + "name": "Prévention et intégration" + }, + "security": { + "description": "Sécurité lors des activités au camp, mesures à prendre en cas d’accident et alerte, premiers secours, réflexions sur la sécurité.", + "name": "Sécurité" + } + } + }, + "info": "Une activité de camp J+S doit aborder au moins un des sujets énumérés.{br}Sélectionne les sujets abordés dans ce bloc.", + "name": "Domaine thématique AC" + }, + "learningObjectives": { + "info": "Formuler en objectifs les compétences que les participant·e·s auront après cette activité.", + "name": "Objectifs d’apprentissage" + }, + "learningTopics": { + "info": "Lister les sujets sur lesquels les participant·e·s apprendront quelque chose dans cette activité.", + "name": "Sujets d'apprentissage" + }, + "material": { + "info": "Tu peux saisir ici les besoins en matériel pour ce bloc.{br}Tu peux gérer les listes de matériel dans le menu 'Admin'.{br}Tu peux trouver un résumé des achats dans le menu 'Matériel'.", + "name": "Matériel" + }, + "notes": { + "info": "Tu peux y inscrire tes notes, par exemple des idées, des tâches à faire, des questions ouvertes, des contacts, des correspondances avec les transports publics, etc.", + "name": "Remarques" + }, + "responsiveLayout": { + "mainContent": "Contenu principal", + "name": "Disposition par défaut", + "printAboveMainContent": "Imprimer au-dessus du contenu principal", + "printBelowMainContent": "Imprimer sous le contenu principal" + }, + "safetyConsiderations": { + "info": "Certains blocs nécessitent de réfléchir aux risques. Tu peux enregistrer ces réflexions ici.{br}Enregistre les risques que tu as identifiés - et comment tu peux y faire face.", + "name": "Considérations sur la sécurité" + }, + "storyboard": { + "entity": { + "section": { + "fields": { + "column1": "Heure", + "column2Html": "Programme", + "column3": "Responsable" + }, + "name": "Section du programme | Sections du programme" + } + }, + "info": "Ici, tu peux planifier le contenu de ce bloc.{br}Dans la colonne de gauche [Temps], tu peux enregistrer la durée des différents éléments.{br}Dans la colonne de droite [Responsable], tu peux assigner des personnes.", + "name": "Sections du programme" + }, + "storycontext": { + "info": "Décris comment ce bloc s'intègre dans l'histoire du camp.{br}Tu peux trouver un résumé de tous les éléments de l'histoire dans le menu 'Histoire'.{br}Tu peux aussi d'abord élaborer une histoire continue dans le menu 'Histoire' - pour que tu puisses parfaitement intégrer le contenu du bloc dans l'histoire.", + "name": "Histoire" + } + }, + "entity": { + "activity": { + "fields": { + "category": "Catégorie d'activité", + "location": "Lieu", + "progressLabel": "Statut", + "responsible": "Responsable", + "title": "Titre" + }, + "name": "Activité", + "new": "Nouvelle activité" + }, + "activityProgressLabel": { + "fields": { + "title": "Titre" + } + }, + "camp": { + "collaborators": { + "guest": "Invité", + "invite": "Inviter", + "manager": "Administration", + "member": "Membre" + }, + "fields": { + "addressCity": "Ville", + "addressName": "Nom", + "addressStreet": "Rue", + "addressZipcode": "Code postal", + "coachName": "Nom du·de la coach J+S", + "courseKind": "Type de cours (pour les cours J+S : terminologie J+S)", + "courseNumber": "Numéro de cours", + "kind": "Type de camp (chalet, tente, itinérant, été, automne)", + "motto": "Fil rouge / Thème", + "organizer": "Organisateur", + "printYSLogoOnPicasso": "Imprimer le logo J+S sur le programme général (requis pour les cours J+S)", + "shortTitle": "Nom du camp court", + "title": "Nom du camp", + "trainingAdvisorName": "Nom du coach J+S" + }, + "name": "Camp", + "prototype": "Modèle de camp" + }, + "campCollaboration": { + "fields": { + "abbreviation": "Abréviation", + "color": "Couleur", + "inviteEmail": "E-mail", + "role": "Role", + "status": "Statut" + }, + "status": { + "established": "Actif", + "inactive": "Inactif", + "invited": "Invité" + } + }, + "category": { + "fields": { + "color": "Couleur", + "name": "Nom", + "numberingStyle": "Style de numérotation", + "short": "Abréviation" + }, + "name": "Catégories d'activités", + "numberingStyles": { + "-": "pas de numérotation", + "1": "1, 2, 3 - numéros", + "A": "A, B, C - lettres majuscules", + "I": "I, II, III - chiffres romains majuscules", + "a": "a, b, c - lettres minuscules", + "i": "i, ii, iii - chiffres romains minuscules" + } + }, + "checklist": { + "fields": { + "copyChecklistSource": "Exemple", + "name": "Nom" + }, + "name": "Check-list | Check-lists" + }, + "checklistItem": { + "fields": { + "text": "Texte" + }, + "name": "Elément de check-list" + }, + "contentType": { + "name": "Type de contenu | Types de contenu" + }, + "day": { + "fields": { + "dayResponsibles": "Responsable du jour" + }, + "name": "Jour | Jours" + }, + "materialItem": { + "fields": { + "article": "Article", + "list": "Liste de matériel", + "quantity": "Quantité", + "reference": "Activité / Période", + "unit": "Unité" + } + }, + "materialList": { + "fields": { + "name": "Nom" + }, + "name": "Liste de matériel" + }, + "period": { + "defaultDescription": "Camp principal", + "fields": { + "description": "Description", + "end": "Fin", + "start": "Début" + }, + "name": "Période | Périodes" + }, + "profile": { + "fields": { + "abbreviation": "Abréviation", + "color": "Couleur", + "email": "Adresse e-mail", + "firstname": "Prénom", + "language": "Langue", + "nickname": "Surnom", + "password": "Mot de passe", + "surname": "Nom de famille" + }, + "name": "Profil" + }, + "scheduleEntry": { + "fields": { + "duration": "Durée", + "endDate": "Date de fin", + "endDatetime": "Heure de fin", + "nr": "No.", + "startDate": "Date de début", + "startDatetime": "Heure de début", + "time": "Moment" + }, + "name": "Inscription au calendrier" + } + }, + "global": { + "datetime": { + "dateLong": "dd L", + "dateShort": "dd D.M.", + "dateTimeLong": "dd L LT", + "duration": { + "daysAndHours": "{days} d {hours} h", + "daysAndHoursAndMinutes": "{days} d {hours} h {minutes} min", + "daysAndMinutes": "{days} d {minutes} min", + "hoursAndMinutes": "{hours} h {minutes} min", + "daysOnly": "{days} d", + "hoursOnly": "{hours} h", + "minutesOnly": "{minutes} min" + }, + "hourLong": "LT", + "hourShort": "H:mm" + }, + "shortScheduleEntryDescription": "jour{dayNumber} {startTime}" + }, + "print": { + "activityList": { + "title": "Liste d'activités" + }, + "config": { + "periods": "Période(s) du camp" + }, + "cover": { + "title": "Page de couverture" + }, + "picasso": { + "picassoFooter": { + "coach": "Coach: {coach}", + "courseNumber": "Numéro de cours: {courseNumber}", + "leaders": "Responsable: {leaders}", + "trainingAdvisor": "Conseiller à la formation: {trainingAdvisor}" + }, + "title": "Aperçu du programme {period}" + }, + "program": { + "title": "Programme" + }, + "summary": { + "safetyConsiderations": { + "title": "Considérations sur la sécurité" + }, + "storycontext": { + "title": "Histoire" + } + }, + "toc": { + "title": "Table des matières" + } + } +} diff --git a/frontend-vue3/src/common/locales/it-CH-scout.json b/frontend-vue3/src/common/locales/it-CH-scout.json new file mode 100644 index 0000000000..9e26dfeeb6 --- /dev/null +++ b/frontend-vue3/src/common/locales/it-CH-scout.json @@ -0,0 +1 @@ +{} \ No newline at end of file diff --git a/frontend-vue3/src/common/locales/it.json b/frontend-vue3/src/common/locales/it.json new file mode 100644 index 0000000000..a35244b580 --- /dev/null +++ b/frontend-vue3/src/common/locales/it.json @@ -0,0 +1,249 @@ +{ + "components": { + "summary": { + "summaryDay": { + "noContent": "Nessun contenuto '{contentType}' trovato in questo giorno..." + } + } + }, + "contentNode": { + "columnLayout": { + "entity": { + "column": { + "name": "Colonna|Colonna {name}" + } + }, + "name": "Layout delle colonne" + }, + "laThematicArea": { + "entity": { + "option": { + "campsiteAndSurroundings": { + "description": "Allestire campo/dintorni, smontare le costruzioni, preparare le installazioni per il terreno da gioco e le attrezzature sportive.", + "name": "Campo/dintorni" + }, + "natureAndEnvironment": { + "description": "Flora e fauna, tutela dell’ambiente al campo, meteorologia e astronomia, tecniche di trasmissione, accensione di un fuoco.", + "name": "Natura e ambiente" + }, + "outdoorTechnique": { + "description": "Pianificazione delle escursioni, lettura delle carte topografiche (p. es. NORDA), schizzi topografici, strumenti di supporto (p.es. bussola, GPS, altimetro, ecc.), orientamento sul terreno.", + "name": "Tecniche outdoor" + }, + "pioneeringTechnique": { + "description": "Installare il bivacco, costruire un igloo, tecniche relative a materiali ed equipaggiamento, effettuare la manutenzione del materiale, montare e smontare le costruzioni pionieristiche, tecniche delle corde e dei nodi, tirolese, ponti di corda, discesa in corda doppia.", + "name": "Tecnica pionieristica" + }, + "preventionAndIntegration": { + "description": "Attività volte a promuovere la prevenzione e l’integrazione nonché a migliorare le competenze dei partecipanti in questo ambito.", + "name": "Prevenzione e integrazione" + }, + "security": { + "description": "Sicurezza durante le attività al campo, organizzazione in caso di infortuni e sistema di allerta, primi soccorsi, riflessioni sulla sicurezza.", + "name": "Sicurezza" + } + } + }, + "info": "Un'attività del campo Y+S deve trattare almeno uno degli argomenti elencati.{br}Seleziona gli argomenti da trattare in questo blocco.", + "name": "Area tematica AC" + }, + "material": { + "info": "Qui puoi inserire i requisiti del materiale per questo blocco.{br}Puoi gestire gli elenchi dei materiali nel menu 'Amministrazione'.{br}Puoi trovare un riepilogo degli acquisti nel menu 'Materiale'.", + "name": "Materiale" + }, + "notes": { + "info": "Qui puoi inserire qualsiasi nota, ad esempio idee, impegni, domande aperte, contatti, collegamenti con i mezzi pubblici, ecc.", + "name": "Noti" + }, + "responsiveLayout": { + "mainContent": "Contenuto principale", + "name": "Layout di default", + "printAboveMainContent": "Stampa sopra il contenuto principale", + "printBelowMainContent": "Stampa sotto il contenuto principale" + }, + "safetyConsiderations": { + "info": "Alcuni blocchi richiedono una riflessione sui rischi. Qui puoi registrare questi pensieri.{br}Registra i rischi che hai identificato e come puoi affrontarli.", + "name": "Considerazioni sulla sicurezza" + }, + "storyboard": { + "entity": { + "section": { + "fields": { + "column1": "Tempo", + "column2Html": "Programma", + "column3": "Responsabile" + }, + "name": "Sezione del programma | Sezioni del programma" + } + }, + "info": "Qui puoi pianificare il contenuto di questo blocco.{br}Nella colonna di sinistra [Tempo] puoi registrare la durata dei singoli elementi.{br}Nella colonna di destra [Responsabile] puoi assegnare delle persone.", + "name": "Programma" + }, + "storycontext": { + "info": "Descrivi come questo blocco si inserisce nella storia del campo.{br}Puoi trovare un riepilogo di tutti gli elementi della storia nel menu \"Storia\".{br}Puoi anche elaborare prima una storia continua nel menu \"Storia\", in modo da incorporare perfettamente il contenuto del blocco nella storia.", + "name": "Storia" + } + }, + "entity": { + "activity": { + "fields": { + "category": "Categoria di attività", + "location": "Posto", + "progressLabel": "Stato", + "responsible": "Responsabile", + "title": "Titolo" + }, + "name": "Attività", + "new": "Nuova attività" + }, + "activityProgressLabel": { + "fields": { + "title": "Titolo" + } + }, + "camp": { + "collaborators": { + "guest": "Ospite", + "invite": "Invita", + "manager": "Amministrazione", + "member": "Membro" + }, + "fields": { + "addressCity": "Città", + "addressName": "Nome", + "addressStreet": "Via", + "addressZipcode": "Codice postale", + "motto": "Motto / Tema", + "shortTitle": "Titolo breve", + "title": "Titolo" + }, + "name": "Campo", + "prototype": "Modello di campo" + }, + "campCollaboration": { + "fields": { + "abbreviation": "Abbreviazione", + "color": "Colore", + "inviteEmail": "E-mail", + "role": "Ruolo", + "status": "Stato" + }, + "status": { + "inactive": "non attivo" + } + }, + "category": { + "fields": { + "color": "Colore", + "name": "Nome", + "numberingStyle": "Stile della numerazione", + "short": "Abbreviazione" + }, + "name": "Categorie di attività", + "numberingStyles": { + "1": "1, 2, 3 - numeri", + "A": "A, B, C - maiuscole di blocco", + "I": "I, II, III - numeri romani maiuscoli", + "a": "a, b, c - lettere minuscole", + "i": "i, ii, iii - numeri romani minuscoli" + } + }, + "contentType": { + "name": "Tipo di contenuto | Tipi di contenuto" + }, + "day": { + "fields": { + "dayResponsibles": "Responsabile del giorno" + }, + "name": "Giorno | Giorni" + }, + "materialItem": { + "fields": { + "article": "Articolo", + "list": "Elenco dei materiali", + "quantity": "Quantità", + "reference": "Attività / Periodo", + "unit": "Unità" + } + }, + "materialList": { + "fields": { + "name": "Nome" + }, + "name": "Elenco dei materiali" + }, + "period": { + "defaultDescription": "Campo principale", + "fields": { + "description": "Descrizione", + "end": "Fine", + "start": "Inizio" + }, + "name": "Periodo | Periodi" + }, + "profile": { + "fields": { + "abbreviation": "Abbreviazione", + "color": "Colore", + "email": "Indirizzo email", + "firstname": "Nome", + "language": "Lingua", + "nickname": "Soprannome", + "password": "Parola d'ordine", + "surname": "Cognome" + }, + "name": "Profilo" + }, + "scheduleEntry": { + "fields": { + "duration": "Durata", + "endDate": "Data di fine", + "endDatetime": "Ora di fine", + "nr": "N.", + "startDate": "Data di inizio", + "startDatetime": "Ora di inizio", + "time": "Tempo" + }, + "name": "Inserimento nel programma" + } + }, + "global": { + "datetime": { + "dateLong": "dd L", + "dateShort": "dd D.M.", + "dateTimeLong": "dd L LT", + "duration": { + "hoursAndMinutes": "{hours}h {minutes}min", + "hoursOnly": "{hours}h", + "minutesOnly": "{minutes}min" + }, + "hourLong": "LT", + "hourShort": "H:mm" + } + }, + "print": { + "config": { + "periods": "Sezione/i portante/i" + }, + "cover": { + "title": "Pagina di copertina" + }, + "picasso": { + "title": "Panoramica del programma {period}" + }, + "program": { + "title": "Programma" + }, + "summary": { + "safetyConsiderations": { + "title": "Considerazioni sulla sicurezza" + }, + "storycontext": { + "title": "Storia" + } + }, + "toc": { + "title": "Indice dei contenuti" + } + } +} diff --git a/frontend-vue3/src/common/locales/rm-CH-scout.json b/frontend-vue3/src/common/locales/rm-CH-scout.json new file mode 100644 index 0000000000..0851f8f04f --- /dev/null +++ b/frontend-vue3/src/common/locales/rm-CH-scout.json @@ -0,0 +1,7 @@ +{ + "print": { + "story": { + "title": "Fil cotschen" + } + } +} diff --git a/frontend-vue3/src/common/locales/rm.json b/frontend-vue3/src/common/locales/rm.json new file mode 100644 index 0000000000..ea13c3db30 --- /dev/null +++ b/frontend-vue3/src/common/locales/rm.json @@ -0,0 +1,16 @@ +{ + "entity": { + "profile": { + "fields": { + "abbreviation": "Abbreviaziun", + "color": "Colur", + "email": "Adressa dad e-mail", + "firstname": "Prenum", + "language": "Lingua", + "nickname": "Surnum", + "password": "Pled-clav", + "surname": "Num da famiglia" + } + } + } +} diff --git a/frontend-vue3/src/components/activity/ActivityResponsibles.vue b/frontend-vue3/src/components/activity/ActivityResponsibles.vue new file mode 100644 index 0000000000..709cb3d967 --- /dev/null +++ b/frontend-vue3/src/components/activity/ActivityResponsibles.vue @@ -0,0 +1,195 @@ + + + + + diff --git a/frontend-vue3/src/components/activity/ButtonNestedContentNodeAdd.vue b/frontend-vue3/src/components/activity/ButtonNestedContentNodeAdd.vue new file mode 100644 index 0000000000..4b31c5f67e --- /dev/null +++ b/frontend-vue3/src/components/activity/ButtonNestedContentNodeAdd.vue @@ -0,0 +1,184 @@ + + + + diff --git a/frontend-vue3/src/components/activity/ContentNode.vue b/frontend-vue3/src/components/activity/ContentNode.vue new file mode 100644 index 0000000000..5b9d393811 --- /dev/null +++ b/frontend-vue3/src/components/activity/ContentNode.vue @@ -0,0 +1,63 @@ + + + + + diff --git a/frontend-vue3/src/components/activity/DaySwitcher.vue b/frontend-vue3/src/components/activity/DaySwitcher.vue new file mode 100644 index 0000000000..1927df1baa --- /dev/null +++ b/frontend-vue3/src/components/activity/DaySwitcher.vue @@ -0,0 +1,137 @@ + + + + + + diff --git a/frontend-vue3/src/components/activity/DraggableContentNodes.vue b/frontend-vue3/src/components/activity/DraggableContentNodes.vue new file mode 100644 index 0000000000..9575e359ed --- /dev/null +++ b/frontend-vue3/src/components/activity/DraggableContentNodes.vue @@ -0,0 +1,249 @@ + + + diff --git a/frontend-vue3/src/components/activity/MenuCardlessContentNode.vue b/frontend-vue3/src/components/activity/MenuCardlessContentNode.vue new file mode 100644 index 0000000000..cddba342a8 --- /dev/null +++ b/frontend-vue3/src/components/activity/MenuCardlessContentNode.vue @@ -0,0 +1,78 @@ + + diff --git a/frontend-vue3/src/components/activity/RootNode.vue b/frontend-vue3/src/components/activity/RootNode.vue new file mode 100644 index 0000000000..052d65946a --- /dev/null +++ b/frontend-vue3/src/components/activity/RootNode.vue @@ -0,0 +1,51 @@ + + + diff --git a/frontend-vue3/src/components/activity/ScheduleEntry.vue b/frontend-vue3/src/components/activity/ScheduleEntry.vue new file mode 100644 index 0000000000..e9bb80b21d --- /dev/null +++ b/frontend-vue3/src/components/activity/ScheduleEntry.vue @@ -0,0 +1,535 @@ + + + + + + + diff --git a/frontend-vue3/src/components/activity/TogglePaperSize.vue b/frontend-vue3/src/components/activity/TogglePaperSize.vue new file mode 100644 index 0000000000..33e87d66c5 --- /dev/null +++ b/frontend-vue3/src/components/activity/TogglePaperSize.vue @@ -0,0 +1,43 @@ + + + + + diff --git a/frontend-vue3/src/components/activity/content/Checklist.vue b/frontend-vue3/src/components/activity/content/Checklist.vue new file mode 100644 index 0000000000..85e5184507 --- /dev/null +++ b/frontend-vue3/src/components/activity/content/Checklist.vue @@ -0,0 +1,251 @@ + + + + + diff --git a/frontend-vue3/src/components/activity/content/ColumnLayout.vue b/frontend-vue3/src/components/activity/content/ColumnLayout.vue new file mode 100644 index 0000000000..de1a98a61e --- /dev/null +++ b/frontend-vue3/src/components/activity/content/ColumnLayout.vue @@ -0,0 +1,212 @@ + + + + + diff --git a/frontend-vue3/src/components/activity/content/LAThematicArea.vue b/frontend-vue3/src/components/activity/content/LAThematicArea.vue new file mode 100644 index 0000000000..9627adade6 --- /dev/null +++ b/frontend-vue3/src/components/activity/content/LAThematicArea.vue @@ -0,0 +1,194 @@ + + + + + diff --git a/frontend-vue3/src/components/activity/content/LearningObjectives.vue b/frontend-vue3/src/components/activity/content/LearningObjectives.vue new file mode 100644 index 0000000000..f3c2232ffb --- /dev/null +++ b/frontend-vue3/src/components/activity/content/LearningObjectives.vue @@ -0,0 +1,29 @@ + + + + + diff --git a/frontend-vue3/src/components/activity/content/LearningTopics.vue b/frontend-vue3/src/components/activity/content/LearningTopics.vue new file mode 100644 index 0000000000..a45a623b2a --- /dev/null +++ b/frontend-vue3/src/components/activity/content/LearningTopics.vue @@ -0,0 +1,29 @@ + + + + + diff --git a/frontend-vue3/src/components/activity/content/Material.vue b/frontend-vue3/src/components/activity/content/Material.vue new file mode 100644 index 0000000000..db78fe5c85 --- /dev/null +++ b/frontend-vue3/src/components/activity/content/Material.vue @@ -0,0 +1,34 @@ + + + + + diff --git a/frontend-vue3/src/components/activity/content/Notes.vue b/frontend-vue3/src/components/activity/content/Notes.vue new file mode 100644 index 0000000000..df269748e6 --- /dev/null +++ b/frontend-vue3/src/components/activity/content/Notes.vue @@ -0,0 +1,26 @@ + + + diff --git a/frontend-vue3/src/components/activity/content/ResponsiveLayout.vue b/frontend-vue3/src/components/activity/content/ResponsiveLayout.vue new file mode 100644 index 0000000000..c055410562 --- /dev/null +++ b/frontend-vue3/src/components/activity/content/ResponsiveLayout.vue @@ -0,0 +1,191 @@ + + + + + diff --git a/frontend-vue3/src/components/activity/content/SafetyConsiderations.vue b/frontend-vue3/src/components/activity/content/SafetyConsiderations.vue new file mode 100644 index 0000000000..ce88a04358 --- /dev/null +++ b/frontend-vue3/src/components/activity/content/SafetyConsiderations.vue @@ -0,0 +1,29 @@ + + + + + diff --git a/frontend-vue3/src/components/activity/content/Storyboard.vue b/frontend-vue3/src/components/activity/content/Storyboard.vue new file mode 100644 index 0000000000..1a87ee2005 --- /dev/null +++ b/frontend-vue3/src/components/activity/content/Storyboard.vue @@ -0,0 +1,196 @@ + + + + diff --git a/frontend-vue3/src/components/activity/content/Storycontext.vue b/frontend-vue3/src/components/activity/content/Storycontext.vue new file mode 100644 index 0000000000..fd16cbb610 --- /dev/null +++ b/frontend-vue3/src/components/activity/content/Storycontext.vue @@ -0,0 +1,26 @@ + + + diff --git a/frontend-vue3/src/components/activity/content/checklist/ChecklistItem.vue b/frontend-vue3/src/components/activity/content/checklist/ChecklistItem.vue new file mode 100644 index 0000000000..4ae9e7883e --- /dev/null +++ b/frontend-vue3/src/components/activity/content/checklist/ChecklistItem.vue @@ -0,0 +1,60 @@ + + + + + diff --git a/frontend-vue3/src/components/activity/content/checklist/ChecklistItems.vue b/frontend-vue3/src/components/activity/content/checklist/ChecklistItems.vue new file mode 100644 index 0000000000..83cf028e7b --- /dev/null +++ b/frontend-vue3/src/components/activity/content/checklist/ChecklistItems.vue @@ -0,0 +1,55 @@ + + + diff --git a/frontend-vue3/src/components/activity/content/columnLayout/ColumnIndicator.vue b/frontend-vue3/src/components/activity/content/columnLayout/ColumnIndicator.vue new file mode 100644 index 0000000000..345bf732cd --- /dev/null +++ b/frontend-vue3/src/components/activity/content/columnLayout/ColumnIndicator.vue @@ -0,0 +1,37 @@ + + diff --git a/frontend-vue3/src/components/activity/content/columnLayout/ColumnOperations.vue b/frontend-vue3/src/components/activity/content/columnLayout/ColumnOperations.vue new file mode 100644 index 0000000000..1c6fe5dc80 --- /dev/null +++ b/frontend-vue3/src/components/activity/content/columnLayout/ColumnOperations.vue @@ -0,0 +1,97 @@ + + diff --git a/frontend-vue3/src/components/activity/content/columnLayout/ResizableColumn.vue b/frontend-vue3/src/components/activity/content/columnLayout/ResizableColumn.vue new file mode 100644 index 0000000000..b58a4aa4fc --- /dev/null +++ b/frontend-vue3/src/components/activity/content/columnLayout/ResizableColumn.vue @@ -0,0 +1,109 @@ + + + + + diff --git a/frontend-vue3/src/components/activity/content/columnLayout/ResizableColumnHeader.vue b/frontend-vue3/src/components/activity/content/columnLayout/ResizableColumnHeader.vue new file mode 100644 index 0000000000..0791270e7b --- /dev/null +++ b/frontend-vue3/src/components/activity/content/columnLayout/ResizableColumnHeader.vue @@ -0,0 +1,169 @@ + + + diff --git a/frontend-vue3/src/components/activity/content/columnLayout/__tests__/calculateNextSlotName.spec.js b/frontend-vue3/src/components/activity/content/columnLayout/__tests__/calculateNextSlotName.spec.js new file mode 100644 index 0000000000..a2a2324432 --- /dev/null +++ b/frontend-vue3/src/components/activity/content/columnLayout/__tests__/calculateNextSlotName.spec.js @@ -0,0 +1,73 @@ +import { describe, expect, it } from 'vitest' +import { calculateNextSlotName, adjustColumnWidths } from '../calculateNextSlotName.js' + +describe('generating a next slot name', () => { + const examples = [ + [[], '1'], + [[''], '1'], + [['0'], '1'], + [['1'], '2'], + [['a'], '1'], + [['A'], '1'], + [['9'], '1'], + [['z'], '1'], + [['Z'], '1'], + [['0.'], '1'], + [['9.'], '1'], + [['999'], '1'], + [['1', '2'], '3'], + [['1', '3'], '2'], + [['1z', '1'], '2'], + [['mitte', 'oben', 'unten'], '1'], + [['😋'], '1'], + [['a😋'], '1'], + [['1', '2', '3', '4', '5', '6', '7', '8', '9'], '10'], + [['1', '2', '3', '4', '5', '6', '7', '8', '9', '10'], '11'], + ] + + examples.forEach(([input, expected]) => { + it(input.toString(), () => { + expect(calculateNextSlotName(input)).toEqual(expected) + }) + }) +}) + +describe('adjusting the column widths', () => { + // prettier-ignore + const examples = [ + [[], []], + // compacting columns + [[{ name: '1', width: 20 }], [12]], + [[{ name: '1', width: 12 }, { name: '2', width: 3 }], [9, 3]], + [[{ name: '1', width: 3 }, { name: '2', width: 9 }, { name: '3', width: 3 }], [3, 6, 3]], + [[{ name: '1', width: 4 }, { name: '2', width: 8 }, { name: '3', width: 3 }], [4, 5, 3]], + [[{ name: '1', width: 5 }, { name: '2', width: 7 }, { name: '3', width: 3 }], [5, 4, 3]], + [[{ name: '1', width: 6 }, { name: '2', width: 6 }, { name: '3', width: 3 }], [6, 3, 3]], + [[{ name: '1', width: 7 }, { name: '2', width: 5 }, { name: '3', width: 3 }], [6, 3, 3]], + [[{ name: '1', width: 8 }, { name: '2', width: 4 }, { name: '3', width: 3 }], [6, 3, 3]], + [[{ name: '1', width: 9 }, { name: '2', width: 3 }, { name: '3', width: 3 }], [6, 3, 3]], + [[{ name: '1', width: 3 }, { name: '2', width: 3 }, { name: '3', width: 6 }, { name: '4', width: 3 }], [3, 3, 3, 3]], + [[{ name: '1', width: 3 }, { name: '2', width: 4 }, { name: '3', width: 5 }, { name: '4', width: 3 }], [3, 3, 3, 3]], + [[{ name: '1', width: 4 }, { name: '2', width: 3 }, { name: '3', width: 5 }, { name: '4', width: 3 }], [3, 3, 3, 3]], + [[{ name: '1', width: 3 }, { name: '2', width: 5 }, { name: '3', width: 4 }, { name: '4', width: 3 }], [3, 3, 3, 3]], + [[{ name: '1', width: 4 }, { name: '2', width: 4 }, { name: '3', width: 4 }, { name: '4', width: 3 }], [3, 3, 3, 3]], + [[{ name: '1', width: 5 }, { name: '2', width: 3 }, { name: '3', width: 4 }, { name: '4', width: 3 }], [3, 3, 3, 3]], + [[{ name: '1', width: 3 }, { name: '2', width: 6 }, { name: '3', width: 3 }, { name: '4', width: 3 }], [3, 3, 3, 3]], + [[{ name: '1', width: 4 }, { name: '2', width: 5 }, { name: '3', width: 3 }, { name: '4', width: 3 }], [3, 3, 3, 3]], + [[{ name: '1', width: 5 }, { name: '2', width: 4 }, { name: '3', width: 3 }, { name: '4', width: 3 }], [3, 3, 3, 3]], + [[{ name: '1', width: 6 }, { name: '2', width: 3 }, { name: '3', width: 3 }, { name: '4', width: 3 }], [3, 3, 3, 3]], + // expanding columns + [[{ name: '1', width: 10 }], [12]], + [[{ name: '1', width: 1 }, { name: '2', width: 3 }], [3, 9]], + [[{ name: '1', width: 3 }, { name: '2', width: 3 }], [3, 9]], + [[{ name: '1', width: 3 }, { name: '2', width: 3 }, { name: '3', width: 3 }], [3, 3, 6]], + [[{ name: '1', width: 3 }, { name: '2', width: 3 }, { name: '3', width: 2 }, { name: '4', width: 3 }], [3, 3, 3, 3]], + [[{ name: '1', width: 3 }, { name: '2', width: 3 }, { name: '3', width: 3 }, { name: '4', width: 3 }], [3, 3, 3, 3]] + ] + + examples.forEach(([input, expected]) => { + it(input.map((col) => col.width).toString(), () => { + expect(adjustColumnWidths(input).map((col) => col.width)).toEqual(expected) + }) + }) +}) diff --git a/frontend-vue3/src/components/activity/content/columnLayout/calculateNextSlotName.js b/frontend-vue3/src/components/activity/content/columnLayout/calculateNextSlotName.js new file mode 100644 index 0000000000..4230abb92c --- /dev/null +++ b/frontend-vue3/src/components/activity/content/columnLayout/calculateNextSlotName.js @@ -0,0 +1,32 @@ +import cloneDeep from 'lodash-es/cloneDeep' + +export function calculateNextSlotName(slotNames) { + let i = 0 + + while (true) { + if (!slotNames.includes((++i).toString())) return i.toString() + } +} + +export function adjustColumnWidths(columns, minWidth = 3, maxWidth = 12) { + const cols = cloneDeep(columns) + + if (cols.length < 1) return cols + + // Enforce minimum column widths + cols.forEach((col) => { + col.width = Math.max(minWidth, col.width) + }) + + // Make sure the column widths sum up to maxWidth + let excess = cols.reduce((sum, col) => sum + col.width, 0) - maxWidth + let i = cols.length - 1 + while (excess !== 0 && i >= 0) { + const diff = Math.min(Math.max(0, cols[i].width - minWidth), excess) + cols[i].width -= diff + excess -= diff + i-- + } + + return cols +} diff --git a/frontend-vue3/src/components/activity/content/contentTypeIcons.js b/frontend-vue3/src/components/activity/content/contentTypeIcons.js new file mode 100644 index 0000000000..c327708e20 --- /dev/null +++ b/frontend-vue3/src/components/activity/content/contentTypeIcons.js @@ -0,0 +1,18 @@ +/** + * Maps content type to mdi icon + */ +const contentTypeIcons = { + checklist: 'mdi-clipboard-list-outline', + columnLayout: 'mdi-view-column', + laThematicArea: 'mdi-shape', + learningObjectives: 'mdi-school', + learningTopics: 'mdi-school', + material: 'mdi-package-variant', + notes: 'mdi-pen', + responsiveLayout: 'mdi-view-compact', + safetyConsiderations: 'mdi-security', + storyboard: 'mdi-script-text-outline', + storycontext: 'mdi-book-open-variant', +} + +export default contentTypeIcons diff --git a/frontend-vue3/src/components/activity/content/layout/ContentNodeCard.vue b/frontend-vue3/src/components/activity/content/layout/ContentNodeCard.vue new file mode 100644 index 0000000000..77cd22c118 --- /dev/null +++ b/frontend-vue3/src/components/activity/content/layout/ContentNodeCard.vue @@ -0,0 +1,173 @@ + + + + + diff --git a/frontend-vue3/src/components/activity/content/layout/LayoutItem.vue b/frontend-vue3/src/components/activity/content/layout/LayoutItem.vue new file mode 100644 index 0000000000..b439c67edc --- /dev/null +++ b/frontend-vue3/src/components/activity/content/layout/LayoutItem.vue @@ -0,0 +1,25 @@ + + + + + diff --git a/frontend-vue3/src/components/activity/content/layout/LayoutNodeCard.vue b/frontend-vue3/src/components/activity/content/layout/LayoutNodeCard.vue new file mode 100644 index 0000000000..d6f32a6886 --- /dev/null +++ b/frontend-vue3/src/components/activity/content/layout/LayoutNodeCard.vue @@ -0,0 +1,46 @@ + + + + + diff --git a/frontend-vue3/src/components/activity/content/storyboard/StoryboardDialogRemoveSection.vue b/frontend-vue3/src/components/activity/content/storyboard/StoryboardDialogRemoveSection.vue new file mode 100644 index 0000000000..0d3a25e8cf --- /dev/null +++ b/frontend-vue3/src/components/activity/content/storyboard/StoryboardDialogRemoveSection.vue @@ -0,0 +1,50 @@ + + + diff --git a/frontend-vue3/src/components/activity/content/storyboard/StoryboardRowDefault.vue b/frontend-vue3/src/components/activity/content/storyboard/StoryboardRowDefault.vue new file mode 100644 index 0000000000..6800cbc2ce --- /dev/null +++ b/frontend-vue3/src/components/activity/content/storyboard/StoryboardRowDefault.vue @@ -0,0 +1,105 @@ + + + diff --git a/frontend-vue3/src/components/activity/content/storyboard/StoryboardRowDense.vue b/frontend-vue3/src/components/activity/content/storyboard/StoryboardRowDense.vue new file mode 100644 index 0000000000..ecd6fbf2dd --- /dev/null +++ b/frontend-vue3/src/components/activity/content/storyboard/StoryboardRowDense.vue @@ -0,0 +1,121 @@ + + + diff --git a/frontend-vue3/src/components/activity/content/storyboard/StoryboardSortable.vue b/frontend-vue3/src/components/activity/content/storyboard/StoryboardSortable.vue new file mode 100644 index 0000000000..dc6a036cd4 --- /dev/null +++ b/frontend-vue3/src/components/activity/content/storyboard/StoryboardSortable.vue @@ -0,0 +1,197 @@ + + + + + diff --git a/frontend-vue3/src/components/activity/dialog/DialogActivityEdit.vue b/frontend-vue3/src/components/activity/dialog/DialogActivityEdit.vue new file mode 100644 index 0000000000..0043eb1a77 --- /dev/null +++ b/frontend-vue3/src/components/activity/dialog/DialogActivityEdit.vue @@ -0,0 +1,168 @@ + + + + + diff --git a/frontend-vue3/src/components/activity/dialog/DialogActivityForm.vue b/frontend-vue3/src/components/activity/dialog/DialogActivityForm.vue new file mode 100644 index 0000000000..b28db8a9d7 --- /dev/null +++ b/frontend-vue3/src/components/activity/dialog/DialogActivityForm.vue @@ -0,0 +1,100 @@ + + + diff --git a/frontend-vue3/src/components/activity/dialog/FormScheduleEntryItem.vue b/frontend-vue3/src/components/activity/dialog/FormScheduleEntryItem.vue new file mode 100644 index 0000000000..5daee45abb --- /dev/null +++ b/frontend-vue3/src/components/activity/dialog/FormScheduleEntryItem.vue @@ -0,0 +1,348 @@ + + + diff --git a/frontend-vue3/src/components/activity/dialog/FormScheduleEntryList.vue b/frontend-vue3/src/components/activity/dialog/FormScheduleEntryList.vue new file mode 100644 index 0000000000..1520279553 --- /dev/null +++ b/frontend-vue3/src/components/activity/dialog/FormScheduleEntryList.vue @@ -0,0 +1,141 @@ + + + diff --git a/frontend-vue3/src/components/buttons/ButtonAdd.vue b/frontend-vue3/src/components/buttons/ButtonAdd.vue new file mode 100644 index 0000000000..5ec7fbe396 --- /dev/null +++ b/frontend-vue3/src/components/buttons/ButtonAdd.vue @@ -0,0 +1,27 @@ + + + + + diff --git a/frontend-vue3/src/components/buttons/ButtonBack.vue b/frontend-vue3/src/components/buttons/ButtonBack.vue new file mode 100644 index 0000000000..fe96c591cc --- /dev/null +++ b/frontend-vue3/src/components/buttons/ButtonBack.vue @@ -0,0 +1,27 @@ + + + + + diff --git a/frontend-vue3/src/components/buttons/ButtonCancel.vue b/frontend-vue3/src/components/buttons/ButtonCancel.vue new file mode 100644 index 0000000000..85b58839ff --- /dev/null +++ b/frontend-vue3/src/components/buttons/ButtonCancel.vue @@ -0,0 +1,11 @@ + + + diff --git a/frontend-vue3/src/components/buttons/ButtonContinue.vue b/frontend-vue3/src/components/buttons/ButtonContinue.vue new file mode 100644 index 0000000000..b605a8b39c --- /dev/null +++ b/frontend-vue3/src/components/buttons/ButtonContinue.vue @@ -0,0 +1,11 @@ + + + diff --git a/frontend-vue3/src/components/buttons/ButtonDelete.vue b/frontend-vue3/src/components/buttons/ButtonDelete.vue new file mode 100644 index 0000000000..addcb1a40c --- /dev/null +++ b/frontend-vue3/src/components/buttons/ButtonDelete.vue @@ -0,0 +1,41 @@ + + + + + diff --git a/frontend-vue3/src/components/buttons/ButtonEdit.vue b/frontend-vue3/src/components/buttons/ButtonEdit.vue new file mode 100644 index 0000000000..773a34982f --- /dev/null +++ b/frontend-vue3/src/components/buttons/ButtonEdit.vue @@ -0,0 +1,27 @@ + + + + + diff --git a/frontend-vue3/src/components/buttons/ButtonRetry.vue b/frontend-vue3/src/components/buttons/ButtonRetry.vue new file mode 100644 index 0000000000..7b36033998 --- /dev/null +++ b/frontend-vue3/src/components/buttons/ButtonRetry.vue @@ -0,0 +1,12 @@ + + + diff --git a/frontend-vue3/src/components/buttons/IconButton.vue b/frontend-vue3/src/components/buttons/IconButton.vue new file mode 100644 index 0000000000..b941009aa5 --- /dev/null +++ b/frontend-vue3/src/components/buttons/IconButton.vue @@ -0,0 +1,48 @@ + + + + + diff --git a/frontend-vue3/src/components/camp/CampListItem.vue b/frontend-vue3/src/components/camp/CampListItem.vue new file mode 100644 index 0000000000..5b28ccf631 --- /dev/null +++ b/frontend-vue3/src/components/camp/CampListItem.vue @@ -0,0 +1,43 @@ + + + + + diff --git a/frontend-vue3/src/components/campAdmin/CampActivityProgressLabels.vue b/frontend-vue3/src/components/campAdmin/CampActivityProgressLabels.vue new file mode 100644 index 0000000000..513c387207 --- /dev/null +++ b/frontend-vue3/src/components/campAdmin/CampActivityProgressLabels.vue @@ -0,0 +1,135 @@ + + + diff --git a/frontend-vue3/src/components/campAdmin/CampAddress.vue b/frontend-vue3/src/components/campAdmin/CampAddress.vue new file mode 100644 index 0000000000..14b7a66487 --- /dev/null +++ b/frontend-vue3/src/components/campAdmin/CampAddress.vue @@ -0,0 +1,51 @@ + + + + + + + diff --git a/frontend-vue3/src/components/campAdmin/CampCategories.vue b/frontend-vue3/src/components/campAdmin/CampCategories.vue new file mode 100644 index 0000000000..47cf96af90 --- /dev/null +++ b/frontend-vue3/src/components/campAdmin/CampCategories.vue @@ -0,0 +1,86 @@ + + + diff --git a/frontend-vue3/src/components/campAdmin/CampConditionalFields.vue b/frontend-vue3/src/components/campAdmin/CampConditionalFields.vue new file mode 100644 index 0000000000..e98f852745 --- /dev/null +++ b/frontend-vue3/src/components/campAdmin/CampConditionalFields.vue @@ -0,0 +1,78 @@ + + + + + diff --git a/frontend-vue3/src/components/campAdmin/CampDangerZone.vue b/frontend-vue3/src/components/campAdmin/CampDangerZone.vue new file mode 100644 index 0000000000..2a44263480 --- /dev/null +++ b/frontend-vue3/src/components/campAdmin/CampDangerZone.vue @@ -0,0 +1,94 @@ + + + + + + + diff --git a/frontend-vue3/src/components/campAdmin/CampPeriods.vue b/frontend-vue3/src/components/campAdmin/CampPeriods.vue new file mode 100644 index 0000000000..9e7db1dde8 --- /dev/null +++ b/frontend-vue3/src/components/campAdmin/CampPeriods.vue @@ -0,0 +1,63 @@ + + + + + + + diff --git a/frontend-vue3/src/components/campAdmin/CampPeriodsListItem.vue b/frontend-vue3/src/components/campAdmin/CampPeriodsListItem.vue new file mode 100644 index 0000000000..b5bcead9b5 --- /dev/null +++ b/frontend-vue3/src/components/campAdmin/CampPeriodsListItem.vue @@ -0,0 +1,150 @@ + + + + + + + diff --git a/frontend-vue3/src/components/campAdmin/CampSettings.vue b/frontend-vue3/src/components/campAdmin/CampSettings.vue new file mode 100644 index 0000000000..80573cbb00 --- /dev/null +++ b/frontend-vue3/src/components/campAdmin/CampSettings.vue @@ -0,0 +1,62 @@ + + + + + + + diff --git a/frontend-vue3/src/components/campAdmin/CreateCampPeriods.vue b/frontend-vue3/src/components/campAdmin/CreateCampPeriods.vue new file mode 100644 index 0000000000..6cf3b809c8 --- /dev/null +++ b/frontend-vue3/src/components/campAdmin/CreateCampPeriods.vue @@ -0,0 +1,115 @@ + + + diff --git a/frontend-vue3/src/components/campAdmin/DialogActivityProgressLabelCreate.vue b/frontend-vue3/src/components/campAdmin/DialogActivityProgressLabelCreate.vue new file mode 100644 index 0000000000..b36aee8dfe --- /dev/null +++ b/frontend-vue3/src/components/campAdmin/DialogActivityProgressLabelCreate.vue @@ -0,0 +1,71 @@ + + + + + diff --git a/frontend-vue3/src/components/campAdmin/DialogActivityProgressLabelEdit.vue b/frontend-vue3/src/components/campAdmin/DialogActivityProgressLabelEdit.vue new file mode 100644 index 0000000000..6aacbb9658 --- /dev/null +++ b/frontend-vue3/src/components/campAdmin/DialogActivityProgressLabelEdit.vue @@ -0,0 +1,83 @@ + + + + + diff --git a/frontend-vue3/src/components/campAdmin/DialogActivityProgressLabelForm.vue b/frontend-vue3/src/components/campAdmin/DialogActivityProgressLabelForm.vue new file mode 100644 index 0000000000..10b234db90 --- /dev/null +++ b/frontend-vue3/src/components/campAdmin/DialogActivityProgressLabelForm.vue @@ -0,0 +1,24 @@ + + + diff --git a/frontend-vue3/src/components/campAdmin/DialogCategoryCreate.vue b/frontend-vue3/src/components/campAdmin/DialogCategoryCreate.vue new file mode 100644 index 0000000000..ae31f768b6 --- /dev/null +++ b/frontend-vue3/src/components/campAdmin/DialogCategoryCreate.vue @@ -0,0 +1,244 @@ + + + + + diff --git a/frontend-vue3/src/components/campAdmin/DialogCategoryForm.vue b/frontend-vue3/src/components/campAdmin/DialogCategoryForm.vue new file mode 100644 index 0000000000..df18d9ff48 --- /dev/null +++ b/frontend-vue3/src/components/campAdmin/DialogCategoryForm.vue @@ -0,0 +1,52 @@ + + + diff --git a/frontend-vue3/src/components/campAdmin/DialogMaterialListCreate.vue b/frontend-vue3/src/components/campAdmin/DialogMaterialListCreate.vue new file mode 100644 index 0000000000..b35b8303f1 --- /dev/null +++ b/frontend-vue3/src/components/campAdmin/DialogMaterialListCreate.vue @@ -0,0 +1,65 @@ + + + + + diff --git a/frontend-vue3/src/components/campAdmin/DialogMaterialListEdit.vue b/frontend-vue3/src/components/campAdmin/DialogMaterialListEdit.vue new file mode 100644 index 0000000000..d3dc65aa46 --- /dev/null +++ b/frontend-vue3/src/components/campAdmin/DialogMaterialListEdit.vue @@ -0,0 +1,65 @@ + + + + + diff --git a/frontend-vue3/src/components/campAdmin/DialogMaterialListForm.vue b/frontend-vue3/src/components/campAdmin/DialogMaterialListForm.vue new file mode 100644 index 0000000000..c5338d8623 --- /dev/null +++ b/frontend-vue3/src/components/campAdmin/DialogMaterialListForm.vue @@ -0,0 +1,24 @@ + + + diff --git a/frontend-vue3/src/components/campAdmin/DialogPeriodCreate.vue b/frontend-vue3/src/components/campAdmin/DialogPeriodCreate.vue new file mode 100644 index 0000000000..579011ef68 --- /dev/null +++ b/frontend-vue3/src/components/campAdmin/DialogPeriodCreate.vue @@ -0,0 +1,66 @@ + + + + + diff --git a/frontend-vue3/src/components/campAdmin/DialogPeriodDateEdit.vue b/frontend-vue3/src/components/campAdmin/DialogPeriodDateEdit.vue new file mode 100644 index 0000000000..6b5f119db0 --- /dev/null +++ b/frontend-vue3/src/components/campAdmin/DialogPeriodDateEdit.vue @@ -0,0 +1,134 @@ + + + + + diff --git a/frontend-vue3/src/components/campAdmin/DialogPeriodDescriptionEdit.vue b/frontend-vue3/src/components/campAdmin/DialogPeriodDescriptionEdit.vue new file mode 100644 index 0000000000..80fbab432d --- /dev/null +++ b/frontend-vue3/src/components/campAdmin/DialogPeriodDescriptionEdit.vue @@ -0,0 +1,53 @@ + + + + + diff --git a/frontend-vue3/src/components/campAdmin/DialogPeriodForm.vue b/frontend-vue3/src/components/campAdmin/DialogPeriodForm.vue new file mode 100644 index 0000000000..05f42cf3b1 --- /dev/null +++ b/frontend-vue3/src/components/campAdmin/DialogPeriodForm.vue @@ -0,0 +1,37 @@ + + + diff --git a/frontend-vue3/src/components/campAdmin/ErrorExistingActivitiesList.vue b/frontend-vue3/src/components/campAdmin/ErrorExistingActivitiesList.vue new file mode 100644 index 0000000000..4639472a44 --- /dev/null +++ b/frontend-vue3/src/components/campAdmin/ErrorExistingActivitiesList.vue @@ -0,0 +1,56 @@ + + + + diff --git a/frontend-vue3/src/components/campCreate/CampCreate.vue b/frontend-vue3/src/components/campCreate/CampCreate.vue new file mode 100644 index 0000000000..e30525d7fc --- /dev/null +++ b/frontend-vue3/src/components/campCreate/CampCreate.vue @@ -0,0 +1,95 @@ + + diff --git a/frontend-vue3/src/components/campCreate/CampCreateStep1.vue b/frontend-vue3/src/components/campCreate/CampCreateStep1.vue new file mode 100644 index 0000000000..9fde37cb87 --- /dev/null +++ b/frontend-vue3/src/components/campCreate/CampCreateStep1.vue @@ -0,0 +1,101 @@ + + diff --git a/frontend-vue3/src/components/campCreate/CampCreateStep2.vue b/frontend-vue3/src/components/campCreate/CampCreateStep2.vue new file mode 100644 index 0000000000..6fc63bc8c7 --- /dev/null +++ b/frontend-vue3/src/components/campCreate/CampCreateStep2.vue @@ -0,0 +1,377 @@ + + + + diff --git a/frontend-vue3/src/components/category/CategoryProperties.vue b/frontend-vue3/src/components/category/CategoryProperties.vue new file mode 100644 index 0000000000..ecf8cc7ea0 --- /dev/null +++ b/frontend-vue3/src/components/category/CategoryProperties.vue @@ -0,0 +1,48 @@ + + + + + diff --git a/frontend-vue3/src/components/category/CategoryTemplate.vue b/frontend-vue3/src/components/category/CategoryTemplate.vue new file mode 100644 index 0000000000..54e7e2cfd4 --- /dev/null +++ b/frontend-vue3/src/components/category/CategoryTemplate.vue @@ -0,0 +1,138 @@ + + + + + diff --git a/frontend-vue3/src/components/checklist/ChecklistCreate.vue b/frontend-vue3/src/components/checklist/ChecklistCreate.vue new file mode 100644 index 0000000000..8522568ec7 --- /dev/null +++ b/frontend-vue3/src/components/checklist/ChecklistCreate.vue @@ -0,0 +1,104 @@ + + + + + diff --git a/frontend-vue3/src/components/checklist/ChecklistDetail.vue b/frontend-vue3/src/components/checklist/ChecklistDetail.vue new file mode 100644 index 0000000000..d834688d1c --- /dev/null +++ b/frontend-vue3/src/components/checklist/ChecklistDetail.vue @@ -0,0 +1,137 @@ + + + diff --git a/frontend-vue3/src/components/checklist/ChecklistItemCreate.vue b/frontend-vue3/src/components/checklist/ChecklistItemCreate.vue new file mode 100644 index 0000000000..3537f6859d --- /dev/null +++ b/frontend-vue3/src/components/checklist/ChecklistItemCreate.vue @@ -0,0 +1,83 @@ + + + + + diff --git a/frontend-vue3/src/components/checklist/ChecklistItemEdit.vue b/frontend-vue3/src/components/checklist/ChecklistItemEdit.vue new file mode 100644 index 0000000000..056658fa68 --- /dev/null +++ b/frontend-vue3/src/components/checklist/ChecklistItemEdit.vue @@ -0,0 +1,134 @@ + + + + + diff --git a/frontend-vue3/src/components/checklist/ChecklistItemParent.vue b/frontend-vue3/src/components/checklist/ChecklistItemParent.vue new file mode 100644 index 0000000000..7bc1926990 --- /dev/null +++ b/frontend-vue3/src/components/checklist/ChecklistItemParent.vue @@ -0,0 +1,159 @@ + + + + + diff --git a/frontend-vue3/src/components/checklist/ChecklistOverview.vue b/frontend-vue3/src/components/checklist/ChecklistOverview.vue new file mode 100644 index 0000000000..6f45701479 --- /dev/null +++ b/frontend-vue3/src/components/checklist/ChecklistOverview.vue @@ -0,0 +1,55 @@ + + + diff --git a/frontend-vue3/src/components/checklist/SortableChecklist.vue b/frontend-vue3/src/components/checklist/SortableChecklist.vue new file mode 100644 index 0000000000..c6b71ffd8c --- /dev/null +++ b/frontend-vue3/src/components/checklist/SortableChecklist.vue @@ -0,0 +1,205 @@ + + + + + diff --git a/frontend-vue3/src/components/checklist/SortableChecklistItem.vue b/frontend-vue3/src/components/checklist/SortableChecklistItem.vue new file mode 100644 index 0000000000..973951a0a0 --- /dev/null +++ b/frontend-vue3/src/components/checklist/SortableChecklistItem.vue @@ -0,0 +1,94 @@ + + + + + diff --git a/frontend-vue3/src/components/collaborator/CollaboratorCreate.vue b/frontend-vue3/src/components/collaborator/CollaboratorCreate.vue new file mode 100644 index 0000000000..b05140ace3 --- /dev/null +++ b/frontend-vue3/src/components/collaborator/CollaboratorCreate.vue @@ -0,0 +1,87 @@ + + + + + diff --git a/frontend-vue3/src/components/collaborator/CollaboratorEdit.vue b/frontend-vue3/src/components/collaborator/CollaboratorEdit.vue new file mode 100644 index 0000000000..a39c68bad2 --- /dev/null +++ b/frontend-vue3/src/components/collaborator/CollaboratorEdit.vue @@ -0,0 +1,232 @@ + + + + + diff --git a/frontend-vue3/src/components/collaborator/CollaboratorForm.vue b/frontend-vue3/src/components/collaborator/CollaboratorForm.vue new file mode 100644 index 0000000000..dc2a926beb --- /dev/null +++ b/frontend-vue3/src/components/collaborator/CollaboratorForm.vue @@ -0,0 +1,178 @@ + + + + + diff --git a/frontend-vue3/src/components/collaborator/CollaboratorList.vue b/frontend-vue3/src/components/collaborator/CollaboratorList.vue new file mode 100644 index 0000000000..bc24af469c --- /dev/null +++ b/frontend-vue3/src/components/collaborator/CollaboratorList.vue @@ -0,0 +1,76 @@ + + + + + diff --git a/frontend-vue3/src/components/collaborator/CollaboratorListItem.vue b/frontend-vue3/src/components/collaborator/CollaboratorListItem.vue new file mode 100644 index 0000000000..c80abb2e25 --- /dev/null +++ b/frontend-vue3/src/components/collaborator/CollaboratorListItem.vue @@ -0,0 +1,85 @@ + + + + + diff --git a/frontend-vue3/src/components/collaborator/PromptCollaboratorDeactivate.vue b/frontend-vue3/src/components/collaborator/PromptCollaboratorDeactivate.vue new file mode 100644 index 0000000000..89caf34be1 --- /dev/null +++ b/frontend-vue3/src/components/collaborator/PromptCollaboratorDeactivate.vue @@ -0,0 +1,80 @@ + + + + + diff --git a/frontend-vue3/src/components/collaborator/isOwnCampCollaboration.js b/frontend-vue3/src/components/collaborator/isOwnCampCollaboration.js new file mode 100644 index 0000000000..1d6ef659cc --- /dev/null +++ b/frontend-vue3/src/components/collaborator/isOwnCampCollaboration.js @@ -0,0 +1,19 @@ +/** + * @typedef Collaborator { + * user: () => { id: string }, + * } + * + * @typedef Auth { + * user: { id: string }, + * } + * + * @param {Collaborator} collaborator + * @param {Auth} auth + * @returns {boolean} + */ +export default function isOwnCampCollaboration(collaborator, auth) { + if (!(typeof collaborator.user === 'function')) { + return false + } + return auth.user?.id === collaborator.user().id +} diff --git a/frontend-vue3/src/components/dashboard/ActivityRow.vue b/frontend-vue3/src/components/dashboard/ActivityRow.vue new file mode 100644 index 0000000000..45c897e88e --- /dev/null +++ b/frontend-vue3/src/components/dashboard/ActivityRow.vue @@ -0,0 +1,203 @@ + + + + + diff --git a/frontend-vue3/src/components/dashboard/BooleanFilter.vue b/frontend-vue3/src/components/dashboard/BooleanFilter.vue new file mode 100644 index 0000000000..ced32fb1b4 --- /dev/null +++ b/frontend-vue3/src/components/dashboard/BooleanFilter.vue @@ -0,0 +1,19 @@ + + + diff --git a/frontend-vue3/src/components/dashboard/CountBadge.vue b/frontend-vue3/src/components/dashboard/CountBadge.vue new file mode 100644 index 0000000000..b565599a2a --- /dev/null +++ b/frontend-vue3/src/components/dashboard/CountBadge.vue @@ -0,0 +1,44 @@ + + + + + diff --git a/frontend-vue3/src/components/dashboard/FilterDivider.vue b/frontend-vue3/src/components/dashboard/FilterDivider.vue new file mode 100644 index 0000000000..ff1d156e3a --- /dev/null +++ b/frontend-vue3/src/components/dashboard/FilterDivider.vue @@ -0,0 +1,16 @@ + + + + + diff --git a/frontend-vue3/src/components/dashboard/SelectFilter.vue b/frontend-vue3/src/components/dashboard/SelectFilter.vue new file mode 100644 index 0000000000..77122cd7dc --- /dev/null +++ b/frontend-vue3/src/components/dashboard/SelectFilter.vue @@ -0,0 +1,141 @@ + + + diff --git a/frontend-vue3/src/components/dialog/DialogBase.vue b/frontend-vue3/src/components/dialog/DialogBase.vue new file mode 100644 index 0000000000..0ae5508643 --- /dev/null +++ b/frontend-vue3/src/components/dialog/DialogBase.vue @@ -0,0 +1,167 @@ + diff --git a/frontend-vue3/src/components/dialog/DialogBottomSheet.vue b/frontend-vue3/src/components/dialog/DialogBottomSheet.vue new file mode 100644 index 0000000000..95ce4a831d --- /dev/null +++ b/frontend-vue3/src/components/dialog/DialogBottomSheet.vue @@ -0,0 +1,150 @@ + + + diff --git a/frontend-vue3/src/components/dialog/DialogEntityDelete.vue b/frontend-vue3/src/components/dialog/DialogEntityDelete.vue new file mode 100644 index 0000000000..f56e37f7b1 --- /dev/null +++ b/frontend-vue3/src/components/dialog/DialogEntityDelete.vue @@ -0,0 +1,52 @@ + + + + + diff --git a/frontend-vue3/src/components/dialog/DialogForm.vue b/frontend-vue3/src/components/dialog/DialogForm.vue new file mode 100644 index 0000000000..16c6ade583 --- /dev/null +++ b/frontend-vue3/src/components/dialog/DialogForm.vue @@ -0,0 +1,160 @@ + + + + + diff --git a/frontend-vue3/src/components/dialog/DialogUiBase.vue b/frontend-vue3/src/components/dialog/DialogUiBase.vue new file mode 100644 index 0000000000..a150d5f0c6 --- /dev/null +++ b/frontend-vue3/src/components/dialog/DialogUiBase.vue @@ -0,0 +1,43 @@ + diff --git a/frontend-vue3/src/components/form/ServerError.vue b/frontend-vue3/src/components/form/ServerError.vue new file mode 100644 index 0000000000..e9a6fb04cf --- /dev/null +++ b/frontend-vue3/src/components/form/ServerError.vue @@ -0,0 +1,28 @@ + + + diff --git a/frontend-vue3/src/components/form/ServerErrorContent.vue b/frontend-vue3/src/components/form/ServerErrorContent.vue new file mode 100644 index 0000000000..c78629d4dd --- /dev/null +++ b/frontend-vue3/src/components/form/ServerErrorContent.vue @@ -0,0 +1,29 @@ + + + diff --git a/frontend-vue3/src/components/form/api/ApiCheckbox.vue b/frontend-vue3/src/components/form/api/ApiCheckbox.vue new file mode 100644 index 0000000000..c4add43c94 --- /dev/null +++ b/frontend-vue3/src/components/form/api/ApiCheckbox.vue @@ -0,0 +1,45 @@ + + + + + + + diff --git a/frontend-vue3/src/components/form/api/ApiColorField.vue b/frontend-vue3/src/components/form/api/ApiColorField.vue new file mode 100644 index 0000000000..99adae9d08 --- /dev/null +++ b/frontend-vue3/src/components/form/api/ApiColorField.vue @@ -0,0 +1,44 @@ + + + + + + + diff --git a/frontend-vue3/src/components/form/api/ApiColorPicker.vue b/frontend-vue3/src/components/form/api/ApiColorPicker.vue new file mode 100644 index 0000000000..ab4187fa8d --- /dev/null +++ b/frontend-vue3/src/components/form/api/ApiColorPicker.vue @@ -0,0 +1,41 @@ + + + + + + + diff --git a/frontend-vue3/src/components/form/api/ApiDatePicker.vue b/frontend-vue3/src/components/form/api/ApiDatePicker.vue new file mode 100644 index 0000000000..5fbce2f547 --- /dev/null +++ b/frontend-vue3/src/components/form/api/ApiDatePicker.vue @@ -0,0 +1,41 @@ + + + + + + + diff --git a/frontend-vue3/src/components/form/api/ApiForm.vue b/frontend-vue3/src/components/form/api/ApiForm.vue new file mode 100644 index 0000000000..e2ff169690 --- /dev/null +++ b/frontend-vue3/src/components/form/api/ApiForm.vue @@ -0,0 +1,21 @@ + + + diff --git a/frontend-vue3/src/components/form/api/ApiNumberField.vue b/frontend-vue3/src/components/form/api/ApiNumberField.vue new file mode 100644 index 0000000000..2ce6affc41 --- /dev/null +++ b/frontend-vue3/src/components/form/api/ApiNumberField.vue @@ -0,0 +1,55 @@ + + + + + + + diff --git a/frontend-vue3/src/components/form/api/ApiRichtext.vue b/frontend-vue3/src/components/form/api/ApiRichtext.vue new file mode 100644 index 0000000000..559af1fef3 --- /dev/null +++ b/frontend-vue3/src/components/form/api/ApiRichtext.vue @@ -0,0 +1,39 @@ + + + + + + + diff --git a/frontend-vue3/src/components/form/api/ApiSelect.vue b/frontend-vue3/src/components/form/api/ApiSelect.vue new file mode 100644 index 0000000000..ef45c04df2 --- /dev/null +++ b/frontend-vue3/src/components/form/api/ApiSelect.vue @@ -0,0 +1,66 @@ + + + + + + + diff --git a/frontend-vue3/src/components/form/api/ApiSortable.vue b/frontend-vue3/src/components/form/api/ApiSortable.vue new file mode 100644 index 0000000000..80fe07c586 --- /dev/null +++ b/frontend-vue3/src/components/form/api/ApiSortable.vue @@ -0,0 +1,111 @@ + + + + + diff --git a/frontend-vue3/src/components/form/api/ApiSwitch.vue b/frontend-vue3/src/components/form/api/ApiSwitch.vue new file mode 100644 index 0000000000..47ab4059b3 --- /dev/null +++ b/frontend-vue3/src/components/form/api/ApiSwitch.vue @@ -0,0 +1,45 @@ + + + + + + + diff --git a/frontend-vue3/src/components/form/api/ApiTextField.vue b/frontend-vue3/src/components/form/api/ApiTextField.vue new file mode 100644 index 0000000000..a216138b09 --- /dev/null +++ b/frontend-vue3/src/components/form/api/ApiTextField.vue @@ -0,0 +1,55 @@ + + + + + + + diff --git a/frontend-vue3/src/components/form/api/ApiTextarea.vue b/frontend-vue3/src/components/form/api/ApiTextarea.vue new file mode 100644 index 0000000000..52d8ca64db --- /dev/null +++ b/frontend-vue3/src/components/form/api/ApiTextarea.vue @@ -0,0 +1,44 @@ + + + + + + + diff --git a/frontend-vue3/src/components/form/api/ApiTimePicker.vue b/frontend-vue3/src/components/form/api/ApiTimePicker.vue new file mode 100644 index 0000000000..c25716bb51 --- /dev/null +++ b/frontend-vue3/src/components/form/api/ApiTimePicker.vue @@ -0,0 +1,41 @@ + + + + + + + diff --git a/frontend-vue3/src/components/form/api/ApiWrapper.vue b/frontend-vue3/src/components/form/api/ApiWrapper.vue new file mode 100644 index 0000000000..07c28f4169 --- /dev/null +++ b/frontend-vue3/src/components/form/api/ApiWrapper.vue @@ -0,0 +1,299 @@ + + + + + + + + + + + diff --git a/frontend-vue3/src/components/form/api/ApiWrapperAppend.vue b/frontend-vue3/src/components/form/api/ApiWrapperAppend.vue new file mode 100644 index 0000000000..d658066fe8 --- /dev/null +++ b/frontend-vue3/src/components/form/api/ApiWrapperAppend.vue @@ -0,0 +1,140 @@ + + + + + diff --git a/frontend-vue3/src/components/form/api/IconSuccess.vue b/frontend-vue3/src/components/form/api/IconSuccess.vue new file mode 100644 index 0000000000..0f8080fff9 --- /dev/null +++ b/frontend-vue3/src/components/form/api/IconSuccess.vue @@ -0,0 +1,48 @@ + + + + + diff --git a/frontend-vue3/src/components/form/api/__tests__/ApiCheckbox.spec.js b/frontend-vue3/src/components/form/api/__tests__/ApiCheckbox.spec.js new file mode 100644 index 0000000000..0cfa44a3e7 --- /dev/null +++ b/frontend-vue3/src/components/form/api/__tests__/ApiCheckbox.spec.js @@ -0,0 +1,98 @@ +import { describe, beforeEach, afterEach, vi, test, expect } from 'vitest' +import ApiCheckbox from '../ApiCheckbox.vue' +import ApiWrapper from '@/components/form/api/ApiWrapper.vue' +import Vue from 'vue' +import Vuetify from 'vuetify' +import flushPromises from 'flush-promises' +import formBaseComponents from '@/plugins/formBaseComponents' +import merge from 'lodash-es/merge' +import { ApiMock } from '@/components/form/api/__tests__/ApiMock' +import { i18n } from '@/plugins' +import { mount as mountComponent } from '@vue/test-utils' +import { waitForDebounce } from '@/test/util' + +Vue.use(Vuetify) +Vue.use(formBaseComponents) + +describe('An ApiCheckbox', () => { + let vuetify + let wrapper + let apiMock + + const path = 'test-field/123' + + beforeEach(() => { + vuetify = new Vuetify() + apiMock = ApiMock.create() + }) + + afterEach(() => { + vi.restoreAllMocks() + wrapper.destroy() + }) + + const mount = (options) => { + const app = Vue.component('App', { + components: { ApiCheckbox }, + props: { + path: { type: String, default: path }, + }, + template: ` +
+ +
+ `, + }) + apiMock.get().thenReturn(ApiMock.success(true).forPath(path)) + const defaultOptions = { + mocks: { + $tc: () => {}, + api: apiMock.getMocks(), + }, + } + return mountComponent(app, { + vuetify, + i18n, + attachTo: document.body, + ...merge(defaultOptions, options), + }) + } + + test('triggers api.patch and status update if input changes', async () => { + apiMock.patch().thenReturn(ApiMock.success(false)) + wrapper = mount() + + await flushPromises() + + const input = wrapper.find('input') + await input.trigger('click') + await input.trigger('submit') + + await waitForDebounce() + await flushPromises() + + expect(apiMock.getMocks().patch).toBeCalledTimes(1) + expect(wrapper.findComponent(ApiWrapper).vm.localValue).toBe(false) + }) + + test('updates state if value in store is refreshed and has new value', async () => { + wrapper = mount() + apiMock.get().thenReturn(ApiMock.success(false).forPath(path)) + + wrapper.findComponent(ApiWrapper).vm.reload() + + await waitForDebounce() + await flushPromises() + + expect(wrapper.findComponent(ApiWrapper).vm.localValue).toBe(false) + expect( + wrapper.find('input[type=checkbox]').element.getAttribute('aria-checked') + ).toBe('false') + }) +}) diff --git a/frontend-vue3/src/components/form/api/__tests__/ApiColorField.spec.js b/frontend-vue3/src/components/form/api/__tests__/ApiColorField.spec.js new file mode 100644 index 0000000000..134e705bac --- /dev/null +++ b/frontend-vue3/src/components/form/api/__tests__/ApiColorField.spec.js @@ -0,0 +1,93 @@ +import { describe, beforeEach, afterEach, vi, test, expect } from 'vitest' +import ApiColorField from '../ApiColorField.vue' +import { fireEvent, screen, waitFor } from '@testing-library/vue' +import { render } from '@/test/renderWithVuetify.js' +import user from '@testing-library/user-event' +import { ApiMock } from '@/components/form/api/__tests__/ApiMock' +import { extend } from 'vee-validate' +import { regex } from 'vee-validate/dist/rules' +import { ColorSpace, sRGB } from 'colorjs.io/fn' + +extend('regex', regex) + +ColorSpace.register(sRGB) +describe('An ApiColorField', () => { + let apiMock + + const FIELD_PATH = 'test-field/123' + const FIELD_LABEL = 'Test field' + const COLOR_1 = '#FF0000' + const COLOR_2 = '#FAFFAF' + + beforeEach(() => { + apiMock = ApiMock.create() + }) + + afterEach(() => { + vi.restoreAllMocks() + }) + + test('triggers api.patch and status update if input changes', async () => { + // given + apiMock.get().thenReturn(ApiMock.success(COLOR_1).forPath(FIELD_PATH)) + apiMock.patch().thenReturn(ApiMock.success(COLOR_2)) + render(ApiColorField, { + props: { + autoSave: false, + path: FIELD_PATH, + uri: 'test-field/123', + label: FIELD_LABEL, + required: true, + }, + mocks: { + api: apiMock.getMocks(), + }, + }) + + // when + const inputField = await screen.findByLabelText(FIELD_LABEL) + inputField.value = COLOR_2 + await fireEvent.input(inputField) + // click the button to open the picker + // click the save button + await waitFor(async () => { + await user.click(screen.getByLabelText('Speichern')) + }) + + // then + await waitFor(async () => { + const inputField = await screen.findByLabelText(FIELD_LABEL) + expect(inputField.value).toBe(COLOR_2) + expect(apiMock.getMocks().patch).toBeCalledTimes(1) + }) + }) + + test('updates state if value in store is refreshed and has new value', async () => { + // given + apiMock.get().thenReturn(ApiMock.networkError().forPath(FIELD_PATH)) + render(ApiColorField, { + props: { + autoSave: false, + path: FIELD_PATH, + uri: 'test-field/123', + label: FIELD_LABEL, + required: true, + }, + mocks: { + api: apiMock.getMocks(), + }, + }) + await screen.findByText('A network error occurred.') + expect((await screen.findByLabelText(FIELD_LABEL)).value).not.toBe(COLOR_1) + const retryButton = await screen.findByText('Erneut versuchen') + apiMock.get().thenReturn(ApiMock.success(COLOR_1).forPath(FIELD_PATH)) + + // when + await user.click(retryButton) + + // then + await waitFor(async () => { + expect((await screen.findByLabelText(FIELD_LABEL)).value).toBe(COLOR_1) + }) + }) +}) diff --git a/frontend-vue3/src/components/form/api/__tests__/ApiColorPicker.spec.js b/frontend-vue3/src/components/form/api/__tests__/ApiColorPicker.spec.js new file mode 100644 index 0000000000..c8e67f30a6 --- /dev/null +++ b/frontend-vue3/src/components/form/api/__tests__/ApiColorPicker.spec.js @@ -0,0 +1,95 @@ +import { describe, beforeEach, afterEach, vi, test, expect } from 'vitest' +import ApiColorPicker from '../ApiColorPicker.vue' +import { screen, waitFor } from '@testing-library/vue' +import { render } from '@/test/renderWithVuetify.js' +import user from '@testing-library/user-event' +import { ApiMock } from '@/components/form/api/__tests__/ApiMock' +import { extend } from 'vee-validate' +import { regex } from 'vee-validate/dist/rules' +import { ColorSpace, sRGB } from 'colorjs.io/fn' + +extend('regex', regex) + +ColorSpace.register(sRGB) +describe('An ApiColorPicker', () => { + let apiMock + + const FIELD_PATH = 'test-field/123' + const FIELD_LABEL = 'Test field' + const COLOR_1 = '#FF0000' + const COLOR_2 = '#FAFFAF' + const PICKER_BUTTON_LABEL_TEXT = 'Dialog öffnen, um eine Farbe für Test field zu wählen' + + beforeEach(() => { + apiMock = ApiMock.create() + }) + + afterEach(() => { + vi.restoreAllMocks() + }) + + test('triggers api.patch and status update if input changes', async () => { + // given + apiMock.get().thenReturn(ApiMock.success(COLOR_1).forPath(FIELD_PATH)) + apiMock.patch().thenReturn(ApiMock.success(COLOR_2)) + const { container } = render(ApiColorPicker, { + props: { + autoSave: false, + path: FIELD_PATH, + uri: 'test-field/123', + label: FIELD_LABEL, + required: true, + }, + mocks: { + api: apiMock.getMocks(), + }, + }) + + // when + // click the button to open the picker + await user.click(screen.getByLabelText(PICKER_BUTTON_LABEL_TEXT)) + // click inside the color picker canvas to select a different color + const canvas = container.querySelector('canvas') + await user.click(canvas, { clientX: 10, clientY: 10 }) + // click the save button + await waitFor(async () => { + await user.click(screen.getByLabelText('Speichern')) + }) + + // then + await waitFor(async () => { + const inputField = await screen.findByLabelText(FIELD_LABEL) + expect(inputField.value).toBe(COLOR_2) + expect(apiMock.getMocks().patch).toBeCalledTimes(1) + }) + }) + + test('updates state if value in store is refreshed and has new value', async () => { + // given + apiMock.get().thenReturn(ApiMock.networkError().forPath(FIELD_PATH)) + render(ApiColorPicker, { + props: { + autoSave: false, + path: FIELD_PATH, + uri: 'test-field/123', + label: FIELD_LABEL, + required: true, + }, + mocks: { + api: apiMock.getMocks(), + }, + }) + await screen.findByText('A network error occurred.') + expect((await screen.findByLabelText(FIELD_LABEL)).value).not.toBe(COLOR_1) + const retryButton = await screen.findByText('Erneut versuchen') + apiMock.get().thenReturn(ApiMock.success(COLOR_1).forPath(FIELD_PATH)) + + // when + await user.click(retryButton) + + // then + await waitFor(async () => { + expect((await screen.findByLabelText(FIELD_LABEL)).value).toBe(COLOR_1) + }) + }) +}) diff --git a/frontend-vue3/src/components/form/api/__tests__/ApiDatePicker.spec.js b/frontend-vue3/src/components/form/api/__tests__/ApiDatePicker.spec.js new file mode 100644 index 0000000000..c1a7afbaf5 --- /dev/null +++ b/frontend-vue3/src/components/form/api/__tests__/ApiDatePicker.spec.js @@ -0,0 +1,87 @@ +import { describe, beforeEach, afterEach, vi, test, expect, it } from 'vitest' +import ApiDatePicker from '../ApiDatePicker.vue' +import { screen, waitFor } from '@testing-library/vue' +import { render, setTestLocale } from '@/test/renderWithVuetify.js' +import user from '@testing-library/user-event' +import { ApiMock } from '@/components/form/api/__tests__/ApiMock' + +describe('An ApiDatePicker', () => { + let apiMock + + const FIELD_PATH = 'test-field/123' + const FIELD_LABEL = 'Test field' + const DATE_1 = '2020-03-01' + const DATE_2 = '2020-03-19' + const PICKER_BUTTON_LABEL_TEXT = 'Dialog öffnen, um ein Datum für Test field zu wählen' + + beforeEach(() => { + setTestLocale('de') + apiMock = ApiMock.create() + }) + + afterEach(() => { + vi.restoreAllMocks() + }) + + it('triggers api.patch and status update if input changes', async () => { + // given + apiMock.get().thenReturn(ApiMock.success(DATE_1).forPath(FIELD_PATH)) + apiMock.patch().thenReturn(ApiMock.success(DATE_2)) + render(ApiDatePicker, { + props: { + autoSave: false, + path: FIELD_PATH, + uri: 'test-field/123', + label: FIELD_LABEL, + required: true, + }, + mocks: { + api: apiMock.getMocks(), + }, + }) + + // when + // click the button to open the picker + await user.click(screen.getByLabelText(PICKER_BUTTON_LABEL_TEXT)) + // click the 19th day of the month + await user.click(screen.getByText('19')) + // click the save button + await user.click(screen.getByLabelText('Speichern')) + + // then + await waitFor(async () => { + const inputField = await screen.findByLabelText(FIELD_LABEL) + expect(inputField.value).toBe('19.03.2020') + expect(apiMock.getMocks().patch).toBeCalledTimes(1) + }) + }) + + test('updates state if value in store is refreshed and has new value', async () => { + // given + apiMock.get().thenReturn(ApiMock.networkError().forPath(FIELD_PATH)) + render(ApiDatePicker, { + props: { + autoSave: false, + path: FIELD_PATH, + uri: 'test-field/123', + label: FIELD_LABEL, + required: true, + }, + mocks: { + api: apiMock.getMocks(), + }, + }) + await screen.findByText('A network error occurred.') + expect((await screen.findByLabelText(FIELD_LABEL)).value).not.toBe('01.03.2020') + const retryButton = await screen.findByText('Erneut versuchen') + apiMock.get().thenReturn(ApiMock.success(DATE_1).forPath(FIELD_PATH)) + + // when + await user.click(retryButton) + + // then + await waitFor(async () => { + expect((await screen.findByLabelText(FIELD_LABEL)).value).toBe('01.03.2020') + }) + }) +}) diff --git a/frontend-vue3/src/components/form/api/__tests__/ApiMock.js b/frontend-vue3/src/components/form/api/__tests__/ApiMock.js new file mode 100644 index 0000000000..96eb8438aa --- /dev/null +++ b/frontend-vue3/src/components/form/api/__tests__/ApiMock.js @@ -0,0 +1,125 @@ +import { vi } from 'vitest' + +function mockPromiseResolving(value) { + return new Promise((resolve) => { + const timer = setTimeout(() => { + clearTimeout(timer) + resolve(value) + }, 100) + }) +} + +class MockStubbing { + constructor(path, value) { + this._path = path + this._value = value + } + + forPath(path) { + this._path = path + return this + } + + get path() { + return this._path + } + + get value() { + return this._value + } +} + +class NetworkErrorMockStubbing extends MockStubbing { + constructor() { + super() + } +} + +class ApiMockState { + constructor() { + this._get = vi.fn() + this._patch = vi.fn() + } + + getMocks() { + return { + get: this._get, + patch: this._patch, + } + } + + get() { + const apiMock = this + return { + thenReturn(mockStubbing) { + if (!(mockStubbing instanceof MockStubbing)) { + throw new Error('apiMock must be instance of MockStubbing') + } + if (mockStubbing instanceof NetworkErrorMockStubbing) { + if (mockStubbing.path === undefined || mockStubbing.value !== undefined) { + throw new Error('path must be defined and value must be undefined') + } + const result = { + _meta: { + load: Promise.reject({ + name: 'Network error', + message: 'A network error occurred.', + }), + }, + } + result[mockStubbing.path] = () => result + apiMock._get.mockReturnValue(result) + return this + } + if (mockStubbing.path === undefined || mockStubbing.value === undefined) { + throw new Error('path and value must be defined') + } + apiMock._get.mockReturnValue({ + [mockStubbing.path]: mockStubbing.value, + _meta: { + load: Promise.resolve(mockStubbing.value), + }, + }) + return this + }, + } + } + + patch() { + const apiMock = this + return { + thenReturn(mockStubbing) { + if (!(mockStubbing instanceof MockStubbing)) { + throw new Error('apiMock must be instance of MockStubbing') + } + if (mockStubbing instanceof NetworkErrorMockStubbing) { + apiMock._patch.mockImplementation(() => { + throw { + name: 'NetworkError', + message: 'A network error occurred.', + } + }) + return this + } + if (mockStubbing.path !== undefined || mockStubbing.value === undefined) { + throw new Error('path must be undefined and value must be defined') + } + apiMock._patch.mockReturnValue(mockPromiseResolving(mockStubbing.value)) + return this + }, + } + } +} + +export class ApiMock { + static create() { + return new ApiMockState() + } + + static success(value) { + return new MockStubbing(undefined, value) + } + static networkError() { + return new NetworkErrorMockStubbing() + } +} diff --git a/frontend-vue3/src/components/form/api/__tests__/ApiNumberField.spec.js b/frontend-vue3/src/components/form/api/__tests__/ApiNumberField.spec.js new file mode 100644 index 0000000000..35735a5240 --- /dev/null +++ b/frontend-vue3/src/components/form/api/__tests__/ApiNumberField.spec.js @@ -0,0 +1,96 @@ +import { describe, beforeEach, afterEach, vi, test, expect } from 'vitest' +import ApiNumberField from '../ApiNumberField.vue' +import ApiWrapper from '@/components/form/api/ApiWrapper.vue' +import Vue from 'vue' +import Vuetify from 'vuetify' +import flushPromises from 'flush-promises' +import formBaseComponents from '@/plugins/formBaseComponents' +import merge from 'lodash-es/merge' +import { ApiMock } from '@/components/form/api/__tests__/ApiMock' +import { i18n } from '@/plugins' +import { mount as mountComponent } from '@vue/test-utils' +import { waitForDebounce } from '@/test/util' + +Vue.use(Vuetify) +Vue.use(formBaseComponents) + +describe('An ApiNumberField', () => { + let vuetify + let wrapper + let apiMock + + const path = 'test-field/123' + const NUMBER_1 = 1.2 + const NUMBER_1_string = '1.2' + + beforeEach(() => { + vuetify = new Vuetify() + apiMock = ApiMock.create() + }) + + afterEach(() => { + vi.restoreAllMocks() + wrapper.destroy() + }) + + const mount = (options) => { + const app = Vue.component('App', { + components: { ApiNumberField }, + props: { + path: { type: String, default: path }, + }, + template: `
+ +
`, + }) + apiMock.get().thenReturn(ApiMock.success(NUMBER_1).forPath(path)) + const defaultOptions = { + mocks: { + $tc: () => {}, + api: apiMock.getMocks(), + }, + } + return mountComponent(app, { + vuetify, + i18n, + attachTo: document.body, + ...merge(defaultOptions, options), + }) + } + + test('triggers api.patch and status update if input changes', async () => { + apiMock.patch().thenReturn(ApiMock.success(NUMBER_1)) + wrapper = mount() + + await flushPromises() + + const input = wrapper.find('input') + await input.setValue(NUMBER_1) + await input.trigger('submit') + + await waitForDebounce() + await flushPromises() + + expect(apiMock.getMocks().patch).toBeCalledTimes(1) + expect(wrapper.findComponent(ApiWrapper).vm.parsedLocalValue).toBe(NUMBER_1) + }) + + test('updates state if value in store is refreshed and has new value', async () => { + wrapper = mount() + apiMock.get().thenReturn(ApiMock.success(NUMBER_1).forPath(path)) + + wrapper.findComponent(ApiWrapper).vm.reload() + + await waitForDebounce() + await flushPromises() + + expect(wrapper.findComponent(ApiWrapper).vm.parsedLocalValue).toBe(NUMBER_1) + expect(wrapper.find('input[type=text]').element.value).toBe(NUMBER_1_string) + }) +}) diff --git a/frontend-vue3/src/components/form/api/__tests__/ApiSelect.spec.js b/frontend-vue3/src/components/form/api/__tests__/ApiSelect.spec.js new file mode 100644 index 0000000000..9408d4d20b --- /dev/null +++ b/frontend-vue3/src/components/form/api/__tests__/ApiSelect.spec.js @@ -0,0 +1,113 @@ +// Libraries +import { describe, beforeEach, afterEach, vi, test, expect } from 'vitest' +import Vue from 'vue' +import Vuetify from 'vuetify' + +import formBaseComponents from '@/plugins/formBaseComponents' + +import { mount as mountComponent } from '@vue/test-utils' +import ApiSelect from '../ApiSelect.vue' +import flushPromises from 'flush-promises' +import ApiWrapper from '@/components/form/api/ApiWrapper.vue' +import { i18n } from '@/plugins' +import merge from 'lodash-es/merge' +import { ApiMock } from '@/components/form/api/__tests__/ApiMock' +import { waitForDebounce } from '@/test/util' + +Vue.use(Vuetify) +Vue.use(formBaseComponents) + +describe('An ApiSelect', () => { + let vuetify + let wrapper + let apiMock + + const path = 'test-field/123' + + const FIRST_OPTION = { + value: 1, + text: 'firstOption', + } + const SECOND_OPTION = { + value: '2', + text: 'secondOption', + } + + const selectValues = [FIRST_OPTION, SECOND_OPTION] + + beforeEach(() => { + vuetify = new Vuetify() + apiMock = ApiMock.create() + }) + + afterEach(() => { + vi.restoreAllMocks() + wrapper.destroy() + }) + + const mount = (options) => { + const app = Vue.component('App', { + components: { ApiSelect }, + props: { + path: { type: String, default: path }, + selectValues: { type: Array, default: () => selectValues }, + }, + template: ` +
+ +
+ `, + }) + apiMock.get().thenReturn(ApiMock.success(FIRST_OPTION.value).forPath(path)) + const defaultOptions = { + mocks: { + $tc: () => {}, + api: apiMock.getMocks(), + }, + } + return mountComponent(app, { + vuetify, + i18n, + attachTo: document.body, + ...merge(defaultOptions, options), + }) + } + + test('triggers api.patch and status update if input changes', async () => { + apiMock.patch().thenReturn(ApiMock.success(SECOND_OPTION.value)) + wrapper = mount() + + await flushPromises() + + await wrapper.find('.v-input__slot').trigger('click') + await wrapper.findAll('[role="option"]').at(1).trigger('click') + await wrapper.find('input').trigger('submit') + + await waitForDebounce() + await flushPromises() + + expect(apiMock.getMocks().patch).toBeCalledTimes(1) + expect(wrapper.findComponent(ApiWrapper).vm.localValue).toBe(SECOND_OPTION.value) + }) + + test('updates state if value in store is refreshed and has new value', async () => { + wrapper = mount() + apiMock.get().thenReturn(ApiMock.success(SECOND_OPTION.value).forPath(path)) + + wrapper.findComponent(ApiWrapper).vm.reload() + + await waitForDebounce() + await flushPromises() + + expect(wrapper.findComponent(ApiWrapper).vm.localValue).toBe(SECOND_OPTION.value) + expect(wrapper.html()).toContain(SECOND_OPTION.text) + expect(wrapper.html()).not.toContain(FIRST_OPTION.text) + }) +}) diff --git a/frontend-vue3/src/components/form/api/__tests__/ApiSwitch.spec.js b/frontend-vue3/src/components/form/api/__tests__/ApiSwitch.spec.js new file mode 100644 index 0000000000..e399071663 --- /dev/null +++ b/frontend-vue3/src/components/form/api/__tests__/ApiSwitch.spec.js @@ -0,0 +1,98 @@ +import { describe, beforeEach, afterEach, vi, test, expect } from 'vitest' +import ApiSwitch from '../ApiSwitch.vue' +import ApiWrapper from '@/components/form/api/ApiWrapper.vue' +import Vue from 'vue' +import Vuetify from 'vuetify' +import flushPromises from 'flush-promises' +import formBaseComponents from '@/plugins/formBaseComponents' +import merge from 'lodash-es/merge' +import { ApiMock } from '@/components/form/api/__tests__/ApiMock' +import { i18n } from '@/plugins' +import { mount as mountComponent } from '@vue/test-utils' +import { waitForDebounce } from '@/test/util' + +Vue.use(Vuetify) +Vue.use(formBaseComponents) + +describe('An ApiSwitch', () => { + let vuetify + let wrapper + let apiMock + + const path = 'test-field/123' + + beforeEach(() => { + vuetify = new Vuetify() + apiMock = ApiMock.create() + }) + + afterEach(() => { + vi.restoreAllMocks() + wrapper.destroy() + }) + + const mount = (options) => { + const app = Vue.component('App', { + components: { ApiSwitch }, + props: { + path: { type: String, default: path }, + }, + template: ` +
+ +
+ `, + }) + apiMock.get().thenReturn(ApiMock.success(true).forPath(path)) + const defaultOptions = { + mocks: { + $tc: () => {}, + api: apiMock.getMocks(), + }, + } + return mountComponent(app, { + vuetify, + i18n, + attachTo: document.body, + ...merge(defaultOptions, options), + }) + } + + test('triggers api.patch and status update if input changes', async () => { + apiMock.patch().thenReturn(ApiMock.success(false)) + wrapper = mount() + + await flushPromises() + + const input = wrapper.find('input') + await input.trigger('click') + await input.trigger('submit') + + await waitForDebounce() + await flushPromises() + + expect(apiMock.getMocks().patch).toBeCalledTimes(1) + expect(wrapper.findComponent(ApiWrapper).vm.localValue).toBe(false) + }) + + test('updates state if value in store is refreshed and has new value', async () => { + wrapper = mount() + apiMock.get().thenReturn(ApiMock.success(false).forPath(path)) + + wrapper.findComponent(ApiWrapper).vm.reload() + + await waitForDebounce() + await flushPromises() + + expect(wrapper.findComponent(ApiWrapper).vm.localValue).toBe(false) + expect( + wrapper.find('input[type=checkbox]').element.getAttribute('aria-checked') + ).toBe('false') + }) +}) diff --git a/frontend-vue3/src/components/form/api/__tests__/ApiTextField.spec.js b/frontend-vue3/src/components/form/api/__tests__/ApiTextField.spec.js new file mode 100644 index 0000000000..734dfba461 --- /dev/null +++ b/frontend-vue3/src/components/form/api/__tests__/ApiTextField.spec.js @@ -0,0 +1,98 @@ +import { describe, beforeEach, afterEach, vi, test, expect } from 'vitest' +import ApiTextField from '../ApiTextField.vue' +import ApiWrapper from '@/components/form/api/ApiWrapper.vue' +import Vue from 'vue' +import Vuetify from 'vuetify' +import flushPromises from 'flush-promises' +import formBaseComponents from '@/plugins/formBaseComponents' +import merge from 'lodash-es/merge' +import { ApiMock } from '@/components/form/api/__tests__/ApiMock' +import { i18n } from '@/plugins' +import { mount as mountComponent } from '@vue/test-utils' +import { waitForDebounce } from '@/test/util' + +Vue.use(Vuetify) +Vue.use(formBaseComponents) + +describe('An ApiTextField', () => { + let vuetify + let wrapper + let apiMock + + const path = 'test-field/123' + const TEXT_1 = 'some text' + const TEXT_2 = 'another text' + + beforeEach(() => { + vuetify = new Vuetify() + apiMock = ApiMock.create() + }) + + afterEach(() => { + vi.restoreAllMocks() + wrapper.destroy() + }) + + const mount = (options) => { + const app = Vue.component('App', { + components: { ApiTextField }, + props: { + path: { type: String, default: path }, + }, + template: `
+ +
`, + }) + apiMock.get().thenReturn(ApiMock.success(TEXT_1).forPath(path)) + const defaultOptions = { + mocks: { + $tc: () => {}, + api: apiMock.getMocks(), + }, + } + return mountComponent(app, { + vuetify, + i18n, + attachTo: document.body, + ...merge(defaultOptions, options), + }) + } + + describe('text', () => { + test('triggers api.patch and status update if input changes', async () => { + apiMock.patch().thenReturn(ApiMock.success(TEXT_2)) + wrapper = mount() + + await flushPromises() + + const input = wrapper.find('input') + await input.setValue(TEXT_2) + await input.trigger('submit') + + await waitForDebounce() + await flushPromises() + + expect(apiMock.getMocks().patch).toBeCalledTimes(1) + expect(wrapper.findComponent(ApiWrapper).vm.localValue).toBe(TEXT_2) + }) + + test('updates state if value in store is refreshed and has new value', async () => { + wrapper = mount() + apiMock.get().thenReturn(ApiMock.success(TEXT_2).forPath(path)) + + wrapper.findComponent(ApiWrapper).vm.reload() + + await waitForDebounce() + await flushPromises() + + expect(wrapper.findComponent(ApiWrapper).vm.localValue).toBe(TEXT_2) + expect(wrapper.find('input[type=text]').element.value).toBe(TEXT_2) + }) + }) +}) diff --git a/frontend-vue3/src/components/form/api/__tests__/ApiTextarea.spec.js b/frontend-vue3/src/components/form/api/__tests__/ApiTextarea.spec.js new file mode 100644 index 0000000000..c4bf3dfd20 --- /dev/null +++ b/frontend-vue3/src/components/form/api/__tests__/ApiTextarea.spec.js @@ -0,0 +1,85 @@ +import { describe, beforeEach, afterEach, vi, test, expect } from 'vitest' +import ApiTextarea from '@/components/form/api/ApiTextarea.vue' +import ApiWrapper from '@/components/form/api/ApiWrapper.vue' +import Vue from 'vue' +import Vuetify from 'vuetify' +import flushPromises from 'flush-promises' +import formBaseComponents from '@/plugins/formBaseComponents' +import merge from 'lodash-es/merge' +import { ApiMock } from '@/components/form/api/__tests__/ApiMock' +import { i18n } from '@/plugins' +import { mount as mountComponent } from '@vue/test-utils' +import { waitForDebounce } from '@/test/util' +import { mockEventClass } from '@/test/mockEventClass' + +Vue.use(Vuetify) +Vue.use(formBaseComponents) + +mockEventClass('ClipboardEvent') +mockEventClass('DragEvent') + +describe('An ApiTextarea', () => { + let vuetify + let wrapper + let apiMock + + const path = 'test-field/123' + const TEXT_1 = 'some text' + const TEXT_2 = 'another text' + + beforeEach(() => { + vuetify = new Vuetify() + apiMock = ApiMock.create() + }) + + afterEach(() => { + vi.restoreAllMocks() + wrapper.destroy() + }) + + const mount = (options) => { + const app = Vue.component('App', { + components: { ApiTextarea }, + props: { + path: { type: String, default: path }, + }, + template: ` +
+ +
`, + }) + apiMock.get().thenReturn(ApiMock.success(TEXT_1).forPath(path)) + const defaultOptions = { + mocks: { + $tc: () => {}, + api: apiMock.getMocks(), + }, + } + return mountComponent(app, { + vuetify, + i18n, + attachTo: document.body, + ...merge(defaultOptions, options), + }) + } + + test('updates state if value in store is refreshed and has new value', async () => { + wrapper = mount() + apiMock.get().thenReturn(ApiMock.success(TEXT_2).forPath(path)) + + wrapper.findComponent(ApiWrapper).vm.reload() + + await waitForDebounce() + await flushPromises() + + expect(wrapper.find('div.e-form-container').element.getAttribute('value')).toBe( + TEXT_2 + ) + }) +}) diff --git a/frontend-vue3/src/components/form/api/__tests__/ApiTimePicker.spec.js b/frontend-vue3/src/components/form/api/__tests__/ApiTimePicker.spec.js new file mode 100644 index 0000000000..463ba9b04f --- /dev/null +++ b/frontend-vue3/src/components/form/api/__tests__/ApiTimePicker.spec.js @@ -0,0 +1,89 @@ +import { describe, beforeEach, afterEach, vi, expect, it } from 'vitest' +import ApiTimePicker from '../ApiTimePicker.vue' +import { screen, waitFor } from '@testing-library/vue' +import { render, setTestLocale } from '@/test/renderWithVuetify.js' +import user from '@testing-library/user-event' +import { ApiMock } from '@/components/form/api/__tests__/ApiMock' + +describe('An ApiTimePicker', () => { + let apiMock + + const FIELD_PATH = 'test-field/123' + const FIELD_LABEL = 'Test field' + const TIME_1 = '2037-07-18T09:52:00+00:00' + const TIME_2 = '2037-07-18T00:52:00+00:00' + const PICKER_BUTTON_LABEL_TEXT = 'Dialog öffnen, um eine Zeit für Test field zu wählen' + + beforeEach(() => { + setTestLocale('de') + apiMock = ApiMock.create() + }) + + afterEach(() => { + vi.restoreAllMocks() + }) + + it('triggers api.patch and status update if input changes', async () => { + // given + apiMock.get().thenReturn(ApiMock.success(TIME_1).forPath(FIELD_PATH)) + apiMock.patch().thenReturn(ApiMock.success(TIME_2)) + render(ApiTimePicker, { + props: { + autoSave: false, + path: FIELD_PATH, + uri: 'test-field/123', + label: FIELD_LABEL, + required: true, + }, + mocks: { + api: apiMock.getMocks(), + }, + }) + + // when + // click the button to open the picker + await user.click(screen.getByLabelText(PICKER_BUTTON_LABEL_TEXT)) + // Click the 0th hour. We can only click this one, because + // testing library is missing the vuetify styles, and all the + // number elements overlap + await user.click(await screen.findByText('0')) + // click the save button + await user.click(screen.getByLabelText('Speichern')) + + // then + await waitFor(async () => { + const inputField = await screen.findByLabelText(FIELD_LABEL) + expect(inputField.value).toBe('00:52') + expect(apiMock.getMocks().patch).toBeCalledTimes(1) + }) + }) + + it('updates state if value in store is refreshed and has new value', async () => { + // given + apiMock.get().thenReturn(ApiMock.networkError().forPath(FIELD_PATH)) + render(ApiTimePicker, { + props: { + autoSave: false, + path: FIELD_PATH, + uri: 'test-field/123', + label: FIELD_LABEL, + required: true, + }, + mocks: { + api: apiMock.getMocks(), + }, + }) + await screen.findByText('A network error occurred.') + expect((await screen.findByLabelText(FIELD_LABEL)).value).not.toBe('09:52') + const retryButton = await screen.findByText('Erneut versuchen') + apiMock.get().thenReturn(ApiMock.success(TIME_1).forPath(FIELD_PATH)) + + // when + await user.click(retryButton) + + // then + await waitFor(async () => { + expect((await screen.findByLabelText(FIELD_LABEL)).value).toBe('09:52') + }) + }) +}) diff --git a/frontend-vue3/src/components/form/api/__tests__/ApiWrapper.spec.js b/frontend-vue3/src/components/form/api/__tests__/ApiWrapper.spec.js new file mode 100644 index 0000000000..05304c5cdd --- /dev/null +++ b/frontend-vue3/src/components/form/api/__tests__/ApiWrapper.spec.js @@ -0,0 +1,552 @@ +import { afterEach, beforeEach, describe, expect, test, vi } from 'vitest' +import Vue from 'vue' +import Vuetify from 'vuetify' +import flushPromises from 'flush-promises' +import { createLocalVue, shallowMount } from '@vue/test-utils' +import veeValidatePlugin from '@/plugins/veeValidate' +import ApiWrapper from '../ApiWrapper.vue' +import { VBtn, VForm } from 'vuetify/components' +import { ValidationObserver } from 'vee-validate' + +const { cloneDeep } = await vi.importActual('lodash-es') + +Vue.use(Vuetify) +Vue.use(veeValidatePlugin) +let vuetify + +let debounce +const resolveDebounce = () => debounce() + +vi.mock('lodash-es', async (importOriginal) => { + const lodash = await importOriginal() + return { + ...lodash, + debounce: (callback) => + function () { + return new Promise((resolve) => (debounce = resolve)).then(callback) + }, + set: lodash.set, + get: lodash.get, + } +}) + +let patch +const resolvePatch = (value) => patch(value) + +function resetPromises() { + patch = undefined +} + +// config factory +function createConfig(overrides) { + const mocks = { + api: { + patch: () => new Promise((resolve) => (patch = resolve)), + get: () => new Promise(), + }, + } + + const propsData = { + value: 'Test Value', + path: 'testField', + uri: '/testEntity/123', + label: 'Test Field', + } + + const stubs = { + VForm, + VBtn, + ValidationObserver, + } + + const scopedSlots = { + default: + '', + } + + const localVue = createLocalVue() + + return cloneDeep( + Object.assign({ mocks, propsData, vuetify, stubs, scopedSlots, localVue }, overrides) + ) +} + +beforeEach(() => { + resetPromises() + vi.useFakeTimers() +}) + +afterEach(() => { + vi.useRealTimers() +}) + +/** + * AutoSave = true + * External value + */ +describe('Testing ApiWrapper [autoSave=true; manual external value]', () => { + let wrapper + let vm + let config + let apiPatch + let validateResolveFunction + let validateCalled + + beforeEach(() => { + vuetify = new Vuetify() + + config = createConfig() + wrapper = shallowMount(ApiWrapper, config) + vm = wrapper.vm + + apiPatch = vi.spyOn(config.mocks.api, 'patch') + + validateCalled = new Promise((resolve) => (validateResolveFunction = resolve)) + + // mock validation Promise + const validate = vi.spyOn(vm.$refs.validationObserver, 'validate') + validate.mockImplementation(() => { + validateResolveFunction() + return true + }) + }) + + afterEach(() => { + wrapper?.destroy() + vi.resetAllMocks() + }) + + test('init correctly with default values', () => { + expect(vm.value).toBe(config.propsData.value) + expect(vm.dirty).toBe(false) + expect(vm.isSaving).toBe(false) + expect(vm.isLoading).toBe(false) + expect(vm.status).toBe('init') + expect(vm.autoSave).toBe(true) + + // no buttons expected in AutoSave Mode (which is default) + expect(wrapper.findAllComponents({ name: 'VBtn' })).toHaveLength(0) + }) + + test('calls api.patch after onInput was triggered', async () => { + const newValue = 'new value' + const newValueFromApi = 'new value' + + await vm.onInput(newValue) + + // value (from outside) is still the same + expect(vm.value).toBe(config.propsData.value) + + // local Value has changed and is dirty + expect(vm.dirty).toBe(true) + expect(vm.localValue).toBe(newValue) + + resolveDebounce() + await flushPromises() + + await validateCalled + + // saving started + expect(vm.isSaving).toBe(true) + expect(vm.dirty).toBe(true) + expect(vm.status).toBe('saving') + + // API patch method called + expect(apiPatch).toBeCalledTimes(1) + expect(apiPatch).toBeCalledWith(config.propsData.uri, { + [config.propsData.path]: newValue, + }) + + resolvePatch({}) + + // feedback changed return value from API & make sure it's taken over to localValue + await wrapper.setProps({ value: newValueFromApi }) + await wrapper.vm.$nextTick() + expect(vm.localValue).toBe(newValueFromApi) + expect(vm.dirty).toBe(false) + + // success state + expect(vm.status).toBe('success') + + // wait for success icon timer to finish + await vi.advanceTimersByTime(2000) + await flushPromises() + + // again in init state + expect(vm.status).toBe('init') + }) + + test('avoid double triggering of save for enter key', async () => { + // given + const input = wrapper.find('input') + + // when + await vm.onInput('new value') + await input.trigger('submit') // trigger submit event (simulates enter key) + + resolveDebounce() + await flushPromises() + + resolvePatch() + + // then + expect(apiPatch).toHaveBeenCalledTimes(1) + }) + + test('shows server error if api.patch failed', async () => { + // given + apiPatch.mockRejectedValueOnce(new Error('server error')) + + // when + await vm.onInput('new value') // Trigger patch + + resolveDebounce() + await flushPromises() + + // then + expect(vm.hasServerError).toBe(true) + expect(vm.errorMessages).toContain('server error') + }) + + test('can process server validation error', async () => { + const validationMsg = 'The input is less than 10 characters long' + apiPatch.mockRejectedValueOnce(new Error(validationMsg)) + + // when + await vm.onInput('new value') // Trigger patch + + resolveDebounce() + await flushPromises() + + // then + expect(vm.hasServerError).toBe(true) + expect(vm.errorMessages).toContain(validationMsg) + }) + + /* + test('shows error if `required` validation fails', async () => { + // given + wrapper.setProps({ required: true }) + + // when + await vm.onInput('') + + // then + expect(vm.hasValidationError).toBe(true) + expect(vm.errorMessages[0]).toMatch('is required') + }) */ + + /* + test('shows error if arbitrary validation fails & aborts save', async () => { + // given + wrapper.setProps({ validation: 'min:3|myOwnValidationRule' }) + validate.mockResolvedValue({ valid: false, errors: ['Validation failed'] }) + + // when + await vm.onInput('any value') + + // then + expect(validate).toHaveBeenCalledWith('any value', 'min:3|myOwnValidationRule', { name: 'Test Field' }) + expect(vm.hasValidationError).toBe(true) + expect(vm.errorMessages[0]).toMatch('Validation failed') + + // when + vm.save() + + // then + expect(apiPatch).not.toHaveBeenCalled() + }) + + test('clears error if arbitrary validation succedes', async () => { + // given + wrapper.setProps({ validation: 'required' }) + wrapper.vm.hasValidationError = true + validate.mockResolvedValue({ valid: true, errors: [] }) + + // when + await vm.onInput('any value') + + // then + expect(vm.hasValidationError).toBe(false) + expect(vm.errorMessages).toHaveLength(0) + }) */ +}) + +/** + * AutoSave = true + * Value from API + */ +describe('Testing ApiWrapper [autoSave=true; value from API]', () => { + let wrapper + let vm + let config + // let apiPatch + let apiGet + + beforeEach(() => { + vuetify = new Vuetify() + + config = createConfig() + delete config.propsData.value + + apiGet = vi.spyOn(config.mocks.api, 'get') + + apiGet.mockReturnValue({ + [config.propsData.path]: 'api value', + _meta: { + load: Promise.resolve(), + }, + }) + }) + + afterEach(() => { + wrapper?.destroy() + }) + + test('loads value from API (path = primitive value)', async () => { + // given + const loadingValue = () => ({}) + loadingValue.loading = true + apiGet.mockReturnValue({ + [config.propsData.path]: loadingValue, + _meta: { + loading: true, + load: Promise.resolve(), + }, + }) + + // when + wrapper = shallowMount(ApiWrapper, config) + vm = wrapper.vm + + // then + expect(vm.isLoading).toBe(true) + expect(vm.localValue).toBe(null) + + // given + apiGet.mockReturnValue({ + [config.propsData.path]: 'api value', + _meta: { + load: Promise.resolve(), + }, + }) + + // when + await flushPromises() // wait for load promise to resolve + + // then + expect(vm.hasFinishedLoading).toBe(true) + expect(vm.isLoading).toBe(false) + expect(vm.localValue).toBe('api value') + }) + + test('shows error when loading value from API fails', async () => { + // given + const loadingValue = () => ({}) + loadingValue._meta = { loading: true } + apiGet.mockReturnValue({ + [config.propsData.path]: loadingValue, + _meta: { + load: Promise.reject(new Error('loading error')), + loading: true, + }, + }) + wrapper = shallowMount(ApiWrapper, config) + vm = wrapper.vm + + // when + await flushPromises() // wait for load promise to resolve + + // then + expect(vm.hasFinishedLoading).toBe(false) + expect(vm.isLoading).toBe(false) + expect(vm.hasLoadingError).toBe(true) + expect(vm.errorMessages[0]).toMatch('loading error') + }) + + test('loads IRI from API (path = embedded entity)', async () => { + // given + const loadingValue = () => ({}) + loadingValue._meta = { loading: true } + apiGet.mockReturnValue({ + [config.propsData.path]: loadingValue, + _meta: { + load: Promise.resolve(), + loading: true, + }, + }) + + wrapper = shallowMount(ApiWrapper, config) + vm = wrapper.vm + + apiGet.mockReturnValue({ + [config.propsData.path]: () => ({ + _meta: { + self: '/iri/5', + }, + }), + _meta: { + load: Promise.resolve(), + }, + }) + + // when + await flushPromises() // wait for load promise to resolve + + // then + expect(vm.hasFinishedLoading).toBe(true) + expect(vm.isLoading).toBe(false) + expect(vm.localValue).toBe('/iri/5') + }) + + test('loads array of IRIs from API (path = embedded collection)', async () => { + // given + const loadingValue = () => ({}) + loadingValue._meta = { loading: true } + apiGet.mockReturnValue({ + [config.propsData.path]: loadingValue, + _meta: { + load: Promise.resolve(), + loading: true, + }, + }) + + wrapper = shallowMount(ApiWrapper, config) + vm = wrapper.vm + + apiGet.mockReturnValue({ + [config.propsData.path]: () => ({ + items: [ + { + _meta: { + self: '/iri/5', + }, + }, + { + _meta: { + self: '/iri/6', + }, + }, + ], + }), + _meta: { + load: Promise.resolve(), + }, + }) + + // when + await flushPromises() // wait for load promise to resolve + + // then + expect(vm.hasFinishedLoading).toBe(true) + expect(vm.isLoading).toBe(false) + expect(vm.localValue).toStrictEqual(['/iri/5', '/iri/6']) + }) +}) + +/** + * Manual mode + */ +describe('Testing ApiWrapper [autoSave=false]', () => { + let wrapper + let vm + let config + let apiPatch + + beforeEach(() => { + vuetify = new Vuetify() + + config = createConfig() + config.propsData.autoSave = false + + wrapper = shallowMount(ApiWrapper, config) + vm = wrapper.vm + + apiPatch = vi.spyOn(config.mocks.api, 'patch') + }) + + afterEach(() => { + wrapper?.destroy() + }) + + test('init correctly with default values', () => { + expect(vm.value).toBe(config.propsData.value) + expect(vm.dirty).toBe(false) + expect(vm.isSaving).toBe(false) + expect(vm.status).toBe('init') + expect(vm.autoSave).toBe(false) + }) + + test('clears dirty flag when local value matches external value', async () => { + // local change + await vm.onInput('new local value') + expect(vm.dirty).toBe(true) + + // new value from external --> local value will not be changed + await wrapper.setProps({ value: 'new external value #1' }) + expect(vm.localValue).toBe('new local value') + + // local change to same value as external value + await vm.onInput('new external value #1') + await vm.$nextTick() // needed for watcher to trigger + expect(vm.dirty).toBe(false) + + // new value from external --> local value will be changed + await wrapper.setProps({ value: 'new external value #2' }) + await vm.$nextTick() // needed for watcher to trigger + expect(vm.localValue).toBe('new external value #2') + }) + + test('resets value and errors when `reset` is called', async () => { + // when + await vm.onInput('new local value') + // vm.hasValidationError = true + + // then + expect(vm.dirty).toBe(true) + expect(vm.localValue).toBe('new local value') + + // when + await vm.reset() + + // then + expect(vm.dirty).toBe(false) + expect(vm.localValue).toBe('Test Value') + // expect(vm.hasValidationError).toBe(false) + }) + + test('trigger save with enter key', async () => { + // given + const input = wrapper.find('input') + + // when + await input.trigger('submit') + await vm.$nextTick() + await flushPromises() // resolve validation + + // then + expect(apiPatch).toHaveBeenCalled() + }) + + test('abort save in readonly mode', async () => { + // given + await wrapper.setProps({ readonly: true }) + + // when + await vm.save() + + // then + expect(apiPatch).not.toHaveBeenCalled() + }) + + test('abort save in disabled mode', async () => { + // given + await wrapper.setProps({ disabled: true }) + + // when + await vm.save() + + // then + expect(apiPatch).not.toHaveBeenCalled() + }) +}) diff --git a/frontend-vue3/src/components/form/base/BaseComponent.vue b/frontend-vue3/src/components/form/base/BaseComponent.vue new file mode 100644 index 0000000000..f553928038 --- /dev/null +++ b/frontend-vue3/src/components/form/base/BaseComponent.vue @@ -0,0 +1,45 @@ + + + diff --git a/frontend-vue3/src/components/form/base/BasePicker.vue b/frontend-vue3/src/components/form/base/BasePicker.vue new file mode 100644 index 0000000000..81b32a9a49 --- /dev/null +++ b/frontend-vue3/src/components/form/base/BasePicker.vue @@ -0,0 +1,239 @@ + + + + + diff --git a/frontend-vue3/src/components/form/base/ColorPicker/ColorSwatch.vue b/frontend-vue3/src/components/form/base/ColorPicker/ColorSwatch.vue new file mode 100644 index 0000000000..6959e6245d --- /dev/null +++ b/frontend-vue3/src/components/form/base/ColorPicker/ColorSwatch.vue @@ -0,0 +1,62 @@ + + + diff --git a/frontend-vue3/src/components/form/base/ECheckbox.vue b/frontend-vue3/src/components/form/base/ECheckbox.vue new file mode 100644 index 0000000000..ae55480949 --- /dev/null +++ b/frontend-vue3/src/components/form/base/ECheckbox.vue @@ -0,0 +1,58 @@ + + + + + diff --git a/frontend-vue3/src/components/form/base/EColorField.vue b/frontend-vue3/src/components/form/base/EColorField.vue new file mode 100644 index 0000000000..de4d002860 --- /dev/null +++ b/frontend-vue3/src/components/form/base/EColorField.vue @@ -0,0 +1,107 @@ + + + diff --git a/frontend-vue3/src/components/form/base/EColorPicker.vue b/frontend-vue3/src/components/form/base/EColorPicker.vue new file mode 100644 index 0000000000..77028223b9 --- /dev/null +++ b/frontend-vue3/src/components/form/base/EColorPicker.vue @@ -0,0 +1,259 @@ + + + + + + diff --git a/frontend-vue3/src/components/form/base/EDatePicker.vue b/frontend-vue3/src/components/form/base/EDatePicker.vue new file mode 100644 index 0000000000..7f6d2a0b6f --- /dev/null +++ b/frontend-vue3/src/components/form/base/EDatePicker.vue @@ -0,0 +1,192 @@ + + + + + + + diff --git a/frontend-vue3/src/components/form/base/EForm.vue b/frontend-vue3/src/components/form/base/EForm.vue new file mode 100644 index 0000000000..aafabf12a0 --- /dev/null +++ b/frontend-vue3/src/components/form/base/EForm.vue @@ -0,0 +1,19 @@ + + + diff --git a/frontend-vue3/src/components/form/base/ENumberField.vue b/frontend-vue3/src/components/form/base/ENumberField.vue new file mode 100644 index 0000000000..076a98507a --- /dev/null +++ b/frontend-vue3/src/components/form/base/ENumberField.vue @@ -0,0 +1,67 @@ + + + diff --git a/frontend-vue3/src/components/form/base/EParseField.vue b/frontend-vue3/src/components/form/base/EParseField.vue new file mode 100644 index 0000000000..cca78d79d8 --- /dev/null +++ b/frontend-vue3/src/components/form/base/EParseField.vue @@ -0,0 +1,218 @@ + + + + + diff --git a/frontend-vue3/src/components/form/base/ERichtext.vue b/frontend-vue3/src/components/form/base/ERichtext.vue new file mode 100644 index 0000000000..5682b9490f --- /dev/null +++ b/frontend-vue3/src/components/form/base/ERichtext.vue @@ -0,0 +1,46 @@ + + + diff --git a/frontend-vue3/src/components/form/base/ESelect.vue b/frontend-vue3/src/components/form/base/ESelect.vue new file mode 100644 index 0000000000..7df36bdac3 --- /dev/null +++ b/frontend-vue3/src/components/form/base/ESelect.vue @@ -0,0 +1,61 @@ + + + + + diff --git a/frontend-vue3/src/components/form/base/ESwitch.vue b/frontend-vue3/src/components/form/base/ESwitch.vue new file mode 100644 index 0000000000..480bfa8f20 --- /dev/null +++ b/frontend-vue3/src/components/form/base/ESwitch.vue @@ -0,0 +1,46 @@ + + + diff --git a/frontend-vue3/src/components/form/base/ETextField.vue b/frontend-vue3/src/components/form/base/ETextField.vue new file mode 100644 index 0000000000..b6ccd53bd1 --- /dev/null +++ b/frontend-vue3/src/components/form/base/ETextField.vue @@ -0,0 +1,205 @@ + + + + + + + diff --git a/frontend-vue3/src/components/form/base/ETextarea.vue b/frontend-vue3/src/components/form/base/ETextarea.vue new file mode 100644 index 0000000000..a99d8c67e3 --- /dev/null +++ b/frontend-vue3/src/components/form/base/ETextarea.vue @@ -0,0 +1,46 @@ + + + diff --git a/frontend-vue3/src/components/form/base/ETimeDropdown.vue b/frontend-vue3/src/components/form/base/ETimeDropdown.vue new file mode 100644 index 0000000000..64ac1e092c --- /dev/null +++ b/frontend-vue3/src/components/form/base/ETimeDropdown.vue @@ -0,0 +1,73 @@ + + + + + diff --git a/frontend-vue3/src/components/form/base/ETimeField.vue b/frontend-vue3/src/components/form/base/ETimeField.vue new file mode 100644 index 0000000000..b06c1c64f4 --- /dev/null +++ b/frontend-vue3/src/components/form/base/ETimeField.vue @@ -0,0 +1,104 @@ + + + diff --git a/frontend-vue3/src/components/form/base/ETimePicker.vue b/frontend-vue3/src/components/form/base/ETimePicker.vue new file mode 100644 index 0000000000..2c3ab07bbb --- /dev/null +++ b/frontend-vue3/src/components/form/base/ETimePicker.vue @@ -0,0 +1,160 @@ + + + + + + + diff --git a/frontend-vue3/src/components/form/base/__tests__/ECheckbox.spec.js b/frontend-vue3/src/components/form/base/__tests__/ECheckbox.spec.js new file mode 100644 index 0000000000..da599827dd --- /dev/null +++ b/frontend-vue3/src/components/form/base/__tests__/ECheckbox.spec.js @@ -0,0 +1,101 @@ +import { describe, beforeEach, vi, test, expect } from 'vitest' +import Vue from 'vue' +import Vuetify from 'vuetify' + +import formBaseComponents from '@/plugins/formBaseComponents' + +import { mount as mountComponent } from '@vue/test-utils' +import ECheckbox from '../ECheckbox.vue' +import { screen } from '@testing-library/vue' + +Vue.use(Vuetify) +Vue.use(formBaseComponents) + +describe('An ECheckbox', () => { + let vuetify + + const mount = (options) => { + const app = Vue.component('App', { + components: { ECheckbox }, + data: function () { + return { + data: null, + } + }, + template: ` +
+ + ${options?.children} + +
+ `, + }) + return mountComponent(app, { vuetify, attachTo: document.body, ...options }) + } + beforeEach(() => { + vuetify = new Vuetify() + }) + test('looks like a checkbox', async () => { + const wrapper = mount() + await wrapper.setData({ data: false }) + expect(wrapper).toMatchSnapshot('unchecked') + + await wrapper.setData({ data: true }) + expect(wrapper).toMatchSnapshot('checked') + }) + + test('is checked when initialized checked', () => { + const wrapper = mount({ + data: function () { + return { + data: true, + } + }, + }) + expect( + wrapper.find('input[type=checkbox]').element.getAttribute('aria-checked') + ).toBe('true') + }) + + test('updates checkbox when vModel changes', async () => { + const wrapper = mount() + await wrapper.setData({ data: false }) + expect( + wrapper.find('input[type=checkbox]').element.getAttribute('aria-checked') + ).toBe('false') + + await wrapper.setData({ data: true }) + expect( + wrapper.find('input[type=checkbox]').element.getAttribute('aria-checked') + ).toBe('true') + + await wrapper.setData({ data: false }) + expect( + wrapper.find('input[type=checkbox]').element.getAttribute('aria-checked') + ).toBe('false') + }) + + test('updates vModel when user clicks on checkbox', async () => { + const wrapper = mount() + const input = wrapper.find('input') + + await input.trigger('click') + expect(wrapper.vm.data).toBe(true) + + vi.resetAllMocks() + await input.trigger('click') + expect(wrapper.vm.data).toBe(false) + }) + + test('allows to use the append slot', async () => { + mount({ + children: ` + + `, + }) + + expect(await screen.findByText('append')).toBeVisible() + }) +}) diff --git a/frontend-vue3/src/components/form/base/__tests__/EColorField.spec.js b/frontend-vue3/src/components/form/base/__tests__/EColorField.spec.js new file mode 100644 index 0000000000..0161d8591b --- /dev/null +++ b/frontend-vue3/src/components/form/base/__tests__/EColorField.spec.js @@ -0,0 +1,90 @@ +import { describe, beforeEach, test, expect } from 'vitest' +import Vue from 'vue' +import Vuetify from 'vuetify' + +import formBaseComponents from '@/plugins/formBaseComponents' + +import EColorField from '@/components/form/base/EColorField.vue' +import { mount as mountComponent } from '@vue/test-utils' +import { ColorSpace, sRGB } from 'colorjs.io/fn' + +Vue.use(Vuetify) +Vue.use(formBaseComponents) + +ColorSpace.register(sRGB) + +describe('An EColorField', () => { + let vuetify + + const mount = (options) => { + const app = Vue.component('App', { + components: { EColorField }, + data: function () { + return { + data: null, + } + }, + methods: { + parse: (value) => { + return value === 'true' ? true : value === 'false' ? false : null + }, + format: (value) => { + return value === null ? '' : `${value}` + }, + }, + template: `
`, + }) + return mountComponent(app, { vuetify, attachTo: document.body, ...options }) + } + + beforeEach(() => { + vuetify = new Vuetify() + }) + + test('looks like a textfield', async () => { + const wrapper = mount() + expect(wrapper).toMatchSnapshot('empty') + + await wrapper.setData({ data: '#FF0000' }) + expect(wrapper).toMatchSnapshot('with text') + }) + + test('updates text when vModel changes', async () => { + const wrapper = mount() + const input = wrapper.find('input').element + expect(input.value).toBeDefined() + + const firstValue = '#A1E1E1' + await wrapper.setData({ data: firstValue }) + expect(input.value).toBe(`${firstValue}`) + + const secondValue = '#FF00FF' + await wrapper.setData({ data: secondValue }) + expect(input.value).toBe(`${secondValue}`) + }) + + test('updates vModel when value of input field changes', async () => { + const wrapper = mount() + const input = wrapper.find('input') + const value = '#123456' + + input.element.value = `${value}` + await input.trigger('input') + + expect(wrapper.vm.data).toBe(value) + }) + + test.each([ + ['#00FF00', '#00FF00'], + ['red', '#FF0000'], + ['', null], + ])('parses "%s" as "%s"', async (string, expected) => { + const wrapper = mount() + const input = wrapper.find('input') + + input.element.value = `${string}` + await input.trigger('input') + + expect(wrapper.vm.data).toBe(expected) + }) +}) diff --git a/frontend-vue3/src/components/form/base/__tests__/EColorPicker.spec.js b/frontend-vue3/src/components/form/base/__tests__/EColorPicker.spec.js new file mode 100644 index 0000000000..d3a4694341 --- /dev/null +++ b/frontend-vue3/src/components/form/base/__tests__/EColorPicker.spec.js @@ -0,0 +1,252 @@ +import { describe, beforeEach, expect, it } from 'vitest' +import { fireEvent, screen, waitFor } from '@testing-library/vue' +import { render, setTestLocale, snapshotOf } from '@/test/renderWithVuetify.js' +import user from '@testing-library/user-event' +import EColorPicker from '../EColorPicker.vue' + +import { regex } from 'vee-validate/dist/rules' +import { extend } from 'vee-validate' +import { ColorSpace, sRGB } from 'colorjs.io/fn' + +extend('regex', regex) + +ColorSpace.register(sRGB) +describe('An EColorPicker', () => { + const COLOR1 = '#FF0000' + const COLOR2 = '#FF00FF' + const COLOR3 = '#FAFFAF' + const INVALID_COLOR = 'some new color' + const PICKER_BUTTON_LABEL_TEXT = 'Dialog öffnen, um eine Farbe für test zu wählen' + const VALIDATION_MESSAGE = 'Bitte gültige Farbe eingeben.' + + beforeEach(() => { + setTestLocale('de') + }) + + it('renders the component', async () => { + // given + + // when + render(EColorPicker, { + props: { + value: COLOR1, + label: 'test', + }, + }) + + // then + await screen.findByDisplayValue(COLOR1) + screen.getByLabelText(PICKER_BUTTON_LABEL_TEXT) + }) + + it('looks like a color picker', async () => { + // given + + // when + const { container } = render(EColorPicker, { + props: { value: COLOR1, label: 'test' }, + }) + + // then + expect(snapshotOf(container)).toMatchSnapshot('pickerclosed') + + // when + await user.click(screen.getByLabelText(PICKER_BUTTON_LABEL_TEXT)) + + // then + await screen.findByTestId('colorpicker') + expect(snapshotOf(container)).toMatchSnapshot('pickeropen') + }) + + it('opens the picker when the text field is clicked', async () => { + // given + render(EColorPicker, { + props: { value: COLOR1, label: 'test' }, + }) + const inputField = await screen.findByDisplayValue(COLOR1) + + // when + await user.click(inputField) + + // then + await waitFor(async () => { + expect(await screen.findByTestId('colorpicker')).toBeVisible() + }) + }) + + it('opens the picker when the icon button is clicked', async () => { + // given + render(EColorPicker, { + props: { value: COLOR1, label: 'test' }, + }) + const button = await screen.getByLabelText(PICKER_BUTTON_LABEL_TEXT) + + // when + await user.click(button) + + // then + await waitFor(async () => { + expect(await screen.findByTestId('colorpicker')).toBeVisible() + }) + }) + + it('closes the picker when clicking outside', async () => { + // given + render(EColorPicker, { + props: { value: COLOR1, label: 'test' }, + }) + const button = await screen.getByLabelText(PICKER_BUTTON_LABEL_TEXT) + await user.click(button) + await waitFor(async () => { + expect(await screen.findByTestId('colorpicker')).toBeVisible() + }) + + // when + await user.click(document.body) + + // then + await waitFor(async () => { + expect(await screen.queryByTestId('colorpicker')).not.toBeVisible() + }) + }) + + it('closes the picker when pressing escape', async () => { + // given + render(EColorPicker, { + props: { value: COLOR1, label: 'test' }, + }) + const button = await screen.getByLabelText(PICKER_BUTTON_LABEL_TEXT) + await user.click(button) + await waitFor(async () => { + expect(await screen.findByTestId('colorpicker')).toBeVisible() + }) + + // when + await user.keyboard('{Escape}') + + // then + await waitFor(async () => { + expect(await screen.queryByTestId('colorpicker')).not.toBeVisible() + }) + }) + + it('does not close the picker when selecting a color', async () => { + // given + const { container } = render(EColorPicker, { + props: { value: COLOR1, label: 'test' }, + }) + const button = await screen.getByLabelText(PICKER_BUTTON_LABEL_TEXT) + await user.click(button) + await waitFor(async () => { + expect(await screen.findByTestId('colorpicker')).toBeVisible() + }) + + // when + // click inside the color picker canvas to select a different color + const canvas = container.querySelector('canvas') + await user.click(canvas, { clientX: 10, clientY: 10 }) + + // then + // close button should stay visible + await expect( + waitFor(() => { + expect(screen.queryByTestId('colorpicker')).not.toBeVisible() + }) + ).rejects.toThrow(/Received element is visible/) + }) + + it('updates v-model when the value changes', async () => { + // given + const { emitted } = render(EColorPicker, { + props: { value: COLOR1, label: 'test' }, + }) + const inputField = await screen.findByDisplayValue(COLOR1) + + // when + await user.clear(inputField) + await user.keyboard(COLOR2) + + // then + await waitFor(async () => { + const events = emitted().input + // some input events were fired + expect(events.length).toBeGreaterThan(0) + // the last one included the parsed version of our entered time + expect(events[events.length - 1]).toEqual([COLOR2]) + }) + // Our entered time should be visible... + screen.getByDisplayValue(COLOR2) + // ...and stay visible + await expect( + waitFor(() => { + expect(screen.getByDisplayValue(COLOR2)).not.toBeVisible() + }) + ).rejects.toThrow(/Received element is visible/) + }) + + it('updates v-model when a new color is selected in the picker', async () => { + // given + const { emitted, container } = render(EColorPicker, { + props: { value: COLOR1, label: 'test' }, + }) + await screen.findByDisplayValue(COLOR1) + const button = await screen.getByLabelText(PICKER_BUTTON_LABEL_TEXT) + + // when + // click the button to open the picker + await user.click(button) + // click inside the color picker canvas to select a different color + const canvas = container.querySelector('canvas') + await user.click(canvas, { clientX: 10, clientY: 10 }) + // click the close button + await user.click(screen.getByTestId('colorpicker')) + + // then + await waitFor(async () => { + const events = emitted().input + // some input events were fired + expect(events.length).toBeGreaterThan(0) + // the last one included the parsed version of our entered time + expect(events[events.length - 1]).toEqual([COLOR3]) + }) + // Our entered time should be visible... + screen.getByDisplayValue(COLOR3) + // ...and stay visible + await expect( + waitFor(() => { + expect(screen.getByDisplayValue(COLOR3)).not.toBeVisible() + }) + ).rejects.toThrow(/Received element is visible/) + }) + + it('validates the input', async () => { + // given + render(EColorPicker, { + props: { value: COLOR1, path: 'test', validationLabelOverride: 'test' }, + }) + const inputField = await screen.findByDisplayValue(COLOR1) + + // when + await user.clear(inputField) + await user.keyboard(INVALID_COLOR) + await fireEvent.blur(inputField) + + // then + await screen.findByText(VALIDATION_MESSAGE) + }) + + it('accepts null', async () => { + render(EColorPicker, { + props: { value: COLOR2, label: 'test' }, + }) + const inputField = await screen.findByDisplayValue(COLOR2) + expect(inputField).toHaveValue(COLOR2) + const button = await screen.getByLabelText(PICKER_BUTTON_LABEL_TEXT) + // click the button to open the picker + await user.click(button) + + // when + await user.click(screen.getByTestId('colorpicker').querySelector('.reset')) + expect(inputField).toHaveValue('') + }) +}) diff --git a/frontend-vue3/src/components/form/base/__tests__/EDatePicker.spec.js b/frontend-vue3/src/components/form/base/__tests__/EDatePicker.spec.js new file mode 100644 index 0000000000..ce842fc677 --- /dev/null +++ b/frontend-vue3/src/components/form/base/__tests__/EDatePicker.spec.js @@ -0,0 +1,406 @@ +import { describe, beforeEach, expect, it } from 'vitest' +import { screen, waitFor } from '@testing-library/vue' +import { render, setTestLocale, snapshotOf } from '@/test/renderWithVuetify.js' +import user from '@testing-library/user-event' +import EDatePicker from '../EDatePicker.vue' + +describe('An EDatePicker', () => { + const DATE1_ISO = '2020-03-01' + const DATE2_ISO = '2020-03-19' + + const localeData = { + de: { + date1: '01.03.2020', + date2: '19.03.2020', + dateShort: '2.4.2021', + dateInWrongLocale: '03/19/2020', + labelText: 'Dialog öffnen, um ein Datum für test zu wählen', + date1Heading: 'März 2020', + date3Heading: 'Januar 2111', + date4Heading: 'Januar 1999', + closeButton: 'Schliessen', + validationMessage: + 'Ungültiges Format, bitte gib das Datum im Format DD.MM.YYYY ein', + }, + en: { + date1: '03/01/2020', + date2: '03/19/2020', + dateShort: '4/2/2021', + dateInWrongLocale: '19.03.2020', + labelText: 'Open dialog to select a date for test', + date1Heading: 'March 2020', + date3Heading: 'January 2111', + date4Heading: 'January 1999', + closeButton: 'Close', + validationMessage: 'Invalid format, please enter the date in the format MM/DD/YYYY', + }, + } + + describe.each(Object.entries(localeData))('in locale %s', (locale, data) => { + beforeEach(() => { + setTestLocale(locale) + }) + + it('renders the component', async () => { + // given + + // when + render(EDatePicker, { props: { value: DATE1_ISO, label: 'test' } }) + + // then + await screen.findByDisplayValue(data.date1) + screen.getByLabelText(data.labelText) + }) + + it('looks like a date picker', async () => { + // given + + // when + const { container } = render(EDatePicker, { + props: { value: DATE1_ISO, label: 'test' }, + }) + + // then + expect(snapshotOf(container)).toMatchSnapshot('pickerclosed') + + // when + await user.click(screen.getByLabelText(data.labelText)) + + // then + await screen.findByText(data.closeButton) + await screen.findByText(data.date1Heading) + expect(snapshotOf(container)).toMatchSnapshot('pickeropen') + }) + + it('does not open the picker when the text field is clicked', async () => { + // given + render(EDatePicker, { + props: { value: DATE1_ISO, label: 'test' }, + }) + const inputField = await screen.findByDisplayValue(data.date1) + + // when + await user.click(inputField) + + // then + // menu should not appear + await expect(screen.findByText(data.date1Heading)).rejects.toThrow( + /Unable to find an element with the text/ + ) + }) + + it('opens the picker when the icon button is clicked', async () => { + // given + render(EDatePicker, { + props: { value: DATE1_ISO, label: 'test' }, + }) + const button = await screen.getByLabelText(data.labelText) + + // when + await user.click(button) + + // then + await waitFor(async () => { + expect(await screen.findByText(data.date1Heading)).toBeVisible() + }) + }) + + it('closes the picker when clicking the close button', async () => { + // given + render(EDatePicker, { + props: { value: DATE1_ISO, label: 'test' }, + }) + const button = await screen.getByLabelText(data.labelText) + await user.click(button) + await waitFor(async () => { + expect(await screen.findByText(data.date1Heading)).toBeVisible() + }) + const closeButton = screen.getByText(data.closeButton) + + // when + await user.click(closeButton) + + // then + await waitFor(async () => { + expect(await screen.queryByText(data.date1Heading)).not.toBeVisible() + }) + }) + + it('closes the picker when clicking outside', async () => { + // given + render(EDatePicker, { + props: { value: DATE1_ISO, label: 'test' }, + }) + const button = await screen.getByLabelText(data.labelText) + await user.click(button) + await waitFor(async () => { + expect(await screen.findByText(data.date1Heading)).toBeVisible() + }) + + // when + await user.click(document.body) + + // then + await waitFor(async () => { + expect(await screen.queryByText(data.date1Heading)).not.toBeVisible() + }) + }) + + it('closes the picker when pressing escape', async () => { + // given + render(EDatePicker, { + props: { value: DATE1_ISO, label: 'test' }, + }) + const button = await screen.getByLabelText(data.labelText) + await user.click(button) + await waitFor(async () => { + expect(await screen.findByText(data.date1Heading)).toBeVisible() + }) + + // when + await user.keyboard('{Escape}') + + // then + await waitFor(async () => { + expect(await screen.queryByText(data.date1Heading)).not.toBeVisible() + }) + }) + + it('closes the picker when selecting a date', async () => { + // given + render(EDatePicker, { + props: { value: DATE1_ISO, label: 'test' }, + }) + const button = await screen.getByLabelText(data.labelText) + await user.click(button) + await waitFor(async () => { + expect(await screen.findByText(data.date1Heading)).toBeVisible() + }) + + // when + // click the 19th day of the month + await user.click(screen.getByText('19')) + + // then + await waitFor(async () => { + expect(await screen.queryByText(data.date1Heading)).not.toBeVisible() + }) + }) + + it('re-opens the picker when clicking the button again after selecting a date', async () => { + // given + render(EDatePicker, { + props: { value: DATE1_ISO, label: 'test' }, + }) + const button = await screen.getByLabelText(data.labelText) + await user.click(button) + await waitFor(async () => { + expect(await screen.findByText(data.date1Heading)).toBeVisible() + }) + // click the 19th day of the month + await user.click(screen.getByText('19')) + await waitFor(async () => { + expect(await screen.queryByText(data.date1Heading)).not.toBeVisible() + }) + + // when + await user.click(button) + + // then + await waitFor(async () => { + expect(await screen.findByText(data.date1Heading)).toBeVisible() + }) + }) + + it('updates v-model when the input field is changed', async () => { + // given + const { emitted } = render(EDatePicker, { + props: { value: DATE1_ISO, label: 'test' }, + }) + const inputField = await screen.findByDisplayValue(data.date1) + + // when + await user.clear(inputField) + await user.keyboard(data.date2) + + // then + await waitFor(async () => { + const events = emitted().input + // some input events were fired + expect(events.length).toBeGreaterThan(0) + // the last one included the parsed version of our entered date + expect(events[events.length - 1]).toEqual([DATE2_ISO]) + }) + // Our entered date should be visible... + screen.getByDisplayValue(data.date2) + // ...and stay visible + await expect( + waitFor(() => { + expect(screen.getByDisplayValue(data.date2)).not.toBeVisible() + }) + ).rejects.toThrow(/Received element is visible/) + }) + + it('updates v-model when a new date is selected in the picker', async () => { + // given + const { emitted } = render(EDatePicker, { + props: { value: DATE1_ISO, label: 'test' }, + }) + await screen.findByDisplayValue(data.date1) + const button = await screen.getByLabelText(data.labelText) + + // when + // click the button to open the picker + await user.click(button) + // click the 19th day of the month + await user.click(screen.getByText('19')) + + // then + await waitFor(async () => { + const events = emitted().input + // some input events were fired + expect(events.length).toBeGreaterThan(0) + // the last one included the parsed version of our entered date + expect(events[events.length - 1]).toEqual([DATE2_ISO]) + }) + // Our selected date should be visible... + screen.getByDisplayValue(data.date2) + // ...and stay visible + await expect( + waitFor(() => { + expect(screen.getByDisplayValue(data.date2)).not.toBeVisible() + }) + ).rejects.toThrow(/Received element is visible/) + }) + + it('validates the input', async () => { + // given + render(EDatePicker, { + props: { value: DATE1_ISO, label: 'test' }, + }) + const inputField = await screen.findByDisplayValue(data.date1) + + // when + await user.clear(inputField) + await user.keyboard(data.dateInWrongLocale) + + // then + await screen.findByText(data.validationMessage) + }) + + it('allows inputting a date in short format', async () => { + // given + render(EDatePicker, { + props: { value: DATE1_ISO, label: 'test' }, + }) + const inputField = await screen.findByDisplayValue(data.date1) + + // when + await user.clear(inputField) + await user.keyboard(data.dateShort) + + // then + expect(screen.queryByText(data.validationMessage)).not.toBeInTheDocument() + // validation message should not appear + await expect(screen.findByText(data.validationMessage)).rejects.toThrow( + /Unable to find an element with the text/ + ) + }) + + it('autoscrolls forward to the earliest allowable month based on min', async () => { + // given + render(EDatePicker, { + props: { value: '', label: 'test', min: '2111-01-01' }, + }) + const button = await screen.getByLabelText(data.labelText) + + // when + await user.click(button) + + // then + await waitFor(async () => { + expect(await screen.findByText(data.date3Heading)).toBeVisible() + }) + }) + + it('does not autoscroll forward if given a value', async () => { + // given + render(EDatePicker, { + props: { value: DATE1_ISO, label: 'test', min: '2111-01-01' }, + }) + const button = await screen.getByLabelText(data.labelText) + + // when + await user.click(button) + + // then + await expect(async () => { + await screen.findByText(data.date3Heading) + }).rejects.toThrow(/Unable to find an element with the text/) + }) + + it('does not autoscroll backward based on min', async () => { + // given + render(EDatePicker, { + props: { value: '', label: 'test', min: '1999-01-01' }, + }) + const button = await screen.getByLabelText(data.labelText) + + // when + await user.click(button) + + // then + await expect(async () => { + await screen.findByText(data.date4Heading) + }).rejects.toThrow(/Unable to find an element with the text/) + }) + + it('autoscrolls back to the latest allowable month based on max', async () => { + // given + render(EDatePicker, { + props: { value: '', label: 'test', max: '1999-01-01' }, + }) + const button = await screen.getByLabelText(data.labelText) + + // when + await user.click(button) + + // then + await waitFor(async () => { + expect(await screen.findByText(data.date4Heading)).toBeVisible() + }) + }) + + it('does not autoscroll forward based on max', async () => { + // given + render(EDatePicker, { + props: { value: '', label: 'test', max: '2111-01-01' }, + }) + const button = await screen.getByLabelText(data.labelText) + + // when + await user.click(button) + + // then + await expect(async () => { + await screen.findByText(data.date3Heading) + }).rejects.toThrow(/Unable to find an element with the text/) + }) + + it('does not autoscroll backward if given a value', async () => { + // given + render(EDatePicker, { + props: { value: DATE1_ISO, label: 'test', max: '1999-01-01' }, + }) + const button = await screen.getByLabelText(data.labelText) + + // when + await user.click(button) + + // then + await expect(async () => { + await screen.findByText(data.date4Heading) + }).rejects.toThrow(/Unable to find an element with the text/) + }) + }) +}) diff --git a/frontend-vue3/src/components/form/base/__tests__/ENumberField.spec.js b/frontend-vue3/src/components/form/base/__tests__/ENumberField.spec.js new file mode 100644 index 0000000000..6f2b3c720e --- /dev/null +++ b/frontend-vue3/src/components/form/base/__tests__/ENumberField.spec.js @@ -0,0 +1,133 @@ +import { describe, beforeEach, test, expect } from 'vitest' +import Vue from 'vue' +import Vuetify from 'vuetify' + +import formBaseComponents from '@/plugins/formBaseComponents' + +import { mount as mountComponent } from '@vue/test-utils' +import ENumberField from '../ENumberField.vue' +import { screen } from '@testing-library/vue' + +Vue.use(Vuetify) +Vue.use(formBaseComponents) + +describe('An ENumberField', () => { + let vuetify + + const mount = (options) => { + const app = Vue.component('App', { + components: { ENumberField }, + data: function () { + return { + data: null, + } + }, + template: ` +
+ + ${options?.children} + +
+ `, + }) + return mountComponent(app, { vuetify, attachTo: document.body, ...options }) + } + + beforeEach(() => { + vuetify = new Vuetify() + }) + + test('looks like a numberfield', async () => { + const wrapper = mount() + expect(wrapper).toMatchSnapshot('empty') + + await wrapper.setData({ data: 3.14 }) + expect(wrapper).toMatchSnapshot('with text') + }) + + test('updates text when vModel changes', async () => { + const wrapper = mount() + const input = wrapper.find('input').element + expect(input.value).toBeDefined() + + const firstNumber = 0 + await wrapper.setData({ data: firstNumber }) + expect(input.value).toBe(`${firstNumber}`) + + const secondNumber = 3.14 + await wrapper.setData({ data: secondNumber }) + expect(input.value).toBe(`${secondNumber}`) + }) + + test('updates vModel when value of input field changes', async () => { + const wrapper = mount() + const input = wrapper.find('input') + const number = 3.14 + + input.element.value = `${number}` + await input.trigger('input') + + expect(wrapper.vm.data).toBe(number) + }) + + test('updates vModel with null or valid numbers', async () => { + const wrapper = mount() + const input = wrapper.find('input') + + expect(wrapper.vm.data).toBeNull() + + input.element.value = '.' + await input.trigger('input') + expect(wrapper.vm.data).toBeNull() + + input.element.value = '.0' + await input.trigger('input') + expect(wrapper.vm.data).toBeNull() + + input.element.value = '.01' + await input.trigger('input') + expect(wrapper.vm.data).toBe(0.01) + }) + + test.each([ + ['1', 1], + ['1.', 1], + ['1..2', 1.2], + ['39.5.', 39.5], + ["2'000", 2000], + ['8.000.000,20', 8000000.2], + ['10e3', 103], + ['2kg', 2], + ['8,000.20', 8000.2], + ['abc123', 123], + ['Hello, World?', null], + ['eCamp. Super!', null], + ['+123..456..789', 123.456789], + ['-10', -10], + ['2-4 Stück', 24], + ['-0', -0], + ['.', null], + ['.a', null], + ['.a02', 0.02], + ])('parses "%s" as "%s"', async (string, expected) => { + const wrapper = mount() + const input = wrapper.find('input') + + input.element.value = string + await input.trigger('input') + + expect(wrapper.vm.data).toBe(expected) + }) + + test('allows to use the append slot', async () => { + mount({ + children: ` + + `, + }) + + expect(await screen.findByText('append')).toBeVisible() + }) +}) diff --git a/frontend-vue3/src/components/form/base/__tests__/EParseField.spec.js b/frontend-vue3/src/components/form/base/__tests__/EParseField.spec.js new file mode 100644 index 0000000000..34f09ba6c6 --- /dev/null +++ b/frontend-vue3/src/components/form/base/__tests__/EParseField.spec.js @@ -0,0 +1,109 @@ +import { describe, beforeEach, test, expect } from 'vitest' +import Vue from 'vue' +import Vuetify from 'vuetify' + +import formBaseComponents from '@/plugins/formBaseComponents' + +import EParseField from '@/components/form/base/EParseField.vue' +import { mount as mountComponent } from '@vue/test-utils' +import { screen } from '@testing-library/vue' + +Vue.use(Vuetify) +Vue.use(formBaseComponents) + +describe('An EParseField', () => { + let vuetify + + const mount = (options) => { + const app = Vue.component('App', { + components: { EParseField }, + data: function () { + return { + data: null, + } + }, + methods: { + parse: (value) => { + return value === 'true' ? true : value === 'false' ? false : null + }, + format: (value) => { + return value === null ? '' : `${value}` + }, + }, + template: ` +
+ + ${options?.children} + +
+ `, + }) + return mountComponent(app, { vuetify, attachTo: document.body, ...options }) + } + + beforeEach(() => { + vuetify = new Vuetify() + }) + + test('looks like a textfield', async () => { + const wrapper = mount() + expect(wrapper).toMatchSnapshot('empty') + + await wrapper.setData({ data: true }) + expect(wrapper).toMatchSnapshot('with text') + }) + + test('updates text when vModel changes', async () => { + const wrapper = mount() + const input = wrapper.find('input').element + expect(input.value).toBeDefined() + + const firstValue = true + await wrapper.setData({ data: firstValue }) + expect(input.value).toBe(`${firstValue}`) + + const secondValue = false + await wrapper.setData({ data: secondValue }) + expect(input.value).toBe(`${secondValue}`) + }) + + test('updates vModel when value of input field changes', async () => { + const wrapper = mount() + const input = wrapper.find('input') + const value = true + + input.element.value = `${value}` + await input.trigger('input') + + expect(wrapper.vm.data).toBe(value) + }) + + test.each([ + ['true', true], + ['false', false], + ['', null], + ['s', null], + ['0', null], + ['1', null], + ])('parses "%s" as "%s"', async (string, expected) => { + const wrapper = mount() + const input = wrapper.find('input') + + input.element.value = `${string}` + await input.trigger('input') + + expect(wrapper.vm.data).toBe(expected) + }) + + test('allows to use the append slot', async () => { + mount({ + children: ` + + `, + }) + + expect(await screen.findByText('append')).toBeVisible() + }) +}) diff --git a/frontend-vue3/src/components/form/base/__tests__/ESelect.spec.js b/frontend-vue3/src/components/form/base/__tests__/ESelect.spec.js new file mode 100644 index 0000000000..d44dd7375b --- /dev/null +++ b/frontend-vue3/src/components/form/base/__tests__/ESelect.spec.js @@ -0,0 +1,140 @@ +import { describe, beforeEach, test, expect } from 'vitest' +import Vue from 'vue' +import Vuetify from 'vuetify' + +import { formBaseComponents } from '@/plugins' + +import { mount as mountComponent } from '@vue/test-utils' +import ESelect from '../ESelect.vue' +import { screen } from '@testing-library/vue' + +Vue.use(Vuetify) +Vue.use(formBaseComponents) + +describe('An ESelect', () => { + let vuetify + + const FIRST_OPTION = { + value: 1, + text: 'firstOption', + } + const SECOND_OPTION = { + value: '2', + text: 'secondOption', + } + const THIRD_OPTION = { + value: { key: 'value', array: [1, 2, 3], nestedObject: { key: 'value' } }, + text: 'thirdOption', + } + const selectValues = [FIRST_OPTION, SECOND_OPTION, THIRD_OPTION] + + const mount = (options) => { + const app = Vue.component('App', { + components: { ESelect }, + data: function () { + return { + selectValues: selectValues, + data: null, + } + }, + template: ` +
+ + ${options?.children} + +
+ `, + }) + return mountComponent(app, { vuetify, attachTo: document.body, ...options }) + } + + beforeEach(() => { + vuetify = new Vuetify() + }) + test('looks like a dropdown', async () => { + const wrapper = mount() + expect(wrapper).toMatchSnapshot('no item selected') + + await wrapper.find('.v-input__slot').trigger('click') + expect(wrapper).toMatchSnapshot('dropdown open') + + await wrapper.findAll('[role="option"]').at(0).trigger('click') + expect(wrapper).toMatchSnapshot('dropdown closed with selected value') + + await wrapper.find('.v-input__slot').trigger('click') + expect(wrapper).toMatchSnapshot('dropdown open with selected value') + }) + + test('update viewmodel with selected value', async () => { + const wrapper = mount() + expect(wrapper.vm.data).toBeNull() + + await wrapper.find('.v-input__slot').trigger('click') + await wrapper.findAll('[role="option"]').at(0).trigger('click') + expect(wrapper.vm.data).toBe(FIRST_OPTION.value) + + await wrapper.find('.v-input__slot').trigger('click') + await wrapper.findAll('[role="option"]').at(2).trigger('click') + expect(wrapper.vm.data).toBe(THIRD_OPTION.value) + }) + + test('update selected value with viewmodel', async () => { + const wrapper = mount() + + await wrapper.setData({ data: SECOND_OPTION.value }) + expect(wrapper.html()).toContain(SECOND_OPTION.text) + expect(wrapper.html()).not.toContain(FIRST_OPTION.text) + + await wrapper.setData({ data: FIRST_OPTION.value }) + expect(wrapper.html()).toContain(FIRST_OPTION.text) + expect(wrapper.html()).not.toContain(SECOND_OPTION.text) + }) + + test('update selected value after it was open', async () => { + const wrapper = mount() + + await wrapper.find('.v-input__slot').trigger('click') + await wrapper.findAll('[role="option"]').at(0).trigger('click') + expect(wrapper.vm.data).toBe(FIRST_OPTION.value) + + await wrapper.setData({ data: SECOND_OPTION.value }) + expect( + wrapper.findAll('[role="option"]').at(1).element.getAttribute('aria-selected') + ).toBe('true') + expect( + wrapper.findAll('[role="option"]').at(0).element.getAttribute('aria-selected') + ).not.toBe('true') + }) + + test('allows to use the append slot', async () => { + mount({ + children: ` + + `, + }) + + expect(await screen.findByText('append')).toBeVisible() + }) + + test('allows to use the append slot with scope', async () => { + const textText = 'myTestText' + const wrapper = mount({ + children: ` + + `, + }) + + await wrapper.find('.v-input__slot').trigger('click') + + expect(await screen.findAllByText(textText)).toHaveLength(3) + }) +}) diff --git a/frontend-vue3/src/components/form/base/__tests__/ESwitch.spec.js b/frontend-vue3/src/components/form/base/__tests__/ESwitch.spec.js new file mode 100644 index 0000000000..7ce1b90d9d --- /dev/null +++ b/frontend-vue3/src/components/form/base/__tests__/ESwitch.spec.js @@ -0,0 +1,126 @@ +import { describe, beforeEach, vi, test, expect } from 'vitest' +import Vue from 'vue' +import Vuetify from 'vuetify' + +import formBaseComponents from '@/plugins/formBaseComponents' + +import { mount as mountComponent } from '@vue/test-utils' +import ESwitch from '@/components/form/base/ESwitch.vue' +import { touch } from '@/test/util' +import { screen } from '@testing-library/vue' + +Vue.use(Vuetify) +Vue.use(formBaseComponents) + +describe('An ESwitch', () => { + let vuetify + + const mount = (options) => { + const app = Vue.component('App', { + components: { ESwitch }, + data: function () { + return { + data: null, + } + }, + template: ` +
+ + ${options?.children} + +
+ `, + }) + return mountComponent(app, { vuetify, attachTo: document.body, ...options }) + } + beforeEach(() => { + vuetify = new Vuetify() + }) + test('looks like a switch', async () => { + const wrapper = mount() + await wrapper.setData({ data: false }) + expect(wrapper).toMatchSnapshot('unchecked') + + await wrapper.setData({ data: true }) + expect(wrapper).toMatchSnapshot('checked') + }) + + test('is checked when initialized checked', () => { + const wrapper = mount({ + data: function () { + return { + data: true, + } + }, + }) + expect( + wrapper.find('input[type=checkbox]').element.getAttribute('aria-checked') + ).toBe('true') + }) + + test('updates switch when vModel changes', async () => { + const wrapper = mount() + expect( + wrapper.find('input[type=checkbox]').element.getAttribute('aria-checked') + ).toBe('false') + + await wrapper.setData({ data: true }) + expect( + wrapper.find('input[type=checkbox]').element.getAttribute('aria-checked') + ).toBe('true') + + await wrapper.setData({ data: false }) + expect( + wrapper.find('input[type=checkbox]').element.getAttribute('aria-checked') + ).toBe('false') + }) + + test('updates vModel when user toggles with click', async () => { + const wrapper = mount() + const input = wrapper.find('input') + + await input.trigger('click') + expect(wrapper.vm.data).toBe(true) + + await input.trigger('click') + expect(wrapper.vm.data).toBe(false) + }) + + test('updates vModel when user toggles with touch swipe', async () => { + const wrapper = mount() + + touch(wrapper.find('.v-input--selection-controls__ripple')).start(0, 0).end(20, 0) + expect(wrapper.vm.data).toBe(true) + + vi.resetAllMocks() + touch(wrapper.find('.v-input--selection-controls__ripple')).start(0, 0).end(-20, 0) + expect(wrapper.vm.data).toBe(false) + }) + + test('updates vModel when user toggles with keys', async () => { + const wrapper = mount() + const input = wrapper.find('input') + + input.trigger('keydown.right') + expect(wrapper.vm.data).toBe(true) + + input.trigger('keydown.right') + expect(wrapper.vm.data).toBe(true) + + vi.resetAllMocks() + input.trigger('keydown.left') + expect(wrapper.vm.data).toBe(false) + }) + + test('allows to use the append slot', async () => { + mount({ + children: ` + + `, + }) + + expect(await screen.findByText('append')).toBeVisible() + }) +}) diff --git a/frontend-vue3/src/components/form/base/__tests__/ETextArea.spec.js b/frontend-vue3/src/components/form/base/__tests__/ETextArea.spec.js new file mode 100644 index 0000000000..2f1944903a --- /dev/null +++ b/frontend-vue3/src/components/form/base/__tests__/ETextArea.spec.js @@ -0,0 +1,93 @@ +import { describe, beforeEach, test, expect } from 'vitest' +import Vue from 'vue' +import Vuetify from 'vuetify' + +import formBaseComponents from '@/plugins/formBaseComponents' + +import { mount as mountComponent } from '@vue/test-utils' +import ETextarea from '../ETextarea.vue' +import { mockEventClass } from '@/test/mockEventClass' + +Vue.use(Vuetify) +Vue.use(formBaseComponents) + +mockEventClass('ClipboardEvent') +mockEventClass('DragEvent') + +describe('An ETextArea', () => { + let vuetify + + const multiLineText = ` + Here comes a text + with new lines + and new lines with \n in them + and tags a + ` + + const mount = ( + options, + template = ` +
+ +
+ ` + ) => { + const app = Vue.component('App', { + components: { ETextarea }, + data: () => ({ data: null }), + template: template, + }) + return mountComponent(app, { vuetify, attachTo: document.body, ...options }) + } + beforeEach(() => { + vuetify = new Vuetify() + }) + test('looks like a textarea', async () => { + const wrapper = mount() + expect(wrapper).toMatchSnapshot('notext') + + await wrapper.setData({ data: multiLineText }) + expect(wrapper).toMatchSnapshot('withtext') + + const mountWithMultiLine = mount( + { data: () => ({ data: multiLineText }) }, + ` +
+ +
+ ` + ) + expect(mountWithMultiLine).toMatchSnapshot('multiline') + + const mountAsinControls = mount( + { data: () => ({ data: multiLineText }) }, + ` +
+ +
+ ` + ) + expect(mountAsinControls).toMatchSnapshot('mountAsInControls') + }) + + test('updates the text with the viewmodel', async () => { + const wrapper = mount() + await wrapper.setData({ data: multiLineText }) + const textWithoutMultiLine = multiLineText + .replace(/\n\s*/g, ' ') + .replace(' ', ' ') + .replace('', '') + .replace('', '') + .trim() + expect(wrapper.find('.editor__content').text()).toBe(textWithoutMultiLine) + expect(wrapper.find('.e-form-container').element.getAttribute('value')).toBe( + multiLineText + ) + expect(wrapper.vm.data).toBe(multiLineText) + }) +}) diff --git a/frontend-vue3/src/components/form/base/__tests__/ETextField.spec.js b/frontend-vue3/src/components/form/base/__tests__/ETextField.spec.js new file mode 100644 index 0000000000..0e3c1e17bd --- /dev/null +++ b/frontend-vue3/src/components/form/base/__tests__/ETextField.spec.js @@ -0,0 +1,86 @@ +import Vue from 'vue' +import Vuetify from 'vuetify' + +import formBaseComponents from '@/plugins/formBaseComponents' + +import { mount as mountComponent } from '@vue/test-utils' +import ETextField from '../ETextField.vue' +import { screen } from '@testing-library/vue' + +Vue.use(Vuetify) +Vue.use(formBaseComponents) + +describe('An ETextField', () => { + let vuetify + + const mount = (options) => { + const app = Vue.component('App', { + components: { ETextField }, + data: function () { + return { + data: null, + } + }, + template: ` +
+ + ${options?.children} + +
+ `, + }) + return mountComponent(app, { vuetify, attachTo: document.body, ...options }) + } + + beforeEach(() => { + vuetify = new Vuetify() + }) + + test('looks like a textfield', async () => { + const wrapper = mount() + expect(wrapper).toMatchSnapshot('empty') + + await wrapper.setData({ data: 'MyText' }) + expect(wrapper).toMatchSnapshot('with text') + }) + + test('updates text when vModel changes', async () => { + const wrapper = mount() + expect(wrapper.find('.e-form-container').element.getAttribute('value')).toBeNull() + + const firstText = 'myText' + await wrapper.setData({ data: firstText }) + expect(wrapper.find('.e-form-container').element.getAttribute('value')).toBe( + firstText + ) + + const secondText = 'myText2' + await wrapper.setData({ data: secondText }) + expect(wrapper.find('.e-form-container').element.getAttribute('value')).toBe( + secondText + ) + }) + + test('updates vModel when value of input field changes', async () => { + const wrapper = mount() + const input = wrapper.find('input') + const text = 'bla' + + input.element.value = text + await input.trigger('input') + + expect(wrapper.vm.data).toBe(text) + }) + + test('allows to use the append slot', async () => { + mount({ + children: ` + + `, + }) + + expect(await screen.findByText('append')).toBeVisible() + }) +}) diff --git a/frontend-vue3/src/components/form/base/__tests__/ETimeField.spec.js b/frontend-vue3/src/components/form/base/__tests__/ETimeField.spec.js new file mode 100644 index 0000000000..59c579dc7b --- /dev/null +++ b/frontend-vue3/src/components/form/base/__tests__/ETimeField.spec.js @@ -0,0 +1,51 @@ +import { describe, beforeEach, expect, test } from 'vitest' +import Vue from 'vue' +import Vuetify from 'vuetify' + +import formBaseComponents from '@/plugins/formBaseComponents' +import dayjs from '@/plugins/dayjs.js' + +import ETimeField from '@/components/form/base/ETimeField.vue' +import { mount as mountComponent } from '@vue/test-utils' + +Vue.use(Vuetify) +Vue.use(dayjs) +Vue.use(formBaseComponents) + +describe('An ETimeField', () => { + let vuetify + + const mount = (options) => { + const app = Vue.component('App', { + components: { ETimeField }, + data: function () { + return { + data: null, + } + }, + template: `
`, + }) + return mountComponent(app, { vuetify, attachTo: document.body, ...options }) + } + + beforeEach(() => { + vuetify = new Vuetify() + }) + + test.each([ + ['8', '08:00'], + [' 9 ', '09:00'], + ['2400', null], + ['19,34', '19:34'], + ['19h34', '19:34'], + ['', null], + ])('parses "%s" as "%s"', async (string, expected) => { + const wrapper = mount() + const input = wrapper.find('input') + + input.element.value = `${string}` + await input.trigger('input') + + expect(wrapper.vm.data).toBe(expected) + }) +}) diff --git a/frontend-vue3/src/components/form/base/__tests__/ETimePicker.spec.js b/frontend-vue3/src/components/form/base/__tests__/ETimePicker.spec.js new file mode 100644 index 0000000000..a33decab01 --- /dev/null +++ b/frontend-vue3/src/components/form/base/__tests__/ETimePicker.spec.js @@ -0,0 +1,406 @@ +import { screen, waitFor } from '@testing-library/vue' +import { render, setTestLocale, snapshotOf } from '@/test/renderWithVuetify.js' +import user from '@testing-library/user-event' +import ETimePicker from '../ETimePicker.vue' + +describe('An ETimePicker', () => { + const TIME1_ISO = '2037-07-18T09:52:00+00:00' + const TIME1_HHMM = '09:52' + const TIME2_ISO = '2037-07-18T18:33:00+00:00' + const TIME3_ISO = '2037-07-18T00:52:00+00:00' + + const localeData = { + de: { + time1: '09:52', + time2: '18:33', + time3: '00:52', + firstHour: '0', + labelText: 'Dialog öffnen, um eine Zeit für test zu wählen', + closeButton: 'Schliessen', + timeInWrongLocale: '9:52 AM', + validationMessage: 'Ungültiges Format, bitte gib die Zeit im Format HH:MM ein', + }, + en: { + time1: '9:52 AM', + time2: '6:33 PM', + time3: '12:52 AM', + firstHour: '12', + labelText: 'Open dialog to select a time for test', + closeButton: 'Close', + timeInWrongLocale: '09:52', + validationMessage: + 'Invalid format, please enter the time in the format HH:MM AM/PM', + }, + } + + describe.each(Object.entries(localeData))('in locale %s', (locale, data) => { + beforeEach(() => { + setTestLocale(locale) + }) + + it('renders the component', async () => { + // given + + // when + render(ETimePicker, { + props: { + value: TIME1_ISO, + label: 'test', + }, + }) + + // then + await screen.findByDisplayValue(data.time1) + screen.getByLabelText(data.labelText) + }) + + it('looks like a time picker', async () => { + // given + + // when + const { container } = render(ETimePicker, { + props: { value: TIME1_ISO, label: 'test' }, + }) + + // then + expect(snapshotOf(container)).toMatchSnapshot('pickerclosed') + + // when + await user.click(screen.getByLabelText(data.labelText)) + + // then + await screen.findByText(data.closeButton) + expect(snapshotOf(container)).toMatchSnapshot('pickeropen') + }) + + it('allows setting a different valueFormat', async () => { + // given + + // when + render(ETimePicker, { + props: { + value: TIME1_HHMM, + label: 'test', + valueFormat: 'HH:mm', + }, + }) + + // then + await screen.findByDisplayValue(data.time1) + screen.getByLabelText(data.labelText) + }) + + it('does not open the picker when the text field is clicked', async () => { + // given + render(ETimePicker, { + props: { value: TIME1_ISO, label: 'test' }, + }) + const inputField = await screen.findByDisplayValue(data.time1) + + // when + await user.click(inputField) + + // then + // menu should not appear + await expect(screen.findByText(data.closeButton)).rejects.toThrow( + /Unable to find an element with the text/ + ) + }) + + it('opens the picker when the icon button is clicked', async () => { + // given + render(ETimePicker, { + props: { value: TIME1_ISO, label: 'test' }, + }) + const button = await screen.getByLabelText(data.labelText) + + // when + await user.click(button) + + // then + await waitFor(async () => { + expect(await screen.findByText(data.closeButton)).toBeVisible() + }) + }) + + it('closes the picker when clicking the close button', async () => { + // given + render(ETimePicker, { + props: { value: TIME1_ISO, label: 'test' }, + }) + const button = await screen.getByLabelText(data.labelText) + await user.click(button) + await waitFor(async () => { + expect(await screen.findByText(data.closeButton)).toBeVisible() + }) + const closeButton = screen.getByText(data.closeButton) + + // when + await user.click(closeButton) + + // then + await waitFor(async () => { + expect(await screen.queryByText(data.closeButton)).not.toBeVisible() + }) + }) + + it('closes the picker when clicking outside', async () => { + // given + render(ETimePicker, { + props: { value: TIME1_ISO, label: 'test' }, + }) + const button = await screen.getByLabelText(data.labelText) + await user.click(button) + await waitFor(async () => { + expect(await screen.findByText(data.closeButton)).toBeVisible() + }) + + // when + await user.click(document.body) + + // then + await waitFor(async () => { + expect(await screen.queryByText(data.closeButton)).not.toBeVisible() + }) + }) + + it('closes the picker when pressing escape', async () => { + // given + render(ETimePicker, { + props: { value: TIME1_ISO, label: 'test' }, + }) + const button = await screen.getByLabelText(data.labelText) + await user.click(button) + await waitFor(async () => { + expect(await screen.findByText(data.closeButton)).toBeVisible() + }) + + // when + await user.click(document.body) + + // then + await waitFor(async () => { + expect(await screen.queryByText(data.closeButton)).not.toBeVisible() + }) + }) + + it('does not close the picker when selecting a time', async () => { + // given + render(ETimePicker, { + props: { value: TIME1_ISO, label: 'test' }, + }) + const button = await screen.getByLabelText(data.labelText) + await user.click(button) + await waitFor(async () => { + expect(await screen.findByText(data.closeButton)).toBeVisible() + }) + + // when + // Click the 0th hour + await user.click(await screen.findByText(data.firstHour)) + // Click the 45th minute + await user.click(await screen.findByText('45')) + + // then + // close button should stay visible + await expect( + waitFor(() => { + expect(screen.queryByText(data.closeButton)).not.toBeVisible() + }) + ).rejects.toThrow(/Received element is visible/) + }) + + describe('updates v-model when the input field is changed', async () => { + const timeConfig1 = { + iso: TIME1_ISO, + localizedTime: data.time1, + textInput: data.time1, + } + const timeConfig2 = { + iso: TIME2_ISO, + localizedTime: data.time2, + textInput: data.time2, + } + const timeConfig3 = { + iso: TIME3_ISO, + localizedTime: data.time3, + textInput: data.time3, + } + it.each([ + { + from: timeConfig1, + to: timeConfig2, + }, + { + from: timeConfig2, + to: timeConfig1, + }, + { + from: timeConfig1, + to: timeConfig3, + }, + //with leading zero + { + from: timeConfig1, + to: { + ...timeConfig2, + textInput: '0' + timeConfig2.localizedTime, + }, + }, + { + from: timeConfig1, + to: { + ...timeConfig2, + textInput: '0000' + timeConfig2.localizedTime, + }, + }, + { + from: timeConfig2, + to: { + ...timeConfig1, + textInput: '0' + timeConfig1.localizedTime, + }, + }, + { + from: timeConfig2, + to: { + ...timeConfig1, + textInput: '00000' + timeConfig1.localizedTime, + }, + }, + { + from: timeConfig1, + to: { + ...timeConfig3, + textInput: '0' + timeConfig3.localizedTime, + }, + }, + { + from: timeConfig1, + to: { + ...timeConfig3, + textInput: '00000' + timeConfig3.localizedTime, + }, + }, + ])( + `from $from.localizedTime to $to.textInput`, + async ({ + from: { iso: fromIso, localizedTime: fromLocalizedTime }, + to: { iso: toIso, localizedTime: toLocalizedTime, textInput }, + }) => { + // given + const { emitted } = render(ETimePicker, { + props: { value: fromIso, label: 'test' }, + }) + const inputField = await screen.findByDisplayValue(fromLocalizedTime) + + // when + await user.clear(inputField) + await user.keyboard(textInput) + + // then + await waitFor(async () => { + const events = emitted().input + // some input events were fired + expect(events.length).toBeGreaterThan(0) + // the last one included the parsed version of our entered time + expect(events[events.length - 1]).toEqual([toIso]) + }) + // Our entered time should be visible... + screen.getByDisplayValue(toLocalizedTime) + // ...and stay visible + await expect( + waitFor(() => { + expect(screen.getByDisplayValue(toLocalizedTime)).not.toBeVisible() + }) + ).rejects.toThrow(/Received element is visible/) + } + ) + }) + + it('updates v-model when a new time is selected in the picker', async () => { + // given + const { emitted } = render(ETimePicker, { + props: { value: TIME1_ISO, label: 'test' }, + }) + await screen.findByDisplayValue(data.time1) + const button = await screen.getByLabelText(data.labelText) + + // when + // click the button to open the picker + await user.click(button) + // Click the 0th hour. We can only click this one, because + // testing library is missing the vuetify styles, and all the + // number elements overlap + await user.click(await screen.findByText(data.firstHour)) + // click the close button + await user.click(screen.getByText(data.closeButton)) + + // then + await waitFor(() => { + expect(screen.queryByText(data.closeButton)).not.toBeVisible() + }) + await waitFor(async () => { + const events = emitted().input + // some input events were fired + expect(events.length).toBeGreaterThan(0) + // the last one included the parsed version of our entered time + expect(events[events.length - 1]).toEqual([TIME3_ISO]) + }) + // Our entered time should be visible... + screen.getByDisplayValue(data.time3) + // ...and stay visible + await expect( + waitFor(() => { + expect(screen.getByDisplayValue(data.time3)).not.toBeVisible() + }) + ).rejects.toThrow(/Received element is visible/) + }) + + describe('validates the input', async () => { + it.each([ + data.timeInWrongLocale, + 'a' + data.time1, + data.time2 + 'a', + '0000:a' + data.time3, + ])('%s', async (textInput) => { + // given + render(ETimePicker, { + props: { value: TIME1_ISO, label: 'test' }, + }) + const inputField = await screen.findByDisplayValue(data.time1) + + // when + await user.clear(inputField) + await user.keyboard(textInput) + + // then + await screen.findByText(data.validationMessage) + }) + }) + + it('works with invalid initialization', async () => { + // given + + // when + render(ETimePicker, { + props: { + value: 'abc', + label: 'test', + }, + }) + + // then + const inputField = await screen.findByDisplayValue('Invalid Date') + + // when + await user.clear(inputField) + await user.keyboard(data.time2) + + // then + waitFor(() => { + expect(screen.queryByText('Invalid Date')).not.toBeInTheDocument() + }) + }) + }) +}) diff --git a/frontend-vue3/src/components/form/base/__tests__/__snapshots__/ECheckbox.spec.js.snap b/frontend-vue3/src/components/form/base/__tests__/__snapshots__/ECheckbox.spec.js.snap new file mode 100644 index 0000000000..033ec7e16c --- /dev/null +++ b/frontend-vue3/src/components/form/base/__tests__/__snapshots__/ECheckbox.spec.js.snap @@ -0,0 +1,53 @@ +// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html + +exports[`An ECheckbox > looks like a checkbox > checked 1`] = ` +
+ +
+
+
+
+ + +
+
+ +
+
+
+
+
+`; + +exports[`An ECheckbox > looks like a checkbox > unchecked 1`] = ` +
+ +
+
+
+
+ + +
+
+ +
+
+
+
+
+`; diff --git a/frontend-vue3/src/components/form/base/__tests__/__snapshots__/EColorField.spec.js.snap b/frontend-vue3/src/components/form/base/__tests__/__snapshots__/EColorField.spec.js.snap new file mode 100644 index 0000000000..12dfeb4f69 --- /dev/null +++ b/frontend-vue3/src/components/form/base/__tests__/__snapshots__/EColorField.spec.js.snap @@ -0,0 +1,58 @@ +// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html + +exports[`An EColorField > looks like a textfield > empty 1`] = ` +
+
+
+
+
+ +
+
+
+
+
+ + +
+
+
+
+
+
+`; + +exports[`An EColorField > looks like a textfield > with text 1`] = ` +
+
+
+
+
+ +
+
+
+
+
+ + +
+
+
+
+
+
+`; diff --git a/frontend-vue3/src/components/form/base/__tests__/__snapshots__/EColorPicker.spec.js.snap b/frontend-vue3/src/components/form/base/__tests__/__snapshots__/EColorPicker.spec.js.snap new file mode 100644 index 0000000000..641d2e0aee --- /dev/null +++ b/frontend-vue3/src/components/form/base/__tests__/__snapshots__/EColorPicker.spec.js.snap @@ -0,0 +1,246 @@ +// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html + +exports[`An EColorPicker > looks like a color picker > pickerclosed 1`] = ` +
+
+
+
+
+
+
+ +
+
+
+
+ + +
+
+
+
+
+
+ +
+
+
+`; + +exports[`An EColorPicker > looks like a color picker > pickeropen 1`] = ` +
+
+
+
+
+
+ +
+
+
+
+ + +
+
+
+
+
+
+
+ +
+
+ +
+`; diff --git a/frontend-vue3/src/components/form/base/__tests__/__snapshots__/EDatePicker.spec.js.snap b/frontend-vue3/src/components/form/base/__tests__/__snapshots__/EDatePicker.spec.js.snap new file mode 100644 index 0000000000..cf6641369a --- /dev/null +++ b/frontend-vue3/src/components/form/base/__tests__/__snapshots__/EDatePicker.spec.js.snap @@ -0,0 +1,815 @@ +// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html + +exports[`An EDatePicker > in locale de > looks like a date picker > pickerclosed 1`] = ` +
+
+
+
+
+
+ +
+
+
+
+ + +
+
+
+
+
+ +
+
+
+`; + +exports[`An EDatePicker > in locale de > looks like a date picker > pickeropen 1`] = ` +
+
+
+
+
+ +
+
+
+
+ + +
+
+
+
+
+
+ +
+
+ +
+`; + +exports[`An EDatePicker > in locale en > looks like a date picker > pickerclosed 1`] = ` +
+
+
+
+
+
+ +
+
+
+
+ + +
+
+
+
+
+ +
+
+
+`; + +exports[`An EDatePicker > in locale en > looks like a date picker > pickeropen 1`] = ` +
+
+
+
+
+ +
+
+
+
+ + +
+
+
+
+
+
+ +
+
+ +
+`; diff --git a/frontend-vue3/src/components/form/base/__tests__/__snapshots__/ENumberField.spec.js.snap b/frontend-vue3/src/components/form/base/__tests__/__snapshots__/ENumberField.spec.js.snap new file mode 100644 index 0000000000..8edadfeef6 --- /dev/null +++ b/frontend-vue3/src/components/form/base/__tests__/__snapshots__/ENumberField.spec.js.snap @@ -0,0 +1,43 @@ +// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html + +exports[`An ENumberField > looks like a numberfield > empty 1`] = ` +
+
+
+
+
+
+ + +
+
+
+
+
+
+`; + +exports[`An ENumberField > looks like a numberfield > with text 1`] = ` +
+
+
+
+
+
+ + +
+
+
+
+
+
+`; diff --git a/frontend-vue3/src/components/form/base/__tests__/__snapshots__/EParseField.spec.js.snap b/frontend-vue3/src/components/form/base/__tests__/__snapshots__/EParseField.spec.js.snap new file mode 100644 index 0000000000..cb85b99c7d --- /dev/null +++ b/frontend-vue3/src/components/form/base/__tests__/__snapshots__/EParseField.spec.js.snap @@ -0,0 +1,41 @@ +// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html + +exports[`An EParseField > looks like a textfield > empty 1`] = ` +
+
+
+
+
+
+ + +
+
+
+
+
+
+`; + +exports[`An EParseField > looks like a textfield > with text 1`] = ` +
+
+
+
+
+
+ + +
+
+
+
+
+
+`; diff --git a/frontend-vue3/src/components/form/base/__tests__/__snapshots__/ESelect.spec.js.snap b/frontend-vue3/src/components/form/base/__tests__/__snapshots__/ESelect.spec.js.snap new file mode 100644 index 0000000000..31d24d86bb --- /dev/null +++ b/frontend-vue3/src/components/form/base/__tests__/__snapshots__/ESelect.spec.js.snap @@ -0,0 +1,272 @@ +// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html + +exports[`An ESelect > looks like a dropdown > dropdown closed with selected value 1`] = ` +
+
+
+
+ +
+
+
+ +
+`; + +exports[`An ESelect > looks like a dropdown > dropdown open 1`] = ` +
+
+
+
+
+
+ +
+ +
+
+
+ +
+
+ +
+
+ +
+
+
+
+
+ +
+`; + +exports[`An ESelect > looks like a dropdown > dropdown open with selected value 1`] = ` +
+
+
+
+
+
+ +
+
firstOption
+ +
+
+
+ +
+
+ +
+
+ +
+
+
+
+
+ +
+`; + +exports[`An ESelect > looks like a dropdown > no item selected 1`] = ` +
+
+
+
+ +
+
+
+
+`; diff --git a/frontend-vue3/src/components/form/base/__tests__/__snapshots__/ESwitch.spec.js.snap b/frontend-vue3/src/components/form/base/__tests__/__snapshots__/ESwitch.spec.js.snap new file mode 100644 index 0000000000..14d8c48196 --- /dev/null +++ b/frontend-vue3/src/components/form/base/__tests__/__snapshots__/ESwitch.spec.js.snap @@ -0,0 +1,57 @@ +// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html + +exports[`An ESwitch > looks like a switch > checked 1`] = ` +
+ +
+
+
+
+ +
+
+
+
+ +
+
+
+
+
+`; + +exports[`An ESwitch > looks like a switch > unchecked 1`] = ` +
+ +
+
+
+
+ +
+
+
+
+ +
+
+
+
+
+`; diff --git a/frontend-vue3/src/components/form/base/__tests__/__snapshots__/ETextArea.spec.js.snap b/frontend-vue3/src/components/form/base/__tests__/__snapshots__/ETextArea.spec.js.snap new file mode 100644 index 0000000000..9a08f89911 --- /dev/null +++ b/frontend-vue3/src/components/form/base/__tests__/__snapshots__/ETextArea.spec.js.snap @@ -0,0 +1,128 @@ +// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html + +exports[`An ETextArea > looks like a textarea > mountAsInControls 1`] = ` +
+
+
+
+
+
+ +
+ +
+
+
+
+
+
+
+
+`; + +exports[`An ETextArea > looks like a textarea > multiline 1`] = ` +
+
+
+
+
+
+ +
+ +
+
+
+
+
+
+
+
+`; + +exports[`An ETextArea > looks like a textarea > notext 1`] = ` +
+
+
+
+
+
+ +
+ +
+
+
+
+
+
+
+
+`; + +exports[`An ETextArea > looks like a textarea > withtext 1`] = ` +
+
+
+
+
+
+ +
+ +
+
+

Here comes a text with new lines and new lines with in them and tags a

+
+
+
+
+
+
+
+
+
+`; diff --git a/frontend-vue3/src/components/form/base/__tests__/__snapshots__/ETextField.spec.js.snap b/frontend-vue3/src/components/form/base/__tests__/__snapshots__/ETextField.spec.js.snap new file mode 100644 index 0000000000..e4d2333125 --- /dev/null +++ b/frontend-vue3/src/components/form/base/__tests__/__snapshots__/ETextField.spec.js.snap @@ -0,0 +1,42 @@ +// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html + +exports[`An ETextField > looks like a textfield > empty 1`] = ` +
+
+
+
+
+
+ + +
+
+
+
+
+
+`; + +exports[`An ETextField > looks like a textfield > with text 1`] = ` +
+
+
+
+
+
+ + +
+
+
+
+
+
+`; diff --git a/frontend-vue3/src/components/form/base/__tests__/__snapshots__/ETimePicker.spec.js.snap b/frontend-vue3/src/components/form/base/__tests__/__snapshots__/ETimePicker.spec.js.snap new file mode 100644 index 0000000000..d1fd281416 --- /dev/null +++ b/frontend-vue3/src/components/form/base/__tests__/__snapshots__/ETimePicker.spec.js.snap @@ -0,0 +1,358 @@ +// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html + +exports[`An ETimePicker > in locale de > looks like a time picker > pickerclosed 1`] = ` +
+
+
+
+
+
+ +
+
+
+
+ + +
+
+
+
+
+ +
+
+
+`; + +exports[`An ETimePicker > in locale de > looks like a time picker > pickeropen 1`] = ` +
+
+
+
+
+ +
+
+
+
+ + +
+
+
+
+
+
+ +
+
+ +
+`; + +exports[`An ETimePicker > in locale en > looks like a time picker > pickerclosed 1`] = ` +
+
+
+
+
+
+ +
+
+
+
+ + +
+
+
+
+
+ +
+
+
+`; + +exports[`An ETimePicker > in locale en > looks like a time picker > pickeropen 1`] = ` +
+
+
+
+
+ +
+
+
+
+ + +
+
+
+
+
+
+ +
+
+ +
+`; diff --git a/frontend-vue3/src/components/form/tiptap/AutoLinkDecoration.js b/frontend-vue3/src/components/form/tiptap/AutoLinkDecoration.js new file mode 100644 index 0000000000..162016a06e --- /dev/null +++ b/frontend-vue3/src/components/form/tiptap/AutoLinkDecoration.js @@ -0,0 +1,77 @@ +import { Extension } from '@tiptap/vue-3' +import { Plugin, PluginKey } from '@tiptap/pm/state' +import { Decoration, DecorationSet } from '@tiptap/pm/view' +import LinkifyIt from 'linkify-it' + +export const AutoLinkKey = new PluginKey('autoLinkDecoration') + +export const AutoLinkDecoration = Extension.create({ + name: 'autoLinkDecoration', + addProseMirrorPlugins() { + const linkify = new LinkifyIt() + /** + * @param {import('prosemirror-model').Node} doc + */ + const urlDecoration = (doc) => { + const decorations = [] + doc.descendants((node, pos) => { + if (node.isText && linkify.pretest(node.text)) { + const matches = linkify.match(node.text) + matches?.forEach(({ index, lastIndex, url }) => { + if (url.charAt(0) === '/') { + return + } + let link + try { + link = new URL(url) + } catch (_) { + /* It can't be parsed as an url */ + } + if (!link.host.includes('.') && !link.port) { + return + } + if (!['http:', 'https:'].includes(link.protocol)) { + return + } + const attrs = { + nodeName: 'a', + href: url, + class: 'autolink', + target: '_blank', + rel: 'noopener noreferrer', + } + if (this.editor.isEditable) { + attrs.onclick = `(event.metaKey || event.ctrlKey || event.detail > 1) && window.open("${link}", "_blank");` + } + decorations.push( + Decoration.inline(pos + index, pos + lastIndex, attrs, { + start: pos + index, + end: pos + lastIndex, + }) + ) + }) + } + }) + return DecorationSet.create(doc, decorations) + } + + return [ + new Plugin({ + key: AutoLinkKey, + state: { + init: (_, { doc }) => { + return urlDecoration(doc) + }, + apply: (tr, oldState) => { + return tr.docChanged ? urlDecoration(tr.doc) : oldState + }, + }, + props: { + decorations(state) { + return this.getState(state) + }, + }, + }), + ] + }, +}) diff --git a/frontend-vue3/src/components/form/tiptap/TiptapEditor.vue b/frontend-vue3/src/components/form/tiptap/TiptapEditor.vue new file mode 100644 index 0000000000..4a6b5c303a --- /dev/null +++ b/frontend-vue3/src/components/form/tiptap/TiptapEditor.vue @@ -0,0 +1,398 @@ + + + + diff --git a/frontend-vue3/src/components/form/tiptap/TiptapToolbarButton.vue b/frontend-vue3/src/components/form/tiptap/TiptapToolbarButton.vue new file mode 100644 index 0000000000..8d22690a42 --- /dev/null +++ b/frontend-vue3/src/components/form/tiptap/TiptapToolbarButton.vue @@ -0,0 +1,13 @@ + + diff --git a/frontend-vue3/src/components/form/tiptap/VTiptapEditor.vue b/frontend-vue3/src/components/form/tiptap/VTiptapEditor.vue new file mode 100644 index 0000000000..7fd712c2bb --- /dev/null +++ b/frontend-vue3/src/components/form/tiptap/VTiptapEditor.vue @@ -0,0 +1,87 @@ + + + diff --git a/frontend-vue3/src/components/generic/AvatarRow.vue b/frontend-vue3/src/components/generic/AvatarRow.vue new file mode 100644 index 0000000000..b52b2a758b --- /dev/null +++ b/frontend-vue3/src/components/generic/AvatarRow.vue @@ -0,0 +1,86 @@ + + + + + diff --git a/frontend-vue3/src/components/generic/CategoryChip.vue b/frontend-vue3/src/components/generic/CategoryChip.vue new file mode 100644 index 0000000000..42f57213a5 --- /dev/null +++ b/frontend-vue3/src/components/generic/CategoryChip.vue @@ -0,0 +1,66 @@ + + + + + diff --git a/frontend-vue3/src/components/generic/ClipboardInfoDialog.vue b/frontend-vue3/src/components/generic/ClipboardInfoDialog.vue new file mode 100644 index 0000000000..046c202c04 --- /dev/null +++ b/frontend-vue3/src/components/generic/ClipboardInfoDialog.vue @@ -0,0 +1,87 @@ + + + diff --git a/frontend-vue3/src/components/generic/DetailPane.vue b/frontend-vue3/src/components/generic/DetailPane.vue new file mode 100644 index 0000000000..c055c441c0 --- /dev/null +++ b/frontend-vue3/src/components/generic/DetailPane.vue @@ -0,0 +1,42 @@ + + + diff --git a/frontend-vue3/src/components/generic/GenericChip.vue b/frontend-vue3/src/components/generic/GenericChip.vue new file mode 100644 index 0000000000..d1be5adc09 --- /dev/null +++ b/frontend-vue3/src/components/generic/GenericChip.vue @@ -0,0 +1,48 @@ + + + + + diff --git a/frontend-vue3/src/components/generic/GenericPage.vue b/frontend-vue3/src/components/generic/GenericPage.vue new file mode 100644 index 0000000000..3faea56de5 --- /dev/null +++ b/frontend-vue3/src/components/generic/GenericPage.vue @@ -0,0 +1,26 @@ + + + diff --git a/frontend-vue3/src/components/generic/IconWithTooltip.vue b/frontend-vue3/src/components/generic/IconWithTooltip.vue new file mode 100644 index 0000000000..35b3e499ed --- /dev/null +++ b/frontend-vue3/src/components/generic/IconWithTooltip.vue @@ -0,0 +1,75 @@ + + + + + diff --git a/frontend-vue3/src/components/generic/LockButton.vue b/frontend-vue3/src/components/generic/LockButton.vue new file mode 100644 index 0000000000..899e84d463 --- /dev/null +++ b/frontend-vue3/src/components/generic/LockButton.vue @@ -0,0 +1,95 @@ + + + + + diff --git a/frontend-vue3/src/components/generic/LockUnlockListItem.vue b/frontend-vue3/src/components/generic/LockUnlockListItem.vue new file mode 100644 index 0000000000..f00872d349 --- /dev/null +++ b/frontend-vue3/src/components/generic/LockUnlockListItem.vue @@ -0,0 +1,27 @@ + + + diff --git a/frontend-vue3/src/components/generic/useClipboardEntity.js b/frontend-vue3/src/components/generic/useClipboardEntity.js new file mode 100644 index 0000000000..2ca7e74604 --- /dev/null +++ b/frontend-vue3/src/components/generic/useClipboardEntity.js @@ -0,0 +1,89 @@ +import { computed, ref } from 'vue' + +export function useClipboardEntity({ + fetchClipboardEntity, + onEntityLoaded, + onEntityLoadFailed, +}) { + const clipboardPermission = ref('unknown') + const clipboardEntity = ref(null) + const _clipoardEntityUrl = ref(null) + const loading = ref(false) + + const clipboardEntityUrl = computed({ + get() { + return _clipoardEntityUrl.value + }, + set: setClipboardEntityUrl, + }) + + async function setClipboardEntityUrl(url) { + loading.value = true + _clipoardEntityUrl.value = url + + return fetchClipboardEntity(url) + .then((entityProxy) => { + if (entityProxy == null) return Promise.reject('not found') + return entityProxy?._meta.load + }) + .then((entity) => { + clipboardEntity.value = entity + onEntityLoaded(entity) + loading.value = false + }) + .catch(() => { + clipboardEntity.value = null + onEntityLoadFailed(url) + loading.value = false + }) + } + + const clipboardAccessDenied = computed(() => { + return ( + clipboardPermission.value === 'unaccessible' || + clipboardPermission.value === 'denied' + ) + }) + + const showClipboardPrompt = computed(() => clipboardPermission.value === 'prompt') + + const hasClipboardEntity = computed(() => { + return clipboardEntity.value != null && clipboardEntity.value._meta.self != null + }) + + const attemptLoadingEntityFromClipboard = async () => { + clipboardEntity.value = null + return navigator.permissions + .query({ name: 'clipboard-read' }) + .then(async (p) => { + clipboardPermission.value = p.state + if (p.state === 'granted') { + const url = await navigator.clipboard.readText() + if (url) return setClipboardEntityUrl(url) + } + // If we get here, we have failed to get the url from the clipboard + onEntityLoadFailed(null) + }) + .catch(() => { + clipboardPermission.value = 'unaccessible' + console.warn('clipboard permission not requestable') + }) + } + + const clearClipboard = async () => { + await navigator.clipboard.writeText('') + attemptLoadingEntityFromClipboard() + } + + return { + clipboardAccessDenied, + showClipboardPrompt, + hasClipboardEntity, + clipboardEntity, + clipboardEntityUrl, + clipboardEntityLoading: loading, + attemptLoadingEntityFromClipboard, + setClipboardEntityUrl, + clearClipboard, + } +} diff --git a/frontend-vue3/src/components/layout/AuthContainer.vue b/frontend-vue3/src/components/layout/AuthContainer.vue new file mode 100644 index 0000000000..2928b0a068 --- /dev/null +++ b/frontend-vue3/src/components/layout/AuthContainer.vue @@ -0,0 +1,53 @@ + + + + + diff --git a/frontend-vue3/src/components/layout/ContentActions.vue b/frontend-vue3/src/components/layout/ContentActions.vue new file mode 100644 index 0000000000..628f58f75e --- /dev/null +++ b/frontend-vue3/src/components/layout/ContentActions.vue @@ -0,0 +1,13 @@ + + + diff --git a/frontend-vue3/src/components/layout/ContentCard.vue b/frontend-vue3/src/components/layout/ContentCard.vue new file mode 100644 index 0000000000..34b316701d --- /dev/null +++ b/frontend-vue3/src/components/layout/ContentCard.vue @@ -0,0 +1,80 @@ + + + + + + + diff --git a/frontend-vue3/src/components/layout/ContentGroup.vue b/frontend-vue3/src/components/layout/ContentGroup.vue new file mode 100644 index 0000000000..ed43fc339b --- /dev/null +++ b/frontend-vue3/src/components/layout/ContentGroup.vue @@ -0,0 +1,50 @@ + + + + + + + diff --git a/frontend-vue3/src/components/layout/HorizontalRule.vue b/frontend-vue3/src/components/layout/HorizontalRule.vue new file mode 100644 index 0000000000..268ff4541a --- /dev/null +++ b/frontend-vue3/src/components/layout/HorizontalRule.vue @@ -0,0 +1,34 @@ + + + + + diff --git a/frontend-vue3/src/components/layout/IconSpacer.vue b/frontend-vue3/src/components/layout/IconSpacer.vue new file mode 100644 index 0000000000..6340c82a7e --- /dev/null +++ b/frontend-vue3/src/components/layout/IconSpacer.vue @@ -0,0 +1,15 @@ + + + + + diff --git a/frontend-vue3/src/components/layout/LanguageSwitcher.vue b/frontend-vue3/src/components/layout/LanguageSwitcher.vue new file mode 100644 index 0000000000..03d890868b --- /dev/null +++ b/frontend-vue3/src/components/layout/LanguageSwitcher.vue @@ -0,0 +1,41 @@ + + + + + diff --git a/frontend-vue3/src/components/layout/SidebarListItem.vue b/frontend-vue3/src/components/layout/SidebarListItem.vue new file mode 100644 index 0000000000..5bb60d52c2 --- /dev/null +++ b/frontend-vue3/src/components/layout/SidebarListItem.vue @@ -0,0 +1,33 @@ + + + + + diff --git a/frontend-vue3/src/components/layout/TextAlignBaseline.vue b/frontend-vue3/src/components/layout/TextAlignBaseline.vue new file mode 100644 index 0000000000..d28a2c7c3b --- /dev/null +++ b/frontend-vue3/src/components/layout/TextAlignBaseline.vue @@ -0,0 +1,28 @@ + + + + + diff --git a/frontend-vue3/src/components/material/DialogMaterialItemCreate.vue b/frontend-vue3/src/components/material/DialogMaterialItemCreate.vue new file mode 100644 index 0000000000..c6a9bf89b7 --- /dev/null +++ b/frontend-vue3/src/components/material/DialogMaterialItemCreate.vue @@ -0,0 +1,77 @@ + + + + + diff --git a/frontend-vue3/src/components/material/DialogMaterialItemEdit.vue b/frontend-vue3/src/components/material/DialogMaterialItemEdit.vue new file mode 100644 index 0000000000..28a89d6031 --- /dev/null +++ b/frontend-vue3/src/components/material/DialogMaterialItemEdit.vue @@ -0,0 +1,73 @@ + + + + + diff --git a/frontend-vue3/src/components/material/DialogMaterialItemForm.vue b/frontend-vue3/src/components/material/DialogMaterialItemForm.vue new file mode 100644 index 0000000000..edc632d4d0 --- /dev/null +++ b/frontend-vue3/src/components/material/DialogMaterialItemForm.vue @@ -0,0 +1,45 @@ + + + diff --git a/frontend-vue3/src/components/material/MaterialCreateItem.vue b/frontend-vue3/src/components/material/MaterialCreateItem.vue new file mode 100644 index 0000000000..01b8a41531 --- /dev/null +++ b/frontend-vue3/src/components/material/MaterialCreateItem.vue @@ -0,0 +1,135 @@ + + + + + diff --git a/frontend-vue3/src/components/material/MaterialLists.vue b/frontend-vue3/src/components/material/MaterialLists.vue new file mode 100644 index 0000000000..8e8490a6f7 --- /dev/null +++ b/frontend-vue3/src/components/material/MaterialLists.vue @@ -0,0 +1,59 @@ + + + diff --git a/frontend-vue3/src/components/material/MaterialListsEdit.vue b/frontend-vue3/src/components/material/MaterialListsEdit.vue new file mode 100644 index 0000000000..3ba7a2e4ab --- /dev/null +++ b/frontend-vue3/src/components/material/MaterialListsEdit.vue @@ -0,0 +1,35 @@ + + diff --git a/frontend-vue3/src/components/material/MaterialTable.vue b/frontend-vue3/src/components/material/MaterialTable.vue new file mode 100644 index 0000000000..8e8ba61704 --- /dev/null +++ b/frontend-vue3/src/components/material/MaterialTable.vue @@ -0,0 +1,508 @@ + + + + + diff --git a/frontend-vue3/src/components/material/PeriodMaterialLists.vue b/frontend-vue3/src/components/material/PeriodMaterialLists.vue new file mode 100644 index 0000000000..fea2a29a43 --- /dev/null +++ b/frontend-vue3/src/components/material/PeriodMaterialLists.vue @@ -0,0 +1,40 @@ + + + diff --git a/frontend-vue3/src/components/material/ScheduleEntryLinks.vue b/frontend-vue3/src/components/material/ScheduleEntryLinks.vue new file mode 100644 index 0000000000..7895b50b8c --- /dev/null +++ b/frontend-vue3/src/components/material/ScheduleEntryLinks.vue @@ -0,0 +1,84 @@ + + + diff --git a/frontend-vue3/src/components/material/__tests__/shortScheduleEntryDescription.spec.js b/frontend-vue3/src/components/material/__tests__/shortScheduleEntryDescription.spec.js new file mode 100644 index 0000000000..f9c9812519 --- /dev/null +++ b/frontend-vue3/src/components/material/__tests__/shortScheduleEntryDescription.spec.js @@ -0,0 +1,39 @@ +import shortScheduleEntryDescription from '../shortScheduleEntryDescription.js' +import createI18n from '@/components/print/print-client/i18n.js' +import { i18n } from '@/plugins/i18n' + +describe('shortScheduleEntryDescription', () => { + const { translate } = createI18n(i18n.messages, 'en') + const tc = (key, _count, params) => translate(key, params) + + it.each([ + [{ _meta: { loading: true } }, ''], + [null, ''], + [undefined, ''], + [ + { + _meta: { loading: false }, + number: '1.2', + activity: () => ({ + title: 'foo', + }), + dayNumber: '3', + }, + '1.2', + ], + [ + { + _meta: { loading: false }, + number: '', + activity: () => ({ + title: 'foo', + }), + dayNumber: '3', + start: '2024-01-01T10:00:00+00:00', + }, + 'day 3 10:00', + ], + ])('maps %o to "%s"', (input, expected) => { + expect(shortScheduleEntryDescription(input, tc)).toEqual(expected) + }) +}) diff --git a/frontend-vue3/src/components/material/shortScheduleEntryDescription.js b/frontend-vue3/src/components/material/shortScheduleEntryDescription.js new file mode 100644 index 0000000000..7eedb20b9b --- /dev/null +++ b/frontend-vue3/src/components/material/shortScheduleEntryDescription.js @@ -0,0 +1,13 @@ +import { hourShort } from '@/common/helpers/dateHelperUTCFormatted.js' + +export default function shortScheduleEntryDescription(scheduleEntry, tc) { + if (!scheduleEntry || scheduleEntry._meta.loading) return '' + return ( + scheduleEntry?.number || + // For numbering style "none", display the activity title and day number instead + tc('global.shortScheduleEntryDescription', 1, { + dayNumber: scheduleEntry.dayNumber, + startTime: hourShort(scheduleEntry.start, tc), + }) + ) +} diff --git a/frontend-vue3/src/components/material/useMaterialViewHelper.js b/frontend-vue3/src/components/material/useMaterialViewHelper.js new file mode 100644 index 0000000000..9f686b2e97 --- /dev/null +++ b/frontend-vue3/src/components/material/useMaterialViewHelper.js @@ -0,0 +1,134 @@ +import { computed, onMounted, ref } from 'vue' +import { useRoute } from 'vue-router' +import * as XLSX from 'xlsx' +import { slugify } from '@/plugins/slugify.js' +import i18n from '@/plugins/i18n/index.js' +import dayjs from '@/common/helpers/dayjs.js' +import { apiStore } from '@/plugins/store/index.js' +import { materialListFromRoute } from '@/router.js' +import shortScheduleEntryDescription from './shortScheduleEntryDescription.js' + +function generateFilename(camp, materialList) { + const description = materialList + ? [i18n.t('components.material.useMaterialViewHelper.detail'), materialList] + : [i18n.t('components.material.useMaterialViewHelper.overview')] + const filename = [camp.name, ...description].map(slugify) + return [...filename, dayjs().format('YYMMDDHHmmss')].join('_') + '.xlsx' +} + +async function getActivity(camp, materialItem) { + if (!materialItem.materialNode) { + return null + } + const root = await materialItem.materialNode().$href('root') + return camp + .activities() + .items.find((activity) => activity.rootContentNode()._meta.self === root) +} + +async function getSheets(camp, collection, materialList) { + return await Promise.all( + collection.map(async ({ period, materialItems }) => { + const data = [ + [ + `${ + materialList ?? i18n.t('components.material.useMaterialViewHelper.overview') + }: ${period.description}`, + ], + [ + i18n.t('entity.materialItem.fields.quantity'), + i18n.t('entity.materialItem.fields.unit'), + i18n.t('entity.materialItem.fields.article'), + ...(!materialList ? [i18n.t('entity.materialItem.fields.list')] : []), + i18n.t('entity.materialItem.fields.reference'), + ], + ] + await Promise.all( + materialItems.items.map(async (materialItem) => { + const activity = await getActivity(camp, materialItem) + const scheduleEntries = activity + ?.scheduleEntries() + .items.map((item) => shortScheduleEntryDescription(item, i18n.tc.bind(i18n))) + .join(', ') + data.push([ + materialItem.quantity, + materialItem.unit, + materialItem.article, + ...(!materialList ? [materialItem.materialList().name] : []), + activity?.title + ? `${activity.category().short} ${activity?.title}: ${scheduleEntries}` + : period.description, + ]) + }) + ) + return { sheetName: period.description, data } + }) + ) +} + +/** + * @param {object} camp + * @param {{value: {period: object, materialItems: {items: array}}[]}} collection + * @param {string} materialList materialList name if set + */ +function downloadMaterialList(camp, collection, materialList) { + return async () => { + await camp.activities().$loadItems() + + const workbook = XLSX.utils.book_new() + const sheets = await getSheets(camp, collection.value, materialList) + sheets.forEach(({ sheetName, data }) => { + const worksheet = XLSX.utils.aoa_to_sheet(data) + const validSheetName = sheetName.replaceAll(/[?*[\]/\\:]/g, '') + workbook.SheetNames.push(validSheetName) + workbook.Sheets[validSheetName] = worksheet + }) + XLSX.writeFile(workbook, generateFilename(camp, materialList)) + } +} + +function loadPeriods(camp) { + const openPeriods = ref([]) + + camp.periods()._meta.load.then((period) => + period.items.forEach((period, index) => { + if (Date.parse(period.end) >= Date.now()) { + openPeriods.value.push(index) + } + }) + ) + + return openPeriods +} + +/** + * @param {Object} camp + * @param {boolean} [list] + */ +export function useMaterialViewHelper(camp, list) { + const computedList = computed(() => (list ? materialListFromRoute(useRoute()) : null)) + + const collection = computed(() => { + const materialList = computedList.value?._meta.self + return camp.periods().items.map((period) => ({ + period, + materialItems: apiStore.get().materialItems({ + period: period._meta.self, + materialList, + }), + })) + }) + + const downloadXlsx = downloadMaterialList(camp, collection, computedList.value?.name) + const openPeriods = loadPeriods(camp) + + onMounted(() => { + collection.value.map(({ materialItems }) => materialItems.$reload()) + }) + + return { + collection, + downloadXlsx, + openPeriods, + } +} diff --git a/frontend-vue3/src/components/navigation/Logo.vue b/frontend-vue3/src/components/navigation/Logo.vue new file mode 100644 index 0000000000..eabeb9f704 --- /dev/null +++ b/frontend-vue3/src/components/navigation/Logo.vue @@ -0,0 +1,33 @@ + + + + + diff --git a/frontend-vue3/src/components/navigation/SideBar.vue b/frontend-vue3/src/components/navigation/SideBar.vue new file mode 100644 index 0000000000..9ae24df8f3 --- /dev/null +++ b/frontend-vue3/src/components/navigation/SideBar.vue @@ -0,0 +1,55 @@ + + + + + diff --git a/frontend-vue3/src/components/navigation/TopNavigationItem.vue b/frontend-vue3/src/components/navigation/TopNavigationItem.vue new file mode 100644 index 0000000000..bca9198507 --- /dev/null +++ b/frontend-vue3/src/components/navigation/TopNavigationItem.vue @@ -0,0 +1,24 @@ + + + + + + diff --git a/frontend-vue3/src/components/navigation/UserMeta.vue b/frontend-vue3/src/components/navigation/UserMeta.vue new file mode 100644 index 0000000000..f876ee438a --- /dev/null +++ b/frontend-vue3/src/components/navigation/UserMeta.vue @@ -0,0 +1,198 @@ + + + + + diff --git a/frontend-vue3/src/components/personal_invitations/DialogPersonalInvitationReject.vue b/frontend-vue3/src/components/personal_invitations/DialogPersonalInvitationReject.vue new file mode 100644 index 0000000000..237da519ad --- /dev/null +++ b/frontend-vue3/src/components/personal_invitations/DialogPersonalInvitationReject.vue @@ -0,0 +1,67 @@ + + + + + diff --git a/frontend-vue3/src/components/personal_invitations/PersonalInvitations.vue b/frontend-vue3/src/components/personal_invitations/PersonalInvitations.vue new file mode 100644 index 0000000000..6964e6c354 --- /dev/null +++ b/frontend-vue3/src/components/personal_invitations/PersonalInvitations.vue @@ -0,0 +1,137 @@ + + diff --git a/frontend-vue3/src/components/print/PrintConfigurator.vue b/frontend-vue3/src/components/print/PrintConfigurator.vue new file mode 100644 index 0000000000..1bf92db25e --- /dev/null +++ b/frontend-vue3/src/components/print/PrintConfigurator.vue @@ -0,0 +1,282 @@ + + + + + diff --git a/frontend-vue3/src/components/print/__tests__/repairPrintConfig.spec.js b/frontend-vue3/src/components/print/__tests__/repairPrintConfig.spec.js new file mode 100644 index 0000000000..54c598658b --- /dev/null +++ b/frontend-vue3/src/components/print/__tests__/repairPrintConfig.spec.js @@ -0,0 +1,948 @@ +import repairConfig from '../repairPrintConfig.js' +import PicassoConfig from '../config/PicassoConfig.vue' +import ActivityConfig from '../config/ActivityConfig.vue' +import CoverConfig from '../config/CoverConfig.vue' +import ProgramConfig from '../config/ProgramConfig.vue' +import StoryConfig from '../config/StoryConfig.vue' +import TocConfig from '../config/TocConfig.vue' + +describe('repairConfig', () => { + const camp = { + _meta: { self: '/camps/1a2b3c4d' }, + name: 'test camp', + periods: () => ({ + items: [ + { + _meta: { self: '/periods/1a2b3c4d' }, + }, + ], + }), + } + const availableLocales = ['en-GB', 'de-CH', 'de-CH-scout'] + const componentRepairers = Object.fromEntries( + [ + ActivityConfig, + CoverConfig, + PicassoConfig, + ProgramConfig, + StoryConfig, + TocConfig, + ].map((component) => [component.name.replace(/Config$/, ''), component.repairConfig]) + ) + const defaultContents = [ + { type: 'Picasso', options: { periods: ['/periods/1a2b3c4d'], orientation: 'L' } }, + ] + const args = [camp, availableLocales, 'en', componentRepairers, defaultContents] + + test('fills empty config with default data', async () => { + // given + const config = {} + + // when + const result = repairConfig(config, ...args) + + // then + expect(result).toEqual({ + camp: '/camps/1a2b3c4d', + contents: [ + { + type: 'Picasso', + options: { periods: ['/periods/1a2b3c4d'], orientation: 'L' }, + }, + ], + documentName: 'test camp', + language: 'en-GB', + }) + }) + + test('leaves valid config alone', async () => { + // given + const config = { + camp: '/camps/1a2b3c4d', + contents: [ + { + type: 'Picasso', + options: { periods: ['/periods/1a2b3c4d'], orientation: 'L' }, + }, + ], + documentName: 'test camp', + language: 'en-GB', + } + + // when + const result = repairConfig(config, ...args) + + // then + expect(result).toEqual({ + camp: '/camps/1a2b3c4d', + contents: [ + { + type: 'Picasso', + options: { periods: ['/periods/1a2b3c4d'], orientation: 'L' }, + }, + ], + documentName: 'test camp', + language: 'en-GB', + }) + }) + + test('allows valid language', async () => { + // given + const config = { + camp: '/camps/1a2b3c4d', + contents: [ + { + type: 'Picasso', + options: { periods: ['/periods/1a2b3c4d'], orientation: 'L' }, + }, + ], + documentName: 'test camp', + language: 'de-CH-scout', + } + + // when + const result = repairConfig(config, ...args) + + // then + expect(result).toEqual({ + camp: '/camps/1a2b3c4d', + contents: [ + { + type: 'Picasso', + options: { periods: ['/periods/1a2b3c4d'], orientation: 'L' }, + }, + ], + documentName: 'test camp', + language: 'de-CH-scout', + }) + }) + + test('replaces invalid language with fallback language', async () => { + // given + const config = { + camp: '/camps/1a2b3c4d', + contents: [ + { + type: 'Picasso', + options: { periods: ['/periods/1a2b3c4d'], orientation: 'L' }, + }, + ], + documentName: 'test camp', + language: 'definitely-not-a-supported-language', + } + + // when + const result = repairConfig( + config, + camp, + availableLocales, + 'de-CH-scout', + componentRepairers, + defaultContents + ) + + // then + expect(result).toEqual({ + camp: '/camps/1a2b3c4d', + contents: [ + { + type: 'Picasso', + options: { periods: ['/periods/1a2b3c4d'], orientation: 'L' }, + }, + ], + documentName: 'test camp', + language: 'de-CH-scout', + }) + }) + + test('replaces invalid language with any valid language if fallback language is also invalid', async () => { + // given + const config = { + camp: '/camps/1a2b3c4d', + contents: [ + { + type: 'Picasso', + options: { periods: ['/periods/1a2b3c4d'], orientation: 'L' }, + }, + ], + documentName: 'test camp', + language: 'definitely-not-a-supported-language', + } + + // when + const result = repairConfig( + config, + camp, + availableLocales, + 'definitely-not-a-valid-language', + componentRepairers, + defaultContents + ) + + // then + expect(result).toEqual({ + camp: '/camps/1a2b3c4d', + contents: [ + { + type: 'Picasso', + options: { periods: ['/periods/1a2b3c4d'], orientation: 'L' }, + }, + ], + documentName: 'test camp', + language: 'en-GB', + }) + }) + + test('leaves custom documentName alone', async () => { + // given + const config = { + camp: '/camps/1a2b3c4d', + contents: [ + { + type: 'Picasso', + options: { periods: ['/periods/1a2b3c4d'], orientation: 'L' }, + }, + ], + documentName: 'foobar', + language: 'en-GB', + } + + // when + const result = repairConfig(config, ...args) + + // then + expect(result).toEqual({ + camp: '/camps/1a2b3c4d', + contents: [ + { + type: 'Picasso', + options: { periods: ['/periods/1a2b3c4d'], orientation: 'L' }, + }, + ], + documentName: 'foobar', + language: 'en-GB', + }) + }) + + test('fills in missing documentName', async () => { + // given + const config = { + camp: '/camps/1a2b3c4d', + contents: [ + { + type: 'Picasso', + options: { periods: ['/periods/1a2b3c4d'], orientation: 'L' }, + }, + ], + documentName: '', + language: 'en-GB', + } + + // when + const result = repairConfig(config, ...args) + + // then + expect(result).toEqual({ + camp: '/camps/1a2b3c4d', + contents: [ + { + type: 'Picasso', + options: { periods: ['/periods/1a2b3c4d'], orientation: 'L' }, + }, + ], + documentName: 'test camp', + language: 'en-GB', + }) + }) + + test('overwrites camp URI', async () => { + // given + const config = { + camp: '/camps/1a2b3c4d?something', + contents: [ + { + type: 'Picasso', + options: { periods: ['/periods/1a2b3c4d'], orientation: 'L' }, + }, + ], + documentName: 'test camp', + language: 'en-GB', + } + + // when + const result = repairConfig(config, ...args) + + // then + expect(result).toEqual({ + camp: '/camps/1a2b3c4d', + contents: [ + { + type: 'Picasso', + options: { periods: ['/periods/1a2b3c4d'], orientation: 'L' }, + }, + ], + documentName: 'test camp', + language: 'en-GB', + }) + }) + + test('overwrites invalid contents with default', async () => { + // given + const config = { + camp: '/camps/1a2b3c4d', + contents: {}, + documentName: 'test camp', + language: 'en-GB', + } + + // when + const result = repairConfig(config, ...args) + + // then + expect(result).toEqual({ + camp: '/camps/1a2b3c4d', + contents: [ + { + type: 'Picasso', + options: { periods: ['/periods/1a2b3c4d'], orientation: 'L' }, + }, + ], + documentName: 'test camp', + language: 'en-GB', + }) + }) + + test('overwrites null contents with default', async () => { + // given + const config = { + camp: '/camps/1a2b3c4d', + contents: null, + documentName: 'test camp', + language: 'en-GB', + } + + // when + const result = repairConfig(config, ...args) + + // then + expect(result).toEqual({ + camp: '/camps/1a2b3c4d', + contents: [ + { + type: 'Picasso', + options: { periods: ['/periods/1a2b3c4d'], orientation: 'L' }, + }, + ], + documentName: 'test camp', + language: 'en-GB', + }) + }) + + test('leaves empty content alone', async () => { + // given + const config = { + camp: '/camps/1a2b3c4d', + contents: [], + documentName: 'test camp', + language: 'en-GB', + } + + // when + const result = repairConfig(config, ...args) + + // then + expect(result).toEqual({ + camp: '/camps/1a2b3c4d', + contents: [], + documentName: 'test camp', + language: 'en-GB', + }) + }) + + test('filters out unknown content', async () => { + // given + const config = { + camp: '/camps/1a2b3c4d', + contents: [ + { + type: 'SomethingUnsupported', + options: {}, + }, + ], + documentName: 'test camp', + language: 'en-GB', + } + + // when + const result = repairConfig(config, ...args) + + // then + expect(result).toEqual({ + camp: '/camps/1a2b3c4d', + contents: [], + documentName: 'test camp', + language: 'en-GB', + }) + }) + + describe('activity', () => { + test('leaves config alone', async () => { + // given + const config = { + camp: '/camps/1a2b3c4d', + contents: [ + { + type: 'Activity', + foo: 'bar', + }, + ], + documentName: 'test camp', + language: 'en-GB', + } + + // when + const result = repairConfig(config, ...args) + + // then + expect(result).toEqual({ + camp: '/camps/1a2b3c4d', + contents: [ + { + type: 'Activity', + foo: 'bar', + }, + ], + documentName: 'test camp', + language: 'en-GB', + }) + }) + }) + + describe('cover', () => { + test('leaves config alone', async () => { + // given + const config = { + camp: '/camps/1a2b3c4d', + contents: [ + { + type: 'Cover', + foo: 'bar', + }, + ], + documentName: 'test camp', + language: 'en-GB', + } + + // when + const result = repairConfig(config, ...args) + + // then + expect(result).toEqual({ + camp: '/camps/1a2b3c4d', + contents: [ + { + type: 'Cover', + foo: 'bar', + }, + ], + documentName: 'test camp', + language: 'en-GB', + }) + }) + }) + + describe('picasso', () => { + test('adds missing options', async () => { + // given + const config = { + camp: '/camps/1a2b3c4d', + contents: [ + { + type: 'Picasso', + }, + ], + documentName: 'test camp', + language: 'en-GB', + } + + // when + const result = repairConfig(config, ...args) + + // then + expect(result).toEqual({ + camp: '/camps/1a2b3c4d', + contents: [ + { + type: 'Picasso', + options: { periods: [], orientation: 'L' }, + }, + ], + documentName: 'test camp', + language: 'en-GB', + }) + }) + + test('allows landscape mode', async () => { + // given + const config = { + camp: '/camps/1a2b3c4d', + contents: [ + { + type: 'Picasso', + options: { periods: ['/periods/1a2b3c4d'], orientation: 'L' }, + }, + ], + documentName: 'test camp', + language: 'en-GB', + } + + // when + const result = repairConfig(config, ...args) + + // then + expect(result).toEqual({ + camp: '/camps/1a2b3c4d', + contents: [ + { + type: 'Picasso', + options: { periods: ['/periods/1a2b3c4d'], orientation: 'L' }, + }, + ], + documentName: 'test camp', + language: 'en-GB', + }) + }) + + test('allows portrait mode', async () => { + // given + const config = { + camp: '/camps/1a2b3c4d', + contents: [ + { + type: 'Picasso', + options: { periods: ['/periods/1a2b3c4d'], orientation: 'P' }, + }, + ], + documentName: 'test camp', + language: 'en-GB', + } + + // when + const result = repairConfig(config, ...args) + + // then + expect(result).toEqual({ + camp: '/camps/1a2b3c4d', + contents: [ + { + type: 'Picasso', + options: { periods: ['/periods/1a2b3c4d'], orientation: 'P' }, + }, + ], + documentName: 'test camp', + language: 'en-GB', + }) + }) + + test('allows empty periods', async () => { + // given + const config = { + camp: '/camps/1a2b3c4d', + contents: [ + { + type: 'Picasso', + options: { periods: [], orientation: 'L' }, + }, + ], + documentName: 'test camp', + language: 'en-GB', + } + + // when + const result = repairConfig(config, ...args) + + // then + expect(result).toEqual({ + camp: '/camps/1a2b3c4d', + contents: [ + { + type: 'Picasso', + options: { periods: [], orientation: 'L' }, + }, + ], + documentName: 'test camp', + language: 'en-GB', + }) + }) + + test('overwrites invalid orientation', async () => { + // given + const config = { + camp: '/camps/1a2b3c4d', + contents: [ + { + type: 'Picasso', + options: { periods: ['/periods/1a2b3c4d'], orientation: 'hello' }, + }, + ], + documentName: 'test camp', + language: 'en-GB', + } + + // when + const result = repairConfig(config, ...args) + + // then + expect(result).toEqual({ + camp: '/camps/1a2b3c4d', + contents: [ + { + type: 'Picasso', + options: { periods: ['/periods/1a2b3c4d'], orientation: 'L' }, + }, + ], + documentName: 'test camp', + language: 'en-GB', + }) + }) + + test('filters out unknown periods', async () => { + // given + const config = { + camp: '/camps/1a2b3c4d', + contents: [ + { + type: 'Picasso', + options: { + periods: ['/periods/11112222', '/periods/1a2b3c4d'], + orientation: 'L', + }, + }, + ], + documentName: 'test camp', + language: 'en-GB', + } + + // when + const result = repairConfig(config, ...args) + + // then + expect(result).toEqual({ + camp: '/camps/1a2b3c4d', + contents: [ + { + type: 'Picasso', + options: { periods: ['/periods/1a2b3c4d'], orientation: 'L' }, + }, + ], + documentName: 'test camp', + language: 'en-GB', + }) + }) + }) + + describe('program', () => { + test('adds missing options', async () => { + // given + const config = { + camp: '/camps/1a2b3c4d', + contents: [ + { + type: 'Program', + }, + ], + documentName: 'test camp', + language: 'en-GB', + } + + // when + const result = repairConfig(config, ...args) + + // then + expect(result).toEqual({ + camp: '/camps/1a2b3c4d', + contents: [ + { + type: 'Program', + options: { + periods: [], + dayOverview: true, + }, + }, + ], + documentName: 'test camp', + language: 'en-GB', + }) + }) + + test('adds missing dayOverview flag', async () => { + // given + const config = { + camp: '/camps/1a2b3c4d', + contents: [ + { + type: 'Program', + options: { + periods: ['/periods/1a2b3c4d'], + }, + }, + ], + documentName: 'test camp', + language: 'en-GB', + } + + // when + const result = repairConfig(config, ...args) + + // then + expect(result).toEqual({ + camp: '/camps/1a2b3c4d', + contents: [ + { + type: 'Program', + options: { + periods: ['/periods/1a2b3c4d'], + dayOverview: true, + }, + }, + ], + documentName: 'test camp', + language: 'en-GB', + }) + }) + + test('allows dayOverview false', async () => { + // given + const config = { + camp: '/camps/1a2b3c4d', + contents: [ + { + type: 'Program', + options: { + periods: ['/periods/1a2b3c4d'], + dayOverview: false, + }, + }, + ], + documentName: 'test camp', + language: 'en-GB', + } + + // when + const result = repairConfig(config, ...args) + + // then + expect(result).toEqual({ + camp: '/camps/1a2b3c4d', + contents: [ + { + type: 'Program', + options: { + periods: ['/periods/1a2b3c4d'], + dayOverview: false, + }, + }, + ], + documentName: 'test camp', + language: 'en-GB', + }) + }) + + test('allows empty periods', async () => { + // given + const config = { + camp: '/camps/1a2b3c4d', + contents: [ + { + type: 'Program', + options: { periods: [], dayOverview: true }, + }, + ], + documentName: 'test camp', + language: 'en-GB', + } + + // when + const result = repairConfig(config, ...args) + + // then + expect(result).toEqual({ + camp: '/camps/1a2b3c4d', + contents: [ + { + type: 'Program', + options: { periods: [], dayOverview: true }, + }, + ], + documentName: 'test camp', + language: 'en-GB', + }) + }) + + test('filters out unknown periods', async () => { + // given + const config = { + camp: '/camps/1a2b3c4d', + contents: [ + { + type: 'Program', + options: { + periods: ['/periods/11112222', '/periods/1a2b3c4d'], + dayOverview: true, + }, + }, + ], + documentName: 'test camp', + language: 'en-GB', + } + + // when + const result = repairConfig(config, ...args) + + // then + expect(result).toEqual({ + camp: '/camps/1a2b3c4d', + contents: [ + { + type: 'Program', + options: { + periods: ['/periods/1a2b3c4d'], + dayOverview: true, + }, + }, + ], + documentName: 'test camp', + language: 'en-GB', + }) + }) + }) + + describe('story', () => { + test('adds missing options', async () => { + // given + const config = { + camp: '/camps/1a2b3c4d', + contents: [ + { + type: 'Story', + }, + ], + documentName: 'test camp', + language: 'en-GB', + } + + // when + const result = repairConfig(config, ...args) + + // then + expect(result).toEqual({ + camp: '/camps/1a2b3c4d', + contents: [ + { + type: 'Story', + options: { periods: [] }, + }, + ], + documentName: 'test camp', + language: 'en-GB', + }) + }) + + test('allows empty periods', async () => { + // given + const config = { + camp: '/camps/1a2b3c4d', + contents: [ + { + type: 'Story', + options: { periods: [] }, + }, + ], + documentName: 'test camp', + language: 'en-GB', + } + + // when + const result = repairConfig(config, ...args) + + // then + expect(result).toEqual({ + camp: '/camps/1a2b3c4d', + contents: [ + { + type: 'Story', + options: { periods: [] }, + }, + ], + documentName: 'test camp', + language: 'en-GB', + }) + }) + + test('filters out unknown periods', async () => { + // given + const config = { + camp: '/camps/1a2b3c4d', + contents: [ + { + type: 'Story', + options: { + periods: ['/periods/11112222', '/periods/1a2b3c4d'], + }, + }, + ], + documentName: 'test camp', + language: 'en-GB', + } + + // when + const result = repairConfig(config, ...args) + + // then + expect(result).toEqual({ + camp: '/camps/1a2b3c4d', + contents: [ + { + type: 'Story', + options: { periods: ['/periods/1a2b3c4d'] }, + }, + ], + documentName: 'test camp', + language: 'en-GB', + }) + }) + }) + + describe('toc', () => { + test('leaves config alone', async () => { + // given + const config = { + camp: '/camps/1a2b3c4d', + contents: [ + { + type: 'Toc', + foo: 'bar', + }, + ], + documentName: 'test camp', + language: 'en-GB', + } + + // when + const result = repairConfig(config, ...args) + + // then + expect(result).toEqual({ + camp: '/camps/1a2b3c4d', + contents: [ + { + type: 'Toc', + foo: 'bar', + }, + ], + documentName: 'test camp', + language: 'en-GB', + }) + }) + }) +}) diff --git a/frontend-vue3/src/components/print/config/ActivityConfig.vue b/frontend-vue3/src/components/print/config/ActivityConfig.vue new file mode 100644 index 0000000000..2f3f3af0e3 --- /dev/null +++ b/frontend-vue3/src/components/print/config/ActivityConfig.vue @@ -0,0 +1,73 @@ + + + diff --git a/frontend-vue3/src/components/print/config/ActivityListConfig.vue b/frontend-vue3/src/components/print/config/ActivityListConfig.vue new file mode 100644 index 0000000000..4d5fb833dc --- /dev/null +++ b/frontend-vue3/src/components/print/config/ActivityListConfig.vue @@ -0,0 +1,92 @@ + + + diff --git a/frontend-vue3/src/components/print/config/CoverConfig.vue b/frontend-vue3/src/components/print/config/CoverConfig.vue new file mode 100644 index 0000000000..53070670be --- /dev/null +++ b/frontend-vue3/src/components/print/config/CoverConfig.vue @@ -0,0 +1,18 @@ + + + diff --git a/frontend-vue3/src/components/print/config/DialogScheduleEntryFilter.vue b/frontend-vue3/src/components/print/config/DialogScheduleEntryFilter.vue new file mode 100644 index 0000000000..ad0168920c --- /dev/null +++ b/frontend-vue3/src/components/print/config/DialogScheduleEntryFilter.vue @@ -0,0 +1,114 @@ + + + diff --git a/frontend-vue3/src/components/print/config/PicassoConfig.vue b/frontend-vue3/src/components/print/config/PicassoConfig.vue new file mode 100644 index 0000000000..da6b1499d2 --- /dev/null +++ b/frontend-vue3/src/components/print/config/PicassoConfig.vue @@ -0,0 +1,84 @@ + + + diff --git a/frontend-vue3/src/components/print/config/ProgramConfig.vue b/frontend-vue3/src/components/print/config/ProgramConfig.vue new file mode 100644 index 0000000000..14d4b8d312 --- /dev/null +++ b/frontend-vue3/src/components/print/config/ProgramConfig.vue @@ -0,0 +1,62 @@ + + + diff --git a/frontend-vue3/src/components/print/config/SafetyConsiderationsConfig.vue b/frontend-vue3/src/components/print/config/SafetyConsiderationsConfig.vue new file mode 100644 index 0000000000..5811134237 --- /dev/null +++ b/frontend-vue3/src/components/print/config/SafetyConsiderationsConfig.vue @@ -0,0 +1,62 @@ + + + diff --git a/frontend-vue3/src/components/print/config/StoryConfig.vue b/frontend-vue3/src/components/print/config/StoryConfig.vue new file mode 100644 index 0000000000..4613843083 --- /dev/null +++ b/frontend-vue3/src/components/print/config/StoryConfig.vue @@ -0,0 +1,58 @@ + + + diff --git a/frontend-vue3/src/components/print/config/SummaryConfig.vue b/frontend-vue3/src/components/print/config/SummaryConfig.vue new file mode 100644 index 0000000000..af20659458 --- /dev/null +++ b/frontend-vue3/src/components/print/config/SummaryConfig.vue @@ -0,0 +1,52 @@ + diff --git a/frontend-vue3/src/components/print/config/TocConfig.vue b/frontend-vue3/src/components/print/config/TocConfig.vue new file mode 100644 index 0000000000..8f23f06f4a --- /dev/null +++ b/frontend-vue3/src/components/print/config/TocConfig.vue @@ -0,0 +1,18 @@ + + + diff --git a/frontend-vue3/src/components/print/configurator/PagesConfig.vue b/frontend-vue3/src/components/print/configurator/PagesConfig.vue new file mode 100644 index 0000000000..842685d5a6 --- /dev/null +++ b/frontend-vue3/src/components/print/configurator/PagesConfig.vue @@ -0,0 +1,224 @@ + + + + + diff --git a/frontend-vue3/src/components/print/configurator/PagesOverview.vue b/frontend-vue3/src/components/print/configurator/PagesOverview.vue new file mode 100644 index 0000000000..a066424753 --- /dev/null +++ b/frontend-vue3/src/components/print/configurator/PagesOverview.vue @@ -0,0 +1,40 @@ + + + + + diff --git a/frontend-vue3/src/components/print/print-client/DownloadClientPdfButton.vue b/frontend-vue3/src/components/print/print-client/DownloadClientPdfButton.vue new file mode 100644 index 0000000000..3094e3b0f7 --- /dev/null +++ b/frontend-vue3/src/components/print/print-client/DownloadClientPdfButton.vue @@ -0,0 +1,19 @@ + + + diff --git a/frontend-vue3/src/components/print/print-client/DownloadClientPdfListItem.vue b/frontend-vue3/src/components/print/print-client/DownloadClientPdfListItem.vue new file mode 100644 index 0000000000..600edaaaf4 --- /dev/null +++ b/frontend-vue3/src/components/print/print-client/DownloadClientPdfListItem.vue @@ -0,0 +1,22 @@ + + + + + diff --git a/frontend-vue3/src/components/print/print-client/PrintPreviewClient.vue b/frontend-vue3/src/components/print/print-client/PrintPreviewClient.vue new file mode 100644 index 0000000000..255f032ca3 --- /dev/null +++ b/frontend-vue3/src/components/print/print-client/PrintPreviewClient.vue @@ -0,0 +1,109 @@ +