@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
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
<script lang="ts" module>
|
|
2
|
+
export type { MenuItem } from './SvMenuList.svelte'
|
|
3
|
+
</script>
|
|
4
|
+
|
|
5
|
+
<script lang="ts">
|
|
6
|
+
/**
|
|
7
|
+
* SvContextMenu - wraps a region and opens a menu at the pointer on right-click
|
|
8
|
+
* (or long-press). Reuses SvMenuList (submenus, keyboard, icons, shortcuts),
|
|
9
|
+
* portals to <body>, and closes via the shared dismissable layer stack.
|
|
10
|
+
* Parity: Smart context-menu.
|
|
11
|
+
*
|
|
12
|
+
* ```svelte
|
|
13
|
+
* <SvContextMenu items={items} onSelect={(i) => run(i)}>
|
|
14
|
+
* <div class="drop-zone">Right-click me</div>
|
|
15
|
+
* </SvContextMenu>
|
|
16
|
+
* ```
|
|
17
|
+
*/
|
|
18
|
+
import type { Snippet } from 'svelte'
|
|
19
|
+
import { portalToBody, popIn } from './popover'
|
|
20
|
+
import { createDismissableLayer } from './a11y/dismissable'
|
|
21
|
+
import SvMenuList, { type MenuItem } from './SvMenuList.svelte'
|
|
22
|
+
|
|
23
|
+
type Props = {
|
|
24
|
+
items: ReadonlyArray<MenuItem>
|
|
25
|
+
onSelect?: (item: MenuItem) => void
|
|
26
|
+
disabled?: boolean
|
|
27
|
+
ariaLabel?: string
|
|
28
|
+
children?: Snippet
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
let { items, onSelect, disabled = false, ariaLabel, children }: Props = $props()
|
|
32
|
+
|
|
33
|
+
let open = $state(false)
|
|
34
|
+
let pos = $state({ x: 0, y: 0 })
|
|
35
|
+
let panelEl = $state<HTMLDivElement | null>(null)
|
|
36
|
+
|
|
37
|
+
const MENU_W = 200
|
|
38
|
+
function openAt(clientX: number, clientY: number) {
|
|
39
|
+
// Clamp so the menu stays on-screen (estimate height from item count).
|
|
40
|
+
const estH = Math.min(items.length, 12) * 34 + 8
|
|
41
|
+
const x = Math.min(clientX, window.innerWidth - MENU_W - 6)
|
|
42
|
+
const y = Math.min(clientY, window.innerHeight - estH - 6)
|
|
43
|
+
pos = { x: Math.max(6, x), y: Math.max(6, y) }
|
|
44
|
+
open = true
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
function onContextMenu(e: MouseEvent) {
|
|
48
|
+
if (disabled) return
|
|
49
|
+
e.preventDefault()
|
|
50
|
+
openAt(e.clientX, e.clientY)
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
$effect(() => {
|
|
54
|
+
if (!open) return
|
|
55
|
+
queueMicrotask(() => panelEl?.querySelector<HTMLElement>('[role="menuitem"]:not([disabled])')?.focus())
|
|
56
|
+
const layer = createDismissableLayer({
|
|
57
|
+
element: () => panelEl,
|
|
58
|
+
onDismiss: () => (open = false),
|
|
59
|
+
})
|
|
60
|
+
layer.activate()
|
|
61
|
+
// Reposition-close on scroll (a moved anchor would leave the menu stranded).
|
|
62
|
+
const onScroll = () => (open = false)
|
|
63
|
+
window.addEventListener('scroll', onScroll, true)
|
|
64
|
+
return () => { layer.release(); window.removeEventListener('scroll', onScroll, true) }
|
|
65
|
+
})
|
|
66
|
+
</script>
|
|
67
|
+
|
|
68
|
+
<!-- svelte-ignore a11y_no_static_element_interactions -->
|
|
69
|
+
<div class="sv-ctx__zone" oncontextmenu={onContextMenu}>
|
|
70
|
+
{@render children?.()}
|
|
71
|
+
</div>
|
|
72
|
+
|
|
73
|
+
{#if open}
|
|
74
|
+
<div
|
|
75
|
+
bind:this={panelEl}
|
|
76
|
+
class="sv-ctx"
|
|
77
|
+
use:portalToBody
|
|
78
|
+
use:popIn={{}}
|
|
79
|
+
style:position="fixed"
|
|
80
|
+
style:top={`${pos.y}px`}
|
|
81
|
+
style:left={`${pos.x}px`}
|
|
82
|
+
aria-label={ariaLabel}
|
|
83
|
+
>
|
|
84
|
+
<SvMenuList {items} onclose={() => (open = false)} onselect={(i) => onSelect?.(i)} />
|
|
85
|
+
</div>
|
|
86
|
+
{/if}
|
|
87
|
+
|
|
88
|
+
<style>
|
|
89
|
+
.sv-ctx__zone { display: contents; }
|
|
90
|
+
:global(.sv-ctx) {
|
|
91
|
+
z-index: 2147483646; min-width: 200px;
|
|
92
|
+
background: var(--sg-bg, #fff); color: var(--sg-fg, #0f172a);
|
|
93
|
+
border: 1px solid var(--sg-border, #e2e8f0); border-radius: 10px;
|
|
94
|
+
box-shadow: 0 16px 48px -12px rgba(15, 23, 42, 0.35); font-size: 13px;
|
|
95
|
+
}
|
|
96
|
+
</style>
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
export type { MenuItem } from './SvMenuList.svelte';
|
|
2
|
+
/**
|
|
3
|
+
* SvContextMenu - wraps a region and opens a menu at the pointer on right-click
|
|
4
|
+
* (or long-press). Reuses SvMenuList (submenus, keyboard, icons, shortcuts),
|
|
5
|
+
* portals to <body>, and closes via the shared dismissable layer stack.
|
|
6
|
+
* Parity: Smart context-menu.
|
|
7
|
+
*
|
|
8
|
+
* ```svelte
|
|
9
|
+
* <SvContextMenu items={items} onSelect={(i) => run(i)}>
|
|
10
|
+
* <div class="drop-zone">Right-click me</div>
|
|
11
|
+
* </SvContextMenu>
|
|
12
|
+
* ```
|
|
13
|
+
*/
|
|
14
|
+
import type { Snippet } from 'svelte';
|
|
15
|
+
import { type MenuItem } from './SvMenuList.svelte';
|
|
16
|
+
type Props = {
|
|
17
|
+
items: ReadonlyArray<MenuItem>;
|
|
18
|
+
onSelect?: (item: MenuItem) => void;
|
|
19
|
+
disabled?: boolean;
|
|
20
|
+
ariaLabel?: string;
|
|
21
|
+
children?: Snippet;
|
|
22
|
+
};
|
|
23
|
+
declare const SvContextMenu: import("svelte").Component<Props, {}, "">;
|
|
24
|
+
type SvContextMenu = ReturnType<typeof SvContextMenu>;
|
|
25
|
+
export default SvContextMenu;
|
|
@@ -8,23 +8,48 @@
|
|
|
8
8
|
* roving active index + keyboard); only portal/measure/focus render concerns
|
|
9
9
|
* live here.
|
|
10
10
|
*/
|
|
11
|
-
import { anchoredRect, portalToBody, type AnchoredRect } from './popover'
|
|
11
|
+
import { anchoredRect, portalToBody, popIn, type AnchoredRect } from './popover'
|
|
12
12
|
import { flagEmoji } from './countries'
|
|
13
|
+
import SvField from './SvField.svelte'
|
|
14
|
+
import { nextEditorId, resolveMessages, type SvEditorProps } from './editor-contract'
|
|
13
15
|
import { createCountryInput } from './createCountryInput.svelte'
|
|
14
16
|
|
|
15
|
-
|
|
17
|
+
/** User-facing strings (localizable via `messages`). */
|
|
18
|
+
type CountryMessages = { search: string; noResults: string }
|
|
19
|
+
const DEFAULT_MESSAGES: CountryMessages = { search: 'Search countries', noResults: 'No matches' }
|
|
20
|
+
|
|
21
|
+
type Props = SvEditorProps & {
|
|
16
22
|
value?: string | null
|
|
17
23
|
onChange?: (code: string) => void
|
|
18
24
|
/** Show the dial code beside each country. */
|
|
19
25
|
showDial?: boolean
|
|
20
26
|
placeholder?: string
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
size?: 'sm' | 'md' | 'lg'
|
|
24
|
-
ariaLabel?: string
|
|
27
|
+
/** Override the built-in strings (search + empty-state). */
|
|
28
|
+
messages?: Partial<CountryMessages>
|
|
25
29
|
}
|
|
26
30
|
|
|
27
|
-
let {
|
|
31
|
+
let {
|
|
32
|
+
value = null,
|
|
33
|
+
onChange,
|
|
34
|
+
showDial = false,
|
|
35
|
+
placeholder = 'Select country…',
|
|
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
|
+
messages,
|
|
48
|
+
}: Props = $props()
|
|
49
|
+
|
|
50
|
+
const autoId = nextEditorId('sv-country')
|
|
51
|
+
const uid = $derived(id ?? autoId)
|
|
52
|
+
const M = $derived(resolveMessages(DEFAULT_MESSAGES, messages))
|
|
28
53
|
|
|
29
54
|
let triggerEl = $state<HTMLButtonElement | null>(null)
|
|
30
55
|
let searchEl = $state<HTMLInputElement | null>(null)
|
|
@@ -36,7 +61,13 @@
|
|
|
36
61
|
onChange: (c) => onChange?.(c),
|
|
37
62
|
disabled: () => disabled,
|
|
38
63
|
ariaLabel: () => ariaLabel,
|
|
64
|
+
searchLabel: () => M.search,
|
|
39
65
|
focusTrigger: () => triggerEl?.focus(),
|
|
66
|
+
id: () => uid,
|
|
67
|
+
invalid: () => invalid,
|
|
68
|
+
required: () => required,
|
|
69
|
+
error: () => error,
|
|
70
|
+
hint: () => hint,
|
|
40
71
|
})
|
|
41
72
|
|
|
42
73
|
const selected = $derived(ci.selected)
|
|
@@ -61,20 +92,22 @@
|
|
|
61
92
|
})
|
|
62
93
|
</script>
|
|
63
94
|
|
|
64
|
-
<
|
|
65
|
-
{
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
95
|
+
<SvField id={uid} {label} {hint} {error} {required} {dir}>
|
|
96
|
+
<button bind:this={triggerEl} class="sv-country sv-country--{size}" class:is-open={ci.open} class:is-disabled={disabled} class:is-invalid={invalid} {...ci.triggerProps()}>
|
|
97
|
+
{#if selected}
|
|
98
|
+
<span class="sv-country__flag" aria-hidden="true">{flagEmoji(selected.code)}</span>
|
|
99
|
+
<span class="sv-country__name">{selected.name}</span>
|
|
100
|
+
{#if showDial}<span class="sv-country__dial">{selected.dial}</span>{/if}
|
|
101
|
+
{:else}
|
|
102
|
+
<span class="sv-country__ph">{placeholder}</span>
|
|
103
|
+
{/if}
|
|
104
|
+
<svg class="sv-country__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>
|
|
105
|
+
</button>
|
|
106
|
+
</SvField>
|
|
74
107
|
|
|
75
108
|
{#if ci.open}
|
|
76
|
-
<div bind:this={panelEl} class="sv-country__panel" use:portalToBody style:position="fixed" style:top={`${rect.top}px`} style:left={`${rect.left}px`} style:min-width={`${rect.width}px`} role="dialog">
|
|
77
|
-
<input bind:this={searchEl} class="sv-country__search" placeholder=
|
|
109
|
+
<div bind:this={panelEl} class="sv-country__panel" 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`} role="dialog">
|
|
110
|
+
<input bind:this={searchEl} class="sv-country__search" placeholder={`${M.search}…`} {...ci.searchProps()} />
|
|
78
111
|
<div class="sv-country__list" {...ci.listboxProps()}>
|
|
79
112
|
{#each ci.filtered as c, i (c.code)}
|
|
80
113
|
<!-- svelte-ignore a11y_click_events_have_key_events a11y_interactive_supports_focus -->
|
|
@@ -84,7 +117,7 @@
|
|
|
84
117
|
<span class="sv-country__dial">{c.dial}</span>
|
|
85
118
|
</div>
|
|
86
119
|
{:else}
|
|
87
|
-
<div class="sv-ddl__empty">
|
|
120
|
+
<div class="sv-ddl__empty">{M.noResults}</div>
|
|
88
121
|
{/each}
|
|
89
122
|
</div>
|
|
90
123
|
</div>
|
|
@@ -95,13 +128,15 @@
|
|
|
95
128
|
.sv-country {
|
|
96
129
|
--_accent: var(--sg-accent, #2563eb);
|
|
97
130
|
display: inline-flex; align-items: center; gap: 8px; width: 220px;
|
|
98
|
-
background: var(--sg-input-bg, #fff); color: var(--sg-fg, #0f172a); font: inherit; text-align:
|
|
131
|
+
background: var(--sg-input-bg, #fff); color: var(--sg-fg, #0f172a); font: inherit; text-align: start;
|
|
99
132
|
border: 1px solid var(--sg-input-border, var(--sg-border, #cbd5e1)); border-radius: var(--sg-radius, 8px); padding: 0 10px; cursor: pointer;
|
|
100
133
|
}
|
|
101
134
|
.sv-country--sm { height: 28px; font-size: 12px; }
|
|
102
135
|
.sv-country--md { height: 34px; font-size: 13px; }
|
|
103
136
|
.sv-country--lg { height: 40px; font-size: 15px; }
|
|
104
137
|
.sv-country.is-open, .sv-country:focus-visible { border-color: var(--_accent); box-shadow: 0 0 0 2px color-mix(in srgb, var(--_accent) 22%, transparent); outline: none; }
|
|
138
|
+
.sv-country.is-invalid { border-color: var(--sg-danger, #dc2626); }
|
|
139
|
+
.sv-country.is-invalid.is-open, .sv-country.is-invalid:focus-visible { box-shadow: 0 0 0 2px color-mix(in srgb, var(--sg-danger, #dc2626) 22%, transparent); }
|
|
105
140
|
.sv-country.is-disabled { opacity: 0.6; cursor: not-allowed; }
|
|
106
141
|
.sv-country__flag { font-size: 16px; }
|
|
107
142
|
.sv-country__name { flex: 1; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
|
|
@@ -1,13 +1,17 @@
|
|
|
1
|
-
type
|
|
1
|
+
import { type SvEditorProps } from './editor-contract';
|
|
2
|
+
/** User-facing strings (localizable via `messages`). */
|
|
3
|
+
type CountryMessages = {
|
|
4
|
+
search: string;
|
|
5
|
+
noResults: string;
|
|
6
|
+
};
|
|
7
|
+
type Props = SvEditorProps & {
|
|
2
8
|
value?: string | null;
|
|
3
9
|
onChange?: (code: string) => void;
|
|
4
10
|
/** Show the dial code beside each country. */
|
|
5
11
|
showDial?: boolean;
|
|
6
12
|
placeholder?: string;
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
size?: 'sm' | 'md' | 'lg';
|
|
10
|
-
ariaLabel?: string;
|
|
13
|
+
/** Override the built-in strings (search + empty-state). */
|
|
14
|
+
messages?: Partial<CountryMessages>;
|
|
11
15
|
};
|
|
12
16
|
declare const SvCountryInput: import("svelte").Component<Props, {}, "">;
|
|
13
17
|
type SvCountryInput = ReturnType<typeof SvCountryInput>;
|
|
@@ -0,0 +1,256 @@
|
|
|
1
|
+
<script lang="ts" module>
|
|
2
|
+
export type DateRangeValue = [Date, Date] | null
|
|
3
|
+
</script>
|
|
4
|
+
|
|
5
|
+
<script lang="ts">
|
|
6
|
+
/**
|
|
7
|
+
* SvDateRangeInput - a start/end date-range field with a portalled two-month
|
|
8
|
+
* range calendar and one-click presets (Today, Last 7 days, This month, ...).
|
|
9
|
+
* Parity target: Smart date-range pickers. Emits `[start, end]` (inclusive) or
|
|
10
|
+
* null. It composes the existing headless range engine: the popover is just a
|
|
11
|
+
* `<SvCalendar selectionMode="range">`, so hover-preview, min/max, restricted /
|
|
12
|
+
* important dates and keyboard all come for free.
|
|
13
|
+
*
|
|
14
|
+
* Part of the SvGrid editor kit: carries the shared editor contract (label,
|
|
15
|
+
* hint, error/validation a11y, size, `dir`/RTL and localizable `messages`) via
|
|
16
|
+
* `<SvField>`, exactly like the other field editors.
|
|
17
|
+
*/
|
|
18
|
+
import SvCalendar from './SvCalendar.svelte'
|
|
19
|
+
import SvField from './SvField.svelte'
|
|
20
|
+
import { anchoredRect, portalToBody, popIn, type AnchoredRect } from './popover'
|
|
21
|
+
import { editorAria, nextEditorId, resolveMessages, type SvEditorProps } from './editor-contract'
|
|
22
|
+
import { formatDate } from './datetime/date-format'
|
|
23
|
+
import { toDate, startOfDay, type DateLike } from './datetime/date-core'
|
|
24
|
+
import { rangeDays } from './datetime/date-selection'
|
|
25
|
+
import type { CalendarPreset } from './createCalendar.svelte'
|
|
26
|
+
|
|
27
|
+
/** User-facing strings (localizable via `messages`). */
|
|
28
|
+
type RangeMessages = { dialog: string; clear: string; open: string; to: string }
|
|
29
|
+
const DEFAULT_MESSAGES: RangeMessages = {
|
|
30
|
+
dialog: 'Choose a date range', clear: 'Clear', open: 'Open calendar', to: 'to',
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
type Props = SvEditorProps & {
|
|
34
|
+
/** Inclusive [start, end] range, or null. */
|
|
35
|
+
value?: DateRangeValue
|
|
36
|
+
onChange?: (value: DateRangeValue) => void
|
|
37
|
+
/** Display format for each end (token engine, e.g. 'yyyy-MM-dd'). */
|
|
38
|
+
formatString?: string
|
|
39
|
+
min?: DateLike | null
|
|
40
|
+
max?: DateLike | null
|
|
41
|
+
/** Number of month panels shown side by side. Default 2. */
|
|
42
|
+
months?: number
|
|
43
|
+
firstDayOfWeek?: number
|
|
44
|
+
weekNumbers?: boolean
|
|
45
|
+
locale?: string
|
|
46
|
+
placeholder?: string
|
|
47
|
+
/** Quick shortcuts shown in the calendar's side rail. */
|
|
48
|
+
presets?: ReadonlyArray<CalendarPreset>
|
|
49
|
+
/** Animate the calendar's month navigation. */
|
|
50
|
+
animate?: boolean | 'slide' | 'fade'
|
|
51
|
+
/** Open the popover as soon as the field is focused. */
|
|
52
|
+
autoOpen?: boolean
|
|
53
|
+
/** Override the built-in strings. */
|
|
54
|
+
messages?: Partial<RangeMessages>
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
let {
|
|
58
|
+
value = null,
|
|
59
|
+
onChange,
|
|
60
|
+
formatString = 'yyyy-MM-dd',
|
|
61
|
+
min = null,
|
|
62
|
+
max = null,
|
|
63
|
+
months = 2,
|
|
64
|
+
firstDayOfWeek = 0,
|
|
65
|
+
weekNumbers = false,
|
|
66
|
+
locale = typeof navigator !== 'undefined' ? navigator.language : 'en-US',
|
|
67
|
+
placeholder = 'Select date range',
|
|
68
|
+
presets,
|
|
69
|
+
animate = false,
|
|
70
|
+
autoOpen = false,
|
|
71
|
+
disabled = false,
|
|
72
|
+
readonly = false,
|
|
73
|
+
name,
|
|
74
|
+
size = 'md',
|
|
75
|
+
ariaLabel,
|
|
76
|
+
invalid = false,
|
|
77
|
+
required = false,
|
|
78
|
+
error,
|
|
79
|
+
label,
|
|
80
|
+
hint,
|
|
81
|
+
dir,
|
|
82
|
+
id,
|
|
83
|
+
messages,
|
|
84
|
+
}: Props = $props()
|
|
85
|
+
|
|
86
|
+
const autoId = nextEditorId('sv-daterange')
|
|
87
|
+
const uid = $derived(id ?? autoId)
|
|
88
|
+
const M = $derived(resolveMessages(DEFAULT_MESSAGES, messages))
|
|
89
|
+
const resolvedDir = $derived(dir === 'ltr' || dir === 'rtl' ? dir : undefined)
|
|
90
|
+
const isInteractive = $derived(!disabled && !readonly)
|
|
91
|
+
|
|
92
|
+
const fmt = (d: Date) => formatDate(d, formatString, locale)
|
|
93
|
+
// The label shown in the field: "start to end", one end, or the placeholder.
|
|
94
|
+
const display = $derived.by(() => {
|
|
95
|
+
if (!value) return ''
|
|
96
|
+
const [a, b] = value
|
|
97
|
+
return a && b ? `${fmt(a)} ${M.to} ${fmt(b)}` : a ? fmt(a) : ''
|
|
98
|
+
})
|
|
99
|
+
// The calendar wants the FULL inclusive span as its value (every day renders
|
|
100
|
+
// selected); we only keep the two endpoints.
|
|
101
|
+
const calValue = $derived(value ? rangeDays(value[0], value[1]) : null)
|
|
102
|
+
|
|
103
|
+
let open = $state(false)
|
|
104
|
+
function openPanel() { if (isInteractive && !open) open = true }
|
|
105
|
+
function closePanel() { open = false }
|
|
106
|
+
function toggle() { open ? closePanel() : openPanel() }
|
|
107
|
+
function clear() { onChange?.(null) }
|
|
108
|
+
|
|
109
|
+
function onCalendarChange(dates: Date[]) {
|
|
110
|
+
if (!dates.length) return
|
|
111
|
+
const start = dates[0]!
|
|
112
|
+
const end = dates[dates.length - 1]!
|
|
113
|
+
onChange?.([startOfDay(start), startOfDay(end)])
|
|
114
|
+
// A completed range (2+ distinct days, or a single-day range) closes the panel.
|
|
115
|
+
if (dates.length >= 1 && start !== end) closePanel()
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
// --- Portalled popover positioning (DOM-bound; stays in the component) -------
|
|
119
|
+
let triggerEl = $state<HTMLDivElement | null>(null)
|
|
120
|
+
let panelEl = $state<HTMLDivElement | null>(null)
|
|
121
|
+
let panelRect = $state<AnchoredRect>({ top: 0, left: 0, width: 0, openUpward: false })
|
|
122
|
+
|
|
123
|
+
function updatePos() {
|
|
124
|
+
if (!triggerEl) return
|
|
125
|
+
panelRect = anchoredRect(triggerEl.getBoundingClientRect(), { estimatedHeight: 360, minWidth: 300 })
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
$effect(() => {
|
|
129
|
+
if (!open) return
|
|
130
|
+
updatePos()
|
|
131
|
+
const reposition = () => updatePos()
|
|
132
|
+
window.addEventListener('scroll', reposition, true)
|
|
133
|
+
window.addEventListener('resize', reposition)
|
|
134
|
+
const onDown = (e: PointerEvent) => {
|
|
135
|
+
const t = e.target as Node | null
|
|
136
|
+
if (!t) return
|
|
137
|
+
if (triggerEl?.contains(t) || panelEl?.contains(t)) return
|
|
138
|
+
closePanel()
|
|
139
|
+
}
|
|
140
|
+
document.addEventListener('pointerdown', onDown, true)
|
|
141
|
+
return () => {
|
|
142
|
+
window.removeEventListener('scroll', reposition, true)
|
|
143
|
+
window.removeEventListener('resize', reposition)
|
|
144
|
+
document.removeEventListener('pointerdown', onDown, true)
|
|
145
|
+
}
|
|
146
|
+
})
|
|
147
|
+
|
|
148
|
+
function onFieldKeydown(e: KeyboardEvent) {
|
|
149
|
+
if (e.key === 'Escape') { closePanel() }
|
|
150
|
+
else if (e.key === 'ArrowDown' && (e.altKey || !value)) { e.preventDefault(); openPanel() }
|
|
151
|
+
}
|
|
152
|
+
function focusOpen(node: HTMLInputElement) {
|
|
153
|
+
if (!autoOpen) return
|
|
154
|
+
node.focus()
|
|
155
|
+
openPanel()
|
|
156
|
+
}
|
|
157
|
+
</script>
|
|
158
|
+
|
|
159
|
+
<SvField id={uid} {label} {hint} {error} {required} {dir}>
|
|
160
|
+
<div class="sv-dri" class:sv-dri--disabled={disabled}>
|
|
161
|
+
<div class="sv-dri__field sv-dri__field--{size}" class:is-invalid={invalid} bind:this={triggerEl} dir={resolvedDir}>
|
|
162
|
+
<svg class="sv-dri__icon" viewBox="0 0 24 24" width="15" height="15" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><rect x="3" y="4" width="18" height="18" rx="2" /><path d="M16 2v4M8 2v4M3 10h18" /></svg>
|
|
163
|
+
<input
|
|
164
|
+
id={uid}
|
|
165
|
+
class="sv-dri__input"
|
|
166
|
+
type="text"
|
|
167
|
+
readonly
|
|
168
|
+
{placeholder}
|
|
169
|
+
value={display}
|
|
170
|
+
{disabled}
|
|
171
|
+
{...editorAria({ id: uid, invalid, required, error, hint, ariaLabel })}
|
|
172
|
+
aria-haspopup="dialog"
|
|
173
|
+
aria-expanded={open}
|
|
174
|
+
onclick={() => isInteractive && toggle()}
|
|
175
|
+
onkeydown={onFieldKeydown}
|
|
176
|
+
use:focusOpen
|
|
177
|
+
/>
|
|
178
|
+
{#if value && isInteractive}
|
|
179
|
+
<button type="button" class="sv-dri__clear" aria-label={M.clear} onclick={(e) => { e.stopPropagation(); clear() }}>×</button>
|
|
180
|
+
{/if}
|
|
181
|
+
</div>
|
|
182
|
+
|
|
183
|
+
{#if open}
|
|
184
|
+
<div
|
|
185
|
+
class="sv-dri__panel"
|
|
186
|
+
bind:this={panelEl}
|
|
187
|
+
use:portalToBody
|
|
188
|
+
use:popIn={{ up: panelRect.openUpward }}
|
|
189
|
+
style:position="fixed"
|
|
190
|
+
style:top={`${panelRect.top}px`}
|
|
191
|
+
style:left={`${panelRect.left}px`}
|
|
192
|
+
role="dialog"
|
|
193
|
+
aria-label={M.dialog}
|
|
194
|
+
dir={resolvedDir}
|
|
195
|
+
>
|
|
196
|
+
<SvCalendar
|
|
197
|
+
value={calValue}
|
|
198
|
+
selectionMode="range"
|
|
199
|
+
{min}
|
|
200
|
+
{max}
|
|
201
|
+
{months}
|
|
202
|
+
{firstDayOfWeek}
|
|
203
|
+
{weekNumbers}
|
|
204
|
+
{locale}
|
|
205
|
+
{presets}
|
|
206
|
+
{animate}
|
|
207
|
+
dir={resolvedDir}
|
|
208
|
+
onChange={onCalendarChange}
|
|
209
|
+
/>
|
|
210
|
+
</div>
|
|
211
|
+
{/if}
|
|
212
|
+
|
|
213
|
+
{#if name}
|
|
214
|
+
<input type="hidden" name={`${name}_start`} value={value?.[0] ? value[0].toISOString() : ''} />
|
|
215
|
+
<input type="hidden" name={`${name}_end`} value={value?.[1] ? value[1].toISOString() : ''} />
|
|
216
|
+
{/if}
|
|
217
|
+
</div>
|
|
218
|
+
</SvField>
|
|
219
|
+
|
|
220
|
+
<style>
|
|
221
|
+
.sv-dri {
|
|
222
|
+
--_accent: var(--sg-accent, #2563eb);
|
|
223
|
+
--_border: var(--sg-input-border, var(--sg-border, #cbd5e1));
|
|
224
|
+
--_radius: var(--sg-radius, 8px);
|
|
225
|
+
display: inline-block; position: relative; color: var(--sg-fg, #0f172a);
|
|
226
|
+
}
|
|
227
|
+
.sv-dri--disabled { opacity: 0.6; }
|
|
228
|
+
.sv-dri__field {
|
|
229
|
+
display: flex; align-items: center; gap: 6px; width: 260px;
|
|
230
|
+
background: var(--sg-input-bg, #fff); border: 1px solid var(--_border); border-radius: var(--_radius);
|
|
231
|
+
padding-inline: 10px 4px;
|
|
232
|
+
}
|
|
233
|
+
.sv-dri__field:focus-within { border-color: var(--_accent); box-shadow: 0 0 0 2px color-mix(in srgb, var(--_accent) 22%, transparent); }
|
|
234
|
+
.sv-dri__field.is-invalid { border-color: var(--sg-danger, #dc2626); }
|
|
235
|
+
.sv-dri__field.is-invalid:focus-within { box-shadow: 0 0 0 2px color-mix(in srgb, var(--sg-danger, #dc2626) 22%, transparent); }
|
|
236
|
+
.sv-dri__field--sm { height: 28px; font-size: 12px; }
|
|
237
|
+
.sv-dri__field--md { height: 34px; font-size: 13px; }
|
|
238
|
+
.sv-dri__field--lg { height: 40px; font-size: 15px; }
|
|
239
|
+
.sv-dri__icon { color: var(--sg-muted, #64748b); flex: none; }
|
|
240
|
+
.sv-dri__input {
|
|
241
|
+
flex: 1; min-width: 0; border: 0; background: none; outline: none; color: inherit; font: inherit;
|
|
242
|
+
cursor: pointer; text-overflow: ellipsis;
|
|
243
|
+
}
|
|
244
|
+
.sv-dri__input::placeholder { color: var(--sg-muted, #94a3b8); }
|
|
245
|
+
.sv-dri__clear {
|
|
246
|
+
display: grid; place-items: center; width: 24px; height: 24px; flex: none;
|
|
247
|
+
background: none; border: 0; color: var(--sg-muted, #64748b); cursor: pointer; border-radius: 6px; font-size: 17px; line-height: 1;
|
|
248
|
+
}
|
|
249
|
+
.sv-dri__clear:hover { color: var(--_accent); background: color-mix(in srgb, var(--_accent) 10%, transparent); }
|
|
250
|
+
|
|
251
|
+
:global(.sv-dri__panel) {
|
|
252
|
+
z-index: 2147483647;
|
|
253
|
+
background: var(--sg-bg, #fff); border: 1px solid var(--sg-border, #e2e8f0);
|
|
254
|
+
border-radius: 12px; box-shadow: 0 16px 48px -12px rgba(15, 23, 42, 0.35);
|
|
255
|
+
}
|
|
256
|
+
</style>
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
export type DateRangeValue = [Date, Date] | null;
|
|
2
|
+
import { type SvEditorProps } from './editor-contract';
|
|
3
|
+
import { type DateLike } from './datetime/date-core';
|
|
4
|
+
import type { CalendarPreset } from './createCalendar.svelte';
|
|
5
|
+
/** User-facing strings (localizable via `messages`). */
|
|
6
|
+
type RangeMessages = {
|
|
7
|
+
dialog: string;
|
|
8
|
+
clear: string;
|
|
9
|
+
open: string;
|
|
10
|
+
to: string;
|
|
11
|
+
};
|
|
12
|
+
type Props = SvEditorProps & {
|
|
13
|
+
/** Inclusive [start, end] range, or null. */
|
|
14
|
+
value?: DateRangeValue;
|
|
15
|
+
onChange?: (value: DateRangeValue) => void;
|
|
16
|
+
/** Display format for each end (token engine, e.g. 'yyyy-MM-dd'). */
|
|
17
|
+
formatString?: string;
|
|
18
|
+
min?: DateLike | null;
|
|
19
|
+
max?: DateLike | null;
|
|
20
|
+
/** Number of month panels shown side by side. Default 2. */
|
|
21
|
+
months?: number;
|
|
22
|
+
firstDayOfWeek?: number;
|
|
23
|
+
weekNumbers?: boolean;
|
|
24
|
+
locale?: string;
|
|
25
|
+
placeholder?: string;
|
|
26
|
+
/** Quick shortcuts shown in the calendar's side rail. */
|
|
27
|
+
presets?: ReadonlyArray<CalendarPreset>;
|
|
28
|
+
/** Animate the calendar's month navigation. */
|
|
29
|
+
animate?: boolean | 'slide' | 'fade';
|
|
30
|
+
/** Open the popover as soon as the field is focused. */
|
|
31
|
+
autoOpen?: boolean;
|
|
32
|
+
/** Override the built-in strings. */
|
|
33
|
+
messages?: Partial<RangeMessages>;
|
|
34
|
+
};
|
|
35
|
+
declare const SvDateRangeInput: import("svelte").Component<Props, {}, "">;
|
|
36
|
+
type SvDateRangeInput = ReturnType<typeof SvDateRangeInput>;
|
|
37
|
+
export default SvDateRangeInput;
|