superdoc 2.24.0-next.1 → 2.24.0-next.3
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-DFNXiKvQ.es.js → create-super-doc-ui-8UTu16Lw.es.js} +229 -82
- package/dist/chunks/{create-super-doc-ui-D_FbXpOQ.cjs → create-super-doc-ui-bTFGKVRb.cjs} +229 -82
- package/dist/collaboration-upgrade-engine.cjs +1 -1
- package/dist/collaboration-upgrade-engine.es.js +1 -1
- package/dist/document-api/src/selection/selection.types.d.ts +35 -8
- package/dist/public/ui-react.cjs +1 -1
- package/dist/public/ui-react.es.js +1 -1
- package/dist/public/ui-vue.cjs +1 -1
- package/dist/public/ui-vue.es.js +1 -1
- package/dist/public/ui.cjs +1 -1
- package/dist/public/ui.es.js +1 -1
- package/dist/superdoc/src/public/ui/types.d.ts +22 -0
- package/dist/superdoc/src/public/ui.d.cts +4 -0
- package/dist/superdoc/src/public/ui.d.ts +1 -1
- package/dist/superdoc.cjs +3 -3
- package/dist/superdoc.es.js +3 -3
- package/dist-cdn/superdoc.min.js +42 -42
- package/package.json +2 -2
package/dist/chunks/{create-super-doc-ui-DFNXiKvQ.es.js → create-super-doc-ui-8UTu16Lw.es.js}
RENAMED
|
@@ -5938,6 +5938,7 @@ function buildTableCommandInput(action, context) {
|
|
|
5938
5938
|
};
|
|
5939
5939
|
case "delete-table": return { nodeId };
|
|
5940
5940
|
case "merge-cells": {
|
|
5941
|
+
if (!context.canMerge) return null;
|
|
5941
5942
|
const range = mergeRange ?? {
|
|
5942
5943
|
start: {
|
|
5943
5944
|
rowIndex,
|
|
@@ -6073,6 +6074,18 @@ function createSuperDocUI(options) {
|
|
|
6073
6074
|
const host = getEditor()?.host;
|
|
6074
6075
|
return host && typeof host === "object" ? host : null;
|
|
6075
6076
|
};
|
|
6077
|
+
/**
|
|
6078
|
+
* The host selection snapshot a selection read, slice, or capture was
|
|
6079
|
+
* resolved from. The host replaces its snapshot object on every selection
|
|
6080
|
+
* change, so an identical object means the selection has not moved since.
|
|
6081
|
+
*/
|
|
6082
|
+
const selectionHostSnapshots = /* @__PURE__ */ new WeakMap();
|
|
6083
|
+
const readHostSelectionSnapshot = () => {
|
|
6084
|
+
const selectionHandle = (safeCall(() => getHost()?.getHandles?.() ?? null, null)?.editing)?.selection;
|
|
6085
|
+
if (typeof selectionHandle?.getSnapshot !== "function") return null;
|
|
6086
|
+
const snapshot = safeCall(() => selectionHandle.getSnapshot(), null);
|
|
6087
|
+
return snapshot && typeof snapshot === "object" ? snapshot : null;
|
|
6088
|
+
};
|
|
6076
6089
|
const createFirstPartyCommandDoc = () => {
|
|
6077
6090
|
const editor = getEditor();
|
|
6078
6091
|
const doc = editor?.doc;
|
|
@@ -6244,7 +6257,7 @@ function createSuperDocUI(options) {
|
|
|
6244
6257
|
};
|
|
6245
6258
|
const resolveTableContext = () => {
|
|
6246
6259
|
const snapshot = readHostTableContext();
|
|
6247
|
-
if (!snapshot || snapshot.inTable !== true) return null;
|
|
6260
|
+
if (!snapshot || snapshot.inTable !== true || snapshot.status && snapshot.status !== "ready") return null;
|
|
6248
6261
|
const table = snapshot.table;
|
|
6249
6262
|
const tableNodeId = typeof table?.nodeId === "string" && table.nodeId.length > 0 ? table.nodeId : null;
|
|
6250
6263
|
if (!tableNodeId) return null;
|
|
@@ -6256,12 +6269,15 @@ function createSuperDocUI(options) {
|
|
|
6256
6269
|
if (rowIndex == null || columnIndex == null) return null;
|
|
6257
6270
|
const cellNodeId = typeof cell?.nodeId === "string" && cell.nodeId.length > 0 ? cell.nodeId : null;
|
|
6258
6271
|
const range = snapshot.cellRange;
|
|
6272
|
+
const mergeRange = readMergeRange(range);
|
|
6273
|
+
const metadata = snapshot.tableSelection;
|
|
6259
6274
|
return {
|
|
6260
6275
|
tableNodeId,
|
|
6261
6276
|
rowIndex,
|
|
6262
6277
|
columnIndex,
|
|
6263
6278
|
cellNodeId,
|
|
6264
|
-
mergeRange
|
|
6279
|
+
mergeRange,
|
|
6280
|
+
canMerge: metadata == null || metadata.selectionMode === "cells" && metadata.isRectangular === true
|
|
6265
6281
|
};
|
|
6266
6282
|
};
|
|
6267
6283
|
const customCommands = /* @__PURE__ */ new Map();
|
|
@@ -7277,12 +7293,21 @@ function createSuperDocUI(options) {
|
|
|
7277
7293
|
...EMPTY_SELECTION,
|
|
7278
7294
|
status
|
|
7279
7295
|
};
|
|
7296
|
+
const slice = buildSelectionSlice(info, status);
|
|
7297
|
+
const hostSelection = selectionHostSnapshots.get(info);
|
|
7298
|
+
if (hostSelection) selectionHostSnapshots.set(slice, hostSelection);
|
|
7299
|
+
return slice;
|
|
7300
|
+
};
|
|
7301
|
+
const buildSelectionSlice = (info, status) => {
|
|
7280
7302
|
const target = info.target ?? null;
|
|
7281
7303
|
const quotedText = typeof info.text === "string" ? info.text : "";
|
|
7282
7304
|
return {
|
|
7283
7305
|
status,
|
|
7284
7306
|
empty: info.empty === true,
|
|
7285
7307
|
target,
|
|
7308
|
+
trackedTarget: info.trackedTarget ?? null,
|
|
7309
|
+
trackedChangeRangeDecisionSupported: info.trackedChangeRangeDecisionSupported,
|
|
7310
|
+
trackedChangesWhollySelected: info.trackedChangesWhollySelected,
|
|
7286
7311
|
selectionTarget: info.selectionTarget ?? null,
|
|
7287
7312
|
tableSelection: info.tableSelection ?? null,
|
|
7288
7313
|
activeMarks: Array.isArray(info.activeMarks) ? info.activeMarks : [],
|
|
@@ -7291,18 +7316,22 @@ function createSuperDocUI(options) {
|
|
|
7291
7316
|
quotedText
|
|
7292
7317
|
};
|
|
7293
7318
|
};
|
|
7294
|
-
const readSelectionInfoLive = () =>
|
|
7295
|
-
const selectionApi = getDoc()?.selection;
|
|
7296
|
-
return readAsync("selection", selectionReadToken(), () => selectionApi?.current ? selectionApi.current({ includeText: true }) : void 0, normalizeSelectionInfo);
|
|
7297
|
-
};
|
|
7319
|
+
const readSelectionInfoLive = () => readAsync("selection", selectionReadToken(), selectionCurrentRun, normalizeSelectionInfo);
|
|
7298
7320
|
const computeSelection = () => {
|
|
7299
7321
|
const { value: info, status } = readSelectionInfoLive();
|
|
7300
7322
|
return selectionSliceFromInfo(info, status);
|
|
7301
7323
|
};
|
|
7302
|
-
|
|
7324
|
+
function selectionCurrentRun() {
|
|
7303
7325
|
const selectionApi = getDoc()?.selection;
|
|
7304
|
-
|
|
7305
|
-
|
|
7326
|
+
if (!selectionApi?.current) return void 0;
|
|
7327
|
+
const hostSelection = readHostSelectionSnapshot();
|
|
7328
|
+
const tag = (info) => {
|
|
7329
|
+
if (hostSelection && info && typeof info === "object") selectionHostSnapshots.set(info, hostSelection);
|
|
7330
|
+
return info;
|
|
7331
|
+
};
|
|
7332
|
+
const result = selectionApi.current({ includeText: true });
|
|
7333
|
+
return isPromiseLike(result) ? Promise.resolve(result).then(tag) : tag(result);
|
|
7334
|
+
}
|
|
7306
7335
|
/** True when a host sync snapshot is a resolved collapsed caret (not a range). */
|
|
7307
7336
|
const isCollapsedCaretSnapshot = (info) => {
|
|
7308
7337
|
if (info.empty !== true) return false;
|
|
@@ -8282,6 +8311,10 @@ function createSuperDocUI(options) {
|
|
|
8282
8311
|
if (!supported) return command.scope === "all" ? SUPERDOC_UI_REASONS.bulkDecisionsDisabled : unavailableRouteReason(doc);
|
|
8283
8312
|
if (disabledReason) return disabledReason;
|
|
8284
8313
|
if (command.scope !== "all" && selection.activeChangeIds.length === 0) return SUPERDOC_UI_REASONS.selectionRequired;
|
|
8314
|
+
if (command.scope !== "all") {
|
|
8315
|
+
const plan = planSelectionTrackDecision(selection, true);
|
|
8316
|
+
if (plan?.kind === "blocked") return plan.reason;
|
|
8317
|
+
}
|
|
8285
8318
|
};
|
|
8286
8319
|
const findTrackChangeForPermission = (id) => {
|
|
8287
8320
|
syncCoordinatorEditor();
|
|
@@ -8301,20 +8334,22 @@ function createSuperDocUI(options) {
|
|
|
8301
8334
|
if (typeof canPerform !== "function" || ids.length === 0) return void 0;
|
|
8302
8335
|
const currentUser = superdoc.config && typeof superdoc.config === "object" ? superdoc.config.user : null;
|
|
8303
8336
|
for (const id of ids) {
|
|
8304
|
-
const trackedChange = findTrackChangeForPermission(id)
|
|
8305
|
-
const isOwn = trackedChangeOwnedByCurrentUser(trackedChange, currentUser);
|
|
8306
|
-
const
|
|
8307
|
-
|
|
8308
|
-
|
|
8309
|
-
|
|
8310
|
-
|
|
8311
|
-
|
|
8312
|
-
|
|
8313
|
-
|
|
8314
|
-
|
|
8315
|
-
|
|
8337
|
+
const trackedChange = findTrackChangeForPermission(id);
|
|
8338
|
+
const isOwn = trackedChange ? trackedChangeOwnedByCurrentUser(trackedChange, currentUser) : false;
|
|
8339
|
+
const permissions = trackedChange ? [kind === "accept" ? isOwn ? "RESOLVE_OWN" : "RESOLVE_OTHER" : isOwn ? "REJECT_OWN" : "REJECT_OTHER"] : kind === "accept" ? ["RESOLVE_OWN", "RESOLVE_OTHER"] : ["REJECT_OWN", "REJECT_OTHER"];
|
|
8340
|
+
for (const candidate of permissions) {
|
|
8341
|
+
let allowed;
|
|
8342
|
+
try {
|
|
8343
|
+
allowed = canPerform.call(superdoc, {
|
|
8344
|
+
permission: candidate,
|
|
8345
|
+
trackedChange: trackedChange ?? { id },
|
|
8346
|
+
comment: null
|
|
8347
|
+
});
|
|
8348
|
+
} catch {
|
|
8349
|
+
return trackedChange ? void 0 : SUPERDOC_UI_REASONS.permissionDenied;
|
|
8350
|
+
}
|
|
8351
|
+
if (allowed === false || !trackedChange && allowed !== true) return SUPERDOC_UI_REASONS.permissionDenied;
|
|
8316
8352
|
}
|
|
8317
|
-
if (allowed === false) return SUPERDOC_UI_REASONS.permissionDenied;
|
|
8318
8353
|
}
|
|
8319
8354
|
};
|
|
8320
8355
|
const hostCommandSupport = (command) => {
|
|
@@ -9155,7 +9190,7 @@ function createSuperDocUI(options) {
|
|
|
9155
9190
|
reason: SUPERDOC_UI_REASONS.documentReadonly
|
|
9156
9191
|
}, "builtin");
|
|
9157
9192
|
const context = resolveTableContext();
|
|
9158
|
-
if (!(context != null && (!descriptor.table.requiresCell || context.cellNodeId != null))) return normalizeCommandState({
|
|
9193
|
+
if (!(context != null && (!descriptor.table.requiresCell || context.cellNodeId != null) && (descriptor.table.action !== "merge-cells" || context.canMerge))) return normalizeCommandState({
|
|
9159
9194
|
enabled: false,
|
|
9160
9195
|
active: false,
|
|
9161
9196
|
supported: true,
|
|
@@ -9994,14 +10029,22 @@ function createSuperDocUI(options) {
|
|
|
9994
10029
|
* ordinary/insertion selections are visible-space, while a selection that
|
|
9995
10030
|
* reaches painted deleted text is projected in tracked space by the host.
|
|
9996
10031
|
*
|
|
9997
|
-
*
|
|
9998
|
-
*
|
|
10032
|
+
* Cross-block coverage must come from the model-backed tracked target;
|
|
10033
|
+
* intermediate block lengths cannot be inferred from the endpoints.
|
|
9999
10034
|
*/
|
|
10000
10035
|
function trackDecisionRangeFromSelection(selection) {
|
|
10001
10036
|
if (selection.empty) return null;
|
|
10002
10037
|
const explicit = selection.selectionTarget;
|
|
10003
10038
|
const start = explicit?.start;
|
|
10004
10039
|
const end = explicit?.end;
|
|
10040
|
+
if (start?.kind === "text" && end?.kind === "text" && start.blockId !== end.blockId) {
|
|
10041
|
+
const range = selection.trackedTarget;
|
|
10042
|
+
return range ? {
|
|
10043
|
+
kind: "range",
|
|
10044
|
+
coordinateSpace: "tracked",
|
|
10045
|
+
range
|
|
10046
|
+
} : null;
|
|
10047
|
+
}
|
|
10005
10048
|
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;
|
|
10006
10049
|
const rangeStart = Math.min(start.offset, end.offset);
|
|
10007
10050
|
const rangeEnd = Math.max(start.offset, end.offset);
|
|
@@ -10046,32 +10089,20 @@ function createSuperDocUI(options) {
|
|
|
10046
10089
|
function normalizeTrackDecisionText(value) {
|
|
10047
10090
|
return typeof value === "string" ? value.replace(/\s+/g, " ").trim() : "";
|
|
10048
10091
|
}
|
|
10049
|
-
function activeChangePartialDecisionRoute() {
|
|
10050
|
-
const activeId =
|
|
10092
|
+
function activeChangePartialDecisionRoute(selection = state.selection) {
|
|
10093
|
+
const activeId = selection.activeChangeIds[0];
|
|
10051
10094
|
if (!activeId) return "unavailable";
|
|
10052
|
-
const story = selectionStoryLocator(
|
|
10053
|
-
const
|
|
10095
|
+
const story = selectionStoryLocator(selection);
|
|
10096
|
+
const trackChanges = state?.trackChanges;
|
|
10097
|
+
const item = (trackChanges?.status === "ready" ? trackChanges.items.find((candidate) => entityRowMatchesRequest(candidate, activeId, story)) : void 0) ?? readBodyTrackChangeForDecision(activeId, story) ?? readAllStoryTrackChanges()?.find((candidate) => entityRowMatchesRequest(candidate, activeId, story));
|
|
10054
10098
|
if (!item) return "unavailable";
|
|
10055
10099
|
const change = trackChangesItemPayload(item);
|
|
10056
10100
|
const type = change.type;
|
|
10057
10101
|
const grouping = change.grouping;
|
|
10058
|
-
if (selectedTextCoversTrackChangeText(
|
|
10102
|
+
if (selectedTextCoversTrackChangeText(selection, item)) return "id";
|
|
10059
10103
|
if (type === "replacement" && grouping === "replacement-pair") return "range";
|
|
10060
10104
|
return (type === "insertion" || type === "deletion" || type === "insert" || type === "delete") && grouping === "standalone" ? "range" : "id";
|
|
10061
10105
|
}
|
|
10062
|
-
function executeTrackDecisionRangeWithIdFallback(kind, rangeTarget, changeId, story) {
|
|
10063
|
-
const fallback = () => callTrackDecisionTarget(kind, trackDecisionIdTarget(changeId, story), changeId, story);
|
|
10064
|
-
try {
|
|
10065
|
-
const result = callTrackDecisionTarget(kind, rangeTarget, changeId, story);
|
|
10066
|
-
if (isPromiseLike(result)) return settleCommandExecution(Promise.resolve(result).then((settled) => {
|
|
10067
|
-
return commandResultSucceeded(commandResultFromOperationResult(settled)) ? settled : fallback();
|
|
10068
|
-
}));
|
|
10069
|
-
const commandResult = commandResultFromOperationResult(result);
|
|
10070
|
-
return settleCommandExecution(commandResultSucceeded(commandResult) ? result : fallback());
|
|
10071
|
-
} catch {
|
|
10072
|
-
return false;
|
|
10073
|
-
}
|
|
10074
|
-
}
|
|
10075
10106
|
/** A decision target carried by the payload itself, independent of the selection. */
|
|
10076
10107
|
function explicitTrackDecisionTarget(payload) {
|
|
10077
10108
|
if (typeof payload === "string" && payload.length > 0) return {
|
|
@@ -10115,29 +10146,88 @@ function createSuperDocUI(options) {
|
|
|
10115
10146
|
story
|
|
10116
10147
|
} : null;
|
|
10117
10148
|
}
|
|
10149
|
+
/**
|
|
10150
|
+
* The selection-derived decision for a review command. The command gate and
|
|
10151
|
+
* execution share these rules so an enabled command always has a target.
|
|
10152
|
+
* `null` means the selection does not drive the decision (no active change
|
|
10153
|
+
* or a collapsed caret) and the caller falls back to the active change id.
|
|
10154
|
+
* `gateOnly` stops after the blocking rules and returns only a block or null.
|
|
10155
|
+
*/
|
|
10156
|
+
function planSelectionTrackDecision(selection, gateOnly = false) {
|
|
10157
|
+
if (selection.tableSelection?.kind === "tableCells" && (selection.tableSelection.type === "cells" || selection.tableSelection.type === "table")) return {
|
|
10158
|
+
kind: "blocked",
|
|
10159
|
+
reason: SUPERDOC_UI_REASONS.operationUnavailable
|
|
10160
|
+
};
|
|
10161
|
+
const ids = selection.activeChangeIds;
|
|
10162
|
+
if (ids.length > 1) {
|
|
10163
|
+
if (selection.empty || selection.trackedChangesWhollySelected === true) return {
|
|
10164
|
+
kind: "ids",
|
|
10165
|
+
ids
|
|
10166
|
+
};
|
|
10167
|
+
if (selection.trackedChangeRangeDecisionSupported === false) return {
|
|
10168
|
+
kind: "blocked",
|
|
10169
|
+
reason: SUPERDOC_UI_REASONS.operationUnavailable
|
|
10170
|
+
};
|
|
10171
|
+
const target = trackDecisionRangeFromSelection(selection);
|
|
10172
|
+
return target ? {
|
|
10173
|
+
kind: "range",
|
|
10174
|
+
target,
|
|
10175
|
+
changeId: null,
|
|
10176
|
+
permissionIds: ids
|
|
10177
|
+
} : {
|
|
10178
|
+
kind: "blocked",
|
|
10179
|
+
reason: SUPERDOC_UI_REASONS.targetUnresolved
|
|
10180
|
+
};
|
|
10181
|
+
}
|
|
10182
|
+
if (ids.length !== 1 || selection.empty) return null;
|
|
10183
|
+
const activeId = ids[0];
|
|
10184
|
+
let routeValue;
|
|
10185
|
+
const route = () => routeValue ??= selection.trackedChangesWhollySelected === true ? "id" : activeChangePartialDecisionRoute(selection);
|
|
10186
|
+
if (selection.trackedChangeRangeDecisionSupported === false && route() !== "id") return {
|
|
10187
|
+
kind: "blocked",
|
|
10188
|
+
reason: SUPERDOC_UI_REASONS.operationUnavailable
|
|
10189
|
+
};
|
|
10190
|
+
if (!selection.selectionTarget) return null;
|
|
10191
|
+
const target = trackDecisionRangeFromSelection(selection);
|
|
10192
|
+
if (!target && route() !== "id") return {
|
|
10193
|
+
kind: "blocked",
|
|
10194
|
+
reason: SUPERDOC_UI_REASONS.targetUnresolved
|
|
10195
|
+
};
|
|
10196
|
+
if (gateOnly) return null;
|
|
10197
|
+
if (route() === "id") {
|
|
10198
|
+
const selectedStory = selectionStoryLocator(selection);
|
|
10199
|
+
return {
|
|
10200
|
+
kind: "id",
|
|
10201
|
+
id: activeId,
|
|
10202
|
+
story: selectedStory && storyLocatorSignature(selectedStory) !== storyLocatorSignature(null) ? selectedStory : void 0
|
|
10203
|
+
};
|
|
10204
|
+
}
|
|
10205
|
+
if (route() === "unavailable" && !selection.trackedTarget) return { kind: "unavailable" };
|
|
10206
|
+
return target ? {
|
|
10207
|
+
kind: "range",
|
|
10208
|
+
target,
|
|
10209
|
+
changeId: activeId,
|
|
10210
|
+
story: nonBodySelectionStoryLocator(selection)
|
|
10211
|
+
} : {
|
|
10212
|
+
kind: "blocked",
|
|
10213
|
+
reason: SUPERDOC_UI_REASONS.targetUnresolved
|
|
10214
|
+
};
|
|
10215
|
+
}
|
|
10118
10216
|
function executeTrackDecisionCommand(command, payload) {
|
|
10119
10217
|
if (command.scope === "id" && payload == null) {
|
|
10120
|
-
|
|
10121
|
-
|
|
10122
|
-
|
|
10123
|
-
|
|
10124
|
-
|
|
10125
|
-
|
|
10126
|
-
|
|
10127
|
-
|
|
10128
|
-
|
|
10129
|
-
|
|
10130
|
-
|
|
10131
|
-
|
|
10132
|
-
|
|
10133
|
-
const activeId = state.selection.activeChangeIds[0];
|
|
10134
|
-
const selectedStory = selectionStoryLocator(state.selection);
|
|
10135
|
-
const story = selectedStory && storyLocatorSignature(selectedStory) !== storyLocatorSignature(null) ? selectedStory : void 0;
|
|
10136
|
-
return executeTrackDecision(command.kind, story ? {
|
|
10137
|
-
id: activeId,
|
|
10138
|
-
story
|
|
10139
|
-
} : activeId);
|
|
10140
|
-
}
|
|
10218
|
+
const plan = planSelectionTrackDecision(state.selection);
|
|
10219
|
+
switch (plan?.kind) {
|
|
10220
|
+
case "blocked":
|
|
10221
|
+
case "unavailable": return false;
|
|
10222
|
+
case "ids": return executeTrackDecisionTarget(command.kind, {
|
|
10223
|
+
kind: "ids",
|
|
10224
|
+
ids: plan.ids
|
|
10225
|
+
}, null, void 0, plan.ids);
|
|
10226
|
+
case "range": return executeTrackDecisionTarget(command.kind, plan.target, plan.changeId, plan.story, plan.permissionIds);
|
|
10227
|
+
case "id": return executeTrackDecision(command.kind, plan.story ? {
|
|
10228
|
+
id: plan.id,
|
|
10229
|
+
story: plan.story
|
|
10230
|
+
} : plan.id);
|
|
10141
10231
|
}
|
|
10142
10232
|
}
|
|
10143
10233
|
const resolved = resolveTrackDecisionTarget(command, payload);
|
|
@@ -11806,11 +11896,14 @@ function createSuperDocUI(options) {
|
|
|
11806
11896
|
if (snapshot.empty) return null;
|
|
11807
11897
|
const cells = currentCellSelectionTarget();
|
|
11808
11898
|
if (!snapshot.target && !snapshot.selectionTarget && !cells) return null;
|
|
11809
|
-
|
|
11899
|
+
const capture = {
|
|
11810
11900
|
...snapshot,
|
|
11811
11901
|
capturedAt: Date.now(),
|
|
11812
11902
|
...cells ? { _tableCellSelectionTarget: cells } : {}
|
|
11813
11903
|
};
|
|
11904
|
+
const hostSelection = selectionHostSnapshots.get(snapshot);
|
|
11905
|
+
if (hostSelection) selectionHostSnapshots.set(capture, hostSelection);
|
|
11906
|
+
return capture;
|
|
11814
11907
|
},
|
|
11815
11908
|
restore: (capture) => {
|
|
11816
11909
|
const done = (result) => {
|
|
@@ -11839,6 +11932,8 @@ function createSuperDocUI(options) {
|
|
|
11839
11932
|
ok: false,
|
|
11840
11933
|
reason: SUPERDOC_UI_REASONS.targetUnresolved
|
|
11841
11934
|
});
|
|
11935
|
+
const heldHostSelection = selectionHostSnapshots.get(capture);
|
|
11936
|
+
if (!hasCellTarget && target.coordinateSpace === "tracked" && heldHostSelection !== void 0 && readHostSelectionSnapshot() === heldHostSelection) return done({ ok: true });
|
|
11842
11937
|
const resolved = getSelectionApplyHelper();
|
|
11843
11938
|
if (!("helper" in resolved)) return done({
|
|
11844
11939
|
ok: false,
|
|
@@ -12675,20 +12770,20 @@ function createSuperDocUI(options) {
|
|
|
12675
12770
|
if (run() === false) return Promise.resolve(false);
|
|
12676
12771
|
return lastCommandSettlement;
|
|
12677
12772
|
};
|
|
12678
|
-
const executeTrackDecisionTarget = (kind, target, changeId, story) => {
|
|
12773
|
+
const executeTrackDecisionTarget = (kind, target, changeId, story, selectionChangeIds) => {
|
|
12679
12774
|
try {
|
|
12680
|
-
return settleCommandExecution(callTrackDecisionTarget(kind, target, changeId, story));
|
|
12775
|
+
return settleCommandExecution(callTrackDecisionTarget(kind, target, changeId, story, selectionChangeIds));
|
|
12681
12776
|
} catch {
|
|
12682
12777
|
return false;
|
|
12683
12778
|
}
|
|
12684
12779
|
};
|
|
12685
|
-
const callTrackDecisionTarget = (kind, target, changeId, story) => {
|
|
12780
|
+
const callTrackDecisionTarget = (kind, target, changeId, story, selectionChangeIds) => {
|
|
12686
12781
|
if (trackedChangeDecisionsAreDisabled()) return false;
|
|
12687
12782
|
const tcApi = getDoc()?.trackChanges;
|
|
12688
12783
|
const isAllTarget = target.kind === "all" || target.scope === "all";
|
|
12689
12784
|
const isRangeTarget = target.kind === "range";
|
|
12690
12785
|
const isMultiIdTarget = target.kind === "ids";
|
|
12691
|
-
const permissionIds = isAllTarget ? [] : isMultiIdTarget && Array.isArray(target.ids) ? target.ids.filter((id) => typeof id === "string" && id.length > 0) : changeId ? [changeId] : [];
|
|
12786
|
+
const permissionIds = isAllTarget ? [] : selectionChangeIds ?? (isMultiIdTarget && Array.isArray(target.ids) ? target.ids.filter((id) => typeof id === "string" && id.length > 0) : changeId ? [changeId] : []);
|
|
12692
12787
|
if (permissionIds.length > 0 && trackedChangeDecisionPermissionReason(kind, permissionIds)) return false;
|
|
12693
12788
|
if (bulkTrackDecisionBlockedReason({
|
|
12694
12789
|
kind,
|
|
@@ -13060,7 +13155,13 @@ function createSuperDocUI(options) {
|
|
|
13060
13155
|
return {
|
|
13061
13156
|
point,
|
|
13062
13157
|
entities: validInput ? entityAt(point) : [],
|
|
13063
|
-
selection:
|
|
13158
|
+
selection: (() => {
|
|
13159
|
+
const current = computeSelection();
|
|
13160
|
+
return current.status === "ready" ? current : {
|
|
13161
|
+
...current,
|
|
13162
|
+
tableSelection: null
|
|
13163
|
+
};
|
|
13164
|
+
})(),
|
|
13064
13165
|
position: null,
|
|
13065
13166
|
insideSelection: false
|
|
13066
13167
|
};
|
|
@@ -13277,21 +13378,67 @@ function createSuperDocUI(options) {
|
|
|
13277
13378
|
columnIndex: null,
|
|
13278
13379
|
cellNodeId: null,
|
|
13279
13380
|
rows: null,
|
|
13280
|
-
columns: null
|
|
13381
|
+
columns: null,
|
|
13382
|
+
status: "ready",
|
|
13383
|
+
cellRange: null,
|
|
13384
|
+
tableSelection: null
|
|
13385
|
+
};
|
|
13386
|
+
const publicTableContext = (snapshot) => {
|
|
13387
|
+
const status = snapshot?.status === "pending" || snapshot?.status === "stale" ? snapshot.status : "ready";
|
|
13388
|
+
if (!snapshot || snapshot.inTable !== true || status !== "ready") return {
|
|
13389
|
+
...EMPTY_TABLE_CONTEXT,
|
|
13390
|
+
status
|
|
13391
|
+
};
|
|
13392
|
+
const table = snapshot.table;
|
|
13393
|
+
const row = snapshot.row;
|
|
13394
|
+
const column = snapshot.column;
|
|
13395
|
+
const cell = snapshot.cell;
|
|
13396
|
+
if (typeof table?.nodeId !== "string") return {
|
|
13397
|
+
...EMPTY_TABLE_CONTEXT,
|
|
13398
|
+
status
|
|
13399
|
+
};
|
|
13400
|
+
return {
|
|
13401
|
+
inTable: true,
|
|
13402
|
+
status,
|
|
13403
|
+
tableNodeId: table.nodeId,
|
|
13404
|
+
rowIndex: typeof row?.index === "number" ? row.index : null,
|
|
13405
|
+
columnIndex: typeof column?.index === "number" ? column.index : null,
|
|
13406
|
+
cellNodeId: typeof cell?.nodeId === "string" ? cell.nodeId : null,
|
|
13407
|
+
rows: typeof table.rows === "number" ? table.rows : null,
|
|
13408
|
+
columns: typeof table.columns === "number" ? table.columns : null,
|
|
13409
|
+
cellRange: readMergeRange(snapshot.cellRange),
|
|
13410
|
+
tableSelection: snapshot.tableSelection ?? null
|
|
13411
|
+
};
|
|
13281
13412
|
};
|
|
13282
13413
|
const tables = {
|
|
13283
|
-
getContext: () =>
|
|
13284
|
-
|
|
13285
|
-
|
|
13286
|
-
|
|
13414
|
+
getContext: () => publicTableContext(readHostTableContext()),
|
|
13415
|
+
getContextAsync: async () => {
|
|
13416
|
+
for (let attempt = 0; attempt < 2; attempt += 1) {
|
|
13417
|
+
const token = selectionReadToken();
|
|
13418
|
+
const host = getHost();
|
|
13419
|
+
const read = host?.getTableContextAsync;
|
|
13420
|
+
if (typeof read !== "function") return publicTableContext(readHostTableContext());
|
|
13421
|
+
let snapshot = null;
|
|
13422
|
+
try {
|
|
13423
|
+
snapshot = await read.call(host);
|
|
13424
|
+
} catch {
|
|
13425
|
+
return {
|
|
13426
|
+
...EMPTY_TABLE_CONTEXT,
|
|
13427
|
+
status: "pending"
|
|
13428
|
+
};
|
|
13429
|
+
}
|
|
13430
|
+
if (disposed) return {
|
|
13431
|
+
...EMPTY_TABLE_CONTEXT,
|
|
13432
|
+
status: "pending"
|
|
13433
|
+
};
|
|
13434
|
+
if (token !== selectionReadToken() || host !== getHost()) continue;
|
|
13435
|
+
const context = publicTableContext(snapshot);
|
|
13436
|
+
if (context.status === "stale") continue;
|
|
13437
|
+
return context;
|
|
13438
|
+
}
|
|
13287
13439
|
return {
|
|
13288
|
-
|
|
13289
|
-
|
|
13290
|
-
rowIndex: context.rowIndex,
|
|
13291
|
-
columnIndex: context.columnIndex,
|
|
13292
|
-
cellNodeId: context.cellNodeId,
|
|
13293
|
-
rows: typeof table?.rows === "number" ? table.rows : null,
|
|
13294
|
-
columns: typeof table?.columns === "number" ? table.columns : null
|
|
13440
|
+
...EMPTY_TABLE_CONTEXT,
|
|
13441
|
+
status: "stale"
|
|
13295
13442
|
};
|
|
13296
13443
|
},
|
|
13297
13444
|
isInTable: () => resolveTableContext() != null
|