@tldraw/editor 3.16.0-next.c30b1b5e551a → 3.16.0-next.e57e478c23e0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist-cjs/index.d.ts +134 -110
- package/dist-cjs/index.js +3 -5
- package/dist-cjs/index.js.map +2 -2
- package/dist-cjs/lib/TldrawEditor.js +8 -6
- package/dist-cjs/lib/TldrawEditor.js.map +2 -2
- package/dist-cjs/lib/components/MenuClickCapture.js +0 -5
- package/dist-cjs/lib/components/MenuClickCapture.js.map +2 -2
- package/dist-cjs/lib/components/Shape.js +7 -10
- package/dist-cjs/lib/components/Shape.js.map +2 -2
- package/dist-cjs/lib/components/default-components/DefaultCanvas.js +4 -23
- package/dist-cjs/lib/components/default-components/DefaultCanvas.js.map +2 -2
- package/dist-cjs/lib/components/default-components/DefaultCollaboratorHint.js +1 -1
- package/dist-cjs/lib/components/default-components/DefaultCollaboratorHint.js.map +1 -1
- package/dist-cjs/lib/components/default-components/DefaultErrorFallback.js +1 -1
- package/dist-cjs/lib/components/default-components/DefaultErrorFallback.js.map +2 -2
- package/dist-cjs/lib/components/default-components/DefaultScribble.js +1 -1
- package/dist-cjs/lib/components/default-components/DefaultScribble.js.map +2 -2
- package/dist-cjs/lib/components/default-components/DefaultShapeIndicator.js +9 -1
- package/dist-cjs/lib/components/default-components/DefaultShapeIndicator.js.map +2 -2
- package/dist-cjs/lib/config/TLUserPreferences.js +9 -3
- package/dist-cjs/lib/config/TLUserPreferences.js.map +2 -2
- package/dist-cjs/lib/editor/Editor.js +77 -133
- package/dist-cjs/lib/editor/Editor.js.map +2 -2
- package/dist-cjs/lib/editor/managers/UserPreferencesManager/UserPreferencesManager.js +9 -4
- package/dist-cjs/lib/editor/managers/UserPreferencesManager/UserPreferencesManager.js.map +2 -2
- package/dist-cjs/lib/editor/shapes/ShapeUtil.js +13 -0
- package/dist-cjs/lib/editor/shapes/ShapeUtil.js.map +2 -2
- package/dist-cjs/lib/editor/types/misc-types.js.map +1 -1
- package/dist-cjs/lib/exports/getSvgJsx.js +35 -16
- package/dist-cjs/lib/exports/getSvgJsx.js.map +2 -2
- package/dist-cjs/lib/hooks/useCanvasEvents.js +31 -25
- package/dist-cjs/lib/hooks/useCanvasEvents.js.map +2 -2
- package/dist-cjs/lib/hooks/usePassThroughMouseOverEvents.js +4 -1
- package/dist-cjs/lib/hooks/usePassThroughMouseOverEvents.js.map +2 -2
- package/dist-cjs/lib/hooks/usePassThroughWheelEvents.js +4 -1
- package/dist-cjs/lib/hooks/usePassThroughWheelEvents.js.map +2 -2
- package/dist-cjs/lib/{utils/nearestMultiple.js → hooks/useStateAttribute.js} +15 -14
- package/dist-cjs/lib/hooks/useStateAttribute.js.map +7 -0
- package/dist-cjs/lib/license/LicenseManager.js +17 -22
- package/dist-cjs/lib/license/LicenseManager.js.map +2 -2
- package/dist-cjs/lib/license/LicenseProvider.js +5 -0
- package/dist-cjs/lib/license/LicenseProvider.js.map +2 -2
- package/dist-cjs/lib/license/Watermark.js +8 -8
- package/dist-cjs/lib/license/Watermark.js.map +1 -1
- package/dist-cjs/lib/license/useLicenseManagerState.js.map +2 -2
- package/dist-cjs/lib/options.js +7 -0
- package/dist-cjs/lib/options.js.map +2 -2
- package/dist-cjs/lib/primitives/Box.js +3 -0
- package/dist-cjs/lib/primitives/Box.js.map +2 -2
- package/dist-cjs/lib/primitives/Vec.js +0 -4
- package/dist-cjs/lib/primitives/Vec.js.map +2 -2
- package/dist-cjs/lib/primitives/geometry/Geometry2d.js +26 -18
- package/dist-cjs/lib/primitives/geometry/Geometry2d.js.map +2 -2
- package/dist-cjs/lib/primitives/geometry/Group2d.js +3 -0
- package/dist-cjs/lib/primitives/geometry/Group2d.js.map +2 -2
- package/dist-cjs/lib/utils/EditorAtom.js +45 -0
- package/dist-cjs/lib/utils/EditorAtom.js.map +7 -0
- package/dist-cjs/lib/utils/reparenting.js +2 -35
- package/dist-cjs/lib/utils/reparenting.js.map +3 -3
- package/dist-cjs/version.js +3 -3
- package/dist-cjs/version.js.map +1 -1
- package/dist-esm/index.d.mts +134 -110
- package/dist-esm/index.mjs +3 -5
- package/dist-esm/index.mjs.map +2 -2
- package/dist-esm/lib/TldrawEditor.mjs +8 -6
- package/dist-esm/lib/TldrawEditor.mjs.map +2 -2
- package/dist-esm/lib/components/MenuClickCapture.mjs +0 -5
- package/dist-esm/lib/components/MenuClickCapture.mjs.map +2 -2
- package/dist-esm/lib/components/Shape.mjs +7 -10
- package/dist-esm/lib/components/Shape.mjs.map +2 -2
- package/dist-esm/lib/components/default-components/DefaultCanvas.mjs +4 -23
- package/dist-esm/lib/components/default-components/DefaultCanvas.mjs.map +2 -2
- package/dist-esm/lib/components/default-components/DefaultCollaboratorHint.mjs +1 -1
- package/dist-esm/lib/components/default-components/DefaultCollaboratorHint.mjs.map +1 -1
- package/dist-esm/lib/components/default-components/DefaultErrorFallback.mjs +1 -1
- package/dist-esm/lib/components/default-components/DefaultErrorFallback.mjs.map +2 -2
- package/dist-esm/lib/components/default-components/DefaultScribble.mjs +1 -1
- package/dist-esm/lib/components/default-components/DefaultScribble.mjs.map +2 -2
- package/dist-esm/lib/components/default-components/DefaultShapeIndicator.mjs +9 -1
- package/dist-esm/lib/components/default-components/DefaultShapeIndicator.mjs.map +2 -2
- package/dist-esm/lib/config/TLUserPreferences.mjs +9 -3
- package/dist-esm/lib/config/TLUserPreferences.mjs.map +2 -2
- package/dist-esm/lib/editor/Editor.mjs +77 -133
- package/dist-esm/lib/editor/Editor.mjs.map +2 -2
- package/dist-esm/lib/editor/managers/UserPreferencesManager/UserPreferencesManager.mjs +9 -4
- package/dist-esm/lib/editor/managers/UserPreferencesManager/UserPreferencesManager.mjs.map +2 -2
- package/dist-esm/lib/editor/shapes/ShapeUtil.mjs +13 -0
- package/dist-esm/lib/editor/shapes/ShapeUtil.mjs.map +2 -2
- package/dist-esm/lib/exports/getSvgJsx.mjs +36 -16
- package/dist-esm/lib/exports/getSvgJsx.mjs.map +2 -2
- package/dist-esm/lib/hooks/useCanvasEvents.mjs +32 -26
- package/dist-esm/lib/hooks/useCanvasEvents.mjs.map +2 -2
- package/dist-esm/lib/hooks/usePassThroughMouseOverEvents.mjs +4 -1
- package/dist-esm/lib/hooks/usePassThroughMouseOverEvents.mjs.map +2 -2
- package/dist-esm/lib/hooks/usePassThroughWheelEvents.mjs +4 -1
- package/dist-esm/lib/hooks/usePassThroughWheelEvents.mjs.map +2 -2
- package/dist-esm/lib/hooks/useStateAttribute.mjs +15 -0
- package/dist-esm/lib/hooks/useStateAttribute.mjs.map +7 -0
- package/dist-esm/lib/license/LicenseManager.mjs +17 -22
- package/dist-esm/lib/license/LicenseManager.mjs.map +2 -2
- package/dist-esm/lib/license/LicenseProvider.mjs +5 -0
- package/dist-esm/lib/license/LicenseProvider.mjs.map +2 -2
- package/dist-esm/lib/license/Watermark.mjs +8 -8
- package/dist-esm/lib/license/Watermark.mjs.map +1 -1
- package/dist-esm/lib/license/useLicenseManagerState.mjs.map +2 -2
- package/dist-esm/lib/options.mjs +7 -0
- package/dist-esm/lib/options.mjs.map +2 -2
- package/dist-esm/lib/primitives/Box.mjs +4 -1
- package/dist-esm/lib/primitives/Box.mjs.map +2 -2
- package/dist-esm/lib/primitives/Vec.mjs +0 -4
- package/dist-esm/lib/primitives/Vec.mjs.map +2 -2
- package/dist-esm/lib/primitives/geometry/Geometry2d.mjs +29 -19
- package/dist-esm/lib/primitives/geometry/Geometry2d.mjs.map +2 -2
- package/dist-esm/lib/primitives/geometry/Group2d.mjs +3 -0
- package/dist-esm/lib/primitives/geometry/Group2d.mjs.map +2 -2
- package/dist-esm/lib/utils/EditorAtom.mjs +25 -0
- package/dist-esm/lib/utils/EditorAtom.mjs.map +7 -0
- package/dist-esm/lib/utils/reparenting.mjs +3 -40
- package/dist-esm/lib/utils/reparenting.mjs.map +2 -2
- package/dist-esm/version.mjs +3 -3
- package/dist-esm/version.mjs.map +1 -1
- package/editor.css +301 -288
- package/package.json +14 -37
- package/src/index.ts +3 -9
- package/src/lib/TldrawEditor.tsx +13 -17
- package/src/lib/components/MenuClickCapture.tsx +0 -8
- package/src/lib/components/Shape.tsx +6 -12
- package/src/lib/components/default-components/DefaultCanvas.tsx +5 -22
- package/src/lib/components/default-components/DefaultCollaboratorHint.tsx +1 -1
- package/src/lib/components/default-components/DefaultErrorFallback.tsx +1 -1
- package/src/lib/components/default-components/DefaultScribble.tsx +1 -1
- package/src/lib/components/default-components/DefaultShapeIndicator.tsx +5 -1
- package/src/lib/config/TLUserPreferences.ts +8 -1
- package/src/lib/editor/Editor.test.ts +12 -11
- package/src/lib/editor/Editor.ts +108 -193
- package/src/lib/editor/managers/ClickManager/ClickManager.test.ts +15 -14
- package/src/lib/editor/managers/EdgeScrollManager/EdgeScrollManager.test.ts +16 -15
- package/src/lib/editor/managers/FocusManager/FocusManager.test.ts +49 -48
- package/src/lib/editor/managers/FontManager/FontManager.test.ts +24 -23
- package/src/lib/editor/managers/HistoryManager/HistoryManager.test.ts +7 -6
- package/src/lib/editor/managers/ScribbleManager/ScribbleManager.test.ts +12 -11
- package/src/lib/editor/managers/SnapManager/SnapManager.test.ts +57 -50
- package/src/lib/editor/managers/TextManager/TextManager.test.ts +51 -26
- package/src/lib/editor/managers/TickManager/TickManager.test.ts +14 -13
- package/src/lib/editor/managers/UserPreferencesManager/UserPreferencesManager.test.ts +34 -26
- package/src/lib/editor/managers/UserPreferencesManager/UserPreferencesManager.ts +6 -1
- package/src/lib/editor/shapes/ShapeUtil.ts +35 -0
- package/src/lib/editor/types/misc-types.ts +54 -7
- package/src/lib/exports/getSvgJsx.test.ts +868 -0
- package/src/lib/exports/getSvgJsx.tsx +78 -21
- package/src/lib/hooks/useCanvasEvents.ts +45 -38
- package/src/lib/hooks/usePassThroughMouseOverEvents.ts +4 -1
- package/src/lib/hooks/usePassThroughWheelEvents.ts +6 -1
- package/src/lib/hooks/useStateAttribute.ts +15 -0
- package/src/lib/license/LicenseManager.test.ts +61 -52
- package/src/lib/license/LicenseManager.ts +32 -24
- package/src/lib/license/LicenseProvider.tsx +8 -0
- package/src/lib/license/Watermark.test.tsx +2 -1
- package/src/lib/license/Watermark.tsx +8 -8
- package/src/lib/license/useLicenseManagerState.ts +2 -2
- package/src/lib/options.ts +8 -0
- package/src/lib/primitives/Box.test.ts +126 -0
- package/src/lib/primitives/Box.ts +10 -1
- package/src/lib/primitives/Vec.ts +0 -5
- package/src/lib/primitives/geometry/Geometry2d.ts +49 -19
- package/src/lib/primitives/geometry/Group2d.ts +4 -0
- package/src/lib/utils/EditorAtom.ts +37 -0
- package/src/lib/utils/reparenting.ts +3 -69
- package/src/lib/utils/sync/LocalIndexedDb.test.ts +2 -1
- package/src/lib/utils/sync/TLLocalSyncClient.test.ts +15 -15
- package/src/version.ts +3 -3
- package/dist-cjs/lib/utils/nearestMultiple.js.map +0 -7
- package/dist-esm/lib/utils/nearestMultiple.mjs +0 -14
- package/dist-esm/lib/utils/nearestMultiple.mjs.map +0 -7
- package/src/lib/utils/nearestMultiple.ts +0 -13
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../src/lib/utils/EditorAtom.ts"],
|
|
4
|
+
"sourcesContent": ["import { atom, Atom } from '@tldraw/state'\nimport { WeakCache } from '@tldraw/utils'\nimport { Editor } from '../editor/Editor'\n\n/**\n * An Atom that is scoped to the lifetime of an Editor.\n *\n * This is useful for storing UI state for tldraw applications. Keeping state scoped to an editor\n * instead of stored in a global atom can prevent issues with state being shared between editors\n * when navigating between pages, or when multiple editor instances are used on the same page.\n *\n * @public\n */\nexport class EditorAtom<T> {\n\tprivate states = new WeakCache<Editor, Atom<T>>()\n\n\tconstructor(\n\t\tprivate name: string,\n\t\tprivate getInitialState: (editor: Editor) => T\n\t) {}\n\n\tgetAtom(editor: Editor): Atom<T> {\n\t\treturn this.states.get(editor, () => atom(this.name, this.getInitialState(editor)))\n\t}\n\n\tget(editor: Editor): T {\n\t\treturn this.getAtom(editor).get()\n\t}\n\n\tupdate(editor: Editor, update: (state: T) => T): T {\n\t\treturn this.getAtom(editor).update(update)\n\t}\n\n\tset(editor: Editor, state: T): T {\n\t\treturn this.getAtom(editor).set(state)\n\t}\n}\n"],
|
|
5
|
+
"mappings": ";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,mBAA2B;AAC3B,mBAA0B;AAYnB,MAAM,WAAc;AAAA,EAG1B,YACS,MACA,iBACP;AAFO;AACA;AAAA,EACN;AAAA,EALK,SAAS,IAAI,uBAA2B;AAAA,EAOhD,QAAQ,QAAyB;AAChC,WAAO,KAAK,OAAO,IAAI,QAAQ,UAAM,mBAAK,KAAK,MAAM,KAAK,gBAAgB,MAAM,CAAC,CAAC;AAAA,EACnF;AAAA,EAEA,IAAI,QAAmB;AACtB,WAAO,KAAK,QAAQ,MAAM,EAAE,IAAI;AAAA,EACjC;AAAA,EAEA,OAAO,QAAgB,QAA4B;AAClD,WAAO,KAAK,QAAQ,MAAM,EAAE,OAAO,MAAM;AAAA,EAC1C;AAAA,EAEA,IAAI,QAAgB,OAAa;AAChC,WAAO,KAAK,QAAQ,MAAM,EAAE,IAAI,KAAK;AAAA,EACtC;AACD;",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -18,16 +18,13 @@ var __copyProps = (to, from, except, desc) => {
|
|
|
18
18
|
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
19
|
var reparenting_exports = {};
|
|
20
20
|
__export(reparenting_exports, {
|
|
21
|
-
doesGeometryOverlapPolygon: () => doesGeometryOverlapPolygon,
|
|
22
21
|
getDroppedShapesToNewParents: () => getDroppedShapesToNewParents,
|
|
23
22
|
kickoutOccludedShapes: () => kickoutOccludedShapes
|
|
24
23
|
});
|
|
25
24
|
module.exports = __toCommonJS(reparenting_exports);
|
|
26
25
|
var import_state = require("@tldraw/state");
|
|
27
26
|
var import_utils = require("@tldraw/utils");
|
|
28
|
-
var import_Group2d = require("../primitives/geometry/Group2d");
|
|
29
27
|
var import_intersect = require("../primitives/intersect");
|
|
30
|
-
var import_utils2 = require("../primitives/utils");
|
|
31
28
|
function kickoutOccludedShapes(editor, shapeIds, opts) {
|
|
32
29
|
const parentsToCheck = /* @__PURE__ */ new Set();
|
|
33
30
|
for (const id of shapeIds) {
|
|
@@ -123,39 +120,9 @@ function getOverlappingShapes(editor, shape, otherShapes) {
|
|
|
123
120
|
if (!shapePageBounds || !parentPageBounds.includes(shapePageBounds)) return false;
|
|
124
121
|
const parentPolygonInShapeShape = editor.getShapePageTransform(childId).clone().invert().applyToPoints(parentPagePolygon);
|
|
125
122
|
const geometry = editor.getShapeGeometry(childId);
|
|
126
|
-
return
|
|
123
|
+
return geometry.overlapsPolygon(parentPolygonInShapeShape);
|
|
127
124
|
});
|
|
128
125
|
}
|
|
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
126
|
function getDroppedShapesToNewParents(editor, shapes, cb) {
|
|
160
127
|
const shapesToActuallyCheck = new Set(shapes);
|
|
161
128
|
const movingGroups = /* @__PURE__ */ new Set();
|
|
@@ -208,7 +175,7 @@ function getDroppedShapesToNewParents(editor, shapes, cb) {
|
|
|
208
175
|
if (shapeGroupId !== parentShapeContainingGroupId) continue shapeCheck;
|
|
209
176
|
if (editor.findShapeAncestor(parentShape, (s) => shape.id === s.id)) continue shapeCheck;
|
|
210
177
|
const parentPolygonInShapeSpace = editor.getShapePageTransform(shape).clone().invert().applyToPoints(parentPagePolygon);
|
|
211
|
-
if (
|
|
178
|
+
if (editor.getShapeGeometry(shape).overlapsPolygon(parentPolygonInShapeSpace)) {
|
|
212
179
|
if (!editor.getShapeUtil(parentShape).canReceiveNewChildrenOfType?.(parentShape, shape.type))
|
|
213
180
|
continue shapeCheck;
|
|
214
181
|
if (shape.parentId !== parentShape.id) {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
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": ";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA
|
|
6
|
-
"names": ["
|
|
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 { intersectPolygonPolygon } from '../primitives/intersect'\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 geometry.overlapsPolygon(parentPolygonInShapeShape)\n\t})\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 (editor.getShapeGeometry(shape).overlapsPolygon(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": ["shapeIds"]
|
|
7
7
|
}
|
package/dist-cjs/version.js
CHANGED
|
@@ -22,10 +22,10 @@ __export(version_exports, {
|
|
|
22
22
|
version: () => version
|
|
23
23
|
});
|
|
24
24
|
module.exports = __toCommonJS(version_exports);
|
|
25
|
-
const version = "3.16.0-next.
|
|
25
|
+
const version = "3.16.0-next.e57e478c23e0";
|
|
26
26
|
const publishDates = {
|
|
27
27
|
major: "2024-09-13T14:36:29.063Z",
|
|
28
|
-
minor: "2025-
|
|
29
|
-
patch: "2025-
|
|
28
|
+
minor: "2025-09-08T07:48:02.447Z",
|
|
29
|
+
patch: "2025-09-08T07:48:02.447Z"
|
|
30
30
|
};
|
|
31
31
|
//# sourceMappingURL=version.js.map
|
package/dist-cjs/version.js.map
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../src/version.ts"],
|
|
4
|
-
"sourcesContent": ["// This file is automatically generated by internal/scripts/refresh-assets.ts.\n// Do not edit manually. Or do, I'm a comment, not a cop.\n\nexport const version = '3.16.0-next.
|
|
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.16.0-next.e57e478c23e0'\nexport const publishDates = {\n\tmajor: '2024-09-13T14:36:29.063Z',\n\tminor: '2025-09-08T07:48:02.447Z',\n\tpatch: '2025-09-08T07:48:02.447Z',\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
|
}
|
package/dist-esm/index.d.mts
CHANGED
|
@@ -510,6 +510,7 @@ export declare class Box {
|
|
|
510
510
|
static ExpandBy(A: Box, n: number): Box;
|
|
511
511
|
static Collides(A: Box, B: Box): boolean;
|
|
512
512
|
static Contains(A: Box, B: Box): boolean;
|
|
513
|
+
static ContainsApproximately(A: Box, B: Box, precision?: number): boolean;
|
|
513
514
|
static Includes(A: Box, B: Box): boolean;
|
|
514
515
|
static ContainsPoint(A: Box, B: VecLike, margin?: number): boolean;
|
|
515
516
|
static Common(boxes: Box[]): Box;
|
|
@@ -760,11 +761,6 @@ export declare class CubicSpline2d extends Geometry2d {
|
|
|
760
761
|
/** @public */
|
|
761
762
|
export declare function dataUrlToFile(url: string, filename: string, mimeType: string): Promise<File>;
|
|
762
763
|
|
|
763
|
-
/**
|
|
764
|
-
* @deprecated Licensing is now enabled in the tldraw SDK.
|
|
765
|
-
* @public */
|
|
766
|
-
export declare function debugEnableLicensing(): void;
|
|
767
|
-
|
|
768
764
|
/* Excluded from this release type: DebugFlag */
|
|
769
765
|
|
|
770
766
|
/* Excluded from this release type: DebugFlagDef */
|
|
@@ -889,6 +885,9 @@ export declare const defaultTldrawOptions: {
|
|
|
889
885
|
readonly nonce: undefined;
|
|
890
886
|
readonly temporaryAssetPreviewLifetimeMs: 180000;
|
|
891
887
|
readonly textShadowLod: 0.35;
|
|
888
|
+
readonly tooltipDelayMs: 700;
|
|
889
|
+
readonly uiCoarseDragDistanceSquared: 625;
|
|
890
|
+
readonly uiDragDistanceSquared: 16;
|
|
892
891
|
};
|
|
893
892
|
|
|
894
893
|
/** @public */
|
|
@@ -904,6 +903,7 @@ export declare const defaultUserPreferences: Readonly<{
|
|
|
904
903
|
isWrapMode: false;
|
|
905
904
|
locale: "ar" | "bn" | "ca" | "cs" | "da" | "de" | "el" | "en" | "es" | "fa" | "fi" | "fr" | "gl" | "gu-in" | "he" | "hi-in" | "hr" | "hu" | "id" | "it" | "ja" | "km-kh" | "kn" | "ko-kr" | "ml" | "mr" | "ms" | "ne" | "nl" | "no" | "pa" | "pl" | "pt-br" | "pt-pt" | "ro" | "ru" | "sl" | "so" | "sv" | "ta" | "te" | "th" | "tl" | "tr" | "uk" | "ur" | "vi" | "zh-cn" | "zh-tw";
|
|
906
905
|
name: "";
|
|
906
|
+
showUiLabels: false;
|
|
907
907
|
}>;
|
|
908
908
|
|
|
909
909
|
/**
|
|
@@ -979,7 +979,7 @@ export declare class EdgeScrollManager {
|
|
|
979
979
|
/** @public */
|
|
980
980
|
export declare class Editor extends EventEmitter<TLEventMap> {
|
|
981
981
|
readonly id: string;
|
|
982
|
-
constructor({ store, user, shapeUtils, bindingUtils, tools, getContainer, cameraOptions, textOptions, initialState, autoFocus, inferDarkMode, options,
|
|
982
|
+
constructor({ store, user, shapeUtils, bindingUtils, tools, getContainer, cameraOptions, textOptions, initialState, autoFocus, inferDarkMode, options, getShapeVisibility, fontAssetUrls, }: TLEditorOptions);
|
|
983
983
|
private readonly _getShapeVisibility?;
|
|
984
984
|
private getIsShapeHiddenCache;
|
|
985
985
|
isShapeHidden(shapeOrId: TLShape | TLShapeId): boolean;
|
|
@@ -1046,22 +1046,6 @@ export declare class Editor extends EventEmitter<TLEventMap> {
|
|
|
1046
1046
|
* @public
|
|
1047
1047
|
*/
|
|
1048
1048
|
readonly fonts: FontManager;
|
|
1049
|
-
/**
|
|
1050
|
-
* A manager for the editor's environment.
|
|
1051
|
-
*
|
|
1052
|
-
* @deprecated This is deprecated and will be removed in a future version. Use the `tlenv` global export instead.
|
|
1053
|
-
* @public
|
|
1054
|
-
*/
|
|
1055
|
-
readonly environment: {
|
|
1056
|
-
hasCanvasSupport: boolean;
|
|
1057
|
-
isAndroid: boolean;
|
|
1058
|
-
isChromeForIos: boolean;
|
|
1059
|
-
isDarwin: boolean;
|
|
1060
|
-
isFirefox: boolean;
|
|
1061
|
-
isIos: boolean;
|
|
1062
|
-
isSafari: boolean;
|
|
1063
|
-
isWebview: boolean;
|
|
1064
|
-
};
|
|
1065
1049
|
/**
|
|
1066
1050
|
* A manager for the editor's scribbles.
|
|
1067
1051
|
*
|
|
@@ -1204,22 +1188,6 @@ export declare class Editor extends EventEmitter<TLEventMap> {
|
|
|
1204
1188
|
* @public
|
|
1205
1189
|
*/
|
|
1206
1190
|
getCanRedo(): boolean;
|
|
1207
|
-
/**
|
|
1208
|
-
* Create a new "mark", or stopping point, in the undo redo history. Creating a mark will clear
|
|
1209
|
-
* any redos.
|
|
1210
|
-
*
|
|
1211
|
-
* @example
|
|
1212
|
-
* ```ts
|
|
1213
|
-
* editor.mark()
|
|
1214
|
-
* editor.mark('flip shapes')
|
|
1215
|
-
* ```
|
|
1216
|
-
*
|
|
1217
|
-
* @param markId - The mark's id, usually the reason for adding the mark.
|
|
1218
|
-
*
|
|
1219
|
-
* @public
|
|
1220
|
-
* @deprecated use {@link Editor.markHistoryStoppingPoint} instead
|
|
1221
|
-
*/
|
|
1222
|
-
mark(markId?: string): this;
|
|
1223
1191
|
/**
|
|
1224
1192
|
* Create a new "mark", or stopping point, in the undo redo history. Creating a mark will clear
|
|
1225
1193
|
* any redos. You typically want to do this just before a user interaction begins or is handled.
|
|
@@ -1309,10 +1277,6 @@ export declare class Editor extends EventEmitter<TLEventMap> {
|
|
|
1309
1277
|
* @public
|
|
1310
1278
|
*/
|
|
1311
1279
|
run(fn: () => void, opts?: TLEditorRunOptions): this;
|
|
1312
|
-
/**
|
|
1313
|
-
* @deprecated Use `Editor.run` instead.
|
|
1314
|
-
*/
|
|
1315
|
-
batch(fn: () => void, opts?: TLEditorRunOptions): this;
|
|
1316
1280
|
/* Excluded from this release type: annotateError */
|
|
1317
1281
|
/* Excluded from this release type: createErrorAnnotations */
|
|
1318
1282
|
/* Excluded from this release type: _crashingError */
|
|
@@ -1434,36 +1398,6 @@ export declare class Editor extends EventEmitter<TLEventMap> {
|
|
|
1434
1398
|
hasOpenMenus: () => boolean;
|
|
1435
1399
|
isMenuOpen: (id: string) => boolean;
|
|
1436
1400
|
};
|
|
1437
|
-
/**
|
|
1438
|
-
* @deprecated Use `editor.menus.getOpenMenus` instead.
|
|
1439
|
-
*
|
|
1440
|
-
* @public
|
|
1441
|
-
*/
|
|
1442
|
-
getOpenMenus(): string[];
|
|
1443
|
-
/**
|
|
1444
|
-
* @deprecated Use `editor.menus.addOpenMenu` instead.
|
|
1445
|
-
*
|
|
1446
|
-
* @public
|
|
1447
|
-
*/
|
|
1448
|
-
addOpenMenu(id: string): this;
|
|
1449
|
-
/**
|
|
1450
|
-
* @deprecated Use `editor.menus.deleteOpenMenu` instead.
|
|
1451
|
-
*
|
|
1452
|
-
* @public
|
|
1453
|
-
*/
|
|
1454
|
-
deleteOpenMenu(id: string): this;
|
|
1455
|
-
/**
|
|
1456
|
-
* @deprecated Use `editor.menus.clearOpenMenus` instead.
|
|
1457
|
-
*
|
|
1458
|
-
* @public
|
|
1459
|
-
*/
|
|
1460
|
-
clearOpenMenus(): this;
|
|
1461
|
-
/**
|
|
1462
|
-
* @deprecated Use `editor.menus.hasAnyOpenMenus` instead.
|
|
1463
|
-
*
|
|
1464
|
-
* @public
|
|
1465
|
-
*/
|
|
1466
|
-
getIsMenuOpen(): boolean;
|
|
1467
1401
|
/**
|
|
1468
1402
|
* Set the cursor.
|
|
1469
1403
|
*
|
|
@@ -2690,15 +2624,7 @@ export declare class Editor extends EventEmitter<TLEventMap> {
|
|
|
2690
2624
|
*
|
|
2691
2625
|
* @returns The shape at the given point, or undefined if there is no shape at the point.
|
|
2692
2626
|
*/
|
|
2693
|
-
getShapeAtPoint(point: VecLike, opts?:
|
|
2694
|
-
filter?(shape: TLShape): boolean;
|
|
2695
|
-
hitFrameInside?: boolean;
|
|
2696
|
-
hitInside?: boolean;
|
|
2697
|
-
hitLabels?: boolean;
|
|
2698
|
-
hitLocked?: boolean;
|
|
2699
|
-
margin?: number;
|
|
2700
|
-
renderingOnly?: boolean;
|
|
2701
|
-
}): TLShape | undefined;
|
|
2627
|
+
getShapeAtPoint(point: VecLike, opts?: TLGetShapeAtPointOptions): TLShape | undefined;
|
|
2702
2628
|
/**
|
|
2703
2629
|
* Get the shapes, if any, at a given page point.
|
|
2704
2630
|
*
|
|
@@ -2920,8 +2846,6 @@ export declare class Editor extends EventEmitter<TLEventMap> {
|
|
|
2920
2846
|
* @public
|
|
2921
2847
|
*/
|
|
2922
2848
|
getShapeAndDescendantIds(ids: TLShapeId[]): Set<TLShapeId>;
|
|
2923
|
-
/** @deprecated Use {@link Editor.getDraggingOverShape} instead */
|
|
2924
|
-
getDroppingOverShape(point: Vec, droppingShapes: TLShape[]): TLShape | undefined;
|
|
2925
2849
|
/**
|
|
2926
2850
|
* Get the shape that some shapes should be dropped on at a given point.
|
|
2927
2851
|
*
|
|
@@ -3696,8 +3620,6 @@ export declare class Editor extends EventEmitter<TLEventMap> {
|
|
|
3696
3620
|
svg: string;
|
|
3697
3621
|
width: number;
|
|
3698
3622
|
} | undefined>;
|
|
3699
|
-
/** @deprecated Use {@link Editor.getSvgString} or {@link Editor.getSvgElement} instead. */
|
|
3700
|
-
getSvg(shapes: TLShape[] | TLShapeId[], opts?: TLSvgExportOptions): Promise<SVGSVGElement | undefined>;
|
|
3701
3623
|
/**
|
|
3702
3624
|
* Get an exported image of the given shapes.
|
|
3703
3625
|
*
|
|
@@ -3712,6 +3634,20 @@ export declare class Editor extends EventEmitter<TLEventMap> {
|
|
|
3712
3634
|
height: number;
|
|
3713
3635
|
width: number;
|
|
3714
3636
|
}>;
|
|
3637
|
+
/**
|
|
3638
|
+
* Get an exported image of the given shapes as a data URL.
|
|
3639
|
+
*
|
|
3640
|
+
* @param shapes - The shapes (or shape ids) to export.
|
|
3641
|
+
* @param opts - Options for the export.
|
|
3642
|
+
*
|
|
3643
|
+
* @returns A data URL of the image.
|
|
3644
|
+
* @public
|
|
3645
|
+
*/
|
|
3646
|
+
toImageDataUrl(shapes: TLShape[] | TLShapeId[], opts?: TLImageExportOptions): Promise<{
|
|
3647
|
+
height: number;
|
|
3648
|
+
url: string;
|
|
3649
|
+
width: number;
|
|
3650
|
+
}>;
|
|
3715
3651
|
/**
|
|
3716
3652
|
* The app's current input state.
|
|
3717
3653
|
*
|
|
@@ -4036,6 +3972,26 @@ export declare class Editor extends EventEmitter<TLEventMap> {
|
|
|
4036
3972
|
/* Excluded from this release type: maybeTrackPerformance */
|
|
4037
3973
|
}
|
|
4038
3974
|
|
|
3975
|
+
/**
|
|
3976
|
+
* An Atom that is scoped to the lifetime of an Editor.
|
|
3977
|
+
*
|
|
3978
|
+
* This is useful for storing UI state for tldraw applications. Keeping state scoped to an editor
|
|
3979
|
+
* instead of stored in a global atom can prevent issues with state being shared between editors
|
|
3980
|
+
* when navigating between pages, or when multiple editor instances are used on the same page.
|
|
3981
|
+
*
|
|
3982
|
+
* @public
|
|
3983
|
+
*/
|
|
3984
|
+
export declare class EditorAtom<T> {
|
|
3985
|
+
private name;
|
|
3986
|
+
private getInitialState;
|
|
3987
|
+
private states;
|
|
3988
|
+
constructor(name: string, getInitialState: (editor: Editor) => T);
|
|
3989
|
+
getAtom(editor: Editor): Atom<T>;
|
|
3990
|
+
get(editor: Editor): T;
|
|
3991
|
+
update(editor: Editor, update: (state: T) => T): T;
|
|
3992
|
+
set(editor: Editor, state: T): T;
|
|
3993
|
+
}
|
|
3994
|
+
|
|
4039
3995
|
/** @public */
|
|
4040
3996
|
export declare const EditorContext: React_3.Context<Editor | null>;
|
|
4041
3997
|
|
|
@@ -4156,9 +4112,8 @@ export declare abstract class Geometry2d {
|
|
|
4156
4112
|
* along the edge it is as a fraction of the total length.
|
|
4157
4113
|
*/
|
|
4158
4114
|
uninterpolateAlongEdge(point: VecLike, _filters?: Geometry2dFilters): number;
|
|
4159
|
-
/** @deprecated Iterate the vertices instead. */
|
|
4160
|
-
nearestPointOnLineSegment(A: VecLike, B: VecLike): Vec;
|
|
4161
4115
|
isPointInBounds(point: VecLike, margin?: number): boolean;
|
|
4116
|
+
overlapsPolygon(_polygon: VecLike[]): boolean;
|
|
4162
4117
|
transform(transform: MatModel, opts?: TransformedGeometry2dOptions): Geometry2d;
|
|
4163
4118
|
private _vertices;
|
|
4164
4119
|
get vertices(): Vec[];
|
|
@@ -4367,6 +4322,7 @@ export declare class Group2d extends Geometry2d {
|
|
|
4367
4322
|
toSimpleSvgPath(): string;
|
|
4368
4323
|
getLength(filters?: Geometry2dFilters): number;
|
|
4369
4324
|
getSvgPathData(): string;
|
|
4325
|
+
overlapsPolygon(polygon: VecLike[]): boolean;
|
|
4370
4326
|
}
|
|
4371
4327
|
|
|
4372
4328
|
/** @public */
|
|
@@ -4613,6 +4569,8 @@ export declare function kickoutOccludedShapes(editor: Editor, shapeIds: TLShapeI
|
|
|
4613
4569
|
|
|
4614
4570
|
/* Excluded from this release type: LicenseManager */
|
|
4615
4571
|
|
|
4572
|
+
/* Excluded from this release type: LicenseState */
|
|
4573
|
+
|
|
4616
4574
|
/** @public */
|
|
4617
4575
|
export declare function linesIntersect(A: VecLike, B: VecLike, C: VecLike, D: VecLike): boolean;
|
|
4618
4576
|
|
|
@@ -5219,6 +5177,25 @@ export declare abstract class ShapeUtil<Shape extends TLUnknownShape = TLUnknown
|
|
|
5219
5177
|
*/
|
|
5220
5178
|
canBeLaidOut(_shape: Shape, _info: TLShapeUtilCanBeLaidOutOpts): boolean;
|
|
5221
5179
|
/* Excluded from this release type: providesBackgroundForChildren */
|
|
5180
|
+
/**
|
|
5181
|
+
* Get the clip path to apply to this shape's children.
|
|
5182
|
+
*
|
|
5183
|
+
* @param shape - The shape to get the clip path for
|
|
5184
|
+
* @returns Array of points defining the clipping polygon in local coordinates, or undefined if no clipping
|
|
5185
|
+
* @public
|
|
5186
|
+
*/
|
|
5187
|
+
getClipPath?(shape: Shape): undefined | Vec[];
|
|
5188
|
+
/**
|
|
5189
|
+
* Whether a specific child shape should be clipped by this shape.
|
|
5190
|
+
* Only called if getClipPath returns a valid polygon.
|
|
5191
|
+
*
|
|
5192
|
+
* If not defined, the default behavior is to clip all children.
|
|
5193
|
+
*
|
|
5194
|
+
* @param child - The child shape to check
|
|
5195
|
+
* @returns boolean indicating if this child should be clipped
|
|
5196
|
+
* @public
|
|
5197
|
+
*/
|
|
5198
|
+
shouldClipChild?(child: TLShape): boolean;
|
|
5222
5199
|
/**
|
|
5223
5200
|
* Whether the shape should hide its resize handles when selected.
|
|
5224
5201
|
*
|
|
@@ -5249,6 +5226,17 @@ export declare abstract class ShapeUtil<Shape extends TLUnknownShape = TLUnknown
|
|
|
5249
5226
|
* @public
|
|
5250
5227
|
*/
|
|
5251
5228
|
isAspectRatioLocked(_shape: Shape): boolean;
|
|
5229
|
+
/**
|
|
5230
|
+
* By default, the bounds of an image export are the bounds of all the shapes it contains, plus
|
|
5231
|
+
* some padding. If an export includes a shape where `isExportBoundsContainer` is true, then the
|
|
5232
|
+
* padding is skipped _if the bounds of that shape contains all the other shapes_. This is
|
|
5233
|
+
* useful in cases like annotating on top of an image, where you usually want to avoid extra
|
|
5234
|
+
* padding around the image if you don't need it.
|
|
5235
|
+
*
|
|
5236
|
+
* @param _shape - The shape to check
|
|
5237
|
+
* @returns True if this shape should be treated as an export bounds container
|
|
5238
|
+
*/
|
|
5239
|
+
isExportBoundsContainer(_shape: Shape): boolean;
|
|
5252
5240
|
/* Excluded from this release type: backgroundComponent */
|
|
5253
5241
|
/**
|
|
5254
5242
|
* Get the interpolated props for an animating shape. This is an optional method.
|
|
@@ -6295,12 +6283,6 @@ export declare interface TldrawEditorBaseProps {
|
|
|
6295
6283
|
* Options for syncing the editor's camera state with the URL.
|
|
6296
6284
|
*/
|
|
6297
6285
|
deepLinks?: TLDeepLinkOptions | true;
|
|
6298
|
-
/**
|
|
6299
|
-
* Predicate for whether or not a shape should be hidden.
|
|
6300
|
-
*
|
|
6301
|
-
* @deprecated Use {@link TldrawEditorBaseProps#getShapeVisibility} instead.
|
|
6302
|
-
*/
|
|
6303
|
-
isShapeHidden?(shape: TLShape, editor: Editor): boolean;
|
|
6304
6286
|
/**
|
|
6305
6287
|
* Provides a way to hide shapes.
|
|
6306
6288
|
*
|
|
@@ -6408,6 +6390,8 @@ export declare interface TldrawOptions {
|
|
|
6408
6390
|
readonly multiClickDurationMs: number;
|
|
6409
6391
|
readonly coarseDragDistanceSquared: number;
|
|
6410
6392
|
readonly dragDistanceSquared: number;
|
|
6393
|
+
readonly uiDragDistanceSquared: number;
|
|
6394
|
+
readonly uiCoarseDragDistanceSquared: number;
|
|
6411
6395
|
readonly defaultSvgPadding: number;
|
|
6412
6396
|
readonly cameraSlideFriction: number;
|
|
6413
6397
|
readonly gridSteps: readonly {
|
|
@@ -6434,6 +6418,7 @@ export declare interface TldrawOptions {
|
|
|
6434
6418
|
readonly flattenImageBoundsPadding: number;
|
|
6435
6419
|
readonly laserDelayMs: number;
|
|
6436
6420
|
readonly maxExportDelayMs: number;
|
|
6421
|
+
readonly tooltipDelayMs: number;
|
|
6437
6422
|
/**
|
|
6438
6423
|
* How long should previews created by {@link Editor.createTemporaryAssetPreview} last before
|
|
6439
6424
|
* they expire? Defaults to 3 minutes.
|
|
@@ -6559,15 +6544,6 @@ export declare interface TLEditorOptions {
|
|
|
6559
6544
|
fontAssetUrls?: {
|
|
6560
6545
|
[key: string]: string | undefined;
|
|
6561
6546
|
};
|
|
6562
|
-
/**
|
|
6563
|
-
* A predicate that should return true if the given shape should be hidden.
|
|
6564
|
-
*
|
|
6565
|
-
* @deprecated Use {@link Editor#getShapeVisibility} instead.
|
|
6566
|
-
*
|
|
6567
|
-
* @param shape - The shape to check.
|
|
6568
|
-
* @param editor - The editor instance.
|
|
6569
|
-
*/
|
|
6570
|
-
isShapeHidden?(shape: TLShape, editor: Editor): boolean;
|
|
6571
6547
|
/**
|
|
6572
6548
|
* Provides a way to hide shapes.
|
|
6573
6549
|
*
|
|
@@ -6835,6 +6811,59 @@ export declare interface TLGeometryOpts {
|
|
|
6835
6811
|
context?: string;
|
|
6836
6812
|
}
|
|
6837
6813
|
|
|
6814
|
+
/**
|
|
6815
|
+
* Options to {@link Editor.getShapeAtPoint}.
|
|
6816
|
+
*
|
|
6817
|
+
* @public
|
|
6818
|
+
*/
|
|
6819
|
+
export declare interface TLGetShapeAtPointOptions {
|
|
6820
|
+
/**
|
|
6821
|
+
* The margin to apply to the shape.
|
|
6822
|
+
* If a number, it will be applied to both the inside and outside of the shape.
|
|
6823
|
+
* If an array, the first element will be applied to the inside of the shape, and the second element will be applied to the outside.
|
|
6824
|
+
*
|
|
6825
|
+
* @example
|
|
6826
|
+
* ```ts
|
|
6827
|
+
* // Get the shape at the center of the screen
|
|
6828
|
+
* const shape = editor.getShapeAtProps({
|
|
6829
|
+
* margin: 10,
|
|
6830
|
+
* })
|
|
6831
|
+
*
|
|
6832
|
+
* // Get the shape at the center of the screen with a 10px inner margin and a 5px outer margin
|
|
6833
|
+
* const shape = editor.getShapeAtProps({
|
|
6834
|
+
* margin: [10, 5],
|
|
6835
|
+
* })
|
|
6836
|
+
* ```
|
|
6837
|
+
*/
|
|
6838
|
+
margin?: [number, number] | number;
|
|
6839
|
+
/**
|
|
6840
|
+
* Whether to register hits inside of shapes (beyond the margin), such as the inside of a solid shape.
|
|
6841
|
+
*/
|
|
6842
|
+
hitInside?: boolean;
|
|
6843
|
+
/**
|
|
6844
|
+
* Whether to register hits on locked shapes.
|
|
6845
|
+
*/
|
|
6846
|
+
hitLocked?: boolean;
|
|
6847
|
+
/**
|
|
6848
|
+
* Whether to register hits on labels.
|
|
6849
|
+
*/
|
|
6850
|
+
hitLabels?: boolean;
|
|
6851
|
+
/**
|
|
6852
|
+
* Whether to only return hits on shapes that are currently being rendered.
|
|
6853
|
+
* todo: rename this to hitCulled or hitNotRendering
|
|
6854
|
+
*/
|
|
6855
|
+
renderingOnly?: boolean;
|
|
6856
|
+
/**
|
|
6857
|
+
* Whether to register hits on the inside of frame shapes.
|
|
6858
|
+
* todo: rename this to hitInsideFrames
|
|
6859
|
+
*/
|
|
6860
|
+
hitFrameInside?: boolean;
|
|
6861
|
+
/**
|
|
6862
|
+
* A filter function to apply to the shapes.
|
|
6863
|
+
*/
|
|
6864
|
+
filter?(shape: TLShape): boolean;
|
|
6865
|
+
}
|
|
6866
|
+
|
|
6838
6867
|
/** @public */
|
|
6839
6868
|
export declare interface TLGridProps {
|
|
6840
6869
|
x: number;
|
|
@@ -7505,12 +7534,6 @@ export declare interface TLSvgExportOptions {
|
|
|
7505
7534
|
preserveAspectRatio?: React.SVGAttributes<SVGSVGElement>['preserveAspectRatio'];
|
|
7506
7535
|
}
|
|
7507
7536
|
|
|
7508
|
-
/**
|
|
7509
|
-
* @public
|
|
7510
|
-
* @deprecated use {@link TLImageExportOptions} instead
|
|
7511
|
-
*/
|
|
7512
|
-
export declare type TLSvgOptions = TLImageExportOptions;
|
|
7513
|
-
|
|
7514
7537
|
/** @public */
|
|
7515
7538
|
export declare interface TLSvgTextExternalContent extends TLBaseExternalContent {
|
|
7516
7539
|
type: 'svg-text';
|
|
@@ -7621,6 +7644,7 @@ export declare interface TLUserPreferences {
|
|
|
7621
7644
|
isWrapMode?: boolean | null;
|
|
7622
7645
|
isDynamicSizeMode?: boolean | null;
|
|
7623
7646
|
isPasteAtCursorMode?: boolean | null;
|
|
7647
|
+
showUiLabels?: boolean | null;
|
|
7624
7648
|
}
|
|
7625
7649
|
|
|
7626
7650
|
/** @public */
|
|
@@ -7793,6 +7817,7 @@ export declare class UserPreferencesManager {
|
|
|
7793
7817
|
isWrapMode: boolean;
|
|
7794
7818
|
locale: string;
|
|
7795
7819
|
name: string;
|
|
7820
|
+
showUiLabels: boolean;
|
|
7796
7821
|
};
|
|
7797
7822
|
getIsDarkMode(): boolean;
|
|
7798
7823
|
/**
|
|
@@ -7809,6 +7834,7 @@ export declare class UserPreferencesManager {
|
|
|
7809
7834
|
getIsWrapMode(): boolean;
|
|
7810
7835
|
getIsDynamicResizeMode(): boolean;
|
|
7811
7836
|
getIsPasteAtCursorMode(): boolean;
|
|
7837
|
+
getShowUiLabels(): boolean;
|
|
7812
7838
|
}
|
|
7813
7839
|
|
|
7814
7840
|
/** @public */
|
|
@@ -7915,8 +7941,6 @@ export declare class Vec {
|
|
|
7915
7941
|
lrp(B: VecLike, t: number): Vec;
|
|
7916
7942
|
equals(B: VecLike): boolean;
|
|
7917
7943
|
equalsXY(x: number, y: number): boolean;
|
|
7918
|
-
/** @deprecated use `uni` instead */
|
|
7919
|
-
norm(): this;
|
|
7920
7944
|
toFixed(): this;
|
|
7921
7945
|
toString(): string;
|
|
7922
7946
|
toJson(): VecModel;
|