@spaced-out/ui-design-system
Version:
Sense UI components library
73 lines • 3.17 kB
TypeScript
import * as React from 'react';
type BoundaryRefType<T> = React.RefObject<T | null>;
type TriggerRefType<T> = React.RefObject<T | null>;
export type ChildProps = {
onOpen: () => void;
isOpen: boolean;
height: number | null | undefined;
pageBottom: number | null | undefined;
clickAway: () => void;
boundaryRef: BoundaryRefType<HTMLElement>;
triggerRef: TriggerRefType<HTMLElement>;
};
export type ClickAwayRefType = {
current: {
forceClose: () => void;
forceOpen: () => void;
} | null | undefined;
} | null | undefined;
export type ClickAwayProps = {
closeOnEscapeKeypress?: boolean;
children: (props: ChildProps) => React.ReactNode;
onChange?: (isOpen: boolean) => unknown;
clickAwayRef?: ClickAwayRefType;
/**
* 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;
};
type ClickAwayState = {
isOpen: boolean;
height: number | null | undefined;
pageBottom: number | null | undefined;
};
export declare class ClickAway extends React.Component<ClickAwayProps, ClickAwayState> {
static defaultProps: {
containsNestedFloatingPortals?: boolean;
closeOnEscapeKeypress?: boolean;
};
state: ClickAwayState;
el: HTMLElement | null | undefined;
boundaryRef: BoundaryRefType<HTMLElement>;
triggerRef: TriggerRefType<HTMLElement>;
componentDidMount(): void;
componentDidUpdate(_prevProps: ClickAwayProps, prevState: 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