@xemahq/ui-kernel 0.8.0 → 0.9.1
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/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +6 -21
- package/dist/index.js.map +1 -1
- package/dist/lib/biome-host/agent-validation.js +5 -9
- package/dist/lib/biome-host/agent-validation.js.map +1 -1
- package/dist/lib/biome-host/biome-builders.js +5 -9
- package/dist/lib/biome-host/biome-builders.js.map +1 -1
- package/dist/lib/biome-host/biome-mode.js +1 -2
- package/dist/lib/biome-host/biome-navigation.js +6 -10
- package/dist/lib/biome-host/biome-navigation.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 -29
- package/dist/lib/biome-host/biome-registry.js.map +1 -1
- package/dist/lib/biome-host/biome-scope.js +9 -14
- package/dist/lib/biome-host/biome-scope.js.map +1 -1
- package/dist/lib/biome-host/biome-scoped-query.js +8 -13
- package/dist/lib/biome-host/biome-scoped-query.js.map +1 -1
- package/dist/lib/biome-host/create-biome-orval-config.js +1 -4
- package/dist/lib/biome-host/create-biome-orval-config.js.map +1 -1
- package/dist/lib/biome-host/define-web-biome.js +3 -6
- package/dist/lib/biome-host/define-web-biome.js.map +1 -1
- package/dist/lib/biome-host/errors.js +1 -4
- package/dist/lib/biome-host/errors.js.map +1 -1
- package/dist/lib/biome-host/frontend-biome.js +3 -6
- package/dist/lib/biome-host/frontend-biome.js.map +1 -1
- package/dist/lib/biome-host/host-bridge.js +5 -9
- package/dist/lib/biome-host/host-bridge.js.map +1 -1
- package/dist/lib/biome-host/host-sources.js +1 -2
- package/dist/lib/biome-host/i18n-hooks.js +5 -9
- package/dist/lib/biome-host/i18n-hooks.js.map +1 -1
- package/dist/lib/biome-host/i18n-port.js +1 -4
- package/dist/lib/biome-host/i18n-port.js.map +1 -1
- package/dist/lib/biome-host/index.js +22 -38
- package/dist/lib/biome-host/index.js.map +1 -1
- package/dist/lib/biome-host/realtime-hooks.js +7 -12
- package/dist/lib/biome-host/realtime-hooks.js.map +1 -1
- package/dist/lib/biome-host/realtime-port.js +1 -2
- package/dist/lib/biome-host/response-envelope.js +2 -6
- package/dist/lib/biome-host/response-envelope.js.map +1 -1
- package/dist/lib/biome-host/session-contributions.js +1 -2
- package/dist/lib/biome-host/session-profiles.js +7 -11
- package/dist/lib/biome-host/session-profiles.js.map +1 -1
- package/dist/lib/biome-host/use-mutation-with-error-toast.js +7 -10
- package/dist/lib/biome-host/use-mutation-with-error-toast.js.map +1 -1
- package/dist/lib/biome-host/use-page-state.js +16 -21
- package/dist/lib/biome-host/use-page-state.js.map +1 -1
- package/dist/lib/capabilities/capability-provider.js +11 -15
- package/dist/lib/capabilities/capability-provider.js.map +1 -1
- package/dist/lib/capabilities/index.js +3 -19
- package/dist/lib/capabilities/index.js.map +1 -1
- package/dist/lib/capabilities/types.js +1 -2
- package/dist/lib/capabilities/use-capability.js +5 -9
- package/dist/lib/capabilities/use-capability.js.map +1 -1
- package/dist/lib/contribution-registry/contribution-registry.d.ts +24 -0
- package/dist/lib/contribution-registry/contribution-registry.d.ts.map +1 -0
- package/dist/lib/contribution-registry/contribution-registry.js +67 -0
- package/dist/lib/contribution-registry/contribution-registry.js.map +1 -0
- package/dist/lib/contribution-registry/index.d.ts +3 -0
- package/dist/lib/contribution-registry/index.d.ts.map +1 -0
- package/dist/lib/contribution-registry/index.js +3 -0
- package/dist/lib/contribution-registry/index.js.map +1 -0
- package/dist/lib/contribution-registry/renderable-registry.d.ts +33 -0
- package/dist/lib/contribution-registry/renderable-registry.d.ts.map +1 -0
- package/dist/lib/contribution-registry/renderable-registry.js +51 -0
- package/dist/lib/contribution-registry/renderable-registry.js.map +1 -0
- package/dist/lib/system-bus/capability-invoke.js +1 -2
- package/dist/lib/system-bus/deeplink.js +12 -17
- package/dist/lib/system-bus/deeplink.js.map +1 -1
- package/dist/lib/system-bus/enums.js +10 -13
- package/dist/lib/system-bus/enums.js.map +1 -1
- package/dist/lib/system-bus/host-ports.js +1 -2
- package/dist/lib/system-bus/index.js +10 -26
- package/dist/lib/system-bus/index.js.map +1 -1
- package/dist/lib/system-bus/intent-registry.js +6 -10
- package/dist/lib/system-bus/intent-registry.js.map +1 -1
- package/dist/lib/system-bus/intents.js +1 -2
- package/dist/lib/system-bus/palette.js +1 -2
- package/dist/lib/system-bus/system-bus-builder.js +10 -13
- package/dist/lib/system-bus/system-bus-builder.js.map +1 -1
- package/dist/lib/system-bus/system-bus.js +1 -2
- package/dist/lib/system-bus/windows.js +1 -2
- package/dist/offline/id.js +1 -4
- package/dist/offline/id.js.map +1 -1
- package/dist/offline/index.js +8 -25
- package/dist/offline/index.js.map +1 -1
- package/dist/offline/mutation.js +5 -8
- package/dist/offline/mutation.js.map +1 -1
- package/dist/offline/offline-status-badge.js +7 -10
- package/dist/offline/offline-status-badge.js.map +1 -1
- package/dist/offline/online-controller.js +2 -7
- package/dist/offline/online-controller.js.map +1 -1
- package/dist/offline/outbox.js +22 -26
- package/dist/offline/outbox.js.map +1 -1
- package/dist/offline/react.js +15 -21
- package/dist/offline/react.js.map +1 -1
- package/dist/offline/storage.js +3 -9
- package/dist/offline/storage.js.map +1 -1
- package/dist/offline/types.js +2 -5
- package/dist/offline/types.js.map +1 -1
- package/dist/org-db/components/DbResultTable.js +7 -10
- package/dist/org-db/components/DbResultTable.js.map +1 -1
- package/dist/org-db/index.js +1 -5
- package/dist/org-db/index.js.map +1 -1
- package/dist/pdf/index.d.ts +2 -0
- package/dist/pdf/index.d.ts.map +1 -0
- package/dist/pdf/index.js +2 -0
- package/dist/pdf/index.js.map +1 -0
- package/dist/registry/index.js +8 -24
- package/dist/registry/index.js.map +1 -1
- package/dist/registry/lib/agent-validation-host.js +5 -8
- package/dist/registry/lib/agent-validation-host.js.map +1 -1
- package/dist/registry/lib/biome-slot.js +9 -12
- package/dist/registry/lib/biome-slot.js.map +1 -1
- package/dist/registry/lib/biomes-enabled-context.js +5 -9
- package/dist/registry/lib/biomes-enabled-context.js.map +1 -1
- package/dist/registry/lib/extension-points.js +1 -4
- package/dist/registry/lib/extension-points.js.map +1 -1
- package/dist/registry/lib/primitives/SessionEventCard.js +7 -10
- package/dist/registry/lib/primitives/SessionEventCard.js.map +1 -1
- package/dist/registry/lib/primitives/SessionEventTimeline.js +9 -12
- package/dist/registry/lib/primitives/SessionEventTimeline.js.map +1 -1
- package/dist/registry/lib/primitives/SessionMutationBar.js +3 -6
- package/dist/registry/lib/primitives/SessionMutationBar.js.map +1 -1
- package/dist/registry/lib/primitives/SessionTabbedDrawer.js +11 -14
- package/dist/registry/lib/primitives/SessionTabbedDrawer.js.map +1 -1
- package/dist/registry/lib/primitives/index.js +4 -20
- package/dist/registry/lib/primitives/index.js.map +1 -1
- package/dist/registry/lib/session-context-builder.js +6 -10
- package/dist/registry/lib/session-context-builder.js.map +1 -1
- package/dist/registry/lib/session-context-provider.js +9 -14
- package/dist/registry/lib/session-context-provider.js.map +1 -1
- package/dist/registry/lib/session-selectors.js +30 -39
- package/dist/registry/lib/session-selectors.js.map +1 -1
- package/dist/session/comments/CommentRail.js +6 -9
- package/dist/session/comments/CommentRail.js.map +1 -1
- package/dist/session/index.js +3 -9
- package/dist/session/index.js.map +1 -1
- package/dist/session/lib/cn.js +4 -7
- package/dist/session/lib/cn.js.map +1 -1
- package/dist/session/shell/SessionWorkspaceShell.js +5 -8
- package/dist/session/shell/SessionWorkspaceShell.js.map +1 -1
- package/dist/session-kit/approvals/ApprovalButton.js +3 -6
- package/dist/session-kit/approvals/ApprovalButton.js.map +1 -1
- package/dist/session-kit/approvals/ApprovalCard.js +30 -33
- package/dist/session-kit/approvals/ApprovalCard.js.map +1 -1
- package/dist/session-kit/approvals/ApprovalsCenter.js +29 -32
- package/dist/session-kit/approvals/ApprovalsCenter.js.map +1 -1
- package/dist/session-kit/approvals/CapabilityApprovalStickyBar.js +12 -15
- package/dist/session-kit/approvals/CapabilityApprovalStickyBar.js.map +1 -1
- package/dist/session-kit/approvals/Obligation.js +12 -16
- package/dist/session-kit/approvals/Obligation.js.map +1 -1
- package/dist/session-kit/approvals/ScopedBody.js +34 -37
- package/dist/session-kit/approvals/ScopedBody.js.map +1 -1
- package/dist/session-kit/approvals/approval-icons.js +1 -2
- package/dist/session-kit/approvals/approval-model.js +6 -11
- package/dist/session-kit/approvals/approval-model.js.map +1 -1
- package/dist/session-kit/approvals/index.js +11 -27
- package/dist/session-kit/approvals/index.js.map +1 -1
- package/dist/session-kit/approvals/obligation-display.js +13 -16
- package/dist/session-kit/approvals/obligation-display.js.map +1 -1
- package/dist/session-kit/approvals/risk-accent.js +6 -9
- package/dist/session-kit/approvals/risk-accent.js.map +1 -1
- package/dist/session-kit/approvals/scope-icons.js +2 -5
- package/dist/session-kit/approvals/scope-icons.js.map +1 -1
- package/dist/session-kit/combobox/Combobox.js +19 -22
- package/dist/session-kit/combobox/Combobox.js.map +1 -1
- package/dist/session-kit/combobox/use-click-outside.js +4 -7
- package/dist/session-kit/combobox/use-click-outside.js.map +1 -1
- package/dist/session-kit/display/ContextHeader.js +10 -13
- package/dist/session-kit/display/ContextHeader.js.map +1 -1
- package/dist/session-kit/display/FileDiffCard.js +11 -14
- package/dist/session-kit/display/FileDiffCard.js.map +1 -1
- package/dist/session-kit/display/MD.js +14 -17
- package/dist/session-kit/display/MD.js.map +1 -1
- package/dist/session-kit/display/MessageTurn.js +20 -23
- package/dist/session-kit/display/MessageTurn.js.map +1 -1
- package/dist/session-kit/display/ThinkingPanel.js +7 -10
- package/dist/session-kit/display/ThinkingPanel.js.map +1 -1
- package/dist/session-kit/display/TodoChecklist.js +13 -16
- package/dist/session-kit/display/TodoChecklist.js.map +1 -1
- package/dist/session-kit/display/TokenMeter.js +8 -11
- package/dist/session-kit/display/TokenMeter.js.map +1 -1
- package/dist/session-kit/display/ToolStrip.js +26 -30
- package/dist/session-kit/display/ToolStrip.js.map +1 -1
- package/dist/session-kit/display/TypingDots.js +3 -6
- package/dist/session-kit/display/TypingDots.js.map +1 -1
- package/dist/session-kit/index.js +20 -36
- package/dist/session-kit/index.js.map +1 -1
- package/dist/session-kit/lib/enums.js +14 -17
- package/dist/session-kit/lib/enums.js.map +1 -1
- package/dist/session-kit/lib/portal-accent.js +1 -4
- package/dist/session-kit/lib/portal-accent.js.map +1 -1
- package/dist/session-kit/lib/status-dot.js +19 -24
- package/dist/session-kit/lib/status-dot.js.map +1 -1
- package/dist/session-kit/primitives/Avatar.js +3 -6
- package/dist/session-kit/primitives/Avatar.js.map +1 -1
- package/dist/session-kit/primitives/PortalGlyph.js +8 -11
- package/dist/session-kit/primitives/PortalGlyph.js.map +1 -1
- package/dist/session-kit/primitives/RiskPill.js +10 -14
- package/dist/session-kit/primitives/RiskPill.js.map +1 -1
- package/dist/session-kit/primitives/ScopeDot.js +7 -10
- package/dist/session-kit/primitives/ScopeDot.js.map +1 -1
- package/dist/session-kit/primitives/Segmented.js +4 -7
- package/dist/session-kit/primitives/Segmented.js.map +1 -1
- package/dist/ui/branding/app-branding-provider.js +13 -51
- package/dist/ui/branding/app-branding-provider.js.map +1 -1
- package/dist/ui/branding/sanitize.js +3 -8
- package/dist/ui/branding/sanitize.js.map +1 -1
- package/dist/ui/breakpoints.js +1 -4
- package/dist/ui/breakpoints.js.map +1 -1
- package/dist/ui/capture/document-preview.js +16 -19
- package/dist/ui/capture/document-preview.js.map +1 -1
- package/dist/ui/capture/field-spec-to-zod.d.ts +1 -0
- package/dist/ui/capture/field-spec-to-zod.d.ts.map +1 -1
- package/dist/ui/capture/field-spec-to-zod.js +51 -36
- package/dist/ui/capture/field-spec-to-zod.js.map +1 -1
- package/dist/ui/capture/field-spec-validate.d.ts +4 -0
- package/dist/ui/capture/field-spec-validate.d.ts.map +1 -0
- package/dist/ui/capture/field-spec-validate.js +129 -0
- package/dist/ui/capture/field-spec-validate.js.map +1 -0
- package/dist/ui/capture/field-spec.d.ts +13 -1
- package/dist/ui/capture/field-spec.d.ts.map +1 -1
- package/dist/ui/capture/field-spec.js +31 -13
- package/dist/ui/capture/field-spec.js.map +1 -1
- package/dist/ui/capture/index.d.ts +4 -2
- package/dist/ui/capture/index.d.ts.map +1 -1
- package/dist/ui/capture/index.js +12 -30
- package/dist/ui/capture/index.js.map +1 -1
- package/dist/ui/capture/schema-field-input.d.ts.map +1 -1
- package/dist/ui/capture/schema-field-input.js +82 -58
- package/dist/ui/capture/schema-field-input.js.map +1 -1
- package/dist/ui/capture/schema-form.js +11 -14
- package/dist/ui/capture/schema-form.js.map +1 -1
- package/dist/ui/capture/submit-values.d.ts +6 -0
- package/dist/ui/capture/submit-values.d.ts.map +1 -0
- package/dist/ui/capture/submit-values.js +28 -0
- package/dist/ui/capture/submit-values.js.map +1 -0
- package/dist/ui/capture/use-prefill.js +13 -16
- package/dist/ui/capture/use-prefill.js.map +1 -1
- package/dist/ui/capture/use-schema-validation.js +13 -16
- package/dist/ui/capture/use-schema-validation.js.map +1 -1
- package/dist/ui/capture/use-wizard.js +15 -18
- package/dist/ui/capture/use-wizard.js.map +1 -1
- package/dist/ui/capture/value-format.js +4 -8
- package/dist/ui/capture/value-format.js.map +1 -1
- package/dist/ui/capture/wizard.js +10 -14
- package/dist/ui/capture/wizard.js.map +1 -1
- package/dist/ui/charts/bar-chart.js +14 -17
- package/dist/ui/charts/bar-chart.js.map +1 -1
- package/dist/ui/charts/chart-frame.js +11 -16
- package/dist/ui/charts/chart-frame.js.map +1 -1
- package/dist/ui/charts/chart-types.js +1 -2
- package/dist/ui/charts/chart-utils.js +7 -15
- package/dist/ui/charts/chart-utils.js.map +1 -1
- package/dist/ui/charts/donut-chart.js +11 -14
- package/dist/ui/charts/donut-chart.js.map +1 -1
- package/dist/ui/charts/index.js +6 -20
- package/dist/ui/charts/index.js.map +1 -1
- package/dist/ui/charts/line-chart.js +15 -18
- package/dist/ui/charts/line-chart.js.map +1 -1
- package/dist/ui/charts/sparkline.js +9 -12
- package/dist/ui/charts/sparkline.js.map +1 -1
- package/dist/ui/chrome/AsyncBoundary.js +9 -15
- package/dist/ui/chrome/AsyncBoundary.js.map +1 -1
- package/dist/ui/chrome/EmptyState.js +9 -12
- package/dist/ui/chrome/EmptyState.js.map +1 -1
- package/dist/ui/chrome/ErrorCard.js +8 -11
- package/dist/ui/chrome/ErrorCard.js.map +1 -1
- package/dist/ui/chrome/LoadingState.js +8 -11
- package/dist/ui/chrome/LoadingState.js.map +1 -1
- package/dist/ui/chrome/PageHeader.js +10 -14
- package/dist/ui/chrome/PageHeader.js.map +1 -1
- package/dist/ui/chrome/StateCard.js +7 -11
- package/dist/ui/chrome/StateCard.js.map +1 -1
- package/dist/ui/chrome/confirm-delete-dialog.js +5 -8
- package/dist/ui/chrome/confirm-delete-dialog.js.map +1 -1
- package/dist/ui/chrome/page-shell.js +9 -15
- package/dist/ui/chrome/page-shell.js.map +1 -1
- package/dist/ui/chrome/scope-badge.js +5 -8
- package/dist/ui/chrome/scope-badge.js.map +1 -1
- package/dist/ui/chrome/status-badge.js +7 -10
- package/dist/ui/chrome/status-badge.js.map +1 -1
- package/dist/ui/cn.js +5 -8
- package/dist/ui/cn.js.map +1 -1
- package/dist/ui/design-tokens.js +21 -28
- package/dist/ui/design-tokens.js.map +1 -1
- package/dist/ui/hooks/use-debounced-value.js +4 -7
- package/dist/ui/hooks/use-debounced-value.js.map +1 -1
- package/dist/ui/hooks/use-is-mobile.js +8 -11
- package/dist/ui/hooks/use-is-mobile.js.map +1 -1
- package/dist/ui/index.d.ts +1 -1
- package/dist/ui/index.d.ts.map +1 -1
- package/dist/ui/index.js +47 -87
- package/dist/ui/index.js.map +1 -1
- package/dist/ui/pdf/pdf-preview.js +17 -20
- package/dist/ui/pdf/pdf-preview.js.map +1 -1
- package/dist/ui/primitives/alert-dialog.js +14 -60
- package/dist/ui/primitives/alert-dialog.js.map +1 -1
- package/dist/ui/primitives/async-combobox.js +18 -21
- package/dist/ui/primitives/async-combobox.js.map +1 -1
- package/dist/ui/primitives/badge.js +7 -44
- package/dist/ui/primitives/badge.js.map +1 -1
- package/dist/ui/primitives/button.js +9 -46
- package/dist/ui/primitives/button.js.map +1 -1
- package/dist/ui/primitives/card.js +10 -51
- package/dist/ui/primitives/card.js.map +1 -1
- package/dist/ui/primitives/checkbox.js +7 -43
- package/dist/ui/primitives/checkbox.js.map +1 -1
- package/dist/ui/primitives/collapsible.js +2 -40
- package/dist/ui/primitives/collapsible.js.map +1 -1
- package/dist/ui/primitives/dialog.js +12 -57
- package/dist/ui/primitives/dialog.js.map +1 -1
- package/dist/ui/primitives/dropdown-menu.js +15 -65
- package/dist/ui/primitives/dropdown-menu.js.map +1 -1
- package/dist/ui/primitives/form-stepper.js +8 -12
- package/dist/ui/primitives/form-stepper.js.map +1 -1
- package/dist/ui/primitives/input.js +5 -41
- package/dist/ui/primitives/input.js.map +1 -1
- package/dist/ui/primitives/label.js +8 -44
- package/dist/ui/primitives/label.js.map +1 -1
- package/dist/ui/primitives/overflow-tabs.d.ts +5 -0
- package/dist/ui/primitives/overflow-tabs.d.ts.map +1 -1
- package/dist/ui/primitives/overflow-tabs.js +19 -22
- package/dist/ui/primitives/overflow-tabs.js.map +1 -1
- package/dist/ui/primitives/popover.js +6 -44
- package/dist/ui/primitives/popover.js.map +1 -1
- package/dist/ui/primitives/preview-device-frame.js +16 -19
- package/dist/ui/primitives/preview-device-frame.js.map +1 -1
- package/dist/ui/primitives/radio-group.js +8 -45
- package/dist/ui/primitives/radio-group.js.map +1 -1
- package/dist/ui/primitives/resizable.js +11 -16
- package/dist/ui/primitives/resizable.js.map +1 -1
- package/dist/ui/primitives/scroll-area.js +7 -44
- package/dist/ui/primitives/scroll-area.js.map +1 -1
- package/dist/ui/primitives/select.js +15 -60
- package/dist/ui/primitives/select.js.map +1 -1
- package/dist/ui/primitives/separator.js +6 -42
- package/dist/ui/primitives/separator.js.map +1 -1
- package/dist/ui/primitives/sheet.js +14 -59
- package/dist/ui/primitives/sheet.js.map +1 -1
- package/dist/ui/primitives/skeleton.js +5 -7
- package/dist/ui/primitives/skeleton.js.map +1 -1
- package/dist/ui/primitives/switch.js +6 -42
- package/dist/ui/primitives/switch.js.map +1 -1
- package/dist/ui/primitives/table.js +12 -55
- package/dist/ui/primitives/table.js.map +1 -1
- package/dist/ui/primitives/tabs.js +8 -47
- package/dist/ui/primitives/tabs.js.map +1 -1
- package/dist/ui/primitives/tag-multi-select.js +24 -27
- package/dist/ui/primitives/tag-multi-select.js.map +1 -1
- package/dist/ui/primitives/textarea.js +5 -41
- package/dist/ui/primitives/textarea.js.map +1 -1
- package/dist/ui/primitives/tooltip.js +6 -45
- package/dist/ui/primitives/tooltip.js.map +1 -1
- package/dist/ui/primitives/url-preview-chrome.d.ts +8 -0
- package/dist/ui/primitives/url-preview-chrome.d.ts.map +1 -0
- package/dist/ui/primitives/url-preview-chrome.js +40 -0
- package/dist/ui/primitives/url-preview-chrome.js.map +1 -0
- package/dist/vista/GenericCatalogueSurface.d.ts +10 -0
- package/dist/vista/GenericCatalogueSurface.d.ts.map +1 -0
- package/dist/vista/GenericCatalogueSurface.js +80 -0
- package/dist/vista/GenericCatalogueSurface.js.map +1 -0
- package/dist/vista/SurfaceFallbackCard.d.ts +9 -0
- package/dist/vista/SurfaceFallbackCard.d.ts.map +1 -0
- package/dist/vista/SurfaceFallbackCard.js +44 -0
- package/dist/vista/SurfaceFallbackCard.js.map +1 -0
- package/dist/vista/VistaPanel.d.ts +21 -0
- package/dist/vista/VistaPanel.d.ts.map +1 -0
- package/dist/vista/VistaPanel.js +31 -0
- package/dist/vista/VistaPanel.js.map +1 -0
- package/dist/vista/html/CustomUiFrame.d.ts +20 -0
- package/dist/vista/html/CustomUiFrame.d.ts.map +1 -0
- package/dist/vista/html/CustomUiFrame.js +69 -0
- package/dist/vista/html/CustomUiFrame.js.map +1 -0
- package/dist/vista/html/custom-ui-frame-bridge.d.ts +13 -0
- package/dist/vista/html/custom-ui-frame-bridge.d.ts.map +1 -0
- package/dist/vista/html/custom-ui-frame-bridge.js +30 -0
- package/dist/vista/html/custom-ui-frame-bridge.js.map +1 -0
- package/dist/vista/html/custom-ui-frame-contract.d.ts +29 -0
- package/dist/vista/html/custom-ui-frame-contract.d.ts.map +1 -0
- package/dist/vista/html/custom-ui-frame-contract.js +16 -0
- package/dist/vista/html/custom-ui-frame-contract.js.map +1 -0
- package/dist/vista/html/custom-ui-intents.d.ts +20 -0
- package/dist/vista/html/custom-ui-intents.d.ts.map +1 -0
- package/dist/vista/html/custom-ui-intents.js +57 -0
- package/dist/vista/html/custom-ui-intents.js.map +1 -0
- package/dist/vista/html/custom-ui-srcdoc.d.ts +17 -0
- package/dist/vista/html/custom-ui-srcdoc.d.ts.map +1 -0
- package/dist/vista/html/custom-ui-srcdoc.js +70 -0
- package/dist/vista/html/custom-ui-srcdoc.js.map +1 -0
- package/dist/vista/html/index.d.ts +6 -0
- package/dist/vista/html/index.d.ts.map +1 -0
- package/dist/vista/html/index.js +6 -0
- package/dist/vista/html/index.js.map +1 -0
- package/dist/vista/index.d.ts +18 -0
- package/dist/vista/index.d.ts.map +1 -0
- package/dist/vista/index.js +18 -0
- package/dist/vista/index.js.map +1 -0
- package/dist/vista/surface-catalogue.d.ts +5 -0
- package/dist/vista/surface-catalogue.d.ts.map +1 -0
- package/dist/vista/surface-catalogue.js +30 -0
- package/dist/vista/surface-catalogue.js.map +1 -0
- package/dist/vista/surface-icons.d.ts +7 -0
- package/dist/vista/surface-icons.d.ts.map +1 -0
- package/dist/vista/surface-icons.js +26 -0
- package/dist/vista/surface-icons.js.map +1 -0
- package/dist/vista/surface-registry.d.ts +7 -0
- package/dist/vista/surface-registry.d.ts.map +1 -0
- package/dist/vista/surface-registry.js +7 -0
- package/dist/vista/surface-registry.js.map +1 -0
- package/dist/vista/surfaces/ChartSurface.d.ts +4 -0
- package/dist/vista/surfaces/ChartSurface.d.ts.map +1 -0
- package/dist/vista/surfaces/ChartSurface.js +17 -0
- package/dist/vista/surfaces/ChartSurface.js.map +1 -0
- package/dist/vista/surfaces/FilesSurface.d.ts +15 -0
- package/dist/vista/surfaces/FilesSurface.d.ts.map +1 -0
- package/dist/vista/surfaces/FilesSurface.js +121 -0
- package/dist/vista/surfaces/FilesSurface.js.map +1 -0
- package/dist/vista/surfaces/FormSurface.d.ts +4 -0
- package/dist/vista/surfaces/FormSurface.d.ts.map +1 -0
- package/dist/vista/surfaces/FormSurface.js +97 -0
- package/dist/vista/surfaces/FormSurface.js.map +1 -0
- package/dist/vista/surfaces/HtmlSurface.d.ts +4 -0
- package/dist/vista/surfaces/HtmlSurface.d.ts.map +1 -0
- package/dist/vista/surfaces/HtmlSurface.js +11 -0
- package/dist/vista/surfaces/HtmlSurface.js.map +1 -0
- package/dist/vista/surfaces/TableSurface.d.ts +4 -0
- package/dist/vista/surfaces/TableSurface.d.ts.map +1 -0
- package/dist/vista/surfaces/TableSurface.js +42 -0
- package/dist/vista/surfaces/TableSurface.js.map +1 -0
- package/dist/vista/surfaces/UrlSurface.d.ts +4 -0
- package/dist/vista/surfaces/UrlSurface.d.ts.map +1 -0
- package/dist/vista/surfaces/UrlSurface.js +7 -0
- package/dist/vista/surfaces/UrlSurface.js.map +1 -0
- package/dist/vista/surfaces/blob-surfaces.d.ts +6 -0
- package/dist/vista/surfaces/blob-surfaces.d.ts.map +1 -0
- package/dist/vista/surfaces/blob-surfaces.js +38 -0
- package/dist/vista/surfaces/blob-surfaces.js.map +1 -0
- package/dist/vista/surfaces/elicitation-transport.d.ts +18 -0
- package/dist/vista/surfaces/elicitation-transport.d.ts.map +1 -0
- package/dist/vista/surfaces/elicitation-transport.js +100 -0
- package/dist/vista/surfaces/elicitation-transport.js.map +1 -0
- package/dist/vista/surfaces/index.d.ts +11 -0
- package/dist/vista/surfaces/index.d.ts.map +1 -0
- package/dist/vista/surfaces/index.js +89 -0
- package/dist/vista/surfaces/index.js.map +1 -0
- package/dist/vista/surfaces/text-surfaces.d.ts +8 -0
- package/dist/vista/surfaces/text-surfaces.d.ts.map +1 -0
- package/dist/vista/surfaces/text-surfaces.js +54 -0
- package/dist/vista/surfaces/text-surfaces.js.map +1 -0
- package/dist/vista/use-vista-tabs.d.ts +30 -0
- package/dist/vista/use-vista-tabs.d.ts.map +1 -0
- package/dist/vista/use-vista-tabs.js +77 -0
- package/dist/vista/use-vista-tabs.js.map +1 -0
- package/dist/vista/vista-code-renderer.d.ts +12 -0
- package/dist/vista/vista-code-renderer.d.ts.map +1 -0
- package/dist/vista/vista-code-renderer.js +10 -0
- package/dist/vista/vista-code-renderer.js.map +1 -0
- package/dist/vista/vista-file-source.d.ts +20 -0
- package/dist/vista/vista-file-source.d.ts.map +1 -0
- package/dist/vista/vista-file-source.js +69 -0
- package/dist/vista/vista-file-source.js.map +1 -0
- package/dist/vista/vista-form-host.d.ts +16 -0
- package/dist/vista/vista-form-host.d.ts.map +1 -0
- package/dist/vista/vista-form-host.js +10 -0
- package/dist/vista/vista-form-host.js.map +1 -0
- package/dist/vista/vista-model.d.ts +12 -0
- package/dist/vista/vista-model.d.ts.map +1 -0
- package/dist/vista/vista-model.js +72 -0
- package/dist/vista/vista-model.js.map +1 -0
- package/dist/vista/vista-open-context.d.ts +9 -0
- package/dist/vista/vista-open-context.d.ts.map +1 -0
- package/dist/vista/vista-open-context.js +10 -0
- package/dist/vista/vista-open-context.js.map +1 -0
- package/dist/vista/vista-payloads.d.ts +107 -0
- package/dist/vista/vista-payloads.d.ts.map +1 -0
- package/dist/vista/vista-payloads.js +305 -0
- package/dist/vista/vista-payloads.js.map +1 -0
- package/dist/vista/vista-tabs-manifest.d.ts +17 -0
- package/dist/vista/vista-tabs-manifest.d.ts.map +1 -0
- package/dist/vista/vista-tabs-manifest.js +60 -0
- package/dist/vista/vista-tabs-manifest.js.map +1 -0
- package/dist/vista/vista-tools.d.ts +41 -0
- package/dist/vista/vista-tools.d.ts.map +1 -0
- package/dist/vista/vista-tools.js +113 -0
- package/dist/vista/vista-tools.js.map +1 -0
- package/package.json +10 -3
- package/src/index.ts +5 -0
- package/src/lib/biome-host/biome-registry.ts +31 -11
- package/src/lib/contribution-registry/contribution-registry.spec.ts +141 -0
- package/src/lib/contribution-registry/contribution-registry.ts +202 -0
- package/src/lib/contribution-registry/index.ts +9 -0
- package/src/lib/contribution-registry/renderable-registry.ts +142 -0
- package/src/pdf/index.ts +11 -0
- package/src/ui/capture/field-spec-to-zod.ts +22 -0
- package/src/ui/capture/field-spec-validate.ts +147 -0
- package/src/ui/capture/field-spec.ts +62 -0
- package/src/ui/capture/index.ts +9 -1
- package/src/ui/capture/schema-field-input.tsx +134 -14
- package/src/ui/capture/submit-values.test.ts +70 -0
- package/src/ui/capture/submit-values.ts +63 -0
- package/src/ui/index.ts +8 -1
- package/src/ui/primitives/overflow-tabs.tsx +24 -4
- package/src/ui/primitives/url-preview-chrome.tsx +102 -0
- package/src/vista/GenericCatalogueSurface.tsx +177 -0
- package/src/vista/SurfaceFallbackCard.tsx +109 -0
- package/src/vista/VistaPanel.tsx +155 -0
- package/src/vista/form-payload.spec.ts +93 -0
- package/src/vista/html/CustomUiFrame.spec.tsx +125 -0
- package/src/vista/html/CustomUiFrame.tsx +204 -0
- package/src/vista/html/custom-ui-frame-bridge.spec.ts +191 -0
- package/src/vista/html/custom-ui-frame-bridge.ts +92 -0
- package/src/vista/html/custom-ui-frame-contract.ts +88 -0
- package/src/vista/html/custom-ui-intents.spec.ts +133 -0
- package/src/vista/html/custom-ui-intents.ts +151 -0
- package/src/vista/html/custom-ui-srcdoc.spec.ts +151 -0
- package/src/vista/html/custom-ui-srcdoc.ts +193 -0
- package/src/vista/html/index.ts +13 -0
- package/src/vista/index.ts +48 -0
- package/src/vista/surface-catalogue.spec.ts +140 -0
- package/src/vista/surface-catalogue.ts +84 -0
- package/src/vista/surface-icons.ts +57 -0
- package/src/vista/surface-registry.ts +56 -0
- package/src/vista/surfaces/ChartSurface.tsx +34 -0
- package/src/vista/surfaces/FilesSurface.tsx +268 -0
- package/src/vista/surfaces/FormSurface.tsx +264 -0
- package/src/vista/surfaces/HtmlSurface.tsx +43 -0
- package/src/vista/surfaces/TableSurface.tsx +99 -0
- package/src/vista/surfaces/UrlSurface.tsx +40 -0
- package/src/vista/surfaces/blob-surfaces.tsx +129 -0
- package/src/vista/surfaces/elicitation-transport.spec.ts +187 -0
- package/src/vista/surfaces/elicitation-transport.ts +175 -0
- package/src/vista/surfaces/index.tsx +157 -0
- package/src/vista/surfaces/text-surfaces.tsx +119 -0
- package/src/vista/use-vista-tabs.ts +188 -0
- package/src/vista/vista-code-renderer.tsx +46 -0
- package/src/vista/vista-file-source.tsx +163 -0
- package/src/vista/vista-form-host.tsx +78 -0
- package/src/vista/vista-model.ts +130 -0
- package/src/vista/vista-open-context.tsx +42 -0
- package/src/vista/vista-payloads.ts +514 -0
- package/src/vista/vista-tabs-manifest.ts +123 -0
- package/src/vista/vista-tools.ts +220 -0
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The Vista tab model — ONE tab vocabulary for every preview plane.
|
|
3
|
+
*
|
|
4
|
+
* Before this module the frontend carried THREE overlapping tab models with no
|
|
5
|
+
* shared code:
|
|
6
|
+
* • `WorkspaceTabKind` (`files|code|md|diff|tests|url`) in the thin session
|
|
7
|
+
* workspace;
|
|
8
|
+
* • `PreviewTabKind` (`files|html|markdown|pdf|image|plain`) buried inside the
|
|
9
|
+
* Design-System-Builder page;
|
|
10
|
+
* • the App-Forge preview.
|
|
11
|
+
* All three collapse onto the kernel {@link SurfaceKind} (Canopy §8.5). A tab is
|
|
12
|
+
* just a {@link VistaSurface} envelope; the Vista registry resolves its `kind`
|
|
13
|
+
* to a renderer.
|
|
14
|
+
*
|
|
15
|
+
* Collapse notes (deliberate, documented decisions):
|
|
16
|
+
* • `md` → {@link SurfaceKind.Markdown}.
|
|
17
|
+
* • `plain` → {@link SurfaceKind.Code}. `Code` is "a source file", and the
|
|
18
|
+
* code renderer is a mono pane; a separate "plain text" kind would be the
|
|
19
|
+
* same renderer under a second name.
|
|
20
|
+
* • `tests` had no kernel equivalent and was never a *render* kind — a test
|
|
21
|
+
* report is a biome-owned surface, so it becomes a biome-contributed
|
|
22
|
+
* `<biomeId>:tests` kind rather than a first-party one. Nothing in the tree
|
|
23
|
+
* rendered it (the thin workspace's `renderTests` slot was never supplied).
|
|
24
|
+
*/
|
|
25
|
+
import { SurfaceKind, type VistaSurface } from '@xemahq/kernel-contracts/surface';
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Id of the pinned, UI-owned file-browser tab. It is owned by the panel, never
|
|
29
|
+
* declared by an agent, and never closeable.
|
|
30
|
+
*/
|
|
31
|
+
export const VISTA_FILES_TAB_ID = 'files';
|
|
32
|
+
|
|
33
|
+
/** Current payload schema version of every first-party surface kind. */
|
|
34
|
+
export const VISTA_SURFACE_VERSION = 1;
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* A Vista tab. Structurally a {@link VistaSurface} — the tab model and the
|
|
38
|
+
* agent-facing envelope are the SAME shape on purpose, so `vista_open` needs no
|
|
39
|
+
* translation layer.
|
|
40
|
+
*/
|
|
41
|
+
export type VistaTab = VistaSurface;
|
|
42
|
+
|
|
43
|
+
/** Extension → first-party surface kind. Closed, deterministic mapping. */
|
|
44
|
+
const EXTENSION_KIND: Readonly<Record<string, SurfaceKind>> = {
|
|
45
|
+
html: SurfaceKind.Html,
|
|
46
|
+
htm: SurfaceKind.Html,
|
|
47
|
+
md: SurfaceKind.Markdown,
|
|
48
|
+
mdx: SurfaceKind.Markdown,
|
|
49
|
+
markdown: SurfaceKind.Markdown,
|
|
50
|
+
pdf: SurfaceKind.Pdf,
|
|
51
|
+
png: SurfaceKind.Image,
|
|
52
|
+
jpg: SurfaceKind.Image,
|
|
53
|
+
jpeg: SurfaceKind.Image,
|
|
54
|
+
gif: SurfaceKind.Image,
|
|
55
|
+
webp: SurfaceKind.Image,
|
|
56
|
+
svg: SurfaceKind.Image,
|
|
57
|
+
avif: SurfaceKind.Image,
|
|
58
|
+
mp4: SurfaceKind.Media,
|
|
59
|
+
webm: SurfaceKind.Media,
|
|
60
|
+
mov: SurfaceKind.Media,
|
|
61
|
+
mp3: SurfaceKind.Media,
|
|
62
|
+
wav: SurfaceKind.Media,
|
|
63
|
+
ogg: SurfaceKind.Media,
|
|
64
|
+
m4a: SurfaceKind.Media,
|
|
65
|
+
json: SurfaceKind.Json,
|
|
66
|
+
diff: SurfaceKind.Diff,
|
|
67
|
+
patch: SurfaceKind.Diff,
|
|
68
|
+
};
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* Resolve the surface kind a file path renders as. Deterministic and total:
|
|
72
|
+
* anything unrecognised is {@link SurfaceKind.Code} (a mono text pane), which is
|
|
73
|
+
* always a correct — if plain — rendering of a file's bytes.
|
|
74
|
+
*/
|
|
75
|
+
export function surfaceKindForPath(path: string): SurfaceKind {
|
|
76
|
+
const dot = path.lastIndexOf('.');
|
|
77
|
+
if (dot === -1) return SurfaceKind.Code;
|
|
78
|
+
const ext = path.slice(dot + 1).toLowerCase();
|
|
79
|
+
return EXTENSION_KIND[ext] ?? SurfaceKind.Code;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
/** The `content-type` a media/blob surface reports for a path, when derivable. */
|
|
83
|
+
const EXTENSION_CONTENT_TYPE: Readonly<Record<string, string>> = {
|
|
84
|
+
png: 'image/png',
|
|
85
|
+
jpg: 'image/jpeg',
|
|
86
|
+
jpeg: 'image/jpeg',
|
|
87
|
+
gif: 'image/gif',
|
|
88
|
+
webp: 'image/webp',
|
|
89
|
+
svg: 'image/svg+xml',
|
|
90
|
+
avif: 'image/avif',
|
|
91
|
+
pdf: 'application/pdf',
|
|
92
|
+
mp4: 'video/mp4',
|
|
93
|
+
webm: 'video/webm',
|
|
94
|
+
mov: 'video/quicktime',
|
|
95
|
+
mp3: 'audio/mpeg',
|
|
96
|
+
wav: 'audio/wav',
|
|
97
|
+
ogg: 'audio/ogg',
|
|
98
|
+
m4a: 'audio/mp4',
|
|
99
|
+
};
|
|
100
|
+
|
|
101
|
+
/** Content type for a path, or `null` when the extension is unknown. */
|
|
102
|
+
export function contentTypeForPath(path: string): string | null {
|
|
103
|
+
const dot = path.lastIndexOf('.');
|
|
104
|
+
if (dot === -1) return null;
|
|
105
|
+
return EXTENSION_CONTENT_TYPE[path.slice(dot + 1).toLowerCase()] ?? null;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
/** The last path segment — the default tab label for a file-backed surface. */
|
|
109
|
+
export function labelForPath(path: string): string {
|
|
110
|
+
const segments = path.split('/');
|
|
111
|
+
return segments[segments.length - 1] || path;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
/**
|
|
115
|
+
* Build a file-backed surface envelope for a path. One seam so every caller
|
|
116
|
+
* (the `.tabs.json` parser, the file browser, `vista_open`) derives kind + label
|
|
117
|
+
* + tab id identically.
|
|
118
|
+
*/
|
|
119
|
+
export function fileSurface(
|
|
120
|
+
path: string,
|
|
121
|
+
overrides?: Readonly<{ title?: string; kind?: SurfaceKind }>,
|
|
122
|
+
): VistaTab {
|
|
123
|
+
return {
|
|
124
|
+
tabId: `file:${path}`,
|
|
125
|
+
kind: overrides?.kind ?? surfaceKindForPath(path),
|
|
126
|
+
version: VISTA_SURFACE_VERSION,
|
|
127
|
+
title: overrides?.title ?? labelForPath(path),
|
|
128
|
+
payload: { path },
|
|
129
|
+
};
|
|
130
|
+
}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `VistaOpenContext` — how a surface asks the panel to open ANOTHER surface.
|
|
3
|
+
*
|
|
4
|
+
* The registry's `render(payload)` is a pure function, so a renderer cannot
|
|
5
|
+
* receive an `onOpen` prop. The panel publishes its `open` through this context
|
|
6
|
+
* instead: the file browser opens a file tab, an object view opens a related
|
|
7
|
+
* object, and so on — all through the SAME `vista_open` semantics the agent
|
|
8
|
+
* uses, never a second code path.
|
|
9
|
+
*
|
|
10
|
+
* A surface mounted without a provider simply renders non-interactive rows
|
|
11
|
+
* (`useVistaOpen()` returns `null`) — an inert list, never a dead click that
|
|
12
|
+
* silently does nothing.
|
|
13
|
+
*/
|
|
14
|
+
import {
|
|
15
|
+
createContext,
|
|
16
|
+
useContext,
|
|
17
|
+
type ReactElement,
|
|
18
|
+
type ReactNode,
|
|
19
|
+
} from 'react';
|
|
20
|
+
|
|
21
|
+
import type { VistaTab } from './vista-model';
|
|
22
|
+
|
|
23
|
+
/** Open (or replace) a tab and focus it. Mirrors `VistaTabsController.open`. */
|
|
24
|
+
export type VistaOpenFn = (surface: VistaTab) => string;
|
|
25
|
+
|
|
26
|
+
const VistaOpenContext = createContext<VistaOpenFn | null>(null);
|
|
27
|
+
|
|
28
|
+
export function VistaOpenProvider({
|
|
29
|
+
open,
|
|
30
|
+
children,
|
|
31
|
+
}: Readonly<{ open: VistaOpenFn; children: ReactNode }>): ReactElement {
|
|
32
|
+
return (
|
|
33
|
+
<VistaOpenContext.Provider value={open}>
|
|
34
|
+
{children}
|
|
35
|
+
</VistaOpenContext.Provider>
|
|
36
|
+
);
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/** The panel's `open`, or `null` when no panel is mounted above. */
|
|
40
|
+
export function useVistaOpen(): VistaOpenFn | null {
|
|
41
|
+
return useContext(VistaOpenContext);
|
|
42
|
+
}
|
|
@@ -0,0 +1,514 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Payload contracts + narrowing validators for the CLOSED first-party
|
|
3
|
+
* {@link SurfaceKind} set.
|
|
4
|
+
*
|
|
5
|
+
* Every validator is total and NEVER throws: it returns the narrowed payload or
|
|
6
|
+
* `null`, and `null` routes the envelope to `SurfaceFallbackCard` with
|
|
7
|
+
* `ContributionFallbackReason.InvalidPayload`. That is the contract the
|
|
8
|
+
* renderable registry depends on — a malformed payload degrades visibly, it is
|
|
9
|
+
* never coerced into a half-rendered surface.
|
|
10
|
+
*
|
|
11
|
+
* ── File-backed vs. inline ──────────────────────────────────────────────────
|
|
12
|
+
* Text/binary surfaces accept EITHER an inline `content`/`url` OR a workspace
|
|
13
|
+
* `path` resolved through the host-supplied {@link VistaFileSource}. Exactly one
|
|
14
|
+
* must be present — supplying both is a contradiction and is rejected, not
|
|
15
|
+
* silently preferred one way.
|
|
16
|
+
*/
|
|
17
|
+
import { validateCaptureFields } from '../ui/capture/field-spec-validate';
|
|
18
|
+
|
|
19
|
+
import type { CaptureFieldSpec } from '../ui/capture/field-spec';
|
|
20
|
+
import type { PreviewDevice } from '../ui/primitives/preview-device-frame';
|
|
21
|
+
|
|
22
|
+
/** A record with unknown values — the shape every validator starts from. */
|
|
23
|
+
type UnknownRecord = Readonly<Record<string, unknown>>;
|
|
24
|
+
|
|
25
|
+
function asRecord(value: unknown): UnknownRecord | null {
|
|
26
|
+
return value !== null && typeof value === 'object' && !Array.isArray(value)
|
|
27
|
+
? (value as UnknownRecord)
|
|
28
|
+
: null;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
function optionalString(value: unknown): string | undefined | null {
|
|
32
|
+
if (value === undefined) return undefined;
|
|
33
|
+
return typeof value === 'string' ? value : null;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* Narrow a "exactly one of `a` / `b`" pair of optional strings. Returns the
|
|
38
|
+
* pair when exactly one is a string, else `null`.
|
|
39
|
+
*/
|
|
40
|
+
function exactlyOne(
|
|
41
|
+
a: unknown,
|
|
42
|
+
b: unknown,
|
|
43
|
+
): Readonly<{ a?: string; b?: string }> | null {
|
|
44
|
+
const left = typeof a === 'string' ? a : undefined;
|
|
45
|
+
const right = typeof b === 'string' ? b : undefined;
|
|
46
|
+
if ((left === undefined) === (right === undefined)) return null;
|
|
47
|
+
return left === undefined ? { b: right } : { a: left };
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/** Where a text-backed surface reads its body from. */
|
|
51
|
+
export interface VistaTextPayload {
|
|
52
|
+
/** Inline body. Mutually exclusive with {@link path}. */
|
|
53
|
+
readonly content?: string;
|
|
54
|
+
/** Workspace-relative path resolved through the host `VistaFileSource`. */
|
|
55
|
+
readonly path?: string;
|
|
56
|
+
/** Optional language hint for a `code` surface (presentation only). */
|
|
57
|
+
readonly language?: string;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
export function validateTextPayload(raw: unknown): VistaTextPayload | null {
|
|
61
|
+
const record = asRecord(raw);
|
|
62
|
+
if (record === null) return null;
|
|
63
|
+
const source = exactlyOne(record.content, record.path);
|
|
64
|
+
if (source === null) return null;
|
|
65
|
+
const language = optionalString(record.language);
|
|
66
|
+
if (language === null) return null;
|
|
67
|
+
const base: VistaTextPayload =
|
|
68
|
+
source.a === undefined ? { path: source.b } : { content: source.a };
|
|
69
|
+
return language === undefined ? base : { ...base, language };
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
/** Where a binary surface (image / media / pdf) reads its bytes from. */
|
|
73
|
+
export interface VistaBlobPayload {
|
|
74
|
+
/** Already-resolved fetchable URL (`https:`, `blob:`, `data:`). */
|
|
75
|
+
readonly url?: string;
|
|
76
|
+
/** Workspace-relative path resolved through the host `VistaFileSource`. */
|
|
77
|
+
readonly path?: string;
|
|
78
|
+
/** Alt text / accessible label. */
|
|
79
|
+
readonly alt?: string;
|
|
80
|
+
/** MIME type. Required by `media` (audio vs. video); optional elsewhere. */
|
|
81
|
+
readonly contentType?: string;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
export function validateBlobPayload(raw: unknown): VistaBlobPayload | null {
|
|
85
|
+
const record = asRecord(raw);
|
|
86
|
+
if (record === null) return null;
|
|
87
|
+
const source = exactlyOne(record.url, record.path);
|
|
88
|
+
if (source === null) return null;
|
|
89
|
+
const alt = optionalString(record.alt);
|
|
90
|
+
if (alt === null) return null;
|
|
91
|
+
const contentType = optionalString(record.contentType);
|
|
92
|
+
if (contentType === null) return null;
|
|
93
|
+
const payload: {
|
|
94
|
+
url?: string;
|
|
95
|
+
path?: string;
|
|
96
|
+
alt?: string;
|
|
97
|
+
contentType?: string;
|
|
98
|
+
} = source.a === undefined ? { path: source.b } : { url: source.a };
|
|
99
|
+
if (alt !== undefined) payload.alt = alt;
|
|
100
|
+
if (contentType !== undefined) payload.contentType = contentType;
|
|
101
|
+
return payload;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
/** `SurfaceKind.Url` — a live external URL inside mock browser chrome. */
|
|
105
|
+
export interface VistaUrlPayload {
|
|
106
|
+
readonly url: string;
|
|
107
|
+
/** Device bezel to render the frame in. Defaults to `desktop`. */
|
|
108
|
+
readonly device?: PreviewDevice;
|
|
109
|
+
/** Bump to force the frame to reload without changing the URL. */
|
|
110
|
+
readonly reloadNonce?: number;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
const PREVIEW_DEVICES: readonly PreviewDevice[] = [
|
|
114
|
+
'desktop',
|
|
115
|
+
'tablet',
|
|
116
|
+
'mobile',
|
|
117
|
+
'presentation',
|
|
118
|
+
'a4',
|
|
119
|
+
];
|
|
120
|
+
|
|
121
|
+
export function validateUrlPayload(raw: unknown): VistaUrlPayload | null {
|
|
122
|
+
const record = asRecord(raw);
|
|
123
|
+
if (record === null) return null;
|
|
124
|
+
if (typeof record.url !== 'string' || record.url.length === 0) return null;
|
|
125
|
+
const payload: { url: string; device?: PreviewDevice; reloadNonce?: number } =
|
|
126
|
+
{ url: record.url };
|
|
127
|
+
if (record.device !== undefined) {
|
|
128
|
+
if (!PREVIEW_DEVICES.includes(record.device as PreviewDevice)) return null;
|
|
129
|
+
payload.device = record.device as PreviewDevice;
|
|
130
|
+
}
|
|
131
|
+
if (record.reloadNonce !== undefined) {
|
|
132
|
+
if (typeof record.reloadNonce !== 'number') return null;
|
|
133
|
+
payload.reloadNonce = record.reloadNonce;
|
|
134
|
+
}
|
|
135
|
+
return payload;
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
/**
|
|
139
|
+
* `SurfaceKind.Html` — UNTRUSTED HTML. Two mutually-exclusive forms:
|
|
140
|
+
*
|
|
141
|
+
* • `document` — an agent-authored HTML document. Rendered with
|
|
142
|
+
* `script-src 'none'`: markup and styles render, script NEVER runs.
|
|
143
|
+
* • `compiledOutput` + `integrity` — a server-compiled, SRI-pinned custom-UI
|
|
144
|
+
* chunk (App Forge Wave-12). Rendered with `script-src '<sha384-…>'`: ONLY
|
|
145
|
+
* those exact bytes execute.
|
|
146
|
+
*
|
|
147
|
+
* Both run in an opaque-origin, `allow-scripts`-only sandbox frame.
|
|
148
|
+
*/
|
|
149
|
+
export type VistaHtmlPayload =
|
|
150
|
+
| { readonly document: string }
|
|
151
|
+
| {
|
|
152
|
+
readonly compiledOutput: string;
|
|
153
|
+
readonly integrity: string;
|
|
154
|
+
readonly styleCss?: string;
|
|
155
|
+
};
|
|
156
|
+
|
|
157
|
+
/** `sha384-<base64>` — the only SRI token form the frame CSP accepts. */
|
|
158
|
+
const SRI_TOKEN = /^sha384-[A-Za-z0-9+/]+={0,2}$/;
|
|
159
|
+
|
|
160
|
+
export function validateHtmlPayload(raw: unknown): VistaHtmlPayload | null {
|
|
161
|
+
const record = asRecord(raw);
|
|
162
|
+
if (record === null) return null;
|
|
163
|
+
const hasDocument = typeof record.document === 'string';
|
|
164
|
+
const hasChunk = typeof record.compiledOutput === 'string';
|
|
165
|
+
if (hasDocument === hasChunk) return null;
|
|
166
|
+
if (hasDocument) return { document: record.document as string };
|
|
167
|
+
// A compiled chunk WITHOUT a well-formed integrity token is rejected: the
|
|
168
|
+
// CSP hash source is what makes executing it safe, so there is no
|
|
169
|
+
// "run it unpinned" path.
|
|
170
|
+
if (typeof record.integrity !== 'string' || !SRI_TOKEN.test(record.integrity))
|
|
171
|
+
return null;
|
|
172
|
+
const styleCss = optionalString(record.styleCss);
|
|
173
|
+
if (styleCss === null) return null;
|
|
174
|
+
const payload = {
|
|
175
|
+
compiledOutput: record.compiledOutput as string,
|
|
176
|
+
integrity: record.integrity,
|
|
177
|
+
};
|
|
178
|
+
return styleCss === undefined ? payload : { ...payload, styleCss };
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
/** `SurfaceKind.Json` — an inspectable JSON tree. */
|
|
182
|
+
export interface VistaJsonPayload {
|
|
183
|
+
readonly data: unknown;
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
export function validateJsonPayload(raw: unknown): VistaJsonPayload | null {
|
|
187
|
+
const record = asRecord(raw);
|
|
188
|
+
if (record === null) return null;
|
|
189
|
+
if (!('data' in record)) return null;
|
|
190
|
+
return { data: record.data };
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
/** `SurfaceKind.Table` — generic columns + rows. */
|
|
194
|
+
export interface VistaTablePayload {
|
|
195
|
+
readonly columns: readonly string[];
|
|
196
|
+
readonly rows: readonly (readonly unknown[])[];
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
export function validateTablePayload(raw: unknown): VistaTablePayload | null {
|
|
200
|
+
const record = asRecord(raw);
|
|
201
|
+
if (record === null) return null;
|
|
202
|
+
if (!Array.isArray(record.columns) || !Array.isArray(record.rows)) return null;
|
|
203
|
+
if (!record.columns.every((c) => typeof c === 'string')) return null;
|
|
204
|
+
if (!record.rows.every((r) => Array.isArray(r))) return null;
|
|
205
|
+
return {
|
|
206
|
+
columns: record.columns,
|
|
207
|
+
rows: record.rows as readonly (readonly unknown[])[],
|
|
208
|
+
};
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
/** Chart shapes the `chart` surface draws. Closed set. */
|
|
212
|
+
export enum VistaChartKind {
|
|
213
|
+
Bar = 'bar',
|
|
214
|
+
Line = 'line',
|
|
215
|
+
Donut = 'donut',
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
/** One labelled point. Value-identical to the kernel `ChartDatum`. */
|
|
219
|
+
export interface VistaChartDatum {
|
|
220
|
+
readonly label: string;
|
|
221
|
+
readonly value: number;
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
/** One named series. */
|
|
225
|
+
export interface VistaChartSeries {
|
|
226
|
+
readonly name: string;
|
|
227
|
+
readonly points: readonly VistaChartDatum[];
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
/**
|
|
231
|
+
* `SurfaceKind.Chart`. At least one series is REQUIRED — `bar`/`donut` render
|
|
232
|
+
* the first one, so an empty `series` would have no defined rendering.
|
|
233
|
+
*/
|
|
234
|
+
export interface VistaChartPayload {
|
|
235
|
+
readonly kind: VistaChartKind;
|
|
236
|
+
readonly title: string;
|
|
237
|
+
readonly series: readonly [VistaChartSeries, ...VistaChartSeries[]];
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
const CHART_KINDS: readonly string[] = Object.values(VistaChartKind);
|
|
241
|
+
|
|
242
|
+
export function validateChartPayload(raw: unknown): VistaChartPayload | null {
|
|
243
|
+
const record = asRecord(raw);
|
|
244
|
+
if (record === null) return null;
|
|
245
|
+
if (typeof record.kind !== 'string' || !CHART_KINDS.includes(record.kind))
|
|
246
|
+
return null;
|
|
247
|
+
if (typeof record.title !== 'string' || record.title.length === 0) return null;
|
|
248
|
+
if (!Array.isArray(record.series) || record.series.length === 0) return null;
|
|
249
|
+
const series: VistaChartSeries[] = [];
|
|
250
|
+
for (const entry of record.series) {
|
|
251
|
+
const row = asRecord(entry);
|
|
252
|
+
if (row === null || typeof row.name !== 'string') return null;
|
|
253
|
+
if (!Array.isArray(row.points)) return null;
|
|
254
|
+
const points: VistaChartDatum[] = [];
|
|
255
|
+
for (const point of row.points) {
|
|
256
|
+
const p = asRecord(point);
|
|
257
|
+
if (p === null || typeof p.label !== 'string') return null;
|
|
258
|
+
if (typeof p.value !== 'number') return null;
|
|
259
|
+
points.push({ label: p.label, value: p.value });
|
|
260
|
+
}
|
|
261
|
+
series.push({ name: row.name, points });
|
|
262
|
+
}
|
|
263
|
+
return {
|
|
264
|
+
kind: record.kind as VistaChartKind,
|
|
265
|
+
title: record.title,
|
|
266
|
+
series: series as [VistaChartSeries, ...VistaChartSeries[]],
|
|
267
|
+
};
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
/** `SurfaceKind.Diff` — a unified diff, inline or file-backed. */
|
|
271
|
+
export type VistaDiffPayload = VistaTextPayload;
|
|
272
|
+
export const validateDiffPayload = validateTextPayload;
|
|
273
|
+
|
|
274
|
+
/** One row in the {@link SurfaceKind.Files} browser. */
|
|
275
|
+
export interface VistaFileEntry {
|
|
276
|
+
/** Workspace-relative path (also the row key). */
|
|
277
|
+
readonly path: string;
|
|
278
|
+
/** Lines added (present only for changed files). */
|
|
279
|
+
readonly add?: number;
|
|
280
|
+
/** Lines deleted (present only for changed files). */
|
|
281
|
+
readonly del?: number;
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
/** `SurfaceKind.Files` — a file tree over a workspace / artifact set. */
|
|
285
|
+
export interface VistaFilesPayload {
|
|
286
|
+
readonly files: readonly VistaFileEntry[];
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
export function validateFilesPayload(raw: unknown): VistaFilesPayload | null {
|
|
290
|
+
const record = asRecord(raw);
|
|
291
|
+
if (record === null) return null;
|
|
292
|
+
if (!Array.isArray(record.files)) return null;
|
|
293
|
+
const files: VistaFileEntry[] = [];
|
|
294
|
+
for (const entry of record.files) {
|
|
295
|
+
const row = asRecord(entry);
|
|
296
|
+
if (row === null || typeof row.path !== 'string') return null;
|
|
297
|
+
const file: { path: string; add?: number; del?: number } = {
|
|
298
|
+
path: row.path,
|
|
299
|
+
};
|
|
300
|
+
if (row.add !== undefined) {
|
|
301
|
+
if (typeof row.add !== 'number') return null;
|
|
302
|
+
file.add = row.add;
|
|
303
|
+
}
|
|
304
|
+
if (row.del !== undefined) {
|
|
305
|
+
if (typeof row.del !== 'number') return null;
|
|
306
|
+
file.del = row.del;
|
|
307
|
+
}
|
|
308
|
+
files.push(file);
|
|
309
|
+
}
|
|
310
|
+
return { files };
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
/**
|
|
314
|
+
* `SurfaceKind.BiomeRoute` — a biome's REAL React route, addressed by the
|
|
315
|
+
* existing `xema://biome/<biomeId>/<route>` deeplink. Validation here is
|
|
316
|
+
* structural only; the HOST parses the deeplink and enforces route access.
|
|
317
|
+
*/
|
|
318
|
+
export interface VistaBiomeRoutePayload {
|
|
319
|
+
readonly deeplink: string;
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
export function validateBiomeRoutePayload(
|
|
323
|
+
raw: unknown,
|
|
324
|
+
): VistaBiomeRoutePayload | null {
|
|
325
|
+
const record = asRecord(raw);
|
|
326
|
+
if (record === null) return null;
|
|
327
|
+
return typeof record.deeplink === 'string' && record.deeplink.length > 0
|
|
328
|
+
? { deeplink: record.deeplink }
|
|
329
|
+
: null;
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
/** `SurfaceKind.Object` — a `xema://<scope>/<kind>/<slug>` entity. */
|
|
333
|
+
export interface VistaObjectPayload {
|
|
334
|
+
readonly ref: string;
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
export function validateObjectPayload(raw: unknown): VistaObjectPayload | null {
|
|
338
|
+
const record = asRecord(raw);
|
|
339
|
+
if (record === null) return null;
|
|
340
|
+
return typeof record.ref === 'string' && record.ref.length > 0
|
|
341
|
+
? { ref: record.ref }
|
|
342
|
+
: null;
|
|
343
|
+
}
|
|
344
|
+
|
|
345
|
+
/** `SurfaceKind.Graph` — the capability graph, optionally anchored. */
|
|
346
|
+
export interface VistaGraphPayload {
|
|
347
|
+
/** Anchor the view on a resource/capability ref. Absent = whole snapshot. */
|
|
348
|
+
readonly anchorRef?: string;
|
|
349
|
+
/** Traversal depth from the anchor. */
|
|
350
|
+
readonly depth?: number;
|
|
351
|
+
}
|
|
352
|
+
|
|
353
|
+
export function validateGraphPayload(raw: unknown): VistaGraphPayload | null {
|
|
354
|
+
const record = asRecord(raw);
|
|
355
|
+
if (record === null) return null;
|
|
356
|
+
const anchorRef = optionalString(record.anchorRef);
|
|
357
|
+
if (anchorRef === null) return null;
|
|
358
|
+
if (record.depth !== undefined && typeof record.depth !== 'number')
|
|
359
|
+
return null;
|
|
360
|
+
const payload: { anchorRef?: string; depth?: number } = {};
|
|
361
|
+
if (anchorRef !== undefined) payload.anchorRef = anchorRef;
|
|
362
|
+
if (record.depth !== undefined) payload.depth = record.depth;
|
|
363
|
+
return payload;
|
|
364
|
+
}
|
|
365
|
+
|
|
366
|
+
/** `SurfaceKind.Web` — a first-party in-app route rendered inside the tab. */
|
|
367
|
+
export interface VistaWebPayload {
|
|
368
|
+
/** Host-relative path (leading `/`). */
|
|
369
|
+
readonly href: string;
|
|
370
|
+
}
|
|
371
|
+
|
|
372
|
+
export function validateWebPayload(raw: unknown): VistaWebPayload | null {
|
|
373
|
+
const record = asRecord(raw);
|
|
374
|
+
if (record === null) return null;
|
|
375
|
+
return typeof record.href === 'string' && record.href.startsWith('/')
|
|
376
|
+
? { href: record.href }
|
|
377
|
+
: null;
|
|
378
|
+
}
|
|
379
|
+
|
|
380
|
+
/**
|
|
381
|
+
* An `http(s)` ABSOLUTE URL, or `null`.
|
|
382
|
+
*
|
|
383
|
+
* Every URL on a {@link VistaFormPayload} must be absolute. That is the
|
|
384
|
+
* structural half of "the value goes browser → service and never through the
|
|
385
|
+
* agent": a relative path would resolve against the HOST app's origin — i.e.
|
|
386
|
+
* its BFF, where the chat transport lives — so a relative submit target is
|
|
387
|
+
* rejected outright rather than normalised.
|
|
388
|
+
*/
|
|
389
|
+
function absoluteHttpUrl(value: unknown): string | null {
|
|
390
|
+
if (typeof value !== 'string' || value.length === 0) return null;
|
|
391
|
+
let parsed: URL;
|
|
392
|
+
try {
|
|
393
|
+
parsed = new URL(value);
|
|
394
|
+
} catch {
|
|
395
|
+
return null;
|
|
396
|
+
}
|
|
397
|
+
return parsed.protocol === 'https:' || parsed.protocol === 'http:' ? value : null;
|
|
398
|
+
}
|
|
399
|
+
|
|
400
|
+
/**
|
|
401
|
+
* The consent / install handoff of a {@link VistaFormPayload}.
|
|
402
|
+
*
|
|
403
|
+
* Present when the connector's app auth is `oauth2` or `app_install`: there is
|
|
404
|
+
* no field form to fill, only a link the user follows in another window. It is
|
|
405
|
+
* fully generic — the URL is minted per-provider by the owning service and
|
|
406
|
+
* carried here verbatim, so no provider is special-cased in the renderer.
|
|
407
|
+
*/
|
|
408
|
+
export interface VistaFormLaunch {
|
|
409
|
+
/** ABSOLUTE consent / install URL, opened in a new window. */
|
|
410
|
+
readonly url: string;
|
|
411
|
+
/** Button copy, e.g. "Install Acme" / "Continue to Acme". */
|
|
412
|
+
readonly label: string;
|
|
413
|
+
/** Optional explanation rendered above the button. */
|
|
414
|
+
readonly hint?: string;
|
|
415
|
+
}
|
|
416
|
+
|
|
417
|
+
/**
|
|
418
|
+
* `SurfaceKind.Form` — the SECURE ELICITATION surface.
|
|
419
|
+
*
|
|
420
|
+
* The agent opens it to walk a user through providing a credential it must
|
|
421
|
+
* never see. Two mutually-exclusive modes, chosen by the presence of
|
|
422
|
+
* {@link launch}:
|
|
423
|
+
*
|
|
424
|
+
* • FIELD mode — render `fields`, POST them to `submitUrl` with the user's
|
|
425
|
+
* own JWT;
|
|
426
|
+
* • LAUNCH mode — render the consent/install link, then confirm completion
|
|
427
|
+
* against `statusUrl`.
|
|
428
|
+
*
|
|
429
|
+
* Both settle into the same `{ submitted, ref }` shape, so the agent's view of
|
|
430
|
+
* the world does not depend on which mode ran.
|
|
431
|
+
*/
|
|
432
|
+
export interface VistaFormPayload {
|
|
433
|
+
/** Opaque, non-secret elicitation reference. The agent polls this. */
|
|
434
|
+
readonly ref: string;
|
|
435
|
+
/** Why the credential is being asked for — shown to the user verbatim. */
|
|
436
|
+
readonly purpose: string;
|
|
437
|
+
/** ABSOLUTE service URL the captured fields are POSTed to. */
|
|
438
|
+
readonly submitUrl: string;
|
|
439
|
+
/** ABSOLUTE service URL reporting whether the elicitation has settled. */
|
|
440
|
+
readonly statusUrl: string;
|
|
441
|
+
/** The onboarding form's fields. MAY be empty — the service is the authority. */
|
|
442
|
+
readonly fields: readonly CaptureFieldSpec[];
|
|
443
|
+
/** Optional heading override (defaults to the tab title). */
|
|
444
|
+
readonly heading?: string;
|
|
445
|
+
/** Submit-button copy for field mode. */
|
|
446
|
+
readonly submitLabel?: string;
|
|
447
|
+
/** Present ⇒ LAUNCH mode (oauth2 / app_install). */
|
|
448
|
+
readonly launch?: VistaFormLaunch;
|
|
449
|
+
}
|
|
450
|
+
|
|
451
|
+
export function validateFormPayload(raw: unknown): VistaFormPayload | null {
|
|
452
|
+
const record = asRecord(raw);
|
|
453
|
+
if (record === null) return null;
|
|
454
|
+
if (typeof record.ref !== 'string' || record.ref.length === 0) return null;
|
|
455
|
+
if (typeof record.purpose !== 'string') return null;
|
|
456
|
+
|
|
457
|
+
const submitUrl = absoluteHttpUrl(record.submitUrl);
|
|
458
|
+
if (submitUrl === null) return null;
|
|
459
|
+
const statusUrl = absoluteHttpUrl(record.statusUrl);
|
|
460
|
+
if (statusUrl === null) return null;
|
|
461
|
+
|
|
462
|
+
const fields = validateCaptureFields(record.fields);
|
|
463
|
+
if (fields === null) return null;
|
|
464
|
+
|
|
465
|
+
const heading = optionalString(record.heading);
|
|
466
|
+
if (heading === null) return null;
|
|
467
|
+
const submitLabel = optionalString(record.submitLabel);
|
|
468
|
+
if (submitLabel === null) return null;
|
|
469
|
+
|
|
470
|
+
let launch: VistaFormLaunch | undefined;
|
|
471
|
+
if (record.launch !== undefined) {
|
|
472
|
+
const raw_ = asRecord(record.launch);
|
|
473
|
+
if (raw_ === null) return null;
|
|
474
|
+
const url = absoluteHttpUrl(raw_.url);
|
|
475
|
+
if (url === null) return null;
|
|
476
|
+
if (typeof raw_.label !== 'string' || raw_.label.length === 0) return null;
|
|
477
|
+
const hint = optionalString(raw_.hint);
|
|
478
|
+
if (hint === null) return null;
|
|
479
|
+
launch = hint === undefined ? { url, label: raw_.label } : { url, label: raw_.label, hint };
|
|
480
|
+
}
|
|
481
|
+
|
|
482
|
+
const payload: {
|
|
483
|
+
ref: string;
|
|
484
|
+
purpose: string;
|
|
485
|
+
submitUrl: string;
|
|
486
|
+
statusUrl: string;
|
|
487
|
+
fields: readonly CaptureFieldSpec[];
|
|
488
|
+
heading?: string;
|
|
489
|
+
submitLabel?: string;
|
|
490
|
+
launch?: VistaFormLaunch;
|
|
491
|
+
} = { ref: record.ref, purpose: record.purpose, submitUrl, statusUrl, fields };
|
|
492
|
+
if (heading !== undefined) payload.heading = heading;
|
|
493
|
+
if (submitLabel !== undefined) payload.submitLabel = submitLabel;
|
|
494
|
+
if (launch !== undefined) payload.launch = launch;
|
|
495
|
+
return payload;
|
|
496
|
+
}
|
|
497
|
+
|
|
498
|
+
/** `SurfaceKind.App` — a runtime App-Platform app rendered in its own frame. */
|
|
499
|
+
export interface VistaAppPayload {
|
|
500
|
+
readonly appId: string;
|
|
501
|
+
/** In-app route, defaults to the app's entry route. */
|
|
502
|
+
readonly path?: string;
|
|
503
|
+
}
|
|
504
|
+
|
|
505
|
+
export function validateAppPayload(raw: unknown): VistaAppPayload | null {
|
|
506
|
+
const record = asRecord(raw);
|
|
507
|
+
if (record === null) return null;
|
|
508
|
+
if (typeof record.appId !== 'string' || record.appId.length === 0) return null;
|
|
509
|
+
const path = optionalString(record.path);
|
|
510
|
+
if (path === null) return null;
|
|
511
|
+
return path === undefined
|
|
512
|
+
? { appId: record.appId }
|
|
513
|
+
: { appId: record.appId, path };
|
|
514
|
+
}
|