@tldraw/editor 5.2.0-next.b91d4a4551c9 → 5.2.0-next.e2b8d10bf10e
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist-cjs/index.d.ts +5 -7
- package/dist-cjs/index.js +1 -1
- package/dist-cjs/lib/editor/Editor.js +34 -12
- package/dist-cjs/lib/editor/Editor.js.map +3 -3
- package/dist-cjs/lib/editor/managers/ClickManager/ClickManager.js +8 -58
- package/dist-cjs/lib/editor/managers/ClickManager/ClickManager.js.map +2 -2
- package/dist-cjs/lib/editor/managers/FocusManager/FocusManager.js +1 -2
- package/dist-cjs/lib/editor/managers/FocusManager/FocusManager.js.map +2 -2
- package/dist-cjs/lib/editor/tools/StateNode.js.map +2 -2
- package/dist-cjs/lib/editor/types/event-types.js +0 -2
- package/dist-cjs/lib/editor/types/event-types.js.map +2 -2
- package/dist-cjs/version.js +3 -3
- package/dist-cjs/version.js.map +1 -1
- package/dist-esm/index.d.mts +5 -7
- package/dist-esm/index.mjs +1 -1
- package/dist-esm/lib/editor/Editor.mjs +34 -12
- package/dist-esm/lib/editor/Editor.mjs.map +3 -3
- package/dist-esm/lib/editor/managers/ClickManager/ClickManager.mjs +8 -58
- package/dist-esm/lib/editor/managers/ClickManager/ClickManager.mjs.map +2 -2
- package/dist-esm/lib/editor/managers/FocusManager/FocusManager.mjs +1 -2
- package/dist-esm/lib/editor/managers/FocusManager/FocusManager.mjs.map +2 -2
- package/dist-esm/lib/editor/tools/StateNode.mjs.map +2 -2
- package/dist-esm/lib/editor/types/event-types.mjs +0 -2
- package/dist-esm/lib/editor/types/event-types.mjs.map +2 -2
- package/dist-esm/version.mjs +3 -3
- package/dist-esm/version.mjs.map +1 -1
- package/package.json +7 -7
- package/src/lib/editor/Editor.ts +59 -20
- package/src/lib/editor/managers/ClickManager/ClickManager.test.ts +54 -74
- package/src/lib/editor/managers/ClickManager/ClickManager.ts +15 -65
- package/src/lib/editor/managers/FocusManager/FocusManager.test.ts +4 -4
- package/src/lib/editor/managers/FocusManager/FocusManager.ts +1 -2
- package/src/lib/editor/tools/StateNode.ts +0 -2
- package/src/lib/editor/types/event-types.ts +2 -6
- package/src/version.ts +3 -3
|
@@ -122,7 +122,7 @@ describe('ClickManager', () => {
|
|
|
122
122
|
expect(result.type).toBe('click')
|
|
123
123
|
expect(result.name).toBe('double_click')
|
|
124
124
|
expect(result.phase).toBe('down')
|
|
125
|
-
expect(clickManager.clickState).toBe('
|
|
125
|
+
expect(clickManager.clickState).toBe('pendingOverflow')
|
|
126
126
|
})
|
|
127
127
|
|
|
128
128
|
it('should generate double_click up event on pointer_up after double_click down', () => {
|
|
@@ -139,12 +139,34 @@ describe('ClickManager', () => {
|
|
|
139
139
|
expect(result.phase).toBe('up')
|
|
140
140
|
})
|
|
141
141
|
|
|
142
|
-
it('should dispatch double_click settle event after timeout in
|
|
142
|
+
it('should dispatch double_click settle-down event after timeout in pendingOverflow (pointer held)', () => {
|
|
143
143
|
const firstDown = createPointerEvent('pointer_down', { x: 100, y: 100 })
|
|
144
144
|
const secondDown = createPointerEvent('pointer_down', { x: 100, y: 100 })
|
|
145
145
|
|
|
146
146
|
clickManager.handlePointerEvent(firstDown)
|
|
147
147
|
clickManager.handlePointerEvent(secondDown)
|
|
148
|
+
// no pointer_up between or after — pointer is still down at settle time
|
|
149
|
+
|
|
150
|
+
vi.advanceTimersByTime(350)
|
|
151
|
+
|
|
152
|
+
expect(editor.dispatch).toHaveBeenCalledWith(
|
|
153
|
+
expect.objectContaining({
|
|
154
|
+
type: 'click',
|
|
155
|
+
name: 'double_click',
|
|
156
|
+
phase: 'settle-down',
|
|
157
|
+
})
|
|
158
|
+
)
|
|
159
|
+
expect(clickManager.clickState).toBe('idle')
|
|
160
|
+
})
|
|
161
|
+
|
|
162
|
+
it('should dispatch double_click settle-up event after timeout in pendingOverflow (pointer released)', () => {
|
|
163
|
+
const down = createPointerEvent('pointer_down', { x: 100, y: 100 })
|
|
164
|
+
const up = createPointerEvent('pointer_up', { x: 100, y: 100 })
|
|
165
|
+
|
|
166
|
+
clickManager.handlePointerEvent(down)
|
|
167
|
+
clickManager.handlePointerEvent(up)
|
|
168
|
+
clickManager.handlePointerEvent(down)
|
|
169
|
+
clickManager.handlePointerEvent(up)
|
|
148
170
|
|
|
149
171
|
vi.advanceTimersByTime(350)
|
|
150
172
|
|
|
@@ -152,124 +174,84 @@ describe('ClickManager', () => {
|
|
|
152
174
|
expect.objectContaining({
|
|
153
175
|
type: 'click',
|
|
154
176
|
name: 'double_click',
|
|
155
|
-
phase: 'settle',
|
|
177
|
+
phase: 'settle-up',
|
|
156
178
|
})
|
|
157
179
|
)
|
|
158
180
|
expect(clickManager.clickState).toBe('idle')
|
|
159
181
|
})
|
|
160
182
|
})
|
|
161
183
|
|
|
162
|
-
describe('
|
|
163
|
-
it('should
|
|
184
|
+
describe('overflow click handling', () => {
|
|
185
|
+
it('should enter overflow on the third pointer_down without emitting another click', () => {
|
|
164
186
|
const firstDown = createPointerEvent('pointer_down', { x: 100, y: 100 })
|
|
165
187
|
const secondDown = createPointerEvent('pointer_down', { x: 100, y: 100 })
|
|
166
188
|
const thirdDown = createPointerEvent('pointer_down', { x: 100, y: 100 })
|
|
167
189
|
|
|
168
190
|
clickManager.handlePointerEvent(firstDown)
|
|
169
191
|
clickManager.handlePointerEvent(secondDown)
|
|
170
|
-
const result = clickManager.handlePointerEvent(thirdDown)
|
|
192
|
+
const result = clickManager.handlePointerEvent(thirdDown)
|
|
171
193
|
|
|
172
|
-
expect(result
|
|
173
|
-
expect(
|
|
174
|
-
expect(result.phase).toBe('down')
|
|
175
|
-
expect(clickManager.clickState).toBe('pendingQuadruple')
|
|
194
|
+
expect(result).toBe(thirdDown)
|
|
195
|
+
expect(clickManager.clickState).toBe('overflow')
|
|
176
196
|
})
|
|
177
197
|
|
|
178
|
-
it('should
|
|
198
|
+
it('should keep overflow active on further clicks', () => {
|
|
179
199
|
const pointerDown = createPointerEvent('pointer_down', { x: 100, y: 100 })
|
|
180
200
|
|
|
181
201
|
clickManager.handlePointerEvent(pointerDown) // first
|
|
182
202
|
clickManager.handlePointerEvent(pointerDown) // second (double_click)
|
|
183
|
-
clickManager.handlePointerEvent(pointerDown) // third (
|
|
184
|
-
const result = clickManager.handlePointerEvent(pointerDown)
|
|
185
|
-
|
|
186
|
-
expect(result.type).toBe('click')
|
|
187
|
-
expect(result.name).toBe('quadruple_click')
|
|
188
|
-
expect(result.phase).toBe('down')
|
|
189
|
-
expect(clickManager.clickState).toBe('pendingOverflow')
|
|
190
|
-
})
|
|
191
|
-
|
|
192
|
-
it('should handle overflow state after quadruple click', () => {
|
|
193
|
-
const pointerDown = createPointerEvent('pointer_down', { x: 100, y: 100 })
|
|
194
|
-
|
|
195
|
-
clickManager.handlePointerEvent(pointerDown) // first
|
|
196
|
-
clickManager.handlePointerEvent(pointerDown) // second
|
|
197
|
-
clickManager.handlePointerEvent(pointerDown) // third
|
|
198
|
-
clickManager.handlePointerEvent(pointerDown) // fourth
|
|
199
|
-
const result = clickManager.handlePointerEvent(pointerDown) // fifth
|
|
203
|
+
clickManager.handlePointerEvent(pointerDown) // third (overflow)
|
|
204
|
+
const result = clickManager.handlePointerEvent(pointerDown) // fourth
|
|
200
205
|
|
|
201
206
|
expect(result).toBe(pointerDown)
|
|
202
207
|
expect(clickManager.clickState).toBe('overflow')
|
|
203
208
|
})
|
|
204
209
|
|
|
205
|
-
it('should
|
|
206
|
-
const pointerDown = createPointerEvent('pointer_down', { x: 100, y: 100 })
|
|
207
|
-
const pointerUp = createPointerEvent('pointer_up', { x: 100, y: 100 })
|
|
208
|
-
|
|
209
|
-
clickManager.handlePointerEvent(pointerDown) // first
|
|
210
|
-
clickManager.handlePointerEvent(pointerDown) // second
|
|
211
|
-
clickManager.handlePointerEvent(pointerDown) // third
|
|
212
|
-
const result = clickManager.handlePointerEvent(pointerUp) as TLClickEventInfo
|
|
213
|
-
|
|
214
|
-
expect(result.type).toBe('click')
|
|
215
|
-
expect(result.name).toBe('triple_click')
|
|
216
|
-
expect(result.phase).toBe('up')
|
|
217
|
-
})
|
|
218
|
-
|
|
219
|
-
it('should generate quadruple_click up event on pointer_up after quadruple_click down', () => {
|
|
210
|
+
it('should not emit double_click up events while in overflow', () => {
|
|
220
211
|
const pointerDown = createPointerEvent('pointer_down', { x: 100, y: 100 })
|
|
221
212
|
const pointerUp = createPointerEvent('pointer_up', { x: 100, y: 100 })
|
|
222
213
|
|
|
223
214
|
clickManager.handlePointerEvent(pointerDown) // first
|
|
224
215
|
clickManager.handlePointerEvent(pointerDown) // second
|
|
225
216
|
clickManager.handlePointerEvent(pointerDown) // third
|
|
226
|
-
clickManager.handlePointerEvent(
|
|
227
|
-
const result = clickManager.handlePointerEvent(pointerUp) as TLClickEventInfo
|
|
217
|
+
const result = clickManager.handlePointerEvent(pointerUp)
|
|
228
218
|
|
|
229
|
-
expect(result
|
|
230
|
-
expect(
|
|
231
|
-
expect(result.phase).toBe('up')
|
|
219
|
+
expect(result).toBe(pointerUp)
|
|
220
|
+
expect(clickManager.clickState).toBe('overflow')
|
|
232
221
|
})
|
|
233
|
-
})
|
|
234
222
|
|
|
235
|
-
|
|
236
|
-
it('should dispatch triple_click settle event after timeout in pendingQuadruple', () => {
|
|
223
|
+
it('should return to idle after overflow timeout without dispatching a settle event', () => {
|
|
237
224
|
const pointerDown = createPointerEvent('pointer_down', { x: 100, y: 100 })
|
|
238
225
|
|
|
239
226
|
clickManager.handlePointerEvent(pointerDown) // first
|
|
240
227
|
clickManager.handlePointerEvent(pointerDown) // second
|
|
241
|
-
clickManager.handlePointerEvent(pointerDown) // third
|
|
228
|
+
clickManager.handlePointerEvent(pointerDown) // third -> overflow
|
|
242
229
|
|
|
243
230
|
vi.advanceTimersByTime(350)
|
|
244
231
|
|
|
245
|
-
expect(editor.dispatch).
|
|
246
|
-
expect.objectContaining({
|
|
247
|
-
type: 'click',
|
|
248
|
-
name: 'triple_click',
|
|
249
|
-
phase: 'settle',
|
|
250
|
-
})
|
|
251
|
-
)
|
|
232
|
+
expect(editor.dispatch).not.toHaveBeenCalled()
|
|
252
233
|
expect(clickManager.clickState).toBe('idle')
|
|
253
234
|
})
|
|
235
|
+
})
|
|
254
236
|
|
|
255
|
-
|
|
256
|
-
|
|
237
|
+
describe('timeout behavior and settle events', () => {
|
|
238
|
+
it('should track press/release state across the pending window (settle-down then release → settle-up)', () => {
|
|
239
|
+
const down = createPointerEvent('pointer_down', { x: 100, y: 100 })
|
|
240
|
+
const up = createPointerEvent('pointer_up', { x: 100, y: 100 })
|
|
257
241
|
|
|
258
|
-
clickManager.handlePointerEvent(
|
|
259
|
-
clickManager.handlePointerEvent(
|
|
260
|
-
clickManager.handlePointerEvent(
|
|
261
|
-
clickManager.handlePointerEvent(
|
|
242
|
+
clickManager.handlePointerEvent(down)
|
|
243
|
+
clickManager.handlePointerEvent(up)
|
|
244
|
+
clickManager.handlePointerEvent(down) // second press — pointer is down...
|
|
245
|
+
clickManager.handlePointerEvent(up) // ...but released before timeout
|
|
262
246
|
|
|
263
247
|
vi.advanceTimersByTime(350)
|
|
264
248
|
|
|
265
249
|
expect(editor.dispatch).toHaveBeenCalledWith(
|
|
266
250
|
expect.objectContaining({
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
phase: 'settle',
|
|
251
|
+
name: 'double_click',
|
|
252
|
+
phase: 'settle-up',
|
|
270
253
|
})
|
|
271
254
|
)
|
|
272
|
-
expect(clickManager.clickState).toBe('idle')
|
|
273
255
|
})
|
|
274
256
|
|
|
275
257
|
it('should use different timeout durations for different states', () => {
|
|
@@ -316,7 +298,7 @@ describe('ClickManager', () => {
|
|
|
316
298
|
|
|
317
299
|
expect(result.type).toBe('click')
|
|
318
300
|
expect(result.name).toBe('double_click')
|
|
319
|
-
expect(clickManager.clickState).toBe('
|
|
301
|
+
expect(clickManager.clickState).toBe('pendingOverflow')
|
|
320
302
|
})
|
|
321
303
|
})
|
|
322
304
|
|
|
@@ -396,7 +378,7 @@ describe('ClickManager', () => {
|
|
|
396
378
|
|
|
397
379
|
clickManager.handlePointerEvent(pointerDown)
|
|
398
380
|
clickManager.handlePointerEvent(pointerDown) // double click
|
|
399
|
-
expect(clickManager.clickState).toBe('
|
|
381
|
+
expect(clickManager.clickState).toBe('pendingOverflow')
|
|
400
382
|
|
|
401
383
|
clickManager.cancelDoubleClickTimeout()
|
|
402
384
|
|
|
@@ -416,9 +398,7 @@ describe('ClickManager', () => {
|
|
|
416
398
|
// Get to overflow state
|
|
417
399
|
clickManager.handlePointerEvent(pointerDown) // 1
|
|
418
400
|
clickManager.handlePointerEvent(pointerDown) // 2
|
|
419
|
-
clickManager.handlePointerEvent(pointerDown) // 3
|
|
420
|
-
clickManager.handlePointerEvent(pointerDown) // 4
|
|
421
|
-
clickManager.handlePointerEvent(pointerDown) // 5 -> overflow
|
|
401
|
+
clickManager.handlePointerEvent(pointerDown) // 3 -> overflow
|
|
422
402
|
|
|
423
403
|
expect(clickManager.clickState).toBe('overflow')
|
|
424
404
|
|
|
@@ -4,13 +4,7 @@ import type { Editor } from '../../Editor'
|
|
|
4
4
|
import { TLClickEventInfo, TLPointerEventInfo } from '../../types/event-types'
|
|
5
5
|
|
|
6
6
|
/** @public */
|
|
7
|
-
export type TLClickState =
|
|
8
|
-
| 'idle'
|
|
9
|
-
| 'pendingDouble'
|
|
10
|
-
| 'pendingTriple'
|
|
11
|
-
| 'pendingQuadruple'
|
|
12
|
-
| 'pendingOverflow'
|
|
13
|
-
| 'overflow'
|
|
7
|
+
export type TLClickState = 'idle' | 'pendingDouble' | 'pendingOverflow' | 'overflow'
|
|
14
8
|
|
|
15
9
|
const MAX_CLICK_DISTANCE = 40
|
|
16
10
|
|
|
@@ -26,6 +20,8 @@ export class ClickManager {
|
|
|
26
20
|
|
|
27
21
|
private _previousScreenPoint?: Vec
|
|
28
22
|
|
|
23
|
+
private _isPressingWhilePending = false
|
|
24
|
+
|
|
29
25
|
@bind
|
|
30
26
|
_getClickTimeout(state: TLClickState, id = uniqueId()) {
|
|
31
27
|
this._clickId = id
|
|
@@ -34,30 +30,12 @@ export class ClickManager {
|
|
|
34
30
|
() => {
|
|
35
31
|
if (this._clickState === state && this._clickId === id) {
|
|
36
32
|
switch (this._clickState) {
|
|
37
|
-
case 'pendingTriple': {
|
|
38
|
-
this.editor.dispatch({
|
|
39
|
-
...this.lastPointerInfo,
|
|
40
|
-
type: 'click',
|
|
41
|
-
name: 'double_click',
|
|
42
|
-
phase: 'settle',
|
|
43
|
-
})
|
|
44
|
-
break
|
|
45
|
-
}
|
|
46
|
-
case 'pendingQuadruple': {
|
|
47
|
-
this.editor.dispatch({
|
|
48
|
-
...this.lastPointerInfo,
|
|
49
|
-
type: 'click',
|
|
50
|
-
name: 'triple_click',
|
|
51
|
-
phase: 'settle',
|
|
52
|
-
})
|
|
53
|
-
break
|
|
54
|
-
}
|
|
55
33
|
case 'pendingOverflow': {
|
|
56
34
|
this.editor.dispatch({
|
|
57
35
|
...this.lastPointerInfo,
|
|
58
36
|
type: 'click',
|
|
59
|
-
name: '
|
|
60
|
-
phase: 'settle',
|
|
37
|
+
name: 'double_click',
|
|
38
|
+
phase: this._isPressingWhilePending ? 'settle-down' : 'settle-up',
|
|
61
39
|
})
|
|
62
40
|
break
|
|
63
41
|
}
|
|
@@ -100,6 +78,8 @@ export class ClickManager {
|
|
|
100
78
|
if (!this._clickState) return info
|
|
101
79
|
this._clickScreenPoint = Vec.From(info.point)
|
|
102
80
|
|
|
81
|
+
this._isPressingWhilePending = true
|
|
82
|
+
|
|
103
83
|
if (
|
|
104
84
|
this._previousScreenPoint &&
|
|
105
85
|
Vec.Dist2(this._previousScreenPoint, this._clickScreenPoint) > MAX_CLICK_DISTANCE ** 2
|
|
@@ -113,32 +93,12 @@ export class ClickManager {
|
|
|
113
93
|
|
|
114
94
|
switch (this._clickState) {
|
|
115
95
|
case 'pendingDouble': {
|
|
116
|
-
this._clickState = 'pendingTriple'
|
|
117
|
-
this._clickTimeout = this._getClickTimeout(this._clickState)
|
|
118
|
-
return {
|
|
119
|
-
...info,
|
|
120
|
-
type: 'click',
|
|
121
|
-
name: 'double_click',
|
|
122
|
-
phase: 'down',
|
|
123
|
-
}
|
|
124
|
-
}
|
|
125
|
-
case 'pendingTriple': {
|
|
126
|
-
this._clickState = 'pendingQuadruple'
|
|
127
|
-
this._clickTimeout = this._getClickTimeout(this._clickState)
|
|
128
|
-
return {
|
|
129
|
-
...info,
|
|
130
|
-
type: 'click',
|
|
131
|
-
name: 'triple_click',
|
|
132
|
-
phase: 'down',
|
|
133
|
-
}
|
|
134
|
-
}
|
|
135
|
-
case 'pendingQuadruple': {
|
|
136
96
|
this._clickState = 'pendingOverflow'
|
|
137
97
|
this._clickTimeout = this._getClickTimeout(this._clickState)
|
|
138
98
|
return {
|
|
139
99
|
...info,
|
|
140
100
|
type: 'click',
|
|
141
|
-
name: '
|
|
101
|
+
name: 'double_click',
|
|
142
102
|
phase: 'down',
|
|
143
103
|
}
|
|
144
104
|
}
|
|
@@ -159,30 +119,17 @@ export class ClickManager {
|
|
|
159
119
|
}
|
|
160
120
|
case 'pointer_up': {
|
|
161
121
|
if (!this._clickState) return info
|
|
122
|
+
|
|
162
123
|
this._clickScreenPoint = Vec.From(info.point)
|
|
163
124
|
|
|
125
|
+
this._isPressingWhilePending = false
|
|
126
|
+
|
|
164
127
|
switch (this._clickState) {
|
|
165
|
-
case 'pendingTriple': {
|
|
166
|
-
return {
|
|
167
|
-
...this.lastPointerInfo,
|
|
168
|
-
type: 'click',
|
|
169
|
-
name: 'double_click',
|
|
170
|
-
phase: 'up',
|
|
171
|
-
}
|
|
172
|
-
}
|
|
173
|
-
case 'pendingQuadruple': {
|
|
174
|
-
return {
|
|
175
|
-
...this.lastPointerInfo,
|
|
176
|
-
type: 'click',
|
|
177
|
-
name: 'triple_click',
|
|
178
|
-
phase: 'up',
|
|
179
|
-
}
|
|
180
|
-
}
|
|
181
128
|
case 'pendingOverflow': {
|
|
182
129
|
return {
|
|
183
130
|
...this.lastPointerInfo,
|
|
184
131
|
type: 'click',
|
|
185
|
-
name: '
|
|
132
|
+
name: 'double_click',
|
|
186
133
|
phase: 'up',
|
|
187
134
|
}
|
|
188
135
|
}
|
|
@@ -219,5 +166,8 @@ export class ClickManager {
|
|
|
219
166
|
cancelDoubleClickTimeout() {
|
|
220
167
|
this._clickTimeout = clearTimeout(this._clickTimeout)
|
|
221
168
|
this._clickState = 'idle'
|
|
169
|
+
// when a double click is cancelled, we are no longer pending any further
|
|
170
|
+
// clicks, so we set this to false even if the user is still pressing
|
|
171
|
+
this._isPressingWhilePending = false
|
|
222
172
|
}
|
|
223
173
|
}
|
|
@@ -14,7 +14,7 @@ describe('FocusManager', () => {
|
|
|
14
14
|
getInstanceState: Mock
|
|
15
15
|
updateInstanceState: Mock
|
|
16
16
|
getContainer: Mock
|
|
17
|
-
|
|
17
|
+
getEditingShapeId: Mock
|
|
18
18
|
getSelectedShapeIds: Mock
|
|
19
19
|
complete: Mock
|
|
20
20
|
}
|
|
@@ -51,7 +51,7 @@ describe('FocusManager', () => {
|
|
|
51
51
|
updateInstanceState: vi.fn(),
|
|
52
52
|
getContainer: vi.fn(() => mockContainer),
|
|
53
53
|
getContainerDocument: vi.fn(() => document),
|
|
54
|
-
|
|
54
|
+
getEditingShapeId: vi.fn(() => null),
|
|
55
55
|
getSelectedShapeIds: vi.fn(() => []),
|
|
56
56
|
complete: vi.fn(),
|
|
57
57
|
} as any
|
|
@@ -243,7 +243,7 @@ describe('FocusManager', () => {
|
|
|
243
243
|
})
|
|
244
244
|
|
|
245
245
|
it('should return early when editor is in editing mode', () => {
|
|
246
|
-
editor.
|
|
246
|
+
editor.getEditingShapeId.mockReturnValue('shape:1')
|
|
247
247
|
const event = new KeyboardEvent('keydown', { key: 'Tab' })
|
|
248
248
|
|
|
249
249
|
keydownHandler(event)
|
|
@@ -407,7 +407,7 @@ describe('FocusManager', () => {
|
|
|
407
407
|
const keydownCall = addEventListenerCalls.find((call: any) => call[0] === 'keydown')
|
|
408
408
|
const keydownHandler = keydownCall![1]
|
|
409
409
|
|
|
410
|
-
editor.
|
|
410
|
+
editor.getEditingShapeId.mockReturnValue('shape:1') // Editing mode
|
|
411
411
|
|
|
412
412
|
const event = new KeyboardEvent('keydown', { key: 'Tab' })
|
|
413
413
|
keydownHandler(event)
|
|
@@ -63,8 +63,7 @@ export class FocusManager {
|
|
|
63
63
|
const activeEl = container.ownerDocument.activeElement
|
|
64
64
|
// Edit mode should remove the focus ring, however if the active element's
|
|
65
65
|
// parent is the contextual toolbar, then allow it.
|
|
66
|
-
if (this.editor.
|
|
67
|
-
return
|
|
66
|
+
if (this.editor.getEditingShapeId() && !activeEl?.closest('.tlui-contextual-toolbar')) return
|
|
68
67
|
if (activeEl === container && this.editor.getSelectedShapeIds().length > 0) return
|
|
69
68
|
if (['Tab', 'ArrowUp', 'ArrowDown'].includes(keyEvent.key)) {
|
|
70
69
|
container.classList.remove('tl-container__no-focus-ring')
|
|
@@ -268,8 +268,6 @@ export abstract class StateNode implements Partial<TLEventHandlers> {
|
|
|
268
268
|
onLongPress?(info: TLPointerEventInfo): void
|
|
269
269
|
onPointerUp?(info: TLPointerEventInfo): void
|
|
270
270
|
onDoubleClick?(info: TLClickEventInfo): void
|
|
271
|
-
onTripleClick?(info: TLClickEventInfo): void
|
|
272
|
-
onQuadrupleClick?(info: TLClickEventInfo): void
|
|
273
271
|
onRightClick?(info: TLPointerEventInfo): void
|
|
274
272
|
onMiddleClick?(info: TLPointerEventInfo): void
|
|
275
273
|
onKeyDown?(info: TLKeyboardEventInfo): void
|
|
@@ -24,7 +24,7 @@ export type TLPointerEventName =
|
|
|
24
24
|
| 'middle_click'
|
|
25
25
|
|
|
26
26
|
/** @public */
|
|
27
|
-
export type TLCLickEventName = 'double_click'
|
|
27
|
+
export type TLCLickEventName = 'double_click'
|
|
28
28
|
|
|
29
29
|
/** @public */
|
|
30
30
|
export type TLPinchEventName = 'pinch_start' | 'pinch' | 'pinch_end'
|
|
@@ -72,7 +72,7 @@ export type TLClickEventInfo = TLBaseEventInfo & {
|
|
|
72
72
|
point: VecLike
|
|
73
73
|
pointerId: number
|
|
74
74
|
button: number
|
|
75
|
-
phase: 'down' | 'up' | 'settle'
|
|
75
|
+
phase: 'down' | 'up' | 'settle-down' | 'settle-up'
|
|
76
76
|
} & TLPointerEventTarget
|
|
77
77
|
|
|
78
78
|
/** @public */
|
|
@@ -173,8 +173,6 @@ export interface TLEventHandlers {
|
|
|
173
173
|
onLongPress: TLPointerEvent
|
|
174
174
|
onRightClick: TLPointerEvent
|
|
175
175
|
onDoubleClick: TLClickEvent
|
|
176
|
-
onTripleClick: TLClickEvent
|
|
177
|
-
onQuadrupleClick: TLClickEvent
|
|
178
176
|
onMiddleClick: TLPointerEvent
|
|
179
177
|
onPointerUp: TLPointerEvent
|
|
180
178
|
onKeyDown: TLKeyboardEvent
|
|
@@ -206,7 +204,5 @@ export const EVENT_NAME_MAP: Record<
|
|
|
206
204
|
complete: 'onComplete',
|
|
207
205
|
interrupt: 'onInterrupt',
|
|
208
206
|
double_click: 'onDoubleClick',
|
|
209
|
-
triple_click: 'onTripleClick',
|
|
210
|
-
quadruple_click: 'onQuadrupleClick',
|
|
211
207
|
tick: 'onTick',
|
|
212
208
|
}
|
package/src/version.ts
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
// This file is automatically generated by internal/scripts/refresh-assets.ts.
|
|
2
2
|
// Do not edit manually. Or do, I'm a comment, not a cop.
|
|
3
3
|
|
|
4
|
-
export const version = '5.2.0-next.
|
|
4
|
+
export const version = '5.2.0-next.e2b8d10bf10e'
|
|
5
5
|
export const publishDates = {
|
|
6
6
|
major: '2026-05-06T16:28:18.473Z',
|
|
7
|
-
minor: '2026-06-
|
|
8
|
-
patch: '2026-06-
|
|
7
|
+
minor: '2026-06-05T16:06:49.927Z',
|
|
8
|
+
patch: '2026-06-05T16:06:49.927Z',
|
|
9
9
|
}
|