@a3s-lab/office 0.36.0 → 0.37.1

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 (59) hide show
  1. package/README.md +18 -6
  2. package/dist/0~3557.js +2 -1
  3. package/dist/0~3635.js +4 -1
  4. package/dist/0~7048.js +93 -1
  5. package/dist/0~9073.js +7 -2
  6. package/dist/0~presentation-editor.js +45 -9
  7. package/dist/0~spreadsheet-editor.js +20321 -16966
  8. package/dist/4121.js +1942 -1939
  9. package/dist/{3266.js → 5416.js} +1504 -20
  10. package/dist/9333.js +1 -1
  11. package/dist/core.d.ts +1 -0
  12. package/dist/core.js +141 -28
  13. package/dist/index.js +1 -1
  14. package/dist/internal/features/work/editors/office-shortcuts.d.ts +1 -0
  15. package/dist/internal/features/work/editors/spreadsheet-auto-filter-command.d.ts +3 -0
  16. package/dist/internal/features/work/editors/spreadsheet-auto-filter-condition-dialog-model.d.ts +27 -0
  17. package/dist/internal/features/work/editors/spreadsheet-auto-filter-condition-dialog.d.ts +17 -0
  18. package/dist/internal/features/work/editors/spreadsheet-auto-filter-menu.d.ts +10 -0
  19. package/dist/internal/features/work/editors/spreadsheet-auto-filter.d.ts +16 -4
  20. package/dist/internal/features/work/editors/spreadsheet-cell-range.d.ts +1 -0
  21. package/dist/internal/features/work/editors/spreadsheet-command-catalog.d.ts +9 -0
  22. package/dist/internal/features/work/editors/spreadsheet-command-controller.d.ts +13 -1
  23. package/dist/internal/features/work/editors/spreadsheet-current-region.d.ts +12 -0
  24. package/dist/internal/features/work/editors/spreadsheet-editor.d.ts +3 -0
  25. package/dist/internal/features/work/editors/spreadsheet-sort-appearance.d.ts +45 -0
  26. package/dist/internal/features/work/editors/spreadsheet-sort-collation.d.ts +8 -0
  27. package/dist/internal/features/work/editors/spreadsheet-sort-command.d.ts +3 -0
  28. package/dist/internal/features/work/editors/spreadsheet-sort-custom-list-editor.d.ts +8 -0
  29. package/dist/internal/features/work/editors/spreadsheet-sort-custom-list-store.d.ts +13 -0
  30. package/dist/internal/features/work/editors/spreadsheet-sort-custom-list.d.ts +26 -0
  31. package/dist/internal/features/work/editors/spreadsheet-sort-dialog.d.ts +9 -0
  32. package/dist/internal/features/work/editors/spreadsheet-sort-matrix.d.ts +4 -0
  33. package/dist/internal/features/work/editors/spreadsheet-sort-options-dialog.d.ts +7 -0
  34. package/dist/internal/features/work/editors/spreadsheet-sort-order-controls.d.ts +16 -0
  35. package/dist/internal/features/work/editors/spreadsheet-sort-range-dialog.d.ts +7 -0
  36. package/dist/internal/features/work/editors/spreadsheet-sort.d.ts +138 -0
  37. package/dist/internal/features/work/editors/spreadsheet-table-totals.d.ts +39 -0
  38. package/dist/internal/features/work/editors/spreadsheet-table.d.ts +11 -1
  39. package/dist/internal/features/work/editors/use-spreadsheet-auto-filter.d.ts +12 -3
  40. package/dist/internal/features/work/editors/use-spreadsheet-sort.d.ts +26 -0
  41. package/dist/internal/features/work/editors/work-office-chrome.d.ts +3 -0
  42. package/dist/internal/features/work/work-spreadsheet-auto-filter.d.ts +14 -0
  43. package/dist/internal/features/work/work-spreadsheet-dynamic-filter.d.ts +7 -0
  44. package/dist/internal/features/work/work-spreadsheet-filter-contract.d.ts +3 -0
  45. package/dist/internal/features/work/work-spreadsheet-wildcard.d.ts +7 -0
  46. package/dist/internal/features/work/work-types.d.ts +45 -7
  47. package/dist/internal/features/work/work-xlsx-interop.d.ts +2 -1
  48. package/dist/internal/features/work/work-xlsx-table-filters.d.ts +3 -1
  49. package/dist/internal/kernel/office-kernel-spreadsheet-fallback-formula.d.ts +11 -0
  50. package/dist/office-kernel.wasm +0 -0
  51. package/dist/office-kernel.worker.js +93 -1
  52. package/dist/styles.css +789 -145
  53. package/dist/vue.d.ts +3 -1
  54. package/dist/vue.js +2 -0
  55. package/dist/web-component.d.ts +3 -1
  56. package/dist/web-component.js +9 -0
  57. package/dist/work-spreadsheet-package-scan.worker.js +2 -1
  58. package/docs/latest/en/browser-editor-architecture.md +136 -2
  59. package/package.json +24 -1
package/README.md CHANGED
@@ -56,7 +56,7 @@ workflows, and a separate Rust automation plane.
56
56
 
57
57
  ## Latest on `main`
58
58
 
59
- The `0.36.0` release exposes these capabilities as normal user-facing
59
+ The `0.37.1` release exposes these capabilities as normal user-facing
60
60
  Playground templates, with matching implementation detail in the documentation:
61
61
 
62
62
  | Editor | Latest capability | Public entry |
@@ -68,7 +68,7 @@ Playground templates, with matching implementation detail in the documentation:
68
68
  | Writer | Native character shading with exact `w:shd` patterns, foreground/background color identity, explicit resets, authoring, and DOCX reopen | Playground **Latest capabilities → 字符底纹** · [Document reference](docs/latest/en/components/document.mdx#native-character-shading) |
69
69
  | Writer | Independent Latin, East Asian, and bidi proofing languages plus explicit `w:noProof` inclusion/exclusion | Playground **Latest capabilities → 校对语言** · [Document reference](docs/latest/en/components/document.mdx#native-proofing-languages) |
70
70
  | Spreadsheet | Complete common Data Validation input, blank/dropdown, and Stop/Warning/Information error settings with native XLSX round trips | Playground **Latest capabilities → 数据验证** · [Spreadsheet reference](docs/latest/en/components/spreadsheet.mdx#data-validation) |
71
- | Spreadsheet | Bounded structured-reference calculation plus automatic calculated-column fill for table names/display names, contiguous columns, header/data/totals selectors, qualified references, and table-local current-row formulas across Rust/WASM and JavaScript fallback | Playground **Latest capabilities → 结构化引用** · [Spreadsheet reference](docs/latest/en/components/spreadsheet.mdx#structured-reference-calculation) |
71
+ | Spreadsheet | Native totals-row authoring with per-column aggregates, labels, custom formulas, filtered-row-aware `SUBTOTAL`, automatic calculated-column fill for newly inserted table body rows, and bounded structured-reference calculation across Rust/WASM and JavaScript fallback | Playground **Latest capabilities → 结构化引用** · [Totals-row reference](docs/latest/en/components/spreadsheet.mdx#native-totals-row-authoring) · [Structured-reference calculation](docs/latest/en/components/spreadsheet.mdx#structured-reference-calculation) |
72
72
  | PDF | Insert, delete, rotate, reorder, extract, merge, and split pages through a dedicated Web Worker, with Blob-level Undo/Redo and independent binary reopen verification | Playground **Latest capabilities → 组织 PDF 页面** · [PDF reference](docs/latest/en/components/pdf.mdx#page-organization) |
73
73
 
74
74
  All nine entries are reachable from the first Playground viewport. The
@@ -152,7 +152,8 @@ baseline rather than one specific release.
152
152
  | Formatting and style rendering | **Partial** — native fonts, colors, borders, alignment, number formats, cell styles, all 17 native non-solid OOXML pattern fills, native linear/path XLSX gradients, and one Format Cells surface that authors none, solid, pattern, or gradient fills with exact geometry and 2–256 ordered stops; static date/time entry, contrast-safe font preview, native XLSX rich-text runs, selected-text font formatting, direct formula-bar/F2 insertion or deletion, and bounded authenticated formatted-HTML paste | Disjoint multi-edit rich-text authoring, broader themes, locale formats, and advanced style effects |
153
153
  | Ribbon and shortcuts | **Partial** — common Office-style Home/Data/View commands, grid-scoped shortcuts, and focused Font-dialog aliases | Larger command catalog and platform-specific accelerators |
154
154
  | Formulas and recalculation | **Partial** — dependency-aware calculation plus bounded structured references (`Table[Column]`, contiguous ranges, `#All`/`#Headers`/`#Data`/`#Totals`/`#This Row`, and `[@Column]`) in the shared Rust/WASM and JavaScript paths | Wider functions, arrays, volatile semantics, and calculation parity |
155
- | Tables, pivots, charts, and rules | **Partial** — native tables, bounded structured-reference formulas, calculated-column formulas with automatic fill for newly inserted body rows, pivots, charts, conditional formatting, and common validation rules with complete input/error-setting authoring | Complete totals-row authoring, slicers, pivot charts, custom/dependent validation rules, advanced analysis, and broader browser alert flows |
155
+ | Sort and filter | **Partial** — Traditional Office-style current-region expansion warnings for partial selections; Traditional Office-compatible top-to-bottom or left-to-right Custom Sort with stable value, custom-list, effective cell-color, effective font-color, and conditional-format icon keys; offline Simplified Chinese pinyin/stroke comparison, optional lowercase-before-uppercase case sensitivity, and lexical numeric text; seven built-in month/weekday sequences; bounded typed host-stored or mounted-session sequences; header retention for top-to-bottom sorting; top/bottom or left/right appearance placement; up to 64 ordered keys; blanks-last value behavior; axis-aware relative-formula translation; and one-step Undo; plus worksheet AutoFilter authoring, keyboard menus, common text/value/numeric/blank conditions, exactly two same-column conditions joined by AND or OR, native OOXML `*`/`?`/`~` wildcard expressions, negative prefix/suffix operators, tie-aware Top/Bottom item and percentage filters, locally evaluated above/below-average and complete native relative-date, month, and quarter dynamic families on typed 1900-system date cells, multi-column row ownership, manual-hide preservation, and native XLSX criteria round trips with imported dynamic-filter recomputation | Custom-list deletion/reordering UI, broader locale collation, source-level 1904 date-system retention for dynamic dates, large aggregate/rank Worker/WASM offload, and table/AutoFilter-integrated custom sorting |
156
+ | Tables, pivots, charts, and rules | **Partial** — native tables, bounded structured-reference formulas, calculated-column formulas with automatic fill for newly inserted body rows, complete common totals-row authoring, pivots, charts, conditional formatting, and common validation rules with complete input/error-setting authoring | Slicers, pivot charts, custom/dependent validation rules, advanced analysis, and broader browser alert flows |
156
157
  | Large worksheets | **Supported with boundaries** — maximum-dimension sparse import/editing and viewport-bounded Canvas painting | Highly optimized native grid with hardware-dependent limits |
157
158
  | Files and printing | **Partial** — XLS/XLSX/ODS/CSV import, XLSX export, and PDF output | Broader round trips, external data, print fidelity, and legacy conversion |
158
159
  | External data, macros, and specialist analysis | **Gap** — active macros are never executed; bounded models are still needed for data connections and solver-like tools | Established data, macro/add-in, scenario, and optimization ecosystems |
@@ -216,6 +217,9 @@ is requested. The complete gap inventory and exit evidence live in the
216
217
  preserving spatial arrow-key navigation.
217
218
  Shared Office selects use 44 px phone option rows and bounded internal
218
219
  scrolling while retaining keyboard selection and exact focus restoration.
220
+ Host-provided file menus keep every action visually identifiable with an
221
+ explicit or neutral fallback icon, readable long labels, grouped destructive
222
+ actions, and a visible keyboard focus ring.
219
223
  - **Editor-scoped zoom** — Status controls and Ctrl/Cmd + mouse-wheel gestures
220
224
  share each surface's bounded zoom model without changing the host browser's
221
225
  page scale.
@@ -756,9 +760,15 @@ conflicting column fails closed and drops its automatic rule. XLSX
756
760
  `<calculatedColumnFormula>` metadata round-trips with the leading `=` restored
757
761
  in the controlled model, while unsafe or external formulas are omitted.
758
762
  The Playground's **结构化引用** template shows a calculated `Revenue` column,
759
- an insertion hint, a totals row, and a worksheet-qualified summary. Complete
760
- totals-row authoring, slicers, and external/query tables remain explicit
761
- boundaries.
763
+ an insertion hint, an editable totals row, and a worksheet-qualified summary.
764
+ The Table Design totals menu enables or disables the row and assigns each
765
+ column a label, one of ten native aggregate functions, or a bounded custom
766
+ formula. Native aggregates emit filtered-row-aware `SUBTOTAL` formulas; direct
767
+ cell edits reconcile back into table metadata, table structure changes move
768
+ the row without overwriting manual cells, and table renames rewrite only
769
+ generated formulas. Dense and sparse worksheets, Yjs collaboration, and XLSX
770
+ `totalsRowFunction`, `totalsRowLabel`, and `totalsRowFormula` round trips share
771
+ the same model. Slicers and external/query tables remain explicit boundaries.
762
772
 
763
773
  Use `downloadArtifact` to start a browser download or
764
774
  `createArtifactBlob` when your application owns upload and persistence.
@@ -1641,6 +1651,8 @@ keep working without hard-coded return URLs.
1641
1651
 
1642
1652
  - [Live Playground](https://a3s-lab.github.io/Office/playground/)
1643
1653
  - [Documentation center](https://a3s-lab.github.io/Office/docs/)
1654
+ - [A3S Office 0.37.1 documentation](https://a3s-lab.github.io/Office/docs/0.37.1/)
1655
+ - [A3S Office 0.37.0 documentation](https://a3s-lab.github.io/Office/docs/0.37.0/)
1644
1656
  - [A3S Office 0.36.0 documentation](https://a3s-lab.github.io/Office/docs/0.36.0/)
1645
1657
  - [A3S Office 0.34.0 documentation](https://a3s-lab.github.io/Office/docs/0.34.0/)
1646
1658
  - [A3S Office 0.33.0 documentation](https://a3s-lab.github.io/Office/docs/0.33.0/)
package/dist/0~3557.js CHANGED
@@ -1,4 +1,5 @@
1
1
  import { useEffect, useLayoutEffect, useMemo, useRef } from "react";
2
+ import { isOfficeCompositionKeyboardEvent } from "./0~3635.js";
2
3
  import { matchesOfficeEditorKeyboardShortcut } from "./0~8136.js";
3
4
  const DEFAULT_EXTENSION_PRIORITY = 100;
4
5
  function createOfficeEditorExtension(config) {
@@ -97,7 +98,7 @@ function createOfficeEditorRuntime(initialContext, extensions, options = {}) {
97
98
  storage: Object.freeze(storage),
98
99
  can: ()=>canApi,
99
100
  handleKeyDown: (event)=>{
100
- if (event.defaultPrevented) return false;
101
+ if (event.defaultPrevented || isOfficeCompositionKeyboardEvent(event)) return false;
101
102
  for (const instance of instances)for (const shortcut of instance.keyboardShortcuts)if (matchesOfficeEditorKeyboardShortcut(event, shortcut.shortcut) && shortcut.handler(readContext(), commandApi, canApi, event)) {
102
103
  event.preventDefault();
103
104
  return true;
package/dist/0~3635.js CHANGED
@@ -314,10 +314,13 @@ function swatchForeground(color) {
314
314
  }
315
315
  const MODAL_DIALOG_SELECTOR = '[role="dialog"][aria-modal="true"]';
316
316
  const OFFICE_SHORTCUT_IGNORE_SELECTOR = '[data-office-shortcuts="ignore"]';
317
+ function isOfficeCompositionKeyboardEvent(event) {
318
+ return event.isComposing || 'Process' === event.key || 229 === event.keyCode;
319
+ }
317
320
  function isOfficeShortcutBlocked(target) {
318
321
  if ("u" < typeof document) return false;
319
322
  if (target instanceof Element && (target.closest(MODAL_DIALOG_SELECTOR) || target.closest(OFFICE_SHORTCUT_IGNORE_SELECTOR))) return true;
320
323
  if (document.activeElement instanceof Element && (document.activeElement.closest(MODAL_DIALOG_SELECTOR) || document.activeElement.closest(OFFICE_SHORTCUT_IGNORE_SELECTOR))) return true;
321
324
  return null !== document.querySelector(MODAL_DIALOG_SELECTOR);
322
325
  }
323
- export { OfficeColorPicker, isOfficeShortcutBlocked };
326
+ export { OfficeColorPicker, isOfficeCompositionKeyboardEvent, isOfficeShortcutBlocked };
package/dist/0~7048.js CHANGED
@@ -1352,6 +1352,13 @@ const browserScalarFunctionArities = new Map([
1352
1352
  1
1353
1353
  ]
1354
1354
  ],
1355
+ [
1356
+ 'SUBTOTAL',
1357
+ [
1358
+ 2,
1359
+ 255
1360
+ ]
1361
+ ],
1355
1362
  [
1356
1363
  'SUM',
1357
1364
  [
@@ -1372,6 +1379,90 @@ function normalizeSpreadsheetFunctionName(name) {
1372
1379
  while(normalized.startsWith('_XLFN.') || normalized.startsWith('_XLWS.'))normalized = normalized.slice(6);
1373
1380
  return normalized;
1374
1381
  }
1382
+ function evaluateParserSubtotal(parameters) {
1383
+ const codeValue = parserNumericValue(parameters[0]);
1384
+ if (void 0 === codeValue) return 'VALUE!';
1385
+ const code = Math.trunc(codeValue);
1386
+ const values = parameters.slice(1).flatMap((parameter)=>flattenParserValues(parameter));
1387
+ for (const value of values){
1388
+ const error = parserErrorValue(value);
1389
+ if (error) return error;
1390
+ }
1391
+ switch(code){
1392
+ case 1:
1393
+ case 101:
1394
+ return parserSubtotalNumeric(values, 'average');
1395
+ case 2:
1396
+ case 102:
1397
+ return values.filter((value)=>'number' == typeof value).length;
1398
+ case 3:
1399
+ case 103:
1400
+ return values.filter((value)=>null != value).length;
1401
+ case 4:
1402
+ case 104:
1403
+ return parserSubtotalNumeric(values, 'max');
1404
+ case 5:
1405
+ case 105:
1406
+ return parserSubtotalNumeric(values, 'min');
1407
+ case 6:
1408
+ case 106:
1409
+ return parserSubtotalNumeric(values, 'product');
1410
+ case 7:
1411
+ case 107:
1412
+ return parserSubtotalNumeric(values, 'stddev');
1413
+ case 8:
1414
+ case 108:
1415
+ return parserSubtotalNumeric(values, 'stddevp');
1416
+ case 9:
1417
+ case 109:
1418
+ return parserSubtotalNumeric(values, 'sum');
1419
+ case 10:
1420
+ case 110:
1421
+ return parserSubtotalNumeric(values, 'var');
1422
+ case 11:
1423
+ case 111:
1424
+ return parserSubtotalNumeric(values, 'varp');
1425
+ default:
1426
+ return 'VALUE!';
1427
+ }
1428
+ }
1429
+ function parserSubtotalNumeric(values, operation) {
1430
+ const numbers = values.filter((value)=>'number' == typeof value && Number.isFinite(value));
1431
+ const count = numbers.length;
1432
+ const sum = numbers.reduce((total, value)=>total + value, 0);
1433
+ if ('sum' === operation) return finiteParserNumber(sum);
1434
+ if ('average' === operation) return count ? finiteParserNumber(sum / count) : 'DIV/0!';
1435
+ if ('max' === operation) return finiteParserNumber(Math.max(...numbers, 0));
1436
+ if ('min' === operation) return finiteParserNumber(Math.min(...numbers, 0));
1437
+ if ('product' === operation) return finiteParserNumber(count ? numbers.reduce((total, value)=>total * value, 1) : 0);
1438
+ if ('stddev' === operation || 'var' === operation) {
1439
+ if (count < 2) return 'DIV/0!';
1440
+ } else if (0 === count) return 'DIV/0!';
1441
+ const mean = sum / count;
1442
+ const divisor = 'stddev' === operation || 'var' === operation ? count - 1 : count;
1443
+ const variance = numbers.reduce((total, value)=>total + (value - mean) ** 2, 0) / divisor;
1444
+ return finiteParserNumber('stddev' === operation || 'stddevp' === operation ? Math.sqrt(variance) : variance);
1445
+ }
1446
+ function flattenParserValues(value) {
1447
+ if (!Array.isArray(value)) return [
1448
+ value
1449
+ ];
1450
+ return value.flatMap((entry)=>flattenParserValues(entry));
1451
+ }
1452
+ function parserNumericValue(value) {
1453
+ if ('number' == typeof value) return Number.isFinite(value) ? value : void 0;
1454
+ if ('boolean' == typeof value) return value ? 1 : 0;
1455
+ if ('string' != typeof value || !value.trim()) return;
1456
+ const parsed = Number(value);
1457
+ return Number.isFinite(parsed) ? parsed : void 0;
1458
+ }
1459
+ function parserErrorValue(value) {
1460
+ if (value instanceof Error) return value.message.startsWith('#') ? value.message.slice(1) : 'VALUE!';
1461
+ return 'string' == typeof value && value.startsWith('#') ? value.slice(1) : void 0;
1462
+ }
1463
+ function finiteParserNumber(value) {
1464
+ return Number.isFinite(value) ? value : 'NUM!';
1465
+ }
1375
1466
  function normalizeFormulaForFortuneParser(formula) {
1376
1467
  const source = formula.replace(/^=/, '');
1377
1468
  let output = '';
@@ -2154,10 +2245,11 @@ class JavaScriptSpreadsheetEvaluator {
2154
2245
  let unsupportedFunction;
2155
2246
  let materializedRangeCells = 0;
2156
2247
  parser.setFunction('IFERROR', evaluateParserIfError).setFunction('ROW', (parameters)=>parameters.length ? null : coordinate.row + 1).setFunction('COLUMN', (parameters)=>parameters.length ? null : coordinate.column + 1);
2157
- parser.on('callFunction', (name, parameters)=>{
2248
+ parser.on('callFunction', (name, parameters, done)=>{
2158
2249
  const normalized = normalizeSpreadsheetFunctionName(name);
2159
2250
  const arity = browserScalarFunctionArities.get(normalized);
2160
2251
  if (!arity || parameters.length < arity[0] || parameters.length > arity[1]) unsupportedFunction ??= name.toUpperCase();
2252
+ if ('SUBTOTAL' === normalized) done(evaluateParserSubtotal(parameters));
2161
2253
  });
2162
2254
  parser.on('callCellValue', (cell, _options, done)=>{
2163
2255
  const dependency = this.resolveCoordinate(indexed.sheet, cell);
package/dist/0~9073.js CHANGED
@@ -1,7 +1,7 @@
1
1
  import { Fragment as jsx_runtime_Fragment, jsx, jsxs } from "react/jsx-runtime";
2
2
  import { Fragment, useCallback, useEffect, useId, useLayoutEffect, useMemo, useRef, useState } from "react";
3
3
  import { createPortal } from "react-dom";
4
- import { ArrowUpRight, Check, ChevronDown, ChevronLeft, ChevronRight, ChevronUp, Eye, Minus, Plus } from "lucide-react";
4
+ import { ArrowUpRight, Check, ChevronDown, ChevronLeft, ChevronRight, ChevronUp, Eye, File, Minus, Plus } from "lucide-react";
5
5
  import { WorkOfficeCollaborationParticipants, moveOfficeMenuFocus, Popover, matchesAriaKeyShortcuts, officeOverlayPortalRoot } from "./0~8136.js";
6
6
  const CONTEXT_MENU_MARGIN = 8;
7
7
  const CONTEXT_MENU_TAB_STOP_SELECTOR = 'a[href]:not([tabindex="-1"]), button:not(:disabled):not([tabindex="-1"]), input:not(:disabled):not([type="hidden"]):not([tabindex="-1"]), select:not(:disabled):not([tabindex="-1"]), textarea:not(:disabled):not([tabindex="-1"]), [contenteditable="true"]:not([tabindex="-1"]), [tabindex]:not([tabindex="-1"])';
@@ -1071,6 +1071,8 @@ function WorkOfficeFileMenu({ actions }) {
1071
1071
  type: "button",
1072
1072
  role: "menuitem",
1073
1073
  tabIndex: -1,
1074
+ className: action.danger ? 'danger' : void 0,
1075
+ "data-danger": action.danger ? 'true' : void 0,
1074
1076
  disabled: action.disabled,
1075
1077
  onClick: ()=>{
1076
1078
  close();
@@ -1080,9 +1082,12 @@ function WorkOfficeFileMenu({ actions }) {
1080
1082
  /*#__PURE__*/ jsx("span", {
1081
1083
  className: "work-office-file-action-icon",
1082
1084
  "aria-hidden": "true",
1083
- children: action.icon
1085
+ children: action.icon ?? /*#__PURE__*/ jsx(File, {
1086
+ size: 16
1087
+ })
1084
1088
  }),
1085
1089
  /*#__PURE__*/ jsx("span", {
1090
+ className: "work-office-file-action-label",
1086
1091
  children: action.label
1087
1092
  }),
1088
1093
  action.shortcut && /*#__PURE__*/ jsx("kbd", {
@@ -21,7 +21,7 @@ import { WorkspaceContextMenu, isWorkspaceContextMenuKeyboardEvent, WorkOfficeZo
21
21
  import { presentationAgentProposalTargets, SpreadsheetChartSeriesStyleEditor, applyPresentationAgentProposalChanges, normalizeOptionalOfficeNumber, SpreadsheetErrorBarEditor, useOfficeHistory, presentationNotesProposalTarget, presentationAgentSelection, SpreadsheetTrendlineEditor, presentationAgentMenuItems } from "./0~3539.js";
22
22
  import { slideTransitionDurationMilliseconds, workSlideAnimationIndex, workSlideAnimationForElement, remapWorkSlideAnimations, createWorkSlideTransition, workSlideTransitionsEqual, workSlideAnimationCues, initialWorkSlideAnimationCueIndex, normalizeWorkSlideAnimation, createWorkSlideAnimation, removeWorkSlideAnimationsForElements } from "./0~5809.js";
23
23
  import { createOfficeEditorExtension, useOfficeEditorRuntime, useOfficeEditorKeyboardShortcuts } from "./0~3557.js";
24
- import { isOfficeShortcutBlocked, OfficeColorPicker } from "./0~3635.js";
24
+ import { isOfficeShortcutBlocked, OfficeColorPicker, isOfficeCompositionKeyboardEvent } from "./0~3635.js";
25
25
  import { normalizeDocumentHref, DOCUMENT_LINK_VALIDATION_MESSAGE } from "./0~work-document-links.js";
26
26
  import { showToast } from "./6489.js";
27
27
  import { scaledPresentationVisuals } from "./0~work-presentation-visual-scale.js";
@@ -4357,6 +4357,8 @@ function PresentationTextEditor({ autoFocus = false, element, onChange, onEditor
4357
4357
  const onEditorChangeRef = useRef(onEditorChange);
4358
4358
  const onExitEditingRef = useRef(onExitEditing);
4359
4359
  const onSelectionChangeRef = useRef(onSelectionChange);
4360
+ const editorRef = useRef(null);
4361
+ const compositionPublishTimerRef = useRef(null);
4360
4362
  const appliedSignatureRef = useRef(presentationTextElementSignature(element));
4361
4363
  const initialContentRef = useRef(presentationTextElementHtml(element));
4362
4364
  const initialFocusTargetRef = useRef("u" > typeof document && document.activeElement instanceof HTMLElement ? document.activeElement : null);
@@ -4368,6 +4370,30 @@ function PresentationTextEditor({ autoFocus = false, element, onChange, onEditor
4368
4370
  const extensions = useMemo(()=>createPresentationTextEditorExtensions(element.placeholder?.prompt ?? '输入文字'), [
4369
4371
  element.placeholder?.prompt
4370
4372
  ]);
4373
+ const publishEditorValue = (current)=>{
4374
+ const value = presentationTextValue(current, elementRef.current);
4375
+ const signature = presentationTextElementSignature({
4376
+ ...elementRef.current,
4377
+ ...value
4378
+ });
4379
+ if (signature === appliedSignatureRef.current) return;
4380
+ appliedSignatureRef.current = signature;
4381
+ onChangeRef.current(value);
4382
+ };
4383
+ const cancelCompositionPublication = ()=>{
4384
+ if (null === compositionPublishTimerRef.current) return;
4385
+ window.clearTimeout(compositionPublishTimerRef.current);
4386
+ compositionPublishTimerRef.current = null;
4387
+ };
4388
+ const publishCommittedComposition = ()=>{
4389
+ cancelCompositionPublication();
4390
+ compositionPublishTimerRef.current = window.setTimeout(()=>{
4391
+ compositionPublishTimerRef.current = null;
4392
+ const current = editorRef.current;
4393
+ if (!current || current.isDestroyed || current.view.composing) return;
4394
+ publishEditorValue(current);
4395
+ }, 0);
4396
+ };
4371
4397
  const editor = useEditor({
4372
4398
  extensions,
4373
4399
  content: initialContentRef.current,
@@ -4380,7 +4406,18 @@ function PresentationTextEditor({ autoFocus = false, element, onChange, onEditor
4380
4406
  role: 'textbox',
4381
4407
  spellcheck: 'true'
4382
4408
  },
4409
+ handleDOMEvents: {
4410
+ compositionstart: ()=>{
4411
+ cancelCompositionPublication();
4412
+ return false;
4413
+ },
4414
+ compositionend: ()=>{
4415
+ publishCommittedComposition();
4416
+ return false;
4417
+ }
4418
+ },
4383
4419
  handleKeyDown: (view, event)=>{
4420
+ if (view.composing || isOfficeCompositionKeyboardEvent(event)) return false;
4384
4421
  if ('Escape' !== event.key || !onExitEditingRef.current) return false;
4385
4422
  const object = view.dom.closest('[data-slide-element-origin]');
4386
4423
  event.preventDefault();
@@ -4390,18 +4427,17 @@ function PresentationTextEditor({ autoFocus = false, element, onChange, onEditor
4390
4427
  }
4391
4428
  },
4392
4429
  onCreate: ({ editor: current })=>{
4430
+ editorRef.current = current;
4393
4431
  applyPresentationTextStoredMarks(current, elementRef.current);
4394
4432
  },
4433
+ onDestroy: ()=>{
4434
+ editorRef.current = null;
4435
+ cancelCompositionPublication();
4436
+ },
4395
4437
  onSelectionUpdate: ()=>onSelectionChangeRef.current?.(),
4396
4438
  onUpdate: ({ editor: current })=>{
4397
- const value = presentationTextValue(current, elementRef.current);
4398
- const signature = presentationTextElementSignature({
4399
- ...elementRef.current,
4400
- ...value
4401
- });
4402
- if (signature === appliedSignatureRef.current) return;
4403
- appliedSignatureRef.current = signature;
4404
- onChangeRef.current(value);
4439
+ if (current.view.composing) return;
4440
+ publishEditorValue(current);
4405
4441
  }
4406
4442
  });
4407
4443
  useEffect(()=>{