@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
package/dist/SvSheet.svelte.d.ts
CHANGED
|
@@ -24,6 +24,10 @@ import type { GridCommandContext } from '@svgrid/grid/shortcuts';
|
|
|
24
24
|
import type { Workbook, SheetData } from './sheet/workbook.js';
|
|
25
25
|
import { type SheetDocument, type SheetState, type SheetChangeReason } from './sheet/document.js';
|
|
26
26
|
import { type CellFormatEntry } from './sheet/format-store.js';
|
|
27
|
+
import { type SheetPresence } from './sheet/presence.js';
|
|
28
|
+
import { type SheetLocalization } from './sheet/messages.js';
|
|
29
|
+
import { type GridSheetSpec } from './sheet/sheet-kinds.js';
|
|
30
|
+
import { type Rect } from './sheet/rects.js';
|
|
27
31
|
import type { RibbonActionId } from './sheet/ribbon.js';
|
|
28
32
|
/**
|
|
29
33
|
* A grid row carries the RAW text of every cell on it, keyed by column
|
|
@@ -55,6 +59,15 @@ type Props = {
|
|
|
55
59
|
workbook?: Workbook;
|
|
56
60
|
/** Seed sheets, when not supplying a workbook. */
|
|
57
61
|
data?: ReadonlyArray<SheetData>;
|
|
62
|
+
/**
|
|
63
|
+
* Tabs that are a bound table rather than a cell grid, by name.
|
|
64
|
+
*
|
|
65
|
+
* Each one keeps records instead of cells and renders as a grid, and
|
|
66
|
+
* its records are projected into the workbook's cells, so
|
|
67
|
+
* `=SUM(Orders!D2:D99)` on a cell tab reads it like any other sheet.
|
|
68
|
+
* A name here that `data` does not list is added as a new tab.
|
|
69
|
+
*/
|
|
70
|
+
gridSheets?: Record<string, GridSheetSpec>;
|
|
58
71
|
/** Minimum grid size, so a sparse sheet still looks like a sheet. */
|
|
59
72
|
rows?: number;
|
|
60
73
|
columns?: number;
|
|
@@ -105,11 +118,27 @@ type Props = {
|
|
|
105
118
|
*/
|
|
106
119
|
formats?: Readonly<Record<string, CellFormatEntry>>;
|
|
107
120
|
/**
|
|
108
|
-
*
|
|
109
|
-
* Insert > Chart
|
|
110
|
-
* application
|
|
121
|
+
* Kept for the applications that passed it: the shell answers Insert >
|
|
122
|
+
* Table and Insert > Chart itself now, so nothing has to be listed
|
|
123
|
+
* here. An application that wants its own can still take either over
|
|
124
|
+
* through `onAction`.
|
|
125
|
+
*
|
|
126
|
+
* @deprecated Both buttons are always on.
|
|
111
127
|
*/
|
|
112
128
|
extras?: ReadonlyArray<'insert-table' | 'insert-chart'>;
|
|
129
|
+
/**
|
|
130
|
+
* The shell's language: `text` overrides any of its strings (the
|
|
131
|
+
* ribbon's, the dialogs', the status bar's; see `SheetMessages`) and
|
|
132
|
+
* `locale` formats the status bar's numbers and the grid's own
|
|
133
|
+
* matching. Unset keys stay English, so a partial map is fine.
|
|
134
|
+
*/
|
|
135
|
+
localization?: SheetLocalization;
|
|
136
|
+
/**
|
|
137
|
+
* Who signs a comment: the name a new comment and a reply carry, the
|
|
138
|
+
* way Excel signs a threaded comment with the signed-in user. Unset,
|
|
139
|
+
* a new comment is a plain note and a reply carries its time alone.
|
|
140
|
+
*/
|
|
141
|
+
commentAuthor?: string;
|
|
113
142
|
/** Hide any part of the chrome. */
|
|
114
143
|
showRibbon?: boolean;
|
|
115
144
|
showFormulaBar?: boolean;
|
|
@@ -123,6 +152,17 @@ type Props = {
|
|
|
123
152
|
* stays closed, so an application can put its own in their place.
|
|
124
153
|
*/
|
|
125
154
|
onAction?: (action: RibbonActionId, cmd: GridCommandContext) => void | boolean;
|
|
155
|
+
/**
|
|
156
|
+
* A button drawn in a cell was pressed. `action` is the region's own
|
|
157
|
+
* `action`, or its id when it has none, so a sheet can tell one column
|
|
158
|
+
* of buttons from another.
|
|
159
|
+
*/
|
|
160
|
+
onCellAction?: (event: {
|
|
161
|
+
row: number;
|
|
162
|
+
col: number;
|
|
163
|
+
action: string;
|
|
164
|
+
sheet: string;
|
|
165
|
+
}) => void;
|
|
126
166
|
onReady?: (api: SheetApi, document: SheetDocument) => void;
|
|
127
167
|
/**
|
|
128
168
|
* Something the user did landed in the document: a cell, a format, a
|
|
@@ -132,11 +172,44 @@ type Props = {
|
|
|
132
172
|
* (`getState()`, debounced). Undo and redo report too.
|
|
133
173
|
*/
|
|
134
174
|
onChange?: (reasons: ReadonlyArray<SheetChangeReason>) => void;
|
|
175
|
+
/**
|
|
176
|
+
* Other people on this workbook: each one's sheet, selection, name and
|
|
177
|
+
* colour, drawn over the cells as a coloured box with a tag.
|
|
178
|
+
*
|
|
179
|
+
* Presence is not part of the document and is never saved: a cursor
|
|
180
|
+
* belongs to a session. It comes in as a prop so the transport stays
|
|
181
|
+
* the application's, and `createDeltaStream` carries it for an
|
|
182
|
+
* application that wants one wire for both.
|
|
183
|
+
*/
|
|
184
|
+
presence?: ReadonlyArray<SheetPresence>;
|
|
185
|
+
/**
|
|
186
|
+
* Where THIS user is, every time it moves: the sheet, the selection and
|
|
187
|
+
* the active cell. What an application broadcasts as its own presence.
|
|
188
|
+
*/
|
|
189
|
+
onPresence?: (me: {
|
|
190
|
+
sheet: string;
|
|
191
|
+
rect: Rect;
|
|
192
|
+
active: {
|
|
193
|
+
row: number;
|
|
194
|
+
col: number;
|
|
195
|
+
};
|
|
196
|
+
}) => void;
|
|
135
197
|
};
|
|
136
198
|
declare const SvSheet: import("svelte").Component<Props, {
|
|
137
199
|
getState: () => SheetState;
|
|
138
200
|
setState: (state: SheetState) => void;
|
|
201
|
+
open: (file: Blob & {
|
|
202
|
+
name?: string;
|
|
203
|
+
}) => Promise<void>;
|
|
204
|
+
toXlsx: () => Promise<Blob>;
|
|
205
|
+
toOds: () => Promise<Blob>;
|
|
206
|
+
toXls: () => Blob;
|
|
207
|
+
toCsv: () => string;
|
|
208
|
+
printHtml: () => string;
|
|
209
|
+
print: () => void;
|
|
210
|
+
newWorkbook: () => void;
|
|
139
211
|
refresh: () => void;
|
|
212
|
+
act: (action: RibbonActionId) => void;
|
|
140
213
|
}, "">;
|
|
141
214
|
type SvSheet = ReturnType<typeof SvSheet>;
|
|
142
215
|
export default SvSheet;
|
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
/**
|
|
3
|
+
* Excel's Chart Design tab, as the one dialog the sheet needs: the chart
|
|
4
|
+
* type, its title, whether the range's first row and column are labels,
|
|
5
|
+
* whether a series is a column of the range or a row, and stacking.
|
|
6
|
+
* Opened by a double-click on a chart or by Chart Setup on the ribbon
|
|
7
|
+
* while one is selected. Delete removes the chart.
|
|
8
|
+
*/
|
|
9
|
+
import { useSheetText } from './sheet-text'
|
|
10
|
+
import { SvModal } from '@svgrid/grid'
|
|
11
|
+
import {
|
|
12
|
+
SHEET_CHART_TYPES, SHEET_CHART_TRENDS, copyObject,
|
|
13
|
+
type SheetChartObject, type SheetChartType, type SheetChartTrend,
|
|
14
|
+
} from './sheet/objects'
|
|
15
|
+
import { colToLetters } from './sheet/address'
|
|
16
|
+
|
|
17
|
+
type Props = {
|
|
18
|
+
open?: boolean
|
|
19
|
+
/** The chart as it stands. */
|
|
20
|
+
chart: SheetChartObject
|
|
21
|
+
/**
|
|
22
|
+
* The series it is drawing, by the labels the range gives them: what
|
|
23
|
+
* the secondary-axis list offers. The dialog has the chart, not the
|
|
24
|
+
* cells, so the shell reads them off the drawing.
|
|
25
|
+
*/
|
|
26
|
+
seriesLabels?: ReadonlyArray<string>
|
|
27
|
+
onApply: (chart: SheetChartObject) => void
|
|
28
|
+
onDelete: () => void
|
|
29
|
+
onClose?: () => void
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
let { open = $bindable(false), chart, seriesLabels = [], onApply, onDelete, onClose }: Props = $props()
|
|
33
|
+
const t = useSheetText()
|
|
34
|
+
|
|
35
|
+
let type = $state<SheetChartType>('bar')
|
|
36
|
+
let title = $state('')
|
|
37
|
+
let headers = $state(true)
|
|
38
|
+
let series = $state<'columns' | 'rows'>('columns')
|
|
39
|
+
let stacked = $state(false)
|
|
40
|
+
let trend = $state<SheetChartTrend | ''>('')
|
|
41
|
+
let secondary = $state('')
|
|
42
|
+
let first = $state<HTMLSelectElement | null>(null)
|
|
43
|
+
|
|
44
|
+
$effect(() => {
|
|
45
|
+
if (!open) return
|
|
46
|
+
type = chart.type
|
|
47
|
+
title = chart.title ?? ''
|
|
48
|
+
headers = chart.headers
|
|
49
|
+
series = chart.series
|
|
50
|
+
stacked = Boolean(chart.stacked)
|
|
51
|
+
trend = chart.trend ?? ''
|
|
52
|
+
secondary = chart.secondary ?? ''
|
|
53
|
+
queueMicrotask(() => first?.focus())
|
|
54
|
+
})
|
|
55
|
+
|
|
56
|
+
const rangeText = $derived.by(() => {
|
|
57
|
+
const [r1, c1, r2, c2] = chart.range
|
|
58
|
+
return `${colToLetters(c1)}${r1 + 1}:${colToLetters(c2)}${r2 + 1}`
|
|
59
|
+
})
|
|
60
|
+
/** Stacking means nothing on a pie or a scatter. */
|
|
61
|
+
const stackable = $derived(type === 'bar' || type === 'area' || type === 'line')
|
|
62
|
+
/** A pie has one axis and no trend to draw over it. */
|
|
63
|
+
const twoAxes = $derived(type !== 'pie')
|
|
64
|
+
|
|
65
|
+
function ok() {
|
|
66
|
+
const next = copyObject(chart) as SheetChartObject
|
|
67
|
+
next.type = type
|
|
68
|
+
next.headers = headers
|
|
69
|
+
next.series = series
|
|
70
|
+
if (title.trim()) next.title = title.trim()
|
|
71
|
+
else delete next.title
|
|
72
|
+
if (stacked && stackable) next.stacked = true
|
|
73
|
+
else delete next.stacked
|
|
74
|
+
// A pie has one axis and no line to trend, so neither setting survives
|
|
75
|
+
// a change to one: keeping a hidden setting is how a dialog lies.
|
|
76
|
+
if (trend && twoAxes) next.trend = trend
|
|
77
|
+
else delete next.trend
|
|
78
|
+
// A second axis means nothing on a pie, and nothing for a series that
|
|
79
|
+
// is no longer there.
|
|
80
|
+
if (secondary && twoAxes && seriesLabels.includes(secondary)) next.secondary = secondary
|
|
81
|
+
else delete next.secondary
|
|
82
|
+
open = false
|
|
83
|
+
onApply(next)
|
|
84
|
+
onClose?.()
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
function close() {
|
|
88
|
+
open = false
|
|
89
|
+
onClose?.()
|
|
90
|
+
}
|
|
91
|
+
</script>
|
|
92
|
+
|
|
93
|
+
<SvModal bind:open onClose={onClose} title={t('chartSetup.title')} size="sm">
|
|
94
|
+
<form class="sv-sheet-dialog" onsubmit={(e) => { e.preventDefault(); ok() }}>
|
|
95
|
+
<div class="where">{t('chartSetup.range', { range: rangeText })}</div>
|
|
96
|
+
<label class="field">
|
|
97
|
+
<span>{t('chartSetup.type')}</span>
|
|
98
|
+
<select bind:this={first} bind:value={type}>
|
|
99
|
+
{#each SHEET_CHART_TYPES as kind (kind)}<option value={kind}>{t(`chartSetup.type.${kind}`)}</option>{/each}
|
|
100
|
+
</select>
|
|
101
|
+
</label>
|
|
102
|
+
<label class="field">
|
|
103
|
+
<span>{t('chartSetup.chartTitle')}</span>
|
|
104
|
+
<input type="text" bind:value={title} spellcheck="false" placeholder={t('chartSetup.titlePlaceholder')} />
|
|
105
|
+
</label>
|
|
106
|
+
<label class="field">
|
|
107
|
+
<span>{t('chartSetup.series')}</span>
|
|
108
|
+
<select bind:value={series}>
|
|
109
|
+
<option value="columns">{t('chartSetup.series.columns')}</option>
|
|
110
|
+
<option value="rows">{t('chartSetup.series.rows')}</option>
|
|
111
|
+
</select>
|
|
112
|
+
</label>
|
|
113
|
+
{#if twoAxes}
|
|
114
|
+
<label class="field">
|
|
115
|
+
<span>{t('chartSetup.trend')}</span>
|
|
116
|
+
<select bind:value={trend}>
|
|
117
|
+
<option value="">{t('chartSetup.trend.none')}</option>
|
|
118
|
+
{#each SHEET_CHART_TRENDS as kind (kind)}<option value={kind}>{t(`chartSetup.trend.${kind}`)}</option>{/each}
|
|
119
|
+
</select>
|
|
120
|
+
</label>
|
|
121
|
+
{#if seriesLabels.length > 1}
|
|
122
|
+
<label class="field">
|
|
123
|
+
<span>{t('chartSetup.secondary')}</span>
|
|
124
|
+
<select bind:value={secondary}>
|
|
125
|
+
<option value="">{t('chartSetup.secondary.none')}</option>
|
|
126
|
+
{#each seriesLabels as label (label)}<option value={label}>{label}</option>{/each}
|
|
127
|
+
</select>
|
|
128
|
+
</label>
|
|
129
|
+
{/if}
|
|
130
|
+
{/if}
|
|
131
|
+
<div class="checks">
|
|
132
|
+
<label class="check"><input type="checkbox" bind:checked={headers} /> {t('chartSetup.headers')}</label>
|
|
133
|
+
{#if stackable}
|
|
134
|
+
<label class="check"><input type="checkbox" bind:checked={stacked} /> {t('chartSetup.stacked')}</label>
|
|
135
|
+
{/if}
|
|
136
|
+
</div>
|
|
137
|
+
<p class="hint">{t('chartSetup.hint')}</p>
|
|
138
|
+
</form>
|
|
139
|
+
{#snippet footer()}
|
|
140
|
+
<div class="sv-sheet-dialog-buttons">
|
|
141
|
+
<button type="button" class="btn" onclick={() => { open = false; onDelete() }}>{t('delete')}</button>
|
|
142
|
+
<span class="spacer"></span>
|
|
143
|
+
<button type="button" class="btn primary" onclick={ok}>{t('ok')}</button>
|
|
144
|
+
<button type="button" class="btn" onclick={close}>{t('cancel')}</button>
|
|
145
|
+
</div>
|
|
146
|
+
{/snippet}
|
|
147
|
+
</SvModal>
|
|
148
|
+
|
|
149
|
+
<style>
|
|
150
|
+
.spacer { flex: 1; }
|
|
151
|
+
</style>
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { type SheetChartObject } from './sheet/objects.js';
|
|
2
|
+
type Props = {
|
|
3
|
+
open?: boolean;
|
|
4
|
+
/** The chart as it stands. */
|
|
5
|
+
chart: SheetChartObject;
|
|
6
|
+
/**
|
|
7
|
+
* The series it is drawing, by the labels the range gives them: what
|
|
8
|
+
* the secondary-axis list offers. The dialog has the chart, not the
|
|
9
|
+
* cells, so the shell reads them off the drawing.
|
|
10
|
+
*/
|
|
11
|
+
seriesLabels?: ReadonlyArray<string>;
|
|
12
|
+
onApply: (chart: SheetChartObject) => void;
|
|
13
|
+
onDelete: () => void;
|
|
14
|
+
onClose?: () => void;
|
|
15
|
+
};
|
|
16
|
+
declare const SvSheetChartSetup: import("svelte").Component<Props, {}, "open">;
|
|
17
|
+
type SvSheetChartSetup = ReturnType<typeof SvSheetChartSetup>;
|
|
18
|
+
export default SvSheetChartSetup;
|
|
@@ -1,62 +1,201 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
2
|
/**
|
|
3
|
-
* The comment
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
3
|
+
* The comment box: Excel's note editor for a new comment, and its
|
|
4
|
+
* threaded comment card once one is there. New: a textarea over the
|
|
5
|
+
* text, Save, and the text kept whatever closes the box (Escape and a
|
|
6
|
+
* click elsewhere included), which is why every keystroke is reported
|
|
7
|
+
* through `onDraft` and the shell saves the draft on dismissal;
|
|
8
|
+
* Ctrl+Enter saves too. Existing: the first entry with its author and
|
|
9
|
+
* time, the replies under it, Edit and Delete on each, a reply box,
|
|
10
|
+
* and Resolve / Reopen in the head. Replies, edits and the resolved
|
|
11
|
+
* state go out whole through `onUpdate`; the first text through
|
|
12
|
+
* `onSave`, as before; Delete removes the thread. The shell mounts it
|
|
13
|
+
* inside the popover anchored to the cell.
|
|
10
14
|
*/
|
|
15
|
+
import { useSheetText } from './sheet-text'
|
|
16
|
+
import type { CommentThread, CommentEntry } from './sheet/comments'
|
|
17
|
+
|
|
11
18
|
type Props = {
|
|
12
|
-
/** The comment as it is,
|
|
19
|
+
/** The comment as it is, null for a new one. */
|
|
20
|
+
thread: CommentThread | null
|
|
21
|
+
/** The first text as it stands, the draft the box opens on. */
|
|
13
22
|
text: string
|
|
14
23
|
/** A1 of the cell, for the heading. */
|
|
15
24
|
address: string
|
|
16
|
-
/**
|
|
25
|
+
/** Who signs a reply, when the application says. */
|
|
26
|
+
author?: string
|
|
27
|
+
/** For the times. */
|
|
28
|
+
locale?: string
|
|
29
|
+
/** Every change of the first text, so the shell can keep it on dismissal. */
|
|
17
30
|
onDraft: (text: string) => void
|
|
18
31
|
onSave: (text: string) => void
|
|
19
32
|
onDelete: () => void
|
|
33
|
+
/** A reply, an edited or deleted reply, or Resolve / Reopen: the whole thread as it should be. */
|
|
34
|
+
onUpdate: (thread: CommentThread) => void
|
|
20
35
|
}
|
|
21
36
|
|
|
22
|
-
let { text, address, onDraft, onSave, onDelete }: Props = $props()
|
|
37
|
+
let { thread, text, address, author, locale, onDraft, onSave, onDelete, onUpdate }: Props = $props()
|
|
38
|
+
const t = useSheetText()
|
|
23
39
|
|
|
24
40
|
let draft = $state('')
|
|
41
|
+
let editingRoot = $state(false)
|
|
42
|
+
let reply = $state('')
|
|
43
|
+
let editingReply = $state<number | null>(null)
|
|
44
|
+
let replyDraft = $state('')
|
|
25
45
|
let box = $state<HTMLTextAreaElement | null>(null)
|
|
46
|
+
let replyBox = $state<HTMLTextAreaElement | null>(null)
|
|
26
47
|
|
|
27
48
|
$effect(() => {
|
|
28
49
|
draft = text
|
|
50
|
+
editingRoot = false
|
|
51
|
+
editingReply = null
|
|
52
|
+
reply = ''
|
|
29
53
|
queueMicrotask(() => {
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
54
|
+
const target = thread ? replyBox : box
|
|
55
|
+
if (!target) return
|
|
56
|
+
target.focus()
|
|
57
|
+
target.setSelectionRange(target.value.length, target.value.length)
|
|
33
58
|
})
|
|
34
59
|
})
|
|
35
60
|
|
|
61
|
+
const composing = $derived(!thread || editingRoot)
|
|
62
|
+
|
|
63
|
+
function when(at: string | undefined): string {
|
|
64
|
+
if (!at) return ''
|
|
65
|
+
const ms = Date.parse(at)
|
|
66
|
+
if (!Number.isFinite(ms)) return ''
|
|
67
|
+
try {
|
|
68
|
+
return new Date(ms).toLocaleString(locale, { dateStyle: 'medium', timeStyle: 'short' })
|
|
69
|
+
} catch {
|
|
70
|
+
return new Date(ms).toLocaleString(undefined, { dateStyle: 'medium', timeStyle: 'short' })
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
const stamp = (): Pick<CommentEntry, 'author' | 'at'> => ({ ...(author ? { author } : {}), at: new Date().toISOString() })
|
|
75
|
+
|
|
76
|
+
function saveRoot() {
|
|
77
|
+
editingRoot = false
|
|
78
|
+
onSave(draft)
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
function postReply() {
|
|
82
|
+
const body = reply.trim()
|
|
83
|
+
if (!thread || !body) return
|
|
84
|
+
onUpdate({ ...thread, replies: [...(thread.replies ?? []), { text: body, ...stamp() }] })
|
|
85
|
+
reply = ''
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
function saveReply(index: number) {
|
|
89
|
+
if (!thread) return
|
|
90
|
+
const body = replyDraft.trim()
|
|
91
|
+
const replies = (thread.replies ?? []).map((r, i) => (i === index ? { ...r, text: body } : r)).filter((r) => r.text)
|
|
92
|
+
editingReply = null
|
|
93
|
+
onUpdate({ ...thread, replies })
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
function deleteReply(index: number) {
|
|
97
|
+
if (!thread) return
|
|
98
|
+
onUpdate({ ...thread, replies: (thread.replies ?? []).filter((_, i) => i !== index) })
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
function setResolved(resolved: boolean) {
|
|
102
|
+
if (!thread) return
|
|
103
|
+
const next = { ...thread }
|
|
104
|
+
if (resolved) next.resolved = true
|
|
105
|
+
else delete next.resolved
|
|
106
|
+
onUpdate(next)
|
|
107
|
+
}
|
|
108
|
+
|
|
36
109
|
function onKeyDown(event: KeyboardEvent) {
|
|
37
|
-
if (event.key
|
|
110
|
+
if (event.key !== 'Enter' || !(event.ctrlKey || event.metaKey)) return
|
|
111
|
+
event.preventDefault()
|
|
112
|
+
const target = event.target
|
|
113
|
+
if (target === replyBox) postReply()
|
|
114
|
+
else if (editingReply !== null) saveReply(editingReply)
|
|
115
|
+
else if (composing) saveRoot()
|
|
38
116
|
}
|
|
39
117
|
</script>
|
|
40
118
|
|
|
41
119
|
<!-- svelte-ignore a11y_no_static_element_interactions -->
|
|
42
|
-
<div class="sv-sheet-comment" role="dialog" aria-label=
|
|
43
|
-
<div class="head">
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
></textarea>
|
|
53
|
-
<div class="sv-sheet-dialog-buttons">
|
|
54
|
-
<span class="keys">Ctrl+Enter saves</span>
|
|
55
|
-
<button type="button" class="btn primary" onclick={() => onSave(draft)}>Save</button>
|
|
56
|
-
{#if text}
|
|
57
|
-
<button type="button" class="btn" onclick={onDelete}>Delete</button>
|
|
120
|
+
<div class="sv-sheet-comment" class:threaded={!!thread} role="dialog" tabindex="-1" aria-label={t('commentOn', { address })} onkeydown={onKeyDown}>
|
|
121
|
+
<div class="head">
|
|
122
|
+
<span>{address}</span>
|
|
123
|
+
{#if thread}
|
|
124
|
+
{#if thread.resolved}
|
|
125
|
+
<span class="badge">{t('commentResolved')}</span>
|
|
126
|
+
<button type="button" class="link" onclick={() => setResolved(false)}>{t('commentReopen')}</button>
|
|
127
|
+
{:else}
|
|
128
|
+
<button type="button" class="link" onclick={() => setResolved(true)}>{t('commentResolve')}</button>
|
|
129
|
+
{/if}
|
|
58
130
|
{/if}
|
|
59
131
|
</div>
|
|
132
|
+
{#if composing}
|
|
133
|
+
<textarea
|
|
134
|
+
bind:this={box}
|
|
135
|
+
bind:value={draft}
|
|
136
|
+
oninput={() => onDraft(draft)}
|
|
137
|
+
rows="4"
|
|
138
|
+
aria-label={t('comment')}
|
|
139
|
+
placeholder={t('commentPlaceholder')}
|
|
140
|
+
spellcheck="false"
|
|
141
|
+
></textarea>
|
|
142
|
+
<div class="sv-sheet-dialog-buttons">
|
|
143
|
+
<span class="keys">{t('commentSaves')}</span>
|
|
144
|
+
<button type="button" class="btn primary" onclick={saveRoot}>{t('save')}</button>
|
|
145
|
+
{#if thread}
|
|
146
|
+
<button type="button" class="btn" onclick={() => { draft = text; onDraft(text); editingRoot = false }}>{t('cancel')}</button>
|
|
147
|
+
{:else if text}
|
|
148
|
+
<button type="button" class="btn" onclick={onDelete}>{t('delete')}</button>
|
|
149
|
+
{/if}
|
|
150
|
+
</div>
|
|
151
|
+
{:else if thread}
|
|
152
|
+
<div class="entry root">
|
|
153
|
+
<div class="who">
|
|
154
|
+
{#if thread.author}<span class="author">{thread.author}</span>{/if}
|
|
155
|
+
{#if thread.at}<span class="when">{when(thread.at)}</span>{/if}
|
|
156
|
+
</div>
|
|
157
|
+
<div class="text">{thread.text}</div>
|
|
158
|
+
<div class="actions">
|
|
159
|
+
<button type="button" class="link" onclick={() => { editingRoot = true; queueMicrotask(() => box?.focus()) }}>{t('commentEdit')}</button>
|
|
160
|
+
<button type="button" class="link" onclick={onDelete}>{t('delete')}</button>
|
|
161
|
+
</div>
|
|
162
|
+
</div>
|
|
163
|
+
{#each thread.replies ?? [] as entry, i (i)}
|
|
164
|
+
<div class="entry reply">
|
|
165
|
+
<div class="who">
|
|
166
|
+
{#if entry.author}<span class="author">{entry.author}</span>{/if}
|
|
167
|
+
{#if entry.at}<span class="when">{when(entry.at)}</span>{/if}
|
|
168
|
+
</div>
|
|
169
|
+
{#if editingReply === i}
|
|
170
|
+
<textarea bind:value={replyDraft} rows="3" aria-label={t('commentReply')} spellcheck="false"></textarea>
|
|
171
|
+
<div class="actions">
|
|
172
|
+
<button type="button" class="link" onclick={() => saveReply(i)}>{t('save')}</button>
|
|
173
|
+
<button type="button" class="link" onclick={() => (editingReply = null)}>{t('cancel')}</button>
|
|
174
|
+
</div>
|
|
175
|
+
{:else}
|
|
176
|
+
<div class="text">{entry.text}</div>
|
|
177
|
+
<div class="actions">
|
|
178
|
+
<button type="button" class="link" onclick={() => { editingReply = i; replyDraft = entry.text }}>{t('commentEdit')}</button>
|
|
179
|
+
<button type="button" class="link" onclick={() => deleteReply(i)}>{t('delete')}</button>
|
|
180
|
+
</div>
|
|
181
|
+
{/if}
|
|
182
|
+
</div>
|
|
183
|
+
{/each}
|
|
184
|
+
{#if !thread.resolved}
|
|
185
|
+
<textarea
|
|
186
|
+
bind:this={replyBox}
|
|
187
|
+
bind:value={reply}
|
|
188
|
+
rows="2"
|
|
189
|
+
aria-label={t('commentReply')}
|
|
190
|
+
placeholder={t('commentReplyPlaceholder')}
|
|
191
|
+
spellcheck="false"
|
|
192
|
+
></textarea>
|
|
193
|
+
<div class="sv-sheet-dialog-buttons">
|
|
194
|
+
<span class="keys">{t('commentPosts')}</span>
|
|
195
|
+
<button type="button" class="btn primary" onclick={postReply} disabled={!reply.trim()}>{t('commentReply')}</button>
|
|
196
|
+
</div>
|
|
197
|
+
{/if}
|
|
198
|
+
{/if}
|
|
60
199
|
</div>
|
|
61
200
|
|
|
62
201
|
<style>
|
|
@@ -69,20 +208,66 @@
|
|
|
69
208
|
font-size: 12px;
|
|
70
209
|
color: var(--sg-fg, #242424);
|
|
71
210
|
}
|
|
211
|
+
.sv-sheet-comment.threaded {
|
|
212
|
+
width: 300px;
|
|
213
|
+
max-height: 360px;
|
|
214
|
+
overflow-y: auto;
|
|
215
|
+
}
|
|
72
216
|
.head {
|
|
217
|
+
display: flex;
|
|
218
|
+
align-items: center;
|
|
219
|
+
gap: 8px;
|
|
73
220
|
font-weight: 600;
|
|
74
221
|
color: var(--sg-muted, #616161);
|
|
75
222
|
}
|
|
223
|
+
.head .link { margin-left: auto; }
|
|
224
|
+
.badge {
|
|
225
|
+
padding: 1px 6px;
|
|
226
|
+
font-size: 11px;
|
|
227
|
+
font-weight: 600;
|
|
228
|
+
color: var(--sg-on-accent, #fff);
|
|
229
|
+
background: var(--sg-accent, #107c41);
|
|
230
|
+
border-radius: 9px;
|
|
231
|
+
}
|
|
76
232
|
.keys {
|
|
77
233
|
margin-right: auto;
|
|
78
234
|
font-size: 11px;
|
|
79
235
|
color: var(--sg-muted, #616161);
|
|
80
236
|
}
|
|
237
|
+
.entry {
|
|
238
|
+
display: flex;
|
|
239
|
+
flex-direction: column;
|
|
240
|
+
gap: 3px;
|
|
241
|
+
padding: 6px 0;
|
|
242
|
+
border-top: 1px solid var(--sg-border, #e5e5e5);
|
|
243
|
+
}
|
|
244
|
+
.entry.root { border-top: 0; padding-top: 0; }
|
|
245
|
+
.entry.reply { padding-left: 12px; }
|
|
246
|
+
.who {
|
|
247
|
+
display: flex;
|
|
248
|
+
gap: 8px;
|
|
249
|
+
align-items: baseline;
|
|
250
|
+
font-size: 11px;
|
|
251
|
+
color: var(--sg-muted, #616161);
|
|
252
|
+
}
|
|
253
|
+
.author { font-weight: 600; color: var(--sg-fg, #242424); }
|
|
254
|
+
.text { white-space: pre-wrap; overflow-wrap: anywhere; }
|
|
255
|
+
.actions { display: flex; gap: 10px; }
|
|
256
|
+
.link {
|
|
257
|
+
padding: 0;
|
|
258
|
+
font: inherit;
|
|
259
|
+
font-size: 11px;
|
|
260
|
+
color: var(--sg-accent, #107c41);
|
|
261
|
+
background: none;
|
|
262
|
+
border: 0;
|
|
263
|
+
cursor: pointer;
|
|
264
|
+
}
|
|
265
|
+
.link:hover { text-decoration: underline; }
|
|
81
266
|
textarea {
|
|
82
267
|
width: 100%;
|
|
83
268
|
box-sizing: border-box;
|
|
84
269
|
resize: vertical;
|
|
85
|
-
min-height:
|
|
270
|
+
min-height: 40px;
|
|
86
271
|
padding: 6px 8px;
|
|
87
272
|
font: inherit;
|
|
88
273
|
line-height: 1.4;
|
|
@@ -1,21 +1,21 @@
|
|
|
1
|
-
|
|
2
|
-
* The comment editor: Excel's note box, opened by New Comment, Edit
|
|
3
|
-
* Comment, Shift+F2 and the cell menu. A textarea over the text, Save,
|
|
4
|
-
* and Delete when there is something to delete. As in Excel the text is
|
|
5
|
-
* kept whatever closes the box: Escape and a click elsewhere save what
|
|
6
|
-
* was typed, which is why every keystroke is reported through `onDraft`
|
|
7
|
-
* and the shell saves the draft on dismissal. Ctrl+Enter saves too.
|
|
8
|
-
* The shell mounts it inside the popover anchored to the cell.
|
|
9
|
-
*/
|
|
1
|
+
import type { CommentThread } from './sheet/comments.js';
|
|
10
2
|
type Props = {
|
|
11
|
-
/** The comment as it is,
|
|
3
|
+
/** The comment as it is, null for a new one. */
|
|
4
|
+
thread: CommentThread | null;
|
|
5
|
+
/** The first text as it stands, the draft the box opens on. */
|
|
12
6
|
text: string;
|
|
13
7
|
/** A1 of the cell, for the heading. */
|
|
14
8
|
address: string;
|
|
15
|
-
/**
|
|
9
|
+
/** Who signs a reply, when the application says. */
|
|
10
|
+
author?: string;
|
|
11
|
+
/** For the times. */
|
|
12
|
+
locale?: string;
|
|
13
|
+
/** Every change of the first text, so the shell can keep it on dismissal. */
|
|
16
14
|
onDraft: (text: string) => void;
|
|
17
15
|
onSave: (text: string) => void;
|
|
18
16
|
onDelete: () => void;
|
|
17
|
+
/** A reply, an edited or deleted reply, or Resolve / Reopen: the whole thread as it should be. */
|
|
18
|
+
onUpdate: (thread: CommentThread) => void;
|
|
19
19
|
};
|
|
20
20
|
declare const SvSheetComment: import("svelte").Component<Props, {}, "">;
|
|
21
21
|
type SvSheetComment = ReturnType<typeof SvSheetComment>;
|