Skip to content

Commit a481586

Browse files
committed
refactor: improve box model code elegance
- Extract isInFlowChild and hasVisibleSize predicates for declarative child filtering in computeChildGaps - Cache isColumnAxis to reduce repeated axis checks in computeAxisGaps - Extract currentRect/nextRect locals to eliminate array index repetition - Move BoxModelLayerName type to module scope per AGENTS.md guidelines
1 parent 20b2642 commit a481586

2 files changed

Lines changed: 20 additions & 17 deletions

File tree

packages/react-grab/src/components/overlay-canvas.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ const LAYER_STYLES = {
4545
} as const;
4646

4747
type LayerName = "drag" | "selection" | "grabbed" | "inspect";
48+
type BoxModelLayerName = "margin" | "border" | "padding" | "content";
4849

4950
interface OffscreenLayer {
5051
canvas: OffscreenCanvas | null;
@@ -103,7 +104,6 @@ export const OverlayCanvas: Component<OverlayCanvasProps> = (props) => {
103104
let selectionAnimations: AnimatedBounds[] = [];
104105
let dragAnimation: AnimatedBounds | null = null;
105106
let grabbedAnimations: AnimatedBounds[] = [];
106-
type BoxModelLayerName = "margin" | "border" | "padding" | "content";
107107
let boxModelAnimations: Partial<Record<BoxModelLayerName, AnimatedBounds>> = {};
108108

109109
const canvasColorSpace: PredefinedColorSpace = supportsDisplayP3() ? "display-p3" : "srgb";

packages/react-grab/src/utils/create-box-model-bounds.ts

Lines changed: 19 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -49,26 +49,35 @@ const outsetBounds = (
4949
const maxSide = (sides: BoxSides): number =>
5050
Math.max(sides.top, sides.right, sides.bottom, sides.left);
5151

52+
const isInFlowChild = (child: Element): boolean => {
53+
const childStyle = window.getComputedStyle(child);
54+
return childStyle.display !== "none" && !OUT_OF_FLOW_POSITIONS.has(childStyle.position);
55+
};
56+
57+
const hasVisibleSize = (rect: DOMRect): boolean => rect.width > 0 || rect.height > 0;
58+
5259
const computeAxisGaps = (
5360
childRects: DOMRect[],
5461
contentBounds: OverlayBounds,
5562
axis: "row" | "column",
5663
): GapRect[] => {
64+
const isColumnAxis = axis === "column";
65+
5766
const sortedRects = [...childRects].sort((a, b) =>
58-
axis === "column" ? a.top - b.top : a.left - b.left,
67+
isColumnAxis ? a.top - b.top : a.left - b.left,
5968
);
6069

6170
const gaps: GapRect[] = [];
6271
for (let childIndex = 0; childIndex < sortedRects.length - 1; childIndex++) {
63-
const gapStart =
64-
axis === "column" ? sortedRects[childIndex].bottom : sortedRects[childIndex].right;
65-
const gapEnd =
66-
axis === "column" ? sortedRects[childIndex + 1].top : sortedRects[childIndex + 1].left;
72+
const currentRect = sortedRects[childIndex];
73+
const nextRect = sortedRects[childIndex + 1];
74+
const gapStart = isColumnAxis ? currentRect.bottom : currentRect.right;
75+
const gapEnd = isColumnAxis ? nextRect.top : nextRect.left;
6776
const gapSize = gapEnd - gapStart;
6877

6978
if (gapSize > BOX_MODEL_GAP_THRESHOLD_PX) {
7079
gaps.push(
71-
axis === "column"
80+
isColumnAxis
7281
? { x: contentBounds.x, y: gapStart, width: contentBounds.width, height: gapSize }
7382
: { x: gapStart, y: contentBounds.y, width: gapSize, height: contentBounds.height },
7483
);
@@ -87,16 +96,10 @@ const computeChildGaps = (
8796
return [];
8897
}
8998

90-
const childRects: DOMRect[] = [];
91-
for (const child of element.children) {
92-
const childStyle = window.getComputedStyle(child);
93-
if (childStyle.display === "none" || OUT_OF_FLOW_POSITIONS.has(childStyle.position)) {
94-
continue;
95-
}
96-
const rect = child.getBoundingClientRect();
97-
if (rect.width === 0 && rect.height === 0) continue;
98-
childRects.push(rect);
99-
}
99+
const childRects = Array.from(element.children)
100+
.filter(isInFlowChild)
101+
.map((child) => child.getBoundingClientRect())
102+
.filter(hasVisibleSize);
100103

101104
if (childRects.length < 2) return [];
102105

0 commit comments

Comments
 (0)