Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add refs to underlying DOM elements in imperative API #249

Closed
Closed
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
13 changes: 10 additions & 3 deletions packages/react-resizable-panels/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,10 @@ import { Panel, PanelGroup, PanelResizeHandle } from "react-resizable-panels";
`PanelGroup` components also expose an imperative API for manual resizing:
| method | description
| :-------------------------------- | :---
| `setLayout(panelSizes: number[])` | Resize panel group to the specified _panelSizes_ (`[1 - 100, ...]`).
| `getId(): string` | Gets the panel group's ID.
| `getLayout(): number[]` | Gets the panel group's current _layout_ (`[1 - 100, ...]`).
| `setLayout(layout: number[])` | Resize panel group to the specified _layout_ (`[1 - 100, ...]`).
| `elementRef: RefObject<HTMLElement>` | A ref to the underlying DOM element for the panel group.

### `Panel`

Expand All @@ -73,9 +76,13 @@ import { Panel, PanelGroup, PanelResizeHandle } from "react-resizable-panels";
| :--------------------------- | :---
| `collapse()` | If panel is `collapsible`, collapse it fully.
| `expand()` | If panel is currently _collapsed_, expand it to its most recent size.
| `getCollapsed(): boolean` | Returns `true` if the panel is currently _collapsed_ (`size === 0`).
| `getId(): string` | Gets the ID of the panel.
| `getSize(): number` | Gets the current size of the panel as a percentage (`1 - 100`).
| `isCollapsed(): boolean` | Returns `true` if the panel is currently _collapsed_ (`size === 0`).
| `isExpanded(): boolean` | Returns `true` if the panel is currently _not collapsed_ (`!isCollapsed()`).
| `getSize(): number` | Returns the most recently commited size of the panel as a percentage (`1 - 100`).
| `resize(percentage: number)` | Resize panel to the specified _percentage_ (`1 - 100`).
| `resize(size: number)` | Resize panel to the specified _percentage_ (`1 - 100`).
| `elementRef: RefObject<HTMLElement>` | A ref to the underlying DOM element for the panel.

### `PanelResizeHandle`

Expand Down
6 changes: 6 additions & 0 deletions packages/react-resizable-panels/src/Panel.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import {
useContext,
useImperativeHandle,
useRef,
RefObject,
} from "./vendor/react";

export type PanelOnCollapse = () => void;
Expand Down Expand Up @@ -52,6 +53,7 @@ export type ImperativePanelHandle = {
isCollapsed: () => boolean;
isExpanded: () => boolean;
resize: (size: number) => void;
elementRef: RefObject<HTMLElement>;
};

export type PanelProps = Omit<HTMLAttributes<ElementType>, "id" | "onResize"> &
Expand Down Expand Up @@ -112,6 +114,8 @@ export function PanelWithForwardedRef({

const panelId = useUniqueId(idFromProps);

const panelElementRef = useRef<HTMLElement>(null);

const panelDataRef = useRef<PanelData>({
callbacks: {
onCollapse,
Expand Down Expand Up @@ -201,6 +205,7 @@ export function PanelWithForwardedRef({
resize: (size: number) => {
resizePanel(panelDataRef.current, size);
},
elementRef: panelElementRef,
}),
[
collapsePanel,
Expand All @@ -223,6 +228,7 @@ export function PanelWithForwardedRef({
...style,
...styleFromProps,
},
ref: panelElementRef,

// CSS selectors
"data-panel": "",
Expand Down
6 changes: 6 additions & 0 deletions packages/react-resizable-panels/src/PanelGroup.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ import {
useMemo,
useRef,
useState,
RefObject,
} from "./vendor/react";

const LOCAL_STORAGE_DEBOUNCE_INTERVAL = 100;
Expand All @@ -48,6 +49,7 @@ export type ImperativePanelGroupHandle = {
getId: () => string;
getLayout: () => number[];
setLayout: (layout: number[]) => void;
elementRef: RefObject<HTMLElement>;
};

export type PanelGroupStorage = {
Expand Down Expand Up @@ -106,6 +108,8 @@ function PanelGroupWithForwardedRef({
const [dragState, setDragState] = useState<DragState | null>(null);
const [layout, setLayout] = useState<number[]>([]);

const panelGroupElementRef = useRef<HTMLElement>(null);

const panelIdToLastNotifiedSizeMapRef = useRef<Record<string, number>>({});
const panelSizeBeforeCollapseRef = useRef<Map<string, number>>(new Map());
const prevDeltaRef = useRef<number>(0);
Expand Down Expand Up @@ -184,6 +188,7 @@ function PanelGroupWithForwardedRef({
);
}
},
elementRef: panelGroupElementRef,
}),
[]
);
Expand Down Expand Up @@ -804,6 +809,7 @@ function PanelGroupWithForwardedRef({
...style,
...styleFromProps,
},
ref: panelGroupElementRef,

// CSS selectors
"data-panel-group": "",
Expand Down