@svgrid/enterprise 3.0.1 → 3.0.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (445) hide show
  1. package/LICENSE +94 -24
  2. package/README.md +36 -4
  3. package/dist/SvAdvancedFilter.svelte +1 -1
  4. package/dist/SvAlertsManager.svelte +2 -1
  5. package/dist/SvBoard.svelte +2 -1
  6. package/dist/SvExportMenu.svelte +4 -1
  7. package/dist/SvExportMenu.svelte.d.ts +0 -13
  8. package/dist/SvExpressionEditor.svelte +3 -3
  9. package/dist/SvFormulaBar.svelte +680 -0
  10. package/dist/SvFormulaBar.svelte.d.ts +69 -0
  11. package/dist/SvGridAlerts.svelte +49 -9
  12. package/dist/SvGridBoard.svelte +13 -8
  13. package/dist/SvGridBulkEditDrawer.svelte +26 -2
  14. package/dist/SvGridEditPanel.svelte +3 -0
  15. package/dist/SvGridScheduler.svelte +69 -40
  16. package/dist/SvGridSelectionBar.svelte +10 -3
  17. package/dist/SvPivotDesigner.svelte +263 -54
  18. package/dist/SvPivotDesigner.svelte.d.ts +27 -20
  19. package/dist/SvRibbonIcon.svelte +46 -0
  20. package/dist/SvRibbonIcon.svelte.d.ts +17 -0
  21. package/dist/SvSchemaChart.svelte +4 -2
  22. package/dist/SvSheet.svelte +7914 -0
  23. package/dist/SvSheet.svelte.d.ts +215 -0
  24. package/dist/SvSheetChartSetup.svelte +151 -0
  25. package/dist/SvSheetChartSetup.svelte.d.ts +18 -0
  26. package/dist/SvSheetComment.svelte +283 -0
  27. package/dist/SvSheetComment.svelte.d.ts +22 -0
  28. package/dist/SvSheetConditionalFormat.svelte +159 -0
  29. package/dist/SvSheetConditionalFormat.svelte.d.ts +14 -0
  30. package/dist/SvSheetDataValidation.svelte +273 -0
  31. package/dist/SvSheetDataValidation.svelte.d.ts +14 -0
  32. package/dist/SvSheetEditRanges.svelte +217 -0
  33. package/dist/SvSheetEditRanges.svelte.d.ts +15 -0
  34. package/dist/SvSheetErrors.svelte +125 -0
  35. package/dist/SvSheetErrors.svelte.d.ts +20 -0
  36. package/dist/SvSheetEvaluate.svelte +133 -0
  37. package/dist/SvSheetEvaluate.svelte.d.ts +15 -0
  38. package/dist/SvSheetFilterMenu.svelte +320 -0
  39. package/dist/SvSheetFilterMenu.svelte.d.ts +22 -0
  40. package/dist/SvSheetFindReplace.svelte +132 -0
  41. package/dist/SvSheetFindReplace.svelte.d.ts +10 -0
  42. package/dist/SvSheetFormatCells.svelte +465 -0
  43. package/dist/SvSheetFormatCells.svelte.d.ts +17 -0
  44. package/dist/SvSheetGoalSeek.svelte +145 -0
  45. package/dist/SvSheetGoalSeek.svelte.d.ts +12 -0
  46. package/dist/SvSheetInsertFunction.svelte +149 -0
  47. package/dist/SvSheetInsertFunction.svelte.d.ts +8 -0
  48. package/dist/SvSheetIteration.svelte +81 -0
  49. package/dist/SvSheetIteration.svelte.d.ts +10 -0
  50. package/dist/SvSheetLink.svelte +99 -0
  51. package/dist/SvSheetLink.svelte.d.ts +17 -0
  52. package/dist/SvSheetListPicker.svelte +91 -0
  53. package/dist/SvSheetListPicker.svelte.d.ts +10 -0
  54. package/dist/SvSheetManageRules.svelte +187 -0
  55. package/dist/SvSheetManageRules.svelte.d.ts +16 -0
  56. package/dist/SvSheetNameManager.svelte +227 -0
  57. package/dist/SvSheetNameManager.svelte.d.ts +11 -0
  58. package/dist/SvSheetPageSetup.svelte +159 -0
  59. package/dist/SvSheetPageSetup.svelte.d.ts +13 -0
  60. package/dist/SvSheetPasteSpecial.svelte +107 -0
  61. package/dist/SvSheetPasteSpecial.svelte.d.ts +12 -0
  62. package/dist/SvSheetPivot.svelte +220 -0
  63. package/dist/SvSheetPivot.svelte.d.ts +21 -0
  64. package/dist/SvSheetProtectSheet.svelte +81 -0
  65. package/dist/SvSheetProtectSheet.svelte.d.ts +11 -0
  66. package/dist/SvSheetRemoveDuplicates.svelte +152 -0
  67. package/dist/SvSheetRemoveDuplicates.svelte.d.ts +12 -0
  68. package/dist/SvSheetRibbon.svelte +1254 -0
  69. package/dist/SvSheetRibbon.svelte.d.ts +34 -0
  70. package/dist/SvSheetSizeDialog.svelte +60 -0
  71. package/dist/SvSheetSizeDialog.svelte.d.ts +11 -0
  72. package/dist/SvSheetSort.svelte +218 -0
  73. package/dist/SvSheetSort.svelte.d.ts +28 -0
  74. package/dist/SvSheetSparklines.svelte +135 -0
  75. package/dist/SvSheetSparklines.svelte.d.ts +14 -0
  76. package/dist/SvSheetTable.svelte +160 -0
  77. package/dist/SvSheetTable.svelte.d.ts +24 -0
  78. package/dist/SvSheetTabs.svelte +571 -0
  79. package/dist/SvSheetTabs.svelte.d.ts +50 -0
  80. package/dist/SvSheetTabs.test-harness.svelte.d.ts +17 -0
  81. package/dist/SvSheetTabs.test-harness.svelte.js +22 -0
  82. package/dist/SvSheetTextToColumns.svelte +172 -0
  83. package/dist/SvSheetTextToColumns.svelte.d.ts +13 -0
  84. package/dist/SvSheetValidationAlert.svelte +85 -0
  85. package/dist/SvSheetValidationAlert.svelte.d.ts +15 -0
  86. package/dist/advanced-filter-enable.js +1 -1
  87. package/dist/alerts/alert-engine.d.ts +6 -0
  88. package/dist/alerts/alert-engine.js +21 -4
  89. package/dist/alerts/alert-formats.js +2 -0
  90. package/dist/alerts/alert-types.d.ts +1 -1
  91. package/dist/alerts.d.ts +1 -1
  92. package/dist/alerts.js +2 -2
  93. package/dist/board.js +2 -2
  94. package/dist/bulk-edit.d.ts +3 -1
  95. package/dist/bulk-edit.js +1 -1
  96. package/dist/cdn/svgrid-enterprise.svelte-external.js +43538 -6539
  97. package/dist/designer/assets/GridMenus-8gTNssgV.js +8 -0
  98. package/dist/designer/assets/SvChartMenu-BDoeqGz6.js +1 -0
  99. package/dist/designer/assets/SvChartMenu-BYO9cYdy.css +1 -0
  100. package/dist/designer/assets/SvDateRangeInput-BBRzrQeg.js +1 -0
  101. package/dist/designer/assets/SvDateTimePicker-DCPg7WGN.js +1 -0
  102. package/dist/designer/assets/SvGridCellEditor-DMoWJjEI.js +4 -0
  103. package/dist/designer/assets/SvGridChart-BgLuPO7I.css +1 -0
  104. package/dist/designer/assets/SvGridChart-Cy1ATrWh.js +3 -0
  105. package/dist/designer/assets/SvGridChartBuilder-08YWWeqY.css +1 -0
  106. package/dist/designer/assets/SvGridChartBuilder-eQ3mn0L9.js +1 -0
  107. package/dist/designer/assets/SvGridChartPanel-4Pc8y5yO.css +1 -0
  108. package/dist/designer/assets/SvGridChartPanel-CATdVc9X.js +4 -0
  109. package/dist/designer/assets/{SvGridChartView-DUc-1RUf.css → SvGridChartView-7msfnWZT.css} +1 -1
  110. package/dist/designer/assets/SvGridChartView-CmsZtCED.js +1 -0
  111. package/dist/designer/assets/SvGridDropdown-Cjz0H-fI.js +1 -0
  112. package/dist/designer/assets/SvListBox-BDS66lmZ.js +110 -0
  113. package/dist/designer/assets/SvMenuList-DJ47ba1h.css +1 -0
  114. package/dist/designer/assets/SvMenuList-Dgq2D5VN.js +1 -0
  115. package/dist/designer/assets/SvTabs-2mHC6oaz.js +1 -0
  116. package/dist/designer/assets/SvTabs-DKmwb5p1.css +1 -0
  117. package/dist/designer/assets/cell-formatting-BbubJTVz.js +1 -0
  118. package/dist/designer/assets/chart-Cn7MnNqA.js +1 -0
  119. package/dist/designer/assets/chart-export-B6bkQ3X8.js +11 -0
  120. package/dist/designer/assets/chart-export-pdf-BbA28-gt.js +11 -0
  121. package/dist/designer/assets/chart-panel-messages-Dz7PTIqT.js +1 -0
  122. package/dist/designer/assets/chart-summary-BD1qYB2R.js +1 -0
  123. package/dist/designer/assets/chart-trend-B8xr5LuD.js +1 -0
  124. package/dist/designer/assets/chart-validate-BMqM-qkF.js +1 -0
  125. package/dist/designer/assets/column-resize-BYDzR1Ve.js +1 -0
  126. package/dist/designer/assets/date-format-B8JbEtIG.js +1 -0
  127. package/dist/designer/assets/date-format-DKS-z0xS.css +1 -0
  128. package/dist/designer/assets/{dismissable-BO547MH9.js → dismissable-ChWRPkoa.js} +1 -1
  129. package/dist/designer/assets/editor-contract-Bpoa7A5g.js +1 -0
  130. package/dist/designer/assets/{export-format-D-eP4b2l.js → export-format-DGckmgKr.js} +1 -1
  131. package/dist/designer/assets/focus-trap-V2-6Fy9I.js +1 -0
  132. package/dist/designer/assets/{index-C_a9Cj8Y.js → index-D5bVbuzI.js} +318 -315
  133. package/dist/designer/assets/index-_JVFxt02.css +1 -0
  134. package/dist/designer/assets/list-option-BP_dWS66.js +1 -0
  135. package/dist/designer/assets/row-resize-BInFWCpr.js +1 -0
  136. package/dist/designer/assets/server-block-cache-CXJKkJpy.js +1 -0
  137. package/dist/designer/assets/src-CITpcm6b.js +1 -0
  138. package/dist/designer/assets/src-DUQ4xE3x.js +58 -0
  139. package/dist/designer/assets/validate-C3B8QKsM.js +1 -0
  140. package/dist/designer/index.html +29 -19
  141. package/dist/export-pdf.d.ts +164 -0
  142. package/dist/export-pdf.js +346 -15
  143. package/dist/export.js +25 -10
  144. package/dist/gantt/SvGridGantt.svelte +2890 -0
  145. package/dist/gantt/SvGridGantt.svelte.d.ts +30 -0
  146. package/dist/gantt/gantt-config.d.ts +73 -0
  147. package/dist/gantt/gantt-config.js +1 -0
  148. package/dist/gantt/gantt-critical-path.d.ts +67 -0
  149. package/dist/gantt/gantt-critical-path.js +207 -0
  150. package/dist/gantt/gantt-model.d.ts +257 -0
  151. package/dist/gantt/gantt-model.js +651 -0
  152. package/dist/gantt/gantt-resources.d.ts +59 -0
  153. package/dist/gantt/gantt-resources.js +71 -0
  154. package/dist/gantt/gantt.d.ts +7 -0
  155. package/dist/gantt/gantt.js +36 -0
  156. package/dist/gantt/index.d.ts +15 -0
  157. package/dist/gantt/index.js +22 -0
  158. package/dist/gantt/timeline-arrows.d.ts +102 -0
  159. package/dist/gantt/timeline-arrows.js +181 -0
  160. package/dist/import.d.ts +2 -2
  161. package/dist/import.js +1 -1
  162. package/dist/index.d.ts +93 -3
  163. package/dist/index.js +107 -3
  164. package/dist/install.js +13 -1
  165. package/dist/license-core.d.ts +17 -1
  166. package/dist/license-core.js +16 -5
  167. package/dist/license.d.ts +18 -2
  168. package/dist/license.js +71 -6
  169. package/dist/node/studio.js +203 -9
  170. package/dist/pivot-chart.d.ts +25 -1
  171. package/dist/pivot-chart.js +25 -69
  172. package/dist/pivot-enable.js +2 -2
  173. package/dist/scheduler-dependencies.d.ts +35 -0
  174. package/dist/scheduler-dependencies.js +36 -1
  175. package/dist/scheduler.js +2 -2
  176. package/dist/selection-bar.js +2 -2
  177. package/dist/server/SvGroupCell.svelte +213 -0
  178. package/dist/server/SvGroupCell.svelte.d.ts +62 -0
  179. package/dist/server/SvRowGroupPanel.svelte +322 -0
  180. package/dist/server/SvRowGroupPanel.svelte.d.ts +37 -0
  181. package/dist/server/enable.d.ts +17 -0
  182. package/dist/server/enable.js +49 -0
  183. package/dist/server/index.d.ts +22 -0
  184. package/dist/server/index.js +24 -0
  185. package/dist/server/messages.d.ts +45 -0
  186. package/dist/server/messages.js +35 -0
  187. package/dist/server/server-group-model.d.ts +104 -0
  188. package/dist/server/server-group-model.js +272 -0
  189. package/dist/server/server-pivot.d.ts +46 -0
  190. package/dist/server/server-pivot.js +57 -0
  191. package/dist/server/server-row-model.d.ts +547 -0
  192. package/dist/server/server-row-model.js +1551 -0
  193. package/dist/server/server-selection.d.ts +99 -0
  194. package/dist/server/server-selection.js +215 -0
  195. package/dist/server/svgrid-adapter.d.ts +155 -0
  196. package/dist/server/svgrid-adapter.js +202 -0
  197. package/dist/sheet/address.d.ts +43 -0
  198. package/dist/sheet/address.js +81 -0
  199. package/dist/sheet/ast.d.ts +138 -0
  200. package/dist/sheet/ast.js +70 -0
  201. package/dist/sheet/auto-filter.d.ts +120 -0
  202. package/dist/sheet/auto-filter.js +295 -0
  203. package/dist/sheet/autocomplete.d.ts +51 -0
  204. package/dist/sheet/autocomplete.js +248 -0
  205. package/dist/sheet/cell-images.d.ts +39 -0
  206. package/dist/sheet/cell-images.js +90 -0
  207. package/dist/sheet/cell-types.d.ts +58 -0
  208. package/dist/sheet/cell-types.js +96 -0
  209. package/dist/sheet/coerce.d.ts +71 -0
  210. package/dist/sheet/coerce.js +289 -0
  211. package/dist/sheet/commands.d.ts +89 -0
  212. package/dist/sheet/commands.js +230 -0
  213. package/dist/sheet/comments.d.ts +63 -0
  214. package/dist/sheet/comments.js +131 -0
  215. package/dist/sheet/conditional-formats.d.ts +167 -0
  216. package/dist/sheet/conditional-formats.js +341 -0
  217. package/dist/sheet/csv.d.ts +32 -0
  218. package/dist/sheet/csv.js +158 -0
  219. package/dist/sheet/culture.d.ts +87 -0
  220. package/dist/sheet/culture.js +247 -0
  221. package/dist/sheet/delta.d.ts +102 -0
  222. package/dist/sheet/delta.js +203 -0
  223. package/dist/sheet/deps.d.ts +104 -0
  224. package/dist/sheet/deps.js +274 -0
  225. package/dist/sheet/document.d.ts +252 -0
  226. package/dist/sheet/document.js +465 -0
  227. package/dist/sheet/edit-keys.d.ts +14 -0
  228. package/dist/sheet/edit-keys.js +40 -0
  229. package/dist/sheet/engine.d.ts +67 -0
  230. package/dist/sheet/engine.js +19 -0
  231. package/dist/sheet/entry.d.ts +35 -0
  232. package/dist/sheet/entry.js +226 -0
  233. package/dist/sheet/error-check.d.ts +49 -0
  234. package/dist/sheet/error-check.js +83 -0
  235. package/dist/sheet/evaluate-steps.d.ts +48 -0
  236. package/dist/sheet/evaluate-steps.js +196 -0
  237. package/dist/sheet/evaluate.d.ts +128 -0
  238. package/dist/sheet/evaluate.js +1049 -0
  239. package/dist/sheet/filter-files.d.ts +37 -0
  240. package/dist/sheet/filter-files.js +465 -0
  241. package/dist/sheet/find-replace.d.ts +62 -0
  242. package/dist/sheet/find-replace.js +152 -0
  243. package/dist/sheet/format-store.d.ts +114 -0
  244. package/dist/sheet/format-store.js +243 -0
  245. package/dist/sheet/freeze.d.ts +54 -0
  246. package/dist/sheet/freeze.js +58 -0
  247. package/dist/sheet/from-rows.d.ts +14 -0
  248. package/dist/sheet/from-rows.js +50 -0
  249. package/dist/sheet/function-catalog.d.ts +10 -0
  250. package/dist/sheet/function-catalog.js +385 -0
  251. package/dist/sheet/functions.d.ts +28 -0
  252. package/dist/sheet/functions.js +634 -0
  253. package/dist/sheet/goal-seek.d.ts +73 -0
  254. package/dist/sheet/goal-seek.js +153 -0
  255. package/dist/sheet/index.d.ts +80 -0
  256. package/dist/sheet/index.js +80 -0
  257. package/dist/sheet/links.d.ts +57 -0
  258. package/dist/sheet/links.js +174 -0
  259. package/dist/sheet/merges.d.ts +71 -0
  260. package/dist/sheet/merges.js +137 -0
  261. package/dist/sheet/messages.d.ts +778 -0
  262. package/dist/sheet/messages.js +806 -0
  263. package/dist/sheet/names.d.ts +31 -0
  264. package/dist/sheet/names.js +87 -0
  265. package/dist/sheet/navigate.d.ts +52 -0
  266. package/dist/sheet/navigate.js +135 -0
  267. package/dist/sheet/number-format.d.ts +110 -0
  268. package/dist/sheet/number-format.js +905 -0
  269. package/dist/sheet/objects.d.ts +106 -0
  270. package/dist/sheet/objects.js +149 -0
  271. package/dist/sheet/ods-document.d.ts +44 -0
  272. package/dist/sheet/ods-document.js +1275 -0
  273. package/dist/sheet/open-file.d.ts +26 -0
  274. package/dist/sheet/open-file.js +56 -0
  275. package/dist/sheet/outline.d.ts +82 -0
  276. package/dist/sheet/outline.js +228 -0
  277. package/dist/sheet/packs/array.d.ts +16 -0
  278. package/dist/sheet/packs/array.js +172 -0
  279. package/dist/sheet/packs/database.d.ts +42 -0
  280. package/dist/sheet/packs/database.js +142 -0
  281. package/dist/sheet/packs/engineering.d.ts +2 -0
  282. package/dist/sheet/packs/engineering.js +296 -0
  283. package/dist/sheet/packs/financial.d.ts +5 -0
  284. package/dist/sheet/packs/financial.js +220 -0
  285. package/dist/sheet/packs/math-stats.d.ts +2 -0
  286. package/dist/sheet/packs/math-stats.js +372 -0
  287. package/dist/sheet/packs/special.d.ts +44 -0
  288. package/dist/sheet/packs/special.js +187 -0
  289. package/dist/sheet/packs/stats-dist.d.ts +2 -0
  290. package/dist/sheet/packs/stats-dist.js +785 -0
  291. package/dist/sheet/packs/text-date.d.ts +2 -0
  292. package/dist/sheet/packs/text-date.js +332 -0
  293. package/dist/sheet/packs/trig.d.ts +2 -0
  294. package/dist/sheet/packs/trig.js +73 -0
  295. package/dist/sheet/page-setup.d.ts +73 -0
  296. package/dist/sheet/page-setup.js +73 -0
  297. package/dist/sheet/palette.d.ts +19 -0
  298. package/dist/sheet/palette.js +84 -0
  299. package/dist/sheet/parse.d.ts +13 -0
  300. package/dist/sheet/parse.js +140 -0
  301. package/dist/sheet/paste-special.d.ts +186 -0
  302. package/dist/sheet/paste-special.js +601 -0
  303. package/dist/sheet/pivot-range.d.ts +160 -0
  304. package/dist/sheet/pivot-range.js +333 -0
  305. package/dist/sheet/presence.d.ts +73 -0
  306. package/dist/sheet/presence.js +79 -0
  307. package/dist/sheet/print.d.ts +104 -0
  308. package/dist/sheet/print.js +169 -0
  309. package/dist/sheet/protection.d.ts +75 -0
  310. package/dist/sheet/protection.js +101 -0
  311. package/dist/sheet/rects.d.ts +45 -0
  312. package/dist/sheet/rects.js +112 -0
  313. package/dist/sheet/refs.d.ts +130 -0
  314. package/dist/sheet/refs.js +413 -0
  315. package/dist/sheet/ribbon-icons.d.ts +31 -0
  316. package/dist/sheet/ribbon-icons.js +536 -0
  317. package/dist/sheet/ribbon.d.ts +173 -0
  318. package/dist/sheet/ribbon.js +1054 -0
  319. package/dist/sheet/sheet-kinds.d.ts +74 -0
  320. package/dist/sheet/sheet-kinds.js +91 -0
  321. package/dist/sheet/shortcuts.d.ts +174 -0
  322. package/dist/sheet/shortcuts.js +674 -0
  323. package/dist/sheet/sort.d.ts +51 -0
  324. package/dist/sheet/sort.js +107 -0
  325. package/dist/sheet/sparklines.d.ts +111 -0
  326. package/dist/sheet/sparklines.js +204 -0
  327. package/dist/sheet/structure.d.ts +87 -0
  328. package/dist/sheet/structure.js +166 -0
  329. package/dist/sheet/table-styles.d.ts +74 -0
  330. package/dist/sheet/table-styles.js +152 -0
  331. package/dist/sheet/tables.d.ts +89 -0
  332. package/dist/sheet/tables.js +178 -0
  333. package/dist/sheet/tokenize.d.ts +71 -0
  334. package/dist/sheet/tokenize.js +355 -0
  335. package/dist/sheet/transforms.d.ts +76 -0
  336. package/dist/sheet/transforms.js +154 -0
  337. package/dist/sheet/validation.d.ts +108 -0
  338. package/dist/sheet/validation.js +278 -0
  339. package/dist/sheet/workbook.d.ts +217 -0
  340. package/dist/sheet/workbook.js +1120 -0
  341. package/dist/sheet/xls-cfb.d.ts +32 -0
  342. package/dist/sheet/xls-cfb.js +290 -0
  343. package/dist/sheet/xls-document.d.ts +10 -0
  344. package/dist/sheet/xls-document.js +1243 -0
  345. package/dist/sheet/xls-formula.d.ts +40 -0
  346. package/dist/sheet/xls-formula.js +569 -0
  347. package/dist/sheet/xlsx-document.d.ts +108 -0
  348. package/dist/sheet/xlsx-document.js +1849 -0
  349. package/dist/sheet/xlsx-drawing.d.ts +99 -0
  350. package/dist/sheet/xlsx-drawing.js +420 -0
  351. package/dist/sheet-enable.d.ts +6 -0
  352. package/dist/sheet-enable.js +45 -0
  353. package/dist/sheet-text.d.ts +7 -0
  354. package/dist/sheet-text.js +29 -0
  355. package/dist/sources/auth-supabase.js +2 -2
  356. package/dist/sources/realtime-supabase.js +2 -2
  357. package/dist/sources/rest.d.ts +6 -2
  358. package/dist/sources/rest.js +42 -7
  359. package/dist/sources/supabase.d.ts +10 -1
  360. package/dist/sources/supabase.js +73 -40
  361. package/dist/studio/emit-project.js +14 -1
  362. package/dist/studio/index.js +1 -1
  363. package/dist/studio/project.d.ts +11 -2
  364. package/dist/studio/project.js +5 -2
  365. package/dist/studio/ui-components.generated.js +170 -3
  366. package/dist/sveltekit/in-memory.d.ts +2 -2
  367. package/dist/sveltekit/in-memory.js +125 -4
  368. package/dist/sveltekit/index.d.ts +1 -1
  369. package/dist/sveltekit/index.js +1 -1
  370. package/dist/sveltekit/query-plan.d.ts +50 -4
  371. package/dist/sveltekit/query-plan.js +25 -3
  372. package/dist/sveltekit/sql-source.d.ts +6 -0
  373. package/dist/sveltekit/sql-source.js +34 -6
  374. package/dist/sveltekit/sql.d.ts +31 -0
  375. package/dist/sveltekit/sql.js +135 -25
  376. package/dist/sveltekit/transport.d.ts +10 -2
  377. package/dist/sveltekit/transport.js +30 -6
  378. package/dist/upgrade-prompt.d.ts +1 -1
  379. package/dist/version.d.ts +1 -1
  380. package/dist/version.js +1 -1
  381. package/dist/watermark.js +35 -2
  382. package/dist/wc/GridMenus-By9vPuq0.js +1088 -0
  383. package/dist/wc/SvChartMenu-CQNrQGT2.js +308 -0
  384. package/dist/wc/SvDateRangeInput-DR6m7bSM.js +199 -0
  385. package/dist/wc/SvDateTimePicker-D-vRnaMo.js +771 -0
  386. package/dist/wc/SvField-B_kurx_P.js +149 -0
  387. package/dist/wc/SvGrid.helpers-BdVDtjUm.js +135 -0
  388. package/dist/wc/SvGridCellEditor-Bnf1Kr5C.js +560 -0
  389. package/dist/wc/SvGridChart-BqUJh2pG.js +3572 -0
  390. package/dist/wc/SvGridChartBuilder-CGycC5cn.js +988 -0
  391. package/dist/wc/SvGridChartPanel-CRnizsHD.js +1746 -0
  392. package/dist/wc/SvGridChartView-D1pa_xMy.js +47 -0
  393. package/dist/wc/SvGridDropdown-45WsObLL.js +259 -0
  394. package/dist/wc/SvModal-DrfOYYyX.js +189 -0
  395. package/dist/wc/cell-formatting-CBfgahv1.js +86 -0
  396. package/dist/wc/chart-6OXlybVT.js +4341 -0
  397. package/dist/wc/chart-export-CeSADGfi.js +135 -0
  398. package/dist/wc/chart-export-pdf-BGko7MER.js +104 -0
  399. package/dist/wc/chart-summary-2m3ia1-n.js +137 -0
  400. package/dist/wc/chart-trend-CQOQtTMl.js +50 -0
  401. package/dist/wc/chart-validate-CD6ptiwg.js +180 -0
  402. package/dist/wc/client-DQIzjDBG.js +3064 -0
  403. package/dist/wc/column-resize-DUPgynvc.js +101 -0
  404. package/dist/wc/date-format-DS-z_h9v.js +1130 -0
  405. package/dist/wc/dismissable-CQ6XFXsk.js +45 -0
  406. package/dist/wc/editor-contract-peBDxir_.js +22 -0
  407. package/dist/wc/editor-registry-DxGKqcvx.js +24 -0
  408. package/dist/wc/focus-trap-Dbb2tJxb.js +65 -0
  409. package/dist/wc/list-option-DrRyivWp.js +82 -0
  410. package/dist/wc/popover-WsGlvtQv.js +69 -0
  411. package/dist/wc/positioning-BiKLfu1E.js +112 -0
  412. package/dist/wc/react.d.ts +41 -0
  413. package/dist/wc/react.js +90 -0
  414. package/dist/wc/rolldown-runtime-Dy4uBu1J.js +11 -0
  415. package/dist/wc/row-drag-touch-CycRR65n.js +93 -0
  416. package/dist/wc/row-resize-limG_N1z.js +111 -0
  417. package/dist/wc/sv-sheet-element.d.ts +97 -0
  418. package/dist/wc/sv-sheet-element.js +44213 -0
  419. package/dist/wc/svelte-virtualizer.svelte-CXtQy2TQ.js +530 -0
  420. package/dist/wc/validate-BqDthkNr.js +88 -0
  421. package/dist/wc/vue.d.ts +31 -0
  422. package/dist/wc/vue.js +75 -0
  423. package/package.json +36 -6
  424. package/dist/designer/assets/GridMenus-B1JtIN21.js +0 -8
  425. package/dist/designer/assets/SvDateRangeInput-CjO7nn_x.js +0 -1
  426. package/dist/designer/assets/SvDateTimePicker-ByBD_ov6.js +0 -1
  427. package/dist/designer/assets/SvField-YDLipR6O.css +0 -1
  428. package/dist/designer/assets/SvField-cj1PFNgZ.js +0 -1
  429. package/dist/designer/assets/SvGridCellEditor-0W1L2hJ1.js +0 -2
  430. package/dist/designer/assets/SvGridChart-DBOR4xcz.js +0 -2
  431. package/dist/designer/assets/SvGridChart-fkMWeh1J.css +0 -1
  432. package/dist/designer/assets/SvGridChartPanel-symrhNnR.js +0 -11
  433. package/dist/designer/assets/SvGridChartView-BmRxq6mU.js +0 -1
  434. package/dist/designer/assets/SvGridDropdown-Bb3HH2Aj.js +0 -1
  435. package/dist/designer/assets/SvListBox-1oUF6Iav.js +0 -110
  436. package/dist/designer/assets/cell-formatting-wr5wm7US.js +0 -1
  437. package/dist/designer/assets/chart-DXFganU8.js +0 -1
  438. package/dist/designer/assets/column-resize-C_inr5zT.js +0 -1
  439. package/dist/designer/assets/date-format-DGagAqRc.css +0 -1
  440. package/dist/designer/assets/date-format-onlYDsrY.js +0 -1
  441. package/dist/designer/assets/easing-zaypKrr0.js +0 -3
  442. package/dist/designer/assets/index-k2stW6L8.css +0 -1
  443. package/dist/designer/assets/row-resize-B0FWHcNr.js +0 -1
  444. package/dist/designer/assets/src-D9p27OGC.js +0 -58
  445. package/dist/designer/assets/validate-h-aslRV9.js +0 -1
