@tldraw/editor 3.14.0-canary.f907ed7d9ee5 → 3.14.0-canary.fb0390b30559

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 (75) hide show
  1. package/dist-cjs/index.d.ts +149 -50
  2. package/dist-cjs/index.js +4 -1
  3. package/dist-cjs/index.js.map +2 -2
  4. package/dist-cjs/lib/editor/Editor.js +82 -25
  5. package/dist-cjs/lib/editor/Editor.js.map +2 -2
  6. package/dist-cjs/lib/editor/managers/HistoryManager/HistoryManager.js +3 -1
  7. package/dist-cjs/lib/editor/managers/HistoryManager/HistoryManager.js.map +2 -2
  8. package/dist-cjs/lib/editor/managers/TextManager/TextManager.js +73 -42
  9. package/dist-cjs/lib/editor/managers/TextManager/TextManager.js.map +2 -2
  10. package/dist-cjs/lib/editor/shapes/ShapeUtil.js +0 -10
  11. package/dist-cjs/lib/editor/shapes/ShapeUtil.js.map +2 -2
  12. package/dist-cjs/lib/editor/tools/BaseBoxShapeTool/children/Pointing.js +13 -6
  13. package/dist-cjs/lib/editor/tools/BaseBoxShapeTool/children/Pointing.js.map +3 -3
  14. package/dist-cjs/lib/editor/tools/StateNode.js +3 -3
  15. package/dist-cjs/lib/editor/tools/StateNode.js.map +2 -2
  16. package/dist-cjs/lib/editor/types/emit-types.js.map +1 -1
  17. package/dist-cjs/lib/editor/types/external-content.js.map +1 -1
  18. package/dist-cjs/lib/hooks/useCanvasEvents.js +1 -2
  19. package/dist-cjs/lib/hooks/useCanvasEvents.js.map +2 -2
  20. package/dist-cjs/lib/primitives/geometry/Geometry2d.js +6 -2
  21. package/dist-cjs/lib/primitives/geometry/Geometry2d.js.map +2 -2
  22. package/dist-cjs/lib/primitives/geometry/Group2d.js +11 -6
  23. package/dist-cjs/lib/primitives/geometry/Group2d.js.map +2 -2
  24. package/dist-cjs/lib/utils/dom.js +1 -1
  25. package/dist-cjs/lib/utils/dom.js.map +2 -2
  26. package/dist-cjs/lib/utils/reparenting.js +232 -0
  27. package/dist-cjs/lib/utils/reparenting.js.map +7 -0
  28. package/dist-cjs/version.js +3 -3
  29. package/dist-cjs/version.js.map +1 -1
  30. package/dist-esm/index.d.mts +149 -50
  31. package/dist-esm/index.mjs +4 -1
  32. package/dist-esm/index.mjs.map +2 -2
  33. package/dist-esm/lib/editor/Editor.mjs +82 -25
  34. package/dist-esm/lib/editor/Editor.mjs.map +2 -2
  35. package/dist-esm/lib/editor/managers/HistoryManager/HistoryManager.mjs +3 -1
  36. package/dist-esm/lib/editor/managers/HistoryManager/HistoryManager.mjs.map +2 -2
  37. package/dist-esm/lib/editor/managers/TextManager/TextManager.mjs +73 -42
  38. package/dist-esm/lib/editor/managers/TextManager/TextManager.mjs.map +2 -2
  39. package/dist-esm/lib/editor/shapes/ShapeUtil.mjs +0 -10
  40. package/dist-esm/lib/editor/shapes/ShapeUtil.mjs.map +2 -2
  41. package/dist-esm/lib/editor/tools/BaseBoxShapeTool/children/Pointing.mjs +13 -6
  42. package/dist-esm/lib/editor/tools/BaseBoxShapeTool/children/Pointing.mjs.map +3 -3
  43. package/dist-esm/lib/editor/tools/StateNode.mjs +3 -3
  44. package/dist-esm/lib/editor/tools/StateNode.mjs.map +2 -2
  45. package/dist-esm/lib/hooks/useCanvasEvents.mjs +1 -2
  46. package/dist-esm/lib/hooks/useCanvasEvents.mjs.map +2 -2
  47. package/dist-esm/lib/primitives/geometry/Geometry2d.mjs +6 -2
  48. package/dist-esm/lib/primitives/geometry/Geometry2d.mjs.map +2 -2
  49. package/dist-esm/lib/primitives/geometry/Group2d.mjs +11 -6
  50. package/dist-esm/lib/primitives/geometry/Group2d.mjs.map +2 -2
  51. package/dist-esm/lib/utils/dom.mjs +1 -1
  52. package/dist-esm/lib/utils/dom.mjs.map +2 -2
  53. package/dist-esm/lib/utils/reparenting.mjs +216 -0
  54. package/dist-esm/lib/utils/reparenting.mjs.map +7 -0
  55. package/dist-esm/version.mjs +3 -3
  56. package/dist-esm/version.mjs.map +1 -1
  57. package/editor.css +446 -489
  58. package/package.json +7 -7
  59. package/src/index.ts +7 -0
  60. package/src/lib/editor/Editor.ts +103 -36
  61. package/src/lib/editor/managers/HistoryManager/HistoryManager.ts +3 -1
  62. package/src/lib/editor/managers/TextManager/TextManager.test.ts +1 -5
  63. package/src/lib/editor/managers/TextManager/TextManager.ts +118 -86
  64. package/src/lib/editor/shapes/ShapeUtil.ts +47 -15
  65. package/src/lib/editor/tools/BaseBoxShapeTool/children/Pointing.ts +25 -17
  66. package/src/lib/editor/tools/StateNode.ts +3 -3
  67. package/src/lib/editor/types/emit-types.ts +4 -0
  68. package/src/lib/editor/types/external-content.ts +11 -2
  69. package/src/lib/hooks/useCanvasEvents.ts +0 -1
  70. package/src/lib/primitives/geometry/Geometry2d.ts +7 -2
  71. package/src/lib/primitives/geometry/Group2d.ts +11 -5
  72. package/src/lib/utils/dom.ts +1 -1
  73. package/src/lib/utils/reparenting.ts +383 -0
  74. package/src/version.ts +3 -3
  75. package/CHANGELOG.md +0 -4327
