@tldraw/editor 3.14.0-canary.cbdb3d4e5362 → 3.14.0-canary.d649afc753b1

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 (116) hide show
  1. package/dist-cjs/index.d.ts +59 -46
  2. package/dist-cjs/index.js +3 -1
  3. package/dist-cjs/index.js.map +2 -2
  4. package/dist-cjs/lib/editor/Editor.js +3 -6
  5. package/dist-cjs/lib/editor/Editor.js.map +2 -2
  6. package/dist-cjs/lib/editor/derivations/notVisibleShapes.js +16 -20
  7. package/dist-cjs/lib/editor/derivations/notVisibleShapes.js.map +3 -3
  8. package/dist-cjs/lib/editor/managers/FocusManager.js +2 -0
  9. package/dist-cjs/lib/editor/managers/FocusManager.js.map +2 -2
  10. package/dist-cjs/lib/editor/managers/FontManager.js +5 -1
  11. package/dist-cjs/lib/editor/managers/FontManager.js.map +2 -2
  12. package/dist-cjs/lib/editor/shapes/ShapeUtil.js +8 -0
  13. package/dist-cjs/lib/editor/shapes/ShapeUtil.js.map +2 -2
  14. package/dist-cjs/lib/editor/shapes/group/GroupShapeUtil.js +6 -0
  15. package/dist-cjs/lib/editor/shapes/group/GroupShapeUtil.js.map +2 -2
  16. package/dist-cjs/lib/primitives/Box.js +39 -33
  17. package/dist-cjs/lib/primitives/Box.js.map +2 -2
  18. package/dist-cjs/lib/primitives/Vec.js +13 -8
  19. package/dist-cjs/lib/primitives/Vec.js.map +2 -2
  20. package/dist-cjs/lib/primitives/geometry/Arc2d.js +41 -21
  21. package/dist-cjs/lib/primitives/geometry/Arc2d.js.map +2 -2
  22. package/dist-cjs/lib/primitives/geometry/Circle2d.js +11 -11
  23. package/dist-cjs/lib/primitives/geometry/Circle2d.js.map +2 -2
  24. package/dist-cjs/lib/primitives/geometry/CubicBezier2d.js +13 -16
  25. package/dist-cjs/lib/primitives/geometry/CubicBezier2d.js.map +2 -2
  26. package/dist-cjs/lib/primitives/geometry/CubicSpline2d.js +4 -4
  27. package/dist-cjs/lib/primitives/geometry/CubicSpline2d.js.map +2 -2
  28. package/dist-cjs/lib/primitives/geometry/Edge2d.js +14 -17
  29. package/dist-cjs/lib/primitives/geometry/Edge2d.js.map +2 -2
  30. package/dist-cjs/lib/primitives/geometry/Ellipse2d.js +10 -10
  31. package/dist-cjs/lib/primitives/geometry/Ellipse2d.js.map +2 -2
  32. package/dist-cjs/lib/primitives/geometry/Point2d.js +6 -6
  33. package/dist-cjs/lib/primitives/geometry/Point2d.js.map +2 -2
  34. package/dist-cjs/lib/primitives/geometry/Polygon2d.js +3 -0
  35. package/dist-cjs/lib/primitives/geometry/Polygon2d.js.map +2 -2
  36. package/dist-cjs/lib/primitives/geometry/Polyline2d.js +8 -5
  37. package/dist-cjs/lib/primitives/geometry/Polyline2d.js.map +2 -2
  38. package/dist-cjs/lib/primitives/geometry/Rectangle2d.js +22 -11
  39. package/dist-cjs/lib/primitives/geometry/Rectangle2d.js.map +2 -2
  40. package/dist-cjs/lib/primitives/geometry/Stadium2d.js +22 -22
  41. package/dist-cjs/lib/primitives/geometry/Stadium2d.js.map +2 -2
  42. package/dist-cjs/lib/utils/areShapesContentEqual.js +1 -1
  43. package/dist-cjs/lib/utils/areShapesContentEqual.js.map +2 -2
  44. package/dist-cjs/version.js +3 -3
  45. package/dist-cjs/version.js.map +1 -1
  46. package/dist-esm/index.d.mts +59 -46
  47. package/dist-esm/index.mjs +3 -1
  48. package/dist-esm/index.mjs.map +2 -2
  49. package/dist-esm/lib/editor/Editor.mjs +3 -6
  50. package/dist-esm/lib/editor/Editor.mjs.map +2 -2
  51. package/dist-esm/lib/editor/derivations/notVisibleShapes.mjs +16 -20
  52. package/dist-esm/lib/editor/derivations/notVisibleShapes.mjs.map +3 -3
  53. package/dist-esm/lib/editor/managers/FocusManager.mjs +2 -0
  54. package/dist-esm/lib/editor/managers/FocusManager.mjs.map +2 -2
  55. package/dist-esm/lib/editor/managers/FontManager.mjs +5 -1
  56. package/dist-esm/lib/editor/managers/FontManager.mjs.map +2 -2
  57. package/dist-esm/lib/editor/shapes/ShapeUtil.mjs +8 -0
  58. package/dist-esm/lib/editor/shapes/ShapeUtil.mjs.map +2 -2
  59. package/dist-esm/lib/editor/shapes/group/GroupShapeUtil.mjs +6 -0
  60. package/dist-esm/lib/editor/shapes/group/GroupShapeUtil.mjs.map +2 -2
  61. package/dist-esm/lib/primitives/Box.mjs +39 -33
  62. package/dist-esm/lib/primitives/Box.mjs.map +2 -2
  63. package/dist-esm/lib/primitives/Vec.mjs +13 -8
  64. package/dist-esm/lib/primitives/Vec.mjs.map +2 -2
  65. package/dist-esm/lib/primitives/geometry/Arc2d.mjs +41 -21
  66. package/dist-esm/lib/primitives/geometry/Arc2d.mjs.map +2 -2
  67. package/dist-esm/lib/primitives/geometry/Circle2d.mjs +11 -11
  68. package/dist-esm/lib/primitives/geometry/Circle2d.mjs.map +2 -2
  69. package/dist-esm/lib/primitives/geometry/CubicBezier2d.mjs +13 -16
  70. package/dist-esm/lib/primitives/geometry/CubicBezier2d.mjs.map +2 -2
  71. package/dist-esm/lib/primitives/geometry/CubicSpline2d.mjs +4 -4
  72. package/dist-esm/lib/primitives/geometry/CubicSpline2d.mjs.map +2 -2
  73. package/dist-esm/lib/primitives/geometry/Edge2d.mjs +14 -17
  74. package/dist-esm/lib/primitives/geometry/Edge2d.mjs.map +2 -2
  75. package/dist-esm/lib/primitives/geometry/Ellipse2d.mjs +11 -11
  76. package/dist-esm/lib/primitives/geometry/Ellipse2d.mjs.map +2 -2
  77. package/dist-esm/lib/primitives/geometry/Point2d.mjs +6 -6
  78. package/dist-esm/lib/primitives/geometry/Point2d.mjs.map +2 -2
  79. package/dist-esm/lib/primitives/geometry/Polygon2d.mjs +3 -0
  80. package/dist-esm/lib/primitives/geometry/Polygon2d.mjs.map +2 -2
  81. package/dist-esm/lib/primitives/geometry/Polyline2d.mjs +8 -5
  82. package/dist-esm/lib/primitives/geometry/Polyline2d.mjs.map +2 -2
  83. package/dist-esm/lib/primitives/geometry/Rectangle2d.mjs +22 -11
  84. package/dist-esm/lib/primitives/geometry/Rectangle2d.mjs.map +2 -2
  85. package/dist-esm/lib/primitives/geometry/Stadium2d.mjs +22 -22
  86. package/dist-esm/lib/primitives/geometry/Stadium2d.mjs.map +2 -2
  87. package/dist-esm/lib/utils/areShapesContentEqual.mjs +1 -1
  88. package/dist-esm/lib/utils/areShapesContentEqual.mjs.map +2 -2
  89. package/dist-esm/version.mjs +3 -3
  90. package/dist-esm/version.mjs.map +1 -1
  91. package/package.json +7 -7
  92. package/src/index.ts +1 -0
  93. package/src/lib/editor/Editor.ts +4 -6
  94. package/src/lib/editor/derivations/notVisibleShapes.ts +24 -25
  95. package/src/lib/editor/managers/FocusManager.ts +2 -0
  96. package/src/lib/editor/managers/FontManager.ts +5 -1
  97. package/src/lib/editor/shapes/ShapeUtil.ts +9 -0
  98. package/src/lib/editor/shapes/group/GroupShapeUtil.tsx +8 -0
  99. package/src/lib/primitives/Box.test.ts +588 -7
  100. package/src/lib/primitives/Box.ts +41 -33
  101. package/src/lib/primitives/Vec.test.ts +2 -2
  102. package/src/lib/primitives/Vec.ts +13 -8
  103. package/src/lib/primitives/geometry/Arc2d.ts +42 -23
  104. package/src/lib/primitives/geometry/Circle2d.ts +12 -12
  105. package/src/lib/primitives/geometry/CubicBezier2d.test.ts +5 -0
  106. package/src/lib/primitives/geometry/CubicBezier2d.ts +13 -17
  107. package/src/lib/primitives/geometry/CubicSpline2d.ts +5 -5
  108. package/src/lib/primitives/geometry/Edge2d.ts +14 -18
  109. package/src/lib/primitives/geometry/Ellipse2d.ts +12 -13
  110. package/src/lib/primitives/geometry/Point2d.ts +6 -6
  111. package/src/lib/primitives/geometry/Polygon2d.ts +4 -0
  112. package/src/lib/primitives/geometry/Polyline2d.ts +10 -7
  113. package/src/lib/primitives/geometry/Rectangle2d.ts +24 -11
  114. package/src/lib/primitives/geometry/Stadium2d.ts +22 -23
  115. package/src/lib/utils/areShapesContentEqual.ts +2 -1
  116. package/src/version.ts +3 -3
