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
|
@@ -5939,6 +5939,7 @@ function buildTableCommandInput(action, context) {
|
|
|
5939
5939
|
};
|
|
5940
5940
|
case "delete-table": return { nodeId };
|
|
5941
5941
|
case "merge-cells": {
|
|
5942
|
+
if (!context.canMerge) return null;
|
|
5942
5943
|
const range = mergeRange ?? {
|
|
5943
5944
|
start: {
|
|
5944
5945
|
rowIndex,
|
|
@@ -6074,6 +6075,18 @@ function createSuperDocUI(options) {
|
|
|
6074
6075
|
const host = getEditor()?.host;
|
|
6075
6076
|
return host && typeof host === "object" ? host : null;
|
|
6076
6077
|
};
|
|
6078
|
+
/**
|
|
6079
|
+
* The host selection snapshot a selection read, slice, or capture was
|
|
6080
|
+
* resolved from. The host replaces its snapshot object on every selection
|
|
6081
|
+
* change, so an identical object means the selection has not moved since.
|
|
6082
|
+
*/
|
|
6083
|
+
const selectionHostSnapshots = /* @__PURE__ */ new WeakMap();
|
|
6084
|
+
const readHostSelectionSnapshot = () => {
|
|
6085
|
+
const selectionHandle = (safeCall(() => getHost()?.getHandles?.() ?? null, null)?.editing)?.selection;
|
|
6086
|
+
if (typeof selectionHandle?.getSnapshot !== "function") return null;
|
|
6087
|
+
const snapshot = safeCall(() => selectionHandle.getSnapshot(), null);
|
|
6088
|
+
return snapshot && typeof snapshot === "object" ? snapshot : null;
|
|
6089
|
+
};
|
|
6077
6090
|
const createFirstPartyCommandDoc = () => {
|
|
6078
6091
|
const editor = getEditor();
|
|
6079
6092
|
const doc = editor?.doc;
|
|
@@ -6245,7 +6258,7 @@ function createSuperDocUI(options) {
|
|
|
6245
6258
|
};
|
|
6246
6259
|
const resolveTableContext = () => {
|
|
6247
6260
|
const snapshot = readHostTableContext();
|
|
6248
|
-
if (!snapshot || snapshot.inTable !== true) return null;
|
|
6261
|
+
if (!snapshot || snapshot.inTable !== true || snapshot.status && snapshot.status !== "ready") return null;
|
|
6249
6262
|
const table = snapshot.table;
|
|
6250
6263
|
const tableNodeId = typeof table?.nodeId === "string" && table.nodeId.length > 0 ? table.nodeId : null;
|
|
6251
6264
|
if (!tableNodeId) return null;
|
|
@@ -6257,12 +6270,15 @@ function createSuperDocUI(options) {
|
|
|
6257
6270
|
if (rowIndex == null || columnIndex == null) return null;
|
|
6258
6271
|
const cellNodeId = typeof cell?.nodeId === "string" && cell.nodeId.length > 0 ? cell.nodeId : null;
|
|
6259
6272
|
const range = snapshot.cellRange;
|
|
6273
|
+
const mergeRange = readMergeRange(range);
|
|
6274
|
+
const metadata = snapshot.tableSelection;
|
|
6260
6275
|
return {
|
|
6261
6276
|
tableNodeId,
|
|
6262
6277
|
rowIndex,
|
|
6263
6278
|
columnIndex,
|
|
6264
6279
|
cellNodeId,
|
|
6265
|
-
mergeRange
|
|
6280
|
+
mergeRange,
|
|
6281
|
+
canMerge: metadata == null || metadata.selectionMode === "cells" && metadata.isRectangular === true
|
|
6266
6282
|
};
|
|
6267
6283
|
};
|
|
6268
6284
|
const customCommands = /* @__PURE__ */ new Map();
|
|
@@ -7278,12 +7294,21 @@ function createSuperDocUI(options) {
|
|
|
7278
7294
|
...EMPTY_SELECTION,
|
|
7279
7295
|
status
|
|
7280
7296
|
};
|
|
7297
|
+
const slice = buildSelectionSlice(info, status);
|
|
7298
|
+
const hostSelection = selectionHostSnapshots.get(info);
|
|
7299
|
+
if (hostSelection) selectionHostSnapshots.set(slice, hostSelection);
|
|
7300
|
+
return slice;
|
|
7301
|
+
};
|
|
7302
|
+
const buildSelectionSlice = (info, status) => {
|
|
7281
7303
|
const target = info.target ?? null;
|
|
7282
7304
|
const quotedText = typeof info.text === "string" ? info.text : "";
|
|
7283
7305
|
return {
|
|
7284
7306
|
status,
|
|
7285
7307
|
empty: info.empty === true,
|
|
7286
7308
|
target,
|
|
7309
|
+
trackedTarget: info.trackedTarget ?? null,
|
|
7310
|
+
trackedChangeRangeDecisionSupported: info.trackedChangeRangeDecisionSupported,
|
|
7311
|
+
trackedChangesWhollySelected: info.trackedChangesWhollySelected,
|
|
7287
7312
|
selectionTarget: info.selectionTarget ?? null,
|
|
7288
7313
|
tableSelection: info.tableSelection ?? null,
|
|
7289
7314
|
activeMarks: Array.isArray(info.activeMarks) ? info.activeMarks : [],
|
|
@@ -7292,18 +7317,22 @@ function createSuperDocUI(options) {
|
|
|
7292
7317
|
quotedText
|
|
7293
7318
|
};
|
|
7294
7319
|
};
|
|
7295
|
-
const readSelectionInfoLive = () =>
|
|
7296
|
-
const selectionApi = getDoc()?.selection;
|
|
7297
|
-
return readAsync("selection", selectionReadToken(), () => selectionApi?.current ? selectionApi.current({ includeText: true }) : void 0, normalizeSelectionInfo);
|
|
7298
|
-
};
|
|
7320
|
+
const readSelectionInfoLive = () => readAsync("selection", selectionReadToken(), selectionCurrentRun, normalizeSelectionInfo);
|
|
7299
7321
|
const computeSelection = () => {
|
|
7300
7322
|
const { value: info, status } = readSelectionInfoLive();
|
|
7301
7323
|
return selectionSliceFromInfo(info, status);
|
|
7302
7324
|
};
|
|
7303
|
-
|
|
7325
|
+
function selectionCurrentRun() {
|
|
7304
7326
|
const selectionApi = getDoc()?.selection;
|
|
7305
|
-
|
|
7306
|
-
|
|
7327
|
+
if (!selectionApi?.current) return void 0;
|
|
7328
|
+
const hostSelection = readHostSelectionSnapshot();
|
|
7329
|
+
const tag = (info) => {
|
|
7330
|
+
if (hostSelection && info && typeof info === "object") selectionHostSnapshots.set(info, hostSelection);
|
|
7331
|
+
return info;
|
|
7332
|
+
};
|
|
7333
|
+
const result = selectionApi.current({ includeText: true });
|
|
7334
|
+
return isPromiseLike(result) ? Promise.resolve(result).then(tag) : tag(result);
|
|
7335
|
+
}
|
|
7307
7336
|
/** True when a host sync snapshot is a resolved collapsed caret (not a range). */
|
|
7308
7337
|
const isCollapsedCaretSnapshot = (info) => {
|
|
7309
7338
|
if (info.empty !== true) return false;
|
|
@@ -8283,6 +8312,10 @@ function createSuperDocUI(options) {
|
|
|
8283
8312
|
if (!supported) return command.scope === "all" ? SUPERDOC_UI_REASONS.bulkDecisionsDisabled : unavailableRouteReason(doc);
|
|
8284
8313
|
if (disabledReason) return disabledReason;
|
|
8285
8314
|
if (command.scope !== "all" && selection.activeChangeIds.length === 0) return SUPERDOC_UI_REASONS.selectionRequired;
|
|
8315
|
+
if (command.scope !== "all") {
|
|
8316
|
+
const plan = planSelectionTrackDecision(selection, true);
|
|
8317
|
+
if (plan?.kind === "blocked") return plan.reason;
|
|
8318
|
+
}
|
|
8286
8319
|
};
|
|
8287
8320
|
const findTrackChangeForPermission = (id) => {
|
|
8288
8321
|
syncCoordinatorEditor();
|
|
@@ -8302,20 +8335,22 @@ function createSuperDocUI(options) {
|
|
|
8302
8335
|
if (typeof canPerform !== "function" || ids.length === 0) return void 0;
|
|
8303
8336
|
const currentUser = superdoc.config && typeof superdoc.config === "object" ? superdoc.config.user : null;
|
|
8304
8337
|
for (const id of ids) {
|
|
8305
|
-
const trackedChange = findTrackChangeForPermission(id)
|
|
8306
|
-
const isOwn = trackedChangeOwnedByCurrentUser(trackedChange, currentUser);
|
|
8307
|
-
const
|
|
8308
|
-
|
|
8309
|
-
|
|
8310
|
-
|
|
8311
|
-
|
|
8312
|
-
|
|
8313
|
-
|
|
8314
|
-
|
|
8315
|
-
|
|
8316
|
-
|
|
8338
|
+
const trackedChange = findTrackChangeForPermission(id);
|
|
8339
|
+
const isOwn = trackedChange ? trackedChangeOwnedByCurrentUser(trackedChange, currentUser) : false;
|
|
8340
|
+
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"];
|
|
8341
|
+
for (const candidate of permissions) {
|
|
8342
|
+
let allowed;
|
|
8343
|
+
try {
|
|
8344
|
+
allowed = canPerform.call(superdoc, {
|
|
8345
|
+
permission: candidate,
|
|
8346
|
+
trackedChange: trackedChange ?? { id },
|
|
8347
|
+
comment: null
|
|
8348
|
+
});
|
|
8349
|
+
} catch {
|
|
8350
|
+
return trackedChange ? void 0 : SUPERDOC_UI_REASONS.permissionDenied;
|
|
8351
|
+
}
|
|
8352
|
+
if (allowed === false || !trackedChange && allowed !== true) return SUPERDOC_UI_REASONS.permissionDenied;
|
|
8317
8353
|
}
|
|
8318
|
-
if (allowed === false) return SUPERDOC_UI_REASONS.permissionDenied;
|
|
8319
8354
|
}
|
|
8320
8355
|
};
|
|
8321
8356
|
const hostCommandSupport = (command) => {
|
|
@@ -9156,7 +9191,7 @@ function createSuperDocUI(options) {
|
|
|
9156
9191
|
reason: SUPERDOC_UI_REASONS.documentReadonly
|
|
9157
9192
|
}, "builtin");
|
|
9158
9193
|
const context = resolveTableContext();
|
|
9159
|
-
if (!(context != null && (!descriptor.table.requiresCell || context.cellNodeId != null))) return normalizeCommandState({
|
|
9194
|
+
if (!(context != null && (!descriptor.table.requiresCell || context.cellNodeId != null) && (descriptor.table.action !== "merge-cells" || context.canMerge))) return normalizeCommandState({
|
|
9160
9195
|
enabled: false,
|
|
9161
9196
|
active: false,
|
|
9162
9197
|
supported: true,
|
|
@@ -9995,14 +10030,22 @@ function createSuperDocUI(options) {
|
|
|
9995
10030
|
* ordinary/insertion selections are visible-space, while a selection that
|
|
9996
10031
|
* reaches painted deleted text is projected in tracked space by the host.
|
|
9997
10032
|
*
|
|
9998
|
-
*
|
|
9999
|
-
*
|
|
10033
|
+
* Cross-block coverage must come from the model-backed tracked target;
|
|
10034
|
+
* intermediate block lengths cannot be inferred from the endpoints.
|
|
10000
10035
|
*/
|
|
10001
10036
|
function trackDecisionRangeFromSelection(selection) {
|
|
10002
10037
|
if (selection.empty) return null;
|
|
10003
10038
|
const explicit = selection.selectionTarget;
|
|
10004
10039
|
const start = explicit?.start;
|
|
10005
10040
|
const end = explicit?.end;
|
|
10041
|
+
if (start?.kind === "text" && end?.kind === "text" && start.blockId !== end.blockId) {
|
|
10042
|
+
const range = selection.trackedTarget;
|
|
10043
|
+
return range ? {
|
|
10044
|
+
kind: "range",
|
|
10045
|
+
coordinateSpace: "tracked",
|
|
10046
|
+
range
|
|
10047
|
+
} : null;
|
|
10048
|
+
}
|
|
10006
10049
|
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;
|
|
10007
10050
|
const rangeStart = Math.min(start.offset, end.offset);
|
|
10008
10051
|
const rangeEnd = Math.max(start.offset, end.offset);
|
|
@@ -10047,32 +10090,20 @@ function createSuperDocUI(options) {
|
|
|
10047
10090
|
function normalizeTrackDecisionText(value) {
|
|
10048
10091
|
return typeof value === "string" ? value.replace(/\s+/g, " ").trim() : "";
|
|
10049
10092
|
}
|
|
10050
|
-
function activeChangePartialDecisionRoute() {
|
|
10051
|
-
const activeId =
|
|
10093
|
+
function activeChangePartialDecisionRoute(selection = state.selection) {
|
|
10094
|
+
const activeId = selection.activeChangeIds[0];
|
|
10052
10095
|
if (!activeId) return "unavailable";
|
|
10053
|
-
const story = selectionStoryLocator(
|
|
10054
|
-
const
|
|
10096
|
+
const story = selectionStoryLocator(selection);
|
|
10097
|
+
const trackChanges = state?.trackChanges;
|
|
10098
|
+
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));
|
|
10055
10099
|
if (!item) return "unavailable";
|
|
10056
10100
|
const change = trackChangesItemPayload(item);
|
|
10057
10101
|
const type = change.type;
|
|
10058
10102
|
const grouping = change.grouping;
|
|
10059
|
-
if (selectedTextCoversTrackChangeText(
|
|
10103
|
+
if (selectedTextCoversTrackChangeText(selection, item)) return "id";
|
|
10060
10104
|
if (type === "replacement" && grouping === "replacement-pair") return "range";
|
|
10061
10105
|
return (type === "insertion" || type === "deletion" || type === "insert" || type === "delete") && grouping === "standalone" ? "range" : "id";
|
|
10062
10106
|
}
|
|
10063
|
-
function executeTrackDecisionRangeWithIdFallback(kind, rangeTarget, changeId, story) {
|
|
10064
|
-
const fallback = () => callTrackDecisionTarget(kind, trackDecisionIdTarget(changeId, story), changeId, story);
|
|
10065
|
-
try {
|
|
10066
|
-
const result = callTrackDecisionTarget(kind, rangeTarget, changeId, story);
|
|
10067
|
-
if (isPromiseLike(result)) return settleCommandExecution(Promise.resolve(result).then((settled) => {
|
|
10068
|
-
return commandResultSucceeded(commandResultFromOperationResult(settled)) ? settled : fallback();
|
|
10069
|
-
}));
|
|
10070
|
-
const commandResult = commandResultFromOperationResult(result);
|
|
10071
|
-
return settleCommandExecution(commandResultSucceeded(commandResult) ? result : fallback());
|
|
10072
|
-
} catch {
|
|
10073
|
-
return false;
|
|
10074
|
-
}
|
|
10075
|
-
}
|
|
10076
10107
|
/** A decision target carried by the payload itself, independent of the selection. */
|
|
10077
10108
|
function explicitTrackDecisionTarget(payload) {
|
|
10078
10109
|
if (typeof payload === "string" && payload.length > 0) return {
|
|
@@ -10116,29 +10147,88 @@ function createSuperDocUI(options) {
|
|
|
10116
10147
|
story
|
|
10117
10148
|
} : null;
|
|
10118
10149
|
}
|
|
10150
|
+
/**
|
|
10151
|
+
* The selection-derived decision for a review command. The command gate and
|
|
10152
|
+
* execution share these rules so an enabled command always has a target.
|
|
10153
|
+
* `null` means the selection does not drive the decision (no active change
|
|
10154
|
+
* or a collapsed caret) and the caller falls back to the active change id.
|
|
10155
|
+
* `gateOnly` stops after the blocking rules and returns only a block or null.
|
|
10156
|
+
*/
|
|
10157
|
+
function planSelectionTrackDecision(selection, gateOnly = false) {
|
|
10158
|
+
if (selection.tableSelection?.kind === "tableCells" && (selection.tableSelection.type === "cells" || selection.tableSelection.type === "table")) return {
|
|
10159
|
+
kind: "blocked",
|
|
10160
|
+
reason: SUPERDOC_UI_REASONS.operationUnavailable
|
|
10161
|
+
};
|
|
10162
|
+
const ids = selection.activeChangeIds;
|
|
10163
|
+
if (ids.length > 1) {
|
|
10164
|
+
if (selection.empty || selection.trackedChangesWhollySelected === true) return {
|
|
10165
|
+
kind: "ids",
|
|
10166
|
+
ids
|
|
10167
|
+
};
|
|
10168
|
+
if (selection.trackedChangeRangeDecisionSupported === false) return {
|
|
10169
|
+
kind: "blocked",
|
|
10170
|
+
reason: SUPERDOC_UI_REASONS.operationUnavailable
|
|
10171
|
+
};
|
|
10172
|
+
const target = trackDecisionRangeFromSelection(selection);
|
|
10173
|
+
return target ? {
|
|
10174
|
+
kind: "range",
|
|
10175
|
+
target,
|
|
10176
|
+
changeId: null,
|
|
10177
|
+
permissionIds: ids
|
|
10178
|
+
} : {
|
|
10179
|
+
kind: "blocked",
|
|
10180
|
+
reason: SUPERDOC_UI_REASONS.targetUnresolved
|
|
10181
|
+
};
|
|
10182
|
+
}
|
|
10183
|
+
if (ids.length !== 1 || selection.empty) return null;
|
|
10184
|
+
const activeId = ids[0];
|
|
10185
|
+
let routeValue;
|
|
10186
|
+
const route = () => routeValue ??= selection.trackedChangesWhollySelected === true ? "id" : activeChangePartialDecisionRoute(selection);
|
|
10187
|
+
if (selection.trackedChangeRangeDecisionSupported === false && route() !== "id") return {
|
|
10188
|
+
kind: "blocked",
|
|
10189
|
+
reason: SUPERDOC_UI_REASONS.operationUnavailable
|
|
10190
|
+
};
|
|
10191
|
+
if (!selection.selectionTarget) return null;
|
|
10192
|
+
const target = trackDecisionRangeFromSelection(selection);
|
|
10193
|
+
if (!target && route() !== "id") return {
|
|
10194
|
+
kind: "blocked",
|
|
10195
|
+
reason: SUPERDOC_UI_REASONS.targetUnresolved
|
|
10196
|
+
};
|
|
10197
|
+
if (gateOnly) return null;
|
|
10198
|
+
if (route() === "id") {
|
|
10199
|
+
const selectedStory = selectionStoryLocator(selection);
|
|
10200
|
+
return {
|
|
10201
|
+
kind: "id",
|
|
10202
|
+
id: activeId,
|
|
10203
|
+
story: selectedStory && storyLocatorSignature(selectedStory) !== storyLocatorSignature(null) ? selectedStory : void 0
|
|
10204
|
+
};
|
|
10205
|
+
}
|
|
10206
|
+
if (route() === "unavailable" && !selection.trackedTarget) return { kind: "unavailable" };
|
|
10207
|
+
return target ? {
|
|
10208
|
+
kind: "range",
|
|
10209
|
+
target,
|
|
10210
|
+
changeId: activeId,
|
|
10211
|
+
story: nonBodySelectionStoryLocator(selection)
|
|
10212
|
+
} : {
|
|
10213
|
+
kind: "blocked",
|
|
10214
|
+
reason: SUPERDOC_UI_REASONS.targetUnresolved
|
|
10215
|
+
};
|
|
10216
|
+
}
|
|
10119
10217
|
function executeTrackDecisionCommand(command, payload) {
|
|
10120
10218
|
if (command.scope === "id" && payload == null) {
|
|
10121
|
-
|
|
10122
|
-
|
|
10123
|
-
|
|
10124
|
-
|
|
10125
|
-
|
|
10126
|
-
|
|
10127
|
-
|
|
10128
|
-
|
|
10129
|
-
|
|
10130
|
-
|
|
10131
|
-
|
|
10132
|
-
|
|
10133
|
-
|
|
10134
|
-
const activeId = state.selection.activeChangeIds[0];
|
|
10135
|
-
const selectedStory = selectionStoryLocator(state.selection);
|
|
10136
|
-
const story = selectedStory && storyLocatorSignature(selectedStory) !== storyLocatorSignature(null) ? selectedStory : void 0;
|
|
10137
|
-
return executeTrackDecision(command.kind, story ? {
|
|
10138
|
-
id: activeId,
|
|
10139
|
-
story
|
|
10140
|
-
} : activeId);
|
|
10141
|
-
}
|
|
10219
|
+
const plan = planSelectionTrackDecision(state.selection);
|
|
10220
|
+
switch (plan?.kind) {
|
|
10221
|
+
case "blocked":
|
|
10222
|
+
case "unavailable": return false;
|
|
10223
|
+
case "ids": return executeTrackDecisionTarget(command.kind, {
|
|
10224
|
+
kind: "ids",
|
|
10225
|
+
ids: plan.ids
|
|
10226
|
+
}, null, void 0, plan.ids);
|
|
10227
|
+
case "range": return executeTrackDecisionTarget(command.kind, plan.target, plan.changeId, plan.story, plan.permissionIds);
|
|
10228
|
+
case "id": return executeTrackDecision(command.kind, plan.story ? {
|
|
10229
|
+
id: plan.id,
|
|
10230
|
+
story: plan.story
|
|
10231
|
+
} : plan.id);
|
|
10142
10232
|
}
|
|
10143
10233
|
}
|
|
10144
10234
|
const resolved = resolveTrackDecisionTarget(command, payload);
|
|
@@ -11807,11 +11897,14 @@ function createSuperDocUI(options) {
|
|
|
11807
11897
|
if (snapshot.empty) return null;
|
|
11808
11898
|
const cells = currentCellSelectionTarget();
|
|
11809
11899
|
if (!snapshot.target && !snapshot.selectionTarget && !cells) return null;
|
|
11810
|
-
|
|
11900
|
+
const capture = {
|
|
11811
11901
|
...snapshot,
|
|
11812
11902
|
capturedAt: Date.now(),
|
|
11813
11903
|
...cells ? { _tableCellSelectionTarget: cells } : {}
|
|
11814
11904
|
};
|
|
11905
|
+
const hostSelection = selectionHostSnapshots.get(snapshot);
|
|
11906
|
+
if (hostSelection) selectionHostSnapshots.set(capture, hostSelection);
|
|
11907
|
+
return capture;
|
|
11815
11908
|
},
|
|
11816
11909
|
restore: (capture) => {
|
|
11817
11910
|
const done = (result) => {
|
|
@@ -11840,6 +11933,8 @@ function createSuperDocUI(options) {
|
|
|
11840
11933
|
ok: false,
|
|
11841
11934
|
reason: SUPERDOC_UI_REASONS.targetUnresolved
|
|
11842
11935
|
});
|
|
11936
|
+
const heldHostSelection = selectionHostSnapshots.get(capture);
|
|
11937
|
+
if (!hasCellTarget && target.coordinateSpace === "tracked" && heldHostSelection !== void 0 && readHostSelectionSnapshot() === heldHostSelection) return done({ ok: true });
|
|
11843
11938
|
const resolved = getSelectionApplyHelper();
|
|
11844
11939
|
if (!("helper" in resolved)) return done({
|
|
11845
11940
|
ok: false,
|
|
@@ -12676,20 +12771,20 @@ function createSuperDocUI(options) {
|
|
|
12676
12771
|
if (run() === false) return Promise.resolve(false);
|
|
12677
12772
|
return lastCommandSettlement;
|
|
12678
12773
|
};
|
|
12679
|
-
const executeTrackDecisionTarget = (kind, target, changeId, story) => {
|
|
12774
|
+
const executeTrackDecisionTarget = (kind, target, changeId, story, selectionChangeIds) => {
|
|
12680
12775
|
try {
|
|
12681
|
-
return settleCommandExecution(callTrackDecisionTarget(kind, target, changeId, story));
|
|
12776
|
+
return settleCommandExecution(callTrackDecisionTarget(kind, target, changeId, story, selectionChangeIds));
|
|
12682
12777
|
} catch {
|
|
12683
12778
|
return false;
|
|
12684
12779
|
}
|
|
12685
12780
|
};
|
|
12686
|
-
const callTrackDecisionTarget = (kind, target, changeId, story) => {
|
|
12781
|
+
const callTrackDecisionTarget = (kind, target, changeId, story, selectionChangeIds) => {
|
|
12687
12782
|
if (trackedChangeDecisionsAreDisabled()) return false;
|
|
12688
12783
|
const tcApi = getDoc()?.trackChanges;
|
|
12689
12784
|
const isAllTarget = target.kind === "all" || target.scope === "all";
|
|
12690
12785
|
const isRangeTarget = target.kind === "range";
|
|
12691
12786
|
const isMultiIdTarget = target.kind === "ids";
|
|
12692
|
-
const permissionIds = isAllTarget ? [] : isMultiIdTarget && Array.isArray(target.ids) ? target.ids.filter((id) => typeof id === "string" && id.length > 0) : changeId ? [changeId] : [];
|
|
12787
|
+
const permissionIds = isAllTarget ? [] : selectionChangeIds ?? (isMultiIdTarget && Array.isArray(target.ids) ? target.ids.filter((id) => typeof id === "string" && id.length > 0) : changeId ? [changeId] : []);
|
|
12693
12788
|
if (permissionIds.length > 0 && trackedChangeDecisionPermissionReason(kind, permissionIds)) return false;
|
|
12694
12789
|
if (bulkTrackDecisionBlockedReason({
|
|
12695
12790
|
kind,
|
|
@@ -13061,7 +13156,13 @@ function createSuperDocUI(options) {
|
|
|
13061
13156
|
return {
|
|
13062
13157
|
point,
|
|
13063
13158
|
entities: validInput ? entityAt(point) : [],
|
|
13064
|
-
selection:
|
|
13159
|
+
selection: (() => {
|
|
13160
|
+
const current = computeSelection();
|
|
13161
|
+
return current.status === "ready" ? current : {
|
|
13162
|
+
...current,
|
|
13163
|
+
tableSelection: null
|
|
13164
|
+
};
|
|
13165
|
+
})(),
|
|
13065
13166
|
position: null,
|
|
13066
13167
|
insideSelection: false
|
|
13067
13168
|
};
|
|
@@ -13278,21 +13379,67 @@ function createSuperDocUI(options) {
|
|
|
13278
13379
|
columnIndex: null,
|
|
13279
13380
|
cellNodeId: null,
|
|
13280
13381
|
rows: null,
|
|
13281
|
-
columns: null
|
|
13382
|
+
columns: null,
|
|
13383
|
+
status: "ready",
|
|
13384
|
+
cellRange: null,
|
|
13385
|
+
tableSelection: null
|
|
13386
|
+
};
|
|
13387
|
+
const publicTableContext = (snapshot) => {
|
|
13388
|
+
const status = snapshot?.status === "pending" || snapshot?.status === "stale" ? snapshot.status : "ready";
|
|
13389
|
+
if (!snapshot || snapshot.inTable !== true || status !== "ready") return {
|
|
13390
|
+
...EMPTY_TABLE_CONTEXT,
|
|
13391
|
+
status
|
|
13392
|
+
};
|
|
13393
|
+
const table = snapshot.table;
|
|
13394
|
+
const row = snapshot.row;
|
|
13395
|
+
const column = snapshot.column;
|
|
13396
|
+
const cell = snapshot.cell;
|
|
13397
|
+
if (typeof table?.nodeId !== "string") return {
|
|
13398
|
+
...EMPTY_TABLE_CONTEXT,
|
|
13399
|
+
status
|
|
13400
|
+
};
|
|
13401
|
+
return {
|
|
13402
|
+
inTable: true,
|
|
13403
|
+
status,
|
|
13404
|
+
tableNodeId: table.nodeId,
|
|
13405
|
+
rowIndex: typeof row?.index === "number" ? row.index : null,
|
|
13406
|
+
columnIndex: typeof column?.index === "number" ? column.index : null,
|
|
13407
|
+
cellNodeId: typeof cell?.nodeId === "string" ? cell.nodeId : null,
|
|
13408
|
+
rows: typeof table.rows === "number" ? table.rows : null,
|
|
13409
|
+
columns: typeof table.columns === "number" ? table.columns : null,
|
|
13410
|
+
cellRange: readMergeRange(snapshot.cellRange),
|
|
13411
|
+
tableSelection: snapshot.tableSelection ?? null
|
|
13412
|
+
};
|
|
13282
13413
|
};
|
|
13283
13414
|
const tables = {
|
|
13284
|
-
getContext: () =>
|
|
13285
|
-
|
|
13286
|
-
|
|
13287
|
-
|
|
13415
|
+
getContext: () => publicTableContext(readHostTableContext()),
|
|
13416
|
+
getContextAsync: async () => {
|
|
13417
|
+
for (let attempt = 0; attempt < 2; attempt += 1) {
|
|
13418
|
+
const token = selectionReadToken();
|
|
13419
|
+
const host = getHost();
|
|
13420
|
+
const read = host?.getTableContextAsync;
|
|
13421
|
+
if (typeof read !== "function") return publicTableContext(readHostTableContext());
|
|
13422
|
+
let snapshot = null;
|
|
13423
|
+
try {
|
|
13424
|
+
snapshot = await read.call(host);
|
|
13425
|
+
} catch {
|
|
13426
|
+
return {
|
|
13427
|
+
...EMPTY_TABLE_CONTEXT,
|
|
13428
|
+
status: "pending"
|
|
13429
|
+
};
|
|
13430
|
+
}
|
|
13431
|
+
if (disposed) return {
|
|
13432
|
+
...EMPTY_TABLE_CONTEXT,
|
|
13433
|
+
status: "pending"
|
|
13434
|
+
};
|
|
13435
|
+
if (token !== selectionReadToken() || host !== getHost()) continue;
|
|
13436
|
+
const context = publicTableContext(snapshot);
|
|
13437
|
+
if (context.status === "stale") continue;
|
|
13438
|
+
return context;
|
|
13439
|
+
}
|
|
13288
13440
|
return {
|
|
13289
|
-
|
|
13290
|
-
|
|
13291
|
-
rowIndex: context.rowIndex,
|
|
13292
|
-
columnIndex: context.columnIndex,
|
|
13293
|
-
cellNodeId: context.cellNodeId,
|
|
13294
|
-
rows: typeof table?.rows === "number" ? table.rows : null,
|
|
13295
|
-
columns: typeof table?.columns === "number" ? table.columns : null
|
|
13441
|
+
...EMPTY_TABLE_CONTEXT,
|
|
13442
|
+
status: "stale"
|
|
13296
13443
|
};
|
|
13297
13444
|
},
|
|
13298
13445
|
isInTable: () => resolveTableContext() != null
|
|
@@ -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.24.0-next.
|
|
22
|
+
superdocVersion: "2.24.0-next.3",
|
|
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.24.0-next.
|
|
21
|
+
superdocVersion: "2.24.0-next.3",
|
|
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
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import { SelectionTarget, TextTarget } from '../types/address.js';
|
|
2
2
|
export interface SelectionTableCellsTarget {
|
|
3
3
|
kind: 'tableCells';
|
|
4
|
+
selectionMode?: 'cells';
|
|
5
|
+
isRectangular?: true;
|
|
4
6
|
tableId: string;
|
|
5
7
|
start: {
|
|
6
8
|
rowIndex: number;
|
|
@@ -12,15 +14,33 @@ export interface SelectionTableCellsTarget {
|
|
|
12
14
|
};
|
|
13
15
|
story?: SelectionTarget['story'];
|
|
14
16
|
}
|
|
15
|
-
/** Table
|
|
16
|
-
export interface TableSelectionInfo
|
|
17
|
-
|
|
17
|
+
/** Table/cell context for the selection; bounds alone are not an editing target. */
|
|
18
|
+
export interface TableSelectionInfo {
|
|
19
|
+
kind: 'tableCells';
|
|
20
|
+
tableId: string;
|
|
21
|
+
story?: SelectionTarget['story'];
|
|
22
|
+
/** Inclusive logical bounds, including each selected owner's span. */
|
|
23
|
+
start: {
|
|
24
|
+
rowIndex: number;
|
|
25
|
+
columnIndex: number;
|
|
26
|
+
};
|
|
27
|
+
end: {
|
|
28
|
+
rowIndex: number;
|
|
29
|
+
columnIndex: number;
|
|
30
|
+
};
|
|
31
|
+
/** Whole-table identity requires whole-cell selection intent. */
|
|
18
32
|
type: 'table' | 'cell' | 'cells';
|
|
19
|
-
/**
|
|
33
|
+
/** Text context preserves exact character targets; cells denotes whole-cell intent. */
|
|
34
|
+
selectionMode: 'text' | 'cells';
|
|
35
|
+
/** Whether the exact cells fill the bounding rectangle without holes. */
|
|
36
|
+
isRectangular: boolean;
|
|
37
|
+
/** Exact logical owners in row-major order; vertical continuations are deduplicated. */
|
|
20
38
|
cells: {
|
|
21
39
|
nodeId: string;
|
|
22
40
|
rowIndex: number;
|
|
23
41
|
columnIndex: number;
|
|
42
|
+
rowspan: number;
|
|
43
|
+
colspan: number;
|
|
24
44
|
}[];
|
|
25
45
|
}
|
|
26
46
|
export type SelectionExtractOoxmlInput = {
|
|
@@ -123,6 +143,12 @@ export interface SelectionInfo {
|
|
|
123
143
|
* full selection.
|
|
124
144
|
*/
|
|
125
145
|
target: TextTarget | null;
|
|
146
|
+
/** Deletion-inclusive multi-block text coverage for range review decisions, when resolvable. */
|
|
147
|
+
trackedTarget?: TextTarget | null;
|
|
148
|
+
/** Whether this exact text range supports tracked-change decisions; excludes permissions. */
|
|
149
|
+
trackedChangeRangeDecisionSupported?: boolean;
|
|
150
|
+
/** Whether the selection covers every tracked-text fragment of each active change. */
|
|
151
|
+
trackedChangesWhollySelected?: boolean;
|
|
126
152
|
/**
|
|
127
153
|
* Explicit selection envelope for the current live selection, or `null` when
|
|
128
154
|
* the runtime cannot project one truthfully.
|
|
@@ -132,10 +158,11 @@ export interface SelectionInfo {
|
|
|
132
158
|
*/
|
|
133
159
|
selectionTarget?: SelectionTarget | null;
|
|
134
160
|
/**
|
|
135
|
-
* V2 browser
|
|
136
|
-
*
|
|
137
|
-
*
|
|
138
|
-
*
|
|
161
|
+
* V2 browser cell context with inclusive, zero-based logical bounds.
|
|
162
|
+
* Whole-cell selections clear text targets. Character selections preserve
|
|
163
|
+
* their targets and include the containing cells, including endpoint cells.
|
|
164
|
+
* Exact cell IDs and spans describe merged or nonrectangular selections;
|
|
165
|
+
* only rectangular whole-cell metadata can become a table-cells target.
|
|
139
166
|
*/
|
|
140
167
|
tableSelection?: TableSelectionInfo | null;
|
|
141
168
|
/**
|
package/dist/public/ui-react.cjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
|
-
const require_create_super_doc_ui = require("../chunks/create-super-doc-ui-
|
|
2
|
+
const require_create_super_doc_ui = require("../chunks/create-super-doc-ui-bTFGKVRb.cjs");
|
|
3
3
|
const require_slice_source = require("../chunks/slice-source-CFaqq0Vo.cjs");
|
|
4
4
|
let react = require("react");
|
|
5
5
|
//#region src/public/ui/react.ts
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { t as createSuperDocUI } from "../chunks/create-super-doc-ui-
|
|
1
|
+
import { t as createSuperDocUI } from "../chunks/create-super-doc-ui-8UTu16Lw.es.js";
|
|
2
2
|
import { t as toSliceSource } from "../chunks/slice-source-gfOhG2MW.es.js";
|
|
3
3
|
import { createContext, createElement, useCallback, useContext, useEffect, useRef, useState } from "react";
|
|
4
4
|
//#region src/public/ui/react.ts
|
package/dist/public/ui-vue.cjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
|
-
const require_create_super_doc_ui = require("../chunks/create-super-doc-ui-
|
|
2
|
+
const require_create_super_doc_ui = require("../chunks/create-super-doc-ui-bTFGKVRb.cjs");
|
|
3
3
|
const require_slice_source = require("../chunks/slice-source-CFaqq0Vo.cjs");
|
|
4
4
|
let superdoc_entry_vue = require("vue");
|
|
5
5
|
//#region src/public/ui/vue.ts
|
package/dist/public/ui-vue.es.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { t as createSuperDocUI } from "../chunks/create-super-doc-ui-
|
|
1
|
+
import { t as createSuperDocUI } from "../chunks/create-super-doc-ui-8UTu16Lw.es.js";
|
|
2
2
|
import { t as toSliceSource } from "../chunks/slice-source-gfOhG2MW.es.js";
|
|
3
3
|
import { computed, inject, onScopeDispose, provide, shallowRef, toRaw, toValue, watch } from "vue";
|
|
4
4
|
//#region src/public/ui/vue.ts
|
package/dist/public/ui.cjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
|
-
const require_create_super_doc_ui = require("../chunks/create-super-doc-ui-
|
|
2
|
+
const require_create_super_doc_ui = require("../chunks/create-super-doc-ui-bTFGKVRb.cjs");
|
|
3
3
|
exports.BUILT_IN_COMMAND_IDS = require_create_super_doc_ui.BUILT_IN_COMMAND_IDS;
|
|
4
4
|
exports.createSuperDocUI = require_create_super_doc_ui.createSuperDocUI;
|
|
5
5
|
exports.shallowEqual = require_create_super_doc_ui.shallowEqual;
|
package/dist/public/ui.es.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { a as BUILT_IN_COMMAND_IDS, t as createSuperDocUI, u as shallowEqual } from "../chunks/create-super-doc-ui-
|
|
1
|
+
import { a as BUILT_IN_COMMAND_IDS, t as createSuperDocUI, u as shallowEqual } from "../chunks/create-super-doc-ui-8UTu16Lw.es.js";
|
|
2
2
|
export { BUILT_IN_COMMAND_IDS, createSuperDocUI, shallowEqual };
|
|
@@ -551,6 +551,12 @@ export interface SelectionSlice {
|
|
|
551
551
|
empty: boolean;
|
|
552
552
|
/** Resolved text target for the selection, when available. */
|
|
553
553
|
target: TextTarget | null;
|
|
554
|
+
/** Deletion-inclusive multi-block coverage for range review decisions, when available. */
|
|
555
|
+
trackedTarget?: TextTarget | null;
|
|
556
|
+
/** Whether this exact text range supports tracked-change decisions; excludes permissions. */
|
|
557
|
+
trackedChangeRangeDecisionSupported?: boolean;
|
|
558
|
+
/** Whether the selection covers every tracked-text fragment of each active change. */
|
|
559
|
+
trackedChangesWhollySelected?: boolean;
|
|
554
560
|
/** Explicit start/end selection target, when available. */
|
|
555
561
|
selectionTarget: SelectionTarget | null;
|
|
556
562
|
/** Table/cell identities from the settled public selection read, when supported. */
|
|
@@ -1270,6 +1276,20 @@ export interface MetadataHandle {
|
|
|
1270
1276
|
* through; custom UIs read it to enable / label their own table controls.
|
|
1271
1277
|
*/
|
|
1272
1278
|
export interface TableContextInfo {
|
|
1279
|
+
/** Runtime always supplies status; stale/pending snapshots carry no previous cell IDs. */
|
|
1280
|
+
status?: SliceStatus;
|
|
1281
|
+
/** Inclusive logical bounding geometry; use tableSelection for exact membership. */
|
|
1282
|
+
cellRange?: {
|
|
1283
|
+
start: {
|
|
1284
|
+
rowIndex: number;
|
|
1285
|
+
columnIndex: number;
|
|
1286
|
+
};
|
|
1287
|
+
end: {
|
|
1288
|
+
rowIndex: number;
|
|
1289
|
+
columnIndex: number;
|
|
1290
|
+
};
|
|
1291
|
+
} | null;
|
|
1292
|
+
tableSelection?: SelectionInfo['tableSelection'];
|
|
1273
1293
|
/** Whether the current selection is inside a table. */
|
|
1274
1294
|
inTable: boolean;
|
|
1275
1295
|
/** Stable node id of the enclosing table, when resolved. */
|
|
@@ -1289,6 +1309,8 @@ export interface TableContextInfo {
|
|
|
1289
1309
|
export interface TablesHandle {
|
|
1290
1310
|
/** Read the current table context snapshot. */
|
|
1291
1311
|
getContext(): TableContextInfo;
|
|
1312
|
+
/** Resolve fresh, bounded table context for immediate context-menu callbacks. */
|
|
1313
|
+
getContextAsync(): Promise<TableContextInfo>;
|
|
1292
1314
|
/** Convenience: whether the current selection is inside a table. */
|
|
1293
1315
|
isInTable(): boolean;
|
|
1294
1316
|
}
|