@james_sww/metaform-asset-distribution 0.1.0 → 0.1.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +8 -6
- package/codebase/codebase.json +13 -11
- package/codebase/template/.env.example +11 -1
- package/codebase/template/.metaform/template-overrides.json +24 -0
- package/codebase/template/index.html +1 -1
- package/codebase/template/src/components/common/empty-state.tsx +52 -0
- package/codebase/template/src/components/common/error-boundary.tsx +2 -2
- package/codebase/template/src/components/ui/alert.tsx +48 -50
- package/codebase/template/src/hooks/index.ts +2 -2
- package/codebase/template/src/integrations/platform.ts +65 -1
- package/codebase/template/src/layouts/role-workspace-shell.tsx +136 -48
- package/codebase/template/src/lib/http-client.ts +1 -1
- package/codebase/template/src/main.tsx +11 -1
- package/codebase/template/src/workspace/default-workspace.tsx +1 -1
- package/dist/application-source.d.ts +5 -3
- package/dist/application-source.js +43 -32
- package/dist/cli.js +1 -1
- package/dist/contracts.d.ts +6 -1
- package/dist/contracts.js +1 -1
- package/dist/export-source.js +3 -3
- package/dist/prepare.d.ts +1 -1
- package/dist/prepare.js +41 -25
- package/dist/source-map.d.ts +2 -1
- package/dist/source-map.js +10 -8
- package/dist/template.d.ts +1 -1
- package/dist/template.js +1 -1
- package/package.json +2 -2
- package/registry/47e2405d581daf6aa5433b033351b639e11f9730d174a0563b88e36bc06402f9/catalog.json +1 -0
- package/registry/47e2405d581daf6aa5433b033351b639e11f9730d174a0563b88e36bc06402f9/r/common-semantic-region-scaffold.json +1 -0
- package/registry/47e2405d581daf6aa5433b033351b639e11f9730d174a0563b88e36bc06402f9/r/components-business-role-tasks-icons.json +1 -0
- package/registry/47e2405d581daf6aa5433b033351b639e11f9730d174a0563b88e36bc06402f9/r/components-business-role-tasks-types.json +1 -0
- package/registry/47e2405d581daf6aa5433b033351b639e11f9730d174a0563b88e36bc06402f9/r/components-common-semantic-region-contract.json +1 -0
- package/registry/47e2405d581daf6aa5433b033351b639e11f9730d174a0563b88e36bc06402f9/r/layouts-role-workspace-account.json +1 -0
- package/registry/47e2405d581daf6aa5433b033351b639e11f9730d174a0563b88e36bc06402f9/r/layouts-role-workspace-icons.json +1 -0
- package/registry/47e2405d581daf6aa5433b033351b639e11f9730d174a0563b88e36bc06402f9/r/layouts-role-workspace-routes.json +1 -0
- package/registry/47e2405d581daf6aa5433b033351b639e11f9730d174a0563b88e36bc06402f9/r/layouts-role-workspace-types.json +1 -0
- package/registry/47e2405d581daf6aa5433b033351b639e11f9730d174a0563b88e36bc06402f9/r/lib-utils.json +1 -0
- package/registry/47e2405d581daf6aa5433b033351b639e11f9730d174a0563b88e36bc06402f9/r/quality-role-task-groups.json +1 -0
- package/registry/47e2405d581daf6aa5433b033351b639e11f9730d174a0563b88e36bc06402f9/r/quality-role-task-overview.json +1 -0
- package/registry/47e2405d581daf6aa5433b033351b639e11f9730d174a0563b88e36bc06402f9/r/role-workspace-shell.json +1 -0
- package/registry/47e2405d581daf6aa5433b033351b639e11f9730d174a0563b88e36bc06402f9/r/styles-styles.json +1 -0
- package/registry/47e2405d581daf6aa5433b033351b639e11f9730d174a0563b88e36bc06402f9/r/styles-theme-tokens.json +1 -0
- package/registry/47e2405d581daf6aa5433b033351b639e11f9730d174a0563b88e36bc06402f9/r/ui-avatar.json +1 -0
- package/registry/47e2405d581daf6aa5433b033351b639e11f9730d174a0563b88e36bc06402f9/r/ui-badge.json +1 -0
- package/registry/47e2405d581daf6aa5433b033351b639e11f9730d174a0563b88e36bc06402f9/r/ui-button.json +1 -0
- package/registry/47e2405d581daf6aa5433b033351b639e11f9730d174a0563b88e36bc06402f9/r/ui-collapsible.json +1 -0
- package/registry/47e2405d581daf6aa5433b033351b639e11f9730d174a0563b88e36bc06402f9/r/ui-dropdown-menu.json +1 -0
- package/registry/47e2405d581daf6aa5433b033351b639e11f9730d174a0563b88e36bc06402f9/r/ui-empty.json +1 -0
- package/registry/47e2405d581daf6aa5433b033351b639e11f9730d174a0563b88e36bc06402f9/r/ui-sheet.json +1 -0
- package/registry/47e2405d581daf6aa5433b033351b639e11f9730d174a0563b88e36bc06402f9/r/ui-skeleton.json +1 -0
- package/registry/47e2405d581daf6aa5433b033351b639e11f9730d174a0563b88e36bc06402f9/r/ui-tooltip.json +1 -0
- package/registry/47e2405d581daf6aa5433b033351b639e11f9730d174a0563b88e36bc06402f9/registry.json +1 -0
- package/registry/47e2405d581daf6aa5433b033351b639e11f9730d174a0563b88e36bc06402f9/release.json +1 -0
- package/registry/5bce235170d2de6e2c3b0cfe10d0596dd53189c83acb8d3e4256b11606d95a22/catalog.json +1 -0
- package/registry/5bce235170d2de6e2c3b0cfe10d0596dd53189c83acb8d3e4256b11606d95a22/r/common-semantic-region-scaffold.json +1 -0
- package/registry/5bce235170d2de6e2c3b0cfe10d0596dd53189c83acb8d3e4256b11606d95a22/r/components-business-role-tasks-icons.json +1 -0
- package/registry/5bce235170d2de6e2c3b0cfe10d0596dd53189c83acb8d3e4256b11606d95a22/r/components-business-role-tasks-types.json +1 -0
- package/registry/5bce235170d2de6e2c3b0cfe10d0596dd53189c83acb8d3e4256b11606d95a22/r/components-common-semantic-region-contract.json +1 -0
- package/registry/5bce235170d2de6e2c3b0cfe10d0596dd53189c83acb8d3e4256b11606d95a22/r/layouts-role-workspace-account.json +1 -0
- package/registry/5bce235170d2de6e2c3b0cfe10d0596dd53189c83acb8d3e4256b11606d95a22/r/layouts-role-workspace-icons.json +1 -0
- package/registry/5bce235170d2de6e2c3b0cfe10d0596dd53189c83acb8d3e4256b11606d95a22/r/layouts-role-workspace-routes.json +1 -0
- package/registry/5bce235170d2de6e2c3b0cfe10d0596dd53189c83acb8d3e4256b11606d95a22/r/layouts-role-workspace-types.json +1 -0
- package/registry/5bce235170d2de6e2c3b0cfe10d0596dd53189c83acb8d3e4256b11606d95a22/r/lib-utils.json +1 -0
- package/registry/5bce235170d2de6e2c3b0cfe10d0596dd53189c83acb8d3e4256b11606d95a22/r/quality-role-task-groups.json +1 -0
- package/registry/5bce235170d2de6e2c3b0cfe10d0596dd53189c83acb8d3e4256b11606d95a22/r/quality-role-task-overview.json +1 -0
- package/registry/5bce235170d2de6e2c3b0cfe10d0596dd53189c83acb8d3e4256b11606d95a22/r/role-workspace-shell.json +1 -0
- package/registry/5bce235170d2de6e2c3b0cfe10d0596dd53189c83acb8d3e4256b11606d95a22/r/styles-styles.json +1 -0
- package/registry/5bce235170d2de6e2c3b0cfe10d0596dd53189c83acb8d3e4256b11606d95a22/r/styles-theme-tokens.json +1 -0
- package/registry/5bce235170d2de6e2c3b0cfe10d0596dd53189c83acb8d3e4256b11606d95a22/r/ui-avatar.json +1 -0
- package/registry/5bce235170d2de6e2c3b0cfe10d0596dd53189c83acb8d3e4256b11606d95a22/r/ui-badge.json +1 -0
- package/registry/5bce235170d2de6e2c3b0cfe10d0596dd53189c83acb8d3e4256b11606d95a22/r/ui-button.json +1 -0
- package/registry/5bce235170d2de6e2c3b0cfe10d0596dd53189c83acb8d3e4256b11606d95a22/r/ui-collapsible.json +1 -0
- package/registry/5bce235170d2de6e2c3b0cfe10d0596dd53189c83acb8d3e4256b11606d95a22/r/ui-dropdown-menu.json +1 -0
- package/registry/5bce235170d2de6e2c3b0cfe10d0596dd53189c83acb8d3e4256b11606d95a22/r/ui-empty.json +1 -0
- package/registry/5bce235170d2de6e2c3b0cfe10d0596dd53189c83acb8d3e4256b11606d95a22/r/ui-sheet.json +1 -0
- package/registry/5bce235170d2de6e2c3b0cfe10d0596dd53189c83acb8d3e4256b11606d95a22/r/ui-skeleton.json +1 -0
- package/registry/5bce235170d2de6e2c3b0cfe10d0596dd53189c83acb8d3e4256b11606d95a22/r/ui-tooltip.json +1 -0
- package/registry/5bce235170d2de6e2c3b0cfe10d0596dd53189c83acb8d3e4256b11606d95a22/registry.json +1 -0
- package/registry/5bce235170d2de6e2c3b0cfe10d0596dd53189c83acb8d3e4256b11606d95a22/release.json +1 -0
- package/registry/ac851c907cc97669042b64a5d30d9bec2017d07e43c8cd933db399f446c5bb86/catalog.json +1 -0
- package/registry/ac851c907cc97669042b64a5d30d9bec2017d07e43c8cd933db399f446c5bb86/r/common-semantic-region-scaffold.json +1 -0
- package/registry/ac851c907cc97669042b64a5d30d9bec2017d07e43c8cd933db399f446c5bb86/r/components-business-role-tasks-icons.json +1 -0
- package/registry/ac851c907cc97669042b64a5d30d9bec2017d07e43c8cd933db399f446c5bb86/r/components-business-role-tasks-types.json +1 -0
- package/registry/ac851c907cc97669042b64a5d30d9bec2017d07e43c8cd933db399f446c5bb86/r/components-common-semantic-region-contract.json +1 -0
- package/registry/ac851c907cc97669042b64a5d30d9bec2017d07e43c8cd933db399f446c5bb86/r/lib-utils.json +1 -0
- package/registry/ac851c907cc97669042b64a5d30d9bec2017d07e43c8cd933db399f446c5bb86/r/quality-role-task-groups.json +1 -0
- package/registry/ac851c907cc97669042b64a5d30d9bec2017d07e43c8cd933db399f446c5bb86/r/quality-role-task-overview.json +1 -0
- package/registry/ac851c907cc97669042b64a5d30d9bec2017d07e43c8cd933db399f446c5bb86/r/styles-styles.json +1 -0
- package/registry/ac851c907cc97669042b64a5d30d9bec2017d07e43c8cd933db399f446c5bb86/r/styles-theme-tokens.json +1 -0
- package/registry/ac851c907cc97669042b64a5d30d9bec2017d07e43c8cd933db399f446c5bb86/r/ui-badge.json +1 -0
- package/registry/ac851c907cc97669042b64a5d30d9bec2017d07e43c8cd933db399f446c5bb86/r/ui-button.json +1 -0
- package/registry/ac851c907cc97669042b64a5d30d9bec2017d07e43c8cd933db399f446c5bb86/r/ui-collapsible.json +1 -0
- package/registry/ac851c907cc97669042b64a5d30d9bec2017d07e43c8cd933db399f446c5bb86/r/ui-empty.json +1 -0
- package/registry/ac851c907cc97669042b64a5d30d9bec2017d07e43c8cd933db399f446c5bb86/registry.json +1 -0
- package/registry/ac851c907cc97669042b64a5d30d9bec2017d07e43c8cd933db399f446c5bb86/release.json +1 -0
- package/registry/f5db0c88ee95ccef50d6ced1f08e935c8c56006e337b978e332f0974b18d79b2/catalog.json +1 -0
- package/registry/f5db0c88ee95ccef50d6ced1f08e935c8c56006e337b978e332f0974b18d79b2/r/common-semantic-region-scaffold.json +1 -0
- package/registry/f5db0c88ee95ccef50d6ced1f08e935c8c56006e337b978e332f0974b18d79b2/r/components-business-role-tasks-icons.json +1 -0
- package/registry/f5db0c88ee95ccef50d6ced1f08e935c8c56006e337b978e332f0974b18d79b2/r/components-business-role-tasks-types.json +1 -0
- package/registry/f5db0c88ee95ccef50d6ced1f08e935c8c56006e337b978e332f0974b18d79b2/r/components-common-semantic-region-contract.json +1 -0
- package/registry/f5db0c88ee95ccef50d6ced1f08e935c8c56006e337b978e332f0974b18d79b2/r/lib-utils.json +1 -0
- package/registry/f5db0c88ee95ccef50d6ced1f08e935c8c56006e337b978e332f0974b18d79b2/r/quality-role-task-groups.json +1 -0
- package/registry/f5db0c88ee95ccef50d6ced1f08e935c8c56006e337b978e332f0974b18d79b2/r/quality-role-task-overview.json +1 -0
- package/registry/f5db0c88ee95ccef50d6ced1f08e935c8c56006e337b978e332f0974b18d79b2/r/styles-styles.json +1 -0
- package/registry/f5db0c88ee95ccef50d6ced1f08e935c8c56006e337b978e332f0974b18d79b2/r/styles-theme-tokens.json +1 -0
- package/registry/f5db0c88ee95ccef50d6ced1f08e935c8c56006e337b978e332f0974b18d79b2/r/ui-badge.json +1 -0
- package/registry/f5db0c88ee95ccef50d6ced1f08e935c8c56006e337b978e332f0974b18d79b2/r/ui-button.json +1 -0
- package/registry/f5db0c88ee95ccef50d6ced1f08e935c8c56006e337b978e332f0974b18d79b2/r/ui-collapsible.json +1 -0
- package/registry/f5db0c88ee95ccef50d6ced1f08e935c8c56006e337b978e332f0974b18d79b2/r/ui-empty.json +1 -0
- package/registry/f5db0c88ee95ccef50d6ced1f08e935c8c56006e337b978e332f0974b18d79b2/registry.json +1 -0
- package/registry/f5db0c88ee95ccef50d6ced1f08e935c8c56006e337b978e332f0974b18d79b2/release.json +1 -0
- package/registry/release.json +1 -1
package/registry/f5db0c88ee95ccef50d6ced1f08e935c8c56006e337b978e332f0974b18d79b2/registry.json
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"$schema":"https://ui.shadcn.com/schema/registry.json","homepage":"http://localhost:4318/","items":[{"$schema":"https://ui.shadcn.com/schema/registry-item.json","dependencies":[],"description":"components.common.semantic-region.contract","files":[{"content":"export type DecisionStatus = 'pending' | 'confirmed' | 'deferred';\nexport interface SemanticAction {\n id: string;\n label: string;\n intent: 'navigate' | 'query' | 'command';\n inputs: string[];\n preconditions: string[];\n result: string;\n feedback: string;\n enabled: boolean;\n blockedReason?: string;\n targetPageId?: string;\n capabilityRef?: string;\n}\nexport interface SemanticRegionContract {\n id: string;\n pageId: string;\n parentRegionId?: string;\n title: string;\n responsibility: string;\n sourceRefs: { ref: string; version?: string }[];\n inputs: string[];\n outputs: string[];\n bindings: {\n id: string;\n label: string;\n logicalTarget: string;\n status: DecisionStatus;\n concreteRef?: string;\n }[];\n actions: SemanticAction[];\n businessStates: string[];\n navigation: string[];\n replacement: { inputs: string[]; events: string[]; stateOwner: string };\n questions: {\n id: string;\n question: string;\n status: DecisionStatus;\n answer?: string;\n evidence?: string;\n }[];\n progress: {\n design: 'proposed' | 'confirmed';\n implementation: 'scaffold' | 'asset' | 'custom';\n binding: 'pending' | 'ready';\n verification: 'not-run' | 'passed' | 'failed';\n };\n}\nexport interface ContractIssue {\n path: string;\n message: string;\n}\n\nexport function isJsonData(value: unknown, ancestors = new Set<object>(), depth = 0): boolean {\n if (depth > 48) return false;\n if (value === null || typeof value === 'string' || typeof value === 'boolean') return true;\n if (typeof value === 'number') return Number.isFinite(value);\n if (typeof value !== 'object' || ancestors.has(value)) return false;\n if (\n !Array.isArray(value) &&\n Object.getPrototypeOf(value) !== Object.prototype &&\n Object.getPrototypeOf(value) !== null\n )\n return false;\n ancestors.add(value);\n const valid = Object.entries(value).every(\n ([key, item]) =>\n !['__proto__', 'constructor', 'prototype'].includes(key) &&\n isJsonData(item, ancestors, depth + 1),\n );\n ancestors.delete(value);\n return valid;\n}\n\nexport function validateSemanticRegion(value: unknown): {\n valid: boolean;\n issues: ContractIssue[];\n} {\n const issues: ContractIssue[] = [];\n const issue = (path: string, message: string) => {\n issues.push({ path, message });\n };\n if (!isJsonData(value))\n return { valid: false, issues: [{ path: '', message: '只接受普通 JSON 数据' }] };\n function object(v: unknown, path: string): Record<string, unknown> {\n if (!v || typeof v !== 'object' || Array.isArray(v)) {\n issue(path, '需要对象');\n return {};\n }\n return v as Record<string, unknown>;\n }\n function text(v: unknown, path: string) {\n if (typeof v !== 'string' || !v.trim()) issue(path, '需要非空文字');\n }\n function choice(v: unknown, path: string, values: string[]) {\n if (!values.includes(v as string)) issue(path, '状态不在允许范围');\n }\n function array(v: unknown, path: string): unknown[] {\n if (!Array.isArray(v)) {\n issue(path, '需要数组');\n return [];\n }\n return v;\n }\n function strings(v: unknown, path: string) {\n array(v, path).forEach((x, i) => text(x, `${path}.${i}`));\n }\n function rows(\n v: unknown,\n path: string,\n visit: (row: Record<string, unknown>, path: string) => void,\n ) {\n const ids = new Set<string>();\n array(v, path).forEach((x, i) => {\n const p = `${path}.${i}`,\n row = object(x, p);\n text(row.id, p + '.id');\n if (typeof row.id === 'string') {\n if (!/^[a-z][a-z0-9-]*$/.test(row.id) || ids.has(row.id))\n issue(p + '.id', '标识无效或重复');\n ids.add(row.id);\n }\n visit(row, p);\n });\n }\n const r = object(value, '');\n for (const key of ['id', 'pageId', 'title', 'responsibility']) text(r[key], key);\n if (typeof r.id === 'string' && !/^[a-z][a-z0-9-]*$/.test(r.id)) issue('id', '区域标识无效');\n for (const key of ['inputs', 'outputs', 'businessStates', 'navigation']) strings(r[key], key);\n array(r.sourceRefs, 'sourceRefs').forEach((x, i) => {\n const row = object(x, `sourceRefs.${i}`);\n text(row.ref, `sourceRefs.${i}.ref`);\n if (row.version !== undefined) text(row.version, `sourceRefs.${i}.version`);\n });\n rows(r.bindings, 'bindings', (b, p) => {\n for (const key of ['label', 'logicalTarget']) text(b[key], p + '.' + key);\n choice(b.status, p + '.status', ['pending', 'confirmed', 'deferred']);\n if (b.status === 'confirmed') text(b.concreteRef, p + '.concreteRef');\n });\n rows(r.actions, 'actions', (a, p) => {\n for (const key of ['label', 'result', 'feedback']) text(a[key], p + '.' + key);\n strings(a.inputs, p + '.inputs');\n strings(a.preconditions, p + '.preconditions');\n choice(a.intent, p + '.intent', ['navigate', 'query', 'command']);\n if (typeof a.enabled !== 'boolean') issue(p + '.enabled', '需要明确可用性');\n if (a.enabled === false) text(a.blockedReason, p + '.blockedReason');\n if (a.enabled === true)\n text(a.intent === 'navigate' ? a.targetPageId : a.capabilityRef, p + '.target');\n });\n const replacement = object(r.replacement, 'replacement');\n strings(replacement.inputs, 'replacement.inputs');\n strings(replacement.events, 'replacement.events');\n text(replacement.stateOwner, 'replacement.stateOwner');\n rows(r.questions, 'questions', (q, p) => {\n text(q.question, p + '.question');\n choice(q.status, p + '.status', ['pending', 'confirmed', 'deferred']);\n if (q.status === 'confirmed') {\n text(q.answer, p + '.answer');\n text(q.evidence, p + '.evidence');\n }\n });\n const progress = object(r.progress, 'progress');\n choice(progress.design, 'progress.design', ['proposed', 'confirmed']);\n choice(progress.implementation, 'progress.implementation', ['scaffold', 'asset', 'custom']);\n choice(progress.binding, 'progress.binding', ['pending', 'ready']);\n choice(progress.verification, 'progress.verification', ['not-run', 'passed', 'failed']);\n if (\n progress.binding === 'ready' &&\n array(r.bindings, 'bindings').some((b) => object(b, 'bindings').status !== 'confirmed')\n )\n issue('progress.binding', '仍有未确认的数据需求');\n return { valid: issues.length === 0, issues };\n}\n","path":"src/components/common/semantic-region/contract.ts","target":"~/src/components/common/semantic-region/contract.ts","type":"registry:file"}],"meta":{"assetId":"components.common.semantic-region.contract","contractRef":"layout/src/semantic-region/contract.ts","maturity":"candidate","releaseDigest":"f5db0c88ee95ccef50d6ced1f08e935c8c56006e337b978e332f0974b18d79b2","version":"0.1.0"},"name":"components-common-semantic-region-contract","registryDependencies":[],"title":"components.common.semantic-region.contract","type":"registry:block"},{"$schema":"https://ui.shadcn.com/schema/registry-item.json","dependencies":["clsx@2.1.1","tailwind-merge@3.6.0"],"description":"lib.utils","files":[{"content":"import { type ClassValue, clsx } from \"clsx\";\nimport { twMerge } from \"tailwind-merge\";\n\nexport function cn(...inputs: ClassValue[]) {\n return twMerge(clsx(inputs));\n}\n","path":"src/lib/utils.ts","target":"~/src/lib/utils.ts","type":"registry:file"}],"meta":{"assetId":"lib.utils","contractRef":"vendor/design-system/src/lib/utils.ts","maturity":"candidate","releaseDigest":"f5db0c88ee95ccef50d6ced1f08e935c8c56006e337b978e332f0974b18d79b2","version":"0.1.0"},"name":"lib-utils","registryDependencies":[],"title":"lib.utils","type":"registry:block"},{"$schema":"https://ui.shadcn.com/schema/registry-item.json","dependencies":[],"description":"styles.theme-tokens","files":[{"content":"/* Platform console's always-dark navigation, shared by light and dark modes. */\n[data-sidebar-theme='platform'] {\n --sidebar-background: #17263c;\n --sidebar-foreground: #aebed0;\n --sidebar-border: #2e4055;\n --sidebar-user-foreground: #fff;\n --sidebar-avatar-background: #e4d9c9;\n --sidebar-avatar-foreground: #7a6044;\n --foreground: #fff;\n --muted-foreground: #859bb2;\n --control-hover: #263950;\n --selection: #294c54;\n --selection-foreground: #58d5bd;\n --selection-border: #294c54;\n --ring: #58d5bd;\n}\n\n/*\n * Metaform theme source of truth.\n *\n * Palette tokens never change meaning. Theme role tokens are the only values\n * overridden by a preset, so application code never depends on a brand hex.\n */\n:root {\n --radius: 0.5rem;\n\n /* Fixed palette */\n --palette-ink: oklch(21.01% 0.0318 264.66deg);\n --palette-ink-hover: oklch(27.81% 0.0296 256.85deg);\n --palette-ink-active: oklch(12.96% 0.0274 261.69deg);\n --palette-cobalt: oklch(54.78% 0.1724 265.67deg);\n --palette-cobalt-hover: oklch(47.44% 0.1459 265.64deg);\n --palette-cobalt-active: oklch(39.72% 0.1074 262.56deg);\n --palette-cyan: oklch(71.5% 0.143 215.22deg);\n --palette-teal: oklch(49.5% 0.102 181.5deg);\n --palette-teal-hover: oklch(43.5% 0.092 181.5deg);\n --palette-teal-active: oklch(36% 0.075 181.5deg);\n --palette-steel: oklch(48% 0.065 245deg);\n --palette-steel-hover: oklch(41% 0.06 245deg);\n --palette-steel-active: oklch(33% 0.052 245deg);\n --palette-safety: oklch(66% 0.17 58deg);\n --palette-safety-hover: oklch(57% 0.15 58deg);\n --palette-safety-active: oklch(48% 0.13 58deg);\n --palette-ocean: oklch(49% 0.11 210deg);\n --palette-ocean-hover: oklch(42% 0.1 210deg);\n --palette-ocean-active: oklch(35% 0.082 210deg);\n --palette-white: oklch(98.5% 0.003 247.86deg);\n\n /* Theme roles: neutral is the default preset. */\n --theme-accent: var(--palette-ink);\n --theme-accent-hover: var(--palette-ink-hover);\n --theme-accent-active: var(--palette-ink-active);\n --theme-accent-soft: oklch(96.83% 0.0069 247.9deg);\n --theme-accent-border: oklch(86.9% 0.0198 252.89deg);\n --theme-accent-foreground: var(--palette-white);\n\n /* Auxiliary brand roles: every preset owns the complete family. */\n --theme-support: var(--palette-cobalt);\n --theme-support-strong: var(--palette-teal);\n --theme-support-soft: oklch(96.5% 0.012 230deg);\n --theme-display-gradient-start: var(--palette-cobalt-active);\n --theme-display-gradient-highlight: var(--palette-cyan);\n --theme-display-gradient-end: var(--palette-teal);\n\n /* Stable semantic colors never follow the selected brand theme. */\n --semantic-success: oklch(65.59% 0.1686 146.19deg);\n --semantic-success-soft: oklch(96.3% 0.032 146.19deg);\n --semantic-success-foreground: oklch(40.5% 0.115 146.19deg);\n --semantic-warning: oklch(79.98% 0.1706 72.75deg);\n --semantic-warning-soft: oklch(97.3% 0.035 72.75deg);\n --semantic-warning-foreground: oklch(43% 0.12 72.75deg);\n --semantic-danger: oklch(63.07% 0.201 25.03deg);\n --semantic-danger-soft: oklch(95.8% 0.025 25.03deg);\n --semantic-danger-foreground: oklch(44% 0.16 25.03deg);\n\n /* Surfaces and content */\n --surface-canvas: oklch(97.89% 0.0029 264.54deg);\n --surface-panel: oklch(99.5% 0.002 247.86deg);\n --surface-raised: oklch(100% 0.001 247.86deg);\n --surface-muted: oklch(96.7% 0.004 264.54deg);\n --surface-muted-foreground: var(--text-regular);\n --text-primary: var(--palette-ink);\n --text-regular: oklch(37.3% 0.034 259.73deg);\n --text-secondary: oklch(55.44% 0.0407 257.42deg);\n\n /* Navigation links stay blue independently of the selected brand theme. */\n --link-foreground: var(--palette-cobalt);\n --link-hover-foreground: var(--palette-cobalt-hover);\n --border-base: oklch(92.88% 0.0126 255.51deg);\n --border-soft: oklch(95.5% 0.008 255.51deg);\n --border-input: oklch(84.5% 0.016 255.51deg);\n --control-hover: var(--surface-muted);\n --control-active: var(--selection);\n --control-active-foreground: var(--selection-foreground);\n --control-active-border: var(--selection-border);\n\n /* shadcn focus ring: neutral gray, not brand accent */\n --ring-muted: oklch(70.4% 0.04 256.79deg);\n\n /* Application roles derived from the active theme preset. */\n --brand-accent: var(--theme-accent);\n --brand-accent-hover: var(--theme-accent-hover);\n --brand-accent-active: var(--theme-accent-active);\n --brand-accent-soft: var(--theme-accent-soft);\n --brand-accent-border: var(--theme-accent-border);\n --brand-accent-foreground: var(--theme-accent-foreground);\n --brand-support: var(--theme-support);\n --brand-support-strong: var(--theme-support-strong);\n --brand-support-soft: var(--theme-support-soft);\n --brand-gradient-start: var(--theme-display-gradient-start);\n --brand-gradient-highlight: var(--theme-display-gradient-highlight);\n --brand-gradient-end: var(--theme-display-gradient-end);\n --action-primary: var(--theme-accent);\n --action-primary-hover: var(--theme-accent-hover);\n --action-primary-active: var(--theme-accent-active);\n --action-primary-foreground: var(--theme-accent-foreground);\n --selection: var(--theme-accent-soft);\n --selection-foreground: var(--theme-accent);\n --selection-border: var(--theme-accent-border);\n --selection-strong: var(--theme-accent-active);\n --focus-ring: var(--theme-accent);\n --sidebar-background: var(--surface-panel);\n --sidebar-foreground: var(--text-primary);\n --sidebar-active: var(--selection);\n --sidebar-active-foreground: var(--selection-foreground);\n --sidebar-border: var(--border-base);\n\n /* Data visualization colors are fixed and independent from branding. */\n --data-blue: var(--palette-cobalt);\n --data-cyan: var(--palette-cyan);\n --data-violet: oklch(60.6% 0.196 286.48deg);\n --data-green: var(--semantic-success);\n --data-amber: var(--semantic-warning);\n --data-red: var(--semantic-danger);\n --data-business: var(--palette-teal);\n --data-equipment: var(--semantic-danger);\n --data-process: var(--semantic-warning);\n --data-metric: var(--data-violet);\n --data-strategy: var(--palette-cyan);\n --data-business-soft: color-mix(in oklch, var(--data-business) 10%, var(--surface-panel));\n --data-equipment-soft: color-mix(in oklch, var(--data-equipment) 10%, var(--surface-panel));\n --data-process-soft: color-mix(in oklch, var(--data-process) 10%, var(--surface-panel));\n --data-metric-soft: color-mix(in oklch, var(--data-metric) 10%, var(--surface-panel));\n --data-strategy-soft: color-mix(in oklch, var(--data-strategy) 10%, var(--surface-panel));\n\n /* Theme setting swatches */\n --theme-swatch-neutral: var(--palette-ink);\n --theme-swatch-cobalt: var(--palette-cobalt);\n --theme-swatch-teal: var(--palette-teal);\n --theme-swatch-steel: var(--palette-steel);\n --theme-swatch-safety: var(--palette-safety);\n --theme-swatch-ocean: var(--palette-ocean);\n\n /* shadcn roles */\n --background: var(--surface-canvas);\n --foreground: var(--text-primary);\n --card: var(--surface-panel);\n --card-foreground: var(--text-primary);\n --popover: var(--surface-raised);\n --popover-foreground: var(--text-primary);\n --primary: var(--action-primary);\n --primary-foreground: var(--action-primary-foreground);\n --secondary: var(--surface-muted);\n --secondary-foreground: var(--surface-muted-foreground);\n --muted: var(--surface-muted);\n --muted-foreground: var(--text-secondary);\n --accent: var(--selection);\n --accent-foreground: var(--selection-foreground);\n --destructive: var(--semantic-danger);\n --destructive-foreground: var(--palette-white);\n --border: var(--border-base);\n --input: var(--border-input);\n --ring: var(--brand-accent);\n\n /* Legacy aliases. New code should use role tokens above. */\n --el-color-primary: var(--theme-accent);\n --el-color-primary-hover: var(--theme-accent-hover);\n --el-color-primary-active: var(--theme-accent-active);\n --el-color-primary-light-9: var(--theme-accent-soft);\n --el-color-primary-light-7: var(--theme-accent-border);\n --el-color-action: var(--action-primary);\n --el-color-action-hover: var(--action-primary-hover);\n --el-color-action-active: var(--action-primary-active);\n --el-color-success: var(--semantic-success);\n --el-color-success-light-9: var(--semantic-success-soft);\n --el-color-warning: var(--semantic-warning);\n --el-color-warning-light-9: var(--semantic-warning-soft);\n --el-color-danger: var(--semantic-danger);\n --el-color-danger-light-9: var(--semantic-danger-soft);\n --el-bg-color: var(--surface-canvas);\n --el-text-color-primary: var(--text-primary);\n --el-text-color-regular: var(--text-regular);\n --el-text-color-secondary: var(--text-secondary);\n --el-border-color-base: var(--border-base);\n}\n\n:root[data-accent='cobalt'] {\n --theme-accent: var(--palette-cobalt);\n --theme-accent-hover: var(--palette-cobalt-hover);\n --theme-accent-active: var(--palette-cobalt-active);\n --theme-accent-soft: oklch(95.53% 0.0154 269.98deg);\n --theme-accent-border: oklch(86.49% 0.0463 269.14deg);\n --theme-accent-foreground: var(--palette-white);\n --theme-support: var(--palette-cyan);\n --theme-support-strong: var(--palette-teal);\n --theme-support-soft: oklch(95.5% 0.025 215.22deg);\n --theme-display-gradient-start: var(--palette-cobalt-active);\n --theme-display-gradient-highlight: oklch(70% 0.13 265.67deg);\n --theme-display-gradient-end: var(--palette-cobalt);\n}\n\n:root[data-accent='teal'] {\n --theme-accent: var(--palette-teal);\n --theme-accent-hover: var(--palette-teal-hover);\n --theme-accent-active: var(--palette-teal-active);\n --theme-accent-soft: oklch(96% 0.018 181.5deg);\n --theme-accent-border: oklch(84% 0.045 181.5deg);\n --theme-accent-foreground: var(--palette-white);\n --theme-support: var(--palette-cyan);\n --theme-support-strong: var(--palette-cobalt);\n --theme-support-soft: oklch(95.5% 0.025 205deg);\n --theme-display-gradient-start: var(--palette-teal-active);\n --theme-display-gradient-highlight: oklch(72% 0.1 181.5deg);\n --theme-display-gradient-end: var(--palette-teal);\n}\n\n:root[data-accent='steel'] {\n --theme-accent: var(--palette-steel);\n --theme-accent-hover: var(--palette-steel-hover);\n --theme-accent-active: var(--palette-steel-active);\n --theme-accent-soft: oklch(95.5% 0.012 245deg);\n --theme-accent-border: oklch(84% 0.035 245deg);\n --theme-accent-foreground: var(--palette-white);\n --theme-support: var(--palette-cobalt);\n --theme-support-strong: var(--palette-ocean);\n --theme-support-soft: oklch(95.5% 0.02 225deg);\n --theme-display-gradient-start: var(--palette-steel-active);\n --theme-display-gradient-highlight: oklch(75% 0.08 225deg);\n --theme-display-gradient-end: var(--palette-ocean);\n}\n\n:root[data-accent='safety'] {\n --theme-accent: var(--palette-safety);\n --theme-accent-hover: var(--palette-safety-hover);\n --theme-accent-active: var(--palette-safety-active);\n --theme-accent-soft: oklch(96.5% 0.025 75deg);\n --theme-accent-border: oklch(86% 0.08 70deg);\n --theme-accent-foreground: var(--palette-ink-active);\n --theme-support: var(--palette-ocean);\n --theme-support-strong: var(--palette-steel);\n --theme-support-soft: oklch(95.5% 0.02 210deg);\n --theme-display-gradient-start: var(--palette-safety-active);\n --theme-display-gradient-highlight: oklch(79% 0.11 75deg);\n --theme-display-gradient-end: var(--palette-ocean);\n}\n\n:root[data-accent='ocean'] {\n --theme-accent: var(--palette-ocean);\n --theme-accent-hover: var(--palette-ocean-hover);\n --theme-accent-active: var(--palette-ocean-active);\n --theme-accent-soft: oklch(95.5% 0.02 210deg);\n --theme-accent-border: oklch(84% 0.055 210deg);\n --theme-accent-foreground: var(--palette-white);\n --theme-support: var(--palette-cyan);\n --theme-support-strong: var(--palette-steel);\n --theme-support-soft: oklch(95.5% 0.025 215deg);\n --theme-display-gradient-start: var(--palette-ocean-active);\n --theme-display-gradient-highlight: oklch(78% 0.1 210deg);\n --theme-display-gradient-end: var(--palette-cyan);\n}\n\n:root.dark {\n color-scheme: dark;\n\n --link-foreground: oklch(72% 0.12 265.67deg);\n --link-hover-foreground: oklch(78% 0.105 265.67deg);\n --theme-accent: oklch(92.88% 0.0126 255.51deg);\n --theme-accent-hover: oklch(86% 0.015 255.51deg);\n --theme-accent-active: oklch(78% 0.018 255.51deg);\n --theme-accent-soft: oklch(25.5% 0.018 257.42deg);\n --theme-accent-border: oklch(36% 0.02 257.42deg);\n --theme-accent-foreground: oklch(16% 0.02 264.66deg);\n --theme-support: oklch(72% 0.12 215.22deg);\n --theme-support-strong: oklch(72% 0.1 181.5deg);\n --theme-support-soft: oklch(25.5% 0.025 215.22deg);\n --theme-display-gradient-start: oklch(69% 0.02 257.42deg);\n --theme-display-gradient-highlight: oklch(96% 0.008 255.51deg);\n --theme-display-gradient-end: oklch(82% 0.014 255.51deg);\n --surface-canvas: oklch(14.5% 0.014 264.66deg);\n --surface-panel: oklch(17.8% 0.016 264.66deg);\n --surface-raised: oklch(21% 0.018 264.66deg);\n --surface-muted: oklch(24.5% 0.017 264.66deg);\n --surface-muted-foreground: var(--text-regular);\n --text-primary: oklch(95.5% 0.008 255.51deg);\n --text-regular: oklch(82% 0.014 255.51deg);\n --text-secondary: oklch(69% 0.02 257.42deg);\n --border-base: oklch(31% 0.018 257.42deg);\n --border-soft: oklch(25.5% 0.015 257.42deg);\n --border-input: oklch(38% 0.02 257.42deg);\n --ring-muted: oklch(55.1% 0.027 264.36deg);\n --semantic-success: oklch(74% 0.145 146.19deg);\n --semantic-success-soft: oklch(24% 0.045 146.19deg);\n --semantic-success-foreground: oklch(82% 0.12 146.19deg);\n --semantic-warning: oklch(82% 0.15 72.75deg);\n --semantic-warning-soft: oklch(25% 0.045 72.75deg);\n --semantic-warning-foreground: oklch(86% 0.12 72.75deg);\n --semantic-danger: oklch(70.4% 0.191 22.22deg);\n --semantic-danger-soft: oklch(25% 0.045 22.22deg);\n --semantic-danger-foreground: oklch(82% 0.14 22.22deg);\n}\n\n:root.dark[data-accent='cobalt'] {\n --theme-accent: oklch(67.5% 0.145 265.67deg);\n --theme-accent-hover: oklch(73% 0.125 265.67deg);\n --theme-accent-active: oklch(62% 0.135 265.67deg);\n --theme-accent-soft: oklch(25.5% 0.04 265.67deg);\n --theme-accent-border: oklch(42% 0.075 265.67deg);\n --theme-accent-foreground: oklch(16% 0.02 264.66deg);\n --theme-support: oklch(76% 0.11 215.22deg);\n --theme-support-strong: oklch(72% 0.1 181.5deg);\n --theme-support-soft: oklch(25.5% 0.04 215.22deg);\n --theme-display-gradient-start: oklch(62% 0.135 265.67deg);\n --theme-display-gradient-highlight: oklch(82% 0.095 265.67deg);\n --theme-display-gradient-end: oklch(70% 0.13 265.67deg);\n}\n\n:root.dark[data-accent='teal'] {\n --theme-accent: oklch(72% 0.12 181.5deg);\n --theme-accent-hover: oklch(78% 0.105 181.5deg);\n --theme-accent-active: oklch(65% 0.11 181.5deg);\n --theme-accent-soft: oklch(25.5% 0.035 181.5deg);\n --theme-accent-border: oklch(42% 0.065 181.5deg);\n --theme-accent-foreground: oklch(16% 0.02 264.66deg);\n --theme-support: oklch(76% 0.11 215.22deg);\n --theme-support-strong: oklch(72% 0.12 265.67deg);\n --theme-support-soft: oklch(25.5% 0.035 215.22deg);\n --theme-display-gradient-start: oklch(65% 0.11 181.5deg);\n --theme-display-gradient-highlight: oklch(84% 0.08 181.5deg);\n --theme-display-gradient-end: oklch(72% 0.12 181.5deg);\n}\n\n:root.dark[data-accent='steel'],\n:root.dark[data-accent='safety'],\n:root.dark[data-accent='ocean'] {\n --theme-accent-foreground: oklch(16% 0.02 264.66deg);\n --theme-accent-soft: color-mix(in oklch, var(--theme-accent) 22%, transparent);\n --theme-accent-border: color-mix(in oklch, var(--theme-accent) 48%, var(--border-base));\n --theme-support-soft: color-mix(in oklch, var(--theme-support) 22%, transparent);\n}\n\n:root.dark[data-accent='steel'] {\n --theme-accent: oklch(70% 0.075 245deg);\n --theme-accent-hover: oklch(77% 0.065 245deg);\n --theme-accent-active: oklch(62% 0.07 245deg);\n --theme-support: oklch(73% 0.1 210deg);\n --theme-support-strong: oklch(70% 0.08 210deg);\n}\n\n:root.dark[data-accent='safety'] {\n --theme-accent: oklch(76% 0.15 65deg);\n --theme-accent-hover: oklch(82% 0.12 65deg);\n --theme-accent-active: oklch(68% 0.14 65deg);\n --theme-support: oklch(73% 0.1 210deg);\n --theme-support-strong: oklch(70% 0.075 245deg);\n}\n\n:root.dark[data-accent='ocean'] {\n --theme-accent: oklch(72% 0.11 210deg);\n --theme-accent-hover: oklch(79% 0.095 210deg);\n --theme-accent-active: oklch(64% 0.105 210deg);\n --theme-support: oklch(76% 0.11 215.22deg);\n --theme-support-strong: oklch(70% 0.075 245deg);\n}\n","path":"src/styles/theme-tokens.css","target":"~/src/styles/theme-tokens.css","type":"registry:file"}],"meta":{"assetId":"styles.theme-tokens","contractRef":"vendor/design-system/src/theme-tokens.css","maturity":"candidate","releaseDigest":"f5db0c88ee95ccef50d6ced1f08e935c8c56006e337b978e332f0974b18d79b2","version":"0.1.0"},"name":"styles-theme-tokens","registryDependencies":[],"title":"styles.theme-tokens","type":"registry:block"},{"$schema":"https://ui.shadcn.com/schema/registry-item.json","dependencies":["tw-animate-css@1.4.0"],"description":"styles.styles","files":[{"content":"@import 'tw-animate-css';\n@import './theme-tokens.css';\n@custom-variant dark (&:is(.dark *));\n\n@theme inline {\n --color-background: var(--background);\n --color-foreground: var(--foreground);\n --color-link: var(--link-foreground);\n --color-link-hover: var(--link-hover-foreground);\n --color-card: var(--card);\n --color-card-foreground: var(--card-foreground);\n --color-popover: var(--popover);\n --color-popover-foreground: var(--popover-foreground);\n --color-primary: var(--primary);\n --color-primary-foreground: var(--primary-foreground);\n --color-secondary: var(--secondary);\n --color-secondary-foreground: var(--secondary-foreground);\n --color-muted: var(--muted);\n --color-muted-foreground: var(--muted-foreground);\n --color-accent: var(--accent);\n --color-accent-foreground: var(--accent-foreground);\n --color-destructive: var(--destructive);\n --color-destructive-foreground: var(--destructive-foreground);\n --color-border: var(--border);\n --color-input: var(--input);\n --color-ring: var(--ring);\n --color-brand: var(--brand-accent);\n --color-brand-foreground: var(--brand-accent-foreground);\n --color-brand-hover: var(--brand-accent-hover);\n --color-brand-active: var(--brand-accent-active);\n --color-brand-soft: var(--brand-accent-soft);\n --color-brand-support: var(--brand-support);\n --color-brand-support-strong: var(--brand-support-strong);\n --color-brand-support-soft: var(--brand-support-soft);\n --color-action: var(--action-primary);\n --color-action-hover: var(--action-primary-hover);\n --color-action-active: var(--action-primary-active);\n --color-action-foreground: var(--action-primary-foreground);\n --color-selection: var(--selection);\n --color-selection-foreground: var(--selection-foreground);\n --color-surface-muted: var(--surface-muted);\n --color-surface-muted-foreground: var(--surface-muted-foreground);\n --color-control-hover: var(--control-hover);\n --color-control-active: var(--control-active);\n --color-control-active-foreground: var(--control-active-foreground);\n --color-control-active-border: var(--control-active-border);\n --color-sidebar: var(--sidebar-background);\n --color-sidebar-foreground: var(--sidebar-foreground);\n --color-data-blue: var(--data-blue);\n --color-data-cyan: var(--data-cyan);\n --color-data-violet: var(--data-violet);\n --color-data-green: var(--data-green);\n --color-data-amber: var(--data-amber);\n --color-data-red: var(--data-red);\n --color-data-business: var(--data-business);\n --color-data-equipment: var(--data-equipment);\n --color-data-process: var(--data-process);\n --color-data-metric: var(--data-metric);\n --color-data-strategy: var(--data-strategy);\n --color-data-business-soft: var(--data-business-soft);\n --color-data-equipment-soft: var(--data-equipment-soft);\n --color-data-process-soft: var(--data-process-soft);\n --color-data-metric-soft: var(--data-metric-soft);\n --color-data-strategy-soft: var(--data-strategy-soft);\n --color-success: var(--semantic-success);\n --color-success-soft: var(--semantic-success-soft);\n --color-success-foreground: var(--semantic-success-foreground);\n --color-warning: var(--semantic-warning);\n --color-warning-soft: var(--semantic-warning-soft);\n --color-warning-foreground: var(--semantic-warning-foreground);\n --color-danger: var(--semantic-danger);\n --color-danger-soft: var(--semantic-danger-soft);\n --color-danger-foreground: var(--semantic-danger-foreground);\n --radius-sm: calc(var(--radius) - 4px);\n --radius-md: calc(var(--radius) - 2px);\n --radius-lg: var(--radius);\n --radius-xl: calc(var(--radius) + 4px);\n --color-border-soft: var(--border-soft);\n}\n\n/*\n * Match shadcn-admin: default border-color on all elements so width-only\n * utilities (border-b, border, etc.) resolve to --border instead of currentColor.\n */\n@layer base {\n * {\n @apply border-border outline-ring/50;\n }\n\n [data-sonner-toaster] [data-sonner-toast] {\n background: var(--card) !important;\n border-color: var(--border) !important;\n }\n\n [data-sonner-toaster] [data-sonner-toast][data-type='info'],\n [data-sonner-toaster] [data-sonner-toast][data-type='info'] [data-title],\n [data-sonner-toaster] [data-sonner-toast][data-type='info'] [data-content],\n [data-sonner-toaster] [data-sonner-toast]:not([data-type]),\n [data-sonner-toaster] [data-sonner-toast]:not([data-type]) [data-title],\n [data-sonner-toaster] [data-sonner-toast]:not([data-type]) [data-content] {\n color: var(--brand-accent) !important;\n }\n\n [data-sonner-toaster] [data-sonner-toast][data-type='success'],\n [data-sonner-toaster] [data-sonner-toast][data-type='success'] [data-title],\n [data-sonner-toaster] [data-sonner-toast][data-type='success'] [data-content] {\n color: var(--semantic-success) !important;\n }\n\n [data-sonner-toaster] [data-sonner-toast][data-type='warning'],\n [data-sonner-toaster] [data-sonner-toast][data-type='warning'] [data-title],\n [data-sonner-toaster] [data-sonner-toast][data-type='warning'] [data-content] {\n color: var(--semantic-warning) !important;\n }\n\n [data-sonner-toaster] [data-sonner-toast][data-type='error'],\n [data-sonner-toaster] [data-sonner-toast][data-type='error'] [data-title],\n [data-sonner-toaster] [data-sonner-toast][data-type='error'] [data-content] {\n color: var(--semantic-danger) !important;\n }\n\n [data-sonner-toaster] [data-sonner-toast] [data-description] {\n color: var(--muted-foreground) !important;\n }\n}\n","path":"src/styles/styles.css","target":"~/src/styles/styles.css","type":"registry:file"}],"meta":{"assetId":"styles.styles","contractRef":"vendor/design-system/src/styles.css","maturity":"candidate","releaseDigest":"f5db0c88ee95ccef50d6ced1f08e935c8c56006e337b978e332f0974b18d79b2","version":"0.1.0"},"name":"styles-styles","registryDependencies":["http://localhost:4318/f5db0c88ee95ccef50d6ced1f08e935c8c56006e337b978e332f0974b18d79b2/r/styles-theme-tokens.json"],"title":"styles.styles","type":"registry:block"},{"$schema":"https://ui.shadcn.com/schema/registry-item.json","dependencies":["react@19.2.8","class-variance-authority@0.7.1","radix-ui@1.6.7"],"description":"ui.badge","files":[{"content":"import * as React from \"react\";\n\nimport { type VariantProps, cva } from \"class-variance-authority\";\nimport { Slot } from \"radix-ui\";\n\nimport { cn } from \"../../lib/utils\";\n\nconst badgeVariants = cva(\n 'inline-flex w-fit shrink-0 items-center justify-center gap-1 overflow-hidden rounded-full border border-transparent px-2 py-0.5 text-xs font-medium whitespace-nowrap transition-[color,box-shadow] focus-visible:border-ring focus-visible:ring-[3px] focus-visible:ring-ring/50 aria-invalid:border-destructive aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 [&>svg]:pointer-events-none [&>svg]:size-3',\n {\n variants: {\n variant: {\n default: 'bg-action text-action-foreground [a&]:hover:bg-action-hover',\n secondary: 'bg-secondary text-secondary-foreground [a&]:hover:bg-secondary/90',\n destructive:\n 'bg-destructive text-destructive-foreground focus-visible:ring-destructive/20 dark:focus-visible:ring-destructive/40 [a&]:hover:bg-destructive/90',\n outline:\n 'border-border text-foreground [a&]:hover:bg-control-hover [a&]:hover:text-foreground',\n ghost: '[a&]:hover:bg-control-hover [a&]:hover:text-foreground',\n link: 'text-brand underline-offset-4 [a&]:hover:text-brand-hover [a&]:hover:underline',\n success: 'bg-success-soft text-success-foreground',\n warning: 'bg-warning-soft text-warning-foreground',\n danger: 'bg-danger-soft text-danger-foreground',\n neutral: 'bg-secondary text-secondary-foreground',\n },\n },\n defaultVariants: {\n variant: 'default',\n },\n },\n);\n\nfunction Badge({\n className,\n variant = 'default',\n asChild = false,\n ...props\n}: React.ComponentProps<'span'> & VariantProps<typeof badgeVariants> & { asChild?: boolean }) {\n const Comp = asChild ? Slot.Root : 'span';\n\n return (\n <Comp\n data-slot=\"badge\"\n data-variant={variant}\n className={cn(badgeVariants({ variant }), className)}\n {...props}\n />\n );\n}\n\nexport { Badge, badgeVariants };\n","path":"src/components/ui/badge.tsx","target":"~/src/components/ui/badge.tsx","type":"registry:file"}],"meta":{"assetId":"ui.badge","contractRef":"vendor/design-system/src/components/ui/badge.tsx","maturity":"candidate","releaseDigest":"f5db0c88ee95ccef50d6ced1f08e935c8c56006e337b978e332f0974b18d79b2","version":"0.1.0"},"name":"ui-badge","registryDependencies":["http://localhost:4318/f5db0c88ee95ccef50d6ced1f08e935c8c56006e337b978e332f0974b18d79b2/r/lib-utils.json"],"title":"ui.badge","type":"registry:block"},{"$schema":"https://ui.shadcn.com/schema/registry-item.json","dependencies":["react@19.2.8","class-variance-authority@0.7.1","radix-ui@1.6.7"],"description":"ui.button","files":[{"content":"import * as React from \"react\";\n\nimport { type VariantProps, cva } from \"class-variance-authority\";\nimport { Slot } from \"radix-ui\";\n\nimport { cn } from \"../../lib/utils\";\n\nconst buttonVariants = cva(\n \"inline-flex shrink-0 cursor-pointer items-center justify-center gap-2 rounded-md text-sm font-medium whitespace-nowrap transition-[color,background-color,border-color,box-shadow,transform,opacity] outline-none focus-visible:border-ring focus-visible:ring-[3px] focus-visible:ring-ring/50 active:translate-y-px disabled:pointer-events-none disabled:cursor-not-allowed disabled:translate-y-0 disabled:opacity-50 aria-invalid:border-destructive aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4\",\n {\n variants: {\n variant: {\n default: 'bg-action text-action-foreground hover:bg-action-hover active:bg-action-active',\n destructive:\n 'bg-destructive text-destructive-foreground hover:bg-destructive/90 focus-visible:ring-destructive/20 dark:focus-visible:ring-destructive/40',\n outline:\n 'border border-border bg-transparent text-foreground shadow-xs hover:bg-muted/60 hover:text-foreground active:bg-muted/80',\n secondary:\n 'border border-border bg-transparent text-brand hover:border-border hover:bg-brand-soft hover:text-brand-hover active:border-border active:bg-brand-soft/80 active:text-brand-active',\n ghost:\n 'border border-transparent bg-transparent text-brand hover:border-transparent hover:bg-brand-soft hover:text-brand-hover active:border-transparent active:bg-brand-soft/80 active:text-brand-active',\n 'ghost-neutral':\n 'border border-transparent bg-transparent text-muted-foreground hover:border-transparent hover:bg-control-hover hover:text-foreground active:border-transparent active:bg-control-hover active:text-foreground',\n link: 'text-brand underline-offset-4 hover:text-brand-hover hover:underline',\n },\n size: {\n default: 'h-9 px-4 py-2 has-[>svg]:px-3',\n xs: \"h-6 gap-1 rounded-md px-2 text-xs has-[>svg]:px-1.5 [&_svg:not([class*='size-'])]:size-3\",\n sm: 'h-8 gap-1.5 rounded-md px-3 text-xs has-[>svg]:px-2.5',\n lg: 'h-10 rounded-md px-6 has-[>svg]:px-4',\n icon: 'size-9',\n 'icon-xs': \"size-6 rounded-md [&_svg:not([class*='size-'])]:size-3\",\n 'icon-sm': 'size-8',\n 'icon-lg': 'size-10',\n },\n },\n defaultVariants: {\n variant: 'default',\n size: 'default',\n },\n },\n);\n\nfunction Button({\n className,\n variant = 'default',\n size = 'default',\n asChild = false,\n ...props\n}: React.ComponentProps<'button'> &\n VariantProps<typeof buttonVariants> & {\n asChild?: boolean;\n }) {\n const Comp = asChild ? Slot.Root : 'button';\n\n return (\n <Comp\n data-slot=\"button\"\n data-variant={variant}\n data-size={size}\n className={cn(buttonVariants({ variant, size, className }))}\n {...props}\n />\n );\n}\n\nexport { Button, buttonVariants };\n","path":"src/components/ui/button.tsx","target":"~/src/components/ui/button.tsx","type":"registry:file"}],"meta":{"assetId":"ui.button","contractRef":"vendor/design-system/src/components/ui/button.tsx","maturity":"candidate","releaseDigest":"f5db0c88ee95ccef50d6ced1f08e935c8c56006e337b978e332f0974b18d79b2","version":"0.1.0"},"name":"ui-button","registryDependencies":["http://localhost:4318/f5db0c88ee95ccef50d6ced1f08e935c8c56006e337b978e332f0974b18d79b2/r/lib-utils.json"],"title":"ui.button","type":"registry:block"},{"$schema":"https://ui.shadcn.com/schema/registry-item.json","dependencies":["radix-ui@1.6.7"],"description":"ui.collapsible","files":[{"content":"import { Collapsible as CollapsiblePrimitive } from \"radix-ui\";\n\nfunction Collapsible({ ...props }: React.ComponentProps<typeof CollapsiblePrimitive.Root>) {\n return <CollapsiblePrimitive.Root data-slot=\"collapsible\" {...props} />;\n}\n\nfunction CollapsibleTrigger({\n ...props\n}: React.ComponentProps<typeof CollapsiblePrimitive.CollapsibleTrigger>) {\n return <CollapsiblePrimitive.CollapsibleTrigger data-slot=\"collapsible-trigger\" {...props} />;\n}\n\nfunction CollapsibleContent({\n ...props\n}: React.ComponentProps<typeof CollapsiblePrimitive.CollapsibleContent>) {\n return <CollapsiblePrimitive.CollapsibleContent data-slot=\"collapsible-content\" {...props} />;\n}\n\nexport { Collapsible, CollapsibleTrigger, CollapsibleContent };\n","path":"src/components/ui/collapsible.tsx","target":"~/src/components/ui/collapsible.tsx","type":"registry:file"}],"meta":{"assetId":"ui.collapsible","contractRef":"vendor/design-system/src/components/ui/collapsible.tsx","maturity":"candidate","releaseDigest":"f5db0c88ee95ccef50d6ced1f08e935c8c56006e337b978e332f0974b18d79b2","version":"0.1.0"},"name":"ui-collapsible","registryDependencies":[],"title":"ui.collapsible","type":"registry:block"},{"$schema":"https://ui.shadcn.com/schema/registry-item.json","dependencies":["react@19.2.8"],"description":"common.semantic-region-scaffold","files":[{"content":"import \"../../../styles/styles.css\";\nimport { type ReactNode, useId } from \"react\";\n\nimport { Badge } from \"../../ui/badge\";\nimport { Button } from \"../../ui/button\";\nimport {\n Collapsible,\n CollapsibleContent,\n CollapsibleTrigger,\n} from \"../../ui/collapsible\";\nimport { cn } from \"../../../lib/utils\";\n\nimport type { SemanticAction, SemanticRegionContract } from \"./contract\";\n\nexport interface SemanticRegionScaffoldProps {\n contract: SemanticRegionContract;\n commands?: { onAction(action: SemanticAction): void };\n slots?: { authoringActions?: ReactNode };\n className?: string;\n}\nfunction DetailList({ title, items }: { title: string; items: readonly string[] }) {\n return (\n <div className=\"space-y-2\">\n <h3 className=\"font-medium text-foreground\">{title}</h3>\n {items.length ? (\n <ul className=\"space-y-1 text-muted-foreground\">\n {items.map((item, i) => (\n <li key={i}>{item}</li>\n ))}\n </ul>\n ) : (\n <p className=\"text-muted-foreground\">尚未确定</p>\n )}\n </div>\n );\n}\nexport function SemanticRegionScaffold({\n contract,\n commands,\n slots,\n className,\n}: SemanticRegionScaffoldProps) {\n const titleId = useId();\n return (\n <section\n aria-labelledby={titleId}\n data-region-id={contract.id}\n data-region-implementation=\"scaffold\"\n className={cn(\n 'min-w-0 rounded-lg border border-dashed border-border bg-card p-5 text-sm text-foreground',\n className,\n )}\n >\n <div className=\"flex flex-wrap items-start justify-between gap-3\">\n <div className=\"min-w-0 space-y-2\">\n <div className=\"flex flex-wrap items-center gap-3\">\n <h2 id={titleId} className=\"text-base font-semibold\">\n {contract.title}\n </h2>\n <Badge variant=\"outline\">待打造</Badge>\n </div>\n <p className=\"max-w-3xl leading-relaxed text-muted-foreground\">\n {contract.responsibility}\n </p>\n </div>\n {slots?.authoringActions}\n </div>\n <div className=\"mt-4 flex flex-wrap gap-x-5 gap-y-2 text-muted-foreground\">\n <span>{contract.progress.binding === 'ready' ? '绑定已确认' : '数据待绑定'}</span>\n <span>{contract.progress.design === 'confirmed' ? '设计已确认' : '设计待确认'}</span>\n </div>\n {contract.actions.length ? (\n <div className=\"mt-5 grid gap-3 sm:grid-cols-2\">\n {contract.actions.map((action) => {\n const reason = !action.enabled\n ? action.blockedReason\n : !commands?.onAction\n ? '尚未接入操作处理'\n : undefined;\n return (\n <div key={action.id} className=\"space-y-2\">\n <Button\n type=\"button\"\n variant=\"outline\"\n data-action-id={action.id}\n disabled={Boolean(reason)}\n onClick={() => {\n if (!reason) commands?.onAction(action);\n }}\n >\n {action.label}\n </Button>\n <p className=\"text-xs leading-relaxed text-muted-foreground\">\n {reason ?? action.result}\n </p>\n </div>\n );\n })}\n </div>\n ) : null}\n <Collapsible className=\"mt-5 border-t border-border pt-3\">\n <CollapsibleTrigger asChild>\n <Button type=\"button\" variant=\"ghost-neutral\">\n 查看区域设计详情\n </Button>\n </CollapsibleTrigger>\n <CollapsibleContent className=\"pt-4\">\n <div className=\"grid gap-6 sm:grid-cols-2\">\n <DetailList title=\"输入与预期结果\" items={[...contract.inputs, ...contract.outputs]} />\n <DetailList\n title=\"数据指向\"\n items={contract.bindings.map(\n (b) =>\n `${b.label}:${b.logicalTarget}(${b.status === 'confirmed' ? '已确认' : b.status === 'deferred' ? '已暂缓' : '待确认'})`,\n )}\n />\n <DetailList\n title=\"业务状态与导航\"\n items={[...contract.businessStates, ...contract.navigation]}\n />\n <DetailList\n title=\"后续替换契约\"\n items={[\n ...contract.replacement.inputs.map((x) => `输入:${x}`),\n ...contract.replacement.events.map((x) => `事件:${x}`),\n `状态归属:${contract.replacement.stateOwner}`,\n ]}\n />\n <DetailList\n title=\"操作要求\"\n items={contract.actions.map(\n (a) => `${a.label}:${a.preconditions.join(';') || '前置待确认'};${a.feedback}`,\n )}\n />\n <DetailList\n title=\"待确认问题\"\n items={contract.questions.map(\n (q) => `${q.question}${q.answer ? `:${q.answer}` : ''}`,\n )}\n />\n <DetailList\n title=\"本体来源\"\n items={contract.sourceRefs.map(\n (s) => `${s.ref}${s.version ? ` · ${s.version}` : ' · 版本待核验'}`,\n )}\n />\n </div>\n </CollapsibleContent>\n </Collapsible>\n </section>\n );\n}\n","path":"src/components/common/semantic-region/semantic-region-scaffold.tsx","target":"~/src/components/common/semantic-region/semantic-region-scaffold.tsx","type":"registry:file"}],"meta":{"assetId":"common.semantic-region-scaffold","contractRef":"layout/src/semantic-region/semantic-region-scaffold.tsx","maturity":"candidate","releaseDigest":"f5db0c88ee95ccef50d6ced1f08e935c8c56006e337b978e332f0974b18d79b2","version":"0.1.0"},"name":"common-semantic-region-scaffold","registryDependencies":["http://localhost:4318/f5db0c88ee95ccef50d6ced1f08e935c8c56006e337b978e332f0974b18d79b2/r/components-common-semantic-region-contract.json","http://localhost:4318/f5db0c88ee95ccef50d6ced1f08e935c8c56006e337b978e332f0974b18d79b2/r/lib-utils.json","http://localhost:4318/f5db0c88ee95ccef50d6ced1f08e935c8c56006e337b978e332f0974b18d79b2/r/styles-styles.json","http://localhost:4318/f5db0c88ee95ccef50d6ced1f08e935c8c56006e337b978e332f0974b18d79b2/r/ui-badge.json","http://localhost:4318/f5db0c88ee95ccef50d6ced1f08e935c8c56006e337b978e332f0974b18d79b2/r/ui-button.json","http://localhost:4318/f5db0c88ee95ccef50d6ced1f08e935c8c56006e337b978e332f0974b18d79b2/r/ui-collapsible.json"],"title":"common.semantic-region-scaffold","type":"registry:block"},{"$schema":"https://ui.shadcn.com/schema/registry-item.json","dependencies":[],"description":"components.business.role-tasks.icons","files":[{"content":"const paths = {\n clipboard:\n 'M9 5H6a2 2 0 0 0-2 2v13a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7a2 2 0 0 0-2-2h-3 M9 3h6v4H9z',\n document: 'M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z M14 2v6h6 M8 13h8 M8 17h6',\n check:\n 'M9 5H6a2 2 0 0 0-2 2v13a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7a2 2 0 0 0-2-2h-3 M9 3h6v4H9z M8 14l3 3 5-6',\n play: 'M10 8l6 4-6 4z M22 12a10 10 0 1 1-20 0 10 10 0 0 1 20 0',\n query: 'M5 3h14v18H5z M9 7h6 M9 11h6 M9 15h3',\n alert: 'M12 8v5 M12 17h.01 M22 12a10 10 0 1 1-20 0 10 10 0 0 1 20 0',\n history: 'M3 3v6h6 M3 9a9 9 0 1 1 0 6 M12 7v5l3 2',\n database:\n 'M20 6c0 2-4 3-8 3S4 8 4 6s4-3 8-3 8 1 8 3z M4 6v12c0 2 4 3 8 3s8-1 8-3V6 M4 12c0 2 4 3 8 3s8-1 8-3',\n folder: 'M3 7V5a2 2 0 0 1 2-2h5l2 3h7a2 2 0 0 1 2 2v11a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2z',\n target: 'M21 12a9 9 0 1 1-9-9 M17 12a5 5 0 1 1-5-5 M12 12l9-9 M16 3h5v5',\n arrowRight: 'M5 12h14 M13 6l6 6-6 6',\n arrowUpRight: 'M7 17 17 7 M7 7h10v10',\n arrowLeft: 'M19 12H5 M11 6l-6 6 6 6',\n};\n\nexport function RoleTaskIcon({\n name,\n className = 'size-4',\n}: {\n name: keyof typeof paths;\n className?: string;\n}) {\n return (\n <svg\n aria-hidden=\"true\"\n className={className}\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"1.8\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n >\n <path d={paths[name]} />\n </svg>\n );\n}\n","path":"src/components/business/role-tasks/icons.tsx","target":"~/src/components/business/role-tasks/icons.tsx","type":"registry:file"}],"meta":{"assetId":"components.business.role-tasks.icons","contractRef":"business/quality/src/role-tasks/icons.tsx","maturity":"candidate","releaseDigest":"f5db0c88ee95ccef50d6ced1f08e935c8c56006e337b978e332f0974b18d79b2","version":"0.1.0"},"name":"components-business-role-tasks-icons","registryDependencies":[],"title":"components.business.role-tasks.icons","type":"registry:block"},{"$schema":"https://ui.shadcn.com/schema/registry-item.json","dependencies":["react@19.2.8"],"description":"components.business.role-tasks.types","files":[{"content":"import type { ReactNode } from \"react\";\n\nexport interface RoleTaskAction {\n onSelect: () => void;\n disabled?: boolean;\n}\n\nexport interface RoleTaskOverviewProps {\n model: {\n stageName: string;\n stageDescription: string;\n roleLabel: string;\n taskCount: number | null;\n relatedItemCount: number | null;\n goal: string;\n workItemCount?: number | null;\n icon?: ReactNode;\n scopeLabel?: string;\n };\n commands?: {\n onViewValue?: RoleTaskAction;\n onViewWorkItems?: RoleTaskAction;\n };\n}\n\nexport interface RoleTask {\n id: string;\n title: string;\n typeLabel: string;\n description: string;\n icon?: ReactNode;\n relatedItemCount: number | null;\n pendingItemCount: number | null;\n pendingActionTone?: 'primary' | 'accent' | 'neutral';\n iconTone?: 'brand' | 'support' | 'warning';\n viewPendingDisabled?: boolean;\n openTaskDisabled?: boolean;\n}\n\nexport interface RoleTaskGroup {\n id: string;\n title: string;\n description: string;\n tasks: readonly RoleTask[];\n}\n\nexport interface RoleTaskGroupsProps {\n groups: readonly RoleTaskGroup[];\n commands: {\n onViewPendingItems: (task: RoleTask, group: RoleTaskGroup) => void;\n onOpenTask: (task: RoleTask, group: RoleTaskGroup) => void;\n };\n}\n","path":"src/components/business/role-tasks/types.ts","target":"~/src/components/business/role-tasks/types.ts","type":"registry:file"}],"meta":{"assetId":"components.business.role-tasks.types","contractRef":"business/quality/src/role-tasks/types.ts","maturity":"candidate","releaseDigest":"f5db0c88ee95ccef50d6ced1f08e935c8c56006e337b978e332f0974b18d79b2","version":"0.1.0"},"name":"components-business-role-tasks-types","registryDependencies":[],"title":"components.business.role-tasks.types","type":"registry:block"},{"$schema":"https://ui.shadcn.com/schema/registry-item.json","dependencies":["react@19.2.8","class-variance-authority@0.7.1"],"description":"ui.empty","files":[{"content":"import type { ComponentProps } from \"react\";\n\nimport { type VariantProps, cva } from \"class-variance-authority\";\n\nimport { cn } from \"../../lib/utils\";\n\nfunction Empty({ className, ...props }: ComponentProps<'div'>) {\n return (\n <div\n data-slot=\"empty\"\n className={cn(\n 'flex min-w-0 flex-1 flex-col items-center justify-center gap-6 rounded-lg border-dashed p-6 text-center text-balance md:p-12',\n className,\n )}\n {...props}\n />\n );\n}\n\nfunction EmptyHeader({ className, ...props }: ComponentProps<'div'>) {\n return (\n <div\n data-slot=\"empty-header\"\n className={cn('flex max-w-sm flex-col items-center gap-2 text-center', className)}\n {...props}\n />\n );\n}\n\nconst emptyMediaVariants = cva(\n 'mb-2 flex shrink-0 items-center justify-center [&_svg]:pointer-events-none [&_svg]:shrink-0',\n {\n variants: {\n variant: {\n default: 'bg-transparent',\n icon: \"flex size-10 shrink-0 items-center justify-center rounded-lg bg-muted text-foreground [&_svg:not([class*='size-'])]:size-6\",\n },\n },\n defaultVariants: {\n variant: 'default',\n },\n },\n);\n\nfunction EmptyMedia({\n className,\n variant = 'default',\n ...props\n}: ComponentProps<'div'> & VariantProps<typeof emptyMediaVariants>) {\n return (\n <div\n data-slot=\"empty-icon\"\n data-variant={variant}\n className={cn(emptyMediaVariants({ variant, className }))}\n {...props}\n />\n );\n}\n\nfunction EmptyTitle({ className, ...props }: ComponentProps<'div'>) {\n return (\n <div\n data-slot=\"empty-title\"\n className={cn('text-lg font-medium tracking-tight', className)}\n {...props}\n />\n );\n}\n\nfunction EmptyDescription({ className, ...props }: ComponentProps<'p'>) {\n return (\n <div\n data-slot=\"empty-description\"\n className={cn(\n 'text-sm/relaxed text-muted-foreground [&>a]:underline [&>a]:underline-offset-4 [&>a:hover]:text-brand',\n className,\n )}\n {...props}\n />\n );\n}\n\nfunction EmptyContent({ className, ...props }: ComponentProps<'div'>) {\n return (\n <div\n data-slot=\"empty-content\"\n className={cn(\n 'flex w-full max-w-sm min-w-0 flex-col items-center gap-4 text-sm text-balance',\n className,\n )}\n {...props}\n />\n );\n}\n\nexport { Empty, EmptyHeader, EmptyTitle, EmptyDescription, EmptyContent, EmptyMedia };\n","path":"src/components/ui/empty.tsx","target":"~/src/components/ui/empty.tsx","type":"registry:file"}],"meta":{"assetId":"ui.empty","contractRef":"vendor/design-system/src/components/ui/empty.tsx","maturity":"candidate","releaseDigest":"f5db0c88ee95ccef50d6ced1f08e935c8c56006e337b978e332f0974b18d79b2","version":"0.1.0"},"name":"ui-empty","registryDependencies":["http://localhost:4318/f5db0c88ee95ccef50d6ced1f08e935c8c56006e337b978e332f0974b18d79b2/r/lib-utils.json"],"title":"ui.empty","type":"registry:block"},{"$schema":"https://ui.shadcn.com/schema/registry-item.json","dependencies":["react@19.2.8"],"description":"quality.role-task-groups","files":[{"content":"import \"../../../styles/styles.css\";\nimport { useId } from \"react\";\n\nimport { Badge } from \"../../ui/badge\";\nimport { Button } from \"../../ui/button\";\nimport { Empty, EmptyTitle } from \"../../ui/empty\";\n\nimport { RoleTaskIcon } from \"./icons\";\nimport type { RoleTask, RoleTaskGroupsProps } from \"./types\";\n\nexport type { RoleTaskGroupsProps } from \"./types\";\n\ntype PendingTone = 'primary' | 'accent' | 'neutral';\n\nfunction resolvePendingTone(task: RoleTask): PendingTone {\n if (task.pendingActionTone) return task.pendingActionTone;\n if (task.pendingItemCount !== null && task.pendingItemCount > 1) return 'primary';\n if (task.pendingItemCount === 1) return 'accent';\n return 'neutral';\n}\n\nconst pendingButtonClass: Record<PendingTone, string> = {\n primary:\n 'bg-link font-semibold text-action-foreground hover:bg-link-hover hover:text-action-foreground',\n accent:\n 'border-link bg-transparent font-semibold text-link shadow-none hover:bg-muted hover:text-link',\n neutral:\n 'border-border bg-muted/40 font-semibold text-muted-foreground shadow-none hover:bg-muted hover:text-muted-foreground',\n};\n\nexport function RoleTaskGroups({ groups, commands }: RoleTaskGroupsProps) {\n const prefix = useId();\n if (groups.length === 0)\n return (\n <Empty>\n <EmptyTitle className=\"text-sm\">暂无岗位任务</EmptyTitle>\n </Empty>\n );\n return (\n <div className=\"space-y-7\">\n {groups.map((group, index) => (\n <section key={group.id} aria-labelledby={`${prefix}-${index}`}>\n <div className=\"mb-2.5 flex flex-wrap items-baseline gap-x-5 gap-y-1\">\n <h2\n id={`${prefix}-${index}`}\n className=\"text-lg leading-7 font-semibold text-foreground\"\n >\n {group.title}\n </h2>\n <p className=\"text-sm text-muted-foreground\">\n <span className=\"tabular-nums\">{group.tasks.length}</span> 项任务 ·{' '}\n {group.description}\n </p>\n </div>\n {group.tasks.length === 0 ? (\n <Empty>\n <EmptyTitle className=\"text-sm\">此分组暂无岗位任务</EmptyTitle>\n </Empty>\n ) : (\n <div className=\"grid grid-cols-1 gap-2.5 md:grid-cols-2\">\n {group.tasks.map((task) => {\n const pendingTone = resolvePendingTone(task);\n return (\n <article\n key={task.id}\n aria-label={task.title}\n className=\"flex min-w-0 flex-col rounded-xl border border-border bg-card px-5 py-4 shadow-2xs\"\n >\n <div className=\"flex items-start gap-5\">\n {task.icon ? (\n <span\n aria-hidden=\"true\"\n className={`flex size-11 shrink-0 items-center justify-center rounded-lg [&_svg]:size-5 ${task.iconTone === 'support' ? 'bg-brand-support-soft text-brand-support-strong' : task.iconTone === 'warning' ? 'bg-warning-soft text-warning-foreground' : 'bg-link/10 text-link'}`}\n >\n {task.icon}\n </span>\n ) : null}\n <div className=\"min-w-0 flex-1\">\n <div className=\"flex flex-wrap items-center justify-between gap-2\">\n <Badge\n variant=\"secondary\"\n className=\"h-6 rounded-md bg-muted px-2 py-0.5 text-xs font-medium text-muted-foreground\"\n >\n {task.typeLabel}\n </Badge>\n <p className=\"text-sm text-muted-foreground\">\n 关联事项{' '}\n <span\n className={`ml-1.5 text-lg leading-7 font-semibold tabular-nums ${task.relatedItemCount !== null && task.relatedItemCount > 0 ? 'text-foreground' : 'text-muted-foreground'}`}\n >\n {task.relatedItemCount ?? '—'}\n </span>\n </p>\n </div>\n <h3 className=\"mt-2 text-base leading-6 font-semibold text-foreground\">\n {task.title}\n </h3>\n <p className=\"mt-1 break-words text-sm leading-5 text-muted-foreground\">\n {task.description}\n </p>\n </div>\n </div>\n <div className=\"mt-auto flex flex-wrap items-center justify-between gap-2 pt-3\">\n <Button\n type=\"button\"\n variant={pendingTone === 'primary' ? 'default' : 'outline'}\n className={pendingButtonClass[pendingTone]}\n disabled={task.viewPendingDisabled}\n onClick={() => commands.onViewPendingItems(task, group)}\n aria-label={`${task.title}:查看待办事项(${task.pendingItemCount ?? '—'})`}\n >\n <span>\n 查看待办事项{' '}\n <span className=\"tabular-nums\">({task.pendingItemCount ?? '—'})</span>\n </span>\n </Button>\n <Button\n type=\"button\"\n variant=\"ghost-neutral\"\n className=\"h-9 gap-1.5 px-0 text-sm font-medium hover:bg-transparent has-[>svg]:px-0\"\n disabled={task.openTaskDisabled}\n onClick={() => commands.onOpenTask(task, group)}\n aria-label={`${task.title}:打开任务界面`}\n >\n 打开任务界面 <RoleTaskIcon name=\"arrowUpRight\" />\n </Button>\n </div>\n </article>\n );\n })}\n </div>\n )}\n </section>\n ))}\n </div>\n );\n}\n","path":"src/components/business/role-tasks/role-task-groups.tsx","target":"~/src/components/business/role-tasks/role-task-groups.tsx","type":"registry:file"}],"meta":{"assetId":"quality.role-task-groups","contractRef":"business/quality/src/role-tasks/role-task-groups.tsx","maturity":"candidate","releaseDigest":"f5db0c88ee95ccef50d6ced1f08e935c8c56006e337b978e332f0974b18d79b2","version":"0.1.0"},"name":"quality-role-task-groups","registryDependencies":["http://localhost:4318/f5db0c88ee95ccef50d6ced1f08e935c8c56006e337b978e332f0974b18d79b2/r/components-business-role-tasks-icons.json","http://localhost:4318/f5db0c88ee95ccef50d6ced1f08e935c8c56006e337b978e332f0974b18d79b2/r/components-business-role-tasks-types.json","http://localhost:4318/f5db0c88ee95ccef50d6ced1f08e935c8c56006e337b978e332f0974b18d79b2/r/styles-styles.json","http://localhost:4318/f5db0c88ee95ccef50d6ced1f08e935c8c56006e337b978e332f0974b18d79b2/r/ui-badge.json","http://localhost:4318/f5db0c88ee95ccef50d6ced1f08e935c8c56006e337b978e332f0974b18d79b2/r/ui-button.json","http://localhost:4318/f5db0c88ee95ccef50d6ced1f08e935c8c56006e337b978e332f0974b18d79b2/r/ui-empty.json"],"title":"quality.role-task-groups","type":"registry:block"},{"$schema":"https://ui.shadcn.com/schema/registry-item.json","dependencies":["react@19.2.8"],"description":"quality.role-task-overview","files":[{"content":"import \"../../../styles/styles.css\";\nimport { useId } from \"react\";\n\nimport { Button } from \"../../ui/button\";\n\nimport { RoleTaskIcon } from \"./icons\";\nimport type { RoleTaskOverviewProps } from \"./types\";\n\nexport type { RoleTaskOverviewProps } from \"./types\";\n\nexport function RoleTaskOverview({ model, commands }: RoleTaskOverviewProps) {\n const titleId = useId();\n return (\n <section aria-labelledby={titleId} className=\"space-y-5\">\n <div className=\"rounded-2xl border border-border bg-card px-5 py-4 shadow-2xs\">\n <div className=\"flex flex-col gap-4 lg:flex-row lg:items-center lg:justify-between lg:gap-8\">\n <div className=\"flex min-w-0 items-center gap-4\">\n {model.icon ? (\n <span\n aria-hidden=\"true\"\n className=\"flex size-12 shrink-0 items-center justify-center rounded-lg bg-link/10 text-link [&_svg]:size-6\"\n >\n {model.icon}\n </span>\n ) : null}\n <div className=\"min-w-0\">\n <h2 id={titleId} className=\"text-[22px] leading-8 font-semibold text-foreground\">\n {model.stageName}\n </h2>\n <p className=\"mt-0.5 text-sm leading-5 text-muted-foreground\">\n {model.stageDescription}\n </p>\n </div>\n </div>\n <dl className=\"flex shrink-0 flex-wrap items-center gap-y-2 text-sm [&>div]:mr-4 [&>div]:border-r [&>div]:border-border [&>div]:pr-4 [&>div:last-of-type]:mr-0 [&>div:last-of-type]:border-r-0 [&>div:last-of-type]:pr-0\">\n <div className=\"flex items-center gap-2\">\n <dt className=\"text-muted-foreground\">当前角色</dt>\n <dd className=\"font-semibold text-foreground\">{model.roleLabel}</dd>\n </div>\n <div className=\"flex items-center gap-2\">\n <dt className=\"text-muted-foreground\">岗位任务</dt>\n <dd className=\"font-semibold tabular-nums text-foreground\">\n {model.taskCount ?? '—'} 项\n </dd>\n </div>\n <div className=\"flex items-center gap-2\">\n <dt className=\"text-muted-foreground\">关联事项</dt>\n <dd className=\"font-semibold tabular-nums text-foreground\">\n {model.relatedItemCount ?? '—'} 项\n </dd>\n </div>\n {model.scopeLabel ? (\n <div className=\"text-muted-foreground\">\n <dt className=\"sr-only\">统计范围</dt>\n <dd>{model.scopeLabel}</dd>\n </div>\n ) : null}\n </dl>\n </div>\n </div>\n <div className=\"flex min-h-12 flex-wrap items-center justify-between gap-3 rounded-xl border border-link/20 bg-link/10 px-4 py-2\">\n <p className=\"flex min-w-0 items-center gap-3 text-sm text-foreground\">\n <span\n aria-hidden=\"true\"\n className=\"flex size-8 shrink-0 items-center justify-center rounded-full bg-card text-link\"\n >\n <RoleTaskIcon name=\"target\" className=\"size-4\" />\n </span>\n <span>\n <span className=\"font-semibold\">岗位目标:</span>\n <span className=\"text-muted-foreground\">{model.goal}</span>\n </span>\n </p>\n <div className=\"flex flex-wrap items-center\">\n {commands?.onViewValue ? (\n <Button\n type=\"button\"\n variant=\"ghost\"\n className=\"h-9 gap-1 rounded-none px-3 text-sm font-medium text-link hover:bg-transparent hover:text-link-hover\"\n disabled={commands.onViewValue.disabled}\n onClick={commands.onViewValue.onSelect}\n >\n 查看业务价值关联 <RoleTaskIcon name=\"arrowUpRight\" />\n </Button>\n ) : null}\n {commands?.onViewValue && commands?.onViewWorkItems ? (\n <span aria-hidden=\"true\" className=\"h-4 w-px bg-border\" />\n ) : null}\n {commands?.onViewWorkItems ? (\n <Button\n type=\"button\"\n variant=\"ghost\"\n className=\"h-9 gap-1 rounded-none px-3 text-sm font-medium text-link hover:bg-transparent hover:text-link-hover\"\n disabled={commands.onViewWorkItems.disabled}\n onClick={commands.onViewWorkItems.onSelect}\n >\n <span>\n 我的处理事项\n {model.workItemCount !== undefined ? (\n <span className=\"tabular-nums\"> ({model.workItemCount ?? '—'})</span>\n ) : null}\n </span>\n <RoleTaskIcon name=\"arrowRight\" />\n </Button>\n ) : null}\n </div>\n </div>\n </section>\n );\n}\n","path":"src/components/business/role-tasks/role-task-overview.tsx","target":"~/src/components/business/role-tasks/role-task-overview.tsx","type":"registry:file"}],"meta":{"assetId":"quality.role-task-overview","contractRef":"business/quality/src/role-tasks/role-task-overview.tsx","maturity":"candidate","releaseDigest":"f5db0c88ee95ccef50d6ced1f08e935c8c56006e337b978e332f0974b18d79b2","version":"0.1.0"},"name":"quality-role-task-overview","registryDependencies":["http://localhost:4318/f5db0c88ee95ccef50d6ced1f08e935c8c56006e337b978e332f0974b18d79b2/r/components-business-role-tasks-icons.json","http://localhost:4318/f5db0c88ee95ccef50d6ced1f08e935c8c56006e337b978e332f0974b18d79b2/r/components-business-role-tasks-types.json","http://localhost:4318/f5db0c88ee95ccef50d6ced1f08e935c8c56006e337b978e332f0974b18d79b2/r/styles-styles.json","http://localhost:4318/f5db0c88ee95ccef50d6ced1f08e935c8c56006e337b978e332f0974b18d79b2/r/ui-button.json"],"title":"quality.role-task-overview","type":"registry:block"}],"name":"metaform"}
|