@utopia-studio-design/design-system-cli 0.4.1 → 0.6.0

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.
Files changed (126) hide show
  1. package/README.md +23 -0
  2. package/bin/utopia-ds-mcp.mjs +9 -2
  3. package/bin/utopia-ds.mjs +106 -8
  4. package/data/blocks/activity-feed/ActivityFeedBlock.tsx +255 -0
  5. package/data/blocks/activity-feed/README.md +16 -0
  6. package/data/blocks/activity-feed/activity-feed-contract.ts +96 -0
  7. package/data/blocks/activity-feed/activity-feed-fixture.ts +22 -0
  8. package/data/blocks/activity-feed/activity-feed.css +154 -0
  9. package/data/blocks/agent-status/AgentStatusBlock.tsx +313 -0
  10. package/data/blocks/agent-status/README.md +15 -0
  11. package/data/blocks/agent-status/agent-status-contract.ts +133 -0
  12. package/data/blocks/agent-status/agent-status-fixture.ts +79 -0
  13. package/data/blocks/agent-status/agent-status.css +216 -0
  14. package/data/blocks/analytics-dashboard/AnalyticsDashboardBlocks.tsx +107 -0
  15. package/data/blocks/analytics-dashboard/AnalyticsMetricBlocks.tsx +87 -0
  16. package/data/blocks/analytics-dashboard/README.md +17 -0
  17. package/data/blocks/analytics-dashboard/analytics-dashboard.css +92 -0
  18. package/data/blocks/calendar-application/CalendarApplicationBlocks.tsx +519 -0
  19. package/data/blocks/calendar-application/README.md +20 -0
  20. package/data/blocks/calendar-application/calendar-application.css +216 -0
  21. package/data/blocks/calendar-application/calendar-localization.ts +90 -0
  22. package/data/blocks/calendar-application/calendar-panel-contract.ts +72 -0
  23. package/data/blocks/dashboard-composer/CeramicPuckAdapter.tsx +380 -0
  24. package/data/blocks/dashboard-composer/DashboardComposerBlocks.tsx +337 -0
  25. package/data/blocks/dashboard-composer/README.md +16 -0
  26. package/data/blocks/dashboard-composer/RegistryDataBlocks.tsx +238 -0
  27. package/data/blocks/dashboard-composer/dashboard-composer.css +328 -0
  28. package/data/blocks/database-workspace/DatabaseWorkspaceBlocks.tsx +240 -0
  29. package/data/blocks/database-workspace/README.md +9 -0
  30. package/data/blocks/database-workspace/database-workspace.css +107 -0
  31. package/data/blocks/interaction-workbench/InteractionWorkbench.tsx +271 -0
  32. package/data/blocks/interaction-workbench/README.md +9 -0
  33. package/data/blocks/interaction-workbench/interaction-workbench.css +226 -0
  34. package/data/docs/calendar.md +164 -0
  35. package/data/docs/charts.md +95 -0
  36. package/data/docs/composition-registry.md +174 -0
  37. package/data/docs/dashboard-composer.md +94 -0
  38. package/data/docs/database.md +68 -0
  39. package/data/docs/examples/dashboard-layout.v1.json +65 -0
  40. package/data/docs/foundations.md +1 -1
  41. package/data/docs/interaction-foundation.md +109 -0
  42. package/data/docs/quick-start-ai.md +23 -1
  43. package/data/manifests/blocks.json +392 -0
  44. package/data/manifests/catalog.json +7 -4
  45. package/data/manifests/components.json +179 -0
  46. package/data/manifests/composition-registry.json +427 -0
  47. package/data/manifests/motion-profiles.json +1 -1
  48. package/data/manifests/patterns.json +113 -1
  49. package/data/manifests/templates.json +346 -0
  50. package/data/manifests/theme-renacore.json +142 -0
  51. package/data/manifests/theme-vyapti.json +125 -0
  52. package/data/manifests/themes.json +400 -28
  53. package/data/templates/analytics-dashboard/AnalyticsDashboardBlocks.tsx +107 -0
  54. package/data/templates/analytics-dashboard/AnalyticsMetricBlocks.tsx +87 -0
  55. package/data/templates/analytics-dashboard/README.md +6 -0
  56. package/data/templates/analytics-dashboard/analytics-dashboard.css +92 -0
  57. package/data/templates/analytics-dashboard/index.html +13 -0
  58. package/data/templates/analytics-dashboard/main.tsx +196 -0
  59. package/data/templates/analytics-dashboard/styles.css +120 -0
  60. package/data/templates/analytics-dashboard/template.manifest.json +17 -0
  61. package/data/templates/calendar-application/CalendarApplicationBlocks.tsx +519 -0
  62. package/data/templates/calendar-application/README.md +10 -0
  63. package/data/templates/calendar-application/calendar-application.css +216 -0
  64. package/data/templates/calendar-application/calendar-localization.ts +90 -0
  65. package/data/templates/calendar-application/index.html +14 -0
  66. package/data/templates/calendar-application/main.tsx +409 -0
  67. package/data/templates/calendar-application/styles.css +248 -0
  68. package/data/templates/calendar-application/template.manifest.json +27 -0
  69. package/data/templates/composition-registry-lab/README.md +9 -0
  70. package/data/templates/composition-registry-lab/index.html +14 -0
  71. package/data/templates/composition-registry-lab/main.tsx +217 -0
  72. package/data/templates/composition-registry-lab/sample-layout.json +63 -0
  73. package/data/templates/composition-registry-lab/styles.css +343 -0
  74. package/data/templates/composition-registry-lab/template.manifest.json +34 -0
  75. package/data/templates/dashboard-composer/ActivityFeedBlock.tsx +255 -0
  76. package/data/templates/dashboard-composer/AgentStatusBlock.tsx +313 -0
  77. package/data/templates/dashboard-composer/AnalyticsDashboardBlocks.tsx +107 -0
  78. package/data/templates/dashboard-composer/AnalyticsMetricBlocks.tsx +87 -0
  79. package/data/templates/dashboard-composer/CalendarApplicationBlocks.tsx +519 -0
  80. package/data/templates/dashboard-composer/CeramicPuckAdapter.tsx +380 -0
  81. package/data/templates/dashboard-composer/DashboardComposerBlocks.tsx +337 -0
  82. package/data/templates/dashboard-composer/DatabaseWorkspaceBlocks.tsx +240 -0
  83. package/data/templates/dashboard-composer/README.md +53 -0
  84. package/data/templates/dashboard-composer/RegistryDataBlocks.tsx +238 -0
  85. package/data/templates/dashboard-composer/activity-feed-contract.ts +96 -0
  86. package/data/templates/dashboard-composer/activity-feed-fixture.ts +22 -0
  87. package/data/templates/dashboard-composer/activity-feed.css +154 -0
  88. package/data/templates/dashboard-composer/agent-status-contract.ts +133 -0
  89. package/data/templates/dashboard-composer/agent-status-fixture.ts +79 -0
  90. package/data/templates/dashboard-composer/agent-status-lab/index.html +19 -0
  91. package/data/templates/dashboard-composer/agent-status-lab/main.tsx +151 -0
  92. package/data/templates/dashboard-composer/agent-status-lab/styles.css +139 -0
  93. package/data/templates/dashboard-composer/agent-status.css +216 -0
  94. package/data/templates/dashboard-composer/analytics-dashboard.css +92 -0
  95. package/data/templates/dashboard-composer/calendar-application.css +216 -0
  96. package/data/templates/dashboard-composer/calendar-localization.ts +90 -0
  97. package/data/templates/dashboard-composer/calendar-panel-contract.ts +72 -0
  98. package/data/templates/dashboard-composer/dashboard-composer.css +328 -0
  99. package/data/templates/dashboard-composer/database-workspace.css +107 -0
  100. package/data/templates/dashboard-composer/index.html +14 -0
  101. package/data/templates/dashboard-composer/main.tsx +550 -0
  102. package/data/templates/dashboard-composer/sample-layout.json +147 -0
  103. package/data/templates/dashboard-composer/styles.css +198 -0
  104. package/data/templates/dashboard-composer/template.manifest.json +34 -0
  105. package/data/templates/dashboard-composer/visual-editor/PuckEditorSurface.tsx +132 -0
  106. package/data/templates/dashboard-composer/visual-editor/VisualEditorApp.tsx +343 -0
  107. package/data/templates/dashboard-composer/visual-editor/index.html +17 -0
  108. package/data/templates/dashboard-composer/visual-editor/main.tsx +95 -0
  109. package/data/templates/dashboard-composer/visual-editor/styles.css +310 -0
  110. package/data/templates/database-workspace/DatabaseWorkspaceBlocks.tsx +240 -0
  111. package/data/templates/database-workspace/README.md +5 -0
  112. package/data/templates/database-workspace/database-workspace.css +107 -0
  113. package/data/templates/database-workspace/index.html +14 -0
  114. package/data/templates/database-workspace/main.tsx +247 -0
  115. package/data/templates/database-workspace/styles.css +121 -0
  116. package/data/templates/database-workspace/template.manifest.json +19 -0
  117. package/data/templates/interaction-lab/InteractionWorkbench.tsx +271 -0
  118. package/data/templates/interaction-lab/README.md +7 -0
  119. package/data/templates/interaction-lab/index.html +14 -0
  120. package/data/templates/interaction-lab/interaction-workbench.css +226 -0
  121. package/data/templates/interaction-lab/main.tsx +104 -0
  122. package/data/templates/interaction-lab/styles.css +224 -0
  123. package/data/templates/interaction-lab/template.manifest.json +36 -0
  124. package/lib/api.mjs +72 -5
  125. package/lib/composition-runtime.mjs +382 -0
  126. package/package.json +4 -1
