@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/dist/editing.js CHANGED
@@ -5,7 +5,7 @@ import { parseEditorValue, } from "./index.js";
5
5
  import "./sv-grid-scrollbar.js";
6
6
  import { getNextActiveCell } from "./keyboard.js";
7
7
  import { getCellKey, toValueArray, } from "./SvGrid.helpers.js";
8
- import { getColumnBaseValue, isGroupRow, } from "./cell-values.js";
8
+ import { createDataIndexLookup, getColumnBaseValue, isGroupRow, } from "./cell-values.js";
9
9
  export function createEditing(ctx) {
10
10
  /**
11
11
  * Resolve `columnDef.editable` for one row × column pair.
@@ -117,6 +117,8 @@ export function createEditing(ctx) {
117
117
  const column = ctx.allColumns.find((entry) => entry.id === ctx.editingCell?.columnId);
118
118
  const parsedValue = parseEditorValue(ctx.editingCell.editorType, ctx.editingCell.value, {
119
119
  multiple: column?.columnDef.editorMultiple === true,
120
+ // A dateString column holds 'YYYY-MM-DD', not a timestamp.
121
+ dateOnly: column?.columnDef.cellDataType === "dateString",
120
122
  });
121
123
  let oldValue = undefined;
122
124
  let finalValue = parsedValue;
@@ -378,16 +380,16 @@ export function createEditing(ctx) {
378
380
  ? endCol - startCol + 1
379
381
  : Math.max(...lines.map((l) => l.split("\t").length));
380
382
  const next = ctx.internalData.slice();
383
+ const dataIndexOf = createDataIndexLookup(next);
381
384
  for (let i = 0; i < rowSpan; i += 1) {
382
385
  const targetRowIndex = startRow + i;
383
386
  const row = ctx.allRows[targetRowIndex];
384
387
  if (!row || isGroupRow(row))
385
388
  continue;
386
- // Map the visible row back to its index in the data array via row.id (default = String(index)).
387
- const dataIndex = Number(row.id);
388
- if (!Number.isInteger(dataIndex) ||
389
- dataIndex < 0 ||
390
- dataIndex >= next.length)
389
+ // Map the visible row back to its slot in the data array by identity -
390
+ // `row.id` is only the index under the default getRowId.
391
+ const dataIndex = dataIndexOf(row);
392
+ if (dataIndex < 0)
391
393
  continue;
392
394
  const originalRow = next[dataIndex];
393
395
  if (!originalRow)
@@ -407,7 +409,9 @@ export function createEditing(ctx) {
407
409
  const editorType = (column.columnDef.editorType ??
408
410
  "text");
409
411
  const raw = fillRange ? lines[0] : sourceCells?.[j] ?? "";
410
- updated[column.columnDef.field] = parseEditorValue(editorType, raw);
412
+ updated[column.columnDef.field] = parseEditorValue(editorType, raw, {
413
+ dateOnly: column.columnDef.cellDataType === "dateString",
414
+ });
411
415
  }
412
416
  next[dataIndex] = updated;
413
417
  }
@@ -496,6 +500,7 @@ export function createEditing(ctx) {
496
500
  const editorType = (column.columnDef.editorType ?? "text");
497
501
  const parsed = parseEditorValue(editorType, fr.draft[column.id], {
498
502
  multiple: column.columnDef.editorMultiple === true,
503
+ dateOnly: column.columnDef.cellDataType === "dateString",
499
504
  });
500
505
  const oldValue = row.original[field];
501
506
  const parser = column.columnDef.valueParser;
@@ -12,6 +12,17 @@ export type CellEditorOption = {
12
12
  export type ParseEditorValueOptions = {
13
13
  /** When true, list/chips return an array; otherwise a scalar. */
14
14
  multiple?: boolean;
15
+ /**
16
+ * Keep a date as the plain `YYYY-MM-DD` string the user picked, instead of a
17
+ * full ISO timestamp. Set for `cellDataType: 'dateString'` columns, which
18
+ * exist precisely to hold ISO date strings.
19
+ *
20
+ * It is not only about shape. `new Date('2026-12-25').toISOString()` sends
21
+ * the value through UTC, so a local midnight becomes the previous or next
22
+ * day either side of the meridian - the stored DATE changes depending on
23
+ * where the user is sitting. Slicing the picked date avoids that entirely.
24
+ */
25
+ dateOnly?: boolean;
15
26
  };
