UNPKG

@spaced-out/ui-design-system

Version:
71 lines 3.55 kB
import * as React from 'react'; type BoundaryRefType<T extends HTMLElement> = React.RefObject<T | null>; type TriggerRefType<T extends HTMLElement> = React.RefObject<T | null>; export interface ChildProps<TTrigger extends HTMLElement = HTMLButtonElement, TBoundary extends HTMLElement = HTMLDivElement> { onOpen: () => void; isOpen: boolean; height: number | null | undefined; pageBottom: number | null | undefined; clickAway: () => void; boundaryRef: BoundaryRefType<TBoundary>; triggerRef: TriggerRefType<TTrigger>; } export interface ClickAwayRefType { forceClose: () => void; forceOpen: () => void; } export interface ClickAwayProps<TTrigger extends HTMLElement = HTMLButtonElement, TBoundary extends HTMLElement = HTMLDivElement> { closeOnEscapeKeypress?: boolean; children: (props: ChildProps<TTrigger, TBoundary>) => React.ReactNode; onChange?: (isOpen: boolean) => unknown; clickAwayRef?: React.RefObject<ClickAwayRefType | null>; /** * When containsNestedFloatingPortals is true, prevents ClickAway from closing the dropdown if the click target * is inside a floating portal root element. * * This is necessary for nested dropdowns rendered using floating portals, * such as via `@floating-ui/react`. Floating portals render elements outside * the normal DOM tree (often directly into `document.body` or another container) * using `ReactDOM.createPortal`. As a result, these nested dropdowns do not * appear inside the parent dropdown's `boundaryRef` or `triggerRef` subtree. * * To address this, the floating portal ensures that all nested dropdowns * are mounted into a **shared root element** — effectively maintaining a * common DOM ancestry. This allows parent dropdowns to detect when clicks * occur within any of their nested children, even if rendered via portals. * The shared root element is the closest parent element that has a `data-floating-ui-portal` attribute. * Because of this, the ClickAway logic will not close the parent menu if the click target is inside boundaryRef's parentElement. * * Enabling `containsNestedFloatingPortals` allows the ClickAway logic to account * for this shared root and avoids incorrectly closing the parent menu when * interacting with nested dropdowns. */ containsNestedFloatingPortals?: boolean; } interface ClickAwayState { isOpen: boolean; height: number | null | undefined; pageBottom: number | null | undefined; } export declare class ClickAway<TTrigger extends HTMLElement = HTMLButtonElement, TBoundary extends HTMLElement = HTMLDivElement> extends React.Component<ClickAwayProps<TTrigger, TBoundary>, ClickAwayState> { static defaultProps: { containsNestedFloatingPortals?: boolean; closeOnEscapeKeypress?: boolean; }; state: ClickAwayState; el: HTMLElement | null | undefined; boundaryRef: BoundaryRefType<TBoundary>; triggerRef: TriggerRefType<TTrigger>; componentDidMount(): void; componentDidUpdate(_prevProps: Readonly<ClickAwayProps<TTrigger, TBoundary>>, prevState: Readonly<ClickAwayState>): void; componentWillUnmount(): void; render(): React.ReactNode; handleOpenClick: () => void; handleCloseClick: (evt: MouseEvent) => void; handleCloseOnEscapeKeypress: (evt?: KeyboardEvent) => void; forceClose: () => void; handleOnChange: () => unknown; pageBottom(): number; } export {}; //# sourceMappingURL=click-away.d.ts.map