Files
tools/vue/primitives/src/overlays/drawer/context.ts
T
robonen eefd7abf83 feat(primitives): media-editor components, category reorg, perf + type cleanup
Reorganize components into category folders (forms/canvas/overlays/etc.); add the
media-editor headless family (timeline, curve-editor, waveform, crop, color
picker, etc.); apply perf fixes (O(1) collection lookups, plain-object drag
state, gesture-leak teardown, shallowRef color state, rect caching) and replace
source `any` with proper types.
2026-06-15 16:54:29 +07:00

85 lines
4.0 KiB
TypeScript

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<boolean>;
/** Alias of {@link open}; kept for parity with consumers reading `isOpen`. */
isOpen: Ref<boolean>;
/** Whether the drawer blocks the rest of the page (focus trap, scroll lock). */
modal: Ref<boolean>;
/** Becomes `true` the first time the drawer opens; gates Safari position fixes. */
hasBeenOpened: Ref<boolean>;
/** DOM node of the drawer content (DialogContent), tracked for drag math. */
drawerRef: MaybeElementRef<HTMLElement | undefined>;
/** DOM node of the overlay, faded in sync with the drag. */
overlayRef: MaybeElementRef<HTMLElement | undefined>;
/** DOM node of the drag handle. */
handleRef: MaybeElementRef<HTMLElement | undefined>;
/** Whether a pointer drag is currently in progress. */
isDragging: Ref<boolean>;
/** Timestamp the active drag started, for velocity calculations. */
dragStartTime: Ref<Date | null>;
/** Latched once a drag is permitted, so it can't be cancelled mid-gesture. */
isAllowedToDrag: Ref<boolean>;
/** Configured snap points (fractions of the screen or px strings). */
snapPoints: Ref<Array<number | string> | undefined>;
/** Whether any snap points are configured. */
hasSnapPoints: Ref<boolean>;
/** Whether the on-screen keyboard is currently considered open. */
keyboardIsOpen: Ref<boolean>;
/** The currently active snap point value (px string, fraction, or null). */
activeSnapPoint: Ref<number | string | null | undefined>;
/** Pointer coordinate (clientX/clientY) captured at drag start. */
pointerStart: Ref<number>;
/** Whether dragging/clicking outside/escape closes the drawer. */
dismissible: Ref<boolean>;
/** Measured height of the drawer content in px. */
drawerHeightRef: Ref<number>;
/** Pixel offset of each snap point along the drag axis. */
snapPointsOffset: Ref<number[]>;
/** The edge the drawer is anchored to. */
direction: Ref<DrawerDirection>;
/** 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<boolean>;
/** Snap point index from which the overlay starts fading. */
fadeFromIndex: Ref<number | undefined>;
/** Whether the page background scales back while the drawer is open. */
shouldScaleBackground: Ref<boolean | undefined>;
/** Whether to set the body background to black during the scale effect. */
setBackgroundColorOnScale: Ref<boolean | undefined>;
/** 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<boolean>;
/** Whether dragging is only permitted from the handle. */
handleOnly: Ref<boolean>;
/** Whether to skip Vaul-style body styling entirely. */
noBodyStyles: Ref<boolean>;
}
const ctx = useContextFactory<DrawerRootContext>('DrawerRootContext');
export const provideDrawerRootContext = ctx.provide;
export const injectDrawerRootContext = ctx.inject;