tldraw 5.2.2 → 5.2.4

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/DOCS.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # tldraw Documentation
2
2
 
3
- Version: `5.2.2`
3
+ Version: `5.2.4`
4
4
 
5
5
  This file is generated during package publishing from the tldraw docs content for this exact package version.
6
6
 
package/RELEASE_NOTES.md CHANGED
@@ -1,10 +1,10 @@
1
1
  # Releases
2
2
 
3
- Version: `5.2.2`
3
+ Version: `5.2.4`
4
4
 
5
5
  This file is generated during package publishing from the tldraw release notes content for this exact package version.
6
6
 
7
- ## v5.2.2
7
+ ## v5.2.4
8
8
 
9
9
 
10
10
 
package/dist-cjs/index.js CHANGED
@@ -648,7 +648,7 @@ var import_buildFromV1Document = require("./lib/utils/tldr/buildFromV1Document")
648
648
  var import_file = require("./lib/utils/tldr/file");
649
649
  (0, import_editor.registerTldrawLibraryVersion)(
650
650
  "tldraw",
651
- "5.2.2",
651
+ "5.2.4",
652
652
  "cjs"
653
653
  );
654
654
  //# sourceMappingURL=index.js.map
@@ -262,8 +262,8 @@ function DrawShapeSvg({
262
262
  }
263
263
  const strokePoints = (0, import_getStrokePoints.getStrokePoints)(allPointsFromSegments, options);
264
264
  const isDot = strokePoints.length < 2;
265
- const solidStrokePath = isDot ? getDot(allPointsFromSegments[0], 0) : (0, import_svg.getSvgPathFromStrokePoints)(strokePoints, shape.props.isClosed);
266
265
  const fill = isDot || shape.props.isClosed ? shape.props.fill : "none";
266
+ const solidStrokePath = isDot ? getDot(allPointsFromSegments[0], 0) : (0, import_svg.getSvgPathFromStrokePoints)(strokePoints, shape.props.isClosed && fill !== "none");
267
267
  return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
268
268
  isDot || !shape.props.isClosed || fill === "none" ? null : fill === "pattern" ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
269
269
  import_PatternFill.PatternFill,
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../src/lib/shapes/draw/DrawShapeUtil.tsx"],
4
- "sourcesContent": ["import {\n\tBox,\n\tCircle2d,\n\tPolygon2d,\n\tPolyline2d,\n\tSVGContainer,\n\tShapeUtil,\n\tSvgExportContext,\n\tTLDrawShape,\n\tTLDrawShapeProps,\n\tTLResizeInfo,\n\tTLShapeUtilCanvasSvgDef,\n\tVecLike,\n\tb64Vecs,\n\tdrawShapeMigrations,\n\tdrawShapeProps,\n\tgetColorValue,\n\tlast,\n\tlerp,\n\trng,\n\tuseEditor,\n\tuseValue,\n} from '@tldraw/editor'\nimport { STROKE_SIZES } from '../shared/default-shape-constants'\nimport { DEFAULT_FILL_COLOR_NAMES } from '../shared/defaultFills'\nimport { getFillDefForCanvas, getFillDefForExport } from '../shared/defaultStyleDefs'\nimport { getStrokePoints } from '../shared/freehand/getStrokePoints'\nimport { getSvgPathFromStrokePoints } from '../shared/freehand/svg'\nimport { svgInk } from '../shared/freehand/svgInk'\nimport { ShapeOptionsWithDisplayValues, getDisplayValues } from '../shared/getDisplayValues'\nimport { interpolateSegments } from '../shared/interpolate-props'\nimport { PatternFill } from '../shared/PatternFill'\nimport {\n\tgetDrawShapeStrokeDashArray,\n\tgetFreehandOptions,\n\tgetPointsFromDrawSegments,\n} from './getPath'\n\n/** @public */\nexport interface DrawShapeUtilDisplayValues {\n\tstrokeColor: string\n\tstrokeWidth: number\n\tfillColor: string\n\tpatternFillFallbackColor: string\n}\n\n/** @public */\nexport interface DrawShapeOptions extends ShapeOptionsWithDisplayValues<\n\tTLDrawShape,\n\tDrawShapeUtilDisplayValues\n> {\n\t/**\n\t * The maximum number of points in a line before the draw tool will begin a new shape.\n\t * A higher number will lead to poor performance while drawing very long lines.\n\t */\n\treadonly maxPointsPerShape: number\n}\n\n/** @public */\nexport class DrawShapeUtil extends ShapeUtil<TLDrawShape> {\n\tstatic override type = 'draw' as const\n\tstatic override props = drawShapeProps\n\tstatic override migrations = drawShapeMigrations\n\n\toverride options: DrawShapeOptions = {\n\t\tmaxPointsPerShape: 600,\n\t\tgetDefaultDisplayValues(_editor, shape, theme, colorMode): DrawShapeUtilDisplayValues {\n\t\t\tconst { color, fill, size } = shape.props\n\t\t\tconst colors = theme.colors[colorMode]\n\t\t\treturn {\n\t\t\t\tstrokeColor: getColorValue(colors, color, 'solid'),\n\t\t\t\tstrokeWidth: theme.strokeWidth * STROKE_SIZES[size],\n\t\t\t\tfillColor:\n\t\t\t\t\tfill === 'none'\n\t\t\t\t\t\t? 'transparent'\n\t\t\t\t\t\t: fill === 'semi'\n\t\t\t\t\t\t\t? colors.solid\n\t\t\t\t\t\t\t: getColorValue(colors, color, DEFAULT_FILL_COLOR_NAMES[fill]),\n\t\t\t\tpatternFillFallbackColor: getColorValue(colors, color, 'semi'),\n\t\t\t}\n\t\t},\n\t\tgetCustomDisplayValues(): Partial<DrawShapeUtilDisplayValues> {\n\t\t\treturn {}\n\t\t},\n\t}\n\n\toverride hideResizeHandles(shape: TLDrawShape) {\n\t\treturn getIsDot(shape)\n\t}\n\toverride hideRotateHandle(shape: TLDrawShape) {\n\t\treturn getIsDot(shape)\n\t}\n\toverride hideSelectionBoundsFg(shape: TLDrawShape) {\n\t\treturn getIsDot(shape)\n\t}\n\n\toverride getDefaultProps(): TLDrawShape['props'] {\n\t\treturn {\n\t\t\tsegments: [],\n\t\t\tcolor: 'black',\n\t\t\tfill: 'none',\n\t\t\tdash: 'draw',\n\t\t\tsize: 'm',\n\t\t\tisComplete: false,\n\t\t\tisClosed: false,\n\t\t\tisPen: false,\n\t\t\tscale: 1,\n\t\t\tscaleX: 1,\n\t\t\tscaleY: 1,\n\t\t}\n\t}\n\n\tgetGeometry(shape: TLDrawShape) {\n\t\tconst points = getPointsFromDrawSegments(\n\t\t\tshape.props.segments,\n\t\t\tshape.props.scaleX,\n\t\t\tshape.props.scaleY\n\t\t)\n\n\t\tconst sw = (getDisplayValues(this, shape).strokeWidth + 1) * shape.props.scale\n\n\t\t// A dot\n\t\tif (shape.props.segments.length === 1) {\n\t\t\tconst box = Box.FromPoints(points)\n\t\t\tif (box.width < sw * 2 && box.height < sw * 2) {\n\t\t\t\treturn new Circle2d({\n\t\t\t\t\tx: -sw,\n\t\t\t\t\ty: -sw,\n\t\t\t\t\tradius: sw,\n\t\t\t\t\tisFilled: true,\n\t\t\t\t})\n\t\t\t}\n\t\t}\n\n\t\tconst strokePoints = getStrokePoints(\n\t\t\tpoints,\n\t\t\tgetFreehandOptions(shape.props, sw, shape.props.isPen, true)\n\t\t).map((p) => p.point)\n\n\t\t// A closed draw stroke\n\t\tif (shape.props.isClosed && strokePoints.length > 2) {\n\t\t\treturn new Polygon2d({\n\t\t\t\tpoints: strokePoints,\n\t\t\t\tisFilled: shape.props.fill !== 'none',\n\t\t\t})\n\t\t}\n\n\t\tif (strokePoints.length === 1) {\n\t\t\treturn new Circle2d({\n\t\t\t\tx: -sw,\n\t\t\t\ty: -sw,\n\t\t\t\tradius: sw,\n\t\t\t\tisFilled: true,\n\t\t\t})\n\t\t}\n\n\t\t// An open draw stroke\n\t\treturn new Polyline2d({\n\t\t\tpoints: strokePoints,\n\t\t})\n\t}\n\n\tcomponent(shape: TLDrawShape) {\n\t\tconst dv = getDisplayValues(this, shape)\n\t\treturn (\n\t\t\t<SVGContainer>\n\t\t\t\t<DrawShapeSvg\n\t\t\t\t\tshape={shape}\n\t\t\t\t\tstrokeColor={dv.strokeColor}\n\t\t\t\t\tstrokeWidth={dv.strokeWidth}\n\t\t\t\t\tfillColor={dv.fillColor}\n\t\t\t\t\tpatternFillFallbackColor={dv.patternFillFallbackColor}\n\t\t\t\t/>\n\t\t\t</SVGContainer>\n\t\t)\n\t}\n\n\toverride getIndicatorPath(shape: TLDrawShape): Path2D {\n\t\tconst allPointsFromSegments = getPointsFromDrawSegments(\n\t\t\tshape.props.segments,\n\t\t\tshape.props.scaleX,\n\t\t\tshape.props.scaleY\n\t\t)\n\n\t\tlet sw = (getDisplayValues(this, shape).strokeWidth + 1) * shape.props.scale\n\n\t\tconst zoomLevel = this.editor.getEfficientZoomLevel()\n\t\tconst forceSolid = zoomLevel < 0.5 && zoomLevel < 1.5 / sw\n\n\t\tif (\n\t\t\t!forceSolid &&\n\t\t\t!shape.props.isPen &&\n\t\t\tshape.props.dash === 'draw' &&\n\t\t\tallPointsFromSegments.length === 1\n\t\t) {\n\t\t\tsw += rng(shape.id)() * (sw / 6)\n\t\t}\n\n\t\tconst showAsComplete = shape.props.isComplete || last(shape.props.segments)?.type === 'straight'\n\t\tconst options = getFreehandOptions(shape.props, sw, showAsComplete, true)\n\t\tconst strokePoints = getStrokePoints(allPointsFromSegments, options)\n\t\tconst solidStrokePath =\n\t\t\tstrokePoints.length > 1\n\t\t\t\t? getSvgPathFromStrokePoints(strokePoints, shape.props.isClosed)\n\t\t\t\t: getDot(allPointsFromSegments[0], sw)\n\n\t\treturn new Path2D(solidStrokePath)\n\t}\n\n\toverride toSvg(shape: TLDrawShape, ctx: SvgExportContext) {\n\t\tctx.addExportDef(getFillDefForExport(shape.props.fill))\n\t\tconst dv = getDisplayValues(this, shape, ctx.colorMode)\n\t\tconst scaleFactor = 1 / shape.props.scale\n\t\treturn (\n\t\t\t<g transform={`scale(${scaleFactor})`}>\n\t\t\t\t<DrawShapeSvg\n\t\t\t\t\tshape={shape}\n\t\t\t\t\tzoomOverride={1}\n\t\t\t\t\tstrokeColor={dv.strokeColor}\n\t\t\t\t\tstrokeWidth={dv.strokeWidth}\n\t\t\t\t\tfillColor={dv.fillColor}\n\t\t\t\t\tpatternFillFallbackColor={dv.patternFillFallbackColor}\n\t\t\t\t/>\n\t\t\t</g>\n\t\t)\n\t}\n\n\toverride getCanvasSvgDefs(): TLShapeUtilCanvasSvgDef[] {\n\t\treturn [getFillDefForCanvas()]\n\t}\n\n\toverride onResize(shape: TLDrawShape, info: TLResizeInfo<TLDrawShape>) {\n\t\tconst newScaleX = info.scaleX * shape.props.scaleX\n\t\tconst newScaleY = info.scaleY * shape.props.scaleY\n\t\tif (newScaleX === 0 || newScaleY === 0) return\n\n\t\treturn {\n\t\t\tprops: {\n\t\t\t\tscaleX: newScaleX,\n\t\t\t\tscaleY: newScaleY,\n\t\t\t},\n\t\t}\n\t}\n\n\toverride expandSelectionOutlinePx(shape: TLDrawShape): number {\n\t\tconst multiplier = shape.props.dash === 'draw' ? 1.6 : 1\n\t\treturn ((getDisplayValues(this, shape).strokeWidth * multiplier) / 2) * shape.props.scale\n\t}\n\toverride getInterpolatedProps(\n\t\tstartShape: TLDrawShape,\n\t\tendShape: TLDrawShape,\n\t\tt: number\n\t): TLDrawShapeProps {\n\t\treturn {\n\t\t\t...(t > 0.5 ? endShape.props : startShape.props),\n\t\t\tsegments: interpolateSegments(startShape.props.segments, endShape.props.segments, t),\n\t\t\tscale: lerp(startShape.props.scale, endShape.props.scale, t),\n\t\t}\n\t}\n}\n\nfunction getDot(point: VecLike, sw: number) {\n\tconst r = (sw + 1) * 0.5\n\treturn `M ${point.x} ${point.y} m -${r}, 0 a ${r},${r} 0 1,0 ${r * 2},0 a ${r},${r} 0 1,0 -${\n\t\tr * 2\n\t},0`\n}\n\nfunction getIsDot(shape: TLDrawShape) {\n\t// A dot is a single-point segment. isSinglePoint knows the per-encoding length\n\t// (and takes the segment's dim), so this stays correct for both 2D and 3D paths.\n\t// A bare length threshold can't: a 2-point 2D path is the same length as a 1-point\n\t// 3D path, so only the dim disambiguates them.\n\tconst segment = shape.props.segments[0]\n\treturn shape.props.segments.length === 1 && b64Vecs.isSinglePoint(segment.path, segment.dim)\n}\n\nfunction DrawShapeSvg({\n\tshape,\n\tzoomOverride,\n\tstrokeColor,\n\tstrokeWidth: baseStrokeWidth,\n\tfillColor,\n\tpatternFillFallbackColor,\n}: {\n\tshape: TLDrawShape\n\tzoomOverride?: number\n\tstrokeColor: string\n\tstrokeWidth: number\n\tfillColor: string\n\tpatternFillFallbackColor: string\n}) {\n\tconst editor = useEditor()\n\n\tconst allPointsFromSegments = getPointsFromDrawSegments(\n\t\tshape.props.segments,\n\t\tshape.props.scaleX,\n\t\tshape.props.scaleY\n\t)\n\n\tconst showAsComplete = shape.props.isComplete || last(shape.props.segments)?.type === 'straight'\n\n\tlet sw = (baseStrokeWidth + 1) * shape.props.scale\n\tconst forceSolid = useValue(\n\t\t'force solid',\n\t\t() => {\n\t\t\tconst zoomLevel = zoomOverride ?? editor.getEfficientZoomLevel()\n\t\t\treturn zoomLevel < 0.5 && zoomLevel < 1.5 / sw\n\t\t},\n\t\t[editor, sw, zoomOverride]\n\t)\n\n\tconst dotAdjustment = useValue(\n\t\t'dot adjustment',\n\t\t() => {\n\t\t\tconst zoomLevel = zoomOverride ?? editor.getEfficientZoomLevel()\n\t\t\t// If we're zoomed way out (10%), then we need to make the dotted line go to 9 instead 0.1\n\t\t\t// Chrome doesn't render anything otherwise.\n\t\t\treturn zoomLevel < 0.2 ? 9 : 0.1\n\t\t},\n\t\t[editor, zoomOverride]\n\t)\n\n\tif (\n\t\t!forceSolid &&\n\t\t!shape.props.isPen &&\n\t\tshape.props.dash === 'draw' &&\n\t\tallPointsFromSegments.length === 1\n\t) {\n\t\tsw += rng(shape.id)() * (sw / 6)\n\t}\n\n\tconst options = getFreehandOptions(shape.props, sw, showAsComplete, forceSolid)\n\n\tif (!forceSolid && shape.props.dash === 'draw') {\n\t\treturn (\n\t\t\t<>\n\t\t\t\t{shape.props.isClosed &&\n\t\t\t\t\tshape.props.fill !== 'none' &&\n\t\t\t\t\tallPointsFromSegments.length > 1 &&\n\t\t\t\t\t(shape.props.fill === 'pattern' ? (\n\t\t\t\t\t\t<PatternFill\n\t\t\t\t\t\t\td={getSvgPathFromStrokePoints(\n\t\t\t\t\t\t\t\tgetStrokePoints(allPointsFromSegments, options),\n\t\t\t\t\t\t\t\tshape.props.isClosed\n\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\tfillColor={fillColor}\n\t\t\t\t\t\t\tpatternFillFallbackColor={patternFillFallbackColor}\n\t\t\t\t\t\t\tscale={shape.props.scale}\n\t\t\t\t\t\t/>\n\t\t\t\t\t) : (\n\t\t\t\t\t\t<path\n\t\t\t\t\t\t\tfill={fillColor}\n\t\t\t\t\t\t\td={getSvgPathFromStrokePoints(\n\t\t\t\t\t\t\t\tgetStrokePoints(allPointsFromSegments, options),\n\t\t\t\t\t\t\t\tshape.props.isClosed\n\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t/>\n\t\t\t\t\t))}\n\t\t\t\t<path d={svgInk(allPointsFromSegments, options)} strokeLinecap=\"round\" fill={strokeColor} />\n\t\t\t</>\n\t\t)\n\t}\n\n\tconst strokePoints = getStrokePoints(allPointsFromSegments, options)\n\tconst isDot = strokePoints.length < 2\n\tconst solidStrokePath = isDot\n\t\t? getDot(allPointsFromSegments[0], 0)\n\t\t: getSvgPathFromStrokePoints(strokePoints, shape.props.isClosed)\n\n\tconst fill = isDot || shape.props.isClosed ? shape.props.fill : 'none'\n\n\treturn (\n\t\t<>\n\t\t\t{isDot || !shape.props.isClosed || fill === 'none' ? null : fill === 'pattern' ? (\n\t\t\t\t<PatternFill\n\t\t\t\t\td={solidStrokePath}\n\t\t\t\t\tfillColor={fillColor}\n\t\t\t\t\tpatternFillFallbackColor={patternFillFallbackColor}\n\t\t\t\t\tscale={shape.props.scale}\n\t\t\t\t/>\n\t\t\t) : (\n\t\t\t\t<path fill={fillColor} d={solidStrokePath} />\n\t\t\t)}\n\t\t\t{shape.props.dash !== 'none' && (\n\t\t\t\t<path\n\t\t\t\t\td={solidStrokePath}\n\t\t\t\t\tstrokeLinecap=\"round\"\n\t\t\t\t\tfill={isDot ? strokeColor : 'none'}\n\t\t\t\t\tstroke={strokeColor}\n\t\t\t\t\tstrokeWidth={sw}\n\t\t\t\t\tstrokeDasharray={isDot ? 'none' : getDrawShapeStrokeDashArray(shape, sw, dotAdjustment)}\n\t\t\t\t\tstrokeDashoffset=\"0\"\n\t\t\t\t/>\n\t\t\t)}\n\t\t</>\n\t)\n}\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["import {\n\tBox,\n\tCircle2d,\n\tPolygon2d,\n\tPolyline2d,\n\tSVGContainer,\n\tShapeUtil,\n\tSvgExportContext,\n\tTLDrawShape,\n\tTLDrawShapeProps,\n\tTLResizeInfo,\n\tTLShapeUtilCanvasSvgDef,\n\tVecLike,\n\tb64Vecs,\n\tdrawShapeMigrations,\n\tdrawShapeProps,\n\tgetColorValue,\n\tlast,\n\tlerp,\n\trng,\n\tuseEditor,\n\tuseValue,\n} from '@tldraw/editor'\nimport { STROKE_SIZES } from '../shared/default-shape-constants'\nimport { DEFAULT_FILL_COLOR_NAMES } from '../shared/defaultFills'\nimport { getFillDefForCanvas, getFillDefForExport } from '../shared/defaultStyleDefs'\nimport { getStrokePoints } from '../shared/freehand/getStrokePoints'\nimport { getSvgPathFromStrokePoints } from '../shared/freehand/svg'\nimport { svgInk } from '../shared/freehand/svgInk'\nimport { ShapeOptionsWithDisplayValues, getDisplayValues } from '../shared/getDisplayValues'\nimport { interpolateSegments } from '../shared/interpolate-props'\nimport { PatternFill } from '../shared/PatternFill'\nimport {\n\tgetDrawShapeStrokeDashArray,\n\tgetFreehandOptions,\n\tgetPointsFromDrawSegments,\n} from './getPath'\n\n/** @public */\nexport interface DrawShapeUtilDisplayValues {\n\tstrokeColor: string\n\tstrokeWidth: number\n\tfillColor: string\n\tpatternFillFallbackColor: string\n}\n\n/** @public */\nexport interface DrawShapeOptions extends ShapeOptionsWithDisplayValues<\n\tTLDrawShape,\n\tDrawShapeUtilDisplayValues\n> {\n\t/**\n\t * The maximum number of points in a line before the draw tool will begin a new shape.\n\t * A higher number will lead to poor performance while drawing very long lines.\n\t */\n\treadonly maxPointsPerShape: number\n}\n\n/** @public */\nexport class DrawShapeUtil extends ShapeUtil<TLDrawShape> {\n\tstatic override type = 'draw' as const\n\tstatic override props = drawShapeProps\n\tstatic override migrations = drawShapeMigrations\n\n\toverride options: DrawShapeOptions = {\n\t\tmaxPointsPerShape: 600,\n\t\tgetDefaultDisplayValues(_editor, shape, theme, colorMode): DrawShapeUtilDisplayValues {\n\t\t\tconst { color, fill, size } = shape.props\n\t\t\tconst colors = theme.colors[colorMode]\n\t\t\treturn {\n\t\t\t\tstrokeColor: getColorValue(colors, color, 'solid'),\n\t\t\t\tstrokeWidth: theme.strokeWidth * STROKE_SIZES[size],\n\t\t\t\tfillColor:\n\t\t\t\t\tfill === 'none'\n\t\t\t\t\t\t? 'transparent'\n\t\t\t\t\t\t: fill === 'semi'\n\t\t\t\t\t\t\t? colors.solid\n\t\t\t\t\t\t\t: getColorValue(colors, color, DEFAULT_FILL_COLOR_NAMES[fill]),\n\t\t\t\tpatternFillFallbackColor: getColorValue(colors, color, 'semi'),\n\t\t\t}\n\t\t},\n\t\tgetCustomDisplayValues(): Partial<DrawShapeUtilDisplayValues> {\n\t\t\treturn {}\n\t\t},\n\t}\n\n\toverride hideResizeHandles(shape: TLDrawShape) {\n\t\treturn getIsDot(shape)\n\t}\n\toverride hideRotateHandle(shape: TLDrawShape) {\n\t\treturn getIsDot(shape)\n\t}\n\toverride hideSelectionBoundsFg(shape: TLDrawShape) {\n\t\treturn getIsDot(shape)\n\t}\n\n\toverride getDefaultProps(): TLDrawShape['props'] {\n\t\treturn {\n\t\t\tsegments: [],\n\t\t\tcolor: 'black',\n\t\t\tfill: 'none',\n\t\t\tdash: 'draw',\n\t\t\tsize: 'm',\n\t\t\tisComplete: false,\n\t\t\tisClosed: false,\n\t\t\tisPen: false,\n\t\t\tscale: 1,\n\t\t\tscaleX: 1,\n\t\t\tscaleY: 1,\n\t\t}\n\t}\n\n\tgetGeometry(shape: TLDrawShape) {\n\t\tconst points = getPointsFromDrawSegments(\n\t\t\tshape.props.segments,\n\t\t\tshape.props.scaleX,\n\t\t\tshape.props.scaleY\n\t\t)\n\n\t\tconst sw = (getDisplayValues(this, shape).strokeWidth + 1) * shape.props.scale\n\n\t\t// A dot\n\t\tif (shape.props.segments.length === 1) {\n\t\t\tconst box = Box.FromPoints(points)\n\t\t\tif (box.width < sw * 2 && box.height < sw * 2) {\n\t\t\t\treturn new Circle2d({\n\t\t\t\t\tx: -sw,\n\t\t\t\t\ty: -sw,\n\t\t\t\t\tradius: sw,\n\t\t\t\t\tisFilled: true,\n\t\t\t\t})\n\t\t\t}\n\t\t}\n\n\t\tconst strokePoints = getStrokePoints(\n\t\t\tpoints,\n\t\t\tgetFreehandOptions(shape.props, sw, shape.props.isPen, true)\n\t\t).map((p) => p.point)\n\n\t\t// A closed draw stroke\n\t\tif (shape.props.isClosed && strokePoints.length > 2) {\n\t\t\treturn new Polygon2d({\n\t\t\t\tpoints: strokePoints,\n\t\t\t\tisFilled: shape.props.fill !== 'none',\n\t\t\t})\n\t\t}\n\n\t\tif (strokePoints.length === 1) {\n\t\t\treturn new Circle2d({\n\t\t\t\tx: -sw,\n\t\t\t\ty: -sw,\n\t\t\t\tradius: sw,\n\t\t\t\tisFilled: true,\n\t\t\t})\n\t\t}\n\n\t\t// An open draw stroke\n\t\treturn new Polyline2d({\n\t\t\tpoints: strokePoints,\n\t\t})\n\t}\n\n\tcomponent(shape: TLDrawShape) {\n\t\tconst dv = getDisplayValues(this, shape)\n\t\treturn (\n\t\t\t<SVGContainer>\n\t\t\t\t<DrawShapeSvg\n\t\t\t\t\tshape={shape}\n\t\t\t\t\tstrokeColor={dv.strokeColor}\n\t\t\t\t\tstrokeWidth={dv.strokeWidth}\n\t\t\t\t\tfillColor={dv.fillColor}\n\t\t\t\t\tpatternFillFallbackColor={dv.patternFillFallbackColor}\n\t\t\t\t/>\n\t\t\t</SVGContainer>\n\t\t)\n\t}\n\n\toverride getIndicatorPath(shape: TLDrawShape): Path2D {\n\t\tconst allPointsFromSegments = getPointsFromDrawSegments(\n\t\t\tshape.props.segments,\n\t\t\tshape.props.scaleX,\n\t\t\tshape.props.scaleY\n\t\t)\n\n\t\tlet sw = (getDisplayValues(this, shape).strokeWidth + 1) * shape.props.scale\n\n\t\tconst zoomLevel = this.editor.getEfficientZoomLevel()\n\t\tconst forceSolid = zoomLevel < 0.5 && zoomLevel < 1.5 / sw\n\n\t\tif (\n\t\t\t!forceSolid &&\n\t\t\t!shape.props.isPen &&\n\t\t\tshape.props.dash === 'draw' &&\n\t\t\tallPointsFromSegments.length === 1\n\t\t) {\n\t\t\tsw += rng(shape.id)() * (sw / 6)\n\t\t}\n\n\t\tconst showAsComplete = shape.props.isComplete || last(shape.props.segments)?.type === 'straight'\n\t\tconst options = getFreehandOptions(shape.props, sw, showAsComplete, true)\n\t\tconst strokePoints = getStrokePoints(allPointsFromSegments, options)\n\t\tconst solidStrokePath =\n\t\t\tstrokePoints.length > 1\n\t\t\t\t? getSvgPathFromStrokePoints(strokePoints, shape.props.isClosed)\n\t\t\t\t: getDot(allPointsFromSegments[0], sw)\n\n\t\treturn new Path2D(solidStrokePath)\n\t}\n\n\toverride toSvg(shape: TLDrawShape, ctx: SvgExportContext) {\n\t\tctx.addExportDef(getFillDefForExport(shape.props.fill))\n\t\tconst dv = getDisplayValues(this, shape, ctx.colorMode)\n\t\tconst scaleFactor = 1 / shape.props.scale\n\t\treturn (\n\t\t\t<g transform={`scale(${scaleFactor})`}>\n\t\t\t\t<DrawShapeSvg\n\t\t\t\t\tshape={shape}\n\t\t\t\t\tzoomOverride={1}\n\t\t\t\t\tstrokeColor={dv.strokeColor}\n\t\t\t\t\tstrokeWidth={dv.strokeWidth}\n\t\t\t\t\tfillColor={dv.fillColor}\n\t\t\t\t\tpatternFillFallbackColor={dv.patternFillFallbackColor}\n\t\t\t\t/>\n\t\t\t</g>\n\t\t)\n\t}\n\n\toverride getCanvasSvgDefs(): TLShapeUtilCanvasSvgDef[] {\n\t\treturn [getFillDefForCanvas()]\n\t}\n\n\toverride onResize(shape: TLDrawShape, info: TLResizeInfo<TLDrawShape>) {\n\t\tconst newScaleX = info.scaleX * shape.props.scaleX\n\t\tconst newScaleY = info.scaleY * shape.props.scaleY\n\t\tif (newScaleX === 0 || newScaleY === 0) return\n\n\t\treturn {\n\t\t\tprops: {\n\t\t\t\tscaleX: newScaleX,\n\t\t\t\tscaleY: newScaleY,\n\t\t\t},\n\t\t}\n\t}\n\n\toverride expandSelectionOutlinePx(shape: TLDrawShape): number {\n\t\tconst multiplier = shape.props.dash === 'draw' ? 1.6 : 1\n\t\treturn ((getDisplayValues(this, shape).strokeWidth * multiplier) / 2) * shape.props.scale\n\t}\n\toverride getInterpolatedProps(\n\t\tstartShape: TLDrawShape,\n\t\tendShape: TLDrawShape,\n\t\tt: number\n\t): TLDrawShapeProps {\n\t\treturn {\n\t\t\t...(t > 0.5 ? endShape.props : startShape.props),\n\t\t\tsegments: interpolateSegments(startShape.props.segments, endShape.props.segments, t),\n\t\t\tscale: lerp(startShape.props.scale, endShape.props.scale, t),\n\t\t}\n\t}\n}\n\nfunction getDot(point: VecLike, sw: number) {\n\tconst r = (sw + 1) * 0.5\n\treturn `M ${point.x} ${point.y} m -${r}, 0 a ${r},${r} 0 1,0 ${r * 2},0 a ${r},${r} 0 1,0 -${\n\t\tr * 2\n\t},0`\n}\n\nfunction getIsDot(shape: TLDrawShape) {\n\t// A dot is a single-point segment. isSinglePoint knows the per-encoding length\n\t// (and takes the segment's dim), so this stays correct for both 2D and 3D paths.\n\t// A bare length threshold can't: a 2-point 2D path is the same length as a 1-point\n\t// 3D path, so only the dim disambiguates them.\n\tconst segment = shape.props.segments[0]\n\treturn shape.props.segments.length === 1 && b64Vecs.isSinglePoint(segment.path, segment.dim)\n}\n\nfunction DrawShapeSvg({\n\tshape,\n\tzoomOverride,\n\tstrokeColor,\n\tstrokeWidth: baseStrokeWidth,\n\tfillColor,\n\tpatternFillFallbackColor,\n}: {\n\tshape: TLDrawShape\n\tzoomOverride?: number\n\tstrokeColor: string\n\tstrokeWidth: number\n\tfillColor: string\n\tpatternFillFallbackColor: string\n}) {\n\tconst editor = useEditor()\n\n\tconst allPointsFromSegments = getPointsFromDrawSegments(\n\t\tshape.props.segments,\n\t\tshape.props.scaleX,\n\t\tshape.props.scaleY\n\t)\n\n\tconst showAsComplete = shape.props.isComplete || last(shape.props.segments)?.type === 'straight'\n\n\tlet sw = (baseStrokeWidth + 1) * shape.props.scale\n\tconst forceSolid = useValue(\n\t\t'force solid',\n\t\t() => {\n\t\t\tconst zoomLevel = zoomOverride ?? editor.getEfficientZoomLevel()\n\t\t\treturn zoomLevel < 0.5 && zoomLevel < 1.5 / sw\n\t\t},\n\t\t[editor, sw, zoomOverride]\n\t)\n\n\tconst dotAdjustment = useValue(\n\t\t'dot adjustment',\n\t\t() => {\n\t\t\tconst zoomLevel = zoomOverride ?? editor.getEfficientZoomLevel()\n\t\t\t// If we're zoomed way out (10%), then we need to make the dotted line go to 9 instead 0.1\n\t\t\t// Chrome doesn't render anything otherwise.\n\t\t\treturn zoomLevel < 0.2 ? 9 : 0.1\n\t\t},\n\t\t[editor, zoomOverride]\n\t)\n\n\tif (\n\t\t!forceSolid &&\n\t\t!shape.props.isPen &&\n\t\tshape.props.dash === 'draw' &&\n\t\tallPointsFromSegments.length === 1\n\t) {\n\t\tsw += rng(shape.id)() * (sw / 6)\n\t}\n\n\tconst options = getFreehandOptions(shape.props, sw, showAsComplete, forceSolid)\n\n\tif (!forceSolid && shape.props.dash === 'draw') {\n\t\treturn (\n\t\t\t<>\n\t\t\t\t{shape.props.isClosed &&\n\t\t\t\t\tshape.props.fill !== 'none' &&\n\t\t\t\t\tallPointsFromSegments.length > 1 &&\n\t\t\t\t\t(shape.props.fill === 'pattern' ? (\n\t\t\t\t\t\t<PatternFill\n\t\t\t\t\t\t\td={getSvgPathFromStrokePoints(\n\t\t\t\t\t\t\t\tgetStrokePoints(allPointsFromSegments, options),\n\t\t\t\t\t\t\t\tshape.props.isClosed\n\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\tfillColor={fillColor}\n\t\t\t\t\t\t\tpatternFillFallbackColor={patternFillFallbackColor}\n\t\t\t\t\t\t\tscale={shape.props.scale}\n\t\t\t\t\t\t/>\n\t\t\t\t\t) : (\n\t\t\t\t\t\t<path\n\t\t\t\t\t\t\tfill={fillColor}\n\t\t\t\t\t\t\td={getSvgPathFromStrokePoints(\n\t\t\t\t\t\t\t\tgetStrokePoints(allPointsFromSegments, options),\n\t\t\t\t\t\t\t\tshape.props.isClosed\n\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t/>\n\t\t\t\t\t))}\n\t\t\t\t<path d={svgInk(allPointsFromSegments, options)} strokeLinecap=\"round\" fill={strokeColor} />\n\t\t\t</>\n\t\t)\n\t}\n\n\tconst strokePoints = getStrokePoints(allPointsFromSegments, options)\n\tconst isDot = strokePoints.length < 2\n\tconst fill = isDot || shape.props.isClosed ? shape.props.fill : 'none'\n\n\tconst solidStrokePath = isDot\n\t\t? getDot(allPointsFromSegments[0], 0)\n\t\t: getSvgPathFromStrokePoints(strokePoints, shape.props.isClosed && fill !== 'none')\n\n\treturn (\n\t\t<>\n\t\t\t{isDot || !shape.props.isClosed || fill === 'none' ? null : fill === 'pattern' ? (\n\t\t\t\t<PatternFill\n\t\t\t\t\td={solidStrokePath}\n\t\t\t\t\tfillColor={fillColor}\n\t\t\t\t\tpatternFillFallbackColor={patternFillFallbackColor}\n\t\t\t\t\tscale={shape.props.scale}\n\t\t\t\t/>\n\t\t\t) : (\n\t\t\t\t<path fill={fillColor} d={solidStrokePath} />\n\t\t\t)}\n\t\t\t{shape.props.dash !== 'none' && (\n\t\t\t\t<path\n\t\t\t\t\td={solidStrokePath}\n\t\t\t\t\tstrokeLinecap=\"round\"\n\t\t\t\t\tfill={isDot ? strokeColor : 'none'}\n\t\t\t\t\tstroke={strokeColor}\n\t\t\t\t\tstrokeWidth={sw}\n\t\t\t\t\tstrokeDasharray={isDot ? 'none' : getDrawShapeStrokeDashArray(shape, sw, dotAdjustment)}\n\t\t\t\t\tstrokeDashoffset=\"0\"\n\t\t\t\t/>\n\t\t\t)}\n\t\t</>\n\t)\n}\n"],
5
+ "mappings": "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",
6
6
  "names": []
7
7
  }
@@ -31,8 +31,10 @@ class PointingHandle extends import_editor.StateNode {
31
31
  static id = "pointing_handle";
32
32
  didCtrlOnEnter = false;
33
33
  info = {};
34
+ isDoubleClick = false;
34
35
  onEnter(info) {
35
36
  this.info = info;
37
+ this.isDoubleClick = false;
36
38
  this.didCtrlOnEnter = info.accelKey;
37
39
  const { shape } = info;
38
40
  if (this.editor.isShapeOfType(shape, "arrow")) {
@@ -59,6 +61,16 @@ class PointingHandle extends import_editor.StateNode {
59
61
  }
60
62
  onPointerUp() {
61
63
  const { shape, handle } = this.info;
64
+ if (this.isDoubleClick) {
65
+ this.parent.transition("idle");
66
+ this.parent.getCurrent()?.handleEvent({
67
+ ...this.info,
68
+ type: "click",
69
+ name: "double_click",
70
+ phase: "down"
71
+ });
72
+ return;
73
+ }
62
74
  if (this.editor.isShapeOfType(shape, "note")) {
63
75
  const { editor } = this;
64
76
  const nextNote = getNoteForAdjacentPosition(editor, shape, handle, false);
@@ -73,8 +85,7 @@ class PointingHandle extends import_editor.StateNode {
73
85
  if (this.editor.inputs.getShiftKey() || info.phase !== "down" || info.ctrlKey || info.shiftKey) {
74
86
  return;
75
87
  }
76
- this.parent.transition("idle");
77
- this.parent.getCurrent()?.handleEvent(info);
88
+ this.isDoubleClick = true;
78
89
  }
79
90
  onPointerMove(info) {
80
91
  const { editor } = this;
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../../src/lib/tools/SelectTool/childStates/PointingHandle.ts"],
4
- "sourcesContent": ["import {\n\tEditor,\n\tStateNode,\n\tTLClickEventInfo,\n\tTLHandle,\n\tTLNoteShape,\n\tTLPointerEventInfo,\n\tVec,\n} from '@tldraw/editor'\nimport { updateArrowTargetState } from '../../../shapes/arrow/arrowTargetState'\nimport { getArrowBindings } from '../../../shapes/arrow/shared'\nimport {\n\tgetNoteAdjacentPositions,\n\tgetNoteShapeForAdjacentPosition,\n} from '../../../shapes/note/noteHelpers'\nimport type { NoteShapeUtil } from '../../../shapes/note/NoteShapeUtil'\nimport { getDisplayValues } from '../../../shapes/shared/getDisplayValues'\nimport { startEditingShapeWithRichText } from '../selectHelpers'\n\nexport class PointingHandle extends StateNode {\n\tstatic override id = 'pointing_handle'\n\n\tdidCtrlOnEnter = false\n\n\tinfo = {} as TLPointerEventInfo & { target: 'handle' }\n\n\toverride onEnter(info: TLPointerEventInfo & { target: 'handle' }) {\n\t\tthis.info = info\n\n\t\tthis.didCtrlOnEnter = info.accelKey\n\n\t\tconst { shape } = info\n\t\tif (this.editor.isShapeOfType(shape, 'arrow')) {\n\t\t\tconst initialBindings = getArrowBindings(this.editor, shape)\n\t\t\tconst currentBinding = initialBindings[info.handle.id as 'start' | 'end']\n\t\t\tconst oppositeBinding = initialBindings[info.handle.id === 'start' ? 'end' : 'start']\n\t\t\tconst arrowTransform = this.editor.getShapePageTransform(shape.id)!\n\n\t\t\tif (currentBinding) {\n\t\t\t\tupdateArrowTargetState({\n\t\t\t\t\teditor: this.editor,\n\t\t\t\t\tpointInPageSpace: arrowTransform.applyToPoint(info.handle),\n\t\t\t\t\tarrow: shape,\n\t\t\t\t\tisPrecise: currentBinding.props.isPrecise,\n\t\t\t\t\tcurrentBinding: currentBinding,\n\t\t\t\t\toppositeBinding: oppositeBinding,\n\t\t\t\t})\n\t\t\t}\n\t\t}\n\n\t\tthis.editor.setCursor({ type: 'grabbing', rotation: 0 })\n\t}\n\n\toverride onExit() {\n\t\tthis.editor.setHintingShapes([])\n\t\tthis.editor.setCursor({ type: 'default', rotation: 0 })\n\t}\n\n\toverride onPointerUp() {\n\t\tconst { shape, handle } = this.info\n\n\t\tif (this.editor.isShapeOfType(shape, 'note')) {\n\t\t\tconst { editor } = this\n\t\t\tconst nextNote = getNoteForAdjacentPosition(editor, shape, handle, false)\n\t\t\tif (nextNote) {\n\t\t\t\tstartEditingShapeWithRichText(editor, nextNote, { selectAll: true })\n\t\t\t\treturn\n\t\t\t}\n\t\t}\n\n\t\tthis.parent.transition('idle', this.info)\n\t}\n\n\toverride onDoubleClick(info: TLClickEventInfo) {\n\t\tif (\n\t\t\tthis.editor.inputs.getShiftKey() ||\n\t\t\tinfo.phase !== 'down' ||\n\t\t\tinfo.ctrlKey ||\n\t\t\tinfo.shiftKey\n\t\t) {\n\t\t\treturn\n\t\t}\n\n\t\tthis.parent.transition('idle')\n\t\tthis.parent.getCurrent()?.handleEvent(info)\n\t}\n\n\toverride onPointerMove(info: TLPointerEventInfo) {\n\t\tconst { editor } = this\n\t\tif (editor.inputs.getIsDragging()) {\n\t\t\tif (this.didCtrlOnEnter) {\n\t\t\t\tthis.parent.transition('brushing', info)\n\t\t\t} else {\n\t\t\t\tthis.startDraggingHandle()\n\t\t\t}\n\t\t}\n\t}\n\n\toverride onLongPress() {\n\t\tthis.startDraggingHandle()\n\t}\n\n\tprivate startDraggingHandle() {\n\t\tconst { editor } = this\n\t\tif (editor.getIsReadonly()) return\n\t\tconst { shape, handle } = this.info\n\n\t\tif (editor.isShapeOfType(shape, 'note')) {\n\t\t\tconst noteUtil = editor.getShapeUtil(shape) as NoteShapeUtil\n\t\t\tconst dv = getDisplayValues(noteUtil, shape)\n\n\t\t\tconst nextNote = getNoteForAdjacentPosition(editor, shape, handle, true)\n\t\t\tif (nextNote) {\n\t\t\t\t// Center the shape on the current pointer\n\t\t\t\tconst centeredOnPointer = editor\n\t\t\t\t\t.getPointInParentSpace(nextNote, editor.inputs.getOriginPagePoint())\n\t\t\t\t\t.sub(\n\t\t\t\t\t\tVec.Rot(\n\t\t\t\t\t\t\tnew Vec(dv.noteWidth / 2, dv.noteHeight / 2).mul(shape.props.scale),\n\t\t\t\t\t\t\tnextNote.rotation\n\t\t\t\t\t\t)\n\t\t\t\t\t)\n\t\t\t\teditor.updateShape({ ...nextNote, x: centeredOnPointer.x, y: centeredOnPointer.y })\n\n\t\t\t\t// Then select and begin translating the shape\n\t\t\t\teditor\n\t\t\t\t\t.setHoveredShape(nextNote.id) // important!\n\t\t\t\t\t.select(nextNote.id)\n\t\t\t\t\t.setCurrentTool('select.translating', {\n\t\t\t\t\t\t...this.info,\n\t\t\t\t\t\ttarget: 'shape',\n\t\t\t\t\t\tshape: editor.getShape(nextNote),\n\t\t\t\t\t\tonInteractionEnd: 'note',\n\t\t\t\t\t\tisCreating: true,\n\t\t\t\t\t\tonCreate: () => {\n\t\t\t\t\t\t\t// When we're done, start editing it\n\t\t\t\t\t\t\tstartEditingShapeWithRichText(editor, nextNote, { selectAll: true })\n\t\t\t\t\t\t},\n\t\t\t\t\t})\n\t\t\t\treturn\n\t\t\t}\n\t\t}\n\n\t\tthis.parent.transition('dragging_handle', this.info)\n\t}\n\n\toverride onCancel() {\n\t\tthis.cancel()\n\t}\n\n\toverride onComplete() {\n\t\tthis.cancel()\n\t}\n\n\toverride onInterrupt() {\n\t\tthis.cancel()\n\t}\n\n\tprivate cancel() {\n\t\tthis.parent.transition('idle')\n\t}\n}\n\nfunction getNoteForAdjacentPosition(\n\teditor: Editor,\n\tshape: TLNoteShape,\n\thandle: TLHandle,\n\tforceNew: boolean\n) {\n\tconst noteUtil = editor.getShapeUtil(shape) as NoteShapeUtil\n\tconst dv = getDisplayValues(noteUtil, shape)\n\n\tconst pageTransform = editor.getShapePageTransform(shape.id)!\n\tconst pagePoint = pageTransform.point()\n\tconst pageRotation = pageTransform.rotation()\n\tconst positions = getNoteAdjacentPositions(editor, {\n\t\tpagePoint,\n\t\tpageRotation,\n\t\tgrowY: shape.props.growY * shape.props.scale,\n\t\textraHeight: 0,\n\t\tscale: shape.props.scale,\n\t\tnoteWidth: dv.noteWidth,\n\t\tnoteHeight: dv.noteHeight,\n\t})\n\tconst position = positions[handle.index]\n\tif (position) {\n\t\treturn getNoteShapeForAdjacentPosition(editor, {\n\t\t\tshape,\n\t\t\tcenter: position,\n\t\t\tpageRotation,\n\t\t\tnoteWidth: dv.noteWidth,\n\t\t\tnoteHeight: dv.noteHeight,\n\t\t\tforceNew,\n\t\t})\n\t}\n\treturn undefined\n}\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["import {\n\tEditor,\n\tStateNode,\n\tTLClickEventInfo,\n\tTLHandle,\n\tTLNoteShape,\n\tTLPointerEventInfo,\n\tVec,\n} from '@tldraw/editor'\nimport { updateArrowTargetState } from '../../../shapes/arrow/arrowTargetState'\nimport { getArrowBindings } from '../../../shapes/arrow/shared'\nimport {\n\tgetNoteAdjacentPositions,\n\tgetNoteShapeForAdjacentPosition,\n} from '../../../shapes/note/noteHelpers'\nimport type { NoteShapeUtil } from '../../../shapes/note/NoteShapeUtil'\nimport { getDisplayValues } from '../../../shapes/shared/getDisplayValues'\nimport { startEditingShapeWithRichText } from '../selectHelpers'\n\nexport class PointingHandle extends StateNode {\n\tstatic override id = 'pointing_handle'\n\n\tdidCtrlOnEnter = false\n\n\tinfo = {} as TLPointerEventInfo & { target: 'handle' }\n\tisDoubleClick = false\n\n\toverride onEnter(info: TLPointerEventInfo & { target: 'handle' }) {\n\t\tthis.info = info\n\t\tthis.isDoubleClick = false\n\n\t\tthis.didCtrlOnEnter = info.accelKey\n\n\t\tconst { shape } = info\n\t\tif (this.editor.isShapeOfType(shape, 'arrow')) {\n\t\t\tconst initialBindings = getArrowBindings(this.editor, shape)\n\t\t\tconst currentBinding = initialBindings[info.handle.id as 'start' | 'end']\n\t\t\tconst oppositeBinding = initialBindings[info.handle.id === 'start' ? 'end' : 'start']\n\t\t\tconst arrowTransform = this.editor.getShapePageTransform(shape.id)!\n\n\t\t\tif (currentBinding) {\n\t\t\t\tupdateArrowTargetState({\n\t\t\t\t\teditor: this.editor,\n\t\t\t\t\tpointInPageSpace: arrowTransform.applyToPoint(info.handle),\n\t\t\t\t\tarrow: shape,\n\t\t\t\t\tisPrecise: currentBinding.props.isPrecise,\n\t\t\t\t\tcurrentBinding: currentBinding,\n\t\t\t\t\toppositeBinding: oppositeBinding,\n\t\t\t\t})\n\t\t\t}\n\t\t}\n\n\t\tthis.editor.setCursor({ type: 'grabbing', rotation: 0 })\n\t}\n\n\toverride onExit() {\n\t\tthis.editor.setHintingShapes([])\n\t\tthis.editor.setCursor({ type: 'default', rotation: 0 })\n\t}\n\n\toverride onPointerUp() {\n\t\tconst { shape, handle } = this.info\n\n\t\tif (this.isDoubleClick) {\n\t\t\tthis.parent.transition('idle')\n\t\t\tthis.parent.getCurrent()?.handleEvent({\n\t\t\t\t...this.info,\n\t\t\t\ttype: 'click',\n\t\t\t\tname: 'double_click',\n\t\t\t\tphase: 'down',\n\t\t\t})\n\t\t\treturn\n\t\t}\n\n\t\tif (this.editor.isShapeOfType(shape, 'note')) {\n\t\t\tconst { editor } = this\n\t\t\tconst nextNote = getNoteForAdjacentPosition(editor, shape, handle, false)\n\t\t\tif (nextNote) {\n\t\t\t\tstartEditingShapeWithRichText(editor, nextNote, { selectAll: true })\n\t\t\t\treturn\n\t\t\t}\n\t\t}\n\n\t\tthis.parent.transition('idle', this.info)\n\t}\n\n\toverride onDoubleClick(info: TLClickEventInfo) {\n\t\tif (\n\t\t\tthis.editor.inputs.getShiftKey() ||\n\t\t\tinfo.phase !== 'down' ||\n\t\t\tinfo.ctrlKey ||\n\t\t\tinfo.shiftKey\n\t\t) {\n\t\t\treturn\n\t\t}\n\n\t\tthis.isDoubleClick = true\n\t}\n\n\toverride onPointerMove(info: TLPointerEventInfo) {\n\t\tconst { editor } = this\n\t\tif (editor.inputs.getIsDragging()) {\n\t\t\tif (this.didCtrlOnEnter) {\n\t\t\t\tthis.parent.transition('brushing', info)\n\t\t\t} else {\n\t\t\t\tthis.startDraggingHandle()\n\t\t\t}\n\t\t}\n\t}\n\n\toverride onLongPress() {\n\t\tthis.startDraggingHandle()\n\t}\n\n\tprivate startDraggingHandle() {\n\t\tconst { editor } = this\n\t\tif (editor.getIsReadonly()) return\n\t\tconst { shape, handle } = this.info\n\n\t\tif (editor.isShapeOfType(shape, 'note')) {\n\t\t\tconst noteUtil = editor.getShapeUtil(shape) as NoteShapeUtil\n\t\t\tconst dv = getDisplayValues(noteUtil, shape)\n\n\t\t\tconst nextNote = getNoteForAdjacentPosition(editor, shape, handle, true)\n\t\t\tif (nextNote) {\n\t\t\t\t// Center the shape on the current pointer\n\t\t\t\tconst centeredOnPointer = editor\n\t\t\t\t\t.getPointInParentSpace(nextNote, editor.inputs.getOriginPagePoint())\n\t\t\t\t\t.sub(\n\t\t\t\t\t\tVec.Rot(\n\t\t\t\t\t\t\tnew Vec(dv.noteWidth / 2, dv.noteHeight / 2).mul(shape.props.scale),\n\t\t\t\t\t\t\tnextNote.rotation\n\t\t\t\t\t\t)\n\t\t\t\t\t)\n\t\t\t\teditor.updateShape({ ...nextNote, x: centeredOnPointer.x, y: centeredOnPointer.y })\n\n\t\t\t\t// Then select and begin translating the shape\n\t\t\t\teditor\n\t\t\t\t\t.setHoveredShape(nextNote.id) // important!\n\t\t\t\t\t.select(nextNote.id)\n\t\t\t\t\t.setCurrentTool('select.translating', {\n\t\t\t\t\t\t...this.info,\n\t\t\t\t\t\ttarget: 'shape',\n\t\t\t\t\t\tshape: editor.getShape(nextNote),\n\t\t\t\t\t\tonInteractionEnd: 'note',\n\t\t\t\t\t\tisCreating: true,\n\t\t\t\t\t\tonCreate: () => {\n\t\t\t\t\t\t\t// When we're done, start editing it\n\t\t\t\t\t\t\tstartEditingShapeWithRichText(editor, nextNote, { selectAll: true })\n\t\t\t\t\t\t},\n\t\t\t\t\t})\n\t\t\t\treturn\n\t\t\t}\n\t\t}\n\n\t\tthis.parent.transition('dragging_handle', this.info)\n\t}\n\n\toverride onCancel() {\n\t\tthis.cancel()\n\t}\n\n\toverride onComplete() {\n\t\tthis.cancel()\n\t}\n\n\toverride onInterrupt() {\n\t\tthis.cancel()\n\t}\n\n\tprivate cancel() {\n\t\tthis.parent.transition('idle')\n\t}\n}\n\nfunction getNoteForAdjacentPosition(\n\teditor: Editor,\n\tshape: TLNoteShape,\n\thandle: TLHandle,\n\tforceNew: boolean\n) {\n\tconst noteUtil = editor.getShapeUtil(shape) as NoteShapeUtil\n\tconst dv = getDisplayValues(noteUtil, shape)\n\n\tconst pageTransform = editor.getShapePageTransform(shape.id)!\n\tconst pagePoint = pageTransform.point()\n\tconst pageRotation = pageTransform.rotation()\n\tconst positions = getNoteAdjacentPositions(editor, {\n\t\tpagePoint,\n\t\tpageRotation,\n\t\tgrowY: shape.props.growY * shape.props.scale,\n\t\textraHeight: 0,\n\t\tscale: shape.props.scale,\n\t\tnoteWidth: dv.noteWidth,\n\t\tnoteHeight: dv.noteHeight,\n\t})\n\tconst position = positions[handle.index]\n\tif (position) {\n\t\treturn getNoteShapeForAdjacentPosition(editor, {\n\t\t\tshape,\n\t\t\tcenter: position,\n\t\t\tpageRotation,\n\t\t\tnoteWidth: dv.noteWidth,\n\t\t\tnoteHeight: dv.noteHeight,\n\t\t\tforceNew,\n\t\t})\n\t}\n\treturn undefined\n}\n"],
5
+ "mappings": "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",
6
6
  "names": []
7
7
  }
@@ -22,10 +22,10 @@ __export(version_exports, {
22
22
  version: () => version
23
23
  });
24
24
  module.exports = __toCommonJS(version_exports);
25
- const version = "5.2.2";
25
+ const version = "5.2.4";
26
26
  const publishDates = {
27
27
  major: "2026-05-06T16:28:18.473Z",
28
28
  minor: "2026-07-01T09:20:01.735Z",
29
- patch: "2026-07-02T09:30:17.167Z"
29
+ patch: "2026-07-09T17:45:01.425Z"
30
30
  };
31
31
  //# sourceMappingURL=version.js.map
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../src/lib/ui/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 = '5.2.2'\nexport const publishDates = {\n\tmajor: '2026-05-06T16:28:18.473Z',\n\tminor: '2026-07-01T09:20:01.735Z',\n\tpatch: '2026-07-02T09:30:17.167Z',\n}\n"],
4
+ "sourcesContent": ["// This file is automatically generated by internal/scripts/refresh-assets.ts.\n// Do not edit manually. Or do, I'm a comment, not a cop.\n\nexport const version = '5.2.4'\nexport const publishDates = {\n\tmajor: '2026-05-06T16:28:18.473Z',\n\tminor: '2026-07-01T09:20:01.735Z',\n\tpatch: '2026-07-09T17:45:01.425Z',\n}\n"],
5
5
  "mappings": ";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAGO,MAAM,UAAU;AAChB,MAAM,eAAe;AAAA,EAC3B,OAAO;AAAA,EACP,OAAO;AAAA,EACP,OAAO;AACR;",
6
6
  "names": []
7
7
  }
@@ -634,7 +634,7 @@ import {
634
634
  } from "./lib/utils/tldr/file.mjs";
635
635
  registerTldrawLibraryVersion(
636
636
  "tldraw",
637
- "5.2.2",
637
+ "5.2.4",
638
638
  "esm"
639
639
  );
640
640
  export {
@@ -259,8 +259,8 @@ function DrawShapeSvg({
259
259
  }
260
260
  const strokePoints = getStrokePoints(allPointsFromSegments, options);
261
261
  const isDot = strokePoints.length < 2;
262
- const solidStrokePath = isDot ? getDot(allPointsFromSegments[0], 0) : getSvgPathFromStrokePoints(strokePoints, shape.props.isClosed);
263
262
  const fill = isDot || shape.props.isClosed ? shape.props.fill : "none";
263
+ const solidStrokePath = isDot ? getDot(allPointsFromSegments[0], 0) : getSvgPathFromStrokePoints(strokePoints, shape.props.isClosed && fill !== "none");
264
264
  return /* @__PURE__ */ jsxs(Fragment, { children: [
265
265
  isDot || !shape.props.isClosed || fill === "none" ? null : fill === "pattern" ? /* @__PURE__ */ jsx(
266
266
  PatternFill,
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../src/lib/shapes/draw/DrawShapeUtil.tsx"],
4
- "sourcesContent": ["import {\n\tBox,\n\tCircle2d,\n\tPolygon2d,\n\tPolyline2d,\n\tSVGContainer,\n\tShapeUtil,\n\tSvgExportContext,\n\tTLDrawShape,\n\tTLDrawShapeProps,\n\tTLResizeInfo,\n\tTLShapeUtilCanvasSvgDef,\n\tVecLike,\n\tb64Vecs,\n\tdrawShapeMigrations,\n\tdrawShapeProps,\n\tgetColorValue,\n\tlast,\n\tlerp,\n\trng,\n\tuseEditor,\n\tuseValue,\n} from '@tldraw/editor'\nimport { STROKE_SIZES } from '../shared/default-shape-constants'\nimport { DEFAULT_FILL_COLOR_NAMES } from '../shared/defaultFills'\nimport { getFillDefForCanvas, getFillDefForExport } from '../shared/defaultStyleDefs'\nimport { getStrokePoints } from '../shared/freehand/getStrokePoints'\nimport { getSvgPathFromStrokePoints } from '../shared/freehand/svg'\nimport { svgInk } from '../shared/freehand/svgInk'\nimport { ShapeOptionsWithDisplayValues, getDisplayValues } from '../shared/getDisplayValues'\nimport { interpolateSegments } from '../shared/interpolate-props'\nimport { PatternFill } from '../shared/PatternFill'\nimport {\n\tgetDrawShapeStrokeDashArray,\n\tgetFreehandOptions,\n\tgetPointsFromDrawSegments,\n} from './getPath'\n\n/** @public */\nexport interface DrawShapeUtilDisplayValues {\n\tstrokeColor: string\n\tstrokeWidth: number\n\tfillColor: string\n\tpatternFillFallbackColor: string\n}\n\n/** @public */\nexport interface DrawShapeOptions extends ShapeOptionsWithDisplayValues<\n\tTLDrawShape,\n\tDrawShapeUtilDisplayValues\n> {\n\t/**\n\t * The maximum number of points in a line before the draw tool will begin a new shape.\n\t * A higher number will lead to poor performance while drawing very long lines.\n\t */\n\treadonly maxPointsPerShape: number\n}\n\n/** @public */\nexport class DrawShapeUtil extends ShapeUtil<TLDrawShape> {\n\tstatic override type = 'draw' as const\n\tstatic override props = drawShapeProps\n\tstatic override migrations = drawShapeMigrations\n\n\toverride options: DrawShapeOptions = {\n\t\tmaxPointsPerShape: 600,\n\t\tgetDefaultDisplayValues(_editor, shape, theme, colorMode): DrawShapeUtilDisplayValues {\n\t\t\tconst { color, fill, size } = shape.props\n\t\t\tconst colors = theme.colors[colorMode]\n\t\t\treturn {\n\t\t\t\tstrokeColor: getColorValue(colors, color, 'solid'),\n\t\t\t\tstrokeWidth: theme.strokeWidth * STROKE_SIZES[size],\n\t\t\t\tfillColor:\n\t\t\t\t\tfill === 'none'\n\t\t\t\t\t\t? 'transparent'\n\t\t\t\t\t\t: fill === 'semi'\n\t\t\t\t\t\t\t? colors.solid\n\t\t\t\t\t\t\t: getColorValue(colors, color, DEFAULT_FILL_COLOR_NAMES[fill]),\n\t\t\t\tpatternFillFallbackColor: getColorValue(colors, color, 'semi'),\n\t\t\t}\n\t\t},\n\t\tgetCustomDisplayValues(): Partial<DrawShapeUtilDisplayValues> {\n\t\t\treturn {}\n\t\t},\n\t}\n\n\toverride hideResizeHandles(shape: TLDrawShape) {\n\t\treturn getIsDot(shape)\n\t}\n\toverride hideRotateHandle(shape: TLDrawShape) {\n\t\treturn getIsDot(shape)\n\t}\n\toverride hideSelectionBoundsFg(shape: TLDrawShape) {\n\t\treturn getIsDot(shape)\n\t}\n\n\toverride getDefaultProps(): TLDrawShape['props'] {\n\t\treturn {\n\t\t\tsegments: [],\n\t\t\tcolor: 'black',\n\t\t\tfill: 'none',\n\t\t\tdash: 'draw',\n\t\t\tsize: 'm',\n\t\t\tisComplete: false,\n\t\t\tisClosed: false,\n\t\t\tisPen: false,\n\t\t\tscale: 1,\n\t\t\tscaleX: 1,\n\t\t\tscaleY: 1,\n\t\t}\n\t}\n\n\tgetGeometry(shape: TLDrawShape) {\n\t\tconst points = getPointsFromDrawSegments(\n\t\t\tshape.props.segments,\n\t\t\tshape.props.scaleX,\n\t\t\tshape.props.scaleY\n\t\t)\n\n\t\tconst sw = (getDisplayValues(this, shape).strokeWidth + 1) * shape.props.scale\n\n\t\t// A dot\n\t\tif (shape.props.segments.length === 1) {\n\t\t\tconst box = Box.FromPoints(points)\n\t\t\tif (box.width < sw * 2 && box.height < sw * 2) {\n\t\t\t\treturn new Circle2d({\n\t\t\t\t\tx: -sw,\n\t\t\t\t\ty: -sw,\n\t\t\t\t\tradius: sw,\n\t\t\t\t\tisFilled: true,\n\t\t\t\t})\n\t\t\t}\n\t\t}\n\n\t\tconst strokePoints = getStrokePoints(\n\t\t\tpoints,\n\t\t\tgetFreehandOptions(shape.props, sw, shape.props.isPen, true)\n\t\t).map((p) => p.point)\n\n\t\t// A closed draw stroke\n\t\tif (shape.props.isClosed && strokePoints.length > 2) {\n\t\t\treturn new Polygon2d({\n\t\t\t\tpoints: strokePoints,\n\t\t\t\tisFilled: shape.props.fill !== 'none',\n\t\t\t})\n\t\t}\n\n\t\tif (strokePoints.length === 1) {\n\t\t\treturn new Circle2d({\n\t\t\t\tx: -sw,\n\t\t\t\ty: -sw,\n\t\t\t\tradius: sw,\n\t\t\t\tisFilled: true,\n\t\t\t})\n\t\t}\n\n\t\t// An open draw stroke\n\t\treturn new Polyline2d({\n\t\t\tpoints: strokePoints,\n\t\t})\n\t}\n\n\tcomponent(shape: TLDrawShape) {\n\t\tconst dv = getDisplayValues(this, shape)\n\t\treturn (\n\t\t\t<SVGContainer>\n\t\t\t\t<DrawShapeSvg\n\t\t\t\t\tshape={shape}\n\t\t\t\t\tstrokeColor={dv.strokeColor}\n\t\t\t\t\tstrokeWidth={dv.strokeWidth}\n\t\t\t\t\tfillColor={dv.fillColor}\n\t\t\t\t\tpatternFillFallbackColor={dv.patternFillFallbackColor}\n\t\t\t\t/>\n\t\t\t</SVGContainer>\n\t\t)\n\t}\n\n\toverride getIndicatorPath(shape: TLDrawShape): Path2D {\n\t\tconst allPointsFromSegments = getPointsFromDrawSegments(\n\t\t\tshape.props.segments,\n\t\t\tshape.props.scaleX,\n\t\t\tshape.props.scaleY\n\t\t)\n\n\t\tlet sw = (getDisplayValues(this, shape).strokeWidth + 1) * shape.props.scale\n\n\t\tconst zoomLevel = this.editor.getEfficientZoomLevel()\n\t\tconst forceSolid = zoomLevel < 0.5 && zoomLevel < 1.5 / sw\n\n\t\tif (\n\t\t\t!forceSolid &&\n\t\t\t!shape.props.isPen &&\n\t\t\tshape.props.dash === 'draw' &&\n\t\t\tallPointsFromSegments.length === 1\n\t\t) {\n\t\t\tsw += rng(shape.id)() * (sw / 6)\n\t\t}\n\n\t\tconst showAsComplete = shape.props.isComplete || last(shape.props.segments)?.type === 'straight'\n\t\tconst options = getFreehandOptions(shape.props, sw, showAsComplete, true)\n\t\tconst strokePoints = getStrokePoints(allPointsFromSegments, options)\n\t\tconst solidStrokePath =\n\t\t\tstrokePoints.length > 1\n\t\t\t\t? getSvgPathFromStrokePoints(strokePoints, shape.props.isClosed)\n\t\t\t\t: getDot(allPointsFromSegments[0], sw)\n\n\t\treturn new Path2D(solidStrokePath)\n\t}\n\n\toverride toSvg(shape: TLDrawShape, ctx: SvgExportContext) {\n\t\tctx.addExportDef(getFillDefForExport(shape.props.fill))\n\t\tconst dv = getDisplayValues(this, shape, ctx.colorMode)\n\t\tconst scaleFactor = 1 / shape.props.scale\n\t\treturn (\n\t\t\t<g transform={`scale(${scaleFactor})`}>\n\t\t\t\t<DrawShapeSvg\n\t\t\t\t\tshape={shape}\n\t\t\t\t\tzoomOverride={1}\n\t\t\t\t\tstrokeColor={dv.strokeColor}\n\t\t\t\t\tstrokeWidth={dv.strokeWidth}\n\t\t\t\t\tfillColor={dv.fillColor}\n\t\t\t\t\tpatternFillFallbackColor={dv.patternFillFallbackColor}\n\t\t\t\t/>\n\t\t\t</g>\n\t\t)\n\t}\n\n\toverride getCanvasSvgDefs(): TLShapeUtilCanvasSvgDef[] {\n\t\treturn [getFillDefForCanvas()]\n\t}\n\n\toverride onResize(shape: TLDrawShape, info: TLResizeInfo<TLDrawShape>) {\n\t\tconst newScaleX = info.scaleX * shape.props.scaleX\n\t\tconst newScaleY = info.scaleY * shape.props.scaleY\n\t\tif (newScaleX === 0 || newScaleY === 0) return\n\n\t\treturn {\n\t\t\tprops: {\n\t\t\t\tscaleX: newScaleX,\n\t\t\t\tscaleY: newScaleY,\n\t\t\t},\n\t\t}\n\t}\n\n\toverride expandSelectionOutlinePx(shape: TLDrawShape): number {\n\t\tconst multiplier = shape.props.dash === 'draw' ? 1.6 : 1\n\t\treturn ((getDisplayValues(this, shape).strokeWidth * multiplier) / 2) * shape.props.scale\n\t}\n\toverride getInterpolatedProps(\n\t\tstartShape: TLDrawShape,\n\t\tendShape: TLDrawShape,\n\t\tt: number\n\t): TLDrawShapeProps {\n\t\treturn {\n\t\t\t...(t > 0.5 ? endShape.props : startShape.props),\n\t\t\tsegments: interpolateSegments(startShape.props.segments, endShape.props.segments, t),\n\t\t\tscale: lerp(startShape.props.scale, endShape.props.scale, t),\n\t\t}\n\t}\n}\n\nfunction getDot(point: VecLike, sw: number) {\n\tconst r = (sw + 1) * 0.5\n\treturn `M ${point.x} ${point.y} m -${r}, 0 a ${r},${r} 0 1,0 ${r * 2},0 a ${r},${r} 0 1,0 -${\n\t\tr * 2\n\t},0`\n}\n\nfunction getIsDot(shape: TLDrawShape) {\n\t// A dot is a single-point segment. isSinglePoint knows the per-encoding length\n\t// (and takes the segment's dim), so this stays correct for both 2D and 3D paths.\n\t// A bare length threshold can't: a 2-point 2D path is the same length as a 1-point\n\t// 3D path, so only the dim disambiguates them.\n\tconst segment = shape.props.segments[0]\n\treturn shape.props.segments.length === 1 && b64Vecs.isSinglePoint(segment.path, segment.dim)\n}\n\nfunction DrawShapeSvg({\n\tshape,\n\tzoomOverride,\n\tstrokeColor,\n\tstrokeWidth: baseStrokeWidth,\n\tfillColor,\n\tpatternFillFallbackColor,\n}: {\n\tshape: TLDrawShape\n\tzoomOverride?: number\n\tstrokeColor: string\n\tstrokeWidth: number\n\tfillColor: string\n\tpatternFillFallbackColor: string\n}) {\n\tconst editor = useEditor()\n\n\tconst allPointsFromSegments = getPointsFromDrawSegments(\n\t\tshape.props.segments,\n\t\tshape.props.scaleX,\n\t\tshape.props.scaleY\n\t)\n\n\tconst showAsComplete = shape.props.isComplete || last(shape.props.segments)?.type === 'straight'\n\n\tlet sw = (baseStrokeWidth + 1) * shape.props.scale\n\tconst forceSolid = useValue(\n\t\t'force solid',\n\t\t() => {\n\t\t\tconst zoomLevel = zoomOverride ?? editor.getEfficientZoomLevel()\n\t\t\treturn zoomLevel < 0.5 && zoomLevel < 1.5 / sw\n\t\t},\n\t\t[editor, sw, zoomOverride]\n\t)\n\n\tconst dotAdjustment = useValue(\n\t\t'dot adjustment',\n\t\t() => {\n\t\t\tconst zoomLevel = zoomOverride ?? editor.getEfficientZoomLevel()\n\t\t\t// If we're zoomed way out (10%), then we need to make the dotted line go to 9 instead 0.1\n\t\t\t// Chrome doesn't render anything otherwise.\n\t\t\treturn zoomLevel < 0.2 ? 9 : 0.1\n\t\t},\n\t\t[editor, zoomOverride]\n\t)\n\n\tif (\n\t\t!forceSolid &&\n\t\t!shape.props.isPen &&\n\t\tshape.props.dash === 'draw' &&\n\t\tallPointsFromSegments.length === 1\n\t) {\n\t\tsw += rng(shape.id)() * (sw / 6)\n\t}\n\n\tconst options = getFreehandOptions(shape.props, sw, showAsComplete, forceSolid)\n\n\tif (!forceSolid && shape.props.dash === 'draw') {\n\t\treturn (\n\t\t\t<>\n\t\t\t\t{shape.props.isClosed &&\n\t\t\t\t\tshape.props.fill !== 'none' &&\n\t\t\t\t\tallPointsFromSegments.length > 1 &&\n\t\t\t\t\t(shape.props.fill === 'pattern' ? (\n\t\t\t\t\t\t<PatternFill\n\t\t\t\t\t\t\td={getSvgPathFromStrokePoints(\n\t\t\t\t\t\t\t\tgetStrokePoints(allPointsFromSegments, options),\n\t\t\t\t\t\t\t\tshape.props.isClosed\n\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\tfillColor={fillColor}\n\t\t\t\t\t\t\tpatternFillFallbackColor={patternFillFallbackColor}\n\t\t\t\t\t\t\tscale={shape.props.scale}\n\t\t\t\t\t\t/>\n\t\t\t\t\t) : (\n\t\t\t\t\t\t<path\n\t\t\t\t\t\t\tfill={fillColor}\n\t\t\t\t\t\t\td={getSvgPathFromStrokePoints(\n\t\t\t\t\t\t\t\tgetStrokePoints(allPointsFromSegments, options),\n\t\t\t\t\t\t\t\tshape.props.isClosed\n\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t/>\n\t\t\t\t\t))}\n\t\t\t\t<path d={svgInk(allPointsFromSegments, options)} strokeLinecap=\"round\" fill={strokeColor} />\n\t\t\t</>\n\t\t)\n\t}\n\n\tconst strokePoints = getStrokePoints(allPointsFromSegments, options)\n\tconst isDot = strokePoints.length < 2\n\tconst solidStrokePath = isDot\n\t\t? getDot(allPointsFromSegments[0], 0)\n\t\t: getSvgPathFromStrokePoints(strokePoints, shape.props.isClosed)\n\n\tconst fill = isDot || shape.props.isClosed ? shape.props.fill : 'none'\n\n\treturn (\n\t\t<>\n\t\t\t{isDot || !shape.props.isClosed || fill === 'none' ? null : fill === 'pattern' ? (\n\t\t\t\t<PatternFill\n\t\t\t\t\td={solidStrokePath}\n\t\t\t\t\tfillColor={fillColor}\n\t\t\t\t\tpatternFillFallbackColor={patternFillFallbackColor}\n\t\t\t\t\tscale={shape.props.scale}\n\t\t\t\t/>\n\t\t\t) : (\n\t\t\t\t<path fill={fillColor} d={solidStrokePath} />\n\t\t\t)}\n\t\t\t{shape.props.dash !== 'none' && (\n\t\t\t\t<path\n\t\t\t\t\td={solidStrokePath}\n\t\t\t\t\tstrokeLinecap=\"round\"\n\t\t\t\t\tfill={isDot ? strokeColor : 'none'}\n\t\t\t\t\tstroke={strokeColor}\n\t\t\t\t\tstrokeWidth={sw}\n\t\t\t\t\tstrokeDasharray={isDot ? 'none' : getDrawShapeStrokeDashArray(shape, sw, dotAdjustment)}\n\t\t\t\t\tstrokeDashoffset=\"0\"\n\t\t\t\t/>\n\t\t\t)}\n\t\t</>\n\t)\n}\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["import {\n\tBox,\n\tCircle2d,\n\tPolygon2d,\n\tPolyline2d,\n\tSVGContainer,\n\tShapeUtil,\n\tSvgExportContext,\n\tTLDrawShape,\n\tTLDrawShapeProps,\n\tTLResizeInfo,\n\tTLShapeUtilCanvasSvgDef,\n\tVecLike,\n\tb64Vecs,\n\tdrawShapeMigrations,\n\tdrawShapeProps,\n\tgetColorValue,\n\tlast,\n\tlerp,\n\trng,\n\tuseEditor,\n\tuseValue,\n} from '@tldraw/editor'\nimport { STROKE_SIZES } from '../shared/default-shape-constants'\nimport { DEFAULT_FILL_COLOR_NAMES } from '../shared/defaultFills'\nimport { getFillDefForCanvas, getFillDefForExport } from '../shared/defaultStyleDefs'\nimport { getStrokePoints } from '../shared/freehand/getStrokePoints'\nimport { getSvgPathFromStrokePoints } from '../shared/freehand/svg'\nimport { svgInk } from '../shared/freehand/svgInk'\nimport { ShapeOptionsWithDisplayValues, getDisplayValues } from '../shared/getDisplayValues'\nimport { interpolateSegments } from '../shared/interpolate-props'\nimport { PatternFill } from '../shared/PatternFill'\nimport {\n\tgetDrawShapeStrokeDashArray,\n\tgetFreehandOptions,\n\tgetPointsFromDrawSegments,\n} from './getPath'\n\n/** @public */\nexport interface DrawShapeUtilDisplayValues {\n\tstrokeColor: string\n\tstrokeWidth: number\n\tfillColor: string\n\tpatternFillFallbackColor: string\n}\n\n/** @public */\nexport interface DrawShapeOptions extends ShapeOptionsWithDisplayValues<\n\tTLDrawShape,\n\tDrawShapeUtilDisplayValues\n> {\n\t/**\n\t * The maximum number of points in a line before the draw tool will begin a new shape.\n\t * A higher number will lead to poor performance while drawing very long lines.\n\t */\n\treadonly maxPointsPerShape: number\n}\n\n/** @public */\nexport class DrawShapeUtil extends ShapeUtil<TLDrawShape> {\n\tstatic override type = 'draw' as const\n\tstatic override props = drawShapeProps\n\tstatic override migrations = drawShapeMigrations\n\n\toverride options: DrawShapeOptions = {\n\t\tmaxPointsPerShape: 600,\n\t\tgetDefaultDisplayValues(_editor, shape, theme, colorMode): DrawShapeUtilDisplayValues {\n\t\t\tconst { color, fill, size } = shape.props\n\t\t\tconst colors = theme.colors[colorMode]\n\t\t\treturn {\n\t\t\t\tstrokeColor: getColorValue(colors, color, 'solid'),\n\t\t\t\tstrokeWidth: theme.strokeWidth * STROKE_SIZES[size],\n\t\t\t\tfillColor:\n\t\t\t\t\tfill === 'none'\n\t\t\t\t\t\t? 'transparent'\n\t\t\t\t\t\t: fill === 'semi'\n\t\t\t\t\t\t\t? colors.solid\n\t\t\t\t\t\t\t: getColorValue(colors, color, DEFAULT_FILL_COLOR_NAMES[fill]),\n\t\t\t\tpatternFillFallbackColor: getColorValue(colors, color, 'semi'),\n\t\t\t}\n\t\t},\n\t\tgetCustomDisplayValues(): Partial<DrawShapeUtilDisplayValues> {\n\t\t\treturn {}\n\t\t},\n\t}\n\n\toverride hideResizeHandles(shape: TLDrawShape) {\n\t\treturn getIsDot(shape)\n\t}\n\toverride hideRotateHandle(shape: TLDrawShape) {\n\t\treturn getIsDot(shape)\n\t}\n\toverride hideSelectionBoundsFg(shape: TLDrawShape) {\n\t\treturn getIsDot(shape)\n\t}\n\n\toverride getDefaultProps(): TLDrawShape['props'] {\n\t\treturn {\n\t\t\tsegments: [],\n\t\t\tcolor: 'black',\n\t\t\tfill: 'none',\n\t\t\tdash: 'draw',\n\t\t\tsize: 'm',\n\t\t\tisComplete: false,\n\t\t\tisClosed: false,\n\t\t\tisPen: false,\n\t\t\tscale: 1,\n\t\t\tscaleX: 1,\n\t\t\tscaleY: 1,\n\t\t}\n\t}\n\n\tgetGeometry(shape: TLDrawShape) {\n\t\tconst points = getPointsFromDrawSegments(\n\t\t\tshape.props.segments,\n\t\t\tshape.props.scaleX,\n\t\t\tshape.props.scaleY\n\t\t)\n\n\t\tconst sw = (getDisplayValues(this, shape).strokeWidth + 1) * shape.props.scale\n\n\t\t// A dot\n\t\tif (shape.props.segments.length === 1) {\n\t\t\tconst box = Box.FromPoints(points)\n\t\t\tif (box.width < sw * 2 && box.height < sw * 2) {\n\t\t\t\treturn new Circle2d({\n\t\t\t\t\tx: -sw,\n\t\t\t\t\ty: -sw,\n\t\t\t\t\tradius: sw,\n\t\t\t\t\tisFilled: true,\n\t\t\t\t})\n\t\t\t}\n\t\t}\n\n\t\tconst strokePoints = getStrokePoints(\n\t\t\tpoints,\n\t\t\tgetFreehandOptions(shape.props, sw, shape.props.isPen, true)\n\t\t).map((p) => p.point)\n\n\t\t// A closed draw stroke\n\t\tif (shape.props.isClosed && strokePoints.length > 2) {\n\t\t\treturn new Polygon2d({\n\t\t\t\tpoints: strokePoints,\n\t\t\t\tisFilled: shape.props.fill !== 'none',\n\t\t\t})\n\t\t}\n\n\t\tif (strokePoints.length === 1) {\n\t\t\treturn new Circle2d({\n\t\t\t\tx: -sw,\n\t\t\t\ty: -sw,\n\t\t\t\tradius: sw,\n\t\t\t\tisFilled: true,\n\t\t\t})\n\t\t}\n\n\t\t// An open draw stroke\n\t\treturn new Polyline2d({\n\t\t\tpoints: strokePoints,\n\t\t})\n\t}\n\n\tcomponent(shape: TLDrawShape) {\n\t\tconst dv = getDisplayValues(this, shape)\n\t\treturn (\n\t\t\t<SVGContainer>\n\t\t\t\t<DrawShapeSvg\n\t\t\t\t\tshape={shape}\n\t\t\t\t\tstrokeColor={dv.strokeColor}\n\t\t\t\t\tstrokeWidth={dv.strokeWidth}\n\t\t\t\t\tfillColor={dv.fillColor}\n\t\t\t\t\tpatternFillFallbackColor={dv.patternFillFallbackColor}\n\t\t\t\t/>\n\t\t\t</SVGContainer>\n\t\t)\n\t}\n\n\toverride getIndicatorPath(shape: TLDrawShape): Path2D {\n\t\tconst allPointsFromSegments = getPointsFromDrawSegments(\n\t\t\tshape.props.segments,\n\t\t\tshape.props.scaleX,\n\t\t\tshape.props.scaleY\n\t\t)\n\n\t\tlet sw = (getDisplayValues(this, shape).strokeWidth + 1) * shape.props.scale\n\n\t\tconst zoomLevel = this.editor.getEfficientZoomLevel()\n\t\tconst forceSolid = zoomLevel < 0.5 && zoomLevel < 1.5 / sw\n\n\t\tif (\n\t\t\t!forceSolid &&\n\t\t\t!shape.props.isPen &&\n\t\t\tshape.props.dash === 'draw' &&\n\t\t\tallPointsFromSegments.length === 1\n\t\t) {\n\t\t\tsw += rng(shape.id)() * (sw / 6)\n\t\t}\n\n\t\tconst showAsComplete = shape.props.isComplete || last(shape.props.segments)?.type === 'straight'\n\t\tconst options = getFreehandOptions(shape.props, sw, showAsComplete, true)\n\t\tconst strokePoints = getStrokePoints(allPointsFromSegments, options)\n\t\tconst solidStrokePath =\n\t\t\tstrokePoints.length > 1\n\t\t\t\t? getSvgPathFromStrokePoints(strokePoints, shape.props.isClosed)\n\t\t\t\t: getDot(allPointsFromSegments[0], sw)\n\n\t\treturn new Path2D(solidStrokePath)\n\t}\n\n\toverride toSvg(shape: TLDrawShape, ctx: SvgExportContext) {\n\t\tctx.addExportDef(getFillDefForExport(shape.props.fill))\n\t\tconst dv = getDisplayValues(this, shape, ctx.colorMode)\n\t\tconst scaleFactor = 1 / shape.props.scale\n\t\treturn (\n\t\t\t<g transform={`scale(${scaleFactor})`}>\n\t\t\t\t<DrawShapeSvg\n\t\t\t\t\tshape={shape}\n\t\t\t\t\tzoomOverride={1}\n\t\t\t\t\tstrokeColor={dv.strokeColor}\n\t\t\t\t\tstrokeWidth={dv.strokeWidth}\n\t\t\t\t\tfillColor={dv.fillColor}\n\t\t\t\t\tpatternFillFallbackColor={dv.patternFillFallbackColor}\n\t\t\t\t/>\n\t\t\t</g>\n\t\t)\n\t}\n\n\toverride getCanvasSvgDefs(): TLShapeUtilCanvasSvgDef[] {\n\t\treturn [getFillDefForCanvas()]\n\t}\n\n\toverride onResize(shape: TLDrawShape, info: TLResizeInfo<TLDrawShape>) {\n\t\tconst newScaleX = info.scaleX * shape.props.scaleX\n\t\tconst newScaleY = info.scaleY * shape.props.scaleY\n\t\tif (newScaleX === 0 || newScaleY === 0) return\n\n\t\treturn {\n\t\t\tprops: {\n\t\t\t\tscaleX: newScaleX,\n\t\t\t\tscaleY: newScaleY,\n\t\t\t},\n\t\t}\n\t}\n\n\toverride expandSelectionOutlinePx(shape: TLDrawShape): number {\n\t\tconst multiplier = shape.props.dash === 'draw' ? 1.6 : 1\n\t\treturn ((getDisplayValues(this, shape).strokeWidth * multiplier) / 2) * shape.props.scale\n\t}\n\toverride getInterpolatedProps(\n\t\tstartShape: TLDrawShape,\n\t\tendShape: TLDrawShape,\n\t\tt: number\n\t): TLDrawShapeProps {\n\t\treturn {\n\t\t\t...(t > 0.5 ? endShape.props : startShape.props),\n\t\t\tsegments: interpolateSegments(startShape.props.segments, endShape.props.segments, t),\n\t\t\tscale: lerp(startShape.props.scale, endShape.props.scale, t),\n\t\t}\n\t}\n}\n\nfunction getDot(point: VecLike, sw: number) {\n\tconst r = (sw + 1) * 0.5\n\treturn `M ${point.x} ${point.y} m -${r}, 0 a ${r},${r} 0 1,0 ${r * 2},0 a ${r},${r} 0 1,0 -${\n\t\tr * 2\n\t},0`\n}\n\nfunction getIsDot(shape: TLDrawShape) {\n\t// A dot is a single-point segment. isSinglePoint knows the per-encoding length\n\t// (and takes the segment's dim), so this stays correct for both 2D and 3D paths.\n\t// A bare length threshold can't: a 2-point 2D path is the same length as a 1-point\n\t// 3D path, so only the dim disambiguates them.\n\tconst segment = shape.props.segments[0]\n\treturn shape.props.segments.length === 1 && b64Vecs.isSinglePoint(segment.path, segment.dim)\n}\n\nfunction DrawShapeSvg({\n\tshape,\n\tzoomOverride,\n\tstrokeColor,\n\tstrokeWidth: baseStrokeWidth,\n\tfillColor,\n\tpatternFillFallbackColor,\n}: {\n\tshape: TLDrawShape\n\tzoomOverride?: number\n\tstrokeColor: string\n\tstrokeWidth: number\n\tfillColor: string\n\tpatternFillFallbackColor: string\n}) {\n\tconst editor = useEditor()\n\n\tconst allPointsFromSegments = getPointsFromDrawSegments(\n\t\tshape.props.segments,\n\t\tshape.props.scaleX,\n\t\tshape.props.scaleY\n\t)\n\n\tconst showAsComplete = shape.props.isComplete || last(shape.props.segments)?.type === 'straight'\n\n\tlet sw = (baseStrokeWidth + 1) * shape.props.scale\n\tconst forceSolid = useValue(\n\t\t'force solid',\n\t\t() => {\n\t\t\tconst zoomLevel = zoomOverride ?? editor.getEfficientZoomLevel()\n\t\t\treturn zoomLevel < 0.5 && zoomLevel < 1.5 / sw\n\t\t},\n\t\t[editor, sw, zoomOverride]\n\t)\n\n\tconst dotAdjustment = useValue(\n\t\t'dot adjustment',\n\t\t() => {\n\t\t\tconst zoomLevel = zoomOverride ?? editor.getEfficientZoomLevel()\n\t\t\t// If we're zoomed way out (10%), then we need to make the dotted line go to 9 instead 0.1\n\t\t\t// Chrome doesn't render anything otherwise.\n\t\t\treturn zoomLevel < 0.2 ? 9 : 0.1\n\t\t},\n\t\t[editor, zoomOverride]\n\t)\n\n\tif (\n\t\t!forceSolid &&\n\t\t!shape.props.isPen &&\n\t\tshape.props.dash === 'draw' &&\n\t\tallPointsFromSegments.length === 1\n\t) {\n\t\tsw += rng(shape.id)() * (sw / 6)\n\t}\n\n\tconst options = getFreehandOptions(shape.props, sw, showAsComplete, forceSolid)\n\n\tif (!forceSolid && shape.props.dash === 'draw') {\n\t\treturn (\n\t\t\t<>\n\t\t\t\t{shape.props.isClosed &&\n\t\t\t\t\tshape.props.fill !== 'none' &&\n\t\t\t\t\tallPointsFromSegments.length > 1 &&\n\t\t\t\t\t(shape.props.fill === 'pattern' ? (\n\t\t\t\t\t\t<PatternFill\n\t\t\t\t\t\t\td={getSvgPathFromStrokePoints(\n\t\t\t\t\t\t\t\tgetStrokePoints(allPointsFromSegments, options),\n\t\t\t\t\t\t\t\tshape.props.isClosed\n\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\tfillColor={fillColor}\n\t\t\t\t\t\t\tpatternFillFallbackColor={patternFillFallbackColor}\n\t\t\t\t\t\t\tscale={shape.props.scale}\n\t\t\t\t\t\t/>\n\t\t\t\t\t) : (\n\t\t\t\t\t\t<path\n\t\t\t\t\t\t\tfill={fillColor}\n\t\t\t\t\t\t\td={getSvgPathFromStrokePoints(\n\t\t\t\t\t\t\t\tgetStrokePoints(allPointsFromSegments, options),\n\t\t\t\t\t\t\t\tshape.props.isClosed\n\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t/>\n\t\t\t\t\t))}\n\t\t\t\t<path d={svgInk(allPointsFromSegments, options)} strokeLinecap=\"round\" fill={strokeColor} />\n\t\t\t</>\n\t\t)\n\t}\n\n\tconst strokePoints = getStrokePoints(allPointsFromSegments, options)\n\tconst isDot = strokePoints.length < 2\n\tconst fill = isDot || shape.props.isClosed ? shape.props.fill : 'none'\n\n\tconst solidStrokePath = isDot\n\t\t? getDot(allPointsFromSegments[0], 0)\n\t\t: getSvgPathFromStrokePoints(strokePoints, shape.props.isClosed && fill !== 'none')\n\n\treturn (\n\t\t<>\n\t\t\t{isDot || !shape.props.isClosed || fill === 'none' ? null : fill === 'pattern' ? (\n\t\t\t\t<PatternFill\n\t\t\t\t\td={solidStrokePath}\n\t\t\t\t\tfillColor={fillColor}\n\t\t\t\t\tpatternFillFallbackColor={patternFillFallbackColor}\n\t\t\t\t\tscale={shape.props.scale}\n\t\t\t\t/>\n\t\t\t) : (\n\t\t\t\t<path fill={fillColor} d={solidStrokePath} />\n\t\t\t)}\n\t\t\t{shape.props.dash !== 'none' && (\n\t\t\t\t<path\n\t\t\t\t\td={solidStrokePath}\n\t\t\t\t\tstrokeLinecap=\"round\"\n\t\t\t\t\tfill={isDot ? strokeColor : 'none'}\n\t\t\t\t\tstroke={strokeColor}\n\t\t\t\t\tstrokeWidth={sw}\n\t\t\t\t\tstrokeDasharray={isDot ? 'none' : getDrawShapeStrokeDashArray(shape, sw, dotAdjustment)}\n\t\t\t\t\tstrokeDashoffset=\"0\"\n\t\t\t\t/>\n\t\t\t)}\n\t\t</>\n\t)\n}\n"],
5
+ "mappings": "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",
6
6
  "names": []
7
7
  }
@@ -14,8 +14,10 @@ class PointingHandle extends StateNode {
14
14
  static id = "pointing_handle";
15
15
  didCtrlOnEnter = false;
16
16
  info = {};
17
+ isDoubleClick = false;
17
18
  onEnter(info) {
18
19
  this.info = info;
20
+ this.isDoubleClick = false;
19
21
  this.didCtrlOnEnter = info.accelKey;
20
22
  const { shape } = info;
21
23
  if (this.editor.isShapeOfType(shape, "arrow")) {
@@ -42,6 +44,16 @@ class PointingHandle extends StateNode {
42
44
  }
43
45
  onPointerUp() {
44
46
  const { shape, handle } = this.info;
47
+ if (this.isDoubleClick) {
48
+ this.parent.transition("idle");
49
+ this.parent.getCurrent()?.handleEvent({
50
+ ...this.info,
51
+ type: "click",
52
+ name: "double_click",
53
+ phase: "down"
54
+ });
55
+ return;
56
+ }
45
57
  if (this.editor.isShapeOfType(shape, "note")) {
46
58
  const { editor } = this;
47
59
  const nextNote = getNoteForAdjacentPosition(editor, shape, handle, false);
@@ -56,8 +68,7 @@ class PointingHandle extends StateNode {
56
68
  if (this.editor.inputs.getShiftKey() || info.phase !== "down" || info.ctrlKey || info.shiftKey) {
57
69
  return;
58
70
  }
59
- this.parent.transition("idle");
60
- this.parent.getCurrent()?.handleEvent(info);
71
+ this.isDoubleClick = true;
61
72
  }
62
73
  onPointerMove(info) {
63
74
  const { editor } = this;
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../../src/lib/tools/SelectTool/childStates/PointingHandle.ts"],
4
- "sourcesContent": ["import {\n\tEditor,\n\tStateNode,\n\tTLClickEventInfo,\n\tTLHandle,\n\tTLNoteShape,\n\tTLPointerEventInfo,\n\tVec,\n} from '@tldraw/editor'\nimport { updateArrowTargetState } from '../../../shapes/arrow/arrowTargetState'\nimport { getArrowBindings } from '../../../shapes/arrow/shared'\nimport {\n\tgetNoteAdjacentPositions,\n\tgetNoteShapeForAdjacentPosition,\n} from '../../../shapes/note/noteHelpers'\nimport type { NoteShapeUtil } from '../../../shapes/note/NoteShapeUtil'\nimport { getDisplayValues } from '../../../shapes/shared/getDisplayValues'\nimport { startEditingShapeWithRichText } from '../selectHelpers'\n\nexport class PointingHandle extends StateNode {\n\tstatic override id = 'pointing_handle'\n\n\tdidCtrlOnEnter = false\n\n\tinfo = {} as TLPointerEventInfo & { target: 'handle' }\n\n\toverride onEnter(info: TLPointerEventInfo & { target: 'handle' }) {\n\t\tthis.info = info\n\n\t\tthis.didCtrlOnEnter = info.accelKey\n\n\t\tconst { shape } = info\n\t\tif (this.editor.isShapeOfType(shape, 'arrow')) {\n\t\t\tconst initialBindings = getArrowBindings(this.editor, shape)\n\t\t\tconst currentBinding = initialBindings[info.handle.id as 'start' | 'end']\n\t\t\tconst oppositeBinding = initialBindings[info.handle.id === 'start' ? 'end' : 'start']\n\t\t\tconst arrowTransform = this.editor.getShapePageTransform(shape.id)!\n\n\t\t\tif (currentBinding) {\n\t\t\t\tupdateArrowTargetState({\n\t\t\t\t\teditor: this.editor,\n\t\t\t\t\tpointInPageSpace: arrowTransform.applyToPoint(info.handle),\n\t\t\t\t\tarrow: shape,\n\t\t\t\t\tisPrecise: currentBinding.props.isPrecise,\n\t\t\t\t\tcurrentBinding: currentBinding,\n\t\t\t\t\toppositeBinding: oppositeBinding,\n\t\t\t\t})\n\t\t\t}\n\t\t}\n\n\t\tthis.editor.setCursor({ type: 'grabbing', rotation: 0 })\n\t}\n\n\toverride onExit() {\n\t\tthis.editor.setHintingShapes([])\n\t\tthis.editor.setCursor({ type: 'default', rotation: 0 })\n\t}\n\n\toverride onPointerUp() {\n\t\tconst { shape, handle } = this.info\n\n\t\tif (this.editor.isShapeOfType(shape, 'note')) {\n\t\t\tconst { editor } = this\n\t\t\tconst nextNote = getNoteForAdjacentPosition(editor, shape, handle, false)\n\t\t\tif (nextNote) {\n\t\t\t\tstartEditingShapeWithRichText(editor, nextNote, { selectAll: true })\n\t\t\t\treturn\n\t\t\t}\n\t\t}\n\n\t\tthis.parent.transition('idle', this.info)\n\t}\n\n\toverride onDoubleClick(info: TLClickEventInfo) {\n\t\tif (\n\t\t\tthis.editor.inputs.getShiftKey() ||\n\t\t\tinfo.phase !== 'down' ||\n\t\t\tinfo.ctrlKey ||\n\t\t\tinfo.shiftKey\n\t\t) {\n\t\t\treturn\n\t\t}\n\n\t\tthis.parent.transition('idle')\n\t\tthis.parent.getCurrent()?.handleEvent(info)\n\t}\n\n\toverride onPointerMove(info: TLPointerEventInfo) {\n\t\tconst { editor } = this\n\t\tif (editor.inputs.getIsDragging()) {\n\t\t\tif (this.didCtrlOnEnter) {\n\t\t\t\tthis.parent.transition('brushing', info)\n\t\t\t} else {\n\t\t\t\tthis.startDraggingHandle()\n\t\t\t}\n\t\t}\n\t}\n\n\toverride onLongPress() {\n\t\tthis.startDraggingHandle()\n\t}\n\n\tprivate startDraggingHandle() {\n\t\tconst { editor } = this\n\t\tif (editor.getIsReadonly()) return\n\t\tconst { shape, handle } = this.info\n\n\t\tif (editor.isShapeOfType(shape, 'note')) {\n\t\t\tconst noteUtil = editor.getShapeUtil(shape) as NoteShapeUtil\n\t\t\tconst dv = getDisplayValues(noteUtil, shape)\n\n\t\t\tconst nextNote = getNoteForAdjacentPosition(editor, shape, handle, true)\n\t\t\tif (nextNote) {\n\t\t\t\t// Center the shape on the current pointer\n\t\t\t\tconst centeredOnPointer = editor\n\t\t\t\t\t.getPointInParentSpace(nextNote, editor.inputs.getOriginPagePoint())\n\t\t\t\t\t.sub(\n\t\t\t\t\t\tVec.Rot(\n\t\t\t\t\t\t\tnew Vec(dv.noteWidth / 2, dv.noteHeight / 2).mul(shape.props.scale),\n\t\t\t\t\t\t\tnextNote.rotation\n\t\t\t\t\t\t)\n\t\t\t\t\t)\n\t\t\t\teditor.updateShape({ ...nextNote, x: centeredOnPointer.x, y: centeredOnPointer.y })\n\n\t\t\t\t// Then select and begin translating the shape\n\t\t\t\teditor\n\t\t\t\t\t.setHoveredShape(nextNote.id) // important!\n\t\t\t\t\t.select(nextNote.id)\n\t\t\t\t\t.setCurrentTool('select.translating', {\n\t\t\t\t\t\t...this.info,\n\t\t\t\t\t\ttarget: 'shape',\n\t\t\t\t\t\tshape: editor.getShape(nextNote),\n\t\t\t\t\t\tonInteractionEnd: 'note',\n\t\t\t\t\t\tisCreating: true,\n\t\t\t\t\t\tonCreate: () => {\n\t\t\t\t\t\t\t// When we're done, start editing it\n\t\t\t\t\t\t\tstartEditingShapeWithRichText(editor, nextNote, { selectAll: true })\n\t\t\t\t\t\t},\n\t\t\t\t\t})\n\t\t\t\treturn\n\t\t\t}\n\t\t}\n\n\t\tthis.parent.transition('dragging_handle', this.info)\n\t}\n\n\toverride onCancel() {\n\t\tthis.cancel()\n\t}\n\n\toverride onComplete() {\n\t\tthis.cancel()\n\t}\n\n\toverride onInterrupt() {\n\t\tthis.cancel()\n\t}\n\n\tprivate cancel() {\n\t\tthis.parent.transition('idle')\n\t}\n}\n\nfunction getNoteForAdjacentPosition(\n\teditor: Editor,\n\tshape: TLNoteShape,\n\thandle: TLHandle,\n\tforceNew: boolean\n) {\n\tconst noteUtil = editor.getShapeUtil(shape) as NoteShapeUtil\n\tconst dv = getDisplayValues(noteUtil, shape)\n\n\tconst pageTransform = editor.getShapePageTransform(shape.id)!\n\tconst pagePoint = pageTransform.point()\n\tconst pageRotation = pageTransform.rotation()\n\tconst positions = getNoteAdjacentPositions(editor, {\n\t\tpagePoint,\n\t\tpageRotation,\n\t\tgrowY: shape.props.growY * shape.props.scale,\n\t\textraHeight: 0,\n\t\tscale: shape.props.scale,\n\t\tnoteWidth: dv.noteWidth,\n\t\tnoteHeight: dv.noteHeight,\n\t})\n\tconst position = positions[handle.index]\n\tif (position) {\n\t\treturn getNoteShapeForAdjacentPosition(editor, {\n\t\t\tshape,\n\t\t\tcenter: position,\n\t\t\tpageRotation,\n\t\t\tnoteWidth: dv.noteWidth,\n\t\t\tnoteHeight: dv.noteHeight,\n\t\t\tforceNew,\n\t\t})\n\t}\n\treturn undefined\n}\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["import {\n\tEditor,\n\tStateNode,\n\tTLClickEventInfo,\n\tTLHandle,\n\tTLNoteShape,\n\tTLPointerEventInfo,\n\tVec,\n} from '@tldraw/editor'\nimport { updateArrowTargetState } from '../../../shapes/arrow/arrowTargetState'\nimport { getArrowBindings } from '../../../shapes/arrow/shared'\nimport {\n\tgetNoteAdjacentPositions,\n\tgetNoteShapeForAdjacentPosition,\n} from '../../../shapes/note/noteHelpers'\nimport type { NoteShapeUtil } from '../../../shapes/note/NoteShapeUtil'\nimport { getDisplayValues } from '../../../shapes/shared/getDisplayValues'\nimport { startEditingShapeWithRichText } from '../selectHelpers'\n\nexport class PointingHandle extends StateNode {\n\tstatic override id = 'pointing_handle'\n\n\tdidCtrlOnEnter = false\n\n\tinfo = {} as TLPointerEventInfo & { target: 'handle' }\n\tisDoubleClick = false\n\n\toverride onEnter(info: TLPointerEventInfo & { target: 'handle' }) {\n\t\tthis.info = info\n\t\tthis.isDoubleClick = false\n\n\t\tthis.didCtrlOnEnter = info.accelKey\n\n\t\tconst { shape } = info\n\t\tif (this.editor.isShapeOfType(shape, 'arrow')) {\n\t\t\tconst initialBindings = getArrowBindings(this.editor, shape)\n\t\t\tconst currentBinding = initialBindings[info.handle.id as 'start' | 'end']\n\t\t\tconst oppositeBinding = initialBindings[info.handle.id === 'start' ? 'end' : 'start']\n\t\t\tconst arrowTransform = this.editor.getShapePageTransform(shape.id)!\n\n\t\t\tif (currentBinding) {\n\t\t\t\tupdateArrowTargetState({\n\t\t\t\t\teditor: this.editor,\n\t\t\t\t\tpointInPageSpace: arrowTransform.applyToPoint(info.handle),\n\t\t\t\t\tarrow: shape,\n\t\t\t\t\tisPrecise: currentBinding.props.isPrecise,\n\t\t\t\t\tcurrentBinding: currentBinding,\n\t\t\t\t\toppositeBinding: oppositeBinding,\n\t\t\t\t})\n\t\t\t}\n\t\t}\n\n\t\tthis.editor.setCursor({ type: 'grabbing', rotation: 0 })\n\t}\n\n\toverride onExit() {\n\t\tthis.editor.setHintingShapes([])\n\t\tthis.editor.setCursor({ type: 'default', rotation: 0 })\n\t}\n\n\toverride onPointerUp() {\n\t\tconst { shape, handle } = this.info\n\n\t\tif (this.isDoubleClick) {\n\t\t\tthis.parent.transition('idle')\n\t\t\tthis.parent.getCurrent()?.handleEvent({\n\t\t\t\t...this.info,\n\t\t\t\ttype: 'click',\n\t\t\t\tname: 'double_click',\n\t\t\t\tphase: 'down',\n\t\t\t})\n\t\t\treturn\n\t\t}\n\n\t\tif (this.editor.isShapeOfType(shape, 'note')) {\n\t\t\tconst { editor } = this\n\t\t\tconst nextNote = getNoteForAdjacentPosition(editor, shape, handle, false)\n\t\t\tif (nextNote) {\n\t\t\t\tstartEditingShapeWithRichText(editor, nextNote, { selectAll: true })\n\t\t\t\treturn\n\t\t\t}\n\t\t}\n\n\t\tthis.parent.transition('idle', this.info)\n\t}\n\n\toverride onDoubleClick(info: TLClickEventInfo) {\n\t\tif (\n\t\t\tthis.editor.inputs.getShiftKey() ||\n\t\t\tinfo.phase !== 'down' ||\n\t\t\tinfo.ctrlKey ||\n\t\t\tinfo.shiftKey\n\t\t) {\n\t\t\treturn\n\t\t}\n\n\t\tthis.isDoubleClick = true\n\t}\n\n\toverride onPointerMove(info: TLPointerEventInfo) {\n\t\tconst { editor } = this\n\t\tif (editor.inputs.getIsDragging()) {\n\t\t\tif (this.didCtrlOnEnter) {\n\t\t\t\tthis.parent.transition('brushing', info)\n\t\t\t} else {\n\t\t\t\tthis.startDraggingHandle()\n\t\t\t}\n\t\t}\n\t}\n\n\toverride onLongPress() {\n\t\tthis.startDraggingHandle()\n\t}\n\n\tprivate startDraggingHandle() {\n\t\tconst { editor } = this\n\t\tif (editor.getIsReadonly()) return\n\t\tconst { shape, handle } = this.info\n\n\t\tif (editor.isShapeOfType(shape, 'note')) {\n\t\t\tconst noteUtil = editor.getShapeUtil(shape) as NoteShapeUtil\n\t\t\tconst dv = getDisplayValues(noteUtil, shape)\n\n\t\t\tconst nextNote = getNoteForAdjacentPosition(editor, shape, handle, true)\n\t\t\tif (nextNote) {\n\t\t\t\t// Center the shape on the current pointer\n\t\t\t\tconst centeredOnPointer = editor\n\t\t\t\t\t.getPointInParentSpace(nextNote, editor.inputs.getOriginPagePoint())\n\t\t\t\t\t.sub(\n\t\t\t\t\t\tVec.Rot(\n\t\t\t\t\t\t\tnew Vec(dv.noteWidth / 2, dv.noteHeight / 2).mul(shape.props.scale),\n\t\t\t\t\t\t\tnextNote.rotation\n\t\t\t\t\t\t)\n\t\t\t\t\t)\n\t\t\t\teditor.updateShape({ ...nextNote, x: centeredOnPointer.x, y: centeredOnPointer.y })\n\n\t\t\t\t// Then select and begin translating the shape\n\t\t\t\teditor\n\t\t\t\t\t.setHoveredShape(nextNote.id) // important!\n\t\t\t\t\t.select(nextNote.id)\n\t\t\t\t\t.setCurrentTool('select.translating', {\n\t\t\t\t\t\t...this.info,\n\t\t\t\t\t\ttarget: 'shape',\n\t\t\t\t\t\tshape: editor.getShape(nextNote),\n\t\t\t\t\t\tonInteractionEnd: 'note',\n\t\t\t\t\t\tisCreating: true,\n\t\t\t\t\t\tonCreate: () => {\n\t\t\t\t\t\t\t// When we're done, start editing it\n\t\t\t\t\t\t\tstartEditingShapeWithRichText(editor, nextNote, { selectAll: true })\n\t\t\t\t\t\t},\n\t\t\t\t\t})\n\t\t\t\treturn\n\t\t\t}\n\t\t}\n\n\t\tthis.parent.transition('dragging_handle', this.info)\n\t}\n\n\toverride onCancel() {\n\t\tthis.cancel()\n\t}\n\n\toverride onComplete() {\n\t\tthis.cancel()\n\t}\n\n\toverride onInterrupt() {\n\t\tthis.cancel()\n\t}\n\n\tprivate cancel() {\n\t\tthis.parent.transition('idle')\n\t}\n}\n\nfunction getNoteForAdjacentPosition(\n\teditor: Editor,\n\tshape: TLNoteShape,\n\thandle: TLHandle,\n\tforceNew: boolean\n) {\n\tconst noteUtil = editor.getShapeUtil(shape) as NoteShapeUtil\n\tconst dv = getDisplayValues(noteUtil, shape)\n\n\tconst pageTransform = editor.getShapePageTransform(shape.id)!\n\tconst pagePoint = pageTransform.point()\n\tconst pageRotation = pageTransform.rotation()\n\tconst positions = getNoteAdjacentPositions(editor, {\n\t\tpagePoint,\n\t\tpageRotation,\n\t\tgrowY: shape.props.growY * shape.props.scale,\n\t\textraHeight: 0,\n\t\tscale: shape.props.scale,\n\t\tnoteWidth: dv.noteWidth,\n\t\tnoteHeight: dv.noteHeight,\n\t})\n\tconst position = positions[handle.index]\n\tif (position) {\n\t\treturn getNoteShapeForAdjacentPosition(editor, {\n\t\t\tshape,\n\t\t\tcenter: position,\n\t\t\tpageRotation,\n\t\t\tnoteWidth: dv.noteWidth,\n\t\t\tnoteHeight: dv.noteHeight,\n\t\t\tforceNew,\n\t\t})\n\t}\n\treturn undefined\n}\n"],
5
+ "mappings": "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",
6
6
  "names": []
7
7
  }
@@ -1,8 +1,8 @@
1
- const version = "5.2.2";
1
+ const version = "5.2.4";
2
2
  const publishDates = {
3
3
  major: "2026-05-06T16:28:18.473Z",
4
4
  minor: "2026-07-01T09:20:01.735Z",
5
- patch: "2026-07-02T09:30:17.167Z"
5
+ patch: "2026-07-09T17:45:01.425Z"
6
6
  };
7
7
  export {
8
8
  publishDates,
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../src/lib/ui/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 = '5.2.2'\nexport const publishDates = {\n\tmajor: '2026-05-06T16:28:18.473Z',\n\tminor: '2026-07-01T09:20:01.735Z',\n\tpatch: '2026-07-02T09:30:17.167Z',\n}\n"],
4
+ "sourcesContent": ["// This file is automatically generated by internal/scripts/refresh-assets.ts.\n// Do not edit manually. Or do, I'm a comment, not a cop.\n\nexport const version = '5.2.4'\nexport const publishDates = {\n\tmajor: '2026-05-06T16:28:18.473Z',\n\tminor: '2026-07-01T09:20:01.735Z',\n\tpatch: '2026-07-09T17:45:01.425Z',\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/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "tldraw",
3
3
  "description": "A tiny little drawing editor.",
4
- "version": "5.2.2",
4
+ "version": "5.2.4",
5
5
  "author": {
6
6
  "name": "tldraw Inc.",
7
7
  "email": "hello@tldraw.com"
@@ -63,9 +63,9 @@
63
63
  "@tiptap/pm": "^3.12.1",
64
64
  "@tiptap/react": "^3.12.1",
65
65
  "@tiptap/starter-kit": "^3.12.1",
66
- "@tldraw/driver": "5.2.2",
67
- "@tldraw/editor": "5.2.2",
68
- "@tldraw/store": "5.2.2",
66
+ "@tldraw/driver": "5.2.4",
67
+ "@tldraw/editor": "5.2.4",
68
+ "@tldraw/store": "5.2.4",
69
69
  "classnames": "^2.5.1",
70
70
  "idb": "^7.1.1",
71
71
  "lz-string": "^1.5.0",
@@ -22,6 +22,7 @@ const ids = {
22
22
  box1: createShapeId('box1'),
23
23
  box2: createShapeId('box2'),
24
24
  box3: createShapeId('box3'),
25
+ arrow1: createShapeId('arrow1'),
25
26
  }
26
27
 
27
28
  function bindings(id: TLShapeId) {
@@ -136,6 +137,72 @@ describe('When dragging the arrow', () => {
136
137
  })
137
138
  })
138
139
 
140
+ describe('When double-clicking an arrow handle', () => {
141
+ function createArrow() {
142
+ editor.selectAll().deleteShapes(editor.getSelectedShapeIds())
143
+ editor.createShapes([
144
+ {
145
+ id: ids.arrow1,
146
+ type: 'arrow',
147
+ x: 0,
148
+ y: 0,
149
+ props: {
150
+ start: { x: 0, y: 0 },
151
+ end: { x: 100, y: 100 },
152
+ arrowheadEnd: 'arrow',
153
+ },
154
+ },
155
+ ])
156
+ editor.select(ids.arrow1)
157
+ return editor.getShape(ids.arrow1) as TLArrowShape
158
+ }
159
+
160
+ function getEndHandle() {
161
+ return { id: 'end', type: 'vertex' as const, index: 'a0' as IndexKey, x: 100, y: 100 }
162
+ }
163
+
164
+ function getEndHandleInfo() {
165
+ return {
166
+ target: 'handle' as const,
167
+ shape: editor.getShape(ids.arrow1) as TLArrowShape,
168
+ handle: getEndHandle(),
169
+ }
170
+ }
171
+
172
+ beforeEach(() => {
173
+ editor._transformPointerDownSpy.mockRestore()
174
+ editor._transformPointerUpSpy.mockRestore()
175
+ })
176
+
177
+ it('toggles the arrowhead on the second pointer up', () => {
178
+ createArrow()
179
+
180
+ editor.pointerDown(100, 100, getEndHandleInfo()).pointerUp(100, 100, getEndHandleInfo())
181
+ expect((editor.getShape(ids.arrow1) as TLArrowShape).props.arrowheadEnd).toBe('arrow')
182
+
183
+ editor.pointerDown(100, 100, getEndHandleInfo())
184
+ expect((editor.getShape(ids.arrow1) as TLArrowShape).props.arrowheadEnd).toBe('arrow')
185
+ editor.expectToBeIn('select.pointing_handle')
186
+
187
+ editor.pointerUp(100, 100, getEndHandleInfo())
188
+ expect((editor.getShape(ids.arrow1) as TLArrowShape).props.arrowheadEnd).toBe('none')
189
+ })
190
+
191
+ it('starts a drag instead of toggling when the second click moves', () => {
192
+ createArrow()
193
+
194
+ editor.pointerDown(100, 100, getEndHandleInfo()).pointerUp(100, 100, getEndHandleInfo())
195
+
196
+ editor.pointerDown(100, 100, getEndHandleInfo())
197
+ expect((editor.getShape(ids.arrow1) as TLArrowShape).props.arrowheadEnd).toBe('arrow')
198
+
199
+ editor.pointerMove(140, 140)
200
+
201
+ editor.expectToBeIn('select.dragging_handle')
202
+ expect((editor.getShape(ids.arrow1) as TLArrowShape).props.arrowheadEnd).toBe('arrow')
203
+ })
204
+ })
205
+
139
206
  describe('When pointing a start shape', () => {
140
207
  it('binds to the top shape', () => {
141
208
  editor.setCurrentTool('arrow').pointerDown(375, 375)
@@ -364,11 +364,11 @@ function DrawShapeSvg({
364
364
 
365
365
  const strokePoints = getStrokePoints(allPointsFromSegments, options)
366
366
  const isDot = strokePoints.length < 2
367
+ const fill = isDot || shape.props.isClosed ? shape.props.fill : 'none'
368
+
367
369
  const solidStrokePath = isDot
368
370
  ? getDot(allPointsFromSegments[0], 0)
369
- : getSvgPathFromStrokePoints(strokePoints, shape.props.isClosed)
370
-
371
- const fill = isDot || shape.props.isClosed ? shape.props.fill : 'none'
371
+ : getSvgPathFromStrokePoints(strokePoints, shape.props.isClosed && fill !== 'none')
372
372
 
373
373
  return (
374
374
  <>
@@ -23,9 +23,11 @@ export class PointingHandle extends StateNode {
23
23
  didCtrlOnEnter = false
24
24
 
25
25
  info = {} as TLPointerEventInfo & { target: 'handle' }
26
+ isDoubleClick = false
26
27
 
27
28
  override onEnter(info: TLPointerEventInfo & { target: 'handle' }) {
28
29
  this.info = info
30
+ this.isDoubleClick = false
29
31
 
30
32
  this.didCtrlOnEnter = info.accelKey
31
33
 
@@ -59,6 +61,17 @@ export class PointingHandle extends StateNode {
59
61
  override onPointerUp() {
60
62
  const { shape, handle } = this.info
61
63
 
64
+ if (this.isDoubleClick) {
65
+ this.parent.transition('idle')
66
+ this.parent.getCurrent()?.handleEvent({
67
+ ...this.info,
68
+ type: 'click',
69
+ name: 'double_click',
70
+ phase: 'down',
71
+ })
72
+ return
73
+ }
74
+
62
75
  if (this.editor.isShapeOfType(shape, 'note')) {
63
76
  const { editor } = this
64
77
  const nextNote = getNoteForAdjacentPosition(editor, shape, handle, false)
@@ -81,8 +94,7 @@ export class PointingHandle extends StateNode {
81
94
  return
82
95
  }
83
96
 
84
- this.parent.transition('idle')
85
- this.parent.getCurrent()?.handleEvent(info)
97
+ this.isDoubleClick = true
86
98
  }
87
99
 
88
100
  override onPointerMove(info: TLPointerEventInfo) {
@@ -1,9 +1,9 @@
1
1
  // This file is automatically generated by internal/scripts/refresh-assets.ts.
2
2
  // Do not edit manually. Or do, I'm a comment, not a cop.
3
3
 
4
- export const version = '5.2.2'
4
+ export const version = '5.2.4'
5
5
  export const publishDates = {
6
6
  major: '2026-05-06T16:28:18.473Z',
7
7
  minor: '2026-07-01T09:20:01.735Z',
8
- patch: '2026-07-02T09:30:17.167Z',
8
+ patch: '2026-07-09T17:45:01.425Z',
9
9
  }