@svgrid/enterprise 3.0.2 → 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 (364) hide show
  1. package/LICENSE +94 -24
  2. package/README.md +36 -4
  3. package/dist/SvAdvancedFilter.svelte +1 -1
  4. package/dist/SvAlertsManager.svelte +2 -1
  5. package/dist/SvBoard.svelte +2 -1
  6. package/dist/SvExportMenu.svelte +4 -1
  7. package/dist/SvExportMenu.svelte.d.ts +0 -13
  8. package/dist/SvExpressionEditor.svelte +3 -3
  9. package/dist/SvFormulaBar.svelte +94 -20
  10. package/dist/SvFormulaBar.svelte.d.ts +7 -0
  11. package/dist/SvGridAlerts.svelte +49 -9
  12. package/dist/SvGridBoard.svelte +13 -8
  13. package/dist/SvGridBulkEditDrawer.svelte +26 -2
  14. package/dist/SvGridEditPanel.svelte +3 -0
  15. package/dist/SvGridScheduler.svelte +69 -40
  16. package/dist/SvGridSelectionBar.svelte +10 -3
  17. package/dist/SvPivotDesigner.svelte +198 -40
  18. package/dist/SvPivotDesigner.svelte.d.ts +27 -20
  19. package/dist/SvSheet.svelte +4043 -243
  20. package/dist/SvSheet.svelte.d.ts +76 -3
  21. package/dist/SvSheetChartSetup.svelte +151 -0
  22. package/dist/SvSheetChartSetup.svelte.d.ts +18 -0
  23. package/dist/SvSheetComment.svelte +216 -31
  24. package/dist/SvSheetComment.svelte.d.ts +11 -11
  25. package/dist/SvSheetConditionalFormat.svelte +28 -31
  26. package/dist/SvSheetDataValidation.svelte +66 -42
  27. package/dist/SvSheetEditRanges.svelte +217 -0
  28. package/dist/SvSheetEditRanges.svelte.d.ts +15 -0
  29. package/dist/SvSheetErrors.svelte +125 -0
  30. package/dist/SvSheetErrors.svelte.d.ts +20 -0
  31. package/dist/SvSheetEvaluate.svelte +133 -0
  32. package/dist/SvSheetEvaluate.svelte.d.ts +15 -0
  33. package/dist/SvSheetFilterMenu.svelte +137 -34
  34. package/dist/SvSheetFilterMenu.svelte.d.ts +5 -0
  35. package/dist/SvSheetFindReplace.svelte +19 -19
  36. package/dist/SvSheetFormatCells.svelte +125 -81
  37. package/dist/SvSheetGoalSeek.svelte +17 -16
  38. package/dist/SvSheetInsertFunction.svelte +15 -13
  39. package/dist/SvSheetIteration.svelte +81 -0
  40. package/dist/SvSheetIteration.svelte.d.ts +10 -0
  41. package/dist/SvSheetLink.svelte +99 -0
  42. package/dist/SvSheetLink.svelte.d.ts +17 -0
  43. package/dist/SvSheetListPicker.svelte +4 -2
  44. package/dist/SvSheetListPicker.svelte.d.ts +0 -6
  45. package/dist/SvSheetManageRules.svelte +20 -18
  46. package/dist/SvSheetNameManager.svelte +17 -15
  47. package/dist/SvSheetPageSetup.svelte +159 -0
  48. package/dist/SvSheetPageSetup.svelte.d.ts +13 -0
  49. package/dist/SvSheetPasteSpecial.svelte +22 -20
  50. package/dist/SvSheetPivot.svelte +220 -0
  51. package/dist/SvSheetPivot.svelte.d.ts +21 -0
  52. package/dist/SvSheetProtectSheet.svelte +81 -0
  53. package/dist/SvSheetProtectSheet.svelte.d.ts +11 -0
  54. package/dist/SvSheetRemoveDuplicates.svelte +13 -10
  55. package/dist/SvSheetRibbon.svelte +104 -51
  56. package/dist/SvSheetSizeDialog.svelte +4 -2
  57. package/dist/SvSheetSort.svelte +218 -0
  58. package/dist/SvSheetSort.svelte.d.ts +28 -0
  59. package/dist/SvSheetSparklines.svelte +135 -0
  60. package/dist/SvSheetSparklines.svelte.d.ts +14 -0
  61. package/dist/SvSheetTable.svelte +160 -0
  62. package/dist/SvSheetTable.svelte.d.ts +24 -0
  63. package/dist/SvSheetTabs.svelte +161 -31
  64. package/dist/SvSheetTabs.svelte.d.ts +22 -8
  65. package/dist/SvSheetTextToColumns.svelte +20 -20
  66. package/dist/SvSheetValidationAlert.svelte +8 -6
  67. package/dist/advanced-filter-enable.js +1 -1
  68. package/dist/alerts/alert-engine.d.ts +6 -0
  69. package/dist/alerts/alert-engine.js +21 -4
  70. package/dist/alerts/alert-formats.js +2 -0
  71. package/dist/alerts/alert-types.d.ts +1 -1
  72. package/dist/alerts.d.ts +1 -1
  73. package/dist/alerts.js +2 -2
  74. package/dist/board.js +2 -2
  75. package/dist/bulk-edit.d.ts +3 -1
  76. package/dist/bulk-edit.js +1 -1
  77. package/dist/cdn/svgrid-enterprise.svelte-external.js +39827 -16429
  78. package/dist/designer/assets/GridMenus-8gTNssgV.js +8 -0
  79. package/dist/designer/assets/{SvChartMenu-D9hEeHar.js → SvChartMenu-BDoeqGz6.js} +1 -1
  80. package/dist/designer/assets/{SvDateTimePicker-DARvKUL2.js → SvDateTimePicker-DCPg7WGN.js} +1 -1
  81. package/dist/designer/assets/SvGridCellEditor-DMoWJjEI.js +4 -0
  82. package/dist/designer/assets/{SvGridChart-B8j1SSy3.js → SvGridChart-Cy1ATrWh.js} +2 -2
  83. package/dist/designer/assets/SvGridChartBuilder-eQ3mn0L9.js +1 -0
  84. package/dist/designer/assets/{SvGridChartPanel-pT6ITc2P.js → SvGridChartPanel-CATdVc9X.js} +3 -3
  85. package/dist/designer/assets/{SvGridChartView-bg281UA1.js → SvGridChartView-CmsZtCED.js} +1 -1
  86. package/dist/designer/assets/SvGridDropdown-Cjz0H-fI.js +1 -0
  87. package/dist/designer/assets/{SvTabs-UFCMTHXS.js → SvTabs-2mHC6oaz.js} +1 -1
  88. package/dist/designer/assets/cell-formatting-BbubJTVz.js +1 -0
  89. package/dist/designer/assets/{chart-cIPUsbM5.js → chart-Cn7MnNqA.js} +1 -1
  90. package/dist/designer/assets/{chart-panel-messages-DtTxpBUU.js → chart-panel-messages-Dz7PTIqT.js} +1 -1
  91. package/dist/designer/assets/{chart-summary-Czu_5epb.js → chart-summary-BD1qYB2R.js} +1 -1
  92. package/dist/designer/assets/{chart-trend-D5I5VEe8.js → chart-trend-B8xr5LuD.js} +1 -1
  93. package/dist/designer/assets/{dismissable-BO547MH9.js → dismissable-ChWRPkoa.js} +1 -1
  94. package/dist/designer/assets/{export-format-D-eP4b2l.js → export-format-DGckmgKr.js} +1 -1
  95. package/dist/designer/assets/{focus-trap-CAreAhlU.js → focus-trap-V2-6Fy9I.js} +1 -1
  96. package/dist/designer/assets/{index-DwU7CAMm.js → index-D5bVbuzI.js} +317 -315
  97. package/dist/designer/assets/index-_JVFxt02.css +1 -0
  98. package/dist/designer/assets/row-resize-BInFWCpr.js +1 -0
  99. package/dist/designer/assets/server-block-cache-CXJKkJpy.js +1 -0
  100. package/dist/designer/assets/src-DUQ4xE3x.js +58 -0
  101. package/dist/designer/assets/validate-C3B8QKsM.js +1 -0
  102. package/dist/designer/index.html +17 -16
  103. package/dist/export-pdf.d.ts +75 -0
  104. package/dist/export-pdf.js +216 -15
  105. package/dist/export.js +10 -2
  106. package/dist/gantt/SvGridGantt.svelte +2890 -0
  107. package/dist/gantt/SvGridGantt.svelte.d.ts +30 -0
  108. package/dist/gantt/gantt-config.d.ts +73 -0
  109. package/dist/gantt/gantt-config.js +1 -0
  110. package/dist/gantt/gantt-critical-path.d.ts +67 -0
  111. package/dist/gantt/gantt-critical-path.js +207 -0
  112. package/dist/gantt/gantt-model.d.ts +257 -0
  113. package/dist/gantt/gantt-model.js +651 -0
  114. package/dist/gantt/gantt-resources.d.ts +59 -0
  115. package/dist/gantt/gantt-resources.js +71 -0
  116. package/dist/gantt/gantt.d.ts +7 -0
  117. package/dist/gantt/gantt.js +36 -0
  118. package/dist/gantt/index.d.ts +15 -0
  119. package/dist/gantt/index.js +22 -0
  120. package/dist/gantt/timeline-arrows.d.ts +102 -0
  121. package/dist/gantt/timeline-arrows.js +181 -0
  122. package/dist/import.d.ts +2 -2
  123. package/dist/import.js +1 -1
  124. package/dist/index.d.ts +34 -7
  125. package/dist/index.js +44 -7
  126. package/dist/install.js +8 -1
  127. package/dist/license-core.d.ts +17 -1
  128. package/dist/license-core.js +16 -5
  129. package/dist/license.d.ts +18 -2
  130. package/dist/license.js +71 -6
  131. package/dist/node/studio.js +140 -8
  132. package/dist/pivot-enable.js +2 -2
  133. package/dist/scheduler-dependencies.d.ts +35 -0
  134. package/dist/scheduler-dependencies.js +36 -1
  135. package/dist/scheduler.js +2 -2
  136. package/dist/selection-bar.js +2 -2
  137. package/dist/server/SvGroupCell.svelte +213 -0
  138. package/dist/server/SvGroupCell.svelte.d.ts +62 -0
  139. package/dist/server/SvRowGroupPanel.svelte +322 -0
  140. package/dist/server/SvRowGroupPanel.svelte.d.ts +37 -0
  141. package/dist/server/enable.d.ts +17 -0
  142. package/dist/server/enable.js +49 -0
  143. package/dist/server/index.d.ts +22 -0
  144. package/dist/server/index.js +24 -0
  145. package/dist/server/messages.d.ts +45 -0
  146. package/dist/server/messages.js +35 -0
  147. package/dist/server/server-group-model.d.ts +104 -0
  148. package/dist/server/server-group-model.js +272 -0
  149. package/dist/server/server-pivot.d.ts +46 -0
  150. package/dist/server/server-pivot.js +57 -0
  151. package/dist/server/server-row-model.d.ts +547 -0
  152. package/dist/server/server-row-model.js +1551 -0
  153. package/dist/server/server-selection.d.ts +99 -0
  154. package/dist/server/server-selection.js +215 -0
  155. package/dist/server/svgrid-adapter.d.ts +155 -0
  156. package/dist/server/svgrid-adapter.js +202 -0
  157. package/dist/sheet/ast.d.ts +45 -1
  158. package/dist/sheet/ast.js +14 -0
  159. package/dist/sheet/auto-filter.d.ts +58 -4
  160. package/dist/sheet/auto-filter.js +159 -11
  161. package/dist/sheet/autocomplete.d.ts +9 -0
  162. package/dist/sheet/autocomplete.js +90 -4
  163. package/dist/sheet/cell-images.d.ts +39 -0
  164. package/dist/sheet/cell-images.js +90 -0
  165. package/dist/sheet/cell-types.d.ts +58 -0
  166. package/dist/sheet/cell-types.js +96 -0
  167. package/dist/sheet/coerce.d.ts +40 -0
  168. package/dist/sheet/coerce.js +170 -3
  169. package/dist/sheet/comments.d.ts +43 -9
  170. package/dist/sheet/comments.js +85 -27
  171. package/dist/sheet/conditional-formats.d.ts +29 -6
  172. package/dist/sheet/conditional-formats.js +37 -12
  173. package/dist/sheet/csv.d.ts +32 -0
  174. package/dist/sheet/csv.js +158 -0
  175. package/dist/sheet/culture.d.ts +87 -0
  176. package/dist/sheet/culture.js +247 -0
  177. package/dist/sheet/delta.d.ts +102 -0
  178. package/dist/sheet/delta.js +203 -0
  179. package/dist/sheet/deps.d.ts +45 -1
  180. package/dist/sheet/deps.js +77 -2
  181. package/dist/sheet/document.d.ts +106 -4
  182. package/dist/sheet/document.js +204 -3
  183. package/dist/sheet/engine.d.ts +67 -0
  184. package/dist/sheet/engine.js +19 -0
  185. package/dist/sheet/entry.d.ts +8 -4
  186. package/dist/sheet/entry.js +171 -21
  187. package/dist/sheet/error-check.d.ts +49 -0
  188. package/dist/sheet/error-check.js +83 -0
  189. package/dist/sheet/evaluate-steps.d.ts +48 -0
  190. package/dist/sheet/evaluate-steps.js +196 -0
  191. package/dist/sheet/evaluate.d.ts +67 -0
  192. package/dist/sheet/evaluate.js +725 -13
  193. package/dist/sheet/filter-files.d.ts +37 -0
  194. package/dist/sheet/filter-files.js +465 -0
  195. package/dist/sheet/format-store.d.ts +15 -0
  196. package/dist/sheet/format-store.js +11 -1
  197. package/dist/sheet/from-rows.d.ts +14 -0
  198. package/dist/sheet/from-rows.js +50 -0
  199. package/dist/sheet/function-catalog.d.ts +1 -1
  200. package/dist/sheet/function-catalog.js +296 -5
  201. package/dist/sheet/functions.js +363 -91
  202. package/dist/sheet/index.d.ts +35 -8
  203. package/dist/sheet/index.js +35 -8
  204. package/dist/sheet/links.d.ts +57 -0
  205. package/dist/sheet/links.js +174 -0
  206. package/dist/sheet/messages.d.ts +778 -0
  207. package/dist/sheet/messages.js +806 -0
  208. package/dist/sheet/number-format.d.ts +52 -5
  209. package/dist/sheet/number-format.js +465 -68
  210. package/dist/sheet/objects.d.ts +106 -0
  211. package/dist/sheet/objects.js +149 -0
  212. package/dist/sheet/ods-document.d.ts +44 -0
  213. package/dist/sheet/ods-document.js +1275 -0
  214. package/dist/sheet/open-file.d.ts +26 -0
  215. package/dist/sheet/open-file.js +56 -0
  216. package/dist/sheet/outline.d.ts +82 -0
  217. package/dist/sheet/outline.js +228 -0
  218. package/dist/sheet/packs/array.d.ts +16 -0
  219. package/dist/sheet/packs/array.js +172 -0
  220. package/dist/sheet/packs/database.d.ts +42 -0
  221. package/dist/sheet/packs/database.js +142 -0
  222. package/dist/sheet/packs/engineering.d.ts +2 -0
  223. package/dist/sheet/packs/engineering.js +296 -0
  224. package/dist/sheet/packs/financial.d.ts +5 -0
  225. package/dist/sheet/packs/financial.js +220 -0
  226. package/dist/sheet/packs/math-stats.d.ts +2 -0
  227. package/dist/sheet/packs/math-stats.js +372 -0
  228. package/dist/sheet/packs/special.d.ts +44 -0
  229. package/dist/sheet/packs/special.js +187 -0
  230. package/dist/sheet/packs/stats-dist.d.ts +2 -0
  231. package/dist/sheet/packs/stats-dist.js +785 -0
  232. package/dist/sheet/packs/text-date.d.ts +2 -0
  233. package/dist/sheet/packs/text-date.js +332 -0
  234. package/dist/sheet/packs/trig.d.ts +2 -0
  235. package/dist/sheet/packs/trig.js +73 -0
  236. package/dist/sheet/page-setup.d.ts +73 -0
  237. package/dist/sheet/page-setup.js +73 -0
  238. package/dist/sheet/parse.js +42 -10
  239. package/dist/sheet/paste-special.d.ts +22 -0
  240. package/dist/sheet/paste-special.js +14 -5
  241. package/dist/sheet/pivot-range.d.ts +160 -0
  242. package/dist/sheet/pivot-range.js +333 -0
  243. package/dist/sheet/presence.d.ts +73 -0
  244. package/dist/sheet/presence.js +79 -0
  245. package/dist/sheet/print.d.ts +104 -0
  246. package/dist/sheet/print.js +169 -0
  247. package/dist/sheet/protection.d.ts +55 -1
  248. package/dist/sheet/protection.js +55 -2
  249. package/dist/sheet/rects.d.ts +1 -1
  250. package/dist/sheet/refs.d.ts +48 -0
  251. package/dist/sheet/refs.js +155 -8
  252. package/dist/sheet/ribbon-icons.d.ts +1 -1
  253. package/dist/sheet/ribbon-icons.js +186 -0
  254. package/dist/sheet/ribbon.d.ts +1 -1
  255. package/dist/sheet/ribbon.js +324 -23
  256. package/dist/sheet/sheet-kinds.d.ts +74 -0
  257. package/dist/sheet/sheet-kinds.js +91 -0
  258. package/dist/sheet/shortcuts.d.ts +13 -3
  259. package/dist/sheet/shortcuts.js +63 -12
  260. package/dist/sheet/sort.d.ts +51 -0
  261. package/dist/sheet/sort.js +107 -0
  262. package/dist/sheet/sparklines.d.ts +111 -0
  263. package/dist/sheet/sparklines.js +204 -0
  264. package/dist/sheet/table-styles.d.ts +74 -0
  265. package/dist/sheet/table-styles.js +152 -0
  266. package/dist/sheet/tables.d.ts +19 -0
  267. package/dist/sheet/tables.js +31 -0
  268. package/dist/sheet/tokenize.d.ts +18 -1
  269. package/dist/sheet/tokenize.js +60 -9
  270. package/dist/sheet/validation.d.ts +16 -0
  271. package/dist/sheet/validation.js +37 -0
  272. package/dist/sheet/workbook.d.ts +148 -3
  273. package/dist/sheet/workbook.js +742 -31
  274. package/dist/sheet/xls-cfb.d.ts +32 -0
  275. package/dist/sheet/xls-cfb.js +290 -0
  276. package/dist/sheet/xls-document.d.ts +10 -0
  277. package/dist/sheet/xls-document.js +1243 -0
  278. package/dist/sheet/xls-formula.d.ts +40 -0
  279. package/dist/sheet/xls-formula.js +569 -0
  280. package/dist/sheet/xlsx-document.d.ts +108 -0
  281. package/dist/sheet/xlsx-document.js +1849 -0
  282. package/dist/sheet/xlsx-drawing.d.ts +99 -0
  283. package/dist/sheet/xlsx-drawing.js +420 -0
  284. package/dist/sheet-enable.js +6 -7
  285. package/dist/sheet-text.d.ts +7 -0
  286. package/dist/sheet-text.js +29 -0
  287. package/dist/sources/auth-supabase.js +2 -2
  288. package/dist/sources/realtime-supabase.js +2 -2
  289. package/dist/sources/rest.d.ts +6 -2
  290. package/dist/sources/rest.js +42 -7
  291. package/dist/sources/supabase.d.ts +10 -1
  292. package/dist/sources/supabase.js +73 -40
  293. package/dist/studio/emit-project.js +14 -1
  294. package/dist/studio/index.js +1 -1
  295. package/dist/studio/project.d.ts +11 -2
  296. package/dist/studio/project.js +5 -2
  297. package/dist/studio/ui-components.generated.js +107 -2
  298. package/dist/sveltekit/in-memory.d.ts +2 -2
  299. package/dist/sveltekit/in-memory.js +125 -4
  300. package/dist/sveltekit/index.d.ts +1 -1
  301. package/dist/sveltekit/index.js +1 -1
  302. package/dist/sveltekit/query-plan.d.ts +50 -4
  303. package/dist/sveltekit/query-plan.js +25 -3
  304. package/dist/sveltekit/sql-source.d.ts +6 -0
  305. package/dist/sveltekit/sql-source.js +34 -6
  306. package/dist/sveltekit/sql.d.ts +31 -0
  307. package/dist/sveltekit/sql.js +135 -25
  308. package/dist/sveltekit/transport.d.ts +10 -2
  309. package/dist/sveltekit/transport.js +30 -6
  310. package/dist/upgrade-prompt.d.ts +1 -1
  311. package/dist/version.d.ts +1 -1
  312. package/dist/version.js +1 -1
  313. package/dist/watermark.js +35 -2
  314. package/dist/wc/GridMenus-By9vPuq0.js +1088 -0
  315. package/dist/wc/SvChartMenu-CQNrQGT2.js +308 -0
  316. package/dist/wc/SvDateRangeInput-DR6m7bSM.js +199 -0
  317. package/dist/wc/SvDateTimePicker-D-vRnaMo.js +771 -0
  318. package/dist/wc/SvField-B_kurx_P.js +149 -0
  319. package/dist/wc/SvGrid.helpers-BdVDtjUm.js +135 -0
  320. package/dist/wc/SvGridCellEditor-Bnf1Kr5C.js +560 -0
  321. package/dist/wc/SvGridChart-BqUJh2pG.js +3572 -0
  322. package/dist/wc/SvGridChartBuilder-CGycC5cn.js +988 -0
  323. package/dist/wc/SvGridChartPanel-CRnizsHD.js +1746 -0
  324. package/dist/wc/SvGridChartView-D1pa_xMy.js +47 -0
  325. package/dist/wc/SvGridDropdown-45WsObLL.js +259 -0
  326. package/dist/wc/SvModal-DrfOYYyX.js +189 -0
  327. package/dist/wc/cell-formatting-CBfgahv1.js +86 -0
  328. package/dist/wc/chart-6OXlybVT.js +4341 -0
  329. package/dist/wc/chart-export-CeSADGfi.js +135 -0
  330. package/dist/wc/chart-export-pdf-BGko7MER.js +104 -0
  331. package/dist/wc/chart-summary-2m3ia1-n.js +137 -0
  332. package/dist/wc/chart-trend-CQOQtTMl.js +50 -0
  333. package/dist/wc/chart-validate-CD6ptiwg.js +180 -0
  334. package/dist/wc/client-DQIzjDBG.js +3064 -0
  335. package/dist/wc/column-resize-DUPgynvc.js +101 -0
  336. package/dist/wc/date-format-DS-z_h9v.js +1130 -0
  337. package/dist/wc/dismissable-CQ6XFXsk.js +45 -0
  338. package/dist/wc/editor-contract-peBDxir_.js +22 -0
  339. package/dist/wc/editor-registry-DxGKqcvx.js +24 -0
  340. package/dist/wc/focus-trap-Dbb2tJxb.js +65 -0
  341. package/dist/wc/list-option-DrRyivWp.js +82 -0
  342. package/dist/wc/popover-WsGlvtQv.js +69 -0
  343. package/dist/wc/positioning-BiKLfu1E.js +112 -0
  344. package/dist/wc/react.d.ts +41 -0
  345. package/dist/wc/react.js +90 -0
  346. package/dist/wc/rolldown-runtime-Dy4uBu1J.js +11 -0
  347. package/dist/wc/row-drag-touch-CycRR65n.js +93 -0
  348. package/dist/wc/row-resize-limG_N1z.js +111 -0
  349. package/dist/wc/sv-sheet-element.d.ts +97 -0
  350. package/dist/wc/sv-sheet-element.js +44213 -0
  351. package/dist/wc/svelte-virtualizer.svelte-CXtQy2TQ.js +530 -0
  352. package/dist/wc/validate-BqDthkNr.js +88 -0
  353. package/dist/wc/vue.d.ts +31 -0
  354. package/dist/wc/vue.js +75 -0
  355. package/package.json +30 -5
  356. package/dist/designer/assets/GridMenus-BlsvL_aU.js +0 -8
  357. package/dist/designer/assets/SvGridCellEditor-C7uQXYds.js +0 -4
  358. package/dist/designer/assets/SvGridChartBuilder-kvyIU_Rl.js +0 -1
  359. package/dist/designer/assets/SvGridDropdown-Bb3HH2Aj.js +0 -1
  360. package/dist/designer/assets/cell-formatting-wr5wm7US.js +0 -1
  361. package/dist/designer/assets/index-CMFgAoVV.css +0 -1
  362. package/dist/designer/assets/row-resize-DLktcqUK.js +0 -1
  363. package/dist/designer/assets/src-EdI3Xqds.js +0 -58
  364. package/dist/designer/assets/validate-h-aslRV9.js +0 -1
@@ -48,7 +48,25 @@ export function precedentsOf(ast, self, lastRow,
48
48
  * `Tax` leaves the formula showing its old value until something else
49
49
  * forces a recalculation.
50
50
  */
51
- resolveName, depth = 0) {
51
+ resolveName,
52
+ /**
53
+ * The rectangle behind a structured reference (`Orders[Amount]`,
54
+ * `[@Qty]`). Without it a formula over a table records no precedents, so
55
+ * editing a cell in the table leaves every total reading it stale until
56
+ * something forces a full recalculation.
57
+ */
58
+ resolveTable,
59
+ /**
60
+ * The rectangle a spilled-range operator (`A1#`) currently covers. The
61
+ * anchor cell is always recorded regardless, so a formula reading `A1#`
62
+ * recalculates whenever the array is re-typed and picks up the new extent;
63
+ * the covered cells are added on top so a change anywhere in the spill
64
+ * reaches it too.
65
+ */
66
+ resolveSpill,
67
+ /** The sheets a 3D reference spans, so it recalculates when the cell on any
68
+ * of them changes. */
69
+ resolveSheets, depth = 0) {
52
70
  const out = [];
53
71
  visit(ast, (n) => {
54
72
  if (n.k === 'name') {
@@ -56,7 +74,46 @@ resolveName, depth = 0) {
56
74
  // after a few hops rather than recursing forever.
57
75
  const target = depth < 8 ? resolveName?.(n.name) : null;
58
76
  if (target)
59
- out.push(...precedentsOf(target, self, lastRow, resolveName, depth + 1));
77
+ out.push(...precedentsOf(target, self, lastRow, resolveName, resolveTable, resolveSpill, resolveSheets, depth + 1));
78
+ return;
79
+ }
80
+ if (n.k === 'ref3d') {
81
+ const sheets = resolveSheets?.(n.sheetFrom, n.sheetTo);
82
+ if (!sheets)
83
+ return;
84
+ const r1 = Math.min(n.from.row ?? 0, n.to.row ?? 0);
85
+ const r2 = Math.max(n.from.row ?? 0, n.to.row ?? 0);
86
+ const c1 = Math.min(n.from.col, n.to.col);
87
+ const c2 = Math.max(n.from.col, n.to.col);
88
+ for (const s of sheets) {
89
+ for (let r = r1; r <= r2; r += 1) {
90
+ for (let c = c1; c <= c2; c += 1)
91
+ out.push(cellKey(s, r, c));
92
+ }
93
+ }
94
+ return;
95
+ }
96
+ if (n.k === 'spill') {
97
+ // The anchor always: retyping the array changes the anchor cell, so
98
+ // this makes the reader recalculate and re-derive the extent below.
99
+ out.push(cellKey(n.ref.sheet ?? self.sheet, n.ref.row ?? 0, n.ref.col));
100
+ const rect = resolveSpill?.(n);
101
+ if (rect) {
102
+ for (let r = rect.r1; r <= rect.r2; r += 1) {
103
+ for (let c = rect.c1; c <= rect.c2; c += 1)
104
+ out.push(cellKey(rect.sheet ?? self.sheet, r, c));
105
+ }
106
+ }
107
+ return;
108
+ }
109
+ if (n.k === 'table') {
110
+ const rect = resolveTable?.(n);
111
+ if (!rect)
112
+ return;
113
+ for (let r = rect.firstRow; r <= rect.lastRow; r += 1) {
114
+ for (let c = rect.firstCol; c <= rect.lastCol; c += 1)
115
+ out.push(cellKey(rect.sheet, r, c));
116
+ }
60
117
  return;
61
118
  }
62
119
  if (n.k === 'ref' && n.ref.row !== null) {
@@ -79,6 +136,21 @@ resolveName, depth = 0) {
79
136
  });
80
137
  return out;
81
138
  }
139
+ /**
140
+ * Functions whose result can change without any precedent changing: a
141
+ * reference built from text, a range built from arithmetic, the clock, a
142
+ * random number. A cell holding one is recomputed on every edit, as Excel
143
+ * recomputes its volatile cells, rather than trusting the graph.
144
+ */
145
+ export const VOLATILE_FUNCTIONS = new Set(['INDIRECT', 'OFFSET', 'RAND', 'RANDBETWEEN', 'NOW', 'TODAY']);
146
+ export function isVolatile(ast) {
147
+ let found = false;
148
+ visit(ast, (n) => {
149
+ if (n.k === 'fn' && VOLATILE_FUNCTIONS.has(n.name))
150
+ found = true;
151
+ });
152
+ return found;
153
+ }
82
154
  export function createDependencyGraph() {
83
155
  /** cell -> what it reads. */
84
156
  const precedents = new Map();
@@ -188,6 +260,9 @@ export function createDependencyGraph() {
188
260
  }
189
261
  return out;
190
262
  },
263
+ precedentsOf(cell) {
264
+ return [...(precedents.get(cell) ?? [])];
265
+ },
191
266
  dependentsOf(cell) {
192
267
  return [...(dependents.get(cell) ?? [])];
193
268
  },
@@ -21,10 +21,20 @@ import { type Workbook, type SheetData } from './workbook.js';
21
21
  import { type SheetFormatStore, type CellFormatEntry } from './format-store.js';
22
22
  import type { FreezeState } from './freeze.js';
23
23
  import type { StructuralEdit } from './refs.js';
24
- import { type NotesMap, type Rect } from './rects.js';
24
+ import { type Rect } from './rects.js';
25
+ import type { CommentsMap } from './comments.js';
26
+ import { type SheetProtection } from './protection.js';
27
+ import { type PageSetup } from './page-setup.js';
28
+ import { type SheetObject } from './objects.js';
29
+ import { type SparklineGroup } from './sparklines.js';
30
+ import { type SheetPivot } from './pivot-range.js';
31
+ import { type LinksMap } from './links.js';
25
32
  import { type ValidationRule } from './validation.js';
26
33
  import { type CfRule } from './conditional-formats.js';
27
34
  import { type AutoFilterState } from './auto-filter.js';
35
+ import { type CellTypeRegion } from './cell-types.js';
36
+ import { type GridSheetSpec, type SheetKind } from './sheet-kinds.js';
37
+ import { type OutlineState } from './outline.js';
28
38
  /** Why the document changed. A listener gets every reason since its last call. */
29
39
  export type SheetChangeReason = {
30
40
  kind: 'cells';
@@ -46,6 +56,27 @@ export type SheetChangeReason = {
46
56
  kind: 'conditional-formats';
47
57
  } | {
48
58
  kind: 'protection';
59
+ } | {
60
+ kind: 'page-setup';
61
+ } | {
62
+ kind: 'objects';
63
+ } | {
64
+ kind: 'sparklines';
65
+ } | {
66
+ kind: 'pivots';
67
+ } | {
68
+ kind: 'links';
69
+ } | {
70
+ kind: 'tables';
71
+ }
72
+ /**
73
+ * The workbook's own parts rather than a sheet's: its defined names and
74
+ * its calculation settings. They belong to no sheet, so nothing keyed by
75
+ * sheet can carry them, and a listener that mirrors a document elsewhere
76
+ * has to hear about them separately.
77
+ */
78
+ | {
79
+ kind: 'workbook';
49
80
  } | {
50
81
  kind: 'merges';
51
82
  } | {
@@ -68,15 +99,48 @@ export type PerSheetState = {
68
99
  rows: Set<number>;
69
100
  cols: Set<number>;
70
101
  };
102
+ /** Data > Group: the outline level of each row and column, and which
103
+ * summary lines are collapsed. Lines a collapsed group hides are kept
104
+ * apart from `hidden`, so expanding a group does not un-hide a row the
105
+ * user hid by hand. */
106
+ outline: {
107
+ rows: OutlineState;
108
+ cols: OutlineState;
109
+ };
71
110
  freeze: FreezeState;
72
- /** Cell comments in the grid's `notes` shape: `r4` -> `B` -> text. */
73
- notes: NotesMap;
111
+ /** Cell comments keyed like the grid's `notes`: `r4` -> `B` -> a note's text or a thread. */
112
+ notes: CommentsMap;
74
113
  protected: boolean;
114
+ /** What stays allowed while protected, and the ranges that take an edit anyway. */
115
+ protection: SheetProtection;
116
+ /** Page Layout: orientation, paper, margins, print area, title rows, gridlines, headings, scale. */
117
+ pageSetup: PageSetup;
118
+ /** Charts and pictures anchored over the cells, back to front. */
119
+ objects: SheetObject[];
120
+ sparklines: SparklineGroup[];
121
+ pivots: SheetPivot[];
122
+ /** Hyperlinks by cell, keyed like the comments: `r4` -> `B` -> the link. */
123
+ links: LinksMap;
124
+ /** Excel's Hide Sheet: the tab is not shown and the shortcuts skip it. */
125
+ sheetHidden: boolean;
126
+ /**
127
+ * What this tab is: a cell grid, or a table bound to records.
128
+ *
129
+ * A `grid` sheet keeps its records in `grid` and projects them into the
130
+ * workbook's cells, so a formula on any other sheet reads it the way it
131
+ * reads a cell sheet. See `sheet-kinds.ts`.
132
+ */
133
+ kind: SheetKind;
134
+ /** The records and columns of a `grid` sheet; absent on a cell sheet. */
135
+ grid?: GridSheetSpec;
75
136
  merges: Rect[];
76
137
  /** Data validation rules, in order; the last one covering a cell applies. */
77
138
  validation: ValidationRule[];
78
139
  /** Conditional formatting rules, in priority order: the first one decides. */
79
140
  conditionalFormats: CfRule[];
141
+ /** Cells drawn as a control rather than as text: a checkbox, a button,
142
+ * a radio group. The cell's value stays the truth. */
143
+ cellTypes: CellTypeRegion[];
80
144
  /** Excel's AutoFilter over a region, or null when the arrows are off. */
81
145
  autoFilter: AutoFilterState | null;
82
146
  /** The rows the AutoFilter hides right now; worked out, never saved. */
@@ -91,12 +155,37 @@ export type SheetStateEntry = {
91
155
  rows: number[];
92
156
  cols: number[];
93
157
  };
158
+ /** Absent in documents saved before outlining existed. */
159
+ outline?: {
160
+ rows: OutlineState;
161
+ cols: OutlineState;
162
+ };
94
163
  freeze: FreezeState;
95
- comments: NotesMap;
164
+ /** `r4` -> `B` -> a note's text, or a thread with its author, replies and state. */
165
+ comments: CommentsMap;
96
166
  protected: boolean;
167
+ /** Absent in documents saved before the allow list and edit ranges existed. */
168
+ protection?: SheetProtection;
169
+ /** Absent in documents saved before Page Layout existed. */
170
+ pageSetup?: PageSetup;
171
+ /** Absent in documents saved before objects existed. */
172
+ objects?: SheetObject[];
173
+ /** Absent in documents saved before sparklines existed. */
174
+ sparklines?: SparklineGroup[];
175
+ /** Absent in documents saved before pivots existed. */
176
+ pivots?: SheetPivot[];
177
+ /** Absent in documents saved before hyperlinks existed. */
178
+ links?: LinksMap;
179
+ /** Absent in documents saved before hidden sheets existed. */
180
+ sheetHidden?: boolean;
181
+ /** Absent in documents saved before sheet kinds existed; reads as 'cells'. */
182
+ kind?: SheetKind;
183
+ grid?: GridSheetSpec;
97
184
  merges: Array<[number, number, number, number]>;
98
185
  validation: ValidationRule[];
99
186
  conditionalFormats: CfRule[];
187
+ /** Absent in documents saved before cell types existed. */
188
+ cellTypes?: CellTypeRegion[];
100
189
  autoFilter: AutoFilterState | null;
101
190
  };
102
191
  /**
@@ -116,6 +205,12 @@ export type SheetDocument = {
116
205
  has(name: string): boolean;
117
206
  rename(from: string, to: string): void;
118
207
  remove(name: string): void;
208
+ /**
209
+ * Excel's Move or Copy > Create a copy: a new sheet after `from` with
210
+ * its cells and everything this document keeps beside them, named `to`
211
+ * or "Name (2)". Returns the new name, or null when it could not.
212
+ */
213
+ duplicate(from: string, to?: string): string | null;
119
214
  /** The sheets that have state, in no particular order. */
120
215
  names(): string[];
121
216
  /**
@@ -135,6 +230,13 @@ export type SheetDocument = {
135
230
  setState(state: SheetState): void;
136
231
  /** Hear about changes, once per tick with every reason since the last call. */
137
232
  subscribe(listener: (reasons: ReadonlyArray<SheetChangeReason>) => void): () => void;
233
+ /**
234
+ * Put back only the parts `entry` names, leaving the rest of the sheet as
235
+ * it is: what a delta from another user applies, and what a host that
236
+ * wants to set one feature calls. Reports the change, so the shell
237
+ * repaints; wrap it in `mute` where it should not.
238
+ */
239
+ patch(name: string, entry: Partial<SheetStateEntry>): void;
138
240
  /** Record a change. Coalesced per microtask; silent while muted. */
139
241
  changed(reason: SheetChangeReason): void;
140
242
  /** Run `fn` without reporting changes: restores and mount-time seeding. */
@@ -20,29 +20,89 @@
20
20
  import { createWorkbook } from './workbook.js';
21
21
  import { createFormatStore } from './format-store.js';
22
22
  import { lineShift, remapNotes, shiftRect } from './rects.js';
23
+ import { copyProtection, defaultProtection } from './protection.js';
24
+ import { copyPageSetup, defaultPageSetup, shiftPageSetup } from './page-setup.js';
25
+ import { copyObject, objectId, shiftObjects } from './objects.js';
26
+ import { copySparkline, shiftSparklines, sparklineId } from './sparklines.js';
27
+ import { copyPivot, pivotId, shiftPivots } from './pivot-range.js';
28
+ import { copyLinks, shiftLinks } from './links.js';
29
+ import { releaseFilteredRows } from './filter-files.js';
23
30
  import { colToLetters, lettersToCol } from './address.js';
24
31
  import { shiftValidation } from './validation.js';
25
32
  import { shiftCf } from './conditional-formats.js';
26
33
  import { shiftAutoFilter } from './auto-filter.js';
34
+ import { copyCellType, shiftCellTypes } from './cell-types.js';
35
+ import { copyGridSheet } from './sheet-kinds.js';
36
+ import { emptyOutline, shiftOutline } from './outline.js';
37
+ /** A deep copy of one axis's outline, absent reading as an empty one. */
38
+ const copyOutline = (o) => (o ? { levels: { ...o.levels }, collapsed: [...o.collapsed] } : emptyOutline());
39
+ /** Which change a patched part of a sheet counts as, so listeners hear it. */
40
+ function reasonsForEntry(entry) {
41
+ const out = [];
42
+ if (entry.formats !== undefined)
43
+ out.push({ kind: 'formats' });
44
+ if (entry.columnWidths !== undefined || entry.rowHeights !== undefined)
45
+ out.push({ kind: 'sizes' });
46
+ if (entry.hidden !== undefined || entry.sheetHidden !== undefined)
47
+ out.push({ kind: 'hidden' });
48
+ if (entry.freeze !== undefined)
49
+ out.push({ kind: 'freeze' });
50
+ if (entry.comments !== undefined)
51
+ out.push({ kind: 'comments' });
52
+ if (entry.protected !== undefined || entry.protection !== undefined)
53
+ out.push({ kind: 'protection' });
54
+ if (entry.pageSetup !== undefined)
55
+ out.push({ kind: 'page-setup' });
56
+ if (entry.objects !== undefined)
57
+ out.push({ kind: 'objects' });
58
+ if (entry.sparklines !== undefined)
59
+ out.push({ kind: 'sparklines' });
60
+ if (entry.pivots !== undefined)
61
+ out.push({ kind: 'pivots' });
62
+ if (entry.links !== undefined)
63
+ out.push({ kind: 'links' });
64
+ if (entry.merges !== undefined)
65
+ out.push({ kind: 'merges' });
66
+ if (entry.validation !== undefined)
67
+ out.push({ kind: 'validation' });
68
+ if (entry.conditionalFormats !== undefined)
69
+ out.push({ kind: 'conditional-formats' });
70
+ if (entry.autoFilter !== undefined)
71
+ out.push({ kind: 'filter' });
72
+ return out;
73
+ }
27
74
  function emptySheetState() {
28
75
  return {
29
76
  formats: createFormatStore(),
30
77
  widths: {},
31
78
  heights: new Map(),
32
79
  hidden: { rows: new Set(), cols: new Set() },
80
+ outline: { rows: emptyOutline(), cols: emptyOutline() },
33
81
  freeze: { rows: 0, cols: 0 },
34
82
  notes: {},
35
83
  protected: false,
84
+ protection: defaultProtection(),
85
+ pageSetup: defaultPageSetup(),
86
+ objects: [],
87
+ sparklines: [],
88
+ pivots: [],
89
+ links: {},
90
+ sheetHidden: false,
91
+ kind: 'cells',
36
92
  merges: [],
37
93
  validation: [],
38
94
  conditionalFormats: [],
95
+ cellTypes: [],
39
96
  autoFilter: null,
40
97
  filterHidden: new Set(),
41
98
  };
42
99
  }
43
100
  export function createSheetDocument(init = {}) {
44
101
  const workbook = init.workbook ??
45
- createWorkbook(init.state ? init.state.workbook.sheets.map((s) => ({ name: s.name, cells: s.cells })) : (init.sheets ? [...init.sheets] : [{ name: 'Sheet1', cells: [] }]));
102
+ createWorkbook(init.state ? init.state.workbook.sheets.map((s) => ({ name: s.name, cells: s.cells })) : (init.sheets ? [...init.sheets] : [{ name: 'Sheet1', cells: [] }]), {
103
+ ...(init.state?.workbook.tables?.length ? { tables: init.state.workbook.tables } : {}),
104
+ ...(init.state?.workbook.iteration ? { iteration: init.state.workbook.iteration } : {}),
105
+ });
46
106
  const entries = new Map();
47
107
  const listeners = new Set();
48
108
  let pending = [];
@@ -77,29 +137,121 @@ export function createSheetDocument(init = {}) {
77
137
  scheduled = true;
78
138
  queueMicrotask(flush);
79
139
  }
140
+ /** A row of comments copied deep enough that a saved thread is not the live one. */
141
+ function copyLine(line) {
142
+ const out = {};
143
+ for (const [c, v] of Object.entries(line))
144
+ out[c] = typeof v === 'string' ? v : { ...v, ...(v.replies ? { replies: v.replies.map((r) => ({ ...r })) } : {}) };
145
+ return out;
146
+ }
80
147
  function serializeEntry(state) {
81
148
  return {
82
149
  formats: state.formats.serialize(),
83
150
  columnWidths: { ...state.widths },
84
151
  rowHeights: [...state.heights].map(([r, h]) => [r, h]),
85
152
  hidden: { rows: [...state.hidden.rows], cols: [...state.hidden.cols] },
153
+ outline: { rows: copyOutline(state.outline.rows), cols: copyOutline(state.outline.cols) },
86
154
  freeze: { ...state.freeze },
87
- comments: Object.fromEntries(Object.entries(state.notes).map(([r, line]) => [r, { ...line }])),
155
+ comments: Object.fromEntries(Object.entries(state.notes).map(([r, line]) => [r, copyLine(line)])),
88
156
  protected: state.protected,
157
+ protection: copyProtection(state.protection),
158
+ pageSetup: copyPageSetup(state.pageSetup),
159
+ objects: state.objects.map(copyObject),
160
+ sparklines: state.sparklines.map(copySparkline),
161
+ pivots: state.pivots.map(copyPivot),
162
+ links: copyLinks(state.links),
163
+ sheetHidden: state.sheetHidden,
164
+ kind: state.kind,
165
+ ...(state.grid ? { grid: copyGridSheet(state.grid) } : {}),
89
166
  merges: state.merges.map(([r1, c1, r2, c2]) => [r1, c1, r2, c2]),
90
167
  validation: state.validation.map((rule) => ({ ...rule, rects: rule.rects.map((r) => [...r]), alert: { ...rule.alert } })),
91
168
  conditionalFormats: state.conditionalFormats.map((rule) => ({ ...rule, rects: rule.rects.map((r) => [...r]) })),
169
+ cellTypes: state.cellTypes.map(copyCellType),
92
170
  autoFilter: state.autoFilter ? { range: [...state.autoFilter.range], filters: { ...state.autoFilter.filters } } : null,
93
171
  };
94
172
  }
173
+ /**
174
+ * Put back only the parts an entry names, leaving the rest as they are.
175
+ * `hydrateEntry` below is the whole-sheet version, which resets what is
176
+ * absent to its default; this one is what a delta applies, since a delta
177
+ * carries the one feature that changed.
178
+ */
179
+ function patchEntry(state, entry) {
180
+ if (entry.formats !== undefined)
181
+ state.formats.hydrate(entry.formats);
182
+ if (entry.columnWidths !== undefined)
183
+ state.widths = { ...entry.columnWidths };
184
+ if (entry.rowHeights !== undefined)
185
+ state.heights = new Map(entry.rowHeights);
186
+ if (entry.hidden !== undefined)
187
+ state.hidden = { rows: new Set(entry.hidden.rows ?? []), cols: new Set(entry.hidden.cols ?? []) };
188
+ if (entry.outline !== undefined)
189
+ state.outline = { rows: copyOutline(entry.outline.rows), cols: copyOutline(entry.outline.cols) };
190
+ if (entry.freeze !== undefined)
191
+ state.freeze = { rows: entry.freeze.rows ?? 0, cols: entry.freeze.cols ?? 0 };
192
+ if (entry.comments !== undefined)
193
+ state.notes = Object.fromEntries(Object.entries(entry.comments).map(([r, line]) => [r, copyLine(line)]));
194
+ if (entry.protected !== undefined)
195
+ state.protected = entry.protected;
196
+ if (entry.protection !== undefined)
197
+ state.protection = copyProtection({ allow: entry.protection.allow ?? {}, ranges: entry.protection.ranges ?? [] });
198
+ if (entry.pageSetup !== undefined)
199
+ state.pageSetup = copyPageSetup({ ...defaultPageSetup(), ...entry.pageSetup });
200
+ if (entry.objects !== undefined)
201
+ state.objects = entry.objects.map(copyObject);
202
+ if (entry.sparklines !== undefined)
203
+ state.sparklines = entry.sparklines.map(copySparkline);
204
+ if (entry.pivots !== undefined)
205
+ state.pivots = entry.pivots.map(copyPivot);
206
+ if (entry.links !== undefined)
207
+ state.links = copyLinks(entry.links);
208
+ if (entry.sheetHidden !== undefined)
209
+ state.sheetHidden = entry.sheetHidden;
210
+ if (entry.kind !== undefined)
211
+ state.kind = entry.kind;
212
+ if (entry.grid !== undefined)
213
+ state.grid = copyGridSheet(entry.grid);
214
+ if (entry.merges !== undefined)
215
+ state.merges = entry.merges.map(([r1, c1, r2, c2]) => [r1, c1, r2, c2]);
216
+ if (entry.validation !== undefined) {
217
+ state.validation = entry.validation.map((rule) => ({
218
+ ...rule,
219
+ rects: rule.rects.map(([r1, c1, r2, c2]) => [r1, c1, r2, c2]),
220
+ alert: { ...rule.alert },
221
+ }));
222
+ }
223
+ if (entry.conditionalFormats !== undefined) {
224
+ state.conditionalFormats = entry.conditionalFormats.map((rule) => ({
225
+ ...rule,
226
+ rects: rule.rects.map(([r1, c1, r2, c2]) => [r1, c1, r2, c2]),
227
+ }));
228
+ }
229
+ if (entry.cellTypes !== undefined)
230
+ state.cellTypes = entry.cellTypes.map(copyCellType);
231
+ if (entry.autoFilter !== undefined) {
232
+ const af = entry.autoFilter;
233
+ state.autoFilter = af ? { range: [af.range[0], af.range[1], af.range[2], af.range[3]], filters: { ...af.filters } } : null;
234
+ state.filterHidden = new Set();
235
+ }
236
+ }
95
237
  function hydrateEntry(state, entry) {
96
238
  state.formats.hydrate(entry.formats ?? {});
97
239
  state.widths = { ...(entry.columnWidths ?? {}) };
98
240
  state.heights = new Map(entry.rowHeights ?? []);
99
241
  state.hidden = { rows: new Set(entry.hidden?.rows ?? []), cols: new Set(entry.hidden?.cols ?? []) };
242
+ state.outline = { rows: copyOutline(entry.outline?.rows), cols: copyOutline(entry.outline?.cols) };
100
243
  state.freeze = { rows: entry.freeze?.rows ?? 0, cols: entry.freeze?.cols ?? 0 };
101
- state.notes = Object.fromEntries(Object.entries(entry.comments ?? {}).map(([r, line]) => [r, { ...line }]));
244
+ state.notes = Object.fromEntries(Object.entries(entry.comments ?? {}).map(([r, line]) => [r, copyLine(line)]));
102
245
  state.protected = entry.protected ?? false;
246
+ state.protection = entry.protection ? copyProtection({ allow: entry.protection.allow ?? {}, ranges: entry.protection.ranges ?? [] }) : defaultProtection();
247
+ state.pageSetup = entry.pageSetup ? copyPageSetup({ ...defaultPageSetup(), ...entry.pageSetup }) : defaultPageSetup();
248
+ state.objects = (entry.objects ?? []).map(copyObject);
249
+ state.sparklines = (entry.sparklines ?? []).map(copySparkline);
250
+ state.pivots = (entry.pivots ?? []).map(copyPivot);
251
+ state.links = copyLinks(entry.links ?? {});
252
+ state.sheetHidden = entry.sheetHidden ?? false;
253
+ state.kind = entry.kind ?? 'cells';
254
+ state.grid = entry.grid ? copyGridSheet(entry.grid) : undefined;
103
255
  state.merges = (entry.merges ?? []).map(([r1, c1, r2, c2]) => [r1, c1, r2, c2]);
104
256
  state.validation = (entry.validation ?? []).map((rule) => ({
105
257
  ...rule,
@@ -110,6 +262,7 @@ export function createSheetDocument(init = {}) {
110
262
  ...rule,
111
263
  rects: rule.rects.map(([r1, c1, r2, c2]) => [r1, c1, r2, c2]),
112
264
  }));
265
+ state.cellTypes = (entry.cellTypes ?? []).map(copyCellType);
113
266
  const af = entry.autoFilter;
114
267
  state.autoFilter = af ? { range: [af.range[0], af.range[1], af.range[2], af.range[3]], filters: { ...af.filters } } : null;
115
268
  state.filterHidden = new Set();
@@ -117,6 +270,11 @@ export function createSheetDocument(init = {}) {
117
270
  const document = {
118
271
  workbook,
119
272
  get,
273
+ patch(name, entry) {
274
+ patchEntry(get(name), entry);
275
+ for (const reason of reasonsForEntry(entry))
276
+ changed(reason);
277
+ },
120
278
  has: (name) => entries.has(key(name)),
121
279
  rename(from, to) {
122
280
  const moved = entries.get(key(from));
@@ -127,6 +285,24 @@ export function createSheetDocument(init = {}) {
127
285
  remove(name) {
128
286
  entries.delete(key(name));
129
287
  },
288
+ duplicate(from, to) {
289
+ const made = workbook.copySheet(from, to);
290
+ if (made === null)
291
+ return null;
292
+ // Through the JSON shape, so nothing is shared between the two.
293
+ const copy = JSON.parse(JSON.stringify(serializeEntry(get(from))));
294
+ copy.sheetHidden = false;
295
+ // The copy's chart, picture, sparkline and pivot are its own, so they
296
+ // get their own ids the way Excel's Move or Copy does. Sharing them
297
+ // would mean a shell that tracks the selected object by id following
298
+ // the copy's one across a sheet switch, and deleting it there.
299
+ copy.objects = copy.objects?.map((object) => ({ ...object, id: objectId() }));
300
+ copy.sparklines = copy.sparklines?.map((group) => ({ ...group, id: sparklineId() }));
301
+ copy.pivots = copy.pivots?.map((pivot) => ({ ...pivot, id: pivotId() }));
302
+ hydrateEntry(get(made), copy);
303
+ changed({ kind: 'sheets' });
304
+ return made;
305
+ },
130
306
  names: () => [...entries.keys()],
131
307
  shift(name, edit) {
132
308
  const state = get(name);
@@ -175,12 +351,25 @@ export function createSheetDocument(init = {}) {
175
351
  hiddenCols.add(next);
176
352
  }
177
353
  state.hidden = { rows: state.hidden.rows, cols: hiddenCols };
354
+ state.outline = { rows: state.outline.rows, cols: shiftOutline(state.outline.cols, edit.at, edit.count * (edit.kind === 'deleteCols' ? -1 : 1)) };
178
355
  state.notes = remapNotes(state.notes, 'cols', shift);
179
356
  }
180
357
  state.merges = state.merges.map((m) => shiftRect(m, edit)).filter((m) => m !== null);
181
358
  state.validation = shiftValidation(state.validation, edit);
182
359
  state.conditionalFormats = shiftCf(state.conditionalFormats, edit);
360
+ state.cellTypes = shiftCellTypes(state.cellTypes, edit);
183
361
  state.autoFilter = shiftAutoFilter(state.autoFilter, edit);
362
+ state.pageSetup = shiftPageSetup(state.pageSetup, edit);
363
+ state.objects = shiftObjects(state.objects, edit);
364
+ state.sparklines = shiftSparklines(state.sparklines, edit);
365
+ state.pivots = shiftPivots(state.pivots, edit);
366
+ state.links = shiftLinks(state.links, edit);
367
+ state.protection = {
368
+ allow: state.protection.allow,
369
+ ranges: state.protection.ranges
370
+ .map((range) => ({ ...range, rects: range.rects.map((r) => shiftRect(r, edit)).filter((r) => r !== null) }))
371
+ .filter((range) => range.rects.length > 0),
372
+ };
184
373
  },
185
374
  getState() {
186
375
  const sheets = {};
@@ -220,6 +409,14 @@ export function createSheetDocument(init = {}) {
220
409
  }
221
410
  }
222
411
  workbook.names.hydrate(state.workbook.names ?? {});
412
+ // Tables are workbook-wide, and the registry is what a structured
413
+ // reference resolves through: put back exactly the saved set.
414
+ workbook.tables.clear();
415
+ for (const table of state.workbook.tables ?? [])
416
+ workbook.tables.define({ ...table });
417
+ // Iterative calculation is workbook-wide too, and absent in a saved
418
+ // document that never turned it on, which means off.
419
+ workbook.setIteration(state.workbook.iteration ?? { enabled: false });
223
420
  if (workbook.sheets.some((s) => key(s) === key(state.workbook.active)))
224
421
  workbook.setActive(state.workbook.active);
225
422
  // Entries are hydrated in place, never replaced: a format store the
@@ -231,6 +428,8 @@ export function createSheetDocument(init = {}) {
231
428
  entries.delete(name);
232
429
  for (const name of workbook.sheets)
233
430
  hydrateEntry(get(name), state.sheets?.[name] ?? {});
431
+ for (const name of workbook.sheets)
432
+ releaseFilteredRows(document, name);
234
433
  });
235
434
  changed({ kind: 'restore' });
236
435
  },
@@ -258,6 +457,8 @@ export function createSheetDocument(init = {}) {
258
457
  workbook.setActive(init.state.workbook.active);
259
458
  for (const [name, entry] of Object.entries(init.state.sheets ?? {}))
260
459
  hydrateEntry(get(name), entry);
460
+ for (const name of workbook.sheets)
461
+ releaseFilteredRows(document, name);
261
462
  });
262
463
  }
263
464
  return document;
@@ -0,0 +1,67 @@
1
+ /**
2
+ * The seam between the workbook and whatever works a formula out.
3
+ *
4
+ * The built-in engine (the tokenizer, parser and evaluator beside this
5
+ * file) is the one the sheet ships with and the one it is tested against.
6
+ * The seam is here for an application that has its own evaluator to put
7
+ * behind the same sheet: `createWorkbook(sheets, { engine: mine })`.
8
+ *
9
+ * What an engine is asked for is narrow on purpose: a formula's value in
10
+ * a cell, and the grid it spills when it has one. The workbook keeps
11
+ * everything else, because none of it is the engine's to decide. The
12
+ * dependency graph, the volatile set, the value cache, cycle detection
13
+ * and the spill ranges are all read off the reference grammar, which is
14
+ * Excel's whatever evaluates it, so they stay correct for any engine and
15
+ * an engine cannot get them wrong.
16
+ *
17
+ * `load` and `write` are the lifecycle an engine with a copy of the cells
18
+ * needs: `load` when the workbook is built and whenever its cells change
19
+ * wholesale (a structural edit, a sheet added or renamed, a restore),
20
+ * `write` on a single cell. An engine that reads through `host` on demand,
21
+ * as the built-in does, leaves both off.
22
+ */
23
+ import type { CellValue, Node } from './ast.js';
24
+ import type { EvalContext } from './evaluate.js';
25
+ import type { SheetData } from './workbook.js';
26
+ /** Where a formula sits. */
27
+ export type SheetEngineCell = {
28
+ sheet: string;
29
+ row: number;
30
+ col: number;
31
+ };
32
+ export type SheetEngineHost = {
33
+ /**
34
+ * The context the built-in evaluator uses for this cell: `resolve` reads
35
+ * through the workbook's cache and cycle detection, so an engine that
36
+ * wants a precedent's value asks here rather than reading raw text.
37
+ */
38
+ context: EvalContext;
39
+ /** The workbook's parse cache: one parse per distinct formula text, null when it does not parse. */
40
+ parse(text: string): Node | null;
41
+ };
42
+ export type SheetEngineResult = {
43
+ value: CellValue;
44
+ /**
45
+ * The grid the formula spills, or null / absent for a plain value. The
46
+ * workbook lays it over the cells below and to the right, refuses it
47
+ * with `#SPILL!` where something is in the way, and moves it with an
48
+ * insert or delete.
49
+ */
50
+ spill?: CellValue[][] | null;
51
+ };
52
+ export type SheetEngine = {
53
+ /** For the docs and an error message; the built-in is `'builtin'`. */
54
+ name?: string;
55
+ /** Every sheet's raw text, at creation and after a wholesale change. */
56
+ load?(sheets: ReadonlyArray<SheetData>): void;
57
+ /** One cell's raw text changed. */
58
+ write?(sheet: string, row: number, col: number, text: string): void;
59
+ /** What the formula is worth here. `text` keeps its leading `=`. */
60
+ evaluate(text: string, at: SheetEngineCell, host: SheetEngineHost): SheetEngineResult;
61
+ };
62
+ /**
63
+ * The engine the sheet ships with: the parser and evaluator in this
64
+ * folder, which read the workbook's own cells through the host's context
65
+ * and so need no copy of anything.
66
+ */
67
+ export declare function builtinEngine(): SheetEngine;
@@ -0,0 +1,19 @@
1
+ import { evaluate, evaluateSpill } from './evaluate.js';
2
+ /**
3
+ * The engine the sheet ships with: the parser and evaluator in this
4
+ * folder, which read the workbook's own cells through the host's context
5
+ * and so need no copy of anything.
6
+ */
7
+ export function builtinEngine() {
8
+ return {
9
+ name: 'builtin',
10
+ evaluate(text, _at, host) {
11
+ const ast = host.parse(text);
12
+ if (!ast)
13
+ return { value: { error: '#PARSE!' } };
14
+ const value = evaluate(ast, host.context);
15
+ const spill = typeof value === 'object' && value !== null && 'error' in value ? null : evaluateSpill(ast, host.context);
16
+ return { value, spill };
17
+ },
18
+ };
19
+ }