@@ -1,4 +1,4 @@
1
- const areShapesContentEqual = (a, b) => a.props === b.props && a.meta === b.meta;
1
+ const areShapesContentEqual = (a, b) => a.parentId === b.parentId && a.props === b.props && a.meta === b.meta;
2
2
  export {
3
3
  areShapesContentEqual
4
4
  };
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../src/lib/utils/areShapesContentEqual.ts"],
4
- "sourcesContent": ["import { TLShape } from '@tldraw/tlschema'\n\nexport const areShapesContentEqual = (a: TLShape, b: TLShape) =>\n\ta.props === b.props && a.meta === b.meta\n"],
5
- "mappings": "AAEO,MAAM,wBAAwB,CAAC,GAAY,MACjD,EAAE,UAAU,EAAE,SAAS,EAAE,SAAS,EAAE;",
4
+ "sourcesContent": ["import { TLShape } from '@tldraw/tlschema'\n\n/** @public */\nexport const areShapesContentEqual = (a: TLShape, b: TLShape) =>\n\ta.parentId === b.parentId && a.props === b.props && a.meta === b.meta\n"],
5
+ "mappings": "AAGO,MAAM,wBAAwB,CAAC,GAAY,MACjD,EAAE,aAAa,EAAE,YAAY,EAAE,UAAU,EAAE,SAAS,EAAE,SAAS,EAAE;",
6
6
  "names": []
