@a3s-lab/office 0.20.0 → 0.22.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.
@@ -1,10 +1,10 @@
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 { AArrowDown, AArrowUp, AlignCenter, AlignLeft, AlignRight, AlignVerticalJustifyCenter, AlignVerticalJustifyEnd, AlignVerticalJustifyStart, ArrowDown, ArrowDownToLine, ArrowLeft, ArrowLeftToLine, ArrowRight, ArrowRightToLine, ArrowUp, ArrowUpToLine, BadgeJapaneseYen, BarChart3, BetweenHorizontalEnd, BetweenHorizontalStart, BetweenVerticalEnd, BetweenVerticalStart, Bold, Bookmark, Calculator, Check, ChevronDown, ChevronLeft, ChevronRight, ClipboardPaste, Cloud, Columns3, Copy, CopyPlus, DecimalsArrowLeft, DecimalsArrowRight, Eraser, Eye, EyeOff, FileX2, Globe2, Grid2X2, Grid3X3, Hash, Italic, KeyRound, Layers2, Link2, Link2Off, ListChecks, ListFilter, LocateFixed, Merge, MessageSquareX, MoveHorizontal, MoveVertical, Paintbrush, Palette, PanelLeft, PanelTop, PanelsTopLeft, Pencil, Percent, Plus, Printer, Redo2, RefreshCw, Rows3, Save, Scissors, Search, Settings2, ShieldCheck, Sigma, SortAsc, SortDesc, Strikethrough, SwatchBook, Table2, TableProperties, Trash2, Underline, Undo2, WrapText, X } from "lucide-react";
4
+ import { AArrowDown, AArrowUp, AlignCenter, AlignLeft, AlignRight, AlignVerticalJustifyCenter, AlignVerticalJustifyEnd, AlignVerticalJustifyStart, ArrowDown, ArrowDownToLine, ArrowLeft, ArrowLeftToLine, ArrowRight, ArrowRightToLine, ArrowUp, ArrowUpToLine, BadgeJapaneseYen, BarChart3, BetweenHorizontalEnd, BetweenHorizontalStart, BetweenVerticalEnd, BetweenVerticalStart, Bold, Bookmark, Calculator, CalendarClock, CalendarDays, Check, ChevronDown, ChevronLeft, ChevronRight, ClipboardPaste, Clock, Cloud, Columns3, Copy, CopyPlus, DecimalsArrowLeft, DecimalsArrowRight, Eraser, Eye, EyeOff, FileX2, Globe2, Grid2X2, Grid3X3, Hash, Italic, KeyRound, Layers2, Link2, Link2Off, ListChecks, ListFilter, LocateFixed, Merge, MessageSquareX, MoveHorizontal, MoveVertical, Paintbrush, Palette, PanelLeft, PanelTop, PanelsTopLeft, Pencil, Percent, Plus, Printer, Redo2, RefreshCw, Rows3, Save, Scissors, Search, Settings2, ShieldCheck, Sigma, SortAsc, SortDesc, Strikethrough, SwatchBook, Table2, TableProperties, Trash2, Underline, Undo2, WrapText, X } from "lucide-react";
5
5
  import { Fragment as external_react_Fragment, cloneElement, memo, useCallback, useEffect, useId, useLayoutEffect, useMemo, useRef, useState } from "react";
6
6
  import { genarate, indexToColumnChar, update as core_update } from "@fortune-sheet/core";
7
- import { freezeImportedSpreadsheetCell, spreadsheetTextOrientationFromChoice, spreadsheetMatrixProfile, withoutEditableRange, spreadsheetTextOrientationFromAngle, isSpreadsheetTextOrientationId, normalizeSpreadsheetConditionalVisualOptions, spreadsheetUnderlineCellValue, effectiveSpreadsheetPageSetup, attachSpreadsheetShownCommentCells, withEditableRange, sameSpreadsheetHistoryValue, createOfficeSpreadsheetCollaborationBinding as createWorkOfficeSpreadsheetCollaborationBinding, isSpreadsheetConditionalComparisonOperator, spreadsheetConditionalIconForValue, defaultSpreadsheetConditionalIconThresholds, spreadsheetUnderlineStyle, normalizeSpreadsheetDateValidationBoundary, sheetProtectionAuthority, editableRangeCellCount, unlockedCellCount, registerDerivedSpreadsheetMatrix, editableRangeRequiresCredentials, spreadsheetTextOrientationCellStyle, normalizeSpreadsheetConditionalIconSetFormat, defaultSpreadsheetDataBarOptions, spreadsheetConditionalThresholdValue, spreadsheetTextOrientationChoiceFromCell, normalizeSheetProtectionAuthority, withSheetProtection, defaultSpreadsheetColorScaleThresholds, spreadsheetProtectionKey, protectedSheetCount, SPREADSHEET_CONDITIONAL_ICON_SETS, SPREADSHEET_CONDITIONAL_COMPARISON_OPERATORS, withSheetSelectionPermissions, spreadsheetConditionalComparisonNeedsUpperValue, drawSpreadsheetConditionalIcon, spreadsheetTextOrientationFromCell, replaceOfficeSpreadsheetCollaboration as replaceWorkOfficeSpreadsheetCollaboration, readOfficeSpreadsheetCollaboration as readWorkOfficeSpreadsheetCollaboration, spreadsheetConditionalThresholdsEqual, isSpreadsheetUnderlineStyle, spreadsheetVisibleTextRotationFromCell } from "./6164.js";
7
+ import { freezeImportedSpreadsheetCell, spreadsheetTextOrientationFromChoice, spreadsheetMatrixProfile, withoutEditableRange, spreadsheetTextOrientationFromAngle, isSpreadsheetTextOrientationId, normalizeSpreadsheetConditionalVisualOptions, spreadsheetCellValueWithDiagonalBorder, spreadsheetUnderlineCellValue, effectiveSpreadsheetPageSetup, attachSpreadsheetShownCommentCells, withEditableRange, sameSpreadsheetHistoryValue, createOfficeSpreadsheetCollaborationBinding as createWorkOfficeSpreadsheetCollaborationBinding, isSpreadsheetConditionalComparisonOperator, spreadsheetConditionalIconForValue, defaultSpreadsheetConditionalIconThresholds, spreadsheetUnderlineStyle, normalizeSpreadsheetDateValidationBoundary, sheetProtectionAuthority, editableRangeCellCount, unlockedCellCount, registerDerivedSpreadsheetMatrix, editableRangeRequiresCredentials, spreadsheetTextOrientationCellStyle, normalizeSpreadsheetConditionalIconSetFormat, defaultSpreadsheetDataBarOptions, spreadsheetConditionalThresholdValue, spreadsheetTextOrientationChoiceFromCell, normalizeSheetProtectionAuthority, withSheetProtection, defaultSpreadsheetColorScaleThresholds, spreadsheetProtectionKey, spreadsheetDiagonalBorderFromCellValue, SPREADSHEET_CONDITIONAL_ICON_SETS, protectedSheetCount, withSheetSelectionPermissions, SPREADSHEET_CONDITIONAL_COMPARISON_OPERATORS, spreadsheetConditionalComparisonNeedsUpperValue, drawSpreadsheetConditionalIcon, spreadsheetTextOrientationFromCell, replaceOfficeSpreadsheetCollaboration as replaceWorkOfficeSpreadsheetCollaboration, readOfficeSpreadsheetCollaboration as readWorkOfficeSpreadsheetCollaboration, spreadsheetConditionalThresholdsEqual, isSpreadsheetUnderlineStyle, spreadsheetVisibleTextRotationFromCell } from "./5045.js";
8
8
  import { workSpreadsheetChartSupportsGrouping, createSpreadsheetChartFromSelection, normalizeWorkSpreadsheetDataLabelPosition, normalizeSpreadsheetPrintTitleColumns, normalizeSpreadsheetPrintTitleRows, formulaHasStructuredReference, normalizeWorkSpreadsheetErrorBars, defaultPivotValueCaption, workSpreadsheetChartSupportsBarSpacing, normalizeWorkSpreadsheetChartGrouping, spreadsheetGridSize, normalizeWorkSpreadsheetChartAxisGroup, normalizeWorkSpreadsheetScatterStyle, cloneSparseMatrix, spreadsheetPivotAggregationLabel, workSpreadsheetChartAxisIsCategoryAxis, reconcileSpreadsheetChartPreviews, normalizeWorkSpreadsheetChartAxes, normalizeWorkSpreadsheetDoughnutHoleSize, normalizeWorkSpreadsheetChartLegendPosition, spreadsheetChartCount, workSpreadsheetChartTypeLabel, sparseArrayEntries, normalizeWorkSpreadsheetTrendline, effectiveSpreadsheetCalculationSettings, spreadsheetPivotIntersects, normalizeWorkSpreadsheetDataLabels, spreadsheetPivotOutputContains, normalizeSpreadsheetPrintArea, spreadsheetCellAddress, formatSpreadsheetCellRanges, normalizeWorkSpreadsheetChartLayout, spreadsheetFormulaRangeForCell, workSpreadsheetChartAxisIsValueAxis, normalizeWorkSpreadsheetChartSmoothLines, spreadsheetPivotFilterValueKey, normalizeWorkSpreadsheetBubbleScale, normalizeWorkSpreadsheetChartSeriesStyle, volatileSpreadsheetFormulaFunctions, sparseArrayIndexes, normalizeWorkSpreadsheetBubbleSizeRepresents, workSpreadsheetChartSupportsTrendlines, normalizeWorkSpreadsheetChartLegendOverlay, parseSpreadsheetChartReference, workSpreadsheetChartGroupingIsStacked, normalizeWorkSpreadsheetChartGapWidth, workSpreadsheetChartSupportsSmoothLines, refreshSpreadsheetPivotTables, createSpreadsheetPivotFromSelection, reconcileSpreadsheetPivots, spreadsheetPivotCount, sparseMatrixColumnCount, workSpreadsheetChartSupportsErrorBars, formulaHasExternalReference, isValidSpreadsheetDefinedName, spreadsheetPivotValidation, deleteSpreadsheetPivotTable, workSpreadsheetChartAxisDefaultLabelPosition, workSpreadsheetChartSupportsSeriesAnalysis, parseSpreadsheetCellRanges, spreadsheetPivotFilterItems, spreadsheetPivotFields, normalizeWorkSpreadsheetChartOverlap, spreadsheetFormulaRangeConflict, spreadsheetSheetsWithChartPreviews, workSpreadsheetChartUsesNumericXAxis, workSpreadsheetChartAxisShowsMajorGridlinesByDefault, workSpreadsheetChartSupportsAxes, normalizeWorkSpreadsheetCombinationSeriesType, normalizeWorkSpreadsheetRadarStyle } from "./8715.js";
