@svgrid/enterprise 3.0.2 → 3.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (364) hide show
  1. package/LICENSE +94 -24
  2. package/README.md +36 -4
  3. package/dist/SvAdvancedFilter.svelte +1 -1
  4. package/dist/SvAlertsManager.svelte +2 -1
  5. package/dist/SvBoard.svelte +2 -1
  6. package/dist/SvExportMenu.svelte +4 -1
  7. package/dist/SvExportMenu.svelte.d.ts +0 -13
  8. package/dist/SvExpressionEditor.svelte +3 -3
  9. package/dist/SvFormulaBar.svelte +94 -20
  10. package/dist/SvFormulaBar.svelte.d.ts +7 -0
  11. package/dist/SvGridAlerts.svelte +49 -9
  12. package/dist/SvGridBoard.svelte +13 -8
  13. package/dist/SvGridBulkEditDrawer.svelte +26 -2
  14. package/dist/SvGridEditPanel.svelte +3 -0
  15. package/dist/SvGridScheduler.svelte +69 -40
  16. package/dist/SvGridSelectionBar.svelte +10 -3
  17. package/dist/SvPivotDesigner.svelte +198 -40
  18. package/dist/SvPivotDesigner.svelte.d.ts +27 -20
  19. package/dist/SvSheet.svelte +4043 -243
  20. package/dist/SvSheet.svelte.d.ts +76 -3
  21. package/dist/SvSheetChartSetup.svelte +151 -0
  22. package/dist/SvSheetChartSetup.svelte.d.ts +18 -0
  23. package/dist/SvSheetComment.svelte +216 -31
  24. package/dist/SvSheetComment.svelte.d.ts +11 -11
  25. package/dist/SvSheetConditionalFormat.svelte +28 -31
  26. package/dist/SvSheetDataValidation.svelte +66 -42
  27. package/dist/SvSheetEditRanges.svelte +217 -0
  28. package/dist/SvSheetEditRanges.svelte.d.ts +15 -0
  29. package/dist/SvSheetErrors.svelte +125 -0
  30. package/dist/SvSheetErrors.svelte.d.ts +20 -0
  31. package/dist/SvSheetEvaluate.svelte +133 -0
  32. package/dist/SvSheetEvaluate.svelte.d.ts +15 -0
  33. package/dist/SvSheetFilterMenu.svelte +137 -34
  34. package/dist/SvSheetFilterMenu.svelte.d.ts +5 -0
  35. package/dist/SvSheetFindReplace.svelte +19 -19
  36. package/dist/SvSheetFormatCells.svelte +125 -81
  37. package/dist/SvSheetGoalSeek.svelte +17 -16
  38. package/dist/SvSheetInsertFunction.svelte +15 -13
  39. package/dist/SvSheetIteration.svelte +81 -0
  40. package/dist/SvSheetIteration.svelte.d.ts +10 -0
  41. package/dist/SvSheetLink.svelte +99 -0
  42. package/dist/SvSheetLink.svelte.d.ts +17 -0
  43. package/dist/SvSheetListPicker.svelte +4 -2
  44. package/dist/SvSheetListPicker.svelte.d.ts +0 -6
  45. package/dist/SvSheetManageRules.svelte +20 -18
  46. package/dist/SvSheetNameManager.svelte +17 -15
  47. package/dist/SvSheetPageSetup.svelte +159 -0
  48. package/dist/SvSheetPageSetup.svelte.d.ts +13 -0
  49. package/dist/SvSheetPasteSpecial.svelte +22 -20
  50. package/dist/SvSheetPivot.svelte +220 -0
  51. package/dist/SvSheetPivot.svelte.d.ts +21 -0
  52. package/dist/SvSheetProtectSheet.svelte +81 -0
  53. package/dist/SvSheetProtectSheet.svelte.d.ts +11 -0
  54. package/dist/SvSheetRemoveDuplicates.svelte +13 -10
  55. package/dist/SvSheetRibbon.svelte +104 -51
  56. package/dist/SvSheetSizeDialog.svelte +4 -2
  57. package/dist/SvSheetSort.svelte +218 -0
  58. package/dist/SvSheetSort.svelte.d.ts +28 -0
  59. package/dist/SvSheetSparklines.svelte +135 -0
  60. package/dist/SvSheetSparklines.svelte.d.ts +14 -0
  61. package/dist/SvSheetTable.svelte +160 -0
  62. package/dist/SvSheetTable.svelte.d.ts +24 -0
  63. package/dist/SvSheetTabs.svelte +161 -31
  64. package/dist/SvSheetTabs.svelte.d.ts +22 -8
  65. package/dist/SvSheetTextToColumns.svelte +20 -20
  66. package/dist/SvSheetValidationAlert.svelte +8 -6
  67. package/dist/advanced-filter-enable.js +1 -1
  68. package/dist/alerts/alert-engine.d.ts +6 -0
  69. package/dist/alerts/alert-engine.js +21 -4
  70. package/dist/alerts/alert-formats.js +2 -0
  71. package/dist/alerts/alert-types.d.ts +1 -1
  72. package/dist/alerts.d.ts +1 -1
  73. package/dist/alerts.js +2 -2
  74. package/dist/board.js +2 -2
  75. package/dist/bulk-edit.d.ts +3 -1
  76. package/dist/bulk-edit.js +1 -1
  77. package/dist/cdn/svgrid-enterprise.svelte-external.js +39827 -16429
  78. package/dist/designer/assets/GridMenus-8gTNssgV.js +8 -0
  79. package/dist/designer/assets/{SvChartMenu-D9hEeHar.js → SvChartMenu-BDoeqGz6.js} +1 -1
  80. package/dist/designer/assets/{SvDateTimePicker-DARvKUL2.js → SvDateTimePicker-DCPg7WGN.js} +1 -1
  81. package/dist/designer/assets/SvGridCellEditor-DMoWJjEI.js +4 -0
  82. package/dist/designer/assets/{SvGridChart-B8j1SSy3.js → SvGridChart-Cy1ATrWh.js} +2 -2
  83. package/dist/designer/assets/SvGridChartBuilder-eQ3mn0L9.js +1 -0
  84. package/dist/designer/assets/{SvGridChartPanel-pT6ITc2P.js → SvGridChartPanel-CATdVc9X.js} +3 -3
  85. package/dist/designer/assets/{SvGridChartView-bg281UA1.js → SvGridChartView-CmsZtCED.js} +1 -1
  86. package/dist/designer/assets/SvGridDropdown-Cjz0H-fI.js +1 -0
  87. package/dist/designer/assets/{SvTabs-UFCMTHXS.js → SvTabs-2mHC6oaz.js} +1 -1
  88. package/dist/designer/assets/cell-formatting-BbubJTVz.js +1 -0
  89. package/dist/designer/assets/{chart-cIPUsbM5.js → chart-Cn7MnNqA.js} +1 -1
  90. package/dist/designer/assets/{chart-panel-messages-DtTxpBUU.js → chart-panel-messages-Dz7PTIqT.js} +1 -1
  91. package/dist/designer/assets/{chart-summary-Czu_5epb.js → chart-summary-BD1qYB2R.js} +1 -1
  92. package/dist/designer/assets/{chart-trend-D5I5VEe8.js → chart-trend-B8xr5LuD.js} +1 -1
  93. package/dist/designer/assets/{dismissable-BO547MH9.js → dismissable-ChWRPkoa.js} +1 -1
  94. package/dist/designer/assets/{export-format-D-eP4b2l.js → export-format-DGckmgKr.js} +1 -1
  95. package/dist/designer/assets/{focus-trap-CAreAhlU.js → focus-trap-V2-6Fy9I.js} +1 -1
  96. package/dist/designer/assets/{index-DwU7CAMm.js → index-BSjv6Qec.js} +317 -315
  97. package/dist/designer/assets/index-_JVFxt02.css +1 -0
  98. package/dist/designer/assets/row-resize-BInFWCpr.js +1 -0
  99. package/dist/designer/assets/server-block-cache-CXJKkJpy.js +1 -0
  100. package/dist/designer/assets/src-DUQ4xE3x.js +58 -0
  101. package/dist/designer/assets/validate-C3B8QKsM.js +1 -0
  102. package/dist/designer/index.html +17 -16
  103. package/dist/export-pdf.d.ts +75 -0
  104. package/dist/export-pdf.js +216 -15
  105. package/dist/export.js +10 -2
  106. package/dist/gantt/SvGridGantt.svelte +2890 -0
  107. package/dist/gantt/SvGridGantt.svelte.d.ts +30 -0
  108. package/dist/gantt/gantt-config.d.ts +73 -0
  109. package/dist/gantt/gantt-config.js +1 -0
  110. package/dist/gantt/gantt-critical-path.d.ts +67 -0
  111. package/dist/gantt/gantt-critical-path.js +207 -0
  112. package/dist/gantt/gantt-model.d.ts +257 -0
  113. package/dist/gantt/gantt-model.js +651 -0
  114. package/dist/gantt/gantt-resources.d.ts +59 -0
  115. package/dist/gantt/gantt-resources.js +71 -0
  116. package/dist/gantt/gantt.d.ts +7 -0
  117. package/dist/gantt/gantt.js +36 -0
  118. package/dist/gantt/index.d.ts +15 -0
  119. package/dist/gantt/index.js +22 -0
  120. package/dist/gantt/timeline-arrows.d.ts +102 -0
  121. package/dist/gantt/timeline-arrows.js +181 -0
  122. package/dist/import.d.ts +2 -2
  123. package/dist/import.js +1 -1
  124. package/dist/index.d.ts +34 -7
  125. package/dist/index.js +44 -7
  126. package/dist/install.js +8 -1
  127. package/dist/license-core.d.ts +17 -1
  128. package/dist/license-core.js +16 -5
  129. package/dist/license.d.ts +18 -2
  130. package/dist/license.js +71 -6
  131. package/dist/node/studio.js +140 -8
  132. package/dist/pivot-enable.js +2 -2
  133. package/dist/scheduler-dependencies.d.ts +35 -0
  134. package/dist/scheduler-dependencies.js +36 -1
  135. package/dist/scheduler.js +2 -2
  136. package/dist/selection-bar.js +2 -2
  137. package/dist/server/SvGroupCell.svelte +213 -0
  138. package/dist/server/SvGroupCell.svelte.d.ts +62 -0
  139. package/dist/server/SvRowGroupPanel.svelte +322 -0
  140. package/dist/server/SvRowGroupPanel.svelte.d.ts +37 -0
  141. package/dist/server/enable.d.ts +17 -0
  142. package/dist/server/enable.js +49 -0
  143. package/dist/server/index.d.ts +22 -0
  144. package/dist/server/index.js +24 -0
  145. package/dist/server/messages.d.ts +45 -0
  146. package/dist/server/messages.js +35 -0
  147. package/dist/server/server-group-model.d.ts +104 -0
  148. package/dist/server/server-group-model.js +272 -0
  149. package/dist/server/server-pivot.d.ts +46 -0
  150. package/dist/server/server-pivot.js +57 -0
  151. package/dist/server/server-row-model.d.ts +547 -0
  152. package/dist/server/server-row-model.js +1551 -0
  153. package/dist/server/server-selection.d.ts +99 -0
  154. package/dist/server/server-selection.js +215 -0
  155. package/dist/server/svgrid-adapter.d.ts +155 -0
  156. package/dist/server/svgrid-adapter.js +202 -0
  157. package/dist/sheet/ast.d.ts +45 -1
  158. package/dist/sheet/ast.js +14 -0
  159. package/dist/sheet/auto-filter.d.ts +58 -4
  160. package/dist/sheet/auto-filter.js +159 -11
  161. package/dist/sheet/autocomplete.d.ts +9 -0
  162. package/dist/sheet/autocomplete.js +90 -4
  163. package/dist/sheet/cell-images.d.ts +39 -0
  164. package/dist/sheet/cell-images.js +90 -0
  165. package/dist/sheet/cell-types.d.ts +58 -0
  166. package/dist/sheet/cell-types.js +96 -0
  167. package/dist/sheet/coerce.d.ts +40 -0
  168. package/dist/sheet/coerce.js +170 -3
  169. package/dist/sheet/comments.d.ts +43 -9
  170. package/dist/sheet/comments.js +85 -27
  171. package/dist/sheet/conditional-formats.d.ts +29 -6
  172. package/dist/sheet/conditional-formats.js +37 -12
  173. package/dist/sheet/csv.d.ts +32 -0
  174. package/dist/sheet/csv.js +158 -0
  175. package/dist/sheet/culture.d.ts +87 -0
  176. package/dist/sheet/culture.js +247 -0
  177. package/dist/sheet/delta.d.ts +102 -0
  178. package/dist/sheet/delta.js +203 -0
  179. package/dist/sheet/deps.d.ts +45 -1
  180. package/dist/sheet/deps.js +77 -2
  181. package/dist/sheet/document.d.ts +106 -4
  182. package/dist/sheet/document.js +204 -3
  183. package/dist/sheet/engine.d.ts +67 -0
  184. package/dist/sheet/engine.js +19 -0
  185. package/dist/sheet/entry.d.ts +8 -4
  186. package/dist/sheet/entry.js +171 -21
  187. package/dist/sheet/error-check.d.ts +49 -0
  188. package/dist/sheet/error-check.js +83 -0
  189. package/dist/sheet/evaluate-steps.d.ts +48 -0
  190. package/dist/sheet/evaluate-steps.js +196 -0
  191. package/dist/sheet/evaluate.d.ts +67 -0
  192. package/dist/sheet/evaluate.js +725 -13
  193. package/dist/sheet/filter-files.d.ts +37 -0
  194. package/dist/sheet/filter-files.js +465 -0
  195. package/dist/sheet/format-store.d.ts +15 -0
  196. package/dist/sheet/format-store.js +11 -1
  197. package/dist/sheet/from-rows.d.ts +14 -0
  198. package/dist/sheet/from-rows.js +50 -0
  199. package/dist/sheet/function-catalog.d.ts +1 -1
  200. package/dist/sheet/function-catalog.js +296 -5
  201. package/dist/sheet/functions.js +363 -91
  202. package/dist/sheet/index.d.ts +35 -8
  203. package/dist/sheet/index.js +35 -8
  204. package/dist/sheet/links.d.ts +57 -0
  205. package/dist/sheet/links.js +174 -0
  206. package/dist/sheet/messages.d.ts +778 -0
  207. package/dist/sheet/messages.js +806 -0
  208. package/dist/sheet/number-format.d.ts +52 -5
  209. package/dist/sheet/number-format.js +465 -68
  210. package/dist/sheet/objects.d.ts +106 -0
  211. package/dist/sheet/objects.js +149 -0
  212. package/dist/sheet/ods-document.d.ts +44 -0
  213. package/dist/sheet/ods-document.js +1275 -0
  214. package/dist/sheet/open-file.d.ts +26 -0
  215. package/dist/sheet/open-file.js +56 -0
  216. package/dist/sheet/outline.d.ts +82 -0
  217. package/dist/sheet/outline.js +228 -0
  218. package/dist/sheet/packs/array.d.ts +16 -0
  219. package/dist/sheet/packs/array.js +172 -0
  220. package/dist/sheet/packs/database.d.ts +42 -0
  221. package/dist/sheet/packs/database.js +142 -0
  222. package/dist/sheet/packs/engineering.d.ts +2 -0
  223. package/dist/sheet/packs/engineering.js +296 -0
  224. package/dist/sheet/packs/financial.d.ts +5 -0
  225. package/dist/sheet/packs/financial.js +220 -0
  226. package/dist/sheet/packs/math-stats.d.ts +2 -0
  227. package/dist/sheet/packs/math-stats.js +372 -0
  228. package/dist/sheet/packs/special.d.ts +44 -0
  229. package/dist/sheet/packs/special.js +187 -0
  230. package/dist/sheet/packs/stats-dist.d.ts +2 -0
  231. package/dist/sheet/packs/stats-dist.js +785 -0
  232. package/dist/sheet/packs/text-date.d.ts +2 -0
  233. package/dist/sheet/packs/text-date.js +332 -0
  234. package/dist/sheet/packs/trig.d.ts +2 -0
  235. package/dist/sheet/packs/trig.js +73 -0
  236. package/dist/sheet/page-setup.d.ts +73 -0
  237. package/dist/sheet/page-setup.js +73 -0
  238. package/dist/sheet/parse.js +42 -10
  239. package/dist/sheet/paste-special.d.ts +22 -0
  240. package/dist/sheet/paste-special.js +14 -5
  241. package/dist/sheet/pivot-range.d.ts +160 -0
  242. package/dist/sheet/pivot-range.js +333 -0
  243. package/dist/sheet/presence.d.ts +73 -0
  244. package/dist/sheet/presence.js +79 -0
  245. package/dist/sheet/print.d.ts +104 -0
  246. package/dist/sheet/print.js +169 -0
  247. package/dist/sheet/protection.d.ts +55 -1
  248. package/dist/sheet/protection.js +55 -2
  249. package/dist/sheet/rects.d.ts +1 -1
  250. package/dist/sheet/refs.d.ts +48 -0
  251. package/dist/sheet/refs.js +155 -8
  252. package/dist/sheet/ribbon-icons.d.ts +1 -1
  253. package/dist/sheet/ribbon-icons.js +186 -0
  254. package/dist/sheet/ribbon.d.ts +1 -1
  255. package/dist/sheet/ribbon.js +324 -23
  256. package/dist/sheet/sheet-kinds.d.ts +74 -0
  257. package/dist/sheet/sheet-kinds.js +91 -0
  258. package/dist/sheet/shortcuts.d.ts +13 -3
  259. package/dist/sheet/shortcuts.js +63 -12
  260. package/dist/sheet/sort.d.ts +51 -0
  261. package/dist/sheet/sort.js +107 -0
  262. package/dist/sheet/sparklines.d.ts +111 -0
  263. package/dist/sheet/sparklines.js +204 -0
  264. package/dist/sheet/table-styles.d.ts +74 -0
  265. package/dist/sheet/table-styles.js +152 -0
  266. package/dist/sheet/tables.d.ts +19 -0
  267. package/dist/sheet/tables.js +31 -0
  268. package/dist/sheet/tokenize.d.ts +18 -1
  269. package/dist/sheet/tokenize.js +60 -9
  270. package/dist/sheet/validation.d.ts +16 -0
  271. package/dist/sheet/validation.js +37 -0
  272. package/dist/sheet/workbook.d.ts +148 -3
  273. package/dist/sheet/workbook.js +742 -31
  274. package/dist/sheet/xls-cfb.d.ts +32 -0
  275. package/dist/sheet/xls-cfb.js +290 -0
  276. package/dist/sheet/xls-document.d.ts +10 -0
  277. package/dist/sheet/xls-document.js +1243 -0
  278. package/dist/sheet/xls-formula.d.ts +40 -0
  279. package/dist/sheet/xls-formula.js +569 -0
  280. package/dist/sheet/xlsx-document.d.ts +108 -0
  281. package/dist/sheet/xlsx-document.js +1849 -0
  282. package/dist/sheet/xlsx-drawing.d.ts +99 -0
  283. package/dist/sheet/xlsx-drawing.js +420 -0
  284. package/dist/sheet-enable.js +6 -7
  285. package/dist/sheet-text.d.ts +7 -0
  286. package/dist/sheet-text.js +29 -0
  287. package/dist/sources/auth-supabase.js +2 -2
  288. package/dist/sources/realtime-supabase.js +2 -2
  289. package/dist/sources/rest.d.ts +6 -2
  290. package/dist/sources/rest.js +42 -7
  291. package/dist/sources/supabase.d.ts +10 -1
  292. package/dist/sources/supabase.js +73 -40
  293. package/dist/studio/emit-project.js +14 -1
  294. package/dist/studio/index.js +1 -1
  295. package/dist/studio/project.d.ts +11 -2
  296. package/dist/studio/project.js +5 -2
  297. package/dist/studio/ui-components.generated.js +107 -2
  298. package/dist/sveltekit/in-memory.d.ts +2 -2
  299. package/dist/sveltekit/in-memory.js +125 -4
  300. package/dist/sveltekit/index.d.ts +1 -1
  301. package/dist/sveltekit/index.js +1 -1
  302. package/dist/sveltekit/query-plan.d.ts +50 -4
  303. package/dist/sveltekit/query-plan.js +25 -3
  304. package/dist/sveltekit/sql-source.d.ts +6 -0
  305. package/dist/sveltekit/sql-source.js +34 -6
  306. package/dist/sveltekit/sql.d.ts +31 -0
  307. package/dist/sveltekit/sql.js +135 -25
  308. package/dist/sveltekit/transport.d.ts +10 -2
  309. package/dist/sveltekit/transport.js +30 -6
  310. package/dist/upgrade-prompt.d.ts +1 -1
  311. package/dist/version.d.ts +1 -1
  312. package/dist/version.js +1 -1
  313. package/dist/watermark.js +35 -2
  314. package/dist/wc/GridMenus-By9vPuq0.js +1088 -0
  315. package/dist/wc/SvChartMenu-CQNrQGT2.js +308 -0
  316. package/dist/wc/SvDateRangeInput-DR6m7bSM.js +199 -0
  317. package/dist/wc/SvDateTimePicker-D-vRnaMo.js +771 -0
  318. package/dist/wc/SvField-B_kurx_P.js +149 -0
  319. package/dist/wc/SvGrid.helpers-BdVDtjUm.js +135 -0
  320. package/dist/wc/SvGridCellEditor-Bnf1Kr5C.js +560 -0
  321. package/dist/wc/SvGridChart-BqUJh2pG.js +3572 -0
  322. package/dist/wc/SvGridChartBuilder-CGycC5cn.js +988 -0
  323. package/dist/wc/SvGridChartPanel-CRnizsHD.js +1746 -0
  324. package/dist/wc/SvGridChartView-D1pa_xMy.js +47 -0
  325. package/dist/wc/SvGridDropdown-45WsObLL.js +259 -0
  326. package/dist/wc/SvModal-DrfOYYyX.js +189 -0
  327. package/dist/wc/cell-formatting-CBfgahv1.js +86 -0
  328. package/dist/wc/chart-6OXlybVT.js +4341 -0
  329. package/dist/wc/chart-export-CeSADGfi.js +135 -0
  330. package/dist/wc/chart-export-pdf-BGko7MER.js +104 -0
  331. package/dist/wc/chart-summary-2m3ia1-n.js +137 -0
  332. package/dist/wc/chart-trend-CQOQtTMl.js +50 -0
  333. package/dist/wc/chart-validate-CD6ptiwg.js +180 -0
  334. package/dist/wc/client-DQIzjDBG.js +3064 -0
  335. package/dist/wc/column-resize-DUPgynvc.js +101 -0
  336. package/dist/wc/date-format-DS-z_h9v.js +1130 -0
  337. package/dist/wc/dismissable-CQ6XFXsk.js +45 -0
  338. package/dist/wc/editor-contract-peBDxir_.js +22 -0
  339. package/dist/wc/editor-registry-DxGKqcvx.js +24 -0
  340. package/dist/wc/focus-trap-Dbb2tJxb.js +65 -0
  341. package/dist/wc/list-option-DrRyivWp.js +82 -0
  342. package/dist/wc/popover-WsGlvtQv.js +69 -0
  343. package/dist/wc/positioning-BiKLfu1E.js +112 -0
  344. package/dist/wc/react.d.ts +41 -0
  345. package/dist/wc/react.js +90 -0
  346. package/dist/wc/rolldown-runtime-Dy4uBu1J.js +11 -0
  347. package/dist/wc/row-drag-touch-CycRR65n.js +93 -0
  348. package/dist/wc/row-resize-limG_N1z.js +111 -0
  349. package/dist/wc/sv-sheet-element.d.ts +97 -0
  350. package/dist/wc/sv-sheet-element.js +44213 -0
  351. package/dist/wc/svelte-virtualizer.svelte-CXtQy2TQ.js +530 -0
  352. package/dist/wc/validate-BqDthkNr.js +88 -0
  353. package/dist/wc/vue.d.ts +31 -0
  354. package/dist/wc/vue.js +75 -0
  355. package/package.json +30 -5
  356. package/dist/designer/assets/GridMenus-BlsvL_aU.js +0 -8
  357. package/dist/designer/assets/SvGridCellEditor-C7uQXYds.js +0 -4
  358. package/dist/designer/assets/SvGridChartBuilder-kvyIU_Rl.js +0 -1
  359. package/dist/designer/assets/SvGridDropdown-Bb3HH2Aj.js +0 -1
  360. package/dist/designer/assets/cell-formatting-wr5wm7US.js +0 -1
  361. package/dist/designer/assets/index-CMFgAoVV.css +0 -1
  362. package/dist/designer/assets/row-resize-DLktcqUK.js +0 -1
  363. package/dist/designer/assets/src-EdI3Xqds.js +0 -58
  364. package/dist/designer/assets/validate-h-aslRV9.js +0 -1
@@ -1,5 +1,5 @@
1
1
  import { resolveIdField } from '../schema.js';
2
- import { nudgeEnterprise } from '../license.js';
2
+ import { nudgeEnterpriseFor } from '../license.js';
3
3
  import { normalizeFilters } from './filters.js';
4
4
  const encodePredicate = (p) => {
5
5
  if (p.op === 'in')
@@ -48,22 +48,57 @@ function defaultBuildQuery(request) {
48
48
  if (aggs.length)
49
49
  params.aggregate = aggs.map((a) => `${a.fn}:${a.col}`).join(',');
50
50
  }
51
+ // The grid wants a grand-total row it does not have yet. An endpoint that
52
+ // supports it answers with `grandTotal` in the body (the aggregates over
53
+ // the filtered set, path excluded); one that does not simply ignores the
54
+ // flag and the grid shows no total. The aggregate list is sent either
55
+ // way, so a leaf-level request still says what to total.
56
+ if (request.needsGrandTotal) {
57
+ params.grandTotal = '1';
58
+ const aggs = request.aggregations ?? [];
59
+ if (aggs.length && !params.aggregate)
60
+ params.aggregate = aggs.map((a) => `${a.fn}:${a.col}`).join(',');
61
+ }
62
+ // Pivot: the columns whose values become fields, on a grouped request.
63
+ // The endpoint answers with the pivoted fields on each group row and
64
+ // lists them in `pivotResultFields`; see the SQL source for the shape.
65
+ //
66
+ // ?groupBy=region&aggregate=sum:amount&pivot=year,quarter
67
+ if (request.pivotMode && request.pivotBy?.length && params.groupBy) {
68
+ params.pivot = request.pivotBy.join(',');
69
+ }
51
70
  return params;
52
71
  }
53
- function defaultParse(body, response) {
72
+ /**
73
+ * The count when the API sent none: a short block is the last one, so the
74
+ * end is known; a full block says nothing, so the count is unknown (`-1`)
75
+ * and an infinite-scrolling grid discovers the end from a later short
76
+ * block. Claiming `rows.length` would tell a pager there is one page.
77
+ */
78
+ function countWithoutTotal(rows, request) {
79
+ const asked = Math.max(1, request.endRow - request.startRow);
80
+ return rows.length < asked ? request.startRow + rows.length : -1;
81
+ }
82
+ function defaultParse(body, response, request) {
54
83
  if (Array.isArray(body)) {
55
84
  // Total from a Content-Range header (`items 0-9/240`) when present.
56
85
  const range = response.headers.get('content-range');
57
86
  const total = range && /\/(\d+)\s*$/.exec(range);
58
- return { rows: body, rowCount: total ? Number(total[1]) : body.length };
87
+ return { rows: body, rowCount: total ? Number(total[1]) : countWithoutTotal(body, request) };
59
88
  }
60
89
  const b = (body ?? {});
90
+ // `grandTotal` rides along in an envelope body when the endpoint answered
91
+ // the request for one. Absent means "keep what you have", `null` means
92
+ // "there is none" - the same three-way contract as ServerResult.
93
+ const grandTotal = 'grandTotal' in b ? { grandTotal: (b.grandTotal ?? null) } : {};
61
94
  const rows = (b.rows ?? b.data ?? b.items ?? []);
62
- const rowCount = Number(b.rowCount ?? b.total ?? b.count ?? rows.length);
63
- return { rows, rowCount };
95
+ const declared = b.rowCount ?? b.total ?? b.count;
96
+ const rowCount = declared == null ? countWithoutTotal(rows, request) : Number(declared);
97
+ const pivot = Array.isArray(b.pivotResultFields) ? { pivotResultFields: b.pivotResultFields } : {};
98
+ return { rows, rowCount, ...grandTotal, ...pivot };
64
99
  }
65
100
  export function createRestDataSource(config) {
66
- nudgeEnterprise('Studio'); // soft-gate; never blocks
101
+ nudgeEnterpriseFor('studio', 'Studio'); // evaluation nudge; never blocks
67
102
  const doFetch = config.fetch ?? globalThis.fetch;
68
103
  const idField = config.idField ?? (config.schema ? resolveIdField(config.schema) : 'id');
69
104
  const base = config.url.replace(/\/+$/, '');
@@ -86,7 +121,7 @@ export function createRestDataSource(config) {
86
121
  const qs = new URLSearchParams({ ...config.query, ...buildQuery(request) }).toString();
87
122
  const url = qs ? `${base}?${qs}` : base;
88
123
  const { body, res } = (await send(url, { headers: headers() }));
89
- return parse(body, res);
124
+ return parse(body, res, request);
90
125
  },
91
126
  async createRow(input) {
92
127
  const { body } = (await send(base, {
@@ -12,7 +12,7 @@
12
12
  * with `searchColumns`. The primary key comes from the schema (`idField`) and is
13
13
  * stripped from inserts (it's database-generated).
14
14
  */
15
- import type { RowData } from '@svgrid/grid';
15
+ import type { RowData, ServerRequest, ServerResult } from '@svgrid/grid';
16
16
  import { type EntitySchema } from '../schema.js';
17
17
  import type { WritableDataSource } from '../sveltekit/types.js';
18
18
  /** The slice of a `supabase-js` client this adapter needs. */
@@ -29,5 +29,14 @@ export type SupabaseDataSourceConfig<TData extends RowData> = {
29
29
  * schema's text + enum fields.
30
30
  */
31
31
  searchColumns?: string[];
32
+ /**
33
+ * Server-side pivot. PostgREST has no way to turn values into columns, so
34
+ * a pivoted request (`pivotMode` with `pivotBy`) goes to this function
35
+ * instead - typically an RPC (`client.rpc(...)`) that returns the group
36
+ * rows with one field per (pivot key x aggregation) and lists them in
37
+ * `pivotResultFields`; the SQL source documents the shape. Without it a
38
+ * pivoted request is answered as plain grouping, with a warning once.
39
+ */
40
+ pivot?: (request: ServerRequest) => Promise<ServerResult<TData>>;
32
41
  };
33
42
  export declare function createSupabaseDataSource<TData extends RowData>(config: SupabaseDataSourceConfig<TData>): WritableDataSource<TData>;
@@ -1,15 +1,27 @@
1
1
  import { resolveIdField } from '../schema.js';
2
- import { nudgeEnterprise } from '../license.js';
2
+ import { nudgeEnterpriseFor } from '../license.js';
3
3
  import { normalizeFilters } from './filters.js';
4
4
  const sanitize = (term) => term.replace(/[%,()]/g, '');
5
5
  export function createSupabaseDataSource(config) {
6
- nudgeEnterprise('Studio'); // soft-gate; never blocks
6
+ nudgeEnterpriseFor('studio', 'Studio'); // evaluation nudge; never blocks
7
7
  const { client, table, schema } = config;
8
8
  const idField = resolveIdField(schema);
9
9
  const searchColumns = config.searchColumns ??
10
10
  schema.fields.filter((f) => f.type === 'text' || f.type === 'enum').map((f) => String(f.field));
11
+ let warnedPivot = false;
11
12
  return {
12
13
  async getRows(request) {
14
+ // ---- Server-side pivot ----------------------------------------------
15
+ // Only a grouped level pivots; the leaves under a path do not.
16
+ const grouped = (request.groupKeys?.length ?? 0) < (request.groupBy?.length ?? 0);
17
+ if (grouped && request.pivotMode && request.pivotBy?.length) {
18
+ if (config.pivot)
19
+ return config.pivot(request);
20
+ if (!warnedPivot) {
21
+ warnedPivot = true;
22
+ console.warn('[svgrid] createSupabaseDataSource: a pivoted request needs the `pivot` option (an RPC that pivots); answering it as plain grouping.');
23
+ }
24
+ }
13
25
  // ---- Server-side grouping -------------------------------------------
14
26
  // The grid asks one level at a time. The already-chosen path becomes
15
27
  // ordinary `.eq()` filters below; at this level we ask PostgREST for the
@@ -26,50 +38,61 @@ export function createSupabaseDataSource(config) {
26
38
  const groupCols = request.groupBy ?? [];
27
39
  const groupKeys = request.groupKeys ?? [];
28
40
  const groupField = groupKeys.length < groupCols.length ? groupCols[groupKeys.length] : undefined;
41
+ const aggregateSelects = (request.aggregations ?? []).map((a) => a.fn === 'count' ? `${a.col}:count()` : `${a.col}:${a.col}.${a.fn}()`);
42
+ // The innermost group level can say how many rows each group holds
43
+ // (a plain count). Higher levels would need COUNT(DISTINCT next),
44
+ // which PostgREST does not expose, so those group rows carry no
45
+ // childCount and the grid shows no badge for them.
46
+ const innermost = groupField != null && groupKeys.length === groupCols.length - 1;
29
47
  const selectExpr = groupField
30
- ? [
31
- groupField,
32
- ...(request.aggregations ?? []).map((a) => a.fn === 'count' ? `${a.col}:count()` : `${a.col}:${a.col}.${a.fn}()`),
33
- ].join(',')
48
+ ? [groupField, ...aggregateSelects, ...(innermost ? ['childCount:count()'] : [])].join(',')
34
49
  : '*';
35
50
  let q = client.from(table).select(selectExpr, { count: 'exact' });
51
+ // The filters are applied to two queries when a grand total was asked
52
+ // for: the level itself (below, with the group path) and the total
53
+ // (the filters alone). Build them once.
54
+ const applyFilters = (query) => {
55
+ let out = query;
56
+ const { predicates, search } = normalizeFilters(request.filterModel);
57
+ for (const p of predicates) {
58
+ switch (p.op) {
59
+ case 'in':
60
+ out = out.in(p.column, p.values);
61
+ break;
62
+ case 'contains':
63
+ out = out.ilike(p.column, `%${p.value}%`);
64
+ break;
65
+ case 'startsWith':
66
+ out = out.ilike(p.column, `${p.value}%`);
67
+ break;
68
+ case 'eq':
69
+ out = out.eq(p.column, p.value);
70
+ break;
71
+ case 'gt':
72
+ out = out.gt(p.column, p.value);
73
+ break;
74
+ case 'lt':
75
+ out = out.lt(p.column, p.value);
76
+ break;
77
+ case 'between':
78
+ out = out.gte(p.column, p.value).lte(p.column, p.valueTo);
79
+ break;
80
+ case 'isNull':
81
+ out = out.is(p.column, null);
82
+ break;
83
+ }
84
+ }
85
+ if (search && searchColumns.length) {
86
+ const term = sanitize(search);
87
+ out = out.or(searchColumns.map((c) => `${c}.ilike.%${term}%`).join(','));
88
+ }
89
+ return out;
90
+ };
36
91
  // The path constrains the rows before grouping.
37
92
  for (let i = 0; i < groupKeys.length && i < groupCols.length; i += 1) {
38
93
  q = q.eq(groupCols[i], groupKeys[i]);
39
94
  }
40
- const { predicates, search } = normalizeFilters(request.filterModel);
41
- for (const p of predicates) {
42
- switch (p.op) {
43
- case 'in':
44
- q = q.in(p.column, p.values);
45
- break;
46
- case 'contains':
47
- q = q.ilike(p.column, `%${p.value}%`);
48
- break;
49
- case 'startsWith':
50
- q = q.ilike(p.column, `${p.value}%`);
51
- break;
52
- case 'eq':
53
- q = q.eq(p.column, p.value);
54
- break;
55
- case 'gt':
56
- q = q.gt(p.column, p.value);
57
- break;
58
- case 'lt':
59
- q = q.lt(p.column, p.value);
60
- break;
61
- case 'between':
62
- q = q.gte(p.column, p.value).lte(p.column, p.valueTo);
63
- break;
64
- case 'isNull':
65
- q = q.is(p.column, null);
66
- break;
67
- }
68
- }
69
- if (search && searchColumns.length) {
70
- const term = sanitize(search);
71
- q = q.or(searchColumns.map((c) => `${c}.ilike.%${term}%`).join(','));
72
- }
95
+ q = applyFilters(q);
73
96
  // When grouping, only columns the grouped select actually produces can be
74
97
  // ordered on - PostgREST rejects an ORDER BY over a column that is
75
98
  // neither grouped nor aggregated. Fall back to the group key so the
@@ -95,7 +118,17 @@ export function createSupabaseDataSource(config) {
95
118
  const { data, count, error } = await q.range(request.startRow, request.endRow - 1);
96
119
  if (error)
97
120
  throw new Error(error.message);
98
- return { rows: (data ?? []), rowCount: count ?? 0 };
121
+ const result = { rows: (data ?? []), rowCount: count ?? 0 };
122
+ // The grand total: one aggregate-only select over the filtered set,
123
+ // with no group column (so PostgREST returns a single row) and no path.
124
+ if (request.needsGrandTotal && aggregateSelects.length) {
125
+ const total = applyFilters(client.from(table).select(aggregateSelects.join(',')));
126
+ const { data: totalRows, error: totalError } = await total;
127
+ if (totalError)
128
+ throw new Error(totalError.message);
129
+ result.grandTotal = (totalRows?.[0] ?? null);
130
+ }
131
+ return result;
99
132
  },
100
133
  async createRow(input) {
101
134
  const rest = { ...input };
@@ -478,6 +478,17 @@ ${panels}
478
478
  // Dragging a card updates its groupBy value in the local row state (optimistic).
479
479
  return ` <div ${wrapperStyle(block)}${cls}>
480
480
  <SvBoard schema={${schemaVar}} rows={allRows} loading={!allRowsReady} groupBy=${JSON.stringify(cfg.groupBy)} titleField=${JSON.stringify(asText(cfg.titleField))}${badge}${sub}${onOpen} height={${h}} onMove={(id, value) => { allRows = allRows.map((r) => String((r as Record<string, unknown>)[idField]) === String(id) ? ({ ...r, ['${cfg.groupBy}']: value }) : r) }} />
481
+ </div>`;
482
+ }
483
+ case 'sheet': {
484
+ const h = block.height ?? 480;
485
+ // The shell reads `data` once at mount, so it mounts once the rows are in.
486
+ const chosen = cfg.fields?.length ? cfg.fields : entity.fields.map((f) => f.field);
487
+ const specs = chosen.map((field) => ({ field, label: entity.fields.find((f) => f.field === field)?.label ?? field }));
488
+ // Excel's sheet-name rules: none of []:*?/\ and at most 31 characters.
489
+ const sheetName = (entity.label ?? entity.name).replace(/[[\]:*?/\\]/g, ' ').trim().slice(0, 31) || 'Sheet1';
490
+ return ` <div ${wrapperStyle(block, `min-height: ${h}px`)}${cls}>
491
+ {#if allRowsReady}<SvSheet data={[{ name: ${JSON.stringify(sheetName)}, cells: sheetCellsFromRows(${rowsExpr}, ${JSON.stringify(specs)}, { totals: ${cfg.totals ? 'true' : 'false'} }) }]} height={${h}} />{/if}
481
492
  </div>`;
482
493
  }
483
494
  case 'calendar': {
@@ -1981,7 +1992,7 @@ function screenPage(schema, rawSchema, screen, resolve, rawResolve, accessEnable
1981
1992
  const exportApiVars = blocks.filter((b) => b.config.kind === 'grid' && gridHasExport(b.config) && !(codeGrid && b.id === codeGridBlockId)).map((b) => `gridApi_${b.id.replace(/-/g, '_')}`);
1982
1993
  const needsGridApiType = codeGrid || exportApiVars.length > 0;
1983
1994
  // The pivot reads the whole table (like charts / dashboards).
1984
- const needsAllRows = hasAgg || hasMD || hasPivot || hasBoundComponent || hasGroupedGrid || hasTreeGrid || hasSchedulerGrid || has(allBlocks, 'board') || has(allBlocks, 'calendar') || has(allBlocks, 'detail');
1995
+ const needsAllRows = hasAgg || hasMD || hasPivot || hasBoundComponent || hasGroupedGrid || hasTreeGrid || hasSchedulerGrid || has(allBlocks, 'board') || has(allBlocks, 'calendar') || has(allBlocks, 'detail') || has(allBlocks, 'sheet');
1985
1996
  // --- imports ---
1986
1997
  const gridSpecs = [];
1987
1998
  if (needsController)
@@ -2030,6 +2041,8 @@ function screenPage(schema, rawSchema, screen, resolve, rawResolve, accessEnable
2030
2041
  entImports.push('schemaToColumns');
2031
2042
  if (has(allBlocks, 'detail'))
2032
2043
  entImports.push('SvRecordDetail');
2044
+ if (has(allBlocks, 'sheet'))
2045
+ entImports.push('SvSheet', 'sheetCellsFromRows');
2033
2046
  if (has(allBlocks, 'kpi') || has(allBlocks, 'gauge') || hasAggregateBinding)
2034
2047
  entImports.push('reduceValue');
2035
2048
  const kpiCfgs = allBlocks.filter((b) => b.config.kind === 'kpi').map((b) => b.config);
@@ -36,6 +36,6 @@ export { resolveDeployTarget, deployCommands, missingEnvKeys, } from './deploy-c
36
36
  export { runStudioAdd, runStudioAddApp, resolveSchema, resolveSchemas, } from './cli.js';
37
37
  // Re-export the schema surface so consumers get everything from one entry.
38
38
  export { resolveIdField, schemaToColumns, schemaToFormFields, isFieldHidden, linkRelationLabels, pickLabelField, } from '../schema.js';
39
- // Pure license classification, so the Node/MCP generator can soft-gate with the
39
+ // Pure license classification, so the Node/MCP generator can nudge with the
40
40
  // same rules as the browser (see license-core.ts). No DOM, safe in Node.
41
41
  export { checkLicenseKey } from '../license-core.js';
@@ -95,7 +95,7 @@ export type EntityDataSource = MemorySource | RestSource | SqlSource | SupabaseS
95
95
  /** The kinds of block a screen can hold: data-bound (entity-derived) or the
96
96
  * entity-agnostic `'component'` (a UI-kit component from `UI_COMPONENT_REGISTRY`,
97
97
  * usable on any screen, including a freestanding one with no entity). */
98
- export type BlockKind = 'grid' | 'form' | 'chart' | 'dashboard' | 'kpi' | 'gauge' | 'tree' | 'tabs' | 'accordion' | 'master-detail' | 'lookup' | 'pivot' | 'filter' | 'record' | 'board' | 'calendar' | 'detail' | 'component';
98
+ export type BlockKind = 'grid' | 'form' | 'chart' | 'dashboard' | 'kpi' | 'gauge' | 'tree' | 'tabs' | 'accordion' | 'master-detail' | 'lookup' | 'pivot' | 'filter' | 'record' | 'board' | 'calendar' | 'detail' | 'sheet' | 'component';
99
99
  export type GridAlign = 'left' | 'center' | 'right';
100
100
  /** No-code per-column value formatting. Compiles to the grid's `format` (CellFormatConfig):
101
101
  * a raw `1234.5` becomes `$1,234.50` / `42%` / `Jun 27, 2026` without a code renderer. */
@@ -516,6 +516,15 @@ export type DetailConfig = {
516
516
  }[];
517
517
  related?: DetailRelated[];
518
518
  };
519
+ /** The entity's rows on the spreadsheet shell (SvSheet): a header row of field
520
+ * labels, a row per record, and, with `totals`, a SUM row under every numeric
521
+ * column. `fields` narrows and orders the columns (empty = every field). The
522
+ * sheet is Excel over the dataset: formulas, formats, filters and an xlsx out. */
523
+ export type SheetConfig = {
524
+ kind: 'sheet';
525
+ fields?: string[];
526
+ totals?: boolean;
527
+ };
519
528
  /** A UI-kit component (from `UI_COMPONENT_REGISTRY`, keyed by `component`) dropped
520
529
  * onto a screen. Entity-agnostic - works on a freestanding page or mixed onto an
521
530
  * entity-bound screen alike. `props` holds its configured "chrome" values, keyed
@@ -543,7 +552,7 @@ export type ComponentConfig = {
543
552
  name?: string;
544
553
  bindings?: Record<string, ComponentBinding>;
545
554
  };
546
- export type BlockConfig = GridConfig | FormConfig | ChartConfig | KpiConfig | GaugeConfig | TreeConfig | TabsConfig | AccordionConfig | DashboardConfig | MasterDetailConfig | LookupConfig | PivotConfig | FilterPanelConfig | RecordConfig | BoardConfig | CalendarConfig | DetailConfig | ComponentConfig;
555
+ export type BlockConfig = GridConfig | FormConfig | ChartConfig | KpiConfig | GaugeConfig | TreeConfig | TabsConfig | AccordionConfig | DashboardConfig | MasterDetailConfig | LookupConfig | PivotConfig | FilterPanelConfig | RecordConfig | BoardConfig | CalendarConfig | DetailConfig | SheetConfig | ComponentConfig;
547
556
  /** Block kinds allowed inside a Tabs / Accordion container: the controller-free,
548
557
  * `allRows`-driven display blocks (no grid / form / master-detail, which need the
549
558
  * screen controller). `component` covers any UI-kit component added by key. */
@@ -432,6 +432,7 @@ export const blockPalette = [
432
432
  { kind: 'board', label: 'Board' },
433
433
  { kind: 'calendar', label: 'Calendar' },
434
434
  { kind: 'detail', label: 'Detail page' },
435
+ { kind: 'sheet', label: 'Spreadsheet' },
435
436
  { kind: 'filter', label: 'Filter panel' },
436
437
  { kind: 'record', label: 'Record panel' },
437
438
  { kind: 'lookup', label: 'Lookup' },
@@ -538,6 +539,8 @@ export function defaultBlockConfig(kind, entity) {
538
539
  const metrics = nonKey.filter((f) => f.type === 'number').slice(0, 3).map((f) => f.field);
539
540
  return { kind, titleField: titleF, ...(subF ? { subtitleField: subF } : {}), ...(statusF ? { statusField: statusF } : {}), ...(metrics.length ? { metricFields: metrics } : {}) };
540
541
  }
542
+ case 'sheet':
543
+ return { kind, totals: entity.fields.some((f) => f.type === 'number' && !f.primaryKey) };
541
544
  case 'component':
542
545
  // Entity-agnostic - built directly by `addComponentBlock`, never through here.
543
546
  return { kind, component: '', props: {} };
@@ -554,7 +557,7 @@ export function pickFacetFields(entity) {
554
557
  }
555
558
  const facetRank = (t) => (t === 'enum' ? 0 : t === 'boolean' ? 1 : 2);
556
559
  const DEFAULT_SPAN = {
557
- grid: 3, form: 1, chart: 2, dashboard: 3, kpi: 1, gauge: 1, tree: 2, tabs: 3, accordion: 3, 'master-detail': 3, lookup: 1, pivot: 3, filter: 1, record: 1, board: 3, calendar: 3, detail: 3, component: 1,
560
+ grid: 3, form: 1, chart: 2, dashboard: 3, kpi: 1, gauge: 1, tree: 2, tabs: 3, accordion: 3, 'master-detail': 3, lookup: 1, pivot: 3, filter: 1, record: 1, board: 3, calendar: 3, detail: 3, sheet: 3, component: 1,
558
561
  };
559
562
  function makeBlock(kind, entity, taken) {
560
563
  return { id: uid(`${kind}-`, taken), span: DEFAULT_SPAN[kind], config: defaultBlockConfig(kind, entity) };
@@ -1249,7 +1252,7 @@ function dockPaneTitle(block) {
1249
1252
  grid: 'Grid', form: 'Form', chart: 'Chart', dashboard: 'Dashboard', tree: 'Tree', pivot: 'Pivot',
1250
1253
  filter: 'Filters', record: 'Record', detail: 'Detail', board: 'Board', calendar: 'Calendar',
1251
1254
  'master-detail': 'Master / detail', lookup: 'Lookup', tabs: 'Tabs', accordion: 'Accordion',
1252
- kpi: 'KPI', gauge: 'Gauge', component: 'Component',
1255
+ kpi: 'KPI', gauge: 'Gauge', sheet: 'Spreadsheet', component: 'Component',
1253
1256
  };
1254
1257
  return c.label || c.title || c.name || c.component || byKind[c.kind] || 'Panel';
1255
1258
  }
@@ -6583,6 +6583,7 @@ export const GENERATED_UI_SURFACE = {
6583
6583
  "key": "data",
6584
6584
  "label": "Data",
6585
6585
  "type": "json",
6586
+ "description": "The rows to render. Optional only because `rowModel` can supply them instead; a grid with neither renders empty. When both are present `data` wins.",
6586
6587
  "group": "common"
6587
6588
  },
6588
6589
  {
@@ -6605,6 +6606,13 @@ export const GENERATED_UI_SURFACE = {
6605
6606
  "description": "Scheduler / calendar mode. When set, the grid renders its rows as events on a Month / Week / Day / Agenda calendar instead of a table. See .",
6606
6607
  "group": "common"
6607
6608
  },
6609
+ {
6610
+ "key": "gantt",
6611
+ "label": "Gantt",
6612
+ "type": "json",
6613
+ "description": "Gantt mode. When set, the grid renders its rows as a task table beside a time chart: one bar per row by start / end, a work-breakdown tree from `parentField`, and dependency arrows. See . A view of the grid like the board and scheduler; the renderer ships in `@svgrid/enterprise` (call `enableGanttView()`).",
6614
+ "group": "common"
6615
+ },
6608
6616
  {
6609
6617
  "key": "chart",
6610
6618
  "label": "Chart",
@@ -7036,6 +7044,14 @@ export const GENERATED_UI_SURFACE = {
7036
7044
  "code": true,
7037
7045
  "group": "advanced"
7038
7046
  },
7047
+ {
7048
+ "key": "includeCollapsedRows",
7049
+ "label": "Include Collapsed Rows",
7050
+ "type": "json",
7051
+ "description": "Whether a collapsed row still takes part in a copy or a fill that spans it. Left out, both skip every collapsed row, which is what \"filter, copy, paste\" needs and what a fill dragged over a filtered list expects: the series runs over the rows that show. A spreadsheet answers per row: a row hidden by hand is copied and filled, as Excel does, while a row a filter folded away is not.",
7052
+ "code": true,
7053
+ "group": "advanced"
7054
+ },
7039
7055
  {
7040
7056
  "key": "clipboardHtml",
7041
7057
  "label": "Clipboard Html",
@@ -7244,6 +7260,34 @@ export const GENERATED_UI_SURFACE = {
7244
7260
  "description": "Which rows feed the min/max range that `colorScale` / `dataBar` formats scale against. - `filtered` (default): every row that survives the filters, ignoring the page slice. The scale follows what you filtered to but does not shift when you page, so the same value keeps the same colour on page 1 and page 2. - `visible`: only the rows currently on screen. Rescales per page - use it when you want each page's heat map normalized to that page. - `all`: the full unfiltered dataset, for a scale that stays put as you filter.",
7245
7261
  "group": "common"
7246
7262
  },
7263
+ {
7264
+ "key": "rowPlaceholder",
7265
+ "label": "Row Placeholder",
7266
+ "type": "json",
7267
+ "description": "Marks a row as one whose data has not arrived: `\"loading\"` draws a shimmer in every cell, `\"failed\"` draws a full-width \"could not load\" row with a Retry button, and `null` (the default for every row) renders normally. Placeholder rows are inert - not selectable, not editable, and skipped by cell navigation - because there is nothing there to act on yet. `createServerDataSource` in `infinite` mode fills the gaps with rows this recognises, so the usual wiring is `rowPlaceholder={rowPlaceholderState}` (or nothing at all, via `rowModel`).",
7268
+ "code": true,
7269
+ "group": "advanced"
7270
+ },
7271
+ {
7272
+ "key": "rowModel",
7273
+ "label": "Row Model",
7274
+ "type": "json",
7275
+ "description": "Drive the grid from a row model instead of wiring a dozen props. `createServerDataSource` returns one, and so does the Enterprise server-side row model, so server-backed grids become: ```svelte <SvGrid rowModel={ctl} {columns} /> ``` The model supplies `data`, `loading`, `getRowId`, the external sort and filter wiring, the visible range, placeholder rows, group accessors, selection and paging - each one only if it implements that part. A prop written explicitly on the grid always wins, so you can adopt it and still override one piece.",
7276
+ "group": "common"
7277
+ },
7278
+ {
7279
+ "key": "pivotResultColumns",
7280
+ "label": "Pivot Result Columns",
7281
+ "type": "json",
7282
+ "description": "Columns that REPLACE `columns` while set. The server-side row model supplies them in pivot mode - one column per pivoted value, grouped under a header per pivot key - and clears them when pivot mode ends, so `columns` stays the app's own list. Rarely set by hand.",
7283
+ "group": "common"
7284
+ },
7285
+ {
7286
+ "key": "rowSelectionModel",
7287
+ "label": "Row Selection Model",
7288
+ "type": "json",
7289
+ "group": "common"
7290
+ },
7247
7291
  {
7248
7292
  "key": "isDetailRow",
7249
7293
  "label": "Is Detail Row",
@@ -7252,11 +7296,41 @@ export const GENERATED_UI_SURFACE = {
7252
7296
  "code": true,
7253
7297
  "group": "advanced"
7254
7298
  },
7299
+ {
7300
+ "key": "detailRowHeight",
7301
+ "label": "Detail Row Height",
7302
+ "type": "number",
7303
+ "description": "The height of a detail row, in px, or a function of its data. With it the virtualizer can size detail rows, so master-detail works with `virtualization` on (the panel scrolls inside its cell when taller). Without it a detail row is auto height, which needs `virtualization={false}`.",
7304
+ "group": "common"
7305
+ },
7306
+ {
7307
+ "key": "showDetailToggle",
7308
+ "label": "Show Detail Toggle",
7309
+ "type": "boolean",
7310
+ "description": "A row-header column of chevrons that open and close detail rows. It sits with the row-number and selection columns: sticky at the left, no column menu, not resizable, not reorderable, outside the active cell and the selection. The chevron calls `onDetailToggle` (or, on a server row model, the model's own toggle) and reads `isDetailOpen` for its direction; `hasDetail` hides it on rows that have nothing to open. Detail rows themselves get an empty cell.",
7311
+ "group": "common"
7312
+ },
7313
+ {
7314
+ "key": "isDetailOpen",
7315
+ "label": "Is Detail Open",
7316
+ "type": "json",
7317
+ "description": "Whether the detail under a row is open: the chevron's direction and `aria-expanded`.",
7318
+ "code": true,
7319
+ "group": "advanced"
7320
+ },
7321
+ {
7322
+ "key": "hasDetail",
7323
+ "label": "Has Detail",
7324
+ "type": "json",
7325
+ "description": "Whether a row has a detail to open; the chevron is left out where this returns false.",
7326
+ "code": true,
7327
+ "group": "advanced"
7328
+ },
7255
7329
  {
7256
7330
  "key": "serverGroup",
7257
7331
  "label": "Server Group",
7258
7332
  "type": "json",
7259
- "description": "Server-side group / tree keyboard + accessibility, built into the grid. When set, the grid uses the treegrid role and marks matching rows with `aria-level` / `aria-expanded`, and ArrowRight / ArrowLeft expand / collapse the focused group row (no app-level key handling). Pair with `serverGroupRows` + `SvGroupCell` for the visual expander. Every accessor receives the row data.",
7333
+ "description": "Server-side group / tree keyboard + accessibility, built into the grid. When set, the grid uses the treegrid role and marks matching rows with `aria-level` / `aria-expanded`, and ArrowRight / ArrowLeft expand / collapse the focused group row (no app-level key handling). Pair with `serverGroupRows` + `SvGroupCell` from `@svgrid/enterprise` for the visual expander, or drive it from your own tree state. Every accessor receives the row data.",
7260
7334
  "group": "common"
7261
7335
  },
7262
7336
  {
@@ -7281,6 +7355,13 @@ export const GENERATED_UI_SURFACE = {
7281
7355
  "description": "Freeze the first N rows: they stay under the header while the body scrolls, and unlike `pinnedTopRows` they are the grid's own rows, still editable, selectable and numbered as rows 1..N. Excel's Freeze Panes, for the row half; the column half is `columnPinning`. Under `virtualization` the frozen rows are always rendered and the window skips them.",
7282
7356
  "group": "common"
7283
7357
  },
7358
+ {
7359
+ "key": "stickyGroupRows",
7360
+ "label": "Sticky Group Rows",
7361
+ "type": "boolean",
7362
+ "description": "Keep the group a row belongs to in view: while the rows of an open group scroll past, the group's row (and its parents' rows) stay under the header, the way a section heading stays put in a long list, so a screen deep inside a 60,000-row group still says which group it is. Works for server-side groups (`rowModel` / `serverGroup`), client grouping and tree data. Under `virtualization` the band shows a copy of each ancestor row; without it the rows themselves stick. Off by default.",
7363
+ "group": "common"
7364
+ },
7284
7365
  {
7285
7366
  "key": "mergedCells",
7286
7367
  "label": "Merged Cells",
@@ -7398,7 +7479,7 @@ export const GENERATED_UI_SURFACE = {
7398
7479
  "key": "cellSelectionChange",
7399
7480
  "label": "Cell Selection Change",
7400
7481
  "prop": "onCellSelectionChange",
7401
- "description": "Fires whenever the cell-selection rectangle changes (mouse, keyboard, or `api.selectCells()`). `ranges` matches `api.getSelected()` - `[rowStart, colStart, rowEnd, colEnd]` rectangles in grid coords. Empty array when the user clears the selection."
7482
+ "description": "Fires whenever the cell selection changes (mouse, keyboard, or `api.selectCells()`). `ranges` is every selected rectangle, matching `api.getSelected()`: the ones a Ctrl+click committed and the active one last, each `[rowStart, colStart, rowEnd, colEnd]` in grid coords. Empty array when the user clears the selection."
7402
7483
  },
7403
7484
  {
7404
7485
  "key": "sortingChange",
@@ -7466,6 +7547,24 @@ export const GENERATED_UI_SURFACE = {
7466
7547
  "prop": "onScrollBottomReached",
7467
7548
  "description": "Fires once each time the body is scrolled to (within ~32px of) the bottom. Re-arms after the user scrolls back up. The canonical hook for infinite / lazy loading - append more rows to `data` when it fires."
7468
7549
  },
7550
+ {
7551
+ "key": "visibleRangeChange",
7552
+ "label": "Visible Range Change",
7553
+ "prop": "onVisibleRangeChange",
7554
+ "description": "Fires when the range of rows on screen changes, with the first and last row INDEX (not pixels). Coalesced to one call per frame, so it is cheap to wire to something that fetches. This is the hook a block-loading data source needs and `onScrollBottomReached` cannot give it: \"the user is looking at rows 4,000-4,020\" answers which block to fetch and which to keep, while \"they hit the bottom\" only ever means \"append more\". Both are free; use this one with `createServerDataSource({ mode: 'infinite' })`, or let `rowModel` wire it for you. Reports `0, data.length - 1` when virtualization is off, since every row really is rendered."
7555
+ },
7556
+ {
7557
+ "key": "retryRow",
7558
+ "label": "Retry Row",
7559
+ "prop": "onRetryRow",
7560
+ "description": "Called by the Retry button on a `\"failed\"` placeholder row."
7561
+ },
7562
+ {
7563
+ "key": "detailToggle",
7564
+ "label": "Detail Toggle",
7565
+ "prop": "onDetailToggle",
7566
+ "description": "Open or close the detail under a row. The chevron of `showDetailToggle` and Ctrl+Enter on a row call it; you keep the open set and insert or remove the detail row in `data`. A server row model supplies its own (the `rowModel` prop wires `toggleDetail`), so this is the client side."
7567
+ },
7469
7568
  {
7470
7569
  "key": "columnOrderChange",
7471
7570
  "label": "Column Order Change",
@@ -7477,6 +7576,12 @@ export const GENERATED_UI_SURFACE = {
7477
7576
  "label": "Row Drag End",
7478
7577
  "prop": "onRowDragEnd",
7479
7578
  "description": "Fires on the TARGET grid after a managed row drag settles, with the moved row, its landing index, whether it stayed in the same grid, and the source / target grid ids. Use it to mirror the move into your own state (persistence, server sync). The grid has already applied the change to its internal data by the time this fires."
7579
+ },
7580
+ {
7581
+ "key": "rowDrop",
7582
+ "label": "Row Drop",
7583
+ "prop": "onRowDrop",
7584
+ "description": "Take the drop yourself. With this set the grid keeps the drag affordance and the drop indicator but does not touch its data: the handler gets the dragged row, the row it landed on (null for the empty space below the rows) and the side - `before` / `after`, or `into` when it landed on the middle of a group or tree row, which makes it that row's child. The path for a `rowModel`, whose rows the grid does not own: hand the move to the model (`moveRow`) or to your server. Only fires within one grid; a drop from another grid stays managed."
7480
7585
  }
7481
7586
  ]
7482
7587
  }
@@ -5,10 +5,10 @@
5
5
  * do, and is genuinely useful on its own for small datasets, tests, demos,
6
6
  * and prototyping a schema before a database exists behind it.
7
7
  */
8
- import type { RowData } from '@svgrid/grid';
8
+ import type { RowData, ServerDataSource } from '@svgrid/grid';
9
9
  import { type EntitySchema } from '../schema.js';
10
10
  import type { WritableDataSource } from './types.js';
11
11
  import { type AggregateSource } from '../sources/aggregate.js';
12
- export declare function createInMemoryDataSource<TData extends RowData>(initial: ReadonlyArray<TData>, schema: EntitySchema<TData>): WritableDataSource<TData> & AggregateSource & {
12
+ export declare function createInMemoryDataSource<TData extends RowData>(initial: ReadonlyArray<TData>, schema: EntitySchema<TData>): WritableDataSource<TData> & Required<Pick<ServerDataSource<TData>, 'updateWhere'>> & AggregateSource & {
13
13
  rows(): ReadonlyArray<TData>;
14
14
  };