@tldraw/editor 3.8.0-canary.b53fbf400e09 → 3.8.0-canary.b78121f8fa3f

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 (61) hide show
  1. package/dist-cjs/index.d.ts +100 -54
  2. package/dist-cjs/index.js +9 -8
  3. package/dist-cjs/index.js.map +2 -2
  4. package/dist-cjs/lib/config/TLSessionStateSnapshot.js.map +2 -2
  5. package/dist-cjs/lib/editor/Editor.js +3 -2
  6. package/dist-cjs/lib/editor/Editor.js.map +2 -2
  7. package/dist-cjs/lib/editor/managers/SnapManager/BoundsSnaps.js.map +2 -2
  8. package/dist-cjs/lib/editor/managers/TextManager.js +1 -0
  9. package/dist-cjs/lib/editor/managers/TextManager.js.map +2 -2
  10. package/dist-cjs/lib/editor/shapes/ShapeUtil.js +13 -0
  11. package/dist-cjs/lib/editor/shapes/ShapeUtil.js.map +2 -2
  12. package/dist-cjs/lib/editor/types/emit-types.js.map +1 -1
  13. package/dist-cjs/lib/editor/types/external-content.js.map +1 -1
  14. package/dist-cjs/lib/exports/StyleEmbedder.js.map +2 -2
  15. package/dist-cjs/lib/hooks/useDocumentEvents.js +1 -3
  16. package/dist-cjs/lib/hooks/useDocumentEvents.js.map +2 -2
  17. package/dist-cjs/lib/hooks/usePassThroughWheelEvents.js +4 -0
  18. package/dist-cjs/lib/hooks/usePassThroughWheelEvents.js.map +3 -3
  19. package/dist-cjs/lib/options.js +1 -2
  20. package/dist-cjs/lib/options.js.map +2 -2
  21. package/dist-cjs/lib/utils/dom.js +6 -0
  22. package/dist-cjs/lib/utils/dom.js.map +2 -2
  23. package/dist-cjs/version.js +3 -3
  24. package/dist-cjs/version.js.map +1 -1
  25. package/dist-esm/index.d.mts +100 -54
  26. package/dist-esm/index.mjs +3 -1
  27. package/dist-esm/index.mjs.map +2 -2
  28. package/dist-esm/lib/config/TLSessionStateSnapshot.mjs.map +2 -2
  29. package/dist-esm/lib/editor/Editor.mjs +3 -2
  30. package/dist-esm/lib/editor/Editor.mjs.map +2 -2
  31. package/dist-esm/lib/editor/managers/SnapManager/BoundsSnaps.mjs.map +2 -2
  32. package/dist-esm/lib/editor/managers/TextManager.mjs +1 -0
  33. package/dist-esm/lib/editor/managers/TextManager.mjs.map +2 -2
  34. package/dist-esm/lib/editor/shapes/ShapeUtil.mjs +13 -0
  35. package/dist-esm/lib/editor/shapes/ShapeUtil.mjs.map +2 -2
  36. package/dist-esm/lib/exports/StyleEmbedder.mjs.map +2 -2
  37. package/dist-esm/lib/hooks/useDocumentEvents.mjs +2 -4
  38. package/dist-esm/lib/hooks/useDocumentEvents.mjs.map +2 -2
  39. package/dist-esm/lib/hooks/usePassThroughWheelEvents.mjs +4 -0
  40. package/dist-esm/lib/hooks/usePassThroughWheelEvents.mjs.map +3 -3
  41. package/dist-esm/lib/options.mjs +1 -2
  42. package/dist-esm/lib/options.mjs.map +2 -2
  43. package/dist-esm/lib/utils/dom.mjs +6 -0
  44. package/dist-esm/lib/utils/dom.mjs.map +2 -2
  45. package/dist-esm/version.mjs +3 -3
  46. package/dist-esm/version.mjs.map +1 -1
  47. package/package.json +20 -20
  48. package/src/index.ts +14 -1
  49. package/src/lib/config/TLSessionStateSnapshot.ts +3 -1
  50. package/src/lib/editor/Editor.ts +18 -18
  51. package/src/lib/editor/managers/SnapManager/BoundsSnaps.ts +4 -4
  52. package/src/lib/editor/managers/TextManager.ts +1 -0
  53. package/src/lib/editor/shapes/ShapeUtil.ts +19 -0
  54. package/src/lib/editor/types/emit-types.ts +1 -0
  55. package/src/lib/editor/types/external-content.ts +90 -50
  56. package/src/lib/exports/StyleEmbedder.ts +1 -1
  57. package/src/lib/hooks/useDocumentEvents.ts +2 -11
  58. package/src/lib/hooks/usePassThroughWheelEvents.ts +7 -0
  59. package/src/lib/options.ts +3 -6
  60. package/src/lib/utils/dom.ts +12 -0
  61. package/src/version.ts +3 -3
