@zag-js/splitter
Version:
Core logic for the splitter widget implemented as a state machine
228 lines (220 loc) • 7.13 kB
text/typescript
import * as _zag_js_anatomy from '@zag-js/anatomy';
import { RequiredBy, DirectionProperty, CommonProperties, PropTypes, NormalizeProps } from '@zag-js/types';
import * as _zag_js_core from '@zag-js/core';
import { Service, EventObject, Machine } from '@zag-js/core';
declare const anatomy: _zag_js_anatomy.AnatomyInstance<"root" | "panel" | "resizeTrigger">;
type PanelId = string;
type ResizeTriggerId = `${PanelId}:${PanelId}`;
interface PanelData {
/**
* The id of the panel.
*/
id: PanelId;
/**
* The order of the panel. useful of you intend to conditionally render the panel.
*/
order?: number | undefined;
/**
* The minimum size of the panel.
*/
minSize?: number | undefined;
/**
* The maximum size of the panel.
*/
maxSize?: number | undefined;
/**
* Whether the panel is collapsible.
*/
collapsible?: boolean | undefined;
/**
* The size of the panel when collapsed.
*/
collapsedSize?: number | undefined;
}
interface ResizeDetails {
size: number[];
resizeTriggerId: string | null;
layout: string;
expandToSizes: Record<string, number>;
}
interface ResizeEndDetails {
size: number[];
resizeTriggerId: string | null;
}
interface ExpandCollapseDetails {
panelId: string;
size: number;
}
type ElementIds = Partial<{
root: string;
resizeTrigger: (id: string) => string;
label: (id: string) => string;
panel: (id: string | number) => string;
}>;
interface SplitterProps extends DirectionProperty, CommonProperties {
/**
* The orientation of the splitter. Can be `horizontal` or `vertical`
* @default "horizontal"
*/
orientation?: "horizontal" | "vertical" | undefined;
/**
* The controlled size data of the panels
*/
size?: number[] | undefined;
/**
* The initial size of the panels when rendered.
* Use when you don't need to control the size of the panels.
*/
defaultSize?: number[] | undefined;
/**
* The size constraints of the panels.
*/
panels: PanelData[];
/**
* Function called when the splitter is resized.
*/
onResize?: ((details: ResizeDetails) => void) | undefined;
/**
* Function called when the splitter resize starts.
*/
onResizeStart?: (() => void) | undefined;
/**
* Function called when the splitter resize ends.
*/
onResizeEnd?: ((details: ResizeEndDetails) => void) | undefined;
/**
* The ids of the elements in the splitter. Useful for composition.
*/
ids?: ElementIds | undefined;
/**
* The number of pixels to resize the panel by when the keyboard is used.
*/
keyboardResizeBy?: number | null | undefined;
/**
* The nonce for the injected splitter cursor stylesheet.
*/
nonce?: string | undefined;
/**
* Function called when a panel is collapsed.
*/
onCollapse?: ((details: ExpandCollapseDetails) => void) | undefined;
/**
* Function called when a panel is expanded.
*/
onExpand?: ((details: ExpandCollapseDetails) => void) | undefined;
}
type PropWithDefault = "orientation" | "panels";
interface DragState {
resizeTriggerId: string;
resizeTriggerRect: DOMRect;
initialCursorPosition: number;
initialSize: number[];
}
interface KeyboardState {
resizeTriggerId: string;
}
interface Context {
dragState: DragState | null;
keyboardState: KeyboardState | null;
size: number[];
}
interface Refs {
panelSizeBeforeCollapse: Map<string, number>;
panelIdToLastNotifiedSizeMap: Map<string, number>;
prevDelta: number;
}
interface SplitterSchema {
state: "idle" | "hover:temp" | "hover" | "dragging" | "focused";
tag: "focus";
props: RequiredBy<SplitterProps, PropWithDefault>;
context: Context;
computed: {
horizontal: boolean;
};
refs: Refs;
action: string;
event: EventObject;
effect: string;
guard: string;
}
type SplitterService = Service<SplitterSchema>;
type SplitterMachine = Machine<SplitterSchema>;
interface PanelProps {
id: PanelId;
}
interface ResizeTriggerProps {
id: ResizeTriggerId;
disabled?: boolean | undefined;
}
interface PanelItem {
type: "panel";
id: PanelId;
}
interface ResizeTriggerItem {
type: "handle";
id: ResizeTriggerId;
}
type SplitterItem = PanelItem | ResizeTriggerItem;
interface SplitterApi<T extends PropTypes = PropTypes> {
/**
* Whether the splitter is currently being resized.
*/
dragging: boolean;
/**
* Returns the current sizes of the panels.
*/
getSizes: () => number[];
/**
* Sets the sizes of the panels.
*/
setSizes: (size: number[]) => void;
/**
* Returns the items of the splitter.
*/
getItems: () => SplitterItem[];
/**
* Returns the size of the specified panel.
*/
getPanelSize: (id: PanelId) => number;
/**
* Returns whether the specified panel is collapsed.
*/
isPanelCollapsed: (id: PanelId) => boolean;
/**
* Returns whether the specified panel is expanded.
*/
isPanelExpanded: (id: PanelId) => boolean;
/**
* Collapses the specified panel.
*/
collapsePanel: (id: PanelId) => void;
/**
* Expands the specified panel.
*/
expandPanel: (id: PanelId, minSize?: number) => void;
/**
* Resizes the specified panel.
*/
resizePanel: (id: PanelId, unsafePanelSize: number) => void;
/**
* Returns the layout of the splitter.
*/
getLayout: () => string;
/**
* Resets the splitter to its initial state.
*/
resetSizes: VoidFunction;
getRootProps: () => T["element"];
getPanelProps: (props: PanelProps) => T["element"];
getResizeTriggerProps: (props: ResizeTriggerProps) => T["element"];
}
declare function connect<T extends PropTypes>(service: SplitterService, normalize: NormalizeProps<T>): SplitterApi<T>;
declare const machine: _zag_js_core.Machine<SplitterSchema>;
declare const props: (keyof SplitterProps)[];
declare const splitProps: <Props extends Partial<SplitterProps>>(props: Props) => [Partial<SplitterProps>, Omit<Props, keyof SplitterProps>];
declare const panelProps: "id"[];
declare const splitPanelProps: <Props extends PanelProps>(props: Props) => [PanelProps, Omit<Props, "id">];
declare const resizeTriggerProps: (keyof ResizeTriggerProps)[];
declare const splitResizeTriggerProps: <Props extends ResizeTriggerProps>(props: Props) => [ResizeTriggerProps, Omit<Props, keyof ResizeTriggerProps>];
declare function getPanelLayout(panels: PanelData[]): string;
export { type SplitterApi as Api, type ElementIds, type ExpandCollapseDetails, type SplitterItem as Item, type SplitterMachine as Machine, type PanelData, type PanelProps, type SplitterProps as Props, type ResizeDetails, type ResizeEndDetails, type ResizeTriggerProps, type SplitterService as Service, anatomy, connect, getPanelLayout as layout, machine, panelProps, props, resizeTriggerProps, splitPanelProps, splitProps, splitResizeTriggerProps };