@a3s-lab/office 0.1.0 → 0.2.2

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 (69) hide show
  1. package/README.md +101 -24
  2. package/dist/0~2582.js +485 -0
  3. package/dist/0~4595.js +14 -7
  4. package/dist/0~4750.js +939 -0
  5. package/dist/{0~work-document-paragraph-formatting.js → 0~5861.js} +174 -3
  6. package/dist/0~7048.js +8 -6
  7. package/dist/0~9512.js +7 -4
  8. package/dist/0~document-editor.js +3147 -531
  9. package/dist/0~markdown-editor.js +26 -1
  10. package/dist/0~presentation-editor.js +68 -12
  11. package/dist/0~spreadsheet-editor.js +37 -17
  12. package/dist/0~work-document-extensions.js +588 -13
  13. package/dist/0~work-document-model-codec.js +1 -1
  14. package/dist/0~work-docx-bibliography.js +1 -1
  15. package/dist/0~work-docx-export.js +116 -55
  16. package/dist/0~work-docx-import.js +766 -107
  17. package/dist/0~work-office-diagnostics.js +2 -2
  18. package/dist/{4704.js → 2881.js} +162 -71
  19. package/dist/4104.js +2 -62
  20. package/dist/internal/features/work/editors/document-comment-window.d.ts +37 -0
  21. package/dist/internal/features/work/editors/document-navigation-panel.d.ts +3 -1
  22. package/dist/internal/features/work/editors/document-navigation-window.d.ts +64 -0
  23. package/dist/internal/features/work/editors/document-outline-navigation.d.ts +11 -0
  24. package/dist/internal/features/work/editors/document-page-navigation.d.ts +11 -1
  25. package/dist/internal/features/work/editors/document-page-thumbnail.d.ts +31 -0
  26. package/dist/internal/features/work/editors/document-picture-properties-dialog-model.d.ts +28 -0
  27. package/dist/internal/features/work/editors/document-picture-properties-dialog.d.ts +4 -0
  28. package/dist/internal/features/work/editors/document-search-navigation.d.ts +12 -0
  29. package/dist/internal/features/work/editors/document-table-margins-popover.d.ts +4 -0
  30. package/dist/internal/features/work/editors/document-table-properties-dialog-model.d.ts +51 -0
  31. package/dist/internal/features/work/editors/document-table-properties-dialog-sections.d.ts +19 -0
  32. package/dist/internal/features/work/editors/document-table-properties-dialog.d.ts +8 -0
  33. package/dist/internal/features/work/editors/office-task-pane.d.ts +1 -1
  34. package/dist/internal/features/work/editors/presentation-chart-panel.d.ts +2 -1
  35. package/dist/internal/features/work/editors/presentation-comments-panel.d.ts +2 -1
  36. package/dist/internal/features/work/editors/spreadsheet-workbook-panel.d.ts +2 -1
  37. package/dist/internal/features/work/editors/use-document-pagination.d.ts +6 -0
  38. package/dist/internal/features/work/editors/use-presentation-review-commands.d.ts +1 -1
  39. package/dist/internal/features/work/work-document-image-layout.d.ts +11 -0
  40. package/dist/internal/features/work/work-document-page-capture.d.ts +15 -0
  41. package/dist/internal/features/work/work-document-paragraph-formatting.d.ts +4 -0
  42. package/dist/internal/features/work/work-document-section.d.ts +3 -1
  43. package/dist/internal/features/work/work-document-table-borders.d.ts +20 -0
  44. package/dist/internal/features/work/work-document-table-cell-formatting.d.ts +8 -5
  45. package/dist/internal/features/work/work-document-table-geometry.d.ts +41 -0
  46. package/dist/internal/features/work/work-document-table-property-changes.d.ts +25 -0
  47. package/dist/internal/features/work/work-document-table-sizing.d.ts +15 -2
  48. package/dist/internal/features/work/work-document-word-line-metrics.d.ts +11 -0
  49. package/dist/internal/features/work/work-docx-document-layout.d.ts +2 -0
  50. package/dist/internal/features/work/work-docx-paragraph-alignment-import.d.ts +2 -1
  51. package/dist/internal/features/work/work-docx-paragraph-direction-import.d.ts +2 -1
  52. package/dist/internal/features/work/work-docx-paragraph-indent-import.d.ts +2 -1
  53. package/dist/internal/features/work/work-docx-paragraph-pagination-import.d.ts +2 -1
  54. package/dist/internal/features/work/work-docx-paragraph-spacing-import.d.ts +3 -2
  55. package/dist/internal/features/work/work-docx-paragraph-styles.d.ts +2 -2
  56. package/dist/internal/features/work/work-docx-run-formatting-import.d.ts +8 -1
  57. package/dist/internal/features/work/work-docx-tab-stop-import.d.ts +2 -1
  58. package/dist/internal/features/work/work-docx-table-cell-export.d.ts +1 -1
  59. package/dist/internal/features/work/work-docx-table-cell-import.d.ts +14 -4
  60. package/dist/internal/features/work/work-docx-table-sizing-export.d.ts +1 -1
  61. package/dist/internal/features/work/work-docx-table-sizing-import.d.ts +4 -3
  62. package/dist/internal/features/work/work-docx-table-styles.d.ts +22 -0
  63. package/dist/internal/features/work/work-types.d.ts +6 -0
  64. package/dist/office-kernel.wasm +0 -0
  65. package/dist/styles.css +1288 -233
  66. package/docs/{browser-editor-architecture.md → latest/en/browser-editor-architecture.md} +144 -35
  67. package/package.json +9 -5
  68. package/dist/0~6552.js +0 -787
  69. package/dist/0~8155.js +0 -299
@@ -1440,6 +1440,7 @@ function MarkdownWorkspace({ editor, markdown, mode, readOnly = false, visualRea
1440
1440
  const releaseFrameRef = useRef(null);
1441
1441
  const sourceInputTypeRef = useRef(void 0);
1442
1442
  const [sourcePanePercent, setSourcePanePercent] = useState(DEFAULT_MARKDOWN_SPLIT_PERCENT);
1443
+ const [compactPane, setCompactPane] = useState('source');
1443
1444
  const [resizing, setResizing] = useState(false);
1444
1445
  const showSource = !readOnly && 'visual' !== mode;
1445
1446
  const showVisual = readOnly || 'source' !== mode;
@@ -1538,16 +1539,40 @@ function MarkdownWorkspace({ editor, markdown, mode, readOnly = false, visualRea
1538
1539
  return /*#__PURE__*/ jsxs("div", {
1539
1540
  ref: workspaceRef,
1540
1541
  className: `work-markdown-workspace ${mode}`,
1542
+ "data-compact-pane": 'split' === mode ? compactPane : void 0,
1541
1543
  "data-split-resizing": resizing || void 0,
1542
1544
  style: workspaceStyle,
1543
1545
  children: [
1546
+ 'split' === mode && /*#__PURE__*/ jsxs("fieldset", {
1547
+ className: "work-markdown-compact-switch",
1548
+ children: [
1549
+ /*#__PURE__*/ jsx("legend", {
1550
+ className: "sr-only",
1551
+ children: "分屏显示内容"
1552
+ }),
1553
+ /*#__PURE__*/ jsx("button", {
1554
+ type: "button",
1555
+ "aria-label": "显示源码窗格",
1556
+ "aria-pressed": 'source' === compactPane,
1557
+ onClick: ()=>setCompactPane('source'),
1558
+ children: "源码"
1559
+ }),
1560
+ /*#__PURE__*/ jsx("button", {
1561
+ type: "button",
1562
+ "aria-label": "显示预览窗格",
1563
+ "aria-pressed": 'preview' === compactPane,
1564
+ onClick: ()=>setCompactPane('preview'),
1565
+ children: "预览"
1566
+ })
1567
+ ]
1568
+ }),
1544
1569
  showSource && /*#__PURE__*/ jsxs("section", {
1545
1570
  "aria-label": "Markdown 源码窗格",
1546
1571
  className: "work-markdown-pane source",
1547
1572
  children: [
1548
1573
  'split' === mode && /*#__PURE__*/ jsx("header", {
1549
1574
  className: "work-markdown-pane-label",
1550
- children: "编辑"
1575
+ children: "源码"
1551
1576
  }),
1552
1577
  /*#__PURE__*/ jsx("textarea", {
1553
1578
  ref: sourceRef,
@@ -15,8 +15,8 @@ import { createOfficeId as createWorkId } from "./1134.js";
15
15
  import { OfficeTableInsertPopover, readOfficeFileAsDataUrl } from "./0~9445.js";
16
16
  import { normalizePresentationChartLegendPosition, presentationChartDataLabelPositions, presentationChartDataLabelText, normalizePresentationBubbleSizeRepresents, parsePresentationChartCategories, presentationChartXValues, withPresentationChartLayout, presentationChartTypeLabel, presentationChartAxes, withPresentationChartSeriesAnalysis, presentationChartUsesNumericXAxis, presentationChartSupportsSeriesMarkers, presentationChartBubbleSizes, createPresentationChartElement, parsePresentationChartValueDraft, normalizePresentationChartDataLabelPosition, presentationChartSupportsAxisTitles, withPresentationChartDataLabels, withPresentationChartType, createPresentationChartSeries, presentationChartErrorBarCount, normalizePresentationScatterStyle, withPresentationChartSeriesStyle, normalizePresentationBubbleScale, presentationChartDataLabelPositionLabel, presentationChartShowsLegend, presentationChartTrendlineCount, presentationChartHasDataLabels, normalizeDoughnutHoleSize, withPresentationChartAxes } from "./0~work-presentation-charts.js";
17
17
  import { spreadsheetChartSeriesLayout, workSpreadsheetChartSupportsGrouping, normalizeWorkSpreadsheetChartSmoothLines, workSpreadsheetChartAxisIsValueAxis, fitSpreadsheetTrendline, spreadsheetChartSeriesLegendColor, normalizeWorkSpreadsheetChartSeriesStyle, spreadsheetChartCategoryVisualIndex, errorBarSourceValues, normalizeWorkSpreadsheetErrorBars, workSpreadsheetChartSupportsTrendlines, normalizeWorkSpreadsheetChartLegendOverlay, normalizeWorkSpreadsheetChartGapWidth, spreadsheetChartCategoryLabelVisible, spreadsheetChartAxisLabelLayout, workSpreadsheetChartSupportsSmoothLines, workSpreadsheetChartGroupingIsStacked, normalizeWorkSpreadsheetChartGrouping, workSpreadsheetChartSupportsBarSpacing, workSpreadsheetChartSupportsErrorBars, spreadsheetChartSeriesLineStyle, workSpreadsheetChartAxisDefaultLabelPosition, workSpreadsheetChartSupportsSeriesAnalysis, workSpreadsheetChartAxisIsCategoryAxis, spreadsheetErrorBarAmounts, spreadsheetChartAxisValueRatio, spreadsheetChartAxisScale, normalizeWorkSpreadsheetChartOverlap, spreadsheetChartBarGeometry, workSpreadsheetChartAxisShowsMajorGridlinesByDefault, spreadsheetChartAxisGridlinesVisible, normalizeWorkSpreadsheetTrendline, roundChartNumber, formatSpreadsheetChartAxisNumber, spreadsheetChartSeriesFillStyle } from "./8715.js";
18
- import { useOfficeEditorWheelZoom, office_text_field_OfficeTextArea, stepOfficeZoom, button_Button, CommittedOfficeTextArea, CommittedOfficeTextField, office_text_field_OfficeTextField, icon_button_IconButton, useDialogFocusScope, office_text_field_OfficeFileInput } from "./0~9512.js";
19
- import { useOfficeTaskPaneEscape, normalizeOfficeFontFamily, OfficeCheckbox, CommittedOfficeNumberField, officeFontFamilyLabel, useOfficeDialog, createOfficeKernelClient, officeFontFamilies, CollectionState, OfficeNumberField, handleOfficeTaskPaneKeyDown } from "./0~7048.js";
18
+ import { useOfficeEditorWheelZoom, office_text_field_OfficeTextArea, stepOfficeZoom, button_Button, CommittedOfficeTextArea, CommittedOfficeTextField, office_text_field_OfficeTextField, useDialogFocusScope, icon_button_IconButton, office_text_field_OfficeFileInput } from "./0~9512.js";
19
+ import { useOfficeTaskPaneEscape, normalizeOfficeFontFamily, OfficeCheckbox, CommittedOfficeNumberField, useOfficeTaskPaneModal, officeFontFamilyLabel, useOfficeDialog, officeFontFamilies, CollectionState, createOfficeKernelClient, OfficeNumberField, handleOfficeTaskPaneKeyDown } from "./0~7048.js";
20
20
  import { WorkspaceContextMenu, isWorkspaceContextMenuKeyboardEvent, WorkOfficeZoomControls, WorkOfficeStatusBar, WorkOfficeRibbon, workspaceContextMenuPosition, OfficeSelect, WorkOfficeRibbonGroup, WorkOfficePreviewBar, WorkOfficeRibbonButton } from "./0~4595.js";
21
21
  import { presentationAgentProposalTargets, SpreadsheetChartSeriesStyleEditor, applyPresentationAgentProposalChanges, normalizeOptionalOfficeNumber, SpreadsheetErrorBarEditor, useOfficeHistory, presentationNotesProposalTarget, presentationAgentSelection, SpreadsheetTrendlineEditor, presentationAgentMenuItems } from "./0~3539.js";
22
22
  import { createOfficeEditorExtension, useOfficeEditorRuntime, useOfficeEditorKeyboardShortcuts } from "./0~3557.js";
@@ -978,6 +978,7 @@ function PresentationChartSeriesAnalysisEditor({ chart, seriesIndex, onChange })
978
978
  ]
979
979
  });
980
980
  }
981
+ const PRESENTATION_CHART_PANE_MODAL_QUERY = '(max-width: 1100px)';
981
982
  const CHART_TYPES = [
982
983
  'column',
983
984
  'bar',
@@ -989,7 +990,20 @@ const CHART_TYPES = [
989
990
  'scatter',
990
991
  'bubble'
991
992
  ];
992
- function PresentationChartPanel({ chart, onChange, onDelete, onClose }) {
993
+ function PresentationChartPanel({ chart, onChange, onDelete, onClose, restoreFocusTarget }) {
994
+ const panelRef = useRef(null);
995
+ const closeRef = useRef(null);
996
+ const modal = useOfficeTaskPaneModal(PRESENTATION_CHART_PANE_MODAL_QUERY);
997
+ const modalAttributes = modal ? {
998
+ role: 'dialog',
999
+ 'aria-modal': true
1000
+ } : {};
1001
+ const focusScope = useDialogFocusScope({
1002
+ active: modal,
1003
+ initialFocus: ()=>closeRef.current,
1004
+ getActiveScope: ()=>panelRef.current,
1005
+ restoreFocusTarget
1006
+ });
993
1007
  const numericXAxis = presentationChartUsesNumericXAxis(chart.type);
994
1008
  const updateSeries = (index, patch)=>{
995
1009
  onChange({
@@ -1001,9 +1015,14 @@ function PresentationChartPanel({ chart, onChange, onDelete, onClose }) {
1001
1015
  });
1002
1016
  };
1003
1017
  return /*#__PURE__*/ jsxs("section", {
1018
+ ...modalAttributes,
1019
+ ref: panelRef,
1004
1020
  className: "work-presentation-chart-panel",
1005
1021
  "aria-label": "演示图表数据",
1006
- onKeyDown: (event)=>handleOfficeTaskPaneKeyDown(event, onClose),
1022
+ onKeyDown: (event)=>{
1023
+ focusScope.handleKeyDown(event);
1024
+ if (!event.defaultPrevented) handleOfficeTaskPaneKeyDown(event, onClose);
1025
+ },
1007
1026
  children: [
1008
1027
  /*#__PURE__*/ jsxs("header", {
1009
1028
  children: [
@@ -1031,6 +1050,7 @@ function PresentationChartPanel({ chart, onChange, onDelete, onClose }) {
1031
1050
  ]
1032
1051
  }),
1033
1052
  /*#__PURE__*/ jsx(icon_button_IconButton, {
1053
+ ref: closeRef,
1034
1054
  className: "close",
1035
1055
  label: "关闭演示图表数据",
1036
1056
  onClick: (event)=>{
@@ -1886,12 +1906,31 @@ function createPresentationEditorExtensions() {
1886
1906
  createPresentationKeyboardExtension()
1887
1907
  ];
1888
1908
  }
1889
- function PresentationCommentsPanel({ slides, activeCommentId, commands }) {
1909
+ const PRESENTATION_COMMENTS_PANE_MODAL_QUERY = '(max-width: 640px)';
1910
+ function PresentationCommentsPanel({ slides, activeCommentId, commands, restoreFocusTarget }) {
1911
+ const panelRef = useRef(null);
1912
+ const closeRef = useRef(null);
1913
+ const modal = useOfficeTaskPaneModal(PRESENTATION_COMMENTS_PANE_MODAL_QUERY);
1914
+ const modalAttributes = modal ? {
1915
+ role: 'dialog',
1916
+ 'aria-modal': true
1917
+ } : {};
1918
+ const focusScope = useDialogFocusScope({
1919
+ active: modal,
1920
+ initialFocus: ()=>closeRef.current,
1921
+ getActiveScope: ()=>panelRef.current,
1922
+ restoreFocusTarget
1923
+ });
1890
1924
  const comments = presentationCommentViews(slides);
1891
1925
  return /*#__PURE__*/ jsxs("section", {
1926
+ ...modalAttributes,
1927
+ ref: panelRef,
1892
1928
  className: "work-presentation-comments-panel",
1893
1929
  "aria-label": "演示批注审阅",
1894
- onKeyDown: (event)=>handleOfficeTaskPaneKeyDown(event, commands.closeComments),
1930
+ onKeyDown: (event)=>{
1931
+ focusScope.handleKeyDown(event);
1932
+ if (!event.defaultPrevented) handleOfficeTaskPaneKeyDown(event, commands.closeComments);
1933
+ },
1895
1934
  children: [
1896
1935
  /*#__PURE__*/ jsxs("header", {
1897
1936
  children: [
@@ -1901,11 +1940,12 @@ function PresentationCommentsPanel({ slides, activeCommentId, commands }) {
1901
1940
  children: "演示批注"
1902
1941
  }),
1903
1942
  /*#__PURE__*/ jsx("span", {
1904
- children: comments.length ? `${comments.length} 条传统 PPTX 批注` : '没有批注'
1943
+ children: comments.length ? `${comments.length} 条批注` : '没有批注'
1905
1944
  })
1906
1945
  ]
1907
1946
  }),
1908
1947
  /*#__PURE__*/ jsx(icon_button_IconButton, {
1948
+ ref: closeRef,
1909
1949
  className: "close",
1910
1950
  label: "关闭演示批注审阅",
1911
1951
  onClick: commands.closeComments,
@@ -7204,6 +7244,7 @@ function resolveHistorySlideSelection(currentContent, nextContent, currentSlideI
7204
7244
  function usePresentationReviewCommands({ content, onChange, onClearSelection, onCloseComments, onOpenComments, onSelectComment, onSelectSlide, selectedElement, selectedSlide }) {
7205
7245
  const officeDialog = useOfficeDialog();
7206
7246
  const addComment = useCallback(()=>{
7247
+ const invoker = activePresentationReviewInvoker();
7207
7248
  officeDialog.prompt({
7208
7249
  title: '批注内容',
7209
7250
  multiline: true,
@@ -7228,7 +7269,7 @@ function usePresentationReviewCommands({ content, onChange, onClearSelection, on
7228
7269
  ]
7229
7270
  }), onChange);
7230
7271
  onSelectComment(comment.id);
7231
- onOpenComments();
7272
+ onOpenComments(invoker);
7232
7273
  });
7233
7274
  }, [
7234
7275
  content,
@@ -7240,8 +7281,9 @@ function usePresentationReviewCommands({ content, onChange, onClearSelection, on
7240
7281
  selectedSlide.id
7241
7282
  ]);
7242
7283
  const openComment = useCallback((commentId)=>{
7284
+ const invoker = activePresentationReviewInvoker();
7243
7285
  onSelectComment(commentId);
7244
- onOpenComments();
7286
+ onOpenComments(invoker);
7245
7287
  }, [
7246
7288
  onOpenComments,
7247
7289
  onSelectComment
@@ -7288,6 +7330,9 @@ function usePresentationReviewCommands({ content, onChange, onClearSelection, on
7288
7330
  updateComment
7289
7331
  };
7290
7332
  }
7333
+ function activePresentationReviewInvoker() {
7334
+ return "u" > typeof document && document.activeElement instanceof HTMLElement ? document.activeElement : null;
7335
+ }
7291
7336
  function usePresentationSelection(elements) {
7292
7337
  const [selectedElementIds, setSelectedElementIds] = useState([]);
7293
7338
  const [editingElementId, setEditingElementId] = useState(null);
@@ -7800,6 +7845,7 @@ function PresentationEditingSurface({ initialSlide, content, preview, saveStatus
7800
7845
  const [slideshowStartIndex, setSlideshowStartIndex] = useState(null);
7801
7846
  const [zoom, setZoom] = useState(90);
7802
7847
  const slideshowReturnFocusRef = useRef(null);
7848
+ const commentsInvokerRef = useRef(null);
7803
7849
  const presentationRootRef = useRef(null);
7804
7850
  const canvasRef = useRef(null);
7805
7851
  const objectFocusStateRef = useRef({
@@ -7949,7 +7995,11 @@ function PresentationEditingSurface({ initialSlide, content, preview, saveStatus
7949
7995
  const closeComments = useCallback(()=>{
7950
7996
  setTaskPane((current)=>'comments' === current ? null : current);
7951
7997
  }, []);
7952
- const openComments = useCallback(()=>{
7998
+ const openComments = useCallback((invoker)=>{
7999
+ const activeElement = "u" > typeof document && document.activeElement instanceof HTMLElement ? document.activeElement : null;
8000
+ const candidate = invoker ?? activeElement;
8001
+ const fallback = presentationRootRef.current?.querySelector('.work-presentation-ribbon button[aria-label^="查看批注"]') ?? null;
8002
+ commentsInvokerRef.current = !candidate?.isConnected || candidate.matches(':disabled') || candidate.closest('[hidden], [aria-hidden="true"]') ? fallback : candidate;
7953
8003
  if ('slide' !== designMode) {
7954
8004
  setDesignMode('slide');
7955
8005
  selection.clear();
@@ -7961,7 +8011,7 @@ function PresentationEditingSurface({ initialSlide, content, preview, saveStatus
7961
8011
  ]);
7962
8012
  const toggleComments = useCallback(()=>{
7963
8013
  if (commentsOpen) return void closeComments();
7964
- openComments();
8014
+ openComments("u" > typeof document && document.activeElement instanceof HTMLElement ? document.activeElement : null);
7965
8015
  }, [
7966
8016
  closeComments,
7967
8017
  commentsOpen,
@@ -8237,7 +8287,12 @@ function PresentationEditingSurface({ initialSlide, content, preview, saveStatus
8237
8287
  commentsOpen && 'slide' === designMode && /*#__PURE__*/ jsx(PresentationCommentsPanel, {
8238
8288
  slides: content.slides,
8239
8289
  activeCommentId: activeCommentId,
8240
- commands: presentationCommands
8290
+ commands: presentationCommands,
8291
+ restoreFocusTarget: ()=>{
8292
+ const invoker = commentsInvokerRef.current;
8293
+ if (invoker?.isConnected && !invoker.matches(':disabled') && !invoker.closest('[hidden], [aria-hidden="true"]')) return invoker;
8294
+ return presentationRootRef.current?.querySelector('.work-presentation-ribbon button[aria-label^="查看批注"]') ?? null;
8295
+ }
8241
8296
  }),
8242
8297
  /*#__PURE__*/ jsxs("div", {
8243
8298
  className: "work-presentation-workspace",
@@ -8281,6 +8336,7 @@ function PresentationEditingSurface({ initialSlide, content, preview, saveStatus
8281
8336
  altText: chart.title || '演示图表'
8282
8337
  }),
8283
8338
  onDelete: presentationCommands.deleteSelection,
8339
+ restoreFocusTarget: ()=>presentationRootRef.current?.querySelector('.work-slide-element.chart.selected') ?? null,
8284
8340
  onClose: closeChartPane
8285
8341
  })
8286
8342
  ]
@@ -6,13 +6,13 @@ import { Fragment as external_react_Fragment, useCallback, useEffect, useId, use
6
6
  import { genarate, update as core_update } from "@fortune-sheet/core";
7
7
  import { withoutEditableRange, SPREADSHEET_CONDITIONAL_COMPARISON_OPERATORS, editableRangeRequiresCredentials, normalizeSpreadsheetConditionalIconSetFormat, defaultSpreadsheetDataBarOptions, spreadsheetConditionalThresholdValue, normalizeSpreadsheetConditionalVisualOptions, withSheetProtection, spreadsheetProtectionKey, defaultSpreadsheetColorScaleThresholds, effectiveSpreadsheetPageSetup, protectedSheetCount, SPREADSHEET_CONDITIONAL_ICON_SETS, withSheetSelectionPermissions, withEditableRange, spreadsheetConditionalComparisonNeedsUpperValue, isSpreadsheetConditionalComparisonOperator, drawSpreadsheetConditionalIcon, spreadsheetConditionalIconForValue, defaultSpreadsheetConditionalIconThresholds, sheetProtectionAuthority, spreadsheetConditionalThresholdsEqual, editableRangeCellCount, unlockedCellCount } from "./8728.js";
8
8
  import { showToast } from "./6489.js";
9
- import { useOfficeTaskPaneEscape, OfficeCheckbox, CommittedOfficeNumberField, useOfficeDialog, createOfficeKernelClient, isOfficeKernelSpreadsheetError, officeFontFamilies, CollectionState, office_kernel_spreadsheet_protocol_OFFICE_KERNEL_SPREADSHEET_MAX_ROWS, OfficeNumberField, handleOfficeTaskPaneKeyDown } from "./0~7048.js";
9
+ import { useOfficeTaskPaneEscape, OfficeCheckbox, CommittedOfficeNumberField, useOfficeDialog, useOfficeTaskPaneModal, isOfficeKernelSpreadsheetError, officeFontFamilies, CollectionState, office_kernel_spreadsheet_protocol_OFFICE_KERNEL_SPREADSHEET_MAX_ROWS, OfficeNumberField, createOfficeKernelClient, handleOfficeTaskPaneKeyDown } from "./0~7048.js";
10
10
  import { isOfficeShortcutBlocked, OfficeColorPicker } from "./0~3635.js";
11
11
  import { createOfficeEditorExtension, useOfficeEditorRuntime, useOfficeEditorKeyboardShortcuts } from "./0~3557.js";
12
12
  import { workSpreadsheetChartSupportsGrouping, createSpreadsheetChartFromSelection, normalizeWorkSpreadsheetDataLabelPosition, normalizeSpreadsheetPrintTitleRows, normalizeSpreadsheetPrintTitleColumns, formulaHasStructuredReference, normalizeWorkSpreadsheetErrorBars, defaultPivotValueCaption, workSpreadsheetChartSupportsBarSpacing, normalizeWorkSpreadsheetChartGrouping, normalizeWorkSpreadsheetChartAxisGroup, normalizeWorkSpreadsheetScatterStyle, spreadsheetPivotAggregationLabel, workSpreadsheetChartAxisIsCategoryAxis, reconcileSpreadsheetChartPreviews, normalizeWorkSpreadsheetChartAxes, normalizeWorkSpreadsheetDoughnutHoleSize, normalizeWorkSpreadsheetChartLegendPosition, spreadsheetChartCount, workSpreadsheetChartTypeLabel, normalizeWorkSpreadsheetTrendline, spreadsheetPivotOutputContains, effectiveSpreadsheetCalculationSettings, normalizeWorkSpreadsheetDataLabels, spreadsheetPivotIntersects, normalizeSpreadsheetPrintArea, spreadsheetCellAddress, formatSpreadsheetCellRanges, normalizeWorkSpreadsheetChartLayout, spreadsheetFormulaRangeForCell, workSpreadsheetChartAxisIsValueAxis, normalizeWorkSpreadsheetChartSmoothLines, spreadsheetPivotFilterValueKey, normalizeWorkSpreadsheetBubbleScale, normalizeWorkSpreadsheetChartSeriesStyle, volatileSpreadsheetFormulaFunctions, normalizeWorkSpreadsheetBubbleSizeRepresents, workSpreadsheetChartSupportsTrendlines, normalizeWorkSpreadsheetChartLegendOverlay, parseSpreadsheetChartReference, workSpreadsheetChartGroupingIsStacked, normalizeWorkSpreadsheetChartGapWidth, workSpreadsheetChartSupportsSmoothLines, refreshSpreadsheetPivotTables, createSpreadsheetPivotFromSelection, spreadsheetPivotCount, reconcileSpreadsheetPivots, workSpreadsheetChartSupportsErrorBars, formulaHasExternalReference, isValidSpreadsheetDefinedName, spreadsheetPivotValidation, deleteSpreadsheetPivotTable, workSpreadsheetChartAxisDefaultLabelPosition, workSpreadsheetChartSupportsSeriesAnalysis, parseSpreadsheetCellRanges, spreadsheetPivotFields, spreadsheetPivotFilterItems, normalizeWorkSpreadsheetChartOverlap, spreadsheetFormulaRangeConflict, spreadsheetSheetsWithChartPreviews, workSpreadsheetChartUsesNumericXAxis, workSpreadsheetChartAxisShowsMajorGridlinesByDefault, workSpreadsheetChartSupportsAxes, normalizeWorkSpreadsheetCombinationSeriesType, normalizeWorkSpreadsheetRadarStyle } from "./8715.js";
13
13
  import { unsupportedSpreadsheetFormulaFunctions } from "./0~work-spreadsheet-formula-support.js";
14
14
  import { WorkspaceContextMenu, isWorkspaceContextMenuKeyboardEvent, WorkOfficeZoomControls, WorkOfficeStatusBar, WorkOfficeRibbon, workspaceContextMenuPosition, OfficeSelect, WorkOfficeRibbonGroup, WorkOfficePreviewBar, WorkOfficeRibbonButton } from "./0~4595.js";
15
- import { button_Button, moveOfficeMenuFocus, stepOfficeZoom, icon_button_IconButton, office_text_field_OfficeTextField, Popover, useOfficeEditorWheelZoom } from "./0~9512.js";
15
+ import { moveOfficeMenuFocus, stepOfficeZoom, Popover, button_Button, icon_button_IconButton, office_text_field_OfficeTextField, useDialogFocusScope, useOfficeEditorWheelZoom } from "./0~9512.js";
16
16
  import { useOfficeDraft } from "./0~use-office-draft.js";
17
17
  import { spreadsheetAgentMenuItems, SpreadsheetChartSeriesStyleEditor, normalizeOptionalOfficeNumber, normalizeRequiredOfficeNumber, SpreadsheetErrorBarEditor, useOfficeHistory, spreadsheetAgentSelection, SpreadsheetTrendlineEditor, applySpreadsheetAgentProposalChanges } from "./0~3539.js";
18
18
  import { StateView } from "./432.js";
@@ -8315,15 +8315,33 @@ function newRangeDraft() {
8315
8315
  reference: 'B2:B10'
8316
8316
  };
8317
8317
  }
8318
- function SpreadsheetWorkbookPanel({ id, content, view, activeSheetId, selection, can, commands, onClose }) {
8318
+ function SpreadsheetWorkbookPanel({ id, content, view, activeSheetId, selection, can, commands, restoreFocusTarget, onClose }) {
8319
8319
  const title = panelTitle(view);
8320
+ const panelRef = useRef(null);
8321
+ const closeRef = useRef(null);
8322
+ const modal = useOfficeTaskPaneModal();
8323
+ const modalAttributes = modal ? {
8324
+ role: 'dialog',
8325
+ 'aria-modal': true
8326
+ } : {};
8327
+ const focusScope = useDialogFocusScope({
8328
+ active: modal,
8329
+ initialFocus: ()=>closeRef.current,
8330
+ getActiveScope: ()=>panelRef.current,
8331
+ restoreFocusTarget
8332
+ });
8320
8333
  useOfficeTaskPaneEscape(true, onClose);
8321
8334
  return /*#__PURE__*/ jsxs("section", {
8335
+ ...modalAttributes,
8336
+ ref: panelRef,
8322
8337
  id: id,
8323
8338
  className: "work-spreadsheet-workbook-panel",
8324
8339
  "aria-label": title.label,
8325
8340
  "data-view": view,
8326
- onKeyDown: (event)=>handleOfficeTaskPaneKeyDown(event, onClose),
8341
+ onKeyDown: (event)=>{
8342
+ focusScope.handleKeyDown(event);
8343
+ if (!event.defaultPrevented) handleOfficeTaskPaneKeyDown(event, onClose);
8344
+ },
8327
8345
  children: [
8328
8346
  /*#__PURE__*/ jsxs("header", {
8329
8347
  children: [
@@ -8338,6 +8356,7 @@ function SpreadsheetWorkbookPanel({ id, content, view, activeSheetId, selection,
8338
8356
  ]
8339
8357
  }),
8340
8358
  /*#__PURE__*/ jsx(icon_button_IconButton, {
8359
+ ref: closeRef,
8341
8360
  label: `关闭${title.heading}`,
8342
8361
  onClick: onClose,
8343
8362
  children: /*#__PURE__*/ jsx(X, {
@@ -9712,9 +9731,13 @@ function SpreadsheetEditor({ content, kernelWasmUrl, preview, saveStatus = '已
9712
9731
  ]);
9713
9732
  const closeWorkbookPanel = useCallback(()=>{
9714
9733
  const trigger = panelTriggerRef.current;
9715
- panelTriggerRef.current = null;
9716
9734
  setPanel(null);
9717
- if (trigger?.isConnected) trigger.focus();
9735
+ requestAnimationFrame(()=>{
9736
+ if (trigger?.isConnected) trigger.focus({
9737
+ preventScroll: true
9738
+ });
9739
+ if (panelTriggerRef.current === trigger) panelTriggerRef.current = null;
9740
+ });
9718
9741
  }, []);
9719
9742
  const workbookHooks = useMemo(()=>({
9720
9743
  afterActivateSheet: (id)=>{
@@ -9875,7 +9898,7 @@ function SpreadsheetEditor({ content, kernelWasmUrl, preview, saveStatus = '已
9875
9898
  }, []);
9876
9899
  const closeSpreadsheetFind = useCallback(()=>{
9877
9900
  setFindOpen(false);
9878
- requestAnimationFrame(()=>focusSpreadsheetGrid(spreadsheetCanvasRef.current));
9901
+ focusSpreadsheetGrid(spreadsheetCanvasRef.current);
9879
9902
  }, []);
9880
9903
  const selectSpreadsheetFindMatch = useCallback((match)=>{
9881
9904
  try {
@@ -10054,17 +10077,13 @@ function SpreadsheetEditor({ content, kernelWasmUrl, preview, saveStatus = '已
10054
10077
  onOpenFind: openSpreadsheetFind,
10055
10078
  onTabChange: (tab)=>{
10056
10079
  setRibbonTab(tab);
10057
- panelTriggerRef.current = null;
10058
- setPanel(null);
10080
+ if (panel) closeWorkbookPanel();
10081
+ },
10082
+ onTogglePanel: (nextPanel, trigger)=>{
10083
+ if (panel === nextPanel) return void closeWorkbookPanel();
10084
+ panelTriggerRef.current = trigger;
10085
+ setPanel(nextPanel);
10059
10086
  },
10060
- onTogglePanel: (nextPanel, trigger)=>setPanel((current)=>{
10061
- if (current === nextPanel) {
10062
- panelTriggerRef.current = null;
10063
- return null;
10064
- }
10065
- panelTriggerRef.current = trigger;
10066
- return nextPanel;
10067
- }),
10068
10087
  panel: panel,
10069
10088
  toolbarCell: toolbarCell
10070
10089
  }),
@@ -10120,6 +10139,7 @@ function SpreadsheetEditor({ content, kernelWasmUrl, preview, saveStatus = '已
10120
10139
  selection: selectionState?.sheetId === panelSheetId ? selectionState.selection : void 0,
10121
10140
  can: spreadsheetCan,
10122
10141
  commands: spreadsheetCommands,
10142
+ restoreFocusTarget: ()=>panelTriggerRef.current,
10123
10143
  onClose: closeWorkbookPanel
10124
10144
  })
10125
10145
  ]