import type { Ref } from 'vue'; import { useContextFactory } from '@robonen/vue'; import type { MaybeElementRef } from '@robonen/vue'; import type { DrawerDirection } from './types'; export interface DrawerRootContext { /** Source-of-truth open state (also bound to the underlying Dialog). */ open: Ref; /** Alias of {@link open}; kept for parity with consumers reading `isOpen`. */ isOpen: Ref; /** Whether the drawer blocks the rest of the page (focus trap, scroll lock). */ modal: Ref; /** Becomes `true` the first time the drawer opens; gates Safari position fixes. */ hasBeenOpened: Ref; /** DOM node of the drawer content (DialogContent), tracked for drag math. */ drawerRef: MaybeElementRef; /** DOM node of the overlay, faded in sync with the drag. */ overlayRef: MaybeElementRef; /** DOM node of the drag handle. */ handleRef: MaybeElementRef; /** Whether a pointer drag is currently in progress. */ isDragging: Ref; /** Timestamp the active drag started, for velocity calculations. */ dragStartTime: Ref; /** Latched once a drag is permitted, so it can't be cancelled mid-gesture. */ isAllowedToDrag: Ref; /** Configured snap points (fractions of the screen or px strings). */ snapPoints: Ref | undefined>; /** Whether any snap points are configured. */ hasSnapPoints: Ref; /** Whether the on-screen keyboard is currently considered open. */ keyboardIsOpen: Ref; /** The currently active snap point value (px string, fraction, or null). */ activeSnapPoint: Ref; /** Pointer coordinate (clientX/clientY) captured at drag start. */ pointerStart: Ref; /** Whether dragging/clicking outside/escape closes the drawer. */ dismissible: Ref; /** Measured height of the drawer content in px. */ drawerHeightRef: Ref; /** Pixel offset of each snap point along the drag axis. */ snapPointsOffset: Ref; /** The edge the drawer is anchored to. */ direction: Ref; /** Begin a drag gesture. */ onPress: (event: PointerEvent) => void; /** Update the drawer position during a drag. */ onDrag: (event: PointerEvent) => void; /** Settle the drawer (snap, close, or reset) when the pointer is released. */ onRelease: (event: PointerEvent) => void; /** Programmatically close the drawer. */ closeDrawer: () => void; /** Whether the overlay should fade with the drag at the current snap point. */ shouldFade: Ref; /** Snap point index from which the overlay starts fading. */ fadeFromIndex: Ref; /** Whether the page background scales back while the drawer is open. */ shouldScaleBackground: Ref; /** Whether to set the body background to black during the scale effect. */ setBackgroundColorOnScale: Ref; /** Drive the parent drawer's transform as a nested child drawer is dragged. */ onNestedDrag: (percentageDragged: number) => void; /** Settle the parent drawer when a nested child drawer is released. */ onNestedRelease: (o: boolean) => void; /** React to a nested child drawer opening/closing. */ onNestedOpenChange: (o: boolean) => void; /** Emit the root's `close` event. */ emitClose: () => void; /** Emit the root's `drag` event with the drag percentage. */ emitDrag: (percentageDragged: number) => void; /** Emit the root's `release` event. */ emitRelease: (open: boolean) => void; /** Whether this drawer is nested inside another drawer. */ nested: Ref; /** Whether dragging is only permitted from the handle. */ handleOnly: Ref; /** Whether to skip Vaul-style body styling entirely. */ noBodyStyles: Ref; } const ctx = useContextFactory('DrawerRootContext'); export const provideDrawerRootContext = ctx.provide; export const injectDrawerRootContext = ctx.inject;