@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.
- package/package.json +33 -9
- package/src/index.ts +545 -43
- package/src/jdw/JdwPreview.tsx +38 -0
- package/src/jdw/JsonCodeEditorPane.tsx +274 -0
- package/src/jdw/builtins/renderBuiltinWidgetLeaf.tsx +29 -0
- package/src/jdw/builtins/renderBuiltinWidgetNode.tsx +126 -0
- package/src/jdw/createBuiltinJdwRegistry.ts +111 -0
- package/src/jdw/cssRenderBackend.tsx +134 -0
- package/src/jdw/document.ts +38 -0
- package/src/jdw/fixtures/jdw-fixtures.ts +52 -0
- package/src/jdw/fixtures/jdw-sample-screens.ts +522 -0
- package/src/jdw/index.ts +45 -0
- package/src/jdw/parse.ts +1 -0
- package/src/jdw/renderJdw.tsx +32 -0
- package/src/json-config/JsonConfigWorkbench.tsx +316 -0
- package/src/json-config/index.ts +6 -0
- package/src/json-config/json-config-editor-state.ts +42 -0
- package/src/layout/Panel.tsx +146 -1
- package/src/layout/SideBarViewFrame.tsx +367 -328
- package/src/layout/WorkbenchCanvas.tsx +849 -0
- package/src/layout/WorkbenchFullscreen.tsx +368 -0
- package/src/layout/WorkbenchLayout.tsx +5 -0
- package/src/layout/WorkbenchLayoutBase.tsx +294 -0
- package/src/layout/WorkbenchPropertyPanel.tsx +497 -0
- package/src/layout/WorkbenchSidebarActions.tsx +274 -0
- package/src/layout/WorkbenchTree.tsx +351 -0
- package/src/layout/layoutHelpers.ts +25 -0
- package/src/modal/ConfirmDialog.tsx +61 -53
- package/src/modal/Modal.tsx +295 -35
- package/src/overlay/ContextMenu.tsx +146 -145
- package/src/primitives/AbsoluteBox.tsx +46 -0
- package/src/primitives/Badge.tsx +12 -12
- package/src/primitives/Button.tsx +44 -14
- package/src/primitives/Checkbox.tsx +11 -5
- package/src/primitives/EmptyState.tsx +27 -26
- package/src/primitives/Field.tsx +38 -38
- package/src/primitives/IconButton.tsx +5 -2
- package/src/primitives/List.tsx +111 -0
- package/src/primitives/NumberInput.tsx +38 -0
- package/src/primitives/ScrollArea.tsx +42 -0
- package/src/primitives/Select.tsx +1 -12
- package/src/primitives/StatusBar.tsx +46 -0
- package/src/primitives/TextArea.tsx +36 -0
- package/src/primitives/TextInput.tsx +11 -2
- package/src/primitives/WorkbenchChrome.tsx +424 -0
- package/src/primitives/WorkbenchEditor.tsx +394 -0
- package/src/primitives/index.ts +105 -0
- package/src/primitives/select/Select.tsx +266 -0
- package/src/primitives/select/index.ts +2 -0
- package/src/primitives/select/options.ts +38 -0
- package/src/primitives/select/overlay.ts +63 -0
- package/src/primitives/select/select.app.css +9 -0
- package/src/primitives/select/select.css +140 -0
- package/src/primitives/select/types.ts +18 -0
- package/src/primitives/styles.css +955 -0
- package/src/scrollbars.css +69 -0
- package/src/styles.css +7738 -1762
- package/src/utils/codicon.ts +17 -0
- package/src/widget-asset/WidgetAssetEditor.tsx +140 -0
- package/src/widget-asset/WidgetAssetMetadataForm.tsx +82 -0
- package/src/widget-asset/WidgetAssetModeControls.tsx +42 -0
- package/src/widget-asset/WidgetAssetSourceEditor.tsx +50 -0
- package/src/widget-asset/WidgetAssetWorkbench.tsx +112 -0
- package/src/widget-asset/index.ts +17 -0
- package/src/widget-asset/widget-asset-document.ts +37 -0
- package/src/widget-asset/widget-asset-mode.ts +3 -0
- package/src/widget-studio/builtin-widget-asset-catalog.ts +12 -0
- package/src/widget-studio/create-widget-studio-workspace-editor.tsx +79 -0
- package/src/widget-studio/index.ts +7 -0
- package/src/widget-studio/resolve-widget-studio-asset-catalog.ts +26 -0
- package/src/widget-tree/WidgetAssetPalette.tsx +77 -0
- package/src/widget-tree/WidgetInspectorPanel.tsx +266 -0
- package/src/widget-tree/WidgetSourceEditor.tsx +56 -0
- package/src/widget-tree/WidgetTreeLab.tsx +272 -0
- package/src/widget-tree/WidgetTreeModeControls.tsx +44 -0
- package/src/widget-tree/WidgetTreeSidePanel.tsx +49 -0
- package/src/widget-tree/WidgetTreeView.tsx +97 -0
- package/src/widget-tree/WidgetTreeWorkbench.tsx +111 -0
- package/src/widget-tree/WidgetTreeWorkspaceShell.tsx +154 -0
- package/src/widget-tree/demo-registry.ts +32 -0
- package/src/widget-tree/demo-widget-assets.ts +4 -0
- package/src/widget-tree/index.ts +27 -0
- package/src/widget-tree/widget-tree-document.ts +20 -0
- package/src/widget-tree/widget-tree-layout.ts +31 -0
- package/src/widget-tree/widget-tree-mode.ts +7 -0
- package/src/widget-tree/widget-tree-play-helpers.ts +74 -0
- package/src/workbench/ActivityBar.tsx +52 -52
- package/src/workbench/ArtifactShell.tsx +397 -0
- package/src/workbench/CommandPalette.tsx +819 -0
- package/src/workbench/ConfirmationFlow.tsx +245 -0
- package/src/workbench/MarkdownPreview.tsx +151 -0
- package/src/workbench/ShortcutCommandBridge.tsx +368 -0
- package/src/workbench/SplitView.tsx +136 -136
- package/src/workbench/StatusBar.tsx +178 -123
- package/src/workbench/StructuredArtifactEditor.tsx +205 -0
- package/src/workbench/Timeline.tsx +302 -0
- package/src/workbench/WorkbenchCanvasShell.tsx +941 -0
- package/src/workbench/WorkbenchShell.tsx +74 -70
- package/src/workbench/WorkbenchStandaloneShell.tsx +318 -291
- package/src/workbench/auth/WorkbenchAuthGate.tsx +61 -0
- package/src/workbench/auth/WorkbenchLoginView.tsx +635 -0
- package/src/workbench/auth/index.ts +19 -0
- package/src/workbench/chat/ChatComposer.tsx +165 -148
- package/src/workbench/chat/ChatMessageItem.tsx +10 -1
- package/src/workbench/chat/index.ts +9 -0
- package/src/workbench/chat/slashCommand.ts +28 -0
- package/src/workbench/chat/useChatRuntimeState.ts +76 -0
- package/src/workbench/chat/useSlashCommandSuggest.ts +101 -0
- package/src/workbench/commands.ts +520 -490
- package/src/workbench/index.ts +443 -98
- package/src/workbench/keyboard.ts +53 -0
- package/src/workbench/schema/index.ts +48 -0
- package/src/workbench/schema/workbenchDocument.ts +31 -0
- package/src/workbench/schema/workbenchDocumentActions.ts +6 -0
- package/src/workbench/schema/workbenchDocumentAdapter.ts +9 -0
- package/src/workbench/schema/workbenchDocumentPatch.ts +13 -0
- package/src/workbench/schema/workbenchDocumentRenderer.tsx +702 -0
- package/src/workbench/settings/NavigationPanel.tsx +47 -0
- package/src/workbench/settings/SchemaForm.tsx +420 -0
- package/src/workbench/settings/SectionedPanel.tsx +415 -0
- package/src/workbench/settings/StructuredDataForm.tsx +539 -0
- package/src/workbench/settings/StructuredDataSchemaPanel.tsx +559 -0
- package/src/workbench/settings/StructuredDataSchemaPanelEmbed.tsx +21 -0
- package/src/workbench/settings/StructuredDataSchemaPanelFrame.tsx +76 -0
- package/src/workbench/settings/StructuredDataTableView.tsx +127 -0
- package/src/workbench/settings/WorkbenchPanelRegion.tsx +46 -0
- package/src/workbench/settings/WorkbenchSettingsModal.tsx +21 -12
- package/src/workbench/settings/WorkbenchSettingsNav.tsx +38 -22
- package/src/workbench/settings/index.ts +135 -0
- package/src/workbench/settings/panel-region.css +21 -0
- package/src/workbench/settings/sectionedPanelScrollSpy.ts +143 -0
- package/src/workbench/settings/structured-data-schema-panel.css +330 -0
- package/src/workbench/settings/structured-data-table-view.css +85 -0
- package/src/workbench/settings/structuredDataSchema.ts +886 -0
- package/src/workbench/shell.ts +15 -0
- package/src/workbench/shellState.ts +203 -203
- package/src/workbench/standalone.ts +101 -94
- package/src/workbench/status.ts +129 -0
- package/src/workbench/theme.ts +44 -0
- package/src/workbench/workspace/MultiProviderExplorer.tsx +625 -0
- package/src/workbench/workspace/WorkspaceDraftsContext.tsx +111 -0
- package/src/workbench/workspace/WorkspaceEditor.tsx +47 -12
- package/src/workbench/workspace/WorkspaceEditorPanel.tsx +334 -353
- package/src/workbench/workspace/WorkspaceExplorer.tsx +532 -524
- package/src/workbench/workspace/WorkspaceFileIcon.tsx +32 -2
- package/src/workbench/workspace/WorkspaceSearchPanel.tsx +113 -113
- package/src/workbench/workspace/WorkspaceSearchResults.tsx +47 -47
- package/src/workbench/workspace/index.ts +156 -98
- package/src/workbench/workspace/mimeType.ts +45 -0
- package/src/workbench/workspace/path.ts +10 -10
- package/src/workbench/workspace/search.ts +6 -6
- package/src/workbench/workspace/tree.ts +1 -1
- package/src/workbench/workspace/types.ts +10 -10
- package/src/workbench/workspace/useVirtualWorkspace.ts +111 -98
- package/src/workbench/workspace/workspaceJsonDiagnostics.ts +83 -0
|
@@ -0,0 +1,886 @@
|
|
|
1
|
+
import type { ComponentPropsWithRef, FormEvent, ReactNode } from 'react';
|
|
2
|
+
import {
|
|
3
|
+
asWorkbenchStructuredDataRecord,
|
|
4
|
+
getWorkbenchStructuredDataValue,
|
|
5
|
+
isWorkbenchStructuredDataRecord,
|
|
6
|
+
setWorkbenchStructuredDataPathOrRootValue,
|
|
7
|
+
setWorkbenchStructuredDataValue,
|
|
8
|
+
type WorkbenchStructuredDataPath,
|
|
9
|
+
type WorkbenchStructuredDataRecord,
|
|
10
|
+
} from '@workbench-kit/workspace';
|
|
11
|
+
|
|
12
|
+
export type { WorkbenchStructuredDataPath, WorkbenchStructuredDataRecord };
|
|
13
|
+
export {
|
|
14
|
+
asWorkbenchStructuredDataRecord,
|
|
15
|
+
getWorkbenchStructuredDataValue,
|
|
16
|
+
isWorkbenchStructuredDataRecord,
|
|
17
|
+
setWorkbenchStructuredDataPathOrRootValue,
|
|
18
|
+
setWorkbenchStructuredDataValue,
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
export type WorkbenchStructuredDataFieldType =
|
|
22
|
+
| 'checkbox'
|
|
23
|
+
| 'number'
|
|
24
|
+
| 'select'
|
|
25
|
+
| 'text'
|
|
26
|
+
| 'text-array';
|
|
27
|
+
|
|
28
|
+
export type WorkbenchStructuredDataFieldValue = boolean | number | string | readonly string[];
|
|
29
|
+
|
|
30
|
+
export type WorkbenchStructuredDataFormErrors = Record<string, ReactNode>;
|
|
31
|
+
|
|
32
|
+
export type WorkbenchStructuredDataSchemaFieldControl =
|
|
33
|
+
| 'checkbox'
|
|
34
|
+
| 'date'
|
|
35
|
+
| 'number'
|
|
36
|
+
| 'select'
|
|
37
|
+
| 'text'
|
|
38
|
+
| 'textarea';
|
|
39
|
+
|
|
40
|
+
export interface WorkbenchStructuredDataSchemaFieldDefinition {
|
|
41
|
+
default?: unknown;
|
|
42
|
+
description?: string | undefined;
|
|
43
|
+
enum?: readonly (boolean | number | string)[] | undefined;
|
|
44
|
+
format?: string | undefined;
|
|
45
|
+
items?: {
|
|
46
|
+
type?: string | undefined;
|
|
47
|
+
};
|
|
48
|
+
markdownDescription?: string | undefined;
|
|
49
|
+
title?: string | undefined;
|
|
50
|
+
type?: string | undefined;
|
|
51
|
+
ui?: {
|
|
52
|
+
control?: WorkbenchStructuredDataSchemaFieldControl | string | undefined;
|
|
53
|
+
placeholder?: string | undefined;
|
|
54
|
+
rows?: number | undefined;
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
export interface WorkbenchStructuredDataSchemaSectionSummary {
|
|
59
|
+
columns?: readonly string[] | undefined;
|
|
60
|
+
dataPath?: string | undefined;
|
|
61
|
+
fieldCount?: number | undefined;
|
|
62
|
+
fields?: readonly string[] | undefined;
|
|
63
|
+
id?: string | undefined;
|
|
64
|
+
sectionKey?: string | undefined;
|
|
65
|
+
title?: string | undefined;
|
|
66
|
+
type?: string | undefined;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
export interface WorkbenchStructuredDataSchemaTableDefinition {
|
|
70
|
+
items?: Record<string, WorkbenchStructuredDataSchemaFieldDefinition> | undefined;
|
|
71
|
+
title?: string | undefined;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
export interface WorkbenchStructuredDataSchemaDocument {
|
|
75
|
+
activePattern?: string | undefined;
|
|
76
|
+
pattern?: string | undefined;
|
|
77
|
+
patterns?: readonly {
|
|
78
|
+
pattern: string;
|
|
79
|
+
sections?: readonly WorkbenchStructuredDataSchemaSectionSummary[] | undefined;
|
|
80
|
+
}[];
|
|
81
|
+
sampleDraft?: unknown;
|
|
82
|
+
sampleDrafts?: Record<string, unknown> | undefined;
|
|
83
|
+
schema?: {
|
|
84
|
+
properties?: Record<string, WorkbenchStructuredDataSchemaFieldDefinition> | undefined;
|
|
85
|
+
sections?: readonly WorkbenchStructuredDataSchemaSectionSummary[] | undefined;
|
|
86
|
+
tables?: Record<string, WorkbenchStructuredDataSchemaTableDefinition> | undefined;
|
|
87
|
+
};
|
|
88
|
+
ui?: {
|
|
89
|
+
patterns?: Record<
|
|
90
|
+
string,
|
|
91
|
+
{
|
|
92
|
+
label?: string | undefined;
|
|
93
|
+
sections?: readonly WorkbenchStructuredDataSchemaSectionSummary[] | undefined;
|
|
94
|
+
}
|
|
95
|
+
>;
|
|
96
|
+
};
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
export type WorkbenchStructuredDataSchemaSectionAliases = Record<
|
|
100
|
+
string,
|
|
101
|
+
readonly WorkbenchStructuredDataPath[]
|
|
102
|
+
>;
|
|
103
|
+
|
|
104
|
+
export interface WorkbenchStructuredDataSchemaTableColumnInput {
|
|
105
|
+
maxColumns?: number | undefined;
|
|
106
|
+
preferredColumns?: readonly string[] | undefined;
|
|
107
|
+
rows: readonly WorkbenchStructuredDataRecord[];
|
|
108
|
+
schemaColumns?: readonly string[] | undefined;
|
|
109
|
+
sectionColumns?: readonly string[] | undefined;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
export interface WorkbenchStructuredDataSchemaTableRowKeyInput {
|
|
113
|
+
row: WorkbenchStructuredDataRecord;
|
|
114
|
+
rowIndex: number;
|
|
115
|
+
value: unknown;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
export interface WorkbenchStructuredDataFormOption {
|
|
119
|
+
disabled?: boolean;
|
|
120
|
+
label: ReactNode;
|
|
121
|
+
value: string;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
export interface WorkbenchStructuredDataFormFieldBase {
|
|
125
|
+
defaultValue?: WorkbenchStructuredDataFieldValue;
|
|
126
|
+
description?: ReactNode;
|
|
127
|
+
disabled?: boolean;
|
|
128
|
+
id: string;
|
|
129
|
+
label: ReactNode;
|
|
130
|
+
metadata?: Record<string, unknown>;
|
|
131
|
+
path: WorkbenchStructuredDataPath;
|
|
132
|
+
readOnly?: boolean;
|
|
133
|
+
required?: boolean;
|
|
134
|
+
validationMessage?: ReactNode;
|
|
135
|
+
validate?: (
|
|
136
|
+
value: WorkbenchStructuredDataFieldValue,
|
|
137
|
+
data: WorkbenchStructuredDataRecord,
|
|
138
|
+
field: WorkbenchStructuredDataFormField,
|
|
139
|
+
) => ReactNode | undefined;
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
export interface WorkbenchStructuredDataFormTextField extends WorkbenchStructuredDataFormFieldBase {
|
|
143
|
+
autocomplete?: string;
|
|
144
|
+
monospace?: boolean;
|
|
145
|
+
placeholder?: string;
|
|
146
|
+
type: 'text';
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
export interface WorkbenchStructuredDataFormNumberField extends WorkbenchStructuredDataFormFieldBase {
|
|
150
|
+
max?: number;
|
|
151
|
+
min?: number;
|
|
152
|
+
placeholder?: string;
|
|
153
|
+
step?: number;
|
|
154
|
+
type: 'number';
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
export interface WorkbenchStructuredDataFormSelectField extends WorkbenchStructuredDataFormFieldBase {
|
|
158
|
+
emptyOptionLabel?: ReactNode;
|
|
159
|
+
options: readonly WorkbenchStructuredDataFormOption[];
|
|
160
|
+
type: 'select';
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
export interface WorkbenchStructuredDataFormCheckboxField extends WorkbenchStructuredDataFormFieldBase {
|
|
164
|
+
type: 'checkbox';
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
export interface WorkbenchStructuredDataFormTextArrayField extends WorkbenchStructuredDataFormFieldBase {
|
|
168
|
+
addLabel?: ReactNode;
|
|
169
|
+
emptyLabel?: ReactNode;
|
|
170
|
+
itemLabel?: string;
|
|
171
|
+
itemPlaceholder?: string;
|
|
172
|
+
maxItems?: number;
|
|
173
|
+
minItems?: number;
|
|
174
|
+
removeLabel?: string;
|
|
175
|
+
type: 'text-array';
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
export interface WorkbenchStructuredDataTextArrayInputProps extends Omit<
|
|
179
|
+
ComponentPropsWithRef<'div'>,
|
|
180
|
+
'children' | 'onChange'
|
|
181
|
+
> {
|
|
182
|
+
addLabel?: ReactNode | undefined;
|
|
183
|
+
ariaDescribedBy?: string | undefined;
|
|
184
|
+
ariaLabel: string;
|
|
185
|
+
disabled?: boolean | undefined;
|
|
186
|
+
emptyLabel?: ReactNode | undefined;
|
|
187
|
+
maxItems?: number | undefined;
|
|
188
|
+
minItems?: number | undefined;
|
|
189
|
+
placeholder?: string | undefined;
|
|
190
|
+
readOnly?: boolean | undefined;
|
|
191
|
+
removeLabel?: string | undefined;
|
|
192
|
+
value?: unknown;
|
|
193
|
+
onValueChange?: ((value: string[]) => void) | undefined;
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
export interface WorkbenchStructuredDataSchemaFieldInputProps {
|
|
197
|
+
addTextArrayLabel?: ReactNode | undefined;
|
|
198
|
+
checkboxClassName?: string | undefined;
|
|
199
|
+
className?: string | undefined;
|
|
200
|
+
definition?: WorkbenchStructuredDataSchemaFieldDefinition | undefined;
|
|
201
|
+
fieldPath: string;
|
|
202
|
+
readOnly?: boolean | undefined;
|
|
203
|
+
removeTextArrayLabel?: string | undefined;
|
|
204
|
+
textareaClassName?: string | undefined;
|
|
205
|
+
textArrayClassName?: string | undefined;
|
|
206
|
+
value: unknown;
|
|
207
|
+
onValueChange?: ((value: unknown) => void) | undefined;
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
export type WorkbenchStructuredDataFormField =
|
|
211
|
+
| WorkbenchStructuredDataFormCheckboxField
|
|
212
|
+
| WorkbenchStructuredDataFormNumberField
|
|
213
|
+
| WorkbenchStructuredDataFormSelectField
|
|
214
|
+
| WorkbenchStructuredDataFormTextArrayField
|
|
215
|
+
| WorkbenchStructuredDataFormTextField;
|
|
216
|
+
|
|
217
|
+
export interface WorkbenchStructuredDataTableColumn {
|
|
218
|
+
align?: 'end' | 'start';
|
|
219
|
+
id: string;
|
|
220
|
+
label: ReactNode;
|
|
221
|
+
path?: WorkbenchStructuredDataPath;
|
|
222
|
+
render?: (context: WorkbenchStructuredDataTableCellContext) => ReactNode;
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
export interface WorkbenchStructuredDataTableRow {
|
|
226
|
+
data: WorkbenchStructuredDataRecord;
|
|
227
|
+
id: string;
|
|
228
|
+
label?: ReactNode;
|
|
229
|
+
metadata?: Record<string, unknown>;
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
export interface WorkbenchStructuredDataTableCellContext {
|
|
233
|
+
column: WorkbenchStructuredDataTableColumn;
|
|
234
|
+
row: WorkbenchStructuredDataTableRow;
|
|
235
|
+
value: unknown;
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
export interface WorkbenchStructuredDataTable {
|
|
239
|
+
columns: readonly WorkbenchStructuredDataTableColumn[];
|
|
240
|
+
description?: ReactNode;
|
|
241
|
+
emptyLabel?: ReactNode;
|
|
242
|
+
id: string;
|
|
243
|
+
label?: ReactNode;
|
|
244
|
+
rows: readonly WorkbenchStructuredDataTableRow[];
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
export interface WorkbenchStructuredDataFormSection {
|
|
248
|
+
count?: number;
|
|
249
|
+
description?: ReactNode;
|
|
250
|
+
fields?: readonly WorkbenchStructuredDataFormField[];
|
|
251
|
+
id: string;
|
|
252
|
+
tables?: readonly WorkbenchStructuredDataTable[];
|
|
253
|
+
title: ReactNode;
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
export interface WorkbenchStructuredDataFormFieldChangeContext {
|
|
257
|
+
data: WorkbenchStructuredDataRecord;
|
|
258
|
+
field: WorkbenchStructuredDataFormField;
|
|
259
|
+
fieldId: string;
|
|
260
|
+
path: WorkbenchStructuredDataPath;
|
|
261
|
+
value: WorkbenchStructuredDataFieldValue;
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
export interface WorkbenchStructuredDataFormSubmitContext {
|
|
265
|
+
data: WorkbenchStructuredDataRecord;
|
|
266
|
+
event: FormEvent<HTMLFormElement>;
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
export interface WorkbenchStructuredDataFormCancelContext {
|
|
270
|
+
data: WorkbenchStructuredDataRecord;
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
export interface WorkbenchStructuredDataFormProps extends Omit<
|
|
274
|
+
ComponentPropsWithRef<'form'>,
|
|
275
|
+
'children' | 'defaultValue' | 'onCancel' | 'onChange' | 'onSubmit'
|
|
276
|
+
> {
|
|
277
|
+
ariaLabel: string;
|
|
278
|
+
cancelLabel?: ReactNode;
|
|
279
|
+
data?: WorkbenchStructuredDataRecord;
|
|
280
|
+
defaultData?: WorkbenchStructuredDataRecord;
|
|
281
|
+
disabled?: boolean;
|
|
282
|
+
emptyLabel?: ReactNode;
|
|
283
|
+
errors?: WorkbenchStructuredDataFormErrors;
|
|
284
|
+
onCancel?: (context: WorkbenchStructuredDataFormCancelContext) => void;
|
|
285
|
+
onDataChange?: (
|
|
286
|
+
data: WorkbenchStructuredDataRecord,
|
|
287
|
+
context: WorkbenchStructuredDataFormFieldChangeContext,
|
|
288
|
+
) => void;
|
|
289
|
+
onFieldChange?: (context: WorkbenchStructuredDataFormFieldChangeContext) => void;
|
|
290
|
+
onSubmit?: (
|
|
291
|
+
data: WorkbenchStructuredDataRecord,
|
|
292
|
+
context: WorkbenchStructuredDataFormSubmitContext,
|
|
293
|
+
) => void;
|
|
294
|
+
readOnly?: boolean;
|
|
295
|
+
sections: readonly WorkbenchStructuredDataFormSection[];
|
|
296
|
+
showActions?: boolean;
|
|
297
|
+
submitLabel?: ReactNode;
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
const EMPTY_RECORD: WorkbenchStructuredDataRecord = {};
|
|
301
|
+
|
|
302
|
+
export function getWorkbenchStructuredDataFormFieldDefaultValue(
|
|
303
|
+
field: WorkbenchStructuredDataFormField,
|
|
304
|
+
): WorkbenchStructuredDataFieldValue {
|
|
305
|
+
if (field.defaultValue !== undefined) {
|
|
306
|
+
return coerceWorkbenchStructuredDataFormFieldValue(field, field.defaultValue);
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
if (field.type === 'checkbox') return false;
|
|
310
|
+
if (field.type === 'text-array') return [];
|
|
311
|
+
return '';
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
export function coerceWorkbenchStructuredDataFormFieldValue(
|
|
315
|
+
field: WorkbenchStructuredDataFormField,
|
|
316
|
+
value: unknown,
|
|
317
|
+
): WorkbenchStructuredDataFieldValue {
|
|
318
|
+
if (field.type === 'checkbox') return Boolean(value);
|
|
319
|
+
if (field.type === 'text-array') {
|
|
320
|
+
if (Array.isArray(value)) {
|
|
321
|
+
return value.map((item) => (item === null || item === undefined ? '' : String(item)));
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
if (value === '' || value === null || value === undefined) return [];
|
|
325
|
+
return [String(value)];
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
if (field.type === 'number') {
|
|
329
|
+
if (value === '' || value === null || value === undefined) return '';
|
|
330
|
+
const numericValue = Number(value);
|
|
331
|
+
return Number.isFinite(numericValue) ? numericValue : '';
|
|
332
|
+
}
|
|
333
|
+
|
|
334
|
+
return value === null || value === undefined ? '' : String(value);
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
export function getWorkbenchStructuredDataSchemaFieldControl(
|
|
338
|
+
definition: WorkbenchStructuredDataSchemaFieldDefinition | undefined,
|
|
339
|
+
): WorkbenchStructuredDataSchemaFieldControl {
|
|
340
|
+
if (definition?.ui?.control) {
|
|
341
|
+
return definition.ui.control as WorkbenchStructuredDataSchemaFieldControl;
|
|
342
|
+
}
|
|
343
|
+
if (definition?.enum?.length) return 'select';
|
|
344
|
+
if (definition?.type === 'array') return 'textarea';
|
|
345
|
+
if (definition?.type === 'boolean') return 'checkbox';
|
|
346
|
+
if (definition?.type === 'number' || definition?.type === 'integer') return 'number';
|
|
347
|
+
if (definition?.format === 'date') return 'date';
|
|
348
|
+
return 'text';
|
|
349
|
+
}
|
|
350
|
+
|
|
351
|
+
export function getWorkbenchStructuredDataSchemaFieldDefaultValue(
|
|
352
|
+
definition: WorkbenchStructuredDataSchemaFieldDefinition | undefined,
|
|
353
|
+
) {
|
|
354
|
+
if (definition?.default !== undefined) return definition.default;
|
|
355
|
+
if (definition?.type === 'array') return [];
|
|
356
|
+
if (definition?.type === 'boolean') return false;
|
|
357
|
+
if (definition?.type === 'number' || definition?.type === 'integer') return 0;
|
|
358
|
+
return '';
|
|
359
|
+
}
|
|
360
|
+
|
|
361
|
+
export function stringifyWorkbenchStructuredDataSchemaFieldValue(
|
|
362
|
+
value: unknown,
|
|
363
|
+
definition: WorkbenchStructuredDataSchemaFieldDefinition | undefined,
|
|
364
|
+
) {
|
|
365
|
+
if (Array.isArray(value)) return value.join('\n');
|
|
366
|
+
if (value === null || value === undefined) return '';
|
|
367
|
+
if (definition?.type === 'object') return JSON.stringify(value, null, 2);
|
|
368
|
+
return String(value);
|
|
369
|
+
}
|
|
370
|
+
|
|
371
|
+
export function booleanWorkbenchStructuredDataSchemaFieldValue(value: unknown) {
|
|
372
|
+
return value === true || value === 'true' || value === 'Y';
|
|
373
|
+
}
|
|
374
|
+
|
|
375
|
+
export function coerceWorkbenchStructuredDataSchemaFieldValue(
|
|
376
|
+
rawValue: string,
|
|
377
|
+
definition: WorkbenchStructuredDataSchemaFieldDefinition | undefined,
|
|
378
|
+
): unknown {
|
|
379
|
+
if (definition?.type === 'array') {
|
|
380
|
+
return rawValue.split('\n');
|
|
381
|
+
}
|
|
382
|
+
|
|
383
|
+
if (definition?.type === 'number' || definition?.type === 'integer') {
|
|
384
|
+
if (rawValue.trim() === '') return null;
|
|
385
|
+
const numericValue = Number(rawValue);
|
|
386
|
+
return Number.isFinite(numericValue) ? numericValue : rawValue;
|
|
387
|
+
}
|
|
388
|
+
|
|
389
|
+
if (definition?.enum?.length) {
|
|
390
|
+
return definition.enum.find((option) => String(option) === rawValue) ?? rawValue;
|
|
391
|
+
}
|
|
392
|
+
|
|
393
|
+
return rawValue;
|
|
394
|
+
}
|
|
395
|
+
|
|
396
|
+
export function formatWorkbenchStructuredDataSchemaValue(value: unknown) {
|
|
397
|
+
if (value === null || value === undefined || value === '') return '-';
|
|
398
|
+
if (Array.isArray(value)) return value.join('\n');
|
|
399
|
+
if (typeof value === 'boolean') return value ? 'Y' : 'N';
|
|
400
|
+
if (typeof value === 'object') return JSON.stringify(value, null, 2);
|
|
401
|
+
return String(value);
|
|
402
|
+
}
|
|
403
|
+
|
|
404
|
+
export function getWorkbenchStructuredDataSchemaSectionId(
|
|
405
|
+
section: WorkbenchStructuredDataSchemaSectionSummary,
|
|
406
|
+
) {
|
|
407
|
+
return section.id ?? section.sectionKey;
|
|
408
|
+
}
|
|
409
|
+
|
|
410
|
+
export function getWorkbenchStructuredDataSchemaSectionPath(
|
|
411
|
+
section: WorkbenchStructuredDataSchemaSectionSummary,
|
|
412
|
+
) {
|
|
413
|
+
const dataPath = section.dataPath;
|
|
414
|
+
if (dataPath !== undefined) {
|
|
415
|
+
return dataPath.trim();
|
|
416
|
+
}
|
|
417
|
+
|
|
418
|
+
return section.sectionKey || section.id || '';
|
|
419
|
+
}
|
|
420
|
+
|
|
421
|
+
export function formatWorkbenchStructuredDataSchemaLabel(value: string) {
|
|
422
|
+
return value.replace(/_/g, ' ');
|
|
423
|
+
}
|
|
424
|
+
|
|
425
|
+
export function getWorkbenchStructuredDataSchemaFieldDataPath(
|
|
426
|
+
section: WorkbenchStructuredDataSchemaSectionSummary,
|
|
427
|
+
fieldPath: string,
|
|
428
|
+
) {
|
|
429
|
+
if (fieldPath.includes('.')) return fieldPath;
|
|
430
|
+
const sectionPath = getWorkbenchStructuredDataSchemaSectionPath(section);
|
|
431
|
+
return sectionPath ? `${sectionPath}.${fieldPath}` : fieldPath;
|
|
432
|
+
}
|
|
433
|
+
|
|
434
|
+
export function getWorkbenchStructuredDataSchemaFieldDefinition({
|
|
435
|
+
fieldPath,
|
|
436
|
+
properties,
|
|
437
|
+
section,
|
|
438
|
+
}: {
|
|
439
|
+
fieldPath: string;
|
|
440
|
+
properties?: Record<string, WorkbenchStructuredDataSchemaFieldDefinition> | undefined;
|
|
441
|
+
section: WorkbenchStructuredDataSchemaSectionSummary;
|
|
442
|
+
}) {
|
|
443
|
+
const sectionPath = getWorkbenchStructuredDataSchemaSectionPath(section);
|
|
444
|
+
return (
|
|
445
|
+
properties?.[fieldPath] ??
|
|
446
|
+
(sectionPath ? properties?.[`${sectionPath}.${fieldPath}`] : undefined)
|
|
447
|
+
);
|
|
448
|
+
}
|
|
449
|
+
|
|
450
|
+
export function getWorkbenchStructuredDataSchemaDocumentSections(
|
|
451
|
+
schema: WorkbenchStructuredDataSchemaDocument | null | undefined,
|
|
452
|
+
pattern: string,
|
|
453
|
+
) {
|
|
454
|
+
const activePatternSchema = schema?.patterns?.find((candidate) => candidate.pattern === pattern);
|
|
455
|
+
return (
|
|
456
|
+
schema?.ui?.patterns?.[pattern]?.sections ??
|
|
457
|
+
schema?.schema?.sections ??
|
|
458
|
+
activePatternSchema?.sections ??
|
|
459
|
+
[]
|
|
460
|
+
);
|
|
461
|
+
}
|
|
462
|
+
|
|
463
|
+
export function getWorkbenchStructuredDataSchemaDocumentTableDefinition(
|
|
464
|
+
schema: WorkbenchStructuredDataSchemaDocument | null | undefined,
|
|
465
|
+
section: WorkbenchStructuredDataSchemaSectionSummary,
|
|
466
|
+
) {
|
|
467
|
+
const tablePath = getWorkbenchStructuredDataSchemaSectionPath(section);
|
|
468
|
+
return tablePath ? schema?.schema?.tables?.[tablePath] : undefined;
|
|
469
|
+
}
|
|
470
|
+
|
|
471
|
+
export function getWorkbenchStructuredDataSchemaDocumentFieldDefinition(
|
|
472
|
+
schema: WorkbenchStructuredDataSchemaDocument | null | undefined,
|
|
473
|
+
section: WorkbenchStructuredDataSchemaSectionSummary,
|
|
474
|
+
fieldPath: string,
|
|
475
|
+
) {
|
|
476
|
+
return getWorkbenchStructuredDataSchemaFieldDefinition({
|
|
477
|
+
fieldPath,
|
|
478
|
+
properties: schema?.schema?.properties,
|
|
479
|
+
section,
|
|
480
|
+
});
|
|
481
|
+
}
|
|
482
|
+
|
|
483
|
+
export function getWorkbenchStructuredDataSchemaFieldDescription(
|
|
484
|
+
definition: WorkbenchStructuredDataSchemaFieldDefinition | undefined,
|
|
485
|
+
) {
|
|
486
|
+
return definition?.description ?? definition?.markdownDescription;
|
|
487
|
+
}
|
|
488
|
+
|
|
489
|
+
export function getWorkbenchStructuredDataSchemaDocumentFieldLabel(
|
|
490
|
+
schema: WorkbenchStructuredDataSchemaDocument | null | undefined,
|
|
491
|
+
section: WorkbenchStructuredDataSchemaSectionSummary,
|
|
492
|
+
fieldPath: string,
|
|
493
|
+
) {
|
|
494
|
+
return (
|
|
495
|
+
getWorkbenchStructuredDataSchemaDocumentFieldDefinition(schema, section, fieldPath)?.title ??
|
|
496
|
+
formatWorkbenchStructuredDataSchemaLabel(fieldPath.split('.').pop() ?? fieldPath)
|
|
497
|
+
);
|
|
498
|
+
}
|
|
499
|
+
|
|
500
|
+
export function getWorkbenchStructuredDataSchemaDocumentColumnDefinition(
|
|
501
|
+
schema: WorkbenchStructuredDataSchemaDocument | null | undefined,
|
|
502
|
+
section: WorkbenchStructuredDataSchemaSectionSummary,
|
|
503
|
+
column: string,
|
|
504
|
+
) {
|
|
505
|
+
return (
|
|
506
|
+
getWorkbenchStructuredDataSchemaDocumentTableDefinition(schema, section)?.items?.[column] ??
|
|
507
|
+
getWorkbenchStructuredDataSchemaDocumentFieldDefinition(schema, section, column)
|
|
508
|
+
);
|
|
509
|
+
}
|
|
510
|
+
|
|
511
|
+
export function getWorkbenchStructuredDataSchemaDocumentColumnLabel(
|
|
512
|
+
schema: WorkbenchStructuredDataSchemaDocument | null | undefined,
|
|
513
|
+
section: WorkbenchStructuredDataSchemaSectionSummary,
|
|
514
|
+
column: string,
|
|
515
|
+
) {
|
|
516
|
+
return (
|
|
517
|
+
getWorkbenchStructuredDataSchemaDocumentColumnDefinition(schema, section, column)?.title ??
|
|
518
|
+
formatWorkbenchStructuredDataSchemaLabel(column)
|
|
519
|
+
);
|
|
520
|
+
}
|
|
521
|
+
|
|
522
|
+
export function getWorkbenchStructuredDataSchemaDocumentSectionValue({
|
|
523
|
+
aliases = {},
|
|
524
|
+
data,
|
|
525
|
+
section,
|
|
526
|
+
}: {
|
|
527
|
+
aliases?: WorkbenchStructuredDataSchemaSectionAliases | undefined;
|
|
528
|
+
data: unknown;
|
|
529
|
+
section: WorkbenchStructuredDataSchemaSectionSummary;
|
|
530
|
+
}) {
|
|
531
|
+
const sectionKey = getWorkbenchStructuredDataSchemaSectionPath(section);
|
|
532
|
+
const record = asWorkbenchStructuredDataRecord(data);
|
|
533
|
+
if (!sectionKey || !record) return sectionKey ? null : data;
|
|
534
|
+
if (sectionKey in record) return record[sectionKey];
|
|
535
|
+
|
|
536
|
+
const directValue = getWorkbenchStructuredDataValue(data, sectionKey.split('.'));
|
|
537
|
+
if (directValue !== null && directValue !== undefined) return directValue;
|
|
538
|
+
|
|
539
|
+
for (const path of aliases[sectionKey] ?? []) {
|
|
540
|
+
if (!path.length) return data;
|
|
541
|
+
const value = getWorkbenchStructuredDataValue(data, path);
|
|
542
|
+
if (value !== null && value !== undefined) return value;
|
|
543
|
+
}
|
|
544
|
+
|
|
545
|
+
return null;
|
|
546
|
+
}
|
|
547
|
+
|
|
548
|
+
export function getWorkbenchStructuredDataSchemaTableRows(
|
|
549
|
+
value: unknown,
|
|
550
|
+
): WorkbenchStructuredDataRecord[] {
|
|
551
|
+
if (Array.isArray(value)) {
|
|
552
|
+
return value.map((item) => asWorkbenchStructuredDataRecord(item) ?? { value: item });
|
|
553
|
+
}
|
|
554
|
+
|
|
555
|
+
const record = asWorkbenchStructuredDataRecord(value);
|
|
556
|
+
if (!record) return [];
|
|
557
|
+
|
|
558
|
+
const objectEntries = Object.entries(record).filter(([, entry]) =>
|
|
559
|
+
asWorkbenchStructuredDataRecord(entry),
|
|
560
|
+
);
|
|
561
|
+
if (!objectEntries.length) return [];
|
|
562
|
+
|
|
563
|
+
return objectEntries.map(([key, entry]) => ({
|
|
564
|
+
id: key,
|
|
565
|
+
...(asWorkbenchStructuredDataRecord(entry) ?? {}),
|
|
566
|
+
}));
|
|
567
|
+
}
|
|
568
|
+
|
|
569
|
+
export function getWorkbenchStructuredDataSchemaTablePath(
|
|
570
|
+
section: WorkbenchStructuredDataSchemaSectionSummary,
|
|
571
|
+
) {
|
|
572
|
+
const tablePath = getWorkbenchStructuredDataSchemaSectionPath(section);
|
|
573
|
+
return tablePath ? tablePath.split('.') : [];
|
|
574
|
+
}
|
|
575
|
+
|
|
576
|
+
export function getWorkbenchStructuredDataSchemaTableRowKey({
|
|
577
|
+
row,
|
|
578
|
+
rowIndex,
|
|
579
|
+
value,
|
|
580
|
+
}: WorkbenchStructuredDataSchemaTableRowKeyInput) {
|
|
581
|
+
return Array.isArray(value) ? String(rowIndex) : String(row.id ?? rowIndex);
|
|
582
|
+
}
|
|
583
|
+
|
|
584
|
+
export function getWorkbenchStructuredDataSchemaTableCellPath({
|
|
585
|
+
column,
|
|
586
|
+
rowKey,
|
|
587
|
+
section,
|
|
588
|
+
}: {
|
|
589
|
+
column: string;
|
|
590
|
+
rowKey: string;
|
|
591
|
+
section: WorkbenchStructuredDataSchemaSectionSummary;
|
|
592
|
+
}) {
|
|
593
|
+
return [...getWorkbenchStructuredDataSchemaTablePath(section), rowKey, column];
|
|
594
|
+
}
|
|
595
|
+
|
|
596
|
+
export function removeWorkbenchStructuredDataSchemaTableRow({
|
|
597
|
+
rowIndex,
|
|
598
|
+
rowKey,
|
|
599
|
+
value,
|
|
600
|
+
}: {
|
|
601
|
+
rowIndex: number;
|
|
602
|
+
rowKey: string;
|
|
603
|
+
value: unknown;
|
|
604
|
+
}) {
|
|
605
|
+
if (Array.isArray(value)) return value.filter((_, index) => index !== rowIndex);
|
|
606
|
+
|
|
607
|
+
const nextRecord = { ...(asWorkbenchStructuredDataRecord(value) ?? {}) };
|
|
608
|
+
delete nextRecord[rowKey];
|
|
609
|
+
return nextRecord;
|
|
610
|
+
}
|
|
611
|
+
|
|
612
|
+
export function appendWorkbenchStructuredDataSchemaTableRow({
|
|
613
|
+
row,
|
|
614
|
+
rowKey,
|
|
615
|
+
value,
|
|
616
|
+
}: {
|
|
617
|
+
row: WorkbenchStructuredDataRecord;
|
|
618
|
+
rowKey: string;
|
|
619
|
+
value: unknown;
|
|
620
|
+
}) {
|
|
621
|
+
if (Array.isArray(value)) return [...value, row];
|
|
622
|
+
|
|
623
|
+
return {
|
|
624
|
+
...(asWorkbenchStructuredDataRecord(value) ?? {}),
|
|
625
|
+
[rowKey]: { ...row, id: rowKey },
|
|
626
|
+
};
|
|
627
|
+
}
|
|
628
|
+
|
|
629
|
+
export function getWorkbenchStructuredDataSchemaTableColumns({
|
|
630
|
+
maxColumns = 6,
|
|
631
|
+
preferredColumns = [],
|
|
632
|
+
rows,
|
|
633
|
+
schemaColumns = [],
|
|
634
|
+
sectionColumns = [],
|
|
635
|
+
}: WorkbenchStructuredDataSchemaTableColumnInput) {
|
|
636
|
+
if (sectionColumns.length) return [...sectionColumns];
|
|
637
|
+
if (schemaColumns.length) return [...schemaColumns];
|
|
638
|
+
|
|
639
|
+
const keys = Array.from(new Set(rows.flatMap((row) => Object.keys(row))));
|
|
640
|
+
const preferred = preferredColumns.filter((column) => keys.includes(column));
|
|
641
|
+
const remaining = keys.filter((column) => !preferred.includes(column));
|
|
642
|
+
return [...preferred, ...remaining].slice(0, maxColumns);
|
|
643
|
+
}
|
|
644
|
+
|
|
645
|
+
export function getWorkbenchStructuredDataSchemaDocumentTableColumns({
|
|
646
|
+
maxColumns,
|
|
647
|
+
preferredColumns,
|
|
648
|
+
rows,
|
|
649
|
+
schema,
|
|
650
|
+
section,
|
|
651
|
+
}: {
|
|
652
|
+
maxColumns?: number | undefined;
|
|
653
|
+
preferredColumns?: readonly string[] | undefined;
|
|
654
|
+
rows: readonly WorkbenchStructuredDataRecord[];
|
|
655
|
+
schema: WorkbenchStructuredDataSchemaDocument | null | undefined;
|
|
656
|
+
section: WorkbenchStructuredDataSchemaSectionSummary;
|
|
657
|
+
}) {
|
|
658
|
+
const schemaColumns = Object.keys(
|
|
659
|
+
getWorkbenchStructuredDataSchemaDocumentTableDefinition(schema, section)?.items ?? {},
|
|
660
|
+
);
|
|
661
|
+
|
|
662
|
+
return getWorkbenchStructuredDataSchemaTableColumns({
|
|
663
|
+
maxColumns,
|
|
664
|
+
preferredColumns,
|
|
665
|
+
rows,
|
|
666
|
+
schemaColumns,
|
|
667
|
+
sectionColumns: section.columns,
|
|
668
|
+
});
|
|
669
|
+
}
|
|
670
|
+
|
|
671
|
+
export function createWorkbenchStructuredDataSchemaEmptyRow({
|
|
672
|
+
columns,
|
|
673
|
+
getDefinition,
|
|
674
|
+
}: {
|
|
675
|
+
columns: readonly string[];
|
|
676
|
+
getDefinition: (column: string) => WorkbenchStructuredDataSchemaFieldDefinition | undefined;
|
|
677
|
+
}) {
|
|
678
|
+
return columns.reduce<WorkbenchStructuredDataRecord>((row, column) => {
|
|
679
|
+
row[column] = getWorkbenchStructuredDataSchemaFieldDefaultValue(getDefinition(column));
|
|
680
|
+
return row;
|
|
681
|
+
}, {});
|
|
682
|
+
}
|
|
683
|
+
|
|
684
|
+
export function createWorkbenchStructuredDataSchemaDocumentEmptyRow({
|
|
685
|
+
columns,
|
|
686
|
+
schema,
|
|
687
|
+
section,
|
|
688
|
+
}: {
|
|
689
|
+
columns: readonly string[];
|
|
690
|
+
schema: WorkbenchStructuredDataSchemaDocument | null | undefined;
|
|
691
|
+
section: WorkbenchStructuredDataSchemaSectionSummary;
|
|
692
|
+
}) {
|
|
693
|
+
return createWorkbenchStructuredDataSchemaEmptyRow({
|
|
694
|
+
columns,
|
|
695
|
+
getDefinition: (column) =>
|
|
696
|
+
getWorkbenchStructuredDataSchemaDocumentColumnDefinition(schema, section, column),
|
|
697
|
+
});
|
|
698
|
+
}
|
|
699
|
+
|
|
700
|
+
export function createWorkbenchStructuredDataSchemaDocumentSampleData(
|
|
701
|
+
schema: WorkbenchStructuredDataSchemaDocument | null | undefined,
|
|
702
|
+
pattern: string,
|
|
703
|
+
) {
|
|
704
|
+
const sections = getWorkbenchStructuredDataSchemaDocumentSections(schema, pattern);
|
|
705
|
+
return sections.reduce<WorkbenchStructuredDataRecord>((sample, section) => {
|
|
706
|
+
const path = getWorkbenchStructuredDataSchemaSectionPath(section);
|
|
707
|
+
if (!path) return sample;
|
|
708
|
+
|
|
709
|
+
if (section.type === 'table') {
|
|
710
|
+
const schemaTable = getWorkbenchStructuredDataSchemaDocumentTableDefinition(schema, section);
|
|
711
|
+
const columns = section.columns?.length
|
|
712
|
+
? section.columns
|
|
713
|
+
: Object.keys(schemaTable?.items ?? {});
|
|
714
|
+
|
|
715
|
+
return setWorkbenchStructuredDataValue(sample, path.split('.'), [
|
|
716
|
+
createWorkbenchStructuredDataSchemaDocumentEmptyRow({
|
|
717
|
+
columns,
|
|
718
|
+
schema,
|
|
719
|
+
section,
|
|
720
|
+
}),
|
|
721
|
+
]);
|
|
722
|
+
}
|
|
723
|
+
|
|
724
|
+
return (section.fields ?? []).reduce<WorkbenchStructuredDataRecord>((nextSample, fieldPath) => {
|
|
725
|
+
const definition = getWorkbenchStructuredDataSchemaDocumentFieldDefinition(
|
|
726
|
+
schema,
|
|
727
|
+
section,
|
|
728
|
+
fieldPath,
|
|
729
|
+
);
|
|
730
|
+
return setWorkbenchStructuredDataValue(
|
|
731
|
+
nextSample,
|
|
732
|
+
getWorkbenchStructuredDataSchemaFieldDataPath(section, fieldPath).split('.'),
|
|
733
|
+
getWorkbenchStructuredDataSchemaFieldDefaultValue(definition),
|
|
734
|
+
);
|
|
735
|
+
}, sample);
|
|
736
|
+
}, {});
|
|
737
|
+
}
|
|
738
|
+
|
|
739
|
+
export function createWorkbenchStructuredDataSchemaFallbackSection({
|
|
740
|
+
data,
|
|
741
|
+
sectionKey = 'data',
|
|
742
|
+
title,
|
|
743
|
+
}: {
|
|
744
|
+
data: unknown;
|
|
745
|
+
sectionKey?: string | undefined;
|
|
746
|
+
title: string;
|
|
747
|
+
}): WorkbenchStructuredDataSchemaSectionSummary {
|
|
748
|
+
const record = asWorkbenchStructuredDataRecord(data);
|
|
749
|
+
return {
|
|
750
|
+
fieldCount: record ? Object.keys(record).length : undefined,
|
|
751
|
+
sectionKey,
|
|
752
|
+
title,
|
|
753
|
+
type: Array.isArray(data) ? 'table' : 'form',
|
|
754
|
+
};
|
|
755
|
+
}
|
|
756
|
+
|
|
757
|
+
export function slugWorkbenchStructuredDataSchemaAnchor(value: string | undefined) {
|
|
758
|
+
return (
|
|
759
|
+
value
|
|
760
|
+
?.toLowerCase()
|
|
761
|
+
.replace(/[^a-z0-9_-]+/g, '-')
|
|
762
|
+
.replace(/^-+|-+$/g, '') || 'section'
|
|
763
|
+
);
|
|
764
|
+
}
|
|
765
|
+
|
|
766
|
+
export function getWorkbenchStructuredDataSchemaSectionAnchorId({
|
|
767
|
+
index,
|
|
768
|
+
panelId,
|
|
769
|
+
section,
|
|
770
|
+
}: {
|
|
771
|
+
index: number;
|
|
772
|
+
panelId: string;
|
|
773
|
+
section: WorkbenchStructuredDataSchemaSectionSummary;
|
|
774
|
+
}) {
|
|
775
|
+
return `${panelId}-section-${index}-${slugWorkbenchStructuredDataSchemaAnchor(
|
|
776
|
+
getWorkbenchStructuredDataSchemaSectionId(section) ?? section.title,
|
|
777
|
+
)}`;
|
|
778
|
+
}
|
|
779
|
+
|
|
780
|
+
export function getWorkbenchStructuredDataSchemaDocumentPanelData({
|
|
781
|
+
data,
|
|
782
|
+
pattern,
|
|
783
|
+
schema,
|
|
784
|
+
}: {
|
|
785
|
+
data: unknown;
|
|
786
|
+
pattern: string;
|
|
787
|
+
schema: WorkbenchStructuredDataSchemaDocument | null | undefined;
|
|
788
|
+
}) {
|
|
789
|
+
return (
|
|
790
|
+
data ??
|
|
791
|
+
schema?.sampleDrafts?.[pattern] ??
|
|
792
|
+
schema?.sampleDraft ??
|
|
793
|
+
createWorkbenchStructuredDataSchemaDocumentSampleData(schema, pattern)
|
|
794
|
+
);
|
|
795
|
+
}
|
|
796
|
+
|
|
797
|
+
export function getWorkbenchStructuredDataFormFields(
|
|
798
|
+
sections: readonly WorkbenchStructuredDataFormSection[],
|
|
799
|
+
) {
|
|
800
|
+
return sections.flatMap((section) => section.fields ?? []);
|
|
801
|
+
}
|
|
802
|
+
|
|
803
|
+
export function normalizeWorkbenchStructuredDataFormData(
|
|
804
|
+
sections: readonly WorkbenchStructuredDataFormSection[],
|
|
805
|
+
data: WorkbenchStructuredDataRecord = EMPTY_RECORD,
|
|
806
|
+
): WorkbenchStructuredDataRecord {
|
|
807
|
+
return getWorkbenchStructuredDataFormFields(sections).reduce<WorkbenchStructuredDataRecord>(
|
|
808
|
+
(nextData, field) => {
|
|
809
|
+
const value = getWorkbenchStructuredDataValue(nextData, field.path);
|
|
810
|
+
return setWorkbenchStructuredDataValue(
|
|
811
|
+
nextData,
|
|
812
|
+
field.path,
|
|
813
|
+
value === undefined
|
|
814
|
+
? getWorkbenchStructuredDataFormFieldDefaultValue(field)
|
|
815
|
+
: coerceWorkbenchStructuredDataFormFieldValue(field, value),
|
|
816
|
+
);
|
|
817
|
+
},
|
|
818
|
+
{ ...data },
|
|
819
|
+
);
|
|
820
|
+
}
|
|
821
|
+
|
|
822
|
+
export function getWorkbenchStructuredDataFormFieldError({
|
|
823
|
+
data,
|
|
824
|
+
field,
|
|
825
|
+
value,
|
|
826
|
+
}: {
|
|
827
|
+
data: WorkbenchStructuredDataRecord;
|
|
828
|
+
field: WorkbenchStructuredDataFormField;
|
|
829
|
+
value: WorkbenchStructuredDataFieldValue;
|
|
830
|
+
}) {
|
|
831
|
+
if (field.validationMessage) return field.validationMessage;
|
|
832
|
+
if (field.required && isWorkbenchStructuredDataFormEmptyValue(value)) {
|
|
833
|
+
return 'This field is required.';
|
|
834
|
+
}
|
|
835
|
+
|
|
836
|
+
return field.validate?.(value, data, field);
|
|
837
|
+
}
|
|
838
|
+
|
|
839
|
+
export function getWorkbenchStructuredDataFormErrors(
|
|
840
|
+
sections: readonly WorkbenchStructuredDataFormSection[],
|
|
841
|
+
data: WorkbenchStructuredDataRecord = EMPTY_RECORD,
|
|
842
|
+
): WorkbenchStructuredDataFormErrors {
|
|
843
|
+
const normalizedData = normalizeWorkbenchStructuredDataFormData(sections, data);
|
|
844
|
+
|
|
845
|
+
return getWorkbenchStructuredDataFormFields(sections).reduce<WorkbenchStructuredDataFormErrors>(
|
|
846
|
+
(errors, field) => {
|
|
847
|
+
const value = coerceWorkbenchStructuredDataFormFieldValue(
|
|
848
|
+
field,
|
|
849
|
+
getWorkbenchStructuredDataValue(normalizedData, field.path),
|
|
850
|
+
);
|
|
851
|
+
const error = getWorkbenchStructuredDataFormFieldError({
|
|
852
|
+
data: normalizedData,
|
|
853
|
+
field,
|
|
854
|
+
value,
|
|
855
|
+
});
|
|
856
|
+
|
|
857
|
+
if (isRenderableWorkbenchStructuredDataFormError(error)) {
|
|
858
|
+
errors[field.id] = error;
|
|
859
|
+
}
|
|
860
|
+
|
|
861
|
+
return errors;
|
|
862
|
+
},
|
|
863
|
+
{},
|
|
864
|
+
);
|
|
865
|
+
}
|
|
866
|
+
|
|
867
|
+
export function isWorkbenchStructuredDataFormSubmittable({
|
|
868
|
+
disabled = false,
|
|
869
|
+
errors = {},
|
|
870
|
+
readOnly = false,
|
|
871
|
+
}: {
|
|
872
|
+
disabled?: boolean;
|
|
873
|
+
errors?: WorkbenchStructuredDataFormErrors;
|
|
874
|
+
readOnly?: boolean;
|
|
875
|
+
}) {
|
|
876
|
+
return !disabled && !readOnly && Object.keys(errors).length === 0;
|
|
877
|
+
}
|
|
878
|
+
|
|
879
|
+
function isWorkbenchStructuredDataFormEmptyValue(value: WorkbenchStructuredDataFieldValue) {
|
|
880
|
+
if (Array.isArray(value)) return value.length === 0;
|
|
881
|
+
return value === '' || value === false;
|
|
882
|
+
}
|
|
883
|
+
|
|
884
|
+
function isRenderableWorkbenchStructuredDataFormError(error: ReactNode) {
|
|
885
|
+
return error !== undefined && error !== null && error !== false && error !== '';
|
|
886
|
+
}
|