Compare commits

...

5 Commits

Author SHA1 Message Date
DrJKL
887b534757 refactor: delete dead duplicate CreditSlider copy
src/platform/cloud/subscription/components/CreditSlider.{vue,test.ts,
stories.ts} was a stale, drifted copy with no production importer. The live
component is src/components/ui/credit-slider/CreditSlider.vue (used by
UnifiedPricingTable). The subscription copy was only referenced by its own
test and story, so it is removed wholesale — no merge needed.

fallow's other "duplicate exports" were reviewed and left as-is: they are
same-name/different-type definitions (User: API zod type vs store interface;
WidgetValue, JobListItem, ModelFile), deliberate re-export shims (ComfyDialog
via ui.ts), or litegraph-vs-renderer geometry types kept separate by the
layering rules. Consolidating them would break types or add speculative
shared modules, so none are changed here.
2026-06-28 22:09:13 -07:00
DrJKL
84326e34d0 refactor: remove unused OAuthConsentDecision type
The OAuthConsentDecision type alias had no references anywhere (the
function submitOAuthConsentDecision is not annotated with it, and nothing
imports it). Removed.

The other type/enum candidates fallow flagged were verified as NOT dead and
are left untouched:
- NodeBadgeMode.None/ShowAll/HideBuiltIn: consumed via Object.values across
  coreSettings, apiSchema (zod enum), and the badge composables.
- src/types/index.ts barrel and litegraph types: public/extension surface.
- generatedManagerTypes paths/webhooks/$defs/operations: openapi-codegen
  output, not hand-editable.
2026-06-28 22:03:24 -07:00
DrJKL
100f2defd5 refactor: remove dead exports
Remove exported symbols with zero consumers, verified by repo-wide grep
(including browser_tests, stories, and dynamic imports).

- clampUsd (comfyCredits.ts): fully unused, deleted.
- getRootParentNode (graphTraversalUtil.ts): no production importer; the
  only references were three stale vi.mock factory keys in the
  rightSidePanel/errors tests, which are removed alongside it.
- createMarkdownRenderer (markdownRendererUtil.ts): used only within its
  own module, downgraded from export to local.

Deliberately kept (fallow flagged, but verified as real usage):
- learningEvents, cloudOnboardingRoutes, ClickHouseTelemetryProvider,
  useShareDialog: consumed via dynamic import / astro page.
- getGalleryItemById (@knipIgnoreUsedByStackedPR), createImageHost
  (@knipIgnoreUnusedButUsedByCustomNodes): pre-annotated intentional keeps.
- storybook/mocks job exports: consumed via the .storybook vite alias.
- menu/index shim, types barrel, litegraph: public/extension surface.
2026-06-28 22:00:41 -07:00
DrJKL
b9948f5351 chore: remove unused dependencies
Drop direct deps fallow flagged as never imported. The primeuix/primevue
packages remain available transitively via primevue, and jiti remains via
eslint, so no install graph capability is lost.

Removed:
- @primeuix/forms, @primeuix/styled, @primevue/icons (transitive via primevue)
- jiti (transitive via eslint; only used to load the TS eslint config)
- stale @types/eslint '-' override (nothing requests @types/eslint)

Kept after verification (fallow false positives):
- eslint-plugin-playwright (.oxlintrc.json jsPlugins)
- postcss-html (.stylelintrc.json customSyntax)
- @iconify-json/lucide (design-system loadIconSet at build time)

Also drop the three removed packages from knip.config.ts ignoreDependencies.
2026-06-28 21:52:24 -07:00
DrJKL
88f2628e1e chore: add fallow dev dependency, scripts, and minimal config
Adds the fallow codebase-intelligence analyzer as a devDependency with
`pnpm fallow` (full scan) and `pnpm fallow:audit` (changed-files gate)
scripts and a minimal .fallowrc.json (entry points + duplicate-clone
threshold). Ignores the .fallow/ cache dir.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-28 18:43:30 -07:00
16 changed files with 230 additions and 740 deletions

9
.fallowrc.json Normal file
View File

@@ -0,0 +1,9 @@
{
"$schema": "https://raw.githubusercontent.com/fallow-rs/fallow/main/schema.json",
"entry": ["src/main.ts", "index.html"],
"duplicates": {
"minOccurrences": 3,
"ignore": ["**/*.generated.*", "**/generatedManagerTypes.ts"]
},
"rules": {}
}

1
.gitignore vendored
View File

@@ -16,6 +16,7 @@ yarn.lock
.eslintcache
.prettiercache
.stylelintcache
.fallow/
node_modules
.pnpm-store

View File

@@ -41,10 +41,7 @@ const config: KnipConfig = {
ignoreDependencies: [
// Weird importmap things
'@iconify-json/lucide',
'@iconify/json',
'@primeuix/forms',
'@primeuix/styled',
'@primevue/icons'
'@iconify/json'
],
ignore: [
// Auto generated API types

View File

@@ -29,6 +29,8 @@
"dev:test": "cross-env VITE_USE_LEGACY_DEFAULT_GRAPH=true vite --config vite.config.mts",
"dev": "vite --config vite.config.mts",
"devtools:pycheck": "python3 -m compileall -q tools/devtools",
"fallow": "fallow",
"fallow:audit": "fallow audit",
"format:check": "oxfmt --check",
"format": "oxfmt --write",
"json-schema": "tsx scripts/generate-json-schema.ts",
@@ -74,12 +76,9 @@
"@customerio/cdp-analytics-browser": "catalog:",
"@formkit/auto-animate": "catalog:",
"@iconify/json": "catalog:",
"@primeuix/forms": "catalog:",
"@primeuix/styled": "catalog:",
"@primeuix/utils": "catalog:",
"@primevue/core": "catalog:",
"@primevue/forms": "catalog:",
"@primevue/icons": "catalog:",
"@primevue/themes": "catalog:",
"@sentry/vue": "catalog:",
"@sparkjsdev/spark": "catalog:",
@@ -171,12 +170,12 @@
"eslint-plugin-testing-library": "catalog:",
"eslint-plugin-unused-imports": "catalog:",
"eslint-plugin-vue": "catalog:",
"fallow": "catalog:",
"fast-check": "catalog:",
"fs-extra": "^11.2.0",
"globals": "catalog:",
"happy-dom": "catalog:",
"husky": "catalog:",
"jiti": "catalog:",
"jsdom": "catalog:",
"knip": "catalog:",
"lint-staged": "catalog:",

371
pnpm-lock.yaml generated
View File

@@ -60,12 +60,6 @@ catalogs:
'@playwright/test':
specifier: ^1.58.1
version: 1.58.1
'@primeuix/forms':
specifier: 0.0.2
version: 0.0.2
'@primeuix/styled':
specifier: 0.3.2
version: 0.3.2
'@primeuix/utils':
specifier: ^0.3.2
version: 0.3.2
@@ -75,9 +69,6 @@ catalogs:
'@primevue/forms':
specifier: ^4.2.5
version: 4.2.5
'@primevue/icons':
specifier: 4.2.5
version: 4.2.5
'@primevue/themes':
specifier: ^4.2.5
version: 4.2.5
@@ -237,6 +228,9 @@ catalogs:
eslint-plugin-vue:
specifier: ^10.9.1
version: 10.9.1
fallow:
specifier: ^2.102.0
version: 2.102.0
fast-check:
specifier: ^4.5.3
version: 4.5.3
@@ -258,9 +252,6 @@ catalogs:
husky:
specifier: ^9.1.7
version: 9.1.7
jiti:
specifier: 2.6.1
version: 2.6.1
jsdom:
specifier: ^27.4.0
version: 27.4.0
@@ -418,7 +409,6 @@ catalogs:
overrides:
vite: ^8.0.13
'@tiptap/pm': 2.27.2
'@types/eslint': '-'
lodash: ^4.18.0
yaml: ^2.8.3
minimatch@^9.0.0: ^9.0.7
@@ -468,12 +458,6 @@ importers:
'@iconify/json':
specifier: 'catalog:'
version: 2.2.380
'@primeuix/forms':
specifier: 'catalog:'
version: 0.0.2
'@primeuix/styled':
specifier: 'catalog:'
version: 0.3.2
'@primeuix/utils':
specifier: 'catalog:'
version: 0.3.2
@@ -483,9 +467,6 @@ importers:
'@primevue/forms':
specifier: 'catalog:'
version: 4.2.5(vue@3.5.34(typescript@5.9.3))
'@primevue/icons':
specifier: 'catalog:'
version: 4.2.5(vue@3.5.34(typescript@5.9.3))
'@primevue/themes':
specifier: 'catalog:'
version: 4.2.5
@@ -648,10 +629,10 @@ importers:
version: link:packages/ingest-types
'@eslint/js':
specifier: 'catalog:'
version: 10.0.1(eslint@10.4.0(jiti@2.6.1))
version: 10.0.1(eslint@10.4.0(jiti@2.7.0))
'@intlify/eslint-plugin-vue-i18n':
specifier: 'catalog:'
version: 4.5.0(eslint@10.4.0(jiti@2.6.1))(jsonc-eslint-parser@2.4.0)(vue-eslint-parser@10.4.0(eslint@10.4.0(jiti@2.6.1)))(yaml-eslint-parser@1.3.0)
version: 4.5.0(eslint@10.4.0(jiti@2.7.0))(jsonc-eslint-parser@2.4.0)(vue-eslint-parser@10.4.0(eslint@10.4.0(jiti@2.7.0)))(yaml-eslint-parser@1.3.0)
'@lobehub/i18n-cli':
specifier: 'catalog:'
version: 1.26.1(@types/react@19.1.9)(typescript@5.9.3)(use-sync-external-store@1.6.0(react@19.2.4))(ws@8.21.0)(zod@3.25.76)
@@ -666,7 +647,7 @@ importers:
version: 4.6.0
'@storybook/addon-docs':
specifier: 'catalog:'
version: 10.2.10(@types/react@19.1.9)(esbuild@0.27.3)(storybook@10.2.10(@testing-library/dom@10.4.1)(prettier@3.7.4)(react-dom@19.2.4(react@19.2.4))(react@19.2.4))(vite@8.0.13(@types/node@24.10.4)(esbuild@0.27.3)(jiti@2.6.1)(terser@5.39.2)(tsx@4.19.4)(yaml@2.9.0))
version: 10.2.10(@types/react@19.1.9)(esbuild@0.27.3)(storybook@10.2.10(@testing-library/dom@10.4.1)(prettier@3.7.4)(react-dom@19.2.4(react@19.2.4))(react@19.2.4))(vite@8.0.13(@types/node@24.10.4)(esbuild@0.27.3)(jiti@2.7.0)(terser@5.39.2)(tsx@4.19.4)(yaml@2.9.0))
'@storybook/addon-mcp':
specifier: 'catalog:'
version: 0.1.6(storybook@10.2.10(@testing-library/dom@10.4.1)(prettier@3.7.4)(react-dom@19.2.4(react@19.2.4))(react@19.2.4))(typescript@5.9.3)
@@ -675,10 +656,10 @@ importers:
version: 10.2.10(storybook@10.2.10(@testing-library/dom@10.4.1)(prettier@3.7.4)(react-dom@19.2.4(react@19.2.4))(react@19.2.4))(vue@3.5.34(typescript@5.9.3))
'@storybook/vue3-vite':
specifier: 'catalog:'
version: 10.2.10(esbuild@0.27.3)(storybook@10.2.10(@testing-library/dom@10.4.1)(prettier@3.7.4)(react-dom@19.2.4(react@19.2.4))(react@19.2.4))(vite@8.0.13(@types/node@24.10.4)(esbuild@0.27.3)(jiti@2.6.1)(terser@5.39.2)(tsx@4.19.4)(yaml@2.9.0))(vue@3.5.34(typescript@5.9.3))
version: 10.2.10(esbuild@0.27.3)(storybook@10.2.10(@testing-library/dom@10.4.1)(prettier@3.7.4)(react-dom@19.2.4(react@19.2.4))(react@19.2.4))(vite@8.0.13(@types/node@24.10.4)(esbuild@0.27.3)(jiti@2.7.0)(terser@5.39.2)(tsx@4.19.4)(yaml@2.9.0))(vue@3.5.34(typescript@5.9.3))
'@tailwindcss/vite':
specifier: 'catalog:'
version: 4.3.0(vite@8.0.13(@types/node@24.10.4)(esbuild@0.27.3)(jiti@2.6.1)(terser@5.39.2)(tsx@4.19.4)(yaml@2.9.0))
version: 4.3.0(vite@8.0.13(@types/node@24.10.4)(esbuild@0.27.3)(jiti@2.7.0)(terser@5.39.2)(tsx@4.19.4)(yaml@2.9.0))
'@testing-library/jest-dom':
specifier: 'catalog:'
version: 6.9.1
@@ -708,7 +689,7 @@ importers:
version: 0.184.1
'@vitejs/plugin-vue':
specifier: 'catalog:'
version: 6.0.3(vite@8.0.13(@types/node@24.10.4)(esbuild@0.27.3)(jiti@2.6.1)(terser@5.39.2)(tsx@4.19.4)(yaml@2.9.0))(vue@3.5.34(typescript@5.9.3))
version: 6.0.3(vite@8.0.13(@types/node@24.10.4)(esbuild@0.27.3)(jiti@2.7.0)(terser@5.39.2)(tsx@4.19.4)(yaml@2.9.0))(vue@3.5.34(typescript@5.9.3))
'@vitest/coverage-v8':
specifier: 'catalog:'
version: 4.0.16(vitest@4.1.8)
@@ -723,37 +704,40 @@ importers:
version: 10.1.0
eslint:
specifier: 'catalog:'
version: 10.4.0(jiti@2.6.1)
version: 10.4.0(jiti@2.7.0)
eslint-config-prettier:
specifier: 'catalog:'
version: 10.1.8(eslint@10.4.0(jiti@2.6.1))
version: 10.1.8(eslint@10.4.0(jiti@2.7.0))
eslint-import-resolver-typescript:
specifier: 'catalog:'
version: 4.4.4(eslint-plugin-import-x@4.16.2(@typescript-eslint/utils@8.60.0(eslint@10.4.0(jiti@2.6.1))(typescript@5.9.3))(eslint@10.4.0(jiti@2.6.1)))(eslint@10.4.0(jiti@2.6.1))
version: 4.4.4(eslint-plugin-import-x@4.16.2(@typescript-eslint/utils@8.60.0(eslint@10.4.0(jiti@2.7.0))(typescript@5.9.3))(eslint@10.4.0(jiti@2.7.0)))(eslint@10.4.0(jiti@2.7.0))
eslint-plugin-better-tailwindcss:
specifier: 'catalog:'
version: 4.3.1(eslint@10.4.0(jiti@2.6.1))(oxlint@1.69.0(oxlint-tsgolint@0.23.0))(tailwindcss@4.3.0)(typescript@5.9.3)
version: 4.3.1(eslint@10.4.0(jiti@2.7.0))(oxlint@1.69.0(oxlint-tsgolint@0.23.0))(tailwindcss@4.3.0)(typescript@5.9.3)
eslint-plugin-import-x:
specifier: 'catalog:'
version: 4.16.2(@typescript-eslint/utils@8.60.0(eslint@10.4.0(jiti@2.6.1))(typescript@5.9.3))(eslint@10.4.0(jiti@2.6.1))
version: 4.16.2(@typescript-eslint/utils@8.60.0(eslint@10.4.0(jiti@2.7.0))(typescript@5.9.3))(eslint@10.4.0(jiti@2.7.0))
eslint-plugin-oxlint:
specifier: 'catalog:'
version: 1.69.0(oxlint@1.69.0(oxlint-tsgolint@0.23.0))
eslint-plugin-playwright:
specifier: 'catalog:'
version: 2.10.1(eslint@10.4.0(jiti@2.6.1))
version: 2.10.1(eslint@10.4.0(jiti@2.7.0))
eslint-plugin-storybook:
specifier: 'catalog:'
version: 10.2.10(eslint@10.4.0(jiti@2.6.1))(storybook@10.2.10(@testing-library/dom@10.4.1)(prettier@3.7.4)(react-dom@19.2.4(react@19.2.4))(react@19.2.4))(typescript@5.9.3)
version: 10.2.10(eslint@10.4.0(jiti@2.7.0))(storybook@10.2.10(@testing-library/dom@10.4.1)(prettier@3.7.4)(react-dom@19.2.4(react@19.2.4))(react@19.2.4))(typescript@5.9.3)
eslint-plugin-testing-library:
specifier: 'catalog:'
version: 7.16.1(eslint@10.4.0(jiti@2.6.1))(typescript@5.9.3)
version: 7.16.1(eslint@10.4.0(jiti@2.7.0))(typescript@5.9.3)
eslint-plugin-unused-imports:
specifier: 'catalog:'
version: 4.4.1(@typescript-eslint/eslint-plugin@8.60.0(@typescript-eslint/parser@8.60.0(eslint@10.4.0(jiti@2.6.1))(typescript@5.9.3))(eslint@10.4.0(jiti@2.6.1))(typescript@5.9.3))(eslint@10.4.0(jiti@2.6.1))
version: 4.4.1(@typescript-eslint/eslint-plugin@8.60.0(@typescript-eslint/parser@8.60.0(eslint@10.4.0(jiti@2.7.0))(typescript@5.9.3))(eslint@10.4.0(jiti@2.7.0))(typescript@5.9.3))(eslint@10.4.0(jiti@2.7.0))
eslint-plugin-vue:
specifier: 'catalog:'
version: 10.9.1(@typescript-eslint/parser@8.60.0(eslint@10.4.0(jiti@2.6.1))(typescript@5.9.3))(eslint@10.4.0(jiti@2.6.1))(vue-eslint-parser@10.4.0(eslint@10.4.0(jiti@2.6.1)))
version: 10.9.1(@typescript-eslint/parser@8.60.0(eslint@10.4.0(jiti@2.7.0))(typescript@5.9.3))(eslint@10.4.0(jiti@2.7.0))(vue-eslint-parser@10.4.0(eslint@10.4.0(jiti@2.7.0)))
fallow:
specifier: 'catalog:'
version: 2.102.0
fast-check:
specifier: 'catalog:'
version: 4.5.3
@@ -769,9 +753,6 @@ importers:
husky:
specifier: 'catalog:'
version: 9.1.7
jiti:
specifier: 'catalog:'
version: 2.6.1
jsdom:
specifier: 'catalog:'
version: 27.4.0
@@ -828,7 +809,7 @@ importers:
version: 5.9.3
typescript-eslint:
specifier: 'catalog:'
version: 8.60.0(eslint@10.4.0(jiti@2.6.1))(typescript@5.9.3)
version: 8.60.0(eslint@10.4.0(jiti@2.7.0))(typescript@5.9.3)
unplugin-icons:
specifier: 'catalog:'
version: 22.5.0(@vue/compiler-sfc@3.5.34)
@@ -843,25 +824,25 @@ importers:
version: 11.1.1
vite:
specifier: ^8.0.13
version: 8.0.13(@types/node@24.10.4)(esbuild@0.27.3)(jiti@2.6.1)(terser@5.39.2)(tsx@4.19.4)(yaml@2.9.0)
version: 8.0.13(@types/node@24.10.4)(esbuild@0.27.3)(jiti@2.7.0)(terser@5.39.2)(tsx@4.19.4)(yaml@2.9.0)
vite-plugin-dts:
specifier: 'catalog:'
version: 4.5.4(@types/node@24.10.4)(typescript@5.9.3)(vite@8.0.13(@types/node@24.10.4)(esbuild@0.27.3)(jiti@2.6.1)(terser@5.39.2)(tsx@4.19.4)(yaml@2.9.0))
version: 4.5.4(@types/node@24.10.4)(typescript@5.9.3)(vite@8.0.13(@types/node@24.10.4)(esbuild@0.27.3)(jiti@2.7.0)(terser@5.39.2)(tsx@4.19.4)(yaml@2.9.0))
vite-plugin-html:
specifier: 'catalog:'
version: 3.2.2(vite@8.0.13(@types/node@24.10.4)(esbuild@0.27.3)(jiti@2.6.1)(terser@5.39.2)(tsx@4.19.4)(yaml@2.9.0))
version: 3.2.2(vite@8.0.13(@types/node@24.10.4)(esbuild@0.27.3)(jiti@2.7.0)(terser@5.39.2)(tsx@4.19.4)(yaml@2.9.0))
vite-plugin-vue-devtools:
specifier: 'catalog:'
version: 8.0.5(vite@8.0.13(@types/node@24.10.4)(esbuild@0.27.3)(jiti@2.6.1)(terser@5.39.2)(tsx@4.19.4)(yaml@2.9.0))(vue@3.5.34(typescript@5.9.3))
version: 8.0.5(vite@8.0.13(@types/node@24.10.4)(esbuild@0.27.3)(jiti@2.7.0)(terser@5.39.2)(tsx@4.19.4)(yaml@2.9.0))(vue@3.5.34(typescript@5.9.3))
vitest:
specifier: 'catalog:'
version: 4.1.8(@opentelemetry/api@1.9.0)(@types/node@24.10.4)(@vitest/coverage-v8@4.0.16)(@vitest/ui@4.0.16)(happy-dom@20.9.0)(jsdom@27.4.0)(vite@8.0.13(@types/node@24.10.4)(esbuild@0.27.3)(jiti@2.6.1)(terser@5.39.2)(tsx@4.19.4)(yaml@2.9.0))
version: 4.1.8(@opentelemetry/api@1.9.0)(@types/node@24.10.4)(@vitest/coverage-v8@4.0.16)(@vitest/ui@4.0.16)(happy-dom@20.9.0)(jsdom@27.4.0)(vite@8.0.13(@types/node@24.10.4)(esbuild@0.27.3)(jiti@2.7.0)(terser@5.39.2)(tsx@4.19.4)(yaml@2.9.0))
vue-component-type-helpers:
specifier: 'catalog:'
version: 3.3.2
vue-eslint-parser:
specifier: 'catalog:'
version: 10.4.0(eslint@10.4.0(jiti@2.6.1))
version: 10.4.0(eslint@10.4.0(jiti@2.7.0))
vue-tsc:
specifier: 'catalog:'
version: 3.2.5(typescript@5.9.3)
@@ -1883,6 +1864,46 @@ packages:
'@exodus/crypto':
optional: true
'@fallow-cli/darwin-arm64@2.102.0':
resolution: {integrity: sha512-B8wzfzJgoX6h5Gv2xQ9ZidO5Jb8/PWdssAxYbWs1pb5oJHZ6S5PLwXuUdINmNSIaRGQwTk4DC9/tIMFHFvd9uw==}
cpu: [arm64]
os: [darwin]
'@fallow-cli/darwin-x64@2.102.0':
resolution: {integrity: sha512-aLbTWWzQnleKdi56obAPXMJm7YA3qAnkIX9T3eocRHiagYqp8nsf4cslM0rZKvu2WwK34NaBm8x886gl4cl+zg==}
cpu: [x64]
os: [darwin]
'@fallow-cli/linux-arm64-gnu@2.102.0':
resolution: {integrity: sha512-8nYeOSLSewqcKH/KUcKZaCq5QII5VTRX62l60B6UM1iKe/0jcmlQ2mOtx4rkHpeq3LL5emvT/ph4NNgGmWKSBg==}
cpu: [arm64]
os: [linux]
'@fallow-cli/linux-arm64-musl@2.102.0':
resolution: {integrity: sha512-2Zi33PXzZxD7HU5sPVwyElZGP7zyEdGo4hK0ewy6gMYgQ9BDfLnFhgaSSOzN1J4paIhYtBmVsLmqakyDKy22Jw==}
cpu: [arm64]
os: [linux]
'@fallow-cli/linux-x64-gnu@2.102.0':
resolution: {integrity: sha512-7Hys4X6hKuR/lqUaGXwezRzDrwXwu9KfahUy85WTuiG1to+ZbzDCqdbZ04LtnI8kK8ufrPDcq+ZXdyt5ksOJHA==}
cpu: [x64]
os: [linux]
'@fallow-cli/linux-x64-musl@2.102.0':
resolution: {integrity: sha512-RuDY1jOEPgJOuHBgEpHVl6J7Xf2QLFklnNy6zO1nw8R1fLgWUAAKlFirn1Y93pb9bXzqpn5Gre3YlhgIZ3+LBA==}
cpu: [x64]
os: [linux]
'@fallow-cli/win32-arm64-msvc@2.102.0':
resolution: {integrity: sha512-wsvHjLzWFvsYmCqnQLm1doSEHb9Z038+sFp1RzMcffPUBC5tqS3vCr8J8nolcLlPk7o3QWHQMXAqb1xSJe+doA==}
cpu: [arm64]
os: [win32]
'@fallow-cli/win32-x64-msvc@2.102.0':
resolution: {integrity: sha512-rH1hd0PD0mm6pCxh1pw5jubpJsvV6f5rjixMoD5AZLzWa6NPJBpPPuzruLGtH/9CYy8B0y7zPrGGTKRO2PCGzg==}
cpu: [x64]
os: [win32]
'@firebase/analytics-compat@0.2.18':
resolution: {integrity: sha512-Hw9mzsSMZaQu6wrTbi3kYYwGw9nBqOHr47pVLxfr5v8CalsdrG5gfs9XUlPOZjHRVISp3oQrh1j7d3E+ulHPjQ==}
peerDependencies:
@@ -5614,6 +5635,11 @@ packages:
extendable-media-recorder@9.2.27:
resolution: {integrity: sha512-2X+Ixi1cxLek0Cj9x9atmhQ+apG+LwJpP2p3ypP8Pxau0poDnicrg7FTfPVQV5PW/3DHFm/eQ16vbgo5Yk3HGQ==}
fallow@2.102.0:
resolution: {integrity: sha512-bkOT58kPVCB12d2apQjIKBw/qSdsGRPQFrN5ff9Yl5WzXRqlDTbT/MVdMXld4sJD5JQW1ftw2bTxJWCINggh6g==}
engines: {node: '>=16'}
hasBin: true
fast-check@4.5.3:
resolution: {integrity: sha512-IE9csY7lnhxBnA8g/WI5eg/hygA6MGWJMSNfFRrBlXUciADEhS1EDB0SIsMSvzubzIlOBbVITSsypCsW717poA==}
engines: {node: '>=12.17.0'}
@@ -6308,10 +6334,6 @@ packages:
engines: {node: '>=10'}
hasBin: true
jiti@2.6.1:
resolution: {integrity: sha512-ekilCSN1jwRvIbgeg/57YFh8qQDNbwDb9xT/qu2DAHbFFZUicIl4ygVaAvzveMhMVr3LnpSKTNnwt8PoOfmKhQ==}
hasBin: true
jiti@2.7.0:
resolution: {integrity: sha512-AC/7JofJvZGrrneWNaEnJeOLUx+JlGt7tNa0wZiRPT4MY1wmfKjt2+6O2p2uz2+skll8OZZmJMNqeke7kKbNgQ==}
hasBin: true
@@ -9808,9 +9830,9 @@ snapshots:
'@esbuild/win32-x64@0.27.3':
optional: true
'@eslint-community/eslint-utils@4.9.1(eslint@10.4.0(jiti@2.6.1))':
'@eslint-community/eslint-utils@4.9.1(eslint@10.4.0(jiti@2.7.0))':
dependencies:
eslint: 10.4.0(jiti@2.6.1)
eslint: 10.4.0(jiti@2.7.0)
eslint-visitor-keys: 3.4.3
'@eslint-community/regexpp@4.12.2': {}
@@ -9850,9 +9872,9 @@ snapshots:
transitivePeerDependencies:
- supports-color
'@eslint/js@10.0.1(eslint@10.4.0(jiti@2.6.1))':
'@eslint/js@10.0.1(eslint@10.4.0(jiti@2.7.0))':
optionalDependencies:
eslint: 10.4.0(jiti@2.6.1)
eslint: 10.4.0(jiti@2.7.0)
'@eslint/object-schema@3.0.5': {}
@@ -9863,6 +9885,30 @@ snapshots:
'@exodus/bytes@1.7.0': {}
'@fallow-cli/darwin-arm64@2.102.0':
optional: true
'@fallow-cli/darwin-x64@2.102.0':
optional: true
'@fallow-cli/linux-arm64-gnu@2.102.0':
optional: true
'@fallow-cli/linux-arm64-musl@2.102.0':
optional: true
'@fallow-cli/linux-x64-gnu@2.102.0':
optional: true
'@fallow-cli/linux-x64-musl@2.102.0':
optional: true
'@fallow-cli/win32-arm64-msvc@2.102.0':
optional: true
'@fallow-cli/win32-x64-msvc@2.102.0':
optional: true
'@firebase/analytics-compat@0.2.18(@firebase/app-compat@0.2.53)(@firebase/app@0.11.4)':
dependencies:
'@firebase/analytics': 0.10.12(@firebase/app@0.11.4)
@@ -10421,14 +10467,14 @@ snapshots:
'@intlify/message-compiler': 9.14.5
'@intlify/shared': 9.14.5
'@intlify/eslint-plugin-vue-i18n@4.5.0(eslint@10.4.0(jiti@2.6.1))(jsonc-eslint-parser@2.4.0)(vue-eslint-parser@10.4.0(eslint@10.4.0(jiti@2.6.1)))(yaml-eslint-parser@1.3.0)':
'@intlify/eslint-plugin-vue-i18n@4.5.0(eslint@10.4.0(jiti@2.7.0))(jsonc-eslint-parser@2.4.0)(vue-eslint-parser@10.4.0(eslint@10.4.0(jiti@2.7.0)))(yaml-eslint-parser@1.3.0)':
dependencies:
'@eslint/eslintrc': 3.3.3
'@intlify/core-base': 11.2.8
'@intlify/message-compiler': 11.2.8
debug: 4.4.3
eslint: 10.4.0(jiti@2.6.1)
eslint-compat-utils: 0.6.5(eslint@10.4.0(jiti@2.6.1))
eslint: 10.4.0(jiti@2.7.0)
eslint-compat-utils: 0.6.5(eslint@10.4.0(jiti@2.7.0))
glob: 10.5.0
globals: 16.5.0
ignore: 7.0.5
@@ -10440,7 +10486,7 @@ snapshots:
parse5: 7.3.0
semver: 7.7.4
synckit: 0.11.12
vue-eslint-parser: 10.4.0(eslint@10.4.0(jiti@2.6.1))
vue-eslint-parser: 10.4.0(eslint@10.4.0(jiti@2.7.0))
yaml-eslint-parser: 1.3.0
transitivePeerDependencies:
- supports-color
@@ -11373,10 +11419,10 @@ snapshots:
'@standard-schema/spec@1.1.0': {}
'@storybook/addon-docs@10.2.10(@types/react@19.1.9)(esbuild@0.27.3)(storybook@10.2.10(@testing-library/dom@10.4.1)(prettier@3.7.4)(react-dom@19.2.4(react@19.2.4))(react@19.2.4))(vite@8.0.13(@types/node@24.10.4)(esbuild@0.27.3)(jiti@2.6.1)(terser@5.39.2)(tsx@4.19.4)(yaml@2.9.0))':
'@storybook/addon-docs@10.2.10(@types/react@19.1.9)(esbuild@0.27.3)(storybook@10.2.10(@testing-library/dom@10.4.1)(prettier@3.7.4)(react-dom@19.2.4(react@19.2.4))(react@19.2.4))(vite@8.0.13(@types/node@24.10.4)(esbuild@0.27.3)(jiti@2.7.0)(terser@5.39.2)(tsx@4.19.4)(yaml@2.9.0))':
dependencies:
'@mdx-js/react': 3.1.1(@types/react@19.1.9)(react@19.2.4)
'@storybook/csf-plugin': 10.2.10(esbuild@0.27.3)(storybook@10.2.10(@testing-library/dom@10.4.1)(prettier@3.7.4)(react-dom@19.2.4(react@19.2.4))(react@19.2.4))(vite@8.0.13(@types/node@24.10.4)(esbuild@0.27.3)(jiti@2.6.1)(terser@5.39.2)(tsx@4.19.4)(yaml@2.9.0))
'@storybook/csf-plugin': 10.2.10(esbuild@0.27.3)(storybook@10.2.10(@testing-library/dom@10.4.1)(prettier@3.7.4)(react-dom@19.2.4(react@19.2.4))(react@19.2.4))(vite@8.0.13(@types/node@24.10.4)(esbuild@0.27.3)(jiti@2.7.0)(terser@5.39.2)(tsx@4.19.4)(yaml@2.9.0))
'@storybook/icons': 2.0.1(react-dom@19.2.4(react@19.2.4))(react@19.2.4)
'@storybook/react-dom-shim': 10.2.10(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(storybook@10.2.10(@testing-library/dom@10.4.1)(prettier@3.7.4)(react-dom@19.2.4(react@19.2.4))(react@19.2.4))
react: 19.2.4
@@ -11402,24 +11448,24 @@ snapshots:
- '@tmcp/auth'
- typescript
'@storybook/builder-vite@10.2.10(esbuild@0.27.3)(storybook@10.2.10(@testing-library/dom@10.4.1)(prettier@3.7.4)(react-dom@19.2.4(react@19.2.4))(react@19.2.4))(vite@8.0.13(@types/node@24.10.4)(esbuild@0.27.3)(jiti@2.6.1)(terser@5.39.2)(tsx@4.19.4)(yaml@2.9.0))':
'@storybook/builder-vite@10.2.10(esbuild@0.27.3)(storybook@10.2.10(@testing-library/dom@10.4.1)(prettier@3.7.4)(react-dom@19.2.4(react@19.2.4))(react@19.2.4))(vite@8.0.13(@types/node@24.10.4)(esbuild@0.27.3)(jiti@2.7.0)(terser@5.39.2)(tsx@4.19.4)(yaml@2.9.0))':
dependencies:
'@storybook/csf-plugin': 10.2.10(esbuild@0.27.3)(storybook@10.2.10(@testing-library/dom@10.4.1)(prettier@3.7.4)(react-dom@19.2.4(react@19.2.4))(react@19.2.4))(vite@8.0.13(@types/node@24.10.4)(esbuild@0.27.3)(jiti@2.6.1)(terser@5.39.2)(tsx@4.19.4)(yaml@2.9.0))
'@storybook/csf-plugin': 10.2.10(esbuild@0.27.3)(storybook@10.2.10(@testing-library/dom@10.4.1)(prettier@3.7.4)(react-dom@19.2.4(react@19.2.4))(react@19.2.4))(vite@8.0.13(@types/node@24.10.4)(esbuild@0.27.3)(jiti@2.7.0)(terser@5.39.2)(tsx@4.19.4)(yaml@2.9.0))
storybook: 10.2.10(@testing-library/dom@10.4.1)(prettier@3.7.4)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)
ts-dedent: 2.2.0
vite: 8.0.13(@types/node@24.10.4)(esbuild@0.27.3)(jiti@2.6.1)(terser@5.39.2)(tsx@4.19.4)(yaml@2.9.0)
vite: 8.0.13(@types/node@24.10.4)(esbuild@0.27.3)(jiti@2.7.0)(terser@5.39.2)(tsx@4.19.4)(yaml@2.9.0)
transitivePeerDependencies:
- esbuild
- rollup
- webpack
'@storybook/csf-plugin@10.2.10(esbuild@0.27.3)(storybook@10.2.10(@testing-library/dom@10.4.1)(prettier@3.7.4)(react-dom@19.2.4(react@19.2.4))(react@19.2.4))(vite@8.0.13(@types/node@24.10.4)(esbuild@0.27.3)(jiti@2.6.1)(terser@5.39.2)(tsx@4.19.4)(yaml@2.9.0))':
'@storybook/csf-plugin@10.2.10(esbuild@0.27.3)(storybook@10.2.10(@testing-library/dom@10.4.1)(prettier@3.7.4)(react-dom@19.2.4(react@19.2.4))(react@19.2.4))(vite@8.0.13(@types/node@24.10.4)(esbuild@0.27.3)(jiti@2.7.0)(terser@5.39.2)(tsx@4.19.4)(yaml@2.9.0))':
dependencies:
storybook: 10.2.10(@testing-library/dom@10.4.1)(prettier@3.7.4)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)
unplugin: 2.3.11
optionalDependencies:
esbuild: 0.27.3
vite: 8.0.13(@types/node@24.10.4)(esbuild@0.27.3)(jiti@2.6.1)(terser@5.39.2)(tsx@4.19.4)(yaml@2.9.0)
vite: 8.0.13(@types/node@24.10.4)(esbuild@0.27.3)(jiti@2.7.0)(terser@5.39.2)(tsx@4.19.4)(yaml@2.9.0)
'@storybook/global@5.0.0': {}
@@ -11444,14 +11490,14 @@ snapshots:
react-dom: 19.2.4(react@19.2.4)
storybook: 10.2.10(@testing-library/dom@10.4.1)(prettier@3.7.4)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)
'@storybook/vue3-vite@10.2.10(esbuild@0.27.3)(storybook@10.2.10(@testing-library/dom@10.4.1)(prettier@3.7.4)(react-dom@19.2.4(react@19.2.4))(react@19.2.4))(vite@8.0.13(@types/node@24.10.4)(esbuild@0.27.3)(jiti@2.6.1)(terser@5.39.2)(tsx@4.19.4)(yaml@2.9.0))(vue@3.5.34(typescript@5.9.3))':
'@storybook/vue3-vite@10.2.10(esbuild@0.27.3)(storybook@10.2.10(@testing-library/dom@10.4.1)(prettier@3.7.4)(react-dom@19.2.4(react@19.2.4))(react@19.2.4))(vite@8.0.13(@types/node@24.10.4)(esbuild@0.27.3)(jiti@2.7.0)(terser@5.39.2)(tsx@4.19.4)(yaml@2.9.0))(vue@3.5.34(typescript@5.9.3))':
dependencies:
'@storybook/builder-vite': 10.2.10(esbuild@0.27.3)(storybook@10.2.10(@testing-library/dom@10.4.1)(prettier@3.7.4)(react-dom@19.2.4(react@19.2.4))(react@19.2.4))(vite@8.0.13(@types/node@24.10.4)(esbuild@0.27.3)(jiti@2.6.1)(terser@5.39.2)(tsx@4.19.4)(yaml@2.9.0))
'@storybook/builder-vite': 10.2.10(esbuild@0.27.3)(storybook@10.2.10(@testing-library/dom@10.4.1)(prettier@3.7.4)(react-dom@19.2.4(react@19.2.4))(react@19.2.4))(vite@8.0.13(@types/node@24.10.4)(esbuild@0.27.3)(jiti@2.7.0)(terser@5.39.2)(tsx@4.19.4)(yaml@2.9.0))
'@storybook/vue3': 10.2.10(storybook@10.2.10(@testing-library/dom@10.4.1)(prettier@3.7.4)(react-dom@19.2.4(react@19.2.4))(react@19.2.4))(vue@3.5.34(typescript@5.9.3))
magic-string: 0.30.21
storybook: 10.2.10(@testing-library/dom@10.4.1)(prettier@3.7.4)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)
typescript: 5.9.3
vite: 8.0.13(@types/node@24.10.4)(esbuild@0.27.3)(jiti@2.6.1)(terser@5.39.2)(tsx@4.19.4)(yaml@2.9.0)
vite: 8.0.13(@types/node@24.10.4)(esbuild@0.27.3)(jiti@2.7.0)(terser@5.39.2)(tsx@4.19.4)(yaml@2.9.0)
vue-component-meta: 2.2.12(typescript@5.9.3)
vue-docgen-api: 4.79.2(vue@3.5.34(typescript@5.9.3))
transitivePeerDependencies:
@@ -11533,12 +11579,12 @@ snapshots:
'@tailwindcss/oxide-win32-arm64-msvc': 4.3.0
'@tailwindcss/oxide-win32-x64-msvc': 4.3.0
'@tailwindcss/vite@4.3.0(vite@8.0.13(@types/node@24.10.4)(esbuild@0.27.3)(jiti@2.6.1)(terser@5.39.2)(tsx@4.19.4)(yaml@2.9.0))':
'@tailwindcss/vite@4.3.0(vite@8.0.13(@types/node@24.10.4)(esbuild@0.27.3)(jiti@2.7.0)(terser@5.39.2)(tsx@4.19.4)(yaml@2.9.0))':
dependencies:
'@tailwindcss/node': 4.3.0
'@tailwindcss/oxide': 4.3.0
tailwindcss: 4.3.0
vite: 8.0.13(@types/node@24.10.4)(esbuild@0.27.3)(jiti@2.6.1)(terser@5.39.2)(tsx@4.19.4)(yaml@2.9.0)
vite: 8.0.13(@types/node@24.10.4)(esbuild@0.27.3)(jiti@2.7.0)(terser@5.39.2)(tsx@4.19.4)(yaml@2.9.0)
'@tailwindcss/vite@4.3.0(vite@8.0.13(@types/node@25.0.3)(esbuild@0.27.3)(jiti@2.7.0)(terser@5.39.2)(tsx@4.19.4)(yaml@2.9.0))':
dependencies:
@@ -11904,15 +11950,15 @@ snapshots:
dependencies:
'@types/node': 25.0.3
'@typescript-eslint/eslint-plugin@8.60.0(@typescript-eslint/parser@8.60.0(eslint@10.4.0(jiti@2.6.1))(typescript@5.9.3))(eslint@10.4.0(jiti@2.6.1))(typescript@5.9.3)':
'@typescript-eslint/eslint-plugin@8.60.0(@typescript-eslint/parser@8.60.0(eslint@10.4.0(jiti@2.7.0))(typescript@5.9.3))(eslint@10.4.0(jiti@2.7.0))(typescript@5.9.3)':
dependencies:
'@eslint-community/regexpp': 4.12.2
'@typescript-eslint/parser': 8.60.0(eslint@10.4.0(jiti@2.6.1))(typescript@5.9.3)
'@typescript-eslint/parser': 8.60.0(eslint@10.4.0(jiti@2.7.0))(typescript@5.9.3)
'@typescript-eslint/scope-manager': 8.60.0
'@typescript-eslint/type-utils': 8.60.0(eslint@10.4.0(jiti@2.6.1))(typescript@5.9.3)
'@typescript-eslint/utils': 8.60.0(eslint@10.4.0(jiti@2.6.1))(typescript@5.9.3)
'@typescript-eslint/type-utils': 8.60.0(eslint@10.4.0(jiti@2.7.0))(typescript@5.9.3)
'@typescript-eslint/utils': 8.60.0(eslint@10.4.0(jiti@2.7.0))(typescript@5.9.3)
'@typescript-eslint/visitor-keys': 8.60.0
eslint: 10.4.0(jiti@2.6.1)
eslint: 10.4.0(jiti@2.7.0)
ignore: 7.0.5
natural-compare: 1.4.0
ts-api-utils: 2.5.0(typescript@5.9.3)
@@ -11920,14 +11966,14 @@ snapshots:
transitivePeerDependencies:
- supports-color
'@typescript-eslint/parser@8.60.0(eslint@10.4.0(jiti@2.6.1))(typescript@5.9.3)':
'@typescript-eslint/parser@8.60.0(eslint@10.4.0(jiti@2.7.0))(typescript@5.9.3)':
dependencies:
'@typescript-eslint/scope-manager': 8.60.0
'@typescript-eslint/types': 8.60.0
'@typescript-eslint/typescript-estree': 8.60.0(typescript@5.9.3)
'@typescript-eslint/visitor-keys': 8.60.0
debug: 4.4.3
eslint: 10.4.0(jiti@2.6.1)
eslint: 10.4.0(jiti@2.7.0)
typescript: 5.9.3
transitivePeerDependencies:
- supports-color
@@ -11950,13 +11996,13 @@ snapshots:
dependencies:
typescript: 5.9.3
'@typescript-eslint/type-utils@8.60.0(eslint@10.4.0(jiti@2.6.1))(typescript@5.9.3)':
'@typescript-eslint/type-utils@8.60.0(eslint@10.4.0(jiti@2.7.0))(typescript@5.9.3)':
dependencies:
'@typescript-eslint/types': 8.60.0
'@typescript-eslint/typescript-estree': 8.60.0(typescript@5.9.3)
'@typescript-eslint/utils': 8.60.0(eslint@10.4.0(jiti@2.6.1))(typescript@5.9.3)
'@typescript-eslint/utils': 8.60.0(eslint@10.4.0(jiti@2.7.0))(typescript@5.9.3)
debug: 4.4.3
eslint: 10.4.0(jiti@2.6.1)
eslint: 10.4.0(jiti@2.7.0)
ts-api-utils: 2.5.0(typescript@5.9.3)
typescript: 5.9.3
transitivePeerDependencies:
@@ -11979,13 +12025,13 @@ snapshots:
transitivePeerDependencies:
- supports-color
'@typescript-eslint/utils@8.60.0(eslint@10.4.0(jiti@2.6.1))(typescript@5.9.3)':
'@typescript-eslint/utils@8.60.0(eslint@10.4.0(jiti@2.7.0))(typescript@5.9.3)':
dependencies:
'@eslint-community/eslint-utils': 4.9.1(eslint@10.4.0(jiti@2.6.1))
'@eslint-community/eslint-utils': 4.9.1(eslint@10.4.0(jiti@2.7.0))
'@typescript-eslint/scope-manager': 8.60.0
'@typescript-eslint/types': 8.60.0
'@typescript-eslint/typescript-estree': 8.60.0(typescript@5.9.3)
eslint: 10.4.0(jiti@2.6.1)
eslint: 10.4.0(jiti@2.7.0)
typescript: 5.9.3
transitivePeerDependencies:
- supports-color
@@ -12086,10 +12132,10 @@ snapshots:
transitivePeerDependencies:
- supports-color
'@vitejs/plugin-vue@6.0.3(vite@8.0.13(@types/node@24.10.4)(esbuild@0.27.3)(jiti@2.6.1)(terser@5.39.2)(tsx@4.19.4)(yaml@2.9.0))(vue@3.5.34(typescript@5.9.3))':
'@vitejs/plugin-vue@6.0.3(vite@8.0.13(@types/node@24.10.4)(esbuild@0.27.3)(jiti@2.7.0)(terser@5.39.2)(tsx@4.19.4)(yaml@2.9.0))(vue@3.5.34(typescript@5.9.3))':
dependencies:
'@rolldown/pluginutils': 1.0.0-beta.53
vite: 8.0.13(@types/node@24.10.4)(esbuild@0.27.3)(jiti@2.6.1)(terser@5.39.2)(tsx@4.19.4)(yaml@2.9.0)
vite: 8.0.13(@types/node@24.10.4)(esbuild@0.27.3)(jiti@2.7.0)(terser@5.39.2)(tsx@4.19.4)(yaml@2.9.0)
vue: 3.5.34(typescript@5.9.3)
'@vitejs/plugin-vue@6.0.3(vite@8.0.13(@types/node@25.0.3)(esbuild@0.27.3)(jiti@2.7.0)(terser@5.39.2)(tsx@4.19.4)(yaml@2.9.0))(vue@3.5.34(typescript@5.9.3))':
@@ -12117,7 +12163,7 @@ snapshots:
obug: 2.1.1
std-env: 3.10.0
tinyrainbow: 3.0.3
vitest: 4.1.8(@opentelemetry/api@1.9.0)(@types/node@24.10.4)(@vitest/coverage-v8@4.0.16)(@vitest/ui@4.0.16)(happy-dom@20.9.0)(jsdom@27.4.0)(vite@8.0.13(@types/node@24.10.4)(esbuild@0.27.3)(jiti@2.6.1)(terser@5.39.2)(tsx@4.19.4)(yaml@2.9.0))
vitest: 4.1.8(@opentelemetry/api@1.9.0)(@types/node@24.10.4)(@vitest/coverage-v8@4.0.16)(@vitest/ui@4.0.16)(happy-dom@20.9.0)(jsdom@27.4.0)(vite@8.0.13(@types/node@24.10.4)(esbuild@0.27.3)(jiti@2.7.0)(terser@5.39.2)(tsx@4.19.4)(yaml@2.9.0))
transitivePeerDependencies:
- supports-color
@@ -12138,13 +12184,13 @@ snapshots:
chai: 6.2.2
tinyrainbow: 3.1.0
'@vitest/mocker@4.1.8(vite@8.0.13(@types/node@24.10.4)(esbuild@0.27.3)(jiti@2.6.1)(terser@5.39.2)(tsx@4.19.4)(yaml@2.9.0))':
'@vitest/mocker@4.1.8(vite@8.0.13(@types/node@24.10.4)(esbuild@0.27.3)(jiti@2.7.0)(terser@5.39.2)(tsx@4.19.4)(yaml@2.9.0))':
dependencies:
'@vitest/spy': 4.1.8
estree-walker: 3.0.3
magic-string: 0.30.21
optionalDependencies:
vite: 8.0.13(@types/node@24.10.4)(esbuild@0.27.3)(jiti@2.6.1)(terser@5.39.2)(tsx@4.19.4)(yaml@2.9.0)
vite: 8.0.13(@types/node@24.10.4)(esbuild@0.27.3)(jiti@2.7.0)(terser@5.39.2)(tsx@4.19.4)(yaml@2.9.0)
'@vitest/mocker@4.1.8(vite@8.0.13(@types/node@25.0.3)(esbuild@0.27.3)(jiti@2.7.0)(terser@5.39.2)(tsx@4.19.4)(yaml@2.9.0))':
dependencies:
@@ -12193,7 +12239,7 @@ snapshots:
sirv: 3.0.2
tinyglobby: 0.2.16
tinyrainbow: 3.0.3
vitest: 4.1.8(@opentelemetry/api@1.9.0)(@types/node@24.10.4)(@vitest/coverage-v8@4.0.16)(@vitest/ui@4.0.16)(happy-dom@20.9.0)(jsdom@27.4.0)(vite@8.0.13(@types/node@24.10.4)(esbuild@0.27.3)(jiti@2.6.1)(terser@5.39.2)(tsx@4.19.4)(yaml@2.9.0))
vitest: 4.1.8(@opentelemetry/api@1.9.0)(@types/node@24.10.4)(@vitest/coverage-v8@4.0.16)(@vitest/ui@4.0.16)(happy-dom@20.9.0)(jsdom@27.4.0)(vite@8.0.13(@types/node@24.10.4)(esbuild@0.27.3)(jiti@2.7.0)(terser@5.39.2)(tsx@4.19.4)(yaml@2.9.0))
'@vitest/utils@3.2.4':
dependencies:
@@ -12373,14 +12419,14 @@ snapshots:
dependencies:
'@vue/devtools-kit': 7.7.9
'@vue/devtools-core@8.0.5(vite@8.0.13(@types/node@24.10.4)(esbuild@0.27.3)(jiti@2.6.1)(terser@5.39.2)(tsx@4.19.4)(yaml@2.9.0))(vue@3.5.34(typescript@5.9.3))':
'@vue/devtools-core@8.0.5(vite@8.0.13(@types/node@24.10.4)(esbuild@0.27.3)(jiti@2.7.0)(terser@5.39.2)(tsx@4.19.4)(yaml@2.9.0))(vue@3.5.34(typescript@5.9.3))':
dependencies:
'@vue/devtools-kit': 8.0.5
'@vue/devtools-shared': 8.0.5
mitt: 3.0.1
nanoid: 5.1.5
pathe: 2.0.3
vite-hot-client: 2.1.0(vite@8.0.13(@types/node@24.10.4)(esbuild@0.27.3)(jiti@2.6.1)(terser@5.39.2)(tsx@4.19.4)(yaml@2.9.0))
vite-hot-client: 2.1.0(vite@8.0.13(@types/node@24.10.4)(esbuild@0.27.3)(jiti@2.7.0)(terser@5.39.2)(tsx@4.19.4)(yaml@2.9.0))
vue: 3.5.34(typescript@5.9.3)
transitivePeerDependencies:
- vite
@@ -13580,14 +13626,14 @@ snapshots:
escape-string-regexp@5.0.0: {}
eslint-compat-utils@0.6.5(eslint@10.4.0(jiti@2.6.1)):
eslint-compat-utils@0.6.5(eslint@10.4.0(jiti@2.7.0)):
dependencies:
eslint: 10.4.0(jiti@2.6.1)
eslint: 10.4.0(jiti@2.7.0)
semver: 7.7.4
eslint-config-prettier@10.1.8(eslint@10.4.0(jiti@2.6.1)):
eslint-config-prettier@10.1.8(eslint@10.4.0(jiti@2.7.0)):
dependencies:
eslint: 10.4.0(jiti@2.6.1)
eslint: 10.4.0(jiti@2.7.0)
eslint-import-context@0.1.9(unrs-resolver@1.11.1):
dependencies:
@@ -13596,10 +13642,10 @@ snapshots:
optionalDependencies:
unrs-resolver: 1.11.1
eslint-import-resolver-typescript@4.4.4(eslint-plugin-import-x@4.16.2(@typescript-eslint/utils@8.60.0(eslint@10.4.0(jiti@2.6.1))(typescript@5.9.3))(eslint@10.4.0(jiti@2.6.1)))(eslint@10.4.0(jiti@2.6.1)):
eslint-import-resolver-typescript@4.4.4(eslint-plugin-import-x@4.16.2(@typescript-eslint/utils@8.60.0(eslint@10.4.0(jiti@2.7.0))(typescript@5.9.3))(eslint@10.4.0(jiti@2.7.0)))(eslint@10.4.0(jiti@2.7.0)):
dependencies:
debug: 4.4.3
eslint: 10.4.0(jiti@2.6.1)
eslint: 10.4.0(jiti@2.7.0)
eslint-import-context: 0.1.9(unrs-resolver@1.11.1)
get-tsconfig: 4.14.0
is-bun-module: 2.0.0
@@ -13607,11 +13653,11 @@ snapshots:
tinyglobby: 0.2.16
unrs-resolver: 1.11.1
optionalDependencies:
eslint-plugin-import-x: 4.16.2(@typescript-eslint/utils@8.60.0(eslint@10.4.0(jiti@2.6.1))(typescript@5.9.3))(eslint@10.4.0(jiti@2.6.1))
eslint-plugin-import-x: 4.16.2(@typescript-eslint/utils@8.60.0(eslint@10.4.0(jiti@2.7.0))(typescript@5.9.3))(eslint@10.4.0(jiti@2.7.0))
transitivePeerDependencies:
- supports-color
eslint-plugin-better-tailwindcss@4.3.1(eslint@10.4.0(jiti@2.6.1))(oxlint@1.69.0(oxlint-tsgolint@0.23.0))(tailwindcss@4.3.0)(typescript@5.9.3):
eslint-plugin-better-tailwindcss@4.3.1(eslint@10.4.0(jiti@2.7.0))(oxlint@1.69.0(oxlint-tsgolint@0.23.0))(tailwindcss@4.3.0)(typescript@5.9.3):
dependencies:
'@eslint/css-tree': 3.6.9
'@valibot/to-json-schema': 1.5.0(valibot@1.2.0(typescript@5.9.3))
@@ -13623,18 +13669,18 @@ snapshots:
tsconfig-paths-webpack-plugin: 4.2.0
valibot: 1.2.0(typescript@5.9.3)
optionalDependencies:
eslint: 10.4.0(jiti@2.6.1)
eslint: 10.4.0(jiti@2.7.0)
oxlint: 1.69.0(oxlint-tsgolint@0.23.0)
transitivePeerDependencies:
- typescript
eslint-plugin-import-x@4.16.2(@typescript-eslint/utils@8.60.0(eslint@10.4.0(jiti@2.6.1))(typescript@5.9.3))(eslint@10.4.0(jiti@2.6.1)):
eslint-plugin-import-x@4.16.2(@typescript-eslint/utils@8.60.0(eslint@10.4.0(jiti@2.7.0))(typescript@5.9.3))(eslint@10.4.0(jiti@2.7.0)):
dependencies:
'@package-json/types': 0.0.12
'@typescript-eslint/types': 8.60.0
comment-parser: 1.4.1
debug: 4.4.3
eslint: 10.4.0(jiti@2.6.1)
eslint: 10.4.0(jiti@2.7.0)
eslint-import-context: 0.1.9(unrs-resolver@1.11.1)
is-glob: 4.0.3
minimatch: 9.0.9
@@ -13642,7 +13688,7 @@ snapshots:
stable-hash-x: 0.2.0
unrs-resolver: 1.11.1
optionalDependencies:
'@typescript-eslint/utils': 8.60.0(eslint@10.4.0(jiti@2.6.1))(typescript@5.9.3)
'@typescript-eslint/utils': 8.60.0(eslint@10.4.0(jiti@2.7.0))(typescript@5.9.3)
transitivePeerDependencies:
- supports-color
@@ -13651,47 +13697,47 @@ snapshots:
jsonc-parser: 3.3.1
oxlint: 1.69.0(oxlint-tsgolint@0.23.0)
eslint-plugin-playwright@2.10.1(eslint@10.4.0(jiti@2.6.1)):
eslint-plugin-playwright@2.10.1(eslint@10.4.0(jiti@2.7.0)):
dependencies:
eslint: 10.4.0(jiti@2.6.1)
eslint: 10.4.0(jiti@2.7.0)
globals: 17.4.0
eslint-plugin-storybook@10.2.10(eslint@10.4.0(jiti@2.6.1))(storybook@10.2.10(@testing-library/dom@10.4.1)(prettier@3.7.4)(react-dom@19.2.4(react@19.2.4))(react@19.2.4))(typescript@5.9.3):
eslint-plugin-storybook@10.2.10(eslint@10.4.0(jiti@2.7.0))(storybook@10.2.10(@testing-library/dom@10.4.1)(prettier@3.7.4)(react-dom@19.2.4(react@19.2.4))(react@19.2.4))(typescript@5.9.3):
dependencies:
'@typescript-eslint/utils': 8.60.0(eslint@10.4.0(jiti@2.6.1))(typescript@5.9.3)
eslint: 10.4.0(jiti@2.6.1)
'@typescript-eslint/utils': 8.60.0(eslint@10.4.0(jiti@2.7.0))(typescript@5.9.3)
eslint: 10.4.0(jiti@2.7.0)
storybook: 10.2.10(@testing-library/dom@10.4.1)(prettier@3.7.4)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)
transitivePeerDependencies:
- supports-color
- typescript
eslint-plugin-testing-library@7.16.1(eslint@10.4.0(jiti@2.6.1))(typescript@5.9.3):
eslint-plugin-testing-library@7.16.1(eslint@10.4.0(jiti@2.7.0))(typescript@5.9.3):
dependencies:
'@typescript-eslint/scope-manager': 8.60.0
'@typescript-eslint/utils': 8.60.0(eslint@10.4.0(jiti@2.6.1))(typescript@5.9.3)
eslint: 10.4.0(jiti@2.6.1)
'@typescript-eslint/utils': 8.60.0(eslint@10.4.0(jiti@2.7.0))(typescript@5.9.3)
eslint: 10.4.0(jiti@2.7.0)
transitivePeerDependencies:
- supports-color
- typescript
eslint-plugin-unused-imports@4.4.1(@typescript-eslint/eslint-plugin@8.60.0(@typescript-eslint/parser@8.60.0(eslint@10.4.0(jiti@2.6.1))(typescript@5.9.3))(eslint@10.4.0(jiti@2.6.1))(typescript@5.9.3))(eslint@10.4.0(jiti@2.6.1)):
eslint-plugin-unused-imports@4.4.1(@typescript-eslint/eslint-plugin@8.60.0(@typescript-eslint/parser@8.60.0(eslint@10.4.0(jiti@2.7.0))(typescript@5.9.3))(eslint@10.4.0(jiti@2.7.0))(typescript@5.9.3))(eslint@10.4.0(jiti@2.7.0)):
dependencies:
eslint: 10.4.0(jiti@2.6.1)
eslint: 10.4.0(jiti@2.7.0)
optionalDependencies:
'@typescript-eslint/eslint-plugin': 8.60.0(@typescript-eslint/parser@8.60.0(eslint@10.4.0(jiti@2.6.1))(typescript@5.9.3))(eslint@10.4.0(jiti@2.6.1))(typescript@5.9.3)
'@typescript-eslint/eslint-plugin': 8.60.0(@typescript-eslint/parser@8.60.0(eslint@10.4.0(jiti@2.7.0))(typescript@5.9.3))(eslint@10.4.0(jiti@2.7.0))(typescript@5.9.3)
eslint-plugin-vue@10.9.1(@typescript-eslint/parser@8.60.0(eslint@10.4.0(jiti@2.6.1))(typescript@5.9.3))(eslint@10.4.0(jiti@2.6.1))(vue-eslint-parser@10.4.0(eslint@10.4.0(jiti@2.6.1))):
eslint-plugin-vue@10.9.1(@typescript-eslint/parser@8.60.0(eslint@10.4.0(jiti@2.7.0))(typescript@5.9.3))(eslint@10.4.0(jiti@2.7.0))(vue-eslint-parser@10.4.0(eslint@10.4.0(jiti@2.7.0))):
dependencies:
'@eslint-community/eslint-utils': 4.9.1(eslint@10.4.0(jiti@2.6.1))
eslint: 10.4.0(jiti@2.6.1)
'@eslint-community/eslint-utils': 4.9.1(eslint@10.4.0(jiti@2.7.0))
eslint: 10.4.0(jiti@2.7.0)
natural-compare: 1.4.0
nth-check: 2.1.1
postcss-selector-parser: 7.1.1
semver: 7.7.4
vue-eslint-parser: 10.4.0(eslint@10.4.0(jiti@2.6.1))
vue-eslint-parser: 10.4.0(eslint@10.4.0(jiti@2.7.0))
xml-name-validator: 4.0.0
optionalDependencies:
'@typescript-eslint/parser': 8.60.0(eslint@10.4.0(jiti@2.6.1))(typescript@5.9.3)
'@typescript-eslint/parser': 8.60.0(eslint@10.4.0(jiti@2.7.0))(typescript@5.9.3)
eslint-scope@9.1.2:
dependencies:
@@ -13706,9 +13752,9 @@ snapshots:
eslint-visitor-keys@5.0.1: {}
eslint@10.4.0(jiti@2.6.1):
eslint@10.4.0(jiti@2.7.0):
dependencies:
'@eslint-community/eslint-utils': 4.9.1(eslint@10.4.0(jiti@2.6.1))
'@eslint-community/eslint-utils': 4.9.1(eslint@10.4.0(jiti@2.7.0))
'@eslint-community/regexpp': 4.12.2
'@eslint/config-array': 0.23.5
'@eslint/config-helpers': 0.6.0
@@ -13739,7 +13785,7 @@ snapshots:
natural-compare: 1.4.0
optionator: 0.9.4
optionalDependencies:
jiti: 2.6.1
jiti: 2.7.0
transitivePeerDependencies:
- supports-color
@@ -13829,6 +13875,19 @@ snapshots:
subscribable-things: 2.1.53
tslib: 2.8.1
fallow@2.102.0:
dependencies:
detect-libc: 2.1.2
optionalDependencies:
'@fallow-cli/darwin-arm64': 2.102.0
'@fallow-cli/darwin-x64': 2.102.0
'@fallow-cli/linux-arm64-gnu': 2.102.0
'@fallow-cli/linux-arm64-musl': 2.102.0
'@fallow-cli/linux-x64-gnu': 2.102.0
'@fallow-cli/linux-x64-musl': 2.102.0
'@fallow-cli/win32-arm64-msvc': 2.102.0
'@fallow-cli/win32-x64-msvc': 2.102.0
fast-check@4.5.3:
dependencies:
pure-rand: 7.0.1
@@ -14613,8 +14672,6 @@ snapshots:
filelist: 1.0.4
minimatch: 3.1.5
jiti@2.6.1: {}
jiti@2.7.0: {}
jju@1.4.0: {}
@@ -16981,13 +17038,13 @@ snapshots:
dependencies:
semver: 7.7.4
typescript-eslint@8.60.0(eslint@10.4.0(jiti@2.6.1))(typescript@5.9.3):
typescript-eslint@8.60.0(eslint@10.4.0(jiti@2.7.0))(typescript@5.9.3):
dependencies:
'@typescript-eslint/eslint-plugin': 8.60.0(@typescript-eslint/parser@8.60.0(eslint@10.4.0(jiti@2.6.1))(typescript@5.9.3))(eslint@10.4.0(jiti@2.6.1))(typescript@5.9.3)
'@typescript-eslint/parser': 8.60.0(eslint@10.4.0(jiti@2.6.1))(typescript@5.9.3)
'@typescript-eslint/eslint-plugin': 8.60.0(@typescript-eslint/parser@8.60.0(eslint@10.4.0(jiti@2.7.0))(typescript@5.9.3))(eslint@10.4.0(jiti@2.7.0))(typescript@5.9.3)
'@typescript-eslint/parser': 8.60.0(eslint@10.4.0(jiti@2.7.0))(typescript@5.9.3)
'@typescript-eslint/typescript-estree': 8.60.0(typescript@5.9.3)
'@typescript-eslint/utils': 8.60.0(eslint@10.4.0(jiti@2.6.1))(typescript@5.9.3)
eslint: 10.4.0(jiti@2.6.1)
'@typescript-eslint/utils': 8.60.0(eslint@10.4.0(jiti@2.7.0))(typescript@5.9.3)
eslint: 10.4.0(jiti@2.7.0)
typescript: 5.9.3
transitivePeerDependencies:
- supports-color
@@ -17237,11 +17294,11 @@ snapshots:
'@types/unist': 3.0.3
vfile-message: 4.0.3
vite-dev-rpc@1.1.0(vite@8.0.13(@types/node@24.10.4)(esbuild@0.27.3)(jiti@2.6.1)(terser@5.39.2)(tsx@4.19.4)(yaml@2.9.0)):
vite-dev-rpc@1.1.0(vite@8.0.13(@types/node@24.10.4)(esbuild@0.27.3)(jiti@2.7.0)(terser@5.39.2)(tsx@4.19.4)(yaml@2.9.0)):
dependencies:
birpc: 2.9.0
vite: 8.0.13(@types/node@24.10.4)(esbuild@0.27.3)(jiti@2.6.1)(terser@5.39.2)(tsx@4.19.4)(yaml@2.9.0)
vite-hot-client: 2.1.0(vite@8.0.13(@types/node@24.10.4)(esbuild@0.27.3)(jiti@2.6.1)(terser@5.39.2)(tsx@4.19.4)(yaml@2.9.0))
vite: 8.0.13(@types/node@24.10.4)(esbuild@0.27.3)(jiti@2.7.0)(terser@5.39.2)(tsx@4.19.4)(yaml@2.9.0)
vite-hot-client: 2.1.0(vite@8.0.13(@types/node@24.10.4)(esbuild@0.27.3)(jiti@2.7.0)(terser@5.39.2)(tsx@4.19.4)(yaml@2.9.0))
vite-dev-rpc@1.1.0(vite@8.0.13(@types/node@25.0.3)(esbuild@0.27.3)(jiti@2.7.0)(terser@5.39.2)(tsx@4.19.4)(yaml@2.9.0)):
dependencies:
@@ -17249,15 +17306,15 @@ snapshots:
vite: 8.0.13(@types/node@25.0.3)(esbuild@0.27.3)(jiti@2.7.0)(terser@5.39.2)(tsx@4.19.4)(yaml@2.9.0)
vite-hot-client: 2.1.0(vite@8.0.13(@types/node@25.0.3)(esbuild@0.27.3)(jiti@2.7.0)(terser@5.39.2)(tsx@4.19.4)(yaml@2.9.0))
vite-hot-client@2.1.0(vite@8.0.13(@types/node@24.10.4)(esbuild@0.27.3)(jiti@2.6.1)(terser@5.39.2)(tsx@4.19.4)(yaml@2.9.0)):
vite-hot-client@2.1.0(vite@8.0.13(@types/node@24.10.4)(esbuild@0.27.3)(jiti@2.7.0)(terser@5.39.2)(tsx@4.19.4)(yaml@2.9.0)):
dependencies:
vite: 8.0.13(@types/node@24.10.4)(esbuild@0.27.3)(jiti@2.6.1)(terser@5.39.2)(tsx@4.19.4)(yaml@2.9.0)
vite: 8.0.13(@types/node@24.10.4)(esbuild@0.27.3)(jiti@2.7.0)(terser@5.39.2)(tsx@4.19.4)(yaml@2.9.0)
vite-hot-client@2.1.0(vite@8.0.13(@types/node@25.0.3)(esbuild@0.27.3)(jiti@2.7.0)(terser@5.39.2)(tsx@4.19.4)(yaml@2.9.0)):
dependencies:
vite: 8.0.13(@types/node@25.0.3)(esbuild@0.27.3)(jiti@2.7.0)(terser@5.39.2)(tsx@4.19.4)(yaml@2.9.0)
vite-plugin-dts@4.5.4(@types/node@24.10.4)(typescript@5.9.3)(vite@8.0.13(@types/node@24.10.4)(esbuild@0.27.3)(jiti@2.6.1)(terser@5.39.2)(tsx@4.19.4)(yaml@2.9.0)):
vite-plugin-dts@4.5.4(@types/node@24.10.4)(typescript@5.9.3)(vite@8.0.13(@types/node@24.10.4)(esbuild@0.27.3)(jiti@2.7.0)(terser@5.39.2)(tsx@4.19.4)(yaml@2.9.0)):
dependencies:
'@microsoft/api-extractor': 7.57.2(@types/node@24.10.4)
'@rollup/pluginutils': 5.3.0
@@ -17270,13 +17327,13 @@ snapshots:
magic-string: 0.30.21
typescript: 5.9.3
optionalDependencies:
vite: 8.0.13(@types/node@24.10.4)(esbuild@0.27.3)(jiti@2.6.1)(terser@5.39.2)(tsx@4.19.4)(yaml@2.9.0)
vite: 8.0.13(@types/node@24.10.4)(esbuild@0.27.3)(jiti@2.7.0)(terser@5.39.2)(tsx@4.19.4)(yaml@2.9.0)
transitivePeerDependencies:
- '@types/node'
- rollup
- supports-color
vite-plugin-html@3.2.2(vite@8.0.13(@types/node@24.10.4)(esbuild@0.27.3)(jiti@2.6.1)(terser@5.39.2)(tsx@4.19.4)(yaml@2.9.0)):
vite-plugin-html@3.2.2(vite@8.0.13(@types/node@24.10.4)(esbuild@0.27.3)(jiti@2.7.0)(terser@5.39.2)(tsx@4.19.4)(yaml@2.9.0)):
dependencies:
'@rollup/pluginutils': 4.2.1
colorette: 2.0.20
@@ -17290,7 +17347,7 @@ snapshots:
html-minifier-terser: 6.1.0
node-html-parser: 5.4.2
pathe: 0.2.0
vite: 8.0.13(@types/node@24.10.4)(esbuild@0.27.3)(jiti@2.6.1)(terser@5.39.2)(tsx@4.19.4)(yaml@2.9.0)
vite: 8.0.13(@types/node@24.10.4)(esbuild@0.27.3)(jiti@2.7.0)(terser@5.39.2)(tsx@4.19.4)(yaml@2.9.0)
vite-plugin-html@3.2.2(vite@8.0.13(@types/node@25.0.3)(esbuild@0.27.3)(jiti@2.7.0)(terser@5.39.2)(tsx@4.19.4)(yaml@2.9.0)):
dependencies:
@@ -17308,7 +17365,7 @@ snapshots:
pathe: 0.2.0
vite: 8.0.13(@types/node@25.0.3)(esbuild@0.27.3)(jiti@2.7.0)(terser@5.39.2)(tsx@4.19.4)(yaml@2.9.0)
vite-plugin-inspect@11.3.3(vite@8.0.13(@types/node@24.10.4)(esbuild@0.27.3)(jiti@2.6.1)(terser@5.39.2)(tsx@4.19.4)(yaml@2.9.0)):
vite-plugin-inspect@11.3.3(vite@8.0.13(@types/node@24.10.4)(esbuild@0.27.3)(jiti@2.7.0)(terser@5.39.2)(tsx@4.19.4)(yaml@2.9.0)):
dependencies:
ansis: 4.2.0
debug: 4.4.3
@@ -17318,8 +17375,8 @@ snapshots:
perfect-debounce: 2.0.0
sirv: 3.0.2
unplugin-utils: 0.3.1
vite: 8.0.13(@types/node@24.10.4)(esbuild@0.27.3)(jiti@2.6.1)(terser@5.39.2)(tsx@4.19.4)(yaml@2.9.0)
vite-dev-rpc: 1.1.0(vite@8.0.13(@types/node@24.10.4)(esbuild@0.27.3)(jiti@2.6.1)(terser@5.39.2)(tsx@4.19.4)(yaml@2.9.0))
vite: 8.0.13(@types/node@24.10.4)(esbuild@0.27.3)(jiti@2.7.0)(terser@5.39.2)(tsx@4.19.4)(yaml@2.9.0)
vite-dev-rpc: 1.1.0(vite@8.0.13(@types/node@24.10.4)(esbuild@0.27.3)(jiti@2.7.0)(terser@5.39.2)(tsx@4.19.4)(yaml@2.9.0))
transitivePeerDependencies:
- supports-color
@@ -17338,15 +17395,15 @@ snapshots:
transitivePeerDependencies:
- supports-color
vite-plugin-vue-devtools@8.0.5(vite@8.0.13(@types/node@24.10.4)(esbuild@0.27.3)(jiti@2.6.1)(terser@5.39.2)(tsx@4.19.4)(yaml@2.9.0))(vue@3.5.34(typescript@5.9.3)):
vite-plugin-vue-devtools@8.0.5(vite@8.0.13(@types/node@24.10.4)(esbuild@0.27.3)(jiti@2.7.0)(terser@5.39.2)(tsx@4.19.4)(yaml@2.9.0))(vue@3.5.34(typescript@5.9.3)):
dependencies:
'@vue/devtools-core': 8.0.5(vite@8.0.13(@types/node@24.10.4)(esbuild@0.27.3)(jiti@2.6.1)(terser@5.39.2)(tsx@4.19.4)(yaml@2.9.0))(vue@3.5.34(typescript@5.9.3))
'@vue/devtools-core': 8.0.5(vite@8.0.13(@types/node@24.10.4)(esbuild@0.27.3)(jiti@2.7.0)(terser@5.39.2)(tsx@4.19.4)(yaml@2.9.0))(vue@3.5.34(typescript@5.9.3))
'@vue/devtools-kit': 8.0.5
'@vue/devtools-shared': 8.0.5
sirv: 3.0.2
vite: 8.0.13(@types/node@24.10.4)(esbuild@0.27.3)(jiti@2.6.1)(terser@5.39.2)(tsx@4.19.4)(yaml@2.9.0)
vite-plugin-inspect: 11.3.3(vite@8.0.13(@types/node@24.10.4)(esbuild@0.27.3)(jiti@2.6.1)(terser@5.39.2)(tsx@4.19.4)(yaml@2.9.0))
vite-plugin-vue-inspector: 5.3.2(vite@8.0.13(@types/node@24.10.4)(esbuild@0.27.3)(jiti@2.6.1)(terser@5.39.2)(tsx@4.19.4)(yaml@2.9.0))
vite: 8.0.13(@types/node@24.10.4)(esbuild@0.27.3)(jiti@2.7.0)(terser@5.39.2)(tsx@4.19.4)(yaml@2.9.0)
vite-plugin-inspect: 11.3.3(vite@8.0.13(@types/node@24.10.4)(esbuild@0.27.3)(jiti@2.7.0)(terser@5.39.2)(tsx@4.19.4)(yaml@2.9.0))
vite-plugin-vue-inspector: 5.3.2(vite@8.0.13(@types/node@24.10.4)(esbuild@0.27.3)(jiti@2.7.0)(terser@5.39.2)(tsx@4.19.4)(yaml@2.9.0))
transitivePeerDependencies:
- '@nuxt/kit'
- supports-color
@@ -17380,7 +17437,7 @@ snapshots:
- supports-color
- vue
vite-plugin-vue-inspector@5.3.2(vite@8.0.13(@types/node@24.10.4)(esbuild@0.27.3)(jiti@2.6.1)(terser@5.39.2)(tsx@4.19.4)(yaml@2.9.0)):
vite-plugin-vue-inspector@5.3.2(vite@8.0.13(@types/node@24.10.4)(esbuild@0.27.3)(jiti@2.7.0)(terser@5.39.2)(tsx@4.19.4)(yaml@2.9.0)):
dependencies:
'@babel/core': 7.29.0
'@babel/plugin-proposal-decorators': 7.29.0(@babel/core@7.29.0)
@@ -17391,7 +17448,7 @@ snapshots:
'@vue/compiler-dom': 3.5.34
kolorist: 1.8.0
magic-string: 0.30.21
vite: 8.0.13(@types/node@24.10.4)(esbuild@0.27.3)(jiti@2.6.1)(terser@5.39.2)(tsx@4.19.4)(yaml@2.9.0)
vite: 8.0.13(@types/node@24.10.4)(esbuild@0.27.3)(jiti@2.7.0)(terser@5.39.2)(tsx@4.19.4)(yaml@2.9.0)
transitivePeerDependencies:
- supports-color
@@ -17425,7 +17482,7 @@ snapshots:
transitivePeerDependencies:
- supports-color
vite@8.0.13(@types/node@24.10.4)(esbuild@0.27.3)(jiti@2.6.1)(terser@5.39.2)(tsx@4.19.4)(yaml@2.9.0):
vite@8.0.13(@types/node@24.10.4)(esbuild@0.27.3)(jiti@2.7.0)(terser@5.39.2)(tsx@4.19.4)(yaml@2.9.0):
dependencies:
lightningcss: 1.32.0
picomatch: 4.0.4
@@ -17436,7 +17493,7 @@ snapshots:
'@types/node': 24.10.4
esbuild: 0.27.3
fsevents: 2.3.3
jiti: 2.6.1
jiti: 2.7.0
terser: 5.39.2
tsx: 4.19.4
yaml: 2.9.0
@@ -17461,10 +17518,10 @@ snapshots:
optionalDependencies:
vite: 8.0.13(@types/node@25.0.3)(esbuild@0.27.3)(jiti@2.7.0)(terser@5.39.2)(tsx@4.19.4)(yaml@2.9.0)
vitest@4.1.8(@opentelemetry/api@1.9.0)(@types/node@24.10.4)(@vitest/coverage-v8@4.0.16)(@vitest/ui@4.0.16)(happy-dom@20.9.0)(jsdom@27.4.0)(vite@8.0.13(@types/node@24.10.4)(esbuild@0.27.3)(jiti@2.6.1)(terser@5.39.2)(tsx@4.19.4)(yaml@2.9.0)):
vitest@4.1.8(@opentelemetry/api@1.9.0)(@types/node@24.10.4)(@vitest/coverage-v8@4.0.16)(@vitest/ui@4.0.16)(happy-dom@20.9.0)(jsdom@27.4.0)(vite@8.0.13(@types/node@24.10.4)(esbuild@0.27.3)(jiti@2.7.0)(terser@5.39.2)(tsx@4.19.4)(yaml@2.9.0)):
dependencies:
'@vitest/expect': 4.1.8
'@vitest/mocker': 4.1.8(vite@8.0.13(@types/node@24.10.4)(esbuild@0.27.3)(jiti@2.6.1)(terser@5.39.2)(tsx@4.19.4)(yaml@2.9.0))
'@vitest/mocker': 4.1.8(vite@8.0.13(@types/node@24.10.4)(esbuild@0.27.3)(jiti@2.7.0)(terser@5.39.2)(tsx@4.19.4)(yaml@2.9.0))
'@vitest/pretty-format': 4.1.8
'@vitest/runner': 4.1.8
'@vitest/snapshot': 4.1.8
@@ -17481,7 +17538,7 @@ snapshots:
tinyexec: 1.0.4
tinyglobby: 0.2.16
tinyrainbow: 3.1.0
vite: 8.0.13(@types/node@24.10.4)(esbuild@0.27.3)(jiti@2.6.1)(terser@5.39.2)(tsx@4.19.4)(yaml@2.9.0)
vite: 8.0.13(@types/node@24.10.4)(esbuild@0.27.3)(jiti@2.7.0)(terser@5.39.2)(tsx@4.19.4)(yaml@2.9.0)
why-is-node-running: 2.3.0
optionalDependencies:
'@opentelemetry/api': 1.9.0
@@ -17659,10 +17716,10 @@ snapshots:
vue: 3.5.34(typescript@5.9.3)
vue-inbrowser-compiler-independent-utils: 4.71.1(vue@3.5.34(typescript@5.9.3))
vue-eslint-parser@10.4.0(eslint@10.4.0(jiti@2.6.1)):
vue-eslint-parser@10.4.0(eslint@10.4.0(jiti@2.7.0)):
dependencies:
debug: 4.4.3
eslint: 10.4.0(jiti@2.6.1)
eslint: 10.4.0(jiti@2.7.0)
eslint-scope: 9.1.2
eslint-visitor-keys: 5.0.1
espree: 11.2.0

View File

@@ -28,12 +28,9 @@ catalog:
'@lucide/vue': ^1.17.0
'@pinia/testing': ^1.0.3
'@playwright/test': ^1.58.1
'@primeuix/forms': 0.0.2
'@primeuix/styled': 0.3.2
'@primeuix/utils': ^0.3.2
'@primevue/core': ^4.2.5
'@primevue/forms': ^4.2.5
'@primevue/icons': 4.2.5
'@primevue/themes': ^4.2.5
'@sentry/vite-plugin': ^4.6.0
'@sentry/vue': ^10.32.1
@@ -88,6 +85,7 @@ catalog:
eslint-plugin-testing-library: ^7.16.1
eslint-plugin-unused-imports: ^4.4.1
eslint-plugin-vue: ^10.9.1
fallow: ^2.102.0
fast-check: ^4.5.3
firebase: ^11.6.0
glob: ^13.0.6
@@ -95,7 +93,6 @@ catalog:
gsap: ^3.14.2
happy-dom: ^20.8.9
husky: ^9.1.7
jiti: 2.6.1
jsdom: ^27.4.0
jsonata: ^2.1.0
knip: ^6.15.0
@@ -166,7 +163,6 @@ allowBuilds:
overrides:
vite: 'catalog:'
'@tiptap/pm': 2.27.2
'@types/eslint': '-'
# Security overrides
lodash: ^4.18.0
yaml: ^2.8.3

View File

@@ -113,13 +113,3 @@ export const formatUsdFromCents = ({
locale,
numberOptions
})
/**
* Clamps a USD value to the allowed range for credit purchases
* @param value - The USD amount to clamp
* @returns The clamped value between $1 and $1000, or 0 if NaN
*/
export const clampUsd = (value: number): number => {
if (Number.isNaN(value)) return 0
return Math.min(1000, Math.max(1, value))
}

View File

@@ -23,7 +23,6 @@ vi.mock('@/scripts/app', () => ({
vi.mock('@/utils/graphTraversalUtil', () => ({
getNodeByExecutionId: vi.fn(),
getRootParentNode: vi.fn(() => null),
forEachNode: vi.fn(),
mapAllNodes: vi.fn(() => [])
}))

View File

@@ -17,7 +17,6 @@ vi.mock('@/scripts/app', () => ({
vi.mock('@/utils/graphTraversalUtil', () => ({
getNodeByExecutionId: vi.fn(),
getExecutionIdByNode: vi.fn(),
getRootParentNode: vi.fn(() => null),
forEachNode: vi.fn(),
mapAllNodes: vi.fn(() => [])
}))

View File

@@ -17,7 +17,6 @@ vi.mock('@/scripts/app', () => ({
vi.mock('@/utils/graphTraversalUtil', () => ({
getNodeByExecutionId: vi.fn(),
getExecutionIdByNode: vi.fn(),
getRootParentNode: vi.fn(() => null),
forEachNode: vi.fn(),
mapAllNodes: vi.fn(() => [])
}))

View File

@@ -51,10 +51,6 @@ export type OAuthConsentDecisionParams = {
expectedRedirectUri?: string
}
export type OAuthConsentDecision = (
params: OAuthConsentDecisionParams
) => Promise<void>
// Schemes that execute in our origin if navigated. Never navigable,
// regardless of what the backend returns. Everything else is governed
// by binding to the challenge's registered redirect_uri — no per-client

View File

@@ -1,110 +0,0 @@
import type { Meta, StoryObj } from '@storybook/vue3-vite'
import { ref } from 'vue'
import CreditSlider from './CreditSlider.vue'
const meta: Meta<typeof CreditSlider> = {
title: 'Platform/Subscription/CreditSlider',
component: CreditSlider,
tags: ['autodocs'],
parameters: { layout: 'centered' },
argTypes: {
disabled: { control: 'boolean' }
},
args: {
disabled: false
},
decorators: [
(story) => ({
components: { story },
// Previews at the real layout width: the Figma "Team Plan" card column is
// 512px wide with 32px padding (DES-197), i.e. a 448px content area — the
// width the slider actually renders into inside PricingTableWorkspace.
template: '<div class="w-[512px] px-8"><story /></div>'
})
]
}
export default meta
type Story = StoryObj<typeof meta>
export const Default: Story = {
render: (args) => ({
components: { CreditSlider },
setup() {
const value = ref(700)
return { args, value }
},
template: '<CreditSlider v-model="value" :disabled="args.disabled" />'
})
}
export const Disabled: Story = {
args: { disabled: true },
render: (args) => ({
components: { CreditSlider },
setup() {
const value = ref(700)
return { args, value }
},
template: '<CreditSlider v-model="value" :disabled="args.disabled" />'
})
}
// Sample `GET /api/billing/plans → team_credit_stops` payload (DES-197 yearly).
// In production this comes from the API; here it shows the stops being driven
// entirely through props rather than the hardcoded default constant.
const apiTeamCreditStops = {
default_stop_index: 2,
stops: [
{
id: 'team_200',
credits: 42_200,
yearly: { price_cents: 20_000, discount_percent: 0 }
},
{
id: 'team_400',
credits: 84_400,
yearly: { price_cents: 38_000, discount_percent: 5 }
},
{
id: 'team_700',
credits: 147_700,
yearly: { price_cents: 63_000, discount_percent: 10 }
},
{
id: 'team_1400',
credits: 295_400,
yearly: { price_cents: 119_000, discount_percent: 15 }
},
{
id: 'team_2500',
credits: 527_500,
yearly: { price_cents: 200_000, discount_percent: 20 }
}
]
}
// Reference adapter (FE-934 will own this in the data layer): API → CreditStop[].
// The pre-discount list price is recovered as discounted / (1 - discount).
const mappedStops = apiTeamCreditStops.stops.map((s) => ({
credits: s.credits,
discountPercentYearly: s.yearly.discount_percent,
usd: Math.round(
s.yearly.price_cents / 100 / (1 - s.yearly.discount_percent / 100)
)
}))
export const BackendDrivenStops: Story = {
name: 'Backend-driven stops (props)',
render: (args) => ({
components: { CreditSlider },
setup() {
const defaultStopIndex = apiTeamCreditStops.default_stop_index
const value = ref(mappedStops[defaultStopIndex].usd)
return { args, value, mappedStops, defaultStopIndex }
},
template:
'<CreditSlider v-model="value" :stops="mappedStops" :default-stop-index="defaultStopIndex" :disabled="args.disabled" />'
})
}

View File

@@ -1,189 +0,0 @@
import { render, screen, within } from '@testing-library/vue'
import userEvent from '@testing-library/user-event'
import { describe, expect, it, vi } from 'vitest'
import { nextTick } from 'vue'
import { createI18n } from 'vue-i18n'
import { usdToCredits } from '@/base/credits/comfyCredits'
import { TEAM_PLAN_CREDIT_STOPS } from '@/platform/cloud/subscription/constants/teamPlanCreditStops'
import CreditSlider from './CreditSlider.vue'
const i18n = createI18n({
legacy: false,
locale: 'en',
messages: {
en: {
subscription: {
usdPerMonth: 'USD / mo',
billedYearly: '{total} Billed yearly',
creditSliderSave: 'Save {percent}% ({amount})'
}
}
}
})
function renderSlider(props: Record<string, unknown> = {}) {
return render(CreditSlider, { props, global: { plugins: [i18n] } })
}
async function flush() {
await nextTick()
await nextTick()
}
describe('CreditSlider', () => {
it('defaults to the $700 stop (index 2) when no value is bound', async () => {
renderSlider()
await flush()
const thumb = screen.getByRole('slider')
expect(thumb).toHaveAttribute('aria-valuemin', '0')
expect(thumb).toHaveAttribute('aria-valuemax', '4')
expect(thumb).toHaveAttribute('aria-valuenow', '2')
})
it('snaps to the next fixed stop on ArrowRight (never a value in between)', async () => {
const user = userEvent.setup()
const onUpdate = vi.fn<(usd: number) => void>()
renderSlider({ modelValue: 700, 'onUpdate:modelValue': onUpdate })
await flush()
screen.getByRole('slider').focus()
await user.keyboard('{ArrowRight}')
expect(onUpdate).toHaveBeenCalledWith(1400)
})
it('snaps to the previous fixed stop on ArrowLeft', async () => {
const user = userEvent.setup()
const onUpdate = vi.fn<(usd: number) => void>()
renderSlider({ modelValue: 700, 'onUpdate:modelValue': onUpdate })
await flush()
screen.getByRole('slider').focus()
await user.keyboard('{ArrowLeft}')
expect(onUpdate).toHaveBeenCalledWith(400)
})
it('emits change with the full {index, usd, credits} payload', async () => {
const user = userEvent.setup()
const onChange = vi.fn()
renderSlider({ modelValue: 700, onChange })
await flush()
screen.getByRole('slider').focus()
await user.keyboard('{ArrowRight}')
expect(onChange).toHaveBeenCalledWith({
index: 3,
usd: 1400,
credits: 295_400
})
})
it('emits nothing when disabled (keyboard interaction suppressed)', async () => {
const user = userEvent.setup()
const onUpdate = vi.fn<(usd: number) => void>()
const onChange = vi.fn()
renderSlider({
modelValue: 700,
disabled: true,
'onUpdate:modelValue': onUpdate,
onChange
})
await flush()
screen.getByRole('slider').focus()
await user.keyboard('{ArrowRight}')
expect(onUpdate).not.toHaveBeenCalled()
expect(onChange).not.toHaveBeenCalled()
})
it('shows the discounted price, struck original, save badge and yearly total (DES-197)', async () => {
renderSlider() // default $700 stop → 10% yearly discount
await flush()
expect(screen.getByTestId('credit-slider-price')).toHaveTextContent('$630')
expect(
screen.getByTestId('credit-slider-original-price')
).toHaveTextContent('$700')
expect(screen.getByTestId('credit-slider-save')).toHaveTextContent(
'Save 10% ($70)'
)
expect(screen.getByTestId('credit-slider-billed-yearly')).toHaveTextContent(
'$7,560'
)
})
it('hides the discount UI at the 0% stop ($200)', async () => {
renderSlider({ modelValue: 200 })
await flush()
expect(screen.getByTestId('credit-slider-price')).toHaveTextContent('$200')
expect(
screen.queryByTestId('credit-slider-original-price')
).not.toBeInTheDocument()
expect(screen.queryByTestId('credit-slider-save')).not.toBeInTheDocument()
})
it('renders all five fixed credit stop labels', async () => {
renderSlider({ modelValue: 700 })
await flush()
const stops = within(screen.getByTestId('credit-slider-stops'))
for (const label of ['42.2K', '84.4K', '147.7K', '295.4K', '527.5K']) {
expect(stops.getByText(label)).toBeInTheDocument()
}
})
it('renders nothing when stops is empty (defensive for BE-sourced data)', async () => {
renderSlider({ stops: [] })
await flush()
expect(screen.queryByRole('slider')).not.toBeInTheDocument()
expect(screen.queryByTestId('credit-slider-price')).not.toBeInTheDocument()
})
it('renders stops + default index supplied via props (BE-sourced override)', async () => {
const stops = [
{ usd: 50, credits: 10_550, discountPercentYearly: 0 },
{ usd: 100, credits: 21_100, discountPercentYearly: 25 }
]
// No modelValue → the model default ($700) matches no stop, so selectedIndex
// falls back to defaultStopIndex (here index 1 → $100).
renderSlider({ stops, defaultStopIndex: 1 })
await flush()
const thumb = screen.getByRole('slider')
expect(thumb).toHaveAttribute('aria-valuemax', '1') // 2 stops → max index 1
expect(thumb).toHaveAttribute('aria-valuenow', '1') // default index honored
// index 1 → $100 at 25% yearly → $75 discounted, struck $100, save $25
expect(screen.getByTestId('credit-slider-price')).toHaveTextContent('$75')
expect(
screen.getByTestId('credit-slider-original-price')
).toHaveTextContent('$100')
expect(screen.getByTestId('credit-slider-save')).toHaveTextContent(
'Save 25% ($25)'
)
// Only the prop's labels render — none of the DES-197 defaults.
const labels = within(screen.getByTestId('credit-slider-stops'))
expect(labels.getByText('10.6K')).toBeInTheDocument()
expect(labels.getByText('21.1K')).toBeInTheDocument()
expect(labels.queryByText('147.7K')).not.toBeInTheDocument()
})
it('keeps every credit amount equal to usdToCredits(usd) (guards rate drift)', () => {
for (const stop of TEAM_PLAN_CREDIT_STOPS) {
expect(stop.credits).toBe(usdToCredits(stop.usd))
}
})
})

View File

@@ -1,228 +0,0 @@
<script setup lang="ts">
import {
TransitionPresets,
usePreferredReducedMotion,
useTransition
} from '@vueuse/core'
import { computed } from 'vue'
import type { HTMLAttributes } from 'vue'
import { useI18n } from 'vue-i18n'
import { cn } from '@comfyorg/tailwind-utils'
import Slider from '@/components/ui/slider/Slider.vue'
import {
DEFAULT_TEAM_PLAN_STOP_INDEX,
TEAM_PLAN_CREDIT_STOPS
} from '@/platform/cloud/subscription/constants/teamPlanCreditStops'
import type { CreditStop } from '@/platform/cloud/subscription/constants/teamPlanCreditStops'
const {
disabled = false,
class: rootClass,
stops = TEAM_PLAN_CREDIT_STOPS,
defaultStopIndex = DEFAULT_TEAM_PLAN_STOP_INDEX
} = defineProps<{
disabled?: boolean
class?: HTMLAttributes['class']
/**
* The fixed credit stops the slider snaps to; when empty, the component
* renders nothing. Defaults to the hardcoded DES-197 set; pass the
* backend-sourced stops once the contract lands — map
* `GET /api/billing/plans → team_credit_stops.stops` to `CreditStop[]`
* (credits, the pre-discount `usd`, and `discountPercentYearly`).
*/
stops?: readonly CreditStop[]
/**
* Stop selected when the bound value matches none (e.g. first render).
* Maps to `team_credit_stops.default_stop_index`. Defaults to DES-197 ($700).
*/
defaultStopIndex?: number
}>()
const emit = defineEmits<{
/** Fired when the selected stop changes, with the full derived payload. */
change: [stop: { index: number; usd: number; credits: number }]
}>()
/**
* v-model carries the selected USD value (one of the `stops`). The literal
* default keeps `defineModel` statically analyzable; when custom `stops` are
* passed without a matching v-model, `selectedIndex` falls back to
* `defaultStopIndex`, so the displayed stop is still correct.
*/
const usd = defineModel<number>({
default: TEAM_PLAN_CREDIT_STOPS[DEFAULT_TEAM_PLAN_STOP_INDEX].usd
})
const selectedIndex = computed(() => {
const i = stops.findIndex((stop) => stop.usd === usd.value)
if (i !== -1) return i
// Fall back to the default stop, clamped into range: a backend-driven `stops`
// array can be shorter than expected (or `defaultStopIndex` out of bounds).
return Math.min(Math.max(defaultStopIndex, 0), Math.max(stops.length - 1, 0))
})
// Zero-stop fallback: `useTransition` reads its source eagerly at setup, so an
// empty `stops` must not crash even though the template then renders nothing.
const EMPTY_STOP: CreditStop = { usd: 0, credits: 0, discountPercentYearly: 0 }
const current = computed(() => stops.at(selectedIndex.value) ?? EMPTY_STOP)
// Yearly commitment (per DES-197): the discount applies to the monthly figure.
// The card shows the discounted monthly price, the struck pre-discount price,
// the saving, and the annual total.
const discountedMonthly = computed(() =>
Math.round(
current.value.usd * (1 - current.value.discountPercentYearly / 100)
)
)
const saveAmount = computed(() => current.value.usd - discountedMonthly.value)
const hasDiscount = computed(() => current.value.discountPercentYearly > 0)
/**
* Smoothly count the price figures up/down as the slider moves between stops
* instead of snapping. Honors the user's reduced-motion preference. The save
* badge ("X% ($Y)") is intentionally left snapping — its percent is a discrete
* tier, so animating the bracketed amount alone would read inconsistently.
*/
const prefersReducedMotion = usePreferredReducedMotion()
const priceTween = {
duration: 350,
easing: TransitionPresets.easeOutCubic,
disabled: computed(() => prefersReducedMotion.value === 'reduce')
}
// One vector tween keeps both figures in phase. Deriving the monthly from the
// animated original instead would jump at the start of each move: the discount
// tier snaps per stop while the base price is still mid-tween.
const animatedPrices = useTransition(
() => [discountedMonthly.value, current.value.usd],
priceTween
)
const displayMonthly = computed(() => Math.round(animatedPrices.value[0]))
const displayOriginal = computed(() => Math.round(animatedPrices.value[1]))
// Derive the yearly total from the displayed monthly so it always reads as
// exactly 12× the price shown — even mid-count — rather than drifting as a
// second, independently-phased tween would.
const displayBilledYearly = computed(() => displayMonthly.value * 12)
/**
* Bridge the discrete stop index (0..n-1) to the reka-ui slider's `number[]`
* model. Driving the slider in index space with `step = 1` guarantees the
* thumb can only land on the fixed stops — never a value in between.
*/
const sliderModel = computed<number[]>({
get: () => [selectedIndex.value],
set: ([index]) => {
const stop = stops[index]
if (!stop) return
usd.value = stop.usd
emit('change', { index, usd: stop.usd, credits: stop.credits })
}
})
const lastIndex = computed(() => Math.max(stops.length - 1, 0))
const formatUsd = (value: number) => `$${value.toLocaleString('en-US')}`
const formatCreditsCompact = (value: number) =>
new Intl.NumberFormat('en-US', {
notation: 'compact',
maximumFractionDigits: 1
}).format(value)
const { t } = useI18n()
</script>
<template>
<div
v-if="stops.length > 0"
:class="cn('flex w-full flex-col gap-3', rootClass)"
>
<!-- Price: discounted monthly + struck pre-discount + save badge -->
<div class="flex flex-col gap-1">
<div class="flex flex-wrap items-center gap-x-2 gap-y-1">
<span class="flex shrink-0 items-baseline gap-1.5 whitespace-nowrap">
<span
class="text-[2rem]/none font-semibold text-base-foreground"
data-testid="credit-slider-price"
>
{{ formatUsd(displayMonthly) }}
</span>
<span
v-if="hasDiscount"
class="text-base text-muted-foreground line-through"
data-testid="credit-slider-original-price"
>
{{ formatUsd(displayOriginal) }}
</span>
<span class="text-base text-muted-foreground">
{{ t('subscription.usdPerMonth') }}
</span>
</span>
<!-- Save badge: outlined primary pill, pushed to the right (DES-197) -->
<span
v-if="hasDiscount"
data-testid="credit-slider-save"
class="ms-auto shrink-0 rounded-full border-2 border-primary-background px-2 py-1 text-sm font-bold whitespace-nowrap text-primary-background"
>
{{
t('subscription.creditSliderSave', {
percent: current.discountPercentYearly,
amount: formatUsd(saveAmount)
})
}}
</span>
</div>
<p
class="m-0 text-sm text-muted-foreground"
data-testid="credit-slider-billed-yearly"
>
{{
t('subscription.billedYearly', {
total: formatUsd(displayBilledYearly)
})
}}
</p>
</div>
<!-- Discrete slider: snaps to the 5 fixed DES-197 stops -->
<Slider
v-model="sliderModel"
:min="0"
:max="lastIndex"
:step="1"
:disabled="disabled"
/>
<!-- Credit stop labels; the selected stop is emphasized -->
<ol
data-testid="credit-slider-stops"
class="m-0 flex list-none justify-between p-0"
>
<li
v-for="(stop, i) in stops"
:key="stop.usd"
:data-selected="i === selectedIndex ? '' : undefined"
:class="
cn(
'flex items-center gap-1 text-xs',
i === selectedIndex
? 'font-semibold text-base-foreground'
: 'text-muted-foreground'
)
"
>
<i
:class="
cn(
'icon-[comfy--credits] size-3 shrink-0',
i === selectedIndex ? 'bg-amber-400' : 'bg-muted-foreground'
)
"
aria-hidden="true"
/>
{{ formatCreditsCompact(stop.credits) }}
</li>
</ol>
</div>
</template>

View File

@@ -308,31 +308,6 @@ export function findSubgraphPathById(
return null
}
/**
* Gets the root parent node associated with a hierarchical execution ID.
* Both Group Nodes and Subgraph Nodes use hierarchical IDs (e.g. "rootId:childId:...").
* The root parent is always located in the rootGraph.
*
* @param rootGraph - The root graph to search from
* @param executionId - The execution ID (e.g., "123:456")
* @returns The root parent node if found, null otherwise
*/
export function getRootParentNode(
rootGraph: LGraph,
executionId: string
): LGraphNode | null {
const parts = parseExecutionId(executionId)
if (!parts || parts.length < 2) return null
const parentId = parts[0]
if (!rootGraph) return null
const localParentId = parseNodeId(parentId)
if (!localParentId) return null
return rootGraph.getNodeById(localParentId) || null
}
/**
* Get a node by its execution ID from anywhere in the graph hierarchy.
* Execution IDs use hierarchical format like "123:456:789" for nested nodes.

View File

@@ -18,7 +18,7 @@ const MEDIA_SRC_REGEX =
/(<(?:img|source|video)[^>]*\ssrc=['"])(?!(?:\/|https?:\/\/))([^'"\s>]+)(['"])/gi
// Create a marked Renderer that prefixes relative URLs with base
export function createMarkdownRenderer(baseUrl?: string): Renderer {
function createMarkdownRenderer(baseUrl?: string): Renderer {
const normalizedBase = baseUrl ? baseUrl.replace(/\/+$/, '') : ''
const renderer = new Renderer()
renderer.image = ({ href, title, text }) => {