@svgrid/grid 2.2.16 → 2.2.17
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 +1 -1
- package/dist/GridFooter.svelte +12 -11
- package/dist/SvAnchor.svelte +65 -0
- package/dist/SvAnchor.svelte.d.ts +24 -0
- package/dist/SvAspectRatio.svelte +38 -0
- package/dist/SvAspectRatio.svelte.d.ts +16 -0
- package/dist/SvAutoComplete.svelte +52 -7
- package/dist/SvAutoComplete.svelte.d.ts +4 -1
- package/dist/SvBlockquote.svelte +43 -0
- package/dist/SvBlockquote.svelte.d.ts +16 -0
- package/dist/SvCalendar.svelte +33 -2
- package/dist/SvCalendar.svelte.d.ts +8 -1
- package/dist/SvCheckBox.svelte +6 -2
- package/dist/SvCode.svelte +52 -0
- package/dist/SvCode.svelte.d.ts +19 -0
- package/dist/SvCollapsible.svelte +75 -0
- package/dist/SvCollapsible.svelte.d.ts +27 -0
- package/dist/SvColorInput.svelte +11 -17
- package/dist/SvColorInput.svelte.d.ts +2 -0
- package/dist/SvComboBox.svelte +85 -8
- package/dist/SvComboBox.svelte.d.ts +14 -0
- package/dist/SvCountryInput.svelte +2 -2
- package/dist/SvCountryInput.svelte.d.ts +1 -1
- package/dist/SvDropDownList.svelte +154 -51
- package/dist/SvDropDownList.svelte.d.ts +17 -3
- package/dist/SvDurationInput.svelte +59 -41
- package/dist/SvDurationInput.svelte.d.ts +18 -0
- package/dist/SvField.svelte +203 -12
- package/dist/SvField.svelte.d.ts +45 -8
- package/dist/SvForm.svelte +195 -21
- package/dist/SvForm.svelte.d.ts +23 -0
- package/dist/SvGrid.controller.svelte.d.ts +12 -1
- package/dist/SvGrid.controller.svelte.js +87 -7
- package/dist/SvGrid.svelte +383 -181
- package/dist/SvGrid.types.d.ts +123 -2
- package/dist/SvGridChartView.svelte +70 -0
- package/dist/SvGridChartView.svelte.d.ts +11 -0
- package/dist/SvGridDropdown.svelte +9 -2
- package/dist/SvGridSelect.svelte +5 -2
- package/dist/SvGridSelect.svelte.d.ts +1 -1
- package/dist/SvGroup.svelte +41 -0
- package/dist/SvGroup.svelte.d.ts +27 -0
- package/dist/SvHoverCard.svelte +70 -0
- package/dist/SvHoverCard.svelte.d.ts +41 -0
- package/dist/SvKbd.svelte +51 -0
- package/dist/SvKbd.svelte.d.ts +18 -0
- package/dist/SvList.svelte +55 -0
- package/dist/SvList.svelte.d.ts +23 -0
- package/dist/SvListBox.svelte +166 -77
- package/dist/SvListBox.svelte.d.ts +17 -4
- package/dist/SvLoadingOverlay.svelte +53 -0
- package/dist/SvLoadingOverlay.svelte.d.ts +28 -0
- package/dist/SvMark.svelte +36 -0
- package/dist/SvMark.svelte.d.ts +14 -0
- package/dist/SvMaskedInput.svelte +50 -35
- package/dist/SvMaskedInput.svelte.d.ts +17 -2
- package/dist/SvMenuList.svelte +32 -3
- package/dist/SvMenubar.svelte +200 -0
- package/dist/SvMenubar.svelte.d.ts +18 -0
- package/dist/SvMultiSelect.svelte +7 -4
- package/dist/SvMultiSelect.svelte.d.ts +1 -1
- package/dist/SvNumberInput.svelte +79 -42
- package/dist/SvNumberInput.svelte.d.ts +25 -0
- package/dist/SvOtpInput.svelte +2 -2
- package/dist/SvPasswordInput.svelte +51 -31
- package/dist/SvPasswordInput.svelte.d.ts +17 -0
- package/dist/SvPhoneInput.svelte +39 -28
- package/dist/SvPhoneInput.svelte.d.ts +4 -0
- package/dist/SvPopconfirm.svelte +79 -0
- package/dist/SvPopconfirm.svelte.d.ts +42 -0
- package/dist/SvPopover.svelte +87 -29
- package/dist/SvPopover.svelte.d.ts +18 -4
- package/dist/SvRadioGroup.svelte +5 -1
- package/dist/SvResult.svelte +73 -0
- package/dist/SvResult.svelte.d.ts +28 -0
- package/dist/SvSegmented.svelte +114 -0
- package/dist/SvSegmented.svelte.d.ts +29 -0
- package/dist/SvSimpleGrid.svelte +41 -0
- package/dist/SvSimpleGrid.svelte.d.ts +25 -0
- package/dist/SvSlider.svelte +23 -10
- package/dist/SvSpinner.svelte +43 -0
- package/dist/SvSpinner.svelte.d.ts +20 -0
- package/dist/SvStack.svelte +37 -0
- package/dist/SvStack.svelte.d.ts +24 -0
- package/dist/SvSwitchButton.svelte +6 -1
- package/dist/SvTagsInput.svelte +9 -5
- package/dist/SvText.svelte +76 -0
- package/dist/SvText.svelte.d.ts +31 -0
- package/dist/SvTextInput.svelte +75 -43
- package/dist/SvTextInput.svelte.d.ts +28 -1
- package/dist/SvTimePicker.svelte +32 -2
- package/dist/SvTimePicker.svelte.d.ts +8 -9
- package/dist/SvTitle.svelte +57 -0
- package/dist/SvTitle.svelte.d.ts +24 -0
- package/dist/SvToaster.svelte +41 -6
- package/dist/SvToggleButton.svelte +4 -1
- package/dist/SvTooltip.svelte +68 -34
- package/dist/SvTooltip.svelte.d.ts +14 -2
- package/dist/SvTree.svelte +81 -21
- package/dist/SvTree.svelte.d.ts +3 -2
- package/dist/SvTreeSelect.svelte +5 -2
- package/dist/SvTreeSelect.svelte.d.ts +1 -1
- package/dist/SvVisuallyHidden.svelte +49 -0
- package/dist/SvVisuallyHidden.svelte.d.ts +19 -0
- package/dist/ai.d.ts +289 -0
- package/dist/ai.js +1013 -0
- package/dist/board-view.svelte.d.ts +22 -0
- package/dist/board-view.svelte.js +13 -0
- package/dist/build-api.js +36 -6
- package/dist/cdn/GridMenus-0AK9O7qG.js +420 -0
- package/dist/cdn/GridMenus-BjUoCXoD.js +416 -0
- package/dist/cdn/SvDateTimePicker-CYC7gRER.js +2176 -0
- package/dist/cdn/SvDateTimePicker-DtQKd4Ns.js +2198 -0
- package/dist/cdn/SvGridChart-BcLCYvw9.js +1195 -0
- package/dist/cdn/SvGridChart-BhnFdLd0.js +1203 -0
- package/dist/cdn/SvGridChartPanel-Cmx9DHAS.js +561 -0
- package/dist/cdn/SvGridChartPanel-DvjwxLvK.js +577 -0
- package/dist/cdn/SvGridChartView-B40DTJSX.js +54 -0
- package/dist/cdn/SvGridChartView-PwqI4s02.js +53 -0
- package/dist/cdn/SvGridDropdown-DjALc_4f.js +255 -0
- package/dist/cdn/SvGridDropdown-hpnHvOGt.js +254 -0
- package/dist/cdn/chart-T1usDN0o.js +1212 -0
- package/dist/cdn/disclose-version-DoD9AFD_.js +2958 -0
- package/dist/cdn/export-format-JT5pWVT8.js +561 -0
- package/dist/cdn/popover-P-9P2YYn.js +69 -0
- package/dist/cdn/rolldown-runtime-Dy4uBu1J.js +11 -0
- package/dist/cdn/src-BLhdLmoN.js +25707 -0
- package/dist/cdn/src-BwnUVj3T.js +25623 -0
- package/dist/cdn/svgrid.js +9 -32897
- package/dist/cdn/svgrid.svelte-external.js +9 -30052
- package/dist/cell-formatting.d.ts +2 -2
- package/dist/cell-render.js +4 -4
- package/dist/chart-view.svelte.d.ts +25 -0
- package/dist/chart-view.svelte.js +14 -0
- package/dist/createCombobox.svelte.d.ts +5 -0
- package/dist/createCombobox.svelte.js +21 -5
- package/dist/createDropdownList.svelte.d.ts +3 -0
- package/dist/createDropdownList.svelte.js +8 -2
- package/dist/createForm.svelte.d.ts +18 -0
- package/dist/createForm.svelte.js +51 -6
- package/dist/createMenu.svelte.js +27 -0
- package/dist/createPopoverSelect.svelte.d.ts +3 -0
- package/dist/createPopoverSelect.svelte.js +9 -1
- package/dist/createSlider.svelte.d.ts +8 -21
- package/dist/createSlider.svelte.js +34 -0
- package/dist/createTooltip.svelte.d.ts +12 -0
- package/dist/createTooltip.svelte.js +72 -9
- package/dist/editor-contract.d.ts +15 -0
- package/dist/export-provider.d.ts +27 -0
- package/dist/export-provider.js +9 -0
- package/dist/filter-operators.d.ts +6 -0
- package/dist/filter-operators.js +33 -0
- package/dist/form-field.d.ts +45 -2
- package/dist/grid-messages.d.ts +61 -0
- package/dist/grid-messages.js +72 -0
- package/dist/group-display.d.ts +62 -0
- package/dist/group-display.js +78 -0
- package/dist/index.d.ts +36 -4
- package/dist/index.js +43 -2
- package/dist/js-scroller.svelte.d.ts +35 -0
- package/dist/js-scroller.svelte.js +154 -0
- package/dist/list-option.d.ts +46 -0
- package/dist/list-option.js +53 -0
- package/dist/menus.js +25 -11
- package/dist/pivot-view.svelte.d.ts +72 -0
- package/dist/pivot-view.svelte.js +13 -0
- package/dist/positioning.d.ts +111 -0
- package/dist/positioning.js +191 -0
- package/dist/scheduler-model.d.ts +3 -0
- package/dist/scheduler-model.js +22 -5
- package/dist/svgrid-wrapper.types.d.ts +18 -0
- package/dist/toast-store.svelte.d.ts +54 -0
- package/dist/toast-store.svelte.js +65 -15
- package/package.json +9 -1
- package/src/GridFooter.svelte +12 -11
- package/src/SvAnchor.svelte +65 -0
- package/src/SvAspectRatio.svelte +38 -0
- package/src/SvAutoComplete.svelte +52 -7
- package/src/SvBlockquote.svelte +43 -0
- package/src/SvCalendar.svelte +33 -2
- package/src/SvCalendar.test.ts +15 -0
- package/src/SvCheckBox.svelte +6 -2
- package/src/SvCode.svelte +52 -0
- package/src/SvCollapsible.svelte +75 -0
- package/src/SvColorInput.svelte +11 -17
- package/src/SvComboBox.svelte +85 -8
- package/src/SvCountryInput.svelte +2 -2
- package/src/SvDropDownList.svelte +154 -51
- package/src/SvDurationInput.svelte +59 -41
- package/src/SvField.svelte +203 -12
- package/src/SvForm.svelte +195 -21
- package/src/SvForm.test.ts +112 -0
- package/src/SvGrid.controller.svelte.ts +88 -7
- package/src/SvGrid.svelte +383 -181
- package/src/SvGrid.types.ts +125 -1
- package/src/SvGridChartView.svelte +70 -0
- package/src/SvGridDropdown.svelte +9 -2
- package/src/SvGridSelect.svelte +5 -2
- package/src/SvGroup.svelte +41 -0
- package/src/SvHoverCard.svelte +70 -0
- package/src/SvKbd.svelte +51 -0
- package/src/SvList.svelte +55 -0
- package/src/SvListBox.svelte +166 -77
- package/src/SvLoadingOverlay.svelte +53 -0
- package/src/SvMark.svelte +36 -0
- package/src/SvMaskedInput.svelte +50 -35
- package/src/SvMenuList.svelte +32 -3
- package/src/SvMenubar.svelte +200 -0
- package/src/SvMultiSelect.svelte +7 -4
- package/src/SvNumberInput.svelte +79 -42
- package/src/SvOtpInput.svelte +2 -2
- package/src/SvPasswordInput.svelte +51 -31
- package/src/SvPhoneInput.svelte +39 -28
- package/src/SvPopconfirm.svelte +79 -0
- package/src/SvPopover.svelte +87 -29
- package/src/SvRadioGroup.svelte +5 -1
- package/src/SvResult.svelte +73 -0
- package/src/SvSegmented.svelte +114 -0
- package/src/SvSimpleGrid.svelte +41 -0
- package/src/SvSlider.svelte +23 -10
- package/src/SvSpinner.svelte +43 -0
- package/src/SvStack.svelte +37 -0
- package/src/SvSwitchButton.svelte +6 -1
- package/src/SvTagsInput.svelte +9 -5
- package/src/SvText.svelte +76 -0
- package/src/SvTextInput.svelte +75 -43
- package/src/SvTimePicker.svelte +32 -2
- package/src/SvTitle.svelte +57 -0
- package/src/SvToaster.svelte +41 -6
- package/src/SvToaster.test.ts +32 -0
- package/src/SvToggleButton.svelte +4 -1
- package/src/SvTooltip.svelte +68 -34
- package/src/SvTree.svelte +81 -21
- package/src/SvTreeSelect.svelte +5 -2
- package/src/SvVisuallyHidden.svelte +49 -0
- package/src/ai.test.ts +502 -0
- package/src/ai.ts +1391 -0
- package/src/board-view.svelte.ts +33 -0
- package/src/build-api.coverage.test.ts +101 -0
- package/src/build-api.ts +43 -18
- package/src/builtin-editors.grid.test.ts +1 -1
- package/src/cell-formatting.ts +5 -5
- package/src/cell-render.ts +4 -4
- package/src/chart-view.svelte.ts +36 -0
- package/src/createCombobox.svelte.ts +17 -5
- package/src/createDropdownList.svelte.ts +8 -2
- package/src/createForm.svelte.ts +59 -6
- package/src/createMenu.svelte.ts +23 -0
- package/src/createPopoverSelect.svelte.ts +8 -1
- package/src/createSlider.svelte.ts +20 -0
- package/src/createTooltip.svelte.ts +67 -9
- package/src/editor-contract.ts +16 -0
- package/src/export-provider.ts +40 -0
- package/src/filter-operators.ts +37 -0
- package/src/form-field.ts +42 -2
- package/src/grid-messages.test.ts +24 -0
- package/src/grid-messages.ts +137 -0
- package/src/group-display.test.ts +77 -0
- package/src/group-display.ts +117 -0
- package/src/i18n.grid.test.ts +73 -0
- package/src/index.ts +91 -2
- package/src/js-scroller.svelte.ts +173 -0
- package/src/list-option.test.ts +56 -0
- package/src/list-option.ts +81 -0
- package/src/menus.test.ts +32 -0
- package/src/menus.ts +25 -12
- package/src/pivot-view.svelte.ts +90 -0
- package/src/pivot-view.test.ts +38 -0
- package/src/pivot.grid.test.ts +102 -0
- package/src/positioning.test.ts +141 -0
- package/src/positioning.ts +266 -0
- package/src/scheduler-model.test.ts +16 -0
- package/src/scheduler-model.ts +24 -5
- package/src/svgrid-wrapper.types.ts +23 -0
- package/src/svgrid.charting.test.ts +8 -1
- package/src/svgrid.comments-autocomplete.test.ts +7 -2
- package/src/svgrid.context-menu.test.ts +8 -3
- package/src/toast-store.svelte.ts +98 -0
- package/src/toast-store.test.ts +62 -1
- package/src/ui-breadth.test.ts +138 -0
- package/src/ui-buttons.test.ts +39 -0
- package/src/ui-inputs.test.ts +2 -2
- package/src/ui-range.test.ts +9 -0
- package/src/ui-selection.test.ts +36 -0
- package/src/ui-tier1.test.ts +1 -1
- package/src/virtual.test.ts +20 -6
- package/dist/SvGridBoard.svelte +0 -2339
- package/dist/SvGridBoard.svelte.d.ts +0 -31
- package/src/SvGridBoard.svelte +0 -2339
- package/src/board.test.ts +0 -927
|
@@ -10,11 +10,13 @@
|
|
|
10
10
|
import { anchoredRect, portalToBody, popIn, type AnchoredRect } from './popover'
|
|
11
11
|
import { startPanelResize } from './panel-resize'
|
|
12
12
|
import { createDismissableLayer } from './a11y/dismissable'
|
|
13
|
-
import { groupOptions,
|
|
14
|
-
import {
|
|
13
|
+
import { groupOptions, normalizeOptions, flattenForVirtual, type ListOption, type IndexedOption, type RowHeight } from './list-option'
|
|
14
|
+
import { createSvelteVirtualizer } from './virtualization/svelte-virtualizer.svelte'
|
|
15
|
+
import { createJsScroller } from './js-scroller.svelte'
|
|
15
16
|
import SvField from './SvField.svelte'
|
|
16
17
|
import { nextEditorId, type SvEditorProps } from './editor-contract'
|
|
17
18
|
import { createDropdownList } from './createDropdownList.svelte'
|
|
19
|
+
import { untrack, type Snippet } from 'svelte'
|
|
18
20
|
|
|
19
21
|
type Props = SvEditorProps & {
|
|
20
22
|
options: ReadonlyArray<ListOption>
|
|
@@ -24,11 +26,24 @@
|
|
|
24
26
|
autoOpen?: boolean
|
|
25
27
|
/** Window the option list (render only visible) for large sets. */
|
|
26
28
|
virtual?: boolean
|
|
27
|
-
/**
|
|
28
|
-
|
|
29
|
+
/** Option height in px - a number, or a per-option function for variable
|
|
30
|
+
* heights. Must match the rendered row height. Default 34. */
|
|
31
|
+
rowHeight?: RowHeight
|
|
32
|
+
/** Height (px) of a group heading row when virtualized + grouped. Default 28. */
|
|
33
|
+
groupHeaderHeight?: number
|
|
34
|
+
/** Max options shown before the panel scrolls (native-select behaviour). Default 8. */
|
|
35
|
+
maxRows?: number
|
|
29
36
|
/** Show a bottom drag grip so the user can resize the open panel's height
|
|
30
37
|
* (only while it opens downward). Off by default. */
|
|
31
38
|
resizable?: boolean
|
|
39
|
+
/** Custom render for each option (receives the ListOption). */
|
|
40
|
+
item?: Snippet<[ListOption]>
|
|
41
|
+
/** Content pinned above the option list. */
|
|
42
|
+
header?: Snippet
|
|
43
|
+
/** Content pinned below the option list. */
|
|
44
|
+
footer?: Snippet
|
|
45
|
+
/** Shown when there are no options. */
|
|
46
|
+
noData?: Snippet
|
|
32
47
|
}
|
|
33
48
|
|
|
34
49
|
let {
|
|
@@ -37,6 +52,7 @@
|
|
|
37
52
|
onChange,
|
|
38
53
|
placeholder = 'Select…',
|
|
39
54
|
disabled = false,
|
|
55
|
+
readonly = false,
|
|
40
56
|
name,
|
|
41
57
|
size = 'md',
|
|
42
58
|
ariaLabel,
|
|
@@ -50,18 +66,66 @@
|
|
|
50
66
|
autoOpen = false,
|
|
51
67
|
virtual = false,
|
|
52
68
|
rowHeight = 34,
|
|
69
|
+
groupHeaderHeight = 28,
|
|
70
|
+
maxRows = 8,
|
|
53
71
|
resizable = false,
|
|
72
|
+
item,
|
|
73
|
+
header,
|
|
74
|
+
footer,
|
|
75
|
+
noData,
|
|
54
76
|
}: Props = $props()
|
|
55
77
|
|
|
56
78
|
const autoId = nextEditorId('sv-ddl')
|
|
57
79
|
const uid = $derived(id ?? autoId)
|
|
58
80
|
|
|
59
|
-
//
|
|
60
|
-
const
|
|
61
|
-
|
|
81
|
+
// Tolerate primitive / partial options - normalize so labels render + keys are stable.
|
|
82
|
+
const norm = $derived(normalizeOptions(options))
|
|
83
|
+
|
|
84
|
+
// Virtualization windows the option list (grouped lists too, via the shared
|
|
85
|
+
// virtualizer + a flattened header/option model with per-row sizes).
|
|
86
|
+
const useVirtual = $derived(virtual)
|
|
62
87
|
let viewportH = $state(0)
|
|
63
|
-
const
|
|
64
|
-
const
|
|
88
|
+
const rowHeightBase = $derived(typeof rowHeight === 'number' ? rowHeight : 34)
|
|
89
|
+
const flat = $derived(flattenForVirtual(norm, { rowHeight, groupHeaderHeight }))
|
|
90
|
+
const uniform = $derived(!flat.hasGroups && typeof rowHeight === 'number')
|
|
91
|
+
const estimateSize = $derived(uniform ? rowHeightBase : (i: number) => flat.sizeAt(i))
|
|
92
|
+
|
|
93
|
+
// Generous overscan buffers fast flings; effective viewport never 0 (see SvListBox).
|
|
94
|
+
const OVERSCAN = 20
|
|
95
|
+
const effViewport = $derived(viewportH > 0 ? viewportH : Math.max(1, maxRows * rowHeightBase))
|
|
96
|
+
|
|
97
|
+
// Seed with the initial (untracked) values so the first paint of the open panel
|
|
98
|
+
// renders a full window; the effects below keep it synced.
|
|
99
|
+
const virtualizer = createSvelteVirtualizer(
|
|
100
|
+
untrack(() => ({ count: flat.entries.length, estimateSize, overscan: OVERSCAN, viewportHeight: effViewport })),
|
|
101
|
+
)
|
|
102
|
+
// untrack keeps the virtualizer's internal `version` write out of these
|
|
103
|
+
// effects' dependencies, so they re-run only on their real inputs.
|
|
104
|
+
$effect(() => {
|
|
105
|
+
const count = flat.entries.length
|
|
106
|
+
const es = estimateSize
|
|
107
|
+
untrack(() => virtualizer.setOptions({ count, estimateSize: es }))
|
|
108
|
+
})
|
|
109
|
+
$effect(() => {
|
|
110
|
+
const vh = effViewport
|
|
111
|
+
untrack(() => virtualizer.setViewportHeight(vh))
|
|
112
|
+
})
|
|
113
|
+
const vItems = $derived.by(() => {
|
|
114
|
+
virtualizer.version
|
|
115
|
+
return virtualizer.getVirtualItems()
|
|
116
|
+
})
|
|
117
|
+
const totalSize = $derived.by(() => {
|
|
118
|
+
virtualizer.version
|
|
119
|
+
return virtualizer.getTotalSize()
|
|
120
|
+
})
|
|
121
|
+
// JS-driven scroll (see SvListBox / js-scroller): no native scroll, so a fast
|
|
122
|
+
// thumb-drag never flashes the empty panel.
|
|
123
|
+
const scroller = createJsScroller({
|
|
124
|
+
virtualizer,
|
|
125
|
+
totalSize: () => totalSize,
|
|
126
|
+
viewport: () => effViewport,
|
|
127
|
+
lineStep: () => rowHeightBase,
|
|
128
|
+
})
|
|
65
129
|
|
|
66
130
|
let triggerEl = $state<HTMLButtonElement | null>(null)
|
|
67
131
|
let panelEl = $state<HTMLDivElement | null>(null)
|
|
@@ -75,11 +139,24 @@
|
|
|
75
139
|
)
|
|
76
140
|
const showGrip = $derived(resizable && !rect.openUpward)
|
|
77
141
|
|
|
142
|
+
// The virtual panel uses NO native scroll, so its rows are absolutely
|
|
143
|
+
// positioned and can't size the panel. Give it an explicit height (content up
|
|
144
|
+
// to `maxRows`, capped by the resized / bounds-aware ceiling) so the flex
|
|
145
|
+
// viewport (`.sv-ddl__vp`) has a definite height to fill.
|
|
146
|
+
const virtualPanelH = $derived(
|
|
147
|
+
Math.min(
|
|
148
|
+
Math.min(totalSize, Math.max(rowHeightBase, maxRows * rowHeightBase)) + 8,
|
|
149
|
+
rect.maxHeight || Number.POSITIVE_INFINITY,
|
|
150
|
+
resizable && userHeight != null ? panelMaxH : Number.POSITIVE_INFINITY,
|
|
151
|
+
),
|
|
152
|
+
)
|
|
153
|
+
|
|
78
154
|
const ddl = createDropdownList({
|
|
79
|
-
options: () =>
|
|
155
|
+
options: () => norm,
|
|
80
156
|
value: () => value,
|
|
81
157
|
onChange: (v) => onChange?.(v),
|
|
82
158
|
disabled: () => disabled,
|
|
159
|
+
readonly: () => readonly,
|
|
83
160
|
ariaLabel: () => ariaLabel,
|
|
84
161
|
focusTrigger: () => triggerEl?.focus(),
|
|
85
162
|
id: () => uid,
|
|
@@ -94,9 +171,13 @@
|
|
|
94
171
|
function updatePos() {
|
|
95
172
|
if (!triggerEl) return
|
|
96
173
|
// When the user has resized, anchor to THAT height so the flip decision and
|
|
97
|
-
// upward top stay correct; otherwise
|
|
174
|
+
// upward top stay correct; otherwise size to the content up to `maxRows` items
|
|
175
|
+
// (native-select behaviour: no scrollbar until the list exceeds the cap). The
|
|
176
|
+
// +PANEL_CHROME budgets the panel's own padding (8) + border (2) so a list
|
|
177
|
+
// that exactly fills `maxRows` is not clipped by the border-box max-height.
|
|
178
|
+
const PANEL_CHROME = 10
|
|
98
179
|
const estimatedHeight =
|
|
99
|
-
resizable && userHeight != null ? userHeight : Math.min(
|
|
180
|
+
resizable && userHeight != null ? userHeight : Math.min(norm.length, maxRows) * rowHeightBase + PANEL_CHROME
|
|
100
181
|
rect = anchoredRect(triggerEl.getBoundingClientRect(), { estimatedHeight })
|
|
101
182
|
}
|
|
102
183
|
|
|
@@ -130,14 +211,15 @@
|
|
|
130
211
|
layer.activate()
|
|
131
212
|
return () => { window.removeEventListener('scroll', rp, true); window.removeEventListener('resize', rp); layer.release() }
|
|
132
213
|
})
|
|
133
|
-
// Keep the active option scrolled into view (render concern)
|
|
214
|
+
// Keep the active option scrolled into view (render concern) - via the scroller
|
|
215
|
+
// (virtual) or scrollIntoView (native non-virtual).
|
|
134
216
|
$effect(() => {
|
|
135
217
|
if (!ddl.open) return
|
|
136
218
|
const i = ddl.activeIndex
|
|
137
219
|
if (useVirtual) {
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
220
|
+
const flatIdx = flat.optionFlatIndex[i]
|
|
221
|
+
if (flatIdx == null) return
|
|
222
|
+
untrack(() => scroller.ensureIndexVisible(flatIdx))
|
|
141
223
|
} else {
|
|
142
224
|
queueMicrotask(() => panelEl?.querySelector<HTMLElement>(`[data-idx="${i}"]`)?.scrollIntoView({ block: 'nearest' }))
|
|
143
225
|
}
|
|
@@ -160,33 +242,56 @@
|
|
|
160
242
|
</button>
|
|
161
243
|
</SvField>
|
|
162
244
|
|
|
245
|
+
{#snippet optRow(opt: IndexedOption, h?: number, top?: number)}
|
|
246
|
+
<!-- svelte-ignore a11y_click_events_have_key_events a11y_interactive_supports_focus -->
|
|
247
|
+
<div class="sv-ddl__opt" style:height={h != null ? `${h}px` : undefined} style:transform={top == null ? undefined : `translateY(${top}px)`} class:is-active={ddl.isActive(opt.index)} class:is-selected={ddl.isSelected(opt)} class:is-disabled={opt.disabled} {...ddl.optionProps(opt.index)}>
|
|
248
|
+
{#if item}{@render item(opt)}{:else}{#if opt.color}<span class="sv-ddl__swatch" style:background={opt.color}></span>{/if}{opt.label}{/if}
|
|
249
|
+
</div>
|
|
250
|
+
{/snippet}
|
|
251
|
+
|
|
163
252
|
{#if ddl.open}
|
|
164
|
-
<div bind:this={panelEl} class="sv-ddl__panel" class:is-virtual={useVirtual} class:is-resizable={showGrip} use:portalToBody use:popIn={{ up: rect.openUpward }} style:--sv-row-h={`${
|
|
165
|
-
{#if
|
|
166
|
-
|
|
167
|
-
{#
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
253
|
+
<div bind:this={panelEl} class="sv-ddl__panel" class:is-virtual={useVirtual} class:is-resizable={showGrip} use:portalToBody use:popIn={{ up: rect.openUpward }} style:--sv-row-h={`${rowHeightBase}px`} style:position="fixed" style:top={`${rect.top}px`} style:left={`${rect.left}px`} style:min-width={`${rect.width}px`} style:max-height={`${panelMaxH}px`} style:height={useVirtual ? `${virtualPanelH}px` : resizable && userHeight != null ? `${panelMaxH}px` : undefined} onwheel={useVirtual ? scroller.onWheel : undefined} {...ddl.listboxProps()}>
|
|
254
|
+
{#if header}<div class="sv-ddl__header">{@render header()}</div>{/if}
|
|
255
|
+
{#if !norm.length}
|
|
256
|
+
{#if noData}{@render noData()}{:else}<div class="sv-ddl__empty">No options</div>{/if}
|
|
257
|
+
{:else if useVirtual}
|
|
258
|
+
<!-- JS-driven scroller: one clipped viewport holds the windowed rows (moved
|
|
259
|
+
by scrollOffset) + a custom scrollbar. No native scroll = no async gap
|
|
260
|
+
= no blank flash on a fast thumb-drag. -->
|
|
261
|
+
<!-- svelte-ignore a11y_no_static_element_interactions -->
|
|
262
|
+
<div class="sv-ddl__vp" bind:clientHeight={viewportH} onpointerdown={scroller.onContentDown} onpointermove={scroller.onContentMove} onpointerup={scroller.onContentUp} onpointercancel={scroller.onContentUp}>
|
|
263
|
+
{#each vItems as vi (vi.key)}
|
|
264
|
+
{@const entry = flat.entries[vi.index]}
|
|
265
|
+
{#if entry?.type === 'group'}
|
|
266
|
+
<div class="sv-ddl__group-label sv-ddl__group-label--abs" aria-hidden="true" style:height={`${vi.size}px`} style:transform={`translateY(${vi.start - scroller.scrollOffset}px)`}>{entry.label}</div>
|
|
267
|
+
{:else if entry}
|
|
268
|
+
{@render optRow(entry.opt, vi.size, vi.start - scroller.scrollOffset)}
|
|
269
|
+
{/if}
|
|
270
|
+
{/each}
|
|
271
|
+
{#if scroller.maxOffset > 0}
|
|
272
|
+
<!-- svelte-ignore a11y_no_static_element_interactions -->
|
|
273
|
+
<div class="sv-ddl__sb" onpointerdown={scroller.onTrackDown} aria-hidden="true">
|
|
274
|
+
<div class="sv-ddl__thumb" class:is-dragging={scroller.dragging} style:height={`${scroller.thumbH}px`} style:transform={`translateY(${scroller.thumbTop}px)`} onpointerdown={scroller.onThumbDown} onpointermove={scroller.onThumbMove} onpointerup={scroller.onThumbUp} onpointercancel={scroller.onThumbUp}></div>
|
|
275
|
+
</div>
|
|
276
|
+
{/if}
|
|
277
|
+
</div>
|
|
172
278
|
{:else}
|
|
173
|
-
{#each groupOptions(
|
|
279
|
+
{#each groupOptions(norm) as g (g.group ?? '')}
|
|
174
280
|
{#if g.group != null}
|
|
175
281
|
<div class="sv-ddl__group" role="group" aria-label={g.group}>
|
|
176
282
|
<div class="sv-ddl__group-label" aria-hidden="true">{g.group}</div>
|
|
177
|
-
{#each g.options as opt (opt.
|
|
178
|
-
|
|
179
|
-
<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)}>{#if opt.color}<span class="sv-ddl__swatch" style:background={opt.color}></span>{/if}{opt.label}</div>
|
|
283
|
+
{#each g.options as opt (opt.index)}
|
|
284
|
+
{@render optRow(opt)}
|
|
180
285
|
{/each}
|
|
181
286
|
</div>
|
|
182
287
|
{:else}
|
|
183
|
-
{#each g.options as opt (opt.
|
|
184
|
-
|
|
185
|
-
<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)}>{#if opt.color}<span class="sv-ddl__swatch" style:background={opt.color}></span>{/if}{opt.label}</div>
|
|
288
|
+
{#each g.options as opt (opt.index)}
|
|
289
|
+
{@render optRow(opt)}
|
|
186
290
|
{/each}
|
|
187
291
|
{/if}
|
|
188
292
|
{/each}
|
|
189
293
|
{/if}
|
|
294
|
+
{#if footer}<div class="sv-ddl__footer">{@render footer()}</div>{/if}
|
|
190
295
|
{#if showGrip}
|
|
191
296
|
<!-- svelte-ignore a11y_no_static_element_interactions -->
|
|
192
297
|
<div class="sv-ddl__grip" onpointerdown={startResize} title="Drag to resize" aria-hidden="true">
|
|
@@ -221,7 +326,18 @@
|
|
|
221
326
|
background: var(--sg-bg, #fff); color: var(--sg-fg, #0f172a);
|
|
222
327
|
border: 1px solid var(--sg-border, #e2e8f0); border-radius: 10px; box-shadow: 0 16px 48px -12px rgba(15,23,42,0.35);
|
|
223
328
|
}
|
|
224
|
-
|
|
329
|
+
/* Virtual panel: a flex column (header / JS-driven viewport / footer / grip)
|
|
330
|
+
with NO native scroll - the viewport moves its rows by `scrollOffset`. */
|
|
331
|
+
:global(.sv-ddl__panel.is-virtual) { display: flex; flex-direction: column; overflow: hidden; }
|
|
332
|
+
:global(.sv-ddl__vp) { position: relative; flex: 1 1 auto; min-height: 0; overflow: hidden; touch-action: none; }
|
|
333
|
+
:global(.sv-ddl__panel.is-virtual .sv-ddl__opt), :global(.sv-ddl__group-label--abs) { position: absolute; left: 0; right: 0; top: 0; }
|
|
334
|
+
:global(.sv-ddl__sb) { position: absolute; top: 0; right: 1px; bottom: 0; width: 10px; z-index: 2; }
|
|
335
|
+
:global(.sv-ddl__thumb) {
|
|
336
|
+
position: absolute; left: 2px; right: 2px; top: 0; min-height: 24px; border-radius: 4px;
|
|
337
|
+
background: color-mix(in srgb, currentColor 26%, transparent); cursor: default; touch-action: none;
|
|
338
|
+
}
|
|
339
|
+
:global(.sv-ddl__thumb:hover), :global(.sv-ddl__thumb.is-dragging) { background: color-mix(in srgb, currentColor 42%, transparent); }
|
|
340
|
+
:global(.sv-ddl__opt) { box-sizing: border-box; flex: none; display: flex; align-items: center; padding: 7px 10px; border-radius: 6px; cursor: pointer; font-size: 13px; }
|
|
225
341
|
/* Color swatch shown before an option's label (option.color) - in both the
|
|
226
342
|
trigger value and the portalled panel options. */
|
|
227
343
|
:global(.sv-ddl__swatch) {
|
|
@@ -244,28 +360,15 @@
|
|
|
244
360
|
background-size: 6px 4px; background-position: center; background-repeat: repeat-x;
|
|
245
361
|
}
|
|
246
362
|
:global(.sv-ddl__grip:hover .sv-ddl__grip-dots) { opacity: 1; }
|
|
247
|
-
/* Faint per-row skeleton so a fast scrollbar-thumb drag reveals placeholder
|
|
248
|
-
rows in this off-screen padding instead of blank, until JS re-windows. */
|
|
249
|
-
:global(.sv-ddl__spacer) {
|
|
250
|
-
padding: 0; margin: 0; flex: none; pointer-events: none;
|
|
251
|
-
background-image: linear-gradient(
|
|
252
|
-
to bottom,
|
|
253
|
-
transparent 0,
|
|
254
|
-
transparent calc((var(--sv-row-h, 34px) - 10px) / 2),
|
|
255
|
-
var(--sg-skeleton, color-mix(in srgb, currentColor 9%, transparent)) calc((var(--sv-row-h, 34px) - 10px) / 2),
|
|
256
|
-
var(--sg-skeleton, color-mix(in srgb, currentColor 9%, transparent)) calc((var(--sv-row-h, 34px) + 10px) / 2),
|
|
257
|
-
transparent calc((var(--sv-row-h, 34px) + 10px) / 2),
|
|
258
|
-
transparent var(--sv-row-h, 34px)
|
|
259
|
-
);
|
|
260
|
-
background-size: 62% var(--sv-row-h, 34px);
|
|
261
|
-
background-repeat: repeat-y;
|
|
262
|
-
background-position: 12px 0;
|
|
263
|
-
}
|
|
264
363
|
:global(.sv-ddl__opt.is-active) { background: var(--sg-row-hover-bg, #f1f5f9); }
|
|
265
364
|
:global(.sv-ddl__opt.is-selected) { color: var(--sg-accent, #2563eb); font-weight: 600; }
|
|
266
365
|
:global(.sv-ddl__opt.is-disabled) { opacity: 0.4; cursor: not-allowed; }
|
|
267
366
|
:global(.sv-ddl__group-label) {
|
|
268
|
-
padding: 8px 10px 3px; font-size: 10.5px; font-weight: 700;
|
|
269
|
-
color: var(--sg-muted, #94a3b8);
|
|
367
|
+
box-sizing: border-box; padding: 8px 10px 3px; font-size: 10.5px; font-weight: 700;
|
|
368
|
+
text-transform: uppercase; letter-spacing: 0.04em; color: var(--sg-muted, #94a3b8);
|
|
369
|
+
display: flex; align-items: flex-end;
|
|
270
370
|
}
|
|
371
|
+
:global(.sv-ddl__empty) { padding: 12px 12px; font-size: 13px; color: var(--sg-muted, #64748b); text-align: center; }
|
|
372
|
+
:global(.sv-ddl__header) { padding: 8px 10px; border-bottom: 1px solid var(--sg-border, #e2e8f0); font-size: 12.5px; color: var(--sg-muted, #64748b); }
|
|
373
|
+
:global(.sv-ddl__footer) { padding: 8px 10px; border-top: 1px solid var(--sg-border, #e2e8f0); font-size: 12.5px; }
|
|
271
374
|
</style>
|
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
import { type ListOption } from './list-option';
|
|
1
|
+
import { type ListOption, type RowHeight } from './list-option';
|
|
2
2
|
import { type SvEditorProps } from './editor-contract';
|
|
3
|
+
import { type Snippet } from 'svelte';
|
|
3
4
|
type Props = SvEditorProps & {
|
|
4
5
|
options: ReadonlyArray<ListOption>;
|
|
5
6
|
value?: string | number | null;
|
|
@@ -8,11 +9,24 @@ type Props = SvEditorProps & {
|
|
|
8
9
|
autoOpen?: boolean;
|
|
9
10
|
/** Window the option list (render only visible) for large sets. */
|
|
10
11
|
virtual?: boolean;
|
|
11
|
-
/**
|
|
12
|
-
|
|
12
|
+
/** Option height in px - a number, or a per-option function for variable
|
|
13
|
+
* heights. Must match the rendered row height. Default 34. */
|
|
14
|
+
rowHeight?: RowHeight;
|
|
15
|
+
/** Height (px) of a group heading row when virtualized + grouped. Default 28. */
|
|
16
|
+
groupHeaderHeight?: number;
|
|
17
|
+
/** Max options shown before the panel scrolls (native-select behaviour). Default 8. */
|
|
18
|
+
maxRows?: number;
|
|
13
19
|
/** Show a bottom drag grip so the user can resize the open panel's height
|
|
14
20
|
* (only while it opens downward). Off by default. */
|
|
15
21
|
resizable?: boolean;
|
|
22
|
+
/** Custom render for each option (receives the ListOption). */
|
|
23
|
+
item?: Snippet<[ListOption]>;
|
|
24
|
+
/** Content pinned above the option list. */
|
|
25
|
+
header?: Snippet;
|
|
26
|
+
/** Content pinned below the option list. */
|
|
27
|
+
footer?: Snippet;
|
|
28
|
+
/** Shown when there are no options. */
|
|
29
|
+
noData?: Snippet;
|
|
16
30
|
};
|
|
17
31
|
declare const SvDropDownList: import("svelte").Component<Props, {}, "">;
|
|
18
32
|
type SvDropDownList = ReturnType<typeof SvDropDownList>;
|
|
@@ -3,8 +3,10 @@
|
|
|
3
3
|
* SvDurationInput - a duration editor whose value is a number of MINUTES but
|
|
4
4
|
* which accepts the human forms people type ("1h 30m", "1:30", "90"). It shows
|
|
5
5
|
* a formatted value when unfocused and re-parses on blur / Enter. As a grid
|
|
6
|
-
* cell editor: Enter commits, Escape cancels.
|
|
6
|
+
* cell editor: Enter commits, Escape cancels. The box, size and invalid state
|
|
7
|
+
* are owned by SvField's `frame` chrome.
|
|
7
8
|
*/
|
|
9
|
+
import type { Snippet } from 'svelte'
|
|
8
10
|
import SvField from './SvField.svelte'
|
|
9
11
|
import { editorAria, nextEditorId, type SvEditorProps } from './editor-contract'
|
|
10
12
|
import { parseDuration, formatDuration } from './duration'
|
|
@@ -19,6 +21,16 @@
|
|
|
19
21
|
style?: 'colon' | 'units'
|
|
20
22
|
placeholder?: string
|
|
21
23
|
autofocus?: boolean
|
|
24
|
+
/** Show a clear (x) button when there is a value. */
|
|
25
|
+
clearable?: boolean
|
|
26
|
+
/** Leading adornment (icon) inside the field. */
|
|
27
|
+
leading?: Snippet
|
|
28
|
+
/** Trailing adornment (icon) inside the field. */
|
|
29
|
+
trailing?: Snippet
|
|
30
|
+
/** Stretch to the container width. */
|
|
31
|
+
block?: boolean
|
|
32
|
+
/** Control width in px (ignored when `block`). Default 160. */
|
|
33
|
+
width?: number
|
|
22
34
|
}
|
|
23
35
|
|
|
24
36
|
let {
|
|
@@ -40,7 +52,13 @@
|
|
|
40
52
|
hint,
|
|
41
53
|
dir,
|
|
42
54
|
id,
|
|
55
|
+
loading = false,
|
|
43
56
|
autofocus = false,
|
|
57
|
+
clearable = false,
|
|
58
|
+
leading,
|
|
59
|
+
trailing,
|
|
60
|
+
block = false,
|
|
61
|
+
width = 160,
|
|
44
62
|
}: Props = $props()
|
|
45
63
|
|
|
46
64
|
const autoId = nextEditorId('sv-dur')
|
|
@@ -65,44 +83,44 @@
|
|
|
65
83
|
}
|
|
66
84
|
</script>
|
|
67
85
|
|
|
68
|
-
<SvField
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
86
|
+
<SvField
|
|
87
|
+
frame
|
|
88
|
+
id={uid}
|
|
89
|
+
{label}
|
|
90
|
+
{hint}
|
|
91
|
+
{error}
|
|
92
|
+
{required}
|
|
93
|
+
{dir}
|
|
94
|
+
{size}
|
|
95
|
+
{invalid}
|
|
96
|
+
{disabled}
|
|
97
|
+
{readonly}
|
|
98
|
+
{loading}
|
|
99
|
+
{block}
|
|
100
|
+
{width}
|
|
101
|
+
{leading}
|
|
102
|
+
{trailing}
|
|
103
|
+
clearable={clearable}
|
|
104
|
+
showClear={value != null}
|
|
105
|
+
onclear={() => { value = null; text = ''; onChange?.(null) }}
|
|
106
|
+
>
|
|
107
|
+
<input
|
|
108
|
+
use:mountFocus
|
|
109
|
+
class="sv-dur__input"
|
|
110
|
+
type="text"
|
|
111
|
+
inputmode="numeric"
|
|
112
|
+
value={text}
|
|
113
|
+
{placeholder}
|
|
114
|
+
{disabled}
|
|
115
|
+
{readonly}
|
|
116
|
+
oninput={(e) => (text = e.currentTarget.value)}
|
|
117
|
+
onfocus={() => (focused = true)}
|
|
118
|
+
onblur={() => { focused = false; commit() }}
|
|
119
|
+
onkeydown={(e) => {
|
|
120
|
+
if (e.key === 'Enter') { onCommit?.(commit()) }
|
|
121
|
+
else if (e.key === 'Escape') onCancel?.()
|
|
122
|
+
}}
|
|
123
|
+
{...editorAria({ id: uid, invalid, required, error, hint, ariaLabel })}
|
|
124
|
+
/>
|
|
125
|
+
{#if name}<input type="hidden" {name} value={value ?? ''} />{/if}
|
|
92
126
|
</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>
|
|
@@ -1,3 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SvDurationInput - a duration editor whose value is a number of MINUTES but
|
|
3
|
+
* which accepts the human forms people type ("1h 30m", "1:30", "90"). It shows
|
|
4
|
+
* a formatted value when unfocused and re-parses on blur / Enter. As a grid
|
|
5
|
+
* cell editor: Enter commits, Escape cancels. The box, size and invalid state
|
|
6
|
+
* are owned by SvField's `frame` chrome.
|
|
7
|
+
*/
|
|
8
|
+
import type { Snippet } from 'svelte';
|
|
1
9
|
import { type SvEditorProps } from './editor-contract';
|
|
2
10
|
type Props = SvEditorProps & {
|
|
3
11
|
/** Value in minutes (or null when empty). */
|
|
@@ -9,6 +17,16 @@ type Props = SvEditorProps & {
|
|
|
9
17
|
style?: 'colon' | 'units';
|
|
10
18
|
placeholder?: string;
|
|
11
19
|
autofocus?: boolean;
|
|
20
|
+
/** Show a clear (x) button when there is a value. */
|
|
21
|
+
clearable?: boolean;
|
|
22
|
+
/** Leading adornment (icon) inside the field. */
|
|
23
|
+
leading?: Snippet;
|
|
24
|
+
/** Trailing adornment (icon) inside the field. */
|
|
25
|
+
trailing?: Snippet;
|
|
26
|
+
/** Stretch to the container width. */
|
|
27
|
+
block?: boolean;
|
|
28
|
+
/** Control width in px (ignored when `block`). Default 160. */
|
|
29
|
+
width?: number;
|
|
12
30
|
};
|
|
13
31
|
declare const SvDurationInput: import("svelte").Component<Props, {}, "value">;
|
|
14
32
|
type SvDurationInput = ReturnType<typeof SvDurationInput>;
|