diff --git a/examples/playground/index.html b/examples/playground/index.html
new file mode 100644
index 0000000..bec7e3c
--- /dev/null
+++ b/examples/playground/index.html
@@ -0,0 +1,16 @@
+
+
+
+
+
+ vibe-registry playground
+
+
+
+
+
+
+
diff --git a/examples/playground/package.json b/examples/playground/package.json
new file mode 100644
index 0000000..2b1375f
--- /dev/null
+++ b/examples/playground/package.json
@@ -0,0 +1,24 @@
+{
+ "name": "vibe-playground",
+ "version": "0.0.1",
+ "private": true,
+ "type": "module",
+ "description": "vibe-registry 渲染验证 playground:画廊 + 真实 React 渲染",
+ "scripts": {
+ "dev": "vite",
+ "build": "tsc --noEmit && vite build",
+ "typecheck": "tsc --noEmit"
+ },
+ "dependencies": {
+ "react": "^18.3.0",
+ "react-dom": "^18.3.0",
+ "vibe-registry": "workspace:*"
+ },
+ "devDependencies": {
+ "@types/react": "^18.3.0",
+ "@types/react-dom": "^18.3.0",
+ "@vitejs/plugin-react": "^4.3.0",
+ "typescript": "^5.8.0",
+ "vite": "^6.0.0"
+ }
+}
diff --git a/examples/playground/src/layouts/admin.tsx b/examples/playground/src/layouts/admin.tsx
new file mode 100644
index 0000000..2382e5a
--- /dev/null
+++ b/examples/playground/src/layouts/admin.tsx
@@ -0,0 +1,27 @@
+/**
+ * admin 布局的真实渲染骨架
+ * layout id 是稳定契约:页面只引用 'admin',骨架长什么样由这里决定
+ */
+import React from 'react'
+import type { LayoutRenderProps } from 'vibe-registry'
+
+export function AdminLayout({ blocks }: LayoutRenderProps): React.ReactElement {
+ const sidebar = (blocks['sidebar'] as React.ReactNode[] | undefined) ?? []
+ const header = (blocks['header'] as React.ReactNode[] | undefined) ?? []
+ const content = (blocks['content'] as React.ReactNode[] | undefined) ?? []
+ const footer = (blocks['footer'] as React.ReactNode[] | undefined) ?? []
+
+ return (
+
+
+
+
{header}
+
{content}
+ {footer.length > 0 ?
: null}
+
+
+ )
+}
diff --git a/examples/playground/src/main.tsx b/examples/playground/src/main.tsx
new file mode 100644
index 0000000..285f3ca
--- /dev/null
+++ b/examples/playground/src/main.tsx
@@ -0,0 +1,50 @@
+/**
+ * playground 入口:画廊 + 真实页面渲染(类 Vite 首页体验)
+ * 演示:import 即注册 → setup 业务 → PageView 渲染
+ */
+import React from 'react'
+import { createRoot } from 'react-dom/client'
+import { registry } from 'vibe-registry'
+import { PageView, LayoutGallery } from 'vibe-registry/render'
+import { orderListPage } from './pages.ts'
+
+function App(): React.ReactElement {
+ const [data, setData] = React.useState | null>(null)
+
+ React.useEffect(() => {
+ let cancelled = false
+ async function load() {
+ if (!orderListPage.setup) return
+ const d = (await orderListPage.setup({ query: {}, params: {} })) as Record | undefined
+ if (!cancelled) setData(d ?? {})
+ }
+ void load()
+ return () => {
+ cancelled = true
+ }
+ }, [])
+
+ return (
+
+
+ vibe-registry playground
+ import 即注册 · 页面只管业务 · 预览即真实
+
+
+
+ 真实渲染:订单列表页(layout: admin)
+ {data ? (
+
+ ) : (
+ setup 加载中…
+ )}
+
+
+
+
+ )
+}
+
+createRoot(document.getElementById('root')!).render()
diff --git a/examples/playground/src/pages.ts b/examples/playground/src/pages.ts
new file mode 100644
index 0000000..c7eac34
--- /dev/null
+++ b/examples/playground/src/pages.ts
@@ -0,0 +1,36 @@
+/**
+ * playground 页面声明 —— 验证"用户告诉 agent 用 admin 布局,页面只管业务"
+ */
+import { definePage } from 'vibe-registry'
+import './registry.ts' // 集中注册(副作用)
+
+export const orderListPage = definePage({
+ layout: 'admin',
+ title: '订单列表',
+ blocks: [
+ { slot: 'sidebar', widget: 'nav-menu', props: { items: [{ label: '订单', active: true }, { label: '商品' }, { label: '客户' }] } },
+ { slot: 'header', widget: 'page-header', props: { title: '订单管理', subtitle: '近 30 天全部订单' } },
+ {
+ slot: 'content',
+ widget: 'data-table',
+ props: {
+ columns: [
+ { key: 'id', title: '订单号' },
+ { key: 'customer', title: '客户' },
+ { key: 'amount', title: '金额' },
+ { key: 'status', title: '状态' },
+ ],
+ },
+ bind: { rows: 'orders' },
+ },
+ ],
+ setup: async () => {
+ return {
+ orders: [
+ { id: 'A1001', customer: '张三', amount: '¥ 1,299', status: '已支付' },
+ { id: 'A1002', customer: '李四', amount: '¥ 88', status: '待发货' },
+ { id: 'A1003', customer: '王五', amount: '¥ 4,560', status: '已完成' },
+ ],
+ }
+ },
+})
diff --git a/examples/playground/src/registry.ts b/examples/playground/src/registry.ts
new file mode 100644
index 0000000..2b8a156
--- /dev/null
+++ b/examples/playground/src/registry.ts
@@ -0,0 +1,44 @@
+/**
+ * playground 集中注册:widget 挂真实组件,layout 挂真实骨架
+ * 这就是"项目侧注册"的完整形态 —— 之后 AI 生成页面只用 id,不碰实现
+ */
+import { registerLayout, registerWidget } from 'vibe-registry'
+import { AdminLayout } from './layouts/admin.tsx'
+import { PageHeader, DataTable, NavMenu } from './widgets.tsx'
+
+// ── 布局注册(带真实渲染骨架)──────────────────────────────
+registerLayout({
+ kind: 'layout',
+ id: 'admin',
+ slots: ['sidebar', 'header', 'content', 'footer'],
+ description: '后台管理骨架',
+ render: AdminLayout,
+ preview: {
+ title: 'Admin · 后台管理',
+ demoBlocks: [
+ { slot: 'sidebar', widget: 'nav-menu', props: { items: [{ label: '订单', active: true }, { label: '商品' }] } },
+ { slot: 'header', widget: 'page-header', props: { title: '订单管理', subtitle: '全部订单' } },
+ { slot: 'content', widget: 'data-table' },
+ ],
+ },
+})
+
+// ── widget 注册(挂真实组件)──────────────────────────────
+registerWidget({
+ kind: 'widget',
+ id: 'page-header',
+ component: PageHeader,
+ description: '页头(标题 + 副标题)',
+})
+registerWidget({
+ kind: 'widget',
+ id: 'nav-menu',
+ component: NavMenu,
+ description: '侧栏导航菜单',
+})
+registerWidget({
+ kind: 'widget',
+ id: 'data-table',
+ component: DataTable,
+ description: '通用数据表格(列定义来自声明 props)',
+})
diff --git a/examples/playground/src/widgets.tsx b/examples/playground/src/widgets.tsx
new file mode 100644
index 0000000..93a0347
--- /dev/null
+++ b/examples/playground/src/widgets.tsx
@@ -0,0 +1,72 @@
+/**
+ * playground 业务 widget(真实 React 组件)
+ * 演示:注册表 widget → React 组件 → 渲染内核装配
+ */
+import React from 'react'
+
+/** 页头 */
+export function PageHeader({ title, subtitle }: { title?: string; subtitle?: string }): React.ReactElement {
+ return React.createElement(
+ 'header',
+ { style: { marginBottom: 16 } },
+ React.createElement('h1', { style: { margin: '0 0 4px', fontSize: 20 } }, title ?? '未命名'),
+ subtitle ? React.createElement('p', { style: { margin: 0, color: '#6b7280', fontSize: 13 } }, subtitle) : null,
+ )
+}
+
+/** 数据表格 */
+export function DataTable({
+ columns = [],
+ rows = [],
+}: {
+ columns?: Array<{ key: string; title: string }>
+ rows?: Array>
+}): React.ReactElement {
+ return React.createElement(
+ 'table',
+ { style: { borderCollapse: 'collapse', width: '100%', fontSize: 13 } },
+ React.createElement(
+ 'thead',
+ {},
+ React.createElement(
+ 'tr',
+ {},
+ ...(columns as Array<{ key: string; title: string }>).map((c) =>
+ React.createElement(
+ 'th',
+ { key: c.key, style: { textAlign: 'left', padding: '6px 8px', borderBottom: '1px solid #d1d5db' } },
+ c.title,
+ ),
+ ),
+ ),
+ ),
+ React.createElement(
+ 'tbody',
+ {},
+ ...(rows as Array>).map((r, i) =>
+ React.createElement(
+ 'tr',
+ { key: i },
+ ...(columns as Array<{ key: string; title: string }>).map((c) =>
+ React.createElement('td', { key: c.key, style: { padding: '6px 8px', borderBottom: '1px solid #f3f4f6' } }, String(r[c.key] ?? '')),
+ ),
+ ),
+ ),
+ ),
+ )
+}
+
+/** 导航菜单 */
+export function NavMenu({ items = [] }: { items?: Array<{ label: string; active?: boolean }> }): React.ReactElement {
+ return React.createElement(
+ 'ul',
+ { style: { listStyle: 'none', margin: 0, padding: 0 } },
+ ...(items as Array<{ label: string; active?: boolean }>).map((it, i) =>
+ React.createElement(
+ 'li',
+ { key: i, style: { padding: '6px 8px', borderRadius: 6, marginBottom: 2, background: it.active ? '#e0e7ff' : 'transparent' } },
+ it.label,
+ ),
+ ),
+ )
+}
diff --git a/examples/playground/tsconfig.json b/examples/playground/tsconfig.json
new file mode 100644
index 0000000..a8d1be1
--- /dev/null
+++ b/examples/playground/tsconfig.json
@@ -0,0 +1,17 @@
+{
+ "compilerOptions": {
+ "target": "ES2022",
+ "module": "ESNext",
+ "moduleResolution": "Bundler",
+ "lib": ["ES2022", "DOM", "DOM.Iterable"],
+ "jsx": "react-jsx",
+ "allowImportingTsExtensions": true,
+ "strict": true,
+ "noEmit": true,
+ "esModuleInterop": true,
+ "skipLibCheck": true,
+ "forceConsistentCasingInFileNames": true,
+ "types": ["vite/client"]
+ },
+ "include": ["src", "vite.config.ts"]
+}
diff --git a/examples/playground/vite.config.ts b/examples/playground/vite.config.ts
new file mode 100644
index 0000000..a366ec8
--- /dev/null
+++ b/examples/playground/vite.config.ts
@@ -0,0 +1,7 @@
+import { defineConfig } from 'vite'
+import react from '@vitejs/plugin-react'
+
+export default defineConfig({
+ plugins: [react()],
+ server: { port: 5183, open: false },
+})
diff --git a/package.json b/package.json
index 6058ee8..349fbcf 100644
--- a/package.json
+++ b/package.json
@@ -6,14 +6,20 @@
"description": "万物皆注册 · 面向 AI 前端的注册式页面框架(M1 概念验证)",
"main": "./src/index.ts",
"exports": {
- ".": "./src/index.ts"
+ ".": "./src/index.ts",
+ "./render": "./src/render.ts"
},
"scripts": {
"typecheck": "tsc --noEmit",
"vr": "node --experimental-strip-types cli/vr.ts"
},
+ "peerDependencies": {
+ "react": ">=18"
+ },
"devDependencies": {
"@types/node": "^22.0.0",
+ "@types/react": "^18.3.0",
+ "react": "^18.3.0",
"typescript": "^5.8.0"
}
}
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index dd0eadd..4442185 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -11,10 +11,44 @@ importers:
'@types/node':
specifier: ^22.0.0
version: 22.20.1
+ '@types/react':
+ specifier: ^18.3.0
+ version: 18.3.31
+ react:
+ specifier: ^18.3.0
+ version: 18.3.1
typescript:
specifier: ^5.8.0
version: 5.9.3
+ examples/playground:
+ dependencies:
+ react:
+ specifier: ^18.3.0
+ version: 18.3.1
+ react-dom:
+ specifier: ^18.3.0
+ version: 18.3.1(react@18.3.1)
+ vibe-registry:
+ specifier: workspace:*
+ version: link:../..
+ devDependencies:
+ '@types/react':
+ specifier: ^18.3.0
+ version: 18.3.31
+ '@types/react-dom':
+ specifier: ^18.3.0
+ version: 18.3.7(@types/react@18.3.31)
+ '@vitejs/plugin-react':
+ specifier: ^4.3.0
+ version: 4.7.0(vite@6.4.3(@types/node@22.20.1))
+ typescript:
+ specifier: ^5.8.0
+ version: 5.9.3
+ vite:
+ specifier: ^6.0.0
+ version: 6.4.3(@types/node@22.20.1)
+
examples/qa-orchestrator:
dependencies:
vibe-registry:
@@ -30,9 +64,578 @@ importers:
packages:
+ '@babel/code-frame@7.29.7':
+ resolution: {integrity: sha512-Aup7aUOfpbAUg2ROOJN6Iw5f9DMBlzu0mIkm/malLQFN/YQgO48wCj0Kxa3sEHJvPVFg7siR+qRInwXd2qhQKw==}
+ engines: {node: '>=6.9.0'}
+
+ '@babel/compat-data@7.29.7':
+ resolution: {integrity: sha512-locTkQyKvwIEgBzVrn8693ebc97F2U8ZHjbXwDXJ5Fn2TCpNwTlKcaKLkdHop5c/icOFE7qt7Q9JC5hnKNa6Gg==}
+ engines: {node: '>=6.9.0'}
+
+ '@babel/core@7.29.7':
+ resolution: {integrity: sha512-RgHBCvtjbOK2gXSNBNIkNoEc9qoVEtau3hj8gEqKQuL3HZAibKarWFEI3Lfm6EYKkLalOh8eSrj9b+ch9H/VBA==}
+ engines: {node: '>=6.9.0'}
+
+ '@babel/generator@7.29.8':
+ resolution: {integrity: sha512-gZbepsdh3WDtgZKWL+vTPh71LSBrm/Y4/QDZBVCcYfmeTEEuoOYwlSy+G1StfJg+/Zy550u/3TATbm7qDbbMtg==}
+ engines: {node: '>=6.9.0'}
+
+ '@babel/helper-compilation-targets@7.29.7':
+ resolution: {integrity: sha512-wem6WaBj4NaVYVdNhLPPVacES6ZJ+KBBfSkTMD3YZxbP3rm3Di85tJU5ljaUNhaOynt+Aj0xruhYuzQBt8n71g==}
+ engines: {node: '>=6.9.0'}
+
+ '@babel/helper-globals@7.29.7':
+ resolution: {integrity: sha512-3nQVUAtvkKH9zahfWgw96Jc/uFOmjACE1kQz82E2lqWmHBgjzbNlsC22nuQTfahmWeQtTq5nQ/4Nnd2A1wj4zA==}
+ engines: {node: '>=6.9.0'}
+
+ '@babel/helper-module-imports@7.29.7':
+ resolution: {integrity: sha512-ejHwrQQYcm9xnTivShn2IDOlIzInN34AXskvq9QicvCtEzq1Vzclu/tKF8Jq1Cg8JG2GL6/EmjgsCT7lXepE3g==}
+ engines: {node: '>=6.9.0'}
+
+ '@babel/helper-module-transforms@7.29.7':
+ resolution: {integrity: sha512-UPUVSyXbOh627KiCIGQSgwWzGeBKLkaJ9PJEdrngIwMSzxLR4jS4+f1f1jb7VzBbg8nFLaYotvVPFCTqdrmTAg==}
+ engines: {node: '>=6.9.0'}
+ peerDependencies:
+ '@babel/core': ^7.0.0
+
+ '@babel/helper-plugin-utils@7.29.7':
+ resolution: {integrity: sha512-G7sHYigPY17oO5SYWnfD/0MTBwVR781S/JI643e/JhUYgVgWE/61SoW3NH9KWUKyKq5LVh3npif99Wkt6j86Jw==}
+ engines: {node: '>=6.9.0'}
+
+ '@babel/helper-string-parser@7.29.7':
+ resolution: {integrity: sha512-Pb5ijPrZ89GDH8223L4UP8i6QApWxs04RbPQJTeWDV0/keR2E36MeKnyr6LYmUUvqRRI+Iv87SuF1W6ErINzYw==}
+ engines: {node: '>=6.9.0'}
+
+ '@babel/helper-validator-identifier@7.29.7':
+ resolution: {integrity: sha512-qehxGkRj55h/ff8EMaJ+cYhyaKlHIxqYDn682wQD7RNp9UujOQsHog2uS0r2vzr4pW+sXf90NeeayjcNaX3fFg==}
+ engines: {node: '>=6.9.0'}
+
+ '@babel/helper-validator-option@7.29.7':
+ resolution: {integrity: sha512-N9ZErrD+yW5geCDtBqnOoxmR8+tNKiGuxKlDpuJxfsqpa2dFcexaziGAE/qoHLiDDreVNMupxGmSoNlyvsA3gw==}
+ engines: {node: '>=6.9.0'}
+
+ '@babel/helpers@7.29.7':
+ resolution: {integrity: sha512-1k2lAGRMfHTcwuNYcCNUmaUffmQv8KWMfh2iJUUeRlwlwH4FdNG7mfPI10NPfLHJFThE4Tyr4mv7kTNZOiPuBg==}
+ engines: {node: '>=6.9.0'}
+
+ '@babel/parser@7.29.8':
+ resolution: {integrity: sha512-E8lTAYNB1KW+FH+VGJuZM1ioAx2E6oVlvQFRrf5P8ZZmsiJXYAD9vTFV7yyEURNzgh1dFqMZuO6tUwcARbqFCA==}
+ engines: {node: '>=6.0.0'}
+ hasBin: true
+
+ '@babel/plugin-transform-react-jsx-self@7.29.7':
+ resolution: {integrity: sha512-TL0hMc9xzy86VD31nUiwzd5otRAcyEPcsegCxolO0PvcXuH1v0kECe/UIznYFihpkvU5wg/jk4v0TTEFfm53fw==}
+ engines: {node: '>=6.9.0'}
+ peerDependencies:
+ '@babel/core': ^7.0.0-0
+
+ '@babel/plugin-transform-react-jsx-source@7.29.7':
+ resolution: {integrity: sha512-06IyK09H3wi4cGbhDBwp5gUGo0IKtnYa8tyTiephirPCK6fbobVGiXMMI5zLQ4aKEYP3wZ3ArU44o+8KMrSG/Q==}
+ engines: {node: '>=6.9.0'}
+ peerDependencies:
+ '@babel/core': ^7.0.0-0
+
+ '@babel/template@7.29.7':
+ resolution: {integrity: sha512-puq+Gf35oI24FeN11LkoUQFqv9uwNeWpxXZi/Ji3rRIoKAzKnxRaZ+Gkj0vKS9ZCiTESfng1N9LyOyXvo+m+Gg==}
+ engines: {node: '>=6.9.0'}
+
+ '@babel/traverse@7.29.8':
+ resolution: {integrity: sha512-I5z7H3bf/41ktsNVLtpN0wAa336HkqIHQ5BuPLEhTkt1jVSyZpeNKIzTgEWmlxjdg81R0IgUCcaE+Ok3NvrfZg==}
+ engines: {node: '>=6.9.0'}
+
+ '@babel/types@7.29.8':
+ resolution: {integrity: sha512-Vj1jF3cPfxg7OAfoI7QnVKLoILlm2JF9pnVHrX8qx7AHMiYWT+NDAA7jChlNgRS4WTLc/fD1lXLmPixluj+3Gg==}
+ engines: {node: '>=6.9.0'}
+
+ '@esbuild/aix-ppc64@0.25.12':
+ resolution: {integrity: sha512-Hhmwd6CInZ3dwpuGTF8fJG6yoWmsToE+vYgD4nytZVxcu1ulHpUQRAB1UJ8+N1Am3Mz4+xOByoQoSZf4D+CpkA==}
+ 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-arm@0.25.12':
+ resolution: {integrity: sha512-VJ+sKvNA/GE7Ccacc9Cha7bpS8nyzVv0jdVgwNDaR4gDMC/2TTRc33Ip8qrNYUcpkOHUT5OZ0bUcNNVZQ9RLlg==}
+ 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/darwin-arm64@0.25.12':
+ resolution: {integrity: sha512-N3zl+lxHCifgIlcMUP5016ESkeQjLj/959RxxNYIthIg+CQHInujFuXeWbWMgnTo4cp5XVHqFPmpyu9J65C1Yg==}
+ 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/freebsd-arm64@0.25.12':
+ resolution: {integrity: sha512-gA0Bx759+7Jve03K1S0vkOu5Lg/85dou3EseOGUes8flVOGxbhDDh/iZaoek11Y8mtyKPGF3vP8XhnkDEAmzeg==}
+ 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/linux-arm64@0.25.12':
+ resolution: {integrity: sha512-8bwX7a8FghIgrupcxb4aUmYDLp8pX06rGh5HqDT7bB+8Rdells6mHvrFHHW2JAOPZUbnjUpKTLg6ECyzvas2AQ==}
+ 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-ia32@0.25.12':
+ resolution: {integrity: sha512-0y9KrdVnbMM2/vG8KfU0byhUN+EFCny9+8g202gYqSSVMonbsCfLjUO+rCci7pM0WBEtz+oK/PIwHkzxkyharA==}
+ 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-mips64el@0.25.12':
+ resolution: {integrity: sha512-iyRrM1Pzy9GFMDLsXn1iHUm18nhKnNMWscjmp4+hpafcZjrr2WbT//d20xaGljXDBYHqRcl8HnxbX6uaA/eGVw==}
+ 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-riscv64@0.25.12':
+ resolution: {integrity: sha512-Zr7KR4hgKUpWAwb1f3o5ygT04MzqVrGEGXGLnj15YQDJErYu/BGg+wmFlIDOdJp0PmB0lLvxFIOXZgFRrdjR0w==}
+ 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-x64@0.25.12':
+ resolution: {integrity: sha512-uqZMTLr/zR/ed4jIGnwSLkaHmPjOjJvnm6TVVitAa08SLS9Z0VM8wIRx7gWbJB5/J54YuIMInDquWyYvQLZkgw==}
+ 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-x64@0.25.12':
+ resolution: {integrity: sha512-Ld5pTlzPy3YwGec4OuHh1aCVCRvOXdH8DgRjfDy/oumVovmuSzWfnSJg+VtakB9Cm0gxNO9BzWkj6mtO1FMXkQ==}
+ 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-x64@0.25.12':
+ resolution: {integrity: sha512-MZyXUkZHjQxUvzK7rN8DJ3SRmrVrke8ZyRusHlP+kuwqTcfWLyqMOE3sScPPyeIXN/mDJIfGXvcMqCgYKekoQw==}
+ 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/sunos-x64@0.25.12':
+ resolution: {integrity: sha512-3wGSCDyuTHQUzt0nV7bocDy72r2lI33QL3gkDNGkod22EsYl04sMf0qLb8luNKTOmgF/eDEDP5BFNwoBKH441w==}
+ 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-ia32@0.25.12':
+ resolution: {integrity: sha512-HkqnmmBoCbCwxUKKNPBixiWDGCpQGVsrQfJoVGYLPT41XWF8lHuE5N6WhVia2n4o5QK5M4tYr21827fNhi4byQ==}
+ 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]
+
+ '@jridgewell/gen-mapping@0.3.13':
+ resolution: {integrity: sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==}
+
+ '@jridgewell/remapping@2.3.5':
+ resolution: {integrity: sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ==}
+
+ '@jridgewell/resolve-uri@3.1.2':
+ resolution: {integrity: sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==}
+ engines: {node: '>=6.0.0'}
+
+ '@jridgewell/sourcemap-codec@1.6.0':
+ resolution: {integrity: sha512-T7jf+5zgsZHwNJ4lvQ7/aezbyk0nNX+zJVWpmHA7VYsEx7a7qr5Rg5IbtJFqkgze5Y2sruq1RUY8Q837Od7iFw==}
+
+ '@jridgewell/trace-mapping@0.3.31':
+ resolution: {integrity: sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==}
+
+ '@napi-rs/lzma-linux-x64-gnu@1.5.1':
+ resolution: {integrity: sha512-oTXEIha4SsuXdTA4Iyskj0kpdx2yVXdhd75c2v3xGrHFfVMsbhTPZU/nMPL4sWKo4pBHm3aucLaqGlF696dTyQ==}
+ engines: {node: ^22.20 || ^24.12 || >=25}
+ cpu: [x64]
+ os: [linux]
+ libc: [glibc]
+
+ '@rolldown/pluginutils@1.0.0-beta.27':
+ resolution: {integrity: sha512-+d0F4MKMCbeVUJwG96uQ4SgAznZNSq93I3V+9NHA4OpvqG8mRCpGdKmK8l/dl02h2CCDHwW2FqilnTyDcAnqjA==}
+
+ '@rollup/rollup-android-arm-eabi@4.63.1':
+ resolution: {integrity: sha512-UZ8sUxPTiHWYX9QNdJedb1kDZSpS1t/VPWBWGSgqHNi9w3Cu6IXvu2mzbhiTiPvtrqgTQJ+zqiAq2iPIPilpaQ==}
+ cpu: [arm]
+ os: [android]
+
+ '@rollup/rollup-android-arm64@4.63.1':
+ resolution: {integrity: sha512-cQ4nFQABN5cDvDpbvJ7bMStCpnaVxynZrRMfUJYgxcIk9Sh54FIO1vtfkg0B69REjER77ioZ/ov+eAApx/KmLQ==}
+ cpu: [arm64]
+ os: [android]
+
+ '@rollup/rollup-darwin-arm64@4.63.1':
+ resolution: {integrity: sha512-FQNqd1lRy/0QhDk3xeRIkSBiCpXCiDnZO3YLVdcDKN1UBiKToNftCzcXYNLshmPDUMlu2TdeS8tGcsU6f3YF1Q==}
+ cpu: [arm64]
+ os: [darwin]
+
+ '@rollup/rollup-darwin-x64@4.63.1':
+ resolution: {integrity: sha512-pvD16V939D3CloK0+qikpGaxiPrDUXTe7Y5cWOMkMSy7m1cawa8EGy/kXYi/G/cKAC4HDAbSnzCIk1WmsoOKXg==}
+ cpu: [x64]
+ os: [darwin]
+
+ '@rollup/rollup-freebsd-arm64@4.63.1':
+ resolution: {integrity: sha512-pcFGeL2345VwdTnJhA6zLbew+YgWB0qBG2+dMtXjCicf6+rm6kO6cOoh5VnTe0ZMrMRgRyuHmCJxZWrIdzYuOw==}
+ cpu: [arm64]
+ os: [freebsd]
+
+ '@rollup/rollup-freebsd-x64@4.63.1':
+ resolution: {integrity: sha512-mRJlqSRulVzcKq/LKA6ICSIc3K/l4fzlVn/gePn2nXIHy8seRi5z/eeRE0d/XMBxcMldiXtQTSpRj0tkkC3g8Q==}
+ cpu: [x64]
+ os: [freebsd]
+
+ '@rollup/rollup-linux-arm-gnueabihf@4.63.1':
+ resolution: {integrity: sha512-YDUNvVM85TI3g/1OpnqKP1h4NeW/j64DfWMf+G3M809xNk1bJSnpFp4sh83NpmVE5DXnkh8ULor4LTVZKoYLHw==}
+ cpu: [arm]
+ os: [linux]
+ libc: [glibc]
+
+ '@rollup/rollup-linux-arm-musleabihf@4.63.1':
+ resolution: {integrity: sha512-7Mcn71p9ZuQFAj+h+dhQXy/yeLePRS2yKRnmW1DijA9thKO5qap0GNOIQK4yQ6iP3SU0Mrb/yWo8h8vgRba8lw==}
+ cpu: [arm]
+ os: [linux]
+ libc: [musl]
+
+ '@rollup/rollup-linux-arm64-gnu@4.63.1':
+ resolution: {integrity: sha512-4YiLQTX6U4CSl0L9cluep9A9W6UmTfqBDc2/CH6wlu54pl4E7Jn3cOD8oxzvBDEGk/JMKgJ47C8g+radF7mwvg==}
+ cpu: [arm64]
+ os: [linux]
+ libc: [glibc]
+
+ '@rollup/rollup-linux-arm64-musl@4.63.1':
+ resolution: {integrity: sha512-2ra8F7w8OquwZN9z2/fKFnli69wa8PLwaVzRMIPGb13ByMJwC28Fbp8YcVGoUhlYMTt7j5j9bNgpysrN2UM+vw==}
+ cpu: [arm64]
+ os: [linux]
+ libc: [musl]
+
+ '@rollup/rollup-linux-loong64-gnu@4.63.1':
+ resolution: {integrity: sha512-Sy20ncyhjmBP0Ml+UvQbimjlk6VFgjW5uNP+qqwHB00mTE8Bl2C1TuHTlRwK2YoXeZbee5lP2XevBWVkAQAtSQ==}
+ cpu: [loong64]
+ os: [linux]
+ libc: [glibc]
+
+ '@rollup/rollup-linux-loong64-musl@4.63.1':
+ resolution: {integrity: sha512-noITLp8oNjYliPnGWmLyelIHwULGqbHloQHGw1rtxbWhTuWooRpnZarZQJ1y9EUC4szuCusCc+HEpUtxpIwYvA==}
+ cpu: [loong64]
+ os: [linux]
+ libc: [musl]
+
+ '@rollup/rollup-linux-ppc64-gnu@4.63.1':
+ resolution: {integrity: sha512-hlxxXd+F1mWiAcaFR7Sv9ZQT6m6UfI8+Vy/kFJzztq2pDMU/0wZ9sish0iszNZvsQDo8Gc0i5yuFEOz5dDf6fA==}
+ cpu: [ppc64]
+ os: [linux]
+ libc: [glibc]
+
+ '@rollup/rollup-linux-ppc64-musl@4.63.1':
+ resolution: {integrity: sha512-EF7OpqQTQ/BvGqLzUi4rEHuagCV9MugAUXSHemwPW5vxZ75RR+jxO/2j95Ph2dalMpFHSVECjRoioHZgA9zOYA==}
+ cpu: [ppc64]
+ os: [linux]
+ libc: [musl]
+
+ '@rollup/rollup-linux-riscv64-gnu@4.63.1':
+ resolution: {integrity: sha512-wQO3JesW9PRkwlabQ27y7sPfVOOTLRG73I4F2UYHG5PXun3J9U3y+b7ezVKSYbsvSKGQ1k1cq8Qlun4C9kLt3w==}
+ cpu: [riscv64]
+ os: [linux]
+ libc: [glibc]
+
+ '@rollup/rollup-linux-riscv64-musl@4.63.1':
+ resolution: {integrity: sha512-ouAGwhO6wHRXdnOVCOsB0tRFkA7nhNB2Nwax6oECXN0YiN8EYUTBAOudADOB1PI+yDL61TeNx/u7MVCzksNbkQ==}
+ cpu: [riscv64]
+ os: [linux]
+ libc: [musl]
+
+ '@rollup/rollup-linux-s390x-gnu@4.63.1':
+ resolution: {integrity: sha512-q2R38Sn+1J8RxhfJ+T54wSWmyKXWec+9jgDfqO2AtArEqHO5R2aeayp5H5OYLr5UYDVGsVaZPEFUooMhYCdz5A==}
+ cpu: [s390x]
+ os: [linux]
+ libc: [glibc]
+
+ '@rollup/rollup-linux-x64-gnu@4.63.1':
+ resolution: {integrity: sha512-gfI5T24WLLuFfSKw7Go/zDXjAAV0fny0swTaDv+WjK7vqcw4cRhFfdsyKL1n+ukI+ooBxn3bVQnyrn06WpI50w==}
+ cpu: [x64]
+ os: [linux]
+ libc: [glibc]
+
+ '@rollup/rollup-linux-x64-musl@4.63.1':
+ resolution: {integrity: sha512-4h6XqthmB4Hspji84wvgk+ElodTsGj+dbZqHJHHtKxj4mYq0ANSEEPX9ys3moJueqsRjwpaJYH7874Itwnj2ow==}
+ cpu: [x64]
+ os: [linux]
+ libc: [musl]
+
+ '@rollup/rollup-openbsd-x64@4.63.1':
+ resolution: {integrity: sha512-dlfCOa87o1VAYegLQ9EKilx2JCeRofiyPGhTCmqnuXZ6bMPiycO1rq1+sKoulAp7pGLIsTIw+1x5R+zgh5LhhA==}
+ cpu: [x64]
+ os: [openbsd]
+
+ '@rollup/rollup-openharmony-arm64@4.63.1':
+ resolution: {integrity: sha512-cjkLbOlfcm3QGhMM1J5zaZjsw1GggbN6rw9UTSSRrPrR1KkcXnN7Uq9rPw34xImQ9VOY9GN+6u2Zj80B9ptkcw==}
+ cpu: [arm64]
+ os: [openharmony]
+
+ '@rollup/rollup-win32-arm64-msvc@4.63.1':
+ resolution: {integrity: sha512-Li1KdUnWGE4N3e1F/B4RTB1ms+nG4WBgjByO46pkeBVX/2UBsY53xf5vK9WygVmnH3RwncIST7lkSdLSY6P9lg==}
+ cpu: [arm64]
+ os: [win32]
+
+ '@rollup/rollup-win32-ia32-msvc@4.63.1':
+ resolution: {integrity: sha512-t4ZYOSoLTgwhuFMrmTMLx/+i1DQVK7HYqMc6kY46EApwi8X0nIVphzdNoThU3xt6n+N5urG1/gxBdCaKDLavfg==}
+ cpu: [ia32]
+ os: [win32]
+
+ '@rollup/rollup-win32-x64-gnu@4.63.1':
+ resolution: {integrity: sha512-RgroPfMmKlD1RzSDxvwgcPiy2HNQKoYV7OmwIXDsk73uKW5t6B/V8KIy27SMv/FNXFo/oSBtWc9J0X7t91ezZg==}
+ cpu: [x64]
+ os: [win32]
+
+ '@rollup/rollup-win32-x64-msvc@4.63.1':
+ resolution: {integrity: sha512-at8QVep6S3h5Y6gSbdGU06bRY5WJkf6WUduM9YtvYMbYhB1MOFfUgc6kehitQXzOtMSaT70q7f9ydPhpqu821w==}
+ cpu: [x64]
+ os: [win32]
+
+ '@types/babel__core@7.20.5':
+ resolution: {integrity: sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==}
+
+ '@types/babel__generator@7.27.0':
+ resolution: {integrity: sha512-ufFd2Xi92OAVPYsy+P4n7/U7e68fex0+Ee8gSG9KX7eo084CWiQ4sdxktvdl0bOPupXtVJPY19zk6EwWqUQ8lg==}
+
+ '@types/babel__template@7.4.4':
+ resolution: {integrity: sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A==}
+
+ '@types/babel__traverse@7.28.0':
+ resolution: {integrity: sha512-8PvcXf70gTDZBgt9ptxJ8elBeBjcLOAcOtoO/mPJjtji1+CdGbHgm77om1GrsPxsiE+uXIpNSK64UYaIwQXd4Q==}
+
+ '@types/estree@1.0.9':
+ resolution: {integrity: sha512-GhdPgy1el4/ImP05X05Uw4cw2/M93BCUmnEvWZNStlCzEKME4Fkk+YpoA5OiHNQmoS7Cafb8Xa3Pya8m1Qrzeg==}
+
'@types/node@22.20.1':
resolution: {integrity: sha512-EANqOCF9QFyra+4pfxUcX9STKJpCLjMbObVzljIJomAWSnuSIEAvyzEU53GaajbXJEgdh0iEcPL+DGvpUd4k1Q==}
+ '@types/prop-types@15.7.15':
+ resolution: {integrity: sha512-F6bEyamV9jKGAFBEmlQnesRPGOQqS2+Uwi0Em15xenOxHaf2hv6L8YCVn3rPdPJOiJfPiCnLIRyvwVaqMY3MIw==}
+
+ '@types/react-dom@18.3.7':
+ resolution: {integrity: sha512-MEe3UeoENYVFXzoXEWsvcpg6ZvlrFNlOQ7EOsvhI3CfAXwzPfO8Qwuxd40nepsYKqyyVQnTdEfv68q91yLcKrQ==}
+ peerDependencies:
+ '@types/react': ^18.0.0
+
+ '@types/react@18.3.31':
+ resolution: {integrity: sha512-vfEqpXTvwT91yhmwdfouStN2hSKwTvyRs8qpLfADyrq/kxDw0hZM7Wk9Ug1FELj8hIby+S/+kQCSRFF32nv2Qw==}
+
+ '@vitejs/plugin-react@4.7.0':
+ resolution: {integrity: sha512-gUu9hwfWvvEDBBmgtAowQCojwZmJ5mcLn3aufeCsitijs3+f2NsrPtlAWIR6OPiqljl96GVCUbLe0HyqIpVaoA==}
+ engines: {node: ^14.18.0 || >=16.0.0}
+ peerDependencies:
+ vite: ^4.2.0 || ^5.0.0 || ^6.0.0 || ^7.0.0
+
+ baseline-browser-mapping@2.11.20:
+ resolution: {integrity: sha512-H0ulySigv6icDJ1F7SjtdCD6PrhTpdYCmP0CactWy1+ekh0AFd0o1Wn5T8b+hnTmdBx19u9yhL6wvCylXMY7zw==}
+ engines: {node: '>=6.0.0'}
+ hasBin: true
+
+ browserslist@4.28.8:
+ resolution: {integrity: sha512-V2NpofLblG64mfOtSgDhOJESZEGogzDMBv/q+W6oc4LXWP/q75eOXoOaaOu1EOadB9U4Bwx/e0yzbvwKH8zalA==}
+ engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7}
+ hasBin: true
+
+ caniuse-lite@1.0.30001810:
+ resolution: {integrity: sha512-TITQPUkaz+aVk5GL6NhOdwk1aEaNTSDPsGFWrTuhKGtjTF70jL/Oht2W4c6rXUe5fu7Ie19VIahAXHIIiWWNeg==}
+
+ convert-source-map@2.0.0:
+ resolution: {integrity: sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==}
+
+ csstype@3.2.3:
+ resolution: {integrity: sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==}
+
+ debug@4.4.3:
+ resolution: {integrity: sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==}
+ engines: {node: '>=6.0'}
+ peerDependencies:
+ supports-color: '*'
+ peerDependenciesMeta:
+ supports-color:
+ optional: true
+
+ electron-to-chromium@1.5.418:
+ resolution: {integrity: sha512-UzS26r3AEbG5wSoGVpJKqwHIU9zwQN7LHdVIThDrJpS0I5KdlXFMEb8543fhc9dVnIIAST6ar8rhwa00AL5MlA==}
+
+ esbuild@0.25.12:
+ resolution: {integrity: sha512-bbPBYYrtZbkt6Os6FiTLCTFxvq4tt3JKall1vRwshA3fdVztsLAatFaZobhkBC8/BrPetoa0oksYoKXoG4ryJg==}
+ engines: {node: '>=18'}
+ hasBin: true
+
+ escalade@3.2.0:
+ resolution: {integrity: sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==}
+ engines: {node: '>=6'}
+
+ fdir@6.5.0:
+ resolution: {integrity: sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==}
+ engines: {node: '>=12.0.0'}
+ peerDependencies:
+ picomatch: ^3 || ^4
+ peerDependenciesMeta:
+ picomatch:
+ optional: true
+
+ fsevents@2.3.3:
+ resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==}
+ engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0}
+ os: [darwin]
+
+ gensync@1.0.0-beta.2:
+ resolution: {integrity: sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==}
+ engines: {node: '>=6.9.0'}
+
+ js-tokens@4.0.0:
+ resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==}
+
+ jsesc@3.1.0:
+ resolution: {integrity: sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==}
+ engines: {node: '>=6'}
+ hasBin: true
+
+ json5@2.2.3:
+ resolution: {integrity: sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==}
+ engines: {node: '>=6'}
+ hasBin: true
+
+ loose-envify@1.4.0:
+ resolution: {integrity: sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==}
+ hasBin: true
+
+ lru-cache@5.1.1:
+ resolution: {integrity: sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==}
+
+ ms@2.1.3:
+ resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==}
+
+ nanoid@3.3.18:
+ resolution: {integrity: sha512-DTg4MJbGMWkfi6VZFdNt2/caMbQy4Ou+Op/hJQvGEWcnVfoA1QA+xzRKAzw9jD6+GVOOeYr/mIcuDSdug6F6+w==}
+ engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1}
+ hasBin: true
+
+ node-releases@2.0.54:
+ resolution: {integrity: sha512-YHs7BmmcsdAI5Ozuf8JZo6PT0mv2GIWC9vMfvUC3dp65M8hn7Ux8CPL+2oBI7juNuj9d0ndhTcznq2ODBps9cQ==}
+ engines: {node: '>=18'}
+
+ picocolors@1.1.1:
+ resolution: {integrity: sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==}
+
+ picomatch@4.0.7:
+ resolution: {integrity: sha512-qcJu88Q2IWqJsDD529JKMdwGm/dvInW4HvQnRwiH9JtihJvzGOscDtHE3x1pBKeUOTysQ8kVmLnJ2kJu7yhcGA==}
+ engines: {node: '>=12'}
+
+ postcss@8.5.26:
+ resolution: {integrity: sha512-u82N74LFzG8ca+dD8puPnplTXoGH4fTPpVGuIbt36G3qvNlkvfD0lEAZSxaly3KX8TS/L1A1gsCEmvKmBcVbkQ==}
+ engines: {node: ^10 || ^12 || >=14}
+
+ react-dom@18.3.1:
+ resolution: {integrity: sha512-5m4nQKp+rZRb09LNH59GM4BxTh9251/ylbKIbpe7TpGxfJ+9kv6BLkLBXIjjspbgbnIBNqlI23tRnTWT0snUIw==}
+ peerDependencies:
+ react: ^18.3.1
+
+ react-refresh@0.17.0:
+ resolution: {integrity: sha512-z6F7K9bV85EfseRCp2bzrpyQ0Gkw1uLoCel9XBVWPg/TjRj94SkJzUTGfOa4bs7iJvBWtQG0Wq7wnI0syw3EBQ==}
+ engines: {node: '>=0.10.0'}
+
+ react@18.3.1:
+ resolution: {integrity: sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==}
+ engines: {node: '>=0.10.0'}
+
+ rollup@4.63.1:
+ resolution: {integrity: sha512-3Df9jsstwhccuEfmAMi9l8XUh/GOkVObmFTU7CCVBysEbcOZLl84jCtaAZMcPiMz2EGKsATzQcU+Xr3n/wU6cg==}
+ engines: {node: '>=18.0.0', npm: '>=8.0.0'}
+ hasBin: true
+
+ scheduler@0.23.2:
+ resolution: {integrity: sha512-UOShsPwz7NrMUqhR6t0hWjFduvOzbtv7toDH1/hIrfRNIDBnnBWd0CwJTGvTpngVlmwGCdP9/Zl/tVrDqcuYzQ==}
+
+ semver@6.3.1:
+ resolution: {integrity: sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==}
+ hasBin: true
+
+ source-map-js@1.2.1:
+ resolution: {integrity: sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==}
+ engines: {node: '>=0.10.0'}
+
+ tinyglobby@0.2.17:
+ resolution: {integrity: sha512-wXR/dYpcqKmfWpEdZjiKJOwCNFndD0DMnrW/cYjVGttEkBfVgcLFHoNrlj47mjOVic9yyNu65alsgF4NQyTa2g==}
+ engines: {node: '>=12.0.0'}
+
typescript@5.9.3:
resolution: {integrity: sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==}
engines: {node: '>=14.17'}
@@ -41,12 +644,565 @@ packages:
undici-types@6.21.0:
resolution: {integrity: sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==}
+ update-browserslist-db@1.3.2:
+ resolution: {integrity: sha512-UQ+MSxlhRm1bzjhU+DcuXfjFO1FzNtqhK5+9Yvlp90ItDLk5vT932A0rFu619nf7RVS+Y/VeaUW1jaRDqZ8VJw==}
+ hasBin: true
+ peerDependencies:
+ browserslist: '>= 4.21.0'
+
+ vite@6.4.3:
+ resolution: {integrity: sha512-NTKlcQjlAK7MlQoyb6LgaqHc8sso/pVyUJYWMws3jg21uTJw/LddqIFPcPqP6PzpgbIcZyKI85sFE4HBrQDA8A==}
+ engines: {node: ^18.0.0 || ^20.0.0 || >=22.0.0}
+ hasBin: true
+ peerDependencies:
+ '@types/node': ^18.0.0 || ^20.0.0 || >=22.0.0
+ jiti: '>=1.21.0'
+ less: '*'
+ lightningcss: ^1.21.0
+ sass: '*'
+ sass-embedded: '*'
+ stylus: '*'
+ sugarss: '*'
+ terser: ^5.16.0
+ tsx: ^4.8.1
+ yaml: ^2.4.2
+ peerDependenciesMeta:
+ '@types/node':
+ optional: true
+ jiti:
+ optional: true
+ less:
+ optional: true
+ lightningcss:
+ optional: true
+ sass:
+ optional: true
+ sass-embedded:
+ optional: true
+ stylus:
+ optional: true
+ sugarss:
+ optional: true
+ terser:
+ optional: true
+ tsx:
+ optional: true
+ yaml:
+ optional: true
+
+ yallist@3.1.1:
+ resolution: {integrity: sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==}
+
snapshots:
+ '@babel/code-frame@7.29.7':
+ dependencies:
+ '@babel/helper-validator-identifier': 7.29.7
+ js-tokens: 4.0.0
+ picocolors: 1.1.1
+
+ '@babel/compat-data@7.29.7': {}
+
+ '@babel/core@7.29.7':
+ dependencies:
+ '@babel/code-frame': 7.29.7
+ '@babel/generator': 7.29.8
+ '@babel/helper-compilation-targets': 7.29.7
+ '@babel/helper-module-transforms': 7.29.7(@babel/core@7.29.7)
+ '@babel/helpers': 7.29.7
+ '@babel/parser': 7.29.8
+ '@babel/template': 7.29.7
+ '@babel/traverse': 7.29.8
+ '@babel/types': 7.29.8
+ '@jridgewell/remapping': 2.3.5
+ convert-source-map: 2.0.0
+ debug: 4.4.3
+ gensync: 1.0.0-beta.2
+ json5: 2.2.3
+ semver: 6.3.1
+ transitivePeerDependencies:
+ - supports-color
+
+ '@babel/generator@7.29.8':
+ dependencies:
+ '@babel/parser': 7.29.8
+ '@babel/types': 7.29.8
+ '@jridgewell/gen-mapping': 0.3.13
+ '@jridgewell/trace-mapping': 0.3.31
+ jsesc: 3.1.0
+
+ '@babel/helper-compilation-targets@7.29.7':
+ dependencies:
+ '@babel/compat-data': 7.29.7
+ '@babel/helper-validator-option': 7.29.7
+ browserslist: 4.28.8
+ lru-cache: 5.1.1
+ semver: 6.3.1
+
+ '@babel/helper-globals@7.29.7': {}
+
+ '@babel/helper-module-imports@7.29.7':
+ dependencies:
+ '@babel/traverse': 7.29.8
+ '@babel/types': 7.29.8
+ transitivePeerDependencies:
+ - supports-color
+
+ '@babel/helper-module-transforms@7.29.7(@babel/core@7.29.7)':
+ dependencies:
+ '@babel/core': 7.29.7
+ '@babel/helper-module-imports': 7.29.7
+ '@babel/helper-validator-identifier': 7.29.7
+ '@babel/traverse': 7.29.8
+ transitivePeerDependencies:
+ - supports-color
+
+ '@babel/helper-plugin-utils@7.29.7': {}
+
+ '@babel/helper-string-parser@7.29.7': {}
+
+ '@babel/helper-validator-identifier@7.29.7': {}
+
+ '@babel/helper-validator-option@7.29.7': {}
+
+ '@babel/helpers@7.29.7':
+ dependencies:
+ '@babel/template': 7.29.7
+ '@babel/types': 7.29.8
+
+ '@babel/parser@7.29.8':
+ dependencies:
+ '@babel/types': 7.29.8
+
+ '@babel/plugin-transform-react-jsx-self@7.29.7(@babel/core@7.29.7)':
+ dependencies:
+ '@babel/core': 7.29.7
+ '@babel/helper-plugin-utils': 7.29.7
+
+ '@babel/plugin-transform-react-jsx-source@7.29.7(@babel/core@7.29.7)':
+ dependencies:
+ '@babel/core': 7.29.7
+ '@babel/helper-plugin-utils': 7.29.7
+
+ '@babel/template@7.29.7':
+ dependencies:
+ '@babel/code-frame': 7.29.7
+ '@babel/parser': 7.29.8
+ '@babel/types': 7.29.8
+
+ '@babel/traverse@7.29.8':
+ dependencies:
+ '@babel/code-frame': 7.29.7
+ '@babel/generator': 7.29.8
+ '@babel/helper-globals': 7.29.7
+ '@babel/parser': 7.29.8
+ '@babel/template': 7.29.7
+ '@babel/types': 7.29.8
+ debug: 4.4.3
+ transitivePeerDependencies:
+ - supports-color
+
+ '@babel/types@7.29.8':
+ dependencies:
+ '@babel/helper-string-parser': 7.29.7
+ '@babel/helper-validator-identifier': 7.29.7
+
+ '@esbuild/aix-ppc64@0.25.12':
+ optional: true
+
+ '@esbuild/android-arm64@0.25.12':
+ optional: true
+
+ '@esbuild/android-arm@0.25.12':
+ optional: true
+
+ '@esbuild/android-x64@0.25.12':
+ optional: true
+
+ '@esbuild/darwin-arm64@0.25.12':
+ optional: true
+
+ '@esbuild/darwin-x64@0.25.12':
+ optional: true
+
+ '@esbuild/freebsd-arm64@0.25.12':
+ optional: true
+
+ '@esbuild/freebsd-x64@0.25.12':
+ optional: true
+
+ '@esbuild/linux-arm64@0.25.12':
+ optional: true
+
+ '@esbuild/linux-arm@0.25.12':
+ optional: true
+
+ '@esbuild/linux-ia32@0.25.12':
+ optional: true
+
+ '@esbuild/linux-loong64@0.25.12':
+ optional: true
+
+ '@esbuild/linux-mips64el@0.25.12':
+ optional: true
+
+ '@esbuild/linux-ppc64@0.25.12':
+ optional: true
+
+ '@esbuild/linux-riscv64@0.25.12':
+ optional: true
+
+ '@esbuild/linux-s390x@0.25.12':
+ optional: true
+
+ '@esbuild/linux-x64@0.25.12':
+ optional: true
+
+ '@esbuild/netbsd-arm64@0.25.12':
+ optional: true
+
+ '@esbuild/netbsd-x64@0.25.12':
+ optional: true
+
+ '@esbuild/openbsd-arm64@0.25.12':
+ optional: true
+
+ '@esbuild/openbsd-x64@0.25.12':
+ optional: true
+
+ '@esbuild/openharmony-arm64@0.25.12':
+ optional: true
+
+ '@esbuild/sunos-x64@0.25.12':
+ optional: true
+
+ '@esbuild/win32-arm64@0.25.12':
+ optional: true
+
+ '@esbuild/win32-ia32@0.25.12':
+ optional: true
+
+ '@esbuild/win32-x64@0.25.12':
+ optional: true
+
+ '@jridgewell/gen-mapping@0.3.13':
+ dependencies:
+ '@jridgewell/sourcemap-codec': 1.6.0
+ '@jridgewell/trace-mapping': 0.3.31
+
+ '@jridgewell/remapping@2.3.5':
+ dependencies:
+ '@jridgewell/gen-mapping': 0.3.13
+ '@jridgewell/trace-mapping': 0.3.31
+
+ '@jridgewell/resolve-uri@3.1.2': {}
+
+ '@jridgewell/sourcemap-codec@1.6.0': {}
+
+ '@jridgewell/trace-mapping@0.3.31':
+ dependencies:
+ '@jridgewell/resolve-uri': 3.1.2
+ '@jridgewell/sourcemap-codec': 1.6.0
+
+ '@napi-rs/lzma-linux-x64-gnu@1.5.1':
+ optional: true
+
+ '@rolldown/pluginutils@1.0.0-beta.27': {}
+
+ '@rollup/rollup-android-arm-eabi@4.63.1':
+ optional: true
+
+ '@rollup/rollup-android-arm64@4.63.1':
+ optional: true
+
+ '@rollup/rollup-darwin-arm64@4.63.1':
+ optional: true
+
+ '@rollup/rollup-darwin-x64@4.63.1':
+ optional: true
+
+ '@rollup/rollup-freebsd-arm64@4.63.1':
+ optional: true
+
+ '@rollup/rollup-freebsd-x64@4.63.1':
+ optional: true
+
+ '@rollup/rollup-linux-arm-gnueabihf@4.63.1':
+ optional: true
+
+ '@rollup/rollup-linux-arm-musleabihf@4.63.1':
+ optional: true
+
+ '@rollup/rollup-linux-arm64-gnu@4.63.1':
+ optional: true
+
+ '@rollup/rollup-linux-arm64-musl@4.63.1':
+ optional: true
+
+ '@rollup/rollup-linux-loong64-gnu@4.63.1':
+ optional: true
+
+ '@rollup/rollup-linux-loong64-musl@4.63.1':
+ optional: true
+
+ '@rollup/rollup-linux-ppc64-gnu@4.63.1':
+ optional: true
+
+ '@rollup/rollup-linux-ppc64-musl@4.63.1':
+ optional: true
+
+ '@rollup/rollup-linux-riscv64-gnu@4.63.1':
+ optional: true
+
+ '@rollup/rollup-linux-riscv64-musl@4.63.1':
+ optional: true
+
+ '@rollup/rollup-linux-s390x-gnu@4.63.1':
+ optional: true
+
+ '@rollup/rollup-linux-x64-gnu@4.63.1':
+ optional: true
+
+ '@rollup/rollup-linux-x64-musl@4.63.1':
+ optional: true
+
+ '@rollup/rollup-openbsd-x64@4.63.1':
+ optional: true
+
+ '@rollup/rollup-openharmony-arm64@4.63.1':
+ optional: true
+
+ '@rollup/rollup-win32-arm64-msvc@4.63.1':
+ optional: true
+
+ '@rollup/rollup-win32-ia32-msvc@4.63.1':
+ optional: true
+
+ '@rollup/rollup-win32-x64-gnu@4.63.1':
+ optional: true
+
+ '@rollup/rollup-win32-x64-msvc@4.63.1':
+ optional: true
+
+ '@types/babel__core@7.20.5':
+ dependencies:
+ '@babel/parser': 7.29.8
+ '@babel/types': 7.29.8
+ '@types/babel__generator': 7.27.0
+ '@types/babel__template': 7.4.4
+ '@types/babel__traverse': 7.28.0
+
+ '@types/babel__generator@7.27.0':
+ dependencies:
+ '@babel/types': 7.29.8
+
+ '@types/babel__template@7.4.4':
+ dependencies:
+ '@babel/parser': 7.29.8
+ '@babel/types': 7.29.8
+
+ '@types/babel__traverse@7.28.0':
+ dependencies:
+ '@babel/types': 7.29.8
+
+ '@types/estree@1.0.9': {}
+
'@types/node@22.20.1':
dependencies:
undici-types: 6.21.0
+ '@types/prop-types@15.7.15': {}
+
+ '@types/react-dom@18.3.7(@types/react@18.3.31)':
+ dependencies:
+ '@types/react': 18.3.31
+
+ '@types/react@18.3.31':
+ dependencies:
+ '@types/prop-types': 15.7.15
+ csstype: 3.2.3
+
+ '@vitejs/plugin-react@4.7.0(vite@6.4.3(@types/node@22.20.1))':
+ dependencies:
+ '@babel/core': 7.29.7
+ '@babel/plugin-transform-react-jsx-self': 7.29.7(@babel/core@7.29.7)
+ '@babel/plugin-transform-react-jsx-source': 7.29.7(@babel/core@7.29.7)
+ '@rolldown/pluginutils': 1.0.0-beta.27
+ '@types/babel__core': 7.20.5
+ react-refresh: 0.17.0
+ vite: 6.4.3(@types/node@22.20.1)
+ transitivePeerDependencies:
+ - supports-color
+
+ baseline-browser-mapping@2.11.20: {}
+
+ browserslist@4.28.8:
+ dependencies:
+ baseline-browser-mapping: 2.11.20
+ caniuse-lite: 1.0.30001810
+ electron-to-chromium: 1.5.418
+ node-releases: 2.0.54
+ update-browserslist-db: 1.3.2(browserslist@4.28.8)
+
+ caniuse-lite@1.0.30001810: {}
+
+ convert-source-map@2.0.0: {}
+
+ csstype@3.2.3: {}
+
+ debug@4.4.3:
+ dependencies:
+ ms: 2.1.3
+
+ electron-to-chromium@1.5.418: {}
+
+ 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
+
+ escalade@3.2.0: {}
+
+ fdir@6.5.0(picomatch@4.0.7):
+ optionalDependencies:
+ picomatch: 4.0.7
+
+ fsevents@2.3.3:
+ optional: true
+
+ gensync@1.0.0-beta.2: {}
+
+ js-tokens@4.0.0: {}
+
+ jsesc@3.1.0: {}
+
+ json5@2.2.3: {}
+
+ loose-envify@1.4.0:
+ dependencies:
+ js-tokens: 4.0.0
+
+ lru-cache@5.1.1:
+ dependencies:
+ yallist: 3.1.1
+
+ ms@2.1.3: {}
+
+ nanoid@3.3.18: {}
+
+ node-releases@2.0.54: {}
+
+ picocolors@1.1.1: {}
+
+ picomatch@4.0.7: {}
+
+ postcss@8.5.26:
+ dependencies:
+ nanoid: 3.3.18
+ picocolors: 1.1.1
+ source-map-js: 1.2.1
+
+ react-dom@18.3.1(react@18.3.1):
+ dependencies:
+ loose-envify: 1.4.0
+ react: 18.3.1
+ scheduler: 0.23.2
+
+ react-refresh@0.17.0: {}
+
+ react@18.3.1:
+ dependencies:
+ loose-envify: 1.4.0
+
+ rollup@4.63.1:
+ dependencies:
+ '@types/estree': 1.0.9
+ optionalDependencies:
+ '@napi-rs/lzma-linux-x64-gnu': 1.5.1
+ '@rollup/rollup-android-arm-eabi': 4.63.1
+ '@rollup/rollup-android-arm64': 4.63.1
+ '@rollup/rollup-darwin-arm64': 4.63.1
+ '@rollup/rollup-darwin-x64': 4.63.1
+ '@rollup/rollup-freebsd-arm64': 4.63.1
+ '@rollup/rollup-freebsd-x64': 4.63.1
+ '@rollup/rollup-linux-arm-gnueabihf': 4.63.1
+ '@rollup/rollup-linux-arm-musleabihf': 4.63.1
+ '@rollup/rollup-linux-arm64-gnu': 4.63.1
+ '@rollup/rollup-linux-arm64-musl': 4.63.1
+ '@rollup/rollup-linux-loong64-gnu': 4.63.1
+ '@rollup/rollup-linux-loong64-musl': 4.63.1
+ '@rollup/rollup-linux-ppc64-gnu': 4.63.1
+ '@rollup/rollup-linux-ppc64-musl': 4.63.1
+ '@rollup/rollup-linux-riscv64-gnu': 4.63.1
+ '@rollup/rollup-linux-riscv64-musl': 4.63.1
+ '@rollup/rollup-linux-s390x-gnu': 4.63.1
+ '@rollup/rollup-linux-x64-gnu': 4.63.1
+ '@rollup/rollup-linux-x64-musl': 4.63.1
+ '@rollup/rollup-openbsd-x64': 4.63.1
+ '@rollup/rollup-openharmony-arm64': 4.63.1
+ '@rollup/rollup-win32-arm64-msvc': 4.63.1
+ '@rollup/rollup-win32-ia32-msvc': 4.63.1
+ '@rollup/rollup-win32-x64-gnu': 4.63.1
+ '@rollup/rollup-win32-x64-msvc': 4.63.1
+ fsevents: 2.3.3
+
+ scheduler@0.23.2:
+ dependencies:
+ loose-envify: 1.4.0
+
+ semver@6.3.1: {}
+
+ source-map-js@1.2.1: {}
+
+ tinyglobby@0.2.17:
+ dependencies:
+ fdir: 6.5.0(picomatch@4.0.7)
+ picomatch: 4.0.7
+
typescript@5.9.3: {}
undici-types@6.21.0: {}
+
+ update-browserslist-db@1.3.2(browserslist@4.28.8):
+ dependencies:
+ browserslist: 4.28.8
+ escalade: 3.2.0
+ picocolors: 1.1.1
+
+ vite@6.4.3(@types/node@22.20.1):
+ dependencies:
+ esbuild: 0.25.12
+ fdir: 6.5.0(picomatch@4.0.7)
+ picomatch: 4.0.7
+ postcss: 8.5.26
+ rollup: 4.63.1
+ tinyglobby: 0.2.17
+ optionalDependencies:
+ '@types/node': 22.20.1
+ fsevents: 2.3.3
+
+ yallist@3.1.1: {}
diff --git a/pnpm-workspace.yaml b/pnpm-workspace.yaml
index c25addb..8a61f06 100644
--- a/pnpm-workspace.yaml
+++ b/pnpm-workspace.yaml
@@ -1,2 +1,8 @@
packages:
- "examples/*"
+
+allowBuilds:
+ esbuild: true
+
+onlyBuiltDependencies:
+ - esbuild
diff --git a/src/index.ts b/src/index.ts
index eee72d4..325071f 100644
--- a/src/index.ts
+++ b/src/index.ts
@@ -8,6 +8,7 @@ export type {
ActionRegistryEntry,
SchemaRegistryEntry,
LayoutPreview,
-} from './registry.js'
+ LayoutRenderProps,
+} from './registry.ts'
export { definePage } from './page.ts'
-export type { PageDeclaration, PageBlockDecl, PageContext, SetupData } from './page.js'
+export type { PageDeclaration, PageBlockDecl, PageContext, SetupData } from './page.ts'
diff --git a/src/page.ts b/src/page.ts
index 8ec4617..ecd2bf0 100644
--- a/src/page.ts
+++ b/src/page.ts
@@ -12,6 +12,8 @@ import { type RegistryApi, registry } from './registry.ts'
export interface PageBlockDecl {
/** widget 注册 id,如 'data-table'、'page-header' */
readonly widget: string
+ /** 落在布局的哪个槽位(缺省 'content';渲染内核按布局 slots 装配) */
+ readonly slot?: string
/** 静态 props(可选) */
readonly props?: Record
/** 业务绑定:setup 返回的数据里取哪些字段喂给 widget(键:widget prop 名,值:setup 结果字段) */
diff --git a/src/registry.ts b/src/registry.ts
index bab0cf6..9ea1052 100644
--- a/src/registry.ts
+++ b/src/registry.ts
@@ -9,6 +9,15 @@
export type RegistryKind = 'layout' | 'widget' | 'action' | 'schema' | 'theme'
+/** 布局渲染函数签名(React 无关,render 层传入类型;避免 core 依赖 React) */
+export interface LayoutRenderProps {
+ readonly slots: readonly S[]
+ /** slot → 已填充的 ReactNode 数组 */
+ readonly blocks: Record
+ /** 页面声明本身(含 title 等元信息) */
+ readonly page: { readonly layout: string; readonly title?: string }
+}
+
/** 布局骨架:页面级结构。渲染内核据 slots 填充 blocks。 */
export interface LayoutRegistryEntry {
readonly kind: 'layout'
@@ -18,6 +27,8 @@ export interface LayoutRegistryEntry {
readonly slots: readonly string[]
/** 描述,供画廊/agent 展示 */
readonly description: string
+ /** 布局渲染实现(slots → 页面骨架)。可选:缺省用画廊的通用骨架 */
+ readonly render?: (props: LayoutRenderProps) => unknown
/** demo 数据(预览即真实,与实装共用渲染内核) */
readonly preview?: LayoutPreview
}
@@ -37,7 +48,7 @@ export interface LayoutPreview {
export interface WidgetRegistryEntry {
readonly kind: 'widget'
readonly id: string
- /** 渲染组件。内核薄,仅做映射层 */
+ /** 渲染组件(React 组件;render 层消费,core 不依赖 React 类型) */
readonly component?: unknown
/** 关联字段/列 schema id(可选) */
readonly schemaId?: string
diff --git a/src/render.ts b/src/render.ts
new file mode 100644
index 0000000..47439e1
--- /dev/null
+++ b/src/render.ts
@@ -0,0 +1,149 @@
+/**
+ * vibe-registry render —— 极薄 React 渲染内核(可选子路径:vibe-registry/render)
+ *
+ * 设计(v0.5):
+ * - core(registry/page)零依赖;渲染内核单独子路径,谁用谁引 React
+ * - 不做运行时编辑器,不重造组件:widget.component 映射已有组件
+ * - 预览即真实:画廊与实装共用本内核
+ */
+import React from 'react'
+import type { RegistryApi, LayoutRegistryEntry, LayoutRenderProps } from './registry.ts'
+import type { PageDeclaration, PageBlockDecl } from './page.ts'
+
+/** widget 的 React 组件形态(宽松:props 由声明 props/bind 决定) */
+export type WidgetComponent = React.ComponentType> | React.ElementType
+
+/* ── 单 widget 渲染 ─────────────────────────────────────────── */
+
+export interface WidgetViewProps {
+ readonly widget: string
+ readonly registry: RegistryApi
+ /** 静态 props */
+ readonly props?: Record
+ /** setup 数据(供 bind 取字段) */
+ readonly data?: Record
+ readonly bind?: Record
+}
+
+export function WidgetView({ widget, registry, props = {}, data = {}, bind }: WidgetViewProps): React.ReactElement {
+ const entry = registry.store.widgets.get(widget)
+ if (!entry) {
+ throw new Error(`[vibe-registry/render] 未知 widget:'${widget}' (未注册)`)
+ }
+ const Comp = entry.component as WidgetComponent | undefined
+ if (!Comp) {
+ throw new Error(`[vibe-registry/render] widget '${widget}' 未挂组件(component 缺失)`)
+ }
+ // bind:props 名 ← setup 数据字段
+ const bound: Record = {}
+ if (bind) {
+ for (const [prop, key] of Object.entries(bind)) bound[prop] = data[key]
+ }
+ return React.createElement(Comp, { ...props, ...bound })
+}
+
+/* ── 整页渲染:声明 + 注册表 → 组件树 ────────────────────────── */
+
+export interface PageViewProps {
+ readonly page: PageDeclaration
+ readonly registry: RegistryApi
+ /** setup 已执行完的数据 */
+ readonly data?: Record
+}
+
+export function PageView({ page, registry, data = {} }: PageViewProps): React.ReactElement {
+ const layout = registry.store.layouts.get(page.layout)
+ if (!layout) {
+ throw new Error(`[vibe-registry/render] 未知布局:'${page.layout}'`)
+ }
+ const renderLayout = (layout.render as React.ComponentType | undefined) ?? DefaultLayout
+ // 按 slot 分组填充 blocks
+ const filled: Record = {}
+ for (const b of page.blocks) {
+ const slot = b.slot ?? 'content'
+ ;(filled[slot] ??= []).push(
+ React.createElement(WidgetView, {
+ key: b.widget + JSON.stringify(b.props ?? {}),
+ widget: b.widget,
+ registry,
+ props: b.props,
+ bind: b.bind,
+ data,
+ }),
+ )
+ }
+ return React.createElement(renderLayout, { slots: layout.slots, blocks: filled, page })
+}
+
+/** 缺省布局骨架:无 render 的布局按 slots 顺序纵向排(演示/兜底用) */
+export function DefaultLayout({ slots, blocks }: LayoutRenderProps): React.ReactElement {
+ return React.createElement(
+ 'div',
+ { style: { border: '1px dashed #d1d5db', borderRadius: 8, padding: 12 } },
+ ...slots.flatMap((slot) => {
+ const children = blocks[slot] as React.ReactNode[] | undefined
+ if (!children || children.length === 0) return []
+ return [
+ React.createElement(
+ 'div',
+ { key: slot, style: { marginBottom: 12 } },
+ React.createElement(
+ 'div',
+ { style: { fontSize: 11, color: '#9ca3af', marginBottom: 4, textTransform: 'uppercase' } },
+ `slot: ${slot}`,
+ ),
+ ...children,
+ ),
+ ]
+ }),
+ )
+}
+
+/* ── 画廊:列出全部注册布局 + live 预览(类 Vite 首页)────────── */
+
+export interface GalleryProps {
+ readonly registry: RegistryApi
+ readonly pages?: readonly PageDeclaration[]
+}
+
+function PreviewShell({ title, children }: { title: string; children?: React.ReactNode }): React.ReactElement {
+ return React.createElement(
+ 'div',
+ { style: { border: '1px solid #e5e7eb', borderRadius: 8, padding: 12, background: '#fff' } },
+ React.createElement('h3', { style: { margin: '0 0 8px', fontSize: 14 } }, title),
+ React.createElement('div', { style: { fontSize: 12, color: '#6b7280' } }, children),
+ )
+}
+
+export function LayoutGallery({ registry }: GalleryProps): React.ReactElement {
+ const layouts = registry.listAll().filter((e): e is LayoutRegistryEntry => e.kind === 'layout')
+ const widgets = registry.listAll().filter((e) => e.kind === 'widget')
+ const items = layouts.map((layout) => {
+ const demo = layout.preview?.demoBlocks ?? []
+ return React.createElement(
+ PreviewShell,
+ { key: layout.id, title: `${layout.preview?.title ?? layout.id} (${layout.id})` },
+ React.createElement(
+ 'div',
+ {},
+ React.createElement('div', {}, `slots: ${layout.slots.join(' → ')}`),
+ demo.length
+ ? React.createElement(
+ 'ul',
+ {},
+ demo.map((d, i) =>
+ React.createElement('li', { key: i }, `${d.slot} ← widget:${d.widget} ${d.props ? JSON.stringify(d.props) : ''}`),
+ ),
+ )
+ : React.createElement('div', {}, '(无 demo)'),
+ ),
+ )
+ })
+ return React.createElement(
+ 'div',
+ { style: { fontFamily: 'system-ui, sans-serif', maxWidth: 720, margin: '0 auto', padding: 24 } },
+ React.createElement('h1', { style: { fontSize: 20 } }, 'vibe-registry · 布局画廊'),
+ React.createElement('p', { style: { color: '#6b7280' } }, `已注册:${layouts.length} 布局 · ${widgets.length} widget`),
+ React.createElement('div', { style: { display: 'grid', gap: 12 } }, ...items),
+ )
+}