@softov/scena 0.1.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +42 -0
- package/dist/controls/command.d.ts +18 -0
- package/dist/controls/command.js +150 -0
- package/dist/controls/events.d.ts +3 -0
- package/dist/controls/events.js +43 -0
- package/dist/controls/index.d.ts +10 -0
- package/dist/controls/index.js +10 -0
- package/dist/controls/keybinding.d.ts +9 -0
- package/dist/controls/keybinding.js +94 -0
- package/dist/controls/layout.d.ts +16 -0
- package/dist/controls/layout.js +201 -0
- package/dist/controls/manifest.d.ts +21 -0
- package/dist/controls/manifest.js +219 -0
- package/dist/controls/session.d.ts +16 -0
- package/dist/controls/session.js +95 -0
- package/dist/controls/shell.d.ts +8 -0
- package/dist/controls/shell.js +48 -0
- package/dist/controls/storage/layout-local.d.ts +6 -0
- package/dist/controls/storage/layout-local.js +47 -0
- package/dist/controls/storage/session-local.d.ts +5 -0
- package/dist/controls/storage/session-local.js +38 -0
- package/dist/controls/when.d.ts +7 -0
- package/dist/controls/when.js +226 -0
- package/dist/converters/a2ui-v0.10.d.ts +23 -0
- package/dist/converters/a2ui-v0.10.js +136 -0
- package/dist/converters/index.d.ts +1 -0
- package/dist/converters/index.js +1 -0
- package/dist/core/backends/modus-backend.d.ts +13 -0
- package/dist/core/backends/modus-backend.js +115 -0
- package/dist/core/backends/storage-backend.d.ts +7 -0
- package/dist/core/backends/storage-backend.js +73 -0
- package/dist/core/backends/yjs-backend.d.ts +3 -0
- package/dist/core/backends/yjs-backend.js +44 -0
- package/dist/core/binding-resolver.d.ts +7 -0
- package/dist/core/binding-resolver.js +106 -0
- package/dist/core/component-graph.d.ts +6 -0
- package/dist/core/component-graph.js +77 -0
- package/dist/core/component-registry.d.ts +7 -0
- package/dist/core/component-registry.js +87 -0
- package/dist/core/computed-dsl.d.ts +2 -0
- package/dist/core/computed-dsl.js +267 -0
- package/dist/core/converter-registry.d.ts +2 -0
- package/dist/core/converter-registry.js +37 -0
- package/dist/core/disposable.d.ts +3 -0
- package/dist/core/disposable.js +19 -0
- package/dist/core/dynamic-resolver.d.ts +12 -0
- package/dist/core/dynamic-resolver.js +134 -0
- package/dist/core/index.d.ts +44 -0
- package/dist/core/index.js +48 -0
- package/dist/core/label.d.ts +2 -0
- package/dist/core/label.js +14 -0
- package/dist/core/mount-menu.d.ts +2 -0
- package/dist/core/mount-menu.js +23 -0
- package/dist/core/mount-surface.d.ts +15 -0
- package/dist/core/mount-surface.js +214 -0
- package/dist/core/path-resolver.d.ts +14 -0
- package/dist/core/path-resolver.js +169 -0
- package/dist/core/permissions.d.ts +2 -0
- package/dist/core/permissions.js +50 -0
- package/dist/core/reactive-store.d.ts +17 -0
- package/dist/core/reactive-store.js +496 -0
- package/dist/core/scena.d.ts +2 -0
- package/dist/core/scena.js +115 -0
- package/dist/core/surface-presentation.d.ts +6 -0
- package/dist/core/surface-presentation.js +12 -0
- package/dist/i18n/i18n-backend.d.ts +2 -0
- package/dist/i18n/i18n-backend.js +35 -0
- package/dist/i18n/registry.d.ts +32 -0
- package/dist/i18n/registry.js +200 -0
- package/dist/porta/Limen.css +50 -0
- package/dist/porta/Limen.d.ts +16 -0
- package/dist/porta/Limen.js +14 -0
- package/dist/porta/PortaContext.d.ts +10 -0
- package/dist/porta/PortaContext.js +20 -0
- package/dist/porta/PortaLock.css +14 -0
- package/dist/porta/PortaLock.d.ts +10 -0
- package/dist/porta/PortaLock.js +13 -0
- package/dist/porta/SigillumGate.d.ts +8 -0
- package/dist/porta/SigillumGate.js +7 -0
- package/dist/porta/commands.d.ts +3 -0
- package/dist/porta/commands.js +125 -0
- package/dist/porta/index.d.ts +18 -0
- package/dist/porta/index.js +22 -0
- package/dist/porta/login-form.block.d.ts +2 -0
- package/dist/porta/login-form.block.js +7 -0
- package/dist/porta/match.d.ts +2 -0
- package/dist/porta/match.js +20 -0
- package/dist/porta/provider.d.ts +59 -0
- package/dist/porta/provider.js +1 -0
- package/dist/porta/providers/examples/google-oauth.d.ts +6 -0
- package/dist/porta/providers/examples/google-oauth.js +21 -0
- package/dist/porta/providers/examples/index.d.ts +6 -0
- package/dist/porta/providers/examples/index.js +3 -0
- package/dist/porta/providers/examples/magic-link.d.ts +8 -0
- package/dist/porta/providers/examples/magic-link.js +31 -0
- package/dist/porta/providers/examples/sms-otp.d.ts +9 -0
- package/dist/porta/providers/examples/sms-otp.js +31 -0
- package/dist/porta/providers/password.d.ts +12 -0
- package/dist/porta/providers/password.js +46 -0
- package/dist/porta/register-blocks.d.ts +3 -0
- package/dist/porta/register-blocks.js +31 -0
- package/dist/porta/register.d.ts +15 -0
- package/dist/porta/register.js +31 -0
- package/dist/porta/sigillum.d.ts +19 -0
- package/dist/porta/sigillum.js +41 -0
- package/dist/react/DefaultShell.d.ts +1 -0
- package/dist/react/DefaultShell.js +37 -0
- package/dist/react/Scena.d.ts +9 -0
- package/dist/react/Scena.js +20 -0
- package/dist/react/ScenaProvider.d.ts +8 -0
- package/dist/react/ScenaProvider.js +13 -0
- package/dist/react/ShellSplitter.d.ts +13 -0
- package/dist/react/ShellSplitter.js +88 -0
- package/dist/react/SurfaceArea.d.ts +13 -0
- package/dist/react/SurfaceArea.js +75 -0
- package/dist/react/Translate.d.ts +8 -0
- package/dist/react/Translate.js +10 -0
- package/dist/react/ViewMount.d.ts +12 -0
- package/dist/react/ViewMount.js +268 -0
- package/dist/react/core.d.ts +6 -0
- package/dist/react/core.js +10 -0
- package/dist/react/hooks/useCommand.d.ts +1 -0
- package/dist/react/hooks/useCommand.js +6 -0
- package/dist/react/hooks/useI18n.d.ts +9 -0
- package/dist/react/hooks/useI18n.js +16 -0
- package/dist/react/hooks/useLabel.d.ts +2 -0
- package/dist/react/hooks/useLabel.js +19 -0
- package/dist/react/hooks/useLayout.d.ts +2 -0
- package/dist/react/hooks/useLayout.js +10 -0
- package/dist/react/hooks/useMounts.d.ts +2 -0
- package/dist/react/hooks/useMounts.js +17 -0
- package/dist/react/hooks/useStore.d.ts +3 -0
- package/dist/react/hooks/useStore.js +40 -0
- package/dist/react/hooks/useStoreLabel.d.ts +3 -0
- package/dist/react/hooks/useStoreLabel.js +25 -0
- package/dist/react/hooks/useSurfacePresentation.d.ts +4 -0
- package/dist/react/hooks/useSurfacePresentation.js +16 -0
- package/dist/react/index.d.ts +20 -0
- package/dist/react/index.js +20 -0
- package/dist/react/mount-context.d.ts +8 -0
- package/dist/react/mount-context.js +20 -0
- package/dist/react/useSurfaceResize.d.ts +39 -0
- package/dist/react/useSurfaceResize.js +135 -0
- package/dist/runtime/args-schema.d.ts +11 -0
- package/dist/runtime/args-schema.js +45 -0
- package/dist/runtime/builtins.d.ts +3 -0
- package/dist/runtime/builtins.js +193 -0
- package/dist/runtime/client-handlers.d.ts +3 -0
- package/dist/runtime/client-handlers.js +19 -0
- package/dist/runtime/in-memory-socket.d.ts +7 -0
- package/dist/runtime/in-memory-socket.js +53 -0
- package/dist/runtime/index.d.ts +10 -0
- package/dist/runtime/index.js +7 -0
- package/dist/runtime/layout-commands.d.ts +5 -0
- package/dist/runtime/layout-commands.js +548 -0
- package/dist/runtime/opener-commands.d.ts +17 -0
- package/dist/runtime/opener-commands.js +96 -0
- package/dist/runtime/surface-bridge.d.ts +15 -0
- package/dist/runtime/surface-bridge.js +116 -0
- package/dist/styles/bar.css +155 -0
- package/dist/styles/base.css +285 -0
- package/dist/styles/geometry.css +32 -0
- package/dist/styles/index.d.ts +29 -0
- package/dist/styles/index.js +109 -0
- package/dist/styles/scrollbar.css +45 -0
- package/dist/styles/surface.css +179 -0
- package/dist/styles/theme.css +3 -0
- package/dist/styles/themes/dark.css +30 -0
- package/dist/styles/themes/light.css +1 -0
- package/dist/styles/themes/tokens.css +222 -0
- package/dist/types/binding-resolver.d.ts +30 -0
- package/dist/types/binding-resolver.js +1 -0
- package/dist/types/colors.d.ts +7 -0
- package/dist/types/colors.js +59 -0
- package/dist/types/command.d.ts +62 -0
- package/dist/types/command.js +1 -0
- package/dist/types/component-graph.d.ts +72 -0
- package/dist/types/component-graph.js +40 -0
- package/dist/types/component-registry.d.ts +70 -0
- package/dist/types/component-registry.js +1 -0
- package/dist/types/converter-registry.d.ts +17 -0
- package/dist/types/converter-registry.js +1 -0
- package/dist/types/disposable.d.ts +3 -0
- package/dist/types/disposable.js +1 -0
- package/dist/types/events.d.ts +75 -0
- package/dist/types/events.js +1 -0
- package/dist/types/host.d.ts +50 -0
- package/dist/types/host.js +1 -0
- package/dist/types/index.d.ts +23 -0
- package/dist/types/index.js +23 -0
- package/dist/types/keybinding.d.ts +36 -0
- package/dist/types/keybinding.js +1 -0
- package/dist/types/label.d.ts +9 -0
- package/dist/types/label.js +1 -0
- package/dist/types/layout.d.ts +117 -0
- package/dist/types/layout.js +1 -0
- package/dist/types/manifest.d.ts +152 -0
- package/dist/types/manifest.js +1 -0
- package/dist/types/mount-menu.d.ts +8 -0
- package/dist/types/mount-menu.js +1 -0
- package/dist/types/mount-surface.d.ts +87 -0
- package/dist/types/mount-surface.js +1 -0
- package/dist/types/permissions.d.ts +18 -0
- package/dist/types/permissions.js +1 -0
- package/dist/types/query.d.ts +34 -0
- package/dist/types/query.js +7 -0
- package/dist/types/reactive-store.d.ts +39 -0
- package/dist/types/reactive-store.js +1 -0
- package/dist/types/scena.d.ts +53 -0
- package/dist/types/scena.js +1 -0
- package/dist/types/scope-backend.d.ts +16 -0
- package/dist/types/scope-backend.js +1 -0
- package/dist/types/session.d.ts +39 -0
- package/dist/types/session.js +1 -0
- package/dist/types/shell.d.ts +21 -0
- package/dist/types/shell.js +1 -0
- package/dist/types/when.d.ts +10 -0
- package/dist/types/when.js +1 -0
- package/dist/ui/_utils.d.ts +8 -0
- package/dist/ui/_utils.js +53 -0
- package/dist/ui/campus/CampusMappa.d.ts +18 -0
- package/dist/ui/campus/CampusMappa.js +106 -0
- package/dist/ui/campus/CampusNodus.d.ts +25 -0
- package/dist/ui/campus/CampusNodus.js +211 -0
- package/dist/ui/campus/CampusStratum.d.ts +13 -0
- package/dist/ui/campus/CampusStratum.js +20 -0
- package/dist/ui/campus/CampusVelum.d.ts +7 -0
- package/dist/ui/campus/CampusVelum.js +12 -0
- package/dist/ui/campus/CampusView.d.ts +27 -0
- package/dist/ui/campus/CampusView.js +420 -0
- package/dist/ui/campus/context.d.ts +13 -0
- package/dist/ui/campus/context.js +12 -0
- package/dist/ui/campus/index.d.ts +14 -0
- package/dist/ui/campus/index.js +11 -0
- package/dist/ui/campus/stratum-context.d.ts +2 -0
- package/dist/ui/campus/stratum-context.js +10 -0
- package/dist/ui/campus/types.d.ts +47 -0
- package/dist/ui/campus/types.js +4 -0
- package/dist/ui/chart/BarChart.css +53 -0
- package/dist/ui/chart/BarChart.d.ts +24 -0
- package/dist/ui/chart/BarChart.js +32 -0
- package/dist/ui/chart/Donut.css +15 -0
- package/dist/ui/chart/Donut.d.ts +15 -0
- package/dist/ui/chart/Donut.js +18 -0
- package/dist/ui/chart/LineChart.css +8 -0
- package/dist/ui/chart/LineChart.d.ts +24 -0
- package/dist/ui/chart/LineChart.js +29 -0
- package/dist/ui/chart/catalog.d.ts +2 -0
- package/dist/ui/chart/catalog.js +7 -0
- package/dist/ui/chart/index.d.ts +6 -0
- package/dist/ui/chart/index.js +4 -0
- package/dist/ui/control/Button.css +7 -0
- package/dist/ui/control/Button.d.ts +17 -0
- package/dist/ui/control/Button.js +17 -0
- package/dist/ui/control/CheckBox.css +16 -0
- package/dist/ui/control/CheckBox.d.ts +15 -0
- package/dist/ui/control/CheckBox.js +23 -0
- package/dist/ui/control/Checks.css +6 -0
- package/dist/ui/control/Checks.d.ts +9 -0
- package/dist/ui/control/Checks.js +10 -0
- package/dist/ui/control/ChoicePicker.css +16 -0
- package/dist/ui/control/ChoicePicker.d.ts +25 -0
- package/dist/ui/control/ChoicePicker.js +38 -0
- package/dist/ui/control/DateTimeInput.css +1 -0
- package/dist/ui/control/DateTimeInput.d.ts +22 -0
- package/dist/ui/control/DateTimeInput.js +41 -0
- package/dist/ui/control/LocaleToggle.css +38 -0
- package/dist/ui/control/LocaleToggle.d.ts +11 -0
- package/dist/ui/control/LocaleToggle.js +23 -0
- package/dist/ui/control/ReloadButton.d.ts +6 -0
- package/dist/ui/control/ReloadButton.js +9 -0
- package/dist/ui/control/Slider.css +2 -0
- package/dist/ui/control/Slider.d.ts +21 -0
- package/dist/ui/control/Slider.js +37 -0
- package/dist/ui/control/TextField.css +0 -0
- package/dist/ui/control/TextField.d.ts +25 -0
- package/dist/ui/control/TextField.js +36 -0
- package/dist/ui/control/_field-parts.css +102 -0
- package/dist/ui/control/_field-parts.d.ts +15 -0
- package/dist/ui/control/_field-parts.js +17 -0
- package/dist/ui/control/catalog.d.ts +2 -0
- package/dist/ui/control/catalog.js +10 -0
- package/dist/ui/control/index.d.ts +13 -0
- package/dist/ui/control/index.js +11 -0
- package/dist/ui/data/DataTable.d.ts +19 -0
- package/dist/ui/data/DataTable.js +20 -0
- package/dist/ui/data/Filter.d.ts +13 -0
- package/dist/ui/data/Filter.js +56 -0
- package/dist/ui/data/List.css +16 -0
- package/dist/ui/data/List.d.ts +15 -0
- package/dist/ui/data/List.js +18 -0
- package/dist/ui/data/Listable.css +245 -0
- package/dist/ui/data/Listable.d.ts +60 -0
- package/dist/ui/data/Listable.js +209 -0
- package/dist/ui/data/Pagination.d.ts +5 -0
- package/dist/ui/data/Pagination.js +43 -0
- package/dist/ui/data/Tree.css +118 -0
- package/dist/ui/data/Tree.d.ts +45 -0
- package/dist/ui/data/Tree.js +170 -0
- package/dist/ui/data/catalog.d.ts +2 -0
- package/dist/ui/data/catalog.js +7 -0
- package/dist/ui/data/index.d.ts +11 -0
- package/dist/ui/data/index.js +7 -0
- package/dist/ui/display/AddPlaceholder.d.ts +6 -0
- package/dist/ui/display/AddPlaceholder.js +24 -0
- package/dist/ui/display/Alert.css +42 -0
- package/dist/ui/display/Alert.d.ts +14 -0
- package/dist/ui/display/Alert.js +13 -0
- package/dist/ui/display/Avatar.css +19 -0
- package/dist/ui/display/Avatar.d.ts +16 -0
- package/dist/ui/display/Avatar.js +52 -0
- package/dist/ui/display/Badge.css +26 -0
- package/dist/ui/display/Badge.d.ts +16 -0
- package/dist/ui/display/Badge.js +9 -0
- package/dist/ui/display/Card.css +15 -0
- package/dist/ui/display/Card.d.ts +11 -0
- package/dist/ui/display/Card.js +8 -0
- package/dist/ui/display/DetailContainer.d.ts +6 -0
- package/dist/ui/display/DetailContainer.js +7 -0
- package/dist/ui/display/DetailHeader.css +53 -0
- package/dist/ui/display/DetailHeader.d.ts +22 -0
- package/dist/ui/display/DetailHeader.js +8 -0
- package/dist/ui/display/DetailList.css +26 -0
- package/dist/ui/display/DetailList.d.ts +13 -0
- package/dist/ui/display/DetailList.js +5 -0
- package/dist/ui/display/DetailNotFound.d.ts +17 -0
- package/dist/ui/display/DetailNotFound.js +39 -0
- package/dist/ui/display/Divider.css +6 -0
- package/dist/ui/display/Divider.d.ts +8 -0
- package/dist/ui/display/Divider.js +16 -0
- package/dist/ui/display/Divisor.css +30 -0
- package/dist/ui/display/Divisor.d.ts +11 -0
- package/dist/ui/display/Divisor.js +43 -0
- package/dist/ui/display/Icon.css +10 -0
- package/dist/ui/display/Icon.d.ts +14 -0
- package/dist/ui/display/Icon.js +144 -0
- package/dist/ui/display/Image.css +1 -0
- package/dist/ui/display/Image.d.ts +16 -0
- package/dist/ui/display/Image.js +19 -0
- package/dist/ui/display/Markdown.css +38 -0
- package/dist/ui/display/Markdown.d.ts +8 -0
- package/dist/ui/display/Markdown.js +140 -0
- package/dist/ui/display/Progress.css +39 -0
- package/dist/ui/display/Progress.d.ts +15 -0
- package/dist/ui/display/Progress.js +17 -0
- package/dist/ui/display/SectionTitle.d.ts +6 -0
- package/dist/ui/display/SectionTitle.js +6 -0
- package/dist/ui/display/Skeleton.css +20 -0
- package/dist/ui/display/Skeleton.d.ts +11 -0
- package/dist/ui/display/Skeleton.js +11 -0
- package/dist/ui/display/Spinner.css +20 -0
- package/dist/ui/display/Spinner.d.ts +12 -0
- package/dist/ui/display/Spinner.js +12 -0
- package/dist/ui/display/Svg.d.ts +13 -0
- package/dist/ui/display/Svg.js +17 -0
- package/dist/ui/display/Text.css +20 -0
- package/dist/ui/display/Text.d.ts +13 -0
- package/dist/ui/display/Text.js +15 -0
- package/dist/ui/display/catalog.d.ts +2 -0
- package/dist/ui/display/catalog.js +12 -0
- package/dist/ui/display/index.d.ts +22 -0
- package/dist/ui/display/index.js +14 -0
- package/dist/ui/embed/HtmlEmbed.d.ts +12 -0
- package/dist/ui/embed/HtmlEmbed.js +16 -0
- package/dist/ui/embed/index.d.ts +2 -0
- package/dist/ui/embed/index.js +1 -0
- package/dist/ui/forms/DangerZone.d.ts +8 -0
- package/dist/ui/forms/DangerZone.js +31 -0
- package/dist/ui/forms/Field.css +15 -0
- package/dist/ui/forms/Field.d.ts +28 -0
- package/dist/ui/forms/Field.js +25 -0
- package/dist/ui/forms/FieldGroup.css +15 -0
- package/dist/ui/forms/FieldGroup.d.ts +7 -0
- package/dist/ui/forms/FieldGroup.js +7 -0
- package/dist/ui/forms/Form.css +14 -0
- package/dist/ui/forms/Form.d.ts +18 -0
- package/dist/ui/forms/Form.js +17 -0
- package/dist/ui/forms/FormActions.css +11 -0
- package/dist/ui/forms/FormActions.d.ts +18 -0
- package/dist/ui/forms/FormActions.js +10 -0
- package/dist/ui/forms/FormSection.css +19 -0
- package/dist/ui/forms/FormSection.d.ts +7 -0
- package/dist/ui/forms/FormSection.js +7 -0
- package/dist/ui/forms/LoginForm.css +105 -0
- package/dist/ui/forms/LoginForm.d.ts +12 -0
- package/dist/ui/forms/LoginForm.js +137 -0
- package/dist/ui/forms/SchemaForm.css +81 -0
- package/dist/ui/forms/SchemaForm.d.ts +26 -0
- package/dist/ui/forms/SchemaForm.js +186 -0
- package/dist/ui/forms/SettingsContainer.d.ts +8 -0
- package/dist/ui/forms/SettingsContainer.js +8 -0
- package/dist/ui/forms/catalog.d.ts +2 -0
- package/dist/ui/forms/catalog.js +11 -0
- package/dist/ui/forms/index.d.ts +19 -0
- package/dist/ui/forms/index.js +12 -0
- package/dist/ui/forms/schema-walk.d.ts +50 -0
- package/dist/ui/forms/schema-walk.js +116 -0
- package/dist/ui/index.d.ts +58 -0
- package/dist/ui/index.js +63 -0
- package/dist/ui/layout/BarLayout.d.ts +2 -0
- package/dist/ui/layout/BarLayout.js +18 -0
- package/dist/ui/layout/Column.css +6 -0
- package/dist/ui/layout/Column.d.ts +12 -0
- package/dist/ui/layout/Column.js +13 -0
- package/dist/ui/layout/FloatingLayout.d.ts +2 -0
- package/dist/ui/layout/FloatingLayout.js +12 -0
- package/dist/ui/layout/Grid.css +5 -0
- package/dist/ui/layout/Grid.d.ts +13 -0
- package/dist/ui/layout/Grid.js +19 -0
- package/dist/ui/layout/InlineLayout.d.ts +2 -0
- package/dist/ui/layout/InlineLayout.js +13 -0
- package/dist/ui/layout/MountTitle.d.ts +12 -0
- package/dist/ui/layout/MountTitle.js +42 -0
- package/dist/ui/layout/RailLayout.d.ts +2 -0
- package/dist/ui/layout/RailLayout.js +38 -0
- package/dist/ui/layout/Row.css +16 -0
- package/dist/ui/layout/Row.d.ts +13 -0
- package/dist/ui/layout/Row.js +21 -0
- package/dist/ui/layout/SectionHeader.d.ts +10 -0
- package/dist/ui/layout/SectionHeader.js +65 -0
- package/dist/ui/layout/SingleLayout.d.ts +2 -0
- package/dist/ui/layout/SingleLayout.js +25 -0
- package/dist/ui/layout/SpatialCard.d.ts +9 -0
- package/dist/ui/layout/SpatialCard.js +30 -0
- package/dist/ui/layout/SpatialLayout.d.ts +2 -0
- package/dist/ui/layout/SpatialLayout.js +446 -0
- package/dist/ui/layout/SplitLayout.d.ts +2 -0
- package/dist/ui/layout/SplitLayout.js +159 -0
- package/dist/ui/layout/Splitter.d.ts +12 -0
- package/dist/ui/layout/Splitter.js +64 -0
- package/dist/ui/layout/StackHeader.d.ts +9 -0
- package/dist/ui/layout/StackHeader.js +87 -0
- package/dist/ui/layout/StackLayout.d.ts +2 -0
- package/dist/ui/layout/StackLayout.js +137 -0
- package/dist/ui/layout/TabLayout.d.ts +2 -0
- package/dist/ui/layout/TabLayout.js +145 -0
- package/dist/ui/layout/TabPanelLayout.d.ts +20 -0
- package/dist/ui/layout/TabPanelLayout.js +615 -0
- package/dist/ui/layout/catalog.d.ts +2 -0
- package/dist/ui/layout/catalog.js +10 -0
- package/dist/ui/layout/index.d.ts +17 -0
- package/dist/ui/layout/index.js +17 -0
- package/dist/ui/layout/register.d.ts +3 -0
- package/dist/ui/layout/register.js +25 -0
- package/dist/ui/media/Audio.css +1 -0
- package/dist/ui/media/Audio.d.ts +12 -0
- package/dist/ui/media/Audio.js +8 -0
- package/dist/ui/media/Video.css +1 -0
- package/dist/ui/media/Video.d.ts +16 -0
- package/dist/ui/media/Video.js +9 -0
- package/dist/ui/media/catalog.d.ts +2 -0
- package/dist/ui/media/catalog.js +5 -0
- package/dist/ui/media/index.d.ts +2 -0
- package/dist/ui/media/index.js +3 -0
- package/dist/ui/menu/ActionList.css +262 -0
- package/dist/ui/menu/ActionList.d.ts +19 -0
- package/dist/ui/menu/ActionList.js +369 -0
- package/dist/ui/menu/ContainerMenu.d.ts +13 -0
- package/dist/ui/menu/ContainerMenu.js +57 -0
- package/dist/ui/menu/ContextMenu.d.ts +27 -0
- package/dist/ui/menu/ContextMenu.js +93 -0
- package/dist/ui/menu/index.d.ts +10 -0
- package/dist/ui/menu/index.js +7 -0
- package/dist/ui/menu/token.d.ts +22 -0
- package/dist/ui/menu/token.js +145 -0
- package/dist/ui/menu/useChatPicker.d.ts +24 -0
- package/dist/ui/menu/useChatPicker.js +210 -0
- package/dist/ui/navigation/Breadcrumb.css +30 -0
- package/dist/ui/navigation/Breadcrumb.d.ts +14 -0
- package/dist/ui/navigation/Breadcrumb.js +12 -0
- package/dist/ui/navigation/Link.css +13 -0
- package/dist/ui/navigation/Link.d.ts +18 -0
- package/dist/ui/navigation/Link.js +43 -0
- package/dist/ui/navigation/Tabs.css +39 -0
- package/dist/ui/navigation/Tabs.d.ts +18 -0
- package/dist/ui/navigation/Tabs.js +55 -0
- package/dist/ui/navigation/Toolbar.css +25 -0
- package/dist/ui/navigation/Toolbar.d.ts +12 -0
- package/dist/ui/navigation/Toolbar.js +21 -0
- package/dist/ui/navigation/catalog.d.ts +2 -0
- package/dist/ui/navigation/catalog.js +5 -0
- package/dist/ui/navigation/index.d.ts +8 -0
- package/dist/ui/navigation/index.js +5 -0
- package/dist/ui/overlay/Modal.css +35 -0
- package/dist/ui/overlay/Modal.d.ts +12 -0
- package/dist/ui/overlay/Modal.js +57 -0
- package/dist/ui/overlay/Popup.d.ts +12 -0
- package/dist/ui/overlay/Popup.js +74 -0
- package/dist/ui/overlay/catalog.d.ts +2 -0
- package/dist/ui/overlay/catalog.js +4 -0
- package/dist/ui/overlay/index.d.ts +1 -0
- package/dist/ui/overlay/index.js +2 -0
- package/dist/ui/register.d.ts +6 -0
- package/dist/ui/register.js +26 -0
- package/package.json +115 -0
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import { jsx as _jsx, Fragment as _Fragment } from "react/jsx-runtime";
|
|
2
|
+
import { Suspense, useEffect, useState, } from 'react';
|
|
3
|
+
import { useScena } from './ScenaProvider.js';
|
|
4
|
+
import { useLayout } from './hooks/useLayout.js';
|
|
5
|
+
import { useMounts } from './hooks/useMounts.js';
|
|
6
|
+
import { MountWrapper, ViewMount } from './ViewMount.js';
|
|
7
|
+
import { useSurfaceResize } from './useSurfaceResize.js';
|
|
8
|
+
function renderOneMount(mount) {
|
|
9
|
+
return (_jsx(MountWrapper, { mountKey: mount.key, dataContext: mount.dataContext, children: _jsx("div", { className: "oo-mount", "data-mount-key": mount.key, children: _jsx(ViewMount, { node: mount.component }) }) }));
|
|
10
|
+
}
|
|
11
|
+
function FallbackLayout({ mounts }) {
|
|
12
|
+
return (_jsx(_Fragment, { children: mounts.map((m) => (_jsx("div", { style: { display: 'contents' }, children: renderOneMount(m) }, m.key))) }));
|
|
13
|
+
}
|
|
14
|
+
export function SurfaceArea({ surface, layout, style, className, presentation = 'docked', resize, }) {
|
|
15
|
+
const scena = useScena();
|
|
16
|
+
const layoutState = useLayout();
|
|
17
|
+
const mounts = useMounts(surface);
|
|
18
|
+
const resizeBinding = useSurfaceResize(surface, presentation, resize);
|
|
19
|
+
const surfaceState = layoutState.surfaces[surface] ?? { visible: true };
|
|
20
|
+
const layoutId = surfaceState.layout ?? layout ?? 'default';
|
|
21
|
+
const [registryTick, setRegistryTick] = useState(0);
|
|
22
|
+
useEffect(() => {
|
|
23
|
+
const sub = scena.events.on('scena:registry:changed', (payload) => {
|
|
24
|
+
if (payload.registry === 'layouts') {
|
|
25
|
+
setRegistryTick((t) => t + 1);
|
|
26
|
+
}
|
|
27
|
+
});
|
|
28
|
+
return () => sub.dispose();
|
|
29
|
+
}, [scena]);
|
|
30
|
+
void registryTick;
|
|
31
|
+
const layoutDef = scena.layouts.get(layoutId);
|
|
32
|
+
const setSurfaceState = (patch) => {
|
|
33
|
+
scena.layout.setSurface(surface, patch);
|
|
34
|
+
};
|
|
35
|
+
const layoutProps = {
|
|
36
|
+
surface,
|
|
37
|
+
mounts,
|
|
38
|
+
state: surfaceState,
|
|
39
|
+
presentation,
|
|
40
|
+
setState: setSurfaceState,
|
|
41
|
+
renderMount: renderOneMount,
|
|
42
|
+
onActivate: (key) => scena.surfaces.focus(key),
|
|
43
|
+
onClose: (key, opts) => scena.surfaces.close(key, opts),
|
|
44
|
+
onReorder: (fromIndex, toIndex) => {
|
|
45
|
+
const persistedOrder = surfaceState.split?.order ?? [];
|
|
46
|
+
const orderSet = new Set(persistedOrder);
|
|
47
|
+
const orderedKnown = persistedOrder.filter((k) => mounts.some((m) => m.key === k));
|
|
48
|
+
const newKeys = mounts.filter((m) => !orderSet.has(m.key)).map((m) => m.key);
|
|
49
|
+
const next = [...orderedKnown, ...newKeys];
|
|
50
|
+
const [moved] = next.splice(fromIndex, 1);
|
|
51
|
+
if (moved !== undefined)
|
|
52
|
+
next.splice(toIndex, 0, moved);
|
|
53
|
+
// Spread the existing split so newer fields like `pinned` survive
|
|
54
|
+
// the write; the prior explicit pick dropped anything not listed.
|
|
55
|
+
scena.layout.setSurface(surface, {
|
|
56
|
+
split: {
|
|
57
|
+
...(surfaceState.split ?? {}),
|
|
58
|
+
order: next,
|
|
59
|
+
},
|
|
60
|
+
});
|
|
61
|
+
},
|
|
62
|
+
};
|
|
63
|
+
return (_jsx("div", { "data-surface": surface, "data-presentation": presentation, className: [
|
|
64
|
+
'oo-surface',
|
|
65
|
+
`oo-surface--${surface.replace(':', '-')}`,
|
|
66
|
+
className,
|
|
67
|
+
]
|
|
68
|
+
.filter(Boolean)
|
|
69
|
+
.join(' '), style: style, ...resizeBinding, children: layoutDef ? ((() => {
|
|
70
|
+
// Layout components are lazy (see ui/layout/register.ts) — render
|
|
71
|
+
// inside Suspense so the first use of a strategy can load its chunk.
|
|
72
|
+
const Layout = layoutDef.component;
|
|
73
|
+
return (_jsx(Suspense, { fallback: _jsx("div", { children: "Loading..." }), children: _jsx(Layout, { ...layoutProps }) }));
|
|
74
|
+
})()) : (_jsx(FallbackLayout, { mounts: mounts })) }));
|
|
75
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { Fragment as _Fragment, jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { useI18n } from './hooks/useI18n.js';
|
|
3
|
+
// Renders a translated message reactively — re-renders on locale switch. For
|
|
4
|
+
// hand-written JSX where a label/value is a ReactNode AND you're outside a
|
|
5
|
+
// component (config, column defs) so you can't call useI18n directly. For
|
|
6
|
+
// declarative ComponentNodes, bind `{ path: '$/t/<key>' }` instead.
|
|
7
|
+
export function Translate({ k, ns, ...params }) {
|
|
8
|
+
const { t } = useI18n(ns);
|
|
9
|
+
return _jsx(_Fragment, { children: t(k, params) });
|
|
10
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { type ReactNode } from 'react';
|
|
2
|
+
import type { BindingPath, ComponentNode } from '../types/component-graph.js';
|
|
3
|
+
interface ViewMountProps {
|
|
4
|
+
node: ComponentNode;
|
|
5
|
+
}
|
|
6
|
+
export declare function ViewMount({ node }: ViewMountProps): import("react").JSX.Element;
|
|
7
|
+
export declare function MountWrapper({ mountKey, dataContext, children, }: {
|
|
8
|
+
mountKey: string;
|
|
9
|
+
dataContext?: BindingPath;
|
|
10
|
+
children: ReactNode;
|
|
11
|
+
}): import("react").JSX.Element;
|
|
12
|
+
export {};
|
|
@@ -0,0 +1,268 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { useCallback, useEffect, useReducer, useRef, useState, } from 'react';
|
|
3
|
+
import { isAction, isComponentNode, isDataBinding, isDynamicChildList, isFunctionCall, } from '../types/component-graph.js';
|
|
4
|
+
import { useScena } from './ScenaProvider.js';
|
|
5
|
+
import { DataContextContext, MountContext, WriteContext, useCurrentMountKey, useDataContext, } from './mount-context.js';
|
|
6
|
+
import { joinAbsolute, readPath } from '../core/path-resolver.js';
|
|
7
|
+
import { resolveAction, resolveDynamicValue, writeDynamic, } from '../core/dynamic-resolver.js';
|
|
8
|
+
import { rewriteLocal } from '../core/reactive-store.js';
|
|
9
|
+
const RESERVED_KEYS = new Set(['id', 'component', '$meta']);
|
|
10
|
+
const reactComponentCache = new WeakMap();
|
|
11
|
+
const reactLoadingPromises = new WeakMap();
|
|
12
|
+
async function loadReactComponent(def) {
|
|
13
|
+
if (def.renderer.kind !== 'react') {
|
|
14
|
+
throw new Error(`Cannot load non-react component "${def.component}" through React adapter`);
|
|
15
|
+
}
|
|
16
|
+
const cached = reactComponentCache.get(def);
|
|
17
|
+
if (cached)
|
|
18
|
+
return cached;
|
|
19
|
+
let pending = reactLoadingPromises.get(def);
|
|
20
|
+
if (pending)
|
|
21
|
+
return pending;
|
|
22
|
+
pending = def.renderer.load().then((mod) => {
|
|
23
|
+
const C = mod.default;
|
|
24
|
+
reactComponentCache.set(def, C);
|
|
25
|
+
return C;
|
|
26
|
+
});
|
|
27
|
+
reactLoadingPromises.set(def, pending);
|
|
28
|
+
return pending;
|
|
29
|
+
}
|
|
30
|
+
// Compute the absolute store path a DataBinding resolves to in this render,
|
|
31
|
+
// applying mount-local rewriting and data-context joining. Returns undefined
|
|
32
|
+
// when the path can't be normalized (e.g., relative path with no data context).
|
|
33
|
+
function normalizePath(path, mountKey, dataContext) {
|
|
34
|
+
try {
|
|
35
|
+
if (path.startsWith('/') && !path.startsWith('$/')) {
|
|
36
|
+
return joinAbsolute(dataContext, path);
|
|
37
|
+
}
|
|
38
|
+
return rewriteLocal(path, mountKey);
|
|
39
|
+
}
|
|
40
|
+
catch {
|
|
41
|
+
return undefined;
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
// Walks every prop value of `node` and collects the absolute store paths the
|
|
45
|
+
// renderer needs to subscribe to so re-renders fire when source data changes.
|
|
46
|
+
function collectPaths(node, mountKey, dataContext, out) {
|
|
47
|
+
for (const [k, v] of Object.entries(node)) {
|
|
48
|
+
if (RESERVED_KEYS.has(k))
|
|
49
|
+
continue;
|
|
50
|
+
collectFromValue(v, mountKey, dataContext, out);
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
function collectFromValue(v, mountKey, dataContext, out) {
|
|
54
|
+
if (v === null || typeof v !== 'object')
|
|
55
|
+
return;
|
|
56
|
+
if (isComponentNode(v)) {
|
|
57
|
+
// Nested ViewMount handles its own subscriptions.
|
|
58
|
+
return;
|
|
59
|
+
}
|
|
60
|
+
// Order matters: more-specific shapes first, so DataBinding's "just path"
|
|
61
|
+
// structural guard doesn't accidentally catch a `{ template, path }`
|
|
62
|
+
// DynamicChildList or `{ event }`/`{ functionCall }` Action.
|
|
63
|
+
if (isAction(v)) {
|
|
64
|
+
if ('event' in v && v.event.context) {
|
|
65
|
+
for (const arg of Object.values(v.event.context)) {
|
|
66
|
+
collectFromValue(arg, mountKey, dataContext, out);
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
else if ('functionCall' in v && v.functionCall.args) {
|
|
70
|
+
for (const arg of Object.values(v.functionCall.args)) {
|
|
71
|
+
collectFromValue(arg, mountKey, dataContext, out);
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
return;
|
|
75
|
+
}
|
|
76
|
+
if (isDynamicChildList(v)) {
|
|
77
|
+
const abs = normalizePath(v.path, mountKey, dataContext);
|
|
78
|
+
if (abs)
|
|
79
|
+
out.add(abs);
|
|
80
|
+
return;
|
|
81
|
+
}
|
|
82
|
+
if (isFunctionCall(v)) {
|
|
83
|
+
if (v.args) {
|
|
84
|
+
for (const arg of Object.values(v.args)) {
|
|
85
|
+
collectFromValue(arg, mountKey, dataContext, out);
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
return;
|
|
89
|
+
}
|
|
90
|
+
if (isDataBinding(v)) {
|
|
91
|
+
const abs = normalizePath(v.path, mountKey, dataContext);
|
|
92
|
+
if (abs)
|
|
93
|
+
out.add(abs);
|
|
94
|
+
return;
|
|
95
|
+
}
|
|
96
|
+
if (Array.isArray(v)) {
|
|
97
|
+
for (const item of v)
|
|
98
|
+
collectFromValue(item, mountKey, dataContext, out);
|
|
99
|
+
return;
|
|
100
|
+
}
|
|
101
|
+
for (const inner of Object.values(v)) {
|
|
102
|
+
collectFromValue(inner, mountKey, dataContext, out);
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
// Resolves one prop value to its render-time form:
|
|
106
|
+
// ComponentNode → <ViewMount node={...} />
|
|
107
|
+
// ComponentNode[] → array of <ViewMount />
|
|
108
|
+
// { template, path } → array of <ViewMount /> per item; each gets a data context
|
|
109
|
+
// DataBinding → resolved store value
|
|
110
|
+
// FunctionCall → resolved (invoked) value
|
|
111
|
+
// Action → 0-arg async handler
|
|
112
|
+
// literal / object → pass through (recurse into nested arrays/objects)
|
|
113
|
+
function resolveProp(v, scena, mountKey, dataContext) {
|
|
114
|
+
if (v === null || typeof v !== 'object')
|
|
115
|
+
return v;
|
|
116
|
+
if (isComponentNode(v)) {
|
|
117
|
+
return _jsx(ViewMount, { node: v });
|
|
118
|
+
}
|
|
119
|
+
if (Array.isArray(v) && v.every(isComponentNode)) {
|
|
120
|
+
return v.map((n, i) => (_jsx(ViewMount, { node: n }, n.id ?? i)));
|
|
121
|
+
}
|
|
122
|
+
if (isAction(v)) {
|
|
123
|
+
return resolveAction(v, dataContext, scena, mountKey);
|
|
124
|
+
}
|
|
125
|
+
if (isDynamicChildList(v)) {
|
|
126
|
+
const listValue = readPath(scena.store, dataContext, v.path);
|
|
127
|
+
if (!Array.isArray(listValue))
|
|
128
|
+
return [];
|
|
129
|
+
const baseAbs = normalizePath(v.path, mountKey, dataContext);
|
|
130
|
+
return listValue.map((_, i) => {
|
|
131
|
+
const itemContext = baseAbs
|
|
132
|
+
? `${baseAbs}/${i}`
|
|
133
|
+
: undefined;
|
|
134
|
+
return (_jsx(DataContextContext.Provider, { value: itemContext, children: _jsx(ViewMount, { node: v.template }) }, i));
|
|
135
|
+
});
|
|
136
|
+
}
|
|
137
|
+
if (isFunctionCall(v)) {
|
|
138
|
+
return resolveDynamicValue(v, dataContext, scena);
|
|
139
|
+
}
|
|
140
|
+
if (isDataBinding(v)) {
|
|
141
|
+
return readPath(scena.store, dataContext, v.path);
|
|
142
|
+
}
|
|
143
|
+
if (Array.isArray(v)) {
|
|
144
|
+
return v.map((item) => resolveProp(item, scena, mountKey, dataContext));
|
|
145
|
+
}
|
|
146
|
+
// Plain object — recurse element-wise. Useful for nested arg structs.
|
|
147
|
+
const out = {};
|
|
148
|
+
for (const [k, inner] of Object.entries(v)) {
|
|
149
|
+
out[k] = resolveProp(inner, scena, mountKey, dataContext);
|
|
150
|
+
}
|
|
151
|
+
return out;
|
|
152
|
+
}
|
|
153
|
+
export function ViewMount({ node }) {
|
|
154
|
+
const scena = useScena();
|
|
155
|
+
const mountKey = useCurrentMountKey();
|
|
156
|
+
const dataContext = useDataContext();
|
|
157
|
+
const [, force] = useReducer((x) => x + 1, 0);
|
|
158
|
+
const [LoadedComponent, setLoadedComponent] = useState(null);
|
|
159
|
+
const def = scena.components.get(node.component);
|
|
160
|
+
useEffect(() => {
|
|
161
|
+
const sub = scena.events.on('scena:registry:changed', (payload) => {
|
|
162
|
+
if (payload.registry === 'components')
|
|
163
|
+
force();
|
|
164
|
+
});
|
|
165
|
+
return () => sub.dispose();
|
|
166
|
+
}, [scena]);
|
|
167
|
+
useEffect(() => {
|
|
168
|
+
if (!def || def.renderer.kind !== 'react') {
|
|
169
|
+
setLoadedComponent(null);
|
|
170
|
+
return;
|
|
171
|
+
}
|
|
172
|
+
const cached = reactComponentCache.get(def);
|
|
173
|
+
if (cached) {
|
|
174
|
+
setLoadedComponent(() => cached);
|
|
175
|
+
return;
|
|
176
|
+
}
|
|
177
|
+
let cancelled = false;
|
|
178
|
+
void loadReactComponent(def).then((C) => {
|
|
179
|
+
if (!cancelled)
|
|
180
|
+
setLoadedComponent(() => C);
|
|
181
|
+
});
|
|
182
|
+
return () => {
|
|
183
|
+
cancelled = true;
|
|
184
|
+
};
|
|
185
|
+
}, [def]);
|
|
186
|
+
// Write-back setter scoped to THIS node. Bidirectional inputs use
|
|
187
|
+
// useWriteBack(propName)(next) to push user input through the resolver.
|
|
188
|
+
// Silently no-ops if the named prop isn't a DataBinding.
|
|
189
|
+
const writeBack = useCallback((propName, next) => {
|
|
190
|
+
const original = node[propName];
|
|
191
|
+
if (original === null ||
|
|
192
|
+
typeof original !== 'object' ||
|
|
193
|
+
!('path' in original)) {
|
|
194
|
+
return;
|
|
195
|
+
}
|
|
196
|
+
try {
|
|
197
|
+
writeDynamic(original, dataContext, scena, next);
|
|
198
|
+
}
|
|
199
|
+
catch (err) {
|
|
200
|
+
console.warn(`[scena.write] prop "${propName}" not writable:`, err);
|
|
201
|
+
}
|
|
202
|
+
}, [node, dataContext, scena]);
|
|
203
|
+
const subsRef = useRef([]);
|
|
204
|
+
useEffect(() => {
|
|
205
|
+
subsRef.current.forEach((d) => d.dispose());
|
|
206
|
+
const paths = new Set();
|
|
207
|
+
collectPaths(node, mountKey, dataContext, paths);
|
|
208
|
+
subsRef.current = [...paths].map((p) => scena.store.subscribe(p, () => force()));
|
|
209
|
+
return () => {
|
|
210
|
+
subsRef.current.forEach((d) => d.dispose());
|
|
211
|
+
subsRef.current = [];
|
|
212
|
+
};
|
|
213
|
+
}, [node, scena, mountKey, dataContext]);
|
|
214
|
+
// Component mount lifecycle — runs once per mounted instance; the returned
|
|
215
|
+
// function (if any) runs on unmount. Lets a component (esp. a template) set
|
|
216
|
+
// up timers / event subscriptions / store seeding. See ComponentMountHandler.
|
|
217
|
+
useEffect(() => {
|
|
218
|
+
if (!def?.onMount)
|
|
219
|
+
return;
|
|
220
|
+
const cleanup = def.onMount({ scena, store: scena.store, mountKey, dataContext });
|
|
221
|
+
return typeof cleanup === 'function' ? cleanup : undefined;
|
|
222
|
+
}, [def, scena, mountKey, dataContext]);
|
|
223
|
+
if (!def) {
|
|
224
|
+
return (_jsxs("span", { className: "oo-missing", title: `No component registered for "${node.component}"`, children: ["[", node.component, "]"] }));
|
|
225
|
+
}
|
|
226
|
+
if (def.renderer.kind === 'template') {
|
|
227
|
+
return _jsx(ViewMount, { node: def.renderer.template });
|
|
228
|
+
}
|
|
229
|
+
const props = resolveProps(node, scena, mountKey, dataContext);
|
|
230
|
+
if (def.renderer.kind === 'html') {
|
|
231
|
+
return _jsx(HtmlMount, { def: def, props: props });
|
|
232
|
+
}
|
|
233
|
+
if (!LoadedComponent) {
|
|
234
|
+
return (_jsxs("span", { className: "oo-loading-dots", "aria-busy": "true", children: [_jsx("span", {}), _jsx("span", {}), _jsx("span", {})] }));
|
|
235
|
+
}
|
|
236
|
+
// `children` prop becomes React children; everything else stays as a prop.
|
|
237
|
+
const { children: childrenProp, ...rest } = props;
|
|
238
|
+
return (_jsx(WriteContext.Provider, { value: writeBack, children: _jsx(LoadedComponent, { ...rest, children: childrenProp }) }));
|
|
239
|
+
}
|
|
240
|
+
function resolveProps(node, scena, mountKey, dataContext) {
|
|
241
|
+
const out = {};
|
|
242
|
+
for (const [k, v] of Object.entries(node)) {
|
|
243
|
+
if (RESERVED_KEYS.has(k))
|
|
244
|
+
continue;
|
|
245
|
+
out[k] = resolveProp(v, scena, mountKey, dataContext);
|
|
246
|
+
}
|
|
247
|
+
return out;
|
|
248
|
+
}
|
|
249
|
+
function HtmlMount({ def, props, }) {
|
|
250
|
+
const hostRef = useRef(null);
|
|
251
|
+
const disposableRef = useRef(null);
|
|
252
|
+
useEffect(() => {
|
|
253
|
+
if (!hostRef.current)
|
|
254
|
+
return;
|
|
255
|
+
if (def.renderer.kind !== 'html')
|
|
256
|
+
return;
|
|
257
|
+
disposableRef.current?.dispose();
|
|
258
|
+
disposableRef.current = def.renderer.mount(hostRef.current, props);
|
|
259
|
+
return () => {
|
|
260
|
+
disposableRef.current?.dispose();
|
|
261
|
+
disposableRef.current = null;
|
|
262
|
+
};
|
|
263
|
+
}, [def, props]);
|
|
264
|
+
return _jsx("div", { ref: hostRef });
|
|
265
|
+
}
|
|
266
|
+
export function MountWrapper({ mountKey, dataContext, children, }) {
|
|
267
|
+
return (_jsx(MountContext.Provider, { value: mountKey, children: _jsx(DataContextContext.Provider, { value: dataContext, children: children }) }));
|
|
268
|
+
}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
export { Scena } from './Scena.js';
|
|
2
|
+
export { ScenaProvider, useScena } from './ScenaProvider.js';
|
|
3
|
+
export { useI18n } from './hooks/useI18n.js';
|
|
4
|
+
export type { UseI18nResult } from './hooks/useI18n.js';
|
|
5
|
+
export { Translate, Translate as T } from './Translate.js';
|
|
6
|
+
export type { TranslateProps } from './Translate.js';
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
// Barrel-free boot entry for the React runtime. Just the provider + hook the
|
|
2
|
+
// app shell needs to mount Scena — importing this does NOT pull the heavy
|
|
3
|
+
// renderers (ViewMount, SurfaceArea, ShellSplitter, DefaultShell) that the full
|
|
4
|
+
// '@softov/scena/react' barrel re-exports. Those load via the barrel only
|
|
5
|
+
// once the shell actually renders (post-login / on first surface).
|
|
6
|
+
export { Scena } from './Scena.js';
|
|
7
|
+
export { ScenaProvider, useScena } from './ScenaProvider.js';
|
|
8
|
+
// i18n hook + <Translate> (alias <T>) — narrow entry (registry-only).
|
|
9
|
+
export { useI18n } from './hooks/useI18n.js';
|
|
10
|
+
export { Translate, Translate as T } from './Translate.js';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function useCommand(id: string): (args?: unknown) => Promise<unknown>;
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { type LocaleInfo, type TranslateOptions } from '../../i18n/registry.js';
|
|
2
|
+
export interface UseI18nResult {
|
|
3
|
+
t: (key: string, fallbackOrOptions?: string | TranslateOptions) => string;
|
|
4
|
+
locale: string;
|
|
5
|
+
info: LocaleInfo | undefined;
|
|
6
|
+
locales: LocaleInfo[];
|
|
7
|
+
setLocale: (locale: string) => void;
|
|
8
|
+
}
|
|
9
|
+
export declare function useI18n(namespace?: string): UseI18nResult;
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { useCallback, useSyncExternalStore } from 'react';
|
|
2
|
+
import { subscribeI18n, getLocale, getLocaleInfo, listLocaleInfo, translate, setLocale, } from '../../i18n/registry.js';
|
|
3
|
+
// Reactive translation for hand-written React. Subscribes to the i18n registry,
|
|
4
|
+
// so the component re-renders on locale switch / message registration. Optional
|
|
5
|
+
// `namespace` is prefixed to every key. For declarative ComponentNodes, bind
|
|
6
|
+
// `{ path: '$/t/<key>' }` instead (served by the i18n ScopeBackend).
|
|
7
|
+
export function useI18n(namespace) {
|
|
8
|
+
const locale = useSyncExternalStore(subscribeI18n, getLocale, getLocale);
|
|
9
|
+
const t = useCallback((key, fallbackOrOptions) => translate(namespace ? `${namespace}/${key}` : key, fallbackOrOptions),
|
|
10
|
+
// `locale` is deliberately a dependency even though `translate` reads it
|
|
11
|
+
// internally: consumers memoize on `t`, so its identity must change on a
|
|
12
|
+
// locale switch or they render stale translations.
|
|
13
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
14
|
+
[namespace, locale]);
|
|
15
|
+
return { t, locale, info: getLocaleInfo(locale), locales: listLocaleInfo(), setLocale };
|
|
16
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { useStore } from './useStore.js';
|
|
2
|
+
import { useI18n } from './useI18n.js';
|
|
3
|
+
import { translate } from '../../i18n/registry.js';
|
|
4
|
+
// Resolve a Label (string | { path } | { t }) reactively: `{ path }` follows the
|
|
5
|
+
// store, `{ t }` follows the locale, a string is returned as-is.
|
|
6
|
+
export function useLabel(label) {
|
|
7
|
+
const path = label && typeof label === 'object' && 'path' in label ? label.path : undefined;
|
|
8
|
+
const bound = useStore(path);
|
|
9
|
+
useI18n(); // subscribe so `{ t }` re-resolves on locale switch
|
|
10
|
+
if (label == null)
|
|
11
|
+
return '';
|
|
12
|
+
if (typeof label === 'string')
|
|
13
|
+
return label;
|
|
14
|
+
if ('t' in label)
|
|
15
|
+
return translate(label.t);
|
|
16
|
+
if ('path' in label)
|
|
17
|
+
return bound == null ? '' : String(bound);
|
|
18
|
+
return '';
|
|
19
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { useSyncExternalStore } from 'react';
|
|
2
|
+
import { useScena } from '../ScenaProvider.js';
|
|
3
|
+
const EMPTY = { surfaces: {} };
|
|
4
|
+
export function useLayout() {
|
|
5
|
+
const scena = useScena();
|
|
6
|
+
return useSyncExternalStore((onChange) => {
|
|
7
|
+
const sub = scena.layout.subscribe(() => onChange());
|
|
8
|
+
return () => sub.dispose();
|
|
9
|
+
}, () => scena.layout.get(), () => EMPTY);
|
|
10
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { useEffect, useState } from 'react';
|
|
2
|
+
import { useScena } from '../ScenaProvider.js';
|
|
3
|
+
export function useMounts(surface) {
|
|
4
|
+
const scena = useScena();
|
|
5
|
+
const [mounts, setMounts] = useState(() => scena.surfaces.listAt(surface));
|
|
6
|
+
useEffect(() => {
|
|
7
|
+
const refresh = () => setMounts(scena.surfaces.listAt(surface));
|
|
8
|
+
refresh();
|
|
9
|
+
const subs = [
|
|
10
|
+
scena.events.on('scena:mount:opened', refresh),
|
|
11
|
+
scena.events.on('scena:mount:closed', refresh),
|
|
12
|
+
scena.events.on('scena:mount:focused', refresh),
|
|
13
|
+
];
|
|
14
|
+
return () => subs.forEach((s) => s.dispose());
|
|
15
|
+
}, [scena, surface]);
|
|
16
|
+
return mounts;
|
|
17
|
+
}
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
import type { BindingPath } from '../../types/component-graph.js';
|
|
2
|
+
export declare function useStore<T = unknown>(path: BindingPath | undefined, dataContextOverride?: BindingPath): T | undefined;
|
|
3
|
+
export declare function useStoreSetter(): (path: BindingPath, value: unknown) => void;
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { useMemo, useSyncExternalStore } from 'react';
|
|
2
|
+
import { useScena } from '../ScenaProvider.js';
|
|
3
|
+
import { useCurrentMountKey, useDataContext } from '../mount-context.js';
|
|
4
|
+
import { rewriteLocal } from '../../core/reactive-store.js';
|
|
5
|
+
import { joinAbsolute, readPath } from '../../core/path-resolver.js';
|
|
6
|
+
function resolveForRead(path, mountKey, dataContext) {
|
|
7
|
+
if (path.startsWith('/') && !path.startsWith('$/')) {
|
|
8
|
+
return joinAbsolute(dataContext, path);
|
|
9
|
+
}
|
|
10
|
+
return rewriteLocal(path, mountKey);
|
|
11
|
+
}
|
|
12
|
+
export function useStore(path,
|
|
13
|
+
// Override the data context for resolving relative (`/…`) paths. Used by
|
|
14
|
+
// layouts that render a mount's title outside its ViewMount provider (the tab
|
|
15
|
+
// strip), passing the mount's own dataContext so `/name` resolves correctly.
|
|
16
|
+
dataContextOverride) {
|
|
17
|
+
const scena = useScena();
|
|
18
|
+
const mountKey = useCurrentMountKey();
|
|
19
|
+
const providerContext = useDataContext();
|
|
20
|
+
const dataContext = dataContextOverride ?? providerContext;
|
|
21
|
+
// Resolve to `null` when the caller passes no path. Hooks below must still
|
|
22
|
+
// run (rules of hooks) — they just become no-ops via the null guard so
|
|
23
|
+
// consumers can do `useStore(cond ? path : undefined)` safely.
|
|
24
|
+
const resolved = useMemo(() => (path === undefined ? null : resolveForRead(path, mountKey, dataContext)), [path, mountKey, dataContext]);
|
|
25
|
+
return useSyncExternalStore((onChange) => {
|
|
26
|
+
if (resolved === null)
|
|
27
|
+
return () => undefined;
|
|
28
|
+
const sub = scena.store.subscribe(resolved, () => onChange());
|
|
29
|
+
return () => sub.dispose();
|
|
30
|
+
}, () => (resolved === null ? undefined : readPath(scena.store, undefined, resolved)), () => undefined);
|
|
31
|
+
}
|
|
32
|
+
export function useStoreSetter() {
|
|
33
|
+
const scena = useScena();
|
|
34
|
+
const mountKey = useCurrentMountKey();
|
|
35
|
+
const dataContext = useDataContext();
|
|
36
|
+
return (path, value) => {
|
|
37
|
+
const resolved = resolveForRead(path, mountKey, dataContext);
|
|
38
|
+
scena.store.set(resolved, value);
|
|
39
|
+
};
|
|
40
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { translate } from '../../i18n/registry.js';
|
|
2
|
+
import { useStore } from './useStore.js';
|
|
3
|
+
const EMPTY_LABEL_PATH = '$/__label__/empty';
|
|
4
|
+
export function useStoreLabel(value, fallback = '', dataContext) {
|
|
5
|
+
const path = value && typeof value === 'object' && 'path' in value
|
|
6
|
+
? value.path
|
|
7
|
+
: EMPTY_LABEL_PATH;
|
|
8
|
+
// Always call the hook (rules of hooks). For non-path labels it reads a dummy
|
|
9
|
+
// path and the result is ignored below. dataContext resolves relative (`/…`)
|
|
10
|
+
// title paths against the mount's record root.
|
|
11
|
+
const stored = useStore(path, dataContext);
|
|
12
|
+
if (typeof value === 'string') {
|
|
13
|
+
return value;
|
|
14
|
+
}
|
|
15
|
+
if (!value) {
|
|
16
|
+
return fallback;
|
|
17
|
+
}
|
|
18
|
+
if ('path' in value) {
|
|
19
|
+
return stored ?? fallback;
|
|
20
|
+
}
|
|
21
|
+
if ('t' in value) {
|
|
22
|
+
return translate(value.t, fallback);
|
|
23
|
+
}
|
|
24
|
+
return fallback;
|
|
25
|
+
}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import type { SurfaceName } from '../../types/mount-surface.js';
|
|
2
|
+
import type { SurfacePresentation } from '../../types/layout.js';
|
|
3
|
+
import { type PresentationPolicy } from '../../core/surface-presentation.js';
|
|
4
|
+
export declare function useSurfacePresentation(surface: SurfaceName, policy?: PresentationPolicy): SurfacePresentation;
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { resolveSurfacePresentation, } from '../../core/surface-presentation.js';
|
|
2
|
+
import { useStore } from './useStore.js';
|
|
3
|
+
// Reads `$/modus/class` and maps it to how this surface should occupy space.
|
|
4
|
+
//
|
|
5
|
+
// `policy` is the app's, not scena's — see surface-presentation.ts. Omitted, or
|
|
6
|
+
// with the modus backend unregistered, every surface stays `docked`, which is
|
|
7
|
+
// exactly the behavior before presentation existed.
|
|
8
|
+
//
|
|
9
|
+
// The backend is registered by the app:
|
|
10
|
+
// { scope: 'modus', create: () => createModusBackend() }
|
|
11
|
+
export function useSurfacePresentation(surface, policy) {
|
|
12
|
+
const modus = useStore('$/modus/class');
|
|
13
|
+
if (!modus)
|
|
14
|
+
return 'docked';
|
|
15
|
+
return resolveSurfacePresentation(surface, modus, policy);
|
|
16
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
export { Scena } from './Scena.js';
|
|
2
|
+
export { ScenaProvider, useScena } from './ScenaProvider.js';
|
|
3
|
+
export { DefaultShell } from './DefaultShell.js';
|
|
4
|
+
export { ViewMount, MountWrapper } from './ViewMount.js';
|
|
5
|
+
export { ShellSplitter } from './ShellSplitter.js';
|
|
6
|
+
export { SurfaceArea } from './SurfaceArea.js';
|
|
7
|
+
export type { SurfaceAreaProps } from './SurfaceArea.js';
|
|
8
|
+
export { useSurfaceResize } from './useSurfaceResize.js';
|
|
9
|
+
export type { SurfaceResizeSpec, SurfaceResizeBinding } from './useSurfaceResize.js';
|
|
10
|
+
export { MountContext, DataContextContext, WriteContext, useCurrentMountKey, useDataContext, useWriteBack, } from './mount-context.js';
|
|
11
|
+
export { useStore, useStoreSetter } from './hooks/useStore.js';
|
|
12
|
+
export { useI18n } from './hooks/useI18n.js';
|
|
13
|
+
export type { UseI18nResult } from './hooks/useI18n.js';
|
|
14
|
+
export { useLabel } from './hooks/useLabel.js';
|
|
15
|
+
export { Translate, Translate as T } from './Translate.js';
|
|
16
|
+
export type { TranslateProps } from './Translate.js';
|
|
17
|
+
export { useCommand } from './hooks/useCommand.js';
|
|
18
|
+
export { useLayout } from './hooks/useLayout.js';
|
|
19
|
+
export { useMounts } from './hooks/useMounts.js';
|
|
20
|
+
export { useSurfacePresentation } from './hooks/useSurfacePresentation.js';
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
export { Scena } from './Scena.js';
|
|
2
|
+
export { ScenaProvider, useScena } from './ScenaProvider.js';
|
|
3
|
+
export { DefaultShell } from './DefaultShell.js';
|
|
4
|
+
export { ViewMount, MountWrapper } from './ViewMount.js';
|
|
5
|
+
export { ShellSplitter } from './ShellSplitter.js';
|
|
6
|
+
export { SurfaceArea } from './SurfaceArea.js';
|
|
7
|
+
// The two resize models. `ShellSplitter` is an element the shell places between
|
|
8
|
+
// surfaces; `useSurfaceResize` (reached through SurfaceArea's `resize` prop, or
|
|
9
|
+
// directly for a custom surface component) puts the grip on the surface's own
|
|
10
|
+
// edge. A shell picks one per surface.
|
|
11
|
+
export { useSurfaceResize } from './useSurfaceResize.js';
|
|
12
|
+
export { MountContext, DataContextContext, WriteContext, useCurrentMountKey, useDataContext, useWriteBack, } from './mount-context.js';
|
|
13
|
+
export { useStore, useStoreSetter } from './hooks/useStore.js';
|
|
14
|
+
export { useI18n } from './hooks/useI18n.js';
|
|
15
|
+
export { useLabel } from './hooks/useLabel.js';
|
|
16
|
+
export { Translate, Translate as T } from './Translate.js';
|
|
17
|
+
export { useCommand } from './hooks/useCommand.js';
|
|
18
|
+
export { useLayout } from './hooks/useLayout.js';
|
|
19
|
+
export { useMounts } from './hooks/useMounts.js';
|
|
20
|
+
export { useSurfacePresentation } from './hooks/useSurfacePresentation.js';
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { BindingPath } from '../types/component-graph.js';
|
|
2
|
+
export declare const MountContext: import("react").Context<string | null>;
|
|
3
|
+
export declare function useCurrentMountKey(): string | null;
|
|
4
|
+
export declare const DataContextContext: import("react").Context<BindingPath | undefined>;
|
|
5
|
+
export declare function useDataContext(): BindingPath | undefined;
|
|
6
|
+
export type WriteBack = (propName: string, next: unknown) => void;
|
|
7
|
+
export declare const WriteContext: import("react").Context<WriteBack | null>;
|
|
8
|
+
export declare function useWriteBack(propName: string): (next: unknown) => void;
|