@selvajs/ui 6.5.1-beta.0 → 6.6.0-beta.11
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/components/ConfirmDialog.svelte +2 -10
- package/dist/components/ErrorScreen.svelte +21 -27
- package/dist/components/compute/AppLayout.svelte +286 -116
- package/dist/components/compute/AppLayout.svelte.d.ts +22 -0
- package/dist/components/compute/ComputeApp.svelte +45 -24
- package/dist/components/compute/ComputeApp.svelte.d.ts +19 -2
- package/dist/components/compute/ComputeMessagesDialog.svelte +47 -83
- package/dist/components/compute/ParameterPresetManager.svelte +37 -130
- package/dist/components/compute/ParameterPresetManager.svelte.d.ts +4 -5
- package/dist/components/compute/SolveMessages.svelte +131 -77
- package/dist/components/compute/SolveMessages.svelte.d.ts +7 -12
- package/dist/components/layout/AppShell.svelte +10 -6
- package/dist/components/layout/PageFooter.svelte +23 -11
- package/dist/components/layout/PageHeader.svelte +11 -7
- package/dist/components/layout/Pagination.svelte +2 -4
- package/dist/components/layout/SectionHeader.svelte +4 -2
- package/dist/components/layout/SideNav.svelte +56 -7
- package/dist/components/preview/ChartOutput.svelte +35 -25
- package/dist/components/preview/Group.svelte +92 -103
- package/dist/components/preview/Group.svelte.d.ts +1 -1
- package/dist/components/preview/HelpButton.svelte +36 -0
- package/dist/components/preview/HelpButton.svelte.d.ts +8 -0
- package/dist/components/preview/ImageOutput.svelte +430 -71
- package/dist/components/preview/InputControl.svelte +163 -90
- package/dist/components/preview/InputControl.svelte.d.ts +5 -1
- package/dist/components/preview/OutputDisplay.svelte +28 -33
- package/dist/components/preview/TabBar.svelte +106 -22
- package/dist/components/preview/TabBar.svelte.d.ts +1 -0
- package/dist/components/preview/TabContent.svelte +63 -57
- package/dist/components/preview/TabContent.svelte.d.ts +5 -1
- package/dist/components/preview/TabLayout.svelte +27 -5
- package/dist/components/preview/TabLayout.svelte.d.ts +5 -0
- package/dist/components/preview/inputs/CheckboxInput.svelte +7 -7
- package/dist/components/preview/inputs/CheckboxInput.svelte.d.ts +3 -0
- package/dist/components/preview/inputs/ChecklistInput.svelte +7 -2
- package/dist/components/preview/inputs/ChecklistInput.svelte.d.ts +2 -1
- package/dist/components/preview/inputs/ColorInput.svelte +4 -2
- package/dist/components/preview/inputs/ColorInput.svelte.d.ts +1 -0
- package/dist/components/preview/inputs/DropdownInput.svelte +19 -4
- package/dist/components/preview/inputs/DropdownInput.svelte.d.ts +2 -1
- package/dist/components/preview/inputs/FileInput.svelte +112 -108
- 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 +123 -61
- 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 +44 -0
- package/dist/components/preview/inputs/SegmentedInput.svelte.d.ts +12 -0
- package/dist/components/preview/inputs/TextInput.svelte +8 -4
- package/dist/components/preview/inputs/TileInput.svelte +80 -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 +11 -18
- package/dist/components/primitives/DataTable.svelte +38 -5
- package/dist/components/primitives/DataTable.svelte.d.ts +2 -0
- package/dist/components/primitives/FilterableDropdown.svelte +42 -129
- package/dist/components/primitives/FilterableDropdown.svelte.d.ts +1 -1
- package/dist/components/primitives/IssueList.svelte +56 -0
- package/dist/components/primitives/IssueList.svelte.d.ts +20 -0
- package/dist/components/primitives/SeverityIcon.svelte +15 -0
- package/dist/components/primitives/SeverityIcon.svelte.d.ts +8 -0
- package/dist/components/primitives/SolvingIndicator.svelte +43 -42
- package/dist/components/primitives/SolvingIndicator.svelte.d.ts +6 -0
- package/dist/components/primitives/StateDisplay.svelte +19 -79
- package/dist/components/primitives/ViewToggle.svelte +18 -33
- package/dist/components/primitives/alert-dialog/alert-dialog-action.svelte +9 -3
- package/dist/components/primitives/alert-dialog/alert-dialog-action.svelte.d.ts +6 -1
- package/dist/components/primitives/alert-dialog/alert-dialog-content.svelte +1 -1
- package/dist/components/primitives/alert-dialog/alert-dialog-overlay.svelte +1 -1
- package/dist/components/primitives/badge/badge.svelte +2 -2
- package/dist/components/primitives/badge/badge.svelte.d.ts +4 -4
- package/dist/components/primitives/button/button.svelte +6 -2
- package/dist/components/primitives/button/button.svelte.d.ts +10 -4
- package/dist/components/primitives/card/card-header.svelte +1 -1
- package/dist/components/primitives/card/card.svelte +21 -5
- package/dist/components/primitives/card/card.svelte.d.ts +25 -1
- package/dist/components/primitives/card/index.d.ts +1 -2
- package/dist/components/primitives/card/index.js +2 -3
- package/dist/components/primitives/checkbox/checkbox.svelte +1 -1
- package/dist/components/primitives/command/command-dialog.svelte +42 -0
- package/dist/components/primitives/command/command-dialog.svelte.d.ts +14 -0
- package/dist/components/primitives/command/command-empty.svelte +17 -0
- package/dist/components/primitives/command/command-empty.svelte.d.ts +4 -0
- package/dist/components/primitives/command/command-group.svelte +33 -0
- package/dist/components/primitives/command/command-group.svelte.d.ts +7 -0
- package/dist/components/primitives/command/command-input.svelte +36 -0
- package/dist/components/primitives/command/command-input.svelte.d.ts +4 -0
- package/dist/components/primitives/command/command-item.svelte +28 -0
- package/dist/components/primitives/command/command-item.svelte.d.ts +4 -0
- package/dist/components/primitives/command/command-link-item.svelte +21 -0
- package/dist/components/primitives/command/command-link-item.svelte.d.ts +4 -0
- package/dist/components/primitives/command/command-list.svelte +20 -0
- package/dist/components/primitives/command/command-list.svelte.d.ts +4 -0
- package/dist/components/primitives/command/command-loading.svelte +7 -0
- package/dist/components/primitives/command/command-loading.svelte.d.ts +4 -0
- package/dist/components/primitives/command/command-separator.svelte +17 -0
- package/dist/components/primitives/command/command-separator.svelte.d.ts +4 -0
- package/dist/components/primitives/command/command-shortcut.svelte +23 -0
- package/dist/components/primitives/command/command-shortcut.svelte.d.ts +5 -0
- package/dist/components/primitives/command/command.svelte +28 -0
- package/dist/components/primitives/command/command.svelte.d.ts +8 -0
- package/dist/components/primitives/command/index.d.ts +12 -0
- package/dist/components/primitives/command/index.js +14 -0
- package/dist/components/primitives/context-menu/context-menu-content.svelte +1 -1
- package/dist/components/primitives/context-menu/context-menu-sub-content.svelte +1 -1
- package/dist/components/primitives/dialog/dialog-content.svelte +11 -3
- package/dist/components/primitives/dialog/dialog-content.svelte.d.ts +2 -0
- package/dist/components/primitives/dialog/dialog-overlay.svelte +1 -1
- package/dist/components/primitives/dialog/dialog-title.svelte +6 -2
- package/dist/components/primitives/dialog/dialog-title.svelte.d.ts +5 -1
- package/dist/components/primitives/drawer/Drawer.svelte +2 -2
- package/dist/components/primitives/dropdown-menu/dropdown-menu-checkbox-group.svelte +16 -0
- package/dist/components/primitives/dropdown-menu/dropdown-menu-checkbox-group.svelte.d.ts +4 -0
- package/dist/components/primitives/dropdown-menu/dropdown-menu-checkbox-item.svelte +46 -0
- package/dist/components/primitives/dropdown-menu/dropdown-menu-checkbox-item.svelte.d.ts +9 -0
- package/dist/components/primitives/dropdown-menu/dropdown-menu-content.svelte +31 -0
- package/dist/components/primitives/dropdown-menu/dropdown-menu-content.svelte.d.ts +10 -0
- package/dist/components/primitives/dropdown-menu/dropdown-menu-group-heading.svelte +22 -0
- package/dist/components/primitives/dropdown-menu/dropdown-menu-group-heading.svelte.d.ts +8 -0
- package/dist/components/primitives/dropdown-menu/dropdown-menu-group.svelte +7 -0
- package/dist/components/primitives/dropdown-menu/dropdown-menu-group.svelte.d.ts +4 -0
- package/dist/components/primitives/dropdown-menu/dropdown-menu-item.svelte +27 -0
- package/dist/components/primitives/dropdown-menu/dropdown-menu-item.svelte.d.ts +8 -0
- package/dist/components/primitives/dropdown-menu/dropdown-menu-label.svelte +24 -0
- package/dist/components/primitives/dropdown-menu/dropdown-menu-label.svelte.d.ts +8 -0
- package/dist/components/primitives/dropdown-menu/dropdown-menu-portal.svelte +7 -0
- package/dist/components/primitives/dropdown-menu/dropdown-menu-portal.svelte.d.ts +3 -0
- package/dist/components/primitives/dropdown-menu/dropdown-menu-radio-group.svelte +16 -0
- package/dist/components/primitives/dropdown-menu/dropdown-menu-radio-group.svelte.d.ts +4 -0
- package/dist/components/primitives/dropdown-menu/dropdown-menu-radio-item.svelte +36 -0
- package/dist/components/primitives/dropdown-menu/dropdown-menu-radio-item.svelte.d.ts +4 -0
- package/dist/components/primitives/dropdown-menu/dropdown-menu-separator.svelte +17 -0
- package/dist/components/primitives/dropdown-menu/dropdown-menu-separator.svelte.d.ts +4 -0
- package/dist/components/primitives/dropdown-menu/dropdown-menu-shortcut.svelte +23 -0
- package/dist/components/primitives/dropdown-menu/dropdown-menu-shortcut.svelte.d.ts +5 -0
- package/dist/components/primitives/dropdown-menu/dropdown-menu-sub-content.svelte +31 -0
- package/dist/components/primitives/dropdown-menu/dropdown-menu-sub-content.svelte.d.ts +10 -0
- package/dist/components/primitives/dropdown-menu/dropdown-menu-sub-trigger.svelte +29 -0
- package/dist/components/primitives/dropdown-menu/dropdown-menu-sub-trigger.svelte.d.ts +7 -0
- package/dist/components/primitives/dropdown-menu/dropdown-menu-sub.svelte +7 -0
- package/dist/components/primitives/dropdown-menu/dropdown-menu-sub.svelte.d.ts +3 -0
- package/dist/components/primitives/dropdown-menu/dropdown-menu-trigger.svelte +7 -0
- package/dist/components/primitives/dropdown-menu/dropdown-menu-trigger.svelte.d.ts +4 -0
- package/dist/components/primitives/dropdown-menu/dropdown-menu.svelte +7 -0
- package/dist/components/primitives/dropdown-menu/dropdown-menu.svelte.d.ts +3 -0
- package/dist/components/primitives/dropdown-menu/index.d.ts +18 -0
- package/dist/components/primitives/dropdown-menu/index.js +18 -0
- package/dist/components/primitives/{alert/alert-description.svelte → empty/empty-content.svelte} +3 -3
- package/dist/components/primitives/empty/empty-content.svelte.d.ts +5 -0
- package/dist/components/primitives/empty/empty-description.svelte +23 -0
- package/dist/components/primitives/{alert/alert-description.svelte.d.ts → empty/empty-description.svelte.d.ts} +4 -4
- package/dist/components/primitives/{alert/alert-title.svelte → empty/empty-header.svelte} +3 -3
- package/dist/components/primitives/empty/empty-header.svelte.d.ts +5 -0
- package/dist/components/primitives/empty/empty-media.svelte +41 -0
- package/dist/components/primitives/empty/empty-media.svelte.d.ts +26 -0
- package/dist/components/primitives/{card/card-action.svelte → empty/empty-title.svelte} +2 -2
- package/dist/components/primitives/{card/card-action.svelte.d.ts → empty/empty-title.svelte.d.ts} +3 -3
- package/dist/components/primitives/empty/empty.svelte +23 -0
- package/dist/components/primitives/empty/empty.svelte.d.ts +5 -0
- package/dist/components/primitives/empty/index.d.ts +7 -0
- package/dist/components/primitives/empty/index.js +9 -0
- package/dist/components/primitives/index.d.ts +10 -1
- package/dist/components/primitives/index.js +10 -1
- package/dist/components/primitives/input/input.svelte +4 -4
- package/dist/components/primitives/input-group/index.d.ts +7 -0
- package/dist/components/primitives/input-group/index.js +9 -0
- package/dist/components/primitives/input-group/input-group-addon.svelte +53 -0
- package/dist/components/primitives/input-group/input-group-addon.svelte.d.ts +32 -0
- package/dist/components/primitives/input-group/input-group-button.svelte +49 -0
- package/dist/components/primitives/input-group/input-group-button.svelte.d.ts +32 -0
- package/dist/components/primitives/input-group/input-group-input.svelte +25 -0
- package/dist/components/primitives/input-group/input-group-input.svelte.d.ts +11 -0
- package/dist/components/primitives/input-group/input-group-text.svelte +22 -0
- package/dist/components/primitives/input-group/input-group-text.svelte.d.ts +5 -0
- package/dist/components/primitives/input-group/input-group-textarea.svelte +23 -0
- package/dist/components/primitives/input-group/input-group-textarea.svelte.d.ts +3 -0
- package/dist/components/primitives/input-group/input-group.svelte +24 -0
- package/dist/components/primitives/{alert/alert-title.svelte.d.ts → input-group/input-group.svelte.d.ts} +4 -4
- package/dist/components/primitives/mode-toggle/mode-toggle.svelte +6 -7
- package/dist/components/primitives/popover/index.d.ts +9 -0
- package/dist/components/primitives/popover/index.js +11 -0
- package/dist/components/primitives/popover/popover-close.svelte +7 -0
- package/dist/components/primitives/popover/popover-close.svelte.d.ts +4 -0
- package/dist/components/primitives/popover/popover-content.svelte +31 -0
- package/dist/components/primitives/popover/popover-content.svelte.d.ts +10 -0
- package/dist/components/primitives/popover/popover-description.svelte +20 -0
- package/dist/components/primitives/popover/popover-description.svelte.d.ts +5 -0
- package/dist/components/primitives/popover/popover-header.svelte +20 -0
- package/dist/components/primitives/popover/popover-header.svelte.d.ts +5 -0
- package/dist/components/primitives/popover/popover-portal.svelte +7 -0
- package/dist/components/primitives/popover/popover-portal.svelte.d.ts +3 -0
- package/dist/components/primitives/popover/popover-title.svelte +15 -0
- package/dist/components/primitives/popover/popover-title.svelte.d.ts +5 -0
- package/dist/components/primitives/popover/popover-trigger.svelte +17 -0
- package/dist/components/primitives/popover/popover-trigger.svelte.d.ts +4 -0
- package/dist/components/primitives/popover/popover.svelte +7 -0
- package/dist/components/primitives/popover/popover.svelte.d.ts +3 -0
- package/dist/components/primitives/resizable/resizable-handle.svelte +6 -2
- package/dist/components/primitives/resizable/resizable-handle.svelte.d.ts +2 -0
- package/dist/components/primitives/resizable/resizable-pane-group.svelte +1 -4
- package/dist/components/primitives/scroll-area/scroll-area.svelte +1 -1
- package/dist/components/primitives/search/search.svelte +3 -3
- package/dist/components/primitives/select/select-content.svelte +1 -1
- package/dist/components/primitives/select/select-trigger.svelte +1 -1
- package/dist/components/primitives/severity.d.ts +7 -0
- package/dist/components/primitives/severity.js +19 -0
- package/dist/components/primitives/slider/slider.svelte +8 -3
- package/dist/components/primitives/slider/slider.svelte.d.ts +5 -1
- package/dist/components/primitives/sonner/sonner.svelte +1 -1
- package/dist/components/primitives/spinner/index.d.ts +1 -0
- package/dist/components/primitives/spinner/index.js +1 -0
- package/dist/components/primitives/spinner/spinner.svelte +29 -0
- package/dist/components/primitives/spinner/spinner.svelte.d.ts +4 -0
- package/dist/components/primitives/switch/switch.svelte +2 -2
- package/dist/components/primitives/tabs/tabs-list.svelte +27 -5
- package/dist/components/primitives/tabs/tabs-list.svelte.d.ts +22 -1
- package/dist/components/primitives/tabs/tabs-trigger.svelte +23 -5
- package/dist/components/primitives/tabs/tabs-trigger.svelte.d.ts +22 -1
- package/dist/components/primitives/tabs/tabs.svelte +6 -2
- package/dist/components/primitives/tabs/tabs.svelte.d.ts +5 -1
- package/dist/components/primitives/textarea/textarea.svelte +1 -1
- package/dist/components/primitives/theme-switcher/ThemeSwitcher.svelte +1 -1
- package/dist/components/primitives/toggle/index.d.ts +3 -0
- package/dist/components/primitives/toggle/index.js +5 -0
- package/dist/components/primitives/toggle/toggle.svelte +54 -0
- package/dist/components/primitives/toggle/toggle.svelte.d.ts +46 -0
- package/dist/components/primitives/toggle-group/index.d.ts +3 -0
- package/dist/components/primitives/toggle-group/index.js +5 -0
- package/dist/components/primitives/toggle-group/toggle-group-item.svelte +35 -0
- package/dist/components/primitives/toggle-group/toggle-group-item.svelte.d.ts +6 -0
- package/dist/components/primitives/toggle-group/toggle-group.svelte +75 -0
- package/dist/components/primitives/toggle-group/toggle-group.svelte.d.ts +17 -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 +14 -5
- package/dist/components/viewer/Viewer.svelte +243 -221
- package/dist/components/viewer/Viewer.svelte.d.ts +3 -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 +7 -9
- package/dist/contexts/hostContext.svelte.d.ts +39 -0
- package/dist/contexts/hostContext.svelte.js +9 -0
- package/dist/i18n/localeContext.svelte.d.ts +10 -3
- package/dist/i18n/localeContext.svelte.js +27 -5
- package/dist/i18n/messages.d.ts +150 -2
- package/dist/i18n/messages.js +261 -11
- package/dist/index.d.ts +4 -1
- package/dist/index.js +3 -0
- package/dist/public.d.ts +1 -1
- 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.js +21 -0
- package/dist/styles/base.css +80 -10
- 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/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 +15 -15
- package/src/lib/components/ConfirmDialog.svelte +2 -10
- package/src/lib/components/ErrorScreen.svelte +21 -27
- package/src/lib/components/compute/AppLayout.svelte +286 -116
- package/src/lib/components/compute/ComputeApp.svelte +45 -24
- package/src/lib/components/compute/ComputeMessagesDialog.svelte +47 -83
- package/src/lib/components/compute/ParameterPresetManager.svelte +37 -130
- package/src/lib/components/compute/SolveMessages.svelte +131 -77
- package/src/lib/components/layout/AppShell.svelte +10 -6
- package/src/lib/components/layout/PageFooter.svelte +23 -11
- package/src/lib/components/layout/PageHeader.svelte +11 -7
- package/src/lib/components/layout/Pagination.svelte +2 -4
- package/src/lib/components/layout/SectionHeader.svelte +4 -2
- package/src/lib/components/layout/SideNav.svelte +56 -7
- package/src/lib/components/preview/ChartOutput.svelte +35 -25
- package/src/lib/components/preview/Group.svelte +92 -103
- package/src/lib/components/preview/HelpButton.svelte +36 -0
- package/src/lib/components/preview/ImageOutput.svelte +430 -71
- package/src/lib/components/preview/InputControl.svelte +163 -90
- package/src/lib/components/preview/OutputDisplay.svelte +28 -33
- package/src/lib/components/preview/TabBar.svelte +106 -22
- package/src/lib/components/preview/TabContent.svelte +63 -57
- package/src/lib/components/preview/TabLayout.svelte +27 -5
- package/src/lib/components/preview/inputs/CheckboxInput.svelte +7 -7
- package/src/lib/components/preview/inputs/ChecklistInput.svelte +7 -2
- package/src/lib/components/preview/inputs/ColorInput.svelte +4 -2
- package/src/lib/components/preview/inputs/DropdownInput.svelte +19 -4
- package/src/lib/components/preview/inputs/FileInput.svelte +112 -108
- package/src/lib/components/preview/inputs/GeometryInput.svelte +128 -0
- package/src/lib/components/preview/inputs/NumberInput.svelte +123 -61
- package/src/lib/components/preview/inputs/OptionGlyph.svelte +29 -0
- package/src/lib/components/preview/inputs/SegmentedInput.svelte +44 -0
- package/src/lib/components/preview/inputs/TextInput.svelte +8 -4
- package/src/lib/components/preview/inputs/TileInput.svelte +80 -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 +11 -18
- package/src/lib/components/primitives/DataTable.svelte +38 -5
- package/src/lib/components/primitives/FilterableDropdown.svelte +42 -129
- package/src/lib/components/primitives/IssueList.svelte +56 -0
- package/src/lib/components/primitives/SeverityIcon.svelte +15 -0
- package/src/lib/components/primitives/SolvingIndicator.svelte +43 -42
- package/src/lib/components/primitives/StateDisplay.svelte +19 -79
- package/src/lib/components/primitives/ViewToggle.svelte +18 -33
- package/src/lib/components/primitives/alert-dialog/alert-dialog-action.svelte +9 -3
- package/src/lib/components/primitives/alert-dialog/alert-dialog-content.svelte +1 -1
- package/src/lib/components/primitives/alert-dialog/alert-dialog-overlay.svelte +1 -1
- package/src/lib/components/primitives/badge/badge.svelte +2 -2
- package/src/lib/components/primitives/button/button.svelte +6 -2
- package/src/lib/components/primitives/card/card-header.svelte +1 -1
- package/src/lib/components/primitives/card/card.svelte +21 -5
- package/src/lib/components/primitives/card/index.ts +1 -4
- package/src/lib/components/primitives/checkbox/checkbox.svelte +1 -1
- package/src/lib/components/primitives/command/command-dialog.svelte +42 -0
- package/src/lib/components/primitives/command/command-empty.svelte +17 -0
- package/src/lib/components/primitives/command/command-group.svelte +33 -0
- package/src/lib/components/primitives/command/command-input.svelte +36 -0
- package/src/lib/components/primitives/command/command-item.svelte +28 -0
- package/src/lib/components/primitives/command/command-link-item.svelte +21 -0
- package/src/lib/components/primitives/command/command-list.svelte +20 -0
- package/src/lib/components/primitives/command/command-loading.svelte +7 -0
- package/src/lib/components/primitives/command/command-separator.svelte +17 -0
- package/src/lib/components/primitives/command/command-shortcut.svelte +23 -0
- package/src/lib/components/primitives/command/command.svelte +28 -0
- package/src/lib/components/primitives/command/index.ts +37 -0
- package/src/lib/components/primitives/context-menu/context-menu-content.svelte +1 -1
- package/src/lib/components/primitives/context-menu/context-menu-sub-content.svelte +1 -1
- package/src/lib/components/primitives/dialog/dialog-content.svelte +11 -3
- package/src/lib/components/primitives/dialog/dialog-overlay.svelte +1 -1
- package/src/lib/components/primitives/dialog/dialog-title.svelte +6 -2
- package/src/lib/components/primitives/drawer/Drawer.svelte +2 -2
- package/src/lib/components/primitives/dropdown-menu/dropdown-menu-checkbox-group.svelte +16 -0
- package/src/lib/components/primitives/dropdown-menu/dropdown-menu-checkbox-item.svelte +46 -0
- package/src/lib/components/primitives/dropdown-menu/dropdown-menu-content.svelte +31 -0
- package/src/lib/components/primitives/dropdown-menu/dropdown-menu-group-heading.svelte +22 -0
- package/src/lib/components/primitives/dropdown-menu/dropdown-menu-group.svelte +7 -0
- package/src/lib/components/primitives/dropdown-menu/dropdown-menu-item.svelte +27 -0
- package/src/lib/components/primitives/dropdown-menu/dropdown-menu-label.svelte +24 -0
- package/src/lib/components/primitives/dropdown-menu/dropdown-menu-portal.svelte +7 -0
- package/src/lib/components/primitives/dropdown-menu/dropdown-menu-radio-group.svelte +16 -0
- package/src/lib/components/primitives/dropdown-menu/dropdown-menu-radio-item.svelte +36 -0
- package/src/lib/components/primitives/dropdown-menu/dropdown-menu-separator.svelte +17 -0
- package/src/lib/components/primitives/dropdown-menu/dropdown-menu-shortcut.svelte +23 -0
- package/src/lib/components/primitives/dropdown-menu/dropdown-menu-sub-content.svelte +31 -0
- package/src/lib/components/primitives/dropdown-menu/dropdown-menu-sub-trigger.svelte +29 -0
- package/src/lib/components/primitives/dropdown-menu/dropdown-menu-sub.svelte +7 -0
- package/src/lib/components/primitives/dropdown-menu/dropdown-menu-trigger.svelte +7 -0
- package/src/lib/components/primitives/dropdown-menu/dropdown-menu.svelte +7 -0
- package/src/lib/components/primitives/dropdown-menu/index.ts +54 -0
- package/src/lib/components/primitives/{alert/alert-description.svelte → empty/empty-content.svelte} +3 -3
- package/src/lib/components/primitives/empty/empty-description.svelte +23 -0
- package/src/lib/components/primitives/{alert/alert-title.svelte → empty/empty-header.svelte} +3 -3
- package/src/lib/components/primitives/empty/empty-media.svelte +41 -0
- package/src/lib/components/primitives/{card/card-action.svelte → empty/empty-title.svelte} +2 -2
- package/src/lib/components/primitives/empty/empty.svelte +23 -0
- package/src/lib/components/primitives/empty/index.ts +22 -0
- package/src/lib/components/primitives/index.ts +10 -1
- package/src/lib/components/primitives/input/input.svelte +4 -4
- package/src/lib/components/primitives/input-group/index.ts +22 -0
- package/src/lib/components/primitives/input-group/input-group-addon.svelte +53 -0
- package/src/lib/components/primitives/input-group/input-group-button.svelte +49 -0
- package/src/lib/components/primitives/input-group/input-group-input.svelte +25 -0
- package/src/lib/components/primitives/input-group/input-group-text.svelte +22 -0
- package/src/lib/components/primitives/input-group/input-group-textarea.svelte +23 -0
- package/src/lib/components/primitives/input-group/input-group.svelte +24 -0
- package/src/lib/components/primitives/mode-toggle/mode-toggle.svelte +6 -7
- package/src/lib/components/primitives/popover/index.ts +28 -0
- package/src/lib/components/primitives/popover/popover-close.svelte +7 -0
- package/src/lib/components/primitives/popover/popover-content.svelte +31 -0
- package/src/lib/components/primitives/popover/popover-description.svelte +20 -0
- package/src/lib/components/primitives/popover/popover-header.svelte +20 -0
- package/src/lib/components/primitives/popover/popover-portal.svelte +7 -0
- package/src/lib/components/primitives/popover/popover-title.svelte +15 -0
- package/src/lib/components/primitives/popover/popover-trigger.svelte +17 -0
- package/src/lib/components/primitives/popover/popover.svelte +7 -0
- package/src/lib/components/primitives/resizable/resizable-handle.svelte +6 -2
- package/src/lib/components/primitives/resizable/resizable-pane-group.svelte +1 -4
- package/src/lib/components/primitives/scroll-area/scroll-area.svelte +1 -1
- package/src/lib/components/primitives/search/search.svelte +3 -3
- package/src/lib/components/primitives/select/select-content.svelte +1 -1
- package/src/lib/components/primitives/select/select-trigger.svelte +1 -1
- package/src/lib/components/primitives/severity.ts +26 -0
- package/src/lib/components/primitives/slider/slider.svelte +8 -3
- package/src/lib/components/primitives/sonner/sonner.svelte +1 -1
- package/src/lib/components/primitives/spinner/index.ts +1 -0
- package/src/lib/components/primitives/spinner/spinner.svelte +29 -0
- package/src/lib/components/primitives/switch/switch.svelte +2 -2
- package/src/lib/components/primitives/tabs/tabs-list.svelte +27 -5
- package/src/lib/components/primitives/tabs/tabs-trigger.svelte +23 -5
- package/src/lib/components/primitives/tabs/tabs.svelte +6 -2
- package/src/lib/components/primitives/textarea/textarea.svelte +1 -1
- package/src/lib/components/primitives/theme-switcher/ThemeSwitcher.svelte +1 -1
- package/src/lib/components/primitives/toggle/index.ts +13 -0
- package/src/lib/components/primitives/toggle/toggle.svelte +54 -0
- package/src/lib/components/primitives/toggle-group/index.ts +10 -0
- package/src/lib/components/primitives/toggle-group/toggle-group-item.svelte +35 -0
- package/src/lib/components/primitives/toggle-group/toggle-group.svelte +75 -0
- package/src/lib/components/viewer/MeshMetadataPanel.svelte +119 -0
- package/src/lib/components/viewer/SceneManager.svelte +14 -5
- package/src/lib/components/viewer/Viewer.svelte +243 -221
- 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 +7 -9
- package/src/lib/contexts/hostContext.svelte.ts +51 -0
- package/src/lib/i18n/localeContext.svelte.ts +40 -5
- package/src/lib/i18n/messages.ts +453 -13
- package/src/lib/index.ts +21 -0
- package/src/lib/public.ts +1 -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 +23 -0
- package/src/lib/styles/base.css +80 -10
- package/src/lib/types/actionButton.ts +16 -3
- package/src/lib/types/presetLabels.ts +13 -11
- 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/alert/alert.svelte +0 -44
- package/dist/components/primitives/alert/alert.svelte.d.ts +0 -26
- package/dist/components/primitives/alert/index.d.ts +0 -5
- package/dist/components/primitives/alert/index.js +0 -7
- package/dist/components/viewer/MeshMetadataDialog.svelte +0 -126
- package/dist/components/viewer/MeshMetadataDialog.svelte.d.ts +0 -10
- package/src/lib/components/primitives/alert/alert.svelte +0 -44
- package/src/lib/components/primitives/alert/index.ts +0 -14
- package/src/lib/components/viewer/MeshMetadataDialog.svelte +0 -126
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
// Which elements of a schema each host renders. Worked out from the schema on every read and
|
|
2
|
+
// never stored in it: a stored copy goes stale the way a saved paramType does. Making an element
|
|
3
|
+
// work on Selva later is a change to SUPPORT, with no schema change and no migration.
|
|
4
|
+
|
|
5
|
+
import type {
|
|
6
|
+
InputLayoutItem,
|
|
7
|
+
LayoutItem,
|
|
8
|
+
SchemaInput,
|
|
9
|
+
UISchema,
|
|
10
|
+
CheckboxWidgetConfig
|
|
11
|
+
} from '@selvajs/schemas';
|
|
12
|
+
import { getGroups } from '@selvajs/schemas';
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Where a UI runs: `rhino` is the plugin's page inside Rhino, solving in the user's own
|
|
16
|
+
* Grasshopper; `selva` is the Selva app, solving headless on Rhino.Compute.
|
|
17
|
+
*/
|
|
18
|
+
export type UIHost = 'rhino' | 'selva';
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* - `value`: an input or output every host renders.
|
|
22
|
+
* - `geometry`: a Rhino Get Geometry/Point/Line/Plane input, filled by picking in the viewport.
|
|
23
|
+
* - `trigger`: a boolean input shown as a button; a press solves once with `true`.
|
|
24
|
+
* - `unknown`: a layout item from a newer schema than this build knows.
|
|
25
|
+
*/
|
|
26
|
+
export type ElementKind = 'value' | 'geometry' | 'trigger' | 'unknown';
|
|
27
|
+
|
|
28
|
+
const SUPPORT: Record<ElementKind, readonly UIHost[]> = {
|
|
29
|
+
value: ['rhino', 'selva'],
|
|
30
|
+
geometry: ['rhino'],
|
|
31
|
+
trigger: ['rhino'],
|
|
32
|
+
unknown: []
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
export const HOST_LABELS: Record<UIHost, string> = { rhino: 'Rhino', selva: 'Selva' };
|
|
36
|
+
|
|
37
|
+
const GEOMETRY_PARAM_TYPES: ReadonlySet<string> = new Set(['geometry', 'point', 'line', 'plane']);
|
|
38
|
+
|
|
39
|
+
type WidgetTypeOf<T extends 'input' | 'output'> = Extract<LayoutItem, { type: T }>['widgetType'];
|
|
40
|
+
|
|
41
|
+
// Keyed by the schema's own widget unions, so a widget added to the schema fails to compile here
|
|
42
|
+
// until someone decides which hosts render it.
|
|
43
|
+
const INPUT_WIDGETS = {
|
|
44
|
+
number: true,
|
|
45
|
+
text: true,
|
|
46
|
+
dropdown: true,
|
|
47
|
+
dynamicValueList: true,
|
|
48
|
+
checkbox: true,
|
|
49
|
+
file: true,
|
|
50
|
+
color: true
|
|
51
|
+
} as const satisfies Record<WidgetTypeOf<'input'>, true>;
|
|
52
|
+
const OUTPUT_WIDGETS = {
|
|
53
|
+
text: true,
|
|
54
|
+
number: true,
|
|
55
|
+
file: true,
|
|
56
|
+
chart: true,
|
|
57
|
+
image: true,
|
|
58
|
+
dynamicValueList: true
|
|
59
|
+
} as const satisfies Record<WidgetTypeOf<'output'>, true>;
|
|
60
|
+
|
|
61
|
+
const KNOWN_WIDGETS: Record<'input' | 'output', ReadonlySet<string>> = {
|
|
62
|
+
input: new Set(Object.keys(INPUT_WIDGETS)),
|
|
63
|
+
output: new Set(Object.keys(OUTPUT_WIDGETS))
|
|
64
|
+
};
|
|
65
|
+
|
|
66
|
+
/** The control comes from this, whatever the saved widgetType says: saved ones hold `text`. */
|
|
67
|
+
export function isGeometryParamType(paramType: string | undefined): boolean {
|
|
68
|
+
return paramType !== undefined && GEOMETRY_PARAM_TYPES.has(paramType);
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
export function isTriggerItem(item: LayoutItem): boolean {
|
|
72
|
+
return (
|
|
73
|
+
item.type === 'input' &&
|
|
74
|
+
item.widgetType === 'checkbox' &&
|
|
75
|
+
(item.config as CheckboxWidgetConfig | undefined)?.displayAs === 'button'
|
|
76
|
+
);
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
export function layoutItemKind(item: LayoutItem, inputs: readonly SchemaInput[]): ElementKind {
|
|
80
|
+
if (item.type === 'linebreak') return 'value';
|
|
81
|
+
if (item.type !== 'input' && item.type !== 'output') return 'unknown';
|
|
82
|
+
if (item.type === 'input') {
|
|
83
|
+
const paramType = inputs.find((i) => i.id === item.paramId)?.paramType;
|
|
84
|
+
if (isGeometryParamType(paramType)) return 'geometry';
|
|
85
|
+
}
|
|
86
|
+
if (!KNOWN_WIDGETS[item.type].has(item.widgetType)) return 'unknown';
|
|
87
|
+
return isTriggerItem(item) ? 'trigger' : 'value';
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
export function hostsFor(kind: ElementKind): readonly UIHost[] {
|
|
91
|
+
return SUPPORT[kind];
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
export function isSupportedOn(host: UIHost, kind: ElementKind): boolean {
|
|
95
|
+
return SUPPORT[kind].includes(host);
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
/**
|
|
99
|
+
* Inputs the form keeps no value for: geometry lives on the Grasshopper param after a pick, and a
|
|
100
|
+
* button only sends a press. Value updates and presets skip them; holding a button's `true` would
|
|
101
|
+
* fire its action again on every solve.
|
|
102
|
+
*/
|
|
103
|
+
export function isValuelessInput(item: InputLayoutItem, input: SchemaInput | undefined): boolean {
|
|
104
|
+
return isGeometryParamType(input?.paramType) || isTriggerItem(item);
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
export function valuelessInputIds(schema: UISchema): Set<string> {
|
|
108
|
+
const ids = new Set<string>();
|
|
109
|
+
for (const input of schema.inputs) {
|
|
110
|
+
if (isGeometryParamType(input.paramType)) ids.add(input.id);
|
|
111
|
+
}
|
|
112
|
+
for (const group of getGroups(schema)) {
|
|
113
|
+
for (const item of group.items ?? []) {
|
|
114
|
+
if (isTriggerItem(item)) ids.add((item as InputLayoutItem).paramId);
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
return ids;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
/** The placed items a host won't render, for the builder's summary of where the UI runs. */
|
|
121
|
+
export function unsupportedItems(schema: UISchema, host: UIHost): LayoutItem[] {
|
|
122
|
+
const items: LayoutItem[] = [];
|
|
123
|
+
for (const group of getGroups(schema)) {
|
|
124
|
+
for (const item of group.items ?? []) {
|
|
125
|
+
if (!isSupportedOn(host, layoutItemKind(item, schema.inputs))) items.push(item);
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
return items;
|
|
129
|
+
}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import type { DropdownWidgetConfig, OptionMedia, UISchema } from '@selvajs/schemas';
|
|
2
|
+
|
|
3
|
+
export type OptionDisplay = NonNullable<DropdownWidgetConfig['displayAs']>;
|
|
4
|
+
|
|
5
|
+
// Past this a button row no longer fits a panel column. A computed list can grow past it at
|
|
6
|
+
// runtime, so the row turns back into a dropdown instead of wrapping.
|
|
7
|
+
const MAX_SEGMENTED_OPTIONS = 6;
|
|
8
|
+
|
|
9
|
+
export function resolveOptionDisplay(
|
|
10
|
+
displayAs: string | undefined,
|
|
11
|
+
optionCount: number
|
|
12
|
+
): OptionDisplay {
|
|
13
|
+
switch (displayAs) {
|
|
14
|
+
case 'checklist':
|
|
15
|
+
case 'tiles':
|
|
16
|
+
return displayAs;
|
|
17
|
+
case 'segmented':
|
|
18
|
+
return optionCount <= MAX_SEGMENTED_OPTIONS ? 'segmented' : 'dropdown';
|
|
19
|
+
default:
|
|
20
|
+
return 'dropdown';
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export type GlyphSource = { kind: 'icon'; d: string } | { kind: 'image'; src: string };
|
|
25
|
+
|
|
26
|
+
// The schema can come from any .gh, so an image reaches <img> only as an inline raster data URI.
|
|
27
|
+
// Anything else could be a URL that makes every viewer's browser call wherever the file points.
|
|
28
|
+
const RASTER_DATA_URI = /^data:image\/(webp|jpeg|png);base64,[A-Za-z0-9+/=]+$/;
|
|
29
|
+
|
|
30
|
+
/** What to draw beside an option: its thumbnail, else its icon. */
|
|
31
|
+
export function optionGlyph(
|
|
32
|
+
media: OptionMedia | undefined,
|
|
33
|
+
assets: UISchema['assets'] | undefined
|
|
34
|
+
): GlyphSource | undefined {
|
|
35
|
+
if (!media || !assets) return undefined;
|
|
36
|
+
|
|
37
|
+
if (media.image) {
|
|
38
|
+
const src = assets[media.image]?.img;
|
|
39
|
+
if (src && RASTER_DATA_URI.test(src)) return { kind: 'image', src };
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
const d = media.icon ? assets[media.icon]?.d : undefined;
|
|
43
|
+
return d ? { kind: 'icon', d } : undefined;
|
|
44
|
+
}
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import { randomId } from '../utils/randomId';
|
|
2
|
+
import { saveBlob } from '../utils/host-files';
|
|
2
3
|
import { getGroups } from '@selvajs/schemas';
|
|
4
|
+
import { isValuelessInput, valuelessInputIds } from './host-support';
|
|
3
5
|
import type {
|
|
4
6
|
UISchema,
|
|
5
7
|
ParameterPreset,
|
|
@@ -24,6 +26,7 @@ export function createSavedState(
|
|
|
24
26
|
if (item.type !== 'input') continue;
|
|
25
27
|
const value = currentValues[item.paramId];
|
|
26
28
|
const inputDef = schema.inputs.find((i) => i.id === item.paramId);
|
|
29
|
+
if (isValuelessInput(item, inputDef)) continue;
|
|
27
30
|
if (value !== undefined && inputDef) {
|
|
28
31
|
parameters.push({
|
|
29
32
|
paramId: item.paramId,
|
|
@@ -110,15 +113,18 @@ export function validateSavedState(
|
|
|
110
113
|
* Params the current schema no longer has are dropped. That's the same condition
|
|
111
114
|
* `validateSavedState` flags as an error, but the rule is re-derived from the schema here
|
|
112
115
|
* rather than read back off the issue list — nothing couples to how sentinel ids are encoded.
|
|
116
|
+
* Valueless inputs are dropped too: a preset saved before an input became a button or a
|
|
117
|
+
* geometry input still holds a value for it.
|
|
113
118
|
*/
|
|
114
119
|
export function extractLoadableValues(
|
|
115
120
|
savedState: ParameterPreset,
|
|
116
121
|
currentSchema: UISchema
|
|
117
122
|
): Record<string, unknown> {
|
|
118
123
|
const values: Record<string, unknown> = {};
|
|
124
|
+
const valueless = valuelessInputIds(currentSchema);
|
|
119
125
|
for (const paramState of savedState.parameters) {
|
|
120
126
|
const exists = currentSchema.inputs.some((i) => i.id === paramState.paramId);
|
|
121
|
-
if (exists) {
|
|
127
|
+
if (exists && !valueless.has(paramState.paramId)) {
|
|
122
128
|
values[paramState.paramId] = paramState.value;
|
|
123
129
|
}
|
|
124
130
|
}
|
|
@@ -147,18 +153,15 @@ export function loadPreset(savedState: ParameterPreset, currentSchema: UISchema)
|
|
|
147
153
|
};
|
|
148
154
|
}
|
|
149
155
|
|
|
150
|
-
|
|
156
|
+
/** Resolves false when the user cancelled the save. */
|
|
157
|
+
export function exportStateAsJson(savedState: ParameterPreset): Promise<boolean> {
|
|
151
158
|
const blob = new Blob([JSON.stringify(savedState, null, 2)], { type: 'application/json' });
|
|
152
159
|
const safeName = savedState.name.replace(/[^a-z0-9]/gi, '_');
|
|
153
160
|
const date = savedState.timestamp.split('T')[0].replace(/-/g, '_');
|
|
154
161
|
|
|
155
|
-
const link = document.createElement('a');
|
|
156
|
-
link.href = URL.createObjectURL(blob);
|
|
157
162
|
// .slvp = Selva parameter preset. Import still accepts the pre-rename .sps — same JSON,
|
|
158
163
|
// only the writer's extension changed.
|
|
159
|
-
|
|
160
|
-
link.click();
|
|
161
|
-
URL.revokeObjectURL(link.href);
|
|
164
|
+
return saveBlob(blob, `${safeName}_${date}.slvp`);
|
|
162
165
|
}
|
|
163
166
|
|
|
164
167
|
export async function importStateFromJson(file: File): Promise<ParameterPreset> {
|
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
import type {
|
|
2
2
|
LayoutItem,
|
|
3
|
+
OutputLayoutItem,
|
|
3
4
|
VisibilityRule,
|
|
4
5
|
VisibilityCondition,
|
|
5
6
|
GroupVisibilityCondition,
|
|
6
7
|
TabConfig
|
|
7
8
|
} from '@selvajs/schemas';
|
|
9
|
+
import { isFileData } from '../utils/file-download';
|
|
8
10
|
|
|
9
11
|
export interface VisibilityResult {
|
|
10
12
|
visible: boolean;
|
|
@@ -76,6 +78,9 @@ export function evaluateVisibility(
|
|
|
76
78
|
if ('visible' in item && item.visible === false) {
|
|
77
79
|
return { visible: false, disabled: false };
|
|
78
80
|
}
|
|
81
|
+
if (item.type === 'output' && drawsNothing(item, values[item.paramId])) {
|
|
82
|
+
return { visible: false, disabled: false };
|
|
83
|
+
}
|
|
79
84
|
if (!item.visibilityCondition?.rules) return { visible: true, disabled: false };
|
|
80
85
|
|
|
81
86
|
const { action = 'show', defaultValue } = item.visibilityCondition;
|
|
@@ -85,6 +90,24 @@ export function evaluateVisibility(
|
|
|
85
90
|
return actionFn(met, defaultValue);
|
|
86
91
|
}
|
|
87
92
|
|
|
93
|
+
/**
|
|
94
|
+
* An image or chart output has nothing to draw until a solve returns its data, and an empty
|
|
95
|
+
* preview box would hold its group, tab and pane open; it counts as hidden until then. A dynamic
|
|
96
|
+
* value list output never draws: it only feeds the options of an input.
|
|
97
|
+
*/
|
|
98
|
+
function drawsNothing(item: OutputLayoutItem, value: unknown): boolean {
|
|
99
|
+
switch (item.widgetType) {
|
|
100
|
+
case 'image':
|
|
101
|
+
return !(Array.isArray(value) ? value.some(isFileData) : isFileData(value));
|
|
102
|
+
case 'chart':
|
|
103
|
+
return value === undefined || value === null || value === '';
|
|
104
|
+
case 'dynamicValueList':
|
|
105
|
+
return true;
|
|
106
|
+
default:
|
|
107
|
+
return false;
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
|
|
88
111
|
/** Must stay identical to the key the renderers use in their `{#each}` blocks. */
|
|
89
112
|
export function itemKey(item: LayoutItem): string {
|
|
90
113
|
return item.type === 'linebreak' ? item.id : item.paramId;
|
package/src/lib/styles/base.css
CHANGED
|
@@ -3,15 +3,19 @@
|
|
|
3
3
|
:root {
|
|
4
4
|
--radius: 0.625rem;
|
|
5
5
|
--header-h: 3.5rem;
|
|
6
|
-
--
|
|
6
|
+
--below-header-h: calc(100svh - var(--header-h));
|
|
7
|
+
--page-px: 1rem;
|
|
7
8
|
--page-py: 1.75rem;
|
|
8
9
|
--background: oklch(0.99 0 0);
|
|
9
10
|
--foreground: oklch(0.22 0 0);
|
|
10
|
-
|
|
11
|
+
/* White, so a card stands apart from background and muted; Group adds a border, since
|
|
12
|
+
white on background alone is too close to see. */
|
|
13
|
+
--card: oklch(1 0 0);
|
|
11
14
|
--card-foreground: oklch(0.22 0 0);
|
|
12
15
|
--popover: oklch(0.99 0 0);
|
|
13
16
|
--popover-foreground: oklch(0.22 0 0);
|
|
14
|
-
|
|
17
|
+
/* 4.5:1 as text on background, card and muted, and under white text. */
|
|
18
|
+
--primary: oklch(0.52 0.07 135);
|
|
15
19
|
--primary-foreground: oklch(0.985 0 0);
|
|
16
20
|
--secondary: oklch(0.94 0 0);
|
|
17
21
|
--secondary-foreground: oklch(0.28 0 0);
|
|
@@ -19,10 +23,14 @@
|
|
|
19
23
|
--muted-foreground: oklch(0.5 0 0);
|
|
20
24
|
--accent: oklch(0.93 0 0);
|
|
21
25
|
--accent-foreground: oklch(0.3 0 0);
|
|
22
|
-
|
|
26
|
+
/* 4.5:1 as small text on background, card and muted, and under white text. */
|
|
27
|
+
--destructive: oklch(0.55 0.19 27);
|
|
28
|
+
--destructive-foreground: oklch(0.985 0 0);
|
|
23
29
|
--border: oklch(0.86 0 0);
|
|
24
|
-
|
|
25
|
-
|
|
30
|
+
/* Field borders and unchecked boxes: at least 3:1 against background, card and muted, the
|
|
31
|
+
WCAG minimum for a control's boundary. Same for the focus ring, which is drawn opaque. */
|
|
32
|
+
--input: oklch(0.62 0 0);
|
|
33
|
+
--ring: oklch(0.55 0 0);
|
|
26
34
|
--success: oklch(0.66 0.14 145);
|
|
27
35
|
--success-foreground: oklch(0.99 0 0);
|
|
28
36
|
--warning: oklch(0.78 0.12 75);
|
|
@@ -36,14 +44,16 @@
|
|
|
36
44
|
--chart-5: oklch(0.68 0.15 30);
|
|
37
45
|
--sidebar: oklch(0.96 0 0);
|
|
38
46
|
--sidebar-foreground: oklch(0.25 0 0);
|
|
39
|
-
--sidebar-primary: oklch(0.
|
|
47
|
+
--sidebar-primary: oklch(0.52 0.07 135);
|
|
40
48
|
--sidebar-primary-foreground: oklch(0.985 0 0);
|
|
41
49
|
--sidebar-accent: oklch(0.93 0 0);
|
|
42
50
|
--sidebar-accent-foreground: oklch(0.3 0 0);
|
|
43
51
|
--sidebar-border: oklch(0.88 0 0);
|
|
44
|
-
--sidebar-ring: oklch(0.
|
|
52
|
+
--sidebar-ring: oklch(0.55 0 0);
|
|
45
53
|
--inputparam: oklch(1 0 0);
|
|
46
54
|
--outputparam: oklch(1 0 0);
|
|
55
|
+
/* Scrim behind modal dialogs and drawers. */
|
|
56
|
+
--overlay: oklch(0 0 0 / 50%);
|
|
47
57
|
}
|
|
48
58
|
|
|
49
59
|
.dark {
|
|
@@ -62,8 +72,9 @@
|
|
|
62
72
|
--accent: oklch(0.36 0 0);
|
|
63
73
|
--accent-foreground: oklch(0.92 0 0);
|
|
64
74
|
--destructive: oklch(0.7 0.17 22);
|
|
75
|
+
--destructive-foreground: oklch(0.985 0 0);
|
|
65
76
|
--border: oklch(1 0 0 / 14%);
|
|
66
|
-
--input: oklch(1 0 0 /
|
|
77
|
+
--input: oklch(1 0 0 / 36%);
|
|
67
78
|
--ring: oklch(0.74 0 0);
|
|
68
79
|
--success: oklch(0.74 0.15 145);
|
|
69
80
|
--success-foreground: oklch(0.18 0.03 145);
|
|
@@ -108,6 +119,8 @@
|
|
|
108
119
|
--color-accent: var(--accent);
|
|
109
120
|
--color-accent-foreground: var(--accent-foreground);
|
|
110
121
|
--color-destructive: var(--destructive);
|
|
122
|
+
--color-destructive-foreground: var(--destructive-foreground);
|
|
123
|
+
--color-overlay: var(--overlay);
|
|
111
124
|
--color-border: var(--border);
|
|
112
125
|
--color-input: var(--input);
|
|
113
126
|
--color-ring: var(--ring);
|
|
@@ -134,9 +147,66 @@
|
|
|
134
147
|
--color-outputparam: var(--outputparam);
|
|
135
148
|
}
|
|
136
149
|
|
|
150
|
+
/* Design tokens beyond Tailwind's defaults. Reach for these before an arbitrary value: the
|
|
151
|
+
design-system lint rejects `text-[10px]`, `max-h-[85dvh]` and the like. */
|
|
152
|
+
@theme {
|
|
153
|
+
/* Type tags, counters and other dense labels. */
|
|
154
|
+
--text-2xs: 0.625rem;
|
|
155
|
+
--text-2xs--line-height: calc(0.875 / 0.625);
|
|
156
|
+
/* Bottom sheets cast their shadow upward. */
|
|
157
|
+
--shadow-sheet: 0 -4px 24px oklch(0 0 0 / 12%);
|
|
158
|
+
/* Width of anything that must keep a 1rem gutter on each side of the viewport. */
|
|
159
|
+
--container-screen-inset: calc(100% - 2rem);
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
@utility max-h-dialog {
|
|
163
|
+
max-height: 85dvh;
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
@utility no-scrollbar {
|
|
167
|
+
scrollbar-width: none;
|
|
168
|
+
&::-webkit-scrollbar {
|
|
169
|
+
display: none;
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
/* Number fields whose value is set elsewhere (a slider, a stepper) drop the browser's spinner. */
|
|
174
|
+
@utility no-spinner {
|
|
175
|
+
appearance: textfield;
|
|
176
|
+
&::-webkit-inner-spin-button,
|
|
177
|
+
&::-webkit-outer-spin-button {
|
|
178
|
+
appearance: none;
|
|
179
|
+
margin: 0;
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
@utility rounded-inherit {
|
|
184
|
+
border-radius: inherit;
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
/* Phones keep a narrower gutter: at 390px every 8px of side padding is 2% of the width. */
|
|
188
|
+
@media (min-width: 40rem) {
|
|
189
|
+
:root {
|
|
190
|
+
--page-px: 1.5rem;
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
/* A native select draws its arrow inside the right padding, so with the `px-2`/`px-3` every
|
|
195
|
+
caller uses it sits on the border. A drawn chevron with its own gutter fixes them all. Unlayered
|
|
196
|
+
on purpose: the gutter has to beat the callers' `px-*` utilities. Mid-grey reads on both themes,
|
|
197
|
+
since a data URI can't take `currentColor`. */
|
|
198
|
+
select:not([multiple]):not([size]) {
|
|
199
|
+
appearance: none;
|
|
200
|
+
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23888' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m6 9 6 6 6-6'/%3E%3C/svg%3E");
|
|
201
|
+
background-repeat: no-repeat;
|
|
202
|
+
background-position: right 0.625rem center;
|
|
203
|
+
background-size: 1.1em;
|
|
204
|
+
padding-inline-end: calc(1.1em + 1rem);
|
|
205
|
+
}
|
|
206
|
+
|
|
137
207
|
@layer base {
|
|
138
208
|
* {
|
|
139
|
-
@apply border-border outline-ring
|
|
209
|
+
@apply border-border outline-ring;
|
|
140
210
|
}
|
|
141
211
|
html,
|
|
142
212
|
body {
|
|
@@ -1,9 +1,22 @@
|
|
|
1
|
+
import type { SolveSettlement } from '@selvajs/solve/client';
|
|
2
|
+
|
|
3
|
+
/** A host action, listed in the panel footer's ⋯ menu after saving and loading inputs. */
|
|
1
4
|
export interface ActionButton {
|
|
2
5
|
id: string;
|
|
3
6
|
label: string;
|
|
4
7
|
/** A Svelte component, rendered before the label. */
|
|
5
8
|
icon?: any;
|
|
6
|
-
variant?: 'default' | '
|
|
7
|
-
|
|
8
|
-
|
|
9
|
+
variant?: 'default' | 'destructive';
|
|
10
|
+
/** Shows the action as unavailable instead of hiding it. Pair it with a `hint` saying why. */
|
|
11
|
+
disabled?: boolean;
|
|
12
|
+
/** A short line under the label: why it is disabled, or what it does. */
|
|
13
|
+
hint?: string;
|
|
14
|
+
/**
|
|
15
|
+
* The action needs the result for the current inputs: picking it solves first when inputs
|
|
16
|
+
* changed, waits for a solve that is running or under review, and runs `onclick` only if
|
|
17
|
+
* that solve is applied. `onclick` then receives it. A refused or failed solve already shows
|
|
18
|
+
* its messages, so the action just doesn't run.
|
|
19
|
+
*/
|
|
20
|
+
solvesFirst?: boolean;
|
|
21
|
+
onclick: (settled?: Extract<SolveSettlement, { status: 'applied' }>) => void | Promise<void>;
|
|
9
22
|
}
|
|
@@ -3,9 +3,9 @@
|
|
|
3
3
|
* unset keys fall back to `DEFAULT_PRESET_LABELS`.
|
|
4
4
|
*/
|
|
5
5
|
export interface PresetLabels {
|
|
6
|
-
//
|
|
7
|
-
|
|
8
|
-
|
|
6
|
+
// Panel footer menu
|
|
7
|
+
saveMenuItem: string;
|
|
8
|
+
loadMenuItem: string;
|
|
9
9
|
|
|
10
10
|
// Save dialog
|
|
11
11
|
saveDialogTitle: string;
|
|
@@ -19,6 +19,7 @@ export interface PresetLabels {
|
|
|
19
19
|
saveTagsLabel: string;
|
|
20
20
|
saveTagsPlaceholder: string;
|
|
21
21
|
saveNameRequired: string;
|
|
22
|
+
saveConfirmButton: string;
|
|
22
23
|
|
|
23
24
|
// Load dialog
|
|
24
25
|
loadDialogTitle: string;
|
|
@@ -47,12 +48,12 @@ export interface PresetLabels {
|
|
|
47
48
|
}
|
|
48
49
|
|
|
49
50
|
export const DEFAULT_PRESET_LABELS: PresetLabels = {
|
|
50
|
-
|
|
51
|
-
|
|
51
|
+
saveMenuItem: 'Save inputs…',
|
|
52
|
+
loadMenuItem: 'Load inputs…',
|
|
52
53
|
|
|
53
|
-
saveDialogTitle: 'Save
|
|
54
|
-
saveDialogDescription: 'Save the current
|
|
55
|
-
saveNameLabel: '
|
|
54
|
+
saveDialogTitle: 'Save inputs',
|
|
55
|
+
saveDialogDescription: 'Save the current input values as a .slvp file',
|
|
56
|
+
saveNameLabel: 'Name *',
|
|
56
57
|
saveNamePlaceholder: 'e.g., Design Option A',
|
|
57
58
|
saveDescriptionLabel: 'Description',
|
|
58
59
|
saveDescriptionPlaceholder: 'Optional description of this state',
|
|
@@ -60,10 +61,11 @@ export const DEFAULT_PRESET_LABELS: PresetLabels = {
|
|
|
60
61
|
saveAuthorPlaceholder: 'Your name or email',
|
|
61
62
|
saveTagsLabel: 'Tags',
|
|
62
63
|
saveTagsPlaceholder: 'facade, option-a, client-approved (comma-separated)',
|
|
63
|
-
saveNameRequired: 'Please enter a name for
|
|
64
|
+
saveNameRequired: 'Please enter a name for these inputs',
|
|
65
|
+
saveConfirmButton: 'Save',
|
|
64
66
|
|
|
65
|
-
loadDialogTitle: 'Load
|
|
66
|
-
loadDialogDescription: 'Select a .slvp
|
|
67
|
+
loadDialogTitle: 'Load inputs',
|
|
68
|
+
loadDialogDescription: 'Select a .slvp file from your drive to load',
|
|
67
69
|
loadFromFileButton: 'Select .slvp File',
|
|
68
70
|
loadEmptyList: 'No saved states found',
|
|
69
71
|
loadImportError: 'Failed to import state: ',
|
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
import { downloadFileDataByRoot, type FileData } from '@selvajs/compute/core';
|
|
1
|
+
import { decodeBase64ToBinary, downloadFileDataByRoot, type FileData } from '@selvajs/compute/core';
|
|
2
2
|
import { SvelteMap } from 'svelte/reactivity';
|
|
3
3
|
import { APP_DEFAULTS } from '../constants';
|
|
4
|
+
import { saveBlob } from './host-files';
|
|
4
5
|
|
|
5
6
|
export const MIME_BY_EXT: Record<string, string> = {
|
|
6
7
|
'.png': 'image/png',
|
|
@@ -19,26 +20,15 @@ export const MIME_BY_EXT: Record<string, string> = {
|
|
|
19
20
|
'.stl': 'model/stl'
|
|
20
21
|
};
|
|
21
22
|
|
|
22
|
-
function saveSingleFile(file: FileData):
|
|
23
|
+
function saveSingleFile(file: FileData): Promise<boolean> {
|
|
23
24
|
const ext = (file.fileType ?? '').toLowerCase();
|
|
24
25
|
const mime = MIME_BY_EXT[ext] ?? 'application/octet-stream';
|
|
25
26
|
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
const bytes = new Uint8Array(binary.length);
|
|
30
|
-
for (let i = 0; i < binary.length; i++) bytes[i] = binary.charCodeAt(i);
|
|
31
|
-
blob = new Blob([bytes], { type: mime });
|
|
32
|
-
} else {
|
|
33
|
-
blob = new Blob([file.data], { type: mime });
|
|
34
|
-
}
|
|
27
|
+
const content = file.isBase64Encoded ? decodeBase64ToBinary(file.data) : file.data;
|
|
28
|
+
// decodeBase64ToBinary returns an ArrayBuffer-backed copy, never a SharedArrayBuffer view.
|
|
29
|
+
const blob = new Blob([content as BlobPart], { type: mime });
|
|
35
30
|
|
|
36
|
-
|
|
37
|
-
const a = document.createElement('a');
|
|
38
|
-
a.href = URL.createObjectURL(blob);
|
|
39
|
-
a.download = fullName;
|
|
40
|
-
a.click();
|
|
41
|
-
URL.revokeObjectURL(a.href);
|
|
31
|
+
return saveBlob(blob, `${file.fileName}${file.fileType ?? ''}`);
|
|
42
32
|
}
|
|
43
33
|
|
|
44
34
|
export async function downloadFiles(
|
|
@@ -53,14 +43,14 @@ export async function downloadFiles(
|
|
|
53
43
|
return;
|
|
54
44
|
}
|
|
55
45
|
|
|
56
|
-
// A lone file is saved as itself rather than zipped
|
|
57
|
-
//
|
|
46
|
+
// A lone file is saved as itself rather than zipped. Everything else, including the
|
|
47
|
+
// per-root archive split, belongs to compute.
|
|
58
48
|
if (filesArray.length === 1) {
|
|
59
|
-
saveSingleFile(filesArray[0]);
|
|
49
|
+
await saveSingleFile(filesArray[0]);
|
|
60
50
|
return;
|
|
61
51
|
}
|
|
62
52
|
|
|
63
|
-
await downloadFileDataByRoot(filesArray, fileName);
|
|
53
|
+
await downloadFileDataByRoot(filesArray, fileName, null, { saveBlob });
|
|
64
54
|
} catch (error) {
|
|
65
55
|
console.error('[FileDownload] Error downloading files:', error);
|
|
66
56
|
throw error;
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
// Where a file the page offers goes, and where a file the page asks for comes from. A browser
|
|
2
|
+
// gets an <a download> click and a hidden <input type=file>. A host whose WebView can't do
|
|
3
|
+
// either safely (the Rhino panel) installs its own once at start-up, before the first save or pick.
|
|
4
|
+
|
|
5
|
+
/** Resolves false when the user cancelled. An anchor download always resolves true: it can't tell. */
|
|
6
|
+
export type BlobSaver = (blob: Blob, fileName: string) => Promise<boolean>;
|
|
7
|
+
|
|
8
|
+
/** `accept` is what `<input accept>` takes: `.slvp,.sps`, `image/*`. Resolves null on cancel. */
|
|
9
|
+
export type FilePicker = (options: { accept: string }) => Promise<File | null>;
|
|
10
|
+
|
|
11
|
+
let saver: BlobSaver = saveWithAnchor;
|
|
12
|
+
let picker: FilePicker = pickWithInput;
|
|
13
|
+
|
|
14
|
+
export function setBlobSaver(next: BlobSaver): void {
|
|
15
|
+
saver = next;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export function setFilePicker(next: FilePicker): void {
|
|
19
|
+
picker = next;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export function saveBlob(blob: Blob, fileName: string): Promise<boolean> {
|
|
23
|
+
return saver(blob, fileName);
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export function pickFile(options: { accept: string }): Promise<File | null> {
|
|
27
|
+
return picker(options);
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
async function saveWithAnchor(blob: Blob, fileName: string): Promise<boolean> {
|
|
31
|
+
const url = URL.createObjectURL(blob);
|
|
32
|
+
const a = document.createElement('a');
|
|
33
|
+
a.href = url;
|
|
34
|
+
a.download = fileName;
|
|
35
|
+
// Firefox only downloads from an anchor that is in the document.
|
|
36
|
+
document.body.appendChild(a);
|
|
37
|
+
a.click();
|
|
38
|
+
a.remove();
|
|
39
|
+
// Revoking synchronously can abort the download: the browser pins the blob only once it starts.
|
|
40
|
+
setTimeout(() => URL.revokeObjectURL(url), 10_000);
|
|
41
|
+
return true;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
function pickWithInput({ accept }: { accept: string }): Promise<File | null> {
|
|
45
|
+
return new Promise((resolve) => {
|
|
46
|
+
const input = document.createElement('input');
|
|
47
|
+
input.type = 'file';
|
|
48
|
+
input.accept = accept;
|
|
49
|
+
input.style.display = 'none';
|
|
50
|
+
|
|
51
|
+
const settle = (file: File | null) => {
|
|
52
|
+
input.remove();
|
|
53
|
+
resolve(file);
|
|
54
|
+
};
|
|
55
|
+
input.addEventListener('change', () => settle(input.files?.[0] ?? null), { once: true });
|
|
56
|
+
input.addEventListener('cancel', () => settle(null), { once: true });
|
|
57
|
+
|
|
58
|
+
document.body.appendChild(input);
|
|
59
|
+
input.click();
|
|
60
|
+
});
|
|
61
|
+
}
|
|
@@ -8,6 +8,8 @@ export function loadScript(
|
|
|
8
8
|
src: string,
|
|
9
9
|
options?: {
|
|
10
10
|
crossOrigin?: string;
|
|
11
|
+
/** Subresource Integrity hash. A cross-origin script also needs `crossOrigin`. */
|
|
12
|
+
integrity?: string;
|
|
11
13
|
async?: boolean;
|
|
12
14
|
defer?: boolean;
|
|
13
15
|
}
|
|
@@ -26,6 +28,7 @@ export function loadScript(
|
|
|
26
28
|
const script = document.createElement('script');
|
|
27
29
|
script.src = src;
|
|
28
30
|
if (options?.crossOrigin) script.crossOrigin = options.crossOrigin;
|
|
31
|
+
if (options?.integrity) script.integrity = options.integrity;
|
|
29
32
|
if (options?.async !== undefined) script.async = options.async;
|
|
30
33
|
if (options?.defer !== undefined) script.defer = options.defer;
|
|
31
34
|
|