@tldraw/editor 4.5.0-canary.ea6778d1533e → 4.5.0-next.a4da812dd479

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.
@@ -20,6 +20,7 @@ import { MigrationSequence } from '@tldraw/store';
20
20
  import { NamedExoticComponent } from 'react';
21
21
  import { Node as Node_2 } from '@tiptap/pm/model';
22
22
  import { PerformanceTracker } from '@tldraw/utils';
23
+ import { PointerEvent as PointerEvent_2 } from 'react';
23
24
  import { PointerEventHandler } from 'react';
24
25
  import * as React_2 from 'react';
25
26
  import { default as React_3 } from 'react';
@@ -63,7 +64,6 @@ import { TLImageAsset } from '@tldraw/tlschema';
63
64
  import { TLInstance } from '@tldraw/tlschema';
64
65
  import { TLInstancePageState } from '@tldraw/tlschema';
65
66
  import { TLInstancePresence } from '@tldraw/tlschema';
66
- import { TLOpacityType } from '@tldraw/tlschema';
67
67
  import { TLPage } from '@tldraw/tlschema';
68
68
  import { TLPageId } from '@tldraw/tlschema';
69
69
  import { TLParentId } from '@tldraw/tlschema';
@@ -439,13 +439,13 @@ export declare class BoundsSnaps {
439
439
  private getSnappablePoints;
440
440
  private getSnappableGapNodes;
441
441
  private getVisibleGaps;
442
- snapTranslateShapes({ lockedAxis, initialSelectionPageBounds, initialSelectionSnapPoints, dragDelta, }: {
442
+ snapTranslateShapes({ lockedAxis, initialSelectionPageBounds, initialSelectionSnapPoints, dragDelta }: {
443
443
  dragDelta: Vec;
444
444
  initialSelectionPageBounds: Box;
445
445
  initialSelectionSnapPoints: BoundsSnapPoint[];
446
446
  lockedAxis: 'x' | 'y' | null;
447
447
  }): SnapData;
448
- snapResizeShapes({ initialSelectionPageBounds, dragDelta, handle: originalHandle, isAspectRatioLocked, isResizingFromCenter, }: {
448
+ snapResizeShapes({ initialSelectionPageBounds, dragDelta, handle: originalHandle, isAspectRatioLocked, isResizingFromCenter }: {
449
449
  dragDelta: Vec;
450
450
  handle: SelectionCorner | SelectionEdge;
451
451
  initialSelectionPageBounds: Box;
@@ -679,7 +679,7 @@ export declare const coreShapes: readonly [typeof GroupShapeUtil];
679
679
  export declare function counterClockwiseAngleDist(a0: number, a1: number): number;
680
680
 
681
681
  /** @public */
682
- export declare function createDebugValue<T>(name: string, { defaults, shouldStoreForSession, }: {
682
+ export declare function createDebugValue<T>(name: string, { defaults, shouldStoreForSession }: {
683
683
  defaults: DebugFlagDefaults<T>;
684
684
  shouldStoreForSession?: boolean;
685
685
  }): DebugFlag<T>;
@@ -729,8 +729,8 @@ export declare function createTLStore({ initialData, defaultName, id, assets, on
729
729
 
730
730
  /** @public */
731
731
  export declare function createTLUser(opts?: {
732
- setUserPreferences?: (userPreferences: TLUserPreferences) => void;
733
- userPreferences?: Signal<TLUserPreferences>;
732
+ setUserPreferences?: ((userPreferences: TLUserPreferences) => void) | undefined;
733
+ userPreferences?: Signal<TLUserPreferences, unknown> | undefined;
734
734
  }): TLUser;
735
735
 
736
736
  /** @public */
@@ -814,7 +814,7 @@ export declare const DefaultBrush: ({ brush, color, opacity, className }: TLBrus
814
814
  export declare function DefaultCanvas({ className }: TLCanvasComponentProps): JSX.Element;
815
815
 
816
816
  /** @public @react */
817
- export declare function DefaultCollaboratorHint({ className, zoom, point, color, viewport, opacity, }: TLCollaboratorHintProps): JSX.Element;
817
+ export declare function DefaultCollaboratorHint({ className, zoom, point, color, viewport, opacity }: TLCollaboratorHintProps): JSX.Element;
818
818
 
819
819
  /** @public @react */
820
820
  export declare const DefaultCursor: NamedExoticComponent<TLCursorProps>;
@@ -1022,7 +1022,7 @@ export declare class EdgeScrollManager {
1022
1022
  /** @public */
1023
1023
  export declare class Editor extends EventEmitter<TLEventMap> {
1024
1024
  readonly id: string;
1025
- constructor({ store, user, shapeUtils, bindingUtils, tools, getContainer, cameraOptions, initialState, autoFocus, inferDarkMode, options: _options, textOptions: _textOptions, getShapeVisibility, fontAssetUrls, }: TLEditorOptions);
1025
+ constructor({ store, user, shapeUtils, bindingUtils, tools, getContainer, cameraOptions, initialState, autoFocus, inferDarkMode, options: _options, textOptions: _textOptions, getShapeVisibility, fontAssetUrls }: TLEditorOptions);
1026
1026
  private readonly _getShapeVisibility?;
1027
1027
  private getIsShapeHiddenCache;
1028
1028
  isShapeHidden(shapeOrId: TLShape | TLShapeId): boolean;
@@ -1095,8 +1095,8 @@ export declare class Editor extends EventEmitter<TLEventMap> {
1095
1095
  readonly timers: {
1096
1096
  dispose: () => void;
1097
1097
  requestAnimationFrame: (callback: FrameRequestCallback) => number;
1098
- setInterval: (handler: TimerHandler, timeout?: number, ...args: any[]) => number;
1099
- setTimeout: (handler: TimerHandler, timeout?: number, ...args: any[]) => number;
1098
+ setInterval: (handler: TimerHandler, timeout?: number | undefined, ...args: any[]) => number;
1099
+ setTimeout: (handler: TimerHandler, timeout?: number | undefined, ...args: any[]) => number;
1100
1100
  };
1101
1101
  /**
1102
1102
  * A manager for the user and their preferences.
@@ -1487,14 +1487,14 @@ export declare class Editor extends EventEmitter<TLEventMap> {
1487
1487
  * @public
1488
1488
  */
1489
1489
  getPageStates(): TLInstancePageState[];
1490
- /* Excluded from this release type: _getPageStatesQuery */
1490
+ private _getPageStatesQuery;
1491
1491
  /**
1492
1492
  * The current page state.
1493
1493
  *
1494
1494
  * @public
1495
1495
  */
1496
1496
  getCurrentPageState(): TLInstancePageState;
1497
- /* Excluded from this release type: _getCurrentPageStateId */
1497
+ private _getCurrentPageStateId;
1498
1498
  /**
1499
1499
  * Update this instance's page state.
1500
1500
  *
@@ -1887,7 +1887,7 @@ export declare class Editor extends EventEmitter<TLEventMap> {
1887
1887
  *
1888
1888
  * @public */
1889
1889
  getTextOptions(): TLTextOptions;
1890
- /* Excluded from this release type: _unsafe_getCameraId */
1890
+ private _unsafe_getCameraId;
1891
1891
  /**
1892
1892
  * The current camera.
1893
1893
  *
@@ -2137,10 +2137,10 @@ export declare class Editor extends EventEmitter<TLEventMap> {
2137
2137
  */
2138
2138
  slideCamera(opts?: {
2139
2139
  direction: VecLike;
2140
- force?: boolean;
2141
- friction?: number;
2140
+ force?: boolean | undefined;
2141
+ friction?: number | undefined;
2142
2142
  speed: number;
2143
- speedThreshold?: number;
2143
+ speedThreshold?: number | undefined;
2144
2144
  }): this;
2145
2145
  /**
2146
2146
  * Animate the camera to a user's cursor position. This also briefly show the user's cursor if it's not currently visible.
@@ -2448,7 +2448,7 @@ export declare class Editor extends EventEmitter<TLEventMap> {
2448
2448
  * @public
2449
2449
  */
2450
2450
  renamePage(page: TLPage | TLPageId, name: string): this;
2451
- /* Excluded from this release type: _getAllAssetsQuery */
2451
+ private _getAllAssetsQuery;
2452
2452
  /**
2453
2453
  * Get all assets in the editor.
2454
2454
  *
@@ -2537,7 +2537,7 @@ export declare class Editor extends EventEmitter<TLEventMap> {
2537
2537
  * @public
2538
2538
  */
2539
2539
  getShapeGeometry<T extends Geometry2d>(shape: TLShape | TLShapeId, opts?: TLGeometryOpts): T;
2540
- /* Excluded from this release type: _getShapeHandlesCache */
2540
+ private _getShapeHandlesCache;
2541
2541
  /**
2542
2542
  * Get the handles (if any) for a shape.
2543
2543
  *
@@ -2567,7 +2567,7 @@ export declare class Editor extends EventEmitter<TLEventMap> {
2567
2567
  * @public
2568
2568
  */
2569
2569
  getShapeLocalTransform(shape: TLShape | TLShapeId): Mat;
2570
- /* Excluded from this release type: _getShapePageTransformCache */
2570
+ private _getShapePageTransformCache;
2571
2571
  /**
2572
2572
  * Get the local transform of a shape's parent as a matrix model.
2573
2573
  *
@@ -2595,7 +2595,7 @@ export declare class Editor extends EventEmitter<TLEventMap> {
2595
2595
  * @public
2596
2596
  */
2597
2597
  getShapePageTransform(shape: TLShape | TLShapeId): Mat;
2598
- /* Excluded from this release type: _getShapePageBoundsCache */
2598
+ private _getShapePageBoundsCache;
2599
2599
  /**
2600
2600
  * Get the bounds of a shape in the current page space.
2601
2601
  *
@@ -2610,7 +2610,7 @@ export declare class Editor extends EventEmitter<TLEventMap> {
2610
2610
  * @public
2611
2611
  */
2612
2612
  getShapePageBounds(shape: TLShape | TLShapeId): Box | undefined;
2613
- /* Excluded from this release type: _getShapeClipPathCache */
2613
+ private _getShapeClipPathCache;
2614
2614
  /**
2615
2615
  * Get the clip path for a shape.
2616
2616
  *
@@ -2627,7 +2627,7 @@ export declare class Editor extends EventEmitter<TLEventMap> {
2627
2627
  * @public
2628
2628
  */
2629
2629
  getShapeClipPath(shape: TLShape | TLShapeId): string | undefined;
2630
- /* Excluded from this release type: _getShapeMaskCache */
2630
+ private _getShapeMaskCache;
2631
2631
  /**
2632
2632
  * Get the mask (in the current page space) for a shape.
2633
2633
  *
@@ -2659,7 +2659,7 @@ export declare class Editor extends EventEmitter<TLEventMap> {
2659
2659
  * @public
2660
2660
  */
2661
2661
  getShapeMaskedPageBounds(shape: TLShape | TLShapeId): Box | undefined;
2662
- /* Excluded from this release type: _getShapeMaskedPageBoundsCache */
2662
+ private _getShapeMaskedPageBoundsCache;
2663
2663
  /**
2664
2664
  * Get the ancestors of a shape.
2665
2665
  *
@@ -2769,8 +2769,8 @@ export declare class Editor extends EventEmitter<TLEventMap> {
2769
2769
  * @public
2770
2770
  */
2771
2771
  getShapesAtPoint(point: VecLike, opts?: {
2772
- hitInside?: boolean;
2773
- margin?: number;
2772
+ hitInside?: boolean | undefined;
2773
+ margin?: number | undefined;
2774
2774
  }): TLShape[];
2775
2775
  /**
2776
2776
  * Get shape IDs within the given bounds.
@@ -2806,8 +2806,8 @@ export declare class Editor extends EventEmitter<TLEventMap> {
2806
2806
  * @public
2807
2807
  */
2808
2808
  isPointInShape(shape: TLShape | TLShapeId, point: VecLike, opts?: {
2809
- hitInside?: boolean;
2810
- margin?: number;
2809
+ hitInside?: boolean | undefined;
2810
+ margin?: number | undefined;
2811
2811
  }): boolean;
2812
2812
  /**
2813
2813
  * Convert a point in the current page space to a point in the local space of a shape. For example, if a
@@ -3081,7 +3081,7 @@ export declare class Editor extends EventEmitter<TLEventMap> {
3081
3081
  * Delete a binding by its ID. If the binding doesn't exist, it's ignored.
3082
3082
  */
3083
3083
  deleteBinding(binding: TLBinding | TLBindingId, opts?: Parameters<this['deleteBindings']>[1]): this;
3084
- canBindShapes({ fromShape, toShape, binding, }: {
3084
+ canBindShapes({ fromShape, toShape, binding }: {
3085
3085
  binding: {
3086
3086
  type: TLBinding['type'];
3087
3087
  } | TLBinding | TLBinding['type'];
@@ -3530,7 +3530,7 @@ export declare class Editor extends EventEmitter<TLEventMap> {
3530
3530
  deleteShape(id: TLShapeId): this;
3531
3531
  deleteShape(shape: TLShape): this;
3532
3532
  /* Excluded from this release type: _extractSharedStyles */
3533
- /* Excluded from this release type: _getSelectionSharedStyles */
3533
+ private _getSelectionSharedStyles;
3534
3534
  /**
3535
3535
  * Get the style for the next shape.
3536
3536
  *
@@ -3719,7 +3719,7 @@ export declare class Editor extends EventEmitter<TLEventMap> {
3719
3719
  * @param opts - Options for handling external content, including force flag to bypass readonly checks.
3720
3720
  */
3721
3721
  putExternalContent<E>(info: TLExternalContent<E>, opts?: {
3722
- force?: boolean;
3722
+ force?: boolean | undefined;
3723
3723
  }): Promise<void>;
3724
3724
  /**
3725
3725
  * Handle replacing external content.
@@ -3728,7 +3728,7 @@ export declare class Editor extends EventEmitter<TLEventMap> {
3728
3728
  * @param opts - Options for handling external content, including force flag to bypass readonly checks.
3729
3729
  */
3730
3730
  replaceExternalContent<E>(info: TLExternalContent<E>, opts?: {
3731
- force?: boolean;
3731
+ force?: boolean | undefined;
3732
3732
  }): Promise<void>;
3733
3733
  /**
3734
3734
  * Get content that can be exported for the given shape ids.
@@ -4268,6 +4268,11 @@ export declare abstract class Geometry2d {
4268
4268
  private _length?;
4269
4269
  get length(): number;
4270
4270
  getLength(_filters?: Geometry2dFilters): number;
4271
+ /**
4272
+ * Called after a hit test succeeds. Return `true` to reject the hit and allow
4273
+ * shapes behind this one to be selected instead (e.g. transparent image pixels).
4274
+ */
4275
+ ignoreHit(_point: VecLike): boolean;
4271
4276
  abstract getSvgPathData(first: boolean): string;
4272
4277
  }
4273
4278
 
@@ -4535,7 +4540,7 @@ export declare class HandleSnaps {
4535
4540
  private iterateSnapOutlines;
4536
4541
  private getHandleSnapPosition;
4537
4542
  private getHandleSnapData;
4538
- snapHandle({ currentShapeId, handle, }: {
4543
+ snapHandle({ currentShapeId, handle }: {
4539
4544
  currentShapeId: TLShapeId;
4540
4545
  handle: TLHandle;
4541
4546
  }): null | SnapData;
@@ -7771,7 +7776,7 @@ export declare const tlmenus: {
7771
7776
  *
7772
7777
  * @public
7773
7778
  */
7774
- clearOpenMenus(contextId?: string): void;
7779
+ clearOpenMenus(contextId?: string | undefined): void;
7775
7780
  /**
7776
7781
  * Delete an open menu.
7777
7782
  *
@@ -7794,7 +7799,7 @@ export declare const tlmenus: {
7794
7799
  *
7795
7800
  * @public
7796
7801
  */
7797
- getOpenMenus(contextId?: string): string[];
7802
+ getOpenMenus(contextId?: string | undefined): string[];
7798
7803
  /**
7799
7804
  * Get whether a menu is open for a given context.
7800
7805
  *
@@ -7808,7 +7813,7 @@ export declare const tlmenus: {
7808
7813
  *
7809
7814
  * @public
7810
7815
  */
7811
- isMenuOpen(id: string, contextId?: string): boolean;
7816
+ isMenuOpen(id: string, contextId?: string | undefined): boolean;
7812
7817
  /**
7813
7818
  * Get whether any menus are open for a given context.
7814
7819
  *
@@ -7846,7 +7851,7 @@ export declare const tlmenus: {
7846
7851
  *
7847
7852
  * @public
7848
7853
  */
7849
- hideOpenMenus(contextId?: string): void;
7854
+ hideOpenMenus(contextId?: string | undefined): void;
7850
7855
  /**
7851
7856
  * Show all hidden menus.
7852
7857
  *
@@ -7860,7 +7865,7 @@ export declare const tlmenus: {
7860
7865
  *
7861
7866
  * @public
7862
7867
  */
7863
- showOpenMenus(contextId?: string): void;
7868
+ showOpenMenus(contextId?: string | undefined): void;
7864
7869
  forContext(contextId: string): {
7865
7870
  addOpenMenu: (id: string) => void;
7866
7871
  clearOpenMenus: () => void;
@@ -8426,6 +8431,7 @@ export declare class TransformedGeometry2d extends Geometry2d {
8426
8431
  intersectCircle(center: VecLike, radius: number, filters?: Geometry2dFilters): Vec[];
8427
8432
  intersectPolygon(polygon: VecLike[], filters?: Geometry2dFilters): VecLike[];
8428
8433
  intersectPolyline(polyline: VecLike[], filters?: Geometry2dFilters): VecLike[];
8434
+ ignoreHit(point: VecLike): boolean;
8429
8435
  transform(transform: MatModel, opts?: TransformedGeometry2dOptions): Geometry2d;
8430
8436
  getSvgPathData(): string;
8431
8437
  }
@@ -8578,7 +8584,7 @@ export declare const userTypeValidator: T.Validator<TLUserPreferences>;
8578
8584
  /** @public */
8579
8585
  export declare function useSelectionEvents(handle: TLSelectionHandle): {
8580
8586
  onPointerDown: PointerEventHandler<Element>;
8581
- onPointerMove: (e: React.PointerEvent) => void;
8587
+ onPointerMove: (e: PointerEvent_2<Element>) => void;
8582
8588
  onPointerUp: PointerEventHandler<Element>;
8583
8589
  };
8584
8590
 
package/dist-cjs/index.js CHANGED
@@ -369,7 +369,7 @@ var import_LocalIndexedDb = require("./lib/utils/sync/LocalIndexedDb");
369
369
  var import_uniq = require("./lib/utils/uniq");
370
370
  (0, import_utils.registerTldrawLibraryVersion)(
371
371
  "@tldraw/editor",
372
- "4.5.0-canary.ea6778d1533e",
372
+ "4.5.0-next.a4da812dd479",
373
373
  "cjs"
374
374
  );
375
375
  //# sourceMappingURL=index.js.map
@@ -3990,6 +3990,9 @@ class Editor extends (_a = import_eventemitter3.default, _getIsShapeHiddenCache_
3990
3990
  if (geometry.isClosed) {
3991
3991
  if (distance <= outerMargin || hitInside && distance <= 0 && distance > -innerMargin) {
3992
3992
  if (geometry.isFilled || isGroup && geometry.children[0].isFilled) {
3993
+ if (geometry.ignoreHit(pointInShapeSpace)) {
3994
+ continue;
3995
+ }
3993
3996
  return inMarginClosestToEdgeHit || shape;
3994
3997
  } else {
3995
3998
  if (this.getShapePageBounds(shape).contains(viewportPageBounds)) continue;
@@ -6725,38 +6728,10 @@ class Editor extends (_a = import_eventemitter3.default, _getIsShapeHiddenCache_
6725
6728
  const bindingIdMap = new Map(
6726
6729
  preserveIds ? bindings.map((binding) => [binding.id, binding.id]) : bindings.map((binding) => [binding.id, (0, import_tlschema.createBindingId)()])
6727
6730
  );
6728
- let pasteParentId = this.getCurrentPageId();
6729
- let lowestDepth = Infinity;
6730
- let lowestAncestors = [];
6731
- for (const shape of this.getSelectedShapes()) {
6732
- if (lowestDepth === 0) break;
6733
- const isFrame = this.isShapeOfType(shape, "frame");
6734
- const ancestors = this.getShapeAncestors(shape);
6735
- if (isFrame) ancestors.push(shape);
6736
- const depth = isFrame ? ancestors.length + 1 : ancestors.length;
6737
- if (depth < lowestDepth) {
6738
- lowestDepth = depth;
6739
- lowestAncestors = ancestors;
6740
- pasteParentId = isFrame ? shape.id : shape.parentId;
6741
- } else if (depth === lowestDepth) {
6742
- if (lowestAncestors.length !== ancestors.length) {
6743
- throw Error(`Ancestors: ${lowestAncestors.length} !== ${ancestors.length}`);
6744
- }
6745
- if (lowestAncestors.length === 0) {
6746
- pasteParentId = currentPageId;
6747
- break;
6748
- } else {
6749
- pasteParentId = currentPageId;
6750
- for (let i = 0; i < lowestAncestors.length; i++) {
6751
- if (ancestors[i] !== lowestAncestors[i]) break;
6752
- pasteParentId = ancestors[i].id;
6753
- }
6754
- }
6755
- }
6756
- }
6731
+ let pasteParentId = currentPageId;
6732
+ const shapesById = new Map(shapes.map((s) => [s.id, s]));
6733
+ const rootShapesFromContent = (0, import_utils.compact)(rootShapeIds.map((id) => shapesById.get(id)));
6757
6734
  if (point) {
6758
- const shapesById = new Map(shapes.map((shape) => [shape.id, shape]));
6759
- const rootShapesFromContent = (0, import_utils.compact)(rootShapeIds.map((id) => shapesById.get(id)));
6760
6735
  if (rootShapesFromContent.length > 0) {
6761
6736
  const targetParent = this.getShapeAtPoint(point, {
6762
6737
  hitInside: true,
@@ -6764,38 +6739,55 @@ class Editor extends (_a = import_eventemitter3.default, _getIsShapeHiddenCache_
6764
6739
  hitLocked: true,
6765
6740
  filter: (shape) => {
6766
6741
  const util = this.getShapeUtil(shape);
6767
- if (!util.canReceiveNewChildrenOfType) return false;
6768
6742
  return rootShapesFromContent.every(
6769
- (rootShape) => util.canReceiveNewChildrenOfType(shape, rootShape.type)
6743
+ (rootShape) => util.canReceiveNewChildrenOfType?.(shape, rootShape.type)
6770
6744
  );
6771
6745
  }
6772
6746
  });
6773
- pasteParentId = targetParent ? targetParent.id : currentPageId;
6774
- }
6775
- }
6776
- let isDuplicating = false;
6777
- if (!(0, import_tlschema.isPageId)(pasteParentId)) {
6778
- const parent = this.getShape(pasteParentId);
6779
- if (parent) {
6780
- if (!this.getViewportPageBounds().includes(this.getShapePageBounds(parent))) {
6781
- pasteParentId = currentPageId;
6782
- } else {
6783
- if (rootShapeIds.length === 1) {
6784
- const rootShape = shapes.find((s) => s.id === rootShapeIds[0]);
6785
- if (this.isShapeOfType(parent, "frame") && this.isShapeOfType(rootShape, "frame") && rootShape.props.w === parent?.props.w && rootShape.props.h === parent?.props.h) {
6786
- isDuplicating = true;
6747
+ pasteParentId = targetParent?.id ?? currentPageId;
6748
+ }
6749
+ } else if (!preservePosition) {
6750
+ const selectedShapes = this.getSelectedShapes();
6751
+ let selectedParent = null;
6752
+ const canAcceptAll = (candidate) => {
6753
+ const util = this.getShapeUtil(candidate);
6754
+ return rootShapesFromContent.every(
6755
+ (rs) => util.canReceiveNewChildrenOfType?.(candidate, rs.type)
6756
+ );
6757
+ };
6758
+ for (const shape of selectedShapes) {
6759
+ const candidate = canAcceptAll(shape) ? shape : this.findShapeAncestor(shape, canAcceptAll) ?? ((0, import_tlschema.isShapeId)(shape.parentId) ? this.getShape(shape.parentId) : null);
6760
+ if (!candidate) {
6761
+ selectedParent = null;
6762
+ break;
6763
+ }
6764
+ if (!selectedParent) {
6765
+ selectedParent = candidate;
6766
+ } else if (selectedParent.id !== candidate.id) {
6767
+ const spAncestors = this.getShapeAncestors(selectedParent);
6768
+ if (canAcceptAll(selectedParent)) spAncestors.push(selectedParent);
6769
+ const acceptingAncestors = spAncestors.filter(canAcceptAll);
6770
+ const candidateAncestorIds = /* @__PURE__ */ new Set([
6771
+ candidate.id,
6772
+ ...this.getShapeAncestors(candidate).map((a) => a.id)
6773
+ ]);
6774
+ let common = null;
6775
+ for (let i = acceptingAncestors.length - 1; i >= 0; i--) {
6776
+ if (candidateAncestorIds.has(acceptingAncestors[i].id)) {
6777
+ common = acceptingAncestors[i];
6778
+ break;
6787
6779
  }
6788
6780
  }
6781
+ selectedParent = common;
6782
+ if (!selectedParent) break;
6789
6783
  }
6790
- } else {
6791
- pasteParentId = currentPageId;
6792
6784
  }
6793
- }
6794
- if (!isDuplicating) {
6795
- isDuplicating = shapeIdMap.has(pasteParentId);
6796
- }
6797
- if (isDuplicating) {
6798
- pasteParentId = this.getShape(pasteParentId).parentId;
6785
+ if (selectedParent && shapeIdMap.has(selectedParent.id)) {
6786
+ selectedParent = null;
6787
+ }
6788
+ if (selectedParent) {
6789
+ pasteParentId = selectedParent.id;
6790
+ }
6799
6791
  }
6800
6792
  let index = this.getHighestIndexForParent(pasteParentId);
6801
6793
  const rootShapes = [];
@@ -6859,22 +6851,17 @@ class Editor extends (_a = import_eventemitter3.default, _getIsShapeHiddenCache_
6859
6851
  })
6860
6852
  );
6861
6853
  this.run(() => {
6862
- if (assetsToCreate.length > 0) {
6863
- this.createAssets(assetsToCreate);
6864
- }
6854
+ if (assetsToCreate.length > 0) this.createAssets(assetsToCreate);
6865
6855
  this.createShapes(newShapes);
6866
6856
  this.createBindings(newBindings);
6867
- if (select) {
6868
- this.select(...rootShapes.map((s) => s.id));
6869
- }
6857
+ if (select) this.select(...rootShapes.map((s) => s.id));
6870
6858
  if (pasteParentId !== currentPageId) {
6871
6859
  this.reparentShapes(
6872
6860
  rootShapes.map((s) => s.id),
6873
6861
  pasteParentId
6874
6862
  );
6875
6863
  }
6876
- const newCreatedShapes = newShapes.map((s) => this.getShape(s.id));
6877
- const bounds = import_Box.Box.Common(newCreatedShapes.map((s) => this.getShapePageBounds(s)));
6864
+ const rootBounds = import_Box.Box.Common((0, import_utils.compact)(rootShapes.map((s) => this.getShapePageBounds(s.id))));
6878
6865
  if (point === void 0) {
6879
6866
  if (!(0, import_tlschema.isPageId)(pasteParentId)) {
6880
6867
  const shape = this.getShape(pasteParentId);
@@ -6882,40 +6869,44 @@ class Editor extends (_a = import_eventemitter3.default, _getIsShapeHiddenCache_
6882
6869
  this.getShapePageTransform(shape),
6883
6870
  this.getShapeGeometry(shape).bounds.center
6884
6871
  );
6872
+ } else if (preservePosition) {
6873
+ point = rootBounds.center;
6885
6874
  } else {
6886
6875
  const viewportPageBounds = this.getViewportPageBounds();
6887
- if (preservePosition || viewportPageBounds.includes(import_Box.Box.From(bounds))) {
6888
- point = bounds.center;
6889
- } else {
6890
- point = viewportPageBounds.center;
6891
- }
6892
- }
6893
- }
6894
- if (rootShapes.length === 1) {
6895
- const onlyRoot = rootShapes[0];
6896
- if (this.isShapeOfType(onlyRoot, "frame")) {
6897
- while (this.getShapesAtPoint(point).some(
6898
- (shape) => this.isShapeOfType(shape, "frame") && shape.props.w === onlyRoot.props.w && shape.props.h === onlyRoot.props.h
6899
- )) {
6900
- point.x += bounds.w + 16;
6901
- }
6876
+ const anyOverlap = rootShapes.some((s) => {
6877
+ const b = this.getShapePageBounds(s.id);
6878
+ return b && viewportPageBounds.collides(b);
6879
+ });
6880
+ point = anyOverlap ? rootBounds.center : viewportPageBounds.center;
6902
6881
  }
6903
6882
  }
6904
6883
  const pageCenter = import_Box.Box.Common(
6905
6884
  (0, import_utils.compact)(rootShapes.map(({ id }) => this.getShapePageBounds(id)))
6906
6885
  ).center;
6907
6886
  const offset = import_Vec.Vec.Sub(point, pageCenter);
6908
- this.updateShapes(
6909
- rootShapes.map(({ id }) => {
6910
- const s = this.getShape(id);
6911
- const localRotation = this.getShapeParentTransform(id).decompose().rotation;
6912
- const localDelta = import_Vec.Vec.Rot(offset, -localRotation);
6913
- return { id: s.id, type: s.type, x: s.x + localDelta.x, y: s.y + localDelta.y };
6914
- })
6915
- );
6887
+ if (offset.x !== 0 || offset.y !== 0) {
6888
+ this.updateShapes(
6889
+ rootShapes.map(({ id }) => {
6890
+ const s = this.getShape(id);
6891
+ const localRotation = this.getShapeParentTransform(id).decompose().rotation;
6892
+ const localDelta = import_Vec.Vec.Rot(offset, -localRotation);
6893
+ return { id: s.id, type: s.type, x: s.x + localDelta.x, y: s.y + localDelta.y };
6894
+ })
6895
+ );
6896
+ }
6916
6897
  if ((0, import_tlschema.isPageId)(pasteParentId)) {
6917
6898
  const currentRootShapes = (0, import_utils.compact)(rootShapes.map((s) => this.getShape(s.id)));
6918
- const { reparenting } = (0, import_reparenting.getDroppedShapesToNewParents)(this, currentRootShapes);
6899
+ const { reparenting } = (0, import_reparenting.getDroppedShapesToNewParents)(
6900
+ this,
6901
+ currentRootShapes,
6902
+ (shape, parent) => {
6903
+ if (shapeIdMap.has(parent.id)) return false;
6904
+ const shapeBounds = this.getShapePageBounds(shape);
6905
+ const parentBounds = this.getShapePageBounds(parent);
6906
+ if (!shapeBounds || !parentBounds) return false;
6907
+ return parentBounds.containsPoint(shapeBounds.center);
6908
+ }
6909
+ );
6919
6910
  reparenting.forEach((childrenToReparent, newParentId) => {
6920
6911
  if (childrenToReparent.length === 0) return;
6921
6912
  this.reparentShapes(
@@ -6924,6 +6915,17 @@ class Editor extends (_a = import_eventemitter3.default, _getIsShapeHiddenCache_
6924
6915
  );
6925
6916
  });
6926
6917
  }
6918
+ const newShapeIdSet = new Set(newShapes.map((s) => s.id));
6919
+ const shapesToKickout = rootShapes.map((s) => s.id).filter((id) => {
6920
+ const shape = this.getShape(id);
6921
+ if (!shape) return false;
6922
+ if ((0, import_tlschema.isPageId)(shape.parentId)) return false;
6923
+ const children = this.getSortedChildIdsForParent(id);
6924
+ return !children.some((childId) => newShapeIdSet.has(childId));
6925
+ });
6926
+ if (shapesToKickout.length > 0) {
6927
+ (0, import_reparenting.kickoutOccludedShapes)(this, shapesToKickout);
6928
+ }
6927
6929
  });
6928
6930
  return this;
6929
6931
  }