@tai42/studio-sdk 0.2.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.
- package/LICENSE +202 -0
- package/NOTICE +15 -0
- package/README.md +318 -0
- package/SECURITY.md +51 -0
- package/dist/components/badge.d.ts +13 -0
- package/dist/components/badge.d.ts.map +1 -0
- package/dist/components/badge.js +14 -0
- package/dist/components/badge.js.map +1 -0
- package/dist/components/checkbox.d.ts +24 -0
- package/dist/components/checkbox.d.ts.map +1 -0
- package/dist/components/checkbox.js +31 -0
- package/dist/components/checkbox.js.map +1 -0
- package/dist/components/code-block.d.ts +7 -0
- package/dist/components/code-block.d.ts.map +1 -0
- package/dist/components/code-block.js +23 -0
- package/dist/components/code-block.js.map +1 -0
- package/dist/components/completion-input.d.ts +31 -0
- package/dist/components/completion-input.d.ts.map +1 -0
- package/dist/components/completion-input.js +61 -0
- package/dist/components/completion-input.js.map +1 -0
- package/dist/components/components.css +2212 -0
- package/dist/components/confirm-dialog.d.ts +40 -0
- package/dist/components/confirm-dialog.d.ts.map +1 -0
- package/dist/components/confirm-dialog.js +11 -0
- package/dist/components/confirm-dialog.js.map +1 -0
- package/dist/components/control-styles.d.ts +12 -0
- package/dist/components/control-styles.d.ts.map +1 -0
- package/dist/components/control-styles.js +14 -0
- package/dist/components/control-styles.js.map +1 -0
- package/dist/components/copy-field.d.ts +8 -0
- package/dist/components/copy-field.d.ts.map +1 -0
- package/dist/components/copy-field.js +106 -0
- package/dist/components/copy-field.js.map +1 -0
- package/dist/components/dialog.d.ts +21 -0
- package/dist/components/dialog.d.ts.map +1 -0
- package/dist/components/dialog.js +25 -0
- package/dist/components/dialog.js.map +1 -0
- package/dist/components/drawer.d.ts +22 -0
- package/dist/components/drawer.d.ts.map +1 -0
- package/dist/components/drawer.js +32 -0
- package/dist/components/drawer.js.map +1 -0
- package/dist/components/error-boundary.d.ts +33 -0
- package/dist/components/error-boundary.d.ts.map +1 -0
- package/dist/components/error-boundary.js +36 -0
- package/dist/components/error-boundary.js.map +1 -0
- package/dist/components/extension-combo-builder.d.ts +70 -0
- package/dist/components/extension-combo-builder.d.ts.map +1 -0
- package/dist/components/extension-combo-builder.js +154 -0
- package/dist/components/extension-combo-builder.js.map +1 -0
- package/dist/components/extension-grouping.d.ts +65 -0
- package/dist/components/extension-grouping.d.ts.map +1 -0
- package/dist/components/extension-grouping.js +78 -0
- package/dist/components/extension-grouping.js.map +1 -0
- package/dist/components/extension-picker.d.ts +35 -0
- package/dist/components/extension-picker.d.ts.map +1 -0
- package/dist/components/extension-picker.js +31 -0
- package/dist/components/extension-picker.js.map +1 -0
- package/dist/components/external-link.d.ts +19 -0
- package/dist/components/external-link.d.ts.map +1 -0
- package/dist/components/external-link.js +12 -0
- package/dist/components/external-link.js.map +1 -0
- package/dist/components/field.d.ts +64 -0
- package/dist/components/field.d.ts.map +1 -0
- package/dist/components/field.js +56 -0
- package/dist/components/field.js.map +1 -0
- package/dist/components/fleet-report.d.ts +39 -0
- package/dist/components/fleet-report.d.ts.map +1 -0
- package/dist/components/fleet-report.js +50 -0
- package/dist/components/fleet-report.js.map +1 -0
- package/dist/components/fonts.css +22 -0
- package/dist/components/icons.d.ts +142 -0
- package/dist/components/icons.d.ts.map +1 -0
- package/dist/components/icons.js +139 -0
- package/dist/components/icons.js.map +1 -0
- package/dist/components/inputs.d.ts +52 -0
- package/dist/components/inputs.d.ts.map +1 -0
- package/dist/components/inputs.js +35 -0
- package/dist/components/inputs.js.map +1 -0
- package/dist/components/json-diff.d.ts +40 -0
- package/dist/components/json-diff.d.ts.map +1 -0
- package/dist/components/json-diff.js +119 -0
- package/dist/components/json-diff.js.map +1 -0
- package/dist/components/json-tree.d.ts +8 -0
- package/dist/components/json-tree.d.ts.map +1 -0
- package/dist/components/json-tree.js +70 -0
- package/dist/components/json-tree.js.map +1 -0
- package/dist/components/modal-focus.d.ts +15 -0
- package/dist/components/modal-focus.d.ts.map +1 -0
- package/dist/components/modal-focus.js +136 -0
- package/dist/components/modal-focus.js.map +1 -0
- package/dist/components/page-header.d.ts +56 -0
- package/dist/components/page-header.d.ts.map +1 -0
- package/dist/components/page-header.js +24 -0
- package/dist/components/page-header.js.map +1 -0
- package/dist/components/primitives.d.ts +186 -0
- package/dist/components/primitives.d.ts.map +1 -0
- package/dist/components/primitives.js +204 -0
- package/dist/components/primitives.js.map +1 -0
- package/dist/components/progress-bar.d.ts +29 -0
- package/dist/components/progress-bar.d.ts.map +1 -0
- package/dist/components/progress-bar.js +48 -0
- package/dist/components/progress-bar.js.map +1 -0
- package/dist/components/radio-group.d.ts +37 -0
- package/dist/components/radio-group.d.ts.map +1 -0
- package/dist/components/radio-group.js +56 -0
- package/dist/components/radio-group.js.map +1 -0
- package/dist/components/reveal-input.d.ts +13 -0
- package/dist/components/reveal-input.d.ts.map +1 -0
- package/dist/components/reveal-input.js +31 -0
- package/dist/components/reveal-input.js.map +1 -0
- package/dist/components/scroll-region.d.ts +85 -0
- package/dist/components/scroll-region.d.ts.map +1 -0
- package/dist/components/scroll-region.js +574 -0
- package/dist/components/scroll-region.js.map +1 -0
- package/dist/components/select.d.ts +53 -0
- package/dist/components/select.d.ts.map +1 -0
- package/dist/components/select.js +33 -0
- package/dist/components/select.js.map +1 -0
- package/dist/components/table.d.ts +59 -0
- package/dist/components/table.d.ts.map +1 -0
- package/dist/components/table.js +20 -0
- package/dist/components/table.js.map +1 -0
- package/dist/components/tabs.d.ts +15 -0
- package/dist/components/tabs.d.ts.map +1 -0
- package/dist/components/tabs.js +13 -0
- package/dist/components/tabs.js.map +1 -0
- package/dist/components/tags.d.ts +46 -0
- package/dist/components/tags.d.ts.map +1 -0
- package/dist/components/tags.js +68 -0
- package/dist/components/tags.js.map +1 -0
- package/dist/components/tokens.css +392 -0
- package/dist/components/tokens.d.ts +15 -0
- package/dist/components/tokens.d.ts.map +1 -0
- package/dist/components/tokens.js +101 -0
- package/dist/components/tokens.js.map +1 -0
- package/dist/components/tool-picker.d.ts +24 -0
- package/dist/components/tool-picker.d.ts.map +1 -0
- package/dist/components/tool-picker.js +97 -0
- package/dist/components/tool-picker.js.map +1 -0
- package/dist/components/tooltip.d.ts +17 -0
- package/dist/components/tooltip.d.ts.map +1 -0
- package/dist/components/tooltip.js +18 -0
- package/dist/components/tooltip.js.map +1 -0
- package/dist/components/version-history-panel.d.ts +71 -0
- package/dist/components/version-history-panel.d.ts.map +1 -0
- package/dist/components/version-history-panel.js +148 -0
- package/dist/components/version-history-panel.js.map +1 -0
- package/dist/download.d.ts +7 -0
- package/dist/download.d.ts.map +1 -0
- package/dist/download.js +18 -0
- package/dist/download.js.map +1 -0
- package/dist/element-slot.d.ts +4 -0
- package/dist/element-slot.d.ts.map +1 -0
- package/dist/element-slot.js +20 -0
- package/dist/element-slot.js.map +1 -0
- package/dist/elicitation/ElicitationForm.d.ts +34 -0
- package/dist/elicitation/ElicitationForm.d.ts.map +1 -0
- package/dist/elicitation/ElicitationForm.js +24 -0
- package/dist/elicitation/ElicitationForm.js.map +1 -0
- package/dist/errors.d.ts +9 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/errors.js +15 -0
- package/dist/errors.js.map +1 -0
- package/dist/extension-combos.d.ts +13 -0
- package/dist/extension-combos.d.ts.map +1 -0
- package/dist/extension-combos.js +9 -0
- package/dist/extension-combos.js.map +1 -0
- package/dist/hooks/useApi.d.ts +1222 -0
- package/dist/hooks/useApi.d.ts.map +1 -0
- package/dist/hooks/useApi.js +22 -0
- package/dist/hooks/useApi.js.map +1 -0
- package/dist/hooks/useAuth.d.ts +13 -0
- package/dist/hooks/useAuth.d.ts.map +1 -0
- package/dist/hooks/useAuth.js +53 -0
- package/dist/hooks/useAuth.js.map +1 -0
- package/dist/hooks/useBreakpoint.d.ts +10 -0
- package/dist/hooks/useBreakpoint.d.ts.map +1 -0
- package/dist/hooks/useBreakpoint.js +66 -0
- package/dist/hooks/useBreakpoint.js.map +1 -0
- package/dist/hooks/useCapabilities.d.ts +88 -0
- package/dist/hooks/useCapabilities.d.ts.map +1 -0
- package/dist/hooks/useCapabilities.js +203 -0
- package/dist/hooks/useCapabilities.js.map +1 -0
- package/dist/hooks/useSse.d.ts +13 -0
- package/dist/hooks/useSse.d.ts.map +1 -0
- package/dist/hooks/useSse.js +298 -0
- package/dist/hooks/useSse.js.map +1 -0
- package/dist/hooks/useTheme.d.ts +20 -0
- package/dist/hooks/useTheme.d.ts.map +1 -0
- package/dist/hooks/useTheme.js +97 -0
- package/dist/hooks/useTheme.js.map +1 -0
- package/dist/hooks/useUnauthorized.d.ts +3 -0
- package/dist/hooks/useUnauthorized.d.ts.map +1 -0
- package/dist/hooks/useUnauthorized.js +18 -0
- package/dist/hooks/useUnauthorized.js.map +1 -0
- package/dist/host.d.ts +11 -0
- package/dist/host.d.ts.map +1 -0
- package/dist/host.js +10 -0
- package/dist/host.js.map +1 -0
- package/dist/index.d.ts +118 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +91 -0
- package/dist/index.js.map +1 -0
- package/dist/navigation/context.d.ts +25 -0
- package/dist/navigation/context.d.ts.map +1 -0
- package/dist/navigation/context.js +45 -0
- package/dist/navigation/context.js.map +1 -0
- package/dist/navigation/index.d.ts +4 -0
- package/dist/navigation/index.d.ts.map +1 -0
- package/dist/navigation/index.js +2 -0
- package/dist/navigation/index.js.map +1 -0
- package/dist/navigation/types.d.ts +97 -0
- package/dist/navigation/types.d.ts.map +1 -0
- package/dist/navigation/types.js +16 -0
- package/dist/navigation/types.js.map +1 -0
- package/dist/plugin/host-state.d.ts +45 -0
- package/dist/plugin/host-state.d.ts.map +1 -0
- package/dist/plugin/host-state.js +62 -0
- package/dist/plugin/host-state.js.map +1 -0
- package/dist/plugin/registry.d.ts +35 -0
- package/dist/plugin/registry.d.ts.map +1 -0
- package/dist/plugin/registry.js +129 -0
- package/dist/plugin/registry.js.map +1 -0
- package/dist/plugin/types.d.ts +165 -0
- package/dist/plugin/types.d.ts.map +1 -0
- package/dist/plugin/types.js +2 -0
- package/dist/plugin/types.js.map +1 -0
- package/dist/plugin/version.d.ts +34 -0
- package/dist/plugin/version.d.ts.map +1 -0
- package/dist/plugin/version.js +37 -0
- package/dist/plugin/version.js.map +1 -0
- package/dist/query-keys.d.ts +31 -0
- package/dist/query-keys.d.ts.map +1 -0
- package/dist/query-keys.js +31 -0
- package/dist/query-keys.js.map +1 -0
- package/dist/schema-editor/SchemaEditor.d.ts +43 -0
- package/dist/schema-editor/SchemaEditor.d.ts.map +1 -0
- package/dist/schema-editor/SchemaEditor.js +106 -0
- package/dist/schema-editor/SchemaEditor.js.map +1 -0
- package/dist/schema-editor/index.d.ts +10 -0
- package/dist/schema-editor/index.d.ts.map +1 -0
- package/dist/schema-editor/index.js +8 -0
- package/dist/schema-editor/index.js.map +1 -0
- package/dist/schema-editor/lint.d.ts +37 -0
- package/dist/schema-editor/lint.d.ts.map +1 -0
- package/dist/schema-editor/lint.js +49 -0
- package/dist/schema-editor/lint.js.map +1 -0
- package/dist/schema-form/SchemaForm.d.ts +70 -0
- package/dist/schema-form/SchemaForm.d.ts.map +1 -0
- package/dist/schema-form/SchemaForm.js +13 -0
- package/dist/schema-form/SchemaForm.js.map +1 -0
- package/dist/schema-form/array-field.d.ts +20 -0
- package/dist/schema-form/array-field.d.ts.map +1 -0
- package/dist/schema-form/array-field.js +39 -0
- package/dist/schema-form/array-field.js.map +1 -0
- package/dist/schema-form/classify.d.ts +87 -0
- package/dist/schema-form/classify.d.ts.map +1 -0
- package/dist/schema-form/classify.js +199 -0
- package/dist/schema-form/classify.js.map +1 -0
- package/dist/schema-form/context.d.ts +4 -0
- package/dist/schema-form/context.d.ts.map +1 -0
- package/dist/schema-form/context.js +14 -0
- package/dist/schema-form/context.js.map +1 -0
- package/dist/schema-form/default-value.d.ts +8 -0
- package/dist/schema-form/default-value.d.ts.map +1 -0
- package/dist/schema-form/default-value.js +64 -0
- package/dist/schema-form/default-value.js.map +1 -0
- package/dist/schema-form/enum-field.d.ts +19 -0
- package/dist/schema-form/enum-field.d.ts.map +1 -0
- package/dist/schema-form/enum-field.js +26 -0
- package/dist/schema-form/enum-field.js.map +1 -0
- package/dist/schema-form/field-group.d.ts +9 -0
- package/dist/schema-form/field-group.d.ts.map +1 -0
- package/dist/schema-form/field-group.js +32 -0
- package/dist/schema-form/field-group.js.map +1 -0
- package/dist/schema-form/field-node.d.ts +24 -0
- package/dist/schema-form/field-node.d.ts.map +1 -0
- package/dist/schema-form/field-node.js +51 -0
- package/dist/schema-form/field-node.js.map +1 -0
- package/dist/schema-form/index.d.ts +13 -0
- package/dist/schema-form/index.d.ts.map +1 -0
- package/dist/schema-form/index.js +11 -0
- package/dist/schema-form/index.js.map +1 -0
- package/dist/schema-form/media-field.d.ts +24 -0
- package/dist/schema-form/media-field.d.ts.map +1 -0
- package/dist/schema-form/media-field.js +169 -0
- package/dist/schema-form/media-field.js.map +1 -0
- package/dist/schema-form/media.d.ts +40 -0
- package/dist/schema-form/media.d.ts.map +1 -0
- package/dist/schema-form/media.js +65 -0
- package/dist/schema-form/media.js.map +1 -0
- package/dist/schema-form/object-fields.d.ts +20 -0
- package/dist/schema-form/object-fields.d.ts.map +1 -0
- package/dist/schema-form/object-fields.js +24 -0
- package/dist/schema-form/object-fields.js.map +1 -0
- package/dist/schema-form/resolve.d.ts +41 -0
- package/dist/schema-form/resolve.d.ts.map +1 -0
- package/dist/schema-form/resolve.js +102 -0
- package/dist/schema-form/resolve.js.map +1 -0
- package/dist/schema-form/string-field.d.ts +20 -0
- package/dist/schema-form/string-field.d.ts.map +1 -0
- package/dist/schema-form/string-field.js +68 -0
- package/dist/schema-form/string-field.js.map +1 -0
- package/dist/schema-form/styles.d.ts +18 -0
- package/dist/schema-form/styles.d.ts.map +1 -0
- package/dist/schema-form/styles.js +18 -0
- package/dist/schema-form/styles.js.map +1 -0
- package/dist/schema-form/types.d.ts +67 -0
- package/dist/schema-form/types.d.ts.map +1 -0
- package/dist/schema-form/types.js +10 -0
- package/dist/schema-form/types.js.map +1 -0
- package/dist/schema-form/union-field.d.ts +24 -0
- package/dist/schema-form/union-field.d.ts.map +1 -0
- package/dist/schema-form/union-field.js +55 -0
- package/dist/schema-form/union-field.js.map +1 -0
- package/dist/schema-form/union.d.ts +4 -0
- package/dist/schema-form/union.d.ts.map +1 -0
- package/dist/schema-form/union.js +68 -0
- package/dist/schema-form/union.js.map +1 -0
- package/dist/schema-form/unsupported-notice.d.ts +18 -0
- package/dist/schema-form/unsupported-notice.d.ts.map +1 -0
- package/dist/schema-form/unsupported-notice.js +8 -0
- package/dist/schema-form/unsupported-notice.js.map +1 -0
- package/dist/schema-form/validate.d.ts +18 -0
- package/dist/schema-form/validate.d.ts.map +1 -0
- package/dist/schema-form/validate.js +162 -0
- package/dist/schema-form/validate.js.map +1 -0
- package/dist/structured-output/StructuredOutput.d.ts +27 -0
- package/dist/structured-output/StructuredOutput.d.ts.map +1 -0
- package/dist/structured-output/StructuredOutput.js +41 -0
- package/dist/structured-output/StructuredOutput.js.map +1 -0
- package/dist/testing.d.ts +80 -0
- package/dist/testing.d.ts.map +1 -0
- package/dist/testing.js +207 -0
- package/dist/testing.js.map +1 -0
- package/package.json +101 -0
- package/src/components/badge.tsx +31 -0
- package/src/components/checkbox.tsx +93 -0
- package/src/components/code-block.tsx +37 -0
- package/src/components/completion-input.tsx +137 -0
- package/src/components/components.css +2212 -0
- package/src/components/confirm-dialog.tsx +77 -0
- package/src/components/control-styles.ts +14 -0
- package/src/components/copy-field.tsx +178 -0
- package/src/components/dialog.tsx +76 -0
- package/src/components/drawer.tsx +83 -0
- package/src/components/error-boundary.tsx +56 -0
- package/src/components/extension-combo-builder.tsx +305 -0
- package/src/components/extension-grouping.ts +116 -0
- package/src/components/extension-picker.tsx +97 -0
- package/src/components/external-link.tsx +40 -0
- package/src/components/field.tsx +169 -0
- package/src/components/fleet-report.tsx +136 -0
- package/src/components/fonts.css +22 -0
- package/src/components/icons.tsx +504 -0
- package/src/components/inputs.tsx +125 -0
- package/src/components/json-diff.tsx +192 -0
- package/src/components/json-tree.tsx +129 -0
- package/src/components/modal-focus.ts +150 -0
- package/src/components/page-header.tsx +107 -0
- package/src/components/primitives.tsx +489 -0
- package/src/components/progress-bar.tsx +100 -0
- package/src/components/radio-group.tsx +160 -0
- package/src/components/reveal-input.tsx +87 -0
- package/src/components/scroll-region.tsx +703 -0
- package/src/components/select.tsx +149 -0
- package/src/components/table.tsx +94 -0
- package/src/components/tabs.tsx +51 -0
- package/src/components/tags.tsx +137 -0
- package/src/components/tokens.css +392 -0
- package/src/components/tokens.ts +102 -0
- package/src/components/tool-picker.tsx +175 -0
- package/src/components/tooltip.tsx +46 -0
- package/src/components/version-history-panel.tsx +407 -0
- package/src/css.d.ts +2 -0
- package/src/download.ts +17 -0
- package/src/element-slot.ts +22 -0
- package/src/elicitation/ElicitationForm.tsx +87 -0
- package/src/errors.ts +12 -0
- package/src/extension-combos.ts +18 -0
- package/src/hooks/useApi.ts +27 -0
- package/src/hooks/useAuth.ts +67 -0
- package/src/hooks/useBreakpoint.ts +78 -0
- package/src/hooks/useCapabilities.ts +242 -0
- package/src/hooks/useSse.ts +314 -0
- package/src/hooks/useTheme.ts +133 -0
- package/src/hooks/useUnauthorized.ts +20 -0
- package/src/host.ts +15 -0
- package/src/index.ts +267 -0
- package/src/navigation/context.tsx +90 -0
- package/src/navigation/index.ts +9 -0
- package/src/navigation/types.ts +90 -0
- package/src/plugin/host-state.ts +93 -0
- package/src/plugin/registry.ts +174 -0
- package/src/plugin/types.ts +178 -0
- package/src/plugin/version.ts +44 -0
- package/src/query-keys.ts +34 -0
- package/src/schema-editor/SchemaEditor.tsx +186 -0
- package/src/schema-editor/index.ts +9 -0
- package/src/schema-editor/lint.ts +70 -0
- package/src/schema-form/SchemaForm.tsx +107 -0
- package/src/schema-form/array-field.tsx +110 -0
- package/src/schema-form/classify.ts +302 -0
- package/src/schema-form/context.ts +17 -0
- package/src/schema-form/default-value.ts +65 -0
- package/src/schema-form/enum-field.tsx +65 -0
- package/src/schema-form/field-group.tsx +71 -0
- package/src/schema-form/field-node.tsx +161 -0
- package/src/schema-form/index.ts +12 -0
- package/src/schema-form/media-field.tsx +281 -0
- package/src/schema-form/media.ts +69 -0
- package/src/schema-form/object-fields.tsx +74 -0
- package/src/schema-form/resolve.ts +114 -0
- package/src/schema-form/string-field.tsx +161 -0
- package/src/schema-form/styles.ts +20 -0
- package/src/schema-form/types.ts +71 -0
- package/src/schema-form/union-field.tsx +122 -0
- package/src/schema-form/union.ts +78 -0
- package/src/schema-form/unsupported-notice.tsx +39 -0
- package/src/schema-form/validate.ts +183 -0
- package/src/structured-output/StructuredOutput.tsx +81 -0
- package/src/testing.ts +235 -0
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `SchemaForm` — the controlled, JSON-Schema-driven auto-form. Given a schema
|
|
3
|
+
* (as Pydantic v2 emits) plus a value and `onChange`, it renders the form and
|
|
4
|
+
* emits a plain JS value; the CALLER owns the submit button. It is the
|
|
5
|
+
* load-bearing renderer reused by the tools run panel and the interactions form
|
|
6
|
+
* answer format, which is why it lives in the SDK (features cannot import each
|
|
7
|
+
* other).
|
|
8
|
+
*
|
|
9
|
+
* SAFETY: every schema-derived string (title, description, enum label, notice)
|
|
10
|
+
* is rendered as TEXT through the DS components — React escapes it. No markdown,
|
|
11
|
+
* no HTML, no `dangerouslySetInnerHTML` sink ever touches a schema-supplied
|
|
12
|
+
* string. Pinned by a test.
|
|
13
|
+
*
|
|
14
|
+
* MEDIA UPLOADS: a string field renders as a file-upload / drag-drop control
|
|
15
|
+
* (instead of a text box) when its schema carries media annotations, so an
|
|
16
|
+
* image/file input stays a JSON-serializable string that round-trips through the
|
|
17
|
+
* normal submit path. The annotation contract:
|
|
18
|
+
* - `contentEncoding: "base64"` + `contentMediaType` (e.g. `"image/*"`,
|
|
19
|
+
* `"application/pdf"`) → the emitted value is the raw base64 body (no
|
|
20
|
+
* `data:` prefix); `contentMediaType` also constrains the accepted MIME.
|
|
21
|
+
* - `format: "data-url"` (optionally with `contentMediaType`) → the emitted
|
|
22
|
+
* value is a full `data:<mime>;base64,<body>` URL.
|
|
23
|
+
* - `contentMaxBytes` pins a per-field size cap (bytes); otherwise the
|
|
24
|
+
* {@link SchemaFormProps.maxUploadBytes} prop, else {@link DEFAULT_MAX_UPLOAD_BYTES}.
|
|
25
|
+
* An over-cap value or a MIME that does not match `contentMediaType` is REJECTED
|
|
26
|
+
* with a visible error — never silently truncated or accepted. The cap holds on
|
|
27
|
+
* EVERY input path (file picker, the paste fallback, and `validateAgainstSchema`),
|
|
28
|
+
* measured against the value's DECODED byte size. A text fallback (paste a
|
|
29
|
+
* URL/base64) stays available. The uploaded filename renders ESCAPED.
|
|
30
|
+
*
|
|
31
|
+
* `contentMaxBytes` is a NONSTANDARD JSON-Schema extension keyword (a standard
|
|
32
|
+
* validator ignores it); these client-side caps are UX guards, and the SERVER
|
|
33
|
+
* MUST independently validate the decoded size. The base64 decoding and cap
|
|
34
|
+
* checks live in the sibling `media` module.
|
|
35
|
+
*/
|
|
36
|
+
import type { ReactNode } from 'react';
|
|
37
|
+
import type { JsonSchema, SchemaFormErrors } from './types';
|
|
38
|
+
/**
|
|
39
|
+
* Fetch argument-value suggestions for a string field. `argName` is the field's
|
|
40
|
+
* path within the form (a property key at the root, a dotted path when nested);
|
|
41
|
+
* `partial` is the value typed so far. The caller owns the source (e.g. an MCP
|
|
42
|
+
* `completion/complete` call) — SchemaForm only routes string fields through the
|
|
43
|
+
* completion-backed input when a provider is supplied.
|
|
44
|
+
*/
|
|
45
|
+
export type CompletionProvider = (argName: string, partial: string) => Promise<string[]>;
|
|
46
|
+
export interface SchemaFormProps {
|
|
47
|
+
readonly schema: JsonSchema;
|
|
48
|
+
readonly value: unknown;
|
|
49
|
+
readonly onChange: (value: unknown) => void;
|
|
50
|
+
readonly errors?: SchemaFormErrors;
|
|
51
|
+
readonly idPrefix?: string;
|
|
52
|
+
/**
|
|
53
|
+
* Optional. When supplied, every string field renders through the
|
|
54
|
+
* completion-backed input (argument autocomplete); when omitted, string fields
|
|
55
|
+
* render as a plain text input — the default, unchanged behaviour.
|
|
56
|
+
*/
|
|
57
|
+
readonly completionProvider?: CompletionProvider;
|
|
58
|
+
/**
|
|
59
|
+
* Optional. Default byte cap for media-upload fields (see the module
|
|
60
|
+
* doc-comment). A field's own `contentMaxBytes` annotation overrides it;
|
|
61
|
+
* absent both, {@link DEFAULT_MAX_UPLOAD_BYTES} applies.
|
|
62
|
+
*/
|
|
63
|
+
readonly maxUploadBytes?: number;
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* Render a controlled form for `schema`. The root is usually an object (a tool's
|
|
67
|
+
* input schema); a scalar/array/union root renders as a single field group.
|
|
68
|
+
*/
|
|
69
|
+
export declare function SchemaForm({ schema, value, onChange, errors, idPrefix, completionProvider, maxUploadBytes, }: SchemaFormProps): ReactNode;
|
|
70
|
+
//# sourceMappingURL=SchemaForm.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SchemaForm.d.ts","sourceRoot":"","sources":["../../src/schema-form/SchemaForm.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkCG;AACH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAMvC,OAAO,KAAK,EAAE,UAAU,EAAE,gBAAgB,EAAE,MAAM,SAAS,CAAC;AAI5D;;;;;;GAMG;AACH,MAAM,MAAM,kBAAkB,GAAG,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC;AAEzF,MAAM,WAAW,eAAe;IAC9B,QAAQ,CAAC,MAAM,EAAE,UAAU,CAAC;IAC5B,QAAQ,CAAC,KAAK,EAAE,OAAO,CAAC;IACxB,QAAQ,CAAC,QAAQ,EAAE,CAAC,KAAK,EAAE,OAAO,KAAK,IAAI,CAAC;IAC5C,QAAQ,CAAC,MAAM,CAAC,EAAE,gBAAgB,CAAC;IACnC,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAC3B;;;;OAIG;IACH,QAAQ,CAAC,kBAAkB,CAAC,EAAE,kBAAkB,CAAC;IACjD;;;;OAIG;IACH,QAAQ,CAAC,cAAc,CAAC,EAAE,MAAM,CAAC;CAClC;AAED;;;GAGG;AACH,wBAAgB,UAAU,CAAC,EACzB,MAAM,EACN,KAAK,EACL,QAAQ,EACR,MAAM,EACN,QAAwB,EACxB,kBAAkB,EAClB,cAAyC,GAC1C,EAAE,eAAe,GAAG,SAAS,CAoB7B"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { CompletionProviderContext, MaxUploadBytesContext } from './context';
|
|
3
|
+
import { FieldNode } from './field-node';
|
|
4
|
+
import { DEFAULT_MAX_UPLOAD_BYTES } from './media';
|
|
5
|
+
import { stackClass } from './styles';
|
|
6
|
+
/**
|
|
7
|
+
* Render a controlled form for `schema`. The root is usually an object (a tool's
|
|
8
|
+
* input schema); a scalar/array/union root renders as a single field group.
|
|
9
|
+
*/
|
|
10
|
+
export function SchemaForm({ schema, value, onChange, errors, idPrefix = 'schema-form', completionProvider, maxUploadBytes = DEFAULT_MAX_UPLOAD_BYTES, }) {
|
|
11
|
+
return (_jsx(CompletionProviderContext.Provider, { value: completionProvider, children: _jsx(MaxUploadBytesContext.Provider, { value: maxUploadBytes, children: _jsx("div", { className: stackClass, "data-testid": idPrefix, children: _jsx(FieldNode, { schema: schema, root: schema, value: value, onChange: onChange, path: "", label: undefined, required: true, errors: errors, idPrefix: idPrefix }) }) }) }));
|
|
12
|
+
}
|
|
13
|
+
//# sourceMappingURL=SchemaForm.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SchemaForm.js","sourceRoot":"","sources":["../../src/schema-form/SchemaForm.tsx"],"names":[],"mappings":";AAqCA,OAAO,EAAE,yBAAyB,EAAE,qBAAqB,EAAE,MAAM,WAAW,CAAC;AAC7E,OAAO,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AACzC,OAAO,EAAE,wBAAwB,EAAE,MAAM,SAAS,CAAC;AACnD,OAAO,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AAkCtC;;;GAGG;AACH,MAAM,UAAU,UAAU,CAAC,EACzB,MAAM,EACN,KAAK,EACL,QAAQ,EACR,MAAM,EACN,QAAQ,GAAG,aAAa,EACxB,kBAAkB,EAClB,cAAc,GAAG,wBAAwB,GACzB;IAChB,OAAO,CACL,KAAC,yBAAyB,CAAC,QAAQ,IAAC,KAAK,EAAE,kBAAkB,YAC3D,KAAC,qBAAqB,CAAC,QAAQ,IAAC,KAAK,EAAE,cAAc,YACnD,cAAK,SAAS,EAAE,UAAU,iBAAe,QAAQ,YAC/C,KAAC,SAAS,IACR,MAAM,EAAE,MAAM,EACd,IAAI,EAAE,MAAM,EACZ,KAAK,EAAE,KAAK,EACZ,QAAQ,EAAE,QAAQ,EAClB,IAAI,EAAC,EAAE,EACP,KAAK,EAAE,SAAS,EAChB,QAAQ,QACR,MAAM,EAAE,MAAM,EACd,QAAQ,EAAE,QAAQ,GAClB,GACE,GACyB,GACE,CACtC,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The array field renderer. Each item is a nested {@link FieldNode}; edits map
|
|
3
|
+
* the list to a new array (add appends a seeded item, remove filters by index).
|
|
4
|
+
* The whole list re-renders as one controlled value, so index keys are correct.
|
|
5
|
+
*/
|
|
6
|
+
import type { ReactNode } from 'react';
|
|
7
|
+
import type { JsonSchema, SchemaFormErrors } from './types';
|
|
8
|
+
export declare function ArrayField({ heading, description, error, items, root, value, onChange, path, errors, idPrefix, }: {
|
|
9
|
+
heading: string;
|
|
10
|
+
description: string | undefined;
|
|
11
|
+
error: string | undefined;
|
|
12
|
+
items: JsonSchema;
|
|
13
|
+
root: JsonSchema;
|
|
14
|
+
value: unknown;
|
|
15
|
+
onChange: (value: unknown) => void;
|
|
16
|
+
path: string;
|
|
17
|
+
errors: SchemaFormErrors | undefined;
|
|
18
|
+
idPrefix: string;
|
|
19
|
+
}): ReactNode;
|
|
20
|
+
//# sourceMappingURL=array-field.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"array-field.d.ts","sourceRoot":"","sources":["../../src/schema-form/array-field.tsx"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAQvC,OAAO,KAAK,EAAE,UAAU,EAAE,gBAAgB,EAAE,MAAM,SAAS,CAAC;AAE5D,wBAAgB,UAAU,CAAC,EACzB,OAAO,EACP,WAAW,EACX,KAAK,EACL,KAAK,EACL,IAAI,EACJ,KAAK,EACL,QAAQ,EACR,IAAI,EACJ,MAAM,EACN,QAAQ,GACT,EAAE;IACD,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,EAAE,MAAM,GAAG,SAAS,CAAC;IAChC,KAAK,EAAE,MAAM,GAAG,SAAS,CAAC;IAC1B,KAAK,EAAE,UAAU,CAAC;IAClB,IAAI,EAAE,UAAU,CAAC;IACjB,KAAK,EAAE,OAAO,CAAC;IACf,QAAQ,EAAE,CAAC,KAAK,EAAE,OAAO,KAAK,IAAI,CAAC;IACnC,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,gBAAgB,GAAG,SAAS,CAAC;IACrC,QAAQ,EAAE,MAAM,CAAC;CAClB,GAAG,SAAS,CA0DZ"}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { CloseIcon } from '../components/icons';
|
|
3
|
+
import { Button } from '../components/primitives';
|
|
4
|
+
import { classifySchema } from './classify';
|
|
5
|
+
import { defaultValueForSchema } from './default-value';
|
|
6
|
+
import { FieldGroup } from './field-group';
|
|
7
|
+
import { FieldNode } from './field-node';
|
|
8
|
+
export function ArrayField({ heading, description, error, items, root, value, onChange, path, errors, idPrefix, }) {
|
|
9
|
+
const list = Array.isArray(value) ? value : [];
|
|
10
|
+
const addItem = () => {
|
|
11
|
+
onChange([...list, newItemValue(items, root)]);
|
|
12
|
+
};
|
|
13
|
+
const removeItem = (index) => {
|
|
14
|
+
onChange(list.filter((_, position) => position !== index));
|
|
15
|
+
};
|
|
16
|
+
const setItem = (index, next) => {
|
|
17
|
+
onChange(list.map((item, position) => (position === index ? next : item)));
|
|
18
|
+
};
|
|
19
|
+
return (_jsxs(FieldGroup, { heading: heading, description: description, error: error, atRoot: false, children: [list.length === 0 ? _jsx("span", { className: "tai-field-hint", children: "No items" }) : null, list.map((item, index) => (_jsxs("div", { className: "tai-row", children: [_jsx("div", { style: { flex: 1 }, children: _jsx(FieldNode, { schema: items, root: root, value: item, onChange: (next) => {
|
|
20
|
+
setItem(index, next);
|
|
21
|
+
}, path: `${path}[${String(index)}]`, label: `Item ${String(index + 1)}`, required: true, errors: errors, idPrefix: idPrefix }) }), _jsxs(Button, { type: "button", variant: "secondary", "aria-label": `Remove item ${String(index + 1)}`, onClick: () => {
|
|
22
|
+
removeItem(index);
|
|
23
|
+
}, children: [_jsx(CloseIcon, {}), "Remove"] })] }, index))), _jsx("div", { children: _jsx(Button, { type: "button", variant: "secondary", onClick: addItem, children: "Add item" }) })] }));
|
|
24
|
+
}
|
|
25
|
+
function newItemValue(schema, root) {
|
|
26
|
+
const seeded = defaultValueForSchema(schema, root);
|
|
27
|
+
if (seeded !== undefined)
|
|
28
|
+
return seeded;
|
|
29
|
+
const classified = classifySchema(schema, root);
|
|
30
|
+
switch (classified.model.kind) {
|
|
31
|
+
case 'string':
|
|
32
|
+
return '';
|
|
33
|
+
case 'boolean':
|
|
34
|
+
return false;
|
|
35
|
+
default:
|
|
36
|
+
return undefined;
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
//# sourceMappingURL=array-field.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"array-field.js","sourceRoot":"","sources":["../../src/schema-form/array-field.tsx"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The single source of truth for "what kind of field is this schema?". Both the
|
|
3
|
+
* renderer and the validator classify through here so a construct is treated
|
|
4
|
+
* identically everywhere. Classification resolves `$ref`, normalizes `anyOf`/
|
|
5
|
+
* `oneOf` (null-union → nullable single field; multi-member → variant selector),
|
|
6
|
+
* and lands every unrecognized construct on the explicit `unsupported` kind —
|
|
7
|
+
* a field is never silently dropped.
|
|
8
|
+
*/
|
|
9
|
+
import { type EnumOption } from './resolve';
|
|
10
|
+
import type { JsonSchema } from './types';
|
|
11
|
+
/**
|
|
12
|
+
* How a string field accepts binary content as a JSON-serializable string.
|
|
13
|
+
* Derived from a field's JSON-Schema media annotations (see the `SchemaForm` module).
|
|
14
|
+
*/
|
|
15
|
+
export interface MediaUpload {
|
|
16
|
+
/**
|
|
17
|
+
* `base64` — the emitted value is the raw base64 body (no `data:` prefix),
|
|
18
|
+
* matching `contentEncoding: "base64"`. `data-url` — the emitted value is a
|
|
19
|
+
* full `data:<mime>;base64,<body>` URL, matching `format: "data-url"`.
|
|
20
|
+
*/
|
|
21
|
+
readonly encoding: 'base64' | 'data-url';
|
|
22
|
+
/**
|
|
23
|
+
* The `contentMediaType` constraint (e.g. `image/*`, `application/pdf`), used
|
|
24
|
+
* for MIME validation and the file picker's `accept`. `undefined` for a bare
|
|
25
|
+
* `format: "data-url"` field with no declared type.
|
|
26
|
+
*/
|
|
27
|
+
readonly mediaType: string | undefined;
|
|
28
|
+
/** A per-field byte cap from `contentMaxBytes`, if the schema pins one. */
|
|
29
|
+
readonly maxBytes: number | undefined;
|
|
30
|
+
}
|
|
31
|
+
/** One selectable variant of a union field. */
|
|
32
|
+
export interface UnionVariant {
|
|
33
|
+
readonly label: string;
|
|
34
|
+
/** The discriminator tag value, or `undefined` for a non-discriminated union. */
|
|
35
|
+
readonly tag: unknown;
|
|
36
|
+
/** The variant schema as written (unresolved — the renderer resolves it). */
|
|
37
|
+
readonly schema: JsonSchema;
|
|
38
|
+
}
|
|
39
|
+
/** The renderer-facing classification of a schema node. */
|
|
40
|
+
export type FieldModel = {
|
|
41
|
+
readonly kind: 'const';
|
|
42
|
+
readonly value: unknown;
|
|
43
|
+
} | {
|
|
44
|
+
readonly kind: 'enum';
|
|
45
|
+
readonly options: readonly EnumOption[];
|
|
46
|
+
} | {
|
|
47
|
+
readonly kind: 'string';
|
|
48
|
+
readonly format: string | undefined;
|
|
49
|
+
/** Present when media annotations opt the field into the upload control. */
|
|
50
|
+
readonly media: MediaUpload | undefined;
|
|
51
|
+
} | {
|
|
52
|
+
readonly kind: 'number';
|
|
53
|
+
readonly integer: boolean;
|
|
54
|
+
} | {
|
|
55
|
+
readonly kind: 'boolean';
|
|
56
|
+
} | {
|
|
57
|
+
readonly kind: 'array';
|
|
58
|
+
readonly items: JsonSchema;
|
|
59
|
+
} | {
|
|
60
|
+
readonly kind: 'object';
|
|
61
|
+
readonly properties: readonly (readonly [string, JsonSchema])[];
|
|
62
|
+
readonly required: ReadonlySet<string>;
|
|
63
|
+
} | {
|
|
64
|
+
readonly kind: 'union';
|
|
65
|
+
readonly variants: readonly UnionVariant[];
|
|
66
|
+
readonly discriminator: string | undefined;
|
|
67
|
+
} | {
|
|
68
|
+
readonly kind: 'unsupported';
|
|
69
|
+
readonly reason: string;
|
|
70
|
+
};
|
|
71
|
+
/** A fully classified field: its model plus resolved metadata. */
|
|
72
|
+
export interface ClassifiedField {
|
|
73
|
+
readonly model: FieldModel;
|
|
74
|
+
/** True when JSON `null` is an accepted value (a null-union member). */
|
|
75
|
+
readonly nullable: boolean;
|
|
76
|
+
/** The effective (ref-resolved) schema this classification describes. */
|
|
77
|
+
readonly schema: JsonSchema;
|
|
78
|
+
readonly title: string | undefined;
|
|
79
|
+
readonly description: string | undefined;
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* Classify a schema node (resolving `$ref` first). `wrapper` metadata (a
|
|
83
|
+
* ref-site title/description) is threaded down so a `{ $ref, title }` or a
|
|
84
|
+
* null-union wrapper keeps its property-level label.
|
|
85
|
+
*/
|
|
86
|
+
export declare function classifySchema(raw: JsonSchema, root: JsonSchema): ClassifiedField;
|
|
87
|
+
//# sourceMappingURL=classify.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"classify.d.ts","sourceRoot":"","sources":["../../src/schema-form/classify.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,OAAO,EAQL,KAAK,UAAU,EAChB,MAAM,WAAW,CAAC;AACnB,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AAE1C;;;GAGG;AACH,MAAM,WAAW,WAAW;IAC1B;;;;OAIG;IACH,QAAQ,CAAC,QAAQ,EAAE,QAAQ,GAAG,UAAU,CAAC;IACzC;;;;OAIG;IACH,QAAQ,CAAC,SAAS,EAAE,MAAM,GAAG,SAAS,CAAC;IACvC,2EAA2E;IAC3E,QAAQ,CAAC,QAAQ,EAAE,MAAM,GAAG,SAAS,CAAC;CACvC;AAED,+CAA+C;AAC/C,MAAM,WAAW,YAAY;IAC3B,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,iFAAiF;IACjF,QAAQ,CAAC,GAAG,EAAE,OAAO,CAAC;IACtB,6EAA6E;IAC7E,QAAQ,CAAC,MAAM,EAAE,UAAU,CAAC;CAC7B;AAED,2DAA2D;AAC3D,MAAM,MAAM,UAAU,GAClB;IAAE,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC;IAAC,QAAQ,CAAC,KAAK,EAAE,OAAO,CAAA;CAAE,GACnD;IAAE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,OAAO,EAAE,SAAS,UAAU,EAAE,CAAA;CAAE,GAClE;IACE,QAAQ,CAAC,IAAI,EAAE,QAAQ,CAAC;IACxB,QAAQ,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC;IACpC,4EAA4E;IAC5E,QAAQ,CAAC,KAAK,EAAE,WAAW,GAAG,SAAS,CAAC;CACzC,GACD;IAAE,QAAQ,CAAC,IAAI,EAAE,QAAQ,CAAC;IAAC,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAA;CAAE,GACtD;IAAE,QAAQ,CAAC,IAAI,EAAE,SAAS,CAAA;CAAE,GAC5B;IAAE,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC;IAAC,QAAQ,CAAC,KAAK,EAAE,UAAU,CAAA;CAAE,GACtD;IACE,QAAQ,CAAC,IAAI,EAAE,QAAQ,CAAC;IACxB,QAAQ,CAAC,UAAU,EAAE,SAAS,CAAC,SAAS,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC,EAAE,CAAC;IAChE,QAAQ,CAAC,QAAQ,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC;CACxC,GACD;IACE,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC;IACvB,QAAQ,CAAC,QAAQ,EAAE,SAAS,YAAY,EAAE,CAAC;IAC3C,QAAQ,CAAC,aAAa,EAAE,MAAM,GAAG,SAAS,CAAC;CAC5C,GACD;IAAE,QAAQ,CAAC,IAAI,EAAE,aAAa,CAAC;IAAC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC;AAE9D,kEAAkE;AAClE,MAAM,WAAW,eAAe;IAC9B,QAAQ,CAAC,KAAK,EAAE,UAAU,CAAC;IAC3B,wEAAwE;IACxE,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAC;IAC3B,yEAAyE;IACzE,QAAQ,CAAC,MAAM,EAAE,UAAU,CAAC;IAC5B,QAAQ,CAAC,KAAK,EAAE,MAAM,GAAG,SAAS,CAAC;IACnC,QAAQ,CAAC,WAAW,EAAE,MAAM,GAAG,SAAS,CAAC;CAC1C;AAuCD;;;;GAIG;AACH,wBAAgB,cAAc,CAAC,GAAG,EAAE,UAAU,EAAE,IAAI,EAAE,UAAU,GAAG,eAAe,CA6KjF"}
|
|
@@ -0,0 +1,199 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The single source of truth for "what kind of field is this schema?". Both the
|
|
3
|
+
* renderer and the validator classify through here so a construct is treated
|
|
4
|
+
* identically everywhere. Classification resolves `$ref`, normalizes `anyOf`/
|
|
5
|
+
* `oneOf` (null-union → nullable single field; multi-member → variant selector),
|
|
6
|
+
* and lands every unrecognized construct on the explicit `unsupported` kind —
|
|
7
|
+
* a field is never silently dropped.
|
|
8
|
+
*/
|
|
9
|
+
import { isNullSchema, resolveRef, scalarLabel, typeList, unionMembers, variantLabel, variantTag, } from './resolve';
|
|
10
|
+
function firstString(...values) {
|
|
11
|
+
for (const value of values) {
|
|
12
|
+
if (typeof value === 'string' && value.length > 0)
|
|
13
|
+
return value;
|
|
14
|
+
}
|
|
15
|
+
return undefined;
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Detect the media-upload annotations on a (ref-resolved) string schema. A field
|
|
19
|
+
* opts into the upload control when it carries `contentEncoding: "base64"` plus a
|
|
20
|
+
* `contentMediaType`, OR `format: "data-url"`. Anything else is a plain string.
|
|
21
|
+
*/
|
|
22
|
+
function mediaUpload(schema) {
|
|
23
|
+
const mediaType = typeof schema.contentMediaType === 'string' ? schema.contentMediaType : undefined;
|
|
24
|
+
const maxBytes = typeof schema.contentMaxBytes === 'number' && schema.contentMaxBytes > 0
|
|
25
|
+
? schema.contentMaxBytes
|
|
26
|
+
: undefined;
|
|
27
|
+
if (schema.format === 'data-url') {
|
|
28
|
+
return { encoding: 'data-url', mediaType, maxBytes };
|
|
29
|
+
}
|
|
30
|
+
if (schema.contentEncoding === 'base64' && mediaType !== undefined) {
|
|
31
|
+
return { encoding: 'base64', mediaType, maxBytes };
|
|
32
|
+
}
|
|
33
|
+
return undefined;
|
|
34
|
+
}
|
|
35
|
+
function unsupported(schema, reason, title, description) {
|
|
36
|
+
return { model: { kind: 'unsupported', reason }, nullable: false, schema, title, description };
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Classify a schema node (resolving `$ref` first). `wrapper` metadata (a
|
|
40
|
+
* ref-site title/description) is threaded down so a `{ $ref, title }` or a
|
|
41
|
+
* null-union wrapper keeps its property-level label.
|
|
42
|
+
*/
|
|
43
|
+
export function classifySchema(raw, root) {
|
|
44
|
+
const resolved = resolveRef(raw, root);
|
|
45
|
+
const title = firstString(raw.title, resolved.title);
|
|
46
|
+
const description = firstString(raw.description, resolved.description);
|
|
47
|
+
// const pins a single value.
|
|
48
|
+
if ('const' in resolved) {
|
|
49
|
+
return {
|
|
50
|
+
model: { kind: 'const', value: resolved.const },
|
|
51
|
+
nullable: false,
|
|
52
|
+
schema: resolved,
|
|
53
|
+
title,
|
|
54
|
+
description,
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
// enum → a fixed choice list.
|
|
58
|
+
if (resolved.enum !== undefined) {
|
|
59
|
+
const options = resolved.enum.map((value) => ({
|
|
60
|
+
value,
|
|
61
|
+
label: scalarLabel(value),
|
|
62
|
+
}));
|
|
63
|
+
const nullable = resolved.enum.some((value) => value === null);
|
|
64
|
+
return { model: { kind: 'enum', options }, nullable, schema: resolved, title, description };
|
|
65
|
+
}
|
|
66
|
+
// anyOf/oneOf union normalization.
|
|
67
|
+
const members = unionMembers(resolved);
|
|
68
|
+
if (members !== undefined) {
|
|
69
|
+
const nonNull = members.filter((member) => !isNullSchema(resolveRef(member, root)));
|
|
70
|
+
const nullable = nonNull.length !== members.length;
|
|
71
|
+
const soleNonNull = nonNull[0];
|
|
72
|
+
if (soleNonNull === undefined) {
|
|
73
|
+
return unsupported(resolved, 'union with no non-null members', title, description);
|
|
74
|
+
}
|
|
75
|
+
if (nonNull.length === 1) {
|
|
76
|
+
const inner = classifySchema(soleNonNull, root);
|
|
77
|
+
// Media annotations (`contentEncoding`/`contentMediaType`/`format: data-url`)
|
|
78
|
+
// that land on the OUTER null-union wrapper of an OPTIONAL field would
|
|
79
|
+
// otherwise be lost when delegating to the inner string member, silently
|
|
80
|
+
// degrading an optional upload field to a plain text box. Re-detect them on
|
|
81
|
+
// the wrapper and attach to the inner string model.
|
|
82
|
+
const model = inner.model.kind === 'string' && inner.model.media === undefined
|
|
83
|
+
? { ...inner.model, media: mediaUpload(resolved) }
|
|
84
|
+
: inner.model;
|
|
85
|
+
return {
|
|
86
|
+
model,
|
|
87
|
+
nullable: nullable || inner.nullable,
|
|
88
|
+
schema: inner.schema,
|
|
89
|
+
title: title ?? inner.title,
|
|
90
|
+
description: description ?? inner.description,
|
|
91
|
+
};
|
|
92
|
+
}
|
|
93
|
+
const discriminator = resolved.discriminator?.propertyName;
|
|
94
|
+
const variants = nonNull.map((member, index) => {
|
|
95
|
+
const tag = discriminator === undefined ? undefined : variantTag(member, discriminator, root);
|
|
96
|
+
return { label: variantLabel(member, index, tag, root), tag, schema: member };
|
|
97
|
+
});
|
|
98
|
+
return {
|
|
99
|
+
model: { kind: 'union', variants, discriminator },
|
|
100
|
+
nullable,
|
|
101
|
+
schema: resolved,
|
|
102
|
+
title,
|
|
103
|
+
description,
|
|
104
|
+
};
|
|
105
|
+
}
|
|
106
|
+
// allOf: Pydantic wraps a single $ref this way; a multi-member intersection is
|
|
107
|
+
// not a form-renderable construct.
|
|
108
|
+
if (resolved.allOf !== undefined) {
|
|
109
|
+
const soleAllOf = resolved.allOf[0];
|
|
110
|
+
if (resolved.allOf.length === 1 && soleAllOf !== undefined) {
|
|
111
|
+
const inner = classifySchema(soleAllOf, root);
|
|
112
|
+
return {
|
|
113
|
+
model: inner.model,
|
|
114
|
+
nullable: inner.nullable,
|
|
115
|
+
schema: inner.schema,
|
|
116
|
+
title: title ?? inner.title,
|
|
117
|
+
description: description ?? inner.description,
|
|
118
|
+
};
|
|
119
|
+
}
|
|
120
|
+
return unsupported(resolved, 'allOf intersection of multiple schemas', title, description);
|
|
121
|
+
}
|
|
122
|
+
// Type-driven classification.
|
|
123
|
+
const types = typeList(resolved);
|
|
124
|
+
const nonNullTypes = types.filter((type) => type !== 'null');
|
|
125
|
+
const nullableByType = nonNullTypes.length !== types.length;
|
|
126
|
+
if (nonNullTypes.length === 0) {
|
|
127
|
+
return unsupported(resolved, 'schema declares no renderable type', title, description);
|
|
128
|
+
}
|
|
129
|
+
if (nonNullTypes.length > 1) {
|
|
130
|
+
return unsupported(resolved, `multiple JSON types (${nonNullTypes.join(', ')}) without a discriminator`, title, description);
|
|
131
|
+
}
|
|
132
|
+
const type = nonNullTypes[0];
|
|
133
|
+
if (type === undefined) {
|
|
134
|
+
return unsupported(resolved, 'schema declares no renderable type', title, description);
|
|
135
|
+
}
|
|
136
|
+
switch (type) {
|
|
137
|
+
case 'string':
|
|
138
|
+
return {
|
|
139
|
+
model: { kind: 'string', format: resolved.format, media: mediaUpload(resolved) },
|
|
140
|
+
nullable: nullableByType,
|
|
141
|
+
schema: resolved,
|
|
142
|
+
title,
|
|
143
|
+
description,
|
|
144
|
+
};
|
|
145
|
+
case 'number':
|
|
146
|
+
return {
|
|
147
|
+
model: { kind: 'number', integer: false },
|
|
148
|
+
nullable: nullableByType,
|
|
149
|
+
schema: resolved,
|
|
150
|
+
title,
|
|
151
|
+
description,
|
|
152
|
+
};
|
|
153
|
+
case 'integer':
|
|
154
|
+
return {
|
|
155
|
+
model: { kind: 'number', integer: true },
|
|
156
|
+
nullable: nullableByType,
|
|
157
|
+
schema: resolved,
|
|
158
|
+
title,
|
|
159
|
+
description,
|
|
160
|
+
};
|
|
161
|
+
case 'boolean':
|
|
162
|
+
return {
|
|
163
|
+
model: { kind: 'boolean' },
|
|
164
|
+
nullable: nullableByType,
|
|
165
|
+
schema: resolved,
|
|
166
|
+
title,
|
|
167
|
+
description,
|
|
168
|
+
};
|
|
169
|
+
case 'array': {
|
|
170
|
+
if (resolved.items === undefined) {
|
|
171
|
+
return unsupported(resolved, 'array without an items schema', title, description);
|
|
172
|
+
}
|
|
173
|
+
return {
|
|
174
|
+
model: { kind: 'array', items: resolved.items },
|
|
175
|
+
nullable: nullableByType,
|
|
176
|
+
schema: resolved,
|
|
177
|
+
title,
|
|
178
|
+
description,
|
|
179
|
+
};
|
|
180
|
+
}
|
|
181
|
+
case 'object': {
|
|
182
|
+
if (resolved.properties === undefined) {
|
|
183
|
+
return unsupported(resolved, 'free-form object (additionalProperties map) is not supported', title, description);
|
|
184
|
+
}
|
|
185
|
+
const properties = Object.entries(resolved.properties);
|
|
186
|
+
const required = new Set(resolved.required ?? []);
|
|
187
|
+
return {
|
|
188
|
+
model: { kind: 'object', properties, required },
|
|
189
|
+
nullable: nullableByType,
|
|
190
|
+
schema: resolved,
|
|
191
|
+
title,
|
|
192
|
+
description,
|
|
193
|
+
};
|
|
194
|
+
}
|
|
195
|
+
default:
|
|
196
|
+
return unsupported(resolved, `unrecognized type "${String(type)}"`, title, description);
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
//# sourceMappingURL=classify.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"classify.js","sourceRoot":"","sources":["../../src/schema-form/classify.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import type { CompletionProvider } from './SchemaForm';
|
|
2
|
+
export declare const CompletionProviderContext: import("react").Context<CompletionProvider | undefined>;
|
|
3
|
+
export declare const MaxUploadBytesContext: import("react").Context<number>;
|
|
4
|
+
//# sourceMappingURL=context.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"context.d.ts","sourceRoot":"","sources":["../../src/schema-form/context.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,cAAc,CAAC;AAIvD,eAAO,MAAM,yBAAyB,yDAA2D,CAAC;AAIlG,eAAO,MAAM,qBAAqB,iCAAkD,CAAC"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Ambient React contexts for the schema-form tree: the optional argument
|
|
3
|
+
* completion provider and the default media-upload byte cap. A field deep in the
|
|
4
|
+
* tree reads these here rather than every intermediate node drilling the prop.
|
|
5
|
+
*/
|
|
6
|
+
import { createContext } from 'react';
|
|
7
|
+
import { DEFAULT_MAX_UPLOAD_BYTES } from './media';
|
|
8
|
+
// Ambient completion provider for the whole form. A string field deep in the
|
|
9
|
+
// tree reads it here rather than every intermediate node drilling the prop.
|
|
10
|
+
export const CompletionProviderContext = createContext(undefined);
|
|
11
|
+
// Ambient default upload cap for the whole form; a media field reads it here so
|
|
12
|
+
// intermediate object/array nodes never drill the prop.
|
|
13
|
+
export const MaxUploadBytesContext = createContext(DEFAULT_MAX_UPLOAD_BYTES);
|
|
14
|
+
//# sourceMappingURL=context.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"context.js","sourceRoot":"","sources":["../../src/schema-form/context.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,OAAO,EAAE,aAAa,EAAE,MAAM,OAAO,CAAC;AAEtC,OAAO,EAAE,wBAAwB,EAAE,MAAM,SAAS,CAAC;AAGnD,6EAA6E;AAC7E,4EAA4E;AAC5E,MAAM,CAAC,MAAM,yBAAyB,GAAG,aAAa,CAAiC,SAAS,CAAC,CAAC;AAElG,gFAAgF;AAChF,wDAAwD;AACxD,MAAM,CAAC,MAAM,qBAAqB,GAAG,aAAa,CAAS,wBAAwB,CAAC,CAAC"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { JsonSchema } from './types';
|
|
2
|
+
/**
|
|
3
|
+
* The initial value for a schema. `root` carries the `$defs` document for
|
|
4
|
+
* `$ref` resolution and defaults to the schema itself (the common
|
|
5
|
+
* whole-tool-schema call).
|
|
6
|
+
*/
|
|
7
|
+
export declare function defaultValueForSchema(schema: JsonSchema, root?: JsonSchema): unknown;
|
|
8
|
+
//# sourceMappingURL=default-value.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"default-value.d.ts","sourceRoot":"","sources":["../../src/schema-form/default-value.ts"],"names":[],"mappings":"AAcA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AAY1C;;;;GAIG;AACH,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,UAAU,EAAE,IAAI,GAAE,UAAmB,GAAG,OAAO,CAiC5F"}
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `defaultValueForSchema` — the initial form value for a schema, honoring
|
|
3
|
+
* `default`/`const` and seeding required nested structure.
|
|
4
|
+
*
|
|
5
|
+
* Inclusion rules keep the seed honest:
|
|
6
|
+
* - a REQUIRED property is seeded (objects → a nested seed, arrays → `[]`); a
|
|
7
|
+
* required scalar with no default is left ABSENT so validation flags it
|
|
8
|
+
* rather than inventing a value;
|
|
9
|
+
* - an OPTIONAL property is included only when it carries an explicit
|
|
10
|
+
* `default` — an optional object/array is NOT auto-materialized, so its own
|
|
11
|
+
* required children can't raise spurious errors on a field the user never
|
|
12
|
+
* opted into.
|
|
13
|
+
*/
|
|
14
|
+
import { classifySchema } from './classify';
|
|
15
|
+
/** The explicit `default` (wrapper takes precedence over the resolved node), if any. */
|
|
16
|
+
function explicitDefault(raw, resolved) {
|
|
17
|
+
if ('default' in raw)
|
|
18
|
+
return { present: true, value: raw.default };
|
|
19
|
+
if ('default' in resolved)
|
|
20
|
+
return { present: true, value: resolved.default };
|
|
21
|
+
return { present: false, value: undefined };
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* The initial value for a schema. `root` carries the `$defs` document for
|
|
25
|
+
* `$ref` resolution and defaults to the schema itself (the common
|
|
26
|
+
* whole-tool-schema call).
|
|
27
|
+
*/
|
|
28
|
+
export function defaultValueForSchema(schema, root = schema) {
|
|
29
|
+
const classified = classifySchema(schema, root);
|
|
30
|
+
const explicit = explicitDefault(schema, classified.schema);
|
|
31
|
+
if (explicit.present)
|
|
32
|
+
return explicit.value;
|
|
33
|
+
const { model } = classified;
|
|
34
|
+
switch (model.kind) {
|
|
35
|
+
case 'const':
|
|
36
|
+
return model.value;
|
|
37
|
+
case 'object': {
|
|
38
|
+
const result = {};
|
|
39
|
+
for (const [name, propSchema] of model.properties) {
|
|
40
|
+
if (model.required.has(name)) {
|
|
41
|
+
const seeded = defaultValueForSchema(propSchema, root);
|
|
42
|
+
if (seeded !== undefined)
|
|
43
|
+
result[name] = seeded;
|
|
44
|
+
continue;
|
|
45
|
+
}
|
|
46
|
+
const propClassified = classifySchema(propSchema, root);
|
|
47
|
+
const propDefault = explicitDefault(propSchema, propClassified.schema);
|
|
48
|
+
if (propDefault.present)
|
|
49
|
+
result[name] = propDefault.value;
|
|
50
|
+
}
|
|
51
|
+
return result;
|
|
52
|
+
}
|
|
53
|
+
case 'array':
|
|
54
|
+
return [];
|
|
55
|
+
case 'enum':
|
|
56
|
+
case 'string':
|
|
57
|
+
case 'number':
|
|
58
|
+
case 'boolean':
|
|
59
|
+
case 'union':
|
|
60
|
+
case 'unsupported':
|
|
61
|
+
return undefined;
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
//# sourceMappingURL=default-value.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"default-value.js","sourceRoot":"","sources":["../../src/schema-form/default-value.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AACH,OAAO,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAG5C,wFAAwF;AACxF,SAAS,eAAe,CACtB,GAAe,EACf,QAAoB;IAEpB,IAAI,SAAS,IAAI,GAAG;QAAE,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,KAAK,EAAE,GAAG,CAAC,OAAO,EAAE,CAAC;IACnE,IAAI,SAAS,IAAI,QAAQ;QAAE,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,KAAK,EAAE,QAAQ,CAAC,OAAO,EAAE,CAAC;IAC7E,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,SAAS,EAAE,CAAC;AAC9C,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,qBAAqB,CAAC,MAAkB,EAAE,OAAmB,MAAM;IACjF,MAAM,UAAU,GAAG,cAAc,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;IAChD,MAAM,QAAQ,GAAG,eAAe,CAAC,MAAM,EAAE,UAAU,CAAC,MAAM,CAAC,CAAC;IAC5D,IAAI,QAAQ,CAAC,OAAO;QAAE,OAAO,QAAQ,CAAC,KAAK,CAAC;IAE5C,MAAM,EAAE,KAAK,EAAE,GAAG,UAAU,CAAC;IAC7B,QAAQ,KAAK,CAAC,IAAI,EAAE,CAAC;QACnB,KAAK,OAAO;YACV,OAAO,KAAK,CAAC,KAAK,CAAC;QACrB,KAAK,QAAQ,CAAC,CAAC,CAAC;YACd,MAAM,MAAM,GAA4B,EAAE,CAAC;YAC3C,KAAK,MAAM,CAAC,IAAI,EAAE,UAAU,CAAC,IAAI,KAAK,CAAC,UAAU,EAAE,CAAC;gBAClD,IAAI,KAAK,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC;oBAC7B,MAAM,MAAM,GAAG,qBAAqB,CAAC,UAAU,EAAE,IAAI,CAAC,CAAC;oBACvD,IAAI,MAAM,KAAK,SAAS;wBAAE,MAAM,CAAC,IAAI,CAAC,GAAG,MAAM,CAAC;oBAChD,SAAS;gBACX,CAAC;gBACD,MAAM,cAAc,GAAG,cAAc,CAAC,UAAU,EAAE,IAAI,CAAC,CAAC;gBACxD,MAAM,WAAW,GAAG,eAAe,CAAC,UAAU,EAAE,cAAc,CAAC,MAAM,CAAC,CAAC;gBACvE,IAAI,WAAW,CAAC,OAAO;oBAAE,MAAM,CAAC,IAAI,CAAC,GAAG,WAAW,CAAC,KAAK,CAAC;YAC5D,CAAC;YACD,OAAO,MAAM,CAAC;QAChB,CAAC;QACD,KAAK,OAAO;YACV,OAAO,EAAE,CAAC;QACZ,KAAK,MAAM,CAAC;QACZ,KAAK,QAAQ,CAAC;QACd,KAAK,QAAQ,CAAC;QACd,KAAK,SAAS,CAAC;QACf,KAAK,OAAO,CAAC;QACb,KAAK,aAAa;YAChB,OAAO,SAAS,CAAC;IACrB,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The enum field renderer. A short enum (up to {@link RADIO_MAX_OPTIONS}
|
|
3
|
+
* options) renders as a radio group; a longer one renders as a select. Options
|
|
4
|
+
* are keyed by index so a non-string enum value round-trips through the string
|
|
5
|
+
* control.
|
|
6
|
+
*/
|
|
7
|
+
import type { ReactNode } from 'react';
|
|
8
|
+
import type { FieldModel } from './classify';
|
|
9
|
+
export declare function EnumField({ heading, description, error, model, value, onChange, }: {
|
|
10
|
+
heading: string;
|
|
11
|
+
description: string | undefined;
|
|
12
|
+
error: string | undefined;
|
|
13
|
+
model: Extract<FieldModel, {
|
|
14
|
+
kind: 'enum';
|
|
15
|
+
}>;
|
|
16
|
+
value: unknown;
|
|
17
|
+
onChange: (value: unknown) => void;
|
|
18
|
+
}): ReactNode;
|
|
19
|
+
//# sourceMappingURL=enum-field.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"enum-field.d.ts","sourceRoot":"","sources":["../../src/schema-form/enum-field.tsx"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAKvC,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAI7C,wBAAgB,SAAS,CAAC,EACxB,OAAO,EACP,WAAW,EACX,KAAK,EACL,KAAK,EACL,KAAK,EACL,QAAQ,GACT,EAAE;IACD,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,EAAE,MAAM,GAAG,SAAS,CAAC;IAChC,KAAK,EAAE,MAAM,GAAG,SAAS,CAAC;IAC1B,KAAK,EAAE,OAAO,CAAC,UAAU,EAAE;QAAE,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAC7C,KAAK,EAAE,OAAO,CAAC;IACf,QAAQ,EAAE,CAAC,KAAK,EAAE,OAAO,KAAK,IAAI,CAAC;CACpC,GAAG,SAAS,CAmCZ"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { Field } from '../components/field';
|
|
3
|
+
import { RadioGroup } from '../components/radio-group';
|
|
4
|
+
import { Select } from '../components/select';
|
|
5
|
+
const RADIO_MAX_OPTIONS = 3;
|
|
6
|
+
export function EnumField({ heading, description, error, model, value, onChange, }) {
|
|
7
|
+
const options = model.options.map((option, index) => ({
|
|
8
|
+
key: String(index),
|
|
9
|
+
label: option.label,
|
|
10
|
+
value: option.value,
|
|
11
|
+
}));
|
|
12
|
+
const selected = options.find((option) => option.value === value);
|
|
13
|
+
// Always a defined string so the control stays controlled from first render
|
|
14
|
+
// (an `undefined` → string transition warns about uncontrolled→controlled).
|
|
15
|
+
const selectedKey = selected?.key ?? '';
|
|
16
|
+
const emit = (key) => {
|
|
17
|
+
const match = options.find((option) => option.key === key);
|
|
18
|
+
if (match !== undefined)
|
|
19
|
+
onChange(match.value);
|
|
20
|
+
};
|
|
21
|
+
if (options.length <= RADIO_MAX_OPTIONS) {
|
|
22
|
+
return (_jsx(Field, { label: heading, description: description, error: error, group: true, children: _jsx(RadioGroup, { options: options.map((option) => ({ value: option.key, label: option.label })), value: selectedKey, onValueChange: emit }) }));
|
|
23
|
+
}
|
|
24
|
+
return (_jsx(Field, { label: heading, description: description, error: error, children: _jsx(Select, { options: options.map((option) => ({ value: option.key, label: option.label })), value: selectedKey, onValueChange: emit }) }));
|
|
25
|
+
}
|
|
26
|
+
//# sourceMappingURL=enum-field.js.map
|