@svgrid/grid 3.0.2 → 3.0.4

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 (281) hide show
  1. package/README.md +2 -1
  2. package/dist/GridMenus.svelte +44 -2
  3. package/dist/SvChartMenu.svelte +69 -0
  4. package/dist/SvChartMenu.svelte.d.ts +11 -0
  5. package/dist/SvChartPanes.svelte +113 -0
  6. package/dist/SvChartPanes.svelte.d.ts +20 -0
  7. package/dist/SvGrid.controller.svelte.d.ts +110 -39
  8. package/dist/SvGrid.controller.svelte.js +655 -200
  9. package/dist/SvGrid.css +105 -2
  10. package/dist/SvGrid.svelte +386 -514
  11. package/dist/SvGrid.types.d.ts +210 -9
  12. package/dist/SvGridCellEditor.svelte +17 -0
  13. package/dist/SvGridChart.svelte +2257 -329
  14. package/dist/SvGridChart.svelte.d.ts +6 -106
  15. package/dist/SvGridChart.types.d.ts +338 -0
  16. package/dist/SvGridChart.types.js +1 -0
  17. package/dist/SvGridChartBuilder.svelte +323 -0
  18. package/dist/SvGridChartBuilder.svelte.d.ts +34 -0
  19. package/dist/SvGridChartPanel.svelte +221 -275
  20. package/dist/SvGridChartPickers.svelte +417 -0
  21. package/dist/SvGridChartPickers.svelte.d.ts +70 -0
  22. package/dist/SvGridChartView.svelte +13 -14
  23. package/dist/SvModal.svelte +7 -1
  24. package/dist/SvModal.svelte.d.ts +5 -0
  25. package/dist/ai.d.ts +40 -8
  26. package/dist/ai.js +135 -24
  27. package/dist/aria.d.ts +11 -0
  28. package/dist/build-api.js +108 -22
  29. package/dist/cdn/GridMenus-7kbpnnBW.js +635 -0
  30. package/dist/cdn/GridMenus-BL7ZgQvU.js +636 -0
  31. package/dist/cdn/SvChartMenu-Bl6PBbkT.js +58 -0
  32. package/dist/cdn/SvChartMenu-FBSMINA6.js +59 -0
  33. package/dist/cdn/{SvDateRangeInput-DMLKmGEc.js → SvDateRangeInput-BeU_TkbQ.js} +15 -14
  34. package/dist/cdn/{SvDateRangeInput-CaOuMs8O.js → SvDateRangeInput-yX8vzleW.js} +38 -37
  35. package/dist/cdn/{SvDateTimePicker-sonaH0oh.js → SvDateTimePicker-DQwt4UAs.js} +139 -180
  36. package/dist/cdn/SvDateTimePicker-vNU6bZ-q.js +775 -0
  37. package/dist/cdn/{SvGridCellEditor-CjEJMJKc.js → SvGridCellEditor-B1p-vCK5.js} +188 -178
  38. package/dist/cdn/{SvGridCellEditor-BWnTi2N7.js → SvGridCellEditor-D_0q4xAu.js} +98 -88
  39. package/dist/cdn/SvGridChart-C3EWAZaM.js +3574 -0
  40. package/dist/cdn/SvGridChart-DzLkSwCH.js +3572 -0
  41. package/dist/cdn/SvGridChartBuilder-BE2T1ykB.js +783 -0
  42. package/dist/cdn/SvGridChartBuilder-CfII62sZ.js +784 -0
  43. package/dist/cdn/SvGridChartPanel-CCX5_Wgd.js +675 -0
  44. package/dist/cdn/SvGridChartPanel-xf4sWVTo.js +699 -0
  45. package/dist/cdn/SvGridChartView-CfuXmY5I.js +48 -0
  46. package/dist/cdn/SvGridChartView-DYwabQWj.js +47 -0
  47. package/dist/cdn/SvMenuList-CLN8OuIK.js +452 -0
  48. package/dist/cdn/SvMenuList-DkGhNKjf.js +451 -0
  49. package/dist/cdn/SvModal-BAE-pjZX.js +396 -0
  50. package/dist/cdn/SvModal-CIZWCcad.js +397 -0
  51. package/dist/cdn/chart-Dz7SqMXH.js +4341 -0
  52. package/dist/cdn/chart-export-BXqueeWJ.js +135 -0
  53. package/dist/cdn/chart-export-pdf-DONFUnNY.js +110 -0
  54. package/dist/cdn/chart-panel-messages-CUbf2R4i.js +1052 -0
  55. package/dist/cdn/chart-panel-messages-CmNrMdsr.js +1053 -0
  56. package/dist/cdn/chart-summary-BJW_tg_X.js +138 -0
  57. package/dist/cdn/chart-trend-CaN9mDEV.js +50 -0
  58. package/dist/cdn/chart-validate-HcOVFAfJ.js +188 -0
  59. package/dist/cdn/{column-resize-DsfNXMom.js → column-resize-DpmOLfRp.js} +3 -3
  60. package/dist/cdn/{date-format-BnnHlqGw.js → date-format-CtquV-p3.js} +583 -603
  61. package/dist/cdn/{date-format-BNii4zeD.js → date-format-D6KFzU_W.js} +347 -367
  62. package/dist/cdn/dismissable-DAHetSNk.js +44 -0
  63. package/dist/cdn/editor-contract-LXgQJAgd.js +22 -0
  64. package/dist/cdn/focus-trap-BBOQYBma.js +65 -0
  65. package/dist/cdn/{row-resize-BRcimkUT.js → row-resize-niQCp040.js} +44 -36
  66. package/dist/cdn/{src-DNbz94Ct.js → src-BKhZ6eXd.js} +10227 -9787
  67. package/dist/cdn/{src-BJ2opd0j.js → src-V1uu8iE9.js} +6568 -6128
  68. package/dist/cdn/svgrid.js +26 -15
  69. package/dist/cdn/svgrid.svelte-external.js +26 -15
  70. package/dist/chart-axes.d.ts +53 -0
  71. package/dist/chart-axes.js +351 -0
  72. package/dist/chart-cartesian.d.ts +88 -0
  73. package/dist/chart-cartesian.js +1862 -0
  74. package/dist/chart-decimate.d.ts +51 -0
  75. package/dist/chart-decimate.js +199 -0
  76. package/dist/chart-export-pdf.d.ts +47 -0
  77. package/dist/chart-export-pdf.js +187 -0
  78. package/dist/chart-export.d.ts +2 -1
  79. package/dist/chart-export.js +18 -3
  80. package/dist/chart-financial.d.ts +91 -0
  81. package/dist/chart-financial.js +175 -0
  82. package/dist/chart-flow.d.ts +10 -0
  83. package/dist/chart-flow.js +298 -0
  84. package/dist/chart-format.d.ts +18 -0
  85. package/dist/chart-format.js +65 -0
  86. package/dist/chart-grid.d.ts +8 -0
  87. package/dist/chart-grid.js +190 -0
  88. package/dist/chart-hierarchy.d.ts +17 -0
  89. package/dist/chart-hierarchy.js +146 -0
  90. package/dist/chart-indicators.d.ts +115 -0
  91. package/dist/chart-indicators.js +389 -0
  92. package/dist/chart-messages.d.ts +95 -0
  93. package/dist/chart-messages.js +92 -0
  94. package/dist/chart-motion.d.ts +16 -0
  95. package/dist/chart-motion.js +141 -0
  96. package/dist/chart-panel-messages.d.ts +265 -0
  97. package/dist/chart-panel-messages.js +285 -0
  98. package/dist/chart-pivot.d.ts +87 -0
  99. package/dist/chart-pivot.js +156 -0
  100. package/dist/chart-polar.d.ts +25 -0
  101. package/dist/chart-polar.js +700 -0
  102. package/dist/chart-samples.d.ts +16 -0
  103. package/dist/chart-samples.js +153 -0
  104. package/dist/chart-scale.d.ts +113 -0
  105. package/dist/chart-scale.js +405 -0
  106. package/dist/chart-stats.d.ts +111 -0
  107. package/dist/chart-stats.js +419 -0
  108. package/dist/chart-stream.d.ts +45 -0
  109. package/dist/chart-stream.js +91 -0
  110. package/dist/chart-summary.d.ts +27 -0
  111. package/dist/chart-summary.js +205 -0
  112. package/dist/chart-sync.svelte.d.ts +32 -0
  113. package/dist/chart-sync.svelte.js +23 -0
  114. package/dist/chart-table.d.ts +35 -0
  115. package/dist/chart-table.js +165 -0
  116. package/dist/chart-trend.d.ts +19 -0
  117. package/dist/chart-trend.js +61 -0
  118. package/dist/chart-types.d.ts +1456 -0
  119. package/dist/chart-types.js +6 -0
  120. package/dist/chart-validate.d.ts +43 -0
  121. package/dist/chart-validate.js +272 -0
  122. package/dist/chart-zoom.d.ts +40 -0
  123. package/dist/chart-zoom.js +145 -0
  124. package/dist/chart.d.ts +186 -865
  125. package/dist/chart.js +460 -2204
  126. package/dist/clipboard.d.ts +1 -0
  127. package/dist/clipboard.js +137 -18
  128. package/dist/column-resize.d.ts +3 -0
  129. package/dist/column-resize.js +4 -1
  130. package/dist/columns.js +3 -0
  131. package/dist/command-context.d.ts +19 -0
  132. package/dist/command-context.js +116 -0
  133. package/dist/core.d.ts +7 -0
  134. package/dist/createPopoverSelect.svelte.d.ts +2 -2
  135. package/dist/editing.d.ts +2 -8
  136. package/dist/editing.js +262 -33
  137. package/dist/fill-patterns.d.ts +0 -5
  138. package/dist/fill-patterns.js +56 -2
  139. package/dist/grid-messages.d.ts +10 -3
  140. package/dist/grid-messages.js +5 -0
  141. package/dist/history.d.ts +83 -0
  142. package/dist/history.js +133 -0
  143. package/dist/index.d.ts +24 -6
  144. package/dist/index.js +20 -2
  145. package/dist/keyboard-handlers.js +88 -31
  146. package/dist/keyboard.d.ts +55 -0
  147. package/dist/keyboard.js +132 -0
  148. package/dist/menus.d.ts +3 -1
  149. package/dist/menus.js +7 -2
  150. package/dist/merges.d.ts +97 -0
  151. package/dist/merges.js +147 -0
  152. package/dist/row-resize.d.ts +3 -0
  153. package/dist/row-resize.js +14 -0
  154. package/dist/scroll-sync.d.ts +1 -0
  155. package/dist/scroll-sync.js +24 -0
  156. package/dist/selection.d.ts +16 -0
  157. package/dist/selection.js +108 -16
  158. package/dist/shortcut-registry.d.ts +145 -0
  159. package/dist/shortcut-registry.js +44 -0
  160. package/dist/svgrid-wrapper.types.d.ts +213 -22
  161. package/dist/virtualization/virtualizer.js +38 -17
  162. package/package.json +6 -1
  163. package/src/GridMenus.svelte +44 -2
  164. package/src/SvChartMenu.svelte +69 -0
  165. package/src/SvChartPanes.svelte +113 -0
  166. package/src/SvChartPanes.test.ts +66 -0
  167. package/src/SvGrid.controller.svelte.ts +629 -172
  168. package/src/SvGrid.css +105 -2
  169. package/src/SvGrid.svelte +386 -514
  170. package/src/SvGrid.types.ts +188 -8
  171. package/src/SvGridCellEditor.svelte +17 -0
  172. package/src/SvGridChart.svelte +2257 -329
  173. package/src/SvGridChart.test.ts +1419 -1
  174. package/src/SvGridChart.types.ts +336 -0
  175. package/src/SvGridChartBuilder.svelte +323 -0
  176. package/src/SvGridChartPanel.svelte +221 -275
  177. package/src/SvGridChartPickers.svelte +417 -0
  178. package/src/SvGridChartView.svelte +13 -14
  179. package/src/SvModal.svelte +7 -1
  180. package/src/SvModal.test.ts +9 -0
  181. package/src/ai.test.ts +57 -2
  182. package/src/ai.ts +166 -22
  183. package/src/aria.d.ts +11 -0
  184. package/src/build-api.coverage.test.ts +184 -0
  185. package/src/build-api.ts +107 -18
  186. package/src/chart-axes.test.ts +573 -0
  187. package/src/chart-axes.ts +342 -0
  188. package/src/chart-cartesian.ts +1863 -0
  189. package/src/chart-decimate.test.ts +249 -0
  190. package/src/chart-decimate.ts +186 -0
  191. package/src/chart-export-pdf.test.ts +91 -0
  192. package/src/chart-export-pdf.ts +207 -0
  193. package/src/chart-export.test.ts +14 -0
  194. package/src/chart-export.ts +13 -3
  195. package/src/chart-financial.ts +208 -0
  196. package/src/chart-flow.ts +286 -0
  197. package/src/chart-format.ts +67 -0
  198. package/src/chart-grid.ts +179 -0
  199. package/src/chart-hierarchy.ts +135 -0
  200. package/src/chart-indicators.test.ts +443 -0
  201. package/src/chart-indicators.ts +384 -0
  202. package/src/chart-messages.test.ts +21 -0
  203. package/src/chart-messages.ts +184 -0
  204. package/src/chart-motion.test.ts +71 -0
  205. package/src/chart-motion.ts +148 -0
  206. package/src/chart-panel-messages.test.ts +29 -0
  207. package/src/chart-panel-messages.ts +550 -0
  208. package/src/chart-pivot.test.ts +54 -0
  209. package/src/chart-pivot.ts +225 -0
  210. package/src/chart-polar.ts +674 -0
  211. package/src/chart-samples.ts +106 -0
  212. package/src/chart-scale.ts +394 -0
  213. package/src/chart-series-types.test.ts +714 -0
  214. package/src/chart-stats.ts +409 -0
  215. package/src/chart-stream.test.ts +75 -0
  216. package/src/chart-stream.ts +114 -0
  217. package/src/chart-summary.test.ts +90 -0
  218. package/src/chart-summary.ts +197 -0
  219. package/src/chart-sync.svelte.ts +41 -0
  220. package/src/chart-table.test.ts +76 -0
  221. package/src/chart-table.ts +178 -0
  222. package/src/chart-trend.ts +47 -0
  223. package/src/chart-types.ts +1309 -0
  224. package/src/chart-validate.test.ts +100 -0
  225. package/src/chart-validate.ts +247 -0
  226. package/src/chart-zoom.test.ts +137 -0
  227. package/src/chart-zoom.ts +124 -0
  228. package/src/chart.coverage.test.ts +81 -0
  229. package/src/chart.test.ts +56 -3
  230. package/src/chart.ts +557 -2784
  231. package/src/clipboard.test.ts +151 -0
  232. package/src/clipboard.ts +145 -16
  233. package/src/column-resize.ts +7 -1
  234. package/src/columns.ts +2 -0
  235. package/src/command-context.test.ts +200 -0
  236. package/src/command-context.ts +137 -0
  237. package/src/core.ts +7 -0
  238. package/src/editing.test.ts +281 -3
  239. package/src/editing.ts +256 -38
  240. package/src/fill-patterns.test.ts +35 -0
  241. package/src/fill-patterns.ts +56 -2
  242. package/src/grid-messages.ts +16 -3
  243. package/src/history.test.ts +196 -0
  244. package/src/history.ts +162 -0
  245. package/src/icon-seam.test.ts +3 -2
  246. package/src/index.ts +150 -2
  247. package/src/keyboard-handlers.coverage.test.ts +126 -6
  248. package/src/keyboard-handlers.ts +91 -30
  249. package/src/keyboard-shortcuts.seam.test.ts +200 -0
  250. package/src/keyboard.test.ts +124 -1
  251. package/src/keyboard.ts +142 -0
  252. package/src/menus.test.ts +26 -0
  253. package/src/menus.ts +10 -3
  254. package/src/merges.test.ts +112 -0
  255. package/src/merges.ts +168 -0
  256. package/src/pivot.grid.test.ts +40 -5
  257. package/src/row-resize.test.ts +44 -0
  258. package/src/row-resize.ts +17 -0
  259. package/src/scroll-sync.test.ts +42 -1
  260. package/src/scroll-sync.ts +25 -0
  261. package/src/selection.multi-range.test.ts +34 -0
  262. package/src/selection.test.ts +30 -2
  263. package/src/selection.ts +111 -19
  264. package/src/shortcut-registry.test.ts +97 -0
  265. package/src/shortcut-registry.ts +181 -0
  266. package/src/svgrid-wrapper.types.ts +184 -13
  267. package/src/svgrid.behavior.test.ts +135 -0
  268. package/src/svgrid.charting.test.ts +513 -3
  269. package/src/svgrid.context-menu.test.ts +31 -0
  270. package/src/svgrid.new-features.wrapper.test.ts +10 -3
  271. package/src/virtualization/virtualizer.ts +39 -17
  272. package/dist/cdn/GridMenus-DyFA-QxA.js +0 -602
  273. package/dist/cdn/GridMenus-M2XP9t0_.js +0 -603
  274. package/dist/cdn/SvDateTimePicker-CCbDZNZB.js +0 -816
  275. package/dist/cdn/SvGridChart-DAb9RbRs.js +0 -1480
  276. package/dist/cdn/SvGridChart-Yl-IXZFO.js +0 -1481
  277. package/dist/cdn/SvGridChartPanel-DayQpDsR.js +0 -834
  278. package/dist/cdn/SvGridChartPanel-aqf8n-vJ.js +0 -810
  279. package/dist/cdn/SvGridChartView-CxfakxR0.js +0 -56
  280. package/dist/cdn/SvGridChartView-Dm_YEx9L.js +0 -55
  281. package/dist/cdn/chart-CKJRCPOk.js +0 -1652
@@ -0,0 +1,145 @@
1
+ /**
2
+ * shortcut-registry - the injection seam for keyboard commands the free grid
3
+ * does not implement. `@svgrid/grid` owns cell navigation, copy/paste, undo and
4
+ * find; the Excel command set (Ctrl+Arrow to the edge of a data region, Ctrl+D
5
+ * fill down, Ctrl+Shift+V paste special, Alt+= autosum) is a paid feature in
6
+ * `@svgrid/enterprise`. This holder lets enterprise register a handler at
7
+ * import time; the grid runs the chain before it interprets a key itself.
8
+ *
9
+ * Same shape as `selection-bar-view`, `scheduler-view` and `board-view`, with
10
+ * one difference: those hold a single renderer, this holds a prioritised chain,
11
+ * because several packages may want a key and the first claim has to win
12
+ * deterministically.
13
+ *
14
+ * The chain runs BEFORE `getKeyboardIntent`, which is the whole point. The
15
+ * intent union in `keyboard.ts` is public API and closed, so there is no member
16
+ * that could mean "jump to the edge of the data region" and no way to add one
17
+ * without breaking a consumer that switches on it exhaustively. Running first
18
+ * sidesteps that: a registered handler claims `Ctrl+ArrowDown` and returns
19
+ * true, and the grid never computes an intent for that event at all.
20
+ *
21
+ * ```ts
22
+ * // in @svgrid/enterprise, at module load:
23
+ * import { registerGridShortcuts } from '@svgrid/grid'
24
+ * registerGridShortcuts(handleSheetKey, { id: 'sheet', priority: 100 })
25
+ * ```
26
+ */
27
+ import type { SvGridApi } from './index.js';
28
+ /** What a handler gets to read and write. A getter object over controller
29
+ * state, built only when at least one handler is registered - a free grid
30
+ * never pays to construct it. Indices are DISPLAY indices, matching
31
+ * `SelectionPoint`, so they follow sort, filter and pagination. */
32
+ export type GridCommandContext = {
33
+ /** The grid's public api. Identity is stable for the life of the grid, so
34
+ * a handler can key per-grid state on it in a WeakMap. */
35
+ readonly api: SvGridApi<any, any>;
36
+ /** True when the event came from the cell editor rather than the grid root.
37
+ * Handlers that only make sense mid-edit (Alt+Enter) check this. */
38
+ readonly editing: boolean;
39
+ /**
40
+ * The open inline editor's element, or null. A binding registered for
41
+ * `editing: true` reads and rewrites the text through it: F4 in a
42
+ * spreadsheet pins the reference under the caret.
43
+ */
44
+ readonly editor: HTMLInputElement | HTMLTextAreaElement | null;
45
+ readonly activeCell: {
46
+ rowIndex: number;
47
+ colIndex: number;
48
+ columnId: string | null;
49
+ } | null;
50
+ /**
51
+ * The corner the active range grows from: the far end of a Shift+Arrow,
52
+ * Shift+click or drag, which need not be the active cell. Null while
53
+ * nothing is anchored. A command that extends the selection steps from
54
+ * here, not from the active cell, or Ctrl+Shift+Down twice would land
55
+ * on the same edge twice.
56
+ */
57
+ readonly selectionFocus: {
58
+ rowIndex: number;
59
+ colIndex: number;
60
+ } | null;
61
+ readonly rowCount: number;
62
+ readonly colCount: number;
63
+ /** Every selected rectangle as [minRow, minCol, maxRow, maxCol], active last. */
64
+ readonly ranges: ReadonlyArray<readonly [number, number, number, number]>;
65
+ columnIdAt(colIndex: number): string | null;
66
+ getCellValue(rowIndex: number, colIndex: number): unknown;
67
+ /** Write a cell and record it in the grid's undo history. Inside `batch`
68
+ * every write joins one step, so a fill or a replace-all is one Ctrl+Z. */
69
+ setCellValue(rowIndex: number, colIndex: number, value: unknown): void;
70
+ setActiveCell(rowIndex: number, colIndex: number): void;
71
+ setSelection(rowIndex: number, colIndex: number): void;
72
+ extendSelection(rowIndex: number, colIndex: number): void;
73
+ scrollIntoView(rowIndex: number, colIndex: number): void;
74
+ startEditing(rowIndex: number, colIndex: number, seed?: string): boolean;
75
+ /** Run every write inside `fn` as ONE undo step. Returns what `fn` returns. */
76
+ batch<T>(fn: () => T): T;
77
+ /**
78
+ * Put something that is not a cell write into the grid's undo history:
79
+ * a format kept in the caller's own store, a structural change the grid
80
+ * cannot see. `undo` and `redo` are what Ctrl+Z and Ctrl+Y will call.
81
+ * Inside `batch` the step joins the batch, so a command that writes cells
82
+ * AND formats is still one press.
83
+ */
84
+ recordUndo(undo: () => void, redo: () => void): void;
85
+ /**
86
+ * Put keyboard focus back on the grid, without scrolling.
87
+ *
88
+ * A toolbar button takes focus when it is clicked and a dialog takes it
89
+ * when it opens, so the keystroke after either - Ctrl+Z to undo what the
90
+ * button did, typing into the cell the dialog changed - lands on the button
91
+ * or on `<body>` rather than on the grid. Excel returns focus to the sheet
92
+ * after every ribbon command and every dialog; a command that owns chrome
93
+ * calls this once it is done.
94
+ */
95
+ focus(): void;
96
+ /**
97
+ * Paste the system clipboard at the active cell, the way Ctrl+V does:
98
+ * tab-separated text becomes a block of cells, one undo step. Resolves
99
+ * once the paste has been applied, or without doing anything when the
100
+ * clipboard cannot be read (an insecure context, or permission refused),
101
+ * which is the same silence Ctrl+V keeps there.
102
+ */
103
+ paste(): Promise<void>;
104
+ /**
105
+ * Copy the selection the way Ctrl+C does: every selected rectangle as
106
+ * tab-separated text, each cell through `processCellForClipboard`. The
107
+ * api's `copyToClipboard` is the export: the displayed rows with their
108
+ * headers, whatever the selection.
109
+ */
110
+ copy(): void;
111
+ /**
112
+ * Cut the selection the way Ctrl+X does: the copy above, then the cells
113
+ * cleared as one undo step.
114
+ */
115
+ cut(): Promise<void>;
116
+ /**
117
+ * Whether a cell may be written: the column's `editable` predicate as
118
+ * the grid's own editor, fill handle and paste read it. `setCellValue`
119
+ * does not consult it (a command is trusted to know what it writes), so
120
+ * a command that fills or stamps a range asks here and skips the cells
121
+ * that say no. Optional for a context built by hand.
122
+ */
123
+ canEdit?(rowIndex: number, colIndex: number): boolean;
124
+ };
125
+ /** Return true to consume the event. The grid stops there and does not
126
+ * interpret the key itself. Return false to let it fall through. */
127
+ export type GridShortcutHandler = (event: KeyboardEvent, cmd: GridCommandContext) => boolean;
128
+ /**
129
+ * Register a keyboard handler. Higher `priority` runs first; ties keep
130
+ * registration order. Passing an `id` that is already registered replaces that
131
+ * entry rather than stacking a second copy, so an enable* function stays
132
+ * idempotent. Returns an unregister function.
133
+ */
134
+ export declare function registerGridShortcuts(handler: GridShortcutHandler, opts?: {
135
+ id?: string;
136
+ priority?: number;
137
+ }): () => void;
138
+ /** Run the chain. Returns true when a handler consumed the event. */
139
+ export declare function runGridShortcuts(event: KeyboardEvent, cmd: GridCommandContext): boolean;
140
+ /** Whether anything is registered. The grid checks this before building a
141
+ * command context, so an unregistered grid pays one array-length read. */
142
+ export declare function hasGridShortcuts(): boolean;
143
+ /** Drop every handler. Tests use this; production code should keep the
144
+ * unregister function `registerGridShortcuts` returns. */
145
+ export declare function clearGridShortcuts(): void;
@@ -0,0 +1,44 @@
1
+ // Module-level, not $state: the chain is written at import time by whoever
2
+ // installs a feature pack and read inside an event handler. Nothing renders
3
+ // from it, so reactivity would cost a proxy for no benefit.
4
+ let entries = [];
5
+ /**
6
+ * Register a keyboard handler. Higher `priority` runs first; ties keep
7
+ * registration order. Passing an `id` that is already registered replaces that
8
+ * entry rather than stacking a second copy, so an enable* function stays
9
+ * idempotent. Returns an unregister function.
10
+ */
11
+ export function registerGridShortcuts(handler, opts) {
12
+ const entry = {
13
+ handler,
14
+ id: opts?.id,
15
+ priority: opts?.priority ?? 0,
16
+ };
17
+ const next = entry.id ? entries.filter((e) => e.id !== entry.id) : entries.slice();
18
+ next.push(entry);
19
+ // Stable sort by descending priority: Array.prototype.sort is stable per
20
+ // spec, so equal priorities keep the order they were pushed in.
21
+ next.sort((a, b) => b.priority - a.priority);
22
+ entries = next;
23
+ return () => {
24
+ entries = entries.filter((e) => e !== entry);
25
+ };
26
+ }
27
+ /** Run the chain. Returns true when a handler consumed the event. */
28
+ export function runGridShortcuts(event, cmd) {
29
+ for (const entry of entries) {
30
+ if (entry.handler(event, cmd))
31
+ return true;
32
+ }
33
+ return false;
34
+ }
35
+ /** Whether anything is registered. The grid checks this before building a
36
+ * command context, so an unregistered grid pays one array-length read. */
37
+ export function hasGridShortcuts() {
38
+ return entries.length > 0;
39
+ }
40
+ /** Drop every handler. Tests use this; production code should keep the
41
+ * unregister function `registerGridShortcuts` returns. */
42
+ export function clearGridShortcuts() {
43
+ entries = [];
44
+ }
@@ -1,8 +1,9 @@
1
1
  import type { CellFormatConfig, ColumnDef, RowData, SvGridOptions, TableFeatures } from './core.js';
2
2
  import type { FilterOperator, Props } from './SvGrid.types.js';
3
3
  import type { GridExportOptions, GridClipboardOptions } from './export-format.js';
4
- import type { ChartSpec, ChartType } from './chart.js';
4
+ import type { ChartFormatState, ChartReducer, ChartSpec, ChartTimeBucket, ChartType, ChartZoomWindow } from './chart.js';
5
5
  import type { GridPredicateExpr } from './filtering/predicate-expr.js';
6
+ import type { GridCommandContext } from './shortcut-registry.js';
6
7
  /** The comparisons a column filter can use, as shown in the filter menu. */
7
8
  export type SvGridFilterOperator = FilterOperator;
8
9
  /**
@@ -56,21 +57,78 @@ export type SvGridViewState = {
56
57
  reduce: 'sum' | 'avg' | 'count';
57
58
  stacked: boolean;
58
59
  };
59
- /** All charts in the tab strip (multi-chart), plus the active index. */
60
- charts?: Array<{
61
- title: string;
62
- type: ChartType;
63
- dimension: string | null;
64
- series: string | null;
65
- measure: string | null;
66
- reduce: 'sum' | 'avg' | 'count';
67
- stacked: boolean | null;
68
- dataLabels: boolean | null;
69
- logScale: boolean | null;
70
- timeAxis: boolean | null;
71
- valueFormat: 'number' | 'currency' | 'percent' | 'compact' | null;
72
- }>;
60
+ /** All charts in the tab strip (multi-chart), plus the active index.
61
+ * Every field the panel can change is here so a saved view restores the
62
+ * chart exactly; `null` inherits the `charting` config. */
63
+ charts?: ChartTabSnapshot[];
73
64
  chartActive?: number;
65
+ /** The named charts kept with `api.saveChart`; present only when there is one. */
66
+ savedCharts?: SavedChart[];
67
+ };
68
+ /** One chart tab as the saved view carries it (`GridState.charts[i]`). */
69
+ export type ChartTabSnapshot = {
70
+ title: string;
71
+ type: ChartType;
72
+ dimension: string | null;
73
+ series: string | null;
74
+ measure: string | null;
75
+ /** Scatter's y measure, a range's high, a bullet's target. */
76
+ measure2?: string | null;
77
+ reduce: ChartReducer;
78
+ stacked: boolean | null;
79
+ stacked100?: boolean | null;
80
+ orientation?: 'vertical' | 'horizontal' | null;
81
+ donut?: boolean | null;
82
+ palette?: string[] | null;
83
+ dataLabels: boolean | null;
84
+ logScale: boolean | null;
85
+ timeAxis: boolean | null;
86
+ valueFormat: 'number' | 'currency' | 'percent' | 'compact' | null;
87
+ bucket?: ChartTimeBucket | null;
88
+ bins?: number | null;
89
+ funnelShape?: 'trapezoid' | 'pyramid' | 'cone' | null;
90
+ candleStyle?: 'classic' | 'hollow' | 'heikin-ashi' | null;
91
+ /** The zoom window as category indices, or null for the whole chart. */
92
+ zoom?: ChartZoomWindow | null;
93
+ ohlc?: {
94
+ open: string | null;
95
+ high: string | null;
96
+ low: string | null;
97
+ close: string | null;
98
+ volume: string | null;
99
+ } | null;
100
+ indicators?: string[];
101
+ format?: ChartFormatState | null;
102
+ /** An unlinked chart carries the spec it was frozen with. */
103
+ frozen?: {
104
+ spec: ChartSpec;
105
+ at: string;
106
+ } | null;
107
+ };
108
+ /** A chart configuration kept under a name (`api.saveChart`). */
109
+ export type SavedChart = {
110
+ name: string;
111
+ /** ISO timestamp of the save. */
112
+ savedAt: string;
113
+ /** The tab's state at the time; `applySavedChart` puts it on the active tab. */
114
+ tab: ChartTabSnapshot;
115
+ };
116
+ /** One cell, in the 0-based display coordinates every selection method uses. */
117
+ export type SvGridCellCoords = {
118
+ row: number;
119
+ col: number;
120
+ };
121
+ /**
122
+ * A selected rectangle with its orientation kept: `from` is where the
123
+ * selection was started (the anchor) and `to` where it ended (the focus),
124
+ * so a range dragged upwards has `from.row > to.row`. `highlight` is the
125
+ * active cell inside it. The same three fields as Handsontable's CellRange,
126
+ * so code written against `getSelectedRange()` there reads the same here.
127
+ */
128
+ export type SvGridSelectedRange = {
129
+ from: SvGridCellCoords;
130
+ to: SvGridCellCoords;
131
+ highlight: SvGridCellCoords;
74
132
  };
75
133
  /**
76
134
  * A batch of row mutations for `api.applyTransaction`. `update` / `remove`
@@ -112,17 +170,44 @@ export type SvGridApi<TFeatures extends TableFeatures, TData extends RowData> =
112
170
  * range is `[rowStart, colStart, rowEnd, colEnd]` in 0-indexed grid
113
171
  * coordinates. Pass an empty array to clear the selection.
114
172
  *
115
- * The grid currently honours the FIRST range only (single-range
116
- * engine); subsequent ranges are accepted for API forward compat
117
- * but ignored. The grid's active cell jumps to the range's start
118
- * corner.
173
+ * Every range is honoured: the last one becomes the active range and
174
+ * the others stay highlighted beside it, as after a Ctrl+drag. The
175
+ * active cell goes to the last range's start corner.
119
176
  */
120
177
  selectCells(ranges: ReadonlyArray<readonly [number, number, number, number]>): void;
121
178
  /**
122
- * Returns the current cell-selection rectangles in the same shape
123
- * `selectCells` accepts. Empty array when no range is active.
179
+ * The current cell-selection rectangles in the same shape `selectCells`
180
+ * accepts, each normalised to `[minRow, minCol, maxRow, maxCol]`, in the
181
+ * order they were selected with the active one last. Empty array when no
182
+ * range is active.
183
+ *
184
+ * Handsontable's method of the same name. Two differences, both on
185
+ * purpose: an empty array rather than `undefined`, so `getSelected()[0]`
186
+ * never throws; and normalised corners, so a loop from the first row to
187
+ * the last cannot run zero times because the range was dragged upwards.
188
+ * For the orientation, and the active cell inside a range, use
189
+ * `getSelectedRange()`.
190
+ *
191
+ * With cell selection off (`selectable={false}`) no rectangle is ever
192
+ * recorded and this stays `[]`; the focused cell is `getActiveCell()`.
124
193
  */
125
194
  getSelected(): Array<[number, number, number, number]>;
195
+ /**
196
+ * The most recently selected rectangle as `[startRow, startCol, endRow,
197
+ * endCol]`, start being where the selection began, or `undefined` when
198
+ * nothing is selected. Handsontable's `getSelectedLast()`, orientation
199
+ * included: a range dragged upwards has `startRow > endRow`.
200
+ */
201
+ getSelectedLast(): [number, number, number, number] | undefined;
202
+ /**
203
+ * Every selected rectangle with its orientation and active cell, oldest
204
+ * first, or `undefined` when nothing is selected. Handsontable's
205
+ * `getSelectedRange()`.
206
+ */
207
+ getSelectedRange(): SvGridSelectedRange[] | undefined;
208
+ /** The most recently selected rectangle, or `undefined`. Handsontable's
209
+ * `getSelectedRangeLast()`. */
210
+ getSelectedRangeLast(): SvGridSelectedRange | undefined;
126
211
  /** Open the built-in chart panel. */
127
212
  openChart(): void;
128
213
  /** Close the built-in chart panel. */
@@ -141,19 +226,69 @@ export type SvGridApi<TFeatures extends TableFeatures, TData extends RowData> =
141
226
  dimension?: string | null;
142
227
  series?: string | null;
143
228
  measure?: string | null;
144
- reduce?: 'sum' | 'avg' | 'count';
229
+ reduce?: ChartReducer;
145
230
  stacked?: boolean;
146
231
  dataLabels?: boolean;
147
232
  logScale?: boolean;
148
233
  timeAxis?: boolean;
149
234
  valueFormat?: 'number' | 'currency' | 'percent' | 'compact';
235
+ /** Group a date dimension by calendar unit; `null` returns to exact values. */
236
+ bucket?: ChartTimeBucket | null;
237
+ /** Second measure: a scatter's Y, a range's high end, a bullet's target. */
238
+ measure2?: string | null;
239
+ /** Histogram bin count; `null` for Sturges' rule. */
240
+ bins?: number | null;
241
+ funnelShape?: 'trapezoid' | 'pyramid' | 'cone' | null;
242
+ candleStyle?: 'classic' | 'hollow' | 'heikin-ashi' | null;
243
+ /** Candlestick / OHLC: the price columns (ids or fields); `null` goes
244
+ * back to guessing them from the column names. */
245
+ ohlc?: {
246
+ open?: string | null;
247
+ high?: string | null;
248
+ low?: string | null;
249
+ close?: string | null;
250
+ volume?: string | null;
251
+ } | null;
252
+ /** Indicator panes under a price chart (`volume`, `rsi`, `macd`,
253
+ * `stochastic`, `atr`, `obv`) and overlays on it (`sma`, `ema`,
254
+ * `bb`, `vwap`). */
255
+ indicators?: Array<'volume' | 'rsi' | 'macd' | 'stochastic' | 'atr' | 'obv' | 'sma' | 'ema' | 'bb' | 'vwap'>;
256
+ /** The builder's format state (titles, axes, legend, per-series style);
257
+ * `null` resets it. */
258
+ format?: ChartFormatState | null;
259
+ /** `true` unlinks the chart from the grid (it keeps the spec it has),
260
+ * `false` links it back. */
261
+ frozen?: boolean;
262
+ /** Apply a saved chart (by name) to the active tab before the other keys. */
263
+ saved?: string;
150
264
  }): void;
265
+ /**
266
+ * Keep the active chart's whole configuration (type, columns, aggregate,
267
+ * switches, indicators, format, zoom) under a name. A same-named entry is
268
+ * replaced. Saved charts travel with `getState()` / `setState()` and show
269
+ * in the panel's Saved charts popover.
270
+ */
271
+ saveChart(name: string): void;
272
+ /** Apply a saved chart to the active tab, which keeps its title. `false` when no chart has that name. */
273
+ applySavedChart(name: string): boolean;
274
+ removeSavedChart(name: string): void;
275
+ getSavedCharts(): SavedChart[];
151
276
  /**
152
277
  * Register a natural-language "chart this" handler. When set, the chart
153
278
  * panel shows an AI button. `@svgrid/enterprise`'s `enableAiCharting(api)`
154
279
  * fills this. Pass `null` to remove it.
155
280
  */
156
281
  setChartAiHandler(handler: ((prompt: string) => Promise<Record<string, unknown> | null>) | null): void;
282
+ /**
283
+ * Register an "explain this chart" handler. When set, the chart panel's AI
284
+ * row shows an Explain button that reads the active chart and shows the
285
+ * summary and insights it returns. `enableAiCharting(api)` fills this with
286
+ * `aiExplainChart`. Pass `null` to remove it.
287
+ */
288
+ setChartExplainHandler(handler: (() => Promise<{
289
+ summary: string;
290
+ insights: string[];
291
+ } | null>) | null): void;
157
292
  /** Add one row. `position` defaults to `'bottom'`. */
158
293
  addRow(row: TData, position?: 'top' | 'bottom' | number): void;
159
294
  addRows(rows: ReadonlyArray<TData>, position?: 'top' | 'bottom' | number): void;
@@ -227,6 +362,13 @@ export type SvGridApi<TFeatures extends TableFeatures, TData extends RowData> =
227
362
  * `editorOptions` returns a Promise - static lists are never refetched.
228
363
  */
229
364
  refreshEditorOptions(columnId?: string): void;
365
+ /**
366
+ * Open the `contextMenu` at the pointer, for the cell at (rowIndex,
367
+ * colIndex), from an element of your own: a spreadsheet's column letters
368
+ * and row numbers offer the cell menu for the column or row they select.
369
+ * Does nothing without a `contextMenu` prop.
370
+ */
371
+ openContextMenu(event: MouseEvent, rowIndex: number, colIndex: number): void;
230
372
  /**
231
373
  * Clear every active column filter (menu, filter-row, set-list, global, and
232
374
  * the advanced filter). Resets the grid to "no filtering" in a single call.
@@ -331,6 +473,43 @@ export type SvGridApi<TFeatures extends TableFeatures, TData extends RowData> =
331
473
  * "Autosize" item.
332
474
  */
333
475
  autosizeColumn(columnId: string): void;
476
+ /**
477
+ * The height of a row in px: the one it was dragged or set to, else the
478
+ * declared `rowHeight` (30 when none). `rowIndex` is a display index.
479
+ */
480
+ getRowHeight(rowIndex: number): number;
481
+ /**
482
+ * Give a row its own height, the way dragging its grip does with
483
+ * `rowResize`; `null` takes it back to the declared height. The height
484
+ * belongs to the row (its id), so it follows the row through a sort and
485
+ * survives the data being replaced. Ignored under `autoRowHeight`, where
486
+ * the content decides.
487
+ */
488
+ setRowHeight(rowIndex: number, height: number | null): void;
489
+ /**
490
+ * Fold a column to nothing, the way a spreadsheet hides one: it keeps
491
+ * its index, its cells and its width, and takes no room until it is
492
+ * unfolded. Unlike `setColumnVisible(id, false)`, which takes the
493
+ * column out of the model and shifts every index after it, references
494
+ * by index stay valid, so a sheet's formulas and formats are untouched.
495
+ * Arrow keys, Tab and Enter step over a collapsed column.
496
+ */
497
+ setColumnCollapsed(columnId: string, collapsed: boolean): void;
498
+ isColumnCollapsed(columnId: string): boolean;
499
+ /**
500
+ * Fold a row to nothing, the row-side twin of `setColumnCollapsed`.
501
+ * `rowIndex` is a display index; the fold belongs to the row (its id)
502
+ * and follows it through a sort.
503
+ */
504
+ setRowCollapsed(rowIndex: number, collapsed: boolean): void;
505
+ isRowCollapsed(rowIndex: number): boolean;
506
+ /** The `mergedCells` in force, copied: origins with their spans. */
507
+ getMergedCells(): Array<{
508
+ rowIndex: number;
509
+ colIndex: number;
510
+ rowSpan: number;
511
+ colSpan: number;
512
+ }>;
334
513
  /** Run `autosizeColumn` on every column. */
335
514
  autosizeAllColumns(): void;
336
515
  /**
@@ -381,6 +560,18 @@ export type SvGridApi<TFeatures extends TableFeatures, TData extends RowData> =
381
560
  canRedo(): boolean;
382
561
  /** Wipe both stacks (e.g. after a server save commits the buffer). */
383
562
  clearHistory(): void;
563
+ /**
564
+ * The same `GridCommandContext` a registered shortcut handler receives.
565
+ *
566
+ * Keyboard commands are handed one on every keystroke, but a button in a
567
+ * ribbon or a toolbar has no keystroke to ride in on, and re-implementing
568
+ * "bold the selection" against the api would give the button and the key
569
+ * two code paths that drift. Both go through this instead.
570
+ *
571
+ * Live, not a snapshot: the object reads through to the grid, so one built
572
+ * once at mount still reports the current selection.
573
+ */
574
+ getCommandContext(): GridCommandContext;
384
575
  /** Open the built-in find overlay (Ctrl+F also opens it). */
385
576
  openFind(): void;
386
577
  /** Close the find overlay and clear the query. */
@@ -23,25 +23,41 @@ function sameState(a, b) {
23
23
  for (let i = 0; i < a.items.length; i += 1) {
24
24
  const ai = a.items[i];
25
25
  const bi = b.items[i];
26
- if (ai.index !== bi.index || ai.start !== bi.start || ai.size !== bi.size)
26
+ if (ai.index !== bi.index || ai.start !== bi.start || ai.size !== bi.size || ai.key !== bi.key)
27
27
  return false;
28
28
  }
29
29
  return true;
30
30
  }
31
- // Slot-based keying: the key is the POSITION of the item inside the
32
- // visible window (slot 0 = topmost rendered row, slot 1 = next, etc.)
33
- // - NOT the data index. As the user scrolls, the window's startIndex
34
- // changes but the slot keys stay the same (0..N-1), so Svelte recycles
35
- // the existing <tr> DOM nodes and only updates their data + position.
31
+ // Slot-based keying: the key is a SLOT number, not the data index, so the
32
+ // same N <tr> nodes stay alive for the lifetime of the grid and scrolling
33
+ // never mounts or unmounts a row. With data-index keys, scrolling down one
34
+ // row meant the old topmost key disappeared and a new bottommost key
35
+ // appeared, so Svelte unmounted the top <tr> and mounted a fresh one at the
36
+ // bottom on every scroll tick.
36
37
  //
37
- // This avoids the mount/unmount churn that previously fired on every
38
- // scroll tick: with data-index keys, scrolling down 1 row meant the old
39
- // topmost key disappeared and a new bottommost key appeared, forcing
40
- // Svelte to unmount the top <tr> and mount a fresh one at the bottom.
41
- // Slot-based keys keep the same N <tr> nodes alive for the lifetime of
42
- // the grid; scroll just translates them via the top spacer.
38
+ // The slot for data index i is `i mod N`, N being the window length. That
39
+ // matters for what a one-row scroll costs: while N holds, a row that stays
40
+ // inside the window keeps its slot, so Svelte keeps its <tr> and touches
41
+ // nothing in it, and only the row that entered gets new content - the keyed
42
+ // each moves that one <tr> to the other end with a single `insertBefore`.
43
+ // The earlier `i - startIndex` slot scheme handed EVERY rendered row a new
44
+ // index on every one-row scroll, so an arrow key re-rendered all ~30 rows x
45
+ // every rendered column to shift the data up by one.
46
+ //
47
+ // The modulus has to be EXACTLY N, not merely >= N: under a larger modulus
48
+ // the window's residues are a proper subset, so each one-row scroll drops
49
+ // one residue and picks up another, and Svelte unmounts a <tr> and mounts a
50
+ // fresh one instead of moving it (measured: mount + unmount per arrow key,
51
+ // zero moves). When N changes - the top and bottom overscan clamping on the
52
+ // first and last rows, a resize, variable row heights - every slot remaps
53
+ // and the whole window re-renders once, which is what the old scheme did on
54
+ // every tick.
55
+ function slotKey(index, windowLength) {
56
+ return `virtual_slot_${index % windowLength}`;
57
+ }
43
58
  function buildUniformItems(startIndex, endIndex, estimateSize) {
44
59
  const items = [];
60
+ const windowLength = endIndex - startIndex + 1;
45
61
  for (let index = startIndex; index <= endIndex; index += 1) {
46
62
  const start = index * estimateSize;
47
63
  items.push({
@@ -49,7 +65,7 @@ function buildUniformItems(startIndex, endIndex, estimateSize) {
49
65
  start,
50
66
  size: estimateSize,
51
67
  end: start + estimateSize,
52
- key: `virtual_slot_${index - startIndex}`,
68
+ key: slotKey(index, windowLength),
53
69
  });
54
70
  }
55
71
  return items;
@@ -72,11 +88,12 @@ export function buildPreMeasureItems(count, estimateSize, viewportHeight, oversc
72
88
  return [];
73
89
  const size = Math.max(estimateSize, 1);
74
90
  const visible = Math.ceil(Math.max(viewportHeight, 0) / size);
75
- const endIndex = Math.min(visible + Math.max(overscan, 0), count - 1);
76
- return buildUniformItems(0, Math.max(endIndex, 0), size);
91
+ const endIndex = Math.max(Math.min(visible + Math.max(overscan, 0), count - 1), 0);
92
+ return buildUniformItems(0, endIndex, size);
77
93
  }
78
94
  function buildVariableItems(startIndex, endIndex, offsets) {
79
95
  const items = [];
96
+ const windowLength = endIndex - startIndex + 1;
80
97
  for (let index = startIndex; index <= endIndex; index += 1) {
81
98
  const start = offsets[index] ?? 0;
82
99
  const end = offsets[index + 1] ?? start;
@@ -85,7 +102,7 @@ function buildVariableItems(startIndex, endIndex, offsets) {
85
102
  start,
86
103
  size: end - start,
87
104
  end,
88
- key: `virtual_slot_${index - startIndex}`,
105
+ key: slotKey(index, windowLength),
89
106
  });
90
107
  }
91
108
  return items;
@@ -168,8 +185,12 @@ export function createVirtualizer(initial) {
168
185
  const sizeFn = options.estimateSize;
169
186
  const offsets = new Array(count + 1);
170
187
  offsets[0] = 0;
188
+ // A size of 0 is a real size: a collapsed row or column takes no room
189
+ // and both searches below stay monotonic over equal offsets. Only a
190
+ // negative size is nonsense. The floor used to be 1, which left every
191
+ // hidden column a one-pixel sliver.
171
192
  for (let i = 0; i < count; i += 1) {
172
- offsets[i + 1] = offsets[i] + Math.max(sizeFn(i), 1);
193
+ offsets[i + 1] = offsets[i] + Math.max(sizeFn(i), 0);
173
194
  }
174
195
  offsetCache = { fn: sizeFn, count, offsets };
175
196
  return offsets;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@svgrid/grid",
3
- "version": "3.0.2",
3
+ "version": "3.0.4",
4
4
  "description": "Svelte 5-native data grid and data table. Headless-first engine with virtual scrolling for 100k+ rows, Excel-style filtering, inline editing, grouping, tree data, pivot, and server-side data. Drop-in <SvGrid> component. TypeScript, SSR-ready.",
5
5
  "author": "jQWidgets <boikom@jqwidgets.com>",
6
6
  "license": "MIT",
@@ -94,6 +94,11 @@
94
94
  "svelte": "./dist/filtering/excel-filters.js",
95
95
  "import": "./dist/filtering/excel-filters.js"
96
96
  },
97
+ "./shortcuts": {
98
+ "types": "./dist/shortcut-registry.d.ts",
99
+ "svelte": "./dist/shortcut-registry.js",
100
+ "import": "./dist/shortcut-registry.js"
101
+ },
97
102
  "./flex-render": {
98
103
  "types": "./dist/flex-render.d.ts",
99
104
  "svelte": "./dist/flex-render.js",