@tldraw/editor 5.6.0-next.c4e9c54a816e → 5.6.0-next.f151f7f3ebd6

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.
Files changed (90) hide show
  1. package/dist-cjs/index.d.ts +157 -2
  2. package/dist-cjs/index.js +7 -1
  3. package/dist-cjs/index.js.map +2 -2
  4. package/dist-cjs/lib/TldrawEditor.js +18 -5
  5. package/dist-cjs/lib/TldrawEditor.js.map +3 -3
  6. package/dist-cjs/lib/components/LiveCollaborators.js +3 -3
  7. package/dist-cjs/lib/components/LiveCollaborators.js.map +2 -2
  8. package/dist-cjs/lib/components/default-components/DefaultErrorFallback.js +57 -15
  9. package/dist-cjs/lib/components/default-components/DefaultErrorFallback.js.map +2 -2
  10. package/dist-cjs/lib/config/TLI18n.js +64 -0
  11. package/dist-cjs/lib/config/TLI18n.js.map +7 -0
  12. package/dist-cjs/lib/editor/Editor.js +29 -12
  13. package/dist-cjs/lib/editor/Editor.js.map +2 -2
  14. package/dist-cjs/lib/editor/derivations/shapeIdsInCurrentPage.js +10 -3
  15. package/dist-cjs/lib/editor/derivations/shapeIdsInCurrentPage.js.map +2 -2
  16. package/dist-cjs/lib/editor/managers/EdgeScrollManager/EdgeScrollManager.js +1 -1
  17. package/dist-cjs/lib/editor/managers/EdgeScrollManager/EdgeScrollManager.js.map +2 -2
  18. package/dist-cjs/lib/editor/managers/FontManager/FontManager.js +19 -2
  19. package/dist-cjs/lib/editor/managers/FontManager/FontManager.js.map +2 -2
  20. package/dist-cjs/lib/editor/managers/ScribbleManager/ScribbleManager.js +3 -5
  21. package/dist-cjs/lib/editor/managers/ScribbleManager/ScribbleManager.js.map +2 -2
  22. package/dist-cjs/lib/editor/managers/SpatialIndexManager/SpatialIndexManager.js +7 -1
  23. package/dist-cjs/lib/editor/managers/SpatialIndexManager/SpatialIndexManager.js.map +2 -2
  24. package/dist-cjs/lib/editor/shapes/ShapeUtil.js +17 -0
  25. package/dist-cjs/lib/editor/shapes/ShapeUtil.js.map +2 -2
  26. package/dist-cjs/lib/hooks/useDocumentEvents.js +28 -3
  27. package/dist-cjs/lib/hooks/useDocumentEvents.js.map +2 -2
  28. package/dist-cjs/lib/license/LicenseManager.js +62 -4
  29. package/dist-cjs/lib/license/LicenseManager.js.map +2 -2
  30. package/dist-cjs/lib/options.js +1 -1
  31. package/dist-cjs/lib/options.js.map +1 -1
  32. package/dist-cjs/version.js +3 -3
  33. package/dist-cjs/version.js.map +1 -1
  34. package/dist-esm/index.d.mts +157 -2
  35. package/dist-esm/index.mjs +13 -1
  36. package/dist-esm/index.mjs.map +2 -2
  37. package/dist-esm/lib/TldrawEditor.mjs +18 -5
  38. package/dist-esm/lib/TldrawEditor.mjs.map +2 -2
  39. package/dist-esm/lib/components/LiveCollaborators.mjs +3 -3
  40. package/dist-esm/lib/components/LiveCollaborators.mjs.map +2 -2
  41. package/dist-esm/lib/components/default-components/DefaultErrorFallback.mjs +61 -16
  42. package/dist-esm/lib/components/default-components/DefaultErrorFallback.mjs.map +2 -2
  43. package/dist-esm/lib/config/TLI18n.mjs +44 -0
  44. package/dist-esm/lib/config/TLI18n.mjs.map +7 -0
  45. package/dist-esm/lib/editor/Editor.mjs +29 -12
  46. package/dist-esm/lib/editor/Editor.mjs.map +2 -2
  47. package/dist-esm/lib/editor/derivations/shapeIdsInCurrentPage.mjs +10 -3
  48. package/dist-esm/lib/editor/derivations/shapeIdsInCurrentPage.mjs.map +2 -2
  49. package/dist-esm/lib/editor/managers/EdgeScrollManager/EdgeScrollManager.mjs +1 -1
  50. package/dist-esm/lib/editor/managers/EdgeScrollManager/EdgeScrollManager.mjs.map +2 -2
  51. package/dist-esm/lib/editor/managers/FontManager/FontManager.mjs +20 -3
  52. package/dist-esm/lib/editor/managers/FontManager/FontManager.mjs.map +2 -2
  53. package/dist-esm/lib/editor/managers/ScribbleManager/ScribbleManager.mjs +3 -5
  54. package/dist-esm/lib/editor/managers/ScribbleManager/ScribbleManager.mjs.map +2 -2
  55. package/dist-esm/lib/editor/managers/SpatialIndexManager/SpatialIndexManager.mjs +7 -1
  56. package/dist-esm/lib/editor/managers/SpatialIndexManager/SpatialIndexManager.mjs.map +2 -2
  57. package/dist-esm/lib/editor/shapes/ShapeUtil.mjs +17 -0
  58. package/dist-esm/lib/editor/shapes/ShapeUtil.mjs.map +2 -2
  59. package/dist-esm/lib/hooks/useDocumentEvents.mjs +28 -3
  60. package/dist-esm/lib/hooks/useDocumentEvents.mjs.map +2 -2
  61. package/dist-esm/lib/license/LicenseManager.mjs +62 -4
  62. package/dist-esm/lib/license/LicenseManager.mjs.map +2 -2
  63. package/dist-esm/lib/options.mjs +1 -1
  64. package/dist-esm/lib/options.mjs.map +1 -1
  65. package/dist-esm/version.mjs +3 -3
  66. package/dist-esm/version.mjs.map +1 -1
  67. package/editor.css +2 -1
  68. package/package.json +7 -7
  69. package/src/index.ts +14 -2
  70. package/src/lib/TldrawEditor.tsx +44 -4
  71. package/src/lib/components/LiveCollaborators.tsx +3 -3
  72. package/src/lib/components/default-components/DefaultErrorFallback.tsx +66 -18
  73. package/src/lib/config/TLI18n.test.ts +84 -0
  74. package/src/lib/config/TLI18n.ts +172 -0
  75. package/src/lib/editor/Editor.ts +52 -24
  76. package/src/lib/editor/derivations/shapeIdsInCurrentPage.ts +19 -3
  77. package/src/lib/editor/managers/EdgeScrollManager/EdgeScrollManager.test.ts +17 -0
  78. package/src/lib/editor/managers/EdgeScrollManager/EdgeScrollManager.ts +2 -2
  79. package/src/lib/editor/managers/FontManager/FontManager.test.ts +1 -0
  80. package/src/lib/editor/managers/FontManager/FontManager.ts +26 -3
  81. package/src/lib/editor/managers/HistoryManager/HistoryManager.test.ts +32 -0
  82. package/src/lib/editor/managers/ScribbleManager/ScribbleManager.ts +4 -6
  83. package/src/lib/editor/managers/SpatialIndexManager/SpatialIndexManager.ts +16 -7
  84. package/src/lib/editor/shapes/ShapeUtil.ts +18 -0
  85. package/src/lib/hooks/useDocumentEvents.ts +51 -3
  86. package/src/lib/license/LicenseManager.test.ts +204 -0
  87. package/src/lib/license/LicenseManager.ts +88 -4
  88. package/src/lib/options.ts +1 -1
  89. package/src/lib/test/useDocumentEvents.test.tsx +153 -22
  90. package/src/version.ts +3 -3
