Skip to content

Commit 8604491

Browse files
committed
Fixed edge case constraints revalidation bug
1 parent 1249258 commit 8604491

File tree

5 files changed

+80
-2
lines changed

5 files changed

+80
-2
lines changed

integrations/vite/src/routes/Decoder.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@ export function Decoder() {
6969
return (
7070
<Box className="p-2" direction="column" gap={2}>
7171
<div>{children}</div>
72-
<Box className="p-2" direction="row" gap={2} wrap>
72+
<Box className="p-2 overflow-auto" direction="row" gap={2} wrap>
7373
<DebugData
7474
data={{
7575
layout: state.layout,

integrations/vite/tests/resize-events.spec.tsx

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,42 @@ test.describe("resize events", () => {
3838
await expect(page.getByText('"right": 46')).toBeVisible();
3939
});
4040

41+
test("resizing the window should revalidate group layout constraints alt", async ({
42+
page
43+
}) => {
44+
await goToUrl(
45+
page,
46+
<Group>
47+
<Panel id="left" minSize={50} />
48+
<Separator />
49+
<Panel id="right" minSize={50} />
50+
</Group>
51+
);
52+
53+
await expect(page.getByText('"onLayoutCount": 1')).toBeVisible();
54+
await expect(page.getByText('"left": 50')).toBeVisible();
55+
await expect(page.getByText('"right": 50')).toBeVisible();
56+
57+
await page.setViewportSize({
58+
width: 500,
59+
height: 500
60+
});
61+
62+
await expect(page.getByText('"onLayoutCount": 1')).toBeVisible();
63+
await expect(page.getByText('"left": 50')).toBeVisible();
64+
await expect(page.getByText('"right": 50')).toBeVisible();
65+
66+
const bounds = (await page.getByRole("separator").boundingBox())!;
67+
await page.mouse.move(bounds.x, bounds.y);
68+
await page.mouse.down();
69+
await page.mouse.move(0, bounds.y);
70+
71+
// Left would be 5% if the constraints were stale
72+
await expect(page.getByText('"onLayoutCount": 2')).toBeVisible();
73+
await expect(page.getByText('"left": 11')).toBeVisible();
74+
await expect(page.getByText('"right": 89')).toBeVisible();
75+
});
76+
4177
test("resizing the window should notify Panel resize handlers", async ({
4278
page
4379
}) => {

lib/global/mountGroup.ts

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import { update, type SeparatorToPanelsMap } from "./mutableState";
1212
import { calculateDefaultLayout } from "./utils/calculateDefaultLayout";
1313
import { layoutsEqual } from "./utils/layoutsEqual";
1414
import { notifyPanelOnResize } from "./utils/notifyPanelOnResize";
15+
import { objectsEqual } from "./utils/objectsEqual";
1516
import { validatePanelGroupLayout } from "./utils/validatePanelGroupLayout";
1617

1718
export function mountGroup(group: RegisteredGroup) {
@@ -52,7 +53,11 @@ export function mountGroup(group: RegisteredGroup) {
5253

5354
if (
5455
!match.defaultLayoutDeferred &&
55-
layoutsEqual(prevLayout, nextLayout)
56+
layoutsEqual(prevLayout, nextLayout) &&
57+
objectsEqual(
58+
match.derivedPanelConstraints,
59+
nextDerivedPanelConstraints
60+
)
5661
) {
5762
return prevState;
5863
}
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
import { describe, expect, test } from "vitest";
2+
import { objectsEqual } from "./objectsEqual";
3+
4+
const EMPTY = {};
5+
const A = { a: 25, b: 75 };
6+
const B = { a: 75, b: 25 };
7+
const C = { a: 75 };
8+
9+
describe("objectsEqual", () => {
10+
test.each([
11+
[EMPTY, EMPTY, true],
12+
[A, A, true],
13+
[B, B, true],
14+
[EMPTY, A, false],
15+
[A, EMPTY, false],
16+
[A, B, false],
17+
[B, A, false],
18+
[A, C, false],
19+
[C, A, false]
20+
])("objectsEqual: %o, %o -> %o", (a, b, expected) => {
21+
expect(objectsEqual(a, b)).toBe(expected);
22+
});
23+
});

lib/global/utils/objectsEqual.ts

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
export function objectsEqual(a: object, b: object) {
2+
const keys = Object.keys(a);
3+
if (keys.length !== Object.keys(b).length) {
4+
return false;
5+
}
6+
7+
for (const key in a) {
8+
if (a[key as keyof typeof a] !== b[key as keyof typeof b]) {
9+
return false;
10+
}
11+
}
12+
13+
return true;
14+
}

0 commit comments

Comments
 (0)