@svgrid/enterprise 3.0.1 → 3.0.3

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 (445) 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 +680 -0
  10. package/dist/SvFormulaBar.svelte.d.ts +69 -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 +263 -54
  18. package/dist/SvPivotDesigner.svelte.d.ts +27 -20
  19. package/dist/SvRibbonIcon.svelte +46 -0
  20. package/dist/SvRibbonIcon.svelte.d.ts +17 -0
  21. package/dist/SvSchemaChart.svelte +4 -2
  22. package/dist/SvSheet.svelte +7914 -0
  23. package/dist/SvSheet.svelte.d.ts +215 -0
  24. package/dist/SvSheetChartSetup.svelte +151 -0
  25. package/dist/SvSheetChartSetup.svelte.d.ts +18 -0
  26. package/dist/SvSheetComment.svelte +283 -0
  27. package/dist/SvSheetComment.svelte.d.ts +22 -0
  28. package/dist/SvSheetConditionalFormat.svelte +159 -0
  29. package/dist/SvSheetConditionalFormat.svelte.d.ts +14 -0
  30. package/dist/SvSheetDataValidation.svelte +273 -0
  31. package/dist/SvSheetDataValidation.svelte.d.ts +14 -0
  32. package/dist/SvSheetEditRanges.svelte +217 -0
  33. package/dist/SvSheetEditRanges.svelte.d.ts +15 -0
  34. package/dist/SvSheetErrors.svelte +125 -0
  35. package/dist/SvSheetErrors.svelte.d.ts +20 -0
  36. package/dist/SvSheetEvaluate.svelte +133 -0
  37. package/dist/SvSheetEvaluate.svelte.d.ts +15 -0
  38. package/dist/SvSheetFilterMenu.svelte +320 -0
  39. package/dist/SvSheetFilterMenu.svelte.d.ts +22 -0
  40. package/dist/SvSheetFindReplace.svelte +132 -0
  41. package/dist/SvSheetFindReplace.svelte.d.ts +10 -0
  42. package/dist/SvSheetFormatCells.svelte +465 -0
  43. package/dist/SvSheetFormatCells.svelte.d.ts +17 -0
  44. package/dist/SvSheetGoalSeek.svelte +145 -0
  45. package/dist/SvSheetGoalSeek.svelte.d.ts +12 -0
  46. package/dist/SvSheetInsertFunction.svelte +149 -0
  47. package/dist/SvSheetInsertFunction.svelte.d.ts +8 -0
  48. package/dist/SvSheetIteration.svelte +81 -0
  49. package/dist/SvSheetIteration.svelte.d.ts +10 -0
  50. package/dist/SvSheetLink.svelte +99 -0
  51. package/dist/SvSheetLink.svelte.d.ts +17 -0
  52. package/dist/SvSheetListPicker.svelte +91 -0
  53. package/dist/SvSheetListPicker.svelte.d.ts +10 -0
  54. package/dist/SvSheetManageRules.svelte +187 -0
  55. package/dist/SvSheetManageRules.svelte.d.ts +16 -0
  56. package/dist/SvSheetNameManager.svelte +227 -0
  57. package/dist/SvSheetNameManager.svelte.d.ts +11 -0
  58. package/dist/SvSheetPageSetup.svelte +159 -0
  59. package/dist/SvSheetPageSetup.svelte.d.ts +13 -0
  60. package/dist/SvSheetPasteSpecial.svelte +107 -0
  61. package/dist/SvSheetPasteSpecial.svelte.d.ts +12 -0
  62. package/dist/SvSheetPivot.svelte +220 -0
  63. package/dist/SvSheetPivot.svelte.d.ts +21 -0
  64. package/dist/SvSheetProtectSheet.svelte +81 -0
  65. package/dist/SvSheetProtectSheet.svelte.d.ts +11 -0
  66. package/dist/SvSheetRemoveDuplicates.svelte +152 -0
  67. package/dist/SvSheetRemoveDuplicates.svelte.d.ts +12 -0
  68. package/dist/SvSheetRibbon.svelte +1254 -0
  69. package/dist/SvSheetRibbon.svelte.d.ts +34 -0
  70. package/dist/SvSheetSizeDialog.svelte +60 -0
  71. package/dist/SvSheetSizeDialog.svelte.d.ts +11 -0
  72. package/dist/SvSheetSort.svelte +218 -0
  73. package/dist/SvSheetSort.svelte.d.ts +28 -0
  74. package/dist/SvSheetSparklines.svelte +135 -0
  75. package/dist/SvSheetSparklines.svelte.d.ts +14 -0
  76. package/dist/SvSheetTable.svelte +160 -0
  77. package/dist/SvSheetTable.svelte.d.ts +24 -0
  78. package/dist/SvSheetTabs.svelte +571 -0
  79. package/dist/SvSheetTabs.svelte.d.ts +50 -0
  80. package/dist/SvSheetTabs.test-harness.svelte.d.ts +17 -0
  81. package/dist/SvSheetTabs.test-harness.svelte.js +22 -0
  82. package/dist/SvSheetTextToColumns.svelte +172 -0
  83. package/dist/SvSheetTextToColumns.svelte.d.ts +13 -0
  84. package/dist/SvSheetValidationAlert.svelte +85 -0
  85. package/dist/SvSheetValidationAlert.svelte.d.ts +15 -0
  86. package/dist/advanced-filter-enable.js +1 -1
  87. package/dist/alerts/alert-engine.d.ts +6 -0
  88. package/dist/alerts/alert-engine.js +21 -4
  89. package/dist/alerts/alert-formats.js +2 -0
  90. package/dist/alerts/alert-types.d.ts +1 -1
  91. package/dist/alerts.d.ts +1 -1
  92. package/dist/alerts.js +2 -2
  93. package/dist/board.js +2 -2
  94. package/dist/bulk-edit.d.ts +3 -1
  95. package/dist/bulk-edit.js +1 -1
  96. package/dist/cdn/svgrid-enterprise.svelte-external.js +43538 -6539
  97. package/dist/designer/assets/GridMenus-8gTNssgV.js +8 -0
  98. package/dist/designer/assets/SvChartMenu-BDoeqGz6.js +1 -0
  99. package/dist/designer/assets/SvChartMenu-BYO9cYdy.css +1 -0
  100. package/dist/designer/assets/SvDateRangeInput-BBRzrQeg.js +1 -0
  101. package/dist/designer/assets/SvDateTimePicker-DCPg7WGN.js +1 -0
  102. package/dist/designer/assets/SvGridCellEditor-DMoWJjEI.js +4 -0
  103. package/dist/designer/assets/SvGridChart-BgLuPO7I.css +1 -0
  104. package/dist/designer/assets/SvGridChart-Cy1ATrWh.js +3 -0
  105. package/dist/designer/assets/SvGridChartBuilder-08YWWeqY.css +1 -0
  106. package/dist/designer/assets/SvGridChartBuilder-eQ3mn0L9.js +1 -0
  107. package/dist/designer/assets/SvGridChartPanel-4Pc8y5yO.css +1 -0
  108. package/dist/designer/assets/SvGridChartPanel-CATdVc9X.js +4 -0
  109. package/dist/designer/assets/{SvGridChartView-DUc-1RUf.css → SvGridChartView-7msfnWZT.css} +1 -1
  110. package/dist/designer/assets/SvGridChartView-CmsZtCED.js +1 -0
  111. package/dist/designer/assets/SvGridDropdown-Cjz0H-fI.js +1 -0
  112. package/dist/designer/assets/SvListBox-BDS66lmZ.js +110 -0
  113. package/dist/designer/assets/SvMenuList-DJ47ba1h.css +1 -0
  114. package/dist/designer/assets/SvMenuList-Dgq2D5VN.js +1 -0
  115. package/dist/designer/assets/SvTabs-2mHC6oaz.js +1 -0
  116. package/dist/designer/assets/SvTabs-DKmwb5p1.css +1 -0
  117. package/dist/designer/assets/cell-formatting-BbubJTVz.js +1 -0
  118. package/dist/designer/assets/chart-Cn7MnNqA.js +1 -0
  119. package/dist/designer/assets/chart-export-B6bkQ3X8.js +11 -0
  120. package/dist/designer/assets/chart-export-pdf-BbA28-gt.js +11 -0
  121. package/dist/designer/assets/chart-panel-messages-Dz7PTIqT.js +1 -0
  122. package/dist/designer/assets/chart-summary-BD1qYB2R.js +1 -0
  123. package/dist/designer/assets/chart-trend-B8xr5LuD.js +1 -0
  124. package/dist/designer/assets/chart-validate-BMqM-qkF.js +1 -0
  125. package/dist/designer/assets/column-resize-BYDzR1Ve.js +1 -0
  126. package/dist/designer/assets/date-format-B8JbEtIG.js +1 -0
  127. package/dist/designer/assets/date-format-DKS-z0xS.css +1 -0
  128. package/dist/designer/assets/{dismissable-BO547MH9.js → dismissable-ChWRPkoa.js} +1 -1
  129. package/dist/designer/assets/editor-contract-Bpoa7A5g.js +1 -0
  130. package/dist/designer/assets/{export-format-D-eP4b2l.js → export-format-DGckmgKr.js} +1 -1
  131. package/dist/designer/assets/focus-trap-V2-6Fy9I.js +1 -0
  132. package/dist/designer/assets/{index-C_a9Cj8Y.js → index-D5bVbuzI.js} +318 -315
  133. package/dist/designer/assets/index-_JVFxt02.css +1 -0
  134. package/dist/designer/assets/list-option-BP_dWS66.js +1 -0
  135. package/dist/designer/assets/row-resize-BInFWCpr.js +1 -0
  136. package/dist/designer/assets/server-block-cache-CXJKkJpy.js +1 -0
  137. package/dist/designer/assets/src-CITpcm6b.js +1 -0
  138. package/dist/designer/assets/src-DUQ4xE3x.js +58 -0
  139. package/dist/designer/assets/validate-C3B8QKsM.js +1 -0
  140. package/dist/designer/index.html +29 -19
  141. package/dist/export-pdf.d.ts +164 -0
  142. package/dist/export-pdf.js +346 -15
  143. package/dist/export.js +25 -10
  144. package/dist/gantt/SvGridGantt.svelte +2890 -0
  145. package/dist/gantt/SvGridGantt.svelte.d.ts +30 -0
  146. package/dist/gantt/gantt-config.d.ts +73 -0
  147. package/dist/gantt/gantt-config.js +1 -0
  148. package/dist/gantt/gantt-critical-path.d.ts +67 -0
  149. package/dist/gantt/gantt-critical-path.js +207 -0
  150. package/dist/gantt/gantt-model.d.ts +257 -0
  151. package/dist/gantt/gantt-model.js +651 -0
  152. package/dist/gantt/gantt-resources.d.ts +59 -0
  153. package/dist/gantt/gantt-resources.js +71 -0
  154. package/dist/gantt/gantt.d.ts +7 -0
  155. package/dist/gantt/gantt.js +36 -0
  156. package/dist/gantt/index.d.ts +15 -0
  157. package/dist/gantt/index.js +22 -0
  158. package/dist/gantt/timeline-arrows.d.ts +102 -0
  159. package/dist/gantt/timeline-arrows.js +181 -0
  160. package/dist/import.d.ts +2 -2
  161. package/dist/import.js +1 -1
  162. package/dist/index.d.ts +93 -3
  163. package/dist/index.js +107 -3
  164. package/dist/install.js +13 -1
  165. package/dist/license-core.d.ts +17 -1
  166. package/dist/license-core.js +16 -5
  167. package/dist/license.d.ts +18 -2
  168. package/dist/license.js +71 -6
  169. package/dist/node/studio.js +203 -9
  170. package/dist/pivot-chart.d.ts +25 -1
  171. package/dist/pivot-chart.js +25 -69
  172. package/dist/pivot-enable.js +2 -2
  173. package/dist/scheduler-dependencies.d.ts +35 -0
  174. package/dist/scheduler-dependencies.js +36 -1
  175. package/dist/scheduler.js +2 -2
  176. package/dist/selection-bar.js +2 -2
  177. package/dist/server/SvGroupCell.svelte +213 -0
  178. package/dist/server/SvGroupCell.svelte.d.ts +62 -0
  179. package/dist/server/SvRowGroupPanel.svelte +322 -0
  180. package/dist/server/SvRowGroupPanel.svelte.d.ts +37 -0
  181. package/dist/server/enable.d.ts +17 -0
  182. package/dist/server/enable.js +49 -0
  183. package/dist/server/index.d.ts +22 -0
  184. package/dist/server/index.js +24 -0
  185. package/dist/server/messages.d.ts +45 -0
  186. package/dist/server/messages.js +35 -0
  187. package/dist/server/server-group-model.d.ts +104 -0
  188. package/dist/server/server-group-model.js +272 -0
  189. package/dist/server/server-pivot.d.ts +46 -0
  190. package/dist/server/server-pivot.js +57 -0
  191. package/dist/server/server-row-model.d.ts +547 -0
  192. package/dist/server/server-row-model.js +1551 -0
  193. package/dist/server/server-selection.d.ts +99 -0
  194. package/dist/server/server-selection.js +215 -0
  195. package/dist/server/svgrid-adapter.d.ts +155 -0
  196. package/dist/server/svgrid-adapter.js +202 -0
  197. package/dist/sheet/address.d.ts +43 -0
  198. package/dist/sheet/address.js +81 -0
  199. package/dist/sheet/ast.d.ts +138 -0
  200. package/dist/sheet/ast.js +70 -0
  201. package/dist/sheet/auto-filter.d.ts +120 -0
  202. package/dist/sheet/auto-filter.js +295 -0
  203. package/dist/sheet/autocomplete.d.ts +51 -0
  204. package/dist/sheet/autocomplete.js +248 -0
  205. package/dist/sheet/cell-images.d.ts +39 -0
  206. package/dist/sheet/cell-images.js +90 -0
  207. package/dist/sheet/cell-types.d.ts +58 -0
  208. package/dist/sheet/cell-types.js +96 -0
  209. package/dist/sheet/coerce.d.ts +71 -0
  210. package/dist/sheet/coerce.js +289 -0
  211. package/dist/sheet/commands.d.ts +89 -0
  212. package/dist/sheet/commands.js +230 -0
  213. package/dist/sheet/comments.d.ts +63 -0
  214. package/dist/sheet/comments.js +131 -0
  215. package/dist/sheet/conditional-formats.d.ts +167 -0
  216. package/dist/sheet/conditional-formats.js +341 -0
  217. package/dist/sheet/csv.d.ts +32 -0
  218. package/dist/sheet/csv.js +158 -0
  219. package/dist/sheet/culture.d.ts +87 -0
  220. package/dist/sheet/culture.js +247 -0
  221. package/dist/sheet/delta.d.ts +102 -0
  222. package/dist/sheet/delta.js +203 -0
  223. package/dist/sheet/deps.d.ts +104 -0
  224. package/dist/sheet/deps.js +274 -0
  225. package/dist/sheet/document.d.ts +252 -0
  226. package/dist/sheet/document.js +465 -0
  227. package/dist/sheet/edit-keys.d.ts +14 -0
  228. package/dist/sheet/edit-keys.js +40 -0
  229. package/dist/sheet/engine.d.ts +67 -0
  230. package/dist/sheet/engine.js +19 -0
  231. package/dist/sheet/entry.d.ts +35 -0
  232. package/dist/sheet/entry.js +226 -0
  233. package/dist/sheet/error-check.d.ts +49 -0
  234. package/dist/sheet/error-check.js +83 -0
  235. package/dist/sheet/evaluate-steps.d.ts +48 -0
  236. package/dist/sheet/evaluate-steps.js +196 -0
  237. package/dist/sheet/evaluate.d.ts +128 -0
  238. package/dist/sheet/evaluate.js +1049 -0
  239. package/dist/sheet/filter-files.d.ts +37 -0
  240. package/dist/sheet/filter-files.js +465 -0
  241. package/dist/sheet/find-replace.d.ts +62 -0
  242. package/dist/sheet/find-replace.js +152 -0
  243. package/dist/sheet/format-store.d.ts +114 -0
  244. package/dist/sheet/format-store.js +243 -0
  245. package/dist/sheet/freeze.d.ts +54 -0
  246. package/dist/sheet/freeze.js +58 -0
  247. package/dist/sheet/from-rows.d.ts +14 -0
  248. package/dist/sheet/from-rows.js +50 -0
  249. package/dist/sheet/function-catalog.d.ts +10 -0
  250. package/dist/sheet/function-catalog.js +385 -0
  251. package/dist/sheet/functions.d.ts +28 -0
  252. package/dist/sheet/functions.js +634 -0
  253. package/dist/sheet/goal-seek.d.ts +73 -0
  254. package/dist/sheet/goal-seek.js +153 -0
  255. package/dist/sheet/index.d.ts +80 -0
  256. package/dist/sheet/index.js +80 -0
  257. package/dist/sheet/links.d.ts +57 -0
  258. package/dist/sheet/links.js +174 -0
  259. package/dist/sheet/merges.d.ts +71 -0
  260. package/dist/sheet/merges.js +137 -0
  261. package/dist/sheet/messages.d.ts +778 -0
  262. package/dist/sheet/messages.js +806 -0
  263. package/dist/sheet/names.d.ts +31 -0
  264. package/dist/sheet/names.js +87 -0
  265. package/dist/sheet/navigate.d.ts +52 -0
  266. package/dist/sheet/navigate.js +135 -0
  267. package/dist/sheet/number-format.d.ts +110 -0
  268. package/dist/sheet/number-format.js +905 -0
  269. package/dist/sheet/objects.d.ts +106 -0
  270. package/dist/sheet/objects.js +149 -0
  271. package/dist/sheet/ods-document.d.ts +44 -0
  272. package/dist/sheet/ods-document.js +1275 -0
  273. package/dist/sheet/open-file.d.ts +26 -0
  274. package/dist/sheet/open-file.js +56 -0
  275. package/dist/sheet/outline.d.ts +82 -0
  276. package/dist/sheet/outline.js +228 -0
  277. package/dist/sheet/packs/array.d.ts +16 -0
  278. package/dist/sheet/packs/array.js +172 -0
  279. package/dist/sheet/packs/database.d.ts +42 -0
  280. package/dist/sheet/packs/database.js +142 -0
  281. package/dist/sheet/packs/engineering.d.ts +2 -0
  282. package/dist/sheet/packs/engineering.js +296 -0
  283. package/dist/sheet/packs/financial.d.ts +5 -0
  284. package/dist/sheet/packs/financial.js +220 -0
  285. package/dist/sheet/packs/math-stats.d.ts +2 -0
  286. package/dist/sheet/packs/math-stats.js +372 -0
  287. package/dist/sheet/packs/special.d.ts +44 -0
  288. package/dist/sheet/packs/special.js +187 -0
  289. package/dist/sheet/packs/stats-dist.d.ts +2 -0
  290. package/dist/sheet/packs/stats-dist.js +785 -0
  291. package/dist/sheet/packs/text-date.d.ts +2 -0
  292. package/dist/sheet/packs/text-date.js +332 -0
  293. package/dist/sheet/packs/trig.d.ts +2 -0
  294. package/dist/sheet/packs/trig.js +73 -0
  295. package/dist/sheet/page-setup.d.ts +73 -0
  296. package/dist/sheet/page-setup.js +73 -0
  297. package/dist/sheet/palette.d.ts +19 -0
  298. package/dist/sheet/palette.js +84 -0
  299. package/dist/sheet/parse.d.ts +13 -0
  300. package/dist/sheet/parse.js +140 -0
  301. package/dist/sheet/paste-special.d.ts +186 -0
  302. package/dist/sheet/paste-special.js +601 -0
  303. package/dist/sheet/pivot-range.d.ts +160 -0
  304. package/dist/sheet/pivot-range.js +333 -0
  305. package/dist/sheet/presence.d.ts +73 -0
  306. package/dist/sheet/presence.js +79 -0
  307. package/dist/sheet/print.d.ts +104 -0
  308. package/dist/sheet/print.js +169 -0
  309. package/dist/sheet/protection.d.ts +75 -0
  310. package/dist/sheet/protection.js +101 -0
  311. package/dist/sheet/rects.d.ts +45 -0
  312. package/dist/sheet/rects.js +112 -0
  313. package/dist/sheet/refs.d.ts +130 -0
  314. package/dist/sheet/refs.js +413 -0
  315. package/dist/sheet/ribbon-icons.d.ts +31 -0
  316. package/dist/sheet/ribbon-icons.js +536 -0
  317. package/dist/sheet/ribbon.d.ts +173 -0
  318. package/dist/sheet/ribbon.js +1054 -0
  319. package/dist/sheet/sheet-kinds.d.ts +74 -0
  320. package/dist/sheet/sheet-kinds.js +91 -0
  321. package/dist/sheet/shortcuts.d.ts +174 -0
  322. package/dist/sheet/shortcuts.js +674 -0
  323. package/dist/sheet/sort.d.ts +51 -0
  324. package/dist/sheet/sort.js +107 -0
  325. package/dist/sheet/sparklines.d.ts +111 -0
  326. package/dist/sheet/sparklines.js +204 -0
  327. package/dist/sheet/structure.d.ts +87 -0
  328. package/dist/sheet/structure.js +166 -0
  329. package/dist/sheet/table-styles.d.ts +74 -0
  330. package/dist/sheet/table-styles.js +152 -0
  331. package/dist/sheet/tables.d.ts +89 -0
  332. package/dist/sheet/tables.js +178 -0
  333. package/dist/sheet/tokenize.d.ts +71 -0
  334. package/dist/sheet/tokenize.js +355 -0
  335. package/dist/sheet/transforms.d.ts +76 -0
  336. package/dist/sheet/transforms.js +154 -0
  337. package/dist/sheet/validation.d.ts +108 -0
  338. package/dist/sheet/validation.js +278 -0
  339. package/dist/sheet/workbook.d.ts +217 -0
  340. package/dist/sheet/workbook.js +1120 -0
  341. package/dist/sheet/xls-cfb.d.ts +32 -0
  342. package/dist/sheet/xls-cfb.js +290 -0
  343. package/dist/sheet/xls-document.d.ts +10 -0
  344. package/dist/sheet/xls-document.js +1243 -0
  345. package/dist/sheet/xls-formula.d.ts +40 -0
  346. package/dist/sheet/xls-formula.js +569 -0
  347. package/dist/sheet/xlsx-document.d.ts +108 -0
  348. package/dist/sheet/xlsx-document.js +1849 -0
  349. package/dist/sheet/xlsx-drawing.d.ts +99 -0
  350. package/dist/sheet/xlsx-drawing.js +420 -0
  351. package/dist/sheet-enable.d.ts +6 -0
  352. package/dist/sheet-enable.js +45 -0
  353. package/dist/sheet-text.d.ts +7 -0
  354. package/dist/sheet-text.js +29 -0
  355. package/dist/sources/auth-supabase.js +2 -2
  356. package/dist/sources/realtime-supabase.js +2 -2
  357. package/dist/sources/rest.d.ts +6 -2
  358. package/dist/sources/rest.js +42 -7
  359. package/dist/sources/supabase.d.ts +10 -1
  360. package/dist/sources/supabase.js +73 -40
  361. package/dist/studio/emit-project.js +14 -1
  362. package/dist/studio/index.js +1 -1
  363. package/dist/studio/project.d.ts +11 -2
  364. package/dist/studio/project.js +5 -2
  365. package/dist/studio/ui-components.generated.js +170 -3
  366. package/dist/sveltekit/in-memory.d.ts +2 -2
  367. package/dist/sveltekit/in-memory.js +125 -4
  368. package/dist/sveltekit/index.d.ts +1 -1
  369. package/dist/sveltekit/index.js +1 -1
  370. package/dist/sveltekit/query-plan.d.ts +50 -4
  371. package/dist/sveltekit/query-plan.js +25 -3
  372. package/dist/sveltekit/sql-source.d.ts +6 -0
  373. package/dist/sveltekit/sql-source.js +34 -6
  374. package/dist/sveltekit/sql.d.ts +31 -0
  375. package/dist/sveltekit/sql.js +135 -25
  376. package/dist/sveltekit/transport.d.ts +10 -2
  377. package/dist/sveltekit/transport.js +30 -6
  378. package/dist/upgrade-prompt.d.ts +1 -1
  379. package/dist/version.d.ts +1 -1
  380. package/dist/version.js +1 -1
  381. package/dist/watermark.js +35 -2
  382. package/dist/wc/GridMenus-By9vPuq0.js +1088 -0
  383. package/dist/wc/SvChartMenu-CQNrQGT2.js +308 -0
  384. package/dist/wc/SvDateRangeInput-DR6m7bSM.js +199 -0
  385. package/dist/wc/SvDateTimePicker-D-vRnaMo.js +771 -0
  386. package/dist/wc/SvField-B_kurx_P.js +149 -0
  387. package/dist/wc/SvGrid.helpers-BdVDtjUm.js +135 -0
  388. package/dist/wc/SvGridCellEditor-Bnf1Kr5C.js +560 -0
  389. package/dist/wc/SvGridChart-BqUJh2pG.js +3572 -0
  390. package/dist/wc/SvGridChartBuilder-CGycC5cn.js +988 -0
  391. package/dist/wc/SvGridChartPanel-CRnizsHD.js +1746 -0
  392. package/dist/wc/SvGridChartView-D1pa_xMy.js +47 -0
  393. package/dist/wc/SvGridDropdown-45WsObLL.js +259 -0
  394. package/dist/wc/SvModal-DrfOYYyX.js +189 -0
  395. package/dist/wc/cell-formatting-CBfgahv1.js +86 -0
  396. package/dist/wc/chart-6OXlybVT.js +4341 -0
  397. package/dist/wc/chart-export-CeSADGfi.js +135 -0
  398. package/dist/wc/chart-export-pdf-BGko7MER.js +104 -0
  399. package/dist/wc/chart-summary-2m3ia1-n.js +137 -0
  400. package/dist/wc/chart-trend-CQOQtTMl.js +50 -0
  401. package/dist/wc/chart-validate-CD6ptiwg.js +180 -0
  402. package/dist/wc/client-DQIzjDBG.js +3064 -0
  403. package/dist/wc/column-resize-DUPgynvc.js +101 -0
  404. package/dist/wc/date-format-DS-z_h9v.js +1130 -0
  405. package/dist/wc/dismissable-CQ6XFXsk.js +45 -0
  406. package/dist/wc/editor-contract-peBDxir_.js +22 -0
  407. package/dist/wc/editor-registry-DxGKqcvx.js +24 -0
  408. package/dist/wc/focus-trap-Dbb2tJxb.js +65 -0
  409. package/dist/wc/list-option-DrRyivWp.js +82 -0
  410. package/dist/wc/popover-WsGlvtQv.js +69 -0
  411. package/dist/wc/positioning-BiKLfu1E.js +112 -0
  412. package/dist/wc/react.d.ts +41 -0
  413. package/dist/wc/react.js +90 -0
  414. package/dist/wc/rolldown-runtime-Dy4uBu1J.js +11 -0
  415. package/dist/wc/row-drag-touch-CycRR65n.js +93 -0
  416. package/dist/wc/row-resize-limG_N1z.js +111 -0
  417. package/dist/wc/sv-sheet-element.d.ts +97 -0
  418. package/dist/wc/sv-sheet-element.js +44213 -0
  419. package/dist/wc/svelte-virtualizer.svelte-CXtQy2TQ.js +530 -0
  420. package/dist/wc/validate-BqDthkNr.js +88 -0
  421. package/dist/wc/vue.d.ts +31 -0
  422. package/dist/wc/vue.js +75 -0
  423. package/package.json +36 -6
  424. package/dist/designer/assets/GridMenus-B1JtIN21.js +0 -8
  425. package/dist/designer/assets/SvDateRangeInput-CjO7nn_x.js +0 -1
  426. package/dist/designer/assets/SvDateTimePicker-ByBD_ov6.js +0 -1
  427. package/dist/designer/assets/SvField-YDLipR6O.css +0 -1
  428. package/dist/designer/assets/SvField-cj1PFNgZ.js +0 -1
  429. package/dist/designer/assets/SvGridCellEditor-0W1L2hJ1.js +0 -2
  430. package/dist/designer/assets/SvGridChart-DBOR4xcz.js +0 -2
  431. package/dist/designer/assets/SvGridChart-fkMWeh1J.css +0 -1
  432. package/dist/designer/assets/SvGridChartPanel-symrhNnR.js +0 -11
  433. package/dist/designer/assets/SvGridChartView-BmRxq6mU.js +0 -1
  434. package/dist/designer/assets/SvGridDropdown-Bb3HH2Aj.js +0 -1
  435. package/dist/designer/assets/SvListBox-1oUF6Iav.js +0 -110
  436. package/dist/designer/assets/cell-formatting-wr5wm7US.js +0 -1
  437. package/dist/designer/assets/chart-DXFganU8.js +0 -1
  438. package/dist/designer/assets/column-resize-C_inr5zT.js +0 -1
  439. package/dist/designer/assets/date-format-DGagAqRc.css +0 -1
  440. package/dist/designer/assets/date-format-onlYDsrY.js +0 -1
  441. package/dist/designer/assets/easing-zaypKrr0.js +0 -3
  442. package/dist/designer/assets/index-k2stW6L8.css +0 -1
  443. package/dist/designer/assets/row-resize-B0FWHcNr.js +0 -1
  444. package/dist/designer/assets/src-D9p27OGC.js +0 -58
  445. package/dist/designer/assets/validate-h-aslRV9.js +0 -1
@@ -19,6 +19,8 @@
19
19
  *
20
20
  * SvPivotDesigner {data} {fields} bind:layout
21
21
  */
22
+ import { untrack } from 'svelte'
23
+
22
24
  import {
23
25
  SvGrid,
24
26
  SvGridChart,
@@ -26,6 +28,7 @@
26
28
  tableFeatures,
27
29
  rowSortingFeature,
28
30
  columnFilteringFeature,
31
+ renderComponent,
29
32
  renderSnippet,
30
33
  portalToBody,
31
34
  popIn,
@@ -35,7 +38,10 @@
35
38
  type ColumnDef,
36
39
  type ChartType,
37
40
  type MenuItem,
41
+ type ServerAggregation,
38
42
  } from '@svgrid/grid'
43
+ import SvGroupCell from './server/SvGroupCell.svelte'
44
+ import { serverGroupText, type ServerRowModel, type ServerRowModelGridRow } from './server/server-row-model'
39
45
  import { createPivotModel, filterCollapsedPivotRows, type PivotRow, type PivotAggregatorId } from './pivot'
40
46
  import { pivotToChartSpec } from './pivot-chart'
41
47
  import {
@@ -44,8 +50,8 @@
44
50
  } from './pivot-designer'
45
51
 
46
52
  type Props = {
47
- /** Flat input rows. */
48
- data: T[]
53
+ /** Flat input rows. Not read in server mode. */
54
+ data?: T[]
49
55
  /** All fields the user can pick from the rail. */
50
56
  fields: PivotField<T>[]
51
57
  /** The current pivot layout. Bindable so the consumer can persist it. */
@@ -87,7 +93,8 @@
87
93
  layout: PivotLayout,
88
94
  ) => ColumnDef<typeof features, PivotRow>[]
