feat(clipping): accept [top,right,bottom,left] margin tuple#46
Merged
Conversation
Widen the `clipping` prop type to `boolean | [number, number, number, number]` so callers can opt into clipping that lets children spill outward by a per-side pixel amount before the scissor cuts them off (negative values inset). The setter normalizes the tuple into four scalar margin fields and keeps `props.clipping` a plain boolean, so the hot-path `=== true`/`=== false` checks and the per-frame `calculateClippingRect` math stay branch-free and allocation-free. Optimized for the common case where clipping is set once at construction: the setter early-returns on identical re-assignment. Also expands the node's `strictBound` by the same margins so descendants sitting inside the margin region aren't culled as out-of-bounds before the scissor sees them. Adds unit tests for setter normalization, the clip-rect math, parent-clip intersection, and the rotation guard, plus a `clipping-margin` visual regression example covering boolean, per-side, all-sides, and inset variants. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
… fields The four `_clipMarginT/R/B/L` fields were sized for a hot path that never materializes — clipping margins are an uncommon opt-in, not a per-frame read. Storing the tuple directly on `props.clipping` removes four fields per CoreNode instance and the constructor's save-and-restore plumbing. Hot-path comparisons that previously checked `props.clipping === true` now use `!== false`; the two places that need the per-side values (`calculateClippingRect`, `createRenderBounds`) extract them inline with an `Array.isArray` check, which only runs when the corresponding update bit is set. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
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.
Summary
clippingprop type toboolean | [number, number, number, number]so callers can let children spill outward by a per-side pixel amount before the scissor clips them. Negative values inset the clip rect.props.clippinga plain boolean, so hot-path=== true/=== falsechecks and the per-framecalculateClippingRectmath stay branch-free and allocation-free. Optimized for the common case whereclippingis set once at construction — the setter early-returns on identical re-assignment.strictBoundby the same margins so descendants sitting inside the margin region aren't culled as out-of-bounds before the scissor sees them.Why
Today
clipping: trueis all-or-nothing — useful for hard edges, but several common UI patterns (focus halos, drop shadows, hover scales) want a clip that's slightly looser than the node's geometry. Reusing the[top, right, bottom, left]shape fromboundsMarginkeeps the API consistent.Reviewer notes
SdfRenderOpscissor) and Canvas2D (ctx.clip) read the existingclippingRect, which is the only thing the new code adjusts.examples/tests/clipping-margin.tsis not committed yet — needspnpm test:visual:update --ci(or CI on this PR) to generate the certified PNG. Please verify the diff before merging.Test plan
pnpm build— cleanpnpm test— 209 passed (13 new tests for the clipping property)pnpm lint— no new warnings on touched filesclipping-margin-1.png)🤖 Generated with Claude Code