diff --git a/.github/workflows/fw-lite.yaml b/.github/workflows/fw-lite.yaml index 53e8672c6d..ed4e2803b9 100644 --- a/.github/workflows/fw-lite.yaml +++ b/.github/workflows/fw-lite.yaml @@ -103,6 +103,38 @@ jobs: if-no-files-found: error path: ${{ env.VIEWER_BUILD_OUTPUT_DIR }} + frontend-component-unit-tests: + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v4 + - uses: pnpm/action-setup@fe02b34f77f8bc703788d5817da081398fad5dd2 # v4.0.0 + with: + package_json_file: 'frontend/package.json' + - uses: actions/setup-node@v4 + with: + node-version-file: './frontend/package.json' + cache: 'pnpm' + cache-dependency-path: './frontend/pnpm-lock.yaml' + - name: Prepare frontend + working-directory: frontend + run: | + pnpm install + # vitest is configured to use playwright for stories and other browser-based tests + - name: Set up Playwright dependencies + working-directory: frontend/viewer + run: pnpm exec playwright install --with-deps + - name: vitest + working-directory: frontend/viewer + run: pnpm run test --reporter=default --reporter=junit --outputFile.junit=test-results/vitest-results.xml + - name: Publish unit test results + uses: EnricoMi/publish-unit-test-result-action@8885e273a4343cd7b48eaa72428dea0c3067ea98 # v2.14.0 + if: always() + with: + check_name: UI unit Tests + files: ./frontend/viewer/test-results/*.xml + action_fail_on_inconclusive: true + publish-mac: name: Publish FW Lite app for Mac needs: [build-and-test, frontend] diff --git a/frontend/Taskfile.yml b/frontend/Taskfile.yml index 71c529e0ef..80375354b5 100644 --- a/frontend/Taskfile.yml +++ b/frontend/Taskfile.yml @@ -36,7 +36,11 @@ tasks: fw-lite-infr-internal: internal: true - deps: [ viewer:run-app, run-https-proxy ] + deps: + - task: viewer:run-app + - task: run-https-proxy + - task: viewer:storybook + vars: { CLI_ARGS: --no-open } playwright-tests: aliases: [ pt ] diff --git a/frontend/package.json b/frontend/package.json index d79d09a51c..82831bad66 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -109,5 +109,10 @@ "sveltekit-search-params": "^3", "tus-js-client": "^4.3.1", "viewer": "workspace:*" + }, + "pnpm": { + "onlyBuiltDependencies": [ + "esbuild" + ] } -} +} \ No newline at end of file diff --git a/frontend/pnpm-lock.yaml b/frontend/pnpm-lock.yaml index b9449abd0e..20be87028f 100644 --- a/frontend/pnpm-lock.yaml +++ b/frontend/pnpm-lock.yaml @@ -7,8 +7,8 @@ settings: catalogs: default: '@playwright/test': - specifier: ^1.49.1 - version: 1.50.1 + specifier: ^1.52.0 + version: 1.52.0 '@stylistic/eslint-plugin': specifier: ^2.12.1 version: 2.13.0 @@ -24,15 +24,21 @@ catalogs: '@vitejs/plugin-basic-ssl': specifier: ^1.2.0 version: 1.2.0 + '@vitest/browser': + specifier: ^3.2.2 + version: 3.2.2 '@vitest/ui': - specifier: ^3.0.5 - version: 3.0.5 + specifier: ^3.2.2 + version: 3.2.2 eslint: specifier: ^9.20.1 version: 9.20.1 eslint-plugin-svelte: specifier: 2.46.1 version: 2.46.1 + playwright: + specifier: ^1.52.0 + version: 1.52.0 postcss: specifier: ^8.4.49 version: 8.5.2 @@ -67,8 +73,8 @@ catalogs: specifier: ^6.0.3 version: 6.1.0 vitest: - specifier: ^3.0.5 - version: 3.0.5 + specifier: ^3.2.2 + version: 3.2.2 importers: @@ -188,7 +194,7 @@ importers: version: 1.2.3 '@playwright/test': specifier: 'catalog:' - version: 1.50.1 + version: 1.52.0 '@stylistic/eslint-plugin': specifier: 'catalog:' version: 2.13.0(eslint@9.20.1(jiti@2.4.2))(typescript@5.7.3) @@ -299,7 +305,7 @@ importers: version: 3.5.0(@graphql-codegen/cli@5.0.5(@types/node@20.17.32)(graphql-sock@1.0.1(graphql@16.11.0))(graphql@16.11.0)(typescript@5.7.3))(graphql@16.11.0)(vite@6.1.0(@types/node@20.17.32)(jiti@2.4.2)(yaml@2.7.1)) vitest: specifier: 'catalog:' - version: 3.0.5(@types/debug@4.1.12)(@types/node@20.17.32)(@vitest/ui@3.0.5)(happy-dom@17.1.0)(jiti@2.4.2)(yaml@2.7.1) + version: 3.2.2(@types/debug@4.1.12)(@types/node@20.17.32)(@vitest/browser@3.2.2)(@vitest/ui@3.2.2)(happy-dom@17.1.0)(jiti@2.4.2)(yaml@2.7.1) zod: specifier: ^3.24.3 version: 3.24.3 @@ -389,11 +395,14 @@ importers: version: 4.34.1 virtua: specifier: ^0.41.2 - version: 0.41.2(svelte@5.28.2) + version: 0.41.2(react-dom@19.1.0(react@19.1.0))(react@19.1.0)(svelte@5.28.2) devDependencies: '@argos-ci/playwright': specifier: ^5.0.4 version: 5.0.4 + '@chromatic-com/storybook': + specifier: ^4 + version: 4.0.0(storybook@9.0.8(@testing-library/dom@10.4.0)(prettier@3.5.0)) '@egoist/tailwindcss-icons': specifier: ^1.9.0 version: 1.9.0(tailwindcss@3.4.17) @@ -408,46 +417,58 @@ importers: version: 5.2.0(typescript@5.7.3) '@lingui/vite-plugin': specifier: ^5.2.0 - version: 5.2.0(typescript@5.7.3)(vite@6.1.0(@types/node@22.15.3)(jiti@2.4.2)(yaml@2.7.1)) + version: 5.2.0(typescript@5.7.3)(vite@6.1.0(@types/node@20.17.32)(jiti@2.4.2)(yaml@2.7.1)) '@mdi/js': specifier: ^7.4.47 version: 7.4.47 '@playwright/test': specifier: 'catalog:' - version: 1.50.1 + version: 1.52.0 + '@storybook/addon-a11y': + specifier: ^9.0.8 + version: 9.0.8(storybook@9.0.8(@testing-library/dom@10.4.0)(prettier@3.5.0)) + '@storybook/addon-docs': + specifier: ^9.0.8 + version: 9.0.8(@types/react@19.1.6)(storybook@9.0.8(@testing-library/dom@10.4.0)(prettier@3.5.0)) + '@storybook/addon-svelte-csf': + specifier: ^5.0.3 + version: 5.0.3(@storybook/svelte@9.0.8(storybook@9.0.8(@testing-library/dom@10.4.0)(prettier@3.5.0))(svelte@5.28.2))(@sveltejs/vite-plugin-svelte@5.0.3(svelte@5.28.2)(vite@6.1.0(@types/node@20.17.32)(jiti@2.4.2)(yaml@2.7.1)))(babel-plugin-macros@3.1.0)(storybook@9.0.8(@testing-library/dom@10.4.0)(prettier@3.5.0))(svelte@5.28.2)(vite@6.1.0(@types/node@20.17.32)(jiti@2.4.2)(yaml@2.7.1)) + '@storybook/addon-vitest': + specifier: ^9.0.8 + version: 9.0.8(@vitest/browser@3.2.2)(@vitest/runner@3.2.2)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)(storybook@9.0.8(@testing-library/dom@10.4.0)(prettier@3.5.0))(vitest@3.2.2) + '@storybook/svelte-vite': + specifier: ^9.0.8 + version: 9.0.8(@sveltejs/vite-plugin-svelte@5.0.3(svelte@5.28.2)(vite@6.1.0(@types/node@20.17.32)(jiti@2.4.2)(yaml@2.7.1)))(storybook@9.0.8(@testing-library/dom@10.4.0)(prettier@3.5.0))(svelte@5.28.2)(vite@6.1.0(@types/node@20.17.32)(jiti@2.4.2)(yaml@2.7.1)) '@stylistic/eslint-plugin': specifier: 'catalog:' version: 2.13.0(eslint@9.20.1(jiti@2.4.2))(typescript@5.7.3) '@sveltejs/vite-plugin-svelte': specifier: 'catalog:' - version: 5.0.3(svelte@5.28.2)(vite@6.1.0(@types/node@22.15.3)(jiti@2.4.2)(yaml@2.7.1)) + version: 5.0.3(svelte@5.28.2)(vite@6.1.0(@types/node@20.17.32)(jiti@2.4.2)(yaml@2.7.1)) '@tailwindcss/container-queries': specifier: ^0.1.1 version: 0.1.1(tailwindcss@3.4.17) '@tailwindcss/typography': specifier: ^0.5.16 version: 0.5.16(tailwindcss@3.4.17) - '@testing-library/jest-dom': - specifier: ^6.6.3 - version: 6.6.3 - '@testing-library/svelte': - specifier: ^5.2.6 - version: 5.2.7(svelte@5.28.2)(vite@6.1.0(@types/node@22.15.3)(jiti@2.4.2)(yaml@2.7.1))(vitest@3.0.5) - '@testing-library/user-event': - specifier: ^14.5.2 - version: 14.6.1(@testing-library/dom@10.4.0) '@tsconfig/svelte': specifier: ^5.0.4 version: 5.0.4 + '@types/node': + specifier: ^20 + version: 20.17.32 '@typescript-eslint/eslint-plugin': specifier: 'catalog:' version: 8.24.0(@typescript-eslint/parser@8.24.0(eslint@9.20.1(jiti@2.4.2))(typescript@5.7.3))(eslint@9.20.1(jiti@2.4.2))(typescript@5.7.3) '@typescript-eslint/parser': specifier: 'catalog:' version: 8.24.0(eslint@9.20.1(jiti@2.4.2))(typescript@5.7.3) + '@vitest/browser': + specifier: 'catalog:' + version: 3.2.2(playwright@1.52.0)(vite@6.1.0(@types/node@20.17.32)(jiti@2.4.2)(yaml@2.7.1))(vitest@3.2.2) '@vitest/ui': specifier: 'catalog:' - version: 3.0.5(vitest@3.0.5) + version: 3.2.2(vitest@3.2.2) bits-ui: specifier: 1.4.3 version: 1.4.3(svelte@5.28.2) @@ -457,6 +478,9 @@ importers: eslint: specifier: 'catalog:' version: 9.20.1(jiti@2.4.2) + eslint-plugin-storybook: + specifier: ^9.0.8 + version: 9.0.8(eslint@9.20.1(jiti@2.4.2))(storybook@9.0.8(@testing-library/dom@10.4.0)(prettier@3.5.0))(typescript@5.7.3) eslint-plugin-svelte: specifier: 'catalog:' version: 2.46.1(eslint@9.20.1(jiti@2.4.2))(svelte@5.28.2) @@ -469,6 +493,12 @@ importers: paneforge: specifier: 1.0.0-next.4 version: 1.0.0-next.4(svelte@5.28.2) + playwright: + specifier: 'catalog:' + version: 1.52.0 + storybook: + specifier: ^9.0.8 + version: 9.0.8(@testing-library/dom@10.4.0)(prettier@3.5.0) svelte: specifier: 'catalog:' version: 5.28.2 @@ -507,13 +537,16 @@ importers: version: 1.0.0-next.6(svelte@5.28.2) vite: specifier: 'catalog:' - version: 6.1.0(@types/node@22.15.3)(jiti@2.4.2)(yaml@2.7.1) + version: 6.1.0(@types/node@20.17.32)(jiti@2.4.2)(yaml@2.7.1) vite-plugin-webfont-dl: specifier: ^3.10.4 - version: 3.10.4(vite@6.1.0(@types/node@22.15.3)(jiti@2.4.2)(yaml@2.7.1)) + version: 3.10.4(vite@6.1.0(@types/node@20.17.32)(jiti@2.4.2)(yaml@2.7.1)) vitest: specifier: 'catalog:' - version: 3.0.5(@types/debug@4.1.12)(@types/node@22.15.3)(@vitest/ui@3.0.5)(happy-dom@17.1.0)(jiti@2.4.2)(yaml@2.7.1) + version: 3.2.2(@types/debug@4.1.12)(@types/node@20.17.32)(@vitest/browser@3.2.2)(@vitest/ui@3.2.2)(happy-dom@17.1.0)(jiti@2.4.2)(yaml@2.7.1) + vitest-browser-svelte: + specifier: ^0.1.0 + version: 0.1.0(@vitest/browser@3.2.2)(svelte@5.28.2)(vitest@3.2.2) packages: @@ -678,6 +711,12 @@ packages: resolution: {integrity: sha512-H45s8fVLYjbhFH62dIJ3WtmJ6RSPt/3DRO0ZcT2SUiYiQyz3BLVb9ADEnLl91m74aQPS3AzzeajZHYOalWe3bg==} engines: {node: '>=6.9.0'} + '@chromatic-com/storybook@4.0.0': + resolution: {integrity: sha512-FfyMHK/lz/dHezWxwNZv4ReFORWVvv+bJx71NT2BSfLhOKOaoZnKJOe4QLyGxWAB7ynnedrM9V9qea3FPFj+rQ==} + engines: {node: '>=20.0.0', yarn: '>=1.22.18'} + peerDependencies: + storybook: ^0.0.0-0 || ^9.0.0 || ^9.1.0-0 + '@colors/colors@1.6.0': resolution: {integrity: sha512-Ir+AOibqzrIsL6ajt3Rz3LskB7OiMVHqltZmspbW/TJuTVuyOMirVqAkjfY6JISiLHgyNqicAC8AyHHGzNd/dA==} engines: {node: '>=0.1.90'} @@ -1554,6 +1593,12 @@ packages: '@mdi/js@7.4.47': resolution: {integrity: sha512-KPnNOtm5i2pMabqZxpUz7iQf+mfrYZyKCZ8QNz85czgEt7cuHcGorWfdzUMWYA0SD+a6Hn4FmJ+YhzzzjkTZrQ==} + '@mdx-js/react@3.1.0': + resolution: {integrity: sha512-QjHtSaoameoalGnKDT3FoIl4+9RwyTmo9ZJGBdLOks/YOiWHoRDI3PUwEzOE7kEmGcV3AFcp9K6dYu9rEuKLAQ==} + peerDependencies: + '@types/react': '>=16' + react: '>=16' + '@messageformat/parser@5.1.1': resolution: {integrity: sha512-3p0YRGCcTUCYvBKLIxtDDyrJ0YijGIwrTRu1DT8gIviIDZru8H23+FkY6MJBzM1n9n20CiM4VeDYuBsrrwnLjg==} @@ -1563,6 +1608,9 @@ packages: '@microsoft/signalr@8.0.7': resolution: {integrity: sha512-PHcdMv8v5hJlBkRHAuKG5trGViQEkPYee36LnJQx4xHOQ5LL4X0nEWIxOp5cCtZ7tu+30quz5V3k0b1YNuc6lw==} + '@neoconfetti/react@1.0.0': + resolution: {integrity: sha512-klcSooChXXOzIm+SE5IISIAn3bYzYfPjbX7D7HoqZL84oAfgREeSg5vSIaSFH+DaGzzvImTyWe1OyrJ67vik4A==} + '@nodelib/fs.scandir@2.1.5': resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==} engines: {node: '>= 8'} @@ -2198,8 +2246,8 @@ packages: resolution: {integrity: sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==} engines: {node: '>=14'} - '@playwright/test@1.50.1': - resolution: {integrity: sha512-Jii3aBg+CEDpgnuDxEp/h7BimHcUTDlpEtce89xEumlJ5ef2hqepZ+PWp1DDpYC/VO9fmWVI1IlEaoI5fK9FXQ==} + '@playwright/test@1.52.0': + resolution: {integrity: sha512-uh6W7sb55hl7D6vsAeA+V2p5JnlAqzhqFyF0VcJkKZXkgnFcVG9PziERRHQfPLfNGx1C292a4JqbWzhR8L4R1g==} engines: {node: '>=18'} hasBin: true @@ -2397,6 +2445,87 @@ packages: '@sinclair/typebox@0.27.8': resolution: {integrity: sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==} + '@storybook/addon-a11y@9.0.8': + resolution: {integrity: sha512-5wFBlISLUDykvpzATR0m7DbvD2+ImiqVx3EfoamrRqzuStTYh/5eEKYvbTznPFBrgvvboCzvVWT2ZqNByeQhxw==} + peerDependencies: + storybook: ^9.0.8 + + '@storybook/addon-docs@9.0.8': + resolution: {integrity: sha512-YRR8qHitwXVTJyn02YMrzd9mCKcuZWSKWt+J/ddFb8khGfLcAW+O0NohGeqMyM6XStLVDKKIKsMoTHggUwIFsA==} + peerDependencies: + storybook: ^9.0.8 + + '@storybook/addon-svelte-csf@5.0.3': + resolution: {integrity: sha512-P6f/fCqL0Wq79LTe1EjSjKppKE5h8Dz5+x9R/NK7+5PyQI4NS1RNwMnppUJeJhF4CqV7BLjsFGr88DT3AAdytw==} + peerDependencies: + '@storybook/svelte': ^0.0.0-0 || ^8.2.0 || ^9.0.0 || ^9.1.0-0 + '@sveltejs/vite-plugin-svelte': ^4.0.0 || ^5.0.0 + storybook: ^0.0.0-0 || ^8.2.0 || ^9.0.0 || ^9.1.0-0 + svelte: ^5.0.0 + vite: ^5.0.0 || ^6.0.0 + + '@storybook/addon-vitest@9.0.8': + resolution: {integrity: sha512-LfO98ZbXwMknEnN9ICOj2UodVyr/62Q1o64WQyuktVZVZ4fXQXtPZO7uP9F4TX5HuvNWIiaxGlhBYfEzcErbUA==} + 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 + + '@storybook/builder-vite@9.0.8': + resolution: {integrity: sha512-dbwDfBUwLW8I71h0Y9r+twtEdjKC+oBP1YweS26ET78qc6qXMFsK5Tfh6lzj/vQbmxY0YhnTVrrkXgfR0erLPA==} + peerDependencies: + storybook: ^9.0.8 + vite: ^5.0.0 || ^6.0.0 + + '@storybook/csf-plugin@9.0.8': + resolution: {integrity: sha512-mNjo4t9liAbQvhE9ni87NU2sz9tqFU4Y54ioSFDlW24wpubsvnhBi5h4z3EkeQJSzIzNMRym9SC7Elbqa3Kf+g==} + peerDependencies: + storybook: ^9.0.8 + + '@storybook/csf@0.1.13': + resolution: {integrity: sha512-7xOOwCLGB3ebM87eemep89MYRFTko+D8qE7EdAAq74lgdqRR5cOUtYWJLjO2dLtP94nqoOdHJo6MdLLKzg412Q==} + + '@storybook/global@5.0.0': + resolution: {integrity: sha512-FcOqPAXACP0I3oJ/ws6/rrPT9WGhu915Cg8D02a9YxLo0DE9zI+a9A5gRGvmQ09fiWPukqI8ZAEoQEdWUKMQdQ==} + + '@storybook/icons@1.4.0': + resolution: {integrity: sha512-Td73IeJxOyalzvjQL+JXx72jlIYHgs+REaHiREOqfpo3A2AYYG71AUbcv+lg7mEDIweKVCxsMQ0UKo634c8XeA==} + 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 + + '@storybook/react-dom-shim@9.0.8': + resolution: {integrity: sha512-SYyjRagHZx724hGEWSZcXRzj82am77OpqeA9ps6ZsCSn4cVY9FORGEeY2bnlQkpLnDUH5yjdV/oh+0fXDbl/8g==} + 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 + + '@storybook/svelte-vite@9.0.8': + resolution: {integrity: sha512-erOrMhuiElM7/vvcIyhGaVZuWQayYAG17Noa4H2IugAoXtZ0ptYmcmjqay98wua+VyX4xIESi601J5ZYdTylHA==} + engines: {node: '>=20.0.0'} + peerDependencies: + '@sveltejs/vite-plugin-svelte': ^2.0.0 || ^3.0.0 || ^4.0.0 || ^5.0.0 + storybook: ^9.0.8 + svelte: ^5.0.0 + vite: ^5.0.0 || ^6.0.0 + + '@storybook/svelte@9.0.8': + resolution: {integrity: sha512-afkG3GlUF6U9qTyfhY92NUlZpmmps0kyCSTs/sLncXZE/D8Ca6Cl00+xhAtGbBui2hoJM6tsYGNL+bLUKWiGUA==} + engines: {node: '>=20.0.0'} + peerDependencies: + storybook: ^9.0.8 + svelte: ^5.0.0 + '@stylistic/eslint-plugin@2.13.0': resolution: {integrity: sha512-RnO1SaiCFHn666wNz2QfZEFxvmiNRqhzaMXHXxXXKt+MEP7aajlPxUSMIQpKAaJfverpovEYqjBOXDq6dDcaOQ==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} @@ -2473,19 +2602,6 @@ packages: resolution: {integrity: sha512-IteBhl4XqYNkM54f4ejhLRJiZNqcSCoXUOG2CPK7qbD322KjQozM4kHQOfkG2oln9b9HTYqs+Sae8vBATubxxA==} engines: {node: '>=14', npm: '>=6', yarn: '>=1'} - '@testing-library/svelte@5.2.7': - resolution: {integrity: sha512-aGhUaFmEXEVost4QOsbHUUbHLwi7ZZRRxAHFDO2Cmr0BZD3/3+XvaYEPq70Rdw0NRNjdqZHdARBEcrCOkPuAqw==} - engines: {node: '>= 10'} - peerDependencies: - svelte: ^3 || ^4 || ^5 || ^5.0.0-next.0 - vite: '*' - vitest: '*' - peerDependenciesMeta: - vite: - optional: true - vitest: - optional: true - '@testing-library/user-event@14.6.1': resolution: {integrity: sha512-vq7fv0rnt+QTXgPxr5Hjc210p6YKq2kmdziLgnsZGgLJ9e6VAShx1pACLuRjd/AS/sr7phAR58OIIpf0LlmQNw==} engines: {node: '>=12', npm: '>=6'} @@ -2510,6 +2626,9 @@ packages: '@types/bunyan@1.8.9': resolution: {integrity: sha512-ZqS9JGpBxVOvsawzmVt30sP++gSQMTejCkIAQ3VdadOcRE8izTyW66hufvwLeH+YEGP6Js2AW7Gz+RMyvrEbmw==} + '@types/chai@5.2.2': + resolution: {integrity: sha512-8kB30R7Hwqf40JPiKhVzodJs2Qc1ZJ5zuT3uzw5Hq/dhNCl3G3l83jfpdI1e20BP348+fV7VIL/+FxaXkqBmWg==} + '@types/connect@3.4.36': resolution: {integrity: sha512-P63Zd/JUGq+PdrM1lv0Wv5SBYeA2+CORvbrXbngriYY0jzLUWfQMQQxOhjONEz/wlHOAxOdY7CY65rgQdTjq2w==} @@ -2528,6 +2647,9 @@ packages: '@types/debug@4.1.12': resolution: {integrity: sha512-vIChWdVG3LG1SMxEvI/AK+FWJthlrqlTu7fbrlywTkkaONwk/UAGaULXRlf8vkzFBLVm0zkMdCquhL5aOjhXPQ==} + '@types/deep-eql@4.0.2': + resolution: {integrity: sha512-c9h9dVVMigMPc4bwTvC5dxqtqJZwQPePsWjPlpSOnojbor6pGqdk541lfA7AqFQr5pB1BRdq0juY9db81BwyFw==} + '@types/estree@0.0.39': resolution: {integrity: sha512-EYNwp3bU+98cpU4lAWYYL7Zz+2gryWH1qbdDTidVd6hkiR6weksdbMadyXKXNPEkQFhXM+hVO9ZygomHXp+AIw==} @@ -2585,6 +2707,9 @@ packages: '@types/mdast@4.0.4': resolution: {integrity: sha512-kGaNbPh1k7AFzgpud/gMdvIm5xuECykRR+JnWKQno9TAXVa6WIVCGTPvYGekIDL4uwCZQSYbUxNBSb1aUo79oA==} + '@types/mdx@2.0.13': + resolution: {integrity: sha512-+OWZQfAYyio6YkJb3HLxDrvnx6SWWDbC0zVPfBRzUk0/nqoDyf6dNxQi3eArPe8rJ473nobTMQ/8Zk+LxJ+Yuw==} + '@types/memcached@2.2.10': resolution: {integrity: sha512-AM9smvZN55Gzs2wRrqeMHVP7KE8KWgCJO/XL5yCly2xF6EKa4YlbpK+cLSAH4NG/Ah64HrlegmGqW8kYws7Vxg==} @@ -2627,6 +2752,9 @@ packages: '@types/range-parser@1.2.7': resolution: {integrity: sha512-hKormJbkJqzQGhziax5PItDUTMAM9uE2XXQmM37dyd4hVM+5aVl7oVxMVUiVQn2oCQFN/LKCZdvSM0pFRqbSmQ==} + '@types/react@19.1.6': + resolution: {integrity: sha512-JeG0rEWak0N6Itr6QUx+X60uQmN+5t3j9r/OVDtWzFXKaj6kD1BwJzOksD0FF6iWxZlbE1kB0q9vtnU2ekqa1Q==} + '@types/resolve@1.17.1': resolution: {integrity: sha512-yy7HuzQhj0dhGpD8RLXSZWEkLsV9ibvxvi6EiJ3bkqLAO1RGo0WbkWQiwpRlSFymTJRz0d3k5LM3kkx8ArDbLw==} @@ -2770,42 +2898,66 @@ packages: peerDependencies: vite: ^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 - '@vitest/expect@3.0.5': - resolution: {integrity: sha512-nNIOqupgZ4v5jWuQx2DSlHLEs7Q4Oh/7AYwNyE+k0UQzG7tSmjPXShUikn1mpNGzYEN2jJbTvLejwShMitovBA==} + '@vitest/browser@3.2.2': + resolution: {integrity: sha512-LJk8ZhCGhgG6G6jFFJ9LX83ibRY8FszLuu9zPaYFDrcHbBwNXwt1v06HRs/vHVYxwjw3/BGzSIgn9Et2P6rCiA==} + peerDependencies: + playwright: '*' + safaridriver: '*' + vitest: 3.2.2 + webdriverio: ^7.0.0 || ^8.0.0 || ^9.0.0 + peerDependenciesMeta: + playwright: + optional: true + safaridriver: + optional: true + webdriverio: + optional: true + + '@vitest/expect@3.0.9': + resolution: {integrity: sha512-5eCqRItYgIML7NNVgJj6TVCmdzE7ZVgJhruW0ziSQV4V7PvLkDL1bBkBdcTs/VuIz0IxPb5da1IDSqc1TR9eig==} + + '@vitest/expect@3.2.2': + resolution: {integrity: sha512-ipHw0z669vEMjzz3xQE8nJX1s0rQIb7oEl4jjl35qWTwm/KIHERIg/p/zORrjAaZKXfsv7IybcNGHwhOOAPMwQ==} - '@vitest/mocker@3.0.5': - resolution: {integrity: sha512-CLPNBFBIE7x6aEGbIjaQAX03ZZlBMaWwAjBdMkIf/cAn6xzLTiM3zYqO/WAbieEjsAZir6tO71mzeHZoodThvw==} + '@vitest/mocker@3.2.2': + resolution: {integrity: sha512-jKojcaRyIYpDEf+s7/dD3LJt53c0dPfp5zCPXz9H/kcGrSlovU/t1yEaNzM9oFME3dcd4ULwRI/x0Po1Zf+LTw==} peerDependencies: msw: ^2.4.9 - vite: ^5.0.0 || ^6.0.0 + vite: ^5.0.0 || ^6.0.0 || ^7.0.0-0 peerDependenciesMeta: msw: optional: true vite: optional: true - '@vitest/pretty-format@3.0.5': - resolution: {integrity: sha512-CjUtdmpOcm4RVtB+up8r2vVDLR16Mgm/bYdkGFe3Yj/scRfCpbSi2W/BDSDcFK7ohw8UXvjMbOp9H4fByd/cOA==} + '@vitest/pretty-format@3.0.9': + resolution: {integrity: sha512-OW9F8t2J3AwFEwENg3yMyKWweF7oRJlMyHOMIhO5F3n0+cgQAJZBjNgrF8dLwFTEXl5jUqBLXd9QyyKv8zEcmA==} + + '@vitest/pretty-format@3.2.2': + resolution: {integrity: sha512-FY4o4U1UDhO9KMd2Wee5vumwcaHw7Vg4V7yR4Oq6uK34nhEJOmdRYrk3ClburPRUA09lXD/oXWZ8y/Sdma0aUQ==} - '@vitest/pretty-format@3.1.2': - resolution: {integrity: sha512-R0xAiHuWeDjTSB3kQ3OQpT8Rx3yhdOAIm/JM4axXxnG7Q/fS8XUwggv/A4xzbQA+drYRjzkMnpYnOGAc4oeq8w==} + '@vitest/runner@3.2.2': + resolution: {integrity: sha512-GYcHcaS3ejGRZYed2GAkvsjBeXIEerDKdX3orQrBJqLRiea4NSS9qvn9Nxmuy1IwIB+EjFOaxXnX79l8HFaBwg==} - '@vitest/runner@3.0.5': - resolution: {integrity: sha512-BAiZFityFexZQi2yN4OX3OkJC6scwRo8EhRB0Z5HIGGgd2q+Nq29LgHU/+ovCtd0fOfXj5ZI6pwdlUmC5bpi8A==} + '@vitest/snapshot@3.2.2': + resolution: {integrity: sha512-aMEI2XFlR1aNECbBs5C5IZopfi5Lb8QJZGGpzS8ZUHML5La5wCbrbhLOVSME68qwpT05ROEEOAZPRXFpxZV2wA==} - '@vitest/snapshot@3.0.5': - resolution: {integrity: sha512-GJPZYcd7v8QNUJ7vRvLDmRwl+a1fGg4T/54lZXe+UOGy47F9yUfE18hRCtXL5aHN/AONu29NGzIXSVFh9K0feA==} + '@vitest/spy@3.0.9': + resolution: {integrity: sha512-/CcK2UDl0aQ2wtkp3YVWldrpLRNCfVcIOFGlVGKO4R5eajsH393Z1yiXLVQ7vWsj26JOEjeZI0x5sm5P4OGUNQ==} - '@vitest/spy@3.0.5': - resolution: {integrity: sha512-5fOzHj0WbUNqPK6blI/8VzZdkBlQLnT25knX0r4dbZI9qoZDf3qAdjoMmDcLG5A83W6oUUFJgUd0EYBc2P5xqg==} + '@vitest/spy@3.2.2': + resolution: {integrity: sha512-6Utxlx3o7pcTxvp0u8kUiXtRFScMrUg28KjB3R2hon7w4YqOFAEA9QwzPVVS1QNL3smo4xRNOpNZClRVfpMcYg==} - '@vitest/ui@3.0.5': - resolution: {integrity: sha512-gw2noso6WI+2PeMVCZFntdATS6xl9qhQcbhkPQ9sOmx/Xn0f4Bx4KDSbD90jpJPF0l5wOzSoGCmKyVR3W612mg==} + '@vitest/ui@3.2.2': + resolution: {integrity: sha512-xHif5tkQOZK4YjA44rrzmvXMI1cb1Qato3P+NL/gwyoK5LdZx0f5Q59Il25JtuhN/htBvrT+Copt3Q4Ma4gJbg==} peerDependencies: - vitest: 3.0.5 + vitest: 3.2.2 + + '@vitest/utils@3.0.9': + resolution: {integrity: sha512-ilHM5fHhZ89MCp5aAaM9uhfl1c2JdxVxl3McqsdVyVNN6JffnEen8UMCdRTzOhGXNQGo5GNL9QugHrz727Wnng==} - '@vitest/utils@3.0.5': - resolution: {integrity: sha512-N9AX0NUoUtVwKwy21JtwzaqR5L5R5A99GAbrHfCCXK1lp593i/3AZAXhSP43wRQuxYsflrdzEfXZFo1reR1Nkg==} + '@vitest/utils@3.2.2': + resolution: {integrity: sha512-qJYMllrWpF/OYfWHP32T31QCaLa3BAzT/n/8mNGhPdVcjY+JYazQFO1nsJvXU12Kp1xMpNY4AGuljPTNjQve6A==} '@whatwg-node/disposablestack@0.0.6': resolution: {integrity: sha512-LOtTn+JgJvX8WfBVJtF08TGrdjuFzGJc4mkP8EdDI8ADbvO7kiexYep1o8dwnt0okb0jYclCDXF13xU7Ge4zSw==} @@ -2930,6 +3082,10 @@ packages: resolution: {integrity: sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA==} engines: {node: '>=12'} + ast-types@0.16.1: + resolution: {integrity: sha512-6t10qk83GOG8p0vKmaCr8eiilZwO171AvbROMtvvNiwrTly62t+7XkA8RdIIVbpMhCASAsxgAzdRSwh6nw/5Dg==} + engines: {node: '>=4'} + astral-regex@2.0.0: resolution: {integrity: sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==} engines: {node: '>=8'} @@ -2962,6 +3118,10 @@ packages: peerDependencies: postcss: ^8.1.0 + axe-core@4.10.3: + resolution: {integrity: sha512-Xm7bpRXnDSX2YE2YFfBk2FnF0ep6tmG7xPh8iHee8MIcrgq762Nkce856dYtJYLkuIoYZvGfTs/PbZhideTcEg==} + engines: {node: '>=4'} + axios@1.7.9: resolution: {integrity: sha512-LhLcE7Hbiryz8oMDdDptSrWowmB4Bl6RCt6sIJKpRB4XtVf0iEgewX3au/pJqm+Py1kCASkb/FFKjxQaLtxJvw==} @@ -2990,6 +3150,10 @@ packages: base64-js@1.5.1: resolution: {integrity: sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==} + better-opn@3.0.2: + resolution: {integrity: sha512-aVNobHnJqLiUelTaHat9DZ1qM2w0C0Eym4LPI/3JxOnSokGVdsl1T1kN7TFvsEAD8G47A6VKQ0TVHqbBnYMJlQ==} + engines: {node: '>=12.0.0'} + bignumber.js@9.3.0: resolution: {integrity: sha512-EM7aMFTXbptt/wZdMlBv2t8IViwQL+h6SLHosp8Yf0dqJMTnY6iL32opnAB6kAdL0SZPuvcAzFr31o0c/R3/RA==} @@ -3132,6 +3296,18 @@ packages: resolution: {integrity: sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA==} engines: {node: '>= 14.16.0'} + chromatic@12.1.0: + resolution: {integrity: sha512-X45IVEb8mX3J+iDEpb6dY6CUvqWm5jlo8QqzgUGFYlcO7A327Ve3G4dzuu96f/hcXifZ0T1E7BMN6/z0iO4V2A==} + hasBin: true + 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 + cjs-module-lexer@1.4.3: resolution: {integrity: sha512-9z8TZaGM1pfswYeXrUpzPrkx8UnWYdhJclsiYMm6x/w5+nN+8Tf/LnAgfLGQCm59qAOxU8WwHEq2vNwF6i4j+Q==} @@ -3341,6 +3517,9 @@ packages: engines: {node: '>=4'} hasBin: true + csstype@3.1.3: + resolution: {integrity: sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==} + cuint@0.2.2: resolution: {integrity: sha512-d4ZVpCW31eWwCMe1YT3ur7mUDnTXbgwyzaL320DrcRT45rfjYxkt5QWLrmOJ+/UEAI2+fQgKe/fCjR8l4TpRgw==} @@ -3416,12 +3595,32 @@ packages: supports-color: optional: true + debug@4.4.1: + resolution: {integrity: sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ==} + engines: {node: '>=6.0'} + peerDependencies: + supports-color: '*' + peerDependenciesMeta: + supports-color: + optional: true + decimal.js@10.5.0: resolution: {integrity: sha512-8vDa8Qxvr/+d94hSh5P3IJwI5t8/c0KsMp+g8bNw9cY2icONa5aPfvKeieW1WlG0WQYwwhJ7mjui2xtiePQSXw==} decode-named-character-reference@1.1.0: resolution: {integrity: sha512-Wy+JTSbFThEOXQIR2L6mxJvEs+veIzpmqD7ynWxMXGpnk3smkHQOp6forLdHsKpAMW9iJpaBBIxz285t1n1C3w==} + dedent-js@1.0.1: + resolution: {integrity: sha512-OUepMozQULMLUmhxS95Vudo0jb0UchLimi3+pQ2plj61Fcy8axbP9hbiD4Sz6DPqn6XG3kfmziVfQ1rSys5AJQ==} + + dedent@1.6.0: + resolution: {integrity: sha512-F1Z+5UCFpmQUzJa11agbyPVMbpgT/qA3/SKyJ1jyBgm7dUcUEa8v9JwDkerSQXfakBwFljIxhOJqGkjUwZ9FSA==} + peerDependencies: + babel-plugin-macros: ^3.1.0 + peerDependenciesMeta: + babel-plugin-macros: + optional: true + deep-eql@5.0.2: resolution: {integrity: sha512-h5k/5U50IJJFpzfL6nO9jaaumfjO/f2NjK/oYB2Djzm4p9L+3T9qWpZqZ2hAbLPuuYq9wrU08WQyBTL5GbPk5Q==} engines: {node: '>=6'} @@ -3606,6 +3805,14 @@ packages: resolution: {integrity: sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==} engines: {node: '>= 0.4'} + es-toolkit@1.39.0: + resolution: {integrity: sha512-EoVtfsblZAUBu1pLM7SS0JH6mOUSln+l7IPkdTAasDFO1jYJIrdFv6usRuGbUFKIuA78OVlvpGldGSztAihQQQ==} + + esbuild-register@3.6.0: + resolution: {integrity: sha512-H2/S7Pm8a9CL1uhp9OvjwrBh5Pvx0H8qVOxNu8Wed9Y7qv56MPtq+GGM8RJpq6glYJn9Wspr8uw7l55uyinNeg==} + peerDependencies: + esbuild: '>=0.12 <1' + esbuild@0.21.5: resolution: {integrity: sha512-mg3OPMV4hXywwpoDxu3Qda5xCKQi+vCTZq8S9J/EpkhB2HzKXq4SNFZE3+NK93JYxc8VMSep+lOUSC/RVKaBqw==} engines: {node: '>=12'} @@ -3642,6 +3849,13 @@ packages: peerDependencies: eslint: '>=6.0.0' + eslint-plugin-storybook@9.0.8: + resolution: {integrity: sha512-JQeVZFw2+z1BFs+qlzsrhPy5xNz6p/8IuwBipnGlzC86Flj6WwQmj4ZVOIupsf0D6kiVjuEQOaiYSMYTR0KCDQ==} + engines: {node: '>=20.0.0'} + peerDependencies: + eslint: '>=8' + storybook: ^9.0.8 + eslint-plugin-svelte@2.46.1: resolution: {integrity: sha512-7xYr2o4NID/f9OEYMqxsEQsCsj4KaMy4q5sANaKkAb6/QeCjYFxRmDm2S3YC3A3pl1kyPZ/syOx/i7LcWYSbIw==} engines: {node: ^14.17.0 || >=16.0.0} @@ -3689,10 +3903,18 @@ packages: resolution: {integrity: sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + esprima@4.0.1: + resolution: {integrity: sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==} + engines: {node: '>=4'} + hasBin: true + esquery@1.6.0: resolution: {integrity: sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg==} engines: {node: '>=0.10'} + esrap@1.2.2: + resolution: {integrity: sha512-F2pSJklxx1BlQIQgooczXCPHmcWpn6EsP5oo73LQfonG9fIlIENQ8vMmfGXeojP9MrkzUNAfyU5vdFlR9shHAw==} + esrap@1.4.6: resolution: {integrity: sha512-F/D2mADJ9SHY3IwksD4DAXjTt7qt7GWUf3/8RhCNWmC/67tyb55dpimHmy7EplakFaflV0R/PC+fdSPqrRHAQw==} @@ -3809,6 +4031,10 @@ packages: resolution: {integrity: sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==} engines: {node: '>=16.0.0'} + filesize@10.1.6: + resolution: {integrity: sha512-sJslQKU2uM33qH5nqewAwVB2QgR6w1aMNsYUp3aN5rMRyXEwJGmZvaWzeJFNTOXWlHQyBFCWrdj3fV/fsTOX8w==} + engines: {node: '>= 10.4.0'} + fill-range@7.1.1: resolution: {integrity: sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==} engines: {node: '>=8'} @@ -4329,6 +4555,9 @@ packages: engines: {node: '>=6'} hasBin: true + jsonfile@6.1.0: + resolution: {integrity: sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==} + juice@10.0.1: resolution: {integrity: sha512-ZhJT1soxJCkOiO55/mz8yeBKTAJhRzX9WBO+16ZTqNTONnnVlUPyVBIzQ7lDRjaBdTbid+bAnyIon/GM3yp4cA==} engines: {node: '>=10.0.0'} @@ -4350,6 +4579,10 @@ packages: keyv@5.3.2: resolution: {integrity: sha512-Lji2XRxqqa5Wg+CHLVfFKBImfJZ4pCSccu9eVWK6w4c2SDFLd8JAn1zqTuSFnsxb7ope6rMsnIHfp+eBbRBRZQ==} + kleur@3.0.3: + resolution: {integrity: sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==} + engines: {node: '>=6'} + kleur@4.1.5: resolution: {integrity: sha512-o+NO+8WrRiQEE4/7nwRJhN1HWpVmJm511pBHUxPLtp0BUISzlBplORYSmTclCnJvQq2tKu/sgl3xVpkc7ZWuQQ==} engines: {node: '>=6'} @@ -5148,13 +5381,13 @@ packages: resolution: {integrity: sha512-nDywThFk1i4BQK4twPQ6TA4RT8bDY96yeuCVBWL3ePARCiEKDRSrNGbFIgUJpLp+XeIR65v8ra7WuJOFUBtkMA==} engines: {node: '>=8'} - playwright-core@1.50.1: - resolution: {integrity: sha512-ra9fsNWayuYumt+NiM069M6OkcRb1FZSK8bgi66AtpFoWkg2+y0bJSNmkFrWhMbEBbVKC/EruAHH3g0zmtwGmQ==} + playwright-core@1.52.0: + resolution: {integrity: sha512-l2osTgLXSMeuLZOML9qYODUQoPPnUsKsb5/P6LJ2e6uPKXUdPK5WYhN4z03G+YNbWmGDY4YENauNu4ZKczreHg==} engines: {node: '>=18'} hasBin: true - playwright@1.50.1: - resolution: {integrity: sha512-G8rwsOQJ63XG6BbKj2w5rHeavFjy5zynBA9zsJMMtBoe/Uf757oG12NXz6e6OirF7RCrTVAKFXbLmn1RbL7Qaw==} + playwright@1.52.0: + resolution: {integrity: sha512-JAwMNMBlxJ2oD1kce4KPtMkDeKGHQstdpFPcPH3maElAXon/QZeTvtsfXmTMRyO9TslfoYOXkSsvao2nE1ilTw==} engines: {node: '>=18'} hasBin: true @@ -5285,6 +5518,10 @@ packages: promise@7.3.1: resolution: {integrity: sha512-nolQXZ/4L+bP/UGlkfaIujX9BKxGwmQ9OT4mOt5yvy8iK1h3wqTEJCijzGANTCCl9nWjY41juyAn2K3Q1hLLTg==} + prompts@2.4.2: + resolution: {integrity: sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q==} + engines: {node: '>= 6'} + proper-lockfile@4.1.2: resolution: {integrity: sha512-TjNPblN4BwAWMXU8s9AEz4JmQxnD1NNL7bNOY/AKUzyamc379FWASUhc/K1pL2noVb+XmZKLL68cjzLsiOAMaA==} @@ -5344,12 +5581,21 @@ packages: queue-microtask@1.2.3: resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==} + react-dom@19.1.0: + resolution: {integrity: sha512-Xs1hdnE+DyKgeHJeJznQmYMIBG3TKIHJJT95Q58nHLSrElKlGQqDTR2HQ9fx5CN/Gk6Vh/kupBTDLU11/nDk/g==} + peerDependencies: + react: ^19.1.0 + react-is@17.0.2: resolution: {integrity: sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==} react-is@18.3.1: resolution: {integrity: sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==} + react@19.1.0: + resolution: {integrity: sha512-FS+XFBNvn3GTAWq26joslQgWNoFu08F4kl0J4CgdNKADkdSGXQyTCnKteIAJy96Br6YbpEU1LSzV5dYtjMkMDg==} + engines: {node: '>=0.10.0'} + read-cache@1.0.0: resolution: {integrity: sha512-Owdv/Ft7IjOgm/i0xvNDZ1LrRANRfew4b2prF3OWMQLxLfu3bS8FVhCsrSCMK4lR56Y9ya+AThoTpDCTxCmpRA==} @@ -5369,6 +5615,10 @@ packages: resolution: {integrity: sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg==} engines: {node: '>= 14.18.0'} + recast@0.23.11: + resolution: {integrity: sha512-YTUo+Flmw4ZXiWfQKGcwwc11KnoRAYgzAE2E7mXKCjSviTKShtxBsN6YUUBB2gtaBzKzeKunxhUwNHQuRryhWA==} + engines: {node: '>= 4'} + redent@3.0.0: resolution: {integrity: sha512-6tDA8g98We0zd0GvVeMT9arEOnTw9qM03L9cJXaCjrip1OO764RDBLBfrB4cwzNGDj5OA5ioymC9GkizgWJDUg==} engines: {node: '>=8'} @@ -5522,6 +5772,9 @@ packages: safer-buffer@2.1.2: resolution: {integrity: sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==} + scheduler@0.26.0: + resolution: {integrity: sha512-NlHwttCI/l5gCPR3D1nNXtWABUmBwvZpEQiD4IXSbIDq8BzLIK/7Ir5gTFSGZDUu37K5cMNp0hFtzO38sC7gWA==} + scuid@1.1.0: resolution: {integrity: sha512-MuCAyrGZcTLfQoH2XoBlQ8C6bzwN88XT/0slOGz0pn8+gIP85BOAfYa44ZXQUTOwRwPU0QvgU+V+OSajl/59Xg==} @@ -5585,6 +5838,9 @@ packages: resolution: {integrity: sha512-FoqMu0NCGBLCcAkS1qA+XJIQTR6/JHfQXl+uGteNCQ76T91DMUjPa9xfmeqMY3z80nLSg9yQmNjK0Px6RWsH/A==} engines: {node: '>=18'} + sisteransi@1.0.5: + resolution: {integrity: sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==} + slash@3.0.0: resolution: {integrity: sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==} engines: {node: '>=8'} @@ -5627,6 +5883,15 @@ packages: std-env@3.9.0: resolution: {integrity: sha512-UGvjygr6F6tpH7o2qyqR6QYpwraIjKSdtzyBdyytFOHmPZY917kwdwLG0RbOjWOnKmnm3PeHjaoLLMie7kPLQw==} + storybook@9.0.8: + resolution: {integrity: sha512-GlOB3HAtzRYc237+o46nnETNkc2Qckh3UrIJ1rJyAzagIlPWau/jTxjSz76sqRODEnt01m8CyIkw3PGv0q1UpQ==} + hasBin: true + peerDependencies: + prettier: ^2 || ^3 + peerDependenciesMeta: + prettier: + optional: true + string-env-interpolation@1.0.1: resolution: {integrity: sha512-78lwMoCcn0nNu8LszbP1UA7g55OeE4v7rCeWnM5B453rnNr4aq+5it3FEYtZrSEiMvHZOZ9Jlqb0OD0M2VInqg==} @@ -5685,6 +5950,12 @@ packages: resolution: {integrity: sha512-oejfWV7//gqgyFDe09qyInaSKBYCjfJ2xTgZS8oWyYTmpy4Eyi4s0Rh9IJbSHxtlAjcmWpIGKiKwVb6cjxgtfw==} hasBin: true + svelte-ast-print@0.4.2: + resolution: {integrity: sha512-hRHHufbJoArFmDYQKCpCvc0xUuIEfwYksvyLYEQyH+1xb5LD5sM/IthfooCdXZQtOIqXz6xm7NmaqdfwG4kh6w==} + engines: {node: '>=18'} + peerDependencies: + svelte: ^5.0.0 + svelte-check@4.1.4: resolution: {integrity: sha512-v0j7yLbT29MezzaQJPEDwksybTE2Ups9rUxEXy92T06TiA0cbqcO8wAOwNUVkFW6B0hsYHA+oAX3BS8b/2oHtw==} engines: {node: '>= 18.0.0'} @@ -5798,6 +6069,12 @@ packages: peerDependencies: svelte: ^3.56.0 || ^4.0.0 || ^5.0.0 + svelte2tsx@0.7.39: + resolution: {integrity: sha512-NX8a7eSqF1hr6WKArvXr7TV7DeE+y0kDFD7L5JP7TWqlwFidzGKaG415p992MHREiiEWOv2xIWXJ+mlONofs0A==} + peerDependencies: + svelte: ^3.55 || ^4.0.0-next.0 || ^4.0 || ^5.0.0-next.0 + typescript: ^4.9.4 || ^5.0.0 + svelte@4.2.19: resolution: {integrity: sha512-IY1rnGr6izd10B0A8LqsBfmlT5OILVuZ7XsI0vdGPEvuonFV7NYEUK4dAkm9Zg2q0Um92kYjTpS1CAP3Nh/KWw==} engines: {node: '>=16'} @@ -5868,6 +6145,9 @@ packages: resolution: {integrity: sha512-YBGpG4bWsHoPvofT6y/5iqulfXIiIErl5B0LdtHT1mGXDFTAhhRrbUpTvBgYbovr+3cKblya2WAOcpoy90XguA==} engines: {node: '>=16'} + tiny-invariant@1.3.3: + resolution: {integrity: sha512-+FbBPE1o9QAYvviau/qC5SE3caw21q3xkvWKBtja5vgqOWIHHJ3ioaq1VPfn/Szqctz2bU/oYeKd9/z5BL+PVg==} + tinybench@2.9.0: resolution: {integrity: sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg==} @@ -5878,8 +6158,12 @@ packages: resolution: {integrity: sha512-Zc+8eJlFMvgatPZTl6A9L/yht8QqdmUNtURHaKZLmKBE12hNPSrqNkUp2cs3M/UKmNVVAMFQYSjYIVHDjW5zew==} engines: {node: '>=12.0.0'} - tinypool@1.0.2: - resolution: {integrity: sha512-al6n+QEANGFOMf/dmUMsuS5/r9B06uwlyNjZZql/zv8J7ybHCgoihBNORZCY2mzUuAnomQa2JdhyHKzZxPCrFA==} + tinyglobby@0.2.14: + resolution: {integrity: sha512-tX5e7OM1HnYr2+a2C/4V0htOcSQcoSTH9KgJnVvNm5zm/cyEWKJ7j7YutsH9CxMdtOkkLFy2AHrMci9IM8IPZQ==} + engines: {node: '>=12.0.0'} + + tinypool@1.1.0: + resolution: {integrity: sha512-7CotroY9a8DKsKprEy/a14aCCm8jYVmR7aFy4fpkZM8sdpNJbKkixuNjgM50yCmip2ezc8z4N7k3oe2+rfRJCQ==} engines: {node: ^18.0.0 || >=20.0.0} tinyrainbow@2.0.0: @@ -5890,6 +6174,10 @@ packages: resolution: {integrity: sha512-n1cw8k1k0x4pgA2+9XrOkFydTerNcJ1zWCO5Nn9scWHTD+5tp8dghT2x1uduQePZTZgd3Tupf+x9BxJjeJi77Q==} engines: {node: '>=14.0.0'} + tinyspy@4.0.3: + resolution: {integrity: sha512-t2T/WLB2WRgZ9EpE4jgPJ9w+i66UZfDc8wHh0xrwiRNN+UwH98GIJkTeZqX9rg0i0ptwzqW+uYeIF0T4F8LR7A==} + engines: {node: '>=14.0.0'} + title-case@3.0.3: resolution: {integrity: sha512-e1zGYRvbffpcHIrnuqT0Dh+gEJtDaxDSoG4JAIpq4oDFyooziLBIiYQv0GBT4FUAnUop5uZ1hiIAj7oAF6sOCA==} @@ -5939,6 +6227,10 @@ packages: peerDependencies: typescript: '>=4.8.4' + ts-dedent@2.2.0: + resolution: {integrity: sha512-q5W7tVM71e2xjHZTlgfTDoPF/SmqKG5hddq9SzR49CH2hayqRKJtQ4mtRlSxKaJlR/+9rEM+mnBHf7I2/BQcpQ==} + engines: {node: '>=6.10'} + ts-interface-checker@0.1.13: resolution: {integrity: sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA==} @@ -5978,6 +6270,10 @@ packages: resolution: {integrity: sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==} engines: {node: '>=10'} + type-fest@2.19.0: + resolution: {integrity: sha512-RAH822pAdBgcNMAfWnCBU3CFZcfZ/i1eZjwFU/dsLKumyuuP3niueg2UAukXYF0E2AAoc82ZSSf9J0WQBinzHA==} + engines: {node: '>=12.20'} + type-fest@4.34.1: resolution: {integrity: sha512-6kSc32kT0rbwxD6QL1CYe8IqdzN/J/ILMrNK+HMQCKH3insCDRY/3ITb0vcBss0a3t72fzh2YSzj8ko1HgwT3g==} engines: {node: '>=16'} @@ -6042,10 +6338,18 @@ packages: resolution: {integrity: sha512-CJ1QgKmNg3CwvAv/kOFmtnEN05f0D/cn9QntgNOQlQF9dgvVTHj3t+8JPdjqawCHk7V/KA+fbUqzZ9XWhcqPUg==} engines: {node: '>= 4.0.0'} + universalify@2.0.1: + resolution: {integrity: sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==} + engines: {node: '>= 10.0.0'} + unixify@1.0.0: resolution: {integrity: sha512-6bc58dPYhCMHHuwxldQxO3RRNZ4eCogZ/st++0+fcC1nr0jiGUtAdBJ2qzmLQWSxbtz42pWt4QQMiZ9HvZf5cg==} engines: {node: '>=0.10.0'} + unplugin@1.16.1: + resolution: {integrity: sha512-4/u/j4FrCKdi17jaxuJA0jClGxB1AvU2hw/IuayPc4ay1XGaJs/rbb4v5WKwAjNifjmXK9PIFyuPiaK8azyR9w==} + engines: {node: '>=14.0.0'} + unraw@3.0.0: resolution: {integrity: sha512-08/DA66UF65OlpUDIQtbJyrqTR0jTAlJ+jsnkQ4jxR7+K5g5YG1APZKQSMCE1vqqmD+2pv6+IdEjmopFatacvg==} @@ -6116,8 +6420,8 @@ packages: vue: optional: true - vite-node@3.0.5: - resolution: {integrity: sha512-02JEJl7SbtwSDJdYS537nU6l+ktdvcREfLksk/NDAqtdKWGqHl+joXzEubHROmS3E6pip+Xgu2tFezMu75jH7A==} + vite-node@3.2.2: + resolution: {integrity: sha512-Xj/jovjZvDXOq2FgLXu8NsY4uHUMWtzVmMC2LkCu9HWdr9Qu1Is5sanX3Z4jOFKdohfaWDnEJWp9pRP0vVpAcA==} engines: {node: ^18.0.0 || ^20.0.0 || >=22.0.0} hasBin: true @@ -6189,16 +6493,24 @@ packages: vite: optional: true - vitest@3.0.5: - resolution: {integrity: sha512-4dof+HvqONw9bvsYxtkfUp2uHsTN9bV2CZIi1pWgoFpL1Lld8LA1ka9q/ONSsoScAKG7NVGf2stJTI7XRkXb2Q==} + vitest-browser-svelte@0.1.0: + resolution: {integrity: sha512-YB6ZUZZQNqU1T9NzvTEDpwpPv35Ng1NZMPBh81zDrLEdOgROGE6nJb79NWb1Eu/a8VkHifqArpOZfJfALge6xQ==} + engines: {node: ^18.0.0 || >=20.0.0} + peerDependencies: + '@vitest/browser': ^2.1.0 || ^3.0.0-0 + svelte: '>3.0.0' + vitest: ^2.1.0 || ^3.0.0-0 + + vitest@3.2.2: + resolution: {integrity: sha512-fyNn/Rp016Bt5qvY0OQvIUCwW2vnaEBLxP42PmKbNIoasSYjML+8xyeADOPvBe+Xfl/ubIw4og7Lt9jflRsCNw==} engines: {node: ^18.0.0 || ^20.0.0 || >=22.0.0} hasBin: true peerDependencies: '@edge-runtime/vm': '*' '@types/debug': ^4.1.12 '@types/node': ^18.0.0 || ^20.0.0 || >=22.0.0 - '@vitest/browser': 3.0.5 - '@vitest/ui': 3.0.5 + '@vitest/browser': 3.2.2 + '@vitest/ui': 3.2.2 happy-dom: '*' jsdom: '*' peerDependenciesMeta: @@ -6241,6 +6553,9 @@ packages: resolution: {integrity: sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g==} engines: {node: '>=12'} + webpack-virtual-modules@0.6.2: + resolution: {integrity: sha512-66/V2i5hQanC51vBQKPH4aI8NMAcBW59FVBs+rC7eGHupMyfn34q7rZIE+ETlJ+XTevqfUhVVBgSUNSW2flEUQ==} + whatwg-mimetype@3.0.0: resolution: {integrity: sha512-nt+N2dzIutVRxARx1nghPKGv1xHikU7HKdfafKkLNLindmPU/ch3U31NOCGGA/dmPcmb1VlofO0vnKAcsm0o/Q==} engines: {node: '>=12'} @@ -6321,6 +6636,18 @@ packages: utf-8-validate: optional: true + ws@8.18.2: + resolution: {integrity: sha512-DMricUmwGZUVr++AEAe2uiVM7UoO9MAVZMDu05UQOaUII0lp+zOzLLU4Xqh/JvTqklB1T4uELaaPBKyjE1r4fQ==} + engines: {node: '>=10.0.0'} + peerDependencies: + bufferutil: ^4.0.1 + utf-8-validate: '>=5.0.2' + peerDependenciesMeta: + bufferutil: + optional: true + utf-8-validate: + optional: true + xtend@4.0.2: resolution: {integrity: sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==} engines: {node: '>=0.4'} @@ -6635,6 +6962,18 @@ snapshots: '@babel/helper-string-parser': 7.25.9 '@babel/helper-validator-identifier': 7.25.9 + '@chromatic-com/storybook@4.0.0(storybook@9.0.8(@testing-library/dom@10.4.0)(prettier@3.5.0))': + dependencies: + '@neoconfetti/react': 1.0.0 + chromatic: 12.1.0 + filesize: 10.1.6 + jsonfile: 6.1.0 + storybook: 9.0.8(@testing-library/dom@10.4.0)(prettier@3.5.0) + strip-ansi: 7.1.0 + transitivePeerDependencies: + - '@chromatic-com/cypress' + - '@chromatic-com/playwright' + '@colors/colors@1.6.0': {} '@dabh/diagnostics@2.0.3': @@ -7538,7 +7877,7 @@ snapshots: '@jest/schemas': 29.6.3 '@types/istanbul-lib-coverage': 2.0.6 '@types/istanbul-reports': 3.0.4 - '@types/node': 22.15.3 + '@types/node': 20.17.32 '@types/yargs': 17.0.33 chalk: 4.1.2 @@ -7656,17 +7995,23 @@ snapshots: '@messageformat/parser': 5.1.1 js-sha256: 0.10.1 - '@lingui/vite-plugin@5.2.0(typescript@5.7.3)(vite@6.1.0(@types/node@22.15.3)(jiti@2.4.2)(yaml@2.7.1))': + '@lingui/vite-plugin@5.2.0(typescript@5.7.3)(vite@6.1.0(@types/node@20.17.32)(jiti@2.4.2)(yaml@2.7.1))': dependencies: '@lingui/cli': 5.2.0(typescript@5.7.3) '@lingui/conf': 5.2.0(typescript@5.7.3) - vite: 6.1.0(@types/node@22.15.3)(jiti@2.4.2)(yaml@2.7.1) + vite: 6.1.0(@types/node@20.17.32)(jiti@2.4.2)(yaml@2.7.1) transitivePeerDependencies: - supports-color - typescript '@mdi/js@7.4.47': {} + '@mdx-js/react@3.1.0(@types/react@19.1.6)(react@19.1.0)': + dependencies: + '@types/mdx': 2.0.13 + '@types/react': 19.1.6 + react: 19.1.0 + '@messageformat/parser@5.1.1': dependencies: moo: 0.5.2 @@ -7685,6 +8030,8 @@ snapshots: - encoding - utf-8-validate + '@neoconfetti/react@1.0.0': {} + '@nodelib/fs.scandir@2.1.5': dependencies: '@nodelib/fs.stat': 2.0.5 @@ -8559,9 +8906,9 @@ snapshots: '@pkgjs/parseargs@0.11.0': optional: true - '@playwright/test@1.50.1': + '@playwright/test@1.52.0': dependencies: - playwright: 1.50.1 + playwright: 1.52.0 '@polka/url@1.0.0-next.29': {} @@ -8715,6 +9062,105 @@ snapshots: '@sinclair/typebox@0.27.8': {} + '@storybook/addon-a11y@9.0.8(storybook@9.0.8(@testing-library/dom@10.4.0)(prettier@3.5.0))': + dependencies: + '@storybook/global': 5.0.0 + axe-core: 4.10.3 + storybook: 9.0.8(@testing-library/dom@10.4.0)(prettier@3.5.0) + + '@storybook/addon-docs@9.0.8(@types/react@19.1.6)(storybook@9.0.8(@testing-library/dom@10.4.0)(prettier@3.5.0))': + dependencies: + '@mdx-js/react': 3.1.0(@types/react@19.1.6)(react@19.1.0) + '@storybook/csf-plugin': 9.0.8(storybook@9.0.8(@testing-library/dom@10.4.0)(prettier@3.5.0)) + '@storybook/icons': 1.4.0(react-dom@19.1.0(react@19.1.0))(react@19.1.0) + '@storybook/react-dom-shim': 9.0.8(react-dom@19.1.0(react@19.1.0))(react@19.1.0)(storybook@9.0.8(@testing-library/dom@10.4.0)(prettier@3.5.0)) + react: 19.1.0 + react-dom: 19.1.0(react@19.1.0) + storybook: 9.0.8(@testing-library/dom@10.4.0)(prettier@3.5.0) + ts-dedent: 2.2.0 + transitivePeerDependencies: + - '@types/react' + + '@storybook/addon-svelte-csf@5.0.3(@storybook/svelte@9.0.8(storybook@9.0.8(@testing-library/dom@10.4.0)(prettier@3.5.0))(svelte@5.28.2))(@sveltejs/vite-plugin-svelte@5.0.3(svelte@5.28.2)(vite@6.1.0(@types/node@20.17.32)(jiti@2.4.2)(yaml@2.7.1)))(babel-plugin-macros@3.1.0)(storybook@9.0.8(@testing-library/dom@10.4.0)(prettier@3.5.0))(svelte@5.28.2)(vite@6.1.0(@types/node@20.17.32)(jiti@2.4.2)(yaml@2.7.1))': + dependencies: + '@storybook/csf': 0.1.13 + '@storybook/svelte': 9.0.8(storybook@9.0.8(@testing-library/dom@10.4.0)(prettier@3.5.0))(svelte@5.28.2) + '@sveltejs/vite-plugin-svelte': 5.0.3(svelte@5.28.2)(vite@6.1.0(@types/node@20.17.32)(jiti@2.4.2)(yaml@2.7.1)) + dedent: 1.6.0(babel-plugin-macros@3.1.0) + es-toolkit: 1.39.0 + esrap: 1.4.6 + magic-string: 0.30.17 + storybook: 9.0.8(@testing-library/dom@10.4.0)(prettier@3.5.0) + svelte: 5.28.2 + svelte-ast-print: 0.4.2(svelte@5.28.2) + vite: 6.1.0(@types/node@20.17.32)(jiti@2.4.2)(yaml@2.7.1) + zimmerframe: 1.1.2 + transitivePeerDependencies: + - babel-plugin-macros + + '@storybook/addon-vitest@9.0.8(@vitest/browser@3.2.2)(@vitest/runner@3.2.2)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)(storybook@9.0.8(@testing-library/dom@10.4.0)(prettier@3.5.0))(vitest@3.2.2)': + dependencies: + '@storybook/global': 5.0.0 + '@storybook/icons': 1.4.0(react-dom@19.1.0(react@19.1.0))(react@19.1.0) + prompts: 2.4.2 + storybook: 9.0.8(@testing-library/dom@10.4.0)(prettier@3.5.0) + ts-dedent: 2.2.0 + optionalDependencies: + '@vitest/browser': 3.2.2(playwright@1.52.0)(vite@6.1.0(@types/node@20.17.32)(jiti@2.4.2)(yaml@2.7.1))(vitest@3.2.2) + '@vitest/runner': 3.2.2 + vitest: 3.2.2(@types/debug@4.1.12)(@types/node@20.17.32)(@vitest/browser@3.2.2)(@vitest/ui@3.2.2)(happy-dom@17.1.0)(jiti@2.4.2)(yaml@2.7.1) + transitivePeerDependencies: + - react + - react-dom + + '@storybook/builder-vite@9.0.8(storybook@9.0.8(@testing-library/dom@10.4.0)(prettier@3.5.0))(vite@6.1.0(@types/node@20.17.32)(jiti@2.4.2)(yaml@2.7.1))': + dependencies: + '@storybook/csf-plugin': 9.0.8(storybook@9.0.8(@testing-library/dom@10.4.0)(prettier@3.5.0)) + storybook: 9.0.8(@testing-library/dom@10.4.0)(prettier@3.5.0) + ts-dedent: 2.2.0 + vite: 6.1.0(@types/node@20.17.32)(jiti@2.4.2)(yaml@2.7.1) + + '@storybook/csf-plugin@9.0.8(storybook@9.0.8(@testing-library/dom@10.4.0)(prettier@3.5.0))': + dependencies: + storybook: 9.0.8(@testing-library/dom@10.4.0)(prettier@3.5.0) + unplugin: 1.16.1 + + '@storybook/csf@0.1.13': + dependencies: + type-fest: 2.19.0 + + '@storybook/global@5.0.0': {} + + '@storybook/icons@1.4.0(react-dom@19.1.0(react@19.1.0))(react@19.1.0)': + dependencies: + react: 19.1.0 + react-dom: 19.1.0(react@19.1.0) + + '@storybook/react-dom-shim@9.0.8(react-dom@19.1.0(react@19.1.0))(react@19.1.0)(storybook@9.0.8(@testing-library/dom@10.4.0)(prettier@3.5.0))': + dependencies: + react: 19.1.0 + react-dom: 19.1.0(react@19.1.0) + storybook: 9.0.8(@testing-library/dom@10.4.0)(prettier@3.5.0) + + '@storybook/svelte-vite@9.0.8(@sveltejs/vite-plugin-svelte@5.0.3(svelte@5.28.2)(vite@6.1.0(@types/node@20.17.32)(jiti@2.4.2)(yaml@2.7.1)))(storybook@9.0.8(@testing-library/dom@10.4.0)(prettier@3.5.0))(svelte@5.28.2)(vite@6.1.0(@types/node@20.17.32)(jiti@2.4.2)(yaml@2.7.1))': + dependencies: + '@storybook/builder-vite': 9.0.8(storybook@9.0.8(@testing-library/dom@10.4.0)(prettier@3.5.0))(vite@6.1.0(@types/node@20.17.32)(jiti@2.4.2)(yaml@2.7.1)) + '@storybook/svelte': 9.0.8(storybook@9.0.8(@testing-library/dom@10.4.0)(prettier@3.5.0))(svelte@5.28.2) + '@sveltejs/vite-plugin-svelte': 5.0.3(svelte@5.28.2)(vite@6.1.0(@types/node@20.17.32)(jiti@2.4.2)(yaml@2.7.1)) + magic-string: 0.30.17 + storybook: 9.0.8(@testing-library/dom@10.4.0)(prettier@3.5.0) + svelte: 5.28.2 + svelte2tsx: 0.7.39(svelte@5.28.2)(typescript@5.7.3) + typescript: 5.7.3 + vite: 6.1.0(@types/node@20.17.32)(jiti@2.4.2)(yaml@2.7.1) + + '@storybook/svelte@9.0.8(storybook@9.0.8(@testing-library/dom@10.4.0)(prettier@3.5.0))(svelte@5.28.2)': + dependencies: + storybook: 9.0.8(@testing-library/dom@10.4.0)(prettier@3.5.0) + svelte: 5.28.2 + ts-dedent: 2.2.0 + type-fest: 2.19.0 + '@stylistic/eslint-plugin@2.13.0(eslint@9.20.1(jiti@2.4.2))(typescript@5.7.3)': dependencies: '@typescript-eslint/utils': 8.31.0(eslint@9.20.1(jiti@2.4.2))(typescript@5.7.3) @@ -8774,15 +9220,6 @@ snapshots: transitivePeerDependencies: - supports-color - '@sveltejs/vite-plugin-svelte-inspector@4.0.1(@sveltejs/vite-plugin-svelte@5.0.3(svelte@5.28.2)(vite@6.1.0(@types/node@22.15.3)(jiti@2.4.2)(yaml@2.7.1)))(svelte@5.28.2)(vite@6.1.0(@types/node@22.15.3)(jiti@2.4.2)(yaml@2.7.1))': - dependencies: - '@sveltejs/vite-plugin-svelte': 5.0.3(svelte@5.28.2)(vite@6.1.0(@types/node@22.15.3)(jiti@2.4.2)(yaml@2.7.1)) - debug: 4.4.0 - svelte: 5.28.2 - vite: 6.1.0(@types/node@22.15.3)(jiti@2.4.2)(yaml@2.7.1) - transitivePeerDependencies: - - supports-color - '@sveltejs/vite-plugin-svelte@3.1.2(svelte@5.28.2)(vite@6.1.0(@types/node@20.17.32)(jiti@2.4.2)(yaml@2.7.1))': dependencies: '@sveltejs/vite-plugin-svelte-inspector': 2.1.0(@sveltejs/vite-plugin-svelte@3.1.2(svelte@5.28.2)(vite@6.1.0(@types/node@20.17.32)(jiti@2.4.2)(yaml@2.7.1)))(svelte@5.28.2)(vite@6.1.0(@types/node@20.17.32)(jiti@2.4.2)(yaml@2.7.1)) @@ -8810,19 +9247,6 @@ snapshots: transitivePeerDependencies: - supports-color - '@sveltejs/vite-plugin-svelte@5.0.3(svelte@5.28.2)(vite@6.1.0(@types/node@22.15.3)(jiti@2.4.2)(yaml@2.7.1))': - dependencies: - '@sveltejs/vite-plugin-svelte-inspector': 4.0.1(@sveltejs/vite-plugin-svelte@5.0.3(svelte@5.28.2)(vite@6.1.0(@types/node@22.15.3)(jiti@2.4.2)(yaml@2.7.1)))(svelte@5.28.2)(vite@6.1.0(@types/node@22.15.3)(jiti@2.4.2)(yaml@2.7.1)) - debug: 4.4.0 - deepmerge: 4.3.1 - kleur: 4.1.5 - magic-string: 0.30.17 - svelte: 5.28.2 - vite: 6.1.0(@types/node@22.15.3)(jiti@2.4.2)(yaml@2.7.1) - vitefu: 1.0.6(vite@6.1.0(@types/node@22.15.3)(jiti@2.4.2)(yaml@2.7.1)) - transitivePeerDependencies: - - supports-color - '@swc/helpers@0.5.15': dependencies: tslib: 2.8.1 @@ -8860,14 +9284,6 @@ snapshots: lodash: 4.17.21 redent: 3.0.0 - '@testing-library/svelte@5.2.7(svelte@5.28.2)(vite@6.1.0(@types/node@22.15.3)(jiti@2.4.2)(yaml@2.7.1))(vitest@3.0.5)': - dependencies: - '@testing-library/dom': 10.4.0 - svelte: 5.28.2 - optionalDependencies: - vite: 6.1.0(@types/node@22.15.3)(jiti@2.4.2)(yaml@2.7.1) - vitest: 3.0.5(@types/debug@4.1.12)(@types/node@22.15.3)(@vitest/ui@3.0.5)(happy-dom@17.1.0)(jiti@2.4.2)(yaml@2.7.1) - '@testing-library/user-event@14.6.1(@testing-library/dom@10.4.0)': dependencies: '@testing-library/dom': 10.4.0 @@ -8891,6 +9307,10 @@ snapshots: dependencies: '@types/node': 20.17.32 + '@types/chai@5.2.2': + dependencies: + '@types/deep-eql': 4.0.2 + '@types/connect@3.4.36': dependencies: '@types/node': 20.17.32 @@ -8914,6 +9334,8 @@ snapshots: dependencies: '@types/ms': 2.1.0 + '@types/deep-eql@4.0.2': {} + '@types/estree@0.0.39': {} '@types/estree@1.0.7': {} @@ -8982,6 +9404,8 @@ snapshots: dependencies: '@types/unist': 3.0.3 + '@types/mdx@2.0.13': {} + '@types/memcached@2.2.10': dependencies: '@types/node': 20.17.32 @@ -9011,6 +9435,7 @@ snapshots: '@types/node@22.15.3': dependencies: undici-types: 6.21.0 + optional: true '@types/parse-json@4.0.2': {} @@ -9028,9 +9453,13 @@ snapshots: '@types/range-parser@1.2.7': {} + '@types/react@19.1.6': + dependencies: + csstype: 3.1.3 + '@types/resolve@1.17.1': dependencies: - '@types/node': 22.15.3 + '@types/node': 20.17.32 '@types/resolve@1.20.2': {} @@ -9224,66 +9653,95 @@ snapshots: dependencies: vite: 6.1.0(@types/node@22.15.3)(jiti@2.4.2)(yaml@2.7.1) - '@vitest/expect@3.0.5': + '@vitest/browser@3.2.2(playwright@1.52.0)(vite@6.1.0(@types/node@20.17.32)(jiti@2.4.2)(yaml@2.7.1))(vitest@3.2.2)': + dependencies: + '@testing-library/dom': 10.4.0 + '@testing-library/user-event': 14.6.1(@testing-library/dom@10.4.0) + '@vitest/mocker': 3.2.2(vite@6.1.0(@types/node@20.17.32)(jiti@2.4.2)(yaml@2.7.1)) + '@vitest/utils': 3.2.2 + magic-string: 0.30.17 + sirv: 3.0.1 + tinyrainbow: 2.0.0 + vitest: 3.2.2(@types/debug@4.1.12)(@types/node@20.17.32)(@vitest/browser@3.2.2)(@vitest/ui@3.2.2)(happy-dom@17.1.0)(jiti@2.4.2)(yaml@2.7.1) + ws: 8.18.2 + optionalDependencies: + playwright: 1.52.0 + transitivePeerDependencies: + - bufferutil + - msw + - utf-8-validate + - vite + + '@vitest/expect@3.0.9': dependencies: - '@vitest/spy': 3.0.5 - '@vitest/utils': 3.0.5 + '@vitest/spy': 3.0.9 + '@vitest/utils': 3.0.9 chai: 5.2.0 tinyrainbow: 2.0.0 - '@vitest/mocker@3.0.5(vite@6.1.0(@types/node@20.17.32)(jiti@2.4.2)(yaml@2.7.1))': + '@vitest/expect@3.2.2': dependencies: - '@vitest/spy': 3.0.5 - estree-walker: 3.0.3 - magic-string: 0.30.17 - optionalDependencies: - vite: 6.1.0(@types/node@20.17.32)(jiti@2.4.2)(yaml@2.7.1) + '@types/chai': 5.2.2 + '@vitest/spy': 3.2.2 + '@vitest/utils': 3.2.2 + chai: 5.2.0 + tinyrainbow: 2.0.0 - '@vitest/mocker@3.0.5(vite@6.1.0(@types/node@22.15.3)(jiti@2.4.2)(yaml@2.7.1))': + '@vitest/mocker@3.2.2(vite@6.1.0(@types/node@20.17.32)(jiti@2.4.2)(yaml@2.7.1))': dependencies: - '@vitest/spy': 3.0.5 + '@vitest/spy': 3.2.2 estree-walker: 3.0.3 magic-string: 0.30.17 optionalDependencies: - vite: 6.1.0(@types/node@22.15.3)(jiti@2.4.2)(yaml@2.7.1) + vite: 6.1.0(@types/node@20.17.32)(jiti@2.4.2)(yaml@2.7.1) - '@vitest/pretty-format@3.0.5': + '@vitest/pretty-format@3.0.9': dependencies: tinyrainbow: 2.0.0 - '@vitest/pretty-format@3.1.2': + '@vitest/pretty-format@3.2.2': dependencies: tinyrainbow: 2.0.0 - '@vitest/runner@3.0.5': + '@vitest/runner@3.2.2': dependencies: - '@vitest/utils': 3.0.5 + '@vitest/utils': 3.2.2 pathe: 2.0.3 - '@vitest/snapshot@3.0.5': + '@vitest/snapshot@3.2.2': dependencies: - '@vitest/pretty-format': 3.0.5 + '@vitest/pretty-format': 3.2.2 magic-string: 0.30.17 pathe: 2.0.3 - '@vitest/spy@3.0.5': + '@vitest/spy@3.0.9': dependencies: tinyspy: 3.0.2 - '@vitest/ui@3.0.5(vitest@3.0.5)': + '@vitest/spy@3.2.2': + dependencies: + tinyspy: 4.0.3 + + '@vitest/ui@3.2.2(vitest@3.2.2)': dependencies: - '@vitest/utils': 3.0.5 + '@vitest/utils': 3.2.2 fflate: 0.8.2 flatted: 3.3.3 pathe: 2.0.3 sirv: 3.0.1 - tinyglobby: 0.2.10 + tinyglobby: 0.2.14 tinyrainbow: 2.0.0 - vitest: 3.0.5(@types/debug@4.1.12)(@types/node@20.17.32)(@vitest/ui@3.0.5)(happy-dom@17.1.0)(jiti@2.4.2)(yaml@2.7.1) + vitest: 3.2.2(@types/debug@4.1.12)(@types/node@20.17.32)(@vitest/browser@3.2.2)(@vitest/ui@3.2.2)(happy-dom@17.1.0)(jiti@2.4.2)(yaml@2.7.1) - '@vitest/utils@3.0.5': + '@vitest/utils@3.0.9': dependencies: - '@vitest/pretty-format': 3.0.5 + '@vitest/pretty-format': 3.0.9 + loupe: 3.1.3 + tinyrainbow: 2.0.0 + + '@vitest/utils@3.2.2': + dependencies: + '@vitest/pretty-format': 3.2.2 loupe: 3.1.3 tinyrainbow: 2.0.0 @@ -9392,6 +9850,10 @@ snapshots: assertion-error@2.0.1: {} + ast-types@0.16.1: + dependencies: + tslib: 2.8.1 + astral-regex@2.0.0: {} async@3.2.6: {} @@ -9422,6 +9884,8 @@ snapshots: postcss: 8.5.2 postcss-value-parser: 4.2.0 + axe-core@4.10.3: {} + axios@1.7.9: dependencies: follow-redirects: 1.15.9(debug@4.4.0) @@ -9458,6 +9922,10 @@ snapshots: base64-js@1.5.1: {} + better-opn@3.0.2: + dependencies: + open: 8.4.2 + bignumber.js@9.3.0: {} binary-extensions@2.3.0: {} @@ -9660,6 +10128,8 @@ snapshots: dependencies: readdirp: 4.1.2 + chromatic@12.1.0: {} + cjs-module-lexer@1.4.3: {} clean-css@4.2.4: @@ -9875,6 +10345,8 @@ snapshots: cssesc@3.0.0: {} + csstype@3.1.3: {} + cuint@0.2.2: {} culori@3.3.0: {} @@ -9938,12 +10410,22 @@ snapshots: dependencies: ms: 2.1.3 + debug@4.4.1: + dependencies: + ms: 2.1.3 + decimal.js@10.5.0: {} decode-named-character-reference@1.1.0: dependencies: character-entities: 2.0.2 + dedent-js@1.0.1: {} + + dedent@1.6.0(babel-plugin-macros@3.1.0): + optionalDependencies: + babel-plugin-macros: 3.1.0 + deep-eql@5.0.2: {} deep-is@0.1.4: {} @@ -10106,6 +10588,15 @@ snapshots: has-tostringtag: 1.0.2 hasown: 2.0.2 + es-toolkit@1.39.0: {} + + esbuild-register@3.6.0(esbuild@0.24.2): + dependencies: + debug: 4.4.0 + esbuild: 0.24.2 + transitivePeerDependencies: + - supports-color + esbuild@0.21.5: optionalDependencies: '@esbuild/aix-ppc64': 0.21.5 @@ -10175,6 +10666,15 @@ snapshots: eslint: 9.20.1(jiti@2.4.2) semver: 7.7.1 + eslint-plugin-storybook@9.0.8(eslint@9.20.1(jiti@2.4.2))(storybook@9.0.8(@testing-library/dom@10.4.0)(prettier@3.5.0))(typescript@5.7.3): + dependencies: + '@typescript-eslint/utils': 8.31.0(eslint@9.20.1(jiti@2.4.2))(typescript@5.7.3) + eslint: 9.20.1(jiti@2.4.2) + storybook: 9.0.8(@testing-library/dom@10.4.0)(prettier@3.5.0) + transitivePeerDependencies: + - supports-color + - typescript + eslint-plugin-svelte@2.46.1(eslint@9.20.1(jiti@2.4.2))(svelte@5.28.2): dependencies: '@eslint-community/eslint-utils': 4.6.1(eslint@9.20.1(jiti@2.4.2)) @@ -10263,10 +10763,17 @@ snapshots: acorn-jsx: 5.3.2(acorn@8.14.1) eslint-visitor-keys: 3.4.3 + esprima@4.0.1: {} + esquery@1.6.0: dependencies: estraverse: 5.3.0 + esrap@1.2.2: + dependencies: + '@jridgewell/sourcemap-codec': 1.5.0 + '@types/estree': 1.0.7 + esrap@1.4.6: dependencies: '@jridgewell/sourcemap-codec': 1.5.0 @@ -10385,6 +10892,8 @@ snapshots: dependencies: flat-cache: 4.0.1 + filesize@10.1.6: {} + fill-range@7.1.1: dependencies: to-regex-range: 5.0.1 @@ -10925,6 +11434,12 @@ snapshots: json5@2.2.3: {} + jsonfile@6.1.0: + dependencies: + universalify: 2.0.1 + optionalDependencies: + graceful-fs: 4.2.11 + juice@10.0.1: dependencies: cheerio: 1.0.0-rc.12 @@ -10949,6 +11464,8 @@ snapshots: dependencies: '@keyv/serialize': 1.0.3 + kleur@3.0.3: {} + kleur@4.1.5: {} klona@2.0.6: {} @@ -12094,11 +12611,11 @@ snapshots: dependencies: find-up: 3.0.0 - playwright-core@1.50.1: {} + playwright-core@1.52.0: {} - playwright@1.50.1: + playwright@1.52.0: dependencies: - playwright-core: 1.50.1 + playwright-core: 1.52.0 optionalDependencies: fsevents: 2.3.2 @@ -12206,6 +12723,11 @@ snapshots: dependencies: asap: 2.0.6 + prompts@2.4.2: + dependencies: + kleur: 3.0.3 + sisteransi: 1.0.5 + proper-lockfile@4.1.2: dependencies: graceful-fs: 4.2.11 @@ -12287,10 +12809,17 @@ snapshots: queue-microtask@1.2.3: {} + react-dom@19.1.0(react@19.1.0): + dependencies: + react: 19.1.0 + scheduler: 0.26.0 + react-is@17.0.2: {} react-is@18.3.1: {} + react@19.1.0: {} + read-cache@1.0.0: dependencies: pify: 2.3.0 @@ -12311,6 +12840,14 @@ snapshots: readdirp@4.1.2: {} + recast@0.23.11: + dependencies: + ast-types: 0.16.1 + esprima: 4.0.1 + source-map: 0.6.1 + tiny-invariant: 1.3.3 + tslib: 2.8.1 + redent@3.0.0: dependencies: indent-string: 4.0.0 @@ -12489,6 +13026,8 @@ snapshots: safer-buffer@2.1.2: {} + scheduler@0.26.0: {} + scuid@1.1.0: {} selderee@0.11.0: @@ -12563,6 +13102,8 @@ snapshots: mrmime: 2.0.1 totalist: 3.0.1 + sisteransi@1.0.5: {} + slash@3.0.0: {} slice-ansi@3.0.0: @@ -12602,6 +13143,27 @@ snapshots: std-env@3.9.0: {} + storybook@9.0.8(@testing-library/dom@10.4.0)(prettier@3.5.0): + dependencies: + '@storybook/global': 5.0.0 + '@testing-library/jest-dom': 6.6.3 + '@testing-library/user-event': 14.6.1(@testing-library/dom@10.4.0) + '@vitest/expect': 3.0.9 + '@vitest/spy': 3.0.9 + better-opn: 3.0.2 + esbuild: 0.24.2 + esbuild-register: 3.6.0(esbuild@0.24.2) + recast: 0.23.11 + semver: 7.7.1 + ws: 8.18.1 + optionalDependencies: + prettier: 3.5.0 + transitivePeerDependencies: + - '@testing-library/dom' + - bufferutil + - supports-color + - utf-8-validate + string-env-interpolation@1.0.1: {} string-width@4.2.3: @@ -12681,6 +13243,12 @@ snapshots: - stylus - sugarss + svelte-ast-print@0.4.2(svelte@5.28.2): + dependencies: + esrap: 1.2.2 + svelte: 5.28.2 + zimmerframe: 1.1.2 + svelte-check@4.1.4(picomatch@4.0.2)(svelte@5.28.2)(typescript@5.7.3): dependencies: '@jridgewell/trace-mapping': 0.3.25 @@ -12832,6 +13400,13 @@ snapshots: - stylus - sugarss + svelte2tsx@0.7.39(svelte@5.28.2)(typescript@5.7.3): + dependencies: + dedent-js: 1.0.1 + pascal-case: 3.1.2 + svelte: 5.28.2 + typescript: 5.7.3 + svelte@4.2.19: dependencies: '@ampproject/remapping': 2.3.0 @@ -12949,6 +13524,8 @@ snapshots: timeout-signal@2.0.0: {} + tiny-invariant@1.3.3: {} + tinybench@2.9.0: {} tinyexec@0.3.2: {} @@ -12958,12 +13535,19 @@ snapshots: fdir: 6.4.4(picomatch@4.0.2) picomatch: 4.0.2 - tinypool@1.0.2: {} + tinyglobby@0.2.14: + dependencies: + fdir: 6.4.4(picomatch@4.0.2) + picomatch: 4.0.2 + + tinypool@1.1.0: {} tinyrainbow@2.0.0: {} tinyspy@3.0.2: {} + tinyspy@4.0.3: {} + title-case@3.0.3: dependencies: tslib: 2.8.1 @@ -13005,6 +13589,8 @@ snapshots: dependencies: typescript: 5.7.3 + ts-dedent@2.2.0: {} + ts-interface-checker@0.1.13: {} ts-log@2.2.7: {} @@ -13042,6 +13628,8 @@ snapshots: type-fest@0.21.3: {} + type-fest@2.19.0: {} + type-fest@4.34.1: {} type-fest@4.40.1: {} @@ -13060,7 +13648,8 @@ snapshots: undici-types@6.19.8: {} - undici-types@6.21.0: {} + undici-types@6.21.0: + optional: true undici@5.29.0: dependencies: @@ -13101,10 +13690,17 @@ snapshots: universalify@0.2.0: {} + universalify@2.0.1: {} + unixify@1.0.0: dependencies: normalize-path: 2.1.1 + unplugin@1.16.1: + dependencies: + acorn: 8.14.1 + webpack-virtual-modules: 0.6.2 + unraw@3.0.0: {} update-browserslist-db@1.1.3(browserslist@4.24.4): @@ -13156,14 +13752,16 @@ snapshots: '@types/unist': 3.0.3 vfile-message: 4.0.2 - virtua@0.41.2(svelte@5.28.2): + virtua@0.41.2(react-dom@19.1.0(react@19.1.0))(react@19.1.0)(svelte@5.28.2): optionalDependencies: + react: 19.1.0 + react-dom: 19.1.0(react@19.1.0) svelte: 5.28.2 - vite-node@3.0.5(@types/node@20.17.32)(jiti@2.4.2)(yaml@2.7.1): + vite-node@3.2.2(@types/node@20.17.32)(jiti@2.4.2)(yaml@2.7.1): dependencies: cac: 6.7.14 - debug: 4.4.0 + debug: 4.4.1 es-module-lexer: 1.7.0 pathe: 2.0.3 vite: 6.1.0(@types/node@20.17.32)(jiti@2.4.2)(yaml@2.7.1) @@ -13181,27 +13779,6 @@ snapshots: - tsx - yaml - vite-node@3.0.5(@types/node@22.15.3)(jiti@2.4.2)(yaml@2.7.1): - dependencies: - cac: 6.7.14 - debug: 4.4.0 - es-module-lexer: 1.7.0 - pathe: 2.0.3 - vite: 6.1.0(@types/node@22.15.3)(jiti@2.4.2)(yaml@2.7.1) - transitivePeerDependencies: - - '@types/node' - - jiti - - less - - lightningcss - - sass - - sass-embedded - - stylus - - sugarss - - supports-color - - terser - - tsx - - yaml - vite-plugin-graphql-codegen@3.5.0(@graphql-codegen/cli@5.0.5(@types/node@20.17.32)(graphql-sock@1.0.1(graphql@16.11.0))(graphql@16.11.0)(typescript@5.7.3))(graphql@16.11.0)(vite@6.1.0(@types/node@20.17.32)(jiti@2.4.2)(yaml@2.7.1)): dependencies: '@graphql-codegen/cli': 5.0.5(@types/node@20.17.32)(graphql-sock@1.0.1(graphql@16.11.0))(graphql@16.11.0)(typescript@5.7.3) @@ -13209,13 +13786,13 @@ snapshots: graphql: 16.11.0 vite: 6.1.0(@types/node@20.17.32)(jiti@2.4.2)(yaml@2.7.1) - vite-plugin-webfont-dl@3.10.4(vite@6.1.0(@types/node@22.15.3)(jiti@2.4.2)(yaml@2.7.1)): + vite-plugin-webfont-dl@3.10.4(vite@6.1.0(@types/node@20.17.32)(jiti@2.4.2)(yaml@2.7.1)): dependencies: axios: 1.7.9 clean-css: 5.3.3 flat-cache: 6.1.7 picocolors: 1.1.1 - vite: 6.1.0(@types/node@22.15.3)(jiti@2.4.2)(yaml@2.7.1) + vite: 6.1.0(@types/node@20.17.32)(jiti@2.4.2)(yaml@2.7.1) transitivePeerDependencies: - debug @@ -13249,77 +13826,42 @@ snapshots: optionalDependencies: vite: 6.1.0(@types/node@20.17.32)(jiti@2.4.2)(yaml@2.7.1) - vitefu@1.0.6(vite@6.1.0(@types/node@22.15.3)(jiti@2.4.2)(yaml@2.7.1)): - optionalDependencies: - vite: 6.1.0(@types/node@22.15.3)(jiti@2.4.2)(yaml@2.7.1) - - vitest@3.0.5(@types/debug@4.1.12)(@types/node@20.17.32)(@vitest/ui@3.0.5)(happy-dom@17.1.0)(jiti@2.4.2)(yaml@2.7.1): + vitest-browser-svelte@0.1.0(@vitest/browser@3.2.2)(svelte@5.28.2)(vitest@3.2.2): dependencies: - '@vitest/expect': 3.0.5 - '@vitest/mocker': 3.0.5(vite@6.1.0(@types/node@20.17.32)(jiti@2.4.2)(yaml@2.7.1)) - '@vitest/pretty-format': 3.1.2 - '@vitest/runner': 3.0.5 - '@vitest/snapshot': 3.0.5 - '@vitest/spy': 3.0.5 - '@vitest/utils': 3.0.5 + '@vitest/browser': 3.2.2(playwright@1.52.0)(vite@6.1.0(@types/node@20.17.32)(jiti@2.4.2)(yaml@2.7.1))(vitest@3.2.2) + svelte: 5.28.2 + vitest: 3.2.2(@types/debug@4.1.12)(@types/node@20.17.32)(@vitest/browser@3.2.2)(@vitest/ui@3.2.2)(happy-dom@17.1.0)(jiti@2.4.2)(yaml@2.7.1) + + vitest@3.2.2(@types/debug@4.1.12)(@types/node@20.17.32)(@vitest/browser@3.2.2)(@vitest/ui@3.2.2)(happy-dom@17.1.0)(jiti@2.4.2)(yaml@2.7.1): + dependencies: + '@types/chai': 5.2.2 + '@vitest/expect': 3.2.2 + '@vitest/mocker': 3.2.2(vite@6.1.0(@types/node@20.17.32)(jiti@2.4.2)(yaml@2.7.1)) + '@vitest/pretty-format': 3.2.2 + '@vitest/runner': 3.2.2 + '@vitest/snapshot': 3.2.2 + '@vitest/spy': 3.2.2 + '@vitest/utils': 3.2.2 chai: 5.2.0 - debug: 4.4.0 + debug: 4.4.1 expect-type: 1.2.1 magic-string: 0.30.17 pathe: 2.0.3 + picomatch: 4.0.2 std-env: 3.9.0 tinybench: 2.9.0 tinyexec: 0.3.2 - tinypool: 1.0.2 + tinyglobby: 0.2.14 + tinypool: 1.1.0 tinyrainbow: 2.0.0 vite: 6.1.0(@types/node@20.17.32)(jiti@2.4.2)(yaml@2.7.1) - vite-node: 3.0.5(@types/node@20.17.32)(jiti@2.4.2)(yaml@2.7.1) + vite-node: 3.2.2(@types/node@20.17.32)(jiti@2.4.2)(yaml@2.7.1) why-is-node-running: 2.3.0 optionalDependencies: '@types/debug': 4.1.12 '@types/node': 20.17.32 - '@vitest/ui': 3.0.5(vitest@3.0.5) - happy-dom: 17.1.0 - transitivePeerDependencies: - - jiti - - less - - lightningcss - - msw - - sass - - sass-embedded - - stylus - - sugarss - - supports-color - - terser - - tsx - - yaml - - vitest@3.0.5(@types/debug@4.1.12)(@types/node@22.15.3)(@vitest/ui@3.0.5)(happy-dom@17.1.0)(jiti@2.4.2)(yaml@2.7.1): - dependencies: - '@vitest/expect': 3.0.5 - '@vitest/mocker': 3.0.5(vite@6.1.0(@types/node@22.15.3)(jiti@2.4.2)(yaml@2.7.1)) - '@vitest/pretty-format': 3.1.2 - '@vitest/runner': 3.0.5 - '@vitest/snapshot': 3.0.5 - '@vitest/spy': 3.0.5 - '@vitest/utils': 3.0.5 - chai: 5.2.0 - debug: 4.4.0 - expect-type: 1.2.1 - magic-string: 0.30.17 - pathe: 2.0.3 - std-env: 3.9.0 - tinybench: 2.9.0 - tinyexec: 0.3.2 - tinypool: 1.0.2 - tinyrainbow: 2.0.0 - vite: 6.1.0(@types/node@22.15.3)(jiti@2.4.2)(yaml@2.7.1) - vite-node: 3.0.5(@types/node@22.15.3)(jiti@2.4.2)(yaml@2.7.1) - why-is-node-running: 2.3.0 - optionalDependencies: - '@types/debug': 4.1.12 - '@types/node': 22.15.3 - '@vitest/ui': 3.0.5(vitest@3.0.5) + '@vitest/browser': 3.2.2(playwright@1.52.0)(vite@6.1.0(@types/node@20.17.32)(jiti@2.4.2)(yaml@2.7.1))(vitest@3.2.2) + '@vitest/ui': 3.2.2(vitest@3.2.2) happy-dom: 17.1.0 transitivePeerDependencies: - jiti @@ -13360,6 +13902,8 @@ snapshots: webidl-conversions@7.0.0: {} + webpack-virtual-modules@0.6.2: {} + whatwg-mimetype@3.0.0: {} whatwg-mimetype@4.0.0: {} @@ -13434,6 +13978,8 @@ snapshots: ws@8.18.1: {} + ws@8.18.2: {} + xtend@4.0.2: {} xxhashjs@0.2.2: diff --git a/frontend/pnpm-workspace.yaml b/frontend/pnpm-workspace.yaml index 109d28515a..40dea5ae6f 100644 --- a/frontend/pnpm-workspace.yaml +++ b/frontend/pnpm-workspace.yaml @@ -13,8 +13,9 @@ catalog: tslib: ^2.6.2 tailwindcss: ^3.4.17 eslint: ^9.20.1 - vitest: ^3.0.5 - "@vitest/ui": ^3.0.5 + vitest: ^3.2.2 + "@vitest/ui": ^3.2.2 + "@vitest/browser": ^3.2.2 svelte-exmarkdown: ^4.0.3 "@typescript-eslint/eslint-plugin": ^8.24.0 "@typescript-eslint/parser": ^8.24.0 @@ -22,5 +23,6 @@ catalog: "svelte-eslint-parser": ^1.0.0-next.0 "@stylistic/eslint-plugin": ^2.12.1 "@vitejs/plugin-basic-ssl": ^1.2.0 - "@playwright/test": ^1.49.1 + playwright: ^1.52.0 + "@playwright/test": ^1.52.0 runed: ^0.27.0 diff --git a/frontend/viewer/.gitignore b/frontend/viewer/.gitignore index cc479eec64..9fd1ce3f27 100644 --- a/frontend/viewer/.gitignore +++ b/frontend/viewer/.gitignore @@ -24,3 +24,6 @@ dist-ssr *.sln *.sw? html-test-results + +*storybook.log +storybook-static diff --git a/frontend/viewer/.storybook/decorators/FWLiteDecorator.svelte b/frontend/viewer/.storybook/decorators/FWLiteDecorator.svelte new file mode 100644 index 0000000000..caaea3cb5a --- /dev/null +++ b/frontend/viewer/.storybook/decorators/FWLiteDecorator.svelte @@ -0,0 +1,87 @@ + + + + + + defaultSize = size}> + {@render children()} + + {#if resizable} + + + + {#if showValue === true || value && showValue !== false} +
+ {#if !hideValue} +
{
+            JSON.stringify(value, null, 2)?.replaceAll(lineSeparator, '\n') ?? 'undefined'}
+            
+ {/if} + hideValue = !hideValue} /> +
+ {/if} +
+ {/if} +
+ +
+ {#if viewPicker} + + {/if} + {#if themePicker} + + {/if} + +
diff --git a/frontend/viewer/.storybook/main.ts b/frontend/viewer/.storybook/main.ts new file mode 100644 index 0000000000..172c78fab3 --- /dev/null +++ b/frontend/viewer/.storybook/main.ts @@ -0,0 +1,20 @@ +import type {StorybookConfig} from '@storybook/svelte-vite'; + +const config: StorybookConfig = { + "stories": [ + "../src/**/*.mdx", + "../src/**/*.stories.@(ts|svelte)" + ], + "addons": [ + "@storybook/addon-svelte-csf", + "@chromatic-com/storybook", + "@storybook/addon-docs", + "@storybook/addon-a11y", + "@storybook/addon-vitest" + ], + "framework": { + "name": "@storybook/svelte-vite", + "options": {} + } +}; +export default config; diff --git a/frontend/viewer/.storybook/preview.ts b/frontend/viewer/.storybook/preview.ts new file mode 100644 index 0000000000..7ea0a9e037 --- /dev/null +++ b/frontend/viewer/.storybook/preview.ts @@ -0,0 +1,48 @@ +import '../src/app.postcss'; + +import FWLiteDecorator, {initSvelteStoryContext} from './decorators/FWLiteDecorator.svelte'; + +import type {Preview} from '@storybook/svelte-vite'; + +const demoIcons = [ + // realistic + 'i-mdi-auto-fix', + 'i-mdi-cloud', + 'i-mdi-pencil-outline', + 'i-mdi-close', + // fun + 'i-mdi-party-popper', + 'i-mdi-cake-variant', + 'i-mdi-guitar-electric', + 'i-mdi-pine-tree', + 'i-mdi-water-polo', +]; + +const preview: Preview = { + argTypesEnhancers: [ + (context) => { + // This is a workaround to make the icon control work with Svelte components + if (context.argTypes.icon) { + context.argTypes.icon.control = {type: 'select', labels: {null: 'None'}}; + context.argTypes.icon.options = [null, ...demoIcons]; + } + return context.argTypes; + } + ], + parameters: { + controls: { + matchers: { + color: /(background|color)$/i, + date: /Date$/i, + }, + }, + }, + // @ts-expect-error Bug in Storybook https://github.com/storybookjs/storybook/issues/29951 + decorators: [(_story, storyContext) => { + // The only way I know how to pass the story context to the decorator + initSvelteStoryContext(storyContext); + return FWLiteDecorator; + }], +}; + +export default preview; diff --git a/frontend/viewer/.storybook/vitest.setup.ts b/frontend/viewer/.storybook/vitest.setup.ts new file mode 100644 index 0000000000..6e2824b408 --- /dev/null +++ b/frontend/viewer/.storybook/vitest.setup.ts @@ -0,0 +1,32 @@ +import * as previewAnnotations from './preview'; + +import {afterAll, beforeAll} from 'vitest'; +import {setProjectAnnotations} from '@storybook/svelte-vite'; + +const annotations = setProjectAnnotations([previewAnnotations]); + +// Run Storybook's beforeAll hook +beforeAll(annotations.beforeAll); + + +const ignoredWarnings = [ + 'ownership_invalid_binding', + 'ownership_invalid_mutation', +]; + +const originalWarn = console.warn.bind(console); + +beforeAll(() => { + console.warn = (...args: any[]) => { + const isIgnoredWarning = args.some(arg => typeof arg === 'string' && ignoredWarnings.some(ignored => arg.includes(ignored))); + if (isIgnoredWarning) { + const outOfOurControl = args.some(arg => typeof arg === 'string' && arg.includes('node_modules')); + if (outOfOurControl) return; // swallow the noise + } + originalWarn(...args); + }; +}); + +afterAll(() => { + console.warn = originalWarn; // Restore the original console.warn +}); diff --git a/frontend/viewer/Taskfile.yml b/frontend/viewer/Taskfile.yml index 12aa559708..25e437ff60 100644 --- a/frontend/viewer/Taskfile.yml +++ b/frontend/viewer/Taskfile.yml @@ -8,6 +8,9 @@ tasks: run-app: interactive: true cmd: pnpm run dev-app + storybook: + interactive: true + cmd: pnpm storybook {{.CLI_ARGS}} web-component: aliases: [ wc ] interactive: true diff --git a/frontend/viewer/eslint.config.js b/frontend/viewer/eslint.config.js index f14c3adaa1..ce16816bae 100644 --- a/frontend/viewer/eslint.config.js +++ b/frontend/viewer/eslint.config.js @@ -1,8 +1,11 @@ +// For more info, see https://github.com/storybookjs/eslint-plugin-storybook#configuration-flat-config-format + import {FlatCompat} from '@eslint/eslintrc'; import {fileURLToPath} from 'url'; import globals from 'globals'; import js from '@eslint/js'; import path from 'path'; +import storybook from "eslint-plugin-storybook"; import svelteParser from 'svelte-eslint-parser'; import tsParser from '@typescript-eslint/parser'; @@ -19,6 +22,7 @@ export default [ '**/*js', '**/generated-types/**', '**/vite.config.*', + '**/.storybook/**', ], }, js.configs.recommended, @@ -77,6 +81,12 @@ export default [ { 'selector': 'import', 'format': ['camelCase', 'PascalCase'], + }, + { + 'selector': 'variable', + 'modifiers': ['destructured'], + 'filter': {'regex': '^Story$', 'match': true}, + 'format': ['PascalCase'], } ], '@stylistic/quotes': ['error', 'single', { 'allowTemplateLiterals': true }], @@ -118,7 +128,12 @@ export default [ parser: tsParser, parserOptions: { projectService: { - allowDefaultProject: ['lingui.config.ts', 'tailwind.config.ts', 'playwright.config.ts'], + allowDefaultProject: [ + 'lingui.config.ts', + 'tailwind.config.ts', + 'playwright.config.ts', + 'vitest.config.ts', + ], }, tsconfigRootDir: __dirname, extraFileExtensions: ['.svelte'], // Yes, TS-Parser, relax when you're fed svelte files @@ -141,4 +156,5 @@ export default [ } }, }, + ...storybook.configs["flat/recommended"], ]; diff --git a/frontend/viewer/package.json b/frontend/viewer/package.json index 7e2252184f..876587e060 100644 --- a/frontend/viewer/package.json +++ b/frontend/viewer/package.json @@ -28,39 +28,50 @@ "test": "vitest run", "test:ui": "vitest --ui", "test:watch": "vitest", + "test:storybook": "vitest --project=storybook", "check": "svelte-check", "lint": "eslint .", "i18n:extract": "lingui extract --clean && lingui extract", - "generate-icon-types": "node ./generate-icon-types.js" + "generate-icon-types": "node ./generate-icon-types.js", + "storybook": "storybook dev -p 6006", + "build-storybook": "storybook build" }, "devDependencies": { "@argos-ci/playwright": "^5.0.4", + "@chromatic-com/storybook": "^4", "@egoist/tailwindcss-icons": "^1.9.0", "@iconify-json/mdi": "^1.1.66", "@lingui/cli": "^5.2.0", "@lingui/format-json": "^5.2.0", "@lingui/vite-plugin": "^5.2.0", "@mdi/js": "^7.4.47", + "playwright": "catalog:", "@playwright/test": "catalog:", + "@storybook/addon-a11y": "^9.0.8", + "@storybook/addon-docs": "^9.0.8", + "@storybook/addon-svelte-csf": "^5.0.3", + "@storybook/addon-vitest": "^9.0.8", + "@storybook/svelte-vite": "^9.0.8", "@stylistic/eslint-plugin": "catalog:", "@sveltejs/vite-plugin-svelte": "catalog:", "@tailwindcss/container-queries": "^0.1.1", "@tailwindcss/typography": "^0.5.16", - "@testing-library/jest-dom": "^6.6.3", - "@testing-library/svelte": "^5.2.6", - "@testing-library/user-event": "^14.5.2", "@tsconfig/svelte": "^5.0.4", + "@types/node": "^20", "@typescript-eslint/eslint-plugin": "catalog:", "@typescript-eslint/parser": "catalog:", + "@vitest/browser": "catalog:", "@vitest/ui": "catalog:", "autoprefixer": "^10.4.20", "bits-ui": "1.4.3", "clsx": "^2.1.1", "eslint": "catalog:", + "eslint-plugin-storybook": "^9.0.8", "eslint-plugin-svelte": "catalog:", "happy-dom": "^17.1.0", "mode-watcher": "^1.0.7", "paneforge": "1.0.0-next.4", + "storybook": "^9.0.8", "svelte": "catalog:", "svelte-check": "catalog:", "svelte-eslint-parser": "catalog:", @@ -75,7 +86,8 @@ "vaul-svelte": "1.0.0-next.6", "vite": "catalog:", "vite-plugin-webfont-dl": "^3.10.4", - "vitest": "catalog:" + "vitest": "catalog:", + "vitest-browser-svelte": "^0.1.0" }, "dependencies": { "@lingui/core": "^5.2.0", diff --git a/frontend/viewer/src/home/HomeView.svelte b/frontend/viewer/src/home/HomeView.svelte index a38285c43e..88a4fec7e5 100644 --- a/frontend/viewer/src/home/HomeView.svelte +++ b/frontend/viewer/src/home/HomeView.svelte @@ -11,6 +11,7 @@ import flexLogo from '$lib/assets/flex-logo.png'; import logoLight from '$lib/assets/logo-light.svg'; import logoDark from '$lib/assets/logo-dark.svg'; + import storybookIcon from '../stories/assets/storybook-icon.svg' import DevContent, {isDev} from '$lib/layout/DevContent.svelte'; import { useFwLiteConfig, @@ -109,6 +110,10 @@

{$t`Dictionaries`}

+ {#if import.meta.env.DEV} +
{:else} -
+
{/if} diff --git a/frontend/viewer/src/lib/components/ui/button/button.svelte b/frontend/viewer/src/lib/components/ui/button/button.svelte index 85318b8c0a..2f4e8de8dd 100644 --- a/frontend/viewer/src/lib/components/ui/button/button.svelte +++ b/frontend/viewer/src/lib/components/ui/button/button.svelte @@ -61,19 +61,23 @@ type = 'button', loading = false, icon = undefined, - iconProps = undefined, + iconProps: nullableIconProps = undefined, children, ...restProps }: ButtonProps = $props(); + + const iconProps = $derived(nullableIconProps && ('icon' in nullableIconProps || 'src' in nullableIconProps) + ? nullableIconProps as IconProps + : icon ? {icon} : undefined); {#snippet content()} - {#if loading || icon} + {#if loading || iconProps} {#if loading} - - {:else if icon} - + + {:else if iconProps} + {/if} {/if} diff --git a/frontend/viewer/src/lib/i18n/LocalizationPicker.svelte b/frontend/viewer/src/lib/i18n/LocalizationPicker.svelte index f76e4c6a7b..f8aa62176c 100644 --- a/frontend/viewer/src/lib/i18n/LocalizationPicker.svelte +++ b/frontend/viewer/src/lib/i18n/LocalizationPicker.svelte @@ -7,7 +7,7 @@ import {onMount} from 'svelte'; import * as DropdownMenu from '$lib/components/ui/dropdown-menu'; import {Button} from '$lib/components/ui/button'; import {Icon} from '$lib/components/ui/icon'; - import {IsMobile} from '$lib/hooks/is-mobile.svelte'; +import {IsMobile} from '$lib/hooks/is-mobile.svelte'; const languages: Record = { 'en': 'English', diff --git a/frontend/viewer/src/stories/assets/storybook-icon.svg b/frontend/viewer/src/stories/assets/storybook-icon.svg new file mode 100644 index 0000000000..fd543a693b --- /dev/null +++ b/frontend/viewer/src/stories/assets/storybook-icon.svg @@ -0,0 +1,18 @@ + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/frontend/viewer/src/stories/decorators/BreakpointMarkers.svelte b/frontend/viewer/src/stories/decorators/BreakpointMarkers.svelte new file mode 100644 index 0000000000..48461c93be --- /dev/null +++ b/frontend/viewer/src/stories/decorators/BreakpointMarkers.svelte @@ -0,0 +1,17 @@ + + + +
@lg
+
@3xl
+ +{@render children?.()} + + diff --git a/frontend/viewer/src/stories/editor/entity-primitives/EntityEditorPrimitiveDecorator.svelte b/frontend/viewer/src/stories/editor/entity-primitives/EntityEditorPrimitiveDecorator.svelte new file mode 100644 index 0000000000..6d7a9c0ea2 --- /dev/null +++ b/frontend/viewer/src/stories/editor/entity-primitives/EntityEditorPrimitiveDecorator.svelte @@ -0,0 +1,15 @@ + + + + + + {@render children()} + + diff --git a/frontend/viewer/src/stories/editor/entity-primitives/entry-editor-primitive.stories.svelte b/frontend/viewer/src/stories/editor/entity-primitives/entry-editor-primitive.stories.svelte new file mode 100644 index 0000000000..1e6eaca41a --- /dev/null +++ b/frontend/viewer/src/stories/editor/entity-primitives/entry-editor-primitive.stories.svelte @@ -0,0 +1,81 @@ + + + EntityEditorPrimitiveDecorator, + ]} + play={async ({ canvasElement, args }) => { + const canvas = within(canvasElement); + const senInput = await canvas.findByLabelText(/(Lexeme form|Word) Sen/); + await expect(senInput).toBeInTheDocument(); + await userEvent.type(senInput, ' new text'); + senInput.blur(); + await tick(); + await expect(args.onchange).toHaveBeenCalledOnce(); + }} +/> + + diff --git a/frontend/viewer/src/stories/editor/fields/FieldDecorator.svelte b/frontend/viewer/src/stories/editor/fields/FieldDecorator.svelte new file mode 100644 index 0000000000..cba45f31c7 --- /dev/null +++ b/frontend/viewer/src/stories/editor/fields/FieldDecorator.svelte @@ -0,0 +1,17 @@ + + + + + + + {@render children()} + + + diff --git a/frontend/viewer/src/stories/editor/fields/MultiStringFieldDecorator.svelte b/frontend/viewer/src/stories/editor/fields/MultiStringFieldDecorator.svelte new file mode 100644 index 0000000000..787824cc09 --- /dev/null +++ b/frontend/viewer/src/stories/editor/fields/MultiStringFieldDecorator.svelte @@ -0,0 +1,9 @@ + + + diff --git a/frontend/viewer/src/stories/editor/fields/WsInputWrapper.svelte b/frontend/viewer/src/stories/editor/fields/WsInputWrapper.svelte new file mode 100644 index 0000000000..e0855b2fc2 --- /dev/null +++ b/frontend/viewer/src/stories/editor/fields/WsInputWrapper.svelte @@ -0,0 +1,15 @@ + + + diff --git a/frontend/viewer/src/stories/editor/fields/multi-select.stories.svelte b/frontend/viewer/src/stories/editor/fields/multi-select.stories.svelte new file mode 100644 index 0000000000..7e2fe3a3d8 --- /dev/null +++ b/frontend/viewer/src/stories/editor/fields/multi-select.stories.svelte @@ -0,0 +1,51 @@ + + + + + + + diff --git a/frontend/viewer/src/stories/editor/fields/multi-ws-input.stories.svelte b/frontend/viewer/src/stories/editor/fields/multi-ws-input.stories.svelte new file mode 100644 index 0000000000..8edac2d46c --- /dev/null +++ b/frontend/viewer/src/stories/editor/fields/multi-ws-input.stories.svelte @@ -0,0 +1,47 @@ + + + MultiStringFieldDecorator, + ]} + play={async ({ canvasElement, args }) => { + const canvas = within(canvasElement); + const porInput = await canvas.findByLabelText('Demo field Por'); + await expect(porInput).toBeInTheDocument(); + await userEvent.type(porInput, ' new text'); + porInput.blur(); + await tick(); + await expect(args.onchange).toHaveBeenCalledOnce(); + }} +/> + + diff --git a/frontend/viewer/src/stories/editor/fields/rich-multi-ws-input.stories.svelte b/frontend/viewer/src/stories/editor/fields/rich-multi-ws-input.stories.svelte new file mode 100644 index 0000000000..f4c23ac191 --- /dev/null +++ b/frontend/viewer/src/stories/editor/fields/rich-multi-ws-input.stories.svelte @@ -0,0 +1,53 @@ + + + MultiStringFieldDecorator, + ]} + play={async ({ canvasElement, args }) => { + const canvas = within(canvasElement); + const porInput = await canvas.findByLabelText('Demo field Por'); + await expect(porInput).toBeInTheDocument(); + porInput.focus(); // Firefox needs this + await userEvent.type(porInput, ' new text'); + porInput.blur(); + await tick(); + await expect(args.onchange).toHaveBeenCalledOnce(); + }} +/> + + diff --git a/frontend/viewer/src/stories/editor/fields/rich-ws-input.stories.svelte b/frontend/viewer/src/stories/editor/fields/rich-ws-input.stories.svelte new file mode 100644 index 0000000000..f4d8756996 --- /dev/null +++ b/frontend/viewer/src/stories/editor/fields/rich-ws-input.stories.svelte @@ -0,0 +1,51 @@ + + + FieldDecorator, + ]} + play={async ({ canvasElement, args }) => { + const canvas = within(canvasElement); + const porInput = await canvas.findByLabelText('Demo field'); + await expect(porInput).toBeInTheDocument(); + porInput.focus(); // Firefox needs this + await userEvent.type(porInput, ' new text'); + porInput.blur(); + await tick(); + await expect(args.onchange).toHaveBeenCalledOnce(); + }} +/> + + diff --git a/frontend/viewer/src/stories/editor/fields/select.stories.svelte b/frontend/viewer/src/stories/editor/fields/select.stories.svelte new file mode 100644 index 0000000000..636859f2cd --- /dev/null +++ b/frontend/viewer/src/stories/editor/fields/select.stories.svelte @@ -0,0 +1,43 @@ + + + diff --git a/frontend/viewer/src/stories/editor/fields/ws-input.stories.svelte b/frontend/viewer/src/stories/editor/fields/ws-input.stories.svelte new file mode 100644 index 0000000000..f6a8d646cd --- /dev/null +++ b/frontend/viewer/src/stories/editor/fields/ws-input.stories.svelte @@ -0,0 +1,45 @@ + + + FieldDecorator, + ]} + play={async ({ canvasElement, args }) => { + const canvas = within(canvasElement); + const porInput = await canvas.findByLabelText('Demo field'); + await expect(porInput).toBeInTheDocument(); + await userEvent.type(porInput, ' new text'); + porInput.blur(); + await tick(); + await expect(args.onchange).toHaveBeenCalledOnce(); + }} +/> + + diff --git a/frontend/viewer/src/stories/editor/misc/entry-picker.stories.svelte b/frontend/viewer/src/stories/editor/misc/entry-picker.stories.svelte new file mode 100644 index 0000000000..e1701b73a1 --- /dev/null +++ b/frontend/viewer/src/stories/editor/misc/entry-picker.stories.svelte @@ -0,0 +1,73 @@ + + + + +
+
+ + +
+ +
+ {#each selectedEntryHistory as selected} +

+ Entry: {writingSystemService?.headword(selected.entry)} + {#if selected.sense} + Sense: {writingSystemService?.firstGloss(selected.sense)} + {/if} +

+ {/each} +
+
+ + + {#snippet template(args)} + + {/snippet} + + + + {#snippet template(args)} + + {/snippet} + + + + {#snippet template(args)} + + {/snippet} + diff --git a/frontend/viewer/src/stories/editor/misc/reorderer.stories.svelte b/frontend/viewer/src/stories/editor/misc/reorderer.stories.svelte new file mode 100644 index 0000000000..6d3e4e9e4f --- /dev/null +++ b/frontend/viewer/src/stories/editor/misc/reorderer.stories.svelte @@ -0,0 +1,52 @@ + + +
+ + + Times 1 + Times 100 + + + +
+ + + {#each items as item} + + {displayFunc(item)} + + {/each} + + +
+ + + {#snippet template(args)} + + {/snippet} + diff --git a/frontend/viewer/src/stories/fwl-parameters.ts b/frontend/viewer/src/stories/fwl-parameters.ts new file mode 100644 index 0000000000..d93a893e8b --- /dev/null +++ b/frontend/viewer/src/stories/fwl-parameters.ts @@ -0,0 +1,11 @@ +export type FwliteStoryParameters = { + themePicker?: boolean, + viewPicker?: boolean, + resizable?: boolean, + showValue?: boolean, + value?: unknown, +}; + +export function fwliteStoryParameters(params: Partial): {fwlite: FwliteStoryParameters} { + return {fwlite: params}; +} diff --git a/frontend/viewer/src/stories/i18n/i18n.stories.svelte b/frontend/viewer/src/stories/i18n/i18n.stories.svelte new file mode 100644 index 0000000000..63dccddfcd --- /dev/null +++ b/frontend/viewer/src/stories/i18n/i18n.stories.svelte @@ -0,0 +1,39 @@ + + + + {#snippet template()} + +
+
Date component:
+
+
Date function:
+
{formatDate(currentDate, {timeStyle: 'medium'})}
+
Number function:
+
{formatNumber(currentDate.getTime())}
+
+ {/snippet} +
+ + + {#snippet template()} + + + {#snippet second()} + 🤠 + {/snippet} + + {/snippet} + diff --git a/frontend/viewer/src/stories/primitives/button.stories.svelte b/frontend/viewer/src/stories/primitives/button.stories.svelte new file mode 100644 index 0000000000..aed032f26e --- /dev/null +++ b/frontend/viewer/src/stories/primitives/button.stories.svelte @@ -0,0 +1,99 @@ + + + + {#snippet template(args)} +
+
+ Variants: +
+ {#each variants as variant} + + {/each} +
+
+
+ Variants with icon: +
+ {#each variants as variant} + + {/each} +
+
+
+ Sizes: +
+ {#each sizes as size} + + {/each} +
+
+
+ Sizes with icon: +
+ {#each sizes as size} +
+
+
+ {/snippet} +
+ + { + const canvas = within(canvasElement); + const loadingButton = await canvas.findByRole('button', { name: 'Standard' }); + await expect(loadingButton).toBeInTheDocument(); + await userEvent.click(loadingButton); + await expect(args.onclick).toHaveBeenCalled(); + }}>Standard + + { + const canvas = within(canvasElement); + const loadingButton = await canvas.findByRole('button', { name: 'Loading' }); + await expect(loadingButton).toBeInTheDocument(); + await userEvent.click(loadingButton, { pointerEventsCheck: 0 }); + await expect(args.onclick).not.toHaveBeenCalled(); + }}>Loading + + { + const canvas = within(canvasElement); + const loadingButton = await canvas.findByRole('button', { name: 'Disabled' }); + await expect(loadingButton).toBeInTheDocument(); + await userEvent.click(loadingButton, { pointerEventsCheck: 0 }); + await expect(args.onclick).not.toHaveBeenCalled(); + }}>Disabled diff --git a/frontend/viewer/src/stories/primitives/lcm-rich-text-editor.stories.svelte b/frontend/viewer/src/stories/primitives/lcm-rich-text-editor.stories.svelte new file mode 100644 index 0000000000..b38072e159 --- /dev/null +++ b/frontend/viewer/src/stories/primitives/lcm-rich-text-editor.stories.svelte @@ -0,0 +1,49 @@ + + + + {#snippet template(args)} +
+ args.value = richString.current = JSON.parse(JSON.stringify($state.snapshot(richString.current)))} /> +
+ + + + +
+
+ {/snippet} +
diff --git a/frontend/viewer/src/stories/primitives/resizable-panes.stories.svelte b/frontend/viewer/src/stories/primitives/resizable-panes.stories.svelte new file mode 100644 index 0000000000..d5b36370f2 --- /dev/null +++ b/frontend/viewer/src/stories/primitives/resizable-panes.stories.svelte @@ -0,0 +1,35 @@ + + + + {#snippet template(args)} + + + Left Pane + + + + Middle Pane + + + + Right Pane + + + {/snippet} + diff --git a/frontend/viewer/tailwind.config.ts b/frontend/viewer/tailwind.config.ts index cfd128098f..89508587e2 100644 --- a/frontend/viewer/tailwind.config.ts +++ b/frontend/viewer/tailwind.config.ts @@ -13,6 +13,7 @@ export default { darkMode: ['class'], content: [ './src/**/!(WebComponent).{html,svelte,ts}', + './.storybook/**/*.{html,svelte,ts}', './node_modules/svelte-ux/**/*.{svelte,js}', //exclude icons.d.ts, because it contains all the icon classes which would cause them all to be included in the bundle '!./src/lib/icon-class.ts' diff --git a/frontend/viewer/tsconfig.json b/frontend/viewer/tsconfig.json index c3cdb40529..d20e70c02a 100644 --- a/frontend/viewer/tsconfig.json +++ b/frontend/viewer/tsconfig.json @@ -29,6 +29,9 @@ "tests/**/*.ts", "tests/**/*.js", "tests/**/*.svelte", + ".storybook/**/*.ts", + ".storybook/**/*.js", + ".storybook/**/*.svelte", ], "references": [{ "path": "./tsconfig.node.json" }], } diff --git a/frontend/viewer/vite.config.ts b/frontend/viewer/vite.config.ts index d2edd658fd..95e9af3911 100644 --- a/frontend/viewer/vite.config.ts +++ b/frontend/viewer/vite.config.ts @@ -1,7 +1,6 @@ import {defineConfig} from 'vite'; -import {svelte} from '@sveltejs/vite-plugin-svelte'; -import {svelteTesting} from '@testing-library/svelte/vite'; import {lingui} from '@lingui/vite-plugin'; +import {svelte} from '@sveltejs/vite-plugin-svelte'; import webfontDownload from 'vite-plugin-webfont-dl'; // https://vitejs.dev/config/ @@ -52,7 +51,6 @@ export default defineConfig(({ mode, command }) => { handler(warning); }, }), - svelteTesting(), lingui(), webfontDownload([], { @@ -66,10 +64,5 @@ export default defineConfig(({ mode, command }) => { allowedHosts: true, cors: true, }, - test: { - environment: 'happy-dom', - setupFiles: ['./vitest-setup.js'], - include: ['**/*.{test,spec,test.svelte}.?(c|m)[jt]s?(x)'], - }, } }); diff --git a/frontend/viewer/vitest-setup.js b/frontend/viewer/vitest-setup.js deleted file mode 100644 index a9d0dd31aa..0000000000 --- a/frontend/viewer/vitest-setup.js +++ /dev/null @@ -1 +0,0 @@ -import '@testing-library/jest-dom/vitest' diff --git a/frontend/viewer/vitest.config.ts b/frontend/viewer/vitest.config.ts new file mode 100644 index 0000000000..6497555586 --- /dev/null +++ b/frontend/viewer/vitest.config.ts @@ -0,0 +1,75 @@ +import {defineConfig} from 'vitest/config'; +import {fileURLToPath} from 'node:url'; +import path from 'node:path'; +import {storybookTest} from '@storybook/addon-vitest/vitest-plugin'; +import {svelte} from '@sveltejs/vite-plugin-svelte'; + +const dirname = + typeof __dirname !== 'undefined' ? __dirname : path.dirname(fileURLToPath(import.meta.url)); + +const browserTestPattern = '**/*.browser.{test,spec}.?(c|m)[jt]s?(x)'; +const e2eTestPattern = './tests/**'; +const defaultExcludeList = ['**/node_modules/**', '**/dist/**', '**/cypress/**', '**/.{idea,git,cache,output,temp}/**', '**/{karma,rollup,webpack,vite,vitest,jest,ava,babel,nyc,cypress,tsup,build,eslint,prettier}.config.*']; + +export default defineConfig({ + test: { + projects: [ + { + test: { + name: 'unit', + environment: 'node', + exclude: [browserTestPattern, e2eTestPattern, ...defaultExcludeList], + }, + resolve: { + alias: [{find: '$lib', replacement: '/src/lib'}] + }, + }, + { + plugins: [ + svelte(), + ], + test: { + name: 'browser (non storybook)', + browser: { + enabled: true, + headless: true, + provider: 'playwright', + instances: [ + {browser: 'chromium'}, + {browser: 'firefox'}, + ], + }, + include: [browserTestPattern], + }, + resolve: { + alias: [{find: '$lib', replacement: '/src/lib'}] + }, + }, + { + plugins: [ + svelte(), + // seems to cause this project to only include storybook tests + storybookTest({ + configDir: path.join(dirname, '.storybook'), + }), + ], + test: { + name: 'storybook', + browser: { + enabled: true, + headless: true, + provider: 'playwright', + instances: [ + {browser: 'chromium'}, + {browser: 'firefox'}, + ], + }, + setupFiles: ['./.storybook/vitest.setup.ts'], + }, + resolve: { + alias: [{find: '$lib', replacement: '/src/lib'}] + }, + } + ], + }, +});