@tldraw/commenting 5.3.0-next.d7d8ced023d5 → 5.3.0-next.dec36c5c2930
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 +85 -87
- package/dist-cjs/canvas/anchor-lifecycle.js +2 -2
- package/dist-cjs/canvas/anchor-lifecycle.js.map +2 -2
- package/dist-cjs/{ui/tooltip-button.js → canvas/canvas-events.js} +16 -13
- 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 +51 -1
- 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-mutations.js +57 -28
- package/dist-cjs/canvas/comment-mutations.js.map +2 -2
- package/dist-cjs/canvas/comment-reactions.js +4 -7
- package/dist-cjs/canvas/comment-reactions.js.map +2 -2
- package/dist-cjs/canvas/comment-render.js +4 -3
- package/dist-cjs/canvas/comment-render.js.map +2 -2
- package/dist-cjs/canvas/comment-store.js.map +2 -2
- package/dist-cjs/canvas/comment-tool.js +12 -7
- package/dist-cjs/canvas/comment-tool.js.map +2 -2
- package/dist-cjs/canvas/comments-filter-menu.js +11 -13
- package/dist-cjs/canvas/comments-filter-menu.js.map +2 -2
- package/dist-cjs/canvas/comments-overflow-menu.js +10 -2
- package/dist-cjs/canvas/comments-overflow-menu.js.map +2 -2
- package/dist-cjs/canvas/comments-overlay.js +81 -871
- package/dist-cjs/canvas/comments-overlay.js.map +3 -3
- package/dist-cjs/canvas/comments-sidebar.js +16 -11
- package/dist-cjs/canvas/comments-sidebar.js.map +2 -2
- package/dist-cjs/canvas/comments-visibility-toggle.js +5 -25
- package/dist-cjs/canvas/comments-visibility-toggle.js.map +2 -2
- package/dist-cjs/canvas/context.js.map +1 -1
- package/dist-cjs/canvas/hooks.js +8 -2
- 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 +39 -1
- package/dist-cjs/canvas/options.js.map +2 -2
- package/dist-cjs/canvas/pending-composer.js +135 -0
- package/dist-cjs/canvas/pending-composer.js.map +7 -0
- package/dist-cjs/canvas/pin-stacking.js +26 -1
- package/dist-cjs/canvas/pin-stacking.js.map +2 -2
- package/dist-cjs/canvas/region-box.js +113 -0
- package/dist-cjs/canvas/region-box.js.map +7 -0
- 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 +41 -49
- package/dist-cjs/canvas/thread-preview.js.map +2 -2
- package/dist-cjs/canvas/thread-stack.js +7 -7
- package/dist-cjs/canvas/thread-stack.js.map +2 -2
- package/dist-cjs/canvas/thread-state.js +15 -0
- package/dist-cjs/canvas/thread-state.js.map +2 -2
- package/dist-cjs/canvas/thread-view.js +120 -67
- package/dist-cjs/canvas/thread-view.js.map +3 -3
- package/dist-cjs/clustering/computeClusterTable.js +2 -2
- 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 +19 -12
- package/dist-cjs/clustering/runtime.js.map +2 -2
- package/dist-cjs/clustering/types.js.map +1 -1
- package/dist-cjs/index.d.ts +326 -203
- package/dist-cjs/index.js +7 -1
- package/dist-cjs/index.js.map +2 -2
- package/dist-cjs/ui/byline.js +5 -3
- package/dist-cjs/ui/byline.js.map +2 -2
- package/dist-cjs/ui/comment-composer.js +2 -18
- package/dist-cjs/ui/comment-composer.js.map +2 -2
- package/dist-cjs/ui/comment-pin.js +2 -15
- package/dist-cjs/ui/comment-pin.js.map +2 -2
- package/dist-cjs/ui/comments-list.js +11 -24
- package/dist-cjs/ui/comments-list.js.map +2 -2
- package/dist-cjs/ui/format-time.js +13 -1
- package/dist-cjs/ui/format-time.js.map +2 -2
- package/dist-cjs/ui/icons.js +138 -0
- package/dist-cjs/ui/icons.js.map +7 -0
- package/dist-cjs/ui/reaction-picker.js +11 -13
- package/dist-cjs/ui/reaction-picker.js.map +2 -2
- package/dist-cjs/ui/reaction.js +3 -4
- package/dist-cjs/ui/reaction.js.map +2 -2
- package/dist-cjs/ui/send-button.js +2 -9
- package/dist-cjs/ui/send-button.js.map +2 -2
- package/dist-cjs/ui/visual-viewport.js +32 -0
- package/dist-cjs/ui/visual-viewport.js.map +7 -0
- package/dist-esm/canvas/anchor-lifecycle.mjs +3 -3
- package/dist-esm/canvas/anchor-lifecycle.mjs.map +2 -2
- 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 +52 -2
- 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-mutations.mjs +57 -28
- package/dist-esm/canvas/comment-mutations.mjs.map +2 -2
- package/dist-esm/canvas/comment-reactions.mjs +5 -12
- package/dist-esm/canvas/comment-reactions.mjs.map +2 -2
- package/dist-esm/canvas/comment-render.mjs +5 -4
- package/dist-esm/canvas/comment-render.mjs.map +2 -2
- package/dist-esm/canvas/comment-store.mjs.map +2 -2
- package/dist-esm/canvas/comment-tool.mjs +12 -7
- package/dist-esm/canvas/comment-tool.mjs.map +2 -2
- package/dist-esm/canvas/comments-filter-menu.mjs +12 -13
- package/dist-esm/canvas/comments-filter-menu.mjs.map +2 -2
- package/dist-esm/canvas/comments-overflow-menu.mjs +11 -2
- package/dist-esm/canvas/comments-overflow-menu.mjs.map +2 -2
- package/dist-esm/canvas/comments-overlay.mjs +58 -879
- package/dist-esm/canvas/comments-overlay.mjs.map +3 -3
- package/dist-esm/canvas/comments-sidebar.mjs +18 -14
- package/dist-esm/canvas/comments-sidebar.mjs.map +2 -2
- package/dist-esm/canvas/comments-visibility-toggle.mjs +5 -25
- package/dist-esm/canvas/comments-visibility-toggle.mjs.map +2 -2
- package/dist-esm/canvas/hooks.mjs +9 -2
- 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 +39 -1
- package/dist-esm/canvas/options.mjs.map +2 -2
- package/dist-esm/canvas/pending-composer.mjs +127 -0
- package/dist-esm/canvas/pending-composer.mjs.map +7 -0
- package/dist-esm/canvas/pin-stacking.mjs +26 -1
- package/dist-esm/canvas/pin-stacking.mjs.map +2 -2
- package/dist-esm/canvas/region-box.mjs +93 -0
- package/dist-esm/canvas/region-box.mjs.map +7 -0
- 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 +42 -49
- package/dist-esm/canvas/thread-preview.mjs.map +2 -2
- package/dist-esm/canvas/thread-stack.mjs +8 -9
- package/dist-esm/canvas/thread-stack.mjs.map +2 -2
- package/dist-esm/canvas/thread-state.mjs +15 -0
- package/dist-esm/canvas/thread-state.mjs.map +2 -2
- package/dist-esm/canvas/thread-view.mjs +131 -72
- package/dist-esm/canvas/thread-view.mjs.map +3 -3
- package/dist-esm/clustering/computeClusterTable.mjs +2 -2
- 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 +19 -12
- package/dist-esm/clustering/runtime.mjs.map +2 -2
- package/dist-esm/index.d.mts +326 -203
- package/dist-esm/index.mjs +16 -3
- package/dist-esm/index.mjs.map +2 -2
- package/dist-esm/ui/byline.mjs +6 -4
- package/dist-esm/ui/byline.mjs.map +2 -2
- package/dist-esm/ui/comment-composer.mjs +2 -18
- package/dist-esm/ui/comment-composer.mjs.map +2 -2
- package/dist-esm/ui/comment-pin.mjs +2 -15
- package/dist-esm/ui/comment-pin.mjs.map +2 -2
- package/dist-esm/ui/comments-list.mjs +10 -23
- package/dist-esm/ui/comments-list.mjs.map +2 -2
- package/dist-esm/ui/format-time.mjs +13 -1
- package/dist-esm/ui/format-time.mjs.map +2 -2
- package/dist-esm/ui/icons.mjs +118 -0
- package/dist-esm/ui/icons.mjs.map +7 -0
- package/dist-esm/ui/reaction-picker.mjs +12 -13
- package/dist-esm/ui/reaction-picker.mjs.map +2 -2
- package/dist-esm/ui/reaction.mjs +3 -4
- package/dist-esm/ui/reaction.mjs.map +2 -2
- package/dist-esm/ui/send-button.mjs +2 -9
- 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 +7 -6
- package/src/canvas/anchor-lifecycle.test.ts +2 -2
- package/src/canvas/anchor-lifecycle.ts +25 -39
- package/src/canvas/canvas-events.ts +18 -0
- package/src/canvas/canvas.css +5 -11
- package/src/canvas/cluster-badge.tsx +133 -0
- package/src/canvas/cluster-fade.ts +102 -0
- package/src/canvas/cluster-input.test.ts +148 -14
- package/src/canvas/cluster-input.ts +92 -5
- package/src/canvas/cluster-model.ts +378 -0
- package/src/canvas/comment-mutations.test.ts +46 -4
- package/src/canvas/comment-mutations.ts +115 -104
- package/src/canvas/comment-reactions.test.ts +22 -0
- package/src/canvas/comment-reactions.tsx +33 -32
- package/src/canvas/comment-render.ts +8 -8
- package/src/canvas/comment-store.ts +12 -17
- package/src/canvas/comment-tool.test.ts +109 -4
- package/src/canvas/comment-tool.tsx +31 -19
- package/src/canvas/comments-filter-menu.tsx +10 -17
- package/src/canvas/comments-overflow-menu.tsx +8 -3
- package/src/canvas/comments-overlay.tsx +160 -1345
- package/src/canvas/comments-sidebar.tsx +40 -19
- package/src/canvas/comments-visibility-toggle.tsx +6 -30
- package/src/canvas/context.ts +4 -3
- package/src/canvas/hooks.test.ts +94 -0
- package/src/canvas/hooks.ts +17 -3
- package/src/canvas/license.ts +1 -1
- package/src/canvas/mobile-placement.ts +115 -0
- package/src/canvas/options.test.ts +124 -2
- package/src/canvas/options.ts +192 -58
- package/src/canvas/pending-composer.tsx +161 -0
- package/src/canvas/pin-stacking.test.ts +111 -1
- package/src/canvas/pin-stacking.ts +46 -0
- package/src/canvas/region-box.tsx +124 -0
- package/src/canvas/state.ts +20 -28
- package/src/canvas/thread-pin.tsx +419 -0
- package/src/canvas/thread-preview.tsx +77 -87
- package/src/canvas/thread-stack.tsx +19 -29
- package/src/canvas/thread-state.test.ts +51 -0
- package/src/canvas/thread-state.ts +56 -23
- package/src/canvas/thread-view.test.ts +72 -0
- package/src/canvas/thread-view.tsx +231 -133
- package/src/clustering/computeClusterTable.ts +12 -3
- package/src/clustering/replay.test.ts +0 -7
- package/src/clustering/replay.ts +131 -32
- package/src/clustering/runtime.test.ts +50 -6
- package/src/clustering/runtime.ts +42 -39
- package/src/clustering/schedule.test.ts +0 -6
- package/src/clustering/screen-offsets.test.ts +171 -0
- package/src/clustering/types.ts +10 -0
- package/src/index.ts +15 -2
- package/src/ui/byline.tsx +16 -6
- package/src/ui/comment-composer.tsx +25 -69
- package/src/ui/comment-pin.tsx +3 -16
- package/src/ui/comments-list.tsx +40 -29
- package/src/ui/comments.css +80 -76
- package/src/ui/format-time.test.ts +69 -0
- package/src/ui/format-time.ts +22 -2
- package/src/ui/icons.tsx +138 -0
- package/src/ui/reaction-picker.tsx +9 -16
- package/src/ui/reaction.tsx +10 -6
- package/src/ui/send-button.tsx +3 -8
- package/src/ui/visual-viewport.test.ts +36 -0
- package/src/ui/visual-viewport.ts +27 -0
- package/dist-cjs/ui/tooltip-button.js.map +0 -7
- package/dist-esm/ui/tooltip-button.mjs +0 -12
- package/dist-esm/ui/tooltip-button.mjs.map +0 -7
- package/src/ui/tooltip-button.tsx +0 -20
|
@@ -13,6 +13,7 @@ import {
|
|
|
13
13
|
} from 'tldraw'
|
|
14
14
|
import { afterEach, beforeEach, describe, expect, it } from 'vitest'
|
|
15
15
|
import { CommentTool } from './comment-tool'
|
|
16
|
+
import { commentsSidebarOpen, pendingComment, regionDraft } from './state'
|
|
16
17
|
|
|
17
18
|
/**
|
|
18
19
|
* Pointer-driven tests for the comment tool's placement affordances. These need a real editor
|
|
@@ -90,14 +91,80 @@ describe('comment tool placement hints', () => {
|
|
|
90
91
|
driver.pointerMove(150, 125)
|
|
91
92
|
expect(editor.getHintingShapeIds()).toEqual([id])
|
|
92
93
|
|
|
93
|
-
//
|
|
94
|
-
|
|
95
|
-
driver.pointerUp(150, 125)
|
|
96
|
-
expect(editor.isIn('select')).toBe(true)
|
|
94
|
+
// Select owns its own hover state, so the comment hint leaves with the tool.
|
|
95
|
+
editor.setCurrentTool('select')
|
|
97
96
|
expect(editor.getHintingShapeIds()).toEqual([])
|
|
98
97
|
})
|
|
99
98
|
})
|
|
100
99
|
|
|
100
|
+
describe('comment tool placement lifecycle', () => {
|
|
101
|
+
let driver: Driver
|
|
102
|
+
|
|
103
|
+
beforeEach(() => {
|
|
104
|
+
driver = makeEditor()
|
|
105
|
+
})
|
|
106
|
+
|
|
107
|
+
it('stays in the tool with the composer open after placing', () => {
|
|
108
|
+
editor.setCurrentTool('comment')
|
|
109
|
+
driver.pointerDown(400, 300)
|
|
110
|
+
driver.pointerUp(400, 300)
|
|
111
|
+
// Placement opens the composer but the interaction isn't over — the tool holds on until
|
|
112
|
+
// the comment is posted or dismissed, so the surrounding UI stays stable.
|
|
113
|
+
expect(editor.isIn('comment.idle')).toBe(true)
|
|
114
|
+
expect(pendingComment.get(editor)).toEqual({
|
|
115
|
+
anchor: { type: 'point', x: 400, y: 300 },
|
|
116
|
+
point: { x: 400, y: 300 },
|
|
117
|
+
})
|
|
118
|
+
})
|
|
119
|
+
|
|
120
|
+
it('re-places the composer on a second click', () => {
|
|
121
|
+
editor.setCurrentTool('comment')
|
|
122
|
+
driver.pointerDown(400, 300)
|
|
123
|
+
driver.pointerUp(400, 300)
|
|
124
|
+
driver.pointerDown(200, 200)
|
|
125
|
+
driver.pointerUp(200, 200)
|
|
126
|
+
expect(editor.isIn('comment.idle')).toBe(true)
|
|
127
|
+
expect(pendingComment.get(editor)).toEqual({
|
|
128
|
+
anchor: { type: 'point', x: 200, y: 200 },
|
|
129
|
+
point: { x: 200, y: 200 },
|
|
130
|
+
})
|
|
131
|
+
})
|
|
132
|
+
|
|
133
|
+
it('drops the pending composer when the tool exits', () => {
|
|
134
|
+
editor.setCurrentTool('comment')
|
|
135
|
+
driver.pointerDown(400, 300)
|
|
136
|
+
driver.pointerUp(400, 300)
|
|
137
|
+
expect(pendingComment.get(editor)).not.toBeNull()
|
|
138
|
+
|
|
139
|
+
// A direct tool switch (toolbar, shortcut) abandons the draft composer — it belongs to
|
|
140
|
+
// the tool. The text itself survives in the comment draft store.
|
|
141
|
+
editor.setCurrentTool('select')
|
|
142
|
+
expect(pendingComment.get(editor)).toBeNull()
|
|
143
|
+
})
|
|
144
|
+
|
|
145
|
+
it('closes the comments sidebar for the whole interaction', () => {
|
|
146
|
+
commentsSidebarOpen.set(editor, true)
|
|
147
|
+
editor.setCurrentTool('comment')
|
|
148
|
+
expect(commentsSidebarOpen.get(editor)).toBe(false)
|
|
149
|
+
|
|
150
|
+
// ...and placing doesn't reopen it: the tool (and the closed sidebar) hold through the
|
|
151
|
+
// composer. Reopening is the host's button, never a side effect of leaving the tool.
|
|
152
|
+
driver.pointerDown(400, 300)
|
|
153
|
+
driver.pointerUp(400, 300)
|
|
154
|
+
expect(editor.isIn('comment.idle')).toBe(true)
|
|
155
|
+
expect(commentsSidebarOpen.get(editor)).toBe(false)
|
|
156
|
+
})
|
|
157
|
+
|
|
158
|
+
it('escape leaves the tool for select and drops the draft', () => {
|
|
159
|
+
editor.setCurrentTool('comment')
|
|
160
|
+
driver.pointerDown(400, 300)
|
|
161
|
+
driver.pointerUp(400, 300)
|
|
162
|
+
editor.cancel()
|
|
163
|
+
expect(editor.isIn('select')).toBe(true)
|
|
164
|
+
expect(pendingComment.get(editor)).toBeNull()
|
|
165
|
+
})
|
|
166
|
+
})
|
|
167
|
+
|
|
101
168
|
describe('comment tool placement hints with regions enabled', () => {
|
|
102
169
|
it('clears the hint when a drag becomes a region', () => {
|
|
103
170
|
const driver = makeEditor(CommentTool.configure({ enableRegions: true }))
|
|
@@ -113,6 +180,44 @@ describe('comment tool placement hints with regions enabled', () => {
|
|
|
113
180
|
expect(editor.isIn('comment.dragging')).toBe(true)
|
|
114
181
|
expect(editor.getHintingShapeIds()).toEqual([])
|
|
115
182
|
})
|
|
183
|
+
|
|
184
|
+
it('stays in the tool with the composer open after a region drag', () => {
|
|
185
|
+
const driver = makeEditor(CommentTool.configure({ enableRegions: true }))
|
|
186
|
+
editor.setCurrentTool('comment')
|
|
187
|
+
driver.pointerDown(100, 100)
|
|
188
|
+
driver.pointerMove(200, 180)
|
|
189
|
+
driver.pointerUp(200, 180)
|
|
190
|
+
expect(editor.isIn('comment.idle')).toBe(true)
|
|
191
|
+
expect(pendingComment.get(editor)).toEqual({
|
|
192
|
+
anchor: { type: 'region', x: 100, y: 100, w: 100, h: 80, pinX: 1, pinY: 1 },
|
|
193
|
+
point: { x: 200, y: 180 },
|
|
194
|
+
})
|
|
195
|
+
})
|
|
196
|
+
|
|
197
|
+
it('does not hint a shape under the pin corner of a placed region', () => {
|
|
198
|
+
const driver = makeEditor(CommentTool.configure({ enableRegions: true }))
|
|
199
|
+
makeShape(100, 100)
|
|
200
|
+
editor.setCurrentTool('comment')
|
|
201
|
+
// Release on top of the shape: a region anchors to its rectangle, so the outline that
|
|
202
|
+
// normally previews a shape anchor would be a lie here.
|
|
203
|
+
driver.pointerDown(50, 50)
|
|
204
|
+
driver.pointerMove(150, 125)
|
|
205
|
+
driver.pointerUp(150, 125)
|
|
206
|
+
expect(editor.isIn('comment.idle')).toBe(true)
|
|
207
|
+
expect(editor.getHintingShapeIds()).toEqual([])
|
|
208
|
+
})
|
|
209
|
+
|
|
210
|
+
it('drops the region draft when the tool exits mid-drag', () => {
|
|
211
|
+
const driver = makeEditor(CommentTool.configure({ enableRegions: true }))
|
|
212
|
+
editor.setCurrentTool('comment')
|
|
213
|
+
driver.pointerDown(100, 100)
|
|
214
|
+
driver.pointerMove(200, 180)
|
|
215
|
+
expect(regionDraft.get(editor)).not.toBeNull()
|
|
216
|
+
|
|
217
|
+
// A direct tool switch (shortcut, toolbar) mid-drag must not strand the drawn rectangle.
|
|
218
|
+
editor.setCurrentTool('select')
|
|
219
|
+
expect(regionDraft.get(editor)).toBeNull()
|
|
220
|
+
})
|
|
116
221
|
})
|
|
117
222
|
|
|
118
223
|
describe('comment tool anchoring to frames', () => {
|
|
@@ -49,11 +49,12 @@ export function regionBetween(a: VecLike, b: VecLike): BoxModel {
|
|
|
49
49
|
}
|
|
50
50
|
|
|
51
51
|
/**
|
|
52
|
-
* The comment tool. Pressing down opens the comment composer
|
|
53
|
-
*
|
|
54
|
-
*
|
|
55
|
-
*
|
|
56
|
-
*
|
|
52
|
+
* The comment tool. Pressing down opens the comment composer at the pointer and it follows until
|
|
53
|
+
* release — like placing a sticky note — settling on a point, or on a shape when released over one.
|
|
54
|
+
* With region comments enabled, dragging past the threshold draws a region rectangle instead.
|
|
55
|
+
* Placement only opens a composer; the records are created when the comment is posted. The tool
|
|
56
|
+
* stays active while the composer is open — posting returns to select, and clicking elsewhere
|
|
57
|
+
* re-places the composer.
|
|
57
58
|
* @public
|
|
58
59
|
*/
|
|
59
60
|
export class CommentTool extends StateNode {
|
|
@@ -99,8 +100,11 @@ export class CommentTool extends StateNode {
|
|
|
99
100
|
|
|
100
101
|
override onExit() {
|
|
101
102
|
// Drop the hover hint painted while pointing at shapes (see CommentIdle). The cursor resets
|
|
102
|
-
// when the next tool takes over.
|
|
103
|
+
// when the next tool takes over. The draft composer and region draft belong to the tool, so
|
|
104
|
+
// they leave with it; the draft's text survives in the comment draft store.
|
|
103
105
|
this.editor.setHintingShapes([])
|
|
106
|
+
pendingComment.set(this.editor, null)
|
|
107
|
+
regionDraft.set(this.editor, null)
|
|
104
108
|
}
|
|
105
109
|
|
|
106
110
|
// Escape leaves the tool, like the built-in tools (the editor dispatches `cancel` on Escape).
|
|
@@ -123,10 +127,16 @@ class CommentIdle extends StateNode {
|
|
|
123
127
|
override onEnter() {
|
|
124
128
|
// Back to hovering: restore the pin cursor (a prior placing state may have hidden it).
|
|
125
129
|
this.editor.setCursor({ type: 'comment', rotation: 0 })
|
|
126
|
-
|
|
130
|
+
// With a region composer open, a shape outline under its pin corner would imply a shape
|
|
131
|
+
// anchor the region will never use — and it would stick, since moves over the composer
|
|
132
|
+
// never reach the canvas. Point placements keep the hint: it previews the next click.
|
|
133
|
+
if (pendingComment.get(this.editor)?.anchor.type === 'region') {
|
|
134
|
+
this.editor.setHintingShapes([])
|
|
135
|
+
} else {
|
|
136
|
+
updateAnchorHint(this.editor)
|
|
137
|
+
}
|
|
127
138
|
}
|
|
128
139
|
|
|
129
|
-
// Hint the shape a click would attach to.
|
|
130
140
|
override onPointerMove() {
|
|
131
141
|
updateAnchorHint(this.editor)
|
|
132
142
|
}
|
|
@@ -187,8 +197,10 @@ class CommentPointing extends StateNode {
|
|
|
187
197
|
)
|
|
188
198
|
: { type: 'point', x: point.x, y: point.y }
|
|
189
199
|
pendingComment.set(editor, { anchor, point: { x: point.x, y: point.y } })
|
|
190
|
-
//
|
|
191
|
-
|
|
200
|
+
// Stay in the tool while the composer is open — the interaction isn't over until the
|
|
201
|
+
// comment is posted or dismissed, and staying keeps the surrounding UI (style panel,
|
|
202
|
+
// sidebar) from churning mid-placement.
|
|
203
|
+
this.parent.transition('idle')
|
|
192
204
|
}
|
|
193
205
|
|
|
194
206
|
override onCancel() {
|
|
@@ -199,9 +211,9 @@ class CommentPointing extends StateNode {
|
|
|
199
211
|
this.cancel()
|
|
200
212
|
}
|
|
201
213
|
|
|
202
|
-
// Abandon the follow composer if placement is interrupted (Escape, focus loss, etc.).
|
|
214
|
+
// Abandon the follow composer if placement is interrupted (Escape, focus loss, etc.). The
|
|
215
|
+
// tool's onExit drops the draft.
|
|
203
216
|
private cancel() {
|
|
204
|
-
pendingComment.set(this.editor, null)
|
|
205
217
|
this.editor.setCurrentTool('select')
|
|
206
218
|
}
|
|
207
219
|
}
|
|
@@ -210,10 +222,9 @@ class CommentDragging extends StateNode {
|
|
|
210
222
|
static override id = 'dragging'
|
|
211
223
|
|
|
212
224
|
override onEnter() {
|
|
213
|
-
// A region drag supersedes the point-follow composer opened in `pointing`. Show a crosshair
|
|
214
|
-
//
|
|
215
|
-
//
|
|
216
|
-
// rectangle, so a single-shape outline under the dashed box would be stale.
|
|
225
|
+
// A region drag supersedes the point-follow composer opened in `pointing`. Show a crosshair again,
|
|
226
|
+
// since the composer no longer stands in for the pointer, and drop the placement hint — a region
|
|
227
|
+
// anchors to its rectangle, so a single-shape outline would be stale.
|
|
217
228
|
pendingComment.set(this.editor, null)
|
|
218
229
|
this.editor.setHintingShapes([])
|
|
219
230
|
this.editor.setCursor({ type: 'cross', rotation: 0 })
|
|
@@ -237,7 +248,8 @@ class CommentDragging extends StateNode {
|
|
|
237
248
|
anchor: { type: 'region', ...region, pinX: pin.x, pinY: pin.y },
|
|
238
249
|
point: regionPinPoint(region, pin),
|
|
239
250
|
})
|
|
240
|
-
|
|
251
|
+
// Same as the point placement: the tool stays active while the composer is open.
|
|
252
|
+
this.parent.transition('idle')
|
|
241
253
|
}
|
|
242
254
|
|
|
243
255
|
override onCancel() {
|
|
@@ -256,8 +268,8 @@ class CommentDragging extends StateNode {
|
|
|
256
268
|
)
|
|
257
269
|
}
|
|
258
270
|
|
|
271
|
+
// The tool's onExit drops the region draft.
|
|
259
272
|
private cancel() {
|
|
260
|
-
regionDraft.set(this.editor, null)
|
|
261
273
|
this.editor.setCurrentTool('select')
|
|
262
274
|
}
|
|
263
275
|
}
|
|
@@ -266,7 +278,7 @@ class CommentDragging extends StateNode {
|
|
|
266
278
|
export const commentTools = [CommentTool]
|
|
267
279
|
|
|
268
280
|
/** Registers the comment tool in the UI (icon, label, shortcut). Compose into your overrides.
|
|
269
|
-
* Once registered, tldraw's `
|
|
281
|
+
* Once registered, tldraw's `DefaultQuickActionsContent` shows the comment button.
|
|
270
282
|
* @public */
|
|
271
283
|
export const commentToolOverrides: TLUiOverrides = {
|
|
272
284
|
tools(editor, tools) {
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import {
|
|
2
|
+
TldrawUiButton,
|
|
2
3
|
TldrawUiDropdownMenuContent,
|
|
3
4
|
TldrawUiDropdownMenuRoot,
|
|
4
5
|
TldrawUiDropdownMenuTrigger,
|
|
@@ -9,7 +10,7 @@ import {
|
|
|
9
10
|
useTranslation,
|
|
10
11
|
useValue,
|
|
11
12
|
} from 'tldraw'
|
|
12
|
-
import {
|
|
13
|
+
import { MoreMenuIcon } from '../ui/icons'
|
|
13
14
|
import { SidebarFilters } from './sidebar-filters'
|
|
14
15
|
import { sidebarFilters } from './state'
|
|
15
16
|
|
|
@@ -37,9 +38,14 @@ export function CommentsFilterMenu({
|
|
|
37
38
|
return (
|
|
38
39
|
<TldrawUiDropdownMenuRoot id="comments-filter">
|
|
39
40
|
<TldrawUiDropdownMenuTrigger>
|
|
40
|
-
<
|
|
41
|
-
|
|
42
|
-
|
|
41
|
+
<TldrawUiButton
|
|
42
|
+
type="icon"
|
|
43
|
+
tooltip={msg('comments.filter')}
|
|
44
|
+
title={msg('comments.filter')}
|
|
45
|
+
className="tlui-cmt-header-btn"
|
|
46
|
+
>
|
|
47
|
+
<MoreMenuIcon />
|
|
48
|
+
</TldrawUiButton>
|
|
43
49
|
</TldrawUiDropdownMenuTrigger>
|
|
44
50
|
{/* No tlui-cmt-menu here: the rows are tldraw menu items, which carry their own insets —
|
|
45
51
|
the extra padding would set this menu apart from the canvas menus it should match. */}
|
|
@@ -80,16 +86,3 @@ export function CommentsFilterMenu({
|
|
|
80
86
|
</TldrawUiDropdownMenuRoot>
|
|
81
87
|
)
|
|
82
88
|
}
|
|
83
|
-
|
|
84
|
-
function FilterIcon() {
|
|
85
|
-
return (
|
|
86
|
-
<svg width="15" height="15" viewBox="0 0 15 15" fill="none" aria-hidden="true">
|
|
87
|
-
<path
|
|
88
|
-
d="M5.5 3C4.67157 3 4 3.67157 4 4.5C4 5.32843 4.67157 6 5.5 6C6.32843 6 7 5.32843 7 4.5C7 3.67157 6.32843 3 5.5 3ZM3 5C3.01671 5 3.03323 4.99918 3.04952 4.99758C3.28022 6.1399 4.28967 7 5.5 7C6.71033 7 7.71978 6.1399 7.95048 4.99758C7.96677 4.99918 7.98329 5 8 5H13.5C13.7761 5 14 4.77614 14 4.5C14 4.22386 13.7761 4 13.5 4H8C7.98329 4 7.96677 4.00082 7.95048 4.00242C7.71978 2.86009 6.71033 2 5.5 2C4.28967 2 3.28022 2.86009 3.04952 4.00242C3.03323 4.00082 3.01671 4 3 4H1.5C1.22386 4 1 4.22386 1 4.5C1 4.77614 1.22386 5 1.5 5H3ZM11.9505 10.9976C11.7198 12.1399 10.7103 13 9.5 13C8.28967 13 7.28022 12.1399 7.04952 10.9976C7.03323 10.9992 7.01671 11 7 11H1.5C1.22386 11 1 10.7761 1 10.5C1 10.2239 1.22386 10 1.5 10H7C7.01671 10 7.03323 10.0008 7.04952 10.0024C7.28022 8.8601 8.28967 8 9.5 8C10.7103 8 11.7198 8.8601 11.9505 10.0024C11.9668 10.0008 11.9833 10 12 10H13.5C13.7761 10 14 10.2239 14 10.5C14 10.7761 13.7761 11 13.5 11H12C11.9833 11 11.9668 10.9992 11.9505 10.9976ZM8 10.5C8 9.67157 8.67157 9 9.5 9C10.3284 9 11 9.67157 11 10.5C11 11.3284 10.3284 12 9.5 12C8.67157 12 8 11.3284 8 10.5Z"
|
|
89
|
-
fill="currentColor"
|
|
90
|
-
fillRule="evenodd"
|
|
91
|
-
clipRule="evenodd"
|
|
92
|
-
/>
|
|
93
|
-
</svg>
|
|
94
|
-
)
|
|
95
|
-
}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import {
|
|
2
|
+
TldrawUiButton,
|
|
2
3
|
TldrawUiDropdownMenuContent,
|
|
3
4
|
TldrawUiDropdownMenuGroup,
|
|
4
5
|
TldrawUiDropdownMenuItem,
|
|
@@ -9,7 +10,6 @@ import {
|
|
|
9
10
|
useTranslation,
|
|
10
11
|
useValue,
|
|
11
12
|
} from 'tldraw'
|
|
12
|
-
import { TooltipButton } from '../ui/tooltip-button'
|
|
13
13
|
import { commentsHidden, toggleCommentsHidden } from './state'
|
|
14
14
|
|
|
15
15
|
// A keyboard-shortcut glyph, not translatable copy — kept out of JSX as a constant.
|
|
@@ -26,9 +26,14 @@ export function CommentsOverflowMenu() {
|
|
|
26
26
|
return (
|
|
27
27
|
<TldrawUiDropdownMenuRoot id="comments-overflow">
|
|
28
28
|
<TldrawUiDropdownMenuTrigger>
|
|
29
|
-
<
|
|
29
|
+
<TldrawUiButton
|
|
30
|
+
type="icon"
|
|
31
|
+
tooltip={msg('comments.more-options')}
|
|
32
|
+
title={msg('comments.more-options')}
|
|
33
|
+
className="tlui-cmt-header-btn"
|
|
34
|
+
>
|
|
30
35
|
<TldrawUiIcon icon="dots-vertical" label={msg('comments.more-options')} small />
|
|
31
|
-
</
|
|
36
|
+
</TldrawUiButton>
|
|
32
37
|
</TldrawUiDropdownMenuTrigger>
|
|
33
38
|
<TldrawUiDropdownMenuContent
|
|
34
39
|
className="tlui-cmt-menu"
|