@@ -53,8 +53,27 @@ export interface TLShapeUtilCanvasSvgDef {
53
53
 
54
54
  /** @public */
55
55
  export abstract class ShapeUtil<Shape extends TLUnknownShape = TLUnknownShape> {
56
+ /** Configure this shape utils {@link ShapeUtil.options | `options`}. */
57
+ static configure<T extends TLShapeUtilConstructor<any, any>>(
58
+ this: T,
59
+ options: T extends new (...args: any[]) => { options: infer Options } ? Partial<Options> : never
60
+ ): T {
61
+ // @ts-expect-error -- typescript has no idea what's going on here but it's fine
62
+ return class extends this {
63
+ // @ts-expect-error
64
+ options = { ...this.options, ...options }
65
+ }
66
+ }
67
+
56
68
  constructor(public editor: Editor) {}
57
69
 
70
+ /**
71
+ * Options for this shape util. If you're implementing a custom shape util, you can override
72
+ * this to provide customization options for your shape. If using an existing shape util, you
73
+ * can customizing this by calling {@link ShapeUtil.configure}.
74
+ */
75
+ options = {}
76
+
58
77
  /**
59
78
  * Props allow you to define the shape's properties in a way that the editor can understand.
60
79
  * This has two main uses:
@@ -12,6 +12,7 @@ export interface TLEventMap {
12
12
  crash: [{ error: unknown }]
13
13
  'stop-camera-animation': []
14
14
  'stop-following': []
15
+ 'before-event': [TLEventInfo]
15
16
  event: [TLEventInfo]
16
17
  tick: [number]
17
18
  frame: [number]
@@ -2,57 +2,97 @@ import { TLAssetId } from '@tldraw/tlschema'
2
2
  import { VecLike } from '../../primitives/Vec'
3
3
  import { TLContent } from './clipboard-types'
4
4
 
5
+ /** @public */
6
+ export interface TLTldrawExternalContentSource {
7
+ type: 'tldraw'
8
+ data: TLContent
9
+ }
10
+
11
+ /** @public */
12
+ export interface TLExcalidrawExternalContentSource {
13
+ type: 'excalidraw'
14
+ data: any
15
+ }
16
+
17
+ /** @public */
18
+ export interface TLTextExternalContentSource {
19
+ type: 'text'
20
+ data: string
21
+ subtype: 'json' | 'html' | 'text' | 'url'
22
+ }
23
+
24
+ /** @public */
25
+ export interface TLErrorExternalContentSource {
26
+ type: 'error'
27
+ data: string | null
28
+ reason: string
29
+ }
30
+
5
31
  /** @public */
6
32
  export type TLExternalContentSource =
7
- | {
8
- type: 'tldraw'
9
- data: TLContent
10
- }
11
- | {
12
- type: 'excalidraw'
13
- data: any
14
- }
15
- | {
16
- type: 'text'
17
- data: string
18
- subtype: 'json' | 'html' | 'text' | 'url'
19
- }
20
- | {
21
- type: 'error'
22
- data: string | null
23
- reason: string
24
- }
25
-
26
- /** @public */
27
- export type TLExternalContent<EmbedDefinition> = {
33
+ | TLTldrawExternalContentSource
34
+ | TLExcalidrawExternalContentSource
35
+ | TLTextExternalContentSource
36
+ | TLErrorExternalContentSource
37
+
38
+ /** @public */
39
+ export interface TLBaseExternalContent {
28
40
  sources?: TLExternalContentSource[]
29
41
  point?: VecLike
30
- } & (
31
- | {
32
- type: 'text'
33
- text: string
34
- }
35
- | {
36
- type: 'files'
37
- files: File[]
38
- ignoreParent: boolean
39
- }
40
- | {
41
- type: 'url'
42
- url: string
43
- }
44
- | {
45
- type: 'svg-text'
46
- text: string
47
- }
48
- | {
49
- type: 'embed'
50
- url: string
51
- embed: EmbedDefinition
52
- }
53
- )
54
-
55
- /** @public */
56
- export type TLExternalAssetContent =
57
- | { type: 'file'; file: File; assetId?: TLAssetId }
58
- | { type: 'url'; url: string }
42
+ }
43
+
44
+ /** @public */
45
+ export interface TLTextExternalContent extends TLBaseExternalContent {
46
+ type: 'text'
47
+ text: string
48
+ }
49
+
50
+ /** @public */
51
+ export interface TLFilesExternalContent extends TLBaseExternalContent {
52
+ type: 'files'
53
+ files: File[]
54
+ ignoreParent: boolean
55
+ }
56
+
57
+ /** @public */
58
+ export interface TLUrlExternalContent extends TLBaseExternalContent {
59
+ type: 'url'
60
+ url: string
61
+ }
62
+
63
+ /** @public */
64
+ export interface TLSvgTextExternalContent extends TLBaseExternalContent {
65
+ type: 'svg-text'
66
+ text: string
67
+ }
68
+
69
+ /** @public */
70
+ export interface TLEmbedExternalContent<EmbedDefinition> extends TLBaseExternalContent {
71
+ type: 'embed'
72
+ url: string
73
+ embed: EmbedDefinition
74
+ }
75
+
76
+ /** @public */
77
+ export type TLExternalContent<EmbedDefinition> =
78
+ | TLTextExternalContent
79
+ | TLFilesExternalContent
80
+ | TLUrlExternalContent
81
+ | TLSvgTextExternalContent
82
+ | TLEmbedExternalContent<EmbedDefinition>
83
+
84
+ /** @public */
85
+ export interface TLFileExternalAsset {
86
+ type: 'file'
87
+ file: File
88
+ assetId?: TLAssetId
89
+ }
90
+
91
+ /** @public */
92
+ export interface TLUrlExternalAsset {
93
+ type: 'url'
94
+ url: string
95
+ }
96
+
97
+ /** @public */
98
+ export type TLExternalAsset = TLFileExternalAsset | TLUrlExternalAsset
@@ -54,7 +54,7 @@ export class StyleEmbedder {
54
54
  : NO_STYLES
55
55
 
56
56
  const parentStyles = shouldSkipInheritedParentStyles
57
- ? this.styles.get(element.parentElement as Element)?.self ?? NO_STYLES
57
+ ? (this.styles.get(element.parentElement as Element)?.self ?? NO_STYLES)
58
58
  : NO_STYLES
59
59
 
60
60
  const info: ElementStyleInfo = {
@@ -2,7 +2,7 @@ import { useValue } from '@tldraw/state-react'
2
2
  import { useEffect } from 'react'
3
3
  import { Editor } from '../editor/Editor'
4
4
  import { TLKeyboardEventInfo } from '../editor/types/event-types'
5
- import { preventDefault, stopEventPropagation } from '../utils/dom'
5
+ import { activeElementShouldCaptureKeys, preventDefault, stopEventPropagation } from '../utils/dom'
6
6
  import { isAccelKey } from '../utils/keyboard'
7
7
  import { useContainer } from './useContainer'
8
8
  import { useEditor } from './useEditor'
@@ -274,15 +274,6 @@ export function useDocumentEvents() {
274
274
  }, [editor, container, isAppFocused])
275
275
  }
276
276
 
277
- const INPUTS = ['input', 'select', 'button', 'textarea']
278
-
279
277
  function areShortcutsDisabled(editor: Editor) {
280
- const { activeElement } = document
281
-
282
- return (
283
- editor.menus.hasOpenMenus() ||
284
- (activeElement &&
285
- (activeElement.getAttribute('contenteditable') ||
286
- INPUTS.indexOf(activeElement.tagName.toLowerCase()) > -1))
287
- )
278
+ return editor.menus.hasOpenMenus() || activeElementShouldCaptureKeys()
288
279
  }
@@ -11,6 +11,13 @@ export function usePassThroughWheelEvents(ref: RefObject<HTMLElement>) {
11
11
  useEffect(() => {
12
12
  function onWheel(e: WheelEvent) {
13
13
  if ((e as any).isSpecialRedispatchedEvent) return
14
+
15
+ // if the element is scrollable, don't redispatch the event
16
+ const elm = ref.current
17
+ if (elm && elm.scrollHeight > elm.clientHeight) {
18
+ return
19
+ }
20
+
14
21
  preventDefault(e)
15
22
  const cvs = container.querySelector('.tl-canvas')
16
23
  if (!cvs) return
@@ -29,7 +29,6 @@ export interface TldrawOptions {
29
29
  readonly dragDistanceSquared: number
30
30
  readonly defaultSvgPadding: number
31
31
  readonly cameraSlideFriction: number
32
- readonly maxPointsPerDrawShape: number
33
32
  readonly gridSteps: readonly {
34
33
  readonly min: number
35
34
  readonly mid: number
@@ -67,10 +66,9 @@ export interface TldrawOptions {
67
66
  */
68
67
  readonly exportProvider: ComponentType<{ children: React.ReactNode }>
69
68
  /**
70
- * How should the note shape resize? By default it does not resize (except automatically based on its text content),
71
- * but you can set it to be user-resizable using scale.
69
+ * By default, the toolbar items are accessible via number shortcuts according to their order. To disable this, set this option to false.
72
70
  */
73
- readonly noteShapeResizeMode: 'none' | 'scale'
71
+ readonly enableToolbarKeyboardShortcuts: boolean
74
72
  }
75
73
 
76
74
  /** @public */
@@ -86,7 +84,6 @@ export const defaultTldrawOptions = {
86
84
  dragDistanceSquared: 16, // 4 squared
87
85
  defaultSvgPadding: 32,
88
86
  cameraSlideFriction: 0.09,
89
- maxPointsPerDrawShape: 500,
90
87
  gridSteps: [
91
88
  { min: -1, mid: 0.15, step: 64 },
92
89
  { min: 0.05, mid: 0.375, step: 16 },
@@ -116,5 +113,5 @@ export const defaultTldrawOptions = {
116
113
  actionShortcutsLocation: 'swap',
117
114
  createTextOnCanvasDoubleClick: true,
118
115
  exportProvider: Fragment,
119
- noteShapeResizeMode: 'none',
116
+ enableToolbarKeyboardShortcuts: true,
120
117
  } as const satisfies TldrawOptions
@@ -90,3 +90,15 @@ export const setStyleProperty = (
90
90
  if (!elm) return
91
91
  elm.style.setProperty(property, value as string)
92
92
  }
93
+
94
+ const INPUTS = ['input', 'select', 'button', 'textarea']
95
+
96
+ /** @internal */
97
+ export function activeElementShouldCaptureKeys() {
98
+ const { activeElement } = document
99
+ return !!(
100
+ activeElement &&
101
+ (activeElement.getAttribute('contenteditable') ||
102
+ INPUTS.indexOf(activeElement.tagName.toLowerCase()) > -1)
103
+ )
104
+ }
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 = '3.8.0-canary.b53fbf400e09'
4
+ export const version = '3.8.0-canary.b78121f8fa3f'
5
5
  export const publishDates = {
6
6
  major: '2024-09-13T14:36:29.063Z',
7
- minor: '2025-01-29T10:32:14.577Z',
8
- patch: '2025-01-29T10:32:14.577Z',
7
+ minor: '2025-02-11T10:02:28.830Z',
8
+ patch: '2025-02-11T10:02:28.830Z',
9
9
  }