superdoc 2.0.0-next.32 → 2.0.0-next.34

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.
@@ -1,3 +1,89 @@
1
+ function getParagraphInlineDirection(attrs) {
2
+ const fromContext = attrs?.directionContext?.inlineDirection;
3
+ if (fromContext != null) return fromContext;
4
+ const ppRtl = attrs?.paragraphProperties?.rightToLeft;
5
+ if (ppRtl === true) return "rtl";
6
+ if (ppRtl === false) return "ltr";
7
+ }
8
+ var FALLBACK_PALETTE = [
9
+ "#1f6feb",
10
+ "#d1242f",
11
+ "#8250df",
12
+ "#bf3989",
13
+ "#1a7f37",
14
+ "#9a6700",
15
+ "#bc4c00",
16
+ "#0969da",
17
+ "#cf222e",
18
+ "#6639ba",
19
+ "#116329",
20
+ "#7d4e00"
21
+ ];
22
+ const authorIdentityKey = (author) => {
23
+ if (!author) return "";
24
+ return `${typeof author.name === "string" ? author.name : ""} ${typeof author.email === "string" ? author.email : ""}`;
25
+ };
26
+ var hashString = (value) => {
27
+ let hash = 2166136261;
28
+ for (let i = 0; i < value.length; i += 1) {
29
+ hash ^= value.charCodeAt(i);
30
+ hash = Math.imul(hash, 16777619);
31
+ }
32
+ return hash >>> 0;
33
+ };
34
+ const fallbackAuthorColor = (author) => {
35
+ return FALLBACK_PALETTE[hashString(authorIdentityKey(author)) % FALLBACK_PALETTE.length];
36
+ };
37
+ var isNonEmptyString = (value) => typeof value === "string" && value.length > 0;
38
+ const composeAuthorColorResolver = (config) => {
39
+ if (!config || config.enabled === false) return void 0;
40
+ const overrides = config.overrides && typeof config.overrides === "object" ? config.overrides : void 0;
41
+ const resolve = typeof config.resolve === "function" ? config.resolve : void 0;
42
+ return (author) => {
43
+ const safeAuthor = author ?? {};
44
+ if (overrides) {
45
+ if (isNonEmptyString(safeAuthor.email) && isNonEmptyString(overrides[safeAuthor.email])) return overrides[safeAuthor.email];
46
+ if (isNonEmptyString(safeAuthor.name) && isNonEmptyString(overrides[safeAuthor.name])) return overrides[safeAuthor.name];
47
+ }
48
+ if (resolve) try {
49
+ const resolved = resolve(safeAuthor);
50
+ if (isNonEmptyString(resolved)) return resolved;
51
+ } catch {}
52
+ return fallbackAuthorColor(safeAuthor);
53
+ };
54
+ };
55
+ const DRAWING_DIAGNOSTIC_CODES = {
56
+ externalImageDeferred: "render.media.external-image-deferred",
57
+ missingRelationship: "render.drawing.missing-relationship",
58
+ missingMediaPart: "render.media.missing-part",
59
+ unsupportedRelationshipType: "render.drawing.unsupported-relationship-type",
60
+ unsupportedMime: "render.media.unsupported-mime",
61
+ imageTooLarge: "render.media.image-too-large",
62
+ unsafeSvg: "render.media.unsafe-svg",
63
+ unsupportedFormat: "render.media.unsupported-format",
64
+ embeddedObjectNotSupported: "render.embedded-object-not-supported",
65
+ unsupportedObject: "render.drawing.unsupported-object",
66
+ vmlUnsupported: "render.drawing.vml-unsupported",
67
+ vmlImageUnsupported: "render.drawing.vml-image-unsupported",
68
+ unsupportedGeometryCommand: "render.drawing.unsupported-geometry-command",
69
+ anchorUnsupported: "render.drawing.anchor-unsupported",
70
+ wrapUnsupported: "render.drawing.wrap-unsupported",
71
+ altContentNoSupportedChoice: "render.drawing.altcontent-no-supported-choice",
72
+ groupChildUnsupported: "render.drawing.group-child-unsupported"
73
+ };
74
+ DRAWING_DIAGNOSTIC_CODES.missingRelationship, DRAWING_DIAGNOSTIC_CODES.unsupportedRelationshipType, DRAWING_DIAGNOSTIC_CODES.unsupportedRelationshipType, DRAWING_DIAGNOSTIC_CODES.imageTooLarge, DRAWING_DIAGNOSTIC_CODES.missingMediaPart, DRAWING_DIAGNOSTIC_CODES.unsupportedObject, DRAWING_DIAGNOSTIC_CODES.vmlUnsupported;
75
+ DRAWING_DIAGNOSTIC_CODES.externalImageDeferred, DRAWING_DIAGNOSTIC_CODES.missingRelationship, DRAWING_DIAGNOSTIC_CODES.missingMediaPart, DRAWING_DIAGNOSTIC_CODES.unsupportedRelationshipType, DRAWING_DIAGNOSTIC_CODES.unsupportedMime, DRAWING_DIAGNOSTIC_CODES.imageTooLarge, DRAWING_DIAGNOSTIC_CODES.unsafeSvg, DRAWING_DIAGNOSTIC_CODES.unsupportedFormat, DRAWING_DIAGNOSTIC_CODES.embeddedObjectNotSupported, DRAWING_DIAGNOSTIC_CODES.unsupportedObject, DRAWING_DIAGNOSTIC_CODES.vmlUnsupported, DRAWING_DIAGNOSTIC_CODES.vmlImageUnsupported, DRAWING_DIAGNOSTIC_CODES.unsupportedGeometryCommand, DRAWING_DIAGNOSTIC_CODES.anchorUnsupported, DRAWING_DIAGNOSTIC_CODES.wrapUnsupported, DRAWING_DIAGNOSTIC_CODES.altContentNoSupportedChoice, DRAWING_DIAGNOSTIC_CODES.groupChildUnsupported;
76
+ Object.freeze([
77
+ "multiple-sections",
78
+ "furniture-page-tokens",
79
+ "non-balanceable-multi-column-sections",
80
+ "body-anchored-objects",
81
+ "footnotes",
82
+ "page-references",
83
+ "keep-constraints",
84
+ "tables",
85
+ "furniture-anchored-objects"
86
+ ]);
1
87
  function getV2TrackedChangeMutationImpact(event) {
2
88
  if (event?.type !== "mutation:committed") return null;
3
89
  const payload = event.origin === "history" ? event.result : event.receipt;
@@ -1262,6 +1348,11 @@ const HEAVY_DOC_READ_POLICY = [
1262
1348
  note: "reserved: full sections list"
1263
1349
  }
1264
1350
  ];
1351
+ var COMMENTS_CATALOG_PART_URIS = new Set([
1352
+ "/word/comments.xml",
1353
+ "/word/commentsExtended.xml",
1354
+ "/word/commentsIds.xml"
1355
+ ]);
1265
1356
  function isHeavyDocReadKey(key) {
1266
1357
  return HEAVY_DOC_READ_POLICY.some((entry) => entry.match === "exact" ? entry.key === key : key.startsWith(entry.key));
1267
1358
  }
@@ -2331,6 +2422,8 @@ function createSuperDocUI(options) {
2331
2422
  const superdoc = options.superdoc;
2332
2423
  const optimisticInlineValues = /* @__PURE__ */ new Map();
2333
2424
  const optimisticInlineToggles = /* @__PURE__ */ new Map();
2425
+ let optimisticParagraphAlignment = null;
2426
+ let optimisticParagraphAlignmentGeneration = 0;
2334
2427
  const pendingInlineToggleMutations = [];
2335
2428
  let lastOptimisticInlineSelectionSignature = null;
2336
2429
  let optimisticInlineToggleGeneration = 0;
@@ -2977,6 +3070,11 @@ function createSuperDocUI(options) {
2977
3070
  demandedHeavyReads.set(key, token);
2978
3071
  scheduleAsyncRefresh();
2979
3072
  };
3073
+ const commentsCatalogMayHaveRows = () => {
3074
+ const entry = asyncReads.get("comments");
3075
+ if (!entry?.hasSettled) return entry?.inflightToken != null;
3076
+ return Array.isArray(entry.value) && entry.value.length > 0;
3077
+ };
2980
3078
  const heavyReadDemandActive = (key, token) => demandedHeavyReads.get(key) === token;
2981
3079
  const ensureContentControlsCatalog = (_reason) => {
2982
3080
  demandHeavyDocRead("contentControls");
@@ -2993,20 +3091,28 @@ function createSuperDocUI(options) {
2993
3091
  let lastTypingMutationAtMs = 0;
2994
3092
  let heavyReadsHeldUntilIdle = false;
2995
3093
  let heavyReadsTypingHoldSinceMs = 0;
3094
+ let heavyReadCeilingReleaseActive = false;
2996
3095
  let heavyReadCompletionRecomputeTimer = null;
2997
3096
  const scheduleHeavyReadCompletionRecompute = () => {
2998
3097
  if (disposed || heavyReadCompletionRecomputeTimer) return;
2999
- const startedAtMs = Date.now();
3098
+ const startedAtMs = heavyReadsTypingHoldSinceMs || Date.now();
3000
3099
  const attempt = () => {
3001
3100
  heavyReadCompletionRecomputeTimer = null;
3002
3101
  if (disposed) return;
3003
3102
  const idleForMs = Date.now() - lastEditableMutationAtMs;
3004
- if ((foregroundMutationActive() || idleForMs < HEAVY_READ_IDLE_MS) && Date.now() - startedAtMs < HEAVY_READ_IDLE_CEILING_MS) {
3103
+ const busy = foregroundMutationActive() || idleForMs < HEAVY_READ_IDLE_MS;
3104
+ if (busy && Date.now() - startedAtMs < HEAVY_READ_IDLE_CEILING_MS) {
3005
3105
  heavyReadCompletionRecomputeTimer = setTimeout(attempt, HEAVY_READ_IDLE_POLL_MS);
3006
3106
  return;
3007
3107
  }
3008
3108
  heavyReadsHeldUntilIdle = false;
3009
- recompute();
3109
+ heavyReadCeilingReleaseActive = busy;
3110
+ try {
3111
+ recompute();
3112
+ } finally {
3113
+ heavyReadCeilingReleaseActive = false;
3114
+ heavyReadsTypingHoldSinceMs = 0;
3115
+ }
3010
3116
  };
3011
3117
  heavyReadCompletionRecomputeTimer = setTimeout(attempt, 0);
3012
3118
  };
@@ -3113,6 +3219,49 @@ function createSuperDocUI(options) {
3113
3219
  invalidateDocumentContent();
3114
3220
  recompute();
3115
3221
  };
3222
+ let pendingPostPaintContentRefresh = null;
3223
+ let postPaintContentRefreshRunning = false;
3224
+ let postPaintContentRefreshDrainToken = 0;
3225
+ const resetPostPaintContentRefresh = () => {
3226
+ pendingPostPaintContentRefresh = null;
3227
+ postPaintContentRefreshRunning = false;
3228
+ postPaintContentRefreshDrainToken += 1;
3229
+ };
3230
+ const schedulePostPaintContentRefresh = () => {
3231
+ const editor = getEditor();
3232
+ const readiness = editor?.documentMutationReadiness;
3233
+ if (!editor || typeof readiness?.whenPainted !== "function") return;
3234
+ pendingPostPaintContentRefresh = {
3235
+ editor,
3236
+ readiness,
3237
+ afterEpoch: typeof readiness.getRenderEpoch === "function" ? safeCall(() => readiness.getRenderEpoch.call(readiness), null) : null
3238
+ };
3239
+ if (postPaintContentRefreshRunning) return;
3240
+ postPaintContentRefreshRunning = true;
3241
+ const drainToken = postPaintContentRefreshDrainToken;
3242
+ const drain = async () => {
3243
+ while (!disposed && drainToken === postPaintContentRefreshDrainToken) {
3244
+ const request = pendingPostPaintContentRefresh;
3245
+ pendingPostPaintContentRefresh = null;
3246
+ if (!request) {
3247
+ postPaintContentRefreshRunning = false;
3248
+ return;
3249
+ }
3250
+ let paintCompleted = false;
3251
+ try {
3252
+ await request.readiness.whenPainted.call(request.readiness, typeof request.afterEpoch === "number" ? { afterEpoch: request.afterEpoch } : void 0);
3253
+ paintCompleted = true;
3254
+ } catch {}
3255
+ if (disposed || drainToken !== postPaintContentRefreshDrainToken) return;
3256
+ if (getEditor() !== request.editor) {
3257
+ resetPostPaintContentRefresh();
3258
+ return;
3259
+ }
3260
+ if (paintCompleted) invalidateDocumentContentAndRecompute();
3261
+ }
3262
+ };
3263
+ drain();
3264
+ };
3116
3265
  const scheduleTypingDocumentContentInvalidation = () => {
3117
3266
  if (typingContentInvalidationTimer) clearTimeout(typingContentInvalidationTimer);
3118
3267
  typingContentInvalidationTimer = setTimeout(() => {
@@ -3200,7 +3349,7 @@ function createSuperDocUI(options) {
3200
3349
  status: "pending"
3201
3350
  };
3202
3351
  }
3203
- if (heavyReadsHeldUntilIdle) {
3352
+ if (heavyReadsHeldUntilIdle && !heavyReadCeilingReleaseActive) {
3204
3353
  scheduleHeavyReadCompletionRecompute();
3205
3354
  if (entry?.hasSettled) return {
3206
3355
  value: entry.value,
@@ -3211,21 +3360,23 @@ function createSuperDocUI(options) {
3211
3360
  status: "pending"
3212
3361
  };
3213
3362
  }
3214
- const nowMs = Date.now();
3215
- if (nowMs - lastTypingMutationAtMs < HEAVY_READ_IDLE_MS && (!heavyReadsTypingHoldSinceMs || nowMs - heavyReadsTypingHoldSinceMs < HEAVY_READ_IDLE_CEILING_MS)) {
3216
- if (!heavyReadsTypingHoldSinceMs) heavyReadsTypingHoldSinceMs = nowMs;
3217
- heavyReadsHeldUntilIdle = true;
3218
- scheduleHeavyReadCompletionRecompute();
3219
- if (entry?.hasSettled) return {
3220
- value: entry.value,
3221
- status: "stale"
3222
- };
3223
- return {
3224
- value: null,
3225
- status: "pending"
3226
- };
3363
+ if (!heavyReadCeilingReleaseActive) {
3364
+ const nowMs = Date.now();
3365
+ if (nowMs - lastTypingMutationAtMs < HEAVY_READ_IDLE_MS && (!heavyReadsTypingHoldSinceMs || nowMs - heavyReadsTypingHoldSinceMs < HEAVY_READ_IDLE_CEILING_MS)) {
3366
+ if (!heavyReadsTypingHoldSinceMs) heavyReadsTypingHoldSinceMs = nowMs;
3367
+ heavyReadsHeldUntilIdle = true;
3368
+ scheduleHeavyReadCompletionRecompute();
3369
+ if (entry?.hasSettled) return {
3370
+ value: entry.value,
3371
+ status: "stale"
3372
+ };
3373
+ return {
3374
+ value: null,
3375
+ status: "pending"
3376
+ };
3377
+ }
3378
+ heavyReadsTypingHoldSinceMs = 0;
3227
3379
  }
3228
- heavyReadsTypingHoldSinceMs = 0;
3229
3380
  }
3230
3381
  if (foregroundMutationActive()) {
3231
3382
  scheduleForegroundAsyncRetry();
@@ -3297,6 +3448,7 @@ function createSuperDocUI(options) {
3297
3448
  const syncCoordinatorEditor = () => {
3298
3449
  const editor = getEditor();
3299
3450
  if (editor === lastCoordinatorEditor) return;
3451
+ resetPostPaintContentRefresh();
3300
3452
  reviewMutationReconciler.reset();
3301
3453
  reviewMutationToken = {};
3302
3454
  lastCoordinatorEditor = editor;
@@ -3310,6 +3462,7 @@ function createSuperDocUI(options) {
3310
3462
  pendingEffectiveInlineRead = null;
3311
3463
  lastEffectiveInlineReadKey = null;
3312
3464
  heldSettledInlineValues = null;
3465
+ optimisticParagraphAlignment = null;
3313
3466
  pendingSelectionSeedValidationToken = null;
3314
3467
  coldAsyncReadDeferrals.clear();
3315
3468
  demandedHeavyReads.clear();
@@ -4215,6 +4368,7 @@ function createSuperDocUI(options) {
4215
4368
  styleName: active.styleName
4216
4369
  };
4217
4370
  }
4371
+ if (descriptor.id === "text-align") return readToolbarParagraphAlignment(doc, selection$1);
4218
4372
  if (descriptor.id === "link") return readActiveLinkHref(doc, selection$1) ?? void 0;
4219
4373
  };
4220
4374
  const readListStateSnapshotForBlock = (doc, blockId, story) => {
@@ -4266,22 +4420,160 @@ function createSuperDocUI(options) {
4266
4420
  const readNodeById = (doc, blockId, story) => {
4267
4421
  if (!doc) return {
4268
4422
  value: null,
4269
- status: "ready"
4423
+ status: "ready",
4424
+ refreshing: false
4270
4425
  };
4271
4426
  const storySignature = storyLocatorSignature(story);
4272
4427
  const isBodyStory = storySignature === "story:body";
4273
4428
  if (isBodyStory && typeof doc.getNodeById !== "function") return {
4274
4429
  value: null,
4275
- status: "ready"
4430
+ status: "ready",
4431
+ refreshing: false
4276
4432
  };
4277
4433
  if (!isBodyStory && typeof doc.getNode !== "function") return {
4278
4434
  value: null,
4279
- status: "ready"
4435
+ status: "ready",
4436
+ refreshing: false
4280
4437
  };
4281
- return readAsync(`node:${storySignature}:${blockId}`, contentToken(), () => isBodyStory ? doc.getNodeById({
4438
+ const key = `node:${storySignature}:${blockId}`;
4439
+ const token = contentToken();
4440
+ const read = readAsync(key, token, () => isBodyStory ? doc.getNodeById({
4282
4441
  nodeId: blockId,
4283
4442
  nodeType: "paragraph"
4284
4443
  }) : doc.getNode(paragraphTarget(blockId, story)), (raw) => raw && typeof raw === "object" ? raw : null);
4444
+ const entry = asyncReads.get(key);
4445
+ return {
4446
+ ...read,
4447
+ refreshing: read.status === "stale" && entry?.inflightToken === token && entry.failedToken !== token
4448
+ };
4449
+ };
4450
+ const normalizeParagraphAlignment = (value) => {
4451
+ return value === "left" || value === "center" || value === "right" || value === "justify" ? value : void 0;
4452
+ };
4453
+ const isProjectionResolvedParagraphAlignment = (value) => {
4454
+ return value === "start" || value === "end" || value === "distributed" || value === "numTab" || value === "lowKashida" || value === "mediumKashida" || value === "highKashida" || value === "thaiDistribute";
4455
+ };
4456
+ const readEffectiveParagraphAlignments = (selection$1, blockIds) => {
4457
+ const host = getHost();
4458
+ const readByIds = host?.readMountedProjectionBlocksByIds;
4459
+ if (typeof readByIds !== "function") return null;
4460
+ const story = selectionStoryLocator(selection$1);
4461
+ const blocks = safeCall(() => story ? readByIds.call(host, [...blockIds], story) : readByIds.call(host, [...blockIds]), null);
4462
+ if (!Array.isArray(blocks)) return /* @__PURE__ */ new Map();
4463
+ const projectionBlocks = collectProjectionTextBlocks(blocks);
4464
+ const alignments = /* @__PURE__ */ new Map();
4465
+ for (const blockId of blockIds) {
4466
+ const block = projectionBlocks.find((candidate) => projectionBlockMatchesId(candidate, blockId));
4467
+ if (!block) continue;
4468
+ const attrs = block.attrs;
4469
+ const alignment = normalizeParagraphAlignment(attrs?.alignment);
4470
+ const inlineDirection = getParagraphInlineDirection(attrs);
4471
+ alignments.set(blockId, alignment ?? (inlineDirection === "rtl" ? "right" : "left"));
4472
+ }
4473
+ return alignments;
4474
+ };
4475
+ const readParagraphAlignment = (doc, blockId, story, effectiveAlignments) => {
4476
+ const { value: result, status, refreshing } = readNodeById(doc, blockId, story);
4477
+ const effective = effectiveAlignments?.get(blockId);
4478
+ if (status === "pending") return effective ? {
4479
+ status: "uniform",
4480
+ value: effective
4481
+ } : { status: "pending" };
4482
+ if (status === "stale" && !refreshing) return { status: "pending" };
4483
+ if (status === "stale" && effective) return {
4484
+ status: "uniform",
4485
+ value: effective
4486
+ };
4487
+ if (status === "stale" && effectiveAlignments && !effective) return { status: "unavailable" };
4488
+ if (!result) return { status: "unavailable" };
4489
+ const node = result.node;
4490
+ if (!node) return { status: "unavailable" };
4491
+ const kind = node.kind;
4492
+ if (kind !== "paragraph" && kind !== "heading") return { status: "unavailable" };
4493
+ const payload = node[kind];
4494
+ if (!payload || typeof payload !== "object") return { status: "unavailable" };
4495
+ const directAlignment = payload.props?.alignment;
4496
+ if (directAlignment == null) return effective ? {
4497
+ status: "uniform",
4498
+ value: effective
4499
+ } : { status: "unavailable" };
4500
+ const alignment = normalizeParagraphAlignment(directAlignment);
4501
+ if (alignment) return {
4502
+ status: "uniform",
4503
+ value: alignment
4504
+ };
4505
+ if (isProjectionResolvedParagraphAlignment(directAlignment) && effective) return {
4506
+ status: "uniform",
4507
+ value: effective
4508
+ };
4509
+ return { status: "unavailable" };
4510
+ };
4511
+ const readUniformParagraphAlignment = (doc, selection$1) => {
4512
+ const blockIds = selectionBlockIds(selection$1);
4513
+ if (blockIds.length === 0 || !canProbeEverySelectedBlock(blockIds)) return { status: "unavailable" };
4514
+ const story = selectionStory(selection$1);
4515
+ const effectiveAlignments = readEffectiveParagraphAlignments(selection$1, blockIds);
4516
+ const first = readParagraphAlignment(doc, blockIds[0], story, effectiveAlignments);
4517
+ if (first.status !== "uniform") return first;
4518
+ for (const blockId of blockIds.slice(1)) {
4519
+ const next = readParagraphAlignment(doc, blockId, story, effectiveAlignments);
4520
+ if (next.status !== "uniform") return next;
4521
+ if (next.value !== first.value) return { status: "mixed" };
4522
+ }
4523
+ return first;
4524
+ };
4525
+ const paragraphAlignmentSelectionSignature = (selection$1) => {
4526
+ const blockIds = selectionBlockIds(selection$1);
4527
+ if (blockIds.length === 0) return null;
4528
+ return `${storyLocatorSignature(selectionStory(selection$1))}:${blockIds.join(",")}`;
4529
+ };
4530
+ const readToolbarParagraphAlignment = (doc, selection$1) => {
4531
+ const resolution = readUniformParagraphAlignment(doc, selection$1);
4532
+ const resolved = resolution.status === "uniform" ? resolution.value : void 0;
4533
+ const optimistic = optimisticParagraphAlignment;
4534
+ if (!optimistic) return resolved;
4535
+ const selectionSignature$1 = paragraphAlignmentSelectionSignature(selection$1);
4536
+ if (selectionSignature$1 && selectionSignature$1 !== optimistic.selectionSignature) {
4537
+ optimisticParagraphAlignment = null;
4538
+ return resolved;
4539
+ }
4540
+ if (!selectionSignature$1) return optimistic.value;
4541
+ if (!optimistic.settled) return optimistic.value;
4542
+ if (resolution.status !== "pending") {
4543
+ optimisticParagraphAlignment = null;
4544
+ return resolved;
4545
+ }
4546
+ return optimistic.value;
4547
+ };
4548
+ const armOptimisticParagraphAlignment = (selection$1, payload) => {
4549
+ const alignment = normalizeParagraphAlignment(payload);
4550
+ const selectionSignature$1 = paragraphAlignmentSelectionSignature(selection$1);
4551
+ const blockIds = selectionBlockIds(selection$1);
4552
+ if (!alignment || !selectionSignature$1 || blockIds.length === 0) return null;
4553
+ const generation = ++optimisticParagraphAlignmentGeneration;
4554
+ optimisticParagraphAlignment = {
4555
+ selectionSignature: selectionSignature$1,
4556
+ value: alignment,
4557
+ generation,
4558
+ settled: false,
4559
+ canReconcile: canProbeEverySelectedBlock(blockIds)
4560
+ };
4561
+ recompute();
4562
+ return generation;
4563
+ };
4564
+ const settleOptimisticParagraphAlignment = (generation, result) => {
4565
+ if (generation == null) return;
4566
+ const optimistic = optimisticParagraphAlignment;
4567
+ if (!optimistic || optimistic.generation !== generation) return;
4568
+ if (!commandResultSucceeded(result)) {
4569
+ optimisticParagraphAlignment = null;
4570
+ return;
4571
+ }
4572
+ if (!optimistic.canReconcile) {
4573
+ optimisticParagraphAlignment = null;
4574
+ return;
4575
+ }
4576
+ optimistic.settled = true;
4285
4577
  };
4286
4578
  const resolveListMembershipForBlockAsync = async (doc, blockId, story) => {
4287
4579
  const listsApi = doc?.lists;
@@ -4932,12 +5224,12 @@ function createSuperDocUI(options) {
4932
5224
  }
4933
5225
  return;
4934
5226
  }
5227
+ if (type === "mutation:committed" || type === "collaboration:remote-changed") lastEditableMutationAtMs = Date.now();
4935
5228
  if (type === "mutation:committed") {
4936
- lastEditableMutationAtMs = Date.now();
4937
5229
  clearAuthoritativeTrackChangesRetry();
4938
5230
  reviewMutationToken = {};
4939
5231
  }
4940
- if (type === "mutation:committed" || type === "save:completed") {
5232
+ if (type === "mutation:committed" || type === "save:completed" || type === "collaboration:remote-changed") {
4941
5233
  const impact = type === "mutation:committed" ? getV2TrackedChangeMutationImpact(event) : null;
4942
5234
  const supersedesPendingReviewReconcile = type === "mutation:committed" && reviewMutationReconciler.getPendingIds().size > 0;
4943
5235
  if (impact?.removedIds.size) markPostDecisionTrackChanges(new Set(impact.removedIds), event.receipt);
@@ -4967,13 +5259,20 @@ function createSuperDocUI(options) {
4967
5259
  }
4968
5260
  }
4969
5261
  if (authoritativeHistoryImpact) return;
4970
- if (type === "mutation:committed" && isEditableTextMutationEvent(event)) {
4971
- lastTypingMutationAtMs = Date.now();
5262
+ const isTypingBurst = type === "mutation:committed" && isEditableTextMutationEvent(event) || type === "collaboration:remote-changed" && Array.isArray(event.changedStoryIds) && event.changedStoryIds.length > 0;
5263
+ if (isTypingBurst) lastTypingMutationAtMs = Date.now();
5264
+ if (type === "mutation:committed" && isTypingBurst) {
4972
5265
  scheduleTypingDocumentContentInvalidation();
4973
5266
  return;
4974
5267
  }
4975
5268
  if (impact?.removedIds.size && impact.upsertIds.size === 0) return;
4976
- invalidateDocumentContentAndRecompute();
5269
+ if (type === "collaboration:remote-changed" || type === "mutation:committed" && !isTypingBurst) schedulePostPaintContentRefresh();
5270
+ const remoteCommentsPartChanged = type === "collaboration:remote-changed" && Array.isArray(event.changedPartUris) && event.changedPartUris.some((partUri) => typeof partUri === "string" && COMMENTS_CATALOG_PART_URIS.has(partUri));
5271
+ const loadedCommentAnchorsMayHaveChanged = type === "collaboration:remote-changed" && Array.isArray(event.changedStoryIds) && event.changedStoryIds.length > 0 && commentsCatalogMayHaveRows();
5272
+ if (remoteCommentsPartChanged && !isTypingBurst) heavyReadsHeldUntilIdle = true;
5273
+ invalidateDocumentContent();
5274
+ if (remoteCommentsPartChanged || loadedCommentAnchorsMayHaveChanged) demandHeavyDocRead("comments");
5275
+ recompute();
4977
5276
  }
4978
5277
  });
4979
5278
  if (typeof off === "function") detachHostEvents = off;
@@ -6100,7 +6399,13 @@ function createSuperDocUI(options) {
6100
6399
  return false;
6101
6400
  }
6102
6401
  }
6103
- if (descriptor.blockParagraph) return settleCommandExecution(executeBlockParagraph(descriptor, op, normalized));
6402
+ if (descriptor.blockParagraph) {
6403
+ const result = executeBlockParagraph(descriptor, op, normalized);
6404
+ const optimisticAlignmentGeneration = descriptor.blockParagraph.kind === "alignment" && commandResultSucceeded(result) ? armOptimisticParagraphAlignment(state.selection, normalized) : null;
6405
+ return settleCommandExecution(result, (settled) => {
6406
+ settleOptimisticParagraphAlignment(optimisticAlignmentGeneration, settled);
6407
+ });
6408
+ }
6104
6409
  if (descriptor.list) return settleCommandExecution(executeListCommand(descriptor, op));
6105
6410
  if (descriptor.link) return settleCommandExecution(executeLinkCommand(normalized));
6106
6411
  if (descriptor.create) return settleCommandExecution(executeCreateCommand(descriptor, op, normalized));
@@ -8200,4 +8505,4 @@ var DEFAULT_FONT_SIZE_OPTIONS = [
8200
8505
  function commandIsActive(descriptor, selection) {
8201
8506
  return descriptor.activeMark ? selection.activeMarks.includes(descriptor.activeMark) : false;
8202
8507
  }
8203
- export { createV2ReviewMutationReconciler as a, isV2EditableTextMutationEvent as i, BUILT_IN_COMMAND_IDS as n, getV2TrackedChangeMutationImpact as o, shallowEqual as r, createSuperDocUI as t };
8508
+ export { createV2ReviewMutationReconciler as a, isV2EditableTextMutationEvent as i, BUILT_IN_COMMAND_IDS as n, getV2TrackedChangeMutationImpact as o, shallowEqual as r, composeAuthorColorResolver as s, createSuperDocUI as t };