@a3s-lab/office 0.26.0 → 0.27.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.
Files changed (81) hide show
  1. package/README.md +75 -2
  2. package/dist/0~4595.js +16 -2
  3. package/dist/0~5093.js +463 -201
  4. package/dist/0~6090.js +77 -77
  5. package/dist/{0~2805.js → 0~7043.js} +305 -2
  6. package/dist/0~document-editor.js +2451 -985
  7. package/dist/0~spreadsheet-editor.js +1324 -378
  8. package/dist/0~work-docx-export.js +492 -10
  9. package/dist/0~work-docx-import.js +171 -98
  10. package/dist/0~work-office-diagnostics.js +198 -4
  11. package/dist/{164.js → 1544.js} +1083 -785
  12. package/dist/4104.js +145 -29
  13. package/dist/6282.js +1774 -384
  14. package/dist/core.js +1 -1
  15. package/dist/index.js +1 -1
  16. package/dist/internal/features/work/editors/document-command-catalog.d.ts +102 -0
  17. package/dist/internal/features/work/editors/document-font-dialog-model.d.ts +83 -0
  18. package/dist/internal/features/work/editors/document-font-dialog-script-font-model.d.ts +18 -0
  19. package/dist/internal/features/work/editors/document-font-dialog.d.ts +9 -0
  20. package/dist/internal/features/work/editors/document-home-ribbon.d.ts +2 -1
  21. package/dist/internal/features/work/editors/document-page-chrome-editor.d.ts +6 -0
  22. package/dist/internal/features/work/editors/document-page-chrome-ribbon.d.ts +2 -1
  23. package/dist/internal/features/work/editors/document-strike-ribbon.d.ts +7 -0
  24. package/dist/internal/features/work/editors/document-text-case-ribbon.d.ts +4 -0
  25. package/dist/internal/features/work/editors/document-toolbar.d.ts +3 -1
  26. package/dist/internal/features/work/editors/document-underline-ribbon.d.ts +9 -0
  27. package/dist/internal/features/work/editors/document-wps-shortcuts.d.ts +1 -0
  28. package/dist/internal/features/work/editors/spreadsheet-cell-fill-format.d.ts +11 -0
  29. package/dist/internal/features/work/editors/spreadsheet-cell-format.d.ts +2 -1
  30. package/dist/internal/features/work/editors/spreadsheet-format-cells-dialog-model.d.ts +13 -2
  31. package/dist/internal/features/work/editors/spreadsheet-format-cells-fill-panel.d.ts +13 -0
  32. package/dist/internal/features/work/editors/spreadsheet-format-cells-fill-preview.d.ts +6 -0
  33. package/dist/internal/features/work/editors/spreadsheet-format-painter.d.ts +1 -1
  34. package/dist/internal/features/work/editors/work-office-chrome.d.ts +9 -1
  35. package/dist/internal/features/work/work-document-character-formatting.d.ts +16 -1
  36. package/dist/internal/features/work/work-document-character-position.d.ts +9 -0
  37. package/dist/internal/features/work/work-document-character-scale.d.ts +8 -0
  38. package/dist/internal/features/work/work-document-character-spacing.d.ts +8 -0
  39. package/dist/internal/features/work/work-document-emphasis.d.ts +7 -0
  40. package/dist/internal/features/work/work-document-equations.d.ts +2 -1
  41. package/dist/internal/features/work/work-document-format-changes.d.ts +16 -2
  42. package/dist/internal/features/work/work-document-hidden-text.d.ts +5 -0
  43. package/dist/internal/features/work/work-document-kerning.d.ts +10 -0
  44. package/dist/internal/features/work/work-document-script-font-extension.d.ts +2 -0
  45. package/dist/internal/features/work/work-document-script-fonts.d.ts +51 -0
  46. package/dist/internal/features/work/work-document-strike.d.ts +21 -0
  47. package/dist/internal/features/work/work-document-text-case.d.ts +10 -0
  48. package/dist/internal/features/work/work-document-underline.d.ts +37 -0
  49. package/dist/internal/features/work/work-document-word-line-metrics.d.ts +12 -0
  50. package/dist/internal/features/work/work-docx-character-position.d.ts +2 -0
  51. package/dist/internal/features/work/work-docx-character-scale.d.ts +2 -0
  52. package/dist/internal/features/work/work-docx-character-spacing.d.ts +4 -0
  53. package/dist/internal/features/work/work-docx-emphasis-diagnostics.d.ts +3 -0
  54. package/dist/internal/features/work/work-docx-emphasis.d.ts +14 -0
  55. package/dist/internal/features/work/work-docx-hidden-text-diagnostics.d.ts +3 -0
  56. package/dist/internal/features/work/work-docx-hidden-text-export.d.ts +16 -0
  57. package/dist/internal/features/work/work-docx-hidden-text.d.ts +11 -0
  58. package/dist/internal/features/work/work-docx-kerning-diagnostics.d.ts +3 -0
  59. package/dist/internal/features/work/work-docx-kerning.d.ts +14 -0
  60. package/dist/internal/features/work/work-docx-run-fonts-diagnostics.d.ts +3 -0
  61. package/dist/internal/features/work/work-docx-run-fonts-export.d.ts +14 -0
  62. package/dist/internal/features/work/work-docx-run-fonts.d.ts +13 -0
  63. package/dist/internal/features/work/work-docx-run-formatting-import.d.ts +23 -2
  64. package/dist/internal/features/work/work-docx-run-script-font-import.d.ts +9 -0
  65. package/dist/internal/features/work/work-docx-strike.d.ts +8 -0
  66. package/dist/internal/features/work/work-docx-theme-reference.d.ts +1 -1
  67. package/dist/internal/features/work/work-docx-twips.d.ts +6 -0
  68. package/dist/internal/features/work/work-docx-underline.d.ts +3 -0
  69. package/dist/internal/features/work/work-spreadsheet-gradient-fill-canvas.d.ts +10 -0
  70. package/dist/internal/features/work/work-spreadsheet-native-fill-canvas.d.ts +8 -0
  71. package/dist/internal/features/work/work-spreadsheet-pattern-fill-canvas.d.ts +8 -0
  72. package/dist/internal/features/work/work-xlsx-cell-style-origin.d.ts +2 -1
  73. package/dist/internal/features/work/work-xlsx-cell-style-writer.d.ts +3 -0
  74. package/dist/internal/features/work/work-xlsx-cell-styles.d.ts +4 -0
  75. package/dist/internal/features/work/work-xlsx-gradient-fill.d.ts +31 -0
  76. package/dist/internal/features/work/work-xlsx-native-fill.d.ts +17 -0
  77. package/dist/internal/features/work/work-xlsx-pattern-fill.d.ts +21 -0
  78. package/dist/office-kernel.wasm +0 -0
  79. package/dist/styles.css +770 -80
  80. package/docs/latest/en/browser-editor-architecture.md +10 -0
  81. package/package.json +32 -1
@@ -4,7 +4,7 @@ import { Workbook } from "@fortune-sheet/react";
4
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 { convertSpanToShareString, genarate, indexToColumnChar, update as core_update } from "@fortune-sheet/core";
7
- import { freezeImportedSpreadsheetCell, spreadsheetMatrixProfile, xlsxRichTextCellText, spreadsheetTextOrientationFromAngle, spreadsheetCellValueWithDiagonalBorder, xlsxSemanticColorMatchesValue, spreadsheetUnderlineCellValue, normalizeXlsxRichTextEditSource, attachSpreadsheetShownCommentCells, sameSpreadsheetHistoryValue, isSpreadsheetConditionalComparisonOperator, defaultSpreadsheetConditionalIconThresholds, normalizeXlsxRichTextCell, normalizeSpreadsheetDateValidationBoundary, unlockedCellCount, editableRangeRequiresCredentials, spreadsheetTextOrientationChoiceFromCell, spreadsheetConditionalThresholdValue, withSheetProtection, defaultSpreadsheetColorScaleThresholds, protectedSheetCount, sameXlsxRichTextRunStyle, withSheetSelectionPermissions, spreadsheetTextOrientationFromCell, patchSpreadsheetRichTextFontRuns, readOfficeSpreadsheetCollaboration as readWorkOfficeSpreadsheetCollaboration, spreadsheetConditionalThresholdsEqual, spreadsheetVisibleTextRotationFromCell, spreadsheetTextOrientationFromChoice, normalizeXlsxSemanticColorOrigin, withoutEditableRange, isSpreadsheetTextOrientationId, normalizeSpreadsheetConditionalVisualOptions, effectiveSpreadsheetPageSetup, normalizeXlsxRichTextColor, isHighSurrogate, withEditableRange, createOfficeSpreadsheetCollaborationBinding as createWorkOfficeSpreadsheetCollaborationBinding, spreadsheetConditionalIconForValue, spreadsheetUnderlineStyle, sheetProtectionAuthority, editableRangeCellCount, registerDerivedSpreadsheetMatrix, SPREADSHEET_CONDITIONAL_COMPARISON_OPERATORS, spreadsheetTextOrientationCellStyle, normalizeSpreadsheetConditionalIconSetFormat, defaultSpreadsheetDataBarOptions, normalizeSheetProtectionAuthority, spreadsheetProtectionKey, normalizeXlsxRichTextRun, spreadsheetDiagonalBorderFromCellValue, SPREADSHEET_CONDITIONAL_ICON_SETS, isLowSurrogate, spreadsheetConditionalComparisonNeedsUpperValue, drawSpreadsheetConditionalIcon, coalesceXlsxRichTextRuns, replaceOfficeSpreadsheetCollaboration as replaceWorkOfficeSpreadsheetCollaboration, validXlsxRichText, isSpreadsheetUnderlineStyle } from "./164.js";
7
+ import { freezeImportedSpreadsheetCell, withXlsxPatternFill, spreadsheetMatrixProfile, xlsxRichTextCellText, spreadsheetTextOrientationFromAngle, spreadsheetCellValueWithDiagonalBorder, xlsxSemanticColorMatchesValue, spreadsheetUnderlineCellValue, normalizeXlsxRichTextEditSource, attachSpreadsheetShownCommentCells, sameSpreadsheetHistoryValue, isSpreadsheetConditionalComparisonOperator, defaultSpreadsheetConditionalIconThresholds, normalizeXlsxRichTextCell, activeXlsxNativeFill, xlsxPatternFillTypes, normalizeSpreadsheetDateValidationBoundary, unlockedCellCount, editableRangeRequiresCredentials, spreadsheetTextOrientationChoiceFromCell, spreadsheetConditionalThresholdValue, withSheetProtection, defaultSpreadsheetColorScaleThresholds, protectedSheetCount, sameXlsxRichTextRunStyle, withSheetSelectionPermissions, spreadsheetTextOrientationFromCell, patchSpreadsheetRichTextFontRuns, readOfficeSpreadsheetCollaboration as readWorkOfficeSpreadsheetCollaboration, spreadsheetConditionalThresholdsEqual, spreadsheetVisibleTextRotationFromCell, spreadsheetTextOrientationFromChoice, normalizeXlsxSemanticColorOrigin, withoutEditableRange, isSpreadsheetTextOrientationId, normalizeSpreadsheetConditionalVisualOptions, withXlsxGradientFill, effectiveSpreadsheetPageSetup, normalizeXlsxPatternFill, normalizeXlsxRichTextColor, isHighSurrogate, xlsxNativeFillCellKeys, withEditableRange, createOfficeSpreadsheetCollaborationBinding as createWorkOfficeSpreadsheetCollaborationBinding, spreadsheetConditionalIconForValue, spreadsheetUnderlineStyle, sheetProtectionAuthority, normalizeXlsxGradientFill, xlsxGradientFillFallbackColor, editableRangeCellCount, registerDerivedSpreadsheetMatrix, deleteXlsxNativeFills, spreadsheetTextOrientationCellStyle, normalizeSpreadsheetConditionalIconSetFormat, defaultSpreadsheetDataBarOptions, normalizeSheetProtectionAuthority, spreadsheetProtectionKey, SPREADSHEET_CONDITIONAL_COMPARISON_OPERATORS, normalizeXlsxRichTextRun, spreadsheetDiagonalBorderFromCellValue, SPREADSHEET_CONDITIONAL_ICON_SETS, isLowSurrogate, spreadsheetConditionalComparisonNeedsUpperValue, drawSpreadsheetConditionalIcon, coalesceXlsxRichTextRuns, replaceOfficeSpreadsheetCollaboration as replaceWorkOfficeSpreadsheetCollaboration, validXlsxRichText, isSpreadsheetUnderlineStyle } from "./1544.js";
8
8
  import { workSpreadsheetChartSupportsGrouping, spreadsheetFormulaRangesForSelection, 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 { normalizeCssColor } from "./9424.js";
@@ -544,6 +544,248 @@ function spreadsheetDiagonalLineDash(style) {
544
544
  ];
545
545
  return [];
546
546
  }
