superdoc 2.0.0-next.26 → 2.0.0-next.28
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-CBs8xQUw.es.js → create-super-doc-ui-BlnUCtrx.es.js} +634 -115
- package/dist/chunks/{create-super-doc-ui-CHZKlLiH.cjs → create-super-doc-ui-CZBUMdjl.cjs} +634 -115
- package/dist/collaboration-upgrade-engine.cjs +1 -1
- package/dist/collaboration-upgrade-engine.es.js +1 -1
- package/dist/document-api/src/comments/comments.types.d.ts +9 -0
- package/dist/document-api/src/content-controls/content-controls.types.d.ts +13 -1
- package/dist/document-api/src/contract/operation-definitions.d.ts +2 -2
- package/dist/document-api/src/track-changes/track-changes.d.ts +6 -2
- package/dist/document-api/src/types/clipboard.d.ts +5 -1
- package/dist/document-api/src/types/table-operations.types.d.ts +6 -4
- package/dist/document-api/src/types/track-changes.types.d.ts +15 -0
- package/dist/layout-engine/contracts/src/incremental-dependency.d.ts +10 -0
- package/dist/layout-engine/contracts/src/index.d.ts +39 -0
- package/dist/layout-engine/layout-bridge/src/incrementalLayout.d.ts +23 -1
- package/dist/layout-engine/layout-engine/src/index.d.ts +17 -0
- package/dist/layout-engine/layout-engine/src/paginator.d.ts +16 -0
- package/dist/layout-engine/layout-engine/src/paragraph-layout-eligibility.d.ts +1 -4
- package/dist/layout-engine/style-engine/src/normalize/types.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.cjs +1 -1
- package/dist/public/ui.es.js +1 -1
- package/dist/style.css +119 -100
- package/dist/style.layered.css +119 -100
- package/dist/superdoc/src/components/CommentsLayer/collect-removed-comment-ids.d.ts +1 -0
- package/dist/superdoc/src/components/CommentsLayer/collect-tracked-change-thread.d.ts +1 -1
- package/dist/superdoc/src/components/CommentsLayer/tracked-change-threading.d.ts +2 -0
- package/dist/superdoc/src/core/types/index.d.ts +7 -0
- package/dist/superdoc/src/helpers/v2-remote-review-hydration.d.ts +12 -0
- package/dist/superdoc/src/public/ui/reasons.d.ts +8 -0
- package/dist/superdoc/src/stores/comments-store.d.ts +9 -9
- package/dist/superdoc/src/stores/helpers/floating-comment-instances.d.ts +2 -10
- package/dist/superdoc/src/stores/superdoc-store.d.ts +27 -27
- package/dist/superdoc.cjs +286 -82
- package/dist/superdoc.es.js +286 -82
- package/dist-cdn/style.layered.css +1 -1
- package/dist-cdn/superdoc.min.css +1 -1
- package/dist-cdn/superdoc.min.js +37 -37
- package/package.json +3 -2
package/dist/chunks/{create-super-doc-ui-CBs8xQUw.es.js → create-super-doc-ui-BlnUCtrx.es.js}
RENAMED
|
@@ -311,7 +311,8 @@ const SUPERDOC_UI_REASONS = {
|
|
|
311
311
|
historyEmpty: "history-empty",
|
|
312
312
|
searchUnavailable: "search-unavailable",
|
|
313
313
|
searchInvalidPattern: "search-invalid-pattern",
|
|
314
|
-
replaceUnsupported: "replace-unsupported"
|
|
314
|
+
replaceUnsupported: "replace-unsupported",
|
|
315
|
+
contentControlLocked: "content-control-locked"
|
|
315
316
|
};
|
|
316
317
|
const BUILT_IN_COMMAND_IDS = {
|
|
317
318
|
bold: "bold",
|
|
@@ -1393,6 +1394,17 @@ function readEntityId(row) {
|
|
|
1393
1394
|
const id = record.id ?? record.commentId ?? record.changeId;
|
|
1394
1395
|
return typeof id === "string" && id.length > 0 ? id : null;
|
|
1395
1396
|
}
|
|
1397
|
+
function readCollapsedHostTrackChangeId(snapshot) {
|
|
1398
|
+
if (!snapshot || typeof snapshot !== "object") return null;
|
|
1399
|
+
const record = snapshot;
|
|
1400
|
+
const anchor = record.anchor;
|
|
1401
|
+
const focus = record.focus;
|
|
1402
|
+
const anchorVisual = anchor?.visualCaret;
|
|
1403
|
+
const focusVisual = focus?.visualCaret;
|
|
1404
|
+
const anchorId = anchorVisual?.trackChangeId;
|
|
1405
|
+
const focusId = focusVisual?.trackChangeId;
|
|
1406
|
+
return typeof anchorId === "string" && anchorId.length > 0 && anchorId === focusId ? anchorId : null;
|
|
1407
|
+
}
|
|
1396
1408
|
var trackedChangeIdContextCache = /* @__PURE__ */ new WeakMap();
|
|
1397
1409
|
function readTrackChangeProvenanceIds(item) {
|
|
1398
1410
|
const out = [];
|
|
@@ -1543,12 +1555,11 @@ function paragraphTarget(blockId, story) {
|
|
|
1543
1555
|
...story && typeof story === "object" ? { story } : {}
|
|
1544
1556
|
};
|
|
1545
1557
|
}
|
|
1546
|
-
function listsBlockTarget(blockId
|
|
1558
|
+
function listsBlockTarget(blockId) {
|
|
1547
1559
|
return {
|
|
1548
1560
|
kind: "block",
|
|
1549
1561
|
nodeType: "paragraph",
|
|
1550
|
-
nodeId: blockId
|
|
1551
|
-
...story && typeof story === "object" ? { story } : {}
|
|
1562
|
+
nodeId: blockId
|
|
1552
1563
|
};
|
|
1553
1564
|
}
|
|
1554
1565
|
function listItemTarget(blockId, story) {
|
|
@@ -2295,6 +2306,40 @@ function createSuperDocUI(options) {
|
|
|
2295
2306
|
const host = getEditor()?.host;
|
|
2296
2307
|
return host && typeof host === "object" ? host : null;
|
|
2297
2308
|
};
|
|
2309
|
+
const resolveActiveHeaderFooterSlot = (story) => {
|
|
2310
|
+
if (story.storyType !== "headerFooterPart" || typeof story.refId !== "string") return null;
|
|
2311
|
+
const editor = getEditor();
|
|
2312
|
+
const host = getHost();
|
|
2313
|
+
const pageLayout = editor?.pageLayout ?? host?.pageLayout;
|
|
2314
|
+
if (!pageLayout || typeof pageLayout !== "object") return null;
|
|
2315
|
+
const getActiveRulerContext = pageLayout.getActiveRulerContext;
|
|
2316
|
+
const resolveEditTarget = host?.resolveHeaderFooterEditTarget;
|
|
2317
|
+
if (typeof getActiveRulerContext !== "function" || typeof resolveEditTarget !== "function") return null;
|
|
2318
|
+
const active = safeCall(() => getActiveRulerContext.call(pageLayout), null);
|
|
2319
|
+
if (!active || typeof active.pageIndex !== "number") return null;
|
|
2320
|
+
for (const headerFooterKind of ["header", "footer"]) {
|
|
2321
|
+
const resolved = safeCall(() => resolveEditTarget.call(host, {
|
|
2322
|
+
pageIndex: active.pageIndex,
|
|
2323
|
+
kind: headerFooterKind
|
|
2324
|
+
}), null);
|
|
2325
|
+
if (resolved?.status !== "ready" || resolved.refId !== story.refId || typeof resolved.sectionId !== "string" || ![
|
|
2326
|
+
"default",
|
|
2327
|
+
"first",
|
|
2328
|
+
"even"
|
|
2329
|
+
].includes(String(resolved.slotVariant))) continue;
|
|
2330
|
+
return {
|
|
2331
|
+
kind: "story",
|
|
2332
|
+
storyType: "headerFooterSlot",
|
|
2333
|
+
section: {
|
|
2334
|
+
kind: "section",
|
|
2335
|
+
sectionId: resolved.sectionId
|
|
2336
|
+
},
|
|
2337
|
+
headerFooterKind,
|
|
2338
|
+
variant: resolved.slotVariant
|
|
2339
|
+
};
|
|
2340
|
+
}
|
|
2341
|
+
return null;
|
|
2342
|
+
};
|
|
2298
2343
|
const readPendingInlineFormat = () => {
|
|
2299
2344
|
const host = getHost();
|
|
2300
2345
|
const fn = host?.getPendingInlineFormat;
|
|
@@ -2407,6 +2452,31 @@ function createSuperDocUI(options) {
|
|
|
2407
2452
|
let explicitActiveChange = null;
|
|
2408
2453
|
let explicitActiveChangeRevision = 0;
|
|
2409
2454
|
let queuedTrackChangeNavigationInvalidation = 0;
|
|
2455
|
+
const mirrorTrackedChangeFocusToHost = (next) => {
|
|
2456
|
+
const host = getHost();
|
|
2457
|
+
if (typeof host?.getHandles !== "function") return;
|
|
2458
|
+
const handles = safeCall(() => host.getHandles(), null);
|
|
2459
|
+
const review = handles?.review;
|
|
2460
|
+
if (!review) return;
|
|
2461
|
+
if (next) {
|
|
2462
|
+
if (typeof review.setActiveReviewTarget !== "function") return;
|
|
2463
|
+
const layout = handles?.layout;
|
|
2464
|
+
safeCall(() => review.setActiveReviewTarget({
|
|
2465
|
+
entityType: "trackedChange",
|
|
2466
|
+
entityId: next.id,
|
|
2467
|
+
...next.paintedEntityId ? { paintedEntityId: next.paintedEntityId } : {},
|
|
2468
|
+
origin: "panel",
|
|
2469
|
+
layoutEpoch: typeof layout?.generation === "number" ? layout.generation : 0,
|
|
2470
|
+
story: next.story ?? {
|
|
2471
|
+
kind: "story",
|
|
2472
|
+
storyType: "body"
|
|
2473
|
+
}
|
|
2474
|
+
}), null);
|
|
2475
|
+
return;
|
|
2476
|
+
}
|
|
2477
|
+
if (typeof review.getActiveReviewTarget !== "function" || typeof review.clearActiveReviewTarget !== "function") return;
|
|
2478
|
+
if (safeCall(() => review.getActiveReviewTarget(), null)?.entityType === "trackedChange") safeCall(() => review.clearActiveReviewTarget(), void 0);
|
|
2479
|
+
};
|
|
2410
2480
|
const setExplicitActiveChange = (next, options$1) => {
|
|
2411
2481
|
explicitActiveChange = next;
|
|
2412
2482
|
explicitActiveChangeRevision += 1;
|
|
@@ -2420,6 +2490,8 @@ function createSuperDocUI(options) {
|
|
|
2420
2490
|
let lastEffectiveInlineReadKey = null;
|
|
2421
2491
|
let pendingEffectiveInlineRead = null;
|
|
2422
2492
|
let asyncRefreshScheduled = false;
|
|
2493
|
+
let asyncReadFailureRetryTimer = null;
|
|
2494
|
+
let asyncReadFailureRetryAtMs = 0;
|
|
2423
2495
|
let foregroundAsyncRetryTimer = null;
|
|
2424
2496
|
let pendingSelectionSeedValidationToken = null;
|
|
2425
2497
|
let typingContentInvalidationTimer = null;
|
|
@@ -2434,6 +2506,19 @@ function createSuperDocUI(options) {
|
|
|
2434
2506
|
if (typeof queueMicrotask === "function") queueMicrotask(run);
|
|
2435
2507
|
else Promise.resolve().then(run);
|
|
2436
2508
|
};
|
|
2509
|
+
const ASYNC_READ_FAILURE_RETRY_BASE_MS = 250;
|
|
2510
|
+
const ASYNC_READ_FAILURE_RETRY_MAX_MS = 5e3;
|
|
2511
|
+
const scheduleAsyncReadFailureRetry = (retryAtMs) => {
|
|
2512
|
+
if (disposed) return;
|
|
2513
|
+
if (asyncReadFailureRetryTimer && asyncReadFailureRetryAtMs <= retryAtMs) return;
|
|
2514
|
+
if (asyncReadFailureRetryTimer) clearTimeout(asyncReadFailureRetryTimer);
|
|
2515
|
+
asyncReadFailureRetryAtMs = retryAtMs;
|
|
2516
|
+
asyncReadFailureRetryTimer = setTimeout(() => {
|
|
2517
|
+
asyncReadFailureRetryTimer = null;
|
|
2518
|
+
asyncReadFailureRetryAtMs = 0;
|
|
2519
|
+
if (!disposed) recompute();
|
|
2520
|
+
}, Math.max(0, retryAtMs - Date.now()));
|
|
2521
|
+
};
|
|
2437
2522
|
const editorIdentityIds = /* @__PURE__ */ new WeakMap();
|
|
2438
2523
|
let editorIdentityCounter = 0;
|
|
2439
2524
|
const editorIdentityId = (editor) => {
|
|
@@ -2653,7 +2738,7 @@ function createSuperDocUI(options) {
|
|
|
2653
2738
|
recompute();
|
|
2654
2739
|
}
|
|
2655
2740
|
});
|
|
2656
|
-
const selectionReadToken = () => `${contentToken()}|s${selectionEpoch}`;
|
|
2741
|
+
const selectionReadToken = () => `${contentToken()}|m${readDocumentMode()}|s${selectionEpoch}`;
|
|
2657
2742
|
const selectionSignature = (selection$1) => JSON.stringify({
|
|
2658
2743
|
t: selection$1.target ?? null,
|
|
2659
2744
|
s: selection$1.selectionTarget ?? null
|
|
@@ -2670,7 +2755,7 @@ function createSuperDocUI(options) {
|
|
|
2670
2755
|
const read = host?.getDocumentLoadingSnapshot;
|
|
2671
2756
|
if (typeof read !== "function") return "unknown";
|
|
2672
2757
|
const stage = safeCall(() => read.call(host), null)?.sourceStage;
|
|
2673
|
-
if (stage === "source-loading") return "loading";
|
|
2758
|
+
if (stage === "opening" || stage === "ready-window" || stage === "source-loading") return "loading";
|
|
2674
2759
|
if (stage === "source-complete" || stage === "source-failed" || stage === "source-cancelled") return "complete";
|
|
2675
2760
|
return "unknown";
|
|
2676
2761
|
};
|
|
@@ -2836,17 +2921,24 @@ function createSuperDocUI(options) {
|
|
|
2836
2921
|
token,
|
|
2837
2922
|
value: normalize(raw),
|
|
2838
2923
|
hasSettled: true,
|
|
2839
|
-
inflightToken: null
|
|
2924
|
+
inflightToken: null,
|
|
2925
|
+
failedToken: null,
|
|
2926
|
+
failureCount: 0,
|
|
2927
|
+
retryAtMs: 0
|
|
2840
2928
|
};
|
|
2841
2929
|
asyncReads.set(key, settled);
|
|
2842
2930
|
return settled;
|
|
2843
2931
|
}
|
|
2844
2932
|
const prev = asyncReads.get(key);
|
|
2933
|
+
const retryingSameToken = prev?.failedToken === token;
|
|
2845
2934
|
asyncReads.set(key, {
|
|
2846
2935
|
token: prev?.token ?? null,
|
|
2847
2936
|
value: prev?.value ?? null,
|
|
2848
2937
|
hasSettled: prev?.hasSettled ?? false,
|
|
2849
|
-
inflightToken: token
|
|
2938
|
+
inflightToken: token,
|
|
2939
|
+
failedToken: retryingSameToken ? token : null,
|
|
2940
|
+
failureCount: retryingSameToken ? prev.failureCount ?? 0 : 0,
|
|
2941
|
+
retryAtMs: 0
|
|
2850
2942
|
});
|
|
2851
2943
|
Promise.resolve(raw).then((resolved) => {
|
|
2852
2944
|
const entry = asyncReads.get(key);
|
|
@@ -2855,17 +2947,26 @@ function createSuperDocUI(options) {
|
|
|
2855
2947
|
token,
|
|
2856
2948
|
value: normalize(resolved),
|
|
2857
2949
|
hasSettled: true,
|
|
2858
|
-
inflightToken: null
|
|
2950
|
+
inflightToken: null,
|
|
2951
|
+
failedToken: null,
|
|
2952
|
+
failureCount: 0,
|
|
2953
|
+
retryAtMs: 0
|
|
2859
2954
|
});
|
|
2860
2955
|
scheduleAsyncRefresh();
|
|
2861
2956
|
}, () => {
|
|
2862
2957
|
const entry = asyncReads.get(key);
|
|
2863
2958
|
if (!entry || entry.inflightToken !== token) return;
|
|
2959
|
+
const failureCount = entry.failedToken === token ? (entry.failureCount ?? 0) + 1 : 1;
|
|
2960
|
+
const retryDelayMs = Math.min(ASYNC_READ_FAILURE_RETRY_MAX_MS, ASYNC_READ_FAILURE_RETRY_BASE_MS * 2 ** Math.min(failureCount - 1, 8));
|
|
2961
|
+
const retryAtMs = Date.now() + retryDelayMs;
|
|
2864
2962
|
asyncReads.set(key, {
|
|
2865
2963
|
...entry,
|
|
2866
|
-
inflightToken: null
|
|
2964
|
+
inflightToken: null,
|
|
2965
|
+
failedToken: token,
|
|
2966
|
+
failureCount,
|
|
2967
|
+
retryAtMs
|
|
2867
2968
|
});
|
|
2868
|
-
|
|
2969
|
+
scheduleAsyncReadFailureRetry(retryAtMs);
|
|
2869
2970
|
});
|
|
2870
2971
|
return null;
|
|
2871
2972
|
};
|
|
@@ -2926,6 +3027,17 @@ function createSuperDocUI(options) {
|
|
|
2926
3027
|
status: "pending"
|
|
2927
3028
|
};
|
|
2928
3029
|
}
|
|
3030
|
+
if (entry?.failedToken === token && entry.inflightToken == null && (entry.retryAtMs ?? 0) > Date.now()) {
|
|
3031
|
+
scheduleAsyncReadFailureRetry(entry.retryAtMs);
|
|
3032
|
+
if (entry.hasSettled) return {
|
|
3033
|
+
value: entry.value,
|
|
3034
|
+
status: "stale"
|
|
3035
|
+
};
|
|
3036
|
+
return {
|
|
3037
|
+
value: null,
|
|
3038
|
+
status: "pending"
|
|
3039
|
+
};
|
|
3040
|
+
}
|
|
2929
3041
|
if (!entry && key.startsWith("effInline:") && shouldDeferEffectiveInlineRead(key)) return {
|
|
2930
3042
|
value: null,
|
|
2931
3043
|
status: "pending"
|
|
@@ -2977,6 +3089,9 @@ function createSuperDocUI(options) {
|
|
|
2977
3089
|
reviewMutationReconciler.reset();
|
|
2978
3090
|
lastCoordinatorEditor = editor;
|
|
2979
3091
|
asyncReads.clear();
|
|
3092
|
+
if (asyncReadFailureRetryTimer) clearTimeout(asyncReadFailureRetryTimer);
|
|
3093
|
+
asyncReadFailureRetryTimer = null;
|
|
3094
|
+
asyncReadFailureRetryAtMs = 0;
|
|
2980
3095
|
if (pendingEffectiveInlineRead?.timer) clearTimeout(pendingEffectiveInlineRead.timer);
|
|
2981
3096
|
pendingEffectiveInlineRead = null;
|
|
2982
3097
|
lastEffectiveInlineReadKey = null;
|
|
@@ -3094,14 +3209,15 @@ function createSuperDocUI(options) {
|
|
|
3094
3209
|
const end = target?.end;
|
|
3095
3210
|
return start?.kind === "text" && end?.kind === "text" && typeof start.blockId === "string" && start.blockId === end.blockId && typeof start.offset === "number" && start.offset === end.offset;
|
|
3096
3211
|
};
|
|
3097
|
-
const seedCaretSelectionFromHost = () => {
|
|
3212
|
+
const seedCaretSelectionFromHost = (hostSelectionSnapshot) => {
|
|
3098
3213
|
const host = getHost();
|
|
3099
3214
|
const read = host?.readLiveSelectionSyncSnapshot;
|
|
3100
3215
|
if (typeof read !== "function") return;
|
|
3101
3216
|
const seed = normalizeSelectionInfo(safeCall(() => read.call(host), null));
|
|
3102
3217
|
if (!seed || !isCollapsedCaretSnapshot(seed)) return;
|
|
3103
3218
|
const token = selectionReadToken();
|
|
3104
|
-
const
|
|
3219
|
+
const foreground = foregroundMutationState();
|
|
3220
|
+
const deferAuthoritativeRead = Boolean(foreground && (foreground.active > 0 || foreground.pending > 0));
|
|
3105
3221
|
if (!deferAuthoritativeRead) {
|
|
3106
3222
|
pendingSelectionSeedValidationToken = null;
|
|
3107
3223
|
if (issueAsyncRead("selection", token, selectionCurrentRun, normalizeSelectionInfo)) return;
|
|
@@ -3111,11 +3227,22 @@ function createSuperDocUI(options) {
|
|
|
3111
3227
|
}
|
|
3112
3228
|
const prev = asyncReads.get("selection");
|
|
3113
3229
|
const seedMarks = Array.isArray(seed.activeMarks) && seed.activeMarks.length > 0 ? seed.activeMarks : Array.isArray(state.selection.activeMarks) ? state.selection.activeMarks : [];
|
|
3230
|
+
const seedCommentIds = Array.isArray(seed.activeCommentIds) ? seed.activeCommentIds : [];
|
|
3231
|
+
const paintedTrackChangeId = readCollapsedHostTrackChangeId(hostSelectionSnapshot);
|
|
3232
|
+
const previousCaret = collapsedTextAddressFromSelection(state.selection);
|
|
3233
|
+
const nextCaret = collapsedTextAddressFromTarget(seed.selectionTarget) ?? collapsedTextAddressFromTarget(seed.target);
|
|
3234
|
+
const previousRange = previousCaret?.range;
|
|
3235
|
+
const nextRange = nextCaret?.range;
|
|
3236
|
+
const sameActiveTypingCaret = Boolean(foreground && foreground.active > 0 && previousCaret && nextCaret && previousCaret.blockId === nextCaret.blockId && storyLocatorSignature(previousCaret.story) === storyLocatorSignature(nextCaret.story) && typeof previousRange?.start === "number" && typeof nextRange?.start === "number" && Math.abs(nextRange.start - previousRange.start) <= 2);
|
|
3237
|
+
const carriedChangeIds = paintedTrackChangeId != null || sameActiveTypingCaret ? state.selection.activeChangeIds.filter((id) => paintedTrackChangeId == null || buildTrackedChangeIdContext(state.trackChanges.items).aliasesFor(id).includes(paintedTrackChangeId)) : [];
|
|
3238
|
+
const seedChangeIds = Array.isArray(seed.activeChangeIds) && seed.activeChangeIds.length > 0 ? seed.activeChangeIds : carriedChangeIds;
|
|
3114
3239
|
asyncReads.set("selection", {
|
|
3115
3240
|
token,
|
|
3116
3241
|
value: {
|
|
3117
3242
|
...seed,
|
|
3118
|
-
activeMarks: seedMarks
|
|
3243
|
+
activeMarks: seedMarks,
|
|
3244
|
+
activeCommentIds: seedCommentIds,
|
|
3245
|
+
activeChangeIds: seedChangeIds
|
|
3119
3246
|
},
|
|
3120
3247
|
hasSettled: true,
|
|
3121
3248
|
inflightToken: deferAuthoritativeRead ? null : prev?.inflightToken ?? null
|
|
@@ -3228,22 +3355,29 @@ function createSuperDocUI(options) {
|
|
|
3228
3355
|
activeIds
|
|
3229
3356
|
};
|
|
3230
3357
|
};
|
|
3231
|
-
const
|
|
3358
|
+
const computeActiveContentControlLockModes = (ccApi, selection$1) => {
|
|
3232
3359
|
if (!ccApi || typeof ccApi.listInRange !== "function") return {
|
|
3233
|
-
|
|
3360
|
+
lockModesById: /* @__PURE__ */ new Map(),
|
|
3234
3361
|
status: "ready"
|
|
3235
3362
|
};
|
|
3236
3363
|
const range = selectionBlockRange(selection$1);
|
|
3237
3364
|
if (!range) return {
|
|
3238
|
-
|
|
3365
|
+
lockModesById: /* @__PURE__ */ new Map(),
|
|
3239
3366
|
status: "ready"
|
|
3240
3367
|
};
|
|
3241
3368
|
const { value, status } = readAsync(`contentControls:inRange:${selectionSignature(selection$1)}`, contentToken(), () => ccApi.listInRange(range), (raw) => raw && Array.isArray(raw.items) ? raw.items : []);
|
|
3242
3369
|
const rows = value ?? [];
|
|
3243
|
-
const
|
|
3244
|
-
for (const row of rows) if (typeof row?.id === "string")
|
|
3370
|
+
const lockModesById = /* @__PURE__ */ new Map();
|
|
3371
|
+
for (const row of rows) if (typeof row?.id === "string") lockModesById.set(row.id, typeof row.lockMode === "string" ? row.lockMode : "unlocked");
|
|
3372
|
+
return {
|
|
3373
|
+
lockModesById,
|
|
3374
|
+
status
|
|
3375
|
+
};
|
|
3376
|
+
};
|
|
3377
|
+
const computeActiveContentControlIds = (ccApi, selection$1) => {
|
|
3378
|
+
const { lockModesById, status } = computeActiveContentControlLockModes(ccApi, selection$1);
|
|
3245
3379
|
return {
|
|
3246
|
-
ids,
|
|
3380
|
+
ids: [...lockModesById.keys()],
|
|
3247
3381
|
status
|
|
3248
3382
|
};
|
|
3249
3383
|
};
|
|
@@ -3559,14 +3693,20 @@ function createSuperDocUI(options) {
|
|
|
3559
3693
|
frozenProjectedValues = projectedInlineValues;
|
|
3560
3694
|
frozenProjectedValuesKey = `${selectionKey(selection$1)}:${contentToken()}`;
|
|
3561
3695
|
}
|
|
3696
|
+
const ccApi = doc?.contentControls;
|
|
3697
|
+
const { lockModesById } = computeActiveContentControlLockModes(ccApi, selection$1);
|
|
3562
3698
|
const states = {};
|
|
3563
|
-
for (const id of allCommandIds()) states[id] = computeCommandState(id, doc, selection$1, projectedInlineValues);
|
|
3699
|
+
for (const id of allCommandIds()) states[id] = computeCommandState(id, doc, selection$1, projectedInlineValues, lockModesById);
|
|
3564
3700
|
return states;
|
|
3565
3701
|
};
|
|
3566
3702
|
const unavailableRouteReason = (doc) => {
|
|
3567
3703
|
if (doc) return SUPERDOC_UI_REASONS.operationUnavailable;
|
|
3568
3704
|
return getEditor() ? SUPERDOC_UI_REASONS.documentApiUnavailable : SUPERDOC_UI_REASONS.notReady;
|
|
3569
3705
|
};
|
|
3706
|
+
const blocksContentStyling = (lockMode) => lockMode === "contentLocked" || lockMode === "sdtContentLocked";
|
|
3707
|
+
const contentControlLockReason = (lockModesById) => {
|
|
3708
|
+
for (const lockMode of lockModesById.values()) if (blocksContentStyling(lockMode)) return SUPERDOC_UI_REASONS.contentControlLocked;
|
|
3709
|
+
};
|
|
3570
3710
|
const trackDecisionReason = (command, supported, readonly, selection$1, doc) => {
|
|
3571
3711
|
if (!supported) return command.scope === "all" ? SUPERDOC_UI_REASONS.bulkDecisionsDisabled : unavailableRouteReason(doc);
|
|
3572
3712
|
if (readonly) return SUPERDOC_UI_REASONS.documentReadonly;
|
|
@@ -3589,7 +3729,7 @@ function createSuperDocUI(options) {
|
|
|
3589
3729
|
if (support && (support.status === "supported" || support.enabled === true)) return void 0;
|
|
3590
3730
|
return SUPERDOC_UI_REASONS.bulkDecisionsDisabled;
|
|
3591
3731
|
};
|
|
3592
|
-
const computeCommandState = (id, doc, selection$1, projectedInlineValues) => {
|
|
3732
|
+
const computeCommandState = (id, doc, selection$1, projectedInlineValues, lockModesById = /* @__PURE__ */ new Map()) => {
|
|
3593
3733
|
if (customCommands.has(id)) return normalizeCommandState({
|
|
3594
3734
|
supported: true,
|
|
3595
3735
|
enabled: true,
|
|
@@ -3664,6 +3804,13 @@ function createSuperDocUI(options) {
|
|
|
3664
3804
|
supported: true,
|
|
3665
3805
|
reason: SUPERDOC_UI_REASONS.documentReadonly
|
|
3666
3806
|
}, "builtin");
|
|
3807
|
+
const lockReason = contentControlLockReason(lockModesById);
|
|
3808
|
+
if (lockReason) return normalizeCommandState({
|
|
3809
|
+
enabled: false,
|
|
3810
|
+
active: false,
|
|
3811
|
+
supported: true,
|
|
3812
|
+
reason: lockReason
|
|
3813
|
+
}, "builtin");
|
|
3667
3814
|
const enabled = selectionBlockIds(selection$1).length > 0 || resolveInlineSelectionTarget(selection$1) != null;
|
|
3668
3815
|
return normalizeCommandState({
|
|
3669
3816
|
enabled,
|
|
@@ -3706,6 +3853,7 @@ function createSuperDocUI(options) {
|
|
|
3706
3853
|
const active = commandActiveState(descriptor, doc, selection$1);
|
|
3707
3854
|
const value = routedCommandValue(descriptor, doc, selection$1, projectedInlineValues);
|
|
3708
3855
|
if (descriptor.list?.mode === "indent" || descriptor.list?.mode === "outdent") return computeHybridIndentCommandState(descriptor, doc, readonly, selection$1, active, value);
|
|
3856
|
+
if (descriptor.list?.mode === "toggle-seed") return computeListToggleCommandState(descriptor, doc, readonly, selection$1, active, value);
|
|
3709
3857
|
if (descriptor.mutates && readonly) return normalizeCommandState({
|
|
3710
3858
|
enabled: false,
|
|
3711
3859
|
active,
|
|
@@ -3713,18 +3861,28 @@ function createSuperDocUI(options) {
|
|
|
3713
3861
|
value,
|
|
3714
3862
|
reason: SUPERDOC_UI_REASONS.documentReadonly
|
|
3715
3863
|
}, "builtin");
|
|
3716
|
-
if (descriptor.inline && !resolveInlineSelectionTarget(selection$1))
|
|
3717
|
-
|
|
3718
|
-
|
|
3719
|
-
|
|
3720
|
-
|
|
3721
|
-
|
|
3722
|
-
|
|
3723
|
-
|
|
3724
|
-
|
|
3725
|
-
|
|
3726
|
-
|
|
3727
|
-
|
|
3864
|
+
if (descriptor.inline && !resolveInlineSelectionTarget(selection$1)) {
|
|
3865
|
+
const lockReason = contentControlLockReason(lockModesById);
|
|
3866
|
+
if (lockReason) return normalizeCommandState({
|
|
3867
|
+
enabled: false,
|
|
3868
|
+
active,
|
|
3869
|
+
supported: true,
|
|
3870
|
+
value,
|
|
3871
|
+
reason: lockReason
|
|
3872
|
+
}, "builtin");
|
|
3873
|
+
return normalizeCommandState(selectionBlockIds(selection$1).length > 0 && typeof getHost()?.setPendingInlineFormat === "function" ? {
|
|
3874
|
+
enabled: true,
|
|
3875
|
+
active,
|
|
3876
|
+
supported: true,
|
|
3877
|
+
value
|
|
3878
|
+
} : {
|
|
3879
|
+
enabled: false,
|
|
3880
|
+
active,
|
|
3881
|
+
supported: true,
|
|
3882
|
+
value,
|
|
3883
|
+
reason: SUPERDOC_UI_REASONS.rangeSelectionRequired
|
|
3884
|
+
}, "builtin");
|
|
3885
|
+
}
|
|
3728
3886
|
if ((descriptor.blockParagraph || descriptor.list) && selectionBlockIds(selection$1).length === 0) return normalizeCommandState({
|
|
3729
3887
|
enabled: false,
|
|
3730
3888
|
active,
|
|
@@ -3738,6 +3896,16 @@ function createSuperDocUI(options) {
|
|
|
3738
3896
|
supported: true,
|
|
3739
3897
|
reason: SUPERDOC_UI_REASONS.rangeSelectionRequired
|
|
3740
3898
|
}, "builtin");
|
|
3899
|
+
if (descriptor.inline) {
|
|
3900
|
+
const lockReason = contentControlLockReason(lockModesById);
|
|
3901
|
+
if (lockReason) return normalizeCommandState({
|
|
3902
|
+
enabled: false,
|
|
3903
|
+
active,
|
|
3904
|
+
supported: true,
|
|
3905
|
+
value,
|
|
3906
|
+
reason: lockReason
|
|
3907
|
+
}, "builtin");
|
|
3908
|
+
}
|
|
3741
3909
|
return normalizeCommandState({
|
|
3742
3910
|
enabled: true,
|
|
3743
3911
|
active,
|
|
@@ -3822,47 +3990,81 @@ function createSuperDocUI(options) {
|
|
|
3822
3990
|
}
|
|
3823
3991
|
if (descriptor.id === "link") return readActiveLinkHref(doc, selection$1) ?? void 0;
|
|
3824
3992
|
};
|
|
3825
|
-
const
|
|
3993
|
+
const readListStateSnapshotForBlock = (doc, blockId, story) => {
|
|
3826
3994
|
const listsApi = doc?.lists;
|
|
3827
|
-
if (!listsApi
|
|
3828
|
-
|
|
3829
|
-
|
|
3995
|
+
if (!listsApi) return {
|
|
3996
|
+
value: null,
|
|
3997
|
+
status: "ready"
|
|
3998
|
+
};
|
|
3999
|
+
const isBodyStory = story.storyType === "body";
|
|
4000
|
+
const readState = typeof listsApi.getStateInStory === "function" ? () => listsApi.getStateInStory({
|
|
4001
|
+
target: listsBlockTarget(blockId),
|
|
4002
|
+
story
|
|
4003
|
+
}) : isBodyStory && typeof listsApi.getState === "function" ? () => listsApi.getState({ target: listsBlockTarget(blockId) }) : null;
|
|
4004
|
+
if (!readState) return {
|
|
4005
|
+
value: null,
|
|
4006
|
+
status: "ready"
|
|
4007
|
+
};
|
|
4008
|
+
const { value: result, status } = readAsync(`lists:${storyLocatorSignature(story)}:${blockId}`, contentToken(), readState, (raw) => raw && typeof raw === "object" ? raw : null);
|
|
4009
|
+
return {
|
|
4010
|
+
value: result?.success === true ? result : null,
|
|
4011
|
+
status
|
|
4012
|
+
};
|
|
3830
4013
|
};
|
|
3831
|
-
const
|
|
3832
|
-
|
|
4014
|
+
const readListStateForBlock = (doc, blockId, story) => {
|
|
4015
|
+
return readListStateSnapshotForBlock(doc, blockId, story).value;
|
|
4016
|
+
};
|
|
4017
|
+
const readListSeedForBlock = (doc, blockId, story) => {
|
|
4018
|
+
const result = readListStateForBlock(doc, blockId, story);
|
|
3833
4019
|
if (!result || result.isListItem !== true) return null;
|
|
3834
4020
|
return result.seed === "bullet" || result.seed === "ordered" ? result.seed : null;
|
|
3835
4021
|
};
|
|
3836
|
-
const
|
|
3837
|
-
const
|
|
3838
|
-
|
|
4022
|
+
const readListMembershipSnapshotForBlock = (doc, blockId, story) => {
|
|
4023
|
+
const snapshot = readListStateSnapshotForBlock(doc, blockId, story);
|
|
4024
|
+
const result = snapshot.value;
|
|
4025
|
+
return {
|
|
4026
|
+
value: result && typeof result.isListItem === "boolean" ? result.isListItem : null,
|
|
4027
|
+
status: snapshot.status
|
|
4028
|
+
};
|
|
3839
4029
|
};
|
|
3840
4030
|
const readListSeed = (doc, selection$1) => {
|
|
3841
4031
|
const blockIds = selectionBlockIds(selection$1);
|
|
3842
4032
|
if (blockIds.length === 0 || !canProbeEverySelectedBlock(blockIds)) return null;
|
|
3843
|
-
const
|
|
4033
|
+
const story = selectionStory(selection$1);
|
|
4034
|
+
const firstSeed = readListSeedForBlock(doc, blockIds[0], story);
|
|
3844
4035
|
if (firstSeed !== "bullet" && firstSeed !== "ordered") return null;
|
|
3845
|
-
for (const blockId of blockIds.slice(1)) if (readListSeedForBlock(doc, blockId) !== firstSeed) return null;
|
|
4036
|
+
for (const blockId of blockIds.slice(1)) if (readListSeedForBlock(doc, blockId, story) !== firstSeed) return null;
|
|
3846
4037
|
return firstSeed;
|
|
3847
4038
|
};
|
|
3848
|
-
const readNodeById = (doc, blockId) => {
|
|
3849
|
-
if (!doc
|
|
4039
|
+
const readNodeById = (doc, blockId, story) => {
|
|
4040
|
+
if (!doc) return {
|
|
4041
|
+
value: null,
|
|
4042
|
+
status: "ready"
|
|
4043
|
+
};
|
|
4044
|
+
const storySignature = storyLocatorSignature(story);
|
|
4045
|
+
const isBodyStory = storySignature === "story:body";
|
|
4046
|
+
if (isBodyStory && typeof doc.getNodeById !== "function") return {
|
|
4047
|
+
value: null,
|
|
4048
|
+
status: "ready"
|
|
4049
|
+
};
|
|
4050
|
+
if (!isBodyStory && typeof doc.getNode !== "function") return {
|
|
3850
4051
|
value: null,
|
|
3851
4052
|
status: "ready"
|
|
3852
4053
|
};
|
|
3853
|
-
return readAsync(`node:${blockId}`, contentToken(), () => doc.getNodeById({
|
|
4054
|
+
return readAsync(`node:${storySignature}:${blockId}`, contentToken(), () => isBodyStory ? doc.getNodeById({
|
|
3854
4055
|
nodeId: blockId,
|
|
3855
4056
|
nodeType: "paragraph"
|
|
3856
|
-
}), (raw) => raw && typeof raw === "object" ? raw : null);
|
|
4057
|
+
}) : doc.getNode(paragraphTarget(blockId, story)), (raw) => raw && typeof raw === "object" ? raw : null);
|
|
3857
4058
|
};
|
|
3858
4059
|
const resolveListMembershipForBlockAsync = async (doc, blockId, story) => {
|
|
3859
4060
|
const listsApi = doc?.lists;
|
|
3860
4061
|
if (!listsApi) return null;
|
|
3861
4062
|
try {
|
|
4063
|
+
const isBodyStory = story.storyType === "body";
|
|
3862
4064
|
const raw = typeof listsApi.getStateInStory === "function" ? await listsApi.getStateInStory({
|
|
3863
4065
|
target: listsBlockTarget(blockId),
|
|
3864
4066
|
story
|
|
3865
|
-
}) : typeof listsApi.getState === "function" ? await listsApi.getState({ target: listsBlockTarget(blockId) }) : null;
|
|
4067
|
+
}) : isBodyStory && typeof listsApi.getState === "function" ? await listsApi.getState({ target: listsBlockTarget(blockId) }) : null;
|
|
3866
4068
|
const result = raw && typeof raw === "object" ? raw : null;
|
|
3867
4069
|
if (!result || result.success !== true || typeof result.isListItem !== "boolean") return null;
|
|
3868
4070
|
return result.isListItem;
|
|
@@ -3870,13 +4072,42 @@ function createSuperDocUI(options) {
|
|
|
3870
4072
|
return null;
|
|
3871
4073
|
}
|
|
3872
4074
|
};
|
|
3873
|
-
const
|
|
3874
|
-
|
|
4075
|
+
const resolveListSeedForBlock = (doc, blockId, story) => {
|
|
4076
|
+
const unavailable = {
|
|
4077
|
+
resolved: false,
|
|
4078
|
+
seed: null
|
|
4079
|
+
};
|
|
4080
|
+
const listsApi = doc?.lists;
|
|
4081
|
+
if (!listsApi) return unavailable;
|
|
4082
|
+
const isBodyStory = story.storyType === "body";
|
|
4083
|
+
const readState = typeof listsApi.getStateInStory === "function" ? () => listsApi.getStateInStory({
|
|
4084
|
+
target: listsBlockTarget(blockId),
|
|
4085
|
+
story
|
|
4086
|
+
}) : isBodyStory && typeof listsApi.getState === "function" ? () => listsApi.getState({ target: listsBlockTarget(blockId) }) : null;
|
|
4087
|
+
if (!readState) return unavailable;
|
|
4088
|
+
const normalize = (raw) => {
|
|
4089
|
+
const result = raw && typeof raw === "object" ? raw : null;
|
|
4090
|
+
if (!result || result.success !== true || typeof result.isListItem !== "boolean") return unavailable;
|
|
4091
|
+
return {
|
|
4092
|
+
resolved: true,
|
|
4093
|
+
seed: result.isListItem === true && (result.seed === "bullet" || result.seed === "ordered") ? result.seed : null
|
|
4094
|
+
};
|
|
4095
|
+
};
|
|
4096
|
+
try {
|
|
4097
|
+
const raw = readState();
|
|
4098
|
+
return isPromiseLike(raw) ? Promise.resolve(raw).then(normalize, () => unavailable) : normalize(raw);
|
|
4099
|
+
} catch {
|
|
4100
|
+
return unavailable;
|
|
4101
|
+
}
|
|
4102
|
+
};
|
|
4103
|
+
const resolveParagraphIndentationForBlockAsync = async (doc, blockId, story) => {
|
|
4104
|
+
if (!doc) return null;
|
|
3875
4105
|
try {
|
|
3876
|
-
const
|
|
4106
|
+
const isBodyStory = !story || story.storyType === "body";
|
|
4107
|
+
const raw = story && typeof doc.getNode === "function" ? await doc.getNode(paragraphTarget(blockId, story)) : isBodyStory && typeof doc.getNodeById === "function" ? await doc.getNodeById({
|
|
3877
4108
|
nodeId: blockId,
|
|
3878
4109
|
nodeType: "paragraph"
|
|
3879
|
-
});
|
|
4110
|
+
}) : null;
|
|
3880
4111
|
return readParagraphIndentationFromResult(raw && typeof raw === "object" ? raw : null);
|
|
3881
4112
|
} catch {
|
|
3882
4113
|
return null;
|
|
@@ -3901,9 +4132,50 @@ function createSuperDocUI(options) {
|
|
|
3901
4132
|
const listOp = descriptor.docRoute ? resolveDocOperation(doc, descriptor.docRoute) : null;
|
|
3902
4133
|
const paragraphSetIndent = resolveDocOperation(doc, "format.paragraph.setIndentation");
|
|
3903
4134
|
const paragraphClearIndent = resolveDocOperation(doc, "format.paragraph.clearIndentation");
|
|
3904
|
-
const
|
|
3905
|
-
|
|
3906
|
-
|
|
4135
|
+
const mode = descriptor.list?.mode;
|
|
4136
|
+
const paragraphOpAvailable = mode === "indent" ? paragraphSetIndent != null : paragraphSetIndent != null || paragraphClearIndent != null;
|
|
4137
|
+
const story = selectionStory(selection$1);
|
|
4138
|
+
let listMembership = null;
|
|
4139
|
+
if (story.storyType !== "body") {
|
|
4140
|
+
listMembership = [];
|
|
4141
|
+
for (const blockId of blockIds) {
|
|
4142
|
+
const { value: isListItem, status } = readListMembershipSnapshotForBlock(doc, blockId, story);
|
|
4143
|
+
if (isListItem === null) {
|
|
4144
|
+
if (status !== "ready" && (listOp != null || paragraphOpAvailable)) return normalizeCommandState({
|
|
4145
|
+
enabled: true,
|
|
4146
|
+
active,
|
|
4147
|
+
supported: true,
|
|
4148
|
+
value
|
|
4149
|
+
}, "builtin");
|
|
4150
|
+
return normalizeCommandState({
|
|
4151
|
+
enabled: false,
|
|
4152
|
+
active,
|
|
4153
|
+
supported: false,
|
|
4154
|
+
value,
|
|
4155
|
+
reason: unavailableRouteReason(doc)
|
|
4156
|
+
}, "builtin");
|
|
4157
|
+
}
|
|
4158
|
+
listMembership.push(isListItem);
|
|
4159
|
+
}
|
|
4160
|
+
}
|
|
4161
|
+
if (listMembership?.some((isListItem) => isListItem === true)) {
|
|
4162
|
+
const rangeRoute = mode === "indent" ? "lists.indentRange" : "lists.outdentRange";
|
|
4163
|
+
const canUseRange = readDocumentMode() !== "suggesting" && listMembership.every((isListItem) => isListItem === true) && resolveDocOperation(doc, rangeRoute) != null;
|
|
4164
|
+
const canUseStoryOutdent = mode === "outdent" && resolveDocOperation(doc, "lists.outdentInStory") != null;
|
|
4165
|
+
if (!canUseRange && !canUseStoryOutdent) return normalizeCommandState({
|
|
4166
|
+
enabled: false,
|
|
4167
|
+
active,
|
|
4168
|
+
supported: false,
|
|
4169
|
+
value,
|
|
4170
|
+
reason: unavailableRouteReason(doc)
|
|
4171
|
+
}, "builtin");
|
|
4172
|
+
}
|
|
4173
|
+
for (const [index, blockId] of blockIds.entries()) {
|
|
4174
|
+
const membership = listMembership ? {
|
|
4175
|
+
value: listMembership[index] ?? null,
|
|
4176
|
+
status: "ready"
|
|
4177
|
+
} : readListMembershipSnapshotForBlock(doc, blockId, story);
|
|
4178
|
+
const isListItem = membership.value;
|
|
3907
4179
|
if (isListItem === true) {
|
|
3908
4180
|
if (listOp != null) return normalizeCommandState({
|
|
3909
4181
|
enabled: true,
|
|
@@ -3913,18 +4185,30 @@ function createSuperDocUI(options) {
|
|
|
3913
4185
|
}, "builtin");
|
|
3914
4186
|
continue;
|
|
3915
4187
|
}
|
|
3916
|
-
if (isListItem === false && paragraphOpAvailable)
|
|
3917
|
-
|
|
3918
|
-
|
|
3919
|
-
|
|
3920
|
-
|
|
3921
|
-
|
|
3922
|
-
|
|
3923
|
-
|
|
3924
|
-
|
|
3925
|
-
|
|
3926
|
-
|
|
3927
|
-
|
|
4188
|
+
if (isListItem === false && paragraphOpAvailable) {
|
|
4189
|
+
if (story.storyType !== "body" && typeof doc?.getNode !== "function") continue;
|
|
4190
|
+
return normalizeCommandState({
|
|
4191
|
+
enabled: true,
|
|
4192
|
+
active,
|
|
4193
|
+
supported: true,
|
|
4194
|
+
value
|
|
4195
|
+
}, "builtin");
|
|
4196
|
+
}
|
|
4197
|
+
if (isListItem === null) {
|
|
4198
|
+
if (membership.status !== "ready" && (listOp != null || paragraphOpAvailable)) return normalizeCommandState({
|
|
4199
|
+
enabled: true,
|
|
4200
|
+
active,
|
|
4201
|
+
supported: true,
|
|
4202
|
+
value
|
|
4203
|
+
}, "builtin");
|
|
4204
|
+
return normalizeCommandState({
|
|
4205
|
+
enabled: false,
|
|
4206
|
+
active,
|
|
4207
|
+
supported: false,
|
|
4208
|
+
value,
|
|
4209
|
+
reason: unavailableRouteReason(doc)
|
|
4210
|
+
}, "builtin");
|
|
4211
|
+
}
|
|
3928
4212
|
}
|
|
3929
4213
|
return normalizeCommandState({
|
|
3930
4214
|
enabled: false,
|
|
@@ -3934,6 +4218,86 @@ function createSuperDocUI(options) {
|
|
|
3934
4218
|
reason: unavailableRouteReason(doc)
|
|
3935
4219
|
}, "builtin");
|
|
3936
4220
|
};
|
|
4221
|
+
const computeListToggleCommandState = (descriptor, doc, readonly, selection$1, active, value) => {
|
|
4222
|
+
if (descriptor.mutates && readonly) return normalizeCommandState({
|
|
4223
|
+
enabled: false,
|
|
4224
|
+
active,
|
|
4225
|
+
supported: true,
|
|
4226
|
+
value,
|
|
4227
|
+
reason: SUPERDOC_UI_REASONS.documentReadonly
|
|
4228
|
+
}, "builtin");
|
|
4229
|
+
const blockIds = selectionBlockIds(selection$1);
|
|
4230
|
+
if (blockIds.length === 0) return normalizeCommandState({
|
|
4231
|
+
enabled: false,
|
|
4232
|
+
active,
|
|
4233
|
+
supported: true,
|
|
4234
|
+
value,
|
|
4235
|
+
reason: SUPERDOC_UI_REASONS.selectionRequired
|
|
4236
|
+
}, "builtin");
|
|
4237
|
+
const story = selectionStory(selection$1);
|
|
4238
|
+
const listsApi = doc?.lists;
|
|
4239
|
+
if (!(typeof listsApi?.getStateInStory === "function" || story.storyType === "body" && typeof listsApi?.getState === "function")) return normalizeCommandState({
|
|
4240
|
+
enabled: false,
|
|
4241
|
+
active,
|
|
4242
|
+
supported: false,
|
|
4243
|
+
value,
|
|
4244
|
+
reason: SUPERDOC_UI_REASONS.operationUnavailable
|
|
4245
|
+
}, "builtin");
|
|
4246
|
+
if (!canProbeEverySelectedBlock(blockIds)) return normalizeCommandState(story.storyType === "body" && resolveDocOperation(doc, "lists.remove") != null ? {
|
|
4247
|
+
enabled: true,
|
|
4248
|
+
active,
|
|
4249
|
+
supported: true,
|
|
4250
|
+
value
|
|
4251
|
+
} : {
|
|
4252
|
+
enabled: false,
|
|
4253
|
+
active,
|
|
4254
|
+
supported: false,
|
|
4255
|
+
value,
|
|
4256
|
+
reason: SUPERDOC_UI_REASONS.operationUnavailable
|
|
4257
|
+
}, "builtin");
|
|
4258
|
+
const snapshots = blockIds.map((blockId) => readListStateSnapshotForBlock(doc, blockId, story));
|
|
4259
|
+
if (snapshots.some(({ status }) => status !== "ready")) return normalizeCommandState({
|
|
4260
|
+
enabled: true,
|
|
4261
|
+
active,
|
|
4262
|
+
supported: true,
|
|
4263
|
+
value
|
|
4264
|
+
}, "builtin");
|
|
4265
|
+
if (snapshots.some(({ value: state$1 }) => state$1 === null)) return normalizeCommandState({
|
|
4266
|
+
enabled: false,
|
|
4267
|
+
active,
|
|
4268
|
+
supported: false,
|
|
4269
|
+
value,
|
|
4270
|
+
reason: SUPERDOC_UI_REASONS.operationUnavailable
|
|
4271
|
+
}, "builtin");
|
|
4272
|
+
const seed = descriptor.list?.seed;
|
|
4273
|
+
const shouldRemove = snapshots.every(({ value: state$1 }) => state$1?.isListItem === true && state$1.seed === seed);
|
|
4274
|
+
if (story.storyType === "body") return normalizeCommandState(!shouldRemove || resolveDocOperation(doc, "lists.remove") != null ? {
|
|
4275
|
+
enabled: true,
|
|
4276
|
+
active,
|
|
4277
|
+
supported: true,
|
|
4278
|
+
value
|
|
4279
|
+
} : {
|
|
4280
|
+
enabled: false,
|
|
4281
|
+
active,
|
|
4282
|
+
supported: false,
|
|
4283
|
+
value,
|
|
4284
|
+
reason: SUPERDOC_UI_REASONS.operationUnavailable
|
|
4285
|
+
}, "builtin");
|
|
4286
|
+
const removeInStory = resolveDocOperation(doc, "lists.removeInStory");
|
|
4287
|
+
if (shouldRemove && removeInStory) return normalizeCommandState({
|
|
4288
|
+
enabled: true,
|
|
4289
|
+
active,
|
|
4290
|
+
supported: true,
|
|
4291
|
+
value
|
|
4292
|
+
}, "builtin");
|
|
4293
|
+
return normalizeCommandState({
|
|
4294
|
+
enabled: false,
|
|
4295
|
+
active,
|
|
4296
|
+
supported: false,
|
|
4297
|
+
value,
|
|
4298
|
+
reason: SUPERDOC_UI_REASONS.operationUnavailable
|
|
4299
|
+
}, "builtin");
|
|
4300
|
+
};
|
|
3937
4301
|
const readActiveLinkHref = (doc, selection$1) => {
|
|
3938
4302
|
const href = (resolveCurrentHyperlink(doc, selection$1)?.properties)?.href;
|
|
3939
4303
|
return typeof href === "string" ? href : null;
|
|
@@ -4048,8 +4412,8 @@ function createSuperDocUI(options) {
|
|
|
4048
4412
|
status: combineStatus(full.status, quickResult.status)
|
|
4049
4413
|
};
|
|
4050
4414
|
};
|
|
4051
|
-
const readBlockStyleRef = (doc, blockId) => {
|
|
4052
|
-
const { value: result, status } = readNodeById(doc, blockId);
|
|
4415
|
+
const readBlockStyleRef = (doc, blockId, story) => {
|
|
4416
|
+
const { value: result, status } = readNodeById(doc, blockId, story);
|
|
4053
4417
|
if (!result) return {
|
|
4054
4418
|
ok: false,
|
|
4055
4419
|
styleRef: null,
|
|
@@ -4128,8 +4492,9 @@ function createSuperDocUI(options) {
|
|
|
4128
4492
|
let blockReadFailures = 0;
|
|
4129
4493
|
let defaultReadFailures = 0;
|
|
4130
4494
|
let readStatus = "ready";
|
|
4495
|
+
const story = selectionStory(selection$1);
|
|
4131
4496
|
for (const blockId of blockIds) {
|
|
4132
|
-
const read = readBlockStyleRef(doc, blockId);
|
|
4497
|
+
const read = readBlockStyleRef(doc, blockId, story);
|
|
4133
4498
|
readStatus = combineStatus(readStatus, read.status);
|
|
4134
4499
|
if (!read.ok) {
|
|
4135
4500
|
blockReadFailures += 1;
|
|
@@ -4273,9 +4638,9 @@ function createSuperDocUI(options) {
|
|
|
4273
4638
|
currentHostSelectionSource = next;
|
|
4274
4639
|
if (!next) return;
|
|
4275
4640
|
try {
|
|
4276
|
-
const unsubscribe = next.subscribe(() => {
|
|
4641
|
+
const unsubscribe = next.subscribe((snapshot) => {
|
|
4277
4642
|
selectionEpoch += 1;
|
|
4278
|
-
seedCaretSelectionFromHost();
|
|
4643
|
+
seedCaretSelectionFromHost(snapshot);
|
|
4279
4644
|
recompute();
|
|
4280
4645
|
});
|
|
4281
4646
|
if (typeof unsubscribe === "function") detachHostSelection = unsubscribe;
|
|
@@ -4428,6 +4793,39 @@ function createSuperDocUI(options) {
|
|
|
4428
4793
|
function readTrackDecisionTargetId(target) {
|
|
4429
4794
|
return target && typeof target === "object" && typeof target.id === "string" ? String(target.id) : null;
|
|
4430
4795
|
}
|
|
4796
|
+
function trackDecisionRangeFromSelection(selection$1) {
|
|
4797
|
+
if (selection$1.empty) return null;
|
|
4798
|
+
const explicit = selection$1.selectionTarget;
|
|
4799
|
+
const start = explicit?.start;
|
|
4800
|
+
const end = explicit?.end;
|
|
4801
|
+
if (explicit?.kind !== "selection" || start?.kind !== "text" || end?.kind !== "text" || typeof start.blockId !== "string" || start.blockId !== end.blockId || !Number.isInteger(start.offset) || !Number.isInteger(end.offset) || start.offset < 0 || end.offset < 0 || start.offset === end.offset) return null;
|
|
4802
|
+
const rangeStart = Math.min(start.offset, end.offset);
|
|
4803
|
+
const rangeEnd = Math.max(start.offset, end.offset);
|
|
4804
|
+
const story = selectionStoryLocator(selection$1);
|
|
4805
|
+
return {
|
|
4806
|
+
kind: "text",
|
|
4807
|
+
...story ? { story } : {},
|
|
4808
|
+
segments: [{
|
|
4809
|
+
blockId: start.blockId,
|
|
4810
|
+
range: {
|
|
4811
|
+
start: rangeStart,
|
|
4812
|
+
end: rangeEnd
|
|
4813
|
+
}
|
|
4814
|
+
}]
|
|
4815
|
+
};
|
|
4816
|
+
}
|
|
4817
|
+
function activeChangePartialDecisionRoute() {
|
|
4818
|
+
const activeId = state.selection.activeChangeIds[0];
|
|
4819
|
+
if (!activeId) return "unavailable";
|
|
4820
|
+
const items = readAllStoryTrackChanges();
|
|
4821
|
+
if (!items) return "unavailable";
|
|
4822
|
+
const story = selectionStoryLocator(state.selection);
|
|
4823
|
+
const item = items.find((candidate) => entityRowMatchesRequest(candidate, activeId, story));
|
|
4824
|
+
if (!item) return "unavailable";
|
|
4825
|
+
const type = trackChangesItemPayload(item).type;
|
|
4826
|
+
const grouping = trackChangesItemPayload(item).grouping;
|
|
4827
|
+
return (type === "insertion" || type === "deletion" || type === "insert" || type === "delete") && grouping === "standalone" ? "range" : "id";
|
|
4828
|
+
}
|
|
4431
4829
|
function resolveTrackDecisionTarget(command, payload) {
|
|
4432
4830
|
if (command.scope === "all") return {
|
|
4433
4831
|
target: { scope: "all" },
|
|
@@ -4465,6 +4863,23 @@ function createSuperDocUI(options) {
|
|
|
4465
4863
|
} : null;
|
|
4466
4864
|
}
|
|
4467
4865
|
function executeTrackDecisionCommand(command, payload) {
|
|
4866
|
+
if (command.scope === "id" && payload == null) {
|
|
4867
|
+
if (state.selection.activeChangeIds.length > 1) return executeTrackDecisionTarget(command.kind, {
|
|
4868
|
+
kind: "ids",
|
|
4869
|
+
ids: state.selection.activeChangeIds
|
|
4870
|
+
}, null);
|
|
4871
|
+
if (state.selection.activeChangeIds.length === 1 && !state.selection.empty && state.selection.selectionTarget) {
|
|
4872
|
+
const route = activeChangePartialDecisionRoute();
|
|
4873
|
+
if (route === "unavailable") return false;
|
|
4874
|
+
if (route === "range") {
|
|
4875
|
+
const range = trackDecisionRangeFromSelection(state.selection);
|
|
4876
|
+
return range ? executeTrackDecisionTarget(command.kind, {
|
|
4877
|
+
kind: "range",
|
|
4878
|
+
range
|
|
4879
|
+
}, null) : false;
|
|
4880
|
+
}
|
|
4881
|
+
}
|
|
4882
|
+
}
|
|
4468
4883
|
const resolved = resolveTrackDecisionTarget(command, payload);
|
|
4469
4884
|
if (!resolved) return false;
|
|
4470
4885
|
return executeTrackDecisionTarget(command.kind, resolved.target, resolved.changeId);
|
|
@@ -4653,8 +5068,8 @@ function createSuperDocUI(options) {
|
|
|
4653
5068
|
offsetSpace: "selection"
|
|
4654
5069
|
});
|
|
4655
5070
|
};
|
|
4656
|
-
const buildBlockParagraphInput = (spec, blockId, payload) => {
|
|
4657
|
-
const target = paragraphTarget(blockId);
|
|
5071
|
+
const buildBlockParagraphInput = (spec, blockId, payload, story) => {
|
|
5072
|
+
const target = paragraphTarget(blockId, story);
|
|
4658
5073
|
switch (spec.kind) {
|
|
4659
5074
|
case "alignment": {
|
|
4660
5075
|
const alignment = payload;
|
|
@@ -4724,6 +5139,9 @@ function createSuperDocUI(options) {
|
|
|
4724
5139
|
return true;
|
|
4725
5140
|
};
|
|
4726
5141
|
const executeClearFormattingCommand = () => {
|
|
5142
|
+
const doc = getDoc();
|
|
5143
|
+
const { lockModesById } = computeActiveContentControlLockModes(doc?.contentControls, state.selection);
|
|
5144
|
+
if (contentControlLockReason(lockModesById)) return false;
|
|
4727
5145
|
const immediateResults = [];
|
|
4728
5146
|
const settledResults = [];
|
|
4729
5147
|
const record = (result) => {
|
|
@@ -4739,7 +5157,6 @@ function createSuperDocUI(options) {
|
|
|
4739
5157
|
settledResults.push(Promise.resolve(false));
|
|
4740
5158
|
}
|
|
4741
5159
|
};
|
|
4742
|
-
const doc = getDoc();
|
|
4743
5160
|
const defaultStyleId = getStyleCatalog().cache?.full.defaults.paragraphStyleId ?? DEFAULT_PARAGRAPH_STYLE_ID;
|
|
4744
5161
|
const rangeTarget = resolveInlineSelectionTarget(state.selection);
|
|
4745
5162
|
if (rangeTarget) {
|
|
@@ -4755,13 +5172,19 @@ function createSuperDocUI(options) {
|
|
|
4755
5172
|
}
|
|
4756
5173
|
}
|
|
4757
5174
|
const resetOp = resolveDocOperation(doc, "format.paragraph.resetDirectFormatting");
|
|
4758
|
-
const listsRemoveOp = resolveDocOperation(doc, "lists.remove");
|
|
4759
5175
|
const setStyleRefOp = resolveDocOperation(doc, "styles.paragraph.setStyleRef");
|
|
5176
|
+
const story = selectionStoryLocator(state.selection);
|
|
5177
|
+
const isBodyStory = !story || story.storyType === "body";
|
|
5178
|
+
const listsRemoveOp = resolveDocOperation(doc, isBodyStory ? "lists.remove" : "lists.removeInStory");
|
|
4760
5179
|
for (const blockId of selectionBlockIds(state.selection)) {
|
|
4761
|
-
const target = paragraphTarget(blockId);
|
|
5180
|
+
const target = paragraphTarget(blockId, story);
|
|
4762
5181
|
if (resetOp) run(resetOp, { target });
|
|
4763
5182
|
if (listsRemoveOp) try {
|
|
4764
|
-
const
|
|
5183
|
+
const listTarget = listsBlockTarget(blockId);
|
|
5184
|
+
const r = settleOperationResult(listsRemoveOp(isBodyStory ? { target: listTarget } : {
|
|
5185
|
+
target: listTarget,
|
|
5186
|
+
story
|
|
5187
|
+
}));
|
|
4765
5188
|
settledResults.push(r.settled.then((s) => commandResultSucceeded(s) ? s : true));
|
|
4766
5189
|
} catch {}
|
|
4767
5190
|
if (setStyleRefOp) run(setStyleRefOp, {
|
|
@@ -4772,7 +5195,7 @@ function createSuperDocUI(options) {
|
|
|
4772
5195
|
if (!rangeTarget && readDocumentMode() !== "suggesting") {
|
|
4773
5196
|
const setMarkRunPropsOp = resolveDocOperation(doc, "format.paragraph.setMarkRunProps");
|
|
4774
5197
|
if (setMarkRunPropsOp) for (const blockId of selectionBlockIds(state.selection)) run(setMarkRunPropsOp, {
|
|
4775
|
-
target: paragraphTarget(blockId),
|
|
5198
|
+
target: paragraphTarget(blockId, story),
|
|
4776
5199
|
markRunProps: {
|
|
4777
5200
|
bold: false,
|
|
4778
5201
|
italic: false,
|
|
@@ -4790,7 +5213,8 @@ function createSuperDocUI(options) {
|
|
|
4790
5213
|
const executeBlockParagraph = (descriptor, op, payload) => {
|
|
4791
5214
|
const blockIds = selectionBlockIds(state.selection);
|
|
4792
5215
|
if (blockIds.length === 0) return false;
|
|
4793
|
-
|
|
5216
|
+
const story = selectionStoryLocator(state.selection);
|
|
5217
|
+
return applyPerBlock(descriptor.docRoute, op, blockIds, (blockId) => buildBlockParagraphInput(descriptor.blockParagraph, blockId, payload, story));
|
|
4794
5218
|
};
|
|
4795
5219
|
const executeHybridIndentCommand = (descriptor, listOp, blockIds) => {
|
|
4796
5220
|
const doc = getDoc();
|
|
@@ -4798,6 +5222,7 @@ function createSuperDocUI(options) {
|
|
|
4798
5222
|
const paragraphClearIndent = resolveDocOperation(doc, "format.paragraph.clearIndentation");
|
|
4799
5223
|
const mode = descriptor.list?.mode;
|
|
4800
5224
|
const story = selectionStory(state.selection);
|
|
5225
|
+
const targetStory = selectionStoryLocator(state.selection);
|
|
4801
5226
|
const planBlock = async (blockId) => {
|
|
4802
5227
|
const isListItem = await resolveListMembershipForBlockAsync(doc, blockId, story);
|
|
4803
5228
|
if (isListItem === true) return {
|
|
@@ -4807,7 +5232,8 @@ function createSuperDocUI(options) {
|
|
|
4807
5232
|
input: { target: listItemTarget(blockId) }
|
|
4808
5233
|
};
|
|
4809
5234
|
if (isListItem === null) return null;
|
|
4810
|
-
|
|
5235
|
+
if (targetStory && targetStory.storyType !== "body" && typeof doc?.getNode !== "function") return null;
|
|
5236
|
+
const current = await resolveParagraphIndentationForBlockAsync(doc, blockId, targetStory);
|
|
4811
5237
|
const preserved = {};
|
|
4812
5238
|
if (current?.right != null) preserved.right = current.right;
|
|
4813
5239
|
if (current?.firstLine != null) preserved.firstLine = current.firstLine;
|
|
@@ -4819,7 +5245,7 @@ function createSuperDocUI(options) {
|
|
|
4819
5245
|
routeToCall: "format.paragraph.setIndentation",
|
|
4820
5246
|
opToCall: paragraphSetIndent,
|
|
4821
5247
|
input: {
|
|
4822
|
-
target: paragraphTarget(blockId),
|
|
5248
|
+
target: paragraphTarget(blockId, targetStory),
|
|
4823
5249
|
left: Math.max(0, current?.left ?? 0) + PARAGRAPH_INDENT_STEP_TWIPS,
|
|
4824
5250
|
...preserved
|
|
4825
5251
|
}
|
|
@@ -4832,14 +5258,14 @@ function createSuperDocUI(options) {
|
|
|
4832
5258
|
kind: "paragraph",
|
|
4833
5259
|
routeToCall: "format.paragraph.clearIndentation",
|
|
4834
5260
|
opToCall: paragraphClearIndent,
|
|
4835
|
-
input: { target: paragraphTarget(blockId) }
|
|
5261
|
+
input: { target: paragraphTarget(blockId, targetStory) }
|
|
4836
5262
|
};
|
|
4837
5263
|
if (paragraphSetIndent) return {
|
|
4838
5264
|
kind: "paragraph",
|
|
4839
5265
|
routeToCall: "format.paragraph.setIndentation",
|
|
4840
5266
|
opToCall: paragraphSetIndent,
|
|
4841
5267
|
input: {
|
|
4842
|
-
target: paragraphTarget(blockId),
|
|
5268
|
+
target: paragraphTarget(blockId, targetStory),
|
|
4843
5269
|
left: 0
|
|
4844
5270
|
}
|
|
4845
5271
|
};
|
|
@@ -4850,7 +5276,7 @@ function createSuperDocUI(options) {
|
|
|
4850
5276
|
routeToCall: "format.paragraph.setIndentation",
|
|
4851
5277
|
opToCall: paragraphSetIndent,
|
|
4852
5278
|
input: {
|
|
4853
|
-
target: paragraphTarget(blockId),
|
|
5279
|
+
target: paragraphTarget(blockId, targetStory),
|
|
4854
5280
|
...preserved
|
|
4855
5281
|
}
|
|
4856
5282
|
};
|
|
@@ -4870,9 +5296,16 @@ function createSuperDocUI(options) {
|
|
|
4870
5296
|
return false;
|
|
4871
5297
|
}
|
|
4872
5298
|
}
|
|
5299
|
+
const nonBodyListPlans = story.storyType !== "body" && plans.some((plan) => plan?.kind === "list");
|
|
5300
|
+
const outdentInStory = nonBodyListPlans && mode === "outdent" ? resolveDocOperation(doc, "lists.outdentInStory") : null;
|
|
5301
|
+
if (nonBodyListPlans && !outdentInStory) return false;
|
|
4873
5302
|
const settledResults = plans.map((plan) => {
|
|
4874
5303
|
if (!plan) return Promise.resolve(false);
|
|
4875
5304
|
try {
|
|
5305
|
+
if (plan.kind === "list" && outdentInStory) return settleOperationResult(callEditorMutation("lists.outdentInStory", outdentInStory, {
|
|
5306
|
+
target: plan.input.target,
|
|
5307
|
+
story
|
|
5308
|
+
})).settled;
|
|
4876
5309
|
return settleOperationResult(callEditorMutation(plan.routeToCall, plan.opToCall, plan.input)).settled;
|
|
4877
5310
|
} catch {
|
|
4878
5311
|
return Promise.resolve(false);
|
|
@@ -4887,17 +5320,62 @@ function createSuperDocUI(options) {
|
|
|
4887
5320
|
const doc = getDoc();
|
|
4888
5321
|
const blockIds = selectionBlockIds(state.selection);
|
|
4889
5322
|
if (blockIds.length === 0) return false;
|
|
5323
|
+
const story = selectionStory(state.selection);
|
|
5324
|
+
const isBodyStory = story.storyType === "body";
|
|
4890
5325
|
if (spec.mode === "indent" || spec.mode === "outdent") return executeHybridIndentCommand(descriptor, op, blockIds);
|
|
4891
5326
|
const seed = spec.seed;
|
|
4892
|
-
|
|
4893
|
-
|
|
4894
|
-
|
|
4895
|
-
|
|
5327
|
+
const executeResolved = (states) => {
|
|
5328
|
+
if (states.some((listState) => !listState.resolved)) return {
|
|
5329
|
+
immediate: false,
|
|
5330
|
+
settled: null
|
|
5331
|
+
};
|
|
5332
|
+
const shouldRemove = states.every((listState) => listState.seed === seed);
|
|
5333
|
+
if (!shouldRemove && !isBodyStory) return {
|
|
5334
|
+
immediate: false,
|
|
5335
|
+
settled: null
|
|
5336
|
+
};
|
|
5337
|
+
const route = shouldRemove ? isBodyStory ? "lists.remove" : "lists.removeInStory" : descriptor.docRoute;
|
|
5338
|
+
const operation = shouldRemove ? resolveDocOperation(doc, route) : op;
|
|
5339
|
+
if (!operation) return {
|
|
5340
|
+
immediate: false,
|
|
5341
|
+
settled: null
|
|
5342
|
+
};
|
|
5343
|
+
const immediateResults = [];
|
|
5344
|
+
const settledResults = [];
|
|
5345
|
+
blockIds.forEach((blockId, index) => {
|
|
5346
|
+
if (!shouldRemove && states[index]?.seed === seed) return;
|
|
5347
|
+
const input = shouldRemove ? {
|
|
5348
|
+
target: listsBlockTarget(blockId),
|
|
5349
|
+
...!isBodyStory ? { story } : {}
|
|
5350
|
+
} : {
|
|
5351
|
+
target: listsBlockTarget(blockId),
|
|
5352
|
+
seed
|
|
5353
|
+
};
|
|
5354
|
+
try {
|
|
5355
|
+
const result$1 = settleOperationResult(callEditorMutation(route, operation, input));
|
|
5356
|
+
immediateResults.push(result$1.immediate);
|
|
5357
|
+
settledResults.push(result$1.settled);
|
|
5358
|
+
} catch {
|
|
5359
|
+
immediateResults.push(false);
|
|
5360
|
+
settledResults.push(Promise.resolve(false));
|
|
5361
|
+
}
|
|
5362
|
+
});
|
|
5363
|
+
return {
|
|
5364
|
+
immediate: combineCommandResults(immediateResults),
|
|
5365
|
+
settled: settledResults.length ? Promise.all(settledResults).then((results) => combineCommandResults(results)) : null
|
|
5366
|
+
};
|
|
5367
|
+
};
|
|
5368
|
+
const stateReads = blockIds.map((blockId) => resolveListSeedForBlock(doc, blockId, story));
|
|
5369
|
+
if (stateReads.some(isPromiseLike)) {
|
|
5370
|
+
pendingCommandSettlement = Promise.all(stateReads).then(async (states) => {
|
|
5371
|
+
const result$1 = executeResolved(states);
|
|
5372
|
+
return result$1.settled ? await result$1.settled : result$1.immediate;
|
|
5373
|
+
});
|
|
5374
|
+
return true;
|
|
4896
5375
|
}
|
|
4897
|
-
|
|
4898
|
-
|
|
4899
|
-
|
|
4900
|
-
});
|
|
5376
|
+
const result = executeResolved(stateReads);
|
|
5377
|
+
pendingCommandSettlement = result.settled;
|
|
5378
|
+
return result.immediate;
|
|
4901
5379
|
};
|
|
4902
5380
|
function readLinkPayloadRecord(payload) {
|
|
4903
5381
|
return payload && typeof payload === "object" ? payload : {};
|
|
@@ -5084,7 +5562,7 @@ function createSuperDocUI(options) {
|
|
|
5084
5562
|
const rows = Number(record.rows ?? record.rowCount);
|
|
5085
5563
|
const columns = Number(record.columns ?? record.cols ?? record.colCount);
|
|
5086
5564
|
if (!Number.isInteger(rows) || rows < 1 || !Number.isInteger(columns) || columns < 1) return false;
|
|
5087
|
-
const caret =
|
|
5565
|
+
const caret = collapsedTextAddressFromSelection(state.selection);
|
|
5088
5566
|
const at = caret && typeof caret.blockId === "string" ? {
|
|
5089
5567
|
kind: "inParagraph",
|
|
5090
5568
|
target: paragraphTarget(caret.blockId),
|
|
@@ -5104,14 +5582,29 @@ function createSuperDocUI(options) {
|
|
|
5104
5582
|
const src = record.src ?? record.value;
|
|
5105
5583
|
if (typeof src !== "string" || src.trim() === "") return false;
|
|
5106
5584
|
const caret = collapsedTextAddressFromSelection(state.selection);
|
|
5585
|
+
const story = selectionStory(state.selection);
|
|
5586
|
+
const nonBodyStory = story.storyType === "body" ? null : story;
|
|
5587
|
+
let at;
|
|
5588
|
+
if (caret && typeof caret.blockId === "string") at = {
|
|
5589
|
+
kind: "inParagraph",
|
|
5590
|
+
target: paragraphTarget(caret.blockId, nonBodyStory),
|
|
5591
|
+
offset: caret.range?.start ?? 0
|
|
5592
|
+
};
|
|
5593
|
+
else {
|
|
5594
|
+
at = createLocationAt(state.selection, "target");
|
|
5595
|
+
if (nonBodyStory && at.kind === "after") at = {
|
|
5596
|
+
...at,
|
|
5597
|
+
target: {
|
|
5598
|
+
...at.target,
|
|
5599
|
+
story: nonBodyStory
|
|
5600
|
+
}
|
|
5601
|
+
};
|
|
5602
|
+
}
|
|
5107
5603
|
const input$1 = {
|
|
5108
5604
|
src,
|
|
5109
|
-
at
|
|
5110
|
-
kind: "inParagraph",
|
|
5111
|
-
target: paragraphTarget(caret.blockId),
|
|
5112
|
-
offset: caret.range?.start ?? 0
|
|
5113
|
-
} : createLocationAt(state.selection, "target")
|
|
5605
|
+
at
|
|
5114
5606
|
};
|
|
5607
|
+
if (nonBodyStory) input$1.in = at.kind === "inParagraph" ? resolveActiveHeaderFooterSlot(nonBodyStory) ?? nonBodyStory : nonBodyStory;
|
|
5115
5608
|
if (typeof record.alt === "string") input$1.alt = record.alt;
|
|
5116
5609
|
if (typeof record.title === "string") input$1.title = record.title;
|
|
5117
5610
|
if (record.size && typeof record.size === "object") input$1.size = record.size;
|
|
@@ -5218,9 +5711,12 @@ function createSuperDocUI(options) {
|
|
|
5218
5711
|
const route = descriptor.docRoute;
|
|
5219
5712
|
if (!route) return false;
|
|
5220
5713
|
if (descriptor.mutates && readDocumentMode() === "viewing") return false;
|
|
5221
|
-
const
|
|
5714
|
+
const doc = getDoc();
|
|
5715
|
+
const op = resolveDocOperation(doc, route);
|
|
5222
5716
|
if (!op) return false;
|
|
5223
5717
|
if (descriptor.inline) {
|
|
5718
|
+
const { lockModesById } = computeActiveContentControlLockModes(doc?.contentControls, state.selection);
|
|
5719
|
+
if (contentControlLockReason(lockModesById)) return false;
|
|
5224
5720
|
const target = resolveInlineSelectionTarget(state.selection);
|
|
5225
5721
|
if (!target) {
|
|
5226
5722
|
if (state.selection.empty === false) return settleCommandExecution(false);
|
|
@@ -5478,6 +5974,12 @@ function createSuperDocUI(options) {
|
|
|
5478
5974
|
}
|
|
5479
5975
|
const doc = getDoc();
|
|
5480
5976
|
if (!doc) return;
|
|
5977
|
+
const targetSelection = selectionSliceFromInfo(selection$1, "ready");
|
|
5978
|
+
const { lockModesById } = computeActiveContentControlLockModes(doc.contentControls, targetSelection);
|
|
5979
|
+
if (contentControlLockReason(lockModesById)) {
|
|
5980
|
+
recompute();
|
|
5981
|
+
return;
|
|
5982
|
+
}
|
|
5481
5983
|
const selTarget = selection$1["target"];
|
|
5482
5984
|
const selectionTarget = selection$1["selectionTarget"];
|
|
5483
5985
|
if (!(selection$1["empty"] === true) && Object.keys(snap.inline).length > 0) {
|
|
@@ -6049,6 +6551,7 @@ function createSuperDocUI(options) {
|
|
|
6049
6551
|
setActive: (input) => {
|
|
6050
6552
|
if (input == null) {
|
|
6051
6553
|
setExplicitActiveChange(null);
|
|
6554
|
+
mirrorTrackedChangeFocusToHost(null);
|
|
6052
6555
|
recompute();
|
|
6053
6556
|
return true;
|
|
6054
6557
|
}
|
|
@@ -6058,6 +6561,7 @@ function createSuperDocUI(options) {
|
|
|
6058
6561
|
story: input.story
|
|
6059
6562
|
};
|
|
6060
6563
|
if (typeof requested.id !== "string" || requested.id.length === 0) return false;
|
|
6564
|
+
const paintedEntityId = requested.id;
|
|
6061
6565
|
if (requested.story) {
|
|
6062
6566
|
const allStoryItems = readAllStoryTrackChanges();
|
|
6063
6567
|
if (!allStoryItems) return false;
|
|
@@ -6070,7 +6574,9 @@ function createSuperDocUI(options) {
|
|
|
6070
6574
|
if (!bodyItems.some((item) => readEntityId(item) === publicId)) return false;
|
|
6071
6575
|
requested.id = publicId;
|
|
6072
6576
|
}
|
|
6577
|
+
if (paintedEntityId !== requested.id) requested.paintedEntityId = paintedEntityId;
|
|
6073
6578
|
setExplicitActiveChange(requested);
|
|
6579
|
+
mirrorTrackedChangeFocusToHost(requested);
|
|
6074
6580
|
recompute();
|
|
6075
6581
|
return true;
|
|
6076
6582
|
},
|
|
@@ -6089,10 +6595,11 @@ function createSuperDocUI(options) {
|
|
|
6089
6595
|
reason: SUPERDOC_UI_REASONS.targetUnresolved
|
|
6090
6596
|
};
|
|
6091
6597
|
const previousActiveChange = explicitActiveChange;
|
|
6092
|
-
|
|
6598
|
+
const requestedActiveChange = story ? {
|
|
6093
6599
|
id: changeId,
|
|
6094
6600
|
story
|
|
6095
|
-
} : { id: changeId }
|
|
6601
|
+
} : { id: changeId };
|
|
6602
|
+
setExplicitActiveChange(requestedActiveChange);
|
|
6096
6603
|
recompute();
|
|
6097
6604
|
const optimisticActiveChange = explicitActiveChange;
|
|
6098
6605
|
const optimisticRevision = explicitActiveChangeRevision;
|
|
@@ -6108,6 +6615,7 @@ function createSuperDocUI(options) {
|
|
|
6108
6615
|
ok: false
|
|
6109
6616
|
};
|
|
6110
6617
|
if (!result.ok && result.reason !== SUPERDOC_UI_REASONS.targetNotVisible) rollback();
|
|
6618
|
+
else mirrorTrackedChangeFocusToHost(requestedActiveChange);
|
|
6111
6619
|
return result;
|
|
6112
6620
|
}
|
|
6113
6621
|
};
|
|
@@ -6123,24 +6631,30 @@ function createSuperDocUI(options) {
|
|
|
6123
6631
|
}, id, story);
|
|
6124
6632
|
};
|
|
6125
6633
|
const executeTrackDecisionTarget = (kind, target, changeId, story) => {
|
|
6634
|
+
try {
|
|
6635
|
+
return settleCommandExecution(callTrackDecisionTarget(kind, target, changeId, story));
|
|
6636
|
+
} catch {
|
|
6637
|
+
return false;
|
|
6638
|
+
}
|
|
6639
|
+
};
|
|
6640
|
+
const callTrackDecisionTarget = (kind, target, changeId, story) => {
|
|
6126
6641
|
if (reviewMutationsAreReadOnly()) return false;
|
|
6127
6642
|
const tcApi = getDoc()?.trackChanges;
|
|
6643
|
+
const isAllTarget = target.scope === "all";
|
|
6644
|
+
const isRangeTarget = target.kind === "range";
|
|
6645
|
+
const isMultiIdTarget = target.kind === "ids";
|
|
6128
6646
|
if (bulkTrackDecisionBlockedReason({
|
|
6129
6647
|
kind,
|
|
6130
|
-
scope:
|
|
6648
|
+
scope: isAllTarget ? "all" : "id"
|
|
6131
6649
|
}, tcApi)) return false;
|
|
6132
|
-
const legacyName =
|
|
6133
|
-
const op = !story && tcApi && typeof tcApi[legacyName] === "function" ? tcApi[legacyName] : null;
|
|
6650
|
+
const legacyName = isAllTarget ? `${kind}All` : kind;
|
|
6651
|
+
const op = !isRangeTarget && !isMultiIdTarget && !story && tcApi && typeof tcApi[legacyName] === "function" ? tcApi[legacyName] : null;
|
|
6134
6652
|
const decide = tcApi && typeof tcApi.decide === "function" ? tcApi.decide : null;
|
|
6135
6653
|
if (!op && !decide) return false;
|
|
6136
|
-
|
|
6137
|
-
|
|
6138
|
-
|
|
6139
|
-
|
|
6140
|
-
}));
|
|
6141
|
-
} catch {
|
|
6142
|
-
return false;
|
|
6143
|
-
}
|
|
6654
|
+
return op ? op.call(tcApi, changeId ?? {}) : decide.call(tcApi, {
|
|
6655
|
+
decision: kind,
|
|
6656
|
+
target
|
|
6657
|
+
});
|
|
6144
6658
|
};
|
|
6145
6659
|
const contentControlsSub = sliceHandle((s) => s.contentControls);
|
|
6146
6660
|
const findContentControl = (id) => {
|
|
@@ -7069,6 +7583,11 @@ function createSuperDocUI(options) {
|
|
|
7069
7583
|
clearTimeout(foregroundAsyncRetryTimer);
|
|
7070
7584
|
foregroundAsyncRetryTimer = null;
|
|
7071
7585
|
}
|
|
7586
|
+
if (asyncReadFailureRetryTimer) {
|
|
7587
|
+
clearTimeout(asyncReadFailureRetryTimer);
|
|
7588
|
+
asyncReadFailureRetryTimer = null;
|
|
7589
|
+
asyncReadFailureRetryAtMs = 0;
|
|
7590
|
+
}
|
|
7072
7591
|
if (pendingEffectiveInlineRead?.timer) {
|
|
7073
7592
|
clearTimeout(pendingEffectiveInlineRead.timer);
|
|
7074
7593
|
pendingEffectiveInlineRead.timer = null;
|