@xemahq/ui-kernel 0.9.2 → 0.11.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/dist/lib/biome-host/agent-validation.d.ts.map +1 -1
- package/dist/lib/biome-host/agent-validation.js +26 -13
- package/dist/lib/biome-host/agent-validation.js.map +1 -1
- package/dist/lib/biome-host/biome-registry.d.ts.map +1 -1
- package/dist/lib/biome-host/biome-registry.js +27 -10
- package/dist/lib/biome-host/biome-registry.js.map +1 -1
- package/dist/lib/biome-host/biome-scope-hooks.d.ts.map +1 -1
- package/dist/lib/biome-host/biome-scope-hooks.js +2 -1
- package/dist/lib/biome-host/biome-scope-hooks.js.map +1 -1
- package/dist/lib/biome-host/biome-scoped-query.d.ts.map +1 -1
- package/dist/lib/biome-host/biome-scoped-query.js +5 -3
- package/dist/lib/biome-host/biome-scoped-query.js.map +1 -1
- package/dist/lib/biome-host/frontend-biome.d.ts +1 -1
- package/dist/lib/biome-host/frontend-biome.d.ts.map +1 -1
- package/dist/lib/biome-host/host-bridge.d.ts +1 -1
- package/dist/lib/biome-host/host-bridge.d.ts.map +1 -1
- package/dist/lib/biome-host/host-bridge.js.map +1 -1
- package/dist/lib/biome-host/i18n-hooks.d.ts.map +1 -1
- package/dist/lib/biome-host/i18n-hooks.js.map +1 -1
- package/dist/lib/biome-host/index.d.ts +0 -1
- package/dist/lib/biome-host/index.d.ts.map +1 -1
- package/dist/lib/biome-host/index.js +0 -1
- package/dist/lib/biome-host/index.js.map +1 -1
- package/dist/lib/biome-host/realtime-hooks.d.ts.map +1 -1
- package/dist/lib/biome-host/realtime-hooks.js.map +1 -1
- package/dist/lib/biome-host/session-contributions.d.ts +10 -5
- package/dist/lib/biome-host/session-contributions.d.ts.map +1 -1
- package/dist/lib/biome-host/use-mutation-with-error-toast.d.ts.map +1 -1
- package/dist/lib/biome-host/use-mutation-with-error-toast.js +3 -2
- package/dist/lib/biome-host/use-mutation-with-error-toast.js.map +1 -1
- package/dist/lib/biome-host/use-page-state.d.ts.map +1 -1
- package/dist/lib/biome-host/use-page-state.js +19 -10
- package/dist/lib/biome-host/use-page-state.js.map +1 -1
- package/dist/lib/capabilities/capability-provider.d.ts +1 -1
- package/dist/lib/capabilities/capability-provider.d.ts.map +1 -1
- package/dist/lib/capabilities/capability-provider.js +2 -2
- package/dist/lib/capabilities/capability-provider.js.map +1 -1
- package/dist/lib/capabilities/use-capability.d.ts +1 -1
- package/dist/lib/capabilities/use-capability.d.ts.map +1 -1
- package/dist/lib/capabilities/use-capability.js +2 -1
- package/dist/lib/capabilities/use-capability.js.map +1 -1
- package/dist/lib/contribution-registry/contribution-registry.d.ts.map +1 -1
- package/dist/lib/contribution-registry/contribution-registry.js +2 -1
- package/dist/lib/contribution-registry/contribution-registry.js.map +1 -1
- package/dist/lib/system-bus/deeplink.d.ts.map +1 -1
- package/dist/lib/system-bus/deeplink.js +4 -2
- package/dist/lib/system-bus/deeplink.js.map +1 -1
- package/dist/lib/system-bus/host-ports.d.ts +2 -2
- 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 +6 -3
- package/dist/lib/system-bus/intent-registry.js.map +1 -1
- package/dist/lib/system-bus/intents.d.ts +1 -1
- package/dist/lib/system-bus/intents.d.ts.map +1 -1
- package/dist/lib/system-bus/palette.d.ts +1 -1
- package/dist/lib/system-bus/palette.d.ts.map +1 -1
- package/dist/lib/system-bus/system-bus-builder.d.ts.map +1 -1
- package/dist/lib/system-bus/system-bus-builder.js +1 -1
- package/dist/lib/system-bus/system-bus-builder.js.map +1 -1
- package/dist/lib/system-bus/windows.d.ts +1 -1
- package/dist/lib/system-bus/windows.d.ts.map +1 -1
- package/dist/offline/outbox.d.ts +1 -0
- package/dist/offline/outbox.d.ts.map +1 -1
- package/dist/offline/outbox.js +4 -1
- package/dist/offline/outbox.js.map +1 -1
- package/dist/offline/react-hooks.d.ts +1 -1
- package/dist/offline/react-hooks.d.ts.map +1 -1
- package/dist/offline/react-hooks.js.map +1 -1
- package/dist/org-db/components/DbResultTable.d.ts.map +1 -1
- package/dist/org-db/components/DbResultTable.js +15 -6
- package/dist/org-db/components/DbResultTable.js.map +1 -1
- package/dist/registry/lib/agent-validation-host.d.ts.map +1 -1
- package/dist/registry/lib/agent-validation-host.js +1 -1
- package/dist/registry/lib/agent-validation-host.js.map +1 -1
- package/dist/registry/lib/biome-slot.d.ts.map +1 -1
- package/dist/registry/lib/biome-slot.js +5 -3
- package/dist/registry/lib/biome-slot.js.map +1 -1
- package/dist/registry/lib/primitives/SessionEventCard.d.ts.map +1 -1
- package/dist/registry/lib/primitives/SessionEventCard.js +14 -2
- package/dist/registry/lib/primitives/SessionEventCard.js.map +1 -1
- package/dist/registry/lib/primitives/SessionEventTimeline.d.ts.map +1 -1
- package/dist/registry/lib/primitives/SessionEventTimeline.js +6 -3
- package/dist/registry/lib/primitives/SessionEventTimeline.js.map +1 -1
- package/dist/registry/lib/primitives/SessionTabbedDrawer.d.ts.map +1 -1
- package/dist/registry/lib/primitives/SessionTabbedDrawer.js +10 -5
- package/dist/registry/lib/primitives/SessionTabbedDrawer.js.map +1 -1
- package/dist/registry/lib/session-context-builder.d.ts +10 -2
- package/dist/registry/lib/session-context-builder.d.ts.map +1 -1
- package/dist/registry/lib/session-context-builder.js +14 -7
- package/dist/registry/lib/session-context-builder.js.map +1 -1
- package/dist/registry/lib/session-context-provider.d.ts +1 -1
- package/dist/registry/lib/session-context-provider.d.ts.map +1 -1
- package/dist/registry/lib/session-context-provider.js.map +1 -1
- package/dist/registry/lib/session-selectors.d.ts.map +1 -1
- package/dist/registry/lib/session-selectors.js +35 -20
- package/dist/registry/lib/session-selectors.js.map +1 -1
- package/dist/session/comments/CommentRail.d.ts.map +1 -1
- package/dist/session/comments/CommentRail.js.map +1 -1
- package/dist/session/shell/SessionWorkspaceShell.d.ts.map +1 -1
- package/dist/session/shell/SessionWorkspaceShell.js.map +1 -1
- package/dist/session-kit/approvals/ApprovalCard.d.ts.map +1 -1
- package/dist/session-kit/approvals/ApprovalCard.js +6 -2
- package/dist/session-kit/approvals/ApprovalCard.js.map +1 -1
- package/dist/session-kit/approvals/ApprovalsCenter.d.ts.map +1 -1
- package/dist/session-kit/approvals/ApprovalsCenter.js +6 -3
- package/dist/session-kit/approvals/ApprovalsCenter.js.map +1 -1
- package/dist/session-kit/combobox/Combobox.d.ts.map +1 -1
- package/dist/session-kit/combobox/Combobox.js +20 -6
- package/dist/session-kit/combobox/Combobox.js.map +1 -1
- package/dist/session-kit/display/MD.d.ts.map +1 -1
- package/dist/session-kit/display/MD.js +7 -4
- package/dist/session-kit/display/MD.js.map +1 -1
- package/dist/ui/branding/app-branding-provider.d.ts.map +1 -1
- package/dist/ui/branding/app-branding-provider.js.map +1 -1
- package/dist/ui/branding/sanitize.d.ts.map +1 -1
- package/dist/ui/branding/sanitize.js +12 -6
- package/dist/ui/branding/sanitize.js.map +1 -1
- package/dist/ui/capture/document-preview.d.ts +1 -1
- package/dist/ui/capture/document-preview.d.ts.map +1 -1
- package/dist/ui/capture/document-preview.js +8 -6
- package/dist/ui/capture/document-preview.js.map +1 -1
- package/dist/ui/capture/field-spec-to-zod.d.ts.map +1 -1
- package/dist/ui/capture/field-spec-to-zod.js +45 -16
- package/dist/ui/capture/field-spec-to-zod.js.map +1 -1
- package/dist/ui/capture/field-spec-validate.d.ts.map +1 -1
- package/dist/ui/capture/field-spec-validate.js +79 -38
- package/dist/ui/capture/field-spec-validate.js.map +1 -1
- package/dist/ui/capture/field-spec.d.ts.map +1 -1
- package/dist/ui/capture/field-spec.js +17 -6
- package/dist/ui/capture/field-spec.js.map +1 -1
- package/dist/ui/capture/schema-field-input.d.ts.map +1 -1
- package/dist/ui/capture/schema-field-input.js +23 -18
- package/dist/ui/capture/schema-field-input.js.map +1 -1
- package/dist/ui/capture/schema-form.d.ts +1 -1
- package/dist/ui/capture/schema-form.d.ts.map +1 -1
- package/dist/ui/capture/schema-form.js +7 -6
- package/dist/ui/capture/schema-form.js.map +1 -1
- package/dist/ui/capture/use-prefill.d.ts.map +1 -1
- package/dist/ui/capture/use-prefill.js +32 -14
- package/dist/ui/capture/use-prefill.js.map +1 -1
- package/dist/ui/capture/use-schema-validation.d.ts +1 -1
- package/dist/ui/capture/use-schema-validation.d.ts.map +1 -1
- package/dist/ui/capture/use-schema-validation.js +13 -8
- package/dist/ui/capture/use-schema-validation.js.map +1 -1
- package/dist/ui/capture/use-wizard.d.ts.map +1 -1
- package/dist/ui/capture/use-wizard.js +23 -8
- package/dist/ui/capture/use-wizard.js.map +1 -1
- package/dist/ui/capture/value-format.d.ts.map +1 -1
- package/dist/ui/capture/value-format.js +6 -3
- package/dist/ui/capture/value-format.js.map +1 -1
- package/dist/ui/capture/wizard.d.ts.map +1 -1
- package/dist/ui/capture/wizard.js +3 -3
- package/dist/ui/capture/wizard.js.map +1 -1
- package/dist/ui/charts/bar-chart.d.ts +1 -1
- package/dist/ui/charts/bar-chart.d.ts.map +1 -1
- package/dist/ui/charts/bar-chart.js +1 -1
- package/dist/ui/charts/bar-chart.js.map +1 -1
- package/dist/ui/charts/chart-frame.d.ts +2 -2
- package/dist/ui/charts/chart-frame.d.ts.map +1 -1
- package/dist/ui/charts/chart-frame.js +4 -3
- package/dist/ui/charts/chart-frame.js.map +1 -1
- package/dist/ui/charts/chart-utils.d.ts.map +1 -1
- package/dist/ui/charts/chart-utils.js +32 -14
- package/dist/ui/charts/chart-utils.js.map +1 -1
- package/dist/ui/charts/donut-chart.d.ts +1 -1
- package/dist/ui/charts/donut-chart.d.ts.map +1 -1
- package/dist/ui/charts/donut-chart.js +7 -3
- package/dist/ui/charts/donut-chart.js.map +1 -1
- package/dist/ui/charts/line-chart.d.ts +1 -1
- package/dist/ui/charts/line-chart.d.ts.map +1 -1
- package/dist/ui/charts/line-chart.js +7 -4
- package/dist/ui/charts/line-chart.js.map +1 -1
- package/dist/ui/charts/sparkline.d.ts +1 -1
- package/dist/ui/charts/sparkline.d.ts.map +1 -1
- package/dist/ui/charts/sparkline.js +10 -6
- package/dist/ui/charts/sparkline.js.map +1 -1
- package/dist/ui/chrome/AsyncBoundary.d.ts +2 -2
- package/dist/ui/chrome/AsyncBoundary.d.ts.map +1 -1
- package/dist/ui/chrome/AsyncBoundary.js +3 -3
- package/dist/ui/chrome/AsyncBoundary.js.map +1 -1
- package/dist/ui/chrome/EmptyState.d.ts +19 -8
- package/dist/ui/chrome/EmptyState.d.ts.map +1 -1
- package/dist/ui/chrome/EmptyState.js +6 -4
- package/dist/ui/chrome/EmptyState.js.map +1 -1
- package/dist/ui/chrome/RecordCardList.d.ts +19 -0
- package/dist/ui/chrome/RecordCardList.d.ts.map +1 -0
- package/dist/ui/chrome/RecordCardList.js +12 -0
- package/dist/ui/chrome/RecordCardList.js.map +1 -0
- package/dist/ui/chrome/page-shell.d.ts.map +1 -1
- package/dist/ui/chrome/page-shell.js +9 -3
- package/dist/ui/chrome/page-shell.js.map +1 -1
- package/dist/ui/chrome/status-badge.d.ts.map +1 -1
- package/dist/ui/chrome/status-badge.js +1 -1
- package/dist/ui/chrome/status-badge.js.map +1 -1
- package/dist/ui/design-tokens.d.ts +4 -6
- package/dist/ui/design-tokens.d.ts.map +1 -1
- package/dist/ui/design-tokens.js +17 -11
- package/dist/ui/design-tokens.js.map +1 -1
- package/dist/ui/index.d.ts +1 -0
- package/dist/ui/index.d.ts.map +1 -1
- package/dist/ui/index.js +1 -0
- package/dist/ui/index.js.map +1 -1
- package/dist/ui/primitives/async-combobox.d.ts.map +1 -1
- package/dist/ui/primitives/async-combobox.js +4 -2
- package/dist/ui/primitives/async-combobox.js.map +1 -1
- package/dist/ui/primitives/badge.d.ts +2 -2
- package/dist/ui/primitives/badge.d.ts.map +1 -1
- package/dist/ui/primitives/badge.js +3 -3
- package/dist/ui/primitives/badge.js.map +1 -1
- package/dist/ui/primitives/button.d.ts +2 -2
- package/dist/ui/primitives/button.d.ts.map +1 -1
- package/dist/ui/primitives/button.js +5 -5
- package/dist/ui/primitives/button.js.map +1 -1
- package/dist/ui/primitives/overflow-tabs.d.ts.map +1 -1
- package/dist/ui/primitives/overflow-tabs.js +19 -12
- package/dist/ui/primitives/overflow-tabs.js.map +1 -1
- package/dist/ui/primitives/preview-device-frame.js +8 -4
- 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 +10 -5
- package/dist/ui/primitives/tag-multi-select.js.map +1 -1
- package/dist/ui/primitives/url-preview-chrome.d.ts.map +1 -1
- package/dist/ui/primitives/url-preview-chrome.js.map +1 -1
- package/dist/vista/GenericCatalogueSurface.d.ts.map +1 -1
- package/dist/vista/GenericCatalogueSurface.js +5 -3
- package/dist/vista/GenericCatalogueSurface.js.map +1 -1
- package/dist/vista/VistaPanel.d.ts.map +1 -1
- package/dist/vista/VistaPanel.js +8 -4
- package/dist/vista/VistaPanel.js.map +1 -1
- package/dist/vista/html/CustomUiFrame.d.ts.map +1 -1
- package/dist/vista/html/CustomUiFrame.js +2 -1
- package/dist/vista/html/CustomUiFrame.js.map +1 -1
- package/dist/vista/html/custom-ui-frame-bridge.d.ts.map +1 -1
- package/dist/vista/html/custom-ui-frame-bridge.js +6 -3
- package/dist/vista/html/custom-ui-frame-bridge.js.map +1 -1
- package/dist/vista/html/custom-ui-intents.d.ts.map +1 -1
- package/dist/vista/html/custom-ui-intents.js +13 -15
- package/dist/vista/html/custom-ui-intents.js.map +1 -1
- package/dist/vista/surface-catalogue.d.ts.map +1 -1
- package/dist/vista/surface-catalogue.js +6 -3
- package/dist/vista/surface-catalogue.js.map +1 -1
- package/dist/vista/surfaces/FormSurface.d.ts.map +1 -1
- package/dist/vista/surfaces/FormSurface.js +20 -7
- package/dist/vista/surfaces/FormSurface.js.map +1 -1
- package/dist/vista/surfaces/TableSurface.d.ts.map +1 -1
- package/dist/vista/surfaces/TableSurface.js +2 -1
- package/dist/vista/surfaces/TableSurface.js.map +1 -1
- package/dist/vista/surfaces/blob-surfaces.d.ts.map +1 -1
- package/dist/vista/surfaces/blob-surfaces.js +7 -2
- package/dist/vista/surfaces/blob-surfaces.js.map +1 -1
- package/dist/vista/surfaces/elicitation-transport.d.ts.map +1 -1
- package/dist/vista/surfaces/elicitation-transport.js +14 -7
- package/dist/vista/surfaces/elicitation-transport.js.map +1 -1
- package/dist/vista/surfaces/file-surface-utils.d.ts.map +1 -1
- package/dist/vista/surfaces/file-surface-utils.js +8 -4
- package/dist/vista/surfaces/file-surface-utils.js.map +1 -1
- package/dist/vista/surfaces/register-surfaces.js +2 -1
- package/dist/vista/surfaces/register-surfaces.js.map +1 -1
- package/dist/vista/surfaces/text-surfaces.d.ts +1 -1
- package/dist/vista/surfaces/text-surfaces.d.ts.map +1 -1
- package/dist/vista/surfaces/text-surfaces.js +13 -7
- package/dist/vista/surfaces/text-surfaces.js.map +1 -1
- package/dist/vista/use-vista-tabs.d.ts.map +1 -1
- package/dist/vista/use-vista-tabs.js +8 -4
- package/dist/vista/use-vista-tabs.js.map +1 -1
- package/dist/vista/vista-code-renderer.d.ts.map +1 -1
- package/dist/vista/vista-code-renderer.js.map +1 -1
- package/dist/vista/vista-file-source.d.ts.map +1 -1
- package/dist/vista/vista-file-source.js +9 -5
- package/dist/vista/vista-file-source.js.map +1 -1
- package/dist/vista/vista-form-host.d.ts.map +1 -1
- package/dist/vista/vista-form-host.js +1 -1
- package/dist/vista/vista-form-host.js.map +1 -1
- package/dist/vista/vista-model.d.ts.map +1 -1
- package/dist/vista/vista-model.js +5 -3
- package/dist/vista/vista-model.js.map +1 -1
- package/dist/vista/vista-open-context.d.ts.map +1 -1
- package/dist/vista/vista-open-context.js +1 -1
- package/dist/vista/vista-open-context.js.map +1 -1
- package/dist/vista/vista-payloads.d.ts.map +1 -1
- package/dist/vista/vista-payloads.js +127 -63
- package/dist/vista/vista-payloads.js.map +1 -1
- package/dist/vista/vista-tabs-manifest.d.ts.map +1 -1
- package/dist/vista/vista-tabs-manifest.js +18 -9
- package/dist/vista/vista-tabs-manifest.js.map +1 -1
- package/dist/vista/vista-tools.d.ts.map +1 -1
- package/dist/vista/vista-tools.js +12 -6
- package/dist/vista/vista-tools.js.map +1 -1
- package/package.json +3 -3
- package/src/lib/biome-host/agent-validation.ts +37 -13
- package/src/lib/biome-host/biome-registry.ts +48 -13
- package/src/lib/biome-host/biome-scope-hooks.ts +3 -1
- package/src/lib/biome-host/biome-scoped-query.ts +7 -6
- package/src/lib/biome-host/frontend-biome.ts +1 -1
- package/src/lib/biome-host/host-bridge.ts +5 -4
- package/src/lib/biome-host/i18n-hooks.ts +1 -0
- package/src/lib/biome-host/index.ts +0 -1
- package/src/lib/biome-host/realtime-hooks.ts +1 -0
- package/src/lib/biome-host/session-contributions.ts +22 -19
- package/src/lib/biome-host/use-mutation-with-error-toast.ts +4 -2
- package/src/lib/biome-host/use-page-state.ts +27 -10
- package/src/lib/capabilities/capability-provider.tsx +12 -5
- package/src/lib/capabilities/use-capability.ts +8 -4
- package/src/lib/contribution-registry/contribution-registry.ts +3 -1
- package/src/lib/system-bus/deeplink.ts +14 -4
- package/src/lib/system-bus/host-ports.ts +3 -7
- package/src/lib/system-bus/intent-registry.ts +12 -8
- package/src/lib/system-bus/intents.ts +6 -2
- package/src/lib/system-bus/palette.ts +2 -1
- package/src/lib/system-bus/system-bus-builder.ts +4 -2
- package/src/lib/system-bus/windows.ts +1 -1
- package/src/offline/outbox.test.ts +12 -3
- package/src/offline/outbox.ts +5 -1
- package/src/offline/react-hooks.ts +5 -2
- package/src/org-db/components/DbResultTable.tsx +48 -15
- package/src/registry/lib/agent-validation-host.ts +1 -2
- package/src/registry/lib/biome-slot.tsx +7 -4
- package/src/registry/lib/primitives/SessionEventCard.tsx +29 -5
- package/src/registry/lib/primitives/SessionEventTimeline.tsx +9 -3
- package/src/registry/lib/primitives/SessionTabbedDrawer.tsx +15 -5
- package/src/registry/lib/session-context-builder.ts +33 -17
- package/src/registry/lib/session-context-provider.tsx +1 -1
- package/src/registry/lib/session-selectors.ts +66 -27
- package/src/session/comments/CommentRail.tsx +2 -2
- package/src/session/shell/SessionWorkspaceShell.tsx +2 -2
- package/src/session-kit/approvals/ApprovalCard.tsx +7 -2
- package/src/session-kit/approvals/ApprovalsCenter.tsx +13 -4
- package/src/session-kit/combobox/Combobox.tsx +42 -11
- package/src/session-kit/display/MD.tsx +14 -5
- package/src/ui/branding/app-branding-provider.tsx +2 -3
- package/src/ui/branding/sanitize.ts +18 -6
- package/src/ui/capture/document-preview.tsx +84 -19
- package/src/ui/capture/field-spec-to-zod.ts +62 -14
- package/src/ui/capture/field-spec-validate.ts +132 -43
- package/src/ui/capture/field-spec.test.ts +2 -2
- package/src/ui/capture/field-spec.ts +41 -10
- package/src/ui/capture/schema-field-input.tsx +218 -38
- package/src/ui/capture/schema-form.tsx +54 -13
- package/src/ui/capture/use-prefill.ts +50 -17
- package/src/ui/capture/use-schema-validation.ts +45 -13
- package/src/ui/capture/use-wizard.ts +57 -11
- package/src/ui/capture/value-format.ts +14 -4
- package/src/ui/capture/wizard.tsx +9 -5
- package/src/ui/charts/bar-chart.tsx +8 -4
- package/src/ui/charts/chart-frame.tsx +18 -5
- package/src/ui/charts/chart-utils.ts +47 -15
- package/src/ui/charts/donut-chart.tsx +24 -6
- package/src/ui/charts/line-chart.tsx +34 -12
- package/src/ui/charts/sparkline.tsx +17 -9
- package/src/ui/chrome/AsyncBoundary.tsx +14 -6
- package/src/ui/chrome/EmptyState.tsx +116 -43
- package/src/ui/chrome/RecordCardList.tsx +98 -0
- package/src/ui/chrome/page-shell.tsx +32 -8
- package/src/ui/chrome/status-badge.tsx +8 -4
- package/src/ui/design-tokens.ts +39 -13
- package/src/ui/index.ts +5 -0
- package/src/ui/primitives/async-combobox.tsx +7 -3
- package/src/ui/primitives/badge.tsx +14 -5
- package/src/ui/primitives/button.tsx +13 -6
- package/src/ui/primitives/overflow-tabs.tsx +46 -16
- package/src/ui/primitives/preview-device-frame.tsx +12 -4
- package/src/ui/primitives/tag-multi-select.tsx +30 -9
- package/src/ui/primitives/url-preview-chrome.tsx +1 -0
- package/src/vista/GenericCatalogueSurface.tsx +7 -5
- package/src/vista/VistaPanel.tsx +12 -4
- package/src/vista/html/CustomUiFrame.spec.tsx +3 -1
- package/src/vista/html/CustomUiFrame.tsx +3 -1
- package/src/vista/html/custom-ui-frame-bridge.ts +9 -3
- package/src/vista/html/custom-ui-intents.spec.ts +3 -1
- package/src/vista/html/custom-ui-intents.ts +19 -15
- package/src/vista/surface-catalogue.ts +9 -3
- package/src/vista/surfaces/FormSurface.tsx +27 -10
- package/src/vista/surfaces/TableSurface.tsx +4 -3
- package/src/vista/surfaces/blob-surfaces.tsx +13 -3
- package/src/vista/surfaces/elicitation-transport.ts +21 -7
- package/src/vista/surfaces/file-surface-utils.ts +11 -4
- package/src/vista/surfaces/register-surfaces.tsx +3 -1
- package/src/vista/surfaces/text-surfaces.tsx +21 -8
- package/src/vista/use-vista-tabs.ts +12 -4
- package/src/vista/vista-code-renderer.tsx +6 -5
- package/src/vista/vista-file-source.tsx +15 -14
- package/src/vista/vista-form-host.tsx +3 -8
- package/src/vista/vista-model.ts +10 -3
- package/src/vista/vista-open-context.tsx +3 -8
- package/src/vista/vista-payloads.ts +186 -63
- package/src/vista/vista-tabs-manifest.ts +28 -13
- package/src/vista/vista-tools.ts +18 -6
- package/dist/lib/biome-host/session-profiles.d.ts +0 -18
- package/dist/lib/biome-host/session-profiles.d.ts.map +0 -1
- package/dist/lib/biome-host/session-profiles.js +0 -38
- package/dist/lib/biome-host/session-profiles.js.map +0 -1
- package/src/lib/biome-host/session-profiles.ts +0 -105
|
@@ -82,11 +82,17 @@ export interface ValidateBiomeCompositionOptions {
|
|
|
82
82
|
*/
|
|
83
83
|
function biomeOwnedSlotOwner(slot: string): string | null {
|
|
84
84
|
const slashIndex = slot.indexOf('/');
|
|
85
|
-
if (slashIndex <= 0)
|
|
86
|
-
|
|
85
|
+
if (slashIndex <= 0) {
|
|
86
|
+
return null;
|
|
87
|
+
} // no slash, or leading slash (empty owner)
|
|
88
|
+
if (slot.indexOf('/', slashIndex + 1) !== -1) {
|
|
89
|
+
return null;
|
|
90
|
+
} // more than one slash
|
|
87
91
|
const owner = slot.slice(0, slashIndex);
|
|
88
92
|
const name = slot.slice(slashIndex + 1);
|
|
89
|
-
if (owner.length === 0 || name.length === 0)
|
|
93
|
+
if (owner.length === 0 || name.length === 0) {
|
|
94
|
+
return null;
|
|
95
|
+
}
|
|
90
96
|
return owner;
|
|
91
97
|
}
|
|
92
98
|
|
|
@@ -113,12 +119,17 @@ export function validateBiomeComposition(
|
|
|
113
119
|
const scope = route.projectScoped ? 'project' : 'root';
|
|
114
120
|
const key = `${scope}:${route.path}`;
|
|
115
121
|
const owners = routeOwners.get(key);
|
|
116
|
-
if (owners)
|
|
117
|
-
|
|
122
|
+
if (owners) {
|
|
123
|
+
owners.push(biome.id);
|
|
124
|
+
} else {
|
|
125
|
+
routeOwners.set(key, [biome.id]);
|
|
126
|
+
}
|
|
118
127
|
}
|
|
119
128
|
}
|
|
120
129
|
for (const [key, owners] of routeOwners) {
|
|
121
|
-
if (owners.length < 2)
|
|
130
|
+
if (owners.length < 2) {
|
|
131
|
+
continue;
|
|
132
|
+
}
|
|
122
133
|
const [scope, path] = splitFirst(key, ':');
|
|
123
134
|
diagnostics.push({
|
|
124
135
|
code: CompositionDiagnosticCode.DuplicateRoutePath,
|
|
@@ -139,12 +150,17 @@ export function validateBiomeComposition(
|
|
|
139
150
|
for (const biome of biomes) {
|
|
140
151
|
for (const navItem of biome.navItems ?? []) {
|
|
141
152
|
const owners = navOwners.get(navItem.id);
|
|
142
|
-
if (owners)
|
|
143
|
-
|
|
153
|
+
if (owners) {
|
|
154
|
+
owners.push(biome.id);
|
|
155
|
+
} else {
|
|
156
|
+
navOwners.set(navItem.id, [biome.id]);
|
|
157
|
+
}
|
|
144
158
|
}
|
|
145
159
|
}
|
|
146
160
|
for (const [navId, owners] of navOwners) {
|
|
147
|
-
if (owners.length < 2)
|
|
161
|
+
if (owners.length < 2) {
|
|
162
|
+
continue;
|
|
163
|
+
}
|
|
148
164
|
diagnostics.push({
|
|
149
165
|
code: CompositionDiagnosticCode.DuplicateNavId,
|
|
150
166
|
severity: CompositionDiagnosticSeverity.Error,
|
|
@@ -159,7 +175,9 @@ export function validateBiomeComposition(
|
|
|
159
175
|
// ── Panel slots: known-slot + dependency-closure ─────────────────────
|
|
160
176
|
for (const biome of biomes) {
|
|
161
177
|
for (const panel of biome.panels ?? []) {
|
|
162
|
-
if (options.knownSlots.has(panel.slot))
|
|
178
|
+
if (options.knownSlots.has(panel.slot)) {
|
|
179
|
+
continue;
|
|
180
|
+
}
|
|
163
181
|
const owner = biomeOwnedSlotOwner(panel.slot);
|
|
164
182
|
if (owner === null) {
|
|
165
183
|
diagnostics.push({
|
|
@@ -197,7 +215,9 @@ export function validateBiomeComposition(
|
|
|
197
215
|
/** Split on the first occurrence of `sep` into a `[head, tail]` pair. */
|
|
198
216
|
function splitFirst(value: string, sep: string): [string, string] {
|
|
199
217
|
const idx = value.indexOf(sep);
|
|
200
|
-
if (idx === -1)
|
|
218
|
+
if (idx === -1) {
|
|
219
|
+
return [value, ''];
|
|
220
|
+
}
|
|
201
221
|
return [value.slice(0, idx), value.slice(idx + sep.length)];
|
|
202
222
|
}
|
|
203
223
|
|
|
@@ -206,10 +226,14 @@ function sortDiagnostics(
|
|
|
206
226
|
diagnostics: CompositionDiagnostic[],
|
|
207
227
|
): CompositionDiagnostic[] {
|
|
208
228
|
return diagnostics.slice().sort((a, b) => {
|
|
209
|
-
if (a.code !== b.code)
|
|
229
|
+
if (a.code !== b.code) {
|
|
230
|
+
return a.code.localeCompare(b.code);
|
|
231
|
+
}
|
|
210
232
|
const ai = a.biomeIds.join(',');
|
|
211
233
|
const bi = b.biomeIds.join(',');
|
|
212
|
-
if (ai !== bi)
|
|
234
|
+
if (ai !== bi) {
|
|
235
|
+
return ai.localeCompare(bi);
|
|
236
|
+
}
|
|
213
237
|
return a.message.localeCompare(b.message);
|
|
214
238
|
});
|
|
215
239
|
}
|
|
@@ -36,7 +36,10 @@ import type { HostBridge } from './host-bridge';
|
|
|
36
36
|
* register/unregister/bootstrap call is a no-op — a single flag controls
|
|
37
37
|
* the entire surface.
|
|
38
38
|
*/
|
|
39
|
-
class FrontendBiomeRegistry extends Registry<
|
|
39
|
+
class FrontendBiomeRegistry extends Registry<
|
|
40
|
+
string,
|
|
41
|
+
FrontendBiome & { key: string }
|
|
42
|
+
> {
|
|
40
43
|
private revisionCount = 0;
|
|
41
44
|
private readonly listeners = new Set<() => void>();
|
|
42
45
|
/**
|
|
@@ -54,7 +57,9 @@ class FrontendBiomeRegistry extends Registry<string, FrontendBiome & { key: stri
|
|
|
54
57
|
}
|
|
55
58
|
|
|
56
59
|
registerBiome(biome: FrontendBiome): void {
|
|
57
|
-
if (!this.enabled)
|
|
60
|
+
if (!this.enabled) {
|
|
61
|
+
return;
|
|
62
|
+
}
|
|
58
63
|
this.register({ ...biome, key: biome.id });
|
|
59
64
|
this.revisionCount += 1;
|
|
60
65
|
this.notify();
|
|
@@ -67,14 +72,20 @@ class FrontendBiomeRegistry extends Registry<string, FrontendBiome & { key: stri
|
|
|
67
72
|
*/
|
|
68
73
|
async runInit(biomeId: string, bridge: HostBridge): Promise<void> {
|
|
69
74
|
const entry = this.get(biomeId);
|
|
70
|
-
if (!entry || !entry.init)
|
|
71
|
-
|
|
75
|
+
if (!entry || !entry.init) {
|
|
76
|
+
return;
|
|
77
|
+
}
|
|
78
|
+
if (this.initialized.has(biomeId)) {
|
|
79
|
+
return;
|
|
80
|
+
}
|
|
72
81
|
this.initialized.add(biomeId);
|
|
73
82
|
await entry.init({ bridge, biomeId });
|
|
74
83
|
}
|
|
75
84
|
|
|
76
85
|
unregisterBiome(id: string): boolean {
|
|
77
|
-
if (!this.enabled)
|
|
86
|
+
if (!this.enabled) {
|
|
87
|
+
return false;
|
|
88
|
+
}
|
|
78
89
|
const entry = this.get(id);
|
|
79
90
|
const removed = this.unregister(id);
|
|
80
91
|
if (removed) {
|
|
@@ -86,7 +97,10 @@ class FrontendBiomeRegistry extends Registry<string, FrontendBiome & { key: stri
|
|
|
86
97
|
// because the biome is being torn down anyway.
|
|
87
98
|
void Promise.resolve(entry.dispose()).catch((error: unknown) => {
|
|
88
99
|
// Surface for devtools without crashing the unregister flow.
|
|
89
|
-
console.error(
|
|
100
|
+
console.error(
|
|
101
|
+
`[xema-ui-kernel] dispose() failed for '${id}':`,
|
|
102
|
+
error,
|
|
103
|
+
);
|
|
90
104
|
});
|
|
91
105
|
}
|
|
92
106
|
this.notify();
|
|
@@ -103,7 +117,9 @@ class FrontendBiomeRegistry extends Registry<string, FrontendBiome & { key: stri
|
|
|
103
117
|
}
|
|
104
118
|
|
|
105
119
|
setEnabled(enabled: boolean): void {
|
|
106
|
-
if (this.enabled === enabled)
|
|
120
|
+
if (this.enabled === enabled) {
|
|
121
|
+
return;
|
|
122
|
+
}
|
|
107
123
|
this.enabled = enabled;
|
|
108
124
|
if (!enabled) {
|
|
109
125
|
// When master-disabling, drop any previously-registered biomes so
|
|
@@ -140,11 +156,15 @@ class FrontendBiomeRegistry extends Registry<string, FrontendBiome & { key: stri
|
|
|
140
156
|
}
|
|
141
157
|
|
|
142
158
|
panelsForSlot(slot: string): readonly PanelContribution[] {
|
|
143
|
-
if (!this.enabled)
|
|
159
|
+
if (!this.enabled) {
|
|
160
|
+
return [];
|
|
161
|
+
}
|
|
144
162
|
const out: PanelContribution[] = [];
|
|
145
163
|
for (const biome of this.list()) {
|
|
146
164
|
for (const panel of biome.panels ?? []) {
|
|
147
|
-
if (panel.slot === slot)
|
|
165
|
+
if (panel.slot === slot) {
|
|
166
|
+
out.push(panel);
|
|
167
|
+
}
|
|
148
168
|
}
|
|
149
169
|
}
|
|
150
170
|
return out.sort((a, b) => (a.weight ?? 100) - (b.weight ?? 100));
|
|
@@ -167,7 +187,9 @@ class FrontendBiomeRegistry extends Registry<string, FrontendBiome & { key: stri
|
|
|
167
187
|
* rejected contribution is never dropped silently.
|
|
168
188
|
*/
|
|
169
189
|
outputRenderers(): ReadonlyMap<string, OutputRendererContribution> {
|
|
170
|
-
if (!this.enabled)
|
|
190
|
+
if (!this.enabled) {
|
|
191
|
+
return new Map<string, OutputRendererContribution>();
|
|
192
|
+
}
|
|
171
193
|
// `onDuplicate` fires SYNCHRONOUSLY from inside `register()`, so this
|
|
172
194
|
// cursor always names the biome whose contribution was rejected — the
|
|
173
195
|
// contribution object itself does not carry its owner.
|
|
@@ -200,6 +222,17 @@ class FrontendBiomeRegistry extends Registry<string, FrontendBiome & { key: stri
|
|
|
200
222
|
|
|
201
223
|
export const biomeRegistry = new FrontendBiomeRegistry();
|
|
202
224
|
|
|
225
|
+
function isFrontendBiome(value: unknown): value is FrontendBiome {
|
|
226
|
+
return (
|
|
227
|
+
value !== null &&
|
|
228
|
+
typeof value === 'object' &&
|
|
229
|
+
'id' in value &&
|
|
230
|
+
typeof value.id === 'string' &&
|
|
231
|
+
'displayName' in value &&
|
|
232
|
+
typeof value.displayName === 'string'
|
|
233
|
+
);
|
|
234
|
+
}
|
|
235
|
+
|
|
203
236
|
/**
|
|
204
237
|
* Register an already-built `FrontendBiome` instance. Prefer
|
|
205
238
|
* `registerFrontendBiome(factory, bridge)` for biomes shipped via
|
|
@@ -222,9 +255,11 @@ export function registerFrontendBiome(
|
|
|
222
255
|
factory: FrontendBiomeFactory,
|
|
223
256
|
bridge: HostBridge,
|
|
224
257
|
): void {
|
|
225
|
-
if (!biomeRegistry.isEnabled())
|
|
226
|
-
|
|
227
|
-
|
|
258
|
+
if (!biomeRegistry.isEnabled()) {
|
|
259
|
+
return;
|
|
260
|
+
}
|
|
261
|
+
const biome: unknown = factory(bridge);
|
|
262
|
+
if (!isFrontendBiome(biome)) {
|
|
228
263
|
throw new Error(
|
|
229
264
|
'[xema-ui-kernel] FrontendBiomeFactory returned a non-FrontendBiome value. ' +
|
|
230
265
|
'A biome module must default-export `(bridge) => FrontendBiome`.',
|
|
@@ -11,7 +11,9 @@ export interface RequiredProjectScope {
|
|
|
11
11
|
}
|
|
12
12
|
|
|
13
13
|
function normalize(value: string | null | undefined): string | null {
|
|
14
|
-
if (typeof value !== 'string')
|
|
14
|
+
if (typeof value !== 'string') {
|
|
15
|
+
return null;
|
|
16
|
+
}
|
|
15
17
|
const trimmed = value.trim();
|
|
16
18
|
return trimmed.length > 0 ? trimmed : null;
|
|
17
19
|
}
|
|
@@ -18,10 +18,7 @@ import {
|
|
|
18
18
|
type UseQueryResult,
|
|
19
19
|
} from '@tanstack/react-query';
|
|
20
20
|
|
|
21
|
-
import {
|
|
22
|
-
useProjectScope,
|
|
23
|
-
type ProjectScope,
|
|
24
|
-
} from './biome-scope-hooks';
|
|
21
|
+
import { useProjectScope, type ProjectScope } from './biome-scope-hooks';
|
|
25
22
|
|
|
26
23
|
/**
|
|
27
24
|
* The canonical Xema-platform tenant header. Every platform biome-api reads it
|
|
@@ -38,8 +35,12 @@ const PROJECT_HEADER = 'X-Project-Id';
|
|
|
38
35
|
*/
|
|
39
36
|
export function buildScopedRequestInit(scope: ProjectScope): RequestInit {
|
|
40
37
|
const headers: Record<string, string> = {};
|
|
41
|
-
if (scope.orgId)
|
|
42
|
-
|
|
38
|
+
if (scope.orgId) {
|
|
39
|
+
headers[ORG_HEADER] = scope.orgId;
|
|
40
|
+
}
|
|
41
|
+
if (scope.projectId) {
|
|
42
|
+
headers[PROJECT_HEADER] = scope.projectId;
|
|
43
|
+
}
|
|
43
44
|
return { headers };
|
|
44
45
|
}
|
|
45
46
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import type { ComponentType, ReactNode } from 'react';
|
|
2
1
|
import type { HostBridge } from './host-bridge';
|
|
3
2
|
import type { SessionContributions } from './session-contributions';
|
|
3
|
+
import type { ComponentType, ReactNode } from 'react';
|
|
4
4
|
|
|
5
5
|
/**
|
|
6
6
|
* Runtime contribution types a `target: 'web'` biome composes. Web
|
|
@@ -1,12 +1,10 @@
|
|
|
1
|
-
import type { QueryClient } from '@tanstack/react-query';
|
|
2
|
-
|
|
3
1
|
import { createContext, useContext, type ReactNode } from 'react';
|
|
4
2
|
|
|
5
3
|
import type { CapabilityPort } from '../capabilities';
|
|
6
4
|
import type { SystemBus } from '../system-bus';
|
|
7
|
-
|
|
8
5
|
import type { I18nSource } from './i18n-port';
|
|
9
6
|
import type { RealtimeSource } from './realtime-port';
|
|
7
|
+
import type { QueryClient } from '@tanstack/react-query';
|
|
10
8
|
|
|
11
9
|
/**
|
|
12
10
|
* `HostBridge` is the host-agnostic abstraction every frontend biome
|
|
@@ -44,7 +42,10 @@ export interface HostBridgeNavigation {
|
|
|
44
42
|
* declares it is the matched route.
|
|
45
43
|
*/
|
|
46
44
|
useRouteParams<
|
|
47
|
-
T extends Record<string, string | undefined> = Record<
|
|
45
|
+
T extends Record<string, string | undefined> = Record<
|
|
46
|
+
string,
|
|
47
|
+
string | undefined
|
|
48
|
+
>,
|
|
48
49
|
>(): T;
|
|
49
50
|
/**
|
|
50
51
|
* Hook returning the current URL query string as a read-only
|
|
@@ -23,7 +23,6 @@ export * from './define-web-biome';
|
|
|
23
23
|
export * from './create-biome-orval-config';
|
|
24
24
|
export * from './biome-registry';
|
|
25
25
|
export * from './session-contributions';
|
|
26
|
-
export * from './session-profiles';
|
|
27
26
|
export * from './host-sources';
|
|
28
27
|
export * from './biome-mode';
|
|
29
28
|
export * from './agent-validation';
|
|
@@ -13,17 +13,15 @@
|
|
|
13
13
|
* `SessionContext`.
|
|
14
14
|
*
|
|
15
15
|
* `appliesTo` is the single gating primitive — biomes use it to scope
|
|
16
|
-
* a contribution to
|
|
17
|
-
*
|
|
16
|
+
* a contribution to explicit Agent, workspace, domain, or session status
|
|
17
|
+
* facts. Without it, every contribution applies everywhere.
|
|
18
18
|
*
|
|
19
19
|
* Naming convention: contribution ids MUST be namespaced as
|
|
20
20
|
* `<biome-id>/<contribution>` so cross-biome collisions surface
|
|
21
21
|
* deterministically at registration time (`RegistryDuplicateKeyError`).
|
|
22
22
|
*/
|
|
23
|
-
import type { ComponentType, ReactNode } from 'react';
|
|
24
|
-
|
|
25
23
|
import type { HostBridge } from './host-bridge';
|
|
26
|
-
import type {
|
|
24
|
+
import type { ComponentType, ReactNode } from 'react';
|
|
27
25
|
|
|
28
26
|
/**
|
|
29
27
|
* Read-only snapshot of the session the contribution is evaluated
|
|
@@ -41,14 +39,15 @@ export interface SessionContext {
|
|
|
41
39
|
* sessions they care about.
|
|
42
40
|
*/
|
|
43
41
|
readonly biomeId?: string;
|
|
44
|
-
readonly profileKey?: string;
|
|
45
42
|
readonly status: string;
|
|
46
43
|
/**
|
|
47
|
-
*
|
|
48
|
-
*
|
|
49
|
-
*
|
|
44
|
+
* The resolved Agent contract that launched this session. This is
|
|
45
|
+
* runtime truth returned by the Agent resolver, never a UI-authored
|
|
46
|
+
* profile or a synthetic fallback.
|
|
50
47
|
*/
|
|
51
|
-
readonly
|
|
48
|
+
readonly agent?: SessionResolvedAgent;
|
|
49
|
+
/** Repository actually bound to the session, when one exists. */
|
|
50
|
+
readonly repositoryId?: string;
|
|
52
51
|
/**
|
|
53
52
|
* `true` while the session is in a state that accepts new work
|
|
54
53
|
* (running, waiting, idle); `false` for terminal/paused/failed states.
|
|
@@ -58,6 +57,19 @@ export interface SessionContext {
|
|
|
58
57
|
readonly isActive: boolean;
|
|
59
58
|
}
|
|
60
59
|
|
|
60
|
+
/**
|
|
61
|
+
* UI-safe projection of the resolved Agent contract. The host obtains this
|
|
62
|
+
* from the Agent resolver and passes it into the kernel; plugins only consume
|
|
63
|
+
* the explicit permission/workspace facts they need.
|
|
64
|
+
*/
|
|
65
|
+
export interface SessionResolvedAgent {
|
|
66
|
+
readonly ref: string;
|
|
67
|
+
readonly requiredCapabilities: ReadonlySet<string>;
|
|
68
|
+
readonly mayEditRepositories: boolean;
|
|
69
|
+
readonly mayWriteKnowledgeBase: boolean;
|
|
70
|
+
readonly hasOutputSurface: boolean;
|
|
71
|
+
}
|
|
72
|
+
|
|
61
73
|
/**
|
|
62
74
|
* Stable representation of a session console event passed into activity
|
|
63
75
|
* + tool-call renderers. Mirrors the host's `SessionConsoleEntry` minus
|
|
@@ -281,13 +293,4 @@ export interface SessionContributions {
|
|
|
281
293
|
readonly mutationBars?: readonly MutationBarContribution[];
|
|
282
294
|
readonly headerChips?: readonly HeaderChipContribution[];
|
|
283
295
|
readonly attachmentClasses?: readonly AttachmentClassContribution[];
|
|
284
|
-
/**
|
|
285
|
-
* Profile descriptors this biome owns. The host matches a session's
|
|
286
|
-
* `profileKey` against these and fans out the descriptor's
|
|
287
|
-
* `capabilities` as `SessionContext.capabilities`, which each
|
|
288
|
-
* contribution's `appliesTo` predicate reads. A biome that ships a
|
|
289
|
-
* profile MUST also ship its descriptor here so the capability vocab
|
|
290
|
-
* stays explicit rather than implicit-from-key-naming.
|
|
291
|
-
*/
|
|
292
|
-
readonly profiles?: readonly SessionProfileDescriptor[];
|
|
293
296
|
}
|
|
@@ -68,10 +68,12 @@ export function useMutationWithErrorToast<
|
|
|
68
68
|
if (successTitle !== null && successTitle !== undefined) {
|
|
69
69
|
bridge.toast.success(successTitle, successDescription);
|
|
70
70
|
}
|
|
71
|
-
if (userOnSuccess)
|
|
71
|
+
if (userOnSuccess) {
|
|
72
|
+
userOnSuccess(data, variables, context, mutation);
|
|
73
|
+
}
|
|
72
74
|
},
|
|
73
75
|
onError: (error: TError) => {
|
|
74
|
-
if (errorTitle !==
|
|
76
|
+
if (errorTitle !== undefined) {
|
|
75
77
|
const shouldSuppressToast = customOnError?.(error) === true;
|
|
76
78
|
if (!shouldSuppressToast) {
|
|
77
79
|
const errorMessage = decodeError(
|
|
@@ -25,9 +25,12 @@ function buildPath(pathname: string, params: URLSearchParams): string {
|
|
|
25
25
|
}
|
|
26
26
|
|
|
27
27
|
function serializeValue<T>(value: T): string {
|
|
28
|
-
if (typeof value === 'string')
|
|
29
|
-
|
|
28
|
+
if (typeof value === 'string') {
|
|
29
|
+
return value;
|
|
30
|
+
}
|
|
31
|
+
if (typeof value === 'number' || typeof value === 'boolean') {
|
|
30
32
|
return String(value);
|
|
33
|
+
}
|
|
31
34
|
return JSON.stringify(value);
|
|
32
35
|
}
|
|
33
36
|
|
|
@@ -43,7 +46,9 @@ function deserializePrimitive<T>(
|
|
|
43
46
|
rawValue: string,
|
|
44
47
|
defaultValue: T,
|
|
45
48
|
): T | undefined {
|
|
46
|
-
if (typeof defaultValue === 'string')
|
|
49
|
+
if (typeof defaultValue === 'string') {
|
|
50
|
+
return rawValue as T;
|
|
51
|
+
}
|
|
47
52
|
|
|
48
53
|
if (typeof defaultValue === 'number') {
|
|
49
54
|
const numericValue = Number(rawValue);
|
|
@@ -51,8 +56,12 @@ function deserializePrimitive<T>(
|
|
|
51
56
|
}
|
|
52
57
|
|
|
53
58
|
if (typeof defaultValue === 'boolean') {
|
|
54
|
-
if (rawValue === 'true')
|
|
55
|
-
|
|
59
|
+
if (rawValue === 'true') {
|
|
60
|
+
return true as T;
|
|
61
|
+
}
|
|
62
|
+
if (rawValue === 'false') {
|
|
63
|
+
return false as T;
|
|
64
|
+
}
|
|
56
65
|
return defaultValue;
|
|
57
66
|
}
|
|
58
67
|
|
|
@@ -60,10 +69,14 @@ function deserializePrimitive<T>(
|
|
|
60
69
|
}
|
|
61
70
|
|
|
62
71
|
function deserializeValue<T>(rawValue: string | null, defaultValue: T): T {
|
|
63
|
-
if (rawValue === null)
|
|
72
|
+
if (rawValue === null) {
|
|
73
|
+
return defaultValue;
|
|
74
|
+
}
|
|
64
75
|
|
|
65
76
|
const primitive = deserializePrimitive(rawValue, defaultValue);
|
|
66
|
-
if (primitive !== undefined)
|
|
77
|
+
if (primitive !== undefined) {
|
|
78
|
+
return primitive;
|
|
79
|
+
}
|
|
67
80
|
|
|
68
81
|
// Default is null/undefined or a complex type (array/object). The value was
|
|
69
82
|
// written via JSON.stringify in serializeValue, so attempt to parse it back.
|
|
@@ -74,9 +87,13 @@ function deserializeValue<T>(rawValue: string | null, defaultValue: T): T {
|
|
|
74
87
|
return parsedValue as T;
|
|
75
88
|
}
|
|
76
89
|
|
|
77
|
-
if (defaultValue === null || defaultValue === undefined)
|
|
90
|
+
if (defaultValue === null || defaultValue === undefined) {
|
|
91
|
+
return rawValue as T;
|
|
92
|
+
}
|
|
78
93
|
|
|
79
|
-
if (parsedValue !== undefined)
|
|
94
|
+
if (parsedValue !== undefined) {
|
|
95
|
+
return parsedValue as T;
|
|
96
|
+
}
|
|
80
97
|
|
|
81
98
|
if (Array.isArray(defaultValue)) {
|
|
82
99
|
return rawValue ? ([rawValue] as unknown as T) : defaultValue;
|
|
@@ -218,7 +235,7 @@ export function useBatchPageState(): (
|
|
|
218
235
|
(updates: Record<string, string | null>) => {
|
|
219
236
|
const next = new URLSearchParams(searchParams);
|
|
220
237
|
for (const [key, value] of Object.entries(updates)) {
|
|
221
|
-
if (value === null
|
|
238
|
+
if (value === null) {
|
|
222
239
|
next.delete(key);
|
|
223
240
|
} else {
|
|
224
241
|
next.set(key, value);
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
import { useQuery } from '@tanstack/react-query';
|
|
2
|
-
import type { ReactNode } from 'react';
|
|
3
2
|
|
|
4
|
-
import { useHostBridge } from '../biome-host/host-bridge';
|
|
5
3
|
import {
|
|
6
4
|
CapabilityContext,
|
|
7
5
|
type CapabilityContextValue,
|
|
8
6
|
} from './capability-context';
|
|
7
|
+
import { useHostBridge } from '../biome-host/host-bridge';
|
|
9
8
|
|
|
10
9
|
import type { CapabilityPort, MeCapabilitiesSnapshot } from './types';
|
|
10
|
+
import type { ReactNode } from 'react';
|
|
11
11
|
|
|
12
12
|
/**
|
|
13
13
|
* Stable query-key root for the capability snapshot. Folded with the active
|
|
@@ -46,10 +46,13 @@ export interface CapabilityProviderProps {
|
|
|
46
46
|
* Rendering is fail-soft (callers can show a loading state), but failures are
|
|
47
47
|
* SURFACED via `error` rather than masquerading as an empty capability set.
|
|
48
48
|
*/
|
|
49
|
-
export function CapabilityProvider(
|
|
49
|
+
export function CapabilityProvider(
|
|
50
|
+
props: CapabilityProviderProps,
|
|
51
|
+
): JSX.Element {
|
|
50
52
|
const bridge = useHostBridge();
|
|
51
53
|
const port = props.port ?? bridge.capabilities;
|
|
52
|
-
const orgId =
|
|
54
|
+
const orgId =
|
|
55
|
+
props.orgId !== undefined ? props.orgId : bridge.auth.getOrgId();
|
|
53
56
|
|
|
54
57
|
const query = useQuery<MeCapabilitiesSnapshot>({
|
|
55
58
|
queryKey: [...CAPABILITIES_QUERY_ROOT, orgId],
|
|
@@ -62,5 +65,9 @@ export function CapabilityProvider(props: CapabilityProviderProps): JSX.Element
|
|
|
62
65
|
error: query.error,
|
|
63
66
|
};
|
|
64
67
|
|
|
65
|
-
return
|
|
68
|
+
return (
|
|
69
|
+
<CapabilityContext.Provider value={value}>
|
|
70
|
+
{props.children}
|
|
71
|
+
</CapabilityContext.Provider>
|
|
72
|
+
);
|
|
66
73
|
}
|
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import type { ExecutionEnvironmentKind } from '@xemahq/kernel-contracts/execution-environment';
|
|
2
|
-
|
|
3
1
|
import {
|
|
4
2
|
useCapabilityContext,
|
|
5
3
|
type CapabilityContextValue,
|
|
6
4
|
} from './capability-context';
|
|
5
|
+
|
|
7
6
|
import type { MeCapabilitiesSnapshot } from './types';
|
|
7
|
+
import type { ExecutionEnvironmentKind } from '@xemahq/kernel-contracts/execution-environment';
|
|
8
8
|
|
|
9
9
|
export interface UseCapabilityOptions {
|
|
10
10
|
/**
|
|
@@ -45,12 +45,16 @@ export interface CapabilityDecision {
|
|
|
45
45
|
* On error, `allowed` is `false` and `error` is set; the hook never silently
|
|
46
46
|
* degrades a failed fetch into a confident denial.
|
|
47
47
|
*/
|
|
48
|
-
export function useCapability(
|
|
48
|
+
export function useCapability(
|
|
49
|
+
ref: string,
|
|
50
|
+
opts?: UseCapabilityOptions,
|
|
51
|
+
): CapabilityDecision {
|
|
49
52
|
const { snapshot, isLoading, error } = useCapabilityContext();
|
|
50
53
|
|
|
51
54
|
const entry = snapshot?.capabilities.find((c) => c.ref === ref);
|
|
52
55
|
const inEnvironment =
|
|
53
|
-
!!entry &&
|
|
56
|
+
!!entry &&
|
|
57
|
+
(!opts?.environment || entry.environments.includes(opts.environment));
|
|
54
58
|
|
|
55
59
|
return {
|
|
56
60
|
allowed: inEnvironment && !entry.approvalRequired,
|
|
@@ -134,7 +134,9 @@ export function createContributionRegistry<TEntry>(
|
|
|
134
134
|
target.set(kind, entry);
|
|
135
135
|
return;
|
|
136
136
|
}
|
|
137
|
-
if (existing === entry)
|
|
137
|
+
if (existing === entry) {
|
|
138
|
+
return;
|
|
139
|
+
}
|
|
138
140
|
if (duplicatePolicy === DuplicateContributionPolicy.FirstWins) {
|
|
139
141
|
// `onDuplicate` is guaranteed present under this policy (checked above).
|
|
140
142
|
(onDuplicate as (k: string, e: TEntry, r: TEntry) => void)(
|
|
@@ -83,9 +83,13 @@ export type ParsedDeeplink =
|
|
|
83
83
|
|
|
84
84
|
function parseQuery(search: string): Record<string, string> {
|
|
85
85
|
const out: Record<string, string> = {};
|
|
86
|
-
if (search.length === 0)
|
|
86
|
+
if (search.length === 0) {
|
|
87
|
+
return out;
|
|
88
|
+
}
|
|
87
89
|
for (const pair of search.split('&')) {
|
|
88
|
-
if (pair.length === 0)
|
|
90
|
+
if (pair.length === 0) {
|
|
91
|
+
continue;
|
|
92
|
+
}
|
|
89
93
|
const eq = pair.indexOf('=');
|
|
90
94
|
if (eq === -1) {
|
|
91
95
|
out[decodeURIComponent(pair)] = '';
|
|
@@ -105,7 +109,10 @@ function parseQuery(search: string): Record<string, string> {
|
|
|
105
109
|
*/
|
|
106
110
|
export function parseDeeplink(raw: string): ParsedDeeplink {
|
|
107
111
|
if (typeof raw !== 'string' || !raw.startsWith(DEEPLINK_SCHEME)) {
|
|
108
|
-
throw new DeeplinkParseError(
|
|
112
|
+
throw new DeeplinkParseError(
|
|
113
|
+
String(raw),
|
|
114
|
+
`must start with "${DEEPLINK_SCHEME}"`,
|
|
115
|
+
);
|
|
109
116
|
}
|
|
110
117
|
const afterScheme = raw.slice(DEEPLINK_SCHEME.length);
|
|
111
118
|
if (afterScheme.length === 0) {
|
|
@@ -140,7 +147,10 @@ export function parseDeeplink(raw: string): ParsedDeeplink {
|
|
|
140
147
|
case DeeplinkTargetKind.Object: {
|
|
141
148
|
const body = segments.slice(1).join('/');
|
|
142
149
|
if (body.length === 0) {
|
|
143
|
-
throw new DeeplinkParseError(
|
|
150
|
+
throw new DeeplinkParseError(
|
|
151
|
+
raw,
|
|
152
|
+
'object deeplink missing <XemaObjectRef>',
|
|
153
|
+
);
|
|
144
154
|
}
|
|
145
155
|
return {
|
|
146
156
|
kind: DeeplinkTargetKind.Object,
|
|
@@ -1,16 +1,12 @@
|
|
|
1
|
-
import type { CapabilityRef } from '@xemahq/kernel-contracts/capability';
|
|
2
1
|
import type {
|
|
3
2
|
CapabilityInvokeMeta,
|
|
4
3
|
CapabilityInvokeResult,
|
|
5
4
|
} from './capability-invoke';
|
|
6
5
|
import type { ParsedDeeplink } from './deeplink';
|
|
7
|
-
import type { PaletteEntry, PaletteQuery } from './palette';
|
|
8
|
-
import type {
|
|
9
|
-
OpenWindowRequest,
|
|
10
|
-
WindowId,
|
|
11
|
-
WindowState,
|
|
12
|
-
} from './windows';
|
|
13
6
|
import type { WindowArrangement } from './enums';
|
|
7
|
+
import type { PaletteEntry, PaletteQuery } from './palette';
|
|
8
|
+
import type { OpenWindowRequest, WindowId, WindowState } from './windows';
|
|
9
|
+
import type { CapabilityRef } from '@xemahq/kernel-contracts/capability';
|
|
14
10
|
|
|
15
11
|
/**
|
|
16
12
|
* Framework-agnostic host ports the concrete host implements so the
|