@a3s-lab/office 0.3.0 → 0.4.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/COLLABORATION_ROADMAP.md +426 -0
- package/README.md +635 -9
- package/dist/0~1403.js +1 -1
- package/dist/0~2805.js +1279 -0
- package/dist/{0~use-office-draft.js → 0~345.js} +30 -1
- package/dist/0~3539.js +1 -1
- package/dist/0~3557.js +1 -1
- package/dist/0~3635.js +1 -1
- package/dist/0~4595.js +7 -2
- package/dist/0~4980.js +154 -0
- package/dist/{0~9512.js → 0~6090.js} +539 -3
- package/dist/0~7048.js +92 -66
- package/dist/0~7614.js +2 -1
- package/dist/0~7754.js +5653 -0
- package/dist/0~9445.js +1 -1
- package/dist/0~document-editor.js +1815 -1553
- package/dist/0~markdown-editor.js +250 -44
- package/dist/0~pdf-viewer.js +1016 -24
- package/dist/0~presentation-editor.js +179 -8
- package/dist/0~spreadsheet-editor.js +3371 -578
- package/dist/0~work-docx-export.js +6801 -658
- package/dist/0~work-docx-import.js +1388 -795
- package/dist/0~work-office-diagnostics.js +524 -30
- package/dist/0~work-pptx-export.js +2 -1
- package/dist/0~work-pptx-import.js +1 -2
- package/dist/0~work-presentation-charts.js +1 -1
- package/dist/2591.js +197 -0
- package/dist/3818.js +1090 -0
- package/dist/4104.js +970 -60
- package/dist/432.js +171 -14
- package/dist/4476.js +2008 -0
- package/dist/4560.js +674 -0
- package/dist/4650.js +70 -0
- package/dist/{1134.js → 5184.js} +183 -1
- package/dist/6489.js +18 -18
- package/dist/7060.js +132 -0
- package/dist/8715.js +2 -136
- package/dist/8928.js +16778 -0
- package/dist/9787.js +209 -0
- package/dist/core.d.ts +29 -9
- package/dist/core.js +10 -2
- package/dist/index.js +13 -3
- package/dist/internal/collaboration/office-collaboration-flat-json.d.ts +13 -0
- package/dist/internal/collaboration/office-collaboration-json.d.ts +4 -0
- package/dist/internal/collaboration/office-collaboration-presence.d.ts +86 -0
- package/dist/internal/collaboration/office-collaboration-transport.d.ts +42 -0
- package/dist/internal/collaboration/office-collaboration.d.ts +85 -0
- package/dist/internal/collaboration/office-document-collaboration-bibliography.d.ts +7 -0
- package/dist/internal/collaboration/office-document-collaboration-claims.d.ts +9 -0
- package/dist/internal/collaboration/office-document-collaboration-comments.d.ts +7 -0
- package/dist/internal/collaboration/office-document-collaboration-sidecar-utils.d.ts +27 -0
- package/dist/internal/collaboration/office-document-collaboration-sidecars.d.ts +16 -0
- package/dist/internal/collaboration/office-document-collaboration.d.ts +45 -0
- package/dist/internal/collaboration/office-markdown-collaboration.d.ts +31 -0
- package/dist/internal/collaboration/office-pdf-collaboration-claims.d.ts +4 -0
- package/dist/internal/collaboration/office-pdf-collaboration-conflicts.d.ts +2 -0
- package/dist/internal/collaboration/office-pdf-collaboration-model.d.ts +26 -0
- package/dist/internal/collaboration/office-pdf-collaboration-records.d.ts +21 -0
- package/dist/internal/collaboration/office-pdf-collaboration-types.d.ts +91 -0
- package/dist/internal/collaboration/office-pdf-collaboration-validation.d.ts +4 -0
- package/dist/internal/collaboration/office-pdf-collaboration.d.ts +35 -0
- package/dist/internal/collaboration/office-presentation-collaboration-model.d.ts +25 -0
- package/dist/internal/collaboration/office-presentation-collaboration-records.d.ts +22 -0
- package/dist/internal/collaboration/office-presentation-collaboration-validation.d.ts +4 -0
- package/dist/internal/collaboration/office-presentation-collaboration.d.ts +32 -0
- package/dist/internal/collaboration/office-spreadsheet-collaboration-cells.d.ts +13 -0
- package/dist/internal/collaboration/office-spreadsheet-collaboration-claims.d.ts +4 -0
- package/dist/internal/collaboration/office-spreadsheet-collaboration-conflicts.d.ts +2 -0
- package/dist/internal/collaboration/office-spreadsheet-collaboration-flat-json.d.ts +10 -0
- package/dist/internal/collaboration/office-spreadsheet-collaboration-model.d.ts +31 -0
- package/dist/internal/collaboration/office-spreadsheet-collaboration-records.d.ts +17 -0
- package/dist/internal/collaboration/office-spreadsheet-collaboration-validation.d.ts +4 -0
- package/dist/internal/collaboration/office-spreadsheet-collaboration.d.ts +32 -0
- package/dist/internal/features/work/components/work-document-page-border.d.ts +6 -0
- package/dist/internal/features/work/editors/document-command-catalog.d.ts +9 -0
- package/dist/internal/features/work/editors/document-editor-focus.d.ts +1 -1
- package/dist/internal/features/work/editors/document-editor.d.ts +7 -1
- package/dist/internal/features/work/editors/document-external-content.d.ts +14 -0
- package/dist/internal/features/work/editors/document-page-stack.d.ts +10 -1
- package/dist/internal/features/work/editors/document-page-thumbnail.d.ts +2 -0
- package/dist/internal/features/work/editors/document-pagination-run-coordinator.d.ts +26 -0
- package/dist/internal/features/work/editors/document-picture-properties-dialog-model.d.ts +20 -1
- package/dist/internal/features/work/editors/document-table-properties-dialog-model.d.ts +4 -1
- package/dist/internal/features/work/editors/document-toolbar.d.ts +8 -1
- package/dist/internal/features/work/editors/markdown-editor-focus.d.ts +1 -1
- package/dist/internal/features/work/editors/markdown-editor.d.ts +5 -1
- package/dist/internal/features/work/editors/markdown-toolbar.d.ts +2 -1
- package/dist/internal/features/work/editors/office-collaboration-participants.d.ts +3 -0
- package/dist/internal/features/work/editors/office-collaboration-presence-context.d.ts +17 -0
- package/dist/internal/features/work/editors/office-collaboration-presence-ui.d.ts +25 -0
- package/dist/internal/features/work/editors/office-editor-focus-handoff.d.ts +27 -0
- package/dist/internal/features/work/editors/pdf-annotation-controller.d.ts +5 -0
- package/dist/internal/features/work/editors/pdf-collaboration-presence.d.ts +3 -0
- package/dist/internal/features/work/editors/pdf-collaboration-projection.d.ts +10 -0
- package/dist/internal/features/work/editors/pdf-evidence-contract.d.ts +36 -0
- package/dist/internal/features/work/editors/pdf-evidence-overlay.d.ts +37 -0
- package/dist/internal/features/work/editors/pdf-toolbar.d.ts +2 -1
- package/dist/internal/features/work/editors/pdf-viewer-controller.d.ts +7 -1
- package/dist/internal/features/work/editors/pdf-viewer.d.ts +11 -1
- package/dist/internal/features/work/editors/presentation-collaboration-presence.d.ts +5 -0
- package/dist/internal/features/work/editors/presentation-editor-focus.d.ts +3 -2
- package/dist/internal/features/work/editors/presentation-editor-types.d.ts +3 -0
- package/dist/internal/features/work/editors/presentation-editor.d.ts +1 -1
- package/dist/internal/features/work/editors/spreadsheet-auto-filter.d.ts +9 -0
- package/dist/internal/features/work/editors/spreadsheet-cell-clear.d.ts +3 -0
- package/dist/internal/features/work/editors/spreadsheet-cell-merge.d.ts +12 -0
- package/dist/internal/features/work/editors/spreadsheet-clipboard-shortcuts.d.ts +3 -7
- package/dist/internal/features/work/editors/spreadsheet-collaboration-presence.d.ts +9 -0
- package/dist/internal/features/work/editors/spreadsheet-command-catalog.d.ts +464 -0
- package/dist/internal/features/work/editors/spreadsheet-command-controller.d.ts +45 -9
- package/dist/internal/features/work/editors/spreadsheet-context-menu.d.ts +2 -0
- package/dist/internal/features/work/editors/spreadsheet-editor-ribbon.d.ts +9 -28
- package/dist/internal/features/work/editors/spreadsheet-editor.d.ts +8 -2
- package/dist/internal/features/work/editors/spreadsheet-format-painter.d.ts +27 -0
- package/dist/internal/features/work/editors/spreadsheet-freeze-panes.d.ts +14 -0
- package/dist/internal/features/work/editors/use-document-insert-commands.d.ts +3 -2
- package/dist/internal/features/work/editors/use-document-pagination.d.ts +6 -1
- package/dist/internal/features/work/editors/use-document-review-conflicts.d.ts +28 -0
- package/dist/internal/features/work/editors/use-spreadsheet-auto-filter.d.ts +21 -0
- package/dist/internal/features/work/editors/use-spreadsheet-collaboration.d.ts +27 -0
- package/dist/internal/features/work/editors/use-spreadsheet-format-painter.d.ts +18 -0
- package/dist/internal/features/work/work-document-bookmark-references.d.ts +37 -0
- package/dist/internal/features/work/work-document-bookmarks.d.ts +29 -0
- package/dist/internal/features/work/work-document-caption-nodes.d.ts +4 -1
- package/dist/internal/features/work/work-document-comments.d.ts +1 -1
- package/dist/internal/features/work/work-document-equations.d.ts +513 -0
- package/dist/internal/features/work/work-document-extensions.d.ts +1 -0
- package/dist/internal/features/work/work-document-field-identity.d.ts +2 -0
- package/dist/internal/features/work/work-document-field-node.d.ts +2 -2
- package/dist/internal/features/work/work-document-fields.d.ts +7 -0
- package/dist/internal/features/work/work-document-image-identity.d.ts +30 -0
- package/dist/internal/features/work/work-document-image-layout.d.ts +46 -1
- package/dist/internal/features/work/work-document-image-wrap-contour.d.ts +16 -0
- package/dist/internal/features/work/work-document-incremental-layout.d.ts +2 -2
- package/dist/internal/features/work/work-document-model-codec.d.ts +4 -1
- package/dist/internal/features/work/work-document-note-integrity.d.ts +2 -0
- package/dist/internal/features/work/work-document-page-borders.d.ts +25 -0
- package/dist/internal/features/work/work-document-page-capture.d.ts +8 -0
- package/dist/internal/features/work/work-document-page-frames.d.ts +15 -0
- package/dist/internal/features/work/work-document-page-margins.d.ts +56 -0
- package/dist/internal/features/work/work-document-page-size.d.ts +47 -0
- package/dist/internal/features/work/work-document-pagination-measurement.d.ts +1 -2
- package/dist/internal/features/work/work-document-pagination-types.d.ts +7 -2
- package/dist/internal/features/work/work-document-pagination.d.ts +2 -2
- package/dist/internal/features/work/work-document-paragraph-borders.d.ts +32 -0
- package/dist/internal/features/work/work-document-paragraph-identity.d.ts +26 -0
- package/dist/internal/features/work/work-document-paragraph-shading.d.ts +18 -0
- package/dist/internal/features/work/work-document-review-conflicts.d.ts +35 -0
- package/dist/internal/features/work/work-document-section.d.ts +4 -0
- package/dist/internal/features/work/work-document-snapshot.d.ts +19 -0
- package/dist/internal/features/work/work-document-source.d.ts +23 -0
- package/dist/internal/features/work/work-document-table-column-widths.d.ts +7 -0
- package/dist/internal/features/work/work-document-table-property-changes.d.ts +3 -0
- package/dist/internal/features/work/work-document-table-row-identity.d.ts +15 -0
- package/dist/internal/features/work/work-document-table-sizing.d.ts +3 -0
- package/dist/internal/features/work/work-document-text-layout.d.ts +3 -1
- package/dist/internal/features/work/work-document-word-line-metrics.d.ts +2 -0
- package/dist/internal/features/work/work-docx-bookmark-diagnostics.d.ts +3 -0
- package/dist/internal/features/work/work-docx-bookmark-import.d.ts +24 -0
- package/dist/internal/features/work/work-docx-bookmarks.d.ts +17 -0
- package/dist/internal/features/work/work-docx-comment-durable-id-preservation.d.ts +2 -0
- package/dist/internal/features/work/work-docx-comment-export.d.ts +3 -0
- package/dist/internal/features/work/work-docx-comment-metadata.d.ts +2 -0
- package/dist/internal/features/work/work-docx-drawing-extension-preservation.d.ts +4 -0
- package/dist/internal/features/work/work-docx-equation-diagnostics.d.ts +3 -0
- package/dist/internal/features/work/work-docx-equation-export.d.ts +14 -0
- package/dist/internal/features/work/work-docx-equation-import.d.ts +30 -0
- package/dist/internal/features/work/work-docx-equation-story.d.ts +9 -0
- package/dist/internal/features/work/work-docx-export-formatting.d.ts +3 -1
- package/dist/internal/features/work/work-docx-export-image.d.ts +5 -1
- package/dist/internal/features/work/work-docx-export.d.ts +1 -1
- package/dist/internal/features/work/work-docx-field-instructions.d.ts +8 -0
- package/dist/internal/features/work/work-docx-font-table-preservation.d.ts +3 -0
- package/dist/internal/features/work/work-docx-ignorable-extension-preservation.d.ts +15 -0
- package/dist/internal/features/work/work-docx-image-crop.d.ts +12 -0
- package/dist/internal/features/work/work-docx-image-identity.d.ts +17 -0
- package/dist/internal/features/work/work-docx-image-layer.d.ts +12 -0
- package/dist/internal/features/work/work-docx-image-layout-import.d.ts +14 -2
- package/dist/internal/features/work/work-docx-image-wrap.d.ts +15 -0
- package/dist/internal/features/work/work-docx-import.d.ts +13 -3
- package/dist/internal/features/work/work-docx-list-export.d.ts +18 -0
- package/dist/internal/features/work/work-docx-list-import.d.ts +14 -0
- package/dist/internal/features/work/work-docx-note-comment-content-control-block-preservation.d.ts +18 -0
- package/dist/internal/features/work/work-docx-note-comment-content-control-model.d.ts +47 -0
- package/dist/internal/features/work/work-docx-note-comment-content-control-preservation.d.ts +4 -0
- package/dist/internal/features/work/work-docx-note-comment-content-control-properties.d.ts +17 -0
- package/dist/internal/features/work/work-docx-note-comment-content-control-table-model.d.ts +17 -0
- package/dist/internal/features/work/work-docx-note-comment-content-control-xml.d.ts +14 -0
- package/dist/internal/features/work/work-docx-note-comment-extension-preservation.d.ts +2 -0
- package/dist/internal/features/work/work-docx-note-comment-hyperlink-content.d.ts +40 -0
- package/dist/internal/features/work/work-docx-note-comment-hyperlink-preservation.d.ts +5 -0
- package/dist/internal/features/work/work-docx-note-comment-hyperlink-relationships.d.ts +35 -0
- package/dist/internal/features/work/work-docx-note-comment-identity.d.ts +15 -0
- package/dist/internal/features/work/work-docx-note-comment-run-preservation.d.ts +4 -0
- package/dist/internal/features/work/work-docx-note-comment-run-properties.d.ts +2 -0
- package/dist/internal/features/work/work-docx-note-image-import.d.ts +12 -0
- package/dist/internal/features/work/work-docx-note-image-relationships.d.ts +1 -0
- package/dist/internal/features/work/work-docx-numbering-extension-preservation.d.ts +6 -0
- package/dist/internal/features/work/work-docx-numbering.d.ts +1 -0
- package/dist/internal/features/work/work-docx-page-borders-diagnostics.d.ts +3 -0
- package/dist/internal/features/work/work-docx-page-borders-import.d.ts +10 -0
- package/dist/internal/features/work/work-docx-page-margins-diagnostics.d.ts +3 -0
- package/dist/internal/features/work/work-docx-page-margins-import.d.ts +18 -0
- package/dist/internal/features/work/work-docx-page-size-diagnostics.d.ts +2 -0
- package/dist/internal/features/work/work-docx-page-size-import.d.ts +17 -0
- package/dist/internal/features/work/work-docx-paragraph-borders-diagnostics.d.ts +3 -0
- package/dist/internal/features/work/work-docx-paragraph-borders-export.d.ts +18 -0
- package/dist/internal/features/work/work-docx-paragraph-borders-import.d.ts +24 -0
- package/dist/internal/features/work/work-docx-paragraph-default-collapsed.d.ts +19 -0
- package/dist/internal/features/work/work-docx-paragraph-extension-preservation.d.ts +2 -0
- package/dist/internal/features/work/work-docx-paragraph-identity-import.d.ts +10 -0
- package/dist/internal/features/work/work-docx-paragraph-identity.d.ts +18 -0
- package/dist/internal/features/work/work-docx-paragraph-pagination-import.d.ts +6 -1
- package/dist/internal/features/work/work-docx-paragraph-shading-diagnostics.d.ts +3 -0
- package/dist/internal/features/work/work-docx-paragraph-shading-export.d.ts +5 -0
- package/dist/internal/features/work/work-docx-paragraph-shading-import.d.ts +18 -0
- package/dist/internal/features/work/work-docx-run-formatting-import.d.ts +3 -0
- package/dist/internal/features/work/work-docx-settings-preservation.d.ts +10 -0
- package/dist/internal/features/work/work-docx-settings-xml.d.ts +16 -0
- package/dist/internal/features/work/work-docx-style-extension-preservation.d.ts +2 -0
- package/dist/internal/features/work/work-docx-table-cell-export.d.ts +2 -1
- package/dist/internal/features/work/work-docx-table-cell-import.d.ts +3 -0
- package/dist/internal/features/work/work-docx-table-extension-preservation.d.ts +2 -0
- package/dist/internal/features/work/work-docx-table-row-import.d.ts +2 -0
- package/dist/internal/features/work/work-docx-table-sizing-import.d.ts +1 -0
- package/dist/internal/features/work/work-docx-theme-reference.d.ts +23 -0
- package/dist/internal/features/work/work-docx-theme.d.ts +4 -1
- package/dist/internal/features/work/work-docx-twips.d.ts +12 -0
- package/dist/internal/features/work/work-file-contract.d.ts +1 -0
- package/dist/internal/features/work/work-file-io.d.ts +1 -1
- package/dist/internal/features/work/work-markdown-extensions.d.ts +4 -1
- package/dist/internal/features/work/work-ooxml-package-preservation.d.ts +12 -0
- package/dist/internal/features/work/work-ooxml-package-security.d.ts +6 -0
- package/dist/internal/features/work/work-ooxml-relationship-preservation.d.ts +10 -0
- package/dist/internal/features/work/work-ooxml-xml.d.ts +2 -0
- package/dist/internal/features/work/work-pdf-export.d.ts +10 -0
- package/dist/internal/features/work/work-repository.d.ts +2 -0
- package/dist/internal/features/work/work-types.d.ts +15 -2
- package/dist/internal/kernel/office-kernel-client-types.d.ts +1 -0
- package/dist/internal/kernel/office-kernel-protocol.d.ts +7 -0
- package/dist/internal/kernel/office-kernel-version.d.ts +1 -1
- package/dist/office-kernel.wasm +0 -0
- package/dist/office-kernel.worker.js +93 -41
- package/dist/react.d.ts +18 -12
- package/dist/react.js +1 -1
- package/dist/styles.css +1153 -14
- package/dist/vue.d.ts +48 -5
- package/dist/vue.js +42 -3
- package/dist/web-component.d.ts +24 -2
- package/dist/web-component.js +101 -2
- package/docs/latest/en/browser-editor-architecture.md +231 -49
- package/package.json +19 -4
- package/dist/0~152.js +0 -94
- package/dist/0~2582.js +0 -485
- package/dist/0~4750.js +0 -939
- package/dist/0~5861.js +0 -596
- package/dist/0~work-document-extensions.js +0 -3045
- package/dist/0~work-document-model-codec.js +0 -42
- package/dist/0~work-docx-bibliography.js +0 -347
- package/dist/0~work-docx-page-color.js +0 -42
- package/dist/2881.js +0 -1455
- package/dist/8728.js +0 -723
|
@@ -1,22 +1,22 @@
|
|
|
1
1
|
import { __webpack_require__ } from "./0~rslib-runtime.js";
|
|
2
2
|
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
3
3
|
import { Workbook } from "@fortune-sheet/react";
|
|
4
|
-
import { AlignCenter, AlignLeft, AlignRight, AlignVerticalJustifyCenter, AlignVerticalJustifyEnd, AlignVerticalJustifyStart, ArrowDown, ArrowLeft, ArrowRight, ArrowUp, BarChart3, Bold, Bookmark, Calculator, Check, ChevronDown, ChevronLeft, ChevronRight, ClipboardPaste, Cloud, Copy, CopyPlus, DecimalsArrowLeft, DecimalsArrowRight, Eraser, Eye, EyeOff, Grid3X3, Italic, KeyRound, Layers2, Merge, MoveHorizontal, MoveVertical, Palette, Pencil, Percent, Plus, Printer, Redo2, RefreshCw, Save, Scissors, Search, ShieldCheck, TableProperties, Trash2, Underline, Undo2, WrapText, X } from "lucide-react";
|
|
4
|
+
import { AlignCenter, AlignLeft, AlignRight, AlignVerticalJustifyCenter, AlignVerticalJustifyEnd, AlignVerticalJustifyStart, ArrowDown, ArrowLeft, ArrowRight, ArrowUp, BarChart3, BetweenHorizontalEnd, BetweenHorizontalStart, BetweenVerticalEnd, BetweenVerticalStart, Bold, Bookmark, Calculator, Check, ChevronDown, ChevronLeft, ChevronRight, ClipboardPaste, Cloud, Columns3, Copy, CopyPlus, DecimalsArrowLeft, DecimalsArrowRight, Eraser, Eye, EyeOff, FileX2, Grid3X3, Italic, KeyRound, Layers2, Link2Off, ListFilter, Merge, MessageSquareX, MoveHorizontal, MoveVertical, Paintbrush, Palette, PanelLeft, PanelTop, PanelsTopLeft, Pencil, Percent, Plus, Printer, Redo2, RefreshCw, Rows3, Save, Scissors, Search, ShieldCheck, SortAsc, SortDesc, TableProperties, Trash2, Underline, Undo2, WrapText, X } from "lucide-react";
|
|
5
5
|
import { Fragment as external_react_Fragment, useCallback, useEffect, useId, useLayoutEffect, useMemo, useRef, useState } from "react";
|
|
6
|
-
import { genarate, update as core_update } from "@fortune-sheet/core";
|
|
7
|
-
import { withoutEditableRange, SPREADSHEET_CONDITIONAL_COMPARISON_OPERATORS, editableRangeRequiresCredentials, normalizeSpreadsheetConditionalIconSetFormat, defaultSpreadsheetDataBarOptions, spreadsheetConditionalThresholdValue, normalizeSpreadsheetConditionalVisualOptions, withSheetProtection, spreadsheetProtectionKey, defaultSpreadsheetColorScaleThresholds, effectiveSpreadsheetPageSetup, protectedSheetCount, SPREADSHEET_CONDITIONAL_ICON_SETS, withSheetSelectionPermissions, withEditableRange, spreadsheetConditionalComparisonNeedsUpperValue, isSpreadsheetConditionalComparisonOperator, drawSpreadsheetConditionalIcon, spreadsheetConditionalIconForValue, defaultSpreadsheetConditionalIconThresholds, sheetProtectionAuthority, spreadsheetConditionalThresholdsEqual, editableRangeCellCount, unlockedCellCount } from "./
|
|
8
|
-
import {
|
|
9
|
-
import { useOfficeTaskPaneEscape, OfficeCheckbox, CommittedOfficeNumberField, useOfficeDialog, useOfficeTaskPaneModal, isOfficeKernelSpreadsheetError, officeFontFamilies, CollectionState, office_kernel_spreadsheet_protocol_OFFICE_KERNEL_SPREADSHEET_MAX_ROWS, OfficeNumberField, createOfficeKernelClient, handleOfficeTaskPaneKeyDown } from "./0~7048.js";
|
|
6
|
+
import { genarate, indexToColumnChar, update as core_update } from "@fortune-sheet/core";
|
|
7
|
+
import { withoutEditableRange, SPREADSHEET_CONDITIONAL_COMPARISON_OPERATORS, editableRangeRequiresCredentials, normalizeSpreadsheetConditionalIconSetFormat, defaultSpreadsheetDataBarOptions, spreadsheetConditionalThresholdValue, normalizeSpreadsheetConditionalVisualOptions, withSheetProtection, spreadsheetProtectionKey, defaultSpreadsheetColorScaleThresholds, effectiveSpreadsheetPageSetup, protectedSheetCount, SPREADSHEET_CONDITIONAL_ICON_SETS, withSheetSelectionPermissions, withEditableRange, spreadsheetConditionalComparisonNeedsUpperValue, createOfficeSpreadsheetCollaborationBinding as createWorkOfficeSpreadsheetCollaborationBinding, isSpreadsheetConditionalComparisonOperator, drawSpreadsheetConditionalIcon, spreadsheetConditionalIconForValue, defaultSpreadsheetConditionalIconThresholds, sheetProtectionAuthority, readOfficeSpreadsheetCollaboration as readWorkOfficeSpreadsheetCollaboration, spreadsheetConditionalThresholdsEqual, editableRangeCellCount, unlockedCellCount } from "./4476.js";
|
|
8
|
+
import { useOfficeTaskPaneEscape, OfficeCheckbox, CommittedOfficeNumberField, useOfficeDialog, useOfficeTaskPaneModal, createOfficeKernelClient, officeFontFamilies, CollectionState, OfficeNumberField, handleOfficeTaskPaneKeyDown } from "./0~7048.js";
|
|
10
9
|
import { isOfficeShortcutBlocked, OfficeColorPicker } from "./0~3635.js";
|
|
11
10
|
import { createOfficeEditorExtension, useOfficeEditorRuntime, useOfficeEditorKeyboardShortcuts } from "./0~3557.js";
|
|
11
|
+
import { showToast } from "./6489.js";
|
|
12
12
|
import { workSpreadsheetChartSupportsGrouping, createSpreadsheetChartFromSelection, normalizeWorkSpreadsheetDataLabelPosition, normalizeSpreadsheetPrintTitleRows, normalizeSpreadsheetPrintTitleColumns, formulaHasStructuredReference, normalizeWorkSpreadsheetErrorBars, defaultPivotValueCaption, workSpreadsheetChartSupportsBarSpacing, normalizeWorkSpreadsheetChartGrouping, normalizeWorkSpreadsheetChartAxisGroup, normalizeWorkSpreadsheetScatterStyle, spreadsheetPivotAggregationLabel, workSpreadsheetChartAxisIsCategoryAxis, reconcileSpreadsheetChartPreviews, normalizeWorkSpreadsheetChartAxes, normalizeWorkSpreadsheetDoughnutHoleSize, normalizeWorkSpreadsheetChartLegendPosition, spreadsheetChartCount, workSpreadsheetChartTypeLabel, normalizeWorkSpreadsheetTrendline, spreadsheetPivotOutputContains, effectiveSpreadsheetCalculationSettings, normalizeWorkSpreadsheetDataLabels, spreadsheetPivotIntersects, normalizeSpreadsheetPrintArea, spreadsheetCellAddress, formatSpreadsheetCellRanges, normalizeWorkSpreadsheetChartLayout, spreadsheetFormulaRangeForCell, workSpreadsheetChartAxisIsValueAxis, normalizeWorkSpreadsheetChartSmoothLines, spreadsheetPivotFilterValueKey, normalizeWorkSpreadsheetBubbleScale, normalizeWorkSpreadsheetChartSeriesStyle, volatileSpreadsheetFormulaFunctions, normalizeWorkSpreadsheetBubbleSizeRepresents, workSpreadsheetChartSupportsTrendlines, normalizeWorkSpreadsheetChartLegendOverlay, parseSpreadsheetChartReference, workSpreadsheetChartGroupingIsStacked, normalizeWorkSpreadsheetChartGapWidth, workSpreadsheetChartSupportsSmoothLines, refreshSpreadsheetPivotTables, createSpreadsheetPivotFromSelection, spreadsheetPivotCount, reconcileSpreadsheetPivots, workSpreadsheetChartSupportsErrorBars, formulaHasExternalReference, isValidSpreadsheetDefinedName, spreadsheetPivotValidation, deleteSpreadsheetPivotTable, workSpreadsheetChartAxisDefaultLabelPosition, workSpreadsheetChartSupportsSeriesAnalysis, parseSpreadsheetCellRanges, spreadsheetPivotFields, spreadsheetPivotFilterItems, normalizeWorkSpreadsheetChartOverlap, spreadsheetFormulaRangeConflict, spreadsheetSheetsWithChartPreviews, workSpreadsheetChartUsesNumericXAxis, workSpreadsheetChartAxisShowsMajorGridlinesByDefault, workSpreadsheetChartSupportsAxes, normalizeWorkSpreadsheetCombinationSeriesType, normalizeWorkSpreadsheetRadarStyle } from "./8715.js";
|
|
13
13
|
import { unsupportedSpreadsheetFormulaFunctions } from "./0~work-spreadsheet-formula-support.js";
|
|
14
14
|
import { WorkspaceContextMenu, isWorkspaceContextMenuKeyboardEvent, WorkOfficeZoomControls, WorkOfficeStatusBar, WorkOfficeRibbon, workspaceContextMenuPosition, OfficeSelect, WorkOfficeRibbonGroup, WorkOfficePreviewBar, WorkOfficeRibbonButton } from "./0~4595.js";
|
|
15
|
-
import { moveOfficeMenuFocus, stepOfficeZoom, Popover, button_Button, icon_button_IconButton, office_text_field_OfficeTextField, useDialogFocusScope, useOfficeEditorWheelZoom } from "./0~
|
|
16
|
-
import { useOfficeDraft } from "./0~
|
|
15
|
+
import { moveOfficeMenuFocus, stepOfficeZoom, Popover, useOfficeRemoteParticipants, button_Button, officePresenceColor, useOfficePublishPresenceLocation, icon_button_IconButton, office_text_field_OfficeTextField, useDialogFocusScope, useOfficeEditorWheelZoom } from "./0~6090.js";
|
|
16
|
+
import { useOfficeDraft, InlineNotice } from "./0~345.js";
|
|
17
17
|
import { spreadsheetAgentMenuItems, SpreadsheetChartSeriesStyleEditor, normalizeOptionalOfficeNumber, normalizeRequiredOfficeNumber, SpreadsheetErrorBarEditor, useOfficeHistory, spreadsheetAgentSelection, SpreadsheetTrendlineEditor, applySpreadsheetAgentProposalChanges } from "./0~3539.js";
|
|
18
|
-
import { StateView } from "./432.js";
|
|
19
|
-
import { createOfficeId as createWorkId } from "./
|
|
18
|
+
import { useOfficeEditorFocusOrigin, useOfficeCollaborationLocationNavigator, StateView } from "./432.js";
|
|
19
|
+
import { OFFICE_KERNEL_SPREADSHEET_MAX_ROWS, createOfficeId as createWorkId, isOfficeKernelSpreadsheetError } from "./5184.js";
|
|
20
20
|
var spreadsheet_editor_namespaceObject = {};
|
|
21
21
|
__webpack_require__.r(spreadsheet_editor_namespaceObject);
|
|
22
22
|
__webpack_require__.d(spreadsheet_editor_namespaceObject, {
|
|
@@ -483,249 +483,6 @@ function decodeColumn(value) {
|
|
|
483
483
|
for (const character of value.toUpperCase())result = 26 * result + character.charCodeAt(0) - 64;
|
|
484
484
|
return result - 1;
|
|
485
485
|
}
|
|
486
|
-
const spreadsheetSystemClipboardTimeoutMs = 800;
|
|
487
|
-
function spreadsheetCoreContextMenuItems({ can, clipboard = browserSpreadsheetClipboard, commands, selection }) {
|
|
488
|
-
const copy = (cut)=>{
|
|
489
|
-
copySpreadsheetSelection(clipboard, selection.clipboard, cut).then((copied)=>{
|
|
490
|
-
if (copied && cut && !commands.clearSelectedCells()) showToast('选区已复制,但无法清除原内容。', 'error');
|
|
491
|
-
});
|
|
492
|
-
};
|
|
493
|
-
return [
|
|
494
|
-
{
|
|
495
|
-
id: 'cut-cells',
|
|
496
|
-
label: '剪切',
|
|
497
|
-
icon: /*#__PURE__*/ jsx(Scissors, {
|
|
498
|
-
size: 14
|
|
499
|
-
}),
|
|
500
|
-
shortcut: '⌘X',
|
|
501
|
-
ariaKeyShortcut: 'Control+X Meta+X',
|
|
502
|
-
disabled: !can.clearSelectedCells(),
|
|
503
|
-
onSelect: ()=>copy(true)
|
|
504
|
-
},
|
|
505
|
-
{
|
|
506
|
-
id: 'copy-cells',
|
|
507
|
-
label: '复制',
|
|
508
|
-
icon: /*#__PURE__*/ jsx(Copy, {
|
|
509
|
-
size: 14
|
|
510
|
-
}),
|
|
511
|
-
shortcut: '⌘C',
|
|
512
|
-
ariaKeyShortcut: 'Control+C Meta+C',
|
|
513
|
-
onSelect: ()=>copy(false)
|
|
514
|
-
},
|
|
515
|
-
{
|
|
516
|
-
id: 'paste-cells',
|
|
517
|
-
label: '粘贴',
|
|
518
|
-
icon: /*#__PURE__*/ jsx(ClipboardPaste, {
|
|
519
|
-
size: 14
|
|
520
|
-
}),
|
|
521
|
-
shortcut: '⌘V',
|
|
522
|
-
ariaKeyShortcut: 'Control+V Meta+V',
|
|
523
|
-
disabled: !can.pasteCells([
|
|
524
|
-
[
|
|
525
|
-
''
|
|
526
|
-
]
|
|
527
|
-
]),
|
|
528
|
-
onSelect: ()=>void pasteSpreadsheetSelection(clipboard, commands.pasteCells)
|
|
529
|
-
},
|
|
530
|
-
{
|
|
531
|
-
id: 'clear-cells',
|
|
532
|
-
label: '清除内容',
|
|
533
|
-
icon: /*#__PURE__*/ jsx(Eraser, {
|
|
534
|
-
size: 14
|
|
535
|
-
}),
|
|
536
|
-
shortcut: 'Delete',
|
|
537
|
-
ariaKeyShortcut: 'Delete',
|
|
538
|
-
separatorBefore: true,
|
|
539
|
-
disabled: !can.clearSelectedCells(),
|
|
540
|
-
onSelect: ()=>{
|
|
541
|
-
if (!commands.clearSelectedCells()) showToast(`无法清除选区 ${selection.reference}。`, 'error');
|
|
542
|
-
}
|
|
543
|
-
}
|
|
544
|
-
];
|
|
545
|
-
}
|
|
546
|
-
function spreadsheetStructureContextMenuItems({ axis, can, commands, onResize }) {
|
|
547
|
-
const row = 'row' === axis;
|
|
548
|
-
const subject = row ? '行' : '列';
|
|
549
|
-
const before = row ? '上方' : '左侧';
|
|
550
|
-
const after = row ? '下方' : '右侧';
|
|
551
|
-
const defaultSize = row ? 24 : 96;
|
|
552
|
-
return [
|
|
553
|
-
...spreadsheetSortContextMenuItems({
|
|
554
|
-
can,
|
|
555
|
-
commands,
|
|
556
|
-
idSuffix: axis
|
|
557
|
-
}),
|
|
558
|
-
{
|
|
559
|
-
id: `insert-${axis}-before`,
|
|
560
|
-
label: `在${before}插入${subject}`,
|
|
561
|
-
icon: /*#__PURE__*/ jsx(Plus, {
|
|
562
|
-
size: 14
|
|
563
|
-
}),
|
|
564
|
-
separatorBefore: true,
|
|
565
|
-
disabled: !can.insertSelectedStructure(axis, 'before'),
|
|
566
|
-
onSelect: ()=>commands.insertSelectedStructure(axis, 'before')
|
|
567
|
-
},
|
|
568
|
-
{
|
|
569
|
-
id: `insert-${axis}-after`,
|
|
570
|
-
label: `在${after}插入${subject}`,
|
|
571
|
-
icon: /*#__PURE__*/ jsx(Plus, {
|
|
572
|
-
size: 14
|
|
573
|
-
}),
|
|
574
|
-
disabled: !can.insertSelectedStructure(axis, 'after'),
|
|
575
|
-
onSelect: ()=>commands.insertSelectedStructure(axis, 'after')
|
|
576
|
-
},
|
|
577
|
-
{
|
|
578
|
-
id: `delete-${axis}`,
|
|
579
|
-
label: `删除所选${subject}`,
|
|
580
|
-
icon: /*#__PURE__*/ jsx(Trash2, {
|
|
581
|
-
size: 14
|
|
582
|
-
}),
|
|
583
|
-
danger: true,
|
|
584
|
-
disabled: !can.deleteSelectedStructure(axis),
|
|
585
|
-
onSelect: ()=>commands.deleteSelectedStructure(axis)
|
|
586
|
-
},
|
|
587
|
-
{
|
|
588
|
-
id: `resize-${axis}`,
|
|
589
|
-
label: row ? '行高…' : '列宽…',
|
|
590
|
-
icon: row ? /*#__PURE__*/ jsx(MoveVertical, {
|
|
591
|
-
size: 14
|
|
592
|
-
}) : /*#__PURE__*/ jsx(MoveHorizontal, {
|
|
593
|
-
size: 14
|
|
594
|
-
}),
|
|
595
|
-
disabled: !can.setSelectedStructureSize(axis, defaultSize),
|
|
596
|
-
onSelect: ()=>onResize(axis)
|
|
597
|
-
},
|
|
598
|
-
{
|
|
599
|
-
id: `hide-${axis}`,
|
|
600
|
-
label: `隐藏所选${subject}`,
|
|
601
|
-
icon: /*#__PURE__*/ jsx(EyeOff, {
|
|
602
|
-
size: 14
|
|
603
|
-
}),
|
|
604
|
-
separatorBefore: true,
|
|
605
|
-
disabled: !can.setSelectedStructureHidden(axis, true),
|
|
606
|
-
onSelect: ()=>commands.setSelectedStructureHidden(axis, true)
|
|
607
|
-
},
|
|
608
|
-
{
|
|
609
|
-
id: `show-${axis}`,
|
|
610
|
-
label: `取消隐藏${subject}`,
|
|
611
|
-
icon: /*#__PURE__*/ jsx(Eye, {
|
|
612
|
-
size: 14
|
|
613
|
-
}),
|
|
614
|
-
disabled: !can.setSelectedStructureHidden(axis, false),
|
|
615
|
-
onSelect: ()=>commands.setSelectedStructureHidden(axis, false)
|
|
616
|
-
}
|
|
617
|
-
];
|
|
618
|
-
}
|
|
619
|
-
function spreadsheetSortContextMenuItems({ can, commands, idSuffix = 'selection', separatorBefore = false }) {
|
|
620
|
-
return [
|
|
621
|
-
{
|
|
622
|
-
id: `sort-${idSuffix}-ascending`,
|
|
623
|
-
label: '升序排列',
|
|
624
|
-
icon: /*#__PURE__*/ jsx(ArrowUp, {
|
|
625
|
-
size: 14
|
|
626
|
-
}),
|
|
627
|
-
separatorBefore,
|
|
628
|
-
disabled: !can.sortSelectedCells('ascending'),
|
|
629
|
-
onSelect: ()=>commands.sortSelectedCells('ascending')
|
|
630
|
-
},
|
|
631
|
-
{
|
|
632
|
-
id: `sort-${idSuffix}-descending`,
|
|
633
|
-
label: '降序排列',
|
|
634
|
-
icon: /*#__PURE__*/ jsx(ArrowDown, {
|
|
635
|
-
size: 14
|
|
636
|
-
}),
|
|
637
|
-
disabled: !can.sortSelectedCells('descending'),
|
|
638
|
-
onSelect: ()=>commands.sortSelectedCells('descending')
|
|
639
|
-
}
|
|
640
|
-
];
|
|
641
|
-
}
|
|
642
|
-
function parseSpreadsheetClipboardText(value) {
|
|
643
|
-
if (!value) return [];
|
|
644
|
-
const normalized = value.replace(/\r\n?/g, '\n').replace(/\n$/, '');
|
|
645
|
-
if (!normalized) return [];
|
|
646
|
-
const rows = normalized.split('\n').map((row)=>row.split('\t'));
|
|
647
|
-
const width = Math.max(...rows.map((row)=>row.length));
|
|
648
|
-
return rows.map((row)=>[
|
|
649
|
-
...row,
|
|
650
|
-
...Array.from({
|
|
651
|
-
length: width - row.length
|
|
652
|
-
}, ()=>'')
|
|
653
|
-
]);
|
|
654
|
-
}
|
|
655
|
-
const browserSpreadsheetClipboard = {
|
|
656
|
-
readText: ()=>readSpreadsheetClipboardText("u" > typeof navigator && navigator.clipboard?.readText ? ()=>navigator.clipboard.readText() : void 0, readLocalClipboard, spreadsheetSystemClipboardTimeoutMs, canReadBrowserSystemClipboard),
|
|
657
|
-
writeText: (value)=>writeSpreadsheetClipboardText(value, "u" > typeof navigator && navigator.clipboard?.writeText ? (next)=>navigator.clipboard.writeText(next) : void 0, writeLocalClipboard)
|
|
658
|
-
};
|
|
659
|
-
async function readSpreadsheetClipboardText(readSystem, readLocal, timeoutMs = spreadsheetSystemClipboardTimeoutMs, canReadSystem = ()=>true) {
|
|
660
|
-
if (readSystem && await canReadSystem()) try {
|
|
661
|
-
const value = await withSpreadsheetClipboardTimeout(readSystem(), timeoutMs);
|
|
662
|
-
if (value) return value;
|
|
663
|
-
} catch {}
|
|
664
|
-
return readLocal();
|
|
665
|
-
}
|
|
666
|
-
async function canReadBrowserSystemClipboard() {
|
|
667
|
-
if ("u" < typeof navigator || !navigator.permissions?.query) return true;
|
|
668
|
-
try {
|
|
669
|
-
const permission = await navigator.permissions.query({
|
|
670
|
-
name: 'clipboard-read'
|
|
671
|
-
});
|
|
672
|
-
return 'granted' === permission.state;
|
|
673
|
-
} catch {
|
|
674
|
-
return true;
|
|
675
|
-
}
|
|
676
|
-
}
|
|
677
|
-
async function writeSpreadsheetClipboardText(value, writeSystem, writeLocal, timeoutMs = spreadsheetSystemClipboardTimeoutMs) {
|
|
678
|
-
writeLocal(value);
|
|
679
|
-
if (!writeSystem) return;
|
|
680
|
-
try {
|
|
681
|
-
await withSpreadsheetClipboardTimeout(writeSystem(value), timeoutMs);
|
|
682
|
-
} catch {}
|
|
683
|
-
}
|
|
684
|
-
async function copySpreadsheetSelection(clipboard, value, cut) {
|
|
685
|
-
try {
|
|
686
|
-
await clipboard.writeText(value);
|
|
687
|
-
showToast(cut ? '选区已剪切' : '选区已复制', 'success');
|
|
688
|
-
return true;
|
|
689
|
-
} catch {
|
|
690
|
-
showToast('无法访问剪贴板,请使用系统快捷键。', 'error');
|
|
691
|
-
return false;
|
|
692
|
-
}
|
|
693
|
-
}
|
|
694
|
-
async function pasteSpreadsheetSelection(clipboard, paste) {
|
|
695
|
-
try {
|
|
696
|
-
const values = parseSpreadsheetClipboardText(await clipboard.readText());
|
|
697
|
-
if (!values.length) return void showToast('剪贴板中没有可粘贴的表格内容。', 'error');
|
|
698
|
-
if (!paste(values)) showToast('当前选区无法粘贴这些内容。', 'error');
|
|
699
|
-
} catch {
|
|
700
|
-
showToast('无法读取剪贴板,请使用系统粘贴快捷键。', 'error');
|
|
701
|
-
}
|
|
702
|
-
}
|
|
703
|
-
function readLocalClipboard() {
|
|
704
|
-
try {
|
|
705
|
-
return sessionStorage.getItem('a3s-office-spreadsheet-clipboard') ?? '';
|
|
706
|
-
} catch {
|
|
707
|
-
return '';
|
|
708
|
-
}
|
|
709
|
-
}
|
|
710
|
-
function writeLocalClipboard(value) {
|
|
711
|
-
try {
|
|
712
|
-
sessionStorage.setItem('a3s-office-spreadsheet-clipboard', value);
|
|
713
|
-
} catch {}
|
|
714
|
-
}
|
|
715
|
-
async function withSpreadsheetClipboardTimeout(request, timeoutMs) {
|
|
716
|
-
let timeout;
|
|
717
|
-
const expired = new Promise((_resolve, reject)=>{
|
|
718
|
-
timeout = setTimeout(()=>reject(new Error('Spreadsheet clipboard request timed out.')), Math.max(0, timeoutMs));
|
|
719
|
-
});
|
|
720
|
-
try {
|
|
721
|
-
return await Promise.race([
|
|
722
|
-
request,
|
|
723
|
-
expired
|
|
724
|
-
]);
|
|
725
|
-
} finally{
|
|
726
|
-
if (timeout) clearTimeout(timeout);
|
|
727
|
-
}
|
|
728
|
-
}
|
|
729
486
|
const spreadsheetFontSizes = [
|
|
730
487
|
9,
|
|
731
488
|
10,
|
|
@@ -1021,38 +778,561 @@ function spreadsheetFormulaHistoryCellType(cellType) {
|
|
|
1021
778
|
};
|
|
1022
779
|
return Object.keys(normalized).length ? normalized : void 0;
|
|
1023
780
|
}
|
|
1024
|
-
function runSpreadsheetClipboardShortcut(event,
|
|
1025
|
-
|
|
1026
|
-
if (event.defaultPrevented || event.repeat || event.altKey || event.shiftKey || !(event.metaKey || event.ctrlKey) || !clipboardShortcutKeys.has(key) || isOfficeShortcutBlocked(event.target) || isSpreadsheetNativeTextUndoTarget(event.target)) return false;
|
|
1027
|
-
const selectionText = 'v' === key ? null : options.readSelectionText();
|
|
1028
|
-
if ('v' !== key && null === selectionText) return false;
|
|
781
|
+
function runSpreadsheetClipboardShortcut(event, canExecute, execute) {
|
|
782
|
+
if (event.defaultPrevented || event.repeat || event.altKey || event.shiftKey || !(event.metaKey || event.ctrlKey) || isOfficeShortcutBlocked(event.target) || isSpreadsheetNativeTextUndoTarget(event.target) || !canExecute() || !execute()) return false;
|
|
1029
783
|
event.preventDefault();
|
|
1030
784
|
event.stopPropagation();
|
|
1031
|
-
if ('v' === key) {
|
|
1032
|
-
options.clipboard.readText().then((value)=>{
|
|
1033
|
-
const cells = parseSpreadsheetClipboardText(value);
|
|
1034
|
-
if (cells.length) options.pasteCells(cells);
|
|
1035
|
-
}).catch(()=>void 0).finally(options.restoreFocus);
|
|
1036
|
-
return true;
|
|
1037
|
-
}
|
|
1038
|
-
options.clipboard.writeText(selectionText ?? '').catch(()=>void 0);
|
|
1039
|
-
if ('x' === key) options.clearSelectedCells();
|
|
1040
|
-
options.restoreFocus();
|
|
1041
785
|
return true;
|
|
1042
786
|
}
|
|
1043
|
-
const
|
|
1044
|
-
'
|
|
1045
|
-
'
|
|
1046
|
-
'
|
|
1047
|
-
|
|
1048
|
-
|
|
1049
|
-
|
|
1050
|
-
|
|
1051
|
-
|
|
1052
|
-
|
|
1053
|
-
|
|
1054
|
-
|
|
1055
|
-
|
|
787
|
+
const spreadsheetCellFormatProperties = [
|
|
788
|
+
'bg',
|
|
789
|
+
'bl',
|
|
790
|
+
'it',
|
|
791
|
+
'ff',
|
|
792
|
+
'fs',
|
|
793
|
+
'fc',
|
|
794
|
+
'ht',
|
|
795
|
+
'vt',
|
|
796
|
+
'tb',
|
|
797
|
+
'cl',
|
|
798
|
+
'un',
|
|
799
|
+
'tr',
|
|
800
|
+
'rt',
|
|
801
|
+
'ct',
|
|
802
|
+
'lo',
|
|
803
|
+
'hi'
|
|
804
|
+
];
|
|
805
|
+
function clearSpreadsheetSheetSelection(sheet, selection, mode) {
|
|
806
|
+
const range = normalizeClearRange(selection);
|
|
807
|
+
const data = sheet.data?.map((row, rowIndex)=>{
|
|
808
|
+
if (rowIndex < range.row[0] || rowIndex > range.row[1]) return row;
|
|
809
|
+
return row.map((cell, columnIndex)=>clearSpreadsheetCellAt(cell, rowIndex, columnIndex, range, mode));
|
|
810
|
+
});
|
|
811
|
+
const celldata = data ? void 0 : sheet.celldata?.flatMap((entry)=>{
|
|
812
|
+
const cell = clearSpreadsheetCellAt(entry.v, entry.r, entry.c, range, mode);
|
|
813
|
+
return cell ? [
|
|
814
|
+
{
|
|
815
|
+
...entry,
|
|
816
|
+
v: cell
|
|
817
|
+
}
|
|
818
|
+
] : [];
|
|
819
|
+
});
|
|
820
|
+
let next = {
|
|
821
|
+
...sheet,
|
|
822
|
+
...data ? {
|
|
823
|
+
data
|
|
824
|
+
} : {},
|
|
825
|
+
...celldata ? {
|
|
826
|
+
celldata
|
|
827
|
+
} : {}
|
|
828
|
+
};
|
|
829
|
+
if (data && next.celldata) delete next.celldata;
|
|
830
|
+
if ('formats' === mode || 'all' === mode) next = clearSpreadsheetSheetFormats(next, range);
|
|
831
|
+
if ('hyperlinks' === mode || 'all' === mode) next = clearSpreadsheetSheetHyperlinks(next, range);
|
|
832
|
+
return next;
|
|
833
|
+
}
|
|
834
|
+
function clearSpreadsheetCellAt(cell, row, column, range, mode) {
|
|
835
|
+
if (!cell || !clearRangeContains(range, row, column)) return cell;
|
|
836
|
+
if ('all' === mode) return cell.mc ? {
|
|
837
|
+
mc: {
|
|
838
|
+
...cell.mc
|
|
839
|
+
}
|
|
840
|
+
} : null;
|
|
841
|
+
const next = {
|
|
842
|
+
...cell
|
|
843
|
+
};
|
|
844
|
+
if ('contents' === mode) clearSpreadsheetCellContents(next);
|
|
845
|
+
if ('formats' === mode) clearSpreadsheetCellFormats(next);
|
|
846
|
+
if ('comments' === mode) delete next.ps;
|
|
847
|
+
if ('hyperlinks' === mode) delete next.hl;
|
|
848
|
+
removeUndefinedCellProperties(next);
|
|
849
|
+
return Object.keys(next).length ? next : null;
|
|
850
|
+
}
|
|
851
|
+
function clearSpreadsheetCellContents(cell) {
|
|
852
|
+
delete cell.v;
|
|
853
|
+
delete cell.m;
|
|
854
|
+
delete cell.f;
|
|
855
|
+
delete cell.spl;
|
|
856
|
+
delete cell.qp;
|
|
857
|
+
if (cell.ct && 's' in cell.ct) {
|
|
858
|
+
const cellType = {
|
|
859
|
+
...cell.ct
|
|
860
|
+
};
|
|
861
|
+
delete cellType.s;
|
|
862
|
+
cell.ct = Object.keys(cellType).length ? cellType : void 0;
|
|
863
|
+
}
|
|
864
|
+
}
|
|
865
|
+
function clearSpreadsheetCellFormats(cell) {
|
|
866
|
+
const inlineText = spreadsheetInlineCellText(cell);
|
|
867
|
+
for (const property of spreadsheetCellFormatProperties)delete cell[property];
|
|
868
|
+
if (void 0 !== cell.v) cell.m = spreadsheetGeneralDisplayValue(cell.v);
|
|
869
|
+
else if (!cell.f && null !== inlineText) {
|
|
870
|
+
cell.v = inlineText;
|
|
871
|
+
cell.m = inlineText;
|
|
872
|
+
}
|
|
873
|
+
}
|
|
874
|
+
function spreadsheetInlineCellText(cell) {
|
|
875
|
+
const segments = cell.ct?.s;
|
|
876
|
+
if (!Array.isArray(segments)) return null;
|
|
877
|
+
return segments.map((segment)=>{
|
|
878
|
+
if (!segment || 'object' != typeof segment) return '';
|
|
879
|
+
const value = segment.v;
|
|
880
|
+
return null == value ? '' : String(value);
|
|
881
|
+
}).join('');
|
|
882
|
+
}
|
|
883
|
+
function spreadsheetGeneralDisplayValue(value) {
|
|
884
|
+
if ('boolean' == typeof value) return value ? 'TRUE' : 'FALSE';
|
|
885
|
+
return void 0 === value ? '' : String(value);
|
|
886
|
+
}
|
|
887
|
+
function removeUndefinedCellProperties(cell) {
|
|
888
|
+
const record = cell;
|
|
889
|
+
for (const key of Object.keys(record))if (void 0 === record[key]) delete record[key];
|
|
890
|
+
}
|
|
891
|
+
function clearSpreadsheetSheetFormats(sheet, range) {
|
|
892
|
+
const config = sheet.config ? {
|
|
893
|
+
...sheet.config
|
|
894
|
+
} : void 0;
|
|
895
|
+
if (config?.borderInfo) {
|
|
896
|
+
const borderInfo = clearSpreadsheetBorderFormats(config.borderInfo, range);
|
|
897
|
+
if (borderInfo.length) config.borderInfo = borderInfo;
|
|
898
|
+
else delete config.borderInfo;
|
|
899
|
+
}
|
|
900
|
+
const conditionalFormats = clearSpreadsheetConditionalFormats(sheet.luckysheet_conditionformat_save, range);
|
|
901
|
+
const alternateFormats = clearSpreadsheetAlternateFormats(sheet.luckysheet_alternateformat_save, range);
|
|
902
|
+
const next = {
|
|
903
|
+
...sheet,
|
|
904
|
+
...config ? {
|
|
905
|
+
config
|
|
906
|
+
} : {},
|
|
907
|
+
...conditionalFormats.length ? {
|
|
908
|
+
luckysheet_conditionformat_save: conditionalFormats
|
|
909
|
+
} : {},
|
|
910
|
+
...alternateFormats.length ? {
|
|
911
|
+
luckysheet_alternateformat_save: alternateFormats
|
|
912
|
+
} : {}
|
|
913
|
+
};
|
|
914
|
+
if (!conditionalFormats.length) delete next.luckysheet_conditionformat_save;
|
|
915
|
+
if (!alternateFormats.length) delete next.luckysheet_alternateformat_save;
|
|
916
|
+
return next;
|
|
917
|
+
}
|
|
918
|
+
function clearSpreadsheetBorderFormats(formats, range) {
|
|
919
|
+
return formats.flatMap((format)=>{
|
|
920
|
+
if (!isRecord(format)) return [
|
|
921
|
+
format
|
|
922
|
+
];
|
|
923
|
+
if ('cell' === format.rangeType) {
|
|
924
|
+
const value = isRecord(format.value) ? format.value : null;
|
|
925
|
+
const row = finiteIndex(value?.row_index);
|
|
926
|
+
const column = finiteIndex(value?.col_index);
|
|
927
|
+
return null !== row && null !== column && clearRangeContains(range, row, column) ? [] : [
|
|
928
|
+
format
|
|
929
|
+
];
|
|
930
|
+
}
|
|
931
|
+
if ('range' !== format.rangeType || !Array.isArray(format.range)) return [
|
|
932
|
+
format
|
|
933
|
+
];
|
|
934
|
+
const remaining = format.range.flatMap((candidate)=>{
|
|
935
|
+
const parsed = parseClearRange(candidate);
|
|
936
|
+
if (!parsed) return [
|
|
937
|
+
candidate
|
|
938
|
+
];
|
|
939
|
+
if ('border-slash' === format.borderType) return clearRangesIntersect(parsed, range) ? [] : [
|
|
940
|
+
parsed
|
|
941
|
+
];
|
|
942
|
+
return subtractSpreadsheetRange(parsed, range);
|
|
943
|
+
});
|
|
944
|
+
return remaining.length ? [
|
|
945
|
+
{
|
|
946
|
+
...format,
|
|
947
|
+
range: remaining
|
|
948
|
+
}
|
|
949
|
+
] : [];
|
|
950
|
+
});
|
|
951
|
+
}
|
|
952
|
+
function clearSpreadsheetConditionalFormats(formats, range) {
|
|
953
|
+
if (!Array.isArray(formats)) return [];
|
|
954
|
+
return formats.flatMap((format)=>{
|
|
955
|
+
if (!isRecord(format) || !Array.isArray(format.cellrange)) return [
|
|
956
|
+
format
|
|
957
|
+
];
|
|
958
|
+
const remaining = format.cellrange.flatMap((candidate)=>{
|
|
959
|
+
const parsed = parseClearRange(candidate);
|
|
960
|
+
return parsed ? subtractSpreadsheetRange(parsed, range) : [
|
|
961
|
+
candidate
|
|
962
|
+
];
|
|
963
|
+
});
|
|
964
|
+
return remaining.length ? [
|
|
965
|
+
{
|
|
966
|
+
...format,
|
|
967
|
+
cellrange: remaining
|
|
968
|
+
}
|
|
969
|
+
] : [];
|
|
970
|
+
});
|
|
971
|
+
}
|
|
972
|
+
function clearSpreadsheetAlternateFormats(formats, range) {
|
|
973
|
+
if (!Array.isArray(formats)) return [];
|
|
974
|
+
return formats.flatMap((format)=>{
|
|
975
|
+
if (!isRecord(format)) return [
|
|
976
|
+
format
|
|
977
|
+
];
|
|
978
|
+
const source = parseClearRange(format.cellrange);
|
|
979
|
+
if (!source) return [
|
|
980
|
+
format
|
|
981
|
+
];
|
|
982
|
+
return subtractSpreadsheetRange(source, range).map((cellrange)=>({
|
|
983
|
+
...format,
|
|
984
|
+
cellrange
|
|
985
|
+
}));
|
|
986
|
+
});
|
|
987
|
+
}
|
|
988
|
+
function clearSpreadsheetSheetHyperlinks(sheet, range) {
|
|
989
|
+
if (!sheet.hyperlink) return sheet;
|
|
990
|
+
const hyperlink = Object.fromEntries(Object.entries(sheet.hyperlink).filter(([key])=>{
|
|
991
|
+
const position = spreadsheetHyperlinkPosition(key);
|
|
992
|
+
return !position || !clearRangeContains(range, position.row, position.column);
|
|
993
|
+
}));
|
|
994
|
+
const next = {
|
|
995
|
+
...sheet,
|
|
996
|
+
hyperlink
|
|
997
|
+
};
|
|
998
|
+
if (!Object.keys(hyperlink).length) delete next.hyperlink;
|
|
999
|
+
return next;
|
|
1000
|
+
}
|
|
1001
|
+
function spreadsheetHyperlinkPosition(value) {
|
|
1002
|
+
const match = /^(\d+)_(\d+)$/.exec(value);
|
|
1003
|
+
if (!match) return null;
|
|
1004
|
+
return {
|
|
1005
|
+
row: Number(match[1]),
|
|
1006
|
+
column: Number(match[2])
|
|
1007
|
+
};
|
|
1008
|
+
}
|
|
1009
|
+
function subtractSpreadsheetRange(source, removed) {
|
|
1010
|
+
const top = Math.max(source.row[0], removed.row[0]);
|
|
1011
|
+
const bottom = Math.min(source.row[1], removed.row[1]);
|
|
1012
|
+
const left = Math.max(source.column[0], removed.column[0]);
|
|
1013
|
+
const right = Math.min(source.column[1], removed.column[1]);
|
|
1014
|
+
if (top > bottom || left > right) return [
|
|
1015
|
+
source
|
|
1016
|
+
];
|
|
1017
|
+
const remaining = [];
|
|
1018
|
+
if (source.row[0] < top) remaining.push({
|
|
1019
|
+
row: [
|
|
1020
|
+
source.row[0],
|
|
1021
|
+
top - 1
|
|
1022
|
+
],
|
|
1023
|
+
column: [
|
|
1024
|
+
...source.column
|
|
1025
|
+
]
|
|
1026
|
+
});
|
|
1027
|
+
if (bottom < source.row[1]) remaining.push({
|
|
1028
|
+
row: [
|
|
1029
|
+
bottom + 1,
|
|
1030
|
+
source.row[1]
|
|
1031
|
+
],
|
|
1032
|
+
column: [
|
|
1033
|
+
...source.column
|
|
1034
|
+
]
|
|
1035
|
+
});
|
|
1036
|
+
if (source.column[0] < left) remaining.push({
|
|
1037
|
+
row: [
|
|
1038
|
+
top,
|
|
1039
|
+
bottom
|
|
1040
|
+
],
|
|
1041
|
+
column: [
|
|
1042
|
+
source.column[0],
|
|
1043
|
+
left - 1
|
|
1044
|
+
]
|
|
1045
|
+
});
|
|
1046
|
+
if (right < source.column[1]) remaining.push({
|
|
1047
|
+
row: [
|
|
1048
|
+
top,
|
|
1049
|
+
bottom
|
|
1050
|
+
],
|
|
1051
|
+
column: [
|
|
1052
|
+
right + 1,
|
|
1053
|
+
source.column[1]
|
|
1054
|
+
]
|
|
1055
|
+
});
|
|
1056
|
+
return remaining;
|
|
1057
|
+
}
|
|
1058
|
+
function clearRangesIntersect(left, right) {
|
|
1059
|
+
return !(left.row[1] < right.row[0] || right.row[1] < left.row[0] || left.column[1] < right.column[0] || right.column[1] < left.column[0]);
|
|
1060
|
+
}
|
|
1061
|
+
function clearRangeContains(range, row, column) {
|
|
1062
|
+
return row >= range.row[0] && row <= range.row[1] && column >= range.column[0] && column <= range.column[1];
|
|
1063
|
+
}
|
|
1064
|
+
function normalizeClearRange(range) {
|
|
1065
|
+
return {
|
|
1066
|
+
row: normalizeClearAxis(range.row),
|
|
1067
|
+
column: normalizeClearAxis(range.column)
|
|
1068
|
+
};
|
|
1069
|
+
}
|
|
1070
|
+
function parseClearRange(value) {
|
|
1071
|
+
if (!isRecord(value)) return null;
|
|
1072
|
+
const row = parseClearAxis(value.row);
|
|
1073
|
+
const column = parseClearAxis(value.column);
|
|
1074
|
+
return row && column ? {
|
|
1075
|
+
row,
|
|
1076
|
+
column
|
|
1077
|
+
} : null;
|
|
1078
|
+
}
|
|
1079
|
+
function normalizeClearAxis(value) {
|
|
1080
|
+
const first = finiteIndex(value[0]) ?? 0;
|
|
1081
|
+
const second = finiteIndex(value[1]) ?? first;
|
|
1082
|
+
return [
|
|
1083
|
+
Math.min(first, second),
|
|
1084
|
+
Math.max(first, second)
|
|
1085
|
+
];
|
|
1086
|
+
}
|
|
1087
|
+
function parseClearAxis(value) {
|
|
1088
|
+
if (!Array.isArray(value)) return null;
|
|
1089
|
+
const first = finiteIndex(value[0]);
|
|
1090
|
+
const second = finiteIndex(value[1]);
|
|
1091
|
+
if (null === first || null === second) return null;
|
|
1092
|
+
return [
|
|
1093
|
+
Math.min(first, second),
|
|
1094
|
+
Math.max(first, second)
|
|
1095
|
+
];
|
|
1096
|
+
}
|
|
1097
|
+
function finiteIndex(value) {
|
|
1098
|
+
return 'number' == typeof value && Number.isFinite(value) && value >= 0 ? Math.trunc(value) : null;
|
|
1099
|
+
}
|
|
1100
|
+
function isRecord(value) {
|
|
1101
|
+
return Boolean(value && 'object' == typeof value && !Array.isArray(value));
|
|
1102
|
+
}
|
|
1103
|
+
function canApplySpreadsheetCellMerge(sheet, range, command) {
|
|
1104
|
+
if (!sheet) return false;
|
|
1105
|
+
const normalized = normalizeSpreadsheetCellMergeRange(range);
|
|
1106
|
+
if (!normalized) return false;
|
|
1107
|
+
const merged = spreadsheetMergesIntersectingRange(sheet, normalized);
|
|
1108
|
+
if ('unmerge-cells' === command || 'unmerge-and-fill' === command) return merged.length > 0;
|
|
1109
|
+
if (merged.length > 0) return false;
|
|
1110
|
+
const rowCount = normalized.row[1] - normalized.row[0] + 1;
|
|
1111
|
+
const columnCount = normalized.column[1] - normalized.column[0] + 1;
|
|
1112
|
+
if ('merge-across' === command) return columnCount > 1;
|
|
1113
|
+
return rowCount * columnCount > 1;
|
|
1114
|
+
}
|
|
1115
|
+
function spreadsheetCellMergeApiCalls(sheet, sheetId, range, command) {
|
|
1116
|
+
if (!canApplySpreadsheetCellMerge(sheet, range, command) || !sheet) return [];
|
|
1117
|
+
const normalized = normalizeSpreadsheetCellMergeRange(range);
|
|
1118
|
+
if (!normalized) return [];
|
|
1119
|
+
const options = {
|
|
1120
|
+
id: sheetId
|
|
1121
|
+
};
|
|
1122
|
+
if ('merge-and-center' === command) return [
|
|
1123
|
+
{
|
|
1124
|
+
name: 'mergeCells',
|
|
1125
|
+
args: [
|
|
1126
|
+
[
|
|
1127
|
+
normalized
|
|
1128
|
+
],
|
|
1129
|
+
'merge-all',
|
|
1130
|
+
options
|
|
1131
|
+
]
|
|
1132
|
+
},
|
|
1133
|
+
{
|
|
1134
|
+
name: 'setCellFormatByRange',
|
|
1135
|
+
args: [
|
|
1136
|
+
'ht',
|
|
1137
|
+
'0',
|
|
1138
|
+
normalized,
|
|
1139
|
+
options
|
|
1140
|
+
]
|
|
1141
|
+
}
|
|
1142
|
+
];
|
|
1143
|
+
if ('merge-cells' === command || 'merge-across' === command) return [
|
|
1144
|
+
{
|
|
1145
|
+
name: 'mergeCells',
|
|
1146
|
+
args: [
|
|
1147
|
+
[
|
|
1148
|
+
normalized
|
|
1149
|
+
],
|
|
1150
|
+
'merge-across' === command ? 'merge-horizontal' : 'merge-all',
|
|
1151
|
+
options
|
|
1152
|
+
]
|
|
1153
|
+
}
|
|
1154
|
+
];
|
|
1155
|
+
const merges = spreadsheetMergesIntersectingRange(sheet, normalized);
|
|
1156
|
+
const mergeRanges = merges.map(spreadsheetNativeMergeRange);
|
|
1157
|
+
const calls = [
|
|
1158
|
+
{
|
|
1159
|
+
name: 'cancelMerge',
|
|
1160
|
+
args: [
|
|
1161
|
+
mergeRanges,
|
|
1162
|
+
options
|
|
1163
|
+
]
|
|
1164
|
+
}
|
|
1165
|
+
];
|
|
1166
|
+
if ('unmerge-cells' === command) return calls;
|
|
1167
|
+
for (const merge of merges){
|
|
1168
|
+
const anchor = sheet.data?.[merge.r]?.[merge.c];
|
|
1169
|
+
if (!anchor) continue;
|
|
1170
|
+
const targetRange = spreadsheetNativeMergeRange(merge);
|
|
1171
|
+
calls.push({
|
|
1172
|
+
name: 'setCellValuesByRange',
|
|
1173
|
+
args: [
|
|
1174
|
+
Array.from({
|
|
1175
|
+
length: merge.rs
|
|
1176
|
+
}, ()=>Array.from({
|
|
1177
|
+
length: merge.cs
|
|
1178
|
+
}, ()=>cloneSpreadsheetCellWithoutMerge(anchor))),
|
|
1179
|
+
targetRange,
|
|
1180
|
+
null,
|
|
1181
|
+
options
|
|
1182
|
+
]
|
|
1183
|
+
});
|
|
1184
|
+
}
|
|
1185
|
+
return calls;
|
|
1186
|
+
}
|
|
1187
|
+
function normalizeSpreadsheetCellMergeRange(range) {
|
|
1188
|
+
const row = spreadsheetCellMergeBoundary(range.row);
|
|
1189
|
+
const column = spreadsheetCellMergeBoundary(range.column);
|
|
1190
|
+
return row && column ? {
|
|
1191
|
+
row,
|
|
1192
|
+
column
|
|
1193
|
+
} : null;
|
|
1194
|
+
}
|
|
1195
|
+
function spreadsheetCellMergeBoundary(values) {
|
|
1196
|
+
if (!values.length || values.some((value)=>!Number.isInteger(value) || value < 0)) return null;
|
|
1197
|
+
return [
|
|
1198
|
+
Math.min(...values),
|
|
1199
|
+
Math.max(...values)
|
|
1200
|
+
];
|
|
1201
|
+
}
|
|
1202
|
+
function spreadsheetMergesIntersectingRange(sheet, range) {
|
|
1203
|
+
return Object.values(sheet.config?.merge ?? {}).filter(isSpreadsheetNativeMerge).filter((merge)=>merge.r <= range.row[1] && merge.r + merge.rs - 1 >= range.row[0] && merge.c <= range.column[1] && merge.c + merge.cs - 1 >= range.column[0]).sort((left, right)=>left.r - right.r || left.c - right.c);
|
|
1204
|
+
}
|
|
1205
|
+
function isSpreadsheetNativeMerge(value) {
|
|
1206
|
+
if (!value || 'object' != typeof value) return false;
|
|
1207
|
+
const merge = value;
|
|
1208
|
+
return Number.isInteger(merge.r) && Number.isInteger(merge.c) && Number.isInteger(merge.rs) && Number.isInteger(merge.cs) && Number(merge.r) >= 0 && Number(merge.c) >= 0 && Number(merge.rs) > 0 && Number(merge.cs) > 0;
|
|
1209
|
+
}
|
|
1210
|
+
function spreadsheetNativeMergeRange(merge) {
|
|
1211
|
+
return {
|
|
1212
|
+
row: [
|
|
1213
|
+
merge.r,
|
|
1214
|
+
merge.r + merge.rs - 1
|
|
1215
|
+
],
|
|
1216
|
+
column: [
|
|
1217
|
+
merge.c,
|
|
1218
|
+
merge.c + merge.cs - 1
|
|
1219
|
+
]
|
|
1220
|
+
};
|
|
1221
|
+
}
|
|
1222
|
+
function cloneSpreadsheetCellWithoutMerge(cell) {
|
|
1223
|
+
const clone = structuredClone(cell);
|
|
1224
|
+
delete clone.mc;
|
|
1225
|
+
return clone;
|
|
1226
|
+
}
|
|
1227
|
+
function spreadsheetFreezePaneForSelection(selection) {
|
|
1228
|
+
const finite = finiteSpreadsheetSelection(selection);
|
|
1229
|
+
return spreadsheetFrozenPaneFromCounts(finite.row_focus ?? finite.row[0] ?? 0, finite.column_focus ?? finite.column[0] ?? 0);
|
|
1230
|
+
}
|
|
1231
|
+
function spreadsheetFreezePanesSelectionLabel(selection) {
|
|
1232
|
+
const boundary = spreadsheetFreezePaneForSelection(selection);
|
|
1233
|
+
if (!boundary) return '冻结至当前单元格';
|
|
1234
|
+
const { rows, columns } = spreadsheetFreezePaneBoundary(boundary);
|
|
1235
|
+
if (rows && columns) return `冻结至第 ${rows} 行、${indexToColumnChar(columns - 1)} 列`;
|
|
1236
|
+
if (rows) return `冻结至第 ${rows} 行`;
|
|
1237
|
+
return `冻结至 ${indexToColumnChar(columns - 1)} 列`;
|
|
1238
|
+
}
|
|
1239
|
+
function spreadsheetFreezePaneBoundary(frozen) {
|
|
1240
|
+
if (!frozen) return {
|
|
1241
|
+
rows: 0,
|
|
1242
|
+
columns: 0
|
|
1243
|
+
};
|
|
1244
|
+
const freezesRows = [
|
|
1245
|
+
'row',
|
|
1246
|
+
'both',
|
|
1247
|
+
'rangeRow',
|
|
1248
|
+
'rangeBoth'
|
|
1249
|
+
].includes(frozen.type);
|
|
1250
|
+
const freezesColumns = [
|
|
1251
|
+
'column',
|
|
1252
|
+
'both',
|
|
1253
|
+
'rangeColumn',
|
|
1254
|
+
'rangeBoth'
|
|
1255
|
+
].includes(frozen.type);
|
|
1256
|
+
return {
|
|
1257
|
+
rows: freezesRows ? Math.max(1, finiteFreezeIndex(frozen.range?.row_focus) + 1) : 0,
|
|
1258
|
+
columns: freezesColumns ? Math.max(1, finiteFreezeIndex(frozen.range?.column_focus) + 1) : 0
|
|
1259
|
+
};
|
|
1260
|
+
}
|
|
1261
|
+
function spreadsheetFreezePanesStatus(frozen) {
|
|
1262
|
+
const { rows, columns } = spreadsheetFreezePaneBoundary(frozen);
|
|
1263
|
+
if (rows && columns) return `已冻结前 ${rows} 行和前 ${columns} 列。`;
|
|
1264
|
+
if (rows) return `已冻结前 ${rows} 行。`;
|
|
1265
|
+
if (columns) return `已冻结前 ${columns} 列。`;
|
|
1266
|
+
return '';
|
|
1267
|
+
}
|
|
1268
|
+
function updateSpreadsheetFreezePanes(content, sheetId, preset, selection) {
|
|
1269
|
+
const sheetIndex = content.sheets.findIndex((sheet)=>sheet.id === sheetId);
|
|
1270
|
+
const sheet = content.sheets[sheetIndex];
|
|
1271
|
+
if (!sheet) return null;
|
|
1272
|
+
const nextFrozen = spreadsheetFrozenPaneForPreset(preset, selection);
|
|
1273
|
+
if ('none' !== preset && !nextFrozen) return null;
|
|
1274
|
+
if (!nextFrozen && !sheet.frozen) return null;
|
|
1275
|
+
if (nextFrozen && sameSpreadsheetFreezePane(sheet.frozen, nextFrozen)) return null;
|
|
1276
|
+
const savedSelection = finiteSpreadsheetSelection(selection);
|
|
1277
|
+
const nextSheet = nextFrozen ? {
|
|
1278
|
+
...sheet,
|
|
1279
|
+
frozen: nextFrozen,
|
|
1280
|
+
luckysheet_select_save: [
|
|
1281
|
+
savedSelection
|
|
1282
|
+
]
|
|
1283
|
+
} : spreadsheetSheetWithoutFreezePanes(sheet, savedSelection);
|
|
1284
|
+
const sheets = [
|
|
1285
|
+
...content.sheets
|
|
1286
|
+
];
|
|
1287
|
+
sheets[sheetIndex] = nextSheet;
|
|
1288
|
+
return {
|
|
1289
|
+
...content,
|
|
1290
|
+
sheets
|
|
1291
|
+
};
|
|
1292
|
+
}
|
|
1293
|
+
function spreadsheetFrozenPaneForPreset(preset, selection) {
|
|
1294
|
+
if ('selection' === preset) return spreadsheetFreezePaneForSelection(selection);
|
|
1295
|
+
if ('topRow' === preset) return spreadsheetFrozenPaneFromCounts(1, 0);
|
|
1296
|
+
if ('firstColumn' === preset) return spreadsheetFrozenPaneFromCounts(0, 1);
|
|
1297
|
+
return null;
|
|
1298
|
+
}
|
|
1299
|
+
function spreadsheetFrozenPaneFromCounts(rows, columns) {
|
|
1300
|
+
const safeRows = finiteFreezeIndex(rows);
|
|
1301
|
+
const safeColumns = finiteFreezeIndex(columns);
|
|
1302
|
+
if (!safeRows && !safeColumns) return null;
|
|
1303
|
+
return {
|
|
1304
|
+
type: safeRows && safeColumns ? 'rangeBoth' : safeRows ? 'rangeRow' : 'rangeColumn',
|
|
1305
|
+
range: {
|
|
1306
|
+
row_focus: Math.max(0, safeRows - 1),
|
|
1307
|
+
column_focus: Math.max(0, safeColumns - 1)
|
|
1308
|
+
}
|
|
1309
|
+
};
|
|
1310
|
+
}
|
|
1311
|
+
function spreadsheetSheetWithoutFreezePanes(sheet, selection) {
|
|
1312
|
+
const { frozen: _frozen, ...remaining } = sheet;
|
|
1313
|
+
return {
|
|
1314
|
+
...remaining,
|
|
1315
|
+
luckysheet_select_save: [
|
|
1316
|
+
selection
|
|
1317
|
+
]
|
|
1318
|
+
};
|
|
1319
|
+
}
|
|
1320
|
+
function sameSpreadsheetFreezePane(current, next) {
|
|
1321
|
+
const currentBoundary = spreadsheetFreezePaneBoundary(current);
|
|
1322
|
+
const nextBoundary = spreadsheetFreezePaneBoundary(next);
|
|
1323
|
+
return currentBoundary.rows === nextBoundary.rows && currentBoundary.columns === nextBoundary.columns;
|
|
1324
|
+
}
|
|
1325
|
+
function finiteFreezeIndex(value) {
|
|
1326
|
+
return 'number' == typeof value && Number.isFinite(value) ? Math.max(0, Math.trunc(value)) : 0;
|
|
1327
|
+
}
|
|
1328
|
+
const spreadsheetKeyboardPageRows = 20;
|
|
1329
|
+
const spreadsheetDefaultRows = 60;
|
|
1330
|
+
const spreadsheetDefaultColumns = 26;
|
|
1331
|
+
function moveSpreadsheetKeyboardSelection(sheet, selection, move, extend) {
|
|
1332
|
+
const bounds = spreadsheetSheetBounds(sheet);
|
|
1333
|
+
const current = normalizeSpreadsheetKeyboardSelection(selection, bounds);
|
|
1334
|
+
let targetRow = current.rowFocus;
|
|
1335
|
+
let targetColumn = current.columnFocus;
|
|
1056
1336
|
switch(move){
|
|
1057
1337
|
case 'up':
|
|
1058
1338
|
targetRow -= 1;
|
|
@@ -1468,6 +1748,53 @@ function createSpreadsheetEditorExtensions() {
|
|
|
1468
1748
|
}
|
|
1469
1749
|
})
|
|
1470
1750
|
}),
|
|
1751
|
+
createOfficeEditorExtension({
|
|
1752
|
+
name: 'spreadsheetFormatPainter',
|
|
1753
|
+
addCommands: ()=>({
|
|
1754
|
+
activateFormatPainter: {
|
|
1755
|
+
canExecute: ({ formatPainter })=>formatPainter.canActivate,
|
|
1756
|
+
execute: ({ formatPainter }, mode)=>formatPainter.canActivate && formatPainter.activate(mode)
|
|
1757
|
+
},
|
|
1758
|
+
applyFormatPainter: {
|
|
1759
|
+
canExecute: ({ formatPainter })=>formatPainter.active,
|
|
1760
|
+
execute: ({ formatPainter }, target)=>formatPainter.active && formatPainter.applySelection(target)
|
|
1761
|
+
},
|
|
1762
|
+
cancelFormatPainter: {
|
|
1763
|
+
canExecute: ({ formatPainter })=>formatPainter.active,
|
|
1764
|
+
execute: ({ formatPainter })=>formatPainter.active && formatPainter.cancel()
|
|
1765
|
+
}
|
|
1766
|
+
})
|
|
1767
|
+
}),
|
|
1768
|
+
createOfficeEditorExtension({
|
|
1769
|
+
name: 'spreadsheetAutoFilter',
|
|
1770
|
+
addCommands: ()=>({
|
|
1771
|
+
openAutoFilterMenu: {
|
|
1772
|
+
canExecute: ({ autoFilter })=>autoFilter.canOpenMenu,
|
|
1773
|
+
execute: ({ autoFilter })=>autoFilter.canOpenMenu && autoFilter.openMenu()
|
|
1774
|
+
},
|
|
1775
|
+
toggleAutoFilter: {
|
|
1776
|
+
canExecute: ({ autoFilter })=>autoFilter.canToggle,
|
|
1777
|
+
execute: ({ autoFilter })=>autoFilter.canToggle && autoFilter.toggle()
|
|
1778
|
+
}
|
|
1779
|
+
})
|
|
1780
|
+
}),
|
|
1781
|
+
createOfficeEditorExtension({
|
|
1782
|
+
name: 'spreadsheetClipboard',
|
|
1783
|
+
addCommands: ()=>({
|
|
1784
|
+
copySelection: {
|
|
1785
|
+
canExecute: ({ clipboard })=>clipboard.canCopySelection,
|
|
1786
|
+
execute: ({ clipboard })=>clipboard.canCopySelection && clipboard.copySelection()
|
|
1787
|
+
},
|
|
1788
|
+
cutSelection: {
|
|
1789
|
+
canExecute: ({ clipboard })=>clipboard.canCutSelection,
|
|
1790
|
+
execute: ({ clipboard })=>clipboard.canCutSelection && clipboard.cutSelection()
|
|
1791
|
+
},
|
|
1792
|
+
pasteSelection: {
|
|
1793
|
+
canExecute: ({ clipboard })=>clipboard.canPasteSelection,
|
|
1794
|
+
execute: ({ clipboard })=>clipboard.canPasteSelection && clipboard.pasteSelection()
|
|
1795
|
+
}
|
|
1796
|
+
})
|
|
1797
|
+
}),
|
|
1471
1798
|
createOfficeEditorExtension({
|
|
1472
1799
|
name: 'spreadsheetHistory',
|
|
1473
1800
|
addCommands: ()=>({
|
|
@@ -1533,17 +1860,25 @@ function createSpreadsheetEditorExtensions() {
|
|
|
1533
1860
|
addKeyboardShortcuts: ()=>({
|
|
1534
1861
|
'Mod-a': ({ can, commands }, event)=>selectSpreadsheetFormulaBarContents(event) || runSpreadsheetSelectionScopeShortcut(event, can.selectCellRange, commands.selectCellRange, 'all'),
|
|
1535
1862
|
'Mod-b': ({ can, commands, context }, event)=>runSpreadsheetCellFormatShortcut(event, context, can.setCellFormat, commands.setCellFormat, 'bl'),
|
|
1863
|
+
'Mod-c': ({ can, commands }, event)=>runSpreadsheetClipboardShortcut(event, can.copySelection, commands.copySelection),
|
|
1536
1864
|
'Mod-i': ({ can, commands, context }, event)=>runSpreadsheetCellFormatShortcut(event, context, can.setCellFormat, commands.setCellFormat, 'it'),
|
|
1865
|
+
'Mod-v': ({ can, commands }, event)=>runSpreadsheetClipboardShortcut(event, can.pasteSelection, commands.pasteSelection),
|
|
1866
|
+
'Mod-x': ({ can, commands }, event)=>runSpreadsheetClipboardShortcut(event, can.cutSelection, commands.cutSelection),
|
|
1537
1867
|
'Mod-u': ({ can, commands, context }, event)=>runSpreadsheetCellFormatShortcut(event, context, can.setCellFormat, commands.setCellFormat, 'un'),
|
|
1538
1868
|
'Mod-z': ({ can, commands }, event)=>runSpreadsheetHistoryShortcut(event, can.undo, commands.undo),
|
|
1539
1869
|
'Mod-Shift-z': ({ can, commands }, event)=>runSpreadsheetHistoryShortcut(event, can.redo, commands.redo),
|
|
1540
1870
|
'Mod-y': ({ can, commands }, event)=>runSpreadsheetHistoryShortcut(event, can.redo, commands.redo),
|
|
1871
|
+
'Control-m': ({ can, commands }, event)=>runSpreadsheetMergeShortcut(event, can.mergeSelectedCells, commands.mergeSelectedCells),
|
|
1872
|
+
'Mod-Shift-l': ({ can, commands }, event)=>runSpreadsheetAutoFilterShortcut(event, can.toggleAutoFilter, commands.toggleAutoFilter),
|
|
1873
|
+
'Alt-ArrowDown': ({ can, commands }, event)=>runSpreadsheetAutoFilterShortcut(event, can.openAutoFilterMenu, commands.openAutoFilterMenu),
|
|
1541
1874
|
'Control-PageUp': ({ context, commands }, event)=>runSpreadsheetSheetNavigationShortcut(event, context, commands.activateSheet, -1),
|
|
1542
1875
|
'Control-PageDown': ({ context, commands }, event)=>runSpreadsheetSheetNavigationShortcut(event, context, commands.activateSheet, 1),
|
|
1543
1876
|
'Mod-PageUp': ({ context, commands }, event)=>runSpreadsheetSheetNavigationShortcut(event, context, commands.activateSheet, -1),
|
|
1544
1877
|
'Mod-PageDown': ({ context, commands }, event)=>runSpreadsheetSheetNavigationShortcut(event, context, commands.activateSheet, 1),
|
|
1545
1878
|
'Shift-F11': ({ can, commands }, event)=>runSpreadsheetAddSheetShortcut(event, can.addSheet, commands.addSheet),
|
|
1546
1879
|
'Alt-Shift-F1': ({ can, commands }, event)=>runSpreadsheetAddSheetShortcut(event, can.addSheet, commands.addSheet),
|
|
1880
|
+
Escape: ({ can, commands }, event)=>runSpreadsheetFormatPainterEscape(event, can.cancelFormatPainter, commands.cancelFormatPainter),
|
|
1881
|
+
F9: ({ can, commands }, event)=>runSpreadsheetRecalculationShortcut(event, can.recalculateFormula, commands.recalculateFormula),
|
|
1547
1882
|
Delete: ({ can, commands }, event)=>runSpreadsheetClearShortcut(event, can.clearSelectedCells, commands.clearSelectedCells),
|
|
1548
1883
|
Backspace: ({ can, commands }, event)=>runSpreadsheetClearShortcut(event, can.clearSelectedCells, commands.clearSelectedCells),
|
|
1549
1884
|
ArrowUp: ({ can, commands }, event)=>runSpreadsheetSelectionMoveShortcut(event, can.moveSelection, commands.moveSelection, 'up', false),
|
|
@@ -1612,7 +1947,7 @@ function createSpreadsheetEditorExtensions() {
|
|
|
1612
1947
|
name: 'spreadsheetCellFormatting',
|
|
1613
1948
|
addCommands: ()=>({
|
|
1614
1949
|
clearSelectedCells: {
|
|
1615
|
-
canExecute: canEditSelectedCells,
|
|
1950
|
+
canExecute: (context)=>canEditSelectedCells(context),
|
|
1616
1951
|
execute: clearSelectedCells
|
|
1617
1952
|
},
|
|
1618
1953
|
pasteCells: {
|
|
@@ -1623,9 +1958,9 @@ function createSpreadsheetEditorExtensions() {
|
|
|
1623
1958
|
canExecute: canEditSelectedCells,
|
|
1624
1959
|
execute: formatCells
|
|
1625
1960
|
},
|
|
1626
|
-
|
|
1627
|
-
canExecute:
|
|
1628
|
-
execute:
|
|
1961
|
+
mergeSelectedCells: {
|
|
1962
|
+
canExecute: canMergeSelectedCells,
|
|
1963
|
+
execute: mergeSelectedCells
|
|
1629
1964
|
}
|
|
1630
1965
|
})
|
|
1631
1966
|
}),
|
|
@@ -1641,6 +1976,10 @@ function createSpreadsheetEditorExtensions() {
|
|
|
1641
1976
|
createOfficeEditorExtension({
|
|
1642
1977
|
name: 'spreadsheetView',
|
|
1643
1978
|
addCommands: ()=>({
|
|
1979
|
+
setFreezePanes: {
|
|
1980
|
+
canExecute: canSetFreezePanes,
|
|
1981
|
+
execute: setFreezePanes
|
|
1982
|
+
},
|
|
1644
1983
|
setGridLines: {
|
|
1645
1984
|
canExecute: hasActiveSheet,
|
|
1646
1985
|
execute: (context, visible)=>updateSpreadsheetSheet(context, 'gridLines', visible)
|
|
@@ -1798,26 +2137,37 @@ function spreadsheetStructureExtent(context, axis) {
|
|
|
1798
2137
|
const dataWidth = Math.max(0, ...(sheet.data ?? []).map((row)=>row.length));
|
|
1799
2138
|
return Math.max(sheet.column ?? 0, dataWidth, range[1] + 1);
|
|
1800
2139
|
}
|
|
1801
|
-
function clearSelectedCells(context) {
|
|
2140
|
+
function clearSelectedCells(context, mode = 'contents') {
|
|
1802
2141
|
if (!context.workbook || !context.targetSheetId) return false;
|
|
1803
2142
|
const range = liveRange(context);
|
|
1804
2143
|
const calls = [];
|
|
1805
|
-
for(let row = range.row[0]; row <= range.row[1]; row += 1)for(let column = range.column[0]; column <= range.column[1]; column += 1)calls.push({
|
|
1806
|
-
name: 'clearCell',
|
|
1807
|
-
args: [
|
|
1808
|
-
row,
|
|
1809
|
-
column,
|
|
1810
|
-
{
|
|
1811
|
-
id: context.targetSheetId
|
|
1812
|
-
}
|
|
1813
|
-
]
|
|
1814
|
-
});
|
|
1815
2144
|
try {
|
|
2145
|
+
const sheet = context.workbook.getSheet({
|
|
2146
|
+
id: context.targetSheetId
|
|
2147
|
+
});
|
|
2148
|
+
if ('contents' === mode || 'all' === mode) for(let row = range.row[0]; row <= range.row[1]; row += 1)for(let column = range.column[0]; column <= range.column[1]; column += 1)calls.push({
|
|
2149
|
+
name: 'clearCell',
|
|
2150
|
+
args: [
|
|
2151
|
+
row,
|
|
2152
|
+
column,
|
|
2153
|
+
{
|
|
2154
|
+
id: context.targetSheetId
|
|
2155
|
+
}
|
|
2156
|
+
]
|
|
2157
|
+
});
|
|
2158
|
+
calls.push({
|
|
2159
|
+
name: 'updateSheet',
|
|
2160
|
+
args: [
|
|
2161
|
+
[
|
|
2162
|
+
clearSpreadsheetSheetSelection(sheet, range, mode)
|
|
2163
|
+
]
|
|
2164
|
+
]
|
|
2165
|
+
});
|
|
1816
2166
|
context.workbook.batchCallApis(calls);
|
|
1817
2167
|
} catch {
|
|
1818
2168
|
return false;
|
|
1819
2169
|
}
|
|
1820
|
-
syncSpreadsheetFormulaBar(context, '');
|
|
2170
|
+
if ('contents' === mode || 'all' === mode) syncSpreadsheetFormulaBar(context, '');
|
|
1821
2171
|
return true;
|
|
1822
2172
|
}
|
|
1823
2173
|
function canNavigateSpreadsheetSelection(context) {
|
|
@@ -1916,18 +2266,20 @@ function isSpreadsheetCellTypeFormat(value) {
|
|
|
1916
2266
|
const format = value;
|
|
1917
2267
|
return Boolean('string' == typeof format?.fa && format.fa.trim() && 'string' == typeof format.t && format.t.trim());
|
|
1918
2268
|
}
|
|
1919
|
-
function
|
|
2269
|
+
function canMergeSelectedCells(context, command) {
|
|
2270
|
+
if (!canEditSelectedCells(context)) return false;
|
|
2271
|
+
return canApplySpreadsheetCellMerge(context.content.sheets.find((sheet)=>sheet.id === context.targetSheetId), liveRange(context), command);
|
|
2272
|
+
}
|
|
2273
|
+
function mergeSelectedCells(context, command) {
|
|
1920
2274
|
if (!context.workbook || !context.targetSheetId) return false;
|
|
1921
|
-
const
|
|
1922
|
-
|
|
1923
|
-
|
|
1924
|
-
|
|
1925
|
-
|
|
1926
|
-
}
|
|
1927
|
-
|
|
1928
|
-
|
|
1929
|
-
});
|
|
1930
|
-
return true;
|
|
2275
|
+
const calls = spreadsheetCellMergeApiCalls(context.content.sheets.find((sheet)=>sheet.id === context.targetSheetId), context.targetSheetId, liveRange(context), command);
|
|
2276
|
+
if (!calls.length) return false;
|
|
2277
|
+
try {
|
|
2278
|
+
context.workbook.batchCallApis(calls);
|
|
2279
|
+
return true;
|
|
2280
|
+
} catch {
|
|
2281
|
+
return false;
|
|
2282
|
+
}
|
|
1931
2283
|
}
|
|
1932
2284
|
function recalculateSpreadsheet(context, scope) {
|
|
1933
2285
|
if (!context.calculation) return false;
|
|
@@ -1963,6 +2315,15 @@ function updateSpreadsheetSheet(context, property, value) {
|
|
|
1963
2315
|
context.onChange(next);
|
|
1964
2316
|
return true;
|
|
1965
2317
|
}
|
|
2318
|
+
function canSetFreezePanes(context, preset) {
|
|
2319
|
+
return Boolean(context.editable && updateSpreadsheetFreezePanes(context.content, context.activeSheetId, preset, liveFreezePanesSelection(context)));
|
|
2320
|
+
}
|
|
2321
|
+
function setFreezePanes(context, preset) {
|
|
2322
|
+
return applySpreadsheetSheetChange(context, updateSpreadsheetFreezePanes(context.content, context.activeSheetId, preset, liveFreezePanesSelection(context)));
|
|
2323
|
+
}
|
|
2324
|
+
function liveFreezePanesSelection(context) {
|
|
2325
|
+
return finiteSpreadsheetSelection(context.workbook?.getSelection()?.at(-1) ?? context.fallbackRange);
|
|
2326
|
+
}
|
|
1966
2327
|
function canEditSelectedCells(context) {
|
|
1967
2328
|
return Boolean(context.editable && context.workbook && context.targetSheetId);
|
|
1968
2329
|
}
|
|
@@ -1978,15 +2339,30 @@ function runSpreadsheetHistoryShortcut(event, canExecute, execute) {
|
|
|
1978
2339
|
if (event.repeat || isOfficeShortcutBlocked(event.target) || isSpreadsheetNativeTextUndoTarget(event.target) || !canExecute()) return false;
|
|
1979
2340
|
return execute();
|
|
1980
2341
|
}
|
|
2342
|
+
function isSpreadsheetAutoFilterTextTarget(target) {
|
|
2343
|
+
return target instanceof HTMLInputElement || target instanceof HTMLTextAreaElement || target instanceof HTMLSelectElement || target instanceof HTMLElement && (target.isContentEditable || Boolean(target.closest('[contenteditable="true"]')));
|
|
2344
|
+
}
|
|
1981
2345
|
function runSpreadsheetCellFormatShortcut(event, context, canExecute, execute, attribute) {
|
|
1982
2346
|
if (event.repeat || isOfficeShortcutBlocked(event.target) || isSpreadsheetNativeTextUndoTarget(event.target)) return false;
|
|
1983
2347
|
const value = 1 === Number(context.toolbarCell?.[attribute]) ? 0 : 1;
|
|
1984
2348
|
return canExecute(attribute, value) && execute(attribute, value);
|
|
1985
2349
|
}
|
|
2350
|
+
function runSpreadsheetMergeShortcut(event, canExecute, execute) {
|
|
2351
|
+
if (event.repeat || isOfficeShortcutBlocked(event.target) || isSpreadsheetNativeTextUndoTarget(event.target) || !canExecute('merge-and-center')) return false;
|
|
2352
|
+
return execute('merge-and-center');
|
|
2353
|
+
}
|
|
1986
2354
|
function runSpreadsheetClearShortcut(event, canExecute, execute) {
|
|
1987
2355
|
if (event.repeat || isOfficeShortcutBlocked(event.target) || isSpreadsheetNativeTextUndoTarget(event.target) || !isSpreadsheetGridKeyboardTarget(event.target) || !canExecute()) return false;
|
|
1988
2356
|
return execute();
|
|
1989
2357
|
}
|
|
2358
|
+
function runSpreadsheetAutoFilterShortcut(event, canExecute, execute) {
|
|
2359
|
+
if (event.repeat || isOfficeShortcutBlocked(event.target) || isSpreadsheetNativeTextUndoTarget(event.target) || isSpreadsheetAutoFilterTextTarget(event.target) || !isSpreadsheetGridKeyboardTarget(event.target) || !canExecute()) return false;
|
|
2360
|
+
return execute();
|
|
2361
|
+
}
|
|
2362
|
+
function runSpreadsheetFormatPainterEscape(event, canExecute, execute) {
|
|
2363
|
+
if (event.repeat || isOfficeShortcutBlocked(event.target) || isSpreadsheetNativeTextUndoTarget(event.target) || !canExecute()) return false;
|
|
2364
|
+
return execute();
|
|
2365
|
+
}
|
|
1990
2366
|
function runSpreadsheetSheetNavigationShortcut(event, context, activateSheet, direction) {
|
|
1991
2367
|
if (event.repeat || isOfficeShortcutBlocked(event.target) || isSpreadsheetNativeTextUndoTarget(event.target)) return false;
|
|
1992
2368
|
const target = adjacentSpreadsheetSheetId(context.content, context.activeSheetId, direction);
|
|
@@ -1996,16 +2372,263 @@ function runSpreadsheetAddSheetShortcut(event, canExecute, execute) {
|
|
|
1996
2372
|
if (event.repeat || isOfficeShortcutBlocked(event.target) || isSpreadsheetNativeTextUndoTarget(event.target) || !canExecute()) return false;
|
|
1997
2373
|
return execute();
|
|
1998
2374
|
}
|
|
2375
|
+
function runSpreadsheetRecalculationShortcut(event, canExecute, execute) {
|
|
2376
|
+
if (event.repeat || isOfficeShortcutBlocked(event.target) || isSpreadsheetNativeTextUndoTarget(event.target) || !canExecute('workbook')) return false;
|
|
2377
|
+
return execute('workbook');
|
|
2378
|
+
}
|
|
1999
2379
|
function liveRange(context) {
|
|
2000
2380
|
const live = context.workbook?.getSelection()?.at(-1);
|
|
2001
2381
|
return spreadsheetSingleRange(live ?? context.fallbackRange);
|
|
2002
2382
|
}
|
|
2003
|
-
|
|
2004
|
-
|
|
2005
|
-
|
|
2006
|
-
|
|
2007
|
-
|
|
2008
|
-
|
|
2383
|
+
const spreadsheetSystemClipboardTimeoutMs = 800;
|
|
2384
|
+
function spreadsheetCoreContextMenuItems({ can, clipboard = browserSpreadsheetClipboard, commands, selection }) {
|
|
2385
|
+
const copy = (cut)=>{
|
|
2386
|
+
copySpreadsheetSelection(clipboard, selection.clipboard, cut).then((copied)=>{
|
|
2387
|
+
if (copied && cut && !commands.clearSelectedCells()) showToast('选区已复制,但无法清除原内容。', 'error');
|
|
2388
|
+
});
|
|
2389
|
+
};
|
|
2390
|
+
return [
|
|
2391
|
+
{
|
|
2392
|
+
id: 'cut-cells',
|
|
2393
|
+
label: '剪切',
|
|
2394
|
+
icon: /*#__PURE__*/ jsx(Scissors, {
|
|
2395
|
+
size: 14
|
|
2396
|
+
}),
|
|
2397
|
+
shortcut: '⌘X',
|
|
2398
|
+
ariaKeyShortcut: 'Control+X Meta+X',
|
|
2399
|
+
disabled: !can.clearSelectedCells(),
|
|
2400
|
+
onSelect: ()=>copy(true)
|
|
2401
|
+
},
|
|
2402
|
+
{
|
|
2403
|
+
id: 'copy-cells',
|
|
2404
|
+
label: '复制',
|
|
2405
|
+
icon: /*#__PURE__*/ jsx(Copy, {
|
|
2406
|
+
size: 14
|
|
2407
|
+
}),
|
|
2408
|
+
shortcut: '⌘C',
|
|
2409
|
+
ariaKeyShortcut: 'Control+C Meta+C',
|
|
2410
|
+
onSelect: ()=>copy(false)
|
|
2411
|
+
},
|
|
2412
|
+
{
|
|
2413
|
+
id: 'paste-cells',
|
|
2414
|
+
label: '粘贴',
|
|
2415
|
+
icon: /*#__PURE__*/ jsx(ClipboardPaste, {
|
|
2416
|
+
size: 14
|
|
2417
|
+
}),
|
|
2418
|
+
shortcut: '⌘V',
|
|
2419
|
+
ariaKeyShortcut: 'Control+V Meta+V',
|
|
2420
|
+
disabled: !can.pasteCells([
|
|
2421
|
+
[
|
|
2422
|
+
''
|
|
2423
|
+
]
|
|
2424
|
+
]),
|
|
2425
|
+
onSelect: ()=>void pasteSpreadsheetSelection(clipboard, commands.pasteCells)
|
|
2426
|
+
},
|
|
2427
|
+
{
|
|
2428
|
+
id: 'clear-cells',
|
|
2429
|
+
label: '清除内容',
|
|
2430
|
+
icon: /*#__PURE__*/ jsx(Eraser, {
|
|
2431
|
+
size: 14
|
|
2432
|
+
}),
|
|
2433
|
+
shortcut: 'Delete',
|
|
2434
|
+
ariaKeyShortcut: 'Delete',
|
|
2435
|
+
separatorBefore: true,
|
|
2436
|
+
disabled: !can.clearSelectedCells(),
|
|
2437
|
+
onSelect: ()=>{
|
|
2438
|
+
if (!commands.clearSelectedCells()) showToast(`无法清除选区 ${selection.reference}。`, 'error');
|
|
2439
|
+
}
|
|
2440
|
+
}
|
|
2441
|
+
];
|
|
2442
|
+
}
|
|
2443
|
+
function spreadsheetStructureContextMenuItems({ axis, can, commands, onResize }) {
|
|
2444
|
+
const row = 'row' === axis;
|
|
2445
|
+
const subject = row ? '行' : '列';
|
|
2446
|
+
const before = row ? '上方' : '左侧';
|
|
2447
|
+
const after = row ? '下方' : '右侧';
|
|
2448
|
+
const defaultSize = row ? 24 : 96;
|
|
2449
|
+
return [
|
|
2450
|
+
...spreadsheetSortContextMenuItems({
|
|
2451
|
+
can,
|
|
2452
|
+
commands,
|
|
2453
|
+
idSuffix: axis
|
|
2454
|
+
}),
|
|
2455
|
+
{
|
|
2456
|
+
id: `insert-${axis}-before`,
|
|
2457
|
+
label: `在${before}插入${subject}`,
|
|
2458
|
+
icon: /*#__PURE__*/ jsx(Plus, {
|
|
2459
|
+
size: 14
|
|
2460
|
+
}),
|
|
2461
|
+
separatorBefore: true,
|
|
2462
|
+
disabled: !can.insertSelectedStructure(axis, 'before'),
|
|
2463
|
+
onSelect: ()=>commands.insertSelectedStructure(axis, 'before')
|
|
2464
|
+
},
|
|
2465
|
+
{
|
|
2466
|
+
id: `insert-${axis}-after`,
|
|
2467
|
+
label: `在${after}插入${subject}`,
|
|
2468
|
+
icon: /*#__PURE__*/ jsx(Plus, {
|
|
2469
|
+
size: 14
|
|
2470
|
+
}),
|
|
2471
|
+
disabled: !can.insertSelectedStructure(axis, 'after'),
|
|
2472
|
+
onSelect: ()=>commands.insertSelectedStructure(axis, 'after')
|
|
2473
|
+
},
|
|
2474
|
+
{
|
|
2475
|
+
id: `delete-${axis}`,
|
|
2476
|
+
label: `删除所选${subject}`,
|
|
2477
|
+
icon: /*#__PURE__*/ jsx(Trash2, {
|
|
2478
|
+
size: 14
|
|
2479
|
+
}),
|
|
2480
|
+
danger: true,
|
|
2481
|
+
disabled: !can.deleteSelectedStructure(axis),
|
|
2482
|
+
onSelect: ()=>commands.deleteSelectedStructure(axis)
|
|
2483
|
+
},
|
|
2484
|
+
{
|
|
2485
|
+
id: `resize-${axis}`,
|
|
2486
|
+
label: row ? '行高…' : '列宽…',
|
|
2487
|
+
icon: row ? /*#__PURE__*/ jsx(MoveVertical, {
|
|
2488
|
+
size: 14
|
|
2489
|
+
}) : /*#__PURE__*/ jsx(MoveHorizontal, {
|
|
2490
|
+
size: 14
|
|
2491
|
+
}),
|
|
2492
|
+
disabled: !can.setSelectedStructureSize(axis, defaultSize),
|
|
2493
|
+
onSelect: ()=>onResize(axis)
|
|
2494
|
+
},
|
|
2495
|
+
{
|
|
2496
|
+
id: `hide-${axis}`,
|
|
2497
|
+
label: `隐藏所选${subject}`,
|
|
2498
|
+
icon: /*#__PURE__*/ jsx(EyeOff, {
|
|
2499
|
+
size: 14
|
|
2500
|
+
}),
|
|
2501
|
+
separatorBefore: true,
|
|
2502
|
+
disabled: !can.setSelectedStructureHidden(axis, true),
|
|
2503
|
+
onSelect: ()=>commands.setSelectedStructureHidden(axis, true)
|
|
2504
|
+
},
|
|
2505
|
+
{
|
|
2506
|
+
id: `show-${axis}`,
|
|
2507
|
+
label: `取消隐藏${subject}`,
|
|
2508
|
+
icon: /*#__PURE__*/ jsx(Eye, {
|
|
2509
|
+
size: 14
|
|
2510
|
+
}),
|
|
2511
|
+
disabled: !can.setSelectedStructureHidden(axis, false),
|
|
2512
|
+
onSelect: ()=>commands.setSelectedStructureHidden(axis, false)
|
|
2513
|
+
}
|
|
2514
|
+
];
|
|
2515
|
+
}
|
|
2516
|
+
function spreadsheetSortContextMenuItems({ can, commands, idSuffix = 'selection', separatorBefore = false }) {
|
|
2517
|
+
return [
|
|
2518
|
+
{
|
|
2519
|
+
id: `sort-${idSuffix}-ascending`,
|
|
2520
|
+
label: '升序排列',
|
|
2521
|
+
icon: /*#__PURE__*/ jsx(ArrowUp, {
|
|
2522
|
+
size: 14
|
|
2523
|
+
}),
|
|
2524
|
+
separatorBefore,
|
|
2525
|
+
disabled: !can.sortSelectedCells('ascending'),
|
|
2526
|
+
onSelect: ()=>commands.sortSelectedCells('ascending')
|
|
2527
|
+
},
|
|
2528
|
+
{
|
|
2529
|
+
id: `sort-${idSuffix}-descending`,
|
|
2530
|
+
label: '降序排列',
|
|
2531
|
+
icon: /*#__PURE__*/ jsx(ArrowDown, {
|
|
2532
|
+
size: 14
|
|
2533
|
+
}),
|
|
2534
|
+
disabled: !can.sortSelectedCells('descending'),
|
|
2535
|
+
onSelect: ()=>commands.sortSelectedCells('descending')
|
|
2536
|
+
}
|
|
2537
|
+
];
|
|
2538
|
+
}
|
|
2539
|
+
function parseSpreadsheetClipboardText(value) {
|
|
2540
|
+
if (!value) return [];
|
|
2541
|
+
const normalized = value.replace(/\r\n?/g, '\n').replace(/\n$/, '');
|
|
2542
|
+
if (!normalized) return [];
|
|
2543
|
+
const rows = normalized.split('\n').map((row)=>row.split('\t'));
|
|
2544
|
+
const width = Math.max(...rows.map((row)=>row.length));
|
|
2545
|
+
return rows.map((row)=>[
|
|
2546
|
+
...row,
|
|
2547
|
+
...Array.from({
|
|
2548
|
+
length: width - row.length
|
|
2549
|
+
}, ()=>'')
|
|
2550
|
+
]);
|
|
2551
|
+
}
|
|
2552
|
+
const browserSpreadsheetClipboard = {
|
|
2553
|
+
readText: ()=>readSpreadsheetClipboardText("u" > typeof navigator && navigator.clipboard?.readText ? ()=>navigator.clipboard.readText() : void 0, readLocalClipboard, spreadsheetSystemClipboardTimeoutMs, canReadBrowserSystemClipboard),
|
|
2554
|
+
writeText: (value)=>writeSpreadsheetClipboardText(value, "u" > typeof navigator && navigator.clipboard?.writeText ? (next)=>navigator.clipboard.writeText(next) : void 0, writeLocalClipboard)
|
|
2555
|
+
};
|
|
2556
|
+
async function readSpreadsheetClipboardText(readSystem, readLocal, timeoutMs = spreadsheetSystemClipboardTimeoutMs, canReadSystem = ()=>true) {
|
|
2557
|
+
if (readSystem && await canReadSystem()) try {
|
|
2558
|
+
const value = await withSpreadsheetClipboardTimeout(readSystem(), timeoutMs);
|
|
2559
|
+
if (value) return value;
|
|
2560
|
+
} catch {}
|
|
2561
|
+
return readLocal();
|
|
2562
|
+
}
|
|
2563
|
+
async function canReadBrowserSystemClipboard() {
|
|
2564
|
+
if ("u" < typeof navigator || !navigator.permissions?.query) return true;
|
|
2565
|
+
try {
|
|
2566
|
+
const permission = await navigator.permissions.query({
|
|
2567
|
+
name: 'clipboard-read'
|
|
2568
|
+
});
|
|
2569
|
+
return 'granted' === permission.state;
|
|
2570
|
+
} catch {
|
|
2571
|
+
return true;
|
|
2572
|
+
}
|
|
2573
|
+
}
|
|
2574
|
+
async function writeSpreadsheetClipboardText(value, writeSystem, writeLocal, timeoutMs = spreadsheetSystemClipboardTimeoutMs) {
|
|
2575
|
+
writeLocal(value);
|
|
2576
|
+
if (!writeSystem) return;
|
|
2577
|
+
try {
|
|
2578
|
+
await withSpreadsheetClipboardTimeout(writeSystem(value), timeoutMs);
|
|
2579
|
+
} catch {}
|
|
2580
|
+
}
|
|
2581
|
+
async function copySpreadsheetSelection(clipboard, value, cut) {
|
|
2582
|
+
try {
|
|
2583
|
+
await clipboard.writeText(value);
|
|
2584
|
+
showToast(cut ? '选区已剪切' : '选区已复制', 'success');
|
|
2585
|
+
return true;
|
|
2586
|
+
} catch {
|
|
2587
|
+
showToast('无法访问剪贴板,请使用系统快捷键。', 'error');
|
|
2588
|
+
return false;
|
|
2589
|
+
}
|
|
2590
|
+
}
|
|
2591
|
+
async function pasteSpreadsheetSelection(clipboard, paste) {
|
|
2592
|
+
try {
|
|
2593
|
+
const values = parseSpreadsheetClipboardText(await clipboard.readText());
|
|
2594
|
+
if (!values.length) return void showToast('剪贴板中没有可粘贴的表格内容。', 'error');
|
|
2595
|
+
if (!paste(values)) showToast('当前选区无法粘贴这些内容。', 'error');
|
|
2596
|
+
} catch {
|
|
2597
|
+
showToast('无法读取剪贴板,请使用系统粘贴快捷键。', 'error');
|
|
2598
|
+
}
|
|
2599
|
+
}
|
|
2600
|
+
function readLocalClipboard() {
|
|
2601
|
+
try {
|
|
2602
|
+
return sessionStorage.getItem('a3s-office-spreadsheet-clipboard') ?? '';
|
|
2603
|
+
} catch {
|
|
2604
|
+
return '';
|
|
2605
|
+
}
|
|
2606
|
+
}
|
|
2607
|
+
function writeLocalClipboard(value) {
|
|
2608
|
+
try {
|
|
2609
|
+
sessionStorage.setItem('a3s-office-spreadsheet-clipboard', value);
|
|
2610
|
+
} catch {}
|
|
2611
|
+
}
|
|
2612
|
+
async function withSpreadsheetClipboardTimeout(request, timeoutMs) {
|
|
2613
|
+
let timeout;
|
|
2614
|
+
const expired = new Promise((_resolve, reject)=>{
|
|
2615
|
+
timeout = setTimeout(()=>reject(new Error('Spreadsheet clipboard request timed out.')), Math.max(0, timeoutMs));
|
|
2616
|
+
});
|
|
2617
|
+
try {
|
|
2618
|
+
return await Promise.race([
|
|
2619
|
+
request,
|
|
2620
|
+
expired
|
|
2621
|
+
]);
|
|
2622
|
+
} finally{
|
|
2623
|
+
if (timeout) clearTimeout(timeout);
|
|
2624
|
+
}
|
|
2625
|
+
}
|
|
2626
|
+
function spreadsheetFormulaCount(content) {
|
|
2627
|
+
return content.sheets.reduce((count, sheet)=>count + (sheet.data ?? []).reduce((sheetCount, row)=>sheetCount + row.reduce((rowCount, cell)=>rowCount + (cell?.f ? 1 : 0), 0), 0), 0);
|
|
2628
|
+
}
|
|
2629
|
+
function spreadsheetFormulaAnalysis(content) {
|
|
2630
|
+
const scan = scanSpreadsheetFormulas(content);
|
|
2631
|
+
return {
|
|
2009
2632
|
summary: scan.summary,
|
|
2010
2633
|
diagnostics: createSpreadsheetFormulaDiagnostics(content, scan)
|
|
2011
2634
|
};
|
|
@@ -2185,13 +2808,493 @@ function scanSpreadsheetFormulas(content) {
|
|
|
2185
2808
|
function isFormulaError(cell) {
|
|
2186
2809
|
return cell.ct?.t === 'e' || /^#(?:NULL!|DIV\/0!|VALUE!|REF!|NAME\?|NUM!|N\/A|GETTING_DATA)$/i.test(String(cell.m ?? ''));
|
|
2187
2810
|
}
|
|
2188
|
-
const
|
|
2189
|
-
|
|
2190
|
-
|
|
2191
|
-
|
|
2192
|
-
|
|
2193
|
-
|
|
2194
|
-
|
|
2811
|
+
const spreadsheetRibbonTabs = [
|
|
2812
|
+
{
|
|
2813
|
+
id: 'home',
|
|
2814
|
+
label: '开始'
|
|
2815
|
+
},
|
|
2816
|
+
{
|
|
2817
|
+
id: 'insert',
|
|
2818
|
+
label: '插入'
|
|
2819
|
+
},
|
|
2820
|
+
{
|
|
2821
|
+
id: 'pageLayout',
|
|
2822
|
+
label: '页面布局',
|
|
2823
|
+
compactLabel: '布局'
|
|
2824
|
+
},
|
|
2825
|
+
{
|
|
2826
|
+
id: 'formulas',
|
|
2827
|
+
label: '公式'
|
|
2828
|
+
},
|
|
2829
|
+
{
|
|
2830
|
+
id: 'data',
|
|
2831
|
+
label: '数据'
|
|
2832
|
+
},
|
|
2833
|
+
{
|
|
2834
|
+
id: 'review',
|
|
2835
|
+
label: '审阅'
|
|
2836
|
+
},
|
|
2837
|
+
{
|
|
2838
|
+
id: 'view',
|
|
2839
|
+
label: '视图'
|
|
2840
|
+
}
|
|
2841
|
+
];
|
|
2842
|
+
const spreadsheetCommandCatalog = {
|
|
2843
|
+
undo: {
|
|
2844
|
+
id: 'history.undo',
|
|
2845
|
+
label: '撤销',
|
|
2846
|
+
location: {
|
|
2847
|
+
area: 'quickAccess'
|
|
2848
|
+
},
|
|
2849
|
+
shortcut: {
|
|
2850
|
+
label: 'Cmd/Ctrl+Z',
|
|
2851
|
+
aria: 'Control+Z Meta+Z',
|
|
2852
|
+
editor: [
|
|
2853
|
+
'Mod-z'
|
|
2854
|
+
]
|
|
2855
|
+
}
|
|
2856
|
+
},
|
|
2857
|
+
redo: {
|
|
2858
|
+
id: 'history.redo',
|
|
2859
|
+
label: '重做',
|
|
2860
|
+
location: {
|
|
2861
|
+
area: 'quickAccess'
|
|
2862
|
+
},
|
|
2863
|
+
shortcut: {
|
|
2864
|
+
label: 'Cmd/Ctrl+Shift+Z 或 Cmd/Ctrl+Y',
|
|
2865
|
+
aria: 'Control+Shift+Z Meta+Shift+Z Control+Y Meta+Y',
|
|
2866
|
+
editor: [
|
|
2867
|
+
'Mod-Shift-z',
|
|
2868
|
+
'Mod-y'
|
|
2869
|
+
]
|
|
2870
|
+
}
|
|
2871
|
+
},
|
|
2872
|
+
paste: {
|
|
2873
|
+
id: 'clipboard.paste',
|
|
2874
|
+
label: '粘贴',
|
|
2875
|
+
location: {
|
|
2876
|
+
area: 'ribbon',
|
|
2877
|
+
tab: 'home',
|
|
2878
|
+
group: 'clipboard'
|
|
2879
|
+
},
|
|
2880
|
+
shortcut: {
|
|
2881
|
+
label: 'Cmd/Ctrl+V',
|
|
2882
|
+
aria: 'Control+V Meta+V',
|
|
2883
|
+
editor: [
|
|
2884
|
+
'Mod-v'
|
|
2885
|
+
]
|
|
2886
|
+
}
|
|
2887
|
+
},
|
|
2888
|
+
cut: {
|
|
2889
|
+
id: 'clipboard.cut',
|
|
2890
|
+
label: '剪切',
|
|
2891
|
+
location: {
|
|
2892
|
+
area: 'ribbon',
|
|
2893
|
+
tab: 'home',
|
|
2894
|
+
group: 'clipboard'
|
|
2895
|
+
},
|
|
2896
|
+
shortcut: {
|
|
2897
|
+
label: 'Cmd/Ctrl+X',
|
|
2898
|
+
aria: 'Control+X Meta+X',
|
|
2899
|
+
editor: [
|
|
2900
|
+
'Mod-x'
|
|
2901
|
+
]
|
|
2902
|
+
}
|
|
2903
|
+
},
|
|
2904
|
+
copy: {
|
|
2905
|
+
id: 'clipboard.copy',
|
|
2906
|
+
label: '复制',
|
|
2907
|
+
location: {
|
|
2908
|
+
area: 'ribbon',
|
|
2909
|
+
tab: 'home',
|
|
2910
|
+
group: 'clipboard'
|
|
2911
|
+
},
|
|
2912
|
+
shortcut: {
|
|
2913
|
+
label: 'Cmd/Ctrl+C',
|
|
2914
|
+
aria: 'Control+C Meta+C',
|
|
2915
|
+
editor: [
|
|
2916
|
+
'Mod-c'
|
|
2917
|
+
]
|
|
2918
|
+
}
|
|
2919
|
+
},
|
|
2920
|
+
formatPainter: {
|
|
2921
|
+
id: 'clipboard.formatPainter',
|
|
2922
|
+
label: '格式刷',
|
|
2923
|
+
location: {
|
|
2924
|
+
area: 'ribbon',
|
|
2925
|
+
tab: 'home',
|
|
2926
|
+
group: 'clipboard'
|
|
2927
|
+
}
|
|
2928
|
+
},
|
|
2929
|
+
bold: {
|
|
2930
|
+
id: 'font.bold',
|
|
2931
|
+
label: '加粗',
|
|
2932
|
+
location: {
|
|
2933
|
+
area: 'ribbon',
|
|
2934
|
+
tab: 'home',
|
|
2935
|
+
group: 'font'
|
|
2936
|
+
},
|
|
2937
|
+
shortcut: {
|
|
2938
|
+
label: 'Cmd/Ctrl+B',
|
|
2939
|
+
aria: 'Control+B Meta+B',
|
|
2940
|
+
editor: [
|
|
2941
|
+
'Mod-b'
|
|
2942
|
+
]
|
|
2943
|
+
}
|
|
2944
|
+
},
|
|
2945
|
+
italic: {
|
|
2946
|
+
id: 'font.italic',
|
|
2947
|
+
label: '斜体',
|
|
2948
|
+
location: {
|
|
2949
|
+
area: 'ribbon',
|
|
2950
|
+
tab: 'home',
|
|
2951
|
+
group: 'font'
|
|
2952
|
+
},
|
|
2953
|
+
shortcut: {
|
|
2954
|
+
label: 'Cmd/Ctrl+I',
|
|
2955
|
+
aria: 'Control+I Meta+I',
|
|
2956
|
+
editor: [
|
|
2957
|
+
'Mod-i'
|
|
2958
|
+
]
|
|
2959
|
+
}
|
|
2960
|
+
},
|
|
2961
|
+
underline: {
|
|
2962
|
+
id: 'font.underline',
|
|
2963
|
+
label: '下划线',
|
|
2964
|
+
location: {
|
|
2965
|
+
area: 'ribbon',
|
|
2966
|
+
tab: 'home',
|
|
2967
|
+
group: 'font'
|
|
2968
|
+
},
|
|
2969
|
+
shortcut: {
|
|
2970
|
+
label: 'Cmd/Ctrl+U',
|
|
2971
|
+
aria: 'Control+U Meta+U',
|
|
2972
|
+
editor: [
|
|
2973
|
+
'Mod-u'
|
|
2974
|
+
]
|
|
2975
|
+
}
|
|
2976
|
+
},
|
|
2977
|
+
mergeAndCenter: {
|
|
2978
|
+
id: 'alignment.mergeAndCenter',
|
|
2979
|
+
label: '合并居中',
|
|
2980
|
+
location: {
|
|
2981
|
+
area: 'ribbon',
|
|
2982
|
+
tab: 'home',
|
|
2983
|
+
group: 'alignment'
|
|
2984
|
+
},
|
|
2985
|
+
shortcut: {
|
|
2986
|
+
label: 'Ctrl+M',
|
|
2987
|
+
aria: 'Control+M',
|
|
2988
|
+
editor: [
|
|
2989
|
+
'Control-m'
|
|
2990
|
+
]
|
|
2991
|
+
}
|
|
2992
|
+
},
|
|
2993
|
+
mergeCells: {
|
|
2994
|
+
id: 'alignment.mergeCells',
|
|
2995
|
+
label: '合并单元格',
|
|
2996
|
+
location: {
|
|
2997
|
+
area: 'ribbon',
|
|
2998
|
+
tab: 'home',
|
|
2999
|
+
group: 'alignment'
|
|
3000
|
+
}
|
|
3001
|
+
},
|
|
3002
|
+
mergeAcross: {
|
|
3003
|
+
id: 'alignment.mergeAcross',
|
|
3004
|
+
label: '跨行合并',
|
|
3005
|
+
location: {
|
|
3006
|
+
area: 'ribbon',
|
|
3007
|
+
tab: 'home',
|
|
3008
|
+
group: 'alignment'
|
|
3009
|
+
}
|
|
3010
|
+
},
|
|
3011
|
+
unmergeCells: {
|
|
3012
|
+
id: 'alignment.unmergeCells',
|
|
3013
|
+
label: '取消合并单元格',
|
|
3014
|
+
location: {
|
|
3015
|
+
area: 'ribbon',
|
|
3016
|
+
tab: 'home',
|
|
3017
|
+
group: 'alignment'
|
|
3018
|
+
}
|
|
3019
|
+
},
|
|
3020
|
+
unmergeAndFill: {
|
|
3021
|
+
id: 'alignment.unmergeAndFill',
|
|
3022
|
+
label: '取消合并并填充',
|
|
3023
|
+
location: {
|
|
3024
|
+
area: 'ribbon',
|
|
3025
|
+
tab: 'home',
|
|
3026
|
+
group: 'alignment'
|
|
3027
|
+
}
|
|
3028
|
+
},
|
|
3029
|
+
conditionalFormatting: {
|
|
3030
|
+
id: 'styles.conditionalFormatting',
|
|
3031
|
+
label: '条件格式',
|
|
3032
|
+
location: {
|
|
3033
|
+
area: 'ribbon',
|
|
3034
|
+
tab: 'home',
|
|
3035
|
+
group: 'styles'
|
|
3036
|
+
}
|
|
3037
|
+
},
|
|
3038
|
+
insertRowsAbove: {
|
|
3039
|
+
id: 'cells.insertRowsAbove',
|
|
3040
|
+
label: '在上方插入行',
|
|
3041
|
+
location: {
|
|
3042
|
+
area: 'ribbon',
|
|
3043
|
+
tab: 'home',
|
|
3044
|
+
group: 'cells'
|
|
3045
|
+
}
|
|
3046
|
+
},
|
|
3047
|
+
insertRowsBelow: {
|
|
3048
|
+
id: 'cells.insertRowsBelow',
|
|
3049
|
+
label: '在下方插入行',
|
|
3050
|
+
location: {
|
|
3051
|
+
area: 'ribbon',
|
|
3052
|
+
tab: 'home',
|
|
3053
|
+
group: 'cells'
|
|
3054
|
+
}
|
|
3055
|
+
},
|
|
3056
|
+
insertColumnsLeft: {
|
|
3057
|
+
id: 'cells.insertColumnsLeft',
|
|
3058
|
+
label: '在左侧插入列',
|
|
3059
|
+
location: {
|
|
3060
|
+
area: 'ribbon',
|
|
3061
|
+
tab: 'home',
|
|
3062
|
+
group: 'cells'
|
|
3063
|
+
}
|
|
3064
|
+
},
|
|
3065
|
+
insertColumnsRight: {
|
|
3066
|
+
id: 'cells.insertColumnsRight',
|
|
3067
|
+
label: '在右侧插入列',
|
|
3068
|
+
location: {
|
|
3069
|
+
area: 'ribbon',
|
|
3070
|
+
tab: 'home',
|
|
3071
|
+
group: 'cells'
|
|
3072
|
+
}
|
|
3073
|
+
},
|
|
3074
|
+
deleteRows: {
|
|
3075
|
+
id: 'cells.deleteRows',
|
|
3076
|
+
label: '删除所选行',
|
|
3077
|
+
location: {
|
|
3078
|
+
area: 'ribbon',
|
|
3079
|
+
tab: 'home',
|
|
3080
|
+
group: 'cells'
|
|
3081
|
+
}
|
|
3082
|
+
},
|
|
3083
|
+
deleteColumns: {
|
|
3084
|
+
id: 'cells.deleteColumns',
|
|
3085
|
+
label: '删除所选列',
|
|
3086
|
+
location: {
|
|
3087
|
+
area: 'ribbon',
|
|
3088
|
+
tab: 'home',
|
|
3089
|
+
group: 'cells'
|
|
3090
|
+
}
|
|
3091
|
+
},
|
|
3092
|
+
clearAll: {
|
|
3093
|
+
id: 'editing.clearAll',
|
|
3094
|
+
label: '清除全部',
|
|
3095
|
+
location: {
|
|
3096
|
+
area: 'ribbon',
|
|
3097
|
+
tab: 'home',
|
|
3098
|
+
group: 'editing'
|
|
3099
|
+
}
|
|
3100
|
+
},
|
|
3101
|
+
clearFormats: {
|
|
3102
|
+
id: 'editing.clearFormats',
|
|
3103
|
+
label: '清除格式',
|
|
3104
|
+
location: {
|
|
3105
|
+
area: 'ribbon',
|
|
3106
|
+
tab: 'home',
|
|
3107
|
+
group: 'editing'
|
|
3108
|
+
}
|
|
3109
|
+
},
|
|
3110
|
+
clearContents: {
|
|
3111
|
+
id: 'editing.clearContents',
|
|
3112
|
+
label: '清除内容',
|
|
3113
|
+
location: {
|
|
3114
|
+
area: 'ribbon',
|
|
3115
|
+
tab: 'home',
|
|
3116
|
+
group: 'editing'
|
|
3117
|
+
},
|
|
3118
|
+
shortcut: {
|
|
3119
|
+
label: 'Delete/Backspace',
|
|
3120
|
+
aria: 'Delete Backspace',
|
|
3121
|
+
editor: [
|
|
3122
|
+
'Delete',
|
|
3123
|
+
'Backspace'
|
|
3124
|
+
]
|
|
3125
|
+
}
|
|
3126
|
+
},
|
|
3127
|
+
clearComments: {
|
|
3128
|
+
id: 'editing.clearComments',
|
|
3129
|
+
label: '清除批注',
|
|
3130
|
+
location: {
|
|
3131
|
+
area: 'ribbon',
|
|
3132
|
+
tab: 'home',
|
|
3133
|
+
group: 'editing'
|
|
3134
|
+
}
|
|
3135
|
+
},
|
|
3136
|
+
clearHyperlinks: {
|
|
3137
|
+
id: 'editing.clearHyperlinks',
|
|
3138
|
+
label: '清除超链接',
|
|
3139
|
+
location: {
|
|
3140
|
+
area: 'ribbon',
|
|
3141
|
+
tab: 'home',
|
|
3142
|
+
group: 'editing'
|
|
3143
|
+
}
|
|
3144
|
+
},
|
|
3145
|
+
find: {
|
|
3146
|
+
id: 'editing.find',
|
|
3147
|
+
label: '查找',
|
|
3148
|
+
location: {
|
|
3149
|
+
area: 'ribbon',
|
|
3150
|
+
tab: 'home',
|
|
3151
|
+
group: 'editing'
|
|
3152
|
+
},
|
|
3153
|
+
shortcut: {
|
|
3154
|
+
label: 'Cmd/Ctrl+F',
|
|
3155
|
+
aria: 'Control+F Meta+F',
|
|
3156
|
+
editor: [
|
|
3157
|
+
'Mod-f'
|
|
3158
|
+
]
|
|
3159
|
+
}
|
|
3160
|
+
},
|
|
3161
|
+
insertChart: {
|
|
3162
|
+
id: 'insert.chart',
|
|
3163
|
+
label: '插入图表',
|
|
3164
|
+
location: {
|
|
3165
|
+
area: 'ribbon',
|
|
3166
|
+
tab: 'insert',
|
|
3167
|
+
group: 'charts'
|
|
3168
|
+
}
|
|
3169
|
+
},
|
|
3170
|
+
printSettings: {
|
|
3171
|
+
id: 'pageLayout.printSettings',
|
|
3172
|
+
label: '打印设置',
|
|
3173
|
+
location: {
|
|
3174
|
+
area: 'ribbon',
|
|
3175
|
+
tab: 'pageLayout',
|
|
3176
|
+
group: 'pageSetup'
|
|
3177
|
+
}
|
|
3178
|
+
},
|
|
3179
|
+
nameManager: {
|
|
3180
|
+
id: 'formulas.nameManager',
|
|
3181
|
+
label: '名称管理器',
|
|
3182
|
+
location: {
|
|
3183
|
+
area: 'ribbon',
|
|
3184
|
+
tab: 'formulas',
|
|
3185
|
+
group: 'definedNames'
|
|
3186
|
+
}
|
|
3187
|
+
},
|
|
3188
|
+
formulaManager: {
|
|
3189
|
+
id: 'formulas.manager',
|
|
3190
|
+
label: '公式与计算',
|
|
3191
|
+
location: {
|
|
3192
|
+
area: 'ribbon',
|
|
3193
|
+
tab: 'formulas',
|
|
3194
|
+
group: 'calculation'
|
|
3195
|
+
}
|
|
3196
|
+
},
|
|
3197
|
+
recalculateWorkbook: {
|
|
3198
|
+
id: 'formulas.recalculateWorkbook',
|
|
3199
|
+
label: '重新计算工作簿',
|
|
3200
|
+
location: {
|
|
3201
|
+
area: 'ribbon',
|
|
3202
|
+
tab: 'formulas',
|
|
3203
|
+
group: 'calculation'
|
|
3204
|
+
},
|
|
3205
|
+
shortcut: {
|
|
3206
|
+
label: 'F9',
|
|
3207
|
+
aria: 'F9',
|
|
3208
|
+
editor: [
|
|
3209
|
+
'F9'
|
|
3210
|
+
]
|
|
3211
|
+
}
|
|
3212
|
+
},
|
|
3213
|
+
sortAscending: {
|
|
3214
|
+
id: 'data.sortAscending',
|
|
3215
|
+
label: '升序',
|
|
3216
|
+
location: {
|
|
3217
|
+
area: 'ribbon',
|
|
3218
|
+
tab: 'data',
|
|
3219
|
+
group: 'sortAndFilter'
|
|
3220
|
+
}
|
|
3221
|
+
},
|
|
3222
|
+
sortDescending: {
|
|
3223
|
+
id: 'data.sortDescending',
|
|
3224
|
+
label: '降序',
|
|
3225
|
+
location: {
|
|
3226
|
+
area: 'ribbon',
|
|
3227
|
+
tab: 'data',
|
|
3228
|
+
group: 'sortAndFilter'
|
|
3229
|
+
}
|
|
3230
|
+
},
|
|
3231
|
+
autoFilter: {
|
|
3232
|
+
id: 'data.autoFilter',
|
|
3233
|
+
label: '自动筛选',
|
|
3234
|
+
location: {
|
|
3235
|
+
area: 'ribbon',
|
|
3236
|
+
tab: 'data',
|
|
3237
|
+
group: 'sortAndFilter'
|
|
3238
|
+
},
|
|
3239
|
+
shortcut: {
|
|
3240
|
+
label: 'Cmd/Ctrl+Shift+L',
|
|
3241
|
+
aria: 'Control+Shift+L Meta+Shift+L',
|
|
3242
|
+
editor: [
|
|
3243
|
+
'Mod-Shift-l'
|
|
3244
|
+
]
|
|
3245
|
+
},
|
|
3246
|
+
menuShortcut: {
|
|
3247
|
+
label: 'Alt+↓',
|
|
3248
|
+
aria: 'Alt+ArrowDown',
|
|
3249
|
+
editor: [
|
|
3250
|
+
'Alt-ArrowDown'
|
|
3251
|
+
]
|
|
3252
|
+
}
|
|
3253
|
+
},
|
|
3254
|
+
pivotTable: {
|
|
3255
|
+
id: 'data.pivotTable',
|
|
3256
|
+
label: '数据透视表',
|
|
3257
|
+
location: {
|
|
3258
|
+
area: 'ribbon',
|
|
3259
|
+
tab: 'data',
|
|
3260
|
+
group: 'analysis'
|
|
3261
|
+
}
|
|
3262
|
+
},
|
|
3263
|
+
protectSheet: {
|
|
3264
|
+
id: 'review.protectSheet',
|
|
3265
|
+
label: '工作表保护',
|
|
3266
|
+
location: {
|
|
3267
|
+
area: 'ribbon',
|
|
3268
|
+
tab: 'review',
|
|
3269
|
+
group: 'protection'
|
|
3270
|
+
}
|
|
3271
|
+
},
|
|
3272
|
+
gridLines: {
|
|
3273
|
+
id: 'view.gridLines',
|
|
3274
|
+
label: '网格线',
|
|
3275
|
+
location: {
|
|
3276
|
+
area: 'ribbon',
|
|
3277
|
+
tab: 'view',
|
|
3278
|
+
group: 'workbookViews'
|
|
3279
|
+
}
|
|
3280
|
+
},
|
|
3281
|
+
freezePanes: {
|
|
3282
|
+
id: 'view.freezePanes',
|
|
3283
|
+
label: '冻结窗格',
|
|
3284
|
+
location: {
|
|
3285
|
+
area: 'ribbon',
|
|
3286
|
+
tab: 'view',
|
|
3287
|
+
group: 'window'
|
|
3288
|
+
}
|
|
3289
|
+
}
|
|
3290
|
+
};
|
|
3291
|
+
const COMPARISON_LABELS = {
|
|
3292
|
+
greaterThan: '大于',
|
|
3293
|
+
greaterThanOrEqual: '大于或等于',
|
|
3294
|
+
lessThan: '小于',
|
|
3295
|
+
lessThanOrEqual: '小于或等于',
|
|
3296
|
+
equal: '等于',
|
|
3297
|
+
notEqual: '不等于',
|
|
2195
3298
|
between: '介于',
|
|
2196
3299
|
notBetween: '不介于'
|
|
2197
3300
|
};
|
|
@@ -2589,34 +3692,6 @@ function adjustSpreadsheetNumberFormatSection(section, direction) {
|
|
|
2589
3692
|
const replacement = `${match[1]}${nextDecimals ? `.${nextDecimals}` : ''}`;
|
|
2590
3693
|
return `${section.slice(0, match.index)}${replacement}${section.slice(match.index + match[0].length)}`;
|
|
2591
3694
|
}
|
|
2592
|
-
function InlineNotice({ title, children, icon, actions, tone = 'info', role, className = '' }) {
|
|
2593
|
-
return /*#__PURE__*/ jsxs("div", {
|
|
2594
|
-
className: `ds-inline-notice ${tone}${className ? ` ${className}` : ''}`,
|
|
2595
|
-
role: role,
|
|
2596
|
-
children: [
|
|
2597
|
-
icon && /*#__PURE__*/ jsx("span", {
|
|
2598
|
-
className: "ds-inline-notice-icon",
|
|
2599
|
-
"aria-hidden": "true",
|
|
2600
|
-
children: icon
|
|
2601
|
-
}),
|
|
2602
|
-
/*#__PURE__*/ jsxs("div", {
|
|
2603
|
-
className: "ds-inline-notice-copy",
|
|
2604
|
-
children: [
|
|
2605
|
-
title && /*#__PURE__*/ jsx("strong", {
|
|
2606
|
-
children: title
|
|
2607
|
-
}),
|
|
2608
|
-
/*#__PURE__*/ jsx("div", {
|
|
2609
|
-
children: children
|
|
2610
|
-
})
|
|
2611
|
-
]
|
|
2612
|
-
}),
|
|
2613
|
-
actions && /*#__PURE__*/ jsx("div", {
|
|
2614
|
-
className: "ds-inline-notice-actions",
|
|
2615
|
-
children: actions
|
|
2616
|
-
})
|
|
2617
|
-
]
|
|
2618
|
-
});
|
|
2619
|
-
}
|
|
2620
3695
|
function parseSpreadsheetRowPageBreaks(value, maximumRow) {
|
|
2621
3696
|
return parsePageBreakList(value, maximumRow, (token)=>{
|
|
2622
3697
|
const match = /^\$?([1-9]\d*)$/.exec(token);
|
|
@@ -3394,37 +4469,6 @@ function validPageSetup(pageSetup) {
|
|
|
3394
4469
|
const validInteger = (value, minimum, maximum)=>Number.isInteger(value) && value >= minimum && value <= maximum;
|
|
3395
4470
|
return validInteger(pageSetup.scale, 10, 400) && validInteger(pageSetup.fitToWidth, 0, 32767) && validInteger(pageSetup.fitToHeight, 0, 32767) && validInteger(pageSetup.pageNumberStart, 1, 32767) && Object.values(pageSetup.margins).every((margin)=>Number.isFinite(margin) && margin >= 0 && margin <= 100);
|
|
3396
4471
|
}
|
|
3397
|
-
const spreadsheetRibbonTabs = [
|
|
3398
|
-
{
|
|
3399
|
-
id: 'home',
|
|
3400
|
-
label: '开始'
|
|
3401
|
-
},
|
|
3402
|
-
{
|
|
3403
|
-
id: 'insert',
|
|
3404
|
-
label: '插入'
|
|
3405
|
-
},
|
|
3406
|
-
{
|
|
3407
|
-
id: 'pageLayout',
|
|
3408
|
-
label: '页面布局',
|
|
3409
|
-
compactLabel: '布局'
|
|
3410
|
-
},
|
|
3411
|
-
{
|
|
3412
|
-
id: 'formulas',
|
|
3413
|
-
label: '公式'
|
|
3414
|
-
},
|
|
3415
|
-
{
|
|
3416
|
-
id: 'data',
|
|
3417
|
-
label: '数据'
|
|
3418
|
-
},
|
|
3419
|
-
{
|
|
3420
|
-
id: 'review',
|
|
3421
|
-
label: '审阅'
|
|
3422
|
-
},
|
|
3423
|
-
{
|
|
3424
|
-
id: 'view',
|
|
3425
|
-
label: '视图'
|
|
3426
|
-
}
|
|
3427
|
-
];
|
|
3428
4472
|
const spreadsheetNumberFormatOptions = [
|
|
3429
4473
|
{
|
|
3430
4474
|
value: 'general',
|
|
@@ -3444,7 +4488,19 @@ const spreadsheetNumberFormatOptions = [
|
|
|
3444
4488
|
disabled: true
|
|
3445
4489
|
}
|
|
3446
4490
|
];
|
|
3447
|
-
|
|
4491
|
+
const defaultSpreadsheetFreezePanesSelection = {
|
|
4492
|
+
row: [
|
|
4493
|
+
0,
|
|
4494
|
+
0
|
|
4495
|
+
],
|
|
4496
|
+
column: [
|
|
4497
|
+
0,
|
|
4498
|
+
0
|
|
4499
|
+
],
|
|
4500
|
+
row_focus: 0,
|
|
4501
|
+
column_focus: 0
|
|
4502
|
+
};
|
|
4503
|
+
function SpreadsheetEditorRibbon({ activeTab, autoFilterActive = false, can, commands, content, fileActions, findOpen, formatPainterMode = null, freezePanesActive = false, freezePanesSelection = defaultSpreadsheetFreezePanesSelection, gridLinesVisible, panelId, onOpenFind, onTabChange, onTogglePanel, panel, toolbarCell }) {
|
|
3448
4504
|
const formulaCount = useMemo(()=>spreadsheetFormulaCount(content), [
|
|
3449
4505
|
content
|
|
3450
4506
|
]);
|
|
@@ -3464,32 +4520,89 @@ function SpreadsheetEditorRibbon({ activeTab, can, commands, content, fileAction
|
|
|
3464
4520
|
defaultTab: "home",
|
|
3465
4521
|
activeTab: activeTab,
|
|
3466
4522
|
onTabChange: onTabChange,
|
|
4523
|
+
adaptive: true,
|
|
4524
|
+
collapsible: true,
|
|
3467
4525
|
fileActions: fileActions,
|
|
4526
|
+
quickAccessActions: [
|
|
4527
|
+
{
|
|
4528
|
+
id: spreadsheetCommandCatalog.undo.id,
|
|
4529
|
+
label: spreadsheetCommandCatalog.undo.label,
|
|
4530
|
+
icon: /*#__PURE__*/ jsx(Undo2, {
|
|
4531
|
+
size: 15
|
|
4532
|
+
}),
|
|
4533
|
+
shortcut: spreadsheetCommandCatalog.undo.shortcut.label,
|
|
4534
|
+
ariaKeyShortcuts: spreadsheetCommandCatalog.undo.shortcut.aria,
|
|
4535
|
+
disabled: !can.undo(),
|
|
4536
|
+
onSelect: ()=>{
|
|
4537
|
+
commands.undo();
|
|
4538
|
+
}
|
|
4539
|
+
},
|
|
4540
|
+
{
|
|
4541
|
+
id: spreadsheetCommandCatalog.redo.id,
|
|
4542
|
+
label: spreadsheetCommandCatalog.redo.label,
|
|
4543
|
+
icon: /*#__PURE__*/ jsx(Redo2, {
|
|
4544
|
+
size: 15
|
|
4545
|
+
}),
|
|
4546
|
+
shortcut: spreadsheetCommandCatalog.redo.shortcut.label,
|
|
4547
|
+
ariaKeyShortcuts: spreadsheetCommandCatalog.redo.shortcut.aria,
|
|
4548
|
+
disabled: !can.redo(),
|
|
4549
|
+
onSelect: ()=>{
|
|
4550
|
+
commands.redo();
|
|
4551
|
+
}
|
|
4552
|
+
}
|
|
4553
|
+
],
|
|
3468
4554
|
className: "work-spreadsheet-ribbon",
|
|
3469
4555
|
toolbarClassName: "work-spreadsheet-ribbon-toolbar",
|
|
3470
4556
|
panels: {
|
|
3471
4557
|
home: /*#__PURE__*/ jsxs(Fragment, {
|
|
3472
4558
|
children: [
|
|
3473
4559
|
/*#__PURE__*/ jsxs(WorkOfficeRibbonGroup, {
|
|
3474
|
-
label: "
|
|
4560
|
+
label: "剪贴板",
|
|
4561
|
+
priority: "high",
|
|
3475
4562
|
children: [
|
|
3476
4563
|
/*#__PURE__*/ jsx(WorkOfficeRibbonButton, {
|
|
3477
|
-
label:
|
|
3478
|
-
title:
|
|
3479
|
-
"aria-keyshortcuts":
|
|
3480
|
-
disabled: !can.
|
|
3481
|
-
onClick: commands.
|
|
3482
|
-
children: /*#__PURE__*/ jsx(
|
|
4564
|
+
label: spreadsheetCommandCatalog.paste.label,
|
|
4565
|
+
title: `${spreadsheetCommandCatalog.paste.label}(${spreadsheetCommandCatalog.paste.shortcut.label})`,
|
|
4566
|
+
"aria-keyshortcuts": spreadsheetCommandCatalog.paste.shortcut.aria,
|
|
4567
|
+
disabled: !can.pasteSelection(),
|
|
4568
|
+
onClick: commands.pasteSelection,
|
|
4569
|
+
children: /*#__PURE__*/ jsx(ClipboardPaste, {
|
|
4570
|
+
size: 19
|
|
4571
|
+
})
|
|
4572
|
+
}),
|
|
4573
|
+
/*#__PURE__*/ jsx(WorkOfficeRibbonButton, {
|
|
4574
|
+
label: spreadsheetCommandCatalog.cut.label,
|
|
4575
|
+
title: `${spreadsheetCommandCatalog.cut.label}(${spreadsheetCommandCatalog.cut.shortcut.label})`,
|
|
4576
|
+
"aria-keyshortcuts": spreadsheetCommandCatalog.cut.shortcut.aria,
|
|
4577
|
+
disabled: !can.cutSelection(),
|
|
4578
|
+
onClick: commands.cutSelection,
|
|
4579
|
+
children: /*#__PURE__*/ jsx(Scissors, {
|
|
4580
|
+
size: 19
|
|
4581
|
+
})
|
|
4582
|
+
}),
|
|
4583
|
+
/*#__PURE__*/ jsx(WorkOfficeRibbonButton, {
|
|
4584
|
+
label: spreadsheetCommandCatalog.copy.label,
|
|
4585
|
+
title: `${spreadsheetCommandCatalog.copy.label}(${spreadsheetCommandCatalog.copy.shortcut.label})`,
|
|
4586
|
+
"aria-keyshortcuts": spreadsheetCommandCatalog.copy.shortcut.aria,
|
|
4587
|
+
disabled: !can.copySelection(),
|
|
4588
|
+
onClick: commands.copySelection,
|
|
4589
|
+
children: /*#__PURE__*/ jsx(Copy, {
|
|
3483
4590
|
size: 19
|
|
3484
4591
|
})
|
|
3485
4592
|
}),
|
|
3486
4593
|
/*#__PURE__*/ jsx(WorkOfficeRibbonButton, {
|
|
3487
|
-
label:
|
|
3488
|
-
title:
|
|
3489
|
-
|
|
3490
|
-
|
|
3491
|
-
|
|
3492
|
-
|
|
4594
|
+
label: spreadsheetCommandCatalog.formatPainter.label,
|
|
4595
|
+
title: spreadsheetFormatPainterTitle(formatPainterMode),
|
|
4596
|
+
active: null !== formatPainterMode,
|
|
4597
|
+
badge: 'locked' === formatPainterMode ? '连续' : void 0,
|
|
4598
|
+
disabled: null === formatPainterMode ? !can.activateFormatPainter('once') : !can.cancelFormatPainter(),
|
|
4599
|
+
onClick: (event)=>{
|
|
4600
|
+
if (event.detail > 1) return;
|
|
4601
|
+
if (null === formatPainterMode) commands.activateFormatPainter('once');
|
|
4602
|
+
else commands.cancelFormatPainter();
|
|
4603
|
+
},
|
|
4604
|
+
onDoubleClick: ()=>commands.activateFormatPainter('locked'),
|
|
4605
|
+
children: /*#__PURE__*/ jsx(Paintbrush, {
|
|
3493
4606
|
size: 19
|
|
3494
4607
|
})
|
|
3495
4608
|
})
|
|
@@ -3497,6 +4610,7 @@ function SpreadsheetEditorRibbon({ activeTab, can, commands, content, fileAction
|
|
|
3497
4610
|
}),
|
|
3498
4611
|
/*#__PURE__*/ jsxs(WorkOfficeRibbonGroup, {
|
|
3499
4612
|
label: "字体",
|
|
4613
|
+
priority: "high",
|
|
3500
4614
|
children: [
|
|
3501
4615
|
/*#__PURE__*/ jsx(OfficeSelect, {
|
|
3502
4616
|
className: "work-spreadsheet-font-family",
|
|
@@ -3514,9 +4628,9 @@ function SpreadsheetEditorRibbon({ activeTab, can, commands, content, fileAction
|
|
|
3514
4628
|
onValueChange: (value)=>commands.setCellFormat('fs', Number(value))
|
|
3515
4629
|
}),
|
|
3516
4630
|
/*#__PURE__*/ jsx(WorkOfficeRibbonButton, {
|
|
3517
|
-
label:
|
|
3518
|
-
title:
|
|
3519
|
-
"aria-keyshortcuts":
|
|
4631
|
+
label: spreadsheetCommandCatalog.bold.label,
|
|
4632
|
+
title: `${spreadsheetCommandCatalog.bold.label}(${spreadsheetCommandCatalog.bold.shortcut.label})`,
|
|
4633
|
+
"aria-keyshortcuts": spreadsheetCommandCatalog.bold.shortcut.aria,
|
|
3520
4634
|
displayLabel: false,
|
|
3521
4635
|
active: 1 === Number(toolbarCell?.bl),
|
|
3522
4636
|
disabled: !can.setCellFormat('bl', 1 === Number(toolbarCell?.bl) ? 0 : 1),
|
|
@@ -3526,9 +4640,9 @@ function SpreadsheetEditorRibbon({ activeTab, can, commands, content, fileAction
|
|
|
3526
4640
|
})
|
|
3527
4641
|
}),
|
|
3528
4642
|
/*#__PURE__*/ jsx(WorkOfficeRibbonButton, {
|
|
3529
|
-
label:
|
|
3530
|
-
title:
|
|
3531
|
-
"aria-keyshortcuts":
|
|
4643
|
+
label: spreadsheetCommandCatalog.italic.label,
|
|
4644
|
+
title: `${spreadsheetCommandCatalog.italic.label}(${spreadsheetCommandCatalog.italic.shortcut.label})`,
|
|
4645
|
+
"aria-keyshortcuts": spreadsheetCommandCatalog.italic.shortcut.aria,
|
|
3532
4646
|
displayLabel: false,
|
|
3533
4647
|
active: 1 === Number(toolbarCell?.it),
|
|
3534
4648
|
disabled: !can.setCellFormat('it', 1 === Number(toolbarCell?.it) ? 0 : 1),
|
|
@@ -3538,9 +4652,9 @@ function SpreadsheetEditorRibbon({ activeTab, can, commands, content, fileAction
|
|
|
3538
4652
|
})
|
|
3539
4653
|
}),
|
|
3540
4654
|
/*#__PURE__*/ jsx(WorkOfficeRibbonButton, {
|
|
3541
|
-
label:
|
|
3542
|
-
title:
|
|
3543
|
-
"aria-keyshortcuts":
|
|
4655
|
+
label: spreadsheetCommandCatalog.underline.label,
|
|
4656
|
+
title: `${spreadsheetCommandCatalog.underline.label}(${spreadsheetCommandCatalog.underline.shortcut.label})`,
|
|
4657
|
+
"aria-keyshortcuts": spreadsheetCommandCatalog.underline.shortcut.aria,
|
|
3544
4658
|
displayLabel: false,
|
|
3545
4659
|
active: 1 === Number(toolbarCell?.un),
|
|
3546
4660
|
disabled: !can.setCellFormat('un', 1 === Number(toolbarCell?.un) ? 0 : 1),
|
|
@@ -3569,6 +4683,7 @@ function SpreadsheetEditorRibbon({ activeTab, can, commands, content, fileAction
|
|
|
3569
4683
|
}),
|
|
3570
4684
|
/*#__PURE__*/ jsxs(WorkOfficeRibbonGroup, {
|
|
3571
4685
|
label: "对齐",
|
|
4686
|
+
priority: "high",
|
|
3572
4687
|
children: [
|
|
3573
4688
|
/*#__PURE__*/ jsx(WorkOfficeRibbonButton, {
|
|
3574
4689
|
label: "左对齐",
|
|
@@ -3639,11 +4754,16 @@ function SpreadsheetEditorRibbon({ activeTab, can, commands, content, fileAction
|
|
|
3639
4754
|
children: /*#__PURE__*/ jsx(WrapText, {
|
|
3640
4755
|
size: 15
|
|
3641
4756
|
})
|
|
4757
|
+
}),
|
|
4758
|
+
/*#__PURE__*/ jsx(SpreadsheetMergeMenu, {
|
|
4759
|
+
can: can,
|
|
4760
|
+
commands: commands
|
|
3642
4761
|
})
|
|
3643
4762
|
]
|
|
3644
4763
|
}),
|
|
3645
4764
|
/*#__PURE__*/ jsxs(WorkOfficeRibbonGroup, {
|
|
3646
4765
|
label: "数字",
|
|
4766
|
+
priority: "high",
|
|
3647
4767
|
children: [
|
|
3648
4768
|
/*#__PURE__*/ jsx(OfficeSelect, {
|
|
3649
4769
|
className: "work-spreadsheet-number-format",
|
|
@@ -3689,54 +4809,12 @@ function SpreadsheetEditorRibbon({ activeTab, can, commands, content, fileAction
|
|
|
3689
4809
|
})
|
|
3690
4810
|
]
|
|
3691
4811
|
}),
|
|
3692
|
-
/*#__PURE__*/ jsx(WorkOfficeRibbonGroup, {
|
|
3693
|
-
label: "单元格",
|
|
3694
|
-
children: /*#__PURE__*/ jsx(WorkOfficeRibbonButton, {
|
|
3695
|
-
label: toolbarCell?.mc ? '取消合并' : '合并单元格',
|
|
3696
|
-
disabled: !can.toggleCellMerge(Boolean(toolbarCell?.mc)) || !toolbarCell?.mc && !multipleCellsSelected,
|
|
3697
|
-
onClick: ()=>commands.toggleCellMerge(Boolean(toolbarCell?.mc)),
|
|
3698
|
-
children: /*#__PURE__*/ jsx(Merge, {
|
|
3699
|
-
size: 19
|
|
3700
|
-
})
|
|
3701
|
-
})
|
|
3702
|
-
}),
|
|
3703
|
-
/*#__PURE__*/ jsx(WorkOfficeRibbonGroup, {
|
|
3704
|
-
label: "编辑",
|
|
3705
|
-
children: /*#__PURE__*/ jsx(WorkOfficeRibbonButton, {
|
|
3706
|
-
label: "查找",
|
|
3707
|
-
title: "查找(Cmd/Ctrl+F)",
|
|
3708
|
-
"aria-keyshortcuts": "Control+F Meta+F",
|
|
3709
|
-
active: findOpen,
|
|
3710
|
-
onClick: onOpenFind,
|
|
3711
|
-
children: /*#__PURE__*/ jsx(Search, {
|
|
3712
|
-
size: 19
|
|
3713
|
-
})
|
|
3714
|
-
})
|
|
3715
|
-
})
|
|
3716
|
-
]
|
|
3717
|
-
}),
|
|
3718
|
-
insert: /*#__PURE__*/ jsxs(Fragment, {
|
|
3719
|
-
children: [
|
|
3720
|
-
/*#__PURE__*/ jsx(WorkOfficeRibbonGroup, {
|
|
3721
|
-
label: "图表",
|
|
3722
|
-
children: /*#__PURE__*/ jsx(SpreadsheetRibbonTool, {
|
|
3723
|
-
controlsId: panelId,
|
|
3724
|
-
panel: "charts",
|
|
3725
|
-
label: "插入图表",
|
|
3726
|
-
count: spreadsheetChartCount(content),
|
|
3727
|
-
icon: /*#__PURE__*/ jsx(BarChart3, {
|
|
3728
|
-
size: 19
|
|
3729
|
-
}),
|
|
3730
|
-
active: 'charts' === panel,
|
|
3731
|
-
onToggle: onTogglePanel
|
|
3732
|
-
})
|
|
3733
|
-
}),
|
|
3734
4812
|
/*#__PURE__*/ jsx(WorkOfficeRibbonGroup, {
|
|
3735
4813
|
label: "样式",
|
|
3736
4814
|
children: /*#__PURE__*/ jsx(SpreadsheetRibbonTool, {
|
|
3737
4815
|
controlsId: panelId,
|
|
3738
4816
|
panel: "conditional-formatting",
|
|
3739
|
-
label:
|
|
4817
|
+
label: spreadsheetCommandCatalog.conditionalFormatting.label,
|
|
3740
4818
|
count: managedConditionalFormatCount(content),
|
|
3741
4819
|
icon: /*#__PURE__*/ jsx(Palette, {
|
|
3742
4820
|
size: 19
|
|
@@ -3744,16 +4822,59 @@ function SpreadsheetEditorRibbon({ activeTab, can, commands, content, fileAction
|
|
|
3744
4822
|
active: 'conditional-formatting' === panel,
|
|
3745
4823
|
onToggle: onTogglePanel
|
|
3746
4824
|
})
|
|
4825
|
+
}),
|
|
4826
|
+
/*#__PURE__*/ jsx(WorkOfficeRibbonGroup, {
|
|
4827
|
+
label: "单元格",
|
|
4828
|
+
children: /*#__PURE__*/ jsx(SpreadsheetRowsAndColumnsMenu, {
|
|
4829
|
+
can: can,
|
|
4830
|
+
commands: commands
|
|
4831
|
+
})
|
|
4832
|
+
}),
|
|
4833
|
+
/*#__PURE__*/ jsxs(WorkOfficeRibbonGroup, {
|
|
4834
|
+
label: "编辑",
|
|
4835
|
+
priority: "low",
|
|
4836
|
+
children: [
|
|
4837
|
+
/*#__PURE__*/ jsx(SpreadsheetClearMenu, {
|
|
4838
|
+
can: can,
|
|
4839
|
+
commands: commands
|
|
4840
|
+
}),
|
|
4841
|
+
/*#__PURE__*/ jsx(WorkOfficeRibbonButton, {
|
|
4842
|
+
label: spreadsheetCommandCatalog.find.label,
|
|
4843
|
+
title: `${spreadsheetCommandCatalog.find.label}(${spreadsheetCommandCatalog.find.shortcut.label})`,
|
|
4844
|
+
"aria-keyshortcuts": spreadsheetCommandCatalog.find.shortcut.aria,
|
|
4845
|
+
active: findOpen,
|
|
4846
|
+
onClick: onOpenFind,
|
|
4847
|
+
children: /*#__PURE__*/ jsx(Search, {
|
|
4848
|
+
size: 19
|
|
4849
|
+
})
|
|
4850
|
+
})
|
|
4851
|
+
]
|
|
3747
4852
|
})
|
|
3748
4853
|
]
|
|
3749
4854
|
}),
|
|
3750
|
-
|
|
3751
|
-
label: "
|
|
4855
|
+
insert: /*#__PURE__*/ jsx(WorkOfficeRibbonGroup, {
|
|
4856
|
+
label: "图表",
|
|
4857
|
+
priority: "high",
|
|
3752
4858
|
children: /*#__PURE__*/ jsx(SpreadsheetRibbonTool, {
|
|
3753
4859
|
controlsId: panelId,
|
|
3754
|
-
panel: "
|
|
3755
|
-
label:
|
|
3756
|
-
count:
|
|
4860
|
+
panel: "charts",
|
|
4861
|
+
label: spreadsheetCommandCatalog.insertChart.label,
|
|
4862
|
+
count: spreadsheetChartCount(content),
|
|
4863
|
+
icon: /*#__PURE__*/ jsx(BarChart3, {
|
|
4864
|
+
size: 19
|
|
4865
|
+
}),
|
|
4866
|
+
active: 'charts' === panel,
|
|
4867
|
+
onToggle: onTogglePanel
|
|
4868
|
+
})
|
|
4869
|
+
}),
|
|
4870
|
+
pageLayout: /*#__PURE__*/ jsx(WorkOfficeRibbonGroup, {
|
|
4871
|
+
label: "页面设置",
|
|
4872
|
+
priority: "high",
|
|
4873
|
+
children: /*#__PURE__*/ jsx(SpreadsheetRibbonTool, {
|
|
4874
|
+
controlsId: panelId,
|
|
4875
|
+
panel: "print-area",
|
|
4876
|
+
label: spreadsheetCommandCatalog.printSettings.label,
|
|
4877
|
+
count: spreadsheetPrintSettingCount(content),
|
|
3757
4878
|
icon: /*#__PURE__*/ jsx(Printer, {
|
|
3758
4879
|
size: 19
|
|
3759
4880
|
}),
|
|
@@ -3765,10 +4886,11 @@ function SpreadsheetEditorRibbon({ activeTab, can, commands, content, fileAction
|
|
|
3765
4886
|
children: [
|
|
3766
4887
|
/*#__PURE__*/ jsx(WorkOfficeRibbonGroup, {
|
|
3767
4888
|
label: "定义的名称",
|
|
4889
|
+
priority: "high",
|
|
3768
4890
|
children: /*#__PURE__*/ jsx(SpreadsheetRibbonTool, {
|
|
3769
4891
|
controlsId: panelId,
|
|
3770
4892
|
panel: "names",
|
|
3771
|
-
label:
|
|
4893
|
+
label: spreadsheetCommandCatalog.nameManager.label,
|
|
3772
4894
|
count: content.namedRanges?.length ?? 0,
|
|
3773
4895
|
icon: /*#__PURE__*/ jsx(Bookmark, {
|
|
3774
4896
|
size: 19
|
|
@@ -3777,42 +4899,93 @@ function SpreadsheetEditorRibbon({ activeTab, can, commands, content, fileAction
|
|
|
3777
4899
|
onToggle: onTogglePanel
|
|
3778
4900
|
})
|
|
3779
4901
|
}),
|
|
3780
|
-
/*#__PURE__*/
|
|
4902
|
+
/*#__PURE__*/ jsxs(WorkOfficeRibbonGroup, {
|
|
3781
4903
|
label: "计算",
|
|
4904
|
+
priority: "high",
|
|
4905
|
+
children: [
|
|
4906
|
+
/*#__PURE__*/ jsx(SpreadsheetRibbonTool, {
|
|
4907
|
+
controlsId: panelId,
|
|
4908
|
+
panel: "formulas",
|
|
4909
|
+
label: spreadsheetCommandCatalog.formulaManager.label,
|
|
4910
|
+
count: formulaCount,
|
|
4911
|
+
icon: /*#__PURE__*/ jsx(Calculator, {
|
|
4912
|
+
size: 19
|
|
4913
|
+
}),
|
|
4914
|
+
active: 'formulas' === panel,
|
|
4915
|
+
onToggle: onTogglePanel
|
|
4916
|
+
}),
|
|
4917
|
+
/*#__PURE__*/ jsx(WorkOfficeRibbonButton, {
|
|
4918
|
+
label: spreadsheetCommandCatalog.recalculateWorkbook.label,
|
|
4919
|
+
title: `${spreadsheetCommandCatalog.recalculateWorkbook.label}(${spreadsheetCommandCatalog.recalculateWorkbook.shortcut.label})`,
|
|
4920
|
+
"aria-keyshortcuts": spreadsheetCommandCatalog.recalculateWorkbook.shortcut.aria,
|
|
4921
|
+
disabled: !can.recalculateFormula('workbook'),
|
|
4922
|
+
onClick: ()=>commands.recalculateFormula('workbook'),
|
|
4923
|
+
children: /*#__PURE__*/ jsx(RefreshCw, {
|
|
4924
|
+
size: 19
|
|
4925
|
+
})
|
|
4926
|
+
})
|
|
4927
|
+
]
|
|
4928
|
+
})
|
|
4929
|
+
]
|
|
4930
|
+
}),
|
|
4931
|
+
data: /*#__PURE__*/ jsxs(Fragment, {
|
|
4932
|
+
children: [
|
|
4933
|
+
/*#__PURE__*/ jsxs(WorkOfficeRibbonGroup, {
|
|
4934
|
+
label: "排序和筛选",
|
|
4935
|
+
priority: "high",
|
|
4936
|
+
children: [
|
|
4937
|
+
/*#__PURE__*/ jsx(WorkOfficeRibbonButton, {
|
|
4938
|
+
label: spreadsheetCommandCatalog.sortAscending.label,
|
|
4939
|
+
disabled: !can.sortSelectedCells('ascending'),
|
|
4940
|
+
onClick: ()=>commands.sortSelectedCells('ascending'),
|
|
4941
|
+
children: /*#__PURE__*/ jsx(SortAsc, {
|
|
4942
|
+
size: 19
|
|
4943
|
+
})
|
|
4944
|
+
}),
|
|
4945
|
+
/*#__PURE__*/ jsx(WorkOfficeRibbonButton, {
|
|
4946
|
+
label: spreadsheetCommandCatalog.sortDescending.label,
|
|
4947
|
+
disabled: !can.sortSelectedCells('descending'),
|
|
4948
|
+
onClick: ()=>commands.sortSelectedCells('descending'),
|
|
4949
|
+
children: /*#__PURE__*/ jsx(SortDesc, {
|
|
4950
|
+
size: 19
|
|
4951
|
+
})
|
|
4952
|
+
}),
|
|
4953
|
+
/*#__PURE__*/ jsx(WorkOfficeRibbonButton, {
|
|
4954
|
+
label: spreadsheetCommandCatalog.autoFilter.label,
|
|
4955
|
+
title: `${spreadsheetCommandCatalog.autoFilter.label}(${spreadsheetCommandCatalog.autoFilter.shortcut.label});表头菜单(${spreadsheetCommandCatalog.autoFilter.menuShortcut.label})`,
|
|
4956
|
+
"aria-keyshortcuts": spreadsheetCommandCatalog.autoFilter.shortcut.aria,
|
|
4957
|
+
active: autoFilterActive,
|
|
4958
|
+
disabled: !can.toggleAutoFilter(),
|
|
4959
|
+
onClick: ()=>commands.toggleAutoFilter(),
|
|
4960
|
+
children: /*#__PURE__*/ jsx(ListFilter, {
|
|
4961
|
+
size: 19
|
|
4962
|
+
})
|
|
4963
|
+
})
|
|
4964
|
+
]
|
|
4965
|
+
}),
|
|
4966
|
+
/*#__PURE__*/ jsx(WorkOfficeRibbonGroup, {
|
|
4967
|
+
label: "分析",
|
|
3782
4968
|
children: /*#__PURE__*/ jsx(SpreadsheetRibbonTool, {
|
|
3783
4969
|
controlsId: panelId,
|
|
3784
|
-
panel: "
|
|
3785
|
-
label:
|
|
3786
|
-
count:
|
|
3787
|
-
icon: /*#__PURE__*/ jsx(
|
|
4970
|
+
panel: "pivots",
|
|
4971
|
+
label: spreadsheetCommandCatalog.pivotTable.label,
|
|
4972
|
+
count: pivotCount,
|
|
4973
|
+
icon: /*#__PURE__*/ jsx(TableProperties, {
|
|
3788
4974
|
size: 19
|
|
3789
4975
|
}),
|
|
3790
|
-
active: '
|
|
4976
|
+
active: 'pivots' === panel,
|
|
3791
4977
|
onToggle: onTogglePanel
|
|
3792
4978
|
})
|
|
3793
4979
|
})
|
|
3794
4980
|
]
|
|
3795
4981
|
}),
|
|
3796
|
-
data: /*#__PURE__*/ jsx(WorkOfficeRibbonGroup, {
|
|
3797
|
-
label: "分析",
|
|
3798
|
-
children: /*#__PURE__*/ jsx(SpreadsheetRibbonTool, {
|
|
3799
|
-
controlsId: panelId,
|
|
3800
|
-
panel: "pivots",
|
|
3801
|
-
label: "数据透视表",
|
|
3802
|
-
count: pivotCount,
|
|
3803
|
-
icon: /*#__PURE__*/ jsx(TableProperties, {
|
|
3804
|
-
size: 19
|
|
3805
|
-
}),
|
|
3806
|
-
active: 'pivots' === panel,
|
|
3807
|
-
onToggle: onTogglePanel
|
|
3808
|
-
})
|
|
3809
|
-
}),
|
|
3810
4982
|
review: /*#__PURE__*/ jsx(WorkOfficeRibbonGroup, {
|
|
3811
4983
|
label: "保护",
|
|
4984
|
+
priority: "high",
|
|
3812
4985
|
children: /*#__PURE__*/ jsx(SpreadsheetRibbonTool, {
|
|
3813
4986
|
controlsId: panelId,
|
|
3814
4987
|
panel: "protection",
|
|
3815
|
-
label:
|
|
4988
|
+
label: spreadsheetCommandCatalog.protectSheet.label,
|
|
3816
4989
|
count: protectedSheetCount(content.sheets),
|
|
3817
4990
|
icon: /*#__PURE__*/ jsx(ShieldCheck, {
|
|
3818
4991
|
size: 19
|
|
@@ -3821,22 +4994,422 @@ function SpreadsheetEditorRibbon({ activeTab, can, commands, content, fileAction
|
|
|
3821
4994
|
onToggle: onTogglePanel
|
|
3822
4995
|
})
|
|
3823
4996
|
}),
|
|
3824
|
-
view: /*#__PURE__*/
|
|
3825
|
-
|
|
3826
|
-
|
|
3827
|
-
|
|
3828
|
-
|
|
3829
|
-
|
|
3830
|
-
|
|
3831
|
-
|
|
3832
|
-
|
|
3833
|
-
|
|
4997
|
+
view: /*#__PURE__*/ jsxs(Fragment, {
|
|
4998
|
+
children: [
|
|
4999
|
+
/*#__PURE__*/ jsx(WorkOfficeRibbonGroup, {
|
|
5000
|
+
label: "工作簿视图",
|
|
5001
|
+
priority: "high",
|
|
5002
|
+
children: /*#__PURE__*/ jsx(WorkOfficeRibbonButton, {
|
|
5003
|
+
label: gridLinesVisible ? '隐藏网格线' : '显示网格线',
|
|
5004
|
+
visibleLabel: spreadsheetCommandCatalog.gridLines.label,
|
|
5005
|
+
active: gridLinesVisible,
|
|
5006
|
+
disabled: !can.setGridLines(!gridLinesVisible),
|
|
5007
|
+
onClick: ()=>commands.setGridLines(!gridLinesVisible),
|
|
5008
|
+
children: /*#__PURE__*/ jsx(Grid3X3, {
|
|
5009
|
+
size: 19
|
|
5010
|
+
})
|
|
5011
|
+
})
|
|
5012
|
+
}),
|
|
5013
|
+
/*#__PURE__*/ jsx(WorkOfficeRibbonGroup, {
|
|
5014
|
+
label: "窗口",
|
|
5015
|
+
priority: "high",
|
|
5016
|
+
children: /*#__PURE__*/ jsx(SpreadsheetFreezePanesMenu, {
|
|
5017
|
+
active: freezePanesActive,
|
|
5018
|
+
can: can,
|
|
5019
|
+
commands: commands,
|
|
5020
|
+
selection: freezePanesSelection
|
|
5021
|
+
})
|
|
3834
5022
|
})
|
|
5023
|
+
]
|
|
5024
|
+
})
|
|
5025
|
+
}
|
|
5026
|
+
});
|
|
5027
|
+
}
|
|
5028
|
+
function SpreadsheetMergeMenu({ can, commands }) {
|
|
5029
|
+
const items = [
|
|
5030
|
+
{
|
|
5031
|
+
command: 'merge-and-center',
|
|
5032
|
+
id: spreadsheetCommandCatalog.mergeAndCenter.id,
|
|
5033
|
+
label: spreadsheetCommandCatalog.mergeAndCenter.label,
|
|
5034
|
+
icon: /*#__PURE__*/ jsx(Merge, {
|
|
5035
|
+
size: 16
|
|
5036
|
+
})
|
|
5037
|
+
},
|
|
5038
|
+
{
|
|
5039
|
+
command: 'merge-cells',
|
|
5040
|
+
id: spreadsheetCommandCatalog.mergeCells.id,
|
|
5041
|
+
label: spreadsheetCommandCatalog.mergeCells.label,
|
|
5042
|
+
icon: /*#__PURE__*/ jsx(Grid3X3, {
|
|
5043
|
+
size: 16
|
|
5044
|
+
})
|
|
5045
|
+
},
|
|
5046
|
+
{
|
|
5047
|
+
command: 'merge-across',
|
|
5048
|
+
id: spreadsheetCommandCatalog.mergeAcross.id,
|
|
5049
|
+
label: spreadsheetCommandCatalog.mergeAcross.label,
|
|
5050
|
+
icon: /*#__PURE__*/ jsx(Rows3, {
|
|
5051
|
+
size: 16
|
|
5052
|
+
})
|
|
5053
|
+
},
|
|
5054
|
+
{
|
|
5055
|
+
command: 'unmerge-cells',
|
|
5056
|
+
id: spreadsheetCommandCatalog.unmergeCells.id,
|
|
5057
|
+
label: spreadsheetCommandCatalog.unmergeCells.label,
|
|
5058
|
+
icon: /*#__PURE__*/ jsx(X, {
|
|
5059
|
+
size: 16
|
|
5060
|
+
})
|
|
5061
|
+
},
|
|
5062
|
+
{
|
|
5063
|
+
command: 'unmerge-and-fill',
|
|
5064
|
+
id: spreadsheetCommandCatalog.unmergeAndFill.id,
|
|
5065
|
+
label: spreadsheetCommandCatalog.unmergeAndFill.label,
|
|
5066
|
+
icon: /*#__PURE__*/ jsx(Grid3X3, {
|
|
5067
|
+
size: 16
|
|
5068
|
+
})
|
|
5069
|
+
}
|
|
5070
|
+
];
|
|
5071
|
+
const primaryDisabled = !can.mergeSelectedCells('merge-and-center');
|
|
5072
|
+
const menuDisabled = items.every(({ command })=>false === can.mergeSelectedCells(command));
|
|
5073
|
+
return /*#__PURE__*/ jsx(Popover, {
|
|
5074
|
+
label: "更多合并方式",
|
|
5075
|
+
panelLabel: "合并选项",
|
|
5076
|
+
panelRole: "menu",
|
|
5077
|
+
portal: true,
|
|
5078
|
+
className: "work-spreadsheet-ribbon-split-root",
|
|
5079
|
+
panelClassName: "work-office-context-menu work-spreadsheet-ribbon-menu",
|
|
5080
|
+
disabled: menuDisabled,
|
|
5081
|
+
focusFirstOnOpen: true,
|
|
5082
|
+
onPanelKeyDown: moveOfficeMenuFocus,
|
|
5083
|
+
trigger: (triggerProps, { open })=>/*#__PURE__*/ jsxs(Fragment, {
|
|
5084
|
+
children: [
|
|
5085
|
+
/*#__PURE__*/ jsxs("button", {
|
|
5086
|
+
type: "button",
|
|
5087
|
+
className: "with-label work-spreadsheet-ribbon-split-primary",
|
|
5088
|
+
"aria-label": spreadsheetCommandCatalog.mergeAndCenter.label,
|
|
5089
|
+
"aria-keyshortcuts": spreadsheetCommandCatalog.mergeAndCenter.shortcut.aria,
|
|
5090
|
+
title: `${spreadsheetCommandCatalog.mergeAndCenter.label}(${spreadsheetCommandCatalog.mergeAndCenter.shortcut.label})`,
|
|
5091
|
+
disabled: primaryDisabled,
|
|
5092
|
+
onClick: ()=>commands.mergeSelectedCells('merge-and-center'),
|
|
5093
|
+
children: [
|
|
5094
|
+
/*#__PURE__*/ jsx(Merge, {
|
|
5095
|
+
size: 19
|
|
5096
|
+
}),
|
|
5097
|
+
/*#__PURE__*/ jsx("span", {
|
|
5098
|
+
children: spreadsheetCommandCatalog.mergeAndCenter.label
|
|
5099
|
+
})
|
|
5100
|
+
]
|
|
5101
|
+
}),
|
|
5102
|
+
/*#__PURE__*/ jsx("button", {
|
|
5103
|
+
...triggerProps,
|
|
5104
|
+
className: `work-spreadsheet-ribbon-split-disclosure${open ? ' active' : ''}`,
|
|
5105
|
+
title: "更多合并方式",
|
|
5106
|
+
children: /*#__PURE__*/ jsx(ChevronDown, {
|
|
5107
|
+
size: 13,
|
|
5108
|
+
"aria-hidden": "true"
|
|
5109
|
+
})
|
|
5110
|
+
})
|
|
5111
|
+
]
|
|
5112
|
+
}),
|
|
5113
|
+
children: (close)=>items.map(({ command, id, label, icon })=>/*#__PURE__*/ jsxs("button", {
|
|
5114
|
+
type: "button",
|
|
5115
|
+
role: "menuitem",
|
|
5116
|
+
tabIndex: -1,
|
|
5117
|
+
"aria-keyshortcuts": 'merge-and-center' === command ? spreadsheetCommandCatalog.mergeAndCenter.shortcut.aria : void 0,
|
|
5118
|
+
disabled: !can.mergeSelectedCells(command),
|
|
5119
|
+
onClick: ()=>{
|
|
5120
|
+
close();
|
|
5121
|
+
commands.mergeSelectedCells(command);
|
|
5122
|
+
},
|
|
5123
|
+
children: [
|
|
5124
|
+
/*#__PURE__*/ jsx("span", {
|
|
5125
|
+
className: "work-spreadsheet-ribbon-menu-item-icon",
|
|
5126
|
+
children: icon
|
|
5127
|
+
}),
|
|
5128
|
+
/*#__PURE__*/ jsx("span", {
|
|
5129
|
+
children: label
|
|
5130
|
+
})
|
|
5131
|
+
]
|
|
5132
|
+
}, id))
|
|
5133
|
+
});
|
|
5134
|
+
}
|
|
5135
|
+
function SpreadsheetFreezePanesMenu({ active, can, commands, selection }) {
|
|
5136
|
+
const presets = [
|
|
5137
|
+
...active ? [
|
|
5138
|
+
{
|
|
5139
|
+
preset: 'none',
|
|
5140
|
+
label: '取消冻结窗格',
|
|
5141
|
+
icon: /*#__PURE__*/ jsx(X, {
|
|
5142
|
+
size: 16
|
|
3835
5143
|
})
|
|
5144
|
+
}
|
|
5145
|
+
] : [],
|
|
5146
|
+
{
|
|
5147
|
+
preset: 'selection',
|
|
5148
|
+
label: spreadsheetFreezePanesSelectionLabel(selection),
|
|
5149
|
+
icon: /*#__PURE__*/ jsx(PanelsTopLeft, {
|
|
5150
|
+
size: 16
|
|
5151
|
+
})
|
|
5152
|
+
},
|
|
5153
|
+
{
|
|
5154
|
+
preset: 'topRow',
|
|
5155
|
+
label: '冻结首行',
|
|
5156
|
+
icon: /*#__PURE__*/ jsx(PanelTop, {
|
|
5157
|
+
size: 16
|
|
5158
|
+
})
|
|
5159
|
+
},
|
|
5160
|
+
{
|
|
5161
|
+
preset: 'firstColumn',
|
|
5162
|
+
label: '冻结首列',
|
|
5163
|
+
icon: /*#__PURE__*/ jsx(PanelLeft, {
|
|
5164
|
+
size: 16
|
|
5165
|
+
})
|
|
5166
|
+
}
|
|
5167
|
+
];
|
|
5168
|
+
const disabled = !presets.some(({ preset })=>can.setFreezePanes(preset));
|
|
5169
|
+
return /*#__PURE__*/ jsx(Popover, {
|
|
5170
|
+
label: spreadsheetCommandCatalog.freezePanes.label,
|
|
5171
|
+
panelLabel: "冻结窗格选项",
|
|
5172
|
+
panelRole: "menu",
|
|
5173
|
+
portal: true,
|
|
5174
|
+
className: "work-spreadsheet-ribbon-menu-root",
|
|
5175
|
+
panelClassName: "work-office-context-menu work-spreadsheet-ribbon-menu",
|
|
5176
|
+
disabled: disabled,
|
|
5177
|
+
focusFirstOnOpen: true,
|
|
5178
|
+
onPanelKeyDown: moveOfficeMenuFocus,
|
|
5179
|
+
trigger: (triggerProps, { open })=>/*#__PURE__*/ jsxs("button", {
|
|
5180
|
+
...triggerProps,
|
|
5181
|
+
className: `with-label work-spreadsheet-ribbon-menu-trigger${active || open ? ' active' : ''}`,
|
|
5182
|
+
"aria-pressed": active,
|
|
5183
|
+
title: active ? '冻结窗格(已启用)' : '冻结窗格',
|
|
5184
|
+
children: [
|
|
5185
|
+
/*#__PURE__*/ jsx(PanelsTopLeft, {
|
|
5186
|
+
size: 19
|
|
5187
|
+
}),
|
|
5188
|
+
/*#__PURE__*/ jsx("span", {
|
|
5189
|
+
children: spreadsheetCommandCatalog.freezePanes.label
|
|
5190
|
+
})
|
|
5191
|
+
]
|
|
5192
|
+
}),
|
|
5193
|
+
children: (close)=>presets.map(({ preset, label, icon })=>/*#__PURE__*/ jsxs("button", {
|
|
5194
|
+
type: "button",
|
|
5195
|
+
role: "menuitem",
|
|
5196
|
+
tabIndex: -1,
|
|
5197
|
+
disabled: !can.setFreezePanes(preset),
|
|
5198
|
+
onClick: ()=>{
|
|
5199
|
+
close();
|
|
5200
|
+
commands.setFreezePanes(preset);
|
|
5201
|
+
},
|
|
5202
|
+
children: [
|
|
5203
|
+
/*#__PURE__*/ jsx("span", {
|
|
5204
|
+
className: "work-spreadsheet-ribbon-menu-item-icon",
|
|
5205
|
+
children: icon
|
|
5206
|
+
}),
|
|
5207
|
+
/*#__PURE__*/ jsx("span", {
|
|
5208
|
+
children: label
|
|
5209
|
+
})
|
|
5210
|
+
]
|
|
5211
|
+
}, preset))
|
|
5212
|
+
});
|
|
5213
|
+
}
|
|
5214
|
+
function SpreadsheetRowsAndColumnsMenu({ can, commands }) {
|
|
5215
|
+
const items = [
|
|
5216
|
+
{
|
|
5217
|
+
id: spreadsheetCommandCatalog.insertRowsAbove.id,
|
|
5218
|
+
label: spreadsheetCommandCatalog.insertRowsAbove.label,
|
|
5219
|
+
icon: /*#__PURE__*/ jsx(BetweenHorizontalStart, {
|
|
5220
|
+
size: 16
|
|
5221
|
+
}),
|
|
5222
|
+
disabled: !can.insertSelectedStructure('row', 'before'),
|
|
5223
|
+
execute: ()=>commands.insertSelectedStructure('row', 'before')
|
|
5224
|
+
},
|
|
5225
|
+
{
|
|
5226
|
+
id: spreadsheetCommandCatalog.insertRowsBelow.id,
|
|
5227
|
+
label: spreadsheetCommandCatalog.insertRowsBelow.label,
|
|
5228
|
+
icon: /*#__PURE__*/ jsx(BetweenHorizontalEnd, {
|
|
5229
|
+
size: 16
|
|
5230
|
+
}),
|
|
5231
|
+
disabled: !can.insertSelectedStructure('row', 'after'),
|
|
5232
|
+
execute: ()=>commands.insertSelectedStructure('row', 'after')
|
|
5233
|
+
},
|
|
5234
|
+
{
|
|
5235
|
+
id: spreadsheetCommandCatalog.insertColumnsLeft.id,
|
|
5236
|
+
label: spreadsheetCommandCatalog.insertColumnsLeft.label,
|
|
5237
|
+
icon: /*#__PURE__*/ jsx(BetweenVerticalStart, {
|
|
5238
|
+
size: 16
|
|
5239
|
+
}),
|
|
5240
|
+
disabled: !can.insertSelectedStructure('column', 'before'),
|
|
5241
|
+
execute: ()=>commands.insertSelectedStructure('column', 'before')
|
|
5242
|
+
},
|
|
5243
|
+
{
|
|
5244
|
+
id: spreadsheetCommandCatalog.insertColumnsRight.id,
|
|
5245
|
+
label: spreadsheetCommandCatalog.insertColumnsRight.label,
|
|
5246
|
+
icon: /*#__PURE__*/ jsx(BetweenVerticalEnd, {
|
|
5247
|
+
size: 16
|
|
5248
|
+
}),
|
|
5249
|
+
disabled: !can.insertSelectedStructure('column', 'after'),
|
|
5250
|
+
execute: ()=>commands.insertSelectedStructure('column', 'after')
|
|
5251
|
+
},
|
|
5252
|
+
{
|
|
5253
|
+
id: spreadsheetCommandCatalog.deleteRows.id,
|
|
5254
|
+
label: spreadsheetCommandCatalog.deleteRows.label,
|
|
5255
|
+
icon: /*#__PURE__*/ jsx(Rows3, {
|
|
5256
|
+
size: 16
|
|
5257
|
+
}),
|
|
5258
|
+
danger: true,
|
|
5259
|
+
disabled: !can.deleteSelectedStructure('row'),
|
|
5260
|
+
execute: ()=>commands.deleteSelectedStructure('row')
|
|
5261
|
+
},
|
|
5262
|
+
{
|
|
5263
|
+
id: spreadsheetCommandCatalog.deleteColumns.id,
|
|
5264
|
+
label: spreadsheetCommandCatalog.deleteColumns.label,
|
|
5265
|
+
icon: /*#__PURE__*/ jsx(Columns3, {
|
|
5266
|
+
size: 16
|
|
5267
|
+
}),
|
|
5268
|
+
danger: true,
|
|
5269
|
+
disabled: !can.deleteSelectedStructure('column'),
|
|
5270
|
+
execute: ()=>commands.deleteSelectedStructure('column')
|
|
5271
|
+
}
|
|
5272
|
+
];
|
|
5273
|
+
const disabled = items.every((item)=>item.disabled);
|
|
5274
|
+
return /*#__PURE__*/ jsx(Popover, {
|
|
5275
|
+
label: "行和列",
|
|
5276
|
+
panelLabel: "行和列选项",
|
|
5277
|
+
panelRole: "menu",
|
|
5278
|
+
portal: true,
|
|
5279
|
+
className: "work-spreadsheet-ribbon-menu-root",
|
|
5280
|
+
panelClassName: "work-office-context-menu work-spreadsheet-ribbon-menu",
|
|
5281
|
+
disabled: disabled,
|
|
5282
|
+
focusFirstOnOpen: true,
|
|
5283
|
+
onPanelKeyDown: moveOfficeMenuFocus,
|
|
5284
|
+
trigger: (triggerProps, { open })=>/*#__PURE__*/ jsxs("button", {
|
|
5285
|
+
...triggerProps,
|
|
5286
|
+
className: `with-label work-spreadsheet-ribbon-menu-trigger${open ? ' active' : ''}`,
|
|
5287
|
+
title: "行和列",
|
|
5288
|
+
children: [
|
|
5289
|
+
/*#__PURE__*/ jsx(Rows3, {
|
|
5290
|
+
size: 19
|
|
5291
|
+
}),
|
|
5292
|
+
/*#__PURE__*/ jsx("span", {
|
|
5293
|
+
children: "行和列"
|
|
5294
|
+
})
|
|
5295
|
+
]
|
|
5296
|
+
}),
|
|
5297
|
+
children: (close)=>items.map(({ id, label, icon, danger, disabled, execute })=>/*#__PURE__*/ jsxs("button", {
|
|
5298
|
+
type: "button",
|
|
5299
|
+
role: "menuitem",
|
|
5300
|
+
tabIndex: -1,
|
|
5301
|
+
className: danger ? 'danger' : void 0,
|
|
5302
|
+
disabled: disabled,
|
|
5303
|
+
onClick: ()=>{
|
|
5304
|
+
close();
|
|
5305
|
+
execute();
|
|
5306
|
+
},
|
|
5307
|
+
children: [
|
|
5308
|
+
/*#__PURE__*/ jsx("span", {
|
|
5309
|
+
className: "work-spreadsheet-ribbon-menu-item-icon",
|
|
5310
|
+
children: icon
|
|
5311
|
+
}),
|
|
5312
|
+
/*#__PURE__*/ jsx("span", {
|
|
5313
|
+
children: label
|
|
5314
|
+
})
|
|
5315
|
+
]
|
|
5316
|
+
}, id))
|
|
5317
|
+
});
|
|
5318
|
+
}
|
|
5319
|
+
function SpreadsheetClearMenu({ can, commands }) {
|
|
5320
|
+
const items = [
|
|
5321
|
+
{
|
|
5322
|
+
mode: 'all',
|
|
5323
|
+
id: spreadsheetCommandCatalog.clearAll.id,
|
|
5324
|
+
label: spreadsheetCommandCatalog.clearAll.label,
|
|
5325
|
+
icon: /*#__PURE__*/ jsx(Trash2, {
|
|
5326
|
+
size: 16
|
|
5327
|
+
})
|
|
5328
|
+
},
|
|
5329
|
+
{
|
|
5330
|
+
mode: 'formats',
|
|
5331
|
+
id: spreadsheetCommandCatalog.clearFormats.id,
|
|
5332
|
+
label: spreadsheetCommandCatalog.clearFormats.label,
|
|
5333
|
+
icon: /*#__PURE__*/ jsx(Paintbrush, {
|
|
5334
|
+
size: 16
|
|
5335
|
+
})
|
|
5336
|
+
},
|
|
5337
|
+
{
|
|
5338
|
+
mode: 'contents',
|
|
5339
|
+
id: spreadsheetCommandCatalog.clearContents.id,
|
|
5340
|
+
label: spreadsheetCommandCatalog.clearContents.label,
|
|
5341
|
+
icon: /*#__PURE__*/ jsx(FileX2, {
|
|
5342
|
+
size: 16
|
|
5343
|
+
})
|
|
5344
|
+
},
|
|
5345
|
+
{
|
|
5346
|
+
mode: 'comments',
|
|
5347
|
+
id: spreadsheetCommandCatalog.clearComments.id,
|
|
5348
|
+
label: spreadsheetCommandCatalog.clearComments.label,
|
|
5349
|
+
icon: /*#__PURE__*/ jsx(MessageSquareX, {
|
|
5350
|
+
size: 16
|
|
5351
|
+
})
|
|
5352
|
+
},
|
|
5353
|
+
{
|
|
5354
|
+
mode: 'hyperlinks',
|
|
5355
|
+
id: spreadsheetCommandCatalog.clearHyperlinks.id,
|
|
5356
|
+
label: spreadsheetCommandCatalog.clearHyperlinks.label,
|
|
5357
|
+
icon: /*#__PURE__*/ jsx(Link2Off, {
|
|
5358
|
+
size: 16
|
|
3836
5359
|
})
|
|
3837
5360
|
}
|
|
5361
|
+
];
|
|
5362
|
+
const disabled = items.every(({ mode })=>!can.clearSelectedCells(mode));
|
|
5363
|
+
return /*#__PURE__*/ jsx(Popover, {
|
|
5364
|
+
label: "清除",
|
|
5365
|
+
panelLabel: "清除选项",
|
|
5366
|
+
panelRole: "menu",
|
|
5367
|
+
portal: true,
|
|
5368
|
+
className: "work-spreadsheet-ribbon-menu-root",
|
|
5369
|
+
panelClassName: "work-office-context-menu work-spreadsheet-ribbon-menu",
|
|
5370
|
+
disabled: disabled,
|
|
5371
|
+
focusFirstOnOpen: true,
|
|
5372
|
+
onPanelKeyDown: moveOfficeMenuFocus,
|
|
5373
|
+
trigger: (triggerProps, { open })=>/*#__PURE__*/ jsxs("button", {
|
|
5374
|
+
...triggerProps,
|
|
5375
|
+
className: `with-label work-spreadsheet-ribbon-menu-trigger${open ? ' active' : ''}`,
|
|
5376
|
+
title: "清除",
|
|
5377
|
+
children: [
|
|
5378
|
+
/*#__PURE__*/ jsx(Eraser, {
|
|
5379
|
+
size: 19
|
|
5380
|
+
}),
|
|
5381
|
+
/*#__PURE__*/ jsx("span", {
|
|
5382
|
+
children: "清除"
|
|
5383
|
+
})
|
|
5384
|
+
]
|
|
5385
|
+
}),
|
|
5386
|
+
children: (close)=>items.map(({ mode, id, label, icon })=>/*#__PURE__*/ jsxs("button", {
|
|
5387
|
+
type: "button",
|
|
5388
|
+
role: "menuitem",
|
|
5389
|
+
tabIndex: -1,
|
|
5390
|
+
"aria-keyshortcuts": 'contents' === mode ? spreadsheetCommandCatalog.clearContents.shortcut.aria : void 0,
|
|
5391
|
+
disabled: !can.clearSelectedCells(mode),
|
|
5392
|
+
onClick: ()=>{
|
|
5393
|
+
close();
|
|
5394
|
+
commands.clearSelectedCells(mode);
|
|
5395
|
+
},
|
|
5396
|
+
children: [
|
|
5397
|
+
/*#__PURE__*/ jsx("span", {
|
|
5398
|
+
className: "work-spreadsheet-ribbon-menu-item-icon",
|
|
5399
|
+
children: icon
|
|
5400
|
+
}),
|
|
5401
|
+
/*#__PURE__*/ jsx("span", {
|
|
5402
|
+
children: label
|
|
5403
|
+
})
|
|
5404
|
+
]
|
|
5405
|
+
}, id))
|
|
3838
5406
|
});
|
|
3839
5407
|
}
|
|
5408
|
+
function spreadsheetFormatPainterTitle(mode) {
|
|
5409
|
+
if ('locked' === mode) return '格式刷已锁定(再次点击或按 Escape 退出)';
|
|
5410
|
+
if ('once' === mode) return '格式刷已开启(选择目标区域,按 Escape 退出)';
|
|
5411
|
+
return '格式刷(单击应用一次,双击锁定连续应用)';
|
|
5412
|
+
}
|
|
3840
5413
|
function SpreadsheetRibbonTool({ active, count, controlsId, icon, label, panel, onToggle }) {
|
|
3841
5414
|
const hasCount = count > 0;
|
|
3842
5415
|
return /*#__PURE__*/ jsx(WorkOfficeRibbonButton, {
|
|
@@ -8746,7 +10319,7 @@ function projectSpreadsheetKernelWorkbookOperations(previous, sheets, operations
|
|
|
8746
10319
|
if ('data' !== operation.path[0]) continue;
|
|
8747
10320
|
const row = operation.path[1];
|
|
8748
10321
|
const column = operation.path[2];
|
|
8749
|
-
if (!operation.id || !sheetsById.has(operation.id) || !isSpreadsheetCoordinateIndex(row,
|
|
10322
|
+
if (!operation.id || !sheetsById.has(operation.id) || !isSpreadsheetCoordinateIndex(row, OFFICE_KERNEL_SPREADSHEET_MAX_ROWS) || !isSpreadsheetCoordinateIndex(column, 16384)) return null;
|
|
8750
10323
|
const coordinate = {
|
|
8751
10324
|
sheetId: operation.id,
|
|
8752
10325
|
row,
|
|
@@ -8847,7 +10420,7 @@ function spreadsheetOperationsMayChangeCalculation(operations, workbook) {
|
|
|
8847
10420
|
if (!workbook) return operation.path.length <= 3 || isInputCellPath(operation);
|
|
8848
10421
|
const row = operation.path[1];
|
|
8849
10422
|
const column = operation.path[2];
|
|
8850
|
-
if (!operation.id || !isSpreadsheetCoordinateIndex(row,
|
|
10423
|
+
if (!operation.id || !isSpreadsheetCoordinateIndex(row, OFFICE_KERNEL_SPREADSHEET_MAX_ROWS) || !isSpreadsheetCoordinateIndex(column, 16384)) return true;
|
|
8851
10424
|
const previous = workbook.sourceState.sourceCells.get(sourceCellKey(operation.id, row, column));
|
|
8852
10425
|
if (operation.path.length <= 3) {
|
|
8853
10426
|
const current = spreadsheetInputCell('remove' === operation.op ? null : operation.value, row, column);
|
|
@@ -9108,7 +10681,7 @@ function sparseSpreadsheetCells(sheet, maximumCells) {
|
|
|
9108
10681
|
return true;
|
|
9109
10682
|
};
|
|
9110
10683
|
if (sheet.data) {
|
|
9111
|
-
if (sheet.data.length >
|
|
10684
|
+
if (sheet.data.length > OFFICE_KERNEL_SPREADSHEET_MAX_ROWS) return null;
|
|
9112
10685
|
for(let row = 0; row < sheet.data.length; row += 1){
|
|
9113
10686
|
const values = sheet.data[row];
|
|
9114
10687
|
if (values) {
|
|
@@ -9121,7 +10694,7 @@ function sparseSpreadsheetCells(sheet, maximumCells) {
|
|
|
9121
10694
|
}
|
|
9122
10695
|
function spreadsheetInputCell(cell, row, column) {
|
|
9123
10696
|
if (!cell || !cell.f && void 0 === cell.v && void 0 === cell.m) return null;
|
|
9124
|
-
if (!Number.isSafeInteger(row) || row < 0 || row >=
|
|
10697
|
+
if (!Number.isSafeInteger(row) || row < 0 || row >= OFFICE_KERNEL_SPREADSHEET_MAX_ROWS || !Number.isSafeInteger(column) || column < 0 || column >= 16384 || cell.f && Array.from(cell.f).length > SPREADSHEET_KERNEL_MAX_FORMULA_CHARACTERS) return;
|
|
9125
10698
|
const value = spreadsheetKernelValue(cell);
|
|
9126
10699
|
if (!value) return;
|
|
9127
10700
|
return {
|
|
@@ -9509,80 +11082,917 @@ function useSpreadsheetCalculation({ content, kernelWasmUrl, workbookRef }) {
|
|
|
9509
11082
|
clearTimer(automaticTimerRef);
|
|
9510
11083
|
clearTimer(fallbackTimerRef);
|
|
9511
11084
|
}, []);
|
|
9512
|
-
useEffect(()=>{
|
|
9513
|
-
if (acceptedContentRef.current === content) {
|
|
9514
|
-
acceptedContentRef.current = null;
|
|
9515
|
-
return;
|
|
11085
|
+
useEffect(()=>{
|
|
11086
|
+
if (acceptedContentRef.current === content) {
|
|
11087
|
+
acceptedContentRef.current = null;
|
|
11088
|
+
return;
|
|
11089
|
+
}
|
|
11090
|
+
acceptedContentRef.current = null;
|
|
11091
|
+
resultOperationsRef.current = [];
|
|
11092
|
+
pendingOperationCancellationRef.current = false;
|
|
11093
|
+
synchronizeSnapshot(content, createSpreadsheetKernelWorkbook(content));
|
|
11094
|
+
}, [
|
|
11095
|
+
content,
|
|
11096
|
+
kernelWasmUrl,
|
|
11097
|
+
synchronizeSnapshot
|
|
11098
|
+
]);
|
|
11099
|
+
const recalculate = useCallback((command)=>{
|
|
11100
|
+
clearTimer(automaticTimerRef);
|
|
11101
|
+
let snapshot = snapshotRef.current;
|
|
11102
|
+
if (!snapshot) {
|
|
11103
|
+
snapshot = createSpreadsheetKernelWorkbook(latestContentRef.current);
|
|
11104
|
+
snapshotRef.current = snapshot;
|
|
11105
|
+
}
|
|
11106
|
+
if (!snapshot) return void fallbackWithFortune(workbookRef.current, command);
|
|
11107
|
+
runCalculation(command, snapshot, documentRevisionRef.current);
|
|
11108
|
+
}, [
|
|
11109
|
+
runCalculation,
|
|
11110
|
+
workbookRef
|
|
11111
|
+
]);
|
|
11112
|
+
const hasPendingResultPatches = useCallback(()=>resultOperationsRef.current.length > 0, []);
|
|
11113
|
+
return useMemo(()=>({
|
|
11114
|
+
hasPendingResultPatches,
|
|
11115
|
+
notifyWorkbookOperations,
|
|
11116
|
+
recalculate,
|
|
11117
|
+
synchronizeWorkbook
|
|
11118
|
+
}), [
|
|
11119
|
+
hasPendingResultPatches,
|
|
11120
|
+
notifyWorkbookOperations,
|
|
11121
|
+
recalculate,
|
|
11122
|
+
synchronizeWorkbook
|
|
11123
|
+
]);
|
|
11124
|
+
}
|
|
11125
|
+
function scheduleIssueFallback(workbookRef, issues, active, revisionRef, timerRef) {
|
|
11126
|
+
if (!issues.length) return;
|
|
11127
|
+
clearTimer(timerRef);
|
|
11128
|
+
timerRef.current = setTimeout(()=>{
|
|
11129
|
+
timerRef.current = null;
|
|
11130
|
+
if (revisionRef.current !== active.revision || active.controller.signal.aborted) return;
|
|
11131
|
+
const workbook = workbookRef.current;
|
|
11132
|
+
if (!workbook) return;
|
|
11133
|
+
for (const issue of issues)workbook.calculateFormula(issue.cell.sheetId, {
|
|
11134
|
+
row: [
|
|
11135
|
+
issue.cell.row,
|
|
11136
|
+
issue.cell.row
|
|
11137
|
+
],
|
|
11138
|
+
column: [
|
|
11139
|
+
issue.cell.column,
|
|
11140
|
+
issue.cell.column
|
|
11141
|
+
]
|
|
11142
|
+
});
|
|
11143
|
+
}, 0);
|
|
11144
|
+
}
|
|
11145
|
+
function fallbackWithFortune(workbook, command) {
|
|
11146
|
+
if (!workbook) return;
|
|
11147
|
+
if ('workbook' === command.scope) workbook.calculateFormula();
|
|
11148
|
+
else workbook.calculateFormula(command.sheetId, command.range);
|
|
11149
|
+
}
|
|
11150
|
+
function clearTimer(timerRef) {
|
|
11151
|
+
if (null !== timerRef.current) clearTimeout(timerRef.current);
|
|
11152
|
+
timerRef.current = null;
|
|
11153
|
+
}
|
|
11154
|
+
function isCurrentCalculation(current, expected) {
|
|
11155
|
+
return current?.revision === expected.revision && current.documentRevision === expected.documentRevision && !expected.controller.signal.aborted;
|
|
11156
|
+
}
|
|
11157
|
+
function isAbortError(error) {
|
|
11158
|
+
return error instanceof DOMException && 'AbortError' === error.name;
|
|
11159
|
+
}
|
|
11160
|
+
function spreadsheetAutoFilterRange(sheet, selection) {
|
|
11161
|
+
if (sheet.isPivotTable || sheet.pivotTables?.length) return null;
|
|
11162
|
+
const normalized = normalizeAutoFilterSelection(selection);
|
|
11163
|
+
const range = normalized.row[0] !== normalized.row[1] ? normalized : spreadsheetCurrentRegion(sheet, normalized);
|
|
11164
|
+
if (!range || !validSpreadsheetAutoFilterRange(sheet, range)) return null;
|
|
11165
|
+
return range;
|
|
11166
|
+
}
|
|
11167
|
+
function spreadsheetAutoFilterHeaderColumn(sheet, selection) {
|
|
11168
|
+
const range = normalizedFilterSelection(sheet?.filter_select);
|
|
11169
|
+
if (!sheet || !range) return null;
|
|
11170
|
+
const row = spreadsheet_auto_filter_finiteIndex(selection.row_focus, selection.row[0]);
|
|
11171
|
+
const column = spreadsheet_auto_filter_finiteIndex(selection.column_focus, selection.column[0]);
|
|
11172
|
+
if (row !== range.row[0] || column < range.column[0] || column > range.column[1]) return null;
|
|
11173
|
+
return column;
|
|
11174
|
+
}
|
|
11175
|
+
function toggleSpreadsheetAutoFilter(content, sheetId, selection) {
|
|
11176
|
+
const sheetIndex = content.sheets.findIndex((sheet)=>sheet.id === sheetId);
|
|
11177
|
+
const sheet = content.sheets[sheetIndex];
|
|
11178
|
+
if (!sheet) return null;
|
|
11179
|
+
const nextSheet = sheet.filter_select ? spreadsheetSheetWithoutAutoFilter(sheet) : spreadsheetSheetWithAutoFilter(sheet, selection);
|
|
11180
|
+
if (!nextSheet) return null;
|
|
11181
|
+
const sheets = [
|
|
11182
|
+
...content.sheets
|
|
11183
|
+
];
|
|
11184
|
+
sheets[sheetIndex] = {
|
|
11185
|
+
...nextSheet,
|
|
11186
|
+
luckysheet_select_save: [
|
|
11187
|
+
finiteSpreadsheetSelection(selection)
|
|
11188
|
+
]
|
|
11189
|
+
};
|
|
11190
|
+
return {
|
|
11191
|
+
...content,
|
|
11192
|
+
sheets
|
|
11193
|
+
};
|
|
11194
|
+
}
|
|
11195
|
+
function spreadsheetSheetWithAutoFilter(sheet, selection) {
|
|
11196
|
+
const range = spreadsheetAutoFilterRange(sheet, selection);
|
|
11197
|
+
if (!range) return null;
|
|
11198
|
+
return {
|
|
11199
|
+
...sheet,
|
|
11200
|
+
filter: {},
|
|
11201
|
+
filter_select: {
|
|
11202
|
+
row: [
|
|
11203
|
+
...range.row
|
|
11204
|
+
],
|
|
11205
|
+
column: [
|
|
11206
|
+
...range.column
|
|
11207
|
+
]
|
|
11208
|
+
}
|
|
11209
|
+
};
|
|
11210
|
+
}
|
|
11211
|
+
function spreadsheetSheetWithoutAutoFilter(sheet) {
|
|
11212
|
+
const hiddenByFilter = spreadsheetFilterHiddenRows(sheet.filter);
|
|
11213
|
+
const rowhidden = {
|
|
11214
|
+
...sheet.config?.rowhidden
|
|
11215
|
+
};
|
|
11216
|
+
for (const row of hiddenByFilter)delete rowhidden[row];
|
|
11217
|
+
const config = sheet.config ? {
|
|
11218
|
+
...sheet.config,
|
|
11219
|
+
rowhidden
|
|
11220
|
+
} : void 0;
|
|
11221
|
+
const { filter: _filter, filter_select: _selection, ...remaining } = sheet;
|
|
11222
|
+
return {
|
|
11223
|
+
...remaining,
|
|
11224
|
+
config
|
|
11225
|
+
};
|
|
11226
|
+
}
|
|
11227
|
+
function spreadsheetFilterHiddenRows(filter) {
|
|
11228
|
+
const rows = new Set();
|
|
11229
|
+
for (const value of Object.values(filter ?? {})){
|
|
11230
|
+
if (!value || 'object' != typeof value) continue;
|
|
11231
|
+
const rowhidden = value.rowhidden;
|
|
11232
|
+
if (rowhidden && 'object' == typeof rowhidden) for (const row of Object.keys(rowhidden))rows.add(row);
|
|
11233
|
+
}
|
|
11234
|
+
return rows;
|
|
11235
|
+
}
|
|
11236
|
+
function spreadsheetCurrentRegion(sheet, selection) {
|
|
11237
|
+
const cells = spreadsheetCellReader(sheet);
|
|
11238
|
+
const bounds = spreadsheetUsedBounds(sheet);
|
|
11239
|
+
let startRow = selection.row[0];
|
|
11240
|
+
let endRow = selection.row[1];
|
|
11241
|
+
let startColumn = selection.column[0];
|
|
11242
|
+
let endColumn = selection.column[1];
|
|
11243
|
+
if (startRow > bounds.lastRow || startColumn > bounds.lastColumn || !spreadsheet_auto_filter_spreadsheetCellHasContent(cells(startRow, startColumn))) return null;
|
|
11244
|
+
let changed = true;
|
|
11245
|
+
while(changed){
|
|
11246
|
+
changed = false;
|
|
11247
|
+
while(startColumn > 0 && spreadsheetColumnHasContent(cells, startColumn - 1, startRow, endRow)){
|
|
11248
|
+
startColumn -= 1;
|
|
11249
|
+
changed = true;
|
|
11250
|
+
}
|
|
11251
|
+
while(endColumn < bounds.lastColumn && spreadsheetColumnHasContent(cells, endColumn + 1, startRow, endRow)){
|
|
11252
|
+
endColumn += 1;
|
|
11253
|
+
changed = true;
|
|
11254
|
+
}
|
|
11255
|
+
while(startRow > 0 && spreadsheetRowHasContent(cells, startRow - 1, startColumn, endColumn)){
|
|
11256
|
+
startRow -= 1;
|
|
11257
|
+
changed = true;
|
|
11258
|
+
}
|
|
11259
|
+
while(endRow < bounds.lastRow && spreadsheetRowHasContent(cells, endRow + 1, startColumn, endColumn)){
|
|
11260
|
+
endRow += 1;
|
|
11261
|
+
changed = true;
|
|
11262
|
+
}
|
|
11263
|
+
}
|
|
11264
|
+
return {
|
|
11265
|
+
row: [
|
|
11266
|
+
startRow,
|
|
11267
|
+
endRow
|
|
11268
|
+
],
|
|
11269
|
+
column: [
|
|
11270
|
+
startColumn,
|
|
11271
|
+
endColumn
|
|
11272
|
+
]
|
|
11273
|
+
};
|
|
11274
|
+
}
|
|
11275
|
+
function validSpreadsheetAutoFilterRange(sheet, range) {
|
|
11276
|
+
if (range.row[1] <= range.row[0]) return false;
|
|
11277
|
+
const cells = spreadsheetCellReader(sheet);
|
|
11278
|
+
if (!spreadsheetRowHasContent(cells, range.row[0], range.column[0], range.column[1])) return false;
|
|
11279
|
+
let dataFound = false;
|
|
11280
|
+
for(let row = range.row[0] + 1; row <= range.row[1]; row += 1)if (spreadsheetRowHasContent(cells, row, range.column[0], range.column[1])) {
|
|
11281
|
+
dataFound = true;
|
|
11282
|
+
break;
|
|
11283
|
+
}
|
|
11284
|
+
return dataFound && !spreadsheetRangeIntersectsMerge(sheet, range);
|
|
11285
|
+
}
|
|
11286
|
+
function spreadsheetRangeIntersectsMerge(sheet, range) {
|
|
11287
|
+
return Object.values(sheet.config?.merge ?? {}).some((merge)=>{
|
|
11288
|
+
const endRow = merge.r + Math.max(merge.rs, 1) - 1;
|
|
11289
|
+
const endColumn = merge.c + Math.max(merge.cs, 1) - 1;
|
|
11290
|
+
return merge.r <= range.row[1] && endRow >= range.row[0] && merge.c <= range.column[1] && endColumn >= range.column[0];
|
|
11291
|
+
});
|
|
11292
|
+
}
|
|
11293
|
+
function spreadsheetRowHasContent(cellAt, row, startColumn, endColumn) {
|
|
11294
|
+
for(let column = startColumn; column <= endColumn; column += 1)if (spreadsheet_auto_filter_spreadsheetCellHasContent(cellAt(row, column))) return true;
|
|
11295
|
+
return false;
|
|
11296
|
+
}
|
|
11297
|
+
function spreadsheetColumnHasContent(cellAt, column, startRow, endRow) {
|
|
11298
|
+
for(let row = startRow; row <= endRow; row += 1)if (spreadsheet_auto_filter_spreadsheetCellHasContent(cellAt(row, column))) return true;
|
|
11299
|
+
return false;
|
|
11300
|
+
}
|
|
11301
|
+
function spreadsheet_auto_filter_spreadsheetCellHasContent(cell) {
|
|
11302
|
+
if (!cell) return false;
|
|
11303
|
+
return [
|
|
11304
|
+
cell.v,
|
|
11305
|
+
cell.m,
|
|
11306
|
+
cell.f
|
|
11307
|
+
].some((value)=>null != value && '' !== value);
|
|
11308
|
+
}
|
|
11309
|
+
function spreadsheetCellReader(sheet) {
|
|
11310
|
+
if (sheet.data) return (row, column)=>sheet.data?.[row]?.[column] ?? null;
|
|
11311
|
+
const cells = new Map((sheet.celldata ?? []).map((cell)=>[
|
|
11312
|
+
`${cell.r}:${cell.c}`,
|
|
11313
|
+
cell.v
|
|
11314
|
+
]));
|
|
11315
|
+
return (row, column)=>cells.get(`${row}:${column}`) ?? null;
|
|
11316
|
+
}
|
|
11317
|
+
function spreadsheetUsedBounds(sheet) {
|
|
11318
|
+
let lastRow = Math.max((sheet.data?.length ?? 1) - 1, 0);
|
|
11319
|
+
let lastColumn = Math.max(...sheet.data?.map((row)=>Math.max((row?.length ?? 1) - 1, 0)) ?? [
|
|
11320
|
+
0
|
|
11321
|
+
]);
|
|
11322
|
+
for (const cell of sheet.celldata ?? []){
|
|
11323
|
+
lastRow = Math.max(lastRow, cell.r);
|
|
11324
|
+
lastColumn = Math.max(lastColumn, cell.c);
|
|
11325
|
+
}
|
|
11326
|
+
return {
|
|
11327
|
+
lastColumn,
|
|
11328
|
+
lastRow
|
|
11329
|
+
};
|
|
11330
|
+
}
|
|
11331
|
+
function normalizeAutoFilterSelection(selection) {
|
|
11332
|
+
const startRow = spreadsheet_auto_filter_finiteIndex(selection.row[0], 0);
|
|
11333
|
+
const endRow = spreadsheet_auto_filter_finiteIndex(selection.row[1], startRow);
|
|
11334
|
+
const startColumn = spreadsheet_auto_filter_finiteIndex(selection.column[0], 0);
|
|
11335
|
+
const endColumn = spreadsheet_auto_filter_finiteIndex(selection.column[1], startColumn);
|
|
11336
|
+
return {
|
|
11337
|
+
row: [
|
|
11338
|
+
Math.min(startRow, endRow),
|
|
11339
|
+
Math.max(startRow, endRow)
|
|
11340
|
+
],
|
|
11341
|
+
column: [
|
|
11342
|
+
Math.min(startColumn, endColumn),
|
|
11343
|
+
Math.max(startColumn, endColumn)
|
|
11344
|
+
]
|
|
11345
|
+
};
|
|
11346
|
+
}
|
|
11347
|
+
function normalizedFilterSelection(selection) {
|
|
11348
|
+
if (!selection?.row?.length || !selection.column?.length) return null;
|
|
11349
|
+
return normalizeAutoFilterSelection(selection);
|
|
11350
|
+
}
|
|
11351
|
+
function spreadsheet_auto_filter_finiteIndex(value, fallback) {
|
|
11352
|
+
return 'number' == typeof value && Number.isFinite(value) ? Math.max(0, Math.floor(value)) : fallback;
|
|
11353
|
+
}
|
|
11354
|
+
function useSpreadsheetAutoFilter({ canvasRef, content, editable, mountRevision, onChange, selection, sheetId, workbook = null }) {
|
|
11355
|
+
const contentRef = useRef(content);
|
|
11356
|
+
const editableRef = useRef(editable);
|
|
11357
|
+
const onChangeRef = useRef(onChange);
|
|
11358
|
+
const selectionRef = useRef(selection);
|
|
11359
|
+
const sheetIdRef = useRef(sheetId);
|
|
11360
|
+
const workbookRef = useRef(workbook);
|
|
11361
|
+
const keyboardInvokerRef = useRef(null);
|
|
11362
|
+
const restoreInvokerFocusRef = useRef(false);
|
|
11363
|
+
const menuWasOpenRef = useRef(false);
|
|
11364
|
+
contentRef.current = content;
|
|
11365
|
+
editableRef.current = editable;
|
|
11366
|
+
onChangeRef.current = onChange;
|
|
11367
|
+
selectionRef.current = selection;
|
|
11368
|
+
sheetIdRef.current = sheetId;
|
|
11369
|
+
workbookRef.current = workbook;
|
|
11370
|
+
const sheet = content.sheets.find((candidate)=>candidate.id === sheetId);
|
|
11371
|
+
const active = Boolean(sheet?.filter_select);
|
|
11372
|
+
const canToggle = Boolean(editable && sheet && (active || spreadsheetAutoFilterRange(sheet, selection)));
|
|
11373
|
+
const canOpenMenu = Boolean(editable && sheet?.filter_select);
|
|
11374
|
+
const toggle = useCallback(()=>{
|
|
11375
|
+
if (!editableRef.current) return false;
|
|
11376
|
+
const next = toggleSpreadsheetAutoFilter(contentRef.current, sheetIdRef.current, currentSpreadsheetAutoFilterSelection(selectionRef.current, workbookRef.current));
|
|
11377
|
+
if (!next) return false;
|
|
11378
|
+
contentRef.current = next;
|
|
11379
|
+
onChangeRef.current(next);
|
|
11380
|
+
return true;
|
|
11381
|
+
}, []);
|
|
11382
|
+
const openMenu = useCallback(()=>{
|
|
11383
|
+
if (!editableRef.current) return false;
|
|
11384
|
+
const container = canvasRef.current;
|
|
11385
|
+
const activeSheet = contentRef.current.sheets.find((candidate)=>candidate.id === sheetIdRef.current);
|
|
11386
|
+
const column = spreadsheetAutoFilterHeaderColumn(activeSheet, currentSpreadsheetAutoFilterSelection(selectionRef.current, workbookRef.current));
|
|
11387
|
+
const startColumn = activeSheet?.filter_select?.column?.[0];
|
|
11388
|
+
if (!container || null === column || !Number.isFinite(startColumn)) return false;
|
|
11389
|
+
enhanceSpreadsheetAutoFilterSurface(container, activeSheet, keyboardInvokerRef.current);
|
|
11390
|
+
const triggers = [
|
|
11391
|
+
...container.querySelectorAll('.luckysheet-filter-options')
|
|
11392
|
+
];
|
|
11393
|
+
const trigger = triggers[column - Number(startColumn)];
|
|
11394
|
+
if (!trigger) return false;
|
|
11395
|
+
keyboardInvokerRef.current = trigger;
|
|
11396
|
+
restoreInvokerFocusRef.current = true;
|
|
11397
|
+
trigger.click();
|
|
11398
|
+
focusSpreadsheetAutoFilterMenu(container);
|
|
11399
|
+
return true;
|
|
11400
|
+
}, [
|
|
11401
|
+
canvasRef
|
|
11402
|
+
]);
|
|
11403
|
+
const reserveAltKey = useCallback(()=>{
|
|
11404
|
+
if (!editableRef.current) return false;
|
|
11405
|
+
const activeSheet = contentRef.current.sheets.find((candidate)=>candidate.id === sheetIdRef.current);
|
|
11406
|
+
return null !== spreadsheetAutoFilterHeaderColumn(activeSheet, currentSpreadsheetAutoFilterSelection(selectionRef.current, workbookRef.current));
|
|
11407
|
+
}, []);
|
|
11408
|
+
useEffect(()=>{
|
|
11409
|
+
const container = canvasRef.current;
|
|
11410
|
+
if (!container || !editable) return;
|
|
11411
|
+
const enhance = ()=>{
|
|
11412
|
+
const activeSheet = contentRef.current.sheets.find((candidate)=>candidate.id === sheetIdRef.current);
|
|
11413
|
+
const menu = enhanceSpreadsheetAutoFilterSurface(container, activeSheet, keyboardInvokerRef.current);
|
|
11414
|
+
const menuOpen = Boolean(menu);
|
|
11415
|
+
if (menuWasOpenRef.current && !menuOpen && restoreInvokerFocusRef.current) {
|
|
11416
|
+
const invoker = keyboardInvokerRef.current;
|
|
11417
|
+
requestAnimationFrame(()=>{
|
|
11418
|
+
if (invoker?.isConnected) invoker.focus({
|
|
11419
|
+
preventScroll: true
|
|
11420
|
+
});
|
|
11421
|
+
});
|
|
11422
|
+
restoreInvokerFocusRef.current = false;
|
|
11423
|
+
}
|
|
11424
|
+
menuWasOpenRef.current = menuOpen;
|
|
11425
|
+
};
|
|
11426
|
+
const handlePointerDown = (event)=>{
|
|
11427
|
+
const trigger = spreadsheetAutoFilterTrigger(event.target);
|
|
11428
|
+
if (!trigger) return;
|
|
11429
|
+
keyboardInvokerRef.current = trigger;
|
|
11430
|
+
restoreInvokerFocusRef.current = false;
|
|
11431
|
+
};
|
|
11432
|
+
const handleKeyDown = (event)=>{
|
|
11433
|
+
const trigger = spreadsheetAutoFilterTrigger(event.target);
|
|
11434
|
+
if (trigger && ('Enter' === event.key || ' ' === event.key)) {
|
|
11435
|
+
event.preventDefault();
|
|
11436
|
+
event.stopPropagation();
|
|
11437
|
+
keyboardInvokerRef.current = trigger;
|
|
11438
|
+
restoreInvokerFocusRef.current = true;
|
|
11439
|
+
trigger.click();
|
|
11440
|
+
focusSpreadsheetAutoFilterMenu(container);
|
|
11441
|
+
return;
|
|
11442
|
+
}
|
|
11443
|
+
const menu = spreadsheetAutoFilterMenu(event.target);
|
|
11444
|
+
if (!menu) return;
|
|
11445
|
+
if ('Escape' === event.key) {
|
|
11446
|
+
event.preventDefault();
|
|
11447
|
+
event.stopPropagation();
|
|
11448
|
+
menu.querySelector('.button-default')?.click();
|
|
11449
|
+
return;
|
|
11450
|
+
}
|
|
11451
|
+
const target = event.target;
|
|
11452
|
+
if (('Enter' === event.key || ' ' === event.key) && target instanceof HTMLElement && !(target instanceof HTMLInputElement) && target.tabIndex >= 0) {
|
|
11453
|
+
event.preventDefault();
|
|
11454
|
+
event.stopPropagation();
|
|
11455
|
+
target.click();
|
|
11456
|
+
return;
|
|
11457
|
+
}
|
|
11458
|
+
if (('ArrowDown' === event.key || 'ArrowUp' === event.key) && !(target instanceof HTMLInputElement && 'checkbox' !== target.type)) {
|
|
11459
|
+
const focusable = spreadsheetAutoFilterMenuFocusable(menu);
|
|
11460
|
+
const current = focusable.indexOf(document.activeElement);
|
|
11461
|
+
if (!focusable.length) return;
|
|
11462
|
+
event.preventDefault();
|
|
11463
|
+
event.stopPropagation();
|
|
11464
|
+
const offset = 'ArrowDown' === event.key ? 1 : -1;
|
|
11465
|
+
const next = (Math.max(current, 0) + offset + focusable.length) % focusable.length;
|
|
11466
|
+
focusable[next]?.focus({
|
|
11467
|
+
preventScroll: true
|
|
11468
|
+
});
|
|
11469
|
+
}
|
|
11470
|
+
};
|
|
11471
|
+
enhance();
|
|
11472
|
+
container.addEventListener('pointerdown', handlePointerDown, true);
|
|
11473
|
+
container.addEventListener('keydown', handleKeyDown, true);
|
|
11474
|
+
if ("u" < typeof MutationObserver) return ()=>{
|
|
11475
|
+
container.removeEventListener('pointerdown', handlePointerDown, true);
|
|
11476
|
+
container.removeEventListener('keydown', handleKeyDown, true);
|
|
11477
|
+
};
|
|
11478
|
+
const observer = new MutationObserver(enhance);
|
|
11479
|
+
observer.observe(container, {
|
|
11480
|
+
childList: true,
|
|
11481
|
+
subtree: true
|
|
11482
|
+
});
|
|
11483
|
+
return ()=>{
|
|
11484
|
+
observer.disconnect();
|
|
11485
|
+
container.removeEventListener('pointerdown', handlePointerDown, true);
|
|
11486
|
+
container.removeEventListener('keydown', handleKeyDown, true);
|
|
11487
|
+
};
|
|
11488
|
+
}, [
|
|
11489
|
+
canvasRef,
|
|
11490
|
+
editable,
|
|
11491
|
+
mountRevision
|
|
11492
|
+
]);
|
|
11493
|
+
const commandPort = useMemo(()=>({
|
|
11494
|
+
active,
|
|
11495
|
+
canOpenMenu,
|
|
11496
|
+
canToggle,
|
|
11497
|
+
openMenu,
|
|
11498
|
+
toggle
|
|
11499
|
+
}), [
|
|
11500
|
+
active,
|
|
11501
|
+
canOpenMenu,
|
|
11502
|
+
canToggle,
|
|
11503
|
+
openMenu,
|
|
11504
|
+
toggle
|
|
11505
|
+
]);
|
|
11506
|
+
return {
|
|
11507
|
+
active,
|
|
11508
|
+
commandPort,
|
|
11509
|
+
reserveAltKey,
|
|
11510
|
+
status: active ? '自动筛选已开启;在表头按 Alt+向下箭头打开筛选菜单。' : ''
|
|
11511
|
+
};
|
|
11512
|
+
}
|
|
11513
|
+
function currentSpreadsheetAutoFilterSelection(fallback, workbook) {
|
|
11514
|
+
const live = workbook?.getSelection()?.at(-1);
|
|
11515
|
+
if (!live) return fallback;
|
|
11516
|
+
return {
|
|
11517
|
+
...fallback,
|
|
11518
|
+
...live,
|
|
11519
|
+
row: [
|
|
11520
|
+
...live.row
|
|
11521
|
+
],
|
|
11522
|
+
column: [
|
|
11523
|
+
...live.column
|
|
11524
|
+
]
|
|
11525
|
+
};
|
|
11526
|
+
}
|
|
11527
|
+
function enhanceSpreadsheetAutoFilterSurface(container, sheet, invoker) {
|
|
11528
|
+
const range = sheet?.filter_select;
|
|
11529
|
+
const startRow = range?.row?.[0];
|
|
11530
|
+
const startColumn = range?.column?.[0];
|
|
11531
|
+
const triggers = [
|
|
11532
|
+
...container.querySelectorAll('.luckysheet-filter-options')
|
|
11533
|
+
];
|
|
11534
|
+
for (const [index, trigger] of triggers.entries()){
|
|
11535
|
+
const column = Number(startColumn) + index;
|
|
11536
|
+
if (!Number.isFinite(column) || !Number.isFinite(startRow)) continue;
|
|
11537
|
+
const label = spreadsheetAutoFilterColumnLabel(sheet, Number(startRow), column);
|
|
11538
|
+
trigger.dataset.filterColumn = String(column);
|
|
11539
|
+
trigger.dataset.officeShortcuts = 'ignore';
|
|
11540
|
+
trigger.setAttribute('role', 'button');
|
|
11541
|
+
trigger.setAttribute('aria-label', `${label} 筛选`);
|
|
11542
|
+
trigger.setAttribute('aria-haspopup', 'dialog');
|
|
11543
|
+
trigger.setAttribute('aria-expanded', 'false');
|
|
11544
|
+
trigger.setAttribute('title', `${label} 筛选(Alt+↓)`);
|
|
11545
|
+
}
|
|
11546
|
+
const menu = container.querySelector('.fortune-filter-menu');
|
|
11547
|
+
if (!menu) return null;
|
|
11548
|
+
const trigger = invoker ?? triggers.find((candidate)=>candidate.matches(':focus'));
|
|
11549
|
+
const triggerLabel = trigger?.getAttribute('aria-label')?.replace(/\s*筛选$/, '');
|
|
11550
|
+
const label = triggerLabel || '列';
|
|
11551
|
+
menu.setAttribute('role', 'dialog');
|
|
11552
|
+
menu.dataset.officeShortcuts = 'ignore';
|
|
11553
|
+
menu.setAttribute('aria-label', `${label} 筛选`);
|
|
11554
|
+
menu.setAttribute('aria-modal', 'false');
|
|
11555
|
+
trigger?.setAttribute('aria-expanded', 'true');
|
|
11556
|
+
const search = menu.querySelector('.filtermenu-input-container input, input:not([type="checkbox"])');
|
|
11557
|
+
search?.setAttribute('aria-label', '搜索筛选值');
|
|
11558
|
+
for (const checkbox of menu.querySelectorAll('input[type="checkbox"]')){
|
|
11559
|
+
const item = checkbox.closest('.select-item');
|
|
11560
|
+
const itemLabel = item ? [
|
|
11561
|
+
...item.children
|
|
11562
|
+
].filter((child)=>child !== checkbox && !child.classList.contains('count') && !child.classList.contains('filter-caret')).map((child)=>child.textContent?.trim()).find(Boolean) : void 0;
|
|
11563
|
+
checkbox.setAttribute('aria-label', `显示 ${itemLabel || '筛选值'}`);
|
|
11564
|
+
}
|
|
11565
|
+
for (const action of menu.querySelectorAll('.luckysheet-cols-menuitem, .fortune-byvalue-btn, .button-basic')){
|
|
11566
|
+
action.setAttribute('role', 'button');
|
|
11567
|
+
const actionLabel = action.textContent?.replace(/\s+/g, ' ').trim();
|
|
11568
|
+
if (actionLabel) action.setAttribute('aria-label', actionLabel);
|
|
11569
|
+
}
|
|
11570
|
+
return menu;
|
|
11571
|
+
}
|
|
11572
|
+
function focusSpreadsheetAutoFilterMenu(container) {
|
|
11573
|
+
requestAnimationFrame(()=>{
|
|
11574
|
+
const menu = container.querySelector('.fortune-filter-menu');
|
|
11575
|
+
if (!menu) return;
|
|
11576
|
+
spreadsheetAutoFilterMenuFocusable(menu)[0]?.focus({
|
|
11577
|
+
preventScroll: true
|
|
11578
|
+
});
|
|
11579
|
+
});
|
|
11580
|
+
}
|
|
11581
|
+
function spreadsheetAutoFilterMenuFocusable(menu) {
|
|
11582
|
+
return [
|
|
11583
|
+
...menu.querySelectorAll('.luckysheet-cols-menuitem, .fortune-byvalue-btn, .select-item[tabindex], input:not([disabled]), .button-basic')
|
|
11584
|
+
].filter((element)=>element.tabIndex >= 0 && !element.hidden);
|
|
11585
|
+
}
|
|
11586
|
+
function spreadsheetAutoFilterTrigger(target) {
|
|
11587
|
+
return target instanceof Element ? target.closest('.luckysheet-filter-options') : null;
|
|
11588
|
+
}
|
|
11589
|
+
function spreadsheetAutoFilterMenu(target) {
|
|
11590
|
+
return target instanceof Element ? target.closest('.fortune-filter-menu') : null;
|
|
11591
|
+
}
|
|
11592
|
+
function spreadsheetAutoFilterColumnLabel(sheet, row, column) {
|
|
11593
|
+
const cell = sheet?.data ? sheet.data[row]?.[column] : sheet?.celldata?.find((candidate)=>candidate.r === row && candidate.c === column)?.v;
|
|
11594
|
+
const value = cell?.m ?? cell?.v;
|
|
11595
|
+
const label = null == value ? '' : String(value).trim();
|
|
11596
|
+
return label || `列 ${spreadsheetColumnName(column)}`;
|
|
11597
|
+
}
|
|
11598
|
+
function spreadsheetColumnName(column) {
|
|
11599
|
+
let value = Math.max(0, Math.floor(column)) + 1;
|
|
11600
|
+
let name = '';
|
|
11601
|
+
while(value > 0){
|
|
11602
|
+
value -= 1;
|
|
11603
|
+
name = String.fromCharCode(65 + value % 26) + name;
|
|
11604
|
+
value = Math.floor(value / 26);
|
|
11605
|
+
}
|
|
11606
|
+
return name;
|
|
11607
|
+
}
|
|
11608
|
+
const spreadsheetCellFormatAttributes = [
|
|
11609
|
+
'bl',
|
|
11610
|
+
'it',
|
|
11611
|
+
'ff',
|
|
11612
|
+
'fs',
|
|
11613
|
+
'fc',
|
|
11614
|
+
'ht',
|
|
11615
|
+
'vt',
|
|
11616
|
+
'tb',
|
|
11617
|
+
'cl',
|
|
11618
|
+
'un',
|
|
11619
|
+
'tr',
|
|
11620
|
+
'ct',
|
|
11621
|
+
'bg'
|
|
11622
|
+
];
|
|
11623
|
+
function captureSpreadsheetFormatPattern(cells) {
|
|
11624
|
+
const rowCount = cells.length;
|
|
11625
|
+
const columnCount = cells[0]?.length ?? 0;
|
|
11626
|
+
if (rowCount < 1 || columnCount < 1 || cells.some((row)=>row.length !== columnCount)) return null;
|
|
11627
|
+
return {
|
|
11628
|
+
cells: cells.map((row)=>row.map((cell)=>spreadsheetCellFormatSnapshot(cell))),
|
|
11629
|
+
columnCount,
|
|
11630
|
+
rowCount
|
|
11631
|
+
};
|
|
11632
|
+
}
|
|
11633
|
+
function spreadsheetFormatPainterTargetRange(target, pattern, bounds) {
|
|
11634
|
+
if (pattern.rowCount < 1 || pattern.columnCount < 1 || bounds.rowCount < 1 || bounds.columnCount < 1) return null;
|
|
11635
|
+
const normalized = normalizeSpreadsheetFormatPainterRange(target);
|
|
11636
|
+
if (!normalized) return null;
|
|
11637
|
+
const singleCell = normalized.row[0] === normalized.row[1] && normalized.column[0] === normalized.column[1];
|
|
11638
|
+
const startRow = clampIndex(normalized.row[0], bounds.rowCount);
|
|
11639
|
+
const startColumn = clampIndex(normalized.column[0], bounds.columnCount);
|
|
11640
|
+
const requestedEndRow = singleCell ? startRow + pattern.rowCount - 1 : normalized.row[1];
|
|
11641
|
+
const requestedEndColumn = singleCell ? startColumn + pattern.columnCount - 1 : normalized.column[1];
|
|
11642
|
+
return {
|
|
11643
|
+
row: [
|
|
11644
|
+
startRow,
|
|
11645
|
+
clampIndex(requestedEndRow, bounds.rowCount)
|
|
11646
|
+
],
|
|
11647
|
+
column: [
|
|
11648
|
+
startColumn,
|
|
11649
|
+
clampIndex(requestedEndColumn, bounds.columnCount)
|
|
11650
|
+
]
|
|
11651
|
+
};
|
|
11652
|
+
}
|
|
11653
|
+
function spreadsheetFormatPainterCellCount(range) {
|
|
11654
|
+
const normalized = normalizeSpreadsheetFormatPainterRange(range);
|
|
11655
|
+
if (!normalized) return 0;
|
|
11656
|
+
return (normalized.row[1] - normalized.row[0] + 1) * (normalized.column[1] - normalized.column[0] + 1);
|
|
11657
|
+
}
|
|
11658
|
+
function spreadsheetFormatPainterBatches(pattern, target) {
|
|
11659
|
+
const normalized = normalizeSpreadsheetFormatPainterRange(target);
|
|
11660
|
+
if (!normalized || pattern.rowCount < 1 || pattern.columnCount < 1) return [];
|
|
11661
|
+
const batches = [];
|
|
11662
|
+
for (const attribute of spreadsheetCellFormatAttributes){
|
|
11663
|
+
const rectangles = spreadsheetFormatRectangles(pattern, normalized, attribute);
|
|
11664
|
+
const groups = new Map();
|
|
11665
|
+
for (const rectangle of rectangles){
|
|
11666
|
+
const key = spreadsheetFormatValueKey(rectangle.value);
|
|
11667
|
+
const group = groups.get(key);
|
|
11668
|
+
if (group) group.ranges.push(rectangle.range);
|
|
11669
|
+
else groups.set(key, {
|
|
11670
|
+
ranges: [
|
|
11671
|
+
rectangle.range
|
|
11672
|
+
],
|
|
11673
|
+
value: cloneSpreadsheetFormatValue(rectangle.value)
|
|
11674
|
+
});
|
|
11675
|
+
}
|
|
11676
|
+
for (const group of groups.values())batches.push({
|
|
11677
|
+
attribute,
|
|
11678
|
+
ranges: group.ranges,
|
|
11679
|
+
value: group.value
|
|
11680
|
+
});
|
|
11681
|
+
}
|
|
11682
|
+
return batches;
|
|
11683
|
+
}
|
|
11684
|
+
function spreadsheetCellFormatSnapshot(cell) {
|
|
11685
|
+
const snapshot = {};
|
|
11686
|
+
for (const attribute of spreadsheetCellFormatAttributes)snapshot[attribute] = 'ct' === attribute ? spreadsheetNumberFormatSnapshot(cell?.ct) : cloneSpreadsheetFormatValue(cell?.[attribute]);
|
|
11687
|
+
return snapshot;
|
|
11688
|
+
}
|
|
11689
|
+
function spreadsheetNumberFormatSnapshot(value) {
|
|
11690
|
+
const format = value?.fa?.trim();
|
|
11691
|
+
const type = value?.t?.trim();
|
|
11692
|
+
return {
|
|
11693
|
+
fa: format || 'General',
|
|
11694
|
+
t: type || 'g'
|
|
11695
|
+
};
|
|
11696
|
+
}
|
|
11697
|
+
function spreadsheetFormatRectangles(pattern, target, attribute) {
|
|
11698
|
+
const rectangles = [];
|
|
11699
|
+
let previous = new Map();
|
|
11700
|
+
for(let row = target.row[0]; row <= target.row[1]; row += 1){
|
|
11701
|
+
const runs = [];
|
|
11702
|
+
let startColumn = target.column[0];
|
|
11703
|
+
let value = spreadsheetPatternValue(pattern, target, row, startColumn, attribute);
|
|
11704
|
+
let key = spreadsheetFormatValueKey(value);
|
|
11705
|
+
for(let column = target.column[0] + 1; column <= target.column[1] + 1; column += 1){
|
|
11706
|
+
const nextValue = column <= target.column[1] ? spreadsheetPatternValue(pattern, target, row, column, attribute) : void 0;
|
|
11707
|
+
const nextKey = column <= target.column[1] ? spreadsheetFormatValueKey(nextValue) : '__end__';
|
|
11708
|
+
if (nextKey !== key) {
|
|
11709
|
+
runs.push({
|
|
11710
|
+
endColumn: column - 1,
|
|
11711
|
+
key,
|
|
11712
|
+
startColumn,
|
|
11713
|
+
value
|
|
11714
|
+
});
|
|
11715
|
+
startColumn = column;
|
|
11716
|
+
value = nextValue;
|
|
11717
|
+
key = nextKey;
|
|
11718
|
+
}
|
|
11719
|
+
}
|
|
11720
|
+
const current = new Map();
|
|
11721
|
+
for (const run of runs){
|
|
11722
|
+
const signature = `${run.startColumn}:${run.endColumn}:${run.key}`;
|
|
11723
|
+
const continuing = previous.get(signature);
|
|
11724
|
+
if (continuing) {
|
|
11725
|
+
continuing.range.row[1] = row;
|
|
11726
|
+
current.set(signature, continuing);
|
|
11727
|
+
continue;
|
|
11728
|
+
}
|
|
11729
|
+
const rectangle = {
|
|
11730
|
+
range: {
|
|
11731
|
+
row: [
|
|
11732
|
+
row,
|
|
11733
|
+
row
|
|
11734
|
+
],
|
|
11735
|
+
column: [
|
|
11736
|
+
run.startColumn,
|
|
11737
|
+
run.endColumn
|
|
11738
|
+
]
|
|
11739
|
+
},
|
|
11740
|
+
value: run.value
|
|
11741
|
+
};
|
|
11742
|
+
rectangles.push(rectangle);
|
|
11743
|
+
current.set(signature, rectangle);
|
|
11744
|
+
}
|
|
11745
|
+
previous = current;
|
|
11746
|
+
}
|
|
11747
|
+
return rectangles;
|
|
11748
|
+
}
|
|
11749
|
+
function spreadsheetPatternValue(pattern, target, row, column, attribute) {
|
|
11750
|
+
const sourceRow = (row - target.row[0]) % pattern.rowCount;
|
|
11751
|
+
const sourceColumn = (column - target.column[0]) % pattern.columnCount;
|
|
11752
|
+
return pattern.cells[sourceRow]?.[sourceColumn]?.[attribute];
|
|
11753
|
+
}
|
|
11754
|
+
function normalizeSpreadsheetFormatPainterRange(range) {
|
|
11755
|
+
const values = [
|
|
11756
|
+
...range.row,
|
|
11757
|
+
...range.column
|
|
11758
|
+
];
|
|
11759
|
+
if (4 !== values.length || values.some((value)=>!Number.isFinite(value))) return null;
|
|
11760
|
+
return {
|
|
11761
|
+
row: [
|
|
11762
|
+
Math.max(0, Math.floor(Math.min(range.row[0], range.row[1]))),
|
|
11763
|
+
Math.max(0, Math.floor(Math.max(range.row[0], range.row[1])))
|
|
11764
|
+
],
|
|
11765
|
+
column: [
|
|
11766
|
+
Math.max(0, Math.floor(Math.min(range.column[0], range.column[1]))),
|
|
11767
|
+
Math.max(0, Math.floor(Math.max(range.column[0], range.column[1])))
|
|
11768
|
+
]
|
|
11769
|
+
};
|
|
11770
|
+
}
|
|
11771
|
+
function clampIndex(value, length) {
|
|
11772
|
+
return Math.max(0, Math.min(Math.floor(value), Math.floor(length) - 1));
|
|
11773
|
+
}
|
|
11774
|
+
function spreadsheetFormatValueKey(value) {
|
|
11775
|
+
if (void 0 === value) return 'undefined';
|
|
11776
|
+
if ('number' == typeof value && Number.isNaN(value)) return 'number:NaN';
|
|
11777
|
+
return `${typeof value}:${JSON.stringify(value)}`;
|
|
11778
|
+
}
|
|
11779
|
+
function cloneSpreadsheetFormatValue(value) {
|
|
11780
|
+
if (!value || 'object' != typeof value) return value;
|
|
11781
|
+
if (Array.isArray(value)) return value.map((item)=>cloneSpreadsheetFormatValue(item));
|
|
11782
|
+
return Object.fromEntries(Object.entries(value).map(([key, item])=>[
|
|
11783
|
+
key,
|
|
11784
|
+
cloneSpreadsheetFormatValue(item)
|
|
11785
|
+
]));
|
|
11786
|
+
}
|
|
11787
|
+
const spreadsheetFormatPainterMaximumCells = 50000;
|
|
11788
|
+
function useSpreadsheetFormatPainter({ content, editable, onError, sourceRange, sourceSheetId, workbook }) {
|
|
11789
|
+
const contentRef = useRef(content);
|
|
11790
|
+
const editableRef = useRef(editable);
|
|
11791
|
+
const onErrorRef = useRef(onError);
|
|
11792
|
+
const sessionRef = useRef(null);
|
|
11793
|
+
const sourceRef = useRef({
|
|
11794
|
+
range: copySpreadsheetFormatPainterRange(sourceRange),
|
|
11795
|
+
sheetId: sourceSheetId
|
|
11796
|
+
});
|
|
11797
|
+
const workbookRef = useRef(workbook);
|
|
11798
|
+
const [mode, setMode] = useState(null);
|
|
11799
|
+
contentRef.current = content;
|
|
11800
|
+
editableRef.current = editable;
|
|
11801
|
+
onErrorRef.current = onError;
|
|
11802
|
+
sourceRef.current = {
|
|
11803
|
+
range: copySpreadsheetFormatPainterRange(sourceRange),
|
|
11804
|
+
sheetId: sourceSheetId
|
|
11805
|
+
};
|
|
11806
|
+
workbookRef.current = workbook;
|
|
11807
|
+
const clearSession = useCallback(()=>{
|
|
11808
|
+
sessionRef.current = null;
|
|
11809
|
+
setMode(null);
|
|
11810
|
+
}, []);
|
|
11811
|
+
useEffect(()=>{
|
|
11812
|
+
if (!editable || !workbook) clearSession();
|
|
11813
|
+
}, [
|
|
11814
|
+
clearSession,
|
|
11815
|
+
editable,
|
|
11816
|
+
workbook
|
|
11817
|
+
]);
|
|
11818
|
+
const activate = useCallback((nextMode)=>{
|
|
11819
|
+
const activeWorkbook = workbookRef.current;
|
|
11820
|
+
const source = sourceRef.current;
|
|
11821
|
+
if (!editableRef.current || !activeWorkbook || !source.sheetId) return false;
|
|
11822
|
+
if (spreadsheetFormatPainterCellCount(source.range) > spreadsheetFormatPainterMaximumCells) {
|
|
11823
|
+
onErrorRef.current(`格式刷一次最多复制 ${spreadsheetFormatPainterMaximumCells.toLocaleString()} 个单元格,请缩小源区域后重试。`);
|
|
11824
|
+
return false;
|
|
11825
|
+
}
|
|
11826
|
+
try {
|
|
11827
|
+
const pattern = captureSpreadsheetFormatPattern(activeWorkbook.getCellsByRange(source.range, {
|
|
11828
|
+
id: source.sheetId
|
|
11829
|
+
}));
|
|
11830
|
+
if (!pattern || !spreadsheetFormatPatternMatchesRange(pattern, source.range)) {
|
|
11831
|
+
onErrorRef.current('无法读取完整的源格式,请重新选择后重试。');
|
|
11832
|
+
return false;
|
|
11833
|
+
}
|
|
11834
|
+
sessionRef.current = {
|
|
11835
|
+
mode: nextMode,
|
|
11836
|
+
pattern
|
|
11837
|
+
};
|
|
11838
|
+
setMode(nextMode);
|
|
11839
|
+
return true;
|
|
11840
|
+
} catch {
|
|
11841
|
+
onErrorRef.current('无法读取源格式,请重新选择后重试。');
|
|
11842
|
+
return false;
|
|
11843
|
+
}
|
|
11844
|
+
}, []);
|
|
11845
|
+
const applySelection = useCallback((target)=>{
|
|
11846
|
+
const activeWorkbook = workbookRef.current;
|
|
11847
|
+
const session = sessionRef.current;
|
|
11848
|
+
const sheet = contentRef.current.sheets.find((candidate)=>candidate.id === target.sheetId);
|
|
11849
|
+
if (!editableRef.current || !activeWorkbook || !session || !sheet) return false;
|
|
11850
|
+
const rawTarget = spreadsheetSelectionRange(target);
|
|
11851
|
+
const targetRange = spreadsheetFormatPainterTargetRange(rawTarget, session.pattern, spreadsheetFormatPainterSheetBounds(sheet, rawTarget, session.pattern));
|
|
11852
|
+
if (!targetRange) return false;
|
|
11853
|
+
const targetKey = spreadsheetFormatPainterTargetKey(target.sheetId, targetRange);
|
|
11854
|
+
if (session.lastAppliedTargetKey === targetKey) return false;
|
|
11855
|
+
if (spreadsheetFormatPainterCellCount(targetRange) > spreadsheetFormatPainterMaximumCells) {
|
|
11856
|
+
onErrorRef.current(`格式刷一次最多应用到 ${spreadsheetFormatPainterMaximumCells.toLocaleString()} 个单元格,请缩小目标区域后重试。`);
|
|
11857
|
+
return false;
|
|
9516
11858
|
}
|
|
9517
|
-
|
|
9518
|
-
|
|
9519
|
-
|
|
9520
|
-
|
|
11859
|
+
const batches = spreadsheetFormatPainterBatches(session.pattern, targetRange);
|
|
11860
|
+
if (!batches.length) return false;
|
|
11861
|
+
session.lastAppliedTargetKey = targetKey;
|
|
11862
|
+
try {
|
|
11863
|
+
activeWorkbook.batchCallApis(batches.map((batch)=>({
|
|
11864
|
+
name: 'setCellFormatByRange',
|
|
11865
|
+
args: [
|
|
11866
|
+
batch.attribute,
|
|
11867
|
+
batch.value,
|
|
11868
|
+
batch.ranges,
|
|
11869
|
+
{
|
|
11870
|
+
id: target.sheetId
|
|
11871
|
+
}
|
|
11872
|
+
]
|
|
11873
|
+
})));
|
|
11874
|
+
} catch {
|
|
11875
|
+
session.lastAppliedTargetKey = void 0;
|
|
11876
|
+
onErrorRef.current('无法应用格式,请缩小目标区域或重试。');
|
|
11877
|
+
return false;
|
|
11878
|
+
}
|
|
11879
|
+
if ('once' === session.mode) clearSession();
|
|
11880
|
+
return true;
|
|
9521
11881
|
}, [
|
|
9522
|
-
|
|
9523
|
-
kernelWasmUrl,
|
|
9524
|
-
synchronizeSnapshot
|
|
11882
|
+
clearSession
|
|
9525
11883
|
]);
|
|
9526
|
-
const
|
|
9527
|
-
|
|
9528
|
-
|
|
9529
|
-
|
|
9530
|
-
snapshot = createSpreadsheetKernelWorkbook(latestContentRef.current);
|
|
9531
|
-
snapshotRef.current = snapshot;
|
|
9532
|
-
}
|
|
9533
|
-
if (!snapshot) return void fallbackWithFortune(workbookRef.current, command);
|
|
9534
|
-
runCalculation(command, snapshot, documentRevisionRef.current);
|
|
11884
|
+
const cancel = useCallback(()=>{
|
|
11885
|
+
if (!sessionRef.current) return false;
|
|
11886
|
+
clearSession();
|
|
11887
|
+
return true;
|
|
9535
11888
|
}, [
|
|
9536
|
-
|
|
9537
|
-
workbookRef
|
|
11889
|
+
clearSession
|
|
9538
11890
|
]);
|
|
9539
|
-
const
|
|
9540
|
-
|
|
9541
|
-
|
|
9542
|
-
|
|
9543
|
-
|
|
9544
|
-
|
|
11891
|
+
const commandPort = useMemo(()=>({
|
|
11892
|
+
active: null !== mode,
|
|
11893
|
+
activate,
|
|
11894
|
+
applySelection,
|
|
11895
|
+
canActivate: editable && Boolean(workbook && sourceSheetId),
|
|
11896
|
+
cancel,
|
|
11897
|
+
mode
|
|
9545
11898
|
}), [
|
|
9546
|
-
|
|
9547
|
-
|
|
9548
|
-
|
|
9549
|
-
|
|
11899
|
+
activate,
|
|
11900
|
+
applySelection,
|
|
11901
|
+
cancel,
|
|
11902
|
+
editable,
|
|
11903
|
+
mode,
|
|
11904
|
+
sourceSheetId,
|
|
11905
|
+
workbook
|
|
9550
11906
|
]);
|
|
11907
|
+
return {
|
|
11908
|
+
commandPort,
|
|
11909
|
+
mode
|
|
11910
|
+
};
|
|
9551
11911
|
}
|
|
9552
|
-
function
|
|
9553
|
-
|
|
9554
|
-
clearTimer(timerRef);
|
|
9555
|
-
timerRef.current = setTimeout(()=>{
|
|
9556
|
-
timerRef.current = null;
|
|
9557
|
-
if (revisionRef.current !== active.revision || active.controller.signal.aborted) return;
|
|
9558
|
-
const workbook = workbookRef.current;
|
|
9559
|
-
if (!workbook) return;
|
|
9560
|
-
for (const issue of issues)workbook.calculateFormula(issue.cell.sheetId, {
|
|
9561
|
-
row: [
|
|
9562
|
-
issue.cell.row,
|
|
9563
|
-
issue.cell.row
|
|
9564
|
-
],
|
|
9565
|
-
column: [
|
|
9566
|
-
issue.cell.column,
|
|
9567
|
-
issue.cell.column
|
|
9568
|
-
]
|
|
9569
|
-
});
|
|
9570
|
-
}, 0);
|
|
11912
|
+
function spreadsheetFormatPatternMatchesRange(pattern, range) {
|
|
11913
|
+
return pattern.rowCount === Math.abs(range.row[1] - range.row[0]) + 1 && pattern.columnCount === Math.abs(range.column[1] - range.column[0]) + 1;
|
|
9571
11914
|
}
|
|
9572
|
-
function
|
|
9573
|
-
|
|
9574
|
-
|
|
9575
|
-
|
|
11915
|
+
function spreadsheetSelectionRange(target) {
|
|
11916
|
+
return {
|
|
11917
|
+
row: [
|
|
11918
|
+
...target.selection.row
|
|
11919
|
+
],
|
|
11920
|
+
column: [
|
|
11921
|
+
...target.selection.column
|
|
11922
|
+
]
|
|
11923
|
+
};
|
|
9576
11924
|
}
|
|
9577
|
-
function
|
|
9578
|
-
|
|
9579
|
-
|
|
11925
|
+
function copySpreadsheetFormatPainterRange(range) {
|
|
11926
|
+
return {
|
|
11927
|
+
row: [
|
|
11928
|
+
...range.row
|
|
11929
|
+
],
|
|
11930
|
+
column: [
|
|
11931
|
+
...range.column
|
|
11932
|
+
]
|
|
11933
|
+
};
|
|
9580
11934
|
}
|
|
9581
|
-
function
|
|
9582
|
-
return
|
|
11935
|
+
function spreadsheetFormatPainterTargetKey(sheetId, range) {
|
|
11936
|
+
return `${sheetId}:${range.row[0]}:${range.row[1]}:${range.column[0]}:${range.column[1]}`;
|
|
9583
11937
|
}
|
|
9584
|
-
function
|
|
9585
|
-
|
|
11938
|
+
function spreadsheetFormatPainterSheetBounds(sheet, target, pattern) {
|
|
11939
|
+
const requestedRowCount = Math.max(target.row[0], target.row[1]) + pattern.rowCount;
|
|
11940
|
+
const requestedColumnCount = Math.max(target.column[0], target.column[1]) + pattern.columnCount;
|
|
11941
|
+
return {
|
|
11942
|
+
rowCount: positiveInteger(sheet.row) ?? Math.max(sheet.data?.length ?? 0, requestedRowCount),
|
|
11943
|
+
columnCount: positiveInteger(sheet.column) ?? Math.max(...sheet.data?.map((row)=>row?.length ?? 0) ?? [
|
|
11944
|
+
0
|
|
11945
|
+
], requestedColumnCount)
|
|
11946
|
+
};
|
|
11947
|
+
}
|
|
11948
|
+
function positiveInteger(value) {
|
|
11949
|
+
return 'number' == typeof value && Number.isFinite(value) && value > 0 ? Math.floor(value) : null;
|
|
11950
|
+
}
|
|
11951
|
+
function useSpreadsheetCollaborationPresenceProjection({ content, workbook }) {
|
|
11952
|
+
const participants = useOfficeRemoteParticipants();
|
|
11953
|
+
useEffect(()=>{
|
|
11954
|
+
if (!workbook) return;
|
|
11955
|
+
const projected = spreadsheetPresenceProjection(content, participants);
|
|
11956
|
+
if (projected.length) workbook.addPresences(projected);
|
|
11957
|
+
return ()=>{
|
|
11958
|
+
if (!projected.length) return;
|
|
11959
|
+
workbook.removePresences(projected.map(({ userId, username })=>({
|
|
11960
|
+
userId,
|
|
11961
|
+
username
|
|
11962
|
+
})));
|
|
11963
|
+
};
|
|
11964
|
+
}, [
|
|
11965
|
+
content,
|
|
11966
|
+
participants,
|
|
11967
|
+
workbook
|
|
11968
|
+
]);
|
|
11969
|
+
}
|
|
11970
|
+
function spreadsheetPresenceProjection(content, participants) {
|
|
11971
|
+
return participants.flatMap((participant)=>{
|
|
11972
|
+
const location = participant.location;
|
|
11973
|
+
if (location?.kind !== 'spreadsheet') return [];
|
|
11974
|
+
const sheet = content.sheets.find((candidate)=>candidate.id === location.sheetId && 1 !== candidate.hide);
|
|
11975
|
+
if (!sheet) return [];
|
|
11976
|
+
const selection = location.activeCell ?? {
|
|
11977
|
+
row: location.ranges[0]?.startRow ?? -1,
|
|
11978
|
+
column: location.ranges[0]?.startColumn ?? -1
|
|
11979
|
+
};
|
|
11980
|
+
const rowCount = Math.max(sheet.row ?? 60, sheet.data?.length ?? 0);
|
|
11981
|
+
const columnCount = Math.max(sheet.column ?? 26, sheet.data?.reduce((maximum, row)=>Math.max(maximum, row?.length ?? 0), 0) ?? 0);
|
|
11982
|
+
if (selection.row < 0 || selection.column < 0 || selection.row >= rowCount || selection.column >= columnCount) return [];
|
|
11983
|
+
return [
|
|
11984
|
+
{
|
|
11985
|
+
sheetId: location.sheetId,
|
|
11986
|
+
username: participant.actor.name,
|
|
11987
|
+
userId: `a3s-office:${participant.presenceId}`,
|
|
11988
|
+
color: officePresenceColor(participant),
|
|
11989
|
+
selection: {
|
|
11990
|
+
r: selection.row,
|
|
11991
|
+
c: selection.column
|
|
11992
|
+
}
|
|
11993
|
+
}
|
|
11994
|
+
];
|
|
11995
|
+
});
|
|
9586
11996
|
}
|
|
9587
11997
|
const MAXIMUM_BUFFERED_SPREADSHEET_OPERATIONS = 10001;
|
|
9588
11998
|
function useSpreadsheetWorkbookSync(content) {
|
|
@@ -9621,10 +12031,173 @@ function useSpreadsheetWorkbookSync(content) {
|
|
|
9621
12031
|
takeOperations
|
|
9622
12032
|
};
|
|
9623
12033
|
}
|
|
12034
|
+
function useSpreadsheetCollaboration({ initialContent, onChange, session }) {
|
|
12035
|
+
const sessionRef = useRef(session);
|
|
12036
|
+
if (sessionRef.current !== session) throw new Error('SpreadsheetEditor collaboration sessions cannot be replaced while mounted. Remount the editor for another shared workbook.');
|
|
12037
|
+
const viewStateRef = useRef(spreadsheetCollaborationViewState(initialContent));
|
|
12038
|
+
const [content, setContent] = useState(()=>spreadsheetContentWithCollaborationViewState(readWorkOfficeSpreadsheetCollaboration(session), viewStateRef.current));
|
|
12039
|
+
const contentRef = useRef(content);
|
|
12040
|
+
const bindingRef = useRef(void 0);
|
|
12041
|
+
const [historyRevision, refreshHistory] = useState(0);
|
|
12042
|
+
const onChangeRef = useRef(onChange);
|
|
12043
|
+
onChangeRef.current = onChange;
|
|
12044
|
+
contentRef.current = content;
|
|
12045
|
+
useEffect(()=>{
|
|
12046
|
+
const binding = createWorkOfficeSpreadsheetCollaborationBinding(session);
|
|
12047
|
+
bindingRef.current = binding;
|
|
12048
|
+
const project = (sharedContent)=>{
|
|
12049
|
+
const projected = spreadsheetContentWithCollaborationViewState(sharedContent, viewStateRef.current);
|
|
12050
|
+
contentRef.current = projected;
|
|
12051
|
+
setContent(projected);
|
|
12052
|
+
return projected;
|
|
12053
|
+
};
|
|
12054
|
+
const unsubscribeContent = binding.subscribe(({ content: next })=>{
|
|
12055
|
+
onChangeRef.current(project(next));
|
|
12056
|
+
});
|
|
12057
|
+
const unsubscribeError = binding.subscribeError((error)=>{
|
|
12058
|
+
queueMicrotask(()=>{
|
|
12059
|
+
throw error;
|
|
12060
|
+
});
|
|
12061
|
+
});
|
|
12062
|
+
const unsubscribeHistory = binding.subscribeHistory(()=>refreshHistory((value)=>value + 1));
|
|
12063
|
+
project(binding.content());
|
|
12064
|
+
return ()=>{
|
|
12065
|
+
unsubscribeContent();
|
|
12066
|
+
unsubscribeError();
|
|
12067
|
+
unsubscribeHistory();
|
|
12068
|
+
if (bindingRef.current === binding) bindingRef.current = void 0;
|
|
12069
|
+
binding.destroy();
|
|
12070
|
+
};
|
|
12071
|
+
}, [
|
|
12072
|
+
session
|
|
12073
|
+
]);
|
|
12074
|
+
const commit = useCallback((next)=>{
|
|
12075
|
+
updateSpreadsheetCollaborationViewState(viewStateRef.current, next);
|
|
12076
|
+
const previous = contentRef.current;
|
|
12077
|
+
const binding = bindingRef.current;
|
|
12078
|
+
if (binding?.replace(previous, next)) {
|
|
12079
|
+
contentRef.current = spreadsheetContentWithCollaborationViewState(binding.content(), viewStateRef.current);
|
|
12080
|
+
return;
|
|
12081
|
+
}
|
|
12082
|
+
const projected = spreadsheetContentWithCollaborationViewState(binding?.content() ?? previous, viewStateRef.current);
|
|
12083
|
+
contentRef.current = projected;
|
|
12084
|
+
setContent(projected);
|
|
12085
|
+
}, []);
|
|
12086
|
+
const view = useMemo(()=>({
|
|
12087
|
+
activateSheet: (sheetId)=>{
|
|
12088
|
+
viewStateRef.current.activeSheetId = sheetId;
|
|
12089
|
+
},
|
|
12090
|
+
select: (sheetId, selection)=>{
|
|
12091
|
+
viewStateRef.current.selections.set(sheetId, finiteSpreadsheetSelection(selection));
|
|
12092
|
+
},
|
|
12093
|
+
setZoom: (sheetId, zoomRatio)=>{
|
|
12094
|
+
viewStateRef.current.zoomBySheet.set(sheetId, zoomRatio);
|
|
12095
|
+
}
|
|
12096
|
+
}), []);
|
|
12097
|
+
const history = useMemo(()=>({
|
|
12098
|
+
canRedo: bindingRef.current?.canRedo() ?? false,
|
|
12099
|
+
canUndo: bindingRef.current?.canUndo() ?? false,
|
|
12100
|
+
redo: ()=>bindingRef.current?.redo() ?? false,
|
|
12101
|
+
undo: ()=>bindingRef.current?.undo() ?? false
|
|
12102
|
+
}), [
|
|
12103
|
+
historyRevision
|
|
12104
|
+
]);
|
|
12105
|
+
return {
|
|
12106
|
+
content,
|
|
12107
|
+
history,
|
|
12108
|
+
onChange: commit,
|
|
12109
|
+
readOnly: 'edit' !== session.mode,
|
|
12110
|
+
view
|
|
12111
|
+
};
|
|
12112
|
+
}
|
|
12113
|
+
function spreadsheetCollaborationViewState(content) {
|
|
12114
|
+
const selections = new Map();
|
|
12115
|
+
const zoomBySheet = new Map();
|
|
12116
|
+
for (const sheet of content.sheets){
|
|
12117
|
+
if (!sheet.id) continue;
|
|
12118
|
+
const selection = sheet.luckysheet_select_save?.at(-1);
|
|
12119
|
+
if (selection) selections.set(sheet.id, finiteSpreadsheetSelection(selection));
|
|
12120
|
+
if (void 0 !== sheet.zoomRatio) zoomBySheet.set(sheet.id, sheet.zoomRatio);
|
|
12121
|
+
}
|
|
12122
|
+
return {
|
|
12123
|
+
activeSheetId: content.sheets.find((sheet)=>1 === sheet.status)?.id ?? content.sheets.find((sheet)=>1 !== sheet.hide)?.id,
|
|
12124
|
+
selections,
|
|
12125
|
+
zoomBySheet
|
|
12126
|
+
};
|
|
12127
|
+
}
|
|
12128
|
+
function updateSpreadsheetCollaborationViewState(view, content) {
|
|
12129
|
+
pruneSpreadsheetCollaborationViewState(view, content);
|
|
12130
|
+
const active = content.sheets.find((sheet)=>1 === sheet.status);
|
|
12131
|
+
if (active?.id) view.activeSheetId = active.id;
|
|
12132
|
+
for (const sheet of content.sheets){
|
|
12133
|
+
if (!sheet.id) continue;
|
|
12134
|
+
const selection = sheet.luckysheet_select_save?.at(-1);
|
|
12135
|
+
if (selection) view.selections.set(sheet.id, finiteSpreadsheetSelection(selection));
|
|
12136
|
+
if (void 0 !== sheet.zoomRatio) view.zoomBySheet.set(sheet.id, sheet.zoomRatio);
|
|
12137
|
+
}
|
|
12138
|
+
}
|
|
12139
|
+
function spreadsheetContentWithCollaborationViewState(content, view) {
|
|
12140
|
+
pruneSpreadsheetCollaborationViewState(view, content);
|
|
12141
|
+
const visibleIds = new Set(content.sheets.filter((sheet)=>1 !== sheet.hide && sheet.id).map((sheet)=>sheet.id));
|
|
12142
|
+
const activeSheetId = (view.activeSheetId && visibleIds.has(view.activeSheetId) ? view.activeSheetId : content.sheets.find((sheet)=>1 !== sheet.hide)?.id) ?? content.sheets[0]?.id;
|
|
12143
|
+
if (activeSheetId) view.activeSheetId = activeSheetId;
|
|
12144
|
+
return {
|
|
12145
|
+
...content,
|
|
12146
|
+
sheets: content.sheets.map((sheet)=>{
|
|
12147
|
+
const id = sheet.id;
|
|
12148
|
+
const selection = id ? view.selections.get(id) : void 0;
|
|
12149
|
+
const zoomRatio = id ? view.zoomBySheet.get(id) : void 0;
|
|
12150
|
+
return {
|
|
12151
|
+
...sheet,
|
|
12152
|
+
status: id === activeSheetId ? 1 : 0,
|
|
12153
|
+
...selection ? {
|
|
12154
|
+
luckysheet_select_save: [
|
|
12155
|
+
selection
|
|
12156
|
+
]
|
|
12157
|
+
} : {},
|
|
12158
|
+
...void 0 === zoomRatio ? {} : {
|
|
12159
|
+
zoomRatio
|
|
12160
|
+
}
|
|
12161
|
+
};
|
|
12162
|
+
})
|
|
12163
|
+
};
|
|
12164
|
+
}
|
|
12165
|
+
function pruneSpreadsheetCollaborationViewState(view, content) {
|
|
12166
|
+
const sheetIds = new Set(content.sheets.flatMap((sheet)=>sheet.id ? [
|
|
12167
|
+
sheet.id
|
|
12168
|
+
] : []));
|
|
12169
|
+
for (const sheetId of view.selections.keys())if (!sheetIds.has(sheetId)) view.selections.delete(sheetId);
|
|
12170
|
+
for (const sheetId of view.zoomBySheet.keys())if (!sheetIds.has(sheetId)) view.zoomBySheet.delete(sheetId);
|
|
12171
|
+
}
|
|
9624
12172
|
const spreadsheetFocusRetryFrames = 12;
|
|
9625
12173
|
const spreadsheetFocusObservationMs = 5000;
|
|
9626
12174
|
const spreadsheetFocusCleanups = new WeakMap();
|
|
9627
|
-
function SpreadsheetEditor(
|
|
12175
|
+
function SpreadsheetEditor(props) {
|
|
12176
|
+
if (props.collaboration) return /*#__PURE__*/ jsx(CollaborativeSpreadsheetEditor, {
|
|
12177
|
+
...props,
|
|
12178
|
+
collaboration: props.collaboration
|
|
12179
|
+
});
|
|
12180
|
+
return /*#__PURE__*/ jsx(SpreadsheetEditorSurface, {
|
|
12181
|
+
...props
|
|
12182
|
+
});
|
|
12183
|
+
}
|
|
12184
|
+
function CollaborativeSpreadsheetEditor(props) {
|
|
12185
|
+
const { collaboration } = props;
|
|
12186
|
+
const shared = useSpreadsheetCollaboration({
|
|
12187
|
+
initialContent: props.content,
|
|
12188
|
+
onChange: props.onChange,
|
|
12189
|
+
session: collaboration
|
|
12190
|
+
});
|
|
12191
|
+
return /*#__PURE__*/ jsx(SpreadsheetEditorSurface, {
|
|
12192
|
+
...props,
|
|
12193
|
+
content: shared.content,
|
|
12194
|
+
collaborationHistory: shared.history,
|
|
12195
|
+
collaborationView: shared.view,
|
|
12196
|
+
onChange: shared.onChange,
|
|
12197
|
+
preview: props.preview || shared.readOnly
|
|
12198
|
+
});
|
|
12199
|
+
}
|
|
12200
|
+
function SpreadsheetEditorSurface({ autoFocus = true, content, collaborationHistory, collaborationView, kernelWasmUrl, preview, saveStatus = '已自动保存', fileActions, onChange, onAgentRequest }) {
|
|
9628
12201
|
const materializedContent = useMemo(()=>refreshSpreadsheetPivotTables(content), [
|
|
9629
12202
|
content
|
|
9630
12203
|
]);
|
|
@@ -9633,6 +12206,7 @@ function SpreadsheetEditor({ content, kernelWasmUrl, preview, saveStatus = '已
|
|
|
9633
12206
|
const previewRef = useRef(preview);
|
|
9634
12207
|
const spreadsheetRootRef = useRef(null);
|
|
9635
12208
|
const spreadsheetCanvasRef = useRef(null);
|
|
12209
|
+
const editorFocusOrigin = useOfficeEditorFocusOrigin();
|
|
9636
12210
|
const workbookRef = useRef(null);
|
|
9637
12211
|
const spreadsheetZoomRef = useRef(100);
|
|
9638
12212
|
const [workbookInstance, setWorkbookInstance] = useState(null);
|
|
@@ -9651,6 +12225,7 @@ function SpreadsheetEditor({ content, kernelWasmUrl, preview, saveStatus = '已
|
|
|
9651
12225
|
const [panel, setPanel] = useState(null);
|
|
9652
12226
|
const panelTriggerRef = useRef(null);
|
|
9653
12227
|
const [selectionState, setSelectionState] = useState(null);
|
|
12228
|
+
const formatPainterSelectionHandlerRef = useRef((_sheetId, _selection)=>void 0);
|
|
9654
12229
|
const [contextMenu, setContextMenu] = useState(null);
|
|
9655
12230
|
const officeDialog = useOfficeDialog();
|
|
9656
12231
|
const [findOpen, setFindOpen] = useState(false);
|
|
@@ -9663,14 +12238,15 @@ function SpreadsheetEditor({ content, kernelWasmUrl, preview, saveStatus = '已
|
|
|
9663
12238
|
const focusedSheetIdRef = useRef(null);
|
|
9664
12239
|
contentRef.current = materializedContent;
|
|
9665
12240
|
previewRef.current = preview;
|
|
9666
|
-
const
|
|
12241
|
+
const controlledHistory = useOfficeHistory({
|
|
9667
12242
|
content,
|
|
9668
12243
|
onChange: (next)=>{
|
|
9669
12244
|
const liveSelection = workbookRef.current?.getSelection()?.at(-1);
|
|
9670
12245
|
onChange(spreadsheetContentWithSelection(next, selectionState?.sheetId ?? activeSheetIdRef.current, liveSelection ?? selectionState?.selection));
|
|
9671
12246
|
},
|
|
9672
|
-
sameValue: sameSpreadsheetHistoryContent
|
|
12247
|
+
sameValue: collaborationHistory ? ignoreSpreadsheetControlledHistory : sameSpreadsheetHistoryContent
|
|
9673
12248
|
});
|
|
12249
|
+
const history = collaborationHistory ?? controlledHistory;
|
|
9674
12250
|
const conditionalStylesBySheet = useMemo(()=>new Map(materializedContent.sheets.flatMap((sheet)=>sheet.id ? [
|
|
9675
12251
|
[
|
|
9676
12252
|
sheet.id,
|
|
@@ -9691,12 +12267,23 @@ function SpreadsheetEditor({ content, kernelWasmUrl, preview, saveStatus = '已
|
|
|
9691
12267
|
activeSheetId
|
|
9692
12268
|
]);
|
|
9693
12269
|
useEffect(()=>{
|
|
9694
|
-
if (!activeSheetId || focusedSheetIdRef.current === activeSheetId) return;
|
|
12270
|
+
if (preview || !activeSheetId || focusedSheetIdRef.current === activeSheetId) return;
|
|
12271
|
+
const initialFocus = null === focusedSheetIdRef.current;
|
|
12272
|
+
if (initialFocus && !autoFocus) {
|
|
12273
|
+
focusedSheetIdRef.current = activeSheetId;
|
|
12274
|
+
return;
|
|
12275
|
+
}
|
|
9695
12276
|
focusedSheetIdRef.current = activeSheetId;
|
|
9696
|
-
const frame = requestAnimationFrame(()=>focusSpreadsheetGrid(spreadsheetCanvasRef.current
|
|
12277
|
+
const frame = requestAnimationFrame(()=>focusSpreadsheetGrid(spreadsheetCanvasRef.current, {
|
|
12278
|
+
focusOrigin: initialFocus ? editorFocusOrigin : document.activeElement,
|
|
12279
|
+
forceInitial: !initialFocus
|
|
12280
|
+
}));
|
|
9697
12281
|
return ()=>cancelAnimationFrame(frame);
|
|
9698
12282
|
}, [
|
|
9699
|
-
activeSheetId
|
|
12283
|
+
activeSheetId,
|
|
12284
|
+
autoFocus,
|
|
12285
|
+
editorFocusOrigin,
|
|
12286
|
+
preview
|
|
9700
12287
|
]);
|
|
9701
12288
|
useEffect(()=>{
|
|
9702
12289
|
const container = spreadsheetCanvasRef.current;
|
|
@@ -9742,14 +12329,17 @@ function SpreadsheetEditor({ content, kernelWasmUrl, preview, saveStatus = '已
|
|
|
9742
12329
|
const workbookHooks = useMemo(()=>({
|
|
9743
12330
|
afterActivateSheet: (id)=>{
|
|
9744
12331
|
activeSheetIdRef.current = id;
|
|
12332
|
+
collaborationView?.activateSheet(id);
|
|
9745
12333
|
if (previewRef.current) setPreviewActiveSheetId(id);
|
|
9746
12334
|
setSelectionState(null);
|
|
9747
12335
|
},
|
|
9748
12336
|
afterSelectionChange: (sheetId, selection)=>{
|
|
12337
|
+
collaborationView?.select(sheetId, selection);
|
|
9749
12338
|
setSelectionState({
|
|
9750
12339
|
sheetId,
|
|
9751
12340
|
selection
|
|
9752
12341
|
});
|
|
12342
|
+
formatPainterSelectionHandlerRef.current(sheetId, selection);
|
|
9753
12343
|
},
|
|
9754
12344
|
beforeUpdateCell: (row, column)=>{
|
|
9755
12345
|
const sheet = contentRef.current.sheets.find((candidate)=>candidate.id === activeSheetIdRef.current);
|
|
@@ -9782,6 +12372,7 @@ function SpreadsheetEditor({ content, kernelWasmUrl, preview, saveStatus = '已
|
|
|
9782
12372
|
if (cell?.ps) drawSpreadsheetCommentMarker(context, cellInfo);
|
|
9783
12373
|
}
|
|
9784
12374
|
}), [
|
|
12375
|
+
collaborationView,
|
|
9785
12376
|
conditionalStylesBySheet
|
|
9786
12377
|
]);
|
|
9787
12378
|
const conditionalFormatKey = content.sheets.map((sheet)=>`${sheet.id}:${JSON.stringify(sheet.luckysheet_conditionformat_save ?? [])}`).join('|');
|
|
@@ -9842,15 +12433,93 @@ function SpreadsheetEditor({ content, kernelWasmUrl, preview, saveStatus = '已
|
|
|
9842
12433
|
const toolbarSheetId = selectionState?.sheetId ?? activeSheetId;
|
|
9843
12434
|
const toolbarSheet = workbookSheets.find((sheet)=>sheet.id === toolbarSheetId);
|
|
9844
12435
|
const toolbarSelection = finiteSpreadsheetSelection(selectionState?.selection ?? toolbarSheet?.luckysheet_select_save?.at(-1));
|
|
12436
|
+
const spreadsheetPresenceLocation = useMemo(()=>{
|
|
12437
|
+
if (!toolbarSheetId) return null;
|
|
12438
|
+
const liveSelections = workbookRef.current?.getSelection();
|
|
12439
|
+
const ranges = (liveSelections?.length ? liveSelections : [
|
|
12440
|
+
toolbarSelection
|
|
12441
|
+
]).slice(0, 64).map((selection)=>({
|
|
12442
|
+
startRow: Math.min(selection.row[0] ?? 0, selection.row[1] ?? 0),
|
|
12443
|
+
startColumn: Math.min(selection.column[0] ?? 0, selection.column[1] ?? 0),
|
|
12444
|
+
endRow: Math.max(selection.row[0] ?? 0, selection.row[1] ?? 0),
|
|
12445
|
+
endColumn: Math.max(selection.column[0] ?? 0, selection.column[1] ?? 0)
|
|
12446
|
+
}));
|
|
12447
|
+
const activeCell = {
|
|
12448
|
+
row: toolbarSelection.row_focus ?? toolbarSelection.row[0] ?? 0,
|
|
12449
|
+
column: toolbarSelection.column_focus ?? toolbarSelection.column[0] ?? 0
|
|
12450
|
+
};
|
|
12451
|
+
return {
|
|
12452
|
+
kind: 'spreadsheet',
|
|
12453
|
+
sheetId: toolbarSheetId,
|
|
12454
|
+
ranges,
|
|
12455
|
+
activeCell
|
|
12456
|
+
};
|
|
12457
|
+
}, [
|
|
12458
|
+
selectionState,
|
|
12459
|
+
toolbarSelection,
|
|
12460
|
+
toolbarSheetId
|
|
12461
|
+
]);
|
|
12462
|
+
useOfficePublishPresenceLocation(spreadsheetPresenceLocation);
|
|
12463
|
+
useSpreadsheetCollaborationPresenceProjection({
|
|
12464
|
+
content: materializedContent,
|
|
12465
|
+
workbook: workbookInstance
|
|
12466
|
+
});
|
|
9845
12467
|
const toolbarCell = spreadsheetCellAt(toolbarSheet, toolbarSelection.row_focus ?? toolbarSelection.row[0], toolbarSelection.column_focus ?? toolbarSelection.column[0]);
|
|
9846
12468
|
const selectedRange = spreadsheetSingleRange(toolbarSelection);
|
|
9847
12469
|
const multipleCellsSelected = selectedRange.row[0] !== selectedRange.row[1] || selectedRange.column[0] !== selectedRange.column[1];
|
|
9848
12470
|
const selectionSummary = multipleCellsSelected ? spreadsheetSelectionSummary(toolbarSheet, toolbarSelection) : null;
|
|
12471
|
+
const { commandPort: formatPainter, mode: formatPainterMode } = useSpreadsheetFormatPainter({
|
|
12472
|
+
content: materializedContent,
|
|
12473
|
+
editable: !preview,
|
|
12474
|
+
onError: (message)=>showToast(message, 'error'),
|
|
12475
|
+
sourceRange: selectedRange,
|
|
12476
|
+
sourceSheetId: toolbarSheetId,
|
|
12477
|
+
workbook: workbookInstance
|
|
12478
|
+
});
|
|
12479
|
+
const { active: autoFilterActive, commandPort: autoFilter, reserveAltKey: reserveAutoFilterAltKey, status: autoFilterStatus } = useSpreadsheetAutoFilter({
|
|
12480
|
+
canvasRef: spreadsheetCanvasRef,
|
|
12481
|
+
content: materializedContent,
|
|
12482
|
+
editable: !preview,
|
|
12483
|
+
mountRevision: workbookMountRevision,
|
|
12484
|
+
onChange: (next)=>{
|
|
12485
|
+
contentRef.current = next;
|
|
12486
|
+
onChange(next);
|
|
12487
|
+
},
|
|
12488
|
+
selection: toolbarSelection,
|
|
12489
|
+
sheetId: toolbarSheetId,
|
|
12490
|
+
workbook: workbookInstance
|
|
12491
|
+
});
|
|
12492
|
+
const currentClipboardSelection = ()=>{
|
|
12493
|
+
if (previewRef.current) return null;
|
|
12494
|
+
const sheetId = selectionState?.sheetId ?? activeSheetIdRef.current;
|
|
12495
|
+
const sheet = contentRef.current.sheets.find((candidate)=>candidate.id === sheetId);
|
|
12496
|
+
const selection = selectionState?.selection ?? sheet?.luckysheet_select_save?.at(-1);
|
|
12497
|
+
if (!selection) return null;
|
|
12498
|
+
const range = spreadsheetSingleRange(selection);
|
|
12499
|
+
const maximumCells = (range.row[1] - range.row[0] + 1) * (range.column[1] - range.column[0] + 1);
|
|
12500
|
+
return spreadsheetAgentSelection(contentRef.current, sheetId, selection, maximumCells);
|
|
12501
|
+
};
|
|
12502
|
+
const runSpreadsheetClipboardCopy = (cut)=>{
|
|
12503
|
+
const selection = currentClipboardSelection();
|
|
12504
|
+
const commands = spreadsheetCommandsRef.current;
|
|
12505
|
+
if (!selection || cut && !commands) return false;
|
|
12506
|
+
copySpreadsheetSelection(browserSpreadsheetClipboard, selection.clipboard, cut).then((copied)=>{
|
|
12507
|
+
if (copied && cut && !commands?.clearSelectedCells()) showToast('选区已复制,但无法清除原内容。', 'error');
|
|
12508
|
+
});
|
|
12509
|
+
return true;
|
|
12510
|
+
};
|
|
12511
|
+
const runSpreadsheetClipboardPaste = ()=>{
|
|
12512
|
+
const commands = spreadsheetCommandsRef.current;
|
|
12513
|
+
if (!commands) return false;
|
|
12514
|
+
pasteSpreadsheetSelection(browserSpreadsheetClipboard, commands.pasteCells);
|
|
12515
|
+
return true;
|
|
12516
|
+
};
|
|
9849
12517
|
const activateReadOnlySpreadsheetSheet = useCallback((sheetId)=>{
|
|
9850
12518
|
if (!previewRef.current) return false;
|
|
9851
12519
|
const sheet = contentRef.current.sheets.find((candidate)=>candidate.id === sheetId && 1 !== candidate.hide);
|
|
9852
12520
|
if (!sheet) return false;
|
|
9853
12521
|
activeSheetIdRef.current = sheetId;
|
|
12522
|
+
collaborationView?.activateSheet(sheetId);
|
|
9854
12523
|
setSelectionState(null);
|
|
9855
12524
|
setPreviewActiveSheetId(sheetId);
|
|
9856
12525
|
try {
|
|
@@ -9861,11 +12530,22 @@ function SpreadsheetEditor({ content, kernelWasmUrl, preview, saveStatus = '已
|
|
|
9861
12530
|
return false;
|
|
9862
12531
|
}
|
|
9863
12532
|
return true;
|
|
9864
|
-
}, [
|
|
12533
|
+
}, [
|
|
12534
|
+
collaborationView
|
|
12535
|
+
]);
|
|
9865
12536
|
const spreadsheetExtensions = useMemo(createSpreadsheetEditorExtensions, []);
|
|
9866
12537
|
const spreadsheetEditor = useOfficeEditorRuntime({
|
|
9867
12538
|
activeSheetId,
|
|
12539
|
+
autoFilter,
|
|
9868
12540
|
calculation,
|
|
12541
|
+
clipboard: {
|
|
12542
|
+
canCopySelection: !preview && Boolean(toolbarSheet),
|
|
12543
|
+
canCutSelection: !preview && Boolean(toolbarSheet && workbookInstance),
|
|
12544
|
+
canPasteSelection: !preview && Boolean(toolbarSheet && workbookInstance),
|
|
12545
|
+
copySelection: ()=>runSpreadsheetClipboardCopy(false),
|
|
12546
|
+
cutSelection: ()=>runSpreadsheetClipboardCopy(true),
|
|
12547
|
+
pasteSelection: runSpreadsheetClipboardPaste
|
|
12548
|
+
},
|
|
9869
12549
|
content: contentRef.current,
|
|
9870
12550
|
editable: !preview,
|
|
9871
12551
|
fallbackRange: selectedRange,
|
|
@@ -9875,6 +12555,7 @@ function SpreadsheetEditor({ content, kernelWasmUrl, preview, saveStatus = '已
|
|
|
9875
12555
|
if (formulaBar) formulaBar.textContent = null == value ? '' : String(value);
|
|
9876
12556
|
}
|
|
9877
12557
|
},
|
|
12558
|
+
formatPainter,
|
|
9878
12559
|
history,
|
|
9879
12560
|
onChange: (next)=>{
|
|
9880
12561
|
contentRef.current = next;
|
|
@@ -9890,7 +12571,59 @@ function SpreadsheetEditor({ content, kernelWasmUrl, preview, saveStatus = '已
|
|
|
9890
12571
|
}, spreadsheetExtensions);
|
|
9891
12572
|
const spreadsheetCommands = spreadsheetEditor.commands;
|
|
9892
12573
|
spreadsheetCommandsRef.current = spreadsheetCommands;
|
|
12574
|
+
formatPainterSelectionHandlerRef.current = (sheetId, selection)=>{
|
|
12575
|
+
spreadsheetCommandsRef.current?.applyFormatPainter({
|
|
12576
|
+
sheetId,
|
|
12577
|
+
selection
|
|
12578
|
+
});
|
|
12579
|
+
};
|
|
9893
12580
|
const spreadsheetCan = spreadsheetEditor.can();
|
|
12581
|
+
const navigateToSpreadsheetParticipant = useCallback((participant)=>{
|
|
12582
|
+
const location = participant.location;
|
|
12583
|
+
const workbook = workbookRef.current;
|
|
12584
|
+
if (!workbook || location?.kind !== 'spreadsheet') return false;
|
|
12585
|
+
const sheet = materializedContent.sheets.find((candidate)=>candidate.id === location.sheetId && 1 !== candidate.hide);
|
|
12586
|
+
if (!sheet) return false;
|
|
12587
|
+
const ranges = location.ranges.filter((range)=>spreadsheetPresenceRangeExists(sheet, range)).map((range)=>({
|
|
12588
|
+
row: [
|
|
12589
|
+
range.startRow,
|
|
12590
|
+
range.endRow
|
|
12591
|
+
],
|
|
12592
|
+
column: [
|
|
12593
|
+
range.startColumn,
|
|
12594
|
+
range.endColumn
|
|
12595
|
+
]
|
|
12596
|
+
}));
|
|
12597
|
+
if (!ranges.length) return false;
|
|
12598
|
+
const activeCell = location.activeCell ?? {
|
|
12599
|
+
row: ranges[0]?.row[0] ?? 0,
|
|
12600
|
+
column: ranges[0]?.column[0] ?? 0
|
|
12601
|
+
};
|
|
12602
|
+
if (!spreadsheetPresenceCellExists(sheet, activeCell)) return false;
|
|
12603
|
+
try {
|
|
12604
|
+
activeSheetIdRef.current = location.sheetId;
|
|
12605
|
+
collaborationView?.activateSheet(location.sheetId);
|
|
12606
|
+
if (previewRef.current) setPreviewActiveSheetId(location.sheetId);
|
|
12607
|
+
workbook.activateSheet({
|
|
12608
|
+
id: location.sheetId
|
|
12609
|
+
});
|
|
12610
|
+
workbook.setSelection(ranges, {
|
|
12611
|
+
id: location.sheetId
|
|
12612
|
+
});
|
|
12613
|
+
workbook.scroll({
|
|
12614
|
+
targetRow: activeCell.row,
|
|
12615
|
+
targetColumn: activeCell.column
|
|
12616
|
+
});
|
|
12617
|
+
} catch {
|
|
12618
|
+
return false;
|
|
12619
|
+
}
|
|
12620
|
+
requestAnimationFrame(()=>focusSpreadsheetGrid(spreadsheetCanvasRef.current));
|
|
12621
|
+
return true;
|
|
12622
|
+
}, [
|
|
12623
|
+
collaborationView,
|
|
12624
|
+
materializedContent.sheets
|
|
12625
|
+
]);
|
|
12626
|
+
useOfficeCollaborationLocationNavigator(navigateToSpreadsheetParticipant);
|
|
9894
12627
|
const restoreSpreadsheetGridFocus = useCallback(()=>focusSpreadsheetGrid(spreadsheetCanvasRef.current), []);
|
|
9895
12628
|
const openSpreadsheetFind = useCallback(()=>{
|
|
9896
12629
|
setFindOpen(true);
|
|
@@ -9938,6 +12671,8 @@ function SpreadsheetEditor({ content, kernelWasmUrl, preview, saveStatus = '已
|
|
|
9938
12671
|
const next = stepOfficeZoom(current, direction);
|
|
9939
12672
|
if (next === current) return;
|
|
9940
12673
|
spreadsheetZoomRef.current = next;
|
|
12674
|
+
const sheetId = activeSheetIdRef.current;
|
|
12675
|
+
if (sheetId) collaborationView?.setZoom(sheetId, next / 100);
|
|
9941
12676
|
if (previewRef.current) setPreviewZoom(next);
|
|
9942
12677
|
else spreadsheetCommandsRef.current?.setZoom(next);
|
|
9943
12678
|
};
|
|
@@ -9949,17 +12684,12 @@ function SpreadsheetEditor({ content, kernelWasmUrl, preview, saveStatus = '已
|
|
|
9949
12684
|
const handleSpreadsheetEditingEscape = (event)=>{
|
|
9950
12685
|
if ('Escape' === event.key && isSpreadsheetCellEditingTarget(event.target)) requestAnimationFrame(()=>focusSpreadsheetGrid(spreadsheetCanvasRef.current));
|
|
9951
12686
|
};
|
|
9952
|
-
const currentClipboardSelection = ()=>{
|
|
9953
|
-
if (previewRef.current) return null;
|
|
9954
|
-
const sheetId = selectionState?.sheetId ?? activeSheetIdRef.current;
|
|
9955
|
-
const sheet = contentRef.current.sheets.find((candidate)=>candidate.id === sheetId);
|
|
9956
|
-
const selection = selectionState?.selection ?? sheet?.luckysheet_select_save?.at(-1);
|
|
9957
|
-
if (!selection) return null;
|
|
9958
|
-
const range = spreadsheetSingleRange(selection);
|
|
9959
|
-
const maximumCells = (range.row[1] - range.row[0] + 1) * (range.column[1] - range.column[0] + 1);
|
|
9960
|
-
return spreadsheetAgentSelection(contentRef.current, sheetId, selection, maximumCells);
|
|
9961
|
-
};
|
|
9962
12687
|
const handleSpreadsheetKeyDownCapture = (event)=>{
|
|
12688
|
+
if ('Alt' === event.key && !event.repeat && event.target instanceof Element && event.target.closest('.fortune-sheet-overlay') && reserveAutoFilterAltKey()) {
|
|
12689
|
+
event.preventDefault();
|
|
12690
|
+
event.stopPropagation();
|
|
12691
|
+
return;
|
|
12692
|
+
}
|
|
9963
12693
|
if ((event.metaKey || event.ctrlKey) && !event.altKey && !event.shiftKey && 'f' === event.key.toLocaleLowerCase()) {
|
|
9964
12694
|
event.preventDefault();
|
|
9965
12695
|
event.stopPropagation();
|
|
@@ -9967,14 +12697,6 @@ function SpreadsheetEditor({ content, kernelWasmUrl, preview, saveStatus = '已
|
|
|
9967
12697
|
return;
|
|
9968
12698
|
}
|
|
9969
12699
|
handleSpreadsheetEditingEscape(event);
|
|
9970
|
-
const handled = runSpreadsheetClipboardShortcut(event.nativeEvent, {
|
|
9971
|
-
clipboard: browserSpreadsheetClipboard,
|
|
9972
|
-
clearSelectedCells: spreadsheetCommands.clearSelectedCells,
|
|
9973
|
-
pasteCells: spreadsheetCommands.pasteCells,
|
|
9974
|
-
readSelectionText: ()=>currentClipboardSelection()?.clipboard ?? null,
|
|
9975
|
-
restoreFocus: restoreSpreadsheetGridFocus
|
|
9976
|
-
});
|
|
9977
|
-
if (handled) event.stopPropagation();
|
|
9978
12700
|
};
|
|
9979
12701
|
const handleSpreadsheetCopy = (event, cut)=>{
|
|
9980
12702
|
if (isSpreadsheetNativeTextUndoTarget(event.target)) return;
|
|
@@ -10051,6 +12773,9 @@ function SpreadsheetEditor({ content, kernelWasmUrl, preview, saveStatus = '已
|
|
|
10051
12773
|
return /*#__PURE__*/ jsxs("section", {
|
|
10052
12774
|
ref: spreadsheetRootRef,
|
|
10053
12775
|
className: `work-spreadsheet-editor ${preview ? 'preview' : ''}`,
|
|
12776
|
+
"data-auto-filter": autoFilterActive ? 'active' : void 0,
|
|
12777
|
+
"data-format-painter": formatPainterMode ?? void 0,
|
|
12778
|
+
"data-freeze-panes": toolbarSheet?.frozen ? 'active' : void 0,
|
|
10054
12779
|
"aria-label": "表格工作区",
|
|
10055
12780
|
onKeyDownCapture: handleSpreadsheetKeyDownCapture,
|
|
10056
12781
|
onCopyCapture: (event)=>handleSpreadsheetCopy(event, false),
|
|
@@ -10066,13 +12791,16 @@ function SpreadsheetEditor({ content, kernelWasmUrl, preview, saveStatus = '已
|
|
|
10066
12791
|
}),
|
|
10067
12792
|
!preview && /*#__PURE__*/ jsx(SpreadsheetEditorRibbon, {
|
|
10068
12793
|
activeTab: ribbonTab,
|
|
12794
|
+
autoFilterActive: autoFilterActive,
|
|
10069
12795
|
can: spreadsheetCan,
|
|
10070
12796
|
commands: spreadsheetRibbonCommands,
|
|
10071
12797
|
content: content,
|
|
10072
12798
|
fileActions: fileActions,
|
|
10073
12799
|
findOpen: findOpen,
|
|
12800
|
+
formatPainterMode: formatPainterMode,
|
|
12801
|
+
freezePanesActive: Boolean(toolbarSheet?.frozen),
|
|
12802
|
+
freezePanesSelection: toolbarSelection,
|
|
10074
12803
|
gridLinesVisible: gridLinesVisible,
|
|
10075
|
-
multipleCellsSelected: multipleCellsSelected,
|
|
10076
12804
|
panelId: panelId,
|
|
10077
12805
|
onOpenFind: openSpreadsheetFind,
|
|
10078
12806
|
onTabChange: (tab)=>{
|
|
@@ -10087,6 +12815,16 @@ function SpreadsheetEditor({ content, kernelWasmUrl, preview, saveStatus = '已
|
|
|
10087
12815
|
panel: panel,
|
|
10088
12816
|
toolbarCell: toolbarCell
|
|
10089
12817
|
}),
|
|
12818
|
+
/*#__PURE__*/ jsx("output", {
|
|
12819
|
+
className: "sr-only",
|
|
12820
|
+
"aria-live": "polite",
|
|
12821
|
+
"aria-atomic": "true",
|
|
12822
|
+
children: [
|
|
12823
|
+
spreadsheetFormatPainterStatus(formatPainterMode),
|
|
12824
|
+
autoFilterStatus,
|
|
12825
|
+
spreadsheetFreezePanesStatus(toolbarSheet?.frozen)
|
|
12826
|
+
].filter(Boolean).join(' ')
|
|
12827
|
+
}),
|
|
10090
12828
|
/*#__PURE__*/ jsxs("div", {
|
|
10091
12829
|
className: "work-spreadsheet-workspace",
|
|
10092
12830
|
children: [
|
|
@@ -10184,6 +12922,8 @@ function SpreadsheetEditor({ content, kernelWasmUrl, preview, saveStatus = '已
|
|
|
10184
12922
|
outputLabel: "表格缩放比例",
|
|
10185
12923
|
sliderLabel: "表格缩放",
|
|
10186
12924
|
onChange: (nextZoom)=>{
|
|
12925
|
+
const sheetId = activeSheetIdRef.current;
|
|
12926
|
+
if (sheetId) collaborationView?.setZoom(sheetId, nextZoom / 100);
|
|
10187
12927
|
if (preview) setPreviewZoom(nextZoom);
|
|
10188
12928
|
else spreadsheetCommands.setZoom(nextZoom);
|
|
10189
12929
|
}
|
|
@@ -10255,24 +12995,36 @@ function SpreadsheetEditor({ content, kernelWasmUrl, preview, saveStatus = '已
|
|
|
10255
12995
|
]
|
|
10256
12996
|
});
|
|
10257
12997
|
}
|
|
10258
|
-
function focusSpreadsheetGrid(container) {
|
|
12998
|
+
function focusSpreadsheetGrid(container, { focusOrigin = document.activeElement, forceInitial = true } = {}) {
|
|
10259
12999
|
if (!container) return;
|
|
10260
13000
|
spreadsheetFocusCleanups.get(container)?.();
|
|
10261
13001
|
let remainingFrames = spreadsheetFocusRetryFrames;
|
|
10262
13002
|
let lastFocusedTarget = null;
|
|
10263
|
-
const commandTrigger =
|
|
13003
|
+
const commandTrigger = focusOrigin;
|
|
10264
13004
|
const initialFocusTarget = spreadsheetGridFocusTarget(container);
|
|
10265
13005
|
const initialFocusTargetReady = spreadsheetGridFocusTargetReady(initialFocusTarget);
|
|
10266
13006
|
let focusObserver = null;
|
|
10267
13007
|
let focusObservationTimeout = null;
|
|
10268
13008
|
let focusOutHandler = null;
|
|
13009
|
+
let pointerDownHandler = null;
|
|
13010
|
+
let tabKeyHandler = null;
|
|
13011
|
+
let focusRestorationStopped = false;
|
|
10269
13012
|
const stopObservingFocusTarget = ()=>{
|
|
13013
|
+
focusRestorationStopped = true;
|
|
10270
13014
|
focusObserver?.disconnect();
|
|
10271
13015
|
focusObserver = null;
|
|
10272
13016
|
if (focusOutHandler) {
|
|
10273
13017
|
container.removeEventListener('focusout', focusOutHandler);
|
|
10274
13018
|
focusOutHandler = null;
|
|
10275
13019
|
}
|
|
13020
|
+
if (pointerDownHandler) {
|
|
13021
|
+
document.removeEventListener('pointerdown', pointerDownHandler, true);
|
|
13022
|
+
pointerDownHandler = null;
|
|
13023
|
+
}
|
|
13024
|
+
if (tabKeyHandler) {
|
|
13025
|
+
document.removeEventListener('keydown', tabKeyHandler, true);
|
|
13026
|
+
tabKeyHandler = null;
|
|
13027
|
+
}
|
|
10276
13028
|
if (null !== focusObservationTimeout) {
|
|
10277
13029
|
window.clearTimeout(focusObservationTimeout);
|
|
10278
13030
|
focusObservationTimeout = null;
|
|
@@ -10280,6 +13032,7 @@ function focusSpreadsheetGrid(container) {
|
|
|
10280
13032
|
if (spreadsheetFocusCleanups.get(container) === stopObservingFocusTarget) spreadsheetFocusCleanups.delete(container);
|
|
10281
13033
|
};
|
|
10282
13034
|
const restoreFocus = (force)=>{
|
|
13035
|
+
if (focusRestorationStopped) return;
|
|
10283
13036
|
const activeElement = document.activeElement;
|
|
10284
13037
|
if (!force && isSpreadsheetCellEditingTarget(activeElement)) return void stopObservingFocusTarget();
|
|
10285
13038
|
if (!force && activeElement !== document.body && activeElement !== document.documentElement && activeElement !== commandTrigger && activeElement !== lastFocusedTarget) return void stopObservingFocusTarget();
|
|
@@ -10299,6 +13052,14 @@ function focusSpreadsheetGrid(container) {
|
|
|
10299
13052
|
requestAnimationFrame(()=>restoreFocus(false));
|
|
10300
13053
|
};
|
|
10301
13054
|
container.addEventListener('focusout', focusOutHandler);
|
|
13055
|
+
pointerDownHandler = (event)=>{
|
|
13056
|
+
if (event.target instanceof Node && !container.contains(event.target)) stopObservingFocusTarget();
|
|
13057
|
+
};
|
|
13058
|
+
tabKeyHandler = (event)=>{
|
|
13059
|
+
if ('Tab' === event.key) stopObservingFocusTarget();
|
|
13060
|
+
};
|
|
13061
|
+
document.addEventListener('pointerdown', pointerDownHandler, true);
|
|
13062
|
+
document.addEventListener('keydown', tabKeyHandler, true);
|
|
10302
13063
|
if ("u" > typeof MutationObserver) {
|
|
10303
13064
|
focusObserver = new MutationObserver(()=>{
|
|
10304
13065
|
const focusTarget = spreadsheetGridFocusTarget(container);
|
|
@@ -10319,7 +13080,7 @@ function focusSpreadsheetGrid(container) {
|
|
|
10319
13080
|
}
|
|
10320
13081
|
focusObservationTimeout = window.setTimeout(stopObservingFocusTarget, spreadsheetFocusObservationMs);
|
|
10321
13082
|
spreadsheetFocusCleanups.set(container, stopObservingFocusTarget);
|
|
10322
|
-
restoreFocus(
|
|
13083
|
+
restoreFocus(forceInitial);
|
|
10323
13084
|
}
|
|
10324
13085
|
function spreadsheetCommandsWithGridFocus(commands, restoreFocus) {
|
|
10325
13086
|
const afterSuccessfulCommand = (command)=>(...args)=>{
|
|
@@ -10329,13 +13090,31 @@ function spreadsheetCommandsWithGridFocus(commands, restoreFocus) {
|
|
|
10329
13090
|
};
|
|
10330
13091
|
return {
|
|
10331
13092
|
...commands,
|
|
13093
|
+
activateFormatPainter: afterSuccessfulCommand(commands.activateFormatPainter),
|
|
13094
|
+
cancelFormatPainter: afterSuccessfulCommand(commands.cancelFormatPainter),
|
|
13095
|
+
clearSelectedCells: afterSuccessfulCommand(commands.clearSelectedCells),
|
|
13096
|
+
copySelection: afterSuccessfulCommand(commands.copySelection),
|
|
13097
|
+
cutSelection: afterSuccessfulCommand(commands.cutSelection),
|
|
13098
|
+
deleteSelectedStructure: afterSuccessfulCommand(commands.deleteSelectedStructure),
|
|
13099
|
+
insertSelectedStructure: afterSuccessfulCommand(commands.insertSelectedStructure),
|
|
13100
|
+
mergeSelectedCells: afterSuccessfulCommand(commands.mergeSelectedCells),
|
|
13101
|
+
pasteSelection: afterSuccessfulCommand(commands.pasteSelection),
|
|
10332
13102
|
redo: afterSuccessfulCommand(commands.redo),
|
|
10333
13103
|
setCellFormat: afterSuccessfulCommand(commands.setCellFormat),
|
|
13104
|
+
setFreezePanes: afterSuccessfulCommand(commands.setFreezePanes),
|
|
10334
13105
|
setGridLines: afterSuccessfulCommand(commands.setGridLines),
|
|
10335
|
-
|
|
13106
|
+
toggleAutoFilter: afterSuccessfulCommand(commands.toggleAutoFilter),
|
|
10336
13107
|
undo: afterSuccessfulCommand(commands.undo)
|
|
10337
13108
|
};
|
|
10338
13109
|
}
|
|
13110
|
+
function ignoreSpreadsheetControlledHistory() {
|
|
13111
|
+
return true;
|
|
13112
|
+
}
|
|
13113
|
+
function spreadsheetFormatPainterStatus(mode) {
|
|
13114
|
+
if ('locked' === mode) return '格式刷已锁定,可连续选择目标区域;再次点击格式刷或按 Escape 退出。';
|
|
13115
|
+
if ('once' === mode) return '格式刷已开启,请选择一个目标区域;按 Escape 退出。';
|
|
13116
|
+
return '';
|
|
13117
|
+
}
|
|
10339
13118
|
function spreadsheetGridFocusTarget(container) {
|
|
10340
13119
|
return container?.querySelector('.fortune-sheet-overlay') ?? container?.querySelector('.fortune-cell-area') ?? null;
|
|
10341
13120
|
}
|
|
@@ -10390,6 +13169,20 @@ function spreadsheetGridFocusTargetReady(target) {
|
|
|
10390
13169
|
const bounds = target.getBoundingClientRect();
|
|
10391
13170
|
return bounds.width > 0 && bounds.height > 0;
|
|
10392
13171
|
}
|
|
13172
|
+
function spreadsheetPresenceRangeExists(sheet, range) {
|
|
13173
|
+
const { columns, rows } = spreadsheetPresenceSheetSize(sheet);
|
|
13174
|
+
return range.startRow >= 0 && range.startColumn >= 0 && range.endRow < rows && range.endColumn < columns;
|
|
13175
|
+
}
|
|
13176
|
+
function spreadsheetPresenceCellExists(sheet, cell) {
|
|
13177
|
+
const { columns, rows } = spreadsheetPresenceSheetSize(sheet);
|
|
13178
|
+
return cell.row >= 0 && cell.column >= 0 && cell.row < rows && cell.column < columns;
|
|
13179
|
+
}
|
|
13180
|
+
function spreadsheetPresenceSheetSize(sheet) {
|
|
13181
|
+
return {
|
|
13182
|
+
rows: Math.max(sheet.row ?? 60, sheet.data?.length ?? 0),
|
|
13183
|
+
columns: Math.max(sheet.column ?? 26, sheet.data?.reduce((maximum, row)=>Math.max(maximum, row?.length ?? 0), 0) ?? 0)
|
|
13184
|
+
};
|
|
13185
|
+
}
|
|
10393
13186
|
function spreadsheetSelectionSummaryText(summary) {
|
|
10394
13187
|
const parts = [
|
|
10395
13188
|
`计数 ${summary.nonEmptyCount}`
|