diff --git a/packages/react-resizable-panels/CHANGELOG.md b/packages/react-resizable-panels/CHANGELOG.md index 437d59678..6f63241bb 100644 --- a/packages/react-resizable-panels/CHANGELOG.md +++ b/packages/react-resizable-panels/CHANGELOG.md @@ -1,5 +1,8 @@ # Changelog +## 0.0.31 +* [#71](https://github.com/bvaughn/react-resizable-panels/pull/71): Added `getSize` and `getCollapsed` to imperative API exposed by `Panel`. + ## 0.0.30 * [#68](https://github.com/bvaughn/react-resizable-panels/pull/68): Reduce volume/frequency of local storage writes for `PanelGroup`s configured to _auto-save_. * Added `onLayout` prop to `PanelGroup` to be called when group layout changes. Note that some form of debouncing is recommended before processing these values (e.g. saving to a database). diff --git a/packages/react-resizable-panels/README.md b/packages/react-resizable-panels/README.md index f75949499..95779703e 100644 --- a/packages/react-resizable-panels/README.md +++ b/packages/react-resizable-panels/README.md @@ -52,8 +52,10 @@ import { Panel, PanelGroup, PanelResizeHandle } from "react-resizable-panels"; `Panel` components also expose an imperative API for manual resizing: | method | description | :--------------------------- | :--- -| `collapse` | If panel is `collapsible`, collapse it fully. -| `expand` | If panel is currently _collapsed_, expand it to its most recent size. +| `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`). +| `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`). ### `PanelResizeHandle` diff --git a/packages/react-resizable-panels/src/Panel.ts b/packages/react-resizable-panels/src/Panel.ts index 923ac3e99..0ca40dfc9 100644 --- a/packages/react-resizable-panels/src/Panel.ts +++ b/packages/react-resizable-panels/src/Panel.ts @@ -34,6 +34,8 @@ export type PanelProps = { export type ImperativePanelHandle = { collapse: () => void; expand: () => void; + getCollapsed(): boolean; + getSize(): number; resize: (percentage: number) => void; }; @@ -72,16 +74,6 @@ function PanelWithForwardedRef({ unregisterPanel, } = context; - useImperativeHandle( - forwardedRef, - () => ({ - collapse: () => collapsePanel(panelId), - expand: () => expandPanel(panelId), - resize: (percentage: number) => resizePanel(panelId, percentage), - }), - [collapsePanel, expandPanel, panelId, resizePanel] - ); - // Use a ref to guard against users passing inline props const callbacksRef = useRef<{ onCollapse: PanelOnCollapse | null; @@ -142,6 +134,31 @@ function PanelWithForwardedRef({ const style = getPanelStyle(panelId); + const committedValuesRef = useRef<{ + size: number; + }>({ + size: parseSizeFromStyle(style), + }); + useIsomorphicLayoutEffect(() => { + committedValuesRef.current.size = parseSizeFromStyle(style); + }); + + useImperativeHandle( + forwardedRef, + () => ({ + collapse: () => collapsePanel(panelId), + expand: () => expandPanel(panelId), + getCollapsed() { + return committedValuesRef.current.size === 0; + }, + getSize() { + return committedValuesRef.current.size; + }, + resize: (percentage: number) => resizePanel(panelId, percentage), + }), + [collapsePanel, expandPanel, panelId, resizePanel] + ); + return createElement(Type, { children, className: classNameFromProps, @@ -167,3 +184,13 @@ export const Panel = forwardRef( // See github.com/parcel-bundler/parcel/issues/8724 (PanelWithForwardedRef as any).displayName = "Panel"; (Panel as any).displayName = "forwardRef(Panel)"; + +// HACK +function parseSizeFromStyle(style: CSSProperties): number { + const { flexGrow } = style; + if (typeof flexGrow === "string") { + return parseFloat(flexGrow); + } else { + return flexGrow; + } +}