@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
@@ -0,0 +1,204 @@
1
+ import { shiftRect, rectContains } from './rects.js';
2
+ // The geometry only, through the grid's own subpath: this module is read by
3
+ // the xlsx writer and by tests that run without a DOM, and the package root
4
+ // would drag every component in with it.
5
+ import { buildSparkline } from '@svgrid/grid/sparkline';
6
+ /** The three Excel offers: Line, Column and Win/Loss. */
7
+ export const SPARKLINE_TYPES = ['line', 'column', 'winloss'];
8
+ let nextSparklineId = 1;
9
+ /** An id no other group of this session carries. */
10
+ export const sparklineId = () => `spark-${Date.now().toString(36)}-${(nextSparklineId += 1).toString(36)}`;
11
+ /** A copy safe to hand out or save. */
12
+ export function copySparkline(group) {
13
+ return { ...group, location: [...group.location], data: [...group.data] };
14
+ }
15
+ /**
16
+ * The group after an insert or delete: both rectangles move with their
17
+ * cells. Null when the edit took every cell the group was drawn in, or
18
+ * every cell it read.
19
+ */
20
+ export function shiftSparkline(group, edit) {
21
+ const location = shiftRect(group.location, edit);
22
+ if (!location)
23
+ return null;
24
+ const data = shiftRect(group.data, edit);
25
+ if (!data)
26
+ return null;
27
+ return { ...copySparkline(group), location: location, data: data };
28
+ }
29
+ /** The groups of a sheet after an insert or delete, the gone ones dropped. */
30
+ export function shiftSparklines(groups, edit) {
31
+ return groups.map((g) => shiftSparkline(g, edit)).filter((g) => g !== null);
32
+ }
33
+ /** True when the group draws down a column of cells rather than along a row. */
34
+ export function isColumnLocation(group) {
35
+ const [r1, c1, r2, c2] = group.location;
36
+ // A single cell counts as a column: its data is read as one line either way.
37
+ return r2 - r1 >= c2 - c1;
38
+ }
39
+ /** A cell's value as a number, or null when it is not one. */
40
+ function numberOf(value) {
41
+ if (typeof value === 'number')
42
+ return Number.isFinite(value) ? value : null;
43
+ if (typeof value === 'boolean')
44
+ return value ? 1 : 0;
45
+ if (typeof value === 'string' && value.trim() !== '') {
46
+ const n = Number(value);
47
+ return Number.isFinite(n) ? n : null;
48
+ }
49
+ return null;
50
+ }
51
+ /**
52
+ * The numbers one location cell draws, read through `valueAt`. The nth cell
53
+ * of the location reads the nth line of the data: the nth row when the
54
+ * sparklines run down a column, the nth column when they run along a row.
55
+ * A blank or a text cell inside the line is a gap, which Excel draws as a
56
+ * zero rather than breaking the line.
57
+ */
58
+ export function sparklineSeries(group, row, col, valueAt) {
59
+ if (!rectContains(group.location, row, col))
60
+ return null;
61
+ const [lr1, lc1] = group.location;
62
+ const [dr1, dc1, dr2, dc2] = group.data;
63
+ const down = isColumnLocation(group);
64
+ const index = down ? row - lr1 : col - lc1;
65
+ const values = [];
66
+ if (down) {
67
+ const r = dr1 + index;
68
+ if (r > dr2)
69
+ return null;
70
+ for (let c = dc1; c <= dc2; c += 1)
71
+ values.push(numberOf(valueAt(r, c)) ?? 0);
72
+ }
73
+ else {
74
+ const c = dc1 + index;
75
+ if (c > dc2)
76
+ return null;
77
+ for (let r = dr1; r <= dr2; r += 1)
78
+ values.push(numberOf(valueAt(r, c)) ?? 0);
79
+ }
80
+ return values.length ? values : null;
81
+ }
82
+ /** The group drawn in a cell, or null: the last one wins, as Excel's does. */
83
+ /**
84
+ * One line per cell of the group: the cell the sparkline is drawn in and
85
+ * the block of numbers it reads.
86
+ *
87
+ * The drawing works this out cell by cell as it paints; a writer needs the
88
+ * whole list, because Excel stores a sparkline group as one entry per cell
89
+ * with its own reference.
90
+ */
91
+ /**
92
+ * A sparkline as standalone SVG markup, for a page the component cannot
93
+ * draw on: the printed sheet.
94
+ *
95
+ * The geometry is the grid's own `buildSparkline`, so the printed line is
96
+ * the line on screen rather than a second drawing that can disagree with
97
+ * it. The markup carries its colours inline, since the print document has
98
+ * no stylesheet of ours.
99
+ */
100
+ export function sparklineSvg(values, options) {
101
+ const geo = buildSparkline([...values], {
102
+ type: options.type === 'column' ? 'bar' : options.type === 'winloss' ? 'winloss' : 'line',
103
+ width: options.width,
104
+ height: options.height,
105
+ ...(options.color ? { color: options.color } : {}),
106
+ ...(options.negativeColor ? { negativeColor: options.negativeColor } : {}),
107
+ ...(options.min !== undefined ? { min: options.min } : {}),
108
+ ...(options.max !== undefined ? { max: options.max } : {}),
109
+ lastPoint: Boolean(options.markers),
110
+ });
111
+ if (!geo)
112
+ return '';
113
+ const parts = [];
114
+ if (geo.bars.length) {
115
+ for (const bar of geo.bars) {
116
+ const fill = bar.negative ? geo.negativeColor : geo.color;
117
+ parts.push(`<rect x="${round(bar.x)}" y="${round(bar.y)}" width="${round(bar.w)}" height="${round(bar.h)}" fill="${fill}"/>`);
118
+ }
119
+ }
120
+ if (geo.linePath) {
121
+ parts.push(`<path d="${geo.linePath}" fill="none" stroke="${geo.color}" stroke-width="${geo.lineWidth}" stroke-linejoin="round" stroke-linecap="round"/>`);
122
+ }
123
+ if (geo.lastPoint && options.markers) {
124
+ parts.push(`<circle cx="${round(geo.lastPoint.x)}" cy="${round(geo.lastPoint.y)}" r="${geo.lineWidth + 0.5}" fill="${geo.color}"/>`);
125
+ }
126
+ return `<svg xmlns="http://www.w3.org/2000/svg" width="${geo.width}" height="${geo.height}" viewBox="0 0 ${geo.width} ${geo.height}" role="img" aria-hidden="true">${parts.join('')}</svg>`;
127
+ }
128
+ const round = (n) => Math.round(n * 100) / 100;
129
+ export function sparklineLines(group) {
130
+ const [lr1, lc1, lr2, lc2] = group.location;
131
+ const [dr1, dc1, dr2, dc2] = group.data;
132
+ const down = isColumnLocation(group);
133
+ const out = [];
134
+ const count = down ? lr2 - lr1 + 1 : lc2 - lc1 + 1;
135
+ for (let i = 0; i < count; i += 1) {
136
+ if (down) {
137
+ const r = dr1 + i;
138
+ if (r > dr2)
139
+ break;
140
+ out.push({ row: lr1 + i, col: lc1, data: [r, dc1, r, dc2] });
141
+ }
142
+ else {
143
+ const c = dc1 + i;
144
+ if (c > dc2)
145
+ break;
146
+ out.push({ row: lr1, col: lc1 + i, data: [dr1, c, dr2, c] });
147
+ }
148
+ }
149
+ return out;
150
+ }
151
+ export function sparklineAt(groups, row, col) {
152
+ for (let i = groups.length - 1; i >= 0; i -= 1) {
153
+ if (rectContains(groups[i].location, row, col))
154
+ return groups[i];
155
+ }
156
+ return null;
157
+ }
158
+ /**
159
+ * The scale a group is drawn on when every sparkline in it shares one, which
160
+ * is Excel's "Same for All": the smallest and largest number anywhere in the
161
+ * data range. Null when the group scales each sparkline on its own.
162
+ */
163
+ export function sparklineScale(group, valueAt) {
164
+ if (!group.sameScale)
165
+ return null;
166
+ const [r1, c1, r2, c2] = group.data;
167
+ let min = Infinity;
168
+ let max = -Infinity;
169
+ for (let r = r1; r <= r2; r += 1) {
170
+ for (let c = c1; c <= c2; c += 1) {
171
+ const n = numberOf(valueAt(r, c));
172
+ if (n === null)
173
+ continue;
174
+ if (n < min)
175
+ min = n;
176
+ if (n > max)
177
+ max = n;
178
+ }
179
+ }
180
+ if (min === Infinity)
181
+ return null;
182
+ return min === max ? { min: min - 1, max: max + 1 } : { min, max };
183
+ }
184
+ /**
185
+ * Where Excel's Create Sparklines dialog opens: the data is the selected
186
+ * block, and the location the column just past it (or the row just under it
187
+ * when the block is a single row). A block one cell tall gets a location of
188
+ * one cell, which is the common "a row of months, a sparkline beside it".
189
+ */
190
+ export function sparklinesFromRange(data, type = 'line') {
191
+ const [r1, c1, r2, c2] = data;
192
+ const alongARow = r2 === r1 && c2 > c1;
193
+ const location = alongARow
194
+ ? [r1, c2 + 1, r1, c2 + 1]
195
+ : [r1, c2 + 1, r2, c2 + 1];
196
+ return { id: sparklineId(), location, data: [r1, c1, r2, c2], type, markers: type === 'line' };
197
+ }
198
+ /** The groups left after clearing every one the rectangles touch. */
199
+ export function clearSparklines(groups, rects) {
200
+ return groups.filter((g) => !rects.some((rect) => overlaps(g.location, rect)));
201
+ }
202
+ function overlaps(a, b) {
203
+ return !(a[2] < b[0] || b[2] < a[0] || a[3] < b[1] || b[3] < a[1]);
204
+ }
@@ -0,0 +1,74 @@
1
+ /**
2
+ * The table styles gallery: Excel's presets, by the names Excel stores.
3
+ *
4
+ * A table's look is drawn rather than written into the cells, which is what
5
+ * lets a row typed under the last one arrive already banded. That drawing
6
+ * needs colours, and "the theme's accent" is one look rather than a gallery,
7
+ * so this is the set to pick from.
8
+ *
9
+ * The ids are Excel's own (`TableStyleMedium2`), and the colours are the
10
+ * Office theme's accents, so a table saved here opens in Excel wearing the
11
+ * same style rather than something approximate. A style is three tones of
12
+ * one accent: Light tints the header, Medium fills it, Dark fills it with a
13
+ * deeper shade, exactly as Excel's three families do.
14
+ */
15
+ export type TableStyleTone = 'light' | 'medium' | 'dark';
16
+ export type TableStyle = {
17
+ /** Excel's name for it, which is what goes in the file. */
18
+ id: string;
19
+ /** The colour's name, for the gallery. */
20
+ colour: string;
21
+ tone: TableStyleTone;
22
+ /** The Office theme accent it is built from. */
23
+ accent: string;
24
+ };
25
+ /**
26
+ * Eighteen styles: six accents in three tones. Excel numbers each family
27
+ * from 1, with 1 reserved for the black-and-white variant, so the accents
28
+ * start at 2 and this maps one for one onto the built-in names.
29
+ */
30
+ export declare const TABLE_STYLES: ReadonlyArray<TableStyle>;
31
+ /** What a table wears unless it is given something else: Excel's own default. */
32
+ export declare const DEFAULT_TABLE_STYLE = "TableStyleMedium2";
33
+ /** No style at all: the cells keep whatever formats they carry. */
34
+ export declare const NO_TABLE_STYLE = "None";
35
+ export declare function findTableStyle(id: string | undefined): TableStyle | undefined;
36
+ /**
37
+ * Black or white over a fill, whichever can be read.
38
+ *
39
+ * Excel paints a header's text white whatever the fill, which on its gold
40
+ * and sky accents is about 2:1: legible to some people, not to others, and
41
+ * flagged by every checker. Picking the readable one keeps Excel's colours
42
+ * and drops the part of Excel's behaviour that fails.
43
+ */
44
+ export declare function readableOn(fill: string): string;
45
+ /**
46
+ * The fill a filled header takes: the accent, darkened only when neither
47
+ * black nor white can be read on it.
48
+ *
49
+ * Mid grey is the one accent where that happens: white is 4.0 against it
50
+ * and near-black 4.3, so both sit under the 4.5 a checker asks for. A few
51
+ * steps darker keeps it recognisably the same grey and lets the white text
52
+ * clear it, which is a smaller lie than a header nobody can read.
53
+ */
54
+ export declare function headerFill(accent: string): string;
55
+ export type TableStyleColours = {
56
+ /** The header row's fill, and the colour its text needs to stay readable. */
57
+ header: string;
58
+ headerText: string;
59
+ /** Every other data row. */
60
+ band: string;
61
+ /** The totals row, and the line over it. */
62
+ totals: string;
63
+ border: string;
64
+ };
65
+ /**
66
+ * A style as CSS colours.
67
+ *
68
+ * `color-mix` rather than fixed hexes for the tints, so a table keeps its
69
+ * colour over a dark sheet as well as a light one: the accent is mixed with
70
+ * the surface underneath rather than painted over it.
71
+ */
72
+ export declare function tableStyleColours(style: TableStyle | string | undefined): TableStyleColours | null;
73
+ /** "Blue, Medium", for the gallery's tooltip and for a screen reader. */
74
+ export declare function tableStyleLabel(style: TableStyle): string;
@@ -0,0 +1,152 @@
1
+ /**
2
+ * The table styles gallery: Excel's presets, by the names Excel stores.
3
+ *
4
+ * A table's look is drawn rather than written into the cells, which is what
5
+ * lets a row typed under the last one arrive already banded. That drawing
6
+ * needs colours, and "the theme's accent" is one look rather than a gallery,
7
+ * so this is the set to pick from.
8
+ *
9
+ * The ids are Excel's own (`TableStyleMedium2`), and the colours are the
10
+ * Office theme's accents, so a table saved here opens in Excel wearing the
11
+ * same style rather than something approximate. A style is three tones of
12
+ * one accent: Light tints the header, Medium fills it, Dark fills it with a
13
+ * deeper shade, exactly as Excel's three families do.
14
+ */
15
+ /** The Office theme's six accents, in Excel's order. */
16
+ const ACCENTS = [
17
+ { name: 'Blue', hex: '#4472c4' },
18
+ { name: 'Orange', hex: '#ed7d31' },
19
+ { name: 'Grey', hex: '#7f7f7f' },
20
+ { name: 'Gold', hex: '#ffc000' },
21
+ { name: 'Sky', hex: '#5b9bd5' },
22
+ { name: 'Green', hex: '#70ad47' },
23
+ ];
24
+ const TONES = [
25
+ { tone: 'light', family: 'Light' },
26
+ { tone: 'medium', family: 'Medium' },
27
+ { tone: 'dark', family: 'Dark' },
28
+ ];
29
+ /**
30
+ * Eighteen styles: six accents in three tones. Excel numbers each family
31
+ * from 1, with 1 reserved for the black-and-white variant, so the accents
32
+ * start at 2 and this maps one for one onto the built-in names.
33
+ */
34
+ export const TABLE_STYLES = TONES.flatMap(({ tone, family }) => ACCENTS.map((accent, i) => ({
35
+ id: `TableStyle${family}${i + 2}`,
36
+ colour: accent.name,
37
+ tone,
38
+ accent: accent.hex,
39
+ })));
40
+ /** What a table wears unless it is given something else: Excel's own default. */
41
+ export const DEFAULT_TABLE_STYLE = 'TableStyleMedium2';
42
+ /** No style at all: the cells keep whatever formats they carry. */
43
+ export const NO_TABLE_STYLE = 'None';
44
+ export function findTableStyle(id) {
45
+ if (!id || id === NO_TABLE_STYLE)
46
+ return undefined;
47
+ return TABLE_STYLES.find((s) => s.id.toLowerCase() === id.toLowerCase());
48
+ }
49
+ /** A hex colour as its three channels, 0 to 255. */
50
+ function channels(hex) {
51
+ const value = hex.trim().replace('#', '');
52
+ const full = value.length === 3 ? value.split('').map((c) => c + c).join('') : value;
53
+ const n = Number.parseInt(full.slice(0, 6), 16);
54
+ return [(n >> 16) & 255, (n >> 8) & 255, n & 255];
55
+ }
56
+ /** Relative luminance, the way WCAG defines it. */
57
+ function luminance(hex) {
58
+ const [r, g, b] = channels(hex).map((c) => {
59
+ const s = c / 255;
60
+ return s <= 0.03928 ? s / 12.92 : ((s + 0.055) / 1.055) ** 2.4;
61
+ });
62
+ return 0.2126 * r + 0.7152 * g + 0.0722 * b;
63
+ }
64
+ function contrast(a, b) {
65
+ const [x, y] = [luminance(a), luminance(b)].sort((p, q) => q - p);
66
+ return (x + 0.05) / (y + 0.05);
67
+ }
68
+ /**
69
+ * Black or white over a fill, whichever can be read.
70
+ *
71
+ * Excel paints a header's text white whatever the fill, which on its gold
72
+ * and sky accents is about 2:1: legible to some people, not to others, and
73
+ * flagged by every checker. Picking the readable one keeps Excel's colours
74
+ * and drops the part of Excel's behaviour that fails.
75
+ */
76
+ export function readableOn(fill) {
77
+ const dark = '#0f172a';
78
+ const light = '#ffffff';
79
+ return contrast(fill, light) >= contrast(fill, dark) ? light : dark;
80
+ }
81
+ /**
82
+ * The fill a filled header takes: the accent, darkened only when neither
83
+ * black nor white can be read on it.
84
+ *
85
+ * Mid grey is the one accent where that happens: white is 4.0 against it
86
+ * and near-black 4.3, so both sit under the 4.5 a checker asks for. A few
87
+ * steps darker keeps it recognisably the same grey and lets the white text
88
+ * clear it, which is a smaller lie than a header nobody can read.
89
+ */
90
+ export function headerFill(accent) {
91
+ const best = Math.max(contrast(accent, '#ffffff'), contrast(accent, '#0f172a'));
92
+ if (best >= 4.5)
93
+ return accent;
94
+ for (let percent = 92; percent >= 60; percent -= 8) {
95
+ const darker = mixWithBlack(accent, percent);
96
+ if (contrast(darker, '#ffffff') >= 4.5)
97
+ return darker;
98
+ }
99
+ return mixWithBlack(accent, 60);
100
+ }
101
+ /** The colour a mix of an accent with black comes out as, for the dark tone. */
102
+ function mixWithBlack(hex, percent) {
103
+ const mixed = channels(hex).map((c) => Math.round((c * percent) / 100));
104
+ return `#${mixed.map((c) => c.toString(16).padStart(2, '0')).join('')}`;
105
+ }
106
+ /**
107
+ * A style as CSS colours.
108
+ *
109
+ * `color-mix` rather than fixed hexes for the tints, so a table keeps its
110
+ * colour over a dark sheet as well as a light one: the accent is mixed with
111
+ * the surface underneath rather than painted over it.
112
+ */
113
+ export function tableStyleColours(style) {
114
+ const found = typeof style === 'string' || style === undefined ? findTableStyle(style) : style;
115
+ if (!found)
116
+ return null;
117
+ const accent = found.accent;
118
+ const mix = (percent, into = 'transparent') => `color-mix(in srgb, ${accent} ${percent}%, ${into})`;
119
+ if (found.tone === 'light') {
120
+ return {
121
+ header: mix(18),
122
+ headerText: 'inherit',
123
+ band: mix(8),
124
+ totals: mix(14),
125
+ border: mix(50),
126
+ };
127
+ }
128
+ if (found.tone === 'dark') {
129
+ return {
130
+ header: `color-mix(in srgb, ${accent} 65%, #000)`,
131
+ headerText: readableOn(mixWithBlack(accent, 65)),
132
+ band: mix(22),
133
+ totals: mix(30),
134
+ border: mix(70),
135
+ };
136
+ }
137
+ const fill = headerFill(accent);
138
+ return {
139
+ header: fill,
140
+ // White where white can be read, near-black where it cannot: Excel's
141
+ // gold and sky headers are about 2:1 against white.
142
+ headerText: readableOn(fill),
143
+ band: mix(13),
144
+ totals: mix(20),
145
+ border: mix(55),
146
+ };
147
+ }
148
+ /** "Blue, Medium", for the gallery's tooltip and for a screen reader. */
149
+ export function tableStyleLabel(style) {
150
+ const tone = style.tone === 'light' ? 'Light' : style.tone === 'dark' ? 'Dark' : 'Medium';
151
+ return `${style.colour}, ${tone}`;
152
+ }
@@ -14,6 +14,7 @@
14
14
  * the range depends on the table's size at that moment rather than at parse
