@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
@@ -12,6 +12,7 @@
12
12
  * grid's history like a typed edit. Styled by the `.sv-sheet-dialog`
13
13
  * rules the shell carries for all four of its dialogs.
14
14
  */
15
+ import { useSheetText } from './sheet-text'
15
16
  import { SvModal } from '@svgrid/grid'
16
17
  import type { GridCommandContext } from '@svgrid/grid/shortcuts'
17
18
  import { findAll, findNext, replaceOne, replaceAll, type FindOptions } from './sheet/find-replace'
@@ -24,6 +25,7 @@
24
25
  }
25
26
 
26
27
  let { open = $bindable(false), cmd, onClose }: Props = $props()
28
+ const t = useSheetText()
27
29
 
28
30
  let findText = $state('')
29
31
  let replaceText = $state('')
@@ -47,7 +49,7 @@
47
49
  const c = cmd()
48
50
  if (!c) return
49
51
  if (!hit) {
50
- status = findText ? `We couldn't find what you were looking for.` : ''
52
+ status = findText ? t('findReplace.notFound') : ''
51
53
  return
52
54
  }
53
55
  c.setActiveCell(hit.rowIndex, hit.colIndex)
@@ -66,7 +68,7 @@
66
68
  const c = cmd()
67
69
  if (!c || !findText) return
68
70
  const n = findAll(c, findText, options()).length
69
- status = n === 0 ? `We couldn't find what you were looking for.` : `${n} cell${n === 1 ? '' : 's'} found`
71
+ status = n === 0 ? t('findReplace.notFound') : t(n === 1 ? 'findReplace.cellFound' : 'findReplace.cellsFound', { count: n })
70
72
  }
71
73
 
72
74
  function replace() {
@@ -79,9 +81,7 @@
79
81
  const c = cmd()
80
82
  if (!c || !findText) return
81
83
  const n = replaceAll(c, findText, replaceText, options())
82
- status = n === 0
83
- ? `We couldn't find anything to replace.`
84
- : `All done. We made ${n} replacement${n === 1 ? '' : 's'}.`
84
+ status = n === 0 ? t('findReplace.nothingToReplace') : t(n === 1 ? 'findReplace.replacedOne' : 'findReplace.replacedMany', { count: n })
85
85
  }
86
86
 
87
87
  function close() {
@@ -97,24 +97,24 @@
97
97
  }
98
98
  </script>
99
99
 
100
- <SvModal bind:open onClose={onClose} title="Find and Replace" size="sm">
101
- <div class="sv-sheet-dialog" role="group" aria-label="Find and Replace">
100
+ <SvModal bind:open onClose={onClose} title={t('findReplace.title')} size="sm">
101
+ <div class="sv-sheet-dialog" role="group" aria-label={t('findReplace.title')}>
102
102
  <label class="field">
103
- <span>Find what:</span>
103
+ <span>{t('findReplace.findWhat')}</span>
104
104
  <input bind:this={findInput} type="text" bind:value={findText} onkeydown={onKey} spellcheck="false" autocomplete="off" />
105
105
  </label>
106
106
  <label class="field">
107
- <span>Replace with:</span>
107
+ <span>{t('findReplace.replaceWith')}</span>
108
108
  <input type="text" bind:value={replaceText} onkeydown={onKey} spellcheck="false" autocomplete="off" />
109
109
  </label>
110
110
  <div class="checks">
111
- <label class="check"><input type="checkbox" bind:checked={matchCase} /> Match case</label>
112
- <label class="check"><input type="checkbox" bind:checked={entireCell} /> Match entire cell contents</label>
111
+ <label class="check"><input type="checkbox" bind:checked={matchCase} /> {t('findReplace.matchCase')}</label>
112
+ <label class="check"><input type="checkbox" bind:checked={entireCell} /> {t('findReplace.entireCell')}</label>
113
113
  <label class="field auto">
114
- <span>Look in:</span>
114
+ <span>{t('findReplace.lookIn')}</span>
115
115
  <select bind:value={lookIn}>
116
- <option value="values">Values</option>
117
- <option value="formulas">Formulas</option>
116
+ <option value="values">{t('findReplace.values')}</option>
117
+ <option value="formulas">{t('findReplace.formulas')}</option>
118
118
  </select>
119
119
  </label>
120
120
  </div>
@@ -122,11 +122,11 @@
122
122
  </div>
