Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 | 14x 14x 13x 9x 4x | import type {
ChangeDetails,
ControllableValueOptions,
RuntimeController,
RuntimeEventSource,
} from '../core/types';
import type { FloatingPositionOptions } from '../positioning/positioning';
import {
createOpenController,
type OpenChangeReason,
type OpenLifecycleEvents,
type OpenSnapshot,
type OverlayElements,
} from './openable';
/** Popover options for state, dismissal, focus, and collision-aware positioning. @public */
export interface PopoverOptions extends Partial<
ControllableValueOptions<boolean, OpenChangeReason>
> {
/** Deterministic popover ID. */
readonly id?: string;
/** Closes on outside focus when true. @defaultValue `true` */
readonly closeOnFocusOutside?: boolean;
/** Moves initial focus into the popover when true. @defaultValue `false` */
readonly focusContent?: boolean;
/** Restores trigger focus after keyboard dismissal. @defaultValue `true` */
readonly restoreFocus?: boolean;
/** Shared placement and collision configuration. */
readonly positioning?: FloatingPositionOptions;
}
/** Headless Popover command, event, binding, and positioning surface. @public */
export interface PopoverController
extends RuntimeController<OpenSnapshot>, RuntimeEventSource<OpenLifecycleEvents> {
/** Opens with a typed cause. */
open(details?: ChangeDetails<OpenChangeReason>): void;
/** Closes with a typed cause. */
close(details?: ChangeDetails<OpenChangeReason>): void;
/** Requests the opposite state. */
toggle(details?: ChangeDetails<OpenChangeReason>): void;
/** Binds trigger, content, optional branches, and optional virtual anchor. */
bind(elements: OverlayElements): () => void;
/** Recalculates coordinates after consumer-rendered size changes. */
updatePosition(): void;
}
/** Creates a collision-aware Popover that treats descendant overlay branches as inside. @public */
export function createPopover(options: PopoverOptions = {}): PopoverController {
const base = createOpenController({
role: 'dialog',
modal: false,
trapFocus: false,
focusOnOpen: options.focusContent ?? false,
restoreFocusOnOutside: false,
closeOnFocusOutside: options.closeOnFocusOutside ?? true,
...(options.id ? { id: options.id } : {}),
...(options.defaultValue !== undefined ? { defaultValue: options.defaultValue } : {}),
...(options.getValue ? { getValue: options.getValue } : {}),
...(options.onValueChange ? { onValueChange: options.onValueChange } : {}),
...(options.subscribeValue ? { subscribeValue: options.subscribeValue } : {}),
...(options.restoreFocus !== undefined ? { restoreFocus: options.restoreFocus } : {}),
...(options.positioning ? { positioning: options.positioning } : {}),
});
return {
...base,
open: (changeDetails = { reason: 'programmatic' }) => base.open(changeDetails),
close: (changeDetails = { reason: 'programmatic' }) => base.close(changeDetails),
toggle: (changeDetails = { reason: 'programmatic' }) => base.toggle(changeDetails),
};
}
|