@@ -0,0 +1,232 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+ var reparenting_exports = {};
20
+ __export(reparenting_exports, {
21
+ doesGeometryOverlapPolygon: () => doesGeometryOverlapPolygon,
22
+ getDroppedShapesToNewParents: () => getDroppedShapesToNewParents,
23
+ kickoutOccludedShapes: () => kickoutOccludedShapes
24
+ });
25
+ module.exports = __toCommonJS(reparenting_exports);
26
+ var import_state = require("@tldraw/state");
27
+ var import_utils = require("@tldraw/utils");
28
+ var import_Group2d = require("../primitives/geometry/Group2d");
29
+ var import_intersect = require("../primitives/intersect");
30
+ var import_utils2 = require("../primitives/utils");
31
+ function kickoutOccludedShapes(editor, shapeIds, opts) {
32
+ const parentsToCheck = /* @__PURE__ */ new Set();
33
+ for (const id of shapeIds) {
34
+ const shape = editor.getShape(id);
35
+ if (!shape) continue;
36
+ parentsToCheck.add(shape);
37
+ const parent = editor.getShape(shape.parentId);
38
+ if (!parent) continue;
39
+ parentsToCheck.add(parent);
40
+ }
41
+ const parentsToLostChildren = /* @__PURE__ */ new Map();
42
+ for (const parent of parentsToCheck) {
43
+ const childIds = editor.getSortedChildIdsForParent(parent);
44
+ if (opts?.filter && !opts.filter(parent)) {
45
+ parentsToLostChildren.set(parent, childIds);
46
+ } else {
47
+ const overlappingChildren = getOverlappingShapes(editor, parent.id, childIds);
48
+ if (overlappingChildren.length < childIds.length) {
49
+ parentsToLostChildren.set(
50
+ parent,
51
+ childIds.filter((id) => !overlappingChildren.includes(id))
52
+ );
53
+ }
54
+ }
55
+ }
56
+ const sortedShapeIds = editor.getCurrentPageShapesSorted().map((s) => s.id);
57
+ const parentsToNewChildren = {};
58
+ for (const [prevParent, lostChildrenIds] of parentsToLostChildren) {
59
+ const lostChildren = (0, import_utils.compact)(lostChildrenIds.map((id) => editor.getShape(id)));
60
+ const { reparenting, remainingShapesToReparent } = getDroppedShapesToNewParents(
61
+ editor,
62
+ lostChildren,
63
+ (shape, maybeNewParent) => {
64
+ if (opts?.filter && !opts.filter(maybeNewParent)) return false;
65
+ return maybeNewParent.id !== prevParent.id && sortedShapeIds.indexOf(maybeNewParent.id) < sortedShapeIds.indexOf(shape.id);
66
+ }
67
+ );
68
+ reparenting.forEach((childrenToReparent, newParentId) => {
69
+ if (childrenToReparent.length === 0) return;
70
+ if (!parentsToNewChildren[newParentId]) {
71
+ parentsToNewChildren[newParentId] = {
72
+ parentId: newParentId,
73
+ shapeIds: []
74
+ };
75
+ }
76
+ parentsToNewChildren[newParentId].shapeIds.push(...childrenToReparent.map((s) => s.id));
77
+ });
78
+ if (remainingShapesToReparent.size > 0) {
79
+ const newParentId = editor.findShapeAncestor(prevParent, (s) => editor.isShapeOfType(s, "group"))?.id ?? editor.getCurrentPageId();
80
+ remainingShapesToReparent.forEach((shape) => {
81
+ if (!parentsToNewChildren[newParentId]) {
82
+ let insertIndexKey;
83
+ const oldParentSiblingIds = editor.getSortedChildIdsForParent(newParentId);
84
+ const oldParentIndex = oldParentSiblingIds.indexOf(prevParent.id);
85
+ if (oldParentIndex > -1) {
86
+ const siblingsIndexAbove = oldParentSiblingIds[oldParentIndex + 1];
87
+ const indexKeyAbove = siblingsIndexAbove ? editor.getShape(siblingsIndexAbove).index : (0, import_utils.getIndexAbove)(prevParent.index);
88
+ insertIndexKey = (0, import_utils.getIndexBetween)(prevParent.index, indexKeyAbove);
89
+ } else {
90
+ }
91
+ parentsToNewChildren[newParentId] = {
92
+ parentId: newParentId,
93
+ shapeIds: [],
94
+ index: insertIndexKey
95
+ };
96
+ }
97
+ parentsToNewChildren[newParentId].shapeIds.push(shape.id);
98
+ });
99
+ }
100
+ }
101
+ editor.run(() => {
102
+ Object.values(parentsToNewChildren).forEach(({ parentId, shapeIds: shapeIds2, index }) => {
103
+ if (shapeIds2.length === 0) return;
104
+ shapeIds2.sort((a, b) => sortedShapeIds.indexOf(a) < sortedShapeIds.indexOf(b) ? -1 : 1);
105
+ editor.reparentShapes(shapeIds2, parentId, index);
106
+ });
107
+ });
108
+ }
109
+ function getOverlappingShapes(editor, shape, otherShapes) {
110
+ if (otherShapes.length === 0) {
111
+ return import_state.EMPTY_ARRAY;
112
+ }
113
+ const parentPageBounds = editor.getShapePageBounds(shape);
114
+ if (!parentPageBounds) return import_state.EMPTY_ARRAY;
115
+ const parentGeometry = editor.getShapeGeometry(shape);
116
+ const parentPageTransform = editor.getShapePageTransform(shape);
117
+ const parentPageCorners = parentPageTransform.applyToPoints(parentGeometry.vertices);
118
+ const parentPageMaskVertices = editor.getShapeMask(shape);
119
+ const parentPagePolygon = parentPageMaskVertices ? (0, import_intersect.intersectPolygonPolygon)(parentPageMaskVertices, parentPageCorners) : parentPageCorners;
120
+ if (!parentPagePolygon) return import_state.EMPTY_ARRAY;
121
+ return otherShapes.filter((childId) => {
122
+ const shapePageBounds = editor.getShapePageBounds(childId);
123
+ if (!shapePageBounds || !parentPageBounds.includes(shapePageBounds)) return false;
124
+ const parentPolygonInShapeShape = editor.getShapePageTransform(childId).clone().invert().applyToPoints(parentPagePolygon);
125
+ const geometry = editor.getShapeGeometry(childId);
126
+ return doesGeometryOverlapPolygon(geometry, parentPolygonInShapeShape);
127
+ });
128
+ }
129
+ function doesGeometryOverlapPolygon(geometry, parentCornersInShapeSpace) {
130
+ if (geometry instanceof import_Group2d.Group2d) {
131
+ return geometry.children.some(
132
+ (childGeometry) => doesGeometryOverlapPolygon(childGeometry, parentCornersInShapeSpace)
133
+ );
134
+ }
135
+ const { vertices, center, isFilled, isEmptyLabel, isClosed } = geometry;
136
+ if (isEmptyLabel) return false;
137
+ if (vertices.some((v) => (0, import_utils2.pointInPolygon)(v, parentCornersInShapeSpace))) {
138
+ return true;
139
+ }
140
+ if (isClosed) {
141
+ if (isFilled) {
142
+ if ((0, import_utils2.pointInPolygon)(center, parentCornersInShapeSpace)) {
143
+ return true;
144
+ }
145
+ if (parentCornersInShapeSpace.every((v) => (0, import_utils2.pointInPolygon)(v, vertices))) {
146
+ return true;
147
+ }
148
+ }
149
+ if ((0, import_intersect.polygonsIntersect)(parentCornersInShapeSpace, vertices)) {
150
+ return true;
151
+ }
152
+ } else {
153
+ if ((0, import_intersect.polygonIntersectsPolyline)(parentCornersInShapeSpace, vertices)) {
154
+ return true;
155
+ }
156
+ }
157
+ return false;
158
+ }
159
+ function getDroppedShapesToNewParents(editor, shapes, cb) {
160
+ const shapesToActuallyCheck = new Set(shapes);
161
+ const movingGroups = /* @__PURE__ */ new Set();
162
+ for (const shape of shapes) {
163
+ const parent = editor.getShapeParent(shape);
164
+ if (parent && editor.isShapeOfType(parent, "group")) {
165
+ if (!movingGroups.has(parent)) {
166
+ movingGroups.add(parent);
167
+ }
168
+ }
169
+ }
170
+ for (const movingGroup of movingGroups) {
171
+ const children = (0, import_utils.compact)(
172
+ editor.getSortedChildIdsForParent(movingGroup).map((id) => editor.getShape(id))
173
+ );
174
+ for (const child of children) {
175
+ shapesToActuallyCheck.delete(child);
176
+ }
177
+ shapesToActuallyCheck.add(movingGroup);
178
+ }
179
+ const shapeGroupIds = /* @__PURE__ */ new Map();
180
+ const reparenting = /* @__PURE__ */ new Map();
181
+ const remainingShapesToReparent = new Set(shapesToActuallyCheck);
182
+ const potentialParentShapes = editor.getCurrentPageShapesSorted().filter(
183
+ (s) => editor.getShapeUtil(s).canReceiveNewChildrenOfType?.(s, s.type) && !remainingShapesToReparent.has(s)
184
+ );
185
+ parentCheck: for (let i = potentialParentShapes.length - 1; i >= 0; i--) {
186
+ const parentShape = potentialParentShapes[i];
187
+ const parentShapeContainingGroupId = editor.findShapeAncestor(
188
+ parentShape,
189
+ (s) => editor.isShapeOfType(s, "group")
190
+ )?.id;
191
+ const parentGeometry = editor.getShapeGeometry(parentShape);
192
+ const parentPageTransform = editor.getShapePageTransform(parentShape);
193
+ const parentPageMaskVertices = editor.getShapeMask(parentShape);
194
+ const parentPageCorners = parentPageTransform.applyToPoints(parentGeometry.vertices);
195
+ const parentPagePolygon = parentPageMaskVertices ? (0, import_intersect.intersectPolygonPolygon)(parentPageMaskVertices, parentPageCorners) : parentPageCorners;
196
+ if (!parentPagePolygon) continue parentCheck;
197
+ const childrenToReparent = [];
198
+ shapeCheck: for (const shape of remainingShapesToReparent) {
199
+ if (parentShape.id === shape.id) continue shapeCheck;
200
+ if (cb && !cb(shape, parentShape)) continue shapeCheck;
201
+ if (!shapeGroupIds.has(shape.id)) {
202
+ shapeGroupIds.set(
203
+ shape.id,
204
+ editor.findShapeAncestor(shape, (s) => editor.isShapeOfType(s, "group"))?.id
205
+ );
206
+ }
207
+ const shapeGroupId = shapeGroupIds.get(shape.id);
208
+ if (shapeGroupId !== parentShapeContainingGroupId) continue shapeCheck;
209
+ if (editor.findShapeAncestor(parentShape, (s) => shape.id === s.id)) continue shapeCheck;
210
+ const parentPolygonInShapeSpace = editor.getShapePageTransform(shape).clone().invert().applyToPoints(parentPagePolygon);
211
+ if (doesGeometryOverlapPolygon(editor.getShapeGeometry(shape), parentPolygonInShapeSpace)) {
212
+ if (!editor.getShapeUtil(parentShape).canReceiveNewChildrenOfType?.(parentShape, shape.type))
213
+ continue shapeCheck;
214
+ if (shape.parentId !== parentShape.id) {
215
+ childrenToReparent.push(shape);
216
+ }
217
+ remainingShapesToReparent.delete(shape);
218
+ continue shapeCheck;
219
+ }
220
+ }
221
+ if (childrenToReparent.length) {
222
+ reparenting.set(parentShape.id, childrenToReparent);
223
+ }
224
+ }
225
+ return {
226
+ // these are the shapes that will be reparented to new parents
227
+ reparenting,
228
+ // these are the shapes that will be reparented to the page or their ancestral group
229
+ remainingShapesToReparent
230
+ };
231
+ }
232
+ //# sourceMappingURL=reparenting.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../src/lib/utils/reparenting.ts"],
4
+ "sourcesContent": ["import { EMPTY_ARRAY } from '@tldraw/state'\nimport { TLGroupShape, TLParentId, TLShape, TLShapeId } from '@tldraw/tlschema'\nimport { IndexKey, compact, getIndexAbove, getIndexBetween } from '@tldraw/utils'\nimport { Editor } from '../editor/Editor'\nimport { Vec } from '../primitives/Vec'\nimport { Geometry2d } from '../primitives/geometry/Geometry2d'\nimport { Group2d } from '../primitives/geometry/Group2d'\nimport {\n\tintersectPolygonPolygon,\n\tpolygonIntersectsPolyline,\n\tpolygonsIntersect,\n} from '../primitives/intersect'\nimport { pointInPolygon } from '../primitives/utils'\n\n/**\n * Reparents shapes that are no longer contained within their parent shapes.\n * todo: rename me to something more descriptive, like `reparentOccludedShapes` or `reparentAutoDroppedShapes`\n *\n * @param editor - The editor instance.\n * @param shapeIds - The IDs of the shapes to reparent.\n * @param opts - Optional options, including a callback to filter out certain parents, such as when removing a frame.\n *\n * @public\n */\nexport function kickoutOccludedShapes(\n\teditor: Editor,\n\tshapeIds: TLShapeId[],\n\topts?: { filter?(parent: TLShape): boolean }\n) {\n\tconst parentsToCheck = new Set<TLShape>()\n\n\tfor (const id of shapeIds) {\n\t\tconst shape = editor.getShape(id)\n\n\t\tif (!shape) continue\n\t\tparentsToCheck.add(shape)\n\n\t\tconst parent = editor.getShape(shape.parentId)\n\t\tif (!parent) continue\n\t\tparentsToCheck.add(parent)\n\t}\n\n\t// Check all of the parents and gather up parents who have lost children\n\tconst parentsToLostChildren = new Map<TLShape, TLShapeId[]>()\n\n\tfor (const parent of parentsToCheck) {\n\t\tconst childIds = editor.getSortedChildIdsForParent(parent)\n\t\tif (opts?.filter && !opts.filter(parent)) {\n\t\t\t// If the shape is filtered out, we kick out all of its children\n\t\t\tparentsToLostChildren.set(parent, childIds)\n\t\t} else {\n\t\t\tconst overlappingChildren = getOverlappingShapes(editor, parent.id, childIds)\n\t\t\tif (overlappingChildren.length < childIds.length) {\n\t\t\t\tparentsToLostChildren.set(\n\t\t\t\t\tparent,\n\t\t\t\t\tchildIds.filter((id) => !overlappingChildren.includes(id))\n\t\t\t\t)\n\t\t\t}\n\t\t}\n\t}\n\n\t// Get all of the shapes on the current page, sorted by their index\n\tconst sortedShapeIds = editor.getCurrentPageShapesSorted().map((s) => s.id)\n\n\tconst parentsToNewChildren: Record<\n\t\tTLParentId,\n\t\t{ parentId: TLParentId; shapeIds: TLShapeId[]; index?: IndexKey }\n\t> = {}\n\n\tfor (const [prevParent, lostChildrenIds] of parentsToLostChildren) {\n\t\tconst lostChildren = compact(lostChildrenIds.map((id) => editor.getShape(id)))\n\n\t\t// Don't fall \"up\" into frames in front of the shape\n\t\t// if (pageShapes.indexOf(shape) < frameSortPosition) continue shapeCheck\n\n\t\t// Otherwise, we have no next dropping shape under the cursor, so go find\n\t\t// all the frames on the page where the moving shapes will fall into\n\t\tconst { reparenting, remainingShapesToReparent } = getDroppedShapesToNewParents(\n\t\t\teditor,\n\t\t\tlostChildren,\n\t\t\t(shape, maybeNewParent) => {\n\t\t\t\t// If we're filtering out a potential parent, don't reparent shapes to the filtered out shape\n\t\t\t\tif (opts?.filter && !opts.filter(maybeNewParent)) return false\n\t\t\t\treturn (\n\t\t\t\t\tmaybeNewParent.id !== prevParent.id &&\n\t\t\t\t\tsortedShapeIds.indexOf(maybeNewParent.id) < sortedShapeIds.indexOf(shape.id)\n\t\t\t\t)\n\t\t\t}\n\t\t)\n\n\t\treparenting.forEach((childrenToReparent, newParentId) => {\n\t\t\tif (childrenToReparent.length === 0) return\n\t\t\tif (!parentsToNewChildren[newParentId]) {\n\t\t\t\tparentsToNewChildren[newParentId] = {\n\t\t\t\t\tparentId: newParentId,\n\t\t\t\t\tshapeIds: [],\n\t\t\t\t}\n\t\t\t}\n\t\t\tparentsToNewChildren[newParentId].shapeIds.push(...childrenToReparent.map((s) => s.id))\n\t\t})\n\n\t\t// Reparent the rest to the page (or containing group)\n\t\tif (remainingShapesToReparent.size > 0) {\n\t\t\t// The remaining shapes are going to be reparented to the old parent's containing group, if there was one, or else to the page\n\t\t\tconst newParentId =\n\t\t\t\teditor.findShapeAncestor(prevParent, (s) => editor.isShapeOfType<TLGroupShape>(s, 'group'))\n\t\t\t\t\t?.id ?? editor.getCurrentPageId()\n\n\t\t\tremainingShapesToReparent.forEach((shape) => {\n\t\t\t\tif (!parentsToNewChildren[newParentId]) {\n\t\t\t\t\tlet insertIndexKey: IndexKey | undefined\n\n\t\t\t\t\tconst oldParentSiblingIds = editor.getSortedChildIdsForParent(newParentId)\n\t\t\t\t\tconst oldParentIndex = oldParentSiblingIds.indexOf(prevParent.id)\n\t\t\t\t\tif (oldParentIndex > -1) {\n\t\t\t\t\t\t// If the old parent is a direct child of the new parent, then we'll add them above the old parent but below the next sibling.\n\t\t\t\t\t\tconst siblingsIndexAbove = oldParentSiblingIds[oldParentIndex + 1]\n\t\t\t\t\t\tconst indexKeyAbove = siblingsIndexAbove\n\t\t\t\t\t\t\t? editor.getShape(siblingsIndexAbove)!.index\n\t\t\t\t\t\t\t: getIndexAbove(prevParent.index)\n\t\t\t\t\t\tinsertIndexKey = getIndexBetween(prevParent.index, indexKeyAbove)\n\t\t\t\t\t} else {\n\t\t\t\t\t\t// If the old parent is not a direct child of the new parent, then we'll add them to the \"top\" of the new parent's children.\n\t\t\t\t\t\t// This is done automatically if we leave the index undefined, so let's do that.\n\t\t\t\t\t}\n\n\t\t\t\t\tparentsToNewChildren[newParentId] = {\n\t\t\t\t\t\tparentId: newParentId,\n\t\t\t\t\t\tshapeIds: [],\n\t\t\t\t\t\tindex: insertIndexKey,\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tparentsToNewChildren[newParentId].shapeIds.push(shape.id)\n\t\t\t})\n\t\t}\n\t}\n\n\teditor.run(() => {\n\t\tObject.values(parentsToNewChildren).forEach(({ parentId, shapeIds, index }) => {\n\t\t\tif (shapeIds.length === 0) return\n\t\t\t// Before we reparent, sort the new shape ids by their place in the original absolute order on the page\n\t\t\tshapeIds.sort((a, b) => (sortedShapeIds.indexOf(a) < sortedShapeIds.indexOf(b) ? -1 : 1))\n\t\t\teditor.reparentShapes(shapeIds, parentId, index)\n\t\t})\n\t})\n}\n\n/**\n * Get the shapes that overlap with a given shape.\n *\n * @param editor - The editor instance.\n * @param shape - The shapes or shape IDs to check against.\n * @param otherShapes - The shapes or shape IDs to check for overlap.\n * @returns An array of shapes or shape IDs that overlap with the given shape.\n */\nfunction getOverlappingShapes<T extends TLShape[] | TLShapeId[]>(\n\teditor: Editor,\n\tshape: T[number],\n\totherShapes: T\n) {\n\tif (otherShapes.length === 0) {\n\t\treturn EMPTY_ARRAY\n\t}\n\n\tconst parentPageBounds = editor.getShapePageBounds(shape)\n\tif (!parentPageBounds) return EMPTY_ARRAY\n\n\tconst parentGeometry = editor.getShapeGeometry(shape)\n\tconst parentPageTransform = editor.getShapePageTransform(shape)\n\tconst parentPageCorners = parentPageTransform.applyToPoints(parentGeometry.vertices)\n\n\tconst parentPageMaskVertices = editor.getShapeMask(shape)\n\tconst parentPagePolygon = parentPageMaskVertices\n\t\t? intersectPolygonPolygon(parentPageMaskVertices, parentPageCorners)\n\t\t: parentPageCorners\n\n\tif (!parentPagePolygon) return EMPTY_ARRAY\n\n\treturn otherShapes.filter((childId) => {\n\t\tconst shapePageBounds = editor.getShapePageBounds(childId)\n\t\tif (!shapePageBounds || !parentPageBounds.includes(shapePageBounds)) return false\n\n\t\tconst parentPolygonInShapeShape = editor\n\t\t\t.getShapePageTransform(childId)\n\t\t\t.clone()\n\t\t\t.invert()\n\t\t\t.applyToPoints(parentPagePolygon)\n\n\t\tconst geometry = editor.getShapeGeometry(childId)\n\n\t\treturn doesGeometryOverlapPolygon(geometry, parentPolygonInShapeShape)\n\t})\n}\n\n/**\n * @public\n */\nexport function doesGeometryOverlapPolygon(\n\tgeometry: Geometry2d,\n\tparentCornersInShapeSpace: Vec[]\n): boolean {\n\t// If the child is a group, check if any of its children overlap the box\n\tif (geometry instanceof Group2d) {\n\t\treturn geometry.children.some((childGeometry) =>\n\t\t\tdoesGeometryOverlapPolygon(childGeometry, parentCornersInShapeSpace)\n\t\t)\n\t}\n\n\t// Otherwise, check if the geometry overlaps the box\n\tconst { vertices, center, isFilled, isEmptyLabel, isClosed } = geometry\n\n\t// We'll do things in order of cheapest to most expensive checks\n\n\t// Skip empty labels\n\tif (isEmptyLabel) return false\n\n\t// If any of the shape's vertices are inside the occluder, it's inside\n\tif (vertices.some((v) => pointInPolygon(v, parentCornersInShapeSpace))) {\n\t\treturn true\n\t}\n\n\t// If the shape is filled and closed and its center is inside the parent, it's inside\n\tif (isClosed) {\n\t\tif (isFilled) {\n\t\t\t// If closed and filled, check if the center is inside the parent\n\t\t\tif (pointInPolygon(center, parentCornersInShapeSpace)) {\n\t\t\t\treturn true\n\t\t\t}\n\n\t\t\t// ..then, slightly more expensive check, see the shape covers the entire parent but not its center\n\t\t\tif (parentCornersInShapeSpace.every((v) => pointInPolygon(v, vertices))) {\n\t\t\t\treturn true\n\t\t\t}\n\t\t}\n\n\t\t// If any the shape's vertices intersect the edge of the occluder, it's inside.\n\t\t// for example when a rotated rectangle is moved over the corner of a parent rectangle\n\t\t// If the child shape is closed, intersect as a polygon\n\t\tif (polygonsIntersect(parentCornersInShapeSpace, vertices)) {\n\t\t\treturn true\n\t\t}\n\t} else {\n\t\t// if the child shape is not closed, intersect as a polyline\n\t\tif (polygonIntersectsPolyline(parentCornersInShapeSpace, vertices)) {\n\t\t\treturn true\n\t\t}\n\t}\n\n\t// If none of the above checks passed, the shape is outside the parent\n\treturn false\n}\n\n/**\n * Get the shapes that will be reparented to new parents when the shapes are dropped.\n *\n * @param editor - The editor instance.\n * @param shapes - The shapes to check.\n * @param cb - A callback to filter out certain shapes.\n * @returns An object with the shapes that will be reparented to new parents and the shapes that will be reparented to the page or their ancestral group.\n *\n * @public\n */\nexport function getDroppedShapesToNewParents(\n\teditor: Editor,\n\tshapes: Set<TLShape> | TLShape[],\n\tcb?: (shape: TLShape, parent: TLShape) => boolean\n) {\n\tconst shapesToActuallyCheck = new Set<TLShape>(shapes)\n\tconst movingGroups = new Set<TLGroupShape>()\n\n\tfor (const shape of shapes) {\n\t\tconst parent = editor.getShapeParent(shape)\n\t\tif (parent && editor.isShapeOfType<TLGroupShape>(parent, 'group')) {\n\t\t\tif (!movingGroups.has(parent)) {\n\t\t\t\tmovingGroups.add(parent)\n\t\t\t}\n\t\t}\n\t}\n\n\t// If all of a group's children are moving, then move the group instead\n\tfor (const movingGroup of movingGroups) {\n\t\tconst children = compact(\n\t\t\teditor.getSortedChildIdsForParent(movingGroup).map((id) => editor.getShape(id))\n\t\t)\n\t\tfor (const child of children) {\n\t\t\tshapesToActuallyCheck.delete(child)\n\t\t}\n\t\tshapesToActuallyCheck.add(movingGroup)\n\t}\n\n\t// this could be cached and passed in\n\tconst shapeGroupIds = new Map<TLShapeId, TLShapeId | undefined>()\n\n\tconst reparenting = new Map<TLShapeId, TLShape[]>()\n\n\tconst remainingShapesToReparent = new Set(shapesToActuallyCheck)\n\n\tconst potentialParentShapes = editor\n\t\t.getCurrentPageShapesSorted()\n\t\t// filter out any shapes that aren't frames or that are included among the provided shapes\n\t\t.filter(\n\t\t\t(s) =>\n\t\t\t\teditor.getShapeUtil(s).canReceiveNewChildrenOfType?.(s, s.type) &&\n\t\t\t\t!remainingShapesToReparent.has(s)\n\t\t)\n\n\tparentCheck: for (let i = potentialParentShapes.length - 1; i >= 0; i--) {\n\t\tconst parentShape = potentialParentShapes[i]\n\t\tconst parentShapeContainingGroupId = editor.findShapeAncestor(parentShape, (s) =>\n\t\t\teditor.isShapeOfType<TLGroupShape>(s, 'group')\n\t\t)?.id\n\n\t\tconst parentGeometry = editor.getShapeGeometry(parentShape)\n\t\tconst parentPageTransform = editor.getShapePageTransform(parentShape)\n\t\tconst parentPageMaskVertices = editor.getShapeMask(parentShape)\n\t\tconst parentPageCorners = parentPageTransform.applyToPoints(parentGeometry.vertices)\n\t\tconst parentPagePolygon = parentPageMaskVertices\n\t\t\t? intersectPolygonPolygon(parentPageMaskVertices, parentPageCorners)\n\t\t\t: parentPageCorners\n\n\t\tif (!parentPagePolygon) continue parentCheck\n\n\t\tconst childrenToReparent = []\n\n\t\t// For each of the dropping shapes...\n\t\tshapeCheck: for (const shape of remainingShapesToReparent) {\n\t\t\t// Don't reparent a frame to itself\n\t\t\tif (parentShape.id === shape.id) continue shapeCheck\n\n\t\t\t// Use the callback to filter out certain shapes\n\t\t\tif (cb && !cb(shape, parentShape)) continue shapeCheck\n\n\t\t\tif (!shapeGroupIds.has(shape.id)) {\n\t\t\t\tshapeGroupIds.set(\n\t\t\t\t\tshape.id,\n\t\t\t\t\teditor.findShapeAncestor(shape, (s) => editor.isShapeOfType<TLGroupShape>(s, 'group'))?.id\n\t\t\t\t)\n\t\t\t}\n\n\t\t\tconst shapeGroupId = shapeGroupIds.get(shape.id)\n\n\t\t\t// Are the shape and the parent part of different groups?\n\t\t\tif (shapeGroupId !== parentShapeContainingGroupId) continue shapeCheck\n\n\t\t\t// Is the shape is actually the ancestor of the parent?\n\t\t\tif (editor.findShapeAncestor(parentShape, (s) => shape.id === s.id)) continue shapeCheck\n\n\t\t\t// Convert the parent polygon to the shape's space\n\t\t\tconst parentPolygonInShapeSpace = editor\n\t\t\t\t.getShapePageTransform(shape)\n\t\t\t\t.clone()\n\t\t\t\t.invert()\n\t\t\t\t.applyToPoints(parentPagePolygon)\n\n\t\t\t// If the shape overlaps the parent polygon, reparent it to that parent\n\t\t\tif (doesGeometryOverlapPolygon(editor.getShapeGeometry(shape), parentPolygonInShapeSpace)) {\n\t\t\t\t// Use the util to check if the shape can be reparented to the parent\n\t\t\t\tif (\n\t\t\t\t\t!editor.getShapeUtil(parentShape).canReceiveNewChildrenOfType?.(parentShape, shape.type)\n\t\t\t\t)\n\t\t\t\t\tcontinue shapeCheck\n\n\t\t\t\tif (shape.parentId !== parentShape.id) {\n\t\t\t\t\tchildrenToReparent.push(shape)\n\t\t\t\t}\n\t\t\t\tremainingShapesToReparent.delete(shape)\n\t\t\t\tcontinue shapeCheck\n\t\t\t}\n\t\t}\n\n\t\tif (childrenToReparent.length) {\n\t\t\treparenting.set(parentShape.id, childrenToReparent)\n\t\t}\n\t}\n\n\treturn {\n\t\t// these are the shapes that will be reparented to new parents\n\t\treparenting,\n\t\t// these are the shapes that will be reparented to the page or their ancestral group\n\t\tremainingShapesToReparent,\n\t}\n}\n"],
5
+ "mappings": "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",
6
+ "names": ["import_utils", "shapeIds"]
7
+ }
@@ -22,10 +22,10 @@ __export(version_exports, {
22
22
  version: () => version
23
23
  });
