Skip to content

refactor(editor): simplify putContentOntoCurrentPage paste-parent and positioning logic#8057

Merged
steveruizok merged 2 commits intomainfrom
steveruiz/refactor-paste-parent-logic
Feb 24, 2026
Merged

refactor(editor): simplify putContentOntoCurrentPage paste-parent and positioning logic#8057
steveruizok merged 2 commits intomainfrom
steveruiz/refactor-paste-parent-logic

Conversation

@steveruizok
Copy link
Copy Markdown
Collaborator

@steveruizok steveruizok commented Feb 20, 2026

In order to make the paste logic in putContentOntoCurrentPage easier to reason about and extend, this PR replaces the convoluted paste-parent selection and positioning code with clearer, well-separated logic paths.

Change type

  • improvement

Test plan

  1. Copy shapes and paste them — they should appear at the viewport center or in-place if already visible
  2. Select a frame, copy shapes, paste — they should land inside the selected frame
  3. Right-click inside a frame and paste — shapes should land inside that frame at the cursor position
  4. Copy a frame that is the same size as a selected frame and paste — the duplicate should not be reparented into the original (the "duplicating a frame" case)
  5. Paste shapes that overlap multiple frames — only shapes whose center is inside a frame should be auto-reparented
  6. Copy shapes inside a group, paste — they should land in the correct parent
  • Unit tests

Release notes

  • Simplify paste-parent selection to use canReceiveNewChildrenOfType instead of frame-specific checks
  • Prevent edge-only overlap from auto-reparenting pasted shapes into adjacent frames

Note

Medium Risk
Changes core paste/reparenting and positioning logic, which can subtly affect many copy/paste scenarios across containers and frames despite test coverage.

Overview
Refactors Editor.putContentOntoCurrentPage paste behavior into clearer paths for paste-at-cursor, standard paste, and preserve-position pastes, using canReceiveNewChildrenOfType (with optional chaining) to choose a valid container from the selection/ancestors and avoiding pasting content into itself (duplicate-container case).

Updates positioning rules to center pastes within the chosen parent, keep coordinates for preservePosition, otherwise choose between original vs viewport center based on viewport overlap, and skips the updateShapes pass when the computed offset is zero.

Tightens page-level auto-reparenting into frames by filtering out source shapes and requiring the pasted shape’s bounds center to be inside the candidate parent (preventing reparenting on edge-only overlap); updates paste.test.ts expectations accordingly.

Written by Cursor Bugbot for commit c7e5719. This will update automatically on new commits. Configure here.

… positioning logic

Replace the convoluted paste-parent selection and positioning logic with
clearer, well-separated code paths for paste-at-cursor vs standard paste.

- Generalize frame-specific checks to use canReceiveNewChildrenOfType
- Replace lowest-depth ancestor walk with findShapeAncestor
- Replace isDuplicating detection with shapeIdMap.has() guard
- Use collides() instead of includes() for viewport overlap check
- Add center-containment filter to auto-reparent callback to prevent
  edge-only overlap from swallowing pasted shapes into adjacent frames
- Remove frame-deduplication offset logic
@vercel
Copy link
Copy Markdown

vercel bot commented Feb 20, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
examples Ready Ready Preview Feb 24, 2026 5:55pm
5 Skipped Deployments
Project Deployment Actions Updated (UTC)
analytics Ignored Ignored Preview Feb 24, 2026 5:55pm
chat-template Ignored Ignored Preview Feb 24, 2026 5:55pm
tldraw-docs Ignored Ignored Preview Feb 24, 2026 5:55pm
tldraw-shader Ignored Ignored Preview Feb 24, 2026 5:55pm
workflow-template Ignored Ignored Preview Feb 24, 2026 5:55pm

Request Review

@huppy-bot huppy-bot bot added the improvement Product improvement label Feb 20, 2026
Copy link
Copy Markdown

@cursor cursor bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes and found 2 potential issues.

Bugbot Autofix is OFF. To automatically fix reported issues with Cloud Agents, enable Autofix in the Cursor dashboard.

pasteParentId = this.getShape(pasteParentId)!.parentId
if (selectedParent) {
pasteParentId = selectedParent.id
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Paste can target offscreen selected parent

Medium Severity

The standard paste path no longer checks whether the chosen selectedParent (or its ancestors) is inside the viewport before setting pasteParentId. This can paste new shapes into an offscreen container and then center them within that container, making the paste appear to “do nothing” because the result is not visible.

Fix in Cursor Fix in Web

if (!candidate) {
selectedParent = null
break
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Non-null assertion may crash during paste

High Severity

candidate computation uses this.getShape(shape.parentId)! when shape.parentId is a shape id. If the parent shape is missing (e.g., transiently deleted/out-of-sync state), this dereference can throw during paste, crashing the action instead of falling back to currentPageId.

Fix in Cursor Fix in Web

@kaneel kaneel mentioned this pull request Feb 23, 2026
7 tasks
@kaneel
Copy link
Copy Markdown
Contributor

kaneel commented Feb 23, 2026

Worth a shot addressing some of the claude comments but as far as I'm concerned, this is working for the "paste at pointer" feature and the test are passing (in comparison with my "fix" which broke a lot of unrelated tests)

@steveruizok steveruizok marked this pull request as draft February 23, 2026 13:03
@steveruizok steveruizok marked this pull request as draft February 23, 2026 13:03
@steveruizok
Copy link
Copy Markdown
Collaborator Author

need to fire kick out children when pasting into a paste parent

Import and call kickoutOccludedShapes during paste to relocate pasted root shapes that end up outside their parent container. The change computes which pasted root shapes are children of a container (not the page) and that do not contain any newly pasted children, then kicks out those shapes to avoid them being occluded or unintentionally nested. Adds a test that copies three spaced rectangles, pastes them into a smaller frame, and asserts the centered shape remains a child while the outlying shapes are moved to the page.
@steveruizok steveruizok marked this pull request as ready for review February 24, 2026 18:23
@steveruizok steveruizok added this pull request to the merge queue Feb 24, 2026
Merged via the queue into main with commit 9c18c7e Feb 24, 2026
17 checks passed
@steveruizok steveruizok deleted the steveruiz/refactor-paste-parent-logic branch February 24, 2026 18:28
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

improvement Product improvement

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants