@tldraw/commenting 0.0.0-bootstrap → 5.3.0-canary.04044ed9e96d
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/README.md +0 -2
- package/commenting.css +1152 -350
- package/dist-cjs/canvas/anchor-lifecycle.js +148 -0
- package/dist-cjs/canvas/anchor-lifecycle.js.map +7 -0
- package/dist-cjs/{ui/avatar.js → canvas/canvas-events.js} +14 -22
- package/dist-cjs/canvas/canvas-events.js.map +7 -0
- package/dist-cjs/canvas/cluster-badge.js +121 -0
- package/dist-cjs/canvas/cluster-badge.js.map +7 -0
- package/dist-cjs/canvas/cluster-fade.js +85 -0
- package/dist-cjs/canvas/cluster-fade.js.map +7 -0
- package/dist-cjs/canvas/cluster-input.js +53 -3
- package/dist-cjs/canvas/cluster-input.js.map +2 -2
- package/dist-cjs/canvas/cluster-model.js +252 -0
- package/dist-cjs/canvas/cluster-model.js.map +7 -0
- 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-mutations.js +152 -0
- package/dist-cjs/canvas/comment-mutations.js.map +7 -0
- package/dist-cjs/canvas/comment-reactions.js +160 -0
- package/dist-cjs/canvas/comment-reactions.js.map +7 -0
- package/dist-cjs/canvas/comment-render.js +9 -6
- package/dist-cjs/canvas/comment-render.js.map +2 -2
- package/dist-cjs/canvas/comment-store.js +19 -9
- package/dist-cjs/canvas/comment-store.js.map +2 -2
- package/dist-cjs/canvas/comment-tool.js +63 -14
- package/dist-cjs/canvas/comment-tool.js.map +2 -2
- package/dist-cjs/canvas/comments-filter-menu.js +17 -37
- package/dist-cjs/canvas/comments-filter-menu.js.map +2 -2
- package/dist-cjs/canvas/comments-overflow-menu.js +25 -22
- package/dist-cjs/canvas/comments-overflow-menu.js.map +2 -2
- package/dist-cjs/canvas/comments-overlay.js +151 -989
- package/dist-cjs/canvas/comments-overlay.js.map +3 -3
- package/dist-cjs/canvas/comments-sidebar.js +49 -41
- package/dist-cjs/canvas/comments-sidebar.js.map +2 -2
- package/dist-cjs/canvas/comments-visibility-toggle.js +45 -0
- package/dist-cjs/canvas/comments-visibility-toggle.js.map +7 -0
- package/dist-cjs/canvas/context.js +17 -0
- package/dist-cjs/canvas/context.js.map +7 -0
- package/dist-cjs/canvas/hooks.js +28 -3
- package/dist-cjs/canvas/hooks.js.map +2 -2
- package/dist-cjs/canvas/license.js.map +1 -1
- package/dist-cjs/canvas/mobile-placement.js +91 -0
- package/dist-cjs/canvas/mobile-placement.js.map +7 -0
- package/dist-cjs/canvas/options.js +57 -2
- package/dist-cjs/canvas/options.js.map +2 -2
- package/dist-cjs/canvas/pending-composer.js +134 -0
- package/dist-cjs/canvas/pending-composer.js.map +7 -0
- package/dist-cjs/canvas/pin-stacking.js +81 -0
- package/dist-cjs/canvas/pin-stacking.js.map +7 -0
- package/dist-cjs/canvas/region-box.js +113 -0
- package/dist-cjs/canvas/region-box.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 +28 -14
- package/dist-cjs/canvas/state.js.map +2 -2
- package/dist-cjs/canvas/thread-pin.js +304 -0
- package/dist-cjs/canvas/thread-pin.js.map +7 -0
- package/dist-cjs/canvas/thread-preview.js +177 -0
- package/dist-cjs/canvas/thread-preview.js.map +7 -0
- package/dist-cjs/canvas/thread-stack.js +199 -0
- package/dist-cjs/canvas/thread-stack.js.map +7 -0
- package/dist-cjs/canvas/thread-state.js +82 -21
- package/dist-cjs/canvas/thread-state.js.map +2 -2
- package/dist-cjs/canvas/thread-view.js +450 -0
- package/dist-cjs/canvas/thread-view.js.map +7 -0
- package/dist-cjs/clustering/computeClusterTable.js +6 -6
- package/dist-cjs/clustering/computeClusterTable.js.map +2 -2
- package/dist-cjs/clustering/replay.js +89 -22
- package/dist-cjs/clustering/replay.js.map +3 -3
- package/dist-cjs/clustering/runtime.js +126 -7
- package/dist-cjs/clustering/runtime.js.map +2 -2
- package/dist-cjs/clustering/types.js.map +1 -1
- package/dist-cjs/index.d.ts +904 -353
- package/dist-cjs/index.js +52 -28
- package/dist-cjs/index.js.map +2 -2
- package/dist-cjs/ui/byline.js +10 -6
- package/dist-cjs/ui/byline.js.map +2 -2
- package/dist-cjs/ui/comment-card.js +15 -8
- package/dist-cjs/ui/comment-card.js.map +2 -2
- package/dist-cjs/ui/comment-composer.js +124 -39
- package/dist-cjs/ui/comment-composer.js.map +2 -2
- package/dist-cjs/ui/comment-pin.js +11 -2
- package/dist-cjs/ui/comment-pin.js.map +2 -2
- package/dist-cjs/ui/comment-thread.js +9 -7
- package/dist-cjs/ui/comment-thread.js.map +2 -2
- package/dist-cjs/ui/comments-list.js +39 -40
- package/dist-cjs/ui/comments-list.js.map +2 -2
- package/dist-cjs/ui/count-badge.js +3 -2
- package/dist-cjs/ui/count-badge.js.map +2 -2
- package/dist-cjs/ui/emoji-picker.js +54 -0
- package/dist-cjs/ui/emoji-picker.js.map +7 -0
- 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 +16 -1
- package/dist-cjs/ui/format-time.js.map +2 -2
- package/dist-cjs/ui/icons.js +115 -0
- package/dist-cjs/ui/icons.js.map +7 -0
- package/dist-cjs/ui/reaction-picker.js +71 -0
- package/dist-cjs/ui/reaction-picker.js.map +7 -0
- package/dist-cjs/ui/reaction.js +58 -6
- package/dist-cjs/ui/reaction.js.map +2 -2
- package/dist-cjs/ui/reactions.js +20 -7
- package/dist-cjs/ui/reactions.js.map +2 -2
- package/dist-cjs/ui/{mention.js → reply-count.js} +9 -11
- package/dist-cjs/ui/reply-count.js.map +7 -0
- package/dist-cjs/ui/send-button.js +13 -1
- package/dist-cjs/ui/send-button.js.map +2 -2
- package/dist-cjs/ui/{comment-text.js → visual-viewport.js} +12 -9
- package/dist-cjs/ui/visual-viewport.js.map +7 -0
- package/dist-esm/canvas/anchor-lifecycle.mjs +128 -0
- package/dist-esm/canvas/anchor-lifecycle.mjs.map +7 -0
- package/dist-esm/canvas/canvas-events.mjs +15 -0
- package/dist-esm/canvas/canvas-events.mjs.map +7 -0
- package/dist-esm/canvas/cluster-badge.mjs +106 -0
- package/dist-esm/canvas/cluster-badge.mjs.map +7 -0
- package/dist-esm/canvas/cluster-fade.mjs +65 -0
- package/dist-esm/canvas/cluster-fade.mjs.map +7 -0
- package/dist-esm/canvas/cluster-input.mjs +54 -4
- package/dist-esm/canvas/cluster-input.mjs.map +2 -2
- package/dist-esm/canvas/cluster-model.mjs +236 -0
- package/dist-esm/canvas/cluster-model.mjs.map +7 -0
- 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-mutations.mjs +132 -0
- package/dist-esm/canvas/comment-mutations.mjs.map +7 -0
- package/dist-esm/canvas/comment-reactions.mjs +145 -0
- package/dist-esm/canvas/comment-reactions.mjs.map +7 -0
- package/dist-esm/canvas/comment-render.mjs +10 -7
- package/dist-esm/canvas/comment-render.mjs.map +2 -2
- package/dist-esm/canvas/comment-store.mjs +19 -9
- package/dist-esm/canvas/comment-store.mjs.map +2 -2
- package/dist-esm/canvas/comment-tool.mjs +66 -17
- package/dist-esm/canvas/comment-tool.mjs.map +2 -2
- package/dist-esm/canvas/comments-filter-menu.mjs +17 -36
- package/dist-esm/canvas/comments-filter-menu.mjs.map +2 -2
- package/dist-esm/canvas/comments-overflow-menu.mjs +27 -22
- package/dist-esm/canvas/comments-overflow-menu.mjs.map +2 -2
- package/dist-esm/canvas/comments-overlay.mjs +157 -1010
- package/dist-esm/canvas/comments-overlay.mjs.map +3 -3
- package/dist-esm/canvas/comments-sidebar.mjs +53 -46
- package/dist-esm/canvas/comments-sidebar.mjs.map +2 -2
- package/dist-esm/canvas/comments-visibility-toggle.mjs +25 -0
- package/dist-esm/canvas/comments-visibility-toggle.mjs.map +7 -0
- package/dist-esm/canvas/context.mjs +1 -0
- package/dist-esm/canvas/context.mjs.map +7 -0
- package/dist-esm/canvas/hooks.mjs +35 -5
- package/dist-esm/canvas/hooks.mjs.map +2 -2
- package/dist-esm/canvas/license.mjs.map +1 -1
- package/dist-esm/canvas/mobile-placement.mjs +71 -0
- package/dist-esm/canvas/mobile-placement.mjs.map +7 -0
- package/dist-esm/canvas/options.mjs +59 -3
- package/dist-esm/canvas/options.mjs.map +2 -2
- package/dist-esm/canvas/pending-composer.mjs +126 -0
- package/dist-esm/canvas/pending-composer.mjs.map +7 -0
- package/dist-esm/canvas/pin-stacking.mjs +61 -0
- package/dist-esm/canvas/pin-stacking.mjs.map +7 -0
- package/dist-esm/canvas/region-box.mjs +93 -0
- package/dist-esm/canvas/region-box.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 +29 -19
- package/dist-esm/canvas/state.mjs.map +2 -2
- package/dist-esm/canvas/thread-pin.mjs +310 -0
- package/dist-esm/canvas/thread-pin.mjs.map +7 -0
- package/dist-esm/canvas/thread-preview.mjs +163 -0
- package/dist-esm/canvas/thread-preview.mjs.map +7 -0
- package/dist-esm/canvas/thread-stack.mjs +189 -0
- package/dist-esm/canvas/thread-stack.mjs.map +7 -0
- package/dist-esm/canvas/thread-state.mjs +86 -22
- package/dist-esm/canvas/thread-state.mjs.map +2 -2
- package/dist-esm/canvas/thread-view.mjs +461 -0
- package/dist-esm/canvas/thread-view.mjs.map +7 -0
- package/dist-esm/clustering/computeClusterTable.mjs +6 -6
- package/dist-esm/clustering/computeClusterTable.mjs.map +2 -2
- package/dist-esm/clustering/replay.mjs +89 -22
- package/dist-esm/clustering/replay.mjs.map +3 -3
- package/dist-esm/clustering/runtime.mjs +126 -7
- package/dist-esm/clustering/runtime.mjs.map +2 -2
- package/dist-esm/index.d.mts +904 -353
- package/dist-esm/index.mjs +102 -43
- package/dist-esm/index.mjs.map +2 -2
- package/dist-esm/ui/byline.mjs +11 -7
- package/dist-esm/ui/byline.mjs.map +2 -2
- package/dist-esm/ui/comment-card.mjs +15 -8
- package/dist-esm/ui/comment-card.mjs.map +2 -2
- package/dist-esm/ui/comment-composer.mjs +135 -39
- package/dist-esm/ui/comment-composer.mjs.map +2 -2
- package/dist-esm/ui/comment-pin.mjs +11 -2
- package/dist-esm/ui/comment-pin.mjs.map +2 -2
- package/dist-esm/ui/comment-thread.mjs +9 -7
- package/dist-esm/ui/comment-thread.mjs.map +2 -2
- package/dist-esm/ui/comments-list.mjs +51 -50
- package/dist-esm/ui/comments-list.mjs.map +2 -2
- package/dist-esm/ui/count-badge.mjs +3 -2
- package/dist-esm/ui/count-badge.mjs.map +2 -2
- package/dist-esm/ui/emoji-picker.mjs +34 -0
- package/dist-esm/ui/emoji-picker.mjs.map +7 -0
- 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 +16 -1
- package/dist-esm/ui/format-time.mjs.map +2 -2
- package/dist-esm/ui/icons.mjs +95 -0
- package/dist-esm/ui/icons.mjs.map +7 -0
- package/dist-esm/ui/reaction-picker.mjs +59 -0
- package/dist-esm/ui/reaction-picker.mjs.map +7 -0
- package/dist-esm/ui/reaction.mjs +59 -7
- package/dist-esm/ui/reaction.mjs.map +2 -2
- package/dist-esm/ui/reactions.mjs +21 -8
- package/dist-esm/ui/reactions.mjs.map +2 -2
- package/dist-esm/ui/reply-count.mjs +9 -0
- package/dist-esm/ui/reply-count.mjs.map +7 -0
- package/dist-esm/ui/send-button.mjs +13 -1
- package/dist-esm/ui/send-button.mjs.map +2 -2
- package/dist-esm/ui/visual-viewport.mjs +12 -0
- package/dist-esm/ui/visual-viewport.mjs.map +7 -0
- package/package.json +6 -6
- package/src/canvas/anchor-lifecycle.test.ts +290 -0
- package/src/canvas/anchor-lifecycle.ts +191 -0
- package/src/canvas/canvas-events.ts +18 -0
- package/src/canvas/canvas.css +464 -55
- package/src/canvas/cluster-badge.tsx +133 -0
- package/src/canvas/cluster-fade.ts +102 -0
- package/src/canvas/cluster-input.test.ts +178 -36
- package/src/canvas/cluster-input.ts +95 -9
- package/src/canvas/cluster-model.ts +378 -0
- 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-mutations.test.ts +452 -0
- package/src/canvas/comment-mutations.ts +299 -0
- package/src/canvas/comment-reactions.test.ts +154 -0
- package/src/canvas/comment-reactions.tsx +246 -0
- package/src/canvas/comment-render.test.ts +1 -1
- package/src/canvas/comment-render.ts +17 -13
- package/src/canvas/comment-store.ts +68 -33
- package/src/canvas/comment-tool.test.ts +162 -0
- package/src/canvas/comment-tool.tsx +103 -25
- package/src/canvas/comments-filter-menu.tsx +20 -36
- package/src/canvas/comments-overflow-menu.tsx +17 -19
- package/src/canvas/comments-overlay.tsx +252 -1369
- package/src/canvas/comments-sidebar.test.ts +45 -0
- package/src/canvas/comments-sidebar.tsx +112 -73
- package/src/canvas/comments-visibility-toggle.tsx +25 -0
- package/src/canvas/context.ts +48 -0
- package/src/canvas/hooks.test.ts +94 -0
- package/src/canvas/hooks.ts +66 -11
- package/src/canvas/license.ts +1 -1
- package/src/canvas/mobile-placement.ts +115 -0
- package/src/canvas/options.test.ts +176 -4
- package/src/canvas/options.ts +276 -18
- package/src/canvas/pending-composer.tsx +157 -0
- package/src/canvas/pin-stacking.test.ts +224 -0
- package/src/canvas/pin-stacking.ts +103 -0
- package/src/canvas/region-box.tsx +124 -0
- package/src/canvas/sidebar-filters.ts +4 -3
- package/src/canvas/state.ts +88 -39
- package/src/canvas/thread-pin.tsx +418 -0
- package/src/canvas/thread-preview.test.ts +91 -0
- package/src/canvas/thread-preview.tsx +294 -0
- package/src/canvas/thread-stack.tsx +242 -0
- package/src/canvas/thread-state.test.ts +260 -0
- package/src/canvas/thread-state.ts +171 -37
- package/src/canvas/thread-view.test.ts +72 -0
- package/src/canvas/thread-view.tsx +614 -0
- package/src/clustering/computeClusterTable.test.ts +24 -23
- package/src/clustering/computeClusterTable.ts +17 -8
- package/src/clustering/replay.test.ts +0 -7
- package/src/clustering/replay.ts +131 -32
- package/src/clustering/runtime.test.ts +267 -13
- package/src/clustering/runtime.ts +176 -19
- package/src/clustering/schedule.test.ts +0 -6
- package/src/clustering/screen-offsets.test.ts +171 -0
- package/src/clustering/types.ts +19 -9
- package/src/index.ts +91 -42
- package/src/ui/byline.tsx +21 -9
- package/src/ui/comment-card.tsx +20 -10
- package/src/ui/comment-composer.tsx +178 -56
- package/src/ui/comment-pin.tsx +13 -2
- package/src/ui/comment-thread.tsx +13 -6
- package/src/ui/comments-list.test.ts +31 -0
- package/src/ui/comments-list.tsx +82 -47
- package/src/ui/comments.css +577 -294
- package/src/ui/count-badge.tsx +9 -2
- package/src/ui/emoji-picker.test.ts +25 -0
- package/src/ui/emoji-picker.tsx +76 -0
- package/src/ui/empty-state.tsx +3 -3
- package/src/ui/format-time.test.ts +69 -0
- package/src/ui/format-time.ts +27 -2
- package/src/ui/icons.tsx +116 -0
- package/src/ui/reaction-picker.tsx +102 -0
- package/src/ui/reaction.tsx +125 -6
- package/src/ui/reactions.tsx +69 -10
- package/src/ui/reply-count.ts +16 -0
- package/src/ui/send-button.tsx +13 -3
- package/src/ui/visual-viewport.test.ts +36 -0
- package/src/ui/visual-viewport.ts +27 -0
- package/dist-cjs/canvas/region-options.js +0 -49
- package/dist-cjs/canvas/region-options.js.map +0 -7
- package/dist-cjs/ui/avatar.js.map +0 -7
- package/dist-cjs/ui/comment-mention.js +0 -42
- package/dist-cjs/ui/comment-mention.js.map +0 -7
- package/dist-cjs/ui/comment-text.js.map +0 -7
- package/dist-cjs/ui/mention-list.js +0 -70
- package/dist-cjs/ui/mention-list.js.map +0 -7
- package/dist-cjs/ui/mention-suggestion.js +0 -206
- package/dist-cjs/ui/mention-suggestion.js.map +0 -7
- package/dist-cjs/ui/mention.js.map +0 -7
- package/dist-cjs/ui/render-markdown.js +0 -63
- package/dist-cjs/ui/render-markdown.js.map +0 -7
- package/dist-esm/canvas/region-options.mjs +0 -29
- package/dist-esm/canvas/region-options.mjs.map +0 -7
- package/dist-esm/ui/avatar.mjs +0 -23
- package/dist-esm/ui/avatar.mjs.map +0 -7
- package/dist-esm/ui/comment-mention.mjs +0 -22
- package/dist-esm/ui/comment-mention.mjs.map +0 -7
- package/dist-esm/ui/comment-text.mjs +0 -9
- package/dist-esm/ui/comment-text.mjs.map +0 -7
- package/dist-esm/ui/mention-list.mjs +0 -50
- package/dist-esm/ui/mention-list.mjs.map +0 -7
- package/dist-esm/ui/mention-suggestion.mjs +0 -186
- package/dist-esm/ui/mention-suggestion.mjs.map +0 -7
- package/dist-esm/ui/mention.mjs +0 -11
- package/dist-esm/ui/mention.mjs.map +0 -7
- package/dist-esm/ui/render-markdown.mjs +0 -45
- package/dist-esm/ui/render-markdown.mjs.map +0 -7
- package/src/canvas/region-options.ts +0 -57
- package/src/ui/avatar.tsx +0 -31
- package/src/ui/comment-mention.ts +0 -47
- package/src/ui/comment-text.tsx +0 -12
- package/src/ui/mention-list.tsx +0 -106
- package/src/ui/mention-suggestion.test.ts +0 -18
- package/src/ui/mention-suggestion.tsx +0 -285
- package/src/ui/mention.tsx +0 -9
- package/src/ui/render-markdown.tsx +0 -72
|
@@ -18,64 +18,125 @@ var __copyProps = (to, from, except, desc) => {
|
|
|
18
18
|
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
19
|
var thread_state_exports = {};
|
|
20
20
|
__export(thread_state_exports, {
|
|
21
|
-
|
|
21
|
+
IMPRECISE_PIN_INSET_PX: () => IMPRECISE_PIN_INSET_PX,
|
|
22
22
|
REGION_PIN_CORNER: () => REGION_PIN_CORNER,
|
|
23
23
|
anchorPagePoint: () => anchorPagePoint,
|
|
24
|
+
commentCenterScreenOffset: () => commentCenterScreenOffset,
|
|
25
|
+
commentTargetShapeAt: () => commentTargetShapeAt,
|
|
24
26
|
focusThread: () => focusThread,
|
|
27
|
+
impreciseShapePinInset: () => impreciseShapePinInset,
|
|
28
|
+
isBoxInInflatedViewport: () => isBoxInInflatedViewport,
|
|
29
|
+
isInInflatedViewport: () => isInInflatedViewport,
|
|
30
|
+
regionAnchorPinCorner: () => regionAnchorPinCorner,
|
|
25
31
|
regionPinPoint: () => regionPinPoint,
|
|
26
32
|
shapeAnchorAt: () => shapeAnchorAt
|
|
27
33
|
});
|
|
28
34
|
module.exports = __toCommonJS(thread_state_exports);
|
|
29
|
-
var
|
|
35
|
+
var import_tldraw = require("tldraw");
|
|
36
|
+
var import_options = require("./options");
|
|
30
37
|
var import_state = require("./state");
|
|
31
|
-
|
|
38
|
+
var import_thread_view = require("./thread-view");
|
|
39
|
+
const IMPRECISE_PIN_INSET_PX = 20;
|
|
40
|
+
const MARKER_CULL_MARGIN_PX = 120;
|
|
41
|
+
function isInInflatedViewport(editor, point) {
|
|
42
|
+
const viewport = editor.getViewportScreenBounds();
|
|
43
|
+
const margin = MARKER_CULL_MARGIN_PX;
|
|
44
|
+
return point.x >= -margin && point.y >= -margin && point.x <= viewport.w + margin && point.y <= viewport.h + margin;
|
|
45
|
+
}
|
|
46
|
+
function isBoxInInflatedViewport(editor, box) {
|
|
47
|
+
const viewport = editor.getViewportScreenBounds();
|
|
48
|
+
const margin = MARKER_CULL_MARGIN_PX;
|
|
49
|
+
const min = editor.pageToViewport({ x: box.x, y: box.y });
|
|
50
|
+
const max = editor.pageToViewport({ x: box.x + box.w, y: box.y + box.h });
|
|
51
|
+
return max.x >= -margin && max.y >= -margin && min.x <= viewport.w + margin && min.y <= viewport.h + margin;
|
|
52
|
+
}
|
|
53
|
+
function impreciseShapePinInset(editor, anchor) {
|
|
54
|
+
if (anchor.type !== "shape" || anchor.isPrecise) return null;
|
|
55
|
+
const spot = (0, import_options.getCommentingOptions)(editor).impreciseShapeAnchor;
|
|
56
|
+
const inset = {
|
|
57
|
+
x: Math.sign(0.5 - spot.x) * IMPRECISE_PIN_INSET_PX,
|
|
58
|
+
y: Math.sign(0.5 - spot.y) * IMPRECISE_PIN_INSET_PX
|
|
59
|
+
};
|
|
60
|
+
const rotation = editor.getShapePageTransform(anchor.shapeId)?.rotation() ?? 0;
|
|
61
|
+
return rotation === 0 ? inset : import_tldraw.Vec.Rot(inset, rotation);
|
|
62
|
+
}
|
|
32
63
|
const REGION_PIN_CORNER = { x: 1, y: 1 };
|
|
64
|
+
function regionAnchorPinCorner(anchor) {
|
|
65
|
+
if (anchor.pinX !== void 0 && anchor.pinY !== void 0) {
|
|
66
|
+
return { x: anchor.pinX, y: anchor.pinY };
|
|
67
|
+
}
|
|
68
|
+
return REGION_PIN_CORNER;
|
|
69
|
+
}
|
|
33
70
|
function regionPinPoint(region, corner = REGION_PIN_CORNER) {
|
|
34
71
|
return {
|
|
35
72
|
x: region.x + corner.x * region.w,
|
|
36
73
|
y: region.y + corner.y * region.h
|
|
37
74
|
};
|
|
38
75
|
}
|
|
39
|
-
function anchorPagePoint(editor, anchor
|
|
76
|
+
function anchorPagePoint(editor, anchor) {
|
|
40
77
|
switch (anchor.type) {
|
|
41
78
|
case "shape": {
|
|
42
|
-
const
|
|
43
|
-
if (!
|
|
44
|
-
const
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
if (!bounds) return null;
|
|
50
|
-
return { x: bounds.maxX, y: bounds.minY };
|
|
79
|
+
const shape = editor.getShape(anchor.shapeId);
|
|
80
|
+
if (!shape) return null;
|
|
81
|
+
const transform = editor.getShapePageTransform(shape);
|
|
82
|
+
if (!transform) return null;
|
|
83
|
+
const { point, size } = editor.getShapeGeometry(shape).bounds;
|
|
84
|
+
const spot = anchor.isPrecise ? anchor : (0, import_options.getCommentingOptions)(editor).impreciseShapeAnchor;
|
|
85
|
+
return import_tldraw.Mat.applyToPoint(transform, import_tldraw.Vec.Add(point, import_tldraw.Vec.MulV(spot, size)));
|
|
51
86
|
}
|
|
52
87
|
case "point":
|
|
53
88
|
return { x: anchor.x, y: anchor.y };
|
|
54
89
|
case "region":
|
|
55
|
-
return regionPinPoint(anchor, (
|
|
90
|
+
return regionPinPoint(anchor, regionAnchorPinCorner(anchor));
|
|
56
91
|
case "page":
|
|
57
92
|
return null;
|
|
58
93
|
}
|
|
59
94
|
}
|
|
95
|
+
function commentTargetShapeAt(editor, page) {
|
|
96
|
+
return editor.getShapeAtPoint(page, {
|
|
97
|
+
hitInside: true,
|
|
98
|
+
hitFrameInside: true,
|
|
99
|
+
margin: editor.getHitTestMargin()
|
|
100
|
+
});
|
|
101
|
+
}
|
|
60
102
|
function shapeAnchorAt(editor, shapeId, page, precise) {
|
|
61
|
-
const
|
|
62
|
-
|
|
103
|
+
const shape = editor.getShape(shapeId);
|
|
104
|
+
const bounds = shape && editor.getShapeGeometry(shape).bounds;
|
|
105
|
+
if (!shape || !bounds || bounds.w === 0 || bounds.h === 0) {
|
|
63
106
|
return { type: "shape", shapeId, x: 0.5, y: 0.5, isPrecise: precise };
|
|
64
107
|
}
|
|
108
|
+
const local = editor.getPointInShapeSpace(shape, page);
|
|
65
109
|
return {
|
|
66
110
|
type: "shape",
|
|
67
111
|
shapeId,
|
|
68
|
-
x: (
|
|
69
|
-
y: (
|
|
112
|
+
x: (local.x - bounds.minX) / bounds.w,
|
|
113
|
+
y: (local.y - bounds.minY) / bounds.h,
|
|
70
114
|
isPrecise: precise
|
|
71
115
|
};
|
|
72
116
|
}
|
|
73
|
-
function focusThread(editor, thread
|
|
117
|
+
function focusThread(editor, thread) {
|
|
74
118
|
if (thread.pageId !== editor.getCurrentPageId()) {
|
|
75
119
|
editor.setCurrentPage(thread.pageId);
|
|
76
120
|
}
|
|
77
121
|
import_state.openThreadId.set(editor, thread.id);
|
|
78
|
-
const point = anchorPagePoint(editor, thread.anchor
|
|
79
|
-
if (point)
|
|
122
|
+
const point = anchorPagePoint(editor, thread.anchor);
|
|
123
|
+
if (!point) return;
|
|
124
|
+
const offset = commentCenterScreenOffset(editor) / editor.getZoomLevel();
|
|
125
|
+
editor.centerOnPoint({ x: point.x + offset, y: point.y }, { animation: { duration: 200 } });
|
|
126
|
+
}
|
|
127
|
+
const CENTER_MARGIN_PX = 8;
|
|
128
|
+
const THREAD_UI_EXTENT_PX = import_thread_view.POPOVER_OFFSET.thread.x + 300;
|
|
129
|
+
function commentCenterScreenOffset(editor) {
|
|
130
|
+
if (!import_state.commentsSidebarOpen.get(editor)) return 0;
|
|
131
|
+
const sidebar = editor.getContainer().querySelector(".tlui-cmt-canvas-sidebar");
|
|
132
|
+
if (!sidebar) return 0;
|
|
133
|
+
const viewport = editor.getViewportScreenBounds();
|
|
134
|
+
const sidebarLeft = sidebar.getBoundingClientRect().left - viewport.x;
|
|
135
|
+
if (sidebarLeft >= viewport.w) return 0;
|
|
136
|
+
const pinX = Math.max(
|
|
137
|
+
Math.min(sidebarLeft / 2, sidebarLeft - CENTER_MARGIN_PX - THREAD_UI_EXTENT_PX),
|
|
138
|
+
CENTER_MARGIN_PX
|
|
139
|
+
);
|
|
140
|
+
return viewport.w / 2 - pinX;
|
|
80
141
|
}
|
|
81
142
|
//# sourceMappingURL=thread-state.js.map
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../src/canvas/thread-state.ts"],
|
|
4
|
-
"sourcesContent": ["import {
|
|
5
|
-
"mappings": ";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;
|
|
4
|
+
"sourcesContent": ["import {\n\tBoxModel,\n\tEditor,\n\tMat,\n\tTLCommentAnchor,\n\tTLCommentThread,\n\tTLShape,\n\tTLShapeId,\n\tVec,\n\tVecLike,\n} from 'tldraw'\nimport { getCommentingOptions } from './options'\nimport { commentsSidebarOpen, openThreadId } from './state'\nimport { POPOVER_OFFSET } from './thread-view'\n\n/** How far an imprecise shape pin steps inside the shape from its anchor spot, in screen px \u2014\n * most of the marker sits within the shape, with a small overhang past the corner. */\nexport const IMPRECISE_PIN_INSET_PX = 20\n\n/** Screen-pixel margin by which the viewport is inflated when culling canvas markers (thread pins\n * and cluster badges), so a marker just off-screen is already mounted when a pan brings it in. */\nconst MARKER_CULL_MARGIN_PX = 120\n\n/**\n * Whether a viewport-space point sits within the viewport inflated by\n * {@link MARKER_CULL_MARGIN_PX}. The cull test for screen-fixed markers: off-screen markers\n * return null from their position signal and unmount instead of tracking every camera frame.\n * @internal\n */\nexport function isInInflatedViewport(editor: Editor, point: VecLike): boolean {\n\tconst viewport = editor.getViewportScreenBounds()\n\tconst margin = MARKER_CULL_MARGIN_PX\n\treturn (\n\t\tpoint.x >= -margin &&\n\t\tpoint.y >= -margin &&\n\t\tpoint.x <= viewport.w + margin &&\n\t\tpoint.y <= viewport.h + margin\n\t)\n}\n\n/**\n * Whether any part of a page-space box overlaps the viewport inflated by\n * {@link MARKER_CULL_MARGIN_PX}. The cull test for region-anchored threads, whose dashed box can\n * be on screen while the pin corner itself is not.\n * @internal\n */\nexport function isBoxInInflatedViewport(editor: Editor, box: BoxModel): boolean {\n\tconst viewport = editor.getViewportScreenBounds()\n\tconst margin = MARKER_CULL_MARGIN_PX\n\t// Zoom is positive, so the page box's corners keep their order through the transform.\n\tconst min = editor.pageToViewport({ x: box.x, y: box.y })\n\tconst max = editor.pageToViewport({ x: box.x + box.w, y: box.y + box.h })\n\treturn (\n\t\tmax.x >= -margin &&\n\t\tmax.y >= -margin &&\n\t\tmin.x <= viewport.w + margin &&\n\t\tmin.y <= viewport.h + margin\n\t)\n}\n\n/** Imprecise shape pins tuck inside the shape rather than hanging off its edge: the marker\n * extends up-right of its anchor point, so step it toward the shape's centre. Screen px \u2014 the\n * pin is screen-fixed while the shape scales with zoom. Null for anchors that need no inset. */\nexport function impreciseShapePinInset(\n\teditor: Editor,\n\tanchor: TLCommentThread['anchor']\n): { x: number; y: number } | null {\n\tif (anchor.type !== 'shape' || anchor.isPrecise) return null\n\tconst spot = getCommentingOptions(editor).impreciseShapeAnchor\n\tconst inset = {\n\t\tx: Math.sign(0.5 - spot.x) * IMPRECISE_PIN_INSET_PX,\n\t\ty: Math.sign(0.5 - spot.y) * IMPRECISE_PIN_INSET_PX,\n\t}\n\t// The spot is a corner of the shape's own bounds, so which way \"toward the centre\" points turns\n\t// with the shape: without this a rotated shape's pin would step out of the shape, not into it.\n\tconst rotation = editor.getShapePageTransform(anchor.shapeId as TLShapeId)?.rotation() ?? 0\n\treturn rotation === 0 ? inset : Vec.Rot(inset, rotation)\n}\n\n/** The corner a region's pin and composer sit on, as a normalized 0\u20131 offset (bottom-right). Pin\n * position, composer placement, region move, and which corner has no resize handle all derive\n * from it. */\nexport const REGION_PIN_CORNER: VecLike = { x: 1, y: 1 }\n\n/** A region anchor's pin corner: the corner its creating drag released on, when recorded, else\n * {@link REGION_PIN_CORNER}. @internal */\nexport function regionAnchorPinCorner(\n\tanchor: Extract<TLCommentAnchor, { type: 'region' }>\n): VecLike {\n\tif (anchor.pinX !== undefined && anchor.pinY !== undefined) {\n\t\treturn { x: anchor.pinX, y: anchor.pinY }\n\t}\n\treturn REGION_PIN_CORNER\n}\n\n/** The page point of a region's pin corner. */\nexport function regionPinPoint(region: BoxModel, corner: VecLike = REGION_PIN_CORNER): VecLike {\n\treturn {\n\t\tx: region.x + corner.x * region.w,\n\t\ty: region.y + corner.y * region.h,\n\t}\n}\n\n/**\n * Where a thread's pin sits on the page, for each anchor kind. Null hides the pin. Imprecise shape\n * anchors use {@link CommentingOptions.impreciseShapeAnchor} rather than the stored `x`/`y`.\n *\n * A shape anchor's `x`/`y` are normalized within the shape's bounds and resolved through its page\n * transform, so the pin rides rotation instead of being left behind in the bounding box.\n * @public\n */\nexport function anchorPagePoint(\n\teditor: Editor,\n\tanchor: TLCommentAnchor\n): { x: number; y: number } | null {\n\tswitch (anchor.type) {\n\t\tcase 'shape': {\n\t\t\tconst shape = editor.getShape(anchor.shapeId as TLShapeId)\n\t\t\tif (!shape) return null\n\t\t\tconst transform = editor.getShapePageTransform(shape)\n\t\t\tif (!transform) return null\n\t\t\tconst { point, size } = editor.getShapeGeometry(shape).bounds\n\t\t\t// Precise pins sit at their stored x/y; imprecise ones at the editor's configured spot.\n\t\t\tconst spot = anchor.isPrecise ? anchor : getCommentingOptions(editor).impreciseShapeAnchor\n\t\t\treturn Mat.applyToPoint(transform, Vec.Add(point, Vec.MulV(spot, size)))\n\t\t}\n\t\tcase 'point':\n\t\t\treturn { x: anchor.x, y: anchor.y }\n\t\tcase 'region':\n\t\t\treturn regionPinPoint(anchor, regionAnchorPinCorner(anchor))\n\t\tcase 'page':\n\t\t\treturn null\n\t}\n}\n\n/**\n * The shape a comment placed at a page point should anchor to, or undefined for empty canvas.\n *\n * Uses the editor's hit-test margin, the same slack select and hover use \u2014 without it, open-path\n * shapes (arrows, lines, draw strokes) are unhittable in practice.\n *\n * `hitFrameInside` lets a click inside a frame's body anchor to the frame, which it otherwise\n * wouldn't (the select-tool convention hits only the edge/label). A child shape under the pointer\n * still wins, so only a frame's empty interior anchors the frame.\n *\n * @internal\n */\nexport function commentTargetShapeAt(editor: Editor, page: VecLike): TLShape | undefined {\n\treturn editor.getShapeAtPoint(page, {\n\t\thitInside: true,\n\t\thitFrameInside: true,\n\t\tmargin: editor.getHitTestMargin(),\n\t})\n}\n\n/**\n * A shape anchor for a page point. `x`/`y` are the point's normalized (0\u20131) offset within the\n * shape's own bounds, taken in the shape's own space, so a pin on a rotated shape records the spot\n * it was dropped on. Remembered either way: when `precise` the pin sits at exactly `x`/`y`,\n * otherwise at the consumer's imprecise default.\n * @public\n */\nexport function shapeAnchorAt(\n\teditor: Editor,\n\tshapeId: TLShapeId,\n\tpage: { x: number; y: number },\n\tprecise: boolean\n): TLCommentAnchor {\n\tconst shape = editor.getShape(shapeId)\n\tconst bounds = shape && editor.getShapeGeometry(shape).bounds\n\tif (!shape || !bounds || bounds.w === 0 || bounds.h === 0) {\n\t\treturn { type: 'shape', shapeId, x: 0.5, y: 0.5, isPrecise: precise }\n\t}\n\tconst local = editor.getPointInShapeSpace(shape, page)\n\treturn {\n\t\ttype: 'shape',\n\t\tshapeId,\n\t\tx: (local.x - bounds.minX) / bounds.w,\n\t\ty: (local.y - bounds.minY) / bounds.h,\n\t\tisPrecise: precise,\n\t}\n}\n\n/** Open a thread and bring it into view \u2014 switch to its page if needed, then center its pin. @public */\nexport function focusThread(editor: Editor, thread: TLCommentThread): void {\n\tif (thread.pageId !== editor.getCurrentPageId()) {\n\t\teditor.setCurrentPage(thread.pageId as any)\n\t}\n\topenThreadId.set(editor, thread.id)\n\tconst point = anchorPagePoint(editor, thread.anchor)\n\tif (!point) return\n\tconst offset = commentCenterScreenOffset(editor) / editor.getZoomLevel()\n\teditor.centerOnPoint({ x: point.x + offset, y: point.y }, { animation: { duration: 200 } })\n}\n\n/** The left inset a nudged pin never crosses, and the gap kept between thread UI and sidebar. */\nconst CENTER_MARGIN_PX = 8\n\n/** How far the open thread UI reaches right of its pin, in screen px: the popover's offset plus\n * the thread panel's fixed width (300px, `.tlui-cmt-thread`). */\nconst THREAD_UI_EXTENT_PX = POPOVER_OFFSET.thread.x + 300\n\n/**\n * How far right of a centered-on pin the true viewport center should sit, in screen px. While the\n * comments sidebar covers the viewport's right edge, dead-centering a pin would put its thread\n * popover under the sidebar \u2014 so centering aims at the middle of the uncovered area instead, never\n * past the viewport's left edge. Zero when the sidebar is closed or not on screen.\n * @internal\n */\nexport function commentCenterScreenOffset(editor: Editor): number {\n\tif (!commentsSidebarOpen.get(editor)) return 0\n\tconst sidebar = editor.getContainer().querySelector('.tlui-cmt-canvas-sidebar')\n\tif (!sidebar) return 0\n\tconst viewport = editor.getViewportScreenBounds()\n\t// Viewport screen bounds are the container's client rect, so this is container-local.\n\tconst sidebarLeft = sidebar.getBoundingClientRect().left - viewport.x\n\tif (sidebarLeft >= viewport.w) return 0\n\t// Aim the pin at the middle of the uncovered area, nudged left until the thread UI clears the\n\t// sidebar \u2014 but never past the left edge (the edge wins when there's no room for both).\n\tconst pinX = Math.max(\n\t\tMath.min(sidebarLeft / 2, sidebarLeft - CENTER_MARGIN_PX - THREAD_UI_EXTENT_PX),\n\t\tCENTER_MARGIN_PX\n\t)\n\treturn viewport.w / 2 - pinX\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -0,0 +1,450 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
var thread_view_exports = {};
|
|
20
|
+
__export(thread_view_exports, {
|
|
21
|
+
POPOVER_OFFSET: () => POPOVER_OFFSET,
|
|
22
|
+
ThreadPopover: () => ThreadPopover,
|
|
23
|
+
ThreadView: () => ThreadView,
|
|
24
|
+
absoluteThreadLink: () => absoluteThreadLink,
|
|
25
|
+
toCardProps: () => toCardProps,
|
|
26
|
+
useResolveName: () => useResolveName
|
|
27
|
+
});
|
|
28
|
+
module.exports = __toCommonJS(thread_view_exports);
|
|
29
|
+
var import_jsx_runtime = require("react/jsx-runtime");
|
|
30
|
+
var import_react = require("react");
|
|
31
|
+
var import_tldraw = require("tldraw");
|
|
32
|
+
var import_comment_card = require("../ui/comment-card");
|
|
33
|
+
var import_comment_composer = require("../ui/comment-composer");
|
|
34
|
+
var import_comment_extensions = require("../ui/comment-extensions");
|
|
35
|
+
var import_comment_thread = require("../ui/comment-thread");
|
|
36
|
+
var import_comment_body = require("./comment-body");
|
|
37
|
+
var import_comment_drafts = require("./comment-drafts");
|
|
38
|
+
var import_comment_mutations = require("./comment-mutations");
|
|
39
|
+
var import_comment_reactions = require("./comment-reactions");
|
|
40
|
+
var import_comment_render = require("./comment-render");
|
|
41
|
+
var import_hooks = require("./hooks");
|
|
42
|
+
var import_mobile_placement = require("./mobile-placement");
|
|
43
|
+
var import_options = require("./options");
|
|
44
|
+
var import_state = require("./state");
|
|
45
|
+
const stop = (e) => e.stopPropagation();
|
|
46
|
+
function useResolveName(resolveAuthor) {
|
|
47
|
+
return (0, import_react.useCallback)((id) => resolveAuthor(id)?.name, [resolveAuthor]);
|
|
48
|
+
}
|
|
49
|
+
const LINK_COPIED_MS = 2e3;
|
|
50
|
+
function absoluteThreadLink(href, base = window.location.href) {
|
|
51
|
+
try {
|
|
52
|
+
return new URL(href, base).toString();
|
|
53
|
+
} catch {
|
|
54
|
+
return href;
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
function useCopyLink(href) {
|
|
58
|
+
const [copied, setCopied] = (0, import_react.useState)(false);
|
|
59
|
+
(0, import_react.useEffect)(() => {
|
|
60
|
+
if (!copied) return;
|
|
61
|
+
const timeout = window.setTimeout(() => setCopied(false), LINK_COPIED_MS);
|
|
62
|
+
return () => window.clearTimeout(timeout);
|
|
63
|
+
}, [copied]);
|
|
64
|
+
const copy = (0, import_react.useCallback)(() => {
|
|
65
|
+
if (href === void 0) return;
|
|
66
|
+
navigator.clipboard?.writeText(absoluteThreadLink(href)).then(
|
|
67
|
+
() => setCopied(true),
|
|
68
|
+
() => setCopied(false)
|
|
69
|
+
);
|
|
70
|
+
}, [href]);
|
|
71
|
+
return [copied, copy];
|
|
72
|
+
}
|
|
73
|
+
function toCardProps(comment, props, components, resolveName) {
|
|
74
|
+
const Body = components.CommentBody;
|
|
75
|
+
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 });
|
|
76
|
+
return {
|
|
77
|
+
author: props.resolveAuthor(comment.authorId) ?? import_comment_render.UNKNOWN_COMMENT_AUTHOR,
|
|
78
|
+
body,
|
|
79
|
+
date: new Date(comment.createdAt).toISOString(),
|
|
80
|
+
you: comment.authorId === props.currentUserId,
|
|
81
|
+
edited: comment.editedAt != null
|
|
82
|
+
};
|
|
83
|
+
}
|
|
84
|
+
const PIN_SIZE = 28;
|
|
85
|
+
const MARKER_SIZE = PIN_SIZE;
|
|
86
|
+
const CARD_TOP_Y = -28;
|
|
87
|
+
const PREVIEW_GAP = 6;
|
|
88
|
+
const POPOVER_OFFSET = {
|
|
89
|
+
thread: { x: PIN_SIZE + PREVIEW_GAP, y: CARD_TOP_Y - PIN_SIZE / 2 },
|
|
90
|
+
list: { x: MARKER_SIZE + PREVIEW_GAP, y: CARD_TOP_Y - MARKER_SIZE / 2 }
|
|
91
|
+
};
|
|
92
|
+
function ThreadPopover({
|
|
93
|
+
base,
|
|
94
|
+
children
|
|
95
|
+
}) {
|
|
96
|
+
const ref = (0, import_react.useRef)(null);
|
|
97
|
+
(0, import_tldraw.usePassThroughWheelEvents)(ref);
|
|
98
|
+
const isMobile = (0, import_mobile_placement.useIsMobileCommenting)();
|
|
99
|
+
const placed = (0, import_mobile_placement.useMobilePlacement)(ref, base, isMobile);
|
|
100
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_tldraw.EditorPortal, { children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
101
|
+
"div",
|
|
102
|
+
{
|
|
103
|
+
ref,
|
|
104
|
+
className: "tlui-cmt-canvas-popover",
|
|
105
|
+
style: { left: placed.left, top: placed.top },
|
|
106
|
+
onPointerDown: stop,
|
|
107
|
+
onContextMenu: stop,
|
|
108
|
+
children
|
|
109
|
+
}
|
|
110
|
+
) });
|
|
111
|
+
}
|
|
112
|
+
const ThreadView = (0, import_react.memo)(function ThreadView2({
|
|
113
|
+
editor,
|
|
114
|
+
thread,
|
|
115
|
+
...props
|
|
116
|
+
}) {
|
|
117
|
+
const {
|
|
118
|
+
currentUserId,
|
|
119
|
+
resolveAuthor,
|
|
120
|
+
onPostComment,
|
|
121
|
+
isCommentUnread,
|
|
122
|
+
onCommentsRead,
|
|
123
|
+
getMentionSuggestions,
|
|
124
|
+
renderMentionSuggestion,
|
|
125
|
+
getThreadHref
|
|
126
|
+
} = props;
|
|
127
|
+
const options = (0, import_options.useCommentingOptions)();
|
|
128
|
+
const comments = (0, import_hooks.useThreadComments)(editor, thread.id);
|
|
129
|
+
const msg = (0, import_tldraw.useTranslation)();
|
|
130
|
+
const resolveName = useResolveName(resolveAuthor);
|
|
131
|
+
const cards = (0, import_react.useMemo)(
|
|
132
|
+
() => comments.map(
|
|
133
|
+
(c) => toCardProps(c, { currentUserId, resolveAuthor }, options.components, resolveName)
|
|
134
|
+
),
|
|
135
|
+
[comments, currentUserId, resolveAuthor, options.components, resolveName]
|
|
136
|
+
);
|
|
137
|
+
const me = currentUserId ? resolveAuthor(currentUserId) : void 0;
|
|
138
|
+
const canComment = (0, import_options.useCanComment)(currentUserId);
|
|
139
|
+
const commentPermissions = (0, import_tldraw.useValue)(
|
|
140
|
+
"comment permissions",
|
|
141
|
+
() => new Map(
|
|
142
|
+
comments.map((comment) => [
|
|
143
|
+
comment.id,
|
|
144
|
+
{
|
|
145
|
+
edit: (0, import_options.getCanModifyComment)(editor, currentUserId, { action: "edit-comment", comment }),
|
|
146
|
+
delete: (0, import_options.getCanModifyComment)(editor, currentUserId, {
|
|
147
|
+
action: "delete-comment",
|
|
148
|
+
comment
|
|
149
|
+
})
|
|
150
|
+
}
|
|
151
|
+
])
|
|
152
|
+
),
|
|
153
|
+
[editor, currentUserId, comments]
|
|
154
|
+
);
|
|
155
|
+
const canModifyThread = (0, import_options.useCanModifyComment)(currentUserId, { action: "delete-thread", thread });
|
|
156
|
+
const canDeleteThread = canComment && canModifyThread;
|
|
157
|
+
const ComposerFallback = options.components.ComposerFallback;
|
|
158
|
+
const [reply, setReply] = (0, import_react.useState)(
|
|
159
|
+
() => (0, import_comment_drafts.getCommentDraft)((0, import_comment_drafts.replyDraftSlot)(thread.id)) ?? import_comment_extensions.EMPTY_COMMENT
|
|
160
|
+
);
|
|
161
|
+
const [editingId, setEditingId] = (0, import_react.useState)(null);
|
|
162
|
+
const [editText, setEditText] = (0, import_react.useState)(import_comment_extensions.EMPTY_COMMENT);
|
|
163
|
+
const canReply = canComment && !thread.resolved;
|
|
164
|
+
const container = (0, import_tldraw.useContainer)();
|
|
165
|
+
const editReturnFocus = (0, import_react.useRef)(null);
|
|
166
|
+
const [focusReply, setFocusReply] = (0, import_react.useState)(false);
|
|
167
|
+
const tabTaken = (0, import_react.useRef)(false);
|
|
168
|
+
const swallowTabUp = (0, import_react.useRef)(false);
|
|
169
|
+
(0, import_react.useEffect)(() => {
|
|
170
|
+
if (!canReply) {
|
|
171
|
+
setFocusReply(false);
|
|
172
|
+
tabTaken.current = false;
|
|
173
|
+
return;
|
|
174
|
+
}
|
|
175
|
+
const doc = container.ownerDocument;
|
|
176
|
+
const onKeyDown = (e) => {
|
|
177
|
+
if (e.key !== "Tab" || e.shiftKey || e.metaKey || e.ctrlKey || e.altKey) return;
|
|
178
|
+
if (e.defaultPrevented || tabTaken.current) return;
|
|
179
|
+
if (e.target !== container && e.target !== doc.body) return;
|
|
180
|
+
tabTaken.current = true;
|
|
181
|
+
swallowTabUp.current = true;
|
|
182
|
+
setFocusReply(true);
|
|
183
|
+
e.preventDefault();
|
|
184
|
+
e.stopPropagation();
|
|
185
|
+
};
|
|
186
|
+
const onKeyUp = (e) => {
|
|
187
|
+
if (e.key !== "Tab" || !swallowTabUp.current) return;
|
|
188
|
+
swallowTabUp.current = false;
|
|
189
|
+
e.preventDefault();
|
|
190
|
+
e.stopPropagation();
|
|
191
|
+
};
|
|
192
|
+
doc.addEventListener("keydown", onKeyDown, true);
|
|
193
|
+
doc.addEventListener("keyup", onKeyUp, true);
|
|
194
|
+
return () => {
|
|
195
|
+
doc.removeEventListener("keydown", onKeyDown, true);
|
|
196
|
+
doc.removeEventListener("keyup", onKeyUp, true);
|
|
197
|
+
};
|
|
198
|
+
}, [canReply, container]);
|
|
199
|
+
(0, import_react.useEffect)(() => {
|
|
200
|
+
if (editingId !== null) return;
|
|
201
|
+
const resolve = editReturnFocus.current;
|
|
202
|
+
editReturnFocus.current = null;
|
|
203
|
+
resolve?.()?.focus();
|
|
204
|
+
}, [editingId]);
|
|
205
|
+
(0, import_react.useEffect)(() => {
|
|
206
|
+
if (!isCommentUnread || !onCommentsRead) return;
|
|
207
|
+
const unreadIds = comments.filter((comment) => isCommentUnread(comment.id)).map((c) => c.id);
|
|
208
|
+
if (unreadIds.length > 0) {
|
|
209
|
+
onCommentsRead(unreadIds);
|
|
210
|
+
}
|
|
211
|
+
}, [comments, isCommentUnread, onCommentsRead]);
|
|
212
|
+
const postReply = () => {
|
|
213
|
+
if ((0, import_comment_extensions.isCommentEmpty)(reply) || !currentUserId) return;
|
|
214
|
+
const comment = (0, import_comment_mutations.commitCommentMutation)(editor, ({ put }) => {
|
|
215
|
+
const comment2 = (0, import_tldraw.createComment)({
|
|
216
|
+
threadId: thread.id,
|
|
217
|
+
pageId: thread.pageId,
|
|
218
|
+
authorId: currentUserId,
|
|
219
|
+
body: reply
|
|
220
|
+
});
|
|
221
|
+
put([comment2]);
|
|
222
|
+
return comment2;
|
|
223
|
+
});
|
|
224
|
+
setReply(import_comment_extensions.EMPTY_COMMENT);
|
|
225
|
+
(0, import_comment_drafts.clearCommentDraft)((0, import_comment_drafts.replyDraftSlot)(thread.id));
|
|
226
|
+
onPostComment?.(comment);
|
|
227
|
+
};
|
|
228
|
+
const toggleResolve = () => {
|
|
229
|
+
if (!currentUserId) return;
|
|
230
|
+
if (thread.resolved) (0, import_comment_mutations.reopenThread)(editor, thread);
|
|
231
|
+
else (0, import_comment_mutations.resolveThread)(editor, thread, currentUserId);
|
|
232
|
+
};
|
|
233
|
+
const removeThread = () => {
|
|
234
|
+
(0, import_comment_mutations.deleteThread)(editor, thread);
|
|
235
|
+
};
|
|
236
|
+
const ThreadActions = options.components.ThreadActions;
|
|
237
|
+
const threadHref = getThreadHref?.(thread.id);
|
|
238
|
+
const [linkCopied, copyThreadLink] = useCopyLink(threadHref);
|
|
239
|
+
const startEdit = (comment, { fromMoreMenu = false } = {}) => {
|
|
240
|
+
const active = container.ownerDocument.activeElement;
|
|
241
|
+
editReturnFocus.current = fromMoreMenu ? () => container.querySelector(`[data-cmt-more-for="${comment.id}"]`) : active instanceof HTMLElement && active !== container && active !== document.body ? () => active.isConnected ? active : null : null;
|
|
242
|
+
setEditingId(comment.id);
|
|
243
|
+
setEditText(comment.body);
|
|
244
|
+
};
|
|
245
|
+
const saveEdit = () => {
|
|
246
|
+
const comment = comments.find((c) => c.id === editingId);
|
|
247
|
+
if (!comment || (0, import_comment_extensions.isCommentEmpty)(editText)) return;
|
|
248
|
+
(0, import_comment_mutations.editComment)(editor, comment, editText);
|
|
249
|
+
setEditingId(null);
|
|
250
|
+
};
|
|
251
|
+
const renderComment = (card, index) => {
|
|
252
|
+
const comment = comments[index];
|
|
253
|
+
const permissions = commentPermissions.get(comment.id);
|
|
254
|
+
if (editingId === comment.id) {
|
|
255
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
256
|
+
"div",
|
|
257
|
+
{
|
|
258
|
+
className: "tlui-cmt-editing",
|
|
259
|
+
onKeyDown: (e) => {
|
|
260
|
+
if (e.key === "Escape") {
|
|
261
|
+
setEditingId(null);
|
|
262
|
+
e.stopPropagation();
|
|
263
|
+
}
|
|
264
|
+
},
|
|
265
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
266
|
+
import_comment_composer.CommentComposer,
|
|
267
|
+
{
|
|
268
|
+
author: card.author,
|
|
269
|
+
placeholder: msg("comments.edit-placeholder"),
|
|
270
|
+
value: editText,
|
|
271
|
+
onChange: setEditText,
|
|
272
|
+
onSubmit: saveEdit,
|
|
273
|
+
sendLabel: msg("comments.save"),
|
|
274
|
+
disabled: (0, import_comment_extensions.isCommentEmpty)(editText),
|
|
275
|
+
getMentionSuggestions,
|
|
276
|
+
renderMentionSuggestion,
|
|
277
|
+
autoFocus: true
|
|
278
|
+
}
|
|
279
|
+
)
|
|
280
|
+
}
|
|
281
|
+
);
|
|
282
|
+
}
|
|
283
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
284
|
+
import_comment_card.CommentCard,
|
|
285
|
+
{
|
|
286
|
+
...card,
|
|
287
|
+
footer: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
288
|
+
import_comment_reactions.CommentReactions,
|
|
289
|
+
{
|
|
290
|
+
comment,
|
|
291
|
+
currentUserId: canComment ? currentUserId : null,
|
|
292
|
+
resolveName
|
|
293
|
+
}
|
|
294
|
+
),
|
|
295
|
+
actions: canComment && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
|
|
296
|
+
(permissions?.edit || permissions?.delete) && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_tldraw.TldrawUiDropdownMenuRoot, { id: `comment-actions-${comment.id}`, children: [
|
|
297
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_tldraw.TldrawUiDropdownMenuTrigger, { children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
298
|
+
import_tldraw.TldrawUiButton,
|
|
299
|
+
{
|
|
300
|
+
type: "icon",
|
|
301
|
+
tooltip: msg("comments.more-options"),
|
|
302
|
+
title: msg("comments.more-options"),
|
|
303
|
+
className: "tlui-cmt-thread__action",
|
|
304
|
+
"data-cmt-more-for": comment.id,
|
|
305
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
306
|
+
import_tldraw.TldrawUiIcon,
|
|
307
|
+
{
|
|
308
|
+
icon: "dots-vertical",
|
|
309
|
+
label: msg("comments.more-options"),
|
|
310
|
+
small: true
|
|
311
|
+
}
|
|
312
|
+
)
|
|
313
|
+
}
|
|
314
|
+
) }),
|
|
315
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
316
|
+
import_tldraw.TldrawUiDropdownMenuContent,
|
|
317
|
+
{
|
|
318
|
+
className: "tlui-cmt-menu",
|
|
319
|
+
side: "bottom",
|
|
320
|
+
align: "start",
|
|
321
|
+
alignOffset: 0,
|
|
322
|
+
sideOffset: 4,
|
|
323
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_tldraw.TldrawUiDropdownMenuGroup, { children: [
|
|
324
|
+
permissions?.edit && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_tldraw.TldrawUiDropdownMenuItem, { children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
325
|
+
"button",
|
|
326
|
+
{
|
|
327
|
+
type: "button",
|
|
328
|
+
className: "tlui-cmt-menu-item",
|
|
329
|
+
onClick: () => startEdit(comment, { fromMoreMenu: true }),
|
|
330
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { children: msg("comments.edit") })
|
|
331
|
+
}
|
|
332
|
+
) }),
|
|
333
|
+
permissions?.delete && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_tldraw.TldrawUiDropdownMenuItem, { children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
334
|
+
"button",
|
|
335
|
+
{
|
|
336
|
+
type: "button",
|
|
337
|
+
className: "tlui-cmt-menu-item tlui-cmt-menu-item--danger",
|
|
338
|
+
onClick: () => (0, import_comment_mutations.deleteComment)(editor, comment),
|
|
339
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { children: msg("action.delete") })
|
|
340
|
+
}
|
|
341
|
+
) })
|
|
342
|
+
] })
|
|
343
|
+
}
|
|
344
|
+
)
|
|
345
|
+
] }),
|
|
346
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_comment_reactions.CommentReactionPicker, { comment, currentUserId })
|
|
347
|
+
] })
|
|
348
|
+
}
|
|
349
|
+
);
|
|
350
|
+
};
|
|
351
|
+
const resolveLabel = msg(thread.resolved ? "comments.reopen" : "comments.resolve");
|
|
352
|
+
const headerActions = /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
|
|
353
|
+
ThreadActions && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ThreadActions, { thread, comments }),
|
|
354
|
+
(threadHref !== void 0 || canDeleteThread) && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_tldraw.TldrawUiDropdownMenuRoot, { id: `comment-thread-actions-${thread.id}`, children: [
|
|
355
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_tldraw.TldrawUiDropdownMenuTrigger, { children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
356
|
+
import_tldraw.TldrawUiButton,
|
|
357
|
+
{
|
|
358
|
+
type: "icon",
|
|
359
|
+
tooltip: msg("comments.more-options"),
|
|
360
|
+
title: msg("comments.more-options"),
|
|
361
|
+
className: "tlui-cmt-thread__action",
|
|
362
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_tldraw.TldrawUiIcon, { icon: "dots-vertical", label: msg("comments.more-options"), small: true })
|
|
363
|
+
}
|
|
364
|
+
) }),
|
|
365
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
366
|
+
import_tldraw.TldrawUiDropdownMenuContent,
|
|
367
|
+
{
|
|
368
|
+
className: "tlui-cmt-menu",
|
|
369
|
+
side: "bottom",
|
|
370
|
+
align: "start",
|
|
371
|
+
alignOffset: 0,
|
|
372
|
+
sideOffset: 4,
|
|
373
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_tldraw.TldrawUiDropdownMenuGroup, { children: [
|
|
374
|
+
threadHref !== void 0 && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_tldraw.TldrawUiDropdownMenuItem, { noClose: true, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", { type: "button", className: "tlui-cmt-menu-item", onClick: copyThreadLink, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { children: msg(linkCopied ? "comments.link-copied" : "comments.copy-link") }) }) }),
|
|
375
|
+
canDeleteThread && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_tldraw.TldrawUiDropdownMenuItem, { children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
376
|
+
"button",
|
|
377
|
+
{
|
|
378
|
+
type: "button",
|
|
379
|
+
className: "tlui-cmt-menu-item tlui-cmt-menu-item--danger",
|
|
380
|
+
onClick: removeThread,
|
|
381
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { children: msg("comments.delete") })
|
|
382
|
+
}
|
|
383
|
+
) })
|
|
384
|
+
] })
|
|
385
|
+
}
|
|
386
|
+
)
|
|
387
|
+
] }),
|
|
388
|
+
canComment && currentUserId && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
389
|
+
import_tldraw.TldrawUiButton,
|
|
390
|
+
{
|
|
391
|
+
type: "icon",
|
|
392
|
+
tooltip: resolveLabel,
|
|
393
|
+
title: resolveLabel,
|
|
394
|
+
className: "tlui-cmt-thread__action",
|
|
395
|
+
onClick: toggleResolve,
|
|
396
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_tldraw.TldrawUiIcon, { icon: "check", label: resolveLabel, small: true })
|
|
397
|
+
}
|
|
398
|
+
),
|
|
399
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
400
|
+
import_tldraw.TldrawUiButton,
|
|
401
|
+
{
|
|
402
|
+
type: "icon",
|
|
403
|
+
tooltip: msg("comments.dismiss"),
|
|
404
|
+
title: msg("comments.dismiss"),
|
|
405
|
+
className: "tlui-cmt-thread__action",
|
|
406
|
+
onClick: () => import_state.openThreadId.set(editor, null),
|
|
407
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_tldraw.TldrawUiIcon, { icon: "cross-2", label: msg("comments.dismiss"), small: true })
|
|
408
|
+
}
|
|
409
|
+
)
|
|
410
|
+
] });
|
|
411
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
412
|
+
import_comment_thread.CommentThread,
|
|
413
|
+
{
|
|
414
|
+
header: msg("comments.thread-title"),
|
|
415
|
+
headerActions,
|
|
416
|
+
renderComment,
|
|
417
|
+
comments: cards,
|
|
418
|
+
resolvedBanner: thread.resolved ? msg("comments.resolved-by").replace(
|
|
419
|
+
"{name}",
|
|
420
|
+
resolveAuthor(thread.resolved.by)?.name ?? import_comment_render.UNKNOWN_AUTHOR
|
|
421
|
+
) : void 0,
|
|
422
|
+
composer: canReply ? {
|
|
423
|
+
author: me ?? import_comment_render.UNKNOWN_COMMENT_AUTHOR,
|
|
424
|
+
placeholder: msg("comments.reply-placeholder"),
|
|
425
|
+
sendLabel: msg("comments.send"),
|
|
426
|
+
value: reply,
|
|
427
|
+
onChange: (value) => {
|
|
428
|
+
setReply(value);
|
|
429
|
+
(0, import_comment_drafts.saveCommentDraft)((0, import_comment_drafts.replyDraftSlot)(thread.id), value);
|
|
430
|
+
},
|
|
431
|
+
onSubmit: postReply,
|
|
432
|
+
// Up in the empty reply box edits the comment directly above it, chat-style —
|
|
433
|
+
// only when you're allowed to edit it (the same gate as the Edit link).
|
|
434
|
+
onArrowUpWhenEmpty: () => {
|
|
435
|
+
const last = comments[comments.length - 1];
|
|
436
|
+
if (last && commentPermissions.get(last.id)?.edit) startEdit(last);
|
|
437
|
+
},
|
|
438
|
+
// No user, no author for the record — dead send button.
|
|
439
|
+
disabled: (0, import_comment_extensions.isCommentEmpty)(reply) || !currentUserId,
|
|
440
|
+
getMentionSuggestions,
|
|
441
|
+
renderMentionSuggestion,
|
|
442
|
+
// Reuses the composer's own focus path, so the caret lands at the end of a
|
|
443
|
+
// restored draft rather than in front of it.
|
|
444
|
+
autoFocus: focusReply
|
|
445
|
+
} : void 0,
|
|
446
|
+
footer: !canComment && !thread.resolved && ComposerFallback ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ComposerFallback, { context: "thread" }) : void 0
|
|
447
|
+
}
|
|
448
|
+
);
|
|
449
|
+
});
|
|
450
|
+
//# sourceMappingURL=thread-view.js.map
|