@svgrid/grid 2.2.33 → 2.4.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 +199 -199
- package/dist/FlexRender.svelte +96 -96
- package/dist/GridFooter.svelte +178 -139
- package/dist/GridMenus.svelte +705 -705
- package/dist/SvAutoComplete.svelte +165 -165
- package/dist/SvAvatar.svelte +75 -75
- package/dist/SvCalendar.svelte +503 -503
- package/dist/SvCarousel.svelte +141 -141
- package/dist/SvCheckBox.svelte +102 -102
- package/dist/SvCircularProgress.svelte +109 -109
- 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 -254
- 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.css +2814 -2804
- package/dist/SvGrid.svelte +3490 -3490
- package/dist/SvGridChart.svelte +1716 -1716
- package/dist/SvGridChartPanel.svelte +485 -485
- package/dist/SvGridChartView.svelte +70 -70
- package/dist/SvGridDropdown.svelte +728 -728
- package/dist/SvGridSelect.svelte +266 -266
- package/dist/SvGroupCell.svelte +116 -116
- package/dist/SvListBox.svelte +326 -326
- package/dist/SvMaskedInput.svelte +122 -122
- package/dist/SvMenu.svelte +124 -124
- package/dist/SvMenuList.svelte +146 -146
- package/dist/SvMultiSelect.svelte +289 -289
- package/dist/SvNumberInput.svelte +168 -168
- package/dist/SvOtpInput.svelte +158 -158
- package/dist/SvPasswordInput.svelte +151 -151
- package/dist/SvPhoneInput.svelte +133 -133
- package/dist/SvPopover.svelte +197 -197
- package/dist/SvProgress.svelte +116 -116
- package/dist/SvRadioGroup.svelte +107 -107
- package/dist/SvRating.svelte +112 -112
- package/dist/SvResult.svelte +73 -73
- package/dist/SvRichText.svelte +211 -211
- package/dist/SvRowGroupPanel.svelte +170 -170
- package/dist/SvScrollArea.svelte +61 -61
- package/dist/SvSlider.svelte +200 -200
- package/dist/SvSwitchButton.svelte +108 -108
- 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 +208 -208
- package/dist/SvTree.svelte +444 -444
- package/dist/SvTreeSelect.svelte +235 -235
- package/dist/cdn/{GridMenus-B7XhhqdN.js → GridMenus-BpVcKyUr.js} +4 -4
- package/dist/cdn/{GridMenus-BxmIvCJh.js → GridMenus-CeXL5IW4.js} +153 -150
- package/dist/cdn/{SvDateTimePicker-ClqtVIj3.js → SvDateTimePicker-DSUhIta8.js} +165 -165
- package/dist/cdn/{SvDateTimePicker-o94wfSUa.js → SvDateTimePicker-h9kPyszT.js} +572 -555
- package/dist/cdn/{SvGridChart-Cr_90pPD.js → SvGridChart-Bs2GIR2Q.js} +28 -21
- package/dist/cdn/{SvGridChart-BhnFdLd0.js → SvGridChart-CwhFz7GV.js} +2 -2
- package/dist/cdn/{SvGridChartPanel-Cmx9DHAS.js → SvGridChartPanel-1WXuStzM.js} +2 -2
- package/dist/cdn/{SvGridChartPanel-ICbxiUvK.js → SvGridChartPanel-e5_nqNP9.js} +20 -12
- package/dist/cdn/{SvGridChartView-Bx42PMvf.js → SvGridChartView-SmPW10dI.js} +3 -3
- package/dist/cdn/{SvGridChartView-B40DTJSX.js → SvGridChartView-eSPuJE6g.js} +2 -2
- package/dist/cdn/{SvGridDropdown-D0VdjeR8.js → SvGridDropdown-B1ZcLpgs.js} +1 -1
- package/dist/cdn/{SvGridDropdown-CUOdm7YA.js → SvGridDropdown-CtdbHcIS.js} +6 -5
- package/dist/cdn/{chart-T1usDN0o.js → chart-i4XcXyHJ.js} +12 -10
- package/dist/cdn/{disclose-version-DljhZohK.js → disclose-version-Dr7rEVv-.js} +989 -1081
- package/dist/cdn/{export-format-JT5pWVT8.js → export-format-Cv1Dll6k.js} +66 -245
- package/dist/cdn/{src-erjBRYfX.js → src-DbeN1ReZ.js} +9221 -8925
- package/dist/cdn/{src-ktbQVOk-.js → src-DmEQFW5_.js} +9021 -8809
- 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/columns.js +9 -2
- package/dist/node_modules/.vite/vitest/67d8ed22ed986c5e2e948f64d892f30be166cc36/_svelte_metadata.json +1 -0
- package/dist/node_modules/.vite/vitest/67d8ed22ed986c5e2e948f64d892f30be166cc36/deps___vitest__/_metadata.json +178 -0
- package/dist/node_modules/.vite/vitest/67d8ed22ed986c5e2e948f64d892f30be166cc36/deps___vitest__/attachments-qzRy9DX4.js +3843 -0
- package/dist/node_modules/.vite/vitest/67d8ed22ed986c5e2e948f64d892f30be166cc36/deps___vitest__/attachments-qzRy9DX4.js.map +1 -0
- package/dist/node_modules/.vite/vitest/67d8ed22ed986c5e2e948f64d892f30be166cc36/deps___vitest__/constants-RLNOXCpz.js +23 -0
- package/dist/node_modules/.vite/vitest/67d8ed22ed986c5e2e948f64d892f30be166cc36/deps___vitest__/constants-RLNOXCpz.js.map +1 -0
- package/dist/node_modules/.vite/vitest/67d8ed22ed986c5e2e948f64d892f30be166cc36/deps___vitest__/dev-DPd12uEU.js +1925 -0
- package/dist/node_modules/.vite/vitest/67d8ed22ed986c5e2e948f64d892f30be166cc36/deps___vitest__/dev-DPd12uEU.js.map +1 -0
- package/dist/node_modules/.vite/vitest/67d8ed22ed986c5e2e948f64d892f30be166cc36/deps___vitest__/events-CDC4DKuQ.js +206 -0
- package/dist/node_modules/.vite/vitest/67d8ed22ed986c5e2e948f64d892f30be166cc36/deps___vitest__/events-CDC4DKuQ.js.map +1 -0
- package/dist/node_modules/.vite/vitest/67d8ed22ed986c5e2e948f64d892f30be166cc36/deps___vitest__/flags-BD-lYX7s.js +20 -0
- package/dist/node_modules/.vite/vitest/67d8ed22ed986c5e2e948f64d892f30be166cc36/deps___vitest__/flags-BD-lYX7s.js.map +1 -0
- package/dist/node_modules/.vite/vitest/67d8ed22ed986c5e2e948f64d892f30be166cc36/deps___vitest__/hydration-D3UBU2t8.js +264 -0
- package/dist/node_modules/.vite/vitest/67d8ed22ed986c5e2e948f64d892f30be166cc36/deps___vitest__/hydration-D3UBU2t8.js.map +1 -0
- package/dist/node_modules/.vite/vitest/67d8ed22ed986c5e2e948f64d892f30be166cc36/deps___vitest__/legacy-client-B0ZUlbSQ.js +698 -0
- package/dist/node_modules/.vite/vitest/67d8ed22ed986c5e2e948f64d892f30be166cc36/deps___vitest__/legacy-client-B0ZUlbSQ.js.map +1 -0
- package/dist/node_modules/.vite/vitest/67d8ed22ed986c5e2e948f64d892f30be166cc36/deps___vitest__/package.json +3 -0
- package/dist/node_modules/.vite/vitest/67d8ed22ed986c5e2e948f64d892f30be166cc36/deps___vitest__/svelte.js +135 -0
- package/dist/node_modules/.vite/vitest/67d8ed22ed986c5e2e948f64d892f30be166cc36/deps___vitest__/svelte.js.map +1 -0
- package/dist/node_modules/.vite/vitest/67d8ed22ed986c5e2e948f64d892f30be166cc36/deps___vitest__/svelte_animate.js +57 -0
- package/dist/node_modules/.vite/vitest/67d8ed22ed986c5e2e948f64d892f30be166cc36/deps___vitest__/svelte_animate.js.map +1 -0
- package/dist/node_modules/.vite/vitest/67d8ed22ed986c5e2e948f64d892f30be166cc36/deps___vitest__/svelte_attachments.js +2 -0
- package/dist/node_modules/.vite/vitest/67d8ed22ed986c5e2e948f64d892f30be166cc36/deps___vitest__/svelte_compiler.js +46691 -0
- package/dist/node_modules/.vite/vitest/67d8ed22ed986c5e2e948f64d892f30be166cc36/deps___vitest__/svelte_compiler.js.map +1 -0
- package/dist/node_modules/.vite/vitest/67d8ed22ed986c5e2e948f64d892f30be166cc36/deps___vitest__/svelte_easing.js +239 -0
- package/dist/node_modules/.vite/vitest/67d8ed22ed986c5e2e948f64d892f30be166cc36/deps___vitest__/svelte_easing.js.map +1 -0
- package/dist/node_modules/.vite/vitest/67d8ed22ed986c5e2e948f64d892f30be166cc36/deps___vitest__/svelte_events.js +2 -0
- package/dist/node_modules/.vite/vitest/67d8ed22ed986c5e2e948f64d892f30be166cc36/deps___vitest__/svelte_internal.js +6 -0
- package/dist/node_modules/.vite/vitest/67d8ed22ed986c5e2e948f64d892f30be166cc36/deps___vitest__/svelte_internal.js.map +1 -0
- package/dist/node_modules/.vite/vitest/67d8ed22ed986c5e2e948f64d892f30be166cc36/deps___vitest__/svelte_internal_client.js +7 -0
- package/dist/node_modules/.vite/vitest/67d8ed22ed986c5e2e948f64d892f30be166cc36/deps___vitest__/svelte_internal_disclose-version.js +6 -0
- package/dist/node_modules/.vite/vitest/67d8ed22ed986c5e2e948f64d892f30be166cc36/deps___vitest__/svelte_internal_disclose-version.js.map +1 -0
- package/dist/node_modules/.vite/vitest/67d8ed22ed986c5e2e948f64d892f30be166cc36/deps___vitest__/svelte_internal_flags_async.js +7 -0
- package/dist/node_modules/.vite/vitest/67d8ed22ed986c5e2e948f64d892f30be166cc36/deps___vitest__/svelte_internal_flags_async.js.map +1 -0
- package/dist/node_modules/.vite/vitest/67d8ed22ed986c5e2e948f64d892f30be166cc36/deps___vitest__/svelte_internal_flags_legacy.js +7 -0
- package/dist/node_modules/.vite/vitest/67d8ed22ed986c5e2e948f64d892f30be166cc36/deps___vitest__/svelte_internal_flags_legacy.js.map +1 -0
- package/dist/node_modules/.vite/vitest/67d8ed22ed986c5e2e948f64d892f30be166cc36/deps___vitest__/svelte_internal_flags_tracing.js +7 -0
- package/dist/node_modules/.vite/vitest/67d8ed22ed986c5e2e948f64d892f30be166cc36/deps___vitest__/svelte_internal_flags_tracing.js.map +1 -0
- package/dist/node_modules/.vite/vitest/67d8ed22ed986c5e2e948f64d892f30be166cc36/deps___vitest__/svelte_internal_server.js +6 -0
- package/dist/node_modules/.vite/vitest/67d8ed22ed986c5e2e948f64d892f30be166cc36/deps___vitest__/svelte_legacy.js +85 -0
- package/dist/node_modules/.vite/vitest/67d8ed22ed986c5e2e948f64d892f30be166cc36/deps___vitest__/svelte_legacy.js.map +1 -0
- package/dist/node_modules/.vite/vitest/67d8ed22ed986c5e2e948f64d892f30be166cc36/deps___vitest__/svelte_motion.js +561 -0
- package/dist/node_modules/.vite/vitest/67d8ed22ed986c5e2e948f64d892f30be166cc36/deps___vitest__/svelte_motion.js.map +1 -0
- package/dist/node_modules/.vite/vitest/67d8ed22ed986c5e2e948f64d892f30be166cc36/deps___vitest__/svelte_reactivity.js +26 -0
- package/dist/node_modules/.vite/vitest/67d8ed22ed986c5e2e948f64d892f30be166cc36/deps___vitest__/svelte_reactivity.js.map +1 -0
- package/dist/node_modules/.vite/vitest/67d8ed22ed986c5e2e948f64d892f30be166cc36/deps___vitest__/svelte_reactivity_window.js +124 -0
- package/dist/node_modules/.vite/vitest/67d8ed22ed986c5e2e948f64d892f30be166cc36/deps___vitest__/svelte_reactivity_window.js.map +1 -0
- package/dist/node_modules/.vite/vitest/67d8ed22ed986c5e2e948f64d892f30be166cc36/deps___vitest__/svelte_server.js +2 -0
- package/dist/node_modules/.vite/vitest/67d8ed22ed986c5e2e948f64d892f30be166cc36/deps___vitest__/svelte_store.js +91 -0
- package/dist/node_modules/.vite/vitest/67d8ed22ed986c5e2e948f64d892f30be166cc36/deps___vitest__/svelte_store.js.map +1 -0
- package/dist/node_modules/.vite/vitest/67d8ed22ed986c5e2e948f64d892f30be166cc36/deps___vitest__/svelte_transition.js +242 -0
- package/dist/node_modules/.vite/vitest/67d8ed22ed986c5e2e948f64d892f30be166cc36/deps___vitest__/svelte_transition.js.map +1 -0
- package/dist/node_modules/.vite/vitest/67d8ed22ed986c5e2e948f64d892f30be166cc36/deps___vitest__/utils-lObbumRX.js +497 -0
- package/dist/node_modules/.vite/vitest/67d8ed22ed986c5e2e948f64d892f30be166cc36/deps___vitest__/utils-lObbumRX.js.map +1 -0
- package/dist/node_modules/.vite/vitest/67d8ed22ed986c5e2e948f64d892f30be166cc36/deps___vitest__/utils-mR9mAWyK.js +4929 -0
- package/dist/node_modules/.vite/vitest/67d8ed22ed986c5e2e948f64d892f30be166cc36/deps___vitest__/utils-mR9mAWyK.js.map +1 -0
- package/dist/node_modules/.vite/vitest/67d8ed22ed986c5e2e948f64d892f30be166cc36/deps___vitest__/validate-CezNmRkM.js +192 -0
- package/dist/node_modules/.vite/vitest/67d8ed22ed986c5e2e948f64d892f30be166cc36/deps___vitest__/validate-CezNmRkM.js.map +1 -0
- package/dist/node_modules/.vite/vitest/67d8ed22ed986c5e2e948f64d892f30be166cc36/deps___vitest__/version-BHHo0WE-.js +10 -0
- package/dist/node_modules/.vite/vitest/67d8ed22ed986c5e2e948f64d892f30be166cc36/deps___vitest__/version-BHHo0WE-.js.map +1 -0
- package/dist/node_modules/.vite/vitest/67d8ed22ed986c5e2e948f64d892f30be166cc36/deps___vitest__/warnings-yiExAB06.js +140 -0
- package/dist/node_modules/.vite/vitest/67d8ed22ed986c5e2e948f64d892f30be166cc36/deps___vitest__/warnings-yiExAB06.js.map +1 -0
- package/package.json +11 -11
- package/src/FlexRender.svelte +96 -96
- package/src/GridFooter.svelte +178 -139
- package/src/GridMenus.svelte +705 -705
- package/src/SvAutoComplete.svelte +165 -165
- package/src/SvAvatar.svelte +75 -75
- package/src/SvCalendar.svelte +503 -503
- package/src/SvCalendar.test.ts +226 -226
- package/src/SvCarousel.svelte +141 -141
- package/src/SvCheckBox.svelte +102 -102
- package/src/SvCircularProgress.svelte +109 -109
- 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 -254
- 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 +3680 -3680
- package/src/SvGrid.css +2814 -2804
- package/src/SvGrid.svelte +3490 -3490
- package/src/SvGrid.types.ts +1708 -1708
- package/src/SvGridChart.svelte +1716 -1716
- package/src/SvGridChartPanel.svelte +485 -485
- package/src/SvGridChartView.svelte +70 -70
- package/src/SvGridDropdown.svelte +728 -728
- package/src/SvGridSelect.svelte +266 -266
- package/src/SvGroupCell.svelte +116 -116
- package/src/SvListBox.svelte +326 -326
- 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 +289 -289
- package/src/SvNumberInput.svelte +168 -168
- package/src/SvOtpInput.svelte +158 -158
- package/src/SvPasswordInput.svelte +151 -151
- package/src/SvPhoneInput.svelte +133 -133
- package/src/SvPopover.svelte +197 -197
- package/src/SvProgress.svelte +116 -116
- package/src/SvRadioGroup.svelte +107 -107
- package/src/SvRating.svelte +112 -112
- package/src/SvResult.svelte +73 -73
- package/src/SvRichText.svelte +211 -211
- package/src/SvRowGroupPanel.svelte +170 -170
- package/src/SvScrollArea.svelte +61 -61
- package/src/SvSlider.svelte +200 -200
- package/src/SvSwitchButton.svelte +108 -108
- 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 +208 -208
- package/src/SvTree.svelte +444 -444
- package/src/SvTreeSelect.svelte +235 -235
- 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 +805 -805
- package/src/builtin-editors.grid.test.ts +85 -85
- package/src/cell-formatting.ts +169 -169
- package/src/cell-render.test.ts +513 -513
- package/src/cell-render.ts +496 -496
- package/src/cell-values.ts +118 -118
- package/src/chart-export.ts +201 -201
- package/src/chart-view.svelte.ts +36 -36
- package/src/chart.ts +2295 -2295
- package/src/collaboration.test.ts +104 -104
- package/src/collaboration.ts +167 -167
- package/src/columns.ts +7 -2
- package/src/core.performance.test.ts +30 -30
- package/src/core.ts +1261 -1261
- 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 +250 -250
- package/src/createMenu.svelte.ts +224 -224
- 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 -949
- package/src/editing.ts +606 -606
- package/src/editor-contract.ts +164 -164
- package/src/editor-registry.grid.test.ts +144 -144
- package/src/editor-registry.ts +122 -122
- package/src/export-data-api.test.ts +126 -126
- package/src/export-format.test.ts +107 -107
- package/src/export-format.ts +601 -601
- package/src/filter-operators.ts +157 -157
- package/src/flex-render.ts +3 -3
- package/src/form-field.ts +127 -127
- package/src/group-display.test.ts +167 -167
- package/src/group-display.ts +200 -200
- package/src/index.ts +724 -724
- package/src/js-scroller.svelte.ts +173 -173
- package/src/keyboard-handlers.ts +270 -270
- 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.ts +567 -567
- package/src/merge-objects.ts +48 -48
- package/src/node_modules/.vite/vitest/67d8ed22ed986c5e2e948f64d892f30be166cc36/_svelte_metadata.json +1 -0
- package/src/node_modules/.vite/vitest/67d8ed22ed986c5e2e948f64d892f30be166cc36/deps___vitest__/_metadata.json +178 -0
- package/src/node_modules/.vite/vitest/67d8ed22ed986c5e2e948f64d892f30be166cc36/deps___vitest__/attachments-qzRy9DX4.js +3843 -0
- package/src/node_modules/.vite/vitest/67d8ed22ed986c5e2e948f64d892f30be166cc36/deps___vitest__/attachments-qzRy9DX4.js.map +1 -0
- package/src/node_modules/.vite/vitest/67d8ed22ed986c5e2e948f64d892f30be166cc36/deps___vitest__/constants-RLNOXCpz.js +23 -0
- package/src/node_modules/.vite/vitest/67d8ed22ed986c5e2e948f64d892f30be166cc36/deps___vitest__/constants-RLNOXCpz.js.map +1 -0
- package/src/node_modules/.vite/vitest/67d8ed22ed986c5e2e948f64d892f30be166cc36/deps___vitest__/dev-DPd12uEU.js +1925 -0
- package/src/node_modules/.vite/vitest/67d8ed22ed986c5e2e948f64d892f30be166cc36/deps___vitest__/dev-DPd12uEU.js.map +1 -0
- package/src/node_modules/.vite/vitest/67d8ed22ed986c5e2e948f64d892f30be166cc36/deps___vitest__/events-CDC4DKuQ.js +206 -0
- package/src/node_modules/.vite/vitest/67d8ed22ed986c5e2e948f64d892f30be166cc36/deps___vitest__/events-CDC4DKuQ.js.map +1 -0
- package/src/node_modules/.vite/vitest/67d8ed22ed986c5e2e948f64d892f30be166cc36/deps___vitest__/flags-BD-lYX7s.js +20 -0
- package/src/node_modules/.vite/vitest/67d8ed22ed986c5e2e948f64d892f30be166cc36/deps___vitest__/flags-BD-lYX7s.js.map +1 -0
- package/src/node_modules/.vite/vitest/67d8ed22ed986c5e2e948f64d892f30be166cc36/deps___vitest__/hydration-D3UBU2t8.js +264 -0
- package/src/node_modules/.vite/vitest/67d8ed22ed986c5e2e948f64d892f30be166cc36/deps___vitest__/hydration-D3UBU2t8.js.map +1 -0
- package/src/node_modules/.vite/vitest/67d8ed22ed986c5e2e948f64d892f30be166cc36/deps___vitest__/legacy-client-B0ZUlbSQ.js +698 -0
- package/src/node_modules/.vite/vitest/67d8ed22ed986c5e2e948f64d892f30be166cc36/deps___vitest__/legacy-client-B0ZUlbSQ.js.map +1 -0
- package/src/node_modules/.vite/vitest/67d8ed22ed986c5e2e948f64d892f30be166cc36/deps___vitest__/package.json +3 -0
- package/src/node_modules/.vite/vitest/67d8ed22ed986c5e2e948f64d892f30be166cc36/deps___vitest__/svelte.js +135 -0
- package/src/node_modules/.vite/vitest/67d8ed22ed986c5e2e948f64d892f30be166cc36/deps___vitest__/svelte.js.map +1 -0
- package/src/node_modules/.vite/vitest/67d8ed22ed986c5e2e948f64d892f30be166cc36/deps___vitest__/svelte_animate.js +57 -0
- package/src/node_modules/.vite/vitest/67d8ed22ed986c5e2e948f64d892f30be166cc36/deps___vitest__/svelte_animate.js.map +1 -0
- package/src/node_modules/.vite/vitest/67d8ed22ed986c5e2e948f64d892f30be166cc36/deps___vitest__/svelte_attachments.js +2 -0
- package/src/node_modules/.vite/vitest/67d8ed22ed986c5e2e948f64d892f30be166cc36/deps___vitest__/svelte_compiler.js +46691 -0
- package/src/node_modules/.vite/vitest/67d8ed22ed986c5e2e948f64d892f30be166cc36/deps___vitest__/svelte_compiler.js.map +1 -0
- package/src/node_modules/.vite/vitest/67d8ed22ed986c5e2e948f64d892f30be166cc36/deps___vitest__/svelte_easing.js +239 -0
- package/src/node_modules/.vite/vitest/67d8ed22ed986c5e2e948f64d892f30be166cc36/deps___vitest__/svelte_easing.js.map +1 -0
- package/src/node_modules/.vite/vitest/67d8ed22ed986c5e2e948f64d892f30be166cc36/deps___vitest__/svelte_events.js +2 -0
- package/src/node_modules/.vite/vitest/67d8ed22ed986c5e2e948f64d892f30be166cc36/deps___vitest__/svelte_internal.js +6 -0
- package/src/node_modules/.vite/vitest/67d8ed22ed986c5e2e948f64d892f30be166cc36/deps___vitest__/svelte_internal.js.map +1 -0
- package/src/node_modules/.vite/vitest/67d8ed22ed986c5e2e948f64d892f30be166cc36/deps___vitest__/svelte_internal_client.js +7 -0
- package/src/node_modules/.vite/vitest/67d8ed22ed986c5e2e948f64d892f30be166cc36/deps___vitest__/svelte_internal_disclose-version.js +6 -0
- package/src/node_modules/.vite/vitest/67d8ed22ed986c5e2e948f64d892f30be166cc36/deps___vitest__/svelte_internal_disclose-version.js.map +1 -0
- package/src/node_modules/.vite/vitest/67d8ed22ed986c5e2e948f64d892f30be166cc36/deps___vitest__/svelte_internal_flags_async.js +7 -0
- package/src/node_modules/.vite/vitest/67d8ed22ed986c5e2e948f64d892f30be166cc36/deps___vitest__/svelte_internal_flags_async.js.map +1 -0
- package/src/node_modules/.vite/vitest/67d8ed22ed986c5e2e948f64d892f30be166cc36/deps___vitest__/svelte_internal_flags_legacy.js +7 -0
- package/src/node_modules/.vite/vitest/67d8ed22ed986c5e2e948f64d892f30be166cc36/deps___vitest__/svelte_internal_flags_legacy.js.map +1 -0
- package/src/node_modules/.vite/vitest/67d8ed22ed986c5e2e948f64d892f30be166cc36/deps___vitest__/svelte_internal_flags_tracing.js +7 -0
- package/src/node_modules/.vite/vitest/67d8ed22ed986c5e2e948f64d892f30be166cc36/deps___vitest__/svelte_internal_flags_tracing.js.map +1 -0
- package/src/node_modules/.vite/vitest/67d8ed22ed986c5e2e948f64d892f30be166cc36/deps___vitest__/svelte_internal_server.js +6 -0
- package/src/node_modules/.vite/vitest/67d8ed22ed986c5e2e948f64d892f30be166cc36/deps___vitest__/svelte_legacy.js +85 -0
- package/src/node_modules/.vite/vitest/67d8ed22ed986c5e2e948f64d892f30be166cc36/deps___vitest__/svelte_legacy.js.map +1 -0
- package/src/node_modules/.vite/vitest/67d8ed22ed986c5e2e948f64d892f30be166cc36/deps___vitest__/svelte_motion.js +561 -0
- package/src/node_modules/.vite/vitest/67d8ed22ed986c5e2e948f64d892f30be166cc36/deps___vitest__/svelte_motion.js.map +1 -0
- package/src/node_modules/.vite/vitest/67d8ed22ed986c5e2e948f64d892f30be166cc36/deps___vitest__/svelte_reactivity.js +26 -0
- package/src/node_modules/.vite/vitest/67d8ed22ed986c5e2e948f64d892f30be166cc36/deps___vitest__/svelte_reactivity.js.map +1 -0
- package/src/node_modules/.vite/vitest/67d8ed22ed986c5e2e948f64d892f30be166cc36/deps___vitest__/svelte_reactivity_window.js +124 -0
- package/src/node_modules/.vite/vitest/67d8ed22ed986c5e2e948f64d892f30be166cc36/deps___vitest__/svelte_reactivity_window.js.map +1 -0
- package/src/node_modules/.vite/vitest/67d8ed22ed986c5e2e948f64d892f30be166cc36/deps___vitest__/svelte_server.js +2 -0
- package/src/node_modules/.vite/vitest/67d8ed22ed986c5e2e948f64d892f30be166cc36/deps___vitest__/svelte_store.js +91 -0
- package/src/node_modules/.vite/vitest/67d8ed22ed986c5e2e948f64d892f30be166cc36/deps___vitest__/svelte_store.js.map +1 -0
- package/src/node_modules/.vite/vitest/67d8ed22ed986c5e2e948f64d892f30be166cc36/deps___vitest__/svelte_transition.js +242 -0
- package/src/node_modules/.vite/vitest/67d8ed22ed986c5e2e948f64d892f30be166cc36/deps___vitest__/svelte_transition.js.map +1 -0
- package/src/node_modules/.vite/vitest/67d8ed22ed986c5e2e948f64d892f30be166cc36/deps___vitest__/utils-lObbumRX.js +497 -0
- package/src/node_modules/.vite/vitest/67d8ed22ed986c5e2e948f64d892f30be166cc36/deps___vitest__/utils-lObbumRX.js.map +1 -0
- package/src/node_modules/.vite/vitest/67d8ed22ed986c5e2e948f64d892f30be166cc36/deps___vitest__/utils-mR9mAWyK.js +4929 -0
- package/src/node_modules/.vite/vitest/67d8ed22ed986c5e2e948f64d892f30be166cc36/deps___vitest__/utils-mR9mAWyK.js.map +1 -0
- package/src/node_modules/.vite/vitest/67d8ed22ed986c5e2e948f64d892f30be166cc36/deps___vitest__/validate-CezNmRkM.js +192 -0
- package/src/node_modules/.vite/vitest/67d8ed22ed986c5e2e948f64d892f30be166cc36/deps___vitest__/validate-CezNmRkM.js.map +1 -0
- package/src/node_modules/.vite/vitest/67d8ed22ed986c5e2e948f64d892f30be166cc36/deps___vitest__/version-BHHo0WE-.js +10 -0
- package/src/node_modules/.vite/vitest/67d8ed22ed986c5e2e948f64d892f30be166cc36/deps___vitest__/version-BHHo0WE-.js.map +1 -0
- package/src/node_modules/.vite/vitest/67d8ed22ed986c5e2e948f64d892f30be166cc36/deps___vitest__/warnings-yiExAB06.js +140 -0
- package/src/node_modules/.vite/vitest/67d8ed22ed986c5e2e948f64d892f30be166cc36/deps___vitest__/warnings-yiExAB06.js.map +1 -0
- package/src/overlays.test.ts +90 -90
- package/src/render-component.ts +28 -28
- package/src/row-resize.ts +210 -210
- 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 +491 -491
- 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 +488 -488
- 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 +526 -526
- package/src/svgrid.async-editor-options.test.ts +271 -271
- package/src/svgrid.auto-row-height.test.ts +204 -204
- package/src/svgrid.behavior.test.ts +705 -705
- package/src/svgrid.charting.test.ts +534 -534
- package/src/svgrid.comments-autocomplete.test.ts +123 -123
- package/src/svgrid.context-menu.test.ts +147 -147
- package/src/svgrid.features.test.ts +157 -157
- package/src/svgrid.filter-depth.test.ts +163 -163
- package/src/svgrid.filter-menu-listbox.svelte.test.ts +322 -322
- package/src/svgrid.filter-menu-scroll.test.ts +112 -112
- package/src/svgrid.footer-pagesize.svelte.test.ts +86 -0
- package/src/svgrid.grand-total.test.ts +188 -188
- package/src/svgrid.group-display-mode.test.ts +171 -171
- package/src/svgrid.group-footers.test.ts +121 -121
- package/src/svgrid.group-pagination.test.ts +153 -153
- package/src/svgrid.new-features.wrapper.test.ts +251 -251
- package/src/svgrid.tree-data.test.ts +186 -186
- package/src/svgrid.wrapper.test.ts +40 -40
- package/src/svgriddropdown.async-panel.svelte.test.ts +195 -195
- package/src/test-setup.ts +62 -62
- package/src/themes/index.ts +257 -257
- package/src/toast-store.svelte.ts +246 -246
- package/src/toast-store.test.ts +147 -147
- package/src/tree-row-model.test.ts +168 -168
- package/src/ui-buttons.test.ts +144 -144
- package/src/ui-inputs.test.ts +118 -118
- package/src/ui-localization.test.ts +113 -113
- 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
|
@@ -1,119 +1,119 @@
|
|
|
1
|
-
import { afterEach, describe, expect, it } from 'vitest'
|
|
2
|
-
import { createDismissableLayer, dismissableDepth, onScrollOutside } from './dismissable'
|
|
3
|
-
|
|
4
|
-
function panel(): HTMLElement {
|
|
5
|
-
const el = document.createElement('div')
|
|
6
|
-
document.body.appendChild(el)
|
|
7
|
-
return el
|
|
8
|
-
}
|
|
9
|
-
|
|
10
|
-
afterEach(() => {
|
|
11
|
-
document.body.innerHTML = ''
|
|
12
|
-
})
|
|
13
|
-
|
|
14
|
-
describe('createDismissableLayer', () => {
|
|
15
|
-
it('dismisses on Escape when topmost', () => {
|
|
16
|
-
const el = panel()
|
|
17
|
-
let reason: string | null = null
|
|
18
|
-
const layer = createDismissableLayer({ element: () => el, onDismiss: (r) => (reason = r) })
|
|
19
|
-
layer.activate()
|
|
20
|
-
document.dispatchEvent(new KeyboardEvent('keydown', { key: 'Escape', bubbles: true }))
|
|
21
|
-
expect(reason).toBe('escape')
|
|
22
|
-
layer.release()
|
|
23
|
-
})
|
|
24
|
-
|
|
25
|
-
it('dismisses on outside pointerdown but not inside', () => {
|
|
26
|
-
const el = panel()
|
|
27
|
-
const inside = document.createElement('button')
|
|
28
|
-
el.appendChild(inside)
|
|
29
|
-
let reason: string | null = null
|
|
30
|
-
const layer = createDismissableLayer({ element: () => el, onDismiss: (r) => (reason = r) })
|
|
31
|
-
layer.activate()
|
|
32
|
-
|
|
33
|
-
inside.dispatchEvent(new MouseEvent('pointerdown', { bubbles: true }))
|
|
34
|
-
expect(reason).toBeNull()
|
|
35
|
-
|
|
36
|
-
document.body.dispatchEvent(new MouseEvent('pointerdown', { bubbles: true }))
|
|
37
|
-
expect(reason).toBe('outside')
|
|
38
|
-
layer.release()
|
|
39
|
-
})
|
|
40
|
-
|
|
41
|
-
it('treats a pointerdown in ANY of multiple elements as inside', () => {
|
|
42
|
-
const panelEl = panel()
|
|
43
|
-
const trigger = panel()
|
|
44
|
-
let reason: string | null = null
|
|
45
|
-
const layer = createDismissableLayer({
|
|
46
|
-
element: () => [panelEl, trigger],
|
|
47
|
-
onDismiss: (r) => (reason = r),
|
|
48
|
-
})
|
|
49
|
-
layer.activate()
|
|
50
|
-
|
|
51
|
-
trigger.dispatchEvent(new MouseEvent('pointerdown', { bubbles: true }))
|
|
52
|
-
expect(reason).toBeNull() // trigger counts as inside
|
|
53
|
-
|
|
54
|
-
document.body.dispatchEvent(new MouseEvent('pointerdown', { bubbles: true }))
|
|
55
|
-
expect(reason).toBe('outside')
|
|
56
|
-
layer.release()
|
|
57
|
-
})
|
|
58
|
-
|
|
59
|
-
it('only the top layer responds to Escape', () => {
|
|
60
|
-
const a = panel()
|
|
61
|
-
const b = panel()
|
|
62
|
-
const hits: string[] = []
|
|
63
|
-
const layerA = createDismissableLayer({ element: () => a, onDismiss: () => hits.push('a') })
|
|
64
|
-
const layerB = createDismissableLayer({ element: () => b, onDismiss: () => hits.push('b') })
|
|
65
|
-
layerA.activate()
|
|
66
|
-
layerB.activate()
|
|
67
|
-
expect(dismissableDepth()).toBe(2)
|
|
68
|
-
|
|
69
|
-
document.dispatchEvent(new KeyboardEvent('keydown', { key: 'Escape', bubbles: true }))
|
|
70
|
-
expect(hits).toEqual(['b']) // only the topmost
|
|
71
|
-
|
|
72
|
-
layerB.release()
|
|
73
|
-
document.dispatchEvent(new KeyboardEvent('keydown', { key: 'Escape', bubbles: true }))
|
|
74
|
-
expect(hits).toEqual(['b', 'a']) // now a is on top
|
|
75
|
-
|
|
76
|
-
layerA.release()
|
|
77
|
-
expect(dismissableDepth()).toBe(0)
|
|
78
|
-
})
|
|
79
|
-
|
|
80
|
-
it('close-on-scroll ignores scrolling inside the panel', () => {
|
|
81
|
-
const el = panel()
|
|
82
|
-
const list = document.createElement('div') // e.g. the filter menu's facet list
|
|
83
|
-
el.appendChild(list)
|
|
84
|
-
let closed = 0
|
|
85
|
-
const off = onScrollOutside(() => el, () => closed++)
|
|
86
|
-
|
|
87
|
-
// Inner scroll containers don't bubble, so this only reaches the capture
|
|
88
|
-
// listener - it must NOT close the menu the user is scrolling.
|
|
89
|
-
list.dispatchEvent(new Event('scroll'))
|
|
90
|
-
el.dispatchEvent(new Event('scroll'))
|
|
91
|
-
expect(closed).toBe(0)
|
|
92
|
-
|
|
93
|
-
// A scroll anywhere else moves the anchor, so the panel closes.
|
|
94
|
-
document.body.dispatchEvent(new Event('scroll'))
|
|
95
|
-
expect(closed).toBe(1)
|
|
96
|
-
document.dispatchEvent(new Event('scroll'))
|
|
97
|
-
expect(closed).toBe(2)
|
|
98
|
-
|
|
99
|
-
off()
|
|
100
|
-
document.body.dispatchEvent(new Event('scroll'))
|
|
101
|
-
expect(closed).toBe(2)
|
|
102
|
-
})
|
|
103
|
-
|
|
104
|
-
it('respects closeOnEscape / closeOnOutside flags', () => {
|
|
105
|
-
const el = panel()
|
|
106
|
-
let count = 0
|
|
107
|
-
const layer = createDismissableLayer({
|
|
108
|
-
element: () => el,
|
|
109
|
-
onDismiss: () => count++,
|
|
110
|
-
closeOnEscape: false,
|
|
111
|
-
closeOnOutside: false,
|
|
112
|
-
})
|
|
113
|
-
layer.activate()
|
|
114
|
-
document.dispatchEvent(new KeyboardEvent('keydown', { key: 'Escape', bubbles: true }))
|
|
115
|
-
document.body.dispatchEvent(new MouseEvent('pointerdown', { bubbles: true }))
|
|
116
|
-
expect(count).toBe(0)
|
|
117
|
-
layer.release()
|
|
118
|
-
})
|
|
119
|
-
})
|
|
1
|
+
import { afterEach, describe, expect, it } from 'vitest'
|
|
2
|
+
import { createDismissableLayer, dismissableDepth, onScrollOutside } from './dismissable'
|
|
3
|
+
|
|
4
|
+
function panel(): HTMLElement {
|
|
5
|
+
const el = document.createElement('div')
|
|
6
|
+
document.body.appendChild(el)
|
|
7
|
+
return el
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
afterEach(() => {
|
|
11
|
+
document.body.innerHTML = ''
|
|
12
|
+
})
|
|
13
|
+
|
|
14
|
+
describe('createDismissableLayer', () => {
|
|
15
|
+
it('dismisses on Escape when topmost', () => {
|
|
16
|
+
const el = panel()
|
|
17
|
+
let reason: string | null = null
|
|
18
|
+
const layer = createDismissableLayer({ element: () => el, onDismiss: (r) => (reason = r) })
|
|
19
|
+
layer.activate()
|
|
20
|
+
document.dispatchEvent(new KeyboardEvent('keydown', { key: 'Escape', bubbles: true }))
|
|
21
|
+
expect(reason).toBe('escape')
|
|
22
|
+
layer.release()
|
|
23
|
+
})
|
|
24
|
+
|
|
25
|
+
it('dismisses on outside pointerdown but not inside', () => {
|
|
26
|
+
const el = panel()
|
|
27
|
+
const inside = document.createElement('button')
|
|
28
|
+
el.appendChild(inside)
|
|
29
|
+
let reason: string | null = null
|
|
30
|
+
const layer = createDismissableLayer({ element: () => el, onDismiss: (r) => (reason = r) })
|
|
31
|
+
layer.activate()
|
|
32
|
+
|
|
33
|
+
inside.dispatchEvent(new MouseEvent('pointerdown', { bubbles: true }))
|
|
34
|
+
expect(reason).toBeNull()
|
|
35
|
+
|
|
36
|
+
document.body.dispatchEvent(new MouseEvent('pointerdown', { bubbles: true }))
|
|
37
|
+
expect(reason).toBe('outside')
|
|
38
|
+
layer.release()
|
|
39
|
+
})
|
|
40
|
+
|
|
41
|
+
it('treats a pointerdown in ANY of multiple elements as inside', () => {
|
|
42
|
+
const panelEl = panel()
|
|
43
|
+
const trigger = panel()
|
|
44
|
+
let reason: string | null = null
|
|
45
|
+
const layer = createDismissableLayer({
|
|
46
|
+
element: () => [panelEl, trigger],
|
|
47
|
+
onDismiss: (r) => (reason = r),
|
|
48
|
+
})
|
|
49
|
+
layer.activate()
|
|
50
|
+
|
|
51
|
+
trigger.dispatchEvent(new MouseEvent('pointerdown', { bubbles: true }))
|
|
52
|
+
expect(reason).toBeNull() // trigger counts as inside
|
|
53
|
+
|
|
54
|
+
document.body.dispatchEvent(new MouseEvent('pointerdown', { bubbles: true }))
|
|
55
|
+
expect(reason).toBe('outside')
|
|
56
|
+
layer.release()
|
|
57
|
+
})
|
|
58
|
+
|
|
59
|
+
it('only the top layer responds to Escape', () => {
|
|
60
|
+
const a = panel()
|
|
61
|
+
const b = panel()
|
|
62
|
+
const hits: string[] = []
|
|
63
|
+
const layerA = createDismissableLayer({ element: () => a, onDismiss: () => hits.push('a') })
|
|
64
|
+
const layerB = createDismissableLayer({ element: () => b, onDismiss: () => hits.push('b') })
|
|
65
|
+
layerA.activate()
|
|
66
|
+
layerB.activate()
|
|
67
|
+
expect(dismissableDepth()).toBe(2)
|
|
68
|
+
|
|
69
|
+
document.dispatchEvent(new KeyboardEvent('keydown', { key: 'Escape', bubbles: true }))
|
|
70
|
+
expect(hits).toEqual(['b']) // only the topmost
|
|
71
|
+
|
|
72
|
+
layerB.release()
|
|
73
|
+
document.dispatchEvent(new KeyboardEvent('keydown', { key: 'Escape', bubbles: true }))
|
|
74
|
+
expect(hits).toEqual(['b', 'a']) // now a is on top
|
|
75
|
+
|
|
76
|
+
layerA.release()
|
|
77
|
+
expect(dismissableDepth()).toBe(0)
|
|
78
|
+
})
|
|
79
|
+
|
|
80
|
+
it('close-on-scroll ignores scrolling inside the panel', () => {
|
|
81
|
+
const el = panel()
|
|
82
|
+
const list = document.createElement('div') // e.g. the filter menu's facet list
|
|
83
|
+
el.appendChild(list)
|
|
84
|
+
let closed = 0
|
|
85
|
+
const off = onScrollOutside(() => el, () => closed++)
|
|
86
|
+
|
|
87
|
+
// Inner scroll containers don't bubble, so this only reaches the capture
|
|
88
|
+
// listener - it must NOT close the menu the user is scrolling.
|
|
89
|
+
list.dispatchEvent(new Event('scroll'))
|
|
90
|
+
el.dispatchEvent(new Event('scroll'))
|
|
91
|
+
expect(closed).toBe(0)
|
|
92
|
+
|
|
93
|
+
// A scroll anywhere else moves the anchor, so the panel closes.
|
|
94
|
+
document.body.dispatchEvent(new Event('scroll'))
|
|
95
|
+
expect(closed).toBe(1)
|
|
96
|
+
document.dispatchEvent(new Event('scroll'))
|
|
97
|
+
expect(closed).toBe(2)
|
|
98
|
+
|
|
99
|
+
off()
|
|
100
|
+
document.body.dispatchEvent(new Event('scroll'))
|
|
101
|
+
expect(closed).toBe(2)
|
|
102
|
+
})
|
|
103
|
+
|
|
104
|
+
it('respects closeOnEscape / closeOnOutside flags', () => {
|
|
105
|
+
const el = panel()
|
|
106
|
+
let count = 0
|
|
107
|
+
const layer = createDismissableLayer({
|
|
108
|
+
element: () => el,
|
|
109
|
+
onDismiss: () => count++,
|
|
110
|
+
closeOnEscape: false,
|
|
111
|
+
closeOnOutside: false,
|
|
112
|
+
})
|
|
113
|
+
layer.activate()
|
|
114
|
+
document.dispatchEvent(new KeyboardEvent('keydown', { key: 'Escape', bubbles: true }))
|
|
115
|
+
document.body.dispatchEvent(new MouseEvent('pointerdown', { bubbles: true }))
|
|
116
|
+
expect(count).toBe(0)
|
|
117
|
+
layer.release()
|
|
118
|
+
})
|
|
119
|
+
})
|
package/src/a11y/dismissable.ts
CHANGED
|
@@ -1,114 +1,114 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* dismissable-layer - a global stack of dismissable overlays (dropdowns,
|
|
3
|
-
* popovers, dialogs). Escape and outside-pointer dismiss only the TOP layer, so
|
|
4
|
-
* a menu opened inside a dialog closes the menu first and the dialog second -
|
|
5
|
-
* the ordering users expect from nested overlays. One set of document listeners
|
|
6
|
-
* is shared by every layer instead of each component wiring its own.
|
|
7
|
-
*/
|
|
8
|
-
type Reason = 'escape' | 'outside'
|
|
9
|
-
|
|
10
|
-
/** One element, several elements, or a getter of either. A pointerdown counts
|
|
11
|
-
* as "inside" when it lands in ANY of them (e.g. a popover's panel AND its
|
|
12
|
-
* trigger, so clicking the trigger doesn't immediately re-dismiss). */
|
|
13
|
-
export type DismissTarget = HTMLElement | null | ReadonlyArray<HTMLElement | null>
|
|
14
|
-
|
|
15
|
-
type Layer = {
|
|
16
|
-
element: () => DismissTarget
|
|
17
|
-
onDismiss: (reason: Reason) => void
|
|
18
|
-
closeOnEscape: boolean
|
|
19
|
-
closeOnOutside: boolean
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
function containsTarget(target: DismissTarget, node: Node | null): boolean {
|
|
23
|
-
if (!node) return false
|
|
24
|
-
const els = Array.isArray(target) ? target : [target as HTMLElement | null]
|
|
25
|
-
return els.some((el) => el != null && el.contains(node))
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
const stack: Layer[] = []
|
|
29
|
-
let wired = false
|
|
30
|
-
|
|
31
|
-
function ensureWired() {
|
|
32
|
-
if (wired || typeof document === 'undefined') return
|
|
33
|
-
wired = true
|
|
34
|
-
document.addEventListener(
|
|
35
|
-
'keydown',
|
|
36
|
-
(e) => {
|
|
37
|
-
if (e.key !== 'Escape') return
|
|
38
|
-
const top = stack[stack.length - 1]
|
|
39
|
-
if (top?.closeOnEscape) {
|
|
40
|
-
e.stopPropagation()
|
|
41
|
-
top.onDismiss('escape')
|
|
42
|
-
}
|
|
43
|
-
},
|
|
44
|
-
true,
|
|
45
|
-
)
|
|
46
|
-
document.addEventListener(
|
|
47
|
-
'pointerdown',
|
|
48
|
-
(e) => {
|
|
49
|
-
const top = stack[stack.length - 1]
|
|
50
|
-
if (!top?.closeOnOutside) return
|
|
51
|
-
if (!containsTarget(top.element(), e.target as Node)) top.onDismiss('outside')
|
|
52
|
-
},
|
|
53
|
-
true,
|
|
54
|
-
)
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
export type DismissableOptions = {
|
|
58
|
-
/** The panel element(s); a pointerdown outside ALL of them dismisses the layer.
|
|
59
|
-
* Pass multiple (e.g. panel + trigger) so clicking the trigger doesn't
|
|
60
|
-
* immediately re-dismiss what it just opened. */
|
|
61
|
-
element: () => DismissTarget
|
|
62
|
-
onDismiss: (reason: Reason) => void
|
|
63
|
-
/** Dismiss on Escape when topmost. Default true. */
|
|
64
|
-
closeOnEscape?: boolean
|
|
65
|
-
/** Dismiss on outside pointerdown when topmost. Default true. */
|
|
66
|
-
closeOnOutside?: boolean
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
export type DismissableLayer = { activate: () => void; release: () => void }
|
|
70
|
-
|
|
71
|
-
/** Register a dismissable layer. Inert until `activate()`. */
|
|
72
|
-
export function createDismissableLayer(options: DismissableOptions): DismissableLayer {
|
|
73
|
-
const layer: Layer = {
|
|
74
|
-
element: options.element,
|
|
75
|
-
onDismiss: options.onDismiss,
|
|
76
|
-
closeOnEscape: options.closeOnEscape ?? true,
|
|
77
|
-
closeOnOutside: options.closeOnOutside ?? true,
|
|
78
|
-
}
|
|
79
|
-
return {
|
|
80
|
-
activate() {
|
|
81
|
-
ensureWired()
|
|
82
|
-
if (!stack.includes(layer)) stack.push(layer)
|
|
83
|
-
},
|
|
84
|
-
release() {
|
|
85
|
-
const i = stack.indexOf(layer)
|
|
86
|
-
if (i >= 0) stack.splice(i, 1)
|
|
87
|
-
},
|
|
88
|
-
}
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
/** Test/introspection helper: current number of active layers. */
|
|
92
|
-
export function dismissableDepth(): number {
|
|
93
|
-
return stack.length
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
/**
|
|
97
|
-
* Close-on-scroll for popovers that are position:fixed and anchored by a
|
|
98
|
-
* one-time measurement taken when they open. Scrolling an ancestor slides the
|
|
99
|
-
* anchor out from under them, so they have to close - but scrolling INSIDE
|
|
100
|
-
* them (a long menu, a facet list) must not, which is what a bare capture-phase
|
|
101
|
-
* window listener gets wrong: inner scroll containers don't bubble, so the
|
|
102
|
-
* capture listener sees them and dismisses the panel the user is scrolling.
|
|
103
|
-
*
|
|
104
|
-
* Returns the unsubscribe function.
|
|
105
|
-
*/
|
|
106
|
-
export function onScrollOutside(element: () => DismissTarget, onOutside: () => void): () => void {
|
|
107
|
-
if (typeof window === 'undefined') return () => {}
|
|
108
|
-
const handler = (event: Event) => {
|
|
109
|
-
if (containsTarget(element(), event.target as Node)) return
|
|
110
|
-
onOutside()
|
|
111
|
-
}
|
|
112
|
-
window.addEventListener('scroll', handler, true)
|
|
113
|
-
return () => window.removeEventListener('scroll', handler, true)
|
|
114
|
-
}
|
|
1
|
+
/**
|
|
2
|
+
* dismissable-layer - a global stack of dismissable overlays (dropdowns,
|
|
3
|
+
* popovers, dialogs). Escape and outside-pointer dismiss only the TOP layer, so
|
|
4
|
+
* a menu opened inside a dialog closes the menu first and the dialog second -
|
|
5
|
+
* the ordering users expect from nested overlays. One set of document listeners
|
|
6
|
+
* is shared by every layer instead of each component wiring its own.
|
|
7
|
+
*/
|
|
8
|
+
type Reason = 'escape' | 'outside'
|
|
9
|
+
|
|
10
|
+
/** One element, several elements, or a getter of either. A pointerdown counts
|
|
11
|
+
* as "inside" when it lands in ANY of them (e.g. a popover's panel AND its
|
|
12
|
+
* trigger, so clicking the trigger doesn't immediately re-dismiss). */
|
|
13
|
+
export type DismissTarget = HTMLElement | null | ReadonlyArray<HTMLElement | null>
|
|
14
|
+
|
|
15
|
+
type Layer = {
|
|
16
|
+
element: () => DismissTarget
|
|
17
|
+
onDismiss: (reason: Reason) => void
|
|
18
|
+
closeOnEscape: boolean
|
|
19
|
+
closeOnOutside: boolean
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
function containsTarget(target: DismissTarget, node: Node | null): boolean {
|
|
23
|
+
if (!node) return false
|
|
24
|
+
const els = Array.isArray(target) ? target : [target as HTMLElement | null]
|
|
25
|
+
return els.some((el) => el != null && el.contains(node))
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
const stack: Layer[] = []
|
|
29
|
+
let wired = false
|
|
30
|
+
|
|
31
|
+
function ensureWired() {
|
|
32
|
+
if (wired || typeof document === 'undefined') return
|
|
33
|
+
wired = true
|
|
34
|
+
document.addEventListener(
|
|
35
|
+
'keydown',
|
|
36
|
+
(e) => {
|
|
37
|
+
if (e.key !== 'Escape') return
|
|
38
|
+
const top = stack[stack.length - 1]
|
|
39
|
+
if (top?.closeOnEscape) {
|
|
40
|
+
e.stopPropagation()
|
|
41
|
+
top.onDismiss('escape')
|
|
42
|
+
}
|
|
43
|
+
},
|
|
44
|
+
true,
|
|
45
|
+
)
|
|
46
|
+
document.addEventListener(
|
|
47
|
+
'pointerdown',
|
|
48
|
+
(e) => {
|
|
49
|
+
const top = stack[stack.length - 1]
|
|
50
|
+
if (!top?.closeOnOutside) return
|
|
51
|
+
if (!containsTarget(top.element(), e.target as Node)) top.onDismiss('outside')
|
|
52
|
+
},
|
|
53
|
+
true,
|
|
54
|
+
)
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
export type DismissableOptions = {
|
|
58
|
+
/** The panel element(s); a pointerdown outside ALL of them dismisses the layer.
|
|
59
|
+
* Pass multiple (e.g. panel + trigger) so clicking the trigger doesn't
|
|
60
|
+
* immediately re-dismiss what it just opened. */
|
|
61
|
+
element: () => DismissTarget
|
|
62
|
+
onDismiss: (reason: Reason) => void
|
|
63
|
+
/** Dismiss on Escape when topmost. Default true. */
|
|
64
|
+
closeOnEscape?: boolean
|
|
65
|
+
/** Dismiss on outside pointerdown when topmost. Default true. */
|
|
66
|
+
closeOnOutside?: boolean
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
export type DismissableLayer = { activate: () => void; release: () => void }
|
|
70
|
+
|
|
71
|
+
/** Register a dismissable layer. Inert until `activate()`. */
|
|
72
|
+
export function createDismissableLayer(options: DismissableOptions): DismissableLayer {
|
|
73
|
+
const layer: Layer = {
|
|
74
|
+
element: options.element,
|
|
75
|
+
onDismiss: options.onDismiss,
|
|
76
|
+
closeOnEscape: options.closeOnEscape ?? true,
|
|
77
|
+
closeOnOutside: options.closeOnOutside ?? true,
|
|
78
|
+
}
|
|
79
|
+
return {
|
|
80
|
+
activate() {
|
|
81
|
+
ensureWired()
|
|
82
|
+
if (!stack.includes(layer)) stack.push(layer)
|
|
83
|
+
},
|
|
84
|
+
release() {
|
|
85
|
+
const i = stack.indexOf(layer)
|
|
86
|
+
if (i >= 0) stack.splice(i, 1)
|
|
87
|
+
},
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
/** Test/introspection helper: current number of active layers. */
|
|
92
|
+
export function dismissableDepth(): number {
|
|
93
|
+
return stack.length
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
/**
|
|
97
|
+
* Close-on-scroll for popovers that are position:fixed and anchored by a
|
|
98
|
+
* one-time measurement taken when they open. Scrolling an ancestor slides the
|
|
99
|
+
* anchor out from under them, so they have to close - but scrolling INSIDE
|
|
100
|
+
* them (a long menu, a facet list) must not, which is what a bare capture-phase
|
|
101
|
+
* window listener gets wrong: inner scroll containers don't bubble, so the
|
|
102
|
+
* capture listener sees them and dismisses the panel the user is scrolling.
|
|
103
|
+
*
|
|
104
|
+
* Returns the unsubscribe function.
|
|
105
|
+
*/
|
|
106
|
+
export function onScrollOutside(element: () => DismissTarget, onOutside: () => void): () => void {
|
|
107
|
+
if (typeof window === 'undefined') return () => {}
|
|
108
|
+
const handler = (event: Event) => {
|
|
109
|
+
if (containsTarget(element(), event.target as Node)) return
|
|
110
|
+
onOutside()
|
|
111
|
+
}
|
|
112
|
+
window.addEventListener('scroll', handler, true)
|
|
113
|
+
return () => window.removeEventListener('scroll', handler, true)
|
|
114
|
+
}
|
|
@@ -1,49 +1,49 @@
|
|
|
1
|
-
import { describe, expect, it } from 'vitest'
|
|
2
|
-
import {
|
|
3
|
-
getGridCellA11yProps,
|
|
4
|
-
getGridHeaderA11yProps,
|
|
5
|
-
getGridRootA11yProps,
|
|
6
|
-
getGridRowA11yProps,
|
|
7
|
-
} from './a11y'
|
|
8
|
-
|
|
9
|
-
function attrsToHtml(attrs: Record<string, string | number | boolean>) {
|
|
10
|
-
return Object.entries(attrs)
|
|
11
|
-
.map(([key, value]) => `${key}="${String(value)}"`)
|
|
12
|
-
.join(' ')
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
describe('a11y contract rendering', () => {
|
|
16
|
-
it('builds expected headless markup attributes', () => {
|
|
17
|
-
const root = getGridRootA11yProps()
|
|
18
|
-
const header = getGridHeaderA11yProps({
|
|
19
|
-
sortable: true,
|
|
20
|
-
sortDirection: 'descending',
|
|
21
|
-
})
|
|
22
|
-
const row = getGridRowA11yProps(1)
|
|
23
|
-
const cell = getGridCellA11yProps({
|
|
24
|
-
rowIndex: 1,
|
|
25
|
-
colIndex: 2,
|
|
26
|
-
selected: true,
|
|
27
|
-
})
|
|
28
|
-
|
|
29
|
-
const html = [
|
|
30
|
-
`<table ${attrsToHtml(root)}><thead>`,
|
|
31
|
-
`<tr ${attrsToHtml(row)}>`,
|
|
32
|
-
`<th ${attrsToHtml(header)}>Age</th>`,
|
|
33
|
-
`</tr></thead><tbody>`,
|
|
34
|
-
`<tr ${attrsToHtml(row)}><td ${attrsToHtml(cell)}>42</td></tr>`,
|
|
35
|
-
`</tbody></table>`,
|
|
36
|
-
].join('')
|
|
37
|
-
|
|
38
|
-
expect(html).toContain('role="grid"')
|
|
39
|
-
expect(html).toContain('role="columnheader"')
|
|
40
|
-
expect(html).toContain('aria-sort="descending"')
|
|
41
|
-
expect(html).toContain('aria-selected="true"')
|
|
42
|
-
expect(html).toContain('aria-colindex="2"')
|
|
43
|
-
})
|
|
44
|
-
|
|
45
|
-
it('creates stable active descendant ids', async () => {
|
|
46
|
-
const { getGridCellDomId } = await import('./a11y')
|
|
47
|
-
expect(getGridCellDomId('svgrid', 3, 4)).toBe('svgrid_cell_3_4')
|
|
48
|
-
})
|
|
49
|
-
})
|
|
1
|
+
import { describe, expect, it } from 'vitest'
|
|
2
|
+
import {
|
|
3
|
+
getGridCellA11yProps,
|
|
4
|
+
getGridHeaderA11yProps,
|
|
5
|
+
getGridRootA11yProps,
|
|
6
|
+
getGridRowA11yProps,
|
|
7
|
+
} from './a11y'
|
|
8
|
+
|
|
9
|
+
function attrsToHtml(attrs: Record<string, string | number | boolean>) {
|
|
10
|
+
return Object.entries(attrs)
|
|
11
|
+
.map(([key, value]) => `${key}="${String(value)}"`)
|
|
12
|
+
.join(' ')
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
describe('a11y contract rendering', () => {
|
|
16
|
+
it('builds expected headless markup attributes', () => {
|
|
17
|
+
const root = getGridRootA11yProps()
|
|
18
|
+
const header = getGridHeaderA11yProps({
|
|
19
|
+
sortable: true,
|
|
20
|
+
sortDirection: 'descending',
|
|
21
|
+
})
|
|
22
|
+
const row = getGridRowA11yProps(1)
|
|
23
|
+
const cell = getGridCellA11yProps({
|
|
24
|
+
rowIndex: 1,
|
|
25
|
+
colIndex: 2,
|
|
26
|
+
selected: true,
|
|
27
|
+
})
|
|
28
|
+
|
|
29
|
+
const html = [
|
|
30
|
+
`<table ${attrsToHtml(root)}><thead>`,
|
|
31
|
+
`<tr ${attrsToHtml(row)}>`,
|
|
32
|
+
`<th ${attrsToHtml(header)}>Age</th>`,
|
|
33
|
+
`</tr></thead><tbody>`,
|
|
34
|
+
`<tr ${attrsToHtml(row)}><td ${attrsToHtml(cell)}>42</td></tr>`,
|
|
35
|
+
`</tbody></table>`,
|
|
36
|
+
].join('')
|
|
37
|
+
|
|
38
|
+
expect(html).toContain('role="grid"')
|
|
39
|
+
expect(html).toContain('role="columnheader"')
|
|
40
|
+
expect(html).toContain('aria-sort="descending"')
|
|
41
|
+
expect(html).toContain('aria-selected="true"')
|
|
42
|
+
expect(html).toContain('aria-colindex="2"')
|
|
43
|
+
})
|
|
44
|
+
|
|
45
|
+
it('creates stable active descendant ids', async () => {
|
|
46
|
+
const { getGridCellDomId } = await import('./a11y')
|
|
47
|
+
expect(getGridCellDomId('svgrid', 3, 4)).toBe('svgrid_cell_3_4')
|
|
48
|
+
})
|
|
49
|
+
})
|