@tldraw/editor 3.16.0-canary.8c74738e06fb → 3.16.0-canary.aa1aff3ffe55
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 +54 -9
- package/dist-cjs/index.js +1 -1
- package/dist-cjs/index.js.map +2 -2
- package/dist-cjs/lib/TldrawEditor.js +1 -1
- package/dist-cjs/lib/TldrawEditor.js.map +2 -2
- package/dist-cjs/lib/components/MenuClickCapture.js +5 -0
- package/dist-cjs/lib/components/MenuClickCapture.js.map +2 -2
- package/dist-cjs/lib/editor/Editor.js +19 -9
- package/dist-cjs/lib/editor/Editor.js.map +2 -2
- package/dist-cjs/lib/editor/types/misc-types.js.map +1 -1
- package/dist-cjs/lib/hooks/useCanvasEvents.js +20 -24
- package/dist-cjs/lib/hooks/useCanvasEvents.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 +54 -9
- package/dist-esm/index.mjs +1 -1
- package/dist-esm/index.mjs.map +2 -2
- package/dist-esm/lib/TldrawEditor.mjs +1 -1
- package/dist-esm/lib/TldrawEditor.mjs.map +2 -2
- package/dist-esm/lib/components/MenuClickCapture.mjs +5 -0
- package/dist-esm/lib/components/MenuClickCapture.mjs.map +2 -2
- package/dist-esm/lib/editor/Editor.mjs +19 -9
- package/dist-esm/lib/editor/Editor.mjs.map +2 -2
- package/dist-esm/lib/hooks/useCanvasEvents.mjs +21 -25
- package/dist-esm/lib/hooks/useCanvasEvents.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 +1 -0
- package/src/lib/TldrawEditor.tsx +5 -5
- package/src/lib/components/MenuClickCapture.tsx +8 -0
- package/src/lib/editor/Editor.ts +33 -27
- package/src/lib/editor/types/misc-types.ts +54 -1
- package/src/lib/hooks/useCanvasEvents.ts +32 -39
- package/src/version.ts +3 -3
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../src/lib/components/MenuClickCapture.tsx"],
|
|
4
|
-
"sourcesContent": ["import { useValue } from '@tldraw/state-react'\nimport { PointerEvent, useCallback, useRef, useState } from 'react'\nimport { useCanvasEvents } from '../hooks/useCanvasEvents'\nimport { useEditor } from '../hooks/useEditor'\nimport { Vec } from '../primitives/Vec'\n\n/**\n * When a menu is open, this component prevents the user from interacting with the canvas.\n *\n * @public @react\n */\nexport function MenuClickCapture() {\n\tconst editor = useEditor()\n\n\t// Whether any menus are open\n\tconst isMenuOpen = useValue('is menu open', () => editor.menus.hasAnyOpenMenus(), [editor])\n\n\t// Whether we're pointing or not\u2014keep this component visible if we're pointing\n\tconst [isPointing, setIsPointing] = useState(false)\n\n\tconst showElement = isMenuOpen || isPointing\n\n\t// Get the same events that we use on the canvas\n\tconst canvasEvents = useCanvasEvents()\n\n\t// Keep track of the pointer state\n\tconst rPointerState = useRef({\n\t\tisDown: false,\n\t\tisDragging: false,\n\t\tstart: new Vec(),\n\t})\n\n\tconst handlePointerDown = useCallback(\n\t\t(e: PointerEvent) => {\n\t\t\tif (e.button === 0) {\n\t\t\t\tsetIsPointing(true)\n\t\t\t\trPointerState.current = {\n\t\t\t\t\tisDown: true,\n\t\t\t\t\tisDragging: false,\n\t\t\t\t\tstart: new Vec(e.clientX, e.clientY),\n\t\t\t\t}\n\t\t\t}\n\t\t\teditor.menus.clearOpenMenus()\n\t\t},\n\t\t[editor]\n\t)\n\n\tconst handlePointerMove = useCallback(\n\t\t(e: PointerEvent) => {\n\t\t\t// Do nothing unless we're pointing\n\t\t\tif (!rPointerState.current.isDown) return\n\n\t\t\tif (\n\t\t\t\t// We're pointing, but are we dragging?\n\t\t\t\tVec.Dist2(rPointerState.current.start, new Vec(e.clientX, e.clientY)) >\n\t\t\t\teditor.options.dragDistanceSquared\n\t\t\t) {\n\t\t\t\t// Wehaddaeventitsadrag\n\t\t\t\trPointerState.current = {\n\t\t\t\t\t...rPointerState.current,\n\t\t\t\t\tisDown: true,\n\t\t\t\t\tisDragging: true,\n\t\t\t\t}\n\t\t\t\t// call the onPointerDown with the original pointer position\n\t\t\t\tconst { x, y } = rPointerState.current.start\n\t\t\t\tcanvasEvents.onPointerDown?.({\n\t\t\t\t\t...e,\n\t\t\t\t\tclientX: x,\n\t\t\t\t\tclientY: y,\n\t\t\t\t\tbutton: 0,\n\t\t\t\t})\n\t\t\t}\n\t\t},\n\t\t[canvasEvents, editor]\n\t)\n\n\tconst handlePointerUp = useCallback(\n\t\t(e: PointerEvent) => {\n\t\t\t// Run the pointer up\n\t\t\tcanvasEvents.onPointerUp?.(e)\n\t\t\t// Then turn off pointing\n\t\t\tsetIsPointing(false)\n\t\t\t// Reset the pointer state\n\t\t\trPointerState.current = {\n\t\t\t\tisDown: false,\n\t\t\t\tisDragging: false,\n\t\t\t\tstart: new Vec(e.clientX, e.clientY),\n\t\t\t}\n\t\t},\n\t\t[canvasEvents]\n\t)\n\n\treturn (\n\t\tshowElement && (\n\t\t\t<div\n\t\t\t\tclassName=\"tlui-menu-click-capture\"\n\t\t\t\tdata-testid=\"menu-click-capture.content\"\n\t\t\t\t{...canvasEvents}\n\t\t\t\tonPointerDown={handlePointerDown}\n\t\t\t\tonPointerMove={handlePointerMove}\n\t\t\t\tonPointerUp={handlePointerUp}\n\t\t\t/>\n\t\t)\n\t)\n}\n"],
|
|
5
|
-
"mappings": "
|
|
4
|
+
"sourcesContent": ["import { useValue } from '@tldraw/state-react'\nimport { PointerEvent, useCallback, useRef, useState } from 'react'\nimport { useCanvasEvents } from '../hooks/useCanvasEvents'\nimport { useEditor } from '../hooks/useEditor'\nimport { Vec } from '../primitives/Vec'\n\n/**\n * When a menu is open, this component prevents the user from interacting with the canvas.\n *\n * @public @react\n */\nexport function MenuClickCapture() {\n\tconst editor = useEditor()\n\n\t// Whether any menus are open\n\tconst isMenuOpen = useValue('is menu open', () => editor.menus.hasAnyOpenMenus(), [editor])\n\n\t// Whether we're pointing or not\u2014keep this component visible if we're pointing\n\tconst [isPointing, setIsPointing] = useState(false)\n\n\tconst showElement = isMenuOpen || isPointing\n\n\t// Get the same events that we use on the canvas\n\tconst canvasEvents = useCanvasEvents()\n\n\t// Keep track of the pointer state\n\tconst rPointerState = useRef({\n\t\tisDown: false,\n\t\tisDragging: false,\n\t\tstart: new Vec(),\n\t})\n\n\tconst handlePointerDown = useCallback(\n\t\t(e: PointerEvent) => {\n\t\t\tif (e.button === 0) {\n\t\t\t\tsetIsPointing(true)\n\t\t\t\trPointerState.current = {\n\t\t\t\t\tisDown: true,\n\t\t\t\t\tisDragging: false,\n\t\t\t\t\tstart: new Vec(e.clientX, e.clientY),\n\t\t\t\t}\n\t\t\t}\n\t\t\teditor.menus.clearOpenMenus()\n\t\t},\n\t\t[editor]\n\t)\n\n\tconst handlePointerMove = useCallback(\n\t\t(e: PointerEvent) => {\n\t\t\t// Do nothing unless we're pointing\n\t\t\tif (!rPointerState.current.isDown) return\n\n\t\t\t// If we're already dragging, pass on the event as it is\n\t\t\tif (rPointerState.current.isDragging) {\n\t\t\t\tcanvasEvents.onPointerMove?.(e)\n\t\t\t\treturn\n\t\t\t}\n\n\t\t\tif (\n\t\t\t\t// We're pointing, but are we dragging?\n\t\t\t\tVec.Dist2(rPointerState.current.start, new Vec(e.clientX, e.clientY)) >\n\t\t\t\teditor.options.dragDistanceSquared\n\t\t\t) {\n\t\t\t\t// Wehaddaeventitsadrag\n\t\t\t\trPointerState.current = {\n\t\t\t\t\t...rPointerState.current,\n\t\t\t\t\tisDown: true,\n\t\t\t\t\tisDragging: true,\n\t\t\t\t}\n\t\t\t\t// call the onPointerDown with the original pointer position\n\t\t\t\tconst { x, y } = rPointerState.current.start\n\t\t\t\tcanvasEvents.onPointerDown?.({\n\t\t\t\t\t...e,\n\t\t\t\t\tclientX: x,\n\t\t\t\t\tclientY: y,\n\t\t\t\t\tbutton: 0,\n\t\t\t\t})\n\t\t\t\t// call the pointer move with the current pointer position\n\t\t\t\tcanvasEvents.onPointerMove?.(e)\n\t\t\t}\n\t\t},\n\t\t[canvasEvents, editor]\n\t)\n\n\tconst handlePointerUp = useCallback(\n\t\t(e: PointerEvent) => {\n\t\t\t// Run the pointer up\n\t\t\tcanvasEvents.onPointerUp?.(e)\n\t\t\t// Then turn off pointing\n\t\t\tsetIsPointing(false)\n\t\t\t// Reset the pointer state\n\t\t\trPointerState.current = {\n\t\t\t\tisDown: false,\n\t\t\t\tisDragging: false,\n\t\t\t\tstart: new Vec(e.clientX, e.clientY),\n\t\t\t}\n\t\t},\n\t\t[canvasEvents]\n\t)\n\n\treturn (\n\t\tshowElement && (\n\t\t\t<div\n\t\t\t\tclassName=\"tlui-menu-click-capture\"\n\t\t\t\tdata-testid=\"menu-click-capture.content\"\n\t\t\t\t{...canvasEvents}\n\t\t\t\tonPointerDown={handlePointerDown}\n\t\t\t\tonPointerMove={handlePointerMove}\n\t\t\t\tonPointerUp={handlePointerUp}\n\t\t\t/>\n\t\t)\n\t)\n}\n"],
|
|
5
|
+
"mappings": "AAsGG;AAtGH,SAAS,gBAAgB;AACzB,SAAuB,aAAa,QAAQ,gBAAgB;AAC5D,SAAS,uBAAuB;AAChC,SAAS,iBAAiB;AAC1B,SAAS,WAAW;AAOb,SAAS,mBAAmB;AAClC,QAAM,SAAS,UAAU;AAGzB,QAAM,aAAa,SAAS,gBAAgB,MAAM,OAAO,MAAM,gBAAgB,GAAG,CAAC,MAAM,CAAC;AAG1F,QAAM,CAAC,YAAY,aAAa,IAAI,SAAS,KAAK;AAElD,QAAM,cAAc,cAAc;AAGlC,QAAM,eAAe,gBAAgB;AAGrC,QAAM,gBAAgB,OAAO;AAAA,IAC5B,QAAQ;AAAA,IACR,YAAY;AAAA,IACZ,OAAO,IAAI,IAAI;AAAA,EAChB,CAAC;AAED,QAAM,oBAAoB;AAAA,IACzB,CAAC,MAAoB;AACpB,UAAI,EAAE,WAAW,GAAG;AACnB,sBAAc,IAAI;AAClB,sBAAc,UAAU;AAAA,UACvB,QAAQ;AAAA,UACR,YAAY;AAAA,UACZ,OAAO,IAAI,IAAI,EAAE,SAAS,EAAE,OAAO;AAAA,QACpC;AAAA,MACD;AACA,aAAO,MAAM,eAAe;AAAA,IAC7B;AAAA,IACA,CAAC,MAAM;AAAA,EACR;AAEA,QAAM,oBAAoB;AAAA,IACzB,CAAC,MAAoB;AAEpB,UAAI,CAAC,cAAc,QAAQ,OAAQ;AAGnC,UAAI,cAAc,QAAQ,YAAY;AACrC,qBAAa,gBAAgB,CAAC;AAC9B;AAAA,MACD;AAEA;AAAA;AAAA,QAEC,IAAI,MAAM,cAAc,QAAQ,OAAO,IAAI,IAAI,EAAE,SAAS,EAAE,OAAO,CAAC,IACpE,OAAO,QAAQ;AAAA,QACd;AAED,sBAAc,UAAU;AAAA,UACvB,GAAG,cAAc;AAAA,UACjB,QAAQ;AAAA,UACR,YAAY;AAAA,QACb;AAEA,cAAM,EAAE,GAAG,EAAE,IAAI,cAAc,QAAQ;AACvC,qBAAa,gBAAgB;AAAA,UAC5B,GAAG;AAAA,UACH,SAAS;AAAA,UACT,SAAS;AAAA,UACT,QAAQ;AAAA,QACT,CAAC;AAED,qBAAa,gBAAgB,CAAC;AAAA,MAC/B;AAAA,IACD;AAAA,IACA,CAAC,cAAc,MAAM;AAAA,EACtB;AAEA,QAAM,kBAAkB;AAAA,IACvB,CAAC,MAAoB;AAEpB,mBAAa,cAAc,CAAC;AAE5B,oBAAc,KAAK;AAEnB,oBAAc,UAAU;AAAA,QACvB,QAAQ;AAAA,QACR,YAAY;AAAA,QACZ,OAAO,IAAI,IAAI,EAAE,SAAS,EAAE,OAAO;AAAA,MACpC;AAAA,IACD;AAAA,IACA,CAAC,YAAY;AAAA,EACd;AAEA,SACC,eACC;AAAA,IAAC;AAAA;AAAA,MACA,WAAU;AAAA,MACV,eAAY;AAAA,MACX,GAAG;AAAA,MACJ,eAAe;AAAA,MACf,eAAe;AAAA,MACf,aAAa;AAAA;AAAA,EACd;AAGH;",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -3944,6 +3944,7 @@ class Editor extends (_a = EventEmitter, _getIsShapeHiddenCache_dec = [computed]
|
|
|
3944
3944
|
hitInside = false,
|
|
3945
3945
|
hitFrameInside = false
|
|
3946
3946
|
} = opts;
|
|
3947
|
+
const [innerMargin, outerMargin] = Array.isArray(margin) ? margin : [margin, margin];
|
|
3947
3948
|
let inHollowSmallestArea = Infinity;
|
|
3948
3949
|
let inHollowSmallestAreaHit = null;
|
|
3949
3950
|
let inMarginClosestToEdgeDistance = Infinity;
|
|
@@ -3953,7 +3954,7 @@ class Editor extends (_a = EventEmitter, _getIsShapeHiddenCache_dec = [computed]
|
|
|
3953
3954
|
return false;
|
|
3954
3955
|
const pageMask = this.getShapeMask(shape);
|
|
3955
3956
|
if (pageMask && !pointInPolygon(point, pageMask)) return false;
|
|
3956
|
-
if (filter
|
|
3957
|
+
if (filter && !filter(shape)) return false;
|
|
3957
3958
|
return true;
|
|
3958
3959
|
});
|
|
3959
3960
|
for (let i = shapesToCheck.length - 1; i >= 0; i--) {
|
|
@@ -3969,8 +3970,8 @@ class Editor extends (_a = EventEmitter, _getIsShapeHiddenCache_dec = [computed]
|
|
|
3969
3970
|
}
|
|
3970
3971
|
}
|
|
3971
3972
|
if (this.isShapeOfType(shape, "frame")) {
|
|
3972
|
-
const distance2 = geometry.distanceToPoint(pointInShapeSpace,
|
|
3973
|
-
if (
|
|
3973
|
+
const distance2 = geometry.distanceToPoint(pointInShapeSpace, hitFrameInside);
|
|
3974
|
+
if (hitFrameInside ? distance2 > 0 && distance2 <= outerMargin || distance2 <= 0 && distance2 > -innerMargin : distance2 > 0 && distance2 <= outerMargin) {
|
|
3974
3975
|
return inMarginClosestToEdgeHit || shape;
|
|
3975
3976
|
}
|
|
3976
3977
|
if (geometry.hitTestPoint(pointInShapeSpace, 0, true)) {
|
|
@@ -3990,10 +3991,10 @@ class Editor extends (_a = EventEmitter, _getIsShapeHiddenCache_dec = [computed]
|
|
|
3990
3991
|
}
|
|
3991
3992
|
distance = minDistance;
|
|
3992
3993
|
} else {
|
|
3993
|
-
if (
|
|
3994
|
+
if (outerMargin === 0 && (geometry.bounds.w < 1 || geometry.bounds.h < 1)) {
|
|
3994
3995
|
distance = geometry.distanceToPoint(pointInShapeSpace, hitInside);
|
|
3995
3996
|
} else {
|
|
3996
|
-
if (geometry.bounds.containsPoint(pointInShapeSpace,
|
|
3997
|
+
if (geometry.bounds.containsPoint(pointInShapeSpace, outerMargin)) {
|
|
3997
3998
|
distance = geometry.distanceToPoint(pointInShapeSpace, hitInside);
|
|
3998
3999
|
} else {
|
|
3999
4000
|
distance = Infinity;
|
|
@@ -4001,12 +4002,22 @@ class Editor extends (_a = EventEmitter, _getIsShapeHiddenCache_dec = [computed]
|
|
|
4001
4002
|
}
|
|
4002
4003
|
}
|
|
4003
4004
|
if (geometry.isClosed) {
|
|
4004
|
-
if (distance <=
|
|
4005
|
+
if (distance <= outerMargin || hitInside && distance <= 0 && distance > -innerMargin) {
|
|
4005
4006
|
if (geometry.isFilled || isGroup && geometry.children[0].isFilled) {
|
|
4006
4007
|
return inMarginClosestToEdgeHit || shape;
|
|
4007
4008
|
} else {
|
|
4008
4009
|
if (this.getShapePageBounds(shape).contains(viewportPageBounds)) continue;
|
|
4009
|
-
if (
|
|
4010
|
+
if (hitInside ? (
|
|
4011
|
+
// On hitInside, the distance will be negative for hits inside
|
|
4012
|
+
// If the distance is positive, check against the outer margin
|
|
4013
|
+
(// If the distance is negative, check against the inner margin
|
|
4014
|
+
distance > 0 && distance <= outerMargin || distance <= 0 && distance > -innerMargin)
|
|
4015
|
+
) : (
|
|
4016
|
+
// If hitInside is false, then sadly _we do not know_ whether the
|
|
4017
|
+
// point is inside or outside of the shape, so we check against
|
|
4018
|
+
// the max of the two margins
|
|
4019
|
+
(Math.abs(distance) <= Math.max(innerMargin, outerMargin))
|
|
4020
|
+
)) {
|
|
4010
4021
|
if (Math.abs(distance) < inMarginClosestToEdgeDistance) {
|
|
4011
4022
|
inMarginClosestToEdgeDistance = Math.abs(distance);
|
|
4012
4023
|
inMarginClosestToEdgeHit = shape;
|
|
@@ -5525,8 +5536,7 @@ class Editor extends (_a = EventEmitter, _getIsShapeHiddenCache_dec = [computed]
|
|
|
5525
5536
|
const shapesMovingTogether = [shape];
|
|
5526
5537
|
const boundsOfShapesMovingTogether = [shapePageBounds];
|
|
5527
5538
|
if (!this.getShapeUtil(shape).canBeLaidOut?.(shape, {
|
|
5528
|
-
type: "stretch"
|
|
5529
|
-
shapes: shapesToStretchFirstPass
|
|
5539
|
+
type: "stretch"
|
|
5530
5540
|
})) {
|
|
5531
5541
|
continue;
|
|
5532
5542
|
}
|