@svgrid/grid 2.6.21 → 2.7.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.
Files changed (358) hide show
  1. package/CHANGELOG.md +150 -88
  2. package/README.md +221 -199
  3. package/dist/FlexRender.svelte +96 -96
  4. package/dist/GridFooter.svelte +181 -181
  5. package/dist/GridMenus.svelte +201 -18
  6. package/dist/SvAutoComplete.svelte +169 -165
  7. package/dist/SvAvatar.svelte +75 -75
  8. package/dist/SvCalendar.svelte +503 -503
  9. package/dist/SvCarousel.svelte +141 -141
  10. package/dist/SvCheckBox.svelte +102 -102
  11. package/dist/SvCircularProgress.svelte +109 -109
  12. package/dist/SvColorInput.svelte +181 -181
  13. package/dist/SvComboBox.svelte +279 -275
  14. package/dist/SvContextMenu.svelte +116 -116
  15. package/dist/SvCountryInput.svelte +163 -163
  16. package/dist/SvDateRangeInput.svelte +25 -3
  17. package/dist/SvDrawer.svelte +254 -254
  18. package/dist/SvDropDownList.svelte +378 -374
  19. package/dist/SvDurationInput.svelte +126 -126
  20. package/dist/SvField.svelte +293 -293
  21. package/dist/SvForm.svelte +437 -437
  22. package/dist/SvGrid.controller.svelte.d.ts +61 -9
  23. package/dist/SvGrid.controller.svelte.js +363 -123
  24. package/dist/SvGrid.css +222 -1
  25. package/dist/SvGrid.helpers.d.ts +55 -0
  26. package/dist/SvGrid.helpers.js +83 -0
  27. package/dist/SvGrid.svelte +255 -56
  28. package/dist/SvGrid.types.d.ts +146 -1
  29. package/dist/SvGridCellEditor.svelte +744 -662
  30. package/dist/SvGridChart.svelte +1716 -1716
  31. package/dist/SvGridChartPanel.svelte +485 -485
  32. package/dist/SvGridChartView.svelte +70 -70
  33. package/dist/SvGridDropdown.svelte +728 -728
  34. package/dist/SvGridSelect.svelte +270 -266
  35. package/dist/SvGridSelect.svelte.d.ts +1 -1
  36. package/dist/SvGroupCell.svelte +116 -116
  37. package/dist/SvListBox.svelte +334 -326
  38. package/dist/SvMaskedInput.svelte +122 -122
  39. package/dist/SvMenu.svelte +124 -124
  40. package/dist/SvMenuList.svelte +146 -146
  41. package/dist/SvMultiSelect.svelte +293 -289
  42. package/dist/SvMultiSelect.svelte.d.ts +1 -1
  43. package/dist/SvNumberInput.svelte +172 -168
  44. package/dist/SvOtpInput.svelte +158 -158
  45. package/dist/SvPasswordInput.svelte +151 -151
  46. package/dist/SvPhoneInput.svelte +133 -133
  47. package/dist/SvPopover.svelte +197 -197
  48. package/dist/SvProgress.svelte +116 -116
  49. package/dist/SvRadioGroup.svelte +107 -107
  50. package/dist/SvRating.svelte +112 -112
  51. package/dist/SvResult.svelte +73 -73
  52. package/dist/SvRichCell.svelte +125 -0
  53. package/dist/SvRichCell.svelte.d.ts +15 -0
  54. package/dist/SvRichText.svelte +211 -211
  55. package/dist/SvRowGroupPanel.svelte +170 -170
  56. package/dist/SvScrollArea.svelte +61 -61
  57. package/dist/SvSlider.svelte +203 -203
  58. package/dist/SvSwitchButton.svelte +108 -108
  59. package/dist/SvTagsInput.svelte +115 -115
  60. package/dist/SvTextArea.svelte +5 -1
  61. package/dist/SvTextInput.svelte +147 -147
  62. package/dist/SvTimePicker.svelte +245 -245
  63. package/dist/SvToaster.svelte +159 -159
  64. package/dist/SvToggleButton.svelte +85 -85
  65. package/dist/SvTooltip.svelte +161 -161
  66. package/dist/SvTour.svelte +208 -208
  67. package/dist/SvTree.svelte +444 -444
  68. package/dist/SvTreeSelect.svelte +239 -235
  69. package/dist/SvTreeSelect.svelte.d.ts +1 -1
  70. package/dist/builtin-editors.d.ts +2 -2
  71. package/dist/builtin-editors.js +19 -3
  72. package/dist/cdn/GridMenus-C4oLsJyj.js +600 -0
  73. package/dist/cdn/GridMenus-yEivjNwl.js +601 -0
  74. package/dist/cdn/SvDateRangeInput-Bh0A0JkF.js +199 -0
  75. package/dist/cdn/SvDateRangeInput-DflbiP7N.js +198 -0
  76. package/dist/cdn/SvDateTimePicker-BWwpfB_o.js +812 -0
  77. package/dist/cdn/SvDateTimePicker-Bivn8dAP.js +816 -0
  78. package/dist/cdn/SvGridCellEditor-AXL8cHGO.js +550 -0
  79. package/dist/cdn/SvGridCellEditor-Ba7rY3eu.js +549 -0
  80. package/dist/cdn/{SvGridChart-BwVos976.js → SvGridChart-Bs2GIR2Q.js} +1 -1
  81. package/dist/cdn/{SvGridChart-BEJmNNx9.js → SvGridChart-CwhFz7GV.js} +1 -1
  82. package/dist/cdn/{SvGridChartPanel-BOknOkrP.js → SvGridChartPanel-1WXuStzM.js} +1 -1
  83. package/dist/cdn/{SvGridChartPanel-D2PjII4O.js → SvGridChartPanel-e5_nqNP9.js} +1 -1
  84. package/dist/cdn/{SvGridChartView-00LPUHL1.js → SvGridChartView-SmPW10dI.js} +1 -1
  85. package/dist/cdn/{SvGridChartView-BhUEJ5ki.js → SvGridChartView-eSPuJE6g.js} +1 -1
  86. package/dist/cdn/{SvGridDropdown-D0VdjeR8.js → SvGridDropdown-B1ZcLpgs.js} +1 -1
  87. package/dist/cdn/{SvGridDropdown-D13MtJ2j.js → SvGridDropdown-CtdbHcIS.js} +1 -1
  88. package/dist/cdn/column-resize-DsfNXMom.js +102 -0
  89. package/dist/cdn/date-format-CcP1tafP.js +1395 -0
  90. package/dist/cdn/date-format-DZT7T1wf.js +1393 -0
  91. package/dist/cdn/{editor-registry-CiI0xlKg.js → editor-registry-BhgE3S84.js} +51 -25
  92. package/dist/cdn/row-resize-BRcimkUT.js +95 -0
  93. package/dist/cdn/{src-BYq-qyrp.js → src-COC0vnpg.js} +7846 -7317
  94. package/dist/cdn/{src-DBel9wRZ.js → src-pYGV2rMR.js} +10033 -9504
  95. package/dist/cdn/svgrid.js +15 -11
  96. package/dist/cdn/svgrid.svelte-external.js +15 -11
  97. package/dist/cell-values.d.ts +16 -0
  98. package/dist/cell-values.js +28 -0
  99. package/dist/chart-export.js +8 -8
  100. package/dist/clipboard.d.ts +22 -0
  101. package/dist/clipboard.js +405 -27
  102. package/dist/column-groups.js +1 -1
  103. package/dist/column-resize.d.ts +46 -0
  104. package/dist/column-resize.js +205 -0
  105. package/dist/columns.d.ts +0 -3
  106. package/dist/columns.js +0 -57
  107. package/dist/core.d.ts +19 -4
  108. package/dist/core.js +460 -119
  109. package/dist/editing.js +12 -7
  110. package/dist/editors/cell-editors.d.ts +11 -0
  111. package/dist/editors/cell-editors.js +18 -1
  112. package/dist/filtering/excel-filters.js +28 -0
  113. package/dist/grid-messages.d.ts +15 -0
  114. package/dist/grid-messages.js +15 -0
  115. package/dist/group-display.d.ts +1 -1
  116. package/dist/index.d.ts +6 -1
  117. package/dist/index.js +10 -0
  118. package/dist/list-option.d.ts +6 -0
  119. package/dist/menus.js +41 -8
  120. package/dist/row-resize.d.ts +11 -0
  121. package/dist/row-resize.js +7 -1
  122. package/dist/sanitize-html.d.ts +37 -0
  123. package/dist/sanitize-html.js +234 -0
  124. package/dist/selection-bar-view.svelte.d.ts +25 -0
  125. package/dist/selection-bar-view.svelte.js +13 -0
  126. package/dist/selection.d.ts +2 -1
  127. package/dist/selection.js +133 -8
  128. package/dist/spreadsheet.d.ts +1 -1
  129. package/dist/spreadsheet.js +1 -1
  130. package/package.json +11 -11
  131. package/src/FlexRender.svelte +96 -96
  132. package/src/GridFooter.svelte +181 -181
  133. package/src/GridMenus.svelte +201 -18
  134. package/src/SvAutoComplete.svelte +169 -165
  135. package/src/SvAvatar.svelte +75 -75
  136. package/src/SvCalendar.svelte +503 -503
  137. package/src/SvCalendar.test.ts +226 -226
  138. package/src/SvCarousel.svelte +141 -141
  139. package/src/SvCheckBox.svelte +102 -102
  140. package/src/SvCircularProgress.svelte +109 -109
  141. package/src/SvColorInput.svelte +181 -181
  142. package/src/SvComboBox.svelte +279 -275
  143. package/src/SvContextMenu.svelte +116 -116
  144. package/src/SvCountryInput.svelte +163 -163
  145. package/src/SvDateRangeInput.svelte +25 -3
  146. package/src/SvDrawer.svelte +254 -254
  147. package/src/SvDropDownList.svelte +378 -374
  148. package/src/SvDurationInput.svelte +126 -126
  149. package/src/SvField.svelte +293 -293
  150. package/src/SvForm.svelte +437 -437
  151. package/src/SvForm.test.ts +411 -411
  152. package/src/SvGrid.controller.svelte.ts +404 -133
  153. package/src/SvGrid.css +222 -1
  154. package/src/SvGrid.helpers.ts +87 -0
  155. package/src/SvGrid.svelte +255 -56
  156. package/src/SvGrid.types.ts +2092 -1940
  157. package/src/SvGridCellEditor.svelte +744 -662
  158. package/src/SvGridChart.svelte +1716 -1716
  159. package/src/SvGridChartPanel.svelte +485 -485
  160. package/src/SvGridChartView.svelte +70 -70
  161. package/src/SvGridDropdown.svelte +728 -728
  162. package/src/SvGridSelect.svelte +270 -266
  163. package/src/SvGroupCell.svelte +116 -116
  164. package/src/SvListBox.svelte +334 -326
  165. package/src/SvMaskedInput.svelte +122 -122
  166. package/src/SvMenu.svelte +124 -124
  167. package/src/SvMenu.test.ts +97 -97
  168. package/src/SvMenuList.svelte +146 -146
  169. package/src/SvMultiSelect.svelte +293 -289
  170. package/src/SvNumberInput.svelte +172 -168
  171. package/src/SvOtpInput.svelte +158 -158
  172. package/src/SvPasswordInput.svelte +151 -151
  173. package/src/SvPhoneInput.svelte +133 -133
  174. package/src/SvPopover.svelte +197 -197
  175. package/src/SvProgress.svelte +116 -116
  176. package/src/SvRadioGroup.svelte +107 -107
  177. package/src/SvRating.svelte +112 -112
  178. package/src/SvResult.svelte +73 -73
  179. package/src/SvRichCell.svelte +125 -0
  180. package/src/SvRichText.svelte +211 -211
  181. package/src/SvRowGroupPanel.svelte +170 -170
  182. package/src/SvScrollArea.svelte +61 -61
  183. package/src/SvSlider.svelte +203 -203
  184. package/src/SvSwitchButton.svelte +108 -108
  185. package/src/SvTagsInput.svelte +115 -115
  186. package/src/SvTextArea.svelte +5 -1
  187. package/src/SvTextInput.svelte +147 -147
  188. package/src/SvTimePicker.svelte +245 -245
  189. package/src/SvToaster.svelte +159 -159
  190. package/src/SvToaster.test.ts +95 -95
  191. package/src/SvToggleButton.svelte +85 -85
  192. package/src/SvTooltip.svelte +161 -161
  193. package/src/SvTour.svelte +208 -208
  194. package/src/SvTree.svelte +444 -444
  195. package/src/SvTreeSelect.svelte +239 -235
  196. package/src/a11y/dismissable.test.ts +119 -119
  197. package/src/a11y/dismissable.ts +114 -114
  198. package/src/a11y.contract.test.ts +49 -49
  199. package/src/a11y.test.ts +59 -59
  200. package/src/a11y.ts +61 -61
  201. package/src/ai.test.ts +502 -502
  202. package/src/ai.ts +1419 -1419
  203. package/src/build-api.coverage.test.ts +633 -633
  204. package/src/build-api.ts +846 -846
  205. package/src/builtin-editors.grid.test.ts +83 -83
  206. package/src/builtin-editors.test.ts +18 -1
  207. package/src/builtin-editors.ts +19 -3
  208. package/src/cell-formatting.ts +171 -171
  209. package/src/cell-render.test.ts +513 -513
  210. package/src/cell-render.ts +496 -496
  211. package/src/cell-values.ts +148 -118
  212. package/src/chart-export.ts +202 -202
  213. package/src/chart-view.svelte.ts +36 -36
  214. package/src/chart.ts +2321 -2321
  215. package/src/clipboard.test.ts +93 -20
  216. package/src/clipboard.ts +433 -33
  217. package/src/collaboration.test.ts +104 -104
  218. package/src/collaboration.ts +167 -167
  219. package/src/column-groups.ts +78 -78
  220. package/src/column-resize.test.ts +381 -0
  221. package/src/column-resize.ts +227 -0
  222. package/src/columns.test.ts +0 -103
  223. package/src/columns.ts +0 -58
  224. package/src/core.aggregate.test.ts +134 -0
  225. package/src/core.filter.test.ts +156 -0
  226. package/src/core.grouping.test.ts +146 -0
  227. package/src/core.performance.test.ts +30 -30
  228. package/src/core.row-shape.test.ts +119 -0
  229. package/src/core.rowmodel-cache.test.ts +121 -0
  230. package/src/core.sort.test.ts +293 -0
  231. package/src/core.ts +1865 -1468
  232. package/src/createAutocomplete.svelte.ts +132 -132
  233. package/src/createCombobox.svelte.ts +191 -191
  234. package/src/createCountryInput.svelte.ts +157 -157
  235. package/src/createDropdownList.svelte.ts +168 -168
  236. package/src/createForm.svelte.ts +386 -386
  237. package/src/createGrid.svelte.ts +42 -42
  238. package/src/createGrid.test.ts +10 -10
  239. package/src/createGridState.svelte.ts +17 -17
  240. package/src/createListbox.svelte.ts +250 -250
  241. package/src/createMenu.svelte.ts +224 -224
  242. package/src/createPopoverSelect.svelte.ts +213 -213
  243. package/src/createSlider.svelte.ts +191 -191
  244. package/src/createTooltip.svelte.ts +144 -144
  245. package/src/createTree.svelte.ts +322 -322
  246. package/src/date-string-column.test.ts +87 -0
  247. package/src/datetime/date-core.ts +206 -206
  248. package/src/datetime/date-restrict.ts +61 -61
  249. package/src/datetime/timezone.ts +135 -135
  250. package/src/dock-manager-model.ts +596 -596
  251. package/src/dock-model.ts +374 -374
  252. package/src/editing.test.ts +974 -949
  253. package/src/editing.ts +609 -606
  254. package/src/editor-block-prop.test.ts +132 -0
  255. package/src/editor-contract.ts +171 -171
  256. package/src/editor-registry.grid.test.ts +144 -144
  257. package/src/editor-registry.ts +122 -122
  258. package/src/editors/cell-editors.ts +27 -1
  259. package/src/export-data-api.test.ts +126 -126
  260. package/src/export-format.test.ts +107 -107
  261. package/src/export-format.ts +601 -601
  262. package/src/filter-operators.ts +160 -160
  263. package/src/filtering/excel-filters.ts +325 -295
  264. package/src/filtering/normalize-fast-path.test.ts +104 -0
  265. package/src/flex-render.ts +3 -3
  266. package/src/form-field.ts +127 -127
  267. package/src/grid-messages.ts +34 -0
  268. package/src/group-display.test.ts +167 -167
  269. package/src/group-display.ts +200 -200
  270. package/src/headless.ts +87 -87
  271. package/src/index.ts +25 -1
  272. package/src/js-scroller.svelte.ts +173 -173
  273. package/src/keyboard-handlers.ts +270 -270
  274. package/src/keyboard.test.ts +59 -59
  275. package/src/keyboard.ts +97 -97
  276. package/src/list-nav.test.ts +49 -49
  277. package/src/list-nav.ts +29 -29
  278. package/src/list-option.test.ts +56 -56
  279. package/src/list-option.ts +179 -173
  280. package/src/menus.test.ts +43 -0
  281. package/src/menus.ts +597 -567
  282. package/src/merge-objects.ts +48 -48
  283. package/src/move-cells.test.ts +850 -0
  284. package/src/number-editor-literal.test.ts +84 -0
  285. package/src/number-editor.grid.test.ts +160 -0
  286. package/src/overlays.test.ts +90 -90
  287. package/src/positioning.ts +268 -268
  288. package/src/render-component.ts +28 -28
  289. package/src/resize-props.test.ts +361 -0
  290. package/src/row-drag-touch.ts +211 -211
  291. package/src/row-drag.test.ts +353 -353
  292. package/src/row-drag.ts +415 -415
  293. package/src/row-resize.test.ts +524 -493
  294. package/src/row-resize.ts +228 -210
  295. package/src/sanitize-html.test.ts +182 -0
  296. package/src/sanitize-html.ts +235 -0
  297. package/src/scheduler-ical.ts +181 -181
  298. package/src/scheduler-model.test.ts +562 -562
  299. package/src/scheduler-model.ts +873 -873
  300. package/src/selection-bar-view.svelte.ts +36 -0
  301. package/src/selection.test.ts +900 -743
  302. package/src/selection.ts +135 -8
  303. package/src/server-data-source.test.ts +383 -383
  304. package/src/server-data-source.ts +469 -469
  305. package/src/sparkline.test.ts +68 -68
  306. package/src/sparkline.ts +169 -169
  307. package/src/spreadsheet.test.ts +488 -488
  308. package/src/spreadsheet.ts +312 -312
  309. package/src/static-functions.ts +11 -11
  310. package/src/subscribe.ts +38 -38
  311. package/src/summaries.ts +113 -113
  312. package/src/svgrid-wrapper.types.ts +563 -563
  313. package/src/svgrid.async-editor-options.test.ts +273 -273
  314. package/src/svgrid.auto-row-height.test.ts +204 -204
  315. package/src/svgrid.behavior.test.ts +910 -910
  316. package/src/svgrid.charting.test.ts +534 -534
  317. package/src/svgrid.comments-autocomplete.test.ts +127 -127
  318. package/src/svgrid.context-menu.test.ts +147 -147
  319. package/src/svgrid.features.test.ts +157 -157
  320. package/src/svgrid.filter-depth.test.ts +163 -163
  321. package/src/svgrid.filter-menu-listbox.svelte.test.ts +377 -331
  322. package/src/svgrid.filter-menu-scroll.test.ts +112 -112
  323. package/src/svgrid.grand-total.test.ts +188 -188
  324. package/src/svgrid.group-display-mode.test.ts +171 -171
  325. package/src/svgrid.group-footers.test.ts +121 -121
  326. package/src/svgrid.group-pagination.test.ts +153 -153
  327. package/src/svgrid.in-suggest-snapshot.svelte.test.ts +91 -0
  328. package/src/svgrid.menu-scroll-close.test.ts +204 -0
  329. package/src/svgrid.new-features.wrapper.test.ts +251 -251
  330. package/src/svgrid.selection-bar-seam.test.ts +185 -0
  331. package/src/svgrid.tree-data.test.ts +186 -186
  332. package/src/svgrid.upsell-license.test.ts +117 -0
  333. package/src/svgrid.wrapper.test.ts +63 -63
  334. package/src/svgriddropdown.async-panel.svelte.test.ts +195 -195
  335. package/src/test-setup.ts +62 -62
  336. package/src/themes/index.ts +288 -288
  337. package/src/toast-store.svelte.ts +250 -250
  338. package/src/toast-store.test.ts +147 -147
  339. package/src/tree-row-model.test.ts +168 -168
  340. package/src/ui-buttons.test.ts +144 -144
  341. package/src/ui-inputs.test.ts +118 -118
  342. package/src/ui-localization.test.ts +113 -113
  343. package/src/ui-range.test.ts +70 -70
  344. package/src/ui-selection.test.ts +155 -155
  345. package/src/ui-tier1.test.ts +142 -142
  346. package/src/virtual.test.ts +88 -88
  347. package/src/virtualization/column-virtualizer.test.ts +27 -27
  348. package/src/virtualization/column-virtualizer.ts +30 -30
  349. package/src/virtualization/svelte-virtualizer.svelte.ts +26 -26
  350. package/src/virtualization/types.ts +30 -30
  351. package/src/virtualization/virtualizer.test.ts +47 -47
  352. package/src/virtualization/virtualizer.ts +322 -322
  353. package/dist/cdn/GridMenus-BfTAKn84.js +0 -488
  354. package/dist/cdn/GridMenus-C3bJd7w8.js +0 -489
  355. package/dist/cdn/SvDateTimePicker-CHnUkWcH.js +0 -2206
  356. package/dist/cdn/SvDateTimePicker-CRQH_U7E.js +0 -2201
  357. package/dist/cdn/SvGridCellEditor-BGUCzuPB.js +0 -523
  358. package/dist/cdn/SvGridCellEditor-G8IMWIws.js +0 -522
package/src/SvGrid.svelte CHANGED
@@ -15,6 +15,8 @@
15
15
  } from "./index";
16
16
  import "./sv-grid-scrollbar";
17
17
  import "./SvGrid.css";
18
+ import type { RowResizeOptions } from "./row-resize";
19
+ import type { ColumnResizeOptions } from "./column-resize";
18
20
  import {
19
21
  RenderSnippetConfig,
20
22
  RenderComponentConfig,
@@ -31,6 +33,9 @@
31
33
  import {
32
34
  cfTextStyle,
33
35
  getEditorInputType,
36
+ usesRichDateFilter,
37
+ toIsoDateLocal,
38
+ fromIsoDateLocal,
34
39
  getOptionLabel,
35
40
  getOptionColor,
36
41
  colorfulChipStyle,
@@ -46,6 +51,7 @@
46
51
  // SvGridChartPanel (charting) and SvGridBoard (Kanban) are heavy, prop-gated
47
52
  // views - lazy-loaded below so they stay out of the base <SvGrid> bundle.
48
53
  import { getSchedulerView } from "./scheduler-view.svelte";
54
+ import { getSelectionBarView } from "./selection-bar-view.svelte";
49
55
  import { getBoardView } from "./board-view.svelte";
50
56
  import { getChartView } from "./chart-view.svelte";
51
57
  let props: Props<TFeatures, TData> = $props();
@@ -97,6 +103,37 @@
97
103
  import("./SvGridChartView.svelte").then((m) => (ChartView = m.default));
98
104
  });