24
24
  module.exports = __toCommonJS(version_exports);
25
- const version = "3.14.0-canary.f907ed7d9ee5";
25
+ const version = "3.14.0-canary.fb0390b30559";
26
26
  const publishDates = {
27
27
  major: "2024-09-13T14:36:29.063Z",
28
- minor: "2025-06-13T07:34:19.323Z",
29
- patch: "2025-06-13T07:34:19.323Z"
28
+ minor: "2025-07-03T08:18:11.921Z",
29
+ patch: "2025-07-03T08:18:11.921Z"
30
30
  };
31
31
  //# sourceMappingURL=version.js.map
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../src/version.ts"],
4
- "sourcesContent": ["// This file is automatically generated by internal/scripts/refresh-assets.ts.\n// Do not edit manually. Or do, I'm a comment, not a cop.\n\nexport const version = '3.14.0-canary.f907ed7d9ee5'\nexport const publishDates = {\n\tmajor: '2024-09-13T14:36:29.063Z',\n\tminor: '2025-06-13T07:34:19.323Z',\n\tpatch: '2025-06-13T07:34:19.323Z',\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 = '3.14.0-canary.fb0390b30559'\nexport const publishDates = {\n\tmajor: '2024-09-13T14:36:29.063Z',\n\tminor: '2025-07-03T08:18:11.921Z',\n\tpatch: '2025-07-03T08:18:11.921Z',\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
  }
