tldraw 3.15.0-canary.d8a8ce37d604 → 3.15.0-canary.db14db4f5395

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 (66) hide show
  1. package/dist-cjs/index.d.ts +84 -77
  2. package/dist-cjs/index.js +30 -31
  3. package/dist-cjs/index.js.map +2 -2
  4. package/dist-cjs/lib/shapes/frame/FrameShapeUtil.js +5 -5
  5. package/dist-cjs/lib/shapes/frame/FrameShapeUtil.js.map +2 -2
  6. package/dist-cjs/lib/shapes/text/TextShapeUtil.js +11 -5
  7. package/dist-cjs/lib/shapes/text/TextShapeUtil.js.map +2 -2
  8. package/dist-cjs/lib/ui/components/KeyboardShortcutsDialog/DefaultKeyboardShortcutsDialogContent.js +1 -11
  9. package/dist-cjs/lib/ui/components/KeyboardShortcutsDialog/DefaultKeyboardShortcutsDialogContent.js.map +2 -2
  10. package/dist-cjs/lib/ui/components/MainMenu/DefaultMainMenuContent.js +0 -1
  11. package/dist-cjs/lib/ui/components/MainMenu/DefaultMainMenuContent.js.map +2 -2
  12. package/dist-cjs/lib/ui/components/menu-items.js +0 -16
  13. package/dist-cjs/lib/ui/components/menu-items.js.map +2 -2
  14. package/dist-cjs/lib/ui/context/actions.js +1 -28
  15. package/dist-cjs/lib/ui/context/actions.js.map +2 -2
  16. package/dist-cjs/lib/ui/context/events.js.map +2 -2
  17. package/dist-cjs/lib/ui/hooks/useClipboardEvents.js +7 -24
  18. package/dist-cjs/lib/ui/hooks/useClipboardEvents.js.map +2 -2
  19. package/dist-cjs/lib/ui/hooks/useKeyboardShortcuts.js +2 -2
  20. package/dist-cjs/lib/ui/hooks/useKeyboardShortcuts.js.map +2 -2
  21. package/dist-cjs/lib/ui/hooks/useTranslation/TLUiTranslationKey.js.map +1 -1
  22. package/dist-cjs/lib/ui/hooks/useTranslation/defaultTranslation.js +0 -4
  23. package/dist-cjs/lib/ui/hooks/useTranslation/defaultTranslation.js.map +2 -2
  24. package/dist-cjs/lib/ui/version.js +3 -3
  25. package/dist-cjs/lib/ui/version.js.map +1 -1
  26. package/dist-esm/index.d.mts +84 -77
  27. package/dist-esm/index.mjs +132 -134
  28. package/dist-esm/index.mjs.map +2 -2
  29. package/dist-esm/lib/shapes/frame/FrameShapeUtil.mjs +5 -5
  30. package/dist-esm/lib/shapes/frame/FrameShapeUtil.mjs.map +2 -2
  31. package/dist-esm/lib/shapes/text/TextShapeUtil.mjs +11 -5
  32. package/dist-esm/lib/shapes/text/TextShapeUtil.mjs.map +2 -2
  33. package/dist-esm/lib/ui/components/KeyboardShortcutsDialog/DefaultKeyboardShortcutsDialogContent.mjs +1 -11
  34. package/dist-esm/lib/ui/components/KeyboardShortcutsDialog/DefaultKeyboardShortcutsDialogContent.mjs.map +2 -2
  35. package/dist-esm/lib/ui/components/MainMenu/DefaultMainMenuContent.mjs +0 -2
  36. package/dist-esm/lib/ui/components/MainMenu/DefaultMainMenuContent.mjs.map +2 -2
  37. package/dist-esm/lib/ui/components/menu-items.mjs +0 -16
  38. package/dist-esm/lib/ui/components/menu-items.mjs.map +2 -2
  39. package/dist-esm/lib/ui/context/actions.mjs +1 -28
  40. package/dist-esm/lib/ui/context/actions.mjs.map +2 -2
  41. package/dist-esm/lib/ui/context/events.mjs.map +2 -2
  42. package/dist-esm/lib/ui/hooks/useClipboardEvents.mjs +7 -24
  43. package/dist-esm/lib/ui/hooks/useClipboardEvents.mjs.map +2 -2
  44. package/dist-esm/lib/ui/hooks/useKeyboardShortcuts.mjs +2 -2
  45. package/dist-esm/lib/ui/hooks/useKeyboardShortcuts.mjs.map +2 -2
  46. package/dist-esm/lib/ui/hooks/useTranslation/defaultTranslation.mjs +0 -4
  47. package/dist-esm/lib/ui/hooks/useTranslation/defaultTranslation.mjs.map +2 -2
  48. package/dist-esm/lib/ui/version.mjs +3 -3
  49. package/dist-esm/lib/ui/version.mjs.map +1 -1
  50. package/package.json +3 -3
  51. package/src/index.ts +158 -159
  52. package/src/lib/shapes/frame/FrameShapeUtil.tsx +7 -5
  53. package/src/lib/shapes/text/TextShapeUtil.tsx +12 -5
  54. package/src/lib/ui/components/KeyboardShortcutsDialog/DefaultKeyboardShortcutsDialogContent.tsx +0 -8
  55. package/src/lib/ui/components/MainMenu/DefaultMainMenuContent.tsx +0 -2
  56. package/src/lib/ui/components/menu-items.tsx +0 -17
  57. package/src/lib/ui/context/actions.tsx +1 -29
  58. package/src/lib/ui/context/events.tsx +0 -2
  59. package/src/lib/ui/hooks/useClipboardEvents.ts +10 -31
  60. package/src/lib/ui/hooks/useKeyboardShortcuts.ts +2 -3
  61. package/src/lib/ui/hooks/useTranslation/TLUiTranslationKey.ts +0 -4
  62. package/src/lib/ui/hooks/useTranslation/defaultTranslation.ts +0 -4
  63. package/src/lib/ui/version.ts +3 -3
  64. package/src/test/Editor.test.tsx +1 -68
  65. package/src/test/commands/clipboard.test.ts +1 -1
  66. package/src/test/editor.test.ts +77 -0
@@ -107,7 +107,6 @@ export interface TLUiEventMap {
107
107
  'toggle-paste-at-cursor': null
108
108
  'toggle-lock': null
109
109
  'toggle-reduce-motion': null
110
- 'toggle-keyboard-shortcuts': null
111
110
  'toggle-edge-scrolling': null
112
111
  'color-scheme': { value: string }
113
112
  'exit-pen-mode': null
@@ -128,7 +127,6 @@ export interface TLUiEventMap {
128
127
  'copy-link': null
129
128
  'image-replace': null
130
129
  'video-replace': null
131
- 'open-kbd-shortcuts': null
132
130
  'rich-text': {
133
131
  operation:
134
132
  | 'bold'
@@ -352,7 +352,7 @@ async function handleClipboardThings(editor: Editor, things: ClipboardThing[], p
352
352
 
353
353
  if (tldrawHtmlComment) {
354
354
  try {
355
- // First try parsing as plain JSON (version 2/3 formats)
355
+ // First try parsing as plain JSON (version 2 format)
356
356
  let json
357
357
  try {
358
358
  json = JSON.parse(tldrawHtmlComment)
@@ -380,32 +380,19 @@ async function handleClipboardThings(editor: Editor, things: ClipboardThing[], p
380
380
  }
381
381
 
382
382
  // Handle versioned clipboard format
383
- if (json.version === 3) {
384
- // Version 3: Assets are plain, decompress only other data
383
+ if (json.version === 2) {
384
+ // Version 2: Assets are plain, decompress only other data
385
385
  try {
386
- const otherData = JSON.parse(
387
- lz.decompressFromBase64(json.data.otherCompressed) || '{}'
388
- )
389
- const reconstructedData = {
390
- assets: json.data.assets || [],
391
- ...otherData,
392
- }
393
-
394
- r({ type: 'tldraw', data: reconstructedData })
386
+ r({ type: 'tldraw', data: json.data })
395
387
  return
396
388
  } catch (error) {
397
389
  r({
398
390
  type: 'error',
399
391
  data: json,
400
- reason: `failed to decompress version 2 clipboard data: ${error}`,
392
+ reason: `failed to parse version 2 clipboard data: ${error}`,
401
393
  })
402
394
  return
403
395
  }
404
- }
405
- if (json.version === 2) {
406
- // Version 2: Everything is plain, this had issues with encoding... :-/
407
- // TODO: nix this support after some time.
408
- r({ type: 'tldraw', data: json.data })
409
396
  } else {
410
397
  // Version 1 or no version: Legacy format
411
398
  if (typeof json.data === 'string') {
@@ -597,21 +584,13 @@ const handleNativeOrMenuCopy = async (editor: Editor) => {
597
584
  return
598
585
  }
599
586
 
600
- // Use versioned clipboard format for better compression
601
- // Version 3: Don't compress assets, only compress other data
602
- const { assets, ...otherData } = content
603
- const clipboardData = {
587
+ // Version 2: Don't compress anything.
588
+ const stringifiedClipboard = JSON.stringify({
604
589
  type: 'application/tldraw',
605
590
  kind: 'content',
606
- version: 3,
607
- data: {
608
- assets: assets || [], // Plain JSON, no compression
609
- otherCompressed: lz.compressToBase64(JSON.stringify(otherData)), // Only compress non-asset data
610
- },
611
- }
612
-
613
- // Don't compress the final structure - just use plain JSON
614
- const stringifiedClipboard = JSON.stringify(clipboardData)
591
+ version: 2,
592
+ data: content,
593
+ })
615
594
 
616
595
  if (typeof navigator === 'undefined') {
617
596
  return
@@ -61,7 +61,7 @@ export function useKeyboardShortcuts() {
61
61
  if (SKIP_KBDS.includes(action.id)) continue
62
62
 
63
63
  hot(getHotkeysStringFromKbd(action.kbd), (event) => {
64
- if (areShortcutsDisabled(editor) && !action.isRequiredA11yAction) return
64
+ if (areShortcutsDisabled(editor)) return
65
65
  preventDefault(event)
66
66
  action.onSelect('kbd')
67
67
  })
@@ -149,8 +149,7 @@ export function areShortcutsDisabled(editor: Editor) {
149
149
  return (
150
150
  editor.menus.hasAnyOpenMenus() ||
151
151
  editor.getEditingShapeId() !== null ||
152
- editor.getCrashingError() ||
153
- !editor.user.getAreKeyboardShortcutsEnabled()
152
+ editor.getCrashingError()
154
153
  )
155
154
  }
156
155
 
@@ -55,7 +55,6 @@ export type TLUiTranslationKey =
55
55
  | 'action.new-project'
56
56
  | 'action.new-shared-project'
57
57
  | 'action.open-cursor-chat'
58
- | 'action.open-kbd-shortcuts'
59
58
  | 'action.open-file'
60
59
  | 'action.pack'
61
60
  | 'action.paste'
@@ -91,8 +90,6 @@ export type TLUiTranslationKey =
91
90
  | 'action.toggle-wrap-mode'
92
91
  | 'action.toggle-reduce-motion.menu'
93
92
  | 'action.toggle-reduce-motion'
94
- | 'action.toggle-keyboard-shortcuts.menu'
95
- | 'action.toggle-keyboard-shortcuts'
96
93
  | 'action.toggle-edge-scrolling.menu'
97
94
  | 'action.toggle-edge-scrolling'
98
95
  | 'action.toggle-debug-mode.menu'
@@ -291,7 +288,6 @@ export type TLUiTranslationKey =
291
288
  | 'a11y.pan-camera'
292
289
  | 'a11y.adjust-shape-styles'
293
290
  | 'a11y.open-context-menu'
294
- | 'a11y.open-keyboard-shortcuts'
295
291
  | 'menu.title'
296
292
  | 'menu.theme'
297
293
  | 'menu.copy-as'
@@ -55,7 +55,6 @@ export const DEFAULT_TRANSLATION = {
55
55
  'action.new-project': 'New project',
56
56
  'action.new-shared-project': 'New shared project',
57
57
  'action.open-cursor-chat': 'Cursor chat',
58
- 'action.open-kbd-shortcuts': 'Open keyboard shortcuts',
59
58
  'action.open-file': 'Open file',
60
59
  'action.pack': 'Pack',
61
60
  'action.paste': 'Paste',
@@ -92,8 +91,6 @@ export const DEFAULT_TRANSLATION = {
92
91
  'action.toggle-wrap-mode': 'Toggle Select on wrap',
93
92
  'action.toggle-reduce-motion.menu': 'Reduce motion',
94
93
  'action.toggle-reduce-motion': 'Toggle reduce motion',
95
- 'action.toggle-keyboard-shortcuts.menu': 'Keyboard shortcuts',
96
- 'action.toggle-keyboard-shortcuts': 'Toggle keyboard shortcuts',
97
94
  'action.toggle-edge-scrolling.menu': 'Edge scrolling',
98
95
  'action.toggle-edge-scrolling': 'Toggle edge scrolling',
99
96
  'action.toggle-debug-mode.menu': 'Debug mode',
@@ -292,7 +289,6 @@ export const DEFAULT_TRANSLATION = {
292
289
  'a11y.pan-camera': 'Pan camera',
293
290
  'a11y.adjust-shape-styles': 'Adjust shape styles',
294
291
  'a11y.open-context-menu': 'Open context menu',
295
- 'a11y.open-keyboard-shortcuts': 'Open keyboard shortcuts',
296
292
  'menu.title': 'Menu',
297
293
  'menu.theme': 'Theme',
298
294
  'menu.copy-as': 'Copy as',
@@ -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 = '3.15.0-canary.d8a8ce37d604'
4
+ export const version = '3.15.0-canary.db14db4f5395'
5
5
  export const publishDates = {
6
6
  major: '2024-09-13T14:36:29.063Z',
7
- minor: '2025-07-10T09:51:55.964Z',
8
- patch: '2025-07-10T09:51:55.964Z',
7
+ minor: '2025-07-03T15:24:41.419Z',
8
+ patch: '2025-07-03T15:24:41.419Z',
9
9
  }
@@ -49,7 +49,7 @@ beforeEach(() => {
49
49
  })
50
50
 
51
51
  const moveShapesToPage2 = () => {
52
- // directly manipulate parentId like would happen in multiplayer situations
52
+ // directly maniuplate parentId like would happen in multiplayer situations
53
53
 
54
54
  editor.updateShapes([
55
55
  { id: ids.box1, type: 'geo', parentId: ids.page2 },
@@ -899,70 +899,3 @@ describe('the geometry cache', () => {
899
899
  expect(editor.getShapePageBounds(A)!.width).toBe(200)
900
900
  })
901
901
  })
902
- describe('editor.getShapePageBounds', () => {
903
- it('calculates axis aligned bounds correctly', () => {
904
- editor.createShape({
905
- type: 'geo',
906
- x: 99,
907
- y: 88,
908
- props: {
909
- w: 199,
910
- h: 188,
911
- },
912
- })
913
- const shape = editor.getLastCreatedShape()
914
- expect(editor.getShapePageBounds(shape)!).toMatchInlineSnapshot(`
915
- Box {
916
- "h": 188,
917
- "w": 199,
918
- "x": 99,
919
- "y": 88,
920
- }
921
- `)
922
- })
923
-
924
- it('calculates rotated bounds correctly', () => {
925
- editor.createShape({
926
- type: 'geo',
927
- x: 99,
928
- y: 88,
929
- rotation: Math.PI / 4,
930
- props: {
931
- w: 199,
932
- h: 188,
933
- },
934
- })
935
- const shape = editor.getLastCreatedShape()
936
- expect(editor.getShapePageBounds(shape)!).toMatchInlineSnapshot(`
937
- Box {
938
- "h": 273.65032431919394,
939
- "w": 273.6503243191939,
940
- "x": -33.93607486307093,
941
- "y": 88,
942
- }
943
- `)
944
- })
945
-
946
- it('calculates bounds based on vertices, not corners', () => {
947
- editor.createShape({
948
- type: 'geo',
949
- x: 99,
950
- y: 88,
951
- rotation: Math.PI / 4,
952
- props: {
953
- geo: 'ellipse',
954
- w: 199,
955
- h: 188,
956
- },
957
- })
958
- const shape = editor.getLastCreatedShape()
959
- expect(editor.getShapePageBounds(shape)!).toMatchInlineSnapshot(`
960
- Box {
961
- "h": 193.49999999999997,
962
- "w": 193.50000000000003,
963
- "x": 6.139087296526014,
964
- "y": 128.07516215959694,
965
- }
966
- `)
967
- })
968
- })
@@ -33,7 +33,7 @@ const doMockClipboard = () => {
33
33
  },
34
34
  })
35
35
 
36
- globalThis.ClipboardItem = jest.fn((payload: any) => payload) as any
36
+ globalThis.ClipboardItem = jest.fn((payload: any) => payload)
37
37
 
38
38
  return context
39
39
  }
@@ -0,0 +1,77 @@
1
+ import { TestEditor } from './TestEditor'
2
+
3
+ describe('editor', () => {
4
+ let editor: TestEditor
5
+
6
+ beforeEach(() => {
7
+ editor = new TestEditor()
8
+ })
9
+
10
+ describe('editor.getShapePageBounds', () => {
11
+ it('calculates axis aligned bounds correctly', () => {
12
+ editor.createShape({
13
+ type: 'geo',
14
+ x: 99,
15
+ y: 88,
16
+ props: {
17
+ w: 199,
18
+ h: 188,
19
+ },
20
+ })
21
+ const shape = editor.getLastCreatedShape()
22
+ expect(editor.getShapePageBounds(shape)!).toMatchInlineSnapshot(`
23
+ Box {
24
+ "h": 188,
25
+ "w": 199,
26
+ "x": 99,
27
+ "y": 88,
28
+ }
29
+ `)
30
+ })
31
+
32
+ it('calculates rotated bounds correctly', () => {
33
+ editor.createShape({
34
+ type: 'geo',
35
+ x: 99,
36
+ y: 88,
37
+ rotation: Math.PI / 4,
38
+ props: {
39
+ w: 199,
40
+ h: 188,
41
+ },
42
+ })
43
+ const shape = editor.getLastCreatedShape()
44
+ expect(editor.getShapePageBounds(shape)!).toMatchInlineSnapshot(`
45
+ Box {
46
+ "h": 273.65032431919394,
47
+ "w": 273.6503243191939,
48
+ "x": -33.93607486307093,
49
+ "y": 88,
50
+ }
51
+ `)
52
+ })
53
+
54
+ it('calculates bounds based on vertices, not corners', () => {
55
+ editor.createShape({
56
+ type: 'geo',
57
+ x: 99,
58
+ y: 88,
59
+ rotation: Math.PI / 4,
60
+ props: {
61
+ geo: 'ellipse',
62
+ w: 199,
63
+ h: 188,
64
+ },
65
+ })
66
+ const shape = editor.getLastCreatedShape()
67
+ expect(editor.getShapePageBounds(shape)!).toMatchInlineSnapshot(`
68
+ Box {
69
+ "h": 193.49999999999997,
70
+ "w": 193.50000000000003,
71
+ "x": 6.139087296526014,
72
+ "y": 128.07516215959694,
73
+ }
74
+ `)
75
+ })
76
+ })
77
+ })