@howells/stacksheet 1.1.6 → 1.1.7
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.
- package/dist/index.js +2 -2
- package/dist/index.js.map +1 -1
- package/dist/styles.css +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -812,7 +812,7 @@ function BottomHandle({ onDismiss }) {
|
|
|
812
812
|
"button",
|
|
813
813
|
{
|
|
814
814
|
"aria-label": "Dismiss",
|
|
815
|
-
className: "flex w-full
|
|
815
|
+
className: "absolute inset-x-0 top-0 z-10 flex w-full cursor-grab touch-none items-center justify-center border-none bg-transparent pt-2 pb-1",
|
|
816
816
|
"data-stacksheet-handle": "",
|
|
817
817
|
onClick: onDismiss,
|
|
818
818
|
type: "button",
|
|
@@ -1038,7 +1038,7 @@ var SheetPanel = memo(function SheetPanel2({
|
|
|
1038
1038
|
side
|
|
1039
1039
|
}
|
|
1040
1040
|
),
|
|
1041
|
-
/* @__PURE__ */ jsxs("div", { className: "flex min-h-0 flex-1 flex-col overflow-hidden rounded-[inherit]", children: [
|
|
1041
|
+
/* @__PURE__ */ jsxs("div", { className: "relative flex min-h-0 flex-1 flex-col overflow-hidden rounded-[inherit]", children: [
|
|
1042
1042
|
showBottomHandle && /* @__PURE__ */ jsx2(BottomHandle, { onDismiss: isNested ? pop : close }),
|
|
1043
1043
|
/* @__PURE__ */ jsx2(
|
|
1044
1044
|
PanelInnerContent,
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/create.tsx","../src/springs.ts","../src/config.ts","../src/renderer.tsx","../src/icons.tsx","../src/media.ts","../src/panel-context.tsx","../src/snap-points.ts","../src/stacking.ts","../src/use-drag.ts","../src/store.ts","../src/parts.tsx"],"sourcesContent":["import { Portal } from \"@radix-ui/react-portal\";\nimport { createContext, useContext, useMemo } from \"react\";\nimport type { StoreApi } from \"zustand\";\nimport { useStore } from \"zustand\";\nimport { useShallow } from \"zustand/react/shallow\";\nimport { resolveConfig } from \"./config\";\nimport { SheetRenderer } from \"./renderer\";\nimport { createSheetStore } from \"./store\";\nimport type {\n ContentMap,\n ResolvedConfig,\n SheetActions,\n StacksheetConfig,\n StacksheetInstance,\n StacksheetProviderProps,\n StacksheetSnapshot,\n} from \"./types\";\n\ntype StoreState<TMap extends object> = StacksheetSnapshot<TMap> &\n SheetActions<TMap>;\n\n/**\n * Create an isolated sheet stack instance with typed store, hooks, and provider.\n *\n * Works with both `interface` and `type` definitions:\n *\n * ```ts\n * // Using an interface\n * interface SheetDataMap {\n * \"bucket-create\": { onCreated?: (b: Bucket) => void };\n * \"bucket-edit\": { bucket: Bucket };\n * }\n *\n * // Using a type alias\n * type SheetDataMap = {\n * \"bucket-create\": { onCreated?: (b: Bucket) => void };\n * \"bucket-edit\": { bucket: Bucket };\n * };\n *\n * const { StacksheetProvider, useSheet, useStacksheetState } =\n * createStacksheet<SheetDataMap>();\n * ```\n *\n * Sheet content components receive their data as **spread props**:\n * ```ts\n * // Data map defines: \"bucket-edit\": { bucket: Bucket }\n * // Component receives: ({ bucket }: { bucket: Bucket }) => JSX.Element\n * ```\n *\n * Use `useSheetPanel()` inside content components to access `close()` and `back()`.\n */\nexport function createStacksheet<TMap extends object>(\n config?: StacksheetConfig\n): StacksheetInstance<TMap> {\n const resolved = resolveConfig(config);\n const { store, componentMap } = createSheetStore<TMap>(resolved);\n\n // Context for the store — allows multiple instances\n const StoreContext = createContext<{\n store: StoreApi<StoreState<TMap>>;\n config: ResolvedConfig;\n } | null>(null);\n\n function useStoreContext() {\n const ctx = useContext(StoreContext);\n if (!ctx) {\n throw new Error(\n \"useSheet/useStacksheetState must be used within <StacksheetProvider>\"\n );\n }\n return ctx;\n }\n\n // ── Provider ────────────────────────────────\n\n const EMPTY_SHEETS = {} as ContentMap<TMap>;\n\n function StacksheetProvider({\n sheets = EMPTY_SHEETS,\n children,\n classNames,\n renderHeader,\n }: StacksheetProviderProps<TMap>) {\n const value = useMemo(() => ({ store, config: resolved }), []);\n return (\n <StoreContext.Provider value={value}>\n {children}\n <Portal asChild={false}>\n <SheetRenderer<TMap>\n classNames={classNames}\n componentMap={componentMap}\n config={resolved}\n renderHeader={renderHeader}\n sheets={sheets}\n store={store}\n />\n </Portal>\n </StoreContext.Provider>\n );\n }\n\n // ── Hooks ───────────────────────────────────\n\n function useSheet(): SheetActions<TMap> {\n const { store: s } = useStoreContext();\n // Actions are stable refs in Zustand v5 — read once, no subscription needed\n return useMemo(() => {\n const state = s.getState();\n return {\n open: state.open,\n push: state.push,\n replace: state.replace,\n swap: state.swap,\n navigate: state.navigate,\n setData: state.setData,\n remove: state.remove,\n pop: state.pop,\n close: state.close,\n };\n }, [s]);\n }\n\n function useStacksheetState(): StacksheetSnapshot<TMap> {\n const { store: s } = useStoreContext();\n return useStore(\n s,\n useShallow((state) => ({\n stack: state.stack,\n isOpen: state.isOpen,\n }))\n );\n }\n\n return { StacksheetProvider, useSheet, useStacksheetState, store };\n}\n","import type { SpringConfig } from \"./types\";\n\n/**\n * Spring presets inspired by iOS animation feel.\n *\n * - `subtle` — Barely noticeable bounce, professional.\n * - `snappy` — Quick, responsive for interactions.\n * - `stiff` — Very quick, controlled. Panels, drawers. **(default)**\n */\nexport const springs = {\n subtle: { stiffness: 300, damping: 30, mass: 1 },\n snappy: { stiffness: 400, damping: 28, mass: 0.8 },\n stiff: { stiffness: 400, damping: 40, mass: 1 },\n} as const satisfies Record<string, SpringConfig>;\n\nexport type SpringPreset = keyof typeof springs;\n","import type { SpringPreset } from \"./springs\";\nimport { springs } from \"./springs\";\nimport type {\n ResolvedConfig,\n ResponsiveSide,\n SideConfig,\n SpringConfig,\n StackingConfig,\n StacksheetConfig,\n} from \"./types\";\n\n// ── Defaults ────────────────────────────────────\n\nconst DEFAULT_STACKING: StackingConfig = {\n scaleStep: 0.04,\n offsetStep: 16,\n opacityStep: 0,\n radius: 12,\n renderThreshold: 3,\n};\n\nconst DEFAULT_SIDE: ResponsiveSide = {\n desktop: \"right\",\n mobile: \"bottom\",\n};\n\n// ── Helpers ─────────────────────────────────────\n\n/** Normalize a string side to a responsive object, merging with defaults. */\nfunction resolveSide(side: SideConfig | undefined): ResponsiveSide {\n if (typeof side === \"string\") {\n return { desktop: side, mobile: side };\n }\n return { ...DEFAULT_SIDE, ...side };\n}\n\n/** Resolve a preset name to a SpringConfig, or merge partial config with defaults. */\nfunction resolveSpring(\n spring: SpringPreset | Partial<SpringConfig> | undefined\n): SpringConfig {\n if (typeof spring === \"string\") {\n return springs[spring];\n }\n return { ...springs.stiff, ...spring };\n}\n\n// ── Resolver ────────────────────────────────────\n\n/** Merge user-provided config with defaults. Resolves union types (side, spring) to concrete values. */\nexport function resolveConfig(config: StacksheetConfig = {}): ResolvedConfig {\n return {\n maxDepth: config.maxDepth ?? Number.POSITIVE_INFINITY,\n closeOnEscape: config.closeOnEscape ?? true,\n closeOnBackdrop: config.closeOnBackdrop ?? true,\n showOverlay: config.showOverlay ?? true,\n lockScroll: config.lockScroll ?? true,\n width: config.width ?? 420,\n maxWidth: config.maxWidth ?? \"90vw\",\n breakpoint: config.breakpoint ?? 768,\n side: resolveSide(config.side),\n stacking: { ...DEFAULT_STACKING, ...config.stacking },\n spring: resolveSpring(config.spring),\n zIndex: config.zIndex ?? 100,\n ariaLabel: config.ariaLabel ?? \"Sheet dialog\",\n onOpenComplete: config.onOpenComplete,\n onCloseComplete: config.onCloseComplete,\n snapPoints: config.snapPoints ?? [],\n snapPointIndex: config.snapPointIndex,\n onSnapPointChange: config.onSnapPointChange,\n snapToSequentialPoints: config.snapToSequentialPoints ?? false,\n drag: config.drag ?? true,\n closeThreshold: config.closeThreshold ?? 0.25,\n velocityThreshold: config.velocityThreshold ?? 0.5,\n dismissible: config.dismissible ?? true,\n modal: config.modal ?? true,\n shouldScaleBackground: config.shouldScaleBackground ?? false,\n scaleBackgroundAmount: config.scaleBackgroundAmount ?? 0.97,\n };\n}\n","// CloseWatcher — ambient type for browsers that support it (Chromium 120+)\ndeclare global {\n var CloseWatcher:\n | (new () => { onclose: (() => void) | null; destroy: () => void })\n | undefined;\n}\n\nimport FocusTrap from \"focus-trap-react\";\nimport { AnimatePresence, motion as m, useReducedMotion } from \"motion/react\";\nimport {\n type ComponentType,\n type CSSProperties,\n memo,\n useCallback,\n useEffect,\n useMemo,\n useRef,\n useState,\n} from \"react\";\nimport { RemoveScroll } from \"react-remove-scroll\";\nimport type { StoreApi } from \"zustand\";\nimport { useStore } from \"zustand\";\nimport { ArrowLeftIcon, XIcon } from \"./icons\";\nimport { useResolvedSide } from \"./media\";\nimport { SheetPanelContext } from \"./panel-context\";\nimport { getSnapOffset, resolveSnapPoints } from \"./snap-points\";\nimport {\n getAnimatedBorderRadius,\n getPanelStyles,\n getSlideFrom,\n getSlideTarget,\n getStackOffset,\n getStackTransform,\n type SlideValues,\n} from \"./stacking\";\nimport type {\n CloseReason,\n ContentMap,\n HeaderRenderProps,\n ResolvedConfig,\n SheetActions,\n SheetItem,\n Side,\n StacksheetClassNames,\n StacksheetSnapshot,\n} from \"./types\";\nimport { type DragState, useDrag } from \"./use-drag\";\n\n// ── Default header ──────────────────────────────\n\nfunction DefaultHeader({\n isNested,\n onBack,\n onClose,\n className,\n}: HeaderRenderProps & { className?: string }) {\n return (\n <div\n className={`flex h-14 shrink-0 items-center justify-between border-b px-6 ${className ?? \"\"}`}\n >\n <div className=\"flex items-center gap-2\">\n {isNested && (\n <button\n aria-label=\"Back\"\n className=\"flex h-8 w-8 shrink-0 cursor-pointer items-center justify-center rounded-md border-none bg-transparent p-0 text-inherit opacity-60 transition-opacity duration-150 hover:opacity-100\"\n onClick={onBack}\n type=\"button\"\n >\n <ArrowLeftIcon />\n </button>\n )}\n </div>\n <button\n aria-label=\"Close\"\n className=\"flex h-8 w-8 shrink-0 cursor-pointer items-center justify-center rounded-md border-none bg-transparent p-0 text-inherit opacity-60 transition-opacity duration-150 hover:opacity-100\"\n onClick={onClose}\n type=\"button\"\n >\n <XIcon />\n </button>\n </div>\n );\n}\n\n// ── Resolved classNames ─────────────────────────\n\ntype ResolvedClassNames = Required<StacksheetClassNames>;\n\nconst EMPTY_CLASSNAMES: ResolvedClassNames = {\n backdrop: \"\",\n panel: \"\",\n header: \"\",\n};\n\nfunction resolveClassNames(cn?: StacksheetClassNames): ResolvedClassNames {\n if (!cn) {\n return EMPTY_CLASSNAMES;\n }\n return {\n backdrop: cn.backdrop ?? \"\",\n panel: cn.panel ?? \"\",\n header: cn.header ?? \"\",\n };\n}\n\n// ── Helpers ──────────────────────────────────────\n\nfunction buildAriaProps(\n isTop: boolean,\n isModal: boolean,\n isComposable: boolean,\n ariaLabel: string,\n panelId: string,\n hasDescription: boolean\n): Record<string, string | undefined> {\n if (!isTop) {\n return {};\n }\n const props: Record<string, string | undefined> = { role: \"dialog\" };\n if (isModal) {\n props[\"aria-modal\"] = \"true\";\n }\n if (isComposable) {\n props[\"aria-labelledby\"] = `${panelId}-title`;\n if (hasDescription) {\n props[\"aria-describedby\"] = `${panelId}-desc`;\n }\n } else {\n props[\"aria-label\"] = ariaLabel;\n }\n return props;\n}\n\nfunction getDragTransform(\n side: Side,\n offset: number\n): { x?: number; y?: number } {\n if (offset === 0) {\n return {};\n }\n switch (side) {\n case \"right\":\n return { x: offset };\n case \"left\":\n return { x: -offset };\n case \"bottom\":\n return { y: offset };\n default:\n return {};\n }\n}\n\n/** Shared tween config for non-spring animated properties (border radius, box shadow) */\nconst VISUAL_TWEEN = {\n type: \"tween\" as const,\n duration: 0.25,\n ease: \"easeOut\" as const,\n};\n\n// ── Panel helpers (extracted to reduce SheetPanel complexity) ──\n\n/** Measure panel height via ResizeObserver for snap point calculations */\nfunction usePanelHeight(\n panelRef: React.RefObject<HTMLDivElement | null>,\n hasSnapPoints: boolean\n): number {\n const [height, setHeight] = useState(0);\n\n useEffect(() => {\n const el = panelRef.current;\n if (!(el && hasSnapPoints)) {\n return;\n }\n setHeight(el.offsetHeight);\n const observer = new ResizeObserver(([entry]) => {\n if (entry) {\n setHeight(entry.contentRect.height);\n }\n });\n observer.observe(el);\n return () => observer.disconnect();\n }, [panelRef, hasSnapPoints]);\n\n return height;\n}\n\n/** Build the panel's inline style object */\nfunction buildPanelStyle(\n panelStyles: CSSProperties,\n isTop: boolean,\n hasPanelClass: boolean,\n isDragging: boolean\n): CSSProperties {\n return {\n ...panelStyles,\n pointerEvents: isTop ? \"auto\" : \"none\",\n ...(isTop ? {} : { contain: \"layout style paint\" }),\n ...(isDragging ? { transition: \"none\" } : {}),\n ...(hasPanelClass\n ? {}\n : {\n background: \"var(--background, #fff)\",\n borderColor: \"var(--border, transparent)\",\n }),\n };\n}\n\n/** Build per-property transition config */\nfunction buildPanelTransition(\n isDragging: boolean,\n isTop: boolean,\n spring: Record<string, unknown>,\n stackSpring: Record<string, unknown>\n) {\n if (isDragging) {\n return { type: \"tween\" as const, duration: 0 };\n }\n\n const base = isTop ? spring : stackSpring;\n return { ...base, borderRadius: VISUAL_TWEEN, boxShadow: VISUAL_TWEEN };\n}\n\n/** Compute the Y offset for the current snap point */\nfunction computeSnapYOffset(\n side: Side,\n snapHeights: number[],\n activeSnapIndex: number,\n measuredHeight: number\n): number {\n if (side !== \"bottom\" || snapHeights.length === 0 || measuredHeight <= 0) {\n return 0;\n }\n return getSnapOffset(activeSnapIndex, snapHeights, measuredHeight);\n}\n\nfunction getBottomSlideDistance(measuredHeight: number): number {\n if (measuredHeight > 0) {\n return measuredHeight;\n }\n if (typeof window !== \"undefined\") {\n return window.innerHeight;\n }\n return 1000;\n}\n\nfunction resolveSlideFrom(\n side: Side,\n slideFrom: SlideValues,\n measuredHeight: number\n): SlideValues {\n if (side !== \"bottom\") {\n return slideFrom;\n }\n return { y: getBottomSlideDistance(measuredHeight) };\n}\n\nfunction buildAnimateTarget(\n slideTarget: SlideValues,\n stackOffset: { x?: number; y?: number },\n dragOffset: { x?: number; y?: number },\n transform: ReturnType<typeof getStackTransform>,\n animatedRadius: Record<string, number>,\n transition: Record<string, unknown>,\n snapYOffset: number,\n isTop: boolean\n) {\n const base = {\n ...slideTarget,\n ...stackOffset,\n ...dragOffset,\n scale: transform.scale,\n opacity: transform.opacity,\n ...animatedRadius,\n boxShadow: getShadow(!isTop),\n transition,\n };\n\n if (snapYOffset > 0) {\n return { ...base, y: (dragOffset.y ?? 0) + snapYOffset };\n }\n return base;\n}\n\n// ── Modal focus trap wrapper ────────────────────\n\n/** Wraps children in a focus trap when modal mode is enabled. */\nfunction ModalFocusTrap({\n enabled,\n active,\n fallbackRef,\n children,\n}: {\n enabled: boolean;\n active: boolean;\n fallbackRef: React.RefObject<HTMLElement | null>;\n children: React.ReactNode;\n}) {\n if (!enabled) {\n return children;\n }\n return (\n <FocusTrap\n active={active}\n focusTrapOptions={{\n initialFocus: false,\n returnFocusOnDeactivate: true,\n escapeDeactivates: false,\n allowOutsideClick: true,\n checkCanFocusTrap: () =>\n new Promise<void>((resolve) =>\n requestAnimationFrame(() => resolve())\n ),\n fallbackFocus: () => {\n if (fallbackRef.current) {\n return fallbackRef.current;\n }\n return document.body;\n },\n }}\n >\n {children}\n </FocusTrap>\n );\n}\n\n// ── SheetPanel ──────────────────────────────────\n\ninterface SheetPanelProps {\n item: SheetItem;\n index: number;\n depth: number;\n isTop: boolean;\n isNested: boolean;\n side: Side;\n config: ResolvedConfig;\n classNames: ResolvedClassNames;\n // biome-ignore lint/suspicious/noExplicitAny: heterogeneous content component\n Content: ComponentType<any> | undefined;\n shouldRender: boolean;\n pop: () => void;\n close: () => void;\n /** Swipe-specific close — sets reason to \"swipe\" */\n swipeClose: () => void;\n /** Swipe-specific pop — sets reason to \"swipe\" */\n swipePop: () => void;\n /** Resolved snap point heights in px (ascending). Empty = no snaps. */\n snapHeights: number[];\n /** Currently active snap index */\n activeSnapIndex: number;\n /** Called when drag release targets a snap point */\n onSnap: (index: number) => void;\n renderHeader?: false | ((props: HeaderRenderProps) => React.ReactNode);\n slideFrom: SlideValues;\n slideTarget: SlideValues;\n spring: Record<string, unknown>;\n stackSpring: Record<string, unknown>;\n /** Whether the user prefers reduced motion */\n prefersReducedMotion: boolean;\n}\n\n/** Renders panel inner content — composable mode vs classic (header + scroll) */\nfunction PanelInnerContent({\n isComposable,\n shouldRender,\n Content,\n data,\n renderHeader,\n headerProps,\n headerClassName,\n}: {\n isComposable: boolean;\n shouldRender: boolean;\n // biome-ignore lint/suspicious/noExplicitAny: heterogeneous content component\n Content: ComponentType<any> | undefined;\n data: Record<string, unknown>;\n renderHeader?: false | ((props: HeaderRenderProps) => React.ReactNode);\n headerProps: HeaderRenderProps;\n headerClassName: string | undefined;\n}) {\n if (isComposable) {\n return shouldRender && Content ? <Content {...data} /> : null;\n }\n\n return (\n <>\n {renderHeader ? (\n renderHeader(headerProps)\n ) : (\n <DefaultHeader {...headerProps} className={headerClassName} />\n )}\n {shouldRender && Content && (\n <div\n className=\"min-h-0 flex-1 overflow-y-auto overscroll-contain\"\n data-stacksheet-no-drag=\"\"\n >\n <Content {...data} />\n </div>\n )}\n </>\n );\n}\n\n/** Built-in drag handle for bottom panels — always visible on the top sheet */\nfunction BottomHandle({ onDismiss }: { onDismiss?: () => void }) {\n return (\n <button\n aria-label=\"Dismiss\"\n className=\"flex w-full shrink-0 cursor-grab touch-none items-center justify-center border-none bg-transparent pt-2 pb-1\"\n data-stacksheet-handle=\"\"\n onClick={onDismiss}\n type=\"button\"\n >\n <div aria-hidden=\"true\" className=\"h-1 w-9 rounded-sm bg-current/25\" />\n </button>\n );\n}\n\n/** Floating drag handle for left/right side panels */\nfunction SideHandle({\n side,\n isHovered,\n onDismiss,\n}: {\n side: Side;\n isHovered: boolean;\n onDismiss?: () => void;\n}) {\n const position: CSSProperties =\n side === \"right\" ? { right: \"100%\" } : { left: \"100%\" };\n\n return (\n <m.div\n animate={{ opacity: isHovered ? 1 : 0 }}\n aria-label=\"Dismiss\"\n className=\"absolute top-0 bottom-0 flex w-6 cursor-grab touch-none items-center justify-center\"\n data-stacksheet-handle=\"\"\n onClick={onDismiss}\n onKeyDown={(e) => {\n if (e.key === \"Enter\" || e.key === \" \") {\n e.preventDefault();\n onDismiss?.();\n }\n }}\n role=\"button\"\n style={position}\n tabIndex={0}\n transition={{ duration: isHovered ? 0.15 : 0.4, ease: \"easeOut\" }}\n >\n <div\n aria-hidden=\"true\"\n className=\"h-10 w-[5px] rounded-sm bg-current/35 shadow-sm\"\n />\n </m.div>\n );\n}\n\nconst SheetPanel = memo(function SheetPanel({\n item,\n index,\n depth,\n isTop,\n isNested,\n side,\n config,\n classNames,\n Content,\n shouldRender,\n pop,\n close,\n swipeClose,\n swipePop,\n snapHeights,\n activeSnapIndex,\n onSnap,\n renderHeader,\n slideFrom,\n slideTarget,\n spring,\n stackSpring,\n prefersReducedMotion,\n}: SheetPanelProps) {\n const panelRef = useRef<HTMLDivElement>(null);\n const hasEnteredRef = useRef(false);\n const [dragState, setDragState] = useState<DragState>({\n offset: 0,\n isDragging: false,\n });\n const [isHovered, setIsHovered] = useState(false);\n\n const measuredHeight = usePanelHeight(panelRef, snapHeights.length > 0);\n\n const transform = getStackTransform(depth, config.stacking);\n const panelStyles = getPanelStyles(side, config, index);\n\n // Reset entrance flag when panel moves away from top\n useEffect(() => {\n if (!isTop) {\n hasEnteredRef.current = false;\n }\n }, [isTop]);\n\n const handleAnimationComplete = useCallback(() => {\n if (isTop && !hasEnteredRef.current) {\n hasEnteredRef.current = true;\n config.onOpenComplete?.();\n }\n }, [isTop, config]);\n\n // Drag-to-dismiss (only on top panel, disabled when reduced motion is preferred)\n useDrag(\n panelRef,\n {\n enabled:\n isTop && config.drag && config.dismissible && !prefersReducedMotion,\n closeThreshold: config.closeThreshold,\n velocityThreshold: config.velocityThreshold,\n side,\n onClose: swipeClose,\n onPop: swipePop,\n isNested,\n snapHeights,\n activeSnapIndex,\n onSnap,\n sequential: config.snapToSequentialPoints,\n },\n setDragState\n );\n\n // Per-sheet aria-label: check data.__ariaLabel, fall back to config\n const ariaLabel =\n (typeof item.data?.__ariaLabel === \"string\"\n ? item.data.__ariaLabel\n : undefined) ?? config.ariaLabel;\n\n // Panel context for composable parts (Sheet.Close, Sheet.Title, etc.)\n const panelId = `stacksheet-${item.id}`;\n const [hasDescription, setHasDescription] = useState(false);\n const registerDescription = useCallback(() => {\n setHasDescription(true);\n return () => setHasDescription(false);\n }, []);\n const panelContext = useMemo(\n () => ({\n close,\n back: pop,\n isNested,\n isTop,\n panelId,\n side,\n hasDescription,\n registerDescription,\n }),\n [\n close,\n pop,\n isNested,\n isTop,\n panelId,\n side,\n hasDescription,\n registerDescription,\n ]\n );\n\n const isComposable = renderHeader === false;\n const hasPanelClass = classNames.panel !== \"\";\n const dragOffset = getDragTransform(side, dragState.offset);\n const panelStyle = buildPanelStyle(\n panelStyles,\n isTop,\n hasPanelClass,\n dragState.isDragging\n );\n\n const headerProps: HeaderRenderProps = {\n isNested,\n onBack: pop,\n onClose: close,\n side,\n };\n\n const ariaProps = buildAriaProps(\n isTop,\n config.modal,\n isComposable,\n ariaLabel,\n panelId,\n hasDescription\n );\n\n const transition = buildPanelTransition(\n dragState.isDragging,\n isTop,\n spring,\n stackSpring\n );\n\n const animatedRadius = getAnimatedBorderRadius(side, depth, config.stacking);\n const snapYOffset = computeSnapYOffset(\n side,\n snapHeights,\n activeSnapIndex,\n measuredHeight\n );\n const resolvedSlideFrom = resolveSlideFrom(side, slideFrom, measuredHeight);\n\n // Merge stack offset + drag offset + snap offset into the animate target.\n const stackOffset = getStackOffset(side, transform.offset);\n const animateTarget = buildAnimateTarget(\n slideTarget,\n stackOffset,\n dragOffset,\n transform,\n animatedRadius,\n transition,\n snapYOffset,\n isTop\n );\n\n const initialRadius = getInitialRadius(side);\n const showSideHandle = isTop && side !== \"bottom\";\n const showBottomHandle = isTop && side === \"bottom\";\n\n const panelContent = (\n <m.div\n animate={animateTarget}\n className={classNames.panel || undefined}\n exit={{\n ...resolvedSlideFrom,\n opacity: 0.6,\n boxShadow: getShadow(false),\n transition: {\n type: \"tween\",\n duration: prefersReducedMotion ? 0 : 0.24,\n ease: \"easeOut\",\n boxShadow: VISUAL_TWEEN,\n },\n }}\n initial={{\n ...resolvedSlideFrom,\n opacity: 0.8,\n ...initialRadius,\n boxShadow: getShadow(false),\n }}\n key={item.id}\n onAnimationComplete={handleAnimationComplete}\n onBlur={showSideHandle ? () => setIsHovered(false) : undefined}\n onFocus={showSideHandle ? () => setIsHovered(true) : undefined}\n onMouseEnter={showSideHandle ? () => setIsHovered(true) : undefined}\n onMouseLeave={showSideHandle ? () => setIsHovered(false) : undefined}\n ref={panelRef}\n style={panelStyle}\n tabIndex={isTop ? -1 : undefined}\n {...(isTop ? {} : { \"aria-hidden\": \"true\" as const, inert: true })}\n {...ariaProps}\n >\n {showSideHandle && (\n <SideHandle\n isHovered={isHovered}\n onDismiss={isNested ? pop : close}\n side={side}\n />\n )}\n <div className=\"flex min-h-0 flex-1 flex-col overflow-hidden rounded-[inherit]\">\n {showBottomHandle && (\n <BottomHandle onDismiss={isNested ? pop : close} />\n )}\n <PanelInnerContent\n Content={Content}\n data={item.data as Record<string, unknown>}\n headerClassName={classNames.header || undefined}\n headerProps={headerProps}\n isComposable={isComposable}\n renderHeader={renderHeader}\n shouldRender={shouldRender}\n />\n </div>\n </m.div>\n );\n\n return (\n <SheetPanelContext.Provider value={panelContext}>\n <ModalFocusTrap\n active={isTop}\n enabled={config.modal}\n fallbackRef={panelRef}\n >\n {panelContent}\n </ModalFocusTrap>\n </SheetPanelContext.Provider>\n );\n});\n\n// ── Body scale effect ───────────────────────────\n\nfunction useBodyScale(\n config: ResolvedConfig,\n isOpen: boolean,\n prefersReducedMotion: boolean\n) {\n useEffect(() => {\n if (!config.shouldScaleBackground || prefersReducedMotion) {\n return;\n }\n\n const wrapper = document.querySelector(\"[data-stacksheet-wrapper]\");\n if (!(wrapper && wrapper instanceof HTMLElement)) {\n return;\n }\n\n if (isOpen) {\n const scale = config.scaleBackgroundAmount;\n wrapper.style.transition =\n \"transform 500ms cubic-bezier(0.32, 0.72, 0, 1), border-radius 500ms cubic-bezier(0.32, 0.72, 0, 1)\";\n wrapper.style.transform = `scale(${scale})`;\n wrapper.style.borderRadius = \"8px\";\n wrapper.style.overflow = \"hidden\";\n wrapper.style.transformOrigin = \"center top\";\n return;\n }\n\n wrapper.style.transform = \"\";\n wrapper.style.borderRadius = \"\";\n // Clean up after transition completes\n const handleEnd = () => {\n wrapper.style.transition = \"\";\n wrapper.style.overflow = \"\";\n wrapper.style.transformOrigin = \"\";\n };\n wrapper.addEventListener(\"transitionend\", handleEnd, { once: true });\n return () => wrapper.removeEventListener(\"transitionend\", handleEnd);\n }, [\n isOpen,\n config.shouldScaleBackground,\n config.scaleBackgroundAmount,\n prefersReducedMotion,\n ]);\n}\n\n// ── Renderer ────────────────────────────────────\n\ninterface SheetRendererProps<TMap extends object> {\n store: StoreApi<StacksheetSnapshot<TMap> & SheetActions<TMap>>;\n config: ResolvedConfig;\n sheets: ContentMap<TMap>;\n /** Ad-hoc component map (type key → component) */\n // biome-ignore lint/suspicious/noExplicitAny: heterogeneous component storage\n componentMap: Map<string, ComponentType<any>>;\n classNames?: StacksheetClassNames;\n renderHeader?: false | ((props: HeaderRenderProps) => React.ReactNode);\n}\n\n/**\n * Root renderer component — manages the backdrop, scroll lock, snap points,\n * close reasons, focus restoration, keyboard/CloseWatcher dismissal, and\n * delegates per-panel rendering to `SheetPanel`.\n *\n * Mounted inside a Portal by `StacksheetProvider`.\n */\nexport function SheetRenderer<TMap extends object>({\n store,\n config,\n sheets,\n componentMap,\n classNames: classNamesProp,\n renderHeader,\n}: SheetRendererProps<TMap>) {\n const isOpen = useStore(store, (s) => s.isOpen);\n const stack = useStore(store, (s) => s.stack);\n const rawClose = useStore(store, (s) => s.close);\n const rawPop = useStore(store, (s) => s.pop);\n\n const side = useResolvedSide(config);\n const prefersReducedMotion = useReducedMotion() ?? false;\n const classNames = useMemo(\n () => resolveClassNames(classNamesProp),\n [classNamesProp]\n );\n\n // ── Snap points ──────────────────────────────\n const snapHeights = useMemo(\n () =>\n side === \"bottom\" && config.snapPoints.length > 0\n ? resolveSnapPoints(\n config.snapPoints,\n typeof window !== \"undefined\" ? window.innerHeight : 0\n )\n : [],\n [side, config.snapPoints]\n );\n\n // Default to the last snap point (fully open) when snap points are defined\n const [internalSnapIndex, setInternalSnapIndex] = useState(\n snapHeights.length > 0 ? snapHeights.length - 1 : 0\n );\n\n // Controlled vs uncontrolled snap index\n const activeSnapIndex = config.snapPointIndex ?? internalSnapIndex;\n\n const handleSnap = useCallback(\n (index: number) => {\n setInternalSnapIndex(index);\n config.onSnapPointChange?.(index);\n },\n [config.onSnapPointChange, config]\n );\n\n // Reset snap index when stack opens (start at initial snap point or fully open)\n useEffect(() => {\n if (isOpen && snapHeights.length > 0) {\n const initial = config.snapPointIndex ?? snapHeights.length - 1;\n setInternalSnapIndex(initial);\n }\n }, [isOpen, snapHeights.length, config.snapPointIndex]);\n\n // Track why the sheet was closed — ref survives until exit animation completes\n const closeReasonRef = useRef<CloseReason>(\"programmatic\");\n\n const closeWith = useCallback(\n (reason: CloseReason) => {\n closeReasonRef.current = reason;\n rawClose();\n },\n [rawClose]\n );\n\n const popWith = useCallback(\n (reason: CloseReason) => {\n closeReasonRef.current = reason;\n rawPop();\n },\n [rawPop]\n );\n\n // Default close/pop (programmatic) for child components\n const close = useCallback(() => closeWith(\"programmatic\"), [closeWith]);\n const pop = useCallback(() => popWith(\"programmatic\"), [popWith]);\n\n // Body scale effect\n useBodyScale(config, isOpen, prefersReducedMotion);\n\n // Focus restoration: capture the element that was focused when the stack opens.\n // When the stack fully closes, return focus to that element.\n const triggerRef = useRef<Element | null>(null);\n const wasOpenRef = useRef(false);\n\n useEffect(() => {\n if (isOpen && !wasOpenRef.current) {\n triggerRef.current = document.activeElement;\n } else if (!isOpen && wasOpenRef.current) {\n const el = triggerRef.current;\n // Only restore focus to meaningful elements — skip document.body\n // which happens when sheets are opened programmatically.\n if (\n el &&\n el instanceof HTMLElement &&\n el !== document.body &&\n el.tagName !== \"BODY\"\n ) {\n el.focus();\n }\n triggerRef.current = null;\n }\n wasOpenRef.current = isOpen;\n }, [isOpen]);\n\n // Ref for stack length — avoids re-subscribing keyboard/CloseWatcher\n // effects on every push/pop.\n const stackLengthRef = useRef(stack.length);\n useEffect(() => {\n stackLengthRef.current = stack.length;\n }, [stack.length]);\n\n // Escape key\n useEffect(() => {\n if (!(isOpen && config.closeOnEscape && config.dismissible)) {\n return;\n }\n\n function handleKeyDown(e: KeyboardEvent) {\n if (e.key === \"Escape\") {\n e.preventDefault();\n if (stackLengthRef.current > 1) {\n popWith(\"escape\");\n } else {\n closeWith(\"escape\");\n }\n }\n }\n\n document.addEventListener(\"keydown\", handleKeyDown);\n return () => document.removeEventListener(\"keydown\", handleKeyDown);\n }, [isOpen, config.closeOnEscape, config.dismissible, popWith, closeWith]);\n\n // CloseWatcher — handles Android back gesture (progressive enhancement).\n // On browsers without support (Safari, Firefox), this is a no-op.\n useEffect(() => {\n if (\n !(isOpen && config.dismissible) ||\n typeof globalThis.CloseWatcher === \"undefined\"\n ) {\n return;\n }\n\n const watcher = new globalThis.CloseWatcher();\n watcher.onclose = () => {\n if (stackLengthRef.current > 1) {\n popWith(\"escape\");\n } else {\n closeWith(\"escape\");\n }\n };\n\n return () => watcher.destroy();\n }, [isOpen, config.dismissible, popWith, closeWith]);\n\n const slideFrom = useMemo(() => getSlideFrom(side), [side]);\n const slideTarget = useMemo(() => getSlideTarget(), []);\n\n // Primary spring — drives the top sheet's entrance slide.\n // When reduced motion is preferred, use instant transitions.\n const spring = useMemo(\n () =>\n prefersReducedMotion\n ? ({ type: \"tween\" as const, duration: 0 } as const)\n : ({\n type: \"spring\" as const,\n damping: config.spring.damping,\n stiffness: config.spring.stiffness,\n mass: config.spring.mass,\n } as const),\n [\n prefersReducedMotion,\n config.spring.damping,\n config.spring.stiffness,\n config.spring.mass,\n ]\n );\n\n // Same spring for stacking transforms\n const stackSpring = spring;\n\n // Non-modal: skip overlay, skip scroll lock\n const isModal = config.modal;\n const showOverlay = isModal && config.showOverlay;\n\n // Backdrop: use className if provided, otherwise inline fallback.\n // will-change hints the compositor to properly manage the layer lifecycle.\n const hasBackdropClass = classNames.backdrop !== \"\";\n const backdropStyle: CSSProperties = {\n zIndex: config.zIndex,\n willChange: \"opacity\",\n cursor:\n config.closeOnBackdrop && config.dismissible ? \"pointer\" : undefined,\n ...(hasBackdropClass\n ? {}\n : { background: \"var(--overlay, rgba(0, 0, 0, 0.2))\" }),\n };\n\n // Handle exit complete — fire onCloseComplete when stack is fully empty\n const handleExitComplete = useCallback(() => {\n if (stack.length === 0) {\n config.onCloseComplete?.(closeReasonRef.current);\n }\n }, [stack.length, config]);\n\n // Force WebKit repaint after backdrop exit animation completes.\n // iOS Safari's compositor can retain the visual layer of a fixed-position\n // element after it's removed from the DOM, leaving a ghost tint.\n // A layout recalc via offsetHeight forces the compositor to invalidate\n // stale layers without affecting element positioning.\n const handleBackdropExitComplete = useCallback(() => {\n requestAnimationFrame(() => {\n // Read offsetHeight to force a layout recalc — the value itself is unused.\n // biome-ignore lint/complexity/noVoid: intentional layout recalc for WebKit\n void document.body.offsetHeight;\n });\n }, []);\n\n // Swipe-specific dismiss callbacks\n const swipeClose = useCallback(() => closeWith(\"swipe\"), [closeWith]);\n const swipePop = useCallback(() => popWith(\"swipe\"), [popWith]);\n\n // Non-modal: don't lock scroll\n const shouldLockScroll = isOpen && isModal && config.lockScroll;\n\n return (\n <>\n {/* Backdrop — independent AnimatePresence so it fades on its own.\n onExitComplete forces a WebKit repaint to clear stale compositor layers (iOS Safari). */}\n {showOverlay && (\n <AnimatePresence onExitComplete={handleBackdropExitComplete}>\n {isOpen && (\n <m.div\n animate={{ opacity: 1 }}\n className={`fixed inset-0 ${classNames.backdrop || \"\"}`}\n exit={{ opacity: 0 }}\n initial={{ opacity: 0 }}\n key=\"stacksheet-backdrop\"\n onClick={\n config.closeOnBackdrop && config.dismissible\n ? () => closeWith(\"backdrop\")\n : undefined\n }\n style={backdropStyle}\n transition={spring}\n />\n )}\n </AnimatePresence>\n )}\n\n {/* Panel clip container — always rendered, invisible when empty */}\n <RemoveScroll enabled={shouldLockScroll} forwardProps>\n <div\n className=\"pointer-events-none fixed inset-0 overflow-hidden\"\n style={{ zIndex: config.zIndex + 1 }}\n >\n <AnimatePresence onExitComplete={handleExitComplete}>\n {stack.map((item, index) => {\n const depth = stack.length - 1 - index;\n const isTop = depth === 0;\n const isNested = index > 0;\n // Keep one extra hidden panel mounted as a warm buffer.\n // Without this, popping from deep stacks can mount content on the\n // same frame it becomes visible, which can cause a reverse jank.\n const shouldRender = depth <= config.stacking.renderThreshold;\n\n // Ad-hoc components take priority, then fall back to sheets map\n const Content = (componentMap.get(item.type) ??\n sheets[item.type as keyof TMap]) as\n | ComponentType<Record<string, unknown>>\n | undefined;\n\n return (\n <SheetPanel\n activeSnapIndex={activeSnapIndex}\n Content={Content}\n classNames={classNames}\n close={close}\n config={config}\n depth={depth}\n index={index}\n isNested={isNested}\n isTop={isTop}\n item={item}\n key={item.id}\n onSnap={handleSnap}\n pop={pop}\n prefersReducedMotion={prefersReducedMotion}\n renderHeader={renderHeader}\n shouldRender={shouldRender}\n side={side}\n slideFrom={slideFrom}\n slideTarget={slideTarget}\n snapHeights={snapHeights}\n spring={spring}\n stackSpring={stackSpring}\n swipeClose={swipeClose}\n swipePop={swipePop}\n />\n );\n })}\n </AnimatePresence>\n </div>\n </RemoveScroll>\n </>\n );\n}\n\n// ── Helpers ─────────────────────────────────────\n\nfunction getInitialRadius(side: Side): Record<string, number> {\n if (side === \"bottom\") {\n return {\n borderTopLeftRadius: 0,\n borderTopRightRadius: 0,\n borderBottomLeftRadius: 0,\n borderBottomRightRadius: 0,\n };\n }\n return { borderRadius: 0 };\n}\n\n// Collins-style layered shadows — soft, diffused, multi-stop.\nconst SHADOW_SM =\n \"0px 2px 5px 0px rgba(0,0,0,0.11), 0px 9px 9px 0px rgba(0,0,0,0.1), 0px 21px 13px 0px rgba(0,0,0,0.06)\";\nconst SHADOW_LG =\n \"0px 23px 52px 0px rgba(0,0,0,0.08), 0px 94px 94px 0px rgba(0,0,0,0.07), 0px 211px 127px 0px rgba(0,0,0,0.04)\";\n\nfunction getShadow(isNested: boolean): string {\n return isNested ? SHADOW_SM : SHADOW_LG;\n}\n","/** Inline SVG icons — no external dependency */\n\nexport function ArrowLeftIcon() {\n return (\n <svg\n aria-hidden=\"true\"\n fill=\"none\"\n height={16}\n stroke=\"currentColor\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n viewBox=\"0 0 24 24\"\n width={16}\n >\n <path d=\"M19 12H5M12 19l-7-7 7-7\" />\n </svg>\n );\n}\n\nexport function XIcon() {\n return (\n <svg\n aria-hidden=\"true\"\n fill=\"none\"\n height={16}\n stroke=\"currentColor\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n viewBox=\"0 0 24 24\"\n width={16}\n >\n <path d=\"M18 6L6 18M6 6l12 12\" />\n </svg>\n );\n}\n","import { useEffect, useState } from \"react\";\nimport type { ResolvedConfig, Side } from \"./types\";\n\n/**\n * Returns true when viewport width is at or below the breakpoint.\n * SSR-safe: defaults to false (desktop).\n */\nexport function useIsMobile(breakpoint: number): boolean {\n const [isMobile, setIsMobile] = useState(false);\n\n useEffect(() => {\n const mql = window.matchMedia(`(max-width: ${breakpoint - 1}px)`);\n setIsMobile(mql.matches);\n\n const handler = (e: MediaQueryListEvent) => setIsMobile(e.matches);\n mql.addEventListener(\"change\", handler);\n return () => mql.removeEventListener(\"change\", handler);\n }, [breakpoint]);\n\n return isMobile;\n}\n\n/** Resolve the current side from config + viewport. */\nexport function useResolvedSide(config: ResolvedConfig): Side {\n const isMobile = useIsMobile(config.breakpoint);\n return isMobile ? config.side.mobile : config.side.desktop;\n}\n","import { createContext, useContext } from \"react\";\nimport type { Side } from \"./types\";\n\nexport interface SheetPanelContextValue {\n /** Close the entire sheet stack */\n close: () => void;\n /** Pop the top sheet (go back one level) */\n back: () => void;\n /** Whether the stack has more than one sheet */\n isNested: boolean;\n /** Whether this is the top (active) sheet */\n isTop: boolean;\n /** Unique ID prefix for this panel (for aria-labelledby linking) */\n panelId: string;\n /** Current resolved side (left/right/bottom) */\n side: Side;\n /** Whether a Sheet.Description is mounted inside this panel */\n hasDescription: boolean;\n /** Called by Sheet.Description on mount to register its presence */\n registerDescription: () => () => void;\n}\n\nexport const SheetPanelContext = createContext<SheetPanelContextValue | null>(\n null\n);\n\n/**\n * Access the current sheet panel's context.\n * Must be called inside a component rendered by the sheet stack.\n */\nexport function useSheetPanel(): SheetPanelContextValue {\n const ctx = useContext(SheetPanelContext);\n if (!ctx) {\n throw new Error(\n \"Sheet.* components must be used inside a sheet panel. \" +\n \"They should be rendered by a component opened via actions.open(), push(), etc.\"\n );\n }\n return ctx;\n}\n","import type { SnapPoint } from \"./types\";\n\nconst SNAP_POINT_RE = /^(\\d+(?:\\.\\d+)?)(px|rem|em|vh|%)$/;\n\n/**\n * Resolve a snap point value to pixels given the viewport height.\n * - number 0-1: fraction of viewport (0.5 → 50% of vh)\n * - number > 1: pixel value (300 → 300px)\n * - string: parsed via regex for CSS unit support\n */\nfunction resolveSnapPointPx(point: SnapPoint, viewportHeight: number): number {\n if (typeof point === \"number\") {\n return point <= 1 ? point * viewportHeight : point;\n }\n\n if (typeof point === \"string\") {\n const match = point.match(SNAP_POINT_RE);\n if (!match?.[1]) {\n return 0;\n }\n const value = Number.parseFloat(match[1]);\n const unit = match[2];\n switch (unit) {\n case \"px\":\n return value;\n case \"rem\":\n case \"em\": {\n const fontSize =\n typeof document !== \"undefined\"\n ? Number.parseFloat(\n getComputedStyle(document.documentElement).fontSize\n )\n : 16;\n return value * fontSize;\n }\n case \"vh\":\n case \"%\":\n return (value / 100) * viewportHeight;\n default:\n return 0;\n }\n }\n\n return 0;\n}\n\n/**\n * Resolve all snap points to sorted pixel heights (ascending).\n * Returns an array of heights in px that the drawer should snap to.\n */\nexport function resolveSnapPoints(\n points: SnapPoint[],\n viewportHeight: number\n): number[] {\n if (points.length === 0) {\n return [];\n }\n\n const resolved = points\n .map((p) => resolveSnapPointPx(p, viewportHeight))\n .filter((px) => px > 0);\n\n // Sort ascending (smallest snap point first)\n resolved.sort((a, b) => a - b);\n\n // Deduplicate (1px tolerance)\n const deduped: number[] = [];\n for (const px of resolved) {\n const last = deduped.at(-1);\n if (last === undefined || Math.abs(px - last) > 1) {\n deduped.push(px);\n }\n }\n\n return deduped;\n}\n\n/** Velocity threshold (px/ms) for skipping intermediate snap points */\nconst SNAP_VELOCITY_THRESHOLD = 0.4;\n\n/** Max velocity to consider for snap offset calculation */\nconst MAX_SNAP_VELOCITY = 2;\n\n/** Multiplier to convert velocity to pixel offset for snap target */\nconst SNAP_VELOCITY_MULTIPLIER = 150;\n\n/**\n * Given the current drag offset (from fully open), resolved snap heights,\n * the panel height, and release velocity, find the best snap point index.\n *\n * `dragOffset` is positive in the dismiss direction (downward for bottom sheets).\n * Snap heights are \"how tall the drawer should be\" (ascending order).\n *\n * Returns -1 if the gesture indicates full dismissal.\n */\nexport function findSnapTarget(\n dragOffset: number,\n panelHeight: number,\n snapHeights: number[],\n velocity: number,\n currentIndex: number,\n sequential: boolean\n): number {\n if (snapHeights.length === 0) {\n return -1;\n }\n\n // Convert snap heights to offsets from fully open (panelHeight = 0 offset)\n // A smaller snap height = larger offset from top = more closed\n const snapOffsets = snapHeights.map((h) => panelHeight - h);\n\n // Current position = dragOffset from fully open\n const currentPos = dragOffset;\n\n if (sequential) {\n // Sequential mode: only snap to adjacent points\n const direction = velocity > 0 ? 1 : -1; // positive = dismissing\n const nextIndex = currentIndex - direction; // snap heights are ascending, so -1 = more closed\n if (nextIndex < 0) {\n return -1; // dismiss\n }\n if (nextIndex >= snapHeights.length) {\n return snapHeights.length - 1; // fully open\n }\n return nextIndex;\n }\n\n // Velocity-based: project position forward based on velocity\n const velocityOffset =\n Math.abs(velocity) >= SNAP_VELOCITY_THRESHOLD\n ? Math.min(Math.max(velocity, -MAX_SNAP_VELOCITY), MAX_SNAP_VELOCITY) *\n SNAP_VELOCITY_MULTIPLIER\n : 0;\n\n const projectedPos = currentPos + velocityOffset;\n\n // Find nearest snap offset to projected position\n const first = snapOffsets[0] ?? 0;\n let bestIndex = 0;\n let bestDist = Math.abs(projectedPos - first);\n\n for (let i = 1; i < snapOffsets.length; i++) {\n const offset = snapOffsets[i] ?? 0;\n const dist = Math.abs(projectedPos - offset);\n if (dist < bestDist) {\n bestDist = dist;\n bestIndex = i;\n }\n }\n\n // Check if dismissal is closer than (or equal to) any snap point.\n // Ties favor dismiss — the user dragged past the last snap point.\n const dismissDist = Math.abs(projectedPos - panelHeight);\n if (dismissDist <= bestDist) {\n return -1;\n }\n\n return bestIndex;\n}\n\n/**\n * Get the Y offset for a snap point relative to fully open (0 offset).\n * Returns the number of pixels the drawer should be translated down from fully open.\n */\nexport function getSnapOffset(\n snapIndex: number,\n snapHeights: number[],\n panelHeight: number\n): number {\n if (snapIndex < 0 || snapIndex >= snapHeights.length) {\n return 0;\n }\n const targetHeight = snapHeights[snapIndex] ?? 0;\n return panelHeight - targetHeight;\n}\n","import type { CSSProperties } from \"react\";\nimport type { ResolvedConfig, Side, StackingConfig } from \"./types\";\n\n// ── Depth transforms ────────────────────────────\n\nexport interface StackTransform {\n scale: number;\n offset: number;\n opacity: number;\n borderRadius: number;\n}\n\n/**\n * Compute visual transforms for a panel at a given depth.\n * depth=0 is the top (foreground) panel.\n * Panels beyond renderThreshold are clamped to the edge position and faded out.\n */\nexport function getStackTransform(\n depth: number,\n stacking: StackingConfig\n): StackTransform {\n if (depth <= 0) {\n return { scale: 1, offset: 0, opacity: 1, borderRadius: 0 };\n }\n\n const beyondThreshold = depth >= stacking.renderThreshold;\n // Clamp visual depth so panels beyond threshold stay at the edge position\n const visualDepth = beyondThreshold ? stacking.renderThreshold - 1 : depth;\n\n return {\n scale: Math.max(0.5, 1 - visualDepth * stacking.scaleStep),\n offset: visualDepth * stacking.offsetStep,\n opacity: beyondThreshold\n ? 0\n : Math.max(0, 1 - visualDepth * stacking.opacityStep),\n borderRadius: stacking.radius,\n };\n}\n\n/**\n * Border radius values for the animate target.\n * Must be animated (not static CSS) so Motion applies scale correction\n * when panels are scaled. See: https://motion.dev/docs/react-layout-animations#scale-correction\n */\nexport function getAnimatedBorderRadius(\n side: Side,\n depth: number,\n stacking: StackingConfig\n): Record<string, number> {\n if (side === \"bottom\") {\n const radius = depth > 0 ? stacking.radius : 16;\n return {\n borderTopLeftRadius: radius,\n borderTopRightRadius: radius,\n borderBottomLeftRadius: 0,\n borderBottomRightRadius: 0,\n };\n }\n\n // Left/right panels: stacked panels get uniform radius, top panel gets none\n if (depth > 0) {\n return { borderRadius: stacking.radius };\n }\n return { borderRadius: 0 };\n}\n\n// ── Slide directions ────────────────────────────\n\nexport interface SlideValues {\n x?: string | number;\n y?: string | number;\n}\n\n/** Motion initial/exit values for sliding from the given side. */\nexport function getSlideFrom(side: Side): SlideValues {\n switch (side) {\n case \"right\":\n return { x: \"100%\" };\n case \"left\":\n return { x: \"-100%\" };\n case \"bottom\":\n return { y: \"100%\" };\n default:\n return { x: \"100%\" };\n }\n}\n\n/** Motion animate target — the resting position. */\nexport function getSlideTarget(): SlideValues {\n return { x: 0, y: 0 };\n}\n\n/** Translate offset that pushes stacked panels away from the stack edge. */\nexport function getStackOffset(\n side: Side,\n offset: number\n): { x?: number; y?: number } {\n if (offset === 0) {\n return {};\n }\n switch (side) {\n case \"right\":\n return { x: -offset };\n case \"left\":\n return { x: offset };\n case \"bottom\":\n return { y: -offset };\n default:\n return {};\n }\n}\n\n// ── Transform origin ────────────────────────────\n\n/** Opposite-side origin so stacked panels recede away from the stack edge. */\nfunction getTransformOrigin(side: Side): string {\n if (side === \"right\") {\n return \"left center\";\n }\n if (side === \"left\") {\n return \"right center\";\n }\n return \"center top\";\n}\n\n// ── Panel positioning ───────────────────────────\n\n/**\n * Fixed-position styles for a panel, accounting for side, width, and depth.\n */\nexport function getPanelStyles(\n side: Side,\n config: ResolvedConfig,\n index: number\n): CSSProperties {\n const { width, maxWidth, zIndex } = config;\n const base: CSSProperties = {\n position: \"fixed\",\n zIndex: zIndex + 10 + index,\n display: \"flex\",\n flexDirection: \"column\",\n willChange: \"transform\",\n transformOrigin: getTransformOrigin(side),\n };\n\n if (side === \"bottom\") {\n return {\n ...base,\n left: 0,\n right: 0,\n bottom: 0,\n // dvh tracks the dynamic viewport on iOS Safari (accounts for browser chrome).\n // The vh fallback covers browsers that don't support dvh yet.\n maxHeight: \"85dvh\",\n // borderRadius is animated via Motion's animate prop for scale correction\n };\n }\n\n // Left or right side panel\n const sideStyles: CSSProperties =\n side === \"right\"\n ? { top: 0, right: 0, bottom: 0 }\n : { top: 0, left: 0, bottom: 0 };\n\n return {\n ...base,\n ...sideStyles,\n width,\n maxWidth,\n };\n}\n","import { type RefObject, useCallback, useEffect, useRef } from \"react\";\nimport { findSnapTarget } from \"./snap-points\";\nimport type { Side } from \"./types\";\n\nexport interface DragConfig {\n /** Enable drag-to-dismiss. Default: true */\n enabled: boolean;\n /** Fraction of panel dimension to trigger close (0-1). Default: 0.25 */\n closeThreshold: number;\n /** Velocity threshold (px/ms) to trigger close. Default: 0.5 */\n velocityThreshold: number;\n /** Side the panel is on — determines drag direction */\n side: Side;\n /** Callback when drag ends and close should fire */\n onClose: () => void;\n /** Callback when drag ends and pop should fire */\n onPop: () => void;\n /** Whether the stack has >1 sheet (swipe pops instead of closing) */\n isNested: boolean;\n /** Resolved snap point heights in px (sorted ascending). Empty = no snap points. */\n snapHeights: number[];\n /** Current active snap point index */\n activeSnapIndex: number;\n /** Called when snap target changes on release */\n onSnap: (index: number) => void;\n /** When true, can't skip intermediate snap points */\n sequential: boolean;\n}\n\nexport interface DragState {\n /** Current drag offset in the dismiss direction (px) */\n offset: number;\n /** Whether a drag is currently active */\n isDragging: boolean;\n}\n\n/** Elements that should never initiate a drag */\nconst INTERACTIVE_TAGS = new Set([\n \"INPUT\",\n \"TEXTAREA\",\n \"SELECT\",\n \"BUTTON\",\n \"A\",\n]);\n\nfunction isInteractiveElement(el: Element): boolean {\n if (INTERACTIVE_TAGS.has(el.tagName)) {\n return true;\n }\n if ((el as HTMLElement).isContentEditable) {\n return true;\n }\n // Children of interactive elements (e.g. SVG inside button, span inside link)\n if (el.closest(\"button, a, input, textarea, select, [contenteditable]\")) {\n return true;\n }\n if (el.closest(\"[data-stacksheet-no-drag]\")) {\n return true;\n }\n return false;\n}\n\n/**\n * Walk up from `el` to find the nearest scrollable ancestor.\n * Returns null if nothing is scrollable in the dismiss axis.\n */\nfunction findScrollableAncestor(el: Element, axis: \"x\" | \"y\"): Element | null {\n let current: Element | null = el;\n while (current) {\n if (current instanceof HTMLElement) {\n const style = getComputedStyle(current);\n const overflow = axis === \"y\" ? style.overflowY : style.overflowX;\n if (overflow === \"auto\" || overflow === \"scroll\") {\n const scrollable =\n axis === \"y\"\n ? current.scrollHeight > current.clientHeight\n : current.scrollWidth > current.clientWidth;\n if (scrollable) {\n return current;\n }\n }\n }\n current = current.parentElement;\n }\n return null;\n}\n\n/**\n * Check if a scrollable element is at its edge in the dismiss direction.\n * For bottom sheets (sign=1, axis=y), \"at edge\" means scrolled to top.\n * For left panels (sign=-1, axis=x), \"at edge\" means scrolled to right end.\n */\nfunction isAtScrollEdge(el: Element, axis: \"x\" | \"y\", sign: 1 | -1): boolean {\n if (axis === \"y\") {\n // Dismiss down (sign=1): at edge when scrollTop ≈ 0\n // Dismiss up (sign=-1): at edge when scrolled to bottom\n return sign === 1\n ? el.scrollTop <= 0\n : el.scrollTop + el.clientHeight >= el.scrollHeight - 1;\n }\n return sign === 1\n ? el.scrollLeft <= 0\n : el.scrollLeft + el.clientWidth >= el.scrollWidth - 1;\n}\n\n/**\n * Get the dismiss direction axis and sign for a given side.\n * - right panel → dismiss by dragging right (+x)\n * - left panel → dismiss by dragging left (-x)\n * - bottom panel → dismiss by dragging down (+y)\n */\nfunction getDismissAxis(side: Side): {\n axis: \"x\" | \"y\";\n sign: 1 | -1;\n} {\n switch (side) {\n case \"right\":\n return { axis: \"x\", sign: 1 };\n case \"left\":\n return { axis: \"x\", sign: -1 };\n case \"bottom\":\n return { axis: \"y\", sign: 1 };\n default:\n return { axis: \"x\", sign: 1 };\n }\n}\n\n/** Dead zone in px before committing to drag vs text selection */\nconst DEAD_ZONE = 10;\n\n/** Max angle (degrees) from dismiss axis to qualify as drag intent */\nconst MAX_ANGLE_DEG = 35;\n\n/** Rubber-band resistance factor for dragging past resting position */\nconst RUBBER_BAND_FACTOR = 0.6;\n\n/**\n * Decide whether a gesture past the dead zone qualifies as a dismiss drag.\n * Returns \"drag\" if it's a valid dismiss gesture, \"none\" if it's off-axis\n * or moving in the wrong direction.\n */\nfunction classifyGesture(\n dx: number,\n dy: number,\n axis: \"x\" | \"y\",\n sign: 1 | -1\n): \"drag\" | \"none\" {\n const absDx = Math.abs(dx);\n const absDy = Math.abs(dy);\n\n // Compute angle between movement vector and dismiss axis\n let angleDeg: number;\n if (axis === \"y\") {\n angleDeg = absDy === 0 ? 90 : (Math.atan(absDx / absDy) * 180) / Math.PI;\n } else {\n angleDeg = absDx === 0 ? 90 : (Math.atan(absDy / absDx) * 180) / Math.PI;\n }\n\n if (angleDeg > MAX_ANGLE_DEG) {\n return \"none\";\n }\n\n // Must be moving in the dismiss direction\n const moveInAxis = axis === \"x\" ? dx : dy;\n if (moveInAxis * sign < 0) {\n return \"none\";\n }\n\n return \"drag\";\n}\n\n/** Decide whether a pointer gesture commits as a drag or should be ignored. */\nfunction commitGesture(\n dx: number,\n dy: number,\n axis: \"x\" | \"y\",\n sign: 1 | -1,\n scrollEl: Element | null\n): \"drag\" | \"none\" {\n const gesture = classifyGesture(dx, dy, axis, sign);\n if (gesture === \"none\") {\n return \"none\";\n }\n if (scrollEl && !isAtScrollEdge(scrollEl, axis, sign)) {\n return \"none\";\n }\n return \"drag\";\n}\n\nfunction getPanelDimension(\n panel: HTMLDivElement | null,\n axis: \"x\" | \"y\"\n): number {\n if (!panel) {\n return 300;\n }\n return axis === \"x\" ? panel.offsetWidth : panel.offsetHeight;\n}\n\n/**\n * Hook that manages drag-to-dismiss for a sheet panel.\n *\n * Gesture pipeline:\n * 1. Dead zone (10px) — ignores micro-movements\n * 2. Angle check (35°) — must be roughly aligned with dismiss axis\n * 3. Scroll conflict — yields to scrollable containers not at edge\n * 4. Commit — drag is active, applies offset via `onDragUpdate`\n * 5. Release — velocity + threshold determine close/snap/bounce-back\n *\n * Opposite-direction drag uses √(offset) damping for elastic\n * rubber-band resistance (same physics as iOS over-scroll).\n *\n * When `snapHeights` is provided, release targeting uses\n * `findSnapTarget()` instead of the simple threshold check.\n */\nexport function useDrag(\n panelRef: RefObject<HTMLDivElement | null>,\n config: DragConfig,\n onDragUpdate: (state: DragState) => void\n) {\n const startRef = useRef<{ x: number; y: number; time: number } | null>(null);\n const committedRef = useRef<\"drag\" | \"none\" | null>(null);\n const offsetRef = useRef(0);\n const scrollTargetRef = useRef<Element | null>(null);\n\n const { axis, sign } = getDismissAxis(config.side);\n\n const handlePointerDown = useCallback(\n (e: PointerEvent) => {\n if (!config.enabled) {\n return;\n }\n // Only primary button\n if (e.button !== 0) {\n return;\n }\n // Check target element\n const target = e.target as Element;\n if (!target) {\n return;\n }\n\n // Allow drag from handle elements always\n const isHandle = !!target.closest(\"[data-stacksheet-handle]\");\n\n // For non-handle areas, check if the target is interactive\n if (!isHandle && isInteractiveElement(target)) {\n return;\n }\n\n // Track nearest scrollable ancestor — checked at commit time\n scrollTargetRef.current = isHandle\n ? null\n : findScrollableAncestor(target, axis);\n\n startRef.current = { x: e.clientX, y: e.clientY, time: Date.now() };\n committedRef.current = null;\n offsetRef.current = 0;\n\n // Capture pointer for reliable move/up outside the element\n (e.currentTarget as HTMLElement)?.setPointerCapture?.(e.pointerId);\n },\n [config.enabled, axis]\n );\n\n const handlePointerMove = useCallback(\n (e: PointerEvent) => {\n if (!startRef.current) {\n return;\n }\n\n const dx = e.clientX - startRef.current.x;\n const dy = e.clientY - startRef.current.y;\n const dist = Math.sqrt(dx * dx + dy * dy);\n\n // Still in dead zone — don't commit yet\n if (committedRef.current === null && dist < DEAD_ZONE) {\n return;\n }\n\n // Commit decision: check direction + scroll state\n if (committedRef.current === null) {\n committedRef.current = commitGesture(\n dx,\n dy,\n axis,\n sign,\n scrollTargetRef.current\n );\n if (committedRef.current !== \"drag\") {\n startRef.current = null;\n return;\n }\n }\n\n if (committedRef.current !== \"drag\") {\n return;\n }\n\n // Calculate offset in dismiss direction\n const rawOffset = axis === \"x\" ? dx : dy;\n const directional = rawOffset * sign;\n\n // Dismiss direction: linear movement. Opposite direction: √ damping\n // for elastic rubber-band resistance (same math as iOS over-scroll).\n const clampedOffset =\n directional >= 0\n ? directional\n : -Math.sqrt(Math.abs(directional)) * RUBBER_BAND_FACTOR;\n\n offsetRef.current = clampedOffset;\n onDragUpdate({ offset: clampedOffset, isDragging: true });\n\n // Prevent text selection during active drag\n e.preventDefault();\n },\n [axis, sign, onDragUpdate]\n );\n\n const dismiss = useCallback(() => {\n if (config.isNested) {\n config.onPop();\n } else {\n config.onClose();\n }\n }, [config]);\n\n const handlePointerUp = useCallback(\n (_e: PointerEvent) => {\n if (!startRef.current || committedRef.current !== \"drag\") {\n startRef.current = null;\n committedRef.current = null;\n scrollTargetRef.current = null;\n return;\n }\n\n const offset = Math.max(0, offsetRef.current);\n const elapsed = Date.now() - startRef.current.time;\n const velocity = elapsed > 0 ? offset / elapsed : 0;\n\n startRef.current = null;\n committedRef.current = null;\n offsetRef.current = 0;\n scrollTargetRef.current = null;\n\n const panelSize = getPanelDimension(panelRef.current, axis);\n\n // Snap points mode\n if (config.snapHeights.length > 0) {\n const targetIndex = findSnapTarget(\n offset,\n panelSize,\n config.snapHeights,\n velocity,\n config.activeSnapIndex,\n config.sequential\n );\n if (targetIndex === -1) {\n dismiss();\n } else {\n config.onSnap(targetIndex);\n onDragUpdate({ offset: 0, isDragging: false });\n }\n return;\n }\n\n // Standard mode: threshold-based close\n const pastThreshold = offset / panelSize > config.closeThreshold;\n const fastEnough = velocity > config.velocityThreshold;\n if (pastThreshold || fastEnough) {\n dismiss();\n } else {\n onDragUpdate({ offset: 0, isDragging: false });\n }\n },\n [panelRef, axis, config, onDragUpdate, dismiss]\n );\n\n const handlePointerCancel = useCallback(() => {\n startRef.current = null;\n committedRef.current = null;\n offsetRef.current = 0;\n scrollTargetRef.current = null;\n onDragUpdate({ offset: 0, isDragging: false });\n }, [onDragUpdate]);\n\n // Attach pointer events to the panel element\n useEffect(() => {\n const el = panelRef.current;\n if (!(el && config.enabled)) {\n return;\n }\n\n el.addEventListener(\"pointerdown\", handlePointerDown);\n el.addEventListener(\"pointermove\", handlePointerMove);\n el.addEventListener(\"pointerup\", handlePointerUp);\n el.addEventListener(\"pointercancel\", handlePointerCancel);\n\n return () => {\n el.removeEventListener(\"pointerdown\", handlePointerDown);\n el.removeEventListener(\"pointermove\", handlePointerMove);\n el.removeEventListener(\"pointerup\", handlePointerUp);\n el.removeEventListener(\"pointercancel\", handlePointerCancel);\n };\n }, [\n panelRef,\n config.enabled,\n handlePointerDown,\n handlePointerMove,\n handlePointerUp,\n handlePointerCancel,\n ]);\n}\n","declare const process: undefined | { env?: { NODE_ENV?: string } };\n\nimport type { ComponentType } from \"react\";\nimport { createStore, type StoreApi } from \"zustand\";\nimport type {\n ResolvedConfig,\n SheetActions,\n SheetItem,\n StacksheetSnapshot,\n} from \"./types\";\n\n// biome-ignore lint/suspicious/noExplicitAny: maps store heterogeneous components — type safety is at the call site\ntype AnyComponent = ComponentType<any>;\n\ntype StoreState<TMap extends object> = StacksheetSnapshot<TMap> &\n SheetActions<TMap>;\n\n/** Return type of createSheetStore — store plus ad-hoc component maps */\nexport interface SheetStoreBundle<TMap extends object> {\n store: StoreApi<StoreState<TMap>>;\n /** Component → generated type key (dedup) */\n componentRegistry: Map<AnyComponent, string>;\n /** Generated type key → Component (for renderer lookup) */\n componentMap: Map<string, AnyComponent>;\n}\n\n// ── Ad-hoc helpers ──────────────────────────────\n\n/**\n * Dev-mode warning: detect likely inline arrow functions passed as ad-hoc components.\n * When a new component reference has the same displayName/name as an existing one,\n * it's almost always an inline arrow being re-created every render.\n */\nfunction warnInlineComponent(\n component: AnyComponent,\n componentRegistry: Map<AnyComponent, string>,\n warnedNames: Set<string>\n): void {\n if (\n typeof process === \"undefined\" ||\n process?.env?.NODE_ENV === \"production\"\n ) {\n return;\n }\n\n const name = component.displayName || component.name;\n if (!name) {\n return;\n }\n if (warnedNames.has(name)) {\n return;\n }\n\n for (const [existing, key] of componentRegistry) {\n const existingName = existing.displayName || existing.name;\n if (existingName === name) {\n warnedNames.add(name);\n console.warn(\n `[stacksheet] A new component reference with name \"${name}\" was registered ` +\n `(key: ${key}), but a different reference with the same name already exists. ` +\n `This usually means you're passing an inline arrow function (e.g. ` +\n \"open(() => <MySheet />)). Define the component outside of render to avoid \" +\n \"memory leaks and broken navigate() same-type detection.\"\n );\n return;\n }\n }\n}\n\n/**\n * If `first` is a function (component), register it and return { type, id, data }.\n * Otherwise, pass through the string-based (type, id, data) args unchanged.\n */\nfunction resolveArgs(\n componentRegistry: Map<AnyComponent, string>,\n componentMap: Map<string, AnyComponent>,\n getNextKey: () => string,\n warnedNames: Set<string>,\n first: unknown,\n second: unknown,\n third: unknown\n): { type: string; id: string; data: Record<string, unknown> } {\n if (typeof first === \"function\") {\n const component = first as AnyComponent;\n\n let typeKey = componentRegistry.get(component);\n if (!typeKey) {\n warnInlineComponent(component, componentRegistry, warnedNames);\n typeKey = getNextKey();\n componentRegistry.set(component, typeKey);\n componentMap.set(typeKey, component);\n }\n\n if (typeof second === \"string\") {\n return {\n type: typeKey,\n id: second,\n data: (third ?? {}) as Record<string, unknown>,\n };\n }\n return {\n type: typeKey,\n id: crypto.randomUUID(),\n data: (second ?? {}) as Record<string, unknown>,\n };\n }\n\n return {\n type: first as string,\n id: second as string,\n data: (third ?? {}) as Record<string, unknown>,\n };\n}\n\n/** Pre-resolved args — skips resolveArgs entirely */\ninterface ResolvedItem {\n type: string;\n id: string;\n data: Record<string, unknown>;\n}\n\n/**\n * Create an isolated Zustand store for a sheet stack instance.\n *\n * Returns a store bundle containing the Zustand store plus two maps\n * that track ad-hoc (component-direct) registrations:\n * - `componentRegistry` — maps `ComponentType` → generated type key (dedup)\n * - `componentMap` — maps generated type key → `ComponentType` (renderer lookup)\n *\n * The ad-hoc counter is scoped per instance to prevent identity leaks across\n * multiple `createStacksheet()` calls or test runs.\n */\nexport function createSheetStore<TMap extends object>(\n config: ResolvedConfig\n): SheetStoreBundle<TMap> {\n type Item = SheetItem<Extract<keyof TMap, string>>;\n\n const componentRegistry = new Map<AnyComponent, string>();\n const componentMap = new Map<string, AnyComponent>();\n\n // Per-instance counter (not module-level) — prevents identity leaks across instances/tests\n let adhocCounter = 0;\n function getNextKey() {\n return `__adhoc_${adhocCounter++}`;\n }\n\n // Set of component names already warned about (avoid log spam)\n const warnedNames = new Set<string>();\n\n function resolve(first: unknown, second: unknown, third: unknown) {\n return resolveArgs(\n componentRegistry,\n componentMap,\n getNextKey,\n warnedNames,\n first,\n second,\n third\n );\n }\n\n /** Remove registry entries for type keys no longer in the stack */\n function pruneRegistry(remainingStack: readonly SheetItem[]) {\n const usedTypes = new Set(remainingStack.map((item) => item.type));\n for (const [component, typeKey] of componentRegistry) {\n if (!usedTypes.has(typeKey)) {\n componentRegistry.delete(component);\n componentMap.delete(typeKey);\n }\n }\n }\n\n const store = createStore<StoreState<TMap>>()((set, get) => {\n // ── Internal resolved methods (no double-resolution) ──\n\n function _openResolved({ type, id, data }: ResolvedItem) {\n set({\n stack: [{ id, type, data } as Item],\n isOpen: true,\n });\n }\n\n function _pushResolved({ type, id, data }: ResolvedItem) {\n set((state) => {\n const item = { id, type, data } as Item;\n if (\n Number.isFinite(config.maxDepth) &&\n state.stack.length >= config.maxDepth\n ) {\n return {\n stack: [...state.stack.slice(0, -1), item],\n isOpen: true,\n };\n }\n return {\n stack: [...state.stack, item],\n isOpen: true,\n };\n });\n }\n\n function _replaceResolved({ type, id, data }: ResolvedItem) {\n set((state) => {\n const item = { id, type, data } as Item;\n if (state.stack.length === 0) {\n return { stack: [item], isOpen: true };\n }\n return {\n stack: [...state.stack.slice(0, -1), item],\n isOpen: true,\n };\n });\n }\n\n return {\n stack: [],\n isOpen: false,\n\n open(first: unknown, second?: unknown, third?: unknown) {\n _openResolved(resolve(first, second, third));\n },\n\n push(first: unknown, second?: unknown, third?: unknown) {\n _pushResolved(resolve(first, second, third));\n },\n\n replace(first: unknown, second?: unknown, third?: unknown) {\n _replaceResolved(resolve(first, second, third));\n },\n\n swap(first: unknown, second?: unknown) {\n let type: string;\n let data: Record<string, unknown>;\n\n if (typeof first === \"function\") {\n const component = first as AnyComponent;\n let typeKey = componentRegistry.get(component);\n if (!typeKey) {\n warnInlineComponent(component, componentRegistry, warnedNames);\n typeKey = getNextKey();\n componentRegistry.set(component, typeKey);\n componentMap.set(typeKey, component);\n }\n type = typeKey;\n data = (second ?? {}) as Record<string, unknown>;\n } else {\n type = first as string;\n data = (second ?? {}) as Record<string, unknown>;\n }\n\n set((state) => {\n const top = state.stack.at(-1);\n if (!top) {\n return state;\n }\n const newStack = [...state.stack];\n newStack[newStack.length - 1] = { id: top.id, type, data } as Item;\n return { stack: newStack };\n });\n },\n\n navigate(first: unknown, second?: unknown, third?: unknown) {\n const resolved = resolve(first, second, third);\n const { stack } = get();\n const top = stack.at(-1);\n\n if (stack.length === 0) {\n _openResolved(resolved);\n return;\n }\n\n // For ad-hoc components, check if the top item's type maps to the same\n // component in the registry. For string types, compare directly.\n let isSameType = top?.type === resolved.type;\n if (!isSameType && typeof first === \"function\") {\n const topComponent = componentMap.get(top?.type ?? \"\");\n isSameType = topComponent === first;\n }\n\n if (isSameType) {\n _replaceResolved(resolved);\n return;\n }\n\n _pushResolved(resolved);\n },\n\n setData(first: unknown, second?: unknown, third?: unknown) {\n // setData always has an id: (type, id, data) or (Component, id, data)\n const { id, data } = resolve(first, second, third);\n set((state) => {\n const idx = state.stack.findIndex((item) => item.id === id);\n if (idx === -1) {\n return state;\n }\n const updated = [...state.stack];\n updated[idx] = { ...updated[idx], data } as Item;\n return { stack: updated };\n });\n },\n\n remove(id) {\n set((state) => {\n const next = state.stack.filter((item) => item.id !== id);\n if (next.length === state.stack.length) {\n return state;\n }\n pruneRegistry(next);\n if (next.length === 0) {\n return { stack: [], isOpen: false };\n }\n return { stack: next };\n });\n },\n\n pop() {\n set((state) => {\n if (state.stack.length <= 1) {\n pruneRegistry([]);\n return { stack: [], isOpen: false };\n }\n const next = state.stack.slice(0, -1);\n pruneRegistry(next);\n return { stack: next, isOpen: true };\n });\n },\n\n close() {\n pruneRegistry([]);\n set({ stack: [], isOpen: false });\n },\n };\n });\n\n return { store, componentRegistry, componentMap };\n}\n","import {\n Root as ScrollAreaRoot,\n Scrollbar as ScrollAreaScrollbar,\n Thumb as ScrollAreaThumb,\n Viewport as ScrollAreaViewport,\n} from \"@radix-ui/react-scroll-area\";\nimport { Slot } from \"@radix-ui/react-slot\";\nimport {\n type CSSProperties,\n type KeyboardEvent as ReactKeyboardEvent,\n type ReactNode,\n useEffect,\n} from \"react\";\nimport { ArrowLeftIcon, XIcon } from \"./icons\";\nimport { useSheetPanel } from \"./panel-context\";\n\n// ── Sheet.Handle ────────────────────────────────\n\nexport interface SheetHandleProps {\n /** Render as child element, merging props */\n asChild?: boolean;\n className?: string;\n style?: CSSProperties;\n /** Custom handle content. Defaults to a centered grab bar. */\n children?: ReactNode;\n}\n\nfunction SheetHandle({\n asChild,\n className,\n style,\n children,\n}: SheetHandleProps) {\n const { close, back, isNested } = useSheetPanel();\n const dismiss = isNested ? back : close;\n const Comp = asChild ? Slot : \"div\";\n return (\n <Comp\n aria-label=\"Dismiss\"\n className={`flex shrink-0 cursor-grab touch-none items-center justify-center pt-4 pb-1 ${className ?? \"\"}`}\n data-stacksheet-handle=\"\"\n onClick={dismiss}\n onKeyDown={(e: ReactKeyboardEvent) => {\n if (e.key === \"Enter\" || e.key === \" \") {\n e.preventDefault();\n dismiss();\n }\n }}\n role=\"button\"\n style={style}\n tabIndex={0}\n >\n {children ?? (\n <div aria-hidden=\"true\" className=\"h-1 w-9 rounded-sm bg-current/25\" />\n )}\n </Comp>\n );\n}\n\n// ── Sheet.Header ────────────────────────────────\n\nexport interface SheetHeaderProps {\n asChild?: boolean;\n className?: string;\n style?: CSSProperties;\n children: ReactNode;\n}\n\nfunction SheetHeader({\n asChild,\n className,\n style,\n children,\n}: SheetHeaderProps) {\n const Comp = asChild ? Slot : \"header\";\n return (\n <Comp\n className={`flex h-14 shrink-0 items-center justify-between border-b px-6 ${className ?? \"\"}`}\n style={style}\n >\n {children}\n </Comp>\n );\n}\n\n// ── Sheet.Title ─────────────────────────────────\n\nexport interface SheetTitleProps {\n asChild?: boolean;\n className?: string;\n style?: CSSProperties;\n children: ReactNode;\n}\n\nfunction SheetTitle({ asChild, className, style, children }: SheetTitleProps) {\n const { panelId } = useSheetPanel();\n const Comp = asChild ? Slot : \"h2\";\n return (\n <Comp\n className={`font-semibold text-sm ${className ?? \"\"}`}\n id={`${panelId}-title`}\n style={style}\n >\n {children}\n </Comp>\n );\n}\n\n// ── Sheet.Description ───────────────────────────\n\nexport interface SheetDescriptionProps {\n asChild?: boolean;\n className?: string;\n style?: CSSProperties;\n children: ReactNode;\n}\n\nfunction SheetDescription({\n asChild,\n className,\n style,\n children,\n}: SheetDescriptionProps) {\n const { panelId, registerDescription } = useSheetPanel();\n\n useEffect(() => registerDescription(), [registerDescription]);\n const Comp = asChild ? Slot : \"p\";\n return (\n <Comp className={className} id={`${panelId}-desc`} style={style}>\n {children}\n </Comp>\n );\n}\n\n// ── Sheet.Body ──────────────────────────────────\n\nexport interface SheetBodyProps {\n /** When true, renders child element directly instead of ScrollArea */\n asChild?: boolean;\n className?: string;\n style?: CSSProperties;\n children: ReactNode;\n}\n\nfunction SheetBody({ asChild, className, style, children }: SheetBodyProps) {\n if (asChild) {\n return (\n <Slot\n className={`relative min-h-0 flex-1 ${className ?? \"\"}`}\n data-stacksheet-no-drag=\"\"\n style={style}\n >\n {children}\n </Slot>\n );\n }\n\n return (\n <ScrollAreaRoot\n className={`relative flex min-h-0 flex-1 flex-col overflow-hidden ${className ?? \"\"}`}\n data-stacksheet-no-drag=\"\"\n style={style}\n >\n <ScrollAreaViewport className=\"min-h-0 w-full flex-1 overscroll-contain\">\n {children}\n </ScrollAreaViewport>\n <ScrollAreaScrollbar\n className=\"flex w-2 touch-none select-none p-0.5\"\n orientation=\"vertical\"\n >\n <ScrollAreaThumb className=\"relative flex-1 rounded bg-current/15\" />\n </ScrollAreaScrollbar>\n </ScrollAreaRoot>\n );\n}\n\n// ── Sheet.Footer ────────────────────────────────\n\nexport interface SheetFooterProps {\n asChild?: boolean;\n className?: string;\n style?: CSSProperties;\n children: ReactNode;\n}\n\nfunction SheetFooter({\n asChild,\n className,\n style,\n children,\n}: SheetFooterProps) {\n const Comp = asChild ? Slot : \"footer\";\n return (\n <Comp\n className={`flex shrink-0 items-center gap-2 border-t px-6 py-3 ${className ?? \"\"}`}\n style={style}\n >\n {children}\n </Comp>\n );\n}\n\n// ── Sheet.Close ─────────────────────────────────\n\nexport interface SheetCloseProps {\n asChild?: boolean;\n className?: string;\n style?: CSSProperties;\n /** Custom content. Defaults to an X icon. */\n children?: ReactNode;\n}\n\nfunction SheetClose({ asChild, className, style, children }: SheetCloseProps) {\n const { close } = useSheetPanel();\n const Comp = asChild ? Slot : \"button\";\n return (\n <Comp\n aria-label={children ? undefined : \"Close\"}\n className={`flex h-8 w-8 shrink-0 cursor-pointer items-center justify-center rounded-md border-none bg-transparent p-0 text-inherit opacity-60 transition-opacity duration-150 hover:opacity-100 ${className ?? \"\"}`}\n onClick={close}\n style={style}\n type={asChild ? undefined : \"button\"}\n >\n {children ?? <XIcon />}\n </Comp>\n );\n}\n\n// ── Sheet.Back ──────────────────────────────────\n\nexport interface SheetBackProps {\n asChild?: boolean;\n className?: string;\n style?: CSSProperties;\n /** Custom content. Defaults to an arrow-left icon. */\n children?: ReactNode;\n}\n\nfunction SheetBack({ asChild, className, style, children }: SheetBackProps) {\n const { back, isNested } = useSheetPanel();\n\n if (!isNested) {\n return null;\n }\n\n const Comp = asChild ? Slot : \"button\";\n return (\n <Comp\n aria-label={children ? undefined : \"Back\"}\n className={`flex h-8 w-8 shrink-0 cursor-pointer items-center justify-center rounded-md border-none bg-transparent p-0 text-inherit opacity-60 transition-opacity duration-150 hover:opacity-100 ${className ?? \"\"}`}\n onClick={back}\n style={style}\n type={asChild ? undefined : \"button\"}\n >\n {children ?? <ArrowLeftIcon />}\n </Comp>\n );\n}\n\n// ── Sheet namespace ─────────────────────────────\n\n/**\n * Composable sheet parts for building custom panel layouts.\n *\n * Use with `renderHeader={false}` on the provider to opt into\n * composable mode — no auto header or scroll wrapper, full control\n * over the panel's structure.\n *\n * `Sheet.Title` and `Sheet.Description` are linked to the panel's\n * `aria-labelledby` and `aria-describedby` via matching IDs.\n */\nexport const Sheet = {\n Handle: SheetHandle,\n Header: SheetHeader,\n Title: SheetTitle,\n Description: SheetDescription,\n Body: SheetBody,\n Footer: SheetFooter,\n Close: SheetClose,\n Back: SheetBack,\n} as const;\n"],"mappings":"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","names":["createContext","useContext","useMemo","useStore","useCallback","useEffect","useRef","useState","useEffect","useEffect","jsx","useState","useEffect","SheetPanel","useRef","useCallback","jsx","jsxs","createContext","useContext","useMemo","useStore","useEffect","jsx","jsxs","useEffect"]}
|
|
1
|
+
{"version":3,"sources":["../src/create.tsx","../src/springs.ts","../src/config.ts","../src/renderer.tsx","../src/icons.tsx","../src/media.ts","../src/panel-context.tsx","../src/snap-points.ts","../src/stacking.ts","../src/use-drag.ts","../src/store.ts","../src/parts.tsx"],"sourcesContent":["import { Portal } from \"@radix-ui/react-portal\";\nimport { createContext, useContext, useMemo } from \"react\";\nimport type { StoreApi } from \"zustand\";\nimport { useStore } from \"zustand\";\nimport { useShallow } from \"zustand/react/shallow\";\nimport { resolveConfig } from \"./config\";\nimport { SheetRenderer } from \"./renderer\";\nimport { createSheetStore } from \"./store\";\nimport type {\n ContentMap,\n ResolvedConfig,\n SheetActions,\n StacksheetConfig,\n StacksheetInstance,\n StacksheetProviderProps,\n StacksheetSnapshot,\n} from \"./types\";\n\ntype StoreState<TMap extends object> = StacksheetSnapshot<TMap> &\n SheetActions<TMap>;\n\n/**\n * Create an isolated sheet stack instance with typed store, hooks, and provider.\n *\n * Works with both `interface` and `type` definitions:\n *\n * ```ts\n * // Using an interface\n * interface SheetDataMap {\n * \"bucket-create\": { onCreated?: (b: Bucket) => void };\n * \"bucket-edit\": { bucket: Bucket };\n * }\n *\n * // Using a type alias\n * type SheetDataMap = {\n * \"bucket-create\": { onCreated?: (b: Bucket) => void };\n * \"bucket-edit\": { bucket: Bucket };\n * };\n *\n * const { StacksheetProvider, useSheet, useStacksheetState } =\n * createStacksheet<SheetDataMap>();\n * ```\n *\n * Sheet content components receive their data as **spread props**:\n * ```ts\n * // Data map defines: \"bucket-edit\": { bucket: Bucket }\n * // Component receives: ({ bucket }: { bucket: Bucket }) => JSX.Element\n * ```\n *\n * Use `useSheetPanel()` inside content components to access `close()` and `back()`.\n */\nexport function createStacksheet<TMap extends object>(\n config?: StacksheetConfig\n): StacksheetInstance<TMap> {\n const resolved = resolveConfig(config);\n const { store, componentMap } = createSheetStore<TMap>(resolved);\n\n // Context for the store — allows multiple instances\n const StoreContext = createContext<{\n store: StoreApi<StoreState<TMap>>;\n config: ResolvedConfig;\n } | null>(null);\n\n function useStoreContext() {\n const ctx = useContext(StoreContext);\n if (!ctx) {\n throw new Error(\n \"useSheet/useStacksheetState must be used within <StacksheetProvider>\"\n );\n }\n return ctx;\n }\n\n // ── Provider ────────────────────────────────\n\n const EMPTY_SHEETS = {} as ContentMap<TMap>;\n\n function StacksheetProvider({\n sheets = EMPTY_SHEETS,\n children,\n classNames,\n renderHeader,\n }: StacksheetProviderProps<TMap>) {\n const value = useMemo(() => ({ store, config: resolved }), []);\n return (\n <StoreContext.Provider value={value}>\n {children}\n <Portal asChild={false}>\n <SheetRenderer<TMap>\n classNames={classNames}\n componentMap={componentMap}\n config={resolved}\n renderHeader={renderHeader}\n sheets={sheets}\n store={store}\n />\n </Portal>\n </StoreContext.Provider>\n );\n }\n\n // ── Hooks ───────────────────────────────────\n\n function useSheet(): SheetActions<TMap> {\n const { store: s } = useStoreContext();\n // Actions are stable refs in Zustand v5 — read once, no subscription needed\n return useMemo(() => {\n const state = s.getState();\n return {\n open: state.open,\n push: state.push,\n replace: state.replace,\n swap: state.swap,\n navigate: state.navigate,\n setData: state.setData,\n remove: state.remove,\n pop: state.pop,\n close: state.close,\n };\n }, [s]);\n }\n\n function useStacksheetState(): StacksheetSnapshot<TMap> {\n const { store: s } = useStoreContext();\n return useStore(\n s,\n useShallow((state) => ({\n stack: state.stack,\n isOpen: state.isOpen,\n }))\n );\n }\n\n return { StacksheetProvider, useSheet, useStacksheetState, store };\n}\n","import type { SpringConfig } from \"./types\";\n\n/**\n * Spring presets inspired by iOS animation feel.\n *\n * - `subtle` — Barely noticeable bounce, professional.\n * - `snappy` — Quick, responsive for interactions.\n * - `stiff` — Very quick, controlled. Panels, drawers. **(default)**\n */\nexport const springs = {\n subtle: { stiffness: 300, damping: 30, mass: 1 },\n snappy: { stiffness: 400, damping: 28, mass: 0.8 },\n stiff: { stiffness: 400, damping: 40, mass: 1 },\n} as const satisfies Record<string, SpringConfig>;\n\nexport type SpringPreset = keyof typeof springs;\n","import type { SpringPreset } from \"./springs\";\nimport { springs } from \"./springs\";\nimport type {\n ResolvedConfig,\n ResponsiveSide,\n SideConfig,\n SpringConfig,\n StackingConfig,\n StacksheetConfig,\n} from \"./types\";\n\n// ── Defaults ────────────────────────────────────\n\nconst DEFAULT_STACKING: StackingConfig = {\n scaleStep: 0.04,\n offsetStep: 16,\n opacityStep: 0,\n radius: 12,\n renderThreshold: 3,\n};\n\nconst DEFAULT_SIDE: ResponsiveSide = {\n desktop: \"right\",\n mobile: \"bottom\",\n};\n\n// ── Helpers ─────────────────────────────────────\n\n/** Normalize a string side to a responsive object, merging with defaults. */\nfunction resolveSide(side: SideConfig | undefined): ResponsiveSide {\n if (typeof side === \"string\") {\n return { desktop: side, mobile: side };\n }\n return { ...DEFAULT_SIDE, ...side };\n}\n\n/** Resolve a preset name to a SpringConfig, or merge partial config with defaults. */\nfunction resolveSpring(\n spring: SpringPreset | Partial<SpringConfig> | undefined\n): SpringConfig {\n if (typeof spring === \"string\") {\n return springs[spring];\n }\n return { ...springs.stiff, ...spring };\n}\n\n// ── Resolver ────────────────────────────────────\n\n/** Merge user-provided config with defaults. Resolves union types (side, spring) to concrete values. */\nexport function resolveConfig(config: StacksheetConfig = {}): ResolvedConfig {\n return {\n maxDepth: config.maxDepth ?? Number.POSITIVE_INFINITY,\n closeOnEscape: config.closeOnEscape ?? true,\n closeOnBackdrop: config.closeOnBackdrop ?? true,\n showOverlay: config.showOverlay ?? true,\n lockScroll: config.lockScroll ?? true,\n width: config.width ?? 420,\n maxWidth: config.maxWidth ?? \"90vw\",\n breakpoint: config.breakpoint ?? 768,\n side: resolveSide(config.side),\n stacking: { ...DEFAULT_STACKING, ...config.stacking },\n spring: resolveSpring(config.spring),\n zIndex: config.zIndex ?? 100,\n ariaLabel: config.ariaLabel ?? \"Sheet dialog\",\n onOpenComplete: config.onOpenComplete,\n onCloseComplete: config.onCloseComplete,\n snapPoints: config.snapPoints ?? [],\n snapPointIndex: config.snapPointIndex,\n onSnapPointChange: config.onSnapPointChange,\n snapToSequentialPoints: config.snapToSequentialPoints ?? false,\n drag: config.drag ?? true,\n closeThreshold: config.closeThreshold ?? 0.25,\n velocityThreshold: config.velocityThreshold ?? 0.5,\n dismissible: config.dismissible ?? true,\n modal: config.modal ?? true,\n shouldScaleBackground: config.shouldScaleBackground ?? false,\n scaleBackgroundAmount: config.scaleBackgroundAmount ?? 0.97,\n };\n}\n","// CloseWatcher — ambient type for browsers that support it (Chromium 120+)\ndeclare global {\n var CloseWatcher:\n | (new () => { onclose: (() => void) | null; destroy: () => void })\n | undefined;\n}\n\nimport FocusTrap from \"focus-trap-react\";\nimport { AnimatePresence, motion as m, useReducedMotion } from \"motion/react\";\nimport {\n type ComponentType,\n type CSSProperties,\n memo,\n useCallback,\n useEffect,\n useMemo,\n useRef,\n useState,\n} from \"react\";\nimport { RemoveScroll } from \"react-remove-scroll\";\nimport type { StoreApi } from \"zustand\";\nimport { useStore } from \"zustand\";\nimport { ArrowLeftIcon, XIcon } from \"./icons\";\nimport { useResolvedSide } from \"./media\";\nimport { SheetPanelContext } from \"./panel-context\";\nimport { getSnapOffset, resolveSnapPoints } from \"./snap-points\";\nimport {\n getAnimatedBorderRadius,\n getPanelStyles,\n getSlideFrom,\n getSlideTarget,\n getStackOffset,\n getStackTransform,\n type SlideValues,\n} from \"./stacking\";\nimport type {\n CloseReason,\n ContentMap,\n HeaderRenderProps,\n ResolvedConfig,\n SheetActions,\n SheetItem,\n Side,\n StacksheetClassNames,\n StacksheetSnapshot,\n} from \"./types\";\nimport { type DragState, useDrag } from \"./use-drag\";\n\n// ── Default header ──────────────────────────────\n\nfunction DefaultHeader({\n isNested,\n onBack,\n onClose,\n className,\n}: HeaderRenderProps & { className?: string }) {\n return (\n <div\n className={`flex h-14 shrink-0 items-center justify-between border-b px-6 ${className ?? \"\"}`}\n >\n <div className=\"flex items-center gap-2\">\n {isNested && (\n <button\n aria-label=\"Back\"\n className=\"flex h-8 w-8 shrink-0 cursor-pointer items-center justify-center rounded-md border-none bg-transparent p-0 text-inherit opacity-60 transition-opacity duration-150 hover:opacity-100\"\n onClick={onBack}\n type=\"button\"\n >\n <ArrowLeftIcon />\n </button>\n )}\n </div>\n <button\n aria-label=\"Close\"\n className=\"flex h-8 w-8 shrink-0 cursor-pointer items-center justify-center rounded-md border-none bg-transparent p-0 text-inherit opacity-60 transition-opacity duration-150 hover:opacity-100\"\n onClick={onClose}\n type=\"button\"\n >\n <XIcon />\n </button>\n </div>\n );\n}\n\n// ── Resolved classNames ─────────────────────────\n\ntype ResolvedClassNames = Required<StacksheetClassNames>;\n\nconst EMPTY_CLASSNAMES: ResolvedClassNames = {\n backdrop: \"\",\n panel: \"\",\n header: \"\",\n};\n\nfunction resolveClassNames(cn?: StacksheetClassNames): ResolvedClassNames {\n if (!cn) {\n return EMPTY_CLASSNAMES;\n }\n return {\n backdrop: cn.backdrop ?? \"\",\n panel: cn.panel ?? \"\",\n header: cn.header ?? \"\",\n };\n}\n\n// ── Helpers ──────────────────────────────────────\n\nfunction buildAriaProps(\n isTop: boolean,\n isModal: boolean,\n isComposable: boolean,\n ariaLabel: string,\n panelId: string,\n hasDescription: boolean\n): Record<string, string | undefined> {\n if (!isTop) {\n return {};\n }\n const props: Record<string, string | undefined> = { role: \"dialog\" };\n if (isModal) {\n props[\"aria-modal\"] = \"true\";\n }\n if (isComposable) {\n props[\"aria-labelledby\"] = `${panelId}-title`;\n if (hasDescription) {\n props[\"aria-describedby\"] = `${panelId}-desc`;\n }\n } else {\n props[\"aria-label\"] = ariaLabel;\n }\n return props;\n}\n\nfunction getDragTransform(\n side: Side,\n offset: number\n): { x?: number; y?: number } {\n if (offset === 0) {\n return {};\n }\n switch (side) {\n case \"right\":\n return { x: offset };\n case \"left\":\n return { x: -offset };\n case \"bottom\":\n return { y: offset };\n default:\n return {};\n }\n}\n\n/** Shared tween config for non-spring animated properties (border radius, box shadow) */\nconst VISUAL_TWEEN = {\n type: \"tween\" as const,\n duration: 0.25,\n ease: \"easeOut\" as const,\n};\n\n// ── Panel helpers (extracted to reduce SheetPanel complexity) ──\n\n/** Measure panel height via ResizeObserver for snap point calculations */\nfunction usePanelHeight(\n panelRef: React.RefObject<HTMLDivElement | null>,\n hasSnapPoints: boolean\n): number {\n const [height, setHeight] = useState(0);\n\n useEffect(() => {\n const el = panelRef.current;\n if (!(el && hasSnapPoints)) {\n return;\n }\n setHeight(el.offsetHeight);\n const observer = new ResizeObserver(([entry]) => {\n if (entry) {\n setHeight(entry.contentRect.height);\n }\n });\n observer.observe(el);\n return () => observer.disconnect();\n }, [panelRef, hasSnapPoints]);\n\n return height;\n}\n\n/** Build the panel's inline style object */\nfunction buildPanelStyle(\n panelStyles: CSSProperties,\n isTop: boolean,\n hasPanelClass: boolean,\n isDragging: boolean\n): CSSProperties {\n return {\n ...panelStyles,\n pointerEvents: isTop ? \"auto\" : \"none\",\n ...(isTop ? {} : { contain: \"layout style paint\" }),\n ...(isDragging ? { transition: \"none\" } : {}),\n ...(hasPanelClass\n ? {}\n : {\n background: \"var(--background, #fff)\",\n borderColor: \"var(--border, transparent)\",\n }),\n };\n}\n\n/** Build per-property transition config */\nfunction buildPanelTransition(\n isDragging: boolean,\n isTop: boolean,\n spring: Record<string, unknown>,\n stackSpring: Record<string, unknown>\n) {\n if (isDragging) {\n return { type: \"tween\" as const, duration: 0 };\n }\n\n const base = isTop ? spring : stackSpring;\n return { ...base, borderRadius: VISUAL_TWEEN, boxShadow: VISUAL_TWEEN };\n}\n\n/** Compute the Y offset for the current snap point */\nfunction computeSnapYOffset(\n side: Side,\n snapHeights: number[],\n activeSnapIndex: number,\n measuredHeight: number\n): number {\n if (side !== \"bottom\" || snapHeights.length === 0 || measuredHeight <= 0) {\n return 0;\n }\n return getSnapOffset(activeSnapIndex, snapHeights, measuredHeight);\n}\n\nfunction getBottomSlideDistance(measuredHeight: number): number {\n if (measuredHeight > 0) {\n return measuredHeight;\n }\n if (typeof window !== \"undefined\") {\n return window.innerHeight;\n }\n return 1000;\n}\n\nfunction resolveSlideFrom(\n side: Side,\n slideFrom: SlideValues,\n measuredHeight: number\n): SlideValues {\n if (side !== \"bottom\") {\n return slideFrom;\n }\n return { y: getBottomSlideDistance(measuredHeight) };\n}\n\nfunction buildAnimateTarget(\n slideTarget: SlideValues,\n stackOffset: { x?: number; y?: number },\n dragOffset: { x?: number; y?: number },\n transform: ReturnType<typeof getStackTransform>,\n animatedRadius: Record<string, number>,\n transition: Record<string, unknown>,\n snapYOffset: number,\n isTop: boolean\n) {\n const base = {\n ...slideTarget,\n ...stackOffset,\n ...dragOffset,\n scale: transform.scale,\n opacity: transform.opacity,\n ...animatedRadius,\n boxShadow: getShadow(!isTop),\n transition,\n };\n\n if (snapYOffset > 0) {\n return { ...base, y: (dragOffset.y ?? 0) + snapYOffset };\n }\n return base;\n}\n\n// ── Modal focus trap wrapper ────────────────────\n\n/** Wraps children in a focus trap when modal mode is enabled. */\nfunction ModalFocusTrap({\n enabled,\n active,\n fallbackRef,\n children,\n}: {\n enabled: boolean;\n active: boolean;\n fallbackRef: React.RefObject<HTMLElement | null>;\n children: React.ReactNode;\n}) {\n if (!enabled) {\n return children;\n }\n return (\n <FocusTrap\n active={active}\n focusTrapOptions={{\n initialFocus: false,\n returnFocusOnDeactivate: true,\n escapeDeactivates: false,\n allowOutsideClick: true,\n checkCanFocusTrap: () =>\n new Promise<void>((resolve) =>\n requestAnimationFrame(() => resolve())\n ),\n fallbackFocus: () => {\n if (fallbackRef.current) {\n return fallbackRef.current;\n }\n return document.body;\n },\n }}\n >\n {children}\n </FocusTrap>\n );\n}\n\n// ── SheetPanel ──────────────────────────────────\n\ninterface SheetPanelProps {\n item: SheetItem;\n index: number;\n depth: number;\n isTop: boolean;\n isNested: boolean;\n side: Side;\n config: ResolvedConfig;\n classNames: ResolvedClassNames;\n // biome-ignore lint/suspicious/noExplicitAny: heterogeneous content component\n Content: ComponentType<any> | undefined;\n shouldRender: boolean;\n pop: () => void;\n close: () => void;\n /** Swipe-specific close — sets reason to \"swipe\" */\n swipeClose: () => void;\n /** Swipe-specific pop — sets reason to \"swipe\" */\n swipePop: () => void;\n /** Resolved snap point heights in px (ascending). Empty = no snaps. */\n snapHeights: number[];\n /** Currently active snap index */\n activeSnapIndex: number;\n /** Called when drag release targets a snap point */\n onSnap: (index: number) => void;\n renderHeader?: false | ((props: HeaderRenderProps) => React.ReactNode);\n slideFrom: SlideValues;\n slideTarget: SlideValues;\n spring: Record<string, unknown>;\n stackSpring: Record<string, unknown>;\n /** Whether the user prefers reduced motion */\n prefersReducedMotion: boolean;\n}\n\n/** Renders panel inner content — composable mode vs classic (header + scroll) */\nfunction PanelInnerContent({\n isComposable,\n shouldRender,\n Content,\n data,\n renderHeader,\n headerProps,\n headerClassName,\n}: {\n isComposable: boolean;\n shouldRender: boolean;\n // biome-ignore lint/suspicious/noExplicitAny: heterogeneous content component\n Content: ComponentType<any> | undefined;\n data: Record<string, unknown>;\n renderHeader?: false | ((props: HeaderRenderProps) => React.ReactNode);\n headerProps: HeaderRenderProps;\n headerClassName: string | undefined;\n}) {\n if (isComposable) {\n return shouldRender && Content ? <Content {...data} /> : null;\n }\n\n return (\n <>\n {renderHeader ? (\n renderHeader(headerProps)\n ) : (\n <DefaultHeader {...headerProps} className={headerClassName} />\n )}\n {shouldRender && Content && (\n <div\n className=\"min-h-0 flex-1 overflow-y-auto overscroll-contain\"\n data-stacksheet-no-drag=\"\"\n >\n <Content {...data} />\n </div>\n )}\n </>\n );\n}\n\n/** Built-in drag handle for bottom panels — always visible on the top sheet */\nfunction BottomHandle({ onDismiss }: { onDismiss?: () => void }) {\n return (\n <button\n aria-label=\"Dismiss\"\n className=\"absolute inset-x-0 top-0 z-10 flex w-full cursor-grab touch-none items-center justify-center border-none bg-transparent pt-2 pb-1\"\n data-stacksheet-handle=\"\"\n onClick={onDismiss}\n type=\"button\"\n >\n <div aria-hidden=\"true\" className=\"h-1 w-9 rounded-sm bg-current/25\" />\n </button>\n );\n}\n\n/** Floating drag handle for left/right side panels */\nfunction SideHandle({\n side,\n isHovered,\n onDismiss,\n}: {\n side: Side;\n isHovered: boolean;\n onDismiss?: () => void;\n}) {\n const position: CSSProperties =\n side === \"right\" ? { right: \"100%\" } : { left: \"100%\" };\n\n return (\n <m.div\n animate={{ opacity: isHovered ? 1 : 0 }}\n aria-label=\"Dismiss\"\n className=\"absolute top-0 bottom-0 flex w-6 cursor-grab touch-none items-center justify-center\"\n data-stacksheet-handle=\"\"\n onClick={onDismiss}\n onKeyDown={(e) => {\n if (e.key === \"Enter\" || e.key === \" \") {\n e.preventDefault();\n onDismiss?.();\n }\n }}\n role=\"button\"\n style={position}\n tabIndex={0}\n transition={{ duration: isHovered ? 0.15 : 0.4, ease: \"easeOut\" }}\n >\n <div\n aria-hidden=\"true\"\n className=\"h-10 w-[5px] rounded-sm bg-current/35 shadow-sm\"\n />\n </m.div>\n );\n}\n\nconst SheetPanel = memo(function SheetPanel({\n item,\n index,\n depth,\n isTop,\n isNested,\n side,\n config,\n classNames,\n Content,\n shouldRender,\n pop,\n close,\n swipeClose,\n swipePop,\n snapHeights,\n activeSnapIndex,\n onSnap,\n renderHeader,\n slideFrom,\n slideTarget,\n spring,\n stackSpring,\n prefersReducedMotion,\n}: SheetPanelProps) {\n const panelRef = useRef<HTMLDivElement>(null);\n const hasEnteredRef = useRef(false);\n const [dragState, setDragState] = useState<DragState>({\n offset: 0,\n isDragging: false,\n });\n const [isHovered, setIsHovered] = useState(false);\n\n const measuredHeight = usePanelHeight(panelRef, snapHeights.length > 0);\n\n const transform = getStackTransform(depth, config.stacking);\n const panelStyles = getPanelStyles(side, config, index);\n\n // Reset entrance flag when panel moves away from top\n useEffect(() => {\n if (!isTop) {\n hasEnteredRef.current = false;\n }\n }, [isTop]);\n\n const handleAnimationComplete = useCallback(() => {\n if (isTop && !hasEnteredRef.current) {\n hasEnteredRef.current = true;\n config.onOpenComplete?.();\n }\n }, [isTop, config]);\n\n // Drag-to-dismiss (only on top panel, disabled when reduced motion is preferred)\n useDrag(\n panelRef,\n {\n enabled:\n isTop && config.drag && config.dismissible && !prefersReducedMotion,\n closeThreshold: config.closeThreshold,\n velocityThreshold: config.velocityThreshold,\n side,\n onClose: swipeClose,\n onPop: swipePop,\n isNested,\n snapHeights,\n activeSnapIndex,\n onSnap,\n sequential: config.snapToSequentialPoints,\n },\n setDragState\n );\n\n // Per-sheet aria-label: check data.__ariaLabel, fall back to config\n const ariaLabel =\n (typeof item.data?.__ariaLabel === \"string\"\n ? item.data.__ariaLabel\n : undefined) ?? config.ariaLabel;\n\n // Panel context for composable parts (Sheet.Close, Sheet.Title, etc.)\n const panelId = `stacksheet-${item.id}`;\n const [hasDescription, setHasDescription] = useState(false);\n const registerDescription = useCallback(() => {\n setHasDescription(true);\n return () => setHasDescription(false);\n }, []);\n const panelContext = useMemo(\n () => ({\n close,\n back: pop,\n isNested,\n isTop,\n panelId,\n side,\n hasDescription,\n registerDescription,\n }),\n [\n close,\n pop,\n isNested,\n isTop,\n panelId,\n side,\n hasDescription,\n registerDescription,\n ]\n );\n\n const isComposable = renderHeader === false;\n const hasPanelClass = classNames.panel !== \"\";\n const dragOffset = getDragTransform(side, dragState.offset);\n const panelStyle = buildPanelStyle(\n panelStyles,\n isTop,\n hasPanelClass,\n dragState.isDragging\n );\n\n const headerProps: HeaderRenderProps = {\n isNested,\n onBack: pop,\n onClose: close,\n side,\n };\n\n const ariaProps = buildAriaProps(\n isTop,\n config.modal,\n isComposable,\n ariaLabel,\n panelId,\n hasDescription\n );\n\n const transition = buildPanelTransition(\n dragState.isDragging,\n isTop,\n spring,\n stackSpring\n );\n\n const animatedRadius = getAnimatedBorderRadius(side, depth, config.stacking);\n const snapYOffset = computeSnapYOffset(\n side,\n snapHeights,\n activeSnapIndex,\n measuredHeight\n );\n const resolvedSlideFrom = resolveSlideFrom(side, slideFrom, measuredHeight);\n\n // Merge stack offset + drag offset + snap offset into the animate target.\n const stackOffset = getStackOffset(side, transform.offset);\n const animateTarget = buildAnimateTarget(\n slideTarget,\n stackOffset,\n dragOffset,\n transform,\n animatedRadius,\n transition,\n snapYOffset,\n isTop\n );\n\n const initialRadius = getInitialRadius(side);\n const showSideHandle = isTop && side !== \"bottom\";\n const showBottomHandle = isTop && side === \"bottom\";\n\n const panelContent = (\n <m.div\n animate={animateTarget}\n className={classNames.panel || undefined}\n exit={{\n ...resolvedSlideFrom,\n opacity: 0.6,\n boxShadow: getShadow(false),\n transition: {\n type: \"tween\",\n duration: prefersReducedMotion ? 0 : 0.24,\n ease: \"easeOut\",\n boxShadow: VISUAL_TWEEN,\n },\n }}\n initial={{\n ...resolvedSlideFrom,\n opacity: 0.8,\n ...initialRadius,\n boxShadow: getShadow(false),\n }}\n key={item.id}\n onAnimationComplete={handleAnimationComplete}\n onBlur={showSideHandle ? () => setIsHovered(false) : undefined}\n onFocus={showSideHandle ? () => setIsHovered(true) : undefined}\n onMouseEnter={showSideHandle ? () => setIsHovered(true) : undefined}\n onMouseLeave={showSideHandle ? () => setIsHovered(false) : undefined}\n ref={panelRef}\n style={panelStyle}\n tabIndex={isTop ? -1 : undefined}\n {...(isTop ? {} : { \"aria-hidden\": \"true\" as const, inert: true })}\n {...ariaProps}\n >\n {showSideHandle && (\n <SideHandle\n isHovered={isHovered}\n onDismiss={isNested ? pop : close}\n side={side}\n />\n )}\n <div className=\"relative flex min-h-0 flex-1 flex-col overflow-hidden rounded-[inherit]\">\n {showBottomHandle && (\n <BottomHandle onDismiss={isNested ? pop : close} />\n )}\n <PanelInnerContent\n Content={Content}\n data={item.data as Record<string, unknown>}\n headerClassName={classNames.header || undefined}\n headerProps={headerProps}\n isComposable={isComposable}\n renderHeader={renderHeader}\n shouldRender={shouldRender}\n />\n </div>\n </m.div>\n );\n\n return (\n <SheetPanelContext.Provider value={panelContext}>\n <ModalFocusTrap\n active={isTop}\n enabled={config.modal}\n fallbackRef={panelRef}\n >\n {panelContent}\n </ModalFocusTrap>\n </SheetPanelContext.Provider>\n );\n});\n\n// ── Body scale effect ───────────────────────────\n\nfunction useBodyScale(\n config: ResolvedConfig,\n isOpen: boolean,\n prefersReducedMotion: boolean\n) {\n useEffect(() => {\n if (!config.shouldScaleBackground || prefersReducedMotion) {\n return;\n }\n\n const wrapper = document.querySelector(\"[data-stacksheet-wrapper]\");\n if (!(wrapper && wrapper instanceof HTMLElement)) {\n return;\n }\n\n if (isOpen) {\n const scale = config.scaleBackgroundAmount;\n wrapper.style.transition =\n \"transform 500ms cubic-bezier(0.32, 0.72, 0, 1), border-radius 500ms cubic-bezier(0.32, 0.72, 0, 1)\";\n wrapper.style.transform = `scale(${scale})`;\n wrapper.style.borderRadius = \"8px\";\n wrapper.style.overflow = \"hidden\";\n wrapper.style.transformOrigin = \"center top\";\n return;\n }\n\n wrapper.style.transform = \"\";\n wrapper.style.borderRadius = \"\";\n // Clean up after transition completes\n const handleEnd = () => {\n wrapper.style.transition = \"\";\n wrapper.style.overflow = \"\";\n wrapper.style.transformOrigin = \"\";\n };\n wrapper.addEventListener(\"transitionend\", handleEnd, { once: true });\n return () => wrapper.removeEventListener(\"transitionend\", handleEnd);\n }, [\n isOpen,\n config.shouldScaleBackground,\n config.scaleBackgroundAmount,\n prefersReducedMotion,\n ]);\n}\n\n// ── Renderer ────────────────────────────────────\n\ninterface SheetRendererProps<TMap extends object> {\n store: StoreApi<StacksheetSnapshot<TMap> & SheetActions<TMap>>;\n config: ResolvedConfig;\n sheets: ContentMap<TMap>;\n /** Ad-hoc component map (type key → component) */\n // biome-ignore lint/suspicious/noExplicitAny: heterogeneous component storage\n componentMap: Map<string, ComponentType<any>>;\n classNames?: StacksheetClassNames;\n renderHeader?: false | ((props: HeaderRenderProps) => React.ReactNode);\n}\n\n/**\n * Root renderer component — manages the backdrop, scroll lock, snap points,\n * close reasons, focus restoration, keyboard/CloseWatcher dismissal, and\n * delegates per-panel rendering to `SheetPanel`.\n *\n * Mounted inside a Portal by `StacksheetProvider`.\n */\nexport function SheetRenderer<TMap extends object>({\n store,\n config,\n sheets,\n componentMap,\n classNames: classNamesProp,\n renderHeader,\n}: SheetRendererProps<TMap>) {\n const isOpen = useStore(store, (s) => s.isOpen);\n const stack = useStore(store, (s) => s.stack);\n const rawClose = useStore(store, (s) => s.close);\n const rawPop = useStore(store, (s) => s.pop);\n\n const side = useResolvedSide(config);\n const prefersReducedMotion = useReducedMotion() ?? false;\n const classNames = useMemo(\n () => resolveClassNames(classNamesProp),\n [classNamesProp]\n );\n\n // ── Snap points ──────────────────────────────\n const snapHeights = useMemo(\n () =>\n side === \"bottom\" && config.snapPoints.length > 0\n ? resolveSnapPoints(\n config.snapPoints,\n typeof window !== \"undefined\" ? window.innerHeight : 0\n )\n : [],\n [side, config.snapPoints]\n );\n\n // Default to the last snap point (fully open) when snap points are defined\n const [internalSnapIndex, setInternalSnapIndex] = useState(\n snapHeights.length > 0 ? snapHeights.length - 1 : 0\n );\n\n // Controlled vs uncontrolled snap index\n const activeSnapIndex = config.snapPointIndex ?? internalSnapIndex;\n\n const handleSnap = useCallback(\n (index: number) => {\n setInternalSnapIndex(index);\n config.onSnapPointChange?.(index);\n },\n [config.onSnapPointChange, config]\n );\n\n // Reset snap index when stack opens (start at initial snap point or fully open)\n useEffect(() => {\n if (isOpen && snapHeights.length > 0) {\n const initial = config.snapPointIndex ?? snapHeights.length - 1;\n setInternalSnapIndex(initial);\n }\n }, [isOpen, snapHeights.length, config.snapPointIndex]);\n\n // Track why the sheet was closed — ref survives until exit animation completes\n const closeReasonRef = useRef<CloseReason>(\"programmatic\");\n\n const closeWith = useCallback(\n (reason: CloseReason) => {\n closeReasonRef.current = reason;\n rawClose();\n },\n [rawClose]\n );\n\n const popWith = useCallback(\n (reason: CloseReason) => {\n closeReasonRef.current = reason;\n rawPop();\n },\n [rawPop]\n );\n\n // Default close/pop (programmatic) for child components\n const close = useCallback(() => closeWith(\"programmatic\"), [closeWith]);\n const pop = useCallback(() => popWith(\"programmatic\"), [popWith]);\n\n // Body scale effect\n useBodyScale(config, isOpen, prefersReducedMotion);\n\n // Focus restoration: capture the element that was focused when the stack opens.\n // When the stack fully closes, return focus to that element.\n const triggerRef = useRef<Element | null>(null);\n const wasOpenRef = useRef(false);\n\n useEffect(() => {\n if (isOpen && !wasOpenRef.current) {\n triggerRef.current = document.activeElement;\n } else if (!isOpen && wasOpenRef.current) {\n const el = triggerRef.current;\n // Only restore focus to meaningful elements — skip document.body\n // which happens when sheets are opened programmatically.\n if (\n el &&\n el instanceof HTMLElement &&\n el !== document.body &&\n el.tagName !== \"BODY\"\n ) {\n el.focus();\n }\n triggerRef.current = null;\n }\n wasOpenRef.current = isOpen;\n }, [isOpen]);\n\n // Ref for stack length — avoids re-subscribing keyboard/CloseWatcher\n // effects on every push/pop.\n const stackLengthRef = useRef(stack.length);\n useEffect(() => {\n stackLengthRef.current = stack.length;\n }, [stack.length]);\n\n // Escape key\n useEffect(() => {\n if (!(isOpen && config.closeOnEscape && config.dismissible)) {\n return;\n }\n\n function handleKeyDown(e: KeyboardEvent) {\n if (e.key === \"Escape\") {\n e.preventDefault();\n if (stackLengthRef.current > 1) {\n popWith(\"escape\");\n } else {\n closeWith(\"escape\");\n }\n }\n }\n\n document.addEventListener(\"keydown\", handleKeyDown);\n return () => document.removeEventListener(\"keydown\", handleKeyDown);\n }, [isOpen, config.closeOnEscape, config.dismissible, popWith, closeWith]);\n\n // CloseWatcher — handles Android back gesture (progressive enhancement).\n // On browsers without support (Safari, Firefox), this is a no-op.\n useEffect(() => {\n if (\n !(isOpen && config.dismissible) ||\n typeof globalThis.CloseWatcher === \"undefined\"\n ) {\n return;\n }\n\n const watcher = new globalThis.CloseWatcher();\n watcher.onclose = () => {\n if (stackLengthRef.current > 1) {\n popWith(\"escape\");\n } else {\n closeWith(\"escape\");\n }\n };\n\n return () => watcher.destroy();\n }, [isOpen, config.dismissible, popWith, closeWith]);\n\n const slideFrom = useMemo(() => getSlideFrom(side), [side]);\n const slideTarget = useMemo(() => getSlideTarget(), []);\n\n // Primary spring — drives the top sheet's entrance slide.\n // When reduced motion is preferred, use instant transitions.\n const spring = useMemo(\n () =>\n prefersReducedMotion\n ? ({ type: \"tween\" as const, duration: 0 } as const)\n : ({\n type: \"spring\" as const,\n damping: config.spring.damping,\n stiffness: config.spring.stiffness,\n mass: config.spring.mass,\n } as const),\n [\n prefersReducedMotion,\n config.spring.damping,\n config.spring.stiffness,\n config.spring.mass,\n ]\n );\n\n // Same spring for stacking transforms\n const stackSpring = spring;\n\n // Non-modal: skip overlay, skip scroll lock\n const isModal = config.modal;\n const showOverlay = isModal && config.showOverlay;\n\n // Backdrop: use className if provided, otherwise inline fallback.\n // will-change hints the compositor to properly manage the layer lifecycle.\n const hasBackdropClass = classNames.backdrop !== \"\";\n const backdropStyle: CSSProperties = {\n zIndex: config.zIndex,\n willChange: \"opacity\",\n cursor:\n config.closeOnBackdrop && config.dismissible ? \"pointer\" : undefined,\n ...(hasBackdropClass\n ? {}\n : { background: \"var(--overlay, rgba(0, 0, 0, 0.2))\" }),\n };\n\n // Handle exit complete — fire onCloseComplete when stack is fully empty\n const handleExitComplete = useCallback(() => {\n if (stack.length === 0) {\n config.onCloseComplete?.(closeReasonRef.current);\n }\n }, [stack.length, config]);\n\n // Force WebKit repaint after backdrop exit animation completes.\n // iOS Safari's compositor can retain the visual layer of a fixed-position\n // element after it's removed from the DOM, leaving a ghost tint.\n // A layout recalc via offsetHeight forces the compositor to invalidate\n // stale layers without affecting element positioning.\n const handleBackdropExitComplete = useCallback(() => {\n requestAnimationFrame(() => {\n // Read offsetHeight to force a layout recalc — the value itself is unused.\n // biome-ignore lint/complexity/noVoid: intentional layout recalc for WebKit\n void document.body.offsetHeight;\n });\n }, []);\n\n // Swipe-specific dismiss callbacks\n const swipeClose = useCallback(() => closeWith(\"swipe\"), [closeWith]);\n const swipePop = useCallback(() => popWith(\"swipe\"), [popWith]);\n\n // Non-modal: don't lock scroll\n const shouldLockScroll = isOpen && isModal && config.lockScroll;\n\n return (\n <>\n {/* Backdrop — independent AnimatePresence so it fades on its own.\n onExitComplete forces a WebKit repaint to clear stale compositor layers (iOS Safari). */}\n {showOverlay && (\n <AnimatePresence onExitComplete={handleBackdropExitComplete}>\n {isOpen && (\n <m.div\n animate={{ opacity: 1 }}\n className={`fixed inset-0 ${classNames.backdrop || \"\"}`}\n exit={{ opacity: 0 }}\n initial={{ opacity: 0 }}\n key=\"stacksheet-backdrop\"\n onClick={\n config.closeOnBackdrop && config.dismissible\n ? () => closeWith(\"backdrop\")\n : undefined\n }\n style={backdropStyle}\n transition={spring}\n />\n )}\n </AnimatePresence>\n )}\n\n {/* Panel clip container — always rendered, invisible when empty */}\n <RemoveScroll enabled={shouldLockScroll} forwardProps>\n <div\n className=\"pointer-events-none fixed inset-0 overflow-hidden\"\n style={{ zIndex: config.zIndex + 1 }}\n >\n <AnimatePresence onExitComplete={handleExitComplete}>\n {stack.map((item, index) => {\n const depth = stack.length - 1 - index;\n const isTop = depth === 0;\n const isNested = index > 0;\n // Keep one extra hidden panel mounted as a warm buffer.\n // Without this, popping from deep stacks can mount content on the\n // same frame it becomes visible, which can cause a reverse jank.\n const shouldRender = depth <= config.stacking.renderThreshold;\n\n // Ad-hoc components take priority, then fall back to sheets map\n const Content = (componentMap.get(item.type) ??\n sheets[item.type as keyof TMap]) as\n | ComponentType<Record<string, unknown>>\n | undefined;\n\n return (\n <SheetPanel\n activeSnapIndex={activeSnapIndex}\n Content={Content}\n classNames={classNames}\n close={close}\n config={config}\n depth={depth}\n index={index}\n isNested={isNested}\n isTop={isTop}\n item={item}\n key={item.id}\n onSnap={handleSnap}\n pop={pop}\n prefersReducedMotion={prefersReducedMotion}\n renderHeader={renderHeader}\n shouldRender={shouldRender}\n side={side}\n slideFrom={slideFrom}\n slideTarget={slideTarget}\n snapHeights={snapHeights}\n spring={spring}\n stackSpring={stackSpring}\n swipeClose={swipeClose}\n swipePop={swipePop}\n />\n );\n })}\n </AnimatePresence>\n </div>\n </RemoveScroll>\n </>\n );\n}\n\n// ── Helpers ─────────────────────────────────────\n\nfunction getInitialRadius(side: Side): Record<string, number> {\n if (side === \"bottom\") {\n return {\n borderTopLeftRadius: 0,\n borderTopRightRadius: 0,\n borderBottomLeftRadius: 0,\n borderBottomRightRadius: 0,\n };\n }\n return { borderRadius: 0 };\n}\n\n// Collins-style layered shadows — soft, diffused, multi-stop.\nconst SHADOW_SM =\n \"0px 2px 5px 0px rgba(0,0,0,0.11), 0px 9px 9px 0px rgba(0,0,0,0.1), 0px 21px 13px 0px rgba(0,0,0,0.06)\";\nconst SHADOW_LG =\n \"0px 23px 52px 0px rgba(0,0,0,0.08), 0px 94px 94px 0px rgba(0,0,0,0.07), 0px 211px 127px 0px rgba(0,0,0,0.04)\";\n\nfunction getShadow(isNested: boolean): string {\n return isNested ? SHADOW_SM : SHADOW_LG;\n}\n","/** Inline SVG icons — no external dependency */\n\nexport function ArrowLeftIcon() {\n return (\n <svg\n aria-hidden=\"true\"\n fill=\"none\"\n height={16}\n stroke=\"currentColor\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n viewBox=\"0 0 24 24\"\n width={16}\n >\n <path d=\"M19 12H5M12 19l-7-7 7-7\" />\n </svg>\n );\n}\n\nexport function XIcon() {\n return (\n <svg\n aria-hidden=\"true\"\n fill=\"none\"\n height={16}\n stroke=\"currentColor\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n viewBox=\"0 0 24 24\"\n width={16}\n >\n <path d=\"M18 6L6 18M6 6l12 12\" />\n </svg>\n );\n}\n","import { useEffect, useState } from \"react\";\nimport type { ResolvedConfig, Side } from \"./types\";\n\n/**\n * Returns true when viewport width is at or below the breakpoint.\n * SSR-safe: defaults to false (desktop).\n */\nexport function useIsMobile(breakpoint: number): boolean {\n const [isMobile, setIsMobile] = useState(false);\n\n useEffect(() => {\n const mql = window.matchMedia(`(max-width: ${breakpoint - 1}px)`);\n setIsMobile(mql.matches);\n\n const handler = (e: MediaQueryListEvent) => setIsMobile(e.matches);\n mql.addEventListener(\"change\", handler);\n return () => mql.removeEventListener(\"change\", handler);\n }, [breakpoint]);\n\n return isMobile;\n}\n\n/** Resolve the current side from config + viewport. */\nexport function useResolvedSide(config: ResolvedConfig): Side {\n const isMobile = useIsMobile(config.breakpoint);\n return isMobile ? config.side.mobile : config.side.desktop;\n}\n","import { createContext, useContext } from \"react\";\nimport type { Side } from \"./types\";\n\nexport interface SheetPanelContextValue {\n /** Close the entire sheet stack */\n close: () => void;\n /** Pop the top sheet (go back one level) */\n back: () => void;\n /** Whether the stack has more than one sheet */\n isNested: boolean;\n /** Whether this is the top (active) sheet */\n isTop: boolean;\n /** Unique ID prefix for this panel (for aria-labelledby linking) */\n panelId: string;\n /** Current resolved side (left/right/bottom) */\n side: Side;\n /** Whether a Sheet.Description is mounted inside this panel */\n hasDescription: boolean;\n /** Called by Sheet.Description on mount to register its presence */\n registerDescription: () => () => void;\n}\n\nexport const SheetPanelContext = createContext<SheetPanelContextValue | null>(\n null\n);\n\n/**\n * Access the current sheet panel's context.\n * Must be called inside a component rendered by the sheet stack.\n */\nexport function useSheetPanel(): SheetPanelContextValue {\n const ctx = useContext(SheetPanelContext);\n if (!ctx) {\n throw new Error(\n \"Sheet.* components must be used inside a sheet panel. \" +\n \"They should be rendered by a component opened via actions.open(), push(), etc.\"\n );\n }\n return ctx;\n}\n","import type { SnapPoint } from \"./types\";\n\nconst SNAP_POINT_RE = /^(\\d+(?:\\.\\d+)?)(px|rem|em|vh|%)$/;\n\n/**\n * Resolve a snap point value to pixels given the viewport height.\n * - number 0-1: fraction of viewport (0.5 → 50% of vh)\n * - number > 1: pixel value (300 → 300px)\n * - string: parsed via regex for CSS unit support\n */\nfunction resolveSnapPointPx(point: SnapPoint, viewportHeight: number): number {\n if (typeof point === \"number\") {\n return point <= 1 ? point * viewportHeight : point;\n }\n\n if (typeof point === \"string\") {\n const match = point.match(SNAP_POINT_RE);\n if (!match?.[1]) {\n return 0;\n }\n const value = Number.parseFloat(match[1]);\n const unit = match[2];\n switch (unit) {\n case \"px\":\n return value;\n case \"rem\":\n case \"em\": {\n const fontSize =\n typeof document !== \"undefined\"\n ? Number.parseFloat(\n getComputedStyle(document.documentElement).fontSize\n )\n : 16;\n return value * fontSize;\n }\n case \"vh\":\n case \"%\":\n return (value / 100) * viewportHeight;\n default:\n return 0;\n }\n }\n\n return 0;\n}\n\n/**\n * Resolve all snap points to sorted pixel heights (ascending).\n * Returns an array of heights in px that the drawer should snap to.\n */\nexport function resolveSnapPoints(\n points: SnapPoint[],\n viewportHeight: number\n): number[] {\n if (points.length === 0) {\n return [];\n }\n\n const resolved = points\n .map((p) => resolveSnapPointPx(p, viewportHeight))\n .filter((px) => px > 0);\n\n // Sort ascending (smallest snap point first)\n resolved.sort((a, b) => a - b);\n\n // Deduplicate (1px tolerance)\n const deduped: number[] = [];\n for (const px of resolved) {\n const last = deduped.at(-1);\n if (last === undefined || Math.abs(px - last) > 1) {\n deduped.push(px);\n }\n }\n\n return deduped;\n}\n\n/** Velocity threshold (px/ms) for skipping intermediate snap points */\nconst SNAP_VELOCITY_THRESHOLD = 0.4;\n\n/** Max velocity to consider for snap offset calculation */\nconst MAX_SNAP_VELOCITY = 2;\n\n/** Multiplier to convert velocity to pixel offset for snap target */\nconst SNAP_VELOCITY_MULTIPLIER = 150;\n\n/**\n * Given the current drag offset (from fully open), resolved snap heights,\n * the panel height, and release velocity, find the best snap point index.\n *\n * `dragOffset` is positive in the dismiss direction (downward for bottom sheets).\n * Snap heights are \"how tall the drawer should be\" (ascending order).\n *\n * Returns -1 if the gesture indicates full dismissal.\n */\nexport function findSnapTarget(\n dragOffset: number,\n panelHeight: number,\n snapHeights: number[],\n velocity: number,\n currentIndex: number,\n sequential: boolean\n): number {\n if (snapHeights.length === 0) {\n return -1;\n }\n\n // Convert snap heights to offsets from fully open (panelHeight = 0 offset)\n // A smaller snap height = larger offset from top = more closed\n const snapOffsets = snapHeights.map((h) => panelHeight - h);\n\n // Current position = dragOffset from fully open\n const currentPos = dragOffset;\n\n if (sequential) {\n // Sequential mode: only snap to adjacent points\n const direction = velocity > 0 ? 1 : -1; // positive = dismissing\n const nextIndex = currentIndex - direction; // snap heights are ascending, so -1 = more closed\n if (nextIndex < 0) {\n return -1; // dismiss\n }\n if (nextIndex >= snapHeights.length) {\n return snapHeights.length - 1; // fully open\n }\n return nextIndex;\n }\n\n // Velocity-based: project position forward based on velocity\n const velocityOffset =\n Math.abs(velocity) >= SNAP_VELOCITY_THRESHOLD\n ? Math.min(Math.max(velocity, -MAX_SNAP_VELOCITY), MAX_SNAP_VELOCITY) *\n SNAP_VELOCITY_MULTIPLIER\n : 0;\n\n const projectedPos = currentPos + velocityOffset;\n\n // Find nearest snap offset to projected position\n const first = snapOffsets[0] ?? 0;\n let bestIndex = 0;\n let bestDist = Math.abs(projectedPos - first);\n\n for (let i = 1; i < snapOffsets.length; i++) {\n const offset = snapOffsets[i] ?? 0;\n const dist = Math.abs(projectedPos - offset);\n if (dist < bestDist) {\n bestDist = dist;\n bestIndex = i;\n }\n }\n\n // Check if dismissal is closer than (or equal to) any snap point.\n // Ties favor dismiss — the user dragged past the last snap point.\n const dismissDist = Math.abs(projectedPos - panelHeight);\n if (dismissDist <= bestDist) {\n return -1;\n }\n\n return bestIndex;\n}\n\n/**\n * Get the Y offset for a snap point relative to fully open (0 offset).\n * Returns the number of pixels the drawer should be translated down from fully open.\n */\nexport function getSnapOffset(\n snapIndex: number,\n snapHeights: number[],\n panelHeight: number\n): number {\n if (snapIndex < 0 || snapIndex >= snapHeights.length) {\n return 0;\n }\n const targetHeight = snapHeights[snapIndex] ?? 0;\n return panelHeight - targetHeight;\n}\n","import type { CSSProperties } from \"react\";\nimport type { ResolvedConfig, Side, StackingConfig } from \"./types\";\n\n// ── Depth transforms ────────────────────────────\n\nexport interface StackTransform {\n scale: number;\n offset: number;\n opacity: number;\n borderRadius: number;\n}\n\n/**\n * Compute visual transforms for a panel at a given depth.\n * depth=0 is the top (foreground) panel.\n * Panels beyond renderThreshold are clamped to the edge position and faded out.\n */\nexport function getStackTransform(\n depth: number,\n stacking: StackingConfig\n): StackTransform {\n if (depth <= 0) {\n return { scale: 1, offset: 0, opacity: 1, borderRadius: 0 };\n }\n\n const beyondThreshold = depth >= stacking.renderThreshold;\n // Clamp visual depth so panels beyond threshold stay at the edge position\n const visualDepth = beyondThreshold ? stacking.renderThreshold - 1 : depth;\n\n return {\n scale: Math.max(0.5, 1 - visualDepth * stacking.scaleStep),\n offset: visualDepth * stacking.offsetStep,\n opacity: beyondThreshold\n ? 0\n : Math.max(0, 1 - visualDepth * stacking.opacityStep),\n borderRadius: stacking.radius,\n };\n}\n\n/**\n * Border radius values for the animate target.\n * Must be animated (not static CSS) so Motion applies scale correction\n * when panels are scaled. See: https://motion.dev/docs/react-layout-animations#scale-correction\n */\nexport function getAnimatedBorderRadius(\n side: Side,\n depth: number,\n stacking: StackingConfig\n): Record<string, number> {\n if (side === \"bottom\") {\n const radius = depth > 0 ? stacking.radius : 16;\n return {\n borderTopLeftRadius: radius,\n borderTopRightRadius: radius,\n borderBottomLeftRadius: 0,\n borderBottomRightRadius: 0,\n };\n }\n\n // Left/right panels: stacked panels get uniform radius, top panel gets none\n if (depth > 0) {\n return { borderRadius: stacking.radius };\n }\n return { borderRadius: 0 };\n}\n\n// ── Slide directions ────────────────────────────\n\nexport interface SlideValues {\n x?: string | number;\n y?: string | number;\n}\n\n/** Motion initial/exit values for sliding from the given side. */\nexport function getSlideFrom(side: Side): SlideValues {\n switch (side) {\n case \"right\":\n return { x: \"100%\" };\n case \"left\":\n return { x: \"-100%\" };\n case \"bottom\":\n return { y: \"100%\" };\n default:\n return { x: \"100%\" };\n }\n}\n\n/** Motion animate target — the resting position. */\nexport function getSlideTarget(): SlideValues {\n return { x: 0, y: 0 };\n}\n\n/** Translate offset that pushes stacked panels away from the stack edge. */\nexport function getStackOffset(\n side: Side,\n offset: number\n): { x?: number; y?: number } {\n if (offset === 0) {\n return {};\n }\n switch (side) {\n case \"right\":\n return { x: -offset };\n case \"left\":\n return { x: offset };\n case \"bottom\":\n return { y: -offset };\n default:\n return {};\n }\n}\n\n// ── Transform origin ────────────────────────────\n\n/** Opposite-side origin so stacked panels recede away from the stack edge. */\nfunction getTransformOrigin(side: Side): string {\n if (side === \"right\") {\n return \"left center\";\n }\n if (side === \"left\") {\n return \"right center\";\n }\n return \"center top\";\n}\n\n// ── Panel positioning ───────────────────────────\n\n/**\n * Fixed-position styles for a panel, accounting for side, width, and depth.\n */\nexport function getPanelStyles(\n side: Side,\n config: ResolvedConfig,\n index: number\n): CSSProperties {\n const { width, maxWidth, zIndex } = config;\n const base: CSSProperties = {\n position: \"fixed\",\n zIndex: zIndex + 10 + index,\n display: \"flex\",\n flexDirection: \"column\",\n willChange: \"transform\",\n transformOrigin: getTransformOrigin(side),\n };\n\n if (side === \"bottom\") {\n return {\n ...base,\n left: 0,\n right: 0,\n bottom: 0,\n // dvh tracks the dynamic viewport on iOS Safari (accounts for browser chrome).\n // The vh fallback covers browsers that don't support dvh yet.\n maxHeight: \"85dvh\",\n // borderRadius is animated via Motion's animate prop for scale correction\n };\n }\n\n // Left or right side panel\n const sideStyles: CSSProperties =\n side === \"right\"\n ? { top: 0, right: 0, bottom: 0 }\n : { top: 0, left: 0, bottom: 0 };\n\n return {\n ...base,\n ...sideStyles,\n width,\n maxWidth,\n };\n}\n","import { type RefObject, useCallback, useEffect, useRef } from \"react\";\nimport { findSnapTarget } from \"./snap-points\";\nimport type { Side } from \"./types\";\n\nexport interface DragConfig {\n /** Enable drag-to-dismiss. Default: true */\n enabled: boolean;\n /** Fraction of panel dimension to trigger close (0-1). Default: 0.25 */\n closeThreshold: number;\n /** Velocity threshold (px/ms) to trigger close. Default: 0.5 */\n velocityThreshold: number;\n /** Side the panel is on — determines drag direction */\n side: Side;\n /** Callback when drag ends and close should fire */\n onClose: () => void;\n /** Callback when drag ends and pop should fire */\n onPop: () => void;\n /** Whether the stack has >1 sheet (swipe pops instead of closing) */\n isNested: boolean;\n /** Resolved snap point heights in px (sorted ascending). Empty = no snap points. */\n snapHeights: number[];\n /** Current active snap point index */\n activeSnapIndex: number;\n /** Called when snap target changes on release */\n onSnap: (index: number) => void;\n /** When true, can't skip intermediate snap points */\n sequential: boolean;\n}\n\nexport interface DragState {\n /** Current drag offset in the dismiss direction (px) */\n offset: number;\n /** Whether a drag is currently active */\n isDragging: boolean;\n}\n\n/** Elements that should never initiate a drag */\nconst INTERACTIVE_TAGS = new Set([\n \"INPUT\",\n \"TEXTAREA\",\n \"SELECT\",\n \"BUTTON\",\n \"A\",\n]);\n\nfunction isInteractiveElement(el: Element): boolean {\n if (INTERACTIVE_TAGS.has(el.tagName)) {\n return true;\n }\n if ((el as HTMLElement).isContentEditable) {\n return true;\n }\n // Children of interactive elements (e.g. SVG inside button, span inside link)\n if (el.closest(\"button, a, input, textarea, select, [contenteditable]\")) {\n return true;\n }\n if (el.closest(\"[data-stacksheet-no-drag]\")) {\n return true;\n }\n return false;\n}\n\n/**\n * Walk up from `el` to find the nearest scrollable ancestor.\n * Returns null if nothing is scrollable in the dismiss axis.\n */\nfunction findScrollableAncestor(el: Element, axis: \"x\" | \"y\"): Element | null {\n let current: Element | null = el;\n while (current) {\n if (current instanceof HTMLElement) {\n const style = getComputedStyle(current);\n const overflow = axis === \"y\" ? style.overflowY : style.overflowX;\n if (overflow === \"auto\" || overflow === \"scroll\") {\n const scrollable =\n axis === \"y\"\n ? current.scrollHeight > current.clientHeight\n : current.scrollWidth > current.clientWidth;\n if (scrollable) {\n return current;\n }\n }\n }\n current = current.parentElement;\n }\n return null;\n}\n\n/**\n * Check if a scrollable element is at its edge in the dismiss direction.\n * For bottom sheets (sign=1, axis=y), \"at edge\" means scrolled to top.\n * For left panels (sign=-1, axis=x), \"at edge\" means scrolled to right end.\n */\nfunction isAtScrollEdge(el: Element, axis: \"x\" | \"y\", sign: 1 | -1): boolean {\n if (axis === \"y\") {\n // Dismiss down (sign=1): at edge when scrollTop ≈ 0\n // Dismiss up (sign=-1): at edge when scrolled to bottom\n return sign === 1\n ? el.scrollTop <= 0\n : el.scrollTop + el.clientHeight >= el.scrollHeight - 1;\n }\n return sign === 1\n ? el.scrollLeft <= 0\n : el.scrollLeft + el.clientWidth >= el.scrollWidth - 1;\n}\n\n/**\n * Get the dismiss direction axis and sign for a given side.\n * - right panel → dismiss by dragging right (+x)\n * - left panel → dismiss by dragging left (-x)\n * - bottom panel → dismiss by dragging down (+y)\n */\nfunction getDismissAxis(side: Side): {\n axis: \"x\" | \"y\";\n sign: 1 | -1;\n} {\n switch (side) {\n case \"right\":\n return { axis: \"x\", sign: 1 };\n case \"left\":\n return { axis: \"x\", sign: -1 };\n case \"bottom\":\n return { axis: \"y\", sign: 1 };\n default:\n return { axis: \"x\", sign: 1 };\n }\n}\n\n/** Dead zone in px before committing to drag vs text selection */\nconst DEAD_ZONE = 10;\n\n/** Max angle (degrees) from dismiss axis to qualify as drag intent */\nconst MAX_ANGLE_DEG = 35;\n\n/** Rubber-band resistance factor for dragging past resting position */\nconst RUBBER_BAND_FACTOR = 0.6;\n\n/**\n * Decide whether a gesture past the dead zone qualifies as a dismiss drag.\n * Returns \"drag\" if it's a valid dismiss gesture, \"none\" if it's off-axis\n * or moving in the wrong direction.\n */\nfunction classifyGesture(\n dx: number,\n dy: number,\n axis: \"x\" | \"y\",\n sign: 1 | -1\n): \"drag\" | \"none\" {\n const absDx = Math.abs(dx);\n const absDy = Math.abs(dy);\n\n // Compute angle between movement vector and dismiss axis\n let angleDeg: number;\n if (axis === \"y\") {\n angleDeg = absDy === 0 ? 90 : (Math.atan(absDx / absDy) * 180) / Math.PI;\n } else {\n angleDeg = absDx === 0 ? 90 : (Math.atan(absDy / absDx) * 180) / Math.PI;\n }\n\n if (angleDeg > MAX_ANGLE_DEG) {\n return \"none\";\n }\n\n // Must be moving in the dismiss direction\n const moveInAxis = axis === \"x\" ? dx : dy;\n if (moveInAxis * sign < 0) {\n return \"none\";\n }\n\n return \"drag\";\n}\n\n/** Decide whether a pointer gesture commits as a drag or should be ignored. */\nfunction commitGesture(\n dx: number,\n dy: number,\n axis: \"x\" | \"y\",\n sign: 1 | -1,\n scrollEl: Element | null\n): \"drag\" | \"none\" {\n const gesture = classifyGesture(dx, dy, axis, sign);\n if (gesture === \"none\") {\n return \"none\";\n }\n if (scrollEl && !isAtScrollEdge(scrollEl, axis, sign)) {\n return \"none\";\n }\n return \"drag\";\n}\n\nfunction getPanelDimension(\n panel: HTMLDivElement | null,\n axis: \"x\" | \"y\"\n): number {\n if (!panel) {\n return 300;\n }\n return axis === \"x\" ? panel.offsetWidth : panel.offsetHeight;\n}\n\n/**\n * Hook that manages drag-to-dismiss for a sheet panel.\n *\n * Gesture pipeline:\n * 1. Dead zone (10px) — ignores micro-movements\n * 2. Angle check (35°) — must be roughly aligned with dismiss axis\n * 3. Scroll conflict — yields to scrollable containers not at edge\n * 4. Commit — drag is active, applies offset via `onDragUpdate`\n * 5. Release — velocity + threshold determine close/snap/bounce-back\n *\n * Opposite-direction drag uses √(offset) damping for elastic\n * rubber-band resistance (same physics as iOS over-scroll).\n *\n * When `snapHeights` is provided, release targeting uses\n * `findSnapTarget()` instead of the simple threshold check.\n */\nexport function useDrag(\n panelRef: RefObject<HTMLDivElement | null>,\n config: DragConfig,\n onDragUpdate: (state: DragState) => void\n) {\n const startRef = useRef<{ x: number; y: number; time: number } | null>(null);\n const committedRef = useRef<\"drag\" | \"none\" | null>(null);\n const offsetRef = useRef(0);\n const scrollTargetRef = useRef<Element | null>(null);\n\n const { axis, sign } = getDismissAxis(config.side);\n\n const handlePointerDown = useCallback(\n (e: PointerEvent) => {\n if (!config.enabled) {\n return;\n }\n // Only primary button\n if (e.button !== 0) {\n return;\n }\n // Check target element\n const target = e.target as Element;\n if (!target) {\n return;\n }\n\n // Allow drag from handle elements always\n const isHandle = !!target.closest(\"[data-stacksheet-handle]\");\n\n // For non-handle areas, check if the target is interactive\n if (!isHandle && isInteractiveElement(target)) {\n return;\n }\n\n // Track nearest scrollable ancestor — checked at commit time\n scrollTargetRef.current = isHandle\n ? null\n : findScrollableAncestor(target, axis);\n\n startRef.current = { x: e.clientX, y: e.clientY, time: Date.now() };\n committedRef.current = null;\n offsetRef.current = 0;\n\n // Capture pointer for reliable move/up outside the element\n (e.currentTarget as HTMLElement)?.setPointerCapture?.(e.pointerId);\n },\n [config.enabled, axis]\n );\n\n const handlePointerMove = useCallback(\n (e: PointerEvent) => {\n if (!startRef.current) {\n return;\n }\n\n const dx = e.clientX - startRef.current.x;\n const dy = e.clientY - startRef.current.y;\n const dist = Math.sqrt(dx * dx + dy * dy);\n\n // Still in dead zone — don't commit yet\n if (committedRef.current === null && dist < DEAD_ZONE) {\n return;\n }\n\n // Commit decision: check direction + scroll state\n if (committedRef.current === null) {\n committedRef.current = commitGesture(\n dx,\n dy,\n axis,\n sign,\n scrollTargetRef.current\n );\n if (committedRef.current !== \"drag\") {\n startRef.current = null;\n return;\n }\n }\n\n if (committedRef.current !== \"drag\") {\n return;\n }\n\n // Calculate offset in dismiss direction\n const rawOffset = axis === \"x\" ? dx : dy;\n const directional = rawOffset * sign;\n\n // Dismiss direction: linear movement. Opposite direction: √ damping\n // for elastic rubber-band resistance (same math as iOS over-scroll).\n const clampedOffset =\n directional >= 0\n ? directional\n : -Math.sqrt(Math.abs(directional)) * RUBBER_BAND_FACTOR;\n\n offsetRef.current = clampedOffset;\n onDragUpdate({ offset: clampedOffset, isDragging: true });\n\n // Prevent text selection during active drag\n e.preventDefault();\n },\n [axis, sign, onDragUpdate]\n );\n\n const dismiss = useCallback(() => {\n if (config.isNested) {\n config.onPop();\n } else {\n config.onClose();\n }\n }, [config]);\n\n const handlePointerUp = useCallback(\n (_e: PointerEvent) => {\n if (!startRef.current || committedRef.current !== \"drag\") {\n startRef.current = null;\n committedRef.current = null;\n scrollTargetRef.current = null;\n return;\n }\n\n const offset = Math.max(0, offsetRef.current);\n const elapsed = Date.now() - startRef.current.time;\n const velocity = elapsed > 0 ? offset / elapsed : 0;\n\n startRef.current = null;\n committedRef.current = null;\n offsetRef.current = 0;\n scrollTargetRef.current = null;\n\n const panelSize = getPanelDimension(panelRef.current, axis);\n\n // Snap points mode\n if (config.snapHeights.length > 0) {\n const targetIndex = findSnapTarget(\n offset,\n panelSize,\n config.snapHeights,\n velocity,\n config.activeSnapIndex,\n config.sequential\n );\n if (targetIndex === -1) {\n dismiss();\n } else {\n config.onSnap(targetIndex);\n onDragUpdate({ offset: 0, isDragging: false });\n }\n return;\n }\n\n // Standard mode: threshold-based close\n const pastThreshold = offset / panelSize > config.closeThreshold;\n const fastEnough = velocity > config.velocityThreshold;\n if (pastThreshold || fastEnough) {\n dismiss();\n } else {\n onDragUpdate({ offset: 0, isDragging: false });\n }\n },\n [panelRef, axis, config, onDragUpdate, dismiss]\n );\n\n const handlePointerCancel = useCallback(() => {\n startRef.current = null;\n committedRef.current = null;\n offsetRef.current = 0;\n scrollTargetRef.current = null;\n onDragUpdate({ offset: 0, isDragging: false });\n }, [onDragUpdate]);\n\n // Attach pointer events to the panel element\n useEffect(() => {\n const el = panelRef.current;\n if (!(el && config.enabled)) {\n return;\n }\n\n el.addEventListener(\"pointerdown\", handlePointerDown);\n el.addEventListener(\"pointermove\", handlePointerMove);\n el.addEventListener(\"pointerup\", handlePointerUp);\n el.addEventListener(\"pointercancel\", handlePointerCancel);\n\n return () => {\n el.removeEventListener(\"pointerdown\", handlePointerDown);\n el.removeEventListener(\"pointermove\", handlePointerMove);\n el.removeEventListener(\"pointerup\", handlePointerUp);\n el.removeEventListener(\"pointercancel\", handlePointerCancel);\n };\n }, [\n panelRef,\n config.enabled,\n handlePointerDown,\n handlePointerMove,\n handlePointerUp,\n handlePointerCancel,\n ]);\n}\n","declare const process: undefined | { env?: { NODE_ENV?: string } };\n\nimport type { ComponentType } from \"react\";\nimport { createStore, type StoreApi } from \"zustand\";\nimport type {\n ResolvedConfig,\n SheetActions,\n SheetItem,\n StacksheetSnapshot,\n} from \"./types\";\n\n// biome-ignore lint/suspicious/noExplicitAny: maps store heterogeneous components — type safety is at the call site\ntype AnyComponent = ComponentType<any>;\n\ntype StoreState<TMap extends object> = StacksheetSnapshot<TMap> &\n SheetActions<TMap>;\n\n/** Return type of createSheetStore — store plus ad-hoc component maps */\nexport interface SheetStoreBundle<TMap extends object> {\n store: StoreApi<StoreState<TMap>>;\n /** Component → generated type key (dedup) */\n componentRegistry: Map<AnyComponent, string>;\n /** Generated type key → Component (for renderer lookup) */\n componentMap: Map<string, AnyComponent>;\n}\n\n// ── Ad-hoc helpers ──────────────────────────────\n\n/**\n * Dev-mode warning: detect likely inline arrow functions passed as ad-hoc components.\n * When a new component reference has the same displayName/name as an existing one,\n * it's almost always an inline arrow being re-created every render.\n */\nfunction warnInlineComponent(\n component: AnyComponent,\n componentRegistry: Map<AnyComponent, string>,\n warnedNames: Set<string>\n): void {\n if (\n typeof process === \"undefined\" ||\n process?.env?.NODE_ENV === \"production\"\n ) {\n return;\n }\n\n const name = component.displayName || component.name;\n if (!name) {\n return;\n }\n if (warnedNames.has(name)) {\n return;\n }\n\n for (const [existing, key] of componentRegistry) {\n const existingName = existing.displayName || existing.name;\n if (existingName === name) {\n warnedNames.add(name);\n console.warn(\n `[stacksheet] A new component reference with name \"${name}\" was registered ` +\n `(key: ${key}), but a different reference with the same name already exists. ` +\n `This usually means you're passing an inline arrow function (e.g. ` +\n \"open(() => <MySheet />)). Define the component outside of render to avoid \" +\n \"memory leaks and broken navigate() same-type detection.\"\n );\n return;\n }\n }\n}\n\n/**\n * If `first` is a function (component), register it and return { type, id, data }.\n * Otherwise, pass through the string-based (type, id, data) args unchanged.\n */\nfunction resolveArgs(\n componentRegistry: Map<AnyComponent, string>,\n componentMap: Map<string, AnyComponent>,\n getNextKey: () => string,\n warnedNames: Set<string>,\n first: unknown,\n second: unknown,\n third: unknown\n): { type: string; id: string; data: Record<string, unknown> } {\n if (typeof first === \"function\") {\n const component = first as AnyComponent;\n\n let typeKey = componentRegistry.get(component);\n if (!typeKey) {\n warnInlineComponent(component, componentRegistry, warnedNames);\n typeKey = getNextKey();\n componentRegistry.set(component, typeKey);\n componentMap.set(typeKey, component);\n }\n\n if (typeof second === \"string\") {\n return {\n type: typeKey,\n id: second,\n data: (third ?? {}) as Record<string, unknown>,\n };\n }\n return {\n type: typeKey,\n id: crypto.randomUUID(),\n data: (second ?? {}) as Record<string, unknown>,\n };\n }\n\n return {\n type: first as string,\n id: second as string,\n data: (third ?? {}) as Record<string, unknown>,\n };\n}\n\n/** Pre-resolved args — skips resolveArgs entirely */\ninterface ResolvedItem {\n type: string;\n id: string;\n data: Record<string, unknown>;\n}\n\n/**\n * Create an isolated Zustand store for a sheet stack instance.\n *\n * Returns a store bundle containing the Zustand store plus two maps\n * that track ad-hoc (component-direct) registrations:\n * - `componentRegistry` — maps `ComponentType` → generated type key (dedup)\n * - `componentMap` — maps generated type key → `ComponentType` (renderer lookup)\n *\n * The ad-hoc counter is scoped per instance to prevent identity leaks across\n * multiple `createStacksheet()` calls or test runs.\n */\nexport function createSheetStore<TMap extends object>(\n config: ResolvedConfig\n): SheetStoreBundle<TMap> {\n type Item = SheetItem<Extract<keyof TMap, string>>;\n\n const componentRegistry = new Map<AnyComponent, string>();\n const componentMap = new Map<string, AnyComponent>();\n\n // Per-instance counter (not module-level) — prevents identity leaks across instances/tests\n let adhocCounter = 0;\n function getNextKey() {\n return `__adhoc_${adhocCounter++}`;\n }\n\n // Set of component names already warned about (avoid log spam)\n const warnedNames = new Set<string>();\n\n function resolve(first: unknown, second: unknown, third: unknown) {\n return resolveArgs(\n componentRegistry,\n componentMap,\n getNextKey,\n warnedNames,\n first,\n second,\n third\n );\n }\n\n /** Remove registry entries for type keys no longer in the stack */\n function pruneRegistry(remainingStack: readonly SheetItem[]) {\n const usedTypes = new Set(remainingStack.map((item) => item.type));\n for (const [component, typeKey] of componentRegistry) {\n if (!usedTypes.has(typeKey)) {\n componentRegistry.delete(component);\n componentMap.delete(typeKey);\n }\n }\n }\n\n const store = createStore<StoreState<TMap>>()((set, get) => {\n // ── Internal resolved methods (no double-resolution) ──\n\n function _openResolved({ type, id, data }: ResolvedItem) {\n set({\n stack: [{ id, type, data } as Item],\n isOpen: true,\n });\n }\n\n function _pushResolved({ type, id, data }: ResolvedItem) {\n set((state) => {\n const item = { id, type, data } as Item;\n if (\n Number.isFinite(config.maxDepth) &&\n state.stack.length >= config.maxDepth\n ) {\n return {\n stack: [...state.stack.slice(0, -1), item],\n isOpen: true,\n };\n }\n return {\n stack: [...state.stack, item],\n isOpen: true,\n };\n });\n }\n\n function _replaceResolved({ type, id, data }: ResolvedItem) {\n set((state) => {\n const item = { id, type, data } as Item;\n if (state.stack.length === 0) {\n return { stack: [item], isOpen: true };\n }\n return {\n stack: [...state.stack.slice(0, -1), item],\n isOpen: true,\n };\n });\n }\n\n return {\n stack: [],\n isOpen: false,\n\n open(first: unknown, second?: unknown, third?: unknown) {\n _openResolved(resolve(first, second, third));\n },\n\n push(first: unknown, second?: unknown, third?: unknown) {\n _pushResolved(resolve(first, second, third));\n },\n\n replace(first: unknown, second?: unknown, third?: unknown) {\n _replaceResolved(resolve(first, second, third));\n },\n\n swap(first: unknown, second?: unknown) {\n let type: string;\n let data: Record<string, unknown>;\n\n if (typeof first === \"function\") {\n const component = first as AnyComponent;\n let typeKey = componentRegistry.get(component);\n if (!typeKey) {\n warnInlineComponent(component, componentRegistry, warnedNames);\n typeKey = getNextKey();\n componentRegistry.set(component, typeKey);\n componentMap.set(typeKey, component);\n }\n type = typeKey;\n data = (second ?? {}) as Record<string, unknown>;\n } else {\n type = first as string;\n data = (second ?? {}) as Record<string, unknown>;\n }\n\n set((state) => {\n const top = state.stack.at(-1);\n if (!top) {\n return state;\n }\n const newStack = [...state.stack];\n newStack[newStack.length - 1] = { id: top.id, type, data } as Item;\n return { stack: newStack };\n });\n },\n\n navigate(first: unknown, second?: unknown, third?: unknown) {\n const resolved = resolve(first, second, third);\n const { stack } = get();\n const top = stack.at(-1);\n\n if (stack.length === 0) {\n _openResolved(resolved);\n return;\n }\n\n // For ad-hoc components, check if the top item's type maps to the same\n // component in the registry. For string types, compare directly.\n let isSameType = top?.type === resolved.type;\n if (!isSameType && typeof first === \"function\") {\n const topComponent = componentMap.get(top?.type ?? \"\");\n isSameType = topComponent === first;\n }\n\n if (isSameType) {\n _replaceResolved(resolved);\n return;\n }\n\n _pushResolved(resolved);\n },\n\n setData(first: unknown, second?: unknown, third?: unknown) {\n // setData always has an id: (type, id, data) or (Component, id, data)\n const { id, data } = resolve(first, second, third);\n set((state) => {\n const idx = state.stack.findIndex((item) => item.id === id);\n if (idx === -1) {\n return state;\n }\n const updated = [...state.stack];\n updated[idx] = { ...updated[idx], data } as Item;\n return { stack: updated };\n });\n },\n\n remove(id) {\n set((state) => {\n const next = state.stack.filter((item) => item.id !== id);\n if (next.length === state.stack.length) {\n return state;\n }\n pruneRegistry(next);\n if (next.length === 0) {\n return { stack: [], isOpen: false };\n }\n return { stack: next };\n });\n },\n\n pop() {\n set((state) => {\n if (state.stack.length <= 1) {\n pruneRegistry([]);\n return { stack: [], isOpen: false };\n }\n const next = state.stack.slice(0, -1);\n pruneRegistry(next);\n return { stack: next, isOpen: true };\n });\n },\n\n close() {\n pruneRegistry([]);\n set({ stack: [], isOpen: false });\n },\n };\n });\n\n return { store, componentRegistry, componentMap };\n}\n","import {\n Root as ScrollAreaRoot,\n Scrollbar as ScrollAreaScrollbar,\n Thumb as ScrollAreaThumb,\n Viewport as ScrollAreaViewport,\n} from \"@radix-ui/react-scroll-area\";\nimport { Slot } from \"@radix-ui/react-slot\";\nimport {\n type CSSProperties,\n type KeyboardEvent as ReactKeyboardEvent,\n type ReactNode,\n useEffect,\n} from \"react\";\nimport { ArrowLeftIcon, XIcon } from \"./icons\";\nimport { useSheetPanel } from \"./panel-context\";\n\n// ── Sheet.Handle ────────────────────────────────\n\nexport interface SheetHandleProps {\n /** Render as child element, merging props */\n asChild?: boolean;\n className?: string;\n style?: CSSProperties;\n /** Custom handle content. Defaults to a centered grab bar. */\n children?: ReactNode;\n}\n\nfunction SheetHandle({\n asChild,\n className,\n style,\n children,\n}: SheetHandleProps) {\n const { close, back, isNested } = useSheetPanel();\n const dismiss = isNested ? back : close;\n const Comp = asChild ? Slot : \"div\";\n return (\n <Comp\n aria-label=\"Dismiss\"\n className={`flex shrink-0 cursor-grab touch-none items-center justify-center pt-4 pb-1 ${className ?? \"\"}`}\n data-stacksheet-handle=\"\"\n onClick={dismiss}\n onKeyDown={(e: ReactKeyboardEvent) => {\n if (e.key === \"Enter\" || e.key === \" \") {\n e.preventDefault();\n dismiss();\n }\n }}\n role=\"button\"\n style={style}\n tabIndex={0}\n >\n {children ?? (\n <div aria-hidden=\"true\" className=\"h-1 w-9 rounded-sm bg-current/25\" />\n )}\n </Comp>\n );\n}\n\n// ── Sheet.Header ────────────────────────────────\n\nexport interface SheetHeaderProps {\n asChild?: boolean;\n className?: string;\n style?: CSSProperties;\n children: ReactNode;\n}\n\nfunction SheetHeader({\n asChild,\n className,\n style,\n children,\n}: SheetHeaderProps) {\n const Comp = asChild ? Slot : \"header\";\n return (\n <Comp\n className={`flex h-14 shrink-0 items-center justify-between border-b px-6 ${className ?? \"\"}`}\n style={style}\n >\n {children}\n </Comp>\n );\n}\n\n// ── Sheet.Title ─────────────────────────────────\n\nexport interface SheetTitleProps {\n asChild?: boolean;\n className?: string;\n style?: CSSProperties;\n children: ReactNode;\n}\n\nfunction SheetTitle({ asChild, className, style, children }: SheetTitleProps) {\n const { panelId } = useSheetPanel();\n const Comp = asChild ? Slot : \"h2\";\n return (\n <Comp\n className={`font-semibold text-sm ${className ?? \"\"}`}\n id={`${panelId}-title`}\n style={style}\n >\n {children}\n </Comp>\n );\n}\n\n// ── Sheet.Description ───────────────────────────\n\nexport interface SheetDescriptionProps {\n asChild?: boolean;\n className?: string;\n style?: CSSProperties;\n children: ReactNode;\n}\n\nfunction SheetDescription({\n asChild,\n className,\n style,\n children,\n}: SheetDescriptionProps) {\n const { panelId, registerDescription } = useSheetPanel();\n\n useEffect(() => registerDescription(), [registerDescription]);\n const Comp = asChild ? Slot : \"p\";\n return (\n <Comp className={className} id={`${panelId}-desc`} style={style}>\n {children}\n </Comp>\n );\n}\n\n// ── Sheet.Body ──────────────────────────────────\n\nexport interface SheetBodyProps {\n /** When true, renders child element directly instead of ScrollArea */\n asChild?: boolean;\n className?: string;\n style?: CSSProperties;\n children: ReactNode;\n}\n\nfunction SheetBody({ asChild, className, style, children }: SheetBodyProps) {\n if (asChild) {\n return (\n <Slot\n className={`relative min-h-0 flex-1 ${className ?? \"\"}`}\n data-stacksheet-no-drag=\"\"\n style={style}\n >\n {children}\n </Slot>\n );\n }\n\n return (\n <ScrollAreaRoot\n className={`relative flex min-h-0 flex-1 flex-col overflow-hidden ${className ?? \"\"}`}\n data-stacksheet-no-drag=\"\"\n style={style}\n >\n <ScrollAreaViewport className=\"min-h-0 w-full flex-1 overscroll-contain\">\n {children}\n </ScrollAreaViewport>\n <ScrollAreaScrollbar\n className=\"flex w-2 touch-none select-none p-0.5\"\n orientation=\"vertical\"\n >\n <ScrollAreaThumb className=\"relative flex-1 rounded bg-current/15\" />\n </ScrollAreaScrollbar>\n </ScrollAreaRoot>\n );\n}\n\n// ── Sheet.Footer ────────────────────────────────\n\nexport interface SheetFooterProps {\n asChild?: boolean;\n className?: string;\n style?: CSSProperties;\n children: ReactNode;\n}\n\nfunction SheetFooter({\n asChild,\n className,\n style,\n children,\n}: SheetFooterProps) {\n const Comp = asChild ? Slot : \"footer\";\n return (\n <Comp\n className={`flex shrink-0 items-center gap-2 border-t px-6 py-3 ${className ?? \"\"}`}\n style={style}\n >\n {children}\n </Comp>\n );\n}\n\n// ── Sheet.Close ─────────────────────────────────\n\nexport interface SheetCloseProps {\n asChild?: boolean;\n className?: string;\n style?: CSSProperties;\n /** Custom content. Defaults to an X icon. */\n children?: ReactNode;\n}\n\nfunction SheetClose({ asChild, className, style, children }: SheetCloseProps) {\n const { close } = useSheetPanel();\n const Comp = asChild ? Slot : \"button\";\n return (\n <Comp\n aria-label={children ? undefined : \"Close\"}\n className={`flex h-8 w-8 shrink-0 cursor-pointer items-center justify-center rounded-md border-none bg-transparent p-0 text-inherit opacity-60 transition-opacity duration-150 hover:opacity-100 ${className ?? \"\"}`}\n onClick={close}\n style={style}\n type={asChild ? undefined : \"button\"}\n >\n {children ?? <XIcon />}\n </Comp>\n );\n}\n\n// ── Sheet.Back ──────────────────────────────────\n\nexport interface SheetBackProps {\n asChild?: boolean;\n className?: string;\n style?: CSSProperties;\n /** Custom content. Defaults to an arrow-left icon. */\n children?: ReactNode;\n}\n\nfunction SheetBack({ asChild, className, style, children }: SheetBackProps) {\n const { back, isNested } = useSheetPanel();\n\n if (!isNested) {\n return null;\n }\n\n const Comp = asChild ? Slot : \"button\";\n return (\n <Comp\n aria-label={children ? undefined : \"Back\"}\n className={`flex h-8 w-8 shrink-0 cursor-pointer items-center justify-center rounded-md border-none bg-transparent p-0 text-inherit opacity-60 transition-opacity duration-150 hover:opacity-100 ${className ?? \"\"}`}\n onClick={back}\n style={style}\n type={asChild ? undefined : \"button\"}\n >\n {children ?? <ArrowLeftIcon />}\n </Comp>\n );\n}\n\n// ── Sheet namespace ─────────────────────────────\n\n/**\n * Composable sheet parts for building custom panel layouts.\n *\n * Use with `renderHeader={false}` on the provider to opt into\n * composable mode — no auto header or scroll wrapper, full control\n * over the panel's structure.\n *\n * `Sheet.Title` and `Sheet.Description` are linked to the panel's\n * `aria-labelledby` and `aria-describedby` via matching IDs.\n */\nexport const Sheet = {\n Handle: SheetHandle,\n Header: SheetHeader,\n Title: SheetTitle,\n Description: SheetDescription,\n Body: SheetBody,\n Footer: SheetFooter,\n Close: SheetClose,\n Back: SheetBack,\n} as const;\n"],"mappings":"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","names":["createContext","useContext","useMemo","useStore","useCallback","useEffect","useRef","useState","useEffect","useEffect","jsx","useState","useEffect","SheetPanel","useRef","useCallback","jsx","jsxs","createContext","useContext","useMemo","useStore","useEffect","jsx","jsxs","useEffect"]}
|
package/dist/styles.css
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
/*! tailwindcss v4.1.18 | MIT License | https://tailwindcss.com */
|
|
2
|
-
@layer properties{@supports (((-webkit-hyphens:none)) and (not (margin-trim:inline))) or ((-moz-orient:inline) and (not (color:rgb(from red r g b)))){*,:before,:after,::backdrop{--tw-rotate-x:initial;--tw-rotate-y:initial;--tw-rotate-z:initial;--tw-skew-x:initial;--tw-skew-y:initial;--tw-border-style:solid;--tw-font-weight:initial;--tw-shadow:0 0 #0000;--tw-shadow-color:initial;--tw-shadow-alpha:100%;--tw-inset-shadow:0 0 #0000;--tw-inset-shadow-color:initial;--tw-inset-shadow-alpha:100%;--tw-ring-color:initial;--tw-ring-shadow:0 0 #0000;--tw-inset-ring-color:initial;--tw-inset-ring-shadow:0 0 #0000;--tw-ring-inset:initial;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-offset-shadow:0 0 #0000;--tw-duration:initial}}}@layer theme{:root,:host{--font-sans:ui-sans-serif,system-ui,sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol","Noto Color Emoji";--font-mono:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono","Courier New",monospace;--spacing:.25rem;--text-sm:.875rem;--text-sm--line-height:calc(1.25/.875);--font-weight-semibold:600;--radius-sm:.25rem;--radius-md:.375rem;--default-transition-duration:.15s;--default-transition-timing-function:cubic-bezier(.4,0,.2,1);--default-font-family:var(--font-sans);--default-mono-font-family:var(--font-mono)}}@layer base{*,:after,:before,::backdrop{box-sizing:border-box;border:0 solid;margin:0;padding:0}::file-selector-button{box-sizing:border-box;border:0 solid;margin:0;padding:0}html,:host{-webkit-text-size-adjust:100%;tab-size:4;line-height:1.5;font-family:var(--default-font-family,ui-sans-serif,system-ui,sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol","Noto Color Emoji");font-feature-settings:var(--default-font-feature-settings,normal);font-variation-settings:var(--default-font-variation-settings,normal);-webkit-tap-highlight-color:transparent}hr{height:0;color:inherit;border-top-width:1px}abbr:where([title]){-webkit-text-decoration:underline dotted;text-decoration:underline dotted}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;-webkit-text-decoration:inherit;-webkit-text-decoration:inherit;-webkit-text-decoration:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,samp,pre{font-family:var(--default-mono-font-family,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono","Courier New",monospace);font-feature-settings:var(--default-mono-font-feature-settings,normal);font-variation-settings:var(--default-mono-font-variation-settings,normal);font-size:1em}small{font-size:80%}sub,sup{vertical-align:baseline;font-size:75%;line-height:0;position:relative}sub{bottom:-.25em}sup{top:-.5em}table{text-indent:0;border-color:inherit;border-collapse:collapse}:-moz-focusring{outline:auto}progress{vertical-align:baseline}summary{display:list-item}ol,ul,menu{list-style:none}img,svg,video,canvas,audio,iframe,embed,object{vertical-align:middle;display:block}img,video{max-width:100%;height:auto}button,input,select,optgroup,textarea{font:inherit;font-feature-settings:inherit;font-variation-settings:inherit;letter-spacing:inherit;color:inherit;opacity:1;background-color:#0000;border-radius:0}::file-selector-button{font:inherit;font-feature-settings:inherit;font-variation-settings:inherit;letter-spacing:inherit;color:inherit;opacity:1;background-color:#0000;border-radius:0}:where(select:is([multiple],[size])) optgroup{font-weight:bolder}:where(select:is([multiple],[size])) optgroup option{padding-inline-start:20px}::file-selector-button{margin-inline-end:4px}::placeholder{opacity:1}@supports (not ((-webkit-appearance:-apple-pay-button))) or (contain-intrinsic-size:1px){::placeholder{color:currentColor}@supports (color:color-mix(in lab, red, red)){::placeholder{color:color-mix(in oklab,currentcolor 50%,transparent)}}}textarea{resize:vertical}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-date-and-time-value{min-height:1lh;text-align:inherit}::-webkit-datetime-edit{display:inline-flex}::-webkit-datetime-edit-fields-wrapper{padding:0}::-webkit-datetime-edit{padding-block:0}::-webkit-datetime-edit-year-field{padding-block:0}::-webkit-datetime-edit-month-field{padding-block:0}::-webkit-datetime-edit-day-field{padding-block:0}::-webkit-datetime-edit-hour-field{padding-block:0}::-webkit-datetime-edit-minute-field{padding-block:0}::-webkit-datetime-edit-second-field{padding-block:0}::-webkit-datetime-edit-millisecond-field{padding-block:0}::-webkit-datetime-edit-meridiem-field{padding-block:0}::-webkit-calendar-picker-indicator{line-height:1}:-moz-ui-invalid{box-shadow:none}button,input:where([type=button],[type=reset],[type=submit]){appearance:button}::file-selector-button{appearance:button}::-webkit-inner-spin-button{height:auto}::-webkit-outer-spin-button{height:auto}[hidden]:where(:not([hidden=until-found])){display:none!important}}@layer components;@layer utilities{.pointer-events-none{pointer-events:none}.invisible{visibility:hidden}.visible{visibility:visible}.absolute{position:absolute}.fixed{position:fixed}.relative{position:relative}.static{position:static}.inset-0{inset:calc(var(--spacing)*0)}.top-0{top:calc(var(--spacing)*0)}.bottom-0{bottom:calc(var(--spacing)*0)}.container{width:100%}@media (min-width:40rem){.container{max-width:40rem}}@media (min-width:48rem){.container{max-width:48rem}}@media (min-width:64rem){.container{max-width:64rem}}@media (min-width:80rem){.container{max-width:80rem}}@media (min-width:96rem){.container{max-width:96rem}}.flex{display:flex}.hidden{display:none}.inline{display:inline}.h-1{height:calc(var(--spacing)*1)}.h-8{height:calc(var(--spacing)*8)}.h-10{height:calc(var(--spacing)*10)}.h-14{height:calc(var(--spacing)*14)}.min-h-0{min-height:calc(var(--spacing)*0)}.w-2{width:calc(var(--spacing)*2)}.w-6{width:calc(var(--spacing)*6)}.w-8{width:calc(var(--spacing)*8)}.w-9{width:calc(var(--spacing)*9)}.w-\[5px\]{width:5px}.w-full{width:100%}.flex-1{flex:1}.shrink-0{flex-shrink:0}.transform{transform:var(--tw-rotate-x,)var(--tw-rotate-y,)var(--tw-rotate-z,)var(--tw-skew-x,)var(--tw-skew-y,)}.cursor-grab{cursor:grab}.cursor-pointer{cursor:pointer}.touch-none{touch-action:none}.flex-col{flex-direction:column}.items-center{align-items:center}.justify-between{justify-content:space-between}.justify-center{justify-content:center}.gap-2{gap:calc(var(--spacing)*2)}.overflow-hidden{overflow:hidden}.overflow-y-auto{overflow-y:auto}.overscroll-contain{overscroll-behavior:contain}.rounded{border-radius:.25rem}.rounded-\[inherit\]{border-radius:inherit}.rounded-md{border-radius:var(--radius-md)}.rounded-sm{border-radius:var(--radius-sm)}.border{border-style:var(--tw-border-style);border-width:1px}.border-t{border-top-style:var(--tw-border-style);border-top-width:1px}.border-b{border-bottom-style:var(--tw-border-style);border-bottom-width:1px}.border-none{--tw-border-style:none;border-style:none}.bg-current\/15{background-color:currentColor}@supports (color:color-mix(in lab, red, red)){.bg-current\/15{background-color:color-mix(in oklab,currentcolor 15%,transparent)}}.bg-current\/25{background-color:currentColor}@supports (color:color-mix(in lab, red, red)){.bg-current\/25{background-color:color-mix(in oklab,currentcolor 25%,transparent)}}.bg-current\/35{background-color:currentColor}@supports (color:color-mix(in lab, red, red)){.bg-current\/35{background-color:color-mix(in oklab,currentcolor 35%,transparent)}}.bg-transparent{background-color:#0000}.p-0{padding:calc(var(--spacing)*0)}.p-0\.5{padding:calc(var(--spacing)*.5)}.px-6{padding-inline:calc(var(--spacing)*6)}.py-3{padding-block:calc(var(--spacing)*3)}.pt-2{padding-top:calc(var(--spacing)*2)}.pt-4{padding-top:calc(var(--spacing)*4)}.pb-1{padding-bottom:calc(var(--spacing)*1)}.text-sm{font-size:var(--text-sm);line-height:var(--tw-leading,var(--text-sm--line-height))}.font-semibold{--tw-font-weight:var(--font-weight-semibold);font-weight:var(--font-weight-semibold)}.text-inherit{color:inherit}.opacity-60{opacity:.6}.shadow-sm{--tw-shadow:0 1px 3px 0 var(--tw-shadow-color,#0000001a),0 1px 2px -1px var(--tw-shadow-color,#0000001a);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.transition{transition-property:color,background-color,border-color,outline-color,text-decoration-color,fill,stroke,--tw-gradient-from,--tw-gradient-via,--tw-gradient-to,opacity,box-shadow,transform,translate,scale,rotate,filter,-webkit-backdrop-filter,backdrop-filter,display,content-visibility,overlay,pointer-events;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.transition-opacity{transition-property:opacity;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.duration-150{--tw-duration:.15s;transition-duration:.15s}.select-none{-webkit-user-select:none;user-select:none}@media (hover:hover){.hover\:opacity-100:hover{opacity:1}}}@property --tw-rotate-x{syntax:"*";inherits:false}@property --tw-rotate-y{syntax:"*";inherits:false}@property --tw-rotate-z{syntax:"*";inherits:false}@property --tw-skew-x{syntax:"*";inherits:false}@property --tw-skew-y{syntax:"*";inherits:false}@property --tw-border-style{syntax:"*";inherits:false;initial-value:solid}@property --tw-font-weight{syntax:"*";inherits:false}@property --tw-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-shadow-color{syntax:"*";inherits:false}@property --tw-shadow-alpha{syntax:"<percentage>";inherits:false;initial-value:100%}@property --tw-inset-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-inset-shadow-color{syntax:"*";inherits:false}@property --tw-inset-shadow-alpha{syntax:"<percentage>";inherits:false;initial-value:100%}@property --tw-ring-color{syntax:"*";inherits:false}@property --tw-ring-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-inset-ring-color{syntax:"*";inherits:false}@property --tw-inset-ring-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-ring-inset{syntax:"*";inherits:false}@property --tw-ring-offset-width{syntax:"<length>";inherits:false;initial-value:0}@property --tw-ring-offset-color{syntax:"*";inherits:false;initial-value:#fff}@property --tw-ring-offset-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-duration{syntax:"*";inherits:false}
|
|
2
|
+
@layer properties{@supports (((-webkit-hyphens:none)) and (not (margin-trim:inline))) or ((-moz-orient:inline) and (not (color:rgb(from red r g b)))){*,:before,:after,::backdrop{--tw-rotate-x:initial;--tw-rotate-y:initial;--tw-rotate-z:initial;--tw-skew-x:initial;--tw-skew-y:initial;--tw-border-style:solid;--tw-font-weight:initial;--tw-shadow:0 0 #0000;--tw-shadow-color:initial;--tw-shadow-alpha:100%;--tw-inset-shadow:0 0 #0000;--tw-inset-shadow-color:initial;--tw-inset-shadow-alpha:100%;--tw-ring-color:initial;--tw-ring-shadow:0 0 #0000;--tw-inset-ring-color:initial;--tw-inset-ring-shadow:0 0 #0000;--tw-ring-inset:initial;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-offset-shadow:0 0 #0000;--tw-duration:initial}}}@layer theme{:root,:host{--font-sans:ui-sans-serif,system-ui,sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol","Noto Color Emoji";--font-mono:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono","Courier New",monospace;--spacing:.25rem;--text-sm:.875rem;--text-sm--line-height:calc(1.25/.875);--font-weight-semibold:600;--radius-sm:.25rem;--radius-md:.375rem;--default-transition-duration:.15s;--default-transition-timing-function:cubic-bezier(.4,0,.2,1);--default-font-family:var(--font-sans);--default-mono-font-family:var(--font-mono)}}@layer base{*,:after,:before,::backdrop{box-sizing:border-box;border:0 solid;margin:0;padding:0}::file-selector-button{box-sizing:border-box;border:0 solid;margin:0;padding:0}html,:host{-webkit-text-size-adjust:100%;tab-size:4;line-height:1.5;font-family:var(--default-font-family,ui-sans-serif,system-ui,sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol","Noto Color Emoji");font-feature-settings:var(--default-font-feature-settings,normal);font-variation-settings:var(--default-font-variation-settings,normal);-webkit-tap-highlight-color:transparent}hr{height:0;color:inherit;border-top-width:1px}abbr:where([title]){-webkit-text-decoration:underline dotted;text-decoration:underline dotted}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;-webkit-text-decoration:inherit;-webkit-text-decoration:inherit;-webkit-text-decoration:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,samp,pre{font-family:var(--default-mono-font-family,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono","Courier New",monospace);font-feature-settings:var(--default-mono-font-feature-settings,normal);font-variation-settings:var(--default-mono-font-variation-settings,normal);font-size:1em}small{font-size:80%}sub,sup{vertical-align:baseline;font-size:75%;line-height:0;position:relative}sub{bottom:-.25em}sup{top:-.5em}table{text-indent:0;border-color:inherit;border-collapse:collapse}:-moz-focusring{outline:auto}progress{vertical-align:baseline}summary{display:list-item}ol,ul,menu{list-style:none}img,svg,video,canvas,audio,iframe,embed,object{vertical-align:middle;display:block}img,video{max-width:100%;height:auto}button,input,select,optgroup,textarea{font:inherit;font-feature-settings:inherit;font-variation-settings:inherit;letter-spacing:inherit;color:inherit;opacity:1;background-color:#0000;border-radius:0}::file-selector-button{font:inherit;font-feature-settings:inherit;font-variation-settings:inherit;letter-spacing:inherit;color:inherit;opacity:1;background-color:#0000;border-radius:0}:where(select:is([multiple],[size])) optgroup{font-weight:bolder}:where(select:is([multiple],[size])) optgroup option{padding-inline-start:20px}::file-selector-button{margin-inline-end:4px}::placeholder{opacity:1}@supports (not ((-webkit-appearance:-apple-pay-button))) or (contain-intrinsic-size:1px){::placeholder{color:currentColor}@supports (color:color-mix(in lab, red, red)){::placeholder{color:color-mix(in oklab,currentcolor 50%,transparent)}}}textarea{resize:vertical}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-date-and-time-value{min-height:1lh;text-align:inherit}::-webkit-datetime-edit{display:inline-flex}::-webkit-datetime-edit-fields-wrapper{padding:0}::-webkit-datetime-edit{padding-block:0}::-webkit-datetime-edit-year-field{padding-block:0}::-webkit-datetime-edit-month-field{padding-block:0}::-webkit-datetime-edit-day-field{padding-block:0}::-webkit-datetime-edit-hour-field{padding-block:0}::-webkit-datetime-edit-minute-field{padding-block:0}::-webkit-datetime-edit-second-field{padding-block:0}::-webkit-datetime-edit-millisecond-field{padding-block:0}::-webkit-datetime-edit-meridiem-field{padding-block:0}::-webkit-calendar-picker-indicator{line-height:1}:-moz-ui-invalid{box-shadow:none}button,input:where([type=button],[type=reset],[type=submit]){appearance:button}::file-selector-button{appearance:button}::-webkit-inner-spin-button{height:auto}::-webkit-outer-spin-button{height:auto}[hidden]:where(:not([hidden=until-found])){display:none!important}}@layer components;@layer utilities{.pointer-events-none{pointer-events:none}.invisible{visibility:hidden}.visible{visibility:visible}.absolute{position:absolute}.fixed{position:fixed}.relative{position:relative}.static{position:static}.inset-0{inset:calc(var(--spacing)*0)}.inset-x-0{inset-inline:calc(var(--spacing)*0)}.top-0{top:calc(var(--spacing)*0)}.bottom-0{bottom:calc(var(--spacing)*0)}.z-10{z-index:10}.container{width:100%}@media (min-width:40rem){.container{max-width:40rem}}@media (min-width:48rem){.container{max-width:48rem}}@media (min-width:64rem){.container{max-width:64rem}}@media (min-width:80rem){.container{max-width:80rem}}@media (min-width:96rem){.container{max-width:96rem}}.flex{display:flex}.hidden{display:none}.inline{display:inline}.h-1{height:calc(var(--spacing)*1)}.h-8{height:calc(var(--spacing)*8)}.h-10{height:calc(var(--spacing)*10)}.h-14{height:calc(var(--spacing)*14)}.min-h-0{min-height:calc(var(--spacing)*0)}.w-2{width:calc(var(--spacing)*2)}.w-6{width:calc(var(--spacing)*6)}.w-8{width:calc(var(--spacing)*8)}.w-9{width:calc(var(--spacing)*9)}.w-\[5px\]{width:5px}.w-full{width:100%}.flex-1{flex:1}.shrink-0{flex-shrink:0}.transform{transform:var(--tw-rotate-x,)var(--tw-rotate-y,)var(--tw-rotate-z,)var(--tw-skew-x,)var(--tw-skew-y,)}.cursor-grab{cursor:grab}.cursor-pointer{cursor:pointer}.touch-none{touch-action:none}.flex-col{flex-direction:column}.items-center{align-items:center}.justify-between{justify-content:space-between}.justify-center{justify-content:center}.gap-2{gap:calc(var(--spacing)*2)}.overflow-hidden{overflow:hidden}.overflow-y-auto{overflow-y:auto}.overscroll-contain{overscroll-behavior:contain}.rounded{border-radius:.25rem}.rounded-\[inherit\]{border-radius:inherit}.rounded-md{border-radius:var(--radius-md)}.rounded-sm{border-radius:var(--radius-sm)}.border{border-style:var(--tw-border-style);border-width:1px}.border-t{border-top-style:var(--tw-border-style);border-top-width:1px}.border-b{border-bottom-style:var(--tw-border-style);border-bottom-width:1px}.border-none{--tw-border-style:none;border-style:none}.bg-current\/15{background-color:currentColor}@supports (color:color-mix(in lab, red, red)){.bg-current\/15{background-color:color-mix(in oklab,currentcolor 15%,transparent)}}.bg-current\/25{background-color:currentColor}@supports (color:color-mix(in lab, red, red)){.bg-current\/25{background-color:color-mix(in oklab,currentcolor 25%,transparent)}}.bg-current\/35{background-color:currentColor}@supports (color:color-mix(in lab, red, red)){.bg-current\/35{background-color:color-mix(in oklab,currentcolor 35%,transparent)}}.bg-transparent{background-color:#0000}.p-0{padding:calc(var(--spacing)*0)}.p-0\.5{padding:calc(var(--spacing)*.5)}.px-6{padding-inline:calc(var(--spacing)*6)}.py-3{padding-block:calc(var(--spacing)*3)}.pt-2{padding-top:calc(var(--spacing)*2)}.pt-4{padding-top:calc(var(--spacing)*4)}.pb-1{padding-bottom:calc(var(--spacing)*1)}.text-sm{font-size:var(--text-sm);line-height:var(--tw-leading,var(--text-sm--line-height))}.font-semibold{--tw-font-weight:var(--font-weight-semibold);font-weight:var(--font-weight-semibold)}.text-inherit{color:inherit}.opacity-60{opacity:.6}.shadow-sm{--tw-shadow:0 1px 3px 0 var(--tw-shadow-color,#0000001a),0 1px 2px -1px var(--tw-shadow-color,#0000001a);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.transition{transition-property:color,background-color,border-color,outline-color,text-decoration-color,fill,stroke,--tw-gradient-from,--tw-gradient-via,--tw-gradient-to,opacity,box-shadow,transform,translate,scale,rotate,filter,-webkit-backdrop-filter,backdrop-filter,display,content-visibility,overlay,pointer-events;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.transition-opacity{transition-property:opacity;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.duration-150{--tw-duration:.15s;transition-duration:.15s}.select-none{-webkit-user-select:none;user-select:none}@media (hover:hover){.hover\:opacity-100:hover{opacity:1}}}@property --tw-rotate-x{syntax:"*";inherits:false}@property --tw-rotate-y{syntax:"*";inherits:false}@property --tw-rotate-z{syntax:"*";inherits:false}@property --tw-skew-x{syntax:"*";inherits:false}@property --tw-skew-y{syntax:"*";inherits:false}@property --tw-border-style{syntax:"*";inherits:false;initial-value:solid}@property --tw-font-weight{syntax:"*";inherits:false}@property --tw-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-shadow-color{syntax:"*";inherits:false}@property --tw-shadow-alpha{syntax:"<percentage>";inherits:false;initial-value:100%}@property --tw-inset-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-inset-shadow-color{syntax:"*";inherits:false}@property --tw-inset-shadow-alpha{syntax:"<percentage>";inherits:false;initial-value:100%}@property --tw-ring-color{syntax:"*";inherits:false}@property --tw-ring-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-inset-ring-color{syntax:"*";inherits:false}@property --tw-inset-ring-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-ring-inset{syntax:"*";inherits:false}@property --tw-ring-offset-width{syntax:"<length>";inherits:false;initial-value:0}@property --tw-ring-offset-color{syntax:"*";inherits:false;initial-value:#fff}@property --tw-ring-offset-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-duration{syntax:"*";inherits:false}
|
package/package.json
CHANGED