15
15
  * time.
16
16
  */
17
+ import type { StructuralEdit } from './refs.js';
17
18
  export type TableRegion = {
18
19
  name: string;
19
20
  sheet: string;
@@ -26,6 +27,12 @@ export type TableRegion = {
26
27
  lastRow: number;
27
28
  /** Whether the row after `lastRow` is a totals row. */
28
29
  hasTotals: boolean;
30
+ /**
31
+ * The look, by Excel's name for it (`TableStyleMedium2`), or `'None'` for
32
+ * cells that keep whatever formats they carry. Absent means the default,
33
+ * which is Excel's default too.
34
+ */
35
+ style?: string;
29
36
  };
30
37
  /** Which part of a table a structured reference asks for. */
31
38
  export type TableSpecifier = '#All' | '#Data' | '#Headers' | '#Totals' | '#ThisRow';
@@ -68,3 +75,15 @@ export declare function resolveTableRange(table: TableRegion, specifier: TableSp
68
75
  } | null, currentRow: number | null): TableRange | null;
69
76
  /** How many data rows a table holds. */
70
77
  export declare function rowCountOf(table: TableRegion): number;
78
+ /**
79
+ * A table after an insert or delete on its own sheet: its header row, its
80
+ * columns and its last row move with the cells. Null when the edit took the
81
+ * header row, or every column, which is what deleting a table looks like.
82
+ *
83
+ * A totals row sits on `lastRow + 1`, so it moves with the rest; an insert
84
+ * INSIDE the table grows it, which is what Excel does when a row is added
85
+ * in the middle of one.
86
+ */
87
+ export declare function shiftTable(table: TableRegion, sheet: string, edit: StructuralEdit): TableRegion | null;
88
+ /** Every table after an edit, the gone ones dropped. */
89
+ export declare function shiftTables(tables: ReadonlyArray<TableRegion>, sheet: string, edit: StructuralEdit): TableRegion[];
@@ -14,6 +14,7 @@
14
14
  * the range depends on the table's size at that moment rather than at parse
