@tldraw/editor 5.2.0-next.ee0fa4d6244f → 5.2.0

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 (189) hide show
  1. package/README.md +7 -1
  2. package/dist-cjs/index.d.ts +117 -60
  3. package/dist-cjs/index.js +7 -8
  4. package/dist-cjs/index.js.map +2 -2
  5. package/dist-cjs/lib/components/MenuClickCapture.js +8 -5
  6. package/dist-cjs/lib/components/MenuClickCapture.js.map +2 -2
  7. package/dist-cjs/lib/components/Shape.js +47 -1
  8. package/dist-cjs/lib/components/Shape.js.map +3 -3
  9. package/dist-cjs/lib/components/default-components/DefaultCanvas.js +1 -16
  10. package/dist-cjs/lib/components/default-components/DefaultCanvas.js.map +2 -2
  11. package/dist-cjs/lib/editor/Editor.js +131 -57
  12. package/dist-cjs/lib/editor/Editor.js.map +3 -3
  13. package/dist-cjs/lib/editor/managers/ClickManager/ClickManager.js +8 -58
  14. package/dist-cjs/lib/editor/managers/ClickManager/ClickManager.js.map +2 -2
  15. package/dist-cjs/lib/editor/managers/CollaboratorsManager/CollaboratorsManager.js +3 -3
  16. package/dist-cjs/lib/editor/managers/CollaboratorsManager/CollaboratorsManager.js.map +2 -2
  17. package/dist-cjs/lib/editor/managers/FocusManager/FocusManager.js +1 -2
  18. package/dist-cjs/lib/editor/managers/FocusManager/FocusManager.js.map +2 -2
  19. package/dist-cjs/lib/editor/managers/FontManager/FontManager.js +28 -4
  20. package/dist-cjs/lib/editor/managers/FontManager/FontManager.js.map +3 -3
  21. package/dist-cjs/lib/editor/managers/HistoryManager/HistoryManager.js +24 -2
  22. package/dist-cjs/lib/editor/managers/HistoryManager/HistoryManager.js.map +2 -2
  23. package/dist-cjs/lib/editor/managers/InputsManager/InputsManager.js +14 -3
  24. package/dist-cjs/lib/editor/managers/InputsManager/InputsManager.js.map +2 -2
  25. package/dist-cjs/lib/editor/managers/SpatialIndexManager/SpatialIndexManager.js +4 -2
  26. package/dist-cjs/lib/editor/managers/SpatialIndexManager/SpatialIndexManager.js.map +2 -2
  27. package/dist-cjs/lib/editor/managers/TextManager/TextManager.js +7 -3
  28. package/dist-cjs/lib/editor/managers/TextManager/TextManager.js.map +2 -2
  29. package/dist-cjs/lib/editor/managers/TickManager/TickManager.js +0 -1
  30. package/dist-cjs/lib/editor/managers/TickManager/TickManager.js.map +2 -2
  31. package/dist-cjs/lib/editor/managers/UserPreferencesManager/UserPreferencesManager.js +15 -2
  32. package/dist-cjs/lib/editor/managers/UserPreferencesManager/UserPreferencesManager.js.map +2 -2
  33. package/dist-cjs/lib/editor/overlays/strokeShapeIndicators.js +79 -0
  34. package/dist-cjs/lib/editor/overlays/strokeShapeIndicators.js.map +7 -0
  35. package/dist-cjs/lib/editor/shapes/ShapeUtil.js.map +2 -2
  36. package/dist-cjs/lib/editor/tools/BaseBoxShapeTool/children/Pointing.js +4 -0
  37. package/dist-cjs/lib/editor/tools/BaseBoxShapeTool/children/Pointing.js.map +2 -2
  38. package/dist-cjs/lib/editor/tools/StateNode.js.map +2 -2
  39. package/dist-cjs/lib/{hooks/useTransform.js → editor/tools/cancelShapeCreationOnLongPress.js} +8 -23
  40. package/dist-cjs/lib/editor/tools/cancelShapeCreationOnLongPress.js.map +7 -0
  41. package/dist-cjs/lib/editor/types/event-types.js +0 -2
  42. package/dist-cjs/lib/editor/types/event-types.js.map +2 -2
  43. package/dist-cjs/lib/globals/environment.js +6 -1
  44. package/dist-cjs/lib/globals/environment.js.map +2 -2
  45. package/dist-cjs/lib/hooks/EditorComponentsContext.js.map +2 -2
  46. package/dist-cjs/lib/hooks/useCanvasEvents.js +17 -8
  47. package/dist-cjs/lib/hooks/useCanvasEvents.js.map +2 -2
  48. package/dist-cjs/lib/hooks/useEditorComponents.js +0 -1
  49. package/dist-cjs/lib/hooks/useEditorComponents.js.map +2 -2
  50. package/dist-cjs/lib/hooks/usePresence.js.map +2 -2
  51. package/dist-cjs/lib/hooks/useScreenBounds.js +1 -0
  52. package/dist-cjs/lib/hooks/useScreenBounds.js.map +2 -2
  53. package/dist-cjs/lib/license/LicenseManager.js +5 -1
  54. package/dist-cjs/lib/license/LicenseManager.js.map +2 -2
  55. package/dist-cjs/lib/primitives/Vec.js +3 -2
  56. package/dist-cjs/lib/primitives/Vec.js.map +2 -2
  57. package/dist-cjs/lib/utils/dom.js +12 -0
  58. package/dist-cjs/lib/utils/dom.js.map +2 -2
  59. package/dist-cjs/lib/utils/getPointerInfo.js +2 -1
  60. package/dist-cjs/lib/utils/getPointerInfo.js.map +2 -2
  61. package/dist-cjs/lib/utils/pointer.js +37 -0
  62. package/dist-cjs/lib/utils/pointer.js.map +7 -0
  63. package/dist-cjs/version.js +3 -3
  64. package/dist-cjs/version.js.map +1 -1
  65. package/dist-esm/index.d.mts +117 -60
  66. package/dist-esm/index.mjs +9 -13
  67. package/dist-esm/index.mjs.map +2 -2
  68. package/dist-esm/lib/components/MenuClickCapture.mjs +8 -5
  69. package/dist-esm/lib/components/MenuClickCapture.mjs.map +2 -2
  70. package/dist-esm/lib/components/Shape.mjs +48 -2
  71. package/dist-esm/lib/components/Shape.mjs.map +3 -3
  72. package/dist-esm/lib/components/default-components/DefaultCanvas.mjs +1 -16
  73. package/dist-esm/lib/components/default-components/DefaultCanvas.mjs.map +2 -2
  74. package/dist-esm/lib/editor/Editor.mjs +131 -57
  75. package/dist-esm/lib/editor/Editor.mjs.map +3 -3
  76. package/dist-esm/lib/editor/managers/ClickManager/ClickManager.mjs +8 -58
  77. package/dist-esm/lib/editor/managers/ClickManager/ClickManager.mjs.map +2 -2
  78. package/dist-esm/lib/editor/managers/CollaboratorsManager/CollaboratorsManager.mjs +3 -3
  79. package/dist-esm/lib/editor/managers/CollaboratorsManager/CollaboratorsManager.mjs.map +2 -2
  80. package/dist-esm/lib/editor/managers/FocusManager/FocusManager.mjs +1 -2
  81. package/dist-esm/lib/editor/managers/FocusManager/FocusManager.mjs.map +2 -2
  82. package/dist-esm/lib/editor/managers/FontManager/FontManager.mjs +28 -4
  83. package/dist-esm/lib/editor/managers/FontManager/FontManager.mjs.map +3 -3
  84. package/dist-esm/lib/editor/managers/HistoryManager/HistoryManager.mjs +24 -2
  85. package/dist-esm/lib/editor/managers/HistoryManager/HistoryManager.mjs.map +2 -2
  86. package/dist-esm/lib/editor/managers/InputsManager/InputsManager.mjs +14 -3
  87. package/dist-esm/lib/editor/managers/InputsManager/InputsManager.mjs.map +2 -2
  88. package/dist-esm/lib/editor/managers/SpatialIndexManager/SpatialIndexManager.mjs +4 -2
  89. package/dist-esm/lib/editor/managers/SpatialIndexManager/SpatialIndexManager.mjs.map +2 -2
  90. package/dist-esm/lib/editor/managers/TextManager/TextManager.mjs +7 -3
  91. package/dist-esm/lib/editor/managers/TextManager/TextManager.mjs.map +2 -2
  92. package/dist-esm/lib/editor/managers/TickManager/TickManager.mjs +0 -1
  93. package/dist-esm/lib/editor/managers/TickManager/TickManager.mjs.map +2 -2
  94. package/dist-esm/lib/editor/managers/UserPreferencesManager/UserPreferencesManager.mjs +15 -2
  95. package/dist-esm/lib/editor/managers/UserPreferencesManager/UserPreferencesManager.mjs.map +2 -2
  96. package/dist-esm/lib/editor/overlays/strokeShapeIndicators.mjs +59 -0
  97. package/dist-esm/lib/editor/overlays/strokeShapeIndicators.mjs.map +7 -0
  98. package/dist-esm/lib/editor/shapes/ShapeUtil.mjs.map +2 -2
  99. package/dist-esm/lib/editor/tools/BaseBoxShapeTool/children/Pointing.mjs +4 -0
  100. package/dist-esm/lib/editor/tools/BaseBoxShapeTool/children/Pointing.mjs.map +2 -2
  101. package/dist-esm/lib/editor/tools/StateNode.mjs.map +2 -2
  102. package/dist-esm/lib/editor/tools/cancelShapeCreationOnLongPress.mjs +8 -0
  103. package/dist-esm/lib/editor/tools/cancelShapeCreationOnLongPress.mjs.map +7 -0
  104. package/dist-esm/lib/editor/types/event-types.mjs +0 -2
  105. package/dist-esm/lib/editor/types/event-types.mjs.map +2 -2
  106. package/dist-esm/lib/globals/environment.mjs +6 -1
  107. package/dist-esm/lib/globals/environment.mjs.map +2 -2
  108. package/dist-esm/lib/hooks/EditorComponentsContext.mjs.map +2 -2
  109. package/dist-esm/lib/hooks/useCanvasEvents.mjs +17 -8
  110. package/dist-esm/lib/hooks/useCanvasEvents.mjs.map +2 -2
  111. package/dist-esm/lib/hooks/useEditorComponents.mjs +0 -1
  112. package/dist-esm/lib/hooks/useEditorComponents.mjs.map +2 -2
  113. package/dist-esm/lib/hooks/usePresence.mjs.map +2 -2
  114. package/dist-esm/lib/hooks/useScreenBounds.mjs +1 -0
  115. package/dist-esm/lib/hooks/useScreenBounds.mjs.map +2 -2
  116. package/dist-esm/lib/license/LicenseManager.mjs +5 -1
  117. package/dist-esm/lib/license/LicenseManager.mjs.map +2 -2
  118. package/dist-esm/lib/primitives/Vec.mjs +3 -2
  119. package/dist-esm/lib/primitives/Vec.mjs.map +2 -2
  120. package/dist-esm/lib/utils/dom.mjs +12 -0
  121. package/dist-esm/lib/utils/dom.mjs.map +2 -2
  122. package/dist-esm/lib/utils/getPointerInfo.mjs +2 -1
  123. package/dist-esm/lib/utils/getPointerInfo.mjs.map +2 -2
  124. package/dist-esm/lib/utils/pointer.mjs +17 -0
  125. package/dist-esm/lib/utils/pointer.mjs.map +7 -0
  126. package/dist-esm/version.mjs +3 -3
  127. package/dist-esm/version.mjs.map +1 -1
  128. package/editor.css +15 -3
  129. package/package.json +11 -8
  130. package/src/index.ts +4 -10
  131. package/src/lib/components/MenuClickCapture.tsx +8 -4
  132. package/src/lib/components/Shape.tsx +88 -1
  133. package/src/lib/components/default-components/DefaultCanvas.tsx +1 -17
  134. package/src/lib/editor/Editor.test.ts +36 -0
  135. package/src/lib/editor/Editor.ts +204 -75
  136. package/src/lib/editor/managers/ClickManager/ClickManager.test.ts +54 -74
  137. package/src/lib/editor/managers/ClickManager/ClickManager.ts +15 -65
  138. package/src/lib/editor/managers/CollaboratorsManager/CollaboratorsManager.test.ts +43 -16
  139. package/src/lib/editor/managers/CollaboratorsManager/CollaboratorsManager.ts +8 -5
  140. package/src/lib/editor/managers/FocusManager/FocusManager.test.ts +4 -4
  141. package/src/lib/editor/managers/FocusManager/FocusManager.ts +1 -2
  142. package/src/lib/editor/managers/FontManager/FontManager.test.ts +37 -10
  143. package/src/lib/editor/managers/FontManager/FontManager.ts +46 -1
  144. package/src/lib/editor/managers/HistoryManager/HistoryManager.test.ts +32 -0
  145. package/src/lib/editor/managers/HistoryManager/HistoryManager.ts +34 -4
  146. package/src/lib/editor/managers/InputsManager/InputsManager.test.ts +61 -0
  147. package/src/lib/editor/managers/InputsManager/InputsManager.ts +16 -4
  148. package/src/lib/editor/managers/SpatialIndexManager/SpatialIndexManager.ts +9 -2
  149. package/src/lib/editor/managers/TextManager/TextManager.test.ts +16 -14
  150. package/src/lib/editor/managers/TextManager/TextManager.ts +17 -2
  151. package/src/lib/editor/managers/TickManager/TickManager.test.ts +0 -40
  152. package/src/lib/editor/managers/TickManager/TickManager.ts +0 -1
  153. package/src/lib/editor/managers/UserPreferencesManager/UserPreferencesManager.test.ts +12 -2
  154. package/src/lib/editor/managers/UserPreferencesManager/UserPreferencesManager.ts +27 -2
  155. package/src/lib/editor/overlays/strokeShapeIndicators.ts +86 -0
  156. package/src/lib/editor/shapes/ShapeUtil.ts +41 -0
  157. package/src/lib/editor/tools/BaseBoxShapeTool/children/Pointing.ts +5 -0
  158. package/src/lib/editor/tools/StateNode.ts +0 -2
  159. package/src/lib/editor/tools/cancelShapeCreationOnLongPress.ts +31 -0
  160. package/src/lib/editor/types/event-types.ts +9 -6
  161. package/src/lib/globals/environment.ts +7 -0
  162. package/src/lib/hooks/EditorComponentsContext.tsx +0 -2
  163. package/src/lib/hooks/useCanvasEvents.ts +24 -12
  164. package/src/lib/hooks/useEditorComponents.tsx +0 -1
  165. package/src/lib/hooks/usePresence.ts +2 -2
  166. package/src/lib/hooks/useScreenBounds.ts +3 -0
  167. package/src/lib/license/LicenseManager.test.ts +24 -16
  168. package/src/lib/license/LicenseManager.ts +8 -2
  169. package/src/lib/primitives/Vec.ts +5 -2
  170. package/src/lib/test/ContentElementSlot.test.tsx +201 -0
  171. package/src/lib/utils/dom.ts +34 -0
  172. package/src/lib/utils/getPointerInfo.ts +2 -1
  173. package/src/lib/utils/pointer.test.ts +76 -0
  174. package/src/lib/utils/pointer.ts +42 -0
  175. package/src/version.ts +3 -3
  176. package/dist-cjs/lib/components/default-components/DefaultSelectionBackground.js +0 -49
  177. package/dist-cjs/lib/components/default-components/DefaultSelectionBackground.js.map +0 -7
  178. package/dist-cjs/lib/editor/overlays/ShapeIndicatorOverlayUtil.js +0 -161
  179. package/dist-cjs/lib/editor/overlays/ShapeIndicatorOverlayUtil.js.map +0 -7
  180. package/dist-cjs/lib/hooks/useTransform.js.map +0 -7
  181. package/dist-esm/lib/components/default-components/DefaultSelectionBackground.mjs +0 -19
  182. package/dist-esm/lib/components/default-components/DefaultSelectionBackground.mjs.map +0 -7
  183. package/dist-esm/lib/editor/overlays/ShapeIndicatorOverlayUtil.mjs +0 -141
  184. package/dist-esm/lib/editor/overlays/ShapeIndicatorOverlayUtil.mjs.map +0 -7
  185. package/dist-esm/lib/hooks/useTransform.mjs +0 -23
  186. package/dist-esm/lib/hooks/useTransform.mjs.map +0 -7
  187. package/src/lib/components/default-components/DefaultSelectionBackground.tsx +0 -25
  188. package/src/lib/editor/overlays/ShapeIndicatorOverlayUtil.ts +0 -216
  189. package/src/lib/hooks/useTransform.ts +0 -30
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../src/lib/hooks/useCanvasEvents.ts"],
4
- "sourcesContent": ["import { useValue } from '@tldraw/state-react'\nimport React, { useEffect, useMemo } from 'react'\nimport { tlenv } from '../globals/environment'\nimport {\n\telementShouldCaptureKeys,\n\tpreventDefault,\n\treleasePointerCapture,\n\tsetPointerCapture,\n} from '../utils/dom'\nimport { getPointerInfo } from '../utils/getPointerInfo'\nimport { useEditor } from './useEditor'\n\nexport function useCanvasEvents() {\n\tconst editor = useEditor()\n\tconst ownerDocument = editor.getContainerDocument()\n\tconst currentTool = useValue('current tool', () => editor.getCurrentTool(), [editor])\n\n\tconst events = useMemo(\n\t\tfunction canvasEvents() {\n\t\t\tfunction onPointerDown(e: React.PointerEvent) {\n\t\t\t\tif (editor.wasEventAlreadyHandled(e)) return\n\n\t\t\t\t// With right-click panning disabled, fire right_click on press and let the\n\t\t\t\t// native contextmenu through so the menu opens at the pointer-down location.\n\t\t\t\tif (e.button === 2 && !editor.options.rightClickPanning) {\n\t\t\t\t\teditor.dispatch({\n\t\t\t\t\t\ttype: 'pointer',\n\t\t\t\t\t\ttarget: 'canvas',\n\t\t\t\t\t\tname: 'right_click',\n\t\t\t\t\t\t...getPointerInfo(editor, e),\n\t\t\t\t\t})\n\t\t\t\t\treturn\n\t\t\t\t}\n\n\t\t\t\tif (e.button !== 0 && e.button !== 1 && e.button !== 2 && e.button !== 5) return\n\n\t\t\t\tsetPointerCapture(e.currentTarget, e)\n\n\t\t\t\teditor.dispatch({\n\t\t\t\t\ttype: 'pointer',\n\t\t\t\t\ttarget: 'canvas',\n\t\t\t\t\tname: 'pointer_down',\n\t\t\t\t\t...getPointerInfo(editor, e),\n\t\t\t\t})\n\t\t\t}\n\n\t\t\tfunction onPointerUp(e: React.PointerEvent) {\n\t\t\t\tif (editor.wasEventAlreadyHandled(e)) return\n\t\t\t\tif (e.button !== 0 && e.button !== 1 && e.button !== 2 && e.button !== 5) return\n\n\t\t\t\tconst rightClickPanning = editor.options.rightClickPanning\n\t\t\t\t// Check before dispatch (which resets isPanning)\n\t\t\t\tconst wasRightClickPanning =\n\t\t\t\t\trightClickPanning && e.button === 2 && editor.inputs.getIsPanning()\n\n\t\t\t\treleasePointerCapture(e.currentTarget, e)\n\n\t\t\t\teditor.dispatch({\n\t\t\t\t\ttype: 'pointer',\n\t\t\t\t\ttarget: 'canvas',\n\t\t\t\t\tname: 'pointer_up',\n\t\t\t\t\t...getPointerInfo(editor, e),\n\t\t\t\t})\n\n\t\t\t\t// Static right-click: fire contextmenu at the pointer-up location\n\t\t\t\tif (rightClickPanning && e.button === 2 && !wasRightClickPanning) {\n\t\t\t\t\tconst contextMenuEvent = new PointerEvent('contextmenu', {\n\t\t\t\t\t\tbubbles: true,\n\t\t\t\t\t\tclientX: e.clientX,\n\t\t\t\t\t\tclientY: e.clientY,\n\t\t\t\t\t\tbutton: 2,\n\t\t\t\t\t\tbuttons: 0,\n\t\t\t\t\t\tpointerId: e.pointerId,\n\t\t\t\t\t\tpointerType: e.pointerType,\n\t\t\t\t\t\tisPrimary: e.isPrimary,\n\t\t\t\t\t})\n\t\t\t\t\te.currentTarget.dispatchEvent(contextMenuEvent)\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tfunction onPointerEnter(e: React.PointerEvent) {\n\t\t\t\tif (editor.wasEventAlreadyHandled(e)) return\n\t\t\t\tif (editor.getInstanceState().isPenMode && e.pointerType !== 'pen') return\n\t\t\t\tconst canHover = e.pointerType === 'mouse' || e.pointerType === 'pen'\n\t\t\t\teditor.updateInstanceState({ isHoveringCanvas: canHover ? true : null })\n\t\t\t}\n\n\t\t\tfunction onPointerLeave(e: React.PointerEvent) {\n\t\t\t\tif (editor.wasEventAlreadyHandled(e)) return\n\t\t\t\tif (editor.getInstanceState().isPenMode && e.pointerType !== 'pen') return\n\t\t\t\tconst canHover = e.pointerType === 'mouse' || e.pointerType === 'pen'\n\t\t\t\teditor.updateInstanceState({ isHoveringCanvas: canHover ? false : null })\n\t\t\t}\n\n\t\t\tfunction onTouchStart(e: React.TouchEvent) {\n\t\t\t\tif (editor.wasEventAlreadyHandled(e)) return\n\t\t\t\teditor.markEventAsHandled(e)\n\t\t\t\tpreventDefault(e)\n\t\t\t}\n\n\t\t\tfunction onTouchEnd(e: React.TouchEvent) {\n\t\t\t\tif (editor.wasEventAlreadyHandled(e)) return\n\t\t\t\teditor.markEventAsHandled(e)\n\t\t\t\tif (!(e.target instanceof editor.getContainerWindow().HTMLElement)) return\n\n\t\t\t\tconst editingShapeId = editor.getEditingShapeId()\n\t\t\t\tif (\n\t\t\t\t\t// if the target is not inside the editing shape\n\t\t\t\t\t!(editingShapeId && e.target.closest(`[data-shape-id=\"${editingShapeId}\"]`)) &&\n\t\t\t\t\t// and the target is not an clickable element\n\t\t\t\t\te.target.tagName !== 'A' &&\n\t\t\t\t\t// and the target is not an editable element\n\t\t\t\t\t!elementShouldCaptureKeys(e.target, false)\n\t\t\t\t) {\n\t\t\t\t\tpreventDefault(e)\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tfunction onDragOver(e: React.DragEvent<Element>) {\n\t\t\t\tif (editor.wasEventAlreadyHandled(e)) return\n\t\t\t\tpreventDefault(e)\n\t\t\t}\n\n\t\t\tasync function onDrop(e: React.DragEvent<Element>) {\n\t\t\t\tif (editor.wasEventAlreadyHandled(e)) return\n\t\t\t\tpreventDefault(e)\n\t\t\t\te.stopPropagation()\n\n\t\t\t\tconst pagePoint = editor.screenToPage({ x: e.clientX, y: e.clientY })\n\n\t\t\t\t// Call the custom onDropOnCanvas callback if provided\n\t\t\t\tif (editor.options.experimental__onDropOnCanvas) {\n\t\t\t\t\tconst handled = editor.options.experimental__onDropOnCanvas({\n\t\t\t\t\t\tpoint: pagePoint,\n\t\t\t\t\t\tevent: e,\n\t\t\t\t\t})\n\t\t\t\t\tif (handled) return\n\t\t\t\t}\n\n\t\t\t\tif (e.dataTransfer?.files?.length) {\n\t\t\t\t\tconst files = Array.from(e.dataTransfer.files)\n\n\t\t\t\t\tawait editor.putExternalContent({\n\t\t\t\t\t\ttype: 'files',\n\t\t\t\t\t\tfiles,\n\t\t\t\t\t\tpoint: pagePoint,\n\t\t\t\t\t})\n\t\t\t\t\treturn\n\t\t\t\t}\n\n\t\t\t\tconst url = e.dataTransfer.getData('url')\n\t\t\t\tif (url) {\n\t\t\t\t\tawait editor.putExternalContent({\n\t\t\t\t\t\ttype: 'url',\n\t\t\t\t\t\turl,\n\t\t\t\t\t\tpoint: pagePoint,\n\t\t\t\t\t})\n\t\t\t\t\treturn\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tfunction onClick(e: React.MouseEvent) {\n\t\t\t\tif (editor.wasEventAlreadyHandled(e)) return\n\t\t\t\te.stopPropagation()\n\t\t\t}\n\n\t\t\tfunction onContextMenu(e: React.MouseEvent) {\n\t\t\t\t// With right-click panning disabled, let the native contextmenu through so the\n\t\t\t\t// menu opens on press.\n\t\t\t\tif (!editor.options.rightClickPanning) return\n\t\t\t\t// Synthetic events \u2014 our own dispatch from onPointerUp, or tests using\n\t\t\t\t// fireEvent.contextMenu \u2014 pass through so Radix can open the menu.\n\t\t\t\tif (!e.nativeEvent.isTrusted) return\n\t\t\t\t// Only suppress the native browser contextmenu when it follows a real\n\t\t\t\t// right-click (button=2 with no ctrl modifier). For those, our pointer\n\t\t\t\t// handling has already decided what to do (either we'll dispatch a\n\t\t\t\t// synthetic contextmenu on pointerup to open the menu at the release\n\t\t\t\t// position, or we panned and don't want a menu at all).\n\t\t\t\t//\n\t\t\t\t// Other contextmenu sources must reach Radix so the menu opens:\n\t\t\t\t// - ctrl+click on macOS (button=0, or button=2 with ctrlKey=true)\n\t\t\t\t// - long-press on touch devices (button=0, pointerType=touch)\n\t\t\t\tif (e.button !== 2 || e.ctrlKey) return\n\t\t\t\tpreventDefault(e)\n\t\t\t}\n\n\t\t\treturn {\n\t\t\t\tonPointerDown,\n\t\t\t\tonPointerUp,\n\t\t\t\tonPointerEnter,\n\t\t\t\tonPointerLeave,\n\t\t\t\tonDragOver,\n\t\t\t\tonDrop,\n\t\t\t\tonTouchStart,\n\t\t\t\tonTouchEnd,\n\t\t\t\tonClick,\n\t\t\t\tonContextMenu,\n\t\t\t}\n\t\t},\n\t\t[editor]\n\t)\n\n\t// onPointerMove is special: where we're only interested in the other events when they're\n\t// happening _on_ the canvas (as opposed to outside of it, or on UI floating over it), we want\n\t// the pointer position to be up to date regardless of whether it's over the tldraw canvas or\n\t// not. So instead of returning a listener to be attached to the canvas, we directly attach a\n\t// listener to the whole document instead.\n\tuseEffect(() => {\n\t\tlet lastX: number, lastY: number\n\n\t\tfunction onPointerMove(e: PointerEvent) {\n\t\t\tif (editor.wasEventAlreadyHandled(e)) return\n\t\t\teditor.markEventAsHandled(e)\n\n\t\t\tif (e.clientX === lastX && e.clientY === lastY) return\n\t\t\tlastX = e.clientX\n\t\t\tlastY = e.clientY\n\n\t\t\t// For tools that benefit from a higher fidelity of events,\n\t\t\t// we dispatch the coalesced events.\n\t\t\t// N.B. Sometimes getCoalescedEvents isn't present on iOS, ugh.\n\t\t\t// Specifically, in local mode (non-https) mode, iOS does not `useCoalescedEvents`\n\t\t\t// so it appears like the ink is working locally, when really it's just that `useCoalescedEvents`\n\t\t\t// is disabled. The intent here is to have `useCoalescedEvents` disabled for iOS.\n\t\t\tconst events =\n\t\t\t\t!tlenv.isIos && currentTool.useCoalescedEvents && e.getCoalescedEvents\n\t\t\t\t\t? e.getCoalescedEvents()\n\t\t\t\t\t: [e]\n\n\t\t\tfor (const singleEvent of events) {\n\t\t\t\teditor.dispatch({\n\t\t\t\t\ttype: 'pointer',\n\t\t\t\t\ttarget: 'canvas',\n\t\t\t\t\tname: 'pointer_move',\n\t\t\t\t\t...getPointerInfo(editor, singleEvent),\n\t\t\t\t})\n\t\t\t}\n\t\t}\n\n\t\townerDocument.body.addEventListener('pointermove', onPointerMove)\n\t\treturn () => {\n\t\t\townerDocument.body.removeEventListener('pointermove', onPointerMove)\n\t\t}\n\t}, [editor, currentTool, ownerDocument])\n\n\treturn events\n}\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["import { useValue } from '@tldraw/state-react'\nimport React, { useEffect, useMemo } from 'react'\nimport { tlenv } from '../globals/environment'\nimport {\n\telementShouldCaptureKeys,\n\tpreventDefault,\n\treleasePointerCapture,\n\tsetPointerCapture,\n} from '../utils/dom'\nimport { getPointerInfo } from '../utils/getPointerInfo'\nimport { getPointerEventButton, isDirectDisplayPen, isSecondaryClickEvent } from '../utils/pointer'\nimport { useEditor } from './useEditor'\n\nexport function useCanvasEvents() {\n\tconst editor = useEditor()\n\tconst ownerDocument = editor.getContainerDocument()\n\tconst currentTool = useValue('current tool', () => editor.getCurrentTool(), [editor])\n\n\tconst events = useMemo(\n\t\tfunction canvasEvents() {\n\t\t\tlet isSecondaryClickPointerDown = false\n\n\t\t\tfunction onPointerDown(e: React.PointerEvent) {\n\t\t\t\tif (editor.wasEventAlreadyHandled(e)) return\n\t\t\t\tconst button = getPointerEventButton(e)\n\t\t\t\tisSecondaryClickPointerDown = button === 2\n\n\t\t\t\t// With right-click panning disabled, fire right_click on press and let the\n\t\t\t\t// native contextmenu through so the menu opens at the pointer-down location.\n\t\t\t\tif (button === 2 && !editor.options.rightClickPanning) {\n\t\t\t\t\teditor.dispatch({\n\t\t\t\t\t\ttype: 'pointer',\n\t\t\t\t\t\ttarget: 'canvas',\n\t\t\t\t\t\tname: 'right_click',\n\t\t\t\t\t\t...getPointerInfo(editor, e),\n\t\t\t\t\t})\n\t\t\t\t\treturn\n\t\t\t\t}\n\n\t\t\t\tif (button !== 0 && button !== 1 && button !== 2 && button !== 5) return\n\n\t\t\t\t// Detect direct-display pen input (Apple Pencil, Surface Pen on a touchscreen) so we\n\t\t\t\t// only auto-enable pen mode for it, not for an indirect desktop tablet stylus.\n\t\t\t\tconst isPenDirect = isDirectDisplayPen(e)\n\n\t\t\t\tsetPointerCapture(e.currentTarget, e)\n\n\t\t\t\teditor.dispatch({\n\t\t\t\t\ttype: 'pointer',\n\t\t\t\t\ttarget: 'canvas',\n\t\t\t\t\tname: 'pointer_down',\n\t\t\t\t\t...getPointerInfo(editor, e),\n\t\t\t\t\tisPenDirect,\n\t\t\t\t})\n\t\t\t}\n\n\t\t\tfunction onPointerUp(e: React.PointerEvent) {\n\t\t\t\tif (editor.wasEventAlreadyHandled(e)) return\n\t\t\t\tconst button = isSecondaryClickPointerDown ? 2 : getPointerEventButton(e)\n\t\t\t\tif (button !== 0 && button !== 1 && button !== 2 && button !== 5) return\n\n\t\t\t\tconst rightClickPanning = editor.options.rightClickPanning\n\t\t\t\t// Check before dispatch (which resets isPanning)\n\t\t\t\tconst wasRightClickPanning =\n\t\t\t\t\trightClickPanning && button === 2 && editor.inputs.getIsPanning()\n\n\t\t\t\treleasePointerCapture(e.currentTarget, e)\n\n\t\t\t\teditor.dispatch({\n\t\t\t\t\ttype: 'pointer',\n\t\t\t\t\ttarget: 'canvas',\n\t\t\t\t\tname: 'pointer_up',\n\t\t\t\t\t...getPointerInfo(editor, e),\n\t\t\t\t\tbutton,\n\t\t\t\t})\n\n\t\t\t\t// Static right-click: fire contextmenu at the pointer-up location\n\t\t\t\tif (rightClickPanning && button === 2 && !wasRightClickPanning) {\n\t\t\t\t\tconst contextMenuEvent = new PointerEvent('contextmenu', {\n\t\t\t\t\t\tbubbles: true,\n\t\t\t\t\t\tclientX: e.clientX,\n\t\t\t\t\t\tclientY: e.clientY,\n\t\t\t\t\t\tbutton: 2,\n\t\t\t\t\t\tbuttons: 0,\n\t\t\t\t\t\tpointerId: e.pointerId,\n\t\t\t\t\t\tpointerType: e.pointerType,\n\t\t\t\t\t\tisPrimary: e.isPrimary,\n\t\t\t\t\t})\n\t\t\t\t\te.currentTarget.dispatchEvent(contextMenuEvent)\n\t\t\t\t}\n\t\t\t\tisSecondaryClickPointerDown = false\n\t\t\t}\n\n\t\t\tfunction onPointerEnter(e: React.PointerEvent) {\n\t\t\t\tif (editor.wasEventAlreadyHandled(e)) return\n\t\t\t\tif (editor.getInstanceState().isPenMode && e.pointerType !== 'pen') return\n\t\t\t\tconst canHover = e.pointerType === 'mouse' || e.pointerType === 'pen'\n\t\t\t\teditor.updateInstanceState({ isHoveringCanvas: canHover ? true : null })\n\t\t\t}\n\n\t\t\tfunction onPointerLeave(e: React.PointerEvent) {\n\t\t\t\tif (editor.wasEventAlreadyHandled(e)) return\n\t\t\t\tif (editor.getInstanceState().isPenMode && e.pointerType !== 'pen') return\n\t\t\t\tconst canHover = e.pointerType === 'mouse' || e.pointerType === 'pen'\n\t\t\t\teditor.updateInstanceState({ isHoveringCanvas: canHover ? false : null })\n\t\t\t}\n\n\t\t\tfunction onTouchStart(e: React.TouchEvent) {\n\t\t\t\tif (editor.wasEventAlreadyHandled(e)) return\n\t\t\t\teditor.markEventAsHandled(e)\n\t\t\t\tpreventDefault(e)\n\t\t\t}\n\n\t\t\tfunction onTouchEnd(e: React.TouchEvent) {\n\t\t\t\tif (editor.wasEventAlreadyHandled(e)) return\n\t\t\t\teditor.markEventAsHandled(e)\n\t\t\t\tif (!(e.target instanceof editor.getContainerWindow().HTMLElement)) return\n\n\t\t\t\tconst editingShapeId = editor.getEditingShapeId()\n\t\t\t\tif (\n\t\t\t\t\t// if the target is not inside the editing shape\n\t\t\t\t\t!(editingShapeId && e.target.closest(`[data-shape-id=\"${editingShapeId}\"]`)) &&\n\t\t\t\t\t// and the target is not an clickable element\n\t\t\t\t\te.target.tagName !== 'A' &&\n\t\t\t\t\t// and the target is not an editable element\n\t\t\t\t\t!elementShouldCaptureKeys(e.target, false)\n\t\t\t\t) {\n\t\t\t\t\tpreventDefault(e)\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tfunction onDragOver(e: React.DragEvent<Element>) {\n\t\t\t\tif (editor.wasEventAlreadyHandled(e)) return\n\t\t\t\tpreventDefault(e)\n\t\t\t}\n\n\t\t\tasync function onDrop(e: React.DragEvent<Element>) {\n\t\t\t\tif (editor.wasEventAlreadyHandled(e)) return\n\t\t\t\tpreventDefault(e)\n\t\t\t\te.stopPropagation()\n\n\t\t\t\tconst pagePoint = editor.screenToPage({ x: e.clientX, y: e.clientY })\n\n\t\t\t\t// Call the custom onDropOnCanvas callback if provided\n\t\t\t\tif (editor.options.experimental__onDropOnCanvas) {\n\t\t\t\t\tconst handled = editor.options.experimental__onDropOnCanvas({\n\t\t\t\t\t\tpoint: pagePoint,\n\t\t\t\t\t\tevent: e,\n\t\t\t\t\t})\n\t\t\t\t\tif (handled) return\n\t\t\t\t}\n\n\t\t\t\tif (e.dataTransfer?.files?.length) {\n\t\t\t\t\tconst files = Array.from(e.dataTransfer.files)\n\n\t\t\t\t\tawait editor.putExternalContent({\n\t\t\t\t\t\ttype: 'files',\n\t\t\t\t\t\tfiles,\n\t\t\t\t\t\tpoint: pagePoint,\n\t\t\t\t\t})\n\t\t\t\t\treturn\n\t\t\t\t}\n\n\t\t\t\tconst url = e.dataTransfer.getData('url')\n\t\t\t\tif (url) {\n\t\t\t\t\tawait editor.putExternalContent({\n\t\t\t\t\t\ttype: 'url',\n\t\t\t\t\t\turl,\n\t\t\t\t\t\tpoint: pagePoint,\n\t\t\t\t\t})\n\t\t\t\t\treturn\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tfunction onClick(e: React.MouseEvent) {\n\t\t\t\tif (editor.wasEventAlreadyHandled(e)) return\n\t\t\t\te.stopPropagation()\n\t\t\t}\n\n\t\t\tfunction onContextMenu(e: React.MouseEvent) {\n\t\t\t\t// With right-click panning disabled, let the native contextmenu through so the\n\t\t\t\t// menu opens on press.\n\t\t\t\tif (!editor.options.rightClickPanning) return\n\t\t\t\t// Synthetic events \u2014 our own dispatch from onPointerUp, or tests using\n\t\t\t\t// fireEvent.contextMenu \u2014 pass through so Radix can open the menu.\n\t\t\t\tif (!e.nativeEvent.isTrusted) return\n\t\t\t\t// Only suppress the native browser contextmenu when it follows a\n\t\t\t\t// secondary click. For those, our pointer handling has already\n\t\t\t\t// decided what to do (either we'll dispatch a synthetic contextmenu on\n\t\t\t\t// pointerup to open the menu at the release position, or we panned and\n\t\t\t\t// don't want a menu at all).\n\t\t\t\t//\n\t\t\t\t// Other contextmenu sources must reach Radix so the menu opens:\n\t\t\t\t// - long-press on touch devices (button=0, pointerType=touch)\n\t\t\t\tif (!isSecondaryClickEvent(e)) return\n\t\t\t\tpreventDefault(e)\n\t\t\t}\n\n\t\t\treturn {\n\t\t\t\tonPointerDown,\n\t\t\t\tonPointerUp,\n\t\t\t\tonPointerEnter,\n\t\t\t\tonPointerLeave,\n\t\t\t\tonDragOver,\n\t\t\t\tonDrop,\n\t\t\t\tonTouchStart,\n\t\t\t\tonTouchEnd,\n\t\t\t\tonClick,\n\t\t\t\tonContextMenu,\n\t\t\t}\n\t\t},\n\t\t[editor]\n\t)\n\n\t// onPointerMove is special: where we're only interested in the other events when they're\n\t// happening _on_ the canvas (as opposed to outside of it, or on UI floating over it), we want\n\t// the pointer position to be up to date regardless of whether it's over the tldraw canvas or\n\t// not. So instead of returning a listener to be attached to the canvas, we directly attach a\n\t// listener to the whole document instead.\n\tuseEffect(() => {\n\t\tlet lastX: number, lastY: number\n\n\t\tfunction onPointerMove(e: PointerEvent) {\n\t\t\tif (editor.wasEventAlreadyHandled(e)) return\n\t\t\teditor.markEventAsHandled(e)\n\n\t\t\tif (e.clientX === lastX && e.clientY === lastY) return\n\t\t\tlastX = e.clientX\n\t\t\tlastY = e.clientY\n\n\t\t\t// For tools that benefit from a higher fidelity of events,\n\t\t\t// we dispatch the coalesced events.\n\t\t\t// N.B. Sometimes getCoalescedEvents isn't present on iOS, ugh.\n\t\t\t// Specifically, in local mode (non-https) mode, iOS does not `useCoalescedEvents`\n\t\t\t// so it appears like the ink is working locally, when really it's just that `useCoalescedEvents`\n\t\t\t// is disabled. The intent here is to have `useCoalescedEvents` disabled for iOS.\n\t\t\tconst events =\n\t\t\t\t!tlenv.isIos && currentTool.useCoalescedEvents && e.getCoalescedEvents\n\t\t\t\t\t? e.getCoalescedEvents()\n\t\t\t\t\t: [e]\n\n\t\t\tfor (const singleEvent of events) {\n\t\t\t\teditor.dispatch({\n\t\t\t\t\ttype: 'pointer',\n\t\t\t\t\ttarget: 'canvas',\n\t\t\t\t\tname: 'pointer_move',\n\t\t\t\t\t...getPointerInfo(editor, singleEvent),\n\t\t\t\t})\n\t\t\t}\n\t\t}\n\n\t\townerDocument.body.addEventListener('pointermove', onPointerMove)\n\t\treturn () => {\n\t\t\townerDocument.body.removeEventListener('pointermove', onPointerMove)\n\t\t}\n\t}, [editor, currentTool, ownerDocument])\n\n\treturn events\n}\n"],
5
+ "mappings": "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",
6
6
  "names": ["events"]
7
7
  }
@@ -25,7 +25,6 @@ function EditorComponentsProvider({
25
25
  InFrontOfTheCanvas: null,
26
26
  LoadingScreen: DefaultLoadingScreen,
27
27
  OnTheCanvas: null,
28
- SelectionBackground: null,
29
28
  ShapeWrapper: DefaultShapeWrapper,
30
29
  Spinner: DefaultSpinner,
31
30
  SvgDefs: DefaultSvgDefs,
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../src/lib/hooks/useEditorComponents.tsx"],
4
- "sourcesContent": ["import { ReactNode, useMemo } from 'react'\nimport { DefaultBackground } from '../components/default-components/DefaultBackground'\nimport { DefaultCanvas } from '../components/default-components/DefaultCanvas'\nimport { DefaultErrorFallback } from '../components/default-components/DefaultErrorFallback'\nimport { DefaultGrid } from '../components/default-components/DefaultGrid'\nimport { DefaultLoadingScreen } from '../components/default-components/DefaultLoadingScreen'\nimport { DefaultShapeErrorFallback } from '../components/default-components/DefaultShapeErrorFallback'\nimport { DefaultShapeWrapper } from '../components/default-components/DefaultShapeWrapper'\nimport { DefaultSpinner } from '../components/default-components/DefaultSpinner'\nimport { DefaultSvgDefs } from '../components/default-components/DefaultSvgDefs'\nimport { EditorComponentsContext } from './EditorComponentsContext'\nimport type { TLEditorComponents } from './EditorComponentsContext'\nimport { useShallowObjectIdentity } from './useIdentity'\n\nexport { useEditorComponents } from './EditorComponentsContext'\nexport type { TLEditorComponents } from './EditorComponentsContext'\n\ninterface ComponentsContextProviderProps {\n\toverrides?: TLEditorComponents\n\tchildren: ReactNode\n}\n\nexport function EditorComponentsProvider({\n\toverrides = {},\n\tchildren,\n}: ComponentsContextProviderProps) {\n\tconst _overrides = useShallowObjectIdentity(overrides)\n\tconst value = useMemo(\n\t\t(): Required<TLEditorComponents> => ({\n\t\t\tBackground: DefaultBackground,\n\t\t\tCanvas: DefaultCanvas,\n\t\t\tGrid: DefaultGrid,\n\t\t\tInFrontOfTheCanvas: null,\n\t\t\tLoadingScreen: DefaultLoadingScreen,\n\t\t\tOnTheCanvas: null,\n\t\t\tSelectionBackground: null,\n\t\t\tShapeWrapper: DefaultShapeWrapper,\n\t\t\tSpinner: DefaultSpinner,\n\t\t\tSvgDefs: DefaultSvgDefs,\n\n\t\t\tErrorFallback: DefaultErrorFallback,\n\t\t\tShapeErrorFallback: DefaultShapeErrorFallback,\n\n\t\t\t..._overrides,\n\t\t}),\n\t\t[_overrides]\n\t)\n\n\treturn (\n\t\t<EditorComponentsContext.Provider value={value}>{children}</EditorComponentsContext.Provider>\n\t)\n}\n"],
5
- "mappings": "AAiDE;AAjDF,SAAoB,eAAe;AACnC,SAAS,yBAAyB;AAClC,SAAS,qBAAqB;AAC9B,SAAS,4BAA4B;AACrC,SAAS,mBAAmB;AAC5B,SAAS,4BAA4B;AACrC,SAAS,iCAAiC;AAC1C,SAAS,2BAA2B;AACpC,SAAS,sBAAsB;AAC/B,SAAS,sBAAsB;AAC/B,SAAS,+BAA+B;AAExC,SAAS,gCAAgC;AAEzC,SAAS,2BAA2B;AAQ7B,SAAS,yBAAyB;AAAA,EACxC,YAAY,CAAC;AAAA,EACb;AACD,GAAmC;AAClC,QAAM,aAAa,yBAAyB,SAAS;AACrD,QAAM,QAAQ;AAAA,IACb,OAAqC;AAAA,MACpC,YAAY;AAAA,MACZ,QAAQ;AAAA,MACR,MAAM;AAAA,MACN,oBAAoB;AAAA,MACpB,eAAe;AAAA,MACf,aAAa;AAAA,MACb,qBAAqB;AAAA,MACrB,cAAc;AAAA,MACd,SAAS;AAAA,MACT,SAAS;AAAA,MAET,eAAe;AAAA,MACf,oBAAoB;AAAA,MAEpB,GAAG;AAAA,IACJ;AAAA,IACA,CAAC,UAAU;AAAA,EACZ;AAEA,SACC,oBAAC,wBAAwB,UAAxB,EAAiC,OAAe,UAAS;AAE5D;",
4
+ "sourcesContent": ["import { ReactNode, useMemo } from 'react'\nimport { DefaultBackground } from '../components/default-components/DefaultBackground'\nimport { DefaultCanvas } from '../components/default-components/DefaultCanvas'\nimport { DefaultErrorFallback } from '../components/default-components/DefaultErrorFallback'\nimport { DefaultGrid } from '../components/default-components/DefaultGrid'\nimport { DefaultLoadingScreen } from '../components/default-components/DefaultLoadingScreen'\nimport { DefaultShapeErrorFallback } from '../components/default-components/DefaultShapeErrorFallback'\nimport { DefaultShapeWrapper } from '../components/default-components/DefaultShapeWrapper'\nimport { DefaultSpinner } from '../components/default-components/DefaultSpinner'\nimport { DefaultSvgDefs } from '../components/default-components/DefaultSvgDefs'\nimport { EditorComponentsContext } from './EditorComponentsContext'\nimport type { TLEditorComponents } from './EditorComponentsContext'\nimport { useShallowObjectIdentity } from './useIdentity'\n\nexport { useEditorComponents } from './EditorComponentsContext'\nexport type { TLEditorComponents } from './EditorComponentsContext'\n\ninterface ComponentsContextProviderProps {\n\toverrides?: TLEditorComponents\n\tchildren: ReactNode\n}\n\nexport function EditorComponentsProvider({\n\toverrides = {},\n\tchildren,\n}: ComponentsContextProviderProps) {\n\tconst _overrides = useShallowObjectIdentity(overrides)\n\tconst value = useMemo(\n\t\t(): Required<TLEditorComponents> => ({\n\t\t\tBackground: DefaultBackground,\n\t\t\tCanvas: DefaultCanvas,\n\t\t\tGrid: DefaultGrid,\n\t\t\tInFrontOfTheCanvas: null,\n\t\t\tLoadingScreen: DefaultLoadingScreen,\n\t\t\tOnTheCanvas: null,\n\t\t\tShapeWrapper: DefaultShapeWrapper,\n\t\t\tSpinner: DefaultSpinner,\n\t\t\tSvgDefs: DefaultSvgDefs,\n\n\t\t\tErrorFallback: DefaultErrorFallback,\n\t\t\tShapeErrorFallback: DefaultShapeErrorFallback,\n\n\t\t\t..._overrides,\n\t\t}),\n\t\t[_overrides]\n\t)\n\n\treturn (\n\t\t<EditorComponentsContext.Provider value={value}>{children}</EditorComponentsContext.Provider>\n\t)\n}\n"],
5
+ "mappings": "AAgDE;AAhDF,SAAoB,eAAe;AACnC,SAAS,yBAAyB;AAClC,SAAS,qBAAqB;AAC9B,SAAS,4BAA4B;AACrC,SAAS,mBAAmB;AAC5B,SAAS,4BAA4B;AACrC,SAAS,iCAAiC;AAC1C,SAAS,2BAA2B;AACpC,SAAS,sBAAsB;AAC/B,SAAS,sBAAsB;AAC/B,SAAS,+BAA+B;AAExC,SAAS,gCAAgC;AAEzC,SAAS,2BAA2B;AAQ7B,SAAS,yBAAyB;AAAA,EACxC,YAAY,CAAC;AAAA,EACb;AACD,GAAmC;AAClC,QAAM,aAAa,yBAAyB,SAAS;AACrD,QAAM,QAAQ;AAAA,IACb,OAAqC;AAAA,MACpC,YAAY;AAAA,MACZ,QAAQ;AAAA,MACR,MAAM;AAAA,MACN,oBAAoB;AAAA,MACpB,eAAe;AAAA,MACf,aAAa;AAAA,MACb,cAAc;AAAA,MACd,SAAS;AAAA,MACT,SAAS;AAAA,MAET,eAAe;AAAA,MACf,oBAAoB;AAAA,MAEpB,GAAG;AAAA,IACJ;AAAA,IACA,CAAC,UAAU;AAAA,EACZ;AAEA,SACC,oBAAC,wBAAwB,UAAxB,EAAiC,OAAe,UAAS;AAE5D;",
6
6
  "names": []
7
7
  }
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../src/lib/hooks/usePresence.ts"],
4
- "sourcesContent": ["import { useValue } from '@tldraw/state-react'\nimport { TLInstancePresence } from '@tldraw/tlschema'\nimport { useEditor } from './useEditor'\n\n// TODO: maybe move this to a computed property on the App class?\n/**\n * @returns The latest presence of the user matching userId\n * @public\n */\nexport function usePresence(userId: string): TLInstancePresence | null {\n\tconst editor = useEditor()\n\n\tconst latestPresence = useValue(\n\t\t`latestPresence:${userId}`,\n\t\t() => {\n\t\t\treturn editor.getCollaborators().find((c) => c.userId === userId)\n\t\t},\n\t\t[editor, userId]\n\t)\n\n\treturn latestPresence ?? null\n}\n"],
5
- "mappings": "AAAA,SAAS,gBAAgB;AAEzB,SAAS,iBAAiB;AAOnB,SAAS,YAAY,QAA2C;AACtE,QAAM,SAAS,UAAU;AAEzB,QAAM,iBAAiB;AAAA,IACtB,kBAAkB,MAAM;AAAA,IACxB,MAAM;AACL,aAAO,OAAO,iBAAiB,EAAE,KAAK,CAAC,MAAM,EAAE,WAAW,MAAM;AAAA,IACjE;AAAA,IACA,CAAC,QAAQ,MAAM;AAAA,EAChB;AAEA,SAAO,kBAAkB;AAC1B;",
4
+ "sourcesContent": ["import { useValue } from '@tldraw/state-react'\nimport { TLInstancePresence, TLUserId } from '@tldraw/tlschema'\nimport { useEditor } from './useEditor'\n\n// TODO: maybe move this to a computed property on the App class?\n/**\n * @returns The latest presence of the user matching userId\n * @public\n */\nexport function usePresence(userId: TLUserId): TLInstancePresence | null {\n\tconst editor = useEditor()\n\n\tconst latestPresence = useValue(\n\t\t`latestPresence:${userId}`,\n\t\t() => {\n\t\t\treturn editor.getCollaborators().find((c) => c.userId === userId)\n\t\t},\n\t\t[editor, userId]\n\t)\n\n\treturn latestPresence ?? null\n}\n"],
5
+ "mappings": "AAAA,SAAS,gBAAgB;AAEzB,SAAS,iBAAiB;AAOnB,SAAS,YAAY,QAA6C;AACxE,QAAM,SAAS,UAAU;AAEzB,QAAM,iBAAiB;AAAA,IACtB,kBAAkB,MAAM;AAAA,IACxB,MAAM;AACL,aAAO,OAAO,iBAAiB,EAAE,KAAK,CAAC,MAAM,EAAE,WAAW,MAAM;AAAA,IACjE;AAAA,IACA,CAAC,QAAQ,MAAM;AAAA,EAChB;AAEA,SAAO,kBAAkB;AAC1B;",
6
6
  "names": []
7
7
  }
@@ -8,6 +8,7 @@ function useScreenBounds(ref) {
8
8
  const updateBounds = throttle(
9
9
  () => {
10
10
  if (!ref.current) return;
11
+ if (!ref.current.ownerDocument.body) return;
11
12
  editor.updateViewportScreenBounds(ref.current);
12
13
  },
13
14
  200,
@@ -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 { 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,SAAS,gBAAgB;AACzB,SAAS,uBAAuB;AAChC,SAAS,sBAAsB;AAC/B,SAAS,iBAAiB;AAEnB,SAAS,gBAAgB,KAA0C;AACzE,QAAM,SAAS,UAAU;AAEzB,kBAAgB,MAAM;AAErB,UAAM,eAAe;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,MAAM,eAAe,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;",
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\t// If the container's document has been torn down (e.g. an iframe\n\t\t\t\t// being removed), there's nothing to measure \u2014 bail.\n\t\t\t\tif (!ref.current.ownerDocument.body) 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,SAAS,gBAAgB;AACzB,SAAS,uBAAuB;AAChC,SAAS,sBAAsB;AAC/B,SAAS,iBAAiB;AAEnB,SAAS,gBAAgB,KAA0C;AACzE,QAAM,SAAS,UAAU;AAEzB,kBAAgB,MAAM;AAErB,UAAM,eAAe;AAAA,MACpB,MAAM;AACL,YAAI,CAAC,IAAI,QAAS;AAGlB,YAAI,CAAC,IAAI,QAAQ,cAAc,KAAM;AACrC,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,MAAM,eAAe,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
  }
@@ -56,7 +56,11 @@ class LicenseManager {
56
56
  });
57
57
  }
58
58
  getIsDevelopment() {
59
- return !["https:", "vscode-webview:"].includes(window.location.protocol) || window.location.hostname === "localhost" || process.env.NODE_ENV !== "production";
59
+ return !["https:", "vscode-webview:"].includes(window.location.protocol) || this.isLoopbackHost(window.location.hostname) || process.env.NODE_ENV !== "production";
60
+ }
61
+ isLoopbackHost(hostname) {
62
+ const host = hostname.toLowerCase().replace(/^\[|\]$/g, "");
63
+ return host === "localhost" || host === "::1" || /^127(?:\.\d{1,3}){3}$/.test(host);
60
64
  }
61
65
  getTrackType(result, licenseState) {
62
66
  if (licenseState === "unlicensed-production") {
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../src/lib/license/LicenseManager.ts"],
4
- "sourcesContent": ["import { atom } from '@tldraw/state'\nimport { publishDates, version } from '../../version'\nimport { getDefaultCdnBaseUrl } from '../utils/assets'\nimport { importPublicKey, str2ab } from '../utils/licensing'\n\nconst GRACE_PERIOD_DAYS = 30\n\nexport const FLAGS = {\n\t// -- MUTUALLY EXCLUSIVE FLAGS\n\t// Annual means the license expires after a time period, usually 1 year.\n\tANNUAL_LICENSE: 1,\n\t// Perpetual means the license never expires up to the max supported version.\n\tPERPETUAL_LICENSE: 1 << 1,\n\n\t// -- ADDITIVE FLAGS --\n\t// Internal means the license is for internal use only.\n\tINTERNAL_LICENSE: 1 << 2,\n\t// Watermark means the product is watermarked.\n\tWITH_WATERMARK: 1 << 3,\n\t// Evaluation means the license is for evaluation purposes only.\n\tEVALUATION_LICENSE: 1 << 4,\n\t// Native means the license is for native apps which switches\n\t// on special-case logic.\n\tNATIVE_LICENSE: 1 << 5,\n}\nconst HIGHEST_FLAG = Math.max(...Object.values(FLAGS))\n\nexport const PROPERTIES = {\n\tID: 0,\n\tHOSTS: 1,\n\tFLAGS: 2,\n\tEXPIRY_DATE: 3,\n}\nconst NUMBER_OF_KNOWN_PROPERTIES = Object.keys(PROPERTIES).length\n\nconst LICENSE_EMAIL = 'sales@tldraw.com'\n\nconst WATERMARK_TRACK_SRC = `${getDefaultCdnBaseUrl()}/watermarks/watermark-track.svg`\n\n/** @internal */\nexport interface LicenseInfo {\n\tid: string\n\thosts: string[]\n\tflags: number\n\texpiryDate: string\n}\n\n/** @internal */\nexport type LicenseState =\n\t| 'pending' // License validation is in progress\n\t| 'licensed' // License is valid and active (no restrictions)\n\t| 'licensed-with-watermark' // License is valid but shows watermark (evaluation licenses, WITH_WATERMARK licenses)\n\t| 'unlicensed' // No valid license found or license is invalid (development)\n\t| 'unlicensed-production' // No valid license in production deployment (missing, invalid, or wrong domain)\n\t| 'expired' // License has been expired (30 days past expiration for regular licenses, immediately for evaluation licenses)\n/** @internal */\nexport type InvalidLicenseReason =\n\t| 'invalid-license-key'\n\t| 'no-key-provided'\n\t| 'has-key-development-mode'\n\n/** @internal */\nexport type LicenseFromKeyResult = InvalidLicenseKeyResult | ValidLicenseKeyResult\n\n/** @internal */\nexport interface InvalidLicenseKeyResult {\n\tisLicenseParseable: false\n\treason: InvalidLicenseReason\n}\n\n/** @internal */\nexport interface ValidLicenseKeyResult {\n\tisLicenseParseable: true\n\tlicense: LicenseInfo\n\tisDevelopment: boolean\n\tisDomainValid: boolean\n\texpiryDate: Date\n\tisAnnualLicense: boolean\n\tisAnnualLicenseExpired: boolean\n\tisPerpetualLicense: boolean\n\tisPerpetualLicenseExpired: boolean\n\tisInternalLicense: boolean\n\tisNativeLicense: boolean\n\tisLicensedWithWatermark: boolean\n\tisEvaluationLicense: boolean\n\tisEvaluationLicenseExpired: boolean\n\tdaysSinceExpiry: number\n}\n\n/** @internal */\nexport type TrackType = 'unlicensed' | 'with_watermark' | 'evaluation' | null\n\n/** @internal */\nexport class LicenseManager {\n\tprivate publicKey =\n\t\t'MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEHJh0uUfxHtCGyerXmmatE368Hd9rI6LH9oPDQihnaCryRFWEVeOvf9U/SPbyxX74LFyJs5tYeAHq5Nc0Ax25LQ'\n\tpublic isDevelopment: boolean\n\tpublic isTest: boolean\n\tpublic isCryptoAvailable: boolean\n\tstate = atom<LicenseState>('license state', 'pending')\n\tpublic verbose = true\n\n\tconstructor(licenseKey: string | undefined, testPublicKey?: string) {\n\t\tthis.isTest = process.env.NODE_ENV === 'test'\n\t\tthis.isDevelopment = this.getIsDevelopment()\n\t\tthis.publicKey = testPublicKey || this.publicKey\n\t\tthis.isCryptoAvailable = !!crypto.subtle\n\n\t\tthis.getLicenseFromKey(licenseKey)\n\t\t\t.then((result) => {\n\t\t\t\tconst licenseState = getLicenseState(\n\t\t\t\t\tresult,\n\t\t\t\t\t(messages: string[]) => this.outputMessages(messages),\n\t\t\t\t\tthis.isDevelopment\n\t\t\t\t)\n\n\t\t\t\tthis.maybeTrack(result, licenseState)\n\n\t\t\t\tthis.state.set(licenseState)\n\t\t\t})\n\t\t\t.catch((error) => {\n\t\t\t\tconsole.error('License validation failed:', error)\n\t\t\t\tthis.state.set('unlicensed')\n\t\t\t})\n\t}\n\n\tprivate getIsDevelopment() {\n\t\t// If we are using https on a non-localhost domain we assume it's a production env and a development one otherwise\n\t\treturn (\n\t\t\t!['https:', 'vscode-webview:'].includes(window.location.protocol) ||\n\t\t\twindow.location.hostname === 'localhost' ||\n\t\t\tprocess.env.NODE_ENV !== 'production'\n\t\t)\n\t}\n\n\tprivate getTrackType(result: LicenseFromKeyResult, licenseState: LicenseState): TrackType {\n\t\t// Track watermark for unlicensed production deployments\n\t\tif (licenseState === 'unlicensed-production') {\n\t\t\treturn 'unlicensed'\n\t\t}\n\n\t\tif (this.isDevelopment) {\n\t\t\treturn null\n\t\t}\n\n\t\tif (!result.isLicenseParseable) {\n\t\t\treturn null\n\t\t}\n\n\t\t// Track evaluation licenses (for analytics, even though no watermark is shown)\n\t\tif (result.isEvaluationLicense) {\n\t\t\treturn 'evaluation'\n\t\t}\n\n\t\t// Track licenses that show watermarks\n\t\tif (licenseState === 'licensed-with-watermark') {\n\t\t\treturn 'with_watermark'\n\t\t}\n\n\t\treturn null\n\t}\n\n\tprivate maybeTrack(result: LicenseFromKeyResult, licenseState: LicenseState): void {\n\t\tconst trackType = this.getTrackType(result, licenseState)\n\t\tif (!trackType) {\n\t\t\treturn\n\t\t}\n\n\t\tconst url = new URL(WATERMARK_TRACK_SRC)\n\t\turl.searchParams.set('version', version)\n\t\turl.searchParams.set('license_type', trackType)\n\t\tif ('license' in result) {\n\t\t\turl.searchParams.set('license_id', result.license.id)\n\t\t\tconst sku = this.isFlagEnabled(result.license.flags, FLAGS.EVALUATION_LICENSE)\n\t\t\t\t? 'evaluation'\n\t\t\t\t: this.isFlagEnabled(result.license.flags, FLAGS.ANNUAL_LICENSE)\n\t\t\t\t\t? 'annual'\n\t\t\t\t\t: this.isFlagEnabled(result.license.flags, FLAGS.PERPETUAL_LICENSE)\n\t\t\t\t\t\t? 'perpetual'\n\t\t\t\t\t\t: 'unknown'\n\t\t\turl.searchParams.set('sku', sku)\n\t\t}\n\t\turl.searchParams.set('url', window.location.href)\n\t\tif (process.env.NODE_ENV) {\n\t\t\turl.searchParams.set('environment', process.env.NODE_ENV)\n\t\t}\n\n\t\t// eslint-disable-next-line no-restricted-globals\n\t\tfetch(url.toString())\n\t}\n\n\tprivate async extractLicenseKey(licenseKey: string): Promise<LicenseInfo> {\n\t\tconst [data, signature] = licenseKey.split('.')\n\t\tconst [prefix, encodedData] = data.split('/')\n\n\t\tif (!prefix.startsWith('tldraw-')) {\n\t\t\tthrow new Error(`Unsupported prefix '${prefix}'`)\n\t\t}\n\n\t\tconst publicCryptoKey = await importPublicKey(this.publicKey)\n\n\t\tlet isVerified\n\t\ttry {\n\t\t\tisVerified = await crypto.subtle.verify(\n\t\t\t\t{\n\t\t\t\t\tname: 'ECDSA',\n\t\t\t\t\thash: { name: 'SHA-256' },\n\t\t\t\t},\n\t\t\t\tpublicCryptoKey,\n\t\t\t\tnew Uint8Array(str2ab(atob(signature))),\n\t\t\t\tnew Uint8Array(str2ab(atob(encodedData)))\n\t\t\t)\n\t\t} catch (e) {\n\t\t\tconsole.error(e)\n\t\t\tthrow new Error('Could not perform signature validation')\n\t\t}\n\n\t\tif (!isVerified) {\n\t\t\tthrow new Error('Invalid signature')\n\t\t}\n\n\t\tlet decodedData: any\n\t\ttry {\n\t\t\tdecodedData = JSON.parse(atob(encodedData))\n\t\t} catch {\n\t\t\tthrow new Error('Could not parse object')\n\t\t}\n\t\tif (decodedData.length > NUMBER_OF_KNOWN_PROPERTIES) {\n\t\t\tthis.outputMessages([\n\t\t\t\t'License key contains some unknown properties.',\n\t\t\t\t'You may want to update tldraw packages to a newer version to get access to new functionality.',\n\t\t\t])\n\t\t}\n\n\t\treturn {\n\t\t\tid: decodedData[PROPERTIES.ID],\n\t\t\thosts: decodedData[PROPERTIES.HOSTS],\n\t\t\tflags: decodedData[PROPERTIES.FLAGS],\n\t\t\texpiryDate: decodedData[PROPERTIES.EXPIRY_DATE],\n\t\t}\n\t}\n\n\tasync getLicenseFromKey(licenseKey?: string): Promise<LicenseFromKeyResult> {\n\t\tif (!licenseKey) {\n\t\t\tif (!this.isDevelopment) {\n\t\t\t\tthis.outputNoLicenseKeyProvided()\n\t\t\t}\n\n\t\t\treturn { isLicenseParseable: false, reason: 'no-key-provided' }\n\t\t}\n\n\t\tif (this.isDevelopment && !this.isCryptoAvailable) {\n\t\t\tif (this.verbose) {\n\t\t\t\t// eslint-disable-next-line no-console\n\t\t\t\tconsole.log(\n\t\t\t\t\t'tldraw: you seem to be in a development environment that does not support crypto. License not verified.'\n\t\t\t\t)\n\t\t\t\t// eslint-disable-next-line no-console\n\t\t\t\tconsole.log('You should check that this works in production separately.')\n\t\t\t}\n\t\t\t// We can't parse the license if we are in development mode since crypto\n\t\t\t// is not available on http\n\t\t\treturn { isLicenseParseable: false, reason: 'has-key-development-mode' }\n\t\t}\n\n\t\t// Borrowed idea from AG Grid:\n\t\t// Copying from various sources (like PDFs) can include zero-width characters.\n\t\t// This helps makes sure the key validation doesn't fail.\n\t\tlet cleanedLicenseKey = licenseKey.replace(/[\\u200B-\\u200D\\uFEFF]/g, '')\n\t\tcleanedLicenseKey = cleanedLicenseKey.replace(/\\r?\\n|\\r/g, '')\n\n\t\ttry {\n\t\t\tconst licenseInfo = await this.extractLicenseKey(cleanedLicenseKey)\n\t\t\tconst expiryDate = new Date(licenseInfo.expiryDate)\n\t\t\tconst isAnnualLicense = this.isFlagEnabled(licenseInfo.flags, FLAGS.ANNUAL_LICENSE)\n\t\t\tconst isPerpetualLicense = this.isFlagEnabled(licenseInfo.flags, FLAGS.PERPETUAL_LICENSE)\n\t\t\tconst isEvaluationLicense = this.isFlagEnabled(licenseInfo.flags, FLAGS.EVALUATION_LICENSE)\n\n\t\t\tconst isAnnualLicenseExpired = isAnnualLicense && this.isAnnualLicenseExpired(expiryDate)\n\t\t\tconst isPerpetualLicenseExpired =\n\t\t\t\tisPerpetualLicense && this.isPerpetualLicenseExpired(expiryDate)\n\n\t\t\t// For perpetual licenses, the calendar expiry date only gates access to future\n\t\t\t// major/minor releases; it does not \"expire\" the license itself. While the user\n\t\t\t// is still on a covered version we report `daysSinceExpiry` as 0 so consumers\n\t\t\t// (and the grace-period warning) don't treat them as past expiry.\n\t\t\tconst daysSinceExpiry =\n\t\t\t\tisPerpetualLicense && !isPerpetualLicenseExpired ? 0 : this.getDaysSinceExpiry(expiryDate)\n\n\t\t\tconst result: ValidLicenseKeyResult = {\n\t\t\t\tlicense: licenseInfo,\n\t\t\t\tisLicenseParseable: true,\n\t\t\t\tisDevelopment: this.isDevelopment,\n\t\t\t\tisDomainValid: this.isDomainValid(licenseInfo),\n\t\t\t\texpiryDate,\n\t\t\t\tisAnnualLicense,\n\t\t\t\tisAnnualLicenseExpired,\n\t\t\t\tisPerpetualLicense,\n\t\t\t\tisPerpetualLicenseExpired,\n\t\t\t\tisInternalLicense: this.isFlagEnabled(licenseInfo.flags, FLAGS.INTERNAL_LICENSE),\n\t\t\t\tisNativeLicense: this.isNativeLicense(licenseInfo),\n\t\t\t\tisLicensedWithWatermark: this.isFlagEnabled(licenseInfo.flags, FLAGS.WITH_WATERMARK),\n\t\t\t\tisEvaluationLicense,\n\t\t\t\tisEvaluationLicenseExpired:\n\t\t\t\t\tisEvaluationLicense && this.isEvaluationLicenseExpired(expiryDate),\n\t\t\t\tdaysSinceExpiry,\n\t\t\t}\n\t\t\tthis.outputLicenseInfoIfNeeded(result)\n\n\t\t\treturn result\n\t\t} catch (e: any) {\n\t\t\tthis.outputInvalidLicenseKey(e.message)\n\t\t\t// If the license can't be parsed, it's invalid\n\t\t\treturn { isLicenseParseable: false, reason: 'invalid-license-key' }\n\t\t}\n\t}\n\n\tprivate isDomainValid(licenseInfo: LicenseInfo) {\n\t\tconst currentHostname = window.location.hostname.toLowerCase()\n\n\t\treturn licenseInfo.hosts.some((host) => {\n\t\t\tconst normalizedHostOrUrlRegex = host.toLowerCase().trim()\n\n\t\t\t// Allow the domain if listed and www variations, 'example.com' allows 'example.com' and 'www.example.com'\n\t\t\tif (\n\t\t\t\tnormalizedHostOrUrlRegex === currentHostname ||\n\t\t\t\t`www.${normalizedHostOrUrlRegex}` === currentHostname ||\n\t\t\t\tnormalizedHostOrUrlRegex === `www.${currentHostname}`\n\t\t\t) {\n\t\t\t\treturn true\n\t\t\t}\n\n\t\t\t// If host is '*', we allow all domains.\n\t\t\tif (host === '*') {\n\t\t\t\t// All domains allowed.\n\t\t\t\treturn true\n\t\t\t}\n\n\t\t\t// Native license support\n\t\t\t// In this case, `normalizedHost` is actually a protocol, e.g. `app-bundle:`\n\t\t\tif (this.isNativeLicense(licenseInfo)) {\n\t\t\t\treturn new RegExp(normalizedHostOrUrlRegex).test(window.location.href)\n\t\t\t}\n\n\t\t\t// Glob testing, we only support '*.somedomain.com' right now.\n\t\t\tif (host.includes('*')) {\n\t\t\t\tconst globToRegex = new RegExp(host.replace(/\\*/g, '.*?'))\n\t\t\t\treturn globToRegex.test(currentHostname) || globToRegex.test(`www.${currentHostname}`)\n\t\t\t}\n\n\t\t\t// VSCode support\n\t\t\tif (window.location.protocol === 'vscode-webview:') {\n\t\t\t\tconst currentUrl = new URL(window.location.href)\n\t\t\t\tconst extensionId = currentUrl.searchParams.get('extensionId')\n\t\t\t\tif (normalizedHostOrUrlRegex === extensionId) {\n\t\t\t\t\treturn true\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn false\n\t\t})\n\t}\n\n\tprivate isNativeLicense(licenseInfo: LicenseInfo) {\n\t\treturn this.isFlagEnabled(licenseInfo.flags, FLAGS.NATIVE_LICENSE)\n\t}\n\n\tprivate getExpirationDateWithoutGracePeriod(expiryDate: Date) {\n\t\treturn new Date(expiryDate.getFullYear(), expiryDate.getMonth(), expiryDate.getDate())\n\t}\n\n\tprivate getExpirationDateWithGracePeriod(expiryDate: Date) {\n\t\treturn new Date(\n\t\t\texpiryDate.getFullYear(),\n\t\t\texpiryDate.getMonth(),\n\t\t\texpiryDate.getDate() + GRACE_PERIOD_DAYS + 1 // Add 1 day to include the expiration day\n\t\t)\n\t}\n\n\tprivate isAnnualLicenseExpired(expiryDate: Date) {\n\t\tconst expiration = this.getExpirationDateWithGracePeriod(expiryDate)\n\t\treturn new Date() >= expiration\n\t}\n\n\tprivate isPerpetualLicenseExpired(expiryDate: Date) {\n\t\tconst expiration = this.getExpirationDateWithGracePeriod(expiryDate)\n\t\tconst dates = {\n\t\t\tmajor: new Date(publishDates.major),\n\t\t\tminor: new Date(publishDates.minor),\n\t\t}\n\t\t// We allow patch releases, but the major and minor releases should be within the expiration date\n\t\treturn dates.major >= expiration || dates.minor >= expiration\n\t}\n\n\tprivate getDaysSinceExpiry(expiryDate: Date): number {\n\t\tconst now = new Date()\n\t\tconst expiration = this.getExpirationDateWithoutGracePeriod(expiryDate)\n\t\tconst diffTime = now.getTime() - expiration.getTime()\n\t\tconst diffDays = Math.floor(diffTime / (1000 * 60 * 60 * 24))\n\t\treturn Math.max(0, diffDays)\n\t}\n\n\tprivate isEvaluationLicenseExpired(expiryDate: Date): boolean {\n\t\t// Evaluation licenses have no grace period - they expire immediately\n\t\tconst now = new Date()\n\t\tconst expiration = this.getExpirationDateWithoutGracePeriod(expiryDate)\n\t\treturn now >= expiration\n\t}\n\n\tprivate isFlagEnabled(flags: number, flag: number) {\n\t\treturn (flags & flag) === flag\n\t}\n\n\tprivate outputNoLicenseKeyProvided() {\n\t\t// Noop, we don't need to show this message.\n\t\t// this.outputMessages([\n\t\t// \t'No tldraw license key provided!',\n\t\t// \t`Please reach out to ${LICENSE_EMAIL} if you would like to license tldraw or if you'd like a trial.`,\n\t\t// ])\n\t}\n\n\tprivate outputInvalidLicenseKey(msg: string) {\n\t\tthis.outputMessages(['Invalid tldraw license key', `Reason: ${msg}`])\n\t}\n\n\tprivate outputLicenseInfoIfNeeded(result: ValidLicenseKeyResult) {\n\t\t// If we added a new flag it will be twice the value of the currently highest flag.\n\t\t// And if all the current flags are on we would get the `HIGHEST_FLAG * 2 - 1`, so anything higher than that means there are new flags.\n\t\tif (result.license.flags >= HIGHEST_FLAG * 2) {\n\t\t\tthis.outputMessages(\n\t\t\t\t[\n\t\t\t\t\t'Warning: This tldraw license contains some unknown flags.',\n\t\t\t\t\t'This will still work, however, you may want to update tldraw packages to a newer version to get access to new functionality.',\n\t\t\t\t],\n\t\t\t\t'warning'\n\t\t\t)\n\t\t}\n\t}\n\n\tprivate outputMessages(messages: string[], type: 'warning' | 'error' = 'error') {\n\t\tif (this.isTest) return\n\t\tif (this.verbose) {\n\t\t\tthis.outputDelimiter(type)\n\t\t\tfor (const message of messages) {\n\t\t\t\tconst bgColor = type === 'warning' ? 'orange' : 'crimson'\n\t\t\t\t// eslint-disable-next-line no-console\n\t\t\t\tconsole.log(\n\t\t\t\t\t`%c${message}`,\n\t\t\t\t\t`color: white; background: ${bgColor}; padding: 2px; border-radius: 3px;`\n\t\t\t\t)\n\t\t\t}\n\t\t\tthis.outputDelimiter(type)\n\t\t}\n\t}\n\n\tprivate outputDelimiter(type: 'warning' | 'error' = 'error') {\n\t\tconst bgColor = type === 'warning' ? 'orange' : 'crimson'\n\t\t// eslint-disable-next-line no-console\n\t\tconsole.log(\n\t\t\t'%c-------------------------------------------------------------------',\n\t\t\t`color: white; background: ${bgColor}; padding: 2px; border-radius: 3px;`\n\t\t)\n\t}\n\n\tstatic className = 'tl-watermark_SEE-LICENSE'\n}\n\nexport function getLicenseState(\n\tresult: LicenseFromKeyResult,\n\toutputMessages: (messages: string[]) => void,\n\tisDevelopment: boolean\n): LicenseState {\n\tif (!result.isLicenseParseable) {\n\t\tif (isDevelopment) {\n\t\t\treturn 'unlicensed'\n\t\t}\n\n\t\t// All unlicensed scenarios should not work in production\n\t\tif (result.reason === 'no-key-provided') {\n\t\t\toutputMessages([\n\t\t\t\t'No tldraw license key provided!',\n\t\t\t\t'A license is required for production deployments.',\n\t\t\t\t`Please reach out to ${LICENSE_EMAIL} to purchase a license.`,\n\t\t\t])\n\t\t} else {\n\t\t\toutputMessages([\n\t\t\t\t'Invalid license key. tldraw requires a valid license for production use.',\n\t\t\t\t`Please reach out to ${LICENSE_EMAIL} to purchase a license.`,\n\t\t\t])\n\t\t}\n\t\treturn 'unlicensed-production'\n\t}\n\n\tif (!result.isDomainValid && !result.isDevelopment) {\n\t\toutputMessages([\n\t\t\t'License key is not valid for this domain.',\n\t\t\t'A license is required for production deployments.',\n\t\t\t`Please reach out to ${LICENSE_EMAIL} to purchase a license.`,\n\t\t])\n\t\treturn 'unlicensed-production'\n\t}\n\n\t// Handle evaluation licenses - they expire immediately with no grace period\n\tif (result.isEvaluationLicense) {\n\t\tif (result.isEvaluationLicenseExpired) {\n\t\t\toutputMessages([\n\t\t\t\t'Your tldraw evaluation license has expired!',\n\t\t\t\t`Please reach out to ${LICENSE_EMAIL} to purchase a full license.`,\n\t\t\t])\n\t\t\treturn 'expired'\n\t\t} else {\n\t\t\t// Valid evaluation license - tracked but no watermark shown\n\t\t\treturn 'licensed'\n\t\t}\n\t}\n\n\t// Handle expired regular licenses (both annual and perpetual)\n\tif (result.isPerpetualLicenseExpired || result.isAnnualLicenseExpired) {\n\t\toutputMessages([\n\t\t\t'Your tldraw license has been expired for more than 30 days!',\n\t\t\t`Please reach out to ${LICENSE_EMAIL} to renew your license.`,\n\t\t])\n\t\treturn 'expired'\n\t}\n\n\t// Check if license is past expiry date but within grace period\n\tconst daysSinceExpiry = result.daysSinceExpiry\n\tif (daysSinceExpiry > 0 && !result.isEvaluationLicense) {\n\t\toutputMessages([\n\t\t\t'Your tldraw license has expired.',\n\t\t\t`License expired ${daysSinceExpiry} days ago.`,\n\t\t\t`Please reach out to ${LICENSE_EMAIL} to renew your license.`,\n\t\t])\n\t\t// Within 30-day grace period: still licensed (no watermark)\n\t\treturn 'licensed'\n\t}\n\n\t// License is valid, determine if it has watermark\n\tif (result.isLicensedWithWatermark) {\n\t\treturn 'licensed-with-watermark'\n\t}\n\n\treturn 'licensed'\n}\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["import { atom } from '@tldraw/state'\nimport { publishDates, version } from '../../version'\nimport { getDefaultCdnBaseUrl } from '../utils/assets'\nimport { importPublicKey, str2ab } from '../utils/licensing'\n\nconst GRACE_PERIOD_DAYS = 30\n\nexport const FLAGS = {\n\t// -- MUTUALLY EXCLUSIVE FLAGS\n\t// Annual means the license expires after a time period, usually 1 year.\n\tANNUAL_LICENSE: 1,\n\t// Perpetual means the license never expires up to the max supported version.\n\tPERPETUAL_LICENSE: 1 << 1,\n\n\t// -- ADDITIVE FLAGS --\n\t// Internal means the license is for internal use only.\n\tINTERNAL_LICENSE: 1 << 2,\n\t// Watermark means the product is watermarked.\n\tWITH_WATERMARK: 1 << 3,\n\t// Evaluation means the license is for evaluation purposes only.\n\tEVALUATION_LICENSE: 1 << 4,\n\t// Native means the license is for native apps which switches\n\t// on special-case logic.\n\tNATIVE_LICENSE: 1 << 5,\n}\nconst HIGHEST_FLAG = Math.max(...Object.values(FLAGS))\n\nexport const PROPERTIES = {\n\tID: 0,\n\tHOSTS: 1,\n\tFLAGS: 2,\n\tEXPIRY_DATE: 3,\n}\nconst NUMBER_OF_KNOWN_PROPERTIES = Object.keys(PROPERTIES).length\n\nconst LICENSE_EMAIL = 'sales@tldraw.com'\n\nconst WATERMARK_TRACK_SRC = `${getDefaultCdnBaseUrl()}/watermarks/watermark-track.svg`\n\n/** @internal */\nexport interface LicenseInfo {\n\tid: string\n\thosts: string[]\n\tflags: number\n\texpiryDate: string\n}\n\n/** @internal */\nexport type LicenseState =\n\t| 'pending' // License validation is in progress\n\t| 'licensed' // License is valid and active (no restrictions)\n\t| 'licensed-with-watermark' // License is valid but shows watermark (evaluation licenses, WITH_WATERMARK licenses)\n\t| 'unlicensed' // No valid license found or license is invalid (development)\n\t| 'unlicensed-production' // No valid license in production deployment (missing, invalid, or wrong domain)\n\t| 'expired' // License has been expired (30 days past expiration for regular licenses, immediately for evaluation licenses)\n/** @internal */\nexport type InvalidLicenseReason =\n\t| 'invalid-license-key'\n\t| 'no-key-provided'\n\t| 'has-key-development-mode'\n\n/** @internal */\nexport type LicenseFromKeyResult = InvalidLicenseKeyResult | ValidLicenseKeyResult\n\n/** @internal */\nexport interface InvalidLicenseKeyResult {\n\tisLicenseParseable: false\n\treason: InvalidLicenseReason\n}\n\n/** @internal */\nexport interface ValidLicenseKeyResult {\n\tisLicenseParseable: true\n\tlicense: LicenseInfo\n\tisDevelopment: boolean\n\tisDomainValid: boolean\n\texpiryDate: Date\n\tisAnnualLicense: boolean\n\tisAnnualLicenseExpired: boolean\n\tisPerpetualLicense: boolean\n\tisPerpetualLicenseExpired: boolean\n\tisInternalLicense: boolean\n\tisNativeLicense: boolean\n\tisLicensedWithWatermark: boolean\n\tisEvaluationLicense: boolean\n\tisEvaluationLicenseExpired: boolean\n\tdaysSinceExpiry: number\n}\n\n/** @internal */\nexport type TrackType = 'unlicensed' | 'with_watermark' | 'evaluation' | null\n\n/** @internal */\nexport class LicenseManager {\n\tprivate publicKey =\n\t\t'MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEHJh0uUfxHtCGyerXmmatE368Hd9rI6LH9oPDQihnaCryRFWEVeOvf9U/SPbyxX74LFyJs5tYeAHq5Nc0Ax25LQ'\n\tpublic isDevelopment: boolean\n\tpublic isTest: boolean\n\tpublic isCryptoAvailable: boolean\n\tstate = atom<LicenseState>('license state', 'pending')\n\tpublic verbose = true\n\n\tconstructor(licenseKey: string | undefined, testPublicKey?: string) {\n\t\tthis.isTest = process.env.NODE_ENV === 'test'\n\t\tthis.isDevelopment = this.getIsDevelopment()\n\t\tthis.publicKey = testPublicKey || this.publicKey\n\t\tthis.isCryptoAvailable = !!crypto.subtle\n\n\t\tthis.getLicenseFromKey(licenseKey)\n\t\t\t.then((result) => {\n\t\t\t\tconst licenseState = getLicenseState(\n\t\t\t\t\tresult,\n\t\t\t\t\t(messages: string[]) => this.outputMessages(messages),\n\t\t\t\t\tthis.isDevelopment\n\t\t\t\t)\n\n\t\t\t\tthis.maybeTrack(result, licenseState)\n\n\t\t\t\tthis.state.set(licenseState)\n\t\t\t})\n\t\t\t.catch((error) => {\n\t\t\t\tconsole.error('License validation failed:', error)\n\t\t\t\tthis.state.set('unlicensed')\n\t\t\t})\n\t}\n\n\tprivate getIsDevelopment() {\n\t\t// If we are using https on a non-loopback domain we assume it's a production env and a development one otherwise\n\t\treturn (\n\t\t\t!['https:', 'vscode-webview:'].includes(window.location.protocol) ||\n\t\t\tthis.isLoopbackHost(window.location.hostname) ||\n\t\t\tprocess.env.NODE_ENV !== 'production'\n\t\t)\n\t}\n\n\tprivate isLoopbackHost(hostname: string) {\n\t\t// localhost, IPv4 loopback (127.0.0.0/8) and IPv6 loopback (::1) are all local development hosts\n\t\tconst host = hostname.toLowerCase().replace(/^\\[|\\]$/g, '')\n\t\treturn host === 'localhost' || host === '::1' || /^127(?:\\.\\d{1,3}){3}$/.test(host)\n\t}\n\n\tprivate getTrackType(result: LicenseFromKeyResult, licenseState: LicenseState): TrackType {\n\t\t// Track watermark for unlicensed production deployments\n\t\tif (licenseState === 'unlicensed-production') {\n\t\t\treturn 'unlicensed'\n\t\t}\n\n\t\tif (this.isDevelopment) {\n\t\t\treturn null\n\t\t}\n\n\t\tif (!result.isLicenseParseable) {\n\t\t\treturn null\n\t\t}\n\n\t\t// Track evaluation licenses (for analytics, even though no watermark is shown)\n\t\tif (result.isEvaluationLicense) {\n\t\t\treturn 'evaluation'\n\t\t}\n\n\t\t// Track licenses that show watermarks\n\t\tif (licenseState === 'licensed-with-watermark') {\n\t\t\treturn 'with_watermark'\n\t\t}\n\n\t\treturn null\n\t}\n\n\tprivate maybeTrack(result: LicenseFromKeyResult, licenseState: LicenseState): void {\n\t\tconst trackType = this.getTrackType(result, licenseState)\n\t\tif (!trackType) {\n\t\t\treturn\n\t\t}\n\n\t\tconst url = new URL(WATERMARK_TRACK_SRC)\n\t\turl.searchParams.set('version', version)\n\t\turl.searchParams.set('license_type', trackType)\n\t\tif ('license' in result) {\n\t\t\turl.searchParams.set('license_id', result.license.id)\n\t\t\tconst sku = this.isFlagEnabled(result.license.flags, FLAGS.EVALUATION_LICENSE)\n\t\t\t\t? 'evaluation'\n\t\t\t\t: this.isFlagEnabled(result.license.flags, FLAGS.ANNUAL_LICENSE)\n\t\t\t\t\t? 'annual'\n\t\t\t\t\t: this.isFlagEnabled(result.license.flags, FLAGS.PERPETUAL_LICENSE)\n\t\t\t\t\t\t? 'perpetual'\n\t\t\t\t\t\t: 'unknown'\n\t\t\turl.searchParams.set('sku', sku)\n\t\t}\n\t\turl.searchParams.set('url', window.location.href)\n\t\tif (process.env.NODE_ENV) {\n\t\t\turl.searchParams.set('environment', process.env.NODE_ENV)\n\t\t}\n\n\t\t// eslint-disable-next-line no-restricted-globals\n\t\tfetch(url.toString())\n\t}\n\n\tprivate async extractLicenseKey(licenseKey: string): Promise<LicenseInfo> {\n\t\tconst [data, signature] = licenseKey.split('.')\n\t\tconst [prefix, encodedData] = data.split('/')\n\n\t\tif (!prefix.startsWith('tldraw-')) {\n\t\t\tthrow new Error(`Unsupported prefix '${prefix}'`)\n\t\t}\n\n\t\tconst publicCryptoKey = await importPublicKey(this.publicKey)\n\n\t\tlet isVerified\n\t\ttry {\n\t\t\tisVerified = await crypto.subtle.verify(\n\t\t\t\t{\n\t\t\t\t\tname: 'ECDSA',\n\t\t\t\t\thash: { name: 'SHA-256' },\n\t\t\t\t},\n\t\t\t\tpublicCryptoKey,\n\t\t\t\tnew Uint8Array(str2ab(atob(signature))),\n\t\t\t\tnew Uint8Array(str2ab(atob(encodedData)))\n\t\t\t)\n\t\t} catch (e) {\n\t\t\tconsole.error(e)\n\t\t\tthrow new Error('Could not perform signature validation')\n\t\t}\n\n\t\tif (!isVerified) {\n\t\t\tthrow new Error('Invalid signature')\n\t\t}\n\n\t\tlet decodedData: any\n\t\ttry {\n\t\t\tdecodedData = JSON.parse(atob(encodedData))\n\t\t} catch {\n\t\t\tthrow new Error('Could not parse object')\n\t\t}\n\t\tif (decodedData.length > NUMBER_OF_KNOWN_PROPERTIES) {\n\t\t\tthis.outputMessages([\n\t\t\t\t'License key contains some unknown properties.',\n\t\t\t\t'You may want to update tldraw packages to a newer version to get access to new functionality.',\n\t\t\t])\n\t\t}\n\n\t\treturn {\n\t\t\tid: decodedData[PROPERTIES.ID],\n\t\t\thosts: decodedData[PROPERTIES.HOSTS],\n\t\t\tflags: decodedData[PROPERTIES.FLAGS],\n\t\t\texpiryDate: decodedData[PROPERTIES.EXPIRY_DATE],\n\t\t}\n\t}\n\n\tasync getLicenseFromKey(licenseKey?: string): Promise<LicenseFromKeyResult> {\n\t\tif (!licenseKey) {\n\t\t\tif (!this.isDevelopment) {\n\t\t\t\tthis.outputNoLicenseKeyProvided()\n\t\t\t}\n\n\t\t\treturn { isLicenseParseable: false, reason: 'no-key-provided' }\n\t\t}\n\n\t\tif (this.isDevelopment && !this.isCryptoAvailable) {\n\t\t\tif (this.verbose) {\n\t\t\t\t// eslint-disable-next-line no-console\n\t\t\t\tconsole.log(\n\t\t\t\t\t'tldraw: you seem to be in a development environment that does not support crypto. License not verified.'\n\t\t\t\t)\n\t\t\t\t// eslint-disable-next-line no-console\n\t\t\t\tconsole.log('You should check that this works in production separately.')\n\t\t\t}\n\t\t\t// We can't parse the license if we are in development mode since crypto\n\t\t\t// is not available on http\n\t\t\treturn { isLicenseParseable: false, reason: 'has-key-development-mode' }\n\t\t}\n\n\t\t// Borrowed idea from AG Grid:\n\t\t// Copying from various sources (like PDFs) can include zero-width characters.\n\t\t// This helps makes sure the key validation doesn't fail.\n\t\tlet cleanedLicenseKey = licenseKey.replace(/[\\u200B-\\u200D\\uFEFF]/g, '')\n\t\tcleanedLicenseKey = cleanedLicenseKey.replace(/\\r?\\n|\\r/g, '')\n\n\t\ttry {\n\t\t\tconst licenseInfo = await this.extractLicenseKey(cleanedLicenseKey)\n\t\t\tconst expiryDate = new Date(licenseInfo.expiryDate)\n\t\t\tconst isAnnualLicense = this.isFlagEnabled(licenseInfo.flags, FLAGS.ANNUAL_LICENSE)\n\t\t\tconst isPerpetualLicense = this.isFlagEnabled(licenseInfo.flags, FLAGS.PERPETUAL_LICENSE)\n\t\t\tconst isEvaluationLicense = this.isFlagEnabled(licenseInfo.flags, FLAGS.EVALUATION_LICENSE)\n\n\t\t\tconst isAnnualLicenseExpired = isAnnualLicense && this.isAnnualLicenseExpired(expiryDate)\n\t\t\tconst isPerpetualLicenseExpired =\n\t\t\t\tisPerpetualLicense && this.isPerpetualLicenseExpired(expiryDate)\n\n\t\t\t// For perpetual licenses, the calendar expiry date only gates access to future\n\t\t\t// major/minor releases; it does not \"expire\" the license itself. While the user\n\t\t\t// is still on a covered version we report `daysSinceExpiry` as 0 so consumers\n\t\t\t// (and the grace-period warning) don't treat them as past expiry.\n\t\t\tconst daysSinceExpiry =\n\t\t\t\tisPerpetualLicense && !isPerpetualLicenseExpired ? 0 : this.getDaysSinceExpiry(expiryDate)\n\n\t\t\tconst result: ValidLicenseKeyResult = {\n\t\t\t\tlicense: licenseInfo,\n\t\t\t\tisLicenseParseable: true,\n\t\t\t\tisDevelopment: this.isDevelopment,\n\t\t\t\tisDomainValid: this.isDomainValid(licenseInfo),\n\t\t\t\texpiryDate,\n\t\t\t\tisAnnualLicense,\n\t\t\t\tisAnnualLicenseExpired,\n\t\t\t\tisPerpetualLicense,\n\t\t\t\tisPerpetualLicenseExpired,\n\t\t\t\tisInternalLicense: this.isFlagEnabled(licenseInfo.flags, FLAGS.INTERNAL_LICENSE),\n\t\t\t\tisNativeLicense: this.isNativeLicense(licenseInfo),\n\t\t\t\tisLicensedWithWatermark: this.isFlagEnabled(licenseInfo.flags, FLAGS.WITH_WATERMARK),\n\t\t\t\tisEvaluationLicense,\n\t\t\t\tisEvaluationLicenseExpired:\n\t\t\t\t\tisEvaluationLicense && this.isEvaluationLicenseExpired(expiryDate),\n\t\t\t\tdaysSinceExpiry,\n\t\t\t}\n\t\t\tthis.outputLicenseInfoIfNeeded(result)\n\n\t\t\treturn result\n\t\t} catch (e: any) {\n\t\t\tthis.outputInvalidLicenseKey(e.message)\n\t\t\t// If the license can't be parsed, it's invalid\n\t\t\treturn { isLicenseParseable: false, reason: 'invalid-license-key' }\n\t\t}\n\t}\n\n\tprivate isDomainValid(licenseInfo: LicenseInfo) {\n\t\tconst currentHostname = window.location.hostname.toLowerCase()\n\n\t\treturn licenseInfo.hosts.some((host) => {\n\t\t\tconst normalizedHostOrUrlRegex = host.toLowerCase().trim()\n\n\t\t\t// Allow the domain if listed and www variations, 'example.com' allows 'example.com' and 'www.example.com'\n\t\t\tif (\n\t\t\t\tnormalizedHostOrUrlRegex === currentHostname ||\n\t\t\t\t`www.${normalizedHostOrUrlRegex}` === currentHostname ||\n\t\t\t\tnormalizedHostOrUrlRegex === `www.${currentHostname}`\n\t\t\t) {\n\t\t\t\treturn true\n\t\t\t}\n\n\t\t\t// If host is '*', we allow all domains.\n\t\t\tif (host === '*') {\n\t\t\t\t// All domains allowed.\n\t\t\t\treturn true\n\t\t\t}\n\n\t\t\t// Native license support\n\t\t\t// In this case, `normalizedHost` is actually a protocol, e.g. `app-bundle:`\n\t\t\tif (this.isNativeLicense(licenseInfo)) {\n\t\t\t\treturn new RegExp(normalizedHostOrUrlRegex).test(window.location.href)\n\t\t\t}\n\n\t\t\t// Glob testing, we only support '*.somedomain.com' right now.\n\t\t\tif (host.includes('*')) {\n\t\t\t\tconst globToRegex = new RegExp(host.replace(/\\*/g, '.*?'))\n\t\t\t\treturn globToRegex.test(currentHostname) || globToRegex.test(`www.${currentHostname}`)\n\t\t\t}\n\n\t\t\t// VSCode support\n\t\t\tif (window.location.protocol === 'vscode-webview:') {\n\t\t\t\tconst currentUrl = new URL(window.location.href)\n\t\t\t\tconst extensionId = currentUrl.searchParams.get('extensionId')\n\t\t\t\tif (normalizedHostOrUrlRegex === extensionId) {\n\t\t\t\t\treturn true\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn false\n\t\t})\n\t}\n\n\tprivate isNativeLicense(licenseInfo: LicenseInfo) {\n\t\treturn this.isFlagEnabled(licenseInfo.flags, FLAGS.NATIVE_LICENSE)\n\t}\n\n\tprivate getExpirationDateWithoutGracePeriod(expiryDate: Date) {\n\t\treturn new Date(expiryDate.getFullYear(), expiryDate.getMonth(), expiryDate.getDate())\n\t}\n\n\tprivate getExpirationDateWithGracePeriod(expiryDate: Date) {\n\t\treturn new Date(\n\t\t\texpiryDate.getFullYear(),\n\t\t\texpiryDate.getMonth(),\n\t\t\texpiryDate.getDate() + GRACE_PERIOD_DAYS + 1 // Add 1 day to include the expiration day\n\t\t)\n\t}\n\n\tprivate isAnnualLicenseExpired(expiryDate: Date) {\n\t\tconst expiration = this.getExpirationDateWithGracePeriod(expiryDate)\n\t\treturn new Date() >= expiration\n\t}\n\n\tprivate isPerpetualLicenseExpired(expiryDate: Date) {\n\t\tconst expiration = this.getExpirationDateWithGracePeriod(expiryDate)\n\t\tconst dates = {\n\t\t\tmajor: new Date(publishDates.major),\n\t\t\tminor: new Date(publishDates.minor),\n\t\t}\n\t\t// We allow patch releases, but the major and minor releases should be within the expiration date\n\t\treturn dates.major >= expiration || dates.minor >= expiration\n\t}\n\n\tprivate getDaysSinceExpiry(expiryDate: Date): number {\n\t\tconst now = new Date()\n\t\tconst expiration = this.getExpirationDateWithoutGracePeriod(expiryDate)\n\t\tconst diffTime = now.getTime() - expiration.getTime()\n\t\tconst diffDays = Math.floor(diffTime / (1000 * 60 * 60 * 24))\n\t\treturn Math.max(0, diffDays)\n\t}\n\n\tprivate isEvaluationLicenseExpired(expiryDate: Date): boolean {\n\t\t// Evaluation licenses have no grace period - they expire immediately\n\t\tconst now = new Date()\n\t\tconst expiration = this.getExpirationDateWithoutGracePeriod(expiryDate)\n\t\treturn now >= expiration\n\t}\n\n\tprivate isFlagEnabled(flags: number, flag: number) {\n\t\treturn (flags & flag) === flag\n\t}\n\n\tprivate outputNoLicenseKeyProvided() {\n\t\t// Noop, we don't need to show this message.\n\t\t// this.outputMessages([\n\t\t// \t'No tldraw license key provided!',\n\t\t// \t`Please reach out to ${LICENSE_EMAIL} if you would like to license tldraw or if you'd like a trial.`,\n\t\t// ])\n\t}\n\n\tprivate outputInvalidLicenseKey(msg: string) {\n\t\tthis.outputMessages(['Invalid tldraw license key', `Reason: ${msg}`])\n\t}\n\n\tprivate outputLicenseInfoIfNeeded(result: ValidLicenseKeyResult) {\n\t\t// If we added a new flag it will be twice the value of the currently highest flag.\n\t\t// And if all the current flags are on we would get the `HIGHEST_FLAG * 2 - 1`, so anything higher than that means there are new flags.\n\t\tif (result.license.flags >= HIGHEST_FLAG * 2) {\n\t\t\tthis.outputMessages(\n\t\t\t\t[\n\t\t\t\t\t'Warning: This tldraw license contains some unknown flags.',\n\t\t\t\t\t'This will still work, however, you may want to update tldraw packages to a newer version to get access to new functionality.',\n\t\t\t\t],\n\t\t\t\t'warning'\n\t\t\t)\n\t\t}\n\t}\n\n\tprivate outputMessages(messages: string[], type: 'warning' | 'error' = 'error') {\n\t\tif (this.isTest) return\n\t\tif (this.verbose) {\n\t\t\tthis.outputDelimiter(type)\n\t\t\tfor (const message of messages) {\n\t\t\t\tconst bgColor = type === 'warning' ? 'orange' : 'crimson'\n\t\t\t\t// eslint-disable-next-line no-console\n\t\t\t\tconsole.log(\n\t\t\t\t\t`%c${message}`,\n\t\t\t\t\t`color: white; background: ${bgColor}; padding: 2px; border-radius: 3px;`\n\t\t\t\t)\n\t\t\t}\n\t\t\tthis.outputDelimiter(type)\n\t\t}\n\t}\n\n\tprivate outputDelimiter(type: 'warning' | 'error' = 'error') {\n\t\tconst bgColor = type === 'warning' ? 'orange' : 'crimson'\n\t\t// eslint-disable-next-line no-console\n\t\tconsole.log(\n\t\t\t'%c-------------------------------------------------------------------',\n\t\t\t`color: white; background: ${bgColor}; padding: 2px; border-radius: 3px;`\n\t\t)\n\t}\n\n\tstatic className = 'tl-watermark_SEE-LICENSE'\n}\n\nexport function getLicenseState(\n\tresult: LicenseFromKeyResult,\n\toutputMessages: (messages: string[]) => void,\n\tisDevelopment: boolean\n): LicenseState {\n\tif (!result.isLicenseParseable) {\n\t\tif (isDevelopment) {\n\t\t\treturn 'unlicensed'\n\t\t}\n\n\t\t// All unlicensed scenarios should not work in production\n\t\tif (result.reason === 'no-key-provided') {\n\t\t\toutputMessages([\n\t\t\t\t'No tldraw license key provided!',\n\t\t\t\t'A license is required for production deployments.',\n\t\t\t\t`Please reach out to ${LICENSE_EMAIL} to purchase a license.`,\n\t\t\t])\n\t\t} else {\n\t\t\toutputMessages([\n\t\t\t\t'Invalid license key. tldraw requires a valid license for production use.',\n\t\t\t\t`Please reach out to ${LICENSE_EMAIL} to purchase a license.`,\n\t\t\t])\n\t\t}\n\t\treturn 'unlicensed-production'\n\t}\n\n\tif (!result.isDomainValid && !result.isDevelopment) {\n\t\toutputMessages([\n\t\t\t'License key is not valid for this domain.',\n\t\t\t'A license is required for production deployments.',\n\t\t\t`Please reach out to ${LICENSE_EMAIL} to purchase a license.`,\n\t\t])\n\t\treturn 'unlicensed-production'\n\t}\n\n\t// Handle evaluation licenses - they expire immediately with no grace period\n\tif (result.isEvaluationLicense) {\n\t\tif (result.isEvaluationLicenseExpired) {\n\t\t\toutputMessages([\n\t\t\t\t'Your tldraw evaluation license has expired!',\n\t\t\t\t`Please reach out to ${LICENSE_EMAIL} to purchase a full license.`,\n\t\t\t])\n\t\t\treturn 'expired'\n\t\t} else {\n\t\t\t// Valid evaluation license - tracked but no watermark shown\n\t\t\treturn 'licensed'\n\t\t}\n\t}\n\n\t// Handle expired regular licenses (both annual and perpetual)\n\tif (result.isPerpetualLicenseExpired || result.isAnnualLicenseExpired) {\n\t\toutputMessages([\n\t\t\t'Your tldraw license has been expired for more than 30 days!',\n\t\t\t`Please reach out to ${LICENSE_EMAIL} to renew your license.`,\n\t\t])\n\t\treturn 'expired'\n\t}\n\n\t// Check if license is past expiry date but within grace period\n\tconst daysSinceExpiry = result.daysSinceExpiry\n\tif (daysSinceExpiry > 0 && !result.isEvaluationLicense) {\n\t\toutputMessages([\n\t\t\t'Your tldraw license has expired.',\n\t\t\t`License expired ${daysSinceExpiry} days ago.`,\n\t\t\t`Please reach out to ${LICENSE_EMAIL} to renew your license.`,\n\t\t])\n\t\t// Within 30-day grace period: still licensed (no watermark)\n\t\treturn 'licensed'\n\t}\n\n\t// License is valid, determine if it has watermark\n\tif (result.isLicensedWithWatermark) {\n\t\treturn 'licensed-with-watermark'\n\t}\n\n\treturn 'licensed'\n}\n"],
5
+ "mappings": "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",
6
6
  "names": []
7
7
  }
@@ -1,4 +1,5 @@
1
1
  import { EASINGS } from "./easings.mjs";
2
+ const { easeInQuad, easeInOutQuad } = EASINGS;
2
3
  function clamp(n, min, max) {
3
4
  return Math.max(min, typeof max !== "undefined" ? Math.min(n, max) : n);
4
5
  }
@@ -497,12 +498,12 @@ class Vec {
497
498
  * @param steps - The number of points to return.
498
499
  * @param ease - The easing to use.
499
500
  */
500
- static PointsBetween(A, B, steps = 6, ease = EASINGS.easeInQuad) {
501
+ static PointsBetween(A, B, steps = 6, ease = easeInQuad) {
501
502
  const results = [];
502
503
  for (let i = 0; i < steps; i++) {
503
504
  const t = ease(i / (steps - 1));
504
505
  const point = Vec.Lrp(A, B, t);
505
- point.z = Math.min(1, 0.5 + Math.abs(0.5 - EASINGS.easeInOutQuad(t)) * 0.65);
506
+ point.z = Math.min(1, 0.5 + Math.abs(0.5 - easeInOutQuad(t)) * 0.65);
506
507
  results.push(point);
507
508
  }
508
509
  return results;
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../src/lib/primitives/Vec.ts"],
4
- "sourcesContent": ["import { VecModel } from '@tldraw/tlschema'\nimport { EASINGS } from './easings'\nfunction clamp(n: number, min: number, max?: number): number {\n\treturn Math.max(min, typeof max !== 'undefined' ? Math.min(n, max) : n)\n}\n\nfunction toFixed(v: number) {\n\treturn Math.round(v * 1e2) / 1e2\n}\n\n/** @public */\nexport type VecLike = Vec | VecModel\n\n/** @public */\nexport class Vec {\n\tconstructor(\n\t\tpublic x = 0,\n\t\tpublic y = 0,\n\t\tpublic z = 1\n\t) {}\n\n\t// eslint-disable-next-line tldraw/no-setter-getter\n\tget pressure() {\n\t\treturn this.z\n\t}\n\n\tset(x = this.x, y = this.y, z = this.z) {\n\t\tthis.x = x\n\t\tthis.y = y\n\t\tthis.z = z\n\t\treturn this\n\t}\n\n\tsetTo({ x = 0, y = 0, z = 1 }: VecLike) {\n\t\tthis.x = x\n\t\tthis.y = y\n\t\tthis.z = z\n\t\treturn this\n\t}\n\n\trot(r: number) {\n\t\tif (r === 0) return this\n\t\tconst { x, y } = this\n\t\tconst s = Math.sin(r)\n\t\tconst c = Math.cos(r)\n\t\tthis.x = x * c - y * s\n\t\tthis.y = x * s + y * c\n\t\treturn this\n\t}\n\n\trotWith(C: VecLike, r: number) {\n\t\tif (r === 0) return this\n\t\tconst x = this.x - C.x\n\t\tconst y = this.y - C.y\n\t\tconst s = Math.sin(r)\n\t\tconst c = Math.cos(r)\n\t\tthis.x = C.x + (x * c - y * s)\n\t\tthis.y = C.y + (x * s + y * c)\n\t\treturn this\n\t}\n\n\tclone(): Vec {\n\t\tconst { x, y, z } = this\n\t\treturn new Vec(x, y, z)\n\t}\n\n\tsub(V: VecLike) {\n\t\tthis.x -= V.x\n\t\tthis.y -= V.y\n\t\treturn this\n\t}\n\n\tsubXY(x: number, y: number) {\n\t\tthis.x -= x\n\t\tthis.y -= y\n\t\treturn this\n\t}\n\n\tsubScalar(n: number) {\n\t\tthis.x -= n\n\t\tthis.y -= n\n\t\t// this.z -= n\n\n\t\treturn this\n\t}\n\n\tadd(V: VecLike) {\n\t\tthis.x += V.x\n\t\tthis.y += V.y\n\t\treturn this\n\t}\n\n\taddXY(x: number, y: number) {\n\t\tthis.x += x\n\t\tthis.y += y\n\t\treturn this\n\t}\n\n\taddScalar(n: number) {\n\t\tthis.x += n\n\t\tthis.y += n\n\t\t// this.z += n\n\n\t\treturn this\n\t}\n\n\tclamp(min: number, max?: number) {\n\t\tthis.x = Math.max(this.x, min)\n\t\tthis.y = Math.max(this.y, min)\n\t\tif (max !== undefined) {\n\t\t\tthis.x = Math.min(this.x, max)\n\t\t\tthis.y = Math.min(this.y, max)\n\t\t}\n\t\treturn this\n\t}\n\n\tdiv(t: number) {\n\t\tthis.x /= t\n\t\tthis.y /= t\n\t\t// this.z /= t\n\t\treturn this\n\t}\n\n\tdivV(V: VecLike) {\n\t\tthis.x /= V.x\n\t\tthis.y /= V.y\n\t\t// this.z /= V.z\n\t\treturn this\n\t}\n\n\tmul(t: number) {\n\t\tthis.x *= t\n\t\tthis.y *= t\n\t\t// this.z *= t\n\t\treturn this\n\t}\n\n\tmulV(V: VecLike) {\n\t\tthis.x *= V.x\n\t\tthis.y *= V.y\n\t\t// this.z *= V.z\n\t\treturn this\n\t}\n\n\tabs() {\n\t\tthis.x = Math.abs(this.x)\n\t\tthis.y = Math.abs(this.y)\n\t\treturn this\n\t}\n\n\tnudge(B: VecLike, distance: number) {\n\t\tconst tan = Vec.Tan(B, this)\n\t\treturn this.add(tan.mul(distance))\n\t}\n\n\tneg() {\n\t\tthis.x *= -1\n\t\tthis.y *= -1\n\t\t// this.z *= -1\n\t\treturn this\n\t}\n\n\tcross(V: VecLike) {\n\t\tthis.x = this.y * V.z! - this.z * V.y\n\t\tthis.y = this.z * V.x - this.x * V.z!\n\t\t// this.z = this.x * V.y - this.y * V.x\n\t\treturn this\n\t}\n\n\tdpr(V: VecLike): number {\n\t\treturn Vec.Dpr(this, V)\n\t}\n\n\tcpr(V: VecLike) {\n\t\treturn Vec.Cpr(this, V)\n\t}\n\n\tlen2(): number {\n\t\treturn Vec.Len2(this)\n\t}\n\n\tlen(): number {\n\t\treturn Vec.Len(this)\n\t}\n\n\tpry(V: VecLike): number {\n\t\treturn Vec.Pry(this, V)\n\t}\n\n\tper() {\n\t\tconst { x, y } = this\n\t\tthis.x = y\n\t\tthis.y = -x\n\t\treturn this\n\t}\n\n\tuni() {\n\t\tconst l = this.len()\n\t\tif (l === 0) return this\n\t\tthis.x /= l\n\t\tthis.y /= l\n\t\treturn this\n\t}\n\n\ttan(V: VecLike): Vec {\n\t\treturn this.sub(V).uni()\n\t}\n\n\tdist(V: VecLike): number {\n\t\treturn Vec.Dist(this, V)\n\t}\n\n\tdistanceToLineSegment(A: VecLike, B: VecLike): number {\n\t\treturn Vec.DistanceToLineSegment(A, B, this)\n\t}\n\n\tslope(B: VecLike): number {\n\t\treturn Vec.Slope(this, B)\n\t}\n\n\tsnapToGrid(gridSize: number) {\n\t\tthis.x = Math.round(this.x / gridSize) * gridSize\n\t\tthis.y = Math.round(this.y / gridSize) * gridSize\n\t\treturn this\n\t}\n\n\tangle(B: VecLike): number {\n\t\treturn Vec.Angle(this, B)\n\t}\n\n\ttoAngle() {\n\t\treturn Vec.ToAngle(this)\n\t}\n\n\tlrp(B: VecLike, t: number): Vec {\n\t\tthis.x = this.x + (B.x - this.x) * t\n\t\tthis.y = this.y + (B.y - this.y) * t\n\t\treturn this\n\t}\n\n\tequals(B: VecLike) {\n\t\treturn Vec.Equals(this, B)\n\t}\n\n\tequalsXY(x: number, y: number) {\n\t\treturn Vec.EqualsXY(this, x, y)\n\t}\n\n\ttoFixed() {\n\t\tthis.x = toFixed(this.x)\n\t\tthis.y = toFixed(this.y)\n\t\treturn this\n\t}\n\n\ttoString() {\n\t\treturn Vec.ToString(Vec.ToFixed(this))\n\t}\n\n\ttoJson(): VecModel {\n\t\treturn Vec.ToJson(this)\n\t}\n\n\ttoArray(): number[] {\n\t\treturn Vec.ToArray(this)\n\t}\n\n\tstatic Add(A: VecLike, B: VecLike): Vec {\n\t\treturn new Vec(A.x + B.x, A.y + B.y)\n\t}\n\n\tstatic AddXY(A: VecLike, x: number, y: number): Vec {\n\t\treturn new Vec(A.x + x, A.y + y)\n\t}\n\n\tstatic Sub(A: VecLike, B: VecLike): Vec {\n\t\treturn new Vec(A.x - B.x, A.y - B.y)\n\t}\n\n\tstatic SubXY(A: VecLike, x: number, y: number): Vec {\n\t\treturn new Vec(A.x - x, A.y - y)\n\t}\n\n\tstatic AddScalar(A: VecLike, n: number): Vec {\n\t\treturn new Vec(A.x + n, A.y + n)\n\t}\n\n\tstatic SubScalar(A: VecLike, n: number): Vec {\n\t\treturn new Vec(A.x - n, A.y - n)\n\t}\n\n\tstatic Div(A: VecLike, t: number): Vec {\n\t\treturn new Vec(A.x / t, A.y / t)\n\t}\n\n\tstatic Mul(A: VecLike, t: number): Vec {\n\t\treturn new Vec(A.x * t, A.y * t)\n\t}\n\n\tstatic DivV(A: VecLike, B: VecLike): Vec {\n\t\treturn new Vec(A.x / B.x, A.y / B.y)\n\t}\n\n\tstatic MulV(A: VecLike, B: VecLike): Vec {\n\t\treturn new Vec(A.x * B.x, A.y * B.y)\n\t}\n\n\tstatic Neg(A: VecLike): Vec {\n\t\treturn new Vec(-A.x, -A.y)\n\t}\n\n\t/**\n\t * Get the perpendicular vector to A.\n\t */\n\tstatic Per(A: VecLike): Vec {\n\t\treturn new Vec(A.y, -A.x)\n\t}\n\n\tstatic Abs(A: VecLike): Vec {\n\t\treturn new Vec(Math.abs(A.x), Math.abs(A.y))\n\t}\n\n\t// Get the distance between two points.\n\tstatic Dist(A: VecLike, B: VecLike): number {\n\t\treturn ((A.y - B.y) ** 2 + (A.x - B.x) ** 2) ** 0.5\n\t}\n\n\t// Get the Manhattan distance between two points.\n\tstatic ManhattanDist(A: VecLike, B: VecLike): number {\n\t\treturn Math.abs(A.x - B.x) + Math.abs(A.y - B.y)\n\t}\n\n\t// Get whether a distance between two points is less than a number. This is faster to calulate than using `Vec.Dist(a, b) < n`.\n\tstatic DistMin(A: VecLike, B: VecLike, n: number): boolean {\n\t\treturn (A.x - B.x) * (A.x - B.x) + (A.y - B.y) * (A.y - B.y) < n ** 2\n\t}\n\n\t// Get the squared distance between two points. This is faster to calculate (no square root) so useful for \"minimum distance\" checks where the actual measurement does not matter.\n\tstatic Dist2(A: VecLike, B: VecLike): number {\n\t\treturn (A.x - B.x) * (A.x - B.x) + (A.y - B.y) * (A.y - B.y)\n\t}\n\n\t/**\n\t * Dot product of two vectors which is used to calculate the angle between them.\n\t */\n\tstatic Dpr(A: VecLike, B: VecLike): number {\n\t\treturn A.x * B.x + A.y * B.y\n\t}\n\n\tstatic Cross(A: VecLike, V: VecLike) {\n\t\treturn new Vec(\n\t\t\tA.y * V.z! - A.z! * V.y,\n\t\t\tA.z! * V.x - A.x * V.z!\n\t\t\t// A.z = A.x * V.y - A.y * V.x\n\t\t)\n\t}\n\n\t/**\n\t * Cross product of two vectors which is used to calculate the area of a parallelogram.\n\t */\n\tstatic Cpr(A: VecLike, B: VecLike) {\n\t\treturn A.x * B.y - B.x * A.y\n\t}\n\n\tstatic Len2(A: VecLike): number {\n\t\treturn A.x * A.x + A.y * A.y\n\t}\n\n\tstatic Len(A: VecLike): number {\n\t\treturn (A.x * A.x + A.y * A.y) ** 0.5\n\t}\n\n\t/**\n\t * Get the projection of A onto B.\n\t */\n\tstatic Pry(A: VecLike, B: VecLike): number {\n\t\treturn Vec.Dpr(A, B) / Vec.Len(B)\n\t}\n\n\t/**\n\t * Get the unit vector of A.\n\t */\n\tstatic Uni(A: VecLike) {\n\t\tconst l = Vec.Len(A)\n\t\treturn new Vec(l === 0 ? 0 : A.x / l, l === 0 ? 0 : A.y / l)\n\t}\n\n\tstatic Tan(A: VecLike, B: VecLike): Vec {\n\t\treturn Vec.Uni(Vec.Sub(A, B))\n\t}\n\n\tstatic Min(A: VecLike, B: VecLike): Vec {\n\t\treturn new Vec(Math.min(A.x, B.x), Math.min(A.y, B.y))\n\t}\n\n\tstatic Max(A: VecLike, B: VecLike): Vec {\n\t\treturn new Vec(Math.max(A.x, B.x), Math.max(A.y, B.y))\n\t}\n\n\tstatic From({ x, y, z = 1 }: VecModel) {\n\t\treturn new Vec(x, y, z)\n\t}\n\n\tstatic FromArray(v: number[]): Vec {\n\t\treturn new Vec(v[0], v[1])\n\t}\n\n\tstatic Rot(A: VecLike, r = 0): Vec {\n\t\tconst s = Math.sin(r)\n\t\tconst c = Math.cos(r)\n\t\treturn new Vec(A.x * c - A.y * s, A.x * s + A.y * c)\n\t}\n\n\tstatic RotWith(A: VecLike, C: VecLike, r: number): Vec {\n\t\tconst x = A.x - C.x\n\t\tconst y = A.y - C.y\n\t\tconst s = Math.sin(r)\n\t\tconst c = Math.cos(r)\n\t\treturn new Vec(C.x + (x * c - y * s), C.y + (x * s + y * c))\n\t}\n\n\t/**\n\t * Get the nearest point on a line with a known unit vector that passes through point A\n\t *\n\t * ```ts\n\t * Vec.nearestPointOnLineThroughPoint(A, u, Point)\n\t * ```\n\t *\n\t * @param A - Any point on the line\n\t * @param u - The unit vector for the line.\n\t * @param P - A point not on the line to test.\n\t */\n\tstatic NearestPointOnLineThroughPoint(A: VecLike, u: VecLike, P: VecLike): Vec {\n\t\t// Inlined: t = Vec.Sub(P, A).pry(u), return Vec.Mul(u, t).add(A)\n\t\tconst t = (P.x - A.x) * u.x + (P.y - A.y) * u.y\n\t\treturn new Vec(A.x + u.x * t, A.y + u.y * t)\n\t}\n\n\tstatic NearestPointOnLineSegment(A: VecLike, B: VecLike, P: VecLike, clamp = true): Vec {\n\t\t// Parametric projection of P onto segment AB.\n\t\t// Inlined: d = Vec.Sub(B, A); t = Vec.Sub(P, A).pry(d) / d.len(); return Vec.Lrp(A, B, t)\n\t\tconst dx = B.x - A.x\n\t\tconst dy = B.y - A.y\n\t\tconst d2 = dx * dx + dy * dy\n\n\t\tif (d2 === 0) return Vec.From(A)\n\n\t\tlet t = ((P.x - A.x) * dx + (P.y - A.y) * dy) / d2\n\n\t\tif (clamp) {\n\t\t\tif (t < 0) t = 0\n\t\t\telse if (t > 1) t = 1\n\t\t}\n\n\t\treturn new Vec(A.x + t * dx, A.y + t * dy)\n\t}\n\n\tstatic DistanceToLineThroughPoint(A: VecLike, u: VecLike, P: VecLike): number {\n\t\t// Inlined: Vec.Dist(P, Vec.NearestPointOnLineThroughPoint(A, u, P))\n\t\t// Uses |cross(P-A, u)| which equals the perpendicular distance when u is a unit vector.\n\t\tconst dx = P.x - A.x\n\t\tconst dy = P.y - A.y\n\t\treturn Math.abs(dx * u.y - dy * u.x)\n\t}\n\n\tstatic DistanceToLineSegment(A: VecLike, B: VecLike, P: VecLike, clamp = true): number {\n\t\t// Inlined: Vec.Dist(P, Vec.NearestPointOnLineSegment(A, B, P, clamp))\n\t\t// Computes the nearest point via parametric t-projection then returns the scalar distance,\n\t\t// avoiding the intermediate Vec allocation that NearestPointOnLineSegment would create.\n\t\tconst dx = B.x - A.x\n\t\tconst dy = B.y - A.y\n\t\tconst d2 = dx * dx + dy * dy\n\n\t\tif (d2 === 0) return Vec.Dist(A, P)\n\n\t\tlet t = ((P.x - A.x) * dx + (P.y - A.y) * dy) / d2\n\n\t\tif (clamp) {\n\t\t\tif (t < 0) t = 0\n\t\t\telse if (t > 1) t = 1\n\t\t}\n\n\t\tconst nx = A.x + t * dx - P.x\n\t\tconst ny = A.y + t * dy - P.y\n\t\treturn Math.sqrt(nx * nx + ny * ny)\n\t}\n\n\tstatic Snap(A: VecLike, step = 1) {\n\t\treturn new Vec(Math.round(A.x / step) * step, Math.round(A.y / step) * step)\n\t}\n\n\tstatic Cast(A: VecLike): Vec {\n\t\tif (A instanceof Vec) return A\n\t\treturn Vec.From(A)\n\t}\n\n\tstatic Slope(A: VecLike, B: VecLike): number {\n\t\tif (A.x === B.y) return NaN\n\t\treturn (A.y - B.y) / (A.x - B.x)\n\t}\n\n\tstatic IsNaN(A: VecLike): boolean {\n\t\treturn isNaN(A.x) || isNaN(A.y)\n\t}\n\n\tstatic IsFinite(A: VecLike): boolean {\n\t\treturn Number.isFinite(A.x) && Number.isFinite(A.y)\n\t}\n\n\t/**\n\t * Get the angle from position A to position B.\n\t */\n\tstatic Angle(A: VecLike, B: VecLike): number {\n\t\treturn Math.atan2(B.y - A.y, B.x - A.x)\n\t}\n\n\t/**\n\t * Get the angle between vector A and vector B. This will return the smallest angle between the\n\t * two vectors, between -\u03C0 and \u03C0. The sign indicates direction of angle.\n\t */\n\tstatic AngleBetween(A: VecLike, B: VecLike): number {\n\t\t// p = dot(A, B); n = |A| * |B| (uses x*x instead of Math.pow(x, 2))\n\t\tconst p = A.x * B.x + A.y * B.y\n\t\tconst n = Math.sqrt((A.x * A.x + A.y * A.y) * (B.x * B.x + B.y * B.y))\n\t\tconst sign = A.x * B.y - A.y * B.x < 0 ? -1 : 1\n\t\treturn sign * Math.acos(clamp(p / n, -1, 1))\n\t}\n\n\t/**\n\t * Linearly interpolate between two points.\n\t * @param A - The first point.\n\t * @param B - The second point.\n\t * @param t - The interpolation value between 0 and 1.\n\t * @returns The interpolated point.\n\t */\n\tstatic Lrp(A: VecLike, B: VecLike, t: number): Vec {\n\t\t// Inlined: Vec.Sub(B, A).mul(t).add(A) \u2014 note: only interpolates x/y, not z.\n\t\treturn new Vec(A.x + (B.x - A.x) * t, A.y + (B.y - A.y) * t)\n\t}\n\n\tstatic Med(A: VecLike, B: VecLike): Vec {\n\t\treturn new Vec((A.x + B.x) / 2, (A.y + B.y) / 2)\n\t}\n\n\tstatic Equals(A: VecLike, B: VecLike): boolean {\n\t\treturn Math.abs(A.x - B.x) < 0.0001 && Math.abs(A.y - B.y) < 0.0001\n\t}\n\n\tstatic EqualsXY(A: VecLike, x: number, y: number): boolean {\n\t\treturn A.x === x && A.y === y\n\t}\n\n\tstatic Clockwise(A: VecLike, B: VecLike, C: VecLike): boolean {\n\t\treturn (C.x - A.x) * (B.y - A.y) - (B.x - A.x) * (C.y - A.y) < 0\n\t}\n\n\tstatic Rescale(A: VecLike, n: number) {\n\t\tconst l = Vec.Len(A)\n\t\treturn new Vec((n * A.x) / l, (n * A.y) / l)\n\t}\n\n\tstatic ScaleWithOrigin(A: VecLike, scale: number, origin: VecLike) {\n\t\treturn Vec.Sub(A, origin).mul(scale).add(origin)\n\t}\n\n\tstatic ToFixed(A: VecLike) {\n\t\treturn new Vec(toFixed(A.x), toFixed(A.y))\n\t}\n\n\tstatic ToInt(A: VecLike) {\n\t\treturn new Vec(\n\t\t\tparseInt(A.x.toFixed(0)),\n\t\t\tparseInt(A.y.toFixed(0)),\n\t\t\tparseInt((A.z ?? 0).toFixed(0))\n\t\t)\n\t}\n\n\tstatic ToCss(A: VecLike) {\n\t\treturn `${A.x},${A.y}`\n\t}\n\n\tstatic Nudge(A: VecLike, B: VecLike, distance: number) {\n\t\treturn Vec.Add(A, Vec.Tan(B, A).mul(distance))\n\t}\n\n\tstatic ToString(A: VecLike) {\n\t\treturn `${A.x}, ${A.y}`\n\t}\n\n\tstatic ToAngle(A: VecLike) {\n\t\tlet r = Math.atan2(A.y, A.x)\n\t\tif (r < 0) r += Math.PI * 2\n\n\t\treturn r\n\t}\n\n\tstatic FromAngle(r: number, length = 1) {\n\t\treturn new Vec(Math.cos(r) * length, Math.sin(r) * length)\n\t}\n\n\tstatic ToArray(A: VecLike) {\n\t\treturn [A.x, A.y, A.z!]\n\t}\n\n\tstatic ToJson(A: VecLike) {\n\t\tconst { x, y, z } = A\n\t\treturn { x, y, z }\n\t}\n\n\tstatic Average(arr: VecLike[]) {\n\t\tconst len = arr.length\n\t\tconst avg = new Vec(0, 0)\n\t\tif (len === 0) {\n\t\t\treturn avg\n\t\t}\n\t\tfor (let i = 0; i < len; i++) {\n\t\t\tavg.add(arr[i])\n\t\t}\n\t\treturn avg.div(len)\n\t}\n\n\tstatic Clamp(A: Vec, min: number, max?: number) {\n\t\tif (max === undefined) {\n\t\t\treturn new Vec(Math.min(Math.max(A.x, min)), Math.min(Math.max(A.y, min)))\n\t\t}\n\n\t\treturn new Vec(Math.min(Math.max(A.x, min), max), Math.min(Math.max(A.y, min), max))\n\t}\n\n\t/**\n\t * Get an array of points (with simulated pressure) between two points.\n\t *\n\t * @param A - The first point.\n\t * @param B - The second point.\n\t * @param steps - The number of points to return.\n\t * @param ease - The easing to use.\n\t */\n\tstatic PointsBetween(A: VecModel, B: VecModel, steps = 6, ease = EASINGS.easeInQuad): Vec[] {\n\t\tconst results: Vec[] = []\n\n\t\tfor (let i = 0; i < steps; i++) {\n\t\t\tconst t = ease(i / (steps - 1))\n\t\t\tconst point = Vec.Lrp(A, B, t)\n\t\t\tpoint.z = Math.min(1, 0.5 + Math.abs(0.5 - EASINGS.easeInOutQuad(t)) * 0.65)\n\t\t\tresults.push(point)\n\t\t}\n\n\t\treturn results\n\t}\n\n\tstatic SnapToGrid(A: VecLike, gridSize = 8) {\n\t\treturn new Vec(Math.round(A.x / gridSize) * gridSize, Math.round(A.y / gridSize) * gridSize)\n\t}\n}\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["import { VecModel } from '@tldraw/tlschema'\nimport { EASINGS } from './easings'\n\nconst { easeInQuad, easeInOutQuad } = EASINGS\n\nfunction clamp(n: number, min: number, max?: number): number {\n\treturn Math.max(min, typeof max !== 'undefined' ? Math.min(n, max) : n)\n}\n\nfunction toFixed(v: number) {\n\treturn Math.round(v * 1e2) / 1e2\n}\n\n/** @public */\nexport type VecLike = Vec | VecModel\n\n/** @public */\nexport class Vec {\n\tconstructor(\n\t\tpublic x = 0,\n\t\tpublic y = 0,\n\t\tpublic z = 1\n\t) {}\n\n\t// eslint-disable-next-line tldraw/no-setter-getter\n\tget pressure() {\n\t\treturn this.z\n\t}\n\n\tset(x = this.x, y = this.y, z = this.z) {\n\t\tthis.x = x\n\t\tthis.y = y\n\t\tthis.z = z\n\t\treturn this\n\t}\n\n\tsetTo({ x = 0, y = 0, z = 1 }: VecLike) {\n\t\tthis.x = x\n\t\tthis.y = y\n\t\tthis.z = z\n\t\treturn this\n\t}\n\n\trot(r: number) {\n\t\tif (r === 0) return this\n\t\tconst { x, y } = this\n\t\tconst s = Math.sin(r)\n\t\tconst c = Math.cos(r)\n\t\tthis.x = x * c - y * s\n\t\tthis.y = x * s + y * c\n\t\treturn this\n\t}\n\n\trotWith(C: VecLike, r: number) {\n\t\tif (r === 0) return this\n\t\tconst x = this.x - C.x\n\t\tconst y = this.y - C.y\n\t\tconst s = Math.sin(r)\n\t\tconst c = Math.cos(r)\n\t\tthis.x = C.x + (x * c - y * s)\n\t\tthis.y = C.y + (x * s + y * c)\n\t\treturn this\n\t}\n\n\tclone(): Vec {\n\t\tconst { x, y, z } = this\n\t\treturn new Vec(x, y, z)\n\t}\n\n\tsub(V: VecLike) {\n\t\tthis.x -= V.x\n\t\tthis.y -= V.y\n\t\treturn this\n\t}\n\n\tsubXY(x: number, y: number) {\n\t\tthis.x -= x\n\t\tthis.y -= y\n\t\treturn this\n\t}\n\n\tsubScalar(n: number) {\n\t\tthis.x -= n\n\t\tthis.y -= n\n\t\t// this.z -= n\n\n\t\treturn this\n\t}\n\n\tadd(V: VecLike) {\n\t\tthis.x += V.x\n\t\tthis.y += V.y\n\t\treturn this\n\t}\n\n\taddXY(x: number, y: number) {\n\t\tthis.x += x\n\t\tthis.y += y\n\t\treturn this\n\t}\n\n\taddScalar(n: number) {\n\t\tthis.x += n\n\t\tthis.y += n\n\t\t// this.z += n\n\n\t\treturn this\n\t}\n\n\tclamp(min: number, max?: number) {\n\t\tthis.x = Math.max(this.x, min)\n\t\tthis.y = Math.max(this.y, min)\n\t\tif (max !== undefined) {\n\t\t\tthis.x = Math.min(this.x, max)\n\t\t\tthis.y = Math.min(this.y, max)\n\t\t}\n\t\treturn this\n\t}\n\n\tdiv(t: number) {\n\t\tthis.x /= t\n\t\tthis.y /= t\n\t\t// this.z /= t\n\t\treturn this\n\t}\n\n\tdivV(V: VecLike) {\n\t\tthis.x /= V.x\n\t\tthis.y /= V.y\n\t\t// this.z /= V.z\n\t\treturn this\n\t}\n\n\tmul(t: number) {\n\t\tthis.x *= t\n\t\tthis.y *= t\n\t\t// this.z *= t\n\t\treturn this\n\t}\n\n\tmulV(V: VecLike) {\n\t\tthis.x *= V.x\n\t\tthis.y *= V.y\n\t\t// this.z *= V.z\n\t\treturn this\n\t}\n\n\tabs() {\n\t\tthis.x = Math.abs(this.x)\n\t\tthis.y = Math.abs(this.y)\n\t\treturn this\n\t}\n\n\tnudge(B: VecLike, distance: number) {\n\t\tconst tan = Vec.Tan(B, this)\n\t\treturn this.add(tan.mul(distance))\n\t}\n\n\tneg() {\n\t\tthis.x *= -1\n\t\tthis.y *= -1\n\t\t// this.z *= -1\n\t\treturn this\n\t}\n\n\tcross(V: VecLike) {\n\t\tthis.x = this.y * V.z! - this.z * V.y\n\t\tthis.y = this.z * V.x - this.x * V.z!\n\t\t// this.z = this.x * V.y - this.y * V.x\n\t\treturn this\n\t}\n\n\tdpr(V: VecLike): number {\n\t\treturn Vec.Dpr(this, V)\n\t}\n\n\tcpr(V: VecLike) {\n\t\treturn Vec.Cpr(this, V)\n\t}\n\n\tlen2(): number {\n\t\treturn Vec.Len2(this)\n\t}\n\n\tlen(): number {\n\t\treturn Vec.Len(this)\n\t}\n\n\tpry(V: VecLike): number {\n\t\treturn Vec.Pry(this, V)\n\t}\n\n\tper() {\n\t\tconst { x, y } = this\n\t\tthis.x = y\n\t\tthis.y = -x\n\t\treturn this\n\t}\n\n\tuni() {\n\t\tconst l = this.len()\n\t\tif (l === 0) return this\n\t\tthis.x /= l\n\t\tthis.y /= l\n\t\treturn this\n\t}\n\n\ttan(V: VecLike): Vec {\n\t\treturn this.sub(V).uni()\n\t}\n\n\tdist(V: VecLike): number {\n\t\treturn Vec.Dist(this, V)\n\t}\n\n\tdistanceToLineSegment(A: VecLike, B: VecLike): number {\n\t\treturn Vec.DistanceToLineSegment(A, B, this)\n\t}\n\n\tslope(B: VecLike): number {\n\t\treturn Vec.Slope(this, B)\n\t}\n\n\tsnapToGrid(gridSize: number) {\n\t\tthis.x = Math.round(this.x / gridSize) * gridSize\n\t\tthis.y = Math.round(this.y / gridSize) * gridSize\n\t\treturn this\n\t}\n\n\tangle(B: VecLike): number {\n\t\treturn Vec.Angle(this, B)\n\t}\n\n\ttoAngle() {\n\t\treturn Vec.ToAngle(this)\n\t}\n\n\tlrp(B: VecLike, t: number): Vec {\n\t\tthis.x = this.x + (B.x - this.x) * t\n\t\tthis.y = this.y + (B.y - this.y) * t\n\t\treturn this\n\t}\n\n\tequals(B: VecLike) {\n\t\treturn Vec.Equals(this, B)\n\t}\n\n\tequalsXY(x: number, y: number) {\n\t\treturn Vec.EqualsXY(this, x, y)\n\t}\n\n\ttoFixed() {\n\t\tthis.x = toFixed(this.x)\n\t\tthis.y = toFixed(this.y)\n\t\treturn this\n\t}\n\n\ttoString() {\n\t\treturn Vec.ToString(Vec.ToFixed(this))\n\t}\n\n\ttoJson(): VecModel {\n\t\treturn Vec.ToJson(this)\n\t}\n\n\ttoArray(): number[] {\n\t\treturn Vec.ToArray(this)\n\t}\n\n\tstatic Add(A: VecLike, B: VecLike): Vec {\n\t\treturn new Vec(A.x + B.x, A.y + B.y)\n\t}\n\n\tstatic AddXY(A: VecLike, x: number, y: number): Vec {\n\t\treturn new Vec(A.x + x, A.y + y)\n\t}\n\n\tstatic Sub(A: VecLike, B: VecLike): Vec {\n\t\treturn new Vec(A.x - B.x, A.y - B.y)\n\t}\n\n\tstatic SubXY(A: VecLike, x: number, y: number): Vec {\n\t\treturn new Vec(A.x - x, A.y - y)\n\t}\n\n\tstatic AddScalar(A: VecLike, n: number): Vec {\n\t\treturn new Vec(A.x + n, A.y + n)\n\t}\n\n\tstatic SubScalar(A: VecLike, n: number): Vec {\n\t\treturn new Vec(A.x - n, A.y - n)\n\t}\n\n\tstatic Div(A: VecLike, t: number): Vec {\n\t\treturn new Vec(A.x / t, A.y / t)\n\t}\n\n\tstatic Mul(A: VecLike, t: number): Vec {\n\t\treturn new Vec(A.x * t, A.y * t)\n\t}\n\n\tstatic DivV(A: VecLike, B: VecLike): Vec {\n\t\treturn new Vec(A.x / B.x, A.y / B.y)\n\t}\n\n\tstatic MulV(A: VecLike, B: VecLike): Vec {\n\t\treturn new Vec(A.x * B.x, A.y * B.y)\n\t}\n\n\tstatic Neg(A: VecLike): Vec {\n\t\treturn new Vec(-A.x, -A.y)\n\t}\n\n\t/**\n\t * Get the perpendicular vector to A.\n\t */\n\tstatic Per(A: VecLike): Vec {\n\t\treturn new Vec(A.y, -A.x)\n\t}\n\n\tstatic Abs(A: VecLike): Vec {\n\t\treturn new Vec(Math.abs(A.x), Math.abs(A.y))\n\t}\n\n\t// Get the distance between two points.\n\tstatic Dist(A: VecLike, B: VecLike): number {\n\t\treturn ((A.y - B.y) ** 2 + (A.x - B.x) ** 2) ** 0.5\n\t}\n\n\t// Get the Manhattan distance between two points.\n\tstatic ManhattanDist(A: VecLike, B: VecLike): number {\n\t\treturn Math.abs(A.x - B.x) + Math.abs(A.y - B.y)\n\t}\n\n\t// Get whether a distance between two points is less than a number. This is faster to calulate than using `Vec.Dist(a, b) < n`.\n\tstatic DistMin(A: VecLike, B: VecLike, n: number): boolean {\n\t\treturn (A.x - B.x) * (A.x - B.x) + (A.y - B.y) * (A.y - B.y) < n ** 2\n\t}\n\n\t// Get the squared distance between two points. This is faster to calculate (no square root) so useful for \"minimum distance\" checks where the actual measurement does not matter.\n\tstatic Dist2(A: VecLike, B: VecLike): number {\n\t\treturn (A.x - B.x) * (A.x - B.x) + (A.y - B.y) * (A.y - B.y)\n\t}\n\n\t/**\n\t * Dot product of two vectors which is used to calculate the angle between them.\n\t */\n\tstatic Dpr(A: VecLike, B: VecLike): number {\n\t\treturn A.x * B.x + A.y * B.y\n\t}\n\n\tstatic Cross(A: VecLike, V: VecLike) {\n\t\treturn new Vec(\n\t\t\tA.y * V.z! - A.z! * V.y,\n\t\t\tA.z! * V.x - A.x * V.z!\n\t\t\t// A.z = A.x * V.y - A.y * V.x\n\t\t)\n\t}\n\n\t/**\n\t * Cross product of two vectors which is used to calculate the area of a parallelogram.\n\t */\n\tstatic Cpr(A: VecLike, B: VecLike) {\n\t\treturn A.x * B.y - B.x * A.y\n\t}\n\n\tstatic Len2(A: VecLike): number {\n\t\treturn A.x * A.x + A.y * A.y\n\t}\n\n\tstatic Len(A: VecLike): number {\n\t\treturn (A.x * A.x + A.y * A.y) ** 0.5\n\t}\n\n\t/**\n\t * Get the projection of A onto B.\n\t */\n\tstatic Pry(A: VecLike, B: VecLike): number {\n\t\treturn Vec.Dpr(A, B) / Vec.Len(B)\n\t}\n\n\t/**\n\t * Get the unit vector of A.\n\t */\n\tstatic Uni(A: VecLike) {\n\t\tconst l = Vec.Len(A)\n\t\treturn new Vec(l === 0 ? 0 : A.x / l, l === 0 ? 0 : A.y / l)\n\t}\n\n\tstatic Tan(A: VecLike, B: VecLike): Vec {\n\t\treturn Vec.Uni(Vec.Sub(A, B))\n\t}\n\n\tstatic Min(A: VecLike, B: VecLike): Vec {\n\t\treturn new Vec(Math.min(A.x, B.x), Math.min(A.y, B.y))\n\t}\n\n\tstatic Max(A: VecLike, B: VecLike): Vec {\n\t\treturn new Vec(Math.max(A.x, B.x), Math.max(A.y, B.y))\n\t}\n\n\tstatic From({ x, y, z = 1 }: VecModel) {\n\t\treturn new Vec(x, y, z)\n\t}\n\n\tstatic FromArray(v: number[]): Vec {\n\t\treturn new Vec(v[0], v[1])\n\t}\n\n\tstatic Rot(A: VecLike, r = 0): Vec {\n\t\tconst s = Math.sin(r)\n\t\tconst c = Math.cos(r)\n\t\treturn new Vec(A.x * c - A.y * s, A.x * s + A.y * c)\n\t}\n\n\tstatic RotWith(A: VecLike, C: VecLike, r: number): Vec {\n\t\tconst x = A.x - C.x\n\t\tconst y = A.y - C.y\n\t\tconst s = Math.sin(r)\n\t\tconst c = Math.cos(r)\n\t\treturn new Vec(C.x + (x * c - y * s), C.y + (x * s + y * c))\n\t}\n\n\t/**\n\t * Get the nearest point on a line with a known unit vector that passes through point A\n\t *\n\t * ```ts\n\t * Vec.nearestPointOnLineThroughPoint(A, u, Point)\n\t * ```\n\t *\n\t * @param A - Any point on the line\n\t * @param u - The unit vector for the line.\n\t * @param P - A point not on the line to test.\n\t */\n\tstatic NearestPointOnLineThroughPoint(A: VecLike, u: VecLike, P: VecLike): Vec {\n\t\t// Inlined: t = Vec.Sub(P, A).pry(u), return Vec.Mul(u, t).add(A)\n\t\tconst t = (P.x - A.x) * u.x + (P.y - A.y) * u.y\n\t\treturn new Vec(A.x + u.x * t, A.y + u.y * t)\n\t}\n\n\tstatic NearestPointOnLineSegment(A: VecLike, B: VecLike, P: VecLike, clamp = true): Vec {\n\t\t// Parametric projection of P onto segment AB.\n\t\t// Inlined: d = Vec.Sub(B, A); t = Vec.Sub(P, A).pry(d) / d.len(); return Vec.Lrp(A, B, t)\n\t\tconst dx = B.x - A.x\n\t\tconst dy = B.y - A.y\n\t\tconst d2 = dx * dx + dy * dy\n\n\t\tif (d2 === 0) return Vec.From(A)\n\n\t\tlet t = ((P.x - A.x) * dx + (P.y - A.y) * dy) / d2\n\n\t\tif (clamp) {\n\t\t\tif (t < 0) t = 0\n\t\t\telse if (t > 1) t = 1\n\t\t}\n\n\t\treturn new Vec(A.x + t * dx, A.y + t * dy)\n\t}\n\n\tstatic DistanceToLineThroughPoint(A: VecLike, u: VecLike, P: VecLike): number {\n\t\t// Inlined: Vec.Dist(P, Vec.NearestPointOnLineThroughPoint(A, u, P))\n\t\t// Uses |cross(P-A, u)| which equals the perpendicular distance when u is a unit vector.\n\t\tconst dx = P.x - A.x\n\t\tconst dy = P.y - A.y\n\t\treturn Math.abs(dx * u.y - dy * u.x)\n\t}\n\n\tstatic DistanceToLineSegment(A: VecLike, B: VecLike, P: VecLike, clamp = true): number {\n\t\t// Inlined: Vec.Dist(P, Vec.NearestPointOnLineSegment(A, B, P, clamp))\n\t\t// Computes the nearest point via parametric t-projection then returns the scalar distance,\n\t\t// avoiding the intermediate Vec allocation that NearestPointOnLineSegment would create.\n\t\tconst dx = B.x - A.x\n\t\tconst dy = B.y - A.y\n\t\tconst d2 = dx * dx + dy * dy\n\n\t\tif (d2 === 0) return Vec.Dist(A, P)\n\n\t\tlet t = ((P.x - A.x) * dx + (P.y - A.y) * dy) / d2\n\n\t\tif (clamp) {\n\t\t\tif (t < 0) t = 0\n\t\t\telse if (t > 1) t = 1\n\t\t}\n\n\t\tconst nx = A.x + t * dx - P.x\n\t\tconst ny = A.y + t * dy - P.y\n\t\treturn Math.sqrt(nx * nx + ny * ny)\n\t}\n\n\tstatic Snap(A: VecLike, step = 1) {\n\t\treturn new Vec(Math.round(A.x / step) * step, Math.round(A.y / step) * step)\n\t}\n\n\tstatic Cast(A: VecLike): Vec {\n\t\tif (A instanceof Vec) return A\n\t\treturn Vec.From(A)\n\t}\n\n\tstatic Slope(A: VecLike, B: VecLike): number {\n\t\tif (A.x === B.y) return NaN\n\t\treturn (A.y - B.y) / (A.x - B.x)\n\t}\n\n\tstatic IsNaN(A: VecLike): boolean {\n\t\treturn isNaN(A.x) || isNaN(A.y)\n\t}\n\n\tstatic IsFinite(A: VecLike): boolean {\n\t\treturn Number.isFinite(A.x) && Number.isFinite(A.y)\n\t}\n\n\t/**\n\t * Get the angle from position A to position B.\n\t */\n\tstatic Angle(A: VecLike, B: VecLike): number {\n\t\treturn Math.atan2(B.y - A.y, B.x - A.x)\n\t}\n\n\t/**\n\t * Get the angle between vector A and vector B. This will return the smallest angle between the\n\t * two vectors, between -\u03C0 and \u03C0. The sign indicates direction of angle.\n\t */\n\tstatic AngleBetween(A: VecLike, B: VecLike): number {\n\t\t// p = dot(A, B); n = |A| * |B| (uses x*x instead of Math.pow(x, 2))\n\t\tconst p = A.x * B.x + A.y * B.y\n\t\tconst n = Math.sqrt((A.x * A.x + A.y * A.y) * (B.x * B.x + B.y * B.y))\n\t\tconst sign = A.x * B.y - A.y * B.x < 0 ? -1 : 1\n\t\treturn sign * Math.acos(clamp(p / n, -1, 1))\n\t}\n\n\t/**\n\t * Linearly interpolate between two points.\n\t * @param A - The first point.\n\t * @param B - The second point.\n\t * @param t - The interpolation value between 0 and 1.\n\t * @returns The interpolated point.\n\t */\n\tstatic Lrp(A: VecLike, B: VecLike, t: number): Vec {\n\t\t// Inlined: Vec.Sub(B, A).mul(t).add(A) \u2014 note: only interpolates x/y, not z.\n\t\treturn new Vec(A.x + (B.x - A.x) * t, A.y + (B.y - A.y) * t)\n\t}\n\n\tstatic Med(A: VecLike, B: VecLike): Vec {\n\t\treturn new Vec((A.x + B.x) / 2, (A.y + B.y) / 2)\n\t}\n\n\tstatic Equals(A: VecLike, B: VecLike): boolean {\n\t\treturn Math.abs(A.x - B.x) < 0.0001 && Math.abs(A.y - B.y) < 0.0001\n\t}\n\n\tstatic EqualsXY(A: VecLike, x: number, y: number): boolean {\n\t\treturn A.x === x && A.y === y\n\t}\n\n\tstatic Clockwise(A: VecLike, B: VecLike, C: VecLike): boolean {\n\t\treturn (C.x - A.x) * (B.y - A.y) - (B.x - A.x) * (C.y - A.y) < 0\n\t}\n\n\tstatic Rescale(A: VecLike, n: number) {\n\t\tconst l = Vec.Len(A)\n\t\treturn new Vec((n * A.x) / l, (n * A.y) / l)\n\t}\n\n\tstatic ScaleWithOrigin(A: VecLike, scale: number, origin: VecLike) {\n\t\treturn Vec.Sub(A, origin).mul(scale).add(origin)\n\t}\n\n\tstatic ToFixed(A: VecLike) {\n\t\treturn new Vec(toFixed(A.x), toFixed(A.y))\n\t}\n\n\tstatic ToInt(A: VecLike) {\n\t\treturn new Vec(\n\t\t\tparseInt(A.x.toFixed(0)),\n\t\t\tparseInt(A.y.toFixed(0)),\n\t\t\tparseInt((A.z ?? 0).toFixed(0))\n\t\t)\n\t}\n\n\tstatic ToCss(A: VecLike) {\n\t\treturn `${A.x},${A.y}`\n\t}\n\n\tstatic Nudge(A: VecLike, B: VecLike, distance: number) {\n\t\treturn Vec.Add(A, Vec.Tan(B, A).mul(distance))\n\t}\n\n\tstatic ToString(A: VecLike) {\n\t\treturn `${A.x}, ${A.y}`\n\t}\n\n\tstatic ToAngle(A: VecLike) {\n\t\tlet r = Math.atan2(A.y, A.x)\n\t\tif (r < 0) r += Math.PI * 2\n\n\t\treturn r\n\t}\n\n\tstatic FromAngle(r: number, length = 1) {\n\t\treturn new Vec(Math.cos(r) * length, Math.sin(r) * length)\n\t}\n\n\tstatic ToArray(A: VecLike) {\n\t\treturn [A.x, A.y, A.z!]\n\t}\n\n\tstatic ToJson(A: VecLike) {\n\t\tconst { x, y, z } = A\n\t\treturn { x, y, z }\n\t}\n\n\tstatic Average(arr: VecLike[]) {\n\t\tconst len = arr.length\n\t\tconst avg = new Vec(0, 0)\n\t\tif (len === 0) {\n\t\t\treturn avg\n\t\t}\n\t\tfor (let i = 0; i < len; i++) {\n\t\t\tavg.add(arr[i])\n\t\t}\n\t\treturn avg.div(len)\n\t}\n\n\tstatic Clamp(A: Vec, min: number, max?: number) {\n\t\tif (max === undefined) {\n\t\t\treturn new Vec(Math.min(Math.max(A.x, min)), Math.min(Math.max(A.y, min)))\n\t\t}\n\n\t\treturn new Vec(Math.min(Math.max(A.x, min), max), Math.min(Math.max(A.y, min), max))\n\t}\n\n\t/**\n\t * Get an array of points (with simulated pressure) between two points.\n\t *\n\t * @param A - The first point.\n\t * @param B - The second point.\n\t * @param steps - The number of points to return.\n\t * @param ease - The easing to use.\n\t */\n\tstatic PointsBetween(A: VecModel, B: VecModel, steps = 6, ease = easeInQuad): Vec[] {\n\t\tconst results: Vec[] = []\n\n\t\tfor (let i = 0; i < steps; i++) {\n\t\t\tconst t = ease(i / (steps - 1))\n\t\t\tconst point = Vec.Lrp(A, B, t)\n\t\t\tpoint.z = Math.min(1, 0.5 + Math.abs(0.5 - easeInOutQuad(t)) * 0.65)\n\t\t\tresults.push(point)\n\t\t}\n\n\t\treturn results\n\t}\n\n\tstatic SnapToGrid(A: VecLike, gridSize = 8) {\n\t\treturn new Vec(Math.round(A.x / gridSize) * gridSize, Math.round(A.y / gridSize) * gridSize)\n\t}\n}\n"],
5
+ "mappings": "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",
6
6
  "names": ["clamp"]
7
7
  }
@@ -43,6 +43,17 @@ function setStyleProperty(elm, property, value) {
43
43
  if (!elm) return;
44
44
  elm.style.setProperty(property, String(value));
45
45
  }
46
+ function moveElementInto(parent, element) {
47
+ if (element.isConnected && parent.isConnected && typeof parent.moveBefore === "function" && element.ownerDocument === parent.ownerDocument) {
48
+ try {
49
+ ;
50
+ parent.moveBefore(element, null);
51
+ return;
52
+ } catch {
53
+ }
54
+ }
55
+ parent.appendChild(element);
56
+ }
46
57
  function elementShouldCaptureKeys(el, includeButtonsAndMenus = true) {
47
58
  if (!el) return false;
48
59
  const tagName = el.tagName.toLowerCase();
@@ -68,6 +79,7 @@ export {
68
79
  getGlobalDocument,
69
80
  getGlobalWindow,
70
81
  loopToHtmlElement,
82
+ moveElementInto,
71
83
  preventDefault,
72
84
  releasePointerCapture,
73
85
  setPointerCapture,
@@ -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\tif ('cancelable' in event && !event.cancelable) return\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 function stopEventPropagation(e: any) {\n\treturn e.stopPropagation()\n}\n\n/** @internal */\nexport function 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/**\n * Returns the global `document`. Use this instead of bare `document` to satisfy lint rules.\n *\n * When you have a DOM node or editor instance, prefer the scoped versions instead:\n * - `getOwnerDocument(node)` \u2013 the document that owns a specific DOM node\n * - `editor.getContainerDocument()` \u2013 the document where the editor is mounted\n *\n * @internal\n */\nexport function getGlobalDocument(): Document {\n\t// eslint-disable-next-line no-restricted-globals\n\tif (typeof document !== 'undefined') return document\n\treturn globalThis.document\n}\n\n/**\n * Returns the global `window`. Use this instead of bare `window` to satisfy lint rules.\n *\n * When you have a DOM node or editor instance, prefer the scoped versions instead:\n * - `getOwnerWindow(node)` \u2013 the window that owns a specific DOM node\n * - `editor.getContainerWindow()` \u2013 the window where the editor is mounted\n *\n * @internal\n */\nexport function getGlobalWindow(): Window & typeof globalThis {\n\tif (typeof window !== 'undefined') return window as Window & typeof globalThis\n\treturn globalThis as Window & typeof globalThis\n}\n\n/** @internal */\nexport function activeElementShouldCaptureKeys(includeButtonsAndMenus = true, doc?: Document) {\n\treturn elementShouldCaptureKeys(\n\t\t(doc ?? getGlobalDocument()).activeElement,\n\t\tincludeButtonsAndMenus\n\t)\n}\n"],
5
- "mappings": "AAeA,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,MAAI,gBAAgB,SAAS,CAAC,MAAM,WAAY;AAChD,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,SAAS,qBAAqB,GAAQ;AAC5C,SAAO,EAAE,gBAAgB;AAC1B;AAGO,SAAS,iBACf,KACA,UACA,OACC;AACD,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;AAWO,SAAS,oBAA8B;AAE7C,MAAI,OAAO,aAAa,YAAa,QAAO;AAC5C,SAAO,WAAW;AACnB;AAWO,SAAS,kBAA8C;AAC7D,MAAI,OAAO,WAAW,YAAa,QAAO;AAC1C,SAAO;AACR;AAGO,SAAS,+BAA+B,yBAAyB,MAAM,KAAgB;AAC7F,SAAO;AAAA,KACL,OAAO,kBAAkB,GAAG;AAAA,IAC7B;AAAA,EACD;AACD;",
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\tif ('cancelable' in event && !event.cancelable) return\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 function stopEventPropagation(e: any) {\n\treturn e.stopPropagation()\n}\n\n/** @internal */\nexport function 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/**\n * Move an element into a new parent, preserving its state where the platform allows it.\n *\n * Uses `Node.moveBefore` (Chromium 133+, Firefox 144+) when both the element and parent are\n * connected to the same document \u2014 this moves the element without resetting its state, so\n * iframes don't reload and media keeps playing. Otherwise (older browsers, disconnected nodes,\n * or a cross-document move) it falls back to `appendChild`, which moves the element but resets\n * its state like an iframe reload.\n *\n * This is the primitive tldraw uses to adopt `ShapeUtil.getAppOwnedElement` elements, exposed so\n * apps can perform symmetric state-preserving moves from `ShapeUtil.onReleaseAppOwnedElement` \u2014\n * for example moving an element to an off-canvas parking lot between editor sessions.\n *\n * @param parent - The element to move `element` into, as its last child.\n * @param element - The element to move.\n * @public\n */\nexport function moveElementInto(parent: HTMLElement, element: HTMLElement) {\n\tif (\n\t\telement.isConnected &&\n\t\tparent.isConnected &&\n\t\ttypeof (parent as any).moveBefore === 'function' &&\n\t\telement.ownerDocument === parent.ownerDocument\n\t) {\n\t\ttry {\n\t\t\t;(parent as any).moveBefore(element, null)\n\t\t\treturn\n\t\t} catch {\n\t\t\t// fall through to appendChild\n\t\t}\n\t}\n\tparent.appendChild(element)\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/**\n * Returns the global `document`. Use this instead of bare `document` to satisfy lint rules.\n *\n * When you have a DOM node or editor instance, prefer the scoped versions instead:\n * - `getOwnerDocument(node)` \u2013 the document that owns a specific DOM node\n * - `editor.getContainerDocument()` \u2013 the document where the editor is mounted\n *\n * @internal\n */\nexport function getGlobalDocument(): Document {\n\t// eslint-disable-next-line no-restricted-globals\n\tif (typeof document !== 'undefined') return document\n\treturn globalThis.document\n}\n\n/**\n * Returns the global `window`. Use this instead of bare `window` to satisfy lint rules.\n *\n * When you have a DOM node or editor instance, prefer the scoped versions instead:\n * - `getOwnerWindow(node)` \u2013 the window that owns a specific DOM node\n * - `editor.getContainerWindow()` \u2013 the window where the editor is mounted\n *\n * @internal\n */\nexport function getGlobalWindow(): Window & typeof globalThis {\n\tif (typeof window !== 'undefined') return window as Window & typeof globalThis\n\treturn globalThis as Window & typeof globalThis\n}\n\n/** @internal */\nexport function activeElementShouldCaptureKeys(includeButtonsAndMenus = true, doc?: Document) {\n\treturn elementShouldCaptureKeys(\n\t\t(doc ?? getGlobalDocument()).activeElement,\n\t\tincludeButtonsAndMenus\n\t)\n}\n"],
5
+ "mappings": "AAeA,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,MAAI,gBAAgB,SAAS,CAAC,MAAM,WAAY;AAChD,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,SAAS,qBAAqB,GAAQ;AAC5C,SAAO,EAAE,gBAAgB;AAC1B;AAGO,SAAS,iBACf,KACA,UACA,OACC;AACD,MAAI,CAAC,IAAK;AACV,MAAI,MAAM,YAAY,UAAU,OAAO,KAAK,CAAC;AAC9C;AAmBO,SAAS,gBAAgB,QAAqB,SAAsB;AAC1E,MACC,QAAQ,eACR,OAAO,eACP,OAAQ,OAAe,eAAe,cACtC,QAAQ,kBAAkB,OAAO,eAChC;AACD,QAAI;AACH;AAAC,MAAC,OAAe,WAAW,SAAS,IAAI;AACzC;AAAA,IACD,QAAQ;AAAA,IAER;AAAA,EACD;AACA,SAAO,YAAY,OAAO;AAC3B;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;AAWO,SAAS,oBAA8B;AAE7C,MAAI,OAAO,aAAa,YAAa,QAAO;AAC5C,SAAO,WAAW;AACnB;AAWO,SAAS,kBAA8C;AAC7D,MAAI,OAAO,WAAW,YAAa,QAAO;AAC1C,SAAO;AACR;AAGO,SAAS,+BAA+B,yBAAyB,MAAM,KAAgB;AAC7F,SAAO;AAAA,KACL,OAAO,kBAAkB,GAAG;AAAA,IAC7B;AAAA,EACD;AACD;",
6
6
  "names": []
7
7
  }
@@ -1,4 +1,5 @@
1
1
  import { isAccelKey } from "./keyboard.mjs";
2
+ import { getPointerEventButton } from "./pointer.mjs";
2
3
  function getPointerInfo(editor, e) {
3
4
  editor.markEventAsHandled(e);
4
5
  return {
@@ -13,7 +14,7 @@ function getPointerInfo(editor, e) {
13
14
  metaKey: e.metaKey,
14
15
  accelKey: isAccelKey(e),
15
16
  pointerId: e.pointerId,
16
- button: e.button,
17
+ button: getPointerEventButton(e),
17
18
  isPen: e.pointerType === "pen"
18
19
  };
19
20
  }
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../src/lib/utils/getPointerInfo.ts"],
4
- "sourcesContent": ["import type React from 'react'\nimport { 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": "AAEA,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 type React from 'react'\nimport { Editor } from '../editor/Editor'\nimport { isAccelKey } from './keyboard'\nimport { getPointerEventButton } from './pointer'\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: getPointerEventButton(e),\n\t\tisPen: e.pointerType === 'pen',\n\t}\n}\n"],
5
+ "mappings": "AAEA,SAAS,kBAAkB;AAC3B,SAAS,6BAA6B;AAG/B,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,sBAAsB,CAAC;AAAA,IAC/B,OAAO,EAAE,gBAAgB;AAAA,EAC1B;AACD;",
6
6
  "names": []
7
7
  }