16
27
  /** Normalize the loose `editorOptions` ColumnDef prop into a uniform shape.
17
28
  * Dynamic (function) editorOptions are resolved before reaching here. */
@@ -36,7 +36,24 @@ export function parseEditorValue(rawType, value, opts) {
36
36
  return s || '#000000';
37
37
  }
38
38
  if (type === 'date') {
39
- const date = new Date(String(value));
39
+ const raw = String(value ?? '');
40
+ if (opts?.dateOnly) {
41
+ // Take the calendar date the editor produced as-is. It already arrives
42
+ // as `YYYY-MM-DD` (or that prefix on a datetime), so there is nothing to
43
+ // convert - and converting is exactly what shifts the day across a
44
+ // timezone boundary.
45
+ const match = /^(\d{4}-\d{2}-\d{2})/.exec(raw.trim());
46
+ if (match)
47
+ return match[1];
48
+ const parsed = new Date(raw);
49
+ if (Number.isNaN(parsed.getTime()))
50
+ return null;
51
+ // A non-ISO input (a locale string) still has to become a date string.
52
+ // Use the LOCAL parts, so the day is the one the user saw.
53
+ const pad = (n) => String(n).padStart(2, '0');
54
+ return `${parsed.getFullYear()}-${pad(parsed.getMonth() + 1)}-${pad(parsed.getDate())}`;
55
+ }
56
+ const date = new Date(raw);
40
57
  return Number.isNaN(date.getTime()) ? null : date.toISOString();
41
58
  }
42
59
  if (type === 'datetime') {
@@ -8,11 +8,39 @@ const DIACRITIC_RE = /[̀-ͯ]/g;
8
8
  export function normalizeForFilter(s, locale) {
9
9
  if (!s)
10
10
  return '';
11
+ // Fast path for pure-ASCII input, which is the overwhelming majority of what
12
+ // a grid filters. Both of the expensive steps are provably no-ops there:
13
+ // ASCII is already NFD-normalised, and the combining-marks block this strips
14
+ // (U+0300..U+036F) contains no ASCII. So lowercasing alone is the same
15
+ // answer, and `normalize-fast-path.test.ts` checks that exhaustively over
16
+ // every ASCII code point rather than taking the argument on trust.
17
+ //
18
+ // Worth the branch: this runs once per cell per filter - 100,000 times for a
19
+ // one-column filter over a 100k grid - and a CPU profile of a browser filter
20
+ // put more time in this function than in any other.
21
+ //
22
+ // Note the locale still routes through toLocaleLowerCase even on the fast
23
+ // path: 'I'.toLocaleLowerCase('tr') is 'ı', so ASCII does NOT imply the
24
+ // locale can be ignored.
25
+ if (isAsciiOnly(s)) {
26
+ return locale ? s.toLocaleLowerCase(locale) : s.toLowerCase();
27
+ }
11
28
  const stripped = s.normalize('NFD').replace(DIACRITIC_RE, '');
12
29
  return locale
13
30
  ? stripped.toLocaleLowerCase(locale)
14
31
  : stripped.toLowerCase();
15
32
  }
33
+ /**
34
+ * True when every code unit is ASCII. A plain char-code scan, which is far
35
+ * cheaper than the `normalize()` + regex pass it lets us skip.
36
+ */
37
+ function isAsciiOnly(s) {
38
+ for (let i = 0; i < s.length; i++) {
39
+ if (s.charCodeAt(i) > 127)
40
+ return false;
41
+ }
42
+ return true;
43
+ }
16
44
  /**
17
45
  * Delimiter used to serialise the `in` / `notIn` value list into the single
18
46
  * `value` string that the filter model carries.
@@ -54,9 +54,24 @@ export type GridMessages = {
54
54
  menuRemoveRow: string;
55
55
  menuRemoveColumn: string;
56
56
  menuEditComment: string;
57
+ selectionBarLabel: string;
58
+ selectionBarCount: string;
59
+ selectionBarClear: string;
60
+ selectionBarMore: string;
61
+ selectionBarSelectAll: string;
62
+ selectionBarEditFields: string;
63
+ bulkEditTitle: string;
64
+ bulkEditLead: string;
65
+ bulkEditMixed: string;
66
+ bulkEditApply: string;
67
+ bulkEditCancel: string;
68
+ bulkEditNoFields: string;
57
69
  chartRange: string;
58
70
  pivotUpsellTitle: string;
59
71
  pivotUpsellBody: string;
72
+ /** Shared licensing line under every Enterprise upsell note. */
73
+ upsellLicense: string;
74
+ upsellLicenseLink: string;
60
75
  };
61
76
  /** English defaults - the literal strings the grid shipped before localization. */
62
77
  export declare const defaultGridMessages: GridMessages;
@@ -49,6 +49,19 @@ export const defaultGridMessages = {
49
49
  menuRemoveRow: 'Remove row',
50
50
  menuRemoveColumn: 'Remove column',
51
51
  menuEditComment: 'Edit comment',
52
+ selectionBarLabel: 'Selection actions',
53
+ /** Label beside the count CHIP, which carries the number itself. */
54
+ selectionBarCount: 'selected',
55
+ selectionBarClear: 'Clear selection',
56
+ selectionBarMore: 'More actions',
57
+ selectionBarSelectAll: 'Select all',
58
+ selectionBarEditFields: 'Edit fields',
59
+ bulkEditTitle: 'Edit fields',
60
+ bulkEditLead: 'Changes apply to all {count} selected items. Fields you leave alone keep their existing values.',
61
+ bulkEditMixed: 'Multiple values',
62
+ bulkEditApply: 'Apply to {count} items',
63
+ bulkEditCancel: 'Cancel',
64
+ bulkEditNoFields: 'No editable fields on this grid.',
52
65
  opContains: 'Contains',
53
66
  opNotContains: 'Not contains',
54
67
  opEquals: 'Equals',
@@ -68,6 +81,8 @@ export const defaultGridMessages = {
68
81
  chartRange: 'Chart selected range',
69
82
  pivotUpsellTitle: 'Pivot mode',
70
83
  pivotUpsellBody: 'Pivot mode is an Enterprise feature. Install @svgrid/enterprise and call enablePivot() to use it.',
84
+ upsellLicense: 'A license key is required for production use. Without one the feature still works, but the grid renders an unlicensed watermark.',
85
+ upsellLicenseLink: 'View licensing',
71
86
  };
72
87
  /**
73
88
  * Merge a consumer's `localeText` over the English defaults. Undefined/empty
@@ -13,7 +13,7 @@
13
13
  * Both are generic over the row / column shape (via small accessor callbacks) so
14
14
  * they are trivially unit-testable and carry no dependency on the grid runtime.
15
15
  */
16
- /** AG-Grid-style grouping display variants. */
16
+ /** Grouping display variants. */
17
17
  export type GroupDisplayType = 'groupRows' | 'singleColumn' | 'multipleColumns';
18
18
  export type GroupFooterOptions<R> = {
19
19
  /** Depth of a row (group rows and their descendants). */
package/dist/index.d.ts CHANGED
@@ -7,10 +7,12 @@ export { subscribeGrid, subscribeSvGrid } from './subscribe.js';
7
7
  export { default as SvGrid } from './SvGrid.svelte';
8
8
  export type { BoardConfig, BoardLane, BoardCardMoveEvent, BoardCardCommitEvent, BoardLayout, BoardSubtask, BoardComment, BoardMenuContext, BoardLaneMenuContext, BoardDrawerConfig } from './SvGrid.types.js';
9
9
  export { registerBoardView, getBoardView, hasBoardView } from './board-view.svelte.js';
10
+ export type { SelectionBarAction, SelectionBarTarget, ContextMenuItem, ContextMenuTarget, } from './SvGrid.types.js';
10
11
  export * from './ai.js';
11
12
  export { registerExportProvider, getExportProvider, type GridExportProvider, type GridExportRunOptions, } from './export-provider.js';
12
13
  export type { SchedulerConfig, SchedulerDrawerConfig, SchedulerEventMoveEvent, SchedulerEventResizeEvent, SchedulerEventCommitEvent, SchedulerRangeSelection, SchedulerView, SchedulerResource, SchedulerCollisionMode, SchedulerException, SchedulerEditScope, SchedulerOccurrenceChangeEvent, } from './SvGrid.types.js';
13
14
  export { registerSchedulerView, getSchedulerView, hasSchedulerView } from './scheduler-view.svelte.js';
15
+ export { registerSelectionBarView, getSelectionBarView, hasSelectionBarView } from './selection-bar-view.svelte.js';
14
16
  export type { ChartViewConfig } from './SvGrid.types.js';
15
17
  export { registerChartView, getChartView, hasChartView } from './chart-view.svelte.js';
16
18
  export { registerPivotEngine, getPivotEngine, hasPivotEngine, type PivotEngine, type GridPivotConfig, type GridPivotValue, type GridPivotRow, } from './pivot-view.svelte.js';
@@ -55,6 +57,7 @@ export { default as SvVisuallyHidden } from './SvVisuallyHidden.svelte';
55
57
  export { default as SvAspectRatio } from './SvAspectRatio.svelte';
56
58
  export { registerCellEditor, getCellEditor, hasCellEditor, unregisterCellEditor, registeredCellEditorTypes, defaultEditorProps, resolveEditorProps, type CellEditorContext, type CellEditorRegistration, } from './editor-registry.js';
57
59
  export { registerBuiltinEditors } from './builtin-editors.js';
60
+ export { sanitizeHtml, renderMarkdown, htmlToText } from './sanitize-html.js';
58
61
  export { default as SvField } from './SvField.svelte';
59
62
  export { createListbox, toSelectedArray, toSelectedSet, type Listbox, type ListboxConfig, type ListboxValue, type ListboxRootProps, type OptionProps, } from './createListbox.svelte.js';
60
63
  export { createCombobox, type Combobox, type ComboboxConfig, type ComboboxValue } from './createCombobox.svelte.js';
@@ -152,6 +155,7 @@ export { default as SvAvatarGroup } from './SvAvatarGroup.svelte';
152
155
  export { default as SvCommand, type CommandItem } from './SvCommand.svelte';
153
156
  export { fuzzyScore, fuzzyMatch } from './fuzzy.js';
154
157
  export { default as SvRichText, type RichTextTool } from './SvRichText.svelte';
158
+ export { default as SvRichCell } from './SvRichCell.svelte';
155
159
  export { default as SvCarousel } from './SvCarousel.svelte';
156
160
  export { default as SvTour, type TourStep } from './SvTour.svelte';
157
161
  export { default as SvPagination } from './SvPagination.svelte';
@@ -194,6 +198,7 @@ export { chartToSvgString, downloadChartSvg, chartToPngBlob, downloadChartPng, c
194
198
  export { buildSparkline, toSparklineValues, type SparklineConfig, type SparklineType, type SparklineGeometry, } from './sparkline.js';
195
199
  export { spreadsheetLayout, spansToMerges, type SpanColumn, type SpreadsheetActionOptions, type MergeSpec, type CellBorderSpec, type BorderSpec, } from './spreadsheet.js';
196
200
  export { rowResize, type RowResizeOptions } from './row-resize.js';
201
+ export { columnResize, type ColumnResizeOptions } from './column-resize.js';
197
202
  export { rowDropZone, type RowDragEndEvent, type RowDropZoneOptions } from './row-drag.js';
198
203
  export { resolveColumnTypes, inferCellDataType, type CellDataType } from './column-types.js';
199
204
  export { computeColumnGroupMeta, hiddenLeavesForCollapse, type ColumnGroupMeta, type ColumnGroupShow, } from './column-groups.js';
@@ -212,7 +217,7 @@ export { createVirtualizer } from './virtualization/virtualizer.js';
212
217
  export { createSvelteVirtualizer } from './virtualization/svelte-virtualizer.svelte.js';
213
218
  export { createColumnVirtualizer } from './virtualization/column-virtualizer.js';
214
219
  export type { VirtualItem, VirtualizerOptions, VirtualizerState } from './virtualization/types.js';
215
- export type { SvGridApi, SvGridFilterOperator, SvGridWrapperProps } from './svgrid-wrapper.types.js';
220
+ export type { SvGridApi, SvGridFilterOperator, SvGridViewState, SvGridWrapperProps, } from './svgrid-wrapper.types.js';
216
221
  export { parseEditorValue, normalizeEditorOptions, type CellEditorType, type CellEditorOption, } from './editors/cell-editors.js';
217
222
  export { applyExcelFilter, compileExcelFilter, normalizeForFilter, splitInTokens, joinInTokens, trailingInToken, type CompiledExcelFilter, type ExcelFilter, type ExcelFilterOperator, type ExcelFilterOptions, } from './filtering/excel-filters.js';
218
223
  export { ALL_FILTER_OPERATORS, SET_OPERATOR_IDS, VALUELESS_OPERATOR_IDS, RANGE_OPERATOR_IDS, isSetOperator, isValuelessOperator, isRangeOperator, type FilterValueType, } from './filtering/filter-operator-catalogue.js';
package/dist/index.js CHANGED
@@ -15,6 +15,8 @@ export { registerBoardView, getBoardView, hasBoardView } from './board-view.svel
15
15
  export * from './ai.js';
16
16
  export { registerExportProvider, getExportProvider, } from './export-provider.js';
17
17
  export { registerSchedulerView, getSchedulerView, hasSchedulerView } from './scheduler-view.svelte.js';
18
+ // Bulk-action bar over the row selection. Prop + types free, renderer Pro.
19
+ export { registerSelectionBarView, getSelectionBarView, hasSelectionBarView } from './selection-bar-view.svelte.js';
18
20
  export { registerChartView, getChartView, hasChartView } from './chart-view.svelte.js';
19
21
  export { registerPivotEngine, getPivotEngine, hasPivotEngine, } from './pivot-view.svelte.js';
20
22
  // Pure scheduler layout/model helpers (framework-free, like recurrence/date-core).
@@ -73,6 +75,7 @@ export { default as SvAspectRatio } from './SvAspectRatio.svelte';
73
75
  // UI kit - custom cell-editor registry (register any component as a grid editor)
74
76
  export { registerCellEditor, getCellEditor, hasCellEditor, unregisterCellEditor, registeredCellEditorTypes, defaultEditorProps, resolveEditorProps, } from './editor-registry.js';
75
77
  export { registerBuiltinEditors } from './builtin-editors.js';
78
+ export { sanitizeHtml, renderMarkdown, htmlToText } from './sanitize-html.js';
76
79
  // UI kit - shared field chrome (label + hint + error + direction wrapper)
77
80
  export { default as SvField } from './SvField.svelte';
78
81
  // UI kit - headless cores (state + prop-getters you render yourself, like createSvGrid)
@@ -187,6 +190,7 @@ export { default as SvAvatarGroup } from './SvAvatarGroup.svelte';
187
190
  export { default as SvCommand } from './SvCommand.svelte';
188
191
  export { fuzzyScore, fuzzyMatch } from './fuzzy.js';
189
192
  export { default as SvRichText } from './SvRichText.svelte';
193
+ export { default as SvRichCell } from './SvRichCell.svelte';
190
194
  export { default as SvCarousel } from './SvCarousel.svelte';
191
195
  export { default as SvTour } from './SvTour.svelte';
192
196
  export { default as SvPagination } from './SvPagination.svelte';
@@ -230,7 +234,13 @@ export { buildChart, formatChartValue, rowsToChartSpec, niceScale, niceLogScale,
230
234
  export { chartToSvgString, downloadChartSvg, chartToPngBlob, downloadChartPng, chartSpecToCsv, downloadChartCsv, } from './chart-export.js';
231
235
  export { buildSparkline, toSparklineValues, } from './sparkline.js';
232
236
  export { spreadsheetLayout, spansToMerges, } from './spreadsheet.js';
237
+ // The two resize actions, exported as a matched pair. `<SvGrid>` drives both
238
+ // through the `rowResize` / `columnResize` props - both default OFF, both are
239
+ // turned on by setting them true, and the grid `import()`s the module itself so
240
+ // a grid that leaves them off carries neither. Import them directly only for a
241
+ // headless table, which renders its own rows and headers.
233
242
  export { rowResize } from './row-resize.js';
243
+ export { columnResize } from './column-resize.js';
234
244
  export { rowDropZone } from './row-drag.js';
235
245
  export { resolveColumnTypes, inferCellDataType } from './column-types.js';
236
246
  export { computeColumnGroupMeta, hiddenLeavesForCollapse, } from './column-groups.js';
@@ -7,6 +7,12 @@ export type ListOption = {
7
7
  group?: string;
8
8
  /** Optional color swatch (any CSS color) shown before the label. */
9
9
  color?: string;
10
+ /**
11
+ * Optional muted text pinned to the trailing edge of the row - a count, a
12
+ * shortcut, a unit. Not part of the label, so it does not affect matching
13
+ * or the accessible name.
14
+ */
15
+ hint?: string;
10
16
  };
11
17
  /**
12
18
  * Coerce a raw options array into well-formed ListOptions. A primitive item
package/dist/menus.js CHANGED
@@ -118,7 +118,7 @@ export function createMenus(ctx) {
118
118
  function openChooseColumns(event) {
119
119
  event.stopPropagation();
120
120
  // Submenu behavior: keep the parent operations menu open and float the
121
- // Choose Columns panel out to the right of it (AG-Grid style). Falls
121
+ // Choose Columns panel out to the right of it, submenu-style. Falls
122
122
  // back to below the item if the popover would clip the viewport.
123
123
  const trigger = event.currentTarget;
124
124
  const menuEl = trigger.closest(".sv-grid-menu");
@@ -249,19 +249,52 @@ export function createMenus(ctx) {
249
249
  }
250
250
  ctx.valueFilters = { ...ctx.valueFilters, [columnId]: new Set(next) };
251
251
  }
252
+ /**
253
+ * With a search query typed, "select all" means the RESULTS - the same thing
254
+ * it means in a spreadsheet. It used to mean the whole column regardless, so
255
+ * the standard flow (type a query, tick select-all, get just the matches)
256
+ * cleared the entire selection instead: `isAllFacetsChecked` saw every value
257
+ * ticked, read that as "on", and turned everything off.
258
+ */
252
259
  function isAllFacetsChecked(columnId) {
253
260
  const selected = ctx.valueFilters[columnId];
254
- return !selected || selected.size >= ctx.columnMenuFacetValues.length;
261
+ const visible = ctx.columnMenuVisibleFacets;
262
+ const searching = visible.length !== ctx.columnMenuFacetValues.length;
263
+ if (!selected)
264
+ return true;
265
+ if (searching)
266
+ return visible.every((value) => selected.has(value));
267
+ return selected.size >= ctx.columnMenuFacetValues.length;
255
268
  }
256
269
  function toggleAllFacets(columnId) {
257
- if (isAllFacetsChecked(columnId)) {
258
- ctx.valueFilters = { ...ctx.valueFilters, [columnId]: new Set() };
270
+ const visible = ctx.columnMenuVisibleFacets;
271
+ const all = ctx.columnMenuFacetValues;
272
+ const searching = visible.length !== all.length;
273
+ const on = isAllFacetsChecked(columnId);
274
+ if (!searching) {
275
+ if (on) {
276
+ ctx.valueFilters = { ...ctx.valueFilters, [columnId]: new Set() };
277
+ }
278
+ else {
279
+ const copy = { ...ctx.valueFilters };
280
+ delete copy[columnId];
281
+ ctx.valueFilters = copy;
282
+ }
283
+ return;
259
284
  }
260
- else {
261
- const copy = { ...ctx.valueFilters };
262
- delete copy[columnId];
263
- ctx.valueFilters = copy;
285
+ // Searching: add or remove just the matches, leaving the rest of the
286
+ // selection alone. An absent entry means "everything", so it has to be
287
+ // materialized before a subtraction can mean anything.
288
+ const current = ctx.valueFilters[columnId]
289
+ ? new Set(ctx.valueFilters[columnId])
290
+ : new Set(all);
291
+ for (const value of visible) {
292
+ if (on)
293
+ current.delete(value);
294
+ else
295
+ current.add(value);
264
296
  }
297
+ ctx.valueFilters = { ...ctx.valueFilters, [columnId]: current };
265
298
  }
266
299
  function clearColumnFilter(columnId) {
267
300
  // `untrack`: read-modify-write on the filter maps. Keeps the method safe to
@@ -36,6 +36,17 @@ export type RowResizeOptions = {
36
36
  max?: number;
37
37
  /** When true, the action removes its strips and ignores events. */
38
38
  disabled?: boolean;
39
+ /**
40
+ * Where the drag strip is anchored.
41
+ * - `'gutter'` (default) - only rows that have a row-header gutter cell get
42
+ * a strip: the built-in row-number column (`showRowNumbers`) or a column
43
+ * tagged `cellClass: 'sv-row-gutter'`. Rows without one are skipped, so on
44
+ * a plain grid the action does nothing.
45
+ * - `'row'` - use the gutter when there is one, otherwise fall back to the
46
+ * row's first body cell. This is what `<SvGrid rowResize>` passes, so the
47
+ * prop works without also asking for a gutter column.
48
+ */
49
+ anchor?: 'gutter' | 'row';
39
50
  };
40
51
  export declare function rowResize(node: HTMLElement, opts: RowResizeOptions): {
41
52
  update(next: RowResizeOptions): void;
@@ -141,7 +141,13 @@ export function rowResize(node, opts) {
141
141
  // A row-header gutter cell: either a user column tagged
142
142
  // `sv-row-gutter`, or the grid's built-in row-number gutter
143
143
  // (`showRowNumbers`), whose cell is `.sv-grid-row-number-cell`.
144
- const gutter = tr.querySelector('.sv-grid-cell.sv-row-gutter, .sv-grid-cell.sv-grid-row-number-cell');
144
+ const gutter = tr.querySelector('.sv-grid-cell.sv-row-gutter, .sv-grid-cell.sv-grid-row-number-cell') ??
145
+ // `anchor: 'row'` - no gutter on this grid, so hang the strip off the
146
+ // first body cell instead. Without this a grid with no row-number
147
+ // column would silently not resize.
148
+ (current.anchor === 'row'
149
+ ? tr.querySelector('.sv-grid-cell')
150
+ : null);
145
151
  if (!gutter)
146
152
  continue;
147
153
  if (gutter.querySelector(`:scope > .${STRIP_CLASS}`))
@@ -0,0 +1,37 @@
1
+ /**
2
+ * sanitize-html - a dependency-free HTML sanitizer and a small Markdown
3
+ * renderer, sized for what a grid cell needs to display.
4
+ *
5
+ * A rich-text cell has to paint markup that came from a user, which is the one
6
+ * place a data grid can hand an attacker script execution. Everything rendered
7
+ * through `SvRichCell` goes through `sanitizeHtml` first, and the allowlist is
8
+ * deliberately narrower than a general-purpose sanitizer: it covers the tags
9
+ * `SvRichText` can produce, plus links and images.
10
+ *
11
+ * The parse uses the platform parser where there is one (`DOMParser`, which
12
+ * neither executes scripts nor runs loaders on a detached document) and a
13
+ * conservative regex stripper during SSR, where there is no DOM. The SSR path
14
+ * is stricter by design: when in doubt it drops markup rather than passing it
15
+ * through, and the hydrated client re-sanitizes with the real parser anyway.
16
+ *
17
+ * This is not a general-purpose sanitizer for arbitrary third-party HTML. It is
18
+ * a narrow allowlist for cell content. To render something outside the
19
+ * allowlist, extend it explicitly rather than widening the defaults.
20
+ */
21
+ /**
22
+ * Return `html` with everything outside the allowlist removed. Idempotent, so
23
+ * it is safe to call on already-sanitized markup.
24
+ */
25
+ export declare function sanitizeHtml(html: string | null | undefined): string;
26
+ /**
27
+ * Render a common Markdown subset to HTML: headings, bold, italic,
28
+ * strikethrough, inline code, links, images, and bullet / ordered lists.
29
+ *
30
+ * Deliberately not a full CommonMark implementation - a grid cell shows a line
31
+ * or two, and a complete parser is a dependency this package does not take. The
32
+ * output is sanitized, so a Markdown link cannot smuggle `javascript:`.
33
+ */
34
+ export declare function renderMarkdown(markdown: string | null | undefined): string;
35
+ /** Strip markup down to readable text, for exports, aria labels and tooltips
36
+ * where a cell's HTML has to collapse to one plain string. */
37
+ export declare function htmlToText(html: string | null | undefined): string;