89
95
  /** Click handler forwarded to the embedded SvGrid - typically used
90
- * to drive a drill-through side panel. */
96
+ * to drive a drill-through side panel. In server mode `row` is the
97
+ * model's grid row (its `__group` says which group or leaf it is). */
91
98
  onCellClick?: (ctx: { columnId: string; row: PivotRow; value: unknown }) => void
92
99
  /** Offer a Table <-> Chart view toggle (same layout as a live chart). Default true. */
93
100
  chartable?: boolean
@@ -149,9 +156,29 @@
149
156
  * narrow the source rows (they drive `layout.filters`). Default false.
150
157
  */
151
158
  toolTabs?: boolean
159
+
160
+ // ---- Server mode ----------------------------------------------------
161
+ /**
162
+ * A `createServerRowModel` controller. The designer then drives it
163
+ * instead of pivoting in the browser - Rows become `groupBy`, Columns
164
+ * `pivotBy`, Values `aggregations` - and the embedded grid mounts it
165
+ * through `rowModel`, showing the columns the backend's
166
+ * `pivotResultFields` describe. `data` is not read. The Filters well,
167
+ * the subtotal switches and the chart view are off: filters belong to
168
+ * the grid's own filter UI, footers and totals to the model's options.
169
+ */
170
+ server?: ServerRowModel<T>
171
+ /** The group column the designer adds in server mode. */
172
+ groupColumn?: { header?: string; width?: number; leafField?: string }
173
+ /**
174
+ * `'immediate'` (default) sends every drag to `onLayoutChange` and the
175
+ * server. `'deferred'` collects edits and shows Apply / Cancel, so one
176
+ * slice-and-dice session is one request.
177
+ */
178
+ applyMode?: 'immediate' | 'deferred'
152
179
  }
