@workbench-kit/react 0.0.1-prototype.0 → 0.0.2-prototype.0.1.1

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 (155) hide show
  1. package/package.json +33 -9
  2. package/src/index.ts +545 -43
  3. package/src/jdw/JdwPreview.tsx +38 -0
  4. package/src/jdw/JsonCodeEditorPane.tsx +274 -0
  5. package/src/jdw/builtins/renderBuiltinWidgetLeaf.tsx +29 -0
  6. package/src/jdw/builtins/renderBuiltinWidgetNode.tsx +126 -0
  7. package/src/jdw/createBuiltinJdwRegistry.ts +111 -0
  8. package/src/jdw/cssRenderBackend.tsx +134 -0
  9. package/src/jdw/document.ts +38 -0
  10. package/src/jdw/fixtures/jdw-fixtures.ts +52 -0
  11. package/src/jdw/fixtures/jdw-sample-screens.ts +522 -0
  12. package/src/jdw/index.ts +45 -0
  13. package/src/jdw/parse.ts +1 -0
  14. package/src/jdw/renderJdw.tsx +32 -0
  15. package/src/json-config/JsonConfigWorkbench.tsx +316 -0
  16. package/src/json-config/index.ts +6 -0
  17. package/src/json-config/json-config-editor-state.ts +42 -0
  18. package/src/layout/Panel.tsx +146 -1
  19. package/src/layout/SideBarViewFrame.tsx +367 -328
  20. package/src/layout/WorkbenchCanvas.tsx +849 -0
  21. package/src/layout/WorkbenchFullscreen.tsx +368 -0
  22. package/src/layout/WorkbenchLayout.tsx +5 -0
  23. package/src/layout/WorkbenchLayoutBase.tsx +294 -0
  24. package/src/layout/WorkbenchPropertyPanel.tsx +497 -0
  25. package/src/layout/WorkbenchSidebarActions.tsx +274 -0
  26. package/src/layout/WorkbenchTree.tsx +351 -0
  27. package/src/layout/layoutHelpers.ts +25 -0
  28. package/src/modal/ConfirmDialog.tsx +61 -53
  29. package/src/modal/Modal.tsx +295 -35
  30. package/src/overlay/ContextMenu.tsx +146 -145
  31. package/src/primitives/AbsoluteBox.tsx +46 -0
  32. package/src/primitives/Badge.tsx +12 -12
  33. package/src/primitives/Button.tsx +44 -14
  34. package/src/primitives/Checkbox.tsx +11 -5
  35. package/src/primitives/EmptyState.tsx +27 -26
  36. package/src/primitives/Field.tsx +38 -38
  37. package/src/primitives/IconButton.tsx +5 -2
  38. package/src/primitives/List.tsx +111 -0
  39. package/src/primitives/NumberInput.tsx +38 -0
  40. package/src/primitives/ScrollArea.tsx +42 -0
  41. package/src/primitives/Select.tsx +1 -12
  42. package/src/primitives/StatusBar.tsx +46 -0
  43. package/src/primitives/TextArea.tsx +36 -0
  44. package/src/primitives/TextInput.tsx +11 -2
  45. package/src/primitives/WorkbenchChrome.tsx +424 -0
  46. package/src/primitives/WorkbenchEditor.tsx +394 -0
  47. package/src/primitives/index.ts +105 -0
  48. package/src/primitives/select/Select.tsx +266 -0
  49. package/src/primitives/select/index.ts +2 -0
  50. package/src/primitives/select/options.ts +38 -0
  51. package/src/primitives/select/overlay.ts +63 -0
  52. package/src/primitives/select/select.app.css +9 -0
  53. package/src/primitives/select/select.css +140 -0
  54. package/src/primitives/select/types.ts +18 -0
  55. package/src/primitives/styles.css +955 -0
  56. package/src/scrollbars.css +69 -0
  57. package/src/styles.css +7738 -1762
  58. package/src/utils/codicon.ts +17 -0
  59. package/src/widget-asset/WidgetAssetEditor.tsx +140 -0
  60. package/src/widget-asset/WidgetAssetMetadataForm.tsx +82 -0
  61. package/src/widget-asset/WidgetAssetModeControls.tsx +42 -0
  62. package/src/widget-asset/WidgetAssetSourceEditor.tsx +50 -0
  63. package/src/widget-asset/WidgetAssetWorkbench.tsx +112 -0
  64. package/src/widget-asset/index.ts +17 -0
  65. package/src/widget-asset/widget-asset-document.ts +37 -0
  66. package/src/widget-asset/widget-asset-mode.ts +3 -0
  67. package/src/widget-studio/builtin-widget-asset-catalog.ts +12 -0
  68. package/src/widget-studio/create-widget-studio-workspace-editor.tsx +79 -0
  69. package/src/widget-studio/index.ts +7 -0
  70. package/src/widget-studio/resolve-widget-studio-asset-catalog.ts +26 -0
  71. package/src/widget-tree/WidgetAssetPalette.tsx +77 -0
  72. package/src/widget-tree/WidgetInspectorPanel.tsx +266 -0
  73. package/src/widget-tree/WidgetSourceEditor.tsx +56 -0
  74. package/src/widget-tree/WidgetTreeLab.tsx +272 -0
  75. package/src/widget-tree/WidgetTreeModeControls.tsx +44 -0
  76. package/src/widget-tree/WidgetTreeSidePanel.tsx +49 -0
  77. package/src/widget-tree/WidgetTreeView.tsx +97 -0
  78. package/src/widget-tree/WidgetTreeWorkbench.tsx +111 -0
  79. package/src/widget-tree/WidgetTreeWorkspaceShell.tsx +154 -0
  80. package/src/widget-tree/demo-registry.ts +32 -0
  81. package/src/widget-tree/demo-widget-assets.ts +4 -0
  82. package/src/widget-tree/index.ts +27 -0
  83. package/src/widget-tree/widget-tree-document.ts +20 -0
  84. package/src/widget-tree/widget-tree-layout.ts +31 -0
  85. package/src/widget-tree/widget-tree-mode.ts +7 -0
  86. package/src/widget-tree/widget-tree-play-helpers.ts +74 -0
  87. package/src/workbench/ActivityBar.tsx +52 -52
  88. package/src/workbench/ArtifactShell.tsx +397 -0
  89. package/src/workbench/CommandPalette.tsx +819 -0
  90. package/src/workbench/ConfirmationFlow.tsx +245 -0
  91. package/src/workbench/MarkdownPreview.tsx +151 -0
  92. package/src/workbench/ShortcutCommandBridge.tsx +368 -0
  93. package/src/workbench/SplitView.tsx +136 -136
  94. package/src/workbench/StatusBar.tsx +178 -123
  95. package/src/workbench/StructuredArtifactEditor.tsx +205 -0
  96. package/src/workbench/Timeline.tsx +302 -0
  97. package/src/workbench/WorkbenchCanvasShell.tsx +941 -0
  98. package/src/workbench/WorkbenchShell.tsx +74 -70
  99. package/src/workbench/WorkbenchStandaloneShell.tsx +318 -291
  100. package/src/workbench/auth/WorkbenchAuthGate.tsx +61 -0
  101. package/src/workbench/auth/WorkbenchLoginView.tsx +635 -0
  102. package/src/workbench/auth/index.ts +19 -0
  103. package/src/workbench/chat/ChatComposer.tsx +165 -148
  104. package/src/workbench/chat/ChatMessageItem.tsx +10 -1
  105. package/src/workbench/chat/index.ts +9 -0
  106. package/src/workbench/chat/slashCommand.ts +28 -0
  107. package/src/workbench/chat/useChatRuntimeState.ts +76 -0
  108. package/src/workbench/chat/useSlashCommandSuggest.ts +101 -0
  109. package/src/workbench/commands.ts +520 -490
  110. package/src/workbench/index.ts +443 -98
  111. package/src/workbench/keyboard.ts +53 -0
  112. package/src/workbench/schema/index.ts +48 -0
  113. package/src/workbench/schema/workbenchDocument.ts +31 -0
  114. package/src/workbench/schema/workbenchDocumentActions.ts +6 -0
  115. package/src/workbench/schema/workbenchDocumentAdapter.ts +9 -0
  116. package/src/workbench/schema/workbenchDocumentPatch.ts +13 -0
  117. package/src/workbench/schema/workbenchDocumentRenderer.tsx +702 -0
  118. package/src/workbench/settings/NavigationPanel.tsx +47 -0
  119. package/src/workbench/settings/SchemaForm.tsx +420 -0
  120. package/src/workbench/settings/SectionedPanel.tsx +415 -0
  121. package/src/workbench/settings/StructuredDataForm.tsx +539 -0
  122. package/src/workbench/settings/StructuredDataSchemaPanel.tsx +559 -0
  123. package/src/workbench/settings/StructuredDataSchemaPanelEmbed.tsx +21 -0
  124. package/src/workbench/settings/StructuredDataSchemaPanelFrame.tsx +76 -0
  125. package/src/workbench/settings/StructuredDataTableView.tsx +127 -0
  126. package/src/workbench/settings/WorkbenchPanelRegion.tsx +46 -0
  127. package/src/workbench/settings/WorkbenchSettingsModal.tsx +21 -12
  128. package/src/workbench/settings/WorkbenchSettingsNav.tsx +38 -22
  129. package/src/workbench/settings/index.ts +135 -0
  130. package/src/workbench/settings/panel-region.css +21 -0
  131. package/src/workbench/settings/sectionedPanelScrollSpy.ts +143 -0
  132. package/src/workbench/settings/structured-data-schema-panel.css +330 -0
  133. package/src/workbench/settings/structured-data-table-view.css +85 -0
  134. package/src/workbench/settings/structuredDataSchema.ts +886 -0
  135. package/src/workbench/shell.ts +15 -0
  136. package/src/workbench/shellState.ts +203 -203
  137. package/src/workbench/standalone.ts +101 -94
  138. package/src/workbench/status.ts +129 -0
  139. package/src/workbench/theme.ts +44 -0
  140. package/src/workbench/workspace/MultiProviderExplorer.tsx +625 -0
  141. package/src/workbench/workspace/WorkspaceDraftsContext.tsx +111 -0
  142. package/src/workbench/workspace/WorkspaceEditor.tsx +47 -12
  143. package/src/workbench/workspace/WorkspaceEditorPanel.tsx +334 -353
  144. package/src/workbench/workspace/WorkspaceExplorer.tsx +532 -524
  145. package/src/workbench/workspace/WorkspaceFileIcon.tsx +32 -2
  146. package/src/workbench/workspace/WorkspaceSearchPanel.tsx +113 -113
  147. package/src/workbench/workspace/WorkspaceSearchResults.tsx +47 -47
  148. package/src/workbench/workspace/index.ts +156 -98
  149. package/src/workbench/workspace/mimeType.ts +45 -0
  150. package/src/workbench/workspace/path.ts +10 -10
  151. package/src/workbench/workspace/search.ts +6 -6
  152. package/src/workbench/workspace/tree.ts +1 -1
  153. package/src/workbench/workspace/types.ts +10 -10
  154. package/src/workbench/workspace/useVirtualWorkspace.ts +111 -98
  155. package/src/workbench/workspace/workspaceJsonDiagnostics.ts +83 -0
