@tldraw/editor 4.5.0-canary.fe0a82f04c21 → 4.5.0-internal.b3f4cb985cc3

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 (147) hide show
  1. package/dist-cjs/index.d.ts +24 -2
  2. package/dist-cjs/index.js +5 -1
  3. package/dist-cjs/index.js.map +2 -2
  4. package/dist-cjs/lib/TldrawEditor.js +5 -4
  5. package/dist-cjs/lib/TldrawEditor.js.map +3 -3
  6. package/dist-cjs/lib/components/default-components/CanvasShapeIndicators.js +3 -2
  7. package/dist-cjs/lib/components/default-components/CanvasShapeIndicators.js.map +2 -2
  8. package/dist-cjs/lib/components/default-components/DefaultCanvas.js +1 -1
  9. package/dist-cjs/lib/components/default-components/DefaultCanvas.js.map +2 -2
  10. package/dist-cjs/lib/components/default-components/DefaultErrorFallback.js +5 -3
  11. package/dist-cjs/lib/components/default-components/DefaultErrorFallback.js.map +2 -2
  12. package/dist-cjs/lib/config/TLSessionStateSnapshot.js +2 -1
  13. package/dist-cjs/lib/config/TLSessionStateSnapshot.js.map +2 -2
  14. package/dist-cjs/lib/config/TLUserPreferences.js.map +2 -2
  15. package/dist-cjs/lib/editor/Editor.js +58 -18
  16. package/dist-cjs/lib/editor/Editor.js.map +2 -2
  17. package/dist-cjs/lib/editor/managers/FocusManager/FocusManager.js +62 -6
  18. package/dist-cjs/lib/editor/managers/FocusManager/FocusManager.js.map +2 -2
  19. package/dist-cjs/lib/editor/managers/FontManager/FontManager.js +4 -3
  20. package/dist-cjs/lib/editor/managers/FontManager/FontManager.js.map +2 -2
  21. package/dist-cjs/lib/editor/managers/TextManager/TextManager.js +2 -2
  22. package/dist-cjs/lib/editor/managers/TextManager/TextManager.js.map +2 -2
  23. package/dist-cjs/lib/editor/managers/UserPreferencesManager/UserPreferencesManager.js.map +2 -2
  24. package/dist-cjs/lib/editor/tools/BaseBoxShapeTool/children/Pointing.js +2 -3
  25. package/dist-cjs/lib/editor/tools/BaseBoxShapeTool/children/Pointing.js.map +2 -2
  26. package/dist-cjs/lib/editor/types/misc-types.js.map +1 -1
  27. package/dist-cjs/lib/exports/FontEmbedder.js +9 -8
  28. package/dist-cjs/lib/exports/FontEmbedder.js.map +2 -2
  29. package/dist-cjs/lib/exports/StyleEmbedder.js +27 -15
  30. package/dist-cjs/lib/exports/StyleEmbedder.js.map +3 -3
  31. package/dist-cjs/lib/exports/domUtils.js +15 -0
  32. package/dist-cjs/lib/exports/domUtils.js.map +2 -2
  33. package/dist-cjs/lib/exports/embedMedia.js +15 -12
  34. package/dist-cjs/lib/exports/embedMedia.js.map +2 -2
  35. package/dist-cjs/lib/exports/exportToSvg.js +8 -7
  36. package/dist-cjs/lib/exports/exportToSvg.js.map +2 -2
  37. package/dist-cjs/lib/exports/getSvgAsImage.js +180 -29
  38. package/dist-cjs/lib/exports/getSvgAsImage.js.map +3 -3
  39. package/dist-cjs/lib/exports/getSvgJsx.js +21 -9
  40. package/dist-cjs/lib/exports/getSvgJsx.js.map +2 -2
  41. package/dist-cjs/lib/globals/environment.js.map +2 -2
  42. package/dist-cjs/lib/hooks/useCanvasEvents.js +4 -4
  43. package/dist-cjs/lib/hooks/useCanvasEvents.js.map +2 -2
  44. package/dist-cjs/lib/hooks/useDocumentEvents.js +13 -11
  45. package/dist-cjs/lib/hooks/useDocumentEvents.js.map +2 -2
  46. package/dist-cjs/lib/hooks/useFixSafariDoubleTapZoomPencilEvents.js +3 -3
  47. package/dist-cjs/lib/hooks/useFixSafariDoubleTapZoomPencilEvents.js.map +2 -2
  48. package/dist-cjs/lib/hooks/useScreenBounds.js +10 -6
  49. package/dist-cjs/lib/hooks/useScreenBounds.js.map +2 -2
  50. package/dist-cjs/lib/hooks/useViewportHeight.js +13 -11
  51. package/dist-cjs/lib/hooks/useViewportHeight.js.map +3 -3
  52. package/dist-cjs/lib/utils/browserCanvasMaxSize.js.map +2 -2
  53. package/dist-cjs/lib/utils/dom.js +8 -4
  54. package/dist-cjs/lib/utils/dom.js.map +2 -2
  55. package/dist-cjs/version.js +3 -3
  56. package/dist-cjs/version.js.map +1 -1
  57. package/dist-esm/index.d.mts +24 -2
  58. package/dist-esm/index.mjs +6 -1
  59. package/dist-esm/index.mjs.map +2 -2
  60. package/dist-esm/lib/TldrawEditor.mjs +5 -4
  61. package/dist-esm/lib/TldrawEditor.mjs.map +3 -3
  62. package/dist-esm/lib/components/default-components/CanvasShapeIndicators.mjs +2 -1
  63. package/dist-esm/lib/components/default-components/CanvasShapeIndicators.mjs.map +2 -2
  64. package/dist-esm/lib/components/default-components/DefaultCanvas.mjs +1 -1
  65. package/dist-esm/lib/components/default-components/DefaultCanvas.mjs.map +2 -2
  66. package/dist-esm/lib/components/default-components/DefaultErrorFallback.mjs +5 -3
  67. package/dist-esm/lib/components/default-components/DefaultErrorFallback.mjs.map +2 -2
  68. package/dist-esm/lib/config/TLSessionStateSnapshot.mjs +2 -1
  69. package/dist-esm/lib/config/TLSessionStateSnapshot.mjs.map +2 -2
  70. package/dist-esm/lib/config/TLUserPreferences.mjs.map +2 -2
  71. package/dist-esm/lib/editor/Editor.mjs +59 -19
  72. package/dist-esm/lib/editor/Editor.mjs.map +2 -2
  73. package/dist-esm/lib/editor/managers/FocusManager/FocusManager.mjs +64 -6
  74. package/dist-esm/lib/editor/managers/FocusManager/FocusManager.mjs.map +2 -2
  75. package/dist-esm/lib/editor/managers/FontManager/FontManager.mjs +4 -3
  76. package/dist-esm/lib/editor/managers/FontManager/FontManager.mjs.map +2 -2
  77. package/dist-esm/lib/editor/managers/TextManager/TextManager.mjs +2 -2
  78. package/dist-esm/lib/editor/managers/TextManager/TextManager.mjs.map +2 -2
  79. package/dist-esm/lib/editor/managers/UserPreferencesManager/UserPreferencesManager.mjs.map +2 -2
  80. package/dist-esm/lib/editor/tools/BaseBoxShapeTool/children/Pointing.mjs +2 -3
  81. package/dist-esm/lib/editor/tools/BaseBoxShapeTool/children/Pointing.mjs.map +2 -2
  82. package/dist-esm/lib/exports/FontEmbedder.mjs +9 -8
  83. package/dist-esm/lib/exports/FontEmbedder.mjs.map +2 -2
  84. package/dist-esm/lib/exports/StyleEmbedder.mjs +29 -16
  85. package/dist-esm/lib/exports/StyleEmbedder.mjs.map +3 -3
  86. package/dist-esm/lib/exports/domUtils.mjs +15 -0
  87. package/dist-esm/lib/exports/domUtils.mjs.map +2 -2
  88. package/dist-esm/lib/exports/embedMedia.mjs +16 -13
  89. package/dist-esm/lib/exports/embedMedia.mjs.map +2 -2
  90. package/dist-esm/lib/exports/exportToSvg.mjs +8 -7
  91. package/dist-esm/lib/exports/exportToSvg.mjs.map +2 -2
  92. package/dist-esm/lib/exports/getSvgAsImage.mjs +180 -29
  93. package/dist-esm/lib/exports/getSvgAsImage.mjs.map +3 -3
  94. package/dist-esm/lib/exports/getSvgJsx.mjs +21 -9
  95. package/dist-esm/lib/exports/getSvgJsx.mjs.map +2 -2
  96. package/dist-esm/lib/globals/environment.mjs.map +2 -2
  97. package/dist-esm/lib/hooks/useCanvasEvents.mjs +10 -5
  98. package/dist-esm/lib/hooks/useCanvasEvents.mjs.map +2 -2
  99. package/dist-esm/lib/hooks/useDocumentEvents.mjs +13 -11
  100. package/dist-esm/lib/hooks/useDocumentEvents.mjs.map +2 -2
  101. package/dist-esm/lib/hooks/useFixSafariDoubleTapZoomPencilEvents.mjs +4 -4
  102. package/dist-esm/lib/hooks/useFixSafariDoubleTapZoomPencilEvents.mjs.map +2 -2
  103. package/dist-esm/lib/hooks/useScreenBounds.mjs +10 -6
  104. package/dist-esm/lib/hooks/useScreenBounds.mjs.map +2 -2
  105. package/dist-esm/lib/hooks/useViewportHeight.mjs +13 -11
  106. package/dist-esm/lib/hooks/useViewportHeight.mjs.map +3 -3
  107. package/dist-esm/lib/utils/browserCanvasMaxSize.mjs.map +2 -2
  108. package/dist-esm/lib/utils/dom.mjs +8 -4
  109. package/dist-esm/lib/utils/dom.mjs.map +2 -2
  110. package/dist-esm/version.mjs +3 -3
  111. package/dist-esm/version.mjs.map +1 -1
  112. package/package.json +7 -7
  113. package/src/index.ts +2 -0
  114. package/src/lib/TldrawEditor.tsx +6 -4
  115. package/src/lib/components/default-components/CanvasShapeIndicators.tsx +2 -1
  116. package/src/lib/components/default-components/DefaultCanvas.tsx +1 -1
  117. package/src/lib/components/default-components/DefaultErrorFallback.tsx +7 -3
  118. package/src/lib/config/TLSessionStateSnapshot.ts +3 -1
  119. package/src/lib/config/TLUserPreferences.ts +2 -0
  120. package/src/lib/editor/Editor.ts +62 -15
  121. package/src/lib/editor/managers/FocusManager/FocusManager.test.ts +7 -6
  122. package/src/lib/editor/managers/FocusManager/FocusManager.ts +10 -7
  123. package/src/lib/editor/managers/FontManager/FontManager.test.ts +1 -0
  124. package/src/lib/editor/managers/FontManager/FontManager.ts +4 -3
  125. package/src/lib/editor/managers/TextManager/TextManager.test.ts +4 -5
  126. package/src/lib/editor/managers/TextManager/TextManager.ts +2 -2
  127. package/src/lib/editor/managers/UserPreferencesManager/UserPreferencesManager.ts +2 -0
  128. package/src/lib/editor/tools/BaseBoxShapeTool/children/Pointing.ts +3 -3
  129. package/src/lib/editor/types/misc-types.ts +8 -2
  130. package/src/lib/exports/FontEmbedder.ts +10 -9
  131. package/src/lib/exports/StyleEmbedder.ts +33 -15
  132. package/src/lib/exports/domUtils.ts +20 -0
  133. package/src/lib/exports/embedMedia.ts +23 -17
  134. package/src/lib/exports/exportToSvg.tsx +8 -7
  135. package/src/lib/exports/getSvgAsImage.ts +292 -31
  136. package/src/lib/exports/getSvgJsx.test.ts +103 -101
  137. package/src/lib/exports/getSvgJsx.tsx +33 -10
  138. package/src/lib/globals/environment.ts +3 -0
  139. package/src/lib/hooks/useCanvasEvents.ts +10 -7
  140. package/src/lib/hooks/useDocumentEvents.ts +16 -11
  141. package/src/lib/hooks/useFixSafariDoubleTapZoomPencilEvents.ts +4 -7
  142. package/src/lib/hooks/useScreenBounds.ts +10 -6
  143. package/src/lib/hooks/useViewportHeight.ts +13 -11
  144. package/src/lib/test/TestEditor.ts +1 -0
  145. package/src/lib/utils/browserCanvasMaxSize.ts +2 -0
  146. package/src/lib/utils/dom.ts +17 -8
  147. package/src/version.ts +3 -3
@@ -52,14 +52,15 @@ function useDocumentEvents() {
52
52
  };
53
53
  }, [container]);