@@ -0,0 +1,905 @@
1
+ /**
2
+ * Excel number-format strings, compiled once and applied many times.
3
+ *
4
+ * The grammar is small but full of traps, so this file is explicit about the
5
+ * ones that bite:
6
+ *
7
+ * - A pattern has up to four sections separated by `;`:
8
+ * positive;negative;zero;text. With two, the second covers negatives AND
9
+ * zero. With one, it covers everything. A negative rendered by section two
10
+ * uses its ABSOLUTE value, which is why `0.00;(0.00)` shows `(1.50)` and
11
+ * not `(-1.50)`.
12
+ * - `,` means two different things. Between placeholders it is a thousands
13
+ * separator; immediately before the decimal point (or at the end) it scales
14
+ * the number down by a thousand per comma.
15
+ * - `%` scales UP by 100 and prints a literal percent.
16
+ * - `0` prints a digit or a zero, `#` prints a digit or nothing, `?` prints a
17
+ * digit or a space. They can be mixed: `#,##0.0#` keeps one decimal always
18
+ * and a second only when it is there.
19
+ * - Anything in quotes, after a backslash, or in the set of always-literal
20
+ * characters is emitted as-is.
21
+ * - `[Red]` and friends set a colour rather than printing.
22
+ * - `@` is the text placeholder and only appears in the fourth section.
23
+ *
24
+ * Dates are detected rather than configured: a pattern containing date tokens
25
+ * outside quotes is a date pattern. `m` is minutes when it follows an hour
26
+ * token and months otherwise, which is the one piece of context the token
27
+ * scanner has to carry.
28
+ */
29
+ const COLORS = {
30
+ BLACK: '#000000', BLUE: '#0000ff', CYAN: '#00ffff', GREEN: '#008000',
31
+ MAGENTA: '#ff00ff', RED: '#ff0000', WHITE: '#ffffff', YELLOW: '#ffff00',
32
+ };
33
+ /** Split on `;` at the top level, ignoring separators inside quotes, brackets
34
+ * or escapes. A naive `pattern.split(';')` breaks `"a;b"` and `[<100]`. */
35
+ function splitSections(pattern) {
36
+ const out = [];
37
+ let current = '';
38
+ let inQuote = false;
39
+ let inBracket = false;
40
+ for (let i = 0; i < pattern.length; i += 1) {
41
+ const ch = pattern[i];
42
+ if (ch === '\\') {
43
+ current += ch + (pattern[i + 1] ?? '');
44
+ i += 1;
45
+ continue;
46
+ }
47
+ if (ch === '"') {
48
+ inQuote = !inQuote;
49
+ current += ch;
50
+ continue;
51
+ }
52
+ if (!inQuote && ch === '[') {
53
+ inBracket = true;
54
+ current += ch;
55
+ continue;
56
+ }
57
+ if (!inQuote && ch === ']') {
58
+ inBracket = false;
59
+ current += ch;
60
+ continue;
61
+ }
62
+ if (ch === ';' && !inQuote && !inBracket) {
63
+ out.push(current);
64
+ current = '';
65
+ continue;
66
+ }
67
+ current += ch;
68
+ }
69
+ out.push(current);
70
+ return out;
71
+ }
72
+ const CONDITION = /^(<=|>=|<>|<|>|=)\s*(-?\d+(?:\.\d+)?)$/;
73
+ function passes(condition, n) {
74
+ switch (condition.op) {
75
+ case '<': return n < condition.value;
76
+ case '<=': return n <= condition.value;
77
+ case '>': return n > condition.value;
78
+ case '>=': return n >= condition.value;
79
+ case '=': return n === condition.value;
80
+ case '<>': return n !== condition.value;
81
+ }
82
+ }
83
+ function parseSection(raw) {
84
+ let color;
85
+ let condition;
86
+ let body = '';
87
+ // Walk rather than regex-replace: a pattern like `"[" @ "]"` has brackets
88
+ // INSIDE quoted literals, and a global /\[[^\]]*\]/ happily eats the text
89
+ // between them.
90
+ for (let i = 0; i < raw.length; i += 1) {
91
+ const ch = raw[i];
92
+ if (ch === '\\') {
93
+ body += ch + (raw[i + 1] ?? '');
94
+ i += 1;
95
+ continue;
96
+ }
97
+ if (ch === '"') {
98
+ const end = raw.indexOf('"', i + 1);
99
+ const stop = end < 0 ? raw.length : end;
100
+ body += raw.slice(i, stop + 1);
101
+ i = stop;
102
+ continue;
103
+ }
104
+ if (ch === '[') {
105
+ const end = raw.indexOf(']', i + 1);
106
+ if (end < 0) {
107
+ body += ch;
108
+ continue;
109
+ }
110
+ const inner = raw.slice(i + 1, end).trim().toUpperCase();
111
+ // An elapsed-time token is part of the pattern rather than a
112
+ // directive about it, so it stays in the body for the renderer.
113
+ if (ELAPSED_TOKEN.test(raw.slice(i))) {
114
+ body += raw.slice(i, end + 1);
115
+ i = end;
116
+ continue;
117
+ }
118
+ const named = COLORS[inner];
119
+ if (named)
120
+ color = named;
121
+ const cond = CONDITION.exec(inner);
122
+ if (cond)
123
+ condition = { op: cond[1], value: Number(cond[2]) };
124
+ // Anything else ([$-409] locale tags and the like) is dropped rather
125
+ // than printed.
126
+ i = end;
127
+ continue;
128
+ }
129
+ body += ch;
130
+ }
131
+ return condition ? { raw, color, condition, body } : { raw, color, body };
132
+ }
133
+ const DATE_TOKEN = /^(yyyy|yy|mmmmm|mmmm|mmm|mm|m|dddd|ddd|dd|d|hh|h|ss|s|AM\/PM|am\/pm|A\/P|a\/p)/;
134
+ /**
135
+ * Excel's elapsed-time tokens: the hours, minutes or seconds a duration
136
+ * holds in TOTAL rather than the clock's reading of it, which is what a
137
+ * timesheet needs. `[h]:mm` over 1.5 days is 36:00, not 12:00. Only h, m
138
+ * and s go in these brackets, so a colour (`[Red]`) or a condition
139
+ * (`[>100]`) never matches.
140
+ */
141
+ const ELAPSED_TOKEN = /^\[(hh?|mm?|ss?)\]/;
142
+ /** Does this section describe a date? Scans outside quotes and escapes. */
143
+ function looksLikeDate(body) {
144
+ for (let i = 0; i < body.length; i += 1) {
145
+ const ch = body[i];
146
+ if (ch === '\\') {
147
+ i += 1;
148
+ continue;
149
+ }
150
+ if (ch === '"') {
151
+ const end = body.indexOf('"', i + 1);
152
+ i = end < 0 ? body.length : end;
153
+ continue;
154
+ }
155
+ if (ELAPSED_TOKEN.test(body.slice(i)))
156
+ return true;
157
+ if (ch === '[') {
158
+ // Any other bracket is a colour or a condition, and says nothing
159
+ // about whether this is a date.
160
+ const end = body.indexOf(']', i + 1);
161
+ i = end < 0 ? body.length : end;
162
+ continue;
163
+ }
164
+ if (DATE_TOKEN.test(body.slice(i))) {
165
+ // `m` alone is ambiguous with the thousands/number grammar only in
166
+ // theory: a numeric pattern never contains a bare letter outside quotes.
167
+ return true;
168
+ }
169
+ }
170
+ return false;
171
+ }
172
+ const MONTHS = ['January', 'February', 'March', 'April', 'May', 'June',
173
+ 'July', 'August', 'September', 'October', 'November', 'December'];
174
+ const DAYS = ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'];
175
+ const pad2 = (n) => String(n).padStart(2, '0');
176
+ function toDate(value) {
177
+ if (value instanceof Date)
178
+ return value;
179
+ if (typeof value === 'number') {
180
+ // Excel serial day, with the usual 1899-12-30 epoch. That is correct for
181
+ // every date from 1900-03-01 on, which is every date anyone stores. Excel
182
+ // itself is a day out below serial 61 because it counts a 1900-02-29 that
183
+ // never existed; matching that bug exactly would break real dates.
184
+ return new Date(Date.UTC(1899, 11, 30) + value * 86400000);
185
+ }
186
+ if (typeof value === 'string' && value.trim() !== '') {
187
+ const d = new Date(value);
188
+ return Number.isNaN(d.getTime()) ? null : d;
189
+ }
190
+ return null;
191
+ }
192
+ /** The meridiem token a pattern carries, which puts `h` on a 12-hour clock. */
193
+ function meridiemOf(body) {
194
+ for (let i = 0; i < body.length; i += 1) {
195
+ if (body[i] === '\\') {
196
+ i += 1;
197
+ continue;
198
+ }
199
+ if (body[i] === '"') {
200
+ const end = body.indexOf('"', i + 1);
201
+ i = end < 0 ? body.length : end;
202
+ continue;
203
+ }
204
+ const m = /^(AM\/PM|am\/pm|A\/P|a\/p)/.exec(body.slice(i));
205
+ if (m)
206
+ return m[1];
207
+ }
208
+ return null;
209
+ }
210
+ /**
211
+ * The finest unit a time pattern shows, in milliseconds, or null for a
212
+ * pattern that shows no time. Excel ROUNDS to it: 23:59:40 under `hh:mm`
213
+ * reads 00:00, and the date rolls with it where the pattern shows one.
214
+ */
215
+ function finestUnit(body) {
216
+ let unit = null;
217
+ let sawHour = false;
218
+ const finer = (ms) => { unit = unit === null ? ms : Math.min(unit, ms); };
219
+ for (let i = 0; i < body.length; i += 1) {
220
+ if (body[i] === '\\') {
221
+ i += 1;
222
+ continue;
223
+ }
224
+ if (body[i] === '"') {
225
+ const end = body.indexOf('"', i + 1);
226
+ i = end < 0 ? body.length : end;
227
+ continue;
228
+ }
229
+ const fraction = /^\.(0+)/.exec(body.slice(i));
230
+ if (fraction && unit !== null) {
231
+ finer(Math.pow(10, 3 - fraction[1].length));
232
+ i += fraction[0].length - 1;
233
+ continue;
234
+ }
235
+ const m = DATE_TOKEN.exec(body.slice(i));
236
+ if (!m)
237
+ continue;
238
+ const token = m[1];
239
+ i += token.length - 1;
240
+ if (token === 'h' || token === 'hh') {
241
+ sawHour = true;
242
+ finer(3600000);
243
+ }
244
+ else if (token === 's' || token === 'ss')
245
+ finer(1000);
246
+ else if ((token === 'm' || token === 'mm') && sawHour)
247
+ finer(60000);
248
+ }
249
+ return unit;
250
+ }
251
+ function renderDate(body, date, serial) {
252
+ const unit = finestUnit(body);
253
+ if (unit !== null && unit > 0)
254
+ date = new Date(Math.round(date.getTime() / unit) * unit);
255
+ const meridiem = meridiemOf(body);
256
+ const hourOf = (d) => (meridiem ? ((d.getUTCHours() + 11) % 12) + 1 : d.getUTCHours());
257
+ let out = '';
258
+ let sawHour = false;
259
+ let sawSecond = false;
260
+ for (let i = 0; i < body.length; i += 1) {
261
+ const ch = body[i];
262
+ if (ch === '\\') {
263
+ out += body[i + 1] ?? '';
264
+ i += 1;
265
+ continue;
266
+ }
267
+ const elapsed = ELAPSED_TOKEN.exec(body.slice(i));
268
+ if (elapsed) {
269
+ const token = elapsed[1];
270
+ i += elapsed[0].length - 1;
271
+ // Without a serial there is no duration to total, so the clock's own
272
+ // reading is the best answer; with one, the whole of it counts.
273
+ const days = serial ?? 0;
274
+ const total = token.startsWith('h') ? days * 24 : token.startsWith('m') ? days * 1440 : days * 86400;
275
+ const whole = Math.floor(Math.abs(total) + 1e-9) * (total < 0 ? -1 : 1);
276
+ out += token.length === 2 ? pad2(whole) : String(whole);
277
+ if (token.startsWith('h'))
278
+ sawHour = true;
279
+ continue;
280
+ }
281
+ if (ch === '"') {
282
+ const end = body.indexOf('"', i + 1);
283
+ out += body.slice(i + 1, end < 0 ? body.length : end);
284
+ i = end < 0 ? body.length : end;
285
+ continue;
286
+ }
287
+ const fraction = sawSecond ? /^\.(0+)/.exec(body.slice(i)) : null;
288
+ if (fraction) {
289
+ const digits = fraction[1].length;
290
+ out += `.${String(date.getUTCMilliseconds()).padStart(3, '0').slice(0, digits).padEnd(digits, '0')}`;
291
+ i += fraction[0].length - 1;
292
+ continue;
293
+ }
294
+ const m = DATE_TOKEN.exec(body.slice(i));
295
+ if (!m) {
296
+ out += ch;
297
+ continue;
298
+ }
299
+ const token = m[1];
300
+ i += token.length - 1;
301
+ if (token === 's' || token === 'ss')
302
+ sawSecond = true;
303
+ switch (token) {
304
+ case 'yyyy':
305
+ out += date.getUTCFullYear();
306
+ break;
307
+ case 'yy':
308
+ out += pad2(date.getUTCFullYear() % 100);
309
+ break;
310
+ case 'mmmm':
311
+ out += MONTHS[date.getUTCMonth()];
312
+ break;
313
+ case 'mmm':
314
+ out += MONTHS[date.getUTCMonth()].slice(0, 3);
315
+ break;
316
+ case 'dddd':
317
+ out += DAYS[date.getUTCDay()];
318
+ break;
319
+ case 'ddd':
320
+ out += DAYS[date.getUTCDay()].slice(0, 3);
321
+ break;
322
+ case 'dd':
323
+ out += pad2(date.getUTCDate());
324
+ break;
325
+ case 'd':
326
+ out += date.getUTCDate();
327
+ break;
328
+ case 'hh':
329
+ out += pad2(hourOf(date));
330
+ sawHour = true;
331
+ break;
332
+ case 'h':
333
+ out += hourOf(date);
334
+ sawHour = true;
335
+ break;
336
+ case 'ss':
337
+ out += pad2(date.getUTCSeconds());
338
+ break;
339
+ case 's':
340
+ out += date.getUTCSeconds();
341
+ break;
342
+ // Excel prints what the token spells: AM/PM in full, A/P as the one
343
+ // letter, and each in the case it was written in.
344
+ case 'AM/PM':
345
+ out += date.getUTCHours() < 12 ? 'AM' : 'PM';
346
+ break;
347
+ case 'am/pm':
348
+ out += date.getUTCHours() < 12 ? 'am' : 'pm';
349
+ break;
350
+ case 'A/P':
351
+ out += date.getUTCHours() < 12 ? 'A' : 'P';
352
+ break;
353
+ case 'a/p':
354
+ out += date.getUTCHours() < 12 ? 'a' : 'p';
355
+ break;
356
+ case 'mmmmm':
357
+ out += MONTHS[date.getUTCMonth()].slice(0, 1);
358
+ break;
359
+ // `m` and `mm` are MINUTES after an hour token, MONTHS otherwise. This
360
+ // is the one piece of context the scanner carries, and getting it wrong
361
+ // turns 09:05 into 09:09.
362
+ case 'mm':
363
+ out += sawHour ? pad2(date.getUTCMinutes()) : pad2(date.getUTCMonth() + 1);
364
+ break;
365
+ case 'm':
366
+ out += sawHour ? date.getUTCMinutes() : date.getUTCMonth() + 1;
367
+ break;
368
+ default: out += token;
369
+ }
370
+ }
371
+ return out;
372
+ }
373
+ const FRACTION = /^(?:([#0?]+)\s+)?([#0?]+)\/([#0?]+|\d+)$/;
374
+ /** The plan for a fraction section, or null when it is not one. */
375
+ function planFraction(body) {
376
+ // Only the bare shape reads as a fraction; anything with quoted text or an
377
+ // escape around it stays on the ordinary numeric path, where it always was.
378
+ const m = FRACTION.exec(body.trim());
379
+ if (!m)
380
+ return null;
381
+ const den = m[3];
382
+ return { int: m[1] ?? null, num: m[2], den, denLiteral: /^\d+$/.test(den) ? Number(den) : null };
383
+ }
384
+ /** The closest numerator and denominator, with the denominator capped. */
385
+ function bestFraction(value, maxDen) {
386
+ // Stern-Brocot: take the mediant of the two bounding fractions until the
387
+ // denominator would pass the cap. Exact for anything that fits, and it
388
+ // cannot run longer than the cap.
389
+ let loNum = 0;
390
+ let loDen = 1;
391
+ let hiNum = 1;
392
+ let hiDen = 0;
393
+ let bestNum = Math.round(value);
394
+ let bestDen = 1;
395
+ let bestErr = Math.abs(value - bestNum);
396
+ for (let i = 0; i < 64; i += 1) {
397
+ const num = loNum + hiNum;
398
+ const den = loDen + hiDen;
399
+ if (den > maxDen)
400
+ break;
401
+ const mediant = num / den;
402
+ const err = Math.abs(value - mediant);
403
+ if (err < bestErr - 1e-12) {
404
+ bestErr = err;
405
+ bestNum = num;
406
+ bestDen = den;
407
+ }
408
+ if (err < 1e-12)
409
+ break;
410
+ if (mediant < value) {
411
+ loNum = num;
412
+ loDen = den;
413
+ }
414
+ else {
415
+ hiNum = num;
416
+ hiDen = den;
417
+ }
418
+ }
419
+ return { num: bestNum, den: bestDen };
420
+ }
421
+ /** A placeholder group as Excel pads it: `0` a zero, `?` a space, `#` nothing. */
422
+ function padHolders(text, holders) {
423
+ if (text.length >= holders.length)
424
+ return text;
425
+ const filler = holders.includes('0') ? '0' : holders.includes('?') ? ' ' : '';
426
+ return filler ? filler.repeat(holders.length - text.length) + text : text;
427
+ }
428
+ /** One number through a fraction pattern. */
429
+ function renderFraction(plan, value) {
430
+ const sign = value < 0 ? '-' : '';
431
+ const magnitude = Math.abs(value);
432
+ const whole = plan.int ? Math.floor(magnitude + 1e-12) : 0;
433
+ const rest = magnitude - whole;
434
+ const maxDen = plan.denLiteral ?? Math.pow(10, plan.den.length) - 1;
435
+ const found = plan.denLiteral
436
+ ? { num: Math.round(rest * plan.denLiteral), den: plan.denLiteral }
437
+ : bestFraction(rest, maxDen);
438
+ let num = found.num;
439
+ const den = found.den;
440
+ let carried = whole;
441
+ // Rounding up to a whole: 0.99 over `# ?/?` is 1, not 1/1.
442
+ if (den > 0 && num >= den) {
443
+ carried += Math.floor(num / den);
444
+ num %= den;
445
+ }
446
+ if (!plan.int) {
447
+ return `${sign}${padHolders(String(num + carried * den), plan.num)}/${padHolders(String(den), plan.den)}`;
448
+ }
449
+ const blanks = (holders) => (holders.includes('?') ? ' '.repeat(holders.length) : '');
450
+ const wholeText = carried === 0 && !plan.int.includes('0')
451
+ ? ' '.repeat(plan.int.includes('?') ? plan.int.length : 0)
452
+ : padHolders(String(carried), plan.int);
453
+ // No remainder: Excel leaves the fraction's width blank rather than
454
+ // printing 0/1, so a column of them still lines up.
455
+ const fraction = num === 0
456
+ ? `${blanks(plan.num)} ${blanks(plan.den)}`
457
+ : `${padHolders(String(num), plan.num)}/${padHolders(String(den), plan.den)}`;
458
+ return `${sign}${wholeText} ${fraction}`.replace(/\s+$/, '');
459
+ }
460
+ /**
461
+ * Pull a numeric section apart into literal text and digit placeholders.
462
+ *
463
+ * Literal text before the first digit is the prefix and after the last is
464
+ * the suffix. Literal text BETWEEN integer digits, as in `000-00-0000` or
465
+ * `(###) ###-####`, turns the integer side into a mask that the digits are
466
+ * laid into from the right, which is how Excel's Special formats work.
467
+ *
468
+ * `_x` (Excel: leave the width of x) and `*x` (fill the cell with x) both
469
+ * become one space here: text has no cell width to leave or fill, and one
470
+ * space is what keeps `_($* #,##0.00_)` reading as `$ 1,234.00`.
471
+ */
472
+ function planNumeric(body) {
473
+ let prefix = '';
474
+ let suffix = '';
475
+ let intPlaceholders = '';
476
+ let fracPlaceholders = '';
477
+ let useGrouping = false;
478
+ let percent = false;
479
+ let scientific = false;
480
+ let expPlaceholders = '';
481
+ let scale = 1;
482
+ let seenPlaceholder = false;
483
+ let afterDecimal = false;
484
+ // The integer side as tokens, literal text included, until the decimal
485
+ // point. `pending` holds literal text after the last integer digit, which
486
+ // is part of the mask only if another digit follows it.
487
+ const mask = [];
488
+ let pending = '';
489
+ let maskHasLiteral = false;
490
+ const literal = (text) => {
491
+ if (!seenPlaceholder)
492
+ prefix += text;
493
+ else if (afterDecimal || scientific)
494
+ suffix += text;
495
+ else
496
+ pending += text;
497
+ };
498
+ for (let i = 0; i < body.length; i += 1) {
499
+ const ch = body[i];
500
+ if (ch === '\\') {
501
+ literal(body[i + 1] ?? '');
502
+ i += 1;
503
+ continue;
504
+ }
505
+ if (ch === '_' || ch === '*') {
506
+ literal(' ');
507
+ i += 1;
508
+ continue;
509
+ }
510
+ if (ch === '"') {
511
+ const end = body.indexOf('"', i + 1);
512
+ literal(body.slice(i + 1, end < 0 ? body.length : end));
513
+ i = end < 0 ? body.length : end;
514
+ continue;
515
+ }
516
+ if (ch === '0' || ch === '#' || ch === '?') {
517
+ seenPlaceholder = true;
518
+ // After an E+ the placeholders size the EXPONENT, not the mantissa.
519
+ // Counting them as decimals turns 0.00E+00 into four decimal places.
520
+ if (scientific)
521
+ expPlaceholders += ch;
522
+ else if (afterDecimal)
523
+ fracPlaceholders += ch;
524
+ else {
525
+ intPlaceholders += ch;
526
+ if (pending) {
527
+ mask.push({ kind: 'lit', text: pending });
528
+ maskHasLiteral = true;
529
+ pending = '';
530
+ }
531
+ mask.push({ kind: 'digit', ch });
532
+ }
533
+ continue;
534
+ }
535
+ if (ch === '.') {
536
+ afterDecimal = true;
537
+ seenPlaceholder = true;
538
+ continue;
539
+ }
540
+ if (ch === ',') {
541
+ // A comma between placeholders groups; one trailing (before the decimal
542
+ // point or at the end of the pattern) scales by a thousand.
543
+ const rest = body.slice(i + 1);
544
+ if (/^[0#?]/.test(rest))
545
+ useGrouping = true;
546
+ else
547
+ scale *= 1000;
548
+ continue;
549
+ }
550
+ if (ch === '%') {
551
+ percent = true;
552
+ literal('%');
553
+ continue;
554
+ }
555
+ if ((ch === 'E' || ch === 'e') && /^[+-]/.test(body.slice(i + 1))) {
556
+ scientific = true;
557
+ i += 1;
558
+ continue;
559
+ }
560
+ literal(ch);
561
+ }
562
+ // Literal text after the last integer digit belongs to the suffix, before
563
+ // whatever the fraction and exponent added.
564
+ if (pending)
565
+ suffix = pending + suffix;
566
+ // A `?` on the integer side pads with a space, which the mask renderer
567
+ // does and the plain path (digits, grouping) does not.
568
+ const needsMask = maskHasLiteral || intPlaceholders.includes('?');
569
+ return {
570
+ prefix, suffix, intPlaceholders, intMask: needsMask ? mask : null,
571
+ fracPlaceholders, expPlaceholders,
572
+ useGrouping, scale, percent, scientific,
573
+ };
574
+ }
575
+ /** Lay digits into a mask from the right: `000-00-0000` on 123456789 is
576
+ * `123-45-6789`; digits left over go in front, missing ones follow the
577
+ * placeholder's rule, so `###-####` on 1234 is `-1234` as Excel gives. */
578
+ function renderMask(mask, digits) {
579
+ let out = '';
580
+ let at = digits.length;
581
+ for (let i = mask.length - 1; i >= 0; i -= 1) {
582
+ const token = mask[i];
583
+ if (token.kind === 'lit') {
584
+ out = token.text + out;
585
+ continue;
586
+ }
587
+ if (at > 0) {
588
+ at -= 1;
589
+ out = digits[at] + out;
590
+ continue;
591
+ }
592
+ if (token.ch === '0')
593
+ out = `0${out}`;
594
+ else if (token.ch === '?')
595
+ out = ` ${out}`;
596
+ }
597
+ return digits.slice(0, at) + out;
598
+ }
599
+ function group(intText, mark) {
600
+ return intText.replace(/\B(?=(\d{3})+(?!\d))/g, mark);
601
+ }
602
+ function renderNumeric(plan, value, marks) {
603
+ let n = value;
604
+ if (plan.percent)
605
+ n *= 100;
606
+ if (plan.scale !== 1)
607
+ n /= plan.scale;
608
+ if (plan.scientific) {
609
+ // The integer placeholders set the STEP of the exponent, which is what
610
+ // makes `##0.0E+0` engineering notation: three of them means the
611
+ // exponent moves in threes and the mantissa carries up to three integer
612
+ // digits, so 12345 reads 12.3E+3 rather than 1.2E+4. The everyday
613
+ // `0.00E+00` has one, and is the ordinary scientific form.
614
+ const step = Math.max(1, plan.intPlaceholders.length);
615
+ const decimals = plan.fracPlaceholders.length;
616
+ let exponent = n === 0 ? 0 : Math.floor(Math.log10(Math.abs(n)));
617
+ exponent = Math.floor(exponent / step) * step;
618
+ let mantissa = n / Math.pow(10, exponent);
619
+ // Rounding can carry the mantissa over its own width: 999.95 with one
620
+ // decimal is 1000.0, which is 1.0 a step further out.
621
+ if (Math.abs(Number(mantissa.toFixed(decimals))) >= Math.pow(10, step)) {
622
+ mantissa /= Math.pow(10, step);
623
+ exponent += step;
624
+ }
625
+ const sign = exponent < 0 ? '-' : '+';
626
+ const digits = String(Math.abs(exponent)).padStart(plan.expPlaceholders.length || 1, '0');
627
+ return `${plan.prefix}${mantissa.toFixed(decimals)}E${sign}${digits}${plan.suffix}`;
628
+ }
629
+ const decimals = plan.fracPlaceholders.length;
630
+ const fixed = Math.abs(n).toFixed(decimals);
631
+ const [rawInt = '0', rawFrac = ''] = fixed.split('.');
632
+ // Pad the integer side out to the number of `0` placeholders, and drop a
633
+ // leading zero entirely when the pattern is all `#`.
634
+ const minInt = plan.intPlaceholders.split('').filter((c) => c === '0').length;
635
+ let intText = rawInt;
636
+ if (plan.intMask) {
637
+ intText = renderMask(plan.intMask, rawInt === '0' && minInt === 0 ? '' : rawInt);
638
+ }
639
+ else {
640
+ if (intText.length < minInt)
641
+ intText = intText.padStart(minInt, '0');
642
+ if (minInt === 0 && intText === '0' && plan.intPlaceholders.length > 0)
643
+ intText = '';
644
+ if (plan.useGrouping && intText !== '')
645
+ intText = group(intText, marks.group);
646
+ }
647
+ // Trim optional decimals from the right: `0.0#` on 1.5 gives "1.5", not
648
+ // "1.50". A `0` placeholder is never trimmed, a `#` always may be, and a
649
+ // `?` becomes a space so columns line up.
650
+ let fracText = rawFrac;
651
+ for (let i = plan.fracPlaceholders.length - 1; i >= 0; i -= 1) {
652
+ const kind = plan.fracPlaceholders[i];
653
+ if (kind === '0')
654
+ break;
655
+ if (fracText[i] !== '0')
656
+ break;
657
+ fracText = kind === '?' ? `${fracText.slice(0, i)} ` : fracText.slice(0, i);
658
+ }
659
+ const body = fracText === '' ? intText : `${intText}${marks.decimal}${fracText}`;
660
+ // `#` on zero prints nothing, which is how "hide zeros" patterns work. The
661
+ // fallback below is only for a pattern with no digit placeholders at all.
662
+ return plan.prefix + body + plan.suffix;
663
+ }
664
+ /** A section with no digit placeholders is pure literal text: `"-"` as the
665
+ * zero section must print `-`, not `-0`. */
666
+ function hasPlaceholders(plan) {
667
+ return plan.intPlaceholders !== '' || plan.fracPlaceholders !== '';
668
+ }
669
+ /** The text section: `@` is the value, quotes and backslashes wrap
670
+ * literals, `_x` and `*x` are one space, as on the numeric side. */
671
+ function renderText(body, value) {
672
+ let out = '';
673
+ for (let i = 0; i < body.length; i += 1) {
674
+ const ch = body[i];
675
+ if (ch === '\\') {
676
+ out += body[i + 1] ?? '';
677
+ i += 1;
678
+ continue;
679
+ }
680
+ if (ch === '_' || ch === '*') {
681
+ out += ' ';
682
+ i += 1;
683
+ continue;
684
+ }
685
+ if (ch === '"') {
686
+ const end = body.indexOf('"', i + 1);
687
+ out += body.slice(i + 1, end < 0 ? body.length : end);
688
+ i = end < 0 ? body.length : end;
689
+ continue;
690
+ }
691
+ out += ch === '@' ? value : ch;
692
+ }
693
+ return out;
694
+ }
695
+ /** Excel's General: up to 11 significant digits, no trailing zeros. */
696
+ function general(value) {
697
+ if (typeof value === 'number') {
698
+ if (!Number.isFinite(value))
699
+ return String(value);
700
+ if (Number.isInteger(value))
701
+ return String(value);
702
+ return String(Number(value.toPrecision(11)));
703
+ }
704
+ if (typeof value === 'boolean')
705
+ return value ? 'TRUE' : 'FALSE';
706
+ return value === null || value === undefined ? '' : String(value);
707
+ }
708
+ /**
709
+ * Compile a format string. Compilation is cached per pattern, so a column of
710
+ * ten thousand cells sharing one format parses it once.
711
+ */
712
+ const cache = new Map();
713
+ export const INVARIANT_MARKS = { decimal: '.', group: ',' };
714
+ export function compileNumberFormat(pattern, marks = INVARIANT_MARKS) {
715
+ // The marks join the cache key, so a sheet showing one locale does not
716
+ // serve its rendered numbers to a sheet showing another.
717
+ const key = marks === INVARIANT_MARKS ? pattern : `${pattern}\u0000${marks.decimal}${marks.group}`;
718
+ const hit = cache.get(key);
719
+ if (hit)
720
+ return hit;
721
+ const sections = splitSections(pattern).map(parseSection);
722
+ const positive = sections[0];
723
+ const negative = sections[1];
724
+ const zero = sections[2];
725
+ const text = sections[3];
726
+ const conditional = sections.some((sec) => sec.condition);
727
+ // Plans are built once here, not per value.
728
+ const plans = new Map();
729
+ const fractions = new Map();
730
+ const dateFlags = new Map();
731
+ for (const s of sections) {
732
+ if (!s)
733
+ continue;
734
+ const isDate = looksLikeDate(s.body);
735
+ dateFlags.set(s, isDate);
736
+ if (isDate)
737
+ continue;
738
+ const fraction = planFraction(s.body);
739
+ if (fraction)
740
+ fractions.set(s, fraction);
741
+ else
742
+ plans.set(s, planNumeric(s.body));
743
+ }
744
+ const compiled = {
745
+ pattern,
746
+ format(value) {
747
+ if (pattern.trim() === '' || pattern.toUpperCase() === 'GENERAL') {
748
+ return { text: general(value) };
749
+ }
750
+ if (typeof value === 'string' && value !== '') {
751
+ // Excel's FOURTH section is the one that governs text. With one, `@`
752
+ // puts the text where it stands and a section without an `@` shows
753
+ // only its own literals, which is what makes `;;;` hide a cell and
754
+ // `;;;"n/a"` show n/a whatever was typed. With no fourth section the
755
+ // text is shown as it is, even under a numeric pattern like `0.00`.
756
+ const section = text ?? (positive?.body.includes('@') ? positive : undefined);
757
+ if (!section)
758
+ return { text: value };
759
+ return { text: renderText(section.body, section.body.includes('@') ? value : ''), color: section.color };
760
+ }
761
+ if (value === null || value === undefined || value === '')
762
+ return { text: '' };
763
+ if (typeof value === 'boolean')
764
+ return { text: value ? 'TRUE' : 'FALSE' };
765
+ const n = typeof value === 'number' ? value : Number(value);
766
+ if (!Number.isFinite(n)) {
767
+ const d = toDate(value);
768
+ if (d && positive && dateFlags.get(positive)) {
769
+ return { text: renderDate(positive.body, d), color: positive.color };
770
+ }
771
+ return { text: String(value) };
772
+ }
773
+ // Pick the section. Two sections means the second covers zero too.
774
+ // With conditions, the first section whose condition the value passes
775
+ // wins and an unconditioned one is the fallback, as in Excel's
776
+ // `[<=9999999]###-####;(###) ###-####`.
777
+ let section;
778
+ if (conditional) {
779
+ section = sections.find((sec) => sec && (sec.condition ? passes(sec.condition, n) : true));
780
+ }
781
+ else {
782
+ section = positive;
783
+ if (n < 0 && negative)
784
+ section = negative;
785
+ else if (n === 0 && zero)
786
+ section = zero;
787
+ }
788
+ if (!section)
789
+ return { text: general(value) };
790
+ if (dateFlags.get(section)) {
791
+ const d = toDate(value);
792
+ // `n` is the serial the value stands for, which is what an elapsed
793
+ // token totals: 1.5 is a day and a half, [h]:mm reads 36:00.
794
+ return d
795
+ ? { text: renderDate(section.body, d, n), color: section.color }
796
+ : { text: general(value) };
797
+ }
798
+ const asFraction = fractions.get(section);
799
+ if (asFraction) {
800
+ // A negative with its own section is rendered from its magnitude,
801
+ // as everywhere else: the section supplies the sign.
802
+ const usingNegative = n < 0 && section === negative && !conditional;
803
+ return { text: renderFraction(asFraction, usingNegative ? Math.abs(n) : n), color: section.color };
804
+ }
805
+ const plan = plans.get(section);
806
+ if (!hasPlaceholders(plan)) {
807
+ // `@` is the text placeholder, and a NUMBER in a cell formatted as
808
+ // Text is still shown by Excel as the number rather than as the
809
+ // placeholder: `@` over 5 reads 5, not @.
810
+ if (section.body.includes('@')) {
811
+ return { text: renderText(section.body, general(value)), color: section.color };
812
+ }
813
+ return { text: plan.prefix + plan.suffix, color: section.color };
814
+ }
815
+ // A negative shown by its own section renders its ABSOLUTE value: the
816
+ // section supplies the sign, usually as parentheses or a literal minus.
817
+ const usingNegativeSection = n < 0 && section === negative && !conditional;
818
+ const magnitude = usingNegativeSection ? Math.abs(n) : n;
819
+ let out = renderNumeric(plan, magnitude, marks);
820
+ // With no negative section, put the sign back on.
821
+ if (n < 0 && !usingNegativeSection && !out.startsWith('-'))
822
+ out = `-${out}`;
823
+ return { text: out, color: section.color };
824
+ },
825
+ };
826
+ cache.set(key, compiled);
827
+ return compiled;
828
+ }
829
+ /** Format one value against a pattern. Convenience over compile-then-call. */
830
+ export function formatWithPattern(value, pattern) {
831
+ return compileNumberFormat(pattern).format(value).text;
832
+ }
833
+ /** The presets behind Ctrl+Shift+1 through 6 and the ribbon's $ % , buttons.
834
+ * Percent is Excel's Percent Style, no decimals: 0.425 reads 43%. */
835
+ export const FORMAT_PRESETS = {
836
+ general: 'General',
837
+ number: '#,##0.00',
838
+ time: 'h:mm AM/PM',
839
+ date: 'yyyy-mm-dd',
840
+ currency: '$#,##0.00;($#,##0.00)',
841
+ accounting: '_($* #,##0.00_);_($* (#,##0.00);_($* "-"??_);_(@_)',
842
+ percent: '0%',
843
+ scientific: '0.00E+00',
844
+ };
845
+ /** What the ribbon's Number Format combo applies for a category. Excel's
846
+ * "Percentage" there carries two decimals where its % button carries none;
847
+ * the other entries are the presets. */
848
+ export const FORMAT_CATEGORY_PATTERNS = {
849
+ ...FORMAT_PRESETS,
850
+ percent: '0.00%',
851
+ };
852
+ /** Excel's Special category: fixed-shape numbers laid into a mask. */
853
+ export const SPECIAL_FORMATS = {
854
+ zip: { label: 'Zip Code', pattern: '00000' },
855
+ zip4: { label: 'Zip Code + 4', pattern: '00000-0000' },
856
+ phone: { label: 'Phone Number', pattern: '[<=9999999]###-####;(###) ###-####' },
857
+ ssn: { label: 'Social Security Number', pattern: '000-00-0000' },
858
+ };
859
+ /** The pattern Excel's Accounting category spells for a symbol and a
860
+ * number of decimals; an empty symbol is its "None". */
861
+ export function accountingPattern(symbol, decimals) {
862
+ const digits = `#,##0${decimals > 0 ? '.' + '0'.repeat(decimals) : ''}`;
863
+ const sym = symbol === '$' ? '$* ' : symbol ? `${JSON.stringify(symbol)}* ` : '* ';
864
+ return `_(${sym}${digits}_);_(${sym}(${digits});_(${sym}"-"${'?'.repeat(decimals)}_);_(@_)`;
865
+ }
866
+ /** The symbol and decimals an accounting pattern was built from, or null
867
+ * when the pattern is not one `accountingPattern` would spell. */
868
+ export function accountingParts(fmt) {
869
+ if (!fmt)
870
+ return null;
871
+ const m = /^_\((?:"([^"]*)"|\$)?\* #,##0(\.0+)?_\);/.exec(fmt);
872
+ if (!m)
873
+ return null;
874
+ const symbol = m[1] !== undefined ? m[1] : fmt.startsWith('_($') ? '$' : '';
875
+ return { symbol, decimals: m[2] ? m[2].length - 1 : 0 };
876
+ }
877
+ /**
878
+ * Which of Excel's categories a pattern belongs to, with the decimals and
879
+ * separator it carries, so the ribbon's combo can say "Percentage" for a
880
+ * cell holding `0%` (a typed 12%) as well as for the combo's `0.00%`, and
881
+ * Format Cells can open on the right category. A pattern that is none of
882
+ * them is 'custom'.
883
+ */
884
+ export function formatCategory(fmt) {
885
+ if (!fmt || fmt === 'General')
886
+ return { category: 'general', decimals: 2, thousands: true };
887
+ const decimals = fmt.match(/\.(0+)/)?.[1]?.length ?? 0;
888
+ if (accountingParts(fmt))
889
+ return { category: 'accounting', decimals, thousands: true };
890
+ if (Object.values(SPECIAL_FORMATS).some((sp) => sp.pattern === fmt))
891
+ return { category: 'special', decimals: 0, thousands: false };
892
+ if (/E\+/i.test(fmt))
893
+ return { category: 'scientific', decimals, thousands: false };
894
+ if (/%$/.test(fmt))
895
+ return { category: 'percent', decimals, thousands: false };
896
+ if (/^\$/.test(fmt))
897
+ return { category: 'currency', decimals, thousands: true };
898
+ if (/[hs]:|AM\/PM/i.test(fmt))
899
+ return { category: 'time', decimals: 0, thousands: false };
900
+ if (/y|d/i.test(fmt) && !/[#0]/.test(fmt))
901
+ return { category: 'date', decimals: 0, thousands: false };
902
+ if (/^#?,?#*0(\.0+)?$/.test(fmt))
903
+ return { category: 'number', decimals, thousands: fmt.includes(',') };
904
+ return { category: 'custom', decimals, thousands: false };
905
+ }