Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Changelog

## Unreleased
## 4.5.9

- [649](https://github.com/bvaughn/react-resizable-panels/pull/649): Optimization: Replace `useForceUpdate` with `useSyncExternalStore` to avoid side effect of swallowing "click" events in certain cases
- [654](https://github.com/bvaughn/react-resizable-panels/pull/654): **Bugfix** Imperative `Group` method `setLayout` persists layout to in-memory cache
Expand Down
33 changes: 28 additions & 5 deletions integrations/tests/src/components/Clickable.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,19 @@

import { useState } from "react";

export type ClickableProps = { className?: string; id?: string };
export type ClickableProps = {
className?: string;
id?: string;
ignoredDefaultPrevented?: boolean;
};

export function Clickable({ className = "", id }: ClickableProps) {
export function Clickable({
className = "",
id,
ignoredDefaultPrevented
}: ClickableProps) {
const [counts, setCounts] = useState({
click: 0,
pointerDown: 0,
pointerUp: 0
});
Expand All @@ -16,28 +25,42 @@ export function Clickable({ className = "", id }: ClickableProps) {
<pre
className={className}
onPointerDown={(event) => {
if (event.defaultPrevented) {
if (event.defaultPrevented && !ignoredDefaultPrevented) {
return;
}

setCounts({
click: counts.click,
pointerDown: counts.pointerDown + 1,
pointerUp: counts.pointerUp
});
}}
onPointerUp={(event) => {
if (event.defaultPrevented) {
if (event.defaultPrevented && !ignoredDefaultPrevented) {
return;
}

setCounts({
click: counts.click,
pointerDown: counts.pointerDown,
pointerUp: counts.pointerUp + 1
});
}}
onClick={(event) => {
if (event.defaultPrevented && !ignoredDefaultPrevented) {
return;
}

setCounts({
click: counts.click + 1,
pointerDown: counts.pointerDown,
pointerUp: counts.pointerUp
});
}}
>
<code>
{label} down:{counts.pointerDown} up:{counts.pointerUp}
{label} down:{counts.pointerDown} up:{counts.pointerUp} click:
{counts.click}
</code>
</pre>
);
Expand Down
36 changes: 36 additions & 0 deletions integrations/tests/tests/pointer-interactions.spec.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -534,4 +534,40 @@ test.describe("pointer interactions", () => {
await page.mouse.move(x - 25, y);
await expect(separator).toHaveAttribute("data-separator", "inactive");
});

test("should not prevent click events if no drag occurs", async ({
page: mainPage
}) => {
const page = await goToUrl(
mainPage,
<Group className="gap-0">
<Panel className="[&>*]:p-0!" id="left">
<Clickable className="bg-red-300 h-full w-full" />
</Panel>
<Separator className="min-w-[1px] w-[1px]" id="separator" />
<Panel id="right" />
</Group>
);

const separator = page.getByRole("separator");
const hitAreaBox = await separator.boundingBox();
const { x, y } = getCenterCoordinates(hitAreaBox!);

const panel = page.getByText("click");
await expect(panel).toContainText("click:0");

// A click that does not resize should not be blocked
await page.mouse.move(x - 2, y);
await page.mouse.down();
await page.mouse.up();
// await page.mouse.click(x - 2, y);
await expect(panel).toContainText("click:1");

// A click that resizes should be blocked
await page.mouse.move(x - 2, y);
await page.mouse.down();
await page.mouse.move(x - 3, y);
await page.mouse.up();
await expect(panel).toContainText("click:1");
});
});
6 changes: 5 additions & 1 deletion lib/global/utils/adjustLayoutByDelta.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2245,9 +2245,13 @@ describe("adjustLayoutByDelta", () => {
(
[
[-4, c([collapsible, {}]), l([46, 54])],
[-6, c([collapsible, {}]), l([44, 56])],
[-4, c([{}, collapsible]), l([46, 54])],
[-6, c([{}, collapsible]), l([44, 56])],
[4, c([collapsible, {}]), l([54, 46])],
[4, c([{}, collapsible]), l([54, 46])]
[6, c([collapsible, {}]), l([56, 44])],
[4, c([{}, collapsible]), l([54, 46])],
[6, c([{}, collapsible]), l([56, 44])]
] satisfies [number, PanelConstraints[], Layout][]
).forEach(([delta, panelConstraints, expectedLayout]) => {
expect(
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "react-resizable-panels",
"version": "4.5.9-alpha.0",
"version": "4.5.9",
"type": "module",
"author": "Brian Vaughn <brian.david.vaughn@gmail.com> (https://github.com/bvaughn/)",
"contributors": [
Expand Down
Loading