@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/README.md +282 -1549
- package/dist/0~9073.js +2 -2
- package/dist/0~controlled-editor-composition.js +54 -0
- package/dist/0~document-editor.js +60 -10
- package/dist/0~markdown-editor.js +62 -21
- package/dist/0~presentation-editor.js +57 -31
- package/dist/0~spreadsheet-editor.js +68 -18
- package/dist/internal/features/work/editors/controlled-editor-composition.d.ts +20 -0
- package/dist/internal/features/work/editors/spreadsheet-editor-support.d.ts +1 -0
- package/dist/internal/features/work/editors/spreadsheet-editor.d.ts +2 -1
- package/dist/internal/features/work/editors/use-document-review-conflicts.d.ts +3 -1
- package/dist/office-kernel.wasm +0 -0
- package/docs/latest/en/browser-editor-architecture.md +16 -0
- package/package.json +2 -1
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
1939
|
-
|
|
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
|
|
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
|
-
|
|
4401
|
+
composition.start();
|
|
4412
4402
|
return false;
|
|
4413
4403
|
},
|
|
4414
4404
|
compositionend: ()=>{
|
|
4415
|
-
|
|
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
|
-
|
|
4429
|
+
composition.destroy();
|
|
4436
4430
|
},
|
|
4437
4431
|
onSelectionUpdate: ()=>onSelectionChangeRef.current?.(),
|
|
4438
4432
|
onUpdate: ({ editor: current })=>{
|
|
4439
|
-
if (current
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
5000
|
-
|
|
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)=>
|
|
5216
|
-
|
|
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
|
|
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
|
-
|
|
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?.
|
|
5352
|
-
|
|
5377
|
+
selectedElement?.id,
|
|
5378
|
+
selectedFontSize
|
|
5353
5379
|
]);
|
|
5354
5380
|
const commitFontSize = (value)=>{
|
|
5355
5381
|
if (!selectedElement) return;
|