@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
@@ -0,0 +1,160 @@
1
+ /**
2
+ * A PivotTable over a range of cells: Excel's Insert > PivotTable, on the
3
+ * pivot engine the grid already has (`pivot.ts`).
4
+ *
5
+ * The definition is what the sheet keeps: the source range (its first row
6
+ * is the field names), where the result is written, and the row fields,
7
+ * column fields and measures. The RESULT is plain cells, written into the
8
+ * sheet like any other block, so every other part of the shell works on it
9
+ * without knowing it came from a pivot: it can be formatted, filtered,
10
+ * charted, printed and saved to an .xlsx. Refresh rebuilds the block from
11
+ * the source, which is what a pivot over live cells owes the user.
12
+ *
13
+ * Everything here is pure: it reads cells through the callbacks it is
14
+ * given, and returns the block of text to write.
15
+ */
16
+ import type { Rect } from './format-store.js';
17
+ import type { StructuralEdit } from './refs.js';
18
+ import type { CellValue } from './ast.js';
19
+ /** The aggregations Excel's Summarize Values By offers, as this sheet has them. */
20
+ export declare const SHEET_PIVOT_AGGS: readonly ["sum", "avg", "count", "countDistinct", "min", "max"];
21
+ export type SheetPivotAgg = (typeof SHEET_PIVOT_AGGS)[number];
22
+ export type SheetPivotValue = {
23
+ /** A field name: one of the source's header cells. */
24
+ field: string;
25
+ agg: SheetPivotAgg;
26
+ label?: string;
27
+ };
28
+ export type SheetPivot = {
29
+ id: string;
30
+ /** The source block, its first row the field names. */
31
+ source: Rect;
32
+ /** The top-left cell of the written block, on the same sheet. */
33
+ target: {
34
+ row: number;
35
+ col: number;
36
+ };
37
+ /** Row fields, outermost first. */
38
+ rows: string[];
39
+ /** Column fields, outermost first. */
40
+ cols: string[];
41
+ values: SheetPivotValue[];
42
+ /**
43
+ * Excel's Filters area: a field, and the one value the whole pivot is
44
+ * narrowed to. An empty value is "(All)", which narrows nothing.
45
+ *
46
+ * It is written above the block, a line per filter, so the reader can
47
+ * see what the numbers are of; typing another value there and refreshing
48
+ * is the fast way to change it.
49
+ */
50
+ filters?: SheetPivotFilter[];
51
+ grandTotalRow?: boolean;
52
+ grandTotalCol?: boolean;
53
+ rowSubtotals?: boolean;
54
+ /** The block the last refresh wrote, so the next one can clear it. */
55
+ written?: Rect;
56
+ };
57
+ export type SheetPivotFilter = {
58
+ field: string;
59
+ /** The value to keep, as text. Empty means every value. */
60
+ value: string;
61
+ };
62
+ /** An id no other pivot of this session carries. */
63
+ export declare const pivotId: () => string;
64
+ /** A copy safe to hand out or save. */
65
+ export declare function copyPivot(pivot: SheetPivot): SheetPivot;
66
+ /**
67
+ * The pivot after an insert or delete: the source moves with its cells and
68
+ * the target with its own. Null when the source is gone, or the cell the
69
+ * result is written at is.
70
+ */
71
+ export declare function shiftPivot(pivot: SheetPivot, edit: StructuralEdit): SheetPivot | null;
72
+ /** The pivots of a sheet after an insert or delete, the gone ones dropped. */
73
+ export declare function shiftPivots(pivots: ReadonlyArray<SheetPivot>, edit: StructuralEdit): SheetPivot[];
74
+ /**
75
+ * The field names of a source range: its first row, with a blank header
76
+ * named after its column the way Excel names an unnamed one.
77
+ */
78
+ export declare function pivotFields(source: Rect, textAt: (row: number, col: number) => string): string[];
79
+ /** The source's body as records keyed by field name, ready for the engine. */
80
+ export declare function pivotRecords(source: Rect, valueAt: (row: number, col: number) => CellValue, textAt: (row: number, col: number) => string): Array<Record<string, unknown>>;
81
+ /**
82
+ * The column tree flattened for a sheet: one header row per level of the
83
+ * tree, and the leaf ids in the order they are written. A header sits over
84
+ * the leaves it covers, and its own cell is the leftmost of them, the way
85
+ * Excel writes a merged group header without the merge.
86
+ */
87
+ export declare function flattenPivotColumns(columns: ReadonlyArray<unknown>): {
88
+ headerRows: string[][];
89
+ leaves: Array<{
90
+ id: string;
91
+ header: string;
92
+ }>;
93
+ };
94
+ /**
95
+ * The records a pivot's filters leave.
96
+ *
97
+ * Excel's report filter narrows the whole pivot, not one part of it, so it
98
+ * applies before anything is grouped: the totals, the subtotals and the
99
+ * drill-down all see the same rows, which is the only way the numbers on
100
+ * the page add up.
101
+ */
102
+ export declare function filteredRecords(pivot: SheetPivot, records: ReadonlyArray<Record<string, unknown>>): Array<Record<string, unknown>>;
103
+ /** The values a field carries, each once, in the order they appear. */
104
+ export declare function pivotFieldValues(field: string, source: Rect, valueAt: (row: number, col: number) => CellValue, textAt: (row: number, col: number) => string): string[];
105
+ /**
106
+ * The block of text a pivot writes: the column headers, then one line per
107
+ * pivot row, the row label indented by its depth the way Excel indents a
108
+ * group under its parent.
109
+ */
110
+ export declare function pivotBlock(pivot: SheetPivot, valueAt: (row: number, col: number) => CellValue, textAt: (row: number, col: number) => string): string[][];
111
+ /**
112
+ * The block, and what each of its lines and columns stands for.
113
+ *
114
+ * `pivotBlock` writes the cells; drilling into one needs to know which
115
+ * field values pin it, which is the same walk. Both come from here so they
116
+ * cannot drift: a cell drawn from one layout and read from another would
117
+ * open the wrong rows.
118
+ */
119
+ export type PivotLayout = {
120
+ cells: string[][];
121
+ /** How many lines of `cells` are column headers. */
122
+ headerCount: number;
123
+ /**
124
+ * The row field values that pin each line, outermost first, aligned to
125
+ * `cells`. Null for a header line; shorter than the pivot's row fields
126
+ * for a group, a subtotal or the grand total, which pin fewer of them.
127
+ */
128
+ rowPaths: Array<string[] | null>;
129
+ /** The same for each column of `cells`. Null for the label column. */
130
+ colPaths: Array<string[] | null>;
131
+ };
132
+ export declare function pivotLayout(pivot: SheetPivot, valueAt: (row: number, col: number) => CellValue, textAt: (row: number, col: number) => string): PivotLayout;
133
+ /** What a filter with no value chosen shows, and what clears one. */
134
+ export declare const ALL_VALUES = "(All)";
135
+ /** The source rows behind one cell of a written pivot. */
136
+ export type PivotDrill = {
137
+ /** The row and column field values that pin the cell, outermost first. */
138
+ rowPath: string[];
139
+ colPath: string[];
140
+ /** The records behind it, in the source's own order. */
141
+ records: Array<Record<string, unknown>>;
142
+ /** The source's fields, in its own order. */
143
+ fields: string[];
144
+ };
145
+ /**
146
+ * Excel's "show details": the rows behind the number in a pivot cell.
147
+ *
148
+ * `row` and `col` are a cell on the sheet, not a place in the block. Null
149
+ * when the cell is outside the pivot, or is a header, or is the row label
150
+ * column, none of which stand for a number.
151
+ */
152
+ export declare function pivotDrill(pivot: SheetPivot, row: number, col: number, valueAt: (row: number, col: number) => CellValue, textAt: (row: number, col: number) => string): PivotDrill | null;
153
+ /** The rectangle a block written at the target covers. */
154
+ export declare function pivotWrittenRect(pivot: SheetPivot, block: ReadonlyArray<ReadonlyArray<string>>): Rect;
155
+ /**
156
+ * Where Excel's Create PivotTable dialog opens: the source is the selected
157
+ * block, and the result lands two columns past it, which keeps it clear of
158
+ * the data it reads.
159
+ */
160
+ export declare function pivotFromRange(source: Rect, fields: ReadonlyArray<string>): SheetPivot;
@@ -0,0 +1,333 @@
1
+ import { shiftRect, lineShift } from './rects.js';
2
+ import { colToLetters } from './address.js';
3
+ import { createPivotModel } from '../pivot.js';
4
+ /** The aggregations Excel's Summarize Values By offers, as this sheet has them. */
5
+ export const SHEET_PIVOT_AGGS = ['sum', 'avg', 'count', 'countDistinct', 'min', 'max'];
6
+ let nextPivotId = 1;
7
+ /** An id no other pivot of this session carries. */
8
+ export const pivotId = () => `pivot-${Date.now().toString(36)}-${(nextPivotId += 1).toString(36)}`;
9
+ /** A copy safe to hand out or save. */
10
+ export function copyPivot(pivot) {
11
+ return {
12
+ ...pivot,
13
+ source: [...pivot.source],
14
+ target: { ...pivot.target },
15
+ rows: [...pivot.rows],
16
+ cols: [...pivot.cols],
17
+ values: pivot.values.map((v) => ({ ...v })),
18
+ ...(pivot.filters?.length ? { filters: pivot.filters.map((f) => ({ ...f })) } : {}),
19
+ ...(pivot.written ? { written: [...pivot.written] } : {}),
20
+ };
21
+ }
22
+ /**
23
+ * The pivot after an insert or delete: the source moves with its cells and
24
+ * the target with its own. Null when the source is gone, or the cell the
25
+ * result is written at is.
26
+ */
27
+ export function shiftPivot(pivot, edit) {
28
+ const source = shiftRect(pivot.source, edit);
29
+ if (!source)
30
+ return null;
31
+ const shift = lineShift(edit);
32
+ const rows = edit.kind === 'insertRows' || edit.kind === 'deleteRows';
33
+ const at = rows ? shift(pivot.target.row) : shift(pivot.target.col);
34
+ if (at === null)
35
+ return null;
36
+ const out = copyPivot(pivot);
37
+ out.source = source;
38
+ out.target = rows ? { ...out.target, row: at } : { ...out.target, col: at };
39
+ if (out.written) {
40
+ const written = shiftRect(out.written, edit);
41
+ if (written)
42
+ out.written = written;
43
+ else
44
+ delete out.written;
45
+ }
46
+ return out;
47
+ }
48
+ /** The pivots of a sheet after an insert or delete, the gone ones dropped. */
49
+ export function shiftPivots(pivots, edit) {
50
+ return pivots.map((p) => shiftPivot(p, edit)).filter((p) => p !== null);
51
+ }
52
+ /**
53
+ * The field names of a source range: its first row, with a blank header
54
+ * named after its column the way Excel names an unnamed one.
55
+ */
56
+ export function pivotFields(source, textAt) {
57
+ const [r1, c1, , c2] = source;
58
+ const out = [];
59
+ const seen = new Set();
60
+ for (let c = c1; c <= c2; c += 1) {
61
+ let name = textAt(r1, c).trim() || `Column ${colToLetters(c)}`;
62
+ // Two columns with one name would collapse into one field.
63
+ while (seen.has(name))
64
+ name = `${name} (${colToLetters(c)})`;
65
+ seen.add(name);
66
+ out.push(name);
67
+ }
68
+ return out;
69
+ }
70
+ /** The source's body as records keyed by field name, ready for the engine. */
71
+ export function pivotRecords(source, valueAt, textAt) {
72
+ const [r1, c1, r2, c2] = source;
73
+ const fields = pivotFields(source, textAt);
74
+ const out = [];
75
+ for (let r = r1 + 1; r <= r2; r += 1) {
76
+ const record = {};
77
+ let any = false;
78
+ for (let c = c1; c <= c2; c += 1) {
79
+ const value = valueAt(r, c);
80
+ record[fields[c - c1]] = value === '' ? null : value;
81
+ if (value !== '')
82
+ any = true;
83
+ }
84
+ // A wholly empty row is a gap in the block, not a record.
85
+ if (any)
86
+ out.push(record);
87
+ }
88
+ return out;
89
+ }
90
+ /**
91
+ * The column tree flattened for a sheet: one header row per level of the
92
+ * tree, and the leaf ids in the order they are written. A header sits over
93
+ * the leaves it covers, and its own cell is the leftmost of them, the way
94
+ * Excel writes a merged group header without the merge.
95
+ */
96
+ export function flattenPivotColumns(columns) {
97
+ const nodes = columns;
98
+ const depthOf = (list) => list.reduce((deep, node) => Math.max(deep, node.columns?.length ? 1 + depthOf(node.columns) : 1), 0);
99
+ const depth = depthOf(nodes);
100
+ const headerRows = Array.from({ length: depth }, () => []);
101
+ const leaves = [];
102
+ const walk = (list, level) => {
103
+ for (const node of list) {
104
+ const label = node.header === undefined || node.header === null ? '' : String(node.header);
105
+ if (node.columns?.length) {
106
+ const start = leaves.length;
107
+ walk(node.columns, level + 1);
108
+ for (let i = start; i < leaves.length; i += 1)
109
+ headerRows[level][i] = i === start ? label : '';
110
+ }
111
+ else {
112
+ leaves.push({ id: String(node.id ?? ''), header: label });
113
+ const at = leaves.length - 1;
114
+ for (let l = level; l < depth - 1; l += 1)
115
+ headerRows[l][at] = '';
116
+ headerRows[depth - 1][at] = label;
117
+ }
118
+ }
119
+ };
120
+ walk(nodes, 0);
121
+ for (const row of headerRows) {
122
+ for (let i = 0; i < leaves.length; i += 1)
123
+ row[i] = row[i] ?? '';
124
+ }
125
+ return { headerRows, leaves };
126
+ }
127
+ /**
128
+ * The records a pivot's filters leave.
129
+ *
130
+ * Excel's report filter narrows the whole pivot, not one part of it, so it
131
+ * applies before anything is grouped: the totals, the subtotals and the
132
+ * drill-down all see the same rows, which is the only way the numbers on
133
+ * the page add up.
134
+ */
135
+ export function filteredRecords(pivot, records) {
136
+ const active = (pivot.filters ?? []).filter((f) => f.field && f.value !== '');
137
+ if (!active.length)
138
+ return [...records];
139
+ return records.filter((record) => active.every((f) => String(record[f.field] ?? '') === f.value));
140
+ }
141
+ /** The values a field carries, each once, in the order they appear. */
142
+ export function pivotFieldValues(field, source, valueAt, textAt) {
143
+ const seen = [];
144
+ for (const record of pivotRecords(source, valueAt, textAt)) {
145
+ const value = String(record[field] ?? '');
146
+ if (value !== '' && !seen.includes(value))
147
+ seen.push(value);
148
+ }
149
+ return seen;
150
+ }
151
+ /** A number without the float noise a sum of decimals leaves behind. */
152
+ function cellText(value) {
153
+ if (value === null || value === undefined || value === '')
154
+ return '';
155
+ if (typeof value === 'number') {
156
+ if (!Number.isFinite(value))
157
+ return '';
158
+ return String(Number(value.toPrecision(12)));
159
+ }
160
+ if (typeof value === 'boolean')
161
+ return value ? 'TRUE' : 'FALSE';
162
+ return String(value);
163
+ }
164
+ /**
165
+ * The block of text a pivot writes: the column headers, then one line per
166
+ * pivot row, the row label indented by its depth the way Excel indents a
167
+ * group under its parent.
168
+ */
169
+ export function pivotBlock(pivot, valueAt, textAt) {
170
+ return pivotLayout(pivot, valueAt, textAt).cells;
171
+ }
172
+ export function pivotLayout(pivot, valueAt, textAt) {
173
+ const empty = { cells: [], headerCount: 0, rowPaths: [], colPaths: [] };
174
+ if (!pivot.values.length)
175
+ return empty;
176
+ const records = filteredRecords(pivot, pivotRecords(pivot.source, valueAt, textAt));
177
+ const result = createPivotModel(records, {
178
+ rows: pivot.rows,
179
+ cols: pivot.cols,
180
+ values: pivot.values.map((v) => ({
181
+ field: v.field,
182
+ agg: v.agg,
183
+ ...(v.label ? { label: v.label } : {}),
184
+ })),
185
+ grandTotalRow: pivot.grandTotalRow !== false,
186
+ // With no column field the grand total column would repeat the only
187
+ // measure column, which is not what Excel shows.
188
+ grandTotalCol: pivot.cols.length ? pivot.grandTotalCol !== false : false,
189
+ rowSubtotals: pivot.rowSubtotals !== false,
190
+ });
191
+ const { headerRows, leaves } = flattenPivotColumns(result.columns);
192
+ // The engine's first column is the row-axis label; it is the block's own
193
+ // first column here rather than one of the leaves.
194
+ const label = leaves[0]?.id === '__pivotRowHeader' ? leaves.shift() : undefined;
195
+ const headerLabel = label?.header ?? '';
196
+ const dropped = label ? 1 : 0;
197
+ const out = headerRows.map((row, i) => [
198
+ i === headerRows.length - 1 ? headerLabel : '',
199
+ ...row.slice(dropped),
200
+ ]);
201
+ // With one measure, the bottom header row is that measure's name under
202
+ // every column, which says nothing the dialog has not. Drop it and let
203
+ // the column values carry the corner label, as Excel's compact form does.
204
+ if (pivot.values.length === 1 && out.length > 1) {
205
+ const measures = out.pop();
206
+ out[out.length - 1][0] = measures[0] ?? '';
207
+ }
208
+ // Excel writes the Filters area above the block, one line per filter and
209
+ // a blank line under them, so the reader sees what the numbers are of
210
+ // before reading a number.
211
+ const filters = (pivot.filters ?? []).filter((f) => f.field);
212
+ if (filters.length) {
213
+ const width = out[0]?.length ?? 2;
214
+ const pad = (line) => {
215
+ while (line.length < Math.max(width, 2))
216
+ line.push('');
217
+ return line;
218
+ };
219
+ out.unshift(...filters.map((f) => pad([f.field, f.value === '' ? ALL_VALUES : f.value])), pad([]));
220
+ }
221
+ const headerCount = out.length;
222
+ const rowPaths = Array.from({ length: headerCount }, () => null);
223
+ // The row axis is a walk down a tree, and the model hands its rows out in
224
+ // that order: a group before what is under it. Keeping the labels seen at
225
+ // each depth is enough to know the path of the line being written, and
226
+ // the label IS the value as the model grouped it, since it groups on the
227
+ // text too.
228
+ const stack = [];
229
+ for (const row of result.rows) {
230
+ const indent = ' '.repeat(Math.max(0, row.__pivotDepth - 1));
231
+ out.push([`${indent}${row.__pivotLabel}`, ...leaves.map((leaf) => cellText(row[leaf.id]))]);
232
+ const depth = Math.max(0, row.__pivotDepth);
233
+ if (row.__pivotKind === 'grandTotal') {
234
+ rowPaths.push([]);
235
+ continue;
236
+ }
237
+ stack.length = depth;
238
+ if (depth > 0)
239
+ stack[depth - 1] = row.__pivotLabel;
240
+ rowPaths.push([...stack]);
241
+ }
242
+ // A column's path is the headers above it, with a group's label repeated
243
+ // under it: `flattenPivotColumns` writes a group once, over its leftmost
244
+ // leaf, the way Excel writes one.
245
+ const levels = Math.min(pivot.cols.length, headerRows.length);
246
+ const colPaths = [null];
247
+ leaves.forEach((leaf, i) => {
248
+ // The grand total column reads every record, and a sheet with no column
249
+ // field has one column per measure, which is the same.
250
+ if (leaf.id.includes('__total__m') || leaf.id.startsWith('pv__all__m')) {
251
+ colPaths.push([]);
252
+ return;
253
+ }
254
+ const path = [];
255
+ for (let level = 0; level < levels; level += 1) {
256
+ let value = '';
257
+ for (let j = 0; j <= i + dropped; j += 1) {
258
+ const cell = headerRows[level]?.[j];
259
+ if (cell)
260
+ value = cell;
261
+ }
262
+ path.push(value);
263
+ }
264
+ colPaths.push(path);
265
+ });
266
+ return { cells: out, headerCount, rowPaths, colPaths };
267
+ }
268
+ /** What a filter with no value chosen shows, and what clears one. */
269
+ export const ALL_VALUES = '(All)';
270
+ /**
271
+ * Excel's "show details": the rows behind the number in a pivot cell.
272
+ *
273
+ * `row` and `col` are a cell on the sheet, not a place in the block. Null
274
+ * when the cell is outside the pivot, or is a header, or is the row label
275
+ * column, none of which stand for a number.
276
+ */
277
+ export function pivotDrill(pivot, row, col, valueAt, textAt) {
278
+ const layout = pivotLayout(pivot, valueAt, textAt);
279
+ if (!layout.cells.length)
280
+ return null;
281
+ const line = row - pivot.target.row;
282
+ const column = col - pivot.target.col;
283
+ if (line < 0 || line >= layout.cells.length)
284
+ return null;
285
+ if (column < 0 || column >= (layout.cells[line]?.length ?? 0))
286
+ return null;
287
+ const rowPath = layout.rowPaths[line];
288
+ const colPath = layout.colPaths[column];
289
+ if (!rowPath || !colPath)
290
+ return null;
291
+ const records = filteredRecords(pivot, pivotRecords(pivot.source, valueAt, textAt));
292
+ const matches = records.filter((record) => {
293
+ for (let i = 0; i < rowPath.length; i += 1) {
294
+ const field = pivot.rows[i];
295
+ if (field === undefined)
296
+ return false;
297
+ if (String(record[field] ?? '') !== rowPath[i])
298
+ return false;
299
+ }
300
+ for (let i = 0; i < colPath.length; i += 1) {
301
+ const field = pivot.cols[i];
302
+ if (field === undefined)
303
+ return false;
304
+ if (String(record[field] ?? '') !== colPath[i])
305
+ return false;
306
+ }
307
+ return true;
308
+ });
309
+ return { rowPath: [...rowPath], colPath: [...colPath], records: matches, fields: pivotFields(pivot.source, textAt) };
310
+ }
311
+ /** The rectangle a block written at the target covers. */
312
+ export function pivotWrittenRect(pivot, block) {
313
+ const height = Math.max(1, block.length);
314
+ const width = Math.max(1, block.reduce((w, row) => Math.max(w, row.length), 0));
315
+ const { row, col } = pivot.target;
316
+ return [row, col, row + height - 1, col + width - 1];
317
+ }
318
+ /**
319
+ * Where Excel's Create PivotTable dialog opens: the source is the selected
320
+ * block, and the result lands two columns past it, which keeps it clear of
321
+ * the data it reads.
322
+ */
323
+ export function pivotFromRange(source, fields) {
324
+ const [r1, , , c2] = source;
325
+ return {
326
+ id: pivotId(),
327
+ source: [...source],
328
+ target: { row: r1, col: c2 + 2 },
329
+ rows: fields.length ? [fields[0]] : [],
330
+ cols: [],
331
+ values: fields.length > 1 ? [{ field: fields[fields.length - 1], agg: 'sum' }] : [],
332
+ };
333
+ }
@@ -0,0 +1,73 @@
1
+ /**
2
+ * Presence: where the other people are.
3
+ *
4
+ * The delta stream carries what everyone TYPES; this carries where everyone
5
+ * IS, which is the other half of two people on one sheet. Seeing a
6
+ * colleague's box move is what stops two people typing into the same cell,
7
+ * and it is what makes a shared sheet feel shared rather than merely
8
+ * synchronised.
9
+ *
10
+ * Presence is not part of the document. It is never saved, never in
11
+ * `getState()` and never in the .xlsx: a cursor belongs to a session, and a
12
+ * file that remembered where someone's cursor was a week ago would be
13
+ * remembering nothing worth keeping. It is passed to the shell as a prop and
14
+ * drawn over the cells.
15
+ */
16
+ import type { Rect } from './rects.js';
17
+ export type SheetPresence = {
18
+ /** Whoever this is, stable for as long as they are here. */
19
+ id: string;
20
+ /** What to put on the tag. */
21
+ name: string;
22
+ /** Their colour, which the box and the tag are drawn in. Left out means
23
+ * one picked from the id, so a set of peers is never all one colour. */
24
+ colour?: string;
25
+ /** The sheet they are looking at. */
26
+ sheet: string;
27
+ /** Their selection, `[minRow, minCol, maxRow, maxCol]`. */
28
+ rect: Rect;
29
+ /** The cell the cursor is in, which is where the tag goes. Defaults to
30
+ * the top-left of the selection. */
31
+ active?: {
32
+ row: number;
33
+ col: number;
34
+ };
35
+ /** When they were last heard from, in ms. Absent counts as now. */
36
+ at?: number;
37
+ };
38
+ /**
39
+ * Eight colours that read as different people rather than as a heat map,
40
+ * stay legible as a thin box over a white sheet and over a dark one, and
41
+ * each carry a white name at 11px at 4.5:1 or better, so every tag wears
42
+ * the same white ink. The first set had five a shade too light for that.
43
+ */
44
+ export declare const PRESENCE_COLOURS: ReadonlyArray<string>;
45
+ /** A colour for an id: the same person gets the same one every session. */
46
+ export declare function presenceColour(id: string): string;
47
+ /**
48
+ * The ink for a name tag on a person's colour: black or white, whichever
49
+ * contrasts more. White on every colour was the first version, and white
50
+ * on the first set's green, orange or yellow was a little over 3:1, under
51
+ * the 4.5:1 an 11px name needs. The built-in set is dark enough now, but a
52
+ * collaborator's own colour can be anything, so the tag still asks.
53
+ * A colour that is not a hex triplet gets white, the way it always did.
54
+ */
55
+ export declare function presenceInk(colour: string): '#000' | '#fff';
56
+ /** Two initials for the tag when the box is too small for a name. */
57
+ export declare function presenceInitials(name: string): string;
58
+ /**
59
+ * The peers still here: the newest entry per person, anyone quiet for
60
+ * longer than `timeoutMs` dropped.
61
+ *
62
+ * A network gives no "goodbye" when a tab is closed, so the only honest
63
+ * answer to "is this person still here" is how long ago they last said
64
+ * anything. Fifteen seconds is the grid's own answer, and this keeps to it.
65
+ */
66
+ export declare function livePresence(list: ReadonlyArray<SheetPresence>, now?: number, timeoutMs?: number): SheetPresence[];
67
+ /** The peers on one sheet, in a stable order so the boxes do not swap. */
68
+ export declare function presenceOnSheet(list: ReadonlyArray<SheetPresence>, sheet: string): SheetPresence[];
69
+ /** Where the tag goes: the cell named, or the top-left of the selection. */
70
+ export declare function presenceAnchor(person: SheetPresence): {
71
+ row: number;
72
+ col: number;
73
+ };
@@ -0,0 +1,79 @@
1
+ /**
2
+ * Eight colours that read as different people rather than as a heat map,
3
+ * stay legible as a thin box over a white sheet and over a dark one, and
4
+ * each carry a white name at 11px at 4.5:1 or better, so every tag wears
5
+ * the same white ink. The first set had five a shade too light for that.
6
+ */
7
+ export const PRESENCE_COLOURS = [
8
+ '#e11d48', '#2563eb', '#15803d', '#7e22ce',
9
+ '#c2410c', '#0e7490', '#a16207', '#db2777',
10
+ ];
11
+ /** A colour for an id: the same person gets the same one every session. */
12
+ export function presenceColour(id) {
13
+ let hash = 0;
14
+ for (let i = 0; i < id.length; i += 1)
15
+ hash = (hash * 31 + id.charCodeAt(i)) >>> 0;
16
+ return PRESENCE_COLOURS[hash % PRESENCE_COLOURS.length];
17
+ }
18
+ /**
19
+ * The ink for a name tag on a person's colour: black or white, whichever
20
+ * contrasts more. White on every colour was the first version, and white
21
+ * on the first set's green, orange or yellow was a little over 3:1, under
22
+ * the 4.5:1 an 11px name needs. The built-in set is dark enough now, but a
23
+ * collaborator's own colour can be anything, so the tag still asks.
24
+ * A colour that is not a hex triplet gets white, the way it always did.
25
+ */
26
+ export function presenceInk(colour) {
27
+ const hex = /^#([0-9a-f]{3}|[0-9a-f]{6})$/i.exec(colour.trim());
28
+ if (!hex)
29
+ return '#fff';
30
+ const digits = hex[1].length === 3 ? [...hex[1]].map((d) => d + d).join('') : hex[1];
31
+ const channel = (at) => {
32
+ const c = parseInt(digits.slice(at, at + 2), 16) / 255;
33
+ return c <= 0.03928 ? c / 12.92 : ((c + 0.055) / 1.055) ** 2.4;
34
+ };
35
+ const luminance = 0.2126 * channel(0) + 0.7152 * channel(2) + 0.0722 * channel(4);
36
+ // Contrast against white is (1.05 / (L + 0.05)); against black, (L + 0.05) / 0.05.
37
+ return 1.05 / (luminance + 0.05) >= (luminance + 0.05) / 0.05 ? '#fff' : '#000';
38
+ }
39
+ /** Two initials for the tag when the box is too small for a name. */
40
+ export function presenceInitials(name) {
41
+ const words = name.trim().split(/\s+/).filter(Boolean);
42
+ if (words.length === 0)
43
+ return '?';
44
+ if (words.length === 1)
45
+ return words[0].slice(0, 2).toUpperCase();
46
+ return `${words[0][0]}${words[words.length - 1][0]}`.toUpperCase();
47
+ }
48
+ /**
49
+ * The peers still here: the newest entry per person, anyone quiet for
50
+ * longer than `timeoutMs` dropped.
51
+ *
52
+ * A network gives no "goodbye" when a tab is closed, so the only honest
53
+ * answer to "is this person still here" is how long ago they last said
54
+ * anything. Fifteen seconds is the grid's own answer, and this keeps to it.
55
+ */
56
+ export function livePresence(list, now = Date.now(), timeoutMs = 15000) {
57
+ const newest = new Map();
58
+ for (const person of list) {
59
+ if (now - (person.at ?? now) > timeoutMs)
60
+ continue;
61
+ const had = newest.get(person.id);
62
+ if (!had || (person.at ?? now) >= (had.at ?? now))
63
+ newest.set(person.id, person);
64
+ }
65
+ return [...newest.values()];
66
+ }
67
+ /** The peers on one sheet, in a stable order so the boxes do not swap. */
68
+ export function presenceOnSheet(list, sheet) {
69
+ return list
70
+ .filter((person) => person.sheet.toLowerCase() === sheet.toLowerCase())
71
+ .sort((a, b) => a.id.localeCompare(b.id));
72
+ }
73
+ /** Where the tag goes: the cell named, or the top-left of the selection. */
74
+ export function presenceAnchor(person) {
75
+ if (person.active)
76
+ return person.active;
77
+ const [r1, c1] = person.rect;
78
+ return { row: r1, col: c1 };
79
+ }