153
180
  let {
154
- data,
181
+ data = [],
155
182
  fields,
156
183
  layout = $bindable<PivotLayout>(defaultLayoutFor([])),
157
184
  onLayoutChange,
@@ -181,8 +208,27 @@
181
208
  hiddenFields = $bindable<string[]>([]),
182
209
  onHiddenFieldsChange,
183
210
  toolTabs = false,
211
+ server,
212
+ groupColumn,
213
+ applyMode = 'immediate',
184
214
  }: Props = $props()
185
215
 
216
+ // ---- Deferred apply -------------------------------------------------
217
+ // `layout` is what the wells show; `committed` is what the pivot (or the
218
+ // server) runs. They differ only in deferred mode, between an edit and
219
+ // Apply.
220
+ let committed = $state<PivotLayout>(layout)
221
+ const deferred = $derived(applyMode === 'deferred')
222
+ const applied = $derived(deferred ? committed : layout)
223
+ const dirty = $derived(deferred && JSON.stringify(layout) !== JSON.stringify(committed))
224
+ function applyLayout() {
225
+ committed = layout
226
+ onLayoutChange?.(layout)
227
+ }
228
+ function cancelLayout() {
229
+ layout = committed
230
+ }
231
+
186
232
  // ---- Columns / Filters tab rail ----------------------------------
