diff --git a/next-ui/.gitignore b/next-ui/.gitignore
index d314cfda..fa41f88e 100644
--- a/next-ui/.gitignore
+++ b/next-ui/.gitignore
@@ -24,3 +24,6 @@ pnpm-debug.log*
# FormatJS compiled translation files
!/src/i18n/README.md
src/i18n
+
+*storybook.log
+storybook-static
diff --git a/next-ui/.storybook/StoryWrapper.vue b/next-ui/.storybook/StoryWrapper.vue
new file mode 100644
index 00000000..2659d78c
--- /dev/null
+++ b/next-ui/.storybook/StoryWrapper.vue
@@ -0,0 +1,17 @@
+
+
+
+
+
+
+
diff --git a/next-ui/.storybook/main.ts b/next-ui/.storybook/main.ts
new file mode 100644
index 00000000..320d58b5
--- /dev/null
+++ b/next-ui/.storybook/main.ts
@@ -0,0 +1,19 @@
+import type { StorybookConfig } from '@storybook/vue3-vite'
+
+const config: StorybookConfig = {
+ stories: ['../src/**/*.mdx', '../src/**/*.stories.@(js|jsx|mjs|ts|tsx)'],
+ addons: [
+ '@chromatic-com/storybook',
+ '@storybook/addon-docs',
+ '@storybook/addon-onboarding',
+ '@storybook/addon-a11y',
+ '@storybook/addon-vitest',
+ '@storybook/addon-themes',
+ ],
+ framework: {
+ name: '@storybook/vue3-vite',
+ options: {},
+ },
+ staticDirs: ['../public-msw'],
+}
+export default config
diff --git a/next-ui/.storybook/manager.ts b/next-ui/.storybook/manager.ts
new file mode 100644
index 00000000..79d299cb
--- /dev/null
+++ b/next-ui/.storybook/manager.ts
@@ -0,0 +1,6 @@
+import { addons } from 'storybook/manager-api'
+import theme from './theme'
+
+addons.setConfig({
+ theme: theme,
+})
diff --git a/next-ui/.storybook/preview.ts b/next-ui/.storybook/preview.ts
new file mode 100644
index 00000000..40fa9edb
--- /dev/null
+++ b/next-ui/.storybook/preview.ts
@@ -0,0 +1,62 @@
+import type { Preview } from '@storybook/vue3-vite'
+import { setup } from '@storybook/vue3'
+import { withVuetifyTheme } from './withVuetifyTheme.decorator'
+
+import { initialize, mswLoader } from 'msw-storybook-addon'
+import { handlers } from '@/mocks/api/handlers'
+import { vuetify, vuetifyRulesPlugin } from '@/plugins/vuetify'
+import { createPinia } from 'pinia'
+import { PiniaColada } from '@pinia/colada'
+import { PiniaColadaAutoRefetch } from '@pinia/colada-plugin-auto-refetch'
+import { vueIntl } from '@/plugins/vue-intl'
+
+initialize(
+ {
+ onUnhandledRequest: 'bypass',
+ },
+ handlers,
+)
+
+const preview: Preview = {
+ parameters: {
+ controls: {
+ matchers: {
+ color: /(background|color)$/i,
+ date: /Date$/i,
+ },
+ },
+
+ a11y: {
+ // 'todo' - show a11y violations in the test UI only
+ // 'error' - fail CI on a11y violations
+ // 'off' - skip a11y checks entirely
+ test: 'todo',
+ },
+ },
+ loaders: [mswLoader],
+}
+
+export default preview
+
+setup((app) => {
+ // Registers your app's plugins into Storybook
+ app.use(vuetify)
+ app.use(vuetifyRulesPlugin)
+ app.use(vueIntl)
+ app.use(createPinia())
+ app.use(PiniaColada, {
+ plugins: [PiniaColadaAutoRefetch()],
+ })
+})
+
+export const decorators = [
+ withVuetifyTheme({
+ // These keys are the labels that will be displayed in the toolbar theme switcher
+ // The values must match the theme keys from your VuetifyOptions
+ themes: {
+ light: 'light',
+ dark: 'dark',
+ },
+ defaultTheme: 'light', // The key of your default theme
+ }),
+]
diff --git a/next-ui/.storybook/storybook.d.ts b/next-ui/.storybook/storybook.d.ts
new file mode 100644
index 00000000..e69de29b
diff --git a/next-ui/.storybook/theme.ts b/next-ui/.storybook/theme.ts
new file mode 100644
index 00000000..7885af3d
--- /dev/null
+++ b/next-ui/.storybook/theme.ts
@@ -0,0 +1,8 @@
+import { create } from 'storybook/theming'
+
+export default create({
+ base: 'light',
+ brandTitle: 'Komga Storybook',
+ brandUrl: 'https://komga.org',
+ brandImage: '../src/assets/komga.svg',
+})
diff --git a/next-ui/.storybook/vitest.setup.ts b/next-ui/.storybook/vitest.setup.ts
new file mode 100644
index 00000000..bf4d1c4c
--- /dev/null
+++ b/next-ui/.storybook/vitest.setup.ts
@@ -0,0 +1,7 @@
+import * as a11yAddonAnnotations from '@storybook/addon-a11y/preview'
+import { setProjectAnnotations } from '@storybook/vue3-vite'
+import * as projectAnnotations from './preview'
+
+// This is an important step to apply the right configuration when testing your stories.
+// More info at: https://storybook.js.org/docs/api/portable-stories/portable-stories-vitest#setprojectannotations
+setProjectAnnotations([a11yAddonAnnotations, projectAnnotations])
diff --git a/next-ui/.storybook/withVuetifyTheme.decorator.ts b/next-ui/.storybook/withVuetifyTheme.decorator.ts
new file mode 100644
index 00000000..ed8e19cc
--- /dev/null
+++ b/next-ui/.storybook/withVuetifyTheme.decorator.ts
@@ -0,0 +1,36 @@
+import { h } from 'vue'
+import { DecoratorHelpers } from '@storybook/addon-themes'
+import StoryWrapper from './StoryWrapper.vue'
+import type { StoryContext } from '@storybook/vue3-vite'
+
+const { initializeThemeState, pluckThemeFromContext } = DecoratorHelpers
+
+export const withVuetifyTheme = ({
+ themes,
+ defaultTheme,
+}: {
+ themes: object
+ defaultTheme: string
+}) => {
+ initializeThemeState(Object.keys(themes), defaultTheme)
+
+ return (storyFn: () => Component, context: StoryContext) => {
+ const selectedTheme = pluckThemeFromContext(context)
+ const { themeOverride } = context.parameters.themes ?? {}
+
+ const selected = themeOverride || selectedTheme || defaultTheme
+
+ const story = storyFn()
+
+ return () => {
+ return h(
+ StoryWrapper,
+ { themeName: selected }, // Props for StoryWrapper
+ {
+ // Puts your story into StoryWrapper's "story" slot with your story args
+ story: () => h(story, { ...context.args }),
+ },
+ )
+ }
+ }
+}
diff --git a/next-ui/dir2json.d.ts b/next-ui/dir2json.d.ts
index 62b99521..e1a6f74b 100644
--- a/next-ui/dir2json.d.ts
+++ b/next-ui/dir2json.d.ts
@@ -4,7 +4,10 @@
// noinspection JSUnusedGlobalSymbols
// Auto generated by vite-plugin-dir2json
declare module "*i18n?dir2json&ext=.json&1" {
- const json: {};
+ const json: {
+ "en": string;
+ "fr": string;
+};
export default json;
}
diff --git a/next-ui/eslint.config.js b/next-ui/eslint.config.ts
similarity index 83%
rename from next-ui/eslint.config.js
rename to next-ui/eslint.config.ts
index 43a8a31c..04f1ca4c 100644
--- a/next-ui/eslint.config.js
+++ b/next-ui/eslint.config.ts
@@ -1,3 +1,5 @@
+import storybook from 'eslint-plugin-storybook'
+
/**
* .eslint.js
*
@@ -23,6 +25,8 @@ export default defineConfigWithVueTs(
'**/coverage/**',
'openapi-generator.mts',
'**/generated/openapi/komga.d.ts',
+ 'public-msw/**/*',
+ 'eslint.config.ts',
],
},
@@ -66,4 +70,15 @@ export default defineConfigWithVueTs(
},
eslintConfigPrettier,
+
+ ...storybook.configs['flat/recommended'],
+
+ {
+ languageOptions: {
+ parserOptions: {
+ projectService: true,
+ tsconfigRootDir: import.meta.dirname,
+ },
+ },
+ },
)
diff --git a/next-ui/i18n/en.json b/next-ui/i18n/en.json
index fb74e335..b9cb5ac0 100644
--- a/next-ui/i18n/en.json
+++ b/next-ui/i18n/en.json
@@ -35,6 +35,10 @@
"defaultMessage": "No restriction",
"description": "User creation/edit dialog: Age restriction field possible option"
},
+ "AjWlka": {
+ "defaultMessage": "Invalid login or password",
+ "description": "Login screen: error message displayed when login failed"
+ },
"CUxhzL": {
"defaultMessage": "Roles",
"description": "User creation/edit dialog: Roles field"
@@ -75,6 +79,10 @@
"defaultMessage": "Users",
"description": "Drawer menu for Server > Users"
},
+ "JbF1nK": {
+ "defaultMessage": "Password changed for user: {email}",
+ "description": "Snackbar notification shown upon successful user's password modification"
+ },
"LaxrEO": {
"defaultMessage": "Passwords must be identical",
"description": "User password change dialog: Error message if passwords differ"
@@ -111,6 +119,10 @@
"defaultMessage": "Shared Libraries",
"description": "User creation/edit dialog: Shared Libraries field"
},
+ "V/OYJE": {
+ "defaultMessage": "User deleted: {email}",
+ "description": "Snackbar notification shown upon successful user deletion"
+ },
"WNY0pu": {
"defaultMessage": "The latest version of Komga is already installed",
"description": "Updates view: banner shown at the top"
@@ -119,6 +131,10 @@
"defaultMessage": "New password",
"description": "User password change dialog: New Password field label"
},
+ "Xz+JXU": {
+ "defaultMessage": "error",
+ "description": "Common message: an unkown error happened"
+ },
"Y6VlM9": {
"defaultMessage": "Read List",
"description": "Drawer menu for Import > Read List"
@@ -127,6 +143,10 @@
"defaultMessage": "User Interface",
"description": "Drawer menu for Server > User Interface"
},
+ "Z/EY89": {
+ "defaultMessage": "Network error",
+ "description": "Common message: a network error happened when communicating with the server"
+ },
"app.locale-name": {
"defaultMessage": "English",
"description": "The name of the locale, shown in the language selection menu. Must be translated to the language's name"
@@ -163,6 +183,10 @@
"defaultMessage": "Duplicate Files",
"description": "Drawer menu for Media > Duplicate Files"
},
+ "egrxd6": {
+ "defaultMessage": "User created: {email}",
+ "description": "Snackbar notification shown upon successful user creation"
+ },
"fQIepD": {
"defaultMessage": "Books",
"description": "Drawer menu for Import > Books"
@@ -183,6 +207,10 @@
"defaultMessage": "Age",
"description": "User creation/edit dialog: Age Restriction > Age field label"
},
+ "kvbi4j": {
+ "defaultMessage": "User updated: {email}",
+ "description": "Snackbar notification shown upon successful user update"
+ },
"l/To3S": {
"defaultMessage": "History",
"description": "Drawer menu for History"
@@ -219,6 +247,10 @@
"defaultMessage": "Unknown",
"description": "Drawer menu for Media > Duplicate Pages > Unknown"
},
+ "r6JNfI": {
+ "defaultMessage": "Forgot your password?",
+ "description": "Login screen: Forgot your password link"
+ },
"rw/Dkw": {
"defaultMessage": "User Interface",
"description": "Drawer menu for My Account > User Interface"
diff --git a/next-ui/package-lock.json b/next-ui/package-lock.json
index 05053cf4..5474485a 100644
--- a/next-ui/package-lock.json
+++ b/next-ui/package-lock.json
@@ -21,27 +21,40 @@
"vuetify": "^3.8.5"
},
"devDependencies": {
+ "@chromatic-com/storybook": "^4.0.0",
"@eslint/js": "^9.28.0",
"@formatjs/cli": "^6.7.1",
"@iconify-json/mdi": "^1.2.3",
+ "@storybook/addon-a11y": "^9.0.8",
+ "@storybook/addon-docs": "^9.0.8",
+ "@storybook/addon-onboarding": "^9.0.8",
+ "@storybook/addon-themes": "^9.0.8",
+ "@storybook/addon-vitest": "^9.0.8",
+ "@storybook/vue3-vite": "^9.0.8",
"@testing-library/vue": "^8.1.0",
"@tsconfig/node22": "^22.0.2",
"@types/node": "^22.15.29",
- "@vitejs/plugin-vue": "^5.1.4",
+ "@vitejs/plugin-vue": "^5.2.4",
+ "@vitest/browser": "^3.2.3",
+ "@vitest/coverage-v8": "^3.2.3",
"@vue/eslint-config-prettier": "^10.2.0",
"@vue/eslint-config-typescript": "^14.1.3",
"@vue/tsconfig": "^0.7.0",
"eslint": "^9.28.0",
"eslint-config-prettier": "^10.1.5",
"eslint-plugin-formatjs": "^5.3.1",
+ "eslint-plugin-storybook": "^9.0.8",
"eslint-plugin-vue": "^10.1.0",
"happy-dom": "^18.0.1",
"msw": "^2.10.2",
+ "msw-storybook-addon": "^2.0.5",
"npm-run-all2": "^8.0.4",
"openapi-typescript": "^7.8.0",
+ "playwright": "^1.53.0",
"prettier": "^3.5.3",
"sass": "^1.88.0",
"sass-embedded": "^1.88.0",
+ "storybook": "^9.0.8",
"typescript": "^5.8.3",
"unplugin-auto-import": "^19.3.0",
"unplugin-fonts": "^1.1.1",
@@ -57,6 +70,27 @@
"vue-tsc": "^2.1.10"
}
},
+ "node_modules/@adobe/css-tools": {
+ "version": "4.4.3",
+ "resolved": "https://registry.npmjs.org/@adobe/css-tools/-/css-tools-4.4.3.tgz",
+ "integrity": "sha512-VQKMkwriZbaOgVCby1UDY/LDk5fIjhQicCvVPFqfe+69fWaPWydbWJ3wRt59/YzIwda1I81loas3oCoHxnqvdA==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "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,
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@jridgewell/gen-mapping": "^0.3.5",
+ "@jridgewell/trace-mapping": "^0.3.24"
+ },
+ "engines": {
+ "node": ">=6.0.0"
+ }
+ },
"node_modules/@antfu/install-pkg": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/@antfu/install-pkg/-/install-pkg-1.1.0.tgz",
@@ -175,6 +209,16 @@
"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,
+ "license": "MIT",
+ "engines": {
+ "node": ">=18"
+ }
+ },
"node_modules/@bufbuild/protobuf": {
"version": "2.5.1",
"resolved": "https://registry.npmjs.org/@bufbuild/protobuf/-/protobuf-2.5.1.tgz",
@@ -229,6 +273,56 @@
"node": ">=6"
}
},
+ "node_modules/@chromatic-com/storybook": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/@chromatic-com/storybook/-/storybook-4.0.0.tgz",
+ "integrity": "sha512-FfyMHK/lz/dHezWxwNZv4ReFORWVvv+bJx71NT2BSfLhOKOaoZnKJOe4QLyGxWAB7ynnedrM9V9qea3FPFj+rQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@neoconfetti/react": "^1.0.0",
+ "chromatic": "^12.0.0",
+ "filesize": "^10.0.12",
+ "jsonfile": "^6.1.0",
+ "strip-ansi": "^7.1.0"
+ },
+ "engines": {
+ "node": ">=20.0.0",
+ "yarn": ">=1.22.18"
+ },
+ "peerDependencies": {
+ "storybook": "^0.0.0-0 || ^9.0.0 || ^9.1.0-0"
+ }
+ },
+ "node_modules/@chromatic-com/storybook/node_modules/ansi-regex": {
+ "version": "6.1.0",
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.1.0.tgz",
+ "integrity": "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/ansi-regex?sponsor=1"
+ }
+ },
+ "node_modules/@chromatic-com/storybook/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,
+ "license": "MIT",
+ "dependencies": {
+ "ansi-regex": "^6.0.1"
+ },
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/strip-ansi?sponsor=1"
+ }
+ },
"node_modules/@csstools/color-helpers": {
"version": "5.0.2",
"resolved": "https://registry.npmjs.org/@csstools/color-helpers/-/color-helpers-5.0.2.tgz",
@@ -1394,12 +1488,86 @@
"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,
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/@jridgewell/gen-mapping": {
+ "version": "0.3.8",
+ "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.8.tgz",
+ "integrity": "sha512-imAbBGkb+ebQyxKgzv5Hu2nmROxoDOXHh80evxdoXNOrvAnVx7zimzc1Oo5h9RlfV4vPXaE2iM5pOFbvOCClWA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@jridgewell/set-array": "^1.2.1",
+ "@jridgewell/sourcemap-codec": "^1.4.10",
+ "@jridgewell/trace-mapping": "^0.3.24"
+ },
+ "engines": {
+ "node": ">=6.0.0"
+ }
+ },
+ "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/set-array": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.2.1.tgz",
+ "integrity": "sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=6.0.0"
+ }
+ },
"node_modules/@jridgewell/sourcemap-codec": {
"version": "1.5.0",
"resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz",
"integrity": "sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==",
"license": "MIT"
},
+ "node_modules/@jridgewell/trace-mapping": {
+ "version": "0.3.25",
+ "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz",
+ "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@jridgewell/resolve-uri": "^3.1.0",
+ "@jridgewell/sourcemap-codec": "^1.4.14"
+ }
+ },
+ "node_modules/@mdx-js/react": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/@mdx-js/react/-/react-3.1.0.tgz",
+ "integrity": "sha512-QjHtSaoameoalGnKDT3FoIl4+9RwyTmo9ZJGBdLOks/YOiWHoRDI3PUwEzOE7kEmGcV3AFcp9K6dYu9rEuKLAQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@types/mdx": "^2.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ },
+ "peerDependencies": {
+ "@types/react": ">=16",
+ "react": ">=16"
+ }
+ },
"node_modules/@mswjs/interceptors": {
"version": "0.39.2",
"resolved": "https://registry.npmjs.org/@mswjs/interceptors/-/interceptors-0.39.2.tgz",
@@ -1418,6 +1586,13 @@
"node": ">=18"
}
},
+ "node_modules/@neoconfetti/react": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/@neoconfetti/react/-/react-1.0.0.tgz",
+ "integrity": "sha512-klcSooChXXOzIm+SE5IISIAn3bYzYfPjbX7D7HoqZL84oAfgREeSg5vSIaSFH+DaGzzvImTyWe1OyrJ67vik4A==",
+ "dev": true,
+ "license": "MIT"
+ },
"node_modules/@nodelib/fs.scandir": {
"version": "2.1.5",
"resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz",
@@ -1888,6 +2063,13 @@
"url": "https://opencollective.com/pkgr"
}
},
+ "node_modules/@polka/url": {
+ "version": "1.0.0-next.29",
+ "resolved": "https://registry.npmjs.org/@polka/url/-/url-1.0.0-next.29.tgz",
+ "integrity": "sha512-wwQAWhWSuHaag8c4q/KN/vCoeOJYshAIvMQwD4GpSb3OiZklFfvAgmj0VCBBImRpuF/aFgIRzllXlVX93Jevww==",
+ "dev": true,
+ "license": "MIT"
+ },
"node_modules/@redocly/ajv": {
"version": "8.11.2",
"resolved": "https://registry.npmjs.org/@redocly/ajv/-/ajv-8.11.2.tgz",
@@ -2234,6 +2416,262 @@
"win32"
]
},
+ "node_modules/@storybook/addon-a11y": {
+ "version": "9.0.8",
+ "resolved": "https://registry.npmjs.org/@storybook/addon-a11y/-/addon-a11y-9.0.8.tgz",
+ "integrity": "sha512-5wFBlISLUDykvpzATR0m7DbvD2+ImiqVx3EfoamrRqzuStTYh/5eEKYvbTznPFBrgvvboCzvVWT2ZqNByeQhxw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@storybook/global": "^5.0.0",
+ "axe-core": "^4.2.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/storybook"
+ },
+ "peerDependencies": {
+ "storybook": "^9.0.8"
+ }
+ },
+ "node_modules/@storybook/addon-docs": {
+ "version": "9.0.8",
+ "resolved": "https://registry.npmjs.org/@storybook/addon-docs/-/addon-docs-9.0.8.tgz",
+ "integrity": "sha512-YRR8qHitwXVTJyn02YMrzd9mCKcuZWSKWt+J/ddFb8khGfLcAW+O0NohGeqMyM6XStLVDKKIKsMoTHggUwIFsA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@mdx-js/react": "^3.0.0",
+ "@storybook/csf-plugin": "9.0.8",
+ "@storybook/icons": "^1.2.12",
+ "@storybook/react-dom-shim": "9.0.8",
+ "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0",
+ "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0",
+ "ts-dedent": "^2.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/storybook"
+ },
+ "peerDependencies": {
+ "storybook": "^9.0.8"
+ }
+ },
+ "node_modules/@storybook/addon-onboarding": {
+ "version": "9.0.8",
+ "resolved": "https://registry.npmjs.org/@storybook/addon-onboarding/-/addon-onboarding-9.0.8.tgz",
+ "integrity": "sha512-xDXVgMTVPvyhVV08pBodXyCiva8MLexe+JvAfaCUEsRb9C6eQUhsGK6uoNNON2hJ32ahVgHCk/xJU79aBx38wQ==",
+ "dev": true,
+ "license": "MIT",
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/storybook"
+ },
+ "peerDependencies": {
+ "storybook": "^9.0.8"
+ }
+ },
+ "node_modules/@storybook/addon-themes": {
+ "version": "9.0.8",
+ "resolved": "https://registry.npmjs.org/@storybook/addon-themes/-/addon-themes-9.0.8.tgz",
+ "integrity": "sha512-YENoT09Z2X8H0llHpZLuAwqJBj7WLfvPgzxya0Ul5+ySv8o/ULsR2qw/ZC9M8QWqJ14E5SB6Kn6zedcWZ1UeLg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "ts-dedent": "^2.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/storybook"
+ },
+ "peerDependencies": {
+ "storybook": "^9.0.8"
+ }
+ },
+ "node_modules/@storybook/addon-vitest": {
+ "version": "9.0.8",
+ "resolved": "https://registry.npmjs.org/@storybook/addon-vitest/-/addon-vitest-9.0.8.tgz",
+ "integrity": "sha512-LfO98ZbXwMknEnN9ICOj2UodVyr/62Q1o64WQyuktVZVZ4fXQXtPZO7uP9F4TX5HuvNWIiaxGlhBYfEzcErbUA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@storybook/global": "^5.0.0",
+ "@storybook/icons": "^1.4.0",
+ "prompts": "^2.4.0",
+ "ts-dedent": "^2.2.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/storybook"
+ },
+ "peerDependencies": {
+ "@vitest/browser": "^3.0.0",
+ "@vitest/runner": "^3.0.0",
+ "storybook": "^9.0.8",
+ "vitest": "^3.0.0"
+ },
+ "peerDependenciesMeta": {
+ "@vitest/browser": {
+ "optional": true
+ },
+ "@vitest/runner": {
+ "optional": true
+ },
+ "vitest": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@storybook/builder-vite": {
+ "version": "9.0.8",
+ "resolved": "https://registry.npmjs.org/@storybook/builder-vite/-/builder-vite-9.0.8.tgz",
+ "integrity": "sha512-dbwDfBUwLW8I71h0Y9r+twtEdjKC+oBP1YweS26ET78qc6qXMFsK5Tfh6lzj/vQbmxY0YhnTVrrkXgfR0erLPA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@storybook/csf-plugin": "9.0.8",
+ "ts-dedent": "^2.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/storybook"
+ },
+ "peerDependencies": {
+ "storybook": "^9.0.8",
+ "vite": "^5.0.0 || ^6.0.0"
+ }
+ },
+ "node_modules/@storybook/csf-plugin": {
+ "version": "9.0.8",
+ "resolved": "https://registry.npmjs.org/@storybook/csf-plugin/-/csf-plugin-9.0.8.tgz",
+ "integrity": "sha512-mNjo4t9liAbQvhE9ni87NU2sz9tqFU4Y54ioSFDlW24wpubsvnhBi5h4z3EkeQJSzIzNMRym9SC7Elbqa3Kf+g==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "unplugin": "^1.3.1"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/storybook"
+ },
+ "peerDependencies": {
+ "storybook": "^9.0.8"
+ }
+ },
+ "node_modules/@storybook/csf-plugin/node_modules/unplugin": {
+ "version": "1.16.1",
+ "resolved": "https://registry.npmjs.org/unplugin/-/unplugin-1.16.1.tgz",
+ "integrity": "sha512-4/u/j4FrCKdi17jaxuJA0jClGxB1AvU2hw/IuayPc4ay1XGaJs/rbb4v5WKwAjNifjmXK9PIFyuPiaK8azyR9w==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "acorn": "^8.14.0",
+ "webpack-virtual-modules": "^0.6.2"
+ },
+ "engines": {
+ "node": ">=14.0.0"
+ }
+ },
+ "node_modules/@storybook/global": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/@storybook/global/-/global-5.0.0.tgz",
+ "integrity": "sha512-FcOqPAXACP0I3oJ/ws6/rrPT9WGhu915Cg8D02a9YxLo0DE9zI+a9A5gRGvmQ09fiWPukqI8ZAEoQEdWUKMQdQ==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/@storybook/icons": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/@storybook/icons/-/icons-1.4.0.tgz",
+ "integrity": "sha512-Td73IeJxOyalzvjQL+JXx72jlIYHgs+REaHiREOqfpo3A2AYYG71AUbcv+lg7mEDIweKVCxsMQ0UKo634c8XeA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=14.0.0"
+ },
+ "peerDependencies": {
+ "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0-beta",
+ "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0-beta"
+ }
+ },
+ "node_modules/@storybook/react-dom-shim": {
+ "version": "9.0.8",
+ "resolved": "https://registry.npmjs.org/@storybook/react-dom-shim/-/react-dom-shim-9.0.8.tgz",
+ "integrity": "sha512-SYyjRagHZx724hGEWSZcXRzj82am77OpqeA9ps6ZsCSn4cVY9FORGEeY2bnlQkpLnDUH5yjdV/oh+0fXDbl/8g==",
+ "dev": true,
+ "license": "MIT",
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/storybook"
+ },
+ "peerDependencies": {
+ "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0-beta",
+ "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0-beta",
+ "storybook": "^9.0.8"
+ }
+ },
+ "node_modules/@storybook/vue3": {
+ "version": "9.0.8",
+ "resolved": "https://registry.npmjs.org/@storybook/vue3/-/vue3-9.0.8.tgz",
+ "integrity": "sha512-Aqe0jCcwZ47nLIBs76Uw+kdpbMX8B824GWnlmzzZrLCJQkvoQIh1d9r+04rSpDM6PUhTvsRB9igAMU4dLmy78g==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@storybook/global": "^5.0.0",
+ "type-fest": "~2.19",
+ "vue-component-type-helpers": "latest"
+ },
+ "engines": {
+ "node": ">=20.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/storybook"
+ },
+ "peerDependencies": {
+ "storybook": "^9.0.8",
+ "vue": "^3.0.0"
+ }
+ },
+ "node_modules/@storybook/vue3-vite": {
+ "version": "9.0.8",
+ "resolved": "https://registry.npmjs.org/@storybook/vue3-vite/-/vue3-vite-9.0.8.tgz",
+ "integrity": "sha512-3ZrY7NBGhVTgQR/mBNkFrjRWkAp/wAj+ce/gTTRZAV7AHXuA30fiIijbTnUOWCVbBMIYt42Cny8IBRjTPCLPrA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@storybook/builder-vite": "9.0.8",
+ "@storybook/vue3": "9.0.8",
+ "find-package-json": "^1.2.0",
+ "magic-string": "^0.30.0",
+ "typescript": "^5.8.3",
+ "vue-component-meta": "^2.0.0",
+ "vue-docgen-api": "^4.75.1"
+ },
+ "engines": {
+ "node": ">=20.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/storybook"
+ },
+ "peerDependencies": {
+ "storybook": "^9.0.8",
+ "vite": "^5.0.0 || ^6.0.0"
+ }
+ },
+ "node_modules/@storybook/vue3/node_modules/type-fest": {
+ "version": "2.19.0",
+ "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-2.19.0.tgz",
+ "integrity": "sha512-RAH822pAdBgcNMAfWnCBU3CFZcfZ/i1eZjwFU/dsLKumyuuP3niueg2UAukXYF0E2AAoc82ZSSf9J0WQBinzHA==",
+ "dev": true,
+ "license": "(MIT OR CC0-1.0)",
+ "engines": {
+ "node": ">=12.20"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
"node_modules/@testing-library/dom": {
"version": "9.3.4",
"resolved": "https://registry.npmjs.org/@testing-library/dom/-/dom-9.3.4.tgz",
@@ -2254,6 +2692,62 @@
"node": ">=14"
}
},
+ "node_modules/@testing-library/jest-dom": {
+ "version": "6.6.3",
+ "resolved": "https://registry.npmjs.org/@testing-library/jest-dom/-/jest-dom-6.6.3.tgz",
+ "integrity": "sha512-IteBhl4XqYNkM54f4ejhLRJiZNqcSCoXUOG2CPK7qbD322KjQozM4kHQOfkG2oln9b9HTYqs+Sae8vBATubxxA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@adobe/css-tools": "^4.4.0",
+ "aria-query": "^5.0.0",
+ "chalk": "^3.0.0",
+ "css.escape": "^1.5.1",
+ "dom-accessibility-api": "^0.6.3",
+ "lodash": "^4.17.21",
+ "redent": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=14",
+ "npm": ">=6",
+ "yarn": ">=1"
+ }
+ },
+ "node_modules/@testing-library/jest-dom/node_modules/chalk": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz",
+ "integrity": "sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "ansi-styles": "^4.1.0",
+ "supports-color": "^7.1.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "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,
+ "license": "MIT"
+ },
+ "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,
+ "license": "MIT",
+ "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",
@@ -2347,6 +2841,13 @@
"dev": true,
"license": "MIT"
},
+ "node_modules/@types/mdx": {
+ "version": "2.0.13",
+ "resolved": "https://registry.npmjs.org/@types/mdx/-/mdx-2.0.13.tgz",
+ "integrity": "sha512-+OWZQfAYyio6YkJb3HLxDrvnx6SWWDbC0zVPfBRzUk0/nqoDyf6dNxQi3eArPe8rJ473nobTMQ/8Zk+LxJ+Yuw==",
+ "dev": true,
+ "license": "MIT"
+ },
"node_modules/@types/node": {
"version": "22.15.29",
"resolved": "https://registry.npmjs.org/@types/node/-/node-22.15.29.tgz",
@@ -2364,6 +2865,17 @@
"dev": true,
"license": "MIT"
},
+ "node_modules/@types/react": {
+ "version": "19.1.8",
+ "resolved": "https://registry.npmjs.org/@types/react/-/react-19.1.8.tgz",
+ "integrity": "sha512-AwAfQ2Wa5bCx9WP8nZL2uMZWod7J7/JSplxbTmBQ5ms6QpqNYm672H0Vu9ZVKVngQ+ii4R/byguVEUZQyeg44g==",
+ "dev": true,
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "csstype": "^3.0.2"
+ }
+ },
"node_modules/@types/statuses": {
"version": "2.0.6",
"resolved": "https://registry.npmjs.org/@types/statuses/-/statuses-2.0.6.tgz",
@@ -2649,6 +3161,106 @@
"vue": "^3.2.25"
}
},
+ "node_modules/@vitest/browser": {
+ "version": "3.2.3",
+ "resolved": "https://registry.npmjs.org/@vitest/browser/-/browser-3.2.3.tgz",
+ "integrity": "sha512-5HpUb0ixGF8JWSAjb/P1x/VPuTYUkL4pL0+YO6DJiuvQgqJN3PREaUEcXwfXjU4nBc37EahfpRbAwdE9pHs9lQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@testing-library/dom": "^10.4.0",
+ "@testing-library/user-event": "^14.6.1",
+ "@vitest/mocker": "3.2.3",
+ "@vitest/utils": "3.2.3",
+ "magic-string": "^0.30.17",
+ "sirv": "^3.0.1",
+ "tinyrainbow": "^2.0.0",
+ "ws": "^8.18.2"
+ },
+ "funding": {
+ "url": "https://opencollective.com/vitest"
+ },
+ "peerDependencies": {
+ "playwright": "*",
+ "vitest": "3.2.3",
+ "webdriverio": "^7.0.0 || ^8.0.0 || ^9.0.0"
+ },
+ "peerDependenciesMeta": {
+ "playwright": {
+ "optional": true
+ },
+ "safaridriver": {
+ "optional": true
+ },
+ "webdriverio": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@vitest/browser/node_modules/@testing-library/dom": {
+ "version": "10.4.0",
+ "resolved": "https://registry.npmjs.org/@testing-library/dom/-/dom-10.4.0.tgz",
+ "integrity": "sha512-pemlzrSESWbdAloYml3bAJMEfNh1Z7EduzqPKprCH5S341frlpYnUEW0H72dLxa6IsYr+mPno20GiSm+h9dEdQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/code-frame": "^7.10.4",
+ "@babel/runtime": "^7.12.5",
+ "@types/aria-query": "^5.0.1",
+ "aria-query": "5.3.0",
+ "chalk": "^4.1.0",
+ "dom-accessibility-api": "^0.5.9",
+ "lz-string": "^1.5.0",
+ "pretty-format": "^27.0.2"
+ },
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@vitest/browser/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,
+ "license": "Apache-2.0",
+ "dependencies": {
+ "dequal": "^2.0.3"
+ }
+ },
+ "node_modules/@vitest/coverage-v8": {
+ "version": "3.2.3",
+ "resolved": "https://registry.npmjs.org/@vitest/coverage-v8/-/coverage-v8-3.2.3.tgz",
+ "integrity": "sha512-D1QKzngg8PcDoCE8FHSZhREDuEy+zcKmMiMafYse41RZpBE5EDJyKOTdqK3RQfsV2S2nyKor5KCs8PyPRFqKPg==",
+ "dev": true,
+ "license": "MIT",
+ "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.3",
+ "vitest": "3.2.3"
+ },
+ "peerDependenciesMeta": {
+ "@vitest/browser": {
+ "optional": true
+ }
+ }
+ },
"node_modules/@vitest/expect": {
"version": "3.2.3",
"resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-3.2.3.tgz",
@@ -3315,6 +3927,20 @@
"url": "https://github.com/sponsors/ljharb"
}
},
+ "node_modules/asap": {
+ "version": "2.0.6",
+ "resolved": "https://registry.npmjs.org/asap/-/asap-2.0.6.tgz",
+ "integrity": "sha512-BSHWgDSAiKs50o2Re8ppvp3seVHXSRM44cdSsT9FfNEUUZLOGWVCsiWaRPWM1Znn+mqZ1OfVZ3z3DWEzSp7hRA==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/assert-never": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/assert-never/-/assert-never-1.4.0.tgz",
+ "integrity": "sha512-5oJg84os6NMQNl27T9LnZkvvqzvAnHu03ShCnoj6bsJwS7L8AO4lf+C/XjK/nvzEqQB744moC6V128RucQd1jA==",
+ "dev": true,
+ "license": "MIT"
+ },
"node_modules/assertion-error": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-2.0.1.tgz",
@@ -3342,6 +3968,38 @@
"url": "https://github.com/sponsors/sxzz"
}
},
+ "node_modules/ast-types": {
+ "version": "0.16.1",
+ "resolved": "https://registry.npmjs.org/ast-types/-/ast-types-0.16.1.tgz",
+ "integrity": "sha512-6t10qk83GOG8p0vKmaCr8eiilZwO171AvbROMtvvNiwrTly62t+7XkA8RdIIVbpMhCASAsxgAzdRSwh6nw/5Dg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "tslib": "^2.0.1"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/ast-v8-to-istanbul": {
+ "version": "0.3.3",
+ "resolved": "https://registry.npmjs.org/ast-v8-to-istanbul/-/ast-v8-to-istanbul-0.3.3.tgz",
+ "integrity": "sha512-MuXMrSLVVoA6sYN/6Hke18vMzrT4TZNbZIj/hvh0fnYFpO+/kFXcLIaiPwXXWaQUPg4yJD8fj+lfJ7/1EBconw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@jridgewell/trace-mapping": "^0.3.25",
+ "estree-walker": "^3.0.3",
+ "js-tokens": "^9.0.1"
+ }
+ },
+ "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,
+ "license": "MIT"
+ },
"node_modules/ast-walker-scope": {
"version": "0.6.2",
"resolved": "https://registry.npmjs.org/ast-walker-scope/-/ast-walker-scope-0.6.2.tgz",
@@ -3372,6 +4030,29 @@
"url": "https://github.com/sponsors/ljharb"
}
},
+ "node_modules/axe-core": {
+ "version": "4.10.3",
+ "resolved": "https://registry.npmjs.org/axe-core/-/axe-core-4.10.3.tgz",
+ "integrity": "sha512-Xm7bpRXnDSX2YE2YFfBk2FnF0ep6tmG7xPh8iHee8MIcrgq762Nkce856dYtJYLkuIoYZvGfTs/PbZhideTcEg==",
+ "dev": true,
+ "license": "MPL-2.0",
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/babel-walk": {
+ "version": "3.0.0-canary-5",
+ "resolved": "https://registry.npmjs.org/babel-walk/-/babel-walk-3.0.0-canary-5.tgz",
+ "integrity": "sha512-GAwkz0AihzY5bkwIY5QDR+LvsRQgB/B+1foMPvi0FZPMl5fjD7ICiznUiBdLYMH1QYe6vqu4gWYytZOccLouFw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/types": "^7.9.6"
+ },
+ "engines": {
+ "node": ">= 10.0.0"
+ }
+ },
"node_modules/balanced-match": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
@@ -3379,6 +4060,19 @@
"dev": true,
"license": "MIT"
},
+ "node_modules/better-opn": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/better-opn/-/better-opn-3.0.2.tgz",
+ "integrity": "sha512-aVNobHnJqLiUelTaHat9DZ1qM2w0C0Eym4LPI/3JxOnSokGVdsl1T1kN7TFvsEAD8G47A6VKQ0TVHqbBnYMJlQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "open": "^8.0.4"
+ },
+ "engines": {
+ "node": ">=12.0.0"
+ }
+ },
"node_modules/binary-extensions": {
"version": "2.3.0",
"resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz",
@@ -3577,6 +4271,16 @@
"dev": true,
"license": "MIT"
},
+ "node_modules/character-parser": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/character-parser/-/character-parser-2.2.0.tgz",
+ "integrity": "sha512-+UqJQjFEFaTAs3bNsF2j2kEN1baG/zghZbdqoYEDxGZtJo9LBzl1A+m0D4n3qKx8N2FNv8/Xp6yV9mQmBuptaw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "is-regex": "^1.0.3"
+ }
+ },
"node_modules/check-error": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/check-error/-/check-error-2.1.1.tgz",
@@ -3602,6 +4306,30 @@
"url": "https://paulmillr.com/funding/"
}
},
+ "node_modules/chromatic": {
+ "version": "12.2.0",
+ "resolved": "https://registry.npmjs.org/chromatic/-/chromatic-12.2.0.tgz",
+ "integrity": "sha512-GswmBW9ZptAoTns1BMyjbm55Z7EsIJnUvYKdQqXIBZIKbGErmpA+p4c0BYA+nzw5B0M+rb3Iqp1IaH8TFwIQew==",
+ "dev": true,
+ "license": "MIT",
+ "bin": {
+ "chroma": "dist/bin.js",
+ "chromatic": "dist/bin.js",
+ "chromatic-cli": "dist/bin.js"
+ },
+ "peerDependencies": {
+ "@chromatic-com/cypress": "^0.*.* || ^1.0.0",
+ "@chromatic-com/playwright": "^0.*.* || ^1.0.0"
+ },
+ "peerDependenciesMeta": {
+ "@chromatic-com/cypress": {
+ "optional": true
+ },
+ "@chromatic-com/playwright": {
+ "optional": true
+ }
+ }
+ },
"node_modules/citty": {
"version": "0.1.6",
"resolved": "https://registry.npmjs.org/citty/-/citty-0.1.6.tgz",
@@ -3731,6 +4459,17 @@
"node": "^14.18.0 || >=16.10.0"
}
},
+ "node_modules/constantinople": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/constantinople/-/constantinople-4.0.1.tgz",
+ "integrity": "sha512-vCrqcSIq4//Gx74TXXCGnHpulY1dskqLTFGDmhrGxzeXL8lF8kvXv6mpNWlJj1uD4DW23D4ljAqbY4RRaaUZIw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/parser": "^7.6.0",
+ "@babel/types": "^7.6.1"
+ }
+ },
"node_modules/cookie": {
"version": "0.7.2",
"resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.2.tgz",
@@ -3782,6 +4521,13 @@
"node": ">= 8"
}
},
+ "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,
+ "license": "MIT"
+ },
"node_modules/cssesc": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz",
@@ -3938,6 +4684,16 @@
"url": "https://github.com/sponsors/ljharb"
}
},
+ "node_modules/define-lazy-prop": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/define-lazy-prop/-/define-lazy-prop-2.0.0.tgz",
+ "integrity": "sha512-Ds09qNh8yw3khSjiJjiUInaGX9xlqZDY7JVryGxdxV7NPeuqQfplOpQ66yJFZut3jLa5zOwkXw1g9EI2uKh4Og==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
"node_modules/define-properties": {
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.1.tgz",
@@ -3962,6 +4718,16 @@
"integrity": "sha512-mEQCMmwJu317oSz8CwdIOdwf3xMif1ttiM8LTufzc3g6kR+9Pe236twL8j3IYT1F7GfRgGcW6MWxzZjLIkuHIg==",
"license": "MIT"
},
+ "node_modules/dequal": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/dequal/-/dequal-2.0.3.tgz",
+ "integrity": "sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=6"
+ }
+ },
"node_modules/destr": {
"version": "2.0.5",
"resolved": "https://registry.npmjs.org/destr/-/destr-2.0.5.tgz",
@@ -3982,6 +4748,13 @@
"node": ">=0.10"
}
},
+ "node_modules/doctypes": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/doctypes/-/doctypes-1.1.0.tgz",
+ "integrity": "sha512-LLBi6pEqS6Do3EKQ3J0NqHWV5hhb78Pi8vvESYwyOy2c31ZEZVdtitdzsQsKb7878PEERhzUk0ftqGhG6Mz+pQ==",
+ "dev": true,
+ "license": "MIT"
+ },
"node_modules/dom-accessibility-api": {
"version": "0.5.16",
"resolved": "https://registry.npmjs.org/dom-accessibility-api/-/dom-accessibility-api-0.5.16.tgz",
@@ -4195,6 +4968,19 @@
"@esbuild/win32-x64": "0.25.5"
}
},
+ "node_modules/esbuild-register": {
+ "version": "3.6.0",
+ "resolved": "https://registry.npmjs.org/esbuild-register/-/esbuild-register-3.6.0.tgz",
+ "integrity": "sha512-H2/S7Pm8a9CL1uhp9OvjwrBh5Pvx0H8qVOxNu8Wed9Y7qv56MPtq+GGM8RJpq6glYJn9Wspr8uw7l55uyinNeg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "debug": "^4.3.4"
+ },
+ "peerDependencies": {
+ "esbuild": ">=0.12 <1"
+ }
+ },
"node_modules/escalade": {
"version": "3.2.0",
"resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz",
@@ -4347,6 +5133,23 @@
}
}
},
+ "node_modules/eslint-plugin-storybook": {
+ "version": "9.0.8",
+ "resolved": "https://registry.npmjs.org/eslint-plugin-storybook/-/eslint-plugin-storybook-9.0.8.tgz",
+ "integrity": "sha512-JQeVZFw2+z1BFs+qlzsrhPy5xNz6p/8IuwBipnGlzC86Flj6WwQmj4ZVOIupsf0D6kiVjuEQOaiYSMYTR0KCDQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@typescript-eslint/utils": "^8.8.1"
+ },
+ "engines": {
+ "node": ">=20.0.0"
+ },
+ "peerDependencies": {
+ "eslint": ">=8",
+ "storybook": "^9.0.8"
+ }
+ },
"node_modules/eslint-plugin-vue": {
"version": "10.1.0",
"resolved": "https://registry.npmjs.org/eslint-plugin-vue/-/eslint-plugin-vue-10.1.0.tgz",
@@ -4436,6 +5239,13 @@
"node": "*"
}
},
+ "node_modules/esm-resolve": {
+ "version": "1.0.11",
+ "resolved": "https://registry.npmjs.org/esm-resolve/-/esm-resolve-1.0.11.tgz",
+ "integrity": "sha512-LxF0wfUQm3ldUDHkkV2MIbvvY0TgzIpJ420jHSV1Dm+IlplBEWiJTKWM61GtxUfvjV6iD4OtTYFGAGM2uuIUWg==",
+ "dev": true,
+ "license": "Apache-2.0"
+ },
"node_modules/espree": {
"version": "10.3.0",
"resolved": "https://registry.npmjs.org/espree/-/espree-10.3.0.tgz",
@@ -4467,6 +5277,20 @@
"url": "https://opencollective.com/eslint"
}
},
+ "node_modules/esprima": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz",
+ "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==",
+ "dev": true,
+ "license": "BSD-2-Clause",
+ "bin": {
+ "esparse": "bin/esparse.js",
+ "esvalidate": "bin/esvalidate.js"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
"node_modules/esquery": {
"version": "1.6.0",
"resolved": "https://registry.npmjs.org/esquery/-/esquery-1.6.0.tgz",
@@ -4633,6 +5457,16 @@
"node": ">=16.0.0"
}
},
+ "node_modules/filesize": {
+ "version": "10.1.6",
+ "resolved": "https://registry.npmjs.org/filesize/-/filesize-10.1.6.tgz",
+ "integrity": "sha512-sJslQKU2uM33qH5nqewAwVB2QgR6w1aMNsYUp3aN5rMRyXEwJGmZvaWzeJFNTOXWlHQyBFCWrdj3fV/fsTOX8w==",
+ "dev": true,
+ "license": "BSD-3-Clause",
+ "engines": {
+ "node": ">= 10.4.0"
+ }
+ },
"node_modules/fill-range": {
"version": "7.1.1",
"resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz",
@@ -4646,6 +5480,13 @@
"node": ">=8"
}
},
+ "node_modules/find-package-json": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/find-package-json/-/find-package-json-1.2.0.tgz",
+ "integrity": "sha512-+SOGcLGYDJHtyqHd87ysBhmaeQ95oWspDKnMXBrnQ9Eq4OkLNqejgoaD8xVWu6GPa0B6roa6KinCMEMcVeqONw==",
+ "dev": true,
+ "license": "MIT"
+ },
"node_modules/find-up": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz",
@@ -4878,6 +5719,14 @@
"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,
+ "license": "ISC",
+ "optional": true
+ },
"node_modules/graphemer": {
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz",
@@ -4995,6 +5844,13 @@
"url": "https://github.com/sponsors/ljharb"
}
},
+ "node_modules/hash-sum": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/hash-sum/-/hash-sum-2.0.0.tgz",
+ "integrity": "sha512-WdZTbAByD+pHfl/g9QSsBIIwy8IT+EsPiKDs0KNX+zSHhdDLFKdZu0BQHljvO+0QI/BasbMSUa8wYNCZTvhslg==",
+ "dev": true,
+ "license": "MIT"
+ },
"node_modules/hasown": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz",
@@ -5046,6 +5902,13 @@
"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,
+ "license": "MIT"
+ },
"node_modules/http-proxy-agent": {
"version": "7.0.2",
"resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-7.0.2.tgz",
@@ -5135,6 +5998,16 @@
"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,
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
"node_modules/index-to-position": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/index-to-position/-/index-to-position-1.1.0.tgz",
@@ -5276,6 +6149,22 @@
"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,
+ "license": "MIT",
+ "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",
@@ -5293,6 +6182,46 @@
"url": "https://github.com/sponsors/ljharb"
}
},
+ "node_modules/is-docker": {
+ "version": "2.2.1",
+ "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-2.2.1.tgz",
+ "integrity": "sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==",
+ "dev": true,
+ "license": "MIT",
+ "bin": {
+ "is-docker": "cli.js"
+ },
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/is-expression": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/is-expression/-/is-expression-4.0.0.tgz",
+ "integrity": "sha512-zMIXX63sxzG3XrkHkrAPvm/OVZVSCPNkwMHU8oTX7/U3AL78I0QXCEICXUM13BIa8TYGZ68PiTKfQz3yaTNr4A==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "acorn": "^7.1.1",
+ "object-assign": "^4.1.1"
+ }
+ },
+ "node_modules/is-expression/node_modules/acorn": {
+ "version": "7.4.1",
+ "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.1.tgz",
+ "integrity": "sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==",
+ "dev": true,
+ "license": "MIT",
+ "bin": {
+ "acorn": "bin/acorn"
+ },
+ "engines": {
+ "node": ">=0.4.0"
+ }
+ },
"node_modules/is-extglob": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
@@ -5382,6 +6311,13 @@
"optional": true,
"peer": true
},
+ "node_modules/is-promise": {
+ "version": "2.2.2",
+ "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-2.2.2.tgz",
+ "integrity": "sha512-+lP4/6lKUBfQjZ2pdxThZvLUAafmZb8OAxFb8XXtiQmS35INgr85hdOGoEs124ez1FCnZJt6jau/T+alh58QFQ==",
+ "dev": true,
+ "license": "MIT"
+ },
"node_modules/is-regex": {
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.2.1.tgz",
@@ -5507,6 +6443,19 @@
"url": "https://github.com/sponsors/mesqueeb"
}
},
+ "node_modules/is-wsl": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-2.2.0.tgz",
+ "integrity": "sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "is-docker": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
"node_modules/isarray": {
"version": "2.0.5",
"resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz",
@@ -5521,6 +6470,60 @@
"dev": true,
"license": "ISC"
},
+ "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,
+ "license": "BSD-3-Clause",
+ "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,
+ "license": "BSD-3-Clause",
+ "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,
+ "license": "BSD-3-Clause",
+ "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.1.7",
+ "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.1.7.tgz",
+ "integrity": "sha512-BewmUXImeuRk2YY0PVbxgKAysvhRPUQE0h5QRM++nVWyubKGV0l8qQ5op8+B2DOmwSe63Jivj0BjkPQVf8fP5g==",
+ "dev": true,
+ "license": "BSD-3-Clause",
+ "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",
@@ -5588,6 +6591,13 @@
"node": ">=0.10.0"
}
},
+ "node_modules/js-stringify": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/js-stringify/-/js-stringify-1.0.2.tgz",
+ "integrity": "sha512-rtS5ATOo2Q5k1G+DADISilDA6lv79zIiwFd6CcjuIxGKLFm5C+RLImRscVap9k55i+MOZwgliw+NejvkLuGD5g==",
+ "dev": true,
+ "license": "MIT"
+ },
"node_modules/js-tokens": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
@@ -5726,6 +6736,29 @@
"node": ">=6"
}
},
+ "node_modules/jsonfile": {
+ "version": "6.1.0",
+ "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz",
+ "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "universalify": "^2.0.0"
+ },
+ "optionalDependencies": {
+ "graceful-fs": "^4.1.6"
+ }
+ },
+ "node_modules/jsonfile/node_modules/universalify": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz",
+ "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 10.0.0"
+ }
+ },
"node_modules/jsonify": {
"version": "0.0.1",
"resolved": "https://registry.npmjs.org/jsonify/-/jsonify-0.0.1.tgz",
@@ -5736,6 +6769,17 @@
"url": "https://github.com/sponsors/ljharb"
}
},
+ "node_modules/jstransformer": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/jstransformer/-/jstransformer-1.0.0.tgz",
+ "integrity": "sha512-C9YK3Rf8q6VAPDCCU9fnqo3mAfOH6vUGnMcP4AQAYIEpWtfGLpwOTmZ+igtdK5y+VvI2n3CyYSzy4Qh34eq24A==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "is-promise": "^2.0.0",
+ "promise": "^7.0.1"
+ }
+ },
"node_modules/keyv": {
"version": "4.5.4",
"resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz",
@@ -5746,6 +6790,16 @@
"json-buffer": "3.0.1"
}
},
+ "node_modules/kleur": {
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz",
+ "integrity": "sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=6"
+ }
+ },
"node_modules/klona": {
"version": "2.0.6",
"resolved": "https://registry.npmjs.org/klona/-/klona-2.0.6.tgz",
@@ -5878,6 +6932,34 @@
"url": "https://github.com/sponsors/sxzz"
}
},
+ "node_modules/magicast": {
+ "version": "0.3.5",
+ "resolved": "https://registry.npmjs.org/magicast/-/magicast-0.3.5.tgz",
+ "integrity": "sha512-L0WhttDl+2BOsybvEOLK7fW3UA0OQ0IQ2d6Zl2x/a6vVRs3bAY0ECOSHHeL5jD+SbOpOCUEi0y1DgHEn9Qn1AQ==",
+ "devOptional": true,
+ "license": "MIT",
+ "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,
+ "license": "MIT",
+ "dependencies": {
+ "semver": "^7.5.3"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
"node_modules/marked": {
"version": "15.0.12",
"resolved": "https://registry.npmjs.org/marked/-/marked-15.0.12.tgz",
@@ -5946,6 +7028,16 @@
"url": "https://github.com/sponsors/jonschlinkert"
}
},
+ "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,
+ "license": "MIT",
+ "engines": {
+ "node": ">=4"
+ }
+ },
"node_modules/minimatch": {
"version": "9.0.5",
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz",
@@ -6007,6 +7099,16 @@
"pathe": "^2.0.1"
}
},
+ "node_modules/mrmime": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/mrmime/-/mrmime-2.0.1.tgz",
+ "integrity": "sha512-Y3wQdFg2Va6etvQ5I82yUhGdsKrcYox6p7FfL1LbK2J4V01F9TGlepTIhnK24t7koZibmg82KGglhA1XK5IsLQ==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=10"
+ }
+ },
"node_modules/ms": {
"version": "2.1.3",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
@@ -6059,6 +7161,19 @@
}
}
},
+ "node_modules/msw-storybook-addon": {
+ "version": "2.0.5",
+ "resolved": "https://registry.npmjs.org/msw-storybook-addon/-/msw-storybook-addon-2.0.5.tgz",
+ "integrity": "sha512-uum2gtprDBoUb8GV/rPMwPytHmB8+AUr25BQUY0MpjYey5/ujaew2Edt+4oHiXpLTd0ThyMqmEvGy/sRpDV4lg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "is-node-process": "^1.0.1"
+ },
+ "peerDependencies": {
+ "msw": "^2.0.0"
+ }
+ },
"node_modules/muggle-string": {
"version": "0.4.1",
"resolved": "https://registry.npmjs.org/muggle-string/-/muggle-string-0.4.1.tgz",
@@ -6258,6 +7373,16 @@
"node": "^14.16.0 || >=16.10.0"
}
},
+ "node_modules/object-assign": {
+ "version": "4.1.1",
+ "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
+ "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
"node_modules/object-inspect": {
"version": "1.13.4",
"resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.4.tgz",
@@ -6325,6 +7450,24 @@
"integrity": "sha512-RdR9FQrFwNBNXAr4GixM8YaRZRJ5PUWbKYbE5eOsrwAjJW0q2REGcf79oYPsLyskQCZG1PLN+S/K1V00joZAoQ==",
"license": "MIT"
},
+ "node_modules/open": {
+ "version": "8.4.2",
+ "resolved": "https://registry.npmjs.org/open/-/open-8.4.2.tgz",
+ "integrity": "sha512-7x81NCL719oNbsq/3mh+hVrAWmFuEYUqrq/Iw3kUzH8ReypT9QQ0BLoJS7/G9k6N81XjW4qHWtjWwe/9eLy1EQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "define-lazy-prop": "^2.0.0",
+ "is-docker": "^2.1.1",
+ "is-wsl": "^2.2.0"
+ },
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
"node_modules/openapi-fetch": {
"version": "0.14.0",
"resolved": "https://registry.npmjs.org/openapi-fetch/-/openapi-fetch-0.14.0.tgz",
@@ -6533,6 +7676,13 @@
"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,
+ "license": "MIT"
+ },
"node_modules/path-scurry": {
"version": "1.11.1",
"resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.11.1.tgz",
@@ -6666,6 +7816,53 @@
"pathe": "^2.0.3"
}
},
+ "node_modules/playwright": {
+ "version": "1.53.0",
+ "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.53.0.tgz",
+ "integrity": "sha512-ghGNnIEYZC4E+YtclRn4/p6oYbdPiASELBIYkBXfaTVKreQUYbMUYQDwS12a8F0/HtIjr/CkGjtwABeFPGcS4Q==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "dependencies": {
+ "playwright-core": "1.53.0"
+ },
+ "bin": {
+ "playwright": "cli.js"
+ },
+ "engines": {
+ "node": ">=18"
+ },
+ "optionalDependencies": {
+ "fsevents": "2.3.2"
+ }
+ },
+ "node_modules/playwright-core": {
+ "version": "1.53.0",
+ "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.53.0.tgz",
+ "integrity": "sha512-mGLg8m0pm4+mmtB7M89Xw/GSqoNC+twivl8ITteqvAndachozYe2ZA7srU6uleV1vEdAHYqjq+SV8SNxRRFYBw==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "bin": {
+ "playwright-core": "cli.js"
+ },
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/playwright/node_modules/fsevents": {
+ "version": "2.3.2",
+ "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz",
+ "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==",
+ "dev": true,
+ "hasInstallScript": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": "^8.16.0 || ^10.6.0 || >=11.0.0"
+ }
+ },
"node_modules/pluralize": {
"version": "8.0.0",
"resolved": "https://registry.npmjs.org/pluralize/-/pluralize-8.0.0.tgz",
@@ -6795,6 +7992,30 @@
"url": "https://github.com/chalk/ansi-styles?sponsor=1"
}
},
+ "node_modules/promise": {
+ "version": "7.3.1",
+ "resolved": "https://registry.npmjs.org/promise/-/promise-7.3.1.tgz",
+ "integrity": "sha512-nolQXZ/4L+bP/UGlkfaIujX9BKxGwmQ9OT4mOt5yvy8iK1h3wqTEJCijzGANTCCl9nWjY41juyAn2K3Q1hLLTg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "asap": "~2.0.3"
+ }
+ },
+ "node_modules/prompts": {
+ "version": "2.4.2",
+ "resolved": "https://registry.npmjs.org/prompts/-/prompts-2.4.2.tgz",
+ "integrity": "sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "kleur": "^3.0.3",
+ "sisteransi": "^1.0.5"
+ },
+ "engines": {
+ "node": ">= 6"
+ }
+ },
"node_modules/proto-list": {
"version": "1.2.4",
"resolved": "https://registry.npmjs.org/proto-list/-/proto-list-1.2.4.tgz",
@@ -6815,6 +8036,142 @@
"url": "https://github.com/sponsors/lupomontero"
}
},
+ "node_modules/pug": {
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/pug/-/pug-3.0.3.tgz",
+ "integrity": "sha512-uBi6kmc9f3SZ3PXxqcHiUZLmIXgfgWooKWXcwSGwQd2Zi5Rb0bT14+8CJjJgI8AB+nndLaNgHGrcc6bPIB665g==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "pug-code-gen": "^3.0.3",
+ "pug-filters": "^4.0.0",
+ "pug-lexer": "^5.0.1",
+ "pug-linker": "^4.0.0",
+ "pug-load": "^3.0.0",
+ "pug-parser": "^6.0.0",
+ "pug-runtime": "^3.0.1",
+ "pug-strip-comments": "^2.0.0"
+ }
+ },
+ "node_modules/pug-attrs": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/pug-attrs/-/pug-attrs-3.0.0.tgz",
+ "integrity": "sha512-azINV9dUtzPMFQktvTXciNAfAuVh/L/JCl0vtPCwvOA21uZrC08K/UnmrL+SXGEVc1FwzjW62+xw5S/uaLj6cA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "constantinople": "^4.0.1",
+ "js-stringify": "^1.0.2",
+ "pug-runtime": "^3.0.0"
+ }
+ },
+ "node_modules/pug-code-gen": {
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/pug-code-gen/-/pug-code-gen-3.0.3.tgz",
+ "integrity": "sha512-cYQg0JW0w32Ux+XTeZnBEeuWrAY7/HNE6TWnhiHGnnRYlCgyAUPoyh9KzCMa9WhcJlJ1AtQqpEYHc+vbCzA+Aw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "constantinople": "^4.0.1",
+ "doctypes": "^1.1.0",
+ "js-stringify": "^1.0.2",
+ "pug-attrs": "^3.0.0",
+ "pug-error": "^2.1.0",
+ "pug-runtime": "^3.0.1",
+ "void-elements": "^3.1.0",
+ "with": "^7.0.0"
+ }
+ },
+ "node_modules/pug-error": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/pug-error/-/pug-error-2.1.0.tgz",
+ "integrity": "sha512-lv7sU9e5Jk8IeUheHata6/UThZ7RK2jnaaNztxfPYUY+VxZyk/ePVaNZ/vwmH8WqGvDz3LrNYt/+gA55NDg6Pg==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/pug-filters": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/pug-filters/-/pug-filters-4.0.0.tgz",
+ "integrity": "sha512-yeNFtq5Yxmfz0f9z2rMXGw/8/4i1cCFecw/Q7+D0V2DdtII5UvqE12VaZ2AY7ri6o5RNXiweGH79OCq+2RQU4A==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "constantinople": "^4.0.1",
+ "jstransformer": "1.0.0",
+ "pug-error": "^2.0.0",
+ "pug-walk": "^2.0.0",
+ "resolve": "^1.15.1"
+ }
+ },
+ "node_modules/pug-lexer": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/pug-lexer/-/pug-lexer-5.0.1.tgz",
+ "integrity": "sha512-0I6C62+keXlZPZkOJeVam9aBLVP2EnbeDw3An+k0/QlqdwH6rv8284nko14Na7c0TtqtogfWXcRoFE4O4Ff20w==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "character-parser": "^2.2.0",
+ "is-expression": "^4.0.0",
+ "pug-error": "^2.0.0"
+ }
+ },
+ "node_modules/pug-linker": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/pug-linker/-/pug-linker-4.0.0.tgz",
+ "integrity": "sha512-gjD1yzp0yxbQqnzBAdlhbgoJL5qIFJw78juN1NpTLt/mfPJ5VgC4BvkoD3G23qKzJtIIXBbcCt6FioLSFLOHdw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "pug-error": "^2.0.0",
+ "pug-walk": "^2.0.0"
+ }
+ },
+ "node_modules/pug-load": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/pug-load/-/pug-load-3.0.0.tgz",
+ "integrity": "sha512-OCjTEnhLWZBvS4zni/WUMjH2YSUosnsmjGBB1An7CsKQarYSWQ0GCVyd4eQPMFJqZ8w9xgs01QdiZXKVjk92EQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "object-assign": "^4.1.1",
+ "pug-walk": "^2.0.0"
+ }
+ },
+ "node_modules/pug-parser": {
+ "version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/pug-parser/-/pug-parser-6.0.0.tgz",
+ "integrity": "sha512-ukiYM/9cH6Cml+AOl5kETtM9NR3WulyVP2y4HOU45DyMim1IeP/OOiyEWRr6qk5I5klpsBnbuHpwKmTx6WURnw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "pug-error": "^2.0.0",
+ "token-stream": "1.0.0"
+ }
+ },
+ "node_modules/pug-runtime": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/pug-runtime/-/pug-runtime-3.0.1.tgz",
+ "integrity": "sha512-L50zbvrQ35TkpHwv0G6aLSuueDRwc/97XdY8kL3tOT0FmhgG7UypU3VztfV/LATAvmUfYi4wNxSajhSAeNN+Kg==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/pug-strip-comments": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/pug-strip-comments/-/pug-strip-comments-2.0.0.tgz",
+ "integrity": "sha512-zo8DsDpH7eTkPHCXFeAk1xZXJbyoTfdPlNR0bK7rpOMuhBYb0f5qUVCO1xlsitYd3w5FQTK7zpNVKb3rZoUrrQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "pug-error": "^2.0.0"
+ }
+ },
+ "node_modules/pug-walk": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/pug-walk/-/pug-walk-2.0.0.tgz",
+ "integrity": "sha512-yYELe9Q5q9IQhuvqsZNwA5hfPkMJ8u92bQLIMcsMxf/VADjNtEYptU+inlufAFYcWdHlwNfZOEnOOQrZrcyJCQ==",
+ "dev": true,
+ "license": "MIT"
+ },
"node_modules/punycode": {
"version": "2.3.1",
"resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz",
@@ -6879,6 +8236,29 @@
"destr": "^2.0.3"
}
},
+ "node_modules/react": {
+ "version": "19.1.0",
+ "resolved": "https://registry.npmjs.org/react/-/react-19.1.0.tgz",
+ "integrity": "sha512-FS+XFBNvn3GTAWq26joslQgWNoFu08F4kl0J4CgdNKADkdSGXQyTCnKteIAJy96Br6YbpEU1LSzV5dYtjMkMDg==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/react-dom": {
+ "version": "19.1.0",
+ "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-19.1.0.tgz",
+ "integrity": "sha512-Xs1hdnE+DyKgeHJeJznQmYMIBG3TKIHJJT95Q58nHLSrElKlGQqDTR2HQ9fx5CN/Gk6Vh/kupBTDLU11/nDk/g==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "scheduler": "^0.26.0"
+ },
+ "peerDependencies": {
+ "react": "^19.1.0"
+ }
+ },
"node_modules/react-is": {
"version": "17.0.2",
"resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz",
@@ -6913,6 +8293,37 @@
"url": "https://paulmillr.com/funding/"
}
},
+ "node_modules/recast": {
+ "version": "0.23.11",
+ "resolved": "https://registry.npmjs.org/recast/-/recast-0.23.11.tgz",
+ "integrity": "sha512-YTUo+Flmw4ZXiWfQKGcwwc11KnoRAYgzAE2E7mXKCjSviTKShtxBsN6YUUBB2gtaBzKzeKunxhUwNHQuRryhWA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "ast-types": "^0.16.1",
+ "esprima": "~4.0.0",
+ "source-map": "~0.6.1",
+ "tiny-invariant": "^1.3.3",
+ "tslib": "^2.0.1"
+ },
+ "engines": {
+ "node": ">= 4"
+ }
+ },
+ "node_modules/redent": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/redent/-/redent-3.0.0.tgz",
+ "integrity": "sha512-6tDA8g98We0zd0GvVeMT9arEOnTw9qM03L9cJXaCjrip1OO764RDBLBfrB4cwzNGDj5OA5ioymC9GkizgWJDUg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "indent-string": "^4.0.0",
+ "strip-indent": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
"node_modules/regexp.prototype.flags": {
"version": "1.5.4",
"resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.4.tgz",
@@ -6961,6 +8372,27 @@
"dev": true,
"license": "MIT"
},
+ "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,
+ "license": "MIT",
+ "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",
@@ -7463,6 +8895,13 @@
"node": ">=v12.22.7"
}
},
+ "node_modules/scheduler": {
+ "version": "0.26.0",
+ "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.26.0.tgz",
+ "integrity": "sha512-NlHwttCI/l5gCPR3D1nNXtWABUmBwvZpEQiD4IXSbIDq8BzLIK/7Ir5gTFSGZDUu37K5cMNp0hFtzO38sC7gWA==",
+ "dev": true,
+ "license": "MIT"
+ },
"node_modules/scule": {
"version": "1.3.0",
"resolved": "https://registry.npmjs.org/scule/-/scule-1.3.0.tgz",
@@ -7647,6 +9086,38 @@
"url": "https://github.com/sponsors/isaacs"
}
},
+ "node_modules/sirv": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/sirv/-/sirv-3.0.1.tgz",
+ "integrity": "sha512-FoqMu0NCGBLCcAkS1qA+XJIQTR6/JHfQXl+uGteNCQ76T91DMUjPa9xfmeqMY3z80nLSg9yQmNjK0Px6RWsH/A==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@polka/url": "^1.0.0-next.24",
+ "mrmime": "^2.0.0",
+ "totalist": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "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": {
+ "version": "0.6.1",
+ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
+ "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
+ "dev": true,
+ "license": "BSD-3-Clause",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
"node_modules/source-map-js": {
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz",
@@ -7702,6 +9173,108 @@
"node": ">= 0.4"
}
},
+ "node_modules/storybook": {
+ "version": "9.0.8",
+ "resolved": "https://registry.npmjs.org/storybook/-/storybook-9.0.8.tgz",
+ "integrity": "sha512-GlOB3HAtzRYc237+o46nnETNkc2Qckh3UrIJ1rJyAzagIlPWau/jTxjSz76sqRODEnt01m8CyIkw3PGv0q1UpQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@storybook/global": "^5.0.0",
+ "@testing-library/jest-dom": "^6.6.3",
+ "@testing-library/user-event": "^14.6.1",
+ "@vitest/expect": "3.0.9",
+ "@vitest/spy": "3.0.9",
+ "better-opn": "^3.0.2",
+ "esbuild": "^0.18.0 || ^0.19.0 || ^0.20.0 || ^0.21.0 || ^0.22.0 || ^0.23.0 || ^0.24.0 || ^0.25.0",
+ "esbuild-register": "^3.5.0",
+ "recast": "^0.23.5",
+ "semver": "^7.6.2",
+ "ws": "^8.18.0"
+ },
+ "bin": {
+ "storybook": "bin/index.cjs"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/storybook"
+ },
+ "peerDependencies": {
+ "prettier": "^2 || ^3"
+ },
+ "peerDependenciesMeta": {
+ "prettier": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/storybook/node_modules/@vitest/expect": {
+ "version": "3.0.9",
+ "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-3.0.9.tgz",
+ "integrity": "sha512-5eCqRItYgIML7NNVgJj6TVCmdzE7ZVgJhruW0ziSQV4V7PvLkDL1bBkBdcTs/VuIz0IxPb5da1IDSqc1TR9eig==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@vitest/spy": "3.0.9",
+ "@vitest/utils": "3.0.9",
+ "chai": "^5.2.0",
+ "tinyrainbow": "^2.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/vitest"
+ }
+ },
+ "node_modules/storybook/node_modules/@vitest/pretty-format": {
+ "version": "3.0.9",
+ "resolved": "https://registry.npmjs.org/@vitest/pretty-format/-/pretty-format-3.0.9.tgz",
+ "integrity": "sha512-OW9F8t2J3AwFEwENg3yMyKWweF7oRJlMyHOMIhO5F3n0+cgQAJZBjNgrF8dLwFTEXl5jUqBLXd9QyyKv8zEcmA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "tinyrainbow": "^2.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/vitest"
+ }
+ },
+ "node_modules/storybook/node_modules/@vitest/spy": {
+ "version": "3.0.9",
+ "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-3.0.9.tgz",
+ "integrity": "sha512-/CcK2UDl0aQ2wtkp3YVWldrpLRNCfVcIOFGlVGKO4R5eajsH393Z1yiXLVQ7vWsj26JOEjeZI0x5sm5P4OGUNQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "tinyspy": "^3.0.2"
+ },
+ "funding": {
+ "url": "https://opencollective.com/vitest"
+ }
+ },
+ "node_modules/storybook/node_modules/@vitest/utils": {
+ "version": "3.0.9",
+ "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-3.0.9.tgz",
+ "integrity": "sha512-ilHM5fHhZ89MCp5aAaM9uhfl1c2JdxVxl3McqsdVyVNN6JffnEen8UMCdRTzOhGXNQGo5GNL9QugHrz727Wnng==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@vitest/pretty-format": "3.0.9",
+ "loupe": "^3.1.3",
+ "tinyrainbow": "^2.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/vitest"
+ }
+ },
+ "node_modules/storybook/node_modules/tinyspy": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/tinyspy/-/tinyspy-3.0.2.tgz",
+ "integrity": "sha512-n1cw8k1k0x4pgA2+9XrOkFydTerNcJ1zWCO5Nn9scWHTD+5tp8dghT2x1uduQePZTZgd3Tupf+x9BxJjeJi77Q==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=14.0.0"
+ }
+ },
"node_modules/strict-event-emitter": {
"version": "0.5.1",
"resolved": "https://registry.npmjs.org/strict-event-emitter/-/strict-event-emitter-0.5.1.tgz",
@@ -7767,6 +9340,19 @@
"node": ">=8"
}
},
+ "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,
+ "license": "MIT",
+ "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",
@@ -7823,6 +9409,19 @@
"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,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
"node_modules/symbol-tree": {
"version": "3.2.4",
"resolved": "https://registry.npmjs.org/symbol-tree/-/symbol-tree-3.2.4.tgz",
@@ -7871,6 +9470,28 @@
"url": "https://opencollective.com/synckit"
}
},
+ "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,
+ "license": "ISC",
+ "dependencies": {
+ "@istanbuljs/schema": "^0.1.2",
+ "glob": "^10.4.1",
+ "minimatch": "^9.0.4"
+ },
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/tiny-invariant": {
+ "version": "1.3.3",
+ "resolved": "https://registry.npmjs.org/tiny-invariant/-/tiny-invariant-1.3.3.tgz",
+ "integrity": "sha512-+FbBPE1o9QAYvviau/qC5SE3caw21q3xkvWKBtja5vgqOWIHHJ3ioaq1VPfn/Szqctz2bU/oYeKd9/z5BL+PVg==",
+ "dev": true,
+ "license": "MIT"
+ },
"node_modules/tinybench": {
"version": "2.9.0",
"resolved": "https://registry.npmjs.org/tinybench/-/tinybench-2.9.0.tgz",
@@ -7967,6 +9588,23 @@
"node": ">=8.0"
}
},
+ "node_modules/token-stream": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/token-stream/-/token-stream-1.0.0.tgz",
+ "integrity": "sha512-VSsyNPPW74RpHwR8Fc21uubwHY7wMDeJLys2IX5zJNih+OnAnaifKHo+1LHT7DAdloQ7apeaaWg8l7qnf/TnEg==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/totalist": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/totalist/-/totalist-3.0.1.tgz",
+ "integrity": "sha512-sf4i37nQ2LBx4m3wB74y+ubopq6W/dIzXg0FDGjsYnZHVa1Da8FH853wlL2gtUhg+xJXjfk3kUZS3BRoQeoQBQ==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=6"
+ }
+ },
"node_modules/tough-cookie": {
"version": "5.1.2",
"resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-5.1.2.tgz",
@@ -8010,6 +9648,23 @@
"typescript": ">=4.8.4"
}
},
+ "node_modules/ts-dedent": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/ts-dedent/-/ts-dedent-2.2.0.tgz",
+ "integrity": "sha512-q5W7tVM71e2xjHZTlgfTDoPF/SmqKG5hddq9SzR49CH2hayqRKJtQ4mtRlSxKaJlR/+9rEM+mnBHf7I2/BQcpQ==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=6.10"
+ }
+ },
+ "node_modules/ts-map": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/ts-map/-/ts-map-1.0.3.tgz",
+ "integrity": "sha512-vDWbsl26LIcPGmDpoVzjEP6+hvHZkBkLW7JpvwbCv/5IYPJlsbzCVXY3wsCeAxAUeTclNOUZxnLdGh3VBD/J6w==",
+ "dev": true,
+ "license": "MIT"
+ },
"node_modules/tslib": {
"version": "2.8.1",
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz",
@@ -8760,6 +10415,16 @@
}
}
},
+ "node_modules/void-elements": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/void-elements/-/void-elements-3.1.0.tgz",
+ "integrity": "sha512-Dhxzh5HZuiHQhbvTW9AMetFfBHDMYpo23Uo9btPXgdYP+3T5S+p+jgNy7spra+veYhBP2dCSgxR/i2Y02h5/6w==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
"node_modules/vscode-uri": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/vscode-uri/-/vscode-uri-3.1.0.tgz",
@@ -8788,6 +10453,27 @@
}
}
},
+ "node_modules/vue-component-meta": {
+ "version": "2.2.10",
+ "resolved": "https://registry.npmjs.org/vue-component-meta/-/vue-component-meta-2.2.10.tgz",
+ "integrity": "sha512-awylfiFFx/RFJKnu424R+btiGBEJgHa1RdJqb7SrbF5OKNYrL4VWkq49Fgvs/YbCsGSwVOjSl4em/mwOlrQ8/Q==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@volar/typescript": "~2.4.11",
+ "@vue/language-core": "2.2.10",
+ "path-browserify": "^1.0.1",
+ "vue-component-type-helpers": "2.2.10"
+ },
+ "peerDependencies": {
+ "typescript": "*"
+ },
+ "peerDependenciesMeta": {
+ "typescript": {
+ "optional": true
+ }
+ }
+ },
"node_modules/vue-component-type-helpers": {
"version": "2.2.10",
"resolved": "https://registry.npmjs.org/vue-component-type-helpers/-/vue-component-type-helpers-2.2.10.tgz",
@@ -8795,6 +10481,40 @@
"dev": true,
"license": "MIT"
},
+ "node_modules/vue-docgen-api": {
+ "version": "4.79.2",
+ "resolved": "https://registry.npmjs.org/vue-docgen-api/-/vue-docgen-api-4.79.2.tgz",
+ "integrity": "sha512-n9ENAcs+40awPZMsas7STqjkZiVlIjxIKgiJr5rSohDP0/JCrD9VtlzNojafsA1MChm/hz2h3PDtUedx3lbgfA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/parser": "^7.24.7",
+ "@babel/types": "^7.24.7",
+ "@vue/compiler-dom": "^3.2.0",
+ "@vue/compiler-sfc": "^3.2.0",
+ "ast-types": "^0.16.1",
+ "esm-resolve": "^1.0.8",
+ "hash-sum": "^2.0.0",
+ "lru-cache": "^8.0.3",
+ "pug": "^3.0.2",
+ "recast": "^0.23.1",
+ "ts-map": "^1.0.3",
+ "vue-inbrowser-compiler-independent-utils": "^4.69.0"
+ },
+ "peerDependencies": {
+ "vue": ">=2"
+ }
+ },
+ "node_modules/vue-docgen-api/node_modules/lru-cache": {
+ "version": "8.0.5",
+ "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-8.0.5.tgz",
+ "integrity": "sha512-MhWWlVnuab1RG5/zMRRcVGXZLCXrZTgfwMikgzCegsPnG62yDQo5JnqKkrK4jO5iKqDAZGItAqN5CtKBCBWRUA==",
+ "dev": true,
+ "license": "ISC",
+ "engines": {
+ "node": ">=16.14"
+ }
+ },
"node_modules/vue-eslint-parser": {
"version": "10.1.3",
"resolved": "https://registry.npmjs.org/vue-eslint-parser/-/vue-eslint-parser-10.1.3.tgz",
@@ -8833,6 +10553,16 @@
"url": "https://opencollective.com/eslint"
}
},
+ "node_modules/vue-inbrowser-compiler-independent-utils": {
+ "version": "4.71.1",
+ "resolved": "https://registry.npmjs.org/vue-inbrowser-compiler-independent-utils/-/vue-inbrowser-compiler-independent-utils-4.71.1.tgz",
+ "integrity": "sha512-K3wt3iVmNGaFEOUR4JIThQRWfqokxLfnPslD41FDZB2ajXp789+wCqJyGYlIFsvEQ2P61PInw6/ph5iiqg51gg==",
+ "dev": true,
+ "license": "MIT",
+ "peerDependencies": {
+ "vue": ">=2"
+ }
+ },
"node_modules/vue-intl": {
"version": "6.5.25",
"resolved": "https://registry.npmjs.org/vue-intl/-/vue-intl-6.5.25.tgz",
@@ -9100,6 +10830,22 @@
"node": ">=8"
}
},
+ "node_modules/with": {
+ "version": "7.0.2",
+ "resolved": "https://registry.npmjs.org/with/-/with-7.0.2.tgz",
+ "integrity": "sha512-RNGKj82nUPg3g5ygxkQl0R937xLyho1J24ItRCBTr/m1YnZkzJy1hUiHUJrc/VlsDQzsCnInEGSg3bci0Lmd4w==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/parser": "^7.9.6",
+ "@babel/types": "^7.9.6",
+ "assert-never": "^1.2.1",
+ "babel-walk": "3.0.0-canary-5"
+ },
+ "engines": {
+ "node": ">= 10.0.0"
+ }
+ },
"node_modules/word-wrap": {
"version": "1.2.5",
"resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz",
@@ -9150,8 +10896,6 @@
"integrity": "sha512-DMricUmwGZUVr++AEAe2uiVM7UoO9MAVZMDu05UQOaUII0lp+zOzLLU4Xqh/JvTqklB1T4uELaaPBKyjE1r4fQ==",
"dev": true,
"license": "MIT",
- "optional": true,
- "peer": true,
"engines": {
"node": ">=10.0.0"
},
diff --git a/next-ui/package.json b/next-ui/package.json
index eb7483c0..05af0011 100644
--- a/next-ui/package.json
+++ b/next-ui/package.json
@@ -9,7 +9,9 @@
"preview": "vite preview",
"build-only": "vite build",
"test": "vitest run",
- "test:watch": "vitest watch",
+ "test:unit": "vitest run --project unit",
+ "test:unit:watch": "vitest watch --project unit",
+ "test:storybook": "vitest run --project storybook",
"type-check": "vue-tsc --build --force",
"lint": "eslint .",
"lint:fix": "npm run lint -- --fix",
@@ -18,7 +20,9 @@
"openapi-generate": "npx tsx ./openapi-generator.mts",
"i18n:extract": "formatjs extract \"src/**/*.{ts,tsx,vue}\" --ignore=\"**/*.d.ts\" --out-file i18n/en.json",
"i18n:compile": "formatjs compile-folder i18n src/i18n",
- "i18n:verify": "formatjs verify --missing-keys --source-locale=en \"i18n/*.json\""
+ "i18n:verify": "formatjs verify --missing-keys --source-locale=en \"i18n/*.json\"",
+ "storybook:dev": "storybook dev -p 6006",
+ "storybook:build": "storybook build"
},
"dependencies": {
"@pinia/colada": "^0.17.0",
@@ -34,27 +38,40 @@
"vuetify": "^3.8.5"
},
"devDependencies": {
+ "@chromatic-com/storybook": "^4.0.0",
"@eslint/js": "^9.28.0",
"@formatjs/cli": "^6.7.1",
"@iconify-json/mdi": "^1.2.3",
+ "@storybook/addon-a11y": "^9.0.8",
+ "@storybook/addon-docs": "^9.0.8",
+ "@storybook/addon-onboarding": "^9.0.8",
+ "@storybook/addon-themes": "^9.0.8",
+ "@storybook/addon-vitest": "^9.0.8",
+ "@storybook/vue3-vite": "^9.0.8",
"@testing-library/vue": "^8.1.0",
"@tsconfig/node22": "^22.0.2",
"@types/node": "^22.15.29",
- "@vitejs/plugin-vue": "^5.1.4",
+ "@vitejs/plugin-vue": "^5.2.4",
+ "@vitest/browser": "^3.2.3",
+ "@vitest/coverage-v8": "^3.2.3",
"@vue/eslint-config-prettier": "^10.2.0",
"@vue/eslint-config-typescript": "^14.1.3",
"@vue/tsconfig": "^0.7.0",
"eslint": "^9.28.0",
"eslint-config-prettier": "^10.1.5",
"eslint-plugin-formatjs": "^5.3.1",
+ "eslint-plugin-storybook": "^9.0.8",
"eslint-plugin-vue": "^10.1.0",
"happy-dom": "^18.0.1",
"msw": "^2.10.2",
+ "msw-storybook-addon": "^2.0.5",
"npm-run-all2": "^8.0.4",
"openapi-typescript": "^7.8.0",
+ "playwright": "^1.53.0",
"prettier": "^3.5.3",
"sass": "^1.88.0",
"sass-embedded": "^1.88.0",
+ "storybook": "^9.0.8",
"typescript": "^5.8.3",
"unplugin-auto-import": "^19.3.0",
"unplugin-fonts": "^1.1.1",
@@ -68,5 +85,10 @@
"vitest": "^3.2.3",
"vue-router": "^4.4.0",
"vue-tsc": "^2.1.10"
+ },
+ "msw": {
+ "workerDirectory": [
+ "public-msw"
+ ]
}
}
diff --git a/next-ui/public-msw/mockServiceWorker.js b/next-ui/public-msw/mockServiceWorker.js
new file mode 100644
index 00000000..b6099e64
--- /dev/null
+++ b/next-ui/public-msw/mockServiceWorker.js
@@ -0,0 +1,336 @@
+/* eslint-disable */
+/* tslint:disable */
+
+/**
+ * Mock Service Worker.
+ * @see https://github.com/mswjs/msw
+ * - Please do NOT modify this file.
+ */
+
+const PACKAGE_VERSION = '2.10.2'
+const INTEGRITY_CHECKSUM = 'f5825c521429caf22a4dd13b66e243af'
+const IS_MOCKED_RESPONSE = Symbol('isMockedResponse')
+const activeClientIds = new Set()
+
+addEventListener('install', function () {
+ self.skipWaiting()
+})
+
+addEventListener('activate', function (event) {
+ event.waitUntil(self.clients.claim())
+})
+
+addEventListener('message', async function (event) {
+ const clientId = Reflect.get(event.source || {}, 'id')
+
+ if (!clientId || !self.clients) {
+ return
+ }
+
+ const client = await self.clients.get(clientId)
+
+ if (!client) {
+ return
+ }
+
+ const allClients = await self.clients.matchAll({
+ type: 'window',
+ })
+
+ switch (event.data) {
+ case 'KEEPALIVE_REQUEST': {
+ sendToClient(client, {
+ type: 'KEEPALIVE_RESPONSE',
+ })
+ break
+ }
+
+ case 'INTEGRITY_CHECK_REQUEST': {
+ sendToClient(client, {
+ type: 'INTEGRITY_CHECK_RESPONSE',
+ payload: {
+ packageVersion: PACKAGE_VERSION,
+ checksum: INTEGRITY_CHECKSUM,
+ },
+ })
+ break
+ }
+
+ case 'MOCK_ACTIVATE': {
+ activeClientIds.add(clientId)
+
+ sendToClient(client, {
+ type: 'MOCKING_ENABLED',
+ payload: {
+ client: {
+ id: client.id,
+ frameType: client.frameType,
+ },
+ },
+ })
+ break
+ }
+
+ case 'MOCK_DEACTIVATE': {
+ activeClientIds.delete(clientId)
+ break
+ }
+
+ case 'CLIENT_CLOSED': {
+ activeClientIds.delete(clientId)
+
+ const remainingClients = allClients.filter((client) => {
+ return client.id !== clientId
+ })
+
+ // Unregister itself when there are no more clients
+ if (remainingClients.length === 0) {
+ self.registration.unregister()
+ }
+
+ break
+ }
+ }
+})
+
+addEventListener('fetch', function (event) {
+ // Bypass navigation requests.
+ if (event.request.mode === 'navigate') {
+ return
+ }
+
+ // Opening the DevTools triggers the "only-if-cached" request
+ // that cannot be handled by the worker. Bypass such requests.
+ if (event.request.cache === 'only-if-cached' && event.request.mode !== 'same-origin') {
+ return
+ }
+
+ // Bypass all requests when there are no active clients.
+ // Prevents the self-unregistered worked from handling requests
+ // after it's been deleted (still remains active until the next reload).
+ if (activeClientIds.size === 0) {
+ return
+ }
+
+ const requestId = crypto.randomUUID()
+ event.respondWith(handleRequest(event, requestId))
+})
+
+/**
+ * @param {FetchEvent} event
+ * @param {string} requestId
+ */
+async function handleRequest(event, requestId) {
+ const client = await resolveMainClient(event)
+ const requestCloneForEvents = event.request.clone()
+ const response = await getResponse(event, client, requestId)
+
+ // Send back the response clone for the "response:*" life-cycle events.
+ // Ensure MSW is active and ready to handle the message, otherwise
+ // this message will pend indefinitely.
+ if (client && activeClientIds.has(client.id)) {
+ const serializedRequest = await serializeRequest(requestCloneForEvents)
+
+ // Clone the response so both the client and the library could consume it.
+ const responseClone = response.clone()
+
+ sendToClient(
+ client,
+ {
+ type: 'RESPONSE',
+ payload: {
+ isMockedResponse: IS_MOCKED_RESPONSE in response,
+ request: {
+ id: requestId,
+ ...serializedRequest,
+ },
+ response: {
+ type: responseClone.type,
+ status: responseClone.status,
+ statusText: responseClone.statusText,
+ headers: Object.fromEntries(responseClone.headers.entries()),
+ body: responseClone.body,
+ },
+ },
+ },
+ responseClone.body ? [serializedRequest.body, responseClone.body] : [],
+ )
+ }
+
+ return response
+}
+
+/**
+ * Resolve the main client for the given event.
+ * Client that issues a request doesn't necessarily equal the client
+ * that registered the worker. It's with the latter the worker should
+ * communicate with during the response resolving phase.
+ * @param {FetchEvent} event
+ * @returns {Promise}
+ */
+async function resolveMainClient(event) {
+ const client = await self.clients.get(event.clientId)
+
+ if (activeClientIds.has(event.clientId)) {
+ return client
+ }
+
+ if (client?.frameType === 'top-level') {
+ return client
+ }
+
+ const allClients = await self.clients.matchAll({
+ type: 'window',
+ })
+
+ return allClients
+ .filter((client) => {
+ // Get only those clients that are currently visible.
+ return client.visibilityState === 'visible'
+ })
+ .find((client) => {
+ // Find the client ID that's recorded in the
+ // set of clients that have registered the worker.
+ return activeClientIds.has(client.id)
+ })
+}
+
+/**
+ * @param {FetchEvent} event
+ * @param {Client | undefined} client
+ * @param {string} requestId
+ * @returns {Promise}
+ */
+async function getResponse(event, client, requestId) {
+ // Clone the request because it might've been already used
+ // (i.e. its body has been read and sent to the client).
+ const requestClone = event.request.clone()
+
+ function passthrough() {
+ // Cast the request headers to a new Headers instance
+ // so the headers can be manipulated with.
+ const headers = new Headers(requestClone.headers)
+
+ // Remove the "accept" header value that marked this request as passthrough.
+ // This prevents request alteration and also keeps it compliant with the
+ // user-defined CORS policies.
+ const acceptHeader = headers.get('accept')
+ if (acceptHeader) {
+ const values = acceptHeader.split(',').map((value) => value.trim())
+ const filteredValues = values.filter((value) => value !== 'msw/passthrough')
+
+ if (filteredValues.length > 0) {
+ headers.set('accept', filteredValues.join(', '))
+ } else {
+ headers.delete('accept')
+ }
+ }
+
+ return fetch(requestClone, { headers })
+ }
+
+ // Bypass mocking when the client is not active.
+ if (!client) {
+ return passthrough()
+ }
+
+ // Bypass initial page load requests (i.e. static assets).
+ // The absence of the immediate/parent client in the map of the active clients
+ // means that MSW hasn't dispatched the "MOCK_ACTIVATE" event yet
+ // and is not ready to handle requests.
+ if (!activeClientIds.has(client.id)) {
+ return passthrough()
+ }
+
+ // Notify the client that a request has been intercepted.
+ const serializedRequest = await serializeRequest(event.request)
+ const clientMessage = await sendToClient(
+ client,
+ {
+ type: 'REQUEST',
+ payload: {
+ id: requestId,
+ ...serializedRequest,
+ },
+ },
+ [serializedRequest.body],
+ )
+
+ switch (clientMessage.type) {
+ case 'MOCK_RESPONSE': {
+ return respondWithMock(clientMessage.data)
+ }
+
+ case 'PASSTHROUGH': {
+ return passthrough()
+ }
+ }
+
+ return passthrough()
+}
+
+/**
+ * @param {Client} client
+ * @param {any} message
+ * @param {Array} transferrables
+ * @returns {Promise}
+ */
+function sendToClient(client, message, transferrables = []) {
+ return new Promise((resolve, reject) => {
+ const channel = new MessageChannel()
+
+ channel.port1.onmessage = (event) => {
+ if (event.data && event.data.error) {
+ return reject(event.data.error)
+ }
+
+ resolve(event.data)
+ }
+
+ client.postMessage(message, [channel.port2, ...transferrables.filter(Boolean)])
+ })
+}
+
+/**
+ * @param {Response} response
+ * @returns {Response}
+ */
+function respondWithMock(response) {
+ // Setting response status code to 0 is a no-op.
+ // However, when responding with a "Response.error()", the produced Response
+ // instance will have status code set to 0. Since it's not possible to create
+ // a Response instance with status code 0, handle that use-case separately.
+ if (response.status === 0) {
+ return Response.error()
+ }
+
+ const mockedResponse = new Response(response.body, response)
+
+ Reflect.defineProperty(mockedResponse, IS_MOCKED_RESPONSE, {
+ value: true,
+ enumerable: true,
+ })
+
+ return mockedResponse
+}
+
+/**
+ * @param {Request} request
+ */
+async function serializeRequest(request) {
+ return {
+ url: request.url,
+ mode: request.mode,
+ method: request.method,
+ headers: Object.fromEntries(request.headers.entries()),
+ cache: request.cache,
+ credentials: request.credentials,
+ destination: request.destination,
+ integrity: request.integrity,
+ redirect: request.redirect,
+ referrer: request.referrer,
+ referrerPolicy: request.referrerPolicy,
+ body: await request.arrayBuffer(),
+ keepalive: request.keepalive,
+ }
+}
diff --git a/next-ui/src/assets/komga.svg b/next-ui/src/assets/komga.svg
new file mode 100644
index 00000000..76683061
--- /dev/null
+++ b/next-ui/src/assets/komga.svg
@@ -0,0 +1,122 @@
+
+
diff --git a/next-ui/src/colada/queries/app-releases.ts b/next-ui/src/colada/queries/app-releases.ts
index 0fc93e4a..b92b15ae 100644
--- a/next-ui/src/colada/queries/app-releases.ts
+++ b/next-ui/src/colada/queries/app-releases.ts
@@ -19,8 +19,8 @@ export const useAppReleases = defineQuery(() => {
const latestRelease = computed(() => data.value?.find((x) => x.latest))
const isLatestVersion = computed(() => {
- if (buildVersion.value && latestRelease.value)
- return buildVersion.value == latestRelease.value?.version
+ if (buildVersion.value && data.value)
+ return data.value?.some((x) => x.latest && x.version == buildVersion.value)
else return undefined
})
diff --git a/next-ui/src/components/BuildCommit.stories.ts b/next-ui/src/components/BuildCommit.stories.ts
new file mode 100644
index 00000000..6371c6b2
--- /dev/null
+++ b/next-ui/src/components/BuildCommit.stories.ts
@@ -0,0 +1,49 @@
+import type { Meta, StoryObj } from '@storybook/vue3-vite'
+
+import BuildCommit from './BuildCommit.vue'
+import { http, HttpResponse, delay } from 'msw'
+import { baseUrl, response401Unauthorized } from '@/mocks/api/handlers/base'
+import { actuatorResponseOk } from '@/mocks/api/handlers/actuator'
+
+const meta = {
+ component: BuildCommit,
+ render: (args: object) => ({
+ components: { BuildCommit },
+ setup() {
+ return { args }
+ },
+ template: '',
+ }),
+ parameters: {
+ // More on how to position stories at: https://storybook.js.org/docs/configure/story-layout
+ },
+ args: {},
+} satisfies Meta
+
+export default meta
+type Story = StoryObj
+
+export const Default: Story = {
+ args: {},
+}
+
+export const Loading: Story = {
+ parameters: {
+ msw: {
+ handlers: [
+ http.get(baseUrl + 'actuator/info', async () => {
+ await delay(5_000)
+ return HttpResponse.json(actuatorResponseOk)
+ }),
+ ],
+ },
+ },
+}
+
+export const Error: Story = {
+ parameters: {
+ msw: {
+ handlers: [http.get(baseUrl + 'actuator/info', response401Unauthorized)],
+ },
+ },
+}
diff --git a/next-ui/src/components/BuildCommit.vue b/next-ui/src/components/BuildCommit.vue
index e81178cd..781e3db7 100644
--- a/next-ui/src/components/BuildCommit.vue
+++ b/next-ui/src/components/BuildCommit.vue
@@ -1,22 +1,22 @@
-
-
- {{ commitId }}
-
-
+
+ {{ commitId || $formatMessage(commonMessages.error) }}
+
diff --git a/next-ui/src/components/BuildVersion.stories.ts b/next-ui/src/components/BuildVersion.stories.ts
new file mode 100644
index 00000000..c3cc0531
--- /dev/null
+++ b/next-ui/src/components/BuildVersion.stories.ts
@@ -0,0 +1,62 @@
+import type { Meta, StoryObj } from '@storybook/vue3-vite'
+
+import { http, HttpResponse, delay } from 'msw'
+import { baseUrl, response401Unauthorized } from '@/mocks/api/handlers/base'
+import BuildVersion from './BuildVersion.vue'
+import { releasesResponseOk, releasesResponseOkNotLatest } from '@/mocks/api/handlers/releases'
+
+const meta = {
+ component: BuildVersion,
+ render: (args: object) => ({
+ components: { BuildVersion },
+ setup() {
+ return { args }
+ },
+ template: '',
+ }),
+ parameters: {
+ // More on how to position stories at: https://storybook.js.org/docs/configure/story-layout
+ },
+ args: {},
+} satisfies Meta
+
+export default meta
+type Story = StoryObj
+
+export const Default: Story = {
+ args: {},
+}
+
+export const OutdatedVersion: Story = {
+ parameters: {
+ msw: {
+ handlers: [
+ http.get(baseUrl + 'api/v1/releases', () => HttpResponse.json(releasesResponseOkNotLatest)),
+ ],
+ },
+ },
+}
+
+export const Loading: Story = {
+ parameters: {
+ msw: {
+ handlers: [
+ http.get(baseUrl + 'api/v1/releases', async () => {
+ await delay(5_000)
+ return HttpResponse.json(releasesResponseOk)
+ }),
+ ],
+ },
+ },
+}
+
+export const Error: Story = {
+ parameters: {
+ msw: {
+ handlers: [
+ http.get(baseUrl + 'actuator/info', response401Unauthorized),
+ http.get(baseUrl + 'api/v1/releases', response401Unauthorized),
+ ],
+ },
+ },
+}
diff --git a/next-ui/src/components/BuildVersion.vue b/next-ui/src/components/BuildVersion.vue
index 5842715c..296ab820 100644
--- a/next-ui/src/components/BuildVersion.vue
+++ b/next-ui/src/components/BuildVersion.vue
@@ -1,27 +1,27 @@
-
-
+
-
- {{ buildVersion }}
-
-
-
+ {{ buildVersion || $formatMessage(commonMessages.error) }}
+
+
diff --git a/next-ui/src/pages/login.stories.ts b/next-ui/src/pages/login.stories.ts
new file mode 100644
index 00000000..c42f9ea8
--- /dev/null
+++ b/next-ui/src/pages/login.stories.ts
@@ -0,0 +1,25 @@
+import type { Meta, StoryObj } from '@storybook/vue3-vite'
+
+import login from './login.vue'
+
+const meta = {
+ component: login,
+ render: (args: object) => ({
+ components: { login },
+ setup() {
+ return { args }
+ },
+ template: '',
+ }),
+ parameters: {
+ // More on how to position stories at: https://storybook.js.org/docs/configure/story-layout
+ },
+ args: {},
+} satisfies Meta
+
+export default meta
+type Story = StoryObj
+
+export const Default: Story = {
+ args: {},
+}
diff --git a/next-ui/src/pages/server/users.stories.ts b/next-ui/src/pages/server/users.stories.ts
new file mode 100644
index 00000000..e17bcc14
--- /dev/null
+++ b/next-ui/src/pages/server/users.stories.ts
@@ -0,0 +1,27 @@
+import type { Meta, StoryObj } from '@storybook/vue3-vite'
+
+import users from './users.vue'
+
+const meta = {
+ component: users,
+ render: (args: object) => ({
+ components: { users },
+ setup() {
+ return { args }
+ },
+ template: '',
+ }),
+ parameters: {
+ // More on how to position stories at: https://storybook.js.org/docs/configure/story-layout
+ },
+ args: {},
+ // This component will have an automatically generated docsPage entry: https://storybook.js.org/docs/writing-docs/autodocs
+ tags: ['autodocs'],
+} satisfies Meta
+
+export default meta
+type Story = StoryObj
+
+export const Default: Story = {
+ args: {},
+}
diff --git a/next-ui/src/utils/i18n/common-messages.ts b/next-ui/src/utils/i18n/common-messages.ts
index 2698daf6..90d0c583 100644
--- a/next-ui/src/utils/i18n/common-messages.ts
+++ b/next-ui/src/utils/i18n/common-messages.ts
@@ -16,4 +16,9 @@ export const commonMessages = {
defaultMessage: 'Network error',
id: 'Z/EY89',
}),
+ error: defineMessage({
+ description: 'Common message: an unkown error happened',
+ defaultMessage: 'error',
+ id: 'Xz+JXU',
+ }),
}
diff --git a/next-ui/src/utils/i18n/locale-helper.ts b/next-ui/src/utils/i18n/locale-helper.ts
index ea700d8f..6c159e82 100644
--- a/next-ui/src/utils/i18n/locale-helper.ts
+++ b/next-ui/src/utils/i18n/locale-helper.ts
@@ -1,5 +1,5 @@
import { defineMessage } from 'vue-intl'
-import localeMessages from '../i18n?dir2json&ext=.json&1'
+import localeMessages from '@/i18n?dir2json&ext=.json&1'
export const defaultLocale = 'en'
diff --git a/next-ui/tsconfig.app.json b/next-ui/tsconfig.app.json
index 5c9bb2c1..92a70f10 100644
--- a/next-ui/tsconfig.app.json
+++ b/next-ui/tsconfig.app.json
@@ -1,6 +1,13 @@
{
"extends": "@vue/tsconfig/tsconfig.dom.json",
- "include": ["env.d.ts", "src/**/*", "src/**/*.vue", "./dir2json.d.ts"],
+ "include": [
+ "env.d.ts",
+ "src/**/*",
+ "src/**/*.vue",
+ "./dir2json.d.ts",
+ "./.storybook/**/*",
+ "vitest.shims.d.ts"
+ ],
"exclude": ["src/**/__tests__/*"],
"compilerOptions": {
"tsBuildInfoFile": "./node_modules/.tmp/tsconfig.app.tsbuildinfo",
diff --git a/next-ui/vite.config.mts b/next-ui/vite.config.mts
index 89c1c8fb..3619a332 100644
--- a/next-ui/vite.config.mts
+++ b/next-ui/vite.config.mts
@@ -16,6 +16,7 @@ import dir2json from 'vite-plugin-dir2json'
// Utilities
import { defineConfig } from 'vite'
import { fileURLToPath, URL } from 'node:url'
+import { storybookTest } from '@storybook/addon-vitest/vitest-plugin'
// https://vitejs.dev/config/
export default defineConfig({
@@ -84,7 +85,32 @@ export default defineConfig({
},
},
test: {
- environment: 'happy-dom',
- restoreMocks: true,
+ projects: [
+ {
+ extends: true,
+ test: {
+ name: 'unit',
+ environment: 'happy-dom',
+ restoreMocks: true,
+ },
+ },
+ {
+ test: {
+ name: 'storybook',
+ browser: {
+ enabled: true,
+ headless: true,
+ provider: 'playwright',
+ instances: [{ browser: 'chromium' }],
+ },
+ setupFiles: ['.storybook/vitest.setup.ts'],
+ },
+ plugins: [
+ // The plugin will run tests for the stories defined in your Storybook config
+ // See options at: https://storybook.js.org/docs/next/writing-tests/integrations/vitest-addon#storybooktest
+ storybookTest(),
+ ],
+ },
+ ],
},
})
diff --git a/next-ui/vitest.shims.d.ts b/next-ui/vitest.shims.d.ts
new file mode 100644
index 00000000..a1d31e5a
--- /dev/null
+++ b/next-ui/vitest.shims.d.ts
@@ -0,0 +1 @@
+///