@svgrid/grid 2.1.22 → 2.2.0
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 +9 -2
- package/dist/DockNodeView.svelte +306 -0
- package/dist/DockNodeView.svelte.d.ts +7 -0
- package/dist/DockPopoutHost.svelte +17 -0
- package/dist/DockPopoutHost.svelte.d.ts +14 -0
- package/dist/FlexRender.svelte +96 -96
- package/dist/GridFooter.svelte +178 -178
- package/dist/GridMenus.svelte +83 -3
- package/dist/SvAutoComplete.svelte +5 -3
- package/dist/SvCarousel.svelte +141 -163
- package/dist/SvColorInput.svelte +187 -186
- package/dist/SvColorInput.svelte.d.ts +1 -1
- package/dist/SvComboBox.svelte +7 -3
- package/dist/SvCommand.svelte +28 -85
- package/dist/SvContextMenu.svelte +116 -116
- package/dist/SvCountryInput.svelte +1 -1
- package/dist/SvDateRangeInput.svelte +1 -1
- package/dist/SvDateTimePicker.svelte +9 -3
- package/dist/SvDateTimePicker.svelte.d.ts +3 -0
- package/dist/SvDockLayout.svelte +244 -0
- package/dist/SvDockLayout.svelte.d.ts +77 -0
- package/dist/SvDockManager.svelte +922 -0
- package/dist/SvDockManager.svelte.d.ts +106 -0
- package/dist/SvDrawer.svelte +250 -228
- package/dist/SvDrawer.svelte.d.ts +4 -0
- package/dist/SvDropDownList.svelte +85 -13
- package/dist/SvDropDownList.svelte.d.ts +3 -0
- package/dist/SvField.svelte +21 -4
- package/dist/SvField.svelte.d.ts +1 -0
- package/dist/SvForm.svelte +201 -91
- package/dist/SvForm.svelte.d.ts +15 -22
- package/dist/SvGrid.controller.svelte.d.ts +32 -1
- package/dist/SvGrid.controller.svelte.js +156 -27
- package/dist/SvGrid.css +193 -5
- package/dist/SvGrid.svelte +3131 -2786
- package/dist/SvGrid.types.d.ts +452 -1
- package/dist/SvGridBoard.svelte +2339 -2339
- package/dist/SvGridChart.svelte +1724 -1724
- package/dist/SvGridChartPanel.svelte +485 -485
- package/dist/SvGridDropdown.svelte +689 -682
- package/dist/SvGridSelect.svelte +1 -0
- package/dist/SvGroupCell.svelte +109 -109
- package/dist/SvListBox.svelte +36 -14
- package/dist/SvMaskedInput.svelte +4 -3
- package/dist/SvMaskedInput.svelte.d.ts +1 -1
- package/dist/SvMenu.svelte +124 -124
- package/dist/SvMenuList.svelte +117 -165
- package/dist/SvMenuList.svelte.d.ts +2 -13
- package/dist/SvModal.svelte +12 -29
- package/dist/SvMultiSelect.svelte +1 -0
- package/dist/SvNumberInput.svelte +131 -130
- package/dist/SvNumberInput.svelte.d.ts +1 -1
- package/dist/SvOtpInput.svelte +158 -158
- package/dist/SvPagination.svelte +18 -18
- package/dist/SvPasswordInput.svelte +3 -2
- package/dist/SvPasswordInput.svelte.d.ts +1 -1
- package/dist/SvPhoneInput.svelte +3 -2
- package/dist/SvPhoneInput.svelte.d.ts +1 -1
- package/dist/SvPopover.svelte +139 -139
- package/dist/SvRowGroupPanel.svelte +170 -170
- package/dist/SvScrollArea.svelte +61 -61
- package/dist/SvStepper.svelte +6 -9
- package/dist/SvTagsInput.svelte +3 -2
- package/dist/SvTagsInput.svelte.d.ts +1 -1
- package/dist/SvTooltip.svelte +127 -138
- package/dist/SvTour.svelte +204 -176
- package/dist/SvTree.svelte +377 -377
- package/dist/SvTreeSelect.svelte +230 -229
- package/dist/build-api.js +76 -54
- package/dist/cdn/svgrid.js +10913 -6450
- package/dist/cdn/svgrid.svelte-external.js +9628 -5481
- package/dist/chart-export.js +8 -8
- package/dist/columns.js +6 -0
- package/dist/conditional-formatting.d.ts +67 -3
- package/dist/conditional-formatting.js +124 -17
- package/dist/createCarousel.svelte.d.ts +72 -0
- package/dist/createCarousel.svelte.js +80 -0
- package/dist/createCommand.svelte.d.ts +62 -0
- package/dist/createCommand.svelte.js +109 -0
- package/dist/createForm.svelte.d.ts +62 -0
- package/dist/createForm.svelte.js +374 -0
- package/dist/createMenu.svelte.d.ts +88 -0
- package/dist/createMenu.svelte.js +153 -0
- package/dist/createOverlay.svelte.d.ts +38 -0
- package/dist/createOverlay.svelte.js +68 -0
- package/dist/createPagination.d.ts +74 -0
- package/dist/createPagination.js +71 -0
- package/dist/createPopoverSelect.svelte.js +6 -12
- package/dist/createStepper.d.ts +44 -0
- package/dist/createStepper.js +26 -0
- package/dist/createTooltip.svelte.d.ts +32 -0
- package/dist/createTooltip.svelte.js +61 -0
- package/dist/datetime/timezone.d.ts +36 -0
- package/dist/datetime/timezone.js +110 -0
- package/dist/dock-context.d.ts +52 -0
- package/dist/dock-context.js +1 -0
- package/dist/dock-manager-model.d.ts +136 -0
- package/dist/dock-manager-model.js +514 -0
- package/dist/dock-model.d.ts +105 -0
- package/dist/dock-model.js +288 -0
- package/dist/dock-popout.d.ts +30 -0
- package/dist/dock-popout.js +81 -0
- package/dist/editor-contract.d.ts +2 -0
- package/dist/filter-operators.d.ts +6 -0
- package/dist/filter-operators.js +35 -2
- package/dist/filtering/excel-filters.d.ts +18 -1
- package/dist/filtering/excel-filters.js +56 -0
- package/dist/form-field.d.ts +73 -0
- package/dist/form-field.js +15 -0
- package/dist/index.d.ts +25 -5
- package/dist/index.js +40 -4
- package/dist/list-nav.d.ts +18 -0
- package/dist/list-nav.js +30 -0
- package/dist/list-option.d.ts +2 -0
- package/dist/menu-item.d.ts +20 -0
- package/dist/menu-item.js +1 -0
- package/dist/menus.d.ts +5 -0
- package/dist/menus.js +68 -16
- package/dist/panel-resize.d.ts +25 -0
- package/dist/panel-resize.js +40 -0
- package/dist/popover.d.ts +29 -3
- package/dist/popover.js +22 -6
- package/dist/recurrence.d.ts +33 -7
- package/dist/recurrence.js +151 -13
- package/dist/row-drag.d.ts +8 -0
- package/dist/row-drag.js +11 -0
- package/dist/scheduler-ical.d.ts +30 -0
- package/dist/scheduler-ical.js +180 -0
- package/dist/scheduler-model.d.ts +269 -0
- package/dist/scheduler-model.js +602 -0
- package/dist/scheduler-view.svelte.d.ts +22 -0
- package/dist/scheduler-view.svelte.js +13 -0
- package/dist/spreadsheet.js +20 -12
- package/dist/ui-app.types.d.ts +3 -0
- package/package.json +14 -10
- package/src/DockNodeView.svelte +306 -0
- package/src/DockPopoutHost.svelte +17 -0
- package/src/FlexRender.svelte +96 -96
- package/src/GridFooter.svelte +178 -178
- package/src/GridMenus.svelte +83 -3
- package/src/SvAutoComplete.svelte +5 -3
- package/src/SvCarousel.svelte +141 -163
- package/src/SvCarousel.test.ts +68 -0
- package/src/SvColorInput.svelte +187 -186
- package/src/SvComboBox.svelte +7 -3
- package/src/SvCommand.svelte +28 -85
- package/src/SvCommand.test.ts +78 -0
- package/src/SvContextMenu.svelte +116 -116
- package/src/SvCountryInput.svelte +1 -1
- package/src/SvDateRangeInput.svelte +1 -1
- package/src/SvDateTimePicker.svelte +9 -3
- package/src/SvDockLayout.svelte +244 -0
- package/src/SvDockManager.svelte +922 -0
- package/src/SvDrawer.svelte +250 -228
- package/src/SvDropDownList.svelte +85 -13
- package/src/SvField.svelte +21 -4
- package/src/SvForm.svelte +201 -91
- package/src/SvForm.test.ts +299 -0
- package/src/SvGrid.controller.svelte.ts +3158 -3034
- package/src/SvGrid.css +193 -5
- package/src/SvGrid.svelte +3131 -2786
- package/src/SvGrid.types.ts +1489 -1027
- package/src/SvGridBoard.svelte +2339 -2339
- package/src/SvGridChart.svelte +1724 -1724
- package/src/SvGridChartPanel.svelte +485 -485
- package/src/SvGridDropdown.svelte +689 -682
- package/src/SvGridSelect.svelte +1 -0
- package/src/SvGroupCell.svelte +109 -109
- package/src/SvListBox.svelte +36 -14
- package/src/SvMaskedInput.svelte +4 -3
- package/src/SvMenu.svelte +124 -124
- package/src/SvMenu.test.ts +97 -73
- package/src/SvMenuList.svelte +117 -165
- package/src/SvModal.svelte +12 -29
- package/src/SvModal.test.ts +82 -0
- package/src/SvMultiSelect.svelte +1 -0
- package/src/SvNumberInput.svelte +131 -130
- package/src/SvOtpInput.svelte +158 -158
- package/src/SvPagination.svelte +18 -18
- package/src/SvPasswordInput.svelte +3 -2
- package/src/SvPhoneInput.svelte +3 -2
- package/src/SvPopover.svelte +139 -139
- package/src/SvRowGroupPanel.svelte +170 -170
- package/src/SvScrollArea.svelte +61 -61
- package/src/SvStepper.svelte +6 -9
- package/src/SvTagsInput.svelte +3 -2
- package/src/SvTooltip.svelte +127 -138
- package/src/SvTooltip.test.ts +73 -0
- package/src/SvTour.svelte +204 -176
- package/src/SvTree.svelte +377 -377
- package/src/SvTreeSelect.svelte +230 -229
- package/src/a11y.contract.test.ts +49 -49
- package/src/a11y.test.ts +59 -59
- package/src/a11y.ts +61 -61
- package/src/build-api.ts +870 -847
- package/src/cell-formatting.ts +169 -169
- package/src/cell-render.ts +469 -469
- package/src/chart-export.ts +201 -201
- package/src/chart.ts +2296 -2296
- package/src/collaboration.test.ts +104 -104
- package/src/collaboration.ts +167 -167
- package/src/columns.ts +5 -0
- package/src/conditional-formatting.test.ts +104 -0
- package/src/conditional-formatting.ts +176 -19
- package/src/core.performance.test.ts +30 -30
- package/src/core.ts +1111 -1111
- package/src/createAutocomplete.svelte.ts +132 -132
- package/src/createCarousel.svelte.ts +104 -0
- package/src/createCombobox.svelte.ts +179 -179
- package/src/createCommand.svelte.ts +125 -0
- package/src/createCountryInput.svelte.ts +157 -157
- package/src/createDropdownList.svelte.ts +162 -162
- package/src/createForm.svelte.ts +333 -0
- package/src/createGrid.svelte.ts +42 -42
- package/src/createGrid.test.ts +10 -10
- package/src/createGridState.svelte.ts +17 -17
- package/src/createMenu.svelte.ts +202 -0
- package/src/createOverlay.svelte.ts +101 -0
- package/src/createPagination.test.ts +65 -0
- package/src/createPagination.ts +84 -0
- package/src/createPopoverSelect.svelte.ts +206 -210
- package/src/createStepper.test.ts +62 -0
- package/src/createStepper.ts +61 -0
- package/src/createTooltip.svelte.ts +86 -0
- package/src/createTree.svelte.ts +319 -319
- package/src/datetime/timezone.test.ts +69 -0
- package/src/datetime/timezone.ts +134 -0
- package/src/dock-context.ts +47 -0
- package/src/dock-manager-model.test.ts +275 -0
- package/src/dock-manager-model.ts +593 -0
- package/src/dock-model.test.ts +163 -0
- package/src/dock-model.ts +368 -0
- package/src/dock-popout.ts +94 -0
- package/src/editing.test.ts +859 -859
- package/src/editing.ts +675 -675
- package/src/editor-contract.ts +2 -0
- package/src/export-data-api.test.ts +126 -126
- package/src/export-format.test.ts +107 -107
- package/src/export-format.ts +598 -598
- package/src/filter-operators.test.ts +59 -0
- package/src/filter-operators.ts +35 -2
- package/src/filtering/excel-filters.test.ts +86 -1
- package/src/filtering/excel-filters.ts +65 -0
- package/src/flex-render.ts +3 -3
- package/src/form-field.ts +87 -0
- package/src/index.ts +623 -469
- package/src/keyboard.test.ts +59 -59
- package/src/keyboard.ts +97 -97
- package/src/list-nav.test.ts +49 -0
- package/src/list-nav.ts +29 -0
- package/src/list-option.ts +2 -0
- package/src/menu-item.ts +21 -0
- package/src/menus.test.ts +48 -0
- package/src/menus.ts +639 -582
- package/src/merge-objects.ts +48 -48
- package/src/overlays.test.ts +90 -90
- package/src/panel-resize.ts +52 -0
- package/src/popover.bounds.test.ts +93 -0
- package/src/popover.ts +51 -7
- package/src/recurrence.test.ts +88 -1
- package/src/recurrence.ts +166 -15
- package/src/render-component.ts +28 -28
- package/src/row-drag.ts +10 -0
- package/src/scheduler-ical.test.ts +68 -0
- package/src/scheduler-ical.ts +180 -0
- package/src/scheduler-model.test.ts +546 -0
- package/src/scheduler-model.ts +853 -0
- package/src/scheduler-view.svelte.ts +33 -0
- package/src/selection.test.ts +754 -754
- package/src/selection.ts +600 -600
- package/src/server-data-source.test.ts +289 -289
- package/src/server-data-source.ts +413 -413
- package/src/sparkline.test.ts +68 -68
- package/src/sparkline.ts +169 -169
- package/src/spreadsheet.test.ts +489 -489
- package/src/spreadsheet.ts +312 -304
- package/src/static-functions.ts +11 -11
- package/src/subscribe.ts +38 -38
- package/src/svgrid-wrapper.types.ts +501 -501
- package/src/svgrid.behavior.test.ts +706 -706
- package/src/svgrid.charting.test.ts +527 -527
- package/src/svgrid.effect-driven-filter.svelte.test.ts +116 -0
- package/src/svgrid.features.test.ts +157 -157
- package/src/svgrid.new-features.wrapper.test.ts +251 -251
- package/src/svgrid.wrapper.test.ts +40 -40
- package/src/test-setup.ts +62 -62
- package/src/themes/index.ts +159 -159
- package/src/ui-app.types.ts +3 -0
- package/src/virtual.test.ts +6 -4
- package/src/virtualization/column-virtualizer.test.ts +27 -27
- package/src/virtualization/column-virtualizer.ts +30 -30
- package/src/virtualization/svelte-virtualizer.svelte.ts +26 -26
- package/src/virtualization/types.ts +30 -30
- package/src/virtualization/virtualizer.test.ts +47 -47
- package/src/virtualization/virtualizer.ts +296 -296
package/dist/SvColorInput.svelte
CHANGED
|
@@ -1,186 +1,187 @@
|
|
|
1
|
-
<script lang="ts">
|
|
2
|
-
/**
|
|
3
|
-
* SvColorInput - a color swatch that opens a portalled popover with a hex
|
|
4
|
-
* field, a native picker, and a preset palette. Parity: Smart `smart-color-input`.
|
|
5
|
-
* Emits a hex string. Popover escapes the grid scroll container via popover.ts.
|
|
6
|
-
*
|
|
7
|
-
* The styled renderer over the headless `createColorInput` core: hex
|
|
8
|
-
* normalization, palette, draft field and open/close state come from the core;
|
|
9
|
-
* the portal + anchored measurement stay here (render concerns).
|
|
10
|
-
*/
|
|
11
|
-
import { anchoredRect, portalToBody, popIn, type AnchoredRect } from './popover'
|
|
12
|
-
import { createDismissableLayer } from './a11y/dismissable'
|
|
13
|
-
import SvField from './SvField.svelte'
|
|
14
|
-
import { nextEditorId, resolveMessages, type SvEditorProps } from './editor-contract'
|
|
15
|
-
import { createColorInput } from './createColorInput.svelte'
|
|
16
|
-
|
|
17
|
-
/** User-facing strings for the color popover (localizable via `messages`). */
|
|
18
|
-
type ColorMessages = { dialog: string; picker: string; hex: string }
|
|
19
|
-
const DEFAULT_MESSAGES: ColorMessages = { dialog: 'Choose color', picker: 'Color picker', hex: 'Hex value' }
|
|
20
|
-
|
|
21
|
-
type Props = SvEditorProps & {
|
|
22
|
-
value?: string
|
|
23
|
-
onChange?: (hex: string) => void
|
|
24
|
-
/** Preset swatches. */
|
|
25
|
-
palette?: string[]
|
|
26
|
-
autoOpen?: boolean
|
|
27
|
-
/** Override the built-in popover strings. */
|
|
28
|
-
messages?: Partial<ColorMessages>
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
let {
|
|
32
|
-
value = '#3b82f6',
|
|
33
|
-
onChange,
|
|
34
|
-
disabled = false,
|
|
35
|
-
readonly = false,
|
|
36
|
-
palette,
|
|
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
|
-
messages,
|
|
49
|
-
}: Props = $props()
|
|
50
|
-
|
|
51
|
-
const autoId = nextEditorId('sv-color')
|
|
52
|
-
const uid = $derived(id ?? autoId)
|
|
53
|
-
const M = $derived(resolveMessages(DEFAULT_MESSAGES, messages))
|
|
54
|
-
|
|
55
|
-
const col = createColorInput({
|
|
56
|
-
value: () => value,
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
let
|
|
71
|
-
let
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
window.addEventListener('
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
window.removeEventListener('
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
class
|
|
107
|
-
class:is-
|
|
108
|
-
{
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
<span class="sv-
|
|
113
|
-
|
|
114
|
-
</
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
use:
|
|
122
|
-
|
|
123
|
-
style:
|
|
124
|
-
style:
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
<input
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
class
|
|
145
|
-
|
|
146
|
-
{
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
{
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
.sv-color--
|
|
164
|
-
.sv-color--
|
|
165
|
-
.sv-color
|
|
166
|
-
.sv-color.is-
|
|
167
|
-
.sv-color.is-invalid
|
|
168
|
-
.sv-color:focus-
|
|
169
|
-
.sv-
|
|
170
|
-
.sv-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
:global(.sv-
|
|
179
|
-
:global(.sv-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
:global(.sv-
|
|
185
|
-
:global(.sv-color__chip
|
|
186
|
-
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
/**
|
|
3
|
+
* SvColorInput - a color swatch that opens a portalled popover with a hex
|
|
4
|
+
* field, a native picker, and a preset palette. Parity: Smart `smart-color-input`.
|
|
5
|
+
* Emits a hex string. Popover escapes the grid scroll container via popover.ts.
|
|
6
|
+
*
|
|
7
|
+
* The styled renderer over the headless `createColorInput` core: hex
|
|
8
|
+
* normalization, palette, draft field and open/close state come from the core;
|
|
9
|
+
* the portal + anchored measurement stay here (render concerns).
|
|
10
|
+
*/
|
|
11
|
+
import { anchoredRect, portalToBody, popIn, type AnchoredRect } from './popover'
|
|
12
|
+
import { createDismissableLayer } from './a11y/dismissable'
|
|
13
|
+
import SvField from './SvField.svelte'
|
|
14
|
+
import { nextEditorId, resolveMessages, type SvEditorProps } from './editor-contract'
|
|
15
|
+
import { createColorInput } from './createColorInput.svelte'
|
|
16
|
+
|
|
17
|
+
/** User-facing strings for the color popover (localizable via `messages`). */
|
|
18
|
+
type ColorMessages = { dialog: string; picker: string; hex: string }
|
|
19
|
+
const DEFAULT_MESSAGES: ColorMessages = { dialog: 'Choose color', picker: 'Color picker', hex: 'Hex value' }
|
|
20
|
+
|
|
21
|
+
type Props = SvEditorProps & {
|
|
22
|
+
value?: string
|
|
23
|
+
onChange?: (hex: string) => void
|
|
24
|
+
/** Preset swatches. */
|
|
25
|
+
palette?: string[]
|
|
26
|
+
autoOpen?: boolean
|
|
27
|
+
/** Override the built-in popover strings. */
|
|
28
|
+
messages?: Partial<ColorMessages>
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
let {
|
|
32
|
+
value = $bindable('#3b82f6'),
|
|
33
|
+
onChange,
|
|
34
|
+
disabled = false,
|
|
35
|
+
readonly = false,
|
|
36
|
+
palette,
|
|
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
|
+
messages,
|
|
49
|
+
}: Props = $props()
|
|
50
|
+
|
|
51
|
+
const autoId = nextEditorId('sv-color')
|
|
52
|
+
const uid = $derived(id ?? autoId)
|
|
53
|
+
const M = $derived(resolveMessages(DEFAULT_MESSAGES, messages))
|
|
54
|
+
|
|
55
|
+
const col = createColorInput({
|
|
56
|
+
value: () => value,
|
|
57
|
+
// Write `value` (so `bind:value` works) AND fire `onChange` (callback users).
|
|
58
|
+
onChange: (hex) => { value = hex; onChange?.(hex) },
|
|
59
|
+
disabled: () => disabled,
|
|
60
|
+
readonly: () => readonly,
|
|
61
|
+
palette: () => palette as string[],
|
|
62
|
+
id: () => uid,
|
|
63
|
+
invalid: () => invalid,
|
|
64
|
+
required: () => required,
|
|
65
|
+
error: () => error,
|
|
66
|
+
hint: () => hint,
|
|
67
|
+
ariaLabel: () => ariaLabel,
|
|
68
|
+
})
|
|
69
|
+
|
|
70
|
+
let triggerEl = $state<HTMLButtonElement | null>(null)
|
|
71
|
+
let panelEl = $state<HTMLDivElement | null>(null)
|
|
72
|
+
let panelRect = $state<AnchoredRect>({ top: 0, left: 0, width: 0, openUpward: false, maxHeight: 0, availHeight: 0 })
|
|
73
|
+
|
|
74
|
+
function updatePos() {
|
|
75
|
+
if (!triggerEl) return
|
|
76
|
+
panelRect = anchoredRect(triggerEl.getBoundingClientRect(), { estimatedHeight: 210, minWidth: 200 })
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
$effect(() => {
|
|
80
|
+
if (!col.popover.open) return
|
|
81
|
+
updatePos()
|
|
82
|
+
const reposition = () => updatePos()
|
|
83
|
+
window.addEventListener('scroll', reposition, true)
|
|
84
|
+
window.addEventListener('resize', reposition)
|
|
85
|
+
const layer = createDismissableLayer({
|
|
86
|
+
element: () => [triggerEl, panelEl],
|
|
87
|
+
onDismiss: () => col.popover.close(),
|
|
88
|
+
})
|
|
89
|
+
layer.activate()
|
|
90
|
+
return () => {
|
|
91
|
+
window.removeEventListener('scroll', reposition, true)
|
|
92
|
+
window.removeEventListener('resize', reposition)
|
|
93
|
+
layer.release()
|
|
94
|
+
}
|
|
95
|
+
})
|
|
96
|
+
|
|
97
|
+
function focusOpen(node: HTMLButtonElement) {
|
|
98
|
+
if (!autoOpen) return
|
|
99
|
+
node.focus(); col.popover.show()
|
|
100
|
+
}
|
|
101
|
+
</script>
|
|
102
|
+
|
|
103
|
+
<SvField id={uid} {label} {hint} {error} {required} {dir}>
|
|
104
|
+
<button
|
|
105
|
+
bind:this={triggerEl}
|
|
106
|
+
class="sv-color sv-color--{size}"
|
|
107
|
+
class:is-disabled={disabled}
|
|
108
|
+
class:is-invalid={invalid}
|
|
109
|
+
{...col.swatchProps()}
|
|
110
|
+
use:focusOpen
|
|
111
|
+
>
|
|
112
|
+
<span class="sv-color__swatch" style:background={col.normalized}></span>
|
|
113
|
+
<span class="sv-color__hex">{col.normalized}</span>
|
|
114
|
+
</button>
|
|
115
|
+
</SvField>
|
|
116
|
+
|
|
117
|
+
{#if col.popover.open}
|
|
118
|
+
<div
|
|
119
|
+
class="sv-color__panel"
|
|
120
|
+
bind:this={panelEl}
|
|
121
|
+
use:portalToBody
|
|
122
|
+
use:popIn={{ up: panelRect.openUpward }}
|
|
123
|
+
style:position="fixed"
|
|
124
|
+
style:top={`${panelRect.top}px`}
|
|
125
|
+
style:left={`${panelRect.left}px`}
|
|
126
|
+
role="dialog"
|
|
127
|
+
aria-label={M.dialog}
|
|
128
|
+
>
|
|
129
|
+
<div class="sv-color__top">
|
|
130
|
+
<input class="sv-color__native" type="color" value={col.normalized} oninput={(e) => col.pick((e.currentTarget as HTMLInputElement).value)} aria-label={M.picker} />
|
|
131
|
+
<input
|
|
132
|
+
class="sv-color__field"
|
|
133
|
+
type="text"
|
|
134
|
+
bind:value={col.hexDraft}
|
|
135
|
+
spellcheck="false"
|
|
136
|
+
aria-label={M.hex}
|
|
137
|
+
onblur={col.commitHex}
|
|
138
|
+
onkeydown={(e) => { if (e.key === 'Enter') col.commitHex() }}
|
|
139
|
+
/>
|
|
140
|
+
</div>
|
|
141
|
+
<div class="sv-color__palette">
|
|
142
|
+
{#each col.palette as c (c)}
|
|
143
|
+
<button
|
|
144
|
+
class="sv-color__chip"
|
|
145
|
+
class:is-active={col.isActive(c)}
|
|
146
|
+
style:background={c}
|
|
147
|
+
{...col.chipProps(c)}
|
|
148
|
+
></button>
|
|
149
|
+
{/each}
|
|
150
|
+
</div>
|
|
151
|
+
</div>
|
|
152
|
+
{/if}
|
|
153
|
+
{#if name}<input type="hidden" {name} value={col.normalized} />{/if}
|
|
154
|
+
|
|
155
|
+
<style>
|
|
156
|
+
.sv-color {
|
|
157
|
+
--_accent: var(--sg-accent, #2563eb);
|
|
158
|
+
display: inline-flex; align-items: center; gap: 8px;
|
|
159
|
+
background: var(--sg-input-bg, #fff); color: var(--sg-fg, #0f172a);
|
|
160
|
+
border: 1px solid var(--sg-input-border, var(--sg-border, #cbd5e1)); border-radius: var(--sg-radius, 8px);
|
|
161
|
+
padding: 0 10px; cursor: pointer; font: inherit;
|
|
162
|
+
}
|
|
163
|
+
.sv-color--sm { height: 28px; font-size: 12px; }
|
|
164
|
+
.sv-color--md { height: 34px; font-size: 13px; }
|
|
165
|
+
.sv-color--lg { height: 40px; font-size: 15px; }
|
|
166
|
+
.sv-color.is-disabled { opacity: 0.6; cursor: not-allowed; }
|
|
167
|
+
.sv-color.is-invalid { border-color: var(--sg-danger, #dc2626); }
|
|
168
|
+
.sv-color.is-invalid:focus-within { box-shadow: 0 0 0 2px color-mix(in srgb, var(--sg-danger, #dc2626) 22%, transparent); }
|
|
169
|
+
.sv-color:focus-visible { outline: 2px solid var(--sg-focus-ring, var(--_accent)); outline-offset: 2px; }
|
|
170
|
+
.sv-color__swatch { width: 18px; height: 18px; border-radius: 4px; border: 1px solid rgba(0,0,0,0.15); flex: none; }
|
|
171
|
+
.sv-color__hex { font-variant-numeric: tabular-nums; text-transform: lowercase; }
|
|
172
|
+
|
|
173
|
+
:global(.sv-color__panel) {
|
|
174
|
+
z-index: 2147483647; width: 208px; padding: 12px;
|
|
175
|
+
background: var(--sg-bg, #fff); border: 1px solid var(--sg-border, #e2e8f0);
|
|
176
|
+
border-radius: 12px; box-shadow: 0 16px 48px -12px rgba(15,23,42,0.35);
|
|
177
|
+
}
|
|
178
|
+
:global(.sv-color__top) { display: flex; gap: 8px; margin-bottom: 10px; }
|
|
179
|
+
:global(.sv-color__native) { width: 36px; height: 34px; padding: 0; border: 1px solid var(--sg-border, #e2e8f0); border-radius: 8px; background: none; cursor: pointer; }
|
|
180
|
+
:global(.sv-color__field) {
|
|
181
|
+
flex: 1; min-width: 0; height: 34px; padding: 0 10px; font: inherit; font-size: 13px;
|
|
182
|
+
border: 1px solid var(--sg-input-border, #cbd5e1); border-radius: 8px; background: var(--sg-input-bg, #fff); color: var(--sg-fg, #0f172a); outline: none;
|
|
183
|
+
}
|
|
184
|
+
:global(.sv-color__palette) { display: grid; grid-template-columns: repeat(10, 1fr); gap: 4px; }
|
|
185
|
+
:global(.sv-color__chip) { width: 100%; aspect-ratio: 1; border-radius: 5px; border: 1px solid rgba(0,0,0,0.12); cursor: pointer; padding: 0; }
|
|
186
|
+
:global(.sv-color__chip.is-active) { outline: 2px solid var(--sg-accent, #2563eb); outline-offset: 1px; }
|
|
187
|
+
</style>
|
|
@@ -14,6 +14,6 @@ type Props = SvEditorProps & {
|
|
|
14
14
|
/** Override the built-in popover strings. */
|
|
15
15
|
messages?: Partial<ColorMessages>;
|
|
16
16
|
};
|
|
17
|
-
declare const SvColorInput: import("svelte").Component<Props, {}, "">;
|
|
17
|
+
declare const SvColorInput: import("svelte").Component<Props, {}, "value">;
|
|
18
18
|
type SvColorInput = ReturnType<typeof SvColorInput>;
|
|
19
19
|
export default SvColorInput;
|
package/dist/SvComboBox.svelte
CHANGED
|
@@ -65,7 +65,7 @@
|
|
|
65
65
|
let inputEl = $state<HTMLInputElement | null>(null)
|
|
66
66
|
let fieldEl = $state<HTMLDivElement | null>(null)
|
|
67
67
|
let panelEl = $state<HTMLDivElement | null>(null)
|
|
68
|
-
let rect = $state<AnchoredRect>({ top: 0, left: 0, width: 0, openUpward: false })
|
|
68
|
+
let rect = $state<AnchoredRect>({ top: 0, left: 0, width: 0, openUpward: false, maxHeight: 0, availHeight: 0 })
|
|
69
69
|
|
|
70
70
|
// Remote data source: fetch options as the query changes (debounced).
|
|
71
71
|
let remoteOptions = $state<ListOption[]>([])
|
|
@@ -111,7 +111,11 @@
|
|
|
111
111
|
|
|
112
112
|
function updatePos() {
|
|
113
113
|
if (!fieldEl) return
|
|
114
|
-
|
|
114
|
+
// estimatedHeight only picks the flip direction (up vs down); the panel's
|
|
115
|
+
// real max-height comes from availHeight below, so it takes its natural
|
|
116
|
+
// content height (options + group labels) and scrolls only when it truly
|
|
117
|
+
// overflows the room - never from an estimate that under-counts a row.
|
|
118
|
+
rect = anchoredRect(fieldEl.getBoundingClientRect(), { estimatedHeight: Math.min(combo.filtered.length, 8) * 34 + 12 })
|
|
115
119
|
}
|
|
116
120
|
|
|
117
121
|
// Position + reposition + outside-click close are render concerns (need the DOM).
|
|
@@ -150,7 +154,7 @@
|
|
|
150
154
|
</SvField>
|
|
151
155
|
|
|
152
156
|
{#if combo.open}
|
|
153
|
-
<div bind:this={panelEl} class="sv-ddl__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`} {...combo.listboxProps()}>
|
|
157
|
+
<div bind:this={panelEl} class="sv-ddl__panel" use:portalToBody use:popIn={{ up: rect.openUpward }} style:position="fixed" style:top={rect.openUpward ? undefined : `${rect.top}px`} style:bottom={rect.openUpward ? `${rect.bottom}px` : undefined} style:left={`${rect.left}px`} style:min-width={`${rect.width}px`} style:max-height={`${Math.min(rect.availHeight, 288)}px`} {...combo.listboxProps()}>
|
|
154
158
|
{#if loading}
|
|
155
159
|
<div class="sv-ddl__empty sv-ddl__loading"><svg class="sv-ddl__spin" viewBox="0 0 24 24" width="14" height="14" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round"><path d="M21 12a9 9 0 1 1-6.2-8.6" /></svg>{M.loading}</div>
|
|
156
160
|
{:else if loadOptions && !searched && combo.query.trim().length < minLength}
|
package/dist/SvCommand.svelte
CHANGED
|
@@ -16,10 +16,8 @@
|
|
|
16
16
|
*/
|
|
17
17
|
import type { CommandItem } from './ui-app.types'
|
|
18
18
|
import { portalToBody, popIn } from './popover'
|
|
19
|
-
import {
|
|
20
|
-
import {
|
|
21
|
-
import { createDismissableLayer } from './a11y/dismissable'
|
|
22
|
-
import { fuzzyScore } from './fuzzy'
|
|
19
|
+
import { createOverlay } from './createOverlay.svelte'
|
|
20
|
+
import { createCommand } from './createCommand.svelte'
|
|
23
21
|
|
|
24
22
|
type Props = {
|
|
25
23
|
open?: boolean
|
|
@@ -42,72 +40,29 @@
|
|
|
42
40
|
hotkey = 'mod+k',
|
|
43
41
|
}: Props = $props()
|
|
44
42
|
|
|
45
|
-
let query = $state('')
|
|
46
|
-
let active = $state(0)
|
|
47
43
|
let panelEl = $state<HTMLDivElement | null>(null)
|
|
48
44
|
let inputEl = $state<HTMLInputElement | null>(null)
|
|
49
45
|
|
|
50
|
-
const results = $derived.by(() => {
|
|
51
|
-
const q = query.trim()
|
|
52
|
-
const list = commands.filter((c) => !c.disabled)
|
|
53
|
-
if (!q) return list
|
|
54
|
-
return list
|
|
55
|
-
.map((c) => ({ c, s: fuzzyScore(`${c.label} ${c.keywords ?? ''} ${c.group ?? ''}`, q) }))
|
|
56
|
-
.filter((x) => x.s !== null)
|
|
57
|
-
.sort((a, b) => (b.s as number) - (a.s as number))
|
|
58
|
-
.map((x) => x.c)
|
|
59
|
-
})
|
|
60
|
-
|
|
61
46
|
function close() { open = false; onClose?.() }
|
|
62
|
-
function run(cmd: CommandItem | undefined) {
|
|
63
|
-
if (!cmd || cmd.disabled) return
|
|
64
|
-
close()
|
|
65
|
-
onRun?.(cmd)
|
|
66
|
-
cmd.onRun?.()
|
|
67
|
-
}
|
|
68
|
-
function move(delta: number) {
|
|
69
|
-
const n = results.length
|
|
70
|
-
if (!n) return
|
|
71
|
-
active = (active + delta + n) % n
|
|
72
|
-
queueMicrotask(() =>
|
|
73
|
-
panelEl?.querySelector(`[data-idx="${active}"]`)?.scrollIntoView({ block: 'nearest' }),
|
|
74
|
-
)
|
|
75
|
-
}
|
|
76
|
-
function onKeydown(e: KeyboardEvent) {
|
|
77
|
-
if (e.key === 'ArrowDown') { e.preventDefault(); move(1) }
|
|
78
|
-
else if (e.key === 'ArrowUp') { e.preventDefault(); move(-1) }
|
|
79
|
-
else if (e.key === 'Enter') { e.preventDefault(); run(results[active]) }
|
|
80
|
-
// Escape + outside-click are owned by the dismissable layer.
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
// Reset active whenever the query changes.
|
|
84
|
-
$effect(() => { void query; active = 0 })
|
|
85
47
|
|
|
86
|
-
//
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
48
|
+
// Fuzzy filter + roving + run + hotkey live in the command core; the overlay
|
|
49
|
+
// lifecycle (focus-trap into the input, scroll-lock, Escape/outside dismissal)
|
|
50
|
+
// is the shared dialog core.
|
|
51
|
+
const cmd = createCommand({
|
|
52
|
+
commands: () => commands,
|
|
53
|
+
open: () => open,
|
|
54
|
+
onRun,
|
|
55
|
+
onClose: close,
|
|
56
|
+
onToggleOpen: () => (open = !open),
|
|
57
|
+
hotkey: () => hotkey,
|
|
58
|
+
scrollActiveIntoView: (i) =>
|
|
59
|
+
queueMicrotask(() => panelEl?.querySelector(`[data-idx="${i}"]`)?.scrollIntoView({ block: 'nearest' })),
|
|
97
60
|
})
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
const onKey = (e: KeyboardEvent) => {
|
|
104
|
-
if ((e.metaKey || e.ctrlKey) && e.key.toLowerCase() === key) {
|
|
105
|
-
e.preventDefault()
|
|
106
|
-
open = !open
|
|
107
|
-
}
|
|
108
|
-
}
|
|
109
|
-
window.addEventListener('keydown', onKey)
|
|
110
|
-
return () => window.removeEventListener('keydown', onKey)
|
|
61
|
+
const overlay = createOverlay({
|
|
62
|
+
open: () => open,
|
|
63
|
+
getDialog: () => panelEl,
|
|
64
|
+
onClose: close,
|
|
65
|
+
initialFocus: () => inputEl,
|
|
111
66
|
})
|
|
112
67
|
</script>
|
|
113
68
|
|
|
@@ -117,11 +72,8 @@
|
|
|
117
72
|
bind:this={panelEl}
|
|
118
73
|
class="sv-cmd"
|
|
119
74
|
use:popIn={{}}
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
aria-label="Command palette"
|
|
123
|
-
tabindex="-1"
|
|
124
|
-
onkeydown={onKeydown}
|
|
75
|
+
{...overlay.dialogProps({ label: 'Command palette' })}
|
|
76
|
+
onkeydown={cmd.onKeydown}
|
|
125
77
|
>
|
|
126
78
|
<div class="sv-cmd__search">
|
|
127
79
|
<span class="sv-cmd__searchicon" aria-hidden="true">⌕</span>
|
|
@@ -129,29 +81,20 @@
|
|
|
129
81
|
bind:this={inputEl}
|
|
130
82
|
class="sv-cmd__input"
|
|
131
83
|
type="text"
|
|
132
|
-
|
|
133
|
-
aria-expanded="true"
|
|
134
|
-
aria-controls="sv-cmd-list"
|
|
135
|
-
aria-activedescendant={results[active] ? `sv-cmd-opt-${active}` : undefined}
|
|
84
|
+
aria-label="Command palette search"
|
|
136
85
|
{placeholder}
|
|
137
|
-
|
|
138
|
-
oninput={(e) => (query = e.currentTarget.value)}
|
|
86
|
+
{...cmd.inputProps()}
|
|
139
87
|
/>
|
|
140
88
|
</div>
|
|
141
|
-
<ul class="sv-cmd__list"
|
|
142
|
-
{#each results as c, i (c.id)}
|
|
143
|
-
{#if !query.trim() && c.group && c.group !== results[i - 1]?.group}
|
|
89
|
+
<ul class="sv-cmd__list" aria-label="Commands" {...cmd.listProps()}>
|
|
90
|
+
{#each cmd.results as c, i (c.id)}
|
|
91
|
+
{#if !cmd.query.trim() && c.group && c.group !== cmd.results[i - 1]?.group}
|
|
144
92
|
<li class="sv-cmd__group" role="presentation">{c.group}</li>
|
|
145
93
|
{/if}
|
|
146
94
|
<li
|
|
147
|
-
id={`sv-cmd-opt-${i}`}
|
|
148
|
-
data-idx={i}
|
|
149
95
|
class="sv-cmd__opt"
|
|
150
|
-
class:is-active={i
|
|
151
|
-
|
|
152
|
-
aria-selected={i === active}
|
|
153
|
-
onpointermove={() => (active = i)}
|
|
154
|
-
onclick={() => run(c)}
|
|
96
|
+
class:is-active={cmd.isActive(i)}
|
|
97
|
+
{...cmd.optionProps(i)}
|
|
155
98
|
>
|
|
156
99
|
{#if c.icon}<span class="sv-cmd__icon" aria-hidden="true">{c.icon}</span>{/if}
|
|
157
100
|
<span class="sv-cmd__label">{c.label}</span>
|