@@ -5,6 +5,34 @@ import { Editor } from '../editor/Editor'
5
5
  import { TLKeyboardEventInfo } from '../editor/types/event-types'
6
6
  import { TL_CONTAINER_CLASS, TldrawEditor } from '../TldrawEditor'
7
7
 
8
+ async function renderEditor() {
9
+ let editor!: Editor
10
+ const store = createTLStore({ shapeUtils: [], bindingUtils: [] })
11
+ await act(async () => {
12
+ render(<TldrawEditor store={store} autoFocus onMount={(e) => void (editor = e)} />)
13
+ })
14
+ const container = document.querySelector<HTMLElement>(`.${TL_CONTAINER_CLASS}`)!
15
+ return { editor, container }
16
+ }
17
+
18
+ function keyDown(container: HTMLElement, init: KeyboardEventInit) {
19
+ act(() => {
20
+ container.dispatchEvent(new KeyboardEvent('keydown', { bubbles: true, ...init }))
21
+ })
22
+ }
23
+
24
+ function keyUp(container: HTMLElement, init: KeyboardEventInit) {
25
+ act(() => {
26
+ container.dispatchEvent(new KeyboardEvent('keyup', { bubbles: true, ...init }))
27
+ })
28
+ }
29
+
30
+ function blurWindow() {
31
+ act(() => {
32
+ window.dispatchEvent(new Event('blur'))
33
+ })
34
+ }
35
+
8
36
  describe('useDocumentEvents drop handling', () => {
9
37
  // The container's native drop listener used to stop propagation before the event reached
10
38
  // React's root, so React onDrop handlers inside the canvas never fired.
@@ -33,28 +61,6 @@ describe('useDocumentEvents drop handling', () => {
33
61
  })
34
62
 
35
63
  describe('useDocumentEvents window blur', () => {
36
- async function renderEditor() {
37
- let editor!: Editor
38
- const store = createTLStore({ shapeUtils: [], bindingUtils: [] })
39
- await act(async () => {
40
- render(<TldrawEditor store={store} autoFocus onMount={(e) => void (editor = e)} />)
41
- })
42
- const container = document.querySelector<HTMLElement>(`.${TL_CONTAINER_CLASS}`)!
43
- return { editor, container }
44
- }
45
-
46
- function keyDown(container: HTMLElement, init: KeyboardEventInit) {
47
- act(() => {
48
- container.dispatchEvent(new KeyboardEvent('keydown', { bubbles: true, ...init }))
49
- })
50
- }
51
-
52
- function blurWindow() {
53
- act(() => {
54
- window.dispatchEvent(new Event('blur'))
55
- })
56
- }
57
-
58
64
  afterEach(() => {
59
65
  cleanup()
60
66
  })
@@ -105,3 +111,128 @@ describe('useDocumentEvents window blur', () => {
105
111
  expect(onEvent).not.toHaveBeenCalled()
106
112
  })
107
113
  })
114
+
115
+ // Browsers report `metaKey` as still true on the keyup of Meta itself.
116
+ const metaKeyUp: KeyboardEventInit = { key: 'Meta', code: 'MetaLeft', metaKey: true }
117
+
118
+ describe('useDocumentEvents meta release', () => {
119
+ afterEach(() => {
120
+ cleanup()
121
+ })
122
+
123
+ // macOS never delivers the keyup of a non-modifier key pressed while Meta is held, so the
124
+ // arrow from a Cmd+Arrow shortcut stayed held and the next plain arrow nudged diagonally.
125
+ it('releases keys whose keyup macOS swallowed while Meta was held', async () => {
126
+ const { editor, container } = await renderEditor()
127
+
128
+ keyDown(container, { key: 'Meta', code: 'MetaLeft', metaKey: true })
129
+ keyDown(container, { key: 'ArrowUp', code: 'ArrowUp', metaKey: true })
130
+ expect([...editor.inputs.keys]).toEqual(['MetaLeft', 'ArrowUp'])
131
+
132
+ // no keyup for ArrowUp ever arrives
133
+ keyUp(container, metaKeyUp)
134
+ expect([...editor.inputs.keys]).toEqual([])
135
+ })
136
+
137
+ // A key held from before Meta went down still gets its own keyup, so releasing it here
138
+ // would drop a key the user is still holding.
139
+ it('leaves keys held from before Meta went down', async () => {
140
+ const { editor, container } = await renderEditor()
141
+
142
+ keyDown(container, { key: ' ', code: 'Space' })
143
+ keyDown(container, { key: 'Meta', code: 'MetaLeft', metaKey: true })
144
+ keyUp(container, metaKeyUp)
145
+
146
+ expect([...editor.inputs.keys]).toEqual(['Space'])
147
+ })
148
+
149
+ // That key keeps auto-repeating, and once Cmd is down those repeats carry `metaKey`.
150
+ // Counting them would release a key that is still physically down - and a repeat never
151
+ // puts it back, since the editor treats key_repeat as a noop.
152
+ it('leaves a key that was already repeating when Meta went down', async () => {
153
+ const { editor, container } = await renderEditor()
154
+
155
+ keyDown(container, { key: 'ArrowUp', code: 'ArrowUp' })
156
+ keyDown(container, { key: 'Meta', code: 'MetaLeft', metaKey: true })
157
+ keyDown(container, { key: 'ArrowUp', code: 'ArrowUp', metaKey: true, repeat: true })
158
+ keyUp(container, metaKeyUp)
159
+
160
+ expect([...editor.inputs.keys]).toEqual(['ArrowUp'])
161
+ })
162
+
163
+ // Idle.onKeyUp re-enters shape editing on Enter, so replaying a key_up here stole the
164
+ // focus that cmd+Enter's a11y action had just put on the style toolbar.
165
+ it('does not fire tool key_up handlers for the keys it releases', async () => {
166
+ const { editor, container } = await renderEditor()
167
+ const keyUps: TLKeyboardEventInfo[] = []
168
+ editor.on('event', (info) => {
169
+ if (info.type === 'keyboard' && info.name === 'key_up') keyUps.push(info)
170
+ })
171
+
172
+ keyDown(container, { key: 'Meta', code: 'MetaLeft', metaKey: true })
173
+ keyDown(container, { key: 'Enter', code: 'Enter', metaKey: true })
174
+ keyUp(container, metaKeyUp)
175
+
176
+ expect([...editor.inputs.keys]).toEqual([])
177
+ expect(keyUps.map((info) => info.code)).toEqual(['MetaLeft'])
178
+ })
179
+
180
+ // A still-held modifier keeps its own keyup, and reporting it as up would start the
181
+ // editor's 150ms release: `ShiftLeft` would leave `inputs.keys` and shrink the nudge step.
182
+ it('leaves a still-held modifier alone', async () => {
183
+ const { editor, container } = await renderEditor()
184
+
185
+ keyDown(container, { key: 'Shift', code: 'ShiftLeft', shiftKey: true })
186
+ keyDown(container, { key: 'Meta', code: 'MetaLeft', shiftKey: true, metaKey: true })
187
+ keyDown(container, { key: 'ArrowUp', code: 'ArrowUp', shiftKey: true, metaKey: true })
188
+
189
+ keyUp(container, { ...metaKeyUp, shiftKey: true })
190
+ expect([...editor.inputs.keys]).toEqual(['ShiftLeft'])
191
+
192
+ await act(async () => {
193
+ await new Promise((resolve) => setTimeout(resolve, 200))
194
+ })
195
+ expect([...editor.inputs.keys]).toEqual(['ShiftLeft'])
196
+ expect(editor.inputs.getShiftKey()).toBe(true)
197
+ })
198
+
199
+ // Letting go of Cmd while still holding the arrow: the arrow is dropped as owed a keyup,
200
+ // but it is genuinely down, and its repeats say so. Without this, nudging stopped dead
201
+ // mid-gesture and stayed dead for as long as the key was held.
202
+ it('takes back a dropped key that is still repeating', async () => {
203
+ const { editor, container } = await renderEditor()
204
+
205
+ keyDown(container, { key: 'Meta', code: 'MetaLeft', metaKey: true })
206
+ keyDown(container, { key: 'ArrowUp', code: 'ArrowUp', metaKey: true })
207
+ keyUp(container, metaKeyUp)
208
+ expect([...editor.inputs.keys]).toEqual([])
209
+
210
+ keyDown(container, { key: 'ArrowUp', code: 'ArrowUp', repeat: true })
211
+ expect([...editor.inputs.keys]).toEqual(['ArrowUp'])
212
+ })
213
+
214
+ it('does not disturb keys held without Meta', async () => {
215
+ const { editor, container } = await renderEditor()
216
+
217
+ keyDown(container, { key: 'ArrowUp', code: 'ArrowUp' })
218
+ keyUp(container, { key: 'ArrowUp', code: 'ArrowUp' })
219
+ keyDown(container, { key: 'ArrowRight', code: 'ArrowRight' })
220
+
221
+ expect([...editor.inputs.keys]).toEqual(['ArrowRight'])
222
+ })
223
+
224
+ // Browsers report `metaKey: true` on Meta's own keyup, which left `getMetaKey()` true
225
+ // until some later event happened to report it false.
226
+ it('releases meta itself, though its keyup reports metaKey as still down', async () => {
227
+ const { editor, container } = await renderEditor()
228
+
229
+ keyDown(container, { key: 'Meta', code: 'MetaLeft', metaKey: true })
230
+ expect(editor.inputs.getMetaKey()).toBe(true)
231
+
232
+ keyUp(container, metaKeyUp)
233
+ await act(async () => {
234
+ await new Promise((resolve) => setTimeout(resolve, 200))
235
+ })
236
+ expect(editor.inputs.getMetaKey()).toBe(false)
237
+ })
238
+ })
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.6.0-next.c4e9c54a816e'
4
+ export const version = '5.6.0-next.f151f7f3ebd6'
5
5
  export const publishDates = {
6
6
  major: '2026-05-06T16:28:18.473Z',
7
- minor: '2026-09-30T11:13:01.329Z',
8
- patch: '2026-09-30T11:13:01.329Z',
7
+ minor: '2026-10-23T09:31:31.035Z',
8
+ patch: '2026-10-23T09:31:31.035Z',
9
9
  }