7
7
  }
@@ -1,8 +1,8 @@
1
- const version = "3.14.0-canary.cbdb3d4e5362";
1
+ const version = "3.14.0-canary.d649afc753b1";
2
2
  const publishDates = {
3
3
  major: "2024-09-13T14:36:29.063Z",
4
- minor: "2025-05-23T14:48:33.705Z",
5
- patch: "2025-05-23T14:48:33.705Z"
4
+ minor: "2025-06-04T16:51:13.993Z",
5
+ patch: "2025-06-04T16:51:13.993Z"
6
6
  };
7
7
  export {
8
8
  publishDates,
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../src/version.ts"],
4
- "sourcesContent": ["// This file is automatically generated by internal/scripts/refresh-assets.ts.\n// Do not edit manually. Or do, I'm a comment, not a cop.\n\nexport const version = '3.14.0-canary.cbdb3d4e5362'\nexport const publishDates = {\n\tmajor: '2024-09-13T14:36:29.063Z',\n\tminor: '2025-05-23T14:48:33.705Z',\n\tpatch: '2025-05-23T14:48:33.705Z',\n}\n"],
4
+ "sourcesContent": ["// This file is automatically generated by internal/scripts/refresh-assets.ts.\n// Do not edit manually. Or do, I'm a comment, not a cop.\n\nexport const version = '3.14.0-canary.d649afc753b1'\nexport const publishDates = {\n\tmajor: '2024-09-13T14:36:29.063Z',\n\tminor: '2025-06-04T16:51:13.993Z',\n\tpatch: '2025-06-04T16:51:13.993Z',\n}\n"],
5
5
  "mappings": "AAGO,MAAM,UAAU;AAChB,MAAM,eAAe;AAAA,EAC3B,OAAO;AAAA,EACP,OAAO;AAAA,EACP,OAAO;AACR;",
6
6
  "names": []
7
7
  }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@tldraw/editor",
