feat(editor): pass through clicks on transparent image pixels#7942
Merged
steveruizok merged 7 commits intomainfrom Feb 24, 2026
Merged
feat(editor): pass through clicks on transparent image pixels#7942steveruizok merged 7 commits intomainfrom
steveruizok merged 7 commits intomainfrom
Conversation
Add a rejectHit() method to Geometry2d that allows shapes to reject hit test results after the standard geometry check passes. Use this in a new ImageRectangle2d geometry that checks a cached alpha map to detect transparent pixels in PNG, WebP, and GIF images. When a click lands on a transparent pixel, the shape is skipped and the click passes through to shapes behind it. Closes #7529
|
The latest updates on your projects. Learn more about Vercel for GitHub.
5 Skipped Deployments
|
Override hitTestPoint on ImageRectangle2d so that selection paths using isPointInShape / getSelectedShapeAtPoint also skip transparent pixels. Extract shared mapToImageCoords helper with [0,1] clamping to handle edge-margin hits slightly outside shape bounds. Co-Authored-By: Claude Opus 4.6 <[email protected]>
When crop.isCircle was set, getGeometry() returned a plain Ellipse2d that bypassed transparency hit logic. Add ImageEllipse2d (mirrors ImageRectangle2d) with hitTestPoint/rejectHit alpha checking, and use it for circle-cropped transparent images. Co-Authored-By: Claude Opus 4.6 <[email protected]>
kaneel
reviewed
Feb 16, 2026
Contributor
kaneel
left a comment
There was a problem hiding this comment.
Don't mind the tiny "what ifs" on speed.
But maybe we can improve the way we check mimetypes and actually have a better map of all possible mimetypes.
mimecuvalo
reviewed
Feb 18, 2026
mimecuvalo
reviewed
Feb 18, 2026
mimecuvalo
reviewed
Feb 18, 2026
mimecuvalo
reviewed
Feb 18, 2026
…ough - Rename rejectHit to ignoreHit on Geometry2d base class (fixes naming mismatch where Editor.ts already used ignoreHit) - Extract shared alpha hit-testing logic from ImageRectangle2d and ImageEllipse2d into ImageAlphaCache helpers to reduce duplication - Replace inline mimeType string checks with TRANSPARENT_IMAGE_MIMETYPES constant array Co-Authored-By: Claude Opus 4.6 <[email protected]>
…ha extraction Use createImageBitmap with resize options to move the heavy image resize off the main thread during alpha data preloading. Reuse a single OffscreenCanvas instance across preloads instead of creating a new canvas element each time. Falls back to sync resize for browsers without createImageBitmap resize support. Co-Authored-By: Claude Opus 4.6 <[email protected]>
…ough - Use TRANSPARENT_IMAGE_MIMETYPES constant consistently (no more substring matching) - Merge ImageRectangle2d and ImageEllipse2d into single file (ImageAlphaGeometry.ts) - Use Uint32Array >>> 24 trick for faster alpha byte extraction - Fix concurrent OffscreenCanvas corruption by moving canvas ops after async bitmap creation - Add image/avif to transparent mimetypes Co-Authored-By: Claude Opus 4.6 <[email protected]>
preloadAlphaData was keyed by the resolved URL (which may be a CDN/optimized URL), but getGeometry looked up alpha data by asset.props.src. When these differed, the cache always missed and click-through never activated. Now preloadAlphaData accepts a separate cacheKey param. The component passes asset.props.src as the key, ensuring getGeometry finds the preloaded data. Co-Authored-By: Claude Opus 4.6 <[email protected]>
There was a problem hiding this comment.
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.
steveruizok
added a commit
that referenced
this pull request
Feb 27, 2026
Add 12 new entries from PRs merged since v4.4.0: - Featured: click-through on transparent image pixels (#7942) - API: enum-to-const-object refactor (#8084) - Improvements: SVG sanitizer (#7896), save-on-blur (#8037) - Bug fixes: cross-origin download (#8090), zero-size draw (#8067), rich text toolbar cleanup (#8050), zoom threshold (#8040), selection foreground fallback (#8011), sticky note SVG shadow (#7934), arrow frame clamping (#7932), zero pressure draw (#5693)
This was referenced Feb 27, 2026
github-merge-queue bot
pushed a commit
that referenced
this pull request
Mar 4, 2026
Update `next.mdx` release notes to cover all SDK-relevant PRs merged to main since v4.4.0. Highlights: - Display values system (#8121) with breaking changes and migration guide - Click-through on transparent image pixels (#7942) - `Editor.resizeToBounds()` (#8120) - SVG sanitization (#7896) - TypeScript enum-to-const refactoring (#8084) - 14 bug fixes and 4 improvements ### Change type - [x] `other` ### Test plan 1. Verify the release notes render correctly on the docs site ### Release notes - Update next release notes with changes since v4.4.0. <!-- CURSOR_SUMMARY --> --- > [!NOTE] > **Low Risk** > Low risk: documentation-only changes updating release notes content and date, with no runtime/code behavior impact. > > **Overview** > Updates `apps/docs/content/releases/next.mdx` for the upcoming release by refreshing the date and replacing the brief blurb with expanded release notes. > > Documents new SDK surface area (`Geometry2d.ignoreHit`, `Editor.resizeToBounds`, `sanitizeSvg`), highlights click-through on transparent image pixels, and adds a list of recent improvements and bug fixes (paste parenting, link/alt-text persistence, SVG sanitization behavior, circular-dependency cleanup, and several crash/export/sync fixes). > > <sup>Written by [Cursor Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit 5f7dc0a. This will update automatically on new commits. Configure [here](https://cursor.com/dashboard?tab=bugbot).</sup> <!-- /CURSOR_SUMMARY -->
1 task
github-merge-queue bot
pushed a commit
that referenced
this pull request
Mar 18, 2026
In order to publish the v4.5.0 release notes and record the v4.4.1 patch, this PR archives release notes and resets `next.mdx` for the next cycle. **v4.5.0.mdx** (new file): - Archived from `next.mdx` with full frontmatter, keywords, and GitHub release link - Featured sections: click-through on transparent image pixels (#7942), breaking `EmbedShapeUtil.configure()` change (#8034) - API changes: `Editor.getResizeScaleFactor()` (#8042), `TLImageAsset.pixelRatio` (#8163), `sanitizeSvg` (#7896), `experimental__onDropOnCanvas` (#7911), enum-to-const refactoring (#8084) - 6 improvements and 20 bug fixes from production **v4.4.0.mdx:** - Add v4.4.1 patch release section with tooltip positioning fix (#8171) - Add v4.4.1 to keywords **next.mdx:** - Reset with `last_version: v4.5.0` and empty content ### Change type - [x] `other` ### Code changes | Section | LOC change | | ------------- | ------------- | | Documentation | +128 / -107 |
huppy-bot bot
pushed a commit
that referenced
this pull request
Mar 18, 2026
In order to publish the v4.5.0 release notes and record the v4.4.1 patch, this PR archives release notes and resets `next.mdx` for the next cycle. **v4.5.0.mdx** (new file): - Archived from `next.mdx` with full frontmatter, keywords, and GitHub release link - Featured sections: click-through on transparent image pixels (#7942), breaking `EmbedShapeUtil.configure()` change (#8034) - API changes: `Editor.getResizeScaleFactor()` (#8042), `TLImageAsset.pixelRatio` (#8163), `sanitizeSvg` (#7896), `experimental__onDropOnCanvas` (#7911), enum-to-const refactoring (#8084) - 6 improvements and 20 bug fixes from production **v4.4.0.mdx:** - Add v4.4.1 patch release section with tooltip positioning fix (#8171) - Add v4.4.1 to keywords **next.mdx:** - Reset with `last_version: v4.5.0` and empty content ### Change type - [x] `other` ### Code changes | Section | LOC change | | ------------- | ------------- | | Documentation | +128 / -107 |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #7529
In order to allow clicks on transparent parts of PNG/WebP/GIF/AVIF images to pass through to shapes behind them, this PR adds an
ignoreHit()mechanism to the geometry system and uses it to check image alpha data at the click point.pr-7942-walkthrough.mp4
How it works
Geometry2d.ignoreHit(point)— New method on the base geometry class (default:false). Called after a standard hit test succeeds. If it returnstrue, the shape is skipped and the click passes through to shapes behind it. Also wired throughTransformedGeometry2dvia inverse matrix.ImageAlphaCache— Preloads and caches a downsampled (max 256×256) alpha channel for each image. UsesUint32Arraywith unsigned right shift for efficient alpha byte extraction. The preload URL and cache key are separated so resolved/CDN URLs work correctly withasset.props.srclookups. A sharedOffscreenCanvasis reused across preloads, with canvas operations kept synchronous after the asynccreateImageBitmapto prevent concurrent corruption.ImageAlphaGeometry.ts— ContainsImageRectangle2d(extendsRectangle2d) andImageEllipse2d(extendsEllipse2d), both withignoreHitandhitTestPointoverrides that map shape-space points to normalized image coordinates (accounting for crop, flipX, flipY) and check the alpha cache. Coordinates are clamped to[0,1]so edge-margin hits slightly outside bounds map to the nearest edge pixel.ImageShapeUtil—getGeometry()now returnsImageRectangle2dfor transparent image formats, orImageEllipse2dwhencrop.isCircleis set. TheImageShapecomponent preloads alpha data when the resolved URL is available, usingasset.props.srcas the cache key.Editor.getShapeAtPoint— After a filled shape geometry hit succeeds, callsgeometry.ignoreHit(pointInShapeSpace). Iftrue, continues to check shapes behind it.The
hitTestPointoverride on both geometry classes ensures that selection paths usingisPointInShape/getSelectedShapeAtPointalso skip transparent pixels. Before alpha data is loaded, images behave as fully opaque (no change from current behavior).Change type
featureTest plan
yarn dev→ import a PNG with transparency over another shapeRelease notes
API changes
Geometry2d.ignoreHit(point)— allows geometries to reject successful hit tests (e.g. for transparent pixels)