123
123
  {#snippet footer()}
124
124
  <div class="sv-sheet-dialog-buttons">
125
- <button type="button" class="btn" onclick={all} disabled={!findText}>Replace All</button>
126
- <button type="button" class="btn" onclick={replace} disabled={!findText}>Replace</button>
127
- <button type="button" class="btn" onclick={countAll} disabled={!findText}>Find All</button>
128
- <button type="button" class="btn primary" onclick={() => next(1)} disabled={!findText}>Find Next</button>
129
- <button type="button" class="btn" onclick={close}>Close</button>
125
+ <button type="button" class="btn" onclick={all} disabled={!findText}>{t('findReplace.replaceAll')}</button>
126
+ <button type="button" class="btn" onclick={replace} disabled={!findText}>{t('findReplace.replace')}</button>
127
+ <button type="button" class="btn" onclick={countAll} disabled={!findText}>{t('findReplace.findAll')}</button>
128
+ <button type="button" class="btn primary" onclick={() => next(1)} disabled={!findText}>{t('findReplace.findNext')}</button>
129
+ <button type="button" class="btn" onclick={close}>{t('close')}</button>
130
130
  </div>
131
131
  {/snippet}
132
132
  </SvModal>
@@ -9,9 +9,13 @@
9
9
  * The shell opens it for Ctrl+1, the group launchers on the ribbon, the
10
10
  * cell menu's Format Cells... and the `format-cells` action.
11
11
  */
12
+ import { useSheetText } from './sheet-text'
12
13
  import { SvModal } from '@svgrid/grid'
13
14
  import type { CellFormatEntry } from './sheet/format-store'
14
- import { compileNumberFormat, FORMAT_PRESETS, formatCategory } from './sheet/number-format'
15
+ import {
16
+ compileNumberFormat, FORMAT_PRESETS, SPECIAL_FORMATS, formatCategory, accountingPattern, accountingParts,
17
+ type SpecialFormatName,
18
+ } from './sheet/number-format'
15
19
  import { FONT_FAMILIES, FONT_SIZES, type BorderPreset } from './sheet/ribbon'
16
20
  import { ALL_COLOURS } from './sheet/palette'
17
21
 
@@ -29,37 +33,52 @@
29
33
  }
30
34
 
31
35
  let { open = $bindable(false), entry, sample, mixedLocked = false, onApply, onClose }: Props = $props()
36
+ const t = useSheetText()
32
37
 
33
38
  type Tab = 'number' | 'alignment' | 'font' | 'border' | 'fill' | 'protection'
34
39
  const TABS: ReadonlyArray<{ id: Tab; label: string }> = [
35
- { id: 'number', label: 'Number' },
36
- { id: 'alignment', label: 'Alignment' },
37
- { id: 'font', label: 'Font' },
38
- { id: 'border', label: 'Border' },
39
- { id: 'fill', label: 'Fill' },
40
- { id: 'protection', label: 'Protection' },
40
+ { id: 'number', label: 'formatCells.tab.number' },
41
+ { id: 'alignment', label: 'formatCells.tab.alignment' },
42
+ { id: 'font', label: 'formatCells.tab.font' },
43
+ { id: 'border', label: 'formatCells.tab.border' },
44
+ { id: 'fill', label: 'formatCells.tab.fill' },
45
+ { id: 'protection', label: 'formatCells.tab.protection' },
41
46
  ]
42
47
  let tab = $state<Tab>('number')
43
48
 
44
- type Category = 'general' | 'number' | 'currency' | 'percent' | 'date' | 'time' | 'scientific' | 'custom'
49
+ type Category = 'general' | 'number' | 'currency' | 'accounting' | 'percent' | 'date' | 'time' | 'scientific' | 'special' | 'custom'
45
50
  const CATEGORIES: ReadonlyArray<{ id: Category; label: string }> = [
46
- { id: 'general', label: 'General' },
47
- { id: 'number', label: 'Number' },
48
- { id: 'currency', label: 'Currency' },
49
- { id: 'percent', label: 'Percentage' },
50
- { id: 'date', label: 'Date' },
51
- { id: 'time', label: 'Time' },
52
- { id: 'scientific', label: 'Scientific' },
53
- { id: 'custom', label: 'Custom' },
51
+ { id: 'general', label: 'formatCells.category.general' },
52
+ { id: 'number', label: 'formatCells.category.number' },
53
+ { id: 'currency', label: 'formatCells.category.currency' },
54
+ { id: 'accounting', label: 'formatCells.category.accounting' },
55
+ { id: 'percent', label: 'formatCells.category.percent' },
56
+ { id: 'date', label: 'formatCells.category.date' },
57
+ { id: 'time', label: 'formatCells.category.time' },
58
+ { id: 'scientific', label: 'formatCells.category.scientific' },
59
+ { id: 'special', label: 'formatCells.category.special' },
60
+ { id: 'custom', label: 'formatCells.category.custom' },
54
61
  ]
