@svgrid/grid 2.2.16 → 2.2.17

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 (290) hide show
  1. package/README.md +1 -1
  2. package/dist/GridFooter.svelte +12 -11
  3. package/dist/SvAnchor.svelte +65 -0
  4. package/dist/SvAnchor.svelte.d.ts +24 -0
  5. package/dist/SvAspectRatio.svelte +38 -0
  6. package/dist/SvAspectRatio.svelte.d.ts +16 -0
  7. package/dist/SvAutoComplete.svelte +52 -7
  8. package/dist/SvAutoComplete.svelte.d.ts +4 -1
  9. package/dist/SvBlockquote.svelte +43 -0
  10. package/dist/SvBlockquote.svelte.d.ts +16 -0
  11. package/dist/SvCalendar.svelte +33 -2
  12. package/dist/SvCalendar.svelte.d.ts +8 -1
  13. package/dist/SvCheckBox.svelte +6 -2
  14. package/dist/SvCode.svelte +52 -0
  15. package/dist/SvCode.svelte.d.ts +19 -0
  16. package/dist/SvCollapsible.svelte +75 -0
  17. package/dist/SvCollapsible.svelte.d.ts +27 -0
  18. package/dist/SvColorInput.svelte +11 -17
  19. package/dist/SvColorInput.svelte.d.ts +2 -0
  20. package/dist/SvComboBox.svelte +85 -8
  21. package/dist/SvComboBox.svelte.d.ts +14 -0
  22. package/dist/SvCountryInput.svelte +2 -2
  23. package/dist/SvCountryInput.svelte.d.ts +1 -1
  24. package/dist/SvDropDownList.svelte +154 -51
  25. package/dist/SvDropDownList.svelte.d.ts +17 -3
  26. package/dist/SvDurationInput.svelte +59 -41
  27. package/dist/SvDurationInput.svelte.d.ts +18 -0
  28. package/dist/SvField.svelte +203 -12
  29. package/dist/SvField.svelte.d.ts +45 -8
  30. package/dist/SvForm.svelte +195 -21
  31. package/dist/SvForm.svelte.d.ts +23 -0
  32. package/dist/SvGrid.controller.svelte.d.ts +12 -1
  33. package/dist/SvGrid.controller.svelte.js +87 -7
  34. package/dist/SvGrid.svelte +383 -181
  35. package/dist/SvGrid.types.d.ts +123 -2
  36. package/dist/SvGridChartView.svelte +70 -0
  37. package/dist/SvGridChartView.svelte.d.ts +11 -0
  38. package/dist/SvGridDropdown.svelte +9 -2
  39. package/dist/SvGridSelect.svelte +5 -2
  40. package/dist/SvGridSelect.svelte.d.ts +1 -1
  41. package/dist/SvGroup.svelte +41 -0
  42. package/dist/SvGroup.svelte.d.ts +27 -0
  43. package/dist/SvHoverCard.svelte +70 -0
  44. package/dist/SvHoverCard.svelte.d.ts +41 -0
  45. package/dist/SvKbd.svelte +51 -0
  46. package/dist/SvKbd.svelte.d.ts +18 -0
  47. package/dist/SvList.svelte +55 -0
  48. package/dist/SvList.svelte.d.ts +23 -0
  49. package/dist/SvListBox.svelte +166 -77
  50. package/dist/SvListBox.svelte.d.ts +17 -4
  51. package/dist/SvLoadingOverlay.svelte +53 -0
  52. package/dist/SvLoadingOverlay.svelte.d.ts +28 -0
  53. package/dist/SvMark.svelte +36 -0
  54. package/dist/SvMark.svelte.d.ts +14 -0
  55. package/dist/SvMaskedInput.svelte +50 -35
  56. package/dist/SvMaskedInput.svelte.d.ts +17 -2
  57. package/dist/SvMenuList.svelte +32 -3
  58. package/dist/SvMenubar.svelte +200 -0
  59. package/dist/SvMenubar.svelte.d.ts +18 -0
  60. package/dist/SvMultiSelect.svelte +7 -4
  61. package/dist/SvMultiSelect.svelte.d.ts +1 -1
  62. package/dist/SvNumberInput.svelte +79 -42
  63. package/dist/SvNumberInput.svelte.d.ts +25 -0
  64. package/dist/SvOtpInput.svelte +2 -2
  65. package/dist/SvPasswordInput.svelte +51 -31
  66. package/dist/SvPasswordInput.svelte.d.ts +17 -0
  67. package/dist/SvPhoneInput.svelte +39 -28
  68. package/dist/SvPhoneInput.svelte.d.ts +4 -0
  69. package/dist/SvPopconfirm.svelte +79 -0
  70. package/dist/SvPopconfirm.svelte.d.ts +42 -0
  71. package/dist/SvPopover.svelte +87 -29
  72. package/dist/SvPopover.svelte.d.ts +18 -4
  73. package/dist/SvRadioGroup.svelte +5 -1
  74. package/dist/SvResult.svelte +73 -0
  75. package/dist/SvResult.svelte.d.ts +28 -0
  76. package/dist/SvSegmented.svelte +114 -0
  77. package/dist/SvSegmented.svelte.d.ts +29 -0
  78. package/dist/SvSimpleGrid.svelte +41 -0
  79. package/dist/SvSimpleGrid.svelte.d.ts +25 -0
  80. package/dist/SvSlider.svelte +23 -10
  81. package/dist/SvSpinner.svelte +43 -0
  82. package/dist/SvSpinner.svelte.d.ts +20 -0
  83. package/dist/SvStack.svelte +37 -0
  84. package/dist/SvStack.svelte.d.ts +24 -0
  85. package/dist/SvSwitchButton.svelte +6 -1
  86. package/dist/SvTagsInput.svelte +9 -5
  87. package/dist/SvText.svelte +76 -0
  88. package/dist/SvText.svelte.d.ts +31 -0
  89. package/dist/SvTextInput.svelte +75 -43
  90. package/dist/SvTextInput.svelte.d.ts +28 -1
  91. package/dist/SvTimePicker.svelte +32 -2
  92. package/dist/SvTimePicker.svelte.d.ts +8 -9
  93. package/dist/SvTitle.svelte +57 -0
  94. package/dist/SvTitle.svelte.d.ts +24 -0
  95. package/dist/SvToaster.svelte +41 -6
  96. package/dist/SvToggleButton.svelte +4 -1
  97. package/dist/SvTooltip.svelte +68 -34
  98. package/dist/SvTooltip.svelte.d.ts +14 -2
  99. package/dist/SvTree.svelte +81 -21
  100. package/dist/SvTree.svelte.d.ts +3 -2
  101. package/dist/SvTreeSelect.svelte +5 -2
  102. package/dist/SvTreeSelect.svelte.d.ts +1 -1
  103. package/dist/SvVisuallyHidden.svelte +49 -0
  104. package/dist/SvVisuallyHidden.svelte.d.ts +19 -0
  105. package/dist/ai.d.ts +289 -0
  106. package/dist/ai.js +1013 -0
  107. package/dist/board-view.svelte.d.ts +22 -0
  108. package/dist/board-view.svelte.js +13 -0
  109. package/dist/build-api.js +36 -6
  110. package/dist/cdn/GridMenus-0AK9O7qG.js +420 -0
  111. package/dist/cdn/GridMenus-BjUoCXoD.js +416 -0
  112. package/dist/cdn/SvDateTimePicker-CYC7gRER.js +2176 -0
  113. package/dist/cdn/SvDateTimePicker-DtQKd4Ns.js +2198 -0
  114. package/dist/cdn/SvGridChart-BcLCYvw9.js +1195 -0
  115. package/dist/cdn/SvGridChart-BhnFdLd0.js +1203 -0
  116. package/dist/cdn/SvGridChartPanel-Cmx9DHAS.js +561 -0
  117. package/dist/cdn/SvGridChartPanel-DvjwxLvK.js +577 -0
  118. package/dist/cdn/SvGridChartView-B40DTJSX.js +54 -0
  119. package/dist/cdn/SvGridChartView-PwqI4s02.js +53 -0
  120. package/dist/cdn/SvGridDropdown-DjALc_4f.js +255 -0
  121. package/dist/cdn/SvGridDropdown-hpnHvOGt.js +254 -0
  122. package/dist/cdn/chart-T1usDN0o.js +1212 -0
  123. package/dist/cdn/disclose-version-DoD9AFD_.js +2958 -0
  124. package/dist/cdn/export-format-JT5pWVT8.js +561 -0
  125. package/dist/cdn/popover-P-9P2YYn.js +69 -0
  126. package/dist/cdn/rolldown-runtime-Dy4uBu1J.js +11 -0
  127. package/dist/cdn/src-BLhdLmoN.js +25707 -0
  128. package/dist/cdn/src-BwnUVj3T.js +25623 -0
  129. package/dist/cdn/svgrid.js +9 -32897
  130. package/dist/cdn/svgrid.svelte-external.js +9 -30052
  131. package/dist/cell-formatting.d.ts +2 -2
  132. package/dist/cell-render.js +4 -4
  133. package/dist/chart-view.svelte.d.ts +25 -0
  134. package/dist/chart-view.svelte.js +14 -0
  135. package/dist/createCombobox.svelte.d.ts +5 -0
  136. package/dist/createCombobox.svelte.js +21 -5
  137. package/dist/createDropdownList.svelte.d.ts +3 -0
  138. package/dist/createDropdownList.svelte.js +8 -2
  139. package/dist/createForm.svelte.d.ts +18 -0
  140. package/dist/createForm.svelte.js +51 -6
  141. package/dist/createMenu.svelte.js +27 -0
  142. package/dist/createPopoverSelect.svelte.d.ts +3 -0
  143. package/dist/createPopoverSelect.svelte.js +9 -1
  144. package/dist/createSlider.svelte.d.ts +8 -21
  145. package/dist/createSlider.svelte.js +34 -0
  146. package/dist/createTooltip.svelte.d.ts +12 -0
  147. package/dist/createTooltip.svelte.js +72 -9
  148. package/dist/editor-contract.d.ts +15 -0
  149. package/dist/export-provider.d.ts +27 -0
  150. package/dist/export-provider.js +9 -0
  151. package/dist/filter-operators.d.ts +6 -0
  152. package/dist/filter-operators.js +33 -0
  153. package/dist/form-field.d.ts +45 -2
  154. package/dist/grid-messages.d.ts +61 -0
  155. package/dist/grid-messages.js +72 -0
  156. package/dist/group-display.d.ts +62 -0
  157. package/dist/group-display.js +78 -0
  158. package/dist/index.d.ts +36 -4
  159. package/dist/index.js +43 -2
  160. package/dist/js-scroller.svelte.d.ts +35 -0
  161. package/dist/js-scroller.svelte.js +154 -0
  162. package/dist/list-option.d.ts +46 -0
  163. package/dist/list-option.js +53 -0
  164. package/dist/menus.js +25 -11
  165. package/dist/pivot-view.svelte.d.ts +72 -0
  166. package/dist/pivot-view.svelte.js +13 -0
  167. package/dist/positioning.d.ts +111 -0
  168. package/dist/positioning.js +191 -0
  169. package/dist/scheduler-model.d.ts +3 -0
  170. package/dist/scheduler-model.js +22 -5
  171. package/dist/svgrid-wrapper.types.d.ts +18 -0
  172. package/dist/toast-store.svelte.d.ts +54 -0
  173. package/dist/toast-store.svelte.js +65 -15
  174. package/package.json +9 -1
  175. package/src/GridFooter.svelte +12 -11
  176. package/src/SvAnchor.svelte +65 -0
  177. package/src/SvAspectRatio.svelte +38 -0
  178. package/src/SvAutoComplete.svelte +52 -7
  179. package/src/SvBlockquote.svelte +43 -0
  180. package/src/SvCalendar.svelte +33 -2
  181. package/src/SvCalendar.test.ts +15 -0
  182. package/src/SvCheckBox.svelte +6 -2
  183. package/src/SvCode.svelte +52 -0
  184. package/src/SvCollapsible.svelte +75 -0
  185. package/src/SvColorInput.svelte +11 -17
  186. package/src/SvComboBox.svelte +85 -8
  187. package/src/SvCountryInput.svelte +2 -2
  188. package/src/SvDropDownList.svelte +154 -51
  189. package/src/SvDurationInput.svelte +59 -41
  190. package/src/SvField.svelte +203 -12
  191. package/src/SvForm.svelte +195 -21
  192. package/src/SvForm.test.ts +112 -0
  193. package/src/SvGrid.controller.svelte.ts +88 -7
  194. package/src/SvGrid.svelte +383 -181
  195. package/src/SvGrid.types.ts +125 -1
  196. package/src/SvGridChartView.svelte +70 -0
  197. package/src/SvGridDropdown.svelte +9 -2
  198. package/src/SvGridSelect.svelte +5 -2
  199. package/src/SvGroup.svelte +41 -0
  200. package/src/SvHoverCard.svelte +70 -0
  201. package/src/SvKbd.svelte +51 -0
  202. package/src/SvList.svelte +55 -0
  203. package/src/SvListBox.svelte +166 -77
  204. package/src/SvLoadingOverlay.svelte +53 -0
  205. package/src/SvMark.svelte +36 -0
  206. package/src/SvMaskedInput.svelte +50 -35
  207. package/src/SvMenuList.svelte +32 -3
  208. package/src/SvMenubar.svelte +200 -0
  209. package/src/SvMultiSelect.svelte +7 -4
  210. package/src/SvNumberInput.svelte +79 -42
  211. package/src/SvOtpInput.svelte +2 -2
  212. package/src/SvPasswordInput.svelte +51 -31
  213. package/src/SvPhoneInput.svelte +39 -28
  214. package/src/SvPopconfirm.svelte +79 -0
  215. package/src/SvPopover.svelte +87 -29
  216. package/src/SvRadioGroup.svelte +5 -1
  217. package/src/SvResult.svelte +73 -0
  218. package/src/SvSegmented.svelte +114 -0
  219. package/src/SvSimpleGrid.svelte +41 -0
  220. package/src/SvSlider.svelte +23 -10
  221. package/src/SvSpinner.svelte +43 -0
  222. package/src/SvStack.svelte +37 -0
  223. package/src/SvSwitchButton.svelte +6 -1
  224. package/src/SvTagsInput.svelte +9 -5
  225. package/src/SvText.svelte +76 -0
  226. package/src/SvTextInput.svelte +75 -43
  227. package/src/SvTimePicker.svelte +32 -2
  228. package/src/SvTitle.svelte +57 -0
  229. package/src/SvToaster.svelte +41 -6
  230. package/src/SvToaster.test.ts +32 -0
  231. package/src/SvToggleButton.svelte +4 -1
  232. package/src/SvTooltip.svelte +68 -34
  233. package/src/SvTree.svelte +81 -21
  234. package/src/SvTreeSelect.svelte +5 -2
  235. package/src/SvVisuallyHidden.svelte +49 -0
  236. package/src/ai.test.ts +502 -0
  237. package/src/ai.ts +1391 -0
  238. package/src/board-view.svelte.ts +33 -0
  239. package/src/build-api.coverage.test.ts +101 -0
  240. package/src/build-api.ts +43 -18
  241. package/src/builtin-editors.grid.test.ts +1 -1
  242. package/src/cell-formatting.ts +5 -5
  243. package/src/cell-render.ts +4 -4
  244. package/src/chart-view.svelte.ts +36 -0
  245. package/src/createCombobox.svelte.ts +17 -5
  246. package/src/createDropdownList.svelte.ts +8 -2
  247. package/src/createForm.svelte.ts +59 -6
  248. package/src/createMenu.svelte.ts +23 -0
  249. package/src/createPopoverSelect.svelte.ts +8 -1
  250. package/src/createSlider.svelte.ts +20 -0
  251. package/src/createTooltip.svelte.ts +67 -9
  252. package/src/editor-contract.ts +16 -0
  253. package/src/export-provider.ts +40 -0
  254. package/src/filter-operators.ts +37 -0
  255. package/src/form-field.ts +42 -2
  256. package/src/grid-messages.test.ts +24 -0
  257. package/src/grid-messages.ts +137 -0
  258. package/src/group-display.test.ts +77 -0
  259. package/src/group-display.ts +117 -0
  260. package/src/i18n.grid.test.ts +73 -0
  261. package/src/index.ts +91 -2
  262. package/src/js-scroller.svelte.ts +173 -0
  263. package/src/list-option.test.ts +56 -0
  264. package/src/list-option.ts +81 -0
  265. package/src/menus.test.ts +32 -0
  266. package/src/menus.ts +25 -12
  267. package/src/pivot-view.svelte.ts +90 -0
  268. package/src/pivot-view.test.ts +38 -0
  269. package/src/pivot.grid.test.ts +102 -0
  270. package/src/positioning.test.ts +141 -0
  271. package/src/positioning.ts +266 -0
  272. package/src/scheduler-model.test.ts +16 -0
  273. package/src/scheduler-model.ts +24 -5
  274. package/src/svgrid-wrapper.types.ts +23 -0
  275. package/src/svgrid.charting.test.ts +8 -1
  276. package/src/svgrid.comments-autocomplete.test.ts +7 -2
  277. package/src/svgrid.context-menu.test.ts +8 -3
  278. package/src/toast-store.svelte.ts +98 -0
  279. package/src/toast-store.test.ts +62 -1
  280. package/src/ui-breadth.test.ts +138 -0
  281. package/src/ui-buttons.test.ts +39 -0
  282. package/src/ui-inputs.test.ts +2 -2
  283. package/src/ui-range.test.ts +9 -0
  284. package/src/ui-selection.test.ts +36 -0
  285. package/src/ui-tier1.test.ts +1 -1
  286. package/src/virtual.test.ts +20 -6
  287. package/dist/SvGridBoard.svelte +0 -2339
  288. package/dist/SvGridBoard.svelte.d.ts +0 -31
  289. package/src/SvGridBoard.svelte +0 -2339
  290. package/src/board.test.ts +0 -927
package/src/SvGrid.svelte CHANGED
@@ -23,8 +23,10 @@
23
23
  RenderComponentConfig,
24
24
  } from "./render-component";
25
25
  import { buildSparkline, toSparklineValues } from "./sparkline";
26
- import SvGridDropdown from "./SvGridDropdown.svelte";
27
- import SvDateTimePicker from "./SvDateTimePicker.svelte";
26
+ import { localizeOperatorLabel } from "./filter-operators";
27
+ // SvGridDropdown (list/chips cell editor) and SvDateTimePicker (date/time cell
28
+ // editors) are lazy-loaded below - they only mount while a cell of that type is
29
+ // actively being edited, so they stay out of the base <SvGrid> bundle.
28
30
  import {
29
31
  hasCellEditor,
30
32
  getCellEditor,
@@ -57,19 +59,106 @@
57
59
  joinInTokens,
58
60
  } from "./filtering/excel-filters";
59
61
  import { createSvGridController } from "./SvGrid.controller.svelte";
60
- import GridMenus from "./GridMenus.svelte";
61
- import SvGridChartPanel from "./SvGridChartPanel.svelte";
62
+ // GridMenus hosts tooltips + all column/filter/context menu overlays - none of
63
+ // which exist until the user hovers or opens a menu, so it too is lazy-loaded.
62
64
  import GridFooter from "./GridFooter.svelte";
63
- import SvGridBoard from "./SvGridBoard.svelte";
65
+ // SvGridChartPanel (charting) and SvGridBoard (Kanban) are heavy, prop-gated
66
+ // views - lazy-loaded below so they stay out of the base <SvGrid> bundle.
64
67
  import { getSchedulerView } from "./scheduler-view.svelte";
68
+ import { getBoardView } from "./board-view.svelte";
69
+ import { getChartView } from "./chart-view.svelte";
65
70
  let props: Props<TFeatures, TData> = $props();
66
71
  const ctrl = createSvGridController(props);
72
+ // Effective props: the controller's `override ?? prop` proxy that backs
73
+ // `api.setOption(...)`. Reading `opt.X` (instead of `props.X`) makes a view-direct
74
+ // prop honor a runtime override. Svelte binds template `props.X` reads to the prop
75
+ // signal (so reassigning `props` would not reroute them); `opt` is a separate
76
+ // binding the template reads by name. Behavioral props (sortable/filterable/...) are
77
+ // already resolved through the controller, so they honor overrides without `opt`.
78
+ const opt = ctrl.props as Props<TFeatures, TData>;
79
+ // Localized chrome strings (English defaults merged with `localeText`).
80
+ const messages = $derived(ctrl.messages);
67
81
  // Kanban board mode: when `board` is set the grid renders lanes of cards
68
82
  // instead of the table (see SvGridBoard). Narrowed derived so the template
69
83
  // branch can pass it non-null.
70
- const boardConfig = $derived(props.board);
84
+ const boardConfig = $derived(opt.board);
71
85
  // Scheduler / calendar mode: same "view of the grid" seam as the board.
72
- const schedulerConfig = $derived(props.scheduler);
86
+ const schedulerConfig = $derived(opt.scheduler);
87
+ // Chart mode: another "view of the grid". Unlike board/scheduler, the renderer
88
+ // is free - a built-in default (SvGridChartView, lazy-loaded below) wraps the
89
+ // standalone SvChart, overridable via the `chart-view` seam (getChartView).
90
+ const chartViewConfig = $derived(opt.chart);
91
+ // Lazy views + editors: charting (SvGridChart engine), the Kanban board, the
92
+ // list/date cell editors and the menu/tooltip overlay host are all large and
93
+ // only used behind a prop or an interaction, so each loads as its own chunk the
94
+ // first time its feature is actually reached - keeping them out of the base
95
+ // <SvGrid> bundle. Held in $state and mounted as dynamic components once
96
+ // resolved (client-only, mirroring the scheduler-view seam above).
97
+ // Holder types use type-only `import(...)` so each keeps full prop inference
98
+ // (callback param types) while the *runtime* import stays lazy - the type
99
+ // import is erased by the compiler and adds nothing to the bundle.
100
+ // The Kanban board renderer ships in @svgrid/enterprise and plugs in through
101
+ // the `board-view` seam (getBoardView) - same model as the scheduler view.
102
+ let ChartPanelView = $state<typeof import("./SvGridChartPanel.svelte").default | null>(null);
103
+ // Built-in chart-view renderer, lazy-loaded the first time the `chart` prop is
104
+ // set (it pulls in the charting engine, so it stays out of the base bundle).
105
+ // Typed as Component<any> - same as the board/scheduler view holders - so the
106
+ // grid's generic <TData> doesn't clash with the renderer's base prop types.
107
+ let ChartView = $state<import("svelte").Component<any> | null>(null);
108
+ $effect(() => {
109
+ if (chartViewConfig && !ChartView)
110
+ import("./SvGridChartView.svelte").then((m) => (ChartView = m.default));
111
+ });
112
+ let DropdownEditor = $state<typeof import("./SvGridDropdown.svelte").default | null>(null);
113
+ let DateEditor = $state<typeof import("./SvDateTimePicker.svelte").default | null>(null);
114
+ let MenusOverlay = $state<typeof import("./GridMenus.svelte").default | null>(null);
115
+ $effect(() => {
116
+ if (ctrl.chartingEnabled && ctrl.chartPanelOpen && !ChartPanelView)
117
+ import("./SvGridChartPanel.svelte").then((m) => (ChartPanelView = m.default));
118
+ });
119
+
120
+ // When the chart panel is docked (not floating), reserve space on the root so
121
+ // the panel sits in a gutter beside/below the grid instead of overlaying the
122
+ // data rows. The panel is absolutely positioned, and absolute offsets are
123
+ // measured from the padding box - so padding on the root pushes the grid
124
+ // content (toolbar + shell + footer) inward and leaves exactly `size` px of
125
+ // gutter for the panel to fill. Mirrors the panel's own position/size logic.
126
+ const chartDockReserveStyle = $derived.by(() => {
127
+ if (!ctrl.chartingEnabled || !ctrl.chartPanelOpen || ctrl.chartFloating)
128
+ return "";
129
+ const cfg = ctrl.chartingConfig;
130
+ const pos = cfg?.position ?? "right";
131
+ const size =
132
+ ctrl.chartSize ??
133
+ (pos === "right" ? (cfg?.width ?? 460) : (cfg?.height ?? 300));
134
+ const edge = pos === "right" ? "padding-right" : "padding-bottom";
135
+ return `${edge}:${size}px; transition:${edge} 180ms cubic-bezier(0.33,1,0.68,1);`;
136
+ });
137
+ $effect(() => {
138
+ const t = ctrl.editingCell?.editorType;
139
+ if (
140
+ (t === "list" || t === "chips" || t === "select" || t === "rich-select") &&
141
+ !DropdownEditor
142
+ )
143
+ import("./SvGridDropdown.svelte").then((m) => (DropdownEditor = m.default));
144
+ if ((t === "date" || t === "datetime" || t === "time") && !DateEditor)
145
+ import("./SvDateTimePicker.svelte").then((m) => (DateEditor = m.default));
146
+ });
147
+ $effect(() => {
148
+ const menuOpen =
149
+ ctrl.tooltip ||
150
+ ctrl.columnMenuFor ||
151
+ ctrl.contextMenuFor ||
152
+ ctrl.filterMenuFor ||
153
+ ctrl.operatorMenuFor ||
154
+ ctrl.chooseColumnsPos;
155
+ if (menuOpen && !MenusOverlay)
156
+ import("./GridMenus.svelte").then((m) => (MenusOverlay = m.default));
157
+ });
158
+ // In-grid pivot mode: when active, the grid renders the pivot result (over its
159
+ // filtered + sorted rows) as a nested grid in place of the flat table.
160
+ const pivotViewOn = $derived(!!ctrl.pivotConfig && ctrl.pivotModeOn);
161
+ const pivotResult = $derived(ctrl.pivotResult);
73
162
  // The board / scheduler render the grid's FILTERED + SORTED rows (not raw
74
163
  // data), so the search box / column filters / sort all flow through to them.
75
164
  const boardData = $derived(
@@ -120,7 +209,7 @@
120
209
  const onColumnHeaderDrop = $derived(ctrl.onColumnHeaderDrop);
121
210
  const onColumnHeaderDragEnd = $derived(ctrl.onColumnHeaderDragEnd);
122
211
  // Managed row dragging
123
- const rowDragManagedEffective = $derived(props.rowDragManaged === true);
212
+ const rowDragManagedEffective = $derived(opt.rowDragManaged === true);
124
213
  const rowDropIndex = $derived(ctrl.rowDropIndex);
125
214
  const rowDropSide = $derived(ctrl.rowDropSide);
126
215
  const onRowDragStart = $derived(ctrl.onRowDragStart);
@@ -155,7 +244,7 @@
155
244
  const isGroupRow = $derived(ctrl.isGroupRow);
156
245
  // Server-side group / tree a11y: aria-level on every tree row, aria-expanded
157
246
  // on the expandable ones. Undefined (attribute omitted) when serverGroup is off.
158
- const serverGroup = $derived(props.serverGroup);
247
+ const serverGroup = $derived(opt.serverGroup);
159
248
  function sgAriaLevel(row: Row<TData>): number | undefined {
160
249
  return serverGroup ? serverGroup.level(row.original as TData) + 1 : undefined;
161
250
  }
@@ -183,7 +272,7 @@
183
272
  // The non-virtualized (`virtualization={false}`) body must apply this too, else its rows
184
273
  // fall back to content height and look shorter than a virtualized grid's.
185
274
  const rowSizePx = (i: number): number => {
186
- const rh = props.rowHeight;
275
+ const rh = opt.rowHeight;
187
276
  return typeof rh === "function" ? rh(i) : (rh ?? 30);
188
277
  };
189
278
  const columnVirtualizationEnabled = $derived(
@@ -532,27 +621,27 @@
532
621
  onpointermove={onWindowPointerMove}
533
622
  />
534
623
 
535
- {#if props.loading && !props.loadingOverlay && !hasMeasured}
624
+ {#if opt.loading && !opt.loadingOverlay && !hasMeasured}
536
625
  <!-- Full-screen loading state only on the *initial* load, before the grid
537
626
  has ever rendered. Once measured, a `loading` flip (from a server-mode
538
627
  sort / filter / page refetch) keeps the table mounted so header inputs
539
628
  and focus survive - the empty-row message + optional `loadingOverlay`
540
629
  cover the in-place refresh. -->
541
630
  <div class="sv-grid-state sv-grid-state-loading" role="status">
542
- Loading grid data...
631
+ {messages.loading}
543
632
  </div>
544
- {:else if props.error}
633
+ {:else if opt.error}
545
634
  <div class="sv-grid-state sv-grid-state-error" role="alert">
546
- {props.error}
635
+ {opt.error}
547
636
  </div>
548
637
  {:else if boardConfig}
549
638
  <div
550
639
  class="sv-grid-root sv-grid-board-root"
551
- class:sv-grid-root-fill={props.containerHeight === "100%"}
640
+ class:sv-grid-root-fill={opt.containerHeight === "100%"}
552
641
  style={`height: ${
553
- typeof props.containerHeight === "string"
554
- ? props.containerHeight
555
- : `${props.containerHeight ?? 520}px`
642
+ typeof opt.containerHeight === "string"
643
+ ? opt.containerHeight
644
+ : `${opt.containerHeight ?? 520}px`
556
645
  }; display: flex; flex-direction: column;`}
557
646
  >
558
647
  {#if boardConfig.searchable !== false}
@@ -570,22 +659,36 @@
570
659
  </label>
571
660
  {/if}
572
661
  <div style="flex: 1 1 auto; min-height: 0;">
573
- <SvGridBoard
574
- data={boardData}
575
- columns={props.columns}
576
- board={boardConfig}
577
- getRowId={props.getRowId}
578
- />
662
+ {#if getBoardView()}
663
+ {@const BoardView = getBoardView()}
664
+ <BoardView
665
+ data={boardData}
666
+ columns={opt.columns}
667
+ board={boardConfig}
668
+ getRowId={opt.getRowId}
669
+ />
670
+ {:else}
671
+ <!-- The Kanban board renderer ships in @svgrid/enterprise. Call
672
+ `enableBoardView()` (or `installEnterprise(api)`) to register it. -->
673
+ <div class="sv-grid-scheduler-upsell" role="note">
674
+ <strong>Kanban board view</strong>
675
+ <p>
676
+ The Kanban board view is an Enterprise feature. Install
677
+ <code>@svgrid/enterprise</code> and call <code>enableBoardView()</code>
678
+ to render it.
679
+ </p>
680
+ </div>
681
+ {/if}
579
682
  </div>
580
683
  </div>
581
684
  {:else if schedulerConfig}
582
685
  <div
583
686
  class="sv-grid-root sv-grid-scheduler-root"
584
- class:sv-grid-root-fill={props.containerHeight === "100%"}
687
+ class:sv-grid-root-fill={opt.containerHeight === "100%"}
585
688
  style={`height: ${
586
- typeof props.containerHeight === "string"
587
- ? props.containerHeight
588
- : `${props.containerHeight ?? 520}px`
689
+ typeof opt.containerHeight === "string"
690
+ ? opt.containerHeight
691
+ : `${opt.containerHeight ?? 520}px`
589
692
  }; display: flex; flex-direction: column;`}
590
693
  >
591
694
  {#if schedulerConfig.searchable !== false}
@@ -607,9 +710,9 @@
607
710
  {@const SchedulerView = getSchedulerView()}
608
711
  <SchedulerView
609
712
  data={boardData}
610
- columns={props.columns}
713
+ columns={opt.columns}
611
714
  scheduler={schedulerConfig}
612
- getRowId={props.getRowId}
715
+ getRowId={opt.getRowId}
613
716
  />
614
717
  {:else}
615
718
  <!-- The scheduler renderer ships in @svgrid/enterprise. Call
@@ -625,6 +728,88 @@
625
728
  {/if}
626
729
  </div>
627
730
  </div>
731
+ {:else if chartViewConfig}
732
+ <div
733
+ class="sv-grid-root sv-grid-chart-root"
734
+ class:sv-grid-root-fill={opt.containerHeight === "100%"}
735
+ style={`height: ${
736
+ typeof opt.containerHeight === "string"
737
+ ? opt.containerHeight
738
+ : `${opt.containerHeight ?? 520}px`
739
+ }; display: flex; flex-direction: column;`}
740
+ >
741
+ {#if chartViewConfig.searchable !== false}
742
+ <label class="sv-grid-board-search">
743
+ <svg viewBox="0 0 16 16" aria-hidden="true" width="14" height="14">
744
+ <circle cx="7" cy="7" r="4.5" fill="none" stroke="currentColor" stroke-width="1.5" />
745
+ <line x1="10.2" y1="10.2" x2="14" y2="14" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" />
746
+ </svg>
747
+ <input
748
+ type="search"
749
+ placeholder={chartViewConfig.searchPlaceholder ?? "Search data..."}
750
+ bind:value={ctrl.globalFilter}
751
+ aria-label="Search data"
752
+ />
753
+ </label>
754
+ {/if}
755
+ <div style="flex: 1 1 auto; min-height: 0;">
756
+ {#if getChartView()}
757
+ {@const RegisteredChartView = getChartView()}
758
+ <RegisteredChartView
759
+ data={boardData}
760
+ columns={opt.columns}
761
+ chart={chartViewConfig}
762
+ getRowId={opt.getRowId}
763
+ />
764
+ {:else if ChartView}
765
+ <ChartView
766
+ data={boardData}
767
+ columns={opt.columns}
768
+ chart={chartViewConfig}
769
+ getRowId={opt.getRowId}
770
+ />
771
+ {:else}
772
+ <!-- The built-in chart view is loading (lazy chunk). -->
773
+ <div class="sv-grid-state" role="status">Loading chart...</div>
774
+ {/if}
775
+ </div>
776
+ </div>
777
+ {:else if pivotViewOn}
778
+ <div
779
+ class="sv-grid-root sv-grid-pivot-root"
780
+ class:sv-grid-root-fill={opt.containerHeight === "100%"}
781
+ style={`height: ${
782
+ typeof opt.containerHeight === "string"
783
+ ? opt.containerHeight
784
+ : `${opt.containerHeight ?? 520}px`
785
+ }; display: flex; flex-direction: column;`}
786
+ >
787
+ <div class="sv-grid-pivot-bar">
788
+ <span class="sv-grid-pivot-badge">{messages.group}</span>
789
+ <button
790
+ type="button"
791
+ class="sv-grid-pivot-toggle"
792
+ aria-pressed="true"
793
+ onclick={() => ctrl.togglePivotMode()}
794
+ >{messages.pivotUpsellTitle}</button>
795
+ </div>
796
+ <div style="flex: 1 1 auto; min-height: 0;">
797
+ {#if pivotResult}
798
+ <svelte:self
799
+ data={pivotResult.rows}
800
+ columns={pivotResult.columns}
801
+ containerHeight="100%"
802
+ />
803
+ {:else}
804
+ <!-- The pivot engine ships in @svgrid/enterprise. Call `enablePivot()`
805
+ (or `installEnterprise(api)`) to register it. -->
806
+ <div class="sv-grid-scheduler-upsell sv-grid-pivot-upsell" role="note">
807
+ <strong>{messages.pivotUpsellTitle}</strong>
808
+ <p>{messages.pivotUpsellBody}</p>
809
+ </div>
810
+ {/if}
811
+ </div>
812
+ </div>
628
813
  {:else}
629
814
  {#snippet icon(name: string)}
630
815
  <svg
@@ -966,22 +1151,24 @@
966
1151
  {:else if ctrl.editingCell?.editorType === "list"}
967
1152
  {@const opts = getColumnEditorOptions(column, row)}
968
1153
  {@const multi = column.columnDef.editorMultiple === true}
969
- <SvGridDropdown
970
- options={opts}
971
- value={ctrl.editingCell?.value}
972
- multiple={multi}
973
- placeholder="Select…"
974
- onChange={(next) => {
975
- ctrl.editingCell = ctrl.editingCell
976
- ? { ...ctrl.editingCell, value: next }
977
- : ctrl.editingCell;
978
- }}
979
- onCommit={() => saveEditingCell()}
980
- onCancel={() => {
981
- ctrl.editingCell = null;
982
- ctrl.gridRootEl?.focus({ preventScroll: true });
983
- }}
984
- />
1154
+ {#if DropdownEditor}
1155
+ <DropdownEditor
1156
+ options={opts}
1157
+ value={ctrl.editingCell?.value}
1158
+ multiple={multi}
1159
+ placeholder="Select…"
1160
+ onChange={(next) => {
1161
+ ctrl.editingCell = ctrl.editingCell
1162
+ ? { ...ctrl.editingCell, value: next }
1163
+ : ctrl.editingCell;
1164
+ }}
1165
+ onCommit={() => saveEditingCell()}
1166
+ onCancel={() => {
1167
+ ctrl.editingCell = null;
1168
+ ctrl.gridRootEl?.focus({ preventScroll: true });
1169
+ }}
1170
+ />
1171
+ {/if}
985
1172
  {:else if ctrl.editingCell?.editorType === "chips"}
986
1173
  {@const opts = getColumnEditorOptions(column, row)}
987
1174
  {@const multi = column.columnDef.editorMultiple === true}
@@ -1029,43 +1216,47 @@
1029
1216
  <!-- Custom dropdown: opens a themed popover identical in feel to
1030
1217
  the existing 'list' editor (single-select, no typeahead). -->
1031
1218
  {@const selectOpts = getColumnEditorOptions(column, row)}
1032
- <SvGridDropdown
1033
- options={selectOpts}
1034
- value={ctrl.editingCell?.value}
1035
- multiple={false}
1036
- placeholder="Select…"
1037
- onChange={(next) => {
1038
- ctrl.editingCell = ctrl.editingCell
1039
- ? { ...ctrl.editingCell, value: next }
1040
- : ctrl.editingCell;
1041
- }}
1042
- onCommit={() => saveEditingCell()}
1043
- onCancel={() => {
1044
- ctrl.editingCell = null;
1045
- ctrl.gridRootEl?.focus({ preventScroll: true });
1046
- }}
1047
- />
1219
+ {#if DropdownEditor}
1220
+ <DropdownEditor
1221
+ options={selectOpts}
1222
+ value={ctrl.editingCell?.value}
1223
+ multiple={false}
1224
+ placeholder="Select…"
1225
+ onChange={(next) => {
1226
+ ctrl.editingCell = ctrl.editingCell
1227
+ ? { ...ctrl.editingCell, value: next }
1228
+ : ctrl.editingCell;
1229
+ }}
1230
+ onCommit={() => saveEditingCell()}
1231
+ onCancel={() => {
1232
+ ctrl.editingCell = null;
1233
+ ctrl.gridRootEl?.focus({ preventScroll: true });
1234
+ }}
1235
+ />
1236
+ {/if}
1048
1237
  {:else if ctrl.editingCell?.editorType === "rich-select"}
1049
1238
  <!-- Searchable combobox: same popover as 'select' with a
1050
1239
  typeahead filter input baked in at the top. -->
1051
1240
  {@const richOpts = getColumnEditorOptions(column, row)}
1052
- <SvGridDropdown
1053
- options={richOpts}
1054
- value={ctrl.editingCell?.value}
1055
- multiple={false}
1056
- searchable={true}
1057
- placeholder="Search…"
1058
- onChange={(next) => {
1059
- ctrl.editingCell = ctrl.editingCell
1060
- ? { ...ctrl.editingCell, value: next }
1061
- : ctrl.editingCell;
1062
- }}
1063
- onCommit={() => saveEditingCell()}
1064
- onCancel={() => {
1065
- ctrl.editingCell = null;
1066
- ctrl.gridRootEl?.focus({ preventScroll: true });
1067
- }}
1068
- />
1241
+ {#if DropdownEditor}
1242
+ <DropdownEditor
1243
+ options={richOpts}
1244
+ value={ctrl.editingCell?.value}
1245
+ multiple={false}
1246
+ searchable={true}
1247
+ placeholder="Search…"
1248
+ onChange={(next) => {
1249
+ ctrl.editingCell = ctrl.editingCell
1250
+ ? { ...ctrl.editingCell, value: next }
1251
+ : ctrl.editingCell;
1252
+ }}
1253
+ onCommit={() => saveEditingCell()}
1254
+ onCancel={() => {
1255
+ ctrl.editingCell = null;
1256
+ ctrl.gridRootEl?.focus({ preventScroll: true });
1257
+ }}
1258
+ />
1259
+ {/if}
1069
1260
  {:else if ctrl.editingCell?.editorType === "textarea"}
1070
1261
  <!-- Multi-line editor. Commits on Tab, Ctrl/Cmd+Enter, or blur.
1071
1262
  Plain Enter inserts a newline (the whole point of textarea).
@@ -1148,49 +1339,55 @@
1148
1339
  {:else if ctrl.editingCell?.editorType === "date"}
1149
1340
  <!-- Rich date editor: SvCalendar popover over a formatted input. Opts
1150
1341
  out to the native <input type="date"> via editorType 'date-native'. -->
1151
- <SvDateTimePicker
1152
- value={ctrl.editingCell?.value as string | number | Date | null}
1153
- formatString="yyyy-MM-dd"
1154
- dropDownDisplayMode="calendar"
1155
- autoOpen
1156
- block
1157
- onChange={(d) => updateEditingCellValue(d)}
1158
- onCommit={() => saveEditingCell()}
1159
- onCancel={() => {
1160
- ctrl.editingCell = null;
1161
- ctrl.gridRootEl?.focus({ preventScroll: true });
1162
- }}
1163
- />
1342
+ {#if DateEditor}
1343
+ <DateEditor
1344
+ value={ctrl.editingCell?.value as string | number | Date | null}
1345
+ formatString="yyyy-MM-dd"
1346
+ dropDownDisplayMode="calendar"
1347
+ autoOpen
1348
+ block
1349
+ onChange={(d) => updateEditingCellValue(d)}
1350
+ onCommit={() => saveEditingCell()}
1351
+ onCancel={() => {
1352
+ ctrl.editingCell = null;
1353
+ ctrl.gridRootEl?.focus({ preventScroll: true });
1354
+ }}
1355
+ />
1356
+ {/if}
1164
1357
  {:else if ctrl.editingCell?.editorType === "datetime"}
1165
- <SvDateTimePicker
1166
- value={ctrl.editingCell?.value as string | number | Date | null}
1167
- formatString="yyyy-MM-dd HH:mm"
1168
- dropDownDisplayMode="both"
1169
- autoOpen
1170
- block
1171
- onChange={(d) => updateEditingCellValue(d)}
1172
- onCommit={() => saveEditingCell()}
1173
- onCancel={() => {
1174
- ctrl.editingCell = null;
1175
- ctrl.gridRootEl?.focus({ preventScroll: true });
1176
- }}
1177
- />
1358
+ {#if DateEditor}
1359
+ <DateEditor
1360
+ value={ctrl.editingCell?.value as string | number | Date | null}
1361
+ formatString="yyyy-MM-dd HH:mm"
1362
+ dropDownDisplayMode="both"
1363
+ autoOpen
1364
+ block
1365
+ onChange={(d) => updateEditingCellValue(d)}
1366
+ onCommit={() => saveEditingCell()}
1367
+ onCancel={() => {
1368
+ ctrl.editingCell = null;
1369
+ ctrl.gridRootEl?.focus({ preventScroll: true });
1370
+ }}
1371
+ />
1372
+ {/if}
1178
1373
  {:else if ctrl.editingCell?.editorType === "time"}
1179
1374
  <!-- Rich time editor: SvTimePicker dial. Stores the 'HH:MM' string the
1180
1375
  `time` parser expects; opts out via editorType 'time-native'. -->
1181
- <SvDateTimePicker
1182
- value={timeStringToDate(ctrl.editingCell?.value)}
1183
- formatString="HH:mm"
1184
- dropDownDisplayMode="time"
1185
- autoOpen
1186
- block
1187
- onChange={(d) => updateEditingCellValue(dateToTimeString(d))}
1188
- onCommit={() => saveEditingCell()}
1189
- onCancel={() => {
1190
- ctrl.editingCell = null;
1191
- ctrl.gridRootEl?.focus({ preventScroll: true });
1192
- }}
1193
- />
1376
+ {#if DateEditor}
1377
+ <DateEditor
1378
+ value={timeStringToDate(ctrl.editingCell?.value)}
1379
+ formatString="HH:mm"
1380
+ dropDownDisplayMode="time"
1381
+ autoOpen
1382
+ block
1383
+ onChange={(d) => updateEditingCellValue(dateToTimeString(d))}
1384
+ onCommit={() => saveEditingCell()}
1385
+ onCancel={() => {
1386
+ ctrl.editingCell = null;
1387
+ ctrl.gridRootEl?.focus({ preventScroll: true });
1388
+ }}
1389
+ />
1390
+ {/if}
1194
1391
  {:else if ctrl.editingCell?.editorType === "color"}
1195
1392
  <!-- Native <input type="color"> opens its picker in a separate OS
1196
1393
  overlay; once the picker closes, focus stays on the input so
@@ -1307,23 +1504,25 @@
1307
1504
  which renders the selected values as chips in its trigger and
1308
1505
  pops out a styled listbox. Identical UX to the list editor
1309
1506
  with renderChipsInTrigger flipped on. -->
1310
- <SvGridDropdown
1311
- options={opts}
1312
- value={ctrl.editingCell?.value}
1313
- multiple={multi}
1314
- placeholder="Pick…"
1315
- renderChipsInTrigger={true}
1316
- onChange={(next) => {
1317
- ctrl.editingCell = ctrl.editingCell
1318
- ? { ...ctrl.editingCell, value: next }
1319
- : ctrl.editingCell;
1320
- }}
1321
- onCommit={() => saveEditingCell()}
1322
- onCancel={() => {
1323
- ctrl.editingCell = null;
1324
- ctrl.gridRootEl?.focus({ preventScroll: true });
1325
- }}
1326
- />
1507
+ {#if DropdownEditor}
1508
+ <DropdownEditor
1509
+ options={opts}
1510
+ value={ctrl.editingCell?.value}
1511
+ multiple={multi}
1512
+ placeholder="Pick…"
1513
+ renderChipsInTrigger={true}
1514
+ onChange={(next) => {
1515
+ ctrl.editingCell = ctrl.editingCell
1516
+ ? { ...ctrl.editingCell, value: next }
1517
+ : ctrl.editingCell;
1518
+ }}
1519
+ onCommit={() => saveEditingCell()}
1520
+ onCancel={() => {
1521
+ ctrl.editingCell = null;
1522
+ ctrl.gridRootEl?.focus({ preventScroll: true });
1523
+ }}
1524
+ />
1525
+ {/if}
1327
1526
  {:else}
1328
1527
  <!-- Free-form chips: typed tags. Enter / comma commits a chip,
1329
1528
  Backspace on empty input removes the last chip, blur saves. -->
@@ -1467,8 +1666,8 @@
1467
1666
  (showRowNumbersEffective ? 1 : 0) +
1468
1667
  (showRowSelectionEffective ? 1 : 0)}
1469
1668
  >
1470
- {#if props.renderDetailRow}
1471
- {@render props.renderDetailRow({
1669
+ {#if opt.renderDetailRow}
1670
+ {@render opt.renderDetailRow({
1472
1671
  row: detailRow.original as TData,
1473
1672
  rowIndex: detailRowIndex,
1474
1673
  })}
@@ -1537,7 +1736,8 @@
1537
1736
 
1538
1737
  <div
1539
1738
  class="sv-grid-root"
1540
- class:sv-grid-root-fill={props.containerHeight === "100%"}
1739
+ class:sv-grid-root-fill={opt.containerHeight === "100%"}
1740
+ style={chartDockReserveStyle}
1541
1741
  >
1542
1742
  {#if showGlobalFilterEffective}
1543
1743
  <label class="sv-grid-global-filter">
@@ -1595,17 +1795,17 @@
1595
1795
  </div>
1596
1796
  {/if}
1597
1797
 
1598
- {#if hasMeasured && (props.paginationPosition === "top" || props.paginationPosition === "both")}
1599
- <GridFooter {ctrl} showStatus={false} top pager pageSizeOptions={props.pageSizeOptions} />
1798
+ {#if hasMeasured && (opt.paginationPosition === "top" || opt.paginationPosition === "both")}
1799
+ <GridFooter {ctrl} showStatus={false} top pager pageSizeOptions={opt.pageSizeOptions} />
1600
1800
  {/if}
1601
1801
 
1602
1802
  <div
1603
1803
  class="sv-grid-shell"
1604
1804
  style={`height: ${
1605
- typeof props.containerHeight === "string"
1606
- ? props.containerHeight
1607
- : `${props.containerHeight ?? 520}px`
1608
- }; --sg-thead-h: ${headerHeight}px; --sg-pinned-row-h: ${typeof props.rowHeight === "number" ? props.rowHeight : 30}px;`}
1805
+ typeof opt.containerHeight === "string"
1806
+ ? opt.containerHeight
1807
+ : `${opt.containerHeight ?? 520}px`
1808
+ }; --sg-thead-h: ${headerHeight}px; --sg-pinned-row-h: ${typeof opt.rowHeight === "number" ? opt.rowHeight : 30}px;`}
1609
1809
  >
1610
1810
  <div
1611
1811
  class="sv-grid-container sv-grid-container-custom-scrollbars"
@@ -1619,12 +1819,12 @@
1619
1819
  <table
1620
1820
  bind:this={ctrl.gridRootEl}
1621
1821
  class="sv-grid-table"
1622
- class:sv-grid-no-row-hover={props.enableRowHover !== true}
1822
+ class:sv-grid-no-row-hover={opt.enableRowHover !== true}
1623
1823
  {...getGridRootA11yProps({
1624
1824
  activeDescendantId,
1625
1825
  rowCount: allRows.length,
1626
1826
  colCount: allColumns.length,
1627
- treegrid: !!props.serverGroup,
1827
+ treegrid: !!opt.serverGroup,
1628
1828
  })}
1629
1829
  onkeydown={onGridKeyDown}
1630
1830
  onpaste={onGridPaste}
@@ -1640,8 +1840,8 @@
1640
1840
  <tr
1641
1841
  class="sv-grid-row sv-grid-header-row sv-grid-group-header-row"
1642
1842
  {...getGridRowA11yProps()}
1643
- style={props.headerHeight
1644
- ? `height: ${props.headerHeight}px;`
1843
+ style={opt.headerHeight
1844
+ ? `height: ${opt.headerHeight}px;`
1645
1845
  : undefined}
1646
1846
  >
1647
1847
  {#if showRowNumbersEffective}
@@ -1726,8 +1926,8 @@
1726
1926
  <tr
1727
1927
  class="sv-grid-row sv-grid-header-row"
1728
1928
  {...getGridRowA11yProps()}
1729
- style={props.headerHeight
1730
- ? `height: ${props.headerHeight}px;`
1929
+ style={opt.headerHeight
1930
+ ? `height: ${opt.headerHeight}px;`
1731
1931
  : undefined}
1732
1932
  >
1733
1933
  {#if showRowNumbersEffective}
@@ -1786,23 +1986,23 @@
1786
1986
  data-align={getColumnAlign(rendered.column)}
1787
1987
  data-pinned={isColumnPinned(rendered.column.id) ??
1788
1988
  undefined}
1789
- draggable={(props.enableColumnReorder ?? false)
1989
+ draggable={(opt.enableColumnReorder ?? false)
1790
1990
  ? true
1791
1991
  : undefined}
1792
1992
  ondragstart={(e) =>
1793
- (props.enableColumnReorder ?? false) &&
1993
+ (opt.enableColumnReorder ?? false) &&
1794
1994
  onColumnHeaderDragStart(e, header.column.id)}
1795
1995
  ondragover={(e) =>
1796
- (props.enableColumnReorder ?? false) &&
1996
+ (opt.enableColumnReorder ?? false) &&
1797
1997
  onColumnHeaderDragOver(e, header.column.id)}
1798
1998
  ondragleave={() =>
1799
- (props.enableColumnReorder ?? false) &&
1999
+ (opt.enableColumnReorder ?? false) &&
1800
2000
  onColumnHeaderDragLeave(header.column.id)}
1801
2001
  ondrop={(e) =>
1802
- (props.enableColumnReorder ?? false) &&
2002
+ (opt.enableColumnReorder ?? false) &&
1803
2003
  onColumnHeaderDrop(e, header.column.id)}
1804
2004
  ondragend={() =>
1805
- (props.enableColumnReorder ?? false) &&
2005
+ (opt.enableColumnReorder ?? false) &&
1806
2006
  onColumnHeaderDragEnd()}
1807
2007
  style={`width: ${rendered.item.size}px; min-width: ${rendered.item.size}px; max-width: ${rendered.item.size}px; ${cellPinStyle(rendered.column.id)}`}
1808
2008
  {...getGridHeaderA11yProps({
@@ -2032,8 +2232,8 @@
2032
2232
  type="button"
2033
2233
  class="sv-grid-filter-operator-btn"
2034
2234
  class:is-open={operatorMenuFor === rendered.column.id}
2035
- title={`Condition: ${operatorOption(activeOperator).label}`}
2036
- aria-label={`Filter condition: ${operatorOption(activeOperator).label}`}
2235
+ title={`Condition: ${localizeOperatorLabel(operatorOption(activeOperator), rendered.column, messages)}`}
2236
+ aria-label={`Filter condition: ${localizeOperatorLabel(operatorOption(activeOperator), rendered.column, messages)}`}
2037
2237
  onclick={(event) =>
2038
2238
  openOperatorMenu(event, rendered.column.id)}
2039
2239
  >
@@ -2160,13 +2360,13 @@
2160
2360
  {/if}
2161
2361
  {/each}
2162
2362
  </thead>
2163
- {#if props.pinnedTopRows && props.pinnedTopRows.length > 0}
2363
+ {#if opt.pinnedTopRows && opt.pinnedTopRows.length > 0}
2164
2364
  <!-- svelte-ignore a11y_no_redundant_roles -->
2165
2365
  <tbody
2166
2366
  class="sv-grid-pinned sv-grid-pinned-top-body"
2167
2367
  role="rowgroup"
2168
2368
  >
2169
- {#each props.pinnedTopRows as r, i (i)}
2369
+ {#each opt.pinnedTopRows as r, i (i)}
2170
2370
  {@render pinnedRowBody(r, "top", i)}
2171
2371
  {/each}
2172
2372
  </tbody>
@@ -2180,7 +2380,7 @@
2180
2380
  : undefined}
2181
2381
  ondrop={rowDragManagedEffective ? onRowsContainerDrop : undefined}
2182
2382
  >
2183
- {#if !allRows.length && !(props.loading && props.loadingOverlay)}
2383
+ {#if !allRows.length && !(opt.loading && opt.loadingOverlay)}
2184
2384
  <tr class="sv-grid-row sv-grid-empty-row">
2185
2385
  <td
2186
2386
  class="sv-grid-cell sv-grid-empty-cell"
@@ -2188,7 +2388,7 @@
2188
2388
  (showRowNumbersEffective ? 1 : 0) +
2189
2389
  (showRowSelectionEffective ? 1 : 0)}
2190
2390
  >
2191
- {props.emptyMessage ?? "No rows to display."}
2391
+ {opt.emptyMessage ?? messages.noRows}
2192
2392
  </td>
2193
2393
  </tr>
2194
2394
  {:else if rowVirtualizationEnabled}
@@ -2207,7 +2407,7 @@
2207
2407
  {@const rowIndex = rowItem.index}
2208
2408
  {@const row = allRows[rowIndex]}
2209
2409
  {#if row}
2210
- {#if props.isDetailRow?.(row.original as TData, rowIndex)}
2410
+ {#if opt.isDetailRow?.(row.original as TData, rowIndex)}
2211
2411
  {@render detailRowMarkup(row, rowIndex)}
2212
2412
  {:else if isGroupRow(row)}
2213
2413
  <tr
@@ -2235,7 +2435,7 @@
2235
2435
  <tr
2236
2436
  class={`sv-grid-row ${userRowClass} ${rowDropClass(rowIndex)}`}
2237
2437
  class:sv-grid-row-selected={isRowSelected(row.id)}
2238
- class:sv-grid-row-alt={props.zebraRows &&
2438
+ class:sv-grid-row-alt={opt.zebraRows &&
2239
2439
  rowIndex % 2 === 1}
2240
2440
  class:sv-grid-row-draggable={rowDragManagedEffective}
2241
2441
  {...getGridRowA11yProps(rowIndex + 1)}
@@ -2459,7 +2659,7 @@
2459
2659
  {/if}
2460
2660
  {:else}
2461
2661
  {#each allRows as row, rowIndex (row.id)}
2462
- {#if props.isDetailRow?.(row.original as TData, rowIndex)}
2662
+ {#if opt.isDetailRow?.(row.original as TData, rowIndex)}
2463
2663
  {@render detailRowMarkup(row, rowIndex)}
2464
2664
  {:else if isGroupRow(row)}
2465
2665
  <tr
@@ -2487,7 +2687,7 @@
2487
2687
  <tr
2488
2688
  class={`sv-grid-row ${userRowClass} ${rowDropClass(rowIndex)}`}
2489
2689
  class:sv-grid-row-selected={isRowSelected(row.id)}
2490
- class:sv-grid-row-alt={props.zebraRows &&
2690
+ class:sv-grid-row-alt={opt.zebraRows &&
2491
2691
  rowIndex % 2 === 1}
2492
2692
  class:sv-grid-row-draggable={rowDragManagedEffective}
2493
2693
  {...getGridRowA11yProps(rowIndex + 1)}
@@ -2688,18 +2888,18 @@
2688
2888
  {/each}
2689
2889
  {/if}
2690
2890
  </tbody>
2691
- {#if props.pinnedBottomRows && props.pinnedBottomRows.length > 0}
2891
+ {#if opt.pinnedBottomRows && opt.pinnedBottomRows.length > 0}
2692
2892
  <!-- svelte-ignore a11y_no_redundant_roles -->
2693
2893
  <tbody
2694
2894
  class="sv-grid-pinned sv-grid-pinned-bottom-body"
2695
2895
  role="rowgroup"
2696
2896
  >
2697
- {#each props.pinnedBottomRows as r, i (i)}
2897
+ {#each opt.pinnedBottomRows as r, i (i)}
2698
2898
  {@render pinnedRowBody(r, "bottom", i)}
2699
2899
  {/each}
2700
2900
  </tbody>
2701
2901
  {/if}
2702
- {#if props.enableRowSummaries ?? true}
2902
+ {#if opt.enableRowSummaries ?? true}
2703
2903
  <!-- svelte-ignore a11y_no_redundant_roles -->
2704
2904
  <tfoot class="sv-grid-foot" role="rowgroup">
2705
2905
  <tr
@@ -2795,7 +2995,7 @@
2795
2995
  content-size={scrollMetrics.scrollHeight ||
2796
2996
  rowDomTotalSize + headerHeight}
2797
2997
  value={scrollMetrics.scrollTop}
2798
- step={typeof props.rowHeight === "number" ? props.rowHeight : 30}
2998
+ step={typeof opt.rowHeight === "number" ? opt.rowHeight : 30}
2799
2999
  style={`top: ${headerHeight}px; height: calc(100% - ${headerHeight + (hasHorizontalOverflow ? 16 : 0)}px);`}
2800
3000
  ></sv-grid-scrollbar>
2801
3001
  {/if}
@@ -2811,7 +3011,7 @@
2811
3011
  viewport-size={viewportWidth}
2812
3012
  content-size={scrollMetrics.scrollWidth || horizontalContentSize}
2813
3013
  value={scrollMetrics.scrollLeft}
2814
- step={props.columnWidth ?? 140}
3014
+ step={opt.columnWidth ?? 140}
2815
3015
  style={`width: calc(100% - ${hasVerticalOverflow ? 16 : 0}px);`}
2816
3016
  ></sv-grid-scrollbar>
2817
3017
  {/if}
@@ -2820,7 +3020,7 @@
2820
3020
  {/if}
2821
3021
  </div>
2822
3022
 
2823
- <GridFooter {ctrl} pager={(props.paginationPosition ?? "bottom") !== "top"} pageSizeOptions={props.pageSizeOptions} />
3023
+ <GridFooter {ctrl} pager={(opt.paginationPosition ?? "bottom") !== "top"} pageSizeOptions={opt.pageSizeOptions} />
2824
3024
 
2825
3025
  {#if ctrl.findOpen}
2826
3026
  <!-- Find-in-grid overlay. Anchored to the TOP of the grid root so
@@ -2928,12 +3128,12 @@
2928
3128
  </div>
2929
3129
  {/if}
2930
3130
 
2931
- {#if props.loading && props.loadingOverlay}
3131
+ {#if opt.loading && opt.loadingOverlay}
2932
3132
  <div class="sv-grid-loading-overlay" role="status" aria-live="polite">
2933
3133
  <div class="sv-grid-loading-bar"></div>
2934
3134
  {#if allRows.length === 0}
2935
3135
  <div class="sv-grid-skeleton" aria-hidden="true">
2936
- {#each Array(props.loadingSkeletonRows ?? 8) as _, r (r)}
3136
+ {#each Array(opt.loadingSkeletonRows ?? 8) as _, r (r)}
2937
3137
  <div class="sv-grid-skeleton-row">
2938
3138
  {#each allColumns as col (col.id)}
2939
3139
  <div
@@ -2971,7 +3171,7 @@
2971
3171
  class:is-active={panelTab === "columns"}
2972
3172
  role="tab"
2973
3173
  aria-selected={panelTab === "columns"}
2974
- onclick={() => (ctrl.toolPanelTab = "columns")}>Columns</button
3174
+ onclick={() => (ctrl.toolPanelTab = "columns")}>{messages.columns}</button
2975
3175
  >
2976
3176
  <button
2977
3177
  type="button"
@@ -2979,7 +3179,7 @@
2979
3179
  class:is-active={panelTab === "filters"}
2980
3180
  role="tab"
2981
3181
  aria-selected={panelTab === "filters"}
2982
- onclick={() => (ctrl.toolPanelTab = "filters")}>Filters</button
3182
+ onclick={() => (ctrl.toolPanelTab = "filters")}>{messages.filters}</button
2983
3183
  >
2984
3184
  </div>
2985
3185
  {#if panelTab === "columns"}
@@ -3050,7 +3250,7 @@
3050
3250
  type="button"
3051
3251
  class="sv-grid-tp-filter-clear"
3052
3252
  aria-label={`Clear ${toolPanelHeaderLabel(column)} filter`}
3053
- title="Clear filter"
3253
+ title={messages.clearFilter}
3054
3254
  onclick={() => clearColumnFilter(column.id)}>✕</button
3055
3255
  >
3056
3256
  {/if}
@@ -3067,7 +3267,7 @@
3067
3267
  >
3068
3268
  {#each operatorsForColumn(column) as option (option.value)}
3069
3269
  <option value={option.value}
3070
- >{operatorOption(option.value).label}</option
3270
+ >{localizeOperatorLabel(operatorOption(option.value), column, messages)}</option
3071
3271
  >
3072
3272
  {/each}
3073
3273
  </select>
@@ -3121,11 +3321,13 @@
3121
3321
  {/if}
3122
3322
  {/if}
3123
3323
 
3124
- {#if ctrl.chartingEnabled && ctrl.chartPanelOpen}
3125
- <SvGridChartPanel {ctrl} />
3324
+ {#if ctrl.chartingEnabled && ctrl.chartPanelOpen && ChartPanelView}
3325
+ <ChartPanelView {ctrl} />
3126
3326
  {/if}
3127
3327
  </div>
3128
3328
  <!-- /.sv-grid-root -->
3129
3329
 
3130
- <GridMenus {ctrl} {icon} />
3330
+ {#if MenusOverlay}
3331
+ <MenusOverlay {ctrl} {icon} />
3332
+ {/if}
3131
3333
  {/if}