superdoc 2.4.0-next.62 → 2.4.0-next.64
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-DNtHxzz_.cjs → create-super-doc-ui-Bom7oDPv.cjs} +110 -20
- package/dist/chunks/{create-super-doc-ui-B_1l545i.es.js → create-super-doc-ui-DbzVC0rr.es.js} +110 -20
- package/dist/collaboration-upgrade-engine.cjs +1 -1
- package/dist/collaboration-upgrade-engine.es.js +1 -1
- package/dist/layout-engine/contracts/src/index.d.ts +119 -0
- package/dist/layout-engine/painters/dom/src/chart-renderer.d.ts +3 -3
- package/dist/layout-engine/painters/dom/src/images/render-placeholder.d.ts +12 -0
- package/dist/layout-engine/painters/dom/src/renderer.d.ts +6 -0
- package/dist/layout-engine/painters/dom/src/runs/text-effects.d.ts +14 -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 +23 -23
- package/dist/style.layered.css +23 -23
- package/dist/superdoc.cjs +4 -3
- package/dist/superdoc.es.js +4 -3
- package/dist-cdn/style.layered.css +1 -1
- package/dist-cdn/superdoc.min.css +1 -1
- package/dist-cdn/superdoc.min.js +35 -35
- package/package.json +2 -2
|
@@ -1874,6 +1874,23 @@ INLINE_PROPERTY_REGISTRY.filter((entry) => entry.storage === "mark").map((entry)
|
|
|
1874
1874
|
* `false` when the surface is unavailable (view mode, a pre-ready editor, or a
|
|
1875
1875
|
* host that has not exposed a Document API facade) rather than throwing.
|
|
1876
1876
|
*/
|
|
1877
|
+
function uiBenchNowMs() {
|
|
1878
|
+
return typeof performance !== "undefined" && typeof performance.now === "function" ? performance.now() : Date.now();
|
|
1879
|
+
}
|
|
1880
|
+
function readUiBenchRuntime() {
|
|
1881
|
+
const benchGlobal = globalThis;
|
|
1882
|
+
return {
|
|
1883
|
+
sink: typeof benchGlobal.__superdocV2BenchPipelineTiming === "function" ? benchGlobal.__superdocV2BenchPipelineTiming : null,
|
|
1884
|
+
workerContext: benchGlobal.__superdocV2BenchWorkerMessageContext ?? null
|
|
1885
|
+
};
|
|
1886
|
+
}
|
|
1887
|
+
function emitUiBenchTiming(event) {
|
|
1888
|
+
const { sink } = readUiBenchRuntime();
|
|
1889
|
+
if (!sink) return;
|
|
1890
|
+
try {
|
|
1891
|
+
sink(event);
|
|
1892
|
+
} catch {}
|
|
1893
|
+
}
|
|
1877
1894
|
var sharedUiTrackedChangesCatalogByHost = /* @__PURE__ */ new WeakMap();
|
|
1878
1895
|
function acquireSharedUiTrackedChangesCatalog(host) {
|
|
1879
1896
|
let state = sharedUiTrackedChangesCatalogByHost.get(host);
|
|
@@ -3716,12 +3733,13 @@ function createSuperDocUI(options) {
|
|
|
3716
3733
|
let foregroundAsyncRetryTimer = null;
|
|
3717
3734
|
let pendingSelectionSeedValidationToken = null;
|
|
3718
3735
|
let typingContentInvalidationTimer = null;
|
|
3736
|
+
const pendingAsyncReadSettlements = [];
|
|
3719
3737
|
const scheduleAsyncRefresh = () => {
|
|
3720
3738
|
if (asyncRefreshScheduled || disposed) return;
|
|
3721
3739
|
asyncRefreshScheduled = true;
|
|
3722
3740
|
const run = () => {
|
|
3723
3741
|
asyncRefreshScheduled = false;
|
|
3724
|
-
if (!disposed) recompute();
|
|
3742
|
+
if (!disposed) recompute("async-read-settled");
|
|
3725
3743
|
};
|
|
3726
3744
|
if (typeof queueMicrotask === "function") queueMicrotask(run);
|
|
3727
3745
|
else Promise.resolve().then(run);
|
|
@@ -4275,6 +4293,24 @@ function createSuperDocUI(options) {
|
|
|
4275
4293
|
failureCount: 0,
|
|
4276
4294
|
retryAtMs: 0
|
|
4277
4295
|
});
|
|
4296
|
+
const { sink, workerContext } = readUiBenchRuntime();
|
|
4297
|
+
if (sink) {
|
|
4298
|
+
const settledAtMs = uiBenchNowMs();
|
|
4299
|
+
pendingAsyncReadSettlements.push({
|
|
4300
|
+
key,
|
|
4301
|
+
settledAtMs,
|
|
4302
|
+
commandId: workerContext?.commandId ?? null,
|
|
4303
|
+
commandKind: workerContext?.commandKind ?? null
|
|
4304
|
+
});
|
|
4305
|
+
emitUiBenchTiming({
|
|
4306
|
+
stage: "superdoc-ui-async-read-settled",
|
|
4307
|
+
atMs: settledAtMs,
|
|
4308
|
+
key,
|
|
4309
|
+
settledAtMs,
|
|
4310
|
+
commandId: workerContext?.commandId ?? null,
|
|
4311
|
+
commandKind: workerContext?.commandKind ?? null
|
|
4312
|
+
});
|
|
4313
|
+
}
|
|
4278
4314
|
scheduleAsyncRefresh();
|
|
4279
4315
|
}, () => {
|
|
4280
4316
|
const entry = asyncReads.get(key);
|
|
@@ -6535,31 +6571,57 @@ function createSuperDocUI(options) {
|
|
|
6535
6571
|
diagnostics
|
|
6536
6572
|
};
|
|
6537
6573
|
};
|
|
6538
|
-
const computeState = () => {
|
|
6539
|
-
const
|
|
6540
|
-
const
|
|
6574
|
+
const computeState = (reason = "direct") => {
|
|
6575
|
+
const { sink } = readUiBenchRuntime();
|
|
6576
|
+
const startedAtMs = sink ? uiBenchNowMs() : 0;
|
|
6577
|
+
const phaseMs = {};
|
|
6578
|
+
const measure = (phase, run) => {
|
|
6579
|
+
if (!sink) return run();
|
|
6580
|
+
const phaseStartedAtMs = uiBenchNowMs();
|
|
6581
|
+
try {
|
|
6582
|
+
return run();
|
|
6583
|
+
} finally {
|
|
6584
|
+
phaseMs[phase] = uiBenchNowMs() - phaseStartedAtMs;
|
|
6585
|
+
}
|
|
6586
|
+
};
|
|
6587
|
+
const documentMode = measure("documentMode", readDocumentMode);
|
|
6588
|
+
const selection = measure("selection", computeSelection);
|
|
6541
6589
|
if (selection.status === "ready") pruneSelectionScopedAsyncReads(selection);
|
|
6542
6590
|
reconcilePendingInlineFormat(selection);
|
|
6543
6591
|
const selectionSignature = selectionInlineValueSignature(selection);
|
|
6544
6592
|
for (const [commandId, optimistic] of optimisticInlineToggles) if (!selectionSignature || optimistic.selectionSignature !== selectionSignature) optimisticInlineToggles.delete(commandId);
|
|
6545
6593
|
else if (optimistic.settled && selection.status === "ready") optimisticInlineToggles.delete(commandId);
|
|
6546
|
-
|
|
6594
|
+
const nextState = {
|
|
6547
6595
|
ready: getEditor() != null,
|
|
6548
6596
|
documentMode,
|
|
6549
|
-
document: computeDocument
|
|
6597
|
+
document: measure("document", computeDocument),
|
|
6550
6598
|
selection,
|
|
6551
6599
|
toolbar: {
|
|
6552
6600
|
context: documentMode,
|
|
6553
|
-
commands: computeCommandStates(selection),
|
|
6601
|
+
commands: measure("toolbarCommands", () => computeCommandStates(selection)),
|
|
6554
6602
|
copyFormatActive: painter.mode !== "idle"
|
|
6555
6603
|
},
|
|
6556
|
-
comments: computeComments(selection),
|
|
6557
|
-
trackChanges: computeTrackChanges(selection),
|
|
6558
|
-
contentControls: computeContentControls(selection),
|
|
6559
|
-
zoom: computeZoom
|
|
6560
|
-
fonts: computeFonts
|
|
6561
|
-
styles: computeStyles(selection)
|
|
6562
|
-
};
|
|
6604
|
+
comments: measure("comments", () => computeComments(selection)),
|
|
6605
|
+
trackChanges: measure("trackChanges", () => computeTrackChanges(selection)),
|
|
6606
|
+
contentControls: measure("contentControls", () => computeContentControls(selection)),
|
|
6607
|
+
zoom: measure("zoom", computeZoom),
|
|
6608
|
+
fonts: measure("fonts", computeFonts),
|
|
6609
|
+
styles: measure("styles", () => computeStyles(selection))
|
|
6610
|
+
};
|
|
6611
|
+
if (sink) {
|
|
6612
|
+
const completedAtMs = uiBenchNowMs();
|
|
6613
|
+
emitUiBenchTiming({
|
|
6614
|
+
stage: "superdoc-ui-compute-state",
|
|
6615
|
+
atMs: completedAtMs,
|
|
6616
|
+
reason,
|
|
6617
|
+
startedAtMs,
|
|
6618
|
+
completedAtMs,
|
|
6619
|
+
durationMs: completedAtMs - startedAtMs,
|
|
6620
|
+
phaseMs,
|
|
6621
|
+
asyncReadSettlements: pendingAsyncReadSettlements.splice(0)
|
|
6622
|
+
});
|
|
6623
|
+
}
|
|
6624
|
+
return nextState;
|
|
6563
6625
|
};
|
|
6564
6626
|
const syncOptimisticInlineSelection = (selection) => {
|
|
6565
6627
|
const nextSignature = selectionInlineValueSignature(selection);
|
|
@@ -6644,7 +6706,7 @@ function createSuperDocUI(options) {
|
|
|
6644
6706
|
const unsubscribe = next.subscribe((snapshot) => {
|
|
6645
6707
|
selectionEpoch += 1;
|
|
6646
6708
|
seedCaretSelectionFromHost(snapshot);
|
|
6647
|
-
recompute();
|
|
6709
|
+
recompute("host-selection");
|
|
6648
6710
|
});
|
|
6649
6711
|
if (typeof unsubscribe === "function") detachHostSelection = unsubscribe;
|
|
6650
6712
|
} catch {
|
|
@@ -6752,7 +6814,7 @@ function createSuperDocUI(options) {
|
|
|
6752
6814
|
};
|
|
6753
6815
|
syncCoordinatorEditor();
|
|
6754
6816
|
syncTrackedChangeFocusFromHostReviewTarget(readHostActiveReviewTarget(readHostReviewSource()));
|
|
6755
|
-
state = computeState();
|
|
6817
|
+
state = computeState("initial");
|
|
6756
6818
|
lastOptimisticInlineSelectionSignature = selectionInlineValueSignature(state.selection);
|
|
6757
6819
|
const syncHostEventsSubscription = () => {
|
|
6758
6820
|
const events = (getEditor()?.host)?.events;
|
|
@@ -6820,8 +6882,10 @@ function createSuperDocUI(options) {
|
|
|
6820
6882
|
currentHostEventsSource = null;
|
|
6821
6883
|
}
|
|
6822
6884
|
};
|
|
6823
|
-
const recompute = () => {
|
|
6885
|
+
const recompute = (reason = "unspecified") => {
|
|
6824
6886
|
if (disposed) return;
|
|
6887
|
+
const { sink } = readUiBenchRuntime();
|
|
6888
|
+
const startedAtMs = sink ? uiBenchNowMs() : 0;
|
|
6825
6889
|
editCommandsRecomputeQueued = false;
|
|
6826
6890
|
syncCoordinatorEditor();
|
|
6827
6891
|
syncHostSelectionSubscription();
|
|
@@ -6830,10 +6894,36 @@ function createSuperDocUI(options) {
|
|
|
6830
6894
|
syncHostReviewSubscription();
|
|
6831
6895
|
syncDocumentSelectionFallbackSubscription();
|
|
6832
6896
|
syncHostEventsSubscription();
|
|
6833
|
-
const nextState = computeState();
|
|
6897
|
+
const nextState = computeState(reason);
|
|
6834
6898
|
syncOptimisticInlineSelection(nextState.selection);
|
|
6835
6899
|
state = nextState;
|
|
6836
|
-
|
|
6900
|
+
let listenerTotalMs = 0;
|
|
6901
|
+
let listenerMaxMs = 0;
|
|
6902
|
+
for (const listener of [...listeners]) {
|
|
6903
|
+
if (!sink) {
|
|
6904
|
+
listener(state);
|
|
6905
|
+
continue;
|
|
6906
|
+
}
|
|
6907
|
+
const listenerStartedAtMs = uiBenchNowMs();
|
|
6908
|
+
listener(state);
|
|
6909
|
+
const listenerMs = uiBenchNowMs() - listenerStartedAtMs;
|
|
6910
|
+
listenerTotalMs += listenerMs;
|
|
6911
|
+
listenerMaxMs = Math.max(listenerMaxMs, listenerMs);
|
|
6912
|
+
}
|
|
6913
|
+
if (sink) {
|
|
6914
|
+
const completedAtMs = uiBenchNowMs();
|
|
6915
|
+
emitUiBenchTiming({
|
|
6916
|
+
stage: "superdoc-ui-recompute",
|
|
6917
|
+
atMs: completedAtMs,
|
|
6918
|
+
reason,
|
|
6919
|
+
startedAtMs,
|
|
6920
|
+
completedAtMs,
|
|
6921
|
+
durationMs: completedAtMs - startedAtMs,
|
|
6922
|
+
listenerCount: listeners.size,
|
|
6923
|
+
listenerTotalMs,
|
|
6924
|
+
listenerMaxMs
|
|
6925
|
+
});
|
|
6926
|
+
}
|
|
6837
6927
|
};
|
|
6838
6928
|
/**
|
|
6839
6929
|
* Work that is bound to one specific active editor and cannot survive a swap.
|
|
@@ -7423,7 +7513,7 @@ function createSuperDocUI(options) {
|
|
|
7423
7513
|
if (options && options.success === false) return options;
|
|
7424
7514
|
if (!selection.selectionTarget) return options ? op(input, options) : op(input);
|
|
7425
7515
|
return op(input, {
|
|
7426
|
-
...options
|
|
7516
|
+
...options,
|
|
7427
7517
|
offsetSpace: "selection"
|
|
7428
7518
|
});
|
|
7429
7519
|
};
|
package/dist/chunks/{create-super-doc-ui-B_1l545i.es.js → create-super-doc-ui-DbzVC0rr.es.js}
RENAMED
|
@@ -1874,6 +1874,23 @@ INLINE_PROPERTY_REGISTRY.filter((entry) => entry.storage === "mark").map((entry)
|
|
|
1874
1874
|
* `false` when the surface is unavailable (view mode, a pre-ready editor, or a
|
|
1875
1875
|
* host that has not exposed a Document API facade) rather than throwing.
|
|
1876
1876
|
*/
|
|
1877
|
+
function uiBenchNowMs() {
|
|
1878
|
+
return typeof performance !== "undefined" && typeof performance.now === "function" ? performance.now() : Date.now();
|
|
1879
|
+
}
|
|
1880
|
+
function readUiBenchRuntime() {
|
|
1881
|
+
const benchGlobal = globalThis;
|
|
1882
|
+
return {
|
|
1883
|
+
sink: typeof benchGlobal.__superdocV2BenchPipelineTiming === "function" ? benchGlobal.__superdocV2BenchPipelineTiming : null,
|
|
1884
|
+
workerContext: benchGlobal.__superdocV2BenchWorkerMessageContext ?? null
|
|
1885
|
+
};
|
|
1886
|
+
}
|
|
1887
|
+
function emitUiBenchTiming(event) {
|
|
1888
|
+
const { sink } = readUiBenchRuntime();
|
|
1889
|
+
if (!sink) return;
|
|
1890
|
+
try {
|
|
1891
|
+
sink(event);
|
|
1892
|
+
} catch {}
|
|
1893
|
+
}
|
|
1877
1894
|
var sharedUiTrackedChangesCatalogByHost = /* @__PURE__ */ new WeakMap();
|
|
1878
1895
|
function acquireSharedUiTrackedChangesCatalog(host) {
|
|
1879
1896
|
let state = sharedUiTrackedChangesCatalogByHost.get(host);
|
|
@@ -3716,12 +3733,13 @@ function createSuperDocUI(options) {
|
|
|
3716
3733
|
let foregroundAsyncRetryTimer = null;
|
|
3717
3734
|
let pendingSelectionSeedValidationToken = null;
|
|
3718
3735
|
let typingContentInvalidationTimer = null;
|
|
3736
|
+
const pendingAsyncReadSettlements = [];
|
|
3719
3737
|
const scheduleAsyncRefresh = () => {
|
|
3720
3738
|
if (asyncRefreshScheduled || disposed) return;
|
|
3721
3739
|
asyncRefreshScheduled = true;
|
|
3722
3740
|
const run = () => {
|
|
3723
3741
|
asyncRefreshScheduled = false;
|
|
3724
|
-
if (!disposed) recompute();
|
|
3742
|
+
if (!disposed) recompute("async-read-settled");
|
|
3725
3743
|
};
|
|
3726
3744
|
if (typeof queueMicrotask === "function") queueMicrotask(run);
|
|
3727
3745
|
else Promise.resolve().then(run);
|
|
@@ -4275,6 +4293,24 @@ function createSuperDocUI(options) {
|
|
|
4275
4293
|
failureCount: 0,
|
|
4276
4294
|
retryAtMs: 0
|
|
4277
4295
|
});
|
|
4296
|
+
const { sink, workerContext } = readUiBenchRuntime();
|
|
4297
|
+
if (sink) {
|
|
4298
|
+
const settledAtMs = uiBenchNowMs();
|
|
4299
|
+
pendingAsyncReadSettlements.push({
|
|
4300
|
+
key,
|
|
4301
|
+
settledAtMs,
|
|
4302
|
+
commandId: workerContext?.commandId ?? null,
|
|
4303
|
+
commandKind: workerContext?.commandKind ?? null
|
|
4304
|
+
});
|
|
4305
|
+
emitUiBenchTiming({
|
|
4306
|
+
stage: "superdoc-ui-async-read-settled",
|
|
4307
|
+
atMs: settledAtMs,
|
|
4308
|
+
key,
|
|
4309
|
+
settledAtMs,
|
|
4310
|
+
commandId: workerContext?.commandId ?? null,
|
|
4311
|
+
commandKind: workerContext?.commandKind ?? null
|
|
4312
|
+
});
|
|
4313
|
+
}
|
|
4278
4314
|
scheduleAsyncRefresh();
|
|
4279
4315
|
}, () => {
|
|
4280
4316
|
const entry = asyncReads.get(key);
|
|
@@ -6535,31 +6571,57 @@ function createSuperDocUI(options) {
|
|
|
6535
6571
|
diagnostics
|
|
6536
6572
|
};
|
|
6537
6573
|
};
|
|
6538
|
-
const computeState = () => {
|
|
6539
|
-
const
|
|
6540
|
-
const
|
|
6574
|
+
const computeState = (reason = "direct") => {
|
|
6575
|
+
const { sink } = readUiBenchRuntime();
|
|
6576
|
+
const startedAtMs = sink ? uiBenchNowMs() : 0;
|
|
6577
|
+
const phaseMs = {};
|
|
6578
|
+
const measure = (phase, run) => {
|
|
6579
|
+
if (!sink) return run();
|
|
6580
|
+
const phaseStartedAtMs = uiBenchNowMs();
|
|
6581
|
+
try {
|
|
6582
|
+
return run();
|
|
6583
|
+
} finally {
|
|
6584
|
+
phaseMs[phase] = uiBenchNowMs() - phaseStartedAtMs;
|
|
6585
|
+
}
|
|
6586
|
+
};
|
|
6587
|
+
const documentMode = measure("documentMode", readDocumentMode);
|
|
6588
|
+
const selection = measure("selection", computeSelection);
|
|
6541
6589
|
if (selection.status === "ready") pruneSelectionScopedAsyncReads(selection);
|
|
6542
6590
|
reconcilePendingInlineFormat(selection);
|
|
6543
6591
|
const selectionSignature = selectionInlineValueSignature(selection);
|
|
6544
6592
|
for (const [commandId, optimistic] of optimisticInlineToggles) if (!selectionSignature || optimistic.selectionSignature !== selectionSignature) optimisticInlineToggles.delete(commandId);
|
|
6545
6593
|
else if (optimistic.settled && selection.status === "ready") optimisticInlineToggles.delete(commandId);
|
|
6546
|
-
|
|
6594
|
+
const nextState = {
|
|
6547
6595
|
ready: getEditor() != null,
|
|
6548
6596
|
documentMode,
|
|
6549
|
-
document: computeDocument
|
|
6597
|
+
document: measure("document", computeDocument),
|
|
6550
6598
|
selection,
|
|
6551
6599
|
toolbar: {
|
|
6552
6600
|
context: documentMode,
|
|
6553
|
-
commands: computeCommandStates(selection),
|
|
6601
|
+
commands: measure("toolbarCommands", () => computeCommandStates(selection)),
|
|
6554
6602
|
copyFormatActive: painter.mode !== "idle"
|
|
6555
6603
|
},
|
|
6556
|
-
comments: computeComments(selection),
|
|
6557
|
-
trackChanges: computeTrackChanges(selection),
|
|
6558
|
-
contentControls: computeContentControls(selection),
|
|
6559
|
-
zoom: computeZoom
|
|
6560
|
-
fonts: computeFonts
|
|
6561
|
-
styles: computeStyles(selection)
|
|
6562
|
-
};
|
|
6604
|
+
comments: measure("comments", () => computeComments(selection)),
|
|
6605
|
+
trackChanges: measure("trackChanges", () => computeTrackChanges(selection)),
|
|
6606
|
+
contentControls: measure("contentControls", () => computeContentControls(selection)),
|
|
6607
|
+
zoom: measure("zoom", computeZoom),
|
|
6608
|
+
fonts: measure("fonts", computeFonts),
|
|
6609
|
+
styles: measure("styles", () => computeStyles(selection))
|
|
6610
|
+
};
|
|
6611
|
+
if (sink) {
|
|
6612
|
+
const completedAtMs = uiBenchNowMs();
|
|
6613
|
+
emitUiBenchTiming({
|
|
6614
|
+
stage: "superdoc-ui-compute-state",
|
|
6615
|
+
atMs: completedAtMs,
|
|
6616
|
+
reason,
|
|
6617
|
+
startedAtMs,
|
|
6618
|
+
completedAtMs,
|
|
6619
|
+
durationMs: completedAtMs - startedAtMs,
|
|
6620
|
+
phaseMs,
|
|
6621
|
+
asyncReadSettlements: pendingAsyncReadSettlements.splice(0)
|
|
6622
|
+
});
|
|
6623
|
+
}
|
|
6624
|
+
return nextState;
|
|
6563
6625
|
};
|
|
6564
6626
|
const syncOptimisticInlineSelection = (selection) => {
|
|
6565
6627
|
const nextSignature = selectionInlineValueSignature(selection);
|
|
@@ -6644,7 +6706,7 @@ function createSuperDocUI(options) {
|
|
|
6644
6706
|
const unsubscribe = next.subscribe((snapshot) => {
|
|
6645
6707
|
selectionEpoch += 1;
|
|
6646
6708
|
seedCaretSelectionFromHost(snapshot);
|
|
6647
|
-
recompute();
|
|
6709
|
+
recompute("host-selection");
|
|
6648
6710
|
});
|
|
6649
6711
|
if (typeof unsubscribe === "function") detachHostSelection = unsubscribe;
|
|
6650
6712
|
} catch {
|
|
@@ -6752,7 +6814,7 @@ function createSuperDocUI(options) {
|
|
|
6752
6814
|
};
|
|
6753
6815
|
syncCoordinatorEditor();
|
|
6754
6816
|
syncTrackedChangeFocusFromHostReviewTarget(readHostActiveReviewTarget(readHostReviewSource()));
|
|
6755
|
-
state = computeState();
|
|
6817
|
+
state = computeState("initial");
|
|
6756
6818
|
lastOptimisticInlineSelectionSignature = selectionInlineValueSignature(state.selection);
|
|
6757
6819
|
const syncHostEventsSubscription = () => {
|
|
6758
6820
|
const events = (getEditor()?.host)?.events;
|
|
@@ -6820,8 +6882,10 @@ function createSuperDocUI(options) {
|
|
|
6820
6882
|
currentHostEventsSource = null;
|
|
6821
6883
|
}
|
|
6822
6884
|
};
|
|
6823
|
-
const recompute = () => {
|
|
6885
|
+
const recompute = (reason = "unspecified") => {
|
|
6824
6886
|
if (disposed) return;
|
|
6887
|
+
const { sink } = readUiBenchRuntime();
|
|
6888
|
+
const startedAtMs = sink ? uiBenchNowMs() : 0;
|
|
6825
6889
|
editCommandsRecomputeQueued = false;
|
|
6826
6890
|
syncCoordinatorEditor();
|
|
6827
6891
|
syncHostSelectionSubscription();
|
|
@@ -6830,10 +6894,36 @@ function createSuperDocUI(options) {
|
|
|
6830
6894
|
syncHostReviewSubscription();
|
|
6831
6895
|
syncDocumentSelectionFallbackSubscription();
|
|
6832
6896
|
syncHostEventsSubscription();
|
|
6833
|
-
const nextState = computeState();
|
|
6897
|
+
const nextState = computeState(reason);
|
|
6834
6898
|
syncOptimisticInlineSelection(nextState.selection);
|
|
6835
6899
|
state = nextState;
|
|
6836
|
-
|
|
6900
|
+
let listenerTotalMs = 0;
|
|
6901
|
+
let listenerMaxMs = 0;
|
|
6902
|
+
for (const listener of [...listeners]) {
|
|
6903
|
+
if (!sink) {
|
|
6904
|
+
listener(state);
|
|
6905
|
+
continue;
|
|
6906
|
+
}
|
|
6907
|
+
const listenerStartedAtMs = uiBenchNowMs();
|
|
6908
|
+
listener(state);
|
|
6909
|
+
const listenerMs = uiBenchNowMs() - listenerStartedAtMs;
|
|
6910
|
+
listenerTotalMs += listenerMs;
|
|
6911
|
+
listenerMaxMs = Math.max(listenerMaxMs, listenerMs);
|
|
6912
|
+
}
|
|
6913
|
+
if (sink) {
|
|
6914
|
+
const completedAtMs = uiBenchNowMs();
|
|
6915
|
+
emitUiBenchTiming({
|
|
6916
|
+
stage: "superdoc-ui-recompute",
|
|
6917
|
+
atMs: completedAtMs,
|
|
6918
|
+
reason,
|
|
6919
|
+
startedAtMs,
|
|
6920
|
+
completedAtMs,
|
|
6921
|
+
durationMs: completedAtMs - startedAtMs,
|
|
6922
|
+
listenerCount: listeners.size,
|
|
6923
|
+
listenerTotalMs,
|
|
6924
|
+
listenerMaxMs
|
|
6925
|
+
});
|
|
6926
|
+
}
|
|
6837
6927
|
};
|
|
6838
6928
|
/**
|
|
6839
6929
|
* Work that is bound to one specific active editor and cannot survive a swap.
|
|
@@ -7423,7 +7513,7 @@ function createSuperDocUI(options) {
|
|
|
7423
7513
|
if (options && options.success === false) return options;
|
|
7424
7514
|
if (!selection.selectionTarget) return options ? op(input, options) : op(input);
|
|
7425
7515
|
return op(input, {
|
|
7426
|
-
...options
|
|
7516
|
+
...options,
|
|
7427
7517
|
offsetSpace: "selection"
|
|
7428
7518
|
});
|
|
7429
7519
|
};
|
|
@@ -19,7 +19,7 @@ var COLLABORATION_UPGRADE_ENGINE_MINIMUM_NODE_MAJOR = 20;
|
|
|
19
19
|
var PRIVATE_ENGINE_INFO = (0, _superdoc_docx_engine_collaboration_upgrade_engine.getCollaborationUpgradeEngineInfo)();
|
|
20
20
|
var ENGINE_INFO = Object.freeze({
|
|
21
21
|
...PRIVATE_ENGINE_INFO,
|
|
22
|
-
superdocVersion: "2.4.0-next.
|
|
22
|
+
superdocVersion: "2.4.0-next.64",
|
|
23
23
|
roomSchemaVersion: Object.freeze({ ...PRIVATE_ENGINE_INFO.roomSchemaVersion }),
|
|
24
24
|
supportedBundleVersions: SUPPORTED_COLLABORATION_UPGRADE_BUNDLE_VERSIONS,
|
|
25
25
|
supportedV1ReaderContractVersions: SUPPORTED_V1_READER_CONTRACT_VERSIONS
|
|
@@ -18,7 +18,7 @@ var COLLABORATION_UPGRADE_ENGINE_MINIMUM_NODE_MAJOR = 20;
|
|
|
18
18
|
var PRIVATE_ENGINE_INFO = getCollaborationUpgradeEngineInfo$1();
|
|
19
19
|
var ENGINE_INFO = Object.freeze({
|
|
20
20
|
...PRIVATE_ENGINE_INFO,
|
|
21
|
-
superdocVersion: "2.4.0-next.
|
|
21
|
+
superdocVersion: "2.4.0-next.64",
|
|
22
22
|
roomSchemaVersion: Object.freeze({ ...PRIVATE_ENGINE_INFO.roomSchemaVersion }),
|
|
23
23
|
supportedBundleVersions: SUPPORTED_COLLABORATION_UPGRADE_BUNDLE_VERSIONS,
|
|
24
24
|
supportedV1ReaderContractVersions: SUPPORTED_V1_READER_CONTRACT_VERSIONS
|
|
@@ -318,6 +318,8 @@ export type RunMarks = {
|
|
|
318
318
|
* Rendering normalizes a shift of zero to "no explicit shift".
|
|
319
319
|
*/
|
|
320
320
|
baselineShift?: number;
|
|
321
|
+
/** Paint-only Word 2010+ text effects (`w14:textFill`, outline, shadow, reflection). */
|
|
322
|
+
textEffects?: TextEffects;
|
|
321
323
|
};
|
|
322
324
|
export type PageReferenceRelativePositionText = 'above' | 'below';
|
|
323
325
|
export type FieldResultFormat = 'charformat' | 'mergeformat';
|
|
@@ -473,6 +475,18 @@ export type ImageHyperlink = {
|
|
|
473
475
|
* baseline next to the surrounding text instead of floating above it.
|
|
474
476
|
*/
|
|
475
477
|
export type ImageRunVerticalAlign = 'top' | 'bottom' | 'baseline';
|
|
478
|
+
/**
|
|
479
|
+
* Explicit fail-closed rendering metadata for content that keeps its authored
|
|
480
|
+
* layout box but cannot be painted faithfully.
|
|
481
|
+
*
|
|
482
|
+
* The producer owns the diagnostic identity; painters only expose it on the
|
|
483
|
+
* visible, accessible placeholder. This keeps support decisions out of the DOM
|
|
484
|
+
* layer and makes degraded output observable in browser regression proofs.
|
|
485
|
+
*/
|
|
486
|
+
export type RenderPlaceholder = {
|
|
487
|
+
diagnosticIds: string[];
|
|
488
|
+
accessibleName: string;
|
|
489
|
+
};
|
|
476
490
|
/**
|
|
477
491
|
* Inline image run for images that flow with text on the same line.
|
|
478
492
|
* Unlike ImageBlock (anchored/floating images), ImageRun is part of the paragraph's run array
|
|
@@ -499,10 +513,16 @@ export type ImageRun = {
|
|
|
499
513
|
width: number;
|
|
500
514
|
/** Image height in pixels. */
|
|
501
515
|
height: number;
|
|
516
|
+
/** Font family of the owning OOXML run, used to compose an image-only line box. */
|
|
517
|
+
fontFamily?: string;
|
|
518
|
+
/** Font size of the owning OOXML run, used to compose an image-only line box. */
|
|
519
|
+
fontSize?: number;
|
|
502
520
|
/** Alternative text for accessibility. */
|
|
503
521
|
alt?: string;
|
|
504
522
|
/** Image title (tooltip). */
|
|
505
523
|
title?: string;
|
|
524
|
+
/** Visible fail-closed replacement when the image source cannot be painted. */
|
|
525
|
+
placeholder?: RenderPlaceholder;
|
|
506
526
|
/** DrawingML docPr/@id of the picture (used to target the Document API for interactive resize). */
|
|
507
527
|
imageId?: string;
|
|
508
528
|
/** Clip-path value for cropped images. */
|
|
@@ -891,6 +911,8 @@ export type ImageBlock = {
|
|
|
891
911
|
height?: number;
|
|
892
912
|
alt?: string;
|
|
893
913
|
title?: string;
|
|
914
|
+
/** Visible fail-closed replacement when the image source cannot be painted. */
|
|
915
|
+
placeholder?: RenderPlaceholder;
|
|
894
916
|
/** DrawingML docPr/@id of the picture (used to target the Document API for interactive resize). */
|
|
895
917
|
imageId?: string;
|
|
896
918
|
objectFit?: 'contain' | 'cover' | 'fill' | 'scale-down';
|
|
@@ -986,6 +1008,52 @@ export type TextFormatting = {
|
|
|
986
1008
|
fontSize?: number;
|
|
987
1009
|
fontFamily?: string;
|
|
988
1010
|
letterSpacing?: number;
|
|
1011
|
+
/** Paint-only Word 2010+ text effects shared with ordinary text runs. */
|
|
1012
|
+
textEffects?: TextEffects;
|
|
1013
|
+
};
|
|
1014
|
+
/** Solid color used by a text effect, with optional opacity. */
|
|
1015
|
+
export type TextEffectColor = {
|
|
1016
|
+
color: string;
|
|
1017
|
+
alpha?: number;
|
|
1018
|
+
};
|
|
1019
|
+
/** Word 2010+ text outline (`w14:textOutline`). */
|
|
1020
|
+
export type TextOutlineEffect = {
|
|
1021
|
+
/** Outline width converted from EMU to CSS pixels. */
|
|
1022
|
+
width: number;
|
|
1023
|
+
fill: FillColor;
|
|
1024
|
+
};
|
|
1025
|
+
/** Word 2010+ outer text shadow (`w14:shadow`). */
|
|
1026
|
+
export type TextShadowEffect = {
|
|
1027
|
+
color: TextEffectColor;
|
|
1028
|
+
/** Blur radius converted from EMU to CSS pixels. */
|
|
1029
|
+
blurRadius: number;
|
|
1030
|
+
/** Shadow distance converted from EMU to CSS pixels. */
|
|
1031
|
+
distance: number;
|
|
1032
|
+
/** Direction in DrawingML degrees (`0` points right, `90` points down). */
|
|
1033
|
+
direction: number;
|
|
1034
|
+
};
|
|
1035
|
+
/** Word 2010+ reflected-text mask (`w14:reflection`). */
|
|
1036
|
+
export type TextReflectionEffect = {
|
|
1037
|
+
blurRadius: number;
|
|
1038
|
+
distance: number;
|
|
1039
|
+
direction: number;
|
|
1040
|
+
startAlpha: number;
|
|
1041
|
+
startPosition: number;
|
|
1042
|
+
endAlpha: number;
|
|
1043
|
+
endPosition: number;
|
|
1044
|
+
scaleX: number;
|
|
1045
|
+
scaleY: number;
|
|
1046
|
+
};
|
|
1047
|
+
/**
|
|
1048
|
+
* Paint-only text effects shared by paragraph runs and flattened shape text.
|
|
1049
|
+
* These effects do not change glyph advances, so layout measurement continues
|
|
1050
|
+
* to use the run's ordinary typography contract.
|
|
1051
|
+
*/
|
|
1052
|
+
export type TextEffects = {
|
|
1053
|
+
fill?: FillColor;
|
|
1054
|
+
outline?: TextOutlineEffect;
|
|
1055
|
+
shadow?: TextShadowEffect;
|
|
1056
|
+
reflection?: TextReflectionEffect;
|
|
989
1057
|
};
|
|
990
1058
|
/** A single text part with optional formatting. */
|
|
991
1059
|
export type TextPart = {
|
|
@@ -1041,6 +1109,20 @@ export type ShapeTextContent = {
|
|
|
1041
1109
|
/** Horizontal text alignment within the shape. */
|
|
1042
1110
|
horizontalAlign?: 'left' | 'center' | 'right';
|
|
1043
1111
|
};
|
|
1112
|
+
/** DrawingML textbox flow/overflow semantics from `a:bodyPr`. */
|
|
1113
|
+
export type ShapeTextLayout = {
|
|
1114
|
+
/** `a:bodyPr/@wrap`; `none` keeps authored paragraphs on explicit lines only. */
|
|
1115
|
+
wrap?: 'square' | 'none';
|
|
1116
|
+
/** `a:bodyPr/@horzOverflow`. */
|
|
1117
|
+
horizontalOverflow?: 'overflow' | 'clip';
|
|
1118
|
+
/** `a:bodyPr/@vertOverflow`. */
|
|
1119
|
+
verticalOverflow?: 'overflow' | 'clip' | 'ellipsis';
|
|
1120
|
+
};
|
|
1121
|
+
/** Resolve the line-breaking width for DrawingML textbox content. */
|
|
1122
|
+
export declare function resolveShapeTextContentMeasureWidth(shapeWidth: number, insets: {
|
|
1123
|
+
left: number;
|
|
1124
|
+
right: number;
|
|
1125
|
+
}, layout: ShapeTextLayout | undefined, autoFitBoundaryWidth?: number): number;
|
|
1044
1126
|
export type LineEnd = {
|
|
1045
1127
|
type?: string;
|
|
1046
1128
|
width?: string;
|
|
@@ -1056,8 +1138,38 @@ export type EffectExtent = {
|
|
|
1056
1138
|
right: number;
|
|
1057
1139
|
bottom: number;
|
|
1058
1140
|
};
|
|
1141
|
+
/**
|
|
1142
|
+
* DrawingML relative rectangle in the source 1000ths-of-a-percent units.
|
|
1143
|
+
* Values may be negative: ECMA-376 allows an outset as well as an inset.
|
|
1144
|
+
*/
|
|
1145
|
+
export type ShapeImageFillRect = {
|
|
1146
|
+
left: number;
|
|
1147
|
+
top: number;
|
|
1148
|
+
right: number;
|
|
1149
|
+
bottom: number;
|
|
1150
|
+
};
|
|
1151
|
+
/** DrawingML `a:tile` parameters, preserved without painter-specific conversion. */
|
|
1152
|
+
export type ShapeImageFillTile = {
|
|
1153
|
+
offsetX?: number;
|
|
1154
|
+
offsetY?: number;
|
|
1155
|
+
scaleX?: number;
|
|
1156
|
+
scaleY?: number;
|
|
1157
|
+
flip?: string;
|
|
1158
|
+
alignment?: string;
|
|
1159
|
+
};
|
|
1160
|
+
/** Resolved bitmap used as the fill paint for vector geometry. */
|
|
1161
|
+
export type ShapeImageFill = {
|
|
1162
|
+
src: string;
|
|
1163
|
+
mode: 'stretch' | 'tile';
|
|
1164
|
+
sourceRect?: ShapeImageFillRect;
|
|
1165
|
+
fillRect?: ShapeImageFillRect;
|
|
1166
|
+
tile?: ShapeImageFillTile;
|
|
1167
|
+
dpi?: number;
|
|
1168
|
+
rotateWithShape?: boolean;
|
|
1169
|
+
};
|
|
1059
1170
|
export type VectorShapeStyle = {
|
|
1060
1171
|
fillColor?: FillColor;
|
|
1172
|
+
imageFill?: ShapeImageFill;
|
|
1061
1173
|
strokeColor?: StrokeColor;
|
|
1062
1174
|
strokeWidth?: number;
|
|
1063
1175
|
/** Physical CSS-pixel dash/gap lengths resolved from the source stroke. */
|
|
@@ -1068,6 +1180,7 @@ export type VectorShapeStyle = {
|
|
|
1068
1180
|
borders?: CellBorders;
|
|
1069
1181
|
lineEnds?: LineEnds;
|
|
1070
1182
|
textContent?: ShapeTextContent;
|
|
1183
|
+
textLayout?: ShapeTextLayout;
|
|
1071
1184
|
textAlign?: string;
|
|
1072
1185
|
textVerticalAlign?: 'top' | 'center' | 'bottom';
|
|
1073
1186
|
/** Legacy VML textbox text-flow semantics. */
|
|
@@ -1129,6 +1242,8 @@ export type DrawingBlockBase = {
|
|
|
1129
1242
|
drawingContent?: DrawingContentSnapshot;
|
|
1130
1243
|
attrs?: Record<string, unknown>;
|
|
1131
1244
|
sourceAnchor?: SourceAnchor;
|
|
1245
|
+
/** Visible fail-closed replacement metadata owned by the projection layer. */
|
|
1246
|
+
placeholder?: RenderPlaceholder;
|
|
1132
1247
|
};
|
|
1133
1248
|
/**
|
|
1134
1249
|
* Custom geometry path data extracted from a:custGeom/a:pathLst.
|
|
@@ -1150,6 +1265,7 @@ export type VectorShapeDrawing = DrawingBlockBase & {
|
|
|
1150
1265
|
shapeKind?: string;
|
|
1151
1266
|
customGeometry?: CustomGeometryData;
|
|
1152
1267
|
fillColor?: FillColor;
|
|
1268
|
+
imageFill?: ShapeImageFill;
|
|
1153
1269
|
strokeColor?: StrokeColor;
|
|
1154
1270
|
strokeWidth?: number;
|
|
1155
1271
|
strokeDashArray?: number[];
|
|
@@ -1158,6 +1274,7 @@ export type VectorShapeDrawing = DrawingBlockBase & {
|
|
|
1158
1274
|
lineEnds?: LineEnds;
|
|
1159
1275
|
effectExtent?: EffectExtent;
|
|
1160
1276
|
textContent?: ShapeTextContent;
|
|
1277
|
+
textLayout?: ShapeTextLayout;
|
|
1161
1278
|
textAlign?: string;
|
|
1162
1279
|
textVerticalAlign?: 'top' | 'center' | 'bottom';
|
|
1163
1280
|
textFlow?: 'horizontal' | 'vertical' | 'vertical-ideographic' | 'horizontal-ideographic' | 'bottom-to-top';
|
|
@@ -1176,6 +1293,7 @@ export type TextboxDrawing = DrawingBlockBase & {
|
|
|
1176
1293
|
shapeKind?: string;
|
|
1177
1294
|
customGeometry?: CustomGeometryData;
|
|
1178
1295
|
fillColor?: FillColor;
|
|
1296
|
+
imageFill?: ShapeImageFill;
|
|
1179
1297
|
strokeColor?: StrokeColor;
|
|
1180
1298
|
strokeWidth?: number;
|
|
1181
1299
|
strokeDashArray?: number[];
|
|
@@ -1184,6 +1302,7 @@ export type TextboxDrawing = DrawingBlockBase & {
|
|
|
1184
1302
|
lineEnds?: LineEnds;
|
|
1185
1303
|
effectExtent?: EffectExtent;
|
|
1186
1304
|
textContent?: ShapeTextContent;
|
|
1305
|
+
textLayout?: ShapeTextLayout;
|
|
1187
1306
|
textAlign?: string;
|
|
1188
1307
|
textVerticalAlign?: 'top' | 'center' | 'bottom';
|
|
1189
1308
|
textFlow?: 'horizontal' | 'vertical' | 'vertical-ideographic' | 'horizontal-ideographic' | 'bottom-to-top';
|
|
@@ -1,13 +1,13 @@
|
|
|
1
|
-
import { ChartModel, DrawingGeometry } from '../../../contracts/src/index.js';
|
|
1
|
+
import { ChartModel, DrawingGeometry, RenderPlaceholder } from '../../../contracts/src/index.js';
|
|
2
2
|
/**
|
|
3
3
|
* Create a chart element from a ChartDrawing block.
|
|
4
4
|
* Routes to the correct renderer based on chart type, with placeholder fallback.
|
|
5
5
|
*/
|
|
6
|
-
export declare function createChartElement(doc: Document, chartData: ChartModel | undefined, geometry: DrawingGeometry): HTMLElement;
|
|
6
|
+
export declare function createChartElement(doc: Document, chartData: ChartModel | undefined, geometry: DrawingGeometry, placeholder?: RenderPlaceholder): HTMLElement;
|
|
7
7
|
/**
|
|
8
8
|
* Create a placeholder for charts with missing data or unsupported types.
|
|
9
9
|
* Preserves layout dimensions and is print-visible.
|
|
10
10
|
*/
|
|
11
|
-
export declare function createChartPlaceholder(doc: Document, container: HTMLElement, label: string): HTMLElement;
|
|
11
|
+
export declare function createChartPlaceholder(doc: Document, container: HTMLElement, label: string, placeholder?: RenderPlaceholder): HTMLElement;
|
|
12
12
|
/** Format a numeric tick value for chart axis labels. */
|
|
13
13
|
export declare function formatTickValue(value: number): string;
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { RenderPlaceholder } from '../../../../contracts/src/index.js';
|
|
2
|
+
export type CreateRenderPlaceholderOptions = {
|
|
3
|
+
doc: Document;
|
|
4
|
+
placeholder: RenderPlaceholder;
|
|
5
|
+
};
|
|
6
|
+
/** Stamp the shared diagnostic and accessibility contract on a placeholder. */
|
|
7
|
+
export declare const applyRenderPlaceholderSemantics: (element: HTMLElement, placeholder: RenderPlaceholder) => void;
|
|
8
|
+
/**
|
|
9
|
+
* Paint an observable, print-visible replacement for content that the
|
|
10
|
+
* projection layer deliberately kept fail-closed.
|
|
11
|
+
*/
|
|
12
|
+
export declare const createRenderPlaceholder: ({ doc, placeholder }: CreateRenderPlaceholderOptions) => HTMLSpanElement;
|