@tldraw/editor 4.3.0-canary.c7096a59bf3b → 4.3.0-canary.cb6779b4f066
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/README.md +1 -1
- package/dist-cjs/index.d.ts +446 -120
- package/dist-cjs/index.js +8 -1
- package/dist-cjs/index.js.map +2 -2
- package/dist-cjs/lib/components/ErrorBoundary.js.map +1 -1
- package/dist-cjs/lib/components/GeometryDebuggingView.js +1 -17
- package/dist-cjs/lib/components/GeometryDebuggingView.js.map +2 -2
- package/dist-cjs/lib/components/default-components/DefaultCanvas.js +4 -5
- package/dist-cjs/lib/components/default-components/DefaultCanvas.js.map +2 -2
- package/dist-cjs/lib/constants.js +1 -3
- package/dist-cjs/lib/constants.js.map +2 -2
- package/dist-cjs/lib/editor/Editor.js +342 -280
- package/dist-cjs/lib/editor/Editor.js.map +2 -2
- package/dist-cjs/lib/editor/derivations/notVisibleShapes.js +16 -23
- package/dist-cjs/lib/editor/derivations/notVisibleShapes.js.map +3 -3
- package/dist-cjs/lib/editor/derivations/parentsToChildren.js +12 -3
- package/dist-cjs/lib/editor/derivations/parentsToChildren.js.map +2 -2
- package/dist-cjs/lib/editor/managers/ClickManager/ClickManager.js +1 -1
- package/dist-cjs/lib/editor/managers/ClickManager/ClickManager.js.map +2 -2
- package/dist-cjs/lib/editor/managers/EdgeScrollManager/EdgeScrollManager.js +5 -6
- package/dist-cjs/lib/editor/managers/EdgeScrollManager/EdgeScrollManager.js.map +2 -2
- package/dist-cjs/lib/editor/managers/InputsManager/InputsManager.js +591 -0
- package/dist-cjs/lib/editor/managers/InputsManager/InputsManager.js.map +7 -0
- package/dist-cjs/lib/editor/managers/SnapManager/SnapManager.js +1 -1
- package/dist-cjs/lib/editor/managers/SnapManager/SnapManager.js.map +2 -2
- package/dist-cjs/lib/editor/managers/SpatialIndexManager/RBushIndex.js +144 -0
- package/dist-cjs/lib/editor/managers/SpatialIndexManager/RBushIndex.js.map +7 -0
- package/dist-cjs/lib/editor/managers/SpatialIndexManager/SpatialIndexManager.js +181 -0
- package/dist-cjs/lib/editor/managers/SpatialIndexManager/SpatialIndexManager.js.map +7 -0
- package/dist-cjs/lib/editor/managers/TickManager/TickManager.js +1 -22
- package/dist-cjs/lib/editor/managers/TickManager/TickManager.js.map +2 -2
- package/dist-cjs/lib/editor/shapes/ShapeUtil.js +31 -23
- package/dist-cjs/lib/editor/shapes/ShapeUtil.js.map +2 -2
- package/dist-cjs/lib/editor/shapes/group/DashedOutlineBox.js +1 -1
- package/dist-cjs/lib/editor/shapes/group/DashedOutlineBox.js.map +2 -2
- package/dist-cjs/lib/editor/tools/BaseBoxShapeTool/children/Pointing.js +3 -3
- package/dist-cjs/lib/editor/tools/BaseBoxShapeTool/children/Pointing.js.map +2 -2
- package/dist-cjs/lib/exports/parseCss.js +1 -1
- package/dist-cjs/lib/exports/parseCss.js.map +2 -2
- package/dist-cjs/lib/globals/environment.js +45 -9
- package/dist-cjs/lib/globals/environment.js.map +2 -2
- package/dist-cjs/lib/hooks/useCoarsePointer.js +14 -29
- package/dist-cjs/lib/hooks/useCoarsePointer.js.map +2 -2
- package/dist-cjs/lib/hooks/useEvent.js +1 -1
- package/dist-cjs/lib/hooks/useEvent.js.map +2 -2
- package/dist-cjs/lib/hooks/useFixSafariDoubleTapZoomPencilEvents.js.map +2 -2
- package/dist-cjs/lib/hooks/useGestureEvents.js +1 -1
- package/dist-cjs/lib/hooks/useGestureEvents.js.map +2 -2
- package/dist-cjs/lib/hooks/usePassThroughMouseOverEvents.js.map +2 -2
- package/dist-cjs/lib/hooks/usePassThroughWheelEvents.js.map +2 -2
- package/dist-cjs/lib/hooks/useScreenBounds.js.map +2 -2
- package/dist-cjs/lib/hooks/useStateAttribute.js +4 -1
- package/dist-cjs/lib/hooks/useStateAttribute.js.map +2 -2
- package/dist-cjs/lib/hooks/useTransform.js.map +1 -1
- package/dist-cjs/lib/hooks/useZoomCss.js +4 -8
- package/dist-cjs/lib/hooks/useZoomCss.js.map +2 -2
- package/dist-cjs/lib/options.js +6 -1
- package/dist-cjs/lib/options.js.map +2 -2
- package/dist-cjs/lib/primitives/Box.js +3 -0
- package/dist-cjs/lib/primitives/Box.js.map +2 -2
- package/dist-cjs/lib/primitives/geometry/Geometry2d.js +1 -0
- package/dist-cjs/lib/primitives/geometry/Geometry2d.js.map +2 -2
- package/dist-cjs/lib/utils/rotation.js +1 -1
- package/dist-cjs/lib/utils/rotation.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 +446 -120
- package/dist-esm/index.mjs +9 -2
- package/dist-esm/index.mjs.map +2 -2
- package/dist-esm/lib/components/ErrorBoundary.mjs.map +1 -1
- package/dist-esm/lib/components/GeometryDebuggingView.mjs +1 -17
- package/dist-esm/lib/components/GeometryDebuggingView.mjs.map +2 -2
- package/dist-esm/lib/components/default-components/DefaultCanvas.mjs +4 -5
- package/dist-esm/lib/components/default-components/DefaultCanvas.mjs.map +2 -2
- package/dist-esm/lib/constants.mjs +1 -3
- package/dist-esm/lib/constants.mjs.map +2 -2
- package/dist-esm/lib/editor/Editor.mjs +343 -283
- package/dist-esm/lib/editor/Editor.mjs.map +2 -2
- package/dist-esm/lib/editor/derivations/notVisibleShapes.mjs +16 -23
- package/dist-esm/lib/editor/derivations/notVisibleShapes.mjs.map +3 -3
- package/dist-esm/lib/editor/derivations/parentsToChildren.mjs +13 -4
- package/dist-esm/lib/editor/derivations/parentsToChildren.mjs.map +2 -2
- package/dist-esm/lib/editor/managers/ClickManager/ClickManager.mjs +1 -1
- package/dist-esm/lib/editor/managers/ClickManager/ClickManager.mjs.map +2 -2
- package/dist-esm/lib/editor/managers/EdgeScrollManager/EdgeScrollManager.mjs +5 -6
- package/dist-esm/lib/editor/managers/EdgeScrollManager/EdgeScrollManager.mjs.map +2 -2
- package/dist-esm/lib/editor/managers/InputsManager/InputsManager.mjs +573 -0
- package/dist-esm/lib/editor/managers/InputsManager/InputsManager.mjs.map +7 -0
- package/dist-esm/lib/editor/managers/SnapManager/SnapManager.mjs +1 -1
- package/dist-esm/lib/editor/managers/SnapManager/SnapManager.mjs.map +2 -2
- package/dist-esm/lib/editor/managers/SpatialIndexManager/RBushIndex.mjs +114 -0
- package/dist-esm/lib/editor/managers/SpatialIndexManager/RBushIndex.mjs.map +7 -0
- package/dist-esm/lib/editor/managers/SpatialIndexManager/SpatialIndexManager.mjs +161 -0
- package/dist-esm/lib/editor/managers/SpatialIndexManager/SpatialIndexManager.mjs.map +7 -0
- package/dist-esm/lib/editor/managers/TickManager/TickManager.mjs +1 -22
- package/dist-esm/lib/editor/managers/TickManager/TickManager.mjs.map +2 -2
- package/dist-esm/lib/editor/shapes/ShapeUtil.mjs +31 -23
- package/dist-esm/lib/editor/shapes/ShapeUtil.mjs.map +2 -2
- package/dist-esm/lib/editor/shapes/group/DashedOutlineBox.mjs +1 -1
- package/dist-esm/lib/editor/shapes/group/DashedOutlineBox.mjs.map +2 -2
- package/dist-esm/lib/editor/tools/BaseBoxShapeTool/children/Pointing.mjs +3 -3
- package/dist-esm/lib/editor/tools/BaseBoxShapeTool/children/Pointing.mjs.map +2 -2
- package/dist-esm/lib/exports/parseCss.mjs +1 -1
- package/dist-esm/lib/exports/parseCss.mjs.map +2 -2
- package/dist-esm/lib/globals/environment.mjs +45 -9
- package/dist-esm/lib/globals/environment.mjs.map +2 -2
- package/dist-esm/lib/hooks/useCoarsePointer.mjs +15 -30
- package/dist-esm/lib/hooks/useCoarsePointer.mjs.map +2 -2
- package/dist-esm/lib/hooks/useEvent.mjs +1 -1
- package/dist-esm/lib/hooks/useEvent.mjs.map +2 -2
- package/dist-esm/lib/hooks/useFixSafariDoubleTapZoomPencilEvents.mjs.map +2 -2
- package/dist-esm/lib/hooks/useGestureEvents.mjs +1 -1
- package/dist-esm/lib/hooks/useGestureEvents.mjs.map +2 -2
- package/dist-esm/lib/hooks/usePassThroughMouseOverEvents.mjs.map +2 -2
- package/dist-esm/lib/hooks/usePassThroughWheelEvents.mjs.map +2 -2
- package/dist-esm/lib/hooks/useScreenBounds.mjs.map +2 -2
- package/dist-esm/lib/hooks/useStateAttribute.mjs +4 -1
- package/dist-esm/lib/hooks/useStateAttribute.mjs.map +2 -2
- package/dist-esm/lib/hooks/useTransform.mjs.map +1 -1
- package/dist-esm/lib/hooks/useZoomCss.mjs +4 -8
- package/dist-esm/lib/hooks/useZoomCss.mjs.map +2 -2
- package/dist-esm/lib/options.mjs +6 -1
- package/dist-esm/lib/options.mjs.map +2 -2
- package/dist-esm/lib/primitives/Box.mjs +3 -0
- package/dist-esm/lib/primitives/Box.mjs.map +2 -2
- package/dist-esm/lib/primitives/geometry/Geometry2d.mjs +1 -0
- package/dist-esm/lib/primitives/geometry/Geometry2d.mjs.map +2 -2
- package/dist-esm/lib/utils/rotation.mjs +1 -1
- package/dist-esm/lib/utils/rotation.mjs.map +2 -2
- package/dist-esm/version.mjs +3 -3
- package/dist-esm/version.mjs.map +1 -1
- package/editor.css +14 -12
- package/package.json +21 -17
- package/src/index.ts +5 -1
- package/src/lib/components/ErrorBoundary.tsx +1 -1
- package/src/lib/components/GeometryDebuggingView.tsx +1 -19
- package/src/lib/components/default-components/DefaultCanvas.tsx +4 -8
- package/src/lib/config/TLUserPreferences.test.ts +40 -0
- package/src/lib/constants.ts +0 -2
- package/src/lib/editor/Editor.test.ts +140 -0
- package/src/lib/editor/Editor.ts +448 -326
- package/src/lib/editor/derivations/notVisibleShapes.ts +21 -33
- package/src/lib/editor/derivations/parentsToChildren.ts +18 -7
- package/src/lib/editor/managers/ClickManager/ClickManager.test.ts +17 -31
- package/src/lib/editor/managers/ClickManager/ClickManager.ts +1 -1
- package/src/lib/editor/managers/EdgeScrollManager/EdgeScrollManager.test.ts +129 -79
- package/src/lib/editor/managers/EdgeScrollManager/EdgeScrollManager.ts +10 -6
- package/src/lib/editor/managers/InputsManager/InputsManager.ts +566 -0
- package/src/lib/editor/managers/ScribbleManager/ScribbleManager.test.ts +0 -4
- package/src/lib/editor/managers/SnapManager/SnapManager.test.ts +12 -0
- package/src/lib/editor/managers/SnapManager/SnapManager.ts +1 -1
- package/src/lib/editor/managers/SpatialIndexManager/RBushIndex.ts +144 -0
- package/src/lib/editor/managers/SpatialIndexManager/SpatialIndexManager.ts +215 -0
- package/src/lib/editor/managers/TickManager/TickManager.test.ts +40 -107
- package/src/lib/editor/managers/TickManager/TickManager.ts +2 -32
- package/src/lib/editor/shapes/ShapeUtil.ts +67 -24
- package/src/lib/editor/shapes/group/DashedOutlineBox.tsx +1 -1
- package/src/lib/editor/tools/BaseBoxShapeTool/children/Pointing.ts +3 -3
- package/src/lib/exports/parseCss.test.ts +1 -0
- package/src/lib/exports/parseCss.ts +1 -1
- package/src/lib/globals/environment.ts +65 -10
- package/src/lib/hooks/useCoarsePointer.ts +16 -59
- package/src/lib/hooks/useEvent.tsx +1 -1
- package/src/lib/hooks/useFixSafariDoubleTapZoomPencilEvents.ts +1 -1
- package/src/lib/hooks/useGestureEvents.ts +2 -2
- package/src/lib/hooks/usePassThroughMouseOverEvents.ts +1 -1
- package/src/lib/hooks/usePassThroughWheelEvents.ts +1 -1
- package/src/lib/hooks/useScreenBounds.ts +1 -1
- package/src/lib/hooks/useStateAttribute.ts +4 -1
- package/src/lib/hooks/useTransform.ts +1 -1
- package/src/lib/hooks/useZoomCss.ts +3 -8
- package/src/lib/options.ts +32 -0
- package/src/lib/primitives/Box.ts +9 -0
- package/src/lib/primitives/geometry/Geometry2d.ts +1 -0
- package/src/lib/utils/rotation.ts +1 -1
- package/src/version.ts +3 -3
|
@@ -16,7 +16,7 @@ function getRotationSnapshot({
|
|
|
16
16
|
const initialPageCenter = rotatedPageBounds.center.clone().rotWith(rotatedPageBounds.point, rotation);
|
|
17
17
|
return {
|
|
18
18
|
initialPageCenter,
|
|
19
|
-
initialCursorAngle: initialPageCenter.angle(editor.inputs.
|
|
19
|
+
initialCursorAngle: initialPageCenter.angle(editor.inputs.getOriginPagePoint()),
|
|
20
20
|
initialShapesRotation: rotation,
|
|
21
21
|
shapeSnapshots: shapes.map((shape) => ({
|
|
22
22
|
shape,
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../src/lib/utils/rotation.ts"],
|
|
4
|
-
"sourcesContent": ["import { isShapeId, TLShape, TLShapeId, TLShapePartial } from '@tldraw/tlschema'\nimport { compact } from '@tldraw/utils'\nimport { Editor } from '../editor/Editor'\nimport { Mat } from '../primitives/Mat'\nimport { canonicalizeRotation } from '../primitives/utils'\nimport { Vec, VecLike } from '../primitives/Vec'\n\n/** @internal */\nexport function getRotationSnapshot({\n\teditor,\n\tids,\n}: {\n\teditor: Editor\n\tids: TLShapeId[]\n}): TLRotationSnapshot | null {\n\tconst shapes = compact(ids.map((id) => editor.getShape(id)))\n\tconst rotation = editor.getShapesSharedRotation(ids)\n\tconst rotatedPageBounds = editor.getShapesRotatedPageBounds(ids)\n\n\t// todo: this assumes we're rotating the selected shapes\n\t// if we try to rotate shapes that aren't selected, this\n\t// will produce the wrong results\n\n\t// Return null if there are no selected shapes\n\tif (!rotatedPageBounds) {\n\t\treturn null\n\t}\n\n\tconst initialPageCenter = rotatedPageBounds.center\n\t\t.clone()\n\t\t.rotWith(rotatedPageBounds.point, rotation)\n\n\treturn {\n\t\tinitialPageCenter,\n\t\tinitialCursorAngle: initialPageCenter.angle(editor.inputs.
|
|
5
|
-
"mappings": "AAAA,SAAS,iBAAqD;AAC9D,SAAS,eAAe;AAExB,SAAS,WAAW;AACpB,SAAS,4BAA4B;AACrC,SAAS,WAAoB;AAGtB,SAAS,oBAAoB;AAAA,EACnC;AAAA,EACA;AACD,GAG8B;AAC7B,QAAM,SAAS,QAAQ,IAAI,IAAI,CAAC,OAAO,OAAO,SAAS,EAAE,CAAC,CAAC;AAC3D,QAAM,WAAW,OAAO,wBAAwB,GAAG;AACnD,QAAM,oBAAoB,OAAO,2BAA2B,GAAG;AAO/D,MAAI,CAAC,mBAAmB;AACvB,WAAO;AAAA,EACR;AAEA,QAAM,oBAAoB,kBAAkB,OAC1C,MAAM,EACN,QAAQ,kBAAkB,OAAO,QAAQ;AAE3C,SAAO;AAAA,IACN;AAAA,IACA,oBAAoB,kBAAkB,MAAM,OAAO,OAAO,
|
|
4
|
+
"sourcesContent": ["import { isShapeId, TLShape, TLShapeId, TLShapePartial } from '@tldraw/tlschema'\nimport { compact } from '@tldraw/utils'\nimport { Editor } from '../editor/Editor'\nimport { Mat } from '../primitives/Mat'\nimport { canonicalizeRotation } from '../primitives/utils'\nimport { Vec, VecLike } from '../primitives/Vec'\n\n/** @internal */\nexport function getRotationSnapshot({\n\teditor,\n\tids,\n}: {\n\teditor: Editor\n\tids: TLShapeId[]\n}): TLRotationSnapshot | null {\n\tconst shapes = compact(ids.map((id) => editor.getShape(id)))\n\tconst rotation = editor.getShapesSharedRotation(ids)\n\tconst rotatedPageBounds = editor.getShapesRotatedPageBounds(ids)\n\n\t// todo: this assumes we're rotating the selected shapes\n\t// if we try to rotate shapes that aren't selected, this\n\t// will produce the wrong results\n\n\t// Return null if there are no selected shapes\n\tif (!rotatedPageBounds) {\n\t\treturn null\n\t}\n\n\tconst initialPageCenter = rotatedPageBounds.center\n\t\t.clone()\n\t\t.rotWith(rotatedPageBounds.point, rotation)\n\n\treturn {\n\t\tinitialPageCenter,\n\t\tinitialCursorAngle: initialPageCenter.angle(editor.inputs.getOriginPagePoint()),\n\t\tinitialShapesRotation: rotation,\n\t\tshapeSnapshots: shapes.map((shape) => ({\n\t\t\tshape,\n\t\t\tinitialPagePoint: editor.getShapePageTransform(shape.id)!.point(),\n\t\t})),\n\t}\n}\n\n/**\n * @internal\n **/\nexport interface TLRotationSnapshot {\n\tinitialPageCenter: Vec\n\tinitialCursorAngle: number\n\tinitialShapesRotation: number\n\tshapeSnapshots: {\n\t\tshape: TLShape\n\t\tinitialPagePoint: Vec\n\t}[]\n}\n\n/** @internal */\nexport function applyRotationToSnapshotShapes({\n\tdelta,\n\teditor,\n\tsnapshot,\n\tstage,\n\tcenterOverride,\n}: {\n\tdelta: number\n\tsnapshot: TLRotationSnapshot\n\teditor: Editor\n\tstage: 'start' | 'update' | 'end' | 'one-off'\n\tcenterOverride?: VecLike\n}) {\n\tconst { initialPageCenter, shapeSnapshots } = snapshot\n\n\teditor.updateShapes(\n\t\tshapeSnapshots.map(({ shape, initialPagePoint }) => {\n\t\t\t// We need to both rotate each shape individually and rotate the shapes\n\t\t\t// around the pivot point (the average center of all rotating shapes.)\n\n\t\t\tconst parentTransform = isShapeId(shape.parentId)\n\t\t\t\t? editor.getShapePageTransform(shape.parentId)!\n\t\t\t\t: Mat.Identity()\n\n\t\t\tconst newPagePoint = Vec.RotWith(initialPagePoint, centerOverride ?? initialPageCenter, delta)\n\n\t\t\tconst newLocalPoint = Mat.applyToPoint(\n\t\t\t\t// use the current parent transform in case it has moved/resized since the start\n\t\t\t\t// (e.g. if rotating a shape at the edge of a group)\n\t\t\t\tMat.Inverse(parentTransform),\n\t\t\t\tnewPagePoint\n\t\t\t)\n\t\t\tconst newRotation = canonicalizeRotation(shape.rotation + delta)\n\n\t\t\treturn {\n\t\t\t\tid: shape.id,\n\t\t\t\ttype: shape.type,\n\t\t\t\tx: newLocalPoint.x,\n\t\t\t\ty: newLocalPoint.y,\n\t\t\t\trotation: newRotation,\n\t\t\t}\n\t\t})\n\t)\n\n\t// Handle change\n\n\tconst changes: TLShapePartial[] = []\n\n\tshapeSnapshots.forEach(({ shape }) => {\n\t\tconst current = editor.getShape(shape.id)\n\t\tif (!current) return\n\t\tconst util = editor.getShapeUtil(shape)\n\n\t\tif (stage === 'start' || stage === 'one-off') {\n\t\t\tconst changeStart = util.onRotateStart?.(shape)\n\t\t\tif (changeStart) changes.push(changeStart)\n\t\t}\n\n\t\tconst changeUpdate = util.onRotate?.(shape, current)\n\t\tif (changeUpdate) changes.push(changeUpdate)\n\n\t\tif (stage === 'end' || stage === 'one-off') {\n\t\t\tconst changeEnd = util.onRotateEnd?.(shape, current)\n\t\t\tif (changeEnd) changes.push(changeEnd)\n\t\t}\n\t})\n\n\tif (changes.length > 0) {\n\t\teditor.updateShapes(changes)\n\t}\n}\n"],
|
|
5
|
+
"mappings": "AAAA,SAAS,iBAAqD;AAC9D,SAAS,eAAe;AAExB,SAAS,WAAW;AACpB,SAAS,4BAA4B;AACrC,SAAS,WAAoB;AAGtB,SAAS,oBAAoB;AAAA,EACnC;AAAA,EACA;AACD,GAG8B;AAC7B,QAAM,SAAS,QAAQ,IAAI,IAAI,CAAC,OAAO,OAAO,SAAS,EAAE,CAAC,CAAC;AAC3D,QAAM,WAAW,OAAO,wBAAwB,GAAG;AACnD,QAAM,oBAAoB,OAAO,2BAA2B,GAAG;AAO/D,MAAI,CAAC,mBAAmB;AACvB,WAAO;AAAA,EACR;AAEA,QAAM,oBAAoB,kBAAkB,OAC1C,MAAM,EACN,QAAQ,kBAAkB,OAAO,QAAQ;AAE3C,SAAO;AAAA,IACN;AAAA,IACA,oBAAoB,kBAAkB,MAAM,OAAO,OAAO,mBAAmB,CAAC;AAAA,IAC9E,uBAAuB;AAAA,IACvB,gBAAgB,OAAO,IAAI,CAAC,WAAW;AAAA,MACtC;AAAA,MACA,kBAAkB,OAAO,sBAAsB,MAAM,EAAE,EAAG,MAAM;AAAA,IACjE,EAAE;AAAA,EACH;AACD;AAgBO,SAAS,8BAA8B;AAAA,EAC7C;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACD,GAMG;AACF,QAAM,EAAE,mBAAmB,eAAe,IAAI;AAE9C,SAAO;AAAA,IACN,eAAe,IAAI,CAAC,EAAE,OAAO,iBAAiB,MAAM;AAInD,YAAM,kBAAkB,UAAU,MAAM,QAAQ,IAC7C,OAAO,sBAAsB,MAAM,QAAQ,IAC3C,IAAI,SAAS;AAEhB,YAAM,eAAe,IAAI,QAAQ,kBAAkB,kBAAkB,mBAAmB,KAAK;AAE7F,YAAM,gBAAgB,IAAI;AAAA;AAAA;AAAA,QAGzB,IAAI,QAAQ,eAAe;AAAA,QAC3B;AAAA,MACD;AACA,YAAM,cAAc,qBAAqB,MAAM,WAAW,KAAK;AAE/D,aAAO;AAAA,QACN,IAAI,MAAM;AAAA,QACV,MAAM,MAAM;AAAA,QACZ,GAAG,cAAc;AAAA,QACjB,GAAG,cAAc;AAAA,QACjB,UAAU;AAAA,MACX;AAAA,IACD,CAAC;AAAA,EACF;AAIA,QAAM,UAA4B,CAAC;AAEnC,iBAAe,QAAQ,CAAC,EAAE,MAAM,MAAM;AACrC,UAAM,UAAU,OAAO,SAAS,MAAM,EAAE;AACxC,QAAI,CAAC,QAAS;AACd,UAAM,OAAO,OAAO,aAAa,KAAK;AAEtC,QAAI,UAAU,WAAW,UAAU,WAAW;AAC7C,YAAM,cAAc,KAAK,gBAAgB,KAAK;AAC9C,UAAI,YAAa,SAAQ,KAAK,WAAW;AAAA,IAC1C;AAEA,UAAM,eAAe,KAAK,WAAW,OAAO,OAAO;AACnD,QAAI,aAAc,SAAQ,KAAK,YAAY;AAE3C,QAAI,UAAU,SAAS,UAAU,WAAW;AAC3C,YAAM,YAAY,KAAK,cAAc,OAAO,OAAO;AACnD,UAAI,UAAW,SAAQ,KAAK,SAAS;AAAA,IACtC;AAAA,EACD,CAAC;AAED,MAAI,QAAQ,SAAS,GAAG;AACvB,WAAO,aAAa,OAAO;AAAA,EAC5B;AACD;",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
package/dist-esm/version.mjs
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
const version = "4.3.0-canary.
|
|
1
|
+
const version = "4.3.0-canary.cb6779b4f066";
|
|
2
2
|
const publishDates = {
|
|
3
3
|
major: "2025-09-18T14:39:22.803Z",
|
|
4
|
-
minor: "
|
|
5
|
-
patch: "
|
|
4
|
+
minor: "2026-01-18T00:37:30.564Z",
|
|
5
|
+
patch: "2026-01-18T00:37:30.564Z"
|
|
6
6
|
};
|
|
7
7
|
export {
|
|
8
8
|
publishDates,
|
package/dist-esm/version.mjs.map
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../src/version.ts"],
|
|
4
|
-
"sourcesContent": ["// This file is automatically generated by internal/scripts/refresh-assets.ts.\n// Do not edit manually. Or do, I'm a comment, not a cop.\n\nexport const version = '4.3.0-canary.
|
|
4
|
+
"sourcesContent": ["// This file is automatically generated by internal/scripts/refresh-assets.ts.\n// Do not edit manually. Or do, I'm a comment, not a cop.\n\nexport const version = '4.3.0-canary.cb6779b4f066'\nexport const publishDates = {\n\tmajor: '2025-09-18T14:39:22.803Z',\n\tminor: '2026-01-18T00:37:30.564Z',\n\tpatch: '2026-01-18T00:37:30.564Z',\n}\n"],
|
|
5
5
|
"mappings": "AAGO,MAAM,UAAU;AAChB,MAAM,eAAe;AAAA,EAC3B,OAAO;AAAA,EACP,OAAO;AAAA,EACP,OAAO;AACR;",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
package/editor.css
CHANGED
|
@@ -607,7 +607,6 @@ input,
|
|
|
607
607
|
pointer-events: all;
|
|
608
608
|
white-space: pre-wrap;
|
|
609
609
|
overflow-wrap: break-word;
|
|
610
|
-
text-shadow: var(--tl-text-outline);
|
|
611
610
|
}
|
|
612
611
|
|
|
613
612
|
.tl-text-wrapper[data-font='draw'] {
|
|
@@ -709,7 +708,7 @@ input,
|
|
|
709
708
|
resize: none;
|
|
710
709
|
border: none;
|
|
711
710
|
user-select: none;
|
|
712
|
-
contain: style paint;
|
|
711
|
+
contain: layout style paint;
|
|
713
712
|
/* N.B. This property, while discouraged ("intended for Document Type Definition (DTD) designers") is necessary for ensuring correct mixed RTL/LTR behavior when exporting SVGs. */
|
|
714
713
|
unicode-bidi: plaintext;
|
|
715
714
|
-webkit-user-select: none;
|
|
@@ -770,7 +769,6 @@ input,
|
|
|
770
769
|
justify-content: center;
|
|
771
770
|
align-items: center;
|
|
772
771
|
color: var(--tl-color-text);
|
|
773
|
-
text-shadow: var(--tl-text-outline);
|
|
774
772
|
line-height: inherit;
|
|
775
773
|
position: absolute;
|
|
776
774
|
inset: 0px;
|
|
@@ -970,6 +968,14 @@ input,
|
|
|
970
968
|
display: block;
|
|
971
969
|
}
|
|
972
970
|
|
|
971
|
+
.tl-text__outline {
|
|
972
|
+
text-shadow: var(--tl-text-outline);
|
|
973
|
+
}
|
|
974
|
+
|
|
975
|
+
.tl-text__no-outline {
|
|
976
|
+
text-shadow: none;
|
|
977
|
+
}
|
|
978
|
+
|
|
973
979
|
/* --------------------- Loading -------------------- */
|
|
974
980
|
|
|
975
981
|
.tl-loading {
|
|
@@ -1134,14 +1140,12 @@ input,
|
|
|
1134
1140
|
fill: none;
|
|
1135
1141
|
}
|
|
1136
1142
|
|
|
1137
|
-
|
|
1138
|
-
|
|
1139
|
-
|
|
1140
|
-
}
|
|
1143
|
+
.tl-container[data-coarse='true'] .tl-handle__bg:active {
|
|
1144
|
+
fill: var(--tl-color-selection-fill);
|
|
1145
|
+
}
|
|
1141
1146
|
|
|
1142
|
-
|
|
1143
|
-
|
|
1144
|
-
}
|
|
1147
|
+
.tl-container[data-coarse='true'] .tl-handle__create {
|
|
1148
|
+
opacity: 1;
|
|
1145
1149
|
}
|
|
1146
1150
|
|
|
1147
1151
|
.tl-rotate-corner:not(:hover),
|
|
@@ -1217,7 +1221,6 @@ input,
|
|
|
1217
1221
|
align-items: center;
|
|
1218
1222
|
text-align: center;
|
|
1219
1223
|
color: var(--tl-color-text);
|
|
1220
|
-
text-shadow: var(--tl-text-outline);
|
|
1221
1224
|
}
|
|
1222
1225
|
|
|
1223
1226
|
.tl-shape[data-shape-type='arrow'] .tl-text-label__inner {
|
|
@@ -1446,7 +1449,6 @@ input,
|
|
|
1446
1449
|
}
|
|
1447
1450
|
|
|
1448
1451
|
.tl-note__container > .tl-text-label {
|
|
1449
|
-
text-shadow: none;
|
|
1450
1452
|
color: currentColor;
|
|
1451
1453
|
}
|
|
1452
1454
|
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tldraw/editor",
|
|
3
3
|
"description": "tldraw infinite canvas SDK (editor).",
|
|
4
|
-
"version": "4.3.0-canary.
|
|
4
|
+
"version": "4.3.0-canary.cb6779b4f066",
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "tldraw Inc.",
|
|
7
7
|
"email": "hello@tldraw.com"
|
|
@@ -47,38 +47,42 @@
|
|
|
47
47
|
"context": "yarn run -T tsx ../../internal/scripts/context.ts"
|
|
48
48
|
},
|
|
49
49
|
"dependencies": {
|
|
50
|
-
"@tiptap/core": "^3.
|
|
51
|
-
"@tiptap/pm": "^3.
|
|
52
|
-
"@tiptap/react": "^3.
|
|
53
|
-
"@tldraw/state": "4.3.0-canary.
|
|
54
|
-
"@tldraw/state-react": "4.3.0-canary.
|
|
55
|
-
"@tldraw/store": "4.3.0-canary.
|
|
56
|
-
"@tldraw/tlschema": "4.3.0-canary.
|
|
57
|
-
"@tldraw/utils": "4.3.0-canary.
|
|
58
|
-
"@tldraw/validate": "4.3.0-canary.
|
|
50
|
+
"@tiptap/core": "^3.12.1",
|
|
51
|
+
"@tiptap/pm": "^3.12.1",
|
|
52
|
+
"@tiptap/react": "^3.12.1",
|
|
53
|
+
"@tldraw/state": "4.3.0-canary.cb6779b4f066",
|
|
54
|
+
"@tldraw/state-react": "4.3.0-canary.cb6779b4f066",
|
|
55
|
+
"@tldraw/store": "4.3.0-canary.cb6779b4f066",
|
|
56
|
+
"@tldraw/tlschema": "4.3.0-canary.cb6779b4f066",
|
|
57
|
+
"@tldraw/utils": "4.3.0-canary.cb6779b4f066",
|
|
58
|
+
"@tldraw/validate": "4.3.0-canary.cb6779b4f066",
|
|
59
59
|
"@types/core-js": "^2.5.8",
|
|
60
60
|
"@use-gesture/react": "^10.3.1",
|
|
61
61
|
"classnames": "^2.5.1",
|
|
62
62
|
"core-js": "^3.40.0",
|
|
63
63
|
"eventemitter3": "^4.0.7",
|
|
64
64
|
"idb": "^7.1.1",
|
|
65
|
-
"is-plain-object": "^5.0.0"
|
|
65
|
+
"is-plain-object": "^5.0.0",
|
|
66
|
+
"rbush": "^4.0.1"
|
|
66
67
|
},
|
|
67
68
|
"peerDependencies": {
|
|
68
|
-
"react": "^18.2.0 || ^19.
|
|
69
|
-
"react-dom": "^18.2.0 || ^19.
|
|
69
|
+
"react": "^18.2.0 || ^19.2.1",
|
|
70
|
+
"react-dom": "^18.2.0 || ^19.2.1"
|
|
70
71
|
},
|
|
71
72
|
"devDependencies": {
|
|
72
73
|
"@peculiar/webcrypto": "^1.5.0",
|
|
73
|
-
"@testing-library/
|
|
74
|
+
"@testing-library/dom": "^10.0.0",
|
|
75
|
+
"@testing-library/react": "^16.0.0",
|
|
74
76
|
"@types/benchmark": "^2.1.5",
|
|
75
|
-
"@types/
|
|
77
|
+
"@types/rbush": "^4.0.0",
|
|
78
|
+
"@types/react": "^19.2.7",
|
|
79
|
+
"@types/react-dom": "^19.2.3",
|
|
76
80
|
"@types/wicg-file-system-access": "^2020.9.8",
|
|
77
81
|
"benchmark": "^2.1.4",
|
|
78
82
|
"fake-indexeddb": "^4.0.2",
|
|
79
83
|
"lazyrepo": "0.0.0-alpha.27",
|
|
80
|
-
"react": "^
|
|
81
|
-
"react-dom": "^
|
|
84
|
+
"react": "^19.2.1",
|
|
85
|
+
"react-dom": "^19.2.1",
|
|
82
86
|
"resize-observer-polyfill": "^1.5.1",
|
|
83
87
|
"vitest": "^3.2.4"
|
|
84
88
|
},
|
package/src/index.ts
CHANGED
|
@@ -146,6 +146,7 @@ export {
|
|
|
146
146
|
type TLFontFaceSource,
|
|
147
147
|
} from './lib/editor/managers/FontManager/FontManager'
|
|
148
148
|
export { HistoryManager } from './lib/editor/managers/HistoryManager/HistoryManager'
|
|
149
|
+
export { InputsManager } from './lib/editor/managers/InputsManager/InputsManager'
|
|
149
150
|
export {
|
|
150
151
|
ScribbleManager,
|
|
151
152
|
type ScribbleItem,
|
|
@@ -163,11 +164,13 @@ export {
|
|
|
163
164
|
type SnapData,
|
|
164
165
|
type SnapIndicator,
|
|
165
166
|
} from './lib/editor/managers/SnapManager/SnapManager'
|
|
167
|
+
export { SpatialIndexManager } from './lib/editor/managers/SpatialIndexManager/SpatialIndexManager'
|
|
166
168
|
export {
|
|
167
169
|
TextManager,
|
|
168
170
|
type TLMeasureTextOpts,
|
|
169
171
|
type TLMeasureTextSpanOpts,
|
|
170
172
|
} from './lib/editor/managers/TextManager/TextManager'
|
|
173
|
+
export { TickManager } from './lib/editor/managers/TickManager/TickManager'
|
|
171
174
|
export { UserPreferencesManager } from './lib/editor/managers/UserPreferencesManager/UserPreferencesManager'
|
|
172
175
|
export { BaseBoxShapeUtil, type TLBaseBoxShape } from './lib/editor/shapes/BaseBoxShapeUtil'
|
|
173
176
|
export { GroupShapeUtil } from './lib/editor/shapes/group/GroupShapeUtil'
|
|
@@ -178,6 +181,7 @@ export {
|
|
|
178
181
|
type TLDragShapesOutInfo,
|
|
179
182
|
type TLDragShapesOverInfo,
|
|
180
183
|
type TLDropShapesOverInfo,
|
|
184
|
+
type TLEditStartInfo,
|
|
181
185
|
type TLGeometryOpts,
|
|
182
186
|
type TLHandleDragInfo,
|
|
183
187
|
type TLResizeInfo,
|
|
@@ -282,7 +286,7 @@ export {
|
|
|
282
286
|
type SvgExportDef,
|
|
283
287
|
} from './lib/editor/types/SvgExportContext'
|
|
284
288
|
export { getSvgAsImage } from './lib/exports/getSvgAsImage'
|
|
285
|
-
export { tlenv } from './lib/globals/environment'
|
|
289
|
+
export { tlenv, tlenvReactive } from './lib/globals/environment'
|
|
286
290
|
export { tlmenus } from './lib/globals/menus'
|
|
287
291
|
export { tltime } from './lib/globals/time'
|
|
288
292
|
export {
|
|
@@ -12,7 +12,7 @@ const initialState = { error: null }
|
|
|
12
12
|
|
|
13
13
|
/** @public */
|
|
14
14
|
export class ErrorBoundary extends React.Component<
|
|
15
|
-
React.
|
|
15
|
+
React.PropsWithChildren<TLErrorBoundaryProps>,
|
|
16
16
|
{ error: Error | null }
|
|
17
17
|
> {
|
|
18
18
|
static getDerivedStateFromError(error: Error) {
|
|
@@ -1,23 +1,9 @@
|
|
|
1
1
|
import { track } from '@tldraw/state-react'
|
|
2
2
|
import { modulate } from '@tldraw/utils'
|
|
3
|
-
import { useEffect, useState } from 'react'
|
|
4
3
|
import { useEditor } from '../hooks/useEditor'
|
|
5
4
|
import { Geometry2d } from '../primitives/geometry/Geometry2d'
|
|
6
5
|
import { Group2d } from '../primitives/geometry/Group2d'
|
|
7
6
|
|
|
8
|
-
function useTick(isEnabled = true) {
|
|
9
|
-
const [_, setTick] = useState(0)
|
|
10
|
-
const editor = useEditor()
|
|
11
|
-
useEffect(() => {
|
|
12
|
-
if (!isEnabled) return
|
|
13
|
-
const update = () => setTick((tick) => tick + 1)
|
|
14
|
-
editor.on('tick', update)
|
|
15
|
-
return () => {
|
|
16
|
-
editor.off('tick', update)
|
|
17
|
-
}
|
|
18
|
-
}, [editor, isEnabled])
|
|
19
|
-
}
|
|
20
|
-
|
|
21
7
|
export const GeometryDebuggingView = track(function GeometryDebuggingView({
|
|
22
8
|
showStroke = true,
|
|
23
9
|
showVertices = true,
|
|
@@ -29,13 +15,9 @@ export const GeometryDebuggingView = track(function GeometryDebuggingView({
|
|
|
29
15
|
}) {
|
|
30
16
|
const editor = useEditor()
|
|
31
17
|
|
|
32
|
-
useTick(showClosestPointOnOutline)
|
|
33
|
-
|
|
34
18
|
const zoomLevel = editor.getZoomLevel()
|
|
35
19
|
const renderingShapes = editor.getRenderingShapes()
|
|
36
|
-
const
|
|
37
|
-
inputs: { currentPagePoint },
|
|
38
|
-
} = editor
|
|
20
|
+
const currentPagePoint = editor.inputs.getCurrentPagePoint()
|
|
39
21
|
|
|
40
22
|
return (
|
|
41
23
|
<svg
|
|
@@ -210,7 +210,7 @@ function GridWrapper() {
|
|
|
210
210
|
function ScribbleWrapper() {
|
|
211
211
|
const editor = useEditor()
|
|
212
212
|
const scribbles = useValue('scribbles', () => editor.getInstanceState().scribbles, [editor])
|
|
213
|
-
const zoomLevel = useValue('zoomLevel', () => editor.
|
|
213
|
+
const zoomLevel = useValue('zoomLevel', () => editor.getEfficientZoomLevel(), [editor])
|
|
214
214
|
const { Scribble } = useEditorComponents()
|
|
215
215
|
|
|
216
216
|
if (!(Scribble && scribbles.length)) return null
|
|
@@ -243,7 +243,7 @@ function ZoomBrushWrapper() {
|
|
|
243
243
|
function SnapIndicatorWrapper() {
|
|
244
244
|
const editor = useEditor()
|
|
245
245
|
const lines = useValue('snapLines', () => editor.snaps.getIndicators(), [editor])
|
|
246
|
-
const zoomLevel = useValue('zoomLevel', () => editor.
|
|
246
|
+
const zoomLevel = useValue('zoomLevel', () => editor.getEfficientZoomLevel(), [editor])
|
|
247
247
|
const { SnapIndicator } = useEditorComponents()
|
|
248
248
|
|
|
249
249
|
if (!(SnapIndicator && lines.length > 0)) return null
|
|
@@ -284,7 +284,7 @@ function HandlesWrapperInner({ shapeId }: { shapeId: TLShapeId }) {
|
|
|
284
284
|
const editor = useEditor()
|
|
285
285
|
const { Handles } = useEditorComponents()
|
|
286
286
|
|
|
287
|
-
const zoomLevel = useValue('zoomLevel', () => editor.
|
|
287
|
+
const zoomLevel = useValue('zoomLevel', () => editor.getEfficientZoomLevel(), [editor])
|
|
288
288
|
|
|
289
289
|
const isCoarse = useValue('coarse pointer', () => editor.getInstanceState().isCoarsePointer, [
|
|
290
290
|
editor,
|
|
@@ -412,11 +412,7 @@ function ReflowIfNeeded() {
|
|
|
412
412
|
'reflow for culled shapes',
|
|
413
413
|
() => {
|
|
414
414
|
const culledShapes = editor.getCulledShapes()
|
|
415
|
-
if (
|
|
416
|
-
culledShapesRef.current.size === culledShapes.size &&
|
|
417
|
-
[...culledShapes].every((id) => culledShapesRef.current.has(id))
|
|
418
|
-
)
|
|
419
|
-
return
|
|
415
|
+
if (culledShapesRef.current === culledShapes) return
|
|
420
416
|
|
|
421
417
|
culledShapesRef.current = culledShapes
|
|
422
418
|
const canvas = document.getElementsByClassName('tl-canvas')
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { describe, expect, it } from 'vitest'
|
|
2
|
+
import { defaultUserPreferences, userTypeValidator } from './TLUserPreferences'
|
|
3
|
+
|
|
4
|
+
describe('TLUserPreferences consistency', () => {
|
|
5
|
+
// When adding a new user preference, add it to this list AND update:
|
|
6
|
+
// 1. TLUserPreferences interface
|
|
7
|
+
// 2. userTypeValidator
|
|
8
|
+
// 3. defaultUserPreferences
|
|
9
|
+
// 4. Versions enum and migrateSnapshot()
|
|
10
|
+
const interfaceKeys = [
|
|
11
|
+
'name',
|
|
12
|
+
'color',
|
|
13
|
+
'locale',
|
|
14
|
+
'animationSpeed',
|
|
15
|
+
'areKeyboardShortcutsEnabled',
|
|
16
|
+
'edgeScrollSpeed',
|
|
17
|
+
'colorScheme',
|
|
18
|
+
'isSnapMode',
|
|
19
|
+
'isWrapMode',
|
|
20
|
+
'isDynamicSizeMode',
|
|
21
|
+
'isPasteAtCursorMode',
|
|
22
|
+
'enhancedA11yMode',
|
|
23
|
+
'inputMode',
|
|
24
|
+
] as const
|
|
25
|
+
|
|
26
|
+
it('defaultUserPreferences contains all TLUserPreferences keys (except id)', () => {
|
|
27
|
+
const defaultKeys = Object.keys(defaultUserPreferences).sort()
|
|
28
|
+
const expected = [...interfaceKeys].sort()
|
|
29
|
+
|
|
30
|
+
expect(defaultKeys).toEqual(expected)
|
|
31
|
+
})
|
|
32
|
+
|
|
33
|
+
it('userTypeValidator validates all TLUserPreferences keys', () => {
|
|
34
|
+
// Access the internal config property to check which keys the validator covers
|
|
35
|
+
const validatorKeys = Object.keys((userTypeValidator as any).config).sort()
|
|
36
|
+
const expected = ['id', ...interfaceKeys].sort()
|
|
37
|
+
|
|
38
|
+
expect(validatorKeys).toEqual(expected)
|
|
39
|
+
})
|
|
40
|
+
})
|
package/src/lib/constants.ts
CHANGED
|
@@ -925,6 +925,146 @@ describe('replaceExternalContent', () => {
|
|
|
925
925
|
})
|
|
926
926
|
})
|
|
927
927
|
|
|
928
|
+
describe('dispatch event emission', () => {
|
|
929
|
+
let testEditor: Editor
|
|
930
|
+
|
|
931
|
+
beforeEach(() => {
|
|
932
|
+
testEditor = new Editor({
|
|
933
|
+
shapeUtils: [CustomShape],
|
|
934
|
+
bindingUtils: [],
|
|
935
|
+
tools: [],
|
|
936
|
+
store: createTLStore({ shapeUtils: [CustomShape], bindingUtils: [] }),
|
|
937
|
+
getContainer: () => document.body,
|
|
938
|
+
})
|
|
939
|
+
// Ensure camera is unlocked so events are processed
|
|
940
|
+
testEditor.setCameraOptions({ isLocked: false })
|
|
941
|
+
})
|
|
942
|
+
|
|
943
|
+
it('emits wheel events through the event emitter', () => {
|
|
944
|
+
const eventHandler = vi.fn()
|
|
945
|
+
testEditor.on('event', eventHandler)
|
|
946
|
+
|
|
947
|
+
const wheelEvent = {
|
|
948
|
+
type: 'wheel' as const,
|
|
949
|
+
name: 'wheel' as const,
|
|
950
|
+
delta: { x: 0, y: 10, z: 0 },
|
|
951
|
+
point: { x: 100, y: 100, z: 1 },
|
|
952
|
+
shiftKey: false,
|
|
953
|
+
altKey: false,
|
|
954
|
+
ctrlKey: false,
|
|
955
|
+
metaKey: false,
|
|
956
|
+
accelKey: false,
|
|
957
|
+
}
|
|
958
|
+
|
|
959
|
+
testEditor.dispatch(wheelEvent)
|
|
960
|
+
// Wheel events are batched for the next tick, so emit a tick to flush them
|
|
961
|
+
testEditor.emit('tick', 16)
|
|
962
|
+
|
|
963
|
+
expect(eventHandler).toHaveBeenCalledWith(wheelEvent)
|
|
964
|
+
})
|
|
965
|
+
|
|
966
|
+
it('emits pinch_start events through the event emitter', () => {
|
|
967
|
+
const eventHandler = vi.fn()
|
|
968
|
+
testEditor.on('event', eventHandler)
|
|
969
|
+
|
|
970
|
+
const pinchStartEvent = {
|
|
971
|
+
type: 'pinch' as const,
|
|
972
|
+
name: 'pinch_start' as const,
|
|
973
|
+
point: { x: 100, y: 100, z: 1 },
|
|
974
|
+
delta: { x: 0, y: 0, z: 0 },
|
|
975
|
+
shiftKey: false,
|
|
976
|
+
altKey: false,
|
|
977
|
+
ctrlKey: false,
|
|
978
|
+
metaKey: false,
|
|
979
|
+
accelKey: false,
|
|
980
|
+
}
|
|
981
|
+
|
|
982
|
+
testEditor.dispatch(pinchStartEvent)
|
|
983
|
+
// Pinch events are batched for the next tick, so emit a tick to flush them
|
|
984
|
+
testEditor.emit('tick', 16)
|
|
985
|
+
|
|
986
|
+
expect(eventHandler).toHaveBeenCalledWith(pinchStartEvent)
|
|
987
|
+
})
|
|
988
|
+
|
|
989
|
+
it('emits pinch events through the event emitter', () => {
|
|
990
|
+
const eventHandler = vi.fn()
|
|
991
|
+
testEditor.on('event', eventHandler)
|
|
992
|
+
|
|
993
|
+
// First dispatch pinch_start to set isPinching
|
|
994
|
+
const pinchStartEvent = {
|
|
995
|
+
type: 'pinch' as const,
|
|
996
|
+
name: 'pinch_start' as const,
|
|
997
|
+
point: { x: 100, y: 100, z: 1 },
|
|
998
|
+
delta: { x: 0, y: 0, z: 0 },
|
|
999
|
+
shiftKey: false,
|
|
1000
|
+
altKey: false,
|
|
1001
|
+
ctrlKey: false,
|
|
1002
|
+
metaKey: false,
|
|
1003
|
+
accelKey: false,
|
|
1004
|
+
}
|
|
1005
|
+
testEditor.dispatch(pinchStartEvent)
|
|
1006
|
+
testEditor.emit('tick', 16)
|
|
1007
|
+
|
|
1008
|
+
eventHandler.mockClear()
|
|
1009
|
+
|
|
1010
|
+
const pinchEvent = {
|
|
1011
|
+
type: 'pinch' as const,
|
|
1012
|
+
name: 'pinch' as const,
|
|
1013
|
+
point: { x: 100, y: 100, z: 1.5 },
|
|
1014
|
+
delta: { x: 10, y: 10, z: 0 },
|
|
1015
|
+
shiftKey: false,
|
|
1016
|
+
altKey: false,
|
|
1017
|
+
ctrlKey: false,
|
|
1018
|
+
metaKey: false,
|
|
1019
|
+
accelKey: false,
|
|
1020
|
+
}
|
|
1021
|
+
|
|
1022
|
+
testEditor.dispatch(pinchEvent)
|
|
1023
|
+
testEditor.emit('tick', 16)
|
|
1024
|
+
|
|
1025
|
+
expect(eventHandler).toHaveBeenCalledWith(pinchEvent)
|
|
1026
|
+
})
|
|
1027
|
+
|
|
1028
|
+
it('emits pinch_end events through the event emitter', () => {
|
|
1029
|
+
const eventHandler = vi.fn()
|
|
1030
|
+
testEditor.on('event', eventHandler)
|
|
1031
|
+
|
|
1032
|
+
// First dispatch pinch_start to set isPinching
|
|
1033
|
+
const pinchStartEvent = {
|
|
1034
|
+
type: 'pinch' as const,
|
|
1035
|
+
name: 'pinch_start' as const,
|
|
1036
|
+
point: { x: 100, y: 100, z: 1 },
|
|
1037
|
+
delta: { x: 0, y: 0, z: 0 },
|
|
1038
|
+
shiftKey: false,
|
|
1039
|
+
altKey: false,
|
|
1040
|
+
ctrlKey: false,
|
|
1041
|
+
metaKey: false,
|
|
1042
|
+
accelKey: false,
|
|
1043
|
+
}
|
|
1044
|
+
testEditor.dispatch(pinchStartEvent)
|
|
1045
|
+
testEditor.emit('tick', 16)
|
|
1046
|
+
|
|
1047
|
+
eventHandler.mockClear()
|
|
1048
|
+
|
|
1049
|
+
const pinchEndEvent = {
|
|
1050
|
+
type: 'pinch' as const,
|
|
1051
|
+
name: 'pinch_end' as const,
|
|
1052
|
+
point: { x: 100, y: 100, z: 1.5 },
|
|
1053
|
+
delta: { x: 0, y: 0, z: 0 },
|
|
1054
|
+
shiftKey: false,
|
|
1055
|
+
altKey: false,
|
|
1056
|
+
ctrlKey: false,
|
|
1057
|
+
metaKey: false,
|
|
1058
|
+
accelKey: false,
|
|
1059
|
+
}
|
|
1060
|
+
|
|
1061
|
+
testEditor.dispatch(pinchEndEvent)
|
|
1062
|
+
testEditor.emit('tick', 16)
|
|
1063
|
+
|
|
1064
|
+
expect(eventHandler).toHaveBeenCalledWith(pinchEndEvent)
|
|
1065
|
+
})
|
|
1066
|
+
})
|
|
1067
|
+
|
|
928
1068
|
describe('setTool', () => {
|
|
929
1069
|
class CustomToolA extends StateNode {
|
|
930
1070
|
static override id = 'custom-tool-a'
|