@svgrid/grid 2.6.3 → 2.6.4
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 -178
- 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 +163 -163
- 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.controller.svelte.d.ts +2 -1
- package/dist/SvGrid.controller.svelte.js +145 -3
- package/dist/SvGrid.css +2846 -2814
- package/dist/SvGrid.svelte +3548 -3490
- package/dist/SvGrid.types.d.ts +61 -0
- 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 +203 -203
- package/dist/SvSwitchButton.svelte +108 -108
- package/dist/SvTagsInput.svelte +115 -115
- 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/a11y/grid-announcements.d.ts +58 -0
- package/dist/a11y/grid-announcements.js +70 -0
- package/dist/advanced-filter.svelte.d.ts +42 -0
- package/dist/advanced-filter.svelte.js +13 -0
- package/dist/build-api.js +44 -2
- package/dist/cdn/{GridMenus-DL1zrDwf.js → GridMenus-1NLNSqWz.js} +15 -15
- package/dist/cdn/{GridMenus-BoVKgAv8.js → GridMenus-B2Dt25-8.js} +15 -15
- package/dist/cdn/{SvDateTimePicker-CHnUkWcH.js → SvDateTimePicker-DSUhIta8.js} +2 -2
- package/dist/cdn/{SvDateTimePicker-CRQH_U7E.js → SvDateTimePicker-h9kPyszT.js} +2 -2
- package/dist/cdn/{SvGridChart-BwVos976.js → SvGridChart-Bs2GIR2Q.js} +1 -1
- package/dist/cdn/{SvGridChart-BEJmNNx9.js → SvGridChart-CwhFz7GV.js} +1 -1
- package/dist/cdn/{SvGridChartPanel-BOknOkrP.js → SvGridChartPanel-1WXuStzM.js} +1 -1
- package/dist/cdn/{SvGridChartPanel-D2PjII4O.js → SvGridChartPanel-e5_nqNP9.js} +1 -1
- package/dist/cdn/{SvGridChartView-00LPUHL1.js → SvGridChartView-SmPW10dI.js} +1 -1
- package/dist/cdn/{SvGridChartView-BhUEJ5ki.js → SvGridChartView-eSPuJE6g.js} +1 -1
- package/dist/cdn/{SvGridDropdown-D0VdjeR8.js → SvGridDropdown-B1ZcLpgs.js} +1 -1
- package/dist/cdn/{SvGridDropdown-D13MtJ2j.js → SvGridDropdown-CtdbHcIS.js} +1 -1
- package/dist/cdn/{src-M2NfKnjX.js → src-D35VGBU5.js} +5954 -5765
- package/dist/cdn/{src-CEpw6Ato.js → src-D7DLIAPD.js} +3396 -3207
- 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/filter-operators.d.ts +2 -1
- package/dist/filter-operators.js +5 -6
- package/dist/filtering/excel-filters.d.ts +1 -0
- package/dist/filtering/excel-filters.js +5 -0
- package/dist/filtering/filter-operator-catalogue.d.ts +42 -0
- package/dist/filtering/filter-operator-catalogue.js +42 -0
- package/dist/filtering/predicate-expr.d.ts +78 -0
- package/dist/filtering/predicate-expr.js +1 -0
- package/dist/filtering/row-predicate.d.ts +17 -0
- package/dist/filtering/row-predicate.js +55 -0
- package/dist/grid-messages.d.ts +7 -0
- package/dist/grid-messages.js +7 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.js +5 -0
- 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/dist/server-data-source.d.ts +34 -0
- package/dist/server-data-source.js +19 -0
- package/dist/svgrid-wrapper.types.d.ts +37 -5
- package/dist/themes/index.js +12 -4
- package/package.json +12 -11
- package/src/FlexRender.svelte +96 -96
- package/src/GridFooter.svelte +178 -178
- 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 +163 -163
- 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 +3858 -3691
- package/src/SvGrid.css +2846 -2814
- package/src/SvGrid.svelte +3548 -3490
- package/src/SvGrid.types.ts +1769 -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 +203 -203
- package/src/SvSwitchButton.svelte +108 -108
- package/src/SvTagsInput.svelte +115 -115
- 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/grid-announcements.test.ts +78 -0
- package/src/a11y/grid-announcements.ts +94 -0
- package/src/a11y.announce.test.ts +250 -0
- package/src/a11y.axe.test.ts +194 -0
- package/src/a11y.contract.test.ts +49 -49
- package/src/a11y.test.ts +59 -59
- package/src/a11y.ts +61 -61
- package/src/advanced-filter.svelte.ts +59 -0
- 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 +846 -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/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 +170 -170
- 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 +160 -157
- package/src/filtering/excel-filters.ts +15 -0
- package/src/filtering/filter-operator-catalogue.ts +74 -0
- package/src/filtering/node-entry.test.ts +75 -0
- package/src/filtering/predicate-expr.ts +50 -0
- package/src/filtering/row-predicate.ts +57 -0
- package/src/flex-render.ts +3 -3
- package/src/form-field.ts +127 -127
- package/src/grid-messages.ts +18 -0
- package/src/group-display.test.ts +167 -167
- package/src/group-display.ts +200 -200
- package/src/index.ts +754 -726
- 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 +383 -289
- package/src/server-data-source.ts +469 -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 +558 -526
- package/src/svgrid.advanced-filter.test.ts +481 -0
- 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.displayed-rows.test.ts +144 -0
- 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 +331 -331
- package/src/svgrid.filter-menu-scroll.test.ts +112 -112
- 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.group-props-reactive.svelte.test.ts +151 -0
- package/src/svgrid.group-props.test.ts +280 -0
- 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 +63 -63
- package/src/svgriddropdown.async-panel.svelte.test.ts +195 -195
- package/src/test-setup.ts +62 -62
- package/src/themes/contrast.test.ts +112 -0
- package/src/themes/index.ts +286 -278
- 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
- package/themes/catppuccin.css +3 -3
- package/themes/dracula.css +3 -3
- package/themes/nord.css +3 -3
- package/themes/notion.css +4 -4
|
@@ -0,0 +1,250 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Verifies the grid actually SPEAKS - that the announcement builders are wired
|
|
3
|
+
* to a real live region and fire on the state changes they were written for.
|
|
4
|
+
*
|
|
5
|
+
* `a11y/grid-announcements.test.ts` proves the message text is right. This file
|
|
6
|
+
* proves the wiring exists, which is the part that was missing: `announce()`
|
|
7
|
+
* shipped and was exported for months while `<SvGrid>` never called it, so the
|
|
8
|
+
* documented "filter and selection announcements" were not happening at all.
|
|
9
|
+
*/
|
|
10
|
+
import { describe, expect, it, beforeEach, afterEach, vi } from 'vitest'
|
|
11
|
+
import { mount, unmount, flushSync } from 'svelte'
|
|
12
|
+
import SvGrid from './SvGrid.svelte'
|
|
13
|
+
import { _resetLiveRegions } from './a11y/live-region'
|
|
14
|
+
import {
|
|
15
|
+
tableFeatures,
|
|
16
|
+
columnFilteringFeature,
|
|
17
|
+
rowSortingFeature,
|
|
18
|
+
rowSelectionFeature,
|
|
19
|
+
createCoreRowModel,
|
|
20
|
+
createFilteredRowModel,
|
|
21
|
+
createSortedRowModel,
|
|
22
|
+
} from './index'
|
|
23
|
+
import type { ColumnDef, SvGridApi } from './index'
|
|
24
|
+
|
|
25
|
+
type Row = { id: string; name: string; team: string }
|
|
26
|
+
|
|
27
|
+
const features = tableFeatures({
|
|
28
|
+
columnFilteringFeature,
|
|
29
|
+
rowSortingFeature,
|
|
30
|
+
rowSelectionFeature,
|
|
31
|
+
})
|
|
32
|
+
|
|
33
|
+
const rows: Row[] = [
|
|
34
|
+
{ id: 'r1', name: 'Ada', team: 'Platform' },
|
|
35
|
+
{ id: 'r2', name: 'Grace', team: 'Compilers' },
|
|
36
|
+
{ id: 'r3', name: 'Karen', team: 'Search' },
|
|
37
|
+
{ id: 'r4', name: 'Barbara', team: 'Platform' },
|
|
38
|
+
]
|
|
39
|
+
|
|
40
|
+
const cols: ColumnDef<typeof features, Row>[] = [
|
|
41
|
+
{ field: 'name', header: 'Name', width: 200 },
|
|
42
|
+
{ field: 'team', header: 'Team', width: 140 },
|
|
43
|
+
]
|
|
44
|
+
|
|
45
|
+
/** Text currently in the polite live region. */
|
|
46
|
+
const politeText = () =>
|
|
47
|
+
document.querySelector('[aria-live="polite"]')?.textContent ?? ''
|
|
48
|
+
|
|
49
|
+
/** `announce()` sets the text on a microtask so a repeat message re-fires. */
|
|
50
|
+
const settle = async () => {
|
|
51
|
+
await Promise.resolve()
|
|
52
|
+
await Promise.resolve()
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
function mountGrid(extraProps: Record<string, unknown> = {}) {
|
|
56
|
+
const target = document.createElement('div')
|
|
57
|
+
document.body.appendChild(target)
|
|
58
|
+
let api: SvGridApi<typeof features, Row> | null = null
|
|
59
|
+
const app = mount(SvGrid, {
|
|
60
|
+
target,
|
|
61
|
+
props: {
|
|
62
|
+
data: rows,
|
|
63
|
+
columns: cols,
|
|
64
|
+
features,
|
|
65
|
+
_rowModels: {
|
|
66
|
+
coreRowModel: createCoreRowModel(),
|
|
67
|
+
filteredRowModel: createFilteredRowModel(),
|
|
68
|
+
sortedRowModel: createSortedRowModel({} as never),
|
|
69
|
+
},
|
|
70
|
+
containerHeight: 300,
|
|
71
|
+
virtualization: false,
|
|
72
|
+
columnVirtualization: false,
|
|
73
|
+
onApiReady: (a: SvGridApi<typeof features, Row>) => {
|
|
74
|
+
api = a
|
|
75
|
+
},
|
|
76
|
+
...extraProps,
|
|
77
|
+
} as never,
|
|
78
|
+
})
|
|
79
|
+
flushSync()
|
|
80
|
+
return {
|
|
81
|
+
target,
|
|
82
|
+
get api() {
|
|
83
|
+
return api!
|
|
84
|
+
},
|
|
85
|
+
destroy: () => {
|
|
86
|
+
unmount(app)
|
|
87
|
+
target.remove()
|
|
88
|
+
},
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
beforeEach(() => {
|
|
93
|
+
vi.useFakeTimers()
|
|
94
|
+
_resetLiveRegions()
|
|
95
|
+
})
|
|
96
|
+
|
|
97
|
+
afterEach(() => {
|
|
98
|
+
vi.useRealTimers()
|
|
99
|
+
_resetLiveRegions()
|
|
100
|
+
})
|
|
101
|
+
|
|
102
|
+
describe('filter announcements', () => {
|
|
103
|
+
it('says nothing on mount', async () => {
|
|
104
|
+
const g = mountGrid()
|
|
105
|
+
try {
|
|
106
|
+
await vi.advanceTimersByTimeAsync(500)
|
|
107
|
+
// An unfiltered grid announcing "4 of 4 rows match" would be noise on
|
|
108
|
+
// every page load.
|
|
109
|
+
expect(politeText()).toBe('')
|
|
110
|
+
} finally {
|
|
111
|
+
g.destroy()
|
|
112
|
+
}
|
|
113
|
+
})
|
|
114
|
+
|
|
115
|
+
it('reports the match count after a filter narrows the rows', async () => {
|
|
116
|
+
const g = mountGrid()
|
|
117
|
+
try {
|
|
118
|
+
g.api.setState({ globalFilter: 'Platform' })
|
|
119
|
+
flushSync()
|
|
120
|
+
await vi.advanceTimersByTimeAsync(500)
|
|
121
|
+
await settle()
|
|
122
|
+
expect(politeText()).toBe('2 of 4 rows match the current filters')
|
|
123
|
+
} finally {
|
|
124
|
+
g.destroy()
|
|
125
|
+
}
|
|
126
|
+
})
|
|
127
|
+
|
|
128
|
+
it('reports no matches distinctly', async () => {
|
|
129
|
+
const g = mountGrid()
|
|
130
|
+
try {
|
|
131
|
+
g.api.setState({ globalFilter: 'nothing-matches-this' })
|
|
132
|
+
flushSync()
|
|
133
|
+
await vi.advanceTimersByTimeAsync(500)
|
|
134
|
+
await settle()
|
|
135
|
+
expect(politeText()).toBe('No rows match the current filters')
|
|
136
|
+
} finally {
|
|
137
|
+
g.destroy()
|
|
138
|
+
}
|
|
139
|
+
})
|
|
140
|
+
|
|
141
|
+
it('debounces so only the final count is announced while typing', async () => {
|
|
142
|
+
const g = mountGrid()
|
|
143
|
+
try {
|
|
144
|
+
// Three keystrokes in quick succession, as a user typing "Pla".
|
|
145
|
+
for (const s of ['P', 'Pl', 'Pla']) {
|
|
146
|
+
g.api.setState({ globalFilter: s })
|
|
147
|
+
flushSync()
|
|
148
|
+
await vi.advanceTimersByTimeAsync(50)
|
|
149
|
+
}
|
|
150
|
+
await vi.advanceTimersByTimeAsync(500)
|
|
151
|
+
await settle()
|
|
152
|
+
// A polite region queues rather than replaces, so without the debounce
|
|
153
|
+
// the user would sit through the count for every prefix.
|
|
154
|
+
expect(politeText()).toBe('2 of 4 rows match the current filters')
|
|
155
|
+
} finally {
|
|
156
|
+
g.destroy()
|
|
157
|
+
}
|
|
158
|
+
})
|
|
159
|
+
|
|
160
|
+
it('confirms that clearing the filters took effect', async () => {
|
|
161
|
+
const g = mountGrid()
|
|
162
|
+
try {
|
|
163
|
+
g.api.setState({ globalFilter: 'Platform' })
|
|
164
|
+
flushSync()
|
|
165
|
+
await vi.advanceTimersByTimeAsync(500)
|
|
166
|
+
g.api.clearAllFilters()
|
|
167
|
+
flushSync()
|
|
168
|
+
await vi.advanceTimersByTimeAsync(500)
|
|
169
|
+
await settle()
|
|
170
|
+
expect(politeText()).toBe('Filters cleared, showing all 4 rows')
|
|
171
|
+
} finally {
|
|
172
|
+
g.destroy()
|
|
173
|
+
}
|
|
174
|
+
})
|
|
175
|
+
|
|
176
|
+
it('stays silent in external-filter mode', async () => {
|
|
177
|
+
// The server decided what matched; the local count describes only the page
|
|
178
|
+
// in hand, so announcing it would misreport the result set.
|
|
179
|
+
const g = mountGrid({ externalFilter: true })
|
|
180
|
+
try {
|
|
181
|
+
g.api.setState({ globalFilter: 'Platform' })
|
|
182
|
+
flushSync()
|
|
183
|
+
await vi.advanceTimersByTimeAsync(500)
|
|
184
|
+
expect(politeText()).toBe('')
|
|
185
|
+
} finally {
|
|
186
|
+
g.destroy()
|
|
187
|
+
}
|
|
188
|
+
})
|
|
189
|
+
})
|
|
190
|
+
|
|
191
|
+
describe('selection announcements', () => {
|
|
192
|
+
it('announces select-all', async () => {
|
|
193
|
+
const g = mountGrid()
|
|
194
|
+
try {
|
|
195
|
+
g.api.selectAllRows()
|
|
196
|
+
flushSync()
|
|
197
|
+
await settle()
|
|
198
|
+
expect(politeText()).toBe('4 rows selected')
|
|
199
|
+
} finally {
|
|
200
|
+
g.destroy()
|
|
201
|
+
}
|
|
202
|
+
})
|
|
203
|
+
|
|
204
|
+
it('announces clearing a multi-row selection', async () => {
|
|
205
|
+
const g = mountGrid()
|
|
206
|
+
try {
|
|
207
|
+
g.api.selectAllRows()
|
|
208
|
+
flushSync()
|
|
209
|
+
await settle()
|
|
210
|
+
g.api.clearRowSelection()
|
|
211
|
+
flushSync()
|
|
212
|
+
await settle()
|
|
213
|
+
expect(politeText()).toBe('Selection cleared')
|
|
214
|
+
} finally {
|
|
215
|
+
g.destroy()
|
|
216
|
+
}
|
|
217
|
+
})
|
|
218
|
+
|
|
219
|
+
it('stays silent when a single row is selected', async () => {
|
|
220
|
+
const g = mountGrid()
|
|
221
|
+
try {
|
|
222
|
+
g.api.selectRows(['r1'])
|
|
223
|
+
flushSync()
|
|
224
|
+
await settle()
|
|
225
|
+
// Focus lands on the row and the reader announces it from aria-selected.
|
|
226
|
+
expect(politeText()).toBe('')
|
|
227
|
+
} finally {
|
|
228
|
+
g.destroy()
|
|
229
|
+
}
|
|
230
|
+
})
|
|
231
|
+
})
|
|
232
|
+
|
|
233
|
+
describe('announcements are localizable', () => {
|
|
234
|
+
it('uses a consumer-supplied template, placeholders and all', async () => {
|
|
235
|
+
const g = mountGrid({
|
|
236
|
+
localization: {
|
|
237
|
+
text: { announceFilterResults: '{visible} van de {total} rijen komen overeen' },
|
|
238
|
+
},
|
|
239
|
+
})
|
|
240
|
+
try {
|
|
241
|
+
g.api.setState({ globalFilter: 'Platform' })
|
|
242
|
+
flushSync()
|
|
243
|
+
await vi.advanceTimersByTimeAsync(500)
|
|
244
|
+
await settle()
|
|
245
|
+
expect(politeText()).toBe('2 van de 4 rijen komen overeen')
|
|
246
|
+
} finally {
|
|
247
|
+
g.destroy()
|
|
248
|
+
}
|
|
249
|
+
})
|
|
250
|
+
})
|
|
@@ -0,0 +1,194 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Accessibility tests that run axe-core against a REAL rendered grid.
|
|
3
|
+
*
|
|
4
|
+
* The other a11y tests in this package (`a11y.test.ts`, `a11y.contract.test.ts`)
|
|
5
|
+
* check the ARIA prop builders in isolation, against strings. Useful, but they
|
|
6
|
+
* cannot catch a violation that only exists once the component is assembled:
|
|
7
|
+
* a duplicated id, a control with no accessible name, a role nested somewhere
|
|
8
|
+
* it is not allowed. This file mounts `<SvGrid>` and audits the resulting DOM.
|
|
9
|
+
*
|
|
10
|
+
* It runs in the normal vitest suite - which means it runs in CI. The Playwright
|
|
11
|
+
* e2e suite cannot, because it depends on the private `website/` submodule.
|
|
12
|
+
*
|
|
13
|
+
* jsdom limitation, stated rather than hidden: jsdom performs no layout, so
|
|
14
|
+
* every geometry-dependent rule is meaningless here and is disabled below. The
|
|
15
|
+
* important one is `color-contrast`, which needs real painting. Contrast is a
|
|
16
|
+
* property of a theme, not of grid markup, and the guidance for verifying it
|
|
17
|
+
* against your own theme lives in docs/help/accessibility.md. What this file
|
|
18
|
+
* does cover is the structural half: roles, names, relationships, and ids.
|
|
19
|
+
*/
|
|
20
|
+
import { describe, expect, it } from 'vitest'
|
|
21
|
+
import { mount, unmount } from 'svelte'
|
|
22
|
+
import axe from 'axe-core'
|
|
23
|
+
import SvGrid from './SvGrid.svelte'
|
|
24
|
+
import {
|
|
25
|
+
tableFeatures,
|
|
26
|
+
columnFilteringFeature,
|
|
27
|
+
rowSortingFeature,
|
|
28
|
+
rowSelectionFeature,
|
|
29
|
+
createCoreRowModel,
|
|
30
|
+
createFilteredRowModel,
|
|
31
|
+
createSortedRowModel,
|
|
32
|
+
} from './index'
|
|
33
|
+
import type { ColumnDef } from './index'
|
|
34
|
+
|
|
35
|
+
type Row = { id: string; name: string; team: string; score: number }
|
|
36
|
+
|
|
37
|
+
const features = tableFeatures({
|
|
38
|
+
columnFilteringFeature,
|
|
39
|
+
rowSortingFeature,
|
|
40
|
+
rowSelectionFeature,
|
|
41
|
+
})
|
|
42
|
+
|
|
43
|
+
const sortFns = {} as never
|
|
44
|
+
|
|
45
|
+
const rows: Row[] = [
|
|
46
|
+
{ id: 'r1', name: 'Ada Lovelace', team: 'Platform', score: 91 },
|
|
47
|
+
{ id: 'r2', name: 'Grace Hopper', team: 'Compilers', score: 88 },
|
|
48
|
+
{ id: 'r3', name: 'Karen Sparck Jones', team: 'Search', score: 95 },
|
|
49
|
+
{ id: 'r4', name: 'Barbara Liskov', team: 'Platform', score: 93 },
|
|
50
|
+
]
|
|
51
|
+
|
|
52
|
+
const cols: ColumnDef<typeof features, Row>[] = [
|
|
53
|
+
{ field: 'name', header: 'Name', width: 200 },
|
|
54
|
+
{ field: 'team', header: 'Team', width: 140 },
|
|
55
|
+
{ field: 'score', header: 'Score', width: 100, align: 'right' },
|
|
56
|
+
]
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* Rules that depend on layout or painting. jsdom gives every element zero size
|
|
60
|
+
* and no computed colour, so these produce noise rather than signal.
|
|
61
|
+
*/
|
|
62
|
+
const LAYOUT_DEPENDENT_RULES = [
|
|
63
|
+
'color-contrast',
|
|
64
|
+
'scrollable-region-focusable',
|
|
65
|
+
'target-size',
|
|
66
|
+
]
|
|
67
|
+
|
|
68
|
+
function mountGrid(extraProps: Record<string, unknown> = {}) {
|
|
69
|
+
const target = document.createElement('div')
|
|
70
|
+
document.body.appendChild(target)
|
|
71
|
+
const app = mount(SvGrid, {
|
|
72
|
+
target,
|
|
73
|
+
props: {
|
|
74
|
+
data: rows,
|
|
75
|
+
columns: cols,
|
|
76
|
+
features,
|
|
77
|
+
_rowModels: {
|
|
78
|
+
coreRowModel: createCoreRowModel(),
|
|
79
|
+
filteredRowModel: createFilteredRowModel(),
|
|
80
|
+
sortedRowModel: createSortedRowModel(sortFns),
|
|
81
|
+
},
|
|
82
|
+
containerHeight: 300,
|
|
83
|
+
virtualization: false,
|
|
84
|
+
columnVirtualization: false,
|
|
85
|
+
...extraProps,
|
|
86
|
+
} as never,
|
|
87
|
+
})
|
|
88
|
+
return {
|
|
89
|
+
target,
|
|
90
|
+
destroy: () => {
|
|
91
|
+
unmount(app)
|
|
92
|
+
target.remove()
|
|
93
|
+
},
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
async function auditGrid(props: Record<string, unknown> = {}) {
|
|
98
|
+
const { target, destroy } = mountGrid(props)
|
|
99
|
+
try {
|
|
100
|
+
// Let the grid settle (row model + effects) before auditing.
|
|
101
|
+
await new Promise((r) => setTimeout(r, 0))
|
|
102
|
+
const results = await axe.run(target, {
|
|
103
|
+
rules: Object.fromEntries(LAYOUT_DEPENDENT_RULES.map((id) => [id, { enabled: false }])),
|
|
104
|
+
})
|
|
105
|
+
return results.violations.map((v) => ({
|
|
106
|
+
id: v.id,
|
|
107
|
+
impact: v.impact,
|
|
108
|
+
help: v.help,
|
|
109
|
+
nodes: v.nodes.map((n) => n.html).slice(0, 3),
|
|
110
|
+
}))
|
|
111
|
+
} finally {
|
|
112
|
+
destroy()
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
describe('axe audit of a rendered grid', () => {
|
|
117
|
+
it('reports no violations for a plain grid', async () => {
|
|
118
|
+
expect(await auditGrid()).toEqual([])
|
|
119
|
+
})
|
|
120
|
+
|
|
121
|
+
it('reports no violations with the filter row and global filter shown', async () => {
|
|
122
|
+
expect(
|
|
123
|
+
await auditGrid({ showColumnFilters: true, showFilterRow: true, showGlobalFilter: true }),
|
|
124
|
+
).toEqual([])
|
|
125
|
+
})
|
|
126
|
+
|
|
127
|
+
it('reports no violations with row selection enabled', async () => {
|
|
128
|
+
expect(await auditGrid({ showRowSelection: true })).toEqual([])
|
|
129
|
+
})
|
|
130
|
+
|
|
131
|
+
it('reports no violations with pagination shown', async () => {
|
|
132
|
+
expect(await auditGrid({ showPagination: true, pageSize: 2 })).toEqual([])
|
|
133
|
+
})
|
|
134
|
+
|
|
135
|
+
it('actually audits something - the grid role is present in the tree', async () => {
|
|
136
|
+
// Guards against the audit silently passing because nothing rendered.
|
|
137
|
+
const { target, destroy } = mountGrid()
|
|
138
|
+
try {
|
|
139
|
+
await new Promise((r) => setTimeout(r, 0))
|
|
140
|
+
expect(target.querySelector('[role="grid"], table')).not.toBeNull()
|
|
141
|
+
} finally {
|
|
142
|
+
destroy()
|
|
143
|
+
}
|
|
144
|
+
})
|
|
145
|
+
})
|
|
146
|
+
|
|
147
|
+
describe('validation is exposed to assistive technology', () => {
|
|
148
|
+
// `validate` used to mark a bad cell with a red class and a `title` only.
|
|
149
|
+
// Both are visual: the class carries no semantics at all, and `title` is
|
|
150
|
+
// unreliably surfaced and unreachable by keyboard. A screen-reader user had
|
|
151
|
+
// no way to know the cell was rejected, which is WCAG 3.3.1.
|
|
152
|
+
const validatedCols: ColumnDef<typeof features, Row>[] = [
|
|
153
|
+
{ field: 'name', header: 'Name', width: 200 },
|
|
154
|
+
{
|
|
155
|
+
field: 'score',
|
|
156
|
+
header: 'Score',
|
|
157
|
+
width: 100,
|
|
158
|
+
validate: ({ value }) => (Number(value) < 90 ? 'Score must be at least 90' : null),
|
|
159
|
+
},
|
|
160
|
+
]
|
|
161
|
+
|
|
162
|
+
it('marks an invalid cell with aria-invalid and keeps the message', async () => {
|
|
163
|
+
const { target, destroy } = mountGrid({ columns: validatedCols })
|
|
164
|
+
try {
|
|
165
|
+
await new Promise((r) => setTimeout(r, 0))
|
|
166
|
+
const invalid = [...target.querySelectorAll('td[aria-invalid="true"]')]
|
|
167
|
+
// Grace 88 fails, Ada 91 / Karen 95 / Barbara 93 pass.
|
|
168
|
+
expect(invalid).toHaveLength(1)
|
|
169
|
+
// The reason must reach assistive tech, not just the hover tooltip:
|
|
170
|
+
// either as the accessible description (`title`) or as visually-hidden
|
|
171
|
+
// text read with the cell. Which one depends on the render path.
|
|
172
|
+
const reason =
|
|
173
|
+
invalid[0]?.getAttribute('title') ??
|
|
174
|
+
invalid[0]?.querySelector('.sv-grid-sr-only')?.textContent
|
|
175
|
+
expect(reason).toBe('Score must be at least 90')
|
|
176
|
+
} finally {
|
|
177
|
+
destroy()
|
|
178
|
+
}
|
|
179
|
+
})
|
|
180
|
+
|
|
181
|
+
it('leaves valid cells unmarked', async () => {
|
|
182
|
+
const { target, destroy } = mountGrid({ columns: validatedCols })
|
|
183
|
+
try {
|
|
184
|
+
await new Promise((r) => setTimeout(r, 0))
|
|
185
|
+
expect(target.querySelectorAll('td[aria-invalid]')).toHaveLength(1)
|
|
186
|
+
} finally {
|
|
187
|
+
destroy()
|
|
188
|
+
}
|
|
189
|
+
})
|
|
190
|
+
|
|
191
|
+
it('passes axe with an invalid cell rendered', async () => {
|
|
192
|
+
expect(await auditGrid({ columns: validatedCols })).toEqual([])
|
|
193
|
+
})
|
|
194
|
+
})
|
|
@@ -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
|
+
})
|
package/src/a11y.test.ts
CHANGED
|
@@ -1,59 +1,59 @@
|
|
|
1
|
-
import { describe, expect, it } from 'vitest'
|
|
2
|
-
import {
|
|
3
|
-
getGridCellA11yProps,
|
|
4
|
-
getGridHeaderA11yProps,
|
|
5
|
-
getGridRootA11yProps,
|
|
6
|
-
getGridRowA11yProps,
|
|
7
|
-
} from './a11y'
|
|
8
|
-
|
|
9
|
-
describe('a11y helpers', () => {
|
|
10
|
-
it('returns grid role props', () => {
|
|
11
|
-
expect(
|
|
12
|
-
getGridRootA11yProps({
|
|
13
|
-
activeDescendantId: 'svgrid_cell_0_0',
|
|
14
|
-
rowCount: 10,
|
|
15
|
-
colCount: 5,
|
|
16
|
-
}),
|
|
17
|
-
).toEqual({
|
|
18
|
-
role: 'grid',
|
|
19
|
-
tabindex: 0,
|
|
20
|
-
'aria-activedescendant': 'svgrid_cell_0_0',
|
|
21
|
-
'aria-rowcount': 10,
|
|
22
|
-
'aria-colcount': 5,
|
|
23
|
-
})
|
|
24
|
-
})
|
|
25
|
-
|
|
26
|
-
it('returns header sort semantics', () => {
|
|
27
|
-
expect(
|
|
28
|
-
getGridHeaderA11yProps({
|
|
29
|
-
sortable: true,
|
|
30
|
-
sortDirection: 'ascending',
|
|
31
|
-
}),
|
|
32
|
-
).toEqual({
|
|
33
|
-
role: 'columnheader',
|
|
34
|
-
'aria-sort': 'ascending',
|
|
35
|
-
})
|
|
36
|
-
})
|
|
37
|
-
|
|
38
|
-
it('returns row and cell indices for accessibility metadata', () => {
|
|
39
|
-
expect(getGridRowA11yProps(2)).toEqual({
|
|
40
|
-
role: 'row',
|
|
41
|
-
'aria-rowindex': 2,
|
|
42
|
-
})
|
|
43
|
-
|
|
44
|
-
expect(
|
|
45
|
-
getGridCellA11yProps({
|
|
46
|
-
id: 'svgrid_cell_2_3',
|
|
47
|
-
rowIndex: 2,
|
|
48
|
-
colIndex: 3,
|
|
49
|
-
selected: true,
|
|
50
|
-
}),
|
|
51
|
-
).toEqual({
|
|
52
|
-
role: 'gridcell',
|
|
53
|
-
id: 'svgrid_cell_2_3',
|
|
54
|
-
'aria-colindex': 3,
|
|
55
|
-
'aria-rowindex': 2,
|
|
56
|
-
'aria-selected': true,
|
|
57
|
-
})
|
|
58
|
-
})
|
|
59
|
-
})
|
|
1
|
+
import { describe, expect, it } from 'vitest'
|
|
2
|
+
import {
|
|
3
|
+
getGridCellA11yProps,
|
|
4
|
+
getGridHeaderA11yProps,
|
|
5
|
+
getGridRootA11yProps,
|
|
6
|
+
getGridRowA11yProps,
|
|
7
|
+
} from './a11y'
|
|
8
|
+
|
|
9
|
+
describe('a11y helpers', () => {
|
|
10
|
+
it('returns grid role props', () => {
|
|
11
|
+
expect(
|
|
12
|
+
getGridRootA11yProps({
|
|
13
|
+
activeDescendantId: 'svgrid_cell_0_0',
|
|
14
|
+
rowCount: 10,
|
|
15
|
+
colCount: 5,
|
|
16
|
+
}),
|
|
17
|
+
).toEqual({
|
|
18
|
+
role: 'grid',
|
|
19
|
+
tabindex: 0,
|
|
20
|
+
'aria-activedescendant': 'svgrid_cell_0_0',
|
|
21
|
+
'aria-rowcount': 10,
|
|
22
|
+
'aria-colcount': 5,
|
|
23
|
+
})
|
|
24
|
+
})
|
|
25
|
+
|
|
26
|
+
it('returns header sort semantics', () => {
|
|
27
|
+
expect(
|
|
28
|
+
getGridHeaderA11yProps({
|
|
29
|
+
sortable: true,
|
|
30
|
+
sortDirection: 'ascending',
|
|
31
|
+
}),
|
|
32
|
+
).toEqual({
|
|
33
|
+
role: 'columnheader',
|
|
34
|
+
'aria-sort': 'ascending',
|
|
35
|
+
})
|
|
36
|
+
})
|
|
37
|
+
|
|
38
|
+
it('returns row and cell indices for accessibility metadata', () => {
|
|
39
|
+
expect(getGridRowA11yProps(2)).toEqual({
|
|
40
|
+
role: 'row',
|
|
41
|
+
'aria-rowindex': 2,
|
|
42
|
+
})
|
|
43
|
+
|
|
44
|
+
expect(
|
|
45
|
+
getGridCellA11yProps({
|
|
46
|
+
id: 'svgrid_cell_2_3',
|
|
47
|
+
rowIndex: 2,
|
|
48
|
+
colIndex: 3,
|
|
49
|
+
selected: true,
|
|
50
|
+
}),
|
|
51
|
+
).toEqual({
|
|
52
|
+
role: 'gridcell',
|
|
53
|
+
id: 'svgrid_cell_2_3',
|
|
54
|
+
'aria-colindex': 3,
|
|
55
|
+
'aria-rowindex': 2,
|
|
56
|
+
'aria-selected': true,
|
|
57
|
+
})
|
|
58
|
+
})
|
|
59
|
+
})
|