@svgrid/grid 2.2.27 → 2.2.29
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 +199 -199
- package/dist/FlexRender.svelte +96 -96
- package/dist/GridFooter.svelte +179 -179
- package/dist/GridMenus.svelte +782 -734
- package/dist/SvAutoComplete.svelte +165 -165
- package/dist/SvCalendar.svelte +503 -503
- package/dist/SvCarousel.svelte +141 -141
- package/dist/SvCheckBox.svelte +101 -101
- package/dist/SvColorInput.svelte +181 -181
- package/dist/SvComboBox.svelte +275 -275
- package/dist/SvContextMenu.svelte +116 -116
- package/dist/SvCountryInput.svelte +160 -160
- package/dist/SvDrawer.svelte +254 -250
- package/dist/SvDropDownList.svelte +374 -374
- package/dist/SvDurationInput.svelte +126 -126
- package/dist/SvField.svelte +293 -293
- package/dist/SvForm.svelte +437 -437
- package/dist/SvGrid.controller.svelte.d.ts +14 -1
- package/dist/SvGrid.controller.svelte.js +112 -28
- package/dist/SvGrid.css +2704 -2723
- package/dist/SvGrid.svelte +3361 -3333
- package/dist/SvGrid.types.d.ts +20 -5
- package/dist/SvGridChart.svelte +1724 -1724
- package/dist/SvGridChartPanel.svelte +485 -485
- package/dist/SvGridChartView.svelte +70 -70
- package/dist/SvGridDropdown.svelte +696 -696
- package/dist/SvGridSelect.svelte +259 -259
- package/dist/SvGroupCell.svelte +109 -109
- package/dist/SvListBox.svelte +326 -287
- package/dist/SvListBox.svelte.d.ts +10 -1
- package/dist/SvMaskedInput.svelte +122 -122
- package/dist/SvMenu.svelte +124 -124
- package/dist/SvMenuList.svelte +146 -146
- package/dist/SvMultiSelect.svelte +281 -281
- package/dist/SvNumberInput.svelte +168 -168
- package/dist/SvOtpInput.svelte +158 -158
- package/dist/SvPasswordInput.svelte +151 -151
- package/dist/SvPhoneInput.svelte +133 -131
- package/dist/SvPopover.svelte +197 -197
- package/dist/SvRadioGroup.svelte +107 -107
- package/dist/SvRowGroupPanel.svelte +170 -170
- package/dist/SvScrollArea.svelte +61 -61
- package/dist/SvSlider.svelte +200 -200
- package/dist/SvSwitchButton.svelte +107 -107
- package/dist/SvTagsInput.svelte +112 -112
- package/dist/SvTextInput.svelte +147 -147
- package/dist/SvTimePicker.svelte +245 -245
- package/dist/SvToaster.svelte +159 -159
- package/dist/SvToggleButton.svelte +85 -85
- package/dist/SvTooltip.svelte +161 -161
- package/dist/SvTour.svelte +204 -204
- package/dist/SvTree.svelte +437 -437
- package/dist/SvTreeSelect.svelte +233 -233
- package/dist/cdn/GridMenus-Da_p7SKS.js +486 -0
- package/dist/cdn/GridMenus-Ds3OpzZT.js +490 -0
- package/dist/cdn/{SvDateTimePicker-B1sDc9Pz.js → SvDateTimePicker-B8GopjhC.js} +2 -2
- package/dist/cdn/{SvDateTimePicker-Bh0FTs1E.js → SvDateTimePicker-DB0aIEk8.js} +2 -2
- package/dist/cdn/{SvGridChart-Bgk4hDs8.js → SvGridChart-BcLCYvw9.js} +1 -1
- package/dist/cdn/{SvGridChart-BKQsO5fZ.js → SvGridChart-BhnFdLd0.js} +1 -1
- package/dist/cdn/{SvGridChartPanel-DkCc2Z7b.js → SvGridChartPanel-Cmx9DHAS.js} +1 -1
- package/dist/cdn/{SvGridChartPanel-DSkHIQDd.js → SvGridChartPanel-DvjwxLvK.js} +1 -1
- package/dist/cdn/{SvGridChartView-BrbVaELm.js → SvGridChartView-B40DTJSX.js} +1 -1
- package/dist/cdn/{SvGridChartView-i9rWvSKg.js → SvGridChartView-PwqI4s02.js} +1 -1
- package/dist/cdn/{SvGridDropdown-D08sVmAy.js → SvGridDropdown-DjALc_4f.js} +1 -1
- package/dist/cdn/{SvGridDropdown-CGxxopQ4.js → SvGridDropdown-hpnHvOGt.js} +1 -1
- package/dist/cdn/{src-cgs1wcUS.js → src-BLJfdyL0.js} +4034 -3889
- package/dist/cdn/{src-Cw8d9U8j.js → src-DYDCiC0D.js} +7053 -6908
- package/dist/cdn/svgrid.js +9 -9
- package/dist/cdn/svgrid.svelte-external.js +9 -9
- package/dist/chart-export.js +8 -8
- package/dist/column-groups.js +8 -10
- package/dist/column-id.d.ts +9 -0
- package/dist/column-id.js +25 -0
- package/dist/core.js +2 -1
- package/dist/createListbox.svelte.d.ts +15 -2
- package/dist/createListbox.svelte.js +27 -6
- package/dist/editing.d.ts +1 -0
- package/dist/editing.js +45 -10
- package/dist/filtering/excel-filters.d.ts +30 -10
- package/dist/filtering/excel-filters.js +96 -15
- package/dist/index.d.ts +2 -2
- package/dist/index.js +2 -2
- package/dist/menus.d.ts +2 -0
- package/dist/menus.js +25 -0
- package/dist/row-resize.js +40 -0
- package/dist/selection.js +1 -1
- package/package.json +10 -10
- package/src/FlexRender.svelte +96 -96
- package/src/GridFooter.svelte +179 -179
- package/src/GridMenus.svelte +782 -734
- package/src/SvAutoComplete.svelte +165 -165
- package/src/SvCalendar.svelte +503 -503
- package/src/SvCalendar.test.ts +226 -226
- package/src/SvCarousel.svelte +141 -141
- package/src/SvCheckBox.svelte +101 -101
- package/src/SvColorInput.svelte +181 -181
- package/src/SvComboBox.svelte +275 -275
- package/src/SvContextMenu.svelte +116 -116
- package/src/SvCountryInput.svelte +160 -160
- package/src/SvDrawer.svelte +254 -250
- package/src/SvDrawer.test.ts +18 -1
- package/src/SvDropDownList.svelte +374 -374
- package/src/SvDurationInput.svelte +126 -126
- package/src/SvField.svelte +293 -293
- package/src/SvForm.svelte +437 -437
- package/src/SvForm.test.ts +411 -411
- package/src/SvGrid.controller.svelte.ts +3335 -3239
- package/src/SvGrid.css +2704 -2723
- package/src/SvGrid.svelte +3361 -3333
- package/src/SvGrid.types.ts +1628 -1613
- package/src/SvGridChart.svelte +1724 -1724
- package/src/SvGridChartPanel.svelte +485 -485
- package/src/SvGridChartView.svelte +70 -70
- package/src/SvGridDropdown.svelte +696 -696
- package/src/SvGridSelect.svelte +259 -259
- package/src/SvGroupCell.svelte +109 -109
- package/src/SvListBox.svelte +326 -287
- package/src/SvMaskedInput.svelte +122 -122
- package/src/SvMenu.svelte +124 -124
- package/src/SvMenu.test.ts +97 -97
- package/src/SvMenuList.svelte +146 -146
- package/src/SvMultiSelect.svelte +281 -281
- package/src/SvNavPane.test.ts +15 -4
- package/src/SvNumberInput.svelte +168 -168
- package/src/SvOtpInput.svelte +158 -158
- package/src/SvPasswordInput.svelte +151 -151
- package/src/SvPhoneInput.svelte +133 -131
- package/src/SvPopover.svelte +197 -197
- package/src/SvRadioGroup.svelte +107 -107
- package/src/SvRowGroupPanel.svelte +170 -170
- package/src/SvScrollArea.svelte +61 -61
- package/src/SvSlider.svelte +200 -200
- package/src/SvSwitchButton.svelte +107 -107
- package/src/SvTagsInput.svelte +112 -112
- package/src/SvTextInput.svelte +147 -147
- package/src/SvTimePicker.svelte +245 -245
- package/src/SvToaster.svelte +159 -159
- package/src/SvToaster.test.ts +95 -95
- package/src/SvToggleButton.svelte +85 -85
- package/src/SvTooltip.svelte +161 -161
- package/src/SvTour.svelte +204 -204
- package/src/SvTree.svelte +437 -437
- package/src/SvTreeSelect.svelte +233 -233
- package/src/a11y/dismissable.test.ts +119 -119
- package/src/a11y/dismissable.ts +114 -114
- package/src/a11y.contract.test.ts +49 -49
- package/src/a11y.test.ts +59 -59
- package/src/a11y.ts +61 -61
- package/src/ai.test.ts +502 -502
- package/src/ai.ts +1391 -1391
- package/src/build-api.coverage.test.ts +633 -633
- package/src/build-api.ts +895 -895
- package/src/builtin-editors.grid.test.ts +85 -85
- package/src/cell-formatting.ts +169 -169
- package/src/cell-render.ts +469 -469
- package/src/chart-export.ts +201 -201
- package/src/chart-view.svelte.ts +36 -36
- package/src/chart.ts +2296 -2296
- package/src/collaboration.test.ts +104 -104
- package/src/collaboration.ts +167 -167
- package/src/column-groups.test.ts +48 -0
- package/src/column-groups.ts +8 -10
- package/src/column-id.ts +30 -0
- package/src/core.performance.test.ts +30 -30
- package/src/core.ts +1112 -1111
- package/src/createAutocomplete.svelte.ts +132 -132
- package/src/createCombobox.svelte.ts +191 -191
- package/src/createCountryInput.svelte.ts +157 -157
- package/src/createDropdownList.svelte.ts +168 -168
- package/src/createForm.svelte.ts +386 -386
- package/src/createGrid.svelte.ts +42 -42
- package/src/createGrid.test.ts +10 -10
- package/src/createGridState.svelte.ts +17 -17
- package/src/createListbox.svelte.ts +39 -7
- package/src/createMenu.svelte.ts +225 -225
- package/src/createPopoverSelect.svelte.ts +213 -213
- package/src/createSlider.svelte.ts +191 -191
- package/src/createTooltip.svelte.ts +144 -144
- package/src/createTree.svelte.ts +319 -319
- package/src/editing.test.ts +949 -859
- package/src/editing.ts +709 -675
- package/src/editor-contract.ts +157 -157
- 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.ts +157 -157
- package/src/filtering/excel-filters.test.ts +44 -1
- package/src/filtering/excel-filters.ts +91 -14
- package/src/flex-render.ts +3 -3
- package/src/form-field.ts +127 -127
- package/src/index.ts +715 -713
- package/src/js-scroller.svelte.ts +173 -173
- package/src/keyboard.test.ts +59 -59
- package/src/keyboard.ts +97 -97
- package/src/list-nav.test.ts +49 -49
- package/src/list-nav.ts +29 -29
- package/src/list-option.test.ts +56 -56
- package/src/list-option.ts +172 -172
- package/src/menus.test.ts +736 -700
- package/src/menus.ts +679 -652
- package/src/merge-objects.ts +48 -48
- package/src/overlays.test.ts +90 -90
- package/src/render-component.ts +28 -28
- package/src/row-resize.test.ts +100 -0
- package/src/row-resize.ts +36 -0
- package/src/scheduler-model.test.ts +562 -562
- package/src/scheduler-model.ts +872 -872
- 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 -312
- package/src/static-functions.ts +11 -11
- package/src/subscribe.ts +38 -38
- package/src/svgrid-wrapper.types.ts +524 -524
- package/src/svgrid.api-extensions.test.ts +8 -3
- package/src/svgrid.behavior.test.ts +706 -706
- package/src/svgrid.cell-dom-ids.test.ts +96 -0
- package/src/svgrid.charting.test.ts +534 -534
- package/src/svgrid.conditional-stat-scope.test.ts +111 -0
- package/src/svgrid.features.test.ts +157 -157
- package/src/svgrid.filter-menu-listbox.svelte.test.ts +308 -0
- package/src/svgrid.filter-menu-scroll.test.ts +3 -1
- package/src/svgrid.group-header-ids.test.ts +121 -0
- 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 +215 -215
- package/src/toast-store.svelte.ts +246 -246
- package/src/toast-store.test.ts +147 -147
- package/src/ui-buttons.test.ts +144 -144
- package/src/ui-inputs.test.ts +118 -118
- package/src/ui-range.test.ts +70 -70
- package/src/ui-selection.test.ts +155 -155
- package/src/ui-tier1.test.ts +142 -142
- package/src/virtual.test.ts +88 -88
- 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/themes/ember.css +71 -71
- package/dist/cdn/GridMenus-BzxEYNtW.js +0 -421
- package/dist/cdn/GridMenus-Dr-nGEXn.js +0 -417
package/src/createGrid.svelte.ts
CHANGED
|
@@ -1,42 +1,42 @@
|
|
|
1
|
-
import { createSvGridCore } from './core'
|
|
2
|
-
import type {
|
|
3
|
-
RowData,
|
|
4
|
-
SvGrid,
|
|
5
|
-
SvGridOptions,
|
|
6
|
-
TableFeatures,
|
|
7
|
-
} from './core'
|
|
8
|
-
|
|
9
|
-
export type SvelteGrid<
|
|
10
|
-
TFeatures extends TableFeatures,
|
|
11
|
-
TData extends RowData,
|
|
12
|
-
TSelected = {},
|
|
13
|
-
> = SvGrid<TData> & {
|
|
14
|
-
readonly state: Readonly<TSelected>
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
export function createSvGrid<
|
|
18
|
-
TFeatures extends TableFeatures,
|
|
19
|
-
TData extends RowData,
|
|
20
|
-
TSelected = {},
|
|
21
|
-
>(
|
|
22
|
-
gridOptions: SvGridOptions<TFeatures, TData>,
|
|
23
|
-
selector: (state: Record<string, any>) => TSelected = () => ({}) as TSelected,
|
|
24
|
-
): SvelteGrid<TFeatures, TData, TSelected> {
|
|
25
|
-
const grid = createSvGridCore(gridOptions) as SvelteGrid<TFeatures, TData, TSelected>
|
|
26
|
-
let selected = $state(selector(grid.store.state))
|
|
27
|
-
grid.store.subscribe(() => {
|
|
28
|
-
selected = selector(grid.store.state)
|
|
29
|
-
})
|
|
30
|
-
|
|
31
|
-
Object.defineProperty(grid, 'state', {
|
|
32
|
-
get() {
|
|
33
|
-
return selected
|
|
34
|
-
},
|
|
35
|
-
configurable: true,
|
|
36
|
-
enumerable: true,
|
|
37
|
-
})
|
|
38
|
-
|
|
39
|
-
return grid
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
export const createGrid = createSvGrid
|
|
1
|
+
import { createSvGridCore } from './core'
|
|
2
|
+
import type {
|
|
3
|
+
RowData,
|
|
4
|
+
SvGrid,
|
|
5
|
+
SvGridOptions,
|
|
6
|
+
TableFeatures,
|
|
7
|
+
} from './core'
|
|
8
|
+
|
|
9
|
+
export type SvelteGrid<
|
|
10
|
+
TFeatures extends TableFeatures,
|
|
11
|
+
TData extends RowData,
|
|
12
|
+
TSelected = {},
|
|
13
|
+
> = SvGrid<TData> & {
|
|
14
|
+
readonly state: Readonly<TSelected>
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export function createSvGrid<
|
|
18
|
+
TFeatures extends TableFeatures,
|
|
19
|
+
TData extends RowData,
|
|
20
|
+
TSelected = {},
|
|
21
|
+
>(
|
|
22
|
+
gridOptions: SvGridOptions<TFeatures, TData>,
|
|
23
|
+
selector: (state: Record<string, any>) => TSelected = () => ({}) as TSelected,
|
|
24
|
+
): SvelteGrid<TFeatures, TData, TSelected> {
|
|
25
|
+
const grid = createSvGridCore(gridOptions) as SvelteGrid<TFeatures, TData, TSelected>
|
|
26
|
+
let selected = $state(selector(grid.store.state))
|
|
27
|
+
grid.store.subscribe(() => {
|
|
28
|
+
selected = selector(grid.store.state)
|
|
29
|
+
})
|
|
30
|
+
|
|
31
|
+
Object.defineProperty(grid, 'state', {
|
|
32
|
+
get() {
|
|
33
|
+
return selected
|
|
34
|
+
},
|
|
35
|
+
configurable: true,
|
|
36
|
+
enumerable: true,
|
|
37
|
+
})
|
|
38
|
+
|
|
39
|
+
return grid
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
export const createGrid = createSvGrid
|
package/src/createGrid.test.ts
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import { describe, expect, it } from 'vitest'
|
|
2
|
-
import { createGridState } from './index'
|
|
3
|
-
|
|
4
|
-
describe('createGrid', () => {
|
|
5
|
-
it('createGridState updates controlled values', () => {
|
|
6
|
-
const [sorting, setSorting] = createGridState([{ id: 'age', desc: false }])
|
|
7
|
-
setSorting((prev) => prev.map((entry) => ({ ...entry, desc: true })))
|
|
8
|
-
expect(sorting()[0]?.desc).toBe(true)
|
|
9
|
-
})
|
|
10
|
-
})
|
|
1
|
+
import { describe, expect, it } from 'vitest'
|
|
2
|
+
import { createGridState } from './index'
|
|
3
|
+
|
|
4
|
+
describe('createGrid', () => {
|
|
5
|
+
it('createGridState updates controlled values', () => {
|
|
6
|
+
const [sorting, setSorting] = createGridState([{ id: 'age', desc: false }])
|
|
7
|
+
setSorting((prev) => prev.map((entry) => ({ ...entry, desc: true })))
|
|
8
|
+
expect(sorting()[0]?.desc).toBe(true)
|
|
9
|
+
})
|
|
10
|
+
})
|
|
@@ -1,17 +1,17 @@
|
|
|
1
|
-
import type { Updater } from './core'
|
|
2
|
-
|
|
3
|
-
export function createGridState<TState>(
|
|
4
|
-
initialValue: TState,
|
|
5
|
-
): [() => TState, (updater: Updater<TState>) => void] {
|
|
6
|
-
let value = $state(initialValue)
|
|
7
|
-
|
|
8
|
-
return [
|
|
9
|
-
() => value,
|
|
10
|
-
(updater: Updater<TState>) => {
|
|
11
|
-
if (updater instanceof Function) value = updater(value)
|
|
12
|
-
else value = updater
|
|
13
|
-
},
|
|
14
|
-
]
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
export const createSvGridState = createGridState
|
|
1
|
+
import type { Updater } from './core'
|
|
2
|
+
|
|
3
|
+
export function createGridState<TState>(
|
|
4
|
+
initialValue: TState,
|
|
5
|
+
): [() => TState, (updater: Updater<TState>) => void] {
|
|
6
|
+
let value = $state(initialValue)
|
|
7
|
+
|
|
8
|
+
return [
|
|
9
|
+
() => value,
|
|
10
|
+
(updater: Updater<TState>) => {
|
|
11
|
+
if (updater instanceof Function) value = updater(value)
|
|
12
|
+
else value = updater
|
|
13
|
+
},
|
|
14
|
+
]
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export const createSvGridState = createGridState
|
|
@@ -25,14 +25,25 @@
|
|
|
25
25
|
import { createTypeaheadBuffer, isTypeaheadKey, nextTypeaheadIndex, type ListOption } from './list-option'
|
|
26
26
|
import { editorAria, type EditorAriaState } from './editor-contract'
|
|
27
27
|
|
|
28
|
-
|
|
28
|
+
/**
|
|
29
|
+
* A `Set` is accepted (and echoed back) in multi-select mode so a caller whose
|
|
30
|
+
* selection is already set-shaped - a filter checklist whose default state is
|
|
31
|
+
* "every value selected" - never has to materialize it as an array to drive the
|
|
32
|
+
* listbox, or to spread it back out again on every click.
|
|
33
|
+
*/
|
|
34
|
+
export type ListboxValue =
|
|
35
|
+
| string
|
|
36
|
+
| number
|
|
37
|
+
| ReadonlyArray<string | number>
|
|
38
|
+
| ReadonlySet<string | number>
|
|
39
|
+
| null
|
|
29
40
|
|
|
30
41
|
/** Reactive inputs are passed as getters so the core tracks live prop changes
|
|
31
42
|
* (the same controlled pattern Svelte headless libraries use). */
|
|
32
43
|
export type ListboxConfig = {
|
|
33
44
|
options: () => ReadonlyArray<ListOption>
|
|
34
45
|
value: () => ListboxValue
|
|
35
|
-
onChange?: (value: string | number | Array<string | number>) => void
|
|
46
|
+
onChange?: (value: string | number | Array<string | number> | Set<string | number>) => void
|
|
36
47
|
multiple?: () => boolean
|
|
37
48
|
disabled?: () => boolean
|
|
38
49
|
ariaLabel?: () => string | undefined
|
|
@@ -95,8 +106,23 @@ let uid = 0
|
|
|
95
106
|
|
|
96
107
|
/** Normalize a listbox value to an array (pure). */
|
|
97
108
|
export function toSelectedArray(value: ListboxValue, multiple: boolean): Array<string | number> {
|
|
98
|
-
if (
|
|
99
|
-
|
|
109
|
+
if (value == null) return []
|
|
110
|
+
if (value instanceof Set || Array.isArray(value)) {
|
|
111
|
+
const all = [...(value as Iterable<string | number>)]
|
|
112
|
+
return multiple ? all : all.slice(0, 1)
|
|
113
|
+
}
|
|
114
|
+
return [value as string | number]
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
/**
|
|
118
|
+
* Membership set for a listbox value (pure). A `Set` value is reused as-is, so
|
|
119
|
+
* `isSelected` stays O(1) without copying - the difference between a linear
|
|
120
|
+
* scan per rendered row and a hash hit when the selection runs to thousands of
|
|
121
|
+
* entries.
|
|
122
|
+
*/
|
|
123
|
+
export function toSelectedSet(value: ListboxValue, multiple: boolean): ReadonlySet<string | number> {
|
|
124
|
+
if (value instanceof Set) return value
|
|
125
|
+
return new Set(toSelectedArray(value, multiple))
|
|
100
126
|
}
|
|
101
127
|
|
|
102
128
|
export function createListbox(config: ListboxConfig): Listbox {
|
|
@@ -106,6 +132,9 @@ export function createListbox(config: ListboxConfig): Listbox {
|
|
|
106
132
|
const disabled = () => config.disabled?.() ?? false
|
|
107
133
|
|
|
108
134
|
let active = $state(0)
|
|
135
|
+
// `selectedSet` drives membership; `selected` (the ordered array) stays a
|
|
136
|
+
// lazy derived so a large selection is only flattened when someone reads it.
|
|
137
|
+
const selectedSet = $derived(toSelectedSet(config.value(), multiple()))
|
|
109
138
|
const selected = $derived(toSelectedArray(config.value(), multiple()))
|
|
110
139
|
const enabledIdx = $derived(opts().map((o, i) => (o.disabled ? -1 : i)).filter((i) => i >= 0))
|
|
111
140
|
|
|
@@ -115,7 +144,7 @@ export function createListbox(config: ListboxConfig): Listbox {
|
|
|
115
144
|
if (!o || o.disabled) active = enabledIdx[0] ?? 0
|
|
116
145
|
})
|
|
117
146
|
|
|
118
|
-
const isSelected = (value: string | number) =>
|
|
147
|
+
const isSelected = (value: string | number) => selectedSet.has(value)
|
|
119
148
|
const isActive = (index: number) => index === active
|
|
120
149
|
const optionId = (index: number) => `${id}-opt-${index}`
|
|
121
150
|
|
|
@@ -129,9 +158,12 @@ export function createListbox(config: ListboxConfig): Listbox {
|
|
|
129
158
|
if (!o || o.disabled || disabled()) return
|
|
130
159
|
active = index
|
|
131
160
|
if (multiple()) {
|
|
132
|
-
const set = new Set(
|
|
161
|
+
const set = new Set(selectedSet)
|
|
133
162
|
set.has(o.value) ? set.delete(o.value) : set.add(o.value)
|
|
134
|
-
|
|
163
|
+
// Echo back the shape we were handed. Toggling one option must not
|
|
164
|
+
// disturb selected values that aren't currently in `options` (search has
|
|
165
|
+
// narrowed the list, say) - they ride along in the set untouched.
|
|
166
|
+
config.onChange?.(config.value() instanceof Set ? set : [...set])
|
|
135
167
|
} else {
|
|
136
168
|
config.onChange?.(o.value)
|
|
137
169
|
}
|