62
+ /** Excel's symbol list, the short one. An empty value is its "None". */
63
+ const SYMBOLS: ReadonlyArray<{ value: string; label: string }> = [
64
+ { value: '$', label: '$' },
65
+ { value: '', label: 'formatCells.symbol.none' },
66
+ { value: '\u20ac', label: 'formatCells.symbol.euro' },
67
+ { value: '\u00a3', label: 'formatCells.symbol.pound' },
68
+ { value: '\u00a5', label: 'formatCells.symbol.yen' },
69
+ ]
70
+ const SPECIALS = Object.keys(SPECIAL_FORMATS) as SpecialFormatName[]
55
71
 
56
72
  // Number
57
73
  let category = $state<Category>('general')
58
74
  let decimals = $state(2)
59
75
  let thousands = $state(true)
76
+ let symbol = $state('$')
77
+ let special = $state<SpecialFormatName>('zip')
60
78
  let custom = $state('')
61
79
  // Alignment
62
80
  let align = $state<'' | 'left' | 'center' | 'right'>('')
81
+ let valign = $state<'top' | 'center' | 'bottom'>('center')
63
82
  let wrap = $state(false)
64
83
  let indent = $state(0)
65
84
  // Font
@@ -95,6 +114,8 @@
95
114
  case 'general': return undefined
96
115
  case 'number': return `${thousands ? '#,##' : ''}0${zeros(decimals)}`
97
116
  case 'currency': return `$#,##0${zeros(decimals)};($#,##0${zeros(decimals)})`
117
+ case 'accounting': return accountingPattern(symbol, decimals)
118
+ case 'special': return SPECIAL_FORMATS[special].pattern
98
119
  case 'percent': return `0${zeros(decimals)}%`
99
120
  case 'date': return FORMAT_PRESETS.date
100
121
  case 'time': return FORMAT_PRESETS.time
@@ -117,8 +138,11 @@
117
138
  category = num.category
118
139
  decimals = num.decimals
119
140
  thousands = num.thousands
141
+ symbol = accountingParts(initial.numFmt)?.symbol ?? '$'
142
+ special = SPECIALS.find((id) => SPECIAL_FORMATS[id].pattern === initial.numFmt) ?? 'zip'
120
143
  custom = initial.numFmt ?? ''
121
144
  align = initial.align ?? ''
145
+ valign = initial.valign ?? 'center'
122
146
  wrap = initial.wrap ?? false
123
147
  indent = initial.indent ?? 0
124
148
  fontFamily = initial.fontFamily ?? ''
@@ -143,6 +167,9 @@
143
167
  }
144
168
  set('numFmt', pattern)
145
169
  set('align', align || undefined)
170
+ // Middle is the default the sheet already draws, so only top and bottom
171
+ // are stored, the way an unset field means "as it was".
172
+ set('valign', valign === 'center' ? undefined : valign)
146
173
  set('wrap', wrap || undefined)
147
174
  set('indent', indent > 0 ? indent : undefined)
148
175
  set('fontFamily', fontFamily || undefined)
@@ -170,29 +197,29 @@
170
197
  }
171
198
 
172
199
  const BORDERS: ReadonlyArray<{ value: BorderPreset; label: string }> = [
173
- { value: 'none', label: 'None' },
174
- { value: 'outside', label: 'Outline' },
175
- { value: 'all', label: 'All borders' },
176
- { value: 'top', label: 'Top' },
177
- { value: 'bottom', label: 'Bottom' },
178
- { value: 'left', label: 'Left' },
179
- { value: 'right', label: 'Right' },
180
- { value: 'thick-bottom', label: 'Thick bottom' },
200
+ { value: 'none', label: 'formatCells.border.none' },
201
+ { value: 'outside', label: 'formatCells.border.outside' },
202
+ { value: 'all', label: 'formatCells.border.all' },
203
+ { value: 'top', label: 'formatCells.border.top' },
204
+ { value: 'bottom', label: 'formatCells.border.bottom' },
205
+ { value: 'left', label: 'formatCells.border.left' },
206
+ { value: 'right', label: 'formatCells.border.right' },
207
+ { value: 'thick-bottom', label: 'formatCells.border.thick-bottom' },
181
208
  ]
182
209
  </script>
183
210
 
184
- <SvModal bind:open onClose={onClose} title="Format Cells" size="md">
185
- <div class="sv-sheet-dialog format" role="group" aria-label="Format Cells">
186
- <div class="tabs" role="tablist" aria-label="Format Cells tabs">
187
- {#each TABS as t (t.id)}
211
+ <SvModal bind:open onClose={onClose} title={t('formatCells.title')} size="md">
212
+ <div class="sv-sheet-dialog format" role="group" aria-label={t('formatCells.title')}>
213
+ <div class="tabs" role="tablist" aria-label={t('formatCells.tabs')}>
214
+ {#each TABS as tabEntry (tabEntry.id)}
188
215
  <button
189
216
  type="button"
190
217
  role="tab"
191
218
  class="tab"
192
- class:on={tab === t.id}
193
- aria-selected={tab === t.id}
194
- onclick={() => (tab = t.id)}
195
- >{t.label}</button>
219
+ class:on={tab === tabEntry.id}
220
+ aria-selected={tab === tabEntry.id}
221
+ onclick={() => (tab = tabEntry.id)}
222
+ >{t(tabEntry.label)}</button>
196
223
  {/each}
197
224
  </div>
198
225
 
@@ -200,65 +227,82 @@
200
227
  {#if tab === 'number'}
201
228
  <div class="number">
202
229
  <div class="categories">
203
- <div class="label">Category:</div>
204
- <ul role="listbox" aria-label="Category">
230
+ <div class="label">{t('formatCells.category')}</div>
231
+ <ul role="listbox" aria-label={t('formatCells.categoryList')}>
205
232
  {#each CATEGORIES as c (c.id)}
206
233
  <!-- svelte-ignore a11y_click_events_have_key_events, a11y_no_noninteractive_element_interactions -->
207
- <li role="option" aria-selected={category === c.id} class:selected={category === c.id} onclick={() => (category = c.id)}>{c.label}</li>
234
+ <li role="option" aria-selected={category === c.id} class:selected={category === c.id} onclick={() => (category = c.id)}>{t(c.label)}</li>
208
235
  {/each}
209
236
  </ul>
210
237
  </div>
211
238
  <div class="settings">
212
239
  <div class="sample">
213
- <div class="label">Sample</div>
240
+ <div class="label">{t('formatCells.sample')}</div>
214
241
  <div class="sample-text">{preview}</div>
215
242
  </div>
216
- {#if category === 'number' || category === 'currency' || category === 'percent' || category === 'scientific'}
243
+ {#if category === 'number' || category === 'currency' || category === 'accounting' || category === 'percent' || category === 'scientific'}
217
244
  <label class="field auto">
218
- <span>Decimal places:</span>
245
+ <span>{t('formatCells.decimalPlaces')}</span>
219
246
  <input type="number" min="0" max="10" bind:value={decimals} />
220
247
  </label>
221
248
  {/if}
222
249
  {#if category === 'number'}
223
- <label class="check"><input type="checkbox" bind:checked={thousands} /> Use 1000 separator (,)</label>
250
+ <label class="check"><input type="checkbox" bind:checked={thousands} /> {t('formatCells.thousands')}</label>
251
+ {/if}
252
+ {#if category === 'accounting'}
253
+ <label class="field auto">
254
+ <span>{t('formatCells.symbol')}</span>
255
+ <select bind:value={symbol}>
256
+ {#each SYMBOLS as sy (sy.value)}<option value={sy.value}>{sy.value === '$' ? sy.label : t(sy.label)}</option>{/each}
257
+ </select>
258
+ </label>
259
+ {/if}
260
+ {#if category === 'special'}
261
+ <label class="field auto">
262
+ <span>{t('formatCells.type')}</span>
263
+ <select bind:value={special}>
264
+ {#each SPECIALS as id (id)}<option value={id}>{t(`formatCells.special.${id}`)}</option>{/each}
265
+ </select>
266
+ </label>
224
267
  {/if}
225
268
  {#if category === 'custom'}
226
269
  <label class="field auto">
227
- <span>Type:</span>
270
+ <span>{t('formatCells.type')}</span>
228
271
  <input type="text" bind:value={custom} spellcheck="false" placeholder="#,##0.00" />
229
272
  </label>
230
273
  {/if}
231
274
  <p class="hint">
232
- {#if category === 'general'}General format cells have no specific number format.
233
- {:else if category === 'number'}Number is used for general display of numbers.
234
- {:else if category === 'currency'}Currency formats are used for general monetary values.
235
- {:else if category === 'percent'}Percentage formats multiply the cell value by 100 and display the result with a percent symbol.
236
- {:else if category === 'date'}Date formats display date serial numbers as dates.
237
- {:else if category === 'time'}Time formats display date serial numbers as times.
238
- {:else if category === 'scientific'}Scientific formats display numbers in exponential notation.
239
- {:else}Type the number format code, using one of the existing codes as a starting point.{/if}
275
+ {t(`formatCells.hint.${category}`)}
240
276
  </p>
241
277
  </div>
242
278
  </div>
243
279
  {:else if tab === 'alignment'}
244
280
  <label class="field">
245
- <span>Horizontal:</span>
281
+ <span>{t('formatCells.horizontal')}</span>
246
282
  <select bind:value={align}>
247
- <option value="">General</option>
248
- <option value="left">Left (Indent)</option>
249
- <option value="center">Center</option>
250
- <option value="right">Right (Indent)</option>
283
+ <option value="">{t('formatCells.align.general')}</option>
284
+ <option value="left">{t('formatCells.align.left')}</option>
285
+ <option value="center">{t('formatCells.align.center')}</option>
286
+ <option value="right">{t('formatCells.align.right')}</option>
287
+ </select>
288
+ </label>
289
+ <label class="field">
290
+ <span>{t('formatCells.vertical')}</span>
291
+ <select bind:value={valign}>
292
+ <option value="top">{t('formatCells.valign.top')}</option>
293
+ <option value="center">{t('formatCells.valign.center')}</option>
294
+ <option value="bottom">{t('formatCells.valign.bottom')}</option>
251
295
  </select>
252
296
  </label>
253
297
  <label class="field">
254
- <span>Indent:</span>
298
+ <span>{t('formatCells.indent')}</span>
255
299
  <input type="number" min="0" max="15" bind:value={indent} />
256
300
  </label>
257
- <div class="label">Text control</div>
258
- <label class="check"><input type="checkbox" bind:checked={wrap} /> Wrap text</label>
301
+ <div class="label">{t('formatCells.textControl')}</div>
302
+ <label class="check"><input type="checkbox" bind:checked={wrap} /> {t('formatCells.wrap')}</label>
259
303
  {:else if tab === 'font'}
260
304
  <label class="field">
261
- <span>Font:</span>
305
+ <span>{t('formatCells.font')}</span>
262
306
  <select bind:value={fontFamily}>
263
307
  {#each FONT_FAMILIES as f (f.value)}
264
308
  <option value={f.value}>{f.label}</option>
@@ -266,49 +310,49 @@
266
310
  </select>
267
311
  </label>
268
312
  <label class="field">
269
- <span>Size:</span>
313
+ <span>{t('formatCells.size')}</span>
270
314
  <select bind:value={fontSize}>
271
- <option value="">Default</option>
315
+ <option value="">{t('formatCells.sizeDefault')}</option>
272
316
  {#each FONT_SIZES as s (s)}
273
317
  <option value={String(s)}>{s}</option>
274
318
  {/each}
275
319
  </select>
276
320
  </label>
277
- <div class="label">Font style</div>
321
+ <div class="label">{t('formatCells.fontStyle')}</div>
278
322
  <div class="checks">
279
- <label class="check"><input type="checkbox" bind:checked={bold} /> Bold</label>
280
- <label class="check"><input type="checkbox" bind:checked={italic} /> Italic</label>
281
- <label class="check"><input type="checkbox" bind:checked={underline} /> Underline</label>
282
- <label class="check"><input type="checkbox" bind:checked={strike} /> Strikethrough</label>
323
+ <label class="check"><input type="checkbox" bind:checked={bold} /> {t('formatCells.bold')}</label>
324
+ <label class="check"><input type="checkbox" bind:checked={italic} /> {t('formatCells.italic')}</label>
325
+ <label class="check"><input type="checkbox" bind:checked={underline} /> {t('formatCells.underline')}</label>
326
+ <label class="check"><input type="checkbox" bind:checked={strike} /> {t('formatCells.strikethrough')}</label>
283
327
  </div>
284
- <div class="label">Color</div>
328
+ <div class="label">{t('formatCells.color')}</div>
285
329
  <div class="checks">
286
- <label class="check"><input type="checkbox" bind:checked={colorAuto} /> Automatic</label>
287
- <input type="color" bind:value={color} disabled={colorAuto} aria-label="Font colour" />
330
+ <label class="check"><input type="checkbox" bind:checked={colorAuto} /> {t('formatCells.automatic')}</label>
331
+ <input type="color" bind:value={color} disabled={colorAuto} aria-label={t('formatCells.fontColor')} />
288
332
  </div>
289
333
  <div class="font-preview" style:font-family={fontFamily || undefined} style:font-size={fontSize ? `${fontSize}px` : undefined} style:font-weight={bold ? 700 : 400} style:font-style={italic ? 'italic' : 'normal'} style:text-decoration={[underline ? 'underline' : '', strike ? 'line-through' : ''].join(' ').trim() || 'none'} style:color={colorAuto ? undefined : color}>AaBbCcYyZz</div>
290
334
  {:else if tab === 'border'}
291
- <div class="label">Presets</div>
292
- <div class="borders" role="radiogroup" aria-label="Border">
293
- <label class="check"><input type="radio" name="sheet-border" value="" bind:group={border} /> Keep as is</label>
335
+ <div class="label">{t('formatCells.presets')}</div>
336
+ <div class="borders" role="radiogroup" aria-label={t('formatCells.borderGroup')}>
337
+ <label class="check"><input type="radio" name="sheet-border" value="" bind:group={border} /> {t('formatCells.keepAsIs')}</label>
294
338
  {#each BORDERS as b (b.value)}
295
- <label class="check"><input type="radio" name="sheet-border" value={b.value} bind:group={border} /> {b.label}</label>
339
+ <label class="check"><input type="radio" name="sheet-border" value={b.value} bind:group={border} /> {t(b.label)}</label>
296
340
  {/each}
297
341
  </div>
298
- <p class="hint">Bottom, top, left and right go on the edge of the selection; All borders lines every cell; Outline frames the block.</p>
342
+ <p class="hint">{t('formatCells.borderHint')}</p>
299
343
  {:else if tab === 'fill'}
300
- <div class="label">Background Color</div>
344
+ <div class="label">{t('formatCells.backgroundColor')}</div>
301
345
  <div class="no-fill">
302
- <button type="button" class="swatch none" class:on={fill === null} aria-label="No Color" title="No Color" onclick={() => (fill = null)}></button>
303
- <span>No Color</span>
346
+ <button type="button" class="swatch none" class:on={fill === null} aria-label={t('formatCells.noColor')} title={t('formatCells.noColor')} onclick={() => (fill = null)}></button>
347
+ <span>{t('formatCells.noColor')}</span>
304
348
  </div>
305
- <div class="swatches" role="radiogroup" aria-label="Fill colour">
349
+ <div class="swatches" role="radiogroup" aria-label={t('formatCells.fillGroup')}>
306
350
  {#each ALL_COLOURS as c, i (i)}
307
351
  <button type="button" class="swatch" class:on={fill === c.value} style:background={c.value} aria-label={c.label} title={c.label} onclick={() => (fill = c.value)}></button>
308
352
  {/each}
309
353
  </div>
310
354
  <div class="sample">
311
- <div class="label">Sample</div>
355
+ <div class="label">{t('formatCells.sample')}</div>
312
356
  <div class="fill-sample" style:background={fill ?? 'transparent'}></div>
313
357
  </div>
314
358
  {:else if tab === 'protection'}
@@ -319,16 +363,16 @@
319
363
  indeterminate={locked === null}
320
364
  onchange={(e) => (locked = (e.currentTarget as HTMLInputElement).checked)}
321
365
  />
322
- Locked
366
+ {t('formatCells.locked')}
323
367
  </label>
324
- <p class="hint">Locking cells has no effect until you protect the sheet (Review tab, Protect Sheet). Every cell is locked to begin with; unlock the ones that may change, then protect the sheet.</p>
368
+ <p class="hint">{t('formatCells.lockedHint')}</p>
325
369
  {/if}
326
370
  </div>
327
371
  </div>
328
372
  {#snippet footer()}
329
373
  <div class="sv-sheet-dialog-buttons">
330
- <button type="button" class="btn primary" onclick={ok}>OK</button>
331
- <button type="button" class="btn" onclick={close}>Cancel</button>
374
+ <button type="button" class="btn primary" onclick={ok}>{t('ok')}</button>
375
+ <button type="button" class="btn" onclick={close}>{t('cancel')}</button>
332
376
  </div>
333
377
  {/snippet}
334
378
  </SvModal>
@@ -5,6 +5,7 @@
5
5
  * page shows what it found; OK keeps the answer through the command
6
6
  * context, so it lands in the grid's history like a typed number.
7
7
  */
8
+ import { useSheetText } from './sheet-text'
8
9
  import { untrack } from 'svelte'
9
10
  import { SvModal } from '@svgrid/grid'
10
11
  import type { GridCommandContext } from '@svgrid/grid/shortcuts'
@@ -21,6 +22,7 @@
21
22
  }
22
23
 
23
24
  let { open = $bindable(false), workbook, cmd, onClose }: Props = $props()
25
+ const t = useSheetText()
24
26
 
25
27
  let step = $state<'ask' | 'done'>('ask')
26
28
  let setCell = $state('')
@@ -56,12 +58,12 @@
56
58
  const formula = address(setCell)
57
59
  const input = address(byCell)
58
60
  const target = Number(toValue)
59
- if (!formula) { problem = `"${setCell}" is not a cell address`; return }
60
- if (!input) { problem = `"${byCell}" is not a cell address`; return }
61
- if (toValue.trim() === '' || !Number.isFinite(target)) { problem = 'To value must be a number'; return }
61
+ if (!formula) { problem = t('goalSeek.notAddress', { text: setCell }); return }
62
+ if (!input) { problem = t('goalSeek.notAddress', { text: byCell }); return }
63
+ if (toValue.trim() === '' || !Number.isFinite(target)) { problem = t('goalSeek.toValueNumber'); return }
62
64
  const sheet = workbook.active
63
65
  if (!workbook.getRaw(sheet, formula.row, formula.col).startsWith('=')) {
64
- problem = `${setCell.toUpperCase()} must contain a formula`
66
+ problem = t('goalSeek.needsFormula', { cell: setCell.toUpperCase() })
65
67
  return
66
68
  }
67
69
  if (workbook.getRaw(sheet, input.row, input.col).startsWith('=')) {
@@ -91,19 +93,19 @@
91
93
  const money = (n: number) => n.toLocaleString('en-US', { maximumFractionDigits: 2 })
92
94
  </script>
93
95
 
94
- <SvModal bind:open onClose={onClose} title={step === 'ask' ? 'Goal Seek' : 'Goal Seek Status'} size="sm">
96
+ <SvModal bind:open onClose={onClose} title={t(step === 'ask' ? 'goalSeek.title' : 'goalSeek.statusTitle')} size="sm">
95
97
  {#if step === 'ask'}
96
98
  <form class="sv-sheet-dialog" onsubmit={(e) => { e.preventDefault(); solve() }}>
97
99
  <label class="field">
98
- <span>Set cell:</span>
100
+ <span>{t('goalSeek.setCell')}</span>
99
101
  <input bind:this={firstInput} type="text" bind:value={setCell} spellcheck="false" />
100
102
  </label>
101
103
  <label class="field">
102
- <span>To value:</span>
104
+ <span>{t('goalSeek.toValue')}</span>
103
105
  <input type="text" bind:value={toValue} inputmode="decimal" />
104
106
  </label>
105
107
  <label class="field">
106
- <span>By changing cell:</span>
108
+ <span>{t('goalSeek.byChanging')}</span>
107
109
  <input type="text" bind:value={byCell} spellcheck="false" />
108
110
  </label>
109
111
  {#if problem}<p class="status problem" role="alert">{problem}</p>{/if}
@@ -111,21 +113,20 @@
111
113
  {:else if found}
112
114
  <div class="sv-sheet-dialog">
113
115
  <p class="lead">
114
- Goal Seeking with Cell <strong>{setCell.toUpperCase()}</strong>
115
- {found.converged ? 'found a solution.' : 'may not have found a solution.'}
116
+ {t(found.converged ? 'goalSeek.found' : 'goalSeek.notFound', { cell: setCell.toUpperCase() })}
116
117
  </p>
117
118
  <dl class="facts">
118
- <dt>Target value:</dt><dd>{money(Number(toValue))}</dd>
119
- <dt>Current value:</dt><dd>{money(found.result)}</dd>
120
- <dt>{byCell.toUpperCase()} becomes:</dt><dd>{money(round(found.value))}</dd>
119
+ <dt>{t('goalSeek.target')}</dt><dd>{money(Number(toValue))}</dd>
120
+ <dt>{t('goalSeek.current')}</dt><dd>{money(found.result)}</dd>
121
+ <dt>{t('goalSeek.becomes', { cell: byCell.toUpperCase() })}</dt><dd>{money(round(found.value))}</dd>
121
122
  </dl>
122
- <p class="status">{found.iterations} iterations.</p>
123
+ <p class="status">{t('goalSeek.iterations', { count: found.iterations })}</p>
123
124
  </div>
124
125
  {/if}
125
126
  {#snippet footer()}
126
127
  <div class="sv-sheet-dialog-buttons">
127
- <button type="button" class="btn primary" onclick={step === 'ask' ? solve : keep}>OK</button>
128
- <button type="button" class="btn" onclick={close}>Cancel</button>
128
+ <button type="button" class="btn primary" onclick={step === 'ask' ? solve : keep}>{t('ok')}</button>
129
+ <button type="button" class="btn" onclick={close}>{t('cancel')}</button>
129
130
  </div>
130
131
  {/snippet}
131
132
  </SvModal>
@@ -7,6 +7,7 @@
7
7
  * Function Arguments dialog; typing the arguments in place with the
8
8
  * signature shown is the same information with less chrome.
9
9
  */
10
+ import { useSheetText } from './sheet-text'
10
11
  import { SvModal } from '@svgrid/grid'
11
12
  import { functionCatalog, FUNCTION_GROUPS, type FunctionGroup, type FunctionInfo } from './sheet/function-catalog'
12
13
 
@@ -17,6 +18,7 @@
17
18
  }
18
19
 
19
20
  let { open = $bindable(false), onPick, onClose }: Props = $props()
21
+ const t = useSheetText()
20
22
 
21
23
  const all = functionCatalog()
22
24
  let search = $state('')
@@ -69,24 +71,24 @@
69
71
  }
70
72
  </script>
71
73
 
72
- <SvModal bind:open onClose={onClose} title="Insert Function" size="md">
73
- <div class="sv-sheet-dialog insert" role="group" aria-label="Insert Function">
74
+ <SvModal bind:open onClose={onClose} title={t('insertFunction.title')} size="md">
75
+ <div class="sv-sheet-dialog insert" role="group" aria-label={t('insertFunction.title')}>
74
76
  <label class="field">
75
- <span>Search for a function:</span>
76
- <input bind:this={searchInput} type="text" bind:value={search} onkeydown={onListKey} spellcheck="false" autocomplete="off" placeholder="Type a name or what you want to do" />
77
+ <span>{t('insertFunction.search')}</span>
78
+ <input bind:this={searchInput} type="text" bind:value={search} onkeydown={onListKey} spellcheck="false" autocomplete="off" placeholder={t('insertFunction.searchPlaceholder')} />
77
79
  </label>
78
80
  <label class="field">
79
- <span>Or select a category:</span>
81
+ <span>{t('insertFunction.category')}</span>
80
82
  <select bind:value={group}>
81
- <option value="All">All</option>
83
+ <option value="All">{t('insertFunction.all')}</option>
82
84
  {#each FUNCTION_GROUPS as g (g)}
83
- <option value={g}>{g}</option>
85
+ <option value={g}>{t(`insertFunction.group.${g}`)}</option>
84
86
  {/each}
85
87
  </select>
86
88
  </label>
87
- <div class="label">Select a function:</div>
89
+ <div class="label">{t('insertFunction.select')}</div>
88
90
  <!-- svelte-ignore a11y_no_noninteractive_tabindex -->
89
- <ul class="list" role="listbox" aria-label="Functions" tabindex="0" onkeydown={onListKey}>
91
+ <ul class="list" role="listbox" aria-label={t('insertFunction.functions')} tabindex="0" onkeydown={onListKey}>
90
92
  {#each shown as fn (fn.name)}
91
93
  <!-- svelte-ignore a11y_click_events_have_key_events, a11y_no_noninteractive_element_interactions -->
92
94
  <li
@@ -97,20 +99,20 @@
97
99
  ondblclick={ok}
98
100
  >{fn.name}</li>
99
101
  {:else}
100
- <li class="empty">No function matches.</li>
102
+ <li class="empty">{t('insertFunction.noMatch')}</li>
101
103
  {/each}
102
104
  </ul>
103
105
  {#if current}
104
106
  <div class="about">
105
107
  <div class="signature">{current.signature}</div>
106
- <div class="description">{current.description || 'No description.'}</div>
108
+ <div class="description">{current.description || t('insertFunction.noDescription')}</div>
107
109
  </div>
108
110
  {/if}
109
111
  </div>
110
112
  {#snippet footer()}
111
113
  <div class="sv-sheet-dialog-buttons">
112
- <button type="button" class="btn primary" onclick={ok} disabled={!current}>OK</button>
113
- <button type="button" class="btn" onclick={close}>Cancel</button>
114
+ <button type="button" class="btn primary" onclick={ok} disabled={!current}>{t('ok')}</button>
115
+ <button type="button" class="btn" onclick={close}>{t('cancel')}</button>
114
116
  </div>
115
117
  {/snippet}
116
118
  </SvModal>