import * as React from 'react'; import { PanelImperativeHandle } from 'react-resizable-panels'; /** * Keeps a resizable shell rail (library secondary nav, docked Ask Leo) at the * pixel width the user last chose. * * Why this exists — `react-resizable-panels` stores layout as percentages. A * pixel `defaultSize` is converted once, against the sum of the panel widths it * can see at that instant. In the app shell that instant is a bad one: the * primary sidebar is still expanded, so the sum is ~200px short and a rail asked * for 256px is registered as a percentage of the narrower row. When the sidebar * collapses, the row grows and the percentage pays out wider than asked * (256 → 301 at 1440px). `groupResizeBehavior: "preserve-pixel-size"` does not * catch it, because the group never observes a resize — the conversion simply * used a width that was already stale. * * That alone would be a cosmetic 45px. The damage came from persisting it: * `onResize` fires for layout recomputation as well as drags, so the inflated * width was saved and became the next session's `defaultSize`, which inflated * again. Measured on a fresh profile: 256 → 301 → 354 → 416 → 480 (the ceiling), * one step per page load, so a rail nobody ever dragged ends up twice its * intended width. * * The fix is to treat the percentage layout as an approximation and re-assert * the pixel width once, on the frame after the panel mounts, and to persist only * sizes that arrive after that (a drag). `usePanelCallbackRef` gives us the * panel handle as state, so the correction re-runs on every panel mount — * compact ↔ expanded, Leo opening, route changes — not just the first one. */ /** Props to spread onto the rail's `ResizablePanel`. */ type ShellRailPanelProps = { defaultSize: string; minSize: string; maxSize: string; groupResizeBehavior: "preserve-pixel-size"; panelRef: React.Dispatch>; onResize: (size: { inPixels: number; }) => void; }; type UseShellRailWidthOptions = { /** `usePersistedState` key, e.g. `shell:secondary-panel-width`. */ storageKey: string; defaultWidth: number; minWidth: number; maxWidth: number; /** Keeps a stored width inside `minWidth`..`maxWidth`. Must be stable. */ clamp: (width: number) => number; /** Bump to drop widths written by an older, broken version. */ version?: number; }; declare function useShellRailWidth({ storageKey, defaultWidth, minWidth, maxWidth, clamp, version, }: UseShellRailWidthOptions): { width: number; panelProps: ShellRailPanelProps; }; export { type ShellRailPanelProps, type UseShellRailWidthOptions, useShellRailWidth };