15
15
  * time.
16
16
  */
17
+ import { shiftRect } from './rects.js';
17
18
  /** Excel's rules for a table name are the same as for a defined name. */
18
19
  export function isValidTableName(name) {
19
20
  if (!/^[A-Za-z_][A-Za-z0-9_.]*$/.test(name))
@@ -145,3 +146,33 @@ export function resolveTableRange(table, specifier, columns, currentRow) {
145
146
  export function rowCountOf(table) {
146
147
  return Math.max(0, table.lastRow - table.headerRow);
147
148
  }
149
+ /**
150
+ * A table after an insert or delete on its own sheet: its header row, its
151
+ * columns and its last row move with the cells. Null when the edit took the
152
+ * header row, or every column, which is what deleting a table looks like.
153
+ *
154
+ * A totals row sits on `lastRow + 1`, so it moves with the rest; an insert
155
+ * INSIDE the table grows it, which is what Excel does when a row is added
156
+ * in the middle of one.
157
+ */
158
+ export function shiftTable(table, sheet, edit) {
159
+ if (table.sheet.toLowerCase() !== sheet.toLowerCase())
160
+ return table;
161
+ const rows = edit.kind === 'insertRows' || edit.kind === 'deleteRows';
162
+ const rect = rows
163
+ ? [table.headerRow, table.firstCol, table.lastRow + (table.hasTotals ? 1 : 0), table.lastCol]
164
+ : [table.headerRow, table.firstCol, table.lastRow + (table.hasTotals ? 1 : 0), table.lastCol];
165
+ const moved = shiftRect(rect, edit);
166
+ if (!moved)
167
+ return null;
168
+ const [r1, c1, r2, c2] = moved;
169
+ // A table with no data rows left is gone, as is one whose header went.
170
+ const lastRow = r2 - (table.hasTotals ? 1 : 0);
171
+ if (lastRow < r1 + 1)
172
+ return null;
173
+ return { ...table, headerRow: r1, firstCol: c1, lastCol: c2, lastRow };
174
+ }
175
+ /** Every table after an edit, the gone ones dropped. */
176
+ export function shiftTables(tables, sheet, edit) {
177
+ return tables.map((t) => shiftTable(t, sheet, edit)).filter((t) => t !== null);
178
+ }
@@ -11,7 +11,7 @@
11
11
  * is what keeps absolute references absolute.
12
12
  */
13
13
  import { type CellRef } from './address.js';
14
- import { type BinaryOp } from './ast.js';
14
+ import { type BinaryOp, type SheetError } from './ast.js';
15
15
  export type TableRefToken = {
16
16
  t: 'table';
17
17
  table: string | null;
@@ -28,13 +28,30 @@ export type Token = TableRefToken | {
28
28
  } | {
29
29
  t: 'bool';
30
30
  v: boolean;
31
+ } | {
32
+ t: 'err';
33
+ v: SheetError;
31
34
  } | {
32
35
  t: 'ref';
33
36
  ref: CellRef;
37
+ }
38
+ /** The spilled-range operator `A1#`: the anchor a spill is read from. */
39
+ | {
40
+ t: 'spill';
41
+ ref: CellRef;
34
42
  } | {
35
43
  t: 'range';
36
44
  from: CellRef;
37
45
  to: CellRef;
46
+ }
47
+ /** A 3D reference `Sheet1:Sheet3!A1`: the cell or rectangle on every sheet
48
+ * in the tab range. `from`/`to` carry no sheet of their own. */
49
+ | {
50
+ t: 'range3d';
51
+ sheetFrom: string;
52
+ sheetTo: string;
53
+ from: CellRef;
54
+ to: CellRef;
38
55
  } | {
39
56
  t: 'name';
40
57
  v: string;
@@ -20,6 +20,9 @@ const SPECIFIERS = {
20
20
  '#totals': '#Totals',
21
21
  '#this row': '#ThisRow',
22
22
  };
23
+ /** The error values a formula can name, longest first so #NUM! cannot win
24
+ * the prefix of a longer code. */
25
+ const ERROR_LITERAL = /^(#NULL!|#DIV\/0!|#VALUE!|#NAME\?|#NUM!|#N\/A|#REF!|#SPILL!|#CALC!|#CYCLE!)/i;
23
26
  const TWO_CHAR_OPS = new Set(['<=', '>=', '<>']);
24
27
  const ONE_CHAR_OPS = '+-*/^%&=<>';
25
28
  export function tokenize(src) {
@@ -161,6 +164,15 @@ export function tokenize(src) {
161
164
  out.push({ t: 'name', v: word });
162
165
  return;
163
166
  }
167
+ // `A1#` is the spilled-range operator: the `#` binds to the reference
168
+ // right before it, with no space between, and names the whole array the
169
+ // cell anchors. A `#` that starts an error literal is handled elsewhere;
170
+ // one sitting immediately after a cell is only ever this.
171
+ if (src[i] === '#') {
172
+ i += 1;
173
+ out.push({ t: 'spill', ref: left });
174
+ return;
175
+ }
164
176
  out.push({ t: 'ref', ref: left });
165
177
  };
166
178
  while (i < src.length) {
@@ -252,34 +264,73 @@ export function tokenize(src) {
252
264
  if (/[A-Za-z$_]/.test(ch)) {
253
265
  const word = readWord();
254
266
  const upper = word.toUpperCase();
267
+ // A 3D reference: Sheet1:Sheet3!A1, the same cell on every sheet in the
268
+ // tab range. The `!` after the second name is what tells it apart from
269
+ // an ordinary A1:B2 range, so on anything else this backtracks.
270
+ if (src[i] === ':') {
271
+ const save = i;
272
+ i += 1;
273
+ const second = readWord();
274
+ if (second !== '' && src[i] === '!') {
275
+ i += 1;
276
+ const from = parseA1(readWord(), null);
277
+ if (!from || from.row === null)
278
+ throw new FormulaError('#PARSE!');
279
+ let to = from;
280
+ if (src[i] === ':') {
281
+ i += 1;
282
+ const right = parseA1(readWord(), null);
283
+ if (!right || right.row === null)
284
+ throw new FormulaError('#PARSE!');
285
+ to = right;
286
+ }
287
+ out.push({ t: 'range3d', sheetFrom: word, sheetTo: second, from, to });
288
+ continue;
289
+ }
290
+ i = save;
291
+ }
255
292
  // Unquoted sheet name: Orders!A1
256
293
  if (src[i] === '!') {
257
294
  i += 1;
258
295
  pushWord(readWord(), word);
259
296
  continue;
260
297
  }
261
- if (upper === 'TRUE') {
262
- out.push({ t: 'bool', v: true });
263
- continue;
264
- }
265
- if (upper === 'FALSE') {
266
- out.push({ t: 'bool', v: false });
267
- continue;
268
- }
269
298
  // A word followed by `[` is a table: Orders[Amount].
270
299
  if (src[i] === '[') {
271
300
  i += 1;
272
301
  out.push(readTableBracket(word));
273
302
  continue;
274
303
  }
275
- // A word followed by `(` is a call, whatever else it might look like.
304
+ // A word followed by `(` is a call, whatever else it might look like -
305
+ // TRUE and FALSE included, since Excel has TRUE() and FALSE() as
306
+ // functions and that is how LibreOffice writes a boolean cell.
276
307
  if (src[skipSpace()] === '(') {
277
308
  out.push({ t: 'fn', v: upper });
278
309
  continue;
279
310
  }
311
+ if (upper === 'TRUE') {
312
+ out.push({ t: 'bool', v: true });
313
+ continue;
314
+ }
315
+ if (upper === 'FALSE') {
316
+ out.push({ t: 'bool', v: false });
317
+ continue;
318
+ }
280
319
  pushWord(word, null);
281
320
  continue;
282
321
  }
322
+ // An error written into the formula: =#N/A, =IFERROR(A1, #REF!). Excel
323
+ // reads one as a value, and a file can carry an error cell as a formula
324
+ // that is nothing else.
325
+ if (ch === '#') {
326
+ const code = ERROR_LITERAL.exec(src.slice(i));
327
+ if (code) {
328
+ out.push({ t: 'err', v: code[0].toUpperCase() });
329
+ i += code[0].length;
330
+ continue;
331
+ }
332
+ throw new FormulaError('#PARSE!');
333
+ }
283
334
  // A bare `[` is the unqualified form, which only means something in a
284
335
  // formula sitting inside a table: [@Amount].
285
336
  if (ch === '[') {
@@ -37,6 +37,12 @@ export type ValidationRule = {
37
37
  title?: string;
38
38
  message?: string;
39
39
  };
40
+ /** Excel's Input Message: shown under the cell while it is selected.
41
+ * Absent when the rule has none. */
42
+ input?: {
43
+ title?: string;
44
+ message?: string;
45
+ };
40
46
  };
41
47
  /** How a rule reads the sheet: the shell wires the workbook in. */
42
48
  export type ValidationContext = {
@@ -90,3 +96,13 @@ export declare function shiftValidation(rules: ReadonlyArray<ValidationRule>, ed
90
96
  export declare function removeValidation(rules: ReadonlyArray<ValidationRule>, rects: ReadonlyArray<Rect>): ValidationRule[];
91
97
  /** A short description for a rule, the way Excel's dialog title reads it. */
92
98
  export declare function describeRule(rule: ValidationRule): string;
99
+ /**
100
+ * Excel's Circle Invalid Data: every cell under a rule whose current text
101
+ * breaks it. Blank cells count when the rule says they do. The rectangles
102
+ * are clipped to `rows` by `cols`, the sheet's used extent, so a rule over
103
+ * a whole column costs the cells that hold something.
104
+ */
105
+ export declare function invalidCells(rules: ReadonlyArray<ValidationRule>, ctx: ValidationContext, rawAt: (row: number, col: number) => string, rows: number, cols: number): Array<{
106
+ row: number;
107
+ col: number;
108
+ }>;