@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
@@ -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
 
@@ -191,6 +191,74 @@ export type ContextMenuItem<TData extends RowData = RowData> = string | {
191
191
  /** Invoked on click. The menu closes afterwards. */
192
192
  action: (target: ContextMenuTarget<TData>) => void;
193
193
  };
194
+ /** What a {@link SelectionBarAction} is handed when it runs. */
195
+ export type SelectionBarTarget<TData extends RowData = RowData> = {
196
+ /** The selected rows, in the grid's current display order. */
197
+ rows: TData[];
198
+ /** Their row ids, same order as `rows`. */
199
+ ids: string[];
200
+ };
201
+ /**
202
+ * One button on the selection bar. Same shape as {@link ContextMenuItem}'s
203
+ * object form - key, label, optional hidden/disabled predicates, and an action -
204
+ * except everything here is handed the whole SELECTION rather than one cell.
205
+ */
206
+ export type SelectionBarAction<TData extends RowData = RowData> = {
207
+ key: string;
208
+ label: string;
209
+ /**
210
+ * Inline SVG path data (the `d` of a single 24x24 path) drawn to the left of
211
+ * the label. A string rather than a component so an action array stays plain
212
+ * data that can live in a `.ts` module next to the columns.
213
+ */
214
+ icon?: string;
215
+ /** Render in the destructive style (red). Does not add a confirmation. */
216
+ danger?: boolean;
217
+ /** Hide the button entirely for this selection. */
218
+ hidden?: (target: SelectionBarTarget<TData>) => boolean;
219
+ /** Render greyed-out and non-clickable for this selection. */
220
+ disabled?: (target: SelectionBarTarget<TData>) => boolean;
221
+ /** Invoked on click. The bar stays open; clear the selection yourself if the
222
+ * action should dismiss it. */
223
+ action: (target: SelectionBarTarget<TData>) => void;
224
+ };
225
+ /**
226
+ * A built-in bar button, named by key - the same convention
227
+ * {@link ContextMenuItem} uses for its string form.
228
+ *
229
+ * - `'selectAll'` selects every row in the current view.
230
+ * - `'editFields'` opens the bulk-edit dialog: pick a field, set one value,
231
+ * apply it to every selected row in a single undo step.
232
+ * - `'separator'` draws a divider.
233
+ */
234
+ export type SelectionBarBuiltin = "selectAll" | "editFields" | "separator";
235
+ /**
236
+ * Full form of the {@link SvGridProps.selectionBar} prop, for when the array
237
+ * shorthand is not enough.
238
+ */
239
+ export type SelectionBarConfig<TData extends RowData = RowData> = {
240
+ /**
241
+ * The buttons, left to right. Strings are {@link SelectionBarBuiltin} keys,
242
+ * objects are your own actions - so a Jira-shaped bar is
243
+ * `['selectAll', 'editFields', 'separator', myAction]`.
244
+ */
245
+ actions?: ReadonlyArray<SelectionBarAction<TData> | SelectionBarBuiltin>;
246
+ /**
247
+ * Which edge of the grid the bar floats against. Default `'bottom'`, where
248
+ * the eye is already going after ticking a checkbox and where it covers the
249
+ * rows a user is least likely to be reading.
250
+ */
251
+ position?: "bottom" | "top";
252
+ /**
253
+ * How many actions stay on the bar before the rest collapse into an overflow
254
+ * menu. Default 6, which fits a full issue-tracker set (select all, edit,
255
+ * status, watch, delete) without collapsing. A bar wide enough to need
256
+ * horizontal scrolling is a bar whose last button nobody finds.
257
+ */
258
+ maxVisible?: number;
259
+ /** Hide the trailing clear (x) button. Default false. */
260
+ hideClear?: boolean;
261
+ };
194
262
  /** A single Kanban lane (board column). {@link BoardConfig}. */
195
263
  export type BoardLane = {
196
264
  /** Lane id - equals the `groupBy` field value of the cards it holds. */
@@ -967,6 +1035,26 @@ export type Props<TFeatures extends TableFeatures = TableFeatures, TData extends
967
1035
  * browser menu shows instead).
968
1036
  */
969
1037
  contextMenu?: boolean | ReadonlyArray<ContextMenuItem<TData>>;
1038
+ /**
1039
+ * Floating bar that appears over the grid while rows are selected, showing
1040
+ * the count and the actions that apply to the whole selection - the pattern
1041
+ * an issue tracker uses for bulk edit.
1042
+ *
1043
+ * `true` gives the count and a Clear button. An array is the shorthand for
1044
+ * `{ actions }`. Pass {@link SelectionBarConfig} to also set `position`
1045
+ * (`'bottom'` default, or `'top'`), `maxVisible` and `hideClear`. Omitted /
1046
+ * `false` is off.
1047
+ *
1048
+ * Default **off**. This is chrome that floats over your content, not a
1049
+ * gesture: it overlaps a row, and what belongs on it is specific to the app.
1050
+ *
1051
+ * **The prop and its types are free; the bar itself is an Enterprise
1052
+ * feature.** Install `@svgrid/enterprise` and call `enableSelectionBar()`
1053
+ * (or `installEnterprise`, which does it for you) to render it - without
1054
+ * that the grid shows a short upsell note in its place, the same way the
1055
+ * scheduler and board views do.
1056
+ */
1057
+ selectionBar?: boolean | ReadonlyArray<SelectionBarAction<TData> | SelectionBarBuiltin> | SelectionBarConfig<TData>;
970
1058
  /**
971
1059
  * The feature set built with `tableFeatures({ ... })`. Optional - the
972
1060
  * `sortable` / `filterable` / `groupable` shortcuts below inject the
@@ -1296,6 +1384,28 @@ export type Props<TFeatures extends TableFeatures = TableFeatures, TData extends
1296
1384
  * supplying per-row heights).
1297
1385
  */
