@a3s-lab/office 0.37.1 → 0.37.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.
package/dist/0~9073.js CHANGED
@@ -155,8 +155,8 @@ function WorkspaceContextMenu({ label, className = '', x, y, items, onClose, onR
155
155
  if (shortcutItem) {
156
156
  event.preventDefault();
157
157
  event.stopPropagation();
158
- dismissAndRestoreFocus();
159
158
  shortcutItem.onSelect();
159
+ dismissAndRestoreFocus();
160
160
  } else if ('Escape' === event.key) {
161
161
  event.preventDefault();
162
162
  event.stopPropagation();
@@ -193,9 +193,9 @@ function WorkspaceContextMenu({ label, className = '', x, y, items, onClose, onR
193
193
  "aria-label": item.label,
194
194
  "aria-keyshortcuts": item.ariaKeyShortcut,
195
195
  onClick: ()=>{
196
+ item.onSelect();
196
197
  onClose();
197
198
  restoreContextFocus();
198
- item.onSelect();
199
199
  },
200
200
  children: [
201
201
  item.icon,
@@ -0,0 +1,54 @@
1
+ const COMPOSITION_SETTLE_RETRY_MS = 20;
2
+ const MAX_COMPOSITION_SETTLE_RETRIES = 4;
3
+ class ControlledEditorComposition {
4
+ active = false;
5
+ generation = 0;
6
+ settling = false;
7
+ timer = null;
8
+ start() {
9
+ this.generation += 1;
10
+ this.cancelTimer();
11
+ this.active = true;
12
+ this.settling = false;
13
+ }
14
+ end(editor, onSettled) {
15
+ const generation = ++this.generation;
16
+ this.cancelTimer();
17
+ this.active = false;
18
+ this.settling = true;
19
+ this.scheduleSettlement(editor, onSettled, generation, 0);
20
+ }
21
+ isBlocking(editor) {
22
+ return this.active || this.settling || Boolean(editor && !editor.isDestroyed && editor.view.composing);
23
+ }
24
+ destroy() {
25
+ this.generation += 1;
26
+ this.cancelTimer();
27
+ this.active = false;
28
+ this.settling = false;
29
+ }
30
+ scheduleSettlement(editor, onSettled, generation, retry) {
31
+ const delay = 0 === retry ? 0 : COMPOSITION_SETTLE_RETRY_MS;
32
+ this.timer = setTimeout(()=>{
33
+ this.timer = null;
34
+ if (generation !== this.generation) return;
35
+ if (editor.isDestroyed) {
36
+ this.settling = false;
37
+ return;
38
+ }
39
+ if (editor.view.composing) {
40
+ if (retry < MAX_COMPOSITION_SETTLE_RETRIES) this.scheduleSettlement(editor, onSettled, generation, retry + 1);
41
+ else this.settling = false;
42
+ return;
43
+ }
44
+ this.settling = false;
45
+ onSettled(editor);
46
+ }, delay);
47
+ }
48
+ cancelTimer() {
49
+ if (null === this.timer) return;
50
+ clearTimeout(this.timer);
51
+ this.timer = null;
52
+ }
53
+ }
54
+ export { ControlledEditorComposition };
@@ -28,6 +28,7 @@ import { mergeOfficeTiptapExtensions, documentHasRefreshableFields, documentCurr
28
28
  import { WorkEditorLoadingState, documentLayoutFontKey, useOfficeCollaborationLocationNavigator, OFFICE_DOCUMENT_LAYOUT_HEBREW_FONT_ID, useOfficeEditorInitialFocus, OFFICE_DOCUMENT_LAYOUT_FONT_ID, OFFICE_DOCUMENT_LAYOUT_ARABIC_FONT_ID, OFFICE_DOCUMENT_LAYOUT_LATIN_FONT_ID } from "./432.js";
29
29
  import { useOfficeDraft, InlineNotice } from "./0~345.js";
30
30
  import { showToast } from "./6489.js";
31
+ import { ControlledEditorComposition } from "./0~controlled-editor-composition.js";
31
32
  import { documentPageColor, normalizeDocumentPageColor } from "./0~work-document-page-color.js";
32
33
  var document_editor_namespaceObject = {};
33
34
  __webpack_require__.r(document_editor_namespaceObject);
@@ -19336,13 +19337,13 @@ function work_document_review_conflicts_changeKey(change) {
19336
19337
  function documentReviewConflictKey(conflict) {
19337
19338
  return 'comment' === conflict.kind ? `comment:${conflict.id}` : `change:${conflict.id}`;
19338
19339
  }
19339
- function useDocumentReviewConflicts({ activeConflictsRef, appliedSourceKeyRef, artifactId, content, editor, editorInput, normalizedContent, onReviewConflict, publishedDocumentRef, reconcileControlledUpdates = true }) {
19340
+ function useDocumentReviewConflicts({ activeConflictsRef, appliedSourceKeyRef, artifactId, content, controlledUpdateRevision = 0, deferControlledUpdates = false, editor, editorInput, normalizedContent, onReviewConflict, publishedDocumentRef, reconcileControlledUpdates = true }) {
19340
19341
  const appliedArtifactIdRef = useRef(artifactId);
19341
19342
  const onReviewConflictRef = useRef(onReviewConflict);
19342
19343
  const [visibleConflicts, setVisibleConflicts] = useState([]);
19343
19344
  onReviewConflictRef.current = onReviewConflict;
19344
19345
  useEffect(()=>{
19345
- if (!editor || !reconcileControlledUpdates) return;
19346
+ if (!editor || !reconcileControlledUpdates || deferControlledUpdates) return;
19346
19347
  const artifactChanged = appliedArtifactIdRef.current !== artifactId;
19347
19348
  const sourceChanged = appliedSourceKeyRef.current !== editorInput.sourceKey;
19348
19349
  appliedArtifactIdRef.current = artifactId;
@@ -19390,6 +19391,8 @@ function useDocumentReviewConflicts({ activeConflictsRef, appliedSourceKeyRef, a
19390
19391
  appliedSourceKeyRef,
19391
19392
  artifactId,
19392
19393
  content,
19394
+ controlledUpdateRevision,
19395
+ deferControlledUpdates,
19393
19396
  editor,
19394
19397
  editorInput,
19395
19398
  normalizedContent,
@@ -19525,6 +19528,11 @@ function DocumentEditorSurface({ artifactId, autoFocus = true, collaboration, co
19525
19528
  const editorBeforeCreateAtRef = useRef(null);
19526
19529
  const editorDetachedMountAtRef = useRef(null);
19527
19530
  const onChangeRef = useRef(onChange);
19531
+ const editorRef = useRef(null);
19532
+ const compositionRef = useRef(null);
19533
+ compositionRef.current ??= new ControlledEditorComposition();
19534
+ const composition = compositionRef.current;
19535
+ const settleCompositionRef = useRef(()=>void 0);
19528
19536
  const trackChangesRef = useRef(suggestionOnly || Boolean(effectiveContent.trackChanges));
19529
19537
  const collaborationBindingRef = useRef(collaborationBinding);
19530
19538
  const validatedModel = useMemo(()=>documentModelForContent(effectiveContent), [
@@ -19563,6 +19571,7 @@ function DocumentEditorSurface({ artifactId, autoFocus = true, collaboration, co
19563
19571
  const [zoom, setZoom] = useState(90);
19564
19572
  const [selectionMenu, setSelectionMenu] = useState(null);
19565
19573
  const [selectionVersion, setSelectionVersion] = useState(0);
19574
+ const [compositionRevision, setCompositionRevision] = useState(0);
19566
19575
  const [statisticsOpen, setStatisticsOpen] = useState(false);
19567
19576
  const loadedLayoutFontIds = useDocumentLayoutFonts(layoutFonts);
19568
19577
  if (!collaboration) contentRef.current = content;
@@ -19632,9 +19641,21 @@ function DocumentEditorSurface({ artifactId, autoFocus = true, collaboration, co
19632
19641
  'aria-readonly': commentOnly ? 'true' : 'false',
19633
19642
  role: 'textbox',
19634
19643
  spellcheck: 'true'
19644
+ },
19645
+ handleDOMEvents: {
19646
+ compositionstart: ()=>{
19647
+ composition.start();
19648
+ return false;
19649
+ },
19650
+ compositionend: ()=>{
19651
+ const current = editorRef.current;
19652
+ if (current) composition.end(current, (settled)=>settleCompositionRef.current(settled));
19653
+ return false;
19654
+ }
19635
19655
  }
19636
19656
  }), [
19637
- commentOnly
19657
+ commentOnly,
19658
+ composition
19638
19659
  ]);
19639
19660
  const publishDocumentUpdate = useCallback((current, previousDocument)=>{
19640
19661
  if (current.isDestroyed || previousDocument.eq(current.state.doc)) return;
@@ -19680,8 +19701,9 @@ function DocumentEditorSurface({ artifactId, autoFocus = true, collaboration, co
19680
19701
  }
19681
19702
  const flush = ()=>{
19682
19703
  const queued = pendingLazyPublicationRef.current;
19704
+ if (!queued || composition.isBlocking(queued.editor)) return;
19683
19705
  pendingLazyPublicationRef.current = null;
19684
- if (queued) publishDocumentUpdate(queued.editor, queued.before);
19706
+ publishDocumentUpdate(queued.editor, queued.before);
19685
19707
  };
19686
19708
  pendingLazyPublicationRef.current = {
19687
19709
  before: previousDocument,
@@ -19689,15 +19711,39 @@ function DocumentEditorSurface({ artifactId, autoFocus = true, collaboration, co
19689
19711
  editor: current
19690
19712
  };
19691
19713
  }, [
19714
+ composition,
19692
19715
  publishDocumentUpdate
19693
19716
  ]);
19717
+ const publishDocumentSnapshot = useCallback((current, previousDocument, immediate = false)=>{
19718
+ if (previousDocument.eq(current.state.doc)) return;
19719
+ const lazyProjection = documentLazyHtmlProjection(contentRef.current.model);
19720
+ if (lazyProjection) transferLazyDocumentTextStatistics(previousDocument, current.state.doc);
19721
+ publishedDocumentRef.current = current.state.doc;
19722
+ if (lazyProjection && !immediate) queueLazyDocumentPublication(current, previousDocument);
19723
+ else publishDocumentUpdate(current, previousDocument);
19724
+ }, [
19725
+ publishDocumentUpdate,
19726
+ queueLazyDocumentPublication
19727
+ ]);
19728
+ settleCompositionRef.current = (current)=>{
19729
+ const pending = pendingLazyPublicationRef.current;
19730
+ if (pending) {
19731
+ pending.cancel();
19732
+ pendingLazyPublicationRef.current = null;
19733
+ }
19734
+ const previousDocument = pending?.before ?? publishedDocumentRef.current;
19735
+ if (previousDocument) publishDocumentSnapshot(current, previousDocument, true);
19736
+ else publishedDocumentRef.current = current.state.doc;
19737
+ setCompositionRevision((value)=>value + 1);
19738
+ };
19694
19739
  useEffect(()=>()=>{
19695
19740
  const pending = pendingLazyPublicationRef.current;
19696
19741
  pendingLazyPublicationRef.current = null;
19697
19742
  if (!pending) return;
19698
19743
  pending.cancel();
19699
- publishDocumentUpdate(pending.editor, pending.before);
19744
+ if (!composition.isBlocking(pending.editor)) publishDocumentUpdate(pending.editor, pending.before);
19700
19745
  }, [
19746
+ composition,
19701
19747
  publishDocumentUpdate
19702
19748
  ]);
19703
19749
  const editor = useEditor({
@@ -19718,6 +19764,7 @@ function DocumentEditorSurface({ artifactId, autoFocus = true, collaboration, co
19718
19764
  if (null !== beforeCreateAt) recordDocumentEditorMeasure('a3s-office.document.editor-state-view', beforeCreateAt, mountedAt);
19719
19765
  },
19720
19766
  onCreate: ({ editor: current })=>{
19767
+ editorRef.current = current;
19721
19768
  publishedDocumentRef.current = current.state.doc;
19722
19769
  const mountedAt = documentEditorNow();
19723
19770
  const detachedMountAt = editorDetachedMountAtRef.current;
@@ -19728,6 +19775,10 @@ function DocumentEditorSurface({ artifactId, autoFocus = true, collaboration, co
19728
19775
  windowed: Boolean(editorInput.model && documentModelUsesWindowing(editorInput.model.root))
19729
19776
  });
19730
19777
  },
19778
+ onDestroy: ()=>{
19779
+ editorRef.current = null;
19780
+ composition.destroy();
19781
+ },
19731
19782
  onTransaction: ({ appendedTransactions, editor: current, transaction })=>{
19732
19783
  if (documentTransactionsOnlyHydrateChunks([
19733
19784
  transaction,
@@ -19735,6 +19786,7 @@ function DocumentEditorSurface({ artifactId, autoFocus = true, collaboration, co
19735
19786
  ])) publishedDocumentRef.current = current.state.doc;
19736
19787
  },
19737
19788
  onUpdate: ({ appendedTransactions, editor: current, transaction })=>{
19789
+ if (composition.isBlocking(current)) return;
19738
19790
  if (!shouldPublishDocumentUpdate(transaction, appendedTransactions ?? [])) {
19739
19791
  publishedDocumentRef.current = current.state.doc;
19740
19792
  return;
@@ -19745,11 +19797,7 @@ function DocumentEditorSurface({ artifactId, autoFocus = true, collaboration, co
19745
19797
  }
19746
19798
  const previousDocument = publishedDocumentRef.current;
19747
19799
  if (previousDocument.eq(current.state.doc)) return;
19748
- const lazyProjection = documentLazyHtmlProjection(contentRef.current.model);
19749
- if (lazyProjection) transferLazyDocumentTextStatistics(previousDocument, current.state.doc);
19750
- publishedDocumentRef.current = current.state.doc;
19751
- if (lazyProjection) queueLazyDocumentPublication(current, previousDocument);
19752
- else publishDocumentUpdate(current, previousDocument);
19800
+ publishDocumentSnapshot(current, previousDocument);
19753
19801
  },
19754
19802
  onSelectionUpdate: ()=>setSelectionVersion((value)=>value + 1)
19755
19803
  });
@@ -19786,6 +19834,8 @@ function DocumentEditorSurface({ artifactId, autoFocus = true, collaboration, co
19786
19834
  appliedSourceKeyRef,
19787
19835
  artifactId,
19788
19836
  content: collaboration ? contentRef.current : content,
19837
+ controlledUpdateRevision: compositionRevision,
19838
+ deferControlledUpdates: composition.isBlocking(editor),
19789
19839
  editor,
19790
19840
  editorInput,
19791
19841
  normalizedContent,
@@ -15,6 +15,7 @@ import { OfficeSelect, isWorkspaceContextMenuKeyboardEvent, WorkOfficeZoomContro
15
15
  import { stepOfficeZoom, MarkdownSourcePresenceLayer, button_Button, OfficeTiptapPresenceLayer, useOfficePublishPresenceLocation, Dialog, office_text_field_OfficeTextField, useOfficeEditorWheelZoom } from "./0~8136.js";
16
16
  import { normalizeDocumentHref, DOCUMENT_LINK_VALIDATION_MESSAGE } from "./0~work-document-links.js";
17
17
  import { readOfficeMarkdownCollaboration as readWorkOfficeMarkdownCollaboration, createOfficeMarkdownCollaborationBinding as createWorkOfficeMarkdownCollaborationBinding } from "./2591.js";
18
+ import { ControlledEditorComposition } from "./0~controlled-editor-composition.js";
18
19
  import { useOfficeEditorInitialFocus, useOfficeCollaborationLocationNavigator, WorkEditorLoadingState } from "./432.js";
19
20
  var markdown_editor_namespaceObject = {};
20
21
  __webpack_require__.r(markdown_editor_namespaceObject);
@@ -1867,6 +1868,11 @@ function MarkdownEditor({ autoFocus = true, collaboration, content, extensions:
1867
1868
  const initialContent = collaboration ? readWorkOfficeMarkdownCollaboration(collaboration) : content;
1868
1869
  const contentRef = useRef(initialContent);
1869
1870
  const onChangeRef = useRef(onChange);
1871
+ const editorRef = useRef(null);
1872
+ const compositionRef = useRef(null);
1873
+ compositionRef.current ??= new ControlledEditorComposition();
1874
+ const composition = compositionRef.current;
1875
+ const publishVisualMarkdownRef = useRef(()=>void 0);
1870
1876
  const receivedContentRef = useRef(content);
1871
1877
  const appliedMarkdownRef = useRef(initialContent.markdown);
1872
1878
  const emittedMarkdownRef = useRef(null);
@@ -1881,6 +1887,7 @@ function MarkdownEditor({ autoFocus = true, collaboration, content, extensions:
1881
1887
  const [viewMode, setViewMode] = useState('split');
1882
1888
  const [zoom, setZoom] = useState(100);
1883
1889
  const [selectionVersion, setSelectionVersion] = useState(0);
1890
+ const [compositionRevision, setCompositionRevision] = useState(0);
1884
1891
  const [presenceSurface, setPresenceSurface] = useState(preview ? 'visual' : 'source');
1885
1892
  const [sourcePresenceSelection, setSourcePresenceSelection] = useState({
1886
1893
  start: 0,
@@ -1910,6 +1917,20 @@ function MarkdownEditor({ autoFocus = true, collaboration, content, extensions:
1910
1917
  role: 'textbox',
1911
1918
  spellcheck: 'true'
1912
1919
  },
1920
+ handleDOMEvents: {
1921
+ compositionstart: ()=>{
1922
+ composition.start();
1923
+ return false;
1924
+ },
1925
+ compositionend: ()=>{
1926
+ const current = editorRef.current;
1927
+ if (current) composition.end(current, (settled)=>{
1928
+ publishVisualMarkdownRef.current(settled);
1929
+ setCompositionRevision((value)=>value + 1);
1930
+ });
1931
+ return false;
1932
+ }
1933
+ },
1913
1934
  handleKeyDown: (_view, event)=>{
1914
1935
  if (!collaborative || readOnly || event.altKey || !(event.metaKey || event.ctrlKey)) return false;
1915
1936
  const key = event.key.toLocaleLowerCase();
@@ -1926,34 +1947,51 @@ function MarkdownEditor({ autoFocus = true, collaboration, content, extensions:
1926
1947
  }
1927
1948
  }), [
1928
1949
  collaborative,
1950
+ composition,
1929
1951
  readOnly
1930
1952
  ]);
1953
+ const publishVisualMarkdown = useCallback((current)=>{
1954
+ const markdown = current.getMarkdown();
1955
+ if (markdown === appliedMarkdownRef.current) return;
1956
+ cancelPreviewSync();
1957
+ if (collaborative) {
1958
+ appliedMarkdownRef.current = markdown;
1959
+ collaborationBindingRef.current?.replace(markdown);
1960
+ return;
1961
+ }
1962
+ const next = {
1963
+ ...contentRef.current,
1964
+ markdown
1965
+ };
1966
+ appliedMarkdownRef.current = markdown;
1967
+ emittedMarkdownRef.current = markdown;
1968
+ sourceMarkdownRef.current = markdown;
1969
+ contentRef.current = next;
1970
+ setSourceMarkdown(markdown);
1971
+ resetSourceHistory(markdown, textareaSelection(sourceTextareaRef.current, markdown.length));
1972
+ onChangeRef.current(next);
1973
+ }, [
1974
+ cancelPreviewSync,
1975
+ collaborative,
1976
+ resetSourceHistory
1977
+ ]);
1978
+ publishVisualMarkdownRef.current = publishVisualMarkdown;
1931
1979
  const editor = useEditor({
1932
1980
  extensions,
1933
1981
  content: initialMarkdownRef.current,
1934
1982
  contentType: 'markdown',
1935
1983
  editable: !readOnly && 'visual' === viewMode,
1936
1984
  editorProps,
1985
+ onCreate: ({ editor: current })=>{
1986
+ editorRef.current = current;
1987
+ },
1988
+ onDestroy: ()=>{
1989
+ editorRef.current = null;
1990
+ composition.destroy();
1991
+ },
1937
1992
  onUpdate: ({ editor: current })=>{
1938
- const markdown = current.getMarkdown();
1939
- if (markdown === appliedMarkdownRef.current) return;
1940
- cancelPreviewSync();
1941
- if (collaborative) {
1942
- appliedMarkdownRef.current = markdown;
1943
- collaborationBindingRef.current?.replace(markdown);
1944
- return;
1945
- }
1946
- const next = {
1947
- ...contentRef.current,
1948
- markdown
1949
- };
1950
- appliedMarkdownRef.current = markdown;
1951
- emittedMarkdownRef.current = markdown;
1952
- sourceMarkdownRef.current = markdown;
1953
- contentRef.current = next;
1954
- setSourceMarkdown(markdown);
1955
- resetSourceHistory(markdown, textareaSelection(sourceTextareaRef.current, markdown.length));
1956
- onChangeRef.current(next);
1993
+ if (composition.isBlocking(current)) return;
1994
+ publishVisualMarkdownRef.current(current);
1957
1995
  },
1958
1996
  onSelectionUpdate: ()=>setSelectionVersion((value)=>value + 1)
1959
1997
  }, [
@@ -1961,13 +1999,14 @@ function MarkdownEditor({ autoFocus = true, collaboration, content, extensions:
1961
1999
  ]);
1962
2000
  const applyMarkdownToEditor = useCallback((markdown)=>{
1963
2001
  cancelPreviewSync();
1964
- if (!editor || editor.isDestroyed || appliedMarkdownRef.current === markdown) return;
2002
+ if (!editor || editor.isDestroyed || composition.isBlocking(editor) || appliedMarkdownRef.current === markdown) return;
1965
2003
  appliedMarkdownRef.current = markdown;
1966
2004
  editor.commands.setWorkMarkdown(markdown, {
1967
2005
  emitUpdate: false
1968
2006
  });
1969
2007
  }, [
1970
2008
  cancelPreviewSync,
2009
+ composition,
1971
2010
  editor
1972
2011
  ]);
1973
2012
  const queueMarkdownPreview = useCallback((markdown, immediate = false)=>{
@@ -2084,7 +2123,7 @@ function MarkdownEditor({ autoFocus = true, collaboration, content, extensions:
2084
2123
  ]);
2085
2124
  useEffect(()=>{
2086
2125
  if (collaborative) return;
2087
- if (!editor || receivedContentRef.current === content) return;
2126
+ if (!editor || composition.isBlocking(editor) || receivedContentRef.current === content) return;
2088
2127
  receivedContentRef.current = content;
2089
2128
  const markdown = content.markdown;
2090
2129
  if (sourceMarkdownRef.current !== markdown) {
@@ -2101,6 +2140,8 @@ function MarkdownEditor({ autoFocus = true, collaboration, content, extensions:
2101
2140
  }, [
2102
2141
  content,
2103
2142
  collaborative,
2143
+ composition,
2144
+ compositionRevision,
2104
2145
  editor,
2105
2146
  readOnly,
2106
2147
  queueMarkdownPreview,
@@ -22,6 +22,7 @@ import { presentationAgentProposalTargets, SpreadsheetChartSeriesStyleEditor, ap
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
24
  import { isOfficeShortcutBlocked, OfficeColorPicker, isOfficeCompositionKeyboardEvent } from "./0~3635.js";
25
+ import { ControlledEditorComposition } from "./0~controlled-editor-composition.js";
25
26
  import { normalizeDocumentHref, DOCUMENT_LINK_VALIDATION_MESSAGE } from "./0~work-document-links.js";
26
27
  import { showToast } from "./6489.js";
27
28
  import { scaledPresentationVisuals } from "./0~work-presentation-visual-scale.js";
@@ -4358,7 +4359,10 @@ function PresentationTextEditor({ autoFocus = false, element, onChange, onEditor
4358
4359
  const onExitEditingRef = useRef(onExitEditing);
4359
4360
  const onSelectionChangeRef = useRef(onSelectionChange);
4360
4361
  const editorRef = useRef(null);
4361
- const compositionPublishTimerRef = useRef(null);
4362
+ const compositionRef = useRef(null);
4363
+ compositionRef.current ??= new ControlledEditorComposition();
4364
+ const composition = compositionRef.current;
4365
+ const [compositionRevision, setCompositionRevision] = useState(0);
4362
4366
  const appliedSignatureRef = useRef(presentationTextElementSignature(element));
4363
4367
  const initialContentRef = useRef(presentationTextElementHtml(element));
4364
4368
  const initialFocusTargetRef = useRef("u" > typeof document && document.activeElement instanceof HTMLElement ? document.activeElement : null);
@@ -4380,20 +4384,6 @@ function PresentationTextEditor({ autoFocus = false, element, onChange, onEditor
4380
4384
  appliedSignatureRef.current = signature;
4381
4385
  onChangeRef.current(value);
4382
4386
  };
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
- };
4397
4387
  const editor = useEditor({
4398
4388
  extensions,
4399
4389
  content: initialContentRef.current,
@@ -4408,11 +4398,15 @@ function PresentationTextEditor({ autoFocus = false, element, onChange, onEditor
4408
4398
  },
4409
4399
  handleDOMEvents: {
4410
4400
  compositionstart: ()=>{
4411
- cancelCompositionPublication();
4401
+ composition.start();
4412
4402
  return false;
4413
4403
  },
4414
4404
  compositionend: ()=>{
4415
- publishCommittedComposition();
4405
+ const current = editorRef.current;
4406
+ if (current) composition.end(current, (settled)=>{
4407
+ publishEditorValue(settled);
4408
+ setCompositionRevision((value)=>value + 1);
4409
+ });
4416
4410
  return false;
4417
4411
  }
4418
4412
  },
@@ -4432,11 +4426,11 @@ function PresentationTextEditor({ autoFocus = false, element, onChange, onEditor
4432
4426
  },
4433
4427
  onDestroy: ()=>{
4434
4428
  editorRef.current = null;
4435
- cancelCompositionPublication();
4429
+ composition.destroy();
4436
4430
  },
4437
4431
  onSelectionUpdate: ()=>onSelectionChangeRef.current?.(),
4438
4432
  onUpdate: ({ editor: current })=>{
4439
- if (current.view.composing) return;
4433
+ if (composition.isBlocking(current)) return;
4440
4434
  publishEditorValue(current);
4441
4435
  }
4442
4436
  });
@@ -4459,7 +4453,7 @@ function PresentationTextEditor({ autoFocus = false, element, onChange, onEditor
4459
4453
  editor
4460
4454
  ]);
4461
4455
  useEffect(()=>{
4462
- if (!editor || editor.isDestroyed) return;
4456
+ if (!editor || editor.isDestroyed || composition.isBlocking(editor)) return;
4463
4457
  const signature = presentationTextElementSignature(element);
4464
4458
  if (signature === appliedSignatureRef.current) return;
4465
4459
  appliedSignatureRef.current = signature;
@@ -4468,6 +4462,8 @@ function PresentationTextEditor({ autoFocus = false, element, onChange, onEditor
4468
4462
  });
4469
4463
  applyPresentationTextStoredMarks(editor, element);
4470
4464
  }, [
4465
+ composition,
4466
+ compositionRevision,
4471
4467
  editor,
4472
4468
  element
4473
4469
  ]);
@@ -4992,12 +4988,22 @@ function PresentationTransitionPanel({ slideId, transition, editable, canApplyTo
4992
4988
  ...patch
4993
4989
  });
4994
4990
  };
4995
- const [advanceAfterDraft, setAdvanceAfterDraft] = useState(()=>presentationAdvanceAfterDraft(transition?.advanceAfterMs));
4991
+ const selectedAdvanceAfterDraft = presentationAdvanceAfterDraft(transition?.advanceAfterMs);
4992
+ const selectedAdvanceAfterDraftRef = useRef({
4993
+ slideId,
4994
+ value: selectedAdvanceAfterDraft
4995
+ });
4996
+ const [advanceAfterDraft, setAdvanceAfterDraft] = useState(selectedAdvanceAfterDraft);
4996
4997
  useEffect(()=>{
4997
- setAdvanceAfterDraft(presentationAdvanceAfterDraft(transition?.advanceAfterMs));
4998
+ const previous = selectedAdvanceAfterDraftRef.current;
4999
+ selectedAdvanceAfterDraftRef.current = {
5000
+ slideId,
5001
+ value: selectedAdvanceAfterDraft
5002
+ };
5003
+ setAdvanceAfterDraft((draft)=>previous.slideId !== slideId || draft === previous.value ? selectedAdvanceAfterDraft : draft);
4998
5004
  }, [
4999
- slideId,
5000
- transition?.advanceAfterMs
5005
+ selectedAdvanceAfterDraft,
5006
+ slideId
5001
5007
  ]);
5002
5008
  const commitAdvanceAfter = (value)=>{
5003
5009
  if (!transition || void 0 === transition.advanceAfterMs) return void setAdvanceAfterDraft('');
@@ -5212,9 +5218,18 @@ function PresentationTransitionPanel({ slideId, transition, editable, canApplyTo
5212
5218
  ariaLabel: "自动换片",
5213
5219
  disabled: !editable || !transition,
5214
5220
  checked: transition?.advanceAfterMs !== void 0,
5215
- onCheckedChange: (checked)=>update({
5216
- advanceAfterMs: checked ? 5000 : void 0
5217
- }),
5221
+ onCheckedChange: (checked)=>{
5222
+ const advanceAfterMs = checked ? 5000 : void 0;
5223
+ const draft = presentationAdvanceAfterDraft(advanceAfterMs);
5224
+ selectedAdvanceAfterDraftRef.current = {
5225
+ slideId,
5226
+ value: draft
5227
+ };
5228
+ setAdvanceAfterDraft(draft);
5229
+ update({
5230
+ advanceAfterMs
5231
+ });
5232
+ },
5218
5233
  children: "自动换片"
5219
5234
  }),
5220
5235
  /*#__PURE__*/ jsxs("div", {
@@ -5342,14 +5357,25 @@ const presentationAlignmentOptions = [
5342
5357
  ];
5343
5358
  function PresentationToolbar({ selectedSlide, selectedElement, selectedUnitCount, can, textFormattingAvailable, commentsOpen, commentCount, designOpen, editingDesign, background, transition, fileActions, viewMode = 'normal', commands }) {
5344
5359
  const officeDialog = useOfficeDialog();
5345
- const [fontSizeDraft, setFontSizeDraft] = useState(()=>selectedElement ? String(selectedElement.fontSize) : '');
5360
+ const selectedFontSize = selectedElement ? String(selectedElement.fontSize) : '';
5361
+ const selectedFontSizeRef = useRef({
5362
+ elementId: selectedElement?.id ?? null,
5363
+ value: selectedFontSize
5364
+ });
5365
+ const [fontSizeDraft, setFontSizeDraft] = useState(selectedFontSize);
5346
5366
  const fontFamilyValue = presentationFontFamilyValue(selectedElement?.fontFamily);
5347
5367
  const selectedAnimation = workSlideAnimationForElement(selectedSlide, selectedElement?.id);
5348
5368
  useEffect(()=>{
5349
- setFontSizeDraft(selectedElement ? String(selectedElement.fontSize) : '');
5369
+ const previous = selectedFontSizeRef.current;
5370
+ const elementId = selectedElement?.id ?? null;
5371
+ selectedFontSizeRef.current = {
5372
+ elementId,
5373
+ value: selectedFontSize
5374
+ };
5375
+ setFontSizeDraft((draft)=>previous.elementId !== elementId || draft === previous.value ? selectedFontSize : draft);
5350
5376
  }, [
5351
- selectedElement?.fontSize,
5352
- selectedElement?.id
5377
+ selectedElement?.id,
5378
+ selectedFontSize
5353
5379
  ]);
5354
5380
  const commitFontSize = (value)=>{
5355
5381
  if (!selectedElement) return;