99
105
  let MenusOverlay = $state<typeof import("./GridMenus.svelte").default | null>(null);
106
+ // The grid's own date picker, for date FILTER inputs. Lazy for the same
107
+ // reason the cell editor's copy is: most grids never show a filter row, and
108
+ // most that do have no date column.
109
+ let FilterDatePicker = $state<typeof import("./SvDateTimePicker.svelte").default | null>(null);
110
+ $effect(() => {
111
+ if (!showFilterRowEffective && !ctrl.filterMenuFor) return;
112
+ if (FilterDatePicker) return;
113
+ const wantsPicker = ctrl.allColumns.some((c: any) =>
114
+ usesRichDateFilter(c.columnDef?.editorType),
115
+ );
116
+ if (wantsPicker)
117
+ import("./SvDateTimePicker.svelte").then((m) => (FilterDatePicker = m.default));
118
+ });
119
+ // `between` on a date column filters with a RANGE control rather than two
120
+ // single-date fields: one field, one popover, both ends picked in a single
121
+ // gesture - and it fits a narrow date column, which two pickers plus their
122
+ // buttons do not. Loaded only once a date column is actually set to Between,
123
+ // so a grid that never uses the operator never pays for the chunk.
124
+ let FilterRangePicker = $state<typeof import("./SvDateRangeInput.svelte").default | null>(null);
125
+ $effect(() => {
126
+ if (!showFilterRowEffective) return;
127
+ if (FilterRangePicker) return;
128
+ const wantsRange = ctrl.allColumns.some(
129
+ (c: any) =>
130
+ usesRichDateFilter(c.columnDef?.editorType) &&
131
+ (ctrl.filterMenuValues[c.id]?.operator ??
132
+ ctrl.defaultOperatorFor(c)) === "between",
133
+ );
134
+ if (wantsRange)
135
+ import("./SvDateRangeInput.svelte").then((m) => (FilterRangePicker = m.default));
136
+ });
100
137
  $effect(() => {
101
138
  if (ctrl.chartingEnabled && ctrl.chartPanelOpen && !ChartPanelView)
102
139
  import("./SvGridChartPanel.svelte").then((m) => (ChartPanelView = m.default));
@@ -167,7 +204,9 @@
167
204
  const hideTooltip = $derived(ctrl.hideTooltip);
168
205
  const findHits = $derived(ctrl.findHits);
169
206
  const headerHeight = $derived(ctrl.headerHeight);
170
- const resizingColumnId = $derived(ctrl.resizingColumnId);
207
+ // Column resizing has always been unconditional; `columnResize={false}` is
208
+ // the opt-out, so the default has to stay on when the prop is absent.
209
+ const columnResizeEnabled = $derived(opt.columnResize === true);
171
210
  const selectionColumnWidth = $derived(ctrl.selectionColumnWidth);
172
211
  const rowNumberColumnWidth = $derived(ctrl.rowNumberColumnWidth);
173
212
  const showRowNumbersEffective = $derived(ctrl.showRowNumbersEffective);
@@ -264,6 +303,23 @@
264
303
  // Row-grouping display modes: group state lives in synthetic columns instead
265
304
  // of a full-width banner row.
266
305
  const groupColumnMode = $derived(ctrl.groupColumnMode);
306
+ /**
307
+ * True when a cell's content needs none of the wrapper snippets.
308
+ *
309
+ * A cell body normally renders through `cellBodyWithFormat` ->
310
+ * `cellBodyFormatted` -> `cellBody`, and with no grouping, no tree data and
311
+ * no conditional formats the first two are pure pass-throughs: three snippet
312
+ * renders and two `{#if}` blocks per cell to reach content that one render
313
+ * produces. Measured by ablation, that chain is 4.2 ms of a 17.4 ms mount at
314
+ * 28 rows x 9 columns - about a quarter of the whole mount, and the largest
315
+ * single per-cell cost.
316
+ *
317
+ * Computed once per render rather than per cell, so the fast path costs one
318
+ * boolean read at each of the ~250 cells instead of two snippet frames.
319
+ */
320
+ const plainCellBody = $derived(
321
+ !groupColumnMode && !treeData && !hasConditionalFormats,
322
+ );
267
323
  const autoGroupCell = $derived(ctrl.autoGroupCell);
268
324
  const isAutoGroupColumn = (id: string): boolean =>
269
325
  id === "__autoGroup" || id.startsWith("__group_");
@@ -280,7 +336,60 @@
280
336
  // The fixed row height, matching what the virtualized path takes from the virtualizer.
281
337
  // The non-virtualized (`virtualization={false}`) body must apply this too, else its rows
282
338
  // fall back to content height and look shorter than a virtualized grid's.
339
+ /**
340
+ * `rowResize` and `columnResize` are both opt-in and both default to OFF, so
341
+ * neither module is imported statically - a grid that leaves them alone must
342
+ * not carry their bytes. This wraps an action so its module is fetched on
343
+ * first enable and never otherwise. The handles appear a microtask after the
344
+ * first paint, which is invisible for a drag affordance.
345
+ *
346
+ * One helper for both: two hand-rolled copies of this bookkeeping would cost
347
+ * more base bundle than the deferral saves.
348
+ */
349
+ type LazyHandle<O> = { update(o: O): void; destroy(): void };
350
+ function lazyAction<O extends { disabled?: boolean }>(
351
+ load: () => Promise<(node: HTMLElement, opts: O) => LazyHandle<O>>,
352
+ ) {
353
+ return (node: HTMLElement, opts: O): LazyHandle<O> => {
354
+ let handle: LazyHandle<O> | null = null;
355
+ let current = opts;
356
+ let destroyed = false;
357
+ const ensure = () => {
358
+ if (handle || destroyed || current.disabled) return;
359
+ void load().then((make) => {
360
+ // The prop can be switched back off, or the grid unmounted, while
361
+ // the chunk is still in flight.
362
+ if (destroyed || current.disabled || handle) return;
363
+ handle = make(node, current);
364
+ });
365
+ };
366
+ ensure();
367
+ return {
368
+ update(next: O) {
369
+ current = next;
370
+ if (handle) handle.update(next);
371
+ else ensure();
372
+ },
373
+ destroy() {
374
+ destroyed = true;
375
+ handle?.destroy();
376
+ },
377
+ };
378
+ };
379
+ }
380
+
381
+ const lazyRowResize = lazyAction<RowResizeOptions>(() =>
382
+ import("./row-resize").then((m) => m.rowResize),
383
+ );
384
+ const lazyColumnResize = lazyAction<ColumnResizeOptions>(() =>
385
+ import("./column-resize").then((m) => m.columnResize),
386
+ );
387
+
283
388
  const rowSizePx = (i: number): number => {
389
+ // A height the user dragged wins over the declared one, so the row stays
390
+ // where they put it across re-renders and virtualization recycling.
391
+ const dragged = ctrl.rowResizeHeightPx(i);
392
+ if (dragged != null) return dragged;
284
393
  const rh = opt.rowHeight;
285
394
  return typeof rh === "function" ? rh(i) : (rh ?? 30);
286
395
  };
@@ -358,26 +467,10 @@
358
467
  return "sv-grid-cell-flash";
359
468
  }
360
469
 
361
- // Keyboard-accessible column resize (#79): focus a resize handle and use the
362
- // arrow keys (Shift = fine 1px step). Complements the pointer-drag resize.
363
- function resizeColumnByKeyboard(e: KeyboardEvent, columnId: string) {
364
- let delta = 0;
365
- const step = e.shiftKey ? 1 : 10;
366
- if (e.key === "ArrowLeft") delta = -step;
367
- else if (e.key === "ArrowRight") delta = step;
368
- else return;
369
- e.preventDefault();
370
- const current = ctrl.getColumnWidth(columnId);
371
- ctrl.columnWidths = {
372
- ...ctrl.columnWidths,
373
- [columnId]: Math.max(40, current + delta),
374
- };
375
- }
376
-
377
470
  // ---- Full-row editing -------------------------------------------------
378
471
  const fullRowEdit = $derived(ctrl.fullRowEdit);
379
472
  // Commit the whole row when the user clicks away from its editors (Excel /
380
- // AG-Grid feel). Clicking within any full-row editor keeps editing.
473
+ // spreadsheet feel). Clicking within any full-row editor keeps editing.
381
474
  // Stays here rather than in SvGridCellEditor: that component is instantiated
382
475
  // once PER editable cell during a full-row edit, so a document listener there
383
476
  // would be attached N times and commit N times.
@@ -429,7 +522,6 @@
429
522
  const setActiveCell = $derived(ctrl.setActiveCell);
430
523
  const scrollActiveCellIntoView = $derived(ctrl.scrollActiveCellIntoView);
431
524
  const getColumnWidth = $derived(ctrl.getColumnWidth);
432
- const startColumnResize = $derived(ctrl.startColumnResize);
433
525
  const getCellRangeEdges = $derived(ctrl.getCellRangeEdges);
434
526
  const fillHandleCell = $derived(ctrl.fillHandleCell);
435
527
  const isInFillPreview = $derived(ctrl.isInFillPreview);
@@ -624,6 +716,24 @@
624
716
  onpointermove={onWindowPointerMove}
625
717
  />
626
718
 
719
+ <!--
720
+ The licensing line every Enterprise upsell note carries. One snippet rather
721
+ than four copies: four gates worded four ways is how a product ends up
722
+ explaining its own licensing inconsistently.
723
+
724
+ Enterprise is SOFT-gated - the feature runs without a key and the grid shows
725
+ an unlicensed watermark - so this says exactly that rather than implying the
726
+ feature is inert without one.
727
+ -->
728
+ {#snippet enterpriseLicenseNote()}
729
+ <p class="sv-grid-upsell-license">
730
+ {messages.upsellLicense}
731
+ <a href="https://svgrid.com/pricing/" target="_blank" rel="noopener noreferrer">
732
+ {messages.upsellLicenseLink}
733
+ </a>
734
+ </p>
735
+ {/snippet}
736
+
627
737
  {#if opt.loading && !opt.loadingOverlay && !hasMeasured}
628
738
  <!-- Full-screen loading state only on the *initial* load, before the grid
629
739
  has ever rendered. Once measured, a `loading` flip (from a server-mode
@@ -680,6 +790,7 @@
680
790
  <code>@svgrid/enterprise</code> and call <code>enableBoardView()</code>
681
791
  to render it.
682
792
  </p>
793
+ {@render enterpriseLicenseNote()}
683
794
  </div>
684
795
  {/if}
685
796
  </div>
@@ -727,6 +838,7 @@
727
838
  <code>@svgrid/enterprise</code> and call <code>enableSchedulerView()</code>
728
839
  to render it.
729
840
  </p>
841
+ {@render enterpriseLicenseNote()}
730
842
  </div>
731
843
  {/if}
732
844
  </div>
@@ -809,6 +921,7 @@
809
921
  <div class="sv-grid-scheduler-upsell sv-grid-pivot-upsell" role="note">
810
922
  <strong>{messages.pivotUpsellTitle}</strong>
811
923
  <p>{messages.pivotUpsellBody}</p>
924
+ {@render enterpriseLicenseNote()}
812
925
  </div>
813
926
  {/if}
814
927
  </div>
@@ -866,6 +979,13 @@
866
979
  <path d="M8 5l9 7-9 7" />
867
980
  {:else if name === "op-lessThan"}
868
981
  <path d="M16 5l-9 7 9 7" />
982
+ {:else if name === "op-between"}
983
+ <!-- Two bounds with the span between them. The catalogue has always
984
+ named this icon; the snippet had no case for it, so the Between
985
+ row in the operator menu drew an empty <svg>. -->
986
+ <path d="M5 5v14" />
987
+ <path d="M19 5v14" />
988
+ <path d="M9 12h6" />
869
989
  {:else if name === "op-isBlank"}
870
990
  <circle cx="12" cy="12" r="8" />
871
991
  <path d="M6.5 6.5l11 11" />
@@ -1294,6 +1414,32 @@
1294
1414
  class="sv-grid-root"
1295
1415
  class:sv-grid-root-fill={opt.containerHeight === "100%"}
1296
1416
  style={chartDockReserveStyle}
1417
+ data-move-grab={ctrl.moveGrabHover || ctrl.moveDrag ? "true" : undefined}
1418
+ data-selbar={
1419
+ ctrl.selectionBarOn && ctrl.selectionBarTarget.ids.length > 0
1420
+ ? (getSelectionBarView() ? ctrl.selectionBarPosition : `upsell-${ctrl.selectionBarPosition}`)
1421
+ : undefined
1422
+ }
1423
+ use:lazyRowResize={{
1424
+ disabled: !ctrl.rowResizeOn,
1425
+ // No gutter column on most grids, so fall back to the first body cell -
1426
+ // otherwise `rowResize` would be a prop that silently does nothing.
1427
+ anchor: "row",
1428
+ onResize: (index, height) => ctrl.setRowResizeHeight(index, height),
1429
+ }}
1430
+ use:lazyColumnResize={{
1431
+ disabled: !columnResizeEnabled,
1432
+ getWidth: (columnId) => ctrl.getColumnWidth(columnId),
1433
+ onResize: (columnId, width) => {
1434
+ ctrl.columnWidths = { ...ctrl.columnWidths, [columnId]: width };
1435
+ },
1436
+ label: (columnId) => {
1437
+ const col = ctrl.findColumnById(columnId);
1438
+ return col ? toolPanelHeaderLabel(col) : columnId;
1439
+ },
1440
+ canResize: (columnId) => ctrl.columnResizable(columnId),
1441
+ onAutosize: (columnId) => ctrl.autosizeColumn(columnId),
1442
+ }}
1297
1443
  >
1298
1444
  {#if showGlobalFilterEffective}
1299
1445
  <label class="sv-grid-global-filter">
@@ -1747,32 +1893,6 @@
1747
1893
  }}
1748
1894
  />
1749
1895
  {/if}
1750
- <div
1751
- class="sv-grid-resize-handle"
1752
- class:is-resizing={resizingColumnId ===
1753
- header.column.id}
1754
- role="separator"
1755
- aria-orientation="vertical"
1756
- aria-label={`Resize ${toolPanelHeaderLabel(header.column)}`}
1757
- tabindex="0"
1758
- {...(() => {
1759
- // A focusable separator is a widget, so ARIA requires
1760
- // aria-valuenow. The value it exposes is the column
1761
- // width the arrow keys change; 40 is the floor
1762
- // enforced in resizeColumnByKeyboard.
1763
- const w = Math.round(ctrl.getColumnWidth(header.column.id));
1764
- return {
1765
- "aria-valuenow": w,
1766
- "aria-valuemin": 40,
1767
- "aria-valuetext": `${w} pixels`,
1768
- };
1769
- })()}
1770
- onpointerdown={(event) =>
1771
- startColumnResize(event, header.column.id)}
1772
- onkeydown={(event) =>
1773
- resizeColumnByKeyboard(event, header.column.id)}
1774
- ondblclick={(event) => event.stopPropagation()}
1775
- ></div>
1776
1896
  {/if}
1777
1897
  </th>
1778
1898
  {/if}
@@ -1900,6 +2020,57 @@
1900
2020
  }}
1901
2021
  />
1902
2022
  </div>
2023
+ {:else if activeOperator !== "isBlank" && activeOperator !== "isNotBlank" && activeOperator !== "regex" && FilterDatePicker && usesRichDateFilter(rendered.column.columnDef.editorType)}
2024
+ <!-- Same picker the cell editor uses, so a date
2025
+ column looks the same wherever you touch it.
2026
+ `regex` keeps the text box - a pattern is not
2027
+ a date. -->
2028
+ {#if activeOperator === "between"}
2029
+ <!-- `between` needs BOTH bounds - `condActive`
2030
+ ignores the filter until `valueTo` is set too -
2031
+ so this is one range field rather than two
2032
+ single-date pickers: both ends come from a
2033
+ single gesture in one popover, and it still
2034
+ fits a narrow date column. It writes the same
2035
+ pair of stores the plain text inputs use. -->
2036
+ {#if FilterRangePicker}
2037
+ {@const RangePicker = FilterRangePicker}
2038
+ {@const from = fromIsoDateLocal(
2039
+ filterRowValues[rendered.column.id],
2040
+ )}
2041
+ {@const to = fromIsoDateLocal(
2042
+ filterMenuValues[rendered.column.id]?.valueTo,
2043
+ )}
2044
+ <RangePicker
2045
+ value={from && to ? [from, to] : null}
2046
+ formatString="yyyy-MM-dd"
2047
+ block
2048
+ placeholder="Range…"
2049
+ onChange={(range) => {
2050
+ updateFilterRow(
2051
+ rendered.column.id,
2052
+ range ? toIsoDateLocal(range[0]) : "",
2053
+ );
2054
+ updateFilterMenuValueTo(
2055
+ rendered.column.id,
2056
+ range ? toIsoDateLocal(range[1]) : "",
2057
+ );
2058
+ }}
2059
+ />
2060
+ {/if}
2061
+ {:else}
2062
+ {@const FilterPicker = FilterDatePicker}
2063
+ <FilterPicker
2064
+ value={(filterRowValues[rendered.column.id] ?? "") || null}
2065
+ formatString="yyyy-MM-dd"
2066
+ dropDownDisplayMode="calendar"
2067
+ block
2068
+ nullable
2069
+ placeholder="Filter…"
2070
+ onChange={(d) =>
2071
+ updateFilterRow(rendered.column.id, toIsoDateLocal(d))}
2072
+ />
2073
+ {/if}
1903
2074
  {:else if activeOperator !== "isBlank" && activeOperator !== "isNotBlank"}
1904
2075
  {@const frType = getEditorInputType(
1905
2076
  rendered.column.columnDef.editorType ?? "text",
@@ -2177,12 +2348,11 @@
2177
2348
  rendered.column.columnDef.cellFlash,
2178
2349
  ),
2179
2350
  }}
2180
- {...getGridCellA11yProps({
2181
- id: getGridCellDomId(ctrl.gridDomId, rowIndex, colIndex),
2182
- rowIndex: rowIndex + 1,
2183
- colIndex: colIndex + 1,
2184
- selected: isRowSelected(row.id),
2185
- })}
2351
+ role="gridcell"
2352
+ id={getGridCellDomId(ctrl.gridDomId, rowIndex, colIndex)}
2353
+ aria-colindex={colIndex + 1}
2354
+ aria-rowindex={rowIndex + 1}
2355
+ aria-selected={isRowSelected(row.id)}
2186
2356
  >
2187
2357
  {#if inRowEdit || isEditing}
2188
2358
  <!-- The editing cell stays empty until the lazy
@@ -2194,11 +2364,15 @@
2194
2364
  <CellEditor {ctrl} column={rendered.column} {row} fullRow={inRowEdit} />
2195
2365
  {/if}
2196
2366
  {:else}
2197
- {@render cellBodyWithFormat(
2198
- row,
2199
- rendered.column,
2200
- cellValue,
2201
- )}
2367
+ {#if plainCellBody}
2368
+ {@render cellBody(row, rendered.column, cellValue)}
2369
+ {:else}
2370
+ {@render cellBodyWithFormat(
2371
+ row,
2372
+ rendered.column,
2373
+ cellValue,
2374
+ )}
2375
+ {/if}
2202
2376
  {/if}
2203
2377
  {#if !isEditing && fillHandleCell && fillHandleCell.rowIndex === rowIndex && fillHandleCell.colIndex === colIndex}
2204
2378
  <!-- Excel-style fill handle: drag down/right to
@@ -2948,6 +3122,31 @@
2948
3122
  {#if ctrl.chartingEnabled && ctrl.chartPanelOpen && ChartPanelView}
2949
3123
  <ChartPanelView {ctrl} />
2950
3124
  {/if}
3125
+
3126
+ <!-- Bulk-action bar. INSIDE the root, unlike GridMenus: it is positioned
3127
+ `absolute` against it, so moving it outside would anchor it to the
3128
+ page. The renderer is Enterprise and arrives through the
3129
+ selection-bar-view seam; without it, a short note in its place. -->
3130
+ {#if ctrl.selectionBarOn && ctrl.selectionBarTarget.ids.length > 0}
3131
+ {#if getSelectionBarView()}
3132
+ {@const SelectionBarView = getSelectionBarView()}
3133
+ <SelectionBarView {ctrl} />
3134
+ {:else}
3135
+ <div
3136
+ class="sv-grid-scheduler-upsell sv-grid-selection-bar-upsell"
3137
+ data-position={ctrl.selectionBarPosition}
3138
+ role="note"
3139
+ >
3140
+ <strong>Bulk-action bar</strong>
3141
+ <p>
3142
+ The selection bar is an Enterprise feature. Install
3143
+ <code>@svgrid/enterprise</code> and call <code>enableSelectionBar()</code>
3144
+ to render it.
3145
+ </p>
3146
+ {@render enterpriseLicenseNote()}
3147
+ </div>
3148
+ {/if}
3149
+ {/if}
2951
3150
  </div>
2952
3151
  <!-- /.sv-grid-root -->
2953
3152