3
3
  "description": "A tiny little drawing app (editor).",
4
- "version": "3.14.0-canary.cbdb3d4e5362",
4
+ "version": "3.14.0-canary.d649afc753b1",
5
5
  "author": {
6
6
  "name": "tldraw Inc.",
7
7
  "email": "hello@tldraw.com"
@@ -48,12 +48,12 @@
48
48
  "@tiptap/core": "^2.9.1",
49
49
  "@tiptap/pm": "^2.9.1",
50
50
  "@tiptap/react": "^2.9.1",
51
- "@tldraw/state": "3.14.0-canary.cbdb3d4e5362",
52
- "@tldraw/state-react": "3.14.0-canary.cbdb3d4e5362",
53
- "@tldraw/store": "3.14.0-canary.cbdb3d4e5362",
54
- "@tldraw/tlschema": "3.14.0-canary.cbdb3d4e5362",
55
- "@tldraw/utils": "3.14.0-canary.cbdb3d4e5362",
56
- "@tldraw/validate": "3.14.0-canary.cbdb3d4e5362",
51
+ "@tldraw/state": "3.14.0-canary.d649afc753b1",
52
+ "@tldraw/state-react": "3.14.0-canary.d649afc753b1",
53
+ "@tldraw/store": "3.14.0-canary.d649afc753b1",
54
+ "@tldraw/tlschema": "3.14.0-canary.d649afc753b1",
55
+ "@tldraw/utils": "3.14.0-canary.d649afc753b1",
56
+ "@tldraw/validate": "3.14.0-canary.d649afc753b1",
57
57
  "@types/core-js": "^2.5.8",
58
58
  "@use-gesture/react": "^10.3.1",
59
59
  "classnames": "^2.5.1",
package/src/index.ts CHANGED
@@ -4,6 +4,7 @@ import 'core-js/stable/array/flat-map.js'
4
4
  import 'core-js/stable/array/flat.js'
5
5
  import 'core-js/stable/string/at.js'
6
6
  import 'core-js/stable/string/replace-all.js'
7
+ export { areShapesContentEqual } from './lib/utils/areShapesContentEqual'
7
8
 
8
9
  // eslint-disable-next-line local/no-export-star
9
10
  export * from '@tldraw/state'
@@ -506,6 +506,8 @@ export class Editor extends EventEmitter<TLEventMap> {
506
506
  shape: {
507
507
  afterChange: (shapeBefore, shapeAfter) => {
508
508
  for (const binding of this.getBindingsInvolvingShape(shapeAfter)) {
509
+ if (areShapesContentEqual(shapeBefore, shapeAfter)) continue
510
+
509
511
  invalidBindingTypes.add(binding.type)
510
512
  if (binding.fromId === shapeAfter.id) {
511
513
  this.getBindingUtil(binding).onAfterChangeFromShape?.({
@@ -3715,10 +3717,7 @@ export class Editor extends EventEmitter<TLEventMap> {
3715
3717
  */
3716
3718
  @computed getViewportScreenCenter() {
3717
3719
  const viewportScreenBounds = this.getViewportScreenBounds()
3718
- return new Vec(
3719
- viewportScreenBounds.midX - viewportScreenBounds.minX,
3720
- viewportScreenBounds.midY - viewportScreenBounds.minY
3721
- )
3720
+ return new Vec(viewportScreenBounds.w / 2, viewportScreenBounds.h / 2)
3722
3721
  }
3723
3722
 
3724
3723
  /**
@@ -5796,8 +5795,7 @@ export class Editor extends EventEmitter<TLEventMap> {
5796
5795
  parent: TLParentId | TLPage | TLShape,
5797
5796
  visitor: (id: TLShapeId) => void | false
5798
5797
  ): this {
5799
- const parentId = typeof parent === 'string' ? parent : parent.id
5800
- const children = this.getSortedChildIdsForParent(parentId)
5798
+ const children = this.getSortedChildIdsForParent(parent)
5801
5799
  for (const id of children) {
5802
5800
  if (visitor(id) === false) continue
5803
5801
  this.visitDescendants(id, visitor)
@@ -1,49 +1,48 @@
1
1
  import { computed, isUninitialized } from '@tldraw/state'
2
2
  import { TLShapeId } from '@tldraw/tlschema'
3
- import { Box } from '../../primitives/Box'
4
3
  import { Editor } from '../Editor'
5
4
 
6
- function isShapeNotVisible(editor: Editor, id: TLShapeId, viewportPageBounds: Box): boolean {
7
- const maskedPageBounds = editor.getShapeMaskedPageBounds(id)
8
- // if the shape is fully outside of its parent's clipping bounds...
9
- if (maskedPageBounds === undefined) return true
10
-
11
- // if the shape is fully outside of the viewport page bounds...
12
- return !viewportPageBounds.includes(maskedPageBounds)
5
+ function fromScratch(editor: Editor): Set<TLShapeId> {
6
+ const shapesIds = editor.getCurrentPageShapeIds()
7
+ const viewportPageBounds = editor.getViewportPageBounds()
8
+ const notVisibleShapes = new Set<TLShapeId>()
9
+ shapesIds.forEach((id) => {
10
+ // If the shape is fully outside of the viewport page bounds, add it to the set.
11
+ // We'll ignore masks here, since they're more expensive to compute and the overhead is not worth it.
12
+ const pageBounds = editor.getShapePageBounds(id)
13
+ if (pageBounds === undefined || !viewportPageBounds.includes(pageBounds)) {
14
+ notVisibleShapes.add(id)
15
+ }
16
+ })
17
+ return notVisibleShapes
13
18
  }
14
19
 
15
20
  /**
16
21
  * Incremental derivation of not visible shapes.
17
- * Non visible shapes are shapes outside of the viewport page bounds and shapes outside of parent's clipping bounds.
22
+ * Non visible shapes are shapes outside of the viewport page bounds.
18
23
  *
19
24
  * @param editor - Instance of the tldraw Editor.
20
25
  * @returns Incremental derivation of non visible shapes.
21
26
  */
22
- export const notVisibleShapes = (editor: Editor) => {
23
- function fromScratch(editor: Editor): Set<TLShapeId> {
24
- const shapes = editor.getCurrentPageShapeIds()
25
- const viewportPageBounds = editor.getViewportPageBounds()
26
- const notVisibleShapes = new Set<TLShapeId>()
27
- shapes.forEach((id) => {
28
- if (isShapeNotVisible(editor, id, viewportPageBounds)) {
29
- notVisibleShapes.add(id)
30
- }
31
- })
32
- return notVisibleShapes
33
- }
34
- return computed<Set<TLShapeId>>('notVisibleShapes', (prevValue) => {
27
+ export function notVisibleShapes(editor: Editor) {
28
+ return computed<Set<TLShapeId>>('notVisibleShapes', function updateNotVisibleShapes(prevValue) {
29
+ const nextValue = fromScratch(editor)
30
+
35
31
  if (isUninitialized(prevValue)) {
36
- return fromScratch(editor)
32
+ return nextValue
37
33
  }
38
34
 
39
- const nextValue = fromScratch(editor)
40
-
35
+ // If there are more or less shapes, we know there's a change
41
36
  if (prevValue.size !== nextValue.size) return nextValue
37
+
38
+ // If any of the old shapes are not in the new set, we know there's a change
42
39
  for (const prev of prevValue) {
43
40
  if (!nextValue.has(prev)) {
44
41
  return nextValue
45
42
  }
46
43
  }
44
+
45
+ // If we've made it here, we know that the set is the same
47
46
  return prevValue
48
47
  })
49
48
  }
@@ -58,6 +58,8 @@ export class FocusManager {
58
58
 
59
59
  private handleKeyDown(keyEvent: KeyboardEvent) {
60
60
  const container = this.editor.getContainer()
61
+ if (this.editor.isIn('select.editing_shape')) return
62
+ if (document.activeElement === container && this.editor.getSelectedShapeIds().length > 0) return
61
63
  if (['Tab', 'ArrowUp', 'ArrowDown'].includes(keyEvent.key)) {
62
64
  container.classList.remove('tl-container__no-focus-ring')
63
65
  }
@@ -94,7 +94,11 @@ export class FontManager {
94
94
  const shapeUtil = this.editor.getShapeUtil(shape)
95
95
  return shapeUtil.getFontFaces(shape)
96
96
  },
97
- { areResultsEqual: areArraysShallowEqual, areRecordsEqual: (a, b) => a.props === b.props }
97
+ {
98
+ areResultsEqual: areArraysShallowEqual,
99
+ // @ts-expect-error
100
+ areRecordsEqual: (a, b) => a.props.richText === b.props.richText,
101
+ }
98
102
  )
99
103
 
100
104
  this.shapeFontLoadStateCache = editor.store.createCache<(FontState | null)[], TLShape>(
@@ -240,6 +240,15 @@ export abstract class ShapeUtil<Shape extends TLUnknownShape = TLUnknownShape> {
240
240
  return true
241
241
  }
242
242
 
243
+ /**
244
+ * When the shape is resized, whether the shape's children should also be resized.
245
+ *
246
+ * @public
247
+ */
248
+ canResizeChildren(_shape: Shape): boolean {
249
+ return true
250
+ }
251
+
243
252
  /**
244
253
  * Whether the shape can be edited in read-only mode.
245
254
  *
@@ -20,6 +20,14 @@ export class GroupShapeUtil extends ShapeUtil<TLGroupShape> {
20
20
  return false
21
21
  }
22
22
 
23
+ canResize() {
24
+ return false
25
+ }
26
+
27
+ canResizeChildren() {
28
+ return true
29
+ }
30
+
23
31
  getDefaultProps(): TLGroupShape['props'] {
24
32
  return {}
25
33
  }