@@ -0,0 +1,522 @@
1
+ import {
2
+ compileScreenSpecToJson,
3
+ type LayoutConstraints,
4
+ screenColumn,
5
+ screenExpanded,
6
+ screenGrid,
7
+ screenPanel,
8
+ screenRow,
9
+ screenStack,
10
+ screenText,
11
+ type JdwScreenSpec,
12
+ } from '@workbench-kit/jdw';
13
+
14
+ export type JdwSampleScreenDefinition = JdwScreenSpec;
15
+
16
+ const muted = { color: '#9aa0a6' };
17
+ const accent = { color: '#4aa8ff' };
18
+
19
+ function defineScreen(spec: JdwScreenSpec): JdwSampleScreenDefinition {
20
+ return spec;
21
+ }
22
+
23
+ export const JDW_SAMPLE_SCREENS: readonly JdwSampleScreenDefinition[] = [
24
+ defineScreen({
25
+ id: 'analytics-dashboard',
26
+ title: 'Analytics Dashboard',
27
+ description: 'Header, KPI strip, and two chart placeholders in a column layout.',
28
+ frameWidth: 720,
29
+ layout: { maxWidth: 720, maxHeight: 420 },
30
+ root: screenColumn(
31
+ [
32
+ screenRow(
33
+ [
34
+ screenText('Analytics', { fontSize: 22, color: '#e8eaed' }),
35
+ screenExpanded(screenText('Last 7 days', { fontSize: 12, ...muted })),
36
+ screenText('Export', { fontSize: 12, ...accent }),
37
+ ],
38
+ { gap: 12 },
39
+ ),
40
+ screenGrid(4, [
41
+ screenColumn(
42
+ [
43
+ screenText('Sessions', { fontSize: 11, ...muted }),
44
+ screenText('12,480', { fontSize: 20, color: '#e8eaed' }),
45
+ screenText('+8.2%', { fontSize: 11, color: '#34a853' }),
46
+ ],
47
+ { gap: 4, col: 0, row: 0 },
48
+ ),
49
+ screenColumn(
50
+ [
51
+ screenText('Bounce rate', { fontSize: 11, ...muted }),
52
+ screenText('41.3%', { fontSize: 20, color: '#e8eaed' }),
53
+ screenText('-1.4%', { fontSize: 11, color: '#34a853' }),
54
+ ],
55
+ { gap: 4, col: 1, row: 0 },
56
+ ),
57
+ screenColumn(
58
+ [
59
+ screenText('Avg. duration', { fontSize: 11, ...muted }),
60
+ screenText('3m 12s', { fontSize: 20, color: '#e8eaed' }),
61
+ screenText('+0.6%', { fontSize: 11, color: '#34a853' }),
62
+ ],
63
+ { gap: 4, col: 2, row: 0 },
64
+ ),
65
+ screenColumn(
66
+ [
67
+ screenText('Conversion', { fontSize: 11, ...muted }),
68
+ screenText('2.9%', { fontSize: 20, color: '#e8eaed' }),
69
+ screenText('-0.2%', { fontSize: 11, color: '#f28b82' }),
70
+ ],
71
+ { gap: 4, col: 3, row: 0 },
72
+ ),
73
+ ]),
74
+ screenRow(
75
+ [
76
+ screenExpanded(screenPanel('Traffic trend', '#1e2127')),
77
+ screenExpanded(screenPanel('Top channels', '#1e2127')),
78
+ ],
79
+ {
80
+ gap: 12,
81
+ },
82
+ ),
83
+ ],
84
+ { gap: 16, padding: 20, background: '#13151a' },
85
+ ),
86
+ }),
87
+ defineScreen({
88
+ id: 'user-profile',
89
+ title: 'User Profile',
90
+ description: 'Avatar block with name, email, and role badge.',
91
+ frameWidth: 480,
92
+ layout: { maxWidth: 480, maxHeight: 160 },
93
+ root: screenRow(
94
+ [
95
+ screenPanel('AV', '#353a42'),
96
+ screenColumn(
97
+ [
98
+ screenText('Alex Morgan', { fontSize: 18, color: '#e8eaed' }),
99
+ screenText('alex.morgan@example.com', { fontSize: 12, ...muted }),
100
+ screenText('Workspace admin', { fontSize: 11, color: '#34a853' }),
101
+ ],
102
+ { gap: 4 },
103
+ ),
104
+ ],
105
+ { gap: 16, padding: 20, background: '#13151a' },
106
+ ),
107
+ }),
108
+ defineScreen({
109
+ id: 'settings-panel',
110
+ title: 'Settings Panel',
111
+ description: 'Label and value rows for a compact preferences block.',
112
+ frameWidth: 520,
113
+ layout: { maxWidth: 520, maxHeight: 280 },
114
+ root: screenColumn(
115
+ [
116
+ screenText('Preferences', { fontSize: 18, color: '#e8eaed' }),
117
+ screenRow(
118
+ [
119
+ screenExpanded(screenText('Theme', { fontSize: 13, ...muted })),
120
+ screenText('Dark', { fontSize: 13, color: '#e8eaed' }),
121
+ ],
122
+ { gap: 8 },
123
+ ),
124
+ screenRow(
125
+ [
126
+ screenExpanded(screenText('Language', { fontSize: 13, ...muted })),
127
+ screenText('English', { fontSize: 13, color: '#e8eaed' }),
128
+ ],
129
+ { gap: 8 },
130
+ ),
131
+ screenRow(
132
+ [
133
+ screenExpanded(screenText('Notifications', { fontSize: 13, ...muted })),
134
+ screenText('Enabled', { fontSize: 13, color: '#34a853' }),
135
+ ],
136
+ { gap: 8 },
137
+ ),
138
+ screenRow(
139
+ [
140
+ screenExpanded(screenText('Auto-save', { fontSize: 13, ...muted })),
141
+ screenText('Every 30s', { fontSize: 13, color: '#e8eaed' }),
142
+ ],
143
+ { gap: 8 },
144
+ ),
145
+ ],
146
+ { gap: 12, padding: 20, background: '#13151a' },
147
+ ),
148
+ }),
149
+ defineScreen({
150
+ id: 'pricing-plans',
151
+ title: 'Pricing Plans',
152
+ description: 'Three plan cards in a grid with highlighted middle tier.',
153
+ frameWidth: 720,
154
+ layout: { maxWidth: 720, maxHeight: 300 },
155
+ root: screenColumn(
156
+ [
157
+ screenText('Choose a plan', { fontSize: 20, color: '#e8eaed' }),
158
+ screenGrid(3, [
159
+ screenColumn(
160
+ [
161
+ screenText('Starter', { fontSize: 14, color: '#e8eaed' }),
162
+ screenText('$0', { fontSize: 24, color: '#e8eaed' }),
163
+ screenText('For personal projects', { fontSize: 11, ...muted }),
164
+ ],
165
+ { gap: 6, col: 0, row: 0, padding: 12, background: '#1e2127' },
166
+ ),
167
+ screenColumn(
168
+ [
169
+ screenText('Pro', { fontSize: 14, color: '#e8eaed' }),
170
+ screenText('$12', { fontSize: 24, color: '#4aa8ff' }),
171
+ screenText('For growing teams', { fontSize: 11, ...muted }),
172
+ ],
173
+ { gap: 6, col: 1, row: 0, padding: 12, background: '#2b3a4f' },
174
+ ),
175
+ screenColumn(
176
+ [
177
+ screenText('Enterprise', { fontSize: 14, color: '#e8eaed' }),
178
+ screenText('Custom', { fontSize: 24, color: '#e8eaed' }),
179
+ screenText('For large orgs', { fontSize: 11, ...muted }),
180
+ ],
181
+ { gap: 6, col: 2, row: 0, padding: 12, background: '#1e2127' },
182
+ ),
183
+ ]),
184
+ ],
185
+ { gap: 16, padding: 20, background: '#13151a' },
186
+ ),
187
+ }),
188
+ defineScreen({
189
+ id: 'media-gallery',
190
+ title: 'Media Gallery',
191
+ description: 'Three media cards with image placeholders and captions.',
192
+ frameWidth: 720,
193
+ layout: { maxWidth: 720, maxHeight: 360 },
194
+ root: screenColumn(
195
+ [
196
+ screenText('Recent uploads', { fontSize: 18, color: '#e8eaed' }),
197
+ screenGrid(3, [
198
+ screenColumn(
199
+ [
200
+ screenPanel(' ', '#2b2f36'),
201
+ screenText('Mountain trail', { fontSize: 13, color: '#e8eaed' }),
202
+ screenText('Edited 2h ago', { fontSize: 11, ...muted }),
203
+ ],
204
+ {
205
+ gap: 8,
206
+ col: 0,
207
+ row: 0,
208
+ },
209
+ ),
210
+ screenColumn(
211
+ [
212
+ screenPanel(' ', '#2b2f36'),
213
+ screenText('City skyline', { fontSize: 13, color: '#e8eaed' }),
214
+ screenText('Edited yesterday', { fontSize: 11, ...muted }),
215
+ ],
216
+ {
217
+ gap: 8,
218
+ col: 1,
219
+ row: 0,
220
+ },
221
+ ),
222
+ screenColumn(
223
+ [
224
+ screenPanel(' ', '#2b2f36'),
225
+ screenText('Studio portrait', { fontSize: 13, color: '#e8eaed' }),
226
+ screenText('Edited 3d ago', { fontSize: 11, ...muted }),
227
+ ],
228
+ {
229
+ gap: 8,
230
+ col: 2,
231
+ row: 0,
232
+ },
233
+ ),
234
+ ]),
235
+ ],
236
+ { gap: 16, padding: 20, background: '#13151a' },
237
+ ),
238
+ }),
239
+ defineScreen({
240
+ id: 'inbox-list',
241
+ title: 'Inbox List',
242
+ description: 'Stacked message rows with sender, preview, and timestamp.',
243
+ frameWidth: 520,
244
+ layout: { maxWidth: 520, maxHeight: 320 },
245
+ root: screenColumn(
246
+ [
247
+ screenText('Inbox', { fontSize: 18, color: '#e8eaed' }),
248
+ screenColumn(
249
+ [
250
+ screenRow(
251
+ [
252
+ screenExpanded(
253
+ screenColumn(
254
+ [
255
+ screenText('Design review', { fontSize: 13, color: '#e8eaed' }),
256
+ screenText('Updated mockups are ready for sign-off.', {
257
+ fontSize: 11,
258
+ ...muted,
259
+ }),
260
+ ],
261
+ { gap: 2 },
262
+ ),
263
+ ),
264
+ screenText('9:41', { fontSize: 10, ...muted }),
265
+ ],
266
+ { gap: 8, padding: 10, background: '#1e2127' },
267
+ ),
268
+ screenRow(
269
+ [
270
+ screenExpanded(
271
+ screenColumn(
272
+ [
273
+ screenText('Deploy notice', { fontSize: 13, color: '#e8eaed' }),
274
+ screenText('Production release completed successfully.', {
275
+ fontSize: 11,
276
+ ...muted,
277
+ }),
278
+ ],
279
+ { gap: 2 },
280
+ ),
281
+ ),
282
+ screenText('8:05', { fontSize: 10, ...muted }),
283
+ ],
284
+ { gap: 8, padding: 10, background: '#1e2127' },
285
+ ),
286
+ screenRow(
287
+ [
288
+ screenExpanded(
289
+ screenColumn(
290
+ [
291
+ screenText('Weekly summary', { fontSize: 13, color: '#e8eaed' }),
292
+ screenText('Your workspace activity report is available.', {
293
+ fontSize: 11,
294
+ ...muted,
295
+ }),
296
+ ],
297
+ { gap: 2 },
298
+ ),
299
+ ),
300
+ screenText('Mon', { fontSize: 10, ...muted }),
301
+ ],
302
+ { gap: 8, padding: 10, background: '#1e2127' },
303
+ ),
304
+ ],
305
+ { gap: 8 },
306
+ ),
307
+ ],
308
+ { gap: 10, padding: 16, background: '#13151a' },
309
+ ),
310
+ }),
311
+ defineScreen({
312
+ id: 'app-toolbar',
313
+ title: 'App Toolbar',
314
+ description: 'Horizontal navigation bar with brand, links, and primary action.',
315
+ frameWidth: 720,
316
+ layout: { maxWidth: 720, maxHeight: 72 },
317
+ root: screenRow(
318
+ [
319
+ screenText('Workbench', { fontSize: 14, color: '#e8eaed' }),
320
+ screenText('Projects', { fontSize: 12, ...accent }),
321
+ screenText('Assets', { fontSize: 12, ...muted }),
322
+ screenText('Docs', { fontSize: 12, ...muted }),
323
+ screenExpanded(screenText(' ', { fontSize: 12 })),
324
+ screenPanel('New project', '#2b5d9f'),
325
+ ],
326
+ { gap: 16, padding: 14, background: '#1e2127' },
327
+ ),
328
+ }),
329
+ defineScreen({
330
+ id: 'hero-landing',
331
+ title: 'Hero Landing',
332
+ description: 'Centered hero copy with supporting text and call-to-action row.',
333
+ frameWidth: 720,
334
+ layout: { maxWidth: 720, maxHeight: 320 },
335
+ root: screenColumn(
336
+ [
337
+ screenText('Build widget screens from JSON', { fontSize: 26, color: '#e8eaed' }),
338
+ screenText(
339
+ 'Compose layouts with row, column, grid, and stack primitives. Preview instantly in Storybook.',
340
+ {
341
+ fontSize: 13,
342
+ ...muted,
343
+ },
344
+ ),
345
+ screenRow([screenPanel('Get started', '#2b5d9f'), screenPanel('View samples', '#2b2f36')], {
346
+ gap: 12,
347
+ }),
348
+ ],
349
+ { gap: 16, padding: 32, background: '#13151a' },
350
+ ),
351
+ }),
352
+ defineScreen({
353
+ id: 'stack-badge-card',
354
+ title: 'Stack Badge Card',
355
+ description: 'Card body with a positioned badge overlay using stack placement.',
356
+ frameWidth: 360,
357
+ layout: { maxWidth: 360, maxHeight: 200 },
358
+ root: screenStack(
359
+ [
360
+ screenColumn(
361
+ [
362
+ screenPanel(' ', '#2b2f36'),
363
+ screenText('Product launch', { fontSize: 15, color: '#e8eaed' }),
364
+ screenText('Ship the first JDW sample gallery.', { fontSize: 11, ...muted }),
365
+ ],
366
+ { gap: 8, padding: 16, background: '#1e2127' },
367
+ ),
368
+ {
369
+ kind: 'text',
370
+ content: 'NEW',
371
+ style: { fontSize: 10, color: '#13151a', background: '#fbbc04' },
372
+ top: 10,
373
+ right: 10,
374
+ left: 300,
375
+ bottom: 160,
376
+ },
377
+ ],
378
+ { background: '#13151a' },
379
+ ),
380
+ }),
381
+ defineScreen({
382
+ id: 'feature-grid',
383
+ title: 'Feature Grid',
384
+ description: 'Two-by-three feature tiles with icon placeholders.',
385
+ frameWidth: 640,
386
+ layout: { maxWidth: 640, maxHeight: 360 },
387
+ root: screenColumn(
388
+ [
389
+ screenText('Platform features', { fontSize: 18, color: '#e8eaed' }),
390
+ screenGrid(2, [
391
+ screenColumn(
392
+ [
393
+ screenPanel('⚡', '#2b2f36'),
394
+ screenText('Fast preview', { fontSize: 13, color: '#e8eaed' }),
395
+ screenText('Layout rects drive CSS rendering.', { fontSize: 11, ...muted }),
396
+ ],
397
+ {
398
+ gap: 6,
399
+ col: 0,
400
+ row: 0,
401
+ padding: 12,
402
+ background: '#1e2127',
403
+ },
404
+ ),
405
+ screenColumn(
406
+ [
407
+ screenPanel('📐', '#2b2f36'),
408
+ screenText('Headless layout', { fontSize: 13, color: '#e8eaed' }),
409
+ screenText('Shared math for row, grid, and stack.', { fontSize: 11, ...muted }),
410
+ ],
411
+ {
412
+ gap: 6,
413
+ col: 1,
414
+ row: 0,
415
+ padding: 12,
416
+ background: '#1e2127',
417
+ },
418
+ ),
419
+ screenColumn(
420
+ [
421
+ screenPanel('🧩', '#2b2f36'),
422
+ screenText('Composable assets', { fontSize: 13, color: '#e8eaed' }),
423
+ screenText('Package manifest + content.json.', { fontSize: 11, ...muted }),
424
+ ],
425
+ {
426
+ gap: 6,
427
+ col: 0,
428
+ row: 1,
429
+ padding: 12,
430
+ background: '#1e2127',
431
+ },
432
+ ),
433
+ screenColumn(
434
+ [
435
+ screenPanel('✓', '#2b2f36'),
436
+ screenText('Schema validation', { fontSize: 13, color: '#e8eaed' }),
437
+ screenText('JDW profile checks before render.', { fontSize: 11, ...muted }),
438
+ ],
439
+ {
440
+ gap: 6,
441
+ col: 1,
442
+ row: 1,
443
+ padding: 12,
444
+ background: '#1e2127',
445
+ },
446
+ ),
447
+ ]),
448
+ ],
449
+ { gap: 16, padding: 20, background: '#13151a' },
450
+ ),
451
+ }),
452
+ defineScreen({
453
+ id: 'status-board',
454
+ title: 'Status Board',
455
+ description: 'Service health rows with colored status chips.',
456
+ frameWidth: 560,
457
+ layout: { maxWidth: 560, maxHeight: 260 },
458
+ root: screenColumn(
459
+ [
460
+ screenText('System status', { fontSize: 18, color: '#e8eaed' }),
461
+ screenColumn(
462
+ [
463
+ screenRow(
464
+ [
465
+ screenExpanded(screenText('API gateway', { fontSize: 13, color: '#e8eaed' })),
466
+ screenText('Operational', {
467
+ fontSize: 11,
468
+ color: '#34a853',
469
+ background: '#1a2e1f',
470
+ }),
471
+ ],
472
+ { gap: 8 },
473
+ ),
474
+ screenRow(
475
+ [
476
+ screenExpanded(screenText('Widget renderer', { fontSize: 13, color: '#e8eaed' })),
477
+ screenText('Operational', {
478
+ fontSize: 11,
479
+ color: '#34a853',
480
+ background: '#1a2e1f',
481
+ }),
482
+ ],
483
+ { gap: 8 },
484
+ ),
485
+ screenRow(
486
+ [
487
+ screenExpanded(screenText('Asset sync', { fontSize: 13, color: '#e8eaed' })),
488
+ screenText('Degraded', { fontSize: 11, color: '#fbbc04', background: '#2e2818' }),
489
+ ],
490
+ { gap: 8 },
491
+ ),
492
+ ],
493
+ { gap: 8 },
494
+ ),
495
+ ],
496
+ { gap: 12, padding: 20, background: '#13151a' },
497
+ ),
498
+ }),
499
+ ];
500
+
501
+ export function sampleLayoutConstraints(
502
+ screenDefinition: JdwSampleScreenDefinition,
503
+ ): LayoutConstraints {
504
+ return {
505
+ minWidth: 0,
506
+ maxWidth: screenDefinition.layout.maxWidth,
507
+ minHeight: 0,
508
+ maxHeight: screenDefinition.layout.maxHeight,
509
+ };
510
+ }
511
+
512
+ export function formatJdwSampleScreenJson(screenDefinition: JdwSampleScreenDefinition): string {
513
+ return compileScreenSpecToJson(screenDefinition);
514
+ }
515
+
516
+ export function formatJdwSampleScreenSpec(screenDefinition: JdwSampleScreenDefinition): string {
517
+ return `${JSON.stringify(screenDefinition, null, 2)}\n`;
518
+ }
519
+
520
+ export const JDW_SAMPLE_SCREEN_MAP = Object.fromEntries(
521
+ JDW_SAMPLE_SCREENS.map((sample) => [sample.id, sample]),
522
+ ) as Record<string, JdwSampleScreenDefinition>;
@@ -0,0 +1,45 @@
1
+ export { JdwPreview, type JdwPreviewProps } from './JdwPreview.js';
2
+ export {
3
+ JDW_DOCUMENT_FILE_EXTENSION,
4
+ JDW_DOCUMENT_MIME,
5
+ JDW_SCHEMA_DOCUMENT_FILE_EXTENSION,
6
+ JDW_SCHEMA_DOCUMENT_MIME,
7
+ JDW_WIDGET_DOCUMENT_FILE_EXTENSION,
8
+ JDW_WIDGET_DOCUMENT_MIME,
9
+ isJdwDocument,
10
+ isJdwDocumentMimeType,
11
+ isJdwDocumentPath,
12
+ isJdwSchemaDocument,
13
+ isJdwSchemaDocumentMimeType,
14
+ isJdwSchemaDocumentPath,
15
+ type JdwDocumentRef,
16
+ type JdwSchemaDocumentRef,
17
+ } from './document.js';
18
+ export {
19
+ JsonCodeEditorPane,
20
+ JsonConfigValidationBanner,
21
+ type JsonCodeEditorPaneProps,
22
+ type JsonConfigValidationBannerProps,
23
+ } from './JsonCodeEditorPane.js';
24
+ export { renderJdw, renderJdwNode, useRenderJdw, type RenderJdwOptions } from './renderJdw.js';
25
+ export {
26
+ renderCssLayoutTree,
27
+ renderJdwWithLayout,
28
+ type CssRenderBackendOptions,
29
+ } from './cssRenderBackend.js';
30
+ export { BUILTIN_JDW_REGISTRY, createBuiltinJdwRegistry } from './createBuiltinJdwRegistry.js';
31
+ export { renderBuiltinWidgetNode } from './builtins/renderBuiltinWidgetNode.js';
32
+ export {
33
+ formatJdwSampleScreenJson,
34
+ formatJdwSampleScreenSpec,
35
+ JDW_SAMPLE_SCREENS,
36
+ JDW_SAMPLE_SCREEN_MAP,
37
+ sampleLayoutConstraints,
38
+ type JdwSampleScreenDefinition,
39
+ } from './fixtures/jdw-sample-screens.js';
40
+ export {
41
+ compileScreenSpecText,
42
+ parseScreenSpecJson,
43
+ type CompiledScreenSpecText,
44
+ type ParsedScreenSpec,
45
+ } from '@workbench-kit/jdw';
@@ -0,0 +1 @@
1
+ export { parseJsonWidgetData, type ParsedJsonWidgetData } from '@workbench-kit/jdw';
@@ -0,0 +1,32 @@
1
+ import { useMemo, type ReactNode } from 'react';
2
+ import {
3
+ parseJsonWidgetData,
4
+ validateJsonWidgetData,
5
+ type JsonWidgetNode,
6
+ } from '@workbench-kit/jdw';
7
+
8
+ import { renderJdwWithLayout, type CssRenderBackendOptions } from './cssRenderBackend.js';
9
+
10
+ export type RenderJdwOptions = CssRenderBackendOptions;
11
+
12
+ export function renderJdwNode(node: JsonWidgetNode, options: RenderJdwOptions = {}): ReactNode {
13
+ return renderJdwWithLayout(node, options);
14
+ }
15
+
16
+ export function renderJdw(source: string, options: RenderJdwOptions = {}): ReactNode {
17
+ const parsed = parseJsonWidgetData(source);
18
+ if (parsed.parseError !== null || parsed.value === null) {
19
+ return null;
20
+ }
21
+
22
+ validateJsonWidgetData(source);
23
+ return renderJdwWithLayout(parsed.value, options);
24
+ }
25
+
26
+ export function useRenderJdw(source: string, options: RenderJdwOptions = {}): ReactNode {
27
+ const { registry, emptyLabel, layoutConstraints } = options;
28
+ return useMemo(
29
+ () => renderJdw(source, { registry, emptyLabel, layoutConstraints }),
30
+ [emptyLabel, layoutConstraints, registry, source],
31
+ );
32
+ }