@@ -1631,6 +1631,13 @@ export declare class Editor extends EventEmitter<TLEventMap> {
1631
1631
  * @public
1632
1632
  */
1633
1633
  getSelectionPageBounds(): Box | null;
1634
+ /**
1635
+ * The bounds of the selection bounding box in the current page space.
1636
+ *
1637
+ * @readonly
1638
+ * @public
1639
+ */
1640
+ getSelectionScreenBounds(): Box | undefined;
1634
1641
  /* Excluded from this release type: getShapesSharedRotation */
1635
1642
  /**
1636
1643
  * The rotation of the selection bounding box in the current page space.
@@ -2904,6 +2911,8 @@ export declare class Editor extends EventEmitter<TLEventMap> {
2904
2911
  * @public
2905
2912
  */
2906
2913
  getShapeAndDescendantIds(ids: TLShapeId[]): Set<TLShapeId>;
2914
+ /** @deprecated Use {@link Editor.getDraggingOverShape} instead */
2915
+ getDroppingOverShape(point: Vec, droppingShapes: TLShape[]): TLShape | undefined;
2907
2916
  /**
2908
2917
  * Get the shape that some shapes should be dropped on at a given point.
2909
2918
  *
@@ -2914,7 +2923,7 @@ export declare class Editor extends EventEmitter<TLEventMap> {
2914
2923
  *
2915
2924
  * @public
2916
2925
  */
2917
- getDroppingOverShape(point: VecLike, droppingShapes?: TLShape[]): TLUnknownShape | undefined;
2926
+ getDraggingOverShape(point: Vec, droppingShapes: TLShape[]): TLShape | undefined;
2918
2927
  /**
2919
2928
  * Get the shape that should be selected when you click on a given shape, assuming there is
2920
2929
  * nothing already selected. It will not return anything higher than or including the current
@@ -3255,6 +3264,22 @@ export declare class Editor extends EventEmitter<TLEventMap> {
3255
3264
  * @public
3256
3265
  */
3257
3266
  getInitialMetaForShape(_shape: TLShape): JsonObject;
3267
+ /**
3268
+ * Get whether the provided shape can be created.
3269
+ *
3270
+ * @param shape - The shape or shape IDs to check.
3271
+ *
3272
+ * @public
3273
+ */
3274
+ canCreateShape<T extends TLUnknownShape>(shape: OptionalKeys<TLShapePartial<T>, 'id'> | T['id']): boolean;
3275
+ /**
3276
+ * Get whether the provided shapes can be created.
3277
+ *
3278
+ * @param shapes - The shapes or shape IDs to create.
3279
+ *
3280
+ * @public
3281
+ */
3282
+ canCreateShapes<T extends TLUnknownShape>(shapes: (OptionalKeys<TLShapePartial<T>, 'id'> | T['id'])[]): boolean;
3258
3283
  /**
3259
3284
  * Create a single shape.
3260
3285
  *
@@ -3601,6 +3626,12 @@ export declare class Editor extends EventEmitter<TLEventMap> {
3601
3626
  * @param info - Info about the external content.
3602
3627
  */
3603
3628
  putExternalContent<E>(info: TLExternalContent<E>): Promise<void>;
3629
+ /**
3630
+ * Handle replacing external content.
3631
+ *
3632
+ * @param info - Info about the external content.
3633
+ */
3634
+ replaceExternalContent<E>(info: TLExternalContent<E>): Promise<void>;
3604
3635
  /**
3605
3636
  * Get content that can be exported for the given shape ids.
3606
3637
  *
@@ -4067,6 +4098,7 @@ export declare abstract class Geometry2d {
4067
4098
  isFilled: boolean;
4068
4099
  isClosed: boolean;
4069
4100
  isLabel: boolean;
4101
+ isEmptyLabel: boolean;
4070
4102
  isInternal: boolean;
4071
4103
  debugColor?: string;
4072
4104
  ignore?: boolean;
@@ -4158,6 +4190,21 @@ export declare function getCursor(cursor: TLCursorType, rotation?: number, color
4158
4190
  /** @public */
4159
4191
  export declare function getDefaultCdnBaseUrl(): string;
4160
4192
 
4193
+ /**
4194
+ * Get the shapes that will be reparented to new parents when the shapes are dropped.
4195
+ *
4196
+ * @param editor - The editor instance.
4197
+ * @param shapes - The shapes to check.
4198
+ * @param cb - A callback to filter out certain shapes.
4199
+ * @returns An object with the shapes that will be reparented to new parents and the shapes that will be reparented to the page or their ancestral group.
4200
+ *
4201
+ * @public
4202
+ */
4203
+ export declare function getDroppedShapesToNewParents(editor: Editor, shapes: Set<TLShape> | TLShape[], cb?: (shape: TLShape, parent: TLShape) => boolean): {
4204
+ remainingShapesToReparent: Set<TLShape>;
4205
+ reparenting: Map<TLShapeId, TLShape[]>;
4206
+ };
4207
+
4161
4208
  /** @public */
4162
4209
  export declare function getFontsFromRichText(editor: Editor, richText: TLRichText, initialState: RichTextFontVisitorState): TLFontFace[];
4163
4210
 
@@ -4511,6 +4558,20 @@ export declare function intersectPolygonPolygon(polygonA: VecLike[], polygonB: V
4511
4558
  */
4512
4559
  export declare const isSafeFloat: (n: number) => boolean;
4513
4560
 
4561
+ /**
4562
+ * Reparents shapes that are no longer contained within their parent shapes.
4563
+ * todo: rename me to something more descriptive, like `reparentOccludedShapes` or `reparentAutoDroppedShapes`
4564
+ *
4565
+ * @param editor - The editor instance.
4566
+ * @param shapeIds - The IDs of the shapes to reparent.
4567
+ * @param opts - Optional options, including a callback to filter out certain parents, such as when removing a frame.
4568
+ *
4569
+ * @public
4570
+ */
4571
+ export declare function kickoutOccludedShapes(editor: Editor, shapeIds: TLShapeId[], opts?: {
4572
+ filter?(parent: TLShape): boolean;
4573
+ }): void;
4574
+
4514
4575
  /* Excluded from this release type: LicenseFromKeyResult */
4515
4576
 
4516
4577
  /* Excluded from this release type: LicenseInfo */
@@ -5190,14 +5251,6 @@ export declare abstract class ShapeUtil<Shape extends TLUnknownShape = TLUnknown
5190
5251
  * @public
5191
5252
  */
5192
5253
  canReceiveNewChildrenOfType(_shape: Shape, _type: TLShape['type']): boolean;
5193
- /**
5194
- * Get whether the shape can receive children of a given type.
5195
- *
5196
- * @param shape - The shape type.
5197
- * @param shapes - The shapes that are being dropped.
5198
- * @public
5199
- */
5200
- canDropShapes(_shape: Shape, _shapes: TLShape[]): boolean;
5201
5254
  /**
5202
5255
  * Get the shape as an SVG object.
5203
5256
  *
@@ -5285,7 +5338,15 @@ export declare abstract class ShapeUtil<Shape extends TLUnknownShape = TLUnknown
5285
5338
  */
5286
5339
  onCrop?(shape: Shape, info: TLCropInfo<Shape>): Omit<TLShapePartial<Shape>, 'id' | 'type'> | undefined | void;
5287
5340
  /**
5288
- * A callback called when some other shapes are dragged over this one.
5341
+ * A callback called when some other shapes are dragged into this one. This fires when the shapes are dragged over the shape for the first time.
5342
+ *
5343
+ * @param shape - The shape.
5344
+ * @param shapes - The shapes that are being dragged in.
5345
+ * @public
5346
+ */
5347
+ onDragShapesIn?(shape: Shape, shapes: TLShape[], info: TLDragShapesInInfo): void;
5348
+ /**
5349
+ * A callback called when some other shapes are dragged over this one. This fires when the shapes are dragged over the shape for the first time (after the onDragShapesIn callback), and again on every update while the shapes are being dragged.
5289
5350
  *
5290
5351
  * @example
5291
5352
  *
@@ -5299,7 +5360,7 @@ export declare abstract class ShapeUtil<Shape extends TLUnknownShape = TLUnknown
5299
5360
  * @param shapes - The shapes that are being dragged over this one.
5300
5361
  * @public
5301
5362
  */
5302
- onDragShapesOver?(shape: Shape, shapes: TLShape[]): void;
5363
+ onDragShapesOver?(shape: Shape, shapes: TLShape[], info: TLDragShapesOverInfo): void;
5303
5364
  /**
5304
5365
  * A callback called when some other shapes are dragged out of this one.
5305
5366
  *
@@ -5307,7 +5368,7 @@ export declare abstract class ShapeUtil<Shape extends TLUnknownShape = TLUnknown
5307
5368
  * @param shapes - The shapes that are being dragged out.
5308
5369
  * @public
5309
5370
  */
5310
- onDragShapesOut?(shape: Shape, shapes: TLShape[]): void;
5371
+ onDragShapesOut?(shape: Shape, shapes: TLShape[], info: TLDragShapesOutInfo): void;
5311
5372
  /**
5312
5373
  * A callback called when some other shapes are dropped over this one.
5313
5374
  *
@@ -5315,7 +5376,7 @@ export declare abstract class ShapeUtil<Shape extends TLUnknownShape = TLUnknown
5315
5376
  * @param shapes - The shapes that are being dropped over this one.
5316
5377
  * @public
5317
5378
  */
5318
- onDropShapesOver?(shape: Shape, shapes: TLShape[]): void;
5379
+ onDropShapesOver?(shape: Shape, shapes: TLShape[], info: TLDropShapesOverInfo): void;
5319
5380
  /**
5320
5381
  * A callback called when a shape starts being resized.
5321
5382
  *
@@ -5617,7 +5678,7 @@ export declare abstract class StateNode implements Partial<TLEventHandlers> {
5617
5678
  transition(id: string, info?: any): this;
5618
5679
  handleEvent(info: Exclude<TLEventInfo, TLPinchEventInfo>): void;
5619
5680
  enter(info: any, from: string): void;
5620
- exit(info: any, from: string): void;
5681
+ exit(info: any, to: string): void;
5621
5682
  /**
5622
5683
  * This is a hack / escape hatch that will tell the editor to
5623
5684
  * report a different state as active (in `getCurrentToolId()`) when
@@ -5724,43 +5785,15 @@ export declare const TAB_ID: string;
5724
5785
  /** @public */
5725
5786
  export declare class TextManager {
5726
5787
  editor: Editor;
5727
- private baseElem;
5788
+ private elm;
5789
+ private defaultStyles;
5728
5790
  constructor(editor: Editor);
5729
- measureText(textToMeasure: string, opts: {
5730
- /**
5731
- * When maxWidth is a number, the text will be wrapped to that maxWidth. When maxWidth
5732
- * is null, the text will be measured without wrapping, but explicit line breaks and
5733
- * space are preserved.
5734
- */
5735
- maxWidth: null | number;
5736
- disableOverflowWrapBreaking?: boolean;
5737
- fontFamily: string;
5738
- fontSize: number;
5739
- fontStyle: string;
5740
- fontWeight: string;
5741
- lineHeight: number;
5742
- minWidth?: null | number;
5743
- padding: string;
5744
- }): BoxModel & {
5791
+ dispose(): void;
5792
+ private resetElmStyles;
5793
+ measureText(textToMeasure: string, opts: TLMeasureTextOpts): BoxModel & {
5745
5794
  scrollWidth: number;
5746
5795
  };
5747
- measureHtml(html: string, opts: {
5748
- /**
5749
- * When maxWidth is a number, the text will be wrapped to that maxWidth. When maxWidth
5750
- * is null, the text will be measured without wrapping, but explicit line breaks and
5751
- * space are preserved.
5752
- */
5753
- maxWidth: null | number;
5754
- disableOverflowWrapBreaking?: boolean;
5755
- fontFamily: string;
5756
- fontSize: number;
5757
- fontStyle: string;
5758
- fontWeight: string;
5759
- lineHeight: number;
5760
- minWidth?: null | number;
5761
- otherStyles?: Record<string, string>;
5762
- padding: string;
5763
- }): BoxModel & {
5796
+ measureHtml(html: string, opts: TLMeasureTextOpts): BoxModel & {
5764
5797
  scrollWidth: number;
5765
5798
  };
5766
5799
  /**
@@ -6017,6 +6050,7 @@ export declare interface TLCropInfo<T extends TLShape> {
6017
6050
  w: number;
6018
6051
  };
6019
6052
  initialShape: T;
6053
+ aspectRatioLocked?: boolean;
6020
6054
  }
6021
6055
 
6022
6056
  /** @public */
@@ -6075,6 +6109,29 @@ export declare interface TLDeepLinkOptions {
6075
6109
  onChange?(url: URL, editor: Editor): void;
6076
6110
  }
6077
6111
 
6112
+ /** @public */
6113
+ export declare interface TLDragShapesInInfo {
6114
+ initialDraggingOverShapeId: null | TLShapeId;
6115
+ prevDraggingOverShapeId: null | TLShapeId;
6116
+ initialParentIds: Map<TLShapeId, TLParentId>;
6117
+ initialIndices: Map<TLShapeId, IndexKey>;
6118
+ }
6119
+
6120
+ /** @public */
6121
+ export declare interface TLDragShapesOutInfo {
6122
+ nextDraggingOverShapeId: null | TLShapeId;
6123
+ initialDraggingOverShapeId: null | TLShapeId;
6124
+ initialParentIds: Map<TLShapeId, TLParentId>;
6125
+ initialIndices: Map<TLShapeId, IndexKey>;
6126
+ }
6127
+
6128
+ /** @public */
6129
+ export declare interface TLDragShapesOverInfo {
6130
+ initialDraggingOverShapeId: null | TLShapeId;
6131
+ initialParentIds: Map<TLShapeId, TLParentId>;
6132
+ initialIndices: Map<TLShapeId, IndexKey>;
6133
+ }
6134
+
6078
6135
  /** @public @react */
6079
6136
  export declare const TldrawEditor: React_2.NamedExoticComponent<TldrawEditorProps>;
6080
6137
 
@@ -6322,6 +6379,13 @@ export declare interface TldrawOptions {
6322
6379
  readonly branding?: string;
6323
6380
  }
6324
6381
 
6382
+ /** @public */
6383
+ export declare interface TLDropShapesOverInfo {
6384
+ initialDraggingOverShapeId: null | TLShapeId;
6385
+ initialParentIds: Map<TLShapeId, TLParentId>;
6386
+ initialIndices: Map<TLShapeId, IndexKey>;
6387
+ }
6388
+
6325
6389
  /** @public */
6326
6390
  export declare interface TLEditorComponents {
6327
6391
  Background?: ComponentType | null;
@@ -6544,6 +6608,10 @@ export declare interface TLEventMap {
6544
6608
  };
6545
6609
  shapeId: TLShapeId;
6546
6610
  }];
6611
+ 'created-shapes': [TLRecord[]];
6612
+ 'edited-shapes': [TLRecord[]];
6613
+ 'deleted-shapes': [TLShapeId[]];
6614
+ edit: [];
6547
6615
  }
6548
6616
 
6549
6617
  /** @public */
@@ -6574,7 +6642,7 @@ export declare type TLExportType = 'jpeg' | 'png' | 'svg' | 'webp';
6574
6642
  export declare type TLExternalAsset = TLFileExternalAsset | TLUrlExternalAsset;
6575
6643
 
6576
6644
  /** @public */
6577
- export declare type TLExternalContent<EmbedDefinition> = TLEmbedExternalContent<EmbedDefinition> | TLExcalidrawExternalContent | TLFilesExternalContent | TLSvgTextExternalContent | TLTextExternalContent | TLTldrawExternalContent | TLUrlExternalContent;
6645
+ export declare type TLExternalContent<EmbedDefinition> = TLEmbedExternalContent<EmbedDefinition> | TLExcalidrawExternalContent | TLFileReplaceExternalContent | TLFilesExternalContent | TLSvgTextExternalContent | TLTextExternalContent | TLTldrawExternalContent | TLUrlExternalContent;
6578
6646
 
6579
6647
  /** @public */
6580
6648
  export declare type TLExternalContentSource = TLErrorExternalContentSource | TLExcalidrawExternalContentSource | TLTextExternalContentSource | TLTldrawExternalContentSource;
@@ -6586,11 +6654,19 @@ export declare interface TLFileExternalAsset {
6586
6654
  assetId?: TLAssetId;
6587
6655
  }
6588
6656
 
6657
+ /** @public */
6658
+ export declare interface TLFileReplaceExternalContent extends TLBaseExternalContent {
6659
+ type: 'file-replace';
6660
+ file: File;
6661
+ shapeId: TLShapeId;
6662
+ isImage: boolean;
6663
+ }
6664
+
6589
6665
  /** @public */
6590
6666
  export declare interface TLFilesExternalContent extends TLBaseExternalContent {
6591
6667
  type: 'files';
6592
6668
  files: File[];
6593
- ignoreParent: boolean;
6669
+ ignoreParent?: boolean;
6594
6670
  }
6595
6671
 
6596
6672
  /**
@@ -6785,6 +6861,27 @@ export declare interface TLLoadSnapshotOptions {
6785
6861
  forceOverwriteSessionState?: boolean;
6786
6862
  }
6787
6863
 
6864
+ /** @public */
6865
+ export declare interface TLMeasureTextOpts {
6866
+ fontStyle: string;
6867
+ fontWeight: string;
6868
+ fontFamily: string;
6869
+ fontSize: number;
6870
+ /** This must be a number, e.g. 1.35, not a pixel value. */
6871
+ lineHeight: number;
6872
+ /**
6873
+ * When maxWidth is a number, the text will be wrapped to that maxWidth. When maxWidth
6874
+ * is null, the text will be measured without wrapping, but explicit line breaks and
6875
+ * space are preserved.
6876
+ */
6877
+ maxWidth: null | number;
6878
+ minWidth?: null | number;
6879
+ padding: string;
6880
+ otherStyles?: Record<string, string>;
6881
+ disableOverflowWrapBreaking?: boolean;
6882
+ measureScrollWidth?: boolean;
6883
+ }
6884
+
6788
6885
  /** @public */
6789
6886
  export declare interface TLMeasureTextSpanOpts {
6790
6887
  overflow: 'truncate-clip' | 'truncate-ellipsis' | 'wrap';
@@ -6798,6 +6895,7 @@ export declare interface TLMeasureTextSpanOpts {
6798
6895
  lineHeight: number;
6799
6896
  textAlign: TLDefaultHorizontalAlignStyle;
6800
6897
  otherStyles?: Record<string, string>;
6898
+ measureScrollWidth?: boolean;
6801
6899
  }
6802
6900
 
6803
6901
  /** @public */
@@ -7459,6 +7557,7 @@ export declare class TransformedGeometry2d extends Geometry2d {
7459
7557
  /** @public */
7460
7558
  export declare interface TransformedGeometry2dOptions {
7461
7559
  isLabel?: boolean;
7560
+ isEmptyLabel?: boolean;
7462
7561
  isInternal?: boolean;
7463
7562
  debugColor?: string;
7464
7563
  ignore?: boolean;