@@ -0,0 +1,14 @@
1
+ <!doctype html>
2
+ <html lang="en" dir="ltr" data-theme="utopia-default" data-color-mode="light">
3
+ <head>
4
+ <meta charset="UTF-8" />
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />
6
+ <meta name="description" content="Ceramic Composition Registry and Layout JSON review lab." />
7
+ <title>Ceramic Composition Registry Lab</title>
8
+ </head>
9
+ <body>
10
+ <a class="skip-link" href="#main-content">Skip to composition registry</a>
11
+ <div id="root"></div>
12
+ <script type="module" src="./main.tsx"></script>
13
+ </body>
14
+ </html>
@@ -0,0 +1,217 @@
1
+ import { StrictMode, useEffect, useMemo, useState, type CSSProperties } from 'react'
2
+ import { createRoot } from 'react-dom/client'
3
+ import { Badge } from '@utopia-studio-design/design-system/Badge'
4
+ import { Button } from '@utopia-studio-design/design-system/Button'
5
+ import {
6
+ listCeramicBlockDefinitions,
7
+ validateCeramicLayout,
8
+ type CeramicLayoutDocument,
9
+ } from '@utopia-studio-design/design-system/Composition'
10
+ import '@utopia-studio-design/design-system/core.css'
11
+ import '@utopia-studio-design/design-system/themes/utopia-default.css'
12
+ import sampleLayout from './sample-layout.json'
13
+ import './styles.css'
14
+
15
+ const activeTheme = 'utopia-default'
16
+ const layout = sampleLayout as CeramicLayoutDocument
17
+ type LayoutBlockStyle = CSSProperties & {
18
+ '--layout-column': number
19
+ '--layout-order': number
20
+ '--layout-span': number
21
+ }
22
+
23
+ function App() {
24
+ const [direction, setDirection] = useState<'ltr' | 'rtl'>('ltr')
25
+ const [dark, setDark] = useState(false)
26
+ const [showPlanned, setShowPlanned] = useState(true)
27
+ const definitions = listCeramicBlockDefinitions()
28
+ const visibleDefinitions = definitions.filter(
29
+ (definition) => showPlanned || definition.availability === 'available',
30
+ )
31
+ const definitionsById = useMemo(
32
+ () => new Map(definitions.map((definition) => [definition.id, definition])),
33
+ [definitions],
34
+ )
35
+ const validation = validateCeramicLayout(layout)
36
+ const warnings = validation.issues.filter((issue) => issue.severity === 'warning')
37
+
38
+ useEffect(() => {
39
+ document.documentElement.dir = direction
40
+ document.documentElement.dataset.previewDirection = direction
41
+
42
+ return () => {
43
+ document.documentElement.dir = 'ltr'
44
+ delete document.documentElement.dataset.previewDirection
45
+ }
46
+ }, [direction])
47
+
48
+ return (
49
+ <main
50
+ className="registry-lab"
51
+ data-color-mode={dark ? 'dark' : 'light'}
52
+ data-preview-direction={direction}
53
+ data-theme={activeTheme}
54
+ dir={direction}
55
+ id="main-content"
56
+ >
57
+ <header className="registry-header">
58
+ <div>
59
+ <p>Step 2 · Composition contract</p>
60
+ <h1>Review who controls the dashboard</h1>
61
+ <span>
62
+ Ceramic defines the blocks and layout rules. Agents and optional visual editors arrange only what the registry allows.
63
+ </span>
64
+ </div>
65
+ <div aria-label="Preview controls" className="registry-controls">
66
+ <div className="registry-control-actions">
67
+ <Button asChild>
68
+ <a href="/templates/dashboard-composer/">Open live composer</a>
69
+ </Button>
70
+ <Button asChild variant="outline">
71
+ <a href="/templates/dashboard-composer/visual-editor/">Open Puck editor</a>
72
+ </Button>
73
+ <Button
74
+ aria-pressed={direction === 'rtl'}
75
+ variant="outline"
76
+ onClick={() => setDirection((value) => value === 'ltr' ? 'rtl' : 'ltr')}
77
+ >
78
+ {direction === 'ltr' ? 'Switch to RTL' : 'Switch to LTR'}
79
+ </Button>
80
+ <Button
81
+ aria-pressed={dark}
82
+ variant="outline"
83
+ onClick={() => setDark((value) => !value)}
84
+ >
85
+ {dark ? 'Switch to light' : 'Switch to dark'}
86
+ </Button>
87
+ </div>
88
+ <output aria-live="polite" className="registry-preview-status">
89
+ Preview: {direction === 'ltr' ? 'LTR · starts on the left' : 'RTL · starts on the right'} · {dark ? 'dark mode' : 'light mode'}
90
+ </output>
91
+ <div
92
+ aria-label={`${direction.toUpperCase()} direction preview`}
93
+ className="registry-direction-preview"
94
+ dir={direction}
95
+ >
96
+ <span>Start edge</span>
97
+ <strong aria-hidden="true">{direction === 'ltr' ? '→' : '←'}</strong>
98
+ <span>End edge</span>
99
+ </div>
100
+ </div>
101
+ </header>
102
+
103
+ <section aria-labelledby="ownership-title" className="ownership-section">
104
+ <div>
105
+ <p className="eyebrow">Source of truth</p>
106
+ <h2 id="ownership-title">Puck is an editor, not the architecture</h2>
107
+ <p>
108
+ The registry already lets an agent and Studio read and write the same JSON. The optional Puck adapter now provides human drag-and-drop over that contract.
109
+ </p>
110
+ </div>
111
+ <ol className="ownership-flow">
112
+ <li><strong>Components</strong><span>Semantic UI</span></li>
113
+ <li><strong>Blocks</strong><span>Dashboard jobs</span></li>
114
+ <li data-current="true"><strong>Registry</strong><span>Allowed composition</span></li>
115
+ <li><strong>Layout JSON</strong><span>Shared document</span></li>
116
+ <li><strong>Agent / Studio / Puck</strong><span>Editors and runtime</span></li>
117
+ </ol>
118
+ </section>
119
+
120
+ <section aria-labelledby="guardrails-title" className="guardrails-section">
121
+ <div>
122
+ <p className="eyebrow">Ceramic concept</p>
123
+ <h2 id="guardrails-title">Semantic choices stay in; arbitrary styling stays out</h2>
124
+ </div>
125
+ <div className="guardrail-grid">
126
+ <article>
127
+ <Badge variant="secondary">Allowed</Badge>
128
+ <h3>Meaning and behavior</h3>
129
+ <p>Density, view, comparison, semantic surface, registered span, state, direction, and permissions.</p>
130
+ </article>
131
+ <article>
132
+ <Badge variant="outline">Rejected</Badge>
133
+ <h3>Design-system bypasses</h3>
134
+ <p>Raw color, shadow, radius, spacing, className, style, sx, CSS, and token overrides.</p>
135
+ </article>
136
+ </div>
137
+ </section>
138
+
139
+ <section aria-labelledby="palette-title" className="palette-section">
140
+ <header>
141
+ <div>
142
+ <p className="eyebrow">Registry palette</p>
143
+ <h2 id="palette-title">{visibleDefinitions.length} registered block definitions</h2>
144
+ <p>Only definitions with an available renderer can be placed in production today.</p>
145
+ </div>
146
+ <Button variant="outline" onClick={() => setShowPlanned((value) => !value)}>
147
+ {showPlanned ? 'Show renderable only' : 'Show planned blocks'}
148
+ </Button>
149
+ </header>
150
+ <div className="definition-grid">
151
+ {visibleDefinitions.map((definition) => (
152
+ <article className="definition-card" key={definition.id}>
153
+ <div>
154
+ <Badge variant={definition.availability === 'available' ? 'secondary' : 'outline'}>
155
+ {definition.availability}
156
+ </Badge>
157
+ <span>v{definition.version}</span>
158
+ </div>
159
+ <h3>{definition.title}</h3>
160
+ <p>{definition.description}</p>
161
+ <dl>
162
+ <div><dt>Spans</dt><dd>{definition.allowedSpans.join(', ')}</dd></div>
163
+ <div><dt>Responsive</dt><dd>{definition.responsiveBehavior}</dd></div>
164
+ <div><dt>Agent create</dt><dd>{definition.agentPermissions.create ? 'Allowed' : 'Not yet'}</dd></div>
165
+ </dl>
166
+ </article>
167
+ ))}
168
+ </div>
169
+ </section>
170
+
171
+ <section aria-labelledby="layout-title" className="layout-section">
172
+ <header>
173
+ <div>
174
+ <p className="eyebrow">Shared Layout JSON</p>
175
+ <h2 id="layout-title">One document, three consumers</h2>
176
+ <p>The agent, Studio runtime, and the Puck adapter use this same validated structure.</p>
177
+ </div>
178
+ <output aria-label="Layout validation result" data-valid={validation.ok}>
179
+ {validation.ok ? 'Schema valid' : 'Schema failed'} · {warnings.length} registry warnings
180
+ </output>
181
+ </header>
182
+ <div aria-label="Sample operations dashboard layout" className="layout-preview">
183
+ {layout.blocks.map((block) => {
184
+ const definition = definitionsById.get(block.type)
185
+ return (
186
+ <article
187
+ className="layout-block"
188
+ data-availability={definition?.availability}
189
+ key={block.id}
190
+ style={{
191
+ '--layout-column': block.placement.column,
192
+ '--layout-order': block.placement.order,
193
+ '--layout-span': block.placement.span,
194
+ } as LayoutBlockStyle}
195
+ >
196
+ <span>{definition?.category}</span>
197
+ <strong>{definition?.title ?? block.type}</strong>
198
+ <small>{block.locked ? 'Locked by owner' : 'Agent may move after renderer approval'}</small>
199
+ </article>
200
+ )
201
+ })}
202
+ </div>
203
+ </section>
204
+
205
+ <details className="registry-evidence">
206
+ <summary>Developer evidence: inspect the versioned Layout JSON</summary>
207
+ <pre>{JSON.stringify(layout, null, 2)}</pre>
208
+ </details>
209
+ </main>
210
+ )
211
+ }
212
+
213
+ createRoot(document.getElementById('root')!).render(
214
+ <StrictMode>
215
+ <App />
216
+ </StrictMode>,
217
+ )
@@ -0,0 +1,63 @@
1
+ {
2
+ "schemaVersion": 1,
3
+ "id": "operations-dashboard",
4
+ "theme": "utopia-default",
5
+ "columns": 12,
6
+ "blocks": [
7
+ {
8
+ "id": "overview-metrics",
9
+ "type": "metric-grid",
10
+ "version": 1,
11
+ "placement": {
12
+ "column": 1,
13
+ "span": 4,
14
+ "order": 1,
15
+ "compactSpan": 12
16
+ },
17
+ "props": {
18
+ "metrics": ["open", "blocked", "resolved"],
19
+ "density": "compact",
20
+ "comparison": "previous-period"
21
+ }
22
+ },
23
+ {
24
+ "id": "automation-status",
25
+ "type": "agent-status",
26
+ "version": 1,
27
+ "placement": {
28
+ "column": 9,
29
+ "span": 4,
30
+ "order": 1,
31
+ "compactSpan": 12
32
+ },
33
+ "props": {
34
+ "showApprovals": true,
35
+ "density": "default"
36
+ },
37
+ "locked": true
38
+ },
39
+ {
40
+ "id": "active-issues",
41
+ "type": "issue-table",
42
+ "version": 1,
43
+ "placement": {
44
+ "column": 1,
45
+ "span": 12,
46
+ "order": 2,
47
+ "compactSpan": 12
48
+ },
49
+ "props": {
50
+ "view": "active",
51
+ "density": "compact",
52
+ "columns": ["title", "status", "priority", "assignee"]
53
+ }
54
+ }
55
+ ],
56
+ "regions": [
57
+ {
58
+ "id": "governance",
59
+ "locked": true,
60
+ "blockIds": ["automation-status"]
61
+ }
62
+ ]
63
+ }
@@ -0,0 +1,343 @@
1
+ * {
2
+ box-sizing: border-box;
3
+ }
4
+
5
+ html,
6
+ body,
7
+ #root {
8
+ min-block-size: 100%;
9
+ margin: 0;
10
+ }
11
+
12
+ body {
13
+ background: var(--background);
14
+ color: var(--foreground);
15
+ font-family: var(--font-sans);
16
+ }
17
+
18
+ .skip-link {
19
+ position: fixed;
20
+ inset-block-start: var(--space-2);
21
+ inset-inline-start: var(--space-2);
22
+ z-index: var(--z-modal);
23
+ translate: 0 -200%;
24
+ }
25
+
26
+ .skip-link:focus {
27
+ translate: 0;
28
+ }
29
+
30
+ .registry-lab {
31
+ min-block-size: 100vh;
32
+ padding: var(--page-gutter);
33
+ background: var(--background);
34
+ color: var(--foreground);
35
+ text-align: start;
36
+ }
37
+
38
+ .registry-header,
39
+ .ownership-section,
40
+ .guardrails-section,
41
+ .palette-section,
42
+ .layout-section,
43
+ .registry-evidence {
44
+ max-inline-size: var(--container-standard);
45
+ margin-inline: auto;
46
+ }
47
+
48
+ .registry-header {
49
+ display: flex;
50
+ align-items: end;
51
+ justify-content: space-between;
52
+ gap: var(--space-6);
53
+ padding-block: var(--space-8);
54
+ border-block-end: var(--border-width-hairline) solid var(--border);
55
+ }
56
+
57
+ .registry-header > div:first-child {
58
+ display: grid;
59
+ gap: var(--space-2);
60
+ max-inline-size: 50rem;
61
+ }
62
+
63
+ .registry-header h1,
64
+ .registry-header p,
65
+ .registry-lab h2,
66
+ .registry-lab h3,
67
+ .registry-lab p {
68
+ margin: 0;
69
+ }
70
+
71
+ .registry-header p,
72
+ .registry-header span,
73
+ .ownership-section p,
74
+ .guardrails-section article p,
75
+ .palette-section header p,
76
+ .definition-card p,
77
+ .layout-section header p {
78
+ color: var(--muted-foreground);
79
+ line-height: var(--line-height-body);
80
+ }
81
+
82
+ .registry-controls {
83
+ display: grid;
84
+ justify-items: end;
85
+ gap: var(--space-2);
86
+ }
87
+
88
+ .registry-control-actions {
89
+ display: flex;
90
+ flex-wrap: wrap;
91
+ gap: var(--space-2);
92
+ }
93
+
94
+ .registry-preview-status {
95
+ color: var(--muted-foreground);
96
+ font-size: var(--font-size-small);
97
+ }
98
+
99
+ .registry-direction-preview {
100
+ display: flex;
101
+ align-items: center;
102
+ justify-content: space-between;
103
+ gap: var(--space-3);
104
+ min-inline-size: min(100%, 18rem);
105
+ padding: var(--space-2) var(--space-3);
106
+ border: var(--border-width-hairline) solid var(--interaction-selection-border);
107
+ background: var(--interaction-selection-surface);
108
+ color: var(--foreground);
109
+ font-size: var(--font-size-small);
110
+ }
111
+
112
+ .registry-direction-preview strong {
113
+ font-size: var(--font-size-body);
114
+ }
115
+
116
+ .ownership-section,
117
+ .guardrails-section,
118
+ .palette-section,
119
+ .layout-section {
120
+ display: grid;
121
+ gap: var(--space-4);
122
+ padding-block: var(--space-6);
123
+ border-block-end: var(--border-width-hairline) solid var(--border);
124
+ }
125
+
126
+ .ownership-section {
127
+ grid-template-columns: minmax(16rem, .7fr) minmax(0, 1.3fr);
128
+ align-items: start;
129
+ }
130
+
131
+ .ownership-section > div,
132
+ .palette-section header > div,
133
+ .layout-section header > div,
134
+ .guardrails-section > div:first-child {
135
+ display: grid;
136
+ gap: var(--space-2);
137
+ }
138
+
139
+ .eyebrow {
140
+ color: var(--muted-foreground);
141
+ font-size: var(--font-size-eyebrow);
142
+ font-weight: var(--font-weight-semibold);
143
+ letter-spacing: var(--tracking-eyebrow);
144
+ text-transform: uppercase;
145
+ }
146
+
147
+ .ownership-flow {
148
+ display: grid;
149
+ grid-template-columns: repeat(5, minmax(0, 1fr));
150
+ margin: 0;
151
+ padding: 0;
152
+ list-style: none;
153
+ border: var(--border-width-hairline) solid var(--border);
154
+ }
155
+
156
+ .ownership-flow li {
157
+ display: grid;
158
+ align-content: start;
159
+ gap: var(--space-1);
160
+ min-inline-size: 0;
161
+ padding: var(--space-3);
162
+ border-inline-end: var(--border-width-hairline) solid var(--border);
163
+ }
164
+
165
+ .ownership-flow li:last-child {
166
+ border-inline-end: 0;
167
+ }
168
+
169
+ .ownership-flow li[data-current='true'] {
170
+ background: var(--interaction-selection-surface);
171
+ }
172
+
173
+ .ownership-flow span,
174
+ .definition-card span,
175
+ .definition-card dt,
176
+ .layout-block span,
177
+ .layout-block small {
178
+ color: var(--muted-foreground);
179
+ font-size: var(--font-size-small);
180
+ }
181
+
182
+ .guardrail-grid,
183
+ .definition-grid {
184
+ display: grid;
185
+ grid-template-columns: repeat(2, minmax(0, 1fr));
186
+ gap: var(--space-3);
187
+ }
188
+
189
+ .guardrails-section article,
190
+ .definition-card {
191
+ display: grid;
192
+ align-content: start;
193
+ gap: var(--space-2);
194
+ min-inline-size: 0;
195
+ padding: var(--space-4);
196
+ border: var(--border-width-hairline) solid var(--border);
197
+ background: var(--surface);
198
+ }
199
+
200
+ .palette-section header,
201
+ .layout-section header {
202
+ display: flex;
203
+ align-items: end;
204
+ justify-content: space-between;
205
+ gap: var(--space-4);
206
+ }
207
+
208
+ .definition-grid {
209
+ grid-template-columns: repeat(3, minmax(0, 1fr));
210
+ }
211
+
212
+ .definition-card > div:first-child {
213
+ display: flex;
214
+ align-items: center;
215
+ justify-content: space-between;
216
+ gap: var(--space-2);
217
+ }
218
+
219
+ .definition-card dl {
220
+ display: grid;
221
+ gap: var(--space-1);
222
+ margin: var(--space-2) 0 0;
223
+ }
224
+
225
+ .definition-card dl div {
226
+ display: flex;
227
+ justify-content: space-between;
228
+ gap: var(--space-2);
229
+ }
230
+
231
+ .definition-card dd {
232
+ margin: 0;
233
+ text-align: end;
234
+ }
235
+
236
+ .layout-section output {
237
+ padding: var(--space-3);
238
+ border: var(--border-width-hairline) solid var(--interaction-selection-border);
239
+ background: var(--interaction-selection-surface);
240
+ font-size: var(--font-size-small);
241
+ }
242
+
243
+ .layout-preview {
244
+ display: grid;
245
+ grid-template-columns: repeat(12, minmax(0, 1fr));
246
+ grid-auto-rows: minmax(8rem, auto);
247
+ gap: var(--space-3);
248
+ min-inline-size: 0;
249
+ padding: var(--space-4);
250
+ border: var(--border-width-hairline) solid var(--border);
251
+ background: var(--surface);
252
+ }
253
+
254
+ .layout-block {
255
+ display: grid;
256
+ align-content: center;
257
+ grid-column: var(--layout-column) / span var(--layout-span);
258
+ grid-row: var(--layout-order);
259
+ gap: var(--space-1);
260
+ min-inline-size: 0;
261
+ padding: var(--space-4);
262
+ border: var(--border-width-hairline) dashed var(--interaction-selection-border);
263
+ background: var(--interaction-selection-surface);
264
+ }
265
+
266
+ .layout-block[data-availability='planned']::after {
267
+ content: 'Renderer planned';
268
+ inline-size: fit-content;
269
+ margin-block-start: var(--space-2);
270
+ padding: var(--space-1) var(--space-2);
271
+ border: var(--border-width-hairline) solid var(--border);
272
+ color: var(--muted-foreground);
273
+ font-size: var(--font-size-eyebrow);
274
+ text-transform: uppercase;
275
+ }
276
+
277
+ .registry-evidence {
278
+ margin-block: var(--space-4);
279
+ padding: var(--space-4);
280
+ border: var(--border-width-hairline) solid var(--border);
281
+ background: var(--surface);
282
+ }
283
+
284
+ .registry-evidence summary {
285
+ cursor: pointer;
286
+ font-weight: var(--font-weight-semibold);
287
+ }
288
+
289
+ .registry-evidence pre {
290
+ max-block-size: 28rem;
291
+ overflow: auto;
292
+ padding: var(--space-3);
293
+ background: var(--background);
294
+ font-size: var(--font-size-small);
295
+ }
296
+
297
+ @media (max-width: 56rem) {
298
+ .definition-grid {
299
+ grid-template-columns: repeat(2, minmax(0, 1fr));
300
+ }
301
+
302
+ .ownership-flow {
303
+ grid-template-columns: 1fr;
304
+ }
305
+
306
+ .ownership-flow li {
307
+ border-inline-end: 0;
308
+ border-block-end: var(--border-width-hairline) solid var(--border);
309
+ }
310
+
311
+ .ownership-flow li:last-child {
312
+ border-block-end: 0;
313
+ }
314
+ }
315
+
316
+ @media (max-width: 44rem) {
317
+ .registry-header,
318
+ .palette-section header,
319
+ .layout-section header {
320
+ align-items: stretch;
321
+ flex-direction: column;
322
+ }
323
+
324
+ .ownership-section,
325
+ .guardrail-grid,
326
+ .definition-grid {
327
+ grid-template-columns: 1fr;
328
+ }
329
+
330
+ .registry-controls {
331
+ justify-items: start;
332
+ inline-size: 100%;
333
+ }
334
+
335
+ .registry-direction-preview {
336
+ inline-size: 100%;
337
+ }
338
+
339
+ .layout-block {
340
+ grid-column: 1 / -1;
341
+ grid-row: auto;
342
+ }
343
+ }
@@ -0,0 +1,34 @@
1
+ {
2
+ "id": "template-composition-registry-lab",
3
+ "name": "Composition Registry Lab",
4
+ "category": "development-tool",
5
+ "status": "available",
6
+ "purpose": "A runnable review surface for Ceramic block definitions, design guardrails, Layout JSON, and editor ownership boundaries.",
7
+ "packageImport": "@utopia-studio-design/design-system/Composition",
8
+ "sourcePath": "templates/composition-registry-lab/main.tsx",
9
+ "entryPath": "templates/composition-registry-lab/index.html",
10
+ "requiredTokens": [
11
+ "interaction-selection-*",
12
+ "background",
13
+ "surface",
14
+ "foreground",
15
+ "muted-foreground",
16
+ "border"
17
+ ],
18
+ "features": {
19
+ "registryDefinitions": true,
20
+ "layoutValidation": true,
21
+ "agentPermissions": true,
22
+ "lockedRegions": true,
23
+ "darkMode": true,
24
+ "rtl": true,
25
+ "responsiveMinimum": "320px",
26
+ "puckAdapter": false
27
+ },
28
+ "translations": {
29
+ "ar": {
30
+ "name": "مختبر سجل التركيب",
31
+ "purpose": "واجهة مراجعة قابلة للتشغيل لتعريفات كتل Ceramic وضوابط التصميم وعقد تخطيط JSON."
32
+ }
33
+ }
34
+ }