@xemahq/ui-kernel 0.10.0 → 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/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 +1 -1
- 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-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/realtime-hooks.ts +1 -0
- package/src/lib/biome-host/session-contributions.ts +1 -1
- 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-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
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
// ═══════════════════════════════════════════════════════════════════════════
|
|
2
2
|
// Sparkline — tiny inline trend line, pure SVG, no axes/legend (Wave 9.2)
|
|
3
3
|
// ═══════════════════════════════════════════════════════════════════════════
|
|
4
|
-
import type { ReactNode } from 'react';
|
|
5
4
|
|
|
6
5
|
import { cn } from '../cn';
|
|
6
|
+
import { chartColorAt, defaultFormatValue, niceScale } from './chart-utils';
|
|
7
7
|
|
|
8
8
|
import type { ChartValueFormatter } from './chart-types';
|
|
9
|
-
import {
|
|
9
|
+
import type { ReactNode } from 'react';
|
|
10
10
|
|
|
11
11
|
const VIEW_W = 100;
|
|
12
12
|
const VIEW_H = 28;
|
|
@@ -36,8 +36,13 @@ export function Sparkline({
|
|
|
36
36
|
}: SparklineProps): ReactNode {
|
|
37
37
|
const format = formatValue ?? defaultFormatValue;
|
|
38
38
|
const finite = values.filter((v) => Number.isFinite(v));
|
|
39
|
+
// Read the endpoints BEFORE the empty guard so the guard itself narrows them:
|
|
40
|
+
// both are `undefined` exactly when `finite` is empty, which is the case the
|
|
41
|
+
// guard already returns for.
|
|
42
|
+
const first = finite[0];
|
|
43
|
+
const last = finite[finite.length - 1];
|
|
39
44
|
|
|
40
|
-
if (
|
|
45
|
+
if (first === undefined || last === undefined) {
|
|
41
46
|
return (
|
|
42
47
|
<span
|
|
43
48
|
role="img"
|
|
@@ -49,7 +54,9 @@ export function Sparkline({
|
|
|
49
54
|
);
|
|
50
55
|
}
|
|
51
56
|
|
|
52
|
-
const scale = niceScale(Math.min(...finite), Math.max(...finite), {
|
|
57
|
+
const scale = niceScale(Math.min(...finite), Math.max(...finite), {
|
|
58
|
+
pinZero: false,
|
|
59
|
+
});
|
|
53
60
|
const span = scale.max - scale.min;
|
|
54
61
|
const yToPx = (v: number): number =>
|
|
55
62
|
VIEW_H - PAD_Y - ((v - scale.min) / span) * (VIEW_H - 2 * PAD_Y);
|
|
@@ -60,17 +67,18 @@ export function Sparkline({
|
|
|
60
67
|
const segments: string[] = [];
|
|
61
68
|
let current: string[] = [];
|
|
62
69
|
values.forEach((v, i) => {
|
|
63
|
-
if (Number.isFinite(v))
|
|
64
|
-
|
|
70
|
+
if (Number.isFinite(v)) {
|
|
71
|
+
current.push(`${xToPx(i)},${yToPx(v)}`);
|
|
72
|
+
} else if (current.length > 0) {
|
|
65
73
|
segments.push(current.join(' '));
|
|
66
74
|
current = [];
|
|
67
75
|
}
|
|
68
76
|
});
|
|
69
|
-
if (current.length > 0)
|
|
77
|
+
if (current.length > 0) {
|
|
78
|
+
segments.push(current.join(' '));
|
|
79
|
+
}
|
|
70
80
|
|
|
71
81
|
const stroke = chartColorAt(0, color);
|
|
72
|
-
const first = finite[0];
|
|
73
|
-
const last = finite[finite.length - 1];
|
|
74
82
|
const summary =
|
|
75
83
|
ariaLabel ??
|
|
76
84
|
`${title}: trend of ${finite.length} points, from ${format(first)} to ${format(last)}.`;
|
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import type { LucideIcon } from 'lucide-react';
|
|
2
|
-
import type { ReactNode } from 'react';
|
|
3
|
-
|
|
4
|
-
import ErrorCard, { type ErrorMessageFormatter } from './ErrorCard';
|
|
5
1
|
import EmptyState from './EmptyState';
|
|
2
|
+
import ErrorCard, { type ErrorMessageFormatter } from './ErrorCard';
|
|
6
3
|
import LoadingState, { type LoadingStateVariant } from './LoadingState';
|
|
7
4
|
|
|
5
|
+
import type { LucideIcon } from 'lucide-react';
|
|
6
|
+
import type { ReactNode } from 'react';
|
|
7
|
+
|
|
8
8
|
interface AsyncBoundaryEmpty {
|
|
9
9
|
icon: LucideIcon;
|
|
10
10
|
title: string;
|
|
@@ -55,11 +55,19 @@ export default function AsyncBoundary({
|
|
|
55
55
|
}
|
|
56
56
|
|
|
57
57
|
if (error) {
|
|
58
|
-
return
|
|
58
|
+
return (
|
|
59
|
+
<ErrorCard error={error} onRetry={onRetry} formatError={formatError} />
|
|
60
|
+
);
|
|
59
61
|
}
|
|
60
62
|
|
|
61
63
|
if (isEmpty && empty) {
|
|
62
|
-
return
|
|
64
|
+
return (
|
|
65
|
+
<EmptyState
|
|
66
|
+
icon={empty.icon}
|
|
67
|
+
title={empty.title}
|
|
68
|
+
description={empty.description}
|
|
69
|
+
/>
|
|
70
|
+
);
|
|
63
71
|
}
|
|
64
72
|
|
|
65
73
|
return <>{children}</>;
|
|
@@ -1,11 +1,14 @@
|
|
|
1
|
-
import type { LucideIcon } from 'lucide-react';
|
|
2
|
-
import type { ComponentType, ReactNode } from 'react';
|
|
3
|
-
|
|
4
1
|
import { cn } from '../cn';
|
|
5
2
|
import { Button } from '../primitives/button';
|
|
6
3
|
import { Card, CardContent } from '../primitives/card';
|
|
7
4
|
|
|
8
|
-
|
|
5
|
+
import type { LucideIcon } from 'lucide-react';
|
|
6
|
+
import type { ComponentType, ReactNode } from 'react';
|
|
7
|
+
|
|
8
|
+
export type EmptyStateVariant =
|
|
9
|
+
| 'not-configured'
|
|
10
|
+
| 'no-results'
|
|
11
|
+
| 'disabled-context';
|
|
9
12
|
|
|
10
13
|
/**
|
|
11
14
|
* Visual density.
|
|
@@ -45,67 +48,94 @@ interface EmptyStateSecondaryAction {
|
|
|
45
48
|
href: string;
|
|
46
49
|
}
|
|
47
50
|
|
|
48
|
-
interface
|
|
49
|
-
icon: LucideIcon;
|
|
51
|
+
interface EmptyStateCommonProps {
|
|
50
52
|
title: string;
|
|
51
53
|
description?: ReactNode;
|
|
54
|
+
action?: EmptyStateAction;
|
|
55
|
+
secondaryAction?: EmptyStateSecondaryAction;
|
|
56
|
+
/** Host link component for `secondaryAction.href` (defaults to `<a>`). */
|
|
57
|
+
linkComponent?: EmptyStateLinkComponent;
|
|
58
|
+
className?: string;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
/** `comfortable` / `dense` render an icon block, so the icon is required. */
|
|
62
|
+
interface EmptyStateIconicProps extends EmptyStateCommonProps {
|
|
63
|
+
size?: Exclude<EmptyStateSize, 'inline'>;
|
|
64
|
+
icon: LucideIcon;
|
|
52
65
|
/** Optional illustration or extra content above the title */
|
|
53
66
|
illustration?: ReactNode;
|
|
54
67
|
/** Visual variant — drives default iconBg/iconColor unless overridden. */
|
|
55
68
|
variant?: EmptyStateVariant;
|
|
56
|
-
size?: EmptyStateSize;
|
|
57
69
|
/** Icon tint — overrides variant defaults */
|
|
58
70
|
iconBg?: string;
|
|
59
71
|
iconColor?: string;
|
|
60
|
-
action?: EmptyStateAction;
|
|
61
|
-
secondaryAction?: EmptyStateSecondaryAction;
|
|
62
|
-
/** Host link component for `secondaryAction.href` (defaults to `<a>`). */
|
|
63
|
-
linkComponent?: EmptyStateLinkComponent;
|
|
64
|
-
className?: string;
|
|
65
72
|
}
|
|
66
73
|
|
|
67
|
-
|
|
74
|
+
/**
|
|
75
|
+
* `inline` is text-only by definition — no icon block, therefore no icon,
|
|
76
|
+
* illustration, variant or icon tint. They are typed `never` rather than
|
|
77
|
+
* silently ignored: an accepted-but-unrendered prop is how callers ended up
|
|
78
|
+
* importing a lucide icon that renders nowhere.
|
|
79
|
+
*/
|
|
80
|
+
interface EmptyStateInlineProps extends EmptyStateCommonProps {
|
|
81
|
+
size: 'inline';
|
|
82
|
+
icon?: never;
|
|
83
|
+
illustration?: never;
|
|
84
|
+
variant?: never;
|
|
85
|
+
iconBg?: never;
|
|
86
|
+
iconColor?: never;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
type EmptyStateProps = EmptyStateIconicProps | EmptyStateInlineProps;
|
|
90
|
+
|
|
91
|
+
const VARIANT_DEFAULTS: Record<
|
|
92
|
+
EmptyStateVariant,
|
|
93
|
+
{ iconBg: string; iconColor: string }
|
|
94
|
+
> = {
|
|
68
95
|
'not-configured': { iconBg: 'bg-info/10', iconColor: 'text-info' },
|
|
69
96
|
'no-results': { iconBg: 'bg-warning/10', iconColor: 'text-warning' },
|
|
70
97
|
'disabled-context': { iconBg: 'bg-muted', iconColor: 'text-ink-3' },
|
|
71
98
|
};
|
|
72
99
|
|
|
73
|
-
export default function EmptyState({
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
description,
|
|
77
|
-
illustration,
|
|
78
|
-
variant = 'not-configured',
|
|
79
|
-
size = 'comfortable',
|
|
80
|
-
iconBg,
|
|
81
|
-
iconColor,
|
|
82
|
-
action,
|
|
83
|
-
secondaryAction,
|
|
84
|
-
linkComponent,
|
|
85
|
-
className,
|
|
86
|
-
}: Readonly<EmptyStateProps>) {
|
|
100
|
+
export default function EmptyState(props: Readonly<EmptyStateProps>) {
|
|
101
|
+
const { title, description, action, secondaryAction, linkComponent, className } =
|
|
102
|
+
props;
|
|
87
103
|
const Link = linkComponent ?? DefaultLink;
|
|
88
|
-
const defaults = VARIANT_DEFAULTS[variant];
|
|
89
|
-
const resolvedIconBg = iconBg ?? defaults.iconBg;
|
|
90
|
-
const resolvedIconColor = iconColor ?? defaults.iconColor;
|
|
91
104
|
|
|
92
|
-
if (size === 'inline') {
|
|
105
|
+
if (props.size === 'inline') {
|
|
93
106
|
return (
|
|
94
|
-
<div
|
|
107
|
+
<div
|
|
108
|
+
className={cn(
|
|
109
|
+
'flex items-center justify-center px-3 py-6 text-center text-body-2 text-ink-4',
|
|
110
|
+
className,
|
|
111
|
+
)}
|
|
112
|
+
>
|
|
95
113
|
<div className="max-w-sm space-y-1">
|
|
96
114
|
<p className="text-ink-3">{title}</p>
|
|
97
115
|
{description && <p className="text-ink-4">{description}</p>}
|
|
98
116
|
{(action || secondaryAction) && (
|
|
99
117
|
<div className="mt-3 flex items-center justify-center gap-2">
|
|
100
118
|
{action && (
|
|
101
|
-
<Button
|
|
119
|
+
<Button
|
|
120
|
+
size="sm"
|
|
121
|
+
variant="outline"
|
|
122
|
+
onClick={action.onClick}
|
|
123
|
+
className="h-7 gap-1.5 text-body-2"
|
|
124
|
+
>
|
|
102
125
|
{action.icon && <action.icon className="h-3.5 w-3.5" />}
|
|
103
126
|
{action.label}
|
|
104
127
|
</Button>
|
|
105
128
|
)}
|
|
106
129
|
{secondaryAction && (
|
|
107
|
-
<Button
|
|
108
|
-
|
|
130
|
+
<Button
|
|
131
|
+
asChild
|
|
132
|
+
size="sm"
|
|
133
|
+
variant="ghost"
|
|
134
|
+
className="h-7 px-2 text-body-2"
|
|
135
|
+
>
|
|
136
|
+
<Link href={secondaryAction.href}>
|
|
137
|
+
{secondaryAction.label}
|
|
138
|
+
</Link>
|
|
109
139
|
</Button>
|
|
110
140
|
)}
|
|
111
141
|
</div>
|
|
@@ -115,6 +145,18 @@ export default function EmptyState({
|
|
|
115
145
|
);
|
|
116
146
|
}
|
|
117
147
|
|
|
148
|
+
const {
|
|
149
|
+
icon: Icon,
|
|
150
|
+
illustration,
|
|
151
|
+
variant = 'not-configured',
|
|
152
|
+
size = 'comfortable',
|
|
153
|
+
iconBg,
|
|
154
|
+
iconColor,
|
|
155
|
+
} = props;
|
|
156
|
+
const defaults = VARIANT_DEFAULTS[variant];
|
|
157
|
+
const resolvedIconBg = iconBg ?? defaults.iconBg;
|
|
158
|
+
const resolvedIconColor = iconColor ?? defaults.iconColor;
|
|
159
|
+
|
|
118
160
|
if (size === 'dense') {
|
|
119
161
|
return (
|
|
120
162
|
<div
|
|
@@ -124,24 +166,41 @@ export default function EmptyState({
|
|
|
124
166
|
)}
|
|
125
167
|
>
|
|
126
168
|
{illustration ?? (
|
|
127
|
-
<div
|
|
169
|
+
<div
|
|
170
|
+
className={cn(
|
|
171
|
+
'h-9 w-9 rounded-xl flex items-center justify-center mb-3',
|
|
172
|
+
resolvedIconBg,
|
|
173
|
+
)}
|
|
174
|
+
>
|
|
128
175
|
<Icon className={cn('h-4 w-4', resolvedIconColor)} />
|
|
129
176
|
</div>
|
|
130
177
|
)}
|
|
131
178
|
<p className="text-body-1 font-semibold text-ink">{title}</p>
|
|
132
179
|
{description && (
|
|
133
|
-
<p className="mt-1 max-w-md text-body-2 leading-snug text-ink-3">
|
|
180
|
+
<p className="mt-1 max-w-md text-body-2 leading-snug text-ink-3">
|
|
181
|
+
{description}
|
|
182
|
+
</p>
|
|
134
183
|
)}
|
|
135
184
|
{(action || secondaryAction) && (
|
|
136
185
|
<div className="mt-3 flex items-center gap-2">
|
|
137
186
|
{action && (
|
|
138
|
-
<Button
|
|
187
|
+
<Button
|
|
188
|
+
size="sm"
|
|
189
|
+
variant="outline"
|
|
190
|
+
onClick={action.onClick}
|
|
191
|
+
className="h-7 gap-1.5 text-body-2"
|
|
192
|
+
>
|
|
139
193
|
{action.icon && <action.icon className="h-3.5 w-3.5" />}
|
|
140
194
|
{action.label}
|
|
141
195
|
</Button>
|
|
142
196
|
)}
|
|
143
197
|
{secondaryAction && (
|
|
144
|
-
<Button
|
|
198
|
+
<Button
|
|
199
|
+
asChild
|
|
200
|
+
size="sm"
|
|
201
|
+
variant="ghost"
|
|
202
|
+
className="h-7 px-2 text-body-2"
|
|
203
|
+
>
|
|
145
204
|
<Link href={secondaryAction.href}>{secondaryAction.label}</Link>
|
|
146
205
|
</Button>
|
|
147
206
|
)}
|
|
@@ -152,21 +211,35 @@ export default function EmptyState({
|
|
|
152
211
|
}
|
|
153
212
|
|
|
154
213
|
return (
|
|
155
|
-
<Card
|
|
214
|
+
<Card
|
|
215
|
+
className={cn(
|
|
216
|
+
'border-2 border-dashed border-border/50 rounded-xl',
|
|
217
|
+
className,
|
|
218
|
+
)}
|
|
219
|
+
>
|
|
156
220
|
<CardContent className="flex flex-col items-center justify-center py-16 text-center">
|
|
157
221
|
{illustration ?? (
|
|
158
|
-
<div
|
|
222
|
+
<div
|
|
223
|
+
className={`h-16 w-16 rounded-2xl flex items-center justify-center mb-5 ${resolvedIconBg}`}
|
|
224
|
+
>
|
|
159
225
|
<Icon className={`h-7 w-7 ${resolvedIconColor}`} />
|
|
160
226
|
</div>
|
|
161
227
|
)}
|
|
162
228
|
<p className="text-subtitle font-semibold text-ink">{title}</p>
|
|
163
229
|
{description && (
|
|
164
|
-
<p className="text-body-1 mt-2 max-w-sm text-ink-3 leading-relaxed">
|
|
230
|
+
<p className="text-body-1 mt-2 max-w-sm text-ink-3 leading-relaxed">
|
|
231
|
+
{description}
|
|
232
|
+
</p>
|
|
165
233
|
)}
|
|
166
234
|
{(action || secondaryAction) && (
|
|
167
235
|
<div className="mt-6 flex items-center gap-3">
|
|
168
236
|
{action && (
|
|
169
|
-
<Button
|
|
237
|
+
<Button
|
|
238
|
+
size="sm"
|
|
239
|
+
variant="outline"
|
|
240
|
+
onClick={action.onClick}
|
|
241
|
+
className="gap-2 h-10 px-5"
|
|
242
|
+
>
|
|
170
243
|
{action.icon && <action.icon className="h-4 w-4" />}
|
|
171
244
|
{action.label}
|
|
172
245
|
</Button>
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
import { cn } from '../cn';
|
|
2
|
+
|
|
3
|
+
import type { ReactNode } from 'react';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* One label/value row inside a record card — mirrors one table column.
|
|
7
|
+
*
|
|
8
|
+
* `key` exists because a card's rows are keyed by the COLUMN, and a column's
|
|
9
|
+
* identity is its field key, not its user-facing label (two columns may carry
|
|
10
|
+
* the same label). It defaults to `label` for the common case where the label
|
|
11
|
+
* is already unique.
|
|
12
|
+
*/
|
|
13
|
+
export interface RecordCardField {
|
|
14
|
+
readonly key?: string;
|
|
15
|
+
readonly label: string;
|
|
16
|
+
readonly value: ReactNode;
|
|
17
|
+
/**
|
|
18
|
+
* `data-*` attributes for the row element — e.g. the same hook the equivalent
|
|
19
|
+
* table cell carries, so a click-to-context resolver lands on the identical
|
|
20
|
+
* node at every viewport width. Deliberately `data-*` only: styling stays in
|
|
21
|
+
* this primitive, so a caller cannot re-open the drift it closed.
|
|
22
|
+
*/
|
|
23
|
+
readonly rowAttributes?: Readonly<Record<`data-${string}`, string>>;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export interface RecordCardListProps<T> {
|
|
27
|
+
readonly items: readonly T[];
|
|
28
|
+
readonly getKey: (item: T) => string;
|
|
29
|
+
/** Card header rendered above the field list (title, status, row toggle). */
|
|
30
|
+
readonly renderHeader?: (item: T) => ReactNode;
|
|
31
|
+
readonly getFields: (item: T) => readonly RecordCardField[];
|
|
32
|
+
/** Row actions, rendered right-aligned below a divider. */
|
|
33
|
+
readonly renderActions?: (item: T) => ReactNode;
|
|
34
|
+
/** Free block appended after the actions (expanded detail). */
|
|
35
|
+
readonly renderDetail?: (item: T) => ReactNode;
|
|
36
|
+
/** Extra classes for the list element. */
|
|
37
|
+
readonly className?: string;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* Small-viewport (below `md`) layout for a record list: one stacked card per
|
|
42
|
+
* record with the table's columns rendered as label/value rows, instead of a
|
|
43
|
+
* horizontal-scroll-only table.
|
|
44
|
+
*
|
|
45
|
+
* This is the ONE definition of that card chrome — spacing, border, divider,
|
|
46
|
+
* label/value alignment. Callers name their columns and their actions; they do
|
|
47
|
+
* not restate the chrome. Deliberately NOT parameterised by card class: a
|
|
48
|
+
* per-caller class hook is how the three copies this replaced drifted apart in
|
|
49
|
+
* the first place.
|
|
50
|
+
*/
|
|
51
|
+
export function RecordCardList<T>(props: Readonly<RecordCardListProps<T>>) {
|
|
52
|
+
const {
|
|
53
|
+
items,
|
|
54
|
+
getKey,
|
|
55
|
+
renderHeader,
|
|
56
|
+
getFields,
|
|
57
|
+
renderActions,
|
|
58
|
+
renderDetail,
|
|
59
|
+
className,
|
|
60
|
+
} = props;
|
|
61
|
+
|
|
62
|
+
return (
|
|
63
|
+
<ul className={cn('space-y-2', className)}>
|
|
64
|
+
{items.map((item) => {
|
|
65
|
+
const actions = renderActions?.(item);
|
|
66
|
+
const detail = renderDetail?.(item);
|
|
67
|
+
return (
|
|
68
|
+
<li
|
|
69
|
+
key={getKey(item)}
|
|
70
|
+
className="space-y-2 rounded-lg border border-rule bg-paper-elev p-3"
|
|
71
|
+
>
|
|
72
|
+
{renderHeader?.(item)}
|
|
73
|
+
<dl className="space-y-1.5">
|
|
74
|
+
{getFields(item).map((field) => (
|
|
75
|
+
<div
|
|
76
|
+
key={field.key ?? field.label}
|
|
77
|
+
{...field.rowAttributes}
|
|
78
|
+
className="flex justify-between gap-3 text-sm"
|
|
79
|
+
>
|
|
80
|
+
<dt className="shrink-0 text-ink-3">{field.label}</dt>
|
|
81
|
+
<dd className="text-right text-ink-2">{field.value}</dd>
|
|
82
|
+
</div>
|
|
83
|
+
))}
|
|
84
|
+
</dl>
|
|
85
|
+
{actions ? (
|
|
86
|
+
<div className="flex items-center justify-end gap-2 border-t border-rule/50 pt-2">
|
|
87
|
+
{actions}
|
|
88
|
+
</div>
|
|
89
|
+
) : null}
|
|
90
|
+
{detail}
|
|
91
|
+
</li>
|
|
92
|
+
);
|
|
93
|
+
})}
|
|
94
|
+
</ul>
|
|
95
|
+
);
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
export default RecordCardList;
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { FileQuestion, type LucideIcon } from 'lucide-react';
|
|
2
2
|
import { type ReactNode } from 'react';
|
|
3
3
|
|
|
4
|
-
import { useHostBridge, type PageBackTarget } from '../../lib/biome-host';
|
|
5
4
|
import EmptyState from './EmptyState';
|
|
5
|
+
import { useHostBridge, type PageBackTarget } from '../../lib/biome-host';
|
|
6
6
|
import { Tabs, TabsList, TabsTrigger } from '../primitives/tabs';
|
|
7
7
|
|
|
8
8
|
interface TabDef {
|
|
@@ -63,7 +63,13 @@ export default function PageShell({
|
|
|
63
63
|
// Single source of truth for the topbar title. Pages that bypass
|
|
64
64
|
// PageShell call the page-meta hook directly; PageShell wraps the same
|
|
65
65
|
// hook so consumers don't need to register meta twice.
|
|
66
|
-
useHostBridge().pageMeta.usePageMeta({
|
|
66
|
+
useHostBridge().pageMeta.usePageMeta({
|
|
67
|
+
title,
|
|
68
|
+
description,
|
|
69
|
+
eyebrow,
|
|
70
|
+
backTo,
|
|
71
|
+
topbarActions,
|
|
72
|
+
});
|
|
67
73
|
if (embedded) {
|
|
68
74
|
// Embedded mode: the host page already provides the title + tabs +
|
|
69
75
|
// context, so we render ONLY the child content + any sub-tab strip +
|
|
@@ -75,7 +81,11 @@ export default function PageShell({
|
|
|
75
81
|
<div className="shrink-0 border-b border-rule bg-paper-elev/40">
|
|
76
82
|
<div className="flex items-center gap-3 px-4 py-2 lg:px-6">
|
|
77
83
|
{tabs && tabs.length > 0 && (
|
|
78
|
-
<Tabs
|
|
84
|
+
<Tabs
|
|
85
|
+
value={activeTab}
|
|
86
|
+
onValueChange={onTabChange}
|
|
87
|
+
className="flex-1 min-w-0"
|
|
88
|
+
>
|
|
79
89
|
<div className="overflow-x-auto">
|
|
80
90
|
<TabsList className="h-7 bg-transparent p-0 gap-0">
|
|
81
91
|
{tabs.map((tab) => (
|
|
@@ -86,7 +96,9 @@ export default function PageShell({
|
|
|
86
96
|
>
|
|
87
97
|
{tab.label}
|
|
88
98
|
{tab.count !== undefined && (
|
|
89
|
-
<span className="ml-1.5 text-caption tabular-nums opacity-70">
|
|
99
|
+
<span className="ml-1.5 text-caption tabular-nums opacity-70">
|
|
100
|
+
{tab.count}
|
|
101
|
+
</span>
|
|
90
102
|
)}
|
|
91
103
|
{tab.indicator && (
|
|
92
104
|
<span className="ml-1.5 inline-block h-1.5 w-1.5 rounded-full bg-warning" />
|
|
@@ -98,12 +110,18 @@ export default function PageShell({
|
|
|
98
110
|
</Tabs>
|
|
99
111
|
)}
|
|
100
112
|
{!tabs && <div className="flex-1" />}
|
|
101
|
-
{actions &&
|
|
113
|
+
{actions && (
|
|
114
|
+
<div className="flex items-center gap-2 shrink-0">
|
|
115
|
+
{actions}
|
|
116
|
+
</div>
|
|
117
|
+
)}
|
|
102
118
|
</div>
|
|
103
119
|
</div>
|
|
104
120
|
) : null}
|
|
105
121
|
<div className="flex-1 overflow-auto min-h-0">
|
|
106
|
-
<div className="flex h-full min-h-0 flex-col px-4 pb-4 pt-3 lg:px-6">
|
|
122
|
+
<div className="flex h-full min-h-0 flex-col px-4 pb-4 pt-3 lg:px-6">
|
|
123
|
+
{children}
|
|
124
|
+
</div>
|
|
107
125
|
</div>
|
|
108
126
|
</div>
|
|
109
127
|
);
|
|
@@ -116,7 +134,11 @@ export default function PageShell({
|
|
|
116
134
|
<div className="shrink-0 border-b border-border/50 px-4 sm:px-5 lg:px-8">
|
|
117
135
|
<div className="flex min-h-[34px] flex-col gap-2 py-1.5 sm:flex-row sm:items-center sm:gap-3 sm:py-0">
|
|
118
136
|
{tabs && tabs.length > 0 && (
|
|
119
|
-
<Tabs
|
|
137
|
+
<Tabs
|
|
138
|
+
value={activeTab}
|
|
139
|
+
onValueChange={onTabChange}
|
|
140
|
+
className="flex-1 min-w-0"
|
|
141
|
+
>
|
|
120
142
|
<div className="overflow-x-auto">
|
|
121
143
|
<TabsList className="h-7 bg-transparent p-0 gap-0">
|
|
122
144
|
{tabs.map((tab) => (
|
|
@@ -127,7 +149,9 @@ export default function PageShell({
|
|
|
127
149
|
>
|
|
128
150
|
{tab.label}
|
|
129
151
|
{tab.count !== undefined && (
|
|
130
|
-
<span className="ml-1.5 text-caption tabular-nums opacity-60">
|
|
152
|
+
<span className="ml-1.5 text-caption tabular-nums opacity-60">
|
|
153
|
+
{tab.count}
|
|
154
|
+
</span>
|
|
131
155
|
)}
|
|
132
156
|
{tab.indicator && (
|
|
133
157
|
<span className="ml-1.5 inline-block h-1.5 w-1.5 rounded-full bg-warning" />
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import type { ReactNode } from 'react';
|
|
2
|
-
|
|
3
1
|
import { cn } from '../cn';
|
|
4
2
|
import { getStatusStyle } from '../design-tokens';
|
|
5
3
|
import { Badge } from '../primitives/badge';
|
|
6
4
|
|
|
5
|
+
import type { ReactNode } from 'react';
|
|
6
|
+
|
|
7
7
|
export type StatusBadgeSize = 'xs' | 'sm' | 'md';
|
|
8
8
|
|
|
9
9
|
export interface StatusBadgeProps {
|
|
@@ -68,8 +68,12 @@ export default function StatusBadge({
|
|
|
68
68
|
className,
|
|
69
69
|
)}
|
|
70
70
|
>
|
|
71
|
-
{dot &&
|
|
72
|
-
|
|
71
|
+
{dot && (
|
|
72
|
+
<span className={cn('shrink-0 rounded-full', sz.dot, style.dot)} />
|
|
73
|
+
)}
|
|
74
|
+
{children ?? (
|
|
75
|
+
<span className="capitalize">{status.replace(/_/g, ' ')}</span>
|
|
76
|
+
)}
|
|
73
77
|
</Badge>
|
|
74
78
|
);
|
|
75
79
|
}
|
package/src/ui/design-tokens.ts
CHANGED
|
@@ -142,8 +142,16 @@ export const STATUS_STYLES: Record<string, StatusStyle> = {
|
|
|
142
142
|
manual_review: WARNING_STYLE,
|
|
143
143
|
};
|
|
144
144
|
|
|
145
|
+
/**
|
|
146
|
+
* Style for an unrecognised status. Same value `STATUS_STYLES.pending` carries —
|
|
147
|
+
* referenced as the fragment rather than re-read out of the open `Record`, so
|
|
148
|
+
* the fallback is structurally guaranteed instead of being a second lookup that
|
|
149
|
+
* can itself miss (e.g. if the `pending` key were ever renamed).
|
|
150
|
+
*/
|
|
151
|
+
const DEFAULT_STATUS_STYLE: StatusStyle = INFO_STYLE;
|
|
152
|
+
|
|
145
153
|
export function getStatusStyle(status: string): StatusStyle {
|
|
146
|
-
return STATUS_STYLES[status] ??
|
|
154
|
+
return STATUS_STYLES[status] ?? DEFAULT_STATUS_STYLE;
|
|
147
155
|
}
|
|
148
156
|
|
|
149
157
|
// ── Priority Styles ────────────────────────────────────────────────
|
|
@@ -156,6 +164,17 @@ export interface PriorityStyle {
|
|
|
156
164
|
label: string;
|
|
157
165
|
}
|
|
158
166
|
|
|
167
|
+
// Lowest priority — also the style for an unrecognised priority. Named so the
|
|
168
|
+
// map entry and `getPriorityStyle`'s fallback are the same proven value rather
|
|
169
|
+
// than a second `Record` lookup that can itself miss.
|
|
170
|
+
const PRIORITY_LOW_STYLE: PriorityStyle = {
|
|
171
|
+
badge: 'bg-paper-elev text-ink-3 border-border',
|
|
172
|
+
text: 'text-ink-3',
|
|
173
|
+
bg: 'bg-muted/30',
|
|
174
|
+
border: 'border-border',
|
|
175
|
+
label: 'Low',
|
|
176
|
+
};
|
|
177
|
+
|
|
159
178
|
export const PRIORITY_STYLES: Record<string, PriorityStyle> = {
|
|
160
179
|
p0: {
|
|
161
180
|
badge: 'bg-destructive text-white border-destructive',
|
|
@@ -178,17 +197,11 @@ export const PRIORITY_STYLES: Record<string, PriorityStyle> = {
|
|
|
178
197
|
border: 'border-warning/30',
|
|
179
198
|
label: 'Medium',
|
|
180
199
|
},
|
|
181
|
-
p3:
|
|
182
|
-
badge: 'bg-paper-elev text-ink-3 border-border',
|
|
183
|
-
text: 'text-ink-3',
|
|
184
|
-
bg: 'bg-muted/30',
|
|
185
|
-
border: 'border-border',
|
|
186
|
-
label: 'Low',
|
|
187
|
-
},
|
|
200
|
+
p3: PRIORITY_LOW_STYLE,
|
|
188
201
|
};
|
|
189
202
|
|
|
190
203
|
export function getPriorityStyle(priority: string): PriorityStyle {
|
|
191
|
-
return PRIORITY_STYLES[priority] ??
|
|
204
|
+
return PRIORITY_STYLES[priority] ?? PRIORITY_LOW_STYLE;
|
|
192
205
|
}
|
|
193
206
|
|
|
194
207
|
// ── Severity Styles ────────────────────────────────────────────────
|
|
@@ -285,15 +298,28 @@ export const IMPORTANCE_STYLES: Record<number, { badge: string; label: string; s
|
|
|
285
298
|
|
|
286
299
|
// ── Risk Level Styles ──────────────────────────────────────────────
|
|
287
300
|
|
|
288
|
-
export
|
|
289
|
-
|
|
301
|
+
export interface RiskLevelStyle {
|
|
302
|
+
badge: string;
|
|
303
|
+
text: string;
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
// Lowest risk — also the style for an unrecognised level. Named for the same
|
|
307
|
+
// reason as PRIORITY_LOW_STYLE: the fallback must be a proven value, not a
|
|
308
|
+
// second lookup into the open `Record`.
|
|
309
|
+
const RISK_LOW_STYLE: RiskLevelStyle = {
|
|
310
|
+
badge: 'bg-success/15 text-success dark:text-success border-success/30',
|
|
311
|
+
text: 'text-success dark:text-success',
|
|
312
|
+
};
|
|
313
|
+
|
|
314
|
+
export const RISK_LEVEL_STYLES: Record<string, RiskLevelStyle> = {
|
|
315
|
+
low: RISK_LOW_STYLE,
|
|
290
316
|
medium: { badge: 'bg-warning/15 text-warning dark:text-warning border-warning/30', text: 'text-warning dark:text-warning' },
|
|
291
317
|
high: { badge: 'bg-warning/15 text-warning dark:text-warning border-warning/30', text: 'text-warning dark:text-warning' },
|
|
292
318
|
critical: { badge: 'bg-destructive/15 text-destructive dark:text-destructive border-destructive/30', text: 'text-destructive dark:text-destructive' },
|
|
293
319
|
};
|
|
294
320
|
|
|
295
|
-
export function getRiskLevelStyle(level: string):
|
|
296
|
-
return RISK_LEVEL_STYLES[level] ??
|
|
321
|
+
export function getRiskLevelStyle(level: string): RiskLevelStyle {
|
|
322
|
+
return RISK_LEVEL_STYLES[level] ?? RISK_LOW_STYLE;
|
|
297
323
|
}
|
|
298
324
|
|
|
299
325
|
// ── Agent Source Styles ────────────────────────────────────────────
|
package/src/ui/index.ts
CHANGED
|
@@ -92,6 +92,11 @@ export {
|
|
|
92
92
|
type EmptyStateLinkComponent,
|
|
93
93
|
} from './chrome/EmptyState';
|
|
94
94
|
export { StateCard } from './chrome/StateCard';
|
|
95
|
+
export {
|
|
96
|
+
RecordCardList,
|
|
97
|
+
type RecordCardField,
|
|
98
|
+
type RecordCardListProps,
|
|
99
|
+
} from './chrome/RecordCardList';
|
|
95
100
|
export { default as PageHeader, PageToolbar } from './chrome/PageHeader';
|
|
96
101
|
export { default as LoadingState, type LoadingStateVariant } from './chrome/LoadingState';
|
|
97
102
|
export { default as AsyncBoundary } from './chrome/AsyncBoundary';
|