superdoc 2.6.0-next.7 → 2.6.0-next.8
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/collaboration-upgrade-engine.cjs +1 -1
- package/dist/collaboration-upgrade-engine.es.js +1 -1
- package/dist/style.css +134 -92
- package/dist/style.layered.css +134 -92
- package/dist/superdoc/src/stores/comments-store.d.ts +62 -5
- package/dist/superdoc/src/stores/superdoc-store.d.ts +186 -15
- package/dist/superdoc.cjs +245 -51
- package/dist/superdoc.es.js +245 -51
- package/dist-cdn/style.layered.css +1 -1
- package/dist-cdn/superdoc.min.css +1 -1
- package/dist-cdn/superdoc.min.js +37 -37
- package/package.json +2 -2
package/dist/superdoc.es.js
CHANGED
|
@@ -5693,7 +5693,7 @@ function useComment(params) {
|
|
|
5693
5693
|
const fileType = params.fileType;
|
|
5694
5694
|
const createdAtVersionNumber = params.createdAtVersionNumber;
|
|
5695
5695
|
const isInternal = ref(params.isInternal !== void 0 ? params.isInternal : true);
|
|
5696
|
-
const mentions = ref([]);
|
|
5696
|
+
const mentions = ref(Array.isArray(params.mentions) ? params.mentions : []);
|
|
5697
5697
|
const commentElement = ref(null);
|
|
5698
5698
|
const isFocused = ref(params.isFocused || false);
|
|
5699
5699
|
const creatorId = ref(params.creatorId ?? null);
|
|
@@ -7253,6 +7253,7 @@ var useCommentsStore = defineStore("comments", () => {
|
|
|
7253
7253
|
const overlappedIds = /* @__PURE__ */ new Set([]);
|
|
7254
7254
|
const suppressInternalExternal = ref(true);
|
|
7255
7255
|
const currentCommentText = ref("");
|
|
7256
|
+
const currentCommentMentions = ref([]);
|
|
7256
7257
|
const commentsList = ref([]);
|
|
7257
7258
|
const reviewDirectoryList = shallowRef([]);
|
|
7258
7259
|
let priorTrackedChangeThreadIndex = /* @__PURE__ */ new Map();
|
|
@@ -8335,6 +8336,7 @@ var useCommentsStore = defineStore("comments", () => {
|
|
|
8335
8336
|
const removePendingComment = (superdoc) => {
|
|
8336
8337
|
const hadPending = !!pendingComment.value;
|
|
8337
8338
|
currentCommentText.value = "";
|
|
8339
|
+
currentCommentMentions.value = [];
|
|
8338
8340
|
pendingComment.value = null;
|
|
8339
8341
|
pendingV2CommentTarget.value = null;
|
|
8340
8342
|
superdocStore.selectionPosition = null;
|
|
@@ -8354,16 +8356,19 @@ var useCommentsStore = defineStore("comments", () => {
|
|
|
8354
8356
|
const v2Adapter = !skipEditorUpdate && !isHydration ? getV2CommentsAdapter(superdoc) : null;
|
|
8355
8357
|
if (v2Adapter && !comment.trackedChange) {
|
|
8356
8358
|
const text = normalizeV2CommentDraftText(pendingComment.value ? currentCommentText.value : comment.commentText);
|
|
8359
|
+
const mentions = pendingComment.value ? currentCommentMentions.value : comment.mentions ?? [];
|
|
8357
8360
|
const target = pendingComment.value ? pendingV2CommentTarget.value : null;
|
|
8358
8361
|
const parentCommentId = comment.parentCommentId ? String(comment.parentCommentId) : pendingComment.value ? null : null;
|
|
8359
8362
|
return (async () => {
|
|
8360
8363
|
try {
|
|
8361
8364
|
return await (parentCommentId ? v2Adapter.reply({
|
|
8362
8365
|
parentCommentId,
|
|
8363
|
-
text
|
|
8366
|
+
text,
|
|
8367
|
+
...mentions.length ? { mentions } : {}
|
|
8364
8368
|
}) : v2Adapter.commitPendingComment({
|
|
8365
8369
|
text,
|
|
8366
|
-
target
|
|
8370
|
+
target,
|
|
8371
|
+
...mentions.length ? { mentions } : {}
|
|
8367
8372
|
}));
|
|
8368
8373
|
} catch (err) {
|
|
8369
8374
|
return {
|
|
@@ -8824,7 +8829,7 @@ var useCommentsStore = defineStore("comments", () => {
|
|
|
8824
8829
|
* - rejection preserves rows and emits a rejected `comments-update` event
|
|
8825
8830
|
* - committed-but-refresh-failed surfaces honestly (no reconcile with `[]`)
|
|
8826
8831
|
*/
|
|
8827
|
-
const replyCommentV2 = async ({ superdoc, parentCommentId, text } = {}) => {
|
|
8832
|
+
const replyCommentV2 = async ({ superdoc, parentCommentId, text, mentions = [] } = {}) => {
|
|
8828
8833
|
if (commentsAreReadOnly()) return readOnlyMutationOutcome();
|
|
8829
8834
|
const v2Adapter = getV2CommentsAdapter(superdoc);
|
|
8830
8835
|
if (!v2Adapter) return {
|
|
@@ -8849,7 +8854,8 @@ var useCommentsStore = defineStore("comments", () => {
|
|
|
8849
8854
|
fileId,
|
|
8850
8855
|
operation: () => v2Adapter.reply({
|
|
8851
8856
|
parentCommentId: normalizedParent,
|
|
8852
|
-
text: plainText
|
|
8857
|
+
text: plainText,
|
|
8858
|
+
...mentions.length ? { mentions } : {}
|
|
8853
8859
|
}),
|
|
8854
8860
|
eventType: COMMENT_EVENTS.ADD,
|
|
8855
8861
|
rejectionFallbackReason: "v2-reply-failed",
|
|
@@ -9305,6 +9311,7 @@ var useCommentsStore = defineStore("comments", () => {
|
|
|
9305
9311
|
};
|
|
9306
9312
|
const applyUpdate = (existing, input) => {
|
|
9307
9313
|
existing.commentText = input.commentText ?? existing.commentText;
|
|
9314
|
+
existing.mentions = Array.isArray(input.mentions) ? input.mentions : [];
|
|
9308
9315
|
existing.isInternal = typeof input.isInternal === "boolean" ? input.isInternal : existing.isInternal;
|
|
9309
9316
|
if (typeof input.resolvedTime === "number") {
|
|
9310
9317
|
existing.resolvedTime = input.resolvedTimeWasSynthesized === true && typeof existing.resolvedTime === "number" ? existing.resolvedTime : input.resolvedTime;
|
|
@@ -9354,6 +9361,58 @@ var useCommentsStore = defineStore("comments", () => {
|
|
|
9354
9361
|
return { added: addedComments[addedComments.length - 1] ?? null };
|
|
9355
9362
|
});
|
|
9356
9363
|
/**
|
|
9364
|
+
* Reconcile and publish a root comment created by the private V2 context menu.
|
|
9365
|
+
* That path owns selection capture, while this store remains the sole owner
|
|
9366
|
+
* of shared comment rows and public comments-update events.
|
|
9367
|
+
*/
|
|
9368
|
+
const announceV2CommentCreated = async ({ superdoc, commentId } = {}) => {
|
|
9369
|
+
const id = normalizeCommentId(commentId);
|
|
9370
|
+
const adapter = getV2CommentsAdapter(superdoc);
|
|
9371
|
+
const commentsApi = superdoc?.activeEditor?.doc?.comments;
|
|
9372
|
+
if (!id) return {
|
|
9373
|
+
ok: false,
|
|
9374
|
+
reason: "comment-id-missing"
|
|
9375
|
+
};
|
|
9376
|
+
if (!adapter || !isCurrentV2CommentsAdapter(adapter)) return {
|
|
9377
|
+
ok: false,
|
|
9378
|
+
reason: "comments-adapter-stale"
|
|
9379
|
+
};
|
|
9380
|
+
if (typeof commentsApi?.get !== "function") return {
|
|
9381
|
+
ok: false,
|
|
9382
|
+
reason: "document-api-unavailable"
|
|
9383
|
+
};
|
|
9384
|
+
let item;
|
|
9385
|
+
try {
|
|
9386
|
+
item = await commentsApi.get({ commentId: id });
|
|
9387
|
+
} catch (err) {
|
|
9388
|
+
return {
|
|
9389
|
+
ok: false,
|
|
9390
|
+
reason: "comment-read-failed",
|
|
9391
|
+
detail: err?.message ?? String(err)
|
|
9392
|
+
};
|
|
9393
|
+
}
|
|
9394
|
+
if (!isCurrentV2CommentsAdapter(adapter)) return {
|
|
9395
|
+
ok: false,
|
|
9396
|
+
reason: "comments-adapter-stale"
|
|
9397
|
+
};
|
|
9398
|
+
const comment = reconcileCommentsFromV2({
|
|
9399
|
+
superdoc,
|
|
9400
|
+
adapter,
|
|
9401
|
+
documentId: adapter.documentId,
|
|
9402
|
+
items: [item],
|
|
9403
|
+
pruneStale: false
|
|
9404
|
+
})?.added ?? commentsList.value.find((candidate) => String(candidate?.commentId ?? "") === id || String(candidate?.importedId ?? "") === id) ?? null;
|
|
9405
|
+
const event = {
|
|
9406
|
+
type: COMMENT_EVENTS.ADD,
|
|
9407
|
+
comment: comment?.getValues?.() ?? null
|
|
9408
|
+
};
|
|
9409
|
+
superdoc?.emit?.("comments-update", event);
|
|
9410
|
+
return {
|
|
9411
|
+
ok: true,
|
|
9412
|
+
comment
|
|
9413
|
+
};
|
|
9414
|
+
};
|
|
9415
|
+
/**
|
|
9357
9416
|
* Cancel the pending comment
|
|
9358
9417
|
*
|
|
9359
9418
|
* @returns {void}
|
|
@@ -9554,7 +9613,7 @@ var useCommentsStore = defineStore("comments", () => {
|
|
|
9554
9613
|
});
|
|
9555
9614
|
commentsList.value = commentsList.value.filter((comment) => !removedComments.includes(comment));
|
|
9556
9615
|
if (removedAliasIds.size) {
|
|
9557
|
-
const nextPositions = { ...editorCommentPositions.value
|
|
9616
|
+
const nextPositions = { ...editorCommentPositions.value };
|
|
9558
9617
|
removedAliasIds.forEach((id) => {
|
|
9559
9618
|
delete nextPositions[id];
|
|
9560
9619
|
});
|
|
@@ -11075,6 +11134,7 @@ var useCommentsStore = defineStore("comments", () => {
|
|
|
11075
11134
|
suppressInternalExternal,
|
|
11076
11135
|
pendingComment,
|
|
11077
11136
|
currentCommentText,
|
|
11137
|
+
currentCommentMentions,
|
|
11078
11138
|
commentsList,
|
|
11079
11139
|
reviewDirectoryList,
|
|
11080
11140
|
isCommentsListVisible,
|
|
@@ -11150,6 +11210,7 @@ var useCommentsStore = defineStore("comments", () => {
|
|
|
11150
11210
|
getV2CommentsAdapter,
|
|
11151
11211
|
applyReviewWindowFromV2,
|
|
11152
11212
|
reconcileCommentsFromV2,
|
|
11213
|
+
announceV2CommentCreated,
|
|
11153
11214
|
isV2EditorActive,
|
|
11154
11215
|
replyCommentV2,
|
|
11155
11216
|
editCommentV2,
|
|
@@ -11298,13 +11359,13 @@ function useUiFontFamily() {
|
|
|
11298
11359
|
//#endregion
|
|
11299
11360
|
//#region src/components/CommentsLayer/CommentsDropdown.vue
|
|
11300
11361
|
var _hoisted_1$31 = { class: "comments-dropdown" };
|
|
11301
|
-
var _hoisted_2$
|
|
11302
|
-
var _hoisted_3$
|
|
11362
|
+
var _hoisted_2$25 = ["onClick"];
|
|
11363
|
+
var _hoisted_3$21 = {
|
|
11303
11364
|
key: 0,
|
|
11304
11365
|
class: "comments-dropdown__option-icon"
|
|
11305
11366
|
};
|
|
11306
|
-
var _hoisted_4$
|
|
11307
|
-
var _hoisted_5$
|
|
11367
|
+
var _hoisted_4$13 = ["innerHTML"];
|
|
11368
|
+
var _hoisted_5$9 = { class: "comments-dropdown__option-label" };
|
|
11308
11369
|
var CommentsDropdown_default = /*#__PURE__*/ _plugin_vue_export_helper_default({
|
|
11309
11370
|
__name: "CommentsDropdown",
|
|
11310
11371
|
props: {
|
|
@@ -11444,13 +11505,13 @@ var CommentsDropdown_default = /*#__PURE__*/ _plugin_vue_export_helper_default({
|
|
|
11444
11505
|
key: option.key,
|
|
11445
11506
|
class: normalizeClass(["comments-dropdown__option", { "sd-disabled": option.disabled }]),
|
|
11446
11507
|
onClick: ($event) => onOptionClick(option)
|
|
11447
|
-
}, [hasIcon(option) ? (openBlock(), createElementBlock("span", _hoisted_3$
|
|
11508
|
+
}, [hasIcon(option) ? (openBlock(), createElementBlock("span", _hoisted_3$21, [option.iconString ? (openBlock(), createElementBlock("span", {
|
|
11448
11509
|
key: 0,
|
|
11449
11510
|
innerHTML: option.iconString
|
|
11450
|
-
}, null, 8, _hoisted_4$
|
|
11511
|
+
}, null, 8, _hoisted_4$13)) : (openBlock(), createBlock(unref(OptionIcon), {
|
|
11451
11512
|
key: 1,
|
|
11452
11513
|
option
|
|
11453
|
-
}, null, 8, ["option"]))])) : createCommentVNode("", true), createElementVNode("span", _hoisted_5$
|
|
11514
|
+
}, null, 8, ["option"]))])) : createCommentVNode("", true), createElementVNode("span", _hoisted_5$9, toDisplayString(option.label), 1)], 10, _hoisted_2$25);
|
|
11454
11515
|
}), 128))], 4)) : createCommentVNode("", true)]))]);
|
|
11455
11516
|
};
|
|
11456
11517
|
}
|
|
@@ -11458,9 +11519,9 @@ var CommentsDropdown_default = /*#__PURE__*/ _plugin_vue_export_helper_default({
|
|
|
11458
11519
|
//#endregion
|
|
11459
11520
|
//#region src/components/CommentsLayer/InternalDropdown.vue
|
|
11460
11521
|
var _hoisted_1$30 = { class: "sd-comment-option" };
|
|
11461
|
-
var _hoisted_2$
|
|
11462
|
-
var _hoisted_3$
|
|
11463
|
-
var _hoisted_4$
|
|
11522
|
+
var _hoisted_2$24 = ["innerHTML"];
|
|
11523
|
+
var _hoisted_3$20 = { class: "sd-option-state" };
|
|
11524
|
+
var _hoisted_4$12 = ["innerHTML"];
|
|
11464
11525
|
var InternalDropdown_default = /*#__PURE__*/ _plugin_vue_export_helper_default({
|
|
11465
11526
|
__name: "InternalDropdown",
|
|
11466
11527
|
props: {
|
|
@@ -11532,12 +11593,12 @@ var InternalDropdown_default = /*#__PURE__*/ _plugin_vue_export_helper_default({
|
|
|
11532
11593
|
createElementVNode("div", {
|
|
11533
11594
|
class: "sd-active-icon",
|
|
11534
11595
|
innerHTML: activeIcon.value
|
|
11535
|
-
}, null, 8, _hoisted_2$
|
|
11536
|
-
createElementVNode("div", _hoisted_3$
|
|
11596
|
+
}, null, 8, _hoisted_2$24),
|
|
11597
|
+
createElementVNode("div", _hoisted_3$20, toDisplayString(getState.value), 1),
|
|
11537
11598
|
createElementVNode("div", {
|
|
11538
11599
|
class: "sd-dropdown-caret",
|
|
11539
11600
|
innerHTML: unref(superdocIcons).caretDown
|
|
11540
|
-
}, null, 8, _hoisted_4$
|
|
11601
|
+
}, null, 8, _hoisted_4$12)
|
|
11541
11602
|
])]),
|
|
11542
11603
|
_: 1
|
|
11543
11604
|
}, 8, ["disabled", "content-style"])], 4);
|
|
@@ -11687,8 +11748,8 @@ var isAllowed = (permission, role, isInternal, context = {}) => {
|
|
|
11687
11748
|
//#endregion
|
|
11688
11749
|
//#region src/components/general/Avatar.vue
|
|
11689
11750
|
var _hoisted_1$29 = { class: "user-container" };
|
|
11690
|
-
var _hoisted_2$
|
|
11691
|
-
var _hoisted_3$
|
|
11751
|
+
var _hoisted_2$23 = ["src"];
|
|
11752
|
+
var _hoisted_3$19 = {
|
|
11692
11753
|
key: 1,
|
|
11693
11754
|
class: "user-bg"
|
|
11694
11755
|
};
|
|
@@ -11713,21 +11774,21 @@ var Avatar_default = /*#__PURE__*/ _plugin_vue_export_helper_default({
|
|
|
11713
11774
|
key: 0,
|
|
11714
11775
|
class: "user-bg",
|
|
11715
11776
|
src: __props.user.image.startsWith("http") ? __props.user.image : `data:image/png;base64,${__props.user.image}`
|
|
11716
|
-
}, null, 8, _hoisted_2$
|
|
11777
|
+
}, null, 8, _hoisted_2$23)) : (openBlock(), createElementBlock("span", _hoisted_3$19, toDisplayString(getInitials(__props.user.name, __props.user.email)), 1))]);
|
|
11717
11778
|
};
|
|
11718
11779
|
}
|
|
11719
11780
|
}, [["__scopeId", "data-v-c95b2073"]]);
|
|
11720
11781
|
//#endregion
|
|
11721
11782
|
//#region src/components/CommentsLayer/CommentHeader.vue
|
|
11722
11783
|
var _hoisted_1$28 = { class: "card-section comment-header" };
|
|
11723
|
-
var _hoisted_2$
|
|
11724
|
-
var _hoisted_3$
|
|
11725
|
-
var _hoisted_4$
|
|
11726
|
-
var _hoisted_5$
|
|
11784
|
+
var _hoisted_2$22 = { class: "comment-header-left" };
|
|
11785
|
+
var _hoisted_3$18 = { class: "user-info" };
|
|
11786
|
+
var _hoisted_4$11 = { class: "user-name" };
|
|
11787
|
+
var _hoisted_5$8 = {
|
|
11727
11788
|
key: 0,
|
|
11728
11789
|
class: "imported-tag"
|
|
11729
11790
|
};
|
|
11730
|
-
var _hoisted_6$
|
|
11791
|
+
var _hoisted_6$7 = {
|
|
11731
11792
|
key: 0,
|
|
11732
11793
|
class: "user-timestamp"
|
|
11733
11794
|
};
|
|
@@ -11952,10 +12013,10 @@ var CommentHeader_default = /*#__PURE__*/ _plugin_vue_export_helper_default({
|
|
|
11952
12013
|
return user;
|
|
11953
12014
|
});
|
|
11954
12015
|
return (_ctx, _cache) => {
|
|
11955
|
-
return openBlock(), createElementBlock("div", _hoisted_1$28, [createElementVNode("div", _hoisted_2$
|
|
12016
|
+
return openBlock(), createElementBlock("div", _hoisted_1$28, [createElementVNode("div", _hoisted_2$22, [createVNode(Avatar_default, {
|
|
11956
12017
|
user: getCurrentUser.value,
|
|
11957
12018
|
class: "avatar"
|
|
11958
|
-
}, null, 8, ["user"]), createElementVNode("div", _hoisted_3$
|
|
12019
|
+
}, null, 8, ["user"]), createElementVNode("div", _hoisted_3$18, [createElementVNode("div", _hoisted_4$11, [createTextVNode(toDisplayString(getCurrentUser.value.name), 1), isImported.value ? (openBlock(), createElementBlock("span", _hoisted_5$8, "IMPORTED")) : createCommentVNode("", true)]), props.comment.createdTime ? (openBlock(), createElementBlock("div", _hoisted_6$7, toDisplayString(unref(formatDate)(props.comment.createdTime)), 1)) : createCommentVNode("", true)])]), createElementVNode("div", { class: normalizeClass(["overflow-menu", { "is-visible": props.isActive }]) }, [
|
|
11959
12020
|
allowResolve.value ? (openBlock(), createElementBlock("div", {
|
|
11960
12021
|
key: 0,
|
|
11961
12022
|
class: normalizeClass(["overflow-menu__icon", { "sd-is-disabled": Boolean(__props.resolveDisabledReason) }]),
|
|
@@ -12004,8 +12065,24 @@ var CommentHeader_default = /*#__PURE__*/ _plugin_vue_export_helper_default({
|
|
|
12004
12065
|
//#endregion
|
|
12005
12066
|
//#region src/components/CommentsLayer/CommentInput.vue
|
|
12006
12067
|
var _hoisted_1$27 = { class: "input-section" };
|
|
12007
|
-
var
|
|
12008
|
-
var
|
|
12068
|
+
var _hoisted_2$21 = { class: "comment-composer" };
|
|
12069
|
+
var _hoisted_3$17 = [
|
|
12070
|
+
"aria-expanded",
|
|
12071
|
+
"aria-controls",
|
|
12072
|
+
"aria-activedescendant"
|
|
12073
|
+
];
|
|
12074
|
+
var _hoisted_4$10 = [
|
|
12075
|
+
"id",
|
|
12076
|
+
"aria-selected",
|
|
12077
|
+
"data-sd-comment-mention-option",
|
|
12078
|
+
"onMousedown"
|
|
12079
|
+
];
|
|
12080
|
+
var _hoisted_5$7 = { class: "comment-mention-option__name" };
|
|
12081
|
+
var _hoisted_6$6 = {
|
|
12082
|
+
key: 0,
|
|
12083
|
+
class: "comment-mention-option__email"
|
|
12084
|
+
};
|
|
12085
|
+
var commentInputSequence = 0;
|
|
12009
12086
|
var CommentInput_default = /*#__PURE__*/ _plugin_vue_export_helper_default({
|
|
12010
12087
|
__name: "CommentInput",
|
|
12011
12088
|
props: {
|
|
@@ -12033,15 +12110,23 @@ var CommentInput_default = /*#__PURE__*/ _plugin_vue_export_helper_default({
|
|
|
12033
12110
|
},
|
|
12034
12111
|
emits: ["focus"],
|
|
12035
12112
|
setup(__props, { expose: __expose, emit: __emit }) {
|
|
12113
|
+
const TEXTAREA_MIN_HEIGHT = 28;
|
|
12114
|
+
const TEXTAREA_MAX_HEIGHT = 132;
|
|
12036
12115
|
const emit = __emit;
|
|
12037
|
-
const
|
|
12116
|
+
const props = __props;
|
|
12117
|
+
const { currentCommentText, currentCommentMentions } = storeToRefs(useCommentsStore());
|
|
12038
12118
|
const inputRef = ref(null);
|
|
12119
|
+
const mentionStart = ref(null);
|
|
12120
|
+
const mentionQuery = ref("");
|
|
12121
|
+
const highlightedMentionIndex = ref(0);
|
|
12122
|
+
const mentionListId = `sd-comment-mention-list-${++commentInputSequence}`;
|
|
12039
12123
|
const handleFocusChange = (focused) => emit("focus", focused);
|
|
12124
|
+
const getInputElement = () => inputRef.value;
|
|
12040
12125
|
const focus = (options) => {
|
|
12041
|
-
|
|
12126
|
+
getInputElement()?.focus?.(options);
|
|
12042
12127
|
};
|
|
12043
12128
|
const syncInputHeight = () => {
|
|
12044
|
-
const input =
|
|
12129
|
+
const input = getInputElement();
|
|
12045
12130
|
if (!input) return;
|
|
12046
12131
|
input.style.height = `${TEXTAREA_MIN_HEIGHT}px`;
|
|
12047
12132
|
const scrollHeight = input.scrollHeight || TEXTAREA_MIN_HEIGHT;
|
|
@@ -12072,6 +12157,79 @@ var CommentInput_default = /*#__PURE__*/ _plugin_vue_export_helper_default({
|
|
|
12072
12157
|
currentCommentText.value = textToHtml(value);
|
|
12073
12158
|
}
|
|
12074
12159
|
});
|
|
12160
|
+
const displayName = (user) => user?.name?.trim() || user?.email?.trim() || "";
|
|
12161
|
+
const userKey = (user) => String(user?.id ?? user?.email ?? user?.name ?? "");
|
|
12162
|
+
const isViewer = (user) => user?.role === "viewer" || user?.access === "viewer" || typeof user?.access === "object" && user.access?.role === "viewer";
|
|
12163
|
+
const mentionIdentity = (user) => ({
|
|
12164
|
+
...user?.id != null ? { id: user.id } : {},
|
|
12165
|
+
...user?.name != null ? { name: user.name } : {},
|
|
12166
|
+
...user?.email != null ? { email: user.email } : {}
|
|
12167
|
+
});
|
|
12168
|
+
const mentionSuggestions = computed(() => {
|
|
12169
|
+
if (mentionStart.value == null) return [];
|
|
12170
|
+
const needle = mentionQuery.value.toLocaleLowerCase();
|
|
12171
|
+
return props.users.filter((user) => !isViewer(user) && displayName(user)).filter((user) => {
|
|
12172
|
+
const name = displayName(user).toLocaleLowerCase();
|
|
12173
|
+
const email = user?.email?.toLocaleLowerCase() ?? "";
|
|
12174
|
+
return !needle || name.startsWith(needle) || email.startsWith(needle);
|
|
12175
|
+
}).slice(0, 8);
|
|
12176
|
+
});
|
|
12177
|
+
const mentionListOpen = computed(() => mentionSuggestions.value.length > 0);
|
|
12178
|
+
const activeMentionOptionId = computed(() => {
|
|
12179
|
+
const user = mentionSuggestions.value[highlightedMentionIndex.value];
|
|
12180
|
+
return user ? `${mentionListId}-${userKey(user)}` : void 0;
|
|
12181
|
+
});
|
|
12182
|
+
const updateMentionQuery = (caret) => {
|
|
12183
|
+
const beforeCaret = commentDraft.value.slice(0, caret);
|
|
12184
|
+
const match = /(?:^|\s)@([^\s@]{0,40})$/.exec(beforeCaret);
|
|
12185
|
+
mentionStart.value = match ? caret - match[1].length - 1 : null;
|
|
12186
|
+
mentionQuery.value = match?.[1] ?? "";
|
|
12187
|
+
highlightedMentionIndex.value = 0;
|
|
12188
|
+
};
|
|
12189
|
+
const onInput = (event) => {
|
|
12190
|
+
currentCommentMentions.value = currentCommentMentions.value.filter((user) => commentDraft.value.includes(`@${displayName(user)}`));
|
|
12191
|
+
updateMentionQuery(event.target.selectionStart ?? commentDraft.value.length);
|
|
12192
|
+
syncInputHeight();
|
|
12193
|
+
};
|
|
12194
|
+
const selectMention = (user) => {
|
|
12195
|
+
if (mentionStart.value == null) return;
|
|
12196
|
+
const start = mentionStart.value;
|
|
12197
|
+
const caret = inputRef.value?.selectionStart ?? commentDraft.value.length;
|
|
12198
|
+
const token = `@${displayName(user)}`;
|
|
12199
|
+
const identity = mentionIdentity(user);
|
|
12200
|
+
commentDraft.value = `${commentDraft.value.slice(0, start)}${token}${commentDraft.value.slice(caret)}`;
|
|
12201
|
+
if (!currentCommentMentions.value.some((selected) => userKey(selected) === userKey(identity))) currentCommentMentions.value = [...currentCommentMentions.value, identity];
|
|
12202
|
+
mentionStart.value = null;
|
|
12203
|
+
mentionQuery.value = "";
|
|
12204
|
+
nextTick(() => {
|
|
12205
|
+
const nextCaret = start + token.length;
|
|
12206
|
+
inputRef.value?.focus();
|
|
12207
|
+
inputRef.value?.setSelectionRange(nextCaret, nextCaret);
|
|
12208
|
+
syncInputHeight();
|
|
12209
|
+
});
|
|
12210
|
+
};
|
|
12211
|
+
const onKeydown = (event) => {
|
|
12212
|
+
if (!mentionListOpen.value) return;
|
|
12213
|
+
if (event.key === "ArrowDown" || event.key === "ArrowUp") {
|
|
12214
|
+
event.preventDefault();
|
|
12215
|
+
event.stopPropagation();
|
|
12216
|
+
const direction = event.key === "ArrowDown" ? 1 : -1;
|
|
12217
|
+
highlightedMentionIndex.value = (highlightedMentionIndex.value + direction + mentionSuggestions.value.length) % mentionSuggestions.value.length;
|
|
12218
|
+
return;
|
|
12219
|
+
}
|
|
12220
|
+
if (event.key === "Enter") {
|
|
12221
|
+
event.preventDefault();
|
|
12222
|
+
event.stopPropagation();
|
|
12223
|
+
const user = mentionSuggestions.value[highlightedMentionIndex.value];
|
|
12224
|
+
if (user) selectMention(user);
|
|
12225
|
+
return;
|
|
12226
|
+
}
|
|
12227
|
+
if (event.key === "Escape") {
|
|
12228
|
+
event.preventDefault();
|
|
12229
|
+
event.stopPropagation();
|
|
12230
|
+
mentionStart.value = null;
|
|
12231
|
+
}
|
|
12232
|
+
};
|
|
12075
12233
|
onMounted(scheduleInputHeightSync);
|
|
12076
12234
|
watch(currentCommentText, scheduleInputHeightSync);
|
|
12077
12235
|
__expose({ focus });
|
|
@@ -12081,20 +12239,45 @@ var CommentInput_default = /*#__PURE__*/ _plugin_vue_export_helper_default({
|
|
|
12081
12239
|
config: __props.config,
|
|
12082
12240
|
comment: __props.comment,
|
|
12083
12241
|
"is-pending-input": true
|
|
12084
|
-
}, null, 8, ["config", "comment"])) : createCommentVNode("", true), createElementVNode("div", { class: normalizeClass(["comment-entry", { "sd-input-active": __props.isFocused }]) }, [withDirectives(createElementVNode("textarea", {
|
|
12242
|
+
}, null, 8, ["config", "comment"])) : createCommentVNode("", true), createElementVNode("div", { class: normalizeClass(["comment-entry", { "sd-input-active": __props.isFocused }]) }, [createElementVNode("div", _hoisted_2$21, [withDirectives(createElementVNode("textarea", {
|
|
12085
12243
|
ref_key: "inputRef",
|
|
12086
12244
|
ref: inputRef,
|
|
12245
|
+
"onUpdate:modelValue": _cache[0] || (_cache[0] = ($event) => commentDraft.value = $event),
|
|
12087
12246
|
class: "superdoc-field",
|
|
12247
|
+
role: "combobox",
|
|
12248
|
+
"aria-autocomplete": "list",
|
|
12249
|
+
"aria-expanded": mentionListOpen.value,
|
|
12250
|
+
"aria-controls": mentionListOpen.value ? mentionListId : void 0,
|
|
12251
|
+
"aria-activedescendant": activeMentionOptionId.value,
|
|
12252
|
+
"data-sd-comment-mention-input": "",
|
|
12253
|
+
"data-sd-comment-text": "",
|
|
12088
12254
|
placeholder: "Add a comment",
|
|
12089
|
-
"onUpdate:modelValue": _cache[0] || (_cache[0] = ($event) => commentDraft.value = $event),
|
|
12090
12255
|
rows: "1",
|
|
12091
|
-
onInput
|
|
12256
|
+
onInput,
|
|
12257
|
+
onKeydown,
|
|
12092
12258
|
onFocus: _cache[1] || (_cache[1] = ($event) => handleFocusChange(true)),
|
|
12093
12259
|
onBlur: _cache[2] || (_cache[2] = ($event) => handleFocusChange(false))
|
|
12094
|
-
}, null,
|
|
12260
|
+
}, null, 40, _hoisted_3$17), [[vModelText, commentDraft.value]]), mentionListOpen.value ? (openBlock(), createElementBlock("div", {
|
|
12261
|
+
key: 0,
|
|
12262
|
+
id: mentionListId,
|
|
12263
|
+
class: "comment-mention-list",
|
|
12264
|
+
role: "listbox",
|
|
12265
|
+
"data-sd-comment-mention-list": ""
|
|
12266
|
+
}, [(openBlock(true), createElementBlock(Fragment, null, renderList(mentionSuggestions.value, (user, index) => {
|
|
12267
|
+
return openBlock(), createElementBlock("button", {
|
|
12268
|
+
id: `${mentionListId}-${userKey(user)}`,
|
|
12269
|
+
key: userKey(user),
|
|
12270
|
+
type: "button",
|
|
12271
|
+
class: normalizeClass(["comment-mention-option", { "comment-mention-option--active": index === highlightedMentionIndex.value }]),
|
|
12272
|
+
role: "option",
|
|
12273
|
+
"aria-selected": index === highlightedMentionIndex.value,
|
|
12274
|
+
"data-sd-comment-mention-option": userKey(user),
|
|
12275
|
+
onMousedown: withModifiers(($event) => selectMention(user), ["prevent"])
|
|
12276
|
+
}, [createElementVNode("span", _hoisted_5$7, toDisplayString(displayName(user)), 1), user.email ? (openBlock(), createElementBlock("span", _hoisted_6$6, toDisplayString(user.email), 1)) : createCommentVNode("", true)], 42, _hoisted_4$10);
|
|
12277
|
+
}), 128))])) : createCommentVNode("", true)])], 2)]);
|
|
12095
12278
|
};
|
|
12096
12279
|
}
|
|
12097
|
-
}, [["__scopeId", "data-v-
|
|
12280
|
+
}, [["__scopeId", "data-v-87953125"]]);
|
|
12098
12281
|
//#endregion
|
|
12099
12282
|
//#region src/components/CommentsLayer/CommentDialog.vue
|
|
12100
12283
|
var _hoisted_1$26 = [
|
|
@@ -12249,7 +12432,7 @@ var CommentDialog_default = /*#__PURE__*/ _plugin_vue_export_helper_default({
|
|
|
12249
12432
|
const superdocStore = useSuperdocStore();
|
|
12250
12433
|
const commentsStore = useCommentsStore();
|
|
12251
12434
|
const { addComment, cancelComment, deleteComment, getCommentAliasIds, removePendingComment, getCommentDocumentId, requestInstantSidebarAlignment, resolveCommentPositionEntry, clearInstantSidebarAlignment, setActiveFloatingCommentInstance } = commentsStore;
|
|
12252
|
-
const { suppressInternalExternal, getConfig, activeComment, activeFloatingCommentInstanceId, floatingCommentsOffset, pendingComment, currentCommentText, isDebugging, editingCommentId, editorCommentPositions, isCommentHighlighted } = storeToRefs(commentsStore);
|
|
12435
|
+
const { suppressInternalExternal, getConfig, activeComment, activeFloatingCommentInstanceId, floatingCommentsOffset, pendingComment, currentCommentText, currentCommentMentions, isDebugging, editingCommentId, editorCommentPositions, isCommentHighlighted } = storeToRefs(commentsStore);
|
|
12253
12436
|
const isInternal = ref(true);
|
|
12254
12437
|
const commentInput = ref(null);
|
|
12255
12438
|
const editCommentInputs = ref(/* @__PURE__ */ new Map());
|
|
@@ -12493,6 +12676,7 @@ var CommentDialog_default = /*#__PURE__*/ _plugin_vue_export_helper_default({
|
|
|
12493
12676
|
if (!active) {
|
|
12494
12677
|
if (isReplying.value || isEditingCommentInThisThread()) {
|
|
12495
12678
|
currentCommentText.value = "";
|
|
12679
|
+
currentCommentMentions.value = [];
|
|
12496
12680
|
editingCommentId.value = null;
|
|
12497
12681
|
}
|
|
12498
12682
|
textExpanded.value = false;
|
|
@@ -12673,7 +12857,8 @@ var CommentDialog_default = /*#__PURE__*/ _plugin_vue_export_helper_default({
|
|
|
12673
12857
|
const outcome = await commentsStore.replyCommentV2({
|
|
12674
12858
|
superdoc: proxy.$superdoc,
|
|
12675
12859
|
parentCommentId,
|
|
12676
|
-
text: currentCommentText.value
|
|
12860
|
+
text: currentCommentText.value,
|
|
12861
|
+
...currentCommentMentions.value.length ? { mentions: currentCommentMentions.value } : {}
|
|
12677
12862
|
});
|
|
12678
12863
|
if (!outcome?.ok) {
|
|
12679
12864
|
nextTick(() => emit("resize"));
|
|
@@ -12681,6 +12866,7 @@ var CommentDialog_default = /*#__PURE__*/ _plugin_vue_export_helper_default({
|
|
|
12681
12866
|
}
|
|
12682
12867
|
isReplying.value = false;
|
|
12683
12868
|
currentCommentText.value = "";
|
|
12869
|
+
currentCommentMentions.value = [];
|
|
12684
12870
|
nextTick(() => emit("resize"));
|
|
12685
12871
|
return outcome;
|
|
12686
12872
|
} finally {
|
|
@@ -12952,6 +13138,7 @@ var CommentDialog_default = /*#__PURE__*/ _plugin_vue_export_helper_default({
|
|
|
12952
13138
|
switch (value) {
|
|
12953
13139
|
case "edit":
|
|
12954
13140
|
currentCommentText.value = comment?.commentText?.value ?? comment?.commentText ?? "";
|
|
13141
|
+
currentCommentMentions.value = Array.isArray(comment?.mentions) ? [...comment.mentions] : [];
|
|
12955
13142
|
activeComment.value = props.comment.commentId;
|
|
12956
13143
|
if (props.floatingInstanceId) setActiveFloatingCommentInstance(props.floatingInstanceId);
|
|
12957
13144
|
editingCommentId.value = comment.commentId;
|
|
@@ -13011,7 +13198,7 @@ var CommentDialog_default = /*#__PURE__*/ _plugin_vue_export_helper_default({
|
|
|
13011
13198
|
};
|
|
13012
13199
|
const usersFiltered = computed(() => {
|
|
13013
13200
|
const users = proxy.$superdoc.users;
|
|
13014
|
-
if (props.comment.isInternal === true) return users.filter((user) => user.access?.role === "internal");
|
|
13201
|
+
if (props.comment.isInternal === true) return users.filter((user) => user.access === "internal" || user.access?.role === "internal");
|
|
13015
13202
|
return users;
|
|
13016
13203
|
});
|
|
13017
13204
|
onMounted(() => {
|
|
@@ -13202,15 +13389,11 @@ var CommentDialog_default = /*#__PURE__*/ _plugin_vue_export_helper_default({
|
|
|
13202
13389
|
}, null, 10, _hoisted_36)) : unref(isDebugging) && !isEditingThisComment.value(comment) ? (openBlock(), createElementBlock("div", _hoisted_37, toDisplayString(unref(editorCommentPositions)[comment.importedId !== void 0 ? comment.importedId : comment.commentId]?.bounds), 1)) : (openBlock(), createElementBlock("div", _hoisted_38, [createElementVNode("div", _hoisted_39, [createVNode(CommentInput_default, {
|
|
13203
13390
|
ref_for: true,
|
|
13204
13391
|
ref: setEditCommentInputRef(comment.commentId),
|
|
13205
|
-
users:
|
|
13392
|
+
users: [],
|
|
13206
13393
|
config: unref(getConfig),
|
|
13207
13394
|
"include-header": false,
|
|
13208
13395
|
comment
|
|
13209
|
-
}, null, 8, [
|
|
13210
|
-
"users",
|
|
13211
|
-
"config",
|
|
13212
|
-
"comment"
|
|
13213
|
-
])]), createElementVNode("div", _hoisted_40, [createElementVNode("button", {
|
|
13396
|
+
}, null, 8, ["config", "comment"])]), createElementVNode("div", _hoisted_40, [createElementVNode("button", {
|
|
13214
13397
|
class: "sd-button reply-btn-cancel",
|
|
13215
13398
|
onClick: withModifiers(($event) => handleCancel(comment), ["stop", "prevent"])
|
|
13216
13399
|
}, "Cancel", 8, _hoisted_41), createElementVNode("button", {
|
|
@@ -13278,7 +13461,7 @@ var CommentDialog_default = /*#__PURE__*/ _plugin_vue_export_helper_default({
|
|
|
13278
13461
|
], 64))], 14, _hoisted_1$26)), [[_directive_click_outside, handleClickOutside]]);
|
|
13279
13462
|
};
|
|
13280
13463
|
}
|
|
13281
|
-
}, [["__scopeId", "data-v-
|
|
13464
|
+
}, [["__scopeId", "data-v-f4c743f2"]]);
|
|
13282
13465
|
//#endregion
|
|
13283
13466
|
//#region src/components/CommentsLayer/commentsList/ReviewDirectoryListItem.vue
|
|
13284
13467
|
var _hoisted_1$25 = [
|
|
@@ -21590,6 +21773,16 @@ var SuperDoc_default = /*#__PURE__*/ _plugin_vue_export_helper_default({
|
|
|
21590
21773
|
const onV2LinkClick = (payload) => {
|
|
21591
21774
|
linkPopover.handleLinkClick(payload);
|
|
21592
21775
|
};
|
|
21776
|
+
const onV2CommentCreated = async (payload) => {
|
|
21777
|
+
try {
|
|
21778
|
+
await commentsStore.announceV2CommentCreated?.({
|
|
21779
|
+
superdoc: proxy.$superdoc,
|
|
21780
|
+
commentId: payload?.commentId
|
|
21781
|
+
});
|
|
21782
|
+
} catch (err) {
|
|
21783
|
+
console.warn("[SuperDoc][v2] context-menu comment reconciliation failed", err);
|
|
21784
|
+
}
|
|
21785
|
+
};
|
|
21593
21786
|
const recollectV2GeometryIfActive = (options = void 0) => {
|
|
21594
21787
|
if (!isV2Mode.value) return;
|
|
21595
21788
|
if (!v2GeometryPublisher.getLastPayload()) return;
|
|
@@ -22692,6 +22885,7 @@ var SuperDoc_default = /*#__PURE__*/ _plugin_vue_export_helper_default({
|
|
|
22692
22885
|
onV2SelectionChanged,
|
|
22693
22886
|
onV2HostEvent: (event) => onV2HostEvent(doc, event),
|
|
22694
22887
|
onV2LinkClick,
|
|
22888
|
+
onV2CommentCreated,
|
|
22695
22889
|
onV2PageMetrics
|
|
22696
22890
|
}, null, 8, [
|
|
22697
22891
|
"file-source",
|
|
@@ -22756,7 +22950,7 @@ var SuperDoc_default = /*#__PURE__*/ _plugin_vue_export_helper_default({
|
|
|
22756
22950
|
], 38);
|
|
22757
22951
|
};
|
|
22758
22952
|
}
|
|
22759
|
-
}, [["__scopeId", "data-v-
|
|
22953
|
+
}, [["__scopeId", "data-v-85324013"]]);
|
|
22760
22954
|
//#endregion
|
|
22761
22955
|
//#region src/core/create-app.js
|
|
22762
22956
|
var PINIA_DEVTOOLS_SETUP_EVENT = "devtools-plugin:setup";
|
|
@@ -43216,7 +43410,7 @@ var SuperDoc = class extends import_eventemitter3.default {
|
|
|
43216
43410
|
this.config.colors = shuffleArray(this.config.colors);
|
|
43217
43411
|
this.userColorMap = /* @__PURE__ */ new Map();
|
|
43218
43412
|
this.colorIndex = 0;
|
|
43219
|
-
this.version = "2.6.0-next.
|
|
43413
|
+
this.version = "2.6.0-next.8";
|
|
43220
43414
|
this.#log("🦋 [superdoc] Using SuperDoc version:", this.version);
|
|
43221
43415
|
this.superdocId = config.superdocId || v4();
|
|
43222
43416
|
this.colors = this.config.colors ?? [];
|