@a3s-lab/office 0.37.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 (53) hide show
  1. package/README.md +6 -1
  2. package/dist/0~3557.js +2 -1
  3. package/dist/0~3635.js +4 -1
  4. package/dist/0~9073.js +7 -2
  5. package/dist/0~presentation-editor.js +45 -9
  6. package/dist/0~spreadsheet-editor.js +13345 -10343
  7. package/dist/{3266.js → 5416.js} +1139 -15
  8. package/dist/9333.js +1 -1
  9. package/dist/core.d.ts +1 -0
  10. package/dist/core.js +112 -26
  11. package/dist/index.js +1 -1
  12. package/dist/internal/features/work/editors/office-shortcuts.d.ts +1 -0
  13. package/dist/internal/features/work/editors/spreadsheet-auto-filter-command.d.ts +3 -0
  14. package/dist/internal/features/work/editors/spreadsheet-auto-filter-condition-dialog-model.d.ts +27 -0
  15. package/dist/internal/features/work/editors/spreadsheet-auto-filter-condition-dialog.d.ts +17 -0
  16. package/dist/internal/features/work/editors/spreadsheet-auto-filter-menu.d.ts +10 -0
  17. package/dist/internal/features/work/editors/spreadsheet-auto-filter.d.ts +16 -4
  18. package/dist/internal/features/work/editors/spreadsheet-cell-range.d.ts +1 -0
  19. package/dist/internal/features/work/editors/spreadsheet-command-catalog.d.ts +9 -0
  20. package/dist/internal/features/work/editors/spreadsheet-command-controller.d.ts +13 -1
  21. package/dist/internal/features/work/editors/spreadsheet-current-region.d.ts +12 -0
  22. package/dist/internal/features/work/editors/spreadsheet-editor.d.ts +3 -0
  23. package/dist/internal/features/work/editors/spreadsheet-sort-appearance.d.ts +45 -0
  24. package/dist/internal/features/work/editors/spreadsheet-sort-collation.d.ts +8 -0
  25. package/dist/internal/features/work/editors/spreadsheet-sort-command.d.ts +3 -0
  26. package/dist/internal/features/work/editors/spreadsheet-sort-custom-list-editor.d.ts +8 -0
  27. package/dist/internal/features/work/editors/spreadsheet-sort-custom-list-store.d.ts +13 -0
  28. package/dist/internal/features/work/editors/spreadsheet-sort-custom-list.d.ts +26 -0
  29. package/dist/internal/features/work/editors/spreadsheet-sort-dialog.d.ts +9 -0
  30. package/dist/internal/features/work/editors/spreadsheet-sort-matrix.d.ts +4 -0
  31. package/dist/internal/features/work/editors/spreadsheet-sort-options-dialog.d.ts +7 -0
  32. package/dist/internal/features/work/editors/spreadsheet-sort-order-controls.d.ts +16 -0
  33. package/dist/internal/features/work/editors/spreadsheet-sort-range-dialog.d.ts +7 -0
  34. package/dist/internal/features/work/editors/spreadsheet-sort.d.ts +138 -0
  35. package/dist/internal/features/work/editors/use-spreadsheet-auto-filter.d.ts +12 -3
  36. package/dist/internal/features/work/editors/use-spreadsheet-sort.d.ts +26 -0
  37. package/dist/internal/features/work/editors/work-office-chrome.d.ts +3 -0
  38. package/dist/internal/features/work/work-spreadsheet-auto-filter.d.ts +14 -0
  39. package/dist/internal/features/work/work-spreadsheet-dynamic-filter.d.ts +7 -0
  40. package/dist/internal/features/work/work-spreadsheet-filter-contract.d.ts +3 -0
  41. package/dist/internal/features/work/work-spreadsheet-wildcard.d.ts +7 -0
  42. package/dist/internal/features/work/work-types.d.ts +31 -7
  43. package/dist/internal/features/work/work-xlsx-interop.d.ts +2 -1
  44. package/dist/internal/features/work/work-xlsx-table-filters.d.ts +3 -1
  45. package/dist/office-kernel.wasm +0 -0
  46. package/dist/styles.css +544 -20
  47. package/dist/vue.d.ts +3 -1
  48. package/dist/vue.js +2 -0
  49. package/dist/web-component.d.ts +3 -1
  50. package/dist/web-component.js +9 -0
  51. package/dist/work-spreadsheet-package-scan.worker.js +2 -1
  52. package/docs/latest/en/browser-editor-architecture.md +128 -0
  53. package/package.json +21 -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.37.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 |
@@ -152,6 +152,7 @@ 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
+ | 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 |
155
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 |
@@ -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.
@@ -1647,6 +1651,7 @@ keep working without hard-coded return URLs.
1647
1651
 
1648
1652
  - [Live Playground](https://a3s-lab.github.io/Office/playground/)
1649
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/)
1650
1655
  - [A3S Office 0.37.0 documentation](https://a3s-lab.github.io/Office/docs/0.37.0/)
1651
1656
  - [A3S Office 0.36.0 documentation](https://a3s-lab.github.io/Office/docs/0.36.0/)
1652
1657
  - [A3S Office 0.34.0 documentation](https://a3s-lab.github.io/Office/docs/0.34.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~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(()=>{