547
+ const MAX_PATH_GRADIENT_CONTOURS = 96;
548
+ function drawSpreadsheetGradientFill(context, bounds, fill, fillRect = context.fillRect) {
549
+ const left = Math.min(bounds.startX, bounds.endX);
550
+ const top = Math.min(bounds.startY, bounds.endY);
551
+ const right = Math.max(bounds.startX, bounds.endX);
552
+ const bottom = Math.max(bounds.startY, bounds.endY);
553
+ const width = right - left;
554
+ const height = bottom - top;
555
+ if (width <= 0 || height <= 0) return;
556
+ context.save();
557
+ if ('linear' === fill.type) drawLinearGradient(context, left, top, width, height, fill, fillRect);
558
+ else drawPathGradient(context, left, top, width, height, fill, fillRect);
559
+ context.restore();
560
+ }
561
+ function drawLinearGradient(context, left, top, width, height, fill, fillRect) {
562
+ if ('function' != typeof context.createLinearGradient) {
563
+ context.fillStyle = fill.stops[0]?.color ?? '#ffffff';
564
+ fillRect.call(context, left, top, width, height);
565
+ return;
566
+ }
567
+ const radians = fill.degree * Math.PI / 180;
568
+ const horizontal = Math.cos(radians);
569
+ const vertical = Math.sin(radians);
570
+ const centerX = left + width / 2;
571
+ const centerY = top + height / 2;
572
+ const span = Math.abs(width * horizontal) + Math.abs(height * vertical);
573
+ const gradient = context.createLinearGradient(centerX - horizontal * span / 2, centerY - vertical * span / 2, centerX + horizontal * span / 2, centerY + vertical * span / 2);
574
+ for (const stop of fill.stops)gradient.addColorStop(stop.position, stop.color);
575
+ context.fillStyle = gradient;
576
+ fillRect.call(context, left, top, width, height);
577
+ }
578
+ function drawPathGradient(context, left, top, width, height, fill, fillRect) {
579
+ const innerLeft = left + width * fill.left;
580
+ const innerRight = left + width * fill.right;
581
+ const innerTop = top + height * fill.top;
582
+ const innerBottom = top + height * fill.bottom;
583
+ const contours = Math.min(MAX_PATH_GRADIENT_CONTOURS, Math.max(2, Math.ceil(Math.max(width, height))));
584
+ for(let index = contours; index >= 0; index -= 1){
585
+ const progress = index / contours;
586
+ const contourLeft = interpolate(innerLeft, left, progress);
587
+ const contourRight = interpolate(innerRight, left + width, progress);
588
+ const contourTop = interpolate(innerTop, top, progress);
589
+ const contourBottom = interpolate(innerBottom, top + height, progress);
590
+ context.fillStyle = gradientColorAt(fill.stops, progress);
591
+ fillRect.call(context, contourLeft, contourTop, contourRight - contourLeft, contourBottom - contourTop);
592
+ }
593
+ }
594
+ function gradientColorAt(stops, position) {
595
+ const first = stops[0];
596
+ const last = stops.at(-1);
597
+ if (!first || !last || position <= first.position) return first?.color ?? '#ffffff';
598
+ if (position >= last.position) return last.color;
599
+ for(let index = 1; index < stops.length; index += 1){
600
+ const right = stops[index];
601
+ const left = stops[index - 1];
602
+ if (!left || !right || position > right.position) continue;
603
+ const span = right.position - left.position;
604
+ const progress = span > 0 ? (position - left.position) / span : 1;
605
+ return interpolateRgb(left.color, right.color, progress);
606
+ }
607
+ return last.color;
608
+ }
609
+ function interpolateRgb(left, right, progress) {
610
+ const leftRgb = rgbChannels(left);
611
+ const rightRgb = rgbChannels(right);
612
+ if (!leftRgb || !rightRgb) return progress < 0.5 ? left : right;
613
+ return `#${leftRgb.map((channel, index)=>Math.round(interpolate(channel, rightRgb[index] ?? channel, progress)).toString(16).padStart(2, '0')).join('')}`;
614
+ }
615
+ function rgbChannels(color) {
616
+ if (!/^#[0-9a-f]{6}$/i.test(color)) return null;
617
+ return [
618
+ Number.parseInt(color.slice(1, 3), 16),
619
+ Number.parseInt(color.slice(3, 5), 16),
620
+ Number.parseInt(color.slice(5, 7), 16)
621
+ ];
622
+ }
623
+ function interpolate(left, right, progress) {
624
+ return left + (right - left) * progress;
625
+ }
626
+ function drawSpreadsheetPatternFillOverlay(context, bounds, fill) {
627
+ const left = Math.min(bounds.startX, bounds.endX) + 1;
628
+ const top = Math.min(bounds.startY, bounds.endY) + 1;
629
+ const right = Math.max(bounds.startX, bounds.endX) - 1;
630
+ const bottom = Math.max(bounds.startY, bounds.endY) - 1;
631
+ if (right <= left || bottom <= top) return;
632
+ context.save();
633
+ context.beginPath();
634
+ context.rect(left, top, right - left, bottom - top);
635
+ context.clip();
636
+ context.strokeStyle = fill.foregroundColor;
637
+ context.fillStyle = fill.foregroundColor;
638
+ context.setLineDash([]);
639
+ switch(fill.patternType){
640
+ case 'darkHorizontal':
641
+ drawHorizontalLines(context, left, top, right, bottom, 4, 2);
642
+ break;
643
+ case 'lightHorizontal':
644
+ drawHorizontalLines(context, left, top, right, bottom, 7, 1);
645
+ break;
646
+ case 'darkVertical':
647
+ drawVerticalLines(context, left, top, right, bottom, 4, 2);
648
+ break;
649
+ case 'lightVertical':
650
+ drawVerticalLines(context, left, top, right, bottom, 7, 1);
651
+ break;
652
+ case 'darkDown':
653
+ drawDiagonalLines(context, left, top, right, bottom, 5, 2, 'down');
654
+ break;
655
+ case 'lightDown':
656
+ drawDiagonalLines(context, left, top, right, bottom, 8, 1, 'down');
657
+ break;
658
+ case 'darkUp':
659
+ drawDiagonalLines(context, left, top, right, bottom, 5, 2, 'up');
660
+ break;
661
+ case 'lightUp':
662
+ drawDiagonalLines(context, left, top, right, bottom, 8, 1, 'up');
663
+ break;
664
+ case 'darkGrid':
665
+ drawHorizontalLines(context, left, top, right, bottom, 5, 1.5);
666
+ drawVerticalLines(context, left, top, right, bottom, 5, 1.5);
667
+ break;
668
+ case 'lightGrid':
669
+ drawHorizontalLines(context, left, top, right, bottom, 8, 1);
670
+ drawVerticalLines(context, left, top, right, bottom, 8, 1);
671
+ break;
672
+ case 'darkTrellis':
673
+ drawDiagonalLines(context, left, top, right, bottom, 6, 1.5, 'down');
674
+ drawDiagonalLines(context, left, top, right, bottom, 6, 1.5, 'up');
675
+ break;
676
+ case 'lightTrellis':
677
+ drawDiagonalLines(context, left, top, right, bottom, 10, 1, 'down');
678
+ drawDiagonalLines(context, left, top, right, bottom, 10, 1, 'up');
679
+ break;
680
+ case 'gray0625':
681
+ drawPatternDots(context, left, top, right, bottom, 8, 1);
682
+ break;
683
+ case 'gray125':
684
+ drawPatternDots(context, left, top, right, bottom, 6, 1);
685
+ break;
686
+ case 'lightGray':
687
+ drawPatternDots(context, left, top, right, bottom, 4, 1.5);
688
+ break;
689
+ case 'mediumGray':
690
+ drawDiagonalLines(context, left, top, right, bottom, 4, 1, 'down');
691
+ drawDiagonalLines(context, left, top, right, bottom, 4, 1, 'up');
692
+ break;
693
+ case 'darkGray':
694
+ context.fillRect(left, top, right - left, bottom - top);
695
+ context.fillStyle = fill.backgroundColor;
696
+ drawPatternDots(context, left, top, right, bottom, 4, 1.5);
697
+ break;
698
+ }
699
+ context.restore();
700
+ }
701
+ function drawHorizontalLines(context, left, top, right, bottom, requestedSpacing, lineWidth) {
702
+ const spacing = boundedLineSpacing(bottom - top, requestedSpacing);
703
+ context.lineWidth = lineWidth;
704
+ context.beginPath();
705
+ for(let y = alignedPatternStart(top, spacing); y <= bottom; y += spacing){
706
+ context.moveTo(left, crispPatternCoordinate(y, lineWidth));
707
+ context.lineTo(right, crispPatternCoordinate(y, lineWidth));
708
+ }
709
+ context.stroke();
710
+ }
711
+ function drawVerticalLines(context, left, top, right, bottom, requestedSpacing, lineWidth) {
712
+ const spacing = boundedLineSpacing(right - left, requestedSpacing);
713
+ context.lineWidth = lineWidth;
714
+ context.beginPath();
715
+ for(let x = alignedPatternStart(left, spacing); x <= right; x += spacing){
716
+ context.moveTo(crispPatternCoordinate(x, lineWidth), top);
717
+ context.lineTo(crispPatternCoordinate(x, lineWidth), bottom);
718
+ }
719
+ context.stroke();
720
+ }
721
+ function drawDiagonalLines(context, left, top, right, bottom, requestedSpacing, lineWidth, direction) {
722
+ const height = bottom - top;
723
+ const spacing = boundedLineSpacing(right - left + height, requestedSpacing);
724
+ context.lineWidth = lineWidth;
725
+ context.beginPath();
726
+ const first = alignedPatternStart(left - height, spacing);
727
+ for(let x = first; x <= right; x += spacing)if ('down' === direction) {
728
+ context.moveTo(x, top);
729
+ context.lineTo(x + height, bottom);
730
+ } else {
731
+ context.moveTo(x, bottom);
732
+ context.lineTo(x + height, top);
733
+ }
734
+ context.stroke();
735
+ }
736
+ function drawPatternDots(context, left, top, right, bottom, requestedSpacing, size) {
737
+ const area = Math.max(1, (right - left) * (bottom - top));
738
+ const spacing = Math.max(requestedSpacing, Math.sqrt(area / 2048));
739
+ const startX = alignedPatternStart(left, spacing);
740
+ const startY = alignedPatternStart(top, spacing);
741
+ for(let y = startY; y <= bottom; y += spacing){
742
+ const offset = Math.round(y / spacing) % 2 ? spacing / 2 : 0;
743
+ for(let x = startX + offset; x <= right; x += spacing)context.fillRect(x, y, size, size);
744
+ }
745
+ }
746
+ function alignedPatternStart(value, spacing) {
747
+ return Math.floor(value / spacing) * spacing;
748
+ }
749
+ function boundedLineSpacing(span, requested) {
750
+ return Math.max(requested, span / 512);
751
+ }
752
+ function crispPatternCoordinate(value, lineWidth) {
753
+ return Math.round(value) + (Math.round(lineWidth) % 2 ? 0.5 : 0);
754
+ }
755
+ const pendingContextRestores = new WeakMap();
756
+ function beginSpreadsheetNativeFillRender(fill, context) {
757
+ finishSpreadsheetNativeFillRender(context);
758
+ if (!fill || 'function' != typeof context.fillRect) return;
759
+ context.fillStyle = 'gradient' === fill.kind ? fill.value.stops[0]?.color ?? '#ffffff' : fill.value.backgroundColor;
760
+ const fillRect = context.fillRect;
761
+ pendingContextRestores.set(context, {
762
+ fillRect,
763
+ fillRectOwned: Object.hasOwn(context, 'fillRect')
764
+ });
765
+ context.fillRect = (x, y, width, height)=>{
766
+ restoreSpreadsheetNativeFillContext(context);
767
+ const bounds = {
768
+ endX: x + width,
769
+ endY: y + height,
770
+ startX: x,
771
+ startY: y
772
+ };
773
+ if ('gradient' === fill.kind) return void drawSpreadsheetGradientFill(context, bounds, fill.value, fillRect);
774
+ context.fillStyle = fill.value.backgroundColor;
775
+ fillRect.call(context, x, y, width, height);
776
+ drawSpreadsheetPatternFillOverlay(context, bounds, fill.value);
777
+ };
778
+ }
779
+ function finishSpreadsheetNativeFillRender(context) {
780
+ restoreSpreadsheetNativeFillContext(context);
781
+ }
782
+ function restoreSpreadsheetNativeFillContext(context) {
783
+ const restore = pendingContextRestores.get(context);
784
+ if (!restore) return;
785
+ if (restore.fillRectOwned) context.fillRect = restore.fillRect;
786
+ else delete context.fillRect;
787
+ pendingContextRestores.delete(context);
788
+ }
547
789
  function spreadsheet_cell_range_normalizeSpreadsheetCellRange(value) {
548
790
  const row = normalizeSpreadsheetCellRangeAxis(value.row);
549
791
  const column = normalizeSpreadsheetCellRangeAxis(value.column);
@@ -4701,7 +4943,8 @@ const spreadsheetCellFormatProperties = [
4701
4943
  'rt',
4702
4944
  'ct',
4703
4945
  'lo',
4704
- 'hi'
4946
+ 'hi',
4947
+ ...xlsxNativeFillCellKeys
4705
4948
  ];
4706
4949
  function clearSpreadsheetSheetSelection(sheet, selection, mode) {
4707
4950
  const range = normalizeClearRange(selection);
@@ -5208,6 +5451,79 @@ function setSpreadsheetCellBordersPerCell(content, sheetId, range, formats) {
5208
5451
  sheets
5209
5452
  };
5210
5453
  }
5454
+ function spreadsheetCellFillFormat(cell) {
5455
+ const nativeFill = activeXlsxNativeFill(cell);
5456
+ if (nativeFill) return nativeFill;
5457
+ const color = normalizeSpreadsheetFillColor(cell?.bg);
5458
+ return color ? {
5459
+ color,
5460
+ kind: 'solid'
5461
+ } : {
5462
+ kind: 'none'
5463
+ };
5464
+ }
5465
+ function normalizeSpreadsheetCellFillFormat(value) {
5466
+ if (!spreadsheet_cell_fill_format_isRecord(value)) return null;
5467
+ if ('none' === value.kind) return {
5468
+ kind: 'none'
5469
+ };
5470
+ if ('solid' === value.kind) {
5471
+ const color = normalizeSpreadsheetFillColor(value.color);
5472
+ return color ? {
5473
+ color,
5474
+ kind: 'solid'
5475
+ } : null;
5476
+ }
5477
+ if ('pattern' === value.kind) {
5478
+ const fill = normalizeXlsxPatternFill(value.value);
5479
+ return fill ? {
5480
+ kind: 'pattern',
5481
+ value: fill
5482
+ } : null;
5483
+ }
5484
+ if ('gradient' === value.kind) {
5485
+ const fill = normalizeXlsxGradientFill(value.value);
5486
+ return fill ? {
5487
+ kind: 'gradient',
5488
+ value: fill
5489
+ } : null;
5490
+ }
5491
+ return null;
5492
+ }
5493
+ function withSpreadsheetCellFillFormat(cell, fill) {
5494
+ const normalized = normalizeSpreadsheetCellFillFormat(fill);
5495
+ if (!normalized) return null;
5496
+ const next = {
5497
+ ...cell
5498
+ };
5499
+ deleteXlsxNativeFills(next);
5500
+ if ('none' === normalized.kind) {
5501
+ delete next.bg;
5502
+ return next;
5503
+ }
5504
+ if ('solid' === normalized.kind) {
5505
+ next.bg = normalized.color;
5506
+ return next;
5507
+ }
5508
+ if ('pattern' === normalized.kind) {
5509
+ next.bg = normalized.value.backgroundColor;
5510
+ return withXlsxPatternFill(next, normalized.value);
5511
+ }
5512
+ next.bg = xlsxGradientFillFallbackColor(normalized.value);
5513
+ return withXlsxGradientFill(next, normalized.value);
5514
+ }
5515
+ function normalizeSpreadsheetFillColor(value) {
5516
+ if ('string' != typeof value) return null;
5517
+ const color = value.trim().toLowerCase();
5518
+ if (/^#[0-9a-f]{6}$/.test(color)) return color;
5519
+ if (!/^#[0-9a-f]{3}$/.test(color)) return null;
5520
+ return `#${[
5521
+ ...color.slice(1)
5522
+ ].map((character)=>character.repeat(2)).join('')}`;
5523
+ }
5524
+ function spreadsheet_cell_fill_format_isRecord(value) {
5525
+ return 'object' == typeof value && null !== value && !Array.isArray(value);
5526
+ }
5211
5527
  const MAX_SPREADSHEET_CELL_FORMAT_CELLS = 10000;
5212
5528
  const patchKeys = new Set([
5213
5529
  'numberFormat',
@@ -5223,7 +5539,7 @@ const patchKeys = new Set([
5223
5539
  'italic',
5224
5540
  'underline',
5225
5541
  'strike',
5226
- 'fillColor',
5542
+ 'fill',
5227
5543
  'borders',
5228
5544
  'locked',
5229
5545
  'hidden'
@@ -5243,7 +5559,7 @@ function canApplySpreadsheetCellFormat(content, request) {
5243
5559
  'top',
5244
5560
  'middle',
5245
5561
  'bottom'
5246
- ].includes(patch.verticalAlignment) || void 0 !== patch.wrapText && 'boolean' != typeof patch.wrapText || void 0 !== patch.rotation && (!Number.isInteger(patch.rotation) || patch.rotation < -90 || patch.rotation > 90) || void 0 !== patch.textOrientation && !isSpreadsheetTextOrientationId(patch.textOrientation) || void 0 !== patch.rotation && void 0 !== patch.textOrientation || void 0 !== patch.fontFamily && !validTrimmedString(patch.fontFamily, 128) || void 0 !== patch.fontSize && (!Number.isFinite(patch.fontSize) || patch.fontSize < 1 || patch.fontSize > 409) || void 0 !== patch.fontColor && !normalizeColor(patch.fontColor) || void 0 !== patch.fillColor && null !== patch.fillColor && !normalizeColor(patch.fillColor) || !validOptionalBoolean(patch.bold) || !validOptionalBoolean(patch.italic) || void 0 !== patch.underline && !isSpreadsheetUnderlineStyle(patch.underline) || !validOptionalBoolean(patch.strike) || !validOptionalBoolean(patch.locked) || !validOptionalBoolean(patch.hidden)) return false;
5562
+ ].includes(patch.verticalAlignment) || void 0 !== patch.wrapText && 'boolean' != typeof patch.wrapText || void 0 !== patch.rotation && (!Number.isInteger(patch.rotation) || patch.rotation < -90 || patch.rotation > 90) || void 0 !== patch.textOrientation && !isSpreadsheetTextOrientationId(patch.textOrientation) || void 0 !== patch.rotation && void 0 !== patch.textOrientation || void 0 !== patch.fontFamily && !validTrimmedString(patch.fontFamily, 128) || void 0 !== patch.fontSize && (!Number.isFinite(patch.fontSize) || patch.fontSize < 1 || patch.fontSize > 409) || void 0 !== patch.fontColor && !normalizeColor(patch.fontColor) || void 0 !== patch.fill && !normalizeSpreadsheetCellFillFormat(patch.fill) || !validOptionalBoolean(patch.bold) || !validOptionalBoolean(patch.italic) || void 0 !== patch.underline && !isSpreadsheetUnderlineStyle(patch.underline) || !validOptionalBoolean(patch.strike) || !validOptionalBoolean(patch.locked) || !validOptionalBoolean(patch.hidden)) return false;
5247
5563
  if (void 0 !== patch.borders) {
5248
5564
  const normalized = patch.borders.map(normalizeSpreadsheetBorderFormat);
5249
5565
  if (normalized.some((format)=>!format || ![
@@ -5376,7 +5692,7 @@ function formatSparseCells(sheet, range, patch) {
5376
5692
  };
5377
5693
  }
5378
5694
  function formatCell(source, patch) {
5379
- const next = {
5695
+ let next = {
5380
5696
  ...source ?? {}
5381
5697
  };
5382
5698
  const writable = next;
@@ -5418,8 +5734,10 @@ function formatCell(source, patch) {
5418
5734
  if (void 0 !== patch.italic) next.it = patch.italic ? 1 : 0;
5419
5735
  if (void 0 !== patch.underline) next.un = spreadsheetUnderlineCellValue(patch.underline);
5420
5736
  if (void 0 !== patch.strike) next.cl = patch.strike ? 1 : 0;
5421
- if (void 0 !== patch.fillColor) if (null === patch.fillColor) delete next.bg;
5422
- else next.bg = normalizeColor(patch.fillColor) ?? patch.fillColor;
5737
+ if (void 0 !== patch.fill) {
5738
+ const filled = withSpreadsheetCellFillFormat(next, patch.fill);
5739
+ if (filled) next = filled;
5740
+ }
5423
5741
  if (void 0 !== patch.locked || void 0 !== patch.hidden) {
5424
5742
  delete next.lo;
5425
5743
  delete next.hi;
@@ -5910,10 +6228,14 @@ function applySpreadsheetCellStyle(content, sheetId, range, preset) {
5910
6228
  for(let row = normalizedRange.row[0]; row <= normalizedRange.row[1]; row += 1){
5911
6229
  const values = data[row] ?? [];
5912
6230
  data[row] = values;
5913
- for(let column = normalizedRange.column[0]; column <= normalizedRange.column[1]; column += 1)values[column] = {
5914
- ...values[column] ?? {},
5915
- ...definition.format
5916
- };
6231
+ for(let column = normalizedRange.column[0]; column <= normalizedRange.column[1]; column += 1){
6232
+ const cell = {
6233
+ ...values[column] ?? {},
6234
+ ...definition.format
6235
+ };
6236
+ deleteXlsxNativeFills(cell);
6237
+ values[column] = cell;
6238
+ }
5917
6239
  }
5918
6240
  const nextSheet = {
5919
6241
  ...sheet,
@@ -9675,10 +9997,35 @@ function formatCells(context, attribute, value) {
9675
9997
  if (context.richTextFormat?.canApply(attribute, value)) return context.richTextFormat.apply(attribute, value);
9676
9998
  if (!context.workbook || !context.targetSheetId) return false;
9677
9999
  if ('ct' === attribute && !isSpreadsheetCellTypeFormat(value)) return false;
10000
+ const range = spreadsheetLiveCommandRange(context);
10001
+ const options = {
10002
+ id: context.targetSheetId
10003
+ };
9678
10004
  try {
9679
- context.workbook.setCellFormatByRange(attribute, value, spreadsheetLiveCommandRange(context), {
9680
- id: context.targetSheetId
9681
- });
10005
+ if ('bg' === attribute) {
10006
+ context.workbook.batchCallApis([
10007
+ {
10008
+ name: 'setCellFormatByRange',
10009
+ args: [
10010
+ attribute,
10011
+ value,
10012
+ range,
10013
+ options
10014
+ ]
10015
+ },
10016
+ ...xlsxNativeFillCellKeys.map((fillAttribute)=>({
10017
+ name: 'setCellFormatByRange',
10018
+ args: [
10019
+ fillAttribute,
10020
+ void 0,
10021
+ range,
10022
+ options
10023
+ ]
10024
+ }))
10025
+ ]);
10026
+ return true;
10027
+ }
10028
+ context.workbook.setCellFormatByRange(attribute, value, range, options);
9682
10029
  return true;
9683
10030
  } catch {
9684
10031
  return false;
@@ -13963,146 +14310,950 @@ function SpreadsheetFindBar({ sheet, focusRequest, onClose, onSelectMatch }) {
13963
14310
  ]
13964
14311
  });
13965
14312
  }
13966
- const MIXED_VALUE = '__mixed__';
13967
- const numberFormatOptions = [
13968
- 'general',
13969
- 'number',
13970
- 'currency',
13971
- 'accounting',
13972
- 'percent',
13973
- 'date',
13974
- 'time',
13975
- 'scientific',
13976
- 'fraction',
13977
- 'text',
13978
- 'custom'
13979
- ].map((value)=>({
13980
- value: value,
13981
- label: spreadsheetNumberFormatPresetLabels[value]
13982
- }));
13983
- const horizontalOptions = [
13984
- {
13985
- value: 'general',
13986
- label: '常规'
13987
- },
13988
- {
13989
- value: 'left',
13990
- label: '左对齐'
13991
- },
13992
- {
13993
- value: 'center',
13994
- label: '居中'
13995
- },
13996
- {
13997
- value: 'right',
13998
- label: '右对齐'
13999
- }
14000
- ];
14001
- const verticalOptions = [
14002
- {
14003
- value: 'top',
14004
- label: '顶端对齐'
14005
- },
14006
- {
14007
- value: 'middle',
14008
- label: '垂直居中'
14009
- },
14010
- {
14011
- value: 'bottom',
14012
- label: '底端对齐'
14013
- }
14014
- ];
14015
- const spreadsheet_format_cells_dialog_panels_underlineOptions = [
14016
- {
14017
- value: 'none',
14018
- label: '无'
14019
- },
14020
- {
14021
- value: 'single',
14022
- label: '单下划线'
14023
- },
14024
- {
14025
- value: 'double',
14026
- label: '双下划线'
14027
- },
14028
- {
14029
- value: 'singleAccounting',
14030
- label: '单会计用下划线'
14031
- },
14032
- {
14033
- value: 'doubleAccounting',
14034
- label: '双会计用下划线'
14035
- }
14036
- ];
14037
- const borderStyleOptions = [
14038
- {
14039
- value: 'thin',
14040
- label: '细实线'
14041
- },
14042
- {
14043
- value: 'dotted',
14044
- label: '点线'
14045
- },
14046
- {
14047
- value: 'dashed',
14048
- label: '虚线'
14049
- },
14050
- {
14051
- value: 'dash-dot',
14052
- label: '点划线'
14053
- },
14054
- {
14055
- value: 'medium',
14056
- label: '中等实线'
14057
- },
14058
- {
14059
- value: 'medium-dashed',
14060
- label: '中等虚线'
14061
- },
14062
- {
14063
- value: 'thick',
14064
- label: '粗实线'
14065
- }
14066
- ];
14067
- const borderTargets = [
14068
- {
14069
- target: 'top',
14070
- label: '上框线'
14071
- },
14072
- {
14073
- target: 'bottom',
14074
- label: '下框线'
14075
- },
14076
- {
14077
- target: 'left',
14078
- label: '左框线'
14079
- },
14080
- {
14081
- target: 'right',
14082
- label: '右框线'
14083
- },
14084
- {
14085
- target: 'diagonalDown',
14086
- label: '斜下框线'
14087
- },
14088
- {
14089
- target: 'diagonalUp',
14090
- label: '斜上框线'
14091
- }
14092
- ];
14093
- function SpreadsheetFormatCellsPanel(props) {
14094
- return /*#__PURE__*/ jsxs("section", {
14095
- id: `${props.idBase}-${props.activeTab}-panel`,
14096
- className: "work-spreadsheet-format-cells-panel",
14097
- role: "tabpanel",
14098
- "aria-labelledby": `${props.idBase}-${props.activeTab}-tab`,
14099
- tabIndex: -1,
14100
- children: [
14101
- 'number' === props.activeTab && /*#__PURE__*/ jsx(NumberPanel, {
14102
- ...props
14103
- }),
14104
- 'alignment' === props.activeTab && /*#__PURE__*/ jsx(AlignmentPanel, {
14105
- ...props
14313
+ function SegmentedControl({ ariaLabel, value, items, onChange, size = 'standard', layout = 'fit', disabled = false, className = '' }) {
14314
+ const groupName = useId();
14315
+ return /*#__PURE__*/ jsx("div", {
14316
+ className: `ds-segmented-control ${size} ${layout}${className ? ` ${className}` : ''}`,
14317
+ role: "radiogroup",
14318
+ "aria-label": ariaLabel,
14319
+ "aria-disabled": disabled || void 0,
14320
+ "aria-orientation": "horizontal",
14321
+ children: items.map((item)=>{
14322
+ const selected = item.id === value;
14323
+ const itemDisabled = disabled || item.disabled;
14324
+ return /*#__PURE__*/ jsxs("label", {
14325
+ className: `ds-segmented-control-item${selected ? ' selected' : ''}`,
14326
+ title: item.description,
14327
+ children: [
14328
+ /*#__PURE__*/ jsx("input", {
14329
+ type: "radio",
14330
+ name: groupName,
14331
+ value: item.id,
14332
+ checked: selected,
14333
+ disabled: itemDisabled,
14334
+ "aria-label": item.ariaLabel,
14335
+ onChange: ()=>onChange(item.id)
14336
+ }),
14337
+ /*#__PURE__*/ jsxs("span", {
14338
+ className: "ds-segmented-control-content",
14339
+ children: [
14340
+ item.icon && /*#__PURE__*/ jsx("span", {
14341
+ className: "ds-segmented-control-icon",
14342
+ "aria-hidden": "true",
14343
+ children: item.icon
14344
+ }),
14345
+ /*#__PURE__*/ jsx("span", {
14346
+ className: "ds-segmented-control-label",
14347
+ children: item.label
14348
+ })
14349
+ ]
14350
+ })
14351
+ ]
14352
+ }, item.id);
14353
+ })
14354
+ });
14355
+ }
14356
+ function createSpreadsheetFormatCellsDialogSource(content, sheetId, rangeInput, cells, requestedActiveCell) {
14357
+ const range = spreadsheet_cell_range_normalizeSpreadsheetCellRange(rangeInput);
14358
+ const sheet = content.sheets.find((candidate)=>candidate.id === sheetId);
14359
+ if (!range || !sheet || spreadsheet_cell_range_spreadsheetCellRangeArea(range) > 10000) return null;
14360
+ const activeRow = clampIndex(requestedActiveCell.row, range.row[0], range.row[1]);
14361
+ const activeColumn = clampIndex(requestedActiveCell.column, range.column[0], range.column[1]);
14362
+ const activeCell = cells[activeRow - range.row[0]]?.[activeColumn - range.column[0]] ?? null;
14363
+ const values = (resolve)=>{
14364
+ const activeValue = resolve(activeCell, activeRow, activeColumn);
14365
+ let mixed = false;
14366
+ for(let row = range.row[0]; row <= range.row[1] && !mixed; row += 1)for(let column = range.column[0]; column <= range.column[1]; column += 1){
14367
+ const cell = cells[row - range.row[0]]?.[column - range.column[0]] ?? null;
14368
+ if (!sameDialogValue(resolve(cell, row, column), activeValue)) {
14369
+ mixed = true;
14370
+ break;
14371
+ }
14372
+ }
14373
+ return {
14374
+ value: activeValue,
14375
+ mixed
14376
+ };
14377
+ };
14378
+ const borders = borderFormatsAt(sheet, activeRow, activeColumn);
14379
+ return {
14380
+ sheetId,
14381
+ range,
14382
+ activeCell,
14383
+ fields: {
14384
+ numberFormat: values((cell)=>cell?.ct?.fa?.trim() || 'General'),
14385
+ horizontalAlignment: values((cell)=>spreadsheet_format_cells_dialog_model_horizontalAlignment(cell?.ht)),
14386
+ verticalAlignment: values((cell)=>verticalAlignment(cell?.vt)),
14387
+ wrapText: values((cell)=>'2' === String(cell?.tb)),
14388
+ rotation: values((cell)=>spreadsheetVisibleTextRotationFromCell(cell)),
14389
+ fontFamily: values((cell)=>'string' == typeof cell?.ff && cell.ff.trim() ? cell.ff.trim() : 'Aptos'),
14390
+ fontSize: values((cell)=>'number' == typeof cell?.fs && Number.isFinite(cell.fs) ? cell.fs : 10),
14391
+ fontColor: values((cell)=>normalizedColor(cell?.fc, '#172033')),
14392
+ bold: values((cell)=>1 === Number(cell?.bl)),
14393
+ italic: values((cell)=>1 === Number(cell?.it)),
14394
+ underline: values((cell)=>spreadsheetUnderlineStyle(cell?.un)),
14395
+ strike: values((cell)=>1 === Number(cell?.cl)),
14396
+ fill: values((cell)=>spreadsheetCellFillFormat(cell)),
14397
+ borders: {
14398
+ value: borders,
14399
+ mixed: spreadsheet_cell_range_spreadsheetCellRangeArea(range) > 1
14400
+ },
14401
+ locked: values((cell, row, column)=>spreadsheetCellProtectionAt(sheet, row, column, cell).locked),
14402
+ hidden: values((cell, row, column)=>spreadsheetCellProtectionAt(sheet, row, column, cell).hidden)
14403
+ }
14404
+ };
14405
+ }
14406
+ function createSpreadsheetFormatCellsDraft(source) {
14407
+ const borders = source.fields.borders.value.map((format)=>({
14408
+ ...format
14409
+ }));
14410
+ return {
14411
+ numberFormat: source.fields.numberFormat.value,
14412
+ horizontalAlignment: source.fields.horizontalAlignment.value,
14413
+ verticalAlignment: source.fields.verticalAlignment.value,
14414
+ wrapText: source.fields.wrapText.value,
14415
+ rotation: source.fields.rotation.value,
14416
+ fontFamily: source.fields.fontFamily.value,
14417
+ fontSize: source.fields.fontSize.value,
14418
+ fontColor: source.fields.fontColor.value,
14419
+ bold: source.fields.bold.value,
14420
+ italic: source.fields.italic.value,
14421
+ underline: source.fields.underline.value,
14422
+ strike: source.fields.strike.value,
14423
+ fill: createSpreadsheetFormatCellsFillDraft(source.fields.fill.value),
14424
+ borders,
14425
+ borderColor: borders[0]?.color ?? '#172033',
14426
+ borderStyle: borders[0]?.style ?? 'thin',
14427
+ locked: source.fields.locked.value,
14428
+ hidden: source.fields.hidden.value
14429
+ };
14430
+ }
14431
+ function spreadsheetFormatCellsPatch(source, draft, touched) {
14432
+ const patch = {};
14433
+ if (shouldEmit(source.fields.numberFormat, draft.numberFormat, touched.numberFormat)) patch.numberFormat = draft.numberFormat.trim();
14434
+ if (shouldEmit(source.fields.horizontalAlignment, draft.horizontalAlignment, touched.horizontalAlignment)) patch.horizontalAlignment = draft.horizontalAlignment;
14435
+ if (shouldEmit(source.fields.verticalAlignment, draft.verticalAlignment, touched.verticalAlignment)) patch.verticalAlignment = draft.verticalAlignment;
14436
+ if (shouldEmit(source.fields.wrapText, draft.wrapText, touched.wrapText)) patch.wrapText = draft.wrapText;
14437
+ if (shouldEmit(source.fields.rotation, draft.rotation, touched.rotation)) patch.rotation = draft.rotation;
14438
+ if (shouldEmit(source.fields.fontFamily, draft.fontFamily, touched.fontFamily)) patch.fontFamily = draft.fontFamily.trim();
14439
+ if (shouldEmit(source.fields.fontSize, draft.fontSize, touched.fontSize)) patch.fontSize = draft.fontSize;
14440
+ if (shouldEmit(source.fields.fontColor, draft.fontColor, touched.fontColor)) patch.fontColor = draft.fontColor;
14441
+ if (shouldEmit(source.fields.bold, draft.bold, touched.bold)) patch.bold = draft.bold;
14442
+ if (shouldEmit(source.fields.italic, draft.italic, touched.italic)) patch.italic = draft.italic;
14443
+ if (shouldEmit(source.fields.underline, draft.underline, touched.underline)) patch.underline = draft.underline;
14444
+ if (shouldEmit(source.fields.strike, draft.strike, touched.strike)) patch.strike = draft.strike;
14445
+ const fill = spreadsheetFormatCellsActiveFill(draft);
14446
+ if (shouldEmit(source.fields.fill, fill, touched.fill)) patch.fill = fill;
14447
+ if (shouldEmit(source.fields.borders, draft.borders, touched.borders)) patch.borders = draft.borders.map((format)=>({
14448
+ ...format
14449
+ }));
14450
+ if (shouldEmit(source.fields.locked, draft.locked, touched.locked)) patch.locked = draft.locked;
14451
+ if (shouldEmit(source.fields.hidden, draft.hidden, touched.hidden)) patch.hidden = draft.hidden;
14452
+ return patch;
14453
+ }
14454
+ function spreadsheetFormatCellsDraftErrors(draft) {
14455
+ const errors = {};
14456
+ if (draft.numberFormat.trim()) {
14457
+ if (draft.numberFormat.trim().length > 255) errors.numberFormat = '数字格式代码不能超过 255 个字符。';
14458
+ } else errors.numberFormat = '请输入数字格式代码。';
14459
+ if (!Number.isFinite(draft.fontSize) || draft.fontSize < 1 || draft.fontSize > 409) errors.fontSize = '字号需为 1–409 之间的数字。';
14460
+ if (!Number.isInteger(draft.rotation) || draft.rotation < -90 || draft.rotation > 90) errors.rotation = '文字旋转角度需为 -90–90 之间的整数。';
14461
+ if (!normalizeSpreadsheetCellFillFormat(spreadsheetFormatCellsActiveFill(draft))) errors.fill = '请检查填充设置。渐变色标需按位置从小到大排列,位置和路径边界需保持在 0%–100%。';
14462
+ return errors;
14463
+ }
14464
+ function spreadsheetFormatCellsActiveFill(draft) {
14465
+ if ('none' === draft.fill.mode) return {
14466
+ kind: 'none'
14467
+ };
14468
+ if ('solid' === draft.fill.mode) return {
14469
+ color: draft.fill.solidColor,
14470
+ kind: 'solid'
14471
+ };
14472
+ if ('pattern' === draft.fill.mode) return {
14473
+ kind: 'pattern',
14474
+ value: draft.fill.pattern
14475
+ };
14476
+ return {
14477
+ kind: 'gradient',
14478
+ value: draft.fill.gradient
14479
+ };
14480
+ }
14481
+ function shouldEmit(source, value, touched) {
14482
+ return Boolean(touched && (source.mixed || !sameDialogValue(source.value, value)));
14483
+ }
14484
+ function createSpreadsheetFormatCellsFillDraft(source) {
14485
+ const fill = normalizeSpreadsheetCellFillFormat(source) ?? {
14486
+ kind: 'none'
14487
+ };
14488
+ const solidColor = spreadsheetFillFallbackColor(fill);
14489
+ return {
14490
+ gradient: 'gradient' === fill.kind ? fill.value : {
14491
+ degree: 0,
14492
+ stops: [
14493
+ {
14494
+ color: solidColor,
14495
+ position: 0
14496
+ },
14497
+ {
14498
+ color: '#ffffff' === solidColor ? '#4472c4' : '#ffffff',
14499
+ position: 1
14500
+ }
14501
+ ],
14502
+ type: 'linear'
14503
+ },
14504
+ mode: fill.kind,
14505
+ pattern: 'pattern' === fill.kind ? fill.value : {
14506
+ backgroundColor: solidColor,
14507
+ foregroundColor: '#ffffff' === solidColor ? '#4472c4' : '#ffffff',
14508
+ patternType: 'lightGrid'
14509
+ },
14510
+ solidColor
14511
+ };
14512
+ }
14513
+ function spreadsheetFillFallbackColor(fill) {
14514
+ if ('solid' === fill.kind) return fill.color;
14515
+ if ('pattern' === fill.kind) return fill.value.backgroundColor;
14516
+ if ('gradient' === fill.kind) return fill.value.stops[0]?.color ?? '#ffffff';
14517
+ return '#ffffff';
14518
+ }
14519
+ function spreadsheet_format_cells_dialog_model_horizontalAlignment(value) {
14520
+ if ('0' === String(value)) return 'center';
14521
+ if ('1' === String(value)) return 'left';
14522
+ if ('2' === String(value)) return 'right';
14523
+ return 'general';
14524
+ }
14525
+ function verticalAlignment(value) {
14526
+ if (0 === Number(value)) return 'middle';
14527
+ if (2 === Number(value)) return 'bottom';
14528
+ return 'top';
14529
+ }
14530
+ function borderFormatsAt(sheet, row, column) {
14531
+ const resolved = spreadsheetCellBordersAt(sheet, row, column);
14532
+ return [
14533
+ 'top',
14534
+ 'bottom',
14535
+ 'left',
14536
+ 'right',
14537
+ 'diagonalDown',
14538
+ 'diagonalUp'
14539
+ ].flatMap((target)=>{
14540
+ const line = resolved[target];
14541
+ if (!line) return [];
14542
+ return [
14543
+ {
14544
+ target,
14545
+ color: normalizedColor(line.color, '#172033') ?? '#172033',
14546
+ style: borderStyle(line.style)
14547
+ }
14548
+ ];
14549
+ });
14550
+ }
14551
+ function borderStyle(value) {
14552
+ return ({
14553
+ 1: 'thin',
14554
+ 3: 'dotted',
14555
+ 4: 'dashed',
14556
+ 5: 'dash-dot',
14557
+ 6: 'dash-dot-dot',
14558
+ 8: 'medium',
14559
+ 9: 'medium-dashed',
14560
+ 10: 'medium-dash-dot',
14561
+ 11: 'medium-dash-dot-dot',
14562
+ 13: 'thick'
14563
+ })[value] ?? 'thin';
14564
+ }
14565
+ function normalizedColor(value, fallback) {
14566
+ if ('string' != typeof value) return fallback;
14567
+ const color = value.trim().toLowerCase();
14568
+ if (/^#[0-9a-f]{6}$/.test(color)) return color;
14569
+ if (/^#[0-9a-f]{3}$/.test(color)) return `#${[
14570
+ ...color.slice(1)
14571
+ ].map((character)=>character.repeat(2)).join('')}`;
14572
+ return fallback;
14573
+ }
14574
+ function sameDialogValue(left, right) {
14575
+ if (Object.is(left, right)) return true;
14576
+ return JSON.stringify(left) === JSON.stringify(right);
14577
+ }
14578
+ function clampIndex(value, minimum, maximum) {
14579
+ return Math.min(maximum, Math.max(minimum, Math.trunc(value)));
14580
+ }
14581
+ function SpreadsheetFormatCellsFillPreview({ fill, patternLabels }) {
14582
+ const canvasRef = useRef(null);
14583
+ useEffect(()=>{
14584
+ const canvas = canvasRef.current;
14585
+ if (!canvas) return;
14586
+ const render = ()=>renderSpreadsheetFillPreview(canvas, fill);
14587
+ render();
14588
+ if ("u" < typeof ResizeObserver) return;
14589
+ const observer = new ResizeObserver(render);
14590
+ observer.observe(canvas);
14591
+ return ()=>observer.disconnect();
14592
+ }, [
14593
+ fill
14594
+ ]);
14595
+ return /*#__PURE__*/ jsxs("figure", {
14596
+ className: `work-spreadsheet-format-cells-fill-preview ${fill.kind}`,
14597
+ children: [
14598
+ /*#__PURE__*/ jsx("canvas", {
14599
+ ref: canvasRef,
14600
+ role: "img",
14601
+ "aria-label": spreadsheetFillPreviewLabel(fill, patternLabels)
14602
+ }),
14603
+ /*#__PURE__*/ jsx("figcaption", {
14604
+ children: spreadsheetFillPreviewCaption(fill, patternLabels)
14605
+ })
14606
+ ]
14607
+ });
14608
+ }
14609
+ function renderSpreadsheetFillPreview(canvas, fill) {
14610
+ let context = null;
14611
+ try {
14612
+ context = canvas.getContext('2d');
14613
+ } catch {
14614
+ return;
14615
+ }
14616
+ if (!context) return;
14617
+ const bounds = canvas.getBoundingClientRect();
14618
+ const width = Math.max(1, Math.round(bounds.width || 220));
14619
+ const height = Math.max(1, Math.round(bounds.height || 132));
14620
+ const scale = Math.min(2, Math.max(1, window.devicePixelRatio || 1));
14621
+ const pixelWidth = Math.round(width * scale);
14622
+ const pixelHeight = Math.round(height * scale);
14623
+ if (canvas.width !== pixelWidth) canvas.width = pixelWidth;
14624
+ if (canvas.height !== pixelHeight) canvas.height = pixelHeight;
14625
+ context.setTransform(scale, 0, 0, scale, 0, 0);
14626
+ context.clearRect(0, 0, width, height);
14627
+ if ('none' === fill.kind) return;
14628
+ if ('solid' === fill.kind) {
14629
+ context.fillStyle = fill.color;
14630
+ context.fillRect(0, 0, width, height);
14631
+ return;
14632
+ }
14633
+ if ('pattern' === fill.kind) {
14634
+ context.fillStyle = fill.value.backgroundColor;
14635
+ context.fillRect(0, 0, width, height);
14636
+ drawSpreadsheetPatternFillOverlay(context, {
14637
+ endX: width,
14638
+ endY: height,
14639
+ startX: 0,
14640
+ startY: 0
14641
+ }, fill.value);
14642
+ return;
14643
+ }
14644
+ drawSpreadsheetGradientFill(context, {
14645
+ endX: width,
14646
+ endY: height,
14647
+ startX: 0,
14648
+ startY: 0
14649
+ }, fill.value);
14650
+ }
14651
+ function spreadsheetFillPreviewLabel(fill, patternLabels) {
14652
+ if ('none' === fill.kind) return '无填充预览';
14653
+ if ('solid' === fill.kind) return `纯色填充预览 ${fill.color}`;
14654
+ if ('pattern' === fill.kind) return `图案填充预览 ${patternLabels[fill.value.patternType]}`;
14655
+ return `${'linear' === fill.value.type ? '线性' : '路径'}渐变填充预览,共 ${fill.value.stops.length} 个色标`;
14656
+ }
14657
+ function spreadsheetFillPreviewCaption(fill, patternLabels) {
14658
+ if ('none' === fill.kind) return '无填充';
14659
+ if ('solid' === fill.kind) return fill.color.toUpperCase();
14660
+ if ('pattern' === fill.kind) return patternLabels[fill.value.patternType];
14661
+ return 'linear' === fill.value.type ? `线性 · ${formatNumber(fill.value.degree)}° · ${fill.value.stops.length} 个色标` : `路径 · ${fill.value.stops.length} 个色标`;
14662
+ }
14663
+ function formatNumber(value) {
14664
+ return Number.isInteger(value) ? String(value) : String(Number(value.toFixed(4)));
14665
+ }
14666
+ const fillModeItems = [
14667
+ {
14668
+ id: 'none',
14669
+ label: '无填充'
14670
+ },
14671
+ {
14672
+ id: 'solid',
14673
+ label: '纯色'
14674
+ },
14675
+ {
14676
+ id: 'pattern',
14677
+ label: '图案'
14678
+ },
14679
+ {
14680
+ id: 'gradient',
14681
+ label: '渐变'
14682
+ }
14683
+ ];
14684
+ const gradientTypeOptions = [
14685
+ {
14686
+ value: 'linear',
14687
+ label: '线性'
14688
+ },
14689
+ {
14690
+ value: 'path',
14691
+ label: '路径'
14692
+ }
14693
+ ];
14694
+ const spreadsheet_format_cells_fill_panel_patternLabels = {
14695
+ darkDown: '深色下斜线',
14696
+ darkGray: '深灰',
14697
+ darkGrid: '深色网格',
14698
+ darkHorizontal: '深色横线',
14699
+ darkTrellis: '深色菱形网格',
14700
+ darkUp: '深色上斜线',
14701
+ darkVertical: '深色竖线',
14702
+ gray0625: '6.25% 灰度',
14703
+ gray125: '12.5% 灰度',
14704
+ lightDown: '浅色下斜线',
14705
+ lightGray: '浅灰',
14706
+ lightGrid: '浅色网格',
14707
+ lightHorizontal: '浅色横线',
14708
+ lightTrellis: '浅色菱形网格',
14709
+ lightUp: '浅色上斜线',
14710
+ lightVertical: '浅色竖线',
14711
+ mediumGray: '中灰'
14712
+ };
14713
+ const patternOptions = xlsxPatternFillTypes.map((value)=>({
14714
+ label: spreadsheet_format_cells_fill_panel_patternLabels[value],
14715
+ value
14716
+ }));
14717
+ function SpreadsheetFormatCellsFillPanel({ source, draft, errors, touched, setDraft, touch }) {
14718
+ const updateFill = (update)=>{
14719
+ touch('fill');
14720
+ setDraft((current)=>({
14721
+ ...current,
14722
+ fill: update(current.fill)
14723
+ }));
14724
+ };
14725
+ const activeFill = spreadsheetFormatCellsActiveFill(draft);
14726
+ return /*#__PURE__*/ jsxs("div", {
14727
+ className: "work-spreadsheet-format-cells-fill",
14728
+ children: [
14729
+ /*#__PURE__*/ jsx(SegmentedControl, {
14730
+ ariaLabel: "填充类型",
14731
+ className: "work-spreadsheet-format-cells-fill-modes",
14732
+ value: draft.fill.mode,
14733
+ items: fillModeItems,
14734
+ layout: "equal",
14735
+ size: "compact",
14736
+ onChange: (mode)=>updateFill((current)=>({
14737
+ ...current,
14738
+ mode
14739
+ }))
14740
+ }),
14741
+ /*#__PURE__*/ jsxs("div", {
14742
+ className: "work-spreadsheet-format-cells-fill-layout",
14743
+ children: [
14744
+ /*#__PURE__*/ jsxs("div", {
14745
+ className: "work-spreadsheet-format-cells-fill-controls",
14746
+ children: [
14747
+ 'none' === draft.fill.mode && /*#__PURE__*/ jsx("p", {
14748
+ className: "work-spreadsheet-format-cells-fill-empty-copy",
14749
+ children: "应用后会移除选区中的纯色、图案和渐变填充。"
14750
+ }),
14751
+ 'solid' === draft.fill.mode && /*#__PURE__*/ jsx(FillField, {
14752
+ label: "背景色",
14753
+ children: /*#__PURE__*/ jsx(OfficeColorPicker, {
14754
+ ariaLabel: "单元格填充颜色",
14755
+ value: draft.fill.solidColor,
14756
+ onValueChange: (solidColor)=>updateFill((current)=>({
14757
+ ...current,
14758
+ solidColor
14759
+ }))
14760
+ })
14761
+ }),
14762
+ 'pattern' === draft.fill.mode && /*#__PURE__*/ jsx(PatternFillControls, {
14763
+ fill: draft.fill.pattern,
14764
+ onChange: (pattern)=>updateFill((current)=>({
14765
+ ...current,
14766
+ pattern
14767
+ }))
14768
+ }),
14769
+ 'gradient' === draft.fill.mode && /*#__PURE__*/ jsx(GradientFillControls, {
14770
+ fill: draft.fill.gradient,
14771
+ onChange: (gradient)=>updateFill((current)=>({
14772
+ ...current,
14773
+ gradient
14774
+ }))
14775
+ }),
14776
+ errors.fill && /*#__PURE__*/ jsx("p", {
14777
+ role: "alert",
14778
+ children: errors.fill
14779
+ }),
14780
+ source.fields.fill.mixed && !touched.fill && /*#__PURE__*/ jsx("p", {
14781
+ className: "work-spreadsheet-format-cells-mixed",
14782
+ children: "选区包含多种填充;只有选择新的填充类型或参数后才会统一应用。"
14783
+ })
14784
+ ]
14785
+ }),
14786
+ /*#__PURE__*/ jsx(SpreadsheetFormatCellsFillPreview, {
14787
+ fill: activeFill,
14788
+ patternLabels: spreadsheet_format_cells_fill_panel_patternLabels
14789
+ })
14790
+ ]
14791
+ })
14792
+ ]
14793
+ });
14794
+ }
14795
+ function PatternFillControls({ fill, onChange }) {
14796
+ const updateColor = (field, color)=>{
14797
+ const next = {
14798
+ ...fill,
14799
+ [field]: color
14800
+ };
14801
+ if ('backgroundColor' === field) delete next.backgroundColorOrigin;
14802
+ else delete next.foregroundColorOrigin;
14803
+ onChange(next);
14804
+ };
14805
+ return /*#__PURE__*/ jsxs("div", {
14806
+ className: "work-spreadsheet-format-cells-pattern-controls",
14807
+ children: [
14808
+ /*#__PURE__*/ jsx(FillField, {
14809
+ label: "图案样式",
14810
+ children: /*#__PURE__*/ jsx(OfficeSelect, {
14811
+ ariaLabel: "填充图案样式",
14812
+ value: fill.patternType,
14813
+ options: patternOptions,
14814
+ onValueChange: (patternType)=>onChange({
14815
+ ...fill,
14816
+ patternType
14817
+ })
14818
+ })
14819
+ }),
14820
+ /*#__PURE__*/ jsx(FillField, {
14821
+ label: "图案颜色",
14822
+ children: /*#__PURE__*/ jsx(OfficeColorPicker, {
14823
+ ariaLabel: "填充图案颜色",
14824
+ value: fill.foregroundColor,
14825
+ onValueChange: (color)=>updateColor('foregroundColor', color)
14826
+ })
14827
+ }),
14828
+ /*#__PURE__*/ jsx(FillField, {
14829
+ label: "背景色",
14830
+ children: /*#__PURE__*/ jsx(OfficeColorPicker, {
14831
+ ariaLabel: "填充图案背景色",
14832
+ value: fill.backgroundColor,
14833
+ onValueChange: (color)=>updateColor('backgroundColor', color)
14834
+ })
14835
+ })
14836
+ ]
14837
+ });
14838
+ }
14839
+ function GradientFillControls({ fill, onChange }) {
14840
+ const changeType = (type)=>{
14841
+ if (type === fill.type) return;
14842
+ const stops = fill.stops.map((stop)=>({
14843
+ ...stop
14844
+ }));
14845
+ onChange('linear' === type ? {
14846
+ degree: 0,
14847
+ stops,
14848
+ type
14849
+ } : {
14850
+ bottom: 0.75,
14851
+ left: 0.25,
14852
+ right: 0.75,
14853
+ stops,
14854
+ top: 0.25,
14855
+ type
14856
+ });
14857
+ };
14858
+ const changeStops = (stops)=>onChange({
14859
+ ...fill,
14860
+ stops
14861
+ });
14862
+ const updateStop = (index, update)=>changeStops(fill.stops.map((stop, stopIndex)=>stopIndex === index ? update(stop) : stop));
14863
+ return /*#__PURE__*/ jsxs("div", {
14864
+ className: "work-spreadsheet-format-cells-gradient-controls",
14865
+ "data-gradient-type": fill.type,
14866
+ children: [
14867
+ /*#__PURE__*/ jsxs("div", {
14868
+ className: "work-spreadsheet-format-cells-gradient-geometry",
14869
+ children: [
14870
+ /*#__PURE__*/ jsx(FillField, {
14871
+ label: "渐变类型",
14872
+ children: /*#__PURE__*/ jsx(OfficeSelect, {
14873
+ ariaLabel: "渐变类型",
14874
+ value: fill.type,
14875
+ options: gradientTypeOptions,
14876
+ onValueChange: changeType
14877
+ })
14878
+ }),
14879
+ 'linear' === fill.type ? /*#__PURE__*/ jsx(PercentField, {
14880
+ label: "角度(\xb0)",
14881
+ ariaLabel: "线性渐变角度",
14882
+ value: fill.degree,
14883
+ step: 1,
14884
+ onChange: (degree)=>onChange({
14885
+ ...fill,
14886
+ degree
14887
+ })
14888
+ }) : /*#__PURE__*/ jsx(PathGeometryFields, {
14889
+ fill: fill,
14890
+ onChange: onChange
14891
+ })
14892
+ ]
14893
+ }),
14894
+ /*#__PURE__*/ jsxs("div", {
14895
+ className: "work-spreadsheet-format-cells-gradient-stops-heading",
14896
+ children: [
14897
+ /*#__PURE__*/ jsxs("div", {
14898
+ children: [
14899
+ /*#__PURE__*/ jsx("strong", {
14900
+ children: "渐变色标"
14901
+ }),
14902
+ /*#__PURE__*/ jsxs("span", {
14903
+ children: [
14904
+ fill.stops.length,
14905
+ " / ",
14906
+ 256
14907
+ ]
14908
+ })
14909
+ ]
14910
+ }),
14911
+ /*#__PURE__*/ jsxs(button_Button, {
14912
+ size: "compact",
14913
+ tone: "quiet",
14914
+ disabled: fill.stops.length >= 256,
14915
+ onClick: ()=>changeStops(addGradientStop(fill.stops)),
14916
+ children: [
14917
+ /*#__PURE__*/ jsx(Plus, {
14918
+ size: 13,
14919
+ "aria-hidden": "true"
14920
+ }),
14921
+ "添加色标"
14922
+ ]
14923
+ })
14924
+ ]
14925
+ }),
14926
+ /*#__PURE__*/ jsx("ol", {
14927
+ className: "work-spreadsheet-format-cells-gradient-stops",
14928
+ "aria-label": "渐变色标列表",
14929
+ "data-stop-count": fill.stops.length,
14930
+ children: fill.stops.map((stop, index)=>/*#__PURE__*/ jsxs("li", {
14931
+ className: "work-spreadsheet-format-cells-gradient-stop",
14932
+ children: [
14933
+ /*#__PURE__*/ jsx("span", {
14934
+ className: "work-spreadsheet-format-cells-gradient-stop-index",
14935
+ children: index + 1
14936
+ }),
14937
+ /*#__PURE__*/ jsx(OfficeColorPicker, {
14938
+ ariaLabel: `色标 ${index + 1} 颜色`,
14939
+ value: stop.color,
14940
+ onValueChange: (color)=>updateStop(index, (current)=>{
14941
+ const next = {
14942
+ ...current,
14943
+ color
14944
+ };
14945
+ delete next.colorOrigin;
14946
+ return next;
14947
+ })
14948
+ }),
14949
+ /*#__PURE__*/ jsxs("div", {
14950
+ className: "work-spreadsheet-format-cells-stop-position",
14951
+ children: [
14952
+ /*#__PURE__*/ jsxs("span", {
14953
+ className: "sr-only",
14954
+ children: [
14955
+ "色标 ",
14956
+ index + 1,
14957
+ " 位置"
14958
+ ]
14959
+ }),
14960
+ /*#__PURE__*/ jsx(OfficeNumberField, {
14961
+ ariaLabel: `色标 ${index + 1} 位置`,
14962
+ value: formatPercentage(stop.position),
14963
+ min: 0,
14964
+ max: 100,
14965
+ step: 1,
14966
+ validationInvalid: stop.position < 0 || stop.position > 1 || index > 0 && (fill.stops[index - 1]?.position ?? 0) > stop.position,
14967
+ onValueChange: (value)=>{
14968
+ const percentage = Number(value);
14969
+ if (!Number.isFinite(percentage)) return;
14970
+ updateStop(index, (current)=>({
14971
+ ...current,
14972
+ position: percentage / 100
14973
+ }));
14974
+ }
14975
+ }),
14976
+ /*#__PURE__*/ jsx("span", {
14977
+ "aria-hidden": "true",
14978
+ children: "%"
14979
+ })
14980
+ ]
14981
+ }),
14982
+ /*#__PURE__*/ jsx(icon_button_IconButton, {
14983
+ className: "work-spreadsheet-format-cells-gradient-stop-remove",
14984
+ label: `删除色标 ${index + 1}`,
14985
+ disabled: fill.stops.length <= 2,
14986
+ onClick: ()=>changeStops(fill.stops.filter((_, stopIndex)=>stopIndex !== index)),
14987
+ children: /*#__PURE__*/ jsx(Trash2, {
14988
+ size: 13
14989
+ })
14990
+ })
14991
+ ]
14992
+ }, index))
14993
+ }),
14994
+ /*#__PURE__*/ jsx("small", {
14995
+ className: "work-spreadsheet-format-cells-gradient-help",
14996
+ children: "色标按列表顺序写入 XLSX;位置需从小到大排列。编辑颜色后会改用显式 RGB,未修改的主题色语义会继续保留。"
14997
+ })
14998
+ ]
14999
+ });
15000
+ }
15001
+ function PathGeometryFields({ fill, onChange }) {
15002
+ const fields = [
15003
+ [
15004
+ 'left',
15005
+ '左边界'
15006
+ ],
15007
+ [
15008
+ 'right',
15009
+ '右边界'
15010
+ ],
15011
+ [
15012
+ 'top',
15013
+ '上边界'
15014
+ ],
15015
+ [
15016
+ 'bottom',
15017
+ '下边界'
15018
+ ]
15019
+ ];
15020
+ return /*#__PURE__*/ jsx("div", {
15021
+ className: "work-spreadsheet-format-cells-path-geometry",
15022
+ children: fields.map(([field, label])=>/*#__PURE__*/ jsx(PercentField, {
15023
+ label: `${label}(%)`,
15024
+ ariaLabel: `路径渐变${label}`,
15025
+ value: 100 * fill[field],
15026
+ min: 0,
15027
+ max: 100,
15028
+ step: 1,
15029
+ invalid: 'left' === field && fill.left > fill.right || 'right' === field && fill.right < fill.left || 'top' === field && fill.top > fill.bottom || 'bottom' === field && fill.bottom < fill.top,
15030
+ onChange: (value)=>onChange({
15031
+ ...fill,
15032
+ [field]: value / 100
15033
+ })
15034
+ }, field))
15035
+ });
15036
+ }
15037
+ function PercentField({ label, ariaLabel, value, min, max, step, invalid = false, onChange }) {
15038
+ return /*#__PURE__*/ jsx(FillField, {
15039
+ label: label,
15040
+ children: /*#__PURE__*/ jsx(OfficeNumberField, {
15041
+ ariaLabel: ariaLabel,
15042
+ value: spreadsheet_format_cells_fill_panel_formatNumber(value),
15043
+ min: min,
15044
+ max: max,
15045
+ step: step,
15046
+ validationInvalid: invalid,
15047
+ onValueChange: (rawValue)=>{
15048
+ const next = Number(rawValue);
15049
+ if (Number.isFinite(next)) onChange(next);
15050
+ }
15051
+ })
15052
+ });
15053
+ }
15054
+ function FillField({ label, children }) {
15055
+ return /*#__PURE__*/ jsxs("div", {
15056
+ className: "work-spreadsheet-format-cells-field",
15057
+ children: [
15058
+ /*#__PURE__*/ jsx("span", {
15059
+ children: label
15060
+ }),
15061
+ children
15062
+ ]
15063
+ });
15064
+ }
15065
+ function addGradientStop(source) {
15066
+ if (source.length >= 256) return [
15067
+ ...source
15068
+ ];
15069
+ let insertAfter = 0;
15070
+ let largestGap = -1 / 0;
15071
+ for(let index = 0; index < source.length - 1; index += 1){
15072
+ const left = source[index];
15073
+ const right = source[index + 1];
15074
+ if (!left || !right) continue;
15075
+ const gap = right.position - left.position;
15076
+ if (gap > largestGap) {
15077
+ insertAfter = index;
15078
+ largestGap = gap;
15079
+ }
15080
+ }
15081
+ const left = source[insertAfter] ?? {
15082
+ color: '#4472c4',
15083
+ position: 0
15084
+ };
15085
+ const right = source[insertAfter + 1] ?? {
15086
+ color: '#ffffff',
15087
+ position: 1
15088
+ };
15089
+ const stop = {
15090
+ color: interpolateHexColor(left.color, right.color),
15091
+ position: (left.position + right.position) / 2
15092
+ };
15093
+ return [
15094
+ ...source.slice(0, insertAfter + 1).map((item)=>({
15095
+ ...item
15096
+ })),
15097
+ stop,
15098
+ ...source.slice(insertAfter + 1).map((item)=>({
15099
+ ...item
15100
+ }))
15101
+ ];
15102
+ }
15103
+ function interpolateHexColor(left, right) {
15104
+ const channels = [
15105
+ 1,
15106
+ 3,
15107
+ 5
15108
+ ].map((offset)=>Math.round((Number.parseInt(left.slice(offset, offset + 2), 16) + Number.parseInt(right.slice(offset, offset + 2), 16)) / 2));
15109
+ return `#${channels.map((channel)=>channel.toString(16).padStart(2, '0')).join('')}`;
15110
+ }
15111
+ function formatPercentage(value) {
15112
+ return spreadsheet_format_cells_fill_panel_formatNumber(100 * value);
15113
+ }
15114
+ function spreadsheet_format_cells_fill_panel_formatNumber(value) {
15115
+ return Number.isInteger(value) ? String(value) : String(Number(value.toFixed(4)));
15116
+ }
15117
+ const MIXED_VALUE = '__mixed__';
15118
+ const numberFormatOptions = [
15119
+ 'general',
15120
+ 'number',
15121
+ 'currency',
15122
+ 'accounting',
15123
+ 'percent',
15124
+ 'date',
15125
+ 'time',
15126
+ 'scientific',
15127
+ 'fraction',
15128
+ 'text',
15129
+ 'custom'
15130
+ ].map((value)=>({
15131
+ value: value,
15132
+ label: spreadsheetNumberFormatPresetLabels[value]
15133
+ }));
15134
+ const horizontalOptions = [
15135
+ {
15136
+ value: 'general',
15137
+ label: '常规'
15138
+ },
15139
+ {
15140
+ value: 'left',
15141
+ label: '左对齐'
15142
+ },
15143
+ {
15144
+ value: 'center',
15145
+ label: '居中'
15146
+ },
15147
+ {
15148
+ value: 'right',
15149
+ label: '右对齐'
15150
+ }
15151
+ ];
15152
+ const verticalOptions = [
15153
+ {
15154
+ value: 'top',
15155
+ label: '顶端对齐'
15156
+ },
15157
+ {
15158
+ value: 'middle',
15159
+ label: '垂直居中'
15160
+ },
15161
+ {
15162
+ value: 'bottom',
15163
+ label: '底端对齐'
15164
+ }
15165
+ ];
15166
+ const spreadsheet_format_cells_dialog_panels_underlineOptions = [
15167
+ {
15168
+ value: 'none',
15169
+ label: '无'
15170
+ },
15171
+ {
15172
+ value: 'single',
15173
+ label: '单下划线'
15174
+ },
15175
+ {
15176
+ value: 'double',
15177
+ label: '双下划线'
15178
+ },
15179
+ {
15180
+ value: 'singleAccounting',
15181
+ label: '单会计用下划线'
15182
+ },
15183
+ {
15184
+ value: 'doubleAccounting',
15185
+ label: '双会计用下划线'
15186
+ }
15187
+ ];
15188
+ const borderStyleOptions = [
15189
+ {
15190
+ value: 'thin',
15191
+ label: '细实线'
15192
+ },
15193
+ {
15194
+ value: 'dotted',
15195
+ label: '点线'
15196
+ },
15197
+ {
15198
+ value: 'dashed',
15199
+ label: '虚线'
15200
+ },
15201
+ {
15202
+ value: 'dash-dot',
15203
+ label: '点划线'
15204
+ },
15205
+ {
15206
+ value: 'medium',
15207
+ label: '中等实线'
15208
+ },
15209
+ {
15210
+ value: 'medium-dashed',
15211
+ label: '中等虚线'
15212
+ },
15213
+ {
15214
+ value: 'thick',
15215
+ label: '粗实线'
15216
+ }
15217
+ ];
15218
+ const borderTargets = [
15219
+ {
15220
+ target: 'top',
15221
+ label: '上框线'
15222
+ },
15223
+ {
15224
+ target: 'bottom',
15225
+ label: '下框线'
15226
+ },
15227
+ {
15228
+ target: 'left',
15229
+ label: '左框线'
15230
+ },
15231
+ {
15232
+ target: 'right',
15233
+ label: '右框线'
15234
+ },
15235
+ {
15236
+ target: 'diagonalDown',
15237
+ label: '斜下框线'
15238
+ },
15239
+ {
15240
+ target: 'diagonalUp',
15241
+ label: '斜上框线'
15242
+ }
15243
+ ];
15244
+ function SpreadsheetFormatCellsPanel(props) {
15245
+ return /*#__PURE__*/ jsxs("section", {
15246
+ id: `${props.idBase}-${props.activeTab}-panel`,
15247
+ className: "work-spreadsheet-format-cells-panel",
15248
+ role: "tabpanel",
15249
+ "aria-labelledby": `${props.idBase}-${props.activeTab}-tab`,
15250
+ tabIndex: -1,
15251
+ children: [
15252
+ 'number' === props.activeTab && /*#__PURE__*/ jsx(NumberPanel, {
15253
+ ...props
15254
+ }),
15255
+ 'alignment' === props.activeTab && /*#__PURE__*/ jsx(AlignmentPanel, {
15256
+ ...props
14106
15257
  }),
14107
15258
  'font' === props.activeTab && /*#__PURE__*/ jsx(FontPanel, {
14108
15259
  ...props
@@ -14110,7 +15261,7 @@ function SpreadsheetFormatCellsPanel(props) {
14110
15261
  'border' === props.activeTab && /*#__PURE__*/ jsx(BorderPanel, {
14111
15262
  ...props
14112
15263
  }),
14113
- 'fill' === props.activeTab && /*#__PURE__*/ jsx(FillPanel, {
15264
+ 'fill' === props.activeTab && /*#__PURE__*/ jsx(SpreadsheetFormatCellsFillPanel, {
14114
15265
  ...props
14115
15266
  }),
14116
15267
  'protection' === props.activeTab && /*#__PURE__*/ jsx(ProtectionPanel, {
@@ -14558,47 +15709,6 @@ function BorderPreview({ draft }) {
14558
15709
  ]
14559
15710
  });
14560
15711
  }
14561
- function FillPanel({ source, draft, touched, setDraft, touch }) {
14562
- return /*#__PURE__*/ jsxs("div", {
14563
- className: "work-spreadsheet-format-cells-fill",
14564
- children: [
14565
- /*#__PURE__*/ jsx(Field, {
14566
- label: "背景色",
14567
- children: /*#__PURE__*/ jsx(OfficeColorPicker, {
14568
- ariaLabel: "单元格填充颜色",
14569
- value: draft.fillColor ?? '#ffffff',
14570
- onValueChange: (fillColor)=>{
14571
- touch('fillColor');
14572
- setDraft((current)=>({
14573
- ...current,
14574
- fillColor
14575
- }));
14576
- }
14577
- })
14578
- }),
14579
- /*#__PURE__*/ jsx(button_Button, {
14580
- size: "compact",
14581
- tone: "quiet",
14582
- onClick: ()=>{
14583
- touch('fillColor');
14584
- setDraft((current)=>({
14585
- ...current,
14586
- fillColor: null
14587
- }));
14588
- },
14589
- children: "无填充"
14590
- }),
14591
- /*#__PURE__*/ jsx("div", {
14592
- className: `work-spreadsheet-format-cells-fill-preview${draft.fillColor ? '' : ' empty'}`,
14593
- style: {
14594
- backgroundColor: draft.fillColor ?? void 0
14595
- },
14596
- children: draft.fillColor ? draft.fillColor.toUpperCase() : '无填充'
14597
- }),
14598
- source.fields.fillColor.mixed && !touched.fillColor && /*#__PURE__*/ jsx(MixedHint, {})
14599
- ]
14600
- });
14601
- }
14602
15712
  function ProtectionPanel({ source, draft, touched, setDraft, touch }) {
14603
15713
  return /*#__PURE__*/ jsxs("div", {
14604
15714
  className: "work-spreadsheet-format-cells-protection",
@@ -14667,177 +15777,6 @@ function borderCss(format) {
14667
15777
  const style = 'dotted' === format.style ? 'dotted' : format.style.includes('dash') ? 'dashed' : 'solid';
14668
15778
  return `${width}px ${style} ${format.color}`;
14669
15779
  }
14670
- function createSpreadsheetFormatCellsDialogSource(content, sheetId, rangeInput, cells, requestedActiveCell) {
14671
- const range = spreadsheet_cell_range_normalizeSpreadsheetCellRange(rangeInput);
14672
- const sheet = content.sheets.find((candidate)=>candidate.id === sheetId);
14673
- if (!range || !sheet || spreadsheet_cell_range_spreadsheetCellRangeArea(range) > 10000) return null;
14674
- const activeRow = clampIndex(requestedActiveCell.row, range.row[0], range.row[1]);
14675
- const activeColumn = clampIndex(requestedActiveCell.column, range.column[0], range.column[1]);
14676
- const activeCell = cells[activeRow - range.row[0]]?.[activeColumn - range.column[0]] ?? null;
14677
- const values = (resolve)=>{
14678
- const activeValue = resolve(activeCell, activeRow, activeColumn);
14679
- let mixed = false;
14680
- for(let row = range.row[0]; row <= range.row[1] && !mixed; row += 1)for(let column = range.column[0]; column <= range.column[1]; column += 1){
14681
- const cell = cells[row - range.row[0]]?.[column - range.column[0]] ?? null;
14682
- if (!sameDialogValue(resolve(cell, row, column), activeValue)) {
14683
- mixed = true;
14684
- break;
14685
- }
14686
- }
14687
- return {
14688
- value: activeValue,
14689
- mixed
14690
- };
14691
- };
14692
- const borders = borderFormatsAt(sheet, activeRow, activeColumn);
14693
- return {
14694
- sheetId,
14695
- range,
14696
- activeCell,
14697
- fields: {
14698
- numberFormat: values((cell)=>cell?.ct?.fa?.trim() || 'General'),
14699
- horizontalAlignment: values((cell)=>spreadsheet_format_cells_dialog_model_horizontalAlignment(cell?.ht)),
14700
- verticalAlignment: values((cell)=>verticalAlignment(cell?.vt)),
14701
- wrapText: values((cell)=>'2' === String(cell?.tb)),
14702
- rotation: values((cell)=>spreadsheetVisibleTextRotationFromCell(cell)),
14703
- fontFamily: values((cell)=>'string' == typeof cell?.ff && cell.ff.trim() ? cell.ff.trim() : 'Aptos'),
14704
- fontSize: values((cell)=>'number' == typeof cell?.fs && Number.isFinite(cell.fs) ? cell.fs : 10),
14705
- fontColor: values((cell)=>normalizedColor(cell?.fc, '#172033')),
14706
- bold: values((cell)=>1 === Number(cell?.bl)),
14707
- italic: values((cell)=>1 === Number(cell?.it)),
14708
- underline: values((cell)=>spreadsheetUnderlineStyle(cell?.un)),
14709
- strike: values((cell)=>1 === Number(cell?.cl)),
14710
- fillColor: values((cell)=>'string' == typeof cell?.bg && cell.bg.trim() ? normalizedColor(cell.bg, null) : null),
14711
- borders: {
14712
- value: borders,
14713
- mixed: spreadsheet_cell_range_spreadsheetCellRangeArea(range) > 1
14714
- },
14715
- locked: values((cell, row, column)=>spreadsheetCellProtectionAt(sheet, row, column, cell).locked),
14716
- hidden: values((cell, row, column)=>spreadsheetCellProtectionAt(sheet, row, column, cell).hidden)
14717
- }
14718
- };
14719
- }
14720
- function createSpreadsheetFormatCellsDraft(source) {
14721
- const borders = source.fields.borders.value.map((format)=>({
14722
- ...format
14723
- }));
14724
- return {
14725
- numberFormat: source.fields.numberFormat.value,
14726
- horizontalAlignment: source.fields.horizontalAlignment.value,
14727
- verticalAlignment: source.fields.verticalAlignment.value,
14728
- wrapText: source.fields.wrapText.value,
14729
- rotation: source.fields.rotation.value,
14730
- fontFamily: source.fields.fontFamily.value,
14731
- fontSize: source.fields.fontSize.value,
14732
- fontColor: source.fields.fontColor.value,
14733
- bold: source.fields.bold.value,
14734
- italic: source.fields.italic.value,
14735
- underline: source.fields.underline.value,
14736
- strike: source.fields.strike.value,
14737
- fillColor: source.fields.fillColor.value,
14738
- borders,
14739
- borderColor: borders[0]?.color ?? '#172033',
14740
- borderStyle: borders[0]?.style ?? 'thin',
14741
- locked: source.fields.locked.value,
14742
- hidden: source.fields.hidden.value
14743
- };
14744
- }
14745
- function spreadsheetFormatCellsPatch(source, draft, touched) {
14746
- const patch = {};
14747
- if (shouldEmit(source.fields.numberFormat, draft.numberFormat, touched.numberFormat)) patch.numberFormat = draft.numberFormat.trim();
14748
- if (shouldEmit(source.fields.horizontalAlignment, draft.horizontalAlignment, touched.horizontalAlignment)) patch.horizontalAlignment = draft.horizontalAlignment;
14749
- if (shouldEmit(source.fields.verticalAlignment, draft.verticalAlignment, touched.verticalAlignment)) patch.verticalAlignment = draft.verticalAlignment;
14750
- if (shouldEmit(source.fields.wrapText, draft.wrapText, touched.wrapText)) patch.wrapText = draft.wrapText;
14751
- if (shouldEmit(source.fields.rotation, draft.rotation, touched.rotation)) patch.rotation = draft.rotation;
14752
- if (shouldEmit(source.fields.fontFamily, draft.fontFamily, touched.fontFamily)) patch.fontFamily = draft.fontFamily.trim();
14753
- if (shouldEmit(source.fields.fontSize, draft.fontSize, touched.fontSize)) patch.fontSize = draft.fontSize;
14754
- if (shouldEmit(source.fields.fontColor, draft.fontColor, touched.fontColor)) patch.fontColor = draft.fontColor;
14755
- if (shouldEmit(source.fields.bold, draft.bold, touched.bold)) patch.bold = draft.bold;
14756
- if (shouldEmit(source.fields.italic, draft.italic, touched.italic)) patch.italic = draft.italic;
14757
- if (shouldEmit(source.fields.underline, draft.underline, touched.underline)) patch.underline = draft.underline;
14758
- if (shouldEmit(source.fields.strike, draft.strike, touched.strike)) patch.strike = draft.strike;
14759
- if (shouldEmit(source.fields.fillColor, draft.fillColor, touched.fillColor)) patch.fillColor = draft.fillColor;
14760
- if (shouldEmit(source.fields.borders, draft.borders, touched.borders)) patch.borders = draft.borders.map((format)=>({
14761
- ...format
14762
- }));
14763
- if (shouldEmit(source.fields.locked, draft.locked, touched.locked)) patch.locked = draft.locked;
14764
- if (shouldEmit(source.fields.hidden, draft.hidden, touched.hidden)) patch.hidden = draft.hidden;
14765
- return patch;
14766
- }
14767
- function spreadsheetFormatCellsDraftErrors(draft) {
14768
- const errors = {};
14769
- if (draft.numberFormat.trim()) {
14770
- if (draft.numberFormat.trim().length > 255) errors.numberFormat = '数字格式代码不能超过 255 个字符。';
14771
- } else errors.numberFormat = '请输入数字格式代码。';
14772
- if (!Number.isFinite(draft.fontSize) || draft.fontSize < 1 || draft.fontSize > 409) errors.fontSize = '字号需为 1–409 之间的数字。';
14773
- if (!Number.isInteger(draft.rotation) || draft.rotation < -90 || draft.rotation > 90) errors.rotation = '文字旋转角度需为 -90–90 之间的整数。';
14774
- return errors;
14775
- }
14776
- function shouldEmit(source, value, touched) {
14777
- return Boolean(touched && (source.mixed || !sameDialogValue(source.value, value)));
14778
- }
14779
- function spreadsheet_format_cells_dialog_model_horizontalAlignment(value) {
14780
- if ('0' === String(value)) return 'center';
14781
- if ('1' === String(value)) return 'left';
14782
- if ('2' === String(value)) return 'right';
14783
- return 'general';
14784
- }
14785
- function verticalAlignment(value) {
14786
- if (0 === Number(value)) return 'middle';
14787
- if (2 === Number(value)) return 'bottom';
14788
- return 'top';
14789
- }
14790
- function borderFormatsAt(sheet, row, column) {
14791
- const resolved = spreadsheetCellBordersAt(sheet, row, column);
14792
- return [
14793
- 'top',
14794
- 'bottom',
14795
- 'left',
14796
- 'right',
14797
- 'diagonalDown',
14798
- 'diagonalUp'
14799
- ].flatMap((target)=>{
14800
- const line = resolved[target];
14801
- if (!line) return [];
14802
- return [
14803
- {
14804
- target,
14805
- color: normalizedColor(line.color, '#172033') ?? '#172033',
14806
- style: borderStyle(line.style)
14807
- }
14808
- ];
14809
- });
14810
- }
14811
- function borderStyle(value) {
14812
- return ({
14813
- 1: 'thin',
14814
- 3: 'dotted',
14815
- 4: 'dashed',
14816
- 5: 'dash-dot',
14817
- 6: 'dash-dot-dot',
14818
- 8: 'medium',
14819
- 9: 'medium-dashed',
14820
- 10: 'medium-dash-dot',
14821
- 11: 'medium-dash-dot-dot',
14822
- 13: 'thick'
14823
- })[value] ?? 'thin';
14824
- }
14825
- function normalizedColor(value, fallback) {
14826
- if ('string' != typeof value) return fallback;
14827
- const color = value.trim().toLowerCase();
14828
- if (/^#[0-9a-f]{6}$/.test(color)) return color;
14829
- if (/^#[0-9a-f]{3}$/.test(color)) return `#${[
14830
- ...color.slice(1)
14831
- ].map((character)=>character.repeat(2)).join('')}`;
14832
- return fallback;
14833
- }
14834
- function sameDialogValue(left, right) {
14835
- if (Object.is(left, right)) return true;
14836
- return JSON.stringify(left) === JSON.stringify(right);
14837
- }
14838
- function clampIndex(value, minimum, maximum) {
14839
- return Math.min(maximum, Math.max(minimum, Math.trunc(value)));
14840
- }
14841
15780
  function SpreadsheetFormatCellsDialog({ source, restoreFocusTarget, openIntent = defaultSpreadsheetFormatCellsOpenIntent, onApply, onClose }) {
14842
15781
  const [draft, setDraft] = useState(()=>createSpreadsheetFormatCellsDraft(source));
14843
15782
  const [touched, setTouched] = useState({});
@@ -16240,13 +17179,13 @@ function SheetMenuButton({ icon, label, danger = false, disabled = false, onClic
16240
17179
  ]
16241
17180
  });
16242
17181
  }
16243
- const pendingContextRestores = new WeakMap();
17182
+ const spreadsheet_table_render_pendingContextRestores = new WeakMap();
16244
17183
  function beginSpreadsheetTableCellRender(_cell, tableStyle, conditionalStyle, context) {
16245
17184
  if (tableStyle) context.fillStyle = tableStyle.background;
16246
17185
  if (conditionalStyle?.cellColor) context.fillStyle = conditionalStyle.cellColor;
16247
- if (!tableStyle || pendingContextRestores.has(context) || 'function' != typeof context.fillText) return;
17186
+ if (!tableStyle || spreadsheet_table_render_pendingContextRestores.has(context) || 'function' != typeof context.fillText) return;
16248
17187
  const fillText = context.fillText;
16249
- pendingContextRestores.set(context, {
17188
+ spreadsheet_table_render_pendingContextRestores.set(context, {
16250
17189
  fillText,
16251
17190
  fillTextOwned: Object.hasOwn(context, 'fillText')
16252
17191
  });
@@ -16267,11 +17206,11 @@ function beginSpreadsheetTableCellRender(_cell, tableStyle, conditionalStyle, co
16267
17206
  }
16268
17207
  function finishSpreadsheetTableCellRender(_cell, cellInfo, tableStyle, context) {
16269
17208
  if (tableStyle) drawSpreadsheetTableCellBorder(cellInfo, tableStyle, context);
16270
- const restore = pendingContextRestores.get(context);
17209
+ const restore = spreadsheet_table_render_pendingContextRestores.get(context);
16271
17210
  if (!restore) return;
16272
17211
  if (restore.fillTextOwned) context.fillText = restore.fillText;
16273
17212
  else delete context.fillText;
16274
- pendingContextRestores.delete(context);
17213
+ spreadsheet_table_render_pendingContextRestores.delete(context);
16275
17214
  }
16276
17215
  function boldSpreadsheetTableCanvasFont(font) {
16277
17216
  return /(?:^|\s)(?:bold|[6-9]00)(?:\s|$)/i.test(font) ? font : `bold ${font}`;
@@ -21715,7 +22654,8 @@ const spreadsheetCellFormatKeys = [
21715
22654
  'cl',
21716
22655
  'un',
21717
22656
  'tr',
21718
- 'rt'
22657
+ 'rt',
22658
+ ...xlsxNativeFillCellKeys
21719
22659
  ];
21720
22660
  function pasteSpreadsheetSpecialCell({ source, destination, content, operation, rowOffset, columnOffset }) {
21721
22661
  let next;
@@ -21862,8 +22802,9 @@ function clearCellContent(cell) {
21862
22802
  }
21863
22803
  }
21864
22804
  function replaceCellFormatting(target, source) {
21865
- for (const key of spreadsheetCellFormatKeys)if (source?.[key] === void 0) delete target[key];
21866
- else target[key] = cloneValue(source[key]);
22805
+ const sourceCell = source;
22806
+ for (const key of spreadsheetCellFormatKeys)if (sourceCell?.[key] === void 0) delete target[key];
22807
+ else target[key] = cloneValue(sourceCell[key]);
21867
22808
  const inline = Array.isArray(target.ct?.s) ? structuredClone(target.ct.s) : void 0;
21868
22809
  const format = source?.ct ? structuredClone(source.ct) : void 0;
21869
22810
  if (format) delete format.s;
@@ -21913,7 +22854,8 @@ function spreadsheetLiteralCellValue(source) {
21913
22854
  }
21914
22855
  function spreadsheetCellHasFormatting(cell) {
21915
22856
  if (!cell) return false;
21916
- return Boolean(spreadsheetCellFormatKeys.some((key)=>void 0 !== cell[key]) || void 0 !== cell.lo || void 0 !== cell.hi || cell.ct?.fa !== void 0 || cell.ct?.t !== void 0);
22857
+ const formattedCell = cell;
22858
+ return Boolean(spreadsheetCellFormatKeys.some((key)=>void 0 !== formattedCell[key]) || void 0 !== cell.lo || void 0 !== cell.hi || cell.ct?.fa !== void 0 || cell.ct?.t !== void 0);
21917
22859
  }
21918
22860
  function spreadsheetPasteOperationValue(destination, source, operation) {
21919
22861
  if ('divide' === operation && 0 === source) return null;
@@ -23345,7 +24287,8 @@ const spreadsheetCellFormatAttributes = [
23345
24287
  'un',
23346
24288
  'tr',
23347
24289
  'ct',
23348
- 'bg'
24290
+ 'bg',
24291
+ ...xlsxNativeFillCellKeys
23349
24292
  ];
23350
24293
  function captureSpreadsheetFormatPattern(cells) {
23351
24294
  const rowCount = cells.length;
@@ -23410,7 +24353,8 @@ function spreadsheetFormatPainterBatches(pattern, target) {
23410
24353
  }
23411
24354
  function spreadsheetCellFormatSnapshot(cell) {
23412
24355
  const snapshot = {};
23413
- for (const attribute of spreadsheetCellFormatAttributes)snapshot[attribute] = 'ct' === attribute ? spreadsheetNumberFormatSnapshot(cell?.ct) : cloneSpreadsheetFormatValue(cell?.[attribute]);
24356
+ const source = cell;
24357
+ for (const attribute of spreadsheetCellFormatAttributes)snapshot[attribute] = 'ct' === attribute ? spreadsheetNumberFormatSnapshot(cell?.ct) : cloneSpreadsheetFormatValue(source?.[attribute]);
23414
24358
  return snapshot;
23415
24359
  }
23416
24360
  function spreadsheetNumberFormatSnapshot(value) {
@@ -24523,6 +25467,7 @@ function SpreadsheetEditorSurface({ autoFocus = true, content, collaborationHist
24523
25467
  const tableStyle = tableStylesBySheetRef.current.get(activeSheetIdRef.current)?.(cellInfo.row, cellInfo.column) ?? null;
24524
25468
  const style = conditionalStylesBySheetRef.current.get(activeSheetIdRef.current)?.get(`${cellInfo.row}_${cellInfo.column}`);
24525
25469
  beginSpreadsheetTableCellRender(cell, tableStyle, style, context);
25470
+ beginSpreadsheetNativeFillRender(tableStyle || style?.cellColor ? void 0 : activeXlsxNativeFill(cell), context);
24526
25471
  return true;
24527
25472
  },
24528
25473
  afterRenderCell: (cell, cellInfo, context)=>{
@@ -24539,6 +25484,7 @@ function SpreadsheetEditorSurface({ autoFocus = true, content, collaborationHist
24539
25484
  if (cell?.ps) drawSpreadsheetCommentMarker(context, cellInfo);
24540
25485
  }
24541
25486
  } finally{
25487
+ finishSpreadsheetNativeFillRender(context);
24542
25488
  finishSpreadsheetTableCellRender(cell, cellInfo, tableStyle, context);
24543
25489
  const diagonal = diagonalBordersBySheetRef.current.get(activeSheetIdRef.current)?.get(`${cellInfo.row}_${cellInfo.column}`);
24544
25490
  if (diagonal?.down) drawSpreadsheetDiagonalDownBorder(context, cellInfo, diagonal.down);