@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,302 @@
1
+ import type { ComponentPropsWithRef, ReactNode } from 'react';
2
+ import { EmptyState } from '../primitives/EmptyState';
3
+ import { cxCodicon } from '../utils/codicon';
4
+ import { cx } from '../utils/cx';
5
+ import { getWorkbenchStatusLabel, isWorkbenchStatusBusy, type WorkbenchStatus } from './status';
6
+
7
+ export type WorkbenchTimelineEventKind =
8
+ | 'message'
9
+ | 'operation-call'
10
+ | 'operation-result'
11
+ | 'file-write'
12
+ | 'progress'
13
+ | 'error';
14
+
15
+ export type WorkbenchTimelineMessageSource = 'assistant' | 'system' | 'user' | (string & {});
16
+ export type WorkbenchTimelineVariant = 'compact' | 'expanded';
17
+
18
+ export interface WorkbenchTimelineEvent {
19
+ content?: ReactNode | undefined;
20
+ description?: ReactNode | undefined;
21
+ id: string;
22
+ kind: WorkbenchTimelineEventKind;
23
+ metadata?: Record<string, unknown> | undefined;
24
+ payload?: unknown;
25
+ source?: WorkbenchTimelineMessageSource | undefined;
26
+ status?: WorkbenchStatus | undefined;
27
+ timestamp?: ReactNode | undefined;
28
+ title?: ReactNode | undefined;
29
+ }
30
+
31
+ export interface WorkbenchTimelineRenderContext {
32
+ defaultLabel: string;
33
+ index: number;
34
+ status: WorkbenchStatus;
35
+ variant: WorkbenchTimelineVariant;
36
+ }
37
+
38
+ export interface WorkbenchTimelineMetadataEntry {
39
+ label: string;
40
+ value: string;
41
+ }
42
+
43
+ export type WorkbenchTimelineRenderMetadata = (
44
+ event: WorkbenchTimelineEvent,
45
+ context: WorkbenchTimelineRenderContext,
46
+ ) => ReactNode;
47
+
48
+ export type WorkbenchTimelineRenderPayload = (
49
+ event: WorkbenchTimelineEvent,
50
+ context: WorkbenchTimelineRenderContext,
51
+ ) => ReactNode;
52
+
53
+ const timelineEventLabels: Record<WorkbenchTimelineEventKind, string> = {
54
+ error: 'Error',
55
+ 'file-write': 'File write',
56
+ message: 'Message',
57
+ 'operation-call': 'Operation call',
58
+ 'operation-result': 'Operation result',
59
+ progress: 'Progress',
60
+ };
61
+
62
+ const timelineEventIconClasses: Record<WorkbenchTimelineEventKind, string> = {
63
+ error: 'codicon-error',
64
+ 'file-write': 'codicon-save',
65
+ message: 'codicon-comment-discussion',
66
+ 'operation-call': 'codicon-debug-start',
67
+ 'operation-result': 'codicon-check',
68
+ progress: 'codicon-loading',
69
+ };
70
+
71
+ const timelineEventDefaultStatuses: Record<WorkbenchTimelineEventKind, WorkbenchStatus> = {
72
+ error: 'failed',
73
+ 'file-write': 'completed',
74
+ message: 'idle',
75
+ 'operation-call': 'running',
76
+ 'operation-result': 'completed',
77
+ progress: 'running',
78
+ };
79
+
80
+ export function getWorkbenchTimelineEventLabel(
81
+ eventOrKind: WorkbenchTimelineEvent | WorkbenchTimelineEventKind,
82
+ ) {
83
+ const kind = typeof eventOrKind === 'string' ? eventOrKind : eventOrKind.kind;
84
+ return timelineEventLabels[kind];
85
+ }
86
+
87
+ export function getWorkbenchTimelineEventIconClass(
88
+ eventOrKind: WorkbenchTimelineEvent | WorkbenchTimelineEventKind,
89
+ ) {
90
+ const kind = typeof eventOrKind === 'string' ? eventOrKind : eventOrKind.kind;
91
+ return timelineEventIconClasses[kind];
92
+ }
93
+
94
+ export function getWorkbenchTimelineEventStatus(event: WorkbenchTimelineEvent): WorkbenchStatus {
95
+ return event.status ?? timelineEventDefaultStatuses[event.kind];
96
+ }
97
+
98
+ export function formatWorkbenchTimelineMetadataValue(value: unknown): string {
99
+ if (value === null) return 'null';
100
+ if (typeof value === 'string') return value;
101
+ if (typeof value === 'number' || typeof value === 'boolean') return String(value);
102
+ if (value === undefined) return '';
103
+
104
+ try {
105
+ return JSON.stringify(value);
106
+ } catch {
107
+ return String(value);
108
+ }
109
+ }
110
+
111
+ export function getWorkbenchTimelineMetadataEntries(
112
+ event: WorkbenchTimelineEvent,
113
+ ): WorkbenchTimelineMetadataEntry[] {
114
+ return Object.entries(event.metadata ?? {})
115
+ .filter(([, value]) => value !== undefined)
116
+ .map(([label, value]) => ({
117
+ label,
118
+ value: formatWorkbenchTimelineMetadataValue(value),
119
+ }));
120
+ }
121
+
122
+ function createTimelineRenderContext(
123
+ event: WorkbenchTimelineEvent,
124
+ index: number,
125
+ variant: WorkbenchTimelineVariant,
126
+ ): WorkbenchTimelineRenderContext {
127
+ return {
128
+ defaultLabel: getWorkbenchTimelineEventLabel(event),
129
+ index,
130
+ status: getWorkbenchTimelineEventStatus(event),
131
+ variant,
132
+ };
133
+ }
134
+
135
+ function defaultPayload(event: WorkbenchTimelineEvent) {
136
+ if (event.payload === undefined) return null;
137
+
138
+ return (
139
+ <pre className="ui-workbench-timeline-event__payload">
140
+ {formatWorkbenchTimelineMetadataValue(event.payload)}
141
+ </pre>
142
+ );
143
+ }
144
+
145
+ function defaultMetadata(event: WorkbenchTimelineEvent) {
146
+ const entries = getWorkbenchTimelineMetadataEntries(event);
147
+ if (entries.length === 0) return null;
148
+
149
+ return (
150
+ <dl className="ui-workbench-timeline-event__metadata">
151
+ {entries.map((entry) => (
152
+ <div key={entry.label} className="ui-workbench-timeline-event__metadata-row">
153
+ <dt>{entry.label}</dt>
154
+ <dd>{entry.value}</dd>
155
+ </div>
156
+ ))}
157
+ </dl>
158
+ );
159
+ }
160
+
161
+ function timelineEventTitle(event: WorkbenchTimelineEvent, defaultLabel: string) {
162
+ if (event.title) return event.title;
163
+ if (event.kind === 'message' && event.source === 'user') return 'User message';
164
+ if (event.kind === 'message' && event.source === 'assistant') return 'Assistant message';
165
+ if (event.kind === 'message' && event.source === 'system') return 'System message';
166
+ return defaultLabel;
167
+ }
168
+
169
+ function timelineEventAccessibleTitle(title: ReactNode, fallback: string) {
170
+ if (typeof title === 'string') return title;
171
+ if (typeof title === 'number') return String(title);
172
+ return fallback;
173
+ }
174
+
175
+ export interface WorkbenchTimelineItemProps extends Omit<
176
+ ComponentPropsWithRef<'article'>,
177
+ 'children'
178
+ > {
179
+ event: WorkbenchTimelineEvent;
180
+ index?: number | undefined;
181
+ renderMetadata?: WorkbenchTimelineRenderMetadata | undefined;
182
+ renderPayload?: WorkbenchTimelineRenderPayload | undefined;
183
+ variant?: WorkbenchTimelineVariant | undefined;
184
+ }
185
+
186
+ export function WorkbenchTimelineItem({
187
+ className,
188
+ event,
189
+ index = 0,
190
+ renderMetadata,
191
+ renderPayload,
192
+ variant = 'expanded',
193
+ ...props
194
+ }: WorkbenchTimelineItemProps) {
195
+ const context = createTimelineRenderContext(event, index, variant);
196
+ const title = timelineEventTitle(event, context.defaultLabel);
197
+ const accessibleTitle = timelineEventAccessibleTitle(title, context.defaultLabel);
198
+ const statusLabel = getWorkbenchStatusLabel(context.status);
199
+ const metadataNode = renderMetadata ? renderMetadata(event, context) : defaultMetadata(event);
200
+ const payloadNode = renderPayload ? renderPayload(event, context) : defaultPayload(event);
201
+
202
+ return (
203
+ <article
204
+ aria-busy={isWorkbenchStatusBusy(context.status) ? true : undefined}
205
+ aria-label={`${context.defaultLabel}: ${accessibleTitle}`}
206
+ className={cx('ui-workbench-timeline-event', className)}
207
+ data-kind={event.kind}
208
+ data-source={event.source}
209
+ data-status={context.status}
210
+ data-variant={variant}
211
+ role="listitem"
212
+ {...props}
213
+ >
214
+ <div className="ui-workbench-timeline-event__rail" aria-hidden="true">
215
+ <span className="ui-workbench-timeline-event__icon">
216
+ <i className={cxCodicon(getWorkbenchTimelineEventIconClass(event))} />
217
+ </span>
218
+ </div>
219
+ <div className="ui-workbench-timeline-event__card">
220
+ <header className="ui-workbench-timeline-event__header">
221
+ <div className="ui-workbench-timeline-event__title-group">
222
+ <span className="ui-workbench-timeline-event__eyebrow">{context.defaultLabel}</span>
223
+ <span className="ui-workbench-timeline-event__title">{title}</span>
224
+ </div>
225
+ <div className="ui-workbench-timeline-event__meta">
226
+ <span
227
+ aria-label={`Status: ${statusLabel}`}
228
+ className="ui-workbench-timeline-event__status"
229
+ title={statusLabel}
230
+ >
231
+ <span aria-hidden="true" className="ui-workbench-timeline-event__status-dot" />
232
+ <span>{statusLabel}</span>
233
+ </span>
234
+ {event.timestamp ? (
235
+ <time className="ui-workbench-timeline-event__time">{event.timestamp}</time>
236
+ ) : null}
237
+ </div>
238
+ </header>
239
+ {event.description ? (
240
+ <div className="ui-workbench-timeline-event__description">{event.description}</div>
241
+ ) : null}
242
+ {event.content ? (
243
+ <div className="ui-workbench-timeline-event__content">{event.content}</div>
244
+ ) : null}
245
+ {payloadNode}
246
+ {metadataNode}
247
+ </div>
248
+ </article>
249
+ );
250
+ }
251
+
252
+ export interface WorkbenchTimelineProps extends Omit<ComponentPropsWithRef<'div'>, 'children'> {
253
+ emptyLabel?: ReactNode | undefined;
254
+ events: readonly WorkbenchTimelineEvent[];
255
+ renderMetadata?: WorkbenchTimelineRenderMetadata | undefined;
256
+ renderPayload?: WorkbenchTimelineRenderPayload | undefined;
257
+ variant?: WorkbenchTimelineVariant | undefined;
258
+ }
259
+
260
+ export function WorkbenchTimeline({
261
+ className,
262
+ emptyLabel = 'No timeline events',
263
+ events,
264
+ renderMetadata,
265
+ renderPayload,
266
+ variant = 'expanded',
267
+ ...props
268
+ }: WorkbenchTimelineProps) {
269
+ if (events.length === 0) {
270
+ return (
271
+ <div className={cx('ui-workbench-timeline', className)} {...props}>
272
+ <EmptyState compact icon="codicon-comment-discussion">
273
+ {emptyLabel}
274
+ </EmptyState>
275
+ </div>
276
+ );
277
+ }
278
+
279
+ return (
280
+ <div
281
+ aria-label={props['aria-label'] ?? 'Workbench timeline'}
282
+ className={cx(
283
+ 'ui-workbench-timeline',
284
+ variant === 'compact' && 'ui-workbench-timeline--compact',
285
+ className,
286
+ )}
287
+ role="list"
288
+ {...props}
289
+ >
290
+ {events.map((event, index) => (
291
+ <WorkbenchTimelineItem
292
+ key={event.id}
293
+ event={event}
294
+ index={index}
295
+ renderMetadata={renderMetadata}
296
+ renderPayload={renderPayload}
297
+ variant={variant}
298
+ />
299
+ ))}
300
+ </div>
301
+ );
302
+ }