@xemahq/ui-kernel 0.9.0 → 0.9.2
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/README.md +2 -2
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/lib/biome-host/biome-builders.d.ts.map +1 -1
- package/dist/lib/biome-host/biome-builders.js +3 -1
- package/dist/lib/biome-host/biome-builders.js.map +1 -1
- package/dist/lib/biome-host/biome-registry.d.ts.map +1 -1
- package/dist/lib/biome-host/biome-registry.js +14 -9
- package/dist/lib/biome-host/biome-registry.js.map +1 -1
- package/dist/lib/biome-host/biome-scope-hooks.d.ts +11 -0
- package/dist/lib/biome-host/biome-scope-hooks.d.ts.map +1 -0
- package/dist/lib/biome-host/biome-scope-hooks.js +25 -0
- package/dist/lib/biome-host/biome-scope-hooks.js.map +1 -0
- package/dist/lib/biome-host/biome-scope.d.ts +1 -10
- package/dist/lib/biome-host/biome-scope.d.ts.map +1 -1
- package/dist/lib/biome-host/biome-scope.js +1 -24
- package/dist/lib/biome-host/biome-scope.js.map +1 -1
- package/dist/lib/biome-host/biome-scoped-query.d.ts +1 -1
- package/dist/lib/biome-host/biome-scoped-query.d.ts.map +1 -1
- package/dist/lib/biome-host/biome-scoped-query.js +1 -1
- package/dist/lib/biome-host/biome-scoped-query.js.map +1 -1
- package/dist/lib/biome-host/create-biome-orval-config.js +2 -2
- package/dist/lib/biome-host/create-biome-orval-config.js.map +1 -1
- package/dist/lib/biome-host/errors.js.map +1 -1
- package/dist/lib/biome-host/index.d.ts +1 -1
- package/dist/lib/biome-host/index.d.ts.map +1 -1
- package/dist/lib/biome-host/index.js +1 -1
- package/dist/lib/biome-host/index.js.map +1 -1
- package/dist/lib/biome-host/session-profiles.d.ts.map +1 -1
- package/dist/lib/biome-host/session-profiles.js +4 -1
- package/dist/lib/biome-host/session-profiles.js.map +1 -1
- package/dist/lib/capabilities/capability-context.d.ts +9 -0
- package/dist/lib/capabilities/capability-context.d.ts.map +1 -0
- package/dist/lib/capabilities/capability-context.js +13 -0
- package/dist/lib/capabilities/capability-context.js.map +1 -0
- package/dist/lib/capabilities/capability-provider.d.ts +2 -8
- package/dist/lib/capabilities/capability-provider.d.ts.map +1 -1
- package/dist/lib/capabilities/capability-provider.js +1 -12
- package/dist/lib/capabilities/capability-provider.js.map +1 -1
- package/dist/lib/capabilities/index.d.ts +1 -0
- package/dist/lib/capabilities/index.d.ts.map +1 -1
- package/dist/lib/capabilities/index.js +1 -0
- package/dist/lib/capabilities/index.js.map +1 -1
- package/dist/lib/capabilities/use-capability.d.ts.map +1 -1
- package/dist/lib/capabilities/use-capability.js +1 -1
- package/dist/lib/capabilities/use-capability.js.map +1 -1
- package/dist/lib/contribution-registry/contribution-registry.d.ts +24 -0
- package/dist/lib/contribution-registry/contribution-registry.d.ts.map +1 -0
- package/dist/lib/contribution-registry/contribution-registry.js +67 -0
- package/dist/lib/contribution-registry/contribution-registry.js.map +1 -0
- package/dist/lib/contribution-registry/index.d.ts +3 -0
- package/dist/lib/contribution-registry/index.d.ts.map +1 -0
- package/dist/lib/contribution-registry/index.js +3 -0
- package/dist/lib/contribution-registry/index.js.map +1 -0
- package/dist/lib/contribution-registry/renderable-registry.d.ts +33 -0
- package/dist/lib/contribution-registry/renderable-registry.d.ts.map +1 -0
- package/dist/lib/contribution-registry/renderable-registry.js +51 -0
- package/dist/lib/contribution-registry/renderable-registry.js.map +1 -0
- package/dist/lib/system-bus/deeplink.js.map +1 -1
- package/dist/lib/system-bus/host-ports.d.ts +2 -1
- package/dist/lib/system-bus/host-ports.d.ts.map +1 -1
- package/dist/lib/system-bus/intent-registry.d.ts.map +1 -1
- package/dist/lib/system-bus/intent-registry.js.map +1 -1
- package/dist/offline/index.d.ts +2 -1
- package/dist/offline/index.d.ts.map +1 -1
- package/dist/offline/index.js +2 -1
- package/dist/offline/index.js.map +1 -1
- package/dist/offline/offline-status-badge.js +1 -1
- package/dist/offline/offline-status-badge.js.map +1 -1
- package/dist/offline/outbox.js.map +1 -1
- package/dist/offline/react-hooks.d.ts +7 -0
- package/dist/offline/react-hooks.d.ts.map +1 -0
- package/dist/offline/react-hooks.js +25 -0
- package/dist/offline/react-hooks.js.map +1 -0
- package/dist/offline/react.d.ts +0 -4
- package/dist/offline/react.d.ts.map +1 -1
- package/dist/offline/react.js +2 -24
- package/dist/offline/react.js.map +1 -1
- package/dist/offline/storage.d.ts.map +1 -1
- package/dist/offline/storage.js +8 -5
- package/dist/offline/storage.js.map +1 -1
- package/dist/registry/index.d.ts +1 -0
- package/dist/registry/index.d.ts.map +1 -1
- package/dist/registry/index.js +1 -0
- package/dist/registry/index.js.map +1 -1
- package/dist/registry/lib/primitives/SessionEventCard.d.ts.map +1 -1
- package/dist/registry/lib/primitives/SessionEventCard.js +1 -1
- package/dist/registry/lib/primitives/SessionEventCard.js.map +1 -1
- package/dist/registry/lib/session-context-provider.d.ts +1 -3
- package/dist/registry/lib/session-context-provider.d.ts.map +1 -1
- package/dist/registry/lib/session-context-provider.js +2 -15
- package/dist/registry/lib/session-context-provider.js.map +1 -1
- package/dist/registry/lib/session-context.d.ts +5 -0
- package/dist/registry/lib/session-context.d.ts.map +1 -0
- package/dist/registry/lib/session-context.js +15 -0
- package/dist/registry/lib/session-context.js.map +1 -0
- package/dist/registry/lib/session-selectors.d.ts.map +1 -1
- package/dist/registry/lib/session-selectors.js +3 -1
- package/dist/registry/lib/session-selectors.js.map +1 -1
- package/dist/ui/branding/app-branding-context.d.ts +9 -0
- package/dist/ui/branding/app-branding-context.d.ts.map +1 -0
- package/dist/ui/branding/app-branding-context.js +10 -0
- package/dist/ui/branding/app-branding-context.js.map +1 -0
- package/dist/ui/branding/app-branding-provider.d.ts +0 -6
- package/dist/ui/branding/app-branding-provider.d.ts.map +1 -1
- package/dist/ui/branding/app-branding-provider.js +1 -8
- package/dist/ui/branding/app-branding-provider.js.map +1 -1
- package/dist/ui/capture/field-spec-to-zod.d.ts +1 -0
- package/dist/ui/capture/field-spec-to-zod.d.ts.map +1 -1
- package/dist/ui/capture/field-spec-to-zod.js +19 -0
- package/dist/ui/capture/field-spec-to-zod.js.map +1 -1
- package/dist/ui/capture/field-spec-validate.d.ts +4 -0
- package/dist/ui/capture/field-spec-validate.d.ts.map +1 -0
- package/dist/ui/capture/field-spec-validate.js +129 -0
- package/dist/ui/capture/field-spec-validate.js.map +1 -0
- package/dist/ui/capture/field-spec.d.ts +13 -1
- package/dist/ui/capture/field-spec.d.ts.map +1 -1
- package/dist/ui/capture/field-spec.js +25 -0
- package/dist/ui/capture/field-spec.js.map +1 -1
- package/dist/ui/capture/index.d.ts +4 -2
- package/dist/ui/capture/index.d.ts.map +1 -1
- package/dist/ui/capture/index.js +4 -2
- package/dist/ui/capture/index.js.map +1 -1
- package/dist/ui/capture/schema-field-input.d.ts.map +1 -1
- package/dist/ui/capture/schema-field-input.js +40 -13
- package/dist/ui/capture/schema-field-input.js.map +1 -1
- package/dist/ui/capture/submit-values.d.ts +6 -0
- package/dist/ui/capture/submit-values.d.ts.map +1 -0
- package/dist/ui/capture/submit-values.js +28 -0
- package/dist/ui/capture/submit-values.js.map +1 -0
- package/dist/ui/capture/use-prefill.d.ts.map +1 -1
- package/dist/ui/capture/use-prefill.js +3 -1
- package/dist/ui/capture/use-prefill.js.map +1 -1
- package/dist/ui/capture/use-wizard.d.ts +1 -1
- package/dist/ui/capture/use-wizard.d.ts.map +1 -1
- package/dist/ui/capture/use-wizard.js +1 -1
- package/dist/ui/capture/use-wizard.js.map +1 -1
- package/dist/ui/capture/wizard.d.ts.map +1 -1
- package/dist/ui/capture/wizard.js.map +1 -1
- package/dist/ui/index.d.ts +6 -1
- package/dist/ui/index.d.ts.map +1 -1
- package/dist/ui/index.js +6 -1
- package/dist/ui/index.js.map +1 -1
- package/dist/ui/primitives/alert-dialog.js +1 -1
- package/dist/ui/primitives/alert-dialog.js.map +1 -1
- package/dist/ui/primitives/badge-variants.d.ts +4 -0
- package/dist/ui/primitives/badge-variants.d.ts.map +1 -0
- package/dist/ui/primitives/badge-variants.js +15 -0
- package/dist/ui/primitives/badge-variants.js.map +1 -0
- package/dist/ui/primitives/badge.d.ts +3 -5
- package/dist/ui/primitives/badge.d.ts.map +1 -1
- package/dist/ui/primitives/badge.js +2 -15
- package/dist/ui/primitives/badge.js.map +1 -1
- package/dist/ui/primitives/button-variants.d.ts +5 -0
- package/dist/ui/primitives/button-variants.d.ts.map +1 -0
- package/dist/ui/primitives/button-variants.js +24 -0
- package/dist/ui/primitives/button-variants.js.map +1 -0
- package/dist/ui/primitives/button.d.ts +3 -6
- package/dist/ui/primitives/button.d.ts.map +1 -1
- package/dist/ui/primitives/button.js +2 -24
- package/dist/ui/primitives/button.js.map +1 -1
- package/dist/ui/primitives/form-stepper.d.ts +1 -13
- package/dist/ui/primitives/form-stepper.d.ts.map +1 -1
- package/dist/ui/primitives/form-stepper.js +1 -6
- package/dist/ui/primitives/form-stepper.js.map +1 -1
- package/dist/ui/primitives/form-stepper.types.d.ts +14 -0
- package/dist/ui/primitives/form-stepper.types.d.ts.map +1 -0
- package/dist/ui/primitives/form-stepper.types.js +7 -0
- package/dist/ui/primitives/form-stepper.types.js.map +1 -0
- package/dist/ui/primitives/overflow-tabs.d.ts +5 -0
- package/dist/ui/primitives/overflow-tabs.d.ts.map +1 -1
- package/dist/ui/primitives/overflow-tabs.js +4 -4
- package/dist/ui/primitives/overflow-tabs.js.map +1 -1
- package/dist/ui/primitives/preview-device-frame.js +1 -1
- package/dist/ui/primitives/preview-device-frame.js.map +1 -1
- package/dist/ui/primitives/tag-multi-select.d.ts.map +1 -1
- package/dist/ui/primitives/tag-multi-select.js +1 -1
- package/dist/ui/primitives/tag-multi-select.js.map +1 -1
- package/dist/ui/primitives/url-preview-chrome.d.ts +8 -0
- package/dist/ui/primitives/url-preview-chrome.d.ts.map +1 -0
- package/dist/ui/primitives/url-preview-chrome.js +40 -0
- package/dist/ui/primitives/url-preview-chrome.js.map +1 -0
- package/dist/vista/GenericCatalogueSurface.d.ts +10 -0
- package/dist/vista/GenericCatalogueSurface.d.ts.map +1 -0
- package/dist/vista/GenericCatalogueSurface.js +80 -0
- package/dist/vista/GenericCatalogueSurface.js.map +1 -0
- package/dist/vista/SurfaceFallbackCard.d.ts +9 -0
- package/dist/vista/SurfaceFallbackCard.d.ts.map +1 -0
- package/dist/vista/SurfaceFallbackCard.js +44 -0
- package/dist/vista/SurfaceFallbackCard.js.map +1 -0
- package/dist/vista/VistaPanel.d.ts +21 -0
- package/dist/vista/VistaPanel.d.ts.map +1 -0
- package/dist/vista/VistaPanel.js +31 -0
- package/dist/vista/VistaPanel.js.map +1 -0
- package/dist/vista/html/CustomUiFrame.d.ts +20 -0
- package/dist/vista/html/CustomUiFrame.d.ts.map +1 -0
- package/dist/vista/html/CustomUiFrame.js +69 -0
- package/dist/vista/html/CustomUiFrame.js.map +1 -0
- package/dist/vista/html/custom-ui-frame-bridge.d.ts +13 -0
- package/dist/vista/html/custom-ui-frame-bridge.d.ts.map +1 -0
- package/dist/vista/html/custom-ui-frame-bridge.js +30 -0
- package/dist/vista/html/custom-ui-frame-bridge.js.map +1 -0
- package/dist/vista/html/custom-ui-frame-contract.d.ts +29 -0
- package/dist/vista/html/custom-ui-frame-contract.d.ts.map +1 -0
- package/dist/vista/html/custom-ui-frame-contract.js +16 -0
- package/dist/vista/html/custom-ui-frame-contract.js.map +1 -0
- package/dist/vista/html/custom-ui-intents.d.ts +20 -0
- package/dist/vista/html/custom-ui-intents.d.ts.map +1 -0
- package/dist/vista/html/custom-ui-intents.js +57 -0
- package/dist/vista/html/custom-ui-intents.js.map +1 -0
- package/dist/vista/html/custom-ui-srcdoc.d.ts +17 -0
- package/dist/vista/html/custom-ui-srcdoc.d.ts.map +1 -0
- package/dist/vista/html/custom-ui-srcdoc.js +70 -0
- package/dist/vista/html/custom-ui-srcdoc.js.map +1 -0
- package/dist/vista/html/index.d.ts +6 -0
- package/dist/vista/html/index.d.ts.map +1 -0
- package/dist/vista/html/index.js +6 -0
- package/dist/vista/html/index.js.map +1 -0
- package/dist/vista/index.d.ts +22 -0
- package/dist/vista/index.d.ts.map +1 -0
- package/dist/vista/index.js +22 -0
- package/dist/vista/index.js.map +1 -0
- package/dist/vista/surface-catalogue.d.ts +5 -0
- package/dist/vista/surface-catalogue.d.ts.map +1 -0
- package/dist/vista/surface-catalogue.js +30 -0
- package/dist/vista/surface-catalogue.js.map +1 -0
- package/dist/vista/surface-icons.d.ts +7 -0
- package/dist/vista/surface-icons.d.ts.map +1 -0
- package/dist/vista/surface-icons.js +26 -0
- package/dist/vista/surface-icons.js.map +1 -0
- package/dist/vista/surface-registry.d.ts +7 -0
- package/dist/vista/surface-registry.d.ts.map +1 -0
- package/dist/vista/surface-registry.js +7 -0
- package/dist/vista/surface-registry.js.map +1 -0
- package/dist/vista/surfaces/ChartSurface.d.ts +4 -0
- package/dist/vista/surfaces/ChartSurface.d.ts.map +1 -0
- package/dist/vista/surfaces/ChartSurface.js +17 -0
- package/dist/vista/surfaces/ChartSurface.js.map +1 -0
- package/dist/vista/surfaces/FilesSurface.d.ts +4 -0
- package/dist/vista/surfaces/FilesSurface.d.ts.map +1 -0
- package/dist/vista/surfaces/FilesSurface.js +77 -0
- package/dist/vista/surfaces/FilesSurface.js.map +1 -0
- package/dist/vista/surfaces/FormSurface.d.ts +4 -0
- package/dist/vista/surfaces/FormSurface.d.ts.map +1 -0
- package/dist/vista/surfaces/FormSurface.js +124 -0
- package/dist/vista/surfaces/FormSurface.js.map +1 -0
- package/dist/vista/surfaces/HtmlSurface.d.ts +4 -0
- package/dist/vista/surfaces/HtmlSurface.d.ts.map +1 -0
- package/dist/vista/surfaces/HtmlSurface.js +11 -0
- package/dist/vista/surfaces/HtmlSurface.js.map +1 -0
- package/dist/vista/surfaces/TableSurface.d.ts +4 -0
- package/dist/vista/surfaces/TableSurface.d.ts.map +1 -0
- package/dist/vista/surfaces/TableSurface.js +42 -0
- package/dist/vista/surfaces/TableSurface.js.map +1 -0
- package/dist/vista/surfaces/UrlSurface.d.ts +4 -0
- package/dist/vista/surfaces/UrlSurface.d.ts.map +1 -0
- package/dist/vista/surfaces/UrlSurface.js +7 -0
- package/dist/vista/surfaces/UrlSurface.js.map +1 -0
- package/dist/vista/surfaces/blob-surfaces.d.ts +6 -0
- package/dist/vista/surfaces/blob-surfaces.d.ts.map +1 -0
- package/dist/vista/surfaces/blob-surfaces.js +38 -0
- package/dist/vista/surfaces/blob-surfaces.js.map +1 -0
- package/dist/vista/surfaces/elicitation-transport.d.ts +27 -0
- package/dist/vista/surfaces/elicitation-transport.d.ts.map +1 -0
- package/dist/vista/surfaces/elicitation-transport.js +193 -0
- package/dist/vista/surfaces/elicitation-transport.js.map +1 -0
- package/dist/vista/surfaces/file-surface-utils.d.ts +13 -0
- package/dist/vista/surfaces/file-surface-utils.d.ts.map +1 -0
- package/dist/vista/surfaces/file-surface-utils.js +46 -0
- package/dist/vista/surfaces/file-surface-utils.js.map +1 -0
- package/dist/vista/surfaces/index.d.ts +12 -0
- package/dist/vista/surfaces/index.d.ts.map +1 -0
- package/dist/vista/surfaces/index.js +12 -0
- package/dist/vista/surfaces/index.js.map +1 -0
- package/dist/vista/surfaces/register-surfaces.d.ts +2 -0
- package/dist/vista/surfaces/register-surfaces.d.ts.map +1 -0
- package/dist/vista/surfaces/register-surfaces.js +80 -0
- package/dist/vista/surfaces/register-surfaces.js.map +1 -0
- package/dist/vista/surfaces/text-surfaces.d.ts +8 -0
- package/dist/vista/surfaces/text-surfaces.d.ts.map +1 -0
- package/dist/vista/surfaces/text-surfaces.js +54 -0
- package/dist/vista/surfaces/text-surfaces.js.map +1 -0
- package/dist/vista/use-vista-tabs.d.ts +30 -0
- package/dist/vista/use-vista-tabs.d.ts.map +1 -0
- package/dist/vista/use-vista-tabs.js +77 -0
- package/dist/vista/use-vista-tabs.js.map +1 -0
- package/dist/vista/vista-code-renderer-context.d.ts +9 -0
- package/dist/vista/vista-code-renderer-context.d.ts.map +1 -0
- package/dist/vista/vista-code-renderer-context.js +6 -0
- package/dist/vista/vista-code-renderer-context.js.map +1 -0
- package/dist/vista/vista-code-renderer.d.ts +7 -0
- package/dist/vista/vista-code-renderer.d.ts.map +1 -0
- package/dist/vista/vista-code-renderer.js +6 -0
- package/dist/vista/vista-code-renderer.js.map +1 -0
- package/dist/vista/vista-file-context.d.ts +8 -0
- package/dist/vista/vista-file-context.d.ts.map +1 -0
- package/dist/vista/vista-file-context.js +6 -0
- package/dist/vista/vista-file-context.js.map +1 -0
- package/dist/vista/vista-file-source.d.ts +15 -0
- package/dist/vista/vista-file-source.d.ts.map +1 -0
- package/dist/vista/vista-file-source.js +66 -0
- package/dist/vista/vista-file-source.js.map +1 -0
- package/dist/vista/vista-form-context.d.ts +13 -0
- package/dist/vista/vista-form-context.d.ts.map +1 -0
- package/dist/vista/vista-form-context.js +6 -0
- package/dist/vista/vista-form-context.js.map +1 -0
- package/dist/vista/vista-form-host.d.ts +7 -0
- package/dist/vista/vista-form-host.d.ts.map +1 -0
- package/dist/vista/vista-form-host.js +6 -0
- package/dist/vista/vista-form-host.js.map +1 -0
- package/dist/vista/vista-model.d.ts +12 -0
- package/dist/vista/vista-model.d.ts.map +1 -0
- package/dist/vista/vista-model.js +72 -0
- package/dist/vista/vista-model.js.map +1 -0
- package/dist/vista/vista-open-context.d.ts +7 -0
- package/dist/vista/vista-open-context.d.ts.map +1 -0
- package/dist/vista/vista-open-context.js +6 -0
- package/dist/vista/vista-open-context.js.map +1 -0
- package/dist/vista/vista-open-state.d.ts +5 -0
- package/dist/vista/vista-open-state.d.ts.map +1 -0
- package/dist/vista/vista-open-state.js +6 -0
- package/dist/vista/vista-open-state.js.map +1 -0
- package/dist/vista/vista-payloads.d.ts +106 -0
- package/dist/vista/vista-payloads.d.ts.map +1 -0
- package/dist/vista/vista-payloads.js +302 -0
- package/dist/vista/vista-payloads.js.map +1 -0
- package/dist/vista/vista-tabs-manifest.d.ts +17 -0
- package/dist/vista/vista-tabs-manifest.d.ts.map +1 -0
- package/dist/vista/vista-tabs-manifest.js +60 -0
- package/dist/vista/vista-tabs-manifest.js.map +1 -0
- package/dist/vista/vista-tools.d.ts +41 -0
- package/dist/vista/vista-tools.d.ts.map +1 -0
- package/dist/vista/vista-tools.js +113 -0
- package/dist/vista/vista-tools.js.map +1 -0
- package/package.json +4 -4
- package/src/index.ts +5 -0
- package/src/lib/biome-host/biome-builders.ts +4 -1
- package/src/lib/biome-host/biome-registry.ts +31 -12
- package/src/lib/biome-host/biome-scope-hooks.ts +39 -0
- package/src/lib/biome-host/biome-scope.tsx +1 -68
- package/src/lib/biome-host/biome-scoped-query.ts +4 -1
- package/src/lib/biome-host/create-biome-orval-config.ts +2 -2
- package/src/lib/biome-host/errors.ts +1 -1
- package/src/lib/biome-host/index.ts +1 -1
- package/src/lib/biome-host/session-profiles.ts +7 -1
- package/src/lib/capabilities/capability-context.ts +25 -0
- package/src/lib/capabilities/capability-provider.tsx +5 -34
- package/src/lib/capabilities/index.ts +1 -0
- package/src/lib/capabilities/use-capability.ts +4 -1
- package/src/lib/contribution-registry/contribution-registry.spec.ts +141 -0
- package/src/lib/contribution-registry/contribution-registry.ts +202 -0
- package/src/lib/contribution-registry/index.ts +9 -0
- package/src/lib/contribution-registry/renderable-registry.ts +142 -0
- package/src/lib/system-bus/deeplink.ts +1 -1
- package/src/lib/system-bus/host-ports.ts +2 -1
- package/src/lib/system-bus/intent-registry.ts +1 -2
- package/src/offline/index.ts +4 -2
- package/src/offline/offline-status-badge.tsx +1 -1
- package/src/offline/outbox.test.ts +23 -16
- package/src/offline/outbox.ts +1 -1
- package/src/offline/react-hooks.ts +37 -0
- package/src/offline/react.tsx +1 -40
- package/src/offline/storage.ts +11 -6
- package/src/registry/index.ts +1 -0
- package/src/registry/lib/primitives/SessionEventCard.tsx +4 -2
- package/src/registry/lib/session-context-provider.tsx +8 -25
- package/src/registry/lib/session-context.ts +21 -0
- package/src/registry/lib/session-selectors.ts +3 -1
- package/src/ui/branding/app-branding-context.ts +20 -0
- package/src/ui/branding/app-branding-provider.tsx +5 -27
- package/src/ui/capture/field-spec-to-zod.ts +22 -0
- package/src/ui/capture/field-spec-validate.ts +147 -0
- package/src/ui/capture/field-spec.ts +62 -0
- package/src/ui/capture/index.ts +9 -1
- package/src/ui/capture/schema-field-input.tsx +141 -15
- package/src/ui/capture/submit-values.test.ts +70 -0
- package/src/ui/capture/submit-values.ts +63 -0
- package/src/ui/capture/use-prefill.ts +4 -1
- package/src/ui/capture/use-wizard.ts +2 -2
- package/src/ui/capture/wizard.tsx +2 -1
- package/src/ui/index.ts +11 -2
- package/src/ui/primitives/alert-dialog.tsx +1 -1
- package/src/ui/primitives/badge-variants.ts +21 -0
- package/src/ui/primitives/badge.tsx +3 -19
- package/src/ui/primitives/button-variants.ts +31 -0
- package/src/ui/primitives/button.tsx +3 -28
- package/src/ui/primitives/form-stepper.tsx +1 -16
- package/src/ui/primitives/form-stepper.types.ts +15 -0
- package/src/ui/primitives/overflow-tabs.tsx +24 -4
- package/src/ui/primitives/preview-device-frame.tsx +1 -1
- package/src/ui/primitives/tag-multi-select.tsx +3 -4
- package/src/ui/primitives/url-preview-chrome.tsx +102 -0
- package/src/vista/GenericCatalogueSurface.tsx +177 -0
- package/src/vista/SurfaceFallbackCard.tsx +109 -0
- package/src/vista/VistaPanel.tsx +155 -0
- package/src/vista/form-payload.spec.ts +139 -0
- package/src/vista/html/CustomUiFrame.spec.tsx +125 -0
- package/src/vista/html/CustomUiFrame.tsx +204 -0
- package/src/vista/html/custom-ui-frame-bridge.spec.ts +191 -0
- package/src/vista/html/custom-ui-frame-bridge.ts +92 -0
- package/src/vista/html/custom-ui-frame-contract.ts +88 -0
- package/src/vista/html/custom-ui-intents.spec.ts +133 -0
- package/src/vista/html/custom-ui-intents.ts +151 -0
- package/src/vista/html/custom-ui-srcdoc.spec.ts +151 -0
- package/src/vista/html/custom-ui-srcdoc.ts +193 -0
- package/src/vista/html/index.ts +13 -0
- package/src/vista/index.ts +52 -0
- package/src/vista/surface-catalogue.spec.ts +140 -0
- package/src/vista/surface-catalogue.ts +84 -0
- package/src/vista/surface-icons.ts +57 -0
- package/src/vista/surface-registry.ts +56 -0
- package/src/vista/surfaces/ChartSurface.tsx +34 -0
- package/src/vista/surfaces/FilesSurface.tsx +202 -0
- package/src/vista/surfaces/FormSurface.tsx +363 -0
- package/src/vista/surfaces/HtmlSurface.tsx +43 -0
- package/src/vista/surfaces/TableSurface.tsx +99 -0
- package/src/vista/surfaces/UrlSurface.tsx +40 -0
- package/src/vista/surfaces/blob-surfaces.tsx +129 -0
- package/src/vista/surfaces/elicitation-transport.spec.ts +369 -0
- package/src/vista/surfaces/elicitation-transport.ts +353 -0
- package/src/vista/surfaces/file-surface-utils.ts +62 -0
- package/src/vista/surfaces/index.ts +24 -0
- package/src/vista/surfaces/register-surfaces.tsx +137 -0
- package/src/vista/surfaces/text-surfaces.tsx +119 -0
- package/src/vista/use-vista-tabs.ts +188 -0
- package/src/vista/vista-code-renderer-context.ts +16 -0
- package/src/vista/vista-code-renderer.tsx +34 -0
- package/src/vista/vista-file-context.ts +14 -0
- package/src/vista/vista-file-source.tsx +140 -0
- package/src/vista/vista-form-context.ts +20 -0
- package/src/vista/vista-form-host.tsx +53 -0
- package/src/vista/vista-model.ts +130 -0
- package/src/vista/vista-open-context.tsx +32 -0
- package/src/vista/vista-open-state.ts +11 -0
- package/src/vista/vista-payloads.ts +512 -0
- package/src/vista/vista-tabs-manifest.ts +123 -0
- package/src/vista/vista-tools.ts +220 -0
- package/dist/lib/biome-host/response-envelope.d.ts +0 -3
- package/dist/lib/biome-host/response-envelope.d.ts.map +0 -1
- package/dist/lib/biome-host/response-envelope.js +0 -21
- package/dist/lib/biome-host/response-envelope.js.map +0 -1
- package/src/lib/biome-host/response-envelope.ts +0 -69
|
@@ -1,6 +1,11 @@
|
|
|
1
1
|
import { Registry } from '@xemahq/registry';
|
|
2
2
|
import { useSyncExternalStore } from 'react';
|
|
3
3
|
|
|
4
|
+
import {
|
|
5
|
+
DuplicateContributionPolicy,
|
|
6
|
+
createContributionRegistry,
|
|
7
|
+
} from '../contribution-registry';
|
|
8
|
+
|
|
4
9
|
import type {
|
|
5
10
|
FrontendBiome,
|
|
6
11
|
FrontendBiomeFactory,
|
|
@@ -81,7 +86,6 @@ class FrontendBiomeRegistry extends Registry<string, FrontendBiome & { key: stri
|
|
|
81
86
|
// because the biome is being torn down anyway.
|
|
82
87
|
void Promise.resolve(entry.dispose()).catch((error: unknown) => {
|
|
83
88
|
// Surface for devtools without crashing the unregister flow.
|
|
84
|
-
// eslint-disable-next-line no-console
|
|
85
89
|
console.error(`[xema-ui-kernel] dispose() failed for '${id}':`, error);
|
|
86
90
|
});
|
|
87
91
|
}
|
|
@@ -153,23 +157,38 @@ class FrontendBiomeRegistry extends Registry<string, FrontendBiome & { key: stri
|
|
|
153
157
|
* light up the moment the biome's frontend loads. Duplicate kinds
|
|
154
158
|
* across biomes are surfaced as a console error and the first
|
|
155
159
|
* registration wins (deterministic + fail-loud, not silent).
|
|
160
|
+
*
|
|
161
|
+
* Built on the shared `createContributionRegistry` core — the same
|
|
162
|
+
* closed+open two-layer bookkeeping the ChatWidget, reply-variant and
|
|
163
|
+
* Vista-surface registries use. This overlay is rebuilt on every call
|
|
164
|
+
* (it is read during render), so it takes the `FirstWins` duplicate
|
|
165
|
+
* policy rather than `Throw`: a duplicate must not take down a render.
|
|
166
|
+
* `FirstWins` still REQUIRES the `onDuplicate` reporter below — the
|
|
167
|
+
* rejected contribution is never dropped silently.
|
|
156
168
|
*/
|
|
157
169
|
outputRenderers(): ReadonlyMap<string, OutputRendererContribution> {
|
|
158
|
-
|
|
159
|
-
|
|
170
|
+
if (!this.enabled) return new Map<string, OutputRendererContribution>();
|
|
171
|
+
// `onDuplicate` fires SYNCHRONOUSLY from inside `register()`, so this
|
|
172
|
+
// cursor always names the biome whose contribution was rejected — the
|
|
173
|
+
// contribution object itself does not carry its owner.
|
|
174
|
+
let contributingBiomeId = '';
|
|
175
|
+
const overlay = createContributionRegistry<OutputRendererContribution>({
|
|
176
|
+
name: 'biome outputRenderer',
|
|
177
|
+
duplicatePolicy: DuplicateContributionPolicy.FirstWins,
|
|
178
|
+
onDuplicate: (outputKind) => {
|
|
179
|
+
console.error(
|
|
180
|
+
`[xema-ui-kernel] duplicate outputRenderer for kind '${outputKind}' ` +
|
|
181
|
+
`from biome '${contributingBiomeId}'; first registration wins.`,
|
|
182
|
+
);
|
|
183
|
+
},
|
|
184
|
+
});
|
|
160
185
|
for (const biome of this.list()) {
|
|
186
|
+
contributingBiomeId = biome.id;
|
|
161
187
|
for (const entry of biome.outputRenderers ?? []) {
|
|
162
|
-
|
|
163
|
-
console.error(
|
|
164
|
-
`[xema-ui-kernel] duplicate outputRenderer for kind '${entry.outputKind}' ` +
|
|
165
|
-
`from biome '${biome.id}'; first registration wins.`,
|
|
166
|
-
);
|
|
167
|
-
continue;
|
|
168
|
-
}
|
|
169
|
-
out.set(entry.outputKind, entry);
|
|
188
|
+
overlay.register(entry.outputKind, entry);
|
|
170
189
|
}
|
|
171
190
|
}
|
|
172
|
-
return
|
|
191
|
+
return overlay.entries();
|
|
173
192
|
}
|
|
174
193
|
|
|
175
194
|
private notify(): void {
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { useHostBridge } from './host-bridge';
|
|
2
|
+
|
|
3
|
+
export interface ProjectScope {
|
|
4
|
+
readonly orgId: string | null;
|
|
5
|
+
readonly projectId: string | null;
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
export interface RequiredProjectScope {
|
|
9
|
+
readonly orgId: string;
|
|
10
|
+
readonly projectId: string;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
function normalize(value: string | null | undefined): string | null {
|
|
14
|
+
if (typeof value !== 'string') return null;
|
|
15
|
+
const trimmed = value.trim();
|
|
16
|
+
return trimmed.length > 0 ? trimmed : null;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export function useProjectScope(): ProjectScope {
|
|
20
|
+
const bridge = useHostBridge();
|
|
21
|
+
const params = bridge.navigation.useRouteParams<{ projectId?: string }>();
|
|
22
|
+
const orgId = normalize(bridge.auth.getOrgId());
|
|
23
|
+
const projectId =
|
|
24
|
+
normalize(params.projectId) ?? normalize(bridge.auth.getProjectId());
|
|
25
|
+
return { orgId, projectId };
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export function useRequiredScope(): RequiredProjectScope {
|
|
29
|
+
const { orgId, projectId } = useProjectScope();
|
|
30
|
+
if (!orgId || !projectId) {
|
|
31
|
+
throw new Error(
|
|
32
|
+
`[xema-ui-kernel] useRequiredScope() requires both orgId and projectId, ` +
|
|
33
|
+
`got orgId=${orgId ?? 'null'} projectId=${projectId ?? 'null'}. ` +
|
|
34
|
+
`Render this component under <ScopeGuard> or use useProjectScope() for ` +
|
|
35
|
+
`org-scoped surfaces.`,
|
|
36
|
+
);
|
|
37
|
+
}
|
|
38
|
+
return { orgId, projectId };
|
|
39
|
+
}
|
|
@@ -13,74 +13,7 @@
|
|
|
13
13
|
*/
|
|
14
14
|
import { Fragment, type ReactElement, type ReactNode } from 'react';
|
|
15
15
|
|
|
16
|
-
import {
|
|
17
|
-
|
|
18
|
-
/**
|
|
19
|
-
* Normalized active scope. Both fields are `null` when absent (never
|
|
20
|
-
* `undefined` and never empty-string) so consumers branch on a single shape.
|
|
21
|
-
*/
|
|
22
|
-
export interface ProjectScope {
|
|
23
|
-
readonly orgId: string | null;
|
|
24
|
-
readonly projectId: string | null;
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
/**
|
|
28
|
-
* Like {@link ProjectScope} but with both fields guaranteed present — the
|
|
29
|
-
* resolved shape {@link useRequiredScope} and {@link ScopeGuard} hand to
|
|
30
|
-
* consumers once the scope is known to be complete.
|
|
31
|
-
*/
|
|
32
|
-
export interface RequiredProjectScope {
|
|
33
|
-
readonly orgId: string;
|
|
34
|
-
readonly projectId: string;
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
/** Collapse `undefined` / `''` to `null`; trim incidental whitespace. */
|
|
38
|
-
function normalize(value: string | null | undefined): string | null {
|
|
39
|
-
if (typeof value !== 'string') return null;
|
|
40
|
-
const trimmed = value.trim();
|
|
41
|
-
return trimmed.length > 0 ? trimmed : null;
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
/**
|
|
45
|
-
* The active `{ orgId, projectId }` for the current biome render.
|
|
46
|
-
*
|
|
47
|
-
* - `orgId` comes from the host (`bridge.auth.getOrgId()`) — the org is owned
|
|
48
|
-
* by the host shell, never carried in a biome URL.
|
|
49
|
-
* - `projectId` is read from the matcher-bound route params
|
|
50
|
-
* (`bridge.navigation.useRouteParams().projectId`, set on project-scoped
|
|
51
|
-
* routes) and falls back to `bridge.auth.getProjectId()` for org-scoped
|
|
52
|
-
* surfaces that still have an active project selection.
|
|
53
|
-
*
|
|
54
|
-
* Both values are null-normalized. This is the single sanctioned scope read —
|
|
55
|
-
* biomes MUST NOT re-derive org/project from JWT claims or ad-hoc params.
|
|
56
|
-
*/
|
|
57
|
-
export function useProjectScope(): ProjectScope {
|
|
58
|
-
const bridge = useHostBridge();
|
|
59
|
-
const params = bridge.navigation.useRouteParams<{ projectId?: string }>();
|
|
60
|
-
const orgId = normalize(bridge.auth.getOrgId());
|
|
61
|
-
const projectId = normalize(params.projectId) ?? normalize(bridge.auth.getProjectId());
|
|
62
|
-
return { orgId, projectId };
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
/**
|
|
66
|
-
* Like {@link useProjectScope} but fail-fast: throws if either `orgId` or
|
|
67
|
-
* `projectId` is absent. Use it in project-scoped components that cannot
|
|
68
|
-
* render without both — wrap them in {@link ScopeGuard} to render a fallback
|
|
69
|
-
* instead of throwing. Returns the {@link RequiredProjectScope} narrowed
|
|
70
|
-
* shape so callers skip null checks.
|
|
71
|
-
*/
|
|
72
|
-
export function useRequiredScope(): RequiredProjectScope {
|
|
73
|
-
const { orgId, projectId } = useProjectScope();
|
|
74
|
-
if (!orgId || !projectId) {
|
|
75
|
-
throw new Error(
|
|
76
|
-
`[xema-ui-kernel] useRequiredScope() requires both orgId and projectId, ` +
|
|
77
|
-
`got orgId=${orgId ?? 'null'} projectId=${projectId ?? 'null'}. ` +
|
|
78
|
-
`Render this component under <ScopeGuard> or use useProjectScope() for ` +
|
|
79
|
-
`org-scoped surfaces.`,
|
|
80
|
-
);
|
|
81
|
-
}
|
|
82
|
-
return { orgId, projectId };
|
|
83
|
-
}
|
|
16
|
+
import { useProjectScope, type ProjectScope } from './biome-scope-hooks';
|
|
84
17
|
|
|
85
18
|
export interface ScopeGuardProps {
|
|
86
19
|
/**
|
|
@@ -18,7 +18,10 @@ import {
|
|
|
18
18
|
type UseQueryResult,
|
|
19
19
|
} from '@tanstack/react-query';
|
|
20
20
|
|
|
21
|
-
import {
|
|
21
|
+
import {
|
|
22
|
+
useProjectScope,
|
|
23
|
+
type ProjectScope,
|
|
24
|
+
} from './biome-scope-hooks';
|
|
22
25
|
|
|
23
26
|
/**
|
|
24
27
|
* The canonical Xema-platform tenant header. Every platform biome-api reads it
|
|
@@ -66,7 +66,7 @@ export function createBiomeOrvalConfig(
|
|
|
66
66
|
baseUrl: opts.baseUrl,
|
|
67
67
|
maxRetries: opts.maxRetries ?? 1,
|
|
68
68
|
getAuthToken: () => bridge.auth.ensureFreshToken(),
|
|
69
|
-
getHeaders:
|
|
69
|
+
getHeaders: () => {
|
|
70
70
|
const headers: Record<string, string> = {
|
|
71
71
|
'X-Correlation-Id': crypto.randomUUID(),
|
|
72
72
|
};
|
|
@@ -75,7 +75,7 @@ export function createBiomeOrvalConfig(
|
|
|
75
75
|
// Canonical header read by every Xema-platform service's RequestContext.
|
|
76
76
|
headers['X-Xema-Org-Id'] = orgId;
|
|
77
77
|
}
|
|
78
|
-
return headers;
|
|
78
|
+
return Promise.resolve(headers);
|
|
79
79
|
},
|
|
80
80
|
onUnauthorized: () => bridge.auth.onUnauthorized(),
|
|
81
81
|
};
|
|
@@ -166,7 +166,7 @@ function getOrvalClientErrorMessage(error: OrvalClientErrorLike, fallback: strin
|
|
|
166
166
|
const payload: WorkflowErrorEnvelope = (() => {
|
|
167
167
|
const message = record['message'];
|
|
168
168
|
if (message && typeof message === 'object') {
|
|
169
|
-
return message
|
|
169
|
+
return message;
|
|
170
170
|
}
|
|
171
171
|
return {
|
|
172
172
|
code: typeof record['code'] === 'string' ? record['code'] : undefined,
|
|
@@ -16,6 +16,7 @@ export * from './frontend-biome';
|
|
|
16
16
|
export * from './host-bridge';
|
|
17
17
|
export * from './biome-navigation';
|
|
18
18
|
export * from './biome-scope';
|
|
19
|
+
export * from './biome-scope-hooks';
|
|
19
20
|
export * from './biome-scoped-query';
|
|
20
21
|
export * from './biome-builders';
|
|
21
22
|
export * from './define-web-biome';
|
|
@@ -31,6 +32,5 @@ export * from './realtime-hooks';
|
|
|
31
32
|
export * from './i18n-port';
|
|
32
33
|
export * from './i18n-hooks';
|
|
33
34
|
export * from './errors';
|
|
34
|
-
export * from './response-envelope';
|
|
35
35
|
export * from './use-mutation-with-error-toast';
|
|
36
36
|
export * from './use-page-state';
|
|
@@ -89,7 +89,13 @@ export function useSessionProfileDescriptor(
|
|
|
89
89
|
for (const biome of biomeRegistry.list()) {
|
|
90
90
|
for (const profile of biome.session?.profiles ?? []) {
|
|
91
91
|
if (profile.key !== profileKey) continue;
|
|
92
|
-
if (
|
|
92
|
+
if (
|
|
93
|
+
biomeId !== null &&
|
|
94
|
+
biomeId !== undefined &&
|
|
95
|
+
profile.biomeId === biomeId
|
|
96
|
+
) {
|
|
97
|
+
return profile;
|
|
98
|
+
}
|
|
93
99
|
crossPluginMatch ??= profile;
|
|
94
100
|
}
|
|
95
101
|
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { createContext, useContext } from 'react';
|
|
2
|
+
|
|
3
|
+
import type { MeCapabilitiesSnapshot } from './types';
|
|
4
|
+
|
|
5
|
+
export interface CapabilityContextValue {
|
|
6
|
+
readonly snapshot: MeCapabilitiesSnapshot | undefined;
|
|
7
|
+
readonly isLoading: boolean;
|
|
8
|
+
readonly error: unknown;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export const CapabilityContext =
|
|
12
|
+
createContext<CapabilityContextValue | null>(null);
|
|
13
|
+
CapabilityContext.displayName = 'CapabilityContext';
|
|
14
|
+
|
|
15
|
+
export function useCapabilityContext(): CapabilityContextValue {
|
|
16
|
+
const ctx = useContext(CapabilityContext);
|
|
17
|
+
if (!ctx) {
|
|
18
|
+
throw new Error(
|
|
19
|
+
'[xema-ui-kernel] useCapability()/useCapabilities() called outside ' +
|
|
20
|
+
'<CapabilityProvider>. The host (or biome shell) must mount the ' +
|
|
21
|
+
'capability provider above any capability-gated subtree.',
|
|
22
|
+
);
|
|
23
|
+
}
|
|
24
|
+
return ctx;
|
|
25
|
+
}
|
|
@@ -1,26 +1,14 @@
|
|
|
1
1
|
import { useQuery } from '@tanstack/react-query';
|
|
2
|
-
import {
|
|
2
|
+
import type { ReactNode } from 'react';
|
|
3
3
|
|
|
4
4
|
import { useHostBridge } from '../biome-host/host-bridge';
|
|
5
|
+
import {
|
|
6
|
+
CapabilityContext,
|
|
7
|
+
type CapabilityContextValue,
|
|
8
|
+
} from './capability-context';
|
|
5
9
|
|
|
6
10
|
import type { CapabilityPort, MeCapabilitiesSnapshot } from './types';
|
|
7
11
|
|
|
8
|
-
/**
|
|
9
|
-
* The value exposed by {@link CapabilityProvider} through React context.
|
|
10
|
-
* `snapshot` is `undefined` until the first successful fetch; `isLoading`
|
|
11
|
-
* and `error` let callers distinguish "still unknown" and "fetch failed"
|
|
12
|
-
* from "explicitly denied" — the gate hook must NOT treat an errored fetch
|
|
13
|
-
* as "no capabilities".
|
|
14
|
-
*/
|
|
15
|
-
export interface CapabilityContextValue {
|
|
16
|
-
readonly snapshot: MeCapabilitiesSnapshot | undefined;
|
|
17
|
-
readonly isLoading: boolean;
|
|
18
|
-
readonly error: unknown;
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
const CapabilityContext = createContext<CapabilityContextValue | null>(null);
|
|
22
|
-
CapabilityContext.displayName = 'CapabilityContext';
|
|
23
|
-
|
|
24
12
|
/**
|
|
25
13
|
* Stable query-key root for the capability snapshot. Folded with the active
|
|
26
14
|
* org so each org caches independently and a re-fetch fires when the org
|
|
@@ -76,20 +64,3 @@ export function CapabilityProvider(props: CapabilityProviderProps): JSX.Element
|
|
|
76
64
|
|
|
77
65
|
return <CapabilityContext.Provider value={value}>{props.children}</CapabilityContext.Provider>;
|
|
78
66
|
}
|
|
79
|
-
|
|
80
|
-
/**
|
|
81
|
-
* Internal accessor for the capability context. Throws fail-fast if used
|
|
82
|
-
* outside {@link CapabilityProvider} — a missing provider is a wiring bug,
|
|
83
|
-
* not a "deny everything" condition.
|
|
84
|
-
*/
|
|
85
|
-
export function useCapabilityContext(): CapabilityContextValue {
|
|
86
|
-
const ctx = useContext(CapabilityContext);
|
|
87
|
-
if (!ctx) {
|
|
88
|
-
throw new Error(
|
|
89
|
-
'[xema-ui-kernel] useCapability()/useCapabilities() called outside ' +
|
|
90
|
-
'<CapabilityProvider>. The host (or biome shell) must mount the ' +
|
|
91
|
-
'capability provider above any capability-gated subtree.',
|
|
92
|
-
);
|
|
93
|
-
}
|
|
94
|
-
return ctx;
|
|
95
|
-
}
|
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
import type { ExecutionEnvironmentKind } from '@xemahq/kernel-contracts/execution-environment';
|
|
2
2
|
|
|
3
|
-
import {
|
|
3
|
+
import {
|
|
4
|
+
useCapabilityContext,
|
|
5
|
+
type CapabilityContextValue,
|
|
6
|
+
} from './capability-context';
|
|
4
7
|
import type { MeCapabilitiesSnapshot } from './types';
|
|
5
8
|
|
|
6
9
|
export interface UseCapabilityOptions {
|
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Guards the shared closed+open contribution registry core — the ONE
|
|
3
|
+
* implementation behind the ChatWidget, biome output-renderer, reply-variant
|
|
4
|
+
* and Vista-surface planes. Every property the hand-written copies had must
|
|
5
|
+
* survive the extraction.
|
|
6
|
+
*
|
|
7
|
+
* Runs under the host-web vitest mirror (this package carries no vitest dep).
|
|
8
|
+
*/
|
|
9
|
+
import { describe, expect, it, vi } from 'vitest';
|
|
10
|
+
|
|
11
|
+
import {
|
|
12
|
+
ContributionFallbackReason,
|
|
13
|
+
DuplicateContributionPolicy,
|
|
14
|
+
createContributionRegistry,
|
|
15
|
+
createRenderableContributionRegistry,
|
|
16
|
+
} from './index';
|
|
17
|
+
|
|
18
|
+
function makeRegistry(): ReturnType<typeof createContributionRegistry<string>> {
|
|
19
|
+
return createContributionRegistry<string>({
|
|
20
|
+
name: 'test',
|
|
21
|
+
reservedKinds: ['plan', 'diff'],
|
|
22
|
+
});
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
describe('createContributionRegistry', () => {
|
|
26
|
+
it('resolves first-party before open, and lists both', () => {
|
|
27
|
+
const registry = makeRegistry();
|
|
28
|
+
registry.registerFirstParty('plan', 'builtin-plan');
|
|
29
|
+
registry.register('acme:gantt', 'acme-gantt');
|
|
30
|
+
expect(registry.get('plan')).toBe('builtin-plan');
|
|
31
|
+
expect(registry.get('acme:gantt')).toBe('acme-gantt');
|
|
32
|
+
expect(registry.has('nope')).toBe(false);
|
|
33
|
+
expect(registry.list()).toEqual(['acme:gantt', 'plan']);
|
|
34
|
+
expect(registry.listOpen()).toEqual(['acme:gantt']);
|
|
35
|
+
expect([...registry.entries().keys()].sort()).toEqual(['acme:gantt', 'plan']);
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
it('refuses to let the open set claim a reserved first-party kind', () => {
|
|
39
|
+
const registry = makeRegistry();
|
|
40
|
+
expect(registry.isReserved('diff')).toBe(true);
|
|
41
|
+
expect(() => registry.register('diff', 'hijack')).toThrow(/reserved/);
|
|
42
|
+
// The namespaced form is fine.
|
|
43
|
+
expect(() => registry.register('acme:diff', 'ok')).not.toThrow();
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
it('is idempotent for the identical entry and throws for a different one', () => {
|
|
47
|
+
const registry = makeRegistry();
|
|
48
|
+
registry.register('acme:gantt', 'entry');
|
|
49
|
+
expect(() => registry.register('acme:gantt', 'entry')).not.toThrow();
|
|
50
|
+
expect(() => registry.register('acme:gantt', 'other')).toThrow(
|
|
51
|
+
/already registered/,
|
|
52
|
+
);
|
|
53
|
+
registry.registerFirstParty('plan', 'builtin');
|
|
54
|
+
expect(() => registry.registerFirstParty('plan', 'builtin')).not.toThrow();
|
|
55
|
+
expect(() => registry.registerFirstParty('plan', 'other')).toThrow(
|
|
56
|
+
/already registered/,
|
|
57
|
+
);
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
it('resets only the OPEN set', () => {
|
|
61
|
+
const registry = makeRegistry();
|
|
62
|
+
registry.registerFirstParty('plan', 'builtin');
|
|
63
|
+
registry.register('acme:gantt', 'entry');
|
|
64
|
+
registry.__resetOpenForTests();
|
|
65
|
+
expect(registry.list()).toEqual(['plan']);
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
it('reports — never swallows — a duplicate under FirstWins', () => {
|
|
69
|
+
const onDuplicate = vi.fn();
|
|
70
|
+
const registry = createContributionRegistry<string>({
|
|
71
|
+
name: 'overlay',
|
|
72
|
+
duplicatePolicy: DuplicateContributionPolicy.FirstWins,
|
|
73
|
+
onDuplicate,
|
|
74
|
+
});
|
|
75
|
+
registry.register('k', 'first');
|
|
76
|
+
registry.register('k', 'second');
|
|
77
|
+
expect(registry.get('k')).toBe('first');
|
|
78
|
+
expect(onDuplicate).toHaveBeenCalledWith('k', 'first', 'second');
|
|
79
|
+
});
|
|
80
|
+
|
|
81
|
+
it('refuses FirstWins without a reporter', () => {
|
|
82
|
+
expect(() =>
|
|
83
|
+
createContributionRegistry<string>({
|
|
84
|
+
name: 'overlay',
|
|
85
|
+
duplicatePolicy: DuplicateContributionPolicy.FirstWins,
|
|
86
|
+
}),
|
|
87
|
+
).toThrow(/onDuplicate/);
|
|
88
|
+
});
|
|
89
|
+
});
|
|
90
|
+
|
|
91
|
+
describe('createRenderableContributionRegistry', () => {
|
|
92
|
+
const registry = createRenderableContributionRegistry<string>({
|
|
93
|
+
name: 'renderable',
|
|
94
|
+
reservedKinds: ['plan'],
|
|
95
|
+
});
|
|
96
|
+
registry.registerFirstParty<{ label: string }>('plan', {
|
|
97
|
+
version: 2,
|
|
98
|
+
validate: (payload) =>
|
|
99
|
+
typeof payload === 'object' &&
|
|
100
|
+
payload !== null &&
|
|
101
|
+
typeof (payload as { label?: unknown }).label === 'string'
|
|
102
|
+
? (payload as { label: string })
|
|
103
|
+
: null,
|
|
104
|
+
render: (payload) => `plan:${payload.label}`,
|
|
105
|
+
});
|
|
106
|
+
|
|
107
|
+
it('renders a matching envelope', () => {
|
|
108
|
+
const resolution = registry.resolve({
|
|
109
|
+
kind: 'plan',
|
|
110
|
+
version: 1,
|
|
111
|
+
payload: { label: 'ship it' },
|
|
112
|
+
});
|
|
113
|
+
expect(resolution).toEqual({
|
|
114
|
+
matched: true,
|
|
115
|
+
kind: 'plan',
|
|
116
|
+
version: 2,
|
|
117
|
+
rendered: 'plan:ship it',
|
|
118
|
+
});
|
|
119
|
+
});
|
|
120
|
+
|
|
121
|
+
it('never throws — it returns a typed reason instead', () => {
|
|
122
|
+
expect(
|
|
123
|
+
registry.resolve({ kind: 'nope', version: 1, payload: {} }),
|
|
124
|
+
).toMatchObject({
|
|
125
|
+
matched: false,
|
|
126
|
+
reason: ContributionFallbackReason.UnknownKind,
|
|
127
|
+
});
|
|
128
|
+
expect(
|
|
129
|
+
registry.resolve({ kind: 'plan', version: 99, payload: {} }),
|
|
130
|
+
).toMatchObject({
|
|
131
|
+
matched: false,
|
|
132
|
+
reason: ContributionFallbackReason.UnsupportedVersion,
|
|
133
|
+
});
|
|
134
|
+
expect(
|
|
135
|
+
registry.resolve({ kind: 'plan', version: 1, payload: { label: 7 } }),
|
|
136
|
+
).toMatchObject({
|
|
137
|
+
matched: false,
|
|
138
|
+
reason: ContributionFallbackReason.InvalidPayload,
|
|
139
|
+
});
|
|
140
|
+
});
|
|
141
|
+
});
|