@tldraw/editor 4.3.0-canary.fd6b7f2a8adc → 4.3.0-next.2b3bfbba757b

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 (48) hide show
  1. package/dist-cjs/index.d.ts +35 -55
  2. package/dist-cjs/index.js +1 -1
  3. package/dist-cjs/lib/editor/Editor.js +12 -1
  4. package/dist-cjs/lib/editor/Editor.js.map +2 -2
  5. package/dist-cjs/lib/editor/bindings/BindingUtil.js.map +2 -2
  6. package/dist-cjs/lib/editor/derivations/bindingsIndex.js.map +2 -2
  7. package/dist-cjs/lib/editor/managers/SnapManager/SnapManager.js.map +2 -2
  8. package/dist-cjs/lib/editor/shapes/BaseBoxShapeUtil.js.map +1 -1
  9. package/dist-cjs/lib/editor/shapes/ShapeUtil.js.map +2 -2
  10. package/dist-cjs/lib/editor/shapes/group/GroupShapeUtil.js.map +2 -2
  11. package/dist-cjs/lib/editor/tools/BaseBoxShapeTool/BaseBoxShapeTool.js.map +2 -2
  12. package/dist-cjs/lib/editor/tools/BaseBoxShapeTool/children/Pointing.js.map +2 -2
  13. package/dist-cjs/lib/exports/getSvgJsx.js.map +2 -2
  14. package/dist-cjs/lib/utils/reparenting.js.map +2 -2
  15. package/dist-cjs/version.js +3 -3
  16. package/dist-cjs/version.js.map +1 -1
  17. package/dist-esm/index.d.mts +35 -55
  18. package/dist-esm/index.mjs +1 -1
  19. package/dist-esm/lib/editor/Editor.mjs +12 -1
  20. package/dist-esm/lib/editor/Editor.mjs.map +2 -2
  21. package/dist-esm/lib/editor/bindings/BindingUtil.mjs.map +2 -2
  22. package/dist-esm/lib/editor/derivations/bindingsIndex.mjs.map +2 -2
  23. package/dist-esm/lib/editor/managers/SnapManager/SnapManager.mjs.map +2 -2
  24. package/dist-esm/lib/editor/shapes/BaseBoxShapeUtil.mjs.map +1 -1
  25. package/dist-esm/lib/editor/shapes/ShapeUtil.mjs.map +2 -2
  26. package/dist-esm/lib/editor/shapes/group/GroupShapeUtil.mjs.map +2 -2
  27. package/dist-esm/lib/editor/tools/BaseBoxShapeTool/BaseBoxShapeTool.mjs.map +2 -2
  28. package/dist-esm/lib/editor/tools/BaseBoxShapeTool/children/Pointing.mjs.map +2 -2
  29. package/dist-esm/lib/exports/getSvgJsx.mjs.map +2 -2
  30. package/dist-esm/lib/utils/reparenting.mjs.map +2 -2
  31. package/dist-esm/version.mjs +3 -3
  32. package/dist-esm/version.mjs.map +1 -1
  33. package/package.json +10 -10
  34. package/src/lib/editor/Editor.test.ts +10 -10
  35. package/src/lib/editor/Editor.ts +59 -82
  36. package/src/lib/editor/bindings/BindingUtil.ts +9 -15
  37. package/src/lib/editor/derivations/bindingsIndex.ts +2 -2
  38. package/src/lib/editor/managers/FontManager/FontManager.test.ts +4 -14
  39. package/src/lib/editor/managers/SnapManager/SnapManager.ts +3 -3
  40. package/src/lib/editor/shapes/BaseBoxShapeUtil.tsx +2 -2
  41. package/src/lib/editor/shapes/ShapeUtil.ts +8 -5
  42. package/src/lib/editor/shapes/group/GroupShapeUtil.tsx +3 -1
  43. package/src/lib/editor/tools/BaseBoxShapeTool/BaseBoxShapeTool.ts +1 -2
  44. package/src/lib/editor/tools/BaseBoxShapeTool/children/Pointing.ts +3 -3
  45. package/src/lib/exports/getSvgJsx.test.ts +19 -10
  46. package/src/lib/exports/getSvgJsx.tsx +5 -2
  47. package/src/lib/utils/reparenting.ts +5 -5
  48. package/src/version.ts +3 -3
@@ -1,15 +1,9 @@
1
- import {
2
- RecordProps,
3
- TLBinding,
4
- TLPropsMigrations,
5
- TLShape,
6
- TLUnknownBinding,
7
- } from '@tldraw/tlschema'
1
+ import { RecordProps, TLPropsMigrations, TLShape, TLUnknownBinding } from '@tldraw/tlschema'
8
2
  import { Editor } from '../Editor'
9
3
 
10
4
  /** @public */
11
5
  export interface TLBindingUtilConstructor<
12
- T extends TLBinding,
6
+ T extends TLUnknownBinding,
13
7
  U extends BindingUtil<T> = BindingUtil<T>,
14
8
  > {
15
9
  new (editor: Editor): U
@@ -26,7 +20,7 @@ export interface TLBindingUtilConstructor<
26
20
  *
27
21
  * @public
28
22
  */
29
- export interface BindingOnCreateOptions<Binding extends TLBinding = TLBinding> {
23
+ export interface BindingOnCreateOptions<Binding extends TLUnknownBinding> {
30
24
  /** The binding being created. */
31
25
  binding: Binding
32
26
  }
@@ -37,7 +31,7 @@ export interface BindingOnCreateOptions<Binding extends TLBinding = TLBinding> {
37
31
  *
38
32
  * @public
39
33
  */
40
- export interface BindingOnChangeOptions<Binding extends TLBinding = TLBinding> {
34
+ export interface BindingOnChangeOptions<Binding extends TLUnknownBinding> {
41
35
  /** The binding record before the change is made. */
42
36
  bindingBefore: Binding
43
37
  /** The binding record after the change is made. */
@@ -50,7 +44,7 @@ export interface BindingOnChangeOptions<Binding extends TLBinding = TLBinding> {
50
44
  *
51
45
  * @public
52
46
  */
53
- export interface BindingOnDeleteOptions<Binding extends TLBinding = TLBinding> {
47
+ export interface BindingOnDeleteOptions<Binding extends TLUnknownBinding> {
54
48
  /** The binding being deleted. */
55
49
  binding: Binding
56
50
  }
@@ -61,7 +55,7 @@ export interface BindingOnDeleteOptions<Binding extends TLBinding = TLBinding> {
61
55
  *
62
56
  * @public
63
57
  */
64
- export interface BindingOnShapeChangeOptions<Binding extends TLBinding = TLBinding> {
58
+ export interface BindingOnShapeChangeOptions<Binding extends TLUnknownBinding> {
65
59
  /** The binding record linking these two shapes. */
66
60
  binding: Binding
67
61
  /** The shape record before the change is made. */
@@ -101,7 +95,7 @@ export interface BindingOnShapeChangeOptions<Binding extends TLBinding = TLBindi
101
95
  *
102
96
  * @public
103
97
  */
104
- export interface BindingOnShapeIsolateOptions<Binding extends TLBinding = TLBinding> {
98
+ export interface BindingOnShapeIsolateOptions<Binding extends TLUnknownBinding> {
105
99
  /** The binding record that refers to the shape in question. */
106
100
  binding: Binding
107
101
  /**
@@ -120,7 +114,7 @@ export interface BindingOnShapeIsolateOptions<Binding extends TLBinding = TLBind
120
114
  *
121
115
  * @public
122
116
  */
123
- export interface BindingOnShapeDeleteOptions<Binding extends TLBinding = TLBinding> {
117
+ export interface BindingOnShapeDeleteOptions<Binding extends TLUnknownBinding> {
124
118
  /** The binding record that refers to the shape in question. */
125
119
  binding: Binding
126
120
  /** The shape that is about to be deleted. */
@@ -128,7 +122,7 @@ export interface BindingOnShapeDeleteOptions<Binding extends TLBinding = TLBindi
128
122
  }
129
123
 
130
124
  /** @public */
131
- export abstract class BindingUtil<Binding extends TLBinding = TLBinding> {
125
+ export abstract class BindingUtil<Binding extends TLUnknownBinding = TLUnknownBinding> {
132
126
  constructor(public editor: Editor) {}
133
127
  static props?: RecordProps<TLUnknownBinding>
134
128
  static migrations?: TLPropsMigrations
@@ -1,11 +1,11 @@
1
1
  import { Computed, RESET_VALUE, computed, isUninitialized } from '@tldraw/state'
2
- import { TLBinding, TLShapeId } from '@tldraw/tlschema'
2
+ import { TLArrowBinding, TLBinding, TLShapeId, TLUnknownBinding } from '@tldraw/tlschema'
3
3
  import { objectMapValues } from '@tldraw/utils'
4
4
  import { Editor } from '../Editor'
5
5
 
6
6
  type TLBindingsIndex = Map<TLShapeId, TLBinding[]>
7
7
 
8
- function fromScratch(bindingsQuery: Computed<TLBinding[], unknown>) {
8
+ function fromScratch(bindingsQuery: Computed<(TLArrowBinding | TLUnknownBinding)[], unknown>) {
9
9
  const allBindings = bindingsQuery.get() as TLBinding[]
10
10
 
11
11
  const shapesToBindings: TLBindingsIndex = new Map()
@@ -1,5 +1,4 @@
1
- import { TLParentId, TLShape, TLShapeId, createShapeId, toRichText } from '@tldraw/tlschema'
2
- import { IndexKey } from '@tldraw/utils'
1
+ import { TLShape, TLShapeId, createShapeId } from '@tldraw/tlschema'
3
2
  import { Mock, Mocked, vi } from 'vitest'
4
3
  import { Editor } from '../../Editor'
5
4
  import { FontManager, TLFontFace } from './FontManager'
@@ -42,21 +41,12 @@ describe('FontManager', () => {
42
41
  x: 0,
43
42
  y: 0,
44
43
  rotation: 0,
45
- index: 'a1' as IndexKey,
46
- parentId: 'page:page' as TLParentId,
44
+ index: 'a1' as any,
45
+ parentId: 'page:page' as any,
47
46
  opacity: 1,
48
47
  isLocked: false,
49
48
  meta: {},
50
- props: {
51
- color: 'black',
52
- size: 'xl',
53
- font: 'serif',
54
- textAlign: 'middle',
55
- w: 100,
56
- richText: toRichText('❤️'),
57
- scale: 2,
58
- autoSize: true,
59
- },
49
+ props: {},
60
50
  typeName: 'shape' as const,
61
51
  })
62
52
 
@@ -1,5 +1,5 @@
1
1
  import { EMPTY_ARRAY, atom, computed } from '@tldraw/state'
2
- import { TLParentId, TLShapeId, isShapeId } from '@tldraw/tlschema'
2
+ import { TLFrameShape, TLGroupShape, TLParentId, TLShapeId, isShapeId } from '@tldraw/tlschema'
3
3
  import { Vec, VecLike } from '../../../primitives/Vec'
4
4
  import type { Editor } from '../../Editor'
5
5
  import { BoundsSnaps } from './BoundsSnaps'
@@ -72,7 +72,7 @@ export class SnapManager {
72
72
  const collectSnappableShapesFromParent = (parentId: TLParentId) => {
73
73
  if (isShapeId(parentId)) {
74
74
  const parent = editor.getShape(parentId)
75
- if (parent && editor.isShapeOfType(parent, 'frame')) {
75
+ if (parent && editor.isShapeOfType<TLFrameShape>(parent, 'frame')) {
76
76
  snappableShapes.add(parentId)
77
77
  }
78
78
  }
@@ -89,7 +89,7 @@ export class SnapManager {
89
89
  const pageBounds = editor.getShapePageBounds(childId)
90
90
  if (!(pageBounds && renderingBounds.includes(pageBounds))) continue
91
91
  // Snap to children of groups but not group itself
92
- if (editor.isShapeOfType(childShape, 'group')) {
92
+ if (editor.isShapeOfType<TLGroupShape>(childShape, 'group')) {
93
93
  collectSnappableShapesFromParent(childId)
94
94
  continue
95
95
  }
@@ -1,4 +1,4 @@
1
- import { ExtractShapeByProps } from '@tldraw/tlschema'
1
+ import { TLBaseShape } from '@tldraw/tlschema'
2
2
  import { lerp } from '@tldraw/utils'
3
3
  import { Geometry2d } from '../../primitives/geometry/Geometry2d'
4
4
  import { Rectangle2d } from '../../primitives/geometry/Rectangle2d'
@@ -7,7 +7,7 @@ import { ShapeUtil, TLResizeInfo } from './ShapeUtil'
7
7
  import { resizeBox } from './shared/resizeBox'
8
8
 
9
9
  /** @public */
10
- export type TLBaseBoxShape = ExtractShapeByProps<{ w: number; h: number }>
10
+ export type TLBaseBoxShape = TLBaseShape<string, { w: number; h: number }>
11
11
 
12
12
  /** @public */
13
13
  export abstract class BaseBoxShapeUtil<Shape extends TLBaseBoxShape> extends ShapeUtil<Shape> {
@@ -26,7 +26,10 @@ import { TLClickEventInfo } from '../types/event-types'
26
26
  import { TLResizeHandle } from '../types/selection-types'
27
27
 
28
28
  /** @public */
29
- export interface TLShapeUtilConstructor<T extends TLShape, U extends ShapeUtil<T> = ShapeUtil<T>> {
29
+ export interface TLShapeUtilConstructor<
30
+ T extends TLUnknownShape,
31
+ U extends ShapeUtil<T> = ShapeUtil<T>,
32
+ > {
30
33
  new (editor: Editor): U
31
34
  type: T['type']
32
35
  props?: RecordProps<T>
@@ -39,11 +42,11 @@ export interface TLShapeUtilConstructor<T extends TLShape, U extends ShapeUtil<T
39
42
  *
40
43
  * @public
41
44
  */
42
- export interface TLShapeUtilCanBindOpts<Shape extends TLShape = TLShape> {
45
+ export interface TLShapeUtilCanBindOpts<Shape extends TLUnknownShape = TLUnknownShape> {
43
46
  /** The type of shape referenced by the `fromId` of the binding. */
44
- fromShapeType: TLShape['type']
47
+ fromShapeType: string
45
48
  /** The type of shape referenced by the `toId` of the binding. */
46
- toShapeType: TLShape['type']
49
+ toShapeType: string
47
50
  /** The type of binding. */
48
51
  bindingType: string
49
52
  }
@@ -76,7 +79,7 @@ export interface TLShapeUtilCanvasSvgDef {
76
79
  }
77
80
 
78
81
  /** @public */
79
- export abstract class ShapeUtil<Shape extends TLShape = TLShape> {
82
+ export abstract class ShapeUtil<Shape extends TLUnknownShape = TLUnknownShape> {
80
83
  /** Configure this shape utils {@link ShapeUtil.options | `options`}. */
81
84
  static configure<T extends TLShapeUtilConstructor<any, any>>(
82
85
  this: T,
@@ -55,7 +55,9 @@ export class GroupShapeUtil extends ShapeUtil<TLGroupShape> {
55
55
  const isHintingOtherGroup =
56
56
  hintingShapeIds.length > 0 &&
57
57
  hintingShapeIds.some(
58
- (id) => id !== shape.id && this.editor.isShapeOfType(this.editor.getShape(id)!, 'group')
58
+ (id) =>
59
+ id !== shape.id &&
60
+ this.editor.isShapeOfType<TLGroupShape>(this.editor.getShape(id)!, 'group')
59
61
  )
60
62
 
61
63
  const isFocused = this.editor.getCurrentPageState().focusedGroupId !== shape.id
@@ -1,5 +1,4 @@
1
1
  import { TLShape } from '@tldraw/tlschema'
2
- import { TLBaseBoxShape } from '../../shapes/BaseBoxShapeUtil'
3
2
  import { StateNode, TLStateNodeConstructor } from '../StateNode'
4
3
  import { Idle } from './children/Idle'
5
4
  import { Pointing } from './children/Pointing'
@@ -12,7 +11,7 @@ export abstract class BaseBoxShapeTool extends StateNode {
12
11
  return [Idle, Pointing]
13
12
  }
14
13
 
15
- abstract override shapeType: TLBaseBoxShape['type']
14
+ abstract override shapeType: string
16
15
 
17
16
  onCreate?(_shape: TLShape | null): void | null
18
17
  }
@@ -23,7 +23,7 @@ export class Pointing extends StateNode {
23
23
  const newPoint = maybeSnapToGrid(originPagePoint, editor)
24
24
 
25
25
  // Allow this to trigger the max shapes reached alert
26
- this.editor.createShapes([
26
+ this.editor.createShapes<TLBaseBoxShape>([
27
27
  {
28
28
  id,
29
29
  type: shapeType,
@@ -88,7 +88,7 @@ export class Pointing extends StateNode {
88
88
 
89
89
  // Allow this to trigger the max shapes reached alert
90
90
  // todo: add scale here when dynamic size is enabled (is this still needed?)
91
- this.editor.createShapes([
91
+ this.editor.createShapes<TLBaseBoxShape>([
92
92
  {
93
93
  id,
94
94
  type: shapeType,
@@ -127,7 +127,7 @@ export class Pointing extends StateNode {
127
127
  ;(next as TLBaseBoxShape & { props: { scale: number } }).props.scale = scale
128
128
  }
129
129
 
130
- this.editor.updateShape(next)
130
+ this.editor.updateShape<TLBaseBoxShape>(next)
131
131
 
132
132
  this.editor.setSelectedShapes([id])
133
133
 
@@ -1,21 +1,30 @@
1
- import { Geometry2d, RecordProps, Rectangle2d, ShapeUtil, T, TLShape, createShapeId } from '../..'
1
+ import {
2
+ Geometry2d,
3
+ RecordProps,
4
+ Rectangle2d,
5
+ ShapeUtil,
6
+ T,
7
+ TLBaseShape,
8
+ createShapeId,
9
+ } from '../..'
2
10
  import { createTLStore } from '../config/createTLStore'
3
11
  import { Editor } from '../editor/Editor'
4
12
  import { Box } from '../primitives/Box'
5
13
  import { getExportDefaultBounds } from './getSvgJsx'
6
14
 
7
- const TEST_SHAPE_TYPE = 'test-shape'
8
-
9
- declare module '@tldraw/tlschema' {
10
- export interface TLGlobalShapePropsMap {
11
- [TEST_SHAPE_TYPE]: { w: number; h: number; x: number; y: number; isContainer?: boolean }
15
+ type ITestShape = TLBaseShape<
16
+ 'test-shape',
17
+ {
18
+ w: number
19
+ h: number
20
+ x: number
21
+ y: number
22
+ isContainer?: boolean
12
23
  }
13
- }
14
-
15
- type ITestShape = TLShape<typeof TEST_SHAPE_TYPE>
24
+ >
16
25
 
17
26
  class TestShape extends ShapeUtil<ITestShape> {
18
- static override type = TEST_SHAPE_TYPE
27
+ static override type = 'test-shape' as const
19
28
  static override props: RecordProps<ITestShape> = {
20
29
  w: T.number,
21
30
  h: T.number,
@@ -1,6 +1,7 @@
1
1
  import { useAtom, useValue } from '@tldraw/state-react'
2
2
  import {
3
3
  TLFrameShape,
4
+ TLGroupShape,
4
5
  TLShape,
5
6
  TLShapeId,
6
7
  getColorValue,
@@ -57,7 +58,9 @@ export function getSvgJsx(editor: Editor, ids: TLShapeId[], opts: TLImageExportO
57
58
 
58
59
  // --- Common bounding box of all shapes
59
60
  const singleFrameShapeId =
60
- ids.length === 1 && editor.isShapeOfType(editor.getShape(ids[0])!, 'frame') ? ids[0] : null
61
+ ids.length === 1 && editor.isShapeOfType<TLFrameShape>(editor.getShape(ids[0])!, 'frame')
62
+ ? ids[0]
63
+ : null
61
64
 
62
65
  let bbox: null | Box = null
63
66
  if (opts.bounds) {
@@ -269,7 +272,7 @@ function SvgExport({
269
272
 
270
273
  const shape = editor.getShape(id)!
271
274
 
272
- if (editor.isShapeOfType(shape, 'group')) return []
275
+ if (editor.isShapeOfType<TLGroupShape>(shape, 'group')) return []
273
276
 
274
277
  const elements = []
275
278
  const util = editor.getShapeUtil(shape)
@@ -95,8 +95,8 @@ export function kickoutOccludedShapes(
95
95
  if (remainingShapesToReparent.size > 0) {
96
96
  // The remaining shapes are going to be reparented to the old parent's containing group, if there was one, or else to the page
97
97
  const newParentId =
98
- editor.findShapeAncestor(prevParent, (s) => editor.isShapeOfType(s, 'group'))?.id ??
99
- editor.getCurrentPageId()
98
+ editor.findShapeAncestor(prevParent, (s) => editor.isShapeOfType<TLGroupShape>(s, 'group'))
99
+ ?.id ?? editor.getCurrentPageId()
100
100
 
101
101
  remainingShapesToReparent.forEach((shape) => {
102
102
  if (!parentsToNewChildren[newParentId]) {
@@ -211,7 +211,7 @@ export function getDroppedShapesToNewParents(
211
211
 
212
212
  for (const shape of shapes) {
213
213
  const parent = editor.getShapeParent(shape)
214
- if (parent && editor.isShapeOfType(parent, 'group')) {
214
+ if (parent && editor.isShapeOfType<TLGroupShape>(parent, 'group')) {
215
215
  if (!movingGroups.has(parent)) {
216
216
  movingGroups.add(parent)
217
217
  }
@@ -248,7 +248,7 @@ export function getDroppedShapesToNewParents(
248
248
  parentCheck: for (let i = potentialParentShapes.length - 1; i >= 0; i--) {
249
249
  const parentShape = potentialParentShapes[i]
250
250
  const parentShapeContainingGroupId = editor.findShapeAncestor(parentShape, (s) =>
251
- editor.isShapeOfType(s, 'group')
251
+ editor.isShapeOfType<TLGroupShape>(s, 'group')
252
252
  )?.id
253
253
 
254
254
  const parentGeometry = editor.getShapeGeometry(parentShape)
@@ -274,7 +274,7 @@ export function getDroppedShapesToNewParents(
274
274
  if (!shapeGroupIds.has(shape.id)) {
275
275
  shapeGroupIds.set(
276
276
  shape.id,
277
- editor.findShapeAncestor(shape, (s) => editor.isShapeOfType(s, 'group'))?.id
277
+ editor.findShapeAncestor(shape, (s) => editor.isShapeOfType<TLGroupShape>(s, 'group'))?.id
278
278
  )
279
279
  }
280
280
 
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 = '4.3.0-canary.fd6b7f2a8adc'
4
+ export const version = '4.3.0-next.2b3bfbba757b'
5
5
  export const publishDates = {
6
6
  major: '2025-09-18T14:39:22.803Z',
7
- minor: '2025-11-24T22:53:38.801Z',
8
- patch: '2025-11-24T22:53:38.801Z',
7
+ minor: '2025-11-25T08:43:48.918Z',
8
+ patch: '2025-11-25T08:43:48.918Z',
9
9
  }