1298
1386
  autoRowHeight?: boolean;
1387
+ /**
1388
+ * Let the user drag a row's bottom edge to change its height. **Off by
1389
+ * default**, because a resizable row needs somewhere to grab and most grids
1390
+ * do not want a drag target on every row.
1391
+ *
1392
+ * The grid remembers the heights itself, so this works as a bare boolean -
1393
+ * no `rowHeight` function required. Drag, or focus the grip and use Up/Down
1394
+ * (Shift for 1px steps).
1395
+ *
1396
+ * Turning this on also turns on the **row header column** ({@link
1397
+ * showRowNumbers}), because that is where the grip lives and where a
1398
+ * spreadsheet puts it - a drag target on the edge of a data cell works but
1399
+ * reads as an accident. An explicit `showRowNumbers={false}` still wins; the
1400
+ * grip then falls back to the row's first cell, and a column of your own
1401
+ * carrying `cellClass: 'sv-row-gutter'` is used ahead of either.
1402
+ *
1403
+ * Ignored under `autoRowHeight`, where the content decides the height and a
1404
+ * manual one would immediately be overwritten. For full control of the
1405
+ * heights - persisting them, sharing them between grids - pass a
1406
+ * function-valued {@link rowHeight} and use the `rowResize` action directly.
1407
+ */
1408
+ rowResize?: boolean;
1299
1409
  /**
1300
1410
  * Height (px) of a single column-header level row. With multi-level
1301
1411
  * (grouped) headers the total header height is `levels * headerHeight`,
@@ -1354,6 +1464,24 @@ export type Props<TFeatures extends TableFeatures = TableFeatures, TData extends
1354
1464
  * win once they happen.
1355
1465
  */
1356
1466
  fitColumns?: boolean;
1467
+ /**
1468
+ * Let the user drag a column's edge to change its width. **Off by default**,
1469
+ * so `width` means the width you asked for until you say otherwise.
1470
+ *
1471
+ * Turn it on for grids the reader is meant to arrange - a spreadsheet, a
1472
+ * dense report, anything with columns whose content varies in length. Leave
1473
+ * it off for layouts you control, and for columns that must keep their size:
1474
+ * a row-number gutter, a checkbox column, an icon column.
1475
+ *
1476
+ * It is grid-wide rather than per-column: there is no `resizable: false` on a
1477
+ * single column definition. `api.autosizeColumn()`, `fitColumns` and
1478
+ * programmatic width changes work either way - this only governs the drag
1479
+ * handle.
1480
+ *
1481
+ * The handles come from the `columnResize` action, loaded on demand: a grid
1482
+ * that leaves this off never fetches that code.
1483
+ */
1484
+ columnResize?: boolean;
1357
1485
  /**
1358
1486
  * Make the grid usable on narrow screens. When the grid's own width drops
1359
1487
  * below the breakpoint (default `640`px), pinned columns are un-pinned so the
@@ -1384,6 +1512,23 @@ export type Props<TFeatures extends TableFeatures = TableFeatures, TData extends
1384
1512
  * is the shortcut alias and wins over it.
1385
1513
  */
1386
1514
  enableCellSelection?: boolean;
1515
+ /**
1516
+ * Excel-style drag-and-drop of a selected cell range: grab the range's
1517
+ * border and drag it somewhere else to MOVE the values there, or hold
1518
+ * Ctrl (Cmd on macOS) to COPY them instead. The modifier is read at drop
1519
+ * time, so it can be pressed or released mid-drag.
1520
+ *
1521
+ * On by default whenever cell selection is on, matching the fill handle.
1522
+ * Set `false` to keep a border pointerdown starting a fresh selection, which
1523
+ * is what it did before this existed.
1524
+ *
1525
+ * The grab strip is the outer 4px of the range border, so a pointerdown
1526
+ * anywhere further inside still starts a new selection. A drop is refused
1527
+ * outright - nothing changes - when the destination would fall outside the
1528
+ * grid, or when any source or destination cell is read-only. It does not
1529
+ * move the part that fits and silently drop the rest.
1530
+ */
1531
+ moveCells?: boolean;
1387
1532
  /**
1388
1533
  * Highlight the row under the pointer. Default **false** - the hover tint can
1389
1534
  * compete with the cell selection / fill marquee. Set `true` to opt in; when
@@ -1463,7 +1608,7 @@ export type Props<TFeatures extends TableFeatures = TableFeatures, TData extends
1463
1608
  charting?: boolean | ChartingConfig<TData>;
1464
1609
  /**
1465
1610
  * Render the header column menu (⋮) as a tabbed popover - **General**,
1466
- * **Filter**, and **Columns** tabs (the AG-Grid layout). Defaults to `false`,
1611
+ * **Filter**, and **Columns** tabs (the tabbed layout). Defaults to `false`,
1467
1612
  * which keeps the flat menu (actions list + "Choose columns" submenu).
1468
1613
  */
1469
1614
  columnMenuTabs?: boolean;