@tldraw/editor 3.12.0-canary.21002dc7ca29 → 3.12.0-canary.2ec6dfe495a2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (85) hide show
  1. package/dist-cjs/index.d.ts +154 -17
  2. package/dist-cjs/index.js +3 -1
  3. package/dist-cjs/index.js.map +2 -2
  4. package/dist-cjs/lib/TldrawEditor.js +4 -0
  5. package/dist-cjs/lib/TldrawEditor.js.map +2 -2
  6. package/dist-cjs/lib/components/GeometryDebuggingView.js +2 -2
  7. package/dist-cjs/lib/components/GeometryDebuggingView.js.map +2 -2
  8. package/dist-cjs/lib/editor/Editor.js +208 -18
  9. package/dist-cjs/lib/editor/Editor.js.map +2 -2
  10. package/dist-cjs/lib/editor/shapes/ShapeUtil.js +9 -0
  11. package/dist-cjs/lib/editor/shapes/ShapeUtil.js.map +2 -2
  12. package/dist-cjs/lib/editor/shapes/group/GroupShapeUtil.js +4 -13
  13. package/dist-cjs/lib/editor/shapes/group/GroupShapeUtil.js.map +2 -2
  14. package/dist-cjs/lib/editor/types/selection-types.js.map +1 -1
  15. package/dist-cjs/lib/exports/StyleEmbedder.js +19 -5
  16. package/dist-cjs/lib/exports/StyleEmbedder.js.map +2 -2
  17. package/dist-cjs/lib/exports/cssRules.js +127 -0
  18. package/dist-cjs/lib/exports/cssRules.js.map +7 -0
  19. package/dist-cjs/lib/exports/parseCss.js +0 -69
  20. package/dist-cjs/lib/exports/parseCss.js.map +2 -2
  21. package/dist-cjs/lib/hooks/useDocumentEvents.js +16 -0
  22. package/dist-cjs/lib/hooks/useDocumentEvents.js.map +2 -2
  23. package/dist-cjs/lib/license/Watermark.js +2 -0
  24. package/dist-cjs/lib/license/Watermark.js.map +2 -2
  25. package/dist-cjs/lib/primitives/geometry/Geometry2d.js +133 -16
  26. package/dist-cjs/lib/primitives/geometry/Geometry2d.js.map +3 -3
  27. package/dist-cjs/lib/primitives/geometry/Group2d.js +54 -11
  28. package/dist-cjs/lib/primitives/geometry/Group2d.js.map +2 -2
  29. package/dist-cjs/lib/primitives/intersect.js +20 -0
  30. package/dist-cjs/lib/primitives/intersect.js.map +2 -2
  31. package/dist-cjs/lib/utils/reorderShapes.js +2 -8
  32. package/dist-cjs/lib/utils/reorderShapes.js.map +2 -2
  33. package/dist-cjs/version.js +3 -3
  34. package/dist-cjs/version.js.map +1 -1
  35. package/dist-esm/index.d.mts +154 -17
  36. package/dist-esm/index.mjs +8 -2
  37. package/dist-esm/index.mjs.map +2 -2
  38. package/dist-esm/lib/TldrawEditor.mjs +4 -0
  39. package/dist-esm/lib/TldrawEditor.mjs.map +2 -2
  40. package/dist-esm/lib/components/GeometryDebuggingView.mjs +3 -3
  41. package/dist-esm/lib/components/GeometryDebuggingView.mjs.map +2 -2
  42. package/dist-esm/lib/editor/Editor.mjs +209 -18
  43. package/dist-esm/lib/editor/Editor.mjs.map +2 -2
  44. package/dist-esm/lib/editor/shapes/ShapeUtil.mjs +9 -0
  45. package/dist-esm/lib/editor/shapes/ShapeUtil.mjs.map +2 -2
  46. package/dist-esm/lib/editor/shapes/group/GroupShapeUtil.mjs +4 -13
  47. package/dist-esm/lib/editor/shapes/group/GroupShapeUtil.mjs.map +2 -2
  48. package/dist-esm/lib/exports/StyleEmbedder.mjs +21 -12
  49. package/dist-esm/lib/exports/StyleEmbedder.mjs.map +2 -2
  50. package/dist-esm/lib/exports/cssRules.mjs +107 -0
  51. package/dist-esm/lib/exports/cssRules.mjs.map +7 -0
  52. package/dist-esm/lib/exports/parseCss.mjs +0 -69
  53. package/dist-esm/lib/exports/parseCss.mjs.map +2 -2
  54. package/dist-esm/lib/hooks/useDocumentEvents.mjs +16 -0
  55. package/dist-esm/lib/hooks/useDocumentEvents.mjs.map +2 -2
  56. package/dist-esm/lib/license/Watermark.mjs +2 -0
  57. package/dist-esm/lib/license/Watermark.mjs.map +2 -2
  58. package/dist-esm/lib/primitives/geometry/Geometry2d.mjs +137 -14
  59. package/dist-esm/lib/primitives/geometry/Geometry2d.mjs.map +2 -2
  60. package/dist-esm/lib/primitives/geometry/Group2d.mjs +55 -12
  61. package/dist-esm/lib/primitives/geometry/Group2d.mjs.map +2 -2
  62. package/dist-esm/lib/primitives/intersect.mjs +20 -0
  63. package/dist-esm/lib/primitives/intersect.mjs.map +2 -2
  64. package/dist-esm/lib/utils/reorderShapes.mjs +2 -8
  65. package/dist-esm/lib/utils/reorderShapes.mjs.map +2 -2
  66. package/dist-esm/version.mjs +3 -3
  67. package/dist-esm/version.mjs.map +1 -1
  68. package/package.json +7 -7
  69. package/src/index.ts +11 -2
  70. package/src/lib/TldrawEditor.tsx +29 -3
  71. package/src/lib/components/GeometryDebuggingView.tsx +3 -3
  72. package/src/lib/editor/Editor.ts +315 -24
  73. package/src/lib/editor/shapes/ShapeUtil.ts +10 -0
  74. package/src/lib/editor/shapes/group/GroupShapeUtil.tsx +7 -15
  75. package/src/lib/editor/types/selection-types.ts +3 -0
  76. package/src/lib/exports/StyleEmbedder.ts +25 -15
  77. package/src/lib/exports/cssRules.ts +126 -0
  78. package/src/lib/exports/parseCss.ts +0 -79
  79. package/src/lib/hooks/useDocumentEvents.ts +18 -0
  80. package/src/lib/license/Watermark.tsx +2 -0
  81. package/src/lib/primitives/geometry/Geometry2d.ts +196 -16
  82. package/src/lib/primitives/geometry/Group2d.ts +76 -13
  83. package/src/lib/primitives/intersect.ts +41 -0
  84. package/src/lib/utils/reorderShapes.ts +2 -9
  85. package/src/version.ts +3 -3
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../src/lib/components/GeometryDebuggingView.tsx"],
4
- "sourcesContent": ["import { track } from '@tldraw/state-react'\nimport { modulate } from '@tldraw/utils'\nimport { useEffect, useState } from 'react'\nimport { useEditor } from '../hooks/useEditor'\nimport { Geometry2d } from '../primitives/geometry/Geometry2d'\nimport { Group2d } from '../primitives/geometry/Group2d'\n\nfunction useTick(isEnabled = true) {\n\tconst [_, setTick] = useState(0)\n\tconst editor = useEditor()\n\tuseEffect(() => {\n\t\tif (!isEnabled) return\n\t\tconst update = () => setTick((tick) => tick + 1)\n\t\teditor.on('tick', update)\n\t\treturn () => {\n\t\t\teditor.off('tick', update)\n\t\t}\n\t}, [editor, isEnabled])\n}\n\nexport const GeometryDebuggingView = track(function GeometryDebuggingView({\n\tshowStroke = true,\n\tshowVertices = true,\n\tshowClosestPointOnOutline = true,\n}: {\n\tshowStroke?: boolean\n\tshowVertices?: boolean\n\tshowClosestPointOnOutline?: boolean\n}) {\n\tconst editor = useEditor()\n\n\tuseTick(showClosestPointOnOutline)\n\n\tconst zoomLevel = editor.getZoomLevel()\n\tconst renderingShapes = editor.getRenderingShapes()\n\tconst {\n\t\tinputs: { currentPagePoint },\n\t} = editor\n\n\treturn (\n\t\t<svg\n\t\t\tstyle={{\n\t\t\t\tposition: 'absolute',\n\t\t\t\tpointerEvents: 'none',\n\t\t\t\tzIndex: 999999999,\n\t\t\t\ttop: 0,\n\t\t\t\tleft: 0,\n\t\t\t\toverflow: 'visible',\n\t\t\t}}\n\t\t>\n\t\t\t{renderingShapes.map((result) => {\n\t\t\t\tconst shape = editor.getShape(result.id)!\n\n\t\t\t\tif (shape.type === 'group') return null\n\n\t\t\t\tconst geometry = editor.getShapeGeometry(shape)\n\t\t\t\tconst pageTransform = editor.getShapePageTransform(shape)!\n\n\t\t\t\tconst pointInShapeSpace = editor.getPointInShapeSpace(shape, currentPagePoint)\n\t\t\t\tconst nearestPointOnShape = geometry.nearestPoint(pointInShapeSpace)\n\t\t\t\tconst distanceToPoint = geometry.distanceToPoint(pointInShapeSpace, true)\n\t\t\t\tconst dist = Math.abs(distanceToPoint) * zoomLevel\n\t\t\t\tconst hitInside = distanceToPoint < 0\n\n\t\t\t\tconst { vertices } = geometry\n\n\t\t\t\treturn (\n\t\t\t\t\t<g\n\t\t\t\t\t\tkey={result.id + '_outline'}\n\t\t\t\t\t\ttransform={pageTransform.toCssString()}\n\t\t\t\t\t\tstrokeLinecap=\"round\"\n\t\t\t\t\t\tstrokeLinejoin=\"round\"\n\t\t\t\t\t>\n\t\t\t\t\t\t{showStroke && (\n\t\t\t\t\t\t\t<g\n\t\t\t\t\t\t\t\tstroke={geometry.debugColor ?? 'red'}\n\t\t\t\t\t\t\t\topacity=\"1\"\n\t\t\t\t\t\t\t\tstrokeWidth={2 / zoomLevel}\n\t\t\t\t\t\t\t\tfill=\"none\"\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t<GeometryStroke geometry={geometry} />\n\t\t\t\t\t\t\t</g>\n\t\t\t\t\t\t)}\n\t\t\t\t\t\t{showVertices &&\n\t\t\t\t\t\t\tvertices.map((v, i) => (\n\t\t\t\t\t\t\t\t<circle\n\t\t\t\t\t\t\t\t\tkey={`v${i}`}\n\t\t\t\t\t\t\t\t\tcx={v.x}\n\t\t\t\t\t\t\t\t\tcy={v.y}\n\t\t\t\t\t\t\t\t\tr={2 / zoomLevel}\n\t\t\t\t\t\t\t\t\tfill={`hsl(${modulate(i, [0, vertices.length - 1], [120, 200])}, 100%, 50%)`}\n\t\t\t\t\t\t\t\t\tstroke=\"black\"\n\t\t\t\t\t\t\t\t\tstrokeWidth={1 / zoomLevel}\n\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t))}\n\t\t\t\t\t\t{showClosestPointOnOutline && dist < 150 && (\n\t\t\t\t\t\t\t<line\n\t\t\t\t\t\t\t\tx1={nearestPointOnShape.x}\n\t\t\t\t\t\t\t\ty1={nearestPointOnShape.y}\n\t\t\t\t\t\t\t\tx2={pointInShapeSpace.x}\n\t\t\t\t\t\t\t\ty2={pointInShapeSpace.y}\n\t\t\t\t\t\t\t\topacity={1 - dist / 150}\n\t\t\t\t\t\t\t\tstroke={hitInside ? 'goldenrod' : 'dodgerblue'}\n\t\t\t\t\t\t\t\tstrokeWidth={2 / zoomLevel}\n\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t)}\n\t\t\t\t\t</g>\n\t\t\t\t)\n\t\t\t})}\n\t\t</svg>\n\t)\n})\n\nfunction GeometryStroke({ geometry }: { geometry: Geometry2d }) {\n\tif (geometry instanceof Group2d) {\n\t\treturn (\n\t\t\t<>\n\t\t\t\t{[...geometry.children, ...geometry.ignoredChildren].map((child, i) => (\n\t\t\t\t\t<GeometryStroke geometry={child} key={i} />\n\t\t\t\t))}\n\t\t\t</>\n\t\t)\n\t}\n\n\treturn <path d={geometry.toSimpleSvgPath()} />\n}\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["import { track } from '@tldraw/state-react'\nimport { modulate } from '@tldraw/utils'\nimport { useEffect, useState } from 'react'\nimport { useEditor } from '../hooks/useEditor'\nimport { Geometry2d } from '../primitives/geometry/Geometry2d'\nimport { Group2d } from '../primitives/geometry/Group2d'\n\nfunction useTick(isEnabled = true) {\n\tconst [_, setTick] = useState(0)\n\tconst editor = useEditor()\n\tuseEffect(() => {\n\t\tif (!isEnabled) return\n\t\tconst update = () => setTick((tick) => tick + 1)\n\t\teditor.on('tick', update)\n\t\treturn () => {\n\t\t\teditor.off('tick', update)\n\t\t}\n\t}, [editor, isEnabled])\n}\n\nexport const GeometryDebuggingView = track(function GeometryDebuggingView({\n\tshowStroke = true,\n\tshowVertices = true,\n\tshowClosestPointOnOutline = true,\n}: {\n\tshowStroke?: boolean\n\tshowVertices?: boolean\n\tshowClosestPointOnOutline?: boolean\n}) {\n\tconst editor = useEditor()\n\n\tuseTick(showClosestPointOnOutline)\n\n\tconst zoomLevel = editor.getZoomLevel()\n\tconst renderingShapes = editor.getRenderingShapes()\n\tconst {\n\t\tinputs: { currentPagePoint },\n\t} = editor\n\n\treturn (\n\t\t<svg\n\t\t\tstyle={{\n\t\t\t\tposition: 'absolute',\n\t\t\t\tpointerEvents: 'none',\n\t\t\t\tzIndex: 999999999,\n\t\t\t\ttop: 0,\n\t\t\t\tleft: 0,\n\t\t\t\toverflow: 'visible',\n\t\t\t}}\n\t\t>\n\t\t\t{renderingShapes.map((result) => {\n\t\t\t\tconst shape = editor.getShape(result.id)!\n\n\t\t\t\tif (shape.type === 'group') return null\n\n\t\t\t\tconst geometry = editor.getShapeGeometry(shape)\n\t\t\t\tconst pageTransform = editor.getShapePageTransform(shape)!\n\n\t\t\t\tconst pointInShapeSpace = editor.getPointInShapeSpace(shape, currentPagePoint)\n\t\t\t\tconst nearestPointOnShape = geometry.nearestPoint(pointInShapeSpace)\n\t\t\t\tconst distanceToPoint = geometry.distanceToPoint(pointInShapeSpace, true)\n\t\t\t\tconst dist = Math.abs(distanceToPoint) * zoomLevel\n\t\t\t\tconst hitInside = distanceToPoint < 0\n\n\t\t\t\tconst { vertices } = geometry\n\n\t\t\t\treturn (\n\t\t\t\t\t<g\n\t\t\t\t\t\tkey={result.id + '_outline'}\n\t\t\t\t\t\ttransform={pageTransform.toCssString()}\n\t\t\t\t\t\tstrokeLinecap=\"round\"\n\t\t\t\t\t\tstrokeLinejoin=\"round\"\n\t\t\t\t\t>\n\t\t\t\t\t\t{showStroke && (\n\t\t\t\t\t\t\t<g\n\t\t\t\t\t\t\t\tstroke={geometry.debugColor ?? 'red'}\n\t\t\t\t\t\t\t\topacity=\"1\"\n\t\t\t\t\t\t\t\tstrokeWidth={2 / zoomLevel}\n\t\t\t\t\t\t\t\tfill=\"none\"\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t<GeometryStroke geometry={geometry} />\n\t\t\t\t\t\t\t</g>\n\t\t\t\t\t\t)}\n\t\t\t\t\t\t{showVertices &&\n\t\t\t\t\t\t\tvertices.map((v, i) => (\n\t\t\t\t\t\t\t\t<circle\n\t\t\t\t\t\t\t\t\tkey={`v${i}`}\n\t\t\t\t\t\t\t\t\tcx={v.x}\n\t\t\t\t\t\t\t\t\tcy={v.y}\n\t\t\t\t\t\t\t\t\tr={2 / zoomLevel}\n\t\t\t\t\t\t\t\t\tfill={`hsl(${modulate(i, [0, vertices.length - 1], [120, 200])}, 100%, 50%)`}\n\t\t\t\t\t\t\t\t\tstroke=\"black\"\n\t\t\t\t\t\t\t\t\tstrokeWidth={1 / zoomLevel}\n\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t))}\n\t\t\t\t\t\t{showClosestPointOnOutline && dist < 150 && (\n\t\t\t\t\t\t\t<line\n\t\t\t\t\t\t\t\tx1={nearestPointOnShape.x}\n\t\t\t\t\t\t\t\ty1={nearestPointOnShape.y}\n\t\t\t\t\t\t\t\tx2={pointInShapeSpace.x}\n\t\t\t\t\t\t\t\ty2={pointInShapeSpace.y}\n\t\t\t\t\t\t\t\topacity={1 - dist / 150}\n\t\t\t\t\t\t\t\tstroke={hitInside ? 'goldenrod' : 'dodgerblue'}\n\t\t\t\t\t\t\t\tstrokeWidth={2 / zoomLevel}\n\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t)}\n\t\t\t\t\t</g>\n\t\t\t\t)\n\t\t\t})}\n\t\t</svg>\n\t)\n})\n\nfunction GeometryStroke({ geometry }: { geometry: Geometry2d }) {\n\tif (geometry instanceof Group2d) {\n\t\treturn (\n\t\t\t<g stroke={geometry.debugColor}>\n\t\t\t\t{[...geometry.children, ...geometry.ignoredChildren].map((child, i) => (\n\t\t\t\t\t<GeometryStroke geometry={child} key={i} />\n\t\t\t\t))}\n\t\t\t</g>\n\t\t)\n\t}\n\n\treturn <path d={geometry.toSimpleSvgPath()} stroke={geometry.debugColor} />\n}\n"],
5
+ "mappings": ";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAmEK;AAnEL,yBAAsB;AACtB,mBAAyB;AACzB,mBAAoC;AACpC,uBAA0B;AAE1B,qBAAwB;AAExB,SAAS,QAAQ,YAAY,MAAM;AAClC,QAAM,CAAC,GAAG,OAAO,QAAI,uBAAS,CAAC;AAC/B,QAAM,aAAS,4BAAU;AACzB,8BAAU,MAAM;AACf,QAAI,CAAC,UAAW;AAChB,UAAM,SAAS,MAAM,QAAQ,CAAC,SAAS,OAAO,CAAC;AAC/C,WAAO,GAAG,QAAQ,MAAM;AACxB,WAAO,MAAM;AACZ,aAAO,IAAI,QAAQ,MAAM;AAAA,IAC1B;AAAA,EACD,GAAG,CAAC,QAAQ,SAAS,CAAC;AACvB;AAEO,MAAM,4BAAwB,0BAAM,SAASA,uBAAsB;AAAA,EACzE,aAAa;AAAA,EACb,eAAe;AAAA,EACf,4BAA4B;AAC7B,GAIG;AACF,QAAM,aAAS,4BAAU;AAEzB,UAAQ,yBAAyB;AAEjC,QAAM,YAAY,OAAO,aAAa;AACtC,QAAM,kBAAkB,OAAO,mBAAmB;AAClD,QAAM;AAAA,IACL,QAAQ,EAAE,iBAAiB;AAAA,EAC5B,IAAI;AAEJ,SACC;AAAA,IAAC;AAAA;AAAA,MACA,OAAO;AAAA,QACN,UAAU;AAAA,QACV,eAAe;AAAA,QACf,QAAQ;AAAA,QACR,KAAK;AAAA,QACL,MAAM;AAAA,QACN,UAAU;AAAA,MACX;AAAA,MAEC,0BAAgB,IAAI,CAAC,WAAW;AAChC,cAAM,QAAQ,OAAO,SAAS,OAAO,EAAE;AAEvC,YAAI,MAAM,SAAS,QAAS,QAAO;AAEnC,cAAM,WAAW,OAAO,iBAAiB,KAAK;AAC9C,cAAM,gBAAgB,OAAO,sBAAsB,KAAK;AAExD,cAAM,oBAAoB,OAAO,qBAAqB,OAAO,gBAAgB;AAC7E,cAAM,sBAAsB,SAAS,aAAa,iBAAiB;AACnE,cAAM,kBAAkB,SAAS,gBAAgB,mBAAmB,IAAI;AACxE,cAAM,OAAO,KAAK,IAAI,eAAe,IAAI;AACzC,cAAM,YAAY,kBAAkB;AAEpC,cAAM,EAAE,SAAS,IAAI;AAErB,eACC;AAAA,UAAC;AAAA;AAAA,YAEA,WAAW,cAAc,YAAY;AAAA,YACrC,eAAc;AAAA,YACd,gBAAe;AAAA,YAEd;AAAA,4BACA;AAAA,gBAAC;AAAA;AAAA,kBACA,QAAQ,SAAS,cAAc;AAAA,kBAC/B,SAAQ;AAAA,kBACR,aAAa,IAAI;AAAA,kBACjB,MAAK;AAAA,kBAEL,sDAAC,kBAAe,UAAoB;AAAA;AAAA,cACrC;AAAA,cAEA,gBACA,SAAS,IAAI,CAAC,GAAG,MAChB;AAAA,gBAAC;AAAA;AAAA,kBAEA,IAAI,EAAE;AAAA,kBACN,IAAI,EAAE;AAAA,kBACN,GAAG,IAAI;AAAA,kBACP,MAAM,WAAO,uBAAS,GAAG,CAAC,GAAG,SAAS,SAAS,CAAC,GAAG,CAAC,KAAK,GAAG,CAAC,CAAC;AAAA,kBAC9D,QAAO;AAAA,kBACP,aAAa,IAAI;AAAA;AAAA,gBANZ,IAAI,CAAC;AAAA,cAOX,CACA;AAAA,cACD,6BAA6B,OAAO,OACpC;AAAA,gBAAC;AAAA;AAAA,kBACA,IAAI,oBAAoB;AAAA,kBACxB,IAAI,oBAAoB;AAAA,kBACxB,IAAI,kBAAkB;AAAA,kBACtB,IAAI,kBAAkB;AAAA,kBACtB,SAAS,IAAI,OAAO;AAAA,kBACpB,QAAQ,YAAY,cAAc;AAAA,kBAClC,aAAa,IAAI;AAAA;AAAA,cAClB;AAAA;AAAA;AAAA,UApCI,OAAO,KAAK;AAAA,QAsClB;AAAA,MAEF,CAAC;AAAA;AAAA,EACF;AAEF,CAAC;AAED,SAAS,eAAe,EAAE,SAAS,GAA6B;AAC/D,MAAI,oBAAoB,wBAAS;AAChC,WACC,4CAAC,OAAE,QAAQ,SAAS,YAClB,WAAC,GAAG,SAAS,UAAU,GAAG,SAAS,eAAe,EAAE,IAAI,CAAC,OAAO,MAChE,4CAAC,kBAAe,UAAU,SAAY,CAAG,CACzC,GACF;AAAA,EAEF;AAEA,SAAO,4CAAC,UAAK,GAAG,SAAS,gBAAgB,GAAG,QAAQ,SAAS,YAAY;AAC1E;",
6
6
  "names": ["GeometryDebuggingView"]
7
7
  }
@@ -122,8 +122,8 @@ var import_TextManager = require("./managers/TextManager");
122
122
  var import_TickManager = require("./managers/TickManager");
123
123
  var import_UserPreferencesManager = require("./managers/UserPreferencesManager");
124
124
  var import_RootState = require("./tools/RootState");
125
- var __setMetaKeyTimeout_dec, __setCtrlKeyTimeout_dec, __setAltKeyTimeout_dec, __setShiftKeyTimeout_dec, _getIsReadonly_dec, _getIsFocused_dec, _getSharedOpacity_dec, _getSharedStyles_dec, __getSelectionSharedStyles_dec, __getBindingsIndexCache_dec, _getCurrentPageRenderingShapesSorted_dec, _getCurrentPageShapesSorted_dec, _getCurrentPageShapes_dec, _getCurrentPageBounds_dec, _getCulledShapes_dec, __notVisibleShapes_dec, __getShapeMaskedPageBoundsCache_dec, __getShapeMaskCache_dec, __getShapeClipPathCache_dec, __getShapePageBoundsCache_dec, __getShapePageTransformCache_dec, __getShapeHandlesCache_dec, __getAllAssetsQuery_dec, _getCurrentPageShapeIdsSorted_dec, _getCurrentPageId_dec, _getPages_dec, __getAllPagesQuery_dec, _getRenderingShapes_dec, _getCollaboratorsOnCurrentPage_dec, _getCollaborators_dec, __getCollaboratorsQuery_dec, _getViewportPageBounds_dec, _getViewportScreenCenter_dec, _getViewportScreenBounds_dec, _getZoomLevel_dec, _getCameraForFollowing_dec, _getViewportPageBoundsForFollowing_dec, _getCamera_dec, __unsafe_getCameraId_dec, _getErasingShapes_dec, _getErasingShapeIds_dec, _getHintingShape_dec, _getHintingShapeIds_dec, _getHoveredShape_dec, _getHoveredShapeId_dec, _getRichTextEditor_dec, _getEditingShape_dec, _getEditingShapeId_dec, _getFocusedGroup_dec, _getFocusedGroupId_dec, _getSelectionRotatedScreenBounds_dec, _getSelectionRotatedPageBounds_dec, _getSelectionRotation_dec, _getSelectionPageBounds_dec, _getOnlySelectedShape_dec, _getOnlySelectedShapeId_dec, _getSelectedShapes_dec, _getSelectedShapeIds_dec, __getCurrentPageStateId_dec, _getCurrentPageState_dec, __getPageStatesQuery_dec, _getPageStates_dec, _getIsMenuOpen_dec, _getOpenMenus_dec, _getInstanceState_dec, _getDocumentSettings_dec, _getCurrentToolId_dec, _getCurrentTool_dec, _getPath_dec, _getCanRedo_dec, _getCanUndo_dec, _getIsShapeHiddenCache_dec, _a, _init;
126
- class Editor extends (_a = import_eventemitter3.default, _getIsShapeHiddenCache_dec = [import_state.computed], _getCanUndo_dec = [import_state.computed], _getCanRedo_dec = [import_state.computed], _getPath_dec = [import_state.computed], _getCurrentTool_dec = [import_state.computed], _getCurrentToolId_dec = [import_state.computed], _getDocumentSettings_dec = [import_state.computed], _getInstanceState_dec = [import_state.computed], _getOpenMenus_dec = [import_state.computed], _getIsMenuOpen_dec = [import_state.computed], _getPageStates_dec = [import_state.computed], __getPageStatesQuery_dec = [import_state.computed], _getCurrentPageState_dec = [import_state.computed], __getCurrentPageStateId_dec = [import_state.computed], _getSelectedShapeIds_dec = [import_state.computed], _getSelectedShapes_dec = [import_state.computed], _getOnlySelectedShapeId_dec = [import_state.computed], _getOnlySelectedShape_dec = [import_state.computed], _getSelectionPageBounds_dec = [import_state.computed], _getSelectionRotation_dec = [import_state.computed], _getSelectionRotatedPageBounds_dec = [import_state.computed], _getSelectionRotatedScreenBounds_dec = [import_state.computed], _getFocusedGroupId_dec = [import_state.computed], _getFocusedGroup_dec = [import_state.computed], _getEditingShapeId_dec = [import_state.computed], _getEditingShape_dec = [import_state.computed], _getRichTextEditor_dec = [import_state.computed], _getHoveredShapeId_dec = [import_state.computed], _getHoveredShape_dec = [import_state.computed], _getHintingShapeIds_dec = [import_state.computed], _getHintingShape_dec = [import_state.computed], _getErasingShapeIds_dec = [import_state.computed], _getErasingShapes_dec = [import_state.computed], __unsafe_getCameraId_dec = [import_state.computed], _getCamera_dec = [import_state.computed], _getViewportPageBoundsForFollowing_dec = [import_state.computed], _getCameraForFollowing_dec = [import_state.computed], _getZoomLevel_dec = [import_state.computed], _getViewportScreenBounds_dec = [import_state.computed], _getViewportScreenCenter_dec = [import_state.computed], _getViewportPageBounds_dec = [import_state.computed], __getCollaboratorsQuery_dec = [import_state.computed], _getCollaborators_dec = [import_state.computed], _getCollaboratorsOnCurrentPage_dec = [import_state.computed], _getRenderingShapes_dec = [import_state.computed], __getAllPagesQuery_dec = [import_state.computed], _getPages_dec = [import_state.computed], _getCurrentPageId_dec = [import_state.computed], _getCurrentPageShapeIdsSorted_dec = [import_state.computed], __getAllAssetsQuery_dec = [import_state.computed], __getShapeHandlesCache_dec = [import_state.computed], __getShapePageTransformCache_dec = [import_state.computed], __getShapePageBoundsCache_dec = [import_state.computed], __getShapeClipPathCache_dec = [import_state.computed], __getShapeMaskCache_dec = [import_state.computed], __getShapeMaskedPageBoundsCache_dec = [import_state.computed], __notVisibleShapes_dec = [import_state.computed], _getCulledShapes_dec = [import_state.computed], _getCurrentPageBounds_dec = [import_state.computed], _getCurrentPageShapes_dec = [import_state.computed], _getCurrentPageShapesSorted_dec = [import_state.computed], _getCurrentPageRenderingShapesSorted_dec = [import_state.computed], __getBindingsIndexCache_dec = [import_state.computed], __getSelectionSharedStyles_dec = [import_state.computed], _getSharedStyles_dec = [(0, import_state.computed)({ isEqual: (a, b) => a.equals(b) })], _getSharedOpacity_dec = [import_state.computed], _getIsFocused_dec = [import_state.computed], _getIsReadonly_dec = [import_state.computed], __setShiftKeyTimeout_dec = [import_utils.bind], __setAltKeyTimeout_dec = [import_utils.bind], __setCtrlKeyTimeout_dec = [import_utils.bind], __setMetaKeyTimeout_dec = [import_utils.bind], _a) {
125
+ var __setMetaKeyTimeout_dec, __setCtrlKeyTimeout_dec, __setAltKeyTimeout_dec, __setShiftKeyTimeout_dec, _getIsReadonly_dec, _getIsFocused_dec, _getSharedOpacity_dec, _getSharedStyles_dec, __getSelectionSharedStyles_dec, __getBindingsIndexCache_dec, _getCurrentPageRenderingShapesSorted_dec, _getCurrentPageShapesSorted_dec, _getCurrentPageShapes_dec, _getCurrentPageBounds_dec, _getCulledShapes_dec, __notVisibleShapes_dec, __getShapeMaskedPageBoundsCache_dec, __getShapeMaskCache_dec, __getShapeClipPathCache_dec, __getShapePageBoundsCache_dec, __getShapePageTransformCache_dec, __getShapeHandlesCache_dec, __getAllAssetsQuery_dec, _getCurrentPageShapeIdsSorted_dec, _getCurrentPageId_dec, _getPages_dec, __getAllPagesQuery_dec, _getRenderingShapes_dec, _getCollaboratorsOnCurrentPage_dec, _getCollaborators_dec, __getCollaboratorsQuery_dec, _getViewportPageBounds_dec, _getViewportScreenCenter_dec, _getViewportScreenBounds_dec, _getZoomLevel_dec, _getCameraForFollowing_dec, _getViewportPageBoundsForFollowing_dec, _getCamera_dec, __unsafe_getCameraId_dec, _getErasingShapes_dec, _getErasingShapeIds_dec, _getHintingShape_dec, _getHintingShapeIds_dec, _getHoveredShape_dec, _getHoveredShapeId_dec, _getRichTextEditor_dec, _getEditingShape_dec, _getEditingShapeId_dec, _getFocusedGroup_dec, _getFocusedGroupId_dec, _getSelectionRotatedScreenBounds_dec, _getSelectionRotatedPageBounds_dec, _getSelectionRotation_dec, _getSelectionPageBounds_dec, _getOnlySelectedShape_dec, _getOnlySelectedShapeId_dec, _getCurrentPageShapesInReadingOrder_dec, _getSelectedShapes_dec, _getSelectedShapeIds_dec, __getCurrentPageStateId_dec, _getCurrentPageState_dec, __getPageStatesQuery_dec, _getPageStates_dec, _getIsMenuOpen_dec, _getOpenMenus_dec, _getInstanceState_dec, _getDocumentSettings_dec, _getCurrentToolId_dec, _getCurrentTool_dec, _getPath_dec, _getCanRedo_dec, _getCanUndo_dec, _getIsShapeHiddenCache_dec, _a, _init;
126
+ class Editor extends (_a = import_eventemitter3.default, _getIsShapeHiddenCache_dec = [import_state.computed], _getCanUndo_dec = [import_state.computed], _getCanRedo_dec = [import_state.computed], _getPath_dec = [import_state.computed], _getCurrentTool_dec = [import_state.computed], _getCurrentToolId_dec = [import_state.computed], _getDocumentSettings_dec = [import_state.computed], _getInstanceState_dec = [import_state.computed], _getOpenMenus_dec = [import_state.computed], _getIsMenuOpen_dec = [import_state.computed], _getPageStates_dec = [import_state.computed], __getPageStatesQuery_dec = [import_state.computed], _getCurrentPageState_dec = [import_state.computed], __getCurrentPageStateId_dec = [import_state.computed], _getSelectedShapeIds_dec = [import_state.computed], _getSelectedShapes_dec = [import_state.computed], _getCurrentPageShapesInReadingOrder_dec = [import_state.computed], _getOnlySelectedShapeId_dec = [import_state.computed], _getOnlySelectedShape_dec = [import_state.computed], _getSelectionPageBounds_dec = [import_state.computed], _getSelectionRotation_dec = [import_state.computed], _getSelectionRotatedPageBounds_dec = [import_state.computed], _getSelectionRotatedScreenBounds_dec = [import_state.computed], _getFocusedGroupId_dec = [import_state.computed], _getFocusedGroup_dec = [import_state.computed], _getEditingShapeId_dec = [import_state.computed], _getEditingShape_dec = [import_state.computed], _getRichTextEditor_dec = [import_state.computed], _getHoveredShapeId_dec = [import_state.computed], _getHoveredShape_dec = [import_state.computed], _getHintingShapeIds_dec = [import_state.computed], _getHintingShape_dec = [import_state.computed], _getErasingShapeIds_dec = [import_state.computed], _getErasingShapes_dec = [import_state.computed], __unsafe_getCameraId_dec = [import_state.computed], _getCamera_dec = [import_state.computed], _getViewportPageBoundsForFollowing_dec = [import_state.computed], _getCameraForFollowing_dec = [import_state.computed], _getZoomLevel_dec = [import_state.computed], _getViewportScreenBounds_dec = [import_state.computed], _getViewportScreenCenter_dec = [import_state.computed], _getViewportPageBounds_dec = [import_state.computed], __getCollaboratorsQuery_dec = [import_state.computed], _getCollaborators_dec = [import_state.computed], _getCollaboratorsOnCurrentPage_dec = [import_state.computed], _getRenderingShapes_dec = [import_state.computed], __getAllPagesQuery_dec = [import_state.computed], _getPages_dec = [import_state.computed], _getCurrentPageId_dec = [import_state.computed], _getCurrentPageShapeIdsSorted_dec = [import_state.computed], __getAllAssetsQuery_dec = [import_state.computed], __getShapeHandlesCache_dec = [import_state.computed], __getShapePageTransformCache_dec = [import_state.computed], __getShapePageBoundsCache_dec = [import_state.computed], __getShapeClipPathCache_dec = [import_state.computed], __getShapeMaskCache_dec = [import_state.computed], __getShapeMaskedPageBoundsCache_dec = [import_state.computed], __notVisibleShapes_dec = [import_state.computed], _getCulledShapes_dec = [import_state.computed], _getCurrentPageBounds_dec = [import_state.computed], _getCurrentPageShapes_dec = [import_state.computed], _getCurrentPageShapesSorted_dec = [import_state.computed], _getCurrentPageRenderingShapesSorted_dec = [import_state.computed], __getBindingsIndexCache_dec = [import_state.computed], __getSelectionSharedStyles_dec = [import_state.computed], _getSharedStyles_dec = [(0, import_state.computed)({ isEqual: (a, b) => a.equals(b) })], _getSharedOpacity_dec = [import_state.computed], _getIsFocused_dec = [import_state.computed], _getIsReadonly_dec = [import_state.computed], __setShiftKeyTimeout_dec = [import_utils.bind], __setAltKeyTimeout_dec = [import_utils.bind], __setCtrlKeyTimeout_dec = [import_utils.bind], __setMetaKeyTimeout_dec = [import_utils.bind], _a) {
127
127
  constructor({
128
128
  store,
129
129
  user,
@@ -137,13 +137,15 @@ class Editor extends (_a = import_eventemitter3.default, _getIsShapeHiddenCache_
137
137
  autoFocus,
138
138
  inferDarkMode,
139
139
  options,
140
+ // eslint-disable-next-line @typescript-eslint/no-deprecated
140
141
  isShapeHidden,
142
+ getShapeVisibility,
141
143
  fontAssetUrls
142
144
  }) {
143
145
  super();
144
146
  __runInitializers(_init, 5, this);
145
147
  __publicField(this, "id", (0, import_utils.uniqueId)());
146
- __publicField(this, "_isShapeHiddenPredicate");
148
+ __publicField(this, "_getShapeVisibility");
147
149
  __publicField(this, "options");
148
150
  __publicField(this, "contextId", (0, import_utils.uniqueId)());
149
151
  /**
@@ -299,6 +301,7 @@ class Editor extends (_a = import_eventemitter3.default, _getIsShapeHiddenCache_
299
301
  __publicField(this, "_currentPageShapeIds");
300
302
  /* --------------------- Shapes --------------------- */
301
303
  __publicField(this, "_shapeGeometryCaches", {});
304
+ __publicField(this, "_shapePageGeometryCaches", {});
302
305
  // Parents and children
303
306
  /**
304
307
  * A cache of parents to children.
@@ -410,7 +413,14 @@ class Editor extends (_a = import_eventemitter3.default, _getIsShapeHiddenCache_
410
413
  /** @internal */
411
414
  __publicField(this, "performanceTrackerTimeout", -1);
412
415
  __publicField(this, "_pendingEventsForNextTick", []);
413
- this._isShapeHiddenPredicate = isShapeHidden;
416
+ (0, import_utils.assert)(
417
+ !(isShapeHidden && getShapeVisibility),
418
+ "Cannot use both isShapeHidden and getShapeVisibility"
419
+ );
420
+ this._getShapeVisibility = isShapeHidden ? (
421
+ // eslint-disable-next-line @typescript-eslint/no-deprecated
422
+ (shape, editor) => isShapeHidden(shape, editor) ? "hidden" : "inherit"
423
+ ) : getShapeVisibility;
414
424
  this.options = { ...import_options.defaultTldrawOptions, ...options };
415
425
  this.store = store;
416
426
  this.disposables.add(this.store.dispose.bind(this.store));
@@ -803,15 +813,16 @@ class Editor extends (_a = import_eventemitter3.default, _getIsShapeHiddenCache_
803
813
  }
804
814
  }
805
815
  getIsShapeHiddenCache() {
806
- if (!this._isShapeHiddenPredicate) return null;
816
+ if (!this._getShapeVisibility) return null;
807
817
  return this.store.createComputedCache("isShapeHidden", (shape) => {
808
- const hiddenParent = this.findShapeAncestor(shape, (p) => this.isShapeHidden(p));
809
- if (hiddenParent) return true;
810
- return this._isShapeHiddenPredicate(shape, this) ?? false;
818
+ const visibility = this._getShapeVisibility(shape, this);
819
+ const isParentHidden = import_tlschema.PageRecordType.isId(shape.parentId) ? false : this.isShapeHidden(shape.parentId);
820
+ if (isParentHidden) return visibility !== "visible";
821
+ return visibility === "hidden";
811
822
  });
812
823
  }
813
824
  isShapeHidden(shapeOrId) {
814
- if (!this._isShapeHiddenPredicate) return false;
825
+ if (!this._getShapeVisibility) return false;
815
826
  return !!this.getIsShapeHiddenCache().get(
816
827
  typeof shapeOrId === "string" ? shapeOrId : shapeOrId.id
817
828
  );
@@ -1430,6 +1441,131 @@ class Editor extends (_a = import_eventemitter3.default, _getIsShapeHiddenCache_
1430
1441
  this.setSelectedShapes(this._getUnlockedShapeIds(ids));
1431
1442
  return this;
1432
1443
  }
1444
+ selectAdjacentShape(direction) {
1445
+ const readingOrderShapes = this.getCurrentPageShapesInReadingOrder();
1446
+ const selectedShapeIds = this.getSelectedShapeIds();
1447
+ const currentShapeId = selectedShapeIds.length === 1 ? selectedShapeIds[0] : readingOrderShapes.find((shape2) => selectedShapeIds.includes(shape2.id))?.id;
1448
+ let adjacentShapeId;
1449
+ if (direction === "next" || direction === "prev") {
1450
+ const shapeIds = readingOrderShapes.map((shape2) => shape2.id);
1451
+ const currentIndex = currentShapeId ? shapeIds.indexOf(currentShapeId) : -1;
1452
+ const adjacentIndex = (currentIndex + (direction === "next" ? 1 : -1) + shapeIds.length) % shapeIds.length;
1453
+ adjacentShapeId = shapeIds[adjacentIndex];
1454
+ } else {
1455
+ if (!currentShapeId) return;
1456
+ adjacentShapeId = this.getNearestAdjacentShape(currentShapeId, direction);
1457
+ }
1458
+ const shape = this.getShape(adjacentShapeId);
1459
+ if (!shape) return;
1460
+ this.setSelectedShapes([shape.id]);
1461
+ this.zoomToSelectionIfOffscreen(256, {
1462
+ animation: {
1463
+ duration: this.options.animationMediumMs
1464
+ },
1465
+ inset: 0
1466
+ });
1467
+ }
1468
+ getCurrentPageShapesInReadingOrder() {
1469
+ const SHALLOW_ANGLE = 20;
1470
+ const ROW_THRESHOLD = 100;
1471
+ const shapes = this.getCurrentPageShapes();
1472
+ const tabbableShapes = shapes.filter((shape) => this.getShapeUtil(shape).canTabTo(shape));
1473
+ if (tabbableShapes.length <= 1) return tabbableShapes;
1474
+ const shapesWithCenters = tabbableShapes.map((shape) => ({
1475
+ shape,
1476
+ center: this.getShapePageBounds(shape).center
1477
+ }));
1478
+ shapesWithCenters.sort((a, b) => a.center.y - b.center.y);
1479
+ const rows = [];
1480
+ for (const shapeWithCenter of shapesWithCenters) {
1481
+ let rowIndex = -1;
1482
+ for (let i = rows.length - 1; i >= 0; i--) {
1483
+ const row = rows[i];
1484
+ const lastShapeInRow = row[row.length - 1];
1485
+ if (Math.abs(shapeWithCenter.center.y - lastShapeInRow.center.y) < ROW_THRESHOLD) {
1486
+ rowIndex = i;
1487
+ break;
1488
+ }
1489
+ }
1490
+ if (rowIndex === -1) {
1491
+ rows.push([shapeWithCenter]);
1492
+ } else {
1493
+ rows[rowIndex].push(shapeWithCenter);
1494
+ }
1495
+ }
1496
+ for (const row of rows) {
1497
+ row.sort((a, b) => a.center.x - b.center.x);
1498
+ }
1499
+ for (const row of rows) {
1500
+ if (row.length <= 2) continue;
1501
+ for (let i = 0; i < row.length - 2; i++) {
1502
+ const currentShape = row[i];
1503
+ const nextShape = row[i + 1];
1504
+ const nextNextShape = row[i + 2];
1505
+ const dist1 = import_Vec.Vec.Dist2(currentShape.center, nextShape.center);
1506
+ const dist2 = import_Vec.Vec.Dist2(currentShape.center, nextNextShape.center);
1507
+ if (dist2 < dist1 * 0.9) {
1508
+ const angle = Math.abs(
1509
+ import_Vec.Vec.Angle(currentShape.center, nextNextShape.center) * (180 / Math.PI)
1510
+ );
1511
+ if (angle <= SHALLOW_ANGLE) {
1512
+ ;
1513
+ [row[i + 1], row[i + 2]] = [row[i + 2], row[i + 1]];
1514
+ }
1515
+ }
1516
+ }
1517
+ }
1518
+ return rows.flat().map((item) => item.shape);
1519
+ }
1520
+ /**
1521
+ * Find the nearest adjacent shape in a specific direction.
1522
+ *
1523
+ * @public
1524
+ */
1525
+ getNearestAdjacentShape(currentShapeId, direction) {
1526
+ const directionToAngle = { right: 0, left: 180, down: 90, up: 270 };
1527
+ const currentShape = this.getShape(currentShapeId);
1528
+ if (!currentShape) return currentShapeId;
1529
+ const shapes = this.getCurrentPageShapes();
1530
+ const tabbableShapes = shapes.filter(
1531
+ (shape) => this.getShapeUtil(shape).canTabTo(shape) && shape.id !== currentShapeId
1532
+ );
1533
+ if (!tabbableShapes.length) return currentShapeId;
1534
+ const currentCenter = this.getShapePageBounds(currentShape).center;
1535
+ const shapesWithCenters = tabbableShapes.map((shape) => ({
1536
+ shape,
1537
+ center: this.getShapePageBounds(shape).center
1538
+ }));
1539
+ const shapesInDirection = shapesWithCenters.filter(({ center }) => {
1540
+ const isRight = center.x > currentCenter.x;
1541
+ const isDown = center.y > currentCenter.y;
1542
+ const xDist = center.x - currentCenter.x;
1543
+ const yDist = center.y - currentCenter.y;
1544
+ const isInXDirection = Math.abs(yDist) < Math.abs(xDist) * 2;
1545
+ const isInYDirection = Math.abs(xDist) < Math.abs(yDist) * 2;
1546
+ if (direction === "left" || direction === "right") {
1547
+ return isInXDirection && (direction === "right" ? isRight : !isRight);
1548
+ }
1549
+ if (direction === "up" || direction === "down") {
1550
+ return isInYDirection && (direction === "down" ? isDown : !isDown);
1551
+ }
1552
+ });
1553
+ if (shapesInDirection.length === 0) return currentShapeId;
1554
+ const lowestScoringShape = (0, import_utils.minBy)(shapesInDirection, ({ center }) => {
1555
+ const distance = import_Vec.Vec.Dist2(currentCenter, center);
1556
+ const dirProp = ["left", "right"].includes(direction) ? "x" : "y";
1557
+ const directionalDistance = Math.abs(center[dirProp] - currentCenter[dirProp]);
1558
+ const offProp = ["left", "right"].includes(direction) ? "y" : "x";
1559
+ const offAxisDeviation = Math.abs(center[offProp] - currentCenter[offProp]);
1560
+ const angle = Math.abs(import_Vec.Vec.Angle(currentCenter, center) * (180 / Math.PI));
1561
+ const angleDeviation = Math.abs(angle - directionToAngle[direction]);
1562
+ return distance * 1 + // Base distance
1563
+ offAxisDeviation * 2 + // Heavy penalty for off-axis deviation
1564
+ (distance - directionalDistance) * 1.5 + // Penalty for diagonal distance
1565
+ angleDeviation * 0.5;
1566
+ });
1567
+ return lowestScoringShape.shape.id;
1568
+ }
1433
1569
  /**
1434
1570
  * Clear the selection.
1435
1571
  *
@@ -2343,6 +2479,23 @@ class Editor extends (_a = import_eventemitter3.default, _getIsShapeHiddenCache_
2343
2479
  }
2344
2480
  return this;
2345
2481
  }
2482
+ /**
2483
+ * Zoom the camera to the current selection if offscreen.
2484
+ *
2485
+ * @public
2486
+ */
2487
+ zoomToSelectionIfOffscreen(padding = 16, opts) {
2488
+ const selectionPageBounds = this.getSelectionPageBounds();
2489
+ const viewportPageBounds = this.getViewportPageBounds();
2490
+ if (selectionPageBounds && !viewportPageBounds.contains(selectionPageBounds)) {
2491
+ const eb = selectionPageBounds.clone().expandBy(padding / this.getZoomLevel()).expand(viewportPageBounds);
2492
+ const nextBounds = viewportPageBounds.clone().translate({
2493
+ x: (eb.center.x - viewportPageBounds.center.x) * 2,
2494
+ y: (eb.center.y - viewportPageBounds.center.y) * 2
2495
+ });
2496
+ this.zoomToBounds(nextBounds, opts);
2497
+ }
2498
+ }
2346
2499
  /**
2347
2500
  * Zoom the camera to fit a bounding box (in the current page space).
2348
2501
  *
@@ -2825,7 +2978,13 @@ class Editor extends (_a = import_eventemitter3.default, _getIsShapeHiddenCache_
2825
2978
  const addShapeById = (id, opacity, isAncestorErasing) => {
2826
2979
  const shape = this.getShape(id);
2827
2980
  if (!shape) return;
2828
- if (this.isShapeHidden(shape)) return;
2981
+ if (this.isShapeHidden(shape)) {
2982
+ const isErasing = isAncestorErasing || erasingShapeIds.includes(id);
2983
+ for (const childId of this.getSortedChildIdsForParent(id)) {
2984
+ addShapeById(childId, opacity, isErasing);
2985
+ }
2986
+ return;
2987
+ }
2829
2988
  opacity *= shape.opacity;
2830
2989
  let isShapeErasing = false;
2831
2990
  const util = this.getShapeUtil(shape);
@@ -3252,7 +3411,7 @@ class Editor extends (_a = import_eventemitter3.default, _getIsShapeHiddenCache_
3252
3411
  return await this.store.props.assets.upload(asset, file, abortSignal);
3253
3412
  }
3254
3413
  /**
3255
- * Get the geometry of a shape.
3414
+ * Get the geometry of a shape in shape-space.
3256
3415
  *
3257
3416
  * @example
3258
3417
  * ```ts
@@ -3282,6 +3441,41 @@ class Editor extends (_a = import_eventemitter3.default, _getIsShapeHiddenCache_
3282
3441
  typeof shape === "string" ? shape : shape.id
3283
3442
  );
3284
3443
  }
3444
+ /**
3445
+ * Get the geometry of a shape in page-space.
3446
+ *
3447
+ * @example
3448
+ * ```ts
3449
+ * editor.getShapePageGeometry(myShape)
3450
+ * editor.getShapePageGeometry(myShapeId)
3451
+ * editor.getShapePageGeometry(myShapeId, { context: "arrow" })
3452
+ * ```
3453
+ *
3454
+ * @param shape - The shape (or shape id) to get the geometry for.
3455
+ * @param opts - Additional options about the request for geometry. Passed to {@link ShapeUtil.getGeometry}.
3456
+ *
3457
+ * @public
3458
+ */
3459
+ getShapePageGeometry(shape, opts) {
3460
+ const context = opts?.context ?? "none";
3461
+ if (!this._shapePageGeometryCaches[context]) {
3462
+ this._shapePageGeometryCaches[context] = this.store.createComputedCache(
3463
+ "bounds",
3464
+ (shape2) => {
3465
+ const geometry = this.getShapeGeometry(shape2.id, opts);
3466
+ const pageTransform = this.getShapePageTransform(shape2.id);
3467
+ return geometry.transform(pageTransform);
3468
+ },
3469
+ {
3470
+ // we only depend directly on the shape id, and changing geometry/transform will update us anyway
3471
+ areRecordsEqual: () => true
3472
+ }
3473
+ );
3474
+ }
3475
+ return this._shapePageGeometryCaches[context].get(
3476
+ typeof shape === "string" ? shape : shape.id
3477
+ );
3478
+ }
3285
3479
  _getShapeHandlesCache() {
3286
3480
  return this.store.createComputedCache("handles", (shape) => {
3287
3481
  return this.getShapeUtil(shape).getHandles?.(shape);
@@ -3369,12 +3563,7 @@ class Editor extends (_a = import_eventemitter3.default, _getIsShapeHiddenCache_
3369
3563
  }
3370
3564
  _getShapePageBoundsCache() {
3371
3565
  return this.store.createComputedCache("pageBoundsCache", (shape) => {
3372
- const pageTransform = this._getShapePageTransformCache().get(shape.id);
3373
- if (!pageTransform) return new import_Box.Box();
3374
- const result = import_Box.Box.FromPoints(
3375
- import_Mat.Mat.applyToPoints(pageTransform, this.getShapeGeometry(shape).vertices)
3376
- );
3377
- return result;
3566
+ return this.getShapePageGeometry(shape).bounds;
3378
3567
  });
3379
3568
  }
3380
3569
  /**
@@ -3434,7 +3623,7 @@ class Editor extends (_a = import_eventemitter3.default, _getIsShapeHiddenCache_
3434
3623
  const pageMask = frameAncestors.map(
3435
3624
  (s) => (
3436
3625
  // Apply the frame transform to the frame outline to get the frame outline in the current page space
3437
- this._getShapePageTransformCache().get(s.id).applyToPoints(this.getShapeGeometry(s).vertices)
3626
+ this.getShapePageGeometry(s.id).vertices
3438
3627
  )
3439
3628
  ).reduce((acc, b) => {
3440
3629
  if (!(b && acc)) return void 0;
@@ -7511,6 +7700,7 @@ __decorateElement(_init, 1, "getCurrentPageState", _getCurrentPageState_dec, Edi
7511
7700
  __decorateElement(_init, 1, "_getCurrentPageStateId", __getCurrentPageStateId_dec, Editor);
7512
7701
  __decorateElement(_init, 1, "getSelectedShapeIds", _getSelectedShapeIds_dec, Editor);
7513
7702
  __decorateElement(_init, 1, "getSelectedShapes", _getSelectedShapes_dec, Editor);
7703
+ __decorateElement(_init, 1, "getCurrentPageShapesInReadingOrder", _getCurrentPageShapesInReadingOrder_dec, Editor);
7514
7704
  __decorateElement(_init, 1, "getOnlySelectedShapeId", _getOnlySelectedShapeId_dec, Editor);
7515
7705
  __decorateElement(_init, 1, "getOnlySelectedShape", _getOnlySelectedShape_dec, Editor);
7516
7706
  __decorateElement(_init, 1, "getSelectionPageBounds", _getSelectionPageBounds_dec, Editor);