@tldraw/editor 3.16.0-canary.c349490eaef0 → 3.16.0-canary.c360426d8b7a

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 (69) hide show
  1. package/dist-cjs/index.d.ts +28 -27
  2. package/dist-cjs/index.js +4 -2
  3. package/dist-cjs/index.js.map +2 -2
  4. package/dist-cjs/lib/TldrawEditor.js +2 -0
  5. package/dist-cjs/lib/TldrawEditor.js.map +2 -2
  6. package/dist-cjs/lib/components/default-components/DefaultCanvas.js +4 -4
  7. package/dist-cjs/lib/components/default-components/DefaultCanvas.js.map +2 -2
  8. package/dist-cjs/lib/editor/Editor.js +0 -29
  9. package/dist-cjs/lib/editor/Editor.js.map +2 -2
  10. package/dist-cjs/lib/hooks/useCanvasEvents.js +17 -17
  11. package/dist-cjs/lib/hooks/useCanvasEvents.js.map +2 -2
  12. package/dist-cjs/lib/hooks/useDocumentEvents.js +4 -4
  13. package/dist-cjs/lib/hooks/useDocumentEvents.js.map +2 -2
  14. package/dist-cjs/lib/hooks/useFixSafariDoubleTapZoomPencilEvents.js +1 -1
  15. package/dist-cjs/lib/hooks/useFixSafariDoubleTapZoomPencilEvents.js.map +2 -2
  16. package/dist-cjs/lib/hooks/useHandleEvents.js +6 -6
  17. package/dist-cjs/lib/hooks/useHandleEvents.js.map +2 -2
  18. package/dist-cjs/lib/hooks/useSelectionEvents.js +8 -8
  19. package/dist-cjs/lib/hooks/useSelectionEvents.js.map +2 -2
  20. package/dist-cjs/lib/license/Watermark.js +2 -3
  21. package/dist-cjs/lib/license/Watermark.js.map +2 -2
  22. package/dist-cjs/lib/utils/dom.js +12 -1
  23. package/dist-cjs/lib/utils/dom.js.map +2 -2
  24. package/dist-cjs/lib/utils/getPointerInfo.js +3 -2
  25. package/dist-cjs/lib/utils/getPointerInfo.js.map +2 -2
  26. package/dist-cjs/version.js +3 -3
  27. package/dist-cjs/version.js.map +1 -1
  28. package/dist-esm/index.d.mts +28 -27
  29. package/dist-esm/index.mjs +7 -3
  30. package/dist-esm/index.mjs.map +2 -2
  31. package/dist-esm/lib/TldrawEditor.mjs +2 -0
  32. package/dist-esm/lib/TldrawEditor.mjs.map +2 -2
  33. package/dist-esm/lib/components/default-components/DefaultCanvas.mjs +5 -5
  34. package/dist-esm/lib/components/default-components/DefaultCanvas.mjs.map +2 -2
  35. package/dist-esm/lib/editor/Editor.mjs +0 -29
  36. package/dist-esm/lib/editor/Editor.mjs.map +2 -2
  37. package/dist-esm/lib/hooks/useCanvasEvents.mjs +24 -18
  38. package/dist-esm/lib/hooks/useCanvasEvents.mjs.map +2 -2
  39. package/dist-esm/lib/hooks/useDocumentEvents.mjs +10 -5
  40. package/dist-esm/lib/hooks/useDocumentEvents.mjs.map +2 -2
  41. package/dist-esm/lib/hooks/useFixSafariDoubleTapZoomPencilEvents.mjs +2 -2
  42. package/dist-esm/lib/hooks/useFixSafariDoubleTapZoomPencilEvents.mjs.map +2 -2
  43. package/dist-esm/lib/hooks/useHandleEvents.mjs +12 -7
  44. package/dist-esm/lib/hooks/useHandleEvents.mjs.map +2 -2
  45. package/dist-esm/lib/hooks/useSelectionEvents.mjs +15 -9
  46. package/dist-esm/lib/hooks/useSelectionEvents.mjs.map +2 -2
  47. package/dist-esm/lib/license/Watermark.mjs +3 -4
  48. package/dist-esm/lib/license/Watermark.mjs.map +2 -2
  49. package/dist-esm/lib/utils/dom.mjs +12 -1
  50. package/dist-esm/lib/utils/dom.mjs.map +2 -2
  51. package/dist-esm/lib/utils/getPointerInfo.mjs +3 -2
  52. package/dist-esm/lib/utils/getPointerInfo.mjs.map +2 -2
  53. package/dist-esm/version.mjs +3 -3
  54. package/dist-esm/version.mjs.map +1 -1
  55. package/package.json +7 -7
  56. package/src/index.ts +2 -0
  57. package/src/lib/TldrawEditor.tsx +2 -0
  58. package/src/lib/components/default-components/DefaultCanvas.tsx +5 -5
  59. package/src/lib/editor/Editor.ts +0 -33
  60. package/src/lib/hooks/useCanvasEvents.ts +24 -18
  61. package/src/lib/hooks/useDocumentEvents.ts +10 -5
  62. package/src/lib/hooks/useFixSafariDoubleTapZoomPencilEvents.ts +2 -2
  63. package/src/lib/hooks/useHandleEvents.ts +12 -7
  64. package/src/lib/hooks/useSelectionEvents.ts +15 -9
  65. package/src/lib/license/Watermark.tsx +3 -4
  66. package/src/lib/utils/dom.test.ts +24 -33
  67. package/src/lib/utils/dom.ts +31 -1
  68. package/src/lib/utils/getPointerInfo.ts +3 -3
  69. package/src/version.ts +3 -3
@@ -36,6 +36,15 @@ function releasePointerCapture(element, event) {
36
36
  }
37
37
  }
38
38
  const stopEventPropagation = (e) => e.stopPropagation();
39
+ const handledEvents = /* @__PURE__ */ new WeakSet();
40
+ function markEventAsHandled(e) {
41
+ const nativeEvent = "nativeEvent" in e ? e.nativeEvent : e;
42
+ handledEvents.add(nativeEvent);
43
+ }
44
+ function wasEventAlreadyHandled(e) {
45
+ const nativeEvent = "nativeEvent" in e ? e.nativeEvent : e;
46
+ return handledEvents.has(nativeEvent);
47
+ }
39
48
  const setStyleProperty = (elm, property, value) => {
40
49
  if (!elm) return;
41
50
  elm.style.setProperty(property, value);
@@ -48,10 +57,12 @@ function activeElementShouldCaptureKeys(allowButtons = false) {
48
57
  export {
49
58
  activeElementShouldCaptureKeys,
50
59
  loopToHtmlElement,
60
+ markEventAsHandled,
51
61
  preventDefault,
52
62
  releasePointerCapture,
53
63
  setPointerCapture,
54
64
  setStyleProperty,
55
- stopEventPropagation
65
+ stopEventPropagation,
66
+ wasEventAlreadyHandled
56
67
  };
57
68
  //# sourceMappingURL=dom.mjs.map
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../src/lib/utils/dom.ts"],
4
- "sourcesContent": ["/*\nThis is used to facilitate double clicking and pointer capture on elements.\n\nThe events in this file are possibly set on individual SVG elements, \nsuch as handles or corner handles, rather than on HTML elements or \nSVGSVGElements. Raw SVG elemnets do not support pointerCapture in \nmost cases, meaning that in order for pointer capture to work, we \nneed to crawl up the DOM tree to find the nearest HTML element. Then,\nin order for that element to also call the `onPointerUp` event from\nthis file, we need to manually set that event on that element and\nlater remove it when the pointerup occurs. This is a potential leak\nif the user clicks on a handle but the pointerup does not fire for\nwhatever reason.\n*/\n\nimport React from 'react'\nimport { debugFlags, pointerCaptureTrackingObject } from './debug-flags'\n\n/** @public */\nexport function loopToHtmlElement(elm: Element): HTMLElement {\n\tif (elm.nodeType === Node.ELEMENT_NODE) return elm as HTMLElement\n\tif (elm.parentElement) return loopToHtmlElement(elm.parentElement)\n\telse throw Error('Could not find a parent element of an HTML type!')\n}\n\n/**\n * This function calls `event.preventDefault()` for you. Why is that useful?\n *\n * Beacuase if you enable `window.preventDefaultLogging = true` it'll log out a message when it\n * happens. Because we use console.warn rather than (log) you'll get a stack trace in the inspector\n * telling you exactly where it happened. This is important because `e.preventDefault()` is the\n * source of many bugs, but unfortuantly it can't be avoided because it also stops a lot of default\n * behaviour which doesn't make sense in our UI\n *\n * @param event - To prevent default on\n * @public\n */\nexport function preventDefault(event: React.BaseSyntheticEvent | Event) {\n\tevent.preventDefault()\n\tif (debugFlags.logPreventDefaults.get()) {\n\t\tconsole.warn('preventDefault called on event:', event)\n\t}\n}\n\n/** @public */\nexport function setPointerCapture(\n\telement: Element,\n\tevent: React.PointerEvent<Element> | PointerEvent\n) {\n\telement.setPointerCapture(event.pointerId)\n\tif (debugFlags.logPointerCaptures.get()) {\n\t\tconst trackingObj = pointerCaptureTrackingObject.get()\n\t\ttrackingObj.set(element, (trackingObj.get(element) ?? 0) + 1)\n\t\tconsole.warn('setPointerCapture called on element:', element, event)\n\t}\n}\n\n/** @public */\nexport function releasePointerCapture(\n\telement: Element,\n\tevent: React.PointerEvent<Element> | PointerEvent\n) {\n\tif (!element.hasPointerCapture(event.pointerId)) {\n\t\treturn\n\t}\n\n\telement.releasePointerCapture(event.pointerId)\n\tif (debugFlags.logPointerCaptures.get()) {\n\t\tconst trackingObj = pointerCaptureTrackingObject.get()\n\t\tif (trackingObj.get(element) === 1) {\n\t\t\ttrackingObj.delete(element)\n\t\t} else if (trackingObj.has(element)) {\n\t\t\ttrackingObj.set(element, trackingObj.get(element)! - 1)\n\t\t} else {\n\t\t\tconsole.warn('Release without capture')\n\t\t}\n\t\tconsole.warn('releasePointerCapture called on element:', element, event)\n\t}\n}\n\n/**\n * Calls `event.stopPropagation()`.\n *\n * @deprecated Use {@link Editor.markEventAsHandled} instead, or manually call `event.stopPropagation()` if\n * that's what you really want.\n *\n * @public\n */\nexport const stopEventPropagation = (e: any) => e.stopPropagation()\n\n/** @internal */\nexport const setStyleProperty = (\n\telm: HTMLElement | null,\n\tproperty: string,\n\tvalue: string | number\n) => {\n\tif (!elm) return\n\telm.style.setProperty(property, value as string)\n}\n\n/** @internal */\nexport function activeElementShouldCaptureKeys(allowButtons = false) {\n\tconst { activeElement } = document\n\tconst elements = allowButtons ? ['input', 'textarea'] : ['input', 'select', 'button', 'textarea']\n\treturn !!(\n\t\tactiveElement &&\n\t\t((activeElement as HTMLElement).isContentEditable ||\n\t\t\telements.indexOf(activeElement.tagName.toLowerCase()) > -1 ||\n\t\t\tactiveElement.classList.contains('tlui-slider__thumb'))\n\t)\n}\n"],
5
- "mappings": "AAgBA,SAAS,YAAY,oCAAoC;AAGlD,SAAS,kBAAkB,KAA2B;AAC5D,MAAI,IAAI,aAAa,KAAK,aAAc,QAAO;AAC/C,MAAI,IAAI,cAAe,QAAO,kBAAkB,IAAI,aAAa;AAAA,MAC5D,OAAM,MAAM,kDAAkD;AACpE;AAcO,SAAS,eAAe,OAAyC;AACvE,QAAM,eAAe;AACrB,MAAI,WAAW,mBAAmB,IAAI,GAAG;AACxC,YAAQ,KAAK,mCAAmC,KAAK;AAAA,EACtD;AACD;AAGO,SAAS,kBACf,SACA,OACC;AACD,UAAQ,kBAAkB,MAAM,SAAS;AACzC,MAAI,WAAW,mBAAmB,IAAI,GAAG;AACxC,UAAM,cAAc,6BAA6B,IAAI;AACrD,gBAAY,IAAI,UAAU,YAAY,IAAI,OAAO,KAAK,KAAK,CAAC;AAC5D,YAAQ,KAAK,wCAAwC,SAAS,KAAK;AAAA,EACpE;AACD;AAGO,SAAS,sBACf,SACA,OACC;AACD,MAAI,CAAC,QAAQ,kBAAkB,MAAM,SAAS,GAAG;AAChD;AAAA,EACD;AAEA,UAAQ,sBAAsB,MAAM,SAAS;AAC7C,MAAI,WAAW,mBAAmB,IAAI,GAAG;AACxC,UAAM,cAAc,6BAA6B,IAAI;AACrD,QAAI,YAAY,IAAI,OAAO,MAAM,GAAG;AACnC,kBAAY,OAAO,OAAO;AAAA,IAC3B,WAAW,YAAY,IAAI,OAAO,GAAG;AACpC,kBAAY,IAAI,SAAS,YAAY,IAAI,OAAO,IAAK,CAAC;AAAA,IACvD,OAAO;AACN,cAAQ,KAAK,yBAAyB;AAAA,IACvC;AACA,YAAQ,KAAK,4CAA4C,SAAS,KAAK;AAAA,EACxE;AACD;AAUO,MAAM,uBAAuB,CAAC,MAAW,EAAE,gBAAgB;AAG3D,MAAM,mBAAmB,CAC/B,KACA,UACA,UACI;AACJ,MAAI,CAAC,IAAK;AACV,MAAI,MAAM,YAAY,UAAU,KAAe;AAChD;AAGO,SAAS,+BAA+B,eAAe,OAAO;AACpE,QAAM,EAAE,cAAc,IAAI;AAC1B,QAAM,WAAW,eAAe,CAAC,SAAS,UAAU,IAAI,CAAC,SAAS,UAAU,UAAU,UAAU;AAChG,SAAO,CAAC,EACP,kBACE,cAA8B,qBAC/B,SAAS,QAAQ,cAAc,QAAQ,YAAY,CAAC,IAAI,MACxD,cAAc,UAAU,SAAS,oBAAoB;AAExD;",
4
+ "sourcesContent": ["/*\nThis is used to facilitate double clicking and pointer capture on elements.\n\nThe events in this file are possibly set on individual SVG elements, \nsuch as handles or corner handles, rather than on HTML elements or \nSVGSVGElements. Raw SVG elemnets do not support pointerCapture in \nmost cases, meaning that in order for pointer capture to work, we \nneed to crawl up the DOM tree to find the nearest HTML element. Then,\nin order for that element to also call the `onPointerUp` event from\nthis file, we need to manually set that event on that element and\nlater remove it when the pointerup occurs. This is a potential leak\nif the user clicks on a handle but the pointerup does not fire for\nwhatever reason.\n*/\n\nimport React from 'react'\nimport { debugFlags, pointerCaptureTrackingObject } from './debug-flags'\n\n/** @public */\nexport function loopToHtmlElement(elm: Element): HTMLElement {\n\tif (elm.nodeType === Node.ELEMENT_NODE) return elm as HTMLElement\n\tif (elm.parentElement) return loopToHtmlElement(elm.parentElement)\n\telse throw Error('Could not find a parent element of an HTML type!')\n}\n\n/**\n * This function calls `event.preventDefault()` for you. Why is that useful?\n *\n * Beacuase if you enable `window.preventDefaultLogging = true` it'll log out a message when it\n * happens. Because we use console.warn rather than (log) you'll get a stack trace in the inspector\n * telling you exactly where it happened. This is important because `e.preventDefault()` is the\n * source of many bugs, but unfortuantly it can't be avoided because it also stops a lot of default\n * behaviour which doesn't make sense in our UI\n *\n * @param event - To prevent default on\n * @public\n */\nexport function preventDefault(event: React.BaseSyntheticEvent | Event) {\n\tevent.preventDefault()\n\tif (debugFlags.logPreventDefaults.get()) {\n\t\tconsole.warn('preventDefault called on event:', event)\n\t}\n}\n\n/** @public */\nexport function setPointerCapture(\n\telement: Element,\n\tevent: React.PointerEvent<Element> | PointerEvent\n) {\n\telement.setPointerCapture(event.pointerId)\n\tif (debugFlags.logPointerCaptures.get()) {\n\t\tconst trackingObj = pointerCaptureTrackingObject.get()\n\t\ttrackingObj.set(element, (trackingObj.get(element) ?? 0) + 1)\n\t\tconsole.warn('setPointerCapture called on element:', element, event)\n\t}\n}\n\n/** @public */\nexport function releasePointerCapture(\n\telement: Element,\n\tevent: React.PointerEvent<Element> | PointerEvent\n) {\n\tif (!element.hasPointerCapture(event.pointerId)) {\n\t\treturn\n\t}\n\n\telement.releasePointerCapture(event.pointerId)\n\tif (debugFlags.logPointerCaptures.get()) {\n\t\tconst trackingObj = pointerCaptureTrackingObject.get()\n\t\tif (trackingObj.get(element) === 1) {\n\t\t\ttrackingObj.delete(element)\n\t\t} else if (trackingObj.has(element)) {\n\t\t\ttrackingObj.set(element, trackingObj.get(element)! - 1)\n\t\t} else {\n\t\t\tconsole.warn('Release without capture')\n\t\t}\n\t\tconsole.warn('releasePointerCapture called on element:', element, event)\n\t}\n}\n\n/**\n * Calls `event.stopPropagation()`.\n *\n * @deprecated Use {@link markEventAsHandled} instead, or manually call `event.stopPropagation()` if\n * that's what you really want.\n *\n * @public\n */\nexport const stopEventPropagation = (e: any) => e.stopPropagation()\n\nconst handledEvents = new WeakSet<Event>()\n\n/**\n * In tldraw, events are sometimes handled by multiple components. For example, the shapes might\n * have events, but the canvas handles events too. The way that the canvas handles events can\n * interfere with the with the shapes event handlers - for example, it calls `.preventDefault()` on\n * `pointerDown`, which also prevents `click` events from firing on the shapes.\n *\n * You can use `.stopPropagation()` to prevent the event from propagating to the rest of the DOM,\n * but that can impact non-tldraw event handlers set up elsewhere. By using `markEventAsHandled`,\n * you'll stop other parts of tldraw from handling the event without impacting other, non-tldraw\n * event handlers. See also {@link wasEventAlreadyHandled}.\n *\n * @public\n */\nexport function markEventAsHandled(e: Event | { nativeEvent: Event }) {\n\tconst nativeEvent = 'nativeEvent' in e ? e.nativeEvent : e\n\thandledEvents.add(nativeEvent)\n}\n\n/**\n * Checks if an event has already been handled. See {@link markEventAsHandled}.\n *\n * @public\n */\nexport function wasEventAlreadyHandled(e: Event | { nativeEvent: Event }) {\n\tconst nativeEvent = 'nativeEvent' in e ? e.nativeEvent : e\n\treturn handledEvents.has(nativeEvent)\n}\n\n/** @internal */\nexport const setStyleProperty = (\n\telm: HTMLElement | null,\n\tproperty: string,\n\tvalue: string | number\n) => {\n\tif (!elm) return\n\telm.style.setProperty(property, value as string)\n}\n\n/** @internal */\nexport function activeElementShouldCaptureKeys(allowButtons = false) {\n\tconst { activeElement } = document\n\tconst elements = allowButtons ? ['input', 'textarea'] : ['input', 'select', 'button', 'textarea']\n\treturn !!(\n\t\tactiveElement &&\n\t\t((activeElement as HTMLElement).isContentEditable ||\n\t\t\telements.indexOf(activeElement.tagName.toLowerCase()) > -1 ||\n\t\t\tactiveElement.classList.contains('tlui-slider__thumb'))\n\t)\n}\n"],
5
+ "mappings": "AAgBA,SAAS,YAAY,oCAAoC;AAGlD,SAAS,kBAAkB,KAA2B;AAC5D,MAAI,IAAI,aAAa,KAAK,aAAc,QAAO;AAC/C,MAAI,IAAI,cAAe,QAAO,kBAAkB,IAAI,aAAa;AAAA,MAC5D,OAAM,MAAM,kDAAkD;AACpE;AAcO,SAAS,eAAe,OAAyC;AACvE,QAAM,eAAe;AACrB,MAAI,WAAW,mBAAmB,IAAI,GAAG;AACxC,YAAQ,KAAK,mCAAmC,KAAK;AAAA,EACtD;AACD;AAGO,SAAS,kBACf,SACA,OACC;AACD,UAAQ,kBAAkB,MAAM,SAAS;AACzC,MAAI,WAAW,mBAAmB,IAAI,GAAG;AACxC,UAAM,cAAc,6BAA6B,IAAI;AACrD,gBAAY,IAAI,UAAU,YAAY,IAAI,OAAO,KAAK,KAAK,CAAC;AAC5D,YAAQ,KAAK,wCAAwC,SAAS,KAAK;AAAA,EACpE;AACD;AAGO,SAAS,sBACf,SACA,OACC;AACD,MAAI,CAAC,QAAQ,kBAAkB,MAAM,SAAS,GAAG;AAChD;AAAA,EACD;AAEA,UAAQ,sBAAsB,MAAM,SAAS;AAC7C,MAAI,WAAW,mBAAmB,IAAI,GAAG;AACxC,UAAM,cAAc,6BAA6B,IAAI;AACrD,QAAI,YAAY,IAAI,OAAO,MAAM,GAAG;AACnC,kBAAY,OAAO,OAAO;AAAA,IAC3B,WAAW,YAAY,IAAI,OAAO,GAAG;AACpC,kBAAY,IAAI,SAAS,YAAY,IAAI,OAAO,IAAK,CAAC;AAAA,IACvD,OAAO;AACN,cAAQ,KAAK,yBAAyB;AAAA,IACvC;AACA,YAAQ,KAAK,4CAA4C,SAAS,KAAK;AAAA,EACxE;AACD;AAUO,MAAM,uBAAuB,CAAC,MAAW,EAAE,gBAAgB;AAElE,MAAM,gBAAgB,oBAAI,QAAe;AAelC,SAAS,mBAAmB,GAAmC;AACrE,QAAM,cAAc,iBAAiB,IAAI,EAAE,cAAc;AACzD,gBAAc,IAAI,WAAW;AAC9B;AAOO,SAAS,uBAAuB,GAAmC;AACzE,QAAM,cAAc,iBAAiB,IAAI,EAAE,cAAc;AACzD,SAAO,cAAc,IAAI,WAAW;AACrC;AAGO,MAAM,mBAAmB,CAC/B,KACA,UACA,UACI;AACJ,MAAI,CAAC,IAAK;AACV,MAAI,MAAM,YAAY,UAAU,KAAe;AAChD;AAGO,SAAS,+BAA+B,eAAe,OAAO;AACpE,QAAM,EAAE,cAAc,IAAI;AAC1B,QAAM,WAAW,eAAe,CAAC,SAAS,UAAU,IAAI,CAAC,SAAS,UAAU,UAAU,UAAU;AAChG,SAAO,CAAC,EACP,kBACE,cAA8B,qBAC/B,SAAS,QAAQ,cAAc,QAAQ,YAAY,CAAC,IAAI,MACxD,cAAc,UAAU,SAAS,oBAAoB;AAExD;",
6
6
  "names": []
7
7
  }
@@ -1,6 +1,7 @@
1
+ import { markEventAsHandled } from "./dom.mjs";
1
2
  import { isAccelKey } from "./keyboard.mjs";
2
- function getPointerInfo(editor, e) {
3
- editor.markEventAsHandled(e);
3
+ function getPointerInfo(e) {
4
+ markEventAsHandled(e);
4
5
  return {
5
6
  point: {
6
7
  x: e.clientX,
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../src/lib/utils/getPointerInfo.ts"],
4
- "sourcesContent": ["import { Editor } from '../editor/Editor'\nimport { isAccelKey } from './keyboard'\n\n/** @public */\nexport function getPointerInfo(editor: Editor, e: React.PointerEvent | PointerEvent) {\n\teditor.markEventAsHandled(e)\n\n\treturn {\n\t\tpoint: {\n\t\t\tx: e.clientX,\n\t\t\ty: e.clientY,\n\t\t\tz: e.pressure,\n\t\t},\n\t\tshiftKey: e.shiftKey,\n\t\taltKey: e.altKey,\n\t\tctrlKey: e.metaKey || e.ctrlKey,\n\t\tmetaKey: e.metaKey,\n\t\taccelKey: isAccelKey(e),\n\t\tpointerId: e.pointerId,\n\t\tbutton: e.button,\n\t\tisPen: e.pointerType === 'pen',\n\t}\n}\n"],
5
- "mappings": "AACA,SAAS,kBAAkB;AAGpB,SAAS,eAAe,QAAgB,GAAsC;AACpF,SAAO,mBAAmB,CAAC;AAE3B,SAAO;AAAA,IACN,OAAO;AAAA,MACN,GAAG,EAAE;AAAA,MACL,GAAG,EAAE;AAAA,MACL,GAAG,EAAE;AAAA,IACN;AAAA,IACA,UAAU,EAAE;AAAA,IACZ,QAAQ,EAAE;AAAA,IACV,SAAS,EAAE,WAAW,EAAE;AAAA,IACxB,SAAS,EAAE;AAAA,IACX,UAAU,WAAW,CAAC;AAAA,IACtB,WAAW,EAAE;AAAA,IACb,QAAQ,EAAE;AAAA,IACV,OAAO,EAAE,gBAAgB;AAAA,EAC1B;AACD;",
4
+ "sourcesContent": ["import { markEventAsHandled } from './dom'\nimport { isAccelKey } from './keyboard'\n\n/** @public */\nexport function getPointerInfo(e: React.PointerEvent | PointerEvent) {\n\tmarkEventAsHandled(e)\n\n\treturn {\n\t\tpoint: {\n\t\t\tx: e.clientX,\n\t\t\ty: e.clientY,\n\t\t\tz: e.pressure,\n\t\t},\n\t\tshiftKey: e.shiftKey,\n\t\taltKey: e.altKey,\n\t\tctrlKey: e.metaKey || e.ctrlKey,\n\t\tmetaKey: e.metaKey,\n\t\taccelKey: isAccelKey(e),\n\t\tpointerId: e.pointerId,\n\t\tbutton: e.button,\n\t\tisPen: e.pointerType === 'pen',\n\t}\n}\n"],
5
+ "mappings": "AAAA,SAAS,0BAA0B;AACnC,SAAS,kBAAkB;AAGpB,SAAS,eAAe,GAAsC;AACpE,qBAAmB,CAAC;AAEpB,SAAO;AAAA,IACN,OAAO;AAAA,MACN,GAAG,EAAE;AAAA,MACL,GAAG,EAAE;AAAA,MACL,GAAG,EAAE;AAAA,IACN;AAAA,IACA,UAAU,EAAE;AAAA,IACZ,QAAQ,EAAE;AAAA,IACV,SAAS,EAAE,WAAW,EAAE;AAAA,IACxB,SAAS,EAAE;AAAA,IACX,UAAU,WAAW,CAAC;AAAA,IACtB,WAAW,EAAE;AAAA,IACb,QAAQ,EAAE;AAAA,IACV,OAAO,EAAE,gBAAgB;AAAA,EAC1B;AACD;",
6
6
  "names": []
7
7
  }
@@ -1,8 +1,8 @@
1
- const version = "3.16.0-canary.c349490eaef0";
1
+ const version = "3.16.0-canary.c360426d8b7a";
2
2
  const publishDates = {
3
3
  major: "2024-09-13T14:36:29.063Z",
4
- minor: "2025-09-17T16:01:20.675Z",
5
- patch: "2025-09-17T16:01:20.675Z"
4
+ minor: "2025-09-17T15:16:03.696Z",
5
+ patch: "2025-09-17T15:16:03.696Z"
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.16.0-canary.c349490eaef0'\nexport const publishDates = {\n\tmajor: '2024-09-13T14:36:29.063Z',\n\tminor: '2025-09-17T16:01:20.675Z',\n\tpatch: '2025-09-17T16:01:20.675Z',\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.16.0-canary.c360426d8b7a'\nexport const publishDates = {\n\tmajor: '2024-09-13T14:36:29.063Z',\n\tminor: '2025-09-17T15:16:03.696Z',\n\tpatch: '2025-09-17T15:16:03.696Z',\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": "tldraw infinite canvas SDK (editor).",
4
- "version": "3.16.0-canary.c349490eaef0",
4
+ "version": "3.16.0-canary.c360426d8b7a",
5
5
  "author": {
6
6
  "name": "tldraw Inc.",
7
7
  "email": "hello@tldraw.com"
@@ -50,12 +50,12 @@
50
50
  "@tiptap/core": "^2.9.1",
51
51
  "@tiptap/pm": "^2.9.1",
52
52
  "@tiptap/react": "^2.9.1",
53
- "@tldraw/state": "3.16.0-canary.c349490eaef0",
54
- "@tldraw/state-react": "3.16.0-canary.c349490eaef0",
55
- "@tldraw/store": "3.16.0-canary.c349490eaef0",
56
- "@tldraw/tlschema": "3.16.0-canary.c349490eaef0",
57
- "@tldraw/utils": "3.16.0-canary.c349490eaef0",
58
- "@tldraw/validate": "3.16.0-canary.c349490eaef0",
53
+ "@tldraw/state": "3.16.0-canary.c360426d8b7a",
54
+ "@tldraw/state-react": "3.16.0-canary.c360426d8b7a",
55
+ "@tldraw/store": "3.16.0-canary.c360426d8b7a",
56
+ "@tldraw/tlschema": "3.16.0-canary.c360426d8b7a",
57
+ "@tldraw/utils": "3.16.0-canary.c360426d8b7a",
58
+ "@tldraw/validate": "3.16.0-canary.c360426d8b7a",
59
59
  "@types/core-js": "^2.5.8",
60
60
  "@use-gesture/react": "^10.3.1",
61
61
  "classnames": "^2.5.1",
package/src/index.ts CHANGED
@@ -447,10 +447,12 @@ export {
447
447
  export {
448
448
  activeElementShouldCaptureKeys,
449
449
  loopToHtmlElement,
450
+ markEventAsHandled,
450
451
  preventDefault,
451
452
  releasePointerCapture,
452
453
  setPointerCapture,
453
454
  stopEventPropagation,
455
+ wasEventAlreadyHandled,
454
456
  } from './lib/utils/dom'
455
457
  export { EditorAtom } from './lib/utils/EditorAtom'
456
458
  export { getIncrementedName } from './lib/utils/getIncrementedName'
@@ -44,6 +44,7 @@ import { LicenseProvider } from './license/LicenseProvider'
44
44
  import { Watermark } from './license/Watermark'
45
45
  import { TldrawOptions } from './options'
46
46
  import { TLDeepLinkOptions } from './utils/deepLinks'
47
+ import { markEventAsHandled } from './utils/dom'
47
48
  import { TLTextOptions } from './utils/richText'
48
49
  import { TLStoreWithStatus } from './utils/sync/StoreWithStatus'
49
50
 
@@ -274,6 +275,7 @@ export const TldrawEditor = memo(function TldrawEditor({
274
275
  data-tldraw={version}
275
276
  draggable={false}
276
277
  className={classNames(`${TL_CONTAINER_CLASS} tl-theme__light`, className)}
278
+ onPointerDown={markEventAsHandled}
277
279
  tabIndex={-1}
278
280
  role="application"
279
281
  aria-label={_options?.branding ?? 'tldraw'}
@@ -21,7 +21,7 @@ import { Mat } from '../../primitives/Mat'
21
21
  import { Vec } from '../../primitives/Vec'
22
22
  import { toDomPrecision } from '../../primitives/utils'
23
23
  import { debugFlags } from '../../utils/debug-flags'
24
- import { setStyleProperty } from '../../utils/dom'
24
+ import { markEventAsHandled, setStyleProperty } from '../../utils/dom'
25
25
  import { GeometryDebuggingView } from '../GeometryDebuggingView'
26
26
  import { LiveCollaborators } from '../LiveCollaborators'
27
27
  import { MenuClickCapture } from '../MenuClickCapture'
@@ -174,10 +174,10 @@ export function DefaultCanvas({ className }: TLCanvasComponentProps) {
174
174
  </div>
175
175
  <div
176
176
  className="tl-canvas__in-front"
177
- onPointerDown={editor.markEventAsHandled}
178
- onPointerUp={editor.markEventAsHandled}
179
- onTouchStart={editor.markEventAsHandled}
180
- onTouchEnd={editor.markEventAsHandled}
177
+ onPointerDown={markEventAsHandled}
178
+ onPointerUp={markEventAsHandled}
179
+ onTouchStart={markEventAsHandled}
180
+ onTouchEnd={markEventAsHandled}
181
181
  >
182
182
  <InFrontOfTheCanvasWrapper />
183
183
  </div>
@@ -343,8 +343,6 @@ export class Editor extends EventEmitter<TLEventMap> {
343
343
  this.root = new NewRoot(this)
344
344
  this.root.children = {}
345
345
 
346
- this.markEventAsHandled = this.markEventAsHandled.bind(this)
347
-
348
346
  const allShapeUtils = checkShapesAndAddCore(shapeUtils)
349
347
 
350
348
  const _shapeUtils = {} as Record<string, ShapeUtil<any>>
@@ -10099,37 +10097,6 @@ export class Editor extends EventEmitter<TLEventMap> {
10099
10097
  /** @internal */
10100
10098
  private performanceTrackerTimeout = -1 as any
10101
10099
 
10102
- /** @internal */
10103
- private handledEvents = new WeakSet<Event>()
10104
-
10105
- /**
10106
- * In tldraw, events are sometimes handled by multiple components. For example, the shapes might
10107
- * have events, but the canvas handles events too. The way that the canvas handles events can
10108
- * interfere with the with the shapes event handlers - for example, it calls `.preventDefault()`
10109
- * on `pointerDown`, which also prevents `click` events from firing on the shapes.
10110
- *
10111
- * You can use `.stopPropagation()` to prevent the event from propagating to the rest of the
10112
- * DOM, but that can impact non-tldraw event handlers set up elsewhere. By using
10113
- * `markEventAsHandled`, you'll stop other parts of tldraw from handling the event without
10114
- * impacting other, non-tldraw event handlers. See also {@link Editor.wasEventAlreadyHandled}.
10115
- *
10116
- * @public
10117
- */
10118
- markEventAsHandled(e: Event | { nativeEvent: Event }) {
10119
- const nativeEvent = 'nativeEvent' in e ? e.nativeEvent : e
10120
- this.handledEvents.add(nativeEvent)
10121
- }
10122
-
10123
- /**
10124
- * Checks if an event has already been handled. See {@link Editor.markEventAsHandled}.
10125
- *
10126
- * @public
10127
- */
10128
- wasEventAlreadyHandled(e: Event | { nativeEvent: Event }) {
10129
- const nativeEvent = 'nativeEvent' in e ? e.nativeEvent : e
10130
- return this.handledEvents.has(nativeEvent)
10131
- }
10132
-
10133
10100
  /**
10134
10101
  * Dispatch an event to the editor.
10135
10102
  *
@@ -1,7 +1,13 @@
1
1
  import { useValue } from '@tldraw/state-react'
2
2
  import React, { useEffect, useMemo } from 'react'
3
3
  import { RIGHT_MOUSE_BUTTON } from '../constants'
4
- import { preventDefault, releasePointerCapture, setPointerCapture } from '../utils/dom'
4
+ import {
5
+ markEventAsHandled,
6
+ preventDefault,
7
+ releasePointerCapture,
8
+ setPointerCapture,
9
+ wasEventAlreadyHandled,
10
+ } from '../utils/dom'
5
11
  import { getPointerInfo } from '../utils/getPointerInfo'
6
12
  import { useEditor } from './useEditor'
7
13
 
@@ -12,14 +18,14 @@ export function useCanvasEvents() {
12
18
  const events = useMemo(
13
19
  function canvasEvents() {
14
20
  function onPointerDown(e: React.PointerEvent) {
15
- if (editor.wasEventAlreadyHandled(e)) return
21
+ if (wasEventAlreadyHandled(e)) return
16
22
 
17
23
  if (e.button === RIGHT_MOUSE_BUTTON) {
18
24
  editor.dispatch({
19
25
  type: 'pointer',
20
26
  target: 'canvas',
21
27
  name: 'right_click',
22
- ...getPointerInfo(editor, e),
28
+ ...getPointerInfo(e),
23
29
  })
24
30
  return
25
31
  }
@@ -32,12 +38,12 @@ export function useCanvasEvents() {
32
38
  type: 'pointer',
33
39
  target: 'canvas',
34
40
  name: 'pointer_down',
35
- ...getPointerInfo(editor, e),
41
+ ...getPointerInfo(e),
36
42
  })
37
43
  }
38
44
 
39
45
  function onPointerUp(e: React.PointerEvent) {
40
- if (editor.wasEventAlreadyHandled(e)) return
46
+ if (wasEventAlreadyHandled(e)) return
41
47
  if (e.button !== 0 && e.button !== 1 && e.button !== 2 && e.button !== 5) return
42
48
 
43
49
  releasePointerCapture(e.currentTarget, e)
@@ -46,33 +52,33 @@ export function useCanvasEvents() {
46
52
  type: 'pointer',
47
53
  target: 'canvas',
48
54
  name: 'pointer_up',
49
- ...getPointerInfo(editor, e),
55
+ ...getPointerInfo(e),
50
56
  })
51
57
  }
52
58
 
53
59
  function onPointerEnter(e: React.PointerEvent) {
54
- if (editor.wasEventAlreadyHandled(e)) return
60
+ if (wasEventAlreadyHandled(e)) return
55
61
  if (editor.getInstanceState().isPenMode && e.pointerType !== 'pen') return
56
62
  const canHover = e.pointerType === 'mouse' || e.pointerType === 'pen'
57
63
  editor.updateInstanceState({ isHoveringCanvas: canHover ? true : null })
58
64
  }
59
65
 
60
66
  function onPointerLeave(e: React.PointerEvent) {
61
- if (editor.wasEventAlreadyHandled(e)) return
67
+ if (wasEventAlreadyHandled(e)) return
62
68
  if (editor.getInstanceState().isPenMode && e.pointerType !== 'pen') return
63
69
  const canHover = e.pointerType === 'mouse' || e.pointerType === 'pen'
64
70
  editor.updateInstanceState({ isHoveringCanvas: canHover ? false : null })
65
71
  }
66
72
 
67
73
  function onTouchStart(e: React.TouchEvent) {
68
- if (editor.wasEventAlreadyHandled(e)) return
69
- editor.markEventAsHandled(e)
74
+ if (wasEventAlreadyHandled(e)) return
75
+ markEventAsHandled(e)
70
76
  preventDefault(e)
71
77
  }
72
78
 
73
79
  function onTouchEnd(e: React.TouchEvent) {
74
- if (editor.wasEventAlreadyHandled(e)) return
75
- editor.markEventAsHandled(e)
80
+ if (wasEventAlreadyHandled(e)) return
81
+ markEventAsHandled(e)
76
82
  // check that e.target is an HTMLElement
77
83
  if (!(e.target instanceof HTMLElement)) return
78
84
 
@@ -91,12 +97,12 @@ export function useCanvasEvents() {
91
97
  }
92
98
 
93
99
  function onDragOver(e: React.DragEvent<Element>) {
94
- if (editor.wasEventAlreadyHandled(e)) return
100
+ if (wasEventAlreadyHandled(e)) return
95
101
  preventDefault(e)
96
102
  }
97
103
 
98
104
  async function onDrop(e: React.DragEvent<Element>) {
99
- if (editor.wasEventAlreadyHandled(e)) return
105
+ if (wasEventAlreadyHandled(e)) return
100
106
  preventDefault(e)
101
107
  e.stopPropagation()
102
108
 
@@ -123,7 +129,7 @@ export function useCanvasEvents() {
123
129
  }
124
130
 
125
131
  function onClick(e: React.MouseEvent) {
126
- if (editor.wasEventAlreadyHandled(e)) return
132
+ if (wasEventAlreadyHandled(e)) return
127
133
  e.stopPropagation()
128
134
  }
129
135
 
@@ -151,8 +157,8 @@ export function useCanvasEvents() {
151
157
  let lastX: number, lastY: number
152
158
 
153
159
  function onPointerMove(e: PointerEvent) {
154
- if (editor.wasEventAlreadyHandled(e)) return
155
- editor.markEventAsHandled(e)
160
+ if (wasEventAlreadyHandled(e)) return
161
+ markEventAsHandled(e)
156
162
 
157
163
  if (e.clientX === lastX && e.clientY === lastY) return
158
164
  lastX = e.clientX
@@ -168,7 +174,7 @@ export function useCanvasEvents() {
168
174
  type: 'pointer',
169
175
  target: 'canvas',
170
176
  name: 'pointer_move',
171
- ...getPointerInfo(editor, singleEvent),
177
+ ...getPointerInfo(singleEvent),
172
178
  })
173
179
  }
174
180
  }
@@ -2,7 +2,12 @@ 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 { activeElementShouldCaptureKeys, preventDefault } from '../utils/dom'
5
+ import {
6
+ activeElementShouldCaptureKeys,
7
+ markEventAsHandled,
8
+ preventDefault,
9
+ wasEventAlreadyHandled,
10
+ } from '../utils/dom'
6
11
  import { isAccelKey } from '../utils/keyboard'
7
12
  import { useContainer } from './useContainer'
8
13
  import { useEditor } from './useEditor'
@@ -103,8 +108,8 @@ export function useDocumentEvents() {
103
108
  preventDefault(e)
104
109
  }
105
110
 
106
- if (editor.wasEventAlreadyHandled(e)) return
107
- editor.markEventAsHandled(e)
111
+ if (wasEventAlreadyHandled(e)) return
112
+ markEventAsHandled(e)
108
113
  const hasSelectedShapes = !!editor.getSelectedShapeIds().length
109
114
 
110
115
  switch (e.key) {
@@ -211,8 +216,8 @@ export function useDocumentEvents() {
211
216
  }
212
217
 
213
218
  const handleKeyUp = (e: KeyboardEvent) => {
214
- if (editor.wasEventAlreadyHandled(e)) return
215
- editor.markEventAsHandled(e)
219
+ if (wasEventAlreadyHandled(e)) return
220
+ markEventAsHandled(e)
216
221
 
217
222
  if (areShortcutsDisabled(editor)) {
218
223
  return
@@ -1,5 +1,5 @@
1
1
  import { useEffect } from 'react'
2
- import { preventDefault } from '../utils/dom'
2
+ import { markEventAsHandled, preventDefault } from '../utils/dom'
3
3
  import { useEditor } from './useEditor'
4
4
 
5
5
  const IGNORED_TAGS = ['textarea', 'input']
@@ -19,7 +19,7 @@ export function useFixSafariDoubleTapZoomPencilEvents(ref: React.RefObject<HTMLE
19
19
 
20
20
  const handleEvent = (e: PointerEvent | TouchEvent) => {
21
21
  if (e instanceof PointerEvent && e.pointerType === 'pen') {
22
- editor.markEventAsHandled(e)
22
+ markEventAsHandled(e)
23
23
  const { target } = e
24
24
 
25
25
  // Allow events to propagate if the app is editing a shape, or if the event is occurring in a text area or input
@@ -1,7 +1,12 @@
1
1
  import { TLArrowShape, TLLineShape, TLShapeId } from '@tldraw/tlschema'
2
2
  import * as React from 'react'
3
3
  import { Editor } from '../editor/Editor'
4
- import { loopToHtmlElement, releasePointerCapture, setPointerCapture } from '../utils/dom'
4
+ import {
5
+ loopToHtmlElement,
6
+ releasePointerCapture,
7
+ setPointerCapture,
8
+ wasEventAlreadyHandled,
9
+ } from '../utils/dom'
5
10
  import { getPointerInfo } from '../utils/getPointerInfo'
6
11
  import { useEditor } from './useEditor'
7
12
 
@@ -16,7 +21,7 @@ export function useHandleEvents(id: TLShapeId, handleId: string) {
16
21
 
17
22
  return React.useMemo(() => {
18
23
  const onPointerDown = (e: React.PointerEvent) => {
19
- if (editor.wasEventAlreadyHandled(e)) return
24
+ if (wasEventAlreadyHandled(e)) return
20
25
 
21
26
  // Must set pointer capture on an HTML element!
22
27
  const target = loopToHtmlElement(e.currentTarget)
@@ -32,7 +37,7 @@ export function useHandleEvents(id: TLShapeId, handleId: string) {
32
37
  handle,
33
38
  shape,
34
39
  name: 'pointer_down',
35
- ...getPointerInfo(editor, e),
40
+ ...getPointerInfo(e),
36
41
  })
37
42
  }
38
43
 
@@ -40,7 +45,7 @@ export function useHandleEvents(id: TLShapeId, handleId: string) {
40
45
  let lastX: number, lastY: number
41
46
 
42
47
  const onPointerMove = (e: React.PointerEvent) => {
43
- if (editor.wasEventAlreadyHandled(e)) return
48
+ if (wasEventAlreadyHandled(e)) return
44
49
  if (e.clientX === lastX && e.clientY === lastY) return
45
50
  lastX = e.clientX
46
51
  lastY = e.clientY
@@ -55,12 +60,12 @@ export function useHandleEvents(id: TLShapeId, handleId: string) {
55
60
  handle,
56
61
  shape,
57
62
  name: 'pointer_move',
58
- ...getPointerInfo(editor, e),
63
+ ...getPointerInfo(e),
59
64
  })
60
65
  }
61
66
 
62
67
  const onPointerUp = (e: React.PointerEvent) => {
63
- if (editor.wasEventAlreadyHandled(e)) return
68
+ if (wasEventAlreadyHandled(e)) return
64
69
 
65
70
  const target = loopToHtmlElement(e.currentTarget)
66
71
  releasePointerCapture(target, e)
@@ -75,7 +80,7 @@ export function useHandleEvents(id: TLShapeId, handleId: string) {
75
80
  handle,
76
81
  shape,
77
82
  name: 'pointer_up',
78
- ...getPointerInfo(editor, e),
83
+ ...getPointerInfo(e),
79
84
  })
80
85
  }
81
86
 
@@ -1,7 +1,13 @@
1
1
  import { useMemo } from 'react'
2
2
  import { RIGHT_MOUSE_BUTTON } from '../constants'
3
3
  import { TLSelectionHandle } from '../editor/types/selection-types'
4
- import { loopToHtmlElement, releasePointerCapture, setPointerCapture } from '../utils/dom'
4
+ import {
5
+ loopToHtmlElement,
6
+ markEventAsHandled,
7
+ releasePointerCapture,
8
+ setPointerCapture,
9
+ wasEventAlreadyHandled,
10
+ } from '../utils/dom'
5
11
  import { getPointerInfo } from '../utils/getPointerInfo'
6
12
  import { useEditor } from './useEditor'
7
13
 
@@ -12,7 +18,7 @@ export function useSelectionEvents(handle: TLSelectionHandle) {
12
18
  const events = useMemo(
13
19
  function selectionEvents() {
14
20
  const onPointerDown: React.PointerEventHandler = (e) => {
15
- if (editor.wasEventAlreadyHandled(e)) return
21
+ if (wasEventAlreadyHandled(e)) return
16
22
 
17
23
  if (e.button === RIGHT_MOUSE_BUTTON) {
18
24
  editor.dispatch({
@@ -20,7 +26,7 @@ export function useSelectionEvents(handle: TLSelectionHandle) {
20
26
  target: 'selection',
21
27
  handle,
22
28
  name: 'right_click',
23
- ...getPointerInfo(editor, e),
29
+ ...getPointerInfo(e),
24
30
  })
25
31
  return
26
32
  }
@@ -47,16 +53,16 @@ export function useSelectionEvents(handle: TLSelectionHandle) {
47
53
  type: 'pointer',
48
54
  target: 'selection',
49
55
  handle,
50
- ...getPointerInfo(editor, e),
56
+ ...getPointerInfo(e),
51
57
  })
52
- editor.markEventAsHandled(e)
58
+ markEventAsHandled(e)
53
59
  }
54
60
 
55
61
  // Track the last screen point
56
62
  let lastX: number, lastY: number
57
63
 
58
64
  function onPointerMove(e: React.PointerEvent) {
59
- if (editor.wasEventAlreadyHandled(e)) return
65
+ if (wasEventAlreadyHandled(e)) return
60
66
  if (e.button !== 0) return
61
67
  if (e.clientX === lastX && e.clientY === lastY) return
62
68
  lastX = e.clientX
@@ -67,12 +73,12 @@ export function useSelectionEvents(handle: TLSelectionHandle) {
67
73
  type: 'pointer',
68
74
  target: 'selection',
69
75
  handle,
70
- ...getPointerInfo(editor, e),
76
+ ...getPointerInfo(e),
71
77
  })
72
78
  }
73
79
 
74
80
  const onPointerUp: React.PointerEventHandler = (e) => {
75
- if (editor.wasEventAlreadyHandled(e)) return
81
+ if (wasEventAlreadyHandled(e)) return
76
82
  if (e.button !== 0) return
77
83
 
78
84
  editor.dispatch({
@@ -80,7 +86,7 @@ export function useSelectionEvents(handle: TLSelectionHandle) {
80
86
  type: 'pointer',
81
87
  target: 'selection',
82
88
  handle,
83
- ...getPointerInfo(editor, e),
89
+ ...getPointerInfo(e),
84
90
  })
85
91
  }
86
92
 
@@ -3,7 +3,7 @@ import { memo, useRef } from 'react'
3
3
  import { useCanvasEvents } from '../hooks/useCanvasEvents'
4
4
  import { useEditor } from '../hooks/useEditor'
5
5
  import { usePassThroughWheelEvents } from '../hooks/usePassThroughWheelEvents'
6
- import { preventDefault } from '../utils/dom'
6
+ import { markEventAsHandled, preventDefault } from '../utils/dom'
7
7
  import { runtime } from '../utils/runtime'
8
8
  import { watermarkDesktopSvg, watermarkMobileSvg } from '../watermarks'
9
9
  import { LicenseManager } from './LicenseManager'
@@ -43,7 +43,6 @@ const UnlicensedWatermark = memo(function UnlicensedWatermark({
43
43
  isDebugMode: boolean
44
44
  isMobile: boolean
45
45
  }) {
46
- const editor = useEditor()
47
46
  const events = useCanvasEvents()
48
47
  const ref = useRef<HTMLDivElement>(null)
49
48
  usePassThroughWheelEvents(ref)
@@ -66,7 +65,7 @@ const UnlicensedWatermark = memo(function UnlicensedWatermark({
66
65
  draggable={false}
67
66
  role="button"
68
67
  onPointerDown={(e) => {
69
- editor.markEventAsHandled(e)
68
+ markEventAsHandled(e)
70
69
  preventDefault(e)
71
70
  }}
72
71
  title="The tldraw SDK requires a license key to work in production. You can get a free 100-day trial license at tldraw.dev/pricing."
@@ -116,7 +115,7 @@ const WatermarkInner = memo(function WatermarkInner({
116
115
  draggable={false}
117
116
  role="button"
118
117
  onPointerDown={(e) => {
119
- editor.markEventAsHandled(e)
118
+ markEventAsHandled(e)
120
119
  preventDefault(e)
121
120
  }}
122
121
  title="Build infinite canvas applications with the tldraw SDK. Learn more at https://tldraw.dev."