54
54
  (0, import_react.useEffect)(() => {
55
- if (typeof window === "undefined" || !("matchMedia" in window)) return;
55
+ const win = editor.getContainerWindow();
56
+ if (!("matchMedia" in win)) return;
56
57
  let remove = null;
57
58
  const updatePixelRatio = () => {
58
59
  if (remove != null) {
59
60
  remove();
60
61
  }
61
- const mqString = `(resolution: ${window.devicePixelRatio}dppx)`;
62
- const media = matchMedia(mqString);
62
+ const mqString = `(resolution: ${win.devicePixelRatio}dppx)`;
63
+ const media = win.matchMedia(mqString);
63
64
  const safariCb = (ev) => {
64
65
  if (ev.type === "change") {
65
66
  updatePixelRatio();
@@ -77,7 +78,7 @@ function useDocumentEvents() {
77
78
  media.removeListener(safariCb);
78
79
  }
79
80
  };
80
- editor.updateInstanceState({ devicePixelRatio: window.devicePixelRatio });
81
+ editor.updateInstanceState({ devicePixelRatio: win.devicePixelRatio });
81
82
  };
82
83
  updatePixelRatio();
83
84
  return () => {
@@ -202,23 +203,24 @@ function useDocumentEvents() {
202
203
  };
203
204
  container.addEventListener("touchstart", handleTouchStart, { passive: false });
204
205
  container.addEventListener("wheel", handleWheel, { passive: false });
205
- document.addEventListener("gesturestart", import_dom.preventDefault);
206
- document.addEventListener("gesturechange", import_dom.preventDefault);
207
- document.addEventListener("gestureend", import_dom.preventDefault);
206
+ const ownerDoc = container.ownerDocument;
207
+ ownerDoc.addEventListener("gesturestart", import_dom.preventDefault);
208
+ ownerDoc.addEventListener("gesturechange", import_dom.preventDefault);
209
+ ownerDoc.addEventListener("gestureend", import_dom.preventDefault);
208
210
  container.addEventListener("keydown", handleKeyDown);
209
211
  container.addEventListener("keyup", handleKeyUp);
210
212
  return () => {
211
213
  container.removeEventListener("touchstart", handleTouchStart);
212
214
  container.removeEventListener("wheel", handleWheel);
213
- document.removeEventListener("gesturestart", import_dom.preventDefault);
214
- document.removeEventListener("gesturechange", import_dom.preventDefault);
215
- document.removeEventListener("gestureend", import_dom.preventDefault);
215
+ ownerDoc.removeEventListener("gesturestart", import_dom.preventDefault);
216
+ ownerDoc.removeEventListener("gesturechange", import_dom.preventDefault);
217
+ ownerDoc.removeEventListener("gestureend", import_dom.preventDefault);
216
218
  container.removeEventListener("keydown", handleKeyDown);
217
219
  container.removeEventListener("keyup", handleKeyUp);
218
220
  };
219
221
  }, [editor, container, isAppFocused, isEditing]);
220
222
  }
221
223
  function areShortcutsDisabled(editor) {
222
- return editor.menus.hasOpenMenus() || (0, import_dom.activeElementShouldCaptureKeys)();
224
+ return editor.menus.hasOpenMenus() || (0, import_dom.activeElementShouldCaptureKeys)(true, editor.getContainerDocument());
223
225
  }
224
226
  //# sourceMappingURL=useDocumentEvents.js.map
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../src/lib/hooks/useDocumentEvents.ts"],
4
- "sourcesContent": ["import { useValue } from '@tldraw/state-react'\nimport { useEffect } from 'react'\nimport { Editor } from '../editor/Editor'\nimport { TLKeyboardEventInfo } from '../editor/types/event-types'\nimport { activeElementShouldCaptureKeys, preventDefault } from '../utils/dom'\nimport { isAccelKey } from '../utils/keyboard'\nimport { useContainer } from './useContainer'\nimport { useEditor } from './useEditor'\n\nexport function useDocumentEvents() {\n\tconst editor = useEditor()\n\tconst container = useContainer()\n\n\tconst isEditing = useValue('isEditing', () => editor.getEditingShapeId(), [editor])\n\tconst isAppFocused = useValue('isFocused', () => editor.getIsFocused(), [editor])\n\n\t// Prevent the browser's default drag and drop behavior on our container (UI, etc)\n\tuseEffect(() => {\n\t\tif (!container) return\n\n\t\tfunction onDrop(e: DragEvent) {\n\t\t\t// this is tricky: we don't want the event to do anything\n\t\t\t// here, but we do want it to make its way to the canvas,\n\t\t\t// even if the drop is over some other element (like a toolbar),\n\t\t\t// so we're going to flag the event and then dispatch\n\t\t\t// it to the canvas; the canvas will handle it and try to\n\t\t\t// stop it from propagating back, but in case we do see it again,\n\t\t\t// we'll look for the flag so we know to stop it from being\n\t\t\t// re-dispatched, which would lead to an infinite loop.\n\t\t\tif ((e as any).isSpecialRedispatchedEvent) return\n\t\t\tpreventDefault(e)\n\t\t\te.stopPropagation()\n\t\t\tconst cvs = container.querySelector('.tl-canvas')\n\t\t\tif (!cvs) return\n\t\t\tconst newEvent = new DragEvent(e.type, e)\n\t\t\t;(newEvent as any).isSpecialRedispatchedEvent = true\n\t\t\tcvs.dispatchEvent(newEvent)\n\t\t}\n\n\t\tcontainer.addEventListener('dragover', onDrop)\n\t\tcontainer.addEventListener('drop', onDrop)\n\t\treturn () => {\n\t\t\tcontainer.removeEventListener('dragover', onDrop)\n\t\t\tcontainer.removeEventListener('drop', onDrop)\n\t\t}\n\t}, [container])\n\n\tuseEffect(() => {\n\t\tif (typeof window === 'undefined' || !('matchMedia' in window)) return\n\n\t\t// https://developer.mozilla.org/en-US/docs/Web/API/Window/devicePixelRatio#monitoring_screen_resolution_or_zoom_level_changes\n\t\tlet remove: (() => void) | null = null\n\t\tconst updatePixelRatio = () => {\n\t\t\tif (remove != null) {\n\t\t\t\tremove()\n\t\t\t}\n\t\t\tconst mqString = `(resolution: ${window.devicePixelRatio}dppx)`\n\t\t\tconst media = matchMedia(mqString)\n\t\t\t// Safari only started supporting `addEventListener('change',...) in version 14\n\t\t\t// https://developer.mozilla.org/en-US/docs/Web/API/MediaQueryList/change_event\n\t\t\tconst safariCb = (ev: any) => {\n\t\t\t\tif (ev.type === 'change') {\n\t\t\t\t\tupdatePixelRatio()\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (media.addEventListener) {\n\t\t\t\tmedia.addEventListener('change', updatePixelRatio)\n\t\t\t\t// eslint-disable-next-line @typescript-eslint/no-deprecated\n\t\t\t} else if (media.addListener) {\n\t\t\t\t// eslint-disable-next-line @typescript-eslint/no-deprecated\n\t\t\t\tmedia.addListener(safariCb)\n\t\t\t}\n\t\t\tremove = () => {\n\t\t\t\tif (media.removeEventListener) {\n\t\t\t\t\tmedia.removeEventListener('change', updatePixelRatio)\n\t\t\t\t\t// eslint-disable-next-line @typescript-eslint/no-deprecated\n\t\t\t\t} else if (media.removeListener) {\n\t\t\t\t\t// eslint-disable-next-line @typescript-eslint/no-deprecated\n\t\t\t\t\tmedia.removeListener(safariCb)\n\t\t\t\t}\n\t\t\t}\n\t\t\teditor.updateInstanceState({ devicePixelRatio: window.devicePixelRatio })\n\t\t}\n\t\tupdatePixelRatio()\n\t\treturn () => {\n\t\t\tremove?.()\n\t\t}\n\t}, [editor])\n\n\tuseEffect(() => {\n\t\tif (!isAppFocused) return\n\n\t\tconst handleKeyDown = (e: KeyboardEvent) => {\n\t\t\tif (\n\t\t\t\te.altKey &&\n\t\t\t\t// todo: When should we allow the alt key to be used? Perhaps states should declare which keys matter to them?\n\t\t\t\t(editor.isIn('zoom') || !editor.getPath().endsWith('.idle')) &&\n\t\t\t\t!areShortcutsDisabled(editor)\n\t\t\t) {\n\t\t\t\t// On windows the alt key opens the menu bar.\n\t\t\t\t// We want to prevent that if the user is doing something else,\n\t\t\t\t// e.g. resizing a shape\n\t\t\t\tpreventDefault(e)\n\t\t\t}\n\n\t\t\tif (editor.wasEventAlreadyHandled(e)) return\n\t\t\teditor.markEventAsHandled(e)\n\t\t\tconst hasSelectedShapes = !!editor.getSelectedShapeIds().length\n\n\t\t\tswitch (e.key) {\n\t\t\t\tcase '=':\n\t\t\t\tcase '-':\n\t\t\t\tcase '0': {\n\t\t\t\t\t// These keys are used for zooming. Technically we only use\n\t\t\t\t\t// the + - and 0 keys, however it's common for them to be\n\t\t\t\t\t// paired with modifier keys (command / control) so we need\n\t\t\t\t\t// to prevent the browser's regular actions (i.e. zooming\n\t\t\t\t\t// the page). A user can zoom by unfocusing the editor.\n\t\t\t\t\tif (e.metaKey || e.ctrlKey) {\n\t\t\t\t\t\tpreventDefault(e)\n\t\t\t\t\t\treturn\n\t\t\t\t\t}\n\t\t\t\t\tbreak\n\t\t\t\t}\n\t\t\t\tcase 'Tab': {\n\t\t\t\t\tif (areShortcutsDisabled(editor)) {\n\t\t\t\t\t\treturn\n\t\t\t\t\t}\n\t\t\t\t\t// isEditing here sounds like it's about text editing\n\t\t\t\t\t// but more specifically, this is so you can tab into an\n\t\t\t\t\t// embed that's being 'edited'. In our world,\n\t\t\t\t\t// editing an embed, means it's interactive.\n\t\t\t\t\tif (hasSelectedShapes && !isEditing) {\n\t\t\t\t\t\t// This is used in tandem with shape navigation.\n\t\t\t\t\t\tpreventDefault(e)\n\t\t\t\t\t}\n\t\t\t\t\tbreak\n\t\t\t\t}\n\t\t\t\tcase 'ArrowLeft':\n\t\t\t\tcase 'ArrowRight':\n\t\t\t\tcase 'ArrowUp':\n\t\t\t\tcase 'ArrowDown': {\n\t\t\t\t\tif (areShortcutsDisabled(editor)) {\n\t\t\t\t\t\treturn\n\t\t\t\t\t}\n\t\t\t\t\tif (hasSelectedShapes && (e.metaKey || e.ctrlKey)) {\n\t\t\t\t\t\t// This is used in tandem with shape navigation.\n\t\t\t\t\t\tpreventDefault(e)\n\t\t\t\t\t}\n\t\t\t\t\tbreak\n\t\t\t\t}\n\t\t\t\tcase ',': {\n\t\t\t\t\t// this was moved to useKeyBoardShortcuts; it's possible\n\t\t\t\t\t// that the comma key is pressed when the container is not\n\t\t\t\t\t// focused, for example when the user has just interacted\n\t\t\t\t\t// with the toolbar. We need to handle it on the window\n\t\t\t\t\t// (ofc ensuring it's a correct time for a shortcut)\n\t\t\t\t\treturn\n\t\t\t\t}\n\t\t\t\tcase 'Escape': {\n\t\t\t\t\t// In certain browsers, pressing escape while in full screen mode\n\t\t\t\t\t// will exit full screen mode. We want to allow that, but not when\n\t\t\t\t\t// escape is being handled by the editor. When a user has an editing\n\t\t\t\t\t// shape, escape stops editing. When a user is using a tool, escape\n\t\t\t\t\t// returns to the select tool. When the user has selected shapes,\n\t\t\t\t\t// escape de-selects them. Only when the user's selection is empty\n\t\t\t\t\t// should we allow escape to do its normal thing.\n\n\t\t\t\t\tif (editor.getEditingShape() || editor.getSelectedShapeIds().length > 0) {\n\t\t\t\t\t\tpreventDefault(e)\n\t\t\t\t\t}\n\n\t\t\t\t\t// Don't do anything if we open menus open\n\t\t\t\t\tif (editor.menus.getOpenMenus().length > 0) return\n\n\t\t\t\t\tif (editor.inputs.keys.has('Escape')) {\n\t\t\t\t\t\t// noop\n\t\t\t\t\t} else {\n\t\t\t\t\t\teditor.inputs.keys.add('Escape')\n\n\t\t\t\t\t\teditor.cancel()\n\t\t\t\t\t\t// Pressing escape will focus the document.body,\n\t\t\t\t\t\t// which will cause the app to lose focus, which\n\t\t\t\t\t\t// will break additional shortcuts. We need to\n\t\t\t\t\t\t// refocus the container in order to keep these\n\t\t\t\t\t\t// shortcuts working.\n\t\t\t\t\t\tcontainer.focus()\n\t\t\t\t\t}\n\t\t\t\t\treturn\n\t\t\t\t}\n\t\t\t\tdefault: {\n\t\t\t\t\tif (areShortcutsDisabled(editor)) {\n\t\t\t\t\t\treturn\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tconst info: TLKeyboardEventInfo = {\n\t\t\t\ttype: 'keyboard',\n\t\t\t\tname: e.repeat ? 'key_repeat' : 'key_down',\n\t\t\t\tkey: e.key,\n\t\t\t\tcode: e.code,\n\t\t\t\tshiftKey: e.shiftKey,\n\t\t\t\taltKey: e.altKey,\n\t\t\t\tctrlKey: e.metaKey || e.ctrlKey,\n\t\t\t\tmetaKey: e.metaKey,\n\t\t\t\taccelKey: isAccelKey(e),\n\t\t\t}\n\n\t\t\teditor.dispatch(info)\n\t\t}\n\n\t\tconst handleKeyUp = (e: KeyboardEvent) => {\n\t\t\tif (editor.wasEventAlreadyHandled(e)) return\n\t\t\teditor.markEventAsHandled(e)\n\n\t\t\tif (areShortcutsDisabled(editor)) {\n\t\t\t\treturn\n\t\t\t}\n\n\t\t\tif (e.key === ',') {\n\t\t\t\treturn\n\t\t\t}\n\n\t\t\tconst info: TLKeyboardEventInfo = {\n\t\t\t\ttype: 'keyboard',\n\t\t\t\tname: 'key_up',\n\t\t\t\tkey: e.key,\n\t\t\t\tcode: e.code,\n\t\t\t\tshiftKey: e.shiftKey,\n\t\t\t\taltKey: e.altKey,\n\t\t\t\tctrlKey: e.metaKey || e.ctrlKey,\n\t\t\t\tmetaKey: e.metaKey,\n\t\t\t\taccelKey: isAccelKey(e),\n\t\t\t}\n\n\t\t\teditor.dispatch(info)\n\t\t}\n\n\t\tfunction handleTouchStart(e: TouchEvent) {\n\t\t\tif (container.contains(e.target as Node)) {\n\t\t\t\t// Center point of the touch area\n\t\t\t\tconst touchXPosition = e.touches[0].pageX\n\t\t\t\t// Size of the touch area\n\t\t\t\tconst touchXRadius = e.touches[0].radiusX || 0\n\n\t\t\t\t// We set a threshold (10px) on both sizes of the screen,\n\t\t\t\t// if the touch area overlaps with the screen edges\n\t\t\t\t// it's likely to trigger the navigation. We prevent the\n\t\t\t\t// touchstart event in that case.\n\t\t\t\t// todo: make this relative to the actual window, not the editor's screen bounds\n\t\t\t\tif (\n\t\t\t\t\ttouchXPosition - touchXRadius < 10 ||\n\t\t\t\t\ttouchXPosition + touchXRadius > editor.getViewportScreenBounds().width - 10\n\t\t\t\t) {\n\t\t\t\t\tif ((e.target as HTMLElement)?.tagName === 'BUTTON') {\n\t\t\t\t\t\t// Force a click before bailing\n\t\t\t\t\t\t;(e.target as HTMLButtonElement)?.click()\n\t\t\t\t\t}\n\n\t\t\t\t\tpreventDefault(e)\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Prevent wheel events that occur inside of the container\n\t\tconst handleWheel = (e: WheelEvent) => {\n\t\t\t// Ctrl/Meta key indicates a pinch event (funny, eh?)\n\t\t\tif (container.contains(e.target as Node) && (e.ctrlKey || e.metaKey)) {\n\t\t\t\tpreventDefault(e)\n\t\t\t}\n\t\t}\n\n\t\tcontainer.addEventListener('touchstart', handleTouchStart, { passive: false })\n\n\t\tcontainer.addEventListener('wheel', handleWheel, { passive: false })\n\n\t\tdocument.addEventListener('gesturestart', preventDefault)\n\t\tdocument.addEventListener('gesturechange', preventDefault)\n\t\tdocument.addEventListener('gestureend', preventDefault)\n\n\t\tcontainer.addEventListener('keydown', handleKeyDown)\n\t\tcontainer.addEventListener('keyup', handleKeyUp)\n\n\t\treturn () => {\n\t\t\tcontainer.removeEventListener('touchstart', handleTouchStart)\n\n\t\t\tcontainer.removeEventListener('wheel', handleWheel)\n\n\t\t\tdocument.removeEventListener('gesturestart', preventDefault)\n\t\t\tdocument.removeEventListener('gesturechange', preventDefault)\n\t\t\tdocument.removeEventListener('gestureend', preventDefault)\n\n\t\t\tcontainer.removeEventListener('keydown', handleKeyDown)\n\t\t\tcontainer.removeEventListener('keyup', handleKeyUp)\n\t\t}\n\t}, [editor, container, isAppFocused, isEditing])\n}\n\nfunction areShortcutsDisabled(editor: Editor) {\n\treturn editor.menus.hasOpenMenus() || activeElementShouldCaptureKeys()\n}\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["import { useValue } from '@tldraw/state-react'\nimport { useEffect } from 'react'\nimport { Editor } from '../editor/Editor'\nimport { TLKeyboardEventInfo } from '../editor/types/event-types'\nimport { activeElementShouldCaptureKeys, preventDefault } from '../utils/dom'\nimport { isAccelKey } from '../utils/keyboard'\nimport { useContainer } from './useContainer'\nimport { useEditor } from './useEditor'\n\nexport function useDocumentEvents() {\n\tconst editor = useEditor()\n\tconst container = useContainer()\n\n\tconst isEditing = useValue('isEditing', () => editor.getEditingShapeId(), [editor])\n\tconst isAppFocused = useValue('isFocused', () => editor.getIsFocused(), [editor])\n\n\t// Prevent the browser's default drag and drop behavior on our container (UI, etc)\n\tuseEffect(() => {\n\t\tif (!container) return\n\n\t\tfunction onDrop(e: DragEvent) {\n\t\t\t// this is tricky: we don't want the event to do anything\n\t\t\t// here, but we do want it to make its way to the canvas,\n\t\t\t// even if the drop is over some other element (like a toolbar),\n\t\t\t// so we're going to flag the event and then dispatch\n\t\t\t// it to the canvas; the canvas will handle it and try to\n\t\t\t// stop it from propagating back, but in case we do see it again,\n\t\t\t// we'll look for the flag so we know to stop it from being\n\t\t\t// re-dispatched, which would lead to an infinite loop.\n\t\t\tif ((e as any).isSpecialRedispatchedEvent) return\n\t\t\tpreventDefault(e)\n\t\t\te.stopPropagation()\n\t\t\tconst cvs = container.querySelector('.tl-canvas')\n\t\t\tif (!cvs) return\n\t\t\tconst newEvent = new DragEvent(e.type, e)\n\t\t\t;(newEvent as any).isSpecialRedispatchedEvent = true\n\t\t\tcvs.dispatchEvent(newEvent)\n\t\t}\n\n\t\tcontainer.addEventListener('dragover', onDrop)\n\t\tcontainer.addEventListener('drop', onDrop)\n\t\treturn () => {\n\t\t\tcontainer.removeEventListener('dragover', onDrop)\n\t\t\tcontainer.removeEventListener('drop', onDrop)\n\t\t}\n\t}, [container])\n\n\tuseEffect(() => {\n\t\tconst win = editor.getContainerWindow()\n\t\tif (!('matchMedia' in win)) return\n\n\t\t// https://developer.mozilla.org/en-US/docs/Web/API/Window/devicePixelRatio#monitoring_screen_resolution_or_zoom_level_changes\n\t\tlet remove: (() => void) | null = null\n\t\tconst updatePixelRatio = () => {\n\t\t\tif (remove != null) {\n\t\t\t\tremove()\n\t\t\t}\n\t\t\tconst mqString = `(resolution: ${win.devicePixelRatio}dppx)`\n\t\t\tconst media = win.matchMedia(mqString)\n\t\t\t// Safari only started supporting `addEventListener('change',...) in version 14\n\t\t\t// https://developer.mozilla.org/en-US/docs/Web/API/MediaQueryList/change_event\n\t\t\tconst safariCb = (ev: any) => {\n\t\t\t\tif (ev.type === 'change') {\n\t\t\t\t\tupdatePixelRatio()\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (media.addEventListener) {\n\t\t\t\tmedia.addEventListener('change', updatePixelRatio)\n\t\t\t\t// eslint-disable-next-line @typescript-eslint/no-deprecated\n\t\t\t} else if (media.addListener) {\n\t\t\t\t// eslint-disable-next-line @typescript-eslint/no-deprecated\n\t\t\t\tmedia.addListener(safariCb)\n\t\t\t}\n\t\t\tremove = () => {\n\t\t\t\tif (media.removeEventListener) {\n\t\t\t\t\tmedia.removeEventListener('change', updatePixelRatio)\n\t\t\t\t\t// eslint-disable-next-line @typescript-eslint/no-deprecated\n\t\t\t\t} else if (media.removeListener) {\n\t\t\t\t\t// eslint-disable-next-line @typescript-eslint/no-deprecated\n\t\t\t\t\tmedia.removeListener(safariCb)\n\t\t\t\t}\n\t\t\t}\n\t\t\teditor.updateInstanceState({ devicePixelRatio: win.devicePixelRatio })\n\t\t}\n\t\tupdatePixelRatio()\n\t\treturn () => {\n\t\t\tremove?.()\n\t\t}\n\t}, [editor])\n\n\tuseEffect(() => {\n\t\tif (!isAppFocused) return\n\n\t\tconst handleKeyDown = (e: KeyboardEvent) => {\n\t\t\tif (\n\t\t\t\te.altKey &&\n\t\t\t\t// todo: When should we allow the alt key to be used? Perhaps states should declare which keys matter to them?\n\t\t\t\t(editor.isIn('zoom') || !editor.getPath().endsWith('.idle')) &&\n\t\t\t\t!areShortcutsDisabled(editor)\n\t\t\t) {\n\t\t\t\t// On windows the alt key opens the menu bar.\n\t\t\t\t// We want to prevent that if the user is doing something else,\n\t\t\t\t// e.g. resizing a shape\n\t\t\t\tpreventDefault(e)\n\t\t\t}\n\n\t\t\tif (editor.wasEventAlreadyHandled(e)) return\n\t\t\teditor.markEventAsHandled(e)\n\t\t\tconst hasSelectedShapes = !!editor.getSelectedShapeIds().length\n\n\t\t\tswitch (e.key) {\n\t\t\t\tcase '=':\n\t\t\t\tcase '-':\n\t\t\t\tcase '0': {\n\t\t\t\t\t// These keys are used for zooming. Technically we only use\n\t\t\t\t\t// the + - and 0 keys, however it's common for them to be\n\t\t\t\t\t// paired with modifier keys (command / control) so we need\n\t\t\t\t\t// to prevent the browser's regular actions (i.e. zooming\n\t\t\t\t\t// the page). A user can zoom by unfocusing the editor.\n\t\t\t\t\tif (e.metaKey || e.ctrlKey) {\n\t\t\t\t\t\tpreventDefault(e)\n\t\t\t\t\t\treturn\n\t\t\t\t\t}\n\t\t\t\t\tbreak\n\t\t\t\t}\n\t\t\t\tcase 'Tab': {\n\t\t\t\t\tif (areShortcutsDisabled(editor)) {\n\t\t\t\t\t\treturn\n\t\t\t\t\t}\n\t\t\t\t\t// isEditing here sounds like it's about text editing\n\t\t\t\t\t// but more specifically, this is so you can tab into an\n\t\t\t\t\t// embed that's being 'edited'. In our world,\n\t\t\t\t\t// editing an embed, means it's interactive.\n\t\t\t\t\tif (hasSelectedShapes && !isEditing) {\n\t\t\t\t\t\t// This is used in tandem with shape navigation.\n\t\t\t\t\t\tpreventDefault(e)\n\t\t\t\t\t}\n\t\t\t\t\tbreak\n\t\t\t\t}\n\t\t\t\tcase 'ArrowLeft':\n\t\t\t\tcase 'ArrowRight':\n\t\t\t\tcase 'ArrowUp':\n\t\t\t\tcase 'ArrowDown': {\n\t\t\t\t\tif (areShortcutsDisabled(editor)) {\n\t\t\t\t\t\treturn\n\t\t\t\t\t}\n\t\t\t\t\tif (hasSelectedShapes && (e.metaKey || e.ctrlKey)) {\n\t\t\t\t\t\t// This is used in tandem with shape navigation.\n\t\t\t\t\t\tpreventDefault(e)\n\t\t\t\t\t}\n\t\t\t\t\tbreak\n\t\t\t\t}\n\t\t\t\tcase ',': {\n\t\t\t\t\t// this was moved to useKeyBoardShortcuts; it's possible\n\t\t\t\t\t// that the comma key is pressed when the container is not\n\t\t\t\t\t// focused, for example when the user has just interacted\n\t\t\t\t\t// with the toolbar. We need to handle it on the window\n\t\t\t\t\t// (ofc ensuring it's a correct time for a shortcut)\n\t\t\t\t\treturn\n\t\t\t\t}\n\t\t\t\tcase 'Escape': {\n\t\t\t\t\t// In certain browsers, pressing escape while in full screen mode\n\t\t\t\t\t// will exit full screen mode. We want to allow that, but not when\n\t\t\t\t\t// escape is being handled by the editor. When a user has an editing\n\t\t\t\t\t// shape, escape stops editing. When a user is using a tool, escape\n\t\t\t\t\t// returns to the select tool. When the user has selected shapes,\n\t\t\t\t\t// escape de-selects them. Only when the user's selection is empty\n\t\t\t\t\t// should we allow escape to do its normal thing.\n\n\t\t\t\t\tif (editor.getEditingShape() || editor.getSelectedShapeIds().length > 0) {\n\t\t\t\t\t\tpreventDefault(e)\n\t\t\t\t\t}\n\n\t\t\t\t\t// Don't do anything if we open menus open\n\t\t\t\t\tif (editor.menus.getOpenMenus().length > 0) return\n\n\t\t\t\t\tif (editor.inputs.keys.has('Escape')) {\n\t\t\t\t\t\t// noop\n\t\t\t\t\t} else {\n\t\t\t\t\t\teditor.inputs.keys.add('Escape')\n\n\t\t\t\t\t\teditor.cancel()\n\t\t\t\t\t\t// Pressing escape will focus the document.body,\n\t\t\t\t\t\t// which will cause the app to lose focus, which\n\t\t\t\t\t\t// will break additional shortcuts. We need to\n\t\t\t\t\t\t// refocus the container in order to keep these\n\t\t\t\t\t\t// shortcuts working.\n\t\t\t\t\t\tcontainer.focus()\n\t\t\t\t\t}\n\t\t\t\t\treturn\n\t\t\t\t}\n\t\t\t\tdefault: {\n\t\t\t\t\tif (areShortcutsDisabled(editor)) {\n\t\t\t\t\t\treturn\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tconst info: TLKeyboardEventInfo = {\n\t\t\t\ttype: 'keyboard',\n\t\t\t\tname: e.repeat ? 'key_repeat' : 'key_down',\n\t\t\t\tkey: e.key,\n\t\t\t\tcode: e.code,\n\t\t\t\tshiftKey: e.shiftKey,\n\t\t\t\taltKey: e.altKey,\n\t\t\t\tctrlKey: e.metaKey || e.ctrlKey,\n\t\t\t\tmetaKey: e.metaKey,\n\t\t\t\taccelKey: isAccelKey(e),\n\t\t\t}\n\n\t\t\teditor.dispatch(info)\n\t\t}\n\n\t\tconst handleKeyUp = (e: KeyboardEvent) => {\n\t\t\tif (editor.wasEventAlreadyHandled(e)) return\n\t\t\teditor.markEventAsHandled(e)\n\n\t\t\tif (areShortcutsDisabled(editor)) {\n\t\t\t\treturn\n\t\t\t}\n\n\t\t\tif (e.key === ',') {\n\t\t\t\treturn\n\t\t\t}\n\n\t\t\tconst info: TLKeyboardEventInfo = {\n\t\t\t\ttype: 'keyboard',\n\t\t\t\tname: 'key_up',\n\t\t\t\tkey: e.key,\n\t\t\t\tcode: e.code,\n\t\t\t\tshiftKey: e.shiftKey,\n\t\t\t\taltKey: e.altKey,\n\t\t\t\tctrlKey: e.metaKey || e.ctrlKey,\n\t\t\t\tmetaKey: e.metaKey,\n\t\t\t\taccelKey: isAccelKey(e),\n\t\t\t}\n\n\t\t\teditor.dispatch(info)\n\t\t}\n\n\t\tfunction handleTouchStart(e: TouchEvent) {\n\t\t\tif (container.contains(e.target as Node)) {\n\t\t\t\t// Center point of the touch area\n\t\t\t\tconst touchXPosition = e.touches[0].pageX\n\t\t\t\t// Size of the touch area\n\t\t\t\tconst touchXRadius = e.touches[0].radiusX || 0\n\n\t\t\t\t// We set a threshold (10px) on both sizes of the screen,\n\t\t\t\t// if the touch area overlaps with the screen edges\n\t\t\t\t// it's likely to trigger the navigation. We prevent the\n\t\t\t\t// touchstart event in that case.\n\t\t\t\t// todo: make this relative to the actual window, not the editor's screen bounds\n\t\t\t\tif (\n\t\t\t\t\ttouchXPosition - touchXRadius < 10 ||\n\t\t\t\t\ttouchXPosition + touchXRadius > editor.getViewportScreenBounds().width - 10\n\t\t\t\t) {\n\t\t\t\t\tif ((e.target as HTMLElement)?.tagName === 'BUTTON') {\n\t\t\t\t\t\t// Force a click before bailing\n\t\t\t\t\t\t;(e.target as HTMLButtonElement)?.click()\n\t\t\t\t\t}\n\n\t\t\t\t\tpreventDefault(e)\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Prevent wheel events that occur inside of the container\n\t\tconst handleWheel = (e: WheelEvent) => {\n\t\t\t// Ctrl/Meta key indicates a pinch event (funny, eh?)\n\t\t\tif (container.contains(e.target as Node) && (e.ctrlKey || e.metaKey)) {\n\t\t\t\tpreventDefault(e)\n\t\t\t}\n\t\t}\n\n\t\tcontainer.addEventListener('touchstart', handleTouchStart, { passive: false })\n\n\t\tcontainer.addEventListener('wheel', handleWheel, { passive: false })\n\n\t\tconst ownerDoc = container.ownerDocument\n\t\townerDoc.addEventListener('gesturestart', preventDefault)\n\t\townerDoc.addEventListener('gesturechange', preventDefault)\n\t\townerDoc.addEventListener('gestureend', preventDefault)\n\n\t\tcontainer.addEventListener('keydown', handleKeyDown)\n\t\tcontainer.addEventListener('keyup', handleKeyUp)\n\n\t\treturn () => {\n\t\t\tcontainer.removeEventListener('touchstart', handleTouchStart)\n\n\t\t\tcontainer.removeEventListener('wheel', handleWheel)\n\n\t\t\townerDoc.removeEventListener('gesturestart', preventDefault)\n\t\t\townerDoc.removeEventListener('gesturechange', preventDefault)\n\t\t\townerDoc.removeEventListener('gestureend', preventDefault)\n\n\t\t\tcontainer.removeEventListener('keydown', handleKeyDown)\n\t\t\tcontainer.removeEventListener('keyup', handleKeyUp)\n\t\t}\n\t}, [editor, container, isAppFocused, isEditing])\n}\n\nfunction areShortcutsDisabled(editor: Editor) {\n\treturn (\n\t\teditor.menus.hasOpenMenus() ||\n\t\tactiveElementShouldCaptureKeys(true, editor.getContainerDocument())\n\t)\n}\n"],
5
+ "mappings": "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",
6
6
  "names": []
7
7
  }
@@ -24,17 +24,17 @@ module.exports = __toCommonJS(useFixSafariDoubleTapZoomPencilEvents_exports);
24
24
  var import_react = require("react");
25
25
  var import_dom = require("../utils/dom");
26
26
  var import_useEditor = require("./useEditor");
27
- const IGNORED_TAGS = ["textarea", "input"];
28
27
  function useFixSafariDoubleTapZoomPencilEvents(ref) {
29
28
  const editor = (0, import_useEditor.useEditor)();
30
29
  (0, import_react.useEffect)(() => {
31
30
  const elm = ref.current;
32
31
  if (!elm) return;
32
+ const win = editor.getContainerWindow();
33
33
  const handleEvent = (e) => {
34
- if (e instanceof PointerEvent && e.pointerType === "pen") {
34
+ if (e instanceof win.PointerEvent && e.pointerType === "pen") {
35
35
  editor.markEventAsHandled(e);
36
36
  const { target } = e;
37
- if (IGNORED_TAGS.includes(target.tagName?.toLocaleLowerCase()) || target.isContentEditable || editor.isIn("select.editing_shape")) {
37
+ if ((0, import_dom.elementShouldCaptureKeys)(target instanceof win.Element ? target : null, false) || editor.isIn("select.editing_shape")) {
38
38
  return;
39
39
  }
40
40
  (0, import_dom.preventDefault)(e);
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../src/lib/hooks/useFixSafariDoubleTapZoomPencilEvents.ts"],
4
- "sourcesContent": ["import { useEffect } from 'react'\nimport { preventDefault } from '../utils/dom'\nimport { useEditor } from './useEditor'\n\nconst IGNORED_TAGS = ['textarea', 'input']\n\n/**\n * When double tapping with the pencil in iOS, it enables a little zoom window in the UI. We don't\n * want this for drawing operations and can disable it by setting 'disableDoubleTapZoom' in the main\n * editor.\n */\nexport function useFixSafariDoubleTapZoomPencilEvents(ref: React.RefObject<HTMLElement | null>) {\n\tconst editor = useEditor()\n\n\tuseEffect(() => {\n\t\tconst elm = ref.current\n\n\t\tif (!elm) return\n\n\t\tconst handleEvent = (e: PointerEvent | TouchEvent) => {\n\t\t\tif (e instanceof PointerEvent && e.pointerType === 'pen') {\n\t\t\t\teditor.markEventAsHandled(e)\n\t\t\t\tconst { target } = e\n\n\t\t\t\t// Allow events to propagate if the app is editing a shape, or if the event is occurring in a text area or input\n\t\t\t\tif (\n\t\t\t\t\tIGNORED_TAGS.includes((target as Element).tagName?.toLocaleLowerCase()) ||\n\t\t\t\t\t(target as HTMLElement).isContentEditable ||\n\t\t\t\t\teditor.isIn('select.editing_shape')\n\t\t\t\t) {\n\t\t\t\t\treturn\n\t\t\t\t}\n\n\t\t\t\tpreventDefault(e)\n\t\t\t}\n\t\t}\n\n\t\telm.addEventListener('touchstart', handleEvent)\n\t\telm.addEventListener('touchend', handleEvent)\n\t\treturn () => {\n\t\t\telm.removeEventListener('touchstart', handleEvent)\n\t\t\telm.removeEventListener('touchend', handleEvent)\n\t\t}\n\t}, [editor, ref])\n}\n"],
5
- "mappings": ";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,mBAA0B;AAC1B,iBAA+B;AAC/B,uBAA0B;AAE1B,MAAM,eAAe,CAAC,YAAY,OAAO;AAOlC,SAAS,sCAAsC,KAA0C;AAC/F,QAAM,aAAS,4BAAU;AAEzB,8BAAU,MAAM;AACf,UAAM,MAAM,IAAI;AAEhB,QAAI,CAAC,IAAK;AAEV,UAAM,cAAc,CAAC,MAAiC;AACrD,UAAI,aAAa,gBAAgB,EAAE,gBAAgB,OAAO;AACzD,eAAO,mBAAmB,CAAC;AAC3B,cAAM,EAAE,OAAO,IAAI;AAGnB,YACC,aAAa,SAAU,OAAmB,SAAS,kBAAkB,CAAC,KACrE,OAAuB,qBACxB,OAAO,KAAK,sBAAsB,GACjC;AACD;AAAA,QACD;AAEA,uCAAe,CAAC;AAAA,MACjB;AAAA,IACD;AAEA,QAAI,iBAAiB,cAAc,WAAW;AAC9C,QAAI,iBAAiB,YAAY,WAAW;AAC5C,WAAO,MAAM;AACZ,UAAI,oBAAoB,cAAc,WAAW;AACjD,UAAI,oBAAoB,YAAY,WAAW;AAAA,IAChD;AAAA,EACD,GAAG,CAAC,QAAQ,GAAG,CAAC;AACjB;",
4
+ "sourcesContent": ["import { useEffect } from 'react'\nimport { elementShouldCaptureKeys, preventDefault } from '../utils/dom'\nimport { useEditor } from './useEditor'\n\n/**\n * When double tapping with the pencil in iOS, it enables a little zoom window in the UI. We don't\n * want this for drawing operations and can disable it by setting 'disableDoubleTapZoom' in the main\n * editor.\n */\nexport function useFixSafariDoubleTapZoomPencilEvents(ref: React.RefObject<HTMLElement | null>) {\n\tconst editor = useEditor()\n\n\tuseEffect(() => {\n\t\tconst elm = ref.current\n\n\t\tif (!elm) return\n\n\t\tconst win = editor.getContainerWindow()\n\t\tconst handleEvent = (e: PointerEvent | TouchEvent) => {\n\t\t\tif (e instanceof win.PointerEvent && e.pointerType === 'pen') {\n\t\t\t\teditor.markEventAsHandled(e)\n\t\t\t\tconst { target } = e\n\n\t\t\t\tif (\n\t\t\t\t\telementShouldCaptureKeys(target instanceof win.Element ? target : null, false) ||\n\t\t\t\t\teditor.isIn('select.editing_shape')\n\t\t\t\t) {\n\t\t\t\t\treturn\n\t\t\t\t}\n\n\t\t\t\tpreventDefault(e)\n\t\t\t}\n\t\t}\n\n\t\telm.addEventListener('touchstart', handleEvent)\n\t\telm.addEventListener('touchend', handleEvent)\n\t\treturn () => {\n\t\t\telm.removeEventListener('touchstart', handleEvent)\n\t\t\telm.removeEventListener('touchend', handleEvent)\n\t\t}\n\t}, [editor, ref])\n}\n"],
5
+ "mappings": ";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,mBAA0B;AAC1B,iBAAyD;AACzD,uBAA0B;AAOnB,SAAS,sCAAsC,KAA0C;AAC/F,QAAM,aAAS,4BAAU;AAEzB,8BAAU,MAAM;AACf,UAAM,MAAM,IAAI;AAEhB,QAAI,CAAC,IAAK;AAEV,UAAM,MAAM,OAAO,mBAAmB;AACtC,UAAM,cAAc,CAAC,MAAiC;AACrD,UAAI,aAAa,IAAI,gBAAgB,EAAE,gBAAgB,OAAO;AAC7D,eAAO,mBAAmB,CAAC;AAC3B,cAAM,EAAE,OAAO,IAAI;AAEnB,gBACC,qCAAyB,kBAAkB,IAAI,UAAU,SAAS,MAAM,KAAK,KAC7E,OAAO,KAAK,sBAAsB,GACjC;AACD;AAAA,QACD;AAEA,uCAAe,CAAC;AAAA,MACjB;AAAA,IACD;AAEA,QAAI,iBAAiB,cAAc,WAAW;AAC9C,QAAI,iBAAiB,YAAY,WAAW;AAC5C,WAAO,MAAM;AACZ,UAAI,oBAAoB,cAAc,WAAW;AACjD,UAAI,oBAAoB,YAAY,WAAW;AAAA,IAChD;AAAA,EACD,GAAG,CAAC,QAAQ,GAAG,CAAC;AACjB;",
6
6
  "names": []
7
7
  }
@@ -23,6 +23,7 @@ __export(useScreenBounds_exports, {
23
23
  module.exports = __toCommonJS(useScreenBounds_exports);
24
24
  var import_utils = require("@tldraw/utils");
25
25
  var import_react = require("react");
26
+ var import_domUtils = require("../exports/domUtils");
26
27
  var import_useEditor = require("./useEditor");
27
28
  function useScreenBounds(ref) {
28
29
  const editor = (0, import_useEditor.useEditor)();
@@ -38,7 +39,8 @@ function useScreenBounds(ref) {
38
39
  }
39
40
  );
40
41
  const interval = editor.timers.setInterval(updateBounds, 1e3);
41
- window.addEventListener("resize", updateBounds);
42
+ const win = editor.getContainerWindow();
43
+ win.addEventListener("resize", updateBounds);
42
44
  const resizeObserver = new ResizeObserver((entries) => {
43
45
  if (!entries[0].contentRect) return;
44
46
  updateBounds();
@@ -52,7 +54,7 @@ function useScreenBounds(ref) {
52
54
  }
53
55
  return () => {
54
56
  clearInterval(interval);
55
- window.removeEventListener("resize", updateBounds);
57
+ win.removeEventListener("resize", updateBounds);
56
58
  resizeObserver.disconnect();
57
59
  scrollingParent?.removeEventListener("scroll", updateBounds);
58
60
  updateBounds.cancel();
@@ -65,18 +67,20 @@ function useScreenBounds(ref) {
65
67
  * https://github.com/excalidraw/excalidraw/blob/48c3465b19f10ec755b3eb84e21a01a468e96e43/packages/excalidraw/utils.ts#L600
66
68
  */
67
69
  const getNearestScrollableContainer = (element) => {
70
+ const doc = element.ownerDocument;
71
+ const win = (0, import_domUtils.getOwnerWindow)(element);
68
72
  let parent = element.parentElement;
69
73
  while (parent) {
70
- if (parent === document.body) {
71
- return document;
74
+ if (parent === doc.body) {
75
+ return doc;
72
76
  }
73
- const { overflowY } = window.getComputedStyle(parent);
77
+ const { overflowY } = win.getComputedStyle(parent);
74
78
  const hasScrollableContent = parent.scrollHeight > parent.clientHeight;
75
79
  if (hasScrollableContent && (overflowY === "auto" || overflowY === "scroll" || overflowY === "overlay")) {
76
80
  return parent;
77
81
  }
78
82
  parent = parent.parentElement;
79
83
  }
80
- return document;
84
+ return doc;
81
85
  };
82
86
  //# sourceMappingURL=useScreenBounds.js.map
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../src/lib/hooks/useScreenBounds.ts"],
4
- "sourcesContent": ["import { throttle } from '@tldraw/utils'\nimport { useLayoutEffect } from 'react'\nimport { useEditor } from './useEditor'\n\nexport function useScreenBounds(ref: React.RefObject<HTMLElement | null>) {\n\tconst editor = useEditor()\n\n\tuseLayoutEffect(() => {\n\t\t// Everything else uses a debounced update...\n\t\tconst updateBounds = throttle(\n\t\t\t() => {\n\t\t\t\tif (!ref.current) return\n\t\t\t\teditor.updateViewportScreenBounds(ref.current)\n\t\t\t},\n\t\t\t200,\n\t\t\t{\n\t\t\t\ttrailing: true,\n\t\t\t}\n\t\t)\n\n\t\t// Rather than running getClientRects on every frame, we'll\n\t\t// run it once a second or when the window resizes.\n\t\tconst interval = editor.timers.setInterval(updateBounds, 1000)\n\t\twindow.addEventListener('resize', updateBounds)\n\n\t\tconst resizeObserver = new ResizeObserver((entries) => {\n\t\t\tif (!entries[0].contentRect) return\n\t\t\tupdateBounds()\n\t\t})\n\n\t\tconst container = ref.current\n\t\tlet scrollingParent: HTMLElement | Document | null = null\n\n\t\tif (container) {\n\t\t\t// When the container's size changes, update the bounds\n\t\t\tresizeObserver.observe(container)\n\n\t\t\t// When the container's nearest scrollable parent scrolls, update the bounds\n\t\t\tscrollingParent = getNearestScrollableContainer(container)\n\t\t\tscrollingParent.addEventListener('scroll', updateBounds)\n\t\t}\n\n\t\treturn () => {\n\t\t\tclearInterval(interval)\n\t\t\twindow.removeEventListener('resize', updateBounds)\n\t\t\tresizeObserver.disconnect()\n\t\t\tscrollingParent?.removeEventListener('scroll', updateBounds)\n\t\t\tupdateBounds.cancel()\n\t\t}\n\t}, [editor, ref])\n}\n\n/*!\n * Author: excalidraw\n * MIT License: https://github.com/excalidraw/excalidraw/blob/master/LICENSE\n * https://github.com/excalidraw/excalidraw/blob/48c3465b19f10ec755b3eb84e21a01a468e96e43/packages/excalidraw/utils.ts#L600\n */\nconst getNearestScrollableContainer = (element: HTMLElement): HTMLElement | Document => {\n\tlet parent = element.parentElement\n\twhile (parent) {\n\t\tif (parent === document.body) {\n\t\t\treturn document\n\t\t}\n\t\tconst { overflowY } = window.getComputedStyle(parent)\n\t\tconst hasScrollableContent = parent.scrollHeight > parent.clientHeight\n\t\tif (\n\t\t\thasScrollableContent &&\n\t\t\t(overflowY === 'auto' || overflowY === 'scroll' || overflowY === 'overlay')\n\t\t) {\n\t\t\treturn parent\n\t\t}\n\t\tparent = parent.parentElement\n\t}\n\treturn document\n}\n"],
5
- "mappings": ";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,mBAAyB;AACzB,mBAAgC;AAChC,uBAA0B;AAEnB,SAAS,gBAAgB,KAA0C;AACzE,QAAM,aAAS,4BAAU;AAEzB,oCAAgB,MAAM;AAErB,UAAM,mBAAe;AAAA,MACpB,MAAM;AACL,YAAI,CAAC,IAAI,QAAS;AAClB,eAAO,2BAA2B,IAAI,OAAO;AAAA,MAC9C;AAAA,MACA;AAAA,MACA;AAAA,QACC,UAAU;AAAA,MACX;AAAA,IACD;AAIA,UAAM,WAAW,OAAO,OAAO,YAAY,cAAc,GAAI;AAC7D,WAAO,iBAAiB,UAAU,YAAY;AAE9C,UAAM,iBAAiB,IAAI,eAAe,CAAC,YAAY;AACtD,UAAI,CAAC,QAAQ,CAAC,EAAE,YAAa;AAC7B,mBAAa;AAAA,IACd,CAAC;AAED,UAAM,YAAY,IAAI;AACtB,QAAI,kBAAiD;AAErD,QAAI,WAAW;AAEd,qBAAe,QAAQ,SAAS;AAGhC,wBAAkB,8BAA8B,SAAS;AACzD,sBAAgB,iBAAiB,UAAU,YAAY;AAAA,IACxD;AAEA,WAAO,MAAM;AACZ,oBAAc,QAAQ;AACtB,aAAO,oBAAoB,UAAU,YAAY;AACjD,qBAAe,WAAW;AAC1B,uBAAiB,oBAAoB,UAAU,YAAY;AAC3D,mBAAa,OAAO;AAAA,IACrB;AAAA,EACD,GAAG,CAAC,QAAQ,GAAG,CAAC;AACjB;AAEA;AAAA;AAAA;AAAA;AAAA;AAKA,MAAM,gCAAgC,CAAC,YAAiD;AACvF,MAAI,SAAS,QAAQ;AACrB,SAAO,QAAQ;AACd,QAAI,WAAW,SAAS,MAAM;AAC7B,aAAO;AAAA,IACR;AACA,UAAM,EAAE,UAAU,IAAI,OAAO,iBAAiB,MAAM;AACpD,UAAM,uBAAuB,OAAO,eAAe,OAAO;AAC1D,QACC,yBACC,cAAc,UAAU,cAAc,YAAY,cAAc,YAChE;AACD,aAAO;AAAA,IACR;AACA,aAAS,OAAO;AAAA,EACjB;AACA,SAAO;AACR;",
4
+ "sourcesContent": ["import { throttle } from '@tldraw/utils'\nimport { useLayoutEffect } from 'react'\nimport { getOwnerWindow } from '../exports/domUtils'\nimport { useEditor } from './useEditor'\n\nexport function useScreenBounds(ref: React.RefObject<HTMLElement | null>) {\n\tconst editor = useEditor()\n\n\tuseLayoutEffect(() => {\n\t\t// Everything else uses a debounced update...\n\t\tconst updateBounds = throttle(\n\t\t\t() => {\n\t\t\t\tif (!ref.current) return\n\t\t\t\teditor.updateViewportScreenBounds(ref.current)\n\t\t\t},\n\t\t\t200,\n\t\t\t{\n\t\t\t\ttrailing: true,\n\t\t\t}\n\t\t)\n\n\t\t// Rather than running getClientRects on every frame, we'll\n\t\t// run it once a second or when the window resizes.\n\t\tconst interval = editor.timers.setInterval(updateBounds, 1000)\n\t\tconst win = editor.getContainerWindow()\n\t\twin.addEventListener('resize', updateBounds)\n\n\t\tconst resizeObserver = new ResizeObserver((entries) => {\n\t\t\tif (!entries[0].contentRect) return\n\t\t\tupdateBounds()\n\t\t})\n\n\t\tconst container = ref.current\n\t\tlet scrollingParent: HTMLElement | Document | null = null\n\n\t\tif (container) {\n\t\t\t// When the container's size changes, update the bounds\n\t\t\tresizeObserver.observe(container)\n\n\t\t\t// When the container's nearest scrollable parent scrolls, update the bounds\n\t\t\tscrollingParent = getNearestScrollableContainer(container)\n\t\t\tscrollingParent.addEventListener('scroll', updateBounds)\n\t\t}\n\n\t\treturn () => {\n\t\t\tclearInterval(interval)\n\t\t\twin.removeEventListener('resize', updateBounds)\n\t\t\tresizeObserver.disconnect()\n\t\t\tscrollingParent?.removeEventListener('scroll', updateBounds)\n\t\t\tupdateBounds.cancel()\n\t\t}\n\t}, [editor, ref])\n}\n\n/*!\n * Author: excalidraw\n * MIT License: https://github.com/excalidraw/excalidraw/blob/master/LICENSE\n * https://github.com/excalidraw/excalidraw/blob/48c3465b19f10ec755b3eb84e21a01a468e96e43/packages/excalidraw/utils.ts#L600\n */\nconst getNearestScrollableContainer = (element: HTMLElement): HTMLElement | Document => {\n\tconst doc = element.ownerDocument\n\tconst win = getOwnerWindow(element)\n\tlet parent = element.parentElement\n\twhile (parent) {\n\t\tif (parent === doc.body) {\n\t\t\treturn doc\n\t\t}\n\t\tconst { overflowY } = win.getComputedStyle(parent)\n\t\tconst hasScrollableContent = parent.scrollHeight > parent.clientHeight\n\t\tif (\n\t\t\thasScrollableContent &&\n\t\t\t(overflowY === 'auto' || overflowY === 'scroll' || overflowY === 'overlay')\n\t\t) {\n\t\t\treturn parent\n\t\t}\n\t\tparent = parent.parentElement\n\t}\n\treturn doc\n}\n"],
5
+ "mappings": ";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,mBAAyB;AACzB,mBAAgC;AAChC,sBAA+B;AAC/B,uBAA0B;AAEnB,SAAS,gBAAgB,KAA0C;AACzE,QAAM,aAAS,4BAAU;AAEzB,oCAAgB,MAAM;AAErB,UAAM,mBAAe;AAAA,MACpB,MAAM;AACL,YAAI,CAAC,IAAI,QAAS;AAClB,eAAO,2BAA2B,IAAI,OAAO;AAAA,MAC9C;AAAA,MACA;AAAA,MACA;AAAA,QACC,UAAU;AAAA,MACX;AAAA,IACD;AAIA,UAAM,WAAW,OAAO,OAAO,YAAY,cAAc,GAAI;AAC7D,UAAM,MAAM,OAAO,mBAAmB;AACtC,QAAI,iBAAiB,UAAU,YAAY;AAE3C,UAAM,iBAAiB,IAAI,eAAe,CAAC,YAAY;AACtD,UAAI,CAAC,QAAQ,CAAC,EAAE,YAAa;AAC7B,mBAAa;AAAA,IACd,CAAC;AAED,UAAM,YAAY,IAAI;AACtB,QAAI,kBAAiD;AAErD,QAAI,WAAW;AAEd,qBAAe,QAAQ,SAAS;AAGhC,wBAAkB,8BAA8B,SAAS;AACzD,sBAAgB,iBAAiB,UAAU,YAAY;AAAA,IACxD;AAEA,WAAO,MAAM;AACZ,oBAAc,QAAQ;AACtB,UAAI,oBAAoB,UAAU,YAAY;AAC9C,qBAAe,WAAW;AAC1B,uBAAiB,oBAAoB,UAAU,YAAY;AAC3D,mBAAa,OAAO;AAAA,IACrB;AAAA,EACD,GAAG,CAAC,QAAQ,GAAG,CAAC;AACjB;AAEA;AAAA;AAAA;AAAA;AAAA;AAKA,MAAM,gCAAgC,CAAC,YAAiD;AACvF,QAAM,MAAM,QAAQ;AACpB,QAAM,UAAM,gCAAe,OAAO;AAClC,MAAI,SAAS,QAAQ;AACrB,SAAO,QAAQ;AACd,QAAI,WAAW,IAAI,MAAM;AACxB,aAAO;AAAA,IACR;AACA,UAAM,EAAE,UAAU,IAAI,IAAI,iBAAiB,MAAM;AACjD,UAAM,uBAAuB,OAAO,eAAe,OAAO;AAC1D,QACC,yBACC,cAAc,UAAU,cAAc,YAAY,cAAc,YAChE;AACD,aAAO;AAAA,IACR;AACA,aAAS,OAAO;AAAA,EACjB;AACA,SAAO;AACR;",
6
6
  "names": []
7
7
  }
@@ -22,6 +22,7 @@ __export(useViewportHeight_exports, {
22
22
  });
23
23
  module.exports = __toCommonJS(useViewportHeight_exports);
24
24
  var import_react = require("react");
25
+ var import_useEditor = require("./useEditor");
25
26
  /*!
26
27
  * BSD License: https://github.com/outline/rich-markdown-editor/blob/main/LICENSE
27
28
  * Copyright (c) 2020 General Outline, Inc (https://www.getoutline.com/) and individual contributors.
@@ -33,24 +34,25 @@ var import_react = require("react");
33
34
  * while using the virtual keyboard.
34
35
  */
35
36
  function useViewportHeight() {
36
- const visualViewport = window.visualViewport;
37
+ const editor = (0, import_useEditor.useMaybeEditor)();
38
+ const win = editor?.getContainerWindow() ?? window;
39
+ const vv = win.visualViewport;
37
40
  const [height, setHeight] = (0, import_react.useState)(
38
- () => visualViewport ? visualViewport.height + visualViewport.offsetTop : window.innerHeight
41
+ () => vv ? vv.height + vv.offsetTop : win.innerHeight
39
42
  );
40
43
  (0, import_react.useLayoutEffect)(() => {
44
+ const win2 = editor?.getContainerWindow() ?? window;
41
45
  const handleResize = () => {
42
- const visualViewport2 = window.visualViewport;
43
- setHeight(
44
- () => visualViewport2 ? visualViewport2.height + visualViewport2.offsetTop : window.innerHeight
45
- );
46
+ const vv2 = win2.visualViewport;
47
+ setHeight(() => vv2 ? vv2.height + vv2.offsetTop : win2.innerHeight);
46
48
  };
47
- window.visualViewport?.addEventListener("resize", handleResize);
48
- window.visualViewport?.addEventListener("scroll", handleResize);
49
+ win2.visualViewport?.addEventListener("resize", handleResize);
50
+ win2.visualViewport?.addEventListener("scroll", handleResize);
49
51
  return () => {
50
- window.visualViewport?.removeEventListener("resize", handleResize);
51
- window.visualViewport?.removeEventListener("scroll", handleResize);
52
+ win2.visualViewport?.removeEventListener("resize", handleResize);
53
+ win2.visualViewport?.removeEventListener("scroll", handleResize);
52
54
  };
53
- }, []);
55
+ }, [editor]);
54
56
  return height;
55
57
  }
56
58
  //# sourceMappingURL=useViewportHeight.js.map
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../src/lib/hooks/useViewportHeight.ts"],
4
- "sourcesContent": ["import { useLayoutEffect, useState } from 'react'\n\n/*!\n * BSD License: https://github.com/outline/rich-markdown-editor/blob/main/LICENSE\n * Copyright (c) 2020 General Outline, Inc (https://www.getoutline.com/) and individual contributors.\n *\n * Returns the height of the viewport.\n * This is mainly to account for virtual keyboards on mobile devices.\n *\n * N.B. On iOS, you have to take into account the offsetTop as well so that you get an accurate position\n * while using the virtual keyboard.\n */\n/** @public */\nexport function useViewportHeight(): number {\n\tconst visualViewport = window.visualViewport\n\tconst [height, setHeight] = useState<number>(() =>\n\t\tvisualViewport ? visualViewport.height + visualViewport.offsetTop : window.innerHeight\n\t)\n\n\tuseLayoutEffect(() => {\n\t\tconst handleResize = () => {\n\t\t\tconst visualViewport = window.visualViewport\n\t\t\tsetHeight(() =>\n\t\t\t\tvisualViewport ? visualViewport.height + visualViewport.offsetTop : window.innerHeight\n\t\t\t)\n\t\t}\n\n\t\twindow.visualViewport?.addEventListener('resize', handleResize)\n\t\twindow.visualViewport?.addEventListener('scroll', handleResize)\n\n\t\treturn () => {\n\t\t\twindow.visualViewport?.removeEventListener('resize', handleResize)\n\t\t\twindow.visualViewport?.removeEventListener('scroll', handleResize)\n\t\t}\n\t}, [])\n\treturn height\n}\n"],
5
- "mappings": ";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,mBAA0C;AAE1C;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAWO,SAAS,oBAA4B;AAC3C,QAAM,iBAAiB,OAAO;AAC9B,QAAM,CAAC,QAAQ,SAAS,QAAI;AAAA,IAAiB,MAC5C,iBAAiB,eAAe,SAAS,eAAe,YAAY,OAAO;AAAA,EAC5E;AAEA,oCAAgB,MAAM;AACrB,UAAM,eAAe,MAAM;AAC1B,YAAMA,kBAAiB,OAAO;AAC9B;AAAA,QAAU,MACTA,kBAAiBA,gBAAe,SAASA,gBAAe,YAAY,OAAO;AAAA,MAC5E;AAAA,IACD;AAEA,WAAO,gBAAgB,iBAAiB,UAAU,YAAY;AAC9D,WAAO,gBAAgB,iBAAiB,UAAU,YAAY;AAE9D,WAAO,MAAM;AACZ,aAAO,gBAAgB,oBAAoB,UAAU,YAAY;AACjE,aAAO,gBAAgB,oBAAoB,UAAU,YAAY;AAAA,IAClE;AAAA,EACD,GAAG,CAAC,CAAC;AACL,SAAO;AACR;",
6
- "names": ["visualViewport"]
4
+ "sourcesContent": ["import { useLayoutEffect, useState } from 'react'\nimport { useMaybeEditor } from './useEditor'\n\n/*!\n * BSD License: https://github.com/outline/rich-markdown-editor/blob/main/LICENSE\n * Copyright (c) 2020 General Outline, Inc (https://www.getoutline.com/) and individual contributors.\n *\n * Returns the height of the viewport.\n * This is mainly to account for virtual keyboards on mobile devices.\n *\n * N.B. On iOS, you have to take into account the offsetTop as well so that you get an accurate position\n * while using the virtual keyboard.\n */\n/** @public */\nexport function useViewportHeight(): number {\n\tconst editor = useMaybeEditor()\n\tconst win = editor?.getContainerWindow() ?? window\n\tconst vv = win.visualViewport\n\tconst [height, setHeight] = useState<number>(() =>\n\t\tvv ? vv.height + vv.offsetTop : win.innerHeight\n\t)\n\n\tuseLayoutEffect(() => {\n\t\tconst win = editor?.getContainerWindow() ?? window\n\t\tconst handleResize = () => {\n\t\t\tconst vv = win.visualViewport\n\t\t\tsetHeight(() => (vv ? vv.height + vv.offsetTop : win.innerHeight))\n\t\t}\n\n\t\twin.visualViewport?.addEventListener('resize', handleResize)\n\t\twin.visualViewport?.addEventListener('scroll', handleResize)\n\n\t\treturn () => {\n\t\t\twin.visualViewport?.removeEventListener('resize', handleResize)\n\t\t\twin.visualViewport?.removeEventListener('scroll', handleResize)\n\t\t}\n\t}, [editor])\n\treturn height\n}\n"],
5
+ "mappings": ";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,mBAA0C;AAC1C,uBAA+B;AAE/B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAWO,SAAS,oBAA4B;AAC3C,QAAM,aAAS,iCAAe;AAC9B,QAAM,MAAM,QAAQ,mBAAmB,KAAK;AAC5C,QAAM,KAAK,IAAI;AACf,QAAM,CAAC,QAAQ,SAAS,QAAI;AAAA,IAAiB,MAC5C,KAAK,GAAG,SAAS,GAAG,YAAY,IAAI;AAAA,EACrC;AAEA,oCAAgB,MAAM;AACrB,UAAMA,OAAM,QAAQ,mBAAmB,KAAK;AAC5C,UAAM,eAAe,MAAM;AAC1B,YAAMC,MAAKD,KAAI;AACf,gBAAU,MAAOC,MAAKA,IAAG,SAASA,IAAG,YAAYD,KAAI,WAAY;AAAA,IAClE;AAEA,IAAAA,KAAI,gBAAgB,iBAAiB,UAAU,YAAY;AAC3D,IAAAA,KAAI,gBAAgB,iBAAiB,UAAU,YAAY;AAE3D,WAAO,MAAM;AACZ,MAAAA,KAAI,gBAAgB,oBAAoB,UAAU,YAAY;AAC9D,MAAAA,KAAI,gBAAgB,oBAAoB,UAAU,YAAY;AAAA,IAC/D;AAAA,EACD,GAAG,CAAC,MAAM,CAAC;AACX,SAAO;AACR;",
6
+ "names": ["win", "vv"]
7
7
  }
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../src/lib/utils/browserCanvasMaxSize.ts"],
4
- "sourcesContent": ["/** @internal */\nexport interface CanvasMaxSize {\n\tmaxWidth: number\n\tmaxHeight: number\n\tmaxArea: number\n}\n\n// Cache this, only want to do this once per browser session\nlet maxCanvasSizes: CanvasMaxSize | null = null\n\nfunction getBrowserCanvasMaxSize(): CanvasMaxSize {\n\tif (!maxCanvasSizes) {\n\t\tmaxCanvasSizes = {\n\t\t\tmaxWidth: getCanvasSize('width'), // test very wide but 1 pixel tall canvases\n\t\t\tmaxHeight: getCanvasSize('height'), // test very tall but 1 pixel wide canvases\n\t\t\tmaxArea: getCanvasSize('area'), // test square canvases\n\t\t}\n\t}\n\treturn maxCanvasSizes\n}\n\n/*!\n * Extracted from https://github.com/jhildenbiddle/canvas-size\n * MIT License: https://github.com/jhildenbiddle/canvas-size/blob/master/LICENSE\n * Copyright (c) John Hildenbiddle\n */\n\nconst MAX_SAFE_CANVAS_DIMENSION = 8192\nconst MAX_SAFE_CANVAS_AREA = 4096 * 4096\n\nconst TEST_SIZES = {\n\tarea: [\n\t\t// Chrome 70 (Mac, Win)\n\t\t// Chrome 68 (Android 4.4)\n\t\t// Edge 17 (Win)\n\t\t// Safari 7-12 (Mac)\n\t\t16384,\n\t\t// Chrome 68 (Android 7.1-9)\n\t\t14188,\n\t\t// Chrome 68 (Android 5)\n\t\t11402,\n\t\t// Firefox 63 (Mac, Win)\n\t\t11180,\n\t\t// Chrome 68 (Android 6)\n\t\t10836,\n\t\t// IE 9-11 (Win)\n\t\t8192,\n\t\t// IE Mobile (Windows Phone 8.x)\n\t\t// Safari (iOS 9 - 12)\n\t\t4096,\n\t],\n\theight: [\n\t\t// Safari 7-12 (Mac)\n\t\t// Safari (iOS 9-12)\n\t\t8388607,\n\t\t// Chrome 83 (Mac, Win)\n\t\t65535,\n\t\t// Chrome 70 (Mac, Win)\n\t\t// Chrome 68 (Android 4.4-9)\n\t\t// Firefox 63 (Mac, Win)\n\t\t32767,\n\t\t// Edge 17 (Win)\n\t\t// IE11 (Win)\n\t\t16384,\n\t\t// IE 9-10 (Win)\n\t\t8192,\n\t\t// IE Mobile (Windows Phone 8.x)\n\t\t4096,\n\t],\n\twidth: [\n\t\t// Safari 7-12 (Mac)\n\t\t// Safari (iOS 9-12)\n\t\t4194303,\n\t\t// Chrome 83 (Mac, Win)\n\t\t65535,\n\t\t// Chrome 70 (Mac, Win)\n\t\t// Chrome 68 (Android 4.4-9)\n\t\t// Firefox 63 (Mac, Win)\n\t\t32767,\n\t\t// Edge 17 (Win)\n\t\t// IE11 (Win)\n\t\t16384,\n\t\t// IE 9-10 (Win)\n\t\t8192,\n\t\t// IE Mobile (Windows Phone 8.x)\n\t\t4096,\n\t],\n} as const\n\n/**\n * Tests ability to read pixel data from canvas elements of various dimensions\n * by decreasing canvas height and/or width until a test succeeds.\n * @param dimension - The dimension to test.\n * @returns The maximum size of the canvas for the given dimension.\n */\nfunction getCanvasSize(dimension: 'width' | 'height' | 'area'): number {\n\tconst cropCvs = document.createElement('canvas')\n\tcropCvs.width = 1\n\tcropCvs.height = 1\n\tconst cropCtx = cropCvs.getContext('2d')!\n\n\tfor (const size of TEST_SIZES[dimension]) {\n\t\tconst w = dimension === 'height' ? 1 : size\n\t\tconst h = dimension === 'width' ? 1 : size\n\n\t\tconst testCvs = document.createElement('canvas')\n\t\ttestCvs.width = w\n\t\ttestCvs.height = h\n\t\tconst testCtx = testCvs.getContext('2d')!\n\n\t\ttestCtx.fillRect(w - 1, h - 1, 1, 1)\n\t\tcropCtx.drawImage(testCvs, w - 1, h - 1, 1, 1, 0, 0, 1, 1)\n\n\t\tconst isTestPassed = cropCtx.getImageData(0, 0, 1, 1).data[3] !== 0\n\t\t// release memory\n\t\ttestCvs.width = 0\n\t\ttestCvs.height = 0\n\n\t\tif (isTestPassed) {\n\t\t\t// release memory\n\t\t\tcropCvs.width = 0\n\t\t\tcropCvs.height = 0\n\n\t\t\tif (dimension === 'area') {\n\t\t\t\treturn size * size\n\t\t\t} else {\n\t\t\t\treturn size\n\t\t\t}\n\t\t}\n\t}\n\n\t// didn't find a good size, release memory and error\n\tcropCvs.width = 0\n\tcropCvs.height = 0\n\n\tthrow Error('Failed to determine maximum canvas dimension')\n}\n\n/** @internal */\nexport function clampToBrowserMaxCanvasSize(width: number, height: number): [number, number] {\n\tif (\n\t\twidth <= MAX_SAFE_CANVAS_DIMENSION &&\n\t\theight <= MAX_SAFE_CANVAS_DIMENSION &&\n\t\twidth * height <= MAX_SAFE_CANVAS_AREA\n\t) {\n\t\treturn [width, height]\n\t}\n\n\tconst { maxWidth, maxHeight, maxArea } = getBrowserCanvasMaxSize()\n\tconst aspectRatio = width / height\n\n\tif (width > maxWidth) {\n\t\twidth = maxWidth\n\t\theight = width / aspectRatio\n\t}\n\n\tif (height > maxHeight) {\n\t\theight = maxHeight\n\t\twidth = height * aspectRatio\n\t}\n\n\tif (width * height > maxArea) {\n\t\tconst ratio = Math.sqrt(maxArea / (width * height))\n\t\twidth *= ratio\n\t\theight *= ratio\n\t}\n\n\treturn [width, height]\n}\n"],
5
- "mappings": ";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAQA,IAAI,iBAAuC;AAE3C,SAAS,0BAAyC;AACjD,MAAI,CAAC,gBAAgB;AACpB,qBAAiB;AAAA,MAChB,UAAU,cAAc,OAAO;AAAA;AAAA,MAC/B,WAAW,cAAc,QAAQ;AAAA;AAAA,MACjC,SAAS,cAAc,MAAM;AAAA;AAAA,IAC9B;AAAA,EACD;AACA,SAAO;AACR;AAEA;AAAA;AAAA;AAAA;AAAA;AAMA,MAAM,4BAA4B;AAClC,MAAM,uBAAuB,OAAO;AAEpC,MAAM,aAAa;AAAA,EAClB,MAAM;AAAA;AAAA;AAAA;AAAA;AAAA,IAKL;AAAA;AAAA,IAEA;AAAA;AAAA,IAEA;AAAA;AAAA,IAEA;AAAA;AAAA,IAEA;AAAA;AAAA,IAEA;AAAA;AAAA;AAAA,IAGA;AAAA,EACD;AAAA,EACA,QAAQ;AAAA;AAAA;AAAA,IAGP;AAAA;AAAA,IAEA;AAAA;AAAA;AAAA;AAAA,IAIA;AAAA;AAAA;AAAA,IAGA;AAAA;AAAA,IAEA;AAAA;AAAA,IAEA;AAAA,EACD;AAAA,EACA,OAAO;AAAA;AAAA;AAAA,IAGN;AAAA;AAAA,IAEA;AAAA;AAAA;AAAA;AAAA,IAIA;AAAA;AAAA;AAAA,IAGA;AAAA;AAAA,IAEA;AAAA;AAAA,IAEA;AAAA,EACD;AACD;AAQA,SAAS,cAAc,WAAgD;AACtE,QAAM,UAAU,SAAS,cAAc,QAAQ;AAC/C,UAAQ,QAAQ;AAChB,UAAQ,SAAS;AACjB,QAAM,UAAU,QAAQ,WAAW,IAAI;AAEvC,aAAW,QAAQ,WAAW,SAAS,GAAG;AACzC,UAAM,IAAI,cAAc,WAAW,IAAI;AACvC,UAAM,IAAI,cAAc,UAAU,IAAI;AAEtC,UAAM,UAAU,SAAS,cAAc,QAAQ;AAC/C,YAAQ,QAAQ;AAChB,YAAQ,SAAS;AACjB,UAAM,UAAU,QAAQ,WAAW,IAAI;AAEvC,YAAQ,SAAS,IAAI,GAAG,IAAI,GAAG,GAAG,CAAC;AACnC,YAAQ,UAAU,SAAS,IAAI,GAAG,IAAI,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,CAAC;AAEzD,UAAM,eAAe,QAAQ,aAAa,GAAG,GAAG,GAAG,CAAC,EAAE,KAAK,CAAC,MAAM;AAElE,YAAQ,QAAQ;AAChB,YAAQ,SAAS;AAEjB,QAAI,cAAc;AAEjB,cAAQ,QAAQ;AAChB,cAAQ,SAAS;AAEjB,UAAI,cAAc,QAAQ;AACzB,eAAO,OAAO;AAAA,MACf,OAAO;AACN,eAAO;AAAA,MACR;AAAA,IACD;AAAA,EACD;AAGA,UAAQ,QAAQ;AAChB,UAAQ,SAAS;AAEjB,QAAM,MAAM,8CAA8C;AAC3D;AAGO,SAAS,4BAA4B,OAAe,QAAkC;AAC5F,MACC,SAAS,6BACT,UAAU,6BACV,QAAQ,UAAU,sBACjB;AACD,WAAO,CAAC,OAAO,MAAM;AAAA,EACtB;AAEA,QAAM,EAAE,UAAU,WAAW,QAAQ,IAAI,wBAAwB;AACjE,QAAM,cAAc,QAAQ;AAE5B,MAAI,QAAQ,UAAU;AACrB,YAAQ;AACR,aAAS,QAAQ;AAAA,EAClB;AAEA,MAAI,SAAS,WAAW;AACvB,aAAS;AACT,YAAQ,SAAS;AAAA,EAClB;AAEA,MAAI,QAAQ,SAAS,SAAS;AAC7B,UAAM,QAAQ,KAAK,KAAK,WAAW,QAAQ,OAAO;AAClD,aAAS;AACT,cAAU;AAAA,EACX;AAEA,SAAO,CAAC,OAAO,MAAM;AACtB;",
4
+ "sourcesContent": ["/** @internal */\nexport interface CanvasMaxSize {\n\tmaxWidth: number\n\tmaxHeight: number\n\tmaxArea: number\n}\n\n// Cache this, only want to do this once per browser session\nlet maxCanvasSizes: CanvasMaxSize | null = null\n\nfunction getBrowserCanvasMaxSize(): CanvasMaxSize {\n\tif (!maxCanvasSizes) {\n\t\tmaxCanvasSizes = {\n\t\t\tmaxWidth: getCanvasSize('width'), // test very wide but 1 pixel tall canvases\n\t\t\tmaxHeight: getCanvasSize('height'), // test very tall but 1 pixel wide canvases\n\t\t\tmaxArea: getCanvasSize('area'), // test square canvases\n\t\t}\n\t}\n\treturn maxCanvasSizes\n}\n\n/*!\n * Extracted from https://github.com/jhildenbiddle/canvas-size\n * MIT License: https://github.com/jhildenbiddle/canvas-size/blob/master/LICENSE\n * Copyright (c) John Hildenbiddle\n */\n\nconst MAX_SAFE_CANVAS_DIMENSION = 8192\nconst MAX_SAFE_CANVAS_AREA = 4096 * 4096\n\nconst TEST_SIZES = {\n\tarea: [\n\t\t// Chrome 70 (Mac, Win)\n\t\t// Chrome 68 (Android 4.4)\n\t\t// Edge 17 (Win)\n\t\t// Safari 7-12 (Mac)\n\t\t16384,\n\t\t// Chrome 68 (Android 7.1-9)\n\t\t14188,\n\t\t// Chrome 68 (Android 5)\n\t\t11402,\n\t\t// Firefox 63 (Mac, Win)\n\t\t11180,\n\t\t// Chrome 68 (Android 6)\n\t\t10836,\n\t\t// IE 9-11 (Win)\n\t\t8192,\n\t\t// IE Mobile (Windows Phone 8.x)\n\t\t// Safari (iOS 9 - 12)\n\t\t4096,\n\t],\n\theight: [\n\t\t// Safari 7-12 (Mac)\n\t\t// Safari (iOS 9-12)\n\t\t8388607,\n\t\t// Chrome 83 (Mac, Win)\n\t\t65535,\n\t\t// Chrome 70 (Mac, Win)\n\t\t// Chrome 68 (Android 4.4-9)\n\t\t// Firefox 63 (Mac, Win)\n\t\t32767,\n\t\t// Edge 17 (Win)\n\t\t// IE11 (Win)\n\t\t16384,\n\t\t// IE 9-10 (Win)\n\t\t8192,\n\t\t// IE Mobile (Windows Phone 8.x)\n\t\t4096,\n\t],\n\twidth: [\n\t\t// Safari 7-12 (Mac)\n\t\t// Safari (iOS 9-12)\n\t\t4194303,\n\t\t// Chrome 83 (Mac, Win)\n\t\t65535,\n\t\t// Chrome 70 (Mac, Win)\n\t\t// Chrome 68 (Android 4.4-9)\n\t\t// Firefox 63 (Mac, Win)\n\t\t32767,\n\t\t// Edge 17 (Win)\n\t\t// IE11 (Win)\n\t\t16384,\n\t\t// IE 9-10 (Win)\n\t\t8192,\n\t\t// IE Mobile (Windows Phone 8.x)\n\t\t4096,\n\t],\n} as const\n\n/**\n * Tests ability to read pixel data from canvas elements of various dimensions\n * by decreasing canvas height and/or width until a test succeeds.\n * @param dimension - The dimension to test.\n * @returns The maximum size of the canvas for the given dimension.\n */\nfunction getCanvasSize(dimension: 'width' | 'height' | 'area'): number {\n\t// eslint-disable-next-line no-restricted-globals\n\tconst cropCvs = document.createElement('canvas')\n\tcropCvs.width = 1\n\tcropCvs.height = 1\n\tconst cropCtx = cropCvs.getContext('2d')!\n\n\tfor (const size of TEST_SIZES[dimension]) {\n\t\tconst w = dimension === 'height' ? 1 : size\n\t\tconst h = dimension === 'width' ? 1 : size\n\n\t\t// eslint-disable-next-line no-restricted-globals\n\t\tconst testCvs = document.createElement('canvas')\n\t\ttestCvs.width = w\n\t\ttestCvs.height = h\n\t\tconst testCtx = testCvs.getContext('2d')!\n\n\t\ttestCtx.fillRect(w - 1, h - 1, 1, 1)\n\t\tcropCtx.drawImage(testCvs, w - 1, h - 1, 1, 1, 0, 0, 1, 1)\n\n\t\tconst isTestPassed = cropCtx.getImageData(0, 0, 1, 1).data[3] !== 0\n\t\t// release memory\n\t\ttestCvs.width = 0\n\t\ttestCvs.height = 0\n\n\t\tif (isTestPassed) {\n\t\t\t// release memory\n\t\t\tcropCvs.width = 0\n\t\t\tcropCvs.height = 0\n\n\t\t\tif (dimension === 'area') {\n\t\t\t\treturn size * size\n\t\t\t} else {\n\t\t\t\treturn size\n\t\t\t}\n\t\t}\n\t}\n\n\t// didn't find a good size, release memory and error\n\tcropCvs.width = 0\n\tcropCvs.height = 0\n\n\tthrow Error('Failed to determine maximum canvas dimension')\n}\n\n/** @internal */\nexport function clampToBrowserMaxCanvasSize(width: number, height: number): [number, number] {\n\tif (\n\t\twidth <= MAX_SAFE_CANVAS_DIMENSION &&\n\t\theight <= MAX_SAFE_CANVAS_DIMENSION &&\n\t\twidth * height <= MAX_SAFE_CANVAS_AREA\n\t) {\n\t\treturn [width, height]\n\t}\n\n\tconst { maxWidth, maxHeight, maxArea } = getBrowserCanvasMaxSize()\n\tconst aspectRatio = width / height\n\n\tif (width > maxWidth) {\n\t\twidth = maxWidth\n\t\theight = width / aspectRatio\n\t}\n\n\tif (height > maxHeight) {\n\t\theight = maxHeight\n\t\twidth = height * aspectRatio\n\t}\n\n\tif (width * height > maxArea) {\n\t\tconst ratio = Math.sqrt(maxArea / (width * height))\n\t\twidth *= ratio\n\t\theight *= ratio\n\t}\n\n\treturn [width, height]\n}\n"],
5
+ "mappings": ";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAQA,IAAI,iBAAuC;AAE3C,SAAS,0BAAyC;AACjD,MAAI,CAAC,gBAAgB;AACpB,qBAAiB;AAAA,MAChB,UAAU,cAAc,OAAO;AAAA;AAAA,MAC/B,WAAW,cAAc,QAAQ;AAAA;AAAA,MACjC,SAAS,cAAc,MAAM;AAAA;AAAA,IAC9B;AAAA,EACD;AACA,SAAO;AACR;AAEA;AAAA;AAAA;AAAA;AAAA;AAMA,MAAM,4BAA4B;AAClC,MAAM,uBAAuB,OAAO;AAEpC,MAAM,aAAa;AAAA,EAClB,MAAM;AAAA;AAAA;AAAA;AAAA;AAAA,IAKL;AAAA;AAAA,IAEA;AAAA;AAAA,IAEA;AAAA;AAAA,IAEA;AAAA;AAAA,IAEA;AAAA;AAAA,IAEA;AAAA;AAAA;AAAA,IAGA;AAAA,EACD;AAAA,EACA,QAAQ;AAAA;AAAA;AAAA,IAGP;AAAA;AAAA,IAEA;AAAA;AAAA;AAAA;AAAA,IAIA;AAAA;AAAA;AAAA,IAGA;AAAA;AAAA,IAEA;AAAA;AAAA,IAEA;AAAA,EACD;AAAA,EACA,OAAO;AAAA;AAAA;AAAA,IAGN;AAAA;AAAA,IAEA;AAAA;AAAA;AAAA;AAAA,IAIA;AAAA;AAAA;AAAA,IAGA;AAAA;AAAA,IAEA;AAAA;AAAA,IAEA;AAAA,EACD;AACD;AAQA,SAAS,cAAc,WAAgD;AAEtE,QAAM,UAAU,SAAS,cAAc,QAAQ;AAC/C,UAAQ,QAAQ;AAChB,UAAQ,SAAS;AACjB,QAAM,UAAU,QAAQ,WAAW,IAAI;AAEvC,aAAW,QAAQ,WAAW,SAAS,GAAG;AACzC,UAAM,IAAI,cAAc,WAAW,IAAI;AACvC,UAAM,IAAI,cAAc,UAAU,IAAI;AAGtC,UAAM,UAAU,SAAS,cAAc,QAAQ;AAC/C,YAAQ,QAAQ;AAChB,YAAQ,SAAS;AACjB,UAAM,UAAU,QAAQ,WAAW,IAAI;AAEvC,YAAQ,SAAS,IAAI,GAAG,IAAI,GAAG,GAAG,CAAC;AACnC,YAAQ,UAAU,SAAS,IAAI,GAAG,IAAI,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,CAAC;AAEzD,UAAM,eAAe,QAAQ,aAAa,GAAG,GAAG,GAAG,CAAC,EAAE,KAAK,CAAC,MAAM;AAElE,YAAQ,QAAQ;AAChB,YAAQ,SAAS;AAEjB,QAAI,cAAc;AAEjB,cAAQ,QAAQ;AAChB,cAAQ,SAAS;AAEjB,UAAI,cAAc,QAAQ;AACzB,eAAO,OAAO;AAAA,MACf,OAAO;AACN,eAAO;AAAA,MACR;AAAA,IACD;AAAA,EACD;AAGA,UAAQ,QAAQ;AAChB,UAAQ,SAAS;AAEjB,QAAM,MAAM,8CAA8C;AAC3D;AAGO,SAAS,4BAA4B,OAAe,QAAkC;AAC5F,MACC,SAAS,6BACT,UAAU,6BACV,QAAQ,UAAU,sBACjB;AACD,WAAO,CAAC,OAAO,MAAM;AAAA,EACtB;AAEA,QAAM,EAAE,UAAU,WAAW,QAAQ,IAAI,wBAAwB;AACjE,QAAM,cAAc,QAAQ;AAE5B,MAAI,QAAQ,UAAU;AACrB,YAAQ;AACR,aAAS,QAAQ;AAAA,EAClB;AAEA,MAAI,SAAS,WAAW;AACvB,aAAS;AACT,YAAQ,SAAS;AAAA,EAClB;AAEA,MAAI,QAAQ,SAAS,SAAS;AAC7B,UAAM,QAAQ,KAAK,KAAK,WAAW,QAAQ,OAAO;AAClD,aAAS;AACT,cAAU;AAAA,EACX;AAEA,SAAO,CAAC,OAAO,MAAM;AACtB;",
6
6
  "names": []
7
7
  }
@@ -19,6 +19,7 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
19
19
  var dom_exports = {};
20
20
  __export(dom_exports, {
21
21
  activeElementShouldCaptureKeys: () => activeElementShouldCaptureKeys,
22
+ elementShouldCaptureKeys: () => elementShouldCaptureKeys,
22
23
  loopToHtmlElement: () => loopToHtmlElement,
23
24
  preventDefault: () => preventDefault,
24
25
  releasePointerCapture: () => releasePointerCapture,
@@ -69,9 +70,12 @@ const setStyleProperty = (elm, property, value) => {
69
70
  if (!elm) return;
70
71
  elm.style.setProperty(property, String(value));
71
72
  };
72
- function activeElementShouldCaptureKeys(ignoreButtons = false) {
73
- const { activeElement } = document;
74
- const elements = ignoreButtons ? ["input", "textarea"] : ["input", "select", "button", "textarea"];
75
- return !!(activeElement && (activeElement.isContentEditable || elements.indexOf(activeElement.tagName.toLowerCase()) > -1 || activeElement.classList.contains("tlui-slider__thumb")));
73
+ function elementShouldCaptureKeys(el, includeButtonsAndMenus = true) {
74
+ if (!el) return false;
75
+ const tagName = el.tagName.toLowerCase();
76
+ return el.isContentEditable || tagName === "input" || tagName === "textarea" || includeButtonsAndMenus && tagName === "select" || includeButtonsAndMenus && tagName === "button" || el.classList.contains("tlui-slider__thumb");
77
+ }
78
+ function activeElementShouldCaptureKeys(includeButtonsAndMenus = true, doc) {
79
+ return elementShouldCaptureKeys((doc ?? document).activeElement, includeButtonsAndMenus);
76
80
  }
77
81
  //# sourceMappingURL=dom.js.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 elements 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 { 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 * Because 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 unfortunately 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, String(value))\n}\n\n/** @internal */\nexport function activeElementShouldCaptureKeys(ignoreButtons = false) {\n\tconst { activeElement } = document\n\tconst elements = ignoreButtons ? ['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": ";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAeA,yBAAyD;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,8BAAW,mBAAmB,IAAI,GAAG;AACxC,YAAQ,KAAK,mCAAmC,KAAK;AAAA,EACtD;AACD;AAGO,SAAS,kBACf,SACA,OACC;AACD,UAAQ,kBAAkB,MAAM,SAAS;AACzC,MAAI,8BAAW,mBAAmB,IAAI,GAAG;AACxC,UAAM,cAAc,gDAA6B,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,8BAAW,mBAAmB,IAAI,GAAG;AACxC,UAAM,cAAc,gDAA6B,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,OAAO,KAAK,CAAC;AAC9C;AAGO,SAAS,+BAA+B,gBAAgB,OAAO;AACrE,QAAM,EAAE,cAAc,IAAI;AAC1B,QAAM,WAAW,gBAAgB,CAAC,SAAS,UAAU,IAAI,CAAC,SAAS,UAAU,UAAU,UAAU;AACjG,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 elements 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 { 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 * Because 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 unfortunately 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, String(value))\n}\n\n/** @internal */\nexport function elementShouldCaptureKeys(el: Element | null, includeButtonsAndMenus = true) {\n\tif (!el) return false\n\n\tconst tagName = el.tagName.toLowerCase()\n\treturn (\n\t\t(el as HTMLElement).isContentEditable ||\n\t\ttagName === 'input' ||\n\t\ttagName === 'textarea' ||\n\t\t(includeButtonsAndMenus && tagName === 'select') ||\n\t\t(includeButtonsAndMenus && tagName === 'button') ||\n\t\tel.classList.contains('tlui-slider__thumb')\n\t)\n}\n\n/** @internal */\nexport function activeElementShouldCaptureKeys(includeButtonsAndMenus = true, doc?: Document) {\n\t// eslint-disable-next-line no-restricted-globals\n\treturn elementShouldCaptureKeys((doc ?? document).activeElement, includeButtonsAndMenus)\n}\n"],
5
+ "mappings": ";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAeA,yBAAyD;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,8BAAW,mBAAmB,IAAI,GAAG;AACxC,YAAQ,KAAK,mCAAmC,KAAK;AAAA,EACtD;AACD;AAGO,SAAS,kBACf,SACA,OACC;AACD,UAAQ,kBAAkB,MAAM,SAAS;AACzC,MAAI,8BAAW,mBAAmB,IAAI,GAAG;AACxC,UAAM,cAAc,gDAA6B,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,8BAAW,mBAAmB,IAAI,GAAG;AACxC,UAAM,cAAc,gDAA6B,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,OAAO,KAAK,CAAC;AAC9C;AAGO,SAAS,yBAAyB,IAAoB,yBAAyB,MAAM;AAC3F,MAAI,CAAC,GAAI,QAAO;AAEhB,QAAM,UAAU,GAAG,QAAQ,YAAY;AACvC,SACE,GAAmB,qBACpB,YAAY,WACZ,YAAY,cACX,0BAA0B,YAAY,YACtC,0BAA0B,YAAY,YACvC,GAAG,UAAU,SAAS,oBAAoB;AAE5C;AAGO,SAAS,+BAA+B,yBAAyB,MAAM,KAAgB;AAE7F,SAAO,0BAA0B,OAAO,UAAU,eAAe,sBAAsB;AACxF;",
6
6
  "names": []
7
7
  }
@@ -22,10 +22,10 @@ __export(version_exports, {
22
22
  version: () => version
23
23
  });
24
24
  module.exports = __toCommonJS(version_exports);
25
- const version = "4.5.0-canary.fe0a82f04c21";
25
+ const version = "4.5.0-internal.b3f4cb985cc3";
26
26
  const publishDates = {
27
27
  major: "2025-09-18T14:39:22.803Z",
28
- minor: "2026-03-09T16:17:44.431Z",
29
- patch: "2026-03-09T16:17:44.431Z"
28
+ minor: "2026-03-11T15:43:43.431Z",
29
+ patch: "2026-03-11T15:43:43.431Z"
30
30
  };
31
31
  //# sourceMappingURL=version.js.map
@@ -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 = '4.5.0-canary.fe0a82f04c21'\nexport const publishDates = {\n\tmajor: '2025-09-18T14:39:22.803Z',\n\tminor: '2026-03-09T16:17:44.431Z',\n\tpatch: '2026-03-09T16:17:44.431Z',\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 = '4.5.0-internal.b3f4cb985cc3'\nexport const publishDates = {\n\tmajor: '2025-09-18T14:39:22.803Z',\n\tminor: '2026-03-11T15:43:43.431Z',\n\tpatch: '2026-03-11T15:43:43.431Z',\n}\n"],
5
5
  "mappings": ";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAGO,MAAM,UAAU;AAChB,MAAM,eAAe;AAAA,EAC3B,OAAO;AAAA,EACP,OAAO;AAAA,EACP,OAAO;AACR;",
6
6
  "names": []
7
7
  }
@@ -1146,6 +1146,8 @@ export declare class Editor extends EventEmitter<TLEventMap> {
1146
1146
  * @public
1147
1147
  */
1148
1148
  getContainer: () => HTMLElement;
1149
+ /* Excluded from this release type: getContainerDocument */
1150
+ /* Excluded from this release type: getContainerWindow */
1149
1151
  /**
1150
1152
  * Dispose the editor.
1151
1153
  *
@@ -1903,6 +1905,12 @@ export declare class Editor extends EventEmitter<TLEventMap> {
1903
1905
  * @public
1904
1906
  */
1905
1907
  getZoomLevel(): number;
1908
+ /**
1909
+ * Get the scale factor used when creating or resizing shapes in dynamic size mode.
1910
+ *
1911
+ * @public
1912
+ */
1913
+ getResizeScaleFactor(): number;
1906
1914
  private _debouncedZoomLevel;
1907
1915
  /**
1908
1916
  * Get the debounced zoom level. When the camera is moving, this returns the zoom level
@@ -3785,6 +3793,7 @@ export declare class Editor extends EventEmitter<TLEventMap> {
3785
3793
  getSvgElement(shapes: TLShape[] | TLShapeId[], opts?: TLSvgExportOptions): Promise<{
3786
3794
  height: number;
3787
3795
  svg: SVGSVGElement;
3796
+ trimPadding: number;
3788
3797
  width: number;
3789
3798
  } | undefined>;
3790
3799
  /**
@@ -3800,6 +3809,7 @@ export declare class Editor extends EventEmitter<TLEventMap> {
3800
3809
  getSvgString(shapes: TLShape[] | TLShapeId[], opts?: TLSvgExportOptions): Promise<{
3801
3810
  height: number;
3802
3811
  svg: string;
3812
+ trimPadding: number;
3803
3813
  width: number;
3804
3814
  } | undefined>;
3805
3815
  /**
@@ -4157,6 +4167,8 @@ export declare interface EditorProviderProps {
4157
4167
  children: React_3.ReactNode;
4158
4168
  }
4159
4169
 
4170
+ /* Excluded from this release type: elementShouldCaptureKeys */
4171
+
4160
4172
  /** @public */
4161
4173
  export declare class Ellipse2d extends Geometry2d {
4162
4174
  config: Omit<Geometry2dOptions, 'isClosed'> & {
@@ -4374,6 +4386,10 @@ export declare function getFreshUserPreferences(): TLUserPreferences;
4374
4386
  */
4375
4387
  export declare function getIncrementedName(name: string, others: string[]): string;
4376
4388
 
4389
+ /* Excluded from this release type: getOwnerDocument */
4390
+
4391
+ /* Excluded from this release type: getOwnerWindow */
4392
+
4377
4393
  /** @public */
4378
4394
  export declare function getPerfectDashProps(totalLength: number, strokeWidth: number, opts?: {
4379
4395
  closed?: boolean;
@@ -8267,9 +8283,15 @@ export declare interface TLSvgExportOptions {
8267
8283
  */
8268
8284
  background?: boolean;
8269
8285
  /**
8270
- * How much padding to include around the bounds of exports? Defaults to 32px.
8286
+ * How much padding to include around the bounds of exports.
8287
+ *
8288
+ * - `'auto'` (default) — trim to visual content bounds, capturing overflow (like thick
8289
+ * strokes or arrowheads) without extra whitespace.
8290
+ * - `number` (e.g. `32`) — fixed padding in px. No trimming; overflow beyond the padding
8291
+ * region is clipped.
8292
+ * - `0` — no padding, no trimming, overflow is clipped.
8271
8293
  */
8272
- padding?: number;
8294
+ padding?: 'auto' | number;
8273
8295
  /**
8274
8296
  * Should the export be rendered in dark mode (true) or light mode (false)? Defaults to the
8275
8297
  * current instance's dark mode setting.
@@ -131,6 +131,7 @@ import {
131
131
  useDelaySvgExport,
132
132
  useSvgExportContext
133
133
  } from "./lib/editor/types/SvgExportContext.mjs";
134
+ import { getOwnerDocument, getOwnerWindow } from "./lib/exports/domUtils.mjs";
134
135
  import { getSvgAsImage } from "./lib/exports/getSvgAsImage.mjs";
135
136
  import { tlenv, tlenvReactive } from "./lib/globals/environment.mjs";
136
137
  import { tlmenus } from "./lib/globals/menus.mjs";
@@ -267,6 +268,7 @@ import {
267
268
  } from "./lib/utils/deepLinks.mjs";
268
269
  import {
269
270
  activeElementShouldCaptureKeys,
271
+ elementShouldCaptureKeys,
270
272
  loopToHtmlElement,
271
273
  preventDefault,
272
274
  releasePointerCapture,
@@ -303,7 +305,7 @@ import { LocalIndexedDb, Table } from "./lib/utils/sync/LocalIndexedDb.mjs";
303
305
  import { uniq } from "./lib/utils/uniq.mjs";
304
306
  registerTldrawLibraryVersion(
305
307
  "@tldraw/editor",
306
- "4.5.0-canary.fe0a82f04c21",
308
+ "4.5.0-internal.b3f4cb985cc3",
307
309
  "esm"
308
310
  );
309
311
  export {
@@ -418,6 +420,7 @@ export {
418
420
  defaultTldrawOptions,
419
421
  defaultUserPreferences,
420
422
  degreesToRadians,
423
+ elementShouldCaptureKeys,
421
424
  extractSessionStateFromLegacySnapshot,
422
425
  featureFlags,
423
426
  getArcMeasure,
@@ -427,6 +430,8 @@ export {
427
430
  getFontsFromRichText,
428
431
  getFreshUserPreferences,
429
432
  getIncrementedName,
433
+ getOwnerDocument,
434
+ getOwnerWindow,
430
435
  getPerfectDashProps,
431
436
  getPointInArcT,
432
437
  getPointOnCircle,