@cosmicdrift/kumiko-renderer 0.374.0 → 0.378.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/README.md +2 -2
- package/dist/app/action-form-support.d.ts +9 -2
- package/dist/app/action-form-support.js +24 -2
- package/dist/app/client-actions.d.ts +2 -2
- package/dist/app/column-renderers.js +1 -1
- package/dist/app/config-edit-shim.js +1 -1
- package/dist/app/content-preview.js +1 -6
- package/dist/app/custom-screens.js +1 -1
- package/dist/app/dashboard-body.d.ts +1 -1
- package/dist/app/entity-list-expanded-row.d.ts +1 -1
- package/dist/app/form-schema.d.ts +1 -1
- package/dist/app/form-schema.js +2 -2
- package/dist/app/kumiko-screen.d.ts +1 -1
- package/dist/app/kumiko-screen.js +10 -7
- package/dist/app/list-empty-content.d.ts +1 -1
- package/dist/app/list-facets.d.ts +1 -1
- package/dist/app/nav.js +2 -2
- package/dist/app/query-state-banners.d.ts +1 -1
- package/dist/app/reference-link.d.ts +1 -1
- package/dist/app/row-actions.d.ts +1 -1
- package/dist/app/secret-mint-body.d.ts +1 -1
- package/dist/app/secrets-edit-body.d.ts +1 -1
- package/dist/app/use-record-actions.d.ts +1 -1
- package/dist/app/write-failed-error.d.ts +1 -1
- package/dist/components/availability-options-select.d.ts +1 -1
- package/dist/components/embedded-list-field.d.ts +1 -1
- package/dist/components/embedded-list-field.js +1 -1
- package/dist/components/file-list-field.d.ts +1 -1
- package/dist/components/form-derivation-patch.d.ts +8 -0
- package/dist/components/form-derivation-patch.js +24 -0
- package/dist/components/form-screen-layout.d.ts +13 -0
- package/dist/components/form-screen-layout.js +13 -0
- package/dist/components/grid-cell-for-field.d.ts +1 -1
- package/dist/components/multi-select-checkboxes.d.ts +1 -1
- package/dist/components/multi-select-checkboxes.js +1 -1
- package/dist/components/query-options-select.d.ts +1 -1
- package/dist/components/related-list-section.d.ts +1 -1
- package/dist/components/render-edit-logic.d.ts +1 -1
- package/dist/components/render-edit-types.d.ts +6 -3
- package/dist/components/render-edit.d.ts +1 -1
- package/dist/components/render-edit.js +18 -3
- package/dist/components/render-field.d.ts +1 -1
- package/dist/components/render-field.js +12 -2
- package/dist/components/render-list.d.ts +1 -1
- package/dist/components/render-list.js +20 -4
- package/dist/components/write-form-section.d.ts +1 -1
- package/dist/components/write-form-section.js +1 -1
- package/dist/context/dispatcher-context.d.ts +1 -1
- package/dist/file-ids-of.d.ts +1 -0
- package/dist/file-ids-of.js +7 -0
- package/dist/flow-diagram/icons.d.ts +3 -0
- package/dist/flow-diagram/icons.js +14 -0
- package/dist/flow-diagram/index.d.ts +2 -0
- package/dist/flow-diagram/index.js +1 -0
- package/dist/flow-diagram/render.d.ts +3 -0
- package/dist/flow-diagram/render.js +234 -0
- package/dist/flow-diagram/types.d.ts +18 -0
- package/dist/flow-diagram/types.js +1 -0
- package/dist/format-when.js +1 -1
- package/dist/headless/apex/css.d.ts +3 -0
- package/dist/headless/apex/css.js +298 -0
- package/dist/headless/apex/index.d.ts +236 -0
- package/dist/headless/apex/index.js +377 -0
- package/dist/headless/apex/lightbox.d.ts +4 -0
- package/dist/headless/apex/lightbox.js +81 -0
- package/dist/headless/contracts/asset.d.ts +15 -0
- package/dist/headless/contracts/asset.js +17 -0
- package/dist/headless/contracts/index.d.ts +3 -0
- package/dist/headless/contracts/index.js +1 -0
- package/dist/headless/contracts/locale.d.ts +7 -0
- package/dist/headless/contracts/locale.js +11 -0
- package/dist/headless/contracts/primitives.d.ts +93 -0
- package/dist/headless/contracts/primitives.js +21 -0
- package/dist/headless/dispatcher/index.d.ts +2 -0
- package/dist/headless/dispatcher/index.js +1 -0
- package/dist/headless/dispatcher/types.d.ts +86 -0
- package/dist/headless/dispatcher/types.js +34 -0
- package/dist/headless/form/form-controller.d.ts +2 -0
- package/dist/headless/form/form-controller.js +409 -0
- package/dist/headless/form/index.d.ts +3 -0
- package/dist/headless/form/index.js +2 -0
- package/dist/headless/form/types.d.ts +76 -0
- package/dist/headless/form/types.js +1 -0
- package/dist/headless/form/zod-bridge.d.ts +10 -0
- package/dist/headless/form/zod-bridge.js +103 -0
- package/dist/headless/format/document-values.d.ts +12 -0
- package/dist/headless/format/document-values.js +70 -0
- package/dist/headless/format/escape.d.ts +5 -0
- package/dist/headless/format/escape.js +75 -0
- package/dist/headless/format/html-template.d.ts +9 -0
- package/dist/headless/format/html-template.js +39 -0
- package/dist/headless/format/index.d.ts +12 -0
- package/dist/headless/format/index.js +237 -0
- package/dist/headless/format/money.d.ts +3 -0
- package/dist/headless/format/money.js +39 -0
- package/dist/headless/index.d.ts +14 -0
- package/dist/headless/index.js +9 -0
- package/dist/headless/locale-routing/index.d.ts +41 -0
- package/dist/headless/locale-routing/index.js +145 -0
- package/dist/headless/nav/index.d.ts +2 -0
- package/dist/headless/nav/index.js +1 -0
- package/dist/headless/nav/resolve.d.ts +2 -0
- package/dist/headless/nav/resolve.js +71 -0
- package/dist/headless/nav/types.d.ts +26 -0
- package/dist/headless/nav/types.js +1 -0
- package/dist/headless/store/create-store.d.ts +2 -0
- package/dist/headless/store/create-store.js +43 -0
- package/dist/headless/store/equality.d.ts +1 -0
- package/dist/headless/store/equality.js +34 -0
- package/dist/headless/store/index.d.ts +3 -0
- package/dist/headless/store/index.js +2 -0
- package/dist/headless/store/types.d.ts +7 -0
- package/dist/headless/store/types.js +10 -0
- package/dist/headless/view-model/edit.d.ts +21 -0
- package/dist/headless/view-model/edit.js +512 -0
- package/dist/headless/view-model/embedded-list.d.ts +27 -0
- package/dist/headless/view-model/embedded-list.js +63 -0
- package/dist/headless/view-model/index.d.ts +7 -0
- package/dist/headless/view-model/index.js +3 -0
- package/dist/headless/view-model/list-file-display.d.ts +3 -0
- package/dist/headless/view-model/list-file-display.js +27 -0
- package/dist/headless/view-model/list.d.ts +16 -0
- package/dist/headless/view-model/list.js +229 -0
- package/dist/headless/view-model/types.d.ts +382 -0
- package/dist/headless/view-model/types.js +1 -0
- package/dist/hooks/use-ai-text.d.ts +1 -1
- package/dist/hooks/use-form.d.ts +1 -1
- package/dist/hooks/use-form.js +1 -1
- package/dist/hooks/use-mutation.d.ts +1 -1
- package/dist/hooks/use-query.d.ts +1 -1
- package/dist/hooks/use-store.d.ts +1 -1
- package/dist/hooks/use-store.js +7 -7
- package/dist/hooks/use-stream-handler.d.ts +1 -1
- package/dist/i18n-defaults.js +6 -0
- package/dist/i18n.d.ts +1 -1
- package/dist/i18n.js +1 -1
- package/dist/index.d.ts +3 -1
- package/dist/index.js +5 -4
- package/dist/live/csrf.d.ts +2 -0
- package/dist/live/csrf.js +60 -0
- package/dist/live/dispatcher-live.d.ts +7 -0
- package/dist/live/dispatcher-live.js +286 -0
- package/dist/live/envelopes.d.ts +101 -0
- package/dist/live/envelopes.js +35 -0
- package/dist/live/error-mapping.d.ts +16 -0
- package/dist/live/error-mapping.js +82 -0
- package/dist/live/index.d.ts +7 -0
- package/dist/live/index.js +5 -0
- package/dist/live/locale.d.ts +2 -0
- package/dist/live/locale.js +25 -0
- package/dist/live/sse-stream.d.ts +14 -0
- package/dist/live/sse-stream.js +128 -0
- package/dist/primitives.d.ts +45 -36
- package/dist/primitives.js +1 -1
- package/dist/session/session-ended.d.ts +1 -1
- package/dist/tokens.d.ts +3 -4
- package/dist/tokens.js +4 -5
- package/dist/web/app/app-schema-boot.d.ts +19 -0
- package/dist/web/app/app-schema-boot.js +124 -0
- package/dist/web/app/browser-locale.d.ts +22 -0
- package/dist/web/app/browser-locale.js +78 -0
- package/dist/web/app/client-plugin.d.ts +106 -0
- package/dist/web/app/client-plugin.js +12 -0
- package/dist/web/app/create-app.d.ts +104 -0
- package/dist/web/app/create-app.js +498 -0
- package/dist/web/app/create-public-surface.d.ts +36 -0
- package/dist/web/app/create-public-surface.js +40 -0
- package/dist/web/app/dashboard-body.d.ts +3 -0
- package/dist/web/app/dashboard-body.js +865 -0
- package/dist/web/app/dashboard-refresh.d.ts +6 -0
- package/dist/web/app/dashboard-refresh.js +15 -0
- package/dist/web/app/document-lang-sync.d.ts +4 -0
- package/dist/web/app/document-lang-sync.js +27 -0
- package/dist/web/app/draft-storage.d.ts +11 -0
- package/dist/web/app/draft-storage.js +53 -0
- package/dist/web/app/nav-providers-context.d.ts +13 -0
- package/dist/web/app/nav-providers-context.js +18 -0
- package/dist/web/app/nav.d.ts +40 -0
- package/dist/web/app/nav.js +231 -0
- package/dist/web/app/plain-content-editor.d.ts +3 -0
- package/dist/web/app/plain-content-editor.js +30 -0
- package/dist/web/app/relative-time.d.ts +10 -0
- package/dist/web/app/relative-time.js +56 -0
- package/dist/web/app/resolvers-context.d.ts +12 -0
- package/dist/web/app/resolvers-context.js +10 -0
- package/dist/web/app/rich-content-editor.d.ts +3 -0
- package/dist/web/app/rich-content-editor.js +15 -0
- package/dist/web/app/root-error-fallback.d.ts +2 -0
- package/dist/web/app/root-error-fallback.js +21 -0
- package/dist/web/app/screen-error-fallback.d.ts +6 -0
- package/dist/web/app/screen-error-fallback.js +17 -0
- package/dist/web/app/tiptap-editor.d.ts +3 -0
- package/dist/web/app/tiptap-editor.js +120 -0
- package/dist/web/app/toast-action-notifier.d.ts +5 -0
- package/dist/web/app/toast-action-notifier.js +17 -0
- package/dist/web/components/config-cascade.d.ts +13 -0
- package/dist/web/components/config-cascade.js +155 -0
- package/dist/web/components/config-source-badge.d.ts +6 -0
- package/dist/web/components/config-source-badge.js +55 -0
- package/dist/web/default-color-scheme.d.ts +2 -0
- package/dist/web/default-color-scheme.js +3 -0
- package/dist/web/icons.d.ts +94 -0
- package/dist/web/icons.js +100 -0
- package/dist/web/index.d.ts +78 -0
- package/dist/web/index.js +53 -0
- package/dist/web/layout/app-layout.d.ts +21 -0
- package/dist/web/layout/app-layout.js +8 -0
- package/dist/web/layout/avatar.d.ts +12 -0
- package/dist/web/layout/avatar.js +63 -0
- package/dist/web/layout/default-app-shell.d.ts +41 -0
- package/dist/web/layout/default-app-shell.js +16 -0
- package/dist/web/layout/editor-panel.d.ts +10 -0
- package/dist/web/layout/editor-panel.js +29 -0
- package/dist/web/layout/fill-classes.d.ts +9 -0
- package/dist/web/layout/fill-classes.js +15 -0
- package/dist/web/layout/filter-app-schema-navs.d.ts +7 -0
- package/dist/web/layout/filter-app-schema-navs.js +68 -0
- package/dist/web/layout/header-action-group.d.ts +6 -0
- package/dist/web/layout/header-action-group.js +8 -0
- package/dist/web/layout/header-overflow-menu.d.ts +4 -0
- package/dist/web/layout/header-overflow-menu.js +8 -0
- package/dist/web/layout/language-menu-items.d.ts +8 -0
- package/dist/web/layout/language-menu-items.js +16 -0
- package/dist/web/layout/language-switcher.d.ts +25 -0
- package/dist/web/layout/language-switcher.js +46 -0
- package/dist/web/layout/nav-tree.d.ts +19 -0
- package/dist/web/layout/nav-tree.js +536 -0
- package/dist/web/layout/page-header-slot.d.ts +25 -0
- package/dist/web/layout/page-header-slot.js +50 -0
- package/dist/web/layout/profile-menu.d.ts +13 -0
- package/dist/web/layout/profile-menu.js +6 -0
- package/dist/web/layout/shell-breadcrumb.d.ts +11 -0
- package/dist/web/layout/shell-breadcrumb.js +34 -0
- package/dist/web/layout/shell-header.d.ts +12 -0
- package/dist/web/layout/shell-header.js +159 -0
- package/dist/web/layout/sidebar-brand.d.ts +15 -0
- package/dist/web/layout/sidebar-brand.js +9 -0
- package/dist/web/layout/sidebar-panel.d.ts +41 -0
- package/dist/web/layout/sidebar-panel.js +107 -0
- package/dist/web/layout/sidebar-user.d.ts +8 -0
- package/dist/web/layout/sidebar-user.js +17 -0
- package/dist/web/layout/sidebar.d.ts +17 -0
- package/dist/web/layout/sidebar.js +11 -0
- package/dist/web/layout/target-resolver-stub.d.ts +13 -0
- package/dist/web/layout/target-resolver-stub.js +61 -0
- package/dist/web/layout/target-url.d.ts +12 -0
- package/dist/web/layout/target-url.js +77 -0
- package/dist/web/layout/theme-label.d.ts +15 -0
- package/dist/web/layout/theme-label.js +35 -0
- package/dist/web/layout/theme-menu-item.d.ts +12 -0
- package/dist/web/layout/theme-menu-item.js +16 -0
- package/dist/web/layout/theme-toggle.d.ts +17 -0
- package/dist/web/layout/theme-toggle.js +22 -0
- package/dist/web/layout/topbar.d.ts +8 -0
- package/dist/web/layout/topbar.js +4 -0
- package/dist/web/layout/workspace-shell.d.ts +63 -0
- package/dist/web/layout/workspace-shell.js +220 -0
- package/dist/web/layout/workspace-switcher.d.ts +15 -0
- package/dist/web/layout/workspace-switcher.js +36 -0
- package/dist/web/lib/accept-attr.d.ts +1 -0
- package/dist/web/lib/accept-attr.js +6 -0
- package/dist/web/lib/clamp.d.ts +1 -0
- package/dist/web/lib/clamp.js +3 -0
- package/dist/web/lib/cn.d.ts +6 -0
- package/dist/web/lib/cn.js +9 -0
- package/dist/web/lib/download.d.ts +2 -0
- package/dist/web/lib/download.js +24 -0
- package/dist/web/lib/file-ref-download.d.ts +15 -0
- package/dist/web/lib/file-ref-download.js +62 -0
- package/dist/web/lib/file-upload-form-data.d.ts +7 -0
- package/dist/web/lib/file-upload-form-data.js +11 -0
- package/dist/web/lib/resize-image.d.ts +1 -0
- package/dist/web/lib/resize-image.js +66 -0
- package/dist/web/lib/upload-file-ref.d.ts +9 -0
- package/dist/web/lib/upload-file-ref.js +29 -0
- package/dist/web/primitives/action-menu.d.ts +34 -0
- package/dist/web/primitives/action-menu.js +30 -0
- package/dist/web/primitives/calendar-popover.d.ts +13 -0
- package/dist/web/primitives/calendar-popover.js +76 -0
- package/dist/web/primitives/combobox.d.ts +56 -0
- package/dist/web/primitives/combobox.js +127 -0
- package/dist/web/primitives/date-field.d.ts +18 -0
- package/dist/web/primitives/date-field.js +74 -0
- package/dist/web/primitives/date-input.d.ts +1 -0
- package/dist/web/primitives/date-input.js +5 -0
- package/dist/web/primitives/date-parse.d.ts +11 -0
- package/dist/web/primitives/date-parse.js +159 -0
- package/dist/web/primitives/dialog.d.ts +3 -0
- package/dist/web/primitives/dialog.js +42 -0
- package/dist/web/primitives/drawer.d.ts +3 -0
- package/dist/web/primitives/drawer.js +17 -0
- package/dist/web/primitives/dropdown-menu.d.ts +15 -0
- package/dist/web/primitives/dropdown-menu.js +56 -0
- package/dist/web/primitives/embedded-list-input.d.ts +9 -0
- package/dist/web/primitives/embedded-list-input.js +382 -0
- package/dist/web/primitives/file-thumbnail.d.ts +31 -0
- package/dist/web/primitives/file-thumbnail.js +90 -0
- package/dist/web/primitives/file-upload.d.ts +21 -0
- package/dist/web/primitives/file-upload.js +56 -0
- package/dist/web/primitives/file-value-list.d.ts +3 -0
- package/dist/web/primitives/file-value-list.js +22 -0
- package/dist/web/primitives/index.d.ts +34 -0
- package/dist/web/primitives/index.js +2023 -0
- package/dist/web/primitives/json-view.d.ts +7 -0
- package/dist/web/primitives/json-view.js +84 -0
- package/dist/web/primitives/layout.d.ts +27 -0
- package/dist/web/primitives/layout.js +30 -0
- package/dist/web/primitives/lightbox.d.ts +3 -0
- package/dist/web/primitives/lightbox.js +36 -0
- package/dist/web/primitives/locale-number.d.ts +2 -0
- package/dist/web/primitives/locale-number.js +54 -0
- package/dist/web/primitives/located-timestamp-input.d.ts +22 -0
- package/dist/web/primitives/located-timestamp-input.js +22 -0
- package/dist/web/primitives/metric.d.ts +5 -0
- package/dist/web/primitives/metric.js +18 -0
- package/dist/web/primitives/modal-shell.d.ts +17 -0
- package/dist/web/primitives/modal-shell.js +9 -0
- package/dist/web/primitives/modal.d.ts +3 -0
- package/dist/web/primitives/modal.js +13 -0
- package/dist/web/primitives/money-input.d.ts +18 -0
- package/dist/web/primitives/money-input.js +122 -0
- package/dist/web/primitives/narrow-pinned-footer.d.ts +12 -0
- package/dist/web/primitives/narrow-pinned-footer.js +153 -0
- package/dist/web/primitives/number-input.d.ts +18 -0
- package/dist/web/primitives/number-input.js +53 -0
- package/dist/web/primitives/option-groups.d.ts +11 -0
- package/dist/web/primitives/option-groups.js +27 -0
- package/dist/web/primitives/page-header.d.ts +3 -0
- package/dist/web/primitives/page-header.js +52 -0
- package/dist/web/primitives/promo-panel.d.ts +3 -0
- package/dist/web/primitives/promo-panel.js +11 -0
- package/dist/web/primitives/segmented-select.d.ts +21 -0
- package/dist/web/primitives/segmented-select.js +62 -0
- package/dist/web/primitives/share-actions.d.ts +4 -0
- package/dist/web/primitives/share-actions.js +56 -0
- package/dist/web/primitives/status-badge.d.ts +3 -0
- package/dist/web/primitives/status-badge.js +5 -0
- package/dist/web/primitives/sticky-action-bar.d.ts +5 -0
- package/dist/web/primitives/sticky-action-bar.js +15 -0
- package/dist/web/primitives/tabs.d.ts +3 -0
- package/dist/web/primitives/tabs.js +107 -0
- package/dist/web/primitives/timestamp-input.d.ts +27 -0
- package/dist/web/primitives/timestamp-input.js +87 -0
- package/dist/web/primitives/toast.d.ts +19 -0
- package/dist/web/primitives/toast.js +63 -0
- package/dist/web/primitives/tz-input.d.ts +11 -0
- package/dist/web/primitives/tz-input.js +8 -0
- package/dist/web/primitives/tz-options.d.ts +4 -0
- package/dist/web/primitives/tz-options.js +17 -0
- package/dist/web/primitives/use-keyboard-inset.d.ts +1 -0
- package/dist/web/primitives/use-keyboard-inset.js +28 -0
- package/dist/web/primitives/use-narrow-viewport.d.ts +4 -0
- package/dist/web/primitives/use-narrow-viewport.js +46 -0
- package/dist/web/react-css-custom-properties.d.ts +6 -0
- package/dist/web/react-css-custom-properties.js +1 -0
- package/dist/web/sse/live-events.d.ts +15 -0
- package/dist/web/sse/live-events.js +148 -0
- package/dist/web/theme-plugin.d.ts +41 -0
- package/dist/web/theme-plugin.js +123 -0
- package/dist/web/tokens.d.ts +24 -0
- package/dist/web/tokens.js +203 -0
- package/dist/web/ui/avatar.d.ts +11 -0
- package/dist/web/ui/avatar.js +25 -0
- package/dist/web/ui/badge.d.ts +9 -0
- package/dist/web/ui/badge.js +26 -0
- package/dist/web/ui/breadcrumb.d.ts +11 -0
- package/dist/web/ui/breadcrumb.js +29 -0
- package/dist/web/ui/button.d.ts +10 -0
- package/dist/web/ui/button.js +37 -0
- package/dist/web/ui/checkbox.d.ts +4 -0
- package/dist/web/ui/checkbox.js +11 -0
- package/dist/web/ui/input.d.ts +3 -0
- package/dist/web/ui/input.js +8 -0
- package/dist/web/ui/label.d.ts +4 -0
- package/dist/web/ui/label.js +10 -0
- package/dist/web/ui/resizable.d.ts +7 -0
- package/dist/web/ui/resizable.js +16 -0
- package/dist/web/ui/separator.d.ts +4 -0
- package/dist/web/ui/separator.js +10 -0
- package/dist/web/ui/sheet.d.ts +14 -0
- package/dist/web/ui/sheet.js +42 -0
- package/dist/web/ui/sidebar.d.ts +73 -0
- package/dist/web/ui/sidebar.js +211 -0
- package/dist/web/ui/skeleton.d.ts +2 -0
- package/dist/web/ui/skeleton.js +7 -0
- package/dist/web/ui/switch.d.ts +6 -0
- package/dist/web/ui/switch.js +10 -0
- package/dist/web/ui/table.d.ts +10 -0
- package/dist/web/ui/table.js +30 -0
- package/dist/web/ui/tabs.d.ts +11 -0
- package/dist/web/ui/tabs.js +31 -0
- package/dist/web/ui/textarea.d.ts +3 -0
- package/dist/web/ui/textarea.js +8 -0
- package/dist/web/ui/tooltip.d.ts +7 -0
- package/dist/web/ui/tooltip.js +19 -0
- package/dist/web/ui/use-mobile.d.ts +1 -0
- package/dist/web/ui/use-mobile.js +16 -0
- package/dist/web/version/update-checker.d.ts +9 -0
- package/dist/web/version/update-checker.js +88 -0
- package/dist/web/widgets/ai-text-field.d.ts +36 -0
- package/dist/web/widgets/ai-text-field.js +137 -0
- package/dist/web/widgets/bounded-load-cache.d.ts +1 -0
- package/dist/web/widgets/bounded-load-cache.js +25 -0
- package/dist/web/widgets/chart-window.d.ts +58 -0
- package/dist/web/widgets/chart-window.js +190 -0
- package/dist/web/widgets/charts.d.ts +208 -0
- package/dist/web/widgets/charts.js +685 -0
- package/dist/web/widgets/collapsible-section.d.ts +10 -0
- package/dist/web/widgets/collapsible-section.js +17 -0
- package/dist/web/widgets/dashboard-list.d.ts +21 -0
- package/dist/web/widgets/dashboard-list.js +45 -0
- package/dist/web/widgets/detail-list.d.ts +15 -0
- package/dist/web/widgets/detail-list.js +8 -0
- package/dist/web/widgets/drawer.d.ts +65 -0
- package/dist/web/widgets/drawer.js +177 -0
- package/dist/web/widgets/feed-list.d.ts +13 -0
- package/dist/web/widgets/feed-list.js +9 -0
- package/dist/web/widgets/floating-panel.d.ts +30 -0
- package/dist/web/widgets/floating-panel.js +242 -0
- package/dist/web/widgets/form-fields.d.ts +93 -0
- package/dist/web/widgets/form-fields.js +50 -0
- package/dist/web/widgets/index.d.ts +28 -0
- package/dist/web/widgets/index.js +31 -0
- package/dist/web/widgets/infinity-list.d.ts +46 -0
- package/dist/web/widgets/infinity-list.js +211 -0
- package/dist/web/widgets/mode-switch.d.ts +21 -0
- package/dist/web/widgets/mode-switch.js +25 -0
- package/dist/web/widgets/pdf-preview.d.ts +10 -0
- package/dist/web/widgets/pdf-preview.js +140 -0
- package/dist/web/widgets/photo-slots.d.ts +29 -0
- package/dist/web/widgets/photo-slots.js +52 -0
- package/dist/web/widgets/plan-card.d.ts +36 -0
- package/dist/web/widgets/plan-card.js +13 -0
- package/dist/web/widgets/progress-bar.d.ts +19 -0
- package/dist/web/widgets/progress-bar.js +24 -0
- package/dist/web/widgets/progress-list.d.ts +19 -0
- package/dist/web/widgets/progress-list.js +11 -0
- package/dist/web/widgets/public-shell.d.ts +22 -0
- package/dist/web/widgets/public-shell.js +15 -0
- package/dist/web/widgets/query-table.d.ts +29 -0
- package/dist/web/widgets/query-table.js +30 -0
- package/dist/web/widgets/result-panel.d.ts +69 -0
- package/dist/web/widgets/result-panel.js +30 -0
- package/dist/web/widgets/section-card.d.ts +12 -0
- package/dist/web/widgets/section-card.js +9 -0
- package/dist/web/widgets/sheet-parts.d.ts +9 -0
- package/dist/web/widgets/sheet-parts.js +11 -0
- package/dist/web/widgets/side-by-side-table.d.ts +31 -0
- package/dist/web/widgets/side-by-side-table.js +11 -0
- package/dist/web/widgets/stat.d.ts +54 -0
- package/dist/web/widgets/stat.js +65 -0
- package/dist/web/widgets/states.d.ts +23 -0
- package/dist/web/widgets/states.js +20 -0
- package/dist/web/widgets/status-badge.d.ts +15 -0
- package/dist/web/widgets/status-badge.js +24 -0
- package/dist/web/widgets/step-bar.d.ts +35 -0
- package/dist/web/widgets/step-bar.js +60 -0
- package/dist/web/widgets/upload-zone.d.ts +24 -0
- package/dist/web/widgets/upload-zone.js +108 -0
- package/dist/web/widgets/use-draft.d.ts +20 -0
- package/dist/web/widgets/use-draft.js +21 -0
- package/dist/web/widgets/use-pointer-drag.d.ts +21 -0
- package/dist/web/widgets/use-pointer-drag.js +53 -0
- package/package.json +114 -7
- package/src/changes.json +92 -0
- package/src/web/fonts/OFL.txt +93 -0
- package/src/web/fonts/ibm-plex-mono-latin-400.woff2 +0 -0
- package/src/web/fonts/ibm-plex-mono-latin-500.woff2 +0 -0
- package/src/web/fonts/ibm-plex-mono-latin-ext-400.woff2 +0 -0
- package/src/web/fonts/ibm-plex-mono-latin-ext-500.woff2 +0 -0
- package/src/web/fonts/ibm-plex-sans-latin-400.woff2 +0 -0
- package/src/web/fonts/ibm-plex-sans-latin-500.woff2 +0 -0
- package/src/web/fonts/ibm-plex-sans-latin-600.woff2 +0 -0
- package/src/web/fonts/ibm-plex-sans-latin-ext-400.woff2 +0 -0
- package/src/web/fonts/ibm-plex-sans-latin-ext-500.woff2 +0 -0
- package/src/web/fonts/ibm-plex-sans-latin-ext-600.woff2 +0 -0
- package/src/web/styles.css +405 -0
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import { Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
2
|
import { evalFieldCondition, isFieldsEditSection, normalizeEditField, PROJECTION_DETAIL_ENTITY, sectionFieldSpecs, } from "@cosmicdrift/kumiko-framework/ui-types";
|
|
3
|
-
import { computeEditViewModel, groupIssuesByPath, relevantFieldIssues, zodErrorToFieldIssues, } from "@cosmicdrift/kumiko-headless";
|
|
4
3
|
import { propertyOf } from "@cosmicdrift/kumiko-types/type-guards";
|
|
4
|
+
import { computeEditViewModel, groupIssuesByPath, relevantFieldIssues, zodErrorToFieldIssues, } from "../headless/index.js";
|
|
5
|
+
import { changedDerivedValues } from "./form-derivation-patch.js";
|
|
5
6
|
import { RenderEditActionButton } from "./render-edit-action-button.js";
|
|
6
7
|
import { AllFieldsRequiredProvider } from "./render-field.js";
|
|
7
8
|
import { useActionMenuItems } from "./use-action-menu-items.js";
|
|
@@ -229,7 +230,7 @@ function resolveTitleTemplate(template, values, translate, fallback) {
|
|
|
229
230
|
return translate(template, values);
|
|
230
231
|
}
|
|
231
232
|
export function RenderEdit(props) {
|
|
232
|
-
const { screen, entity, featureName, initial, writeCommand, translate: translateProp, ctx, schema, onSubmit, payloadMode = "values", buildPayload, serverFieldPathPrefix, onDelete, onCancel, onReload, refreshToken, onDirtyChange, onCopyLink, actions, menuActions, onRelatedListDrawerAction, submitLabel, submitVariant, submitWithoutChanges, footerActions, summary, labelAppendix, fieldAppendix, fieldAppendixPlacement, fieldDescription, fieldAccent, markChangedFields = false, entityId: entityIdProp, extensionInitialValues, onChange, onControlsReady, fields: fieldsFilter, disabled: disabledProp = false, viewMode = false, hideActions, valueDisplay = "form", hideSectionTitles, fillScreenHeight, dirtyFooter, validateOnChange, headerRegion, buildSectionActions, leadContent, submitBlocked = false, } = props;
|
|
233
|
+
const { screen, entity, featureName, initial, writeCommand, translate: translateProp, ctx, schema, onSubmit, payloadMode = "values", buildPayload, serverFieldPathPrefix, onDelete, onCancel, onReload, refreshToken, onDirtyChange, onCopyLink, actions, menuActions, onRelatedListDrawerAction, submitLabel, submitVariant, submitWithoutChanges, footerActions, summary, labelAppendix, fieldAppendix, fieldAppendixPlacement, fieldDescription, fieldAccent, markChangedFields = false, entityId: entityIdProp, extensionInitialValues, onChange, onControlsReady, fields: fieldsFilter, disabled: disabledProp = false, viewMode = false, hideActions, valueDisplay = "form", hideSectionTitles, fillScreenHeight, dirtyFooter, validateOnChange, headerRegion, buildSectionActions, leadContent, submitBlocked = false, formDerivation, } = props;
|
|
233
234
|
// View mode is a locked form, so everything keyed on `disabled` follows.
|
|
234
235
|
const disabled = disabledProp || viewMode;
|
|
235
236
|
const i18nScreenId = props.i18nScreenId ?? screen.id;
|
|
@@ -367,6 +368,16 @@ export function RenderEdit(props) {
|
|
|
367
368
|
...(ctx !== undefined && { ctx }),
|
|
368
369
|
...(submitConfig !== undefined && { submit: submitConfig }),
|
|
369
370
|
});
|
|
371
|
+
// Derived fields are written into form state (not only displayed) so required
|
|
372
|
+
// validation and the submit payload carry them; only a real change is set, which
|
|
373
|
+
// keeps this from looping.
|
|
374
|
+
useEffect(() => {
|
|
375
|
+
if (formDerivation === undefined)
|
|
376
|
+
return;
|
|
377
|
+
const patch = changedDerivedValues(snapshot.values, formDerivation);
|
|
378
|
+
if (patch !== undefined)
|
|
379
|
+
controller.setValues(patch); // @cast-boundary form-values
|
|
380
|
+
}, [snapshot.values, formDerivation, controller]);
|
|
370
381
|
// Wired at the user-input boundary, not in controller.setField: computed
|
|
371
382
|
// fields, prefill, draft restore and action patches also call setValues
|
|
372
383
|
// after a failed submit and must not wipe the errors.
|
|
@@ -654,7 +665,9 @@ export function RenderEdit(props) {
|
|
|
654
665
|
featureName,
|
|
655
666
|
mode: writeVerb,
|
|
656
667
|
...(!isCreateMode && entityIdProp != null && { entityId: entityIdProp }),
|
|
668
|
+
...(formDerivation !== undefined && { derivation: formDerivation }),
|
|
657
669
|
}), [
|
|
670
|
+
formDerivation,
|
|
658
671
|
screen,
|
|
659
672
|
entity,
|
|
660
673
|
snapshot.values,
|
|
@@ -1075,6 +1088,7 @@ export function RenderEdit(props) {
|
|
|
1075
1088
|
wizardBackRef.current = isWizard ? handleWizardBack : () => { };
|
|
1076
1089
|
// Screen forms (entityEdit/actionForm filling the shell height) drop the card;
|
|
1077
1090
|
// the title then lives in the shell header when the shell offers a slot.
|
|
1091
|
+
const rootIssues = snapshot.errors[ROOT_ISSUE_PATH] ?? [];
|
|
1078
1092
|
const isScreenForm = fillScreenHeight === true && hideSectionTitles !== true && !insideDrawer;
|
|
1079
1093
|
const titleInShell = PageHeader !== undefined &&
|
|
1080
1094
|
pageHeaderSlotAvailable &&
|
|
@@ -1480,7 +1494,8 @@ export function RenderEdit(props) {
|
|
|
1480
1494
|
onReload();
|
|
1481
1495
|
setFormError(null);
|
|
1482
1496
|
setExtraDeleteIssues([]);
|
|
1483
|
-
}, testId: "render-edit-form-error-reload", children: translate("kumiko.actions.reload") })) : undefined, children: [_jsx(Text, { testId: "render-edit-form-error-key", children: translate(formError.i18nKey, formError.i18nParams) }),
|
|
1497
|
+
}, testId: "render-edit-form-error-reload", children: translate("kumiko.actions.reload") })) : undefined, children: [_jsx(Text, { testId: "render-edit-form-error-key", children: translate(formError.i18nKey, formError.i18nParams) }), rootIssues.map((issue) => (_jsx(Text, { testId: "render-edit-form-error-root", children: translate(issue.i18nKey, issue.params) }, `${issue.path}:${issue.i18nKey}`))), extraDeleteIssues.map((issue) => (_jsx(Text, { testId: "render-edit-form-error-extra", children: translate(issue.i18nKey, issue.params) }, `${issue.path}:${issue.i18nKey}`)))] })), formError === null &&
|
|
1498
|
+
rootIssues.map((issue) => (_jsx(Banner, { variant: "error", testId: "render-edit-root-issue", children: _jsx(Text, { children: translate(issue.i18nKey, issue.params) }) }, issue.i18nKey))), extensionErrorKey !== null && (_jsx(Banner, { variant: "error", testId: "render-edit-extension-error", children: _jsx(Text, { testId: "render-edit-extension-error-key", children: translate(extensionErrorKey) }) })), actionError !== null && (_jsx(Banner, { variant: "error", testId: "render-edit-action-error", children: actionError })), onDelete !== undefined && (_jsx(Dialog, { open: confirmDeleteOpen, onOpenChange: setConfirmDeleteOpen, title: translate("kumiko.actions.delete-confirm"), confirmLabel: translate("kumiko.actions.delete"), variant: "danger", onConfirm: async () => {
|
|
1484
1499
|
const rejection = await onDelete();
|
|
1485
1500
|
// A rejected delete (e.g. a preDelete hook) carries its reason in
|
|
1486
1501
|
// the field issues; the top-level key is only "validation failed".
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { type EditFieldViewModel, type FieldIssue } from "@cosmicdrift/kumiko-headless";
|
|
2
1
|
import { type ReactNode } from "react";
|
|
2
|
+
import { type EditFieldViewModel, type FieldIssue } from "../headless/index.ts";
|
|
3
3
|
import { type FieldProps } from "../primitives.tsx";
|
|
4
4
|
export type RenderFieldProps = {
|
|
5
5
|
readonly field: EditFieldViewModel;
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
2
|
import { isFormatSpec, SYSTEM_REFERENCE_LABELS, } from "@cosmicdrift/kumiko-framework/ui-types";
|
|
3
|
-
import { applyFormatSpec, currencyDecimals, EMPTY_VALUE_PLACEHOLDER, } from "@cosmicdrift/kumiko-headless";
|
|
4
3
|
import { propertyOf } from "@cosmicdrift/kumiko-types/type-guards";
|
|
5
4
|
import { createContext, Fragment, useCallback, useContext, useEffect, useMemo, useRef, useState, } from "react";
|
|
6
5
|
import { useAppFeatures } from "../app/app-features-context.js";
|
|
@@ -12,6 +11,8 @@ import { evalRowExtractor } from "../app/row-actions.js";
|
|
|
12
11
|
import { screenAccessAllows } from "../app/screen-access.js";
|
|
13
12
|
import { useOptionalDispatcher } from "../context/dispatcher-context.js";
|
|
14
13
|
import { useUserRoles } from "../context/user-roles-context.js";
|
|
14
|
+
import { fileIdsOf } from "../file-ids-of.js";
|
|
15
|
+
import { applyFormatSpec, currencyDecimals, EMPTY_VALUE_PLACEHOLDER, } from "../headless/index.js";
|
|
15
16
|
import { REFERENCE_COMBOBOX_LIMIT } from "../hooks/reference-limits.js";
|
|
16
17
|
import { useQuery } from "../hooks/use-query.js";
|
|
17
18
|
import { referenceOptionSource } from "../hooks/use-reference-lookup.js";
|
|
@@ -280,7 +281,7 @@ function inputId(field) {
|
|
|
280
281
|
// Doesn't resolve the `string` (cross-feature QN) FieldRenderer variant — the
|
|
281
282
|
// list-column path (DataTableCell) doesn't either, so this stays in parity.
|
|
282
283
|
function FieldRendererOutput({ field, renderer, row, appLocale, }) {
|
|
283
|
-
const { Text, JsonView } = usePrimitives();
|
|
284
|
+
const { Text, JsonView, FileValueList } = usePrimitives();
|
|
284
285
|
const t = useTranslation();
|
|
285
286
|
const componentName = !isFormatSpec(renderer) && typeof renderer === "object" && renderer !== null
|
|
286
287
|
? extensionSectionName(renderer)
|
|
@@ -293,6 +294,12 @@ function FieldRendererOutput({ field, renderer, row, appLocale, }) {
|
|
|
293
294
|
if (renderer.format === "json" && JsonView !== undefined) {
|
|
294
295
|
return (_jsx(JsonView, { value: field.value, indent: renderer.indent, testId: `field-value-${field.field}` }));
|
|
295
296
|
}
|
|
297
|
+
if (renderer.format === "file" && FileValueList !== undefined) {
|
|
298
|
+
const fileIds = fileIdsOf(field.value);
|
|
299
|
+
if (fileIds.length === 0)
|
|
300
|
+
return _jsx(Text, { testId: `field-value-${field.field}`, children: EMPTY_VALUE_PLACEHOLDER });
|
|
301
|
+
return _jsx(FileValueList, { fileIds: fileIds, testId: `field-value-${field.field}` });
|
|
302
|
+
}
|
|
296
303
|
// App locale as default when the FormatSpec declares none of its own —
|
|
297
304
|
// otherwise locale-sensitive formats (timestamp/date/number/decimal/
|
|
298
305
|
// bigInt/unit) fell back to Intl's runtime default instead of the app
|
|
@@ -494,6 +501,9 @@ function renderInput({ field, id, hasError, onChange, Input, appLocale, Banner,
|
|
|
494
501
|
if (field.type === "text" && field.format === "password") {
|
|
495
502
|
return (_jsx(Input, { kind: "password", ...common, value: stringValue(field.value), onChange: (v) => onChange(v) }));
|
|
496
503
|
}
|
|
504
|
+
if (field.type === "text" && field.format === "month") {
|
|
505
|
+
return (_jsx(Input, { kind: "month", ...common, value: stringValue(field.value), onChange: (v) => onChange(v) }));
|
|
506
|
+
}
|
|
497
507
|
// text + unknown scalar type → text input. If TextFieldDef.multiline
|
|
498
508
|
// is set (the view-model carries it), the renderer switches to
|
|
499
509
|
// textarea. longText always renders a textarea — that's the point of
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { EntityDefinition, EntityListScreenDefinition, IconKey } from "@cosmicdrift/kumiko-framework/ui-types";
|
|
2
|
-
import type { ListRowViewModel, Translate } from "@cosmicdrift/kumiko-headless";
|
|
3
2
|
import { type ReactNode } from "react";
|
|
3
|
+
import type { ListRowViewModel, Translate } from "../headless/index.ts";
|
|
4
4
|
import type { ListSort } from "../hooks/use-list-url-state.ts";
|
|
5
5
|
import { type DataTableDateRangeFacet, type DataTableFacet, type DataTableProps, type DataTableRowAction, type DataTableRowActionMode, type DataTableRowGrouping } from "../primitives.tsx";
|
|
6
6
|
import { type ListEmptyStateContent } from "./list-empty-state.tsx";
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
-
import { computeListViewModel, EMPTY_VALUE_PLACEHOLDER } from "@cosmicdrift/kumiko-headless";
|
|
3
2
|
import { useCallback, useEffect, useMemo, useRef, useState } from "react";
|
|
4
3
|
import { extensionSectionName, useExtensionSectionComponent } from "../app/extension-sections.js";
|
|
5
4
|
import { useReferenceLinkResolver } from "../app/reference-link.js";
|
|
5
|
+
import { computeListViewModel, EMPTY_VALUE_PLACEHOLDER } from "../headless/index.js";
|
|
6
6
|
import { useReferenceLookup } from "../hooks/use-reference-lookup.js";
|
|
7
7
|
import { useTranslation } from "../i18n.js";
|
|
8
8
|
import { usePageHeaderCompact, usePageHeaderSlotAvailable } from "../page-header-slot.js";
|
|
@@ -104,7 +104,7 @@ export function RenderList(props) {
|
|
|
104
104
|
const labelField = col.refLabelField ?? "id";
|
|
105
105
|
const refEntity = col.refEntity ?? "";
|
|
106
106
|
// Only a row the user can see is linkable: resolved by the server
|
|
107
|
-
// eagerload or by the lookup query. A multi-reference
|
|
107
|
+
// eagerload or by the lookup query. A multi-reference links per entry via linkItemsFor.
|
|
108
108
|
const linkFor = (value, row) => {
|
|
109
109
|
if (value === null || value === undefined || value === "" || Array.isArray(value)) {
|
|
110
110
|
return undefined;
|
|
@@ -118,6 +118,22 @@ export function RenderList(props) {
|
|
|
118
118
|
map?.has(id);
|
|
119
119
|
return resolved === true ? resolveReferenceLink(refEntity, id) : undefined;
|
|
120
120
|
};
|
|
121
|
+
const linkItemsFor = (value, row) => {
|
|
122
|
+
if (!Array.isArray(value) || value.length === 0)
|
|
123
|
+
return undefined;
|
|
124
|
+
const eagerloaded = eagerloadedRef(row, col.field);
|
|
125
|
+
const eagerById = new Map(Array.isArray(eagerloaded) ? eagerloaded.map((r) => [String(r["id"]), r]) : []);
|
|
126
|
+
return value.map((v) => {
|
|
127
|
+
const id = String(v);
|
|
128
|
+
const target = eagerById.get(id);
|
|
129
|
+
const label = String(target?.[labelField] ?? map?.get(id) ?? id);
|
|
130
|
+
// Only a row the user can see is linkable: server eagerload or lookup query.
|
|
131
|
+
const link = target !== undefined || map?.has(id) === true
|
|
132
|
+
? resolveReferenceLink(refEntity, id)
|
|
133
|
+
: undefined;
|
|
134
|
+
return { id, label, ...(link !== undefined && { link }) };
|
|
135
|
+
});
|
|
136
|
+
};
|
|
121
137
|
const renderer = (value, row) => {
|
|
122
138
|
// Tier 2.7e Server-Eagerload: wenn der Server _refs mit-
|
|
123
139
|
// schickt, lesen wir den Display-Wert direkt aus der
|
|
@@ -142,7 +158,7 @@ export function RenderList(props) {
|
|
|
142
158
|
const idStr = String(value);
|
|
143
159
|
return map?.get(idStr) ?? idStr;
|
|
144
160
|
};
|
|
145
|
-
return { ...col, renderer, linkFor };
|
|
161
|
+
return { ...col, renderer, linkFor, linkItemsFor };
|
|
146
162
|
});
|
|
147
163
|
}, [vm.columns, referenceColumns, referenceLookups, resolveReferenceLink]);
|
|
148
164
|
const enrichedVm = useMemo(() => ({
|
|
@@ -190,7 +206,7 @@ export function RenderList(props) {
|
|
|
190
206
|
// Wenn weder onCreate noch ein Override gegeben ist, fällt die
|
|
191
207
|
// DataTable auf den DataTable-Default zurück (`kumiko.list.no-entries`).
|
|
192
208
|
const composedEmptyState = emptyState ??
|
|
193
|
-
(onCreate !== undefined || emptyContent !== undefined || narrowed ? (_jsx(ListEmptyStateBody, { content: emptyContent, narrowed: narrowed, translate: translate, createButton: onCreate !== undefined && !narrowed ? (_jsx(Button, { variant: "primary", icon: "plus", onClick: onCreate, testId: "render-list-empty-create", children: effectiveCreateLabel })) : undefined })) : undefined);
|
|
209
|
+
(onCreate !== undefined || emptyContent !== undefined || narrowed ? (_jsx(ListEmptyStateBody, { content: emptyContent, narrowed: narrowed, translate: translate, createButton: onCreate !== undefined && !narrowed && !createInPageHeader ? (_jsx(Button, { variant: "primary", icon: "plus", onClick: onCreate, testId: "render-list-empty-create", children: effectiveCreateLabel })) : undefined })) : undefined);
|
|
194
210
|
// Title-Resolution: ein konventioneller i18n-Key `screen:<id>.title`.
|
|
195
211
|
// Wenn das Bundle den Key kennt, schöner Titel; sonst kommt der
|
|
196
212
|
// screenId selber raus (kein "Untitled"-Fallback — der App-Dev sieht
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import type { EditWriteFormSectionViewModel, Translate } from "@cosmicdrift/kumiko-headless";
|
|
2
1
|
import { type ReactNode } from "react";
|
|
2
|
+
import type { EditWriteFormSectionViewModel, Translate } from "../headless/index.ts";
|
|
3
3
|
export type WriteFormSectionProps = {
|
|
4
4
|
readonly section: EditWriteFormSectionViewModel;
|
|
5
5
|
readonly featureName: string;
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
-
import { I18N_KEY_PARAM } from "@cosmicdrift/kumiko-headless";
|
|
3
2
|
import { useEffect, useMemo, useRef, useState } from "react";
|
|
4
3
|
import * as z from "zod";
|
|
5
4
|
import { isPresent, REQUIRED_FIELD_I18N_KEY } from "../app/form-schema.js";
|
|
6
5
|
import { dispatcherErrorText } from "../app/write-failed-error.js";
|
|
6
|
+
import { I18N_KEY_PARAM } from "../headless/index.js";
|
|
7
7
|
import { useForm } from "../hooks/use-form.js";
|
|
8
8
|
import { useTranslation } from "../i18n.js";
|
|
9
9
|
import { STICKY_PRIMARY_ACTION_PROP, usePrimitives } from "../primitives.js";
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import type { Dispatcher, DispatcherStatus } from "@cosmicdrift/kumiko-headless";
|
|
2
1
|
import { type ReactNode } from "react";
|
|
2
|
+
import type { Dispatcher, DispatcherStatus } from "../headless/index.ts";
|
|
3
3
|
import { type QueryPools } from "./query-pool.ts";
|
|
4
4
|
export type DispatcherProviderProps = {
|
|
5
5
|
readonly dispatcher: Dispatcher;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function fileIdsOf(value: unknown): readonly string[];
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/** Inner markup for a 24x24 viewBox, stroked via the `.icon` CSS class. "ai" renders as a text badge instead — see render.ts. */
|
|
2
|
+
export const ICONS = {
|
|
3
|
+
ui: '<rect class="icon" x="3" y="4" width="18" height="15" rx="1.5"/><path class="icon" d="M3 8h18"/>',
|
|
4
|
+
api: '<path class="icon" d="M8 6l-5 6 5 6"/><path class="icon" d="M16 6l5 6-5 6"/>',
|
|
5
|
+
handler: '<path class="icon" d="M8 4l-4 8 4 8"/><path class="icon" d="M16 4l4 8-4 8"/><path class="icon" d="M11 20l2-16"/>',
|
|
6
|
+
"event-store": '<path class="icon" d="M4 6c0-1.5 3.6-2.5 8-2.5S20 4.5 20 6s-3.6 2.5-8 2.5S4 7.5 4 6z"/><path class="icon" d="M4 6v12c0 1.5 3.6 2.5 8 2.5s8-1 8-2.5V6"/><path class="icon" d="M4 12c0 1.5 3.6 2.5 8 2.5s8-1 8-2.5"/>',
|
|
7
|
+
database: '<path class="icon" d="M4 6c0-1.5 3.6-2.5 8-2.5S20 4.5 20 6s-3.6 2.5-8 2.5S4 7.5 4 6z"/><path class="icon" d="M4 6v12c0 1.5 3.6 2.5 8 2.5s8-1 8-2.5V6"/>',
|
|
8
|
+
inbox: '<path class="icon" d="M3 6h18v13H3z"/><path class="icon" d="M3 6l9 7 9-7"/>',
|
|
9
|
+
broadcast: '<path class="icon" d="M12 20v-1"/><path class="icon" d="M8.5 15.5a5 5 0 017 0"/><path class="icon" d="M5 12a9 9 0 0114 0"/>',
|
|
10
|
+
person: '<circle class="icon" cx="12" cy="8" r="3.2"/><path class="icon" d="M5 20c0-4 3-6 7-6s7 2 7 6"/>',
|
|
11
|
+
check: '<path class="icon" d="M5 12l5 5L20 6"/>',
|
|
12
|
+
stop: '<rect class="icon" x="7" y="7" width="10" height="10" rx="1.5"/>',
|
|
13
|
+
box: '<rect class="icon" x="4" y="4" width="16" height="16" rx="2"/>',
|
|
14
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { renderFlow } from "./render.js";
|
|
@@ -0,0 +1,234 @@
|
|
|
1
|
+
import { escapeHtml } from "../headless/index.js";
|
|
2
|
+
import { ICONS } from "./icons.js";
|
|
3
|
+
const BADGE = 24;
|
|
4
|
+
const ICON_SIZE = 13;
|
|
5
|
+
const PAD_X = 9.6;
|
|
6
|
+
const GAP_BADGE_TEXT = 8;
|
|
7
|
+
const GAP_RIGHT = 11.2;
|
|
8
|
+
const ROW_GAP = 35;
|
|
9
|
+
const COL_GAP = 22;
|
|
10
|
+
const MIN_CARD_WIDTH = 120;
|
|
11
|
+
const TITLE_SIZE = 11.2;
|
|
12
|
+
const SUB_SIZE = 9.2;
|
|
13
|
+
const STEP_SECONDS = 1.2;
|
|
14
|
+
function textWidth(text, fontSize, bold) {
|
|
15
|
+
return text.length * fontSize * (bold ? 0.62 : 0.56);
|
|
16
|
+
}
|
|
17
|
+
function cardSize(node) {
|
|
18
|
+
const titleWidth = textWidth(node.title, TITLE_SIZE, true);
|
|
19
|
+
const subWidth = node.sub ? textWidth(node.sub, SUB_SIZE, false) : 0;
|
|
20
|
+
const content = Math.max(titleWidth, subWidth);
|
|
21
|
+
const width = Math.max(MIN_CARD_WIDTH, BADGE + GAP_BADGE_TEXT + content + PAD_X + GAP_RIGHT);
|
|
22
|
+
const height = node.sub ? 42 : 32;
|
|
23
|
+
return { width, height };
|
|
24
|
+
}
|
|
25
|
+
function assertEdgesReferenceKnownNodes(spec) {
|
|
26
|
+
const ids = new Set(spec.nodes.map((n) => n.id));
|
|
27
|
+
for (const edge of spec.edges) {
|
|
28
|
+
if (!ids.has(edge.from))
|
|
29
|
+
throw new Error(`FlowSpec: edge references unknown node "${edge.from}"`);
|
|
30
|
+
if (!ids.has(edge.to))
|
|
31
|
+
throw new Error(`FlowSpec: edge references unknown node "${edge.to}"`);
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
function buildAdjacency(spec) {
|
|
35
|
+
const children = new Map();
|
|
36
|
+
const inDegree = new Map();
|
|
37
|
+
for (const node of spec.nodes)
|
|
38
|
+
inDegree.set(node.id, 0);
|
|
39
|
+
for (const edge of spec.edges) {
|
|
40
|
+
children.set(edge.from, [...(children.get(edge.from) ?? []), edge]);
|
|
41
|
+
inDegree.set(edge.to, (inDegree.get(edge.to) ?? 0) + 1);
|
|
42
|
+
}
|
|
43
|
+
return { children, inDegree };
|
|
44
|
+
}
|
|
45
|
+
/** Longest-path depth per node via Kahn's algorithm; throws if the graph has no root or contains a cycle. */
|
|
46
|
+
function longestPathDepths(spec, children, inDegree) {
|
|
47
|
+
const depth = new Map();
|
|
48
|
+
const queue = spec.nodes.filter((n) => inDegree.get(n.id) === 0).map((n) => n.id);
|
|
49
|
+
if (queue.length === 0 && spec.nodes.length > 0) {
|
|
50
|
+
throw new Error("FlowSpec: no root node found (every node has an incoming edge — check for a cycle)");
|
|
51
|
+
}
|
|
52
|
+
for (const id of queue)
|
|
53
|
+
depth.set(id, 0);
|
|
54
|
+
const remaining = new Map(inDegree);
|
|
55
|
+
let visited = 0;
|
|
56
|
+
for (const id of queue) {
|
|
57
|
+
visited += 1;
|
|
58
|
+
for (const edge of children.get(id) ?? []) {
|
|
59
|
+
const next = Math.max(depth.get(edge.to) ?? 0, (depth.get(id) ?? 0) + 1);
|
|
60
|
+
depth.set(edge.to, next);
|
|
61
|
+
const left = (remaining.get(edge.to) ?? 0) - 1;
|
|
62
|
+
remaining.set(edge.to, left);
|
|
63
|
+
if (left === 0)
|
|
64
|
+
queue.push(edge.to);
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
if (visited < spec.nodes.length) {
|
|
68
|
+
throw new Error("FlowSpec: graph has a cycle — a flow diagram must be acyclic");
|
|
69
|
+
}
|
|
70
|
+
return depth;
|
|
71
|
+
}
|
|
72
|
+
function computeDepths(spec) {
|
|
73
|
+
assertEdgesReferenceKnownNodes(spec);
|
|
74
|
+
const { children, inDegree } = buildAdjacency(spec);
|
|
75
|
+
return longestPathDepths(spec, children, inDegree);
|
|
76
|
+
}
|
|
77
|
+
function layout(spec) {
|
|
78
|
+
const depthById = computeDepths(spec);
|
|
79
|
+
const maxDepth = Math.max(0, ...[...depthById.values()]);
|
|
80
|
+
const rows = Array.from({ length: maxDepth + 1 }, () => []);
|
|
81
|
+
for (const node of spec.nodes)
|
|
82
|
+
rows[depthById.get(node.id) ?? 0]?.push(node);
|
|
83
|
+
// Siblings in the same row share one card size (the row's largest), so a
|
|
84
|
+
// row of 3+ always lands symmetrically under its parent — an odd sibling
|
|
85
|
+
// count with mismatched widths otherwise throws the middle card off-center.
|
|
86
|
+
const sizedRows = rows.map((row) => {
|
|
87
|
+
const sizes = row.map((n) => cardSize(n));
|
|
88
|
+
return {
|
|
89
|
+
row,
|
|
90
|
+
width: Math.max(MIN_CARD_WIDTH, ...sizes.map((s) => s.width)),
|
|
91
|
+
height: Math.max(0, ...sizes.map((s) => s.height)),
|
|
92
|
+
};
|
|
93
|
+
});
|
|
94
|
+
const rowWidths = sizedRows.map(({ row, width }) => row.length * width + COL_GAP * Math.max(0, row.length - 1));
|
|
95
|
+
const canvasWidth = Math.max(...rowWidths, MIN_CARD_WIDTH) + 40;
|
|
96
|
+
const centerX = canvasWidth / 2;
|
|
97
|
+
const placed = new Map();
|
|
98
|
+
let y = 20;
|
|
99
|
+
for (const { row, width, height } of sizedRows) {
|
|
100
|
+
const rowWidth = row.length * width + COL_GAP * Math.max(0, row.length - 1);
|
|
101
|
+
let x = centerX - rowWidth / 2;
|
|
102
|
+
for (const node of row) {
|
|
103
|
+
placed.set(node.id, { node, depth: depthById.get(node.id) ?? 0, x, y, width, height });
|
|
104
|
+
x += width + COL_GAP;
|
|
105
|
+
}
|
|
106
|
+
y += height + ROW_GAP;
|
|
107
|
+
}
|
|
108
|
+
const canvasHeight = y - ROW_GAP + 20;
|
|
109
|
+
return { placed, width: canvasWidth, height: canvasHeight, maxDepth };
|
|
110
|
+
}
|
|
111
|
+
function computeTiming(placed, spec, maxDepth) {
|
|
112
|
+
const totalSeconds = STEP_SECONDS * (maxDepth + 1) + STEP_SECONDS * 0.5;
|
|
113
|
+
const timingByEdge = new Map();
|
|
114
|
+
const arrivalByNode = new Map();
|
|
115
|
+
for (const edge of spec.edges) {
|
|
116
|
+
const from = placed.get(edge.from);
|
|
117
|
+
const to = placed.get(edge.to);
|
|
118
|
+
if (!from || !to)
|
|
119
|
+
continue;
|
|
120
|
+
const span = Math.max(1, to.depth - from.depth);
|
|
121
|
+
const startT = from.depth * STEP_SECONDS;
|
|
122
|
+
const travelT = STEP_SECONDS * 0.75 * span;
|
|
123
|
+
const startFrac = startT / totalSeconds;
|
|
124
|
+
const endFrac = Math.min(0.98, (startT + travelT) / totalSeconds);
|
|
125
|
+
timingByEdge.set(edge, { startFrac, endFrac });
|
|
126
|
+
arrivalByNode.set(edge.to, Math.max(arrivalByNode.get(edge.to) ?? 0, endFrac));
|
|
127
|
+
}
|
|
128
|
+
return { totalSeconds, timingByEdge, arrivalByNode };
|
|
129
|
+
}
|
|
130
|
+
const CORNER_RADIUS = 8; // 10 * 0.8
|
|
131
|
+
function edgePath(from, to) {
|
|
132
|
+
const x1 = from.x + from.width / 2;
|
|
133
|
+
const y1 = from.y + from.height;
|
|
134
|
+
const x2 = to.x + to.width / 2;
|
|
135
|
+
const y2 = to.y;
|
|
136
|
+
if (Math.abs(x1 - x2) < 1) {
|
|
137
|
+
return { d: `M ${x1} ${y1} L ${x2} ${y2}`, midX: x1, midY: (y1 + y2) / 2 };
|
|
138
|
+
}
|
|
139
|
+
const midY = (y1 + y2) / 2;
|
|
140
|
+
const dir = x2 > x1 ? 1 : -1;
|
|
141
|
+
const r = Math.min(CORNER_RADIUS, Math.abs(x2 - x1) / 2, midY - y1, y2 - midY);
|
|
142
|
+
const d = `M ${x1} ${y1} L ${x1} ${midY - r} ` +
|
|
143
|
+
`Q ${x1} ${midY} ${x1 + dir * r} ${midY} ` +
|
|
144
|
+
`L ${x2 - dir * r} ${midY} ` +
|
|
145
|
+
`Q ${x2} ${midY} ${x2} ${midY + r} ` +
|
|
146
|
+
`L ${x2} ${y2}`;
|
|
147
|
+
return { d, midX: (x1 + x2) / 2, midY };
|
|
148
|
+
}
|
|
149
|
+
/** Renders a FlowSpec (a small acyclic node/edge graph) to a self-contained, animated SVG diagram string for embedding in docs pages. */
|
|
150
|
+
export function renderFlow(spec) {
|
|
151
|
+
const { placed, width, height, maxDepth } = layout(spec);
|
|
152
|
+
const { totalSeconds, timingByEdge, arrivalByNode } = computeTiming(placed, spec, maxDepth);
|
|
153
|
+
const wires = [];
|
|
154
|
+
const dots = [];
|
|
155
|
+
const labels = [];
|
|
156
|
+
for (const edge of spec.edges) {
|
|
157
|
+
const from = placed.get(edge.from);
|
|
158
|
+
const to = placed.get(edge.to);
|
|
159
|
+
if (!from || !to)
|
|
160
|
+
continue;
|
|
161
|
+
const { d, midX, midY } = edgePath(from, to);
|
|
162
|
+
// html-ok: d is built in edgePath() from numeric coordinates only, never user input
|
|
163
|
+
wires.push(`<path class="wire" d="${d}"/>`);
|
|
164
|
+
if (edge.label) {
|
|
165
|
+
labels.push(`<text class="edge-label" x="${midX}" y="${midY - 6}" text-anchor="middle">${escapeHtml(edge.label)}</text>`);
|
|
166
|
+
}
|
|
167
|
+
const timing = timingByEdge.get(edge);
|
|
168
|
+
if (!timing)
|
|
169
|
+
continue;
|
|
170
|
+
const { startFrac, endFrac } = timing;
|
|
171
|
+
const fadeIn = Math.min(startFrac + 0.02, endFrac);
|
|
172
|
+
const fadeOut = Math.min(endFrac + 0.02, 1);
|
|
173
|
+
dots.push(`<circle r="3.2" class="dot">` +
|
|
174
|
+
`<animateMotion dur="${totalSeconds}s" repeatCount="indefinite" calcMode="linear" ` +
|
|
175
|
+
`keyPoints="0;0;1;1" keyTimes="0;${startFrac};${endFrac};1" path="${d}"/>` +
|
|
176
|
+
`<animate attributeName="opacity" dur="${totalSeconds}s" repeatCount="indefinite" ` +
|
|
177
|
+
`values="0;0;1;1;0;0" keyTimes="0;${startFrac};${fadeIn};${endFrac};${fadeOut};1"/>` +
|
|
178
|
+
`</circle>`);
|
|
179
|
+
}
|
|
180
|
+
const cards = spec.nodes.map((node) => {
|
|
181
|
+
const p = placed.get(node.id);
|
|
182
|
+
if (!p)
|
|
183
|
+
return "";
|
|
184
|
+
const arrival = arrivalByNode.get(node.id) ?? 0.02;
|
|
185
|
+
const pulseEnd = Math.min(arrival + 0.05, 1);
|
|
186
|
+
const badgeX = p.x + PAD_X;
|
|
187
|
+
const badgeY = p.y + (p.height - BADGE) / 2;
|
|
188
|
+
const textX = badgeX + BADGE + GAP_BADGE_TEXT;
|
|
189
|
+
const isTerminal = node.kind === "terminal";
|
|
190
|
+
const badgeFill = isTerminal
|
|
191
|
+
? "var(--flow-card)"
|
|
192
|
+
: node.icon === "check"
|
|
193
|
+
? "var(--flow-green)"
|
|
194
|
+
: "var(--flow-badge)";
|
|
195
|
+
const badgeClass = isTerminal ? "flow-badge flow-badge-terminal" : "flow-badge";
|
|
196
|
+
const iconGroupClass = isTerminal ? "flow-icon-terminal" : "";
|
|
197
|
+
const iconInset = (BADGE - ICON_SIZE) / 2;
|
|
198
|
+
const iconInner = node.icon === "ai"
|
|
199
|
+
? `<text class="flow-ai-label" x="${BADGE / 2}" y="${BADGE / 2 + 3}" text-anchor="middle">AI</text>`
|
|
200
|
+
: // html-ok: ICONS is a static internal map keyed by the FlowIcon union, not user input
|
|
201
|
+
`<svg class="${iconGroupClass}" x="${iconInset}" y="${iconInset}" width="${ICON_SIZE}" height="${ICON_SIZE}" viewBox="0 0 24 24">${ICONS[node.icon ?? "box"]}</svg>`;
|
|
202
|
+
return `<g>
|
|
203
|
+
<rect class="flow-card" x="${p.x}" y="${p.y}" width="${p.width}" height="${p.height}" rx="9">
|
|
204
|
+
<animate attributeName="stroke" dur="${totalSeconds}s" repeatCount="indefinite"
|
|
205
|
+
values="var(--flow-card-border);var(--flow-card-border);var(--flow-violet);var(--flow-card-border);var(--flow-card-border)"
|
|
206
|
+
keyTimes="0;${Math.max(0, arrival - 0.02)};${arrival};${pulseEnd};1"/>
|
|
207
|
+
</rect>
|
|
208
|
+
<g transform="translate(${badgeX}, ${badgeY})">
|
|
209
|
+
<rect class="${badgeClass}" width="${BADGE}" height="${BADGE}" rx="6" fill="${badgeFill}"/>
|
|
210
|
+
${iconInner}
|
|
211
|
+
</g>
|
|
212
|
+
<text class="flow-title" x="${textX}" y="${node.sub ? p.y + p.height / 2 - 2 : p.y + p.height / 2 + 3.5}">${escapeHtml(node.title)}</text>
|
|
213
|
+
${node.sub ? `<text class="flow-sub" x="${textX}" y="${p.y + p.height / 2 + 11}">${escapeHtml(node.sub)}</text>` : ""}
|
|
214
|
+
</g>`;
|
|
215
|
+
});
|
|
216
|
+
// html-ok: wires/dots/labels/cards hold only fragments built from numeric
|
|
217
|
+
// coordinates or already-escaped text (escapeHtml above), never raw user input
|
|
218
|
+
return `<div class="kumiko-flow">
|
|
219
|
+
<svg width="${width}" height="${height}" viewBox="0 0 ${width} ${height}" xmlns="http://www.w3.org/2000/svg" role="img" aria-label="Flow diagram">
|
|
220
|
+
${
|
|
221
|
+
// html-ok: see comment above return
|
|
222
|
+
wires.join("\n ")}
|
|
223
|
+
${
|
|
224
|
+
// html-ok: see comment above return
|
|
225
|
+
dots.join("\n ")}
|
|
226
|
+
${
|
|
227
|
+
// html-ok: see comment above return
|
|
228
|
+
labels.join("\n ")}
|
|
229
|
+
${
|
|
230
|
+
// html-ok: see comment above return
|
|
231
|
+
cards.join("\n ")}
|
|
232
|
+
</svg>
|
|
233
|
+
</div>`;
|
|
234
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
export type FlowIcon = "ui" | "api" | "handler" | "event-store" | "database" | "broadcast" | "ai" | "inbox" | "person" | "check" | "stop" | "box";
|
|
2
|
+
export type FlowNodeKind = "process" | "decision" | "terminal";
|
|
3
|
+
export interface FlowNode {
|
|
4
|
+
id: string;
|
|
5
|
+
title: string;
|
|
6
|
+
sub?: string;
|
|
7
|
+
icon?: FlowIcon;
|
|
8
|
+
kind?: FlowNodeKind;
|
|
9
|
+
}
|
|
10
|
+
export interface FlowEdge {
|
|
11
|
+
from: string;
|
|
12
|
+
to: string;
|
|
13
|
+
label?: string;
|
|
14
|
+
}
|
|
15
|
+
export interface FlowSpec {
|
|
16
|
+
nodes: FlowNode[];
|
|
17
|
+
edges: FlowEdge[];
|
|
18
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
package/dist/format-when.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { toInstant } from "
|
|
1
|
+
import { toInstant } from "./headless/index.js";
|
|
2
2
|
// Shared timestamp formatter for operator screens (audit log, job runs) —
|
|
3
3
|
// falls back to the raw ISO string on an unparseable value instead of "Invalid Date".
|
|
4
4
|
export function formatWhen(value) {
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
export declare const APEX_NAV_MENU_CSS = "\n .nav-toggle { display: none; }\n .nav-toggle__trigger { display: none; align-items: center; justify-content: center;\n width: 2.25rem; height: 2.25rem; border-radius: 0.5rem; cursor: pointer;\n color: var(--fg-muted); list-style: none; }\n .nav-toggle__trigger::-webkit-details-marker { display: none; }\n .nav-toggle__trigger:hover { color: var(--fg); background: var(--bg-muted); }\n .nav-toggle__trigger svg { width: 1.35rem; height: 1.35rem; }\n .apex-dark .nav-toggle__trigger { color: var(--on-dark-muted); }\n .apex-dark .nav-toggle__trigger:hover { color: var(--on-dark); background: rgba(255,255,255,0.08); }\n\n .nav-menu { position: relative; display: inline-flex; }\n .nav-menu__trigger { display: inline-flex; align-items: center; gap: 0.3rem;\n font: inherit; font-size: 0.9375rem; color: var(--fg-muted);\n cursor: pointer; list-style: none; }\n .nav-menu__trigger::-webkit-details-marker { display: none; }\n .nav-menu__trigger:hover { color: var(--fg); }\n .nav-menu__chev { display: inline-flex; transition: transform 0.15s; opacity: 0.7; }\n .nav-menu__chev svg { width: 0.95em; height: 0.95em; }\n .nav-menu[open] .nav-menu__chev { transform: rotate(180deg); }\n .nav-menu__panel { position: absolute; top: calc(100% + 0.5rem); left: 0; z-index: 20;\n min-width: 21rem; padding: 0.5rem; background: var(--bg-card); color: var(--fg);\n border: 1px solid var(--border); border-radius: 0.75rem; box-shadow: var(--shadow);\n flex-direction: column; gap: 0.125rem; }\n .nav-menu[open] .nav-menu__panel { display: flex; }\n .nav-menu__item { display: flex; gap: 0.75rem; align-items: flex-start;\n padding: 0.6rem 0.7rem; border-radius: 0.5rem; color: var(--fg); }\n .nav-menu__item:hover { background: var(--bg-muted); color: var(--fg); }\n .nav-menu__icon { flex: none; display: inline-flex; align-items: center; justify-content: center;\n width: 2rem; height: 2rem; border-radius: 0.5rem;\n background: color-mix(in srgb, var(--primary) 12%, transparent); color: var(--primary); }\n .nav-menu__icon svg { width: 1.1rem; height: 1.1rem; }\n .nav-menu__text { display: flex; flex-direction: column; gap: 0.1rem; }\n .nav-menu__title { font-weight: 600; font-size: 0.9rem; line-height: 1.2; }\n .nav-menu__desc { font-size: 0.8rem; color: var(--fg-muted); line-height: 1.35; }\n .nav-menu__sep { height: 1px; background: var(--border); margin: 0.375rem 0.3rem; }\n .nav-menu__more { display: inline-flex; padding: 0.4rem 0.7rem; font-size: 0.85rem; font-weight: 600; color: var(--primary); }\n .nav-menu__more:hover { color: var(--primary-hover); }\n .apex-dark .nav-menu__trigger { color: var(--on-dark-muted); }\n .apex-dark .nav-menu__trigger:hover { color: var(--on-dark); }\n /* The panel is a light popover; its links must NOT inherit the dark-chrome\n nav-link color (.apex-dark .nav-links a, specificity 0,2,1) or a consumer's\n own .nav-links a. Pin both link types with matching specificity (0,2,1) so\n titles + the footer link stay readable in the dark theme. */\n .nav-menu__panel a.nav-menu__item { color: var(--fg); }\n .nav-menu__panel a.nav-menu__item:hover { color: var(--fg); }\n .nav-menu__panel a.nav-menu__more { color: var(--primary); }\n .nav-menu__panel a.nav-menu__more:hover { color: var(--primary-hover); }\n";
|
|
2
|
+
export declare const APEX_NAV_TOGGLE_RESPONSIVE_CSS = "\n @media (max-width: 640px) {\n .nav { position: relative; }\n .nav .nav-toggle { display: inline-flex; }\n .nav .nav-toggle__trigger { display: inline-flex; }\n .nav-toggle[open] > .nav-links { display: flex; flex-direction: column; align-items: stretch;\n gap: 0.25rem; position: absolute; top: calc(100% + 0.5rem); left: 0; right: 0; z-index: 30;\n background: var(--bg-card); border: 1px solid var(--border); border-radius: 0.75rem;\n box-shadow: var(--shadow); padding: 0.75rem; }\n .nav-toggle[open] > .nav-links > a { color: var(--fg); padding: 0.4rem 0.25rem; }\n .nav-toggle[open] > .nav-links > a:hover { color: var(--fg); }\n .nav-toggle .nav-menu { display: block; }\n .nav-toggle .nav-menu__panel { position: static; min-width: 0;\n margin-top: 0.375rem; box-shadow: none; }\n }\n";
|
|
3
|
+
export declare const APEX_STRUCTURAL_CSS: string;
|