@svgrid/enterprise 3.0.2 → 3.1.0
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.
- package/LICENSE +94 -24
- package/README.md +36 -4
- package/dist/SvAdvancedFilter.svelte +1 -1
- package/dist/SvAlertsManager.svelte +2 -1
- package/dist/SvBoard.svelte +2 -1
- package/dist/SvExportMenu.svelte +4 -1
- package/dist/SvExportMenu.svelte.d.ts +0 -13
- package/dist/SvExpressionEditor.svelte +3 -3
- package/dist/SvFormulaBar.svelte +94 -20
- package/dist/SvFormulaBar.svelte.d.ts +7 -0
- package/dist/SvGridAlerts.svelte +49 -9
- package/dist/SvGridBoard.svelte +13 -8
- package/dist/SvGridBulkEditDrawer.svelte +26 -2
- package/dist/SvGridEditPanel.svelte +3 -0
- package/dist/SvGridScheduler.svelte +69 -40
- package/dist/SvGridSelectionBar.svelte +10 -3
- package/dist/SvPivotDesigner.svelte +198 -40
- package/dist/SvPivotDesigner.svelte.d.ts +27 -20
- package/dist/SvSheet.svelte +4043 -243
- package/dist/SvSheet.svelte.d.ts +76 -3
- package/dist/SvSheetChartSetup.svelte +151 -0
- package/dist/SvSheetChartSetup.svelte.d.ts +18 -0
- package/dist/SvSheetComment.svelte +216 -31
- package/dist/SvSheetComment.svelte.d.ts +11 -11
- package/dist/SvSheetConditionalFormat.svelte +28 -31
- package/dist/SvSheetDataValidation.svelte +66 -42
- package/dist/SvSheetEditRanges.svelte +217 -0
- package/dist/SvSheetEditRanges.svelte.d.ts +15 -0
- package/dist/SvSheetErrors.svelte +125 -0
- package/dist/SvSheetErrors.svelte.d.ts +20 -0
- package/dist/SvSheetEvaluate.svelte +133 -0
- package/dist/SvSheetEvaluate.svelte.d.ts +15 -0
- package/dist/SvSheetFilterMenu.svelte +137 -34
- package/dist/SvSheetFilterMenu.svelte.d.ts +5 -0
- package/dist/SvSheetFindReplace.svelte +19 -19
- package/dist/SvSheetFormatCells.svelte +125 -81
- package/dist/SvSheetGoalSeek.svelte +17 -16
- package/dist/SvSheetInsertFunction.svelte +15 -13
- package/dist/SvSheetIteration.svelte +81 -0
- package/dist/SvSheetIteration.svelte.d.ts +10 -0
- package/dist/SvSheetLink.svelte +99 -0
- package/dist/SvSheetLink.svelte.d.ts +17 -0
- package/dist/SvSheetListPicker.svelte +4 -2
- package/dist/SvSheetListPicker.svelte.d.ts +0 -6
- package/dist/SvSheetManageRules.svelte +20 -18
- package/dist/SvSheetNameManager.svelte +17 -15
- package/dist/SvSheetPageSetup.svelte +159 -0
- package/dist/SvSheetPageSetup.svelte.d.ts +13 -0
- package/dist/SvSheetPasteSpecial.svelte +22 -20
- package/dist/SvSheetPivot.svelte +220 -0
- package/dist/SvSheetPivot.svelte.d.ts +21 -0
- package/dist/SvSheetProtectSheet.svelte +81 -0
- package/dist/SvSheetProtectSheet.svelte.d.ts +11 -0
- package/dist/SvSheetRemoveDuplicates.svelte +13 -10
- package/dist/SvSheetRibbon.svelte +104 -51
- package/dist/SvSheetSizeDialog.svelte +4 -2
- package/dist/SvSheetSort.svelte +218 -0
- package/dist/SvSheetSort.svelte.d.ts +28 -0
- package/dist/SvSheetSparklines.svelte +135 -0
- package/dist/SvSheetSparklines.svelte.d.ts +14 -0
- package/dist/SvSheetTable.svelte +160 -0
- package/dist/SvSheetTable.svelte.d.ts +24 -0
- package/dist/SvSheetTabs.svelte +161 -31
- package/dist/SvSheetTabs.svelte.d.ts +22 -8
- package/dist/SvSheetTextToColumns.svelte +20 -20
- package/dist/SvSheetValidationAlert.svelte +8 -6
- package/dist/advanced-filter-enable.js +1 -1
- package/dist/alerts/alert-engine.d.ts +6 -0
- package/dist/alerts/alert-engine.js +21 -4
- package/dist/alerts/alert-formats.js +2 -0
- package/dist/alerts/alert-types.d.ts +1 -1
- package/dist/alerts.d.ts +1 -1
- package/dist/alerts.js +2 -2
- package/dist/board.js +2 -2
- package/dist/bulk-edit.d.ts +3 -1
- package/dist/bulk-edit.js +1 -1
- package/dist/cdn/svgrid-enterprise.svelte-external.js +39827 -16429
- package/dist/designer/assets/GridMenus-8gTNssgV.js +8 -0
- package/dist/designer/assets/{SvChartMenu-D9hEeHar.js → SvChartMenu-BDoeqGz6.js} +1 -1
- package/dist/designer/assets/{SvDateTimePicker-DARvKUL2.js → SvDateTimePicker-DCPg7WGN.js} +1 -1
- package/dist/designer/assets/SvGridCellEditor-DMoWJjEI.js +4 -0
- package/dist/designer/assets/{SvGridChart-B8j1SSy3.js → SvGridChart-Cy1ATrWh.js} +2 -2
- package/dist/designer/assets/SvGridChartBuilder-eQ3mn0L9.js +1 -0
- package/dist/designer/assets/{SvGridChartPanel-pT6ITc2P.js → SvGridChartPanel-CATdVc9X.js} +3 -3
- package/dist/designer/assets/{SvGridChartView-bg281UA1.js → SvGridChartView-CmsZtCED.js} +1 -1
- package/dist/designer/assets/SvGridDropdown-Cjz0H-fI.js +1 -0
- package/dist/designer/assets/{SvTabs-UFCMTHXS.js → SvTabs-2mHC6oaz.js} +1 -1
- package/dist/designer/assets/cell-formatting-BbubJTVz.js +1 -0
- package/dist/designer/assets/{chart-cIPUsbM5.js → chart-Cn7MnNqA.js} +1 -1
- package/dist/designer/assets/{chart-panel-messages-DtTxpBUU.js → chart-panel-messages-Dz7PTIqT.js} +1 -1
- package/dist/designer/assets/{chart-summary-Czu_5epb.js → chart-summary-BD1qYB2R.js} +1 -1
- package/dist/designer/assets/{chart-trend-D5I5VEe8.js → chart-trend-B8xr5LuD.js} +1 -1
- package/dist/designer/assets/{dismissable-BO547MH9.js → dismissable-ChWRPkoa.js} +1 -1
- package/dist/designer/assets/{export-format-D-eP4b2l.js → export-format-DGckmgKr.js} +1 -1
- package/dist/designer/assets/{focus-trap-CAreAhlU.js → focus-trap-V2-6Fy9I.js} +1 -1
- package/dist/designer/assets/{index-DwU7CAMm.js → index-BSjv6Qec.js} +317 -315
- package/dist/designer/assets/index-_JVFxt02.css +1 -0
- package/dist/designer/assets/row-resize-BInFWCpr.js +1 -0
- package/dist/designer/assets/server-block-cache-CXJKkJpy.js +1 -0
- package/dist/designer/assets/src-DUQ4xE3x.js +58 -0
- package/dist/designer/assets/validate-C3B8QKsM.js +1 -0
- package/dist/designer/index.html +17 -16
- package/dist/export-pdf.d.ts +75 -0
- package/dist/export-pdf.js +216 -15
- package/dist/export.js +10 -2
- package/dist/gantt/SvGridGantt.svelte +2890 -0
- package/dist/gantt/SvGridGantt.svelte.d.ts +30 -0
- package/dist/gantt/gantt-config.d.ts +73 -0
- package/dist/gantt/gantt-config.js +1 -0
- package/dist/gantt/gantt-critical-path.d.ts +67 -0
- package/dist/gantt/gantt-critical-path.js +207 -0
- package/dist/gantt/gantt-model.d.ts +257 -0
- package/dist/gantt/gantt-model.js +651 -0
- package/dist/gantt/gantt-resources.d.ts +59 -0
- package/dist/gantt/gantt-resources.js +71 -0
- package/dist/gantt/gantt.d.ts +7 -0
- package/dist/gantt/gantt.js +36 -0
- package/dist/gantt/index.d.ts +15 -0
- package/dist/gantt/index.js +22 -0
- package/dist/gantt/timeline-arrows.d.ts +102 -0
- package/dist/gantt/timeline-arrows.js +181 -0
- package/dist/import.d.ts +2 -2
- package/dist/import.js +1 -1
- package/dist/index.d.ts +34 -7
- package/dist/index.js +44 -7
- package/dist/install.js +8 -1
- package/dist/license-core.d.ts +17 -1
- package/dist/license-core.js +16 -5
- package/dist/license.d.ts +18 -2
- package/dist/license.js +71 -6
- package/dist/node/studio.js +140 -8
- package/dist/pivot-enable.js +2 -2
- package/dist/scheduler-dependencies.d.ts +35 -0
- package/dist/scheduler-dependencies.js +36 -1
- package/dist/scheduler.js +2 -2
- package/dist/selection-bar.js +2 -2
- package/dist/server/SvGroupCell.svelte +213 -0
- package/dist/server/SvGroupCell.svelte.d.ts +62 -0
- package/dist/server/SvRowGroupPanel.svelte +322 -0
- package/dist/server/SvRowGroupPanel.svelte.d.ts +37 -0
- package/dist/server/enable.d.ts +17 -0
- package/dist/server/enable.js +49 -0
- package/dist/server/index.d.ts +22 -0
- package/dist/server/index.js +24 -0
- package/dist/server/messages.d.ts +45 -0
- package/dist/server/messages.js +35 -0
- package/dist/server/server-group-model.d.ts +104 -0
- package/dist/server/server-group-model.js +272 -0
- package/dist/server/server-pivot.d.ts +46 -0
- package/dist/server/server-pivot.js +57 -0
- package/dist/server/server-row-model.d.ts +547 -0
- package/dist/server/server-row-model.js +1551 -0
- package/dist/server/server-selection.d.ts +99 -0
- package/dist/server/server-selection.js +215 -0
- package/dist/server/svgrid-adapter.d.ts +155 -0
- package/dist/server/svgrid-adapter.js +202 -0
- package/dist/sheet/ast.d.ts +45 -1
- package/dist/sheet/ast.js +14 -0
- package/dist/sheet/auto-filter.d.ts +58 -4
- package/dist/sheet/auto-filter.js +159 -11
- package/dist/sheet/autocomplete.d.ts +9 -0
- package/dist/sheet/autocomplete.js +90 -4
- package/dist/sheet/cell-images.d.ts +39 -0
- package/dist/sheet/cell-images.js +90 -0
- package/dist/sheet/cell-types.d.ts +58 -0
- package/dist/sheet/cell-types.js +96 -0
- package/dist/sheet/coerce.d.ts +40 -0
- package/dist/sheet/coerce.js +170 -3
- package/dist/sheet/comments.d.ts +43 -9
- package/dist/sheet/comments.js +85 -27
- package/dist/sheet/conditional-formats.d.ts +29 -6
- package/dist/sheet/conditional-formats.js +37 -12
- package/dist/sheet/csv.d.ts +32 -0
- package/dist/sheet/csv.js +158 -0
- package/dist/sheet/culture.d.ts +87 -0
- package/dist/sheet/culture.js +247 -0
- package/dist/sheet/delta.d.ts +102 -0
- package/dist/sheet/delta.js +203 -0
- package/dist/sheet/deps.d.ts +45 -1
- package/dist/sheet/deps.js +77 -2
- package/dist/sheet/document.d.ts +106 -4
- package/dist/sheet/document.js +204 -3
- package/dist/sheet/engine.d.ts +67 -0
- package/dist/sheet/engine.js +19 -0
- package/dist/sheet/entry.d.ts +8 -4
- package/dist/sheet/entry.js +171 -21
- package/dist/sheet/error-check.d.ts +49 -0
- package/dist/sheet/error-check.js +83 -0
- package/dist/sheet/evaluate-steps.d.ts +48 -0
- package/dist/sheet/evaluate-steps.js +196 -0
- package/dist/sheet/evaluate.d.ts +67 -0
- package/dist/sheet/evaluate.js +725 -13
- package/dist/sheet/filter-files.d.ts +37 -0
- package/dist/sheet/filter-files.js +465 -0
- package/dist/sheet/format-store.d.ts +15 -0
- package/dist/sheet/format-store.js +11 -1
- package/dist/sheet/from-rows.d.ts +14 -0
- package/dist/sheet/from-rows.js +50 -0
- package/dist/sheet/function-catalog.d.ts +1 -1
- package/dist/sheet/function-catalog.js +296 -5
- package/dist/sheet/functions.js +363 -91
- package/dist/sheet/index.d.ts +35 -8
- package/dist/sheet/index.js +35 -8
- package/dist/sheet/links.d.ts +57 -0
- package/dist/sheet/links.js +174 -0
- package/dist/sheet/messages.d.ts +778 -0
- package/dist/sheet/messages.js +806 -0
- package/dist/sheet/number-format.d.ts +52 -5
- package/dist/sheet/number-format.js +465 -68
- package/dist/sheet/objects.d.ts +106 -0
- package/dist/sheet/objects.js +149 -0
- package/dist/sheet/ods-document.d.ts +44 -0
- package/dist/sheet/ods-document.js +1275 -0
- package/dist/sheet/open-file.d.ts +26 -0
- package/dist/sheet/open-file.js +56 -0
- package/dist/sheet/outline.d.ts +82 -0
- package/dist/sheet/outline.js +228 -0
- package/dist/sheet/packs/array.d.ts +16 -0
- package/dist/sheet/packs/array.js +172 -0
- package/dist/sheet/packs/database.d.ts +42 -0
- package/dist/sheet/packs/database.js +142 -0
- package/dist/sheet/packs/engineering.d.ts +2 -0
- package/dist/sheet/packs/engineering.js +296 -0
- package/dist/sheet/packs/financial.d.ts +5 -0
- package/dist/sheet/packs/financial.js +220 -0
- package/dist/sheet/packs/math-stats.d.ts +2 -0
- package/dist/sheet/packs/math-stats.js +372 -0
- package/dist/sheet/packs/special.d.ts +44 -0
- package/dist/sheet/packs/special.js +187 -0
- package/dist/sheet/packs/stats-dist.d.ts +2 -0
- package/dist/sheet/packs/stats-dist.js +785 -0
- package/dist/sheet/packs/text-date.d.ts +2 -0
- package/dist/sheet/packs/text-date.js +332 -0
- package/dist/sheet/packs/trig.d.ts +2 -0
- package/dist/sheet/packs/trig.js +73 -0
- package/dist/sheet/page-setup.d.ts +73 -0
- package/dist/sheet/page-setup.js +73 -0
- package/dist/sheet/parse.js +42 -10
- package/dist/sheet/paste-special.d.ts +22 -0
- package/dist/sheet/paste-special.js +14 -5
- package/dist/sheet/pivot-range.d.ts +160 -0
- package/dist/sheet/pivot-range.js +333 -0
- package/dist/sheet/presence.d.ts +73 -0
- package/dist/sheet/presence.js +79 -0
- package/dist/sheet/print.d.ts +104 -0
- package/dist/sheet/print.js +169 -0
- package/dist/sheet/protection.d.ts +55 -1
- package/dist/sheet/protection.js +55 -2
- package/dist/sheet/rects.d.ts +1 -1
- package/dist/sheet/refs.d.ts +48 -0
- package/dist/sheet/refs.js +155 -8
- package/dist/sheet/ribbon-icons.d.ts +1 -1
- package/dist/sheet/ribbon-icons.js +186 -0
- package/dist/sheet/ribbon.d.ts +1 -1
- package/dist/sheet/ribbon.js +324 -23
- package/dist/sheet/sheet-kinds.d.ts +74 -0
- package/dist/sheet/sheet-kinds.js +91 -0
- package/dist/sheet/shortcuts.d.ts +13 -3
- package/dist/sheet/shortcuts.js +63 -12
- package/dist/sheet/sort.d.ts +51 -0
- package/dist/sheet/sort.js +107 -0
- package/dist/sheet/sparklines.d.ts +111 -0
- package/dist/sheet/sparklines.js +204 -0
- package/dist/sheet/table-styles.d.ts +74 -0
- package/dist/sheet/table-styles.js +152 -0
- package/dist/sheet/tables.d.ts +19 -0
- package/dist/sheet/tables.js +31 -0
- package/dist/sheet/tokenize.d.ts +18 -1
- package/dist/sheet/tokenize.js +60 -9
- package/dist/sheet/validation.d.ts +16 -0
- package/dist/sheet/validation.js +37 -0
- package/dist/sheet/workbook.d.ts +148 -3
- package/dist/sheet/workbook.js +742 -31
- package/dist/sheet/xls-cfb.d.ts +32 -0
- package/dist/sheet/xls-cfb.js +290 -0
- package/dist/sheet/xls-document.d.ts +10 -0
- package/dist/sheet/xls-document.js +1243 -0
- package/dist/sheet/xls-formula.d.ts +40 -0
- package/dist/sheet/xls-formula.js +569 -0
- package/dist/sheet/xlsx-document.d.ts +108 -0
- package/dist/sheet/xlsx-document.js +1849 -0
- package/dist/sheet/xlsx-drawing.d.ts +99 -0
- package/dist/sheet/xlsx-drawing.js +420 -0
- package/dist/sheet-enable.js +6 -7
- package/dist/sheet-text.d.ts +7 -0
- package/dist/sheet-text.js +29 -0
- package/dist/sources/auth-supabase.js +2 -2
- package/dist/sources/realtime-supabase.js +2 -2
- package/dist/sources/rest.d.ts +6 -2
- package/dist/sources/rest.js +42 -7
- package/dist/sources/supabase.d.ts +10 -1
- package/dist/sources/supabase.js +73 -40
- package/dist/studio/emit-project.js +14 -1
- package/dist/studio/index.js +1 -1
- package/dist/studio/project.d.ts +11 -2
- package/dist/studio/project.js +5 -2
- package/dist/studio/ui-components.generated.js +107 -2
- package/dist/sveltekit/in-memory.d.ts +2 -2
- package/dist/sveltekit/in-memory.js +125 -4
- package/dist/sveltekit/index.d.ts +1 -1
- package/dist/sveltekit/index.js +1 -1
- package/dist/sveltekit/query-plan.d.ts +50 -4
- package/dist/sveltekit/query-plan.js +25 -3
- package/dist/sveltekit/sql-source.d.ts +6 -0
- package/dist/sveltekit/sql-source.js +34 -6
- package/dist/sveltekit/sql.d.ts +31 -0
- package/dist/sveltekit/sql.js +135 -25
- package/dist/sveltekit/transport.d.ts +10 -2
- package/dist/sveltekit/transport.js +30 -6
- package/dist/upgrade-prompt.d.ts +1 -1
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/dist/watermark.js +35 -2
- package/dist/wc/GridMenus-By9vPuq0.js +1088 -0
- package/dist/wc/SvChartMenu-CQNrQGT2.js +308 -0
- package/dist/wc/SvDateRangeInput-DR6m7bSM.js +199 -0
- package/dist/wc/SvDateTimePicker-D-vRnaMo.js +771 -0
- package/dist/wc/SvField-B_kurx_P.js +149 -0
- package/dist/wc/SvGrid.helpers-BdVDtjUm.js +135 -0
- package/dist/wc/SvGridCellEditor-Bnf1Kr5C.js +560 -0
- package/dist/wc/SvGridChart-BqUJh2pG.js +3572 -0
- package/dist/wc/SvGridChartBuilder-CGycC5cn.js +988 -0
- package/dist/wc/SvGridChartPanel-CRnizsHD.js +1746 -0
- package/dist/wc/SvGridChartView-D1pa_xMy.js +47 -0
- package/dist/wc/SvGridDropdown-45WsObLL.js +259 -0
- package/dist/wc/SvModal-DrfOYYyX.js +189 -0
- package/dist/wc/cell-formatting-CBfgahv1.js +86 -0
- package/dist/wc/chart-6OXlybVT.js +4341 -0
- package/dist/wc/chart-export-CeSADGfi.js +135 -0
- package/dist/wc/chart-export-pdf-BGko7MER.js +104 -0
- package/dist/wc/chart-summary-2m3ia1-n.js +137 -0
- package/dist/wc/chart-trend-CQOQtTMl.js +50 -0
- package/dist/wc/chart-validate-CD6ptiwg.js +180 -0
- package/dist/wc/client-DQIzjDBG.js +3064 -0
- package/dist/wc/column-resize-DUPgynvc.js +101 -0
- package/dist/wc/date-format-DS-z_h9v.js +1130 -0
- package/dist/wc/dismissable-CQ6XFXsk.js +45 -0
- package/dist/wc/editor-contract-peBDxir_.js +22 -0
- package/dist/wc/editor-registry-DxGKqcvx.js +24 -0
- package/dist/wc/focus-trap-Dbb2tJxb.js +65 -0
- package/dist/wc/list-option-DrRyivWp.js +82 -0
- package/dist/wc/popover-WsGlvtQv.js +69 -0
- package/dist/wc/positioning-BiKLfu1E.js +112 -0
- package/dist/wc/react.d.ts +41 -0
- package/dist/wc/react.js +90 -0
- package/dist/wc/rolldown-runtime-Dy4uBu1J.js +11 -0
- package/dist/wc/row-drag-touch-CycRR65n.js +93 -0
- package/dist/wc/row-resize-limG_N1z.js +111 -0
- package/dist/wc/sv-sheet-element.d.ts +97 -0
- package/dist/wc/sv-sheet-element.js +44213 -0
- package/dist/wc/svelte-virtualizer.svelte-CXtQy2TQ.js +530 -0
- package/dist/wc/validate-BqDthkNr.js +88 -0
- package/dist/wc/vue.d.ts +31 -0
- package/dist/wc/vue.js +75 -0
- package/package.json +30 -5
- package/dist/designer/assets/GridMenus-BlsvL_aU.js +0 -8
- package/dist/designer/assets/SvGridCellEditor-C7uQXYds.js +0 -4
- package/dist/designer/assets/SvGridChartBuilder-kvyIU_Rl.js +0 -1
- package/dist/designer/assets/SvGridDropdown-Bb3HH2Aj.js +0 -1
- package/dist/designer/assets/cell-formatting-wr5wm7US.js +0 -1
- package/dist/designer/assets/index-CMFgAoVV.css +0 -1
- package/dist/designer/assets/row-resize-DLktcqUK.js +0 -1
- package/dist/designer/assets/src-EdI3Xqds.js +0 -58
- 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 ?
|
|
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 ?
|
|
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=
|
|
101
|
-
<div class="sv-sheet-dialog" role="group" aria-label=
|
|
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>
|
|
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>
|
|
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} />
|
|
112
|
-
<label class="check"><input type="checkbox" bind:checked={entireCell} />
|
|
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>
|
|
114
|
+
<span>{t('findReplace.lookIn')}</span>
|
|
115
115
|
<select bind:value={lookIn}>
|
|
116
|
-
<option value="values">
|
|
117
|
-
<option value="formulas">
|
|
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}>
|
|
126
|
-
<button type="button" class="btn" onclick={replace} disabled={!findText}>
|
|
127
|
-
<button type="button" class="btn" onclick={countAll} disabled={!findText}>
|
|
128
|
-
<button type="button" class="btn primary" onclick={() => next(1)} disabled={!findText}>
|
|
129
|
-
<button type="button" class="btn" onclick={close}>
|
|
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 {
|
|
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: '
|
|
36
|
-
{ id: 'alignment', label: '
|
|
37
|
-
{ id: 'font', label: '
|
|
38
|
-
{ id: 'border', label: '
|
|
39
|
-
{ id: 'fill', label: '
|
|
40
|
-
{ id: 'protection', label: '
|
|
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: '
|
|
47
|
-
{ id: 'number', label: '
|
|
48
|
-
{ id: 'currency', label: '
|
|
49
|
-
{ id: '
|
|
50
|
-
{ id: '
|
|
51
|
-
{ id: '
|
|
52
|
-
{ id: '
|
|
53
|
-
{ id: '
|
|
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: '
|
|
174
|
-
{ value: 'outside', label: '
|
|
175
|
-
{ value: 'all', label: '
|
|
176
|
-
{ value: 'top', label: '
|
|
177
|
-
{ value: 'bottom', label: '
|
|
178
|
-
{ value: 'left', label: '
|
|
179
|
-
{ value: 'right', label: '
|
|
180
|
-
{ value: 'thick-bottom', label: '
|
|
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=
|
|
185
|
-
<div class="sv-sheet-dialog format" role="group" aria-label=
|
|
186
|
-
<div class="tabs" role="tablist" aria-label=
|
|
187
|
-
{#each TABS as
|
|
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 ===
|
|
193
|
-
aria-selected={tab ===
|
|
194
|
-
onclick={() => (tab =
|
|
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">
|
|
204
|
-
<ul role="listbox" aria-label=
|
|
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">
|
|
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>
|
|
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} />
|
|
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>
|
|
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
|
-
{
|
|
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>
|
|
281
|
+
<span>{t('formatCells.horizontal')}</span>
|
|
246
282
|
<select bind:value={align}>
|
|
247
|
-
<option value="">
|
|
248
|
-
<option value="left">
|
|
249
|
-
<option value="center">
|
|
250
|
-
<option value="right">
|
|
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>
|
|
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">
|
|
258
|
-
<label class="check"><input type="checkbox" bind:checked={wrap} />
|
|
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>
|
|
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>
|
|
313
|
+
<span>{t('formatCells.size')}</span>
|
|
270
314
|
<select bind:value={fontSize}>
|
|
271
|
-
<option value="">
|
|
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">
|
|
321
|
+
<div class="label">{t('formatCells.fontStyle')}</div>
|
|
278
322
|
<div class="checks">
|
|
279
|
-
<label class="check"><input type="checkbox" bind:checked={bold} />
|
|
280
|
-
<label class="check"><input type="checkbox" bind:checked={italic} />
|
|
281
|
-
<label class="check"><input type="checkbox" bind:checked={underline} />
|
|
282
|
-
<label class="check"><input type="checkbox" bind:checked={strike} />
|
|
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">
|
|
328
|
+
<div class="label">{t('formatCells.color')}</div>
|
|
285
329
|
<div class="checks">
|
|
286
|
-
<label class="check"><input type="checkbox" bind:checked={colorAuto} />
|
|
287
|
-
<input type="color" bind:value={color} disabled={colorAuto} aria-label=
|
|
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">
|
|
292
|
-
<div class="borders" role="radiogroup" aria-label=
|
|
293
|
-
<label class="check"><input type="radio" name="sheet-border" value="" bind:group={border} />
|
|
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">
|
|
342
|
+
<p class="hint">{t('formatCells.borderHint')}</p>
|
|
299
343
|
{:else if tab === 'fill'}
|
|
300
|
-
<div class="label">
|
|
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=
|
|
303
|
-
<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=
|
|
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">
|
|
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
|
-
|
|
366
|
+
{t('formatCells.locked')}
|
|
323
367
|
</label>
|
|
324
|
-
<p class="hint">
|
|
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}>
|
|
331
|
-
<button type="button" class="btn" onclick={close}>
|
|
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 =
|
|
60
|
-
if (!input) { problem =
|
|
61
|
-
if (toValue.trim() === '' || !Number.isFinite(target)) { problem = '
|
|
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 =
|
|
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' ? '
|
|
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>
|
|
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>
|
|
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>
|
|
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
|
-
|
|
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>
|
|
119
|
-
<dt>
|
|
120
|
-
<dt>{byCell.toUpperCase()}
|
|
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}
|
|
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}>
|
|
128
|
-
<button type="button" class="btn" onclick={close}>
|
|
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=
|
|
73
|
-
<div class="sv-sheet-dialog insert" role="group" aria-label=
|
|
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>
|
|
76
|
-
<input bind:this={searchInput} type="text" bind:value={search} onkeydown={onListKey} spellcheck="false" autocomplete="off" placeholder=
|
|
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>
|
|
81
|
+
<span>{t('insertFunction.category')}</span>
|
|
80
82
|
<select bind:value={group}>
|
|
81
|
-
<option value="All">
|
|
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">
|
|
89
|
+
<div class="label">{t('insertFunction.select')}</div>
|
|
88
90
|
<!-- svelte-ignore a11y_no_noninteractive_tabindex -->
|
|
89
|
-
<ul class="list" role="listbox" aria-label=
|
|
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">
|
|
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 || '
|
|
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}>
|
|
113
|
-
<button type="button" class="btn" onclick={close}>
|
|
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>
|