superdoc 2.28.0-next.6 → 2.28.0-next.8
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/chunks/{create-super-doc-ui-D1eOhAjv.cjs → create-super-doc-ui-B4c55pFy.cjs} +420 -84
- package/dist/chunks/{create-super-doc-ui-B29zw5qD.es.js → create-super-doc-ui-C4Ka5Ph3.es.js} +415 -85
- package/dist/collaboration-upgrade-engine.cjs +1 -1
- package/dist/collaboration-upgrade-engine.es.js +1 -1
- package/dist/document-api/src/content-controls/content-controls.types.d.ts +11 -0
- package/dist/document-api/src/contract/command-catalog.d.ts +1 -1
- package/dist/document-api/src/contract/operation-definitions.d.ts +33 -33
- package/dist/document-api/src/contract/operation-registry.d.ts +4 -0
- package/dist/document-api/src/export/export.d.ts +3 -1
- package/dist/document-api/src/export/export.types.d.ts +8 -0
- package/dist/document-api/src/get-node/get-node.d.ts +10 -4
- package/dist/document-api/src/hyperlinks/hyperlinks.types.d.ts +2 -0
- package/dist/document-api/src/index.d.ts +1 -0
- package/dist/document-api/src/types/track-changes.types.d.ts +10 -2
- package/dist/layout-engine/contracts/src/index.d.ts +2 -0
- package/dist/layout-engine/contracts/src/resolved-layout.d.ts +1 -0
- package/dist/public/ui-react.cjs +1 -1
- package/dist/public/ui-react.es.js +1 -1
- package/dist/public/ui-vue.cjs +1 -1
- package/dist/public/ui-vue.es.js +1 -1
- package/dist/public/ui.cjs +1 -1
- package/dist/public/ui.es.js +1 -1
- package/dist/shared/common/list-marker-utils.d.ts +3 -0
- package/dist/style.css +1 -1
- package/dist/style.layered.css +1 -1
- package/dist/superdoc/src/core/SuperDoc.d.ts +2 -6
- package/dist/superdoc/src/core/config/normalize-ui-config.d.ts +1 -0
- package/dist/superdoc/src/core/editor-runtime/types.d.ts +1 -0
- package/dist/superdoc/src/core/editor-runtime/v2/v2-editor-runtime-adapter.d.ts +2 -2
- package/dist/superdoc/src/core/extensions/types.d.ts +14 -3
- package/dist/superdoc/src/core/helpers/resolve-docx-export.d.ts +6 -0
- package/dist/superdoc/src/core/types/index.d.ts +12 -1
- package/dist/superdoc/src/core/v2-integration/v2-integration.d.ts +0 -8
- package/dist/superdoc/src/internal/toolbar/built-in/color-dropdown-helpers.d.ts +0 -1
- package/dist/superdoc/src/internal/toolbar/built-in/constants.d.ts +0 -2
- package/dist/superdoc/src/public/export-types.d.ts +3 -0
- package/dist/superdoc/src/public/ui/entity-at.d.ts +1 -0
- package/dist/superdoc/src/public/ui/format-painter-helpers.d.ts +0 -13
- package/dist/superdoc/src/public/ui/types.d.ts +16 -2
- package/dist/superdoc/src/public/ui.d.cts +14 -0
- package/dist/superdoc/src/public/ui.d.ts +1 -1
- package/dist/superdoc/src/stores/comments-store.d.ts +3 -57
- package/dist/superdoc/src/stores/superdoc-store.d.ts +9 -171
- package/dist/superdoc.cjs +224 -59
- package/dist/superdoc.es.js +224 -59
- package/dist/word-layout/src/types.d.ts +1 -0
- package/dist-cdn/style.layered.css +1 -1
- package/dist-cdn/superdoc.min.css +1 -1
- package/dist-cdn/superdoc.min.js +42 -42
- package/package.json +2 -2
- package/dist/superdoc/src/helpers/floor.d.ts +0 -1
- package/dist/superdoc/src/index.d.cts +0 -18
- package/dist/superdoc/src/index.d.ts +0 -14
package/dist/chunks/{create-super-doc-ui-B29zw5qD.es.js → create-super-doc-ui-C4Ka5Ph3.es.js}
RENAMED
|
@@ -3691,6 +3691,25 @@ function getCommandDescriptor(id) {
|
|
|
3691
3691
|
}
|
|
3692
3692
|
//#endregion
|
|
3693
3693
|
//#region src/public/ui/entity-at.ts
|
|
3694
|
+
function readDecorationProviders(node) {
|
|
3695
|
+
const encoded = node.getAttribute("data-superdoc-extension-decorations");
|
|
3696
|
+
if (encoded) try {
|
|
3697
|
+
const parsed = JSON.parse(encoded);
|
|
3698
|
+
if (Array.isArray(parsed)) return parsed.filter((id) => typeof id === "string");
|
|
3699
|
+
} catch {
|
|
3700
|
+
return [];
|
|
3701
|
+
}
|
|
3702
|
+
const single = node.getAttribute("data-superdoc-extension-decoration");
|
|
3703
|
+
return single ? [single] : [];
|
|
3704
|
+
}
|
|
3705
|
+
function collectDecorationProvidersFromChain(start, stopAt) {
|
|
3706
|
+
const providers = /* @__PURE__ */ new Set();
|
|
3707
|
+
for (let element = start; element; element = element.parentElement) {
|
|
3708
|
+
for (const provider of readDecorationProviders(element)) providers.add(provider);
|
|
3709
|
+
if (element === stopAt) break;
|
|
3710
|
+
}
|
|
3711
|
+
return [...providers];
|
|
3712
|
+
}
|
|
3694
3713
|
function parseCommaSeparatedIds(value) {
|
|
3695
3714
|
return value.split(",").map((id) => id.trim()).filter(Boolean);
|
|
3696
3715
|
}
|
|
@@ -3762,6 +3781,16 @@ function collectEntityHitsFromChain(start, stopAt) {
|
|
|
3762
3781
|
for (const hit of pendingStory) hit.story = layoutStory;
|
|
3763
3782
|
pendingStory = [];
|
|
3764
3783
|
}
|
|
3784
|
+
for (const decorationProvider of readDecorationProviders(node)) {
|
|
3785
|
+
const key = `decoration:${decorationProvider}`;
|
|
3786
|
+
if (!seen.has(key)) {
|
|
3787
|
+
seen.add(key);
|
|
3788
|
+
hits.push({
|
|
3789
|
+
type: "decoration",
|
|
3790
|
+
id: decorationProvider
|
|
3791
|
+
});
|
|
3792
|
+
}
|
|
3793
|
+
}
|
|
3765
3794
|
const citationId = node.getAttribute("data-citation-id");
|
|
3766
3795
|
if (citationId) {
|
|
3767
3796
|
const key = `citation:${citationId}`;
|
|
@@ -6152,6 +6181,7 @@ function createSuperDocUI(options) {
|
|
|
6152
6181
|
pointerSelecting: false,
|
|
6153
6182
|
keyboardSelecting: false
|
|
6154
6183
|
};
|
|
6184
|
+
const paintedInlineTargets = /* @__PURE__ */ new WeakSet();
|
|
6155
6185
|
let painterCaptureEpoch = 0;
|
|
6156
6186
|
let painterCommandDoc = null;
|
|
6157
6187
|
const painterModeListeners = /* @__PURE__ */ new Set();
|
|
@@ -6248,7 +6278,7 @@ function createSuperDocUI(options) {
|
|
|
6248
6278
|
const readHostSelectionSnapshot = () => {
|
|
6249
6279
|
const handles = safeCall(() => hostMethod(getHost(), "getHandles")?.() ?? null, null);
|
|
6250
6280
|
const editing = isPlainObject(handles) ? handles.editing : void 0;
|
|
6251
|
-
const getSnapshot = hostMethod(isPlainObject(editing) ? editing.selection : void 0, "getSnapshot");
|
|
6281
|
+
const getSnapshot = hostMethod(isPlainObject(editing) ? editing.selection : void 0, "getSnapshot") ?? hostMethod(isPlainObject(handles) ? handles.selection : void 0, "getSnapshot");
|
|
6252
6282
|
if (!getSnapshot) return null;
|
|
6253
6283
|
const snapshot = safeCall(() => getSnapshot(), null);
|
|
6254
6284
|
return snapshot && typeof snapshot === "object" ? snapshot : null;
|
|
@@ -6462,7 +6492,7 @@ function createSuperDocUI(options) {
|
|
|
6462
6492
|
return left.id === right.id && left.paintedEntityId === right.paintedEntityId && storyLocatorSignature(left.story) === storyLocatorSignature(right.story);
|
|
6463
6493
|
};
|
|
6464
6494
|
const hasPendingTrackChangeRevealFocus = (focus) => Array.from(pendingTrackChangeRevealFocuses).some((pendingFocus) => explicitActiveChangesEqual(pendingFocus, focus));
|
|
6465
|
-
const
|
|
6495
|
+
const mirrorReviewFocusToHost = (entityType, next) => {
|
|
6466
6496
|
const readHandles = hostMethod(getHost(), "getHandles");
|
|
6467
6497
|
if (!readHandles) return;
|
|
6468
6498
|
const handles = safeCall(() => readHandles(), null);
|
|
@@ -6473,15 +6503,15 @@ function createSuperDocUI(options) {
|
|
|
6473
6503
|
if (!setActiveReviewTarget) return;
|
|
6474
6504
|
const layout = isPlainObject(handles.layout) ? handles.layout : void 0;
|
|
6475
6505
|
safeCall(() => setActiveReviewTarget({
|
|
6476
|
-
entityType
|
|
6506
|
+
entityType,
|
|
6477
6507
|
entityId: next.id,
|
|
6478
6508
|
...next.paintedEntityId ? { paintedEntityId: next.paintedEntityId } : {},
|
|
6479
6509
|
origin: "panel",
|
|
6480
6510
|
layoutEpoch: typeof layout?.generation === "number" ? layout.generation : 0,
|
|
6481
|
-
story: next.story ?? {
|
|
6511
|
+
...entityType === "trackedChange" ? { story: next.story ?? {
|
|
6482
6512
|
kind: "story",
|
|
6483
6513
|
storyType: "body"
|
|
6484
|
-
}
|
|
6514
|
+
} } : {}
|
|
6485
6515
|
}), null);
|
|
6486
6516
|
return;
|
|
6487
6517
|
}
|
|
@@ -6489,10 +6519,22 @@ function createSuperDocUI(options) {
|
|
|
6489
6519
|
const clearActiveReviewTarget = hostMethod(review, "clearActiveReviewTarget");
|
|
6490
6520
|
if (!getActiveReviewTarget || !clearActiveReviewTarget) return;
|
|
6491
6521
|
const activeTarget = safeCall(() => getActiveReviewTarget(), null);
|
|
6492
|
-
if (isPlainObject(activeTarget) && activeTarget.entityType ===
|
|
6522
|
+
if (isPlainObject(activeTarget) && activeTarget.entityType === entityType) safeCall(() => clearActiveReviewTarget(), void 0);
|
|
6523
|
+
};
|
|
6524
|
+
const mirrorTrackedChangeFocusToHost = (next) => mirrorReviewFocusToHost("trackedChange", next);
|
|
6525
|
+
const readReviewFocus = () => ({
|
|
6526
|
+
change: explicitActiveChange,
|
|
6527
|
+
commentId: explicitActiveCommentId
|
|
6528
|
+
});
|
|
6529
|
+
const restoreReviewFocus = (previous) => {
|
|
6530
|
+
setExplicitActiveChange(previous.change, { invalidateQueuedNavigation: false });
|
|
6531
|
+
explicitActiveCommentId = previous.commentId;
|
|
6532
|
+
if (previous.commentId) mirrorReviewFocusToHost("comment", { id: previous.commentId });
|
|
6533
|
+
else mirrorTrackedChangeFocusToHost(previous.change);
|
|
6493
6534
|
};
|
|
6494
6535
|
const setExplicitActiveChange = (next, options) => {
|
|
6495
6536
|
explicitActiveChange = next;
|
|
6537
|
+
if (next) explicitActiveCommentId = null;
|
|
6496
6538
|
explicitActiveChangeRevision += 1;
|
|
6497
6539
|
trackChangeRevealInvalidation += 1;
|
|
6498
6540
|
if (options?.invalidateQueuedNavigation !== false) queuedTrackChangeNavigationInvalidation += 1;
|
|
@@ -7552,15 +7594,53 @@ function createSuperDocUI(options) {
|
|
|
7552
7594
|
* Explicit whole-table changes have a complete local source range and also
|
|
7553
7595
|
* seed clears, so a delayed worker read cannot retain a cleared table target.
|
|
7554
7596
|
*/
|
|
7555
|
-
|
|
7597
|
+
function captureWholeTableParagraphSeed(host, seed, nativeSelection) {
|
|
7598
|
+
const editor = getEditor();
|
|
7599
|
+
const rawLifetime = safeCall(() => hostMethod(host, "getForegroundInteractionLifetime")?.() ?? null, null);
|
|
7600
|
+
const lifetime = hasAbortedFlag(rawLifetime) ? rawLifetime : null;
|
|
7601
|
+
const mount = safeCall(() => hostMethod(host, "getMountedHandle")?.() ?? null, null);
|
|
7602
|
+
const mode = readDocumentMode();
|
|
7603
|
+
if (!host || !editor || !mount || !lifetime || lifetime.aborted || mode === null || seed.empty || seed.tableSelection?.kind !== "tableCells" || seed.tableSelection.type !== "table" || seed.target?.kind !== "text" || !seed.target.segments.length) return false;
|
|
7604
|
+
if (nativeSelection) {
|
|
7605
|
+
const presentation = safeCall(() => hostMethod(host, "readAppliedSelectionPresentation")?.(), null);
|
|
7606
|
+
const applied = normalizeSelectionInfo(isPlainObject(presentation) ? presentation.selection : null);
|
|
7607
|
+
if (readHostSelectionSnapshot() !== nativeSelection || !isNonCollapsedHostSelection(nativeSelection) || !applied || selectionSignature(selectionSliceFromInfo(applied, "ready")) !== selectionSignature(selectionSliceFromInfo(seed, "ready")) || JSON.stringify(applied.tableSelection) !== JSON.stringify(seed.tableSelection)) return false;
|
|
7608
|
+
const snapshot = nativeSelection;
|
|
7609
|
+
const first = seed.target.segments[0]?.blockId, last = seed.target.segments.at(-1)?.blockId;
|
|
7610
|
+
const matches = (point, blockId) => !!blockId && isPlainObject(point) && point.blockId === blockId && storyLocatorSignature(point.story ?? snapshot.story) === storyLocatorSignature(seed.target?.story);
|
|
7611
|
+
if (!(matches(snapshot.anchor, first) && matches(snapshot.focus, last) || matches(snapshot.focus, first) && matches(snapshot.anchor, last))) return false;
|
|
7612
|
+
}
|
|
7613
|
+
wholeTableParagraphSeed = {
|
|
7614
|
+
editor,
|
|
7615
|
+
host,
|
|
7616
|
+
doc: editor.doc,
|
|
7617
|
+
mount,
|
|
7618
|
+
lifetime,
|
|
7619
|
+
sourceToken: contentToken(),
|
|
7620
|
+
mode,
|
|
7621
|
+
info: seed,
|
|
7622
|
+
nativeSelection
|
|
7623
|
+
};
|
|
7624
|
+
return true;
|
|
7625
|
+
}
|
|
7626
|
+
const refreshSelectionFromHost = (hostSelectionSnapshot, afterTypingPaint = false, wholeTableSelectionChanged = false, initialTableSelection = null) => {
|
|
7627
|
+
const host = getHost();
|
|
7556
7628
|
const foreground = foregroundMutationState();
|
|
7629
|
+
if (isNonCollapsedHostSelection(hostSelectionSnapshot) && readHostSelectionSnapshot() === hostSelectionSnapshot) {
|
|
7630
|
+
const seed = normalizeSelectionInfo(safeCall(() => hostMethod(host, "readLiveSelectionSyncSnapshot")?.(), null));
|
|
7631
|
+
if (seed && !seed.selectionTarget && captureWholeTableParagraphSeed(host, seed, hostSelectionSnapshot)) asyncReads.set("selection", {
|
|
7632
|
+
token: asyncReads.get("selection")?.token ?? null,
|
|
7633
|
+
value: seed,
|
|
7634
|
+
hasSettled: true,
|
|
7635
|
+
inflightToken: null
|
|
7636
|
+
});
|
|
7637
|
+
}
|
|
7557
7638
|
if (isNonCollapsedHostSelection(hostSelectionSnapshot) && !(foreground && foreground.active > 0)) {
|
|
7558
7639
|
typedCaretValidationHeld = false;
|
|
7559
7640
|
pendingSelectionSeedValidationToken = null;
|
|
7560
7641
|
issueAsyncRead("selection", selectionReadToken(), selectionCurrentRun, normalizeSelectionInfo);
|
|
7561
7642
|
return;
|
|
7562
7643
|
}
|
|
7563
|
-
const host = getHost();
|
|
7564
7644
|
const read = host?.readLiveSelectionSyncSnapshot;
|
|
7565
7645
|
if (typeof read !== "function") return;
|
|
7566
7646
|
const seed = normalizeSelectionInfo(safeCall(() => read.call(host), null));
|
|
@@ -7569,21 +7649,7 @@ function createSuperDocUI(options) {
|
|
|
7569
7649
|
typedCaretValidationHeld = false;
|
|
7570
7650
|
pendingSelectionSeedValidationToken = null;
|
|
7571
7651
|
wholeTableParagraphSeed = null;
|
|
7572
|
-
|
|
7573
|
-
const rawLifetime = safeCall(() => hostMethod(host, "getForegroundInteractionLifetime")?.() ?? null, null);
|
|
7574
|
-
const lifetime = hasAbortedFlag(rawLifetime) ? rawLifetime : null;
|
|
7575
|
-
const mount = safeCall(() => hostMethod(host, "getMountedHandle")?.() ?? null, null);
|
|
7576
|
-
const mode = readDocumentMode();
|
|
7577
|
-
if (host && editor && mount && lifetime && !lifetime.aborted && mode !== null && !seed.empty && seed.tableSelection?.kind === "tableCells" && seed.tableSelection.type === "table" && seed.target?.segments.length && seed.selectionTarget) wholeTableParagraphSeed = {
|
|
7578
|
-
editor,
|
|
7579
|
-
host,
|
|
7580
|
-
doc: editor.doc,
|
|
7581
|
-
mount,
|
|
7582
|
-
lifetime,
|
|
7583
|
-
sourceToken: contentToken(),
|
|
7584
|
-
mode,
|
|
7585
|
-
info: seed
|
|
7586
|
-
};
|
|
7652
|
+
captureWholeTableParagraphSeed(host, seed, initialTableSelection);
|
|
7587
7653
|
const token = selectionReadToken();
|
|
7588
7654
|
asyncReads.set("selection", {
|
|
7589
7655
|
token,
|
|
@@ -7741,7 +7807,7 @@ function createSuperDocUI(options) {
|
|
|
7741
7807
|
const directory = asyncReads.get("comments");
|
|
7742
7808
|
const directoryItems = directory?.token === contentToken() && directory.hasSettled && Array.isArray(directory.value) ? directory.value : null;
|
|
7743
7809
|
const activeValidationItems = directoryLeaseCounts.comments > 0 ? directoryItems : items;
|
|
7744
|
-
if (explicitActiveCommentId && activeValidationItems &&
|
|
7810
|
+
if (explicitActiveCommentId && activeValidationItems && (activeValidationItems !== items || listStatus === "ready")) explicitActiveCommentId = resolveActiveCommentId(activeValidationItems, explicitActiveCommentId);
|
|
7745
7811
|
const activeId = explicitActiveCommentId ?? activeIds[0] ?? null;
|
|
7746
7812
|
return {
|
|
7747
7813
|
status: combineStatus(listStatus, selection.status),
|
|
@@ -8386,12 +8452,13 @@ function createSuperDocUI(options) {
|
|
|
8386
8452
|
];
|
|
8387
8453
|
function effectiveInlineUniformityInput(selection) {
|
|
8388
8454
|
const cellTarget = currentCellSelectionTarget();
|
|
8389
|
-
const
|
|
8455
|
+
const paintedTarget = cellTarget ? null : currentUnrepresentableSelectionTarget(selection);
|
|
8456
|
+
const target = cellTarget ?? paintedTarget ?? selection.selectionTarget;
|
|
8390
8457
|
if (!target) return null;
|
|
8391
8458
|
const tableCellSelection = cellTarget ? tableCellSelectionForTarget(cellTarget) : null;
|
|
8392
8459
|
return {
|
|
8393
8460
|
target,
|
|
8394
|
-
offsetSpace: "selection",
|
|
8461
|
+
offsetSpace: cellTarget || paintedTarget ? "selection" : "kernel",
|
|
8395
8462
|
...tableCellSelection ? { tableCellSelection } : {}
|
|
8396
8463
|
};
|
|
8397
8464
|
}
|
|
@@ -8529,7 +8596,11 @@ function createSuperDocUI(options) {
|
|
|
8529
8596
|
const getNodeById = hostMethod(doc, "getNodeById");
|
|
8530
8597
|
const raw = await Promise.resolve(getNode ? getNode(address) : getNodeById?.({
|
|
8531
8598
|
nodeId: address["nodeId"],
|
|
8532
|
-
nodeType: address["nodeType"]
|
|
8599
|
+
nodeType: address["nodeType"],
|
|
8600
|
+
story: address["story"] ?? {
|
|
8601
|
+
kind: "story",
|
|
8602
|
+
storyType: "body"
|
|
8603
|
+
}
|
|
8533
8604
|
}));
|
|
8534
8605
|
return isPlainObject(raw) ? raw : void 0;
|
|
8535
8606
|
};
|
|
@@ -9075,7 +9146,8 @@ function createSuperDocUI(options) {
|
|
|
9075
9146
|
const token = contentToken();
|
|
9076
9147
|
const read = readAsync(key, token, () => isBodyStory ? doc.getNodeById({
|
|
9077
9148
|
nodeId: blockId,
|
|
9078
|
-
nodeType: "paragraph"
|
|
9149
|
+
nodeType: "paragraph",
|
|
9150
|
+
story
|
|
9079
9151
|
}) : doc.getNode(paragraphTarget(blockId, story)), (raw) => raw && typeof raw === "object" ? raw : null);
|
|
9080
9152
|
const entry = asyncReads.get(key);
|
|
9081
9153
|
return {
|
|
@@ -9284,7 +9356,11 @@ function createSuperDocUI(options) {
|
|
|
9284
9356
|
const isBodyStory = !story || story.storyType === "body";
|
|
9285
9357
|
const raw = story && typeof doc.getNode === "function" ? await doc.getNode(paragraphTarget(blockId, story)) : isBodyStory && typeof doc.getNodeById === "function" ? await doc.getNodeById({
|
|
9286
9358
|
nodeId: blockId,
|
|
9287
|
-
nodeType: "paragraph"
|
|
9359
|
+
nodeType: "paragraph",
|
|
9360
|
+
story: {
|
|
9361
|
+
kind: "story",
|
|
9362
|
+
storyType: "body"
|
|
9363
|
+
}
|
|
9288
9364
|
}) : null;
|
|
9289
9365
|
return readParagraphIndentationFromResult(raw && typeof raw === "object" ? raw : null);
|
|
9290
9366
|
} catch {
|
|
@@ -9961,14 +10037,15 @@ function createSuperDocUI(options) {
|
|
|
9961
10037
|
const tableSelection = isPlainObject(handles) ? handles.selection : void 0;
|
|
9962
10038
|
const subscribeWholeTable = hostMethod(tableSelection, "subscribeWholeTable");
|
|
9963
10039
|
if (subscribeWholeTable) {
|
|
9964
|
-
const refreshWholeTable = () => {
|
|
10040
|
+
const refreshWholeTable = (initial = false) => {
|
|
10041
|
+
const native = initial ? readHostSelectionSnapshot() : null;
|
|
9965
10042
|
selectionEpoch += 1;
|
|
9966
|
-
refreshSelectionFromHost(void 0, false, true);
|
|
10043
|
+
refreshSelectionFromHost(void 0, false, true, native);
|
|
9967
10044
|
recompute("host-selection");
|
|
9968
10045
|
};
|
|
9969
|
-
const detach = subscribeWholeTable(refreshWholeTable);
|
|
10046
|
+
const detach = subscribeWholeTable(() => refreshWholeTable());
|
|
9970
10047
|
if (typeof detach === "function") unsubscribeCallbacks.push(() => detach());
|
|
9971
|
-
if (hostMethod(tableSelection, "getWholeTableNodeId")?.()) refreshWholeTable();
|
|
10048
|
+
if (hostMethod(tableSelection, "getWholeTableNodeId")?.()) refreshWholeTable(true);
|
|
9972
10049
|
}
|
|
9973
10050
|
} catch {
|
|
9974
10051
|
currentHostSelectionSource = null;
|
|
@@ -9989,10 +10066,35 @@ function createSuperDocUI(options) {
|
|
|
9989
10066
|
};
|
|
9990
10067
|
let trackedChangeNavigationInFlight = 0;
|
|
9991
10068
|
let lastPublishedHostReviewTarget;
|
|
10069
|
+
const isRepublishedHostReviewTarget = (left, right) => left === right || isPlainObject(left) && isPlainObject(right) && left.layoutEpoch !== right.layoutEpoch && left.origin === right.origin && left.entityType === right.entityType && left.entityId === right.entityId && left.paintedEntityId === right.paintedEntityId && storyLocatorSignature(left.story) === storyLocatorSignature(right.story);
|
|
9992
10070
|
const syncTrackedChangeFocusFromHostReviewTarget = (rawTarget, rawSnapshot) => {
|
|
9993
10071
|
const rejection = (rawSnapshot && typeof rawSnapshot === "object" ? rawSnapshot : null)?.lastInteractionRejection;
|
|
9994
|
-
if (rawTarget == null && rejection && typeof rejection === "object" && rejection.code === "review-target-invalidated" && rejection.detail === "not-painted" && explicitActiveChange) return false;
|
|
10072
|
+
if (rawTarget == null && rejection && typeof rejection === "object" && rejection.code === "review-target-invalidated" && rejection.detail === "not-painted" && (explicitActiveChange || explicitActiveCommentId)) return false;
|
|
9995
10073
|
const target = rawTarget && typeof rawTarget === "object" ? rawTarget : null;
|
|
10074
|
+
if (target?.entityType === "comment" && typeof target.entityId === "string" && target.entityId.length > 0) {
|
|
10075
|
+
const commentId = resolveActiveCommentId(state?.comments.items ?? [], target.entityId) ?? target.entityId;
|
|
10076
|
+
const republished = isRepublishedHostReviewTarget(rawTarget, lastPublishedHostReviewTarget?.raw);
|
|
10077
|
+
lastPublishedHostReviewTarget = {
|
|
10078
|
+
raw: rawTarget,
|
|
10079
|
+
focus: null,
|
|
10080
|
+
origin: target.origin
|
|
10081
|
+
};
|
|
10082
|
+
if (republished || explicitActiveCommentId === commentId && !explicitActiveChange) return false;
|
|
10083
|
+
setExplicitActiveChange(null);
|
|
10084
|
+
explicitActiveCommentId = commentId;
|
|
10085
|
+
return true;
|
|
10086
|
+
}
|
|
10087
|
+
const previousTarget = lastPublishedHostReviewTarget?.raw;
|
|
10088
|
+
if (!target && isPlainObject(previousTarget) && previousTarget.entityType === "comment") {
|
|
10089
|
+
lastPublishedHostReviewTarget = {
|
|
10090
|
+
raw: rawTarget,
|
|
10091
|
+
focus: null,
|
|
10092
|
+
origin: void 0
|
|
10093
|
+
};
|
|
10094
|
+
if (!explicitActiveCommentId) return false;
|
|
10095
|
+
explicitActiveCommentId = null;
|
|
10096
|
+
return true;
|
|
10097
|
+
}
|
|
9996
10098
|
let next = null;
|
|
9997
10099
|
if (target?.entityType === "trackedChange" && typeof target.entityId === "string" && target.entityId.length > 0) {
|
|
9998
10100
|
const targetStory = target.story && typeof target.story === "object" ? target.story : void 0;
|
|
@@ -10017,7 +10119,7 @@ function createSuperDocUI(options) {
|
|
|
10017
10119
|
}
|
|
10018
10120
|
if (rawTarget == null && next == null && explicitActiveChange != null && hasPendingTrackChangeRevealFocus(explicitActiveChange)) return false;
|
|
10019
10121
|
const previousPublication = lastPublishedHostReviewTarget;
|
|
10020
|
-
if (previousPublication && (rawTarget
|
|
10122
|
+
if (previousPublication && (isRepublishedHostReviewTarget(rawTarget, previousPublication.raw) || target?.origin === "panel" && previousPublication.origin === "panel" && next && previousPublication.focus && explicitActiveChangesEqual(previousPublication.focus, next))) return false;
|
|
10021
10123
|
lastPublishedHostReviewTarget = {
|
|
10022
10124
|
raw: rawTarget,
|
|
10023
10125
|
focus: next,
|
|
@@ -10395,11 +10497,16 @@ function createSuperDocUI(options) {
|
|
|
10395
10497
|
* ordinary/insertion selections are visible-space, while a selection that
|
|
10396
10498
|
* reaches painted deleted text is projected in tracked space by the host.
|
|
10397
10499
|
*
|
|
10398
|
-
* Cross-block
|
|
10399
|
-
*
|
|
10500
|
+
* Cross-block and object-containing coverage use the model-backed tracked
|
|
10501
|
+
* target when the explicit text selection cannot represent the range.
|
|
10400
10502
|
*/
|
|
10401
10503
|
function trackDecisionRangeFromSelection(selection) {
|
|
10402
10504
|
if (selection.empty) return null;
|
|
10505
|
+
if (!selection.selectionTarget && selection.trackedTarget) return {
|
|
10506
|
+
kind: "range",
|
|
10507
|
+
coordinateSpace: "tracked",
|
|
10508
|
+
range: selection.trackedTarget
|
|
10509
|
+
};
|
|
10403
10510
|
const explicit = selection.selectionTarget;
|
|
10404
10511
|
const start = explicit?.start;
|
|
10405
10512
|
const end = explicit?.end;
|
|
@@ -10553,7 +10660,7 @@ function createSuperDocUI(options) {
|
|
|
10553
10660
|
kind: "blocked",
|
|
10554
10661
|
reason: SUPERDOC_UI_REASONS.operationUnavailable
|
|
10555
10662
|
};
|
|
10556
|
-
if (!selection.selectionTarget) return null;
|
|
10663
|
+
if (!selection.selectionTarget && !selection.trackedTarget && selection.target?.kind !== "text") return null;
|
|
10557
10664
|
const target = trackDecisionRangeFromSelection(selection);
|
|
10558
10665
|
if (!target && route() !== "id") return {
|
|
10559
10666
|
kind: "blocked",
|
|
@@ -10893,25 +11000,35 @@ function createSuperDocUI(options) {
|
|
|
10893
11000
|
pendingCommandSettlement = settledResults.length ? Promise.all(settledResults).then((results) => combineCommandResults(results)) : null;
|
|
10894
11001
|
return combineCommandResults(immediateResults);
|
|
10895
11002
|
};
|
|
10896
|
-
/**
|
|
10897
|
-
* Call an inline `format.*` operation against the live selection. Mirrors
|
|
10898
|
-
* `callEditorMutation` (suggesting mode adds `changeMode: 'tracked'`), and
|
|
10899
|
-
* when the target is the host's own editable `selectionTarget` it also
|
|
10900
|
-
* carries the PRIVATE V2 option `offsetSpace: 'selection'` (browser
|
|
10901
|
-
* selection offsets count an inline object as one caret position). The
|
|
10902
|
-
* option is not part of public `MutationOptions`; this is the same cast
|
|
10903
|
-
* pattern the delete/replace callers use.
|
|
10904
|
-
*/
|
|
10905
11003
|
function currentCellSelectionTarget() {
|
|
11004
|
+
return captureInputSelectionTarget(true);
|
|
11005
|
+
}
|
|
11006
|
+
function captureInputSelectionTarget(requireTableCells = false) {
|
|
10906
11007
|
const handles = safeCall(() => hostMethod(getHost(), "getHandles")?.(), null);
|
|
10907
11008
|
const selection = isPlainObject(handles) ? handles.selection : void 0;
|
|
10908
11009
|
const held = hostMethod(selection, "getSnapshot")?.();
|
|
10909
|
-
if (!isPlainObject(held) || !held.tableCells) return null;
|
|
11010
|
+
if (requireTableCells && (!isPlainObject(held) || !held.tableCells)) return null;
|
|
10910
11011
|
const resolved = hostMethod(selection, "toSelectionTarget")?.();
|
|
10911
11012
|
return isPlainObject(resolved) && resolved.kind === "ok" && resolved.mode === "range" ? capturedTableCellTarget(resolved.target) : null;
|
|
10912
11013
|
}
|
|
11014
|
+
function currentUnrepresentableSelectionTarget(selection) {
|
|
11015
|
+
if (selection.empty || selection.selectionTarget || selection.target?.kind !== "text") return null;
|
|
11016
|
+
return heldPaintedTextSelectionTarget();
|
|
11017
|
+
}
|
|
11018
|
+
function heldPaintedTextSelectionTarget() {
|
|
11019
|
+
const target = captureInputSelectionTarget();
|
|
11020
|
+
if (target) paintedInlineTargets.add(target);
|
|
11021
|
+
return target;
|
|
11022
|
+
}
|
|
10913
11023
|
function resolveInlineCommandTarget(selection) {
|
|
10914
|
-
|
|
11024
|
+
const cells = currentCellSelectionTarget();
|
|
11025
|
+
if (cells) return cells;
|
|
11026
|
+
if (!selection.empty && !selection.selectionTarget && selection.target?.kind === "text") {
|
|
11027
|
+
const snapshot = readHostSelectionSnapshot();
|
|
11028
|
+
const painted = currentUnrepresentableSelectionTarget(selection);
|
|
11029
|
+
if (painted) return snapshot && appliedSelectionPresentation(selection) && readHostSelectionSnapshot() === snapshot ? painted : null;
|
|
11030
|
+
}
|
|
11031
|
+
return resolveInlineSelectionTarget(selection);
|
|
10915
11032
|
}
|
|
10916
11033
|
function tableCellSelectionForTarget(target) {
|
|
10917
11034
|
const cellTarget = currentCellSelectionTarget();
|
|
@@ -10931,10 +11048,15 @@ function createSuperDocUI(options) {
|
|
|
10931
11048
|
offsetSpace: "selection",
|
|
10932
11049
|
tableCellSelection
|
|
10933
11050
|
});
|
|
11051
|
+
const paintedTarget = input?.target;
|
|
11052
|
+
if (paintedTarget !== null && typeof paintedTarget === "object" && (paintedInlineTargets.has(paintedTarget) || paintedTarget.coordinateSpace === "tracked")) return op(input, {
|
|
11053
|
+
...options,
|
|
11054
|
+
offsetSpace: "selection"
|
|
11055
|
+
});
|
|
10934
11056
|
if (!selection.selectionTarget) return options ? op(input, options) : op(input);
|
|
10935
11057
|
return op(input, {
|
|
10936
11058
|
...options,
|
|
10937
|
-
offsetSpace: "
|
|
11059
|
+
offsetSpace: "kernel"
|
|
10938
11060
|
});
|
|
10939
11061
|
};
|
|
10940
11062
|
/** Build the `format.paragraph.*` / `styles.paragraph.*` input for a block. */
|
|
@@ -11163,13 +11285,16 @@ function createSuperDocUI(options) {
|
|
|
11163
11285
|
};
|
|
11164
11286
|
pendingCommandSettlement = (async () => {
|
|
11165
11287
|
const plans = await Promise.all(blockIds.map((blockId) => planBlock(blockId).catch(() => null)));
|
|
11166
|
-
|
|
11288
|
+
const allListItems = plans.length === blockIds.length && plans.every((plan) => plan?.kind === "list");
|
|
11289
|
+
const preserveFirstItemLevel = blockIds.length === 1 && story.storyType === "body";
|
|
11290
|
+
if (allListItems && (readDocumentMode() !== "suggesting" || preserveFirstItemLevel)) {
|
|
11167
11291
|
const rangeRoute = mode === "indent" ? "lists.indentRange" : "lists.outdentRange";
|
|
11168
11292
|
const rangeOp = resolveDocOperation(doc, rangeRoute);
|
|
11169
11293
|
if (rangeOp) try {
|
|
11170
11294
|
return await settleOperationResult(callEditorMutation(rangeRoute, rangeOp, {
|
|
11171
11295
|
paraIds: blockIds,
|
|
11172
|
-
story
|
|
11296
|
+
story,
|
|
11297
|
+
...preserveFirstItemLevel ? { preserveFirstItemLevel: true } : {}
|
|
11173
11298
|
})).settled;
|
|
11174
11299
|
} catch {
|
|
11175
11300
|
return false;
|
|
@@ -11709,23 +11834,32 @@ function createSuperDocUI(options) {
|
|
|
11709
11834
|
const record = readLinkPayloadRecord(payload);
|
|
11710
11835
|
return Boolean(readLinkPayloadTarget(payload) || isPlainObject(record.hyperlinkTarget) || isPlainObject(record.textTarget));
|
|
11711
11836
|
};
|
|
11712
|
-
const
|
|
11837
|
+
const currentWholeTableParagraphOwner = () => {
|
|
11713
11838
|
const owner = wholeTableParagraphSeed, host = getHost();
|
|
11714
|
-
if (!owner || disposed || owner.lifetime.aborted || owner.host !== host || owner.editor !== getEditor() || owner.editor.doc !== owner.doc || owner.sourceToken !== contentToken() || owner.mode !== readDocumentMode() || safeCall(() => hostMethod(host, "getMountedHandle")?.(), null) !== owner.mount) return
|
|
11839
|
+
if (!owner || disposed || owner.lifetime.aborted || owner.host !== host || owner.editor !== getEditor() || owner.editor.doc !== owner.doc || owner.sourceToken !== contentToken() || owner.mode !== readDocumentMode() || safeCall(() => hostMethod(host, "getMountedHandle")?.(), null) !== owner.mount) return null;
|
|
11715
11840
|
const tableId = owner.info.tableSelection?.tableId;
|
|
11716
11841
|
const activeTable = safeCall(() => {
|
|
11717
11842
|
const handles = hostMethod(host, "getHandles")?.();
|
|
11718
11843
|
return hostMethod(isPlainObject(handles) ? handles.selection : void 0, "getWholeTableNodeId")?.();
|
|
11719
11844
|
}, null);
|
|
11720
|
-
if (!tableId || activeTable !== tableId || state.selection.tableSelection?.type !== "table" || state.selection.tableSelection.tableId !== tableId || selectionSignature(state.selection) !== selectionSignature(selectionSliceFromInfo(owner.info, "ready"))) return
|
|
11845
|
+
if (!tableId || activeTable !== tableId || state.selection.tableSelection?.type !== "table" || state.selection.tableSelection.tableId !== tableId || selectionSignature(state.selection) !== selectionSignature(selectionSliceFromInfo(owner.info, "ready"))) return null;
|
|
11721
11846
|
const applied = appliedSelectionPresentation(state.selection);
|
|
11722
11847
|
const info = normalizeSelectionInfo(applied?.selection);
|
|
11723
|
-
return
|
|
11848
|
+
return info && JSON.stringify(info.tableSelection) === JSON.stringify(owner.info.tableSelection) ? {
|
|
11849
|
+
owner,
|
|
11850
|
+
info
|
|
11851
|
+
} : null;
|
|
11852
|
+
};
|
|
11853
|
+
const currentWholeTableParagraphSelection = () => {
|
|
11854
|
+
const current = currentWholeTableParagraphOwner();
|
|
11855
|
+
if (!current) return false;
|
|
11856
|
+
return current.owner.info.selectionTarget ? selectionInfoMatchesHost(current.info) : current.owner.nativeSelection !== null && readHostSelectionSnapshot() === current.owner.nativeSelection;
|
|
11724
11857
|
};
|
|
11725
11858
|
const commandSelectionIsReady = (id, descriptor, payload) => {
|
|
11726
11859
|
const foreground = foregroundMutationState();
|
|
11727
11860
|
if (foreground && (foreground.active > 0 || foreground.pending > 0)) return false;
|
|
11728
11861
|
if (descriptor?.blockParagraph && currentWholeTableParagraphSelection()) return true;
|
|
11862
|
+
if (descriptor?.blockParagraph && state.selection.tableSelection?.type === "table" && !state.selection.selectionTarget) return false;
|
|
11729
11863
|
if (state.selection.status !== "ready") return false;
|
|
11730
11864
|
if (trackDecisionCommand(id)?.scope === "id") return true;
|
|
11731
11865
|
if (!descriptor || descriptor.disposition !== "routed") return true;
|
|
@@ -12146,10 +12280,23 @@ function createSuperDocUI(options) {
|
|
|
12146
12280
|
const cellTarget = currentCellSelectionTarget();
|
|
12147
12281
|
const tableCellSelection = tableCellSelectionForTarget(cellTarget);
|
|
12148
12282
|
const rawSelection = typeof selectionApi?.["current"] === "function" ? await Promise.resolve(selectionApi["current"]({ includeText: true })) : readSelectionInfoLive().value;
|
|
12283
|
+
const selection = normalizeSelectionInfo(rawSelection);
|
|
12284
|
+
let paintedTarget = null;
|
|
12285
|
+
if (selection && !selection.empty && !selection.selectionTarget && selection.target?.kind === "text" && !cellTarget) {
|
|
12286
|
+
const nativeSelection = readHostSelectionSnapshot();
|
|
12287
|
+
paintedTarget = heldPaintedTextSelectionTarget();
|
|
12288
|
+
if (paintedTarget && (!nativeSelection || !appliedSelectionPresentation(selectionSliceFromInfo(selection, "ready")) || readHostSelectionSnapshot() !== nativeSelection)) return {
|
|
12289
|
+
selection: null,
|
|
12290
|
+
cellTarget: null,
|
|
12291
|
+
tableCellSelection: null,
|
|
12292
|
+
paintedTarget: null
|
|
12293
|
+
};
|
|
12294
|
+
}
|
|
12149
12295
|
return {
|
|
12150
|
-
selection
|
|
12296
|
+
selection,
|
|
12151
12297
|
cellTarget,
|
|
12152
|
-
tableCellSelection
|
|
12298
|
+
tableCellSelection,
|
|
12299
|
+
paintedTarget
|
|
12153
12300
|
};
|
|
12154
12301
|
};
|
|
12155
12302
|
const waitForSelectionSettle = () => new Promise((resolve) => setTimeout(resolve, 16));
|
|
@@ -12167,7 +12314,7 @@ function createSuperDocUI(options) {
|
|
|
12167
12314
|
break;
|
|
12168
12315
|
}
|
|
12169
12316
|
if (selectionRead?.selection && !selectionRead.selection.empty && key !== painter.sourceSelectionKey) {
|
|
12170
|
-
await applyFormatPainter(selectionRead.selection, selectionRead.cellTarget, selectionRead.tableCellSelection);
|
|
12317
|
+
await applyFormatPainter(selectionRead.selection, selectionRead.cellTarget, selectionRead.tableCellSelection, selectionRead.paintedTarget);
|
|
12171
12318
|
return;
|
|
12172
12319
|
}
|
|
12173
12320
|
if (painter.snapshot?.paragraph) {
|
|
@@ -12175,10 +12322,10 @@ function createSuperDocUI(options) {
|
|
|
12175
12322
|
const caretSel = caretRead.selection;
|
|
12176
12323
|
if (!caretSel) return;
|
|
12177
12324
|
if (selectionKey(caretSel) === painter.sourceSelectionKey) return;
|
|
12178
|
-
await applyFormatPainter(caretSel, caretRead.cellTarget, caretRead.tableCellSelection);
|
|
12325
|
+
await applyFormatPainter(caretSel, caretRead.cellTarget, caretRead.tableCellSelection, caretRead.paintedTarget);
|
|
12179
12326
|
}
|
|
12180
12327
|
};
|
|
12181
|
-
const applyFormatPainter = async (selection, cellTarget, tableCellSelection) => {
|
|
12328
|
+
const applyFormatPainter = async (selection, cellTarget, tableCellSelection, paintedTarget) => {
|
|
12182
12329
|
const snap = painter.snapshot;
|
|
12183
12330
|
if (!snap) {
|
|
12184
12331
|
if (painter.mode === "armed") exitFormatPainter();
|
|
@@ -12196,7 +12343,7 @@ function createSuperDocUI(options) {
|
|
|
12196
12343
|
return;
|
|
12197
12344
|
}
|
|
12198
12345
|
const selTarget = selection.target;
|
|
12199
|
-
const selectionTarget = cellTarget ?? selection.selectionTarget;
|
|
12346
|
+
const selectionTarget = cellTarget ?? paintedTarget ?? selection.selectionTarget;
|
|
12200
12347
|
const selectionIsEmpty = selection.empty === true;
|
|
12201
12348
|
const segments = Array.isArray(selTarget?.segments) ? selTarget.segments : [];
|
|
12202
12349
|
const targetStory = selTarget?.story;
|
|
@@ -12434,13 +12581,16 @@ function createSuperDocUI(options) {
|
|
|
12434
12581
|
const snapshot = selectionSub.get();
|
|
12435
12582
|
if (snapshot.empty) return null;
|
|
12436
12583
|
const cells = currentCellSelectionTarget();
|
|
12584
|
+
const painted = cells ? null : currentUnrepresentableSelectionTarget(snapshot);
|
|
12585
|
+
const hostSelection = selectionHostSnapshots.get(snapshot);
|
|
12586
|
+
if ((cells || painted || hostSelection && !snapshot.selectionTarget) && (!hostSelection || readHostSelectionSnapshot() !== hostSelection)) return null;
|
|
12437
12587
|
if (!snapshot.target && !snapshot.selectionTarget && !cells) return null;
|
|
12438
12588
|
const capture = {
|
|
12439
12589
|
...snapshot,
|
|
12440
12590
|
capturedAt: Date.now(),
|
|
12441
|
-
...cells ? { _tableCellSelectionTarget: cells } : {}
|
|
12591
|
+
...cells ? { _tableCellSelectionTarget: cells } : {},
|
|
12592
|
+
...painted ? { _paintedSelectionTarget: painted } : {}
|
|
12442
12593
|
};
|
|
12443
|
-
const hostSelection = selectionHostSnapshots.get(snapshot);
|
|
12444
12594
|
if (hostSelection) selectionHostSnapshots.set(capture, hostSelection);
|
|
12445
12595
|
return capture;
|
|
12446
12596
|
},
|
|
@@ -12466,7 +12616,13 @@ function createSuperDocUI(options) {
|
|
|
12466
12616
|
ok: false,
|
|
12467
12617
|
reason: SUPERDOC_UI_REASONS.targetUnresolved
|
|
12468
12618
|
});
|
|
12469
|
-
const
|
|
12619
|
+
const hasPaintedTarget = "_paintedSelectionTarget" in capture;
|
|
12620
|
+
const paintedTarget = hasPaintedTarget ? capturedTableCellTarget(capture._paintedSelectionTarget) : null;
|
|
12621
|
+
if (hasPaintedTarget && !paintedTarget) return done({
|
|
12622
|
+
ok: false,
|
|
12623
|
+
reason: SUPERDOC_UI_REASONS.targetUnresolved
|
|
12624
|
+
});
|
|
12625
|
+
const target = cellTarget ?? paintedTarget ?? selectionTargetForRestore(capture);
|
|
12470
12626
|
if (!target) return done({
|
|
12471
12627
|
ok: false,
|
|
12472
12628
|
reason: SUPERDOC_UI_REASONS.targetUnresolved
|
|
@@ -12479,7 +12635,7 @@ function createSuperDocUI(options) {
|
|
|
12479
12635
|
reason: resolved.reason
|
|
12480
12636
|
});
|
|
12481
12637
|
try {
|
|
12482
|
-
return done(normalizeHostSelectionApplyResult(hostMethod(resolved.helper, "apply")?.(target, ...cellTarget ? [{ tableCells: true }] : [])));
|
|
12638
|
+
return done(normalizeHostSelectionApplyResult(hostMethod(resolved.helper, "apply")?.(target, ...cellTarget ? [{ tableCells: true }] : paintedTarget ? [{ offsetSpace: "selection" }] : [])));
|
|
12483
12639
|
} catch {
|
|
12484
12640
|
return done({
|
|
12485
12641
|
ok: false,
|
|
@@ -12898,6 +13054,10 @@ function createSuperDocUI(options) {
|
|
|
12898
13054
|
};
|
|
12899
13055
|
const commentsSub = sliceHandle((s) => s.comments);
|
|
12900
13056
|
const commentsSnap = directorySnapshotHandle(commentsSub, select((s) => computeCommentsDirectorySnapshot(s.selection, s.comments)), "comments");
|
|
13057
|
+
documentResetHooks.push(() => {
|
|
13058
|
+
setExplicitActiveChange(null);
|
|
13059
|
+
explicitActiveCommentId = null;
|
|
13060
|
+
});
|
|
12901
13061
|
const comments = {
|
|
12902
13062
|
get: commentsSnap.get,
|
|
12903
13063
|
getSnapshot: commentsSnap.getSnapshot,
|
|
@@ -12991,6 +13151,7 @@ function createSuperDocUI(options) {
|
|
|
12991
13151
|
setActive: (commentId) => {
|
|
12992
13152
|
if (commentId == null) {
|
|
12993
13153
|
explicitActiveCommentId = null;
|
|
13154
|
+
mirrorReviewFocusToHost("comment", null);
|
|
12994
13155
|
recompute();
|
|
12995
13156
|
return true;
|
|
12996
13157
|
}
|
|
@@ -13003,7 +13164,9 @@ function createSuperDocUI(options) {
|
|
|
13003
13164
|
const resolvedId = resolveActiveCommentId(items, commentId);
|
|
13004
13165
|
if (!resolvedId) return false;
|
|
13005
13166
|
if (!items.some((entry) => readEntityId(entry) === resolvedId)) return false;
|
|
13167
|
+
setExplicitActiveChange(null);
|
|
13006
13168
|
explicitActiveCommentId = resolvedId;
|
|
13169
|
+
mirrorReviewFocusToHost("comment", { id: resolvedId });
|
|
13007
13170
|
recompute();
|
|
13008
13171
|
return true;
|
|
13009
13172
|
},
|
|
@@ -13063,7 +13226,7 @@ function createSuperDocUI(options) {
|
|
|
13063
13226
|
};
|
|
13064
13227
|
const navigateAndScrollCurrentRequest = async (step, requestedAtInvalidation) => {
|
|
13065
13228
|
if (queuedTrackChangeNavigationInvalidation !== requestedAtInvalidation) return { success: false };
|
|
13066
|
-
const
|
|
13229
|
+
const previousFocus = readReviewFocus();
|
|
13067
13230
|
const activeId = navigateTrackChange(step, { invalidateQueuedNavigation: false });
|
|
13068
13231
|
if (activeId == null) return { success: false };
|
|
13069
13232
|
const optimisticActiveChange = explicitActiveChange;
|
|
@@ -13071,7 +13234,7 @@ function createSuperDocUI(options) {
|
|
|
13071
13234
|
const isCurrent = () => queuedTrackChangeNavigationInvalidation === requestedAtInvalidation && explicitActiveChange === optimisticActiveChange && explicitActiveChangeRevision === optimisticRevision;
|
|
13072
13235
|
const rollback = () => {
|
|
13073
13236
|
if (!isCurrent()) return;
|
|
13074
|
-
|
|
13237
|
+
restoreReviewFocus(previousFocus);
|
|
13075
13238
|
recompute();
|
|
13076
13239
|
};
|
|
13077
13240
|
if (optimisticActiveChange) pendingTrackChangeRevealFocuses.add(optimisticActiveChange);
|
|
@@ -13091,10 +13254,8 @@ function createSuperDocUI(options) {
|
|
|
13091
13254
|
shouldContinue: isCurrent
|
|
13092
13255
|
});
|
|
13093
13256
|
if (!isCurrent()) return { success: false };
|
|
13094
|
-
if (!result.ok && result.reason !== SUPERDOC_UI_REASONS.targetNotVisible)
|
|
13095
|
-
|
|
13096
|
-
mirrorTrackedChangeFocusToHost(previousActiveChange);
|
|
13097
|
-
} else {
|
|
13257
|
+
if (!result.ok && result.reason !== SUPERDOC_UI_REASONS.targetNotVisible) rollback();
|
|
13258
|
+
else {
|
|
13098
13259
|
if (result.ok) await restampVisibleTrackedChangeCarrierAliases(activeId);
|
|
13099
13260
|
if (!isCurrent()) return { success: false };
|
|
13100
13261
|
mirrorTrackedChangeFocusToHost(optimisticActiveChange);
|
|
@@ -13225,7 +13386,7 @@ function createSuperDocUI(options) {
|
|
|
13225
13386
|
const matchingRow = matchStory ? loadedItems.find((item) => entityRowMatchesRequest(item, publicId, matchStory)) : loadedItems.find((item) => readEntityId(item) === publicId);
|
|
13226
13387
|
const story = matchStory ? requestedStory : readEntityRequestStory(matchingRow);
|
|
13227
13388
|
const importedId = deriveTrackedChangeImportedId(matchingRow);
|
|
13228
|
-
const
|
|
13389
|
+
const previousFocus = readReviewFocus();
|
|
13229
13390
|
const requestedActiveChange = {
|
|
13230
13391
|
id: publicId,
|
|
13231
13392
|
...story ? { story } : {},
|
|
@@ -13253,7 +13414,7 @@ function createSuperDocUI(options) {
|
|
|
13253
13414
|
const isCurrent = () => trackChangeRevealInvalidation === revealInvalidation && explicitActiveChange === optimisticActiveChange && explicitActiveChangeRevision === optimisticRevision;
|
|
13254
13415
|
const rollback = () => {
|
|
13255
13416
|
if (!isCurrent()) return;
|
|
13256
|
-
|
|
13417
|
+
restoreReviewFocus(previousFocus);
|
|
13257
13418
|
recompute();
|
|
13258
13419
|
};
|
|
13259
13420
|
recompute();
|
|
@@ -13267,10 +13428,8 @@ function createSuperDocUI(options) {
|
|
|
13267
13428
|
success: false,
|
|
13268
13429
|
ok: false
|
|
13269
13430
|
};
|
|
13270
|
-
if (!result.ok && result.reason !== SUPERDOC_UI_REASONS.targetNotVisible)
|
|
13271
|
-
|
|
13272
|
-
mirrorTrackedChangeFocusToHost(previousActiveChange);
|
|
13273
|
-
} else {
|
|
13431
|
+
if (!result.ok && result.reason !== SUPERDOC_UI_REASONS.targetNotVisible) rollback();
|
|
13432
|
+
else {
|
|
13274
13433
|
if (result.ok) await restampVisibleTrackedChangeCarrierAliases(publicId);
|
|
13275
13434
|
if (!isCurrent()) return {
|
|
13276
13435
|
success: false,
|
|
@@ -13605,14 +13764,14 @@ function createSuperDocUI(options) {
|
|
|
13605
13764
|
if (root instanceof HTMLElement) return root;
|
|
13606
13765
|
return null;
|
|
13607
13766
|
};
|
|
13608
|
-
const
|
|
13609
|
-
if (typeof x !== "number" || typeof y !== "number" || !Number.isFinite(x) || !Number.isFinite(y)) return
|
|
13767
|
+
const pointHitElements = (x, y) => {
|
|
13768
|
+
if (typeof x !== "number" || typeof y !== "number" || !Number.isFinite(x) || !Number.isFinite(y)) return null;
|
|
13610
13769
|
const dom = globalThis.document;
|
|
13611
|
-
if (!dom || typeof dom.elementFromPoint !== "function") return
|
|
13770
|
+
if (!dom || typeof dom.elementFromPoint !== "function") return null;
|
|
13612
13771
|
const container = resolveVisibleHost();
|
|
13613
|
-
if (!container) return
|
|
13772
|
+
if (!container) return null;
|
|
13614
13773
|
const startEl = dom.elementFromPoint(x, y);
|
|
13615
|
-
if (!startEl || !container.contains(startEl)) return
|
|
13774
|
+
if (!startEl || !container.contains(startEl)) return null;
|
|
13616
13775
|
const primaryEls = [startEl];
|
|
13617
13776
|
const addPrimaryEl = (el) => {
|
|
13618
13777
|
if (el && container.contains(el) && !primaryEls.includes(el)) primaryEls.push(el);
|
|
@@ -13627,6 +13786,17 @@ function createSuperDocUI(options) {
|
|
|
13627
13786
|
}
|
|
13628
13787
|
for (const el of stacked) addPrimaryEl(el);
|
|
13629
13788
|
}
|
|
13789
|
+
return {
|
|
13790
|
+
container,
|
|
13791
|
+
elements: primaryEls,
|
|
13792
|
+
x,
|
|
13793
|
+
y
|
|
13794
|
+
};
|
|
13795
|
+
};
|
|
13796
|
+
const pointEntityHits = (x, y) => {
|
|
13797
|
+
const point = pointHitElements(x, y);
|
|
13798
|
+
if (!point) return [];
|
|
13799
|
+
const { container, elements: primaryEls } = point;
|
|
13630
13800
|
const markerEls = [];
|
|
13631
13801
|
const addMarkerEl = (el) => {
|
|
13632
13802
|
if (el && container.contains(el) && !markerEls.includes(el) && !primaryEls.includes(el)) markerEls.push(el);
|
|
@@ -13640,7 +13810,7 @@ function createSuperDocUI(options) {
|
|
|
13640
13810
|
} catch {
|
|
13641
13811
|
return false;
|
|
13642
13812
|
}
|
|
13643
|
-
return rect != null && x >= rect.left && x <= rect.right && y >= rect.top && y <= rect.bottom;
|
|
13813
|
+
return rect != null && point.x >= rect.left && point.x <= rect.right && point.y >= rect.top && point.y <= rect.bottom;
|
|
13644
13814
|
};
|
|
13645
13815
|
for (const el of primaryEls) {
|
|
13646
13816
|
const queryAll = el.querySelectorAll;
|
|
@@ -13664,6 +13834,18 @@ function createSuperDocUI(options) {
|
|
|
13664
13834
|
const seen = /* @__PURE__ */ new Set();
|
|
13665
13835
|
const hits = [];
|
|
13666
13836
|
for (const hit of rawHits) {
|
|
13837
|
+
if (hit.type === "decoration") {
|
|
13838
|
+
const owner = decorationOwnerForProvider(hit.id);
|
|
13839
|
+
if (!owner) continue;
|
|
13840
|
+
const key = `decoration:${owner.id}`;
|
|
13841
|
+
if (seen.has(key)) continue;
|
|
13842
|
+
seen.add(key);
|
|
13843
|
+
hits.push({
|
|
13844
|
+
type: "decoration",
|
|
13845
|
+
id: owner.id
|
|
13846
|
+
});
|
|
13847
|
+
continue;
|
|
13848
|
+
}
|
|
13667
13849
|
if (hit.type !== "trackedChange") {
|
|
13668
13850
|
const layoutStory = hit.type === "contentControl" ? layoutStoryDatasetToStoryLocator(hit.story) : void 0;
|
|
13669
13851
|
const story = hit.type === "contentControl" ? isTextboxStory(layoutStory) ? layoutStory : storyKeyToStoryLocator(hit.storyKey) ?? layoutStory : void 0;
|
|
@@ -13819,6 +14001,149 @@ function createSuperDocUI(options) {
|
|
|
13819
14001
|
if (status !== "ready") return { reason: "not-ready" };
|
|
13820
14002
|
return value ? { target: value } : { reason: "unresolved" };
|
|
13821
14003
|
};
|
|
14004
|
+
const liveDecorations = /* @__PURE__ */ new Map();
|
|
14005
|
+
const decorationOwnerForProvider = (providerId) => {
|
|
14006
|
+
const owner = currentHostVisuals()?.providerOwner?.(providerId);
|
|
14007
|
+
return isPlainObject(owner) && typeof owner.id === "string" ? owner : null;
|
|
14008
|
+
};
|
|
14009
|
+
const currentHostVisuals = () => getEditor()?.visuals ?? null;
|
|
14010
|
+
const decorationListeners = /* @__PURE__ */ new Set();
|
|
14011
|
+
let detachDecorationPointer = null;
|
|
14012
|
+
let hoveredDecorations = [];
|
|
14013
|
+
let lastPointer = {
|
|
14014
|
+
clientX: 0,
|
|
14015
|
+
clientY: 0
|
|
14016
|
+
};
|
|
14017
|
+
const decorationIdsAt = (x, y) => {
|
|
14018
|
+
const point = pointHitElements(x, y);
|
|
14019
|
+
if (!point) return [];
|
|
14020
|
+
const ids = /* @__PURE__ */ new Set();
|
|
14021
|
+
for (const element of point.elements) for (const provider of collectDecorationProvidersFromChain(element, point.container)) {
|
|
14022
|
+
const owner = decorationOwnerForProvider(provider);
|
|
14023
|
+
if (owner) ids.add(owner.id);
|
|
14024
|
+
}
|
|
14025
|
+
return [...ids];
|
|
14026
|
+
};
|
|
14027
|
+
const decorationData = (id) => {
|
|
14028
|
+
const owner = currentHostVisuals()?.ownerById?.(id);
|
|
14029
|
+
return isPlainObject(owner?.data) ? owner.data : void 0;
|
|
14030
|
+
};
|
|
14031
|
+
const emitDecorationEvent = (type, decoration, point) => {
|
|
14032
|
+
const payload = {
|
|
14033
|
+
type,
|
|
14034
|
+
id: decoration.id,
|
|
14035
|
+
...decoration.data ? { data: decoration.data } : {},
|
|
14036
|
+
clientX: point.clientX,
|
|
14037
|
+
clientY: point.clientY
|
|
14038
|
+
};
|
|
14039
|
+
for (const listener of Array.from(decorationListeners)) safeCall(() => listener(payload), void 0);
|
|
14040
|
+
};
|
|
14041
|
+
const leaveHoveredDecorations = (onlyId) => {
|
|
14042
|
+
const leaving = hoveredDecorations.filter((decoration) => onlyId === void 0 || decoration.id === onlyId);
|
|
14043
|
+
hoveredDecorations = hoveredDecorations.filter((decoration) => !leaving.includes(decoration));
|
|
14044
|
+
for (const decoration of leaving) emitDecorationEvent("hover-leave", decoration, lastPointer);
|
|
14045
|
+
};
|
|
14046
|
+
const attachDecorationPointer = () => {
|
|
14047
|
+
if (detachDecorationPointer || decorationListeners.size === 0) return;
|
|
14048
|
+
const host = resolveVisibleHost();
|
|
14049
|
+
if (!host) return;
|
|
14050
|
+
const onClick = (event) => {
|
|
14051
|
+
for (const id of decorationIdsAt(event.clientX, event.clientY)) emitDecorationEvent("click", {
|
|
14052
|
+
id,
|
|
14053
|
+
data: decorationData(id)
|
|
14054
|
+
}, event);
|
|
14055
|
+
};
|
|
14056
|
+
const onMove = (event) => {
|
|
14057
|
+
lastPointer = {
|
|
14058
|
+
clientX: event.clientX,
|
|
14059
|
+
clientY: event.clientY
|
|
14060
|
+
};
|
|
14061
|
+
const nextIds = decorationIdsAt(event.clientX, event.clientY);
|
|
14062
|
+
const leaving = hoveredDecorations.filter((decoration) => !nextIds.includes(decoration.id));
|
|
14063
|
+
const kept = hoveredDecorations.filter((decoration) => nextIds.includes(decoration.id));
|
|
14064
|
+
const entering = nextIds.filter((id) => !kept.some((decoration) => decoration.id === id)).map((id) => ({
|
|
14065
|
+
id,
|
|
14066
|
+
data: decorationData(id)
|
|
14067
|
+
}));
|
|
14068
|
+
hoveredDecorations = [...kept, ...entering];
|
|
14069
|
+
for (const decoration of leaving) emitDecorationEvent("hover-leave", decoration, event);
|
|
14070
|
+
for (const decoration of entering) emitDecorationEvent("hover-enter", decoration, event);
|
|
14071
|
+
};
|
|
14072
|
+
const onLeave = (event) => {
|
|
14073
|
+
lastPointer = {
|
|
14074
|
+
clientX: event.clientX,
|
|
14075
|
+
clientY: event.clientY
|
|
14076
|
+
};
|
|
14077
|
+
leaveHoveredDecorations();
|
|
14078
|
+
};
|
|
14079
|
+
host.addEventListener("click", onClick);
|
|
14080
|
+
host.addEventListener("pointermove", onMove);
|
|
14081
|
+
host.addEventListener("pointerleave", onLeave);
|
|
14082
|
+
detachDecorationPointer = () => {
|
|
14083
|
+
host.removeEventListener("click", onClick);
|
|
14084
|
+
host.removeEventListener("pointermove", onMove);
|
|
14085
|
+
host.removeEventListener("pointerleave", onLeave);
|
|
14086
|
+
leaveHoveredDecorations();
|
|
14087
|
+
detachDecorationPointer = null;
|
|
14088
|
+
};
|
|
14089
|
+
};
|
|
14090
|
+
const subscribeDecorationPointer = (listener) => {
|
|
14091
|
+
if (disposed) throw new Error("ui.decorations.subscribe called on a destroyed UI controller.");
|
|
14092
|
+
decorationListeners.add(listener);
|
|
14093
|
+
attachDecorationPointer();
|
|
14094
|
+
return () => {
|
|
14095
|
+
decorationListeners.delete(listener);
|
|
14096
|
+
if (decorationListeners.size === 0) detachDecorationPointer?.();
|
|
14097
|
+
};
|
|
14098
|
+
};
|
|
14099
|
+
documentResetHooks.push(() => {
|
|
14100
|
+
leaveHoveredDecorations();
|
|
14101
|
+
const current = currentHostVisuals();
|
|
14102
|
+
for (const [handle, owner] of Array.from(liveDecorations)) if (owner.visuals !== current || owner.generation !== current.generation()) handle.dispose();
|
|
14103
|
+
});
|
|
14104
|
+
activeEditorResetHooks.push(() => {
|
|
14105
|
+
detachDecorationPointer?.();
|
|
14106
|
+
attachDecorationPointer();
|
|
14107
|
+
});
|
|
14108
|
+
const createDecorationsHandle = (track) => ({
|
|
14109
|
+
subscribe: (listener) => {
|
|
14110
|
+
const unsubscribe = subscribeDecorationPointer(listener);
|
|
14111
|
+
track?.({ dispose: unsubscribe });
|
|
14112
|
+
return unsubscribe;
|
|
14113
|
+
},
|
|
14114
|
+
highlight: (id, options) => {
|
|
14115
|
+
if (disposed) throw new Error("ui.decorations.highlight called on a destroyed UI controller.");
|
|
14116
|
+
const visuals = currentHostVisuals();
|
|
14117
|
+
if (!visuals) throw new Error("ui.decorations.highlight requires a ready document.");
|
|
14118
|
+
const inner = visuals.highlight(id, options);
|
|
14119
|
+
let handleDisposed = false;
|
|
14120
|
+
const handle = {
|
|
14121
|
+
id: inner.id,
|
|
14122
|
+
replace: (targets) => inner.replace(targets),
|
|
14123
|
+
add: (targets) => inner.add(targets),
|
|
14124
|
+
clear: () => {
|
|
14125
|
+
if (handleDisposed) return;
|
|
14126
|
+
inner.clear();
|
|
14127
|
+
leaveHoveredDecorations(inner.id);
|
|
14128
|
+
},
|
|
14129
|
+
invalidate: () => inner.invalidate(),
|
|
14130
|
+
dispose: () => {
|
|
14131
|
+
if (handleDisposed) return;
|
|
14132
|
+
handleDisposed = true;
|
|
14133
|
+
liveDecorations.delete(handle);
|
|
14134
|
+
inner.dispose();
|
|
14135
|
+
leaveHoveredDecorations(inner.id);
|
|
14136
|
+
}
|
|
14137
|
+
};
|
|
14138
|
+
liveDecorations.set(handle, {
|
|
14139
|
+
visuals,
|
|
14140
|
+
generation: visuals.generation()
|
|
14141
|
+
});
|
|
14142
|
+
track?.(handle);
|
|
14143
|
+
return handle;
|
|
14144
|
+
}
|
|
14145
|
+
});
|
|
14146
|
+
const decorations = createDecorationsHandle();
|
|
13822
14147
|
const viewport = {
|
|
13823
14148
|
getRects: async (input) => {
|
|
13824
14149
|
const initialHost = getHost();
|
|
@@ -14910,6 +15235,7 @@ function createSuperDocUI(options) {
|
|
|
14910
15235
|
const createScope = () => {
|
|
14911
15236
|
const scopeUnsubs = [];
|
|
14912
15237
|
return {
|
|
15238
|
+
decorations: createDecorationsHandle((handle) => scopeUnsubs.push(() => handle.dispose())),
|
|
14913
15239
|
select: (selector, equality) => {
|
|
14914
15240
|
const sub = select(selector, equality);
|
|
14915
15241
|
return {
|
|
@@ -14930,6 +15256,9 @@ function createSuperDocUI(options) {
|
|
|
14930
15256
|
if (disposed) return;
|
|
14931
15257
|
watermark.destroy();
|
|
14932
15258
|
clearContentControlHighlight();
|
|
15259
|
+
for (const handle of Array.from(liveDecorations.keys())) handle.dispose();
|
|
15260
|
+
detachDecorationPointer?.();
|
|
15261
|
+
decorationListeners.clear();
|
|
14933
15262
|
disposed = true;
|
|
14934
15263
|
completedFallbackSearch = null;
|
|
14935
15264
|
if (searchRefreshTimer !== null) clearTimeout(searchRefreshTimer);
|
|
@@ -15012,6 +15341,7 @@ function createSuperDocUI(options) {
|
|
|
15012
15341
|
zoom,
|
|
15013
15342
|
document: documentHandle,
|
|
15014
15343
|
viewport,
|
|
15344
|
+
decorations,
|
|
15015
15345
|
metadata,
|
|
15016
15346
|
tables,
|
|
15017
15347
|
search,
|
|
@@ -15230,4 +15560,4 @@ function commandIsActive(descriptor, selection) {
|
|
|
15230
15560
|
return descriptor.activeMark ? selection.activeMarks.includes(descriptor.activeMark) : false;
|
|
15231
15561
|
}
|
|
15232
15562
|
//#endregion
|
|
15233
|
-
export {
|
|
15563
|
+
export { createInteractionHistory as _, registerFirstPartyCommandMutation as a, recordInteraction as b, applyV2CommentInvalidationFromMutation as c, createImageFilePicker as d, resolveImageSrc as f, closeInteractionHistory as g, DOM_CLASS_NAMES as h, readFirstPartyPageNumbers as i, getV2TrackedChangeMutationImpact as l, isSyntheticTrackedChangeCommentLaneItem as m, executeFirstPartyCommandAsync as n, isRecord as o, shallowEqual as p, executeFirstPartyShortcutAsync as r, BUILT_IN_COMMAND_IDS as s, createSuperDocUI as t, isPlainObject as u, getWorkflowRecording as v, isWorkflowRecordingEnabled as y };
|