@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,159 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { Fragment, useRef, useState, } from 'react';
|
|
3
|
+
import { useScena } from '../../react/ScenaProvider.js';
|
|
4
|
+
import { ContextMenu } from '../menu/ContextMenu.js';
|
|
5
|
+
import { MountTitle } from './MountTitle.js';
|
|
6
|
+
import { Divisor } from '../display/Divisor.js';
|
|
7
|
+
import { NAMED_GLYPH } from '../display/Icon.js';
|
|
8
|
+
// Side-by-side panes with a draggable divider between each adjacent pair AND
|
|
9
|
+
// a thin header per pane that acts as the drag handle for reorder (HTML5 DnD).
|
|
10
|
+
// Ratios sum to 1 and are stored in `state.split.ratios`. Dragging the divider
|
|
11
|
+
// at index i only adjusts ratios[i] and ratios[i+1] — the rest are preserved.
|
|
12
|
+
const MIN_PANE_RATIO = 0.05;
|
|
13
|
+
const DRAG_MIME = 'application/x-scena-split-index';
|
|
14
|
+
// ----- Layout -----
|
|
15
|
+
export function SplitLayout({ surface, mounts, state, setState, renderMount, onClose, onReorder, }) {
|
|
16
|
+
const scena = useScena();
|
|
17
|
+
const containerRef = useRef(null);
|
|
18
|
+
// Merge persisted order with new mounts so a freshly opened pane shows up
|
|
19
|
+
// even if state.split.order was captured before it existed.
|
|
20
|
+
const persistedOrder = state.split?.order ?? [];
|
|
21
|
+
const orderSet = new Set(persistedOrder);
|
|
22
|
+
const orderedKnown = persistedOrder
|
|
23
|
+
.map((k) => mounts.find((m) => m.key === k))
|
|
24
|
+
.filter((m) => Boolean(m));
|
|
25
|
+
const newMounts = mounts.filter((m) => !orderSet.has(m.key));
|
|
26
|
+
const orderedMounts = [...orderedKnown, ...newMounts];
|
|
27
|
+
const fallbackEqual = orderedMounts.length > 0 ? 1 / orderedMounts.length : 1;
|
|
28
|
+
const ratios = (() => {
|
|
29
|
+
const stored = state.split?.ratios;
|
|
30
|
+
if (stored && stored.length === orderedMounts.length)
|
|
31
|
+
return stored;
|
|
32
|
+
return orderedMounts.map(() => fallbackEqual);
|
|
33
|
+
})();
|
|
34
|
+
function onDividerCommit(cumulativeRatio, id) {
|
|
35
|
+
const index = id;
|
|
36
|
+
if (orderedMounts.length < 2)
|
|
37
|
+
return;
|
|
38
|
+
const before = ratios.slice(0, index).reduce((a, b) => a + b, 0);
|
|
39
|
+
const pair = (ratios[index] ?? 0) + (ratios[index + 1] ?? 0);
|
|
40
|
+
if (pair <= 0)
|
|
41
|
+
return;
|
|
42
|
+
let newPaneI = clamp(cumulativeRatio - before, MIN_PANE_RATIO, pair - MIN_PANE_RATIO);
|
|
43
|
+
let newPaneNext = pair - newPaneI;
|
|
44
|
+
if (newPaneNext < MIN_PANE_RATIO) {
|
|
45
|
+
newPaneNext = MIN_PANE_RATIO;
|
|
46
|
+
newPaneI = pair - newPaneNext;
|
|
47
|
+
}
|
|
48
|
+
const next = [...ratios];
|
|
49
|
+
next[index] = newPaneI;
|
|
50
|
+
next[index + 1] = newPaneNext;
|
|
51
|
+
setState({
|
|
52
|
+
split: {
|
|
53
|
+
order: state.split?.order,
|
|
54
|
+
ratios: next,
|
|
55
|
+
collapsed: state.split?.collapsed,
|
|
56
|
+
},
|
|
57
|
+
});
|
|
58
|
+
}
|
|
59
|
+
// ----- Drag-reorder via pane headers -----
|
|
60
|
+
const [dragOverIdx, setDragOverIdx] = useState(null);
|
|
61
|
+
// ----- Context menu state -----
|
|
62
|
+
// Per-pane right-click → `tab:context`; gutter / container right-click →
|
|
63
|
+
// `surface:context`. SplitLayout has no real "group" concept (each column
|
|
64
|
+
// is one mount) so we don't expose a per-pane [...] button — surface-level
|
|
65
|
+
// operations (close all, switch layout) live on the background menu.
|
|
66
|
+
const [paneMenu, setPaneMenu] = useState(null);
|
|
67
|
+
const [bgMenu, setBgMenu] = useState(null);
|
|
68
|
+
function onPaneContextMenu(e, key, idx) {
|
|
69
|
+
e.preventDefault();
|
|
70
|
+
e.stopPropagation();
|
|
71
|
+
setPaneMenu({ x: e.clientX, y: e.clientY, key, idx });
|
|
72
|
+
}
|
|
73
|
+
function onBgContextMenu(e) {
|
|
74
|
+
if (e.target !== e.currentTarget)
|
|
75
|
+
return;
|
|
76
|
+
e.preventDefault();
|
|
77
|
+
setBgMenu({ x: e.clientX, y: e.clientY });
|
|
78
|
+
}
|
|
79
|
+
const baseContext = {
|
|
80
|
+
'$/surface/name': surface,
|
|
81
|
+
'$/surface/layoutId': 'split',
|
|
82
|
+
'$/surface/mountCount': mounts.length,
|
|
83
|
+
'$/surface/closedHistory': 0,
|
|
84
|
+
'$/tab/canSplit': false,
|
|
85
|
+
'$/tab/canMove': false,
|
|
86
|
+
'$/group/canClose': false,
|
|
87
|
+
'$/group/canMaximize': false,
|
|
88
|
+
};
|
|
89
|
+
function onHeaderDragStart(e, idx) {
|
|
90
|
+
e.dataTransfer.setData(DRAG_MIME, String(idx));
|
|
91
|
+
e.dataTransfer.effectAllowed = 'move';
|
|
92
|
+
}
|
|
93
|
+
function onHeaderDragOver(e, idx) {
|
|
94
|
+
if (!e.dataTransfer.types.includes(DRAG_MIME))
|
|
95
|
+
return;
|
|
96
|
+
e.preventDefault();
|
|
97
|
+
e.dataTransfer.dropEffect = 'move';
|
|
98
|
+
setDragOverIdx(idx);
|
|
99
|
+
}
|
|
100
|
+
function onHeaderDragLeave() {
|
|
101
|
+
setDragOverIdx(null);
|
|
102
|
+
}
|
|
103
|
+
function onHeaderDrop(e, toIdx) {
|
|
104
|
+
if (!e.dataTransfer.types.includes(DRAG_MIME))
|
|
105
|
+
return;
|
|
106
|
+
e.preventDefault();
|
|
107
|
+
const fromIdx = Number(e.dataTransfer.getData(DRAG_MIME));
|
|
108
|
+
setDragOverIdx(null);
|
|
109
|
+
if (Number.isFinite(fromIdx) && fromIdx !== toIdx) {
|
|
110
|
+
onReorder(fromIdx, toIdx);
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
if (orderedMounts.length === 0) {
|
|
114
|
+
return (_jsx("div", { style: { padding: 24, color: 'var(--oo-color-muted)' }, children: "Nothing open." }));
|
|
115
|
+
}
|
|
116
|
+
const containerStyle = {
|
|
117
|
+
display: 'flex',
|
|
118
|
+
flexDirection: 'row',
|
|
119
|
+
height: '100%',
|
|
120
|
+
minHeight: 0,
|
|
121
|
+
};
|
|
122
|
+
return (_jsxs("div", { ref: containerRef, className: "oo-layout oo-layout--split", style: containerStyle, onContextMenu: onBgContextMenu, children: [orderedMounts.map((mount, i) => {
|
|
123
|
+
// Per-field merge: mount.props ?? component.props ?? key.
|
|
124
|
+
const compProps = scena.components.get(mount.component.component)?.props;
|
|
125
|
+
const color = mount.props?.color ?? compProps?.color;
|
|
126
|
+
return (_jsxs(Fragment, { children: [_jsxs("div", { "data-pane-index": i, "data-drag-over": dragOverIdx === i, "data-color": color, className: "oo-split-pane", style: {
|
|
127
|
+
flex: ratios[i] ?? fallbackEqual,
|
|
128
|
+
minWidth: 0,
|
|
129
|
+
overflow: 'hidden',
|
|
130
|
+
display: 'flex',
|
|
131
|
+
flexDirection: 'column',
|
|
132
|
+
}, children: [_jsxs("div", { className: "oo-split-pane-header", draggable: true, onDragStart: (e) => onHeaderDragStart(e, i), onDragOver: (e) => onHeaderDragOver(e, i), onDragLeave: onHeaderDragLeave, onDrop: (e) => onHeaderDrop(e, i), onContextMenu: (e) => onPaneContextMenu(e, mount.key, i), style: {
|
|
133
|
+
flex: '0 0 auto',
|
|
134
|
+
display: 'flex',
|
|
135
|
+
alignItems: 'center',
|
|
136
|
+
justifyContent: 'space-between',
|
|
137
|
+
padding: 'var(--oo-spacing-xs) var(--oo-spacing-sm)',
|
|
138
|
+
background: 'var(--oo-color-surface)',
|
|
139
|
+
borderBottom: '1px solid var(--oo-color-border)',
|
|
140
|
+
fontSize: 'var(--oo-font-size-xs)',
|
|
141
|
+
color: 'var(--oo-color-muted)',
|
|
142
|
+
cursor: 'grab',
|
|
143
|
+
userSelect: 'none',
|
|
144
|
+
}, children: [_jsx(MountTitle, { mount: mount, fallback: mount.key, iconClassName: "oo-split-pane-header__icon", titleClassName: "oo-split-pane-header__title" }), _jsx("span", { onClick: (e) => {
|
|
145
|
+
e.stopPropagation();
|
|
146
|
+
onClose(mount.key);
|
|
147
|
+
}, title: "Close", style: { cursor: 'pointer' }, children: NAMED_GLYPH.closePanel })] }), _jsx("div", { style: { flex: 1, overflow: 'auto', minHeight: 0 }, children: renderMount(mount) })] }), i < orderedMounts.length - 1 ? (_jsx(Divisor, { id: i, direction: "row", containerRef: containerRef, onCommit: onDividerCommit })) : null] }, mount.key));
|
|
148
|
+
}), paneMenu ? (_jsx(ContextMenu, { x: paneMenu.x, y: paneMenu.y, onClose: () => setPaneMenu(null), spec: { query: { slot: 'tab:context' }, footerHints: true }, context: {
|
|
149
|
+
...baseContext,
|
|
150
|
+
'$/tab/key': paneMenu.key,
|
|
151
|
+
'$/tab/index': paneMenu.idx,
|
|
152
|
+
'$/tab/isActive': true,
|
|
153
|
+
'$/tab/isPinned': false,
|
|
154
|
+
'$/group/tabCount': mounts.length,
|
|
155
|
+
} })) : null, bgMenu ? (_jsx(ContextMenu, { x: bgMenu.x, y: bgMenu.y, onClose: () => setBgMenu(null), spec: { query: { slot: 'surface:context' }, footerHints: true }, context: baseContext })) : null] }));
|
|
156
|
+
}
|
|
157
|
+
function clamp(v, min, max) {
|
|
158
|
+
return Math.max(min, Math.min(max, v));
|
|
159
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { type ReactNode } from 'react';
|
|
2
|
+
export interface SplitterProps {
|
|
3
|
+
orientation?: 'horizontal' | 'vertical';
|
|
4
|
+
ratio?: number;
|
|
5
|
+
min?: number;
|
|
6
|
+
max?: number;
|
|
7
|
+
handleSize?: number;
|
|
8
|
+
onRatioChange?: (ratio: number) => void;
|
|
9
|
+
first?: ReactNode;
|
|
10
|
+
second?: ReactNode;
|
|
11
|
+
}
|
|
12
|
+
export declare function Splitter({ orientation, ratio: ratioProp, min, max, handleSize, onRatioChange, first, second, }: SplitterProps): import("react").JSX.Element;
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { useEffect, useRef, useState, } from 'react';
|
|
3
|
+
// Graph-renderable two-pane splitter. Used as a content primitive inside Pages
|
|
4
|
+
// (Tela) or any other graph. Distinct from chrome ShellSplitter, which writes
|
|
5
|
+
// to layout: state and lives between surfaces — this one is internal to a graph.
|
|
6
|
+
export function Splitter({ orientation = 'horizontal', ratio: ratioProp = 0.5, min = 0.1, max = 0.9, handleSize = 4, onRatioChange, first, second, }) {
|
|
7
|
+
const [ratio, setRatio] = useState(clamp(ratioProp, min, max));
|
|
8
|
+
const containerRef = useRef(null);
|
|
9
|
+
const draggingRef = useRef(false);
|
|
10
|
+
const rafRef = useRef(null);
|
|
11
|
+
const pendingRef = useRef(null);
|
|
12
|
+
// Sync from external prop when it changes (e.g., $bind path updates).
|
|
13
|
+
useEffect(() => {
|
|
14
|
+
setRatio(clamp(ratioProp, min, max));
|
|
15
|
+
}, [ratioProp, min, max]);
|
|
16
|
+
function commitPending() {
|
|
17
|
+
if (pendingRef.current !== null) {
|
|
18
|
+
const v = pendingRef.current;
|
|
19
|
+
setRatio(v);
|
|
20
|
+
onRatioChange?.(v);
|
|
21
|
+
pendingRef.current = null;
|
|
22
|
+
}
|
|
23
|
+
rafRef.current = null;
|
|
24
|
+
}
|
|
25
|
+
function onPointerDown(e) {
|
|
26
|
+
e.preventDefault();
|
|
27
|
+
e.currentTarget.setPointerCapture(e.pointerId);
|
|
28
|
+
draggingRef.current = true;
|
|
29
|
+
}
|
|
30
|
+
function onPointerMove(e) {
|
|
31
|
+
if (!draggingRef.current || !containerRef.current)
|
|
32
|
+
return;
|
|
33
|
+
const rect = containerRef.current.getBoundingClientRect();
|
|
34
|
+
const ratio = orientation === 'horizontal'
|
|
35
|
+
? (e.clientX - rect.left) / rect.width
|
|
36
|
+
: (e.clientY - rect.top) / rect.height;
|
|
37
|
+
pendingRef.current = clamp(ratio, min, max);
|
|
38
|
+
if (rafRef.current === null) {
|
|
39
|
+
rafRef.current = requestAnimationFrame(commitPending);
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
function onPointerUp(e) {
|
|
43
|
+
if (rafRef.current !== null) {
|
|
44
|
+
cancelAnimationFrame(rafRef.current);
|
|
45
|
+
commitPending();
|
|
46
|
+
}
|
|
47
|
+
e.currentTarget.releasePointerCapture(e.pointerId);
|
|
48
|
+
draggingRef.current = false;
|
|
49
|
+
}
|
|
50
|
+
const containerStyle = {
|
|
51
|
+
display: 'flex',
|
|
52
|
+
flexDirection: orientation === 'horizontal' ? 'row' : 'column',
|
|
53
|
+
width: '100%',
|
|
54
|
+
height: '100%',
|
|
55
|
+
overflow: 'hidden',
|
|
56
|
+
};
|
|
57
|
+
const handleStyle = orientation === 'horizontal'
|
|
58
|
+
? { width: handleSize, cursor: 'ew-resize', background: 'var(--oo-color-border, rgba(0,0,0,0.1))' }
|
|
59
|
+
: { height: handleSize, cursor: 'ns-resize', background: 'var(--oo-color-border, rgba(0,0,0,0.1))' };
|
|
60
|
+
return (_jsxs("div", { ref: containerRef, className: "oo-splitter", style: containerStyle, children: [_jsx("div", { style: { flex: ratio, overflow: 'auto', minWidth: 0, minHeight: 0 }, children: first }), _jsx("div", { className: "oo-splitter-handle", onPointerDown: onPointerDown, onPointerMove: onPointerMove, onPointerUp: onPointerUp, style: { flex: '0 0 auto', userSelect: 'none', touchAction: 'none', ...handleStyle } }), _jsx("div", { style: { flex: 1 - ratio, overflow: 'auto', minWidth: 0, minHeight: 0 }, children: second })] }));
|
|
61
|
+
}
|
|
62
|
+
function clamp(value, min, max) {
|
|
63
|
+
return Math.max(min, Math.min(max, value));
|
|
64
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { type ReactNode } from 'react';
|
|
2
|
+
import type { LayoutProps } from '../../types/layout.js';
|
|
3
|
+
interface LayoutHeaderProps extends Pick<LayoutProps, 'mounts' | 'state' | 'setState'> {
|
|
4
|
+
title: string;
|
|
5
|
+
icon?: ReactNode;
|
|
6
|
+
color?: string;
|
|
7
|
+
}
|
|
8
|
+
export declare function StackHeader({ mounts, state, setState, title, icon, color, }: LayoutHeaderProps): import("react").JSX.Element;
|
|
9
|
+
export {};
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
2
|
+
import { useState, } from 'react';
|
|
3
|
+
import { useScena } from '../../react/ScenaProvider.js';
|
|
4
|
+
import { ContextMenu } from '../menu/ContextMenu.js';
|
|
5
|
+
import { resolveMountTitle } from './MountTitle.js';
|
|
6
|
+
import { NAMED_GLYPH } from '../display/Icon.js';
|
|
7
|
+
export function StackHeader({
|
|
8
|
+
// surface,
|
|
9
|
+
mounts, state, setState, title, icon, color,
|
|
10
|
+
// renderMount,
|
|
11
|
+
// onClose,
|
|
12
|
+
// onReorder,
|
|
13
|
+
}) {
|
|
14
|
+
const scena = useScena();
|
|
15
|
+
// Merge persisted order with new mounts so a freshly opened section shows up
|
|
16
|
+
// even if state.split.order was captured before it existed.
|
|
17
|
+
const persistedOrder = state.split?.order ?? [];
|
|
18
|
+
const orderSet = new Set(persistedOrder);
|
|
19
|
+
const orderedKnown = persistedOrder
|
|
20
|
+
.map((k) => mounts.find((m) => m.key === k))
|
|
21
|
+
.filter((m) => Boolean(m));
|
|
22
|
+
const newMounts = mounts.filter((m) => !orderSet.has(m.key));
|
|
23
|
+
// `allOrdered` is every mount in display order. `orderedMounts` is what
|
|
24
|
+
// we actually render after applying the user's hide toggles (state.stack.hidden).
|
|
25
|
+
// The `[...]` menu in the container strip operates on `allOrdered` so a
|
|
26
|
+
// hidden mount remains togglable.
|
|
27
|
+
const allOrdered = [...orderedKnown, ...newMounts];
|
|
28
|
+
const hidden = new Set(state.stack?.hidden ?? []);
|
|
29
|
+
// Container [...] menu position. When non-null the overflow menu is open.
|
|
30
|
+
const [overflowMenu, setOverflowMenu] = useState(null);
|
|
31
|
+
function setHidden(next) {
|
|
32
|
+
setState({ stack: { ...state.stack, hidden: [...next] } });
|
|
33
|
+
}
|
|
34
|
+
function toggleHidden(key) {
|
|
35
|
+
const next = new Set(hidden);
|
|
36
|
+
if (next.has(key))
|
|
37
|
+
next.delete(key);
|
|
38
|
+
else
|
|
39
|
+
next.add(key);
|
|
40
|
+
setHidden(next);
|
|
41
|
+
}
|
|
42
|
+
function openOverflowMenu(e) {
|
|
43
|
+
e.stopPropagation();
|
|
44
|
+
const rect = e.currentTarget.getBoundingClientRect();
|
|
45
|
+
setOverflowMenu({ x: rect.right, y: rect.bottom + 2 });
|
|
46
|
+
}
|
|
47
|
+
return (_jsxs(_Fragment, { children: [_jsxs("div", { className: "oo-stack-container-header", "data-color": color, style: {
|
|
48
|
+
flex: '0 0 auto',
|
|
49
|
+
display: 'flex',
|
|
50
|
+
alignItems: 'center',
|
|
51
|
+
justifyContent: 'space-between',
|
|
52
|
+
padding: 'var(--oo-spacing-xs) var(--oo-spacing-sm)',
|
|
53
|
+
background: 'var(--oo-color-surface)',
|
|
54
|
+
borderBottom: '1px solid var(--oo-color-border)',
|
|
55
|
+
fontSize: 'var(--oo-font-size-xs)',
|
|
56
|
+
textTransform: 'uppercase',
|
|
57
|
+
letterSpacing: '0.06em',
|
|
58
|
+
color: 'var(--oo-color-muted)',
|
|
59
|
+
userSelect: 'none',
|
|
60
|
+
minWidth: 0,
|
|
61
|
+
minHeight: 32,
|
|
62
|
+
}, children: [_jsxs("span", { style: { display: 'inline-flex', alignItems: 'center', gap: 6 }, children: [icon ? (_jsx("span", { className: "oo-stack-container-header__icon", "aria-hidden": true, children: icon })) : null, _jsx("span", { className: "oo-stack-container-header__title", children: title })] }), _jsx("button", { type: "button", className: "oo-stack-container-header__overflow", title: "Toggle panes", "aria-label": "Toggle panes", onClick: openOverflowMenu, style: {
|
|
63
|
+
background: 'transparent',
|
|
64
|
+
border: 'none',
|
|
65
|
+
color: 'var(--oo-color-muted)',
|
|
66
|
+
cursor: 'pointer',
|
|
67
|
+
font: 'inherit',
|
|
68
|
+
padding: '0 4px',
|
|
69
|
+
}, children: NAMED_GLYPH.moreHoriz })] }), overflowMenu ? (_jsx(ContextMenu, { x: overflowMenu.x, y: overflowMenu.y, onClose: () => setOverflowMenu(null), spec: {
|
|
70
|
+
footerHints: true,
|
|
71
|
+
items: allOrdered.map((m) => {
|
|
72
|
+
// Per-field merge with the component's registered default.
|
|
73
|
+
const cp = scena.components.get(m.component.component)?.props;
|
|
74
|
+
const visible = !hidden.has(m.key);
|
|
75
|
+
return {
|
|
76
|
+
title: resolveMountTitle(scena, m),
|
|
77
|
+
icon: m.props?.icon ?? cp?.icon,
|
|
78
|
+
color: m.props?.color ?? cp?.color,
|
|
79
|
+
active: visible,
|
|
80
|
+
onSelect: (h) => {
|
|
81
|
+
toggleHidden(m.key);
|
|
82
|
+
h.closeMenu();
|
|
83
|
+
},
|
|
84
|
+
};
|
|
85
|
+
}),
|
|
86
|
+
} })) : null] }));
|
|
87
|
+
}
|
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { useState, } from 'react';
|
|
3
|
+
import { useScena } from '../../react/ScenaProvider.js';
|
|
4
|
+
import { ContextMenu } from '../menu/ContextMenu.js';
|
|
5
|
+
import { StackHeader } from './StackHeader.js';
|
|
6
|
+
import { MountTitle } from './MountTitle.js';
|
|
7
|
+
import { NAMED_GLYPH } from '../display/Icon.js';
|
|
8
|
+
// Vertical stack of mounts, each with a header that toggles collapsed.
|
|
9
|
+
// Headers are draggable for reorder (HTML5 DnD). Used primarily for
|
|
10
|
+
// sidebar:right multi-section panels.
|
|
11
|
+
const DRAG_MIME = 'application/x-scena-stack-index';
|
|
12
|
+
export function StackLayout({ surface, mounts, state, setState, renderMount, onClose, onReorder, }) {
|
|
13
|
+
const scena = useScena();
|
|
14
|
+
// Merge persisted order with new mounts so a freshly opened section shows up
|
|
15
|
+
// even if state.split.order was captured before it existed.
|
|
16
|
+
const persistedOrder = state.split?.order ?? [];
|
|
17
|
+
const orderSet = new Set(persistedOrder);
|
|
18
|
+
const orderedKnown = persistedOrder
|
|
19
|
+
.map((k) => mounts.find((m) => m.key === k))
|
|
20
|
+
.filter((m) => Boolean(m));
|
|
21
|
+
const newMounts = mounts.filter((m) => !orderSet.has(m.key));
|
|
22
|
+
// `allOrdered` is every mount in display order. `orderedMounts` is what
|
|
23
|
+
// we actually render after applying the user's hide toggles (state.stack.hidden).
|
|
24
|
+
// The `[...]` menu in the container strip operates on `allOrdered` so a
|
|
25
|
+
// hidden mount remains togglable.
|
|
26
|
+
const allOrdered = [...orderedKnown, ...newMounts];
|
|
27
|
+
const hidden = new Set(state.stack?.hidden ?? []);
|
|
28
|
+
const orderedMounts = allOrdered.filter((m) => !hidden.has(m.key));
|
|
29
|
+
const container = state.stack?.container;
|
|
30
|
+
const collapsed = new Set(state.split?.collapsed ?? []);
|
|
31
|
+
const [dragOverIdx, setDragOverIdx] = useState(null);
|
|
32
|
+
function toggleCollapsed(key) {
|
|
33
|
+
const next = new Set(collapsed);
|
|
34
|
+
if (next.has(key))
|
|
35
|
+
next.delete(key);
|
|
36
|
+
else
|
|
37
|
+
next.add(key);
|
|
38
|
+
setState({
|
|
39
|
+
split: {
|
|
40
|
+
order: state.split?.order,
|
|
41
|
+
ratios: state.split?.ratios,
|
|
42
|
+
collapsed: [...next],
|
|
43
|
+
},
|
|
44
|
+
});
|
|
45
|
+
}
|
|
46
|
+
function onHeaderDragStart(e, idx) {
|
|
47
|
+
e.dataTransfer.setData(DRAG_MIME, String(idx));
|
|
48
|
+
e.dataTransfer.effectAllowed = 'move';
|
|
49
|
+
}
|
|
50
|
+
function onHeaderDragOver(e, idx) {
|
|
51
|
+
if (!e.dataTransfer.types.includes(DRAG_MIME))
|
|
52
|
+
return;
|
|
53
|
+
e.preventDefault();
|
|
54
|
+
e.dataTransfer.dropEffect = 'move';
|
|
55
|
+
setDragOverIdx(idx);
|
|
56
|
+
}
|
|
57
|
+
function onHeaderDragLeave() {
|
|
58
|
+
setDragOverIdx(null);
|
|
59
|
+
}
|
|
60
|
+
function onHeaderDrop(e, toIdx) {
|
|
61
|
+
if (!e.dataTransfer.types.includes(DRAG_MIME))
|
|
62
|
+
return;
|
|
63
|
+
e.preventDefault();
|
|
64
|
+
const fromIdx = Number(e.dataTransfer.getData(DRAG_MIME));
|
|
65
|
+
setDragOverIdx(null);
|
|
66
|
+
if (Number.isFinite(fromIdx) && fromIdx !== toIdx) {
|
|
67
|
+
onReorder(fromIdx, toIdx);
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
// ----- Context menu state -----
|
|
71
|
+
// Per-section right-click → `tab:context`; container background right-click
|
|
72
|
+
// → `surface:context`. Each section is a single mount so the per-section
|
|
73
|
+
// [...] button is omitted (would duplicate the right-click items).
|
|
74
|
+
const [sectionMenu, setSectionMenu] = useState(null);
|
|
75
|
+
const [bgMenu, setBgMenu] = useState(null);
|
|
76
|
+
function onSectionContextMenu(e, key, idx) {
|
|
77
|
+
e.preventDefault();
|
|
78
|
+
e.stopPropagation();
|
|
79
|
+
setSectionMenu({ x: e.clientX, y: e.clientY, key, idx });
|
|
80
|
+
}
|
|
81
|
+
function onBgContextMenu(e) {
|
|
82
|
+
if (e.target !== e.currentTarget)
|
|
83
|
+
return;
|
|
84
|
+
e.preventDefault();
|
|
85
|
+
setBgMenu({ x: e.clientX, y: e.clientY });
|
|
86
|
+
}
|
|
87
|
+
const baseContext = {
|
|
88
|
+
'$/surface/name': surface,
|
|
89
|
+
'$/surface/layoutId': 'stack',
|
|
90
|
+
'$/surface/mountCount': mounts.length,
|
|
91
|
+
'$/surface/closedHistory': 0,
|
|
92
|
+
'$/tab/canSplit': false,
|
|
93
|
+
'$/tab/canMove': mounts.length > 1,
|
|
94
|
+
'$/group/canClose': false,
|
|
95
|
+
'$/group/canMaximize': false,
|
|
96
|
+
};
|
|
97
|
+
const containerStyle = {
|
|
98
|
+
display: 'flex',
|
|
99
|
+
flexDirection: 'column',
|
|
100
|
+
height: '100%',
|
|
101
|
+
minHeight: 0,
|
|
102
|
+
};
|
|
103
|
+
return (_jsxs("div", { className: "oo-layout oo-layout--stack", style: containerStyle, onContextMenu: onBgContextMenu, children: [_jsx(StackHeader, { title: container?.title ?? 'Details', icon: container?.icon, color: container?.color, mounts: mounts, state: state, setState: setState }), orderedMounts.map((mount, idx) => {
|
|
104
|
+
const isCollapsed = collapsed.has(mount.key);
|
|
105
|
+
// Per-field merge: mount.props ?? component.props ?? key.
|
|
106
|
+
const compProps = scena.components.get(mount.component.component)?.props;
|
|
107
|
+
const color = mount.props?.color ?? compProps?.color;
|
|
108
|
+
return (_jsxs("div", { className: "oo-stack-section", "data-collapsed": isCollapsed, "data-drag-over": dragOverIdx === idx, "data-color": color, style: {
|
|
109
|
+
flex: isCollapsed ? '0 0 auto' : 1,
|
|
110
|
+
minHeight: 0,
|
|
111
|
+
display: 'flex',
|
|
112
|
+
flexDirection: 'column',
|
|
113
|
+
borderBottom: '1px solid var(--oo-color-border)',
|
|
114
|
+
}, children: [_jsxs("div", { className: "oo-stack-header", draggable: true, onDragStart: (e) => onHeaderDragStart(e, idx), onDragOver: (e) => onHeaderDragOver(e, idx), onDragLeave: onHeaderDragLeave, onDrop: (e) => onHeaderDrop(e, idx), onClick: () => toggleCollapsed(mount.key), onContextMenu: (e) => onSectionContextMenu(e, mount.key, idx), style: {
|
|
115
|
+
cursor: 'grab',
|
|
116
|
+
padding: 'var(--oo-spacing-xs) var(--oo-spacing-sm)',
|
|
117
|
+
background: 'var(--oo-color-surface)',
|
|
118
|
+
fontSize: 'var(--oo-font-size-xs)',
|
|
119
|
+
textTransform: 'uppercase',
|
|
120
|
+
color: 'var(--oo-color-muted)',
|
|
121
|
+
display: 'flex',
|
|
122
|
+
justifyContent: 'space-between',
|
|
123
|
+
alignItems: 'center',
|
|
124
|
+
userSelect: 'none',
|
|
125
|
+
}, children: [_jsxs("span", { style: { display: 'inline-flex', alignItems: 'center', gap: 6 }, children: [_jsx("span", { "aria-hidden": true, children: isCollapsed ? '▶' : '▼' }), _jsx(MountTitle, { mount: mount, fallback: mount.key, iconClassName: "oo-stack-section__icon", titleClassName: "oo-stack-section__title" })] }), _jsx("span", { onClick: (e) => {
|
|
126
|
+
e.stopPropagation();
|
|
127
|
+
onClose(mount.key);
|
|
128
|
+
}, title: "Close", style: { cursor: 'pointer' }, children: NAMED_GLYPH.closePanel })] }), !isCollapsed ? (_jsx("div", { style: { flex: 1, overflow: 'auto', minHeight: 0 }, children: renderMount(mount) })) : null] }, mount.key));
|
|
129
|
+
}), sectionMenu ? (_jsx(ContextMenu, { x: sectionMenu.x, y: sectionMenu.y, onClose: () => setSectionMenu(null), spec: { query: { slot: 'tab:context' }, footerHints: true }, context: {
|
|
130
|
+
...baseContext,
|
|
131
|
+
'$/tab/key': sectionMenu.key,
|
|
132
|
+
'$/tab/index': sectionMenu.idx,
|
|
133
|
+
'$/tab/isActive': true,
|
|
134
|
+
'$/tab/isPinned': false,
|
|
135
|
+
'$/group/tabCount': mounts.length,
|
|
136
|
+
} })) : null, bgMenu ? (_jsx(ContextMenu, { x: bgMenu.x, y: bgMenu.y, onClose: () => setBgMenu(null), spec: { query: { slot: 'surface:context' }, footerHints: true }, context: baseContext })) : null] }));
|
|
137
|
+
}
|
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { useEffect, useRef, useState, } from 'react';
|
|
3
|
+
import { useScena } from '../../react/ScenaProvider.js';
|
|
4
|
+
import { ContextMenu } from '../menu/ContextMenu.js';
|
|
5
|
+
import { NAMED_GLYPH } from '../display/Icon.js';
|
|
6
|
+
import { TabTitle } from './TabPanelLayout.js';
|
|
7
|
+
// Tab strip + active mount. Tabs are draggable for reorder (HTML5 DnD).
|
|
8
|
+
// Right-click on a tab opens slot `tab:context`. The [...] trailing button
|
|
9
|
+
// opens slot `tab-group:context`. Right-click on the strip empty area opens
|
|
10
|
+
// slot `surface:context`. The `view/title` slot still renders as inline
|
|
11
|
+
// action buttons next to the strip for the active mount.
|
|
12
|
+
const DRAG_MIME = 'application/x-scena-tab-index';
|
|
13
|
+
export function TabLayout({ surface, mounts, state, renderMount, onActivate, onClose, onReorder, }) {
|
|
14
|
+
const scena = useScena();
|
|
15
|
+
const persistedOrder = state.split?.order ?? [];
|
|
16
|
+
const orderSet = new Set(persistedOrder);
|
|
17
|
+
const orderedKnown = persistedOrder
|
|
18
|
+
.map((k) => mounts.find((m) => m.key === k))
|
|
19
|
+
.filter((m) => Boolean(m));
|
|
20
|
+
const newMounts = mounts.filter((m) => !orderSet.has(m.key));
|
|
21
|
+
const orderedMounts = [...orderedKnown, ...newMounts];
|
|
22
|
+
const active = orderedMounts.find((m) => m.key === state.activeContainerKey) ??
|
|
23
|
+
orderedMounts[orderedMounts.length - 1];
|
|
24
|
+
// Pinned tab keys — render a pin icon instead of × for these. Click on
|
|
25
|
+
// the pin runs `tab.unpin` to flip the state back.
|
|
26
|
+
const pinned = new Set(state.split?.pinned ?? []);
|
|
27
|
+
const titleEntries = active
|
|
28
|
+
? scena.commands.list({ slot: 'view/title', enabled: true })
|
|
29
|
+
: [];
|
|
30
|
+
const [dragOverIdx, setDragOverIdx] = useState(null);
|
|
31
|
+
// Per-tab context menu state. The capability paths injected via
|
|
32
|
+
// ContextMenu.context drive which commands show up in the picker.
|
|
33
|
+
const [tabMenu, setTabMenu] = useState(null);
|
|
34
|
+
const [groupMenu, setGroupMenu] = useState(null);
|
|
35
|
+
const [bgMenu, setBgMenu] = useState(null);
|
|
36
|
+
// Vertical wheel → horizontal scroll on the tab strip. Native listener
|
|
37
|
+
// (not React's onWheel) so we can preventDefault — React's synthetic wheel
|
|
38
|
+
// is passive and would let the page scroll vertically instead.
|
|
39
|
+
const tabsRef = useRef(null);
|
|
40
|
+
useEffect(() => {
|
|
41
|
+
const el = tabsRef.current;
|
|
42
|
+
if (!el)
|
|
43
|
+
return;
|
|
44
|
+
function onWheel(e) {
|
|
45
|
+
if (e.deltaY === 0)
|
|
46
|
+
return;
|
|
47
|
+
e.preventDefault();
|
|
48
|
+
el.scrollLeft += e.deltaY;
|
|
49
|
+
}
|
|
50
|
+
el.addEventListener('wheel', onWheel, { passive: false });
|
|
51
|
+
return () => el.removeEventListener('wheel', onWheel);
|
|
52
|
+
}, []);
|
|
53
|
+
function onTabContextMenu(e, tabKey, tabIdx) {
|
|
54
|
+
e.preventDefault();
|
|
55
|
+
e.stopPropagation();
|
|
56
|
+
setTabMenu({ x: e.clientX, y: e.clientY, tabKey, tabIdx });
|
|
57
|
+
}
|
|
58
|
+
function openGroupMenu(e) {
|
|
59
|
+
const rect = e.currentTarget.getBoundingClientRect();
|
|
60
|
+
setGroupMenu({ x: rect.right, y: rect.bottom + 2 });
|
|
61
|
+
}
|
|
62
|
+
function onBgContextMenu(e) {
|
|
63
|
+
// Only fire when the click really is on the empty body, not on a card.
|
|
64
|
+
if (e.target !== e.currentTarget)
|
|
65
|
+
return;
|
|
66
|
+
e.preventDefault();
|
|
67
|
+
setBgMenu({ x: e.clientX, y: e.clientY });
|
|
68
|
+
}
|
|
69
|
+
function onTabDragStart(e, idx) {
|
|
70
|
+
e.dataTransfer.setData(DRAG_MIME, String(idx));
|
|
71
|
+
e.dataTransfer.effectAllowed = 'move';
|
|
72
|
+
}
|
|
73
|
+
function onTabDragOver(e, idx) {
|
|
74
|
+
if (!e.dataTransfer.types.includes(DRAG_MIME))
|
|
75
|
+
return;
|
|
76
|
+
e.preventDefault();
|
|
77
|
+
e.dataTransfer.dropEffect = 'move';
|
|
78
|
+
setDragOverIdx(idx);
|
|
79
|
+
}
|
|
80
|
+
function onTabDragLeave() {
|
|
81
|
+
setDragOverIdx(null);
|
|
82
|
+
}
|
|
83
|
+
function onTabDrop(e, toIdx) {
|
|
84
|
+
if (!e.dataTransfer.types.includes(DRAG_MIME))
|
|
85
|
+
return;
|
|
86
|
+
e.preventDefault();
|
|
87
|
+
const fromIdx = Number(e.dataTransfer.getData(DRAG_MIME));
|
|
88
|
+
setDragOverIdx(null);
|
|
89
|
+
if (Number.isFinite(fromIdx) && fromIdx !== toIdx) {
|
|
90
|
+
onReorder(fromIdx, toIdx);
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
// Capability paths shared by every menu opened from this layout. The
|
|
94
|
+
// per-menu builder adds the mount-specific overrides on top.
|
|
95
|
+
const baseContext = {
|
|
96
|
+
'$/tab/canSplit': false,
|
|
97
|
+
'$/tab/canMove': false,
|
|
98
|
+
'$/group/canClose': false,
|
|
99
|
+
'$/group/canMaximize': false,
|
|
100
|
+
'$/surface/name': surface,
|
|
101
|
+
'$/surface/layoutId': 'tab',
|
|
102
|
+
'$/surface/mountCount': mounts.length,
|
|
103
|
+
'$/surface/closedHistory': 0,
|
|
104
|
+
};
|
|
105
|
+
// Host-contributed rows for the right-clicked tab (e.g. explorer's "Open
|
|
106
|
+
// with <viewer>" alternates). Empty for tabs no host claims.
|
|
107
|
+
const tabMenuMount = tabMenu
|
|
108
|
+
? orderedMounts.find((m) => m.key === tabMenu.tabKey)
|
|
109
|
+
: undefined;
|
|
110
|
+
const tabMenuExtra = tabMenuMount
|
|
111
|
+
? scena.mountMenus.collect('tab:context', tabMenuMount)
|
|
112
|
+
: undefined;
|
|
113
|
+
return (_jsxs("div", { className: "oo-layout oo-layout--tab", style: { display: 'flex', flexDirection: 'column', height: '100%' }, children: [_jsxs("div", { className: "tab-bar", children: [_jsx("div", { className: "tab-bar__strip", ref: tabsRef, children: orderedMounts.map((m, idx) => {
|
|
114
|
+
// Per-field merge: mount.props wins where defined; otherwise
|
|
115
|
+
// fall through to the component's registered default
|
|
116
|
+
// (ComponentDefinition.props); finally to the raw key.
|
|
117
|
+
const isPinned = pinned.has(m.key);
|
|
118
|
+
return (_jsx(TabTitle, { resourceKey: m.key, m: m, idx: idx, isPinned: isPinned, isActive: m === active, dragOverTab: dragOverIdx, onDragStart: (e) => onTabDragStart(e, idx), onDragOver: (e) => onTabDragOver(e, idx), onDragLeave: onTabDragLeave, onDrop: (e) => onTabDrop(e, idx), onClick: () => onActivate(m.key), onContextMenu: (e) => onTabContextMenu(e, m.key, idx), onClose: (e) => {
|
|
119
|
+
e.stopPropagation();
|
|
120
|
+
onClose(m.key);
|
|
121
|
+
}, onUnpin: (e) => {
|
|
122
|
+
e.stopPropagation();
|
|
123
|
+
scena.store.set('$/tab/key', m.key);
|
|
124
|
+
scena.store.set('$/surface/name', surface);
|
|
125
|
+
void scena.commands.execute('tab.unpin');
|
|
126
|
+
} }, m.key));
|
|
127
|
+
}) }), _jsxs("div", { className: "tab-bar__extras", children: [titleEntries.map((cmd, i) => {
|
|
128
|
+
const label = typeof cmd.title === 'function' ? cmd.title() : cmd.title;
|
|
129
|
+
return (_jsxs("button", { onClick: () => scena.commands.execute(cmd.id), title: String(label), children: [cmd.icon ? `${cmd.icon} ` : '', String(label)] }, i));
|
|
130
|
+
}), _jsx("button", { className: "tab-bar__more", title: "Group actions", "aria-label": "Group actions", onClick: openGroupMenu, children: NAMED_GLYPH.moreHoriz })] })] }), _jsx("div", { style: { flex: 1, minHeight: 0, position: 'relative' }, onContextMenu: onBgContextMenu, children: orderedMounts.length === 0 ? (_jsx("div", { style: { padding: 24, color: 'var(--oo-color-muted)' }, children: "Nothing open." })) : (
|
|
131
|
+
// Keep every mount mounted (state/scroll survive tab switches) and
|
|
132
|
+
// show only the active one. Conditionally rendering just the active
|
|
133
|
+
// mount unmounts the others, losing their React state.
|
|
134
|
+
orderedMounts.map((m) => (_jsx("div", { className: "oo-layout__mount", "data-active": m === active || undefined, style: { height: '100%', overflow: 'auto', display: m === active ? 'block' : 'none' }, children: renderMount(m) }, m.key)))) }), tabMenu ? (_jsx(ContextMenu, { x: tabMenu.x, y: tabMenu.y, onClose: () => setTabMenu(null), spec: { query: { slot: 'tab:context' }, extraItems: tabMenuExtra, footerHints: true }, context: {
|
|
135
|
+
...baseContext,
|
|
136
|
+
'$/tab/key': tabMenu.tabKey,
|
|
137
|
+
'$/tab/index': tabMenu.tabIdx,
|
|
138
|
+
'$/tab/isActive': tabMenu.tabKey === active?.key,
|
|
139
|
+
'$/tab/isPinned': pinned.has(tabMenu.tabKey),
|
|
140
|
+
'$/group/tabCount': orderedMounts.length,
|
|
141
|
+
} })) : null, groupMenu ? (_jsx(ContextMenu, { x: groupMenu.x, y: groupMenu.y, onClose: () => setGroupMenu(null), spec: { query: { slot: 'tab-group:context' }, footerHints: true }, context: {
|
|
142
|
+
...baseContext,
|
|
143
|
+
'$/group/tabCount': orderedMounts.length,
|
|
144
|
+
} })) : null, bgMenu ? (_jsx(ContextMenu, { x: bgMenu.x, y: bgMenu.y, onClose: () => setBgMenu(null), spec: { query: { slot: 'surface:context' }, footerHints: true }, context: baseContext })) : null] }));
|
|
145
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { type DragEvent as ReactDragEvent, type MouseEvent as ReactMouseEvent } from 'react';
|
|
2
|
+
import type { LayoutProps } from '../../types/layout.js';
|
|
3
|
+
import type { ResolvedMount } from '../../types/mount-surface.js';
|
|
4
|
+
export declare function TabPanelLayout({ surface, mounts, state, setState, renderMount, onActivate, onClose, }: LayoutProps): import("react").JSX.Element;
|
|
5
|
+
export declare function TabTitle({ m, resourceKey, isActive, dragOverTab, idx, onDragStart, onDragOver, onDragLeave, onDrop, onClick, onContextMenu, onClose, onUnpin, isPinned }: {
|
|
6
|
+
m: ResolvedMount | undefined;
|
|
7
|
+
resourceKey: string;
|
|
8
|
+
idx: number;
|
|
9
|
+
isActive: boolean;
|
|
10
|
+
dragOverTab: number | null;
|
|
11
|
+
isPinned: boolean;
|
|
12
|
+
onDragStart: (e: ReactDragEvent<HTMLDivElement>) => void;
|
|
13
|
+
onDragOver: (e: ReactDragEvent<HTMLDivElement>) => void;
|
|
14
|
+
onDragLeave: (e: ReactDragEvent<HTMLDivElement>) => void;
|
|
15
|
+
onDrop: (e: ReactDragEvent<HTMLDivElement>) => void;
|
|
16
|
+
onClick: (e: ReactMouseEvent<HTMLDivElement>) => void;
|
|
17
|
+
onContextMenu: (e: ReactMouseEvent<HTMLDivElement>) => void;
|
|
18
|
+
onClose: (e: ReactMouseEvent<HTMLElement>) => void;
|
|
19
|
+
onUnpin: (e: ReactMouseEvent<HTMLElement>) => void;
|
|
20
|
+
}): import("react").JSX.Element;
|