@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,169 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `Field` — the label + description + error wrapper every form control sits in.
|
|
3
|
+
* It owns one generated id and publishes it (plus the description/error ids and
|
|
4
|
+
* the invalid flag) through a context; a nested control reads them via
|
|
5
|
+
* `useFieldControl` and spreads them, so the label's `htmlFor`, the control's
|
|
6
|
+
* `aria-describedby`, and its `aria-invalid` stay wired without the caller
|
|
7
|
+
* threading ids by hand.
|
|
8
|
+
*/
|
|
9
|
+
import { createContext, useContext, useId } from 'react';
|
|
10
|
+
import type { CSSProperties, ReactNode } from 'react';
|
|
11
|
+
|
|
12
|
+
import { XCircleIcon } from './icons';
|
|
13
|
+
|
|
14
|
+
interface FieldContextValue {
|
|
15
|
+
readonly controlId: string | undefined;
|
|
16
|
+
readonly describedBy: string | undefined;
|
|
17
|
+
readonly invalid: boolean;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
const FieldContext = createContext<FieldContextValue | null>(null);
|
|
21
|
+
|
|
22
|
+
/** The a11y wiring a form control spreads onto its element. */
|
|
23
|
+
export interface FieldControlProps {
|
|
24
|
+
readonly id: string | undefined;
|
|
25
|
+
readonly 'aria-describedby': string | undefined;
|
|
26
|
+
readonly 'aria-invalid': true | undefined;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Read the enclosing Field's wiring.
|
|
31
|
+
*
|
|
32
|
+
* `id` and `aria-describedby` are `undefined` both when there is no Field AND
|
|
33
|
+
* inside a group `Field`: a group has no single element to carry them, and the
|
|
34
|
+
* group container itself already carries the name and the description. Only
|
|
35
|
+
* `aria-invalid` still crosses that boundary, because `role="group"` does not
|
|
36
|
+
* support it (ARIA 1.2), so the control is the sole place an errored group can
|
|
37
|
+
* expose its invalid state.
|
|
38
|
+
*/
|
|
39
|
+
export function useFieldControl(): FieldControlProps {
|
|
40
|
+
const ctx = useContext(FieldContext);
|
|
41
|
+
if (ctx === null) {
|
|
42
|
+
return { id: undefined, 'aria-describedby': undefined, 'aria-invalid': undefined };
|
|
43
|
+
}
|
|
44
|
+
return {
|
|
45
|
+
id: ctx.controlId,
|
|
46
|
+
'aria-describedby': ctx.describedBy,
|
|
47
|
+
'aria-invalid': ctx.invalid ? true : undefined,
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
export interface FieldProps {
|
|
52
|
+
readonly label: string;
|
|
53
|
+
readonly description?: string;
|
|
54
|
+
readonly error?: string;
|
|
55
|
+
readonly children: ReactNode;
|
|
56
|
+
readonly style?: CSSProperties;
|
|
57
|
+
/** APPENDED to `tai-field` rather than replacing it, so the field keeps its paint. */
|
|
58
|
+
readonly className?: string;
|
|
59
|
+
/**
|
|
60
|
+
* Set when the wrapped control is a GROUP rather than one labelable element —
|
|
61
|
+
* a `RadioGroup`, a set of checkboxes, any `role="radiogroup"`/`role="group"`
|
|
62
|
+
* panel.
|
|
63
|
+
*
|
|
64
|
+
* `<label for>` can only name a labelable element: pointed at a group it
|
|
65
|
+
* either dangles at an id no element carries or names an element the browser
|
|
66
|
+
* refuses to label, and it is inert either way. So a group Field wraps
|
|
67
|
+
* `children` in the group CONTAINER itself — a `<div role="group">` carrying
|
|
68
|
+
* `aria-labelledby` at the label and `aria-describedby` at the description and
|
|
69
|
+
* error — and the label becomes a `<span>`, because a `<label>` associated
|
|
70
|
+
* with nothing is a semantics lie.
|
|
71
|
+
*
|
|
72
|
+
* IT ALSO CHANGES WHAT A CHILD READS FROM {@link useFieldControl}. The
|
|
73
|
+
* container is what carries the name and the description, so the group Field
|
|
74
|
+
* publishes NEITHER `id` NOR `aria-describedby` — both are `undefined`, and a
|
|
75
|
+
* control that spread them would take the group's own name and description for
|
|
76
|
+
* itself. `aria-invalid` still crosses: `role="group"` does not support it
|
|
77
|
+
* (ARIA 1.2), so the control is the only place an errored group can expose its
|
|
78
|
+
* invalid state.
|
|
79
|
+
*
|
|
80
|
+
* Naming therefore happens BY CONSTRUCTION rather than by the call site
|
|
81
|
+
* remembering to read a hook. The cost is one extra container announcement
|
|
82
|
+
* where the child has a group role of its own; that is accepted deliberately,
|
|
83
|
+
* because the two failure directions are asymmetric — a redundant container is
|
|
84
|
+
* audible, an unnamed group is silent.
|
|
85
|
+
*
|
|
86
|
+
* A group child left UNMARKED is a build failure, not a runtime surprise:
|
|
87
|
+
* `components/field-group.test.ts` ("Field group contract" → "marks every
|
|
88
|
+
* Field whose child does not claim its control id") scans every Field call
|
|
89
|
+
* site in the repository, and a child outside its list of control-id-claiming
|
|
90
|
+
* components — `RadioGroup` among them — reddens until the site passes
|
|
91
|
+
* `group`.
|
|
92
|
+
*/
|
|
93
|
+
readonly group?: boolean;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
export function Field({
|
|
97
|
+
label,
|
|
98
|
+
description,
|
|
99
|
+
error,
|
|
100
|
+
children,
|
|
101
|
+
style,
|
|
102
|
+
className,
|
|
103
|
+
group = false,
|
|
104
|
+
}: FieldProps) {
|
|
105
|
+
const controlId = useId();
|
|
106
|
+
const labelId = `${controlId}-label`;
|
|
107
|
+
const descriptionId = `${controlId}-desc`;
|
|
108
|
+
const errorId = `${controlId}-err`;
|
|
109
|
+
|
|
110
|
+
const describedByIds: string[] = [];
|
|
111
|
+
if (description !== undefined) describedByIds.push(descriptionId);
|
|
112
|
+
if (error !== undefined) describedByIds.push(errorId);
|
|
113
|
+
const describedBy = describedByIds.length > 0 ? describedByIds.join(' ') : undefined;
|
|
114
|
+
|
|
115
|
+
// A group withholds the ID and the DESCRIPTION — there is no single element to
|
|
116
|
+
// carry them, and a control that spread them inside a group would take the
|
|
117
|
+
// group's own name and description for itself — but it still publishes
|
|
118
|
+
// `invalid`. `aria-invalid` is not supported on `role="group"` (ARIA 1.2), so
|
|
119
|
+
// if the group Field withheld it too, a group Field carrying an `error` would
|
|
120
|
+
// expose its invalid state NOWHERE in the accessibility tree.
|
|
121
|
+
const value: FieldContextValue = group
|
|
122
|
+
? { controlId: undefined, describedBy: undefined, invalid: error !== undefined }
|
|
123
|
+
: { controlId, describedBy, invalid: error !== undefined };
|
|
124
|
+
|
|
125
|
+
return (
|
|
126
|
+
<FieldContext.Provider value={value}>
|
|
127
|
+
<div
|
|
128
|
+
className={className === undefined ? 'tai-field' : `tai-field ${className}`}
|
|
129
|
+
style={style}
|
|
130
|
+
>
|
|
131
|
+
{group ? (
|
|
132
|
+
<span id={labelId} className="tai-field-label">
|
|
133
|
+
{label}
|
|
134
|
+
</span>
|
|
135
|
+
) : (
|
|
136
|
+
<label id={labelId} htmlFor={controlId} className="tai-field-label">
|
|
137
|
+
{label}
|
|
138
|
+
</label>
|
|
139
|
+
)}
|
|
140
|
+
{group ? (
|
|
141
|
+
<div
|
|
142
|
+
role="group"
|
|
143
|
+
aria-labelledby={labelId}
|
|
144
|
+
aria-describedby={describedBy}
|
|
145
|
+
className="tai-field-group"
|
|
146
|
+
>
|
|
147
|
+
{children}
|
|
148
|
+
</div>
|
|
149
|
+
) : (
|
|
150
|
+
children
|
|
151
|
+
)}
|
|
152
|
+
{description !== undefined ? (
|
|
153
|
+
<p id={descriptionId} className="tai-field-hint" style={{ margin: 0 }}>
|
|
154
|
+
{description}
|
|
155
|
+
</p>
|
|
156
|
+
) : null}
|
|
157
|
+
{/* The icon carries the invalid state alongside the color, never the color
|
|
158
|
+
alone — and it is the ERROR mark: a rejected value is a definite
|
|
159
|
+
negative, not the warning the triangle states. */}
|
|
160
|
+
{error !== undefined ? (
|
|
161
|
+
<p id={errorId} role="alert" className="tai-field-error" style={{ margin: 0 }}>
|
|
162
|
+
<XCircleIcon />
|
|
163
|
+
{error}
|
|
164
|
+
</p>
|
|
165
|
+
) : null}
|
|
166
|
+
</div>
|
|
167
|
+
</FieldContext.Provider>
|
|
168
|
+
);
|
|
169
|
+
}
|
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `FleetReport` — the shared, loud rendering of a config mutation's fleet broadcast.
|
|
3
|
+
* Every mutation surface (connector, backup, mcp-config, env, extensions, single-MCP
|
|
4
|
+
* reload, fleet reload) computes a `FleetReportSummary` from its response through the
|
|
5
|
+
* api-client's shared handler and hands it here, so a FAILED propagation is never
|
|
6
|
+
* invisible.
|
|
7
|
+
*
|
|
8
|
+
* The `action` prop tunes the copy to the caller's framing: `'save'` (the default,
|
|
9
|
+
* used by every config-mutation surface) reports a saved change that did not fully
|
|
10
|
+
* propagate and points the operator at the System page to reload; `'reload'` (the
|
|
11
|
+
* System page's own fleet-reload action) drops the "Change saved" framing — nothing
|
|
12
|
+
* was saved, a reload was dispatched — and the self-referential System-page pointer.
|
|
13
|
+
*
|
|
14
|
+
* A `converged` summary (every origin applied, or a lone-worker local-only change)
|
|
15
|
+
* renders NOTHING — the calling surface shows its own success. A `degraded` summary
|
|
16
|
+
* (the bus was reached but a sibling did not confirm) or an `unreachable` summary (the
|
|
17
|
+
* bus itself failed) renders a loud `role="alert"` panel naming the honest per-origin
|
|
18
|
+
* outcomes: `failed` / `missing` / `departed` / `timed_out`, or the bus error. It
|
|
19
|
+
* never fakes success on a stranded origin. Every server-supplied string (an origin
|
|
20
|
+
* name, an error/detail message) renders as escaped React text, never an HTML sink.
|
|
21
|
+
*
|
|
22
|
+
* Every state — the headline and each origin's outcome — is a `tai-status` line: an
|
|
23
|
+
* icon MARK plus a word LABEL, with the tone color only reinforcing them, so the
|
|
24
|
+
* report is readable without color perception.
|
|
25
|
+
*/
|
|
26
|
+
import type { ReactNode } from 'react';
|
|
27
|
+
import type { FleetReportSummary, FleetFailureOutcome } from '@tai42/api-client';
|
|
28
|
+
|
|
29
|
+
import { AlertTriangleIcon, PendingIcon, XCircleIcon, type IconComponent } from './icons';
|
|
30
|
+
|
|
31
|
+
/** Human labels for the per-origin non-applied outcomes. */
|
|
32
|
+
const OUTCOME_LABEL: Record<FleetFailureOutcome, string> = {
|
|
33
|
+
failed: 'apply failed',
|
|
34
|
+
missing: 'alive but did not acknowledge in time',
|
|
35
|
+
departed: 'left mid-broadcast',
|
|
36
|
+
timed_out: 'acknowledged but did not finish applying',
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
interface StatusTone {
|
|
40
|
+
/** The `tai-status-*` modifier carrying the tone. */
|
|
41
|
+
readonly tone: string;
|
|
42
|
+
/** The mark that states the outcome without relying on that tone. */
|
|
43
|
+
readonly Icon: IconComponent;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* How each outcome reads as a status. `failed` is a definite negative — the apply
|
|
48
|
+
* raised. `departed` is a warning — the worker is gone, so nothing will converge it.
|
|
49
|
+
* `missing` and `timed_out` are both UNRESOLVED (never acknowledged / acknowledged
|
|
50
|
+
* but never finished), so they read as pending rather than as an outright failure.
|
|
51
|
+
*/
|
|
52
|
+
const OUTCOME_STATUS: Record<FleetFailureOutcome, StatusTone> = {
|
|
53
|
+
failed: { tone: 'tai-status-err', Icon: XCircleIcon },
|
|
54
|
+
missing: { tone: 'tai-status-pending', Icon: PendingIcon },
|
|
55
|
+
departed: { tone: 'tai-status-warn', Icon: AlertTriangleIcon },
|
|
56
|
+
timed_out: { tone: 'tai-status-pending', Icon: PendingIcon },
|
|
57
|
+
};
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* Render a fleet broadcast's failure state. Returns `null` for a converged/absent
|
|
61
|
+
* report (nothing to warn about) so callers can always mount it unconditionally
|
|
62
|
+
* beside their own success line.
|
|
63
|
+
*/
|
|
64
|
+
export interface FleetReportProps {
|
|
65
|
+
readonly summary: FleetReportSummary | null;
|
|
66
|
+
/** Whose framing the copy takes: a saved config change, or a dispatched reload. */
|
|
67
|
+
readonly action?: 'save' | 'reload';
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
export function FleetReport({ summary, action = 'save' }: FleetReportProps): ReactNode {
|
|
71
|
+
if (summary === null || summary.status === 'converged') return null;
|
|
72
|
+
|
|
73
|
+
if (summary.status === 'unreachable') {
|
|
74
|
+
return (
|
|
75
|
+
<div role="alert" className="tai-error-state tai-stack tai-stack-2">
|
|
76
|
+
<strong className="tai-status tai-status-err">
|
|
77
|
+
<XCircleIcon />
|
|
78
|
+
{action === 'reload'
|
|
79
|
+
? 'The worker fleet was not reached'
|
|
80
|
+
: 'Change saved, but the worker fleet was not reached'}
|
|
81
|
+
</strong>
|
|
82
|
+
<p>
|
|
83
|
+
{action === 'reload'
|
|
84
|
+
? 'The worker bus was unreachable, so other workers may still be running the old config. Re-run the reload once the bus is back.'
|
|
85
|
+
: 'The worker bus was unreachable, so other workers may still be running the old config. Re-run the reload from the System page once the bus is back.'}
|
|
86
|
+
</p>
|
|
87
|
+
{/* The bus error is a message, not a listing: it wraps rather than scrolls. */}
|
|
88
|
+
{summary.error !== null ? (
|
|
89
|
+
<p className="tai-code-block tai-code-block-wrap">{summary.error}</p>
|
|
90
|
+
) : null}
|
|
91
|
+
</div>
|
|
92
|
+
);
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
// degraded — the bus was reached but named origins did not converge. That is a
|
|
96
|
+
// warning, not a failure, so it takes the warning surface: a warn-toned
|
|
97
|
+
// headline inside an error-toned panel would state two different severities.
|
|
98
|
+
//
|
|
99
|
+
// A count and its noun agree. `worker(s)` is machine output at the one moment
|
|
100
|
+
// an operator is being told something went wrong, and a single unconverged
|
|
101
|
+
// worker is the commonest degraded fleet there is.
|
|
102
|
+
const count = summary.failures.length;
|
|
103
|
+
const workers = `${String(count)} worker${count === 1 ? '' : 's'}`;
|
|
104
|
+
return (
|
|
105
|
+
<div role="alert" className="tai-warn-state tai-stack tai-stack-2">
|
|
106
|
+
<strong className="tai-status tai-status-warn">
|
|
107
|
+
<AlertTriangleIcon />
|
|
108
|
+
{action === 'reload'
|
|
109
|
+
? `${workers} did not converge`
|
|
110
|
+
: `Change saved, but ${workers} did not converge`}
|
|
111
|
+
</strong>
|
|
112
|
+
<p>
|
|
113
|
+
{`${count === 1 ? 'This worker' : 'These workers'} may still be running the old config — ` +
|
|
114
|
+
(action === 'reload' ? 're-run the reload' : 'reload the fleet from the System page') +
|
|
115
|
+
` to converge ${count === 1 ? 'it' : 'them'}.`}
|
|
116
|
+
</p>
|
|
117
|
+
<ul className="tai-stack tai-stack-2">
|
|
118
|
+
{summary.failures.map((failure) => {
|
|
119
|
+
const { tone, Icon } = OUTCOME_STATUS[failure.outcome];
|
|
120
|
+
return (
|
|
121
|
+
<li key={failure.origin} className="tai-row">
|
|
122
|
+
<span className="tai-mono">{failure.origin}</span>
|
|
123
|
+
<span className={`tai-status ${tone}`}>
|
|
124
|
+
<Icon />
|
|
125
|
+
{OUTCOME_LABEL[failure.outcome]}
|
|
126
|
+
</span>
|
|
127
|
+
{failure.message !== null ? (
|
|
128
|
+
<span className="tai-muted">{failure.message}</span>
|
|
129
|
+
) : null}
|
|
130
|
+
</li>
|
|
131
|
+
);
|
|
132
|
+
})}
|
|
133
|
+
</ul>
|
|
134
|
+
</div>
|
|
135
|
+
);
|
|
136
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* The two webfonts the design system is drawn in, self-hosted so no request ever
|
|
3
|
+
* leaves the deployment (`font-src 'self'`): Inter Variable for the interface and
|
|
4
|
+
* Geist Mono Variable for the machine voice — identifiers, timestamps, code, and
|
|
5
|
+
* the uppercase label style.
|
|
6
|
+
*
|
|
7
|
+
* This is a separate stylesheet so a HOST app loads the faces exactly once. A
|
|
8
|
+
* plugin never imports it; it inherits the families through `--tai-font-sans` and
|
|
9
|
+
* `--tai-font-mono`.
|
|
10
|
+
*
|
|
11
|
+
* BUNDLER-RESOLVED ENTRY POINT. The two lines below are BARE PACKAGE specifiers,
|
|
12
|
+
* not URLs: only a bundler (or anything else applying Node resolution to CSS)
|
|
13
|
+
* turns them into the `@font-face` blocks and the hashed `.woff2` assets. Linked
|
|
14
|
+
* straight into a page — `<link href=".../@tai42/studio-sdk/dist/components/
|
|
15
|
+
* fonts.css">` — a browser resolves them against the stylesheet's own URL, both
|
|
16
|
+
* requests 404, and the page silently falls back to the platform font with
|
|
17
|
+
* nothing failing anywhere. So `@tai42/studio-sdk/fonts.css` is for a build that
|
|
18
|
+
* resolves package specifiers; `tokens.css` and `components.css`, which carry no
|
|
19
|
+
* `@import` at all, are the two subpaths a page may link directly.
|
|
20
|
+
*/
|
|
21
|
+
@import '@fontsource-variable/inter';
|
|
22
|
+
@import '@fontsource-variable/geist-mono';
|