@tldraw/editor 3.12.0-canary.dfe1ebbad12e → 3.12.0-canary.e08eba00c6c8
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.
- package/dist-cjs/index.d.ts +158 -17
- package/dist-cjs/index.js +3 -1
- package/dist-cjs/index.js.map +2 -2
- package/dist-cjs/lib/TldrawEditor.js +5 -0
- package/dist-cjs/lib/TldrawEditor.js.map +2 -2
- package/dist-cjs/lib/components/GeometryDebuggingView.js +2 -2
- package/dist-cjs/lib/components/GeometryDebuggingView.js.map +2 -2
- package/dist-cjs/lib/components/Shape.js +10 -14
- package/dist-cjs/lib/components/Shape.js.map +2 -2
- package/dist-cjs/lib/components/default-components/DefaultCanvas.js +10 -1
- package/dist-cjs/lib/components/default-components/DefaultCanvas.js.map +2 -2
- package/dist-cjs/lib/editor/Editor.js +215 -30
- package/dist-cjs/lib/editor/Editor.js.map +2 -2
- package/dist-cjs/lib/editor/derivations/notVisibleShapes.js +1 -1
- package/dist-cjs/lib/editor/derivations/notVisibleShapes.js.map +2 -2
- package/dist-cjs/lib/editor/managers/FocusManager.js +1 -1
- package/dist-cjs/lib/editor/managers/FocusManager.js.map +2 -2
- package/dist-cjs/lib/editor/managers/FontManager.js +1 -1
- package/dist-cjs/lib/editor/managers/FontManager.js.map +2 -2
- package/dist-cjs/lib/editor/shapes/ShapeUtil.js +12 -0
- package/dist-cjs/lib/editor/shapes/ShapeUtil.js.map +2 -2
- package/dist-cjs/lib/editor/shapes/group/GroupShapeUtil.js +4 -13
- package/dist-cjs/lib/editor/shapes/group/GroupShapeUtil.js.map +2 -2
- package/dist-cjs/lib/editor/tools/StateNode.js +4 -1
- package/dist-cjs/lib/editor/tools/StateNode.js.map +2 -2
- package/dist-cjs/lib/editor/types/selection-types.js.map +1 -1
- package/dist-cjs/lib/exports/StyleEmbedder.js +19 -5
- package/dist-cjs/lib/exports/StyleEmbedder.js.map +2 -2
- package/dist-cjs/lib/exports/cssRules.js +127 -0
- package/dist-cjs/lib/exports/cssRules.js.map +7 -0
- package/dist-cjs/lib/exports/parseCss.js +0 -69
- package/dist-cjs/lib/exports/parseCss.js.map +2 -2
- package/dist-cjs/lib/hooks/useCanvasEvents.js +12 -7
- package/dist-cjs/lib/hooks/useCanvasEvents.js.map +3 -3
- package/dist-cjs/lib/hooks/useDocumentEvents.js +16 -0
- package/dist-cjs/lib/hooks/useDocumentEvents.js.map +2 -2
- package/dist-cjs/lib/hooks/useGestureEvents.js +12 -6
- package/dist-cjs/lib/hooks/useGestureEvents.js.map +2 -2
- package/dist-cjs/lib/license/Watermark.js +10 -20
- package/dist-cjs/lib/license/Watermark.js.map +2 -2
- package/dist-cjs/lib/primitives/geometry/Geometry2d.js +133 -16
- package/dist-cjs/lib/primitives/geometry/Geometry2d.js.map +3 -3
- package/dist-cjs/lib/primitives/geometry/Group2d.js +54 -11
- package/dist-cjs/lib/primitives/geometry/Group2d.js.map +2 -2
- package/dist-cjs/lib/primitives/intersect.js +20 -0
- package/dist-cjs/lib/primitives/intersect.js.map +2 -2
- package/dist-cjs/lib/utils/debug-flags.js +2 -1
- package/dist-cjs/lib/utils/debug-flags.js.map +2 -2
- package/dist-cjs/lib/utils/reorderShapes.js +2 -8
- package/dist-cjs/lib/utils/reorderShapes.js.map +2 -2
- package/dist-cjs/version.js +3 -3
- package/dist-cjs/version.js.map +1 -1
- package/dist-esm/index.d.mts +158 -17
- package/dist-esm/index.mjs +8 -2
- package/dist-esm/index.mjs.map +2 -2
- package/dist-esm/lib/TldrawEditor.mjs +5 -0
- package/dist-esm/lib/TldrawEditor.mjs.map +2 -2
- package/dist-esm/lib/components/GeometryDebuggingView.mjs +3 -3
- package/dist-esm/lib/components/GeometryDebuggingView.mjs.map +2 -2
- package/dist-esm/lib/components/Shape.mjs +11 -15
- package/dist-esm/lib/components/Shape.mjs.map +2 -2
- package/dist-esm/lib/components/default-components/DefaultCanvas.mjs +10 -1
- package/dist-esm/lib/components/default-components/DefaultCanvas.mjs.map +2 -2
- package/dist-esm/lib/editor/Editor.mjs +216 -30
- package/dist-esm/lib/editor/Editor.mjs.map +2 -2
- package/dist-esm/lib/editor/derivations/notVisibleShapes.mjs +1 -1
- package/dist-esm/lib/editor/derivations/notVisibleShapes.mjs.map +2 -2
- package/dist-esm/lib/editor/managers/FocusManager.mjs +1 -1
- package/dist-esm/lib/editor/managers/FocusManager.mjs.map +2 -2
- package/dist-esm/lib/editor/managers/FontManager.mjs +1 -1
- package/dist-esm/lib/editor/managers/FontManager.mjs.map +2 -2
- package/dist-esm/lib/editor/shapes/ShapeUtil.mjs +12 -0
- package/dist-esm/lib/editor/shapes/ShapeUtil.mjs.map +2 -2
- package/dist-esm/lib/editor/shapes/group/GroupShapeUtil.mjs +4 -13
- package/dist-esm/lib/editor/shapes/group/GroupShapeUtil.mjs.map +2 -2
- package/dist-esm/lib/editor/tools/StateNode.mjs +4 -1
- package/dist-esm/lib/editor/tools/StateNode.mjs.map +2 -2
- package/dist-esm/lib/exports/StyleEmbedder.mjs +21 -12
- package/dist-esm/lib/exports/StyleEmbedder.mjs.map +2 -2
- package/dist-esm/lib/exports/cssRules.mjs +107 -0
- package/dist-esm/lib/exports/cssRules.mjs.map +7 -0
- package/dist-esm/lib/exports/parseCss.mjs +0 -69
- package/dist-esm/lib/exports/parseCss.mjs.map +2 -2
- package/dist-esm/lib/hooks/useCanvasEvents.mjs +12 -7
- package/dist-esm/lib/hooks/useCanvasEvents.mjs.map +3 -3
- package/dist-esm/lib/hooks/useDocumentEvents.mjs +16 -0
- package/dist-esm/lib/hooks/useDocumentEvents.mjs.map +2 -2
- package/dist-esm/lib/hooks/useGestureEvents.mjs +12 -6
- package/dist-esm/lib/hooks/useGestureEvents.mjs.map +2 -2
- package/dist-esm/lib/license/Watermark.mjs +10 -20
- package/dist-esm/lib/license/Watermark.mjs.map +2 -2
- package/dist-esm/lib/primitives/geometry/Geometry2d.mjs +137 -14
- package/dist-esm/lib/primitives/geometry/Geometry2d.mjs.map +2 -2
- package/dist-esm/lib/primitives/geometry/Group2d.mjs +55 -12
- package/dist-esm/lib/primitives/geometry/Group2d.mjs.map +2 -2
- package/dist-esm/lib/primitives/intersect.mjs +20 -0
- package/dist-esm/lib/primitives/intersect.mjs.map +2 -2
- package/dist-esm/lib/utils/debug-flags.mjs +2 -1
- package/dist-esm/lib/utils/debug-flags.mjs.map +2 -2
- package/dist-esm/lib/utils/reorderShapes.mjs +2 -8
- package/dist-esm/lib/utils/reorderShapes.mjs.map +2 -2
- package/dist-esm/version.mjs +3 -3
- package/dist-esm/version.mjs.map +1 -1
- package/package.json +7 -7
- package/src/index.ts +11 -2
- package/src/lib/TldrawEditor.tsx +30 -3
- package/src/lib/components/GeometryDebuggingView.tsx +3 -3
- package/src/lib/components/Shape.tsx +15 -19
- package/src/lib/components/default-components/DefaultCanvas.tsx +6 -1
- package/src/lib/editor/Editor.ts +322 -37
- package/src/lib/editor/derivations/notVisibleShapes.ts +1 -1
- package/src/lib/editor/managers/FocusManager.ts +1 -1
- package/src/lib/editor/managers/FontManager.ts +1 -1
- package/src/lib/editor/shapes/ShapeUtil.ts +14 -0
- package/src/lib/editor/shapes/group/GroupShapeUtil.tsx +7 -15
- package/src/lib/editor/tools/StateNode.ts +6 -1
- package/src/lib/editor/types/selection-types.ts +3 -0
- package/src/lib/exports/StyleEmbedder.ts +25 -15
- package/src/lib/exports/cssRules.ts +126 -0
- package/src/lib/exports/parseCss.ts +0 -79
- package/src/lib/hooks/useCanvasEvents.ts +14 -7
- package/src/lib/hooks/useDocumentEvents.ts +18 -0
- package/src/lib/hooks/useGestureEvents.ts +12 -6
- package/src/lib/license/Watermark.tsx +18 -29
- package/src/lib/primitives/geometry/Geometry2d.ts +196 -16
- package/src/lib/primitives/geometry/Group2d.ts +76 -13
- package/src/lib/primitives/intersect.ts +41 -0
- package/src/lib/utils/debug-flags.ts +1 -0
- package/src/lib/utils/reorderShapes.ts +2 -9
- package/src/version.ts +3 -3
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../src/lib/hooks/useGestureEvents.ts"],
|
|
4
|
-
"sourcesContent": ["import type { AnyHandlerEventTypes, EventTypes, GestureKey, Handler } from '@use-gesture/core/types'\nimport { createUseGesture, pinchAction, wheelAction } from '@use-gesture/react'\nimport * as React from 'react'\nimport { TLWheelEventInfo } from '../editor/types/event-types'\nimport { Vec } from '../primitives/Vec'\nimport { preventDefault, stopEventPropagation } from '../utils/dom'\nimport { isAccelKey } from '../utils/keyboard'\nimport { normalizeWheel } from '../utils/normalizeWheel'\nimport { useEditor } from './useEditor'\n\n/*\n\n# How does pinching work?\n\nThe pinching handler is fired under two circumstances: \n- when a user is on a MacBook trackpad and is ZOOMING with a two-finger pinch\n- when a user is on a touch device and is ZOOMING with a two-finger pinch\n- when a user is on a touch device and is PANNING with two fingers\n\nZooming is much more expensive than panning (because it causes shapes to render), \nso we want to be sure that we don't zoom while two-finger panning. \n\nIn order to do this, we keep track of a \"pinchState\", which is either:\n- \"zooming\"\n- \"panning\"\n- \"not sure\"\n\nIf a user is on a trackpad, the pinchState will be set to \"zooming\". \n\nIf the user is on a touch screen, then we start in the \"not sure\" state and switch back and forth\nbetween \"zooming\", \"panning\", and \"not sure\" based on what the user is doing with their fingers.\n\nIn the \"not sure\" state, we examine whether the user has moved the center of the gesture far enough\nto suggest that they're panning; or else that they've moved their fingers further apart or closer\ntogether enough to suggest that they're zooming. \n\nIn the \"panning\" state, we check whether the user's fingers have moved far enough apart to suggest\nthat they're zooming. If they have, we switch to the \"zooming\" state.\n\nIn the \"zooming\" state, we just stay zooming\u2014it's not YET possible to switch back to panning.\n\ntodo: compare velocities of change in order to determine whether the user has switched back to panning\n*/\n\ntype check<T extends AnyHandlerEventTypes, Key extends GestureKey> = undefined extends T[Key]\n\t? EventTypes[Key]\n\t: T[Key]\ntype PinchHandler = Handler<'pinch', check<EventTypes, 'pinch'>>\n\nconst useGesture = createUseGesture([wheelAction, pinchAction])\n\n/**\n * GOTCHA\n *\n * UseGesture fires a wheel event 140ms after the gesture actually ends, with a momentum-adjusted\n * delta. This creates a messed up interaction where after you stop scrolling suddenly the dang page\n * jumps a tick. why do they do this? you are asking the wrong person. it seems intentional though.\n * anyway we want to ignore that last event, but there's no way to directly detect it so we need to\n * keep track of timestamps. Yes this is awful, I am sorry.\n */\nlet lastWheelTime = undefined as undefined | number\n\nconst isWheelEndEvent = (time: number) => {\n\tif (lastWheelTime === undefined) {\n\t\tlastWheelTime = time\n\t\treturn false\n\t}\n\n\tif (time - lastWheelTime > 120 && time - lastWheelTime < 160) {\n\t\tlastWheelTime = time\n\t\treturn true\n\t}\n\n\tlastWheelTime = time\n\treturn false\n}\n\nexport function useGestureEvents(ref: React.RefObject<HTMLDivElement>) {\n\tconst editor = useEditor()\n\n\tconst events = React.useMemo(() => {\n\t\tlet pinchState = 'not sure' as 'not sure' | 'zooming' | 'panning'\n\n\t\tconst onWheel: Handler<'wheel', WheelEvent> = ({ event }) => {\n\t\t\tif (!editor.getInstanceState().isFocused) {\n\t\t\t\treturn\n\t\t\t}\n\n\t\t\tpinchState = 'not sure'\n\n\t\t\tif (isWheelEndEvent(Date.now())) {\n\t\t\t\t// ignore wheelEnd events\n\t\t\t\treturn\n\t\t\t}\n\n\t\t\t// Awful tht we need to put this logic here, but basically\n\t\t\t// we don't want to handle the the wheel event (or call prevent\n\t\t\t// default on the evnet) if the user is wheeling over an a shape\n\t\t\t// that is scrollable which they're currently editing.\n\n\t\t\tconst editingShapeId = editor.getEditingShapeId()\n\t\t\tif (editingShapeId) {\n\t\t\t\tconst shape = editor.getShape(editingShapeId)\n\t\t\t\tif (shape) {\n\t\t\t\t\tconst util = editor.getShapeUtil(shape)\n\t\t\t\t\tif (util.canScroll(shape)) {\n\t\t\t\t\t\tconst bounds = editor.getShapePageBounds(editingShapeId)\n\t\t\t\t\t\tif (bounds?.containsPoint(editor.inputs.currentPagePoint)) {\n\t\t\t\t\t\t\treturn\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tpreventDefault(event)\n\t\t\tstopEventPropagation(event)\n\t\t\tconst delta = normalizeWheel(event)\n\n\t\t\tif (delta.x === 0 && delta.y === 0) return\n\n\t\t\tconst info: TLWheelEventInfo = {\n\t\t\t\ttype: 'wheel',\n\t\t\t\tname: 'wheel',\n\t\t\t\tdelta,\n\t\t\t\tpoint: new Vec(event.clientX, event.clientY),\n\t\t\t\tshiftKey: event.shiftKey,\n\t\t\t\taltKey: event.altKey,\n\t\t\t\tctrlKey: event.metaKey || event.ctrlKey,\n\t\t\t\tmetaKey: event.metaKey,\n\t\t\t\taccelKey: isAccelKey(event),\n\t\t\t}\n\n\t\t\teditor.dispatch(info)\n\t\t}\n\n\t\tlet initDistanceBetweenFingers = 1 // the distance between the two fingers when the pinch starts\n\t\tlet initZoom = 1 // the browser's zoom level when the pinch starts\n\t\tlet currZoom = 1 // the current zoom level according to the pinch gesture recognizer\n\t\tlet currDistanceBetweenFingers = 0\n\t\tconst initPointBetweenFingers = new Vec()\n\t\tconst prevPointBetweenFingers = new Vec()\n\n\t\tconst onPinchStart: PinchHandler = (gesture) => {\n\t\t\tconst elm = ref.current\n\t\t\tpinchState = 'not sure'\n\n\t\t\tconst { event, origin, da } = gesture\n\n\t\t\tif (event instanceof WheelEvent) return\n\t\t\tif (!(event.target === elm || elm?.contains(event.target as Node))) return\n\n\t\t\tprevPointBetweenFingers.x = origin[0]\n\t\t\tprevPointBetweenFingers.y = origin[1]\n\t\t\tinitPointBetweenFingers.x = origin[0]\n\t\t\tinitPointBetweenFingers.y = origin[1]\n\t\t\tinitDistanceBetweenFingers = da[0]\n\t\t\tinitZoom = editor.getZoomLevel()\n\n\t\t\teditor.dispatch({\n\t\t\t\ttype: 'pinch',\n\t\t\t\tname: 'pinch_start',\n\t\t\t\tpoint: { x: origin[0], y: origin[1], z: editor.getZoomLevel() },\n\t\t\t\tdelta: { x: 0, y: 0 },\n\t\t\t\tshiftKey: event.shiftKey,\n\t\t\t\taltKey: event.altKey,\n\t\t\t\tctrlKey: event.metaKey || event.ctrlKey,\n\t\t\t\tmetaKey: event.metaKey,\n\t\t\t\taccelKey: isAccelKey(event),\n\t\t\t})\n\t\t}\n\n\t\t// let timeout: any\n\t\tconst updatePinchState = (isSafariTrackpadPinch: boolean) => {\n\t\t\tif (isSafariTrackpadPinch) {\n\t\t\t\tpinchState = 'zooming'\n\t\t\t}\n\n\t\t\tif (pinchState === 'zooming') {\n\t\t\t\treturn\n\t\t\t}\n\n\t\t\t// Initial: [touch]-------origin-------[touch]\n\t\t\t// Current: [touch]-----------origin----------[touch]\n\t\t\t// |----| |------------|\n\t\t\t// originDistance ^ ^ touchDistance\n\n\t\t\t// How far have the two touch points moved towards or away from eachother?\n\t\t\tconst touchDistance = Math.abs(currDistanceBetweenFingers - initDistanceBetweenFingers)\n\t\t\t// How far has the point between the touches moved?\n\t\t\tconst originDistance = Vec.Dist(initPointBetweenFingers, prevPointBetweenFingers)\n\n\t\t\tswitch (pinchState) {\n\t\t\t\tcase 'not sure': {\n\t\t\t\t\tif (touchDistance > 24) {\n\t\t\t\t\t\tpinchState = 'zooming'\n\t\t\t\t\t} else if (originDistance > 16) {\n\t\t\t\t\t\tpinchState = 'panning'\n\t\t\t\t\t}\n\t\t\t\t\tbreak\n\t\t\t\t}\n\t\t\t\tcase 'panning': {\n\t\t\t\t\t// Slightly more touch distance needed to go from panning to zooming\n\t\t\t\t\tif (touchDistance > 64) {\n\t\t\t\t\t\tpinchState = 'zooming'\n\t\t\t\t\t}\n\t\t\t\t\tbreak\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tconst onPinch: PinchHandler = (gesture) => {\n\t\t\tconst elm = ref.current\n\t\t\tconst { event, origin, offset, da } = gesture\n\n\t\t\tif (event instanceof WheelEvent) return\n\t\t\tif (!(event.target === elm || elm?.contains(event.target as Node))) return\n\n\t\t\t// In (desktop) Safari, a two finger trackpad pinch will be a \"gesturechange\" event\n\t\t\t// and will have 0 touches; on iOS, a two-finger pinch will be a \"pointermove\" event\n\t\t\t// with two touches.\n\t\t\tconst isSafariTrackpadPinch =\n\t\t\t\tgesture.type === 'gesturechange' || gesture.type === 'gestureend'\n\n\t\t\t// The distance between the two touch points\n\t\t\tcurrDistanceBetweenFingers = da[0]\n\n\t\t\t// Only update the zoom if the pointers are far enough apart;\n\t\t\t// a very small touchDistance means that the user has probably\n\t\t\t// pinched out and their fingers are touching; this produces\n\t\t\t// very unstable zooming behavior.\n\n\t\t\tconst dx = origin[0] - prevPointBetweenFingers.x\n\t\t\tconst dy = origin[1] - prevPointBetweenFingers.y\n\n\t\t\tprevPointBetweenFingers.x = origin[0]\n\t\t\tprevPointBetweenFingers.y = origin[1]\n\n\t\t\tupdatePinchState(isSafariTrackpadPinch)\n\n\t\t\tswitch (pinchState) {\n\t\t\t\tcase 'zooming': {\n\t\t\t\t\tcurrZoom = offset[0]\n\n\t\t\t\t\teditor.dispatch({\n\t\t\t\t\t\ttype: 'pinch',\n\t\t\t\t\t\tname: 'pinch',\n\t\t\t\t\t\tpoint: { x: origin[0], y: origin[1], z: currZoom },\n\t\t\t\t\t\tdelta: { x: dx, y: dy },\n\t\t\t\t\t\tshiftKey: event.shiftKey,\n\t\t\t\t\t\taltKey: event.altKey,\n\t\t\t\t\t\tctrlKey: event.metaKey || event.ctrlKey,\n\t\t\t\t\t\tmetaKey: event.metaKey,\n\t\t\t\t\t\taccelKey: isAccelKey(event),\n\t\t\t\t\t})\n\t\t\t\t\tbreak\n\t\t\t\t}\n\t\t\t\tcase 'panning': {\n\t\t\t\t\teditor.dispatch({\n\t\t\t\t\t\ttype: 'pinch',\n\t\t\t\t\t\tname: 'pinch',\n\t\t\t\t\t\tpoint: { x: origin[0], y: origin[1], z: initZoom },\n\t\t\t\t\t\tdelta: { x: dx, y: dy },\n\t\t\t\t\t\tshiftKey: event.shiftKey,\n\t\t\t\t\t\taltKey: event.altKey,\n\t\t\t\t\t\tctrlKey: event.metaKey || event.ctrlKey,\n\t\t\t\t\t\tmetaKey: event.metaKey,\n\t\t\t\t\t\taccelKey: isAccelKey(event),\n\t\t\t\t\t})\n\t\t\t\t\tbreak\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tconst onPinchEnd: PinchHandler = (gesture) => {\n\t\t\tconst elm = ref.current\n\t\t\tconst { event, origin, offset } = gesture\n\n\t\t\tif (event instanceof WheelEvent) return\n\t\t\tif (!(event.target === elm || elm?.contains(event.target as Node))) return\n\n\t\t\tconst scale = offset[0]\n\n\t\t\tpinchState = 'not sure'\n\n\t\t\teditor.timers.requestAnimationFrame(() => {\n\t\t\t\teditor.dispatch({\n\t\t\t\t\ttype: 'pinch',\n\t\t\t\t\tname: 'pinch_end',\n\t\t\t\t\tpoint: { x: origin[0], y: origin[1], z: scale },\n\t\t\t\t\tdelta: { x: origin[0], y: origin[1] },\n\t\t\t\t\tshiftKey: event.shiftKey,\n\t\t\t\t\taltKey: event.altKey,\n\t\t\t\t\tctrlKey: event.metaKey || event.ctrlKey,\n\t\t\t\t\tmetaKey: event.metaKey,\n\t\t\t\t\taccelKey: isAccelKey(event),\n\t\t\t\t})\n\t\t\t})\n\t\t}\n\n\t\treturn {\n\t\t\tonWheel,\n\t\t\tonPinchStart,\n\t\t\tonPinchEnd,\n\t\t\tonPinch,\n\t\t}\n\t}, [editor, ref])\n\n\tuseGesture(events, {\n\t\ttarget: ref,\n\t\teventOptions: { passive: false },\n\t\tpinch: {\n\t\t\tfrom: () => [editor.getZoomLevel(), 0], // Return the camera z to use when pinch starts\n\t\t\tscaleBounds: () => {\n\t\t\t\tconst baseZoom = editor.getBaseZoom()\n\t\t\t\tconst zoomSteps = editor.getCameraOptions().zoomSteps\n\t\t\t\tconst zoomMin = zoomSteps[0] * baseZoom\n\t\t\t\tconst zoomMax = zoomSteps[zoomSteps.length - 1] * baseZoom\n\n\t\t\t\treturn { from: editor.getZoomLevel(), max: zoomMax, min: zoomMin }\n\t\t\t},\n\t\t},\n\t})\n}\n"],
|
|
5
|
-
"mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AACA,mBAA2D;AAC3D,YAAuB;AAEvB,iBAAoB;AACpB,iBAAqD;AACrD,sBAA2B;AAC3B,4BAA+B;AAC/B,uBAA0B;AAyC1B,MAAM,iBAAa,+BAAiB,CAAC,0BAAa,wBAAW,CAAC;AAW9D,IAAI,gBAAgB;AAEpB,MAAM,kBAAkB,CAAC,SAAiB;AACzC,MAAI,kBAAkB,QAAW;AAChC,oBAAgB;AAChB,WAAO;AAAA,EACR;AAEA,MAAI,OAAO,gBAAgB,OAAO,OAAO,gBAAgB,KAAK;AAC7D,oBAAgB;AAChB,WAAO;AAAA,EACR;AAEA,kBAAgB;AAChB,SAAO;AACR;AAEO,SAAS,iBAAiB,KAAsC;AACtE,QAAM,aAAS,4BAAU;AAEzB,QAAM,SAAS,MAAM,QAAQ,MAAM;AAClC,QAAI,aAAa;AAEjB,UAAM,UAAwC,CAAC,EAAE,MAAM,MAAM;AAC5D,UAAI,CAAC,OAAO,iBAAiB,EAAE,WAAW;AACzC;AAAA,MACD;AAEA,mBAAa;AAEb,UAAI,gBAAgB,KAAK,IAAI,CAAC,GAAG;AAEhC;AAAA,MACD;AAOA,YAAM,iBAAiB,OAAO,kBAAkB;AAChD,UAAI,gBAAgB;AACnB,cAAM,QAAQ,OAAO,SAAS,cAAc;AAC5C,YAAI,OAAO;AACV,gBAAM,OAAO,OAAO,aAAa,KAAK;AACtC,cAAI,KAAK,UAAU,KAAK,GAAG;AAC1B,kBAAM,SAAS,OAAO,mBAAmB,cAAc;AACvD,gBAAI,QAAQ,cAAc,OAAO,OAAO,gBAAgB,GAAG;AAC1D;AAAA,YACD;AAAA,UACD;AAAA,QACD;AAAA,MACD;AAEA,qCAAe,KAAK;AACpB,2CAAqB,KAAK;AAC1B,YAAM,YAAQ,sCAAe,KAAK;AAElC,UAAI,MAAM,MAAM,KAAK,MAAM,MAAM,EAAG;AAEpC,YAAM,OAAyB;AAAA,QAC9B,MAAM;AAAA,QACN,MAAM;AAAA,QACN;AAAA,QACA,OAAO,IAAI,eAAI,MAAM,SAAS,MAAM,OAAO;AAAA,QAC3C,UAAU,MAAM;AAAA,QAChB,QAAQ,MAAM;AAAA,QACd,SAAS,MAAM,WAAW,MAAM;AAAA,QAChC,SAAS,MAAM;AAAA,QACf,cAAU,4BAAW,KAAK;AAAA,MAC3B;AAEA,aAAO,SAAS,IAAI;AAAA,IACrB;AAEA,QAAI,6BAA6B;AACjC,QAAI,WAAW;AACf,QAAI,
|
|
4
|
+
"sourcesContent": ["import type { AnyHandlerEventTypes, EventTypes, GestureKey, Handler } from '@use-gesture/core/types'\nimport { createUseGesture, pinchAction, wheelAction } from '@use-gesture/react'\nimport * as React from 'react'\nimport { TLWheelEventInfo } from '../editor/types/event-types'\nimport { Vec } from '../primitives/Vec'\nimport { preventDefault, stopEventPropagation } from '../utils/dom'\nimport { isAccelKey } from '../utils/keyboard'\nimport { normalizeWheel } from '../utils/normalizeWheel'\nimport { useEditor } from './useEditor'\n\n/*\n\n# How does pinching work?\n\nThe pinching handler is fired under two circumstances: \n- when a user is on a MacBook trackpad and is ZOOMING with a two-finger pinch\n- when a user is on a touch device and is ZOOMING with a two-finger pinch\n- when a user is on a touch device and is PANNING with two fingers\n\nZooming is much more expensive than panning (because it causes shapes to render), \nso we want to be sure that we don't zoom while two-finger panning. \n\nIn order to do this, we keep track of a \"pinchState\", which is either:\n- \"zooming\"\n- \"panning\"\n- \"not sure\"\n\nIf a user is on a trackpad, the pinchState will be set to \"zooming\". \n\nIf the user is on a touch screen, then we start in the \"not sure\" state and switch back and forth\nbetween \"zooming\", \"panning\", and \"not sure\" based on what the user is doing with their fingers.\n\nIn the \"not sure\" state, we examine whether the user has moved the center of the gesture far enough\nto suggest that they're panning; or else that they've moved their fingers further apart or closer\ntogether enough to suggest that they're zooming. \n\nIn the \"panning\" state, we check whether the user's fingers have moved far enough apart to suggest\nthat they're zooming. If they have, we switch to the \"zooming\" state.\n\nIn the \"zooming\" state, we just stay zooming\u2014it's not YET possible to switch back to panning.\n\ntodo: compare velocities of change in order to determine whether the user has switched back to panning\n*/\n\ntype check<T extends AnyHandlerEventTypes, Key extends GestureKey> = undefined extends T[Key]\n\t? EventTypes[Key]\n\t: T[Key]\ntype PinchHandler = Handler<'pinch', check<EventTypes, 'pinch'>>\n\nconst useGesture = createUseGesture([wheelAction, pinchAction])\n\n/**\n * GOTCHA\n *\n * UseGesture fires a wheel event 140ms after the gesture actually ends, with a momentum-adjusted\n * delta. This creates a messed up interaction where after you stop scrolling suddenly the dang page\n * jumps a tick. why do they do this? you are asking the wrong person. it seems intentional though.\n * anyway we want to ignore that last event, but there's no way to directly detect it so we need to\n * keep track of timestamps. Yes this is awful, I am sorry.\n */\nlet lastWheelTime = undefined as undefined | number\n\nconst isWheelEndEvent = (time: number) => {\n\tif (lastWheelTime === undefined) {\n\t\tlastWheelTime = time\n\t\treturn false\n\t}\n\n\tif (time - lastWheelTime > 120 && time - lastWheelTime < 160) {\n\t\tlastWheelTime = time\n\t\treturn true\n\t}\n\n\tlastWheelTime = time\n\treturn false\n}\n\nexport function useGestureEvents(ref: React.RefObject<HTMLDivElement>) {\n\tconst editor = useEditor()\n\n\tconst events = React.useMemo(() => {\n\t\tlet pinchState = 'not sure' as 'not sure' | 'zooming' | 'panning'\n\n\t\tconst onWheel: Handler<'wheel', WheelEvent> = ({ event }) => {\n\t\t\tif (!editor.getInstanceState().isFocused) {\n\t\t\t\treturn\n\t\t\t}\n\n\t\t\tpinchState = 'not sure'\n\n\t\t\tif (isWheelEndEvent(Date.now())) {\n\t\t\t\t// ignore wheelEnd events\n\t\t\t\treturn\n\t\t\t}\n\n\t\t\t// Awful tht we need to put this logic here, but basically\n\t\t\t// we don't want to handle the the wheel event (or call prevent\n\t\t\t// default on the evnet) if the user is wheeling over an a shape\n\t\t\t// that is scrollable which they're currently editing.\n\n\t\t\tconst editingShapeId = editor.getEditingShapeId()\n\t\t\tif (editingShapeId) {\n\t\t\t\tconst shape = editor.getShape(editingShapeId)\n\t\t\t\tif (shape) {\n\t\t\t\t\tconst util = editor.getShapeUtil(shape)\n\t\t\t\t\tif (util.canScroll(shape)) {\n\t\t\t\t\t\tconst bounds = editor.getShapePageBounds(editingShapeId)\n\t\t\t\t\t\tif (bounds?.containsPoint(editor.inputs.currentPagePoint)) {\n\t\t\t\t\t\t\treturn\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tpreventDefault(event)\n\t\t\tstopEventPropagation(event)\n\t\t\tconst delta = normalizeWheel(event)\n\n\t\t\tif (delta.x === 0 && delta.y === 0) return\n\n\t\t\tconst info: TLWheelEventInfo = {\n\t\t\t\ttype: 'wheel',\n\t\t\t\tname: 'wheel',\n\t\t\t\tdelta,\n\t\t\t\tpoint: new Vec(event.clientX, event.clientY),\n\t\t\t\tshiftKey: event.shiftKey,\n\t\t\t\taltKey: event.altKey,\n\t\t\t\tctrlKey: event.metaKey || event.ctrlKey,\n\t\t\t\tmetaKey: event.metaKey,\n\t\t\t\taccelKey: isAccelKey(event),\n\t\t\t}\n\n\t\t\teditor.dispatch(info)\n\t\t}\n\n\t\tlet initDistanceBetweenFingers = 1 // the distance between the two fingers when the pinch starts\n\t\tlet initZoom = 1 // the browser's zoom level when the pinch starts\n\t\tlet currDistanceBetweenFingers = 0\n\t\tconst initPointBetweenFingers = new Vec()\n\t\tconst prevPointBetweenFingers = new Vec()\n\n\t\tconst onPinchStart: PinchHandler = (gesture) => {\n\t\t\tconst elm = ref.current\n\t\t\tpinchState = 'not sure'\n\n\t\t\tconst { event, origin, da } = gesture\n\n\t\t\tif (event instanceof WheelEvent) return\n\t\t\tif (!(event.target === elm || elm?.contains(event.target as Node))) return\n\n\t\t\tprevPointBetweenFingers.x = origin[0]\n\t\t\tprevPointBetweenFingers.y = origin[1]\n\t\t\tinitPointBetweenFingers.x = origin[0]\n\t\t\tinitPointBetweenFingers.y = origin[1]\n\t\t\tinitDistanceBetweenFingers = da[0]\n\t\t\tinitZoom = editor.getZoomLevel()\n\n\t\t\teditor.dispatch({\n\t\t\t\ttype: 'pinch',\n\t\t\t\tname: 'pinch_start',\n\t\t\t\tpoint: { x: origin[0], y: origin[1], z: editor.getZoomLevel() },\n\t\t\t\tdelta: { x: 0, y: 0 },\n\t\t\t\tshiftKey: event.shiftKey,\n\t\t\t\taltKey: event.altKey,\n\t\t\t\tctrlKey: event.metaKey || event.ctrlKey,\n\t\t\t\tmetaKey: event.metaKey,\n\t\t\t\taccelKey: isAccelKey(event),\n\t\t\t})\n\t\t}\n\n\t\t// let timeout: any\n\t\tconst updatePinchState = (isSafariTrackpadPinch: boolean) => {\n\t\t\tif (isSafariTrackpadPinch) {\n\t\t\t\tpinchState = 'zooming'\n\t\t\t}\n\n\t\t\tif (pinchState === 'zooming') {\n\t\t\t\treturn\n\t\t\t}\n\n\t\t\t// Initial: [touch]-------origin-------[touch]\n\t\t\t// Current: [touch]-----------origin----------[touch]\n\t\t\t// |----| |------------|\n\t\t\t// originDistance ^ ^ touchDistance\n\n\t\t\t// How far have the two touch points moved towards or away from eachother?\n\t\t\tconst touchDistance = Math.abs(currDistanceBetweenFingers - initDistanceBetweenFingers)\n\t\t\t// How far has the point between the touches moved?\n\t\t\tconst originDistance = Vec.Dist(initPointBetweenFingers, prevPointBetweenFingers)\n\n\t\t\tswitch (pinchState) {\n\t\t\t\tcase 'not sure': {\n\t\t\t\t\tif (touchDistance > 24) {\n\t\t\t\t\t\tpinchState = 'zooming'\n\t\t\t\t\t} else if (originDistance > 16) {\n\t\t\t\t\t\tpinchState = 'panning'\n\t\t\t\t\t}\n\t\t\t\t\tbreak\n\t\t\t\t}\n\t\t\t\tcase 'panning': {\n\t\t\t\t\t// Slightly more touch distance needed to go from panning to zooming\n\t\t\t\t\tif (touchDistance > 64) {\n\t\t\t\t\t\tpinchState = 'zooming'\n\t\t\t\t\t}\n\t\t\t\t\tbreak\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tconst onPinch: PinchHandler = (gesture) => {\n\t\t\tconst elm = ref.current\n\t\t\tconst { event, origin, offset, da } = gesture\n\n\t\t\tif (event instanceof WheelEvent) return\n\t\t\tif (!(event.target === elm || elm?.contains(event.target as Node))) return\n\n\t\t\t// In (desktop) Safari, a two finger trackpad pinch will be a \"gesturechange\" event\n\t\t\t// and will have 0 touches; on iOS, a two-finger pinch will be a \"pointermove\" event\n\t\t\t// with two touches.\n\t\t\tconst isSafariTrackpadPinch =\n\t\t\t\tgesture.type === 'gesturechange' || gesture.type === 'gestureend'\n\n\t\t\t// The distance between the two touch points\n\t\t\tcurrDistanceBetweenFingers = da[0]\n\n\t\t\t// Only update the zoom if the pointers are far enough apart;\n\t\t\t// a very small touchDistance means that the user has probably\n\t\t\t// pinched out and their fingers are touching; this produces\n\t\t\t// very unstable zooming behavior.\n\n\t\t\tconst dx = origin[0] - prevPointBetweenFingers.x\n\t\t\tconst dy = origin[1] - prevPointBetweenFingers.y\n\n\t\t\tprevPointBetweenFingers.x = origin[0]\n\t\t\tprevPointBetweenFingers.y = origin[1]\n\n\t\t\tupdatePinchState(isSafariTrackpadPinch)\n\n\t\t\tswitch (pinchState) {\n\t\t\t\tcase 'zooming': {\n\t\t\t\t\tconst currZoom = offset[0] ** editor.getCameraOptions().zoomSpeed\n\n\t\t\t\t\teditor.dispatch({\n\t\t\t\t\t\ttype: 'pinch',\n\t\t\t\t\t\tname: 'pinch',\n\t\t\t\t\t\tpoint: { x: origin[0], y: origin[1], z: currZoom },\n\t\t\t\t\t\tdelta: { x: dx, y: dy },\n\t\t\t\t\t\tshiftKey: event.shiftKey,\n\t\t\t\t\t\taltKey: event.altKey,\n\t\t\t\t\t\tctrlKey: event.metaKey || event.ctrlKey,\n\t\t\t\t\t\tmetaKey: event.metaKey,\n\t\t\t\t\t\taccelKey: isAccelKey(event),\n\t\t\t\t\t})\n\t\t\t\t\tbreak\n\t\t\t\t}\n\t\t\t\tcase 'panning': {\n\t\t\t\t\teditor.dispatch({\n\t\t\t\t\t\ttype: 'pinch',\n\t\t\t\t\t\tname: 'pinch',\n\t\t\t\t\t\tpoint: { x: origin[0], y: origin[1], z: initZoom },\n\t\t\t\t\t\tdelta: { x: dx, y: dy },\n\t\t\t\t\t\tshiftKey: event.shiftKey,\n\t\t\t\t\t\taltKey: event.altKey,\n\t\t\t\t\t\tctrlKey: event.metaKey || event.ctrlKey,\n\t\t\t\t\t\tmetaKey: event.metaKey,\n\t\t\t\t\t\taccelKey: isAccelKey(event),\n\t\t\t\t\t})\n\t\t\t\t\tbreak\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tconst onPinchEnd: PinchHandler = (gesture) => {\n\t\t\tconst elm = ref.current\n\t\t\tconst { event, origin, offset } = gesture\n\n\t\t\tif (event instanceof WheelEvent) return\n\t\t\tif (!(event.target === elm || elm?.contains(event.target as Node))) return\n\n\t\t\tconst scale = offset[0] ** editor.getCameraOptions().zoomSpeed\n\n\t\t\tpinchState = 'not sure'\n\n\t\t\teditor.timers.requestAnimationFrame(() => {\n\t\t\t\teditor.dispatch({\n\t\t\t\t\ttype: 'pinch',\n\t\t\t\t\tname: 'pinch_end',\n\t\t\t\t\tpoint: { x: origin[0], y: origin[1], z: scale },\n\t\t\t\t\tdelta: { x: origin[0], y: origin[1] },\n\t\t\t\t\tshiftKey: event.shiftKey,\n\t\t\t\t\taltKey: event.altKey,\n\t\t\t\t\tctrlKey: event.metaKey || event.ctrlKey,\n\t\t\t\t\tmetaKey: event.metaKey,\n\t\t\t\t\taccelKey: isAccelKey(event),\n\t\t\t\t})\n\t\t\t})\n\t\t}\n\n\t\treturn {\n\t\t\tonWheel,\n\t\t\tonPinchStart,\n\t\t\tonPinchEnd,\n\t\t\tonPinch,\n\t\t}\n\t}, [editor, ref])\n\n\tuseGesture(events, {\n\t\ttarget: ref,\n\t\teventOptions: { passive: false },\n\t\tpinch: {\n\t\t\tfrom: () => {\n\t\t\t\tconst { zoomSpeed } = editor.getCameraOptions()\n\t\t\t\tconst level = editor.getZoomLevel() ** (1 / zoomSpeed)\n\t\t\t\treturn [level, 0]\n\t\t\t}, // Return the camera z to use when pinch starts\n\t\t\tscaleBounds: () => {\n\t\t\t\tconst baseZoom = editor.getBaseZoom()\n\t\t\t\tconst { zoomSteps, zoomSpeed } = editor.getCameraOptions()\n\t\t\t\tconst zoomMin = zoomSteps[0] * baseZoom\n\t\t\t\tconst zoomMax = zoomSteps[zoomSteps.length - 1] * baseZoom\n\n\t\t\t\treturn {\n\t\t\t\t\tmax: zoomMax ** (1 / zoomSpeed),\n\t\t\t\t\tmin: zoomMin ** (1 / zoomSpeed),\n\t\t\t\t}\n\t\t\t},\n\t\t},\n\t})\n}\n"],
|
|
5
|
+
"mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AACA,mBAA2D;AAC3D,YAAuB;AAEvB,iBAAoB;AACpB,iBAAqD;AACrD,sBAA2B;AAC3B,4BAA+B;AAC/B,uBAA0B;AAyC1B,MAAM,iBAAa,+BAAiB,CAAC,0BAAa,wBAAW,CAAC;AAW9D,IAAI,gBAAgB;AAEpB,MAAM,kBAAkB,CAAC,SAAiB;AACzC,MAAI,kBAAkB,QAAW;AAChC,oBAAgB;AAChB,WAAO;AAAA,EACR;AAEA,MAAI,OAAO,gBAAgB,OAAO,OAAO,gBAAgB,KAAK;AAC7D,oBAAgB;AAChB,WAAO;AAAA,EACR;AAEA,kBAAgB;AAChB,SAAO;AACR;AAEO,SAAS,iBAAiB,KAAsC;AACtE,QAAM,aAAS,4BAAU;AAEzB,QAAM,SAAS,MAAM,QAAQ,MAAM;AAClC,QAAI,aAAa;AAEjB,UAAM,UAAwC,CAAC,EAAE,MAAM,MAAM;AAC5D,UAAI,CAAC,OAAO,iBAAiB,EAAE,WAAW;AACzC;AAAA,MACD;AAEA,mBAAa;AAEb,UAAI,gBAAgB,KAAK,IAAI,CAAC,GAAG;AAEhC;AAAA,MACD;AAOA,YAAM,iBAAiB,OAAO,kBAAkB;AAChD,UAAI,gBAAgB;AACnB,cAAM,QAAQ,OAAO,SAAS,cAAc;AAC5C,YAAI,OAAO;AACV,gBAAM,OAAO,OAAO,aAAa,KAAK;AACtC,cAAI,KAAK,UAAU,KAAK,GAAG;AAC1B,kBAAM,SAAS,OAAO,mBAAmB,cAAc;AACvD,gBAAI,QAAQ,cAAc,OAAO,OAAO,gBAAgB,GAAG;AAC1D;AAAA,YACD;AAAA,UACD;AAAA,QACD;AAAA,MACD;AAEA,qCAAe,KAAK;AACpB,2CAAqB,KAAK;AAC1B,YAAM,YAAQ,sCAAe,KAAK;AAElC,UAAI,MAAM,MAAM,KAAK,MAAM,MAAM,EAAG;AAEpC,YAAM,OAAyB;AAAA,QAC9B,MAAM;AAAA,QACN,MAAM;AAAA,QACN;AAAA,QACA,OAAO,IAAI,eAAI,MAAM,SAAS,MAAM,OAAO;AAAA,QAC3C,UAAU,MAAM;AAAA,QAChB,QAAQ,MAAM;AAAA,QACd,SAAS,MAAM,WAAW,MAAM;AAAA,QAChC,SAAS,MAAM;AAAA,QACf,cAAU,4BAAW,KAAK;AAAA,MAC3B;AAEA,aAAO,SAAS,IAAI;AAAA,IACrB;AAEA,QAAI,6BAA6B;AACjC,QAAI,WAAW;AACf,QAAI,6BAA6B;AACjC,UAAM,0BAA0B,IAAI,eAAI;AACxC,UAAM,0BAA0B,IAAI,eAAI;AAExC,UAAM,eAA6B,CAAC,YAAY;AAC/C,YAAM,MAAM,IAAI;AAChB,mBAAa;AAEb,YAAM,EAAE,OAAO,QAAQ,GAAG,IAAI;AAE9B,UAAI,iBAAiB,WAAY;AACjC,UAAI,EAAE,MAAM,WAAW,OAAO,KAAK,SAAS,MAAM,MAAc,GAAI;AAEpE,8BAAwB,IAAI,OAAO,CAAC;AACpC,8BAAwB,IAAI,OAAO,CAAC;AACpC,8BAAwB,IAAI,OAAO,CAAC;AACpC,8BAAwB,IAAI,OAAO,CAAC;AACpC,mCAA6B,GAAG,CAAC;AACjC,iBAAW,OAAO,aAAa;AAE/B,aAAO,SAAS;AAAA,QACf,MAAM;AAAA,QACN,MAAM;AAAA,QACN,OAAO,EAAE,GAAG,OAAO,CAAC,GAAG,GAAG,OAAO,CAAC,GAAG,GAAG,OAAO,aAAa,EAAE;AAAA,QAC9D,OAAO,EAAE,GAAG,GAAG,GAAG,EAAE;AAAA,QACpB,UAAU,MAAM;AAAA,QAChB,QAAQ,MAAM;AAAA,QACd,SAAS,MAAM,WAAW,MAAM;AAAA,QAChC,SAAS,MAAM;AAAA,QACf,cAAU,4BAAW,KAAK;AAAA,MAC3B,CAAC;AAAA,IACF;AAGA,UAAM,mBAAmB,CAAC,0BAAmC;AAC5D,UAAI,uBAAuB;AAC1B,qBAAa;AAAA,MACd;AAEA,UAAI,eAAe,WAAW;AAC7B;AAAA,MACD;AAQA,YAAM,gBAAgB,KAAK,IAAI,6BAA6B,0BAA0B;AAEtF,YAAM,iBAAiB,eAAI,KAAK,yBAAyB,uBAAuB;AAEhF,cAAQ,YAAY;AAAA,QACnB,KAAK,YAAY;AAChB,cAAI,gBAAgB,IAAI;AACvB,yBAAa;AAAA,UACd,WAAW,iBAAiB,IAAI;AAC/B,yBAAa;AAAA,UACd;AACA;AAAA,QACD;AAAA,QACA,KAAK,WAAW;AAEf,cAAI,gBAAgB,IAAI;AACvB,yBAAa;AAAA,UACd;AACA;AAAA,QACD;AAAA,MACD;AAAA,IACD;AAEA,UAAM,UAAwB,CAAC,YAAY;AAC1C,YAAM,MAAM,IAAI;AAChB,YAAM,EAAE,OAAO,QAAQ,QAAQ,GAAG,IAAI;AAEtC,UAAI,iBAAiB,WAAY;AACjC,UAAI,EAAE,MAAM,WAAW,OAAO,KAAK,SAAS,MAAM,MAAc,GAAI;AAKpE,YAAM,wBACL,QAAQ,SAAS,mBAAmB,QAAQ,SAAS;AAGtD,mCAA6B,GAAG,CAAC;AAOjC,YAAM,KAAK,OAAO,CAAC,IAAI,wBAAwB;AAC/C,YAAM,KAAK,OAAO,CAAC,IAAI,wBAAwB;AAE/C,8BAAwB,IAAI,OAAO,CAAC;AACpC,8BAAwB,IAAI,OAAO,CAAC;AAEpC,uBAAiB,qBAAqB;AAEtC,cAAQ,YAAY;AAAA,QACnB,KAAK,WAAW;AACf,gBAAM,WAAW,OAAO,CAAC,KAAK,OAAO,iBAAiB,EAAE;AAExD,iBAAO,SAAS;AAAA,YACf,MAAM;AAAA,YACN,MAAM;AAAA,YACN,OAAO,EAAE,GAAG,OAAO,CAAC,GAAG,GAAG,OAAO,CAAC,GAAG,GAAG,SAAS;AAAA,YACjD,OAAO,EAAE,GAAG,IAAI,GAAG,GAAG;AAAA,YACtB,UAAU,MAAM;AAAA,YAChB,QAAQ,MAAM;AAAA,YACd,SAAS,MAAM,WAAW,MAAM;AAAA,YAChC,SAAS,MAAM;AAAA,YACf,cAAU,4BAAW,KAAK;AAAA,UAC3B,CAAC;AACD;AAAA,QACD;AAAA,QACA,KAAK,WAAW;AACf,iBAAO,SAAS;AAAA,YACf,MAAM;AAAA,YACN,MAAM;AAAA,YACN,OAAO,EAAE,GAAG,OAAO,CAAC,GAAG,GAAG,OAAO,CAAC,GAAG,GAAG,SAAS;AAAA,YACjD,OAAO,EAAE,GAAG,IAAI,GAAG,GAAG;AAAA,YACtB,UAAU,MAAM;AAAA,YAChB,QAAQ,MAAM;AAAA,YACd,SAAS,MAAM,WAAW,MAAM;AAAA,YAChC,SAAS,MAAM;AAAA,YACf,cAAU,4BAAW,KAAK;AAAA,UAC3B,CAAC;AACD;AAAA,QACD;AAAA,MACD;AAAA,IACD;AAEA,UAAM,aAA2B,CAAC,YAAY;AAC7C,YAAM,MAAM,IAAI;AAChB,YAAM,EAAE,OAAO,QAAQ,OAAO,IAAI;AAElC,UAAI,iBAAiB,WAAY;AACjC,UAAI,EAAE,MAAM,WAAW,OAAO,KAAK,SAAS,MAAM,MAAc,GAAI;AAEpE,YAAM,QAAQ,OAAO,CAAC,KAAK,OAAO,iBAAiB,EAAE;AAErD,mBAAa;AAEb,aAAO,OAAO,sBAAsB,MAAM;AACzC,eAAO,SAAS;AAAA,UACf,MAAM;AAAA,UACN,MAAM;AAAA,UACN,OAAO,EAAE,GAAG,OAAO,CAAC,GAAG,GAAG,OAAO,CAAC,GAAG,GAAG,MAAM;AAAA,UAC9C,OAAO,EAAE,GAAG,OAAO,CAAC,GAAG,GAAG,OAAO,CAAC,EAAE;AAAA,UACpC,UAAU,MAAM;AAAA,UAChB,QAAQ,MAAM;AAAA,UACd,SAAS,MAAM,WAAW,MAAM;AAAA,UAChC,SAAS,MAAM;AAAA,UACf,cAAU,4BAAW,KAAK;AAAA,QAC3B,CAAC;AAAA,MACF,CAAC;AAAA,IACF;AAEA,WAAO;AAAA,MACN;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACD;AAAA,EACD,GAAG,CAAC,QAAQ,GAAG,CAAC;AAEhB,aAAW,QAAQ;AAAA,IAClB,QAAQ;AAAA,IACR,cAAc,EAAE,SAAS,MAAM;AAAA,IAC/B,OAAO;AAAA,MACN,MAAM,MAAM;AACX,cAAM,EAAE,UAAU,IAAI,OAAO,iBAAiB;AAC9C,cAAM,QAAQ,OAAO,aAAa,MAAM,IAAI;AAC5C,eAAO,CAAC,OAAO,CAAC;AAAA,MACjB;AAAA;AAAA,MACA,aAAa,MAAM;AAClB,cAAM,WAAW,OAAO,YAAY;AACpC,cAAM,EAAE,WAAW,UAAU,IAAI,OAAO,iBAAiB;AACzD,cAAM,UAAU,UAAU,CAAC,IAAI;AAC/B,cAAM,UAAU,UAAU,UAAU,SAAS,CAAC,IAAI;AAElD,eAAO;AAAA,UACN,KAAK,YAAY,IAAI;AAAA,UACrB,KAAK,YAAY,IAAI;AAAA,QACtB;AAAA,MACD;AAAA,IACD;AAAA,EACD,CAAC;AACF;",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -24,7 +24,6 @@ module.exports = __toCommonJS(Watermark_exports);
|
|
|
24
24
|
var import_jsx_runtime = require("react/jsx-runtime");
|
|
25
25
|
var import_state_react = require("@tldraw/state-react");
|
|
26
26
|
var import_react = require("react");
|
|
27
|
-
var import_environment = require("../globals/environment");
|
|
28
27
|
var import_useCanvasEvents = require("../hooks/useCanvasEvents");
|
|
29
28
|
var import_useEditor = require("../hooks/useEditor");
|
|
30
29
|
var import_usePassThroughWheelEvents = require("../hooks/usePassThroughWheelEvents");
|
|
@@ -69,8 +68,8 @@ const WatermarkInner = (0, import_react.memo)(function WatermarkInner2({ src })
|
|
|
69
68
|
"data-mobile": isMobile,
|
|
70
69
|
draggable: false,
|
|
71
70
|
...events,
|
|
72
|
-
children:
|
|
73
|
-
"
|
|
71
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
72
|
+
"button",
|
|
74
73
|
{
|
|
75
74
|
draggable: false,
|
|
76
75
|
role: "button",
|
|
@@ -78,21 +77,10 @@ const WatermarkInner = (0, import_react.memo)(function WatermarkInner2({ src })
|
|
|
78
77
|
(0, import_dom.stopEventPropagation)(e);
|
|
79
78
|
(0, import_dom.preventDefault)(e);
|
|
80
79
|
},
|
|
80
|
+
title: "made with tldraw",
|
|
81
81
|
onClick: () => import_runtime.runtime.openWindow(url, "_blank"),
|
|
82
82
|
style: { mask: maskCss, WebkitMask: maskCss }
|
|
83
83
|
}
|
|
84
|
-
) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
85
|
-
"a",
|
|
86
|
-
{
|
|
87
|
-
href: url,
|
|
88
|
-
target: "_blank",
|
|
89
|
-
rel: "noreferrer",
|
|
90
|
-
draggable: false,
|
|
91
|
-
onPointerDown: (e) => {
|
|
92
|
-
(0, import_dom.stopEventPropagation)(e);
|
|
93
|
-
},
|
|
94
|
-
style: { mask: maskCss, WebkitMask: maskCss }
|
|
95
|
-
}
|
|
96
84
|
)
|
|
97
85
|
}
|
|
98
86
|
);
|
|
@@ -127,7 +115,7 @@ To remove the watermark, please purchase a license at tldraw.dev.
|
|
|
127
115
|
box-sizing: content-box;
|
|
128
116
|
}
|
|
129
117
|
|
|
130
|
-
.${className} >
|
|
118
|
+
.${className} > button {
|
|
131
119
|
position: absolute;
|
|
132
120
|
width: 96px;
|
|
133
121
|
height: 32px;
|
|
@@ -135,6 +123,8 @@ To remove the watermark, please purchase a license at tldraw.dev.
|
|
|
135
123
|
cursor: inherit;
|
|
136
124
|
color: var(--color-text);
|
|
137
125
|
opacity: .38;
|
|
126
|
+
border: 0;
|
|
127
|
+
padding: 0;
|
|
138
128
|
background-color: currentColor;
|
|
139
129
|
}
|
|
140
130
|
|
|
@@ -149,13 +139,13 @@ To remove the watermark, please purchase a license at tldraw.dev.
|
|
|
149
139
|
height: 48px;
|
|
150
140
|
}
|
|
151
141
|
|
|
152
|
-
.${className}[data-mobile='true'] >
|
|
142
|
+
.${className}[data-mobile='true'] > button {
|
|
153
143
|
width: 8px;
|
|
154
144
|
height: 32px;
|
|
155
145
|
}
|
|
156
146
|
|
|
157
147
|
@media (hover: hover) {
|
|
158
|
-
.${className} >
|
|
148
|
+
.${className} > button {
|
|
159
149
|
pointer-events: none;
|
|
160
150
|
}
|
|
161
151
|
|
|
@@ -165,12 +155,12 @@ To remove the watermark, please purchase a license at tldraw.dev.
|
|
|
165
155
|
transition-delay: 0.32s;
|
|
166
156
|
}
|
|
167
157
|
|
|
168
|
-
.${className}:hover >
|
|
158
|
+
.${className}:hover > button {
|
|
169
159
|
animation: delayed_link 0.2s forwards ease-in-out;
|
|
170
160
|
animation-delay: 0.32s;
|
|
171
161
|
}
|
|
172
162
|
|
|
173
|
-
.${className} >
|
|
163
|
+
.${className} > button:focus-visible {
|
|
174
164
|
opacity: 1;
|
|
175
165
|
}
|
|
176
166
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../src/lib/license/Watermark.tsx"],
|
|
4
|
-
"sourcesContent": ["import { useValue } from '@tldraw/state-react'\nimport { memo, useRef } from 'react'\nimport {
|
|
5
|
-
"mappings": ";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;
|
|
4
|
+
"sourcesContent": ["import { useValue } from '@tldraw/state-react'\nimport { memo, useRef } from 'react'\nimport { useCanvasEvents } from '../hooks/useCanvasEvents'\nimport { useEditor } from '../hooks/useEditor'\nimport { usePassThroughWheelEvents } from '../hooks/usePassThroughWheelEvents'\nimport { preventDefault, stopEventPropagation } from '../utils/dom'\nimport { runtime } from '../utils/runtime'\nimport { watermarkDesktopSvg, watermarkMobileSvg } from '../watermarks'\nimport { LicenseManager } from './LicenseManager'\nimport { useLicenseContext } from './LicenseProvider'\nimport { useLicenseManagerState } from './useLicenseManagerState'\n\nconst WATERMARK_DESKTOP_LOCAL_SRC = `data:image/svg+xml;utf8,${encodeURIComponent(watermarkDesktopSvg)}`\nconst WATERMARK_MOBILE_LOCAL_SRC = `data:image/svg+xml;utf8,${encodeURIComponent(watermarkMobileSvg)}`\n\n/** @internal */\nexport const Watermark = memo(function Watermark() {\n\tconst licenseManager = useLicenseContext()\n\tconst editor = useEditor()\n\tconst isMobile = useValue('is mobile', () => editor.getViewportScreenBounds().width < 700, [\n\t\teditor,\n\t])\n\n\tconst licenseManagerState = useLicenseManagerState(licenseManager)\n\n\tif (!['licensed-with-watermark', 'unlicensed'].includes(licenseManagerState)) return null\n\n\treturn (\n\t\t<>\n\t\t\t<LicenseStyles />\n\t\t\t<WatermarkInner src={isMobile ? WATERMARK_MOBILE_LOCAL_SRC : WATERMARK_DESKTOP_LOCAL_SRC} />\n\t\t</>\n\t)\n})\n\nconst WatermarkInner = memo(function WatermarkInner({ src }: { src: string }) {\n\tconst editor = useEditor()\n\tconst isDebugMode = useValue('debug mode', () => editor.getInstanceState().isDebugMode, [editor])\n\tconst isMobile = useValue('is mobile', () => editor.getViewportScreenBounds().width < 700, [\n\t\teditor,\n\t])\n\tconst events = useCanvasEvents()\n\n\tconst ref = useRef<HTMLDivElement>(null)\n\tusePassThroughWheelEvents(ref)\n\n\tconst maskCss = `url('${src}') center 100% / 100% no-repeat`\n\tconst url = 'https://tldraw.dev/?utm_source=dotcom&utm_medium=organic&utm_campaign=watermark'\n\n\treturn (\n\t\t<div\n\t\t\tref={ref}\n\t\t\tclassName={LicenseManager.className}\n\t\t\tdata-debug={isDebugMode}\n\t\t\tdata-mobile={isMobile}\n\t\t\tdraggable={false}\n\t\t\t{...events}\n\t\t>\n\t\t\t<button\n\t\t\t\tdraggable={false}\n\t\t\t\trole=\"button\"\n\t\t\t\tonPointerDown={(e) => {\n\t\t\t\t\tstopEventPropagation(e)\n\t\t\t\t\tpreventDefault(e)\n\t\t\t\t}}\n\t\t\t\ttitle=\"made with tldraw\"\n\t\t\t\tonClick={() => runtime.openWindow(url, '_blank')}\n\t\t\t\tstyle={{ mask: maskCss, WebkitMask: maskCss }}\n\t\t\t/>\n\t\t</div>\n\t)\n})\n\nconst LicenseStyles = memo(function LicenseStyles() {\n\tconst editor = useEditor()\n\tconst className = LicenseManager.className\n\n\tconst CSS = `/* ------------------- SEE LICENSE -------------------\nThe tldraw watermark is part of tldraw's license. It is shown for unlicensed\nor \"licensed-with-watermark\" users. By using this library, you agree to\npreserve the watermark's behavior, keeping it visible, unobscured, and\navailable to user-interaction.\n\nTo remove the watermark, please purchase a license at tldraw.dev.\n*/\n\n\t.${className} {\n\t\tposition: absolute;\n\t\tbottom: var(--space-2);\n\t\tright: var(--space-2);\n\t\twidth: 96px;\n\t\theight: 32px;\n\t\tdisplay: flex;\n\t\talign-items: center;\n\t\tjustify-content: center;\n\t\tz-index: var(--layer-watermark) !important;\n\t\tbackground-color: color-mix(in srgb, var(--color-background) 62%, transparent);\n\t\topacity: 1;\n\t\tborder-radius: 5px;\n\t\tpointer-events: all;\n\t\tpadding: 2px;\n\t\tbox-sizing: content-box;\n\t}\n\n\t.${className} > button {\n\t\tposition: absolute;\n\t\twidth: 96px;\n\t\theight: 32px;\n\t\tpointer-events: all;\n\t\tcursor: inherit;\n\t\tcolor: var(--color-text);\n\t\topacity: .38;\n\t\tborder: 0;\n\t\tpadding: 0;\n\t\tbackground-color: currentColor;\n\t}\n\n\t.${className}[data-debug='true'] {\n\t\tbottom: 46px;\n\t}\n\n\t.${className}[data-mobile='true'] {\n\t\tborder-radius: 4px 0px 0px 4px;\n\t\tright: -2px;\n\t\twidth: 8px;\n\t\theight: 48px;\n\t}\n\n\t.${className}[data-mobile='true'] > button {\n\t\twidth: 8px;\n\t\theight: 32px;\n\t}\n\n\t@media (hover: hover) {\n\t\t.${className} > button {\n\t\t\tpointer-events: none;\n\t\t}\n\n\t\t.${className}:hover {\n\t\t\tbackground-color: var(--color-background);\n\t\t\ttransition: background-color 0.2s ease-in-out;\n\t\t\ttransition-delay: 0.32s;\n\t\t}\n\n\t\t.${className}:hover > button {\n\t\t\tanimation: delayed_link 0.2s forwards ease-in-out;\n\t\t\tanimation-delay: 0.32s;\n\t\t}\n\n\t\t.${className} > button:focus-visible {\n\t\t\topacity: 1;\n\t\t}\n\t}\n\n\n\t@keyframes delayed_link {\n\t\t0% {\n\t\t\tcursor: inherit;\n\t\t\topacity: .38;\n\t\t\tpointer-events: none;\n\t\t}\n\t\t100% {\n\t\t\tcursor: pointer;\n\t\t\topacity: 1;\n\t\t\tpointer-events: all;\n\t\t}\n\t}`\n\n\treturn <style nonce={editor.options.nonce}>{CSS}</style>\n})\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": ["Watermark", "WatermarkInner", "LicenseStyles"]
|
|
7
7
|
}
|
|
@@ -18,40 +18,59 @@ var __copyProps = (to, from, except, desc) => {
|
|
|
18
18
|
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
19
|
var Geometry2d_exports = {};
|
|
20
20
|
__export(Geometry2d_exports, {
|
|
21
|
-
Geometry2d: () => Geometry2d
|
|
21
|
+
Geometry2d: () => Geometry2d,
|
|
22
|
+
Geometry2dFilters: () => Geometry2dFilters,
|
|
23
|
+
TransformedGeometry2d: () => TransformedGeometry2d
|
|
22
24
|
});
|
|
23
25
|
module.exports = __toCommonJS(Geometry2d_exports);
|
|
26
|
+
var import_utils = require("@tldraw/utils");
|
|
24
27
|
var import_Box = require("../Box");
|
|
28
|
+
var import_Mat = require("../Mat");
|
|
25
29
|
var import_Vec = require("../Vec");
|
|
26
|
-
var
|
|
30
|
+
var import_intersect = require("../intersect");
|
|
31
|
+
var import_utils2 = require("../utils");
|
|
32
|
+
const Geometry2dFilters = {
|
|
33
|
+
EXCLUDE_NON_STANDARD: {
|
|
34
|
+
includeLabels: false,
|
|
35
|
+
includeInternal: false
|
|
36
|
+
},
|
|
37
|
+
INCLUDE_ALL: { includeLabels: true, includeInternal: true },
|
|
38
|
+
EXCLUDE_LABELS: { includeLabels: false, includeInternal: true },
|
|
39
|
+
EXCLUDE_INTERNAL: { includeLabels: true, includeInternal: false }
|
|
40
|
+
};
|
|
27
41
|
class Geometry2d {
|
|
28
42
|
isFilled = false;
|
|
29
43
|
isClosed = true;
|
|
30
44
|
isLabel = false;
|
|
45
|
+
isInternal = false;
|
|
31
46
|
debugColor;
|
|
32
47
|
ignore;
|
|
33
48
|
constructor(opts) {
|
|
34
49
|
this.isFilled = opts.isFilled;
|
|
35
50
|
this.isClosed = opts.isClosed;
|
|
36
51
|
this.isLabel = opts.isLabel ?? false;
|
|
52
|
+
this.isInternal = opts.isInternal ?? false;
|
|
37
53
|
this.debugColor = opts.debugColor;
|
|
38
54
|
this.ignore = opts.ignore;
|
|
39
55
|
}
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
56
|
+
isExcludedByFilter(filters) {
|
|
57
|
+
if (!filters) return false;
|
|
58
|
+
if (this.isLabel && !filters.includeLabels) return true;
|
|
59
|
+
if (this.isInternal && !filters.includeInternal) return true;
|
|
60
|
+
return false;
|
|
61
|
+
}
|
|
62
|
+
hitTestPoint(point, margin = 0, hitInside = false, filters) {
|
|
63
|
+
if (this.isExcludedByFilter(filters)) return false;
|
|
64
|
+
if (this.isClosed && (this.isFilled || hitInside) && (0, import_utils2.pointInPolygon)(point, this.vertices)) {
|
|
46
65
|
return true;
|
|
47
66
|
}
|
|
48
67
|
return import_Vec.Vec.Dist2(point, this.nearestPoint(point)) <= margin * margin;
|
|
49
68
|
}
|
|
50
|
-
distanceToPoint(point, hitInside = false) {
|
|
51
|
-
return point.dist(this.nearestPoint(point)) * (this.isClosed && (this.isFilled || hitInside) && (0,
|
|
69
|
+
distanceToPoint(point, hitInside = false, filters) {
|
|
70
|
+
return point.dist(this.nearestPoint(point, filters)) * (this.isClosed && (this.isFilled || hitInside) && (0, import_utils2.pointInPolygon)(point, this.vertices) ? -1 : 1);
|
|
52
71
|
}
|
|
53
|
-
distanceToLineSegment(A, B) {
|
|
54
|
-
if (A.equals(B)) return this.distanceToPoint(A);
|
|
72
|
+
distanceToLineSegment(A, B, filters) {
|
|
73
|
+
if (A.equals(B)) return this.distanceToPoint(A, false, filters);
|
|
55
74
|
const { vertices } = this;
|
|
56
75
|
let nearest;
|
|
57
76
|
let dist = Infinity;
|
|
@@ -66,11 +85,30 @@ class Geometry2d {
|
|
|
66
85
|
}
|
|
67
86
|
}
|
|
68
87
|
if (!nearest) throw Error("nearest point not found");
|
|
69
|
-
return this.isClosed && this.isFilled && (0,
|
|
88
|
+
return this.isClosed && this.isFilled && (0, import_utils2.pointInPolygon)(nearest, this.vertices) ? -dist : dist;
|
|
89
|
+
}
|
|
90
|
+
hitTestLineSegment(A, B, distance = 0, filters) {
|
|
91
|
+
return this.distanceToLineSegment(A, B, filters) <= distance;
|
|
92
|
+
}
|
|
93
|
+
intersectLineSegment(A, B, filters) {
|
|
94
|
+
if (this.isExcludedByFilter(filters)) return [];
|
|
95
|
+
const intersections = this.isClosed ? (0, import_intersect.intersectLineSegmentPolygon)(A, B, this.vertices) : (0, import_intersect.intersectLineSegmentPolyline)(A, B, this.vertices);
|
|
96
|
+
return intersections ?? [];
|
|
97
|
+
}
|
|
98
|
+
intersectCircle(center, radius, filters) {
|
|
99
|
+
if (this.isExcludedByFilter(filters)) return [];
|
|
100
|
+
const intersections = this.isClosed ? (0, import_intersect.intersectCirclePolygon)(center, radius, this.vertices) : (0, import_intersect.intersectCirclePolyline)(center, radius, this.vertices);
|
|
101
|
+
return intersections ?? [];
|
|
102
|
+
}
|
|
103
|
+
intersectPolygon(polygon, filters) {
|
|
104
|
+
if (this.isExcludedByFilter(filters)) return [];
|
|
105
|
+
return (0, import_intersect.intersectPolys)(polygon, this.vertices, true, this.isClosed);
|
|
70
106
|
}
|
|
71
|
-
|
|
72
|
-
|
|
107
|
+
intersectPolyline(polyline, filters) {
|
|
108
|
+
if (this.isExcludedByFilter(filters)) return [];
|
|
109
|
+
return (0, import_intersect.intersectPolys)(polyline, this.vertices, false, this.isClosed);
|
|
73
110
|
}
|
|
111
|
+
/** @deprecated Iterate the vertices instead. */
|
|
74
112
|
nearestPointOnLineSegment(A, B) {
|
|
75
113
|
const { vertices } = this;
|
|
76
114
|
let nearest;
|
|
@@ -92,11 +130,14 @@ class Geometry2d {
|
|
|
92
130
|
const { bounds } = this;
|
|
93
131
|
return !(point.x < bounds.minX - margin || point.y < bounds.minY - margin || point.x > bounds.maxX + margin || point.y > bounds.maxY + margin);
|
|
94
132
|
}
|
|
133
|
+
transform(transform) {
|
|
134
|
+
return new TransformedGeometry2d(this, transform);
|
|
135
|
+
}
|
|
95
136
|
_vertices;
|
|
96
137
|
// eslint-disable-next-line no-restricted-syntax
|
|
97
138
|
get vertices() {
|
|
98
139
|
if (!this._vertices) {
|
|
99
|
-
this._vertices = this.getVertices();
|
|
140
|
+
this._vertices = this.getVertices(Geometry2dFilters.EXCLUDE_LABELS);
|
|
100
141
|
}
|
|
101
142
|
return this._vertices;
|
|
102
143
|
}
|
|
@@ -168,4 +209,80 @@ class Geometry2d {
|
|
|
168
209
|
return Math.sqrt(length);
|
|
169
210
|
}
|
|
170
211
|
}
|
|
212
|
+
class TransformedGeometry2d extends Geometry2d {
|
|
213
|
+
constructor(geometry, matrix) {
|
|
214
|
+
super(geometry);
|
|
215
|
+
this.geometry = geometry;
|
|
216
|
+
this.matrix = matrix;
|
|
217
|
+
this.inverse = import_Mat.Mat.Inverse(matrix);
|
|
218
|
+
this.decomposed = import_Mat.Mat.Decompose(matrix);
|
|
219
|
+
(0, import_utils.assert)(
|
|
220
|
+
(0, import_utils2.approximately)(this.decomposed.scaleX, this.decomposed.scaleY),
|
|
221
|
+
"non-uniform scaling is not yet supported"
|
|
222
|
+
);
|
|
223
|
+
}
|
|
224
|
+
inverse;
|
|
225
|
+
decomposed;
|
|
226
|
+
getVertices(filters) {
|
|
227
|
+
return this.geometry.getVertices(filters).map((v) => import_Mat.Mat.applyToPoint(this.matrix, v));
|
|
228
|
+
}
|
|
229
|
+
nearestPoint(point, filters) {
|
|
230
|
+
return import_Mat.Mat.applyToPoint(
|
|
231
|
+
this.matrix,
|
|
232
|
+
this.geometry.nearestPoint(import_Mat.Mat.applyToPoint(this.inverse, point), filters)
|
|
233
|
+
);
|
|
234
|
+
}
|
|
235
|
+
hitTestPoint(point, margin = 0, hitInside, filters) {
|
|
236
|
+
return this.geometry.hitTestPoint(
|
|
237
|
+
import_Mat.Mat.applyToPoint(this.inverse, point),
|
|
238
|
+
margin / this.decomposed.scaleX,
|
|
239
|
+
hitInside,
|
|
240
|
+
filters
|
|
241
|
+
);
|
|
242
|
+
}
|
|
243
|
+
distanceToPoint(point, hitInside = false, filters) {
|
|
244
|
+
return this.geometry.distanceToPoint(import_Mat.Mat.applyToPoint(this.inverse, point), hitInside, filters) * this.decomposed.scaleX;
|
|
245
|
+
}
|
|
246
|
+
distanceToLineSegment(A, B, filters) {
|
|
247
|
+
return this.geometry.distanceToLineSegment(
|
|
248
|
+
import_Mat.Mat.applyToPoint(this.inverse, A),
|
|
249
|
+
import_Mat.Mat.applyToPoint(this.inverse, B),
|
|
250
|
+
filters
|
|
251
|
+
) * this.decomposed.scaleX;
|
|
252
|
+
}
|
|
253
|
+
hitTestLineSegment(A, B, distance = 0, filters) {
|
|
254
|
+
return this.geometry.hitTestLineSegment(
|
|
255
|
+
import_Mat.Mat.applyToPoint(this.inverse, A),
|
|
256
|
+
import_Mat.Mat.applyToPoint(this.inverse, B),
|
|
257
|
+
distance / this.decomposed.scaleX,
|
|
258
|
+
filters
|
|
259
|
+
);
|
|
260
|
+
}
|
|
261
|
+
intersectLineSegment(A, B, filters) {
|
|
262
|
+
return this.geometry.intersectLineSegment(
|
|
263
|
+
import_Mat.Mat.applyToPoint(this.inverse, A),
|
|
264
|
+
import_Mat.Mat.applyToPoint(this.inverse, B),
|
|
265
|
+
filters
|
|
266
|
+
);
|
|
267
|
+
}
|
|
268
|
+
intersectCircle(center, radius, filters) {
|
|
269
|
+
return this.geometry.intersectCircle(
|
|
270
|
+
import_Mat.Mat.applyToPoint(this.inverse, center),
|
|
271
|
+
radius / this.decomposed.scaleX,
|
|
272
|
+
filters
|
|
273
|
+
);
|
|
274
|
+
}
|
|
275
|
+
intersectPolygon(polygon, filters) {
|
|
276
|
+
return this.geometry.intersectPolygon(import_Mat.Mat.applyToPoints(this.inverse, polygon), filters);
|
|
277
|
+
}
|
|
278
|
+
intersectPolyline(polyline, filters) {
|
|
279
|
+
return this.geometry.intersectPolyline(import_Mat.Mat.applyToPoints(this.inverse, polyline), filters);
|
|
280
|
+
}
|
|
281
|
+
transform(transform) {
|
|
282
|
+
return new TransformedGeometry2d(this.geometry, import_Mat.Mat.Multiply(transform, this.matrix));
|
|
283
|
+
}
|
|
284
|
+
getSvgPathData() {
|
|
285
|
+
throw new Error("Cannot get SVG path data for transformed geometry.");
|
|
286
|
+
}
|
|
287
|
+
}
|
|
171
288
|
//# sourceMappingURL=Geometry2d.js.map
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../src/lib/primitives/geometry/Geometry2d.ts"],
|
|
4
|
-
"sourcesContent": ["import { Box } from '../Box'\nimport { Vec } from '../Vec'\nimport { pointInPolygon } from '../utils'\n\n/** @public */\nexport interface Geometry2dOptions {\n\tisFilled: boolean\n\tisClosed: boolean\n\tisLabel?: boolean\n\tdebugColor?: string\n\tignore?: boolean\n}\n\n/** @public */\nexport abstract class Geometry2d {\n\tisFilled = false\n\tisClosed = true\n\tisLabel = false\n\tdebugColor?: string\n\tignore?: boolean\n\n\tconstructor(opts: Geometry2dOptions) {\n\t\tthis.isFilled = opts.isFilled\n\t\tthis.isClosed = opts.isClosed\n\t\tthis.isLabel = opts.isLabel ?? false\n\t\tthis.debugColor = opts.debugColor\n\t\tthis.ignore = opts.ignore\n\t}\n\n\tabstract getVertices(): Vec[]\n\n\tabstract nearestPoint(point: Vec): Vec\n\n\t// hitTestPoint(point: Vec, margin = 0, hitInside = false) {\n\t// \t// We've removed the broad phase here; that should be done outside of the call\n\t// \treturn this.distanceToPoint(point, hitInside) <= margin\n\t// }\n\n\thitTestPoint(point: Vec, margin = 0, hitInside = false) {\n\t\t// First check whether the point is inside\n\t\tif (this.isClosed && (this.isFilled || hitInside) && pointInPolygon(point, this.vertices)) {\n\t\t\treturn true\n\t\t}\n\t\t// Then check whether the distance is within the margin\n\t\treturn Vec.Dist2(point, this.nearestPoint(point)) <= margin * margin\n\t}\n\n\tdistanceToPoint(point: Vec, hitInside = false) {\n\t\treturn (\n\t\t\tpoint.dist(this.nearestPoint(point)) *\n\t\t\t(this.isClosed && (this.isFilled || hitInside) && pointInPolygon(point, this.vertices)\n\t\t\t\t? -1\n\t\t\t\t: 1)\n\t\t)\n\t}\n\n\tdistanceToLineSegment(A: Vec, B: Vec) {\n\t\tif (A.equals(B)) return this.distanceToPoint(A)\n\t\tconst { vertices } = this\n\t\tlet nearest: Vec | undefined\n\t\tlet dist = Infinity\n\t\tlet d: number, p: Vec, q: Vec\n\t\tfor (let i = 0; i < vertices.length; i++) {\n\t\t\tp = vertices[i]\n\t\t\tq = Vec.NearestPointOnLineSegment(A, B, p, true)\n\t\t\td = Vec.Dist2(p, q)\n\t\t\tif (d < dist) {\n\t\t\t\tdist = d\n\t\t\t\tnearest = q\n\t\t\t}\n\t\t}\n\t\tif (!nearest) throw Error('nearest point not found')\n\t\treturn this.isClosed && this.isFilled && pointInPolygon(nearest, this.vertices) ? -dist : dist\n\t}\n\n\thitTestLineSegment(A: Vec, B: Vec, distance = 0): boolean {\n\t\treturn this.distanceToLineSegment(A, B) <= distance\n\t}\n\n\tnearestPointOnLineSegment(A: Vec, B: Vec): Vec {\n\t\tconst { vertices } = this\n\t\tlet nearest: Vec | undefined\n\t\tlet dist = Infinity\n\t\tlet d: number, p: Vec, q: Vec\n\t\tfor (let i = 0; i < vertices.length; i++) {\n\t\t\tp = vertices[i]\n\t\t\tq = Vec.NearestPointOnLineSegment(A, B, p, true)\n\t\t\td = Vec.Dist2(p, q)\n\t\t\tif (d < dist) {\n\t\t\t\tdist = d\n\t\t\t\tnearest = q\n\t\t\t}\n\t\t}\n\t\tif (!nearest) throw Error('nearest point not found')\n\t\treturn nearest\n\t}\n\n\tisPointInBounds(point: Vec, margin = 0) {\n\t\tconst { bounds } = this\n\t\treturn !(\n\t\t\tpoint.x < bounds.minX - margin ||\n\t\t\tpoint.y < bounds.minY - margin ||\n\t\t\tpoint.x > bounds.maxX + margin ||\n\t\t\tpoint.y > bounds.maxY + margin\n\t\t)\n\t}\n\n\tprivate _vertices: Vec[] | undefined\n\n\t// eslint-disable-next-line no-restricted-syntax\n\tget vertices(): Vec[] {\n\t\tif (!this._vertices) {\n\t\t\tthis._vertices = this.getVertices()\n\t\t}\n\n\t\treturn this._vertices\n\t}\n\n\tgetBounds() {\n\t\treturn Box.FromPoints(this.vertices)\n\t}\n\n\tprivate _bounds: Box | undefined\n\n\t// eslint-disable-next-line no-restricted-syntax\n\tget bounds(): Box {\n\t\tif (!this._bounds) {\n\t\t\tthis._bounds = this.getBounds()\n\t\t}\n\t\treturn this._bounds\n\t}\n\n\t// eslint-disable-next-line no-restricted-syntax\n\tget center() {\n\t\treturn this.bounds.center\n\t}\n\n\tprivate _area: number | undefined\n\n\t// eslint-disable-next-line no-restricted-syntax\n\tget area() {\n\t\tif (!this._area) {\n\t\t\tthis._area = this.getArea()\n\t\t}\n\t\treturn this._area\n\t}\n\n\tgetArea() {\n\t\tif (!this.isClosed) {\n\t\t\treturn 0\n\t\t}\n\t\tconst { vertices } = this\n\t\tlet area = 0\n\t\tfor (let i = 0, n = vertices.length; i < n; i++) {\n\t\t\tconst curr = vertices[i]\n\t\t\tconst next = vertices[(i + 1) % n]\n\t\t\tarea += curr.x * next.y - next.x * curr.y\n\t\t}\n\t\treturn area / 2\n\t}\n\n\ttoSimpleSvgPath() {\n\t\tlet path = ''\n\n\t\tconst { vertices } = this\n\t\tconst n = vertices.length\n\n\t\tif (n === 0) return path\n\n\t\tpath += `M${vertices[0].x},${vertices[0].y}`\n\n\t\tfor (let i = 1; i < n; i++) {\n\t\t\tpath += `L${vertices[i].x},${vertices[i].y}`\n\t\t}\n\n\t\tif (this.isClosed) {\n\t\t\tpath += 'Z'\n\t\t}\n\n\t\treturn path\n\t}\n\n\tprivate _length?: number\n\n\t// eslint-disable-next-line no-restricted-syntax\n\tget length() {\n\t\tif (this._length) return this._length\n\t\tthis._length = this.getLength()\n\t\treturn this._length\n\t}\n\n\tgetLength() {\n\t\tconst { vertices } = this\n\t\tlet n1: Vec,\n\t\t\tp1 = vertices[0],\n\t\t\tlength = 0\n\t\tfor (let i = 1; i < vertices.length; i++) {\n\t\t\tn1 = vertices[i]\n\t\t\tlength += Vec.Dist2(p1, n1)\n\t\t\tp1 = n1\n\t\t}\n\t\treturn Math.sqrt(length)\n\t}\n\n\tabstract getSvgPathData(first: boolean): string\n}\n"],
|
|
5
|
-
"mappings": ";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,
|
|
6
|
-
"names": []
|
|
4
|
+
"sourcesContent": ["import { assert } from '@tldraw/utils'\nimport { Box } from '../Box'\nimport { Mat, MatModel } from '../Mat'\nimport { Vec, VecLike } from '../Vec'\nimport {\n\tintersectCirclePolygon,\n\tintersectCirclePolyline,\n\tintersectLineSegmentPolygon,\n\tintersectLineSegmentPolyline,\n\tintersectPolys,\n} from '../intersect'\nimport { approximately, pointInPolygon } from '../utils'\n\n/** @public */\nexport interface Geometry2dFilters {\n\treadonly includeLabels?: boolean\n\treadonly includeInternal?: boolean\n}\n\n/** @public */\nexport const Geometry2dFilters: {\n\tEXCLUDE_NON_STANDARD: Geometry2dFilters\n\tINCLUDE_ALL: Geometry2dFilters\n\tEXCLUDE_LABELS: Geometry2dFilters\n\tEXCLUDE_INTERNAL: Geometry2dFilters\n} = {\n\tEXCLUDE_NON_STANDARD: {\n\t\tincludeLabels: false,\n\t\tincludeInternal: false,\n\t},\n\tINCLUDE_ALL: { includeLabels: true, includeInternal: true },\n\tEXCLUDE_LABELS: { includeLabels: false, includeInternal: true },\n\tEXCLUDE_INTERNAL: { includeLabels: true, includeInternal: false },\n}\n\n/** @public */\nexport interface Geometry2dOptions {\n\tisFilled: boolean\n\tisClosed: boolean\n\tisLabel?: boolean\n\tisInternal?: boolean\n\tdebugColor?: string\n\tignore?: boolean\n}\n\n/** @public */\nexport abstract class Geometry2d {\n\tisFilled = false\n\tisClosed = true\n\tisLabel = false\n\tisInternal = false\n\tdebugColor?: string\n\tignore?: boolean\n\n\tconstructor(opts: Geometry2dOptions) {\n\t\tthis.isFilled = opts.isFilled\n\t\tthis.isClosed = opts.isClosed\n\t\tthis.isLabel = opts.isLabel ?? false\n\t\tthis.isInternal = opts.isInternal ?? false\n\t\tthis.debugColor = opts.debugColor\n\t\tthis.ignore = opts.ignore\n\t}\n\n\tisExcludedByFilter(filters?: Geometry2dFilters) {\n\t\tif (!filters) return false\n\t\tif (this.isLabel && !filters.includeLabels) return true\n\t\tif (this.isInternal && !filters.includeInternal) return true\n\t\treturn false\n\t}\n\n\tabstract getVertices(filters: Geometry2dFilters): Vec[]\n\n\tabstract nearestPoint(point: Vec, filters?: Geometry2dFilters): Vec\n\n\thitTestPoint(point: Vec, margin = 0, hitInside = false, filters?: Geometry2dFilters) {\n\t\tif (this.isExcludedByFilter(filters)) return false\n\t\t// First check whether the point is inside\n\t\tif (this.isClosed && (this.isFilled || hitInside) && pointInPolygon(point, this.vertices)) {\n\t\t\treturn true\n\t\t}\n\t\t// Then check whether the distance is within the margin\n\t\treturn Vec.Dist2(point, this.nearestPoint(point)) <= margin * margin\n\t}\n\n\tdistanceToPoint(point: Vec, hitInside = false, filters?: Geometry2dFilters) {\n\t\treturn (\n\t\t\tpoint.dist(this.nearestPoint(point, filters)) *\n\t\t\t(this.isClosed && (this.isFilled || hitInside) && pointInPolygon(point, this.vertices)\n\t\t\t\t? -1\n\t\t\t\t: 1)\n\t\t)\n\t}\n\n\tdistanceToLineSegment(A: Vec, B: Vec, filters?: Geometry2dFilters) {\n\t\tif (A.equals(B)) return this.distanceToPoint(A, false, filters)\n\t\tconst { vertices } = this\n\t\tlet nearest: Vec | undefined\n\t\tlet dist = Infinity\n\t\tlet d: number, p: Vec, q: Vec\n\t\tfor (let i = 0; i < vertices.length; i++) {\n\t\t\tp = vertices[i]\n\t\t\tq = Vec.NearestPointOnLineSegment(A, B, p, true)\n\t\t\td = Vec.Dist2(p, q)\n\t\t\tif (d < dist) {\n\t\t\t\tdist = d\n\t\t\t\tnearest = q\n\t\t\t}\n\t\t}\n\t\tif (!nearest) throw Error('nearest point not found')\n\t\treturn this.isClosed && this.isFilled && pointInPolygon(nearest, this.vertices) ? -dist : dist\n\t}\n\n\thitTestLineSegment(A: Vec, B: Vec, distance = 0, filters?: Geometry2dFilters): boolean {\n\t\treturn this.distanceToLineSegment(A, B, filters) <= distance\n\t}\n\n\tintersectLineSegment(A: VecLike, B: VecLike, filters?: Geometry2dFilters): VecLike[] {\n\t\tif (this.isExcludedByFilter(filters)) return []\n\n\t\tconst intersections = this.isClosed\n\t\t\t? intersectLineSegmentPolygon(A, B, this.vertices)\n\t\t\t: intersectLineSegmentPolyline(A, B, this.vertices)\n\n\t\treturn intersections ?? []\n\t}\n\n\tintersectCircle(center: VecLike, radius: number, filters?: Geometry2dFilters): VecLike[] {\n\t\tif (this.isExcludedByFilter(filters)) return []\n\t\tconst intersections = this.isClosed\n\t\t\t? intersectCirclePolygon(center, radius, this.vertices)\n\t\t\t: intersectCirclePolyline(center, radius, this.vertices)\n\n\t\treturn intersections ?? []\n\t}\n\n\tintersectPolygon(polygon: VecLike[], filters?: Geometry2dFilters): VecLike[] {\n\t\tif (this.isExcludedByFilter(filters)) return []\n\n\t\treturn intersectPolys(polygon, this.vertices, true, this.isClosed)\n\t}\n\n\tintersectPolyline(polyline: VecLike[], filters?: Geometry2dFilters): VecLike[] {\n\t\tif (this.isExcludedByFilter(filters)) return []\n\t\treturn intersectPolys(polyline, this.vertices, false, this.isClosed)\n\t}\n\n\t/** @deprecated Iterate the vertices instead. */\n\tnearestPointOnLineSegment(A: Vec, B: Vec): Vec {\n\t\tconst { vertices } = this\n\t\tlet nearest: Vec | undefined\n\t\tlet dist = Infinity\n\t\tlet d: number, p: Vec, q: Vec\n\t\tfor (let i = 0; i < vertices.length; i++) {\n\t\t\tp = vertices[i]\n\t\t\tq = Vec.NearestPointOnLineSegment(A, B, p, true)\n\t\t\td = Vec.Dist2(p, q)\n\t\t\tif (d < dist) {\n\t\t\t\tdist = d\n\t\t\t\tnearest = q\n\t\t\t}\n\t\t}\n\t\tif (!nearest) throw Error('nearest point not found')\n\t\treturn nearest\n\t}\n\n\tisPointInBounds(point: Vec, margin = 0) {\n\t\tconst { bounds } = this\n\t\treturn !(\n\t\t\tpoint.x < bounds.minX - margin ||\n\t\t\tpoint.y < bounds.minY - margin ||\n\t\t\tpoint.x > bounds.maxX + margin ||\n\t\t\tpoint.y > bounds.maxY + margin\n\t\t)\n\t}\n\n\ttransform(transform: MatModel): Geometry2d {\n\t\treturn new TransformedGeometry2d(this, transform)\n\t}\n\n\tprivate _vertices: Vec[] | undefined\n\n\t// eslint-disable-next-line no-restricted-syntax\n\tget vertices(): Vec[] {\n\t\tif (!this._vertices) {\n\t\t\tthis._vertices = this.getVertices(Geometry2dFilters.EXCLUDE_LABELS)\n\t\t}\n\n\t\treturn this._vertices\n\t}\n\n\tgetBounds() {\n\t\treturn Box.FromPoints(this.vertices)\n\t}\n\n\tprivate _bounds: Box | undefined\n\n\t// eslint-disable-next-line no-restricted-syntax\n\tget bounds(): Box {\n\t\tif (!this._bounds) {\n\t\t\tthis._bounds = this.getBounds()\n\t\t}\n\t\treturn this._bounds\n\t}\n\n\t// eslint-disable-next-line no-restricted-syntax\n\tget center() {\n\t\treturn this.bounds.center\n\t}\n\n\tprivate _area: number | undefined\n\n\t// eslint-disable-next-line no-restricted-syntax\n\tget area() {\n\t\tif (!this._area) {\n\t\t\tthis._area = this.getArea()\n\t\t}\n\t\treturn this._area\n\t}\n\n\tgetArea() {\n\t\tif (!this.isClosed) {\n\t\t\treturn 0\n\t\t}\n\t\tconst { vertices } = this\n\t\tlet area = 0\n\t\tfor (let i = 0, n = vertices.length; i < n; i++) {\n\t\t\tconst curr = vertices[i]\n\t\t\tconst next = vertices[(i + 1) % n]\n\t\t\tarea += curr.x * next.y - next.x * curr.y\n\t\t}\n\t\treturn area / 2\n\t}\n\n\ttoSimpleSvgPath() {\n\t\tlet path = ''\n\n\t\tconst { vertices } = this\n\t\tconst n = vertices.length\n\n\t\tif (n === 0) return path\n\n\t\tpath += `M${vertices[0].x},${vertices[0].y}`\n\n\t\tfor (let i = 1; i < n; i++) {\n\t\t\tpath += `L${vertices[i].x},${vertices[i].y}`\n\t\t}\n\n\t\tif (this.isClosed) {\n\t\t\tpath += 'Z'\n\t\t}\n\n\t\treturn path\n\t}\n\n\tprivate _length?: number\n\n\t// eslint-disable-next-line no-restricted-syntax\n\tget length() {\n\t\tif (this._length) return this._length\n\t\tthis._length = this.getLength()\n\t\treturn this._length\n\t}\n\n\tgetLength() {\n\t\tconst { vertices } = this\n\t\tlet n1: Vec,\n\t\t\tp1 = vertices[0],\n\t\t\tlength = 0\n\t\tfor (let i = 1; i < vertices.length; i++) {\n\t\t\tn1 = vertices[i]\n\t\t\tlength += Vec.Dist2(p1, n1)\n\t\t\tp1 = n1\n\t\t}\n\t\treturn Math.sqrt(length)\n\t}\n\n\tabstract getSvgPathData(first: boolean): string\n}\n\n// =================================================================================================\n// Because Geometry2d.transform depends on TransformedGeometry2d, we need to define it here instead\n// of in its own files. This prevents a circular import error.\n// =================================================================================================\n\n/** @public */\nexport class TransformedGeometry2d extends Geometry2d {\n\tprivate readonly inverse: MatModel\n\tprivate readonly decomposed\n\n\tconstructor(\n\t\tprivate readonly geometry: Geometry2d,\n\t\tprivate readonly matrix: MatModel\n\t) {\n\t\tsuper(geometry)\n\t\tthis.inverse = Mat.Inverse(matrix)\n\t\tthis.decomposed = Mat.Decompose(matrix)\n\n\t\tassert(\n\t\t\tapproximately(this.decomposed.scaleX, this.decomposed.scaleY),\n\t\t\t'non-uniform scaling is not yet supported'\n\t\t)\n\t}\n\n\tgetVertices(filters: Geometry2dFilters): Vec[] {\n\t\treturn this.geometry.getVertices(filters).map((v) => Mat.applyToPoint(this.matrix, v))\n\t}\n\n\tnearestPoint(point: Vec, filters?: Geometry2dFilters): Vec {\n\t\treturn Mat.applyToPoint(\n\t\t\tthis.matrix,\n\t\t\tthis.geometry.nearestPoint(Mat.applyToPoint(this.inverse, point), filters)\n\t\t)\n\t}\n\n\toverride hitTestPoint(\n\t\tpoint: Vec,\n\t\tmargin = 0,\n\t\thitInside?: boolean,\n\t\tfilters?: Geometry2dFilters\n\t): boolean {\n\t\treturn this.geometry.hitTestPoint(\n\t\t\tMat.applyToPoint(this.inverse, point),\n\t\t\tmargin / this.decomposed.scaleX,\n\t\t\thitInside,\n\t\t\tfilters\n\t\t)\n\t}\n\n\toverride distanceToPoint(point: Vec, hitInside = false, filters?: Geometry2dFilters) {\n\t\treturn (\n\t\t\tthis.geometry.distanceToPoint(Mat.applyToPoint(this.inverse, point), hitInside, filters) *\n\t\t\tthis.decomposed.scaleX\n\t\t)\n\t}\n\n\toverride distanceToLineSegment(A: Vec, B: Vec, filters?: Geometry2dFilters) {\n\t\treturn (\n\t\t\tthis.geometry.distanceToLineSegment(\n\t\t\t\tMat.applyToPoint(this.inverse, A),\n\t\t\t\tMat.applyToPoint(this.inverse, B),\n\t\t\t\tfilters\n\t\t\t) * this.decomposed.scaleX\n\t\t)\n\t}\n\n\toverride hitTestLineSegment(A: Vec, B: Vec, distance = 0, filters?: Geometry2dFilters): boolean {\n\t\treturn this.geometry.hitTestLineSegment(\n\t\t\tMat.applyToPoint(this.inverse, A),\n\t\t\tMat.applyToPoint(this.inverse, B),\n\t\t\tdistance / this.decomposed.scaleX,\n\t\t\tfilters\n\t\t)\n\t}\n\n\toverride intersectLineSegment(A: VecLike, B: VecLike, filters?: Geometry2dFilters) {\n\t\treturn this.geometry.intersectLineSegment(\n\t\t\tMat.applyToPoint(this.inverse, A),\n\t\t\tMat.applyToPoint(this.inverse, B),\n\t\t\tfilters\n\t\t)\n\t}\n\n\toverride intersectCircle(center: VecLike, radius: number, filters?: Geometry2dFilters) {\n\t\treturn this.geometry.intersectCircle(\n\t\t\tMat.applyToPoint(this.inverse, center),\n\t\t\tradius / this.decomposed.scaleX,\n\t\t\tfilters\n\t\t)\n\t}\n\n\toverride intersectPolygon(polygon: VecLike[], filters?: Geometry2dFilters): VecLike[] {\n\t\treturn this.geometry.intersectPolygon(Mat.applyToPoints(this.inverse, polygon), filters)\n\t}\n\n\toverride intersectPolyline(polyline: VecLike[], filters?: Geometry2dFilters): VecLike[] {\n\t\treturn this.geometry.intersectPolyline(Mat.applyToPoints(this.inverse, polyline), filters)\n\t}\n\n\toverride transform(transform: MatModel): Geometry2d {\n\t\treturn new TransformedGeometry2d(this.geometry, Mat.Multiply(transform, this.matrix))\n\t}\n\n\tgetSvgPathData(): string {\n\t\tthrow new Error('Cannot get SVG path data for transformed geometry.')\n\t}\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": ["import_utils"]
|
|
7
7
|
}
|
|
@@ -21,6 +21,7 @@ __export(Group2d_exports, {
|
|
|
21
21
|
Group2d: () => Group2d
|
|
22
22
|
});
|
|
23
23
|
module.exports = __toCommonJS(Group2d_exports);
|
|
24
|
+
var import_state = require("@tldraw/state");
|
|
24
25
|
var import_Box = require("../Box");
|
|
25
26
|
var import_Vec = require("../Vec");
|
|
26
27
|
var import_Geometry2d = require("./Geometry2d");
|
|
@@ -38,10 +39,11 @@ class Group2d extends import_Geometry2d.Geometry2d {
|
|
|
38
39
|
}
|
|
39
40
|
if (this.children.length === 0) throw Error("Group2d must have at least one child");
|
|
40
41
|
}
|
|
41
|
-
getVertices() {
|
|
42
|
-
|
|
42
|
+
getVertices(filters) {
|
|
43
|
+
if (this.isExcludedByFilter(filters)) return [];
|
|
44
|
+
return this.children.filter((c) => !c.isExcludedByFilter(filters)).flatMap((c) => c.getVertices(filters));
|
|
43
45
|
}
|
|
44
|
-
nearestPoint(point) {
|
|
46
|
+
nearestPoint(point, filters) {
|
|
45
47
|
let dist = Infinity;
|
|
46
48
|
let nearest;
|
|
47
49
|
const { children } = this;
|
|
@@ -51,7 +53,8 @@ class Group2d extends import_Geometry2d.Geometry2d {
|
|
|
51
53
|
let p;
|
|
52
54
|
let d;
|
|
53
55
|
for (const child of children) {
|
|
54
|
-
|
|
56
|
+
if (child.isExcludedByFilter(filters)) continue;
|
|
57
|
+
p = child.nearestPoint(point, filters);
|
|
55
58
|
d = import_Vec.Vec.Dist2(p, point);
|
|
56
59
|
if (d < dist) {
|
|
57
60
|
dist = d;
|
|
@@ -61,14 +64,54 @@ class Group2d extends import_Geometry2d.Geometry2d {
|
|
|
61
64
|
if (!nearest) throw Error("nearest point not found");
|
|
62
65
|
return nearest;
|
|
63
66
|
}
|
|
64
|
-
distanceToPoint(point, hitInside = false) {
|
|
65
|
-
|
|
67
|
+
distanceToPoint(point, hitInside = false, filters) {
|
|
68
|
+
let smallestDistance = Infinity;
|
|
69
|
+
for (const child of this.children) {
|
|
70
|
+
if (child.isExcludedByFilter(filters)) continue;
|
|
71
|
+
const distance = child.distanceToPoint(point, hitInside, filters);
|
|
72
|
+
if (distance < smallestDistance) {
|
|
73
|
+
smallestDistance = distance;
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
return smallestDistance;
|
|
77
|
+
}
|
|
78
|
+
hitTestPoint(point, margin, hitInside, filters = import_Geometry2d.Geometry2dFilters.EXCLUDE_LABELS) {
|
|
79
|
+
return !!this.children.filter((c) => !c.isExcludedByFilter(filters)).find((c) => c.hitTestPoint(point, margin, hitInside));
|
|
80
|
+
}
|
|
81
|
+
hitTestLineSegment(A, B, zoom, filters = import_Geometry2d.Geometry2dFilters.EXCLUDE_LABELS) {
|
|
82
|
+
return !!this.children.filter((c) => !c.isExcludedByFilter(filters)).find((c) => c.hitTestLineSegment(A, B, zoom));
|
|
83
|
+
}
|
|
84
|
+
intersectLineSegment(A, B, filters) {
|
|
85
|
+
return this.children.flatMap((child) => {
|
|
86
|
+
if (child.isExcludedByFilter(filters)) return import_state.EMPTY_ARRAY;
|
|
87
|
+
return child.intersectLineSegment(A, B, filters);
|
|
88
|
+
});
|
|
89
|
+
}
|
|
90
|
+
intersectCircle(center, radius, filters) {
|
|
91
|
+
return this.children.flatMap((child) => {
|
|
92
|
+
if (child.isExcludedByFilter(filters)) return import_state.EMPTY_ARRAY;
|
|
93
|
+
return child.intersectCircle(center, radius, filters);
|
|
94
|
+
});
|
|
95
|
+
}
|
|
96
|
+
intersectPolygon(polygon, filters) {
|
|
97
|
+
return this.children.flatMap((child) => {
|
|
98
|
+
if (child.isExcludedByFilter(filters)) return import_state.EMPTY_ARRAY;
|
|
99
|
+
return child.intersectPolygon(polygon, filters);
|
|
100
|
+
});
|
|
66
101
|
}
|
|
67
|
-
|
|
68
|
-
return
|
|
102
|
+
intersectPolyline(polyline, filters) {
|
|
103
|
+
return this.children.flatMap((child) => {
|
|
104
|
+
if (child.isExcludedByFilter(filters)) return import_state.EMPTY_ARRAY;
|
|
105
|
+
return child.intersectPolyline(polyline, filters);
|
|
106
|
+
});
|
|
69
107
|
}
|
|
70
|
-
|
|
71
|
-
return
|
|
108
|
+
transform(transform) {
|
|
109
|
+
return new Group2d({
|
|
110
|
+
children: this.children.map((c) => c.transform(transform)),
|
|
111
|
+
isLabel: this.isLabel,
|
|
112
|
+
debugColor: this.debugColor,
|
|
113
|
+
ignore: this.ignore
|
|
114
|
+
});
|
|
72
115
|
}
|
|
73
116
|
getArea() {
|
|
74
117
|
return this.children[0].area;
|
|
@@ -96,7 +139,7 @@ class Group2d extends import_Geometry2d.Geometry2d {
|
|
|
96
139
|
return this.children.reduce((a, c) => c.isLabel ? a : a + c.length, 0);
|
|
97
140
|
}
|
|
98
141
|
getSvgPathData() {
|
|
99
|
-
return this.children.map((c) => c.isLabel ? "" : c.getSvgPathData(
|
|
142
|
+
return this.children.map((c, i) => c.isLabel ? "" : c.getSvgPathData(i === 0)).join(" ");
|
|
100
143
|
}
|
|
101
144
|
}
|
|
102
145
|
//# sourceMappingURL=Group2d.js.map
|