@svgrid/grid 1.2.34 → 2.0.1
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 +6 -5
- package/dist/SvAccordion.svelte +109 -0
- package/dist/SvAccordion.svelte.d.ts +28 -0
- package/dist/SvAlert.svelte +92 -0
- package/dist/SvAlert.svelte.d.ts +27 -0
- package/dist/SvAutoComplete.svelte +47 -18
- package/dist/SvAutoComplete.svelte.d.ts +2 -5
- package/dist/SvAvatar.svelte +75 -0
- package/dist/SvAvatar.svelte.d.ts +14 -0
- package/dist/SvAvatarGroup.svelte +48 -0
- package/dist/SvAvatarGroup.svelte.d.ts +16 -0
- package/dist/SvBadge.svelte +54 -0
- package/dist/SvBadge.svelte.d.ts +23 -0
- package/dist/SvBreadcrumb.svelte +88 -0
- package/dist/SvBreadcrumb.svelte.d.ts +23 -0
- package/dist/SvButtonGroup.svelte +121 -0
- package/dist/SvButtonGroup.svelte.d.ts +16 -0
- package/dist/SvCalendar.svelte +72 -9
- package/dist/SvCalendar.svelte.d.ts +34 -1
- package/dist/SvCard.svelte +71 -0
- package/dist/SvCard.svelte.d.ts +28 -0
- package/dist/SvCarousel.svelte +134 -0
- package/dist/SvCarousel.svelte.d.ts +28 -0
- package/dist/SvCheckBox.svelte +36 -21
- package/dist/SvCheckBox.svelte.d.ts +2 -5
- package/dist/SvChip.svelte +88 -0
- package/dist/SvChip.svelte.d.ts +31 -0
- package/dist/SvCircularProgress.svelte +109 -0
- package/dist/SvCircularProgress.svelte.d.ts +31 -0
- package/dist/SvColorInput.svelte +54 -27
- package/dist/SvColorInput.svelte.d.ts +10 -6
- package/dist/SvComboBox.svelte +119 -33
- package/dist/SvComboBox.svelte.d.ts +18 -6
- package/dist/SvCommand.svelte +197 -0
- package/dist/SvCommand.svelte.d.ts +26 -0
- package/dist/SvContextMenu.svelte +96 -0
- package/dist/SvContextMenu.svelte.d.ts +25 -0
- package/dist/SvCountryInput.svelte +56 -21
- package/dist/SvCountryInput.svelte.d.ts +9 -5
- package/dist/SvDateRangeInput.svelte +256 -0
- package/dist/SvDateRangeInput.svelte.d.ts +37 -0
- package/dist/SvDateTimePicker.svelte +57 -20
- package/dist/SvDateTimePicker.svelte.d.ts +12 -4
- package/dist/SvDivider.svelte +61 -0
- package/dist/SvDivider.svelte.d.ts +22 -0
- package/dist/SvDrawer.svelte +226 -0
- package/dist/SvDrawer.svelte.d.ts +43 -0
- package/dist/SvDropDownList.svelte +114 -35
- package/dist/SvDropDownList.svelte.d.ts +7 -6
- package/dist/SvDurationInput.svelte +108 -0
- package/dist/SvDurationInput.svelte.d.ts +15 -0
- package/dist/SvEmptyState.svelte +59 -0
- package/dist/SvEmptyState.svelte.d.ts +25 -0
- package/dist/SvField.svelte +85 -0
- package/dist/SvField.svelte.d.ts +30 -0
- package/dist/SvFileUpload.svelte +169 -0
- package/dist/SvFileUpload.svelte.d.ts +24 -0
- package/dist/SvForm.svelte +7 -1
- package/dist/SvForm.svelte.d.ts +3 -0
- package/dist/SvGauge.svelte +7 -1
- package/dist/SvGauge.svelte.d.ts +11 -0
- package/dist/SvGrid.controller.svelte.d.ts +6 -0
- package/dist/SvGrid.controller.svelte.js +64 -9
- package/dist/SvGrid.css +33 -0
- package/dist/SvGrid.svelte +116 -3
- package/dist/SvGrid.types.d.ts +366 -0
- package/dist/SvGridBoard.svelte +2281 -0
- package/dist/SvGridBoard.svelte.d.ts +31 -0
- package/dist/SvGridDropdown.svelte +2 -1
- package/dist/SvGridSelect.svelte +255 -0
- package/dist/SvGridSelect.svelte.d.ts +32 -0
- package/dist/SvGroupCell.svelte +109 -0
- package/dist/SvGroupCell.svelte.d.ts +41 -0
- package/dist/SvListBox.svelte +123 -36
- package/dist/SvListBox.svelte.d.ts +12 -8
- package/dist/SvMaskedInput.svelte +53 -13
- package/dist/SvMaskedInput.svelte.d.ts +16 -6
- package/dist/SvMenu.svelte +101 -0
- package/dist/SvMenu.svelte.d.ts +26 -0
- package/dist/SvMenuList.svelte +143 -0
- package/dist/SvMenuList.svelte.d.ts +24 -0
- package/dist/SvModal.svelte +220 -0
- package/dist/SvModal.svelte.d.ts +31 -0
- package/dist/SvMultiSelect.svelte +277 -0
- package/dist/SvMultiSelect.svelte.d.ts +31 -0
- package/dist/SvNavPane.svelte +314 -0
- package/dist/SvNavPane.svelte.d.ts +59 -0
- package/dist/SvNumberInput.svelte +23 -9
- package/dist/SvNumberInput.svelte.d.ts +2 -0
- package/dist/SvOtpInput.svelte +157 -0
- package/dist/SvOtpInput.svelte.d.ts +16 -0
- package/dist/SvPagination.svelte +100 -0
- package/dist/SvPagination.svelte.d.ts +16 -0
- package/dist/SvPasswordInput.svelte +42 -12
- package/dist/SvPasswordInput.svelte.d.ts +13 -6
- package/dist/SvPhoneInput.svelte +43 -11
- package/dist/SvPhoneInput.svelte.d.ts +10 -11
- package/dist/SvPopover.svelte +127 -0
- package/dist/SvPopover.svelte.d.ts +35 -0
- package/dist/SvProgress.svelte +116 -0
- package/dist/SvProgress.svelte.d.ts +32 -0
- package/dist/SvRadioGroup.svelte +40 -22
- package/dist/SvRadioGroup.svelte.d.ts +2 -10
- package/dist/SvRating.svelte +51 -30
- package/dist/SvRating.svelte.d.ts +10 -7
- package/dist/SvRichText.svelte +192 -0
- package/dist/SvRichText.svelte.d.ts +16 -0
- package/dist/SvRowGroupPanel.svelte +147 -0
- package/dist/SvRowGroupPanel.svelte.d.ts +17 -0
- package/dist/SvScrollArea.svelte +50 -0
- package/dist/SvScrollArea.svelte.d.ts +22 -0
- package/dist/SvSkeleton.svelte +76 -0
- package/dist/SvSkeleton.svelte.d.ts +25 -0
- package/dist/SvSlider.svelte +41 -9
- package/dist/SvSlider.svelte.d.ts +4 -4
- package/dist/SvSparkline.svelte +77 -0
- package/dist/SvSparkline.svelte.d.ts +28 -0
- package/dist/SvSplitter.svelte +138 -0
- package/dist/SvSplitter.svelte.d.ts +32 -0
- package/dist/SvStat.svelte +86 -0
- package/dist/SvStat.svelte.d.ts +30 -0
- package/dist/SvStepper.svelte +91 -0
- package/dist/SvStepper.svelte.d.ts +24 -0
- package/dist/SvSwitchButton.svelte +39 -24
- package/dist/SvSwitchButton.svelte.d.ts +2 -5
- package/dist/SvTabs.svelte +147 -28
- package/dist/SvTabs.svelte.d.ts +16 -4
- package/dist/SvTagsInput.svelte +59 -22
- package/dist/SvTagsInput.svelte.d.ts +9 -4
- package/dist/SvTextArea.svelte +113 -0
- package/dist/SvTextArea.svelte.d.ts +18 -0
- package/dist/SvTextInput.svelte +115 -0
- package/dist/SvTextInput.svelte.d.ts +20 -0
- package/dist/SvTimePicker.svelte +19 -5
- package/dist/SvTimePicker.svelte.d.ts +12 -0
- package/dist/SvTimeline.svelte +75 -0
- package/dist/SvTimeline.svelte.d.ts +24 -0
- package/dist/SvToaster.svelte +124 -0
- package/dist/SvToaster.svelte.d.ts +10 -0
- package/dist/SvToggleButton.svelte +37 -12
- package/dist/SvToggleButton.svelte.d.ts +2 -4
- package/dist/SvTooltip.svelte +113 -0
- package/dist/SvTooltip.svelte.d.ts +22 -0
- package/dist/SvTour.svelte +151 -0
- package/dist/SvTour.svelte.d.ts +25 -0
- package/dist/SvTree.svelte +286 -44
- package/dist/SvTree.svelte.d.ts +26 -9
- package/dist/SvTreeSelect.svelte +222 -0
- package/dist/SvTreeSelect.svelte.d.ts +24 -0
- package/dist/a11y/dismissable.d.ts +32 -0
- package/dist/a11y/dismissable.js +54 -0
- package/dist/a11y/focus-trap.d.ts +39 -0
- package/dist/a11y/focus-trap.js +142 -0
- package/dist/a11y/live-region.d.ts +8 -0
- package/dist/a11y/live-region.js +60 -0
- package/dist/a11y/scroll-lock.d.ts +4 -0
- package/dist/a11y/scroll-lock.js +41 -0
- package/dist/a11y.d.ts +3 -1
- package/dist/a11y.js +1 -1
- package/dist/avatar.d.ts +10 -0
- package/dist/avatar.js +22 -0
- package/dist/builtin-editors.d.ts +5 -0
- package/dist/builtin-editors.js +55 -0
- package/dist/cdn/svgrid.js +16021 -8234
- package/dist/cdn/svgrid.svelte-external.js +14542 -6764
- package/dist/columns.js +3 -2
- package/dist/core.d.ts +7 -1
- package/dist/countries.d.ts +12 -0
- package/dist/countries.js +24 -0
- package/dist/createAccordion.svelte.d.ts +71 -0
- package/dist/createAccordion.svelte.js +99 -0
- package/dist/createAutocomplete.svelte.d.ts +13 -4
- package/dist/createAutocomplete.svelte.js +11 -1
- package/dist/createButtonGroup.svelte.d.ts +62 -0
- package/dist/createButtonGroup.svelte.js +154 -0
- package/dist/createCalendar.svelte.d.ts +5 -0
- package/dist/createCalendar.svelte.js +2 -0
- package/dist/createCheckbox.svelte.d.ts +9 -17
- package/dist/createCheckbox.svelte.js +28 -1
- package/dist/createColorInput.svelte.d.ts +12 -22
- package/dist/createColorInput.svelte.js +13 -0
- package/dist/createCombobox.svelte.d.ts +16 -5
- package/dist/createCombobox.svelte.js +13 -2
- package/dist/createCountryInput.svelte.d.ts +14 -3
- package/dist/createCountryInput.svelte.js +12 -2
- package/dist/createDateTimePicker.svelte.d.ts +17 -2
- package/dist/createDateTimePicker.svelte.js +12 -2
- package/dist/createDropdownList.svelte.d.ts +14 -5
- package/dist/createDropdownList.svelte.js +50 -1
- package/dist/createFileUpload.svelte.d.ts +68 -0
- package/dist/createFileUpload.svelte.js +122 -0
- package/dist/createListbox.svelte.d.ts +10 -1
- package/dist/createListbox.svelte.js +48 -1
- package/dist/createMaskedInput.svelte.d.ts +11 -2
- package/dist/createMaskedInput.svelte.js +11 -1
- package/dist/createNumberInput.svelte.d.ts +1 -0
- package/dist/createNumberInput.svelte.js +1 -0
- package/dist/createPasswordInput.svelte.d.ts +19 -21
- package/dist/createPasswordInput.svelte.js +16 -4
- package/dist/createPhoneInput.svelte.d.ts +26 -7
- package/dist/createPhoneInput.svelte.js +24 -3
- package/dist/createPopoverSelect.svelte.d.ts +86 -0
- package/dist/createPopoverSelect.svelte.js +196 -0
- package/dist/createRadioGroup.svelte.d.ts +9 -0
- package/dist/createRadioGroup.svelte.js +11 -1
- package/dist/createRating.svelte.d.ts +11 -0
- package/dist/createRating.svelte.js +12 -1
- package/dist/createSlider.svelte.d.ts +2 -0
- package/dist/createSlider.svelte.js +16 -5
- package/dist/createSplitter.svelte.d.ts +67 -0
- package/dist/createSplitter.svelte.js +99 -0
- package/dist/createSwitch.svelte.d.ts +9 -16
- package/dist/createSwitch.svelte.js +28 -1
- package/dist/createTabs.svelte.d.ts +7 -0
- package/dist/createTabs.svelte.js +17 -2
- package/dist/createTagsInput.svelte.d.ts +13 -1
- package/dist/createTagsInput.svelte.js +12 -3
- package/dist/createToggle.svelte.d.ts +9 -0
- package/dist/createToggle.svelte.js +12 -1
- package/dist/createTree.svelte.d.ts +19 -0
- package/dist/createTree.svelte.js +108 -15
- package/dist/debounce.d.ts +11 -0
- package/dist/debounce.js +30 -0
- package/dist/duration.d.ts +15 -0
- package/dist/duration.js +51 -0
- package/dist/editor-contract.d.ts +62 -7
- package/dist/editor-contract.js +45 -5
- package/dist/editor-registry.d.ts +67 -0
- package/dist/editor-registry.js +38 -0
- package/dist/editors/cell-editors.d.ts +1 -1
- package/dist/editors/cell-editors.js +5 -0
- package/dist/fuzzy.d.ts +3 -0
- package/dist/fuzzy.js +41 -0
- package/dist/grid-select.d.ts +9 -0
- package/dist/grid-select.js +8 -0
- package/dist/index.d.ts +79 -6
- package/dist/index.js +78 -4
- package/dist/keyboard-handlers.js +19 -0
- package/dist/list-option.d.ts +36 -0
- package/dist/list-option.js +68 -0
- package/dist/otp.d.ts +16 -0
- package/dist/otp.js +26 -0
- package/dist/paginate.d.ts +20 -0
- package/dist/paginate.js +40 -0
- package/dist/popover.d.ts +15 -1
- package/dist/popover.js +29 -3
- package/dist/recurrence.d.ts +36 -0
- package/dist/recurrence.js +90 -0
- package/dist/server-data-source.d.ts +89 -0
- package/dist/server-data-source.js +4 -0
- package/dist/server-group-model.d.ts +98 -0
- package/dist/server-group-model.js +263 -0
- package/dist/toast-store.svelte.d.ts +41 -0
- package/dist/toast-store.svelte.js +113 -0
- package/dist/tree-select.d.ts +19 -0
- package/dist/tree-select.js +40 -0
- package/dist/ui-app.types.d.ts +80 -0
- package/dist/ui-app.types.js +7 -0
- package/dist/validators.d.ts +43 -0
- package/dist/validators.js +53 -0
- package/dist/virtual.d.ts +35 -0
- package/dist/virtual.js +34 -0
- package/package.json +1 -1
- package/src/SvAccordion.svelte +109 -0
- package/src/SvAccordion.test.ts +66 -0
- package/src/SvAlert.svelte +92 -0
- package/src/SvAutoComplete.svelte +47 -18
- package/src/SvAvatar.svelte +75 -0
- package/src/SvAvatarGroup.svelte +48 -0
- package/src/SvBadge.svelte +54 -0
- package/src/SvBreadcrumb.svelte +88 -0
- package/src/SvButtonGroup.svelte +121 -0
- package/src/SvButtonGroup.test.ts +72 -0
- package/src/SvCalendar.svelte +72 -9
- package/src/SvCard.svelte +71 -0
- package/src/SvCarousel.svelte +134 -0
- package/src/SvCheckBox.svelte +36 -21
- package/src/SvChip.svelte +88 -0
- package/src/SvCircularProgress.svelte +109 -0
- package/src/SvColorInput.svelte +54 -27
- package/src/SvComboBox.svelte +119 -33
- package/src/SvCommand.svelte +197 -0
- package/src/SvContextMenu.svelte +96 -0
- package/src/SvCountryInput.svelte +56 -21
- package/src/SvDateRangeInput.svelte +256 -0
- package/src/SvDateRangeInput.test.ts +80 -0
- package/src/SvDateTimePicker.svelte +57 -20
- package/src/SvDivider.svelte +61 -0
- package/src/SvDrawer.svelte +226 -0
- package/src/SvDrawer.test.ts +125 -0
- package/src/SvDropDownList.svelte +114 -35
- package/src/SvDurationInput.svelte +108 -0
- package/src/SvEmptyState.svelte +59 -0
- package/src/SvField.svelte +85 -0
- package/src/SvFileUpload.svelte +169 -0
- package/src/SvFileUpload.test.ts +59 -0
- package/src/SvForm.svelte +7 -1
- package/src/SvGauge.svelte +7 -1
- package/src/SvGrid.controller.svelte.ts +68 -9
- package/src/SvGrid.css +33 -0
- package/src/SvGrid.svelte +116 -3
- package/src/SvGrid.types.ts +374 -0
- package/src/SvGridBoard.svelte +2281 -0
- package/src/SvGridDropdown.svelte +2 -1
- package/src/SvGridSelect.svelte +255 -0
- package/src/SvGridSelect.test.ts +100 -0
- package/src/SvGroupCell.svelte +109 -0
- package/src/SvListBox.svelte +123 -36
- package/src/SvMaskedInput.svelte +53 -13
- package/src/SvMenu.svelte +101 -0
- package/src/SvMenu.test.ts +73 -0
- package/src/SvMenuList.svelte +143 -0
- package/src/SvModal.svelte +220 -0
- package/src/SvMultiSelect.svelte +277 -0
- package/src/SvMultiSelect.test.ts +167 -0
- package/src/SvNavPane.svelte +314 -0
- package/src/SvNavPane.test.ts +70 -0
- package/src/SvNumberInput.svelte +23 -9
- package/src/SvOtpInput.svelte +157 -0
- package/src/SvPagination.svelte +100 -0
- package/src/SvPasswordInput.svelte +42 -12
- package/src/SvPhoneInput.svelte +43 -11
- package/src/SvPopover.svelte +127 -0
- package/src/SvProgress.svelte +116 -0
- package/src/SvRadioGroup.svelte +40 -22
- package/src/SvRating.svelte +51 -30
- package/src/SvRichText.svelte +192 -0
- package/src/SvRowGroupPanel.svelte +147 -0
- package/src/SvScrollArea.svelte +50 -0
- package/src/SvSkeleton.svelte +76 -0
- package/src/SvSlider.svelte +41 -9
- package/src/SvSparkline.svelte +77 -0
- package/src/SvSplitter.svelte +138 -0
- package/src/SvSplitter.test.ts +55 -0
- package/src/SvStat.svelte +86 -0
- package/src/SvStepper.svelte +91 -0
- package/src/SvSwitchButton.svelte +39 -24
- package/src/SvTabs.svelte +147 -28
- package/src/SvTagsInput.svelte +59 -22
- package/src/SvTextArea.svelte +113 -0
- package/src/SvTextInput.svelte +115 -0
- package/src/SvTimePicker.svelte +19 -5
- package/src/SvTimeline.svelte +75 -0
- package/src/SvToaster.svelte +124 -0
- package/src/SvToaster.test.ts +63 -0
- package/src/SvToggleButton.svelte +37 -12
- package/src/SvTooltip.svelte +113 -0
- package/src/SvTour.svelte +151 -0
- package/src/SvTree.svelte +286 -44
- package/src/SvTreeSelect.svelte +222 -0
- package/src/SvTreeSelect.test.ts +87 -0
- package/src/a11y/dismissable.test.ts +95 -0
- package/src/a11y/dismissable.ts +94 -0
- package/src/a11y/focus-trap.test.ts +110 -0
- package/src/a11y/focus-trap.ts +134 -0
- package/src/a11y/live-region.test.ts +40 -0
- package/src/a11y/live-region.ts +65 -0
- package/src/a11y/scroll-lock.test.ts +38 -0
- package/src/a11y/scroll-lock.ts +41 -0
- package/src/a11y.ts +3 -1
- package/src/avatar.test.ts +32 -0
- package/src/avatar.ts +21 -0
- package/src/board.test.ts +927 -0
- package/src/builtin-editors.grid.test.ts +85 -0
- package/src/builtin-editors.test.ts +58 -0
- package/src/builtin-editors.ts +56 -0
- package/src/columns.ts +3 -2
- package/src/core.ts +10 -0
- package/src/countries.ts +25 -0
- package/src/createAccordion.svelte.ts +126 -0
- package/src/createAutocomplete.svelte.ts +18 -1
- package/src/createButtonGroup.svelte.ts +166 -0
- package/src/createCalendar.svelte.ts +6 -0
- package/src/createCheckbox.svelte.ts +23 -1
- package/src/createColorInput.svelte.ts +20 -0
- package/src/createCombobox.svelte.ts +22 -2
- package/src/createCountryInput.svelte.ts +21 -2
- package/src/createDateTimePicker.svelte.ts +23 -2
- package/src/createDropdownList.svelte.ts +31 -2
- package/src/createFileUpload.svelte.ts +144 -0
- package/src/createListbox.svelte.ts +35 -3
- package/src/createMaskedInput.svelte.ts +18 -1
- package/src/createNumberInput.svelte.ts +2 -0
- package/src/createPasswordInput.svelte.ts +31 -5
- package/src/createPhoneInput.svelte.ts +38 -4
- package/src/createPopoverSelect.svelte.ts +208 -0
- package/src/createRadioGroup.svelte.ts +23 -1
- package/src/createRating.svelte.ts +26 -1
- package/src/createSlider.svelte.ts +14 -3
- package/src/createSplitter.svelte.ts +119 -0
- package/src/createSwitch.svelte.ts +26 -3
- package/src/createTabs.svelte.ts +20 -3
- package/src/createTagsInput.svelte.ts +24 -3
- package/src/createToggle.svelte.ts +25 -2
- package/src/createTree.svelte.ts +104 -14
- package/src/debounce.test.ts +50 -0
- package/src/debounce.ts +41 -0
- package/src/duration.test.ts +41 -0
- package/src/duration.ts +51 -0
- package/src/editor-contract.ts +87 -8
- package/src/editor-registry.grid.test.ts +98 -0
- package/src/editor-registry.test.ts +86 -0
- package/src/editor-registry.ts +106 -0
- package/src/editors/cell-editors.ts +10 -1
- package/src/fuzzy.test.ts +40 -0
- package/src/fuzzy.ts +39 -0
- package/src/grid-select.test.ts +28 -0
- package/src/grid-select.ts +20 -0
- package/src/index.ts +150 -5
- package/src/keyboard-handlers.ts +20 -0
- package/src/list-option.ts +74 -0
- package/src/list-power.test.ts +71 -0
- package/src/otp.test.ts +28 -0
- package/src/otp.ts +28 -0
- package/src/overlays.test.ts +85 -0
- package/src/paginate.test.ts +41 -0
- package/src/paginate.ts +61 -0
- package/src/phone-valid.test.ts +26 -0
- package/src/popover.ts +31 -3
- package/src/progress.test.ts +55 -0
- package/src/recurrence.test.ts +91 -0
- package/src/recurrence.ts +111 -0
- package/src/server-data-source.ts +102 -0
- package/src/server-group-model.test.ts +294 -0
- package/src/server-group-model.ts +370 -0
- package/src/svgrid.responsive.test.ts +72 -0
- package/src/toast-store.svelte.ts +148 -0
- package/src/toast-store.test.ts +86 -0
- package/src/tree-edit.test.ts +49 -0
- package/src/tree-filter.test.ts +56 -0
- package/src/tree-select.test.ts +48 -0
- package/src/tree-select.ts +62 -0
- package/src/ui-app.test.ts +130 -0
- package/src/ui-app.types.ts +88 -0
- package/src/ui-display.test.ts +79 -0
- package/src/ui-inputs.test.ts +1 -1
- package/src/ui-status.test.ts +141 -0
- package/src/ui-tier1.test.ts +142 -0
- package/src/ui-tier2.test.ts +124 -0
- package/src/ui-tier3.test.ts +139 -0
- package/src/validators.test.ts +58 -0
- package/src/validators.ts +105 -0
- package/src/virtual.test.ts +72 -0
- package/src/virtual.ts +67 -0
|
@@ -7,23 +7,57 @@
|
|
|
7
7
|
* One styled renderer over the headless `createDropdownList` core (state +
|
|
8
8
|
* keyboard + ARIA); only portal/measure/scroll render concerns live here.
|
|
9
9
|
*/
|
|
10
|
-
import {
|
|
11
|
-
import type
|
|
10
|
+
import { flushSync } from 'svelte'
|
|
11
|
+
import { anchoredRect, portalToBody, popIn, type AnchoredRect } from './popover'
|
|
12
|
+
import { createDismissableLayer } from './a11y/dismissable'
|
|
13
|
+
import { groupOptions, hasGroups, type ListOption } from './list-option'
|
|
14
|
+
import { virtualRange, scrollToIndex } from './virtual'
|
|
15
|
+
import SvField from './SvField.svelte'
|
|
16
|
+
import { nextEditorId, type SvEditorProps } from './editor-contract'
|
|
12
17
|
import { createDropdownList } from './createDropdownList.svelte'
|
|
13
18
|
|
|
14
|
-
type Props = {
|
|
19
|
+
type Props = SvEditorProps & {
|
|
15
20
|
options: ReadonlyArray<ListOption>
|
|
16
21
|
value?: string | number | null
|
|
17
22
|
onChange?: (value: string | number) => void
|
|
18
23
|
placeholder?: string
|
|
19
|
-
disabled?: boolean
|
|
20
|
-
name?: string
|
|
21
|
-
size?: 'sm' | 'md' | 'lg'
|
|
22
|
-
ariaLabel?: string
|
|
23
24
|
autoOpen?: boolean
|
|
25
|
+
/** Window the option list (render only visible) for large sets. */
|
|
26
|
+
virtual?: boolean
|
|
27
|
+
/** Fixed option height in px (must match the CSS). Default 34. */
|
|
28
|
+
rowHeight?: number
|
|
24
29
|
}
|
|
25
30
|
|
|
26
|
-
let {
|
|
31
|
+
let {
|
|
32
|
+
options,
|
|
33
|
+
value = null,
|
|
34
|
+
onChange,
|
|
35
|
+
placeholder = 'Select…',
|
|
36
|
+
disabled = false,
|
|
37
|
+
name,
|
|
38
|
+
size = 'md',
|
|
39
|
+
ariaLabel,
|
|
40
|
+
invalid = false,
|
|
41
|
+
required = false,
|
|
42
|
+
error,
|
|
43
|
+
label,
|
|
44
|
+
hint,
|
|
45
|
+
dir,
|
|
46
|
+
id,
|
|
47
|
+
autoOpen = false,
|
|
48
|
+
virtual = false,
|
|
49
|
+
rowHeight = 34,
|
|
50
|
+
}: Props = $props()
|
|
51
|
+
|
|
52
|
+
const autoId = nextEditorId('sv-ddl')
|
|
53
|
+
const uid = $derived(id ?? autoId)
|
|
54
|
+
|
|
55
|
+
// Virtualization applies to a flat (ungrouped) list.
|
|
56
|
+
const useVirtual = $derived(virtual && !hasGroups(options))
|
|
57
|
+
let scrollTop = $state(0)
|
|
58
|
+
let viewportH = $state(0)
|
|
59
|
+
const vr = $derived(virtualRange({ scrollTop, viewportHeight: viewportH, rowHeight, count: options.length, overscan: 10 }))
|
|
60
|
+
const windowed = $derived(useVirtual ? options.slice(vr.start, vr.end).map((o, i) => ({ ...o, index: vr.start + i })) : [])
|
|
27
61
|
|
|
28
62
|
let triggerEl = $state<HTMLButtonElement | null>(null)
|
|
29
63
|
let panelEl = $state<HTMLDivElement | null>(null)
|
|
@@ -36,6 +70,11 @@
|
|
|
36
70
|
disabled: () => disabled,
|
|
37
71
|
ariaLabel: () => ariaLabel,
|
|
38
72
|
focusTrigger: () => triggerEl?.focus(),
|
|
73
|
+
id: () => uid,
|
|
74
|
+
invalid: () => invalid,
|
|
75
|
+
required: () => required,
|
|
76
|
+
error: () => error,
|
|
77
|
+
hint: () => hint,
|
|
39
78
|
})
|
|
40
79
|
|
|
41
80
|
const selected = $derived(ddl.selected)
|
|
@@ -50,43 +89,74 @@
|
|
|
50
89
|
updatePos()
|
|
51
90
|
const rp = () => updatePos()
|
|
52
91
|
window.addEventListener('scroll', rp, true); window.addEventListener('resize', rp)
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
92
|
+
// Outside-pointer dismissal via the shared layer stack (Escape stays with
|
|
93
|
+
// the core keyboard handler). Because this layer is pushed ON TOP, a
|
|
94
|
+
// dropdown opened inside a dialog/drawer closes itself first and never
|
|
95
|
+
// dismisses the dialog underneath it.
|
|
96
|
+
const layer = createDismissableLayer({
|
|
97
|
+
element: () => [triggerEl, panelEl],
|
|
98
|
+
onDismiss: () => ddl.close(),
|
|
99
|
+
closeOnEscape: false,
|
|
100
|
+
})
|
|
101
|
+
layer.activate()
|
|
102
|
+
return () => { window.removeEventListener('scroll', rp, true); window.removeEventListener('resize', rp); layer.release() }
|
|
56
103
|
})
|
|
57
104
|
// Keep the active option scrolled into view (render concern).
|
|
58
105
|
$effect(() => {
|
|
59
106
|
if (!ddl.open) return
|
|
60
107
|
const i = ddl.activeIndex
|
|
61
|
-
|
|
108
|
+
if (useVirtual) {
|
|
109
|
+
if (!panelEl) return
|
|
110
|
+
const next = scrollToIndex(i, panelEl.scrollTop, panelEl.clientHeight, rowHeight)
|
|
111
|
+
if (next !== panelEl.scrollTop) { panelEl.scrollTop = next; scrollTop = next }
|
|
112
|
+
} else {
|
|
113
|
+
queueMicrotask(() => panelEl?.querySelector<HTMLElement>(`[data-idx="${i}"]`)?.scrollIntoView({ block: 'nearest' }))
|
|
114
|
+
}
|
|
62
115
|
})
|
|
63
116
|
function focusOpen(node: HTMLButtonElement) { if (autoOpen) { node.focus(); ddl.openPanel() } }
|
|
64
117
|
</script>
|
|
65
118
|
|
|
66
|
-
<
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
</
|
|
119
|
+
<SvField id={uid} {label} {hint} {error} {required} {dir}>
|
|
120
|
+
<button
|
|
121
|
+
bind:this={triggerEl}
|
|
122
|
+
class="sv-ddl sv-ddl--{size}"
|
|
123
|
+
class:is-open={ddl.open}
|
|
124
|
+
class:is-disabled={disabled}
|
|
125
|
+
class:is-invalid={invalid}
|
|
126
|
+
{...ddl.triggerProps()}
|
|
127
|
+
use:focusOpen
|
|
128
|
+
>
|
|
129
|
+
<span class="sv-ddl__value" class:is-placeholder={!selected}>{selected?.label ?? placeholder}</span>
|
|
130
|
+
<svg class="sv-ddl__chev" viewBox="0 0 24 24" width="15" height="15" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="m6 9 6 6 6-6" /></svg>
|
|
131
|
+
</button>
|
|
132
|
+
</SvField>
|
|
77
133
|
|
|
78
134
|
{#if ddl.open}
|
|
79
|
-
<div bind:this={panelEl} class="sv-ddl__panel" use:portalToBody style:position="fixed" style:top={`${rect.top}px`} style:left={`${rect.left}px`} style:min-width={`${rect.width}px`} {...ddl.listboxProps()}>
|
|
80
|
-
{#
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
class:is-active={ddl.isActive(
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
135
|
+
<div bind:this={panelEl} class="sv-ddl__panel" class:is-virtual={useVirtual} use:portalToBody use:popIn={{ up: rect.openUpward }} style:position="fixed" style:top={`${rect.top}px`} style:left={`${rect.left}px`} style:min-width={`${rect.width}px`} onscroll={(e) => { scrollTop = e.currentTarget.scrollTop; if (useVirtual) flushSync() }} bind:clientHeight={viewportH} {...ddl.listboxProps()}>
|
|
136
|
+
{#if useVirtual}
|
|
137
|
+
<div class="sv-ddl__sizer" aria-hidden="true" style:height={`${vr.totalHeight}px`}></div>
|
|
138
|
+
{#each windowed as opt (opt.value)}
|
|
139
|
+
<!-- svelte-ignore a11y_click_events_have_key_events a11y_interactive_supports_focus -->
|
|
140
|
+
<div class="sv-ddl__opt sv-ddl__opt--abs" style:height={`${rowHeight}px`} style:transform={`translateY(${opt.index * rowHeight}px)`} class:is-active={ddl.isActive(opt.index)} class:is-selected={ddl.isSelected(opt)} class:is-disabled={opt.disabled} {...ddl.optionProps(opt.index)}>{opt.label}</div>
|
|
141
|
+
{/each}
|
|
142
|
+
{:else}
|
|
143
|
+
{#each groupOptions(options) as g (g.group ?? '')}
|
|
144
|
+
{#if g.group != null}
|
|
145
|
+
<div class="sv-ddl__group" role="group" aria-label={g.group}>
|
|
146
|
+
<div class="sv-ddl__group-label" aria-hidden="true">{g.group}</div>
|
|
147
|
+
{#each g.options as opt (opt.value)}
|
|
148
|
+
<!-- svelte-ignore a11y_click_events_have_key_events a11y_interactive_supports_focus -->
|
|
149
|
+
<div class="sv-ddl__opt" class:is-active={ddl.isActive(opt.index)} class:is-selected={ddl.isSelected(opt)} class:is-disabled={opt.disabled} {...ddl.optionProps(opt.index)}>{opt.label}</div>
|
|
150
|
+
{/each}
|
|
151
|
+
</div>
|
|
152
|
+
{:else}
|
|
153
|
+
{#each g.options as opt (opt.value)}
|
|
154
|
+
<!-- svelte-ignore a11y_click_events_have_key_events a11y_interactive_supports_focus -->
|
|
155
|
+
<div class="sv-ddl__opt" class:is-active={ddl.isActive(opt.index)} class:is-selected={ddl.isSelected(opt)} class:is-disabled={opt.disabled} {...ddl.optionProps(opt.index)}>{opt.label}</div>
|
|
156
|
+
{/each}
|
|
157
|
+
{/if}
|
|
89
158
|
{/each}
|
|
159
|
+
{/if}
|
|
90
160
|
</div>
|
|
91
161
|
{/if}
|
|
92
162
|
{#if name}<input type="hidden" {name} value={value ?? ''} />{/if}
|
|
@@ -95,7 +165,7 @@
|
|
|
95
165
|
.sv-ddl {
|
|
96
166
|
--_accent: var(--sg-accent, #2563eb);
|
|
97
167
|
display: inline-flex; align-items: center; justify-content: space-between; gap: 8px; width: 200px;
|
|
98
|
-
background: var(--sg-input-bg, #fff); color: var(--sg-fg, #0f172a); font: inherit; text-align:
|
|
168
|
+
background: var(--sg-input-bg, #fff); color: var(--sg-fg, #0f172a); font: inherit; text-align: start;
|
|
99
169
|
border: 1px solid var(--sg-input-border, var(--sg-border, #cbd5e1)); border-radius: var(--sg-radius, 8px);
|
|
100
170
|
padding: 0 10px; cursor: pointer;
|
|
101
171
|
}
|
|
@@ -103,6 +173,8 @@
|
|
|
103
173
|
.sv-ddl--md { height: 34px; font-size: 13px; }
|
|
104
174
|
.sv-ddl--lg { height: 40px; font-size: 15px; }
|
|
105
175
|
.sv-ddl.is-open, .sv-ddl:focus-visible { border-color: var(--_accent); box-shadow: 0 0 0 2px color-mix(in srgb, var(--_accent) 22%, transparent); outline: none; }
|
|
176
|
+
.sv-ddl.is-invalid { border-color: var(--sg-danger, #dc2626); }
|
|
177
|
+
.sv-ddl.is-invalid.is-open, .sv-ddl.is-invalid:focus-visible { box-shadow: 0 0 0 2px color-mix(in srgb, var(--sg-danger, #dc2626) 22%, transparent); }
|
|
106
178
|
.sv-ddl.is-disabled { opacity: 0.6; cursor: not-allowed; }
|
|
107
179
|
.sv-ddl__value { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
|
|
108
180
|
.sv-ddl__value.is-placeholder { color: var(--sg-muted, #94a3b8); }
|
|
@@ -113,8 +185,15 @@
|
|
|
113
185
|
background: var(--sg-bg, #fff); color: var(--sg-fg, #0f172a);
|
|
114
186
|
border: 1px solid var(--sg-border, #e2e8f0); border-radius: 10px; box-shadow: 0 16px 48px -12px rgba(15,23,42,0.35);
|
|
115
187
|
}
|
|
116
|
-
:global(.sv-ddl__opt) { padding: 7px 10px; border-radius: 6px; cursor: pointer; font-size: 13px; }
|
|
188
|
+
:global(.sv-ddl__opt) { box-sizing: border-box; display: flex; align-items: center; padding: 7px 10px; border-radius: 6px; cursor: pointer; font-size: 13px; }
|
|
189
|
+
:global(.sv-ddl__panel.is-virtual) { position: fixed; will-change: scroll-position; }
|
|
190
|
+
:global(.sv-ddl__sizer) { padding: 0; margin: 0; pointer-events: none; }
|
|
191
|
+
:global(.sv-ddl__opt--abs) { position: absolute; inset-inline: 4px; top: 4px; }
|
|
117
192
|
:global(.sv-ddl__opt.is-active) { background: var(--sg-row-hover-bg, #f1f5f9); }
|
|
118
193
|
:global(.sv-ddl__opt.is-selected) { color: var(--sg-accent, #2563eb); font-weight: 600; }
|
|
119
194
|
:global(.sv-ddl__opt.is-disabled) { opacity: 0.4; cursor: not-allowed; }
|
|
195
|
+
:global(.sv-ddl__group-label) {
|
|
196
|
+
padding: 8px 10px 3px; font-size: 10.5px; font-weight: 700; text-transform: uppercase; letter-spacing: 0.04em;
|
|
197
|
+
color: var(--sg-muted, #94a3b8);
|
|
198
|
+
}
|
|
120
199
|
</style>
|
|
@@ -1,14 +1,15 @@
|
|
|
1
|
-
import type
|
|
2
|
-
type
|
|
1
|
+
import { type ListOption } from './list-option';
|
|
2
|
+
import { type SvEditorProps } from './editor-contract';
|
|
3
|
+
type Props = SvEditorProps & {
|
|
3
4
|
options: ReadonlyArray<ListOption>;
|
|
4
5
|
value?: string | number | null;
|
|
5
6
|
onChange?: (value: string | number) => void;
|
|
6
7
|
placeholder?: string;
|
|
7
|
-
disabled?: boolean;
|
|
8
|
-
name?: string;
|
|
9
|
-
size?: 'sm' | 'md' | 'lg';
|
|
10
|
-
ariaLabel?: string;
|
|
11
8
|
autoOpen?: boolean;
|
|
9
|
+
/** Window the option list (render only visible) for large sets. */
|
|
10
|
+
virtual?: boolean;
|
|
11
|
+
/** Fixed option height in px (must match the CSS). Default 34. */
|
|
12
|
+
rowHeight?: number;
|
|
12
13
|
};
|
|
13
14
|
declare const SvDropDownList: import("svelte").Component<Props, {}, "">;
|
|
14
15
|
type SvDropDownList = ReturnType<typeof SvDropDownList>;
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
/**
|
|
3
|
+
* SvDurationInput - a duration editor whose value is a number of MINUTES but
|
|
4
|
+
* which accepts the human forms people type ("1h 30m", "1:30", "90"). It shows
|
|
5
|
+
* a formatted value when unfocused and re-parses on blur / Enter. As a grid
|
|
6
|
+
* cell editor: Enter commits, Escape cancels.
|
|
7
|
+
*/
|
|
8
|
+
import SvField from './SvField.svelte'
|
|
9
|
+
import { editorAria, nextEditorId, type SvEditorProps } from './editor-contract'
|
|
10
|
+
import { parseDuration, formatDuration } from './duration'
|
|
11
|
+
|
|
12
|
+
type Props = SvEditorProps & {
|
|
13
|
+
/** Value in minutes (or null when empty). */
|
|
14
|
+
value?: number | null
|
|
15
|
+
onChange?: (minutes: number | null) => void
|
|
16
|
+
onCommit?: (minutes: number | null) => void
|
|
17
|
+
onCancel?: () => void
|
|
18
|
+
/** Display style when unfocused: `1:30` (colon) or `1h 30m` (units). */
|
|
19
|
+
style?: 'colon' | 'units'
|
|
20
|
+
placeholder?: string
|
|
21
|
+
autofocus?: boolean
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
let {
|
|
25
|
+
value = $bindable<number | null>(null),
|
|
26
|
+
onChange,
|
|
27
|
+
onCommit,
|
|
28
|
+
onCancel,
|
|
29
|
+
style = 'colon',
|
|
30
|
+
placeholder = 'e.g. 1h 30m',
|
|
31
|
+
disabled = false,
|
|
32
|
+
readonly = false,
|
|
33
|
+
name,
|
|
34
|
+
size = 'md',
|
|
35
|
+
ariaLabel,
|
|
36
|
+
invalid = false,
|
|
37
|
+
required = false,
|
|
38
|
+
error,
|
|
39
|
+
label,
|
|
40
|
+
hint,
|
|
41
|
+
dir,
|
|
42
|
+
id,
|
|
43
|
+
autofocus = false,
|
|
44
|
+
}: Props = $props()
|
|
45
|
+
|
|
46
|
+
const autoId = nextEditorId('sv-dur')
|
|
47
|
+
const uid = $derived(id ?? autoId)
|
|
48
|
+
|
|
49
|
+
let text = $state('')
|
|
50
|
+
let focused = $state(false)
|
|
51
|
+
// Reflect the external value into the field whenever the user isn't typing.
|
|
52
|
+
$effect(() => {
|
|
53
|
+
if (!focused) text = value == null ? '' : formatDuration(value, style)
|
|
54
|
+
})
|
|
55
|
+
|
|
56
|
+
function commit(): number | null {
|
|
57
|
+
const mins = parseDuration(text)
|
|
58
|
+
value = mins // enables bind:value
|
|
59
|
+
onChange?.(mins)
|
|
60
|
+
if (mins != null) text = formatDuration(mins, style)
|
|
61
|
+
return mins
|
|
62
|
+
}
|
|
63
|
+
function mountFocus(node: HTMLInputElement) {
|
|
64
|
+
if (autofocus) { node.focus(); node.select() }
|
|
65
|
+
}
|
|
66
|
+
</script>
|
|
67
|
+
|
|
68
|
+
<SvField id={uid} {label} {hint} {error} {required} {dir}>
|
|
69
|
+
<div class="sv-dur sv-dur--{size}" class:is-disabled={disabled}>
|
|
70
|
+
<div class="sv-dur__field" class:is-invalid={invalid}>
|
|
71
|
+
<input
|
|
72
|
+
use:mountFocus
|
|
73
|
+
class="sv-dur__input"
|
|
74
|
+
type="text"
|
|
75
|
+
inputmode="numeric"
|
|
76
|
+
value={text}
|
|
77
|
+
{placeholder}
|
|
78
|
+
{disabled}
|
|
79
|
+
{readonly}
|
|
80
|
+
oninput={(e) => (text = e.currentTarget.value)}
|
|
81
|
+
onfocus={() => (focused = true)}
|
|
82
|
+
onblur={() => { focused = false; commit() }}
|
|
83
|
+
onkeydown={(e) => {
|
|
84
|
+
if (e.key === 'Enter') { onCommit?.(commit()) }
|
|
85
|
+
else if (e.key === 'Escape') onCancel?.()
|
|
86
|
+
}}
|
|
87
|
+
{...editorAria({ id: uid, invalid, required, error, hint, ariaLabel })}
|
|
88
|
+
/>
|
|
89
|
+
</div>
|
|
90
|
+
{#if name}<input type="hidden" {name} value={value ?? ''} />{/if}
|
|
91
|
+
</div>
|
|
92
|
+
</SvField>
|
|
93
|
+
|
|
94
|
+
<style>
|
|
95
|
+
.sv-dur { --_accent: var(--sg-accent, #2563eb); display: inline-flex; flex-direction: column; width: 160px; }
|
|
96
|
+
.sv-dur.is-disabled { opacity: 0.6; }
|
|
97
|
+
.sv-dur__field {
|
|
98
|
+
display: flex; align-items: center;
|
|
99
|
+
background: var(--sg-input-bg, #fff); color: var(--sg-fg, #0f172a);
|
|
100
|
+
border: 1px solid var(--sg-input-border, var(--sg-border, #cbd5e1)); border-radius: var(--sg-radius, 8px);
|
|
101
|
+
}
|
|
102
|
+
.sv-dur__field:focus-within { border-color: var(--_accent); box-shadow: 0 0 0 2px color-mix(in srgb, var(--_accent) 22%, transparent); }
|
|
103
|
+
.sv-dur__field.is-invalid { border-color: var(--sg-danger, #dc2626); }
|
|
104
|
+
.sv-dur__input { flex: 1; min-width: 0; border: 0; background: none; outline: none; color: inherit; font: inherit; padding: 0 10px; }
|
|
105
|
+
.sv-dur--sm .sv-dur__field { height: 28px; font-size: 12px; }
|
|
106
|
+
.sv-dur--md .sv-dur__field { height: 34px; font-size: 13px; }
|
|
107
|
+
.sv-dur--lg .sv-dur__field { height: 40px; font-size: 15px; }
|
|
108
|
+
</style>
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { type SvEditorProps } from './editor-contract';
|
|
2
|
+
type Props = SvEditorProps & {
|
|
3
|
+
/** Value in minutes (or null when empty). */
|
|
4
|
+
value?: number | null;
|
|
5
|
+
onChange?: (minutes: number | null) => void;
|
|
6
|
+
onCommit?: (minutes: number | null) => void;
|
|
7
|
+
onCancel?: () => void;
|
|
8
|
+
/** Display style when unfocused: `1:30` (colon) or `1h 30m` (units). */
|
|
9
|
+
style?: 'colon' | 'units';
|
|
10
|
+
placeholder?: string;
|
|
11
|
+
autofocus?: boolean;
|
|
12
|
+
};
|
|
13
|
+
declare const SvDurationInput: import("svelte").Component<Props, {}, "value">;
|
|
14
|
+
type SvDurationInput = ReturnType<typeof SvDurationInput>;
|
|
15
|
+
export default SvDurationInput;
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
/**
|
|
3
|
+
* SvEmptyState - a centered placeholder for empty lists, no-results, and blank
|
|
4
|
+
* screens: an icon/illustration, a title, a description, and an action slot.
|
|
5
|
+
* Theme-driven. Parity: Smart empty / no-data states.
|
|
6
|
+
*
|
|
7
|
+
* ```svelte
|
|
8
|
+
* <SvEmptyState title="No orders yet" description="Create your first order to get going.">
|
|
9
|
+
* <SvButton>New order</SvButton>
|
|
10
|
+
* </SvEmptyState>
|
|
11
|
+
* ```
|
|
12
|
+
*/
|
|
13
|
+
import type { Snippet } from 'svelte'
|
|
14
|
+
|
|
15
|
+
type Props = {
|
|
16
|
+
title?: string
|
|
17
|
+
description?: string
|
|
18
|
+
/** Tighter padding (for empty dropdowns / small panels). */
|
|
19
|
+
compact?: boolean
|
|
20
|
+
/** Custom icon / illustration (overrides the default). */
|
|
21
|
+
icon?: Snippet
|
|
22
|
+
/** Action buttons / links. */
|
|
23
|
+
children?: Snippet
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
let { title, description, compact = false, icon, children }: Props = $props()
|
|
27
|
+
</script>
|
|
28
|
+
|
|
29
|
+
<div class="sv-empty" class:is-compact={compact}>
|
|
30
|
+
<div class="sv-empty__icon" aria-hidden="true">
|
|
31
|
+
{#if icon}
|
|
32
|
+
{@render icon()}
|
|
33
|
+
{:else}
|
|
34
|
+
<svg viewBox="0 0 48 48" width="44" height="44" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
|
35
|
+
<rect x="8" y="12" width="32" height="26" rx="3" /><path d="M8 20h32" /><path d="M16 28h10" />
|
|
36
|
+
</svg>
|
|
37
|
+
{/if}
|
|
38
|
+
</div>
|
|
39
|
+
{#if title}<div class="sv-empty__title">{title}</div>{/if}
|
|
40
|
+
{#if description}<p class="sv-empty__desc">{description}</p>{/if}
|
|
41
|
+
{#if children}<div class="sv-empty__actions">{@render children()}</div>{/if}
|
|
42
|
+
</div>
|
|
43
|
+
|
|
44
|
+
<style>
|
|
45
|
+
.sv-empty {
|
|
46
|
+
display: flex; flex-direction: column; align-items: center; text-align: center;
|
|
47
|
+
gap: 6px; padding: 44px 24px; color: var(--sg-fg, #0f172a);
|
|
48
|
+
}
|
|
49
|
+
.sv-empty.is-compact { padding: 22px 16px; }
|
|
50
|
+
.sv-empty__icon {
|
|
51
|
+
color: var(--sg-muted, #94a3b8); margin-bottom: 4px;
|
|
52
|
+
display: grid; place-items: center; width: 66px; height: 66px; border-radius: 16px;
|
|
53
|
+
background: var(--sg-row-hover-bg, #f1f5f9);
|
|
54
|
+
}
|
|
55
|
+
.sv-empty.is-compact .sv-empty__icon { width: 48px; height: 48px; }
|
|
56
|
+
.sv-empty__title { font-size: 15px; font-weight: 650; }
|
|
57
|
+
.sv-empty__desc { margin: 0; max-width: 42ch; color: var(--sg-muted, #64748b); font-size: 13px; line-height: 1.55; }
|
|
58
|
+
.sv-empty__actions { display: flex; gap: 8px; margin-top: 8px; }
|
|
59
|
+
</style>
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SvEmptyState - a centered placeholder for empty lists, no-results, and blank
|
|
3
|
+
* screens: an icon/illustration, a title, a description, and an action slot.
|
|
4
|
+
* Theme-driven. Parity: Smart empty / no-data states.
|
|
5
|
+
*
|
|
6
|
+
* ```svelte
|
|
7
|
+
* <SvEmptyState title="No orders yet" description="Create your first order to get going.">
|
|
8
|
+
* <SvButton>New order</SvButton>
|
|
9
|
+
* </SvEmptyState>
|
|
10
|
+
* ```
|
|
11
|
+
*/
|
|
12
|
+
import type { Snippet } from 'svelte';
|
|
13
|
+
type Props = {
|
|
14
|
+
title?: string;
|
|
15
|
+
description?: string;
|
|
16
|
+
/** Tighter padding (for empty dropdowns / small panels). */
|
|
17
|
+
compact?: boolean;
|
|
18
|
+
/** Custom icon / illustration (overrides the default). */
|
|
19
|
+
icon?: Snippet;
|
|
20
|
+
/** Action buttons / links. */
|
|
21
|
+
children?: Snippet;
|
|
22
|
+
};
|
|
23
|
+
declare const SvEmptyState: import("svelte").Component<Props, {}, "">;
|
|
24
|
+
type SvEmptyState = ReturnType<typeof SvEmptyState>;
|
|
25
|
+
export default SvEmptyState;
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
/**
|
|
3
|
+
* SvField - the shared field chrome for every value-bearing editor in the kit.
|
|
4
|
+
* It renders an optional `label` (wired to the control via `for`/`id`), the
|
|
5
|
+
* control itself (passed as children), and an optional `hint` / `error` line
|
|
6
|
+
* whose ids match `editorHintId` / `editorErrorId` for `aria-describedby`.
|
|
7
|
+
*
|
|
8
|
+
* Editors wrap their control box in it so label/hint/error/RTL behave
|
|
9
|
+
* IDENTICALLY across the kit:
|
|
10
|
+
*
|
|
11
|
+
* ```svelte
|
|
12
|
+
* <SvField {id} {label} {hint} {error} {required} {dir}>
|
|
13
|
+
* <div class="sv-num">...control...</div>
|
|
14
|
+
* </SvField>
|
|
15
|
+
* ```
|
|
16
|
+
*/
|
|
17
|
+
import type { Snippet } from 'svelte'
|
|
18
|
+
import { editorErrorId, editorHintId, type EditorDir } from './editor-contract'
|
|
19
|
+
|
|
20
|
+
let {
|
|
21
|
+
id,
|
|
22
|
+
label,
|
|
23
|
+
hint,
|
|
24
|
+
error,
|
|
25
|
+
required = false,
|
|
26
|
+
dir,
|
|
27
|
+
/** Stretch the field (and its control) to the container width. */
|
|
28
|
+
block = false,
|
|
29
|
+
children,
|
|
30
|
+
}: {
|
|
31
|
+
id?: string
|
|
32
|
+
label?: string
|
|
33
|
+
hint?: string
|
|
34
|
+
error?: string
|
|
35
|
+
required?: boolean
|
|
36
|
+
dir?: EditorDir
|
|
37
|
+
block?: boolean
|
|
38
|
+
children: Snippet
|
|
39
|
+
} = $props()
|
|
40
|
+
|
|
41
|
+
// 'auto'/undefined -> inherit from the document (no dir attribute).
|
|
42
|
+
const resolvedDir = $derived(dir === 'ltr' || dir === 'rtl' ? dir : undefined)
|
|
43
|
+
</script>
|
|
44
|
+
|
|
45
|
+
<div class="sv-field" class:sv-field--block={block} dir={resolvedDir}>
|
|
46
|
+
{#if label}
|
|
47
|
+
<label class="sv-field__label" for={id}>
|
|
48
|
+
{label}{#if required}<span class="sv-field__req" aria-hidden="true">*</span>{/if}
|
|
49
|
+
</label>
|
|
50
|
+
{/if}
|
|
51
|
+
{@render children()}
|
|
52
|
+
{#if error}
|
|
53
|
+
<span class="sv-field__error" id={editorErrorId(id)} role="alert">{error}</span>
|
|
54
|
+
{:else if hint}
|
|
55
|
+
<span class="sv-field__hint" id={editorHintId(id)}>{hint}</span>
|
|
56
|
+
{/if}
|
|
57
|
+
</div>
|
|
58
|
+
|
|
59
|
+
<style>
|
|
60
|
+
.sv-field {
|
|
61
|
+
display: inline-flex;
|
|
62
|
+
flex-direction: column;
|
|
63
|
+
gap: 3px;
|
|
64
|
+
text-align: start;
|
|
65
|
+
}
|
|
66
|
+
.sv-field--block { display: flex; width: 100%; }
|
|
67
|
+
.sv-field__label {
|
|
68
|
+
font-size: 12.5px;
|
|
69
|
+
font-weight: 550;
|
|
70
|
+
color: var(--sg-fg, #0f172a);
|
|
71
|
+
line-height: 1.3;
|
|
72
|
+
}
|
|
73
|
+
.sv-field__req { color: var(--sg-danger, #dc2626); margin-inline-start: 2px; }
|
|
74
|
+
.sv-field__hint {
|
|
75
|
+
font-size: 11.5px;
|
|
76
|
+
color: var(--sg-muted, #64748b);
|
|
77
|
+
line-height: 1.35;
|
|
78
|
+
}
|
|
79
|
+
.sv-field__error {
|
|
80
|
+
font-size: 11.5px;
|
|
81
|
+
font-weight: 500;
|
|
82
|
+
color: var(--sg-danger, #dc2626);
|
|
83
|
+
line-height: 1.35;
|
|
84
|
+
}
|
|
85
|
+
</style>
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SvField - the shared field chrome for every value-bearing editor in the kit.
|
|
3
|
+
* It renders an optional `label` (wired to the control via `for`/`id`), the
|
|
4
|
+
* control itself (passed as children), and an optional `hint` / `error` line
|
|
5
|
+
* whose ids match `editorHintId` / `editorErrorId` for `aria-describedby`.
|
|
6
|
+
*
|
|
7
|
+
* Editors wrap their control box in it so label/hint/error/RTL behave
|
|
8
|
+
* IDENTICALLY across the kit:
|
|
9
|
+
*
|
|
10
|
+
* ```svelte
|
|
11
|
+
* <SvField {id} {label} {hint} {error} {required} {dir}>
|
|
12
|
+
* <div class="sv-num">...control...</div>
|
|
13
|
+
* </SvField>
|
|
14
|
+
* ```
|
|
15
|
+
*/
|
|
16
|
+
import type { Snippet } from 'svelte';
|
|
17
|
+
import { type EditorDir } from './editor-contract';
|
|
18
|
+
type $$ComponentProps = {
|
|
19
|
+
id?: string;
|
|
20
|
+
label?: string;
|
|
21
|
+
hint?: string;
|
|
22
|
+
error?: string;
|
|
23
|
+
required?: boolean;
|
|
24
|
+
dir?: EditorDir;
|
|
25
|
+
block?: boolean;
|
|
26
|
+
children: Snippet;
|
|
27
|
+
};
|
|
28
|
+
declare const SvField: import("svelte").Component<$$ComponentProps, {}, "">;
|
|
29
|
+
type SvField = ReturnType<typeof SvField>;
|
|
30
|
+
export default SvField;
|