@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
|
@@ -8,6 +8,7 @@
|
|
|
8
8
|
* ribbon, or on a rule from Manage Rules > Edit, and hands back the rule's
|
|
9
9
|
* body for the shell to place.
|
|
10
10
|
*/
|
|
11
|
+
import { useSheetText } from './sheet-text'
|
|
11
12
|
import { SvModal } from '@svgrid/grid'
|
|
12
13
|
import { CF_PRESET_STYLES, type CfPreset, type CfBody, type CfStyledRule } from './sheet/conditional-formats'
|
|
13
14
|
|
|
@@ -23,20 +24,8 @@
|
|
|
23
24
|
}
|
|
24
25
|
|
|
25
26
|
let { open = $bindable(false), preset, rule = null, address, onApply, onClose }: Props = $props()
|
|
27
|
+
const t = useSheetText()
|
|
26
28
|
|
|
27
|
-
const TITLES: Record<CfPreset, string> = {
|
|
28
|
-
greater: 'Greater Than', less: 'Less Than', between: 'Between', equal: 'Equal To',
|
|
29
|
-
text: 'Text That Contains', duplicates: 'Duplicate Values',
|
|
30
|
-
top10: 'Top 10 Items', bottom10: 'Bottom 10 Items', aboveAverage: 'Above Average', belowAverage: 'Below Average',
|
|
31
|
-
}
|
|
32
|
-
const LEADS: Record<CfPreset, string> = {
|
|
33
|
-
greater: 'Format cells that are GREATER THAN:', less: 'Format cells that are LESS THAN:',
|
|
34
|
-
between: 'Format cells that are BETWEEN:', equal: 'Format cells that are EQUAL TO:',
|
|
35
|
-
text: 'Format cells that contain the text:', duplicates: 'Format cells that contain:',
|
|
36
|
-
top10: 'Format cells that rank in the TOP:', bottom10: 'Format cells that rank in the BOTTOM:',
|
|
37
|
-
aboveAverage: 'Format cells that are ABOVE AVERAGE for the selected range:',
|
|
38
|
-
belowAverage: 'Format cells that are BELOW AVERAGE for the selected range:',
|
|
39
|
-
}
|
|
40
29
|
|
|
41
30
|
let value1 = $state('')
|
|
42
31
|
let value2 = $state('')
|
|
@@ -60,13 +49,14 @@
|
|
|
60
49
|
else if (r.kind === 'text') value1 = r.value
|
|
61
50
|
else if (r.kind === 'duplicates') unique = !!r.unique
|
|
62
51
|
else if (r.kind === 'topBottom') { rank = String(r.rank); percent = !!r.percent }
|
|
52
|
+
else if (r.kind === 'formula') value1 = r.formula
|
|
63
53
|
const match = CF_PRESET_STYLES.find((p) => JSON.stringify(p.style) === JSON.stringify(r.style))
|
|
64
54
|
if (match) styleId = match.id
|
|
65
55
|
}
|
|
66
56
|
queueMicrotask(() => first?.focus())
|
|
67
57
|
})
|
|
68
58
|
|
|
69
|
-
const needsValue = $derived(preset === 'greater' || preset === 'less' || preset === 'between' || preset === 'equal' || preset === 'text')
|
|
59
|
+
const needsValue = $derived(preset === 'greater' || preset === 'less' || preset === 'between' || preset === 'equal' || preset === 'text' || preset === 'formula')
|
|
70
60
|
const valid = $derived(
|
|
71
61
|
(!needsValue || value1.trim() !== '')
|
|
72
62
|
&& (preset !== 'between' || value2.trim() !== '')
|
|
@@ -86,6 +76,10 @@
|
|
|
86
76
|
case 'bottom10': return { kind: 'topBottom', top: false, rank: Number(rank), percent, style }
|
|
87
77
|
case 'aboveAverage': return { kind: 'average', above: true, style }
|
|
88
78
|
case 'belowAverage': return { kind: 'average', above: false, style }
|
|
79
|
+
case 'formula': {
|
|
80
|
+
const text = value1.trim()
|
|
81
|
+
return { kind: 'formula', formula: text.startsWith('=') ? text : `=${text}`, style }
|
|
82
|
+
}
|
|
89
83
|
}
|
|
90
84
|
}
|
|
91
85
|
|
|
@@ -104,38 +98,41 @@
|
|
|
104
98
|
const sample = $derived(CF_PRESET_STYLES.find((p) => p.id === styleId)?.style ?? {})
|
|
105
99
|
</script>
|
|
106
100
|
|
|
107
|
-
<SvModal bind:open onClose={onClose} title={
|
|
101
|
+
<SvModal bind:open onClose={onClose} title={t(`cf.title.${preset}`)} size="sm" width={440}>
|
|
108
102
|
<form class="sv-sheet-dialog cf" onsubmit={(e) => { e.preventDefault(); ok() }}>
|
|
109
103
|
<div class="where">{address}</div>
|
|
110
|
-
<div class="lead">{
|
|
104
|
+
<div class="lead">{t(`cf.lead.${preset}`)}</div>
|
|
111
105
|
<div class="row">
|
|
112
106
|
{#if preset === 'between'}
|
|
113
|
-
<input bind:this={first} type="text" bind:value={value1} aria-label=
|
|
114
|
-
<span>and</span>
|
|
115
|
-
<input type="text" bind:value={value2} aria-label=
|
|
107
|
+
<input bind:this={first} type="text" bind:value={value1} aria-label={t('cf.lowerValue')} spellcheck="false" />
|
|
108
|
+
<span>{t('cf.and')}</span>
|
|
109
|
+
<input type="text" bind:value={value2} aria-label={t('cf.upperValue')} spellcheck="false" />
|
|
116
110
|
{:else if needsValue}
|
|
117
|
-
<input bind:this={first} type="text" bind:value={value1} aria-label=
|
|
111
|
+
<input bind:this={first} type="text" bind:value={value1} aria-label={t(preset === 'formula' ? 'cf.formula' : 'cf.value')} spellcheck="false" placeholder={preset === 'text' ? t('cf.textPlaceholder') : preset === 'formula' ? '=$B2>100' : t('cf.valuePlaceholder')} />
|
|
118
112
|
{:else if preset === 'duplicates'}
|
|
119
|
-
<select bind:this={first} bind:value={unique} aria-label=
|
|
120
|
-
<option value={false}>
|
|
121
|
-
<option value={true}>
|
|
113
|
+
<select bind:this={first} bind:value={unique} aria-label={t('cf.duplicateOrUnique')}>
|
|
114
|
+
<option value={false}>{t('cf.duplicate')}</option>
|
|
115
|
+
<option value={true}>{t('cf.unique')}</option>
|
|
122
116
|
</select>
|
|
123
|
-
<span>values</span>
|
|
117
|
+
<span>{t('cf.values')}</span>
|
|
124
118
|
{:else if preset === 'top10' || preset === 'bottom10'}
|
|
125
|
-
<input bind:this={first} type="number" min="1" bind:value={rank} aria-label=
|
|
126
|
-
<label class="check"><input type="checkbox" bind:checked={percent} />
|
|
119
|
+
<input bind:this={first} type="number" min="1" bind:value={rank} aria-label={t('cf.howMany')} />
|
|
120
|
+
<label class="check"><input type="checkbox" bind:checked={percent} /> {t('cf.percentOfRange')}</label>
|
|
127
121
|
{/if}
|
|
128
|
-
<span>with</span>
|
|
129
|
-
<select bind:value={styleId} aria-label=
|
|
130
|
-
{#each CF_PRESET_STYLES as p (p.id)}<option value={p.id}>{p.
|
|
122
|
+
<span>{t('cf.with')}</span>
|
|
123
|
+
<select bind:value={styleId} aria-label={t('cf.formatStyle')}>
|
|
124
|
+
{#each CF_PRESET_STYLES as p (p.id)}<option value={p.id}>{t(`cf.style.${p.id}`)}</option>{/each}
|
|
131
125
|
</select>
|
|
132
126
|
</div>
|
|
127
|
+
{#if preset === 'formula'}
|
|
128
|
+
<p class="hint">{t('cf.formulaHint')}</p>
|
|
129
|
+
{/if}
|
|
133
130
|
<div class="sample" style:background={sample.fill ?? 'transparent'} style:color={sample.color ?? 'inherit'}>AaBbCcYyZz</div>
|
|
134
131
|
</form>
|
|
135
132
|
{#snippet footer()}
|
|
136
133
|
<div class="sv-sheet-dialog-buttons">
|
|
137
|
-
<button type="button" class="btn primary" onclick={ok} disabled={!valid}>
|
|
138
|
-
<button type="button" class="btn" onclick={close}>
|
|
134
|
+
<button type="button" class="btn primary" onclick={ok} disabled={!valid}>{t('ok')}</button>
|
|
135
|
+
<button type="button" class="btn" onclick={close}>{t('cancel')}</button>
|
|
139
136
|
</div>
|
|
140
137
|
{/snippet}
|
|
141
138
|
</SvModal>
|
|
@@ -1,11 +1,13 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
2
|
/**
|
|
3
|
-
* Excel's Data Validation dialog,
|
|
4
|
-
*
|
|
5
|
-
*
|
|
3
|
+
* Excel's Data Validation dialog, its three tabs: Settings (Allow, Data,
|
|
4
|
+
* the bounds or the source, Ignore blank, In-cell dropdown), Input
|
|
5
|
+
* Message (shown under the cell while it is selected) and Error Alert
|
|
6
|
+
* (Style, Title, Message). It opens on the rule
|
|
6
7
|
* at the active cell and, on OK, hands back one rule for the shell to put
|
|
7
8
|
* over the selection; Clear All removes the validation from the selection.
|
|
8
9
|
*/
|
|
10
|
+
import { useSheetText } from './sheet-text'
|
|
9
11
|
import { SvModal } from '@svgrid/grid'
|
|
10
12
|
import {
|
|
11
13
|
OPERATOR_LABELS,
|
|
@@ -24,20 +26,21 @@
|
|
|
24
26
|
}
|
|
25
27
|
|
|
26
28
|
let { open = $bindable(false), rule, address, onApply, onClear, onClose }: Props = $props()
|
|
29
|
+
const t = useSheetText()
|
|
27
30
|
|
|
28
|
-
type Tab = 'settings' | 'alert'
|
|
31
|
+
type Tab = 'settings' | 'input' | 'alert'
|
|
29
32
|
let tab = $state<Tab>('settings')
|
|
30
33
|
|
|
31
34
|
const ALLOWS: ReadonlyArray<{ id: ValidationAllow; label: string }> = [
|
|
32
|
-
{ id: 'any', label: '
|
|
33
|
-
{ id: 'whole', label: '
|
|
34
|
-
{ id: 'decimal', label: '
|
|
35
|
-
{ id: 'list', label: '
|
|
36
|
-
{ id: 'date', label: '
|
|
37
|
-
{ id: 'textLength', label: '
|
|
38
|
-
{ id: 'custom', label: '
|
|
35
|
+
{ id: 'any', label: 'validation.allow.any' },
|
|
36
|
+
{ id: 'whole', label: 'validation.allow.whole' },
|
|
37
|
+
{ id: 'decimal', label: 'validation.allow.decimal' },
|
|
38
|
+
{ id: 'list', label: 'validation.allow.list' },
|
|
39
|
+
{ id: 'date', label: 'validation.allow.date' },
|
|
40
|
+
{ id: 'textLength', label: 'validation.allow.textLength' },
|
|
41
|
+
{ id: 'custom', label: 'validation.allow.custom' },
|
|
39
42
|
]
|
|
40
|
-
const OPERATORS = Object.
|
|
43
|
+
const OPERATORS = Object.keys(OPERATOR_LABELS) as ValidationOperator[]
|
|
41
44
|
|
|
42
45
|
let allow = $state<ValidationAllow>('any')
|
|
43
46
|
let operator = $state<ValidationOperator>('between')
|
|
@@ -48,6 +51,9 @@
|
|
|
48
51
|
let style = $state<'stop' | 'warning'>('stop')
|
|
49
52
|
let title = $state('')
|
|
50
53
|
let message = $state('')
|
|
54
|
+
let showInput = $state(true)
|
|
55
|
+
let inputTitle = $state('')
|
|
56
|
+
let inputMessage = $state('')
|
|
51
57
|
let first = $state<HTMLSelectElement | null>(null)
|
|
52
58
|
|
|
53
59
|
$effect(() => {
|
|
@@ -62,18 +68,21 @@
|
|
|
62
68
|
style = rule?.alert.style ?? 'stop'
|
|
63
69
|
title = rule?.alert.title ?? ''
|
|
64
70
|
message = rule?.alert.message ?? ''
|
|
71
|
+
showInput = rule ? rule.input !== undefined : true
|
|
72
|
+
inputTitle = rule?.input?.title ?? ''
|
|
73
|
+
inputMessage = rule?.input?.message ?? ''
|
|
65
74
|
queueMicrotask(() => first?.focus())
|
|
66
75
|
})
|
|
67
76
|
|
|
68
77
|
const bounded = $derived(allow === 'whole' || allow === 'decimal' || allow === 'date' || allow === 'textLength')
|
|
69
78
|
const twoBounds = $derived(operator === 'between' || operator === 'notBetween')
|
|
70
79
|
const firstLabel = $derived(
|
|
71
|
-
allow === 'list' ? '
|
|
72
|
-
: allow === 'custom' ? '
|
|
73
|
-
: twoBounds ? (allow === 'date' ? '
|
|
74
|
-
: allow === 'date' ? '
|
|
80
|
+
allow === 'list' ? t('validation.source')
|
|
81
|
+
: allow === 'custom' ? t('validation.formula')
|
|
82
|
+
: twoBounds ? t(allow === 'date' ? 'validation.startDate' : 'validation.minimum')
|
|
83
|
+
: t(allow === 'date' ? 'validation.date' : allow === 'textLength' ? 'validation.length' : 'validation.value'),
|
|
75
84
|
)
|
|
76
|
-
const secondLabel = $derived(allow === 'date' ? '
|
|
85
|
+
const secondLabel = $derived(t(allow === 'date' ? 'validation.endDate' : 'validation.maximum'))
|
|
77
86
|
const valid = $derived(
|
|
78
87
|
allow === 'any'
|
|
79
88
|
|| (allow === 'list' && value1.trim() !== '')
|
|
@@ -89,6 +98,10 @@
|
|
|
89
98
|
inCellDropdown: allow === 'list' ? inCellDropdown : false,
|
|
90
99
|
alert: { style, title: title.trim() || undefined, message: message.trim() || undefined },
|
|
91
100
|
}
|
|
101
|
+
// An input message exists when the box is on and there is text to show.
|
|
102
|
+
if (showInput && (inputTitle.trim() || inputMessage.trim())) {
|
|
103
|
+
spec.input = { title: inputTitle.trim() || undefined, message: inputMessage.trim() || undefined }
|
|
104
|
+
}
|
|
92
105
|
if (bounded) {
|
|
93
106
|
spec.operator = operator
|
|
94
107
|
spec.value1 = value1.trim()
|
|
@@ -113,35 +126,35 @@
|
|
|
113
126
|
}
|
|
114
127
|
</script>
|
|
115
128
|
|
|
116
|
-
<SvModal bind:open onClose={onClose} title=
|
|
129
|
+
<SvModal bind:open onClose={onClose} title={t('validation.title')} size="sm" width={400}>
|
|
117
130
|
<form class="sv-sheet-dialog validation" onsubmit={(e) => { e.preventDefault(); ok() }}>
|
|
118
131
|
<div class="where">{address}</div>
|
|
119
|
-
<div class="tabs" role="tablist" aria-label=
|
|
120
|
-
{#each [
|
|
121
|
-
<button type="button" role="tab" class="tab" class:on={tab === id} aria-selected={tab === id} onclick={() => (tab = id as Tab)}>{
|
|
132
|
+
<div class="tabs" role="tablist" aria-label={t('validation.tabs')}>
|
|
133
|
+
{#each ['settings', 'input', 'alert'] as id (id)}
|
|
134
|
+
<button type="button" role="tab" class="tab" class:on={tab === id} aria-selected={tab === id} onclick={() => (tab = id as Tab)}>{t(`validation.tab.${id}`)}</button>
|
|
122
135
|
{/each}
|
|
123
136
|
</div>
|
|
124
137
|
<div class="panel" role="tabpanel">
|
|
125
138
|
{#if tab === 'settings'}
|
|
126
|
-
<div class="lead">
|
|
139
|
+
<div class="lead">{t('validation.criteria')}</div>
|
|
127
140
|
<label class="field">
|
|
128
|
-
<span>
|
|
141
|
+
<span>{t('validation.allow')}</span>
|
|
129
142
|
<select bind:this={first} bind:value={allow}>
|
|
130
|
-
{#each ALLOWS as a (a.id)}<option value={a.id}>{a.label}</option>{/each}
|
|
143
|
+
{#each ALLOWS as a (a.id)}<option value={a.id}>{t(a.label)}</option>{/each}
|
|
131
144
|
</select>
|
|
132
145
|
</label>
|
|
133
146
|
{#if bounded}
|
|
134
147
|
<label class="field">
|
|
135
|
-
<span>
|
|
148
|
+
<span>{t('validation.data')}</span>
|
|
136
149
|
<select bind:value={operator}>
|
|
137
|
-
{#each OPERATORS as
|
|
150
|
+
{#each OPERATORS as id (id)}<option value={id}>{t(`validation.operator.${id}`)}</option>{/each}
|
|
138
151
|
</select>
|
|
139
152
|
</label>
|
|
140
153
|
{/if}
|
|
141
154
|
{#if allow !== 'any'}
|
|
142
155
|
<label class="field">
|
|
143
156
|
<span>{firstLabel}</span>
|
|
144
|
-
<input type="text" bind:value={value1} spellcheck="false" placeholder={allow === 'list' ? '
|
|
157
|
+
<input type="text" bind:value={value1} spellcheck="false" placeholder={allow === 'list' ? t('validation.listPlaceholder') : allow === 'custom' ? '=B1<>""' : ''} />
|
|
145
158
|
</label>
|
|
146
159
|
{/if}
|
|
147
160
|
{#if bounded && twoBounds}
|
|
@@ -151,45 +164,56 @@
|
|
|
151
164
|
</label>
|
|
152
165
|
{/if}
|
|
153
166
|
<div class="checks">
|
|
154
|
-
<label class="check"><input type="checkbox" bind:checked={ignoreBlank} />
|
|
167
|
+
<label class="check"><input type="checkbox" bind:checked={ignoreBlank} /> {t('validation.ignoreBlank')}</label>
|
|
155
168
|
{#if allow === 'list'}
|
|
156
|
-
<label class="check"><input type="checkbox" bind:checked={inCellDropdown} />
|
|
169
|
+
<label class="check"><input type="checkbox" bind:checked={inCellDropdown} /> {t('validation.inCellDropdown')}</label>
|
|
157
170
|
{/if}
|
|
158
171
|
</div>
|
|
159
172
|
{#if allow === 'custom'}
|
|
160
|
-
<p class="hint">
|
|
173
|
+
<p class="hint">{t('validation.customHint')}</p>
|
|
161
174
|
{:else if allow === 'list'}
|
|
162
|
-
<p class="hint">
|
|
175
|
+
<p class="hint">{t('validation.listHint')}</p>
|
|
163
176
|
{:else if allow !== 'any'}
|
|
164
|
-
<p class="hint">
|
|
177
|
+
<p class="hint">{t('validation.boundHint')}</p>
|
|
165
178
|
{/if}
|
|
179
|
+
{:else if tab === 'input'}
|
|
180
|
+
<label class="check"><input type="checkbox" bind:checked={showInput} /> {t('validation.showInput')}</label>
|
|
181
|
+
<div class="lead">{t('validation.inputLead')}</div>
|
|
182
|
+
<label class="field">
|
|
183
|
+
<span>{t('validation.inputTitle')}</span>
|
|
184
|
+
<input type="text" bind:value={inputTitle} disabled={!showInput} />
|
|
185
|
+
</label>
|
|
186
|
+
<label class="field message">
|
|
187
|
+
<span>{t('validation.inputMessage')}</span>
|
|
188
|
+
<textarea rows="4" bind:value={inputMessage} disabled={!showInput}></textarea>
|
|
189
|
+
</label>
|
|
166
190
|
{:else}
|
|
167
|
-
<div class="lead">
|
|
191
|
+
<div class="lead">{t('validation.alertLead')}</div>
|
|
168
192
|
<label class="field">
|
|
169
|
-
<span>
|
|
193
|
+
<span>{t('validation.style')}</span>
|
|
170
194
|
<select bind:value={style}>
|
|
171
|
-
<option value="stop">
|
|
172
|
-
<option value="warning">
|
|
195
|
+
<option value="stop">{t('validation.stop')}</option>
|
|
196
|
+
<option value="warning">{t('validation.warning')}</option>
|
|
173
197
|
</select>
|
|
174
198
|
</label>
|
|
175
199
|
<label class="field">
|
|
176
|
-
<span>
|
|
200
|
+
<span>{t('validation.errorTitle')}</span>
|
|
177
201
|
<input type="text" bind:value={title} />
|
|
178
202
|
</label>
|
|
179
203
|
<label class="field message">
|
|
180
|
-
<span>
|
|
204
|
+
<span>{t('validation.errorMessage')}</span>
|
|
181
205
|
<textarea rows="4" bind:value={message}></textarea>
|
|
182
206
|
</label>
|
|
183
|
-
<p class="hint">
|
|
207
|
+
<p class="hint">{t('validation.alertHint')}</p>
|
|
184
208
|
{/if}
|
|
185
209
|
</div>
|
|
186
210
|
</form>
|
|
187
211
|
{#snippet footer()}
|
|
188
212
|
<div class="sv-sheet-dialog-buttons">
|
|
189
|
-
<button type="button" class="btn" onclick={clearAll}>
|
|
213
|
+
<button type="button" class="btn" onclick={clearAll}>{t('validation.clearAll')}</button>
|
|
190
214
|
<span class="spacer"></span>
|
|
191
|
-
<button type="button" class="btn primary" onclick={ok} disabled={!valid}>
|
|
192
|
-
<button type="button" class="btn" onclick={close}>
|
|
215
|
+
<button type="button" class="btn primary" onclick={ok} disabled={!valid}>{t('ok')}</button>
|
|
216
|
+
<button type="button" class="btn" onclick={close}>{t('cancel')}</button>
|
|
193
217
|
</div>
|
|
194
218
|
{/snippet}
|
|
195
219
|
</SvModal>
|
|
@@ -0,0 +1,217 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
/**
|
|
3
|
+
* Excel's Allow Users to Edit Ranges: the blocks that take an edit while
|
|
4
|
+
* the sheet is protected, locked or not, each with a title. New adds
|
|
5
|
+
* one from a title and an A1 text (`B2:B10`, or several areas with
|
|
6
|
+
* commas), Modify edits one in place, Delete removes it; OK hands the
|
|
7
|
+
* list back as one change, and Protect Sheet... closes this and opens
|
|
8
|
+
* that dialog, as Excel's button does. No password per range.
|
|
9
|
+
*/
|
|
10
|
+
import { useSheetText } from './sheet-text'
|
|
11
|
+
import { SvModal } from '@svgrid/grid'
|
|
12
|
+
import { newEditRangeId, parseRangeText, rangeText, type EditRange } from './sheet/protection'
|
|
13
|
+
|
|
14
|
+
type Props = {
|
|
15
|
+
open?: boolean
|
|
16
|
+
/** The sheet's ranges as they stand. */
|
|
17
|
+
ranges: ReadonlyArray<EditRange>
|
|
18
|
+
/** The selection as A1 text, what a new range's cells open on. */
|
|
19
|
+
selection: string
|
|
20
|
+
onApply: (ranges: EditRange[]) => void
|
|
21
|
+
/** The Protect Sheet... button: the shell opens that dialog. */
|
|
22
|
+
onProtect: () => void
|
|
23
|
+
onClose?: () => void
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
let { open = $bindable(false), ranges, selection, onApply, onProtect, onClose }: Props = $props()
|
|
27
|
+
const t = useSheetText()
|
|
28
|
+
|
|
29
|
+
let working = $state<EditRange[]>([])
|
|
30
|
+
let newTitle = $state('')
|
|
31
|
+
let newRefers = $state('')
|
|
32
|
+
let editing = $state<string | null>(null)
|
|
33
|
+
let editTitle = $state('')
|
|
34
|
+
let editRefers = $state('')
|
|
35
|
+
let problem = $state<string | null>(null)
|
|
36
|
+
let titleBox = $state<HTMLInputElement | null>(null)
|
|
37
|
+
|
|
38
|
+
$effect(() => {
|
|
39
|
+
if (!open) return
|
|
40
|
+
const copy = ranges.map((r) => ({ ...r, rects: r.rects.map(([r1, c1, r2, c2]) => [r1, c1, r2, c2] as const) }))
|
|
41
|
+
working = copy
|
|
42
|
+
newTitle = `Range${copy.length + 1}`
|
|
43
|
+
newRefers = selection
|
|
44
|
+
editing = null
|
|
45
|
+
problem = null
|
|
46
|
+
queueMicrotask(() => titleBox?.focus())
|
|
47
|
+
})
|
|
48
|
+
|
|
49
|
+
function add() {
|
|
50
|
+
const rects = parseRangeText(newRefers)
|
|
51
|
+
if (!rects) { problem = t('editRanges.invalidRef', { text: newRefers }); return }
|
|
52
|
+
const title = newTitle.trim() || `Range${working.length + 1}`
|
|
53
|
+
working = [...working, { id: newEditRangeId(), title, rects }]
|
|
54
|
+
newTitle = `Range${working.length + 1}`
|
|
55
|
+
newRefers = ''
|
|
56
|
+
problem = null
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
function startEdit(range: EditRange) {
|
|
60
|
+
editing = range.id
|
|
61
|
+
editTitle = range.title
|
|
62
|
+
editRefers = rangeText(range.rects)
|
|
63
|
+
problem = null
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
function saveEdit() {
|
|
67
|
+
const rects = parseRangeText(editRefers)
|
|
68
|
+
if (!rects) { problem = t('editRanges.invalidRef', { text: editRefers }); return }
|
|
69
|
+
working = working.map((r) => (r.id === editing ? { ...r, title: editTitle.trim() || r.title, rects } : r))
|
|
70
|
+
editing = null
|
|
71
|
+
problem = null
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
function remove(id: string) {
|
|
75
|
+
working = working.filter((r) => r.id !== id)
|
|
76
|
+
if (editing === id) editing = null
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
function ok() {
|
|
80
|
+
open = false
|
|
81
|
+
onApply(working)
|
|
82
|
+
onClose?.()
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
function protect() {
|
|
86
|
+
open = false
|
|
87
|
+
onApply(working)
|
|
88
|
+
onProtect()
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
function close() {
|
|
92
|
+
open = false
|
|
93
|
+
onClose?.()
|
|
94
|
+
}
|
|
95
|
+
</script>
|
|
96
|
+
|
|
97
|
+
<SvModal bind:open onClose={onClose} title={t('editRanges.title')} size="md">
|
|
98
|
+
<div class="sv-sheet-dialog ranges" role="group" aria-label={t('editRanges.title')}>
|
|
99
|
+
<div class="lead">{t('editRanges.lead')}</div>
|
|
100
|
+
<table class="list">
|
|
101
|
+
<thead>
|
|
102
|
+
<tr><th>{t('editRanges.name')}</th><th>{t('editRanges.refersTo')}</th><th></th></tr>
|
|
103
|
+
</thead>
|
|
104
|
+
<tbody>
|
|
105
|
+
{#each working as range (range.id)}
|
|
106
|
+
<tr>
|
|
107
|
+
{#if editing === range.id}
|
|
108
|
+
<td><input type="text" bind:value={editTitle} aria-label={t('editRanges.name')} spellcheck="false" /></td>
|
|
109
|
+
<td class="mono">
|
|
110
|
+
<input
|
|
111
|
+
type="text"
|
|
112
|
+
bind:value={editRefers}
|
|
113
|
+
aria-label={t('editRanges.refersTo')}
|
|
114
|
+
spellcheck="false"
|
|
115
|
+
onkeydown={(e) => { if (e.key === 'Enter') { e.preventDefault(); saveEdit() } if (e.key === 'Escape') { e.stopPropagation(); editing = null } }}
|
|
116
|
+
/>
|
|
117
|
+
</td>
|
|
118
|
+
<td class="actions">
|
|
119
|
+
<button type="button" class="link" onclick={saveEdit}>{t('save')}</button>
|
|
120
|
+
<button type="button" class="link" onclick={() => (editing = null)}>{t('cancel')}</button>
|
|
121
|
+
</td>
|
|
122
|
+
{:else}
|
|
123
|
+
<td>{range.title}</td>
|
|
124
|
+
<td class="mono">{rangeText(range.rects)}</td>
|
|
125
|
+
<td class="actions">
|
|
126
|
+
<button type="button" class="link" onclick={() => startEdit(range)}>{t('editRanges.modify')}</button>
|
|
127
|
+
<button type="button" class="link" onclick={() => remove(range.id)}>{t('delete')}</button>
|
|
128
|
+
</td>
|
|
129
|
+
{/if}
|
|
130
|
+
</tr>
|
|
131
|
+
{:else}
|
|
132
|
+
<tr><td colspan="3" class="empty">{t('editRanges.empty')}</td></tr>
|
|
133
|
+
{/each}
|
|
134
|
+
</tbody>
|
|
135
|
+
</table>
|
|
136
|
+
<form class="new" onsubmit={(e) => { e.preventDefault(); add() }}>
|
|
137
|
+
<label>
|
|
138
|
+
<span>{t('editRanges.titleField')}</span>
|
|
139
|
+
<input bind:this={titleBox} type="text" bind:value={newTitle} placeholder={t('editRanges.titlePlaceholder')} spellcheck="false" />
|
|
140
|
+
</label>
|
|
141
|
+
<label>
|
|
142
|
+
<span>{t('editRanges.refersField')}</span>
|
|
143
|
+
<input type="text" bind:value={newRefers} placeholder={t('editRanges.refersPlaceholder')} spellcheck="false" />
|
|
144
|
+
</label>
|
|
145
|
+
<button type="submit" class="btn">{t('editRanges.new')}</button>
|
|
146
|
+
</form>
|
|
147
|
+
{#if problem}<p class="status problem" role="alert">{problem}</p>{/if}
|
|
148
|
+
</div>
|
|
149
|
+
{#snippet footer()}
|
|
150
|
+
<div class="sv-sheet-dialog-buttons">
|
|
151
|
+
<button type="button" class="btn" onclick={protect}>{t('editRanges.protectSheet')}</button>
|
|
152
|
+
<span class="spacer"></span>
|
|
153
|
+
<button type="button" class="btn primary" onclick={ok}>{t('ok')}</button>
|
|
154
|
+
<button type="button" class="btn" onclick={close}>{t('cancel')}</button>
|
|
155
|
+
</div>
|
|
156
|
+
{/snippet}
|
|
157
|
+
</SvModal>
|
|
158
|
+
|
|
159
|
+
<style>
|
|
160
|
+
.ranges { min-width: 460px; }
|
|
161
|
+
.list {
|
|
162
|
+
width: 100%;
|
|
163
|
+
border-collapse: collapse;
|
|
164
|
+
font-size: 12px;
|
|
165
|
+
}
|
|
166
|
+
.list th {
|
|
167
|
+
padding: 4px 8px;
|
|
168
|
+
text-align: left;
|
|
169
|
+
font-weight: 600;
|
|
170
|
+
color: var(--sg-muted, #616161);
|
|
171
|
+
border-bottom: 1px solid var(--sg-border, #d1d1d1);
|
|
172
|
+
}
|
|
173
|
+
.list td {
|
|
174
|
+
padding: 4px 8px;
|
|
175
|
+
border-bottom: 1px solid var(--sg-border, #e5e5e5);
|
|
176
|
+
vertical-align: middle;
|
|
177
|
+
}
|
|
178
|
+
.list td input {
|
|
179
|
+
width: 100%;
|
|
180
|
+
box-sizing: border-box;
|
|
181
|
+
padding: 3px 6px;
|
|
182
|
+
font: inherit;
|
|
183
|
+
color: inherit;
|
|
184
|
+
background: var(--sg-bg, #fff);
|
|
185
|
+
border: 1px solid var(--sg-border, #d1d1d1);
|
|
186
|
+
border-radius: 3px;
|
|
187
|
+
}
|
|
188
|
+
.mono { font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace; }
|
|
189
|
+
.empty { color: var(--sg-muted, #616161); text-align: center; }
|
|
190
|
+
.actions { white-space: nowrap; text-align: right; }
|
|
191
|
+
.link {
|
|
192
|
+
padding: 0 4px;
|
|
193
|
+
font: inherit;
|
|
194
|
+
color: var(--sg-accent, #107c41);
|
|
195
|
+
background: none;
|
|
196
|
+
border: 0;
|
|
197
|
+
cursor: pointer;
|
|
198
|
+
}
|
|
199
|
+
.link:hover { text-decoration: underline; }
|
|
200
|
+
.new {
|
|
201
|
+
display: grid;
|
|
202
|
+
grid-template-columns: 1fr 2fr auto;
|
|
203
|
+
gap: 8px;
|
|
204
|
+
align-items: end;
|
|
205
|
+
margin-top: 6px;
|
|
206
|
+
}
|
|
207
|
+
.new label { display: flex; flex-direction: column; gap: 3px; font-size: 12px; }
|
|
208
|
+
.new input {
|
|
209
|
+
padding: 4px 8px;
|
|
210
|
+
font: inherit;
|
|
211
|
+
color: inherit;
|
|
212
|
+
background: var(--sg-bg, #fff);
|
|
213
|
+
border: 1px solid var(--sg-border, #d1d1d1);
|
|
214
|
+
border-radius: 3px;
|
|
215
|
+
}
|
|
216
|
+
.spacer { flex: 1; }
|
|
217
|
+
</style>
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { type EditRange } from './sheet/protection.js';
|
|
2
|
+
type Props = {
|
|
3
|
+
open?: boolean;
|
|
4
|
+
/** The sheet's ranges as they stand. */
|
|
5
|
+
ranges: ReadonlyArray<EditRange>;
|
|
6
|
+
/** The selection as A1 text, what a new range's cells open on. */
|
|
7
|
+
selection: string;
|
|
8
|
+
onApply: (ranges: EditRange[]) => void;
|
|
9
|
+
/** The Protect Sheet... button: the shell opens that dialog. */
|
|
10
|
+
onProtect: () => void;
|
|
11
|
+
onClose?: () => void;
|
|
12
|
+
};
|
|
13
|
+
declare const SvSheetEditRanges: import("svelte").Component<Props, {}, "open">;
|
|
14
|
+
type SvSheetEditRanges = ReturnType<typeof SvSheetEditRanges>;
|
|
15
|
+
export default SvSheetEditRanges;
|