187
233
  let activeTab = $state<'columns' | 'filters'>('columns')
188
234
  let filterCollapsed = $state<Set<string>>(new Set())
@@ -224,7 +270,7 @@
224
270
  return () => window.removeEventListener('mousedown', on)
225
271
  })
226
272
 
227
- const showPivotToggle = $derived(!!flatColumns)
273
+ const showPivotToggle = $derived(!!flatColumns || !!server)
228
274
  function setPivotMode(on: boolean) {
229
275
  pivotMode = on
230
276
  onPivotModeChange?.(on)
@@ -236,10 +282,12 @@
236
282
  $effect.pre(() => {
237
283
  if (!layout || (!layout.rows.length && !layout.cols.length && !layout.values.length && !layout.filters.length)) {
238
284
  layout = defaultLayoutFor(fields)
285
+ committed = layout
239
286
  }
240
287
  })
241
288
 
242
289
  const features = tableFeatures({ rowSortingFeature, columnFilteringFeature })
290
+ const filtersWell = $derived(showFiltersWell && !server)
243
291
  const uid = `pvd-${Math.random().toString(36).slice(2, 8)}`
244
292
 
245
293
  // Lookup helpers -----------------------------------------------------
@@ -331,6 +379,7 @@
331
379
  // ---- Mutation helpers ---------------------------------------------
332
380
  function emit(next: PivotLayout) {
333
381
  layout = next
382
+ if (deferred) return
334
383
  onLayoutChange?.(next)
335
384
  }
336
385
  function defaultWellFor(field: PivotField<T>): Well {
@@ -484,9 +533,9 @@
484
533
  // The pivot model itself has no filtering, but the well clearly should:
485
534
  // a Filters chip with `allowed` restricts which rows reach the model.
486
535
  const filteredData = $derived.by(() => {
487
- if (!layout.filters.length) return data
536
+ if (!applied.filters.length) return data
488
537
  return data.filter((row) => {
489
- for (const f of layout.filters) {
538
+ for (const f of applied.filters) {
490
539
  if (f.allowed == null) continue
491
540
  const v = row[f.field]
492
541
  if (!f.allowed.includes(String(v))) return false
@@ -499,41 +548,145 @@
499
548
  // Whenever the layout or data changes, re-run the pivot. Empty layouts
500
549
  // are tolerated: the grid will show a friendly empty state.
501
550
  const pivot = $derived.by(() => {
502
- if (!layout.values.length && !layout.rows.length && !layout.cols.length) return null
503
- if (!layout.values.length) return null
551
+ if (server) return null
552
+ if (!applied.values.length && !applied.rows.length && !applied.cols.length) return null
553
+ if (!applied.values.length) return null
504
554
  return createPivotModel(filteredData, {
505
- rows: layout.rows as Array<keyof T & string>,
506
- cols: layout.cols as Array<keyof T & string>,
507
- values: layout.values.map((v) => ({
555
+ rows: applied.rows as Array<keyof T & string>,
556
+ cols: applied.cols as Array<keyof T & string>,
557
+ values: applied.values.map((v) => ({
508
558
  field: v.field as keyof T & string,
509
559
  agg: v.agg,
510
560
  label: v.label,
511
561
  format: v.format,
512
562
  })),
513
- grandTotalRow: !layout.hideGrandTotals,
514
- grandTotalCol: !layout.hideGrandTotals,
515
- rowSubtotals: !layout.hideSubtotals,
563
+ grandTotalRow: !applied.hideGrandTotals,
564
+ grandTotalCol: !applied.hideGrandTotals,
565
+ rowSubtotals: !applied.hideSubtotals,
516
566
  })
517
567
  })
518
568
  $effect(() => {
519
569
  if (pivot) onPivot?.(pivot.rows, pivot.columns)
520
570
  })
521
571
 
572
+ // ---- Server mode ----------------------------------------------------
573
+ // The applied layout drives the model in one call, so a designer edit is
574
+ // one reload. Aggregators the contract has no word for are left out.
575
+ const SERVER_FN: Partial<Record<PivotAggregatorId, ServerAggregation['fn']>> = {
576
+ sum: 'sum',
577
+ avg: 'avg',
578
+ min: 'min',
579
+ max: 'max',
580
+ count: 'count',
581
+ }
582
+ $effect(() => {
583
+ if (!server) return
584
+ const l = applied
585
+ server.setLayout({
586
+ groupBy: [...l.rows],
587
+ pivotBy: [...l.cols],
588
+ pivotMode: pivotMode && l.cols.length > 0,
589
+ aggregations: l.values.flatMap((v) => {
590
+ const fn = SERVER_FN[v.agg]
591
+ return fn ? [{ col: v.field, fn }] : []
592
+ }),
593
+ // The same switch the client pivot reads as its total column.
594
+ pivotRowTotals: !l.hideGrandTotals,
595
+ })
596
+ })
597
+ // The model is plain; a version bump re-reads its pivot columns.
598
+ let serverVersion = $state(0)
599
+ $effect(() => {
600
+ if (!server) return
601
+ return server.subscribe(() => {
602
+ serverVersion += 1
603
+ })
604
+ })
605
+ type ServerCol = ColumnDef<typeof features, ServerRowModelGridRow<T>>
606
+ const serverGroupColumn = $derived.by((): ServerCol | null => {
607
+ if (!server) return null
608
+ const model = server
609
+ return {
610
+ id: 'sv-group',
611
+ header: groupColumn?.header ?? 'Group',
612
+ width: groupColumn?.width ?? 260,
613
+ sortable: false,
614
+ filterable: false,
615
+ fieldFn: (row) => serverGroupText(row, groupColumn?.leafField as (keyof T & string) | undefined),
616
+ cell: (ctx) =>
617
+ renderComponent(SvGroupCell, {
618
+ row: ctx.row.original,
619
+ onToggle: () => model.group?.onToggle(ctx.row.original),
620
+ leafField: groupColumn?.leafField,
621
+ }),
622
+ } as ServerCol
623
+ })
624
+ // Pivot off: the group column (when grouping) and the app's own columns.
625
+ const serverColumns = $derived.by((): ServerCol[] => {
626
+ const own = (flatColumns ?? []) as unknown as ServerCol[]
627
+ return applied.rows.length && serverGroupColumn ? [serverGroupColumn, ...own] : own
628
+ })
629
+ // Pivot on: the group column, then the columns the model built from the
630
+ // backend's `pivotResultFields`. Undefined before the first pivoted
631
+ // response, so the grid keeps `serverColumns` until then.
632
+ const serverPivotColumns = $derived.by((): ServerCol[] | undefined => {
633
+ void serverVersion
634
+ if (!server) return undefined
635
+ const cols = server.pivotResultColumns as ServerCol[] | null
636
+ if (!cols) return undefined
637
+ return serverGroupColumn ? [serverGroupColumn, ...cols] : cols
638
+ })
639
+
522
640
  // ---- Table <-> Chart view (the same layout as a live pivot chart) ----
523
- let view = $state<'table' | 'chart'>(defaultView === 'chart' && chartable ? 'chart' : 'table')
641
+ let view = $state<'table' | 'chart'>(untrack(() => (defaultView === 'chart' && chartable ? 'chart' : 'table')))
524
642
  let chartType = $state<ChartType>('bar')
525
643
  let chartStacked = $state(false)
526
- const CHART_TYPES: Array<{ value: ChartType; label: string }> = [
527
- { value: 'bar', label: 'Bar' },
528
- { value: 'line', label: 'Line' },
529
- { value: 'area', label: 'Area' },
530
- { value: 'pie', label: 'Pie' },
644
+ let chartStacked100 = $state(false)
645
+ let chartHorizontal = $state(false)
646
+ // Every shape a pivot's categories + series can take, grouped the way the
647
+ // grid panel groups them. The ones missing (scatter, gauge, box plot,
648
+ // histogram, ranges, bullet, candles) read rows one by one.
649
+ const CHART_TYPES: Array<{ value: ChartType; label: string; group: string }> = [
650
+ { value: 'bar', label: 'Bar', group: 'Compare' },
651
+ { value: 'line', label: 'Line', group: 'Compare' },
652
+ { value: 'area', label: 'Area', group: 'Compare' },
653
+ { value: 'lollipop', label: 'Lollipop', group: 'Compare' },
654
+ { value: 'pareto', label: 'Pareto', group: 'Compare' },
655
+ { value: 'radial-column', label: 'Radial column', group: 'Compare' },
656
+ { value: 'radial-bar', label: 'Radial bar', group: 'Compare' },
657
+ { value: 'nightingale', label: 'Nightingale', group: 'Compare' },
658
+ { value: 'pie', label: 'Pie', group: 'Part of a whole' },
659
+ { value: 'funnel', label: 'Funnel', group: 'Flow' },
660
+ { value: 'waterfall', label: 'Waterfall', group: 'Flow' },
661
+ { value: 'radar', label: 'Radar', group: 'Distribution' },
662
+ { value: 'heatmap', label: 'Heat map', group: 'Distribution' },
663
+ { value: 'stream', label: 'Stream', group: 'Over time' },
531
664
  ]
532
- const chartSpec = $derived.by(() =>
533
- pivot && chartable && view === 'chart'
534
- ? pivotToChartSpec(pivot, { type: chartType, stacked: chartStacked })
535
- : null,
536
- )
665
+ const CHART_GROUPS = [...new Set(CHART_TYPES.map((t) => t.group))]
666
+ const STACKABLE: ChartType[] = ['bar', 'line', 'area', 'radial-column']
667
+ // The measures' formats travel to the chart when they agree; a layout
668
+ // mixing a currency and a count formats plainly rather than putting a "$"
669
+ // on the count. The chip's own format wins over the field's.
670
+ const chartFormat = $derived.by(() => {
671
+ const formats = layout.values.map((v) => v.format ?? fields.find((f) => f.field === v.field)?.format)
672
+ const first = formats[0]
673
+ if (!first) return undefined
674
+ const same = formats.every((f) => f && f.type === first.type && (f.type !== 'currency' || (f as { currency?: string }).currency === (first as { currency?: string }).currency))
675
+ return same ? first : undefined
676
+ })
677
+ const chartSpec = $derived.by(() => {
678
+ if (!pivot || !chartable || view !== 'chart') return null
679
+ const spec = pivotToChartSpec(pivot, {
680
+ type: chartType,
681
+ stacked: chartStacked && STACKABLE.includes(chartType),
682
+ stacked100: chartStacked100 && (chartType === 'bar' || chartType === 'area'),
683
+ format: chartFormat,
684
+ })
685
+ if (chartHorizontal && chartType === 'bar') spec.orientation = 'horizontal'
686
+ // A stream is a stacked area on a wiggle baseline; the box has nothing to add.
687
+ if (chartType === 'stream') { spec.stacked = true; spec.stackOffset = 'wiggle' }
688
+ return spec
689
+ })
537
690
 
538
691
  // ---- Expand / collapse (when `expandable` is on) ------------------
539
692
  // We hold a `collapsed` set of pivot row ids; descendants of a
@@ -797,28 +950,56 @@
797
950
  {/if}
798
951
  </div>
799
952
  {/if}
800
- <label class="pvd-toggle">
801
- <input type="checkbox" checked={!layout.hideSubtotals} onchange={toggleHideSubtotals} /> Subtotals
802
- </label>
803
- <label class="pvd-toggle">
804
- <input type="checkbox" checked={!layout.hideGrandTotals} onchange={toggleHideGrandTotals} /> Grand totals
805
- </label>
806
- {#if chartable}
953
+ {#if !server}
954
+ <label class="pvd-toggle">
955
+ <input type="checkbox" checked={!layout.hideSubtotals} onchange={toggleHideSubtotals} /> Subtotals
956
+ </label>
957
+ <label class="pvd-toggle">
958
+ <input type="checkbox" checked={!layout.hideGrandTotals} onchange={toggleHideGrandTotals} /> Grand totals
959
+ </label>
960
+ {:else}
961
+ <!-- The server model owns its grand-total row (a construction option);
962
+ the switch here is the Total column group, built without a request. -->
963
+ <label class="pvd-toggle">
964
+ <input type="checkbox" checked={!layout.hideGrandTotals} onchange={toggleHideGrandTotals} /> Row totals
965
+ </label>
966
+ {/if}
967
+ {#if deferred}
968
+ <div class="pvd-apply" role="group" aria-label="Apply layout">
969
+ <button type="button" class="pvd-btn pvd-btn-primary" disabled={!dirty} onclick={applyLayout}>Apply</button>
970
+ <button type="button" class="pvd-btn" disabled={!dirty} onclick={cancelLayout}>Cancel</button>
971
+ </div>
972
+ {/if}
973
+ {#if chartable && !server}
807
974
  <div class="pvd-viewswitch" role="group" aria-label="View">
808
975
  <button type="button" class="pvd-view-btn" class:is-active={view === 'table'} onclick={() => (view = 'table')}>{@render ic('table')} Table</button>
809
976
  <button type="button" class="pvd-view-btn" class:is-active={view === 'chart'} onclick={() => (view = 'chart')}>{@render ic('chart')} Chart</button>
810
977
  </div>
811
978
  {#if view === 'chart'}
812
979
  <label class="pvd-toggle">
813
- <select class="pvd-select" value={chartType} onchange={(e) => (chartType = e.currentTarget.value as ChartType)}>
814
- {#each CHART_TYPES as t (t.value)}<option value={t.value}>{t.label}</option>{/each}
980
+ <select class="pvd-select" aria-label="Chart type" value={chartType} onchange={(e) => (chartType = e.currentTarget.value as ChartType)}>
981
+ {#each CHART_GROUPS as g (g)}
982
+ <optgroup label={g}>
983
+ {#each CHART_TYPES.filter((t) => t.group === g) as t (t.value)}<option value={t.value}>{t.label}</option>{/each}
984
+ </optgroup>
985
+ {/each}
815
986
  </select>
816
987
  </label>
817
- {#if chartType !== 'pie'}
988
+ {#if STACKABLE.includes(chartType)}
818
989
  <label class="pvd-toggle">
819
990
  <input type="checkbox" checked={chartStacked} onchange={(e) => (chartStacked = e.currentTarget.checked)} /> Stacked
820
991
  </label>
821
992
  {/if}
993
+ {#if chartType === 'bar' || chartType === 'area'}
994
+ <label class="pvd-toggle">
995
+ <input type="checkbox" checked={chartStacked100} onchange={(e) => (chartStacked100 = e.currentTarget.checked)} /> 100%
996
+ </label>
997
+ {/if}
998
+ {#if chartType === 'bar'}
999
+ <label class="pvd-toggle">
1000
+ <input type="checkbox" checked={chartHorizontal} onchange={(e) => (chartHorizontal = e.currentTarget.checked)} /> Horizontal
1001
+ </label>
1002
+ {/if}
822
1003
  {/if}
823
1004
  {/if}
824
1005
  <div class="pvd-spacer"></div>
@@ -854,7 +1035,7 @@
854
1035
  {/if}
855
1036
  <div class="pvd-main">
856
1037
  {#if showPivotToggle}<div class="pvd-topbar">{@render pivotToggle()}</div>{/if}
857
- <div class="pvd-wells" class:two={!showFiltersWell}>{@render wellsBlock()}</div>
1038
+ <div class="pvd-wells" class:two={!filtersWell}>{@render wellsBlock()}</div>
858
1039
  {@render gridBlock()}
859
1040
  </div>
860
1041
  {/if}
@@ -1048,18 +1229,18 @@
1048
1229
 
1049
1230
  {#snippet wellsBlock()}
1050
1231
  <!-- Filters -->
1051
- {#if showFiltersWell}
1052
- <div class="pvd-well"
1232
+ {#if filtersWell}
1233
+ <div class="pvd-well" data-well="filters" role="group" aria-label="Filters"
1053
1234
  class:drag-over={dragOver === 'filters'}
1054
1235
  ondragover={(e) => onDragOver(e, 'filters')}
1055
1236
  ondragleave={onDragLeave}
1056
1237
  ondrop={(e) => onDrop(e, 'filters')}
1057
1238
  oncontextmenu={(e) => openCtx(e, wellMenu('filters'))}>
1058
1239
  <div class="pvd-well-head">{@render ic('filter')} Filters</div>
1059
- <div class="pvd-well-body">
1240
+ <div class="pvd-well-body" role="list">
1060
1241
  {#each layout.filters as f (f.field)}
1061
1242
  {@const fd = fieldsByName.get(f.field)}
1062
- <div class="pvd-chip" draggable="true" ondragstart={(e) => onDragStart(e, f.field, 'filters')} oncontextmenu={(e) => openCtx(e, chipMenu('filters', f.field))}>
1243
+ <div class="pvd-chip" role="listitem" draggable="true" ondragstart={(e) => onDragStart(e, f.field, 'filters')} oncontextmenu={(e) => openCtx(e, chipMenu('filters', f.field))}>
1063
1244
  <span class="pvd-chip-grip" aria-hidden="true">{@render ic('grip')}</span>
1064
1245
  <button type="button" class="pvd-chip-label" title="Choose which values pass" onclick={() => toggleFilterMenu(f.field)}>
1065
1246
  {fd?.label ?? f.field}{f.allowed ? `: ${f.allowed.length}` : ''} <span class="pvd-chip-caret">▾</span>
@@ -1096,17 +1277,17 @@
1096
1277
  {/if}
1097
1278
 
1098
1279
  <!-- Columns -->
1099
- <div class="pvd-well"
1280
+ <div class="pvd-well" data-well="cols" role="group" aria-label="Cols"
1100
1281
  class:drag-over={dragOver === 'cols'}
1101
1282
  ondragover={(e) => onDragOver(e, 'cols')}
1102
1283
  ondragleave={onDragLeave}
1103
1284
  ondrop={(e) => onDrop(e, 'cols')}
1104
1285
  oncontextmenu={(e) => openCtx(e, wellMenu('cols'))}>
1105
1286
  <div class="pvd-well-head">{@render ic('columns')} Columns</div>
1106
- <div class="pvd-well-body">
1287
+ <div class="pvd-well-body" role="list">
1107
1288
  {#each layout.cols as field (field)}
1108
1289
  {@const fd = fieldsByName.get(field)}
1109
- <div class="pvd-chip" draggable="true" ondragstart={(e) => onDragStart(e, field, 'cols')} oncontextmenu={(e) => openCtx(e, chipMenu('cols', field))}>
1290
+ <div class="pvd-chip" role="listitem" draggable="true" ondragstart={(e) => onDragStart(e, field, 'cols')} oncontextmenu={(e) => openCtx(e, chipMenu('cols', field))}>
1110
1291
  <span class="pvd-chip-grip" aria-hidden="true">{@render ic('grip')}</span>
1111
1292
  <span class="pvd-chip-label">{fd?.label ?? field}</span>
1112
1293
  <button type="button" class="pvd-chip-x" onclick={() => removeFromWell(field, 'cols')} aria-label="Remove">×</button>
@@ -1117,17 +1298,17 @@
1117
1298
  </div>
1118
1299
 
1119
1300
  <!-- Rows -->
1120
- <div class="pvd-well"
1301
+ <div class="pvd-well" data-well="rows" role="group" aria-label="Rows"
1121
1302
  class:drag-over={dragOver === 'rows'}
1122
1303
  ondragover={(e) => onDragOver(e, 'rows')}
1123
1304
  ondragleave={onDragLeave}
1124
1305
  ondrop={(e) => onDrop(e, 'rows')}
1125
1306
  oncontextmenu={(e) => openCtx(e, wellMenu('rows'))}>
1126
1307
  <div class="pvd-well-head">{@render ic('rows')} Rows</div>
1127
- <div class="pvd-well-body">
1308
+ <div class="pvd-well-body" role="list">
1128
1309
  {#each layout.rows as field (field)}
1129
1310
  {@const fd = fieldsByName.get(field)}
1130
- <div class="pvd-chip" draggable="true" ondragstart={(e) => onDragStart(e, field, 'rows')} oncontextmenu={(e) => openCtx(e, chipMenu('rows', field))}>
1311
+ <div class="pvd-chip" role="listitem" draggable="true" ondragstart={(e) => onDragStart(e, field, 'rows')} oncontextmenu={(e) => openCtx(e, chipMenu('rows', field))}>
1131
1312
  <span class="pvd-chip-grip" aria-hidden="true">{@render ic('grip')}</span>
1132
1313
  <span class="pvd-chip-label">{fd?.label ?? field}</span>
1133
1314
  <button type="button" class="pvd-chip-x" onclick={() => removeFromWell(field, 'rows')} aria-label="Remove">×</button>
@@ -1138,17 +1319,17 @@
1138
1319
  </div>
1139
1320
 
1140
1321
  <!-- Values -->
1141
- <div class="pvd-well"
1322
+ <div class="pvd-well" data-well="values" role="group" aria-label="Values"
1142
1323
  class:drag-over={dragOver === 'values'}
1143
1324
  ondragover={(e) => onDragOver(e, 'values')}
1144
1325
  ondragleave={onDragLeave}
1145
1326
  ondrop={(e) => onDrop(e, 'values')}
1146
1327
  oncontextmenu={(e) => openCtx(e, wellMenu('values'))}>
1147
1328
  <div class="pvd-well-head">{@render ic('sigma')} Values</div>
1148
- <div class="pvd-well-body">
1329
+ <div class="pvd-well-body" role="list">
1149
1330
  {#each layout.values as v, vi (v.field + '|' + v.agg + '|' + vi)}
1150
1331
  {@const fd = fieldsByName.get(v.field)}
1151
- <div class="pvd-chip pvd-chip-value" draggable="true" ondragstart={(e) => onDragStart(e, v.field, 'values', vi)} oncontextmenu={(e) => openCtx(e, chipMenu('values', v.field, vi))}>
1332
+ <div class="pvd-chip pvd-chip-value" role="listitem" draggable="true" ondragstart={(e) => onDragStart(e, v.field, 'values', vi)} oncontextmenu={(e) => openCtx(e, chipMenu('values', v.field, vi))}>
1152
1333
  <span class="pvd-chip-grip" aria-hidden="true">{@render ic('grip')}</span>
1153
1334
  <button type="button" class="pvd-chip-label" onclick={() => toggleAggMenu(vi)}>
1154
1335
  <span class="pvd-chip-agg">{AGG_LABEL[v.agg]}</span>
@@ -1181,7 +1362,7 @@
1181
1362
  {#snippet columnsPanel()}
1182
1363
  {#if showPivotToggle}{@render pivotToggle()}{/if}
1183
1364
  {#if showFieldList}<div class="pvd-panel-rail">{@render railBlock()}</div>{/if}
1184
- <div class="pvd-wells pvd-wells--vertical" class:two={!showFiltersWell}>{@render wellsBlock()}</div>
1365
+ <div class="pvd-wells pvd-wells--vertical" class:two={!filtersWell}>{@render wellsBlock()}</div>
1185
1366
  {/snippet}
1186
1367
 
1187
1368
  <!-- The Filters tab body: AG-style set filters. Each active column filter is a
@@ -1247,8 +1428,25 @@
1247
1428
 
1248
1429
  {#snippet gridBlock()}
1249
1430
  {#if embedGrid}
1250
- <div class="pvd-grid" style={`height:${typeof gridHeight === 'number' ? gridHeight + 'px' : gridHeight}`} oncontextmenu={(e) => openCtx(e, gridMenu())}>
1251
- {#if showPivotToggle && !pivotMode}
1431
+ <div class="pvd-grid" role="region" aria-label="Pivot" style={`height:${typeof gridHeight === 'number' ? gridHeight + 'px' : gridHeight}`} oncontextmenu={(e) => openCtx(e, gridMenu())}>
1432
+ {#if server}
1433
+ <SvGrid
1434
+ rowModel={server}
1435
+ columns={serverColumns}
1436
+ pivotResultColumns={pivotMode ? serverPivotColumns : undefined}
1437
+ features={features}
1438
+ sortable
1439
+ selectionMode="none"
1440
+ rowHeight={32}
1441
+ containerHeight="100%"
1442
+ fitColumns={gridFitColumns}
1443
+ columnVirtualization={columnVirtualization}
1444
+ enableRowSummaries={false}
1445
+ onCellClick={onCellClick
1446
+ ? (e) => onCellClick({ columnId: e.columnId, row: e.row as unknown as PivotRow, value: e.value })
1447
+ : undefined}
1448
+ />
1449
+ {:else if showPivotToggle && !pivotMode}
1252
1450
  <SvGrid
1253
1451
  data={filteredData}
1254
1452
  columns={visibleFlatColumns!}
@@ -1264,7 +1462,9 @@
1264
1462
  />
1265
1463
  {:else if pivot && chartable && view === 'chart'}
1266
1464
  {#if chartSpec && chartSpec.series.length}
1267
- <div class="pvd-chart"><SvGridChart spec={chartSpec} interactive legend /></div>
1465
+ <!-- The chart's own toolbar (PNG / SVG / PDF / print / copy) and the
1466
+ spoken summary, at the pane's size. -->
1467
+ <div class="pvd-chart"><SvGridChart spec={chartSpec} interactive legend="bottom" toolbar describe autosize /></div>
1268
1468
  {:else}
1269
1469
  <div class="pvd-empty pvd-grid-empty">Add a measure and a row / column field to chart the pivot.</div>
1270
1470
  {/if}
@@ -1375,6 +1575,15 @@
1375
1575
  border-color: var(--sg-accent, #2563eb);
1376
1576
  }
1377
1577
  .pvd-btn-primary:hover { opacity: 0.9; }
1578
+ .pvd-btn:disabled { opacity: 0.5; cursor: default; }
1579
+ /* Apply with nothing to apply reads as off, not as a paler Apply. */
1580
+ .pvd-btn-primary:disabled {
1581
+ opacity: 1;
1582
+ background: var(--sg-header-bg, #f1f5f9);
1583
+ border-color: var(--sg-border, #e2e8f0);
1584
+ color: var(--sg-muted, #64748b);
1585
+ }
1586
+ .pvd-apply { display: inline-flex; gap: 6px; }
1378
1587
  .pvd-toggle {
1379
1588
  display: inline-flex;
1380
1589
  align-items: center;
@@ -1,28 +1,12 @@
1
1
  type PivotInputRow = Record<string, unknown>;
2
- /**
3
- * SvPivotDesigner - Excel-style pivot table designer.
4
- *
5
- * Self-contained, controlled component. The consumer holds the data
6
- * + the field list + the layout state; everything else (drag-and-drop,
7
- * chip menus, search, presets, the inline pivot grid) is built in.
8
- *
9
- * Minimal wire-up (in a .svelte file):
10
- * const fields = [
11
- * { field: 'region', label: 'Region', kind: 'dimension' },
12
- * { field: 'quarter', label: 'Quarter', kind: 'dimension' },
13
- * { field: 'amount', label: 'Revenue', kind: 'measure', defaultAgg: 'sum' },
14
- * ]
15
- * let layout = $state(defaultLayoutFor(fields))
16
- *
17
- * SvPivotDesigner {data} {fields} bind:layout
18
- */
19
2
  import { type ColumnDef } from '@svgrid/grid';
3
+ import { type ServerRowModel } from './server/server-row-model.js';
20
4
  import { type PivotRow, type PivotAggregatorId } from './pivot.js';
21
5
  import { type PivotField, type PivotLayout, type PivotPreset } from './pivot-designer.js';
22
6
  declare function $$render<T extends PivotInputRow>(): {
23
7
  props: {
24
- /** Flat input rows. */
25
- data: T[];
8
+ /** Flat input rows. Not read in server mode. */
9
+ data?: T[];
26
10
  /** All fields the user can pick from the rail. */
27
11
  fields: PivotField<T>[];
28
12
  /** The current pivot layout. Bindable so the consumer can persist it. */
@@ -80,7 +64,8 @@ declare function $$render<T extends PivotInputRow>(): {
80
64
  };
81
65
  }, PivotRow>[];
82
66
  /** Click handler forwarded to the embedded SvGrid - typically used
83
- * to drive a drill-through side panel. */
67
+ * to drive a drill-through side panel. In server mode `row` is the
68
+ * model's grid row (its `__group` says which group or leaf it is). */
84
69
  onCellClick?: (ctx: {
85
70
  columnId: string;
86
71
  row: PivotRow;
@@ -151,6 +136,28 @@ declare function $$render<T extends PivotInputRow>(): {
151
136
  * narrow the source rows (they drive `layout.filters`). Default false.
152
137
  */
153
138
  toolTabs?: boolean;
139
+ /**
140
+ * A `createServerRowModel` controller. The designer then drives it
141
+ * instead of pivoting in the browser - Rows become `groupBy`, Columns
142
+ * `pivotBy`, Values `aggregations` - and the embedded grid mounts it
143
+ * through `rowModel`, showing the columns the backend's
144
+ * `pivotResultFields` describe. `data` is not read. The Filters well,
145
+ * the subtotal switches and the chart view are off: filters belong to
146
+ * the grid's own filter UI, footers and totals to the model's options.
147
+ */
148
+ server?: ServerRowModel<T>;
149
+ /** The group column the designer adds in server mode. */
150
+ groupColumn?: {
151
+ header?: string;
152
+ width?: number;
153
+ leafField?: string;
154
+ };
155
+ /**
156
+ * `'immediate'` (default) sends every drag to `onLayoutChange` and the
157
+ * server. `'deferred'` collects edits and shows Apply / Cancel, so one
158
+ * slice-and-dice session is one request.
159
+ */
160
+ applyMode?: "immediate" | "deferred";
154
161
  };
155
162
  exports: {};
156
163
  bindings: "pivotMode" | "layout" | "hiddenFields";
@@ -0,0 +1,46 @@
1
+ <script lang="ts">
2
+ /**
3
+ * One ribbon icon, by name, at any size.
4
+ *
5
+ * The paths live in `sheet/ribbon-icons.ts` on a 16-unit grid; the SVG
6
+ * scales them, so a large button gets the same drawing at 32px without a
7
+ * second set. Everything is drawn in `currentColor`: the icon is the
8
+ * colour of the text around it, black on a light ribbon and white on a
9
+ * dark one, and nothing in the set carries a colour of its own.
10
+ */
11
+ import { RIBBON_ICONS, type RibbonIconName } from './sheet/ribbon-icons'
12
+
13
+ let { name, size = 16 }: { name: RibbonIconName; size?: number } = $props()
14
+
15
+ const paths = $derived(RIBBON_ICONS[name] ?? [])
16
+ </script>
17
+
18
+ <svg
19
+ class="sv-ribbon-icon"
20
+ width={size}
21
+ height={size}
22
+ viewBox="0 0 16 16"
23
+ fill="none"
24
+ stroke="currentColor"
25
+ stroke-width="1.4"
26
+ stroke-linecap="round"
27
+ stroke-linejoin="round"
28
+ aria-hidden="true"
29
+ focusable="false"
30
+ >
31
+ {#each paths as path, i (i)}
32
+ <path
33
+ d={path.d}
34
+ fill={path.fill ? 'currentColor' : 'none'}
35
+ stroke-width={path.width}
36
+ stroke-dasharray={path.dash}
37
+ />
38
+ {/each}
39
+ </svg>
40
+
41
+ <style>
42
+ .sv-ribbon-icon {
43
+ display: block;
44
+ flex: 0 0 auto;
45
+ }
46
+ </style>