@tldraw/commenting 0.0.0-bootstrap → 5.3.0-internal.5f14a24c179e
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/commenting.css +280 -151
- package/dist-cjs/canvas/comment-body.js +1 -1
- package/dist-cjs/canvas/comment-body.js.map +2 -2
- package/dist-cjs/canvas/comment-drafts.js +54 -0
- package/dist-cjs/canvas/comment-drafts.js.map +7 -0
- package/dist-cjs/canvas/comment-render.js +2 -0
- package/dist-cjs/canvas/comment-render.js.map +2 -2
- package/dist-cjs/canvas/comment-tool.js +55 -11
- package/dist-cjs/canvas/comment-tool.js.map +2 -2
- package/dist-cjs/canvas/comments-filter-menu.js +55 -56
- package/dist-cjs/canvas/comments-filter-menu.js.map +2 -2
- package/dist-cjs/canvas/comments-overflow-menu.js +21 -19
- package/dist-cjs/canvas/comments-overflow-menu.js.map +2 -2
- package/dist-cjs/canvas/comments-overlay.js +271 -109
- package/dist-cjs/canvas/comments-overlay.js.map +2 -2
- package/dist-cjs/canvas/comments-sidebar.js +12 -18
- package/dist-cjs/canvas/comments-sidebar.js.map +2 -2
- package/dist-cjs/canvas/comments-visibility-toggle.js +67 -0
- package/dist-cjs/canvas/comments-visibility-toggle.js.map +7 -0
- package/dist-cjs/canvas/sidebar-filters.js +2 -2
- package/dist-cjs/canvas/sidebar-filters.js.map +2 -2
- package/dist-cjs/canvas/state.js +11 -0
- package/dist-cjs/canvas/state.js.map +2 -2
- package/dist-cjs/canvas/thread-state.js +8 -1
- package/dist-cjs/canvas/thread-state.js.map +2 -2
- package/dist-cjs/clustering/runtime.js +119 -7
- package/dist-cjs/clustering/runtime.js.map +2 -2
- package/dist-cjs/index.d.ts +100 -39
- package/dist-cjs/index.js +7 -1
- package/dist-cjs/index.js.map +2 -2
- package/dist-cjs/ui/avatar.js +14 -6
- package/dist-cjs/ui/avatar.js.map +2 -2
- package/dist-cjs/ui/byline.js +4 -4
- package/dist-cjs/ui/byline.js.map +2 -2
- package/dist-cjs/ui/comment-author.js +17 -0
- package/dist-cjs/ui/comment-author.js.map +7 -0
- package/dist-cjs/ui/comment-card.js +4 -4
- package/dist-cjs/ui/comment-card.js.map +2 -2
- package/dist-cjs/ui/comment-composer.js +92 -29
- package/dist-cjs/ui/comment-composer.js.map +2 -2
- package/dist-cjs/ui/comment-mention.js +1 -1
- package/dist-cjs/ui/comment-mention.js.map +2 -2
- package/dist-cjs/ui/comment-pin.js +23 -3
- package/dist-cjs/ui/comment-pin.js.map +2 -2
- package/dist-cjs/ui/comment-text.js +1 -1
- package/dist-cjs/ui/comment-text.js.map +2 -2
- package/dist-cjs/ui/comment-thread.js +6 -6
- package/dist-cjs/ui/comment-thread.js.map +2 -2
- package/dist-cjs/ui/comments-list.js +12 -12
- package/dist-cjs/ui/comments-list.js.map +2 -2
- package/dist-cjs/ui/count-badge.js +1 -1
- package/dist-cjs/ui/count-badge.js.map +2 -2
- package/dist-cjs/ui/empty-state.js +3 -3
- package/dist-cjs/ui/empty-state.js.map +2 -2
- package/dist-cjs/ui/format-time.js +3 -0
- package/dist-cjs/ui/format-time.js.map +2 -2
- package/dist-cjs/ui/mention-list.js +8 -8
- package/dist-cjs/ui/mention-list.js.map +2 -2
- package/dist-cjs/ui/mention-suggestion.js +3 -3
- package/dist-cjs/ui/mention-suggestion.js.map +2 -2
- package/dist-cjs/ui/mention.js +1 -1
- package/dist-cjs/ui/mention.js.map +2 -2
- package/dist-cjs/ui/reaction.js +11 -4
- package/dist-cjs/ui/reaction.js.map +2 -2
- package/dist-cjs/ui/reactions.js +10 -2
- package/dist-cjs/ui/reactions.js.map +2 -2
- package/dist-cjs/ui/send-button.js +1 -1
- package/dist-cjs/ui/send-button.js.map +2 -2
- package/dist-esm/canvas/comment-body.mjs +1 -1
- package/dist-esm/canvas/comment-body.mjs.map +2 -2
- package/dist-esm/canvas/comment-drafts.mjs +34 -0
- package/dist-esm/canvas/comment-drafts.mjs.map +7 -0
- package/dist-esm/canvas/comment-render.mjs +2 -0
- package/dist-esm/canvas/comment-render.mjs.map +2 -2
- package/dist-esm/canvas/comment-tool.mjs +56 -12
- package/dist-esm/canvas/comment-tool.mjs.map +2 -2
- package/dist-esm/canvas/comments-filter-menu.mjs +55 -56
- package/dist-esm/canvas/comments-filter-menu.mjs.map +2 -2
- package/dist-esm/canvas/comments-overflow-menu.mjs +22 -19
- package/dist-esm/canvas/comments-overflow-menu.mjs.map +2 -2
- package/dist-esm/canvas/comments-overlay.mjs +289 -111
- package/dist-esm/canvas/comments-overlay.mjs.map +2 -2
- package/dist-esm/canvas/comments-sidebar.mjs +15 -21
- package/dist-esm/canvas/comments-sidebar.mjs.map +2 -2
- package/dist-esm/canvas/comments-visibility-toggle.mjs +47 -0
- package/dist-esm/canvas/comments-visibility-toggle.mjs.map +7 -0
- package/dist-esm/canvas/sidebar-filters.mjs +2 -2
- package/dist-esm/canvas/sidebar-filters.mjs.map +2 -2
- package/dist-esm/canvas/state.mjs +11 -0
- package/dist-esm/canvas/state.mjs.map +2 -2
- package/dist-esm/canvas/thread-state.mjs +8 -1
- package/dist-esm/canvas/thread-state.mjs.map +2 -2
- package/dist-esm/clustering/runtime.mjs +119 -7
- package/dist-esm/clustering/runtime.mjs.map +2 -2
- package/dist-esm/index.d.mts +100 -39
- package/dist-esm/index.mjs +11 -1
- package/dist-esm/index.mjs.map +2 -2
- package/dist-esm/ui/avatar.mjs +14 -6
- package/dist-esm/ui/avatar.mjs.map +2 -2
- package/dist-esm/ui/byline.mjs +4 -4
- package/dist-esm/ui/byline.mjs.map +2 -2
- package/dist-esm/ui/comment-author.mjs +1 -0
- package/dist-esm/ui/comment-author.mjs.map +7 -0
- package/dist-esm/ui/comment-card.mjs +4 -4
- package/dist-esm/ui/comment-card.mjs.map +2 -2
- package/dist-esm/ui/comment-composer.mjs +93 -30
- package/dist-esm/ui/comment-composer.mjs.map +2 -2
- package/dist-esm/ui/comment-mention.mjs +1 -1
- package/dist-esm/ui/comment-mention.mjs.map +2 -2
- package/dist-esm/ui/comment-pin.mjs +23 -3
- package/dist-esm/ui/comment-pin.mjs.map +2 -2
- package/dist-esm/ui/comment-text.mjs +1 -1
- package/dist-esm/ui/comment-text.mjs.map +2 -2
- package/dist-esm/ui/comment-thread.mjs +6 -6
- package/dist-esm/ui/comment-thread.mjs.map +2 -2
- package/dist-esm/ui/comments-list.mjs +12 -12
- package/dist-esm/ui/comments-list.mjs.map +2 -2
- package/dist-esm/ui/count-badge.mjs +1 -1
- package/dist-esm/ui/count-badge.mjs.map +2 -2
- package/dist-esm/ui/empty-state.mjs +3 -3
- package/dist-esm/ui/empty-state.mjs.map +2 -2
- package/dist-esm/ui/format-time.mjs +3 -0
- package/dist-esm/ui/format-time.mjs.map +2 -2
- package/dist-esm/ui/mention-list.mjs +8 -8
- package/dist-esm/ui/mention-list.mjs.map +2 -2
- package/dist-esm/ui/mention-suggestion.mjs +3 -3
- package/dist-esm/ui/mention-suggestion.mjs.map +2 -2
- package/dist-esm/ui/mention.mjs +1 -1
- package/dist-esm/ui/mention.mjs.map +2 -2
- package/dist-esm/ui/reaction.mjs +11 -4
- package/dist-esm/ui/reaction.mjs.map +2 -2
- package/dist-esm/ui/reactions.mjs +10 -2
- package/dist-esm/ui/reactions.mjs.map +2 -2
- package/dist-esm/ui/send-button.mjs +1 -1
- package/dist-esm/ui/send-button.mjs.map +2 -2
- package/package.json +3 -3
- package/src/canvas/canvas.css +79 -36
- package/src/canvas/comment-body.tsx +1 -1
- package/src/canvas/comment-drafts.test.ts +55 -0
- package/src/canvas/comment-drafts.ts +46 -0
- package/src/canvas/comment-render.test.ts +1 -1
- package/src/canvas/comment-render.ts +7 -2
- package/src/canvas/comment-tool.tsx +87 -15
- package/src/canvas/comments-filter-menu.tsx +14 -16
- package/src/canvas/comments-overflow-menu.tsx +11 -15
- package/src/canvas/comments-overlay.tsx +399 -141
- package/src/canvas/comments-sidebar.tsx +27 -28
- package/src/canvas/comments-visibility-toggle.tsx +51 -0
- package/src/canvas/sidebar-filters.ts +4 -3
- package/src/canvas/state.ts +22 -0
- package/src/canvas/thread-state.ts +13 -1
- package/src/clustering/runtime.test.ts +183 -7
- package/src/clustering/runtime.ts +164 -15
- package/src/index.ts +6 -0
- package/src/ui/avatar.tsx +15 -11
- package/src/ui/byline.tsx +6 -5
- package/src/ui/comment-author.ts +15 -0
- package/src/ui/comment-card.tsx +6 -5
- package/src/ui/comment-composer.tsx +122 -33
- package/src/ui/comment-mention.ts +2 -2
- package/src/ui/comment-pin.tsx +35 -4
- package/src/ui/comment-text.tsx +1 -1
- package/src/ui/comment-thread.tsx +8 -6
- package/src/ui/comments-list.tsx +19 -14
- package/src/ui/comments.css +201 -115
- package/src/ui/count-badge.tsx +1 -1
- package/src/ui/empty-state.tsx +3 -3
- package/src/ui/format-time.ts +5 -0
- package/src/ui/mention-list.tsx +13 -16
- package/src/ui/mention-suggestion.tsx +3 -3
- package/src/ui/mention.tsx +1 -1
- package/src/ui/reaction.tsx +6 -3
- package/src/ui/reactions.tsx +6 -2
- package/src/ui/send-button.tsx +1 -1
|
@@ -36,6 +36,7 @@ var import_count_badge = require("../ui/count-badge");
|
|
|
36
36
|
var import_mention_suggestion = require("../ui/mention-suggestion");
|
|
37
37
|
var import_cluster_input = require("./cluster-input");
|
|
38
38
|
var import_comment_body = require("./comment-body");
|
|
39
|
+
var import_comment_drafts = require("./comment-drafts");
|
|
39
40
|
var import_comment_render = require("./comment-render");
|
|
40
41
|
var import_comment_store = require("./comment-store");
|
|
41
42
|
var import_hooks = require("./hooks");
|
|
@@ -45,10 +46,26 @@ var import_region_options = require("./region-options");
|
|
|
45
46
|
var import_state = require("./state");
|
|
46
47
|
var import_thread_state = require("./thread-state");
|
|
47
48
|
const stop = (e) => e.stopPropagation();
|
|
49
|
+
const IMPRECISE_PIN_INSET_PX = 20;
|
|
50
|
+
function impreciseShapePinInset(anchor, spot) {
|
|
51
|
+
if (anchor.type !== "shape" || anchor.isPrecise) return null;
|
|
52
|
+
return {
|
|
53
|
+
x: Math.sign(0.5 - spot.x) * IMPRECISE_PIN_INSET_PX,
|
|
54
|
+
y: Math.sign(0.5 - spot.y) * IMPRECISE_PIN_INSET_PX
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
const isCanvasPanGesture = (editor, e) => e.button !== 0 || editor.inputs.keys.has("Space");
|
|
58
|
+
function forwardPointerEventToCanvas(container, e) {
|
|
59
|
+
const cvs = container.querySelector(".tl-canvas");
|
|
60
|
+
if (!cvs) return;
|
|
61
|
+
const newEvent = new PointerEvent(e.type, e.nativeEvent);
|
|
62
|
+
newEvent.isSpecialRedispatchedEvent = true;
|
|
63
|
+
cvs.dispatchEvent(newEvent);
|
|
64
|
+
}
|
|
48
65
|
const initialOf = (name) => ((0, import_tldraw.getFirstCharacter)(name.trim()) || "?").toUpperCase();
|
|
49
66
|
const CLUSTER_FADE_MS = 150;
|
|
50
67
|
const CLUSTER_EXPAND_ZOOM_MS = 450;
|
|
51
|
-
const draftAvatar = /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_comment_pin.CommentPin, { children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
|
|
68
|
+
const draftAvatar = (color) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_comment_pin.CommentPin, { color, children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
|
|
52
69
|
"svg",
|
|
53
70
|
{
|
|
54
71
|
viewBox: "0 0 24 24",
|
|
@@ -66,11 +83,11 @@ const draftAvatar = /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_comment_p
|
|
|
66
83
|
]
|
|
67
84
|
}
|
|
68
85
|
) });
|
|
69
|
-
function toCardProps(comment, props, components) {
|
|
86
|
+
function toCardProps(comment, props, components, resolveName) {
|
|
70
87
|
const Body = components.CommentBody;
|
|
71
|
-
const body = Body ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Body, { comment }) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_comment_body.CommentBody, { richText: comment.body, resolveName
|
|
88
|
+
const body = Body ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Body, { comment }) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_comment_body.CommentBody, { richText: comment.body, resolveName });
|
|
72
89
|
return {
|
|
73
|
-
author: props.
|
|
90
|
+
author: props.resolveAuthor(comment.authorId) ?? import_comment_render.UNKNOWN_COMMENT_AUTHOR,
|
|
74
91
|
body,
|
|
75
92
|
date: new Date(comment.createdAt).toISOString(),
|
|
76
93
|
you: comment.authorId === props.currentUserId,
|
|
@@ -92,24 +109,23 @@ function CanvasCommentsLayer(props) {
|
|
|
92
109
|
);
|
|
93
110
|
(0, import_react.useEffect)(() => (0, import_region_options.setRegionCommentOptions)(editor, regionOptions), [editor, regionOptions]);
|
|
94
111
|
const layerRef = (0, import_react.useRef)(null);
|
|
95
|
-
(0, import_tldraw.usePassThroughWheelEvents)(layerRef);
|
|
96
112
|
(0, import_tldraw.usePassThroughMouseOverEvents)(layerRef);
|
|
97
113
|
const deepLinkHandled = (0, import_react.useRef)(false);
|
|
98
114
|
const threads = (0, import_hooks.useCommentThreads)(editor);
|
|
99
115
|
const pending = (0, import_state.usePendingComment)();
|
|
100
116
|
const openId = (0, import_tldraw.useValue)("open thread id", () => import_state.openThreadId.get(editor), [editor]);
|
|
101
117
|
const impreciseShapeAnchor = props.impreciseShapeAnchor ?? options.impreciseShapeAnchor;
|
|
102
|
-
const [
|
|
118
|
+
const [heldThreadIds, setHeldThreadIds] = (0, import_react.useState)(EMPTY_SET);
|
|
103
119
|
const adoptOnRebuild = (0, import_react.useRef)(false);
|
|
104
120
|
const clusterLeaves = (0, import_tldraw.useValue)(
|
|
105
121
|
"comment cluster leaves",
|
|
106
122
|
() => (0, import_cluster_input.collectClusterLeaves)(
|
|
107
123
|
editor,
|
|
108
|
-
threads.filter((thread) => !
|
|
124
|
+
threads.filter((thread) => !heldThreadIds.has(thread.id)),
|
|
109
125
|
import_state.openThreadId.get(editor),
|
|
110
126
|
impreciseShapeAnchor
|
|
111
127
|
),
|
|
112
|
-
[editor, threads, impreciseShapeAnchor,
|
|
128
|
+
[editor, threads, impreciseShapeAnchor, heldThreadIds]
|
|
113
129
|
);
|
|
114
130
|
const clusterZoomBounds = (0, import_tldraw.useValue)(
|
|
115
131
|
"comment cluster zoom bounds",
|
|
@@ -124,21 +140,41 @@ function CanvasCommentsLayer(props) {
|
|
|
124
140
|
}, [clusterLeaves, clusterZoomBounds, editor]);
|
|
125
141
|
const [renderedModel, setRenderedModel] = (0, import_react.useState)(latestModel);
|
|
126
142
|
let clusterModel = renderedModel;
|
|
127
|
-
|
|
143
|
+
const pageId = (0, import_tldraw.useValue)("comment cluster page", () => editor.getCurrentPageId(), [editor]);
|
|
144
|
+
const pageRef = (0, import_react.useRef)(pageId);
|
|
145
|
+
if (pageRef.current !== pageId) {
|
|
146
|
+
pageRef.current = pageId;
|
|
147
|
+
adoptOnRebuild.current = false;
|
|
148
|
+
latestModel.runtime.seed(editor.getZoomLevel());
|
|
149
|
+
if (heldThreadIds.size > 0) setHeldThreadIds(EMPTY_SET);
|
|
150
|
+
setRenderedModel(latestModel);
|
|
151
|
+
clusterModel = latestModel;
|
|
152
|
+
}
|
|
153
|
+
const rejoinPending = heldThreadIds.size === 0 && adoptOnRebuild.current;
|
|
154
|
+
if (renderedModel !== latestModel && rejoinPending) {
|
|
128
155
|
adoptOnRebuild.current = false;
|
|
129
156
|
latestModel.runtime.seedFrom(editor.getZoomLevel(), renderedModel.runtime.getVisible());
|
|
130
157
|
setRenderedModel(latestModel);
|
|
131
158
|
clusterModel = latestModel;
|
|
159
|
+
} else if (heldThreadIds.size === 0 && renderedModel === latestModel) {
|
|
160
|
+
adoptOnRebuild.current = false;
|
|
132
161
|
}
|
|
133
162
|
const newlyMovedIds = findMovedClusteredLeafIds(clusterModel, latestModel);
|
|
134
163
|
if (newlyMovedIds.length > 0) {
|
|
135
|
-
|
|
136
|
-
const next = new Set(movedThreadIds);
|
|
164
|
+
const next = new Set(heldThreadIds);
|
|
137
165
|
for (const id of newlyMovedIds) next.add(id);
|
|
138
|
-
|
|
166
|
+
setHeldThreadIds(next);
|
|
167
|
+
}
|
|
168
|
+
{
|
|
169
|
+
const latestLeafIds = new Set(latestModel.table.leaves.map((leaf) => leaf.id));
|
|
170
|
+
for (const leaf of clusterModel.table.leaves) {
|
|
171
|
+
if (!latestLeafIds.has(leaf.id)) {
|
|
172
|
+
clusterModel.runtime.detachLeaf(leaf.id);
|
|
173
|
+
}
|
|
174
|
+
}
|
|
139
175
|
}
|
|
140
176
|
(0, import_react.useEffect)(() => {
|
|
141
|
-
if (
|
|
177
|
+
if (heldThreadIds.size === 0) return;
|
|
142
178
|
let lastZoom = editor.getZoomLevel();
|
|
143
179
|
return (0, import_tldraw.react)("rejoin moved comment pins on zoom out", () => {
|
|
144
180
|
const zoom = editor.getZoomLevel();
|
|
@@ -146,9 +182,9 @@ function CanvasCommentsLayer(props) {
|
|
|
146
182
|
lastZoom = zoom;
|
|
147
183
|
if (zoom >= prevZoom) return;
|
|
148
184
|
adoptOnRebuild.current = true;
|
|
149
|
-
|
|
185
|
+
setHeldThreadIds(EMPTY_SET);
|
|
150
186
|
});
|
|
151
|
-
}, [
|
|
187
|
+
}, [heldThreadIds, editor]);
|
|
152
188
|
(0, import_react.useEffect)(() => {
|
|
153
189
|
if (clusterModel === latestModel) return;
|
|
154
190
|
let lastZoom = editor.getZoomLevel();
|
|
@@ -161,31 +197,31 @@ function CanvasCommentsLayer(props) {
|
|
|
161
197
|
setRenderedModel(latestModel);
|
|
162
198
|
});
|
|
163
199
|
}, [clusterModel, latestModel, editor]);
|
|
200
|
+
const partitionVersion = clusterModel.runtime.version;
|
|
164
201
|
const orphanThreads = (0, import_react.useMemo)(() => {
|
|
165
202
|
if (clusterModel === latestModel) return [];
|
|
166
|
-
const
|
|
203
|
+
const displayed = /* @__PURE__ */ new Set();
|
|
204
|
+
for (const node of clusterModel.runtime.getVisible().values()) {
|
|
205
|
+
for (const member of node.members) displayed.add(member);
|
|
206
|
+
}
|
|
167
207
|
const latestIds = new Set(latestModel.table.leaves.map((leaf) => leaf.id));
|
|
168
|
-
return threads.filter((thread) => latestIds.has(thread.id) && !
|
|
169
|
-
}, [clusterModel, latestModel, threads]);
|
|
170
|
-
const
|
|
171
|
-
() => threads.filter((thread) =>
|
|
172
|
-
[threads,
|
|
208
|
+
return threads.filter((thread) => latestIds.has(thread.id) && !displayed.has(thread.id));
|
|
209
|
+
}, [clusterModel, latestModel, threads, partitionVersion]);
|
|
210
|
+
const heldThreads = (0, import_react.useMemo)(
|
|
211
|
+
() => threads.filter((thread) => heldThreadIds.has(thread.id) && thread.id !== openId),
|
|
212
|
+
[threads, heldThreadIds, openId]
|
|
173
213
|
);
|
|
174
|
-
|
|
175
|
-
"comment cluster
|
|
214
|
+
(0, import_tldraw.useValue)(
|
|
215
|
+
"comment cluster version",
|
|
176
216
|
() => {
|
|
177
217
|
clusterModel.runtime.onCamera(editor.getZoomLevel());
|
|
178
|
-
return clusterModel.runtime.
|
|
218
|
+
return clusterModel.runtime.version;
|
|
179
219
|
},
|
|
180
220
|
[clusterModel, editor]
|
|
181
221
|
);
|
|
182
222
|
const visibleNodes = (0, import_react.useMemo)(() => {
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
`[comments] cluster cursor k=${clusterCursor} \u2192 re-rendering ${nodes.length} visible nodes`
|
|
186
|
-
);
|
|
187
|
-
return nodes;
|
|
188
|
-
}, [clusterModel, clusterCursor]);
|
|
223
|
+
return Array.from(clusterModel.runtime.getVisible().values());
|
|
224
|
+
}, [clusterModel, partitionVersion]);
|
|
189
225
|
const fadeNodes = useFadeVisibleNodes(visibleNodes, clusterModel);
|
|
190
226
|
const threadsById = (0, import_react.useMemo)(
|
|
191
227
|
() => new Map(threads.map((thread) => [thread.id, thread])),
|
|
@@ -244,7 +280,7 @@ function CanvasCommentsLayer(props) {
|
|
|
244
280
|
if (e.key !== "Escape" || import_state.openThreadId.get(editor) === null) return;
|
|
245
281
|
if ((0, import_mention_suggestion.isMentionPickerOpen)()) return;
|
|
246
282
|
const target = e.target;
|
|
247
|
-
if (target && target.closest(".cmt-editing")) return;
|
|
283
|
+
if (target && target.closest(".tlui-cmt-editing")) return;
|
|
248
284
|
import_state.openThreadId.set(editor, null);
|
|
249
285
|
e.preventDefault();
|
|
250
286
|
e.stopPropagation();
|
|
@@ -265,7 +301,7 @@ function CanvasCommentsLayer(props) {
|
|
|
265
301
|
}, [editor]);
|
|
266
302
|
if (hidden) return null;
|
|
267
303
|
return (0, import_react_dom.createPortal)(
|
|
268
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { ref: layerRef, className: "cmt-canvas-layer", children: [
|
|
304
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { ref: layerRef, className: "tlui-cmt-canvas-layer", children: [
|
|
269
305
|
options.enableClustering ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
|
|
270
306
|
fadeNodes.map(({ node, phase }) => {
|
|
271
307
|
let content;
|
|
@@ -296,7 +332,7 @@ function CanvasCommentsLayer(props) {
|
|
|
296
332
|
},
|
|
297
333
|
thread.id
|
|
298
334
|
)),
|
|
299
|
-
|
|
335
|
+
heldThreads.map((thread) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
300
336
|
ThreadPin,
|
|
301
337
|
{
|
|
302
338
|
editor,
|
|
@@ -405,7 +441,7 @@ function cancelClusterFadeFrame(frame) {
|
|
|
405
441
|
else window.clearTimeout(frame);
|
|
406
442
|
}
|
|
407
443
|
function clusterFadeClassName(phase) {
|
|
408
|
-
return `cmt-cluster-fade cmt-cluster-fade--${phase}`;
|
|
444
|
+
return `tlui-cmt-cluster-fade tlui-cmt-cluster-fade--${phase}`;
|
|
409
445
|
}
|
|
410
446
|
function findMovedClusteredLeafIds(rendered, latest) {
|
|
411
447
|
if (rendered.table === latest.table) return [];
|
|
@@ -422,11 +458,6 @@ function findMovedClusteredLeafIds(rendered, latest) {
|
|
|
422
458
|
}
|
|
423
459
|
return moved;
|
|
424
460
|
}
|
|
425
|
-
function hasRemovedLeaves(rendered, latest) {
|
|
426
|
-
if (rendered.leaves.length === 0) return false;
|
|
427
|
-
const latestIds = new Set(latest.leaves.map((leaf) => leaf.id));
|
|
428
|
-
return rendered.leaves.some((leaf) => !latestIds.has(leaf.id));
|
|
429
|
-
}
|
|
430
461
|
function getClusterZoomBounds(editor) {
|
|
431
462
|
const cameraOptions = editor.getCameraOptions();
|
|
432
463
|
const baseZoom = cameraOptions.constraints ? editor.getBaseZoom() : 1;
|
|
@@ -478,6 +509,9 @@ const ClusterBadge = (0, import_react.memo)(function ClusterBadge2({
|
|
|
478
509
|
node,
|
|
479
510
|
onExpand
|
|
480
511
|
}) {
|
|
512
|
+
const container = (0, import_tldraw.useContainer)();
|
|
513
|
+
const badgeRef = (0, import_react.useRef)(null);
|
|
514
|
+
(0, import_tldraw.usePassThroughWheelEvents)(badgeRef);
|
|
481
515
|
const point = (0, import_tldraw.useValue)(
|
|
482
516
|
"cluster badge point",
|
|
483
517
|
() => {
|
|
@@ -491,9 +525,16 @@ const ClusterBadge = (0, import_react.memo)(function ClusterBadge2({
|
|
|
491
525
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
492
526
|
"div",
|
|
493
527
|
{
|
|
494
|
-
|
|
528
|
+
ref: badgeRef,
|
|
529
|
+
className: "tlui-cmt-canvas-cluster",
|
|
495
530
|
style: { left: point.x, top: point.y },
|
|
496
|
-
onPointerDown:
|
|
531
|
+
onPointerDown: (e) => {
|
|
532
|
+
if (isCanvasPanGesture(editor, e)) {
|
|
533
|
+
forwardPointerEventToCanvas(container, e);
|
|
534
|
+
return;
|
|
535
|
+
}
|
|
536
|
+
e.stopPropagation();
|
|
537
|
+
},
|
|
497
538
|
onClick: (e) => {
|
|
498
539
|
e.stopPropagation();
|
|
499
540
|
onExpand(node);
|
|
@@ -516,7 +557,19 @@ function ThreadPopover({
|
|
|
516
557
|
(0, import_tldraw.usePassThroughWheelEvents)(ref);
|
|
517
558
|
(0, import_tldraw.usePassThroughMouseOverEvents)(ref);
|
|
518
559
|
return (0, import_react_dom.createPortal)(
|
|
519
|
-
|
|
560
|
+
// contextmenu also stops here: portals bubble React events to the canvas's context-menu
|
|
561
|
+
// trigger (the layer mounts inside it), which would open the canvas menu over this panel.
|
|
562
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
563
|
+
"div",
|
|
564
|
+
{
|
|
565
|
+
ref,
|
|
566
|
+
className: "tlui-cmt-canvas-popover",
|
|
567
|
+
style,
|
|
568
|
+
onPointerDown: stop,
|
|
569
|
+
onContextMenu: stop,
|
|
570
|
+
children
|
|
571
|
+
}
|
|
572
|
+
),
|
|
520
573
|
container
|
|
521
574
|
);
|
|
522
575
|
}
|
|
@@ -537,12 +590,19 @@ function RegionBox({
|
|
|
537
590
|
[editor, box.x, box.y, box.w, box.h]
|
|
538
591
|
);
|
|
539
592
|
const grabRef = (0, import_react.useRef)(null);
|
|
593
|
+
const container = (0, import_tldraw.useContainer)();
|
|
594
|
+
const boxRef = (0, import_react.useRef)(null);
|
|
595
|
+
(0, import_tldraw.usePassThroughWheelEvents)(boxRef);
|
|
540
596
|
const translated = (e) => {
|
|
541
597
|
const g = grabRef.current;
|
|
542
598
|
const p = editor.screenToPage({ x: e.clientX, y: e.clientY });
|
|
543
599
|
return { ...g.box, x: g.box.x + (p.x - g.page.x), y: g.box.y + (p.y - g.page.y) };
|
|
544
600
|
};
|
|
545
601
|
const startMove = (e) => {
|
|
602
|
+
if (isCanvasPanGesture(editor, e)) {
|
|
603
|
+
forwardPointerEventToCanvas(container, e);
|
|
604
|
+
return;
|
|
605
|
+
}
|
|
546
606
|
e.stopPropagation();
|
|
547
607
|
grabRef.current = { page: editor.screenToPage({ x: e.clientX, y: e.clientY }), box };
|
|
548
608
|
e.currentTarget.setPointerCapture(e.pointerId);
|
|
@@ -561,7 +621,8 @@ function RegionBox({
|
|
|
561
621
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
562
622
|
"div",
|
|
563
623
|
{
|
|
564
|
-
|
|
624
|
+
ref: boxRef,
|
|
625
|
+
className: movable ? "tlui-cmt-canvas-region tlui-cmt-canvas-region--movable" : "tlui-cmt-canvas-region",
|
|
565
626
|
style: rect,
|
|
566
627
|
onPointerDown: movable ? startMove : void 0,
|
|
567
628
|
onPointerMove: movable ? onMove : void 0,
|
|
@@ -635,7 +696,7 @@ function RegionResizeHandles({
|
|
|
635
696
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_jsx_runtime.Fragment, { children: points.map((h) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
636
697
|
"div",
|
|
637
698
|
{
|
|
638
|
-
className: "cmt-canvas-region-handle",
|
|
699
|
+
className: "tlui-cmt-canvas-region-handle",
|
|
639
700
|
style: { left: h.left, top: h.top, cursor: h.cursor },
|
|
640
701
|
onPointerDown: startResize,
|
|
641
702
|
onPointerMove: onResize(h),
|
|
@@ -652,13 +713,15 @@ const ThreadPin = (0, import_react.memo)(function ThreadPin2({
|
|
|
652
713
|
}) {
|
|
653
714
|
const {
|
|
654
715
|
currentUserId,
|
|
655
|
-
|
|
716
|
+
resolveAuthor,
|
|
656
717
|
onPostComment,
|
|
657
718
|
isCommentUnread,
|
|
658
719
|
onCommentRead,
|
|
659
720
|
getMentionSuggestions,
|
|
660
721
|
renderMentionSuggestion
|
|
661
722
|
} = props;
|
|
723
|
+
const resolveName = (0, import_react.useCallback)((id) => resolveAuthor(id)?.name, [resolveAuthor]);
|
|
724
|
+
const me = currentUserId ? resolveAuthor(currentUserId) : void 0;
|
|
662
725
|
const options = (0, import_options.useCommentingOptions)();
|
|
663
726
|
const impreciseShapeAnchor = props.impreciseShapeAnchor ?? options.impreciseShapeAnchor;
|
|
664
727
|
const container = (0, import_tldraw.useContainer)();
|
|
@@ -668,7 +731,9 @@ const ThreadPin = (0, import_react.memo)(function ThreadPin2({
|
|
|
668
731
|
editor,
|
|
669
732
|
thread.id
|
|
670
733
|
]);
|
|
671
|
-
const [reply, setReply] = (0, import_react.useState)(
|
|
734
|
+
const [reply, setReply] = (0, import_react.useState)(
|
|
735
|
+
() => (0, import_comment_drafts.getCommentDraft)((0, import_comment_drafts.replyDraftSlot)(thread.id)) ?? import_comment_extensions.EMPTY_COMMENT
|
|
736
|
+
);
|
|
672
737
|
const [editingId, setEditingId] = (0, import_react.useState)(null);
|
|
673
738
|
const [editText, setEditText] = (0, import_react.useState)(import_comment_extensions.EMPTY_COMMENT);
|
|
674
739
|
const [dragPagePoint, setDragPagePoint] = (0, import_react.useState)(null);
|
|
@@ -687,24 +752,24 @@ const ThreadPin = (0, import_react.memo)(function ThreadPin2({
|
|
|
687
752
|
[editor, thread.anchor, thread.pageId]
|
|
688
753
|
);
|
|
689
754
|
const revealed = open || resizeBounds != null || regionOptions.reveal === "pointer" && pointerInRegion || regionOptions.reveal === "pin-hover" && pinHovered;
|
|
755
|
+
const pinCorner = thread.anchor.type === "region" ? (0, import_thread_state.regionAnchorPinCorner)(editor, thread.anchor) : regionOptions.pinCorner;
|
|
690
756
|
const resizeHandles = (0, import_react.useMemo)(
|
|
691
|
-
() => regionOptions.resize === "edges" ? REGION_EDGES : REGION_CORNERS.filter(
|
|
692
|
-
|
|
693
|
-
),
|
|
694
|
-
[regionOptions.resize, regionOptions.pinCorner]
|
|
757
|
+
() => regionOptions.resize === "edges" ? REGION_EDGES : REGION_CORNERS.filter((c) => c.x !== pinCorner.x || c.y !== pinCorner.y),
|
|
758
|
+
[regionOptions.resize, pinCorner]
|
|
695
759
|
);
|
|
696
760
|
const dragRef = (0, import_react.useRef)(null);
|
|
697
761
|
const markerRef = (0, import_react.useRef)(null);
|
|
762
|
+
(0, import_tldraw.usePassThroughWheelEvents)(markerRef);
|
|
698
763
|
(0, import_react.useEffect)(() => {
|
|
699
764
|
if (!open) return;
|
|
700
765
|
const onPointerDown = (e) => {
|
|
701
766
|
const target = e.target;
|
|
702
767
|
if (!target) return;
|
|
703
|
-
if (target.closest(".cmt-canvas-popover")) return;
|
|
768
|
+
if (target.closest(".tlui-cmt-canvas-popover")) return;
|
|
704
769
|
const marker = markerRef.current;
|
|
705
770
|
if (marker && marker.contains(target)) return;
|
|
706
|
-
if (target.closest(".cmt-canvas-region-handle, .cmt-canvas-region--movable")) return;
|
|
707
|
-
if (target.closest(".tlui-menu, [data-radix-popper-content-wrapper], .cmt-mention-popup"))
|
|
771
|
+
if (target.closest(".tlui-cmt-canvas-region-handle, .tlui-cmt-canvas-region--movable")) return;
|
|
772
|
+
if (target.closest(".tlui-menu, [data-radix-popper-content-wrapper], .tlui-cmt-mention-popup"))
|
|
708
773
|
return;
|
|
709
774
|
import_state.openThreadId.set(editor, null);
|
|
710
775
|
};
|
|
@@ -716,7 +781,10 @@ const ThreadPin = (0, import_react.memo)(function ThreadPin2({
|
|
|
716
781
|
() => {
|
|
717
782
|
if (thread.pageId !== editor.getCurrentPageId()) return null;
|
|
718
783
|
const pagePoint = (0, import_thread_state.anchorPagePoint)(editor, thread.anchor, impreciseShapeAnchor);
|
|
719
|
-
|
|
784
|
+
if (!pagePoint) return null;
|
|
785
|
+
const viewportPoint = editor.pageToViewport(pagePoint);
|
|
786
|
+
const inset = impreciseShapePinInset(thread.anchor, impreciseShapeAnchor);
|
|
787
|
+
return inset ? { x: viewportPoint.x + inset.x, y: viewportPoint.y + inset.y } : viewportPoint;
|
|
720
788
|
},
|
|
721
789
|
[editor, thread.anchor, thread.pageId, impreciseShapeAnchor]
|
|
722
790
|
);
|
|
@@ -743,6 +811,7 @@ const ThreadPin = (0, import_react.memo)(function ThreadPin2({
|
|
|
743
811
|
if (onPostComment) onPostComment(comment);
|
|
744
812
|
});
|
|
745
813
|
setReply(import_comment_extensions.EMPTY_COMMENT);
|
|
814
|
+
(0, import_comment_drafts.clearCommentDraft)((0, import_comment_drafts.replyDraftSlot)(thread.id));
|
|
746
815
|
};
|
|
747
816
|
const toggleResolve = () => {
|
|
748
817
|
if (!currentUserId) return;
|
|
@@ -766,6 +835,16 @@ const ThreadPin = (0, import_react.memo)(function ThreadPin2({
|
|
|
766
835
|
setEditingId(comment.id);
|
|
767
836
|
setEditText(comment.body);
|
|
768
837
|
};
|
|
838
|
+
const deleteComment = (comment) => {
|
|
839
|
+
(0, import_state.commitCommentMutation)(editor, () => {
|
|
840
|
+
if (comments.length === 1) {
|
|
841
|
+
import_state.openThreadId.set(editor, null);
|
|
842
|
+
(0, import_comment_store.removeCommentRecords)(editor, [thread.id, comment.id]);
|
|
843
|
+
} else {
|
|
844
|
+
(0, import_comment_store.removeCommentRecords)(editor, [comment.id]);
|
|
845
|
+
}
|
|
846
|
+
});
|
|
847
|
+
};
|
|
769
848
|
const saveEdit = () => {
|
|
770
849
|
const comment = comments.find((c) => c.id === editingId);
|
|
771
850
|
if (!comment || (0, import_comment_extensions.isCommentEmpty)(editText)) return;
|
|
@@ -780,7 +859,7 @@ const ThreadPin = (0, import_react.memo)(function ThreadPin2({
|
|
|
780
859
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
781
860
|
"div",
|
|
782
861
|
{
|
|
783
|
-
className: "cmt-editing",
|
|
862
|
+
className: "tlui-cmt-editing",
|
|
784
863
|
onKeyDown: (e) => {
|
|
785
864
|
if (e.key === "Escape") {
|
|
786
865
|
setEditingId(null);
|
|
@@ -809,15 +888,46 @@ const ThreadPin = (0, import_react.memo)(function ThreadPin2({
|
|
|
809
888
|
import_comment_card.CommentCard,
|
|
810
889
|
{
|
|
811
890
|
...card,
|
|
812
|
-
actions: comment.authorId === currentUserId ? /* @__PURE__ */ (0, import_jsx_runtime.
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
|
|
891
|
+
actions: comment.authorId === currentUserId ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_tldraw.TldrawUiDropdownMenuRoot, { id: `comment-actions-${comment.id}`, children: [
|
|
892
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_tldraw.TldrawUiDropdownMenuTrigger, { children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
893
|
+
"button",
|
|
894
|
+
{
|
|
895
|
+
type: "button",
|
|
896
|
+
className: "tlui-cmt-thread__action",
|
|
897
|
+
title: msg("comments.more-options"),
|
|
898
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_tldraw.TldrawUiIcon, { icon: "dots-vertical", label: msg("comments.more-options"), small: true })
|
|
899
|
+
}
|
|
900
|
+
) }),
|
|
901
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
902
|
+
import_tldraw.TldrawUiDropdownMenuContent,
|
|
903
|
+
{
|
|
904
|
+
className: "tlui-cmt-menu",
|
|
905
|
+
side: "bottom",
|
|
906
|
+
align: "end",
|
|
907
|
+
alignOffset: 0,
|
|
908
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_tldraw.TldrawUiDropdownMenuGroup, { children: [
|
|
909
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_tldraw.TldrawUiDropdownMenuItem, { children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
910
|
+
"button",
|
|
911
|
+
{
|
|
912
|
+
type: "button",
|
|
913
|
+
className: "tlui-cmt-menu-item",
|
|
914
|
+
onClick: () => startEdit(comment),
|
|
915
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { children: msg("comments.edit-comment") })
|
|
916
|
+
}
|
|
917
|
+
) }),
|
|
918
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_tldraw.TldrawUiDropdownMenuItem, { children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
919
|
+
"button",
|
|
920
|
+
{
|
|
921
|
+
type: "button",
|
|
922
|
+
className: "tlui-cmt-menu-item tlui-cmt-menu-item--danger",
|
|
923
|
+
onClick: () => deleteComment(comment),
|
|
924
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { children: msg("comments.delete-comment") })
|
|
925
|
+
}
|
|
926
|
+
) })
|
|
927
|
+
] })
|
|
928
|
+
}
|
|
929
|
+
)
|
|
930
|
+
] }) : void 0
|
|
821
931
|
}
|
|
822
932
|
);
|
|
823
933
|
};
|
|
@@ -825,7 +935,7 @@ const ThreadPin = (0, import_react.memo)(function ThreadPin2({
|
|
|
825
935
|
currentUserId && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
826
936
|
"button",
|
|
827
937
|
{
|
|
828
|
-
className: "cmt-thread__action",
|
|
938
|
+
className: "tlui-cmt-thread__action",
|
|
829
939
|
title: msg(thread.resolved ? "comments.reopen" : "comments.resolve"),
|
|
830
940
|
onClick: toggleResolve,
|
|
831
941
|
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
@@ -838,33 +948,63 @@ const ThreadPin = (0, import_react.memo)(function ThreadPin2({
|
|
|
838
948
|
)
|
|
839
949
|
}
|
|
840
950
|
),
|
|
841
|
-
currentUserId && /* @__PURE__ */ (0, import_jsx_runtime.
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
|
|
951
|
+
currentUserId && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_tldraw.TldrawUiDropdownMenuRoot, { id: `comment-thread-actions-${thread.id}`, children: [
|
|
952
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_tldraw.TldrawUiDropdownMenuTrigger, { children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
953
|
+
"button",
|
|
954
|
+
{
|
|
955
|
+
type: "button",
|
|
956
|
+
className: "tlui-cmt-thread__action",
|
|
957
|
+
title: msg("comments.more-options"),
|
|
958
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_tldraw.TldrawUiIcon, { icon: "dots-vertical", label: msg("comments.more-options"), small: true })
|
|
959
|
+
}
|
|
960
|
+
) }),
|
|
961
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
962
|
+
import_tldraw.TldrawUiDropdownMenuContent,
|
|
963
|
+
{
|
|
964
|
+
className: "tlui-cmt-menu",
|
|
965
|
+
side: "bottom",
|
|
966
|
+
align: "end",
|
|
967
|
+
alignOffset: 0,
|
|
968
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_tldraw.TldrawUiDropdownMenuGroup, { children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_tldraw.TldrawUiDropdownMenuItem, { children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
969
|
+
"button",
|
|
970
|
+
{
|
|
971
|
+
type: "button",
|
|
972
|
+
className: "tlui-cmt-menu-item tlui-cmt-menu-item--danger",
|
|
973
|
+
onClick: deleteThread,
|
|
974
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { children: msg("comments.delete") })
|
|
975
|
+
}
|
|
976
|
+
) }) })
|
|
977
|
+
}
|
|
978
|
+
)
|
|
979
|
+
] })
|
|
859
980
|
] });
|
|
860
981
|
const PinContent = options.components.PinContent;
|
|
861
|
-
const
|
|
982
|
+
const threadAuthor = resolveAuthor(thread.createdBy);
|
|
983
|
+
const pinContent = PinContent ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(PinContent, { thread, comments }) : initialOf(threadAuthor?.name ?? import_comment_render.UNKNOWN_AUTHOR);
|
|
862
984
|
const isRegion = thread.anchor.type === "region";
|
|
863
985
|
const pinMovable = regionOptions.move !== "body";
|
|
864
986
|
const bodyMovable = regionOptions.move !== "pin";
|
|
865
987
|
const startDrag = (e) => {
|
|
988
|
+
if (isCanvasPanGesture(editor, e)) {
|
|
989
|
+
forwardPointerEventToCanvas(container, e);
|
|
990
|
+
return;
|
|
991
|
+
}
|
|
866
992
|
e.stopPropagation();
|
|
867
|
-
|
|
993
|
+
const grabPage = editor.screenToPage({ x: e.clientX, y: e.clientY });
|
|
994
|
+
const anchorPage = (0, import_thread_state.anchorPagePoint)(editor, thread.anchor, impreciseShapeAnchor);
|
|
995
|
+
const inset = impreciseShapePinInset(thread.anchor, impreciseShapeAnchor);
|
|
996
|
+
if (anchorPage && inset) {
|
|
997
|
+
const zoom = editor.getZoomLevel();
|
|
998
|
+
anchorPage.x += inset.x / zoom;
|
|
999
|
+
anchorPage.y += inset.y / zoom;
|
|
1000
|
+
}
|
|
1001
|
+
dragRef.current = {
|
|
1002
|
+
startX: e.clientX,
|
|
1003
|
+
startY: e.clientY,
|
|
1004
|
+
moved: false,
|
|
1005
|
+
offsetX: anchorPage ? anchorPage.x - grabPage.x : 0,
|
|
1006
|
+
offsetY: anchorPage ? anchorPage.y - grabPage.y : 0
|
|
1007
|
+
};
|
|
868
1008
|
e.currentTarget.setPointerCapture(e.pointerId);
|
|
869
1009
|
};
|
|
870
1010
|
const onDrag = (e) => {
|
|
@@ -873,7 +1013,8 @@ const ThreadPin = (0, import_react.memo)(function ThreadPin2({
|
|
|
873
1013
|
if (isRegion && !pinMovable) return;
|
|
874
1014
|
if (!drag.moved && Math.hypot(e.clientX - drag.startX, e.clientY - drag.startY) < 4) return;
|
|
875
1015
|
drag.moved = true;
|
|
876
|
-
|
|
1016
|
+
const cursorPage = editor.screenToPage({ x: e.clientX, y: e.clientY });
|
|
1017
|
+
setDragPagePoint({ x: cursorPage.x + drag.offsetX, y: cursorPage.y + drag.offsetY });
|
|
877
1018
|
};
|
|
878
1019
|
const endDrag = (e) => {
|
|
879
1020
|
const drag = dragRef.current;
|
|
@@ -886,14 +1027,15 @@ const ThreadPin = (0, import_react.memo)(function ThreadPin2({
|
|
|
886
1027
|
import_state.openThreadId.set(editor, import_state.openThreadId.get(editor) === thread.id ? null : thread.id);
|
|
887
1028
|
return;
|
|
888
1029
|
}
|
|
889
|
-
const
|
|
1030
|
+
const cursorPage = editor.screenToPage({ x: e.clientX, y: e.clientY });
|
|
1031
|
+
const pagePoint = { x: cursorPage.x + drag.offsetX, y: cursorPage.y + drag.offsetY };
|
|
890
1032
|
setDragPagePoint(null);
|
|
891
1033
|
let anchor;
|
|
892
1034
|
if (thread.anchor.type === "region") {
|
|
893
1035
|
anchor = {
|
|
894
1036
|
...thread.anchor,
|
|
895
|
-
x: pagePoint.x -
|
|
896
|
-
y: pagePoint.y -
|
|
1037
|
+
x: pagePoint.x - pinCorner.x * thread.anchor.w,
|
|
1038
|
+
y: pagePoint.y - pinCorner.y * thread.anchor.h
|
|
897
1039
|
};
|
|
898
1040
|
} else {
|
|
899
1041
|
const hit = editor.getShapeAtPoint(pagePoint, { hitInside: true });
|
|
@@ -901,19 +1043,21 @@ const ThreadPin = (0, import_react.memo)(function ThreadPin2({
|
|
|
901
1043
|
}
|
|
902
1044
|
(0, import_state.commitCommentMutation)(editor, () => (0, import_comment_store.putCommentRecords)(editor, [{ ...thread, anchor }]), "drag");
|
|
903
1045
|
};
|
|
904
|
-
const livePinPage = resizeBounds ? (0, import_thread_state.regionPinPoint)(resizeBounds,
|
|
905
|
-
const
|
|
1046
|
+
const livePinPage = resizeBounds ? (0, import_thread_state.regionPinPoint)(resizeBounds, pinCorner) : dragPagePoint;
|
|
1047
|
+
const renderPointBase = livePinPage ? editor.pageToViewport(livePinPage) : point;
|
|
1048
|
+
const renderPoint = isRegion ? { x: renderPointBase.x - 17, y: renderPointBase.y + 17 } : renderPointBase;
|
|
906
1049
|
const regionAnchor = thread.anchor.type === "region" ? thread.anchor : void 0;
|
|
907
1050
|
const movedRegion = regionAnchor && dragPagePoint ? {
|
|
908
1051
|
...regionAnchor,
|
|
909
|
-
x: dragPagePoint.x -
|
|
910
|
-
y: dragPagePoint.y -
|
|
1052
|
+
x: dragPagePoint.x - pinCorner.x * regionAnchor.w,
|
|
1053
|
+
y: dragPagePoint.y - pinCorner.y * regionAnchor.h
|
|
911
1054
|
} : regionAnchor;
|
|
912
1055
|
const regionBoxBounds = resizeBounds ?? movedRegion;
|
|
913
1056
|
const commitResize = (bounds) => {
|
|
914
1057
|
setResizeBounds(null);
|
|
915
1058
|
editor.run(
|
|
916
|
-
|
|
1059
|
+
// Spread the existing anchor first so the region's pin corner survives a resize.
|
|
1060
|
+
() => (0, import_comment_store.putCommentRecords)(editor, [{ ...thread, anchor: { ...regionAnchor, ...bounds } }]),
|
|
917
1061
|
{
|
|
918
1062
|
history: "ignore"
|
|
919
1063
|
}
|
|
@@ -943,44 +1087,51 @@ const ThreadPin = (0, import_react.memo)(function ThreadPin2({
|
|
|
943
1087
|
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
|
|
944
1088
|
"div",
|
|
945
1089
|
{
|
|
946
|
-
className:
|
|
1090
|
+
className: [
|
|
1091
|
+
"tlui-cmt-canvas-pin",
|
|
1092
|
+
open && "tlui-cmt-canvas-pin--open",
|
|
1093
|
+
dragPagePoint && "tlui-cmt-canvas-pin--dragging"
|
|
1094
|
+
].filter(Boolean).join(" "),
|
|
947
1095
|
style: { left: renderPoint.x, top: renderPoint.y },
|
|
948
1096
|
children: [
|
|
949
1097
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
950
1098
|
"div",
|
|
951
1099
|
{
|
|
952
1100
|
ref: markerRef,
|
|
953
|
-
className: "cmt-canvas-pin__marker",
|
|
1101
|
+
className: "tlui-cmt-canvas-pin__marker",
|
|
954
1102
|
onPointerDown: startDrag,
|
|
955
1103
|
onPointerMove: onDrag,
|
|
956
1104
|
onPointerUp: endDrag,
|
|
957
1105
|
onPointerEnter: () => setPinHovered(true),
|
|
958
1106
|
onPointerLeave: () => setPinHovered(false),
|
|
959
|
-
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_comment_pin.CommentPin, { resolved: thread.resolved != null, open, children: pinContent })
|
|
1107
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_comment_pin.CommentPin, { resolved: thread.resolved != null, open, color: threadAuthor?.color, children: pinContent })
|
|
960
1108
|
}
|
|
961
1109
|
),
|
|
962
1110
|
open && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
963
1111
|
ThreadPopover,
|
|
964
1112
|
{
|
|
965
1113
|
container,
|
|
966
|
-
style: { left: renderPoint.x +
|
|
1114
|
+
style: { left: renderPoint.x + 48, top: renderPoint.y - 54 },
|
|
967
1115
|
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
968
1116
|
import_comment_thread.CommentThread,
|
|
969
1117
|
{
|
|
970
1118
|
header: msg("comments.thread-title"),
|
|
971
1119
|
headerActions,
|
|
972
1120
|
renderComment,
|
|
973
|
-
comments: comments.map((c) => toCardProps(c, props, options.components)),
|
|
1121
|
+
comments: comments.map((c) => toCardProps(c, props, options.components, resolveName)),
|
|
974
1122
|
resolvedBanner: thread.resolved ? msg("comments.resolved-by").replace(
|
|
975
1123
|
"{name}",
|
|
976
|
-
|
|
1124
|
+
resolveAuthor(thread.resolved.by)?.name ?? import_comment_render.UNKNOWN_AUTHOR
|
|
977
1125
|
) : void 0,
|
|
978
1126
|
composer: currentUserId && !thread.resolved ? {
|
|
979
|
-
author:
|
|
1127
|
+
author: me ?? import_comment_render.UNKNOWN_COMMENT_AUTHOR,
|
|
980
1128
|
placeholder: msg("comments.reply-placeholder"),
|
|
981
1129
|
sendLabel: msg("comments.send"),
|
|
982
1130
|
value: reply,
|
|
983
|
-
onChange:
|
|
1131
|
+
onChange: (value) => {
|
|
1132
|
+
setReply(value);
|
|
1133
|
+
(0, import_comment_drafts.saveCommentDraft)((0, import_comment_drafts.replyDraftSlot)(thread.id), value);
|
|
1134
|
+
},
|
|
984
1135
|
onSubmit: postReply,
|
|
985
1136
|
disabled: (0, import_comment_extensions.isCommentEmpty)(reply),
|
|
986
1137
|
getMentionSuggestions,
|
|
@@ -999,12 +1150,15 @@ function PendingComposer({
|
|
|
999
1150
|
editor,
|
|
1000
1151
|
pending,
|
|
1001
1152
|
currentUserId,
|
|
1002
|
-
|
|
1153
|
+
resolveAuthor,
|
|
1003
1154
|
onPostComment,
|
|
1004
1155
|
getMentionSuggestions,
|
|
1005
1156
|
renderMentionSuggestion
|
|
1006
1157
|
}) {
|
|
1007
|
-
const
|
|
1158
|
+
const me = currentUserId ? resolveAuthor(currentUserId) : void 0;
|
|
1159
|
+
const [text, setText] = (0, import_react.useState)(
|
|
1160
|
+
() => (0, import_comment_drafts.getCommentDraft)(import_comment_drafts.NEW_COMMENT_DRAFT) ?? import_comment_extensions.EMPTY_COMMENT
|
|
1161
|
+
);
|
|
1008
1162
|
const ref = (0, import_react.useRef)(null);
|
|
1009
1163
|
const msg = (0, import_tldraw.useTranslation)();
|
|
1010
1164
|
const container = (0, import_tldraw.useContainer)();
|
|
@@ -1019,7 +1173,7 @@ function PendingComposer({
|
|
|
1019
1173
|
const el = ref.current;
|
|
1020
1174
|
const target = e.target;
|
|
1021
1175
|
if (!el || !target) return;
|
|
1022
|
-
if (el.contains(target) || target.closest(".cmt-mention-popup")) return;
|
|
1176
|
+
if (el.contains(target) || target.closest(".tlui-cmt-mention-popup")) return;
|
|
1023
1177
|
import_state.pendingComment.set(editor, null);
|
|
1024
1178
|
};
|
|
1025
1179
|
document.addEventListener("pointerdown", onPointerDown, true);
|
|
@@ -1044,6 +1198,7 @@ function PendingComposer({
|
|
|
1044
1198
|
if (onPostComment) onPostComment(comment);
|
|
1045
1199
|
});
|
|
1046
1200
|
setText(import_comment_extensions.EMPTY_COMMENT);
|
|
1201
|
+
(0, import_comment_drafts.clearCommentDraft)(import_comment_drafts.NEW_COMMENT_DRAFT);
|
|
1047
1202
|
import_state.pendingComment.set(editor, null);
|
|
1048
1203
|
};
|
|
1049
1204
|
return (0, import_react_dom.createPortal)(
|
|
@@ -1051,26 +1206,33 @@ function PendingComposer({
|
|
|
1051
1206
|
"div",
|
|
1052
1207
|
{
|
|
1053
1208
|
ref,
|
|
1054
|
-
className:
|
|
1209
|
+
className: [
|
|
1210
|
+
"tlui-cmt-canvas-composer",
|
|
1211
|
+
pending.anchor.type === "region" && "tlui-cmt-canvas-composer--region"
|
|
1212
|
+
].filter(Boolean).join(" "),
|
|
1055
1213
|
style: { left: point.x, top: point.y },
|
|
1056
1214
|
onPointerDown: stop,
|
|
1215
|
+
onContextMenu: stop,
|
|
1057
1216
|
onKeyDown: (e) => {
|
|
1058
1217
|
if (e.key === "Escape" && !(0, import_mention_suggestion.isMentionPickerOpen)()) import_state.pendingComment.set(editor, null);
|
|
1059
1218
|
},
|
|
1060
1219
|
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
1061
1220
|
import_comment_composer.CommentComposer,
|
|
1062
1221
|
{
|
|
1063
|
-
author:
|
|
1222
|
+
author: me ?? import_comment_render.UNKNOWN_COMMENT_AUTHOR,
|
|
1064
1223
|
placeholder: msg("comments.add-placeholder"),
|
|
1065
1224
|
sendLabel: msg("comments.send"),
|
|
1066
1225
|
value: text,
|
|
1067
|
-
onChange:
|
|
1226
|
+
onChange: (value) => {
|
|
1227
|
+
setText(value);
|
|
1228
|
+
(0, import_comment_drafts.saveCommentDraft)(import_comment_drafts.NEW_COMMENT_DRAFT, value);
|
|
1229
|
+
},
|
|
1068
1230
|
onSubmit: submit,
|
|
1069
1231
|
disabled: (0, import_comment_extensions.isCommentEmpty)(text),
|
|
1070
1232
|
getMentionSuggestions,
|
|
1071
1233
|
renderMentionSuggestion,
|
|
1072
1234
|
autoFocus: true,
|
|
1073
|
-
leading: draftAvatar
|
|
1235
|
+
leading: draftAvatar(me?.color)
|
|
1074
1236
|
}
|
|
1075
1237
|
)
|
|
1076
1238
|
}
|