9
9
  import { moveOfficeMenuFocus, stepOfficeZoom, useOfficeRemoteParticipants, Popover, officePresenceColor, useOfficePublishPresenceLocation, button_Button, icon_button_IconButton, moveOfficeGridMenuFocus, office_text_field_OfficeTextField, useDialogFocusScope, useOfficeEditorWheelZoom } from "./0~6090.js";
10
10
  import { useOfficeTaskPaneEscape, OfficeCheckbox, CommittedOfficeNumberField, useOfficeDialog, useOfficeTaskPaneModal, createOfficeKernelClient, officeFontFamilies, CollectionState, OfficeNumberField, handleOfficeTaskPaneKeyDown } from "./0~7048.js";
@@ -86,6 +86,74 @@ function drawCellValue(context, bounds, cell, conditionalTextColor) {
86
86
  context.fillText(String(value), bounds.startX + 4, bounds.startY + height / 2, bounds.endX - bounds.startX - 8);
87
87
  }
88
88
  }
89
+ function drawSpreadsheetDiagonalDownBorder(context, bounds, line) {
90
+ drawSpreadsheetDiagonalBorder(context, bounds, line, 'down');
91
+ }
92
+ function drawSpreadsheetDiagonalUpBorder(context, bounds, line) {
93
+ drawSpreadsheetDiagonalBorder(context, bounds, line, 'up');
94
+ }
95
+ function drawSpreadsheetDiagonalBorder(context, bounds, line, direction) {
96
+ const left = Math.round(bounds.startX) + 0.5;
97
+ const top = Math.round(bounds.startY) + 0.5;
98
+ const right = Math.round(bounds.endX) - 1.5;
99
+ const bottom = Math.round(bounds.endY) - 1.5;
100
+ if (right <= left || bottom <= top) return;
101
+ context.save();
102
+ context.strokeStyle = line.color;
103
+ context.lineCap = 'butt';
104
+ context.lineWidth = spreadsheetDiagonalLineWidth(line.style);
105
+ context.setLineDash(spreadsheetDiagonalLineDash(line.style));
106
+ const startY = 'down' === direction ? top : bottom;
107
+ const endY = 'down' === direction ? bottom : top;
108
+ if ('7' === line.style) {
109
+ drawLine(context, left, startY - 1, right, endY - 1);
110
+ drawLine(context, left, startY + 1, right, endY + 1);
111
+ } else drawLine(context, left, startY, right, endY);
112
+ context.restore();
113
+ }
114
+ function drawLine(context, startX, startY, endX, endY) {
115
+ context.beginPath();
116
+ context.moveTo(startX, startY);
117
+ context.lineTo(endX, endY);
118
+ context.stroke();
119
+ }
120
+ function spreadsheetDiagonalLineWidth(style) {
121
+ if ('2' === style) return 0.5;
122
+ if ([
123
+ '8',
124
+ '9',
125
+ '10',
126
+ '11',
127
+ '12'
128
+ ].includes(style)) return 2;
129
+ if ('13' === style) return 3;
130
+ return 1;
131
+ }
132
+ function spreadsheetDiagonalLineDash(style) {
133
+ if ('3' === style) return [
134
+ 1,
135
+ 2
136
+ ];
137
+ if ('4' === style || '9' === style) return [
138
+ 5,
139
+ 3
140
+ ];
141
+ if ('5' === style || '10' === style || '12' === style) return [
142
+ 6,
143
+ 3,
144
+ 1,
145
+ 3
146
+ ];
147
+ if ('6' === style || '11' === style) return [
148
+ 6,
149
+ 3,
150
+ 1,
151
+ 3,
152
+ 1,
153
+ 3
154
+ ];
155
+ return [];
156
+ }
89
157
  function parseSpreadsheetConditionalColor(value) {
90
158
  const hexadecimal = /^#?([0-9a-f]{6})$/i.exec(value.trim());
91
159
  if (hexadecimal) return {
@@ -577,7 +645,8 @@ const spreadsheetCellBorderTargets = [
577
645
  'inside',
578
646
  'horizontal',
579
647
  'vertical',
580
- 'diagonal'
648
+ 'diagonalDown',
649
+ 'diagonalUp'
581
650
  ];
582
651
  const spreadsheetCellBorderStyles = [
583
652
  'thin',
@@ -615,8 +684,7 @@ const spreadsheetNativeBorderTypeByTarget = {
615
684
  outside: 'border-outside',
616
685
  inside: 'border-inside',
617
686
  horizontal: 'border-horizontal',
618
- vertical: 'border-vertical',
619
- diagonal: 'border-slash'
687
+ vertical: 'border-vertical'
620
688
  };
621
689
  const spreadsheetNativeBorderStyleByName = {
622
690
  thin: '1',
@@ -635,36 +703,29 @@ function spreadsheetNativeBorderStyle(style) {
635
703
  }
636
704
  function canSetSpreadsheetCellBorders(content, sheetId, range, format) {
637
705
  const normalizedRange = spreadsheet_cell_range_normalizeSpreadsheetCellRange(range);
638
- return Boolean(content.sheets.some((sheet)=>sheet.id === sheetId) && normalizedRange && normalizeSpreadsheetBorderFormat(format) && ('diagonal' !== format.target || spreadsheet_cell_range_spreadsheetCellRangeArea(normalizedRange) <= MAX_SPREADSHEET_DIAGONAL_BORDER_CELLS) && spreadsheetBorderInfoIsWritable(content.sheets.find((sheet)=>sheet.id === sheetId)));
706
+ return Boolean(content.sheets.some((sheet)=>sheet.id === sheetId) && normalizedRange && normalizeSpreadsheetBorderFormat(format) && (!isSpreadsheetDiagonalBorderTarget(format.target) || spreadsheet_cell_range_spreadsheetCellRangeArea(normalizedRange) <= MAX_SPREADSHEET_DIAGONAL_BORDER_CELLS) && spreadsheetBorderInfoIsWritable(content.sheets.find((sheet)=>sheet.id === sheetId)));
639
707
  }
640
708
  function setSpreadsheetCellBorders(content, sheetId, range, format) {
641
709
  const sheetIndex = content.sheets.findIndex((sheet)=>sheet.id === sheetId);
642
710
  const sheet = content.sheets[sheetIndex];
643
711
  const normalizedRange = spreadsheet_cell_range_normalizeSpreadsheetCellRange(range);
644
712
  const normalizedFormat = normalizeSpreadsheetBorderFormat(format);
645
- if (!sheet || !normalizedRange || !normalizedFormat || !spreadsheetBorderInfoIsWritable(sheet) || 'diagonal' === normalizedFormat.target && spreadsheet_cell_range_spreadsheetCellRangeArea(normalizedRange) > MAX_SPREADSHEET_DIAGONAL_BORDER_CELLS) return null;
646
- const borderType = spreadsheetNativeBorderTypeByTarget[normalizedFormat.target];
713
+ if (!sheet || !normalizedRange || !normalizedFormat || !spreadsheetBorderInfoIsWritable(sheet) || isSpreadsheetDiagonalBorderTarget(normalizedFormat.target) && spreadsheet_cell_range_spreadsheetCellRangeArea(normalizedRange) > MAX_SPREADSHEET_DIAGONAL_BORDER_CELLS) return null;
647
714
  const source = Array.isArray(sheet.config?.borderInfo) ? sheet.config.borderInfo : [];
715
+ if (isSpreadsheetDiagonalBorderTarget(normalizedFormat.target)) {
716
+ const borderInfo = [
717
+ ...compactSpreadsheetBorderInfo(source, normalizedRange, 'border-slash'),
718
+ ...spreadsheetDiagonalBorderRecords(sheet, normalizedRange, normalizedFormat.target, normalizedFormat.color, spreadsheetNativeBorderStyleByName[normalizedFormat.style])
719
+ ];
720
+ return contentWithSpreadsheetBorderInfo(content, sheetIndex, sheet, borderInfo);
721
+ }
722
+ const borderType = spreadsheetNativeBorderTypeByTarget[normalizedFormat.target];
648
723
  const compacted = compactSpreadsheetBorderInfo(source, normalizedRange, borderType);
649
724
  const borderInfo = [
650
725
  ...compacted,
651
726
  ...spreadsheetNativeBorderRecords(normalizedRange, borderType, normalizedFormat.color, spreadsheetNativeBorderStyleByName[normalizedFormat.style])
652
727
  ];
653
- const nextSheet = {
654
- ...sheet,
655
- config: {
656
- ...sheet.config,
657
- borderInfo: borderInfo
658
- }
659
- };
660
- const sheets = [
661
- ...content.sheets
662
- ];
663
- sheets[sheetIndex] = nextSheet;
664
- return {
665
- ...content,
666
- sheets
667
- };
728
+ return contentWithSpreadsheetBorderInfo(content, sheetIndex, sheet, borderInfo);
668
729
  }
669
730
  function spreadsheetCellBordersAt(sheet, row, column) {
670
731
  const borders = {};
@@ -678,7 +739,7 @@ function spreadsheetCellBordersAt(sheet, row, column) {
678
739
  applyResolvedCellBorderLine(borders, 'right', candidate.value.r);
679
740
  applyResolvedCellBorderLine(borders, 'top', candidate.value.t);
680
741
  applyResolvedCellBorderLine(borders, 'bottom', candidate.value.b);
681
- applyResolvedCellBorderLine(borders, 'diagonal', candidate.value.s);
742
+ applyResolvedCellDiagonalBorders(borders, candidate.value);
682
743
  continue;
683
744
  }
684
745
  if ('range' !== candidate.rangeType || !isSpreadsheetNativeBorderType(candidate.borderType) || !Array.isArray(candidate.range)) continue;
@@ -690,6 +751,69 @@ function spreadsheetCellBordersAt(sheet, row, column) {
690
751
  }
691
752
  return borders;
692
753
  }
754
+ function spreadsheetRenderableDiagonalBorders(sheet) {
755
+ const borders = new Map();
756
+ const source = Array.isArray(sheet.config?.borderInfo) ? sheet.config.borderInfo : [];
757
+ for (const candidate of source){
758
+ if (!spreadsheet_cell_border_isRecord(candidate)) continue;
759
+ if ('cell' === candidate.rangeType) {
760
+ if (!spreadsheet_cell_border_isRecord(candidate.value)) continue;
761
+ const row = finiteSpreadsheetBorderIndex(candidate.value.row_index);
762
+ const column = finiteSpreadsheetBorderIndex(candidate.value.col_index);
763
+ if (null === row || null === column) continue;
764
+ const key = `${row}_${column}`;
765
+ const diagonal = spreadsheetDiagonalBorderFromCellValue(candidate.value);
766
+ if (void 0 === diagonal) continue;
767
+ if (!diagonal) {
768
+ borders.delete(key);
769
+ continue;
770
+ }
771
+ const line = resolvedCellBorderLine(diagonal.line);
772
+ if (!line) {
773
+ borders.delete(key);
774
+ continue;
775
+ }
776
+ borders.set(key, {
777
+ border: {
778
+ ...diagonal.down ? {
779
+ down: line
780
+ } : {},
781
+ ...diagonal.up ? {
782
+ up: line
783
+ } : {}
784
+ },
785
+ column,
786
+ row
787
+ });
788
+ continue;
789
+ }
790
+ if ('range' !== candidate.rangeType || 'border-none' !== candidate.borderType && 'border-slash' !== candidate.borderType || !Array.isArray(candidate.range)) continue;
791
+ const line = resolvedRangeBorderLine(candidate);
792
+ for (const rangeCandidate of candidate.range){
793
+ const range = parseSpreadsheetCellRange(rangeCandidate);
794
+ if (range) {
795
+ for (const [key, entry] of borders)if (spreadsheetCellRangeContains(range, entry.row, entry.column)) {
796
+ if ('border-none' === candidate.borderType || !entry.border.up) {
797
+ borders.delete(key);
798
+ continue;
799
+ }
800
+ borders.set(key, {
801
+ ...entry,
802
+ border: {
803
+ up: line ?? entry.border.up
804
+ }
805
+ });
806
+ }
807
+ }
808
+ }
809
+ }
810
+ return new Map([
811
+ ...borders
812
+ ].map(([key, entry])=>[
813
+ key,
814
+ entry.border
815
+ ]));
816
+ }
693
817
  function normalizeSpreadsheetBorderFormat(format) {
694
818
  if (!spreadsheetCellBorderTargets.includes(format.target) || !spreadsheetCellBorderStyles.includes(format.style)) return null;
695
819
  const color = normalizeSpreadsheetBorderColor(format.color);
@@ -716,14 +840,26 @@ function compactSpreadsheetBorderInfo(formats, range, appliedType) {
716
840
  format
717
841
  ];
718
842
  if ('cell' === format.rangeType) {
719
- if (!supersedesAll || !spreadsheet_cell_border_isRecord(format.value)) return [
843
+ if (!spreadsheet_cell_border_isRecord(format.value)) return [
720
844
  format
721
845
  ];
722
846
  const row = finiteSpreadsheetBorderIndex(format.value.row_index);
723
847
  const column = finiteSpreadsheetBorderIndex(format.value.col_index);
724
- return null !== row && null !== column && spreadsheetCellRangeContains(range, row, column) ? [] : [
848
+ const selected = null !== row && null !== column && spreadsheetCellRangeContains(range, row, column);
849
+ if (!selected) return [
725
850
  format
726
851
  ];
852
+ if (supersedesAll) return [];
853
+ if ('border-slash' !== appliedType) return [
854
+ format
855
+ ];
856
+ const value = spreadsheetCellValueWithDiagonalBorder(format.value, null);
857
+ return Object.keys(value).some((key)=>'row_index' !== key && 'col_index' !== key) ? [
858
+ {
859
+ ...format,
860
+ value
861
+ }
862
+ ] : [];
727
863
  }
728
864
  if ('range' !== format.rangeType || !isSpreadsheetNativeBorderType(format.borderType) || !Array.isArray(format.range) || !supersedesAll && format.borderType !== appliedType) return [
729
865
  format
@@ -733,9 +869,14 @@ function compactSpreadsheetBorderInfo(formats, range, appliedType) {
733
869
  if (!parsed) return [
734
870
  candidate
735
871
  ];
736
- if ('border-slash' === format.borderType) return spreadsheetCellRangesIntersect(parsed, range) ? [] : [
737
- candidate
738
- ];
872
+ if ('border-slash' === format.borderType) {
873
+ if (!spreadsheetCellRangesIntersect(parsed, range)) return [
874
+ candidate
875
+ ];
876
+ return 1 === spreadsheet_cell_range_spreadsheetCellRangeArea(parsed) ? [] : [
877
+ candidate
878
+ ];
879
+ }
739
880
  return subtractSpreadsheetCellRange(parsed, range);
740
881
  });
741
882
  return remaining.length ? [
@@ -747,7 +888,7 @@ function compactSpreadsheetBorderInfo(formats, range, appliedType) {
747
888
  });
748
889
  }
749
890
  function spreadsheetNativeBorderRecords(range, borderType, color, style) {
750
- if ('border-slash' !== borderType) return [
891
+ return [
751
892
  {
752
893
  rangeType: 'range',
753
894
  borderType,
@@ -758,28 +899,91 @@ function spreadsheetNativeBorderRecords(range, borderType, color, style) {
758
899
  ]
759
900
  }
760
901
  ];
902
+ }
903
+ function spreadsheetDiagonalBorderRecords(sheet, range, target, color, style) {
761
904
  const records = [];
762
- for(let row = range.row[0]; row <= range.row[1]; row += 1)for(let column = range.column[0]; column <= range.column[1]; column += 1)records.push({
763
- rangeType: 'range',
764
- borderType,
765
- color,
766
- style,
767
- range: [
768
- {
769
- row: [
770
- row,
771
- row
772
- ],
773
- column: [
774
- column,
775
- column
776
- ],
777
- row_focus: row,
778
- column_focus: column
905
+ const existing = spreadsheetDiagonalBorderDirectionsInRange(sheet, range);
906
+ for(let row = range.row[0]; row <= range.row[1]; row += 1)for(let column = range.column[0]; column <= range.column[1]; column += 1){
907
+ const current = existing.get(`${row}_${column}`);
908
+ const border = {
909
+ down: 'diagonalDown' === target || Boolean(current?.down),
910
+ line: {
911
+ color,
912
+ style
913
+ },
914
+ up: 'diagonalUp' === target || Boolean(current?.up)
915
+ };
916
+ records.push({
917
+ rangeType: 'cell',
918
+ value: spreadsheetCellValueWithDiagonalBorder({
919
+ col_index: column,
920
+ row_index: row
921
+ }, border)
922
+ });
923
+ }
924
+ return records;
925
+ }
926
+ function spreadsheetDiagonalBorderDirectionsInRange(sheet, selection) {
927
+ const directions = new Map();
928
+ const source = Array.isArray(sheet.config?.borderInfo) ? sheet.config.borderInfo : [];
929
+ for (const candidate of source){
930
+ if (!spreadsheet_cell_border_isRecord(candidate)) continue;
931
+ if ('cell' === candidate.rangeType) {
932
+ if (!spreadsheet_cell_border_isRecord(candidate.value)) continue;
933
+ const row = finiteSpreadsheetBorderIndex(candidate.value.row_index);
934
+ const column = finiteSpreadsheetBorderIndex(candidate.value.col_index);
935
+ if (null === row || null === column || !spreadsheetCellRangeContains(selection, row, column)) continue;
936
+ const diagonal = spreadsheetDiagonalBorderFromCellValue(candidate.value);
937
+ if (void 0 === diagonal) continue;
938
+ const line = diagonal && resolvedCellBorderLine(diagonal.line);
939
+ setSpreadsheetDiagonalDirections(directions, row, column, Boolean(line && diagonal?.down), Boolean(line && diagonal?.up));
940
+ continue;
941
+ }
942
+ if ('range' !== candidate.rangeType || 'border-none' !== candidate.borderType && 'border-slash' !== candidate.borderType || !Array.isArray(candidate.range)) continue;
943
+ const line = resolvedRangeBorderLine(candidate);
944
+ for (const rangeCandidate of candidate.range){
945
+ const range = parseSpreadsheetCellRange(rangeCandidate);
946
+ if (!range || !spreadsheetCellRangesIntersect(range, selection)) continue;
947
+ const startRow = Math.max(range.row[0], selection.row[0]);
948
+ const endRow = Math.min(range.row[1], selection.row[1]);
949
+ const startColumn = Math.max(range.column[0], selection.column[0]);
950
+ const endColumn = Math.min(range.column[1], selection.column[1]);
951
+ for(let row = startRow; row <= endRow; row += 1)for(let column = startColumn; column <= endColumn; column += 1){
952
+ if ('border-none' === candidate.borderType) {
953
+ directions.delete(`${row}_${column}`);
954
+ continue;
955
+ }
956
+ const current = directions.get(`${row}_${column}`);
957
+ setSpreadsheetDiagonalDirections(directions, row, column, Boolean(line), Boolean(current?.up));
779
958
  }
780
- ]
959
+ }
960
+ }
961
+ return directions;
962
+ }
963
+ function setSpreadsheetDiagonalDirections(directions, row, column, down, up) {
964
+ const key = `${row}_${column}`;
965
+ if (!down && !up) return void directions.delete(key);
966
+ directions.set(key, {
967
+ down,
968
+ up
781
969
  });
782
- return records;
970
+ }
971
+ function contentWithSpreadsheetBorderInfo(content, sheetIndex, sheet, borderInfo) {
972
+ const nextSheet = {
973
+ ...sheet,
974
+ config: {
975
+ ...sheet.config,
976
+ borderInfo: borderInfo
977
+ }
978
+ };
979
+ const sheets = [
980
+ ...content.sheets
981
+ ];
982
+ sheets[sheetIndex] = nextSheet;
983
+ return {
984
+ ...content,
985
+ sheets
986
+ };
783
987
  }
784
988
  function applyResolvedCellBorderLine(borders, side, value) {
785
989
  if (null === value) return void delete borders[side];
@@ -791,6 +995,26 @@ function applyResolvedCellBorderLine(borders, side, value) {
791
995
  style
792
996
  };
793
997
  }
998
+ function applyResolvedCellDiagonalBorders(borders, value) {
999
+ const diagonal = spreadsheetDiagonalBorderFromCellValue(value);
1000
+ if (void 0 === diagonal) return;
1001
+ delete borders.diagonalDown;
1002
+ delete borders.diagonalUp;
1003
+ if (!diagonal) return;
1004
+ const line = resolvedCellBorderLine(diagonal.line);
1005
+ if (!line) return;
1006
+ if (diagonal.down) borders.diagonalDown = line;
1007
+ if (diagonal.up) borders.diagonalUp = line;
1008
+ }
1009
+ function resolvedCellBorderLine(value) {
1010
+ if (!spreadsheet_cell_border_isRecord(value)) return null;
1011
+ const color = 'string' == typeof value.color ? normalizeSpreadsheetBorderColor(value.color) : null;
1012
+ const style = 'string' == typeof value.style ? value.style : null;
1013
+ return color && style ? {
1014
+ color,
1015
+ style
1016
+ } : null;
1017
+ }
794
1018
  function resolvedRangeBorderLine(value) {
795
1019
  const color = 'string' == typeof value.color ? normalizeSpreadsheetBorderColor(value.color) : null;
796
1020
  const style = 'string' == typeof value.style ? value.style : null;
@@ -826,7 +1050,8 @@ function applyResolvedRangeBorder(borders, range, row, column, type, line) {
826
1050
  delete borders.bottom;
827
1051
  delete borders.left;
828
1052
  delete borders.right;
829
- delete borders.diagonal;
1053
+ delete borders.diagonalDown;
1054
+ delete borders.diagonalUp;
830
1055
  break;
831
1056
  case 'border-all':
832
1057
  set('top');
@@ -855,10 +1080,16 @@ function applyResolvedRangeBorder(borders, range, row, column, type, line) {
855
1080
  if (!onRight) set('right');
856
1081
  break;
857
1082
  case 'border-slash':
858
- set('diagonal');
1083
+ if (line) {
1084
+ borders.diagonalDown = line;
1085
+ if (borders.diagonalUp) borders.diagonalUp = line;
1086
+ } else delete borders.diagonalDown;
859
1087
  break;
860
1088
  }
861
1089
  }
1090
+ function isSpreadsheetDiagonalBorderTarget(target) {
1091
+ return 'diagonalDown' === target || 'diagonalUp' === target;
1092
+ }
862
1093
  function isSpreadsheetNativeBorderType(value) {
863
1094
  return 'string' == typeof value && spreadsheetNativeBorderTypes.has(value);
864
1095
  }
@@ -3005,6 +3236,38 @@ const spreadsheetCommandCatalog = {
3005
3236
  group: 'number'
3006
3237
  }
3007
3238
  },
3239
+ insertCurrentDate: {
3240
+ id: 'number.insertCurrentDate',
3241
+ label: '插入当前日期',
3242
+ location: {
3243
+ area: 'ribbon',
3244
+ tab: 'home',
3245
+ group: 'number'
3246
+ },
3247
+ shortcut: {
3248
+ label: 'Ctrl+;',
3249
+ aria: 'Control+;',
3250
+ editor: [
3251
+ 'Control-;'
3252
+ ]
3253
+ }
3254
+ },
3255
+ insertCurrentTime: {
3256
+ id: 'number.insertCurrentTime',
3257
+ label: '插入当前时间',
3258
+ location: {
3259
+ area: 'ribbon',
3260
+ tab: 'home',
3261
+ group: 'number'
3262
+ },
3263
+ shortcut: {
3264
+ label: 'Ctrl+Shift+;',
3265
+ aria: 'Control+Shift+;',
3266
+ editor: [
3267
+ 'Control-Shift-;'
3268
+ ]
3269
+ }
3270
+ },
3008
3271
  formatCells: {
3009
3272
  id: 'number.formatCells',
3010
3273
  label: '设置单元格格式',
@@ -3127,9 +3390,18 @@ const spreadsheetCommandCatalog = {
3127
3390
  group: 'font'
3128
3391
  }
3129
3392
  },
3130
- borderDiagonal: {
3131
- id: 'font.borderDiagonal',
3132
- label: '斜线框线',
3393
+ borderDiagonalDown: {
3394
+ id: 'font.borderDiagonalDown',
3395
+ label: '斜下框线',
3396
+ location: {
3397
+ area: 'ribbon',
3398
+ tab: 'home',
3399
+ group: 'font'
3400
+ }
3401
+ },
3402
+ borderDiagonalUp: {
3403
+ id: 'font.borderDiagonalUp',
3404
+ label: '斜上框线',
3133
3405
  location: {
3134
3406
  area: 'ribbon',
3135
3407
  tab: 'home',
@@ -4077,14 +4349,16 @@ const MAX_SPREADSHEET_PER_CELL_BORDER_CELLS = 10000;
4077
4349
  function setSpreadsheetCellBordersPerCell(content, sheetId, range, formats) {
4078
4350
  const normalizedRange = spreadsheet_cell_range_normalizeSpreadsheetCellRange(range);
4079
4351
  const normalizedFormats = formats.map(normalizeSpreadsheetBorderFormat);
4080
- if (!normalizedRange || spreadsheet_cell_range_spreadsheetCellRangeArea(normalizedRange) > MAX_SPREADSHEET_PER_CELL_BORDER_CELLS || normalizedFormats.some((format)=>!format || ![
4352
+ const area = normalizedRange ? spreadsheet_cell_range_spreadsheetCellRangeArea(normalizedRange) : 1 / 0;
4353
+ if (!normalizedRange || area > MAX_SPREADSHEET_PER_CELL_BORDER_CELLS || normalizedFormats.some((format)=>!format || ![
4081
4354
  'top',
4082
4355
  'bottom',
4083
4356
  'left',
4084
4357
  'right',
4085
4358
  'all',
4086
- 'diagonal'
4087
- ].includes(format.target))) return null;
4359
+ 'diagonalDown',
4360
+ 'diagonalUp'
4361
+ ].includes(format.target)) || area > 4096 && normalizedFormats.some((format)=>format?.target === 'diagonalDown' || format?.target === 'diagonalUp')) return null;
4088
4362
  const next = setSpreadsheetCellBorders(content, sheetId, normalizedRange, {
4089
4363
  target: 'none',
4090
4364
  color: '#000000',
@@ -4100,6 +4374,9 @@ function setSpreadsheetCellBordersPerCell(content, sheetId, range, formats) {
4100
4374
  row_index: row,
4101
4375
  col_index: column
4102
4376
  };
4377
+ let diagonalDown = false;
4378
+ let diagonalUp = false;
4379
+ let diagonalLine = null;
4103
4380
  for (const format of normalizedFormats){
4104
4381
  if (!format) continue;
4105
4382
  const line = {
@@ -4110,11 +4387,22 @@ function setSpreadsheetCellBordersPerCell(content, sheetId, range, formats) {
4110
4387
  if ('all' === format.target || 'right' === format.target) value.r = line;
4111
4388
  if ('all' === format.target || 'top' === format.target) value.t = line;
4112
4389
  if ('all' === format.target || 'bottom' === format.target) value.b = line;
4113
- if ('diagonal' === format.target) value.s = line;
4390
+ if ('diagonalDown' === format.target) {
4391
+ diagonalDown = true;
4392
+ diagonalLine = line;
4393
+ }
4394
+ if ('diagonalUp' === format.target) {
4395
+ diagonalUp = true;
4396
+ diagonalLine = line;
4397
+ }
4114
4398
  }
4115
4399
  records.push({
4116
4400
  rangeType: 'cell',
4117
- value
4401
+ value: diagonalLine && (diagonalDown || diagonalUp) ? spreadsheetCellValueWithDiagonalBorder(value, {
4402
+ down: diagonalDown,
4403
+ line: diagonalLine,
4404
+ up: diagonalUp
4405
+ }) : value
4118
4406
  });
4119
4407
  }
4120
4408
  const borderInfo = [
@@ -4180,8 +4468,9 @@ function canApplySpreadsheetCellFormat(content, request) {
4180
4468
  'left',
4181
4469
  'right',
4182
4470
  'all',
4183
- 'diagonal'
4184
- ].includes(format.target)) || normalized.some((format)=>format?.target === 'diagonal') && spreadsheet_cell_range_spreadsheetCellRangeArea(range) > 4096) return false;
4471
+ 'diagonalDown',
4472
+ 'diagonalUp'
4473
+ ].includes(format.target)) || normalized.some((format)=>format?.target === 'diagonalDown' || format?.target === 'diagonalUp') && spreadsheet_cell_range_spreadsheetCellRangeArea(range) > 4096) return false;
4185
4474
  }
4186
4475
  return true;
4187
4476
  }
@@ -4699,14 +4988,16 @@ function sameCellStyleBorders(actual, formats) {
4699
4988
  if ('all' === format.target || 'right' === format.target) expected.right = line;
4700
4989
  if ('all' === format.target || 'top' === format.target) expected.top = line;
4701
4990
  if ('all' === format.target || 'bottom' === format.target) expected.bottom = line;
4702
- if ('diagonal' === format.target) expected.diagonal = line;
4991
+ if ('diagonalDown' === format.target) expected.diagonalDown = line;
4992
+ if ('diagonalUp' === format.target) expected.diagonalUp = line;
4703
4993
  }
4704
4994
  return [
4705
4995
  'top',
4706
4996
  'bottom',
4707
4997
  'left',
4708
4998
  'right',
4709
- 'diagonal'
4999
+ 'diagonalDown',
5000
+ 'diagonalUp'
4710
5001
  ].every((side)=>actual[side]?.color === expected[side]?.color && actual[side]?.style === expected[side]?.style);
4711
5002
  }
4712
5003
  function createSpreadsheetCellStyleExtension() {
@@ -5777,6 +6068,207 @@ function clampSpreadsheetDataValidationFocus(value, range) {
5777
6068
  const focus = 'number' == typeof value && Number.isFinite(value) ? Math.trunc(value) : minimum;
5778
6069
  return Math.min(maximum, Math.max(minimum, focus));
5779
6070
  }
6071
+ const MAX_SPREADSHEET_ROWS = 1048576;
6072
+ const spreadsheetPasteContentOptions = [
6073
+ {
6074
+ value: 'all',
6075
+ label: '全部',
6076
+ richOnly: false
6077
+ },
6078
+ {
6079
+ value: 'formulas',
6080
+ label: '公式',
6081
+ richOnly: false
6082
+ },
6083
+ {
6084
+ value: 'values',
6085
+ label: '值',
6086
+ richOnly: false
6087
+ },
6088
+ {
6089
+ value: 'formats',
6090
+ label: '格式',
6091
+ richOnly: true
6092
+ },
6093
+ {
6094
+ value: 'comments',
6095
+ label: '批注',
6096
+ richOnly: true
6097
+ },
6098
+ {
6099
+ value: 'validation',
6100
+ label: '数据验证',
6101
+ richOnly: true
6102
+ },
6103
+ {
6104
+ value: 'all-except-borders',
6105
+ label: '边框除外的全部',
6106
+ richOnly: true
6107
+ },
6108
+ {
6109
+ value: 'formulas-and-number-formats',
6110
+ label: '公式和数字格式',
6111
+ richOnly: true
6112
+ },
6113
+ {
6114
+ value: 'values-and-number-formats',
6115
+ label: '值和数字格式',
6116
+ richOnly: true
6117
+ },
6118
+ {
6119
+ value: 'column-widths',
6120
+ label: '列宽',
6121
+ richOnly: true
6122
+ }
6123
+ ];
6124
+ const spreadsheetPasteOperationOptions = [
6125
+ {
6126
+ value: 'none',
6127
+ label: '无'
6128
+ },
6129
+ {
6130
+ value: 'add',
6131
+ label: '加'
6132
+ },
6133
+ {
6134
+ value: 'subtract',
6135
+ label: '减'
6136
+ },
6137
+ {
6138
+ value: 'multiply',
6139
+ label: '乘'
6140
+ },
6141
+ {
6142
+ value: 'divide',
6143
+ label: '除'
6144
+ }
6145
+ ];
6146
+ const MILLISECONDS_PER_DAY = 86400000;
6147
+ const MINUTES_PER_DAY = 1440;
6148
+ const EXCEL_1900_EPOCH_UTC = Date.UTC(1899, 11, 30);
6149
+ function spreadsheetDateTimeEntry(kind, now) {
6150
+ if (!Number.isFinite(now.getTime())) return null;
6151
+ if ('date' === kind) {
6152
+ const year = now.getFullYear();
6153
+ const month = now.getMonth();
6154
+ const day = now.getDate();
6155
+ const value = (Date.UTC(year, month, day) - EXCEL_1900_EPOCH_UTC) / MILLISECONDS_PER_DAY;
6156
+ if (!Number.isFinite(value)) return null;
6157
+ return {
6158
+ format: {
6159
+ fa: 'yyyy-MM-dd',
6160
+ t: 'd'
6161
+ },
6162
+ formulaBarValue: `${padDatePart(year, 4)}-${padDatePart(month + 1)}-${padDatePart(day)}`,
6163
+ value
6164
+ };
6165
+ }
6166
+ if ('time' !== kind) return null;
6167
+ const hours = now.getHours();
6168
+ const minutes = now.getMinutes();
6169
+ return {
6170
+ format: {
6171
+ fa: 'hh:mm',
6172
+ t: 'd'
6173
+ },
6174
+ formulaBarValue: `${padDatePart(hours)}:${padDatePart(minutes)}`,
6175
+ value: (60 * hours + minutes) / MINUTES_PER_DAY
6176
+ };
6177
+ }
6178
+ function createSpreadsheetDateTimeExtension() {
6179
+ return createOfficeEditorExtension({
6180
+ name: 'spreadsheetDateTime',
6181
+ addCommands: ()=>({
6182
+ insertCurrentDateTime: {
6183
+ canExecute: (context, kind)=>isSpreadsheetDateTimeKind(kind) && null !== spreadsheetDateTimeTarget(context),
6184
+ execute: insertCurrentSpreadsheetDateTime
6185
+ }
6186
+ }),
6187
+ addKeyboardShortcuts: ()=>({
6188
+ [spreadsheetCommandCatalog.insertCurrentDate.shortcut.editor["0"]]: ({ can, commands }, event)=>runSpreadsheetDateTimeShortcut(event, 'date', can.insertCurrentDateTime, commands.insertCurrentDateTime),
6189
+ [spreadsheetCommandCatalog.insertCurrentTime.shortcut.editor["0"]]: ({ can, commands }, event)=>runSpreadsheetDateTimeShortcut(event, 'time', can.insertCurrentDateTime, commands.insertCurrentDateTime)
6190
+ })
6191
+ });
6192
+ }
6193
+ function insertCurrentSpreadsheetDateTime(context, kind) {
6194
+ if (!isSpreadsheetDateTimeKind(kind)) return false;
6195
+ const target = spreadsheetDateTimeTarget(context);
6196
+ const entry = spreadsheetDateTimeEntry(kind, new Date());
6197
+ if (!target || !entry || !context.workbook) return false;
6198
+ try {
6199
+ context.workbook.batchCallApis([
6200
+ {
6201
+ name: 'setCellValuesByRange',
6202
+ args: [
6203
+ [
6204
+ [
6205
+ entry.value
6206
+ ]
6207
+ ],
6208
+ target.range,
6209
+ {
6210
+ id: target.sheetId
6211
+ }
6212
+ ]
6213
+ },
6214
+ {
6215
+ name: 'setCellFormatByRange',
6216
+ args: [
6217
+ 'ct',
6218
+ entry.format,
6219
+ target.range,
6220
+ {
6221
+ id: target.sheetId
6222
+ }
6223
+ ]
6224
+ }
6225
+ ]);
6226
+ } catch {
6227
+ return false;
6228
+ }
6229
+ try {
6230
+ context.formulaBar?.setValue(entry.formulaBarValue);
6231
+ } catch {}
6232
+ return true;
6233
+ }
6234
+ function spreadsheetDateTimeTarget(context) {
6235
+ const workbook = context.workbook;
6236
+ const sheetId = context.targetSheetId;
6237
+ if (!context.editable || !workbook || !sheetId || sheetId !== context.activeSheetId) return null;
6238
+ try {
6239
+ const selection = finiteSpreadsheetSelection(workbook.getSelection()?.at(-1) ?? context.fallbackRange);
6240
+ const row = selection.row_focus ?? selection.row[0] ?? 0;
6241
+ const column = selection.column_focus ?? selection.column[0] ?? 0;
6242
+ if (!Number.isSafeInteger(row) || row < 0 || row >= MAX_SPREADSHEET_ROWS || !Number.isSafeInteger(column) || column < 0 || column >= 16384) return null;
6243
+ const range = {
6244
+ row: [
6245
+ row,
6246
+ row
6247
+ ],
6248
+ column: [
6249
+ column,
6250
+ column
6251
+ ]
6252
+ };
6253
+ const sheet = context.content.sheets.find((candidate)=>candidate.id === sheetId);
6254
+ return canMutateSpreadsheetCellRange(sheet, range) ? {
6255
+ range,
6256
+ sheetId
6257
+ } : null;
6258
+ } catch {
6259
+ return null;
6260
+ }
6261
+ }
6262
+ function runSpreadsheetDateTimeShortcut(event, kind, canExecute, execute) {
6263
+ if (event.repeat || event.isComposing || isOfficeShortcutBlocked(event.target) || isSpreadsheetNativeTextUndoTarget(event.target) || !isSpreadsheetGridKeyboardTarget(event.target) || !canExecute(kind)) return false;
6264
+ return execute(kind);
6265
+ }
6266
+ function isSpreadsheetDateTimeKind(value) {
6267
+ return 'date' === value || 'time' === value;
6268
+ }
6269
+ function padDatePart(value, length = 2) {
6270
+ return String(value).padStart(length, '0');
6271
+ }
5780
6272
  function canApplySpreadsheetCellMerge(sheet, range, command) {
5781
6273
  if (!sheet) return false;
5782
6274
  const normalized = normalizeSpreadsheetCellMergeRange(range);
@@ -8109,6 +8601,7 @@ function createSpreadsheetEditorExtensions() {
8109
8601
  createSpreadsheetCellBorderExtension(),
8110
8602
  createSpreadsheetCellStyleExtension(),
8111
8603
  createSpreadsheetNumberFormatExtension(),
8604
+ createSpreadsheetDateTimeExtension(),
8112
8605
  createSpreadsheetNavigationExtension(),
8113
8606
  createSpreadsheetDataValidationExtension(),
8114
8607
  createSpreadsheetHyperlinkExtension(),
@@ -10195,8 +10688,12 @@ const spreadsheetBorderTargetOptions = [
10195
10688
  definition: spreadsheetCommandCatalog.borderVertical
10196
10689
  },
10197
10690
  {
10198
- target: 'diagonal',
10199
- definition: spreadsheetCommandCatalog.borderDiagonal
10691
+ target: 'diagonalDown',
10692
+ definition: spreadsheetCommandCatalog.borderDiagonalDown
10693
+ },
10694
+ {
10695
+ target: 'diagonalUp',
10696
+ definition: spreadsheetCommandCatalog.borderDiagonalUp
10200
10697
  }
10201
10698
  ];
10202
10699
  function SpreadsheetBorderRibbon({ can, commands }) {
@@ -10458,6 +10955,73 @@ function SpreadsheetUnderlineGlyph({ style }) {
10458
10955
  })
10459
10956
  });
10460
10957
  }
10958
+ function SpreadsheetDateTimeMenu({ can, commands }) {
10959
+ const items = [
10960
+ {
10961
+ definition: spreadsheetCommandCatalog.insertCurrentDate,
10962
+ icon: /*#__PURE__*/ jsx(CalendarDays, {
10963
+ size: 16
10964
+ }),
10965
+ kind: 'date'
10966
+ },
10967
+ {
10968
+ definition: spreadsheetCommandCatalog.insertCurrentTime,
10969
+ icon: /*#__PURE__*/ jsx(Clock, {
10970
+ size: 16
10971
+ }),
10972
+ kind: 'time'
10973
+ }
10974
+ ];
10975
+ const disabled = items.every(({ kind })=>!can.insertCurrentDateTime(kind));
10976
+ return /*#__PURE__*/ jsx(Popover, {
10977
+ label: "日期和时间",
10978
+ panelLabel: "插入日期和时间",
10979
+ panelRole: "menu",
10980
+ portal: true,
10981
+ className: "work-spreadsheet-ribbon-menu-root",
10982
+ panelClassName: "work-office-context-menu work-spreadsheet-ribbon-menu",
10983
+ disabled: disabled,
10984
+ focusFirstOnOpen: true,
10985
+ onPanelKeyDown: moveOfficeMenuFocus,
10986
+ trigger: (triggerProps, { open })=>/*#__PURE__*/ jsxs("button", {
10987
+ ...triggerProps,
10988
+ className: `with-label work-spreadsheet-ribbon-menu-trigger work-spreadsheet-date-time-trigger${open ? ' active' : ''}`,
10989
+ title: "插入当前日期或时间(Ctrl+; / Ctrl+Shift+;)",
10990
+ children: [
10991
+ /*#__PURE__*/ jsx(CalendarClock, {
10992
+ size: 19
10993
+ }),
10994
+ /*#__PURE__*/ jsx("span", {
10995
+ children: "日期和时间"
10996
+ })
10997
+ ]
10998
+ }),
10999
+ children: (close)=>items.map(({ definition, icon, kind })=>/*#__PURE__*/ jsxs("button", {
11000
+ type: "button",
11001
+ role: "menuitem",
11002
+ tabIndex: -1,
11003
+ "aria-label": definition.label,
11004
+ "aria-keyshortcuts": definition.shortcut.aria,
11005
+ disabled: !can.insertCurrentDateTime(kind),
11006
+ onClick: ()=>{
11007
+ close();
11008
+ commands.insertCurrentDateTime(kind);
11009
+ },
11010
+ children: [
11011
+ /*#__PURE__*/ jsx("span", {
11012
+ className: "work-spreadsheet-ribbon-menu-item-icon",
11013
+ children: icon
11014
+ }),
11015
+ /*#__PURE__*/ jsx("span", {
11016
+ children: definition.label
11017
+ }),
11018
+ /*#__PURE__*/ jsx("kbd", {
11019
+ children: definition.shortcut.label
11020
+ })
11021
+ ]
11022
+ }, definition.id))
11023
+ });
11024
+ }
10461
11025
  const spreadsheetNumberFormatOptions = [
10462
11026
  {
10463
11027
  value: 'general',
@@ -10655,16 +11219,25 @@ function SpreadsheetNumberRibbonGroup({ can, commands, toolbarCell }) {
10655
11219
  label: "数字",
10656
11220
  priority: "high",
10657
11221
  children: [
10658
- /*#__PURE__*/ jsx(OfficeSelect, {
10659
- className: "work-spreadsheet-number-format",
10660
- ariaLabel: "数字格式",
10661
- value: numberFormatPreset,
10662
- disabled: !can.setCellFormat('ct', currentNumberFormatValue),
10663
- options: spreadsheetNumberFormatOptions,
10664
- onValueChange: (preset)=>{
10665
- if ('custom' === preset) return;
10666
- commands.setCellFormat('ct', spreadsheetNumberFormatValue(spreadsheetNumberFormatCode(preset), toolbarCell));
10667
- }
11222
+ /*#__PURE__*/ jsxs("div", {
11223
+ className: "work-spreadsheet-number-format-stack",
11224
+ children: [
11225
+ /*#__PURE__*/ jsx(OfficeSelect, {
11226
+ className: "work-spreadsheet-number-format",
11227
+ ariaLabel: "数字格式",
11228
+ value: numberFormatPreset,
11229
+ disabled: !can.setCellFormat('ct', currentNumberFormatValue),
11230
+ options: spreadsheetNumberFormatOptions,
11231
+ onValueChange: (preset)=>{
11232
+ if ('custom' === preset) return;
11233
+ commands.setCellFormat('ct', spreadsheetNumberFormatValue(spreadsheetNumberFormatCode(preset), toolbarCell));
11234
+ }
11235
+ }),
11236
+ /*#__PURE__*/ jsx(SpreadsheetDateTimeMenu, {
11237
+ can: can,
11238
+ commands: commands
11239
+ })
11240
+ ]
10668
11241
  }),
10669
11242
  /*#__PURE__*/ jsx(WorkOfficeRibbonButton, {
10670
11243
  label: `${currencyDefinition.label}格式`,
@@ -12680,8 +13253,12 @@ const borderTargets = [
12680
13253
  label: '右框线'
12681
13254
  },
12682
13255
  {
12683
- target: 'diagonal',
12684
- label: '对角线'
13256
+ target: 'diagonalDown',
13257
+ label: '斜下框线'
13258
+ },
13259
+ {
13260
+ target: 'diagonalUp',
13261
+ label: '斜上框线'
12685
13262
  }
12686
13263
  ];
12687
13264
  function SpreadsheetFormatCellsPanel(props) {
@@ -13114,10 +13691,16 @@ function BorderPreview({ draft }) {
13114
13691
  borderRight: line('right')
13115
13692
  }
13116
13693
  }),
13117
- line('diagonal') && /*#__PURE__*/ jsx("span", {
13118
- className: "diagonal",
13694
+ line('diagonalDown') && /*#__PURE__*/ jsx("span", {
13695
+ className: "diagonal-down",
13696
+ style: {
13697
+ borderTop: line('diagonalDown')
13698
+ }
13699
+ }),
13700
+ line('diagonalUp') && /*#__PURE__*/ jsx("span", {
13701
+ className: "diagonal-up",
13119
13702
  style: {
13120
- borderTop: line('diagonal')
13703
+ borderTop: line('diagonalUp')
13121
13704
  }
13122
13705
  }),
13123
13706
  /*#__PURE__*/ jsx("strong", {
@@ -13388,7 +13971,8 @@ function borderFormatsAt(sheet, row, column) {
13388
13971
  'bottom',
13389
13972
  'left',
13390
13973
  'right',
13391
- 'diagonal'
13974
+ 'diagonalDown',
13975
+ 'diagonalUp'
13392
13976
  ].flatMap((target)=>{
13393
13977
  const line = resolved[target];
13394
13978
  if (!line) return [];
@@ -13510,81 +14094,6 @@ function formatCellsSelectionDescription(source) {
13510
14094
  const columns = source.range.column[1] - source.range.column[0] + 1;
13511
14095
  return `设置当前选区的数字、对齐、字体、边框、填充和保护属性(${rows} 行 × ${columns} 列)。`;
13512
14096
  }
13513
- const MAX_SPREADSHEET_ROWS = 1048576;
13514
- const spreadsheetPasteContentOptions = [
13515
- {
13516
- value: 'all',
13517
- label: '全部',
13518
- richOnly: false
13519
- },
13520
- {
13521
- value: 'formulas',
13522
- label: '公式',
13523
- richOnly: false
13524
- },
13525
- {
13526
- value: 'values',
13527
- label: '值',
13528
- richOnly: false
13529
- },
13530
- {
13531
- value: 'formats',
13532
- label: '格式',
13533
- richOnly: true
13534
- },
13535
- {
13536
- value: 'comments',
13537
- label: '批注',
13538
- richOnly: true
13539
- },
13540
- {
13541
- value: 'validation',
13542
- label: '数据验证',
13543
- richOnly: true
13544
- },
13545
- {
13546
- value: 'all-except-borders',
13547
- label: '边框除外的全部',
13548
- richOnly: true
13549
- },
13550
- {
13551
- value: 'formulas-and-number-formats',
13552
- label: '公式和数字格式',
13553
- richOnly: true
13554
- },
13555
- {
13556
- value: 'values-and-number-formats',
13557
- label: '值和数字格式',
13558
- richOnly: true
13559
- },
13560
- {
13561
- value: 'column-widths',
13562
- label: '列宽',
13563
- richOnly: true
13564
- }
13565
- ];
13566
- const spreadsheetPasteOperationOptions = [
13567
- {
13568
- value: 'none',
13569
- label: '无'
13570
- },
13571
- {
13572
- value: 'add',
13573
- label: '加'
13574
- },
13575
- {
13576
- value: 'subtract',
13577
- label: '减'
13578
- },
13579
- {
13580
- value: 'multiply',
13581
- label: '乘'
13582
- },
13583
- {
13584
- value: 'divide',
13585
- label: '除'
13586
- }
13587
- ];
13588
14097
  function captureSpreadsheetClipboardSnapshot(content, sheetId, selection, plainText) {
13589
14098
  const range = spreadsheet_cell_range_normalizeSpreadsheetCellRange(selection);
13590
14099
  const sheet = content.sheets.find((candidate)=>candidate.id === sheetId);
@@ -20326,20 +20835,22 @@ function applySpreadsheetPasteBorders(content, sheetId, snapshot, plan, processe
20326
20835
  [
20327
20836
  'bottom',
20328
20837
  'b'
20329
- ],
20330
- [
20331
- 'diagonal',
20332
- 's'
20333
20838
  ]
20334
20839
  ];
20335
20840
  for (const [side, key] of sides){
20336
20841
  const line = source.borders[side];
20337
20842
  if (line) value[key] = structuredClone(line);
20338
20843
  }
20339
- return Object.keys(value).length > 2 ? [
20844
+ const diagonal = source.borders.diagonalUp ?? source.borders.diagonalDown ?? null;
20845
+ const withDiagonal = diagonal ? spreadsheetCellValueWithDiagonalBorder(value, {
20846
+ down: Boolean(source.borders.diagonalDown),
20847
+ line: structuredClone(diagonal),
20848
+ up: Boolean(source.borders.diagonalUp)
20849
+ }) : value;
20850
+ return Object.keys(withDiagonal).length > 2 ? [
20340
20851
  {
20341
20852
  rangeType: 'cell',
20342
- value
20853
+ value: withDiagonal
20343
20854
  }
20344
20855
  ] : [];
20345
20856
  });
@@ -22627,6 +23138,16 @@ function SpreadsheetEditorSurface({ autoFocus = true, content, collaborationHist
22627
23138
  ]);
22628
23139
  const tableStylesBySheetRef = useRef(tableStylesBySheet);
22629
23140
  tableStylesBySheetRef.current = tableStylesBySheet;
23141
+ const diagonalBordersBySheet = useMemo(()=>new Map(materializedContent.sheets.flatMap((sheet)=>sheet.id ? [
23142
+ [
23143
+ sheet.id,
23144
+ spreadsheetRenderableDiagonalBorders(sheet)
23145
+ ]
23146
+ ] : [])), [
23147
+ materializedContent.sheets
23148
+ ]);
23149
+ const diagonalBordersBySheetRef = useRef(diagonalBordersBySheet);
23150
+ diagonalBordersBySheetRef.current = diagonalBordersBySheet;
22630
23151
  useEffect(()=>{
22631
23152
  setPreviewActiveSheetId(preview ? contentActiveSheetId : null);
22632
23153
  }, [
@@ -22758,6 +23279,9 @@ function SpreadsheetEditorSurface({ autoFocus = true, content, collaborationHist
22758
23279
  }
22759
23280
  } finally{
22760
23281
  finishSpreadsheetTableCellRender(cell, cellInfo, tableStyle, context);
23282
+ const diagonal = diagonalBordersBySheetRef.current.get(activeSheetIdRef.current)?.get(`${cellInfo.row}_${cellInfo.column}`);
23283
+ if (diagonal?.down) drawSpreadsheetDiagonalDownBorder(context, cellInfo, diagonal.down);
23284
+ if (diagonal?.up) drawSpreadsheetDiagonalUpBorder(context, cellInfo, diagonal.up);
22761
23285
  }
22762
23286
  }
22763
23287
  }), [
@@ -23699,6 +24223,7 @@ function spreadsheetCommandsWithGridFocus(commands, restoreFocus) {
23699
24223
  deleteSelectedStructure: afterSuccessfulCommand(commands.deleteSelectedStructure),
23700
24224
  fillSelectedCells: afterSuccessfulCommand(commands.fillSelectedCells),
23701
24225
  insertSelectedStructure: afterSuccessfulCommand(commands.insertSelectedStructure),
24226
+ insertCurrentDateTime: afterSuccessfulCommand(commands.insertCurrentDateTime),
23702
24227
  mergeSelectedCells: afterSuccessfulCommand(commands.mergeSelectedCells),
23703
24228
  openPasteSpecial: afterSuccessfulCommand(commands.openPasteSpecial),
23704
24229
  pasteSelection: afterSuccessfulCommand(commands.pasteSelection),