diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 00000000..46722366 --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,131 @@ +name: CI + +on: + push: + branches: [main, development] + pull_request: + branches: [main, development] + +jobs: + lint-typecheck: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: pnpm/action-setup@v4 + with: + version: 10 + - uses: actions/setup-node@v4 + with: + node-version: 20 + cache: pnpm + - run: pnpm install --frozen-lockfile + - run: pnpm typecheck + - run: pnpm lint + + test: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: pnpm/action-setup@v4 + with: + version: 10 + - uses: actions/setup-node@v4 + with: + node-version: 20 + cache: pnpm + - run: pnpm install --frozen-lockfile + - run: pnpm test + + bundle-size: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: pnpm/action-setup@v4 + with: + version: 10 + - uses: actions/setup-node@v4 + with: + node-version: 20 + cache: pnpm + - run: pnpm install --frozen-lockfile + - run: pnpm build + - name: Check bundle size + run: | + BUNDLE_SIZE=$(find packages/app/dist/assets -name '*.js' -o -name '*.css' | xargs gzip -c | wc -c) + BUNDLE_KB=$((BUNDLE_SIZE / 1024)) + echo "Bundle size: ${BUNDLE_KB}KB gzipped" + if [ "$BUNDLE_KB" -gt 250 ]; then + echo "::error::Bundle size ${BUNDLE_KB}KB exceeds 250KB budget" + exit 1 + fi + echo "Bundle size ${BUNDLE_KB}KB is within 250KB budget" + + e2e: + runs-on: ubuntu-latest + strategy: + matrix: + browser: [chromium, firefox, webkit] + steps: + - uses: actions/checkout@v4 + - uses: pnpm/action-setup@v4 + with: + version: 10 + - uses: actions/setup-node@v4 + with: + node-version: 20 + cache: pnpm + - run: pnpm install --frozen-lockfile + - run: cd packages/app && npx playwright install --with-deps ${{ matrix.browser }} + - run: cd packages/app && pnpm test:e2e --project=${{ matrix.browser }} + + e2e-mobile: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: pnpm/action-setup@v4 + with: + version: 10 + - uses: actions/setup-node@v4 + with: + node-version: 20 + cache: pnpm + - run: pnpm install --frozen-lockfile + - run: cd packages/app && npx playwright install --with-deps chromium webkit + - run: cd packages/app && pnpm test:e2e --project=iphone14 --project=galaxy-s21 + + lighthouse: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: pnpm/action-setup@v4 + with: + version: 10 + - uses: actions/setup-node@v4 + with: + node-version: 20 + cache: pnpm + - run: pnpm install --frozen-lockfile + - run: pnpm build + - name: Run Lighthouse + uses: treosh/lighthouse-ci-action@v12 + with: + configPath: packages/app/lighthouserc.json + uploadArtifacts: true + + dependency-audit: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: pnpm/action-setup@v4 + with: + version: 10 + - uses: actions/setup-node@v4 + with: + node-version: 20 + cache: pnpm + - run: pnpm install --frozen-lockfile + - name: Audit dependencies + run: pnpm audit --audit-level=critical || true + - name: Check licenses + run: | + npx license-checker --production --onlyAllow 'MIT;Apache-2.0;ISC;BSD-2-Clause;BSD-3-Clause;0BSD;CC0-1.0;Unlicense;CC-BY-4.0;Python-2.0;BlueOak-1.0.0' --excludePrivatePackages || echo "::warning::Non-approved licenses found" diff --git a/.github/workflows/dependency-audit.yml b/.github/workflows/dependency-audit.yml new file mode 100644 index 00000000..b6cbcc56 --- /dev/null +++ b/.github/workflows/dependency-audit.yml @@ -0,0 +1,57 @@ +name: Weekly Dependency Audit + +on: + schedule: + - cron: '0 9 * * 1' # Every Monday at 9am UTC + workflow_dispatch: + +jobs: + audit: + runs-on: ubuntu-latest + permissions: + issues: write + steps: + - uses: actions/checkout@v4 + - uses: pnpm/action-setup@v4 + with: + version: 10 + - uses: actions/setup-node@v4 + with: + node-version: 20 + cache: pnpm + - run: pnpm install --frozen-lockfile + + - name: Audit for vulnerabilities + id: audit + run: | + AUDIT_RESULT=$(pnpm audit --audit-level=moderate 2>&1) || true + echo "$AUDIT_RESULT" + if echo "$AUDIT_RESULT" | grep -q "critical"; then + echo "has_critical=true" >> $GITHUB_OUTPUT + else + echo "has_critical=false" >> $GITHUB_OUTPUT + fi + + - name: Check licenses + id: licenses + run: | + LICENSE_RESULT=$(npx license-checker --production --onlyAllow 'MIT;Apache-2.0;ISC;BSD-2-Clause;BSD-3-Clause;0BSD;CC0-1.0;Unlicense;CC-BY-4.0;Python-2.0;BlueOak-1.0.0' --excludePrivatePackages 2>&1) || true + echo "$LICENSE_RESULT" + if echo "$LICENSE_RESULT" | grep -q "FAIL"; then + echo "has_violations=true" >> $GITHUB_OUTPUT + else + echo "has_violations=false" >> $GITHUB_OUTPUT + fi + + - name: Create issue if violations found + if: steps.audit.outputs.has_critical == 'true' || steps.licenses.outputs.has_violations == 'true' + uses: actions/github-script@v7 + with: + script: | + await github.rest.issues.create({ + owner: context.repo.owner, + repo: context.repo.repo, + title: '⚠️ Dependency audit: violations found', + body: `The weekly dependency audit found issues:\n\n- Critical vulnerabilities: ${{ steps.audit.outputs.has_critical }}\n- License violations: ${{ steps.licenses.outputs.has_violations }}\n\nRun \`pnpm audit\` and \`npx license-checker\` locally for details.`, + labels: ['security', 'dependencies'], + }) diff --git a/packages/app/.storybook/main.ts b/packages/app/.storybook/main.ts new file mode 100644 index 00000000..ac31dc31 --- /dev/null +++ b/packages/app/.storybook/main.ts @@ -0,0 +1,21 @@ +import type { StorybookConfig } from '@storybook/vue3-vite' + +const config: StorybookConfig = { + stories: ['../src/**/__stories__/*.stories.ts'], + framework: { + name: '@storybook/vue3-vite', + options: {}, + }, + addons: ['@storybook/addon-essentials'], + viteFinal(config) { + config.resolve ??= {} + config.resolve.alias ??= {} + // Match app aliases + const alias = config.resolve.alias as Record + alias['@'] = new URL('../src', import.meta.url).pathname + alias['@aiui/core'] = new URL('../../core/src', import.meta.url).pathname + return config + }, +} + +export default config diff --git a/packages/app/.storybook/preview.ts b/packages/app/.storybook/preview.ts new file mode 100644 index 00000000..a31267c1 --- /dev/null +++ b/packages/app/.storybook/preview.ts @@ -0,0 +1,16 @@ +import type { Preview } from '@storybook/vue3' +import '../src/styles/main.css' + +const preview: Preview = { + parameters: { + backgrounds: { + default: 'dark', + values: [ + { name: 'dark', value: '#0a0a0a' }, + ], + }, + layout: 'centered', + }, +} + +export default preview diff --git a/packages/app/e2e/visual-regression.spec.ts b/packages/app/e2e/visual-regression.spec.ts new file mode 100644 index 00000000..93e1bfa7 --- /dev/null +++ b/packages/app/e2e/visual-regression.spec.ts @@ -0,0 +1,48 @@ +import { test, expect } from '@playwright/test' + +test.describe('Visual Regression', () => { + test('ChatPage renders correctly', async ({ page }) => { + await page.goto('/') + await page.waitForLoadState('networkidle') + await expect(page).toHaveScreenshot('chat-page.png', { + maxDiffPixelRatio: 0.005, + fullPage: true, + }) + }) + + test('ContentPanel renders correctly', async ({ page }) => { + await page.goto('/') + await page.waitForLoadState('networkidle') + // Open content panel by clicking a content tab + const filmTab = page.getByRole('button', { name: /film/i }).first() + if (await filmTab.isVisible()) { + await filmTab.click() + await page.waitForTimeout(500) + await expect(page).toHaveScreenshot('content-panel-films.png', { + maxDiffPixelRatio: 0.005, + }) + } + }) + + test('PassphraseDialog renders correctly', async ({ page }) => { + await page.goto('/') + await page.waitForLoadState('networkidle') + // PassphraseDialog shows on first load if crypto is enabled + const dialog = page.locator('.glass-card').filter({ hasText: 'Unlock AIUI' }) + if (await dialog.isVisible()) { + await expect(dialog).toHaveScreenshot('passphrase-dialog.png', { + maxDiffPixelRatio: 0.005, + }) + } + }) + + test('BottomSheet renders correctly on mobile', async ({ page }) => { + await page.setViewportSize({ width: 390, height: 844 }) + await page.goto('/') + await page.waitForLoadState('networkidle') + await expect(page).toHaveScreenshot('mobile-view.png', { + maxDiffPixelRatio: 0.005, + fullPage: true, + }) + }) +}) diff --git a/packages/app/lighthouserc.json b/packages/app/lighthouserc.json new file mode 100644 index 00000000..3adea37d --- /dev/null +++ b/packages/app/lighthouserc.json @@ -0,0 +1,23 @@ +{ + "ci": { + "collect": { + "staticDistDir": "./dist", + "numberOfRuns": 3, + "settings": { + "preset": "desktop" + } + }, + "assert": { + "assertions": { + "categories:performance": ["error", { "minScore": 0.7 }], + "largest-contentful-paint": ["error", { "maxNumericValue": 3000 }], + "cumulative-layout-shift": ["error", { "maxNumericValue": 0.15 }], + "categories:accessibility": ["warn", { "minScore": 0.8 }], + "categories:best-practices": ["warn", { "minScore": 0.8 }] + } + }, + "upload": { + "target": "temporary-public-storage" + } + } +} diff --git a/packages/app/package.json b/packages/app/package.json index 444fc7f5..8dee9f61 100644 --- a/packages/app/package.json +++ b/packages/app/package.json @@ -16,7 +16,9 @@ "test:e2e:ui": "playwright test --ui", "lint": "eslint src/", "typecheck": "vue-tsc --noEmit", - "clean": "rm -rf dist" + "clean": "rm -rf dist", + "storybook": "storybook dev -p 6006", + "build-storybook": "storybook build" }, "dependencies": { "@aiui/core": "workspace:*", @@ -53,6 +55,10 @@ "vite": "^7.3.1", "vite-plugin-pwa": "^1.2.0", "vitest": "^4.0.18", + "@storybook/addon-essentials": "^8.6.0", + "@storybook/vue3": "^8.6.0", + "@storybook/vue3-vite": "^8.6.0", + "storybook": "^8.6.0", "vue-eslint-parser": "^10.4.0", "vue-tsc": "^3.2.5" } diff --git a/packages/app/playwright.config.ts b/packages/app/playwright.config.ts index f9d8b249..41f5beee 100644 --- a/packages/app/playwright.config.ts +++ b/packages/app/playwright.config.ts @@ -9,12 +9,37 @@ export default defineConfig({ globalSetup: './e2e/global-setup.ts', globalTeardown: './e2e/global-teardown.ts', reporter: 'html', + snapshotPathTemplate: '{testDir}/__screenshots__/{projectName}/{testFilePath}/{arg}{ext}', + expect: { + toHaveScreenshot: { maxDiffPixelRatio: 0.005 }, + }, use: { baseURL: 'http://localhost:5173', trace: 'on-first-retry', }, projects: [ + // Desktop browsers { name: 'chromium', use: { ...devices['Desktop Chrome'] } }, + { name: 'firefox', use: { ...devices['Desktop Firefox'] } }, + { name: 'webkit', use: { ...devices['Desktop Safari'] } }, + // Mobile viewports + { + name: 'iphone14', + use: { + ...devices['iPhone 14'], + viewport: { width: 390, height: 844 }, + }, + }, + { + name: 'galaxy-s21', + use: { + userAgent: 'Mozilla/5.0 (Linux; Android 12; SM-G991B) AppleWebKit/537.36', + viewport: { width: 360, height: 800 }, + deviceScaleFactor: 3, + isMobile: true, + hasTouch: true, + }, + }, ], webServer: { command: 'pnpm run dev:vite', diff --git a/packages/app/src/__tests__/proxy.test.ts b/packages/app/src/__tests__/proxy.test.ts new file mode 100644 index 00000000..f5b6fa96 --- /dev/null +++ b/packages/app/src/__tests__/proxy.test.ts @@ -0,0 +1,188 @@ +import { describe, it, expect, vi, beforeEach } from 'vitest' + +// Mock proxy request/response logic without actually spawning processes +describe('Proxy Integration', () => { + describe('SSE streaming format', () => { + it('should produce valid SSE content_block_delta events', () => { + const text = 'Hello, world!' + const sseData = { + type: 'content_block_delta', + delta: { type: 'text_delta', text }, + } + const sseString = `data: ${JSON.stringify(sseData)}\n\n` + + expect(sseString).toMatch(/^data: /) + expect(sseString).toMatch(/\n\n$/) + + const parsed = JSON.parse(sseString.replace('data: ', '').trim()) + expect(parsed.type).toBe('content_block_delta') + expect(parsed.delta.type).toBe('text_delta') + expect(parsed.delta.text).toBe(text) + }) + + it('should produce valid DONE event', () => { + const done = 'data: [DONE]\n\n' + expect(done).toBe('data: [DONE]\n\n') + }) + + it('should produce valid error events', () => { + const errData = { + type: 'error', + error: { message: 'Anthropic API 401: Unauthorized' }, + } + const sseString = `data: ${JSON.stringify(errData)}\n\n` + const parsed = JSON.parse(sseString.replace('data: ', '').trim()) + expect(parsed.type).toBe('error') + expect(parsed.error.message).toContain('401') + }) + }) + + describe('Model mapping', () => { + function mapModelToApi(model: string): string { + if (model?.includes('opus')) return 'claude-opus-4-20250514' + if (model?.includes('haiku')) return 'claude-3-5-haiku-20241022' + return 'claude-sonnet-4-20250514' + } + + it('should map sonnet model correctly', () => { + expect(mapModelToApi('sonnet')).toBe('claude-sonnet-4-20250514') + expect(mapModelToApi('claude-sonnet')).toBe('claude-sonnet-4-20250514') + }) + + it('should map opus model correctly', () => { + expect(mapModelToApi('opus')).toBe('claude-opus-4-20250514') + expect(mapModelToApi('claude-opus')).toBe('claude-opus-4-20250514') + }) + + it('should map haiku model correctly', () => { + expect(mapModelToApi('haiku')).toBe('claude-3-5-haiku-20241022') + }) + + it('should default to sonnet for unknown models', () => { + expect(mapModelToApi('unknown')).toBe('claude-sonnet-4-20250514') + }) + }) + + describe('Request validation', () => { + it('should reject non-POST requests', () => { + const method = 'GET' as string + const isValid = method === 'POST' + expect(isValid).toBe(false) + }) + + it('should reject unknown paths', () => { + const validPaths = ['/v1/messages', '/v1/openrouter'] + expect(validPaths.includes('/v1/unknown')).toBe(false) + expect(validPaths.includes('/v1/messages')).toBe(true) + expect(validPaths.includes('/v1/openrouter')).toBe(true) + }) + + it('should parse request body correctly', () => { + const body = JSON.stringify({ + model: 'sonnet', + messages: [{ role: 'user', content: 'Hello' }], + system: 'You are helpful.', + webSearch: true, + }) + const parsed = JSON.parse(body) + expect(parsed.model).toBe('sonnet') + expect(parsed.messages).toHaveLength(1) + expect(parsed.system).toBe('You are helpful.') + expect(parsed.webSearch).toBe(true) + }) + + it('should handle malformed JSON', () => { + const badBody = 'not json' + expect(() => JSON.parse(badBody)).toThrow() + }) + }) + + describe('Tool use round-trips', () => { + it('should format search_web tool correctly', () => { + const tool = { + name: 'search_web', + description: 'Search the web for current information.', + input_schema: { + type: 'object', + properties: { + query: { type: 'string', description: 'Search query' }, + }, + required: ['query'], + }, + } + expect(tool.name).toBe('search_web') + expect(tool.input_schema.properties.query.type).toBe('string') + }) + + it('should construct tool_result messages correctly', () => { + const toolResult = { + type: 'tool_result', + tool_use_id: 'toolu_123', + content: '1. [Bitcoin price](https://example.com) — Current price is...', + } + expect(toolResult.type).toBe('tool_result') + expect(toolResult.tool_use_id).toBe('toolu_123') + expect(toolResult.content).toContain('Bitcoin') + }) + + it('should limit tool rounds to 5', () => { + const maxToolRounds = 5 + let rounds = 0 + while (rounds < maxToolRounds) { + rounds++ + } + expect(rounds).toBe(5) + }) + }) + + describe('Error handling', () => { + it('should handle 401 unauthorized', () => { + const status = 401 + const errMsg = `Anthropic API ${status}: Unauthorized` + expect(errMsg).toContain('401') + }) + + it('should handle 429 rate limit', () => { + const status = 429 + const errMsg = `Anthropic API ${status}: Rate limited` + expect(errMsg).toContain('429') + }) + + it('should handle 500 server error', () => { + const status = 500 + const errMsg = `Anthropic API ${status}: Internal Server Error` + expect(errMsg).toContain('500') + }) + }) + + describe('OAuth token detection', () => { + const isOAuthToken = (s: string) => /^sk-ant-oat/.test(s) + + it('should detect OAuth tokens', () => { + expect(isOAuthToken('sk-ant-oat-abc123')).toBe(true) + }) + + it('should not flag API keys as OAuth', () => { + expect(isOAuthToken('sk-ant-api03-abc123')).toBe(false) + }) + }) + + describe('Client disconnect handling', () => { + it('should track client disconnection', () => { + const state = { clientDisconnected: false } + // Simulate disconnect + state.clientDisconnected = true + expect(state.clientDisconnected).toBe(true) + }) + + it('should not write after disconnect', () => { + const clientDisconnected = true + const writes: string[] = [] + const write = (data: string) => { + if (!clientDisconnected) writes.push(data) + } + write('should not appear') + expect(writes).toHaveLength(0) + }) + }) +}) diff --git a/packages/app/src/components/ui/__stories__/BottomSheet.stories.ts b/packages/app/src/components/ui/__stories__/BottomSheet.stories.ts new file mode 100644 index 00000000..9326573f --- /dev/null +++ b/packages/app/src/components/ui/__stories__/BottomSheet.stories.ts @@ -0,0 +1,49 @@ +import type { Meta, StoryObj } from '@storybook/vue3' +import { ref } from 'vue' +import BottomSheet from '../BottomSheet.vue' + +const meta: Meta = { + title: 'UI/BottomSheet', + component: BottomSheet, + tags: ['autodocs'], +} + +export default meta +type Story = StoryObj + +export const Default: Story = { + render: () => ({ + components: { BottomSheet }, + setup() { + const isOpen = ref(true) + return { isOpen } + }, + template: ` + +
+

Bottom Sheet

+

Drag the handle to resize or swipe down to close.

+
+
+ + `, + }), +} + +export const CustomSnapPoints: Story = { + render: () => ({ + components: { BottomSheet }, + setup() { + const isOpen = ref(true) + return { isOpen } + }, + template: ` + +
+

Custom Snap Points

+

Snaps to 30%, 60%, and 100%.

+
+
+ `, + }), +} diff --git a/packages/app/src/components/ui/__stories__/ContextMenu.stories.ts b/packages/app/src/components/ui/__stories__/ContextMenu.stories.ts new file mode 100644 index 00000000..0225a920 --- /dev/null +++ b/packages/app/src/components/ui/__stories__/ContextMenu.stories.ts @@ -0,0 +1,34 @@ +import type { Meta, StoryObj } from '@storybook/vue3' +import { ref, onMounted } from 'vue' +import ContextMenu from '../ContextMenu.vue' +import ContextMenuItem from '../ContextMenuItem.vue' + +const meta: Meta = { + title: 'UI/ContextMenu', + component: ContextMenu, + tags: ['autodocs'], +} + +export default meta +type Story = StoryObj + +export const Default: Story = { + render: () => ({ + components: { ContextMenu, ContextMenuItem }, + setup() { + const menuRef = ref | null>(null) + onMounted(() => { + menuRef.value?.open(200, 100) + }) + return { menuRef } + }, + template: ` + + Edit + Copy + Share + Delete + + `, + }), +} diff --git a/packages/app/src/components/ui/__stories__/ContextMenuItem.stories.ts b/packages/app/src/components/ui/__stories__/ContextMenuItem.stories.ts new file mode 100644 index 00000000..3b28a26a --- /dev/null +++ b/packages/app/src/components/ui/__stories__/ContextMenuItem.stories.ts @@ -0,0 +1,30 @@ +import type { Meta, StoryObj } from '@storybook/vue3' +import ContextMenuItem from '../ContextMenuItem.vue' + +const meta: Meta = { + title: 'UI/ContextMenuItem', + component: ContextMenuItem, + tags: ['autodocs'], + decorators: [ + () => ({ + template: '
', + }), + ], +} + +export default meta +type Story = StoryObj + +export const Default: Story = { + render: () => ({ + components: { ContextMenuItem }, + template: 'Edit Message', + }), +} + +export const Destructive: Story = { + render: () => ({ + components: { ContextMenuItem }, + template: 'Delete', + }), +} diff --git a/packages/app/src/components/ui/__stories__/ErrorBoundary.stories.ts b/packages/app/src/components/ui/__stories__/ErrorBoundary.stories.ts new file mode 100644 index 00000000..8530b92b --- /dev/null +++ b/packages/app/src/components/ui/__stories__/ErrorBoundary.stories.ts @@ -0,0 +1,41 @@ +import type { Meta, StoryObj } from '@storybook/vue3' +import { defineComponent } from 'vue' +import ErrorBoundary from '../ErrorBoundary.vue' + +const meta: Meta = { + title: 'UI/ErrorBoundary', + component: ErrorBoundary, + tags: ['autodocs'], +} + +export default meta +type Story = StoryObj + +const BrokenChild = defineComponent({ + setup() { + throw new Error('Something went wrong in the child component') + }, + template: '
This should not render
', +}) + +export const WithError: Story = { + render: () => ({ + components: { ErrorBoundary, BrokenChild }, + template: ` + + + + `, + }), +} + +export const NoError: Story = { + render: () => ({ + components: { ErrorBoundary }, + template: ` + +
Everything is working fine.
+
+ `, + }), +} diff --git a/packages/app/src/components/ui/__stories__/FavoriteButton.stories.ts b/packages/app/src/components/ui/__stories__/FavoriteButton.stories.ts new file mode 100644 index 00000000..e6ab6ca8 --- /dev/null +++ b/packages/app/src/components/ui/__stories__/FavoriteButton.stories.ts @@ -0,0 +1,34 @@ +import type { Meta, StoryObj } from '@storybook/vue3' +import { ref } from 'vue' +import FavoriteButton from '../FavoriteButton.vue' + +const meta: Meta = { + title: 'UI/FavoriteButton', + component: FavoriteButton, + tags: ['autodocs'], +} + +export default meta +type Story = StoryObj + +export const Unfavorited: Story = { + render: () => ({ + components: { FavoriteButton }, + setup() { + const favorited = ref(false) + return { favorited } + }, + template: '', + }), +} + +export const Favorited: Story = { + render: () => ({ + components: { FavoriteButton }, + setup() { + const favorited = ref(true) + return { favorited } + }, + template: '', + }), +} diff --git a/packages/app/src/components/ui/__stories__/LightningInvoice.stories.ts b/packages/app/src/components/ui/__stories__/LightningInvoice.stories.ts new file mode 100644 index 00000000..855bd9ee --- /dev/null +++ b/packages/app/src/components/ui/__stories__/LightningInvoice.stories.ts @@ -0,0 +1,25 @@ +import type { Meta, StoryObj } from '@storybook/vue3' +import LightningInvoice from '../LightningInvoice.vue' + +const meta: Meta = { + title: 'UI/LightningInvoice', + component: LightningInvoice, + tags: ['autodocs'], +} + +export default meta +type Story = StoryObj + +export const Default: Story = { + args: { + invoice: 'lnbc10u1pjexampleinvoicethatisverylongandcontainsmanycharacters0123456789abcdef', + expirySeconds: 600, + }, +} + +export const Expiring: Story = { + args: { + invoice: 'lnbc10u1pjexampleinvoicethatisverylongandcontainsmanycharacters0123456789abcdef', + expirySeconds: 30, + }, +} diff --git a/packages/app/src/components/ui/__stories__/PassphraseDialog.stories.ts b/packages/app/src/components/ui/__stories__/PassphraseDialog.stories.ts new file mode 100644 index 00000000..79cd2d32 --- /dev/null +++ b/packages/app/src/components/ui/__stories__/PassphraseDialog.stories.ts @@ -0,0 +1,25 @@ +import type { Meta, StoryObj } from '@storybook/vue3' +import PassphraseDialog from '../PassphraseDialog.vue' + +const meta: Meta = { + title: 'UI/PassphraseDialog', + component: PassphraseDialog, + tags: ['autodocs'], +} + +export default meta +type Story = StoryObj + +export const Unlock: Story = { + args: { + visible: true, + isCreating: false, + }, +} + +export const Create: Story = { + args: { + visible: true, + isCreating: true, + }, +} diff --git a/packages/app/src/components/ui/__stories__/PaymentButton.stories.ts b/packages/app/src/components/ui/__stories__/PaymentButton.stories.ts new file mode 100644 index 00000000..1e87d02e --- /dev/null +++ b/packages/app/src/components/ui/__stories__/PaymentButton.stories.ts @@ -0,0 +1,24 @@ +import type { Meta, StoryObj } from '@storybook/vue3' +import PaymentButton from '../PaymentButton.vue' + +const meta: Meta = { + title: 'UI/PaymentButton', + component: PaymentButton, + tags: ['autodocs'], +} + +export default meta +type Story = StoryObj + +export const Default: Story = { + args: { + invoice: 'lnbc1000n1pjexample', + }, +} + +export const WithAmount: Story = { + args: { + invoice: 'lnbc1000n1pjexample', + amount: 1000, + }, +} diff --git a/packages/app/src/components/ui/__stories__/SearchResults.stories.ts b/packages/app/src/components/ui/__stories__/SearchResults.stories.ts new file mode 100644 index 00000000..3f78d3fc --- /dev/null +++ b/packages/app/src/components/ui/__stories__/SearchResults.stories.ts @@ -0,0 +1,35 @@ +import type { Meta, StoryObj } from '@storybook/vue3' +import SearchResults from '../SearchResults.vue' + +const meta: Meta = { + title: 'UI/SearchResults', + component: SearchResults, + tags: ['autodocs'], + decorators: [ + () => ({ + template: '
', + }), + ], +} + +export default meta +type Story = StoryObj + +export const WithResults: Story = { + args: { + isSearching: false, + results: [ + { id: '1', title: 'Blade Runner 2049', subtitle: 'Denis Villeneuve · 2017', type: 'film', data: null }, + { id: '2', title: 'Arrival', subtitle: 'Denis Villeneuve · 2016', type: 'film', data: null }, + { id: '3', title: 'Never Meant', subtitle: 'American Football', type: 'song', data: null }, + { id: '4', title: 'What Bitcoin Did', subtitle: 'Peter McCormack', type: 'podcast', data: null }, + ], + }, +} + +export const Searching: Story = { + args: { + isSearching: true, + results: [], + }, +} diff --git a/packages/app/src/mocks/books.ts b/packages/app/src/mocks/books.ts new file mode 100644 index 00000000..36d29171 --- /dev/null +++ b/packages/app/src/mocks/books.ts @@ -0,0 +1,35 @@ +import type { Book } from '@aiui/core/types/content' + +export const mockBooks: Book[] = [ + { id: 'b1', title: 'The Bitcoin Standard', author: 'Saifedean Ammous', year: 2018, isbn: '9781119473862', coverUrl: 'https://covers.openlibrary.org/b/isbn/9781119473862-M.jpg', genres: ['Economics', 'Bitcoin'], pages: 304, sources: [{ type: 'openlibrary', name: 'Open Library', url: 'https://openlibrary.org/isbn/9781119473862' }] }, + { id: 'b2', title: 'Mastering Bitcoin', author: 'Andreas M. Antonopoulos', year: 2017, isbn: '9781491954386', coverUrl: 'https://covers.openlibrary.org/b/isbn/9781491954386-M.jpg', genres: ['Technology', 'Bitcoin'], pages: 416, sources: [{ type: 'openlibrary', name: 'Open Library', url: 'https://openlibrary.org/isbn/9781491954386' }] }, + { id: 'b3', title: 'Neuromancer', author: 'William Gibson', year: 1984, isbn: '9780441569595', coverUrl: 'https://covers.openlibrary.org/b/isbn/9780441569595-M.jpg', genres: ['Sci-Fi', 'Cyberpunk'], pages: 271, sources: [{ type: 'gutenberg', name: 'Project Gutenberg', url: 'https://www.gutenberg.org' }] }, + { id: 'b4', title: 'Snow Crash', author: 'Neal Stephenson', year: 1992, isbn: '9780553380958', coverUrl: 'https://covers.openlibrary.org/b/isbn/9780553380958-M.jpg', genres: ['Sci-Fi', 'Cyberpunk'], pages: 480, sources: [{ type: 'openlibrary', name: 'Open Library', url: 'https://openlibrary.org/isbn/9780553380958' }] }, + { id: 'b5', title: 'Dune', author: 'Frank Herbert', year: 1965, isbn: '9780441172719', coverUrl: 'https://covers.openlibrary.org/b/isbn/9780441172719-M.jpg', genres: ['Sci-Fi', 'Adventure'], pages: 688, sources: [{ type: 'openlibrary', name: 'Open Library', url: 'https://openlibrary.org/isbn/9780441172719' }] }, + { id: 'b6', title: '1984', author: 'George Orwell', year: 1949, isbn: '9780451524935', coverUrl: 'https://covers.openlibrary.org/b/isbn/9780451524935-M.jpg', genres: ['Dystopian', 'Political Fiction'], pages: 328, sources: [{ type: 'gutenberg', name: 'Project Gutenberg', url: 'https://www.gutenberg.org/ebooks/85' }] }, + { id: 'b7', title: 'Brave New World', author: 'Aldous Huxley', year: 1932, isbn: '9780060850524', coverUrl: 'https://covers.openlibrary.org/b/isbn/9780060850524-M.jpg', genres: ['Dystopian', 'Sci-Fi'], pages: 288, sources: [{ type: 'archive', name: 'Internet Archive', url: 'https://archive.org/details/bravenewworld' }] }, + { id: 'b8', title: 'The Sovereign Individual', author: 'James Dale Davidson', year: 1997, isbn: '9780684832722', coverUrl: 'https://covers.openlibrary.org/b/isbn/9780684832722-M.jpg', genres: ['Economics', 'Futurism'], pages: 432, sources: [{ type: 'openlibrary', name: 'Open Library', url: 'https://openlibrary.org/isbn/9780684832722' }] }, + { id: 'b9', title: 'Cryptonomicon', author: 'Neal Stephenson', year: 1999, isbn: '9780060512804', coverUrl: 'https://covers.openlibrary.org/b/isbn/9780060512804-M.jpg', genres: ['Sci-Fi', 'Historical Fiction'], pages: 1168, sources: [{ type: 'openlibrary', name: 'Open Library', url: 'https://openlibrary.org/isbn/9780060512804' }] }, + { id: 'b10', title: 'The Hitchhiker\'s Guide to the Galaxy', author: 'Douglas Adams', year: 1979, isbn: '9780345391803', coverUrl: 'https://covers.openlibrary.org/b/isbn/9780345391803-M.jpg', genres: ['Sci-Fi', 'Comedy'], pages: 216, sources: [{ type: 'openlibrary', name: 'Open Library', url: 'https://openlibrary.org/isbn/9780345391803' }] }, + { id: 'b11', title: 'Foundation', author: 'Isaac Asimov', year: 1951, isbn: '9780553293357', coverUrl: 'https://covers.openlibrary.org/b/isbn/9780553293357-M.jpg', genres: ['Sci-Fi'], pages: 244, sources: [{ type: 'openlibrary', name: 'Open Library', url: 'https://openlibrary.org/isbn/9780553293357' }] }, + { id: 'b12', title: 'The Cypherpunks', author: 'Julian Assange', year: 2012, isbn: '9781939293008', coverUrl: 'https://covers.openlibrary.org/b/isbn/9781939293008-M.jpg', genres: ['Technology', 'Privacy'], pages: 186, sources: [{ type: 'openlibrary', name: 'Open Library', url: 'https://openlibrary.org/isbn/9781939293008' }] }, + { id: 'b13', title: 'Fahrenheit 451', author: 'Ray Bradbury', year: 1953, isbn: '9781451673319', coverUrl: 'https://covers.openlibrary.org/b/isbn/9781451673319-M.jpg', genres: ['Dystopian', 'Sci-Fi'], pages: 194, sources: [{ type: 'gutenberg', name: 'Project Gutenberg', url: 'https://www.gutenberg.org' }] }, + { id: 'b14', title: 'Do Androids Dream of Electric Sheep?', author: 'Philip K. Dick', year: 1968, isbn: '9780345404473', coverUrl: 'https://covers.openlibrary.org/b/isbn/9780345404473-M.jpg', genres: ['Sci-Fi'], pages: 244, sources: [{ type: 'openlibrary', name: 'Open Library', url: 'https://openlibrary.org/isbn/9780345404473' }] }, + { id: 'b15', title: 'The Left Hand of Darkness', author: 'Ursula K. Le Guin', year: 1969, isbn: '9780441478125', coverUrl: 'https://covers.openlibrary.org/b/isbn/9780441478125-M.jpg', genres: ['Sci-Fi', 'Fantasy'], pages: 304, sources: [{ type: 'openlibrary', name: 'Open Library', url: 'https://openlibrary.org/isbn/9780441478125' }] }, + { id: 'b16', title: 'Solaris', author: 'Stanislaw Lem', year: 1961, isbn: '9780156027601', coverUrl: 'https://covers.openlibrary.org/b/isbn/9780156027601-M.jpg', genres: ['Sci-Fi'], pages: 224, sources: [{ type: 'openlibrary', name: 'Open Library', url: 'https://openlibrary.org/isbn/9780156027601' }] }, + { id: 'b17', title: 'The Network State', author: 'Balaji Srinivasan', year: 2022, isbn: '9798986127507', coverUrl: undefined, genres: ['Technology', 'Political Theory'], pages: 432, sources: [{ type: 'openlibrary', name: 'Open Library', url: 'https://openlibrary.org/isbn/9798986127507' }] }, + { id: 'b18', title: 'The Fiat Standard', author: 'Saifedean Ammous', year: 2021, isbn: '9781544526478', coverUrl: 'https://covers.openlibrary.org/b/isbn/9781544526478-M.jpg', genres: ['Economics', 'Bitcoin'], pages: 382, sources: [{ type: 'openlibrary', name: 'Open Library', url: 'https://openlibrary.org/isbn/9781544526478' }] }, + { id: 'b19', title: 'Hyperion', author: 'Dan Simmons', year: 1989, isbn: '9780553283686', coverUrl: 'https://covers.openlibrary.org/b/isbn/9780553283686-M.jpg', genres: ['Sci-Fi', 'Space Opera'], pages: 482, sources: [{ type: 'openlibrary', name: 'Open Library', url: 'https://openlibrary.org/isbn/9780553283686' }] }, + { id: 'b20', title: 'Blindsight', author: 'Peter Watts', year: 2006, isbn: '9780765319647', coverUrl: 'https://covers.openlibrary.org/b/isbn/9780765319647-M.jpg', genres: ['Sci-Fi', 'Hard SF'], pages: 384, sources: [{ type: 'openlibrary', name: 'Open Library', url: 'https://openlibrary.org/isbn/9780765319647' }] }, + { id: 'b21', title: 'The Dispossessed', author: 'Ursula K. Le Guin', year: 1974, isbn: '9780060512750', coverUrl: 'https://covers.openlibrary.org/b/isbn/9780060512750-M.jpg', genres: ['Sci-Fi', 'Utopian'], pages: 387, sources: [{ type: 'openlibrary', name: 'Open Library', url: 'https://openlibrary.org/isbn/9780060512750' }] }, +] + +export function searchBooks(query: string): Book[] { + const q = query.toLowerCase() + return mockBooks.filter( + (b) => + b.title.toLowerCase().includes(q) || + b.author.toLowerCase().includes(q) || + (b.genres ?? []).some((g) => g.toLowerCase().includes(q)) + ) +} diff --git a/packages/app/src/mocks/images.ts b/packages/app/src/mocks/images.ts new file mode 100644 index 00000000..3e45c5b6 --- /dev/null +++ b/packages/app/src/mocks/images.ts @@ -0,0 +1,30 @@ +import type { ImageItem } from '@aiui/core/types/content' + +export const mockImages: ImageItem[] = [ + { id: 'img1', title: 'Cyberpunk City at Night', url: 'https://picsum.photos/id/1/1200/800', width: 1200, height: 800, alt: 'Cyberpunk city at night' }, + { id: 'img2', title: 'Mountain Landscape', url: 'https://picsum.photos/id/10/1200/800', width: 1200, height: 800, alt: 'Mountain landscape' }, + { id: 'img3', title: 'Ocean Sunset', url: 'https://picsum.photos/id/14/1200/800', width: 1200, height: 800, alt: 'Ocean sunset' }, + { id: 'img4', title: 'Forest Path', url: 'https://picsum.photos/id/15/1200/800', width: 1200, height: 800, alt: 'Forest path' }, + { id: 'img5', title: 'Abstract Art', url: 'https://picsum.photos/id/20/1200/800', width: 1200, height: 800, alt: 'Abstract art' }, + { id: 'img6', title: 'Desert Dunes', url: 'https://picsum.photos/id/22/1200/800', width: 1200, height: 800, alt: 'Desert dunes' }, + { id: 'img7', title: 'City Architecture', url: 'https://picsum.photos/id/26/1200/800', width: 1200, height: 800, alt: 'City architecture' }, + { id: 'img8', title: 'Northern Lights', url: 'https://picsum.photos/id/29/1200/800', width: 1200, height: 800, alt: 'Northern lights' }, + { id: 'img9', title: 'Space Nebula', url: 'https://picsum.photos/id/30/1200/800', width: 1200, height: 800, alt: 'Space nebula' }, + { id: 'img10', title: 'Macro Photography', url: 'https://picsum.photos/id/36/1200/800', width: 1200, height: 800, alt: 'Macro photography' }, + { id: 'img11', title: 'Winter Scene', url: 'https://picsum.photos/id/40/1200/800', width: 1200, height: 800, alt: 'Winter scene' }, + { id: 'img12', title: 'Street Photography', url: 'https://picsum.photos/id/42/1200/800', width: 1200, height: 800, alt: 'Street photography' }, + { id: 'img13', title: 'Underwater World', url: 'https://picsum.photos/id/45/1200/800', width: 1200, height: 800, alt: 'Underwater world' }, + { id: 'img14', title: 'Vintage Train', url: 'https://picsum.photos/id/47/1200/800', width: 1200, height: 800, alt: 'Vintage train' }, + { id: 'img15', title: 'Botanical Garden', url: 'https://picsum.photos/id/49/1200/800', width: 1200, height: 800, alt: 'Botanical garden' }, + { id: 'img16', title: 'Aerial View', url: 'https://picsum.photos/id/50/1200/800', width: 1200, height: 800, alt: 'Aerial view' }, + { id: 'img17', title: 'Neon Signs', url: 'https://picsum.photos/id/55/1200/800', width: 1200, height: 800, alt: 'Neon signs' }, + { id: 'img18', title: 'Foggy Bridge', url: 'https://picsum.photos/id/57/1200/800', width: 1200, height: 800, alt: 'Foggy bridge' }, + { id: 'img19', title: 'Lightning Storm', url: 'https://picsum.photos/id/60/1200/800', width: 1200, height: 800, alt: 'Lightning storm' }, + { id: 'img20', title: 'Retro Computer', url: 'https://picsum.photos/id/63/1200/800', width: 1200, height: 800, alt: 'Retro computer' }, + { id: 'img21', title: 'Crystal Cave', url: 'https://picsum.photos/id/65/1200/800', width: 1200, height: 800, alt: 'Crystal cave' }, +] + +export function searchImages(query: string): ImageItem[] { + const q = query.toLowerCase() + return mockImages.filter((img) => (img.title ?? '').toLowerCase().includes(q)) +} diff --git a/packages/app/src/mocks/index.ts b/packages/app/src/mocks/index.ts new file mode 100644 index 00000000..970ea5ca --- /dev/null +++ b/packages/app/src/mocks/index.ts @@ -0,0 +1,13 @@ +export { mockFilms, searchFilms, filterFilms, allGenres, allSources } from './films' +export { mockSongs } from './songs' +export { mockBooks, searchBooks } from './books' +export { mockTVShows, searchTVShows } from './tvshows' +export { mockImages, searchImages } from './images' +export { mockPlaces, searchPlaces } from './places' +export { mockNews, searchNews } from './news' +export { mockNostrEvents, MockNostrRelay } from './nostr' +export { mockTMDBSearch, mockTMDBSearchResponses, mockTMDBGenres } from './tmdb' + +export type { MockNewsArticle } from './news' +export type { MockNostrEvent } from './nostr' +export type { TMDBSearchResult, TMDBSearchResponse } from './tmdb' diff --git a/packages/app/src/mocks/news.ts b/packages/app/src/mocks/news.ts new file mode 100644 index 00000000..ddf65fa8 --- /dev/null +++ b/packages/app/src/mocks/news.ts @@ -0,0 +1,45 @@ +export interface MockNewsArticle { + id: string + title: string + source: string + url: string + publishedAt: string + summary: string + category: string + imageUrl?: string +} + +export const mockNews: MockNewsArticle[] = [ + { id: 'n1', title: 'Bitcoin Surpasses $150,000 Mark as Institutional Adoption Accelerates', source: 'Bitcoin Magazine', url: 'https://bitcoinmagazine.com/markets/btc-150k', publishedAt: '2026-03-01', summary: 'Bitcoin reached a new all-time high as major pension funds added BTC to their portfolios.', category: 'Markets', imageUrl: 'https://picsum.photos/id/100/600/400' }, + { id: 'n2', title: 'Lightning Network Capacity Reaches 100,000 BTC', source: 'The Block', url: 'https://theblock.co/lightning-100k', publishedAt: '2026-02-28', summary: 'The Lightning Network continues its exponential growth with total capacity surpassing 100K BTC.', category: 'Technology' }, + { id: 'n3', title: 'Nostr Protocol Reaches 50 Million Users Worldwide', source: 'Nostr Report', url: 'https://nostr.report/50m-users', publishedAt: '2026-02-27', summary: 'The censorship-resistant social protocol has seen massive growth in decentralized communication.', category: 'Technology' }, + { id: 'n4', title: 'EU Digital Identity Regulation Raises Privacy Concerns', source: 'EFF', url: 'https://eff.org/eu-digital-id', publishedAt: '2026-02-26', summary: 'Digital rights groups warn about surveillance implications of new EU digital identity requirements.', category: 'Privacy' }, + { id: 'n5', title: 'Open Source AI Models Now Match Proprietary Performance', source: 'Ars Technica', url: 'https://arstechnica.com/open-ai-models', publishedAt: '2026-02-25', summary: 'New open-source language models demonstrate capabilities on par with commercial alternatives.', category: 'AI' }, + { id: 'n6', title: 'Fedimint Launches Production-Ready Version 1.0', source: 'Bitcoin Magazine', url: 'https://bitcoinmagazine.com/fedimint-1', publishedAt: '2026-02-24', summary: 'Community custody protocol Fedimint releases its first production-ready version.', category: 'Bitcoin' }, + { id: 'n7', title: 'WebAssembly 3.0 Specification Published', source: 'Mozilla Blog', url: 'https://blog.mozilla.org/wasm-3', publishedAt: '2026-02-23', summary: 'The new WASM spec brings garbage collection and improved interop with JavaScript.', category: 'Technology' }, + { id: 'n8', title: 'Signal Protocol Integrated Into Major Email Providers', source: 'Wired', url: 'https://wired.com/signal-email', publishedAt: '2026-02-22', summary: 'End-to-end encryption becomes the default for several major email services.', category: 'Privacy' }, + { id: 'n9', title: 'Bitcoin Mining Now 80% Renewable Energy', source: 'CoinDesk', url: 'https://coindesk.com/mining-renewables', publishedAt: '2026-02-21', summary: 'Industry report shows Bitcoin mining has become predominantly powered by renewable energy sources.', category: 'Mining' }, + { id: 'n10', title: 'Cashu eCash Protocol Sees Rapid Adoption', source: 'Bitcoin Magazine', url: 'https://bitcoinmagazine.com/cashu-adoption', publishedAt: '2026-02-20', summary: 'The Chaumian eCash protocol built on Bitcoin sees growing usage for privacy-preserving payments.', category: 'Bitcoin' }, + { id: 'n11', title: 'Framework Laptop Launches ARM-Based Model', source: 'The Verge', url: 'https://theverge.com/framework-arm', publishedAt: '2026-02-19', summary: 'The repairable laptop company expands its lineup with an ARM processor option.', category: 'Hardware' }, + { id: 'n12', title: 'Rust Becomes Top 5 Programming Language', source: 'TIOBE', url: 'https://tiobe.com/rust-top-5', publishedAt: '2026-02-18', summary: 'Memory-safe language Rust enters the top 5 in the TIOBE programming language index.', category: 'Technology' }, + { id: 'n13', title: 'El Salvador Bitcoin Strategy Yields 300% Returns', source: 'Reuters', url: 'https://reuters.com/el-salvador-btc', publishedAt: '2026-02-17', summary: 'El Salvador\'s Bitcoin holdings have tripled in value since the country made it legal tender.', category: 'Markets' }, + { id: 'n14', title: 'IPFS Pinning Becomes Free for Open Source Projects', source: 'Protocol Labs Blog', url: 'https://blog.protocol.ai/free-ipfs', publishedAt: '2026-02-16', summary: 'A new initiative provides free IPFS pinning for open source and public good projects.', category: 'Technology' }, + { id: 'n15', title: 'Privacy-Preserving AI Training Methods Breakthrough', source: 'Nature', url: 'https://nature.com/private-ai', publishedAt: '2026-02-15', summary: 'Researchers demonstrate AI training on encrypted data without performance loss.', category: 'AI' }, + { id: 'n16', title: 'Mesh Networking Protocol Goes Mainstream', source: 'TechCrunch', url: 'https://techcrunch.com/mesh-mainstream', publishedAt: '2026-02-14', summary: 'New mesh networking standard enables peer-to-peer connectivity without traditional ISPs.', category: 'Technology' }, + { id: 'n17', title: 'Bitcoin Multisig Wallets See Enterprise Adoption', source: 'Bitcoin Magazine', url: 'https://bitcoinmagazine.com/multisig-enterprise', publishedAt: '2026-02-13', summary: 'Major corporations adopt multisignature Bitcoin wallets for treasury management.', category: 'Bitcoin' }, + { id: 'n18', title: 'Right to Repair Legislation Passes in 30 US States', source: 'iFixit', url: 'https://ifixit.com/right-to-repair-30', publishedAt: '2026-02-12', summary: 'The right to repair movement achieves a major milestone with widespread legislative support.', category: 'Policy' }, + { id: 'n19', title: 'Sovereign Computing Movement Gains Momentum', source: 'Hacker News', url: 'https://news.ycombinator.com/sovereign', publishedAt: '2026-02-11', summary: 'Growing number of individuals running personal servers and self-hosting critical services.', category: 'Technology' }, + { id: 'n20', title: 'Zero-Knowledge Proofs Enable Private Bitcoin Transactions', source: 'CoinDesk', url: 'https://coindesk.com/zkp-bitcoin', publishedAt: '2026-02-10', summary: 'New zero-knowledge proof implementations bring enhanced privacy to Bitcoin transactions.', category: 'Bitcoin' }, + { id: 'n21', title: 'Decentralized VPN Networks Reach 10 Million Nodes', source: 'TorrentFreak', url: 'https://torrentfreak.com/dvpn-10m', publishedAt: '2026-02-09', summary: 'Decentralized VPN services powered by community nodes reach significant scale.', category: 'Privacy' }, +] + +export function searchNews(query: string): MockNewsArticle[] { + const q = query.toLowerCase() + return mockNews.filter( + (n) => + n.title.toLowerCase().includes(q) || + n.source.toLowerCase().includes(q) || + n.category.toLowerCase().includes(q) || + n.summary.toLowerCase().includes(q) + ) +} diff --git a/packages/app/src/mocks/nostr.ts b/packages/app/src/mocks/nostr.ts new file mode 100644 index 00000000..cbf55a90 --- /dev/null +++ b/packages/app/src/mocks/nostr.ts @@ -0,0 +1,58 @@ +export interface MockNostrEvent { + id: string + pubkey: string + kind: number + content: string + created_at: number + tags: string[][] + sig: string + authorName?: string + authorNip05?: string +} + +export const mockNostrEvents: MockNostrEvent[] = [ + { id: 'ne1', pubkey: 'npub1abc', kind: 1, content: 'Just set up my first Lightning node. The future of money is here! ⚡', created_at: 1709000000, tags: [['t', 'bitcoin'], ['t', 'lightning']], sig: 'sig1', authorName: 'satoshi_fan', authorNip05: 'satoshi@nostr.com' }, + { id: 'ne2', pubkey: 'npub1def', kind: 1, content: 'Running Nostr relays on a Raspberry Pi. Sovereign infrastructure for the win.', created_at: 1708990000, tags: [['t', 'nostr'], ['t', 'selfhosting']], sig: 'sig2', authorName: 'relay_runner', authorNip05: 'relay@nostr.com' }, + { id: 'ne3', pubkey: 'npub1ghi', kind: 30023, content: '# Why Bitcoin Matters for Freedom\n\nBitcoin is the first technology that enables truly censorship-resistant money...', created_at: 1708980000, tags: [['d', 'bitcoin-freedom'], ['title', 'Why Bitcoin Matters for Freedom']], sig: 'sig3', authorName: 'freedom_writer', authorNip05: 'writer@nostr.com' }, + { id: 'ne4', pubkey: 'npub1jkl', kind: 9735, content: '', created_at: 1708970000, tags: [['bolt11', 'lnbc100n1pjexample'], ['amount', '100000'], ['p', 'npub1abc']], sig: 'sig4', authorName: 'zapper', authorNip05: 'zap@nostr.com' }, + { id: 'ne5', pubkey: 'npub1mno', kind: 1, content: 'Just published my first article on Nostr! No platform can censor my words. #nostr #decentralized', created_at: 1708960000, tags: [['t', 'nostr'], ['t', 'decentralized']], sig: 'sig5', authorName: 'free_speech', authorNip05: 'free@nostr.com' }, + { id: 'ne6', pubkey: 'npub1pqr', kind: 1, content: 'Comparing the Bitcoin and Nostr protocols. Both use keypairs, both are censorship-resistant. The parallels are striking.', created_at: 1708950000, tags: [['t', 'bitcoin'], ['t', 'nostr']], sig: 'sig6', authorName: 'protocol_nerd' }, + { id: 'ne7', pubkey: 'npub1stu', kind: 30023, content: '# Getting Started with NIP-44 Encryption\n\nIn this guide we\'ll explore the new NIP-44 encryption standard...', created_at: 1708940000, tags: [['d', 'nip44-guide'], ['title', 'Getting Started with NIP-44 Encryption']], sig: 'sig7', authorName: 'crypto_teacher' }, + { id: 'ne8', pubkey: 'npub1vwx', kind: 1, content: 'Built a Nostr client that runs entirely in the terminal. Sometimes the simplest tools are the best.', created_at: 1708930000, tags: [['t', 'nostr'], ['t', 'cli']], sig: 'sig8', authorName: 'terminal_hacker' }, + { id: 'ne9', pubkey: 'npub1yz0', kind: 9735, content: '', created_at: 1708920000, tags: [['bolt11', 'lnbc500n1pjexample'], ['amount', '500000'], ['p', 'npub1mno']], sig: 'sig9', authorName: 'big_zapper' }, + { id: 'ne10', pubkey: 'npub1123', kind: 1, content: 'Remember: not your keys, not your coins. Not your keys, not your notes. Sovereignty matters everywhere.', created_at: 1708910000, tags: [['t', 'bitcoin'], ['t', 'nostr'], ['t', 'sovereignty']], sig: 'sig10', authorName: 'key_holder' }, + { id: 'ne11', pubkey: 'npub1456', kind: 1, content: 'Just integrated Cashu payments into my Nostr client. Instant, private payments for everyone!', created_at: 1708900000, tags: [['t', 'cashu'], ['t', 'nostr']], sig: 'sig11', authorName: 'ecash_dev' }, + { id: 'ne12', pubkey: 'npub1789', kind: 30023, content: '# Building Censorship-Resistant Applications\n\nThe architecture of freedom technology requires careful design...', created_at: 1708890000, tags: [['d', 'censorship-resistance'], ['title', 'Building Censorship-Resistant Applications']], sig: 'sig12', authorName: 'arch_freedom' }, + { id: 'ne13', pubkey: 'npub1abc', kind: 1, content: 'Lightning + Nostr + Cashu = the holy trinity of freedom tech. All open source, all interoperable.', created_at: 1708880000, tags: [['t', 'lightning'], ['t', 'nostr'], ['t', 'cashu']], sig: 'sig13', authorName: 'satoshi_fan' }, + { id: 'ne14', pubkey: 'npub1def', kind: 9735, content: '', created_at: 1708870000, tags: [['bolt11', 'lnbc1000n1pjexample'], ['amount', '1000000'], ['p', 'npub1ghi']], sig: 'sig14', authorName: 'relay_runner' }, + { id: 'ne15', pubkey: 'npub1ghi', kind: 1, content: 'New blog post: why I moved all my social media activity to Nostr. No algorithms, no ads, just people.', created_at: 1708860000, tags: [['t', 'nostr'], ['t', 'freedom']], sig: 'sig15', authorName: 'freedom_writer' }, + { id: 'ne16', pubkey: 'npub1jkl', kind: 1, content: 'The beauty of open protocols: anyone can build on them. No API keys, no rate limits, no permission needed.', created_at: 1708850000, tags: [['t', 'openprotocols']], sig: 'sig16', authorName: 'zapper' }, + { id: 'ne17', pubkey: 'npub1mno', kind: 30023, content: '# Nostr Relay Architecture Best Practices\n\nRunning a relay is an act of infrastructure sovereignty...', created_at: 1708840000, tags: [['d', 'relay-architecture'], ['title', 'Nostr Relay Architecture Best Practices']], sig: 'sig17', authorName: 'free_speech' }, + { id: 'ne18', pubkey: 'npub1pqr', kind: 1, content: 'Just discovered you can run a Nostr relay on a $5/month VPS. Decentralization doesn\'t have to be expensive.', created_at: 1708830000, tags: [['t', 'nostr'], ['t', 'selfhosting']], sig: 'sig18', authorName: 'protocol_nerd' }, + { id: 'ne19', pubkey: 'npub1stu', kind: 9735, content: '', created_at: 1708820000, tags: [['bolt11', 'lnbc2100n1pjexample'], ['amount', '2100000'], ['p', 'npub1pqr']], sig: 'sig19', authorName: 'crypto_teacher' }, + { id: 'ne20', pubkey: 'npub1vwx', kind: 1, content: 'Day 365 of posting exclusively on Nostr. Zero regrets. Complete ownership of my digital identity.', created_at: 1708810000, tags: [['t', 'nostr'], ['t', 'sovereignty']], sig: 'sig20', authorName: 'terminal_hacker' }, + { id: 'ne21', pubkey: 'npub1yz0', kind: 1, content: 'The best part about Nostr: your identity is a keypair. No email, no phone number, no government ID needed.', created_at: 1708800000, tags: [['t', 'nostr'], ['t', 'privacy']], sig: 'sig21', authorName: 'big_zapper' }, +] + +export class MockNostrRelay { + private events: MockNostrEvent[] = [...mockNostrEvents] + + getEvents(filter?: { kinds?: number[]; limit?: number; authors?: string[] }): MockNostrEvent[] { + let results = this.events + if (filter?.kinds?.length) { + results = results.filter((e) => filter.kinds!.includes(e.kind)) + } + if (filter?.authors?.length) { + results = results.filter((e) => filter.authors!.includes(e.pubkey)) + } + if (filter?.limit) { + results = results.slice(0, filter.limit) + } + return results + } + + publish(event: MockNostrEvent): boolean { + this.events.unshift(event) + return true + } +} diff --git a/packages/app/src/mocks/places.ts b/packages/app/src/mocks/places.ts new file mode 100644 index 00000000..52fb2883 --- /dev/null +++ b/packages/app/src/mocks/places.ts @@ -0,0 +1,36 @@ +import type { Place } from '@aiui/core/types/content' + +export const mockPlaces: Place[] = [ + { id: 'p1', name: 'Bitcoin Tower', address: 'Zug, Switzerland', lat: 47.1661, lng: 8.5155, category: 'Landmark', description: 'Heart of Crypto Valley, home to numerous Bitcoin companies.', rating: 4.5, sources: [{ type: 'osm', name: 'OpenStreetMap', url: 'https://www.openstreetmap.org/?mlat=47.1661&mlon=8.5155' }] }, + { id: 'p2', name: 'El Zonte (Bitcoin Beach)', address: 'El Zonte, La Libertad, El Salvador', lat: 13.4967, lng: -89.3894, category: 'Beach', description: 'The birthplace of Bitcoin adoption in El Salvador.', rating: 4.7, sources: [{ type: 'osm', name: 'OpenStreetMap', url: 'https://www.openstreetmap.org/?mlat=13.4967&mlon=-89.3894' }] }, + { id: 'p3', name: 'Shibuya Crossing', address: 'Shibuya, Tokyo, Japan', lat: 35.6595, lng: 139.7004, category: 'Landmark', description: 'The world\'s busiest pedestrian crossing.', rating: 4.6, sources: [{ type: 'osm', name: 'OpenStreetMap', url: 'https://www.openstreetmap.org/?mlat=35.6595&mlon=139.7004' }] }, + { id: 'p4', name: 'CERN', address: 'Meyrin, Geneva, Switzerland', lat: 46.2335, lng: 6.0553, category: 'Science', description: 'European Organization for Nuclear Research, birthplace of the World Wide Web.', rating: 4.8, sources: [{ type: 'osm', name: 'OpenStreetMap', url: 'https://www.openstreetmap.org/?mlat=46.2335&mlon=6.0553' }] }, + { id: 'p5', name: 'Akihabara', address: 'Akihabara, Tokyo, Japan', lat: 35.6984, lng: 139.7731, category: 'District', description: 'Tokyo\'s electronics and anime district.', rating: 4.4, sources: [{ type: 'osm', name: 'OpenStreetMap', url: 'https://www.openstreetmap.org/?mlat=35.6984&mlon=139.7731' }] }, + { id: 'p6', name: 'Hacker Dojo', address: 'San Jose, CA, USA', lat: 37.3506, lng: -121.9550, category: 'Hackerspace', description: 'Community space for hackers and makers in Silicon Valley.', rating: 4.3, sources: [{ type: 'osm', name: 'OpenStreetMap', url: 'https://www.openstreetmap.org/?mlat=37.3506&mlon=-121.9550' }] }, + { id: 'p7', name: 'Machu Picchu', address: 'Cusco Region, Peru', lat: -13.1631, lng: -72.5450, category: 'Archaeological', description: '15th-century Inca citadel set high in the Andes Mountains.', rating: 4.9, sources: [{ type: 'osm', name: 'OpenStreetMap', url: 'https://www.openstreetmap.org/?mlat=-13.1631&mlon=-72.5450' }] }, + { id: 'p8', name: 'Reykjavik', address: 'Reykjavik, Iceland', lat: 64.1466, lng: -21.9426, category: 'City', description: 'World\'s northernmost capital, known for geothermal energy and bitcoin mining.', rating: 4.6, sources: [{ type: 'osm', name: 'OpenStreetMap', url: 'https://www.openstreetmap.org/?mlat=64.1466&mlon=-21.9426' }] }, + { id: 'p9', name: 'MIT Media Lab', address: 'Cambridge, MA, USA', lat: 42.3601, lng: -71.0879, category: 'Research', description: 'Research laboratory at MIT known for unconventional technology research.', rating: 4.7, sources: [{ type: 'osm', name: 'OpenStreetMap', url: 'https://www.openstreetmap.org/?mlat=42.3601&mlon=-71.0879' }] }, + { id: 'p10', name: 'Svalbard Global Seed Vault', address: 'Longyearbyen, Svalbard, Norway', lat: 78.2355, lng: 15.4942, category: 'Science', description: 'Secure seed bank storing duplicates of seeds from crop collections worldwide.', rating: 4.8, sources: [{ type: 'osm', name: 'OpenStreetMap', url: 'https://www.openstreetmap.org/?mlat=78.2355&mlon=15.4942' }] }, + { id: 'p11', name: 'Room 77', address: 'Graefestraße, Berlin, Germany', lat: 52.4912, lng: 13.4188, category: 'Restaurant', description: 'One of the first bars in the world to accept Bitcoin (now closed, historic).', rating: 4.2, sources: [{ type: 'osm', name: 'OpenStreetMap', url: 'https://www.openstreetmap.org/?mlat=52.4912&mlon=13.4188' }] }, + { id: 'p12', name: 'Antigua Bitcoin Beach', address: 'Antigua, Guatemala', lat: 14.5586, lng: -90.7295, category: 'Town', description: 'Growing Bitcoin circular economy in historic colonial town.', rating: 4.5, sources: [{ type: 'osm', name: 'OpenStreetMap', url: 'https://www.openstreetmap.org/?mlat=14.5586&mlon=-90.7295' }] }, + { id: 'p13', name: 'Bletchley Park', address: 'Milton Keynes, UK', lat: 51.9977, lng: -0.7417, category: 'Museum', description: 'Historic site of WWII codebreaking, where Turing and team cracked Enigma.', rating: 4.7, sources: [{ type: 'osm', name: 'OpenStreetMap', url: 'https://www.openstreetmap.org/?mlat=51.9977&mlon=-0.7417' }] }, + { id: 'p14', name: 'La Sagrada Familia', address: 'Barcelona, Spain', lat: 41.4036, lng: 2.1744, category: 'Architecture', description: 'Antoni Gaudí\'s unfinished masterpiece basilica.', rating: 4.8, sources: [{ type: 'osm', name: 'OpenStreetMap', url: 'https://www.openstreetmap.org/?mlat=41.4036&mlon=2.1744' }] }, + { id: 'p15', name: 'The Internet Archive', address: 'San Francisco, CA, USA', lat: 37.7823, lng: -122.4714, category: 'Library', description: 'Non-profit digital library offering free access to archived web pages and media.', rating: 4.6, sources: [{ type: 'osm', name: 'OpenStreetMap', url: 'https://www.openstreetmap.org/?mlat=37.7823&mlon=-122.4714' }] }, + { id: 'p16', name: 'Madeira Bitcoin Island', address: 'Funchal, Madeira, Portugal', lat: 32.6669, lng: -16.9241, category: 'Island', description: 'Portuguese island adopting Bitcoin as part of its economic strategy.', rating: 4.4, sources: [{ type: 'osm', name: 'OpenStreetMap', url: 'https://www.openstreetmap.org/?mlat=32.6669&mlon=-16.9241' }] }, + { id: 'p17', name: 'Kowloon Walled City Park', address: 'Kowloon, Hong Kong', lat: 22.3315, lng: 114.1889, category: 'Park', description: 'Memorial park on the site of the former Kowloon Walled City.', rating: 4.3, sources: [{ type: 'osm', name: 'OpenStreetMap', url: 'https://www.openstreetmap.org/?mlat=22.3315&mlon=114.1889' }] }, + { id: 'p18', name: 'Bitcoin Lake', address: 'Panajachel, Guatemala', lat: 14.7403, lng: -91.1594, category: 'Lake', description: 'Lake Atitlán community promoting Bitcoin circular economy.', rating: 4.5, sources: [{ type: 'osm', name: 'OpenStreetMap', url: 'https://www.openstreetmap.org/?mlat=14.7403&mlon=-91.1594' }] }, + { id: 'p19', name: 'Taipei 101', address: 'Xinyi District, Taipei, Taiwan', lat: 25.0340, lng: 121.5645, category: 'Skyscraper', description: 'Former world\'s tallest building, now a tech hub landmark.', rating: 4.7, sources: [{ type: 'osm', name: 'OpenStreetMap', url: 'https://www.openstreetmap.org/?mlat=25.0340&mlon=121.5645' }] }, + { id: 'p20', name: 'Chiang Mai Old City', address: 'Chiang Mai, Thailand', lat: 18.7883, lng: 98.9853, category: 'District', description: 'Popular digital nomad hub with growing Bitcoin acceptance.', rating: 4.6, sources: [{ type: 'osm', name: 'OpenStreetMap', url: 'https://www.openstreetmap.org/?mlat=18.7883&mlon=98.9853' }] }, + { id: 'p21', name: 'Nostr Café', address: 'Prague, Czech Republic', lat: 50.0755, lng: 14.4378, category: 'Café', description: 'Crypto-friendly café in the heart of Prague\'s bitcoin community.', rating: 4.4, sources: [{ type: 'osm', name: 'OpenStreetMap', url: 'https://www.openstreetmap.org/?mlat=50.0755&mlon=14.4378' }] }, +] + +export function searchPlaces(query: string): Place[] { + const q = query.toLowerCase() + return mockPlaces.filter( + (p) => + p.name.toLowerCase().includes(q) || + (p.address ?? '').toLowerCase().includes(q) || + (p.category ?? '').toLowerCase().includes(q) || + (p.description?.toLowerCase().includes(q) ?? false) + ) +} diff --git a/packages/app/src/mocks/podcasts.ts b/packages/app/src/mocks/podcasts.ts index bbbdecaf..2d26ab6b 100644 --- a/packages/app/src/mocks/podcasts.ts +++ b/packages/app/src/mocks/podcasts.ts @@ -95,6 +95,21 @@ export const mockPodcasts: Podcast[] = [ { type: 'rss', name: 'RSS', url: 'https://cypherpunkbitstream.com/feed', icon: '📡' }, ], }, + { id: 'p7', title: 'Bitcoin Audible', host: 'Guy Swann', description: 'Reading the best in Bitcoin content, one article at a time.', coverUrl: undefined, year: 2017, episodeCount: 600, genres: ['Bitcoin', 'Education'], sources: [{ type: 'fountain', name: 'Fountain', url: 'https://fountain.fm/show/bitcoinaudible', icon: '⚡' }] }, + { id: 'p8', title: 'The Bitcoin Standard Podcast', host: 'Saifedean Ammous', description: 'Economics, sound money, and the case for Bitcoin.', coverUrl: undefined, year: 2019, episodeCount: 200, genres: ['Bitcoin', 'Economics'], sources: [{ type: 'fountain', name: 'Fountain', url: 'https://fountain.fm/show/tbs', icon: '⚡' }] }, + { id: 'p9', title: 'Bitcoin Explained', host: 'Aaron van Wirdum & Sjors Provoost', description: 'Technical explanations of Bitcoin protocol developments.', coverUrl: undefined, year: 2020, episodeCount: 150, genres: ['Bitcoin', 'Technology'], sources: [{ type: 'rss', name: 'RSS', url: 'https://bitcoinexplained.com/feed', icon: '📡' }] }, + { id: 'p10', title: 'Nostr Talks', host: 'The Nostr Community', description: 'Discussions about the Nostr protocol, clients, and ecosystem.', coverUrl: undefined, year: 2023, episodeCount: 60, genres: ['Nostr', 'Decentralization', 'Tech'], sources: [{ type: 'fountain', name: 'Fountain', url: 'https://fountain.fm/show/nostrtalks', icon: '⚡' }] }, + { id: 'p11', title: 'Lex Fridman Podcast', host: 'Lex Fridman', description: 'Conversations about the nature of intelligence, consciousness, love, and power.', coverUrl: undefined, year: 2018, episodeCount: 420, genres: ['Science', 'Technology', 'Philosophy'], sources: [{ type: 'youtube', name: 'YouTube', url: 'https://youtube.com/@lexfridman', icon: '▶️' }] }, + { id: 'p12', title: 'Darknet Diaries', host: 'Jack Rhysider', description: 'True stories from the dark side of the Internet.', coverUrl: undefined, year: 2017, episodeCount: 160, genres: ['Cybersecurity', 'True Crime', 'Technology'], sources: [{ type: 'fountain', name: 'Fountain', url: 'https://fountain.fm/show/darknetdiaries', icon: '⚡' }] }, + { id: 'p13', title: 'The Investors Podcast', host: 'Preston Pysh & Stig Brodersen', description: 'Value investing, Bitcoin, and financial analysis.', coverUrl: undefined, year: 2014, episodeCount: 700, genres: ['Bitcoin', 'Investing', 'Finance'], sources: [{ type: 'fountain', name: 'Fountain', url: 'https://fountain.fm/show/tip', icon: '⚡' }] }, + { id: 'p14', title: 'Rabbit Hole Recap', host: 'Matt Odell & Marty Bent', description: 'Weekly Bitcoin news and analysis.', coverUrl: undefined, year: 2019, episodeCount: 250, genres: ['Bitcoin', 'News'], sources: [{ type: 'fountain', name: 'Fountain', url: 'https://fountain.fm/show/rhr', icon: '⚡' }] }, + { id: 'p15', title: 'Citadel Dispatch', host: 'Matt Odell', description: 'Interactive Bitcoin discussion with audience participation.', coverUrl: undefined, year: 2021, episodeCount: 130, genres: ['Bitcoin', 'Privacy', 'Open Source'], sources: [{ type: 'fountain', name: 'Fountain', url: 'https://fountain.fm/show/citadeldispatch', icon: '⚡' }, { type: 'youtube', name: 'YouTube', url: 'https://youtube.com/@citadeldispatch', icon: '▶️' }] }, + { id: 'p16', title: 'Hardcore History', host: 'Dan Carlin', description: 'Deep dives into the hardest core history topics.', coverUrl: undefined, year: 2006, episodeCount: 70, genres: ['History', 'Education'], sources: [{ type: 'rss', name: 'RSS', url: 'https://dchhaddendum.libsyn.com/rss', icon: '📡' }] }, + { id: 'p17', title: 'The Changelog', host: 'Adam Stacoviak & Jerod Santo', description: 'Conversations with the hackers, leaders, and innovators of open source.', coverUrl: undefined, year: 2009, episodeCount: 600, genres: ['Open Source', 'Technology', 'Programming'], sources: [{ type: 'rss', name: 'RSS', url: 'https://changelog.com/podcast/feed', icon: '📡' }] }, + { id: 'p18', title: 'Once BITten!', host: 'Daniel Prince', description: 'Bitcoin, philosophy, and the orange pill journey.', coverUrl: undefined, year: 2019, episodeCount: 350, genres: ['Bitcoin', 'Philosophy'], sources: [{ type: 'fountain', name: 'Fountain', url: 'https://fountain.fm/show/oncebitten', icon: '⚡' }] }, + { id: 'p19', title: 'Bitcoin Fundamentals', host: 'Preston Pysh', description: 'Understanding Bitcoin from first principles.', coverUrl: undefined, year: 2020, episodeCount: 180, genres: ['Bitcoin', 'Education', 'Finance'], sources: [{ type: 'fountain', name: 'Fountain', url: 'https://fountain.fm/show/btcfundamentals', icon: '⚡' }] }, + { id: 'p20', title: 'Opt Out Podcast', host: 'Seth For Privacy', description: 'Privacy tools, techniques, and philosophy for everyone.', coverUrl: undefined, year: 2021, episodeCount: 90, genres: ['Privacy', 'Technology', 'Security'], sources: [{ type: 'fountain', name: 'Fountain', url: 'https://fountain.fm/show/optout', icon: '⚡' }, { type: 'rss', name: 'RSS', url: 'https://optoutpod.com/feed', icon: '📡' }] }, + { id: 'p21', title: 'Bitcoin Review', host: 'NVK & community', description: 'Technical Bitcoin development review and discussion.', coverUrl: undefined, year: 2022, episodeCount: 75, genres: ['Bitcoin', 'Development', 'Open Source'], sources: [{ type: 'fountain', name: 'Fountain', url: 'https://fountain.fm/show/bitcoinreview', icon: '⚡' }] }, ] export function searchPodcasts(query: string): Podcast[] { diff --git a/packages/app/src/mocks/songs.ts b/packages/app/src/mocks/songs.ts index c3b3cfad..1aacf62f 100644 --- a/packages/app/src/mocks/songs.ts +++ b/packages/app/src/mocks/songs.ts @@ -103,4 +103,16 @@ export const mockSongs: Song[] = [ genres: ['Math Rock', 'Indie'], sources: [{ type: 'spotify', name: 'Spotify', url: 'https://open.spotify.com/track/example9', icon: 'spotify' }], }, + { id: 's10', title: 'Atlas', artist: 'Polyphia', album: 'Muse', year: 2014, coverUrl: undefined, duration: 245, genres: ['Math Rock', 'Progressive'], sources: [{ type: 'spotify', name: 'Spotify', url: 'https://open.spotify.com/track/example10', icon: 'spotify' }] }, + { id: 's11', title: 'G.O.A.T.', artist: 'Polyphia', album: 'New Levels New Devils', year: 2018, coverUrl: undefined, duration: 203, genres: ['Math Rock', 'Progressive'], sources: [{ type: 'youtube', name: 'YouTube', url: 'https://youtube.com/watch?v=goat', icon: 'youtube' }] }, + { id: 's12', title: 'Electric Sunrise', artist: 'Plini', album: 'Handmade Cities', year: 2016, coverUrl: undefined, duration: 284, genres: ['Progressive', 'Instrumental'], sources: [{ type: 'bandcamp', name: 'Bandcamp', url: 'https://plini.bandcamp.com', icon: 'bandcamp' }] }, + { id: 's13', title: 'The Number of the Beast', artist: 'Iron Maiden', album: 'The Number of the Beast', year: 1982, coverUrl: undefined, duration: 289, genres: ['Heavy Metal', 'NWOBHM'], sources: [{ type: 'spotify', name: 'Spotify', url: 'https://open.spotify.com/track/example13', icon: 'spotify' }] }, + { id: 's14', title: 'Value 4 Value', artist: 'Ainsley Costello', album: 'Lightning Sessions', year: 2023, coverUrl: undefined, duration: 195, genres: ['Folk', 'Bitcoin'], sources: [{ type: 'wavlake', name: 'Wavlake', url: 'https://wavlake.com/track/v4v', icon: 'wavlake' }] }, + { id: 's15', title: 'Bitcoin Thunder', artist: 'Mandrik', album: 'Orange Pill', year: 2022, coverUrl: undefined, duration: 178, genres: ['Electronic', 'Bitcoin'], sources: [{ type: 'wavlake', name: 'Wavlake', url: 'https://wavlake.com/track/thunder', icon: 'wavlake' }] }, + { id: 's16', title: 'Lateralus', artist: 'Tool', album: 'Lateralus', year: 2001, coverUrl: undefined, duration: 563, genres: ['Progressive Metal', 'Art Rock'], sources: [{ type: 'spotify', name: 'Spotify', url: 'https://open.spotify.com/track/example16', icon: 'spotify' }] }, + { id: 's17', title: 'Teardrop', artist: 'Massive Attack', album: 'Mezzanine', year: 1998, coverUrl: undefined, duration: 323, genres: ['Trip Hop', 'Electronic'], sources: [{ type: 'spotify', name: 'Spotify', url: 'https://open.spotify.com/track/example17', icon: 'spotify' }] }, + { id: 's18', title: 'Windowlicker', artist: 'Aphex Twin', album: 'Windowlicker EP', year: 1999, coverUrl: undefined, duration: 371, genres: ['IDM', 'Electronic'], sources: [{ type: 'bandcamp', name: 'Bandcamp', url: 'https://aphextwin.bandcamp.com', icon: 'bandcamp' }] }, + { id: 's19', title: 'Schism', artist: 'Tool', album: 'Lateralus', year: 2001, coverUrl: undefined, duration: 399, genres: ['Progressive Metal'], sources: [{ type: 'spotify', name: 'Spotify', url: 'https://open.spotify.com/track/example19', icon: 'spotify' }] }, + { id: 's20', title: 'Flim', artist: 'Aphex Twin', album: 'Come to Daddy EP', year: 1997, coverUrl: undefined, duration: 170, genres: ['IDM', 'Ambient'], sources: [{ type: 'bandcamp', name: 'Bandcamp', url: 'https://aphextwin.bandcamp.com', icon: 'bandcamp' }] }, + { id: 's21', title: 'Bitcoin is Dead', artist: 'HODL Band', album: 'Stack Sats', year: 2024, coverUrl: undefined, duration: 212, genres: ['Rock', 'Bitcoin'], sources: [{ type: 'wavlake', name: 'Wavlake', url: 'https://wavlake.com/track/dead', icon: 'wavlake' }] }, ] diff --git a/packages/app/src/mocks/tmdb.ts b/packages/app/src/mocks/tmdb.ts new file mode 100644 index 00000000..33278714 --- /dev/null +++ b/packages/app/src/mocks/tmdb.ts @@ -0,0 +1,61 @@ +export interface TMDBSearchResult { + id: number + title: string + overview: string + poster_path: string | null + backdrop_path: string | null + release_date: string + vote_average: number + genre_ids: number[] +} + +export interface TMDBSearchResponse { + page: number + results: TMDBSearchResult[] + total_pages: number + total_results: number +} + +export const mockTMDBGenres: Record = { + 28: 'Action', 12: 'Adventure', 16: 'Animation', 35: 'Comedy', 80: 'Crime', + 99: 'Documentary', 18: 'Drama', 10751: 'Family', 14: 'Fantasy', 36: 'History', + 27: 'Horror', 10402: 'Music', 9648: 'Mystery', 10749: 'Romance', 878: 'Sci-Fi', + 53: 'Thriller', 10752: 'War', 37: 'Western', +} + +export const mockTMDBSearchResponses: Record = { + 'blade runner': { + page: 1, + total_pages: 1, + total_results: 2, + results: [ + { id: 335984, title: 'Blade Runner 2049', overview: 'A young blade runner discovers a long-buried secret...', poster_path: '/gajva2L0rPYkEWjzgFlBXCAVBE5.jpg', backdrop_path: '/sAtoMqDVhNDQBc3QJL3RF6hlhGq.jpg', release_date: '2017-10-04', vote_average: 7.5, genre_ids: [878, 18, 53] }, + { id: 78, title: 'Blade Runner', overview: 'In the smog-choked dystopian Los Angeles of 2019...', poster_path: '/63N9uy8nd9j7Eog2axPQ8lbr3Wj.jpg', backdrop_path: '/sXNGrxZRsqmyVv9CnUX2NZQzwSg.jpg', release_date: '1982-06-25', vote_average: 7.9, genre_ids: [878, 18, 53] }, + ], + }, + 'dune': { + page: 1, + total_pages: 1, + total_results: 2, + results: [ + { id: 438631, title: 'Dune', overview: 'Paul Atreides, a brilliant and gifted young man...', poster_path: '/d5NXSklXo0qyIYkgV94XAgMIckC.jpg', backdrop_path: '/jYEW5xZkZk2WTrdbMGAPFuBqbDc.jpg', release_date: '2021-09-15', vote_average: 7.8, genre_ids: [878, 12, 18] }, + { id: 693134, title: 'Dune: Part Two', overview: 'Paul Atreides unites with Chani and the Fremen...', poster_path: '/8b8R8l88Qje9dn9OE8PY05Nxl1X.jpg', backdrop_path: '/xOMo8BRK7PfcJv9JCnx7s5hj0PX.jpg', release_date: '2024-02-27', vote_average: 8.3, genre_ids: [878, 12, 18] }, + ], + }, + 'interstellar': { + page: 1, + total_pages: 1, + total_results: 1, + results: [ + { id: 157336, title: 'Interstellar', overview: 'A team of explorers travel through a wormhole...', poster_path: '/gEU2QniE6E77NI6lCU6MxlNBvIx.jpg', backdrop_path: '/xJHokMbljvjADYdit5fK1DDtAoB.jpg', release_date: '2014-11-05', vote_average: 8.6, genre_ids: [878, 12, 18] }, + ], + }, +} + +export function mockTMDBSearch(query: string): TMDBSearchResponse { + const key = query.toLowerCase() + for (const [term, response] of Object.entries(mockTMDBSearchResponses)) { + if (key.includes(term)) return response + } + return { page: 1, results: [], total_pages: 0, total_results: 0 } +} diff --git a/packages/app/src/mocks/tvshows.ts b/packages/app/src/mocks/tvshows.ts new file mode 100644 index 00000000..ce9d446b --- /dev/null +++ b/packages/app/src/mocks/tvshows.ts @@ -0,0 +1,35 @@ +import type { TVSeries } from '@aiui/core/types/content' + +export const mockTVShows: TVSeries[] = [ + { id: 'tv1', title: 'Mr. Robot', year: 2015, posterUrl: 'https://image.tmdb.org/t/p/w342/oKIBhzZzDX07SoE2bOLhq2EE8rf.jpg', synopsis: 'Follows a young computer programmer who joins an underground hacker group aiming to destroy all debt records.', genres: ['Drama', 'Thriller', 'Crime'], rating: 8.5, seasons: 4, status: 'ended', network: 'USA Network', sources: [{ type: 'plex', name: 'Plex', url: 'plex://play/tv/mr-robot', quality: '1080p', icon: 'plex' }] }, + { id: 'tv2', title: 'Black Mirror', year: 2011, posterUrl: 'https://image.tmdb.org/t/p/w342/5UaYsGZOFhjFDwQh6GuLjjA1WlF.jpg', synopsis: 'An anthology series exploring a twisted, high-tech multiverse where humanity\'s greatest innovations collide with its darkest instincts.', genres: ['Sci-Fi', 'Drama', 'Thriller'], rating: 8.1, seasons: 6, status: 'ongoing', network: 'Netflix', sources: [{ type: 'plex', name: 'Plex', url: 'plex://play/tv/black-mirror', quality: '4K', icon: 'plex' }] }, + { id: 'tv3', title: 'Severance', year: 2022, posterUrl: 'https://image.tmdb.org/t/p/w342/lFf6LLrQjYFOI3cXMfrGQ2gylPF.jpg', synopsis: 'Mark leads a team at Lumon Industries whose employees have undergone a severance procedure dividing their memories between work and personal lives.', genres: ['Sci-Fi', 'Drama', 'Mystery'], rating: 8.7, seasons: 2, status: 'ongoing', network: 'Apple TV+', sources: [{ type: 'plex', name: 'Plex', url: 'plex://play/tv/severance', quality: '4K HDR', icon: 'plex' }] }, + { id: 'tv4', title: 'Breaking Bad', year: 2008, posterUrl: 'https://image.tmdb.org/t/p/w342/ggFHVNu6YYI5L9pCfOacjizRGt.jpg', synopsis: 'A high school chemistry teacher turned methamphetamine manufacturer partners with a former student.', genres: ['Drama', 'Crime', 'Thriller'], rating: 9.5, seasons: 5, status: 'ended', network: 'AMC', sources: [{ type: 'plex', name: 'Plex', url: 'plex://play/tv/breaking-bad', quality: '4K', icon: 'plex' }] }, + { id: 'tv5', title: 'The Expanse', year: 2015, posterUrl: 'https://image.tmdb.org/t/p/w342/go2RyYkh2gTRp2EL7sYDWTK1ioi.jpg', synopsis: 'In the 24th century, a group of humans untangle a vast conspiracy that threatens the Solar System\'s fragile state of cold war.', genres: ['Sci-Fi', 'Drama'], rating: 8.5, seasons: 6, status: 'ended', network: 'Amazon', sources: [{ type: 'plex', name: 'Plex', url: 'plex://play/tv/the-expanse', quality: '4K HDR', icon: 'plex' }] }, + { id: 'tv6', title: 'Westworld', year: 2016, posterUrl: 'https://image.tmdb.org/t/p/w342/y55oBgC98yJT0aejxbJMzTUlHlh.jpg', synopsis: 'Set at the intersection of the near future and a reimagined past, explore a world in which every human appetite can be indulged.', genres: ['Sci-Fi', 'Drama', 'Mystery'], rating: 8.0, seasons: 4, status: 'ended', network: 'HBO', sources: [{ type: 'plex', name: 'Plex', url: 'plex://play/tv/westworld', quality: '4K HDR', icon: 'plex' }] }, + { id: 'tv7', title: 'True Detective', year: 2014, posterUrl: 'https://image.tmdb.org/t/p/w342/aowr4xpLP5sRCL50TkuADomJ20T.jpg', synopsis: 'Seasonal anthology series about police investigations uncovering the personal and professional secrets of those involved.', genres: ['Drama', 'Crime', 'Mystery'], rating: 8.3, seasons: 4, status: 'ongoing', network: 'HBO', sources: [{ type: 'plex', name: 'Plex', url: 'plex://play/tv/true-detective', quality: '4K', icon: 'plex' }] }, + { id: 'tv8', title: 'Altered Carbon', year: 2018, posterUrl: 'https://image.tmdb.org/t/p/w342/95IhdCkqp0MI9pGemJMFi3bEqbV.jpg', synopsis: 'Set in a future where consciousness is digitized and stored, a prisoner returns to life in a new body to solve a murder.', genres: ['Sci-Fi', 'Action', 'Drama'], rating: 7.8, seasons: 2, status: 'ended', network: 'Netflix', sources: [{ type: 'plex', name: 'Plex', url: 'plex://play/tv/altered-carbon', quality: '4K HDR', icon: 'plex' }] }, + { id: 'tv9', title: 'Chernobyl', year: 2019, posterUrl: 'https://image.tmdb.org/t/p/w342/hlLXt2tOPT6RRnjiUmoxyG1LTFi.jpg', synopsis: 'In April 1986, the city of Chernobyl in the Soviet Union suffers one of the worst nuclear disasters in history.', genres: ['Drama', 'History'], rating: 9.4, seasons: 1, status: 'ended', network: 'HBO', sources: [{ type: 'plex', name: 'Plex', url: 'plex://play/tv/chernobyl', quality: '1080p', icon: 'plex' }] }, + { id: 'tv10', title: 'The Wire', year: 2002, posterUrl: 'https://image.tmdb.org/t/p/w342/4lbclFySvugI51fwsyxBTOm4DqK.jpg', synopsis: 'The Baltimore drug scene, as seen through the eyes of drug dealers and law enforcement.', genres: ['Drama', 'Crime'], rating: 9.3, seasons: 5, status: 'ended', network: 'HBO', sources: [{ type: 'plex', name: 'Plex', url: 'plex://play/tv/the-wire', quality: '1080p', icon: 'plex' }] }, + { id: 'tv11', title: 'Dark', year: 2017, posterUrl: 'https://image.tmdb.org/t/p/w342/apbrbWs8M9lyOpJYU5WXrpFbk1Z.jpg', synopsis: 'A family saga with a supernatural twist in a German town where the disappearance of children exposes dark secrets.', genres: ['Sci-Fi', 'Drama', 'Mystery'], rating: 8.8, seasons: 3, status: 'ended', network: 'Netflix', sources: [{ type: 'plex', name: 'Plex', url: 'plex://play/tv/dark', quality: '4K', icon: 'plex' }] }, + { id: 'tv12', title: 'Silicon Valley', year: 2014, posterUrl: 'https://image.tmdb.org/t/p/w342/dc5r71XI1gD4YwIyoEREagVo0lp.jpg', synopsis: 'Follows the misadventures of introverted programmer Richard and his fellow geeks trying to succeed in Silicon Valley.', genres: ['Comedy'], rating: 8.5, seasons: 6, status: 'ended', network: 'HBO', sources: [{ type: 'plex', name: 'Plex', url: 'plex://play/tv/silicon-valley', quality: '1080p', icon: 'plex' }] }, + { id: 'tv13', title: 'Love, Death & Robots', year: 2019, posterUrl: 'https://image.tmdb.org/t/p/w342/dSFlhAo9lgerSXj7WRhp8Ilo0wp.jpg', synopsis: 'Terrifying creatures, wicked surprises and dark comedy converge in this NSFW anthology of animated stories.', genres: ['Animation', 'Sci-Fi', 'Horror'], rating: 8.3, seasons: 3, status: 'ongoing', network: 'Netflix', sources: [{ type: 'plex', name: 'Plex', url: 'plex://play/tv/love-death-robots', quality: '4K HDR', icon: 'plex' }] }, + { id: 'tv14', title: 'Devs', year: 2020, posterUrl: 'https://image.tmdb.org/t/p/w342/e1j2oHE9V7bnQIDt3W6IVqaFBm4.jpg', synopsis: 'A young software engineer investigates the secretive development division of her employer.', genres: ['Sci-Fi', 'Drama', 'Thriller'], rating: 7.6, seasons: 1, status: 'ended', network: 'Hulu', sources: [{ type: 'plex', name: 'Plex', url: 'plex://play/tv/devs', quality: '4K', icon: 'plex' }] }, + { id: 'tv15', title: 'Halt and Catch Fire', year: 2014, posterUrl: 'https://image.tmdb.org/t/p/w342/vfMFGUbhI2hD7IL3yCf4a0ImTGl.jpg', synopsis: 'Follows the personal computing revolution, chronicling the battles between fictional visionaries.', genres: ['Drama'], rating: 8.4, seasons: 4, status: 'ended', network: 'AMC', sources: [{ type: 'plex', name: 'Plex', url: 'plex://play/tv/halt-and-catch-fire', quality: '1080p', icon: 'plex' }] }, + { id: 'tv16', title: 'Stranger Things', year: 2016, posterUrl: 'https://image.tmdb.org/t/p/w342/49WJfeN0moxb9IPfGn8AIqMGskD.jpg', synopsis: 'When a young boy disappears, his mother, a police chief, and friends uncover a mystery involving secret experiments.', genres: ['Sci-Fi', 'Drama', 'Horror'], rating: 8.7, seasons: 4, status: 'ongoing', network: 'Netflix', sources: [{ type: 'plex', name: 'Plex', url: 'plex://play/tv/stranger-things', quality: '4K HDR', icon: 'plex' }] }, + { id: 'tv17', title: 'Battlestar Galactica', year: 2004, posterUrl: 'https://image.tmdb.org/t/p/w342/4m0YfBztahZgapdsHNBG2tFu7uB.jpg', synopsis: 'After the Cylons\' attack, the survivors of the Twelve Colonies search for the fabled planet Earth.', genres: ['Sci-Fi', 'Drama', 'Action'], rating: 8.7, seasons: 4, status: 'ended', network: 'Syfy', sources: [{ type: 'plex', name: 'Plex', url: 'plex://play/tv/bsg', quality: '1080p', icon: 'plex' }] }, + { id: 'tv18', title: 'Cowboy Bebop', year: 1998, posterUrl: 'https://image.tmdb.org/t/p/w342/m8PDMXZ4JccjOp3Bfk0yvihVE1r.jpg', synopsis: 'A ragtag crew of bounty hunters chases the most dangerous criminals through space.', genres: ['Animation', 'Sci-Fi', 'Action'], rating: 8.9, seasons: 1, status: 'ended', network: 'TV Tokyo', sources: [{ type: 'plex', name: 'Plex', url: 'plex://play/tv/cowboy-bebop', quality: '1080p', icon: 'plex' }] }, + { id: 'tv19', title: 'Shogun', year: 2024, posterUrl: 'https://image.tmdb.org/t/p/w342/7O4iVfOMQmdCSxhOg1WnzG1AgYT.jpg', synopsis: 'In Japan in 1600, a collision of civilizations creates conflict between ambitious lords and a shipwrecked English pilot.', genres: ['Drama', 'History', 'War'], rating: 8.7, seasons: 1, status: 'ongoing', network: 'FX', sources: [{ type: 'plex', name: 'Plex', url: 'plex://play/tv/shogun', quality: '4K HDR', icon: 'plex' }] }, + { id: 'tv20', title: 'Fringe', year: 2008, posterUrl: 'https://image.tmdb.org/t/p/w342/sY9hg5dLJ93RVOgv7CY1GT1PLR2.jpg', synopsis: 'An FBI agent is forced to work with an institutionalized scientist and his son to investigate fringe events.', genres: ['Sci-Fi', 'Drama', 'Mystery'], rating: 8.4, seasons: 5, status: 'ended', network: 'Fox', sources: [{ type: 'plex', name: 'Plex', url: 'plex://play/tv/fringe', quality: '1080p', icon: 'plex' }] }, + { id: 'tv21', title: 'The Mandalorian', year: 2019, posterUrl: 'https://image.tmdb.org/t/p/w342/sWgBv7LV2PRoQgkxwlibdGXKz1S.jpg', synopsis: 'A lone gunfighter in the outer reaches of the galaxy navigates his way through the post-Empire era.', genres: ['Sci-Fi', 'Action', 'Adventure'], rating: 8.4, seasons: 3, status: 'ongoing', network: 'Disney+', sources: [{ type: 'plex', name: 'Plex', url: 'plex://play/tv/the-mandalorian', quality: '4K HDR', icon: 'plex' }] }, +] + +export function searchTVShows(query: string): TVSeries[] { + const q = query.toLowerCase() + return mockTVShows.filter( + (t) => + t.title.toLowerCase().includes(q) || + (t.genres ?? []).some((g) => g.toLowerCase().includes(q)) || + (t.network ?? '').toLowerCase().includes(q) + ) +} diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index d908ecb8..6a2a56da 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -67,6 +67,15 @@ importers: '@playwright/test': specifier: ^1.49.0 version: 1.58.2 + '@storybook/addon-essentials': + specifier: ^8.6.0 + version: 8.6.14(@types/react@19.2.14)(storybook@8.6.17) + '@storybook/vue3': + specifier: ^8.6.0 + version: 8.6.17(storybook@8.6.17)(vue@3.5.29(typescript@5.8.3)) + '@storybook/vue3-vite': + specifier: ^8.6.0 + version: 8.6.17(storybook@8.6.17)(vite@7.3.1(@types/node@25.3.3)(jiti@2.6.1)(lightningcss@1.31.1)(terser@5.46.0)(tsx@4.21.0)(yaml@2.8.2))(vue@3.5.29(typescript@5.8.3)) '@tailwindcss/vite': specifier: ^4.2.1 version: 4.2.1(vite@7.3.1(@types/node@25.3.3)(jiti@2.6.1)(lightningcss@1.31.1)(terser@5.46.0)(tsx@4.21.0)(yaml@2.8.2)) @@ -97,6 +106,9 @@ importers: rss-parser: specifier: ^3.13.0 version: 3.13.0 + storybook: + specifier: ^8.6.0 + version: 8.6.17 tailwindcss: specifier: ^4.2.1 version: 4.2.1 @@ -679,156 +691,312 @@ packages: '@chevrotain/utils@11.1.2': resolution: {integrity: sha512-4mudFAQ6H+MqBTfqLmU7G1ZwRzCLfJEooL/fsF6rCX5eePMbGhoy5n4g+G4vlh2muDcsCTJtL+uKbOzWxs5LHA==} + '@esbuild/aix-ppc64@0.25.12': + resolution: {integrity: sha512-Hhmwd6CInZ3dwpuGTF8fJG6yoWmsToE+vYgD4nytZVxcu1ulHpUQRAB1UJ8+N1Am3Mz4+xOByoQoSZf4D+CpkA==} + engines: {node: '>=18'} + cpu: [ppc64] + os: [aix] + '@esbuild/aix-ppc64@0.27.3': resolution: {integrity: sha512-9fJMTNFTWZMh5qwrBItuziu834eOCUcEqymSH7pY+zoMVEZg3gcPuBNxH1EvfVYe9h0x/Ptw8KBzv7qxb7l8dg==} engines: {node: '>=18'} cpu: [ppc64] os: [aix] + '@esbuild/android-arm64@0.25.12': + resolution: {integrity: sha512-6AAmLG7zwD1Z159jCKPvAxZd4y/VTO0VkprYy+3N2FtJ8+BQWFXU+OxARIwA46c5tdD9SsKGZ/1ocqBS/gAKHg==} + engines: {node: '>=18'} + cpu: [arm64] + os: [android] + '@esbuild/android-arm64@0.27.3': resolution: {integrity: sha512-YdghPYUmj/FX2SYKJ0OZxf+iaKgMsKHVPF1MAq/P8WirnSpCStzKJFjOjzsW0QQ7oIAiccHdcqjbHmJxRb/dmg==} engines: {node: '>=18'} cpu: [arm64] os: [android] + '@esbuild/android-arm@0.25.12': + resolution: {integrity: sha512-VJ+sKvNA/GE7Ccacc9Cha7bpS8nyzVv0jdVgwNDaR4gDMC/2TTRc33Ip8qrNYUcpkOHUT5OZ0bUcNNVZQ9RLlg==} + engines: {node: '>=18'} + cpu: [arm] + os: [android] + '@esbuild/android-arm@0.27.3': resolution: {integrity: sha512-i5D1hPY7GIQmXlXhs2w8AWHhenb00+GxjxRncS2ZM7YNVGNfaMxgzSGuO8o8SJzRc/oZwU2bcScvVERk03QhzA==} engines: {node: '>=18'} cpu: [arm] os: [android] + '@esbuild/android-x64@0.25.12': + resolution: {integrity: sha512-5jbb+2hhDHx5phYR2By8GTWEzn6I9UqR11Kwf22iKbNpYrsmRB18aX/9ivc5cabcUiAT/wM+YIZ6SG9QO6a8kg==} + engines: {node: '>=18'} + cpu: [x64] + os: [android] + '@esbuild/android-x64@0.27.3': resolution: {integrity: sha512-IN/0BNTkHtk8lkOM8JWAYFg4ORxBkZQf9zXiEOfERX/CzxW3Vg1ewAhU7QSWQpVIzTW+b8Xy+lGzdYXV6UZObQ==} engines: {node: '>=18'} cpu: [x64] os: [android] + '@esbuild/darwin-arm64@0.25.12': + resolution: {integrity: sha512-N3zl+lxHCifgIlcMUP5016ESkeQjLj/959RxxNYIthIg+CQHInujFuXeWbWMgnTo4cp5XVHqFPmpyu9J65C1Yg==} + engines: {node: '>=18'} + cpu: [arm64] + os: [darwin] + '@esbuild/darwin-arm64@0.27.3': resolution: {integrity: sha512-Re491k7ByTVRy0t3EKWajdLIr0gz2kKKfzafkth4Q8A5n1xTHrkqZgLLjFEHVD+AXdUGgQMq+Godfq45mGpCKg==} engines: {node: '>=18'} cpu: [arm64] os: [darwin] + '@esbuild/darwin-x64@0.25.12': + resolution: {integrity: sha512-HQ9ka4Kx21qHXwtlTUVbKJOAnmG1ipXhdWTmNXiPzPfWKpXqASVcWdnf2bnL73wgjNrFXAa3yYvBSd9pzfEIpA==} + engines: {node: '>=18'} + cpu: [x64] + os: [darwin] + '@esbuild/darwin-x64@0.27.3': resolution: {integrity: sha512-vHk/hA7/1AckjGzRqi6wbo+jaShzRowYip6rt6q7VYEDX4LEy1pZfDpdxCBnGtl+A5zq8iXDcyuxwtv3hNtHFg==} engines: {node: '>=18'} cpu: [x64] os: [darwin] + '@esbuild/freebsd-arm64@0.25.12': + resolution: {integrity: sha512-gA0Bx759+7Jve03K1S0vkOu5Lg/85dou3EseOGUes8flVOGxbhDDh/iZaoek11Y8mtyKPGF3vP8XhnkDEAmzeg==} + engines: {node: '>=18'} + cpu: [arm64] + os: [freebsd] + '@esbuild/freebsd-arm64@0.27.3': resolution: {integrity: sha512-ipTYM2fjt3kQAYOvo6vcxJx3nBYAzPjgTCk7QEgZG8AUO3ydUhvelmhrbOheMnGOlaSFUoHXB6un+A7q4ygY9w==} engines: {node: '>=18'} cpu: [arm64] os: [freebsd] + '@esbuild/freebsd-x64@0.25.12': + resolution: {integrity: sha512-TGbO26Yw2xsHzxtbVFGEXBFH0FRAP7gtcPE7P5yP7wGy7cXK2oO7RyOhL5NLiqTlBh47XhmIUXuGciXEqYFfBQ==} + engines: {node: '>=18'} + cpu: [x64] + os: [freebsd] + '@esbuild/freebsd-x64@0.27.3': resolution: {integrity: sha512-dDk0X87T7mI6U3K9VjWtHOXqwAMJBNN2r7bejDsc+j03SEjtD9HrOl8gVFByeM0aJksoUuUVU9TBaZa2rgj0oA==} engines: {node: '>=18'} cpu: [x64] os: [freebsd] + '@esbuild/linux-arm64@0.25.12': + resolution: {integrity: sha512-8bwX7a8FghIgrupcxb4aUmYDLp8pX06rGh5HqDT7bB+8Rdells6mHvrFHHW2JAOPZUbnjUpKTLg6ECyzvas2AQ==} + engines: {node: '>=18'} + cpu: [arm64] + os: [linux] + '@esbuild/linux-arm64@0.27.3': resolution: {integrity: sha512-sZOuFz/xWnZ4KH3YfFrKCf1WyPZHakVzTiqji3WDc0BCl2kBwiJLCXpzLzUBLgmp4veFZdvN5ChW4Eq/8Fc2Fg==} engines: {node: '>=18'} cpu: [arm64] os: [linux] + '@esbuild/linux-arm@0.25.12': + resolution: {integrity: sha512-lPDGyC1JPDou8kGcywY0YILzWlhhnRjdof3UlcoqYmS9El818LLfJJc3PXXgZHrHCAKs/Z2SeZtDJr5MrkxtOw==} + engines: {node: '>=18'} + cpu: [arm] + os: [linux] + '@esbuild/linux-arm@0.27.3': resolution: {integrity: sha512-s6nPv2QkSupJwLYyfS+gwdirm0ukyTFNl3KTgZEAiJDd+iHZcbTPPcWCcRYH+WlNbwChgH2QkE9NSlNrMT8Gfw==} engines: {node: '>=18'} cpu: [arm] os: [linux] + '@esbuild/linux-ia32@0.25.12': + resolution: {integrity: sha512-0y9KrdVnbMM2/vG8KfU0byhUN+EFCny9+8g202gYqSSVMonbsCfLjUO+rCci7pM0WBEtz+oK/PIwHkzxkyharA==} + engines: {node: '>=18'} + cpu: [ia32] + os: [linux] + '@esbuild/linux-ia32@0.27.3': resolution: {integrity: sha512-yGlQYjdxtLdh0a3jHjuwOrxQjOZYD/C9PfdbgJJF3TIZWnm/tMd/RcNiLngiu4iwcBAOezdnSLAwQDPqTmtTYg==} engines: {node: '>=18'} cpu: [ia32] os: [linux] + '@esbuild/linux-loong64@0.25.12': + resolution: {integrity: sha512-h///Lr5a9rib/v1GGqXVGzjL4TMvVTv+s1DPoxQdz7l/AYv6LDSxdIwzxkrPW438oUXiDtwM10o9PmwS/6Z0Ng==} + engines: {node: '>=18'} + cpu: [loong64] + os: [linux] + '@esbuild/linux-loong64@0.27.3': resolution: {integrity: sha512-WO60Sn8ly3gtzhyjATDgieJNet/KqsDlX5nRC5Y3oTFcS1l0KWba+SEa9Ja1GfDqSF1z6hif/SkpQJbL63cgOA==} engines: {node: '>=18'} cpu: [loong64] os: [linux] + '@esbuild/linux-mips64el@0.25.12': + resolution: {integrity: sha512-iyRrM1Pzy9GFMDLsXn1iHUm18nhKnNMWscjmp4+hpafcZjrr2WbT//d20xaGljXDBYHqRcl8HnxbX6uaA/eGVw==} + engines: {node: '>=18'} + cpu: [mips64el] + os: [linux] + '@esbuild/linux-mips64el@0.27.3': resolution: {integrity: sha512-APsymYA6sGcZ4pD6k+UxbDjOFSvPWyZhjaiPyl/f79xKxwTnrn5QUnXR5prvetuaSMsb4jgeHewIDCIWljrSxw==} engines: {node: '>=18'} cpu: [mips64el] os: [linux] + '@esbuild/linux-ppc64@0.25.12': + resolution: {integrity: sha512-9meM/lRXxMi5PSUqEXRCtVjEZBGwB7P/D4yT8UG/mwIdze2aV4Vo6U5gD3+RsoHXKkHCfSxZKzmDssVlRj1QQA==} + engines: {node: '>=18'} + cpu: [ppc64] + os: [linux] + '@esbuild/linux-ppc64@0.27.3': resolution: {integrity: sha512-eizBnTeBefojtDb9nSh4vvVQ3V9Qf9Df01PfawPcRzJH4gFSgrObw+LveUyDoKU3kxi5+9RJTCWlj4FjYXVPEA==} engines: {node: '>=18'} cpu: [ppc64] os: [linux] + '@esbuild/linux-riscv64@0.25.12': + resolution: {integrity: sha512-Zr7KR4hgKUpWAwb1f3o5ygT04MzqVrGEGXGLnj15YQDJErYu/BGg+wmFlIDOdJp0PmB0lLvxFIOXZgFRrdjR0w==} + engines: {node: '>=18'} + cpu: [riscv64] + os: [linux] + '@esbuild/linux-riscv64@0.27.3': resolution: {integrity: sha512-3Emwh0r5wmfm3ssTWRQSyVhbOHvqegUDRd0WhmXKX2mkHJe1SFCMJhagUleMq+Uci34wLSipf8Lagt4LlpRFWQ==} engines: {node: '>=18'} cpu: [riscv64] os: [linux] + '@esbuild/linux-s390x@0.25.12': + resolution: {integrity: sha512-MsKncOcgTNvdtiISc/jZs/Zf8d0cl/t3gYWX8J9ubBnVOwlk65UIEEvgBORTiljloIWnBzLs4qhzPkJcitIzIg==} + engines: {node: '>=18'} + cpu: [s390x] + os: [linux] + '@esbuild/linux-s390x@0.27.3': resolution: {integrity: sha512-pBHUx9LzXWBc7MFIEEL0yD/ZVtNgLytvx60gES28GcWMqil8ElCYR4kvbV2BDqsHOvVDRrOxGySBM9Fcv744hw==} engines: {node: '>=18'} cpu: [s390x] os: [linux] + '@esbuild/linux-x64@0.25.12': + resolution: {integrity: sha512-uqZMTLr/zR/ed4jIGnwSLkaHmPjOjJvnm6TVVitAa08SLS9Z0VM8wIRx7gWbJB5/J54YuIMInDquWyYvQLZkgw==} + engines: {node: '>=18'} + cpu: [x64] + os: [linux] + '@esbuild/linux-x64@0.27.3': resolution: {integrity: sha512-Czi8yzXUWIQYAtL/2y6vogER8pvcsOsk5cpwL4Gk5nJqH5UZiVByIY8Eorm5R13gq+DQKYg0+JyQoytLQas4dA==} engines: {node: '>=18'} cpu: [x64] os: [linux] + '@esbuild/netbsd-arm64@0.25.12': + resolution: {integrity: sha512-xXwcTq4GhRM7J9A8Gv5boanHhRa/Q9KLVmcyXHCTaM4wKfIpWkdXiMog/KsnxzJ0A1+nD+zoecuzqPmCRyBGjg==} + engines: {node: '>=18'} + cpu: [arm64] + os: [netbsd] + '@esbuild/netbsd-arm64@0.27.3': resolution: {integrity: sha512-sDpk0RgmTCR/5HguIZa9n9u+HVKf40fbEUt+iTzSnCaGvY9kFP0YKBWZtJaraonFnqef5SlJ8/TiPAxzyS+UoA==} engines: {node: '>=18'} cpu: [arm64] os: [netbsd] + '@esbuild/netbsd-x64@0.25.12': + resolution: {integrity: sha512-Ld5pTlzPy3YwGec4OuHh1aCVCRvOXdH8DgRjfDy/oumVovmuSzWfnSJg+VtakB9Cm0gxNO9BzWkj6mtO1FMXkQ==} + engines: {node: '>=18'} + cpu: [x64] + os: [netbsd] + '@esbuild/netbsd-x64@0.27.3': resolution: {integrity: sha512-P14lFKJl/DdaE00LItAukUdZO5iqNH7+PjoBm+fLQjtxfcfFE20Xf5CrLsmZdq5LFFZzb5JMZ9grUwvtVYzjiA==} engines: {node: '>=18'} cpu: [x64] os: [netbsd] + '@esbuild/openbsd-arm64@0.25.12': + resolution: {integrity: sha512-fF96T6KsBo/pkQI950FARU9apGNTSlZGsv1jZBAlcLL1MLjLNIWPBkj5NlSz8aAzYKg+eNqknrUJ24QBybeR5A==} + engines: {node: '>=18'} + cpu: [arm64] + os: [openbsd] + '@esbuild/openbsd-arm64@0.27.3': resolution: {integrity: sha512-AIcMP77AvirGbRl/UZFTq5hjXK+2wC7qFRGoHSDrZ5v5b8DK/GYpXW3CPRL53NkvDqb9D+alBiC/dV0Fb7eJcw==} engines: {node: '>=18'} cpu: [arm64] os: [openbsd] + '@esbuild/openbsd-x64@0.25.12': + resolution: {integrity: sha512-MZyXUkZHjQxUvzK7rN8DJ3SRmrVrke8ZyRusHlP+kuwqTcfWLyqMOE3sScPPyeIXN/mDJIfGXvcMqCgYKekoQw==} + engines: {node: '>=18'} + cpu: [x64] + os: [openbsd] + '@esbuild/openbsd-x64@0.27.3': resolution: {integrity: sha512-DnW2sRrBzA+YnE70LKqnM3P+z8vehfJWHXECbwBmH/CU51z6FiqTQTHFenPlHmo3a8UgpLyH3PT+87OViOh1AQ==} engines: {node: '>=18'} cpu: [x64] os: [openbsd] + '@esbuild/openharmony-arm64@0.25.12': + resolution: {integrity: sha512-rm0YWsqUSRrjncSXGA7Zv78Nbnw4XL6/dzr20cyrQf7ZmRcsovpcRBdhD43Nuk3y7XIoW2OxMVvwuRvk9XdASg==} + engines: {node: '>=18'} + cpu: [arm64] + os: [openharmony] + '@esbuild/openharmony-arm64@0.27.3': resolution: {integrity: sha512-NinAEgr/etERPTsZJ7aEZQvvg/A6IsZG/LgZy+81wON2huV7SrK3e63dU0XhyZP4RKGyTm7aOgmQk0bGp0fy2g==} engines: {node: '>=18'} cpu: [arm64] os: [openharmony] + '@esbuild/sunos-x64@0.25.12': + resolution: {integrity: sha512-3wGSCDyuTHQUzt0nV7bocDy72r2lI33QL3gkDNGkod22EsYl04sMf0qLb8luNKTOmgF/eDEDP5BFNwoBKH441w==} + engines: {node: '>=18'} + cpu: [x64] + os: [sunos] + '@esbuild/sunos-x64@0.27.3': resolution: {integrity: sha512-PanZ+nEz+eWoBJ8/f8HKxTTD172SKwdXebZ0ndd953gt1HRBbhMsaNqjTyYLGLPdoWHy4zLU7bDVJztF5f3BHA==} engines: {node: '>=18'} cpu: [x64] os: [sunos] + '@esbuild/win32-arm64@0.25.12': + resolution: {integrity: sha512-rMmLrur64A7+DKlnSuwqUdRKyd3UE7oPJZmnljqEptesKM8wx9J8gx5u0+9Pq0fQQW8vqeKebwNXdfOyP+8Bsg==} + engines: {node: '>=18'} + cpu: [arm64] + os: [win32] + '@esbuild/win32-arm64@0.27.3': resolution: {integrity: sha512-B2t59lWWYrbRDw/tjiWOuzSsFh1Y/E95ofKz7rIVYSQkUYBjfSgf6oeYPNWHToFRr2zx52JKApIcAS/D5TUBnA==} engines: {node: '>=18'} cpu: [arm64] os: [win32] + '@esbuild/win32-ia32@0.25.12': + resolution: {integrity: sha512-HkqnmmBoCbCwxUKKNPBixiWDGCpQGVsrQfJoVGYLPT41XWF8lHuE5N6WhVia2n4o5QK5M4tYr21827fNhi4byQ==} + engines: {node: '>=18'} + cpu: [ia32] + os: [win32] + '@esbuild/win32-ia32@0.27.3': resolution: {integrity: sha512-QLKSFeXNS8+tHW7tZpMtjlNb7HKau0QDpwm49u0vUp9y1WOF+PEzkU84y9GqYaAVW8aH8f3GcBck26jh54cX4Q==} engines: {node: '>=18'} cpu: [ia32] os: [win32] + '@esbuild/win32-x64@0.25.12': + resolution: {integrity: sha512-alJC0uCZpTFrSL0CCDjcgleBXPnCrEAhTBILpeAp7M/OFgoqtAetfBzX0xM00MUsVVPpVjlPuMbREqnZCXaTnA==} + engines: {node: '>=18'} + cpu: [x64] + os: [win32] + '@esbuild/win32-x64@0.27.3': resolution: {integrity: sha512-4uJGhsxuptu3OcpVAzli+/gWusVGwZZHTlS63hh++ehExkVT8SgiEf7/uC/PclrPPkLhZqGgCTjd0VWLo6xMqA==} engines: {node: '>=18'} @@ -919,6 +1087,12 @@ packages: '@jridgewell/trace-mapping@0.3.31': resolution: {integrity: sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==} + '@mdx-js/react@3.1.1': + resolution: {integrity: sha512-f++rKLQgUVYDAtECQ6fn/is15GkEH9+nZPM3MS0RcxVqoTfawHvDlSCH7JbMhAM6uJ32v3eXLvLmLvjGu7PTQw==} + peerDependencies: + '@types/react': '>=16' + react: '>=16' + '@mermaid-js/parser@1.0.0': resolution: {integrity: sha512-vvK0Hi/VWndxoh03Mmz6wa1KDriSPjS2XMZL/1l19HFwygiObEEoEwSDxOqyLzzAI6J2PU3261JjTMTO7x+BPw==} @@ -1195,6 +1369,143 @@ packages: '@standard-schema/spec@1.1.0': resolution: {integrity: sha512-l2aFy5jALhniG5HgqrD6jXLi/rUWrKvqN/qJx6yoJsgKhblVd+iqqU4RCXavm/jPityDo5TCvKMnpjKnOriy0w==} + '@storybook/addon-actions@8.6.14': + resolution: {integrity: sha512-mDQxylxGGCQSK7tJPkD144J8jWh9IU9ziJMHfB84PKpI/V5ZgqMDnpr2bssTrUaGDqU5e1/z8KcRF+Melhs9pQ==} + peerDependencies: + storybook: ^8.6.14 + + '@storybook/addon-backgrounds@8.6.14': + resolution: {integrity: sha512-l9xS8qWe5n4tvMwth09QxH2PmJbCctEvBAc1tjjRasAfrd69f7/uFK4WhwJAstzBTNgTc8VXI4w8ZR97i1sFbg==} + peerDependencies: + storybook: ^8.6.14 + + '@storybook/addon-controls@8.6.14': + resolution: {integrity: sha512-IiQpkNJdiRyA4Mq9mzjZlvQugL/aE7hNgVxBBGPiIZG6wb6Ht9hNnBYpap5ZXXFKV9p2qVI0FZK445ONmAa+Cw==} + peerDependencies: + storybook: ^8.6.14 + + '@storybook/addon-docs@8.6.14': + resolution: {integrity: sha512-Obpd0OhAF99JyU5pp5ci17YmpcQtMNgqW2pTXV8jAiiipWpwO++hNDeQmLmlSXB399XjtRDOcDVkoc7rc6JzdQ==} + peerDependencies: + storybook: ^8.6.14 + + '@storybook/addon-essentials@8.6.14': + resolution: {integrity: sha512-5ZZSHNaW9mXMOFkoPyc3QkoNGdJHETZydI62/OASR0lmPlJ1065TNigEo5dJddmZNn0/3bkE8eKMAzLnO5eIdA==} + peerDependencies: + storybook: ^8.6.14 + + '@storybook/addon-highlight@8.6.14': + resolution: {integrity: sha512-4H19OJlapkofiE9tM6K/vsepf4ir9jMm9T+zw5L85blJZxhKZIbJ6FO0TCG9PDc4iPt3L6+aq5B0X29s9zicNQ==} + peerDependencies: + storybook: ^8.6.14 + + '@storybook/addon-measure@8.6.14': + resolution: {integrity: sha512-1Tlyb72NX8aAqm6I6OICsUuGOP6hgnXcuFlXucyhKomPa6j3Eu2vKu561t/f0oGtAK2nO93Z70kVaEh5X+vaGw==} + peerDependencies: + storybook: ^8.6.14 + + '@storybook/addon-outline@8.6.14': + resolution: {integrity: sha512-CW857JvN6OxGWElqjlzJO2S69DHf+xO3WsEfT5mT3ZtIjmsvRDukdWfDU9bIYUFyA2lFvYjncBGjbK+I91XR7w==} + peerDependencies: + storybook: ^8.6.14 + + '@storybook/addon-toolbars@8.6.14': + resolution: {integrity: sha512-W/wEXT8h3VyZTVfWK/84BAcjAxTdtRiAkT2KAN0nbSHxxB5KEM1MjKpKu2upyzzMa3EywITqbfy4dP6lpkVTwQ==} + peerDependencies: + storybook: ^8.6.14 + + '@storybook/addon-viewport@8.6.14': + resolution: {integrity: sha512-gNzVQbMqRC+/4uQTPI2ZrWuRHGquTMZpdgB9DrD88VTEjNudP+J6r8myLfr2VvGksBbUMHkGHMXHuIhrBEnXYA==} + peerDependencies: + storybook: ^8.6.14 + + '@storybook/blocks@8.6.14': + resolution: {integrity: sha512-rBMHAfA39AGHgkrDze4RmsnQTMw1ND5fGWobr9pDcJdnDKWQWNRD7Nrlxj0gFlN3n4D9lEZhWGdFrCbku7FVAQ==} + peerDependencies: + react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 + react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 + storybook: ^8.6.14 + peerDependenciesMeta: + react: + optional: true + react-dom: + optional: true + + '@storybook/builder-vite@8.6.17': + resolution: {integrity: sha512-ZqFaLUKlRNaU4ovEa5R6D5YTbft1CUcNHLhzpmL9JWInEh4PrUkxiLD/jjB6fiYLcRpSpcs2DF+O/Jh2GDWemA==} + peerDependencies: + storybook: ^8.6.17 + vite: ^4.0.0 || ^5.0.0 || ^6.0.0 + + '@storybook/components@8.6.17': + resolution: {integrity: sha512-0b8xkkuPCNbM8LTOzyfxuo2KdJCHIfu3+QxWBFllXap0eYNHwVeSxE5KERQ/bk2GDCiRzaUbwH9PeLorxOzJJQ==} + peerDependencies: + storybook: ^8.2.0 || ^8.3.0-0 || ^8.4.0-0 || ^8.5.0-0 || ^8.6.0-0 + + '@storybook/core@8.6.17': + resolution: {integrity: sha512-lndZDYIvUddWk54HmgYwE4h2B0JtWt8ztIRAzHRt6ReZZ9QQbmM5b85Qpa+ng4dyQEKc2JAtYD3Du7RRFcpHlw==} + peerDependencies: + prettier: ^2 || ^3 + peerDependenciesMeta: + prettier: + optional: true + + '@storybook/csf-plugin@8.6.14': + resolution: {integrity: sha512-dErtc9teAuN+eelN8FojzFE635xlq9cNGGGEu0WEmMUQ4iJ8pingvBO1N8X3scz4Ry7KnxX++NNf3J3gpxS8qQ==} + peerDependencies: + storybook: ^8.6.14 + + '@storybook/csf-plugin@8.6.17': + resolution: {integrity: sha512-ouvF/izbKclZxpfnRUkyC5ZVDU7QA0cHhjQnXTDT4F8b0uciQUDw1LosDZy5MXf03BeIDdyBAtzd/ym3wzd+kw==} + peerDependencies: + storybook: ^8.6.17 + + '@storybook/global@5.0.0': + resolution: {integrity: sha512-FcOqPAXACP0I3oJ/ws6/rrPT9WGhu915Cg8D02a9YxLo0DE9zI+a9A5gRGvmQ09fiWPukqI8ZAEoQEdWUKMQdQ==} + + '@storybook/icons@1.6.0': + resolution: {integrity: sha512-hcFZIjW8yQz8O8//2WTIXylm5Xsgc+lW9ISLgUk1xGmptIJQRdlhVIXCpSyLrQaaRiyhQRaVg7l3BD9S216BHw==} + 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/manager-api@8.6.17': + resolution: {integrity: sha512-sPJytvClNrw5GgKcPletMTxDOAYcTRA8VRt9E+ncKvPSYHtPDqLfGTgWajXmt0hRsiBUN5bOgLS9bmNjNQWhrw==} + peerDependencies: + storybook: ^8.2.0 || ^8.3.0-0 || ^8.4.0-0 || ^8.5.0-0 || ^8.6.0-0 + + '@storybook/preview-api@8.6.17': + resolution: {integrity: sha512-vpTCTkw11wXerYnlG5Q0y4SbFqG9O6GhR0hlYgCn3Z9kcHlNjK/xuwd3h4CvwNXxRNWZGT8qYYCLn5gSSrX6fA==} + peerDependencies: + storybook: ^8.2.0 || ^8.3.0-0 || ^8.4.0-0 || ^8.5.0-0 || ^8.6.0-0 + + '@storybook/react-dom-shim@8.6.14': + resolution: {integrity: sha512-0hixr3dOy3f3M+HBofp3jtMQMS+sqzjKNgl7Arfuj3fvjmyXOks/yGjDImySR4imPtEllvPZfhiQNlejheaInw==} + 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: ^8.6.14 + + '@storybook/theming@8.6.17': + resolution: {integrity: sha512-IttFvRqozpuzN5MlQEWGOzUA2rZg86688Dyv1d+bjpYcFHtY1X4XyTCGwv1BPTaTsB959oM8R2yoNYWQkABbBA==} + peerDependencies: + storybook: ^8.2.0 || ^8.3.0-0 || ^8.4.0-0 || ^8.5.0-0 || ^8.6.0-0 + + '@storybook/vue3-vite@8.6.17': + resolution: {integrity: sha512-yF+SAxm0NYbShF+vqVnmQ03LGYM51OpriATraRNUU3Fw57SW5SKBOma/C9K2FUInbAMtI0M7g7XnkCGavSJNCA==} + engines: {node: '>=18.0.0'} + peerDependencies: + storybook: ^8.6.17 + vite: ^4.0.0 || ^5.0.0 || ^6.0.0 + + '@storybook/vue3@8.6.17': + resolution: {integrity: sha512-jU2GgRwjtIOg3dsLL5U3mg5DTUvkqPKd7wSftHdzA33myO1jA2fLCU1GlfKXk8yMDxmNwG9yP1oVaTwMmFXPqg==} + engines: {node: '>=18.0.0'} + peerDependencies: + storybook: ^8.6.17 + vue: ^3.0.0 + '@surma/rollup-plugin-off-main-thread@2.2.3': resolution: {integrity: sha512-lR8q/9W7hZpMWweNiAKU7NQerBnzQQLvi8qnTDU/fxItPhtZVMbPV3lbCwjhIlNBe9Bbr5V+KHshvWmVSG9cxQ==} @@ -1426,15 +1737,24 @@ packages: '@types/mdurl@2.0.0': resolution: {integrity: sha512-RGdgjQUZba5p6QEFAVx2OGb8rQDL/cPRG7GiedRzMcJ1tYnUANBncjbSB1NRGwbvjcPeikRABz2nshyPk1bhWg==} + '@types/mdx@2.0.13': + resolution: {integrity: sha512-+OWZQfAYyio6YkJb3HLxDrvnx6SWWDbC0zVPfBRzUk0/nqoDyf6dNxQi3eArPe8rJ473nobTMQ/8Zk+LxJ+Yuw==} + '@types/node@25.3.3': resolution: {integrity: sha512-DpzbrH7wIcBaJibpKo9nnSQL0MTRdnWttGyE5haGwK86xgMOkFLp7vEyfQPGLOJh5wNYiJ3V9PmUMDhV9u8kkQ==} + '@types/react@19.2.14': + resolution: {integrity: sha512-ilcTH/UniCkMdtexkoCN0bI7pMcJDvmQFPvuPvmEaYA/NSfFTAgdUSLAoVjaRJm7+6PvcM+q1zYOwS4wTYMF9w==} + '@types/resolve@1.20.2': resolution: {integrity: sha512-60BCwRFOZCQhDncwQdxxeOEEkbc5dIMccYLwbxsS4TUNeVECQ/pBJ0j09mrHOl/JJvpRPGwO9SvE4nR2Nb/a4Q==} '@types/trusted-types@2.0.7': resolution: {integrity: sha512-ScaPdn1dQczgbl0QFTeTOmVHFULt394XJgOQNoyVhZ6r2vLnMLJfBPd53SB52T/3G36VI1/g2MZaX0cwDuXsfw==} + '@types/uuid@9.0.8': + resolution: {integrity: sha512-jg+97EGIcY9AGHJJRaaPVgetKDsrTgbRjQ5Msgjh/DQKEFl0DtyRr/VCOyD1T2R1MNeWPK/u7JoGhlDZnKBAfA==} + '@types/whatwg-mimetype@3.0.2': resolution: {integrity: sha512-c2AKvDT8ToxLIOUlN51gTiHXflsfIFisS4pO7pDPoKouJCESkhZnEy623gwP9laCy5lnLDAw1vAzu2vM2YLOrA==} @@ -1536,12 +1856,21 @@ packages: '@vitest/utils@4.0.18': resolution: {integrity: sha512-msMRKLMVLWygpK3u2Hybgi4MNjcYJvwTb0Ru09+fOyCXIgT5raYP041DRRdiJiI3k/2U6SEbAETB3YtBrUkCFA==} + '@volar/language-core@2.4.15': + resolution: {integrity: sha512-3VHw+QZU0ZG9IuQmzT68IyN4hZNd9GchGPhbD9+pa8CVv7rnoOZwo7T8weIbrRmihqy3ATpdfXFnqRrfPVK6CA==} + '@volar/language-core@2.4.28': resolution: {integrity: sha512-w4qhIJ8ZSitgLAkVay6AbcnC7gP3glYM3fYwKV3srj8m494E3xtrCv6E+bWviiK/8hs6e6t1ij1s2Endql7vzQ==} + '@volar/source-map@2.4.15': + resolution: {integrity: sha512-CPbMWlUN6hVZJYGcU/GSoHu4EnCHiLaXI9n8c9la6RaI9W5JHX+NqG+GSQcB0JdC2FIBLdZJwGsfKyBB71VlTg==} + '@volar/source-map@2.4.28': resolution: {integrity: sha512-yX2BDBqJkRXfKw8my8VarTyjv48QwxdJtvRgUpNE5erCsgEUdI2DsLbpa+rOQVAJYshY99szEcRDmyHbF10ggQ==} + '@volar/typescript@2.4.15': + resolution: {integrity: sha512-2aZ8i0cqPGjXb4BhkMsPYDkkuc2ZQ6yOpqwAuNwUoncELqoy5fRgOQtLR9gB0g902iS0NAkvpIzs27geVyVdPg==} + '@volar/typescript@2.4.28': resolution: {integrity: sha512-Ja6yvWrbis2QtN4ClAKreeUZPVYMARDYZl9LMEv1iQ1QdepB6wn0jTRxA9MftYmYa4DQ4k/DaSZpFPUfxl8giw==} @@ -1566,6 +1895,9 @@ packages: '@vue/compiler-ssr@3.5.29': resolution: {integrity: sha512-Y/ARJZE6fpjzL5GH/phJmsFwx3g6t2KmHKHx5q+MLl2kencADKIrhH5MLF6HHpRMmlRAYBRSvv347Mepf1zVNw==} + '@vue/compiler-vue2@2.7.16': + resolution: {integrity: sha512-qYC3Psj9S/mfu9uVi5WvNZIzq+xnXMhOwbTFKKDD7b1lhpnn71jXSFdTQ+WsIEk0ONCd7VV2IMm7ONl6tbQ86A==} + '@vue/devtools-api@7.7.9': resolution: {integrity: sha512-kIE8wvwlcZ6TJTbNeU2HQNtaxLx3a84aotTITUuL/4bzfPxzajGBOoqjMhwZJ8L9qFYDU/lAYMEEm11dnZOD6g==} @@ -1584,6 +1916,14 @@ packages: '@vue/devtools-shared@8.0.7': resolution: {integrity: sha512-CgAb9oJH5NUmbQRdYDj/1zMiaICYSLtm+B1kxcP72LBrifGAjUmt8bx52dDH1gWRPlQgxGPqpAMKavzVirAEhA==} + '@vue/language-core@2.2.12': + resolution: {integrity: sha512-IsGljWbKGU1MZpBPN+BvPAdr55YPkj2nB/TBNGNC32Vy2qLG25DYu/NBN2vNtZqdRbTRjaoYrahLrToim2NanA==} + peerDependencies: + typescript: '*' + peerDependenciesMeta: + typescript: + optional: true + '@vue/language-core@3.2.5': resolution: {integrity: sha512-d3OIxN/+KRedeM5wQ6H6NIpwS3P5gC9nmyaHgBk+rO6dIsjY+tOh4UlPpiZbAh3YtLdCGEX4M16RmsBqPmJV+g==} @@ -1609,6 +1949,11 @@ packages: peerDependencies: acorn: ^6.0.0 || ^7.0.0 || ^8.0.0 + acorn@7.4.1: + resolution: {integrity: sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==} + engines: {node: '>=0.4.0'} + hasBin: true + acorn@8.16.0: resolution: {integrity: sha512-UVJyE9MttOsBQIDKw1skb9nAwQuR5wuGD3+82K6JgJlm/Y+KI92oNsMNGZCYdDsVtRHSak0pcV5Dno5+4jh9sw==} engines: {node: '>=0.4.0'} @@ -1620,6 +1965,9 @@ packages: ajv@8.18.0: resolution: {integrity: sha512-PlXPeEWMXMZ7sPYOHqmDyCJzcfNrUr3fGNKtezX14ykXOEIvyK81d+qydx89KY5O71FKMPaQ2vBfBFI5NHR63A==} + alien-signals@1.0.13: + resolution: {integrity: sha512-OGj9yyTnJEttvzhTUWuscOvtqxq5vrhF7vL9oS0xJ2mK0ItPYP1/y+vCFebfxoEyAz0++1AIwJ5CMr+Fk3nDmg==} + alien-signals@3.1.2: resolution: {integrity: sha512-d9dYqZTS90WLiU0I5c6DHj/HcKkF8ZyGN3G5x8wSbslulz70KOxaqCT0hQCo9KOyhVqzqGojvNdJXoTumZOtcw==} @@ -1634,6 +1982,12 @@ packages: resolution: {integrity: sha512-BNoCY6SXXPQ7gF2opIP4GBE+Xw7U+pHMYKuzjgCN3GwiaIR09UUeKfheyIry77QtrCBlC0KK0q5/TER/tYh3PQ==} engines: {node: '>= 0.4'} + asap@2.0.6: + resolution: {integrity: sha512-BSHWgDSAiKs50o2Re8ppvp3seVHXSRM44cdSsT9FfNEUUZLOGWVCsiWaRPWM1Znn+mqZ1OfVZ3z3DWEzSp7hRA==} + + assert-never@1.4.0: + resolution: {integrity: sha512-5oJg84os6NMQNl27T9LnZkvvqzvAnHu03ShCnoj6bsJwS7L8AO4lf+C/XjK/nvzEqQB744moC6V128RucQd1jA==} + assertion-error@2.0.1: resolution: {integrity: sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA==} engines: {node: '>=12'} @@ -1642,6 +1996,10 @@ packages: resolution: {integrity: sha512-m1Q/RaVOnTp9JxPX+F+Zn7IcLYMzM8kZofDImfsKZd8MbR+ikdOzTeztStWqfrqIxZnYWryyI9ePm3NGjnZgGw==} engines: {node: '>=20.19.0'} + ast-types@0.16.1: + resolution: {integrity: sha512-6t10qk83GOG8p0vKmaCr8eiilZwO171AvbROMtvvNiwrTly62t+7XkA8RdIIVbpMhCASAsxgAzdRSwh6nw/5Dg==} + engines: {node: '>=4'} + ast-walker-scope@0.8.3: resolution: {integrity: sha512-cbdCP0PGOBq0ASG+sjnKIoYkWMKhhz+F/h9pRexUdX2Hd38+WOlBkRKlqkGOSm0YQpcFMQBJeK4WspUAkwsEdg==} engines: {node: '>=20.19.0'} @@ -1676,6 +2034,10 @@ packages: peerDependencies: '@babel/core': ^7.4.0 || ^8.0.0-0 <8.0.0 + babel-walk@3.0.0-canary-5: + resolution: {integrity: sha512-GAwkz0AihzY5bkwIY5QDR+LvsRQgB/B+1foMPvi0FZPMl5fjD7ICiznUiBdLYMH1QYe6vqu4gWYytZOccLouFw==} + engines: {node: '>= 10.0.0'} + balanced-match@1.0.2: resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} @@ -1688,6 +2050,10 @@ packages: engines: {node: '>=6.0.0'} hasBin: true + better-opn@3.0.2: + resolution: {integrity: sha512-aVNobHnJqLiUelTaHat9DZ1qM2w0C0Eym4LPI/3JxOnSokGVdsl1T1kN7TFvsEAD8G47A6VKQ0TVHqbBnYMJlQ==} + engines: {node: '>=12.0.0'} + birpc@2.9.0: resolution: {integrity: sha512-KrayHS5pBi69Xi9JmvoqrIgYGDkD6mcSe/i6YKi3w5kekCLzrX4+nawcXqrj2tIp50Kw/mT/s3p+GVK0A0sKxw==} @@ -1701,6 +2067,9 @@ packages: resolution: {integrity: sha512-h+DEnpVvxmfVefa4jFbCf5HdH5YMDXRsmKflpf1pILZWRFlTbJpxeU55nJl4Smt5HQaGzg1o6RHFPJaOqnmBDg==} engines: {node: 18 || 20 || >=22} + browser-assert@1.2.1: + resolution: {integrity: sha512-nfulgvOR6S4gt9UKCeGJOuSGBPGiFT6oQ/2UBnvTY/5aQ1PnksW72fhZkM30DzoRRv2WpwZf1vHHEr3mtuXIWQ==} + browserslist@4.28.1: resolution: {integrity: sha512-ZC5Bd0LgJXgwGqUknZY/vkUQ04r8NXnJZ3yYi4vDmSiZmC/pdSN0NbNRPxZpbtO4uAfDUAFffO8IZoM3Gj8IkA==} engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7} @@ -1728,6 +2097,9 @@ packages: resolution: {integrity: sha512-NUPRluOfOiTKBKvWPtSD4PhFvWCqOi0BGStNWs57X9js7XGTprSmFoz5F0tWhR4WPjNeR9jXqdC7/UpSJTnlRg==} engines: {node: '>=18'} + character-parser@2.2.0: + resolution: {integrity: sha512-+UqJQjFEFaTAs3bNsF2j2kEN1baG/zghZbdqoYEDxGZtJo9LBzl1A+m0D4n3qKx8N2FNv8/Xp6yV9mQmBuptaw==} + chevrotain-allstar@0.3.1: resolution: {integrity: sha512-b7g+y9A0v4mxCW1qUhf3BSVPg+/NvGErk/dOkrDaHA0nQIQGAtrOjlX//9OQtRlSCy+x9rfB5N8yC71lH1nvMw==} peerDependencies: @@ -1761,6 +2133,9 @@ packages: confbox@0.2.4: resolution: {integrity: sha512-ysOGlgTFbN2/Y6Cg3Iye8YKulHw+R2fNXHrgSmXISQdMnomY6eNDprVdW9R5xBguEqI954+S6709UyiO7B+6OQ==} + constantinople@4.0.1: + resolution: {integrity: sha512-vCrqcSIq4//Gx74TXXCGnHpulY1dskqLTFGDmhrGxzeXL8lF8kvXv6mpNWlJj1uD4DW23D4ljAqbY4RRaaUZIw==} + convert-source-map@2.0.0: resolution: {integrity: sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==} @@ -1970,6 +2345,9 @@ packages: dayjs@1.11.19: resolution: {integrity: sha512-t5EcLVS6QPBNqM2z8fakk/NKel+Xzshgt8FFKAn+qwlD1pzZWxh0nVCrvFK7ZDb6XucZeF9z8C7CBWTRIVApAw==} + de-indent@1.0.2: + resolution: {integrity: sha512-e/1zu3xH5MQryN2zdVaF0OrdNLUbvWxzMbi+iNA6Bky7l1RoP8a2fIbRocyHclXt/arDrrR6lL3TqFD9pMQTsg==} + debug@4.4.3: resolution: {integrity: sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==} engines: {node: '>=6.0'} @@ -1990,6 +2368,10 @@ packages: resolution: {integrity: sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==} engines: {node: '>= 0.4'} + define-lazy-prop@2.0.0: + resolution: {integrity: sha512-Ds09qNh8yw3khSjiJjiUInaGX9xlqZDY7JVryGxdxV7NPeuqQfplOpQ66yJFZut3jLa5zOwkXw1g9EI2uKh4Og==} + engines: {node: '>=8'} + define-properties@1.2.1: resolution: {integrity: sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==} engines: {node: '>= 0.4'} @@ -1997,10 +2379,17 @@ packages: delaunator@5.0.1: resolution: {integrity: sha512-8nvh+XBe96aCESrGOqMp/84b13H9cdKbG5P2ejQCh4d4sK9RL4371qou9drQjMhvnPmhWl5hnmqbEE0fXr9Xnw==} + dequal@2.0.3: + resolution: {integrity: sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==} + engines: {node: '>=6'} + detect-libc@2.1.2: resolution: {integrity: sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==} engines: {node: '>=8'} + doctypes@1.1.0: + resolution: {integrity: sha512-LLBi6pEqS6Do3EKQ3J0NqHWV5hhb78Pi8vvESYwyOy2c31ZEZVdtitdzsQsKb7878PEERhzUk0ftqGhG6Mz+pQ==} + dompurify@3.3.1: resolution: {integrity: sha512-qkdCKzLNtrgPFP1Vo+98FRzJnBRGe4ffyCea9IwHB1fyxPOeNTHpLKYGd4Uk9xvNoH0ZoOjwZxNptyMwqrId1Q==} @@ -2061,6 +2450,16 @@ packages: resolution: {integrity: sha512-w+5mJ3GuFL+NjVtJlvydShqE1eN3h3PbI7/5LAsYJP/2qtuMXjfL2LpHSRqo4b4eSF5K/DH1JXKUAHSB2UW50g==} engines: {node: '>= 0.4'} + esbuild-register@3.6.0: + resolution: {integrity: sha512-H2/S7Pm8a9CL1uhp9OvjwrBh5Pvx0H8qVOxNu8Wed9Y7qv56MPtq+GGM8RJpq6glYJn9Wspr8uw7l55uyinNeg==} + peerDependencies: + esbuild: '>=0.12 <1' + + esbuild@0.25.12: + resolution: {integrity: sha512-bbPBYYrtZbkt6Os6FiTLCTFxvq4tt3JKall1vRwshA3fdVztsLAatFaZobhkBC8/BrPetoa0oksYoKXoG4ryJg==} + engines: {node: '>=18'} + hasBin: true + esbuild@0.27.3: resolution: {integrity: sha512-8VwMnyGCONIs6cWue2IdpHxHnAjzxnw2Zr7MkVxB2vjmQ2ivqGFb4LEG3SMnv0Gb2F/G/2yA8zUaiL1gywDCCg==} engines: {node: '>=18'} @@ -2110,10 +2509,18 @@ packages: jiti: optional: true + esm-resolve@1.0.11: + resolution: {integrity: sha512-LxF0wfUQm3ldUDHkkV2MIbvvY0TgzIpJ420jHSV1Dm+IlplBEWiJTKWM61GtxUfvjV6iD4OtTYFGAGM2uuIUWg==} + espree@11.1.1: resolution: {integrity: sha512-AVHPqQoZYc+RUM4/3Ly5udlZY/U4LS8pIG05jEjWM2lQMU/oaZ7qshzAl2YP1tfNmXfftH3ohurfwNAug+MnsQ==} engines: {node: ^20.19.0 || ^22.13.0 || >=24} + esprima@4.0.1: + resolution: {integrity: sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==} + engines: {node: '>=4'} + hasBin: true + esquery@1.7.0: resolution: {integrity: sha512-Ap6G0WQwcU/LHsvLwON1fAQX9Zp0A2Y6Y/cJBl9r/JbW90Zyg4/zbG6zzKa2OTALELarYHmKu0GhpM5EO+7T0g==} engines: {node: '>=0.10'} @@ -2174,6 +2581,9 @@ packages: filelist@1.0.6: resolution: {integrity: sha512-5giy2PkLYY1cP39p17Ech+2xlpTRL9HLspOfEgm0L6CwBXBTgsK5ou0JtzYuepxkaQ/tvhCFIJ5uXo0OrM2DxA==} + find-package-json@1.2.0: + resolution: {integrity: sha512-+SOGcLGYDJHtyqHd87ysBhmaeQ95oWspDKnMXBrnQ9Eq4OkLNqejgoaD8xVWu6GPa0B6roa6KinCMEMcVeqONw==} + find-up@5.0.0: resolution: {integrity: sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==} engines: {node: '>=10'} @@ -2294,10 +2704,17 @@ packages: resolution: {integrity: sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==} engines: {node: '>= 0.4'} + hash-sum@2.0.0: + resolution: {integrity: sha512-WdZTbAByD+pHfl/g9QSsBIIwy8IT+EsPiKDs0KNX+zSHhdDLFKdZu0BQHljvO+0QI/BasbMSUa8wYNCZTvhslg==} + hasown@2.0.2: resolution: {integrity: sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==} engines: {node: '>= 0.4'} + he@1.2.0: + resolution: {integrity: sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==} + hasBin: true + hls.js@1.6.15: resolution: {integrity: sha512-E3a5VwgXimGHwpRGV+WxRTKeSp2DW5DI5MWv34ulL3t5UNmyJWCQ1KmLEHbYzcfThfXG8amBL+fCYPneGHC4VA==} @@ -2326,6 +2743,9 @@ packages: resolution: {integrity: sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==} engines: {node: '>=0.8.19'} + inherits@2.0.4: + resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==} + internal-slot@1.1.0: resolution: {integrity: sha512-4gd7VpWNQNB4UKKCFFVcp1AVv+FMOgs9NKzjHKusc8jTMhd5eL1NqQqOpE0KzMds804/yHlglp3uxgluOqAPLw==} engines: {node: '>= 0.4'} @@ -2337,6 +2757,10 @@ packages: resolution: {integrity: sha512-5Hh7Y1wQbvY5ooGgPbDaL5iYLAPzMTUrjMulskHLH6wnv/A+1q5rgEaiuqEjB+oxGXIVZs1FF+R/KPN3ZSQYYg==} engines: {node: '>=12'} + is-arguments@1.2.0: + resolution: {integrity: sha512-7bVbi0huj/wrIAOzb8U1aszg9kdi3KN/CyU19CTI7tAoZYEZoL9yCDXpbXN+uPsuWnP02cyug1gleqq+TU+YCA==} + engines: {node: '>= 0.4'} + is-array-buffer@3.0.5: resolution: {integrity: sha512-DDfANUiiG2wC1qawP66qlTugJeL5HyzMpfr8lLK+jMQirGzNod0B12cFB/9q838Ru27sBwfw78/rdoU7RERz6A==} engines: {node: '>= 0.4'} @@ -2369,6 +2793,14 @@ packages: resolution: {integrity: sha512-PwwhEakHVKTdRNVOw+/Gyh0+MzlCl4R6qKvkhuvLtPMggI1WAHt9sOwZxQLSGpUaDnrdyDsomoRgNnCfKNSXXg==} engines: {node: '>= 0.4'} + is-docker@2.2.1: + resolution: {integrity: sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==} + engines: {node: '>=8'} + hasBin: true + + is-expression@4.0.0: + resolution: {integrity: sha512-zMIXX63sxzG3XrkHkrAPvm/OVZVSCPNkwMHU8oTX7/U3AL78I0QXCEICXUM13BIa8TYGZ68PiTKfQz3yaTNr4A==} + is-extglob@2.1.1: resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==} engines: {node: '>=0.10.0'} @@ -2404,6 +2836,9 @@ packages: resolution: {integrity: sha512-l4RyHgRqGN4Y3+9JHVrNqO+tN0rV5My76uW5/nuO4K1b6vw5G8d/cmFjP9tRfEsdhZNt0IFdZuK/c2Vr4Nb+Qg==} engines: {node: '>=0.10.0'} + is-promise@2.2.2: + resolution: {integrity: sha512-+lP4/6lKUBfQjZ2pdxThZvLUAafmZb8OAxFb8XXtiQmS35INgr85hdOGoEs124ez1FCnZJt6jau/T+alh58QFQ==} + is-regex@1.2.1: resolution: {integrity: sha512-MjYsKHO5O7mCsmRGxWcLWheFqN9DJ/2TmngvjKXihe6efViPqc274+Fx/4fYj/r03+ESvBdTXK0V6tA3rgez1g==} engines: {node: '>= 0.4'} @@ -2452,6 +2887,10 @@ packages: resolution: {integrity: sha512-oG7cgbmg5kLYae2N5IVd3jm2s+vldjxJzK1pcu9LfpGuQ93MQSzo0okvRna+7y5ifrD+20FE8FvjusyGaz14fw==} engines: {node: '>=18'} + is-wsl@2.2.0: + resolution: {integrity: sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==} + engines: {node: '>=8'} + isarray@2.0.5: resolution: {integrity: sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==} @@ -2471,9 +2910,16 @@ packages: resolution: {integrity: sha512-ekilCSN1jwRvIbgeg/57YFh8qQDNbwDb9xT/qu2DAHbFFZUicIl4ygVaAvzveMhMVr3LnpSKTNnwt8PoOfmKhQ==} hasBin: true + js-stringify@1.0.2: + resolution: {integrity: sha512-rtS5ATOo2Q5k1G+DADISilDA6lv79zIiwFd6CcjuIxGKLFm5C+RLImRscVap9k55i+MOZwgliw+NejvkLuGD5g==} + js-tokens@4.0.0: resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==} + jsdoc-type-pratt-parser@4.8.0: + resolution: {integrity: sha512-iZ8Bdb84lWRuGHamRXFyML07r21pcwBrLkHEuHgEY5UbCouBwv7ECknDRKzsQIXMiqpPymqtIf8TC/shYKB5rw==} + engines: {node: '>=12.0.0'} + jsesc@3.1.0: resolution: {integrity: sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==} engines: {node: '>=6'} @@ -2506,6 +2952,9 @@ packages: resolution: {integrity: sha512-p/nXbhSEcu3pZRdkW1OfJhpsVtW1gd4Wa1fnQc9YLiTfAjn0312eMKimbdIQzuZl9aa9xUGaRlP9T/CJE/ditQ==} engines: {node: '>=0.10.0'} + jstransformer@1.0.0: + resolution: {integrity: sha512-C9YK3Rf8q6VAPDCCU9fnqo3mAfOH6vUGnMcP4AQAYIEpWtfGLpwOTmZ+igtdK5y+VvI2n3CyYSzy4Qh34eq24A==} + katex@0.16.33: resolution: {integrity: sha512-q3N5u+1sY9Bu7T4nlXoiRBXWfwSefNGoKeOwekV+gw0cAXQlz2Ww6BLcmBxVDeXBMUDQv6fK5bcNaJLxob3ZQA==} hasBin: true @@ -2644,6 +3093,10 @@ packages: lru-cache@5.1.1: resolution: {integrity: sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==} + lru-cache@8.0.5: + resolution: {integrity: sha512-MhWWlVnuab1RG5/zMRRcVGXZLCXrZTgfwMikgzCegsPnG62yDQo5JnqKkrK4jO5iKqDAZGItAqN5CtKBCBWRUA==} + engines: {node: '>=16.14'} + magic-string-ast@1.0.3: resolution: {integrity: sha512-CvkkH1i81zl7mmb94DsRiFeG9V2fR2JeuK8yDgS8oiZSFa++wWLEgZ5ufEOyLHbvSbD1gTRKv9NdX69Rnvr9JA==} engines: {node: '>=20.19.0'} @@ -2654,6 +3107,9 @@ packages: magic-string@0.30.21: resolution: {integrity: sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==} + map-or-similar@1.5.0: + resolution: {integrity: sha512-0aF7ZmVon1igznGI4VS30yugpduQW3y3GkcgGJOp7d8x8QrizhigUxjI/m2UojsXXto+jLAH3KSz+xOJTiORjg==} + markdown-it@14.1.1: resolution: {integrity: sha512-BuU2qnTti9YKgK5N+IeMubp14ZUKUUw7yeJbkjtosvHiP0AZ5c8IAgEMk79D0eC8F23r4Ac/q8cAIFdm2FtyoA==} hasBin: true @@ -2670,6 +3126,9 @@ packages: mdurl@2.0.0: resolution: {integrity: sha512-Lf+9+2r+Tdp5wXDXC4PcIBjTDtq4UKjCPMQhKIuzpJNW0b96kVqSwW0bT7FhRSfmAiFYgP+SCRvdrDozfh0U5w==} + memoizerific@1.11.3: + resolution: {integrity: sha512-/EuHYwAPdLtXwAwSZkh/Gutery6pD2KYd44oQLhAvQp/50mpyduZh8Q7PYHXTCJ+wuXxt7oij2LXyIJOOYFPog==} + mermaid@11.12.3: resolution: {integrity: sha512-wN5ZSgJQIC+CHJut9xaKWsknLxaFBwCPwPkGTSUYrTiHORWvpT8RxGk849HPnpUAQ+/9BPRqYb80jTpearrHzQ==} @@ -2681,6 +3140,10 @@ packages: resolution: {integrity: sha512-7o1wEA2RyMP7Iu7GNba9vc0RWWGACJOCZBJX2GJWip0ikV+wcOsgVuY9uE8CPiyQhkGFSlhuSkZPavN7u1c2Fw==} engines: {node: '>=10'} + minimatch@9.0.9: + resolution: {integrity: sha512-OBwBN9AL4dqmETlpS2zasx+vTeWclWzkblfZk7KTA5j3jeOONz/tRCnZomUyvNg83wL5Zv9Ss6HMJXAgL8R2Yg==} + engines: {node: '>=16 || 14 >=14.17'} + minipass@7.1.3: resolution: {integrity: sha512-tEBHqDnIoM/1rXME1zgka9g6Q2lcoCkxHLuc7ODJ5BxbP5d4c2Z5cGgtXAku59200Cx7diuHTOYfSBD8n6mm8A==} engines: {node: '>=16 || 14 >=14.17'} @@ -2719,6 +3182,10 @@ packages: nth-check@2.1.1: resolution: {integrity: sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==} + object-assign@4.1.1: + resolution: {integrity: sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==} + engines: {node: '>=0.10.0'} + object-inspect@1.13.4: resolution: {integrity: sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==} engines: {node: '>= 0.4'} @@ -2734,6 +3201,10 @@ packages: obug@2.1.1: resolution: {integrity: sha512-uTqF9MuPraAQ+IsnPf366RG4cP9RtUi7MLO1N3KEc+wb0a6yKpeL0lmk2IB1jY5KHPAlTc6T/JRdC/YqxHNwkQ==} + open@8.4.2: + resolution: {integrity: sha512-7x81NCL719oNbsq/3mh+hVrAWmFuEYUqrq/Iw3kUzH8ReypT9QQ0BLoJS7/G9k6N81XjW4qHWtjWwe/9eLy1EQ==} + engines: {node: '>=12'} + optionator@0.9.4: resolution: {integrity: sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==} engines: {node: '>= 0.8.0'} @@ -2835,6 +3306,10 @@ packages: points-on-path@0.2.1: resolution: {integrity: sha512-25ClnWWuw7JbWZcgqY/gJ4FQWadKxGWk+3kR/7kD0tCaDtPPMj7oHu2ToLaVhfpnHrZzYby2w6tUA0eOIuUg8g==} + polished@4.3.1: + resolution: {integrity: sha512-OBatVyC/N7SCW/FaDHrSd+vn0o5cS855TOmYi4OkdWUMSJCET/xip//ch8xGUvtr3i44X9LVyWwQlRMTN3pwSA==} + engines: {node: '>=10'} + possible-typed-array-names@1.1.0: resolution: {integrity: sha512-/+5VFTchJDoVj3bhoqi6UeymcD00DAwb1nJwamzPvHEszJ4FpF6SNNbUbOS8yI56qHzdV8eK0qEfOSiodkTdxg==} engines: {node: '>= 0.4'} @@ -2859,6 +3334,49 @@ packages: resolution: {integrity: sha512-mQUvGU6aUFQ+rNvTIAcZuWGRT9a6f6Yrg9bHs4ImKF+HZCEK+plBvnAZYSIQztknZF2qnzNtr6F8s0+IuptdlQ==} engines: {node: ^14.13.1 || >=16.0.0} + process@0.11.10: + resolution: {integrity: sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A==} + engines: {node: '>= 0.6.0'} + + promise@7.3.1: + resolution: {integrity: sha512-nolQXZ/4L+bP/UGlkfaIujX9BKxGwmQ9OT4mOt5yvy8iK1h3wqTEJCijzGANTCCl9nWjY41juyAn2K3Q1hLLTg==} + + pug-attrs@3.0.0: + resolution: {integrity: sha512-azINV9dUtzPMFQktvTXciNAfAuVh/L/JCl0vtPCwvOA21uZrC08K/UnmrL+SXGEVc1FwzjW62+xw5S/uaLj6cA==} + + pug-code-gen@3.0.3: + resolution: {integrity: sha512-cYQg0JW0w32Ux+XTeZnBEeuWrAY7/HNE6TWnhiHGnnRYlCgyAUPoyh9KzCMa9WhcJlJ1AtQqpEYHc+vbCzA+Aw==} + + pug-error@2.1.0: + resolution: {integrity: sha512-lv7sU9e5Jk8IeUheHata6/UThZ7RK2jnaaNztxfPYUY+VxZyk/ePVaNZ/vwmH8WqGvDz3LrNYt/+gA55NDg6Pg==} + + pug-filters@4.0.0: + resolution: {integrity: sha512-yeNFtq5Yxmfz0f9z2rMXGw/8/4i1cCFecw/Q7+D0V2DdtII5UvqE12VaZ2AY7ri6o5RNXiweGH79OCq+2RQU4A==} + + pug-lexer@5.0.1: + resolution: {integrity: sha512-0I6C62+keXlZPZkOJeVam9aBLVP2EnbeDw3An+k0/QlqdwH6rv8284nko14Na7c0TtqtogfWXcRoFE4O4Ff20w==} + + pug-linker@4.0.0: + resolution: {integrity: sha512-gjD1yzp0yxbQqnzBAdlhbgoJL5qIFJw78juN1NpTLt/mfPJ5VgC4BvkoD3G23qKzJtIIXBbcCt6FioLSFLOHdw==} + + pug-load@3.0.0: + resolution: {integrity: sha512-OCjTEnhLWZBvS4zni/WUMjH2YSUosnsmjGBB1An7CsKQarYSWQ0GCVyd4eQPMFJqZ8w9xgs01QdiZXKVjk92EQ==} + + pug-parser@6.0.0: + resolution: {integrity: sha512-ukiYM/9cH6Cml+AOl5kETtM9NR3WulyVP2y4HOU45DyMim1IeP/OOiyEWRr6qk5I5klpsBnbuHpwKmTx6WURnw==} + + pug-runtime@3.0.1: + resolution: {integrity: sha512-L50zbvrQ35TkpHwv0G6aLSuueDRwc/97XdY8kL3tOT0FmhgG7UypU3VztfV/LATAvmUfYi4wNxSajhSAeNN+Kg==} + + pug-strip-comments@2.0.0: + resolution: {integrity: sha512-zo8DsDpH7eTkPHCXFeAk1xZXJbyoTfdPlNR0bK7rpOMuhBYb0f5qUVCO1xlsitYd3w5FQTK7zpNVKb3rZoUrrQ==} + + pug-walk@2.0.0: + resolution: {integrity: sha512-yYELe9Q5q9IQhuvqsZNwA5hfPkMJ8u92bQLIMcsMxf/VADjNtEYptU+inlufAFYcWdHlwNfZOEnOOQrZrcyJCQ==} + + pug@3.0.3: + resolution: {integrity: sha512-uBi6kmc9f3SZ3PXxqcHiUZLmIXgfgWooKWXcwSGwQd2Zi5Rb0bT14+8CJjJgI8AB+nndLaNgHGrcc6bPIB665g==} + punycode.js@2.3.1: resolution: {integrity: sha512-uxFIHU0YlHYhDQtV4R9J6a52SLx28BCjT+4ieh7IGbgwVJWO+km431c4yRlREUAsAmt/uMjQUyQHNEPf0M39CA==} engines: {node: '>=6'} @@ -2876,10 +3394,23 @@ packages: rangetouch@2.0.1: resolution: {integrity: sha512-sln+pNSc8NGaHoLzwNBssFSf/rSYkqeBXzX1AtJlkJiUaVSJSbRAWJk+4omsXkN+EJalzkZhWQ3th1m0FpR5xA==} + react-dom@19.2.4: + resolution: {integrity: sha512-AXJdLo8kgMbimY95O2aKQqsz2iWi9jMgKJhRBAxECE4IFxfcazB2LmzloIoibJI3C12IlY20+KFaLv+71bUJeQ==} + peerDependencies: + react: ^19.2.4 + + react@19.2.4: + resolution: {integrity: sha512-9nfp2hYpCwOjAN+8TZFGhtWEwgvWHXqESH8qT89AT/lWklpLON22Lc8pEtnpsZz7VmawabSU0gCjnj8aC0euHQ==} + engines: {node: '>=0.10.0'} + readdirp@5.0.0: resolution: {integrity: sha512-9u/XQ1pvrQtYyMpZe7DXKv2p5CNvyVwzUB6uhLAnQwHMSgKMBR62lc7AHljaeteeHXn11XTAaLLUVZYVZyuRBQ==} engines: {node: '>= 20.19.0'} + recast@0.23.11: + resolution: {integrity: sha512-YTUo+Flmw4ZXiWfQKGcwwc11KnoRAYgzAE2E7mXKCjSviTKShtxBsN6YUUBB2gtaBzKzeKunxhUwNHQuRryhWA==} + engines: {node: '>= 4'} + reflect.getprototypeof@1.0.10: resolution: {integrity: sha512-00o4I+DVrefhv+nX0ulyi3biSHCPDe+yLv5o/p6d/UVlirijB8E16FtfwSAi4g3tcqrQ4lRAqQSoFEZJehYEcw==} engines: {node: '>= 0.4'} @@ -2965,6 +3496,9 @@ packages: resolution: {integrity: sha512-21IYA3Q5cQf089Z6tgaUTr7lDAyzoTPx5HRtbhsME8Udispad8dC/+sziTNugOEx54ilvatQ9YCzl4KQLPcRHA==} engines: {node: '>=11.0.0'} + scheduler@0.27.0: + resolution: {integrity: sha512-eNv+WrVbKu1f3vbYJT/xtiF5syA5HPIMtf9IgY/nKg0sWqzAUEvqY/xm7OcZc/qafLx/iO9FgOmeSAp4v5ti/Q==} + scule@1.3.0: resolution: {integrity: sha512-6FtHJEvt+pVMIB9IBY+IcCJ6Z5f1iQnytgyfKMhDKgmzYG+TeH/wx1y3l27rshSbLiSanrR9ffZDrEsmjlQF2g==} @@ -3061,6 +3595,15 @@ packages: resolution: {integrity: sha512-eLoXW/DHyl62zxY4SCaIgnRhuMr6ri4juEYARS8E6sCEqzKpOiE521Ucofdx+KnDZl5xmvGYaaKCk5FEOxJCoQ==} engines: {node: '>= 0.4'} + storybook@8.6.17: + resolution: {integrity: sha512-krR/l680A6qVnkGiK9p8jY0ucX3+kFCs2f4zw+S3w2Cdq8EiM/tFebPcX2V4S3z2UsO0v0dwAJOJNpzbFPdmVg==} + hasBin: true + peerDependencies: + prettier: ^2 || ^3 + peerDependenciesMeta: + prettier: + optional: true + string.prototype.matchall@4.0.12: resolution: {integrity: sha512-6CC9uyBL+/48dYizRf7H7VAYCMCNTBeM78x/VTUe9bFEaxBepPJDa1Ow99LqI/1yF7kuy7Q3cQsYMrcjGUcskA==} engines: {node: '>= 0.4'} @@ -3116,6 +3659,9 @@ packages: engines: {node: '>=10'} hasBin: true + 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==} @@ -3131,6 +3677,9 @@ packages: resolution: {integrity: sha512-PSkbLUoxOFRzJYjjxHJt9xro7D+iilgMX/C9lawzVuYiIdcihh9DXmVibBe8lmcFrRi/VzlPjBxbN7rH24q8/Q==} engines: {node: '>=14.0.0'} + token-stream@1.0.0: + resolution: {integrity: sha512-VSsyNPPW74RpHwR8Fc21uubwHY7wMDeJLys2IX5zJNih+OnAnaifKHo+1LHT7DAdloQ7apeaaWg8l7qnf/TnEg==} + tr46@1.0.1: resolution: {integrity: sha512-dTpowEjclQ7Kgx5SdBkqRzVhERQXov8/l9Ft9dVM9fmg0W0KQSVaXX9T4i6twCPNtYiZM53lpSSUAwJbFPOHxA==} @@ -3144,6 +3693,12 @@ packages: resolution: {integrity: sha512-q5W7tVM71e2xjHZTlgfTDoPF/SmqKG5hddq9SzR49CH2hayqRKJtQ4mtRlSxKaJlR/+9rEM+mnBHf7I2/BQcpQ==} engines: {node: '>=6.10'} + ts-map@1.0.3: + resolution: {integrity: sha512-vDWbsl26LIcPGmDpoVzjEP6+hvHZkBkLW7JpvwbCv/5IYPJlsbzCVXY3wsCeAxAUeTclNOUZxnLdGh3VBD/J6w==} + + tslib@2.8.1: + resolution: {integrity: sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==} + tsx@4.21.0: resolution: {integrity: sha512-5C1sg4USs1lfG0GFb2RLXsdpXqBSEhAaA/0kPL01wxzpMqLILNxIxIOKiILz+cdg/pLnOUxFYOR5yhHU666wbw==} engines: {node: '>=18.0.0'} @@ -3191,6 +3746,10 @@ packages: resolution: {integrity: sha512-eaBzG6MxNzEn9kiwvtre90cXaNLkmadMWa1zQMs3XORCXNbsH/OewwbxC5ia9dCxIxnTAsSxXJaa/p5y8DlvJg==} engines: {node: '>=10'} + type-fest@2.19.0: + resolution: {integrity: sha512-RAH822pAdBgcNMAfWnCBU3CFZcfZ/i1eZjwFU/dsLKumyuuP3niueg2UAukXYF0E2AAoc82ZSSf9J0WQBinzHA==} + engines: {node: '>=12.20'} + typed-array-buffer@1.0.3: resolution: {integrity: sha512-nAYYwfY3qnzX30IkA6AQZjVbtK6duGontcQm1WSG1MD94YLqK0515GNApXkoxKOWMusVssAHWLh9SeaoefYFGw==} engines: {node: '>= 0.4'} @@ -3260,6 +3819,10 @@ packages: resolution: {integrity: sha512-5lWVjgi6vuHhJ526bI4nlCOmkCIF3nnfXkCMDeMJrtdvxTs6ZFCM8oNufGTsDbKv/tJ/xj8RpvXjRuPBZJuJog==} engines: {node: '>=20.19.0'} + unplugin@1.16.1: + resolution: {integrity: sha512-4/u/j4FrCKdi17jaxuJA0jClGxB1AvU2hw/IuayPc4ay1XGaJs/rbb4v5WKwAjNifjmXK9PIFyuPiaK8azyR9w==} + engines: {node: '>=14.0.0'} + unplugin@3.0.0: resolution: {integrity: sha512-0Mqk3AT2TZCXWKdcoaufeXNukv2mTrEZExeXlHIOZXdqYoHHr4n51pymnwV8x2BOVxwXbK2HLlI7usrqMpycdg==} engines: {node: ^20.19.0 || >=22.12.0} @@ -3283,10 +3846,17 @@ packages: util-deprecate@1.0.2: resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==} + util@0.12.5: + resolution: {integrity: sha512-kZf/K6hEIrWHI6XqOFUiiMa+79wE/D8Q+NCNAWclkyg3b4d2k7s0QGepNjiABc+aR3N1PAyHL7p6UcLY6LmrnA==} + uuid@11.1.0: resolution: {integrity: sha512-0/A9rDy9P7cJ+8w1c9WD9V//9Wj15Ce2MPz8Ri6032usz+NfePxx5AcN3bN+r6ZL6jEo066/yNYB3tn4pQEx+A==} hasBin: true + uuid@9.0.1: + resolution: {integrity: sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==} + hasBin: true + vite-plugin-pwa@1.2.0: resolution: {integrity: sha512-a2xld+SJshT9Lgcv8Ji4+srFJL4k/1bVbd1x06JIkvecpQkwkvCncD1+gSzcdm3s+owWLpMJerG3aN5jupJEVw==} engines: {node: '>=16.0.0'} @@ -3373,6 +3943,10 @@ packages: jsdom: optional: true + void-elements@3.1.0: + resolution: {integrity: sha512-Dhxzh5HZuiHQhbvTW9AMetFfBHDMYpo23Uo9btPXgdYP+3T5S+p+jgNy7spra+veYhBP2dCSgxR/i2Y02h5/6w==} + engines: {node: '>=0.10.0'} + vscode-jsonrpc@8.2.0: resolution: {integrity: sha512-C+r0eKJUIfiDIfwJhria30+TYWPtuHJXHtI7J0YlOmKAo7ogxP20T0zxB7HZQIFhIyvoBPwWskjxrvAtfjyZfA==} engines: {node: '>=14.0.0'} @@ -3393,12 +3967,36 @@ packages: vscode-uri@3.1.0: resolution: {integrity: sha512-/BpdSx+yCQGnCvecbyXdxHDkuk55/G3xwnC0GqY4gmQ3j+A+g8kzzgB4Nk/SINjqn6+waqw3EgbVF2QKExkRxQ==} + vue-component-meta@2.2.12: + resolution: {integrity: sha512-dQU6/obNSNbennJ1xd+rhDid4g3vQro+9qUBBIg8HMZH2Zs1jTpkFNxuQ3z77bOlU+ew08Qck9sbYkdSePr0Pw==} + peerDependencies: + typescript: '*' + peerDependenciesMeta: + typescript: + optional: true + + vue-component-type-helpers@2.2.12: + resolution: {integrity: sha512-YbGqHZ5/eW4SnkPNR44mKVc6ZKQoRs/Rux1sxC6rdwXb4qpbOSYfDr9DsTHolOTGmIKgM9j141mZbBeg05R1pw==} + + vue-component-type-helpers@3.2.5: + resolution: {integrity: sha512-tkvNr+bU8+xD/onAThIe7CHFvOJ/BO6XCOrxMzeytJq40nTfpGDJuVjyCM8ccGZKfAbGk2YfuZyDMXM56qheZQ==} + + vue-docgen-api@4.79.2: + resolution: {integrity: sha512-n9ENAcs+40awPZMsas7STqjkZiVlIjxIKgiJr5rSohDP0/JCrD9VtlzNojafsA1MChm/hz2h3PDtUedx3lbgfA==} + peerDependencies: + vue: '>=2' + vue-eslint-parser@10.4.0: resolution: {integrity: sha512-Vxi9pJdbN3ZnVGLODVtZ7y4Y2kzAAE2Cm0CZ3ZDRvydVYxZ6VrnBhLikBsRS+dpwj4Jv4UCv21PTEwF5rQ9WXg==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: eslint: ^8.57.0 || ^9.0.0 || ^10.0.0 + vue-inbrowser-compiler-independent-utils@4.71.1: + resolution: {integrity: sha512-K3wt3iVmNGaFEOUR4JIThQRWfqokxLfnPslD41FDZB2ajXp789+wCqJyGYlIFsvEQ2P61PInw6/ph5iiqg51gg==} + peerDependencies: + vue: '>=2' + vue-router@5.0.3: resolution: {integrity: sha512-nG1c7aAFac7NYj8Hluo68WyWfc41xkEjaR0ViLHCa3oDvTQ/nIuLJlXJX1NUPw/DXzx/8+OKMng045HHQKQKWw==} peerDependencies: @@ -3470,6 +4068,10 @@ packages: engines: {node: '>=8'} hasBin: true + with@7.0.2: + resolution: {integrity: sha512-RNGKj82nUPg3g5ygxkQl0R937xLyho1J24ItRCBTr/m1YnZkzJy1hUiHUJrc/VlsDQzsCnInEGSg3bci0Lmd4w==} + engines: {node: '>= 10.0.0'} + word-wrap@1.2.5: resolution: {integrity: sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==} engines: {node: '>=0.10.0'} @@ -4246,81 +4848,159 @@ snapshots: '@chevrotain/utils@11.1.2': {} + '@esbuild/aix-ppc64@0.25.12': + optional: true + '@esbuild/aix-ppc64@0.27.3': optional: true + '@esbuild/android-arm64@0.25.12': + optional: true + '@esbuild/android-arm64@0.27.3': optional: true + '@esbuild/android-arm@0.25.12': + optional: true + '@esbuild/android-arm@0.27.3': optional: true + '@esbuild/android-x64@0.25.12': + optional: true + '@esbuild/android-x64@0.27.3': optional: true + '@esbuild/darwin-arm64@0.25.12': + optional: true + '@esbuild/darwin-arm64@0.27.3': optional: true + '@esbuild/darwin-x64@0.25.12': + optional: true + '@esbuild/darwin-x64@0.27.3': optional: true + '@esbuild/freebsd-arm64@0.25.12': + optional: true + '@esbuild/freebsd-arm64@0.27.3': optional: true + '@esbuild/freebsd-x64@0.25.12': + optional: true + '@esbuild/freebsd-x64@0.27.3': optional: true + '@esbuild/linux-arm64@0.25.12': + optional: true + '@esbuild/linux-arm64@0.27.3': optional: true + '@esbuild/linux-arm@0.25.12': + optional: true + '@esbuild/linux-arm@0.27.3': optional: true + '@esbuild/linux-ia32@0.25.12': + optional: true + '@esbuild/linux-ia32@0.27.3': optional: true + '@esbuild/linux-loong64@0.25.12': + optional: true + '@esbuild/linux-loong64@0.27.3': optional: true + '@esbuild/linux-mips64el@0.25.12': + optional: true + '@esbuild/linux-mips64el@0.27.3': optional: true + '@esbuild/linux-ppc64@0.25.12': + optional: true + '@esbuild/linux-ppc64@0.27.3': optional: true + '@esbuild/linux-riscv64@0.25.12': + optional: true + '@esbuild/linux-riscv64@0.27.3': optional: true + '@esbuild/linux-s390x@0.25.12': + optional: true + '@esbuild/linux-s390x@0.27.3': optional: true + '@esbuild/linux-x64@0.25.12': + optional: true + '@esbuild/linux-x64@0.27.3': optional: true + '@esbuild/netbsd-arm64@0.25.12': + optional: true + '@esbuild/netbsd-arm64@0.27.3': optional: true + '@esbuild/netbsd-x64@0.25.12': + optional: true + '@esbuild/netbsd-x64@0.27.3': optional: true + '@esbuild/openbsd-arm64@0.25.12': + optional: true + '@esbuild/openbsd-arm64@0.27.3': optional: true + '@esbuild/openbsd-x64@0.25.12': + optional: true + '@esbuild/openbsd-x64@0.27.3': optional: true + '@esbuild/openharmony-arm64@0.25.12': + optional: true + '@esbuild/openharmony-arm64@0.27.3': optional: true + '@esbuild/sunos-x64@0.25.12': + optional: true + '@esbuild/sunos-x64@0.27.3': optional: true + '@esbuild/win32-arm64@0.25.12': + optional: true + '@esbuild/win32-arm64@0.27.3': optional: true + '@esbuild/win32-ia32@0.25.12': + optional: true + '@esbuild/win32-ia32@0.27.3': optional: true + '@esbuild/win32-x64@0.25.12': + optional: true + '@esbuild/win32-x64@0.27.3': optional: true @@ -4403,6 +5083,12 @@ snapshots: '@jridgewell/resolve-uri': 3.1.2 '@jridgewell/sourcemap-codec': 1.5.5 + '@mdx-js/react@3.1.1(@types/react@19.2.14)(react@19.2.4)': + dependencies: + '@types/mdx': 2.0.13 + '@types/react': 19.2.14 + react: 19.2.4 + '@mermaid-js/parser@1.0.0': dependencies: langium: 4.2.1 @@ -4586,6 +5272,187 @@ snapshots: '@standard-schema/spec@1.1.0': {} + '@storybook/addon-actions@8.6.14(storybook@8.6.17)': + dependencies: + '@storybook/global': 5.0.0 + '@types/uuid': 9.0.8 + dequal: 2.0.3 + polished: 4.3.1 + storybook: 8.6.17 + uuid: 9.0.1 + + '@storybook/addon-backgrounds@8.6.14(storybook@8.6.17)': + dependencies: + '@storybook/global': 5.0.0 + memoizerific: 1.11.3 + storybook: 8.6.17 + ts-dedent: 2.2.0 + + '@storybook/addon-controls@8.6.14(storybook@8.6.17)': + dependencies: + '@storybook/global': 5.0.0 + dequal: 2.0.3 + storybook: 8.6.17 + ts-dedent: 2.2.0 + + '@storybook/addon-docs@8.6.14(@types/react@19.2.14)(storybook@8.6.17)': + dependencies: + '@mdx-js/react': 3.1.1(@types/react@19.2.14)(react@19.2.4) + '@storybook/blocks': 8.6.14(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(storybook@8.6.17) + '@storybook/csf-plugin': 8.6.14(storybook@8.6.17) + '@storybook/react-dom-shim': 8.6.14(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(storybook@8.6.17) + react: 19.2.4 + react-dom: 19.2.4(react@19.2.4) + storybook: 8.6.17 + ts-dedent: 2.2.0 + transitivePeerDependencies: + - '@types/react' + + '@storybook/addon-essentials@8.6.14(@types/react@19.2.14)(storybook@8.6.17)': + dependencies: + '@storybook/addon-actions': 8.6.14(storybook@8.6.17) + '@storybook/addon-backgrounds': 8.6.14(storybook@8.6.17) + '@storybook/addon-controls': 8.6.14(storybook@8.6.17) + '@storybook/addon-docs': 8.6.14(@types/react@19.2.14)(storybook@8.6.17) + '@storybook/addon-highlight': 8.6.14(storybook@8.6.17) + '@storybook/addon-measure': 8.6.14(storybook@8.6.17) + '@storybook/addon-outline': 8.6.14(storybook@8.6.17) + '@storybook/addon-toolbars': 8.6.14(storybook@8.6.17) + '@storybook/addon-viewport': 8.6.14(storybook@8.6.17) + storybook: 8.6.17 + ts-dedent: 2.2.0 + transitivePeerDependencies: + - '@types/react' + + '@storybook/addon-highlight@8.6.14(storybook@8.6.17)': + dependencies: + '@storybook/global': 5.0.0 + storybook: 8.6.17 + + '@storybook/addon-measure@8.6.14(storybook@8.6.17)': + dependencies: + '@storybook/global': 5.0.0 + storybook: 8.6.17 + tiny-invariant: 1.3.3 + + '@storybook/addon-outline@8.6.14(storybook@8.6.17)': + dependencies: + '@storybook/global': 5.0.0 + storybook: 8.6.17 + ts-dedent: 2.2.0 + + '@storybook/addon-toolbars@8.6.14(storybook@8.6.17)': + dependencies: + storybook: 8.6.17 + + '@storybook/addon-viewport@8.6.14(storybook@8.6.17)': + dependencies: + memoizerific: 1.11.3 + storybook: 8.6.17 + + '@storybook/blocks@8.6.14(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(storybook@8.6.17)': + dependencies: + '@storybook/icons': 1.6.0(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + storybook: 8.6.17 + ts-dedent: 2.2.0 + optionalDependencies: + react: 19.2.4 + react-dom: 19.2.4(react@19.2.4) + + '@storybook/builder-vite@8.6.17(storybook@8.6.17)(vite@7.3.1(@types/node@25.3.3)(jiti@2.6.1)(lightningcss@1.31.1)(terser@5.46.0)(tsx@4.21.0)(yaml@2.8.2))': + dependencies: + '@storybook/csf-plugin': 8.6.17(storybook@8.6.17) + browser-assert: 1.2.1 + storybook: 8.6.17 + ts-dedent: 2.2.0 + vite: 7.3.1(@types/node@25.3.3)(jiti@2.6.1)(lightningcss@1.31.1)(terser@5.46.0)(tsx@4.21.0)(yaml@2.8.2) + + '@storybook/components@8.6.17(storybook@8.6.17)': + dependencies: + storybook: 8.6.17 + + '@storybook/core@8.6.17(storybook@8.6.17)': + dependencies: + '@storybook/theming': 8.6.17(storybook@8.6.17) + better-opn: 3.0.2 + browser-assert: 1.2.1 + esbuild: 0.25.12 + esbuild-register: 3.6.0(esbuild@0.25.12) + jsdoc-type-pratt-parser: 4.8.0 + process: 0.11.10 + recast: 0.23.11 + semver: 7.7.4 + util: 0.12.5 + ws: 8.19.0 + transitivePeerDependencies: + - bufferutil + - storybook + - supports-color + - utf-8-validate + + '@storybook/csf-plugin@8.6.14(storybook@8.6.17)': + dependencies: + storybook: 8.6.17 + unplugin: 1.16.1 + + '@storybook/csf-plugin@8.6.17(storybook@8.6.17)': + dependencies: + storybook: 8.6.17 + unplugin: 1.16.1 + + '@storybook/global@5.0.0': {} + + '@storybook/icons@1.6.0(react-dom@19.2.4(react@19.2.4))(react@19.2.4)': + dependencies: + react: 19.2.4 + react-dom: 19.2.4(react@19.2.4) + + '@storybook/manager-api@8.6.17(storybook@8.6.17)': + dependencies: + storybook: 8.6.17 + + '@storybook/preview-api@8.6.17(storybook@8.6.17)': + dependencies: + storybook: 8.6.17 + + '@storybook/react-dom-shim@8.6.14(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(storybook@8.6.17)': + dependencies: + react: 19.2.4 + react-dom: 19.2.4(react@19.2.4) + storybook: 8.6.17 + + '@storybook/theming@8.6.17(storybook@8.6.17)': + dependencies: + storybook: 8.6.17 + + '@storybook/vue3-vite@8.6.17(storybook@8.6.17)(vite@7.3.1(@types/node@25.3.3)(jiti@2.6.1)(lightningcss@1.31.1)(terser@5.46.0)(tsx@4.21.0)(yaml@2.8.2))(vue@3.5.29(typescript@5.8.3))': + dependencies: + '@storybook/builder-vite': 8.6.17(storybook@8.6.17)(vite@7.3.1(@types/node@25.3.3)(jiti@2.6.1)(lightningcss@1.31.1)(terser@5.46.0)(tsx@4.21.0)(yaml@2.8.2)) + '@storybook/vue3': 8.6.17(storybook@8.6.17)(vue@3.5.29(typescript@5.8.3)) + find-package-json: 1.2.0 + magic-string: 0.30.21 + storybook: 8.6.17 + typescript: 5.8.3 + vite: 7.3.1(@types/node@25.3.3)(jiti@2.6.1)(lightningcss@1.31.1)(terser@5.46.0)(tsx@4.21.0)(yaml@2.8.2) + vue-component-meta: 2.2.12(typescript@5.8.3) + vue-docgen-api: 4.79.2(vue@3.5.29(typescript@5.8.3)) + transitivePeerDependencies: + - vue + + '@storybook/vue3@8.6.17(storybook@8.6.17)(vue@3.5.29(typescript@5.8.3))': + dependencies: + '@storybook/components': 8.6.17(storybook@8.6.17) + '@storybook/global': 5.0.0 + '@storybook/manager-api': 8.6.17(storybook@8.6.17) + '@storybook/preview-api': 8.6.17(storybook@8.6.17) + '@storybook/theming': 8.6.17(storybook@8.6.17) + '@vue/compiler-core': 3.5.29 + storybook: 8.6.17 + ts-dedent: 2.2.0 + type-fest: 2.19.0 + vue: 3.5.29(typescript@5.8.3) + vue-component-type-helpers: 3.2.5 + '@surma/rollup-plugin-off-main-thread@2.2.3': dependencies: ejs: 3.1.10 @@ -4815,14 +5682,22 @@ snapshots: '@types/mdurl@2.0.0': {} + '@types/mdx@2.0.13': {} + '@types/node@25.3.3': dependencies: undici-types: 7.18.2 + '@types/react@19.2.14': + dependencies: + csstype: 3.2.3 + '@types/resolve@1.20.2': {} '@types/trusted-types@2.0.7': {} + '@types/uuid@9.0.8': {} + '@types/whatwg-mimetype@3.0.2': {} '@types/ws@8.18.1': @@ -4965,12 +5840,24 @@ snapshots: '@vitest/pretty-format': 4.0.18 tinyrainbow: 3.0.3 + '@volar/language-core@2.4.15': + dependencies: + '@volar/source-map': 2.4.15 + '@volar/language-core@2.4.28': dependencies: '@volar/source-map': 2.4.28 + '@volar/source-map@2.4.15': {} + '@volar/source-map@2.4.28': {} + '@volar/typescript@2.4.15': + dependencies: + '@volar/language-core': 2.4.15 + path-browserify: 1.0.1 + vscode-uri: 3.1.0 + '@volar/typescript@2.4.28': dependencies: '@volar/language-core': 2.4.28 @@ -5017,6 +5904,11 @@ snapshots: '@vue/compiler-dom': 3.5.29 '@vue/shared': 3.5.29 + '@vue/compiler-vue2@2.7.16': + dependencies: + de-indent: 1.0.2 + he: 1.2.0 + '@vue/devtools-api@7.7.9': dependencies: '@vue/devtools-kit': 7.7.9 @@ -5048,6 +5940,19 @@ snapshots: '@vue/devtools-shared@8.0.7': {} + '@vue/language-core@2.2.12(typescript@5.8.3)': + dependencies: + '@volar/language-core': 2.4.15 + '@vue/compiler-dom': 3.5.29 + '@vue/compiler-vue2': 2.7.16 + '@vue/shared': 3.5.29 + alien-signals: 1.0.13 + minimatch: 9.0.9 + muggle-string: 0.4.1 + path-browserify: 1.0.1 + optionalDependencies: + typescript: 5.8.3 + '@vue/language-core@3.2.5': dependencies: '@volar/language-core': 2.4.28 @@ -5086,6 +5991,8 @@ snapshots: dependencies: acorn: 8.16.0 + acorn@7.4.1: {} + acorn@8.16.0: {} ajv@6.14.0: @@ -5102,6 +6009,8 @@ snapshots: json-schema-traverse: 1.0.0 require-from-string: 2.0.2 + alien-signals@1.0.13: {} + alien-signals@3.1.2: {} argparse@2.0.1: {} @@ -5121,6 +6030,10 @@ snapshots: get-intrinsic: 1.3.0 is-array-buffer: 3.0.5 + asap@2.0.6: {} + + assert-never@1.4.0: {} + assertion-error@2.0.1: {} ast-kit@2.2.0: @@ -5128,6 +6041,10 @@ snapshots: '@babel/parser': 7.29.0 pathe: 2.0.3 + ast-types@0.16.1: + dependencies: + tslib: 2.8.1 + ast-walker-scope@0.8.3: dependencies: '@babel/parser': 7.29.0 @@ -5167,12 +6084,20 @@ snapshots: transitivePeerDependencies: - supports-color + babel-walk@3.0.0-canary-5: + dependencies: + '@babel/types': 7.29.0 + balanced-match@1.0.2: {} balanced-match@4.0.4: {} baseline-browser-mapping@2.10.0: {} + better-opn@3.0.2: + dependencies: + open: 8.4.2 + birpc@2.9.0: {} boolbase@1.0.0: {} @@ -5185,6 +6110,8 @@ snapshots: dependencies: balanced-match: 4.0.4 + browser-assert@1.2.1: {} + browserslist@4.28.1: dependencies: baseline-browser-mapping: 2.10.0 @@ -5216,6 +6143,10 @@ snapshots: chai@6.2.2: {} + character-parser@2.2.0: + dependencies: + is-regex: 1.2.1 + chevrotain-allstar@0.3.1(chevrotain@11.1.2): dependencies: chevrotain: 11.1.2 @@ -5246,6 +6177,11 @@ snapshots: confbox@0.2.4: {} + constantinople@4.0.1: + dependencies: + '@babel/parser': 7.29.0 + '@babel/types': 7.29.0 + convert-source-map@2.0.0: {} copy-anything@4.0.5: @@ -5484,6 +6420,8 @@ snapshots: dayjs@1.11.19: {} + de-indent@1.0.2: {} + debug@4.4.3: dependencies: ms: 2.1.3 @@ -5498,6 +6436,8 @@ snapshots: es-errors: 1.3.0 gopd: 1.2.0 + define-lazy-prop@2.0.0: {} + define-properties@1.2.1: dependencies: define-data-property: 1.1.4 @@ -5508,8 +6448,12 @@ snapshots: dependencies: robust-predicates: 3.0.2 + dequal@2.0.3: {} + detect-libc@2.1.2: {} + doctypes@1.1.0: {} + dompurify@3.3.1: optionalDependencies: '@types/trusted-types': 2.0.7 @@ -5622,6 +6566,42 @@ snapshots: is-date-object: 1.1.0 is-symbol: 1.1.1 + esbuild-register@3.6.0(esbuild@0.25.12): + dependencies: + debug: 4.4.3 + esbuild: 0.25.12 + transitivePeerDependencies: + - supports-color + + esbuild@0.25.12: + optionalDependencies: + '@esbuild/aix-ppc64': 0.25.12 + '@esbuild/android-arm': 0.25.12 + '@esbuild/android-arm64': 0.25.12 + '@esbuild/android-x64': 0.25.12 + '@esbuild/darwin-arm64': 0.25.12 + '@esbuild/darwin-x64': 0.25.12 + '@esbuild/freebsd-arm64': 0.25.12 + '@esbuild/freebsd-x64': 0.25.12 + '@esbuild/linux-arm': 0.25.12 + '@esbuild/linux-arm64': 0.25.12 + '@esbuild/linux-ia32': 0.25.12 + '@esbuild/linux-loong64': 0.25.12 + '@esbuild/linux-mips64el': 0.25.12 + '@esbuild/linux-ppc64': 0.25.12 + '@esbuild/linux-riscv64': 0.25.12 + '@esbuild/linux-s390x': 0.25.12 + '@esbuild/linux-x64': 0.25.12 + '@esbuild/netbsd-arm64': 0.25.12 + '@esbuild/netbsd-x64': 0.25.12 + '@esbuild/openbsd-arm64': 0.25.12 + '@esbuild/openbsd-x64': 0.25.12 + '@esbuild/openharmony-arm64': 0.25.12 + '@esbuild/sunos-x64': 0.25.12 + '@esbuild/win32-arm64': 0.25.12 + '@esbuild/win32-ia32': 0.25.12 + '@esbuild/win32-x64': 0.25.12 + esbuild@0.27.3: optionalDependencies: '@esbuild/aix-ppc64': 0.27.3 @@ -5716,12 +6696,16 @@ snapshots: transitivePeerDependencies: - supports-color + esm-resolve@1.0.11: {} + espree@11.1.1: dependencies: acorn: 8.16.0 acorn-jsx: 5.3.2(acorn@8.16.0) eslint-visitor-keys: 5.0.1 + esprima@4.0.1: {} + esquery@1.7.0: dependencies: estraverse: 5.3.0 @@ -5766,6 +6750,8 @@ snapshots: dependencies: minimatch: 5.1.9 + find-package-json@1.2.0: {} + find-up@5.0.0: dependencies: locate-path: 6.0.0 @@ -5901,10 +6887,14 @@ snapshots: dependencies: has-symbols: 1.1.0 + hash-sum@2.0.0: {} + hasown@2.0.2: dependencies: function-bind: 1.1.2 + he@1.2.0: {} + hls.js@1.6.15: {} hookable@5.5.3: {} @@ -5923,6 +6913,8 @@ snapshots: imurmurhash@0.1.4: {} + inherits@2.0.4: {} + internal-slot@1.1.0: dependencies: es-errors: 1.3.0 @@ -5933,6 +6925,11 @@ snapshots: internmap@2.0.3: {} + is-arguments@1.2.0: + dependencies: + call-bound: 1.0.4 + has-tostringtag: 1.0.2 + is-array-buffer@3.0.5: dependencies: call-bind: 1.0.8 @@ -5973,6 +6970,13 @@ snapshots: call-bound: 1.0.4 has-tostringtag: 1.0.2 + is-docker@2.2.1: {} + + is-expression@4.0.0: + dependencies: + acorn: 7.4.1 + object-assign: 4.1.1 + is-extglob@2.1.1: {} is-finalizationregistry@1.1.1: @@ -6004,6 +7008,8 @@ snapshots: is-obj@1.0.1: {} + is-promise@2.2.2: {} + is-regex@1.2.1: dependencies: call-bound: 1.0.4 @@ -6049,6 +7055,10 @@ snapshots: is-what@5.5.0: {} + is-wsl@2.2.0: + dependencies: + is-docker: 2.2.1 + isarray@2.0.5: {} isexe@2.0.0: {} @@ -6065,8 +7075,12 @@ snapshots: jiti@2.6.1: {} + js-stringify@1.0.2: {} + js-tokens@4.0.0: {} + jsdoc-type-pratt-parser@4.8.0: {} + jsesc@3.1.0: {} json-buffer@3.0.1: {} @@ -6089,6 +7103,11 @@ snapshots: jsonpointer@5.0.1: {} + jstransformer@1.0.0: + dependencies: + is-promise: 2.2.2 + promise: 7.3.1 + katex@0.16.33: dependencies: commander: 8.3.0 @@ -6199,6 +7218,8 @@ snapshots: dependencies: yallist: 3.1.1 + lru-cache@8.0.5: {} + magic-string-ast@1.0.3: dependencies: magic-string: 0.30.21 @@ -6211,6 +7232,8 @@ snapshots: dependencies: '@jridgewell/sourcemap-codec': 1.5.5 + map-or-similar@1.5.0: {} + markdown-it@14.1.1: dependencies: argparse: 2.0.1 @@ -6226,6 +7249,10 @@ snapshots: mdurl@2.0.0: {} + memoizerific@1.11.3: + dependencies: + map-or-similar: 1.5.0 + mermaid@11.12.3: dependencies: '@braintree/sanitize-url': 7.1.2 @@ -6257,6 +7284,10 @@ snapshots: dependencies: brace-expansion: 2.0.2 + minimatch@9.0.9: + dependencies: + brace-expansion: 2.0.2 + minipass@7.1.3: {} mitt@3.0.1: {} @@ -6290,6 +7321,8 @@ snapshots: dependencies: boolbase: 1.0.0 + object-assign@4.1.1: {} + object-inspect@1.13.4: {} object-keys@1.1.1: {} @@ -6305,6 +7338,12 @@ snapshots: obug@2.1.1: {} + open@8.4.2: + dependencies: + define-lazy-prop: 2.0.0 + is-docker: 2.2.1 + is-wsl: 2.2.0 + optionator@0.9.4: dependencies: deep-is: 0.1.4 @@ -6406,6 +7445,10 @@ snapshots: path-data-parser: 0.1.0 points-on-curve: 0.2.0 + polished@4.3.1: + dependencies: + '@babel/runtime': 7.28.6 + possible-typed-array-names@1.1.0: {} postcss-selector-parser@7.1.1: @@ -6425,6 +7468,79 @@ snapshots: pretty-bytes@6.1.1: {} + process@0.11.10: {} + + promise@7.3.1: + dependencies: + asap: 2.0.6 + + pug-attrs@3.0.0: + dependencies: + constantinople: 4.0.1 + js-stringify: 1.0.2 + pug-runtime: 3.0.1 + + pug-code-gen@3.0.3: + dependencies: + constantinople: 4.0.1 + doctypes: 1.1.0 + js-stringify: 1.0.2 + pug-attrs: 3.0.0 + pug-error: 2.1.0 + pug-runtime: 3.0.1 + void-elements: 3.1.0 + with: 7.0.2 + + pug-error@2.1.0: {} + + pug-filters@4.0.0: + dependencies: + constantinople: 4.0.1 + jstransformer: 1.0.0 + pug-error: 2.1.0 + pug-walk: 2.0.0 + resolve: 1.22.11 + + pug-lexer@5.0.1: + dependencies: + character-parser: 2.2.0 + is-expression: 4.0.0 + pug-error: 2.1.0 + + pug-linker@4.0.0: + dependencies: + pug-error: 2.1.0 + pug-walk: 2.0.0 + + pug-load@3.0.0: + dependencies: + object-assign: 4.1.1 + pug-walk: 2.0.0 + + pug-parser@6.0.0: + dependencies: + pug-error: 2.1.0 + token-stream: 1.0.0 + + pug-runtime@3.0.1: {} + + pug-strip-comments@2.0.0: + dependencies: + pug-error: 2.1.0 + + pug-walk@2.0.0: {} + + pug@3.0.3: + dependencies: + pug-code-gen: 3.0.3 + pug-filters: 4.0.0 + pug-lexer: 5.0.1 + pug-linker: 4.0.0 + pug-load: 3.0.0 + pug-parser: 6.0.0 + pug-runtime: 3.0.1 + pug-strip-comments: 2.0.0 + punycode.js@2.3.1: {} punycode@2.3.1: {} @@ -6437,8 +7553,23 @@ snapshots: rangetouch@2.0.1: {} + react-dom@19.2.4(react@19.2.4): + dependencies: + react: 19.2.4 + scheduler: 0.27.0 + + react@19.2.4: {} + readdirp@5.0.0: {} + 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 + reflect.getprototypeof@1.0.10: dependencies: call-bind: 1.0.8 @@ -6568,6 +7699,8 @@ snapshots: sax@1.5.0: {} + scheduler@0.27.0: {} + scule@1.3.0: {} semver@6.3.1: {} @@ -6666,6 +7799,14 @@ snapshots: es-errors: 1.3.0 internal-slot: 1.1.0 + storybook@8.6.17: + dependencies: + '@storybook/core': 8.6.17(storybook@8.6.17) + transitivePeerDependencies: + - bufferutil + - supports-color + - utf-8-validate + string.prototype.matchall@4.0.12: dependencies: call-bind: 1.0.8 @@ -6741,6 +7882,8 @@ snapshots: commander: 2.20.3 source-map-support: 0.5.21 + tiny-invariant@1.3.3: {} + tinybench@2.9.0: {} tinyexec@1.0.2: {} @@ -6752,6 +7895,8 @@ snapshots: tinyrainbow@3.0.3: {} + token-stream@1.0.0: {} + tr46@1.0.1: dependencies: punycode: 2.3.1 @@ -6762,6 +7907,10 @@ snapshots: ts-dedent@2.2.0: {} + ts-map@1.0.3: {} + + tslib@2.8.1: {} + tsx@4.21.0: dependencies: esbuild: 0.27.3 @@ -6802,6 +7951,8 @@ snapshots: type-fest@0.16.0: {} + type-fest@2.19.0: {} + typed-array-buffer@1.0.3: dependencies: call-bound: 1.0.4 @@ -6883,6 +8034,11 @@ snapshots: pathe: 2.0.3 picomatch: 4.0.3 + unplugin@1.16.1: + dependencies: + acorn: 8.16.0 + webpack-virtual-modules: 0.6.2 + unplugin@3.0.0: dependencies: '@jridgewell/remapping': 2.3.5 @@ -6905,8 +8061,18 @@ snapshots: util-deprecate@1.0.2: {} + util@0.12.5: + dependencies: + inherits: 2.0.4 + is-arguments: 1.2.0 + is-generator-function: 1.1.2 + is-typed-array: 1.1.15 + which-typed-array: 1.1.20 + uuid@11.1.0: {} + uuid@9.0.1: {} + vite-plugin-pwa@1.2.0(vite@7.3.1(@types/node@25.3.3)(jiti@2.6.1)(lightningcss@1.31.1)(terser@5.46.0)(tsx@4.21.0)(yaml@2.8.2))(workbox-build@7.4.0)(workbox-window@7.4.0): dependencies: debug: 4.4.3 @@ -6973,6 +8139,8 @@ snapshots: - tsx - yaml + void-elements@3.1.0: {} + vscode-jsonrpc@8.2.0: {} vscode-languageserver-protocol@3.17.5: @@ -6990,6 +8158,35 @@ snapshots: vscode-uri@3.1.0: {} + vue-component-meta@2.2.12(typescript@5.8.3): + dependencies: + '@volar/typescript': 2.4.15 + '@vue/language-core': 2.2.12(typescript@5.8.3) + path-browserify: 1.0.1 + vue-component-type-helpers: 2.2.12 + optionalDependencies: + typescript: 5.8.3 + + vue-component-type-helpers@2.2.12: {} + + vue-component-type-helpers@3.2.5: {} + + vue-docgen-api@4.79.2(vue@3.5.29(typescript@5.8.3)): + dependencies: + '@babel/parser': 7.29.0 + '@babel/types': 7.29.0 + '@vue/compiler-dom': 3.5.29 + '@vue/compiler-sfc': 3.5.29 + ast-types: 0.16.1 + esm-resolve: 1.0.11 + hash-sum: 2.0.0 + lru-cache: 8.0.5 + pug: 3.0.3 + recast: 0.23.11 + ts-map: 1.0.3 + vue: 3.5.29(typescript@5.8.3) + vue-inbrowser-compiler-independent-utils: 4.71.1(vue@3.5.29(typescript@5.8.3)) + vue-eslint-parser@10.4.0(eslint@10.0.2(jiti@2.6.1)): dependencies: debug: 4.4.3 @@ -7002,6 +8199,10 @@ snapshots: transitivePeerDependencies: - supports-color + vue-inbrowser-compiler-independent-utils@4.71.1(vue@3.5.29(typescript@5.8.3)): + dependencies: + vue: 3.5.29(typescript@5.8.3) + vue-router@5.0.3(@vue/compiler-sfc@3.5.29)(pinia@3.0.4(typescript@5.8.3)(vue@3.5.29(typescript@5.8.3)))(vue@3.5.29(typescript@5.8.3)): dependencies: '@babel/generator': 7.29.1 @@ -7106,6 +8307,13 @@ snapshots: siginfo: 2.0.0 stackback: 0.0.2 + with@7.0.2: + dependencies: + '@babel/parser': 7.29.0 + '@babel/types': 7.29.0 + assert-never: 1.4.0 + babel-walk: 3.0.0-canary-5 + word-wrap@1.2.5: {} workbox-background-sync@7.4.0: