@trackunit/react-components 1.21.13 → 1.21.15

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,19 @@
1
+ import { type RefObject } from "react";
2
+ export type UseProximityAnimationReturn = {
3
+ /** Cancel any running proximity RAF loop and clear the CSS property. */
4
+ readonly cancelProximityAnimation: () => void;
5
+ /**
6
+ * Start a RAF loop that drives `--sheet-snap-proximity` as the sheet
7
+ * settles into a snap, then fades it back to 0.
8
+ */
9
+ readonly startProximityAnimation: (sheet: HTMLElement, targetHeight: number) => void;
10
+ };
11
+ /**
12
+ * Manages the `--sheet-snap-proximity` CSS custom property animation
13
+ * during post-release snap transitions.
14
+ *
15
+ * Tracks the sheet height via `getBoundingClientRect` each frame,
16
+ * computes proximity to the target snap, and fades the value out once
17
+ * the sheet has arrived.
18
+ */
19
+ export declare const useProximityAnimation: (sheetRef: RefObject<HTMLElement | null>) => UseProximityAnimationReturn;
@@ -0,0 +1,27 @@
1
+ import type { UseSheetProps, UseSheetReturnValue } from "./sheet-types";
2
+ /**
3
+ * Hook for managing Sheet open/close state and directional snap navigation.
4
+ *
5
+ * Consumers navigate via `snap.snapUp()` / `snap.snapDown()` /
6
+ * `snap.expand()` / `snap.collapse()` / `snap.dock()` instead of
7
+ * naming specific snap points. The snap state is managed by the composable
8
+ * `useSheetSnap` hook internally.
9
+ *
10
+ * Owns all dismiss handling (ESC, outside-press, gesture) via Floating UI's
11
+ * `useDismiss`. Each dismiss path goes through `onOpenChange` →
12
+ * `requestClose` with the correct `CloseReason`, then through
13
+ * `onBeforeClose` guard, then `handleClose`. The public `close()` is a
14
+ * no-arg wrapper that tags the reason as `"programmatic"`.
15
+ *
16
+ * Outside-press dismiss is only active when `variant="modal"` — the only
17
+ * variant that renders a backdrop overlay. For `"default"` and `"floating"`
18
+ * variants, clicks outside the panel do not close the sheet.
19
+ *
20
+ * Returns a `floatingUi` object (context, refs, getFloatingProps) that the
21
+ * Sheet component uses for focus management and dismiss interaction binding,
22
+ * mirroring `useModal`'s architecture.
23
+ *
24
+ * Supports controlled (isOpen) and uncontrolled (defaultOpen) modes, stores
25
+ * external callbacks in refs for stability.
26
+ */
27
+ export declare const useSheet: (props?: UseSheetProps) => UseSheetReturnValue;
@@ -0,0 +1,28 @@
1
+ import { type RefObject } from "react";
2
+ import type { SheetAnimationState } from "./sheet-animation-reducer";
3
+ type UseSheetDismissIntentProps = {
4
+ /** Whether the sheet supports close gestures (onCloseGesture is defined). */
5
+ readonly closable: boolean;
6
+ /** Current close animation phase from the animation reducer. */
7
+ readonly closePhase: SheetAnimationState["closePhase"];
8
+ /** Ref to the panel element where `--sheet-dismiss-progress` is set. */
9
+ readonly panelRef: RefObject<HTMLElement | null>;
10
+ };
11
+ type UseSheetDismissIntentReturn = {
12
+ readonly onMouseEnter: () => void;
13
+ readonly onMouseLeave: () => void;
14
+ };
15
+ /**
16
+ * Manages the dismiss-intent visual on the sheet handle.
17
+ *
18
+ * Sets `--sheet-dismiss-progress: 1` on the panel element when the user
19
+ * signals dismiss intent — either by holding Cmd/Ctrl+Shift while hovering
20
+ * the handle, or while the close animation is in progress.
21
+ *
22
+ * This is the single owner of `--sheet-dismiss-progress` outside of the
23
+ * gesture hook's drag flow. The gesture hook manages the property during
24
+ * active drag (continuous 0-1 values); this hook manages it for the
25
+ * binary on/off dismiss visual (modifier+hover, close animation).
26
+ */
27
+ export declare const useSheetDismissIntent: ({ closable, closePhase, panelRef, }: UseSheetDismissIntentProps) => UseSheetDismissIntentReturn;
28
+ export {};
@@ -0,0 +1,31 @@
1
+ import type { SheetSizingMode } from "./sheet-types";
2
+ /**
3
+ * Measures the panel's natural content height for fit mode via ResizeObserver.
4
+ *
5
+ * Only active when `sizingMode` is `"fit"` and the panel is visible (docked
6
+ * height is measured separately by useDockedContentHeight).
7
+ *
8
+ * Measures the sum of children's `scrollHeight` rather than the panel's own
9
+ * `scrollHeight`. This is necessary because children with their own scroll
10
+ * context absorb overflow, which would make the panel's `scrollHeight` equal
11
+ * its `clientHeight` (creating a feedback loop where the height shrinks by
12
+ * the border size each cycle).
13
+ *
14
+ * Relies on the scroll area not having `flex-grow` in fit mode (controlled
15
+ * by the `fillHeight` CVA variant on the scroll area element). Without this,
16
+ * a flex-grown scroll area at expanded height would report its stretched
17
+ * `clientHeight` as `scrollHeight`, making the measured fit height equal
18
+ * the expanded height.
19
+ *
20
+ * The initial measurement sets the height directly. Subsequent
21
+ * ResizeObserver callbacks only allow the height to increase, preventing
22
+ * stacking overrides or other transient constraints from permanently
23
+ * reducing the measured height.
24
+ *
25
+ * Accepts the DOM element directly (rather than a RefObject) so that the
26
+ * layoutEffect re-runs whenever the element becomes available — critical
27
+ * because FloatingPortal defers its first render, meaning the element is
28
+ * null on the first layout pass and only non-null after FloatingPortal's
29
+ * own layoutEffect fires and the Card mounts.
30
+ */
31
+ export declare const useSheetFitHeight: (element: HTMLDivElement | null, sizingMode: SheetSizingMode, shouldRender: boolean) => number;
@@ -0,0 +1,49 @@
1
+ import { type PointerEvent as ReactPointerEvent, type RefObject } from "react";
2
+ /**
3
+ * Props for the useSheetGestures hook.
4
+ */
5
+ export type UseSheetGesturesProps = {
6
+ /** Available snap heights in pixels, sorted ascending. */
7
+ readonly snapHeights: ReadonlyArray<number>;
8
+ /** Current active snap height in pixels. */
9
+ readonly activeSnapHeight: number;
10
+ /**
11
+ * Ref to the sheet panel element.
12
+ * The hook sets `--sheet-drag-height` CSS custom property and manages
13
+ * the `transition` inline style on this element during drag.
14
+ */
15
+ readonly sheetRef: RefObject<HTMLElement | null>;
16
+ /** Called with the target snap height (px) when the user releases. */
17
+ readonly onSnap: (snapHeight: number) => void;
18
+ /** Called when the sheet should close (dragged below close threshold). When absent, snaps to min instead. */
19
+ readonly onClose?: () => void;
20
+ /** Container height in pixels (used for close threshold calculation). */
21
+ readonly containerHeight: number;
22
+ /** Whether gesture handling is enabled. */
23
+ readonly enabled: boolean;
24
+ };
25
+ /**
26
+ * Return value of useSheetGestures.
27
+ * Attach all three pointer handlers to the drag handle element.
28
+ * The handle element MUST have `touch-action: none` in CSS.
29
+ */
30
+ export type UseSheetGesturesReturn = {
31
+ readonly onPointerDown: (e: ReactPointerEvent) => void;
32
+ readonly onPointerMove: (e: ReactPointerEvent) => void;
33
+ readonly onPointerUp: (e: ReactPointerEvent) => void;
34
+ readonly onLostPointerCapture: () => void;
35
+ readonly isDragging: boolean;
36
+ };
37
+ /**
38
+ * Hook providing pointer-event-based drag gesture handling for a bottom sheet.
39
+ *
40
+ * Uses native Pointer Events with pointer capture for reliable cross-device
41
+ * tracking. During drag, the hook directly manipulates the sheet element's
42
+ * `--sheet-drag-height` CSS custom property and disables transitions for
43
+ * immediate visual feedback. On release, it restores CSS transitions and
44
+ * calls `onSnap` or `onClose` based on position and velocity.
45
+ *
46
+ * The consuming Sheet component should use `height: var(--sheet-drag-height, <snapHeight>)`
47
+ * so the sheet stays anchored at the bottom while its height changes during drag.
48
+ */
49
+ export declare const useSheetGestures: (props: UseSheetGesturesProps) => UseSheetGesturesReturn;
@@ -0,0 +1,35 @@
1
+ import { type Dispatch, type RefObject, type TransitionEvent } from "react";
2
+ import type { SheetAnimationAction } from "./sheet-animation-reducer";
3
+ import type { SheetVariant } from "./sheet-types";
4
+ type UseSheetLifecycleProps = {
5
+ readonly isOpen: boolean;
6
+ readonly entryAnimation: boolean;
7
+ readonly visuallyOpen: boolean;
8
+ readonly variant: SheetVariant;
9
+ readonly container: HTMLElement | null;
10
+ readonly panelRef: RefObject<HTMLDivElement | null>;
11
+ readonly panelEl: HTMLDivElement | null;
12
+ readonly dispatch: Dispatch<SheetAnimationAction>;
13
+ readonly onCloseComplete?: () => void;
14
+ /**
15
+ * True once the content height is known (or fit mode is inactive).
16
+ * The entry animation is deferred until this is true so the sheet
17
+ * slides in at the correct height without a visible jump.
18
+ */
19
+ readonly fitHeightReady: boolean;
20
+ };
21
+ /**
22
+ * Manages the Sheet's mount/unmount animation lifecycle.
23
+ *
24
+ * - Ensures `shouldRender` is set when re-opening after a stale transitionend closure.
25
+ * - Triggers the open animation by forcing the browser to acknowledge the
26
+ * off-screen `translateY(100%)` position (via `getComputedStyle`) before
27
+ * dispatching `SET_VISUALLY_OPEN`, which changes the inline transform to
28
+ * `translateY(0)`. The existing CSS transition on `transform` then animates
29
+ * the slide-up smoothly.
30
+ * - Handles `transitionend` on the panel to unmount after the close transition.
31
+ */
32
+ export declare const useSheetLifecycle: ({ isOpen, entryAnimation, visuallyOpen, variant, container, panelRef, panelEl, dispatch, onCloseComplete, fitHeightReady, }: UseSheetLifecycleProps) => {
33
+ readonly handleTransitionEnd: (e: TransitionEvent<HTMLDivElement>) => void;
34
+ };
35
+ export {};
@@ -0,0 +1,31 @@
1
+ import { type Ref, type RefCallback, type RefObject } from "react";
2
+ import type { SheetGeometry, SheetState } from "./sheet-types";
3
+ type UseSheetMeasurementsProps = {
4
+ readonly shouldRender: boolean;
5
+ readonly state: SheetState;
6
+ readonly dockingEnabled: boolean;
7
+ readonly snapping: boolean;
8
+ readonly externalRef: Ref<HTMLDivElement> | undefined;
9
+ readonly onGeometryChange: (geometry: SheetGeometry, dockingEnabled: boolean) => void;
10
+ readonly onSnap: (heightPx: number, useLevelSnap: boolean) => void;
11
+ };
12
+ type UseSheetMeasurementsReturn = {
13
+ readonly containerRef: RefCallback<HTMLElement>;
14
+ readonly mergedPanelRef: RefCallback<HTMLDivElement> | null;
15
+ readonly panelRefObj: RefObject<HTMLDivElement | null>;
16
+ readonly panelEl: HTMLDivElement | null;
17
+ readonly containerHeight: number;
18
+ readonly activeSnapHeightPx: number;
19
+ readonly gestureSnapHeights: ReadonlyArray<number>;
20
+ readonly cappedFitHeight: number;
21
+ readonly fitHeightReady: boolean;
22
+ readonly fitHeight: number;
23
+ readonly handleGestureSnap: (heightPx: number) => void;
24
+ };
25
+ /**
26
+ * Consolidates container/panel measurement, docked/fit height tracking,
27
+ * the `onGeometryChange` feedback loop, and all derived snap geometry that Sheet
28
+ * needs for gestures and CSS sizing.
29
+ */
30
+ export declare const useSheetMeasurements: ({ shouldRender, state, dockingEnabled, snapping, externalRef, onGeometryChange, onSnap, }: UseSheetMeasurementsProps) => UseSheetMeasurementsReturn;
31
+ export {};
@@ -0,0 +1,30 @@
1
+ type UseSheetMotionOverflowProps = {
2
+ readonly panelEl: HTMLDivElement | null;
3
+ readonly isDragging: boolean;
4
+ readonly scrollAreaEl: HTMLDivElement | null;
5
+ readonly separatorEl: HTMLElement | null;
6
+ readonly isDocked: boolean;
7
+ readonly isClosing: boolean;
8
+ };
9
+ /**
10
+ * Manages scrollbar and separator-line visibility during sheet motion (drag
11
+ * and CSS height transitions), freezing both to the state captured at motion
12
+ * start to avoid visual flashing.
13
+ *
14
+ * Freeze rules:
15
+ * - **Was overflowing at motion start** — scrollbar is forced visible
16
+ * (`overflow-y: scroll`) and separator stays opaque throughout the motion.
17
+ * - **Was NOT overflowing at motion start** — scrollbar is hidden via
18
+ * `useScrollBlock` (overflow hidden + scrollbar-gutter to prevent reflow)
19
+ * and separator stays transparent throughout the motion.
20
+ * - **Was docked at motion start** — always treated as "not overflowing"
21
+ * because the scroll area is not visible in docked state. Overflow is
22
+ * hidden directly (no scrollbar-gutter) so no space is reserved for a
23
+ * scrollbar that was never visible.
24
+ *
25
+ * At rest, overflow is detected via ResizeObserver + MutationObserver and
26
+ * the separator's `style.opacity` is toggled (CSS transition on the element
27
+ * provides the fade).
28
+ */
29
+ export declare const useSheetMotionOverflow: ({ panelEl, isDragging, scrollAreaEl, separatorEl, isDocked, isClosing, }: UseSheetMotionOverflowProps) => void;
30
+ export {};
@@ -0,0 +1,14 @@
1
+ import type { SheetDefaultSize, UseSheetSnapReturn } from "./sheet-types";
2
+ type UseSheetSnapProps = {
3
+ readonly defaultSize: SheetDefaultSize;
4
+ readonly isOpen: boolean;
5
+ };
6
+ /**
7
+ * Composable hook managing snap-level state for the Sheet component.
8
+ *
9
+ * Owns the snap reducer, processes measurements from Sheet via `onGeometryChange`,
10
+ * and provides stable navigation methods. Used by `useSheet` internally and
11
+ * can be used directly by Modal for independent snap management.
12
+ */
13
+ export declare const useSheetSnap: ({ defaultSize, isOpen }: UseSheetSnapProps) => UseSheetSnapReturn;
14
+ export {};
package/src/index.d.ts CHANGED
@@ -77,6 +77,11 @@ export * from "./components/PreferenceCard/PreferenceCard.variants";
77
77
  export * from "./components/PreferenceCard/PreferenceCardSkeleton";
78
78
  export * from "./components/Prompt/Prompt";
79
79
  export * from "./components/SectionHeader/SectionHeader";
80
+ export { Sheet } from "./components/Sheet/Sheet";
81
+ export { SHEET_TRANSITION_DURATION, SHEET_TRANSITION_DURATION_MS, SHEET_TRANSITION_EASING, } from "./components/Sheet/sheet-snap-config";
82
+ export type { SheetAnchor, SheetDefaultSize, SheetEntryAnimation, SheetFloatingUiProps, SheetGeometry, SheetProps, SheetSizingMode, SheetSnapActions, SheetState, SheetVariant, UseSheetProps, UseSheetReturnValue, UseSheetSnapReturn, } from "./components/Sheet/sheet-types";
83
+ export { useSheet } from "./components/Sheet/useSheet";
84
+ export { useSheetSnap } from "./components/Sheet/useSheetSnap";
80
85
  export * from "./components/Sidebar/Sidebar";
81
86
  export * from "./components/Sidebar/useOverflowItems";
82
87
  export { useRandomCSSLengths } from "./components/Skeleton/Skeleton.helpers";