@selvajs/ui 6.6.0-beta.2 → 6.6.0-beta.20
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +0 -3
- package/dist/components/ErrorScreen.svelte +7 -3
- package/dist/components/compute/AppLayout.svelte +307 -123
- package/dist/components/compute/AppLayout.svelte.d.ts +28 -0
- package/dist/components/compute/CollapsedPanelStrip.svelte +4 -2
- package/dist/components/compute/ComputeApp.svelte +46 -22
- package/dist/components/compute/ComputeApp.svelte.d.ts +20 -3
- package/dist/components/compute/ComputeMessagesDialog.svelte +31 -41
- package/dist/components/compute/ParameterPresetManager.svelte +16 -65
- package/dist/components/compute/ParameterPresetManager.svelte.d.ts +4 -5
- package/dist/components/compute/SolveMessages.svelte +128 -121
- package/dist/components/compute/SolveMessages.svelte.d.ts +12 -12
- package/dist/components/layout/AppShell.svelte +10 -6
- package/dist/components/layout/FooterItemRenderer.svelte +2 -2
- package/dist/components/layout/FooterItemRenderer.svelte.d.ts +1 -1
- package/dist/components/layout/PageContent.svelte +3 -2
- package/dist/components/layout/PageFooter.svelte +26 -14
- package/dist/components/layout/PageHeader.svelte +14 -10
- package/dist/components/layout/SectionHeader.svelte +4 -2
- package/dist/components/layout/SideNav.svelte +57 -8
- package/dist/components/layout/SubNav.svelte +2 -2
- package/dist/components/preview/ChartOutput.svelte +131 -65
- package/dist/components/preview/Group.svelte +42 -22
- package/dist/components/preview/HelpButton.svelte +5 -3
- package/dist/components/preview/ImageOutput.svelte +435 -71
- package/dist/components/preview/InputControl.svelte +125 -51
- package/dist/components/preview/InputControl.svelte.d.ts +5 -1
- package/dist/components/preview/OutputDisplay.svelte +42 -28
- package/dist/components/preview/TabBar.svelte +8 -6
- package/dist/components/preview/TabBar.svelte.d.ts +2 -0
- package/dist/components/preview/TabContent.svelte +66 -31
- package/dist/components/preview/TabContent.svelte.d.ts +5 -1
- package/dist/components/preview/TabLayout.svelte +29 -8
- package/dist/components/preview/TabLayout.svelte.d.ts +5 -0
- package/dist/components/preview/inputs/CheckboxInput.svelte +1 -1
- package/dist/components/preview/inputs/ChecklistInput.svelte +11 -6
- package/dist/components/preview/inputs/ChecklistInput.svelte.d.ts +2 -1
- package/dist/components/preview/inputs/ColorInput.svelte +357 -13
- package/dist/components/preview/inputs/ColorInput.svelte.d.ts +2 -0
- package/dist/components/preview/inputs/DropdownInput.svelte +20 -5
- package/dist/components/preview/inputs/DropdownInput.svelte.d.ts +2 -1
- package/dist/components/preview/inputs/FileInput.svelte +115 -103
- package/dist/components/preview/inputs/GeometryInput.svelte +128 -0
- package/dist/components/preview/inputs/GeometryInput.svelte.d.ts +21 -0
- package/dist/components/preview/inputs/NumberInput.svelte +98 -16
- package/dist/components/preview/inputs/NumberInput.svelte.d.ts +2 -0
- package/dist/components/preview/inputs/OptionGlyph.svelte +29 -0
- package/dist/components/preview/inputs/OptionGlyph.svelte.d.ts +8 -0
- package/dist/components/preview/inputs/SegmentedInput.svelte +45 -0
- package/dist/components/preview/inputs/SegmentedInput.svelte.d.ts +12 -0
- package/dist/components/preview/inputs/TextInput.svelte +11 -6
- package/dist/components/preview/inputs/TileInput.svelte +83 -0
- package/dist/components/preview/inputs/TileInput.svelte.d.ts +12 -0
- package/dist/components/preview/inputs/index.d.ts +3 -0
- package/dist/components/preview/inputs/index.js +3 -0
- package/dist/components/primitives/CalculateButton.svelte +56 -24
- package/dist/components/primitives/CalculateButton.svelte.d.ts +3 -0
- package/dist/components/primitives/Callout.svelte +8 -6
- package/dist/components/primitives/Callout.svelte.d.ts +4 -4
- package/dist/components/primitives/DataTable.svelte +38 -4
- package/dist/components/primitives/DataTable.svelte.d.ts +2 -0
- package/dist/components/primitives/FilterableDropdown.svelte +13 -1
- package/dist/components/primitives/FilterableDropdown.svelte.d.ts +5 -0
- package/dist/components/primitives/ImageUploadField.svelte +1 -1
- package/dist/components/primitives/SolvingIndicator.svelte +245 -15
- package/dist/components/primitives/SolvingIndicator.svelte.d.ts +15 -0
- package/dist/components/primitives/alert-dialog/alert-dialog-content.svelte +1 -1
- package/dist/components/primitives/badge/badge.svelte +4 -4
- package/dist/components/primitives/badge/badge.svelte.d.ts +10 -10
- package/dist/components/primitives/button/button.svelte +10 -8
- package/dist/components/primitives/button/button.svelte.d.ts +20 -17
- package/dist/components/primitives/card/card.svelte +1 -1
- package/dist/components/primitives/card/card.svelte.d.ts +1 -1
- package/dist/components/primitives/checkbox/checkbox.svelte +1 -1
- package/dist/components/primitives/command/command-input.svelte +1 -1
- package/dist/components/primitives/command/command-item.svelte +1 -1
- package/dist/components/primitives/command/command-link-item.svelte +1 -1
- package/dist/components/primitives/command/command.svelte +1 -1
- package/dist/components/primitives/context-menu/context-menu-checkbox-item.svelte +1 -1
- package/dist/components/primitives/context-menu/context-menu-content.svelte +1 -1
- package/dist/components/primitives/context-menu/context-menu-item.svelte +1 -1
- package/dist/components/primitives/context-menu/context-menu-radio-item.svelte +1 -1
- package/dist/components/primitives/context-menu/context-menu-sub-content.svelte +1 -1
- package/dist/components/primitives/context-menu/context-menu-sub-trigger.svelte +1 -1
- package/dist/components/primitives/dialog/dialog-content.svelte +7 -3
- package/dist/components/primitives/drawer/Drawer.svelte +1 -1
- package/dist/components/primitives/dropdown-menu/dropdown-menu-checkbox-item.svelte +31 -11
- package/dist/components/primitives/dropdown-menu/dropdown-menu-checkbox-item.svelte.d.ts +2 -0
- package/dist/components/primitives/dropdown-menu/dropdown-menu-content.svelte +5 -1
- package/dist/components/primitives/dropdown-menu/dropdown-menu-content.svelte.d.ts +2 -0
- package/dist/components/primitives/dropdown-menu/dropdown-menu-item.svelte +4 -2
- package/dist/components/primitives/dropdown-menu/dropdown-menu-item.svelte.d.ts +2 -1
- package/dist/components/primitives/dropdown-menu/dropdown-menu-radio-item.svelte +1 -1
- package/dist/components/primitives/dropdown-menu/dropdown-menu-shortcut.svelte +1 -1
- package/dist/components/primitives/dropdown-menu/dropdown-menu-sub-content.svelte +1 -1
- package/dist/components/primitives/dropdown-menu/dropdown-menu-sub-trigger.svelte +1 -1
- package/dist/components/primitives/index.d.ts +1 -1
- package/dist/components/primitives/index.js +1 -1
- package/dist/components/primitives/input/input.svelte +4 -4
- package/dist/components/primitives/input-group/input-group-input.svelte.d.ts +1 -1
- package/dist/components/primitives/input-group/input-group.svelte +1 -1
- package/dist/components/primitives/mode-toggle/mode-toggle.svelte +5 -2
- package/dist/components/primitives/popover/popover-content.svelte +1 -1
- package/dist/components/primitives/resizable/resizable-handle.svelte +2 -2
- package/dist/components/primitives/scroll-area/scroll-area.svelte +1 -1
- package/dist/components/primitives/search/search.svelte +2 -2
- package/dist/components/primitives/select/select-content.svelte +1 -1
- package/dist/components/primitives/select/select-item.svelte +1 -1
- package/dist/components/primitives/select/select-trigger.svelte +1 -1
- package/dist/components/primitives/slider/slider.svelte +8 -3
- package/dist/components/primitives/slider/slider.svelte.d.ts +5 -1
- package/dist/components/primitives/switch/switch.svelte +1 -1
- package/dist/components/primitives/tabs/tabs-list.svelte +2 -2
- package/dist/components/primitives/tabs/tabs-list.svelte.d.ts +6 -6
- package/dist/components/primitives/tabs/tabs-trigger.svelte +3 -3
- package/dist/components/primitives/tabs/tabs-trigger.svelte.d.ts +7 -7
- package/dist/components/primitives/textarea/textarea.svelte +1 -1
- package/dist/components/primitives/toggle/toggle.svelte +11 -3
- package/dist/components/primitives/toggle/toggle.svelte.d.ts +13 -4
- package/dist/components/primitives/toggle-group/toggle-group-item.svelte +1 -1
- package/dist/components/primitives/toggle-group/toggle-group.svelte +1 -1
- package/dist/components/primitives/tooltip/index.d.ts +6 -0
- package/dist/components/primitives/tooltip/index.js +8 -0
- package/dist/components/primitives/tooltip/tooltip-content.svelte +34 -0
- package/dist/components/primitives/tooltip/tooltip-content.svelte.d.ts +10 -0
- package/dist/components/primitives/tooltip/tooltip-portal.svelte +7 -0
- package/dist/components/primitives/tooltip/tooltip-portal.svelte.d.ts +4 -0
- package/dist/components/primitives/tooltip/tooltip-provider.svelte +7 -0
- package/dist/components/primitives/tooltip/tooltip-provider.svelte.d.ts +4 -0
- package/dist/components/primitives/tooltip/tooltip-trigger.svelte +7 -0
- package/dist/components/primitives/tooltip/tooltip-trigger.svelte.d.ts +4 -0
- package/dist/components/primitives/tooltip/tooltip.svelte +7 -0
- package/dist/components/primitives/tooltip/tooltip.svelte.d.ts +4 -0
- package/dist/components/viewer/MeshMetadataPanel.svelte +119 -0
- package/dist/components/viewer/MeshMetadataPanel.svelte.d.ts +9 -0
- package/dist/components/viewer/SceneManager.svelte +32 -21
- package/dist/components/viewer/SceneManager.svelte.d.ts +3 -1
- package/dist/components/viewer/Viewer.svelte +195 -207
- package/dist/components/viewer/Viewer.svelte.d.ts +7 -2
- package/dist/components/viewer/ViewerDock.svelte +404 -0
- package/dist/components/viewer/ViewerDock.svelte.d.ts +42 -0
- package/dist/composables/useFooterItem.svelte.d.ts +1 -1
- package/dist/composables/useFooterItem.svelte.js +1 -1
- package/dist/compute/liveProgress.svelte.d.ts +16 -0
- package/dist/compute/liveProgress.svelte.js +90 -0
- package/dist/compute/run-panel-action.d.ts +8 -0
- package/dist/compute/run-panel-action.js +12 -0
- package/dist/compute/solving.svelte.d.ts +11 -7
- package/dist/compute/solving.svelte.js +64 -45
- package/dist/compute/useSolveSession.svelte.js +3 -0
- package/dist/constants.d.ts +6 -8
- package/dist/constants.js +8 -11
- package/dist/contexts/hostContext.svelte.d.ts +39 -0
- package/dist/contexts/hostContext.svelte.js +9 -0
- package/dist/features/chart/plotly-compat.d.ts +15 -0
- package/dist/features/chart/plotly-compat.js +124 -0
- package/dist/i18n/localeContext.svelte.d.ts +10 -3
- package/dist/i18n/localeContext.svelte.js +27 -5
- package/dist/i18n/messages.d.ts +164 -2
- package/dist/i18n/messages.js +281 -11
- package/dist/index.d.ts +6 -1
- package/dist/index.js +5 -0
- package/dist/public.d.ts +2 -1
- package/dist/public.js +1 -0
- package/dist/schema/host-support.d.ts +29 -0
- package/dist/schema/host-support.js +97 -0
- package/dist/schema/option-display.d.ts +12 -0
- package/dist/schema/option-display.js +29 -0
- package/dist/schema/param-exporter.d.ts +4 -1
- package/dist/schema/param-exporter.js +10 -6
- package/dist/schema/visibility-rules.d.ts +7 -1
- package/dist/schema/visibility-rules.js +38 -0
- package/dist/styles/base.css +116 -83
- package/dist/types/actionButton.d.ts +17 -3
- package/dist/types/presetLabels.d.ts +3 -2
- package/dist/types/presetLabels.js +9 -8
- package/dist/utils/color-space.d.ts +21 -0
- package/dist/utils/color-space.js +90 -0
- package/dist/utils/file-download.js +10 -22
- package/dist/utils/host-files.d.ts +12 -0
- package/dist/utils/host-files.js +46 -0
- package/dist/utils/loadScript.d.ts +2 -0
- package/dist/utils/loadScript.js +2 -0
- package/dist/utils/webp-to-png.d.ts +10 -0
- package/dist/utils/webp-to-png.js +41 -0
- package/package.json +30 -22
- package/src/lib/components/ErrorScreen.svelte +7 -3
- package/src/lib/components/compute/AppLayout.svelte +307 -123
- package/src/lib/components/compute/CollapsedPanelStrip.svelte +4 -2
- package/src/lib/components/compute/ComputeApp.svelte +46 -22
- package/src/lib/components/compute/ComputeMessagesDialog.svelte +32 -42
- package/src/lib/components/compute/ParameterPresetManager.svelte +16 -65
- package/src/lib/components/compute/SolveMessages.svelte +130 -123
- package/src/lib/components/layout/AppShell.svelte +10 -6
- package/src/lib/components/layout/FooterItemRenderer.svelte +2 -2
- package/src/lib/components/layout/PageContent.svelte +3 -2
- package/src/lib/components/layout/PageFooter.svelte +26 -14
- package/src/lib/components/layout/PageHeader.svelte +14 -10
- package/src/lib/components/layout/SectionHeader.svelte +4 -2
- package/src/lib/components/layout/SideNav.svelte +57 -8
- package/src/lib/components/layout/SubNav.svelte +2 -2
- package/src/lib/components/preview/ChartOutput.svelte +131 -65
- package/src/lib/components/preview/Group.svelte +42 -22
- package/src/lib/components/preview/HelpButton.svelte +5 -3
- package/src/lib/components/preview/ImageOutput.svelte +435 -71
- package/src/lib/components/preview/InputControl.svelte +125 -51
- package/src/lib/components/preview/OutputDisplay.svelte +42 -28
- package/src/lib/components/preview/TabBar.svelte +8 -6
- package/src/lib/components/preview/TabContent.svelte +66 -31
- package/src/lib/components/preview/TabLayout.svelte +29 -8
- package/src/lib/components/preview/inputs/CheckboxInput.svelte +1 -1
- package/src/lib/components/preview/inputs/ChecklistInput.svelte +11 -6
- package/src/lib/components/preview/inputs/ColorInput.svelte +357 -13
- package/src/lib/components/preview/inputs/DropdownInput.svelte +20 -5
- package/src/lib/components/preview/inputs/FileInput.svelte +115 -103
- package/src/lib/components/preview/inputs/GeometryInput.svelte +128 -0
- package/src/lib/components/preview/inputs/NumberInput.svelte +98 -16
- package/src/lib/components/preview/inputs/OptionGlyph.svelte +29 -0
- package/src/lib/components/preview/inputs/SegmentedInput.svelte +45 -0
- package/src/lib/components/preview/inputs/TextInput.svelte +11 -6
- package/src/lib/components/preview/inputs/TileInput.svelte +83 -0
- package/src/lib/components/preview/inputs/index.ts +3 -0
- package/src/lib/components/primitives/CalculateButton.svelte +56 -24
- package/src/lib/components/primitives/Callout.svelte +9 -7
- package/src/lib/components/primitives/DataTable.svelte +38 -4
- package/src/lib/components/primitives/FilterableDropdown.svelte +14 -2
- package/src/lib/components/primitives/ImageUploadField.svelte +1 -1
- package/src/lib/components/primitives/IssueList.svelte +1 -1
- package/src/lib/components/primitives/SeverityIcon.svelte +1 -1
- package/src/lib/components/primitives/SolvingIndicator.svelte +245 -15
- package/src/lib/components/primitives/StateDisplay.svelte +1 -1
- package/src/lib/components/primitives/alert-dialog/alert-dialog-action.svelte +2 -2
- package/src/lib/components/primitives/alert-dialog/alert-dialog-cancel.svelte +2 -2
- package/src/lib/components/primitives/alert-dialog/alert-dialog-content.svelte +2 -2
- package/src/lib/components/primitives/alert-dialog/alert-dialog-description.svelte +1 -1
- package/src/lib/components/primitives/alert-dialog/alert-dialog-footer.svelte +1 -1
- package/src/lib/components/primitives/alert-dialog/alert-dialog-header.svelte +1 -1
- package/src/lib/components/primitives/alert-dialog/alert-dialog-overlay.svelte +1 -1
- package/src/lib/components/primitives/alert-dialog/alert-dialog-title.svelte +1 -1
- package/src/lib/components/primitives/badge/badge.svelte +5 -5
- package/src/lib/components/primitives/button/button.svelte +10 -8
- package/src/lib/components/primitives/button-group/button-group-separator.svelte +2 -2
- package/src/lib/components/primitives/button-group/button-group-text.svelte +1 -1
- package/src/lib/components/primitives/button-group/button-group.svelte +1 -1
- package/src/lib/components/primitives/card/card-content.svelte +1 -1
- package/src/lib/components/primitives/card/card-description.svelte +1 -1
- package/src/lib/components/primitives/card/card-footer.svelte +1 -1
- package/src/lib/components/primitives/card/card-header.svelte +1 -1
- package/src/lib/components/primitives/card/card-title.svelte +1 -1
- package/src/lib/components/primitives/card/card.svelte +2 -2
- package/src/lib/components/primitives/checkbox/checkbox.svelte +2 -2
- package/src/lib/components/primitives/command/command-dialog.svelte +2 -2
- package/src/lib/components/primitives/command/command-empty.svelte +1 -1
- package/src/lib/components/primitives/command/command-group.svelte +1 -1
- package/src/lib/components/primitives/command/command-input.svelte +3 -3
- package/src/lib/components/primitives/command/command-item.svelte +2 -2
- package/src/lib/components/primitives/command/command-link-item.svelte +2 -2
- package/src/lib/components/primitives/command/command-list.svelte +1 -1
- package/src/lib/components/primitives/command/command-separator.svelte +1 -1
- package/src/lib/components/primitives/command/command-shortcut.svelte +1 -1
- package/src/lib/components/primitives/command/command.svelte +2 -2
- package/src/lib/components/primitives/context-menu/context-menu-checkbox-item.svelte +2 -2
- package/src/lib/components/primitives/context-menu/context-menu-content.svelte +2 -2
- package/src/lib/components/primitives/context-menu/context-menu-group-heading.svelte +1 -1
- package/src/lib/components/primitives/context-menu/context-menu-item.svelte +2 -2
- package/src/lib/components/primitives/context-menu/context-menu-label.svelte +1 -1
- package/src/lib/components/primitives/context-menu/context-menu-radio-item.svelte +2 -2
- package/src/lib/components/primitives/context-menu/context-menu-separator.svelte +1 -1
- package/src/lib/components/primitives/context-menu/context-menu-shortcut.svelte +1 -1
- package/src/lib/components/primitives/context-menu/context-menu-sub-content.svelte +2 -2
- package/src/lib/components/primitives/context-menu/context-menu-sub-trigger.svelte +2 -2
- package/src/lib/components/primitives/dialog/dialog-content.svelte +8 -4
- package/src/lib/components/primitives/dialog/dialog-description.svelte +1 -1
- package/src/lib/components/primitives/dialog/dialog-footer.svelte +1 -1
- package/src/lib/components/primitives/dialog/dialog-header.svelte +1 -1
- package/src/lib/components/primitives/dialog/dialog-overlay.svelte +1 -1
- package/src/lib/components/primitives/dialog/dialog-title.svelte +1 -1
- package/src/lib/components/primitives/drawer/Drawer.svelte +1 -1
- package/src/lib/components/primitives/dropdown-menu/dropdown-menu-checkbox-item.svelte +32 -12
- package/src/lib/components/primitives/dropdown-menu/dropdown-menu-content.svelte +6 -2
- package/src/lib/components/primitives/dropdown-menu/dropdown-menu-group-heading.svelte +1 -1
- package/src/lib/components/primitives/dropdown-menu/dropdown-menu-item.svelte +5 -3
- package/src/lib/components/primitives/dropdown-menu/dropdown-menu-label.svelte +1 -1
- package/src/lib/components/primitives/dropdown-menu/dropdown-menu-radio-item.svelte +2 -2
- package/src/lib/components/primitives/dropdown-menu/dropdown-menu-separator.svelte +1 -1
- package/src/lib/components/primitives/dropdown-menu/dropdown-menu-shortcut.svelte +2 -2
- package/src/lib/components/primitives/dropdown-menu/dropdown-menu-sub-content.svelte +2 -2
- package/src/lib/components/primitives/dropdown-menu/dropdown-menu-sub-trigger.svelte +2 -2
- package/src/lib/components/primitives/empty/empty-content.svelte +1 -1
- package/src/lib/components/primitives/empty/empty-description.svelte +1 -1
- package/src/lib/components/primitives/empty/empty-header.svelte +1 -1
- package/src/lib/components/primitives/empty/empty-media.svelte +1 -1
- package/src/lib/components/primitives/empty/empty-title.svelte +1 -1
- package/src/lib/components/primitives/empty/empty.svelte +1 -1
- package/src/lib/components/primitives/field/field-content.svelte +1 -1
- package/src/lib/components/primitives/field/field-description.svelte +1 -1
- package/src/lib/components/primitives/field/field-error.svelte +1 -1
- package/src/lib/components/primitives/field/field-group.svelte +1 -1
- package/src/lib/components/primitives/field/field-label.svelte +2 -2
- package/src/lib/components/primitives/field/field-legend.svelte +1 -1
- package/src/lib/components/primitives/field/field-separator.svelte +2 -2
- package/src/lib/components/primitives/field/field-set.svelte +1 -1
- package/src/lib/components/primitives/field/field-title.svelte +1 -1
- package/src/lib/components/primitives/field/field.svelte +1 -1
- package/src/lib/components/primitives/index.ts +1 -1
- package/src/lib/components/primitives/input/input.svelte +5 -5
- package/src/lib/components/primitives/input-group/input-group-addon.svelte +1 -1
- package/src/lib/components/primitives/input-group/input-group-button.svelte +2 -2
- package/src/lib/components/primitives/input-group/input-group-input.svelte +2 -2
- package/src/lib/components/primitives/input-group/input-group-text.svelte +1 -1
- package/src/lib/components/primitives/input-group/input-group-textarea.svelte +2 -2
- package/src/lib/components/primitives/input-group/input-group.svelte +2 -2
- package/src/lib/components/primitives/label/label.svelte +1 -1
- package/src/lib/components/primitives/mode-toggle/mode-toggle.svelte +5 -2
- package/src/lib/components/primitives/popover/popover-content.svelte +2 -2
- package/src/lib/components/primitives/popover/popover-description.svelte +1 -1
- package/src/lib/components/primitives/popover/popover-header.svelte +1 -1
- package/src/lib/components/primitives/popover/popover-title.svelte +1 -1
- package/src/lib/components/primitives/popover/popover-trigger.svelte +1 -1
- package/src/lib/components/primitives/resizable/resizable-handle.svelte +3 -3
- package/src/lib/components/primitives/resizable/resizable-pane-group.svelte +1 -1
- package/src/lib/components/primitives/scroll-area/scroll-area-scrollbar.svelte +1 -1
- package/src/lib/components/primitives/scroll-area/scroll-area.svelte +2 -2
- package/src/lib/components/primitives/search/search.svelte +3 -3
- package/src/lib/components/primitives/select/select-content.svelte +2 -2
- package/src/lib/components/primitives/select/select-group-heading.svelte +1 -1
- package/src/lib/components/primitives/select/select-item.svelte +2 -2
- package/src/lib/components/primitives/select/select-label.svelte +1 -1
- package/src/lib/components/primitives/select/select-scroll-down-button.svelte +1 -1
- package/src/lib/components/primitives/select/select-scroll-up-button.svelte +1 -1
- package/src/lib/components/primitives/select/select-separator.svelte +2 -2
- package/src/lib/components/primitives/select/select-trigger.svelte +2 -2
- package/src/lib/components/primitives/separator/separator.svelte +1 -1
- package/src/lib/components/primitives/slider/slider.svelte +9 -4
- package/src/lib/components/primitives/spinner/spinner.svelte +1 -1
- package/src/lib/components/primitives/switch/switch.svelte +2 -2
- package/src/lib/components/primitives/tabs/tabs-content.svelte +1 -1
- package/src/lib/components/primitives/tabs/tabs-list.svelte +3 -3
- package/src/lib/components/primitives/tabs/tabs-trigger.svelte +4 -4
- package/src/lib/components/primitives/tabs/tabs.svelte +1 -1
- package/src/lib/components/primitives/textarea/textarea.svelte +2 -2
- package/src/lib/components/primitives/toggle/toggle.svelte +12 -4
- package/src/lib/components/primitives/toggle-group/toggle-group-item.svelte +3 -3
- package/src/lib/components/primitives/toggle-group/toggle-group.svelte +3 -3
- package/src/lib/components/primitives/tooltip/index.ts +19 -0
- package/src/lib/components/primitives/tooltip/tooltip-content.svelte +34 -0
- package/src/lib/components/primitives/tooltip/tooltip-portal.svelte +7 -0
- package/src/lib/components/primitives/tooltip/tooltip-provider.svelte +7 -0
- package/src/lib/components/primitives/tooltip/tooltip-trigger.svelte +7 -0
- package/src/lib/components/primitives/tooltip/tooltip.svelte +7 -0
- package/src/lib/components/viewer/MeshMetadataPanel.svelte +119 -0
- package/src/lib/components/viewer/SceneManager.svelte +32 -21
- package/src/lib/components/viewer/Viewer.svelte +196 -208
- package/src/lib/components/viewer/ViewerDock.svelte +404 -0
- package/src/lib/composables/useFooterItem.svelte.ts +1 -1
- package/src/lib/compute/liveProgress.svelte.ts +103 -0
- package/src/lib/compute/run-panel-action.ts +16 -0
- package/src/lib/compute/solving.svelte.ts +66 -50
- package/src/lib/compute/useSolveSession.svelte.ts +3 -0
- package/src/lib/constants.ts +8 -11
- package/src/lib/contexts/hostContext.svelte.ts +51 -0
- package/src/lib/features/chart/plotly-compat.ts +141 -0
- package/src/lib/i18n/localeContext.svelte.ts +40 -5
- package/src/lib/i18n/messages.ts +487 -13
- package/src/lib/index.ts +23 -0
- package/src/lib/public.ts +2 -0
- package/src/lib/schema/host-support.ts +129 -0
- package/src/lib/schema/option-display.ts +44 -0
- package/src/lib/schema/param-exporter.ts +10 -7
- package/src/lib/schema/visibility-rules.ts +50 -1
- package/src/lib/styles/base.css +116 -83
- package/src/lib/types/actionButton.ts +16 -3
- package/src/lib/types/presetLabels.ts +13 -11
- package/src/lib/utils/color-space.ts +107 -0
- package/src/lib/utils/file-download.ts +11 -21
- package/src/lib/utils/host-files.ts +61 -0
- package/src/lib/utils/loadScript.ts +3 -0
- package/src/lib/utils/webp-to-png.ts +48 -0
- package/dist/components/primitives/theme-switcher/ThemeSwitcher.svelte +0 -39
- package/dist/components/primitives/theme-switcher/ThemeSwitcher.svelte.d.ts +0 -3
- package/dist/components/primitives/theme-switcher/index.d.ts +0 -1
- package/dist/components/primitives/theme-switcher/index.js +0 -1
- package/dist/components/viewer/MeshMetadataDialog.svelte +0 -126
- package/dist/components/viewer/MeshMetadataDialog.svelte.d.ts +0 -10
- package/dist/styles/themes/cyberpunk.css +0 -98
- package/dist/styles/themes/neutral.css +0 -72
- package/dist/styles/themes/ocean.css +0 -75
- package/dist/styles/themes/selva.css +0 -105
- package/dist/theme/themeStore.svelte.d.ts +0 -12
- package/dist/theme/themeStore.svelte.js +0 -40
- package/dist/theme/themes.d.ts +0 -5
- package/dist/theme/themes.js +0 -13
- package/src/lib/components/primitives/theme-switcher/ThemeSwitcher.svelte +0 -39
- package/src/lib/components/primitives/theme-switcher/index.ts +0 -1
- package/src/lib/components/viewer/MeshMetadataDialog.svelte +0 -126
- package/src/lib/styles/themes/cyberpunk.css +0 -98
- package/src/lib/styles/themes/neutral.css +0 -72
- package/src/lib/styles/themes/ocean.css +0 -75
- package/src/lib/styles/themes/selva.css +0 -105
- package/src/lib/theme/themeStore.svelte.ts +0 -50
- package/src/lib/theme/themes.ts +0 -18
|
@@ -16,9 +16,11 @@
|
|
|
16
16
|
import { LoaderCircle } from '@lucide/svelte';
|
|
17
17
|
import type { SolveDiagnostic } from '@selvajs/solve/shared';
|
|
18
18
|
import type { LiveSolveState, SolvePhase } from '@selvajs/solve/client';
|
|
19
|
-
import { Button } from '../primitives/button';
|
|
19
|
+
import { Button } from '../primitives/button/index.js';
|
|
20
20
|
import IssueList, { type Issue } from '../primitives/IssueList.svelte';
|
|
21
21
|
import SeverityIcon from '../primitives/SeverityIcon.svelte';
|
|
22
|
+
import { getLocaleContext } from '../../i18n/localeContext.svelte.js';
|
|
23
|
+
import { createLiveProgress } from '../../compute/liveProgress.svelte.js';
|
|
22
24
|
|
|
23
25
|
interface Props {
|
|
24
26
|
/** What the running (or most recent) solve has said over the live channel. */
|
|
@@ -30,33 +32,20 @@
|
|
|
30
32
|
onabort: () => void;
|
|
31
33
|
onconfirm: () => void;
|
|
32
34
|
ondiscard: () => void;
|
|
33
|
-
|
|
35
|
+
/**
|
|
36
|
+
* See `createSolvingIndicator`. The live panel would only paint once the solve is over, so
|
|
37
|
+
* an Esc hint stands in for it; the result's messages still show.
|
|
38
|
+
*/
|
|
39
|
+
freezesDuringSolve?: boolean;
|
|
40
|
+
/** `floating` overlays the bottom centre; `inline` sits in the flow below the host's content. */
|
|
41
|
+
placement?: 'floating' | 'inline';
|
|
42
|
+
/**
|
|
43
|
+
* The host shows progress and Abort itself (`AppLayout`'s solve status), so the live view
|
|
44
|
+
* keeps only the messages that arrive mid-solve.
|
|
45
|
+
*/
|
|
46
|
+
progressShownByHost?: boolean;
|
|
34
47
|
}
|
|
35
48
|
|
|
36
|
-
interface Labels {
|
|
37
|
-
solving: string;
|
|
38
|
-
blockedTitle: string;
|
|
39
|
-
messagesTitle: string;
|
|
40
|
-
blockedDescription: string;
|
|
41
|
-
messagesDescription: string;
|
|
42
|
-
confirm: string;
|
|
43
|
-
discard: string;
|
|
44
|
-
abort: string;
|
|
45
|
-
dismiss: string;
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
const DEFAULT_LABELS: Labels = {
|
|
49
|
-
solving: 'Solving…',
|
|
50
|
-
blockedTitle: 'Solve stopped',
|
|
51
|
-
messagesTitle: 'Solve messages',
|
|
52
|
-
blockedDescription: 'The definition stopped this solve. No results were produced.',
|
|
53
|
-
messagesDescription: 'This solve reported the following. Continue to see the result.',
|
|
54
|
-
confirm: 'Continue',
|
|
55
|
-
discard: 'Discard',
|
|
56
|
-
abort: 'Abort',
|
|
57
|
-
dismiss: 'Dismiss'
|
|
58
|
-
};
|
|
59
|
-
|
|
60
49
|
let {
|
|
61
50
|
live,
|
|
62
51
|
phase: sessionPhase,
|
|
@@ -64,55 +53,20 @@
|
|
|
64
53
|
onabort,
|
|
65
54
|
onconfirm,
|
|
66
55
|
ondiscard,
|
|
67
|
-
|
|
56
|
+
freezesDuringSolve = false,
|
|
57
|
+
placement = 'floating',
|
|
58
|
+
progressShownByHost = false
|
|
68
59
|
}: Props = $props();
|
|
69
60
|
|
|
70
|
-
const
|
|
61
|
+
const locale = getLocaleContext();
|
|
62
|
+
const t = $derived(locale.messages);
|
|
71
63
|
|
|
72
|
-
const
|
|
64
|
+
const REMARK_LINGER_MS = 6000;
|
|
73
65
|
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
// crawls within each step. A slower run waits at the step's end; a faster one snaps ahead.
|
|
79
|
-
let bars = $state.raw<Record<string, { width: number; ms: number }>>({});
|
|
80
|
-
// Any live event re-runs the effect below. Only a source with a new report may re-snap;
|
|
81
|
-
// the rest keep easing where they are.
|
|
82
|
-
let seen = new Map<string, unknown>();
|
|
83
|
-
let targets: Record<string, { width: number; ms: number }> = {};
|
|
84
|
-
$effect(() => {
|
|
85
|
-
const snapped: Record<string, { width: number; ms: number }> = {};
|
|
86
|
-
const eased: Record<string, { width: number; ms: number }> = {};
|
|
87
|
-
const current = untrack(() => bars);
|
|
88
|
-
// eslint-disable-next-line svelte/prefer-svelte-reactivity -- bookkeeping for this effect; reactive reads here would re-trigger it
|
|
89
|
-
const nextSeen = new Map<string, unknown>();
|
|
90
|
-
for (const p of progress) {
|
|
91
|
-
if (p.fraction === undefined) continue;
|
|
92
|
-
const key = p.source ?? '';
|
|
93
|
-
nextSeen.set(key, p);
|
|
94
|
-
if (seen.get(key) === p && current[key]) {
|
|
95
|
-
snapped[key] = current[key];
|
|
96
|
-
// This run's cleanup cancelled the frame that would have started the ease.
|
|
97
|
-
if (targets[key] && current[key] !== targets[key]) eased[key] = targets[key];
|
|
98
|
-
continue;
|
|
99
|
-
}
|
|
100
|
-
snapped[key] = { width: p.fraction, ms: 150 };
|
|
101
|
-
if (p.nextFraction !== undefined && p.stepMs !== undefined) {
|
|
102
|
-
eased[key] = { width: p.nextFraction, ms: p.stepMs };
|
|
103
|
-
}
|
|
104
|
-
}
|
|
105
|
-
seen = nextSeen;
|
|
106
|
-
targets = eased;
|
|
107
|
-
bars = snapped;
|
|
108
|
-
if (Object.keys(eased).length === 0) return;
|
|
109
|
-
// Two frames: the snapped width must be painted before the eased one is set, or the
|
|
110
|
-
// browser folds both into one style change and there is nothing to transition from.
|
|
111
|
-
let frame = requestAnimationFrame(() => {
|
|
112
|
-
frame = requestAnimationFrame(() => (bars = { ...snapped, ...eased }));
|
|
113
|
-
});
|
|
114
|
-
return () => cancelAnimationFrame(frame);
|
|
115
|
-
});
|
|
66
|
+
const liveProgress = createLiveProgress(() => live);
|
|
67
|
+
const progress = $derived(liveProgress.progress);
|
|
68
|
+
const bars = $derived(liveProgress.bars);
|
|
69
|
+
const headline = $derived(liveProgress.headline);
|
|
116
70
|
// Grasshopper's own complaints stay in the footer log; this panel shows what the author wrote.
|
|
117
71
|
const authored = $derived(diagnostics.filter((d) => d.isGate));
|
|
118
72
|
|
|
@@ -139,16 +93,30 @@
|
|
|
139
93
|
// Keyed on the diagnostics array's identity, which every report renews, rather than on a
|
|
140
94
|
// solve id: only the live channel has one, and on the Compute path remarks arrive with the
|
|
141
95
|
// result. Once per array, so remarks that sat behind a review do not reappear after Continue.
|
|
96
|
+
//
|
|
97
|
+
// A remark is shown once while it stays raised, not after every solve. Every report repeats
|
|
98
|
+
// it: Grasshopper keeps runtime messages on a Message component an input change did not
|
|
99
|
+
// reach, and Compute re-solves the whole definition. It shows again once a solve stops
|
|
100
|
+
// raising it and a later one raises it anew.
|
|
142
101
|
let lingering = $state(false);
|
|
143
102
|
let lingeredFor: SolveDiagnostic[] | null = null;
|
|
103
|
+
let shownRemarks: ReadonlySet<string> = new Set();
|
|
104
|
+
let freshRemarks = $state.raw<SolveDiagnostic[]>([]);
|
|
105
|
+
const remarkKey = (d: SolveDiagnostic) => `${d.source ?? ''}\u0000${d.message}`;
|
|
144
106
|
$effect(() => {
|
|
145
107
|
if (phase === 'live') {
|
|
146
108
|
lingering = false;
|
|
147
109
|
return;
|
|
148
110
|
}
|
|
149
|
-
if (
|
|
111
|
+
if (lingeredFor === diagnostics) return;
|
|
150
112
|
lingeredFor = diagnostics;
|
|
151
|
-
|
|
113
|
+
const raised = authoredRemarks.map(remarkKey);
|
|
114
|
+
const stillShown = raised.filter((k) => shownRemarks.has(k));
|
|
115
|
+
const fresh = authoredRemarks.filter((d) => !shownRemarks.has(remarkKey(d)));
|
|
116
|
+
const showNow = phase === 'idle' && fresh.length > 0;
|
|
117
|
+
shownRemarks = new Set(showNow ? [...stillShown, ...fresh.map(remarkKey)] : stillShown);
|
|
118
|
+
if (!showNow) return;
|
|
119
|
+
freshRemarks = fresh;
|
|
152
120
|
lingering = true;
|
|
153
121
|
const timer = setTimeout(() => (lingering = false), REMARK_LINGER_MS);
|
|
154
122
|
return () => clearTimeout(timer);
|
|
@@ -167,6 +135,7 @@
|
|
|
167
135
|
$effect(() => {
|
|
168
136
|
if (phase === 'live') {
|
|
169
137
|
finishing = false;
|
|
138
|
+
if (freezesDuringSolve) return;
|
|
170
139
|
const timer = setTimeout(() => {
|
|
171
140
|
revealed = true;
|
|
172
141
|
revealedAt = performance.now();
|
|
@@ -193,7 +162,7 @@
|
|
|
193
162
|
// While solving, the live channel is all there is. Once the result lands it is authoritative
|
|
194
163
|
// — it carries remarks too — so the live list is dropped entirely and nothing is shown twice.
|
|
195
164
|
const rows = $derived<SolveDiagnostic[]>(
|
|
196
|
-
view === 'live' ? [...live.diagnostics] : view === 'idle' ?
|
|
165
|
+
view === 'live' ? [...live.diagnostics] : view === 'idle' ? freshRemarks : authoredGating
|
|
197
166
|
);
|
|
198
167
|
|
|
199
168
|
// A remark states something without asking anything, so it reads as a quiet note.
|
|
@@ -205,72 +174,77 @@
|
|
|
205
174
|
}))
|
|
206
175
|
);
|
|
207
176
|
|
|
208
|
-
// Steps a few milliseconds long would swap the headline faster than it can be read. Each one
|
|
209
|
-
// stays up for at least this long; steps that end sooner are skipped in the label but still
|
|
210
|
-
// count in the bar. The label and its step count move together so they never disagree.
|
|
211
|
-
const HEADLINE_MIN_MS = 200;
|
|
212
|
-
let headline = $state.raw<(typeof progress)[number] | undefined>(undefined);
|
|
213
|
-
let headlineAt = 0;
|
|
214
|
-
$effect(() => {
|
|
215
|
-
const next = progress[0];
|
|
216
|
-
const shown = untrack(() => headline);
|
|
217
|
-
if (next?.label === shown?.label && next?.done === shown?.done) {
|
|
218
|
-
headline = next;
|
|
219
|
-
return;
|
|
220
|
-
}
|
|
221
|
-
const show = () => {
|
|
222
|
-
headline = next;
|
|
223
|
-
headlineAt = performance.now();
|
|
224
|
-
};
|
|
225
|
-
const wait = HEADLINE_MIN_MS - (performance.now() - headlineAt);
|
|
226
|
-
if (!shown || wait <= 0) {
|
|
227
|
-
show();
|
|
228
|
-
return;
|
|
229
|
-
}
|
|
230
|
-
const timer = setTimeout(show, wait);
|
|
231
|
-
return () => clearTimeout(timer);
|
|
232
|
-
});
|
|
233
|
-
|
|
234
177
|
const visible = $derived(
|
|
235
178
|
view === 'review' || view === 'blocked'
|
|
236
179
|
? true
|
|
237
180
|
: view === 'live'
|
|
238
|
-
? revealed && (rows.length > 0 || progress.length > 0)
|
|
181
|
+
? revealed && (rows.length > 0 || (!progressShownByHost && progress.length > 0))
|
|
239
182
|
: rows.length > 0 && lingering
|
|
240
183
|
);
|
|
241
184
|
|
|
185
|
+
// What a screen reader hears of the passive views, through a region that outlives the panel: one
|
|
186
|
+
// created together with its text is not announced. The step name, not its counter, so a long
|
|
187
|
+
// solve announces each step rather than every tick. Review and blocked are alerts of their own.
|
|
188
|
+
const announcement = $derived(
|
|
189
|
+
!visible
|
|
190
|
+
? ''
|
|
191
|
+
: view === 'live'
|
|
192
|
+
? ((headline ?? progress[0])?.label ?? t.solveSolving)
|
|
193
|
+
: view === 'idle'
|
|
194
|
+
? rows.map((d) => d.message).join(' ')
|
|
195
|
+
: ''
|
|
196
|
+
);
|
|
197
|
+
|
|
242
198
|
function dismiss() {
|
|
243
199
|
dismissedFor = diagnostics;
|
|
244
200
|
}
|
|
245
201
|
|
|
246
202
|
// Escape resolves to the safe side — discard, keeping what is on screen — never to silently
|
|
247
|
-
// applying a result the user has not accepted.
|
|
203
|
+
// applying a result the user has not accepted. A frozen host gets no keydown until the solve
|
|
204
|
+
// ends; there the plugin aborts on the key state, which only counts while Rhino is in front, so
|
|
205
|
+
// a browser tab (local or Compute) has to abort from the page.
|
|
248
206
|
function handleKeydown(e: KeyboardEvent) {
|
|
249
207
|
if (e.key !== 'Escape') return;
|
|
250
|
-
if (phase === '
|
|
208
|
+
if (phase === 'live') {
|
|
209
|
+
if (!freezesDuringSolve) onabort();
|
|
210
|
+
} else if (phase === 'review') ondiscard();
|
|
251
211
|
else if (phase === 'blocked') dismiss();
|
|
252
212
|
}
|
|
253
213
|
</script>
|
|
254
214
|
|
|
255
215
|
<svelte:window onkeydown={handleKeydown} />
|
|
256
216
|
|
|
257
|
-
{
|
|
217
|
+
<div class="sr-only" role="status" aria-live="polite">{announcement}</div>
|
|
218
|
+
|
|
219
|
+
{#if freezesDuringSolve && view === 'live'}
|
|
220
|
+
<!-- Painted before the solve takes the thread; Abort could not be clicked until it ends. Inline,
|
|
221
|
+
the solving chip carries the hint instead: a line here would resize the footer mid-solve. -->
|
|
222
|
+
{#if placement === 'floating'}
|
|
223
|
+
<p
|
|
224
|
+
class="bottom-4 text-xs fixed left-1/2 z-50 -translate-x-1/2 text-muted-foreground"
|
|
225
|
+
data-testid="solve-esc-hint"
|
|
226
|
+
>
|
|
227
|
+
{t.solveMessagesEscHint}
|
|
228
|
+
</p>
|
|
229
|
+
{/if}
|
|
230
|
+
{:else if visible}
|
|
231
|
+
<!-- Inline, it is a row of the host's footer like the Calculate row under it, not a card: a
|
|
232
|
+
framed box inside an edge-to-edge column reads as a dialog glued into the page. -->
|
|
258
233
|
<div
|
|
259
|
-
class=
|
|
260
|
-
|
|
261
|
-
? 'border-destructive/50'
|
|
262
|
-
|
|
263
|
-
role={view === 'live' || view === 'idle' ? 'status' : 'alert'}
|
|
234
|
+
class={placement === 'inline'
|
|
235
|
+
? `px-2 py-2 border-t ${view === 'blocked' ? 'border-destructive/40' : 'border-border'}`
|
|
236
|
+
: `p-3 bottom-4 shadow-lg w-lg fixed left-1/2 z-50 max-w-screen-inset -translate-x-1/2 rounded-lg border bg-background ${view === 'blocked' ? 'border-destructive/50' : ''}`}
|
|
237
|
+
role={view === 'review' || view === 'blocked' ? 'alert' : undefined}
|
|
264
238
|
data-testid="solve-messages"
|
|
265
239
|
data-view={view}
|
|
266
240
|
>
|
|
267
|
-
{#if view === 'live'}
|
|
241
|
+
{#if view === 'live' && !progressShownByHost}
|
|
268
242
|
{@const head = headline ?? progress[0]}
|
|
269
243
|
<div>
|
|
270
244
|
<div>
|
|
271
245
|
<div class="gap-2 flex items-center">
|
|
272
246
|
<LoaderCircle class="h-4 w-4 animate-spin shrink-0 text-muted-foreground" />
|
|
273
|
-
<span class="min-w-0 text-sm flex-1 truncate">{head?.label ??
|
|
247
|
+
<span class="min-w-0 text-sm flex-1 truncate">{head?.label ?? t.solveSolving}</span>
|
|
274
248
|
{#if head?.done !== undefined && head?.total !== undefined}
|
|
275
249
|
<span class="text-xs shrink-0 text-muted-foreground tabular-nums">
|
|
276
250
|
{head.done} / {head.total}
|
|
@@ -282,8 +256,13 @@
|
|
|
282
256
|
class="-my-1 shrink-0"
|
|
283
257
|
disabled={finishing}
|
|
284
258
|
onclick={onabort}
|
|
259
|
+
aria-keyshortcuts="Escape"
|
|
260
|
+
title={t.solveMessagesEscHint}
|
|
285
261
|
>
|
|
286
|
-
{
|
|
262
|
+
{t.solveMessagesAbort}
|
|
263
|
+
<kbd class="px-1 rounded-sm border border-border font-sans text-2xs opacity-70">
|
|
264
|
+
Esc
|
|
265
|
+
</kbd>
|
|
287
266
|
</Button>
|
|
288
267
|
</div>
|
|
289
268
|
{#each progress as p, i (p.source ?? '')}
|
|
@@ -300,7 +279,7 @@
|
|
|
300
279
|
<div
|
|
301
280
|
class="h-1 overflow-hidden rounded-full bg-muted"
|
|
302
281
|
role="progressbar"
|
|
303
|
-
aria-label={p.label ?? p.source ??
|
|
282
|
+
aria-label={p.label ?? p.source ?? t.solveSolving}
|
|
304
283
|
aria-valuemin={0}
|
|
305
284
|
aria-valuemax={100}
|
|
306
285
|
aria-valuenow={p.fraction !== undefined ? Math.round(p.fraction * 100) : undefined}
|
|
@@ -322,36 +301,64 @@
|
|
|
322
301
|
{/each}
|
|
323
302
|
</div>
|
|
324
303
|
</div>
|
|
304
|
+
{:else if (view === 'review' || view === 'blocked') && placement === 'inline'}
|
|
305
|
+
<!-- Each message carries its own icon, so the label goes without one; the buttons share
|
|
306
|
+
its row rather than adding one under a single line of text. -->
|
|
307
|
+
<div class="mb-1.5 gap-2 flex items-center">
|
|
308
|
+
<span
|
|
309
|
+
class="min-w-0 text-xs font-medium flex-1 truncate {view === 'blocked'
|
|
310
|
+
? 'text-destructive'
|
|
311
|
+
: 'text-muted-foreground'}"
|
|
312
|
+
>
|
|
313
|
+
{view === 'blocked' ? t.solveBlockedTitle : t.solveMessagesTitle}
|
|
314
|
+
</span>
|
|
315
|
+
{#if view === 'blocked'}
|
|
316
|
+
<Button variant="ghost" size="xs" class="-my-1 shrink-0" onclick={dismiss}>
|
|
317
|
+
{t.solveMessagesDismiss}
|
|
318
|
+
</Button>
|
|
319
|
+
{:else}
|
|
320
|
+
<Button variant="ghost" size="xs" class="-my-1 shrink-0" onclick={ondiscard}>
|
|
321
|
+
{t.solveMessagesDiscard}
|
|
322
|
+
</Button>
|
|
323
|
+
<Button size="xs" class="-my-1 shrink-0" onclick={onconfirm}>
|
|
324
|
+
{t.solveMessagesConfirm}
|
|
325
|
+
</Button>
|
|
326
|
+
{/if}
|
|
327
|
+
</div>
|
|
325
328
|
{:else if view === 'review' || view === 'blocked'}
|
|
326
329
|
<div class="mb-2">
|
|
327
330
|
<div class="gap-2 text-sm font-medium flex items-center">
|
|
328
331
|
{#if view === 'blocked'}
|
|
329
332
|
<SeverityIcon severity="error" />
|
|
330
|
-
{
|
|
333
|
+
{t.solveBlockedTitle}
|
|
331
334
|
{:else}
|
|
332
335
|
<SeverityIcon severity="warning" />
|
|
333
|
-
{
|
|
336
|
+
{t.solveMessagesTitle}
|
|
334
337
|
{/if}
|
|
335
338
|
</div>
|
|
336
339
|
<p class="text-xs text-muted-foreground">
|
|
337
|
-
{view === 'blocked' ?
|
|
340
|
+
{view === 'blocked' ? t.solveBlocked : t.solveMessagesDescription}
|
|
338
341
|
</p>
|
|
339
342
|
</div>
|
|
340
343
|
{/if}
|
|
341
344
|
|
|
342
345
|
{#if rows.length > 0}
|
|
343
|
-
<div
|
|
346
|
+
<div
|
|
347
|
+
class="max-h-40 overflow-y-auto {view === 'live' && !progressShownByHost
|
|
348
|
+
? 'mt-3 pt-3 border-t'
|
|
349
|
+
: ''}"
|
|
350
|
+
>
|
|
344
351
|
<IssueList {issues} variant="plain" />
|
|
345
352
|
</div>
|
|
346
353
|
{/if}
|
|
347
354
|
|
|
348
|
-
{#if view === 'review' || view === 'blocked'}
|
|
355
|
+
{#if (view === 'review' || view === 'blocked') && placement === 'floating'}
|
|
349
356
|
<div class="mt-3 gap-2 flex justify-end">
|
|
350
357
|
{#if view === 'blocked'}
|
|
351
|
-
<Button variant="outline" size="sm" onclick={dismiss}>{
|
|
358
|
+
<Button variant="outline" size="sm" onclick={dismiss}>{t.solveMessagesDismiss}</Button>
|
|
352
359
|
{:else}
|
|
353
|
-
<Button variant="outline" size="sm" onclick={ondiscard}>{
|
|
354
|
-
<Button size="sm" onclick={onconfirm}>{
|
|
360
|
+
<Button variant="outline" size="sm" onclick={ondiscard}>{t.solveMessagesDiscard}</Button>
|
|
361
|
+
<Button size="sm" onclick={onconfirm}>{t.solveMessagesConfirm}</Button>
|
|
355
362
|
{/if}
|
|
356
363
|
</div>
|
|
357
364
|
{/if}
|
|
@@ -1,16 +1,5 @@
|
|
|
1
1
|
import type { SolveDiagnostic } from '@selvajs/solve/shared';
|
|
2
2
|
import type { LiveSolveState, SolvePhase } from '@selvajs/solve/client';
|
|
3
|
-
interface Labels {
|
|
4
|
-
solving: string;
|
|
5
|
-
blockedTitle: string;
|
|
6
|
-
messagesTitle: string;
|
|
7
|
-
blockedDescription: string;
|
|
8
|
-
messagesDescription: string;
|
|
9
|
-
confirm: string;
|
|
10
|
-
discard: string;
|
|
11
|
-
abort: string;
|
|
12
|
-
dismiss: string;
|
|
13
|
-
}
|
|
14
3
|
interface Props {
|
|
15
4
|
/** What the running (or most recent) solve has said over the live channel. */
|
|
16
5
|
live: LiveSolveState;
|
|
@@ -21,7 +10,18 @@ interface Props {
|
|
|
21
10
|
onabort: () => void;
|
|
22
11
|
onconfirm: () => void;
|
|
23
12
|
ondiscard: () => void;
|
|
24
|
-
|
|
13
|
+
/**
|
|
14
|
+
* See `createSolvingIndicator`. The live panel would only paint once the solve is over, so
|
|
15
|
+
* an Esc hint stands in for it; the result's messages still show.
|
|
16
|
+
*/
|
|
17
|
+
freezesDuringSolve?: boolean;
|
|
18
|
+
/** `floating` overlays the bottom centre; `inline` sits in the flow below the host's content. */
|
|
19
|
+
placement?: 'floating' | 'inline';
|
|
20
|
+
/**
|
|
21
|
+
* The host shows progress and Abort itself (`AppLayout`'s solve status), so the live view
|
|
22
|
+
* keeps only the messages that arrive mid-solve.
|
|
23
|
+
*/
|
|
24
|
+
progressShownByHost?: boolean;
|
|
25
25
|
}
|
|
26
26
|
declare const SolveMessages: import("svelte").Component<Props, {}, "">;
|
|
27
27
|
type SolveMessages = ReturnType<typeof SolveMessages>;
|
|
@@ -74,14 +74,16 @@
|
|
|
74
74
|
|
|
75
75
|
const rootClass = $derived(
|
|
76
76
|
_mode === 'fixed'
|
|
77
|
-
?
|
|
78
|
-
|
|
77
|
+
? // dvh, not vh: iOS sizes 100vh to the viewport without its toolbar, which hides the
|
|
78
|
+
// footer and the phone drawer's handle behind the toolbar.
|
|
79
|
+
`flex flex-col h-dvh overflow-hidden bg-background ${className}`
|
|
80
|
+
: `flex flex-col min-h-dvh bg-background ${className}`
|
|
79
81
|
);
|
|
80
82
|
|
|
81
83
|
const bodyShellClass = $derived(
|
|
82
84
|
_mode === 'fixed'
|
|
83
|
-
? `flex flex-1 min-h-0 ${sidenav ? 'flex-row' : 'flex-col'} ${bodyClass}`.trim()
|
|
84
|
-
: `flex-1 ${sidenav ? 'flex flex-row' : ''} ${bodyClass}`.trim()
|
|
85
|
+
? `flex flex-1 min-h-0 ${sidenav ? 'flex-col sm:flex-row' : 'flex-col'} ${bodyClass}`.trim()
|
|
86
|
+
: `flex-1 ${sidenav ? 'flex flex-col sm:flex-row' : ''} ${bodyClass}`.trim()
|
|
85
87
|
);
|
|
86
88
|
|
|
87
89
|
const bodyShellStyle = '';
|
|
@@ -92,13 +94,15 @@
|
|
|
92
94
|
const sidenavWrapClass = $derived(
|
|
93
95
|
_mode === 'fixed'
|
|
94
96
|
? 'flex shrink-0'
|
|
95
|
-
: 'flex shrink-0 self-start sticky top-(--header-h) max-h-
|
|
97
|
+
: 'flex shrink-0 sm:self-start sm:sticky sm:top-(--header-h) sm:max-h-(--below-header-h)'
|
|
96
98
|
);
|
|
97
99
|
|
|
98
100
|
// The sticky wrapper is only as tall as its content, so in scroll mode the divider comes
|
|
99
101
|
// from the main column's left edge — that one spans the full body height.
|
|
100
102
|
const mainClass = $derived(
|
|
101
|
-
_mode === 'fixed'
|
|
103
|
+
_mode === 'fixed'
|
|
104
|
+
? 'min-h-0 min-w-0 flex-1 overflow-y-auto'
|
|
105
|
+
: 'min-w-0 flex-1 overflow-y-auto border-border sm:border-l'
|
|
102
106
|
);
|
|
103
107
|
</script>
|
|
104
108
|
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
|
-
import type { FooterItem } from '../../contexts/footerContext.svelte';
|
|
2
|
+
import type { FooterItem } from '../../contexts/footerContext.svelte.js';
|
|
3
3
|
|
|
4
4
|
let { item }: { item: FooterItem } = $props();
|
|
5
5
|
|
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
{#if item.onClick}
|
|
10
10
|
<button
|
|
11
11
|
onclick={item.onClick}
|
|
12
|
-
class="gap-1.5 px-2 py-0.5
|
|
12
|
+
class="gap-1.5 px-2 py-0.5 flex cursor-pointer items-center rounded-sm transition-colors hover:bg-hover"
|
|
13
13
|
>
|
|
14
14
|
<item.component {...itemProps} />
|
|
15
15
|
</button>
|
|
@@ -7,6 +7,7 @@
|
|
|
7
7
|
let { class: className = '', children }: PageContentProps = $props();
|
|
8
8
|
</script>
|
|
9
9
|
|
|
10
|
-
|
|
10
|
+
<!-- One content width for every page, so moving between pages doesn't change the frame. -->
|
|
11
|
+
<div class={`max-w-6xl min-w-0 mx-auto w-full px-(--page-px) py-(--page-py) ${className}`}>
|
|
11
12
|
{@render children?.()}
|
|
12
|
-
</
|
|
13
|
+
</div>
|
|
@@ -2,9 +2,11 @@
|
|
|
2
2
|
import type { Snippet } from 'svelte';
|
|
3
3
|
import { CircleAlert, TriangleAlert, Info } from '@lucide/svelte';
|
|
4
4
|
import type { SolveDiagnostic } from '@selvajs/solve/shared';
|
|
5
|
-
import { useFooter } from '../../contexts/footerContext.svelte';
|
|
5
|
+
import { useFooter } from '../../contexts/footerContext.svelte.js';
|
|
6
6
|
import ComputeMessagesDialog from '../compute/ComputeMessagesDialog.svelte';
|
|
7
7
|
import FooterItemRenderer from './FooterItemRenderer.svelte';
|
|
8
|
+
import { getLocaleContext } from '../../i18n/localeContext.svelte.js';
|
|
9
|
+
import { formatCount, formatMessage } from '../../i18n/messages.js';
|
|
8
10
|
|
|
9
11
|
interface Props {
|
|
10
12
|
errors?: string[];
|
|
@@ -26,6 +28,9 @@
|
|
|
26
28
|
children
|
|
27
29
|
}: Props = $props();
|
|
28
30
|
|
|
31
|
+
const locale = getLocaleContext();
|
|
32
|
+
const t = $derived(locale.messages);
|
|
33
|
+
|
|
29
34
|
let footerStore = (() => {
|
|
30
35
|
try {
|
|
31
36
|
return useFooter();
|
|
@@ -66,16 +71,15 @@
|
|
|
66
71
|
const hasMessages = $derived(totalCount > 0);
|
|
67
72
|
|
|
68
73
|
const copyrightLine = $derived(
|
|
69
|
-
footerText
|
|
70
|
-
? footerText.replace('{name}', copyrightName).replace('{year}', String(_currentYear))
|
|
71
|
-
: `by ${copyrightName} © ${_currentYear}`
|
|
74
|
+
formatMessage(footerText ?? t.copyright, { name: copyrightName, year: _currentYear })
|
|
72
75
|
);
|
|
73
76
|
</script>
|
|
74
77
|
|
|
78
|
+
<!-- One line at any width: the message counts keep their size and the copyright truncates. -->
|
|
75
79
|
<footer
|
|
76
|
-
class="px-4 gap-4 text-xs h-7 flex shrink-0 items-center justify-between border-t border-border bg-background text-muted-foreground select-none"
|
|
80
|
+
class="px-4 gap-4 text-xs h-7 flex shrink-0 items-center justify-between border-t border-border bg-background whitespace-nowrap text-muted-foreground select-none"
|
|
77
81
|
>
|
|
78
|
-
<div class="gap-4 flex items-center">
|
|
82
|
+
<div class="gap-4 flex shrink-0 items-center">
|
|
79
83
|
{#each leftItems as item (item.id)}
|
|
80
84
|
<FooterItemRenderer {item} />
|
|
81
85
|
{/each}
|
|
@@ -84,17 +88,19 @@
|
|
|
84
88
|
<ComputeMessagesDialog {errors} {warnings} {diagnostics}>
|
|
85
89
|
{#snippet trigger()}
|
|
86
90
|
<div
|
|
87
|
-
class="gap-1.5 px-2 py-1
|
|
91
|
+
class="gap-1.5 px-2 py-1 flex cursor-pointer items-center rounded-sm transition-colors hover:bg-hover {errorCount >
|
|
88
92
|
0
|
|
89
93
|
? 'text-destructive hover:bg-destructive/10'
|
|
90
94
|
: warningCount > 0
|
|
91
95
|
? 'text-warning hover:bg-warning/10'
|
|
92
|
-
: 'hover:bg-
|
|
93
|
-
title={
|
|
96
|
+
: 'hover:bg-hover'}"
|
|
97
|
+
title={formatCount(totalCount, t.lastSolveMessagesOne, t.lastSolveMessagesOther)}
|
|
94
98
|
>
|
|
95
99
|
{#if errorCount > 0}
|
|
96
100
|
<CircleAlert class="h-3.5 w-3.5" />
|
|
97
|
-
<span class="font-medium"
|
|
101
|
+
<span class="font-medium"
|
|
102
|
+
>{formatCount(errorCount, t.errorCountOne, t.errorCountOther)}</span
|
|
103
|
+
>
|
|
98
104
|
{/if}
|
|
99
105
|
|
|
100
106
|
{#if warningCount > 0}
|
|
@@ -102,12 +108,16 @@
|
|
|
102
108
|
<span class="text-border">•</span>
|
|
103
109
|
{/if}
|
|
104
110
|
<TriangleAlert class="h-3.5 w-3.5" />
|
|
105
|
-
<span class="font-medium"
|
|
111
|
+
<span class="font-medium"
|
|
112
|
+
>{formatCount(warningCount, t.warningCountOne, t.warningCountOther)}</span
|
|
113
|
+
>
|
|
106
114
|
{/if}
|
|
107
115
|
|
|
108
116
|
{#if errorCount === 0 && warningCount === 0}
|
|
109
117
|
<Info class="h-3.5 w-3.5" />
|
|
110
|
-
<span class="font-medium"
|
|
118
|
+
<span class="font-medium"
|
|
119
|
+
>{formatCount(remarkCount, t.noteCountOne, t.noteCountOther)}</span
|
|
120
|
+
>
|
|
111
121
|
{/if}
|
|
112
122
|
</div>
|
|
113
123
|
{/snippet}
|
|
@@ -121,11 +131,13 @@
|
|
|
121
131
|
{/if}
|
|
122
132
|
</div>
|
|
123
133
|
|
|
124
|
-
<div class="gap-4 ml-auto flex items-center">
|
|
134
|
+
<div class="gap-4 min-w-0 ml-auto flex items-center">
|
|
125
135
|
{#each rightItems as item (item.id)}
|
|
126
136
|
<FooterItemRenderer {item} />
|
|
127
137
|
{/each}
|
|
128
138
|
|
|
129
|
-
|
|
139
|
+
{#if copyrightLine}
|
|
140
|
+
<p class="truncate">{copyrightLine}</p>
|
|
141
|
+
{/if}
|
|
130
142
|
</div>
|
|
131
143
|
</footer>
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
2
|
import type { Snippet } from 'svelte';
|
|
3
|
-
import { ModeToggle } from '../primitives/mode-toggle';
|
|
3
|
+
import { ModeToggle } from '../primitives/mode-toggle/index.js';
|
|
4
4
|
|
|
5
5
|
interface PageHeaderProps {
|
|
6
6
|
homeUrl?: string;
|
|
@@ -31,27 +31,31 @@
|
|
|
31
31
|
<header
|
|
32
32
|
class={`top-0 backdrop-blur-sm sticky z-40 border-b border-border bg-background/90 ${className}`}
|
|
33
33
|
>
|
|
34
|
-
<div class="gap-5 flex h-(--header-h) items-center px-(--page-px)">
|
|
34
|
+
<div class="gap-2 sm:gap-5 flex h-(--header-h) items-center px-(--page-px)">
|
|
35
35
|
<!-- Logo -->
|
|
36
|
-
<a href={homeUrl} class="gap-2 flex shrink-0 items-center">
|
|
37
|
-
<img src={logo} alt="" aria-hidden="true" class="h-
|
|
38
|
-
|
|
36
|
+
<a href={homeUrl} class="gap-2 flex shrink-0 items-center" aria-label={brandName}>
|
|
37
|
+
<img src={logo} alt="" aria-hidden="true" class="h-7 w-7" />
|
|
38
|
+
<!-- On a phone the page title needs the room more than the brand does. -->
|
|
39
|
+
<span
|
|
40
|
+
class="font-semibold text-sm tracking-tight {title !== undefined ? 'sm:inline hidden' : ''}"
|
|
41
|
+
>{brandName}</span
|
|
42
|
+
>
|
|
39
43
|
</a>
|
|
40
44
|
|
|
41
45
|
{#if title !== undefined}
|
|
42
|
-
<span class="text-sm text-border">/</span>
|
|
43
|
-
<span class="text-sm font-medium text-muted-foreground">{title ?? ''}</span>
|
|
46
|
+
<span class="text-sm shrink-0 text-border">/</span>
|
|
47
|
+
<span class="text-sm font-medium min-w-0 truncate text-muted-foreground">{title ?? ''}</span>
|
|
44
48
|
{/if}
|
|
45
49
|
|
|
46
50
|
<!-- Primary nav next to logo -->
|
|
47
51
|
{#if navItems}
|
|
48
|
-
<nav class="ml-5 gap-1 flex">
|
|
52
|
+
<nav class="sm:ml-5 gap-1 flex shrink-0">
|
|
49
53
|
{@render navItems()}
|
|
50
54
|
</nav>
|
|
51
55
|
{/if}
|
|
52
56
|
|
|
53
57
|
<!-- Right cluster: identity + utilities, anchored flush-right -->
|
|
54
|
-
<div class="gap-2 ml-auto flex items-center">
|
|
58
|
+
<div class="gap-2 ml-auto flex shrink-0 items-center">
|
|
55
59
|
{#if rightContent}
|
|
56
60
|
{@render rightContent()}
|
|
57
61
|
{/if}
|
|
@@ -62,7 +66,7 @@
|
|
|
62
66
|
</div>
|
|
63
67
|
|
|
64
68
|
{#if subnav}
|
|
65
|
-
<div class="h-10 flex items-center border-t border-border
|
|
69
|
+
<div class="h-10 flex items-center border-t border-border px-(--page-px)">
|
|
66
70
|
{@render subnav()}
|
|
67
71
|
</div>
|
|
68
72
|
{/if}
|