@svgrid/grid 2.2.16 → 2.2.18

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
@@ -9,6 +9,8 @@ import type {
9
9
  TableFeatures,
10
10
  } from "./index";
11
11
  import type { ConditionalFormat } from "./conditional-formatting";
12
+ import type { GridMessages } from "./grid-messages";
13
+ import type { GridPivotConfig } from "./pivot-view.svelte";
12
14
  import type { MenuItem } from "./SvMenuList.svelte";
13
15
  import type { RecurrenceRule } from "./recurrence";
14
16
 
@@ -65,6 +67,7 @@ import type {
65
67
  ChartSpec,
66
68
  ChartAnnotation,
67
69
  ChartReferenceLine,
70
+ ChartValueFormat,
68
71
  } from "./chart";
69
72
 
70
73
  /** One aggregated bucket returned by a server-side `getAggregate`. */
@@ -196,7 +199,9 @@ export type ContextMenuTarget<TData extends RowData = RowData> = {
196
199
  /**
197
200
  * A context-menu entry. Either a built-in action key, the `"separator"`
198
201
  * divider, or a custom item. Built-in keys: `"copy" | "cut" | "paste" |
199
- * "clear" | "row_above" | "row_below" | "remove_row" | "remove_col"`.
202
+ * "clear" | "row_above" | "row_below" | "remove_row" | "remove_col" |
203
+ * "chart"`. The `"chart"` item (chart the selected range) is only shown when
204
+ * `charting` is enabled; it is appended to the default menu automatically.
200
205
  */
201
206
  export type ContextMenuItem<TData extends RowData = RowData> =
202
207
  | string
@@ -301,6 +306,58 @@ export type BoardCardMoveEvent<TData extends RowData = RowData> = {
301
306
  * of a table. Dragging a card between lanes fires {@link BoardConfig.onCardMove}
302
307
  * where you reassign the `groupBy` field on your own data.
303
308
  */
309
+ /**
310
+ * Chart view of the grid. Setting the `chart` prop on `<SvGrid>` swaps the table
311
+ * for a chart driven by the grid's FILTERED + SORTED rows - so the search box,
312
+ * column filters and sort all flow through to the chart. Unlike the board and
313
+ * scheduler views, the renderer is free: the grid lazy-loads a built-in
314
+ * `SvChart` view unless a host overrides it via `registerChartView`.
315
+ *
316
+ * The config maps directly onto `rowsToChartSpec` - one row field for the
317
+ * category axis, one or more for the value series (or a `series` field to pivot
318
+ * one series per distinct value).
319
+ *
320
+ * ```svelte
321
+ * <SvGrid {data} {columns}
322
+ * chart={{ type: 'bar', category: 'month', value: 'revenue', reduce: 'sum' }} />
323
+ * ```
324
+ */
325
+ export type ChartViewConfig<
326
+ TFeatures extends TableFeatures = TableFeatures,
327
+ TData extends RowData = RowData,
328
+ > = {
329
+ /** Chart type. Default `'bar'`. */
330
+ type?: ChartType;
331
+ /** Row field for the category (x) axis. */
332
+ category: keyof TData & string;
333
+ /** Row field(s) for the value (y) series. */
334
+ value: (keyof TData & string) | Array<keyof TData & string>;
335
+ /** Pivot dimension: one series per distinct value of this field. */
336
+ series?: keyof TData & string;
337
+ /** Aggregation when several rows share a category. Default `'sum'`. */
338
+ reduce?: "sum" | "avg" | "count";
339
+ /** Stack bar / area series instead of grouping them. */
340
+ stacked?: boolean;
341
+ /** Stack to 100% (implies `stacked`). */
342
+ stacked100?: boolean;
343
+ /** Order categories. Default: insertion order (value-desc when `topN` is set). */
344
+ sort?: "value-desc" | "value-asc" | "category" | "none";
345
+ /** Keep only the top N categories; bucket the rest into "Other". */
346
+ topN?: number;
347
+ /** Palette for series without an explicit colour. */
348
+ palette?: string[];
349
+ /** Number format for the value axis, tooltips and data labels. */
350
+ valueFormat?: ChartValueFormat;
351
+ /** Show the clickable legend. Default `true`. */
352
+ legend?: boolean;
353
+ /** Draw the value on each bar / point / slice. Default `false`. */
354
+ dataLabels?: boolean;
355
+ /** Show the search box above the chart (filters rows first). Default `true`. */
356
+ searchable?: boolean;
357
+ /** Placeholder for the search box. */
358
+ searchPlaceholder?: string;
359
+ };
360
+
304
361
  export type BoardConfig<TFeatures extends TableFeatures = TableFeatures, TData extends RowData = RowData> = {
305
362
  /** Field whose value buckets each row into a lane. */
306
363
  groupBy: keyof TData & string;
@@ -581,6 +638,12 @@ export type SchedulerException = {
581
638
  end?: string | number | Date;
582
639
  title?: string;
583
640
  allDay?: boolean;
641
+ /**
642
+ * Per-occurrence overrides for ANY other field (e.g. attendees, calendar,
643
+ * color, resource). Merged over the row for just this occurrence, so "This
644
+ * event" can change fields beyond start / end / title / all-day.
645
+ */
646
+ fields?: Record<string, unknown>;
584
647
  };
585
648
 
586
649
  /** How a change to a recurring event should apply. */
@@ -907,6 +970,30 @@ export type Props<TFeatures extends TableFeatures = TableFeatures, TData extends
907
970
  * {@link SchedulerConfig}.
908
971
  */
909
972
  scheduler?: SchedulerConfig<TFeatures, TData>;
973
+ /**
974
+ * Chart view. When set, the grid renders its FILTERED + SORTED rows as a chart
975
+ * instead of a table (search / filters / sort flow through). Unlike board and
976
+ * scheduler, the renderer is free - the grid lazy-loads a built-in `SvChart`
977
+ * view, overridable via `registerChartView`. See {@link ChartViewConfig}.
978
+ */
979
+ chart?: ChartViewConfig<TFeatures, TData>;
980
+ /**
981
+ * Pivot mode. When set (and `pivotMode` is on), the grid renders its rows as a
982
+ * pivot table in place - the same grid, aggregated across `pivot.rows` /
983
+ * `pivot.cols` with nested column headers - instead of the flat table. The
984
+ * pivot ENGINE ships in `@svgrid/enterprise`; call `enablePivot()` (or
985
+ * `installEnterprise(api)`) to register it, otherwise an upsell note shows.
986
+ * See {@link GridPivotConfig}.
987
+ */
988
+ pivot?: GridPivotConfig<TData>;
989
+ /**
990
+ * Whether pivot mode is currently active. Defaults to `true` when `pivot` is
991
+ * set. Bindable so a toolbar toggle can flip between the pivot and the flat
992
+ * table over the same data.
993
+ */
994
+ pivotMode?: boolean;
995
+ /** Fired when the in-grid Pivot toggle flips `pivotMode`. */
996
+ onPivotModeChange?: (on: boolean) => void;
910
997
  /**
911
998
  * Right-click context menu. `true` shows the default item set (copy, cut,
912
999
  * paste, clear, insert row above/below, remove row, remove column). Pass an
@@ -957,6 +1044,24 @@ export type Props<TFeatures extends TableFeatures = TableFeatures, TData extends
957
1044
  loadingSkeletonRows?: number;
958
1045
  error?: string | null;
959
1046
  emptyMessage?: string;
1047
+ /**
1048
+ * The single place to localize the grid. One object with two fields:
1049
+ *
1050
+ * - `locale` - BCP-47 tag(s) for the DATA: accent/case-insensitive filter
1051
+ * matching AND every column's number / currency / percent / date formatting
1052
+ * (when the column's own `format.locales` is unset). The default for
1053
+ * `filterLocale` and per-column format locales.
1054
+ * - `text` - overrides for the grid's own UI STRINGS (empty state, tool panel,
1055
+ * pager, status bar, filter operator labels, context-menu items, upsell
1056
+ * notes). Any subset overrides the English defaults; unset keys stay English.
1057
+ *
1058
+ * ```svelte
1059
+ * <SvGrid localization={{ locale: 'fr-FR', text: { noRows: 'Aucune ligne' } }} />
1060
+ * ```
1061
+ *
1062
+ * Omitting it (or any field) is a no-op. See {@link GridMessages}.
1063
+ */
1064
+ localization?: GridLocalization;
960
1065
  showGlobalFilter?: boolean;
961
1066
  showColumnFilters?: boolean;
962
1067
  /**
@@ -1177,6 +1282,13 @@ export type Props<TFeatures extends TableFeatures = TableFeatures, TData extends
1177
1282
  * consumer wants to own the row ordering.
1178
1283
  */
1179
1284
  onSortingChange?: (sorting: Array<{ id: string; desc: boolean }>) => void;
1285
+ /**
1286
+ * The sort state to start in - `{ id, desc }` entries. Use with `externalSort`
1287
+ * when the initial ordering is decided server-side (e.g. a URL `?sort=` param
1288
+ * read in a SvelteKit `load`), so the header sort indicators match the already-
1289
+ * sorted data on first render. Applied once at mount; user sorting takes over.
1290
+ */
1291
+ initialSorting?: Array<{ id: string; desc: boolean }>;
1180
1292
  /**
1181
1293
  * When `true`, the grid still records column-filter / global-filter /
1182
1294
  * facet state (so the menu UI works and indicators light up) but does
@@ -1455,6 +1567,18 @@ export type Props<TFeatures extends TableFeatures = TableFeatures, TData extends
1455
1567
  filterLocale?: string | ReadonlyArray<string>;
1456
1568
  };
1457
1569
 
1570
+ /**
1571
+ * The grid's single localization surface (see {@link Props.localization}):
1572
+ * `locale` handles the data (filter matching + number/date formatting) and
1573
+ * `text` handles the UI strings.
1574
+ */
1575
+ export type GridLocalization = {
1576
+ /** BCP-47 tag(s) for filter matching + number / date formatting. */
1577
+ locale?: string | ReadonlyArray<string>;
1578
+ /** Overrides for the grid's own UI strings. */
1579
+ text?: Partial<GridMessages>;
1580
+ };
1581
+
1458
1582
  export type SelectionPoint = { rowIndex: number; colIndex: number };
1459
1583
  export type SelectionRange = {
1460
1584
  anchor: SelectionPoint | null;
@@ -0,0 +1,70 @@
1
+ <script lang="ts">
2
+ /**
3
+ * SvGridChartView - the built-in renderer for the grid's `chart` view. It is a
4
+ * thin adapter: take the grid's filtered + sorted rows, map the ChartViewConfig
5
+ * onto `rowsToChartSpec`, and render the standalone SvChart (SvGridChart) sized
6
+ * to fill the container. This is the piece that makes "chart" a view of the
7
+ * grid, and it stays a thin wrapper precisely because the chart primitive is
8
+ * reusable on its own (unlike the board / scheduler renderers).
9
+ *
10
+ * The grid lazy-loads this by default; a host can replace it via
11
+ * `registerChartView` when it needs a richer renderer.
12
+ */
13
+ import SvGridChart from "./SvGridChart.svelte";
14
+ import { rowsToChartSpec, type ChartSpec } from "./chart";
15
+ import type { ChartViewConfig } from "./SvGrid.types";
16
+
17
+ let {
18
+ data,
19
+ chart,
20
+ }: {
21
+ data: ReadonlyArray<Record<string, unknown>>;
22
+ /** Present for parity with board/scheduler renderers; unused here. */
23
+ columns?: unknown;
24
+ getRowId?: unknown;
25
+ chart: ChartViewConfig;
26
+ } = $props();
27
+
28
+ // Container size -> chart viewBox, so the chart fills the grid area and
29
+ // re-lays out on resize (the same responsive behaviour a table view has).
30
+ let w = $state(0);
31
+ let h = $state(0);
32
+
33
+ const spec = $derived.by<ChartSpec>(() => {
34
+ const s = rowsToChartSpec((data ?? []) as ReadonlyArray<Record<string, unknown>>, {
35
+ type: chart.type ?? "bar",
36
+ category: chart.category,
37
+ value: chart.value,
38
+ series: chart.series,
39
+ reduce: chart.reduce,
40
+ stacked: chart.stacked,
41
+ stacked100: chart.stacked100,
42
+ sort: chart.sort,
43
+ topN: chart.topN,
44
+ palette: chart.palette,
45
+ });
46
+ if (chart.valueFormat) s.valueFormat = chart.valueFormat;
47
+ return s;
48
+ });
49
+ </script>
50
+
51
+ <div class="sv-grid-chart-view" bind:clientWidth={w} bind:clientHeight={h}>
52
+ {#if w > 0 && h > 0}
53
+ <SvGridChart
54
+ {spec}
55
+ width={w}
56
+ height={h}
57
+ legend={chart.legend ?? true}
58
+ dataLabels={chart.dataLabels ?? false}
59
+ />
60
+ {/if}
61
+ </div>
62
+
63
+ <style>
64
+ .sv-grid-chart-view {
65
+ width: 100%;
66
+ height: 100%;
67
+ min-height: 0;
68
+ box-sizing: border-box;
69
+ }
70
+ </style>
@@ -64,6 +64,13 @@
64
64
  return index >= 0 && index < visibleOptions.length ? `${instanceId}-opt-${index}` : undefined
65
65
  }
66
66
 
67
+ // Options that carry a `color` render as full pills (see the option list
68
+ // below), which are taller than a plain text row. The panel-sizing math must
69
+ // reserve that height, otherwise the panel is capped to the plain-row estimate
70
+ // and clips the last option (e.g. a 3-item coloured list). ~40px per chip row
71
+ // vs ~32px for plain text.
72
+ const optionRowHeight = $derived(options.some((o) => o.color) ? 40 : 32)
73
+
67
74
  let searchQuery = $state('')
68
75
  const visibleOptions = $derived(
69
76
  !searchable || !searchQuery.trim()
@@ -153,7 +160,7 @@
153
160
  // Use the smaller of (option count, 10) for the upward-flip math so
154
161
  // a 3-option list doesn't think it needs 320px of headroom.
155
162
  const visibleCount = Math.min(options.length, 10)
156
- const estimatedHeight = visibleCount * 32 + (multiple ? 40 : 0) + 8
163
+ const estimatedHeight = visibleCount * optionRowHeight + (multiple ? 40 : 0) + 8
157
164
  panelRect = anchoredRect(triggerEl.getBoundingClientRect(), {
158
165
  estimatedHeight,
159
166
  // Preserve the original behavior: anchor to the trigger, no clamping.
@@ -381,7 +388,7 @@
381
388
  <!-- Cap to the comfortable 10-row height AND the room the viewport allows,
382
389
  so a panel near the bottom edge scrolls instead of overflowing. -->
383
390
  {@const panelMax = Math.min(
384
- needsScroll ? 10 * 32 + (multiple ? 40 : 0) + 8 : Number.POSITIVE_INFINITY,
391
+ needsScroll ? 10 * optionRowHeight + (multiple ? 40 : 0) + 8 : Number.POSITIVE_INFINITY,
385
392
  panelRect.maxHeight,
386
393
  )}
387
394
  <div
@@ -21,7 +21,7 @@
21
21
 
22
22
  type Props = Pick<
23
23
  SvEditorProps,
24
- 'disabled' | 'label' | 'hint' | 'error' | 'required' | 'invalid' | 'size' | 'id' | 'name' | 'dir' | 'ariaLabel'
24
+ 'disabled' | 'readonly' | 'label' | 'hint' | 'error' | 'required' | 'invalid' | 'size' | 'id' | 'name' | 'dir' | 'ariaLabel' | 'loading'
25
25
  > & {
26
26
  columns: ReadonlyArray<GridSelectColumn>
27
27
  options: ReadonlyArray<Row>
@@ -55,6 +55,7 @@
55
55
  debounceMs = 250,
56
56
  loadingText = 'Loading…',
57
57
  disabled = false,
58
+ readonly = false,
58
59
  label,
59
60
  hint,
60
61
  error,
@@ -65,6 +66,7 @@
65
66
  name,
66
67
  dir,
67
68
  ariaLabel,
69
+ loading: loadingProp = false,
68
70
  }: Props = $props()
69
71
 
70
72
  const autoId = nextEditorId('sv-gs')
@@ -106,6 +108,7 @@
106
108
 
107
109
  const gs = createPopoverSelect({
108
110
  itemCount: () => filtered.length,
111
+ readonly: () => readonly,
109
112
  onSelect: (i) => {
110
113
  const r = filtered[i]
111
114
  if (r) { value = r[idField] as string | number; onChange?.(r[idField] as string | number, r) }
@@ -122,7 +125,7 @@
122
125
  })
123
126
  </script>
124
127
 
125
- <SvField id={uid} {label} {hint} {error} {required} {dir}>
128
+ <SvField id={uid} {label} {hint} {error} {required} {dir} loading={loadingProp || loading}>
126
129
  <div class="sv-gs sv-gs--{size}" class:is-disabled={disabled}>
127
130
  <button
128
131
  bind:this={triggerEl}
@@ -0,0 +1,41 @@
1
+ <script lang="ts">
2
+ /**
3
+ * SvGroup - a horizontal flex layout primitive: lays children in a row with a
4
+ * consistent `gap`, alignment, and optional wrapping. The row counterpart to
5
+ * SvStack - toolbars, button clusters, inline label + control.
6
+ *
7
+ * ```svelte
8
+ * <SvGroup gap={8} justify="between"><Title /><Actions /></SvGroup>
9
+ * ```
10
+ */
11
+ import type { Snippet } from 'svelte'
12
+
13
+ type Props = {
14
+ /** Gap between children (px, or any CSS length). Default 8. */
15
+ gap?: number | string
16
+ /** Cross-axis alignment. Default `center`. */
17
+ align?: 'start' | 'center' | 'end' | 'stretch' | 'baseline'
18
+ /** Main-axis distribution. */
19
+ justify?: 'start' | 'center' | 'end' | 'between' | 'around'
20
+ /** Allow wrapping to multiple rows. */
21
+ wrap?: boolean
22
+ /** Give every child `flex: 1` so they share the width evenly. */
23
+ grow?: boolean
24
+ as?: string
25
+ children?: Snippet
26
+ }
27
+
28
+ let { gap = 8, align = 'center', justify = 'start', wrap = false, grow = false, as = 'div', children }: Props = $props()
29
+ const g = $derived(typeof gap === 'number' ? `${gap}px` : gap)
30
+ const alignMap = { start: 'flex-start', center: 'center', end: 'flex-end', stretch: 'stretch', baseline: 'baseline' } as const
31
+ const justifyMap = { start: 'flex-start', center: 'center', end: 'flex-end', between: 'space-between', around: 'space-around' } as const
32
+ </script>
33
+
34
+ <svelte:element this={as} class="sv-group" class:is-grow={grow} style:gap={g} style:flex-wrap={wrap ? 'wrap' : 'nowrap'} style:align-items={alignMap[align]} style:justify-content={justifyMap[justify]}>
35
+ {@render children?.()}
36
+ </svelte:element>
37
+
38
+ <style>
39
+ .sv-group { display: flex; flex-direction: row; min-width: 0; }
40
+ .sv-group.is-grow > :global(*) { flex: 1 1 0; min-width: 0; }
41
+ </style>
@@ -0,0 +1,70 @@
1
+ <script lang="ts">
2
+ /**
3
+ * SvHoverCard - a rich preview card that opens when the pointer rests on its
4
+ * anchor (a user chip, a link) and closes shortly after it leaves. Built on the
5
+ * shared positioning engine via SvPopover, so it takes any `placement`, flips
6
+ * and shifts to stay in view, and the card itself is hoverable (you can move the
7
+ * pointer onto it). For keyboard/touch users, prefer SvPopover with a click
8
+ * trigger - a hover card is a pointer affordance.
9
+ *
10
+ * ```svelte
11
+ * <SvHoverCard>
12
+ * {#snippet anchor()}<a href="/u/ada">@ada</a>{/snippet}
13
+ * <strong>Ada Lovelace</strong>
14
+ * <p>Analyst, first programmer.</p>
15
+ * </SvHoverCard>
16
+ * ```
17
+ */
18
+ import type { Snippet } from 'svelte'
19
+ import SvPopover from './SvPopover.svelte'
20
+ import type { Placement } from './positioning'
21
+
22
+ type Props = {
23
+ /** Controlled open state (bindable). */
24
+ open?: boolean
25
+ onOpenChange?: (open: boolean) => void
26
+ /** Preferred placement; flips when there is no room. Default `bottom-start`. */
27
+ placement?: Placement
28
+ /** Delay (ms) before the card opens on hover. Default 250. */
29
+ openDelay?: number
30
+ /** Delay (ms) before it closes after the pointer leaves. Default 180. */
31
+ closeDelay?: number
32
+ /** Show a pointer arrow. Default false (cards usually read cleaner without). */
33
+ arrow?: boolean
34
+ /** Force a minimum card width. */
35
+ minWidth?: number
36
+ ariaLabel?: string
37
+ /** The element the card previews. */
38
+ anchor?: Snippet
39
+ /** Card content. */
40
+ children?: Snippet
41
+ }
42
+
43
+ let {
44
+ open = $bindable(false),
45
+ onOpenChange,
46
+ placement = 'bottom-start',
47
+ openDelay = 250,
48
+ closeDelay = 180,
49
+ arrow = false,
50
+ minWidth = 240,
51
+ ariaLabel,
52
+ anchor,
53
+ children,
54
+ }: Props = $props()
55
+ </script>
56
+
57
+ <SvPopover
58
+ bind:open
59
+ {onOpenChange}
60
+ trigger="hover"
61
+ {placement}
62
+ {openDelay}
63
+ {closeDelay}
64
+ {arrow}
65
+ {minWidth}
66
+ {ariaLabel}
67
+ {anchor}
68
+ >
69
+ {@render children?.()}
70
+ </SvPopover>
@@ -0,0 +1,51 @@
1
+ <script lang="ts">
2
+ /**
3
+ * SvKbd - a keyboard-key hint. Pass `keys` for a combo (joined with the OS
4
+ * separator), or a single `children` label.
5
+ *
6
+ * <SvKbd keys={['Ctrl', 'K']} /> · <SvKbd>Esc</SvKbd>
7
+ */
8
+ import type { Snippet } from 'svelte'
9
+
10
+ type Props = {
11
+ /** Key sequence, rendered as separate caps. */
12
+ keys?: string[]
13
+ /** Separator between keys. */
14
+ separator?: string
15
+ size?: 'sm' | 'md'
16
+ children?: Snippet
17
+ }
18
+
19
+ let { keys, separator = '+', size = 'md', children }: Props = $props()
20
+ </script>
21
+
22
+ {#if keys}
23
+ <span class="sv-kbd-group sv-kbd--{size}">
24
+ {#each keys as k, i}
25
+ {#if i > 0}<span class="sv-kbd__sep" aria-hidden="true">{separator}</span>{/if}
26
+ <kbd class="sv-kbd">{k}</kbd>
27
+ {/each}
28
+ </span>
29
+ {:else}
30
+ <kbd class="sv-kbd sv-kbd--{size}">{@render children?.()}</kbd>
31
+ {/if}
32
+
33
+ <style>
34
+ .sv-kbd-group { display: inline-flex; align-items: center; gap: 3px; }
35
+ .sv-kbd {
36
+ display: inline-block;
37
+ min-width: 1.4em;
38
+ padding: 1px 6px;
39
+ font-family: var(--sg-font-mono, ui-monospace, SFMono-Regular, Menlo, monospace);
40
+ font-size: 12px;
41
+ line-height: 1.5;
42
+ text-align: center;
43
+ color: var(--sg-fg, #0f172a);
44
+ background: var(--sg-muted-bg, color-mix(in srgb, var(--sg-fg, #0f172a) 7%, var(--sg-bg, #fff)));
45
+ border: 1px solid var(--sg-border, #e2e8f0);
46
+ border-bottom-width: 2px;
47
+ border-radius: 5px;
48
+ }
49
+ .sv-kbd--sm { font-size: 11px; padding: 0 4px; }
50
+ .sv-kbd__sep { color: var(--sg-muted, #64748b); font-size: 11px; }
51
+ </style>
@@ -0,0 +1,55 @@
1
+ <script lang="ts">
2
+ /**
3
+ * SvList - a themed ordered / unordered / unstyled list. Pass `items` for the
4
+ * simple case, or a `children` snippet for full control over each `<li>`.
5
+ *
6
+ * <SvList items={['One', 'Two', 'Three']} />
7
+ * <SvList type="ordered" spacing="lg" items={steps} />
8
+ */
9
+ import type { Snippet } from 'svelte'
10
+
11
+ type Props = {
12
+ /** Marker style. `none` drops markers + indentation. */
13
+ type?: 'unordered' | 'ordered' | 'none'
14
+ /** Simple string items (skip the snippet). */
15
+ items?: string[]
16
+ /** Vertical gap between items. */
17
+ spacing?: 'sm' | 'md' | 'lg'
18
+ /** Font size step. */
19
+ size?: 'sm' | 'md' | 'lg'
20
+ /** Custom list content (`<li>` elements). Overrides `items`. */
21
+ children?: Snippet
22
+ }
23
+
24
+ let { type = 'unordered', items, spacing = 'md', size = 'md', children }: Props = $props()
25
+
26
+ const gapMap = { sm: '2px', md: '6px', lg: '10px' } as const
27
+ const sizeMap = { sm: '13px', md: '14px', lg: '16px' } as const
28
+ const tag = $derived(type === 'ordered' ? 'ol' : 'ul')
29
+ </script>
30
+
31
+ <svelte:element
32
+ this={tag}
33
+ class="sv-list sv-list--{type}"
34
+ style:--sv-list-gap={gapMap[spacing]}
35
+ style:font-size={sizeMap[size]}
36
+ >
37
+ {#if children}
38
+ {@render children()}
39
+ {:else if items}
40
+ {#each items as item}<li>{item}</li>{/each}
41
+ {/if}
42
+ </svelte:element>
43
+
44
+ <style>
45
+ .sv-list {
46
+ margin: 0;
47
+ font-family: var(--sg-font, inherit);
48
+ color: var(--sg-fg, #0f172a);
49
+ line-height: 1.5;
50
+ }
51
+ .sv-list--unordered, .sv-list--ordered { padding-left: 1.4em; }
52
+ .sv-list--none { padding-left: 0; list-style: none; }
53
+ .sv-list :global(li) { margin-top: var(--sv-list-gap, 6px); }
54
+ .sv-list :global(li:first-child) { margin-top: 0; }
55
+ </style>