@patternmode/stacksheet 1.4.0 → 2.0.0

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.
@@ -1 +1 @@
1
- {"version":3,"file":"index.mjs","names":["motionSprings","ScrollAreaRoot","ScrollAreaViewport","ScrollAreaScrollbar","ScrollAreaThumb"],"sources":["../src/springs.ts","../src/config.ts","../src/media.ts","../src/renderer-effects.ts","../src/snap-points.ts","../src/renderer-helpers.ts","../src/Drag/drag-constants.ts","../src/Drag/drag-geometry.ts","../src/Drag/drag-velocity.ts","../src/Drag/use-drag.ts","../src/panel-context.tsx","../src/stacking.ts","../src/icons.tsx","../src/SheetPanel/default-header.tsx","../src/SheetPanel/sheet-panel-content.tsx","../src/SheetPanel/sheet-panel-focus.tsx","../src/SheetPanel/sheet-panel-handles.tsx","../src/SheetPanel/sheet-panel-layout.ts","../src/SheetPanel/sheet-panel.tsx","../src/renderer.tsx","../src/Store/store-args.ts","../src/Store/create-sheet-store.ts","../src/create.tsx","../src/SheetParts/sheet-back.tsx","../src/SheetParts/sheet-body.tsx","../src/SheetParts/sheet-close.tsx","../src/SheetParts/sheet-description.tsx","../src/SheetParts/sheet-footer.tsx","../src/SheetParts/sheet-handle.tsx","../src/SheetParts/sheet-header.tsx","../src/SheetParts/sheet-title.tsx","../src/SheetParts/sheet-parts.ts"],"sourcesContent":["import { springs as motionSprings } from \"@howells/motion\";\n\nimport type { SpringConfig } from \"./types\";\n\n/** Strips the shared token's `type: \"spring\"` down to Stacksheet's numeric SpringConfig. */\nconst toSpringConfig = (spring: {\n damping: number;\n mass: number;\n stiffness: number;\n}): SpringConfig => ({\n damping: spring.damping,\n mass: spring.mass,\n stiffness: spring.stiffness,\n});\n\n/**\n * Spring presets inspired by iOS animation feel.\n *\n * - `subtle` — Barely noticeable bounce, professional. (shared @howells/motion token)\n * - `snappy` — Quick, responsive for interactions. (shared @howells/motion token)\n * - `stiff` — Very quick, controlled. Panels, drawers. **(default)** Intentional\n * fork: damping 40 (tighter than the shared `stiff`) for drawer control.\n */\nexport const springs = {\n snappy: toSpringConfig(motionSprings.snappy),\n stiff: { damping: 40, mass: 1, stiffness: 400 },\n subtle: toSpringConfig(motionSprings.subtle),\n} 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// ── Defaults ────────────────────────────────────\nconst DEFAULT_STACKING: StackingConfig = {\n offsetStep: 16,\n opacityStep: 0,\n radius: 12,\n renderThreshold: 3,\n scaleStep: 0.04,\n};\nconst DEFAULT_SIDE: ResponsiveSide = {\n desktop: \"right\",\n mobile: \"bottom\",\n};\nconst DEFAULT_CONFIG: Omit<ResolvedConfig, \"side\" | \"spring\" | \"stacking\"> = {\n ariaLabel: \"Sheet dialog\",\n breakpoint: 768,\n closeOnBackdrop: true,\n closeOnEscape: true,\n closeThreshold: 0.25,\n dismissible: true,\n drag: true,\n handle: \"inside\",\n lockScroll: true,\n maxDepth: Number.POSITIVE_INFINITY,\n maxWidth: \"90vw\",\n modal: true,\n repositionInputs: true,\n scaleBackgroundAmount: 0.97,\n shouldScaleBackground: false,\n showOverlay: true,\n snapPoints: [],\n snapToSequentialPoints: false,\n velocityThreshold: 0.5,\n width: 420,\n zIndex: 100,\n};\n// ── Helpers ─────────────────────────────────────\n/** Normalize a string side to a responsive object, merging with defaults. */\nconst resolveSide = (side: SideConfig | undefined): ResponsiveSide => {\n if (typeof side === \"string\") {\n return { desktop: side, mobile: side };\n }\n return { ...DEFAULT_SIDE, ...side };\n};\n/** Resolve a preset name to a SpringConfig, or merge partial config with defaults. */\nconst resolveSpring = (spring: SpringPreset | Partial<SpringConfig> | undefined): SpringConfig => {\n if (typeof spring === \"string\") {\n return springs[spring];\n }\n return { ...springs.stiff, ...spring };\n};\n// ── Resolver ────────────────────────────────────\n/** Merge user-provided config with defaults. Resolves union types (side, spring) to concrete values. */\nexport const resolveConfig = (config: StacksheetConfig = {}): ResolvedConfig => {\n const { side, spring, stacking, ...scalarConfig } = config;\n const definedConfig = Object.fromEntries(\n Object.entries(scalarConfig).filter(([, value]) => value !== undefined),\n ) as Partial<Omit<ResolvedConfig, \"side\" | \"spring\" | \"stacking\">>;\n\n return {\n ...DEFAULT_CONFIG,\n ...definedConfig,\n side: resolveSide(side),\n spring: resolveSpring(spring),\n stacking: { ...DEFAULT_STACKING, ...stacking },\n };\n};\n","import { useEffect, useState } from \"react\";\nimport type { ResolvedConfig, Side } from \"./types\";\n/**\n * Returns true when viewport width is at or below the breakpoint.\n * SSR-safe: defaults to false (desktop).\n */\nexport const useIsMobile = (breakpoint: number): boolean => {\n const [isMobile, setIsMobile] = useState(false);\n useEffect(() => {\n const mql = window.matchMedia(`(max-width: ${breakpoint - 1}px)`);\n setIsMobile(mql.matches);\n const handler = (e: MediaQueryListEvent) => {\n setIsMobile(e.matches);\n };\n mql.addEventListener(\"change\", handler);\n return () => {\n mql.removeEventListener(\"change\", handler);\n };\n }, [breakpoint]);\n return isMobile;\n};\n/** Resolve the current side from config + viewport. */\nexport const useResolvedSide = (config: ResolvedConfig): Side => {\n const isMobile = useIsMobile(config.breakpoint);\n return isMobile ? config.side.mobile : config.side.desktop;\n};\n","import { useEffect, useState } from \"react\";\nimport type { RefObject } from \"react\";\nimport type { ResolvedConfig } from \"./types\";\n\nexport const usePanelHeight = (\n panelRef: RefObject<HTMLDivElement | null>,\n hasSnapPoints: boolean,\n): number => {\n const [height, setHeight] = useState(0);\n useEffect(() => {\n const el = panelRef.current;\n let observer: ResizeObserver | undefined;\n if (el !== null && hasSnapPoints) {\n setHeight(el.offsetHeight);\n observer = new ResizeObserver(([entry]) => {\n if (entry) {\n setHeight(entry.contentRect.height);\n }\n });\n observer.observe(el);\n }\n return () => {\n observer?.disconnect();\n };\n }, [panelRef, hasSnapPoints]);\n return height;\n};\nconst getViewportHeight = () =>\n typeof window === \"undefined\" ? 0 : (window.visualViewport?.height ?? window.innerHeight);\n\nexport const useViewportHeight = (active: boolean): number => {\n const [height, setHeight] = useState<number | undefined>(() =>\n typeof window === \"undefined\" ? undefined : getViewportHeight(),\n );\n useEffect(() => {\n const update = () => {\n setHeight(getViewportHeight());\n };\n const canListen = typeof window !== \"undefined\";\n if (canListen) {\n window.addEventListener(\"resize\", update);\n window.visualViewport?.addEventListener(\"resize\", update);\n }\n return () => {\n if (canListen) {\n window.removeEventListener(\"resize\", update);\n window.visualViewport?.removeEventListener(\"resize\", update);\n }\n };\n }, []);\n return active ? (height ?? 0) : 0;\n};\n\n/** Input types that don't summon the on-screen keyboard. */\nconst NON_TEXT_INPUT_TYPES = new Set([\n \"button\",\n \"checkbox\",\n \"color\",\n \"file\",\n \"hidden\",\n \"image\",\n \"radio\",\n \"range\",\n \"reset\",\n \"submit\",\n]);\n\n/** True for elements whose focus raises the on-screen keyboard. */\nconst isEditableElement = (el: Element | null): boolean => {\n if (!(el instanceof HTMLElement)) {\n return false;\n }\n if (el.isContentEditable) {\n return true;\n }\n if (el instanceof HTMLTextAreaElement) {\n return true;\n }\n if (el instanceof HTMLInputElement) {\n return !NON_TEXT_INPUT_TYPES.has(el.type);\n }\n return false;\n};\n\n/**\n * Height (px) the on-screen keyboard occupies while a field inside `containerRef`\n * is focused, else `0`. Derived from the gap between the layout viewport and the\n * (keyboard-shrunk, possibly panned) visual viewport.\n *\n * Focus-gated to fields *inside the container* so unrelated `visualViewport`\n * changes — Android URL-bar collapse, or typing into the page behind a\n * non-modal sheet — don't move the sheet, and zero while pinch-zoomed since a\n * shrunk visual viewport then isn't a keyboard. rAF-throttled because iOS\n * fires many resize events over the keyboard's open animation.\n */\nexport const useKeyboardInset = (\n active: boolean,\n containerRef: RefObject<HTMLElement | null>,\n): number => {\n const [inset, setInset] = useState(0);\n useEffect(() => {\n const canListen = active && typeof window !== \"undefined\";\n const container = containerRef.current;\n const viewport = canListen ? window.visualViewport : undefined;\n let frame = 0;\n let scheduled = false;\n const measure = () => {\n const el = document.activeElement;\n const focused = isEditableElement(el) && container !== null && container.contains(el);\n // Pinch-zoom also shrinks the visual viewport; that's not a keyboard.\n const zoomed = (viewport?.scale ?? 1) > 1;\n const visibleHeight = viewport?.height ?? window.innerHeight;\n // The keyboard occupies the gap below the visual viewport: layout height\n // minus the viewport's pan offset (iOS scrolls it down) minus its height.\n const gap = window.innerHeight - (viewport?.offsetTop ?? 0) - visibleHeight;\n setInset(focused && !zoomed ? Math.max(0, gap) : 0);\n };\n const schedule = () => {\n if (scheduled) {\n return;\n }\n scheduled = true;\n frame = window.requestAnimationFrame(() => {\n scheduled = false;\n measure();\n });\n };\n if (canListen) {\n container?.addEventListener(\"focusin\", schedule);\n container?.addEventListener(\"focusout\", schedule);\n viewport?.addEventListener(\"resize\", schedule, { passive: true });\n // offsetTop changes as iOS pans the visual viewport while the keyboard is up.\n viewport?.addEventListener(\"scroll\", schedule, { passive: true });\n // Re-measure on (re)activation — state persists across sheet close/reopen,\n // so a stale inset from the last session must be cleared.\n schedule();\n }\n return () => {\n if (frame !== 0) {\n window.cancelAnimationFrame(frame);\n }\n container?.removeEventListener(\"focusin\", schedule);\n container?.removeEventListener(\"focusout\", schedule);\n viewport?.removeEventListener(\"resize\", schedule);\n viewport?.removeEventListener(\"scroll\", schedule);\n };\n }, [active, containerRef]);\n return active ? inset : 0;\n};\nconst BODY_SCALE_TRANSITION =\n \"transform 500ms cubic-bezier(0.32, 0.72, 0, 1), border-radius 500ms cubic-bezier(0.32, 0.72, 0, 1)\";\n/** Fallback delay (transition duration + margin) if `transitionend` never fires. */\nconst BODY_SCALE_RESET_FALLBACK_MS = 600;\n\n/** Cancels a pending un-scale reset when the sheet reopens mid-animation. */\nlet cancelPendingBodyScaleReset: (() => void) | undefined;\n\nexport const useBodyScale = (\n config: ResolvedConfig,\n isOpen: boolean,\n prefersReducedMotion: boolean,\n) => {\n useEffect(() => {\n const wrapper = document.querySelector(\"[data-stacksheet-wrapper]\");\n const canScale =\n config.shouldScaleBackground && !prefersReducedMotion && wrapper instanceof HTMLElement;\n const scalable = canScale && isOpen ? wrapper : null;\n if (scalable !== null) {\n cancelPendingBodyScaleReset?.();\n scalable.style.transition = BODY_SCALE_TRANSITION;\n scalable.style.transform = `scale(${config.scaleBackgroundAmount})`;\n scalable.style.borderRadius = \"8px\";\n scalable.style.overflow = \"hidden\";\n scalable.style.transformOrigin = \"center top\";\n }\n return () => {\n if (scalable === null) {\n return;\n }\n // Closing (or unmounting): re-assert the transition so the un-scale\n // animates, clear the transform, and only remove the remaining inline\n // styles once the transition actually ends (with a timeout fallback).\n scalable.style.transition = BODY_SCALE_TRANSITION;\n scalable.style.transform = \"\";\n scalable.style.borderRadius = \"\";\n const controller = new AbortController();\n const { signal } = controller;\n const finish = () => {\n controller.abort();\n cancelPendingBodyScaleReset = undefined;\n scalable.style.transition = \"\";\n scalable.style.overflow = \"\";\n scalable.style.transformOrigin = \"\";\n };\n scalable.addEventListener(\n \"transitionend\",\n (event) => {\n if (event.target === scalable && event.propertyName === \"transform\") {\n finish();\n }\n },\n { signal },\n );\n const timeoutId = setTimeout(() => {\n if (!signal.aborted) {\n finish();\n }\n }, BODY_SCALE_RESET_FALLBACK_MS);\n signal.addEventListener(\"abort\", () => {\n clearTimeout(timeoutId);\n });\n cancelPendingBodyScaleReset = () => {\n controller.abort();\n cancelPendingBodyScaleReset = undefined;\n };\n };\n }, [isOpen, config.shouldScaleBackground, config.scaleBackgroundAmount, prefersReducedMotion]);\n};\n","import type { SnapPoint } from \"./types\";\n\nconst SNAP_POINT_RE = /^(?<value>\\d+(?:\\.\\d+)?)(?<unit>px|rem|em|vh|%)$/u;\n\nconst getRootFontSize = (): number =>\n typeof document === \"undefined\"\n ? 16\n : Number.parseFloat(getComputedStyle(document.documentElement).fontSize);\n\nconst resolveUnitPx = (value: number, unit: string, viewportHeight: number): number => {\n if (unit === \"px\") {\n return value;\n }\n if (unit === \"rem\" || unit === \"em\") {\n return value * getRootFontSize();\n }\n if (unit === \"vh\" || unit === \"%\") {\n return (value / 100) * viewportHeight;\n }\n return 0;\n};\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 */\nconst resolveSnapPointPx = (point: SnapPoint, viewportHeight: number): number => {\n if (typeof point === \"number\") {\n return point <= 1 ? point * viewportHeight : point;\n }\n if (typeof point === \"string\") {\n const match = SNAP_POINT_RE.exec(point);\n const rawValue = match?.groups?.value;\n const unit = match?.groups?.unit;\n if (rawValue === undefined || unit === undefined) {\n return 0;\n }\n return resolveUnitPx(Number.parseFloat(rawValue), unit, viewportHeight);\n }\n return 0;\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 const resolveSnapPoints = (points: SnapPoint[], viewportHeight: number): number[] => {\n if (points.length === 0) {\n return [];\n }\n const resolved: number[] = [];\n for (const point of points) {\n const px = resolveSnapPointPx(point, viewportHeight);\n if (px > 0) {\n resolved.push(px);\n }\n }\n // Sort ascending (smallest snap point first)\n resolved.sort((a, b) => a - b);\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 return deduped;\n};\n/** Velocity threshold (px/ms) for skipping intermediate snap points */\nconst SNAP_VELOCITY_THRESHOLD = 0.4;\n/** Max velocity to consider for snap offset calculation */\nconst MAX_SNAP_VELOCITY = 2;\n/** Multiplier to convert velocity to pixel offset for snap target */\nconst SNAP_VELOCITY_MULTIPLIER = 150;\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 const 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 // 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 // Current position = dragOffset from fully open\n const currentPos = dragOffset;\n if (sequential) {\n // Sequential mode: only snap to adjacent points\n // Positive velocity means dismissing.\n const direction = velocity > 0 ? 1 : -1;\n // Snap heights are ascending, so -1 moves toward the more closed point.\n const nextIndex = currentIndex - direction;\n if (nextIndex < 0) {\n // Dismiss.\n return -1;\n }\n if (nextIndex >= snapHeights.length) {\n // Fully open.\n return snapHeights.length - 1;\n }\n return nextIndex;\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 const projectedPos = currentPos + velocityOffset;\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 for (let i = 1; i < snapOffsets.length; i += 1) {\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 // 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 return bestIndex;\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 const 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 { getSnapOffset } from \"./snap-points\";\nimport type { getStackTransform, SlideValues } from \"./stacking\";\nimport type { Side, StacksheetClassNames } from \"./types\";\n\n// `header` is deprecated (the header bar is gone) and intentionally dropped\n// from the resolved shape — nothing applies it anymore.\nexport type ResolvedClassNames = Required<Omit<StacksheetClassNames, \"header\">>;\nconst EMPTY_CLASSNAMES: ResolvedClassNames = {\n backdrop: \"\",\n panel: \"\",\n};\nexport const resolveClassNames = (cn?: StacksheetClassNames): ResolvedClassNames => {\n if (!cn) {\n return EMPTY_CLASSNAMES;\n }\n return {\n backdrop: cn.backdrop ?? \"\",\n panel: cn.panel ?? \"\",\n };\n};\nexport const buildAriaProps = ({\n ariaLabel,\n hasDescription,\n hasTitle,\n isComposable,\n isModal,\n isTop,\n panelId,\n}: {\n ariaLabel: string;\n hasDescription: boolean;\n hasTitle: boolean;\n isComposable: boolean;\n isModal: boolean;\n isTop: boolean;\n panelId: string;\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 // Only reference the title element when a Sheet.Title is actually\n // mounted — otherwise fall back to the sheet's aria-label so the\n // dialog is never left with a dangling aria-labelledby.\n if (hasTitle) {\n props[\"aria-labelledby\"] = `${panelId}-title`;\n } else {\n props[\"aria-label\"] = ariaLabel;\n }\n if (hasDescription) {\n props[\"aria-describedby\"] = `${panelId}-desc`;\n }\n } else {\n props[\"aria-label\"] = ariaLabel;\n }\n return props;\n};\nexport const getDragTransform = (\n side: Side,\n offset: number,\n): {\n x?: number;\n y?: number;\n} => {\n if (offset === 0) {\n return {};\n }\n switch (side) {\n case \"right\": {\n return { x: offset };\n }\n case \"left\": {\n return { x: -offset };\n }\n case \"bottom\": {\n return { y: offset };\n }\n default: {\n return {};\n }\n }\n};\nexport const VISUAL_TWEEN = {\n duration: 0.25,\n ease: \"easeOut\" as const,\n type: \"tween\" as const,\n};\nconst SHADOW_SM = \"0px 1px 3px 0px rgba(0,0,0,0.06), 0px 6px 12px 0px rgba(0,0,0,0.06)\";\nconst SHADOW_LG =\n \"0px 8px 24px 0px rgba(0,0,0,0.06), 0px 24px 48px 0px rgba(0,0,0,0.04), 0px 48px 96px 0px rgba(0,0,0,0.03)\";\nexport const getShadow = (isNested: boolean): string => (isNested ? SHADOW_SM : SHADOW_LG);\n\n/**\n * Clear the on-screen keyboard. Plain sheets stay anchored at bottom: 0 and\n * pad their content up instead — the panel surface extends under the keyboard\n * (and iOS Safari's floating URL-pill chrome), so no backdrop gap ever shows\n * between sheet and keyboard, and measurement error hides behind the keyboard.\n * Snap sheets are transform-anchored, so they lift via `bottom` (not the\n * Motion `y` transform) and keep their viewport-driven sizing untouched.\n */\nconst getKeyboardClearance = (keyboardInset: number, padForKeyboard: boolean): CSSProperties => {\n if (keyboardInset <= 0) {\n return {};\n }\n return padForKeyboard ? { paddingBottom: keyboardInset } : { bottom: keyboardInset };\n};\n\nexport const buildPanelStyle = (\n panelStyles: CSSProperties,\n isTop: boolean,\n hasPanelClass: boolean,\n isDragging: boolean,\n keyboardInset: number,\n padForKeyboard: boolean,\n): CSSProperties => ({\n ...panelStyles,\n ...getKeyboardClearance(keyboardInset, padForKeyboard),\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});\nexport const buildPanelTransition = (\n isDragging: boolean,\n isTop: boolean,\n spring: Record<string, unknown>,\n stackSpring: Record<string, unknown>,\n) => {\n if (isDragging) {\n return { duration: 0, type: \"tween\" as const };\n }\n const base = isTop ? spring : stackSpring;\n return { ...base, borderRadius: VISUAL_TWEEN, boxShadow: VISUAL_TWEEN };\n};\nexport const 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};\nexport const 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};\nexport const 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};\nexport const buildAnimateTarget = (\n slideTarget: SlideValues,\n stackOffset: {\n x?: number;\n y?: number;\n },\n dragOffset: {\n x?: number;\n y?: number;\n },\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 ...animatedRadius,\n boxShadow: getShadow(!isTop),\n opacity: transform.opacity,\n scale: transform.scale,\n transition,\n };\n if (snapYOffset > 0) {\n return { ...base, y: (dragOffset.y ?? 0) + snapYOffset };\n }\n return base;\n};\nexport const getInitialRadius = (side: Side): Record<string, number> => {\n if (side === \"bottom\") {\n return {\n borderBottomLeftRadius: 0,\n borderBottomRightRadius: 0,\n borderTopLeftRadius: 0,\n borderTopRightRadius: 0,\n };\n }\n return { borderRadius: 0 };\n};\n","/** Elements that should never initiate a drag */\nexport const INTERACTIVE_TAGS = new Set([\"INPUT\", \"TEXTAREA\", \"SELECT\", \"BUTTON\", \"A\"]);\n\n/** Dead zone in px before committing to drag vs text selection */\nexport const DEAD_ZONE = 10;\n\n/** Max angle (degrees) from dismiss axis to qualify as drag intent */\nexport const MAX_ANGLE_DEG = 35;\n\n/** Rubber-band resistance factor for dragging past resting position */\nexport const RUBBER_BAND_FACTOR = 0.6;\n","import type { Side } from \"../types\";\nimport { INTERACTIVE_TAGS, MAX_ANGLE_DEG } from \"./drag-constants\";\nimport type { DragAxis, DragSign } from \"./drag-types\";\n\nexport const isInteractiveElement = (el: Element): boolean => {\n if (INTERACTIVE_TAGS.has(el.tagName)) {\n return true;\n }\n if (el instanceof HTMLElement && el.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 * Walk up from `el` to find the nearest scrollable ancestor.\n * Returns null if nothing is scrollable in the dismiss axis.\n */\nexport const findScrollableAncestor = (el: Element, axis: DragAxis): 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 * 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 */\nconst isAtScrollEdge = (el: Element, axis: DragAxis, sign: DragSign): 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 ? el.scrollTop <= 0 : el.scrollTop + el.clientHeight >= el.scrollHeight - 1;\n }\n return sign === 1 ? el.scrollLeft <= 0 : el.scrollLeft + el.clientWidth >= el.scrollWidth - 1;\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 */\nexport const getDismissAxis = (\n side: Side,\n): {\n axis: DragAxis;\n sign: DragSign;\n} => {\n switch (side) {\n case \"right\": {\n return { axis: \"x\", sign: 1 };\n }\n case \"left\": {\n return { axis: \"x\", sign: -1 };\n }\n case \"bottom\": {\n return { axis: \"y\", sign: 1 };\n }\n default: {\n return { axis: \"x\", sign: 1 };\n }\n }\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 */\nconst classifyGesture = (\n dx: number,\n dy: number,\n axis: DragAxis,\n sign: DragSign,\n): \"drag\" | \"none\" => {\n const absDx = Math.abs(dx);\n const absDy = Math.abs(dy);\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 if (angleDeg > MAX_ANGLE_DEG) {\n return \"none\";\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 return \"drag\";\n};\n/** Decide whether a pointer gesture commits as a drag or should be ignored. */\nexport const commitGesture = (\n dx: number,\n dy: number,\n axis: DragAxis,\n sign: DragSign,\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 !== null && !isAtScrollEdge(scrollEl, axis, sign)) {\n return \"none\";\n }\n return \"drag\";\n};\nexport const getPanelDimension = (panel: HTMLDivElement | null, axis: DragAxis): number => {\n if (!panel) {\n return 300;\n }\n return axis === \"x\" ? panel.offsetWidth : panel.offsetHeight;\n};\n","/** A single pointer sample recorded during a drag gesture. */\nexport interface VelocitySample {\n /** Drag offset in the dismiss direction (px) at sample time */\n offset: number;\n /** Timestamp in ms (Date.now()) */\n time: number;\n}\n\n/** Sliding window (ms) of samples used to compute release velocity. */\nexport const VELOCITY_WINDOW_MS = 100;\n\n/** Upper bound on retained samples — plenty for a 100ms window at 120Hz. */\nconst MAX_SAMPLES = 20;\n\n/**\n * Append a pointer sample, pruning entries that fall outside the sliding\n * window (plus a hard cap as a memory guard). Mutates and returns `samples`.\n */\nexport const appendVelocitySample = (\n samples: VelocitySample[],\n sample: VelocitySample,\n): VelocitySample[] => {\n samples.push(sample);\n const cutoff = sample.time - VELOCITY_WINDOW_MS;\n while (samples.length > MAX_SAMPLES || (samples.length > 2 && (samples[0]?.time ?? 0) < cutoff)) {\n samples.shift();\n }\n return samples;\n};\n\n/**\n * Compute release velocity (px/ms, positive = dismiss direction) from the\n * samples recorded within the sliding window before `releaseTime`.\n *\n * Using only recent samples means a pause followed by a flick reports the\n * flick's velocity — not the whole-gesture average, which would dilute it\n * to near zero.\n */\nexport const getReleaseVelocity = (samples: VelocitySample[], releaseTime: number): number => {\n const cutoff = releaseTime - VELOCITY_WINDOW_MS;\n const recent = samples.filter((sample) => sample.time >= cutoff);\n const [first] = recent;\n const last = recent.at(-1);\n if (first === undefined || last === undefined || last.time <= first.time) {\n return 0;\n }\n return (last.offset - first.offset) / (last.time - first.time);\n};\n","import { useEffect, useRef } from \"react\";\nimport type { RefObject } from \"react\";\nimport { findSnapTarget } from \"../snap-points\";\nimport { DEAD_ZONE, RUBBER_BAND_FACTOR } from \"./drag-constants\";\nimport {\n commitGesture,\n findScrollableAncestor,\n getDismissAxis,\n getPanelDimension,\n isInteractiveElement,\n} from \"./drag-geometry\";\nimport type { DragConfig, DragState } from \"./drag-types\";\nimport { appendVelocitySample, getReleaseVelocity } from \"./drag-velocity\";\nimport type { VelocitySample } from \"./drag-velocity\";\n\ntype DragCommit = \"drag\" | \"none\";\n\ninterface DragRefs {\n committedRef: RefObject<DragCommit | null>;\n offsetRef: RefObject<number>;\n samplesRef: RefObject<VelocitySample[]>;\n scrollTargetRef: RefObject<Element | null>;\n startRef: RefObject<{\n x: number;\n y: number;\n } | null>;\n}\n\nconst resetDragRefs = ({\n committedRef,\n offsetRef,\n samplesRef,\n scrollTargetRef,\n startRef,\n}: DragRefs) => {\n startRef.current = null;\n committedRef.current = null;\n offsetRef.current = 0;\n samplesRef.current = [];\n scrollTargetRef.current = null;\n};\n\nconst createDragHandlers = ({\n axis,\n config,\n onDragUpdate,\n panelRef,\n refs,\n sign,\n}: {\n axis: \"x\" | \"y\";\n config: DragConfig;\n onDragUpdate: (state: DragState) => void;\n panelRef: RefObject<HTMLDivElement | null>;\n refs: DragRefs;\n sign: 1 | -1;\n}) => {\n const dismiss = () => {\n if (config.isNested) {\n config.onPop();\n } else {\n config.onClose();\n }\n };\n const handlePointerDown = (e: PointerEvent) => {\n if (!config.enabled || e.button !== 0 || !(e.target instanceof Element)) {\n return;\n }\n const { target } = e;\n const isHandle = target.closest(\"[data-stacksheet-handle]\") !== null;\n if (!isHandle && isInteractiveElement(target)) {\n return;\n }\n refs.scrollTargetRef.current = isHandle ? null : findScrollableAncestor(target, axis);\n refs.startRef.current = { x: e.clientX, y: e.clientY };\n refs.committedRef.current = null;\n refs.offsetRef.current = 0;\n refs.samplesRef.current = [{ offset: 0, time: Date.now() }];\n // Pointer capture is deferred until the gesture commits as a drag —\n // capturing here would retarget plain taps away from non-native\n // clickable children (e.g. ARIA-pattern buttons), swallowing their clicks.\n };\n const handlePointerMove = (e: PointerEvent) => {\n if (refs.startRef.current === null) {\n return;\n }\n const dx = e.clientX - refs.startRef.current.x;\n const dy = e.clientY - refs.startRef.current.y;\n const dist = Math.hypot(dx, dy);\n if (refs.committedRef.current === null && dist < DEAD_ZONE) {\n return;\n }\n if (refs.committedRef.current === null) {\n refs.committedRef.current = commitGesture(dx, dy, axis, sign, refs.scrollTargetRef.current);\n if (refs.committedRef.current !== \"drag\") {\n refs.startRef.current = null;\n return;\n }\n // The gesture is now a real drag — capture so the panel keeps\n // receiving pointer events even when the pointer leaves it.\n if (e.currentTarget instanceof HTMLElement) {\n e.currentTarget.setPointerCapture(e.pointerId);\n }\n }\n if (refs.committedRef.current !== \"drag\") {\n return;\n }\n const rawOffset = axis === \"x\" ? dx : dy;\n const directional = rawOffset * sign;\n const clampedOffset =\n directional >= 0 ? directional : -Math.sqrt(Math.abs(directional)) * RUBBER_BAND_FACTOR;\n refs.offsetRef.current = clampedOffset;\n appendVelocitySample(refs.samplesRef.current, { offset: clampedOffset, time: Date.now() });\n onDragUpdate({ isDragging: true, offset: clampedOffset });\n e.preventDefault();\n };\n const handlePointerUp = () => {\n if (refs.startRef.current === null || refs.committedRef.current !== \"drag\") {\n resetDragRefs(refs);\n return;\n }\n const offset = Math.max(0, refs.offsetRef.current);\n // Release velocity comes from a sliding window of recent samples, so a\n // pause followed by a flick still dismisses (a whole-gesture average\n // would dilute the flick to near zero).\n const velocity = getReleaseVelocity(refs.samplesRef.current, Date.now());\n resetDragRefs(refs);\n const panelSize = getPanelDimension(panelRef.current, axis);\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({ isDragging: false, offset: 0 });\n }\n return;\n }\n const pastThreshold = offset / panelSize > config.closeThreshold;\n const fastEnough = velocity > config.velocityThreshold;\n if (pastThreshold || fastEnough) {\n dismiss();\n } else {\n onDragUpdate({ isDragging: false, offset: 0 });\n }\n };\n const handlePointerCancel = () => {\n resetDragRefs(refs);\n onDragUpdate({ isDragging: false, offset: 0 });\n };\n return { handlePointerCancel, handlePointerDown, handlePointerMove, handlePointerUp };\n};\n\n/**\n * Hook that manages drag gestures that can dismiss 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 const useDrag = (\n panelRef: RefObject<HTMLDivElement | null>,\n config: DragConfig,\n onDragUpdate: (state: DragState) => void,\n) => {\n const startRef = useRef<{\n x: number;\n y: number;\n } | null>(null);\n const committedRef = useRef<DragCommit | null>(null);\n const offsetRef = useRef(0);\n const samplesRef = useRef<VelocitySample[]>([]);\n const scrollTargetRef = useRef<Element | null>(null);\n const { axis, sign } = getDismissAxis(config.side);\n const refs = { committedRef, offsetRef, samplesRef, scrollTargetRef, startRef };\n const { handlePointerCancel, handlePointerDown, handlePointerMove, handlePointerUp } =\n createDragHandlers({ axis, config, onDragUpdate, panelRef, refs, sign });\n const handlersRef = useRef({\n handlePointerCancel,\n handlePointerDown,\n handlePointerMove,\n handlePointerUp,\n });\n handlersRef.current = {\n handlePointerCancel,\n handlePointerDown,\n handlePointerMove,\n handlePointerUp,\n };\n // Attach pointer events to the panel element\n useEffect(() => {\n const el = panelRef.current;\n const onPointerDown = (event: PointerEvent) => {\n handlersRef.current.handlePointerDown(event);\n };\n const onPointerMove = (event: PointerEvent) => {\n handlersRef.current.handlePointerMove(event);\n };\n const onPointerUp = () => {\n handlersRef.current.handlePointerUp();\n };\n const onPointerCancel = () => {\n handlersRef.current.handlePointerCancel();\n };\n const canListen = el !== null && config.enabled;\n if (canListen) {\n el.addEventListener(\"pointerdown\", onPointerDown);\n el.addEventListener(\"pointermove\", onPointerMove);\n el.addEventListener(\"pointerup\", onPointerUp);\n el.addEventListener(\"pointercancel\", onPointerCancel);\n }\n return () => {\n if (canListen) {\n el.removeEventListener(\"pointerdown\", onPointerDown);\n el.removeEventListener(\"pointermove\", onPointerMove);\n el.removeEventListener(\"pointerup\", onPointerUp);\n el.removeEventListener(\"pointercancel\", onPointerCancel);\n }\n };\n }, [panelRef, config.enabled]);\n};\n","import { createContext, use } from \"react\";\nimport type { Side } from \"./types\";\n\nexport interface SheetPanelContextValue {\n /** Pop the top sheet (go back one level) */\n back: () => void;\n /** Close the entire sheet stack */\n close: () => void;\n /** Whether a Sheet.Description is mounted inside this panel */\n hasDescription: boolean;\n /** Whether a Sheet.Title is mounted inside this panel */\n hasTitle: boolean;\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 /** Called by Sheet.Description on mount to register its presence */\n registerDescription: () => () => void;\n /** Called by Sheet.Title on mount to register its presence */\n registerTitle: () => () => void;\n /** Current resolved side (left/right/bottom) */\n side: Side;\n}\nexport const SheetPanelContext = createContext<SheetPanelContextValue | null>(null);\n/**\n * Access the current sheet panel's context.\n * Must be called inside a component rendered by the sheet stack.\n */\nexport const useSheetPanel = (): SheetPanelContextValue => {\n const ctx = use(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 { CSSProperties } from \"react\";\nimport type { ResolvedConfig, Side, StackingConfig } from \"./types\";\n\n/**\n * Resting height of a bottom sheet. `dvh` tracks the dynamic viewport on iOS\n * Safari (accounts for browser chrome). Shared so the keyboard-inset `calc()`\n * in `buildPanelStyle` can't drift from the panel's base height.\n */\nexport const BOTTOM_SHEET_HEIGHT = \"85dvh\";\n// ── Depth transforms ────────────────────────────\nexport interface StackTransform {\n borderRadius: number;\n offset: number;\n opacity: number;\n scale: number;\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 const getStackTransform = (depth: number, stacking: StackingConfig): StackTransform => {\n if (depth <= 0) {\n return { borderRadius: 0, offset: 0, opacity: 1, scale: 1 };\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 return {\n borderRadius: stacking.radius,\n offset: visualDepth * stacking.offsetStep,\n opacity: beyondThreshold ? 0 : Math.max(0, 1 - visualDepth * stacking.opacityStep),\n scale: Math.max(0.5, 1 - visualDepth * stacking.scaleStep),\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 const 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 borderBottomLeftRadius: 0,\n borderBottomRightRadius: 0,\n borderTopLeftRadius: radius,\n borderTopRightRadius: radius,\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// ── Slide directions ────────────────────────────\nexport interface SlideValues {\n x?: string | number;\n y?: string | number;\n}\n/** Motion initial/exit values for sliding from the given side. */\nexport const getSlideFrom = (side: string): SlideValues => {\n switch (side) {\n case \"right\": {\n return { x: \"100%\" };\n }\n case \"left\": {\n return { x: \"-100%\" };\n }\n case \"bottom\": {\n return { y: \"100%\" };\n }\n default: {\n return { x: \"100%\" };\n }\n }\n};\n/** Motion animate target — the resting position. */\nexport const getSlideTarget = (): SlideValues => ({ x: 0, y: 0 });\n/** Translate offset that pushes stacked panels away from the stack edge. */\nexport const getStackOffset = (\n side: string,\n offset: number,\n): {\n x?: number;\n y?: number;\n} => {\n if (offset === 0) {\n return {};\n }\n switch (side) {\n case \"right\": {\n return { x: -offset };\n }\n case \"left\": {\n return { x: offset };\n }\n case \"bottom\": {\n return { y: -offset };\n }\n default: {\n return {};\n }\n }\n};\n// ── Transform origin ────────────────────────────\n/** Opposite-side origin so stacked panels recede away from the stack edge. */\nconst 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// ── Panel positioning ───────────────────────────\n/**\n * Fixed-position styles for a panel, accounting for side, width, and depth.\n */\nexport const getPanelStyles = (\n side: Side,\n config: ResolvedConfig,\n index: number,\n): CSSProperties => {\n const { width, maxWidth, zIndex } = config;\n const base: CSSProperties = {\n display: \"flex\",\n flexDirection: \"column\",\n // The panel is focused programmatically on open (to move focus into the\n // dialog); it's not a keyboard tab stop, so suppress the container ring.\n outline: \"none\",\n position: \"fixed\",\n transformOrigin: getTransformOrigin(side),\n willChange: \"transform\",\n zIndex: zIndex + 10 + index,\n };\n if (side === \"bottom\") {\n return {\n ...base,\n bottom: 0,\n // dvh tracks the dynamic viewport on iOS Safari (accounts for browser chrome).\n height: BOTTOM_SHEET_HEIGHT,\n left: 0,\n // borderRadius is animated via Motion's animate prop for scale correction\n maxHeight: BOTTOM_SHEET_HEIGHT,\n right: 0,\n };\n }\n // Left or right side panel\n const sideStyles: CSSProperties =\n side === \"right\" ? { bottom: 0, right: 0, top: 0 } : { bottom: 0, left: 0, top: 0 };\n return {\n ...base,\n ...sideStyles,\n maxWidth,\n width,\n };\n};\n","/** Inline SVG icons — no external dependency */\nexport const ArrowLeftIcon = () => (\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);\nexport const XIcon = () => (\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","import { ArrowLeftIcon, XIcon } from \"../icons\";\nimport type { HeaderRenderProps } from \"../types\";\n\n// No header bar: back and close float in the panel corners so there is no\n// row to fill and no divider. The title lives in the sheet's own content.\nexport const DefaultHeader = ({ isNested, onBack, onClose }: HeaderRenderProps) => (\n <>\n {isNested && (\n <button\n aria-label=\"Back\"\n className=\"absolute left-2 top-2 z-20 flex min-h-11 min-w-11 cursor-pointer items-center justify-center rounded-md border-none bg-transparent p-0 text-inherit opacity-50 transition-opacity duration-150 hover:opacity-100\"\n onClick={onBack}\n type=\"button\"\n >\n <ArrowLeftIcon />\n </button>\n )}\n <button\n aria-label=\"Close\"\n className=\"absolute right-2 top-2 z-20 flex min-h-11 min-w-11 cursor-pointer items-center justify-center rounded-md border-none bg-transparent p-0 text-inherit opacity-50 transition-opacity duration-150 hover:opacity-100\"\n onClick={onClose}\n type=\"button\"\n >\n <XIcon />\n </button>\n </>\n);\n","import type { ComponentType, ReactNode } from \"react\";\n\nimport type { HeaderRenderProps } from \"../types\";\nimport { DefaultHeader } from \"./default-header\";\n\nexport const PanelInnerContent = ({\n isComposable,\n shouldRender,\n Content,\n data,\n renderHeader,\n headerProps,\n}: {\n isComposable: boolean;\n shouldRender: boolean;\n Content: ComponentType<Record<string, unknown>> | undefined;\n data: Record<string, unknown>;\n renderHeader?: false | ((props: HeaderRenderProps) => ReactNode);\n headerProps: HeaderRenderProps;\n}) => {\n if (isComposable) {\n return shouldRender && Content !== undefined ? <Content {...data} /> : null;\n }\n const customHeader =\n renderHeader !== undefined && renderHeader !== false ? renderHeader : undefined;\n\n return (\n <>\n {customHeader === undefined ? <DefaultHeader {...headerProps} /> : customHeader(headerProps)}\n {shouldRender && Content !== undefined && (\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\nPanelInnerContent.displayName = \"PanelInnerContent\";\n","import { FocusTrap } from \"focus-trap-react\";\nimport type { ReactNode, RefObject } from \"react\";\nimport { useSyncExternalStore } from \"react\";\n\nconst LAYERED_MODAL_SELECTORS = [\n '[role=\"dialog\"][data-state=\"open\"]',\n '[role=\"alertdialog\"][data-state=\"open\"]',\n \"[data-radix-popper-content-wrapper]\",\n \"[data-radix-focus-guard]\",\n].join(\", \");\n\nconst subscribeToFocusTarget = (onStoreChange: () => void): (() => void) => {\n document.addEventListener(\"focusin\", onStoreChange, true);\n return () => {\n document.removeEventListener(\"focusin\", onStoreChange, true);\n };\n};\nconst getServerLayeredModalFocused = (): boolean => false;\nconst getLayeredModalFocused = (): boolean => {\n if (typeof document === \"undefined\") {\n return false;\n }\n const target = document.activeElement;\n return (\n !!target &&\n target !== document.body &&\n target instanceof Element &&\n target.closest(LAYERED_MODAL_SELECTORS) !== null\n );\n};\nconst useLayeredModalFocused = (active: boolean): boolean => {\n const layered = useSyncExternalStore(\n subscribeToFocusTarget,\n getLayeredModalFocused,\n getServerLayeredModalFocused,\n );\n return active && layered;\n};\n\nexport const ModalFocusTrap = ({\n enabled,\n active,\n fallbackRef,\n children,\n}: {\n enabled: boolean;\n active: boolean;\n fallbackRef: RefObject<HTMLElement | null>;\n children: ReactNode;\n}): ReactNode => {\n const paused = useLayeredModalFocused(enabled && active);\n if (!enabled) {\n return children;\n }\n return (\n <FocusTrap\n active={active}\n focusTrapOptions={{\n allowOutsideClick: true,\n escapeDeactivates: false,\n fallbackFocus: () => {\n if (fallbackRef.current !== null) {\n return fallbackRef.current;\n }\n return document.body;\n },\n // Focus the panel element itself (it has tabIndex={-1}) so screen\n // readers announce the dialog when it opens.\n initialFocus: () => fallbackRef.current ?? undefined,\n returnFocusOnDeactivate: true,\n }}\n paused={paused}\n >\n {children}\n </FocusTrap>\n );\n};\n","import { joinClassNames } from \"@patternmode/system\";\nimport { m } from \"motion/react\";\nimport type { CSSProperties } from \"react\";\nimport type { HandlePosition, Side } from \"../types\";\n\nexport const BottomHandle = ({\n onDismiss,\n position = \"inside\",\n}: {\n onDismiss?: () => void;\n position?: HandlePosition;\n}) => (\n <button\n aria-label=\"Dismiss\"\n className={joinClassNames(\n // text-inherit matters: the pill is bg-current/15, and without it the\n // button falls back to the UA color — iOS Safari's system blue.\n \"absolute inset-x-0 z-10 flex w-full cursor-grab touch-none items-center justify-center border-none bg-transparent text-inherit\",\n // `outside` floats the pill above the sheet on the backdrop; `inside`\n // tucks it just below the top edge.\n position === \"outside\" ? \"bottom-full pt-1 pb-2\" : \"top-0 pt-2.5 pb-2\",\n )}\n data-stacksheet-handle=\"\"\n onClick={onDismiss}\n type=\"button\"\n >\n <div aria-hidden=\"true\" className=\"h-[5px] w-9 rounded-full bg-current/15\" />\n </button>\n);\nexport const SideHandle = ({\n side,\n isHovered,\n onDismiss,\n}: {\n side: Side;\n isHovered: boolean;\n onDismiss?: () => void;\n}) => {\n const position: CSSProperties = side === \"right\" ? { right: \"100%\" } : { left: \"100%\" };\n return (\n <m.button\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 border-none bg-transparent p-0 text-inherit\"\n data-stacksheet-handle=\"\"\n onClick={onDismiss}\n style={position}\n transition={{ duration: isHovered ? 0.15 : 0.4, ease: \"easeOut\" }}\n type=\"button\"\n >\n <div aria-hidden=\"true\" className=\"h-8 w-1 rounded-full bg-current/20\" />\n </m.button>\n );\n};\n","import type { ReactNode } from \"react\";\nimport type { HeaderRenderProps, StacksheetLayout } from \"../types\";\n\nexport const resolvePanelLayout = (\n layout: StacksheetLayout | undefined,\n renderHeader?: false | ((props: HeaderRenderProps) => ReactNode),\n): StacksheetLayout => {\n if (layout) {\n return layout;\n }\n return renderHeader === false ? \"composable\" : \"classic\";\n};\n","import { m } from \"motion/react\";\nimport { useCallback, useEffect, useMemo, useRef, useState } from \"react\";\nimport type { ReactNode, RefObject } from \"react\";\n\nimport type { DragState } from \"../Drag/drag-types\";\nimport { useDrag } from \"../Drag/use-drag\";\nimport { SheetPanelContext } from \"../panel-context\";\nimport { usePanelHeight } from \"../renderer-effects\";\nimport {\n buildAnimateTarget,\n buildAriaProps,\n buildPanelStyle,\n buildPanelTransition,\n computeSnapYOffset,\n getDragTransform,\n getInitialRadius,\n getShadow,\n resolveSlideFrom,\n VISUAL_TWEEN,\n} from \"../renderer-helpers\";\nimport {\n getAnimatedBorderRadius,\n getPanelStyles,\n getStackOffset,\n getStackTransform,\n} from \"../stacking\";\nimport type { HandlePosition, HeaderRenderProps } from \"../types\";\nimport { PanelInnerContent } from \"./sheet-panel-content\";\nimport { ModalFocusTrap } from \"./sheet-panel-focus\";\nimport { BottomHandle, SideHandle } from \"./sheet-panel-handles\";\nimport { resolvePanelLayout } from \"./sheet-panel-layout\";\nimport type { SheetPanelProps } from \"./sheet-panel-types\";\n\nconst getPanelAriaLabel = (item: SheetPanelProps[\"item\"], fallbackLabel: string): string =>\n item.ariaLabel ??\n (typeof item.data?.__ariaLabel === \"string\" ? item.data.__ariaLabel : undefined) ??\n fallbackLabel;\n\nconst getPanelHoverProps = (enabled: boolean, setIsHovered: (value: boolean) => void) =>\n enabled\n ? {\n onBlur: () => {\n setIsHovered(false);\n },\n onFocus: () => {\n setIsHovered(true);\n },\n onMouseEnter: () => {\n setIsHovered(true);\n },\n onMouseLeave: () => {\n setIsHovered(false);\n },\n }\n : {};\n\nconst getInactivePanelProps = (isTop: boolean) =>\n isTop ? {} : { \"aria-hidden\": \"true\" as const, inert: true };\n\nconst getHeaderProps = ({\n close,\n isNested,\n pop,\n side,\n}: Pick<SheetPanelProps, \"close\" | \"isNested\" | \"pop\" | \"side\">): HeaderRenderProps => ({\n isNested,\n onBack: pop,\n onClose: close,\n side,\n});\n\nconst getPanelContext = ({\n close,\n hasDescription,\n hasTitle,\n isNested,\n isTop,\n panelId,\n pop,\n registerDescription,\n registerTitle,\n side,\n}: Pick<SheetPanelProps, \"close\" | \"isNested\" | \"isTop\" | \"pop\" | \"side\"> & {\n hasDescription: boolean;\n hasTitle: boolean;\n panelId: string;\n registerDescription: () => () => void;\n registerTitle: () => () => void;\n}) => ({\n back: pop,\n close,\n hasDescription,\n hasTitle,\n isNested,\n isTop,\n panelId,\n registerDescription,\n registerTitle,\n side,\n});\n\nconst getOptionalSideHandle = ({\n isHovered,\n onDismiss,\n show,\n side,\n}: {\n isHovered: boolean;\n onDismiss: () => void;\n show: boolean;\n side: SheetPanelProps[\"side\"];\n}): ReactNode =>\n show ? <SideHandle isHovered={isHovered} onDismiss={onDismiss} side={side} /> : null;\n\nconst getOptionalBottomHandle = (\n show: boolean,\n onDismiss: () => void,\n position: HandlePosition,\n): ReactNode => (show ? <BottomHandle onDismiss={onDismiss} position={position} /> : null);\n\nconst completeOpeningAnimation = (\n hasEnteredRef: RefObject<boolean>,\n isTop: boolean,\n onOpenCompleteRef: RefObject<(() => void) | undefined>,\n) => {\n if (isTop && !hasEnteredRef.current) {\n hasEnteredRef.current = true;\n onOpenCompleteRef.current?.();\n }\n};\n\nconst useOpeningCompletion = (isTop: boolean, onOpenComplete: (() => void) | undefined) => {\n const hasEnteredRef = useRef(false);\n const onOpenCompleteRef = useRef(onOpenComplete);\n\n if (!isTop && hasEnteredRef.current) {\n hasEnteredRef.current = false;\n }\n useEffect(() => {\n onOpenCompleteRef.current = onOpenComplete;\n }, [onOpenComplete]);\n\n return () => {\n completeOpeningAnimation(hasEnteredRef, isTop, onOpenCompleteRef);\n };\n};\n\nconst useSheetPanelDrag = (\n {\n activeSnapIndex,\n config,\n isNested,\n isTop,\n onSnap,\n prefersReducedMotion,\n side,\n snapHeights,\n swipeClose,\n swipePop,\n }: SheetPanelProps,\n panelRef: RefObject<HTMLDivElement | null>,\n): DragState => {\n const [dragState, setDragState] = useState<DragState>({\n isDragging: false,\n offset: 0,\n });\n\n useDrag(\n panelRef,\n {\n activeSnapIndex,\n closeThreshold: config.closeThreshold,\n enabled: isTop && config.drag && config.dismissible && !prefersReducedMotion,\n isNested,\n onClose: swipeClose,\n onPop: swipePop,\n onSnap,\n sequential: config.snapToSequentialPoints,\n side,\n snapHeights,\n velocityThreshold: config.velocityThreshold,\n },\n setDragState,\n );\n\n return dragState;\n};\n\nconst useSheetPanelContext = (\n { close, isNested, isTop, pop, side }: SheetPanelProps,\n panelId: string,\n) => {\n const [hasDescription, setHasDescription] = useState(false);\n const [hasTitle, setHasTitle] = useState(false);\n // oxlint-disable-next-line react-doctor/react-compiler-no-manual-memoization -- the library build does not run React Compiler; a stable identity keeps Sheet.Description effects from re-running on every drag re-render.\n const registerDescription = useCallback(() => {\n setHasDescription(true);\n return () => {\n setHasDescription(false);\n };\n }, []);\n // oxlint-disable-next-line react-doctor/react-compiler-no-manual-memoization -- the library build does not run React Compiler; a stable identity keeps Sheet.Title effects from re-running on every drag re-render.\n const registerTitle = useCallback(() => {\n setHasTitle(true);\n return () => {\n setHasTitle(false);\n };\n }, []);\n // Memoized so drag-driven re-renders don't churn the context value (and\n // with it every Sheet.* consumer's effects).\n // oxlint-disable-next-line react-doctor/react-compiler-no-manual-memoization -- the library build does not run React Compiler; without useMemo the panel context is a new object on every pointermove re-render.\n const panelContext = useMemo(\n () =>\n getPanelContext({\n close,\n hasDescription,\n hasTitle,\n isNested,\n isTop,\n panelId,\n pop,\n registerDescription,\n registerTitle,\n side,\n }),\n [\n close,\n hasDescription,\n hasTitle,\n isNested,\n isTop,\n panelId,\n pop,\n registerDescription,\n registerTitle,\n side,\n ],\n );\n\n return { hasDescription, hasTitle, panelContext };\n};\n\nconst useSheetPanelModel = (props: SheetPanelProps) => {\n const {\n item,\n index,\n depth,\n isTop,\n isNested,\n side,\n config,\n classNames,\n pop,\n close,\n snapHeights,\n keyboardInset,\n activeSnapIndex,\n layout,\n renderHeader,\n slideFrom,\n slideTarget,\n spring,\n stackSpring,\n } = props;\n const panelRef = useRef<HTMLDivElement>(null);\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 const handleAnimationComplete = useOpeningCompletion(isTop, config.onOpenComplete);\n const dragState = useSheetPanelDrag(props, panelRef);\n\n const ariaLabel = getPanelAriaLabel(item, config.ariaLabel);\n\n const panelId = `stacksheet-${item.id}`;\n const { hasDescription, hasTitle, panelContext } = useSheetPanelContext(props, panelId);\n\n const panelLayout = resolvePanelLayout(layout, renderHeader);\n const isComposable = panelLayout === \"composable\";\n const hasPanelClass = classNames.panel !== \"\";\n const dragOffset = getDragTransform(side, dragState.offset);\n // Only the top bottom-sheet reacts to the keyboard (background panels are\n // inert and can't hold focus). Plain sheets pad content above the keyboard;\n // snap sheets lift instead — they already track the shrunk visual viewport.\n const activeKeyboardInset = isTop && side === \"bottom\" ? keyboardInset : 0;\n const panelStyle = buildPanelStyle(\n panelStyles,\n isTop,\n hasPanelClass,\n dragState.isDragging,\n activeKeyboardInset,\n snapHeights.length === 0,\n );\n\n const headerProps = getHeaderProps({ close, isNested, pop, side });\n\n const ariaProps = buildAriaProps({\n ariaLabel,\n hasDescription,\n hasTitle,\n isComposable,\n isModal: config.modal,\n isTop,\n panelId,\n });\n\n const transition = buildPanelTransition(dragState.isDragging, isTop, spring, stackSpring);\n\n const animatedRadius = getAnimatedBorderRadius(side, depth, config.stacking);\n const snapYOffset = computeSnapYOffset(side, snapHeights, activeSnapIndex, measuredHeight);\n const resolvedSlideFrom = resolveSlideFrom(side, slideFrom, measuredHeight);\n\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 // Composable layouts own their chrome — Sheet.Handle renders the pill, so\n // the auto handle would duplicate it.\n const showBottomHandle = isTop && side === \"bottom\" && !isComposable;\n const dismiss = isNested ? pop : close;\n const sideHandle = getOptionalSideHandle({\n isHovered,\n onDismiss: dismiss,\n show: showSideHandle,\n side,\n });\n const bottomHandle = getOptionalBottomHandle(showBottomHandle, dismiss, config.handle);\n // Outside handles must render above the overflow-hidden content wrapper, so\n // the panel places them at the panel level rather than inside it.\n const bottomHandleOutside = showBottomHandle && config.handle === \"outside\";\n const hoverProps = getPanelHoverProps(showSideHandle, setIsHovered);\n const inactivePanelProps = getInactivePanelProps(isTop);\n\n return {\n animateTarget,\n ariaProps,\n bottomHandle,\n bottomHandleOutside,\n handleAnimationComplete,\n headerProps,\n hoverProps,\n inactivePanelProps,\n initialRadius,\n isComposable,\n panelContext,\n panelRef,\n panelStyle,\n resolvedSlideFrom,\n sideHandle,\n };\n};\n\nexport const SheetPanel = (props: SheetPanelProps) => {\n const {\n item,\n isTop,\n config,\n classNames,\n Content,\n shouldRender,\n renderHeader,\n prefersReducedMotion,\n } = props;\n const {\n animateTarget,\n ariaProps,\n bottomHandle,\n bottomHandleOutside,\n handleAnimationComplete,\n headerProps,\n hoverProps,\n inactivePanelProps,\n initialRadius,\n isComposable,\n panelContext,\n panelRef,\n panelStyle,\n resolvedSlideFrom,\n sideHandle,\n } = useSheetPanelModel(props);\n\n const panelContent = (\n <m.div\n animate={animateTarget}\n className={classNames.panel || undefined}\n exit={{\n ...resolvedSlideFrom,\n boxShadow: getShadow(false),\n opacity: 0.6,\n transition: {\n boxShadow: VISUAL_TWEEN,\n duration: prefersReducedMotion ? 0 : 0.24,\n ease: \"easeOut\",\n type: \"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 ref={panelRef}\n style={panelStyle}\n tabIndex={isTop ? -1 : undefined}\n {...hoverProps}\n {...inactivePanelProps}\n {...ariaProps}\n >\n {sideHandle}\n {bottomHandleOutside ? bottomHandle : null}\n <div className=\"relative flex min-h-0 flex-1 flex-col overflow-hidden rounded-[inherit]\">\n {bottomHandleOutside ? null : bottomHandle}\n <PanelInnerContent\n Content={Content}\n data={item.data}\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 active={isTop} enabled={config.modal} fallbackRef={panelRef}>\n {panelContent}\n </ModalFocusTrap>\n </SheetPanelContext.Provider>\n );\n};\n","import { AnimatePresence, domMax, LazyMotion, m, useReducedMotion } from \"motion/react\";\nimport { useEffect, useRef, useState } from \"react\";\nimport type { ComponentType, CSSProperties, ReactNode, RefObject } from \"react\";\nimport { RemoveScroll } from \"react-remove-scroll\";\nimport type { StoreApi } from \"zustand\";\nimport { useStore } from \"zustand\";\nimport { useShallow } from \"zustand/react/shallow\";\nimport { useResolvedSide } from \"./media\";\nimport { useBodyScale, useKeyboardInset, useViewportHeight } from \"./renderer-effects\";\nimport { resolveClassNames } from \"./renderer-helpers\";\nimport { SheetPanel } from \"./sheet-panel\";\nimport { resolveSnapPoints } from \"./snap-points\";\nimport { getSlideFrom, getSlideTarget } from \"./stacking\";\nimport type {\n CloseReason,\n ContentMap,\n HeaderRenderProps,\n ResolvedConfig,\n SheetActions,\n Side,\n StacksheetClassNames,\n StacksheetLayout,\n StacksheetSnapshot,\n} from \"./types\";\n\n// CloseWatcher — ambient type for browsers that support it (Chromium 120+)\ndeclare global {\n var CloseWatcher:\n | (new () => {\n addEventListener: (type: \"close\", listener: () => void) => void;\n destroy: () => void;\n removeEventListener: (type: \"close\", listener: () => void) => void;\n })\n | undefined;\n}\n\nconst handleBackdropExitComplete = () => {\n requestAnimationFrame(() => {\n void document.body.offsetHeight;\n });\n};\n\nconst getResolvedSnapHeights = (\n side: Side,\n snapPoints: ResolvedConfig[\"snapPoints\"],\n viewportHeight: number,\n) =>\n side === \"bottom\" && snapPoints.length > 0 ? resolveSnapPoints(snapPoints, viewportHeight) : [];\n\nconst getActiveInternalSnapIndex = ({\n defaultSnapIndex,\n internalSnap,\n snapContext,\n snapHeights,\n}: {\n defaultSnapIndex: number;\n internalSnap: { context: string; index: number; snapCount: number };\n snapContext: string;\n snapHeights: number[];\n}) =>\n internalSnap.context === snapContext && internalSnap.snapCount === snapHeights.length\n ? internalSnap.index\n : defaultSnapIndex;\n\nconst getMotionSpring = (prefersReducedMotion: boolean, config: ResolvedConfig) =>\n prefersReducedMotion\n ? ({ duration: 0, type: \"tween\" as const } as const)\n : ({\n damping: config.spring.damping,\n mass: config.spring.mass,\n stiffness: config.spring.stiffness,\n type: \"spring\" as const,\n } as const);\n\nconst getBackdropStyle = (config: ResolvedConfig, hasBackdropClass: boolean): CSSProperties => ({\n cursor: config.closeOnBackdrop && config.dismissible ? \"pointer\" : undefined,\n willChange: \"opacity\",\n zIndex: config.zIndex,\n ...(hasBackdropClass ? {} : { background: \"var(--overlay, rgba(0, 0, 0, 0.15))\" }),\n});\n\ninterface SheetRendererProps<TMap extends object> {\n classNames?: StacksheetClassNames;\n /** Ad-hoc component map (type key → component) */\n componentMap: Map<string, ComponentType<Record<string, unknown>>>;\n config: ResolvedConfig;\n layout?: StacksheetLayout;\n renderHeader?: false | ((props: HeaderRenderProps) => ReactNode);\n sheets?: ContentMap<TMap>;\n store: StoreApi<StacksheetSnapshot<TMap> & SheetActions<TMap>>;\n}\n\nconst isContentComponent = (content: unknown): content is ComponentType<Record<string, unknown>> =>\n typeof content === \"function\";\n\nconst getStaticContent = <TMap extends object>(\n sheets: ContentMap<TMap> | undefined,\n type: string,\n): ComponentType<Record<string, unknown>> | undefined => {\n if (sheets === undefined) {\n return undefined;\n }\n const match = Object.entries(sheets).find(([sheetType]) => sheetType === type);\n const content = match?.[1];\n return isContentComponent(content) ? content : undefined;\n};\n\nconst useRendererStore = <TMap extends object>(\n store: StoreApi<StacksheetSnapshot<TMap> & SheetActions<TMap>>,\n) => {\n const isOpen = useStore(store, (s) => s.isOpen);\n const stack = useStore(store, (s) => s.stack);\n const { rawClose, rawPop } = useStore(\n store,\n useShallow((s) => ({\n rawClose: s.close,\n rawPop: s.pop,\n })),\n );\n return { isOpen, rawClose, rawPop, stack };\n};\n\nconst useSnapState = (\n config: ResolvedConfig,\n isOpen: boolean,\n side: Side,\n stack: StacksheetSnapshot<object>[\"stack\"],\n) => {\n const viewportHeight = useViewportHeight(\n isOpen && side === \"bottom\" && config.snapPoints.length > 0,\n );\n const snapHeights = getResolvedSnapHeights(side, config.snapPoints, viewportHeight);\n const snapContext = isOpen ? stack.map((item) => item.id).join(\"\\u0000\") : \"\";\n const defaultSnapIndex = snapHeights.length > 0 ? snapHeights.length - 1 : 0;\n const [internalSnap, setInternalSnap] = useState({\n context: \"\",\n index: defaultSnapIndex,\n snapCount: snapHeights.length,\n });\n const internalSnapIndex = getActiveInternalSnapIndex({\n defaultSnapIndex,\n internalSnap,\n snapContext,\n snapHeights,\n });\n const activeSnapIndex = config.snapPointIndex ?? internalSnapIndex;\n const handleSnap = (index: number) => {\n setInternalSnap({\n context: snapContext,\n index,\n snapCount: snapHeights.length,\n });\n config.onSnapPointChange?.(index);\n };\n return { activeSnapIndex, handleSnap, snapHeights };\n};\n\nconst usePanelKeyboardInset = (config: ResolvedConfig, isOpen: boolean, side: Side) => {\n const panelWrapperRef = useRef<HTMLDivElement>(null);\n const keyboardInset = useKeyboardInset(\n isOpen && side === \"bottom\" && config.repositionInputs,\n panelWrapperRef,\n );\n return { keyboardInset, panelWrapperRef };\n};\n\nconst useCloseControls = (rawClose: () => void, rawPop: () => void) => {\n const closeReasonRef = useRef<CloseReason>(\"programmatic\");\n const closeWith = (reason: CloseReason) => {\n closeReasonRef.current = reason;\n rawClose();\n };\n const popWith = (reason: CloseReason) => {\n closeReasonRef.current = reason;\n rawPop();\n };\n return {\n close: () => {\n closeWith(\"programmatic\");\n },\n closeReasonRef,\n closeWith,\n pop: () => {\n popWith(\"programmatic\");\n },\n popWith,\n };\n};\n\nconst useFocusRestore = (isOpen: boolean) => {\n const triggerRef = useRef<Element | null>(null);\n const wasOpenRef = useRef(false);\n useEffect(() => {\n if (isOpen && !wasOpenRef.current) {\n triggerRef.current = document.activeElement;\n } else if (!isOpen && wasOpenRef.current) {\n const el = triggerRef.current;\n if (el && el instanceof HTMLElement && el !== document.body && el.tagName !== \"BODY\") {\n el.focus();\n }\n triggerRef.current = null;\n }\n wasOpenRef.current = isOpen;\n }, [isOpen]);\n};\n\nconst dismissFromEscape = ({\n closeReasonRef,\n rawClose,\n rawPop,\n stackLengthRef,\n}: {\n closeReasonRef: RefObject<CloseReason>;\n rawClose: () => void;\n rawPop: () => void;\n stackLengthRef: RefObject<number>;\n}) => {\n closeReasonRef.current = \"escape\";\n if (stackLengthRef.current > 1) {\n rawPop();\n } else {\n rawClose();\n }\n};\n\nconst useDismissalEffects = ({\n closeReasonRef,\n config,\n isOpen,\n rawClose,\n rawPop,\n stackLength,\n}: {\n closeReasonRef: RefObject<CloseReason>;\n config: ResolvedConfig;\n isOpen: boolean;\n rawClose: () => void;\n rawPop: () => void;\n stackLength: number;\n}) => {\n const stackLengthRef = useRef(stackLength);\n useEffect(() => {\n stackLengthRef.current = stackLength;\n }, [stackLength]);\n useEffect(() => {\n const shouldListen = isOpen && config.closeOnEscape && config.dismissible;\n const handleKeyDown = (e: KeyboardEvent) => {\n // An inner layer (popover, select, menu) already consumed this Escape —\n // don't also pop the sheet.\n if (e.key !== \"Escape\" || e.defaultPrevented) {\n return;\n }\n e.preventDefault();\n dismissFromEscape({ closeReasonRef, rawClose, rawPop, stackLengthRef });\n };\n if (shouldListen) {\n document.addEventListener(\"keydown\", handleKeyDown);\n }\n return () => {\n if (shouldListen) {\n document.removeEventListener(\"keydown\", handleKeyDown);\n }\n };\n }, [isOpen, config.closeOnEscape, config.dismissible, rawPop, rawClose, closeReasonRef]);\n useEffect(() => {\n const CloseWatcherConstructor = globalThis.CloseWatcher;\n // CloseWatcher cannot distinguish Escape from other close requests (e.g.\n // the Android back gesture), so gating on `closeOnEscape` conservatively\n // disables back-gesture dismissal too when Escape dismissal is turned off.\n const shouldListen =\n isOpen && config.closeOnEscape && config.dismissible && CloseWatcherConstructor !== undefined;\n let watcher: InstanceType<NonNullable<typeof CloseWatcherConstructor>> | undefined;\n const handleClose = () => {\n dismissFromEscape({ closeReasonRef, rawClose, rawPop, stackLengthRef });\n };\n if (shouldListen) {\n watcher = new CloseWatcherConstructor();\n watcher.addEventListener(\"close\", handleClose);\n }\n return () => {\n if (watcher !== undefined) {\n watcher.removeEventListener(\"close\", handleClose);\n watcher.destroy();\n }\n };\n }, [isOpen, config.closeOnEscape, config.dismissible, rawPop, rawClose, closeReasonRef]);\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 const SheetRenderer = <TMap extends object>({\n store,\n config,\n sheets,\n componentMap,\n classNames: classNamesProp,\n layout,\n renderHeader,\n}: SheetRendererProps<TMap>) => {\n const { isOpen, rawClose, rawPop, stack } = useRendererStore(store);\n const side = useResolvedSide(config);\n const prefersReducedMotion = useReducedMotion() ?? false;\n const classNames = resolveClassNames(classNamesProp);\n const { activeSnapIndex, handleSnap, snapHeights } = useSnapState(config, isOpen, side, stack);\n const { close, closeReasonRef, closeWith, pop, popWith } = useCloseControls(rawClose, rawPop);\n const { panelWrapperRef, keyboardInset } = usePanelKeyboardInset(config, isOpen, side);\n useBodyScale(config, isOpen, prefersReducedMotion);\n useFocusRestore(isOpen);\n useDismissalEffects({\n closeReasonRef,\n config,\n isOpen,\n rawClose,\n rawPop,\n stackLength: stack.length,\n });\n const slideFrom = getSlideFrom(side);\n const slideTarget = getSlideTarget();\n const spring = getMotionSpring(prefersReducedMotion, config);\n const stackSpring = spring;\n const isModal = config.modal;\n const showOverlay = isModal && config.showOverlay;\n const hasBackdropClass = classNames.backdrop !== \"\";\n const backdropStyle = getBackdropStyle(config, hasBackdropClass);\n const handleExitComplete = () => {\n if (stack.length === 0) {\n config.onCloseComplete?.(closeReasonRef.current);\n }\n };\n const swipeClose = () => {\n closeWith(\"swipe\");\n };\n const swipePop = () => {\n popWith(\"swipe\");\n };\n const shouldLockScroll = isOpen && isModal && config.lockScroll;\n return (\n <LazyMotion features={domMax}>\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 ? () => {\n closeWith(\"backdrop\");\n }\n : undefined\n }\n style={backdropStyle}\n transition={spring}\n />\n )}\n </AnimatePresence>\n )}\n\n <RemoveScroll enabled={shouldLockScroll} forwardProps ref={panelWrapperRef}>\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 const shouldRender = depth <= config.stacking.renderThreshold;\n const Content = componentMap.get(item.type) ?? getStaticContent(sheets, item.type);\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 keyboardInset={keyboardInset}\n layout={layout}\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 </LazyMotion>\n );\n};\n","import type { SheetPresentationOptions } from \"../types\";\nimport type { AnyComponent, ResolvedItem } from \"./store-types\";\n\ndeclare global {\n var process:\n | undefined\n | {\n env?: {\n NODE_ENV?: string;\n };\n };\n}\n\nconst isRecord = (value: unknown): value is Record<string, unknown> =>\n typeof value === \"object\" && value !== null;\n\nexport const toRecord = (value: unknown): Record<string, unknown> => (isRecord(value) ? value : {});\n\nexport const isComponent = (value: unknown): value is AnyComponent => typeof value === \"function\";\n\nconst getComponentName = (component: AnyComponent): string | undefined => {\n const name = component.displayName ?? component.name;\n return name === \"\" ? undefined : name;\n};\n\nconst getNodeEnv = (): string | undefined => globalThis.process?.env?.NODE_ENV;\n\n/**\n * Generate a unique sheet id. `crypto.randomUUID` is only available in\n * secure contexts, so fall back to a timestamp + random suffix on\n * non-secure origins (e.g. plain-HTTP LAN dev servers).\n */\nexport const generateSheetId = (): string => {\n if (typeof globalThis.crypto?.randomUUID === \"function\") {\n return globalThis.crypto.randomUUID();\n }\n return `sheet-${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 10)}`;\n};\n\nexport const getStringArg = (value: unknown, name: string): string => {\n if (typeof value !== \"string\") {\n throw new TypeError(`Expected ${name} to be a string.`);\n }\n return value;\n};\n\nexport const resolvePresentationOptions = (\n value: unknown,\n): SheetPresentationOptions | undefined => {\n if (!isRecord(value)) {\n return undefined;\n }\n const { ariaLabel } = value;\n if (ariaLabel !== undefined && typeof ariaLabel !== \"string\") {\n return undefined;\n }\n return ariaLabel === undefined ? {} : { ariaLabel };\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 */\nexport const warnInlineComponent = (\n component: AnyComponent,\n componentRegistry: Map<AnyComponent, string>,\n warnedNames: Set<string>,\n): void => {\n if (getNodeEnv() === \"production\") {\n return;\n }\n const name = getComponentName(component);\n if (name === undefined) {\n return;\n }\n if (warnedNames.has(name)) {\n return;\n }\n for (const [existing, key] of componentRegistry) {\n const existingName = getComponentName(existing);\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\nexport const registerComponent = (\n component: AnyComponent,\n componentRegistry: Map<AnyComponent, string>,\n componentMap: Map<string, AnyComponent>,\n getNextKey: () => string,\n warnedNames: Set<string>,\n): string => {\n const existingKey = componentRegistry.get(component);\n if (existingKey !== undefined) {\n return existingKey;\n }\n\n warnInlineComponent(component, componentRegistry, warnedNames);\n const nextKey = getNextKey();\n componentRegistry.set(component, nextKey);\n componentMap.set(nextKey, component);\n return nextKey;\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 */\nexport const 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 fourth?: unknown,\n): ResolvedItem => {\n if (isComponent(first)) {\n const typeKey = registerComponent(\n first,\n componentRegistry,\n componentMap,\n getNextKey,\n warnedNames,\n );\n if (typeof second === \"string\") {\n return {\n ariaLabel: resolvePresentationOptions(fourth)?.ariaLabel,\n data: toRecord(third),\n id: second,\n type: typeKey,\n };\n }\n return {\n ariaLabel: resolvePresentationOptions(third)?.ariaLabel,\n data: toRecord(second),\n id: generateSheetId(),\n type: typeKey,\n };\n }\n return {\n ariaLabel: resolvePresentationOptions(fourth)?.ariaLabel,\n data: toRecord(third),\n id: getStringArg(second, \"sheet id\"),\n type: getStringArg(first, \"sheet type\"),\n };\n};\n","import { createStore } from \"zustand\";\nimport type { StateCreator } from \"zustand\";\nimport type { ResolvedConfig, SheetItem } from \"../types\";\nimport {\n getStringArg,\n isComponent,\n registerComponent,\n resolveArgs,\n resolvePresentationOptions,\n toRecord,\n} from \"./store-args\";\nimport type { AnyComponent, ResolvedItem, SheetStoreBundle, StoreState } from \"./store-types\";\n\nconst createItem = ({ type, id, data, ariaLabel }: ResolvedItem): SheetItem => ({\n ariaLabel,\n data,\n id,\n type,\n});\n\ninterface StoreInternals {\n componentMap: Map<string, AnyComponent>;\n componentRegistry: Map<AnyComponent, string>;\n config: ResolvedConfig;\n getNextKey: () => string;\n pruneRegistry: (remainingStack: readonly SheetItem[]) => void;\n resolve: (first: unknown, second: unknown, third: unknown, fourth?: unknown) => ResolvedItem;\n warnedNames: Set<string>;\n}\n\ntype StoreSet<TMap extends object> = Parameters<StateCreator<StoreState<TMap>>>[0];\ntype StoreGet<TMap extends object> = Parameters<StateCreator<StoreState<TMap>>>[1];\n\ninterface ResolvedWriters {\n openResolved: (resolved: ResolvedItem) => void;\n pushResolved: (resolved: ResolvedItem) => void;\n replaceResolved: (resolved: ResolvedItem) => void;\n}\n\nconst createResolvedWriters = <TMap extends object>(\n set: StoreSet<TMap>,\n config: ResolvedConfig,\n): ResolvedWriters => ({\n openResolved: (resolved) => {\n set({\n isOpen: true,\n stack: [createItem(resolved)],\n });\n },\n pushResolved: (resolved) => {\n set((state) => {\n const item = createItem(resolved);\n if (Number.isFinite(config.maxDepth) && state.stack.length >= config.maxDepth) {\n return {\n isOpen: true,\n stack: [...state.stack.slice(0, -1), item],\n };\n }\n return {\n isOpen: true,\n stack: [...state.stack, item],\n };\n });\n },\n replaceResolved: (resolved) => {\n set((state) => {\n const item = createItem(resolved);\n if (state.stack.length === 0) {\n return { isOpen: true, stack: [item] };\n }\n return {\n isOpen: true,\n stack: [...state.stack.slice(0, -1), item],\n };\n });\n },\n});\n\nconst createNavigate =\n <TMap extends object>(\n componentMap: Map<string, AnyComponent>,\n get: StoreGet<TMap>,\n resolve: StoreInternals[\"resolve\"],\n writers: ResolvedWriters,\n ): StoreState<TMap>[\"navigate\"] =>\n (first: unknown, second?: unknown, third?: unknown, fourth?: unknown) => {\n const resolved = resolve(first, second, third, fourth);\n const { stack } = get();\n const top = stack.at(-1);\n if (stack.length === 0) {\n writers.openResolved(resolved);\n return;\n }\n let isSameType = top?.type === resolved.type;\n if (!isSameType && isComponent(first)) {\n const topComponent = componentMap.get(top?.type ?? \"\");\n isSameType = topComponent === first;\n }\n if (isSameType) {\n writers.replaceResolved(resolved);\n return;\n }\n writers.pushResolved(resolved);\n };\n\nconst createPop =\n <TMap extends object>(\n set: StoreSet<TMap>,\n pruneRegistry: StoreInternals[\"pruneRegistry\"],\n ): StoreState<TMap>[\"pop\"] =>\n () => {\n set((state) => {\n if (state.stack.length <= 1) {\n pruneRegistry([]);\n return { isOpen: false, stack: [] };\n }\n const next = state.stack.slice(0, -1);\n pruneRegistry(next);\n return { isOpen: true, stack: next };\n });\n };\n\nconst createRemove =\n <TMap extends object>(\n set: StoreSet<TMap>,\n pruneRegistry: StoreInternals[\"pruneRegistry\"],\n ): StoreState<TMap>[\"remove\"] =>\n (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 return next.length === 0 ? { isOpen: false, stack: [] } : { stack: next };\n });\n };\n\nconst createSetData =\n <TMap extends object>(\n set: StoreSet<TMap>,\n resolve: StoreInternals[\"resolve\"],\n ): StoreState<TMap>[\"setData\"] =>\n (first: unknown, second?: unknown, third?: unknown) => {\n const { id, data } = resolve(first, second, third);\n set((state) => {\n const index = state.stack.findIndex((item) => item.id === id);\n const existing = state.stack[index];\n if (existing === undefined) {\n return state;\n }\n const updated = [...state.stack];\n updated[index] = { ...existing, data };\n return { stack: updated };\n });\n };\n\nconst createSwap =\n <TMap extends object>(\n set: StoreSet<TMap>,\n internals: Pick<\n StoreInternals,\n \"componentMap\" | \"componentRegistry\" | \"getNextKey\" | \"warnedNames\"\n >,\n ): StoreState<TMap>[\"swap\"] =>\n (first: unknown, second?: unknown, third?: unknown) => {\n const type = isComponent(first)\n ? registerComponent(\n first,\n internals.componentRegistry,\n internals.componentMap,\n internals.getNextKey,\n internals.warnedNames,\n )\n : getStringArg(first, \"sheet type\");\n const data = toRecord(second);\n const ariaLabel = resolvePresentationOptions(third)?.ariaLabel;\n set((state) => {\n const top = state.stack.at(-1);\n if (top === undefined) {\n return state;\n }\n const newStack = [...state.stack];\n newStack[newStack.length - 1] = {\n ariaLabel: ariaLabel ?? top.ariaLabel,\n data,\n id: top.id,\n type,\n };\n return { stack: newStack };\n });\n };\n\nconst createStoreState =\n <TMap extends object>({\n componentMap,\n componentRegistry,\n config,\n getNextKey,\n pruneRegistry,\n resolve,\n warnedNames,\n }: StoreInternals): StateCreator<StoreState<TMap>> =>\n (set, get) => {\n const writers = createResolvedWriters(set, config);\n\n return {\n close: () => {\n pruneRegistry([]);\n set({ isOpen: false, stack: [] });\n },\n isOpen: false,\n navigate: createNavigate(componentMap, get, resolve, writers),\n open: (first: unknown, second?: unknown, third?: unknown, fourth?: unknown) => {\n writers.openResolved(resolve(first, second, third, fourth));\n },\n pop: createPop(set, pruneRegistry),\n push: (first: unknown, second?: unknown, third?: unknown, fourth?: unknown) => {\n writers.pushResolved(resolve(first, second, third, fourth));\n },\n remove: createRemove(set, pruneRegistry),\n replace: (first: unknown, second?: unknown, third?: unknown, fourth?: unknown) => {\n writers.replaceResolved(resolve(first, second, third, fourth));\n },\n setData: createSetData(set, resolve),\n stack: [],\n swap: createSwap(set, { componentMap, componentRegistry, getNextKey, warnedNames }),\n };\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 const createSheetStore = <TMap extends object>(\n config: ResolvedConfig,\n): SheetStoreBundle<TMap> => {\n const componentRegistry = new Map<AnyComponent, string>();\n const componentMap = new Map<string, AnyComponent>();\n // Per-instance counter (not module-level) — prevents identity leaks across instances/tests\n let adhocCounter = 0;\n const getNextKey = () => {\n const key = `__adhoc_${adhocCounter}`;\n adhocCounter += 1;\n return key;\n };\n // Set of component names already warned about (avoid log spam)\n const warnedNames = new Set<string>();\n const resolve = (first: unknown, second: unknown, third: unknown, fourth?: unknown) =>\n resolveArgs(\n componentRegistry,\n componentMap,\n getNextKey,\n warnedNames,\n first,\n second,\n third,\n fourth,\n );\n /** Remove registry entries for type keys no longer in the stack */\n const 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 const store = createStore<StoreState<TMap>>()(\n createStoreState<TMap>({\n componentMap,\n componentRegistry,\n config,\n getNextKey,\n pruneRegistry,\n resolve,\n warnedNames,\n }),\n );\n return { componentMap, componentRegistry, store };\n};\n","import { Portal } from \"@radix-ui/react-portal\";\nimport { createContext, use } 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 ResolvedConfig,\n SheetActions,\n StacksheetConfig,\n StacksheetInstance,\n StacksheetProviderProps,\n StacksheetSnapshot,\n} from \"./types\";\n\ntype StoreState<TMap extends object> = StacksheetSnapshot<TMap> & SheetActions<TMap>;\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 const createStacksheet = <TMap extends object>(\n config?: StacksheetConfig,\n): StacksheetInstance<TMap> => {\n const resolved = resolveConfig(config);\n const { store, componentMap } = createSheetStore<TMap>(resolved);\n // Context for the store — allows multiple instances\n const StoreContext = createContext<{\n store: StoreApi<StoreState<TMap>>;\n config: ResolvedConfig;\n } | null>(null);\n const useStoreContext = () => {\n const ctx = use(StoreContext);\n if (!ctx) {\n throw new Error(\"useSheet/useStacksheetState must be used within <StacksheetProvider>\");\n }\n return ctx;\n };\n // ── Provider ────────────────────────────────\n const providerValue = { config: resolved, store };\n const StacksheetProvider = ({\n sheets,\n children,\n classNames,\n layout,\n renderHeader,\n }: StacksheetProviderProps<TMap>) => (\n <StoreContext.Provider value={providerValue}>\n {children}\n <Portal asChild={false}>\n <SheetRenderer<TMap>\n classNames={classNames}\n componentMap={componentMap}\n config={resolved}\n layout={layout}\n renderHeader={renderHeader}\n sheets={sheets}\n store={store}\n />\n </Portal>\n </StoreContext.Provider>\n );\n // ── Hooks ───────────────────────────────────\n const useSheet = (): SheetActions<TMap> => {\n const { store: s } = useStoreContext();\n // Actions are stable refs in Zustand v5 — read once, no subscription needed\n const state = s.getState();\n return {\n close: state.close,\n navigate: state.navigate,\n open: state.open,\n pop: state.pop,\n push: state.push,\n remove: state.remove,\n replace: state.replace,\n setData: state.setData,\n swap: state.swap,\n };\n };\n const useStacksheetState = (): StacksheetSnapshot<TMap> => {\n const { store: s } = useStoreContext();\n return useStore(\n s,\n useShallow((state) => ({\n isOpen: state.isOpen,\n stack: state.stack,\n })),\n );\n };\n return { StacksheetProvider, store, useSheet, useStacksheetState };\n};\n","import { joinClassNames } from \"@patternmode/system\";\nimport { Slot } from \"@radix-ui/react-slot\";\nimport { ArrowLeftIcon } from \"../icons\";\nimport { useSheetPanel } from \"../panel-context\";\nimport type { SheetOptionalContentPartProps } from \"./sheet-part-types\";\n\nexport const SheetBack = ({\n asChild,\n className,\n style,\n children,\n}: SheetOptionalContentPartProps) => {\n const { back, isNested } = useSheetPanel();\n if (!isNested) {\n return null;\n }\n const isAsChild = asChild === true;\n const Comp = isAsChild ? Slot : \"button\";\n const defaults = isAsChild\n ? undefined\n : \"flex min-h-11 min-w-11 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 return (\n <Comp\n aria-label={children === undefined || children === null ? \"Back\" : undefined}\n className={joinClassNames(defaults, className)}\n onClick={back}\n style={style}\n type={isAsChild ? undefined : \"button\"}\n >\n {children ?? <ArrowLeftIcon />}\n </Comp>\n );\n};\n","import { joinClassNames } from \"@patternmode/system\";\nimport {\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 type { SheetPartProps } from \"./sheet-part-types\";\n\nexport const SheetBody = ({ asChild, className, style, children }: SheetPartProps) => {\n if (asChild === true) {\n // `relative min-h-0 flex-1` is structural for the panel flex layout.\n return (\n <Slot\n className={joinClassNames(\"relative min-h-0 flex-1\", className)}\n data-stacksheet-no-drag=\"\"\n style={style}\n >\n {children}\n </Slot>\n );\n }\n return (\n <ScrollAreaRoot\n className={joinClassNames(\"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 className=\"flex w-2 touch-none select-none p-0.5\" orientation=\"vertical\">\n <ScrollAreaThumb className=\"relative flex-1 rounded bg-current/15\" />\n </ScrollAreaScrollbar>\n </ScrollAreaRoot>\n );\n};\n","import { joinClassNames } from \"@patternmode/system\";\nimport { Slot } from \"@radix-ui/react-slot\";\nimport { XIcon } from \"../icons\";\nimport { useSheetPanel } from \"../panel-context\";\nimport type { SheetOptionalContentPartProps } from \"./sheet-part-types\";\n\nexport const SheetClose = ({\n asChild,\n className,\n style,\n children,\n}: SheetOptionalContentPartProps) => {\n const { close } = useSheetPanel();\n const isAsChild = asChild === true;\n const Comp = isAsChild ? Slot : \"button\";\n const defaults = isAsChild\n ? undefined\n : \"absolute right-2 top-2 z-20 flex min-h-11 min-w-11 cursor-pointer items-center justify-center rounded-md border-none bg-transparent p-0 text-inherit opacity-50 transition-opacity duration-150 hover:opacity-100\";\n return (\n <Comp\n aria-label={children === undefined || children === null ? \"Close\" : undefined}\n className={joinClassNames(defaults, className)}\n onClick={close}\n style={style}\n type={isAsChild ? undefined : \"button\"}\n >\n {children ?? <XIcon />}\n </Comp>\n );\n};\n","import { Slot } from \"@radix-ui/react-slot\";\nimport { useEffect } from \"react\";\nimport { useSheetPanel } from \"../panel-context\";\nimport type { SheetPartProps } from \"./sheet-part-types\";\n\nexport const SheetDescription = ({ asChild, className, style, children }: SheetPartProps) => {\n const { panelId, registerDescription } = useSheetPanel();\n useEffect(() => registerDescription(), [registerDescription]);\n const isAsChild = asChild === true;\n const Comp = isAsChild ? Slot : \"p\";\n return (\n <Comp className={className} id={`${panelId}-desc`} style={style}>\n {children}\n </Comp>\n );\n};\n","import { joinClassNames } from \"@patternmode/system\";\nimport { Slot } from \"@radix-ui/react-slot\";\nimport type { SheetPartProps } from \"./sheet-part-types\";\n\nexport const SheetFooter = ({ asChild, className, style, children }: SheetPartProps) => {\n const isAsChild = asChild === true;\n const Comp = isAsChild ? Slot : \"footer\";\n const defaults = isAsChild ? \"shrink-0\" : \"flex shrink-0 items-center gap-2 border-t px-6 py-3\";\n return (\n <Comp className={joinClassNames(defaults, className)} style={style}>\n {children}\n </Comp>\n );\n};\n","import { joinClassNames } from \"@patternmode/system\";\nimport { Slot } from \"@radix-ui/react-slot\";\nimport { useSheetPanel } from \"../panel-context\";\nimport type { SheetOptionalContentPartProps } from \"./sheet-part-types\";\n\nexport const SheetHandle = ({\n asChild,\n className,\n style,\n children,\n}: SheetOptionalContentPartProps) => {\n const { close, back, isNested, side } = useSheetPanel();\n // The grab pill is a top-of-sheet, drag-down affordance — it only belongs on\n // a bottom sheet. Side sheets drag horizontally, so a horizontal pill at the\n // top reads as wrong; render nothing rather than misplaced chrome.\n if (side !== \"bottom\") {\n return null;\n }\n const dismiss = isNested ? back : close;\n const isAsChild = asChild === true;\n const Comp = isAsChild ? Slot : \"button\";\n const defaults = isAsChild\n ? undefined\n : \"flex shrink-0 cursor-grab touch-none items-center justify-center border-none bg-transparent pt-4 pb-1 text-inherit\";\n return (\n <Comp\n aria-label=\"Dismiss\"\n className={joinClassNames(defaults, className)}\n data-stacksheet-handle=\"\"\n onClick={dismiss}\n style={style}\n type={isAsChild ? undefined : \"button\"}\n >\n {children ?? <div aria-hidden=\"true\" className=\"h-1 w-9 rounded-sm bg-current/25\" />}\n </Comp>\n );\n};\n","import { joinClassNames } from \"@patternmode/system\";\nimport { Slot } from \"@radix-ui/react-slot\";\nimport type { SheetPartProps } from \"./sheet-part-types\";\n\nexport const SheetHeader = ({ asChild, className, style, children }: SheetPartProps) => {\n const isAsChild = asChild === true;\n const Comp = isAsChild ? Slot : \"header\";\n // Keep `shrink-0` even on asChild; without it, header collapses in a\n // flex-column panel layout. No bar, no divider — just a minimal top region.\n const defaults = isAsChild ? \"shrink-0\" : \"flex shrink-0 items-center justify-between gap-3\";\n return (\n <Comp className={joinClassNames(defaults, className)} style={style}>\n {children}\n </Comp>\n );\n};\n","import { joinClassNames } from \"@patternmode/system\";\nimport { Slot } from \"@radix-ui/react-slot\";\nimport { useEffect } from \"react\";\nimport { useSheetPanel } from \"../panel-context\";\nimport type { SheetPartProps } from \"./sheet-part-types\";\n\nexport const SheetTitle = ({ asChild, className, style, children }: SheetPartProps) => {\n const { panelId, registerTitle } = useSheetPanel();\n useEffect(() => registerTitle(), [registerTitle]);\n const isAsChild = asChild === true;\n const Comp = isAsChild ? Slot : \"h2\";\n const defaults = isAsChild ? undefined : \"font-semibold text-sm\";\n return (\n <Comp className={joinClassNames(defaults, className)} id={`${panelId}-title`} style={style}>\n {children}\n </Comp>\n );\n};\n","import { SheetBack } from \"./sheet-back\";\nimport { SheetBody } from \"./sheet-body\";\nimport { SheetClose } from \"./sheet-close\";\nimport { SheetDescription } from \"./sheet-description\";\nimport { SheetFooter } from \"./sheet-footer\";\nimport { SheetHandle } from \"./sheet-handle\";\nimport { SheetHeader } from \"./sheet-header\";\nimport { SheetTitle } from \"./sheet-title\";\n\n/**\n * Composable Sheet Parts for building custom Sheet layouts.\n *\n * Use with `layout=\"composable\"` on the provider to opt into composable mode:\n * no auto header or scroll wrapper, full control over the Sheet 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 Back: SheetBack,\n Body: SheetBody,\n Close: SheetClose,\n Description: SheetDescription,\n Footer: SheetFooter,\n Handle: SheetHandle,\n Header: SheetHeader,\n Title: SheetTitle,\n} as const;\n"],"mappings":"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"}
1
+ {"version":3,"file":"index.mjs","names":["motionSprings"],"sources":["../src/springs.ts","../src/config.ts","../src/media.ts","../src/renderer-effects.ts","../src/snap-points.ts","../src/renderer-helpers.ts","../src/Drag/drag-constants.ts","../src/Drag/drag-geometry.ts","../src/Drag/drag-velocity.ts","../src/Drag/use-drag.ts","../src/panel-context.tsx","../src/stacking.ts","../src/icons.tsx","../src/SheetPanel/default-header.tsx","../src/SheetPanel/sheet-panel-content.tsx","../src/SheetPanel/sheet-panel-focus.tsx","../src/SheetPanel/sheet-panel-handles.tsx","../src/SheetPanel/sheet-panel-layout.ts","../src/SheetPanel/sheet-panel.tsx","../src/renderer.tsx","../src/sheet-portal.tsx","../src/Store/store-args.ts","../src/Store/create-sheet-store.ts","../src/create.tsx","../src/SheetParts/sheet-part-element.tsx","../src/SheetParts/sheet-back.tsx","../src/SheetParts/sheet-body.tsx","../src/SheetParts/sheet-close.tsx","../src/SheetParts/sheet-description.tsx","../src/SheetParts/sheet-footer.tsx","../src/SheetParts/sheet-handle.tsx","../src/SheetParts/sheet-header.tsx","../src/SheetParts/sheet-title.tsx","../src/SheetParts/sheet-parts.ts"],"sourcesContent":["import { springs as motionSprings } from \"@howells/motion\";\n\nimport type { SpringConfig } from \"./types\";\n\n/** Strips the shared token's `type: \"spring\"` down to Stacksheet's numeric SpringConfig. */\nconst toSpringConfig = (spring: {\n damping: number;\n mass: number;\n stiffness: number;\n}): SpringConfig => ({\n damping: spring.damping,\n mass: spring.mass,\n stiffness: spring.stiffness,\n});\n\n/**\n * Spring presets inspired by iOS animation feel.\n *\n * - `subtle` — Barely noticeable bounce, professional. (shared @howells/motion token)\n * - `snappy` — Quick, responsive for interactions. (shared @howells/motion token)\n * - `stiff` — Very quick, controlled. Panels, drawers. **(default)** Intentional\n * fork: damping 40 (tighter than the shared `stiff`) for drawer control.\n */\nexport const springs = {\n snappy: toSpringConfig(motionSprings.snappy),\n stiff: { damping: 40, mass: 1, stiffness: 400 },\n subtle: toSpringConfig(motionSprings.subtle),\n} 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// ── Defaults ────────────────────────────────────\nconst DEFAULT_STACKING: StackingConfig = {\n offsetStep: 16,\n opacityStep: 0,\n radius: 12,\n renderThreshold: 3,\n scaleStep: 0.04,\n};\nconst DEFAULT_SIDE: ResponsiveSide = {\n desktop: \"right\",\n mobile: \"bottom\",\n};\nconst DEFAULT_CONFIG: Omit<ResolvedConfig, \"side\" | \"spring\" | \"stacking\"> = {\n ariaLabel: \"Sheet dialog\",\n breakpoint: 768,\n closeOnBackdrop: true,\n closeOnEscape: true,\n closeThreshold: 0.25,\n dismissible: true,\n drag: true,\n handle: \"inside\",\n lockScroll: true,\n maxDepth: Number.POSITIVE_INFINITY,\n maxWidth: \"90vw\",\n modal: true,\n repositionInputs: true,\n scaleBackgroundAmount: 0.97,\n shouldScaleBackground: false,\n showOverlay: true,\n snapPoints: [],\n snapToSequentialPoints: false,\n velocityThreshold: 0.5,\n width: 420,\n zIndex: 100,\n};\n// ── Helpers ─────────────────────────────────────\n/** Normalize a string side to a responsive object, merging with defaults. */\nconst resolveSide = (side: SideConfig | undefined): ResponsiveSide => {\n if (typeof side === \"string\") {\n return { desktop: side, mobile: side };\n }\n return { ...DEFAULT_SIDE, ...side };\n};\n/** Resolve a preset name to a SpringConfig, or merge partial config with defaults. */\nconst resolveSpring = (spring: SpringPreset | Partial<SpringConfig> | undefined): SpringConfig => {\n if (typeof spring === \"string\") {\n return springs[spring];\n }\n return { ...springs.stiff, ...spring };\n};\n// ── Resolver ────────────────────────────────────\n/** Merge user-provided config with defaults. Resolves union types (side, spring) to concrete values. */\nexport const resolveConfig = (config: StacksheetConfig = {}): ResolvedConfig => {\n const { side, spring, stacking, ...scalarConfig } = config;\n const definedConfig = Object.fromEntries(\n Object.entries(scalarConfig).filter(([, value]) => value !== undefined),\n ) as Partial<Omit<ResolvedConfig, \"side\" | \"spring\" | \"stacking\">>;\n\n return {\n ...DEFAULT_CONFIG,\n ...definedConfig,\n side: resolveSide(side),\n spring: resolveSpring(spring),\n stacking: { ...DEFAULT_STACKING, ...stacking },\n };\n};\n","import { useEffect, useState } from \"react\";\nimport type { ResolvedConfig, Side } from \"./types\";\n/**\n * Returns true when viewport width is at or below the breakpoint.\n * SSR-safe: defaults to false (desktop).\n */\nexport const useIsMobile = (breakpoint: number): boolean => {\n const [isMobile, setIsMobile] = useState(false);\n useEffect(() => {\n const mql = window.matchMedia(`(max-width: ${breakpoint - 1}px)`);\n setIsMobile(mql.matches);\n const handler = (e: MediaQueryListEvent) => {\n setIsMobile(e.matches);\n };\n mql.addEventListener(\"change\", handler);\n return () => {\n mql.removeEventListener(\"change\", handler);\n };\n }, [breakpoint]);\n return isMobile;\n};\n/** Resolve the current side from config + viewport. */\nexport const useResolvedSide = (config: ResolvedConfig): Side => {\n const isMobile = useIsMobile(config.breakpoint);\n return isMobile ? config.side.mobile : config.side.desktop;\n};\n","import { useEffect, useState } from \"react\";\nimport type { RefObject } from \"react\";\nimport type { ResolvedConfig } from \"./types\";\n\nexport const usePanelHeight = (\n panelRef: RefObject<HTMLDivElement | null>,\n hasSnapPoints: boolean,\n): number => {\n const [height, setHeight] = useState(0);\n useEffect(() => {\n const el = panelRef.current;\n let observer: ResizeObserver | undefined;\n if (el !== null && hasSnapPoints) {\n setHeight(el.offsetHeight);\n observer = new ResizeObserver(([entry]) => {\n if (entry) {\n setHeight(entry.contentRect.height);\n }\n });\n observer.observe(el);\n }\n return () => {\n observer?.disconnect();\n };\n }, [panelRef, hasSnapPoints]);\n return height;\n};\nconst getViewportHeight = () =>\n typeof window === \"undefined\" ? 0 : (window.visualViewport?.height ?? window.innerHeight);\n\nexport const useViewportHeight = (active: boolean): number => {\n const [height, setHeight] = useState<number | undefined>(() =>\n typeof window === \"undefined\" ? undefined : getViewportHeight(),\n );\n useEffect(() => {\n const update = () => {\n setHeight(getViewportHeight());\n };\n const canListen = typeof window !== \"undefined\";\n if (canListen) {\n window.addEventListener(\"resize\", update);\n window.visualViewport?.addEventListener(\"resize\", update);\n }\n return () => {\n if (canListen) {\n window.removeEventListener(\"resize\", update);\n window.visualViewport?.removeEventListener(\"resize\", update);\n }\n };\n }, []);\n return active ? (height ?? 0) : 0;\n};\n\n/** Input types that don't summon the on-screen keyboard. */\nconst NON_TEXT_INPUT_TYPES = new Set([\n \"button\",\n \"checkbox\",\n \"color\",\n \"file\",\n \"hidden\",\n \"image\",\n \"radio\",\n \"range\",\n \"reset\",\n \"submit\",\n]);\n\n/** True for elements whose focus raises the on-screen keyboard. */\nconst isEditableElement = (el: Element | null): boolean => {\n if (!(el instanceof HTMLElement)) {\n return false;\n }\n if (el.isContentEditable) {\n return true;\n }\n if (el instanceof HTMLTextAreaElement) {\n return true;\n }\n if (el instanceof HTMLInputElement) {\n return !NON_TEXT_INPUT_TYPES.has(el.type);\n }\n return false;\n};\n\n/**\n * Height (px) the on-screen keyboard occupies while a field inside `containerRef`\n * is focused, else `0`. Derived from the gap between the layout viewport and the\n * (keyboard-shrunk, possibly panned) visual viewport.\n *\n * Focus-gated to fields *inside the container* so unrelated `visualViewport`\n * changes — Android URL-bar collapse, or typing into the page behind a\n * non-modal sheet — don't move the sheet, and zero while pinch-zoomed since a\n * shrunk visual viewport then isn't a keyboard. rAF-throttled because iOS\n * fires many resize events over the keyboard's open animation.\n */\nexport const useKeyboardInset = (\n active: boolean,\n containerRef: RefObject<HTMLElement | null>,\n): number => {\n const [inset, setInset] = useState(0);\n useEffect(() => {\n const canListen = active && typeof window !== \"undefined\";\n const container = containerRef.current;\n const viewport = canListen ? window.visualViewport : undefined;\n let frame = 0;\n let scheduled = false;\n const measure = () => {\n const el = document.activeElement;\n const focused = isEditableElement(el) && container !== null && container.contains(el);\n // Pinch-zoom also shrinks the visual viewport; that's not a keyboard.\n const zoomed = (viewport?.scale ?? 1) > 1;\n const visibleHeight = viewport?.height ?? window.innerHeight;\n // The keyboard occupies the gap below the visual viewport: layout height\n // minus the viewport's pan offset (iOS scrolls it down) minus its height.\n const gap = window.innerHeight - (viewport?.offsetTop ?? 0) - visibleHeight;\n setInset(focused && !zoomed ? Math.max(0, gap) : 0);\n };\n const schedule = () => {\n if (scheduled) {\n return;\n }\n scheduled = true;\n frame = window.requestAnimationFrame(() => {\n scheduled = false;\n measure();\n });\n };\n if (canListen) {\n container?.addEventListener(\"focusin\", schedule);\n container?.addEventListener(\"focusout\", schedule);\n viewport?.addEventListener(\"resize\", schedule, { passive: true });\n // offsetTop changes as iOS pans the visual viewport while the keyboard is up.\n viewport?.addEventListener(\"scroll\", schedule, { passive: true });\n // Re-measure on (re)activation — state persists across sheet close/reopen,\n // so a stale inset from the last session must be cleared.\n schedule();\n }\n return () => {\n if (frame !== 0) {\n window.cancelAnimationFrame(frame);\n }\n container?.removeEventListener(\"focusin\", schedule);\n container?.removeEventListener(\"focusout\", schedule);\n viewport?.removeEventListener(\"resize\", schedule);\n viewport?.removeEventListener(\"scroll\", schedule);\n };\n }, [active, containerRef]);\n return active ? inset : 0;\n};\nconst BODY_SCALE_TRANSITION =\n \"transform 500ms cubic-bezier(0.32, 0.72, 0, 1), border-radius 500ms cubic-bezier(0.32, 0.72, 0, 1)\";\n/** Fallback delay (transition duration + margin) if `transitionend` never fires. */\nconst BODY_SCALE_RESET_FALLBACK_MS = 600;\n\n/** Cancels a pending un-scale reset when the sheet reopens mid-animation. */\nlet cancelPendingBodyScaleReset: (() => void) | undefined;\n\nexport const useBodyScale = (\n config: ResolvedConfig,\n isOpen: boolean,\n prefersReducedMotion: boolean,\n) => {\n useEffect(() => {\n const wrapper = document.querySelector(\"[data-stacksheet-wrapper]\");\n const canScale =\n config.shouldScaleBackground && !prefersReducedMotion && wrapper instanceof HTMLElement;\n const scalable = canScale && isOpen ? wrapper : null;\n if (scalable !== null) {\n cancelPendingBodyScaleReset?.();\n scalable.style.transition = BODY_SCALE_TRANSITION;\n scalable.style.transform = `scale(${config.scaleBackgroundAmount})`;\n scalable.style.borderRadius = \"8px\";\n scalable.style.overflow = \"hidden\";\n scalable.style.transformOrigin = \"center top\";\n }\n return () => {\n if (scalable === null) {\n return;\n }\n // Closing (or unmounting): re-assert the transition so the un-scale\n // animates, clear the transform, and only remove the remaining inline\n // styles once the transition actually ends (with a timeout fallback).\n scalable.style.transition = BODY_SCALE_TRANSITION;\n scalable.style.transform = \"\";\n scalable.style.borderRadius = \"\";\n const controller = new AbortController();\n const { signal } = controller;\n const finish = () => {\n controller.abort();\n cancelPendingBodyScaleReset = undefined;\n scalable.style.transition = \"\";\n scalable.style.overflow = \"\";\n scalable.style.transformOrigin = \"\";\n };\n scalable.addEventListener(\n \"transitionend\",\n (event) => {\n if (event.target === scalable && event.propertyName === \"transform\") {\n finish();\n }\n },\n { signal },\n );\n const timeoutId = setTimeout(() => {\n if (!signal.aborted) {\n finish();\n }\n }, BODY_SCALE_RESET_FALLBACK_MS);\n signal.addEventListener(\"abort\", () => {\n clearTimeout(timeoutId);\n });\n cancelPendingBodyScaleReset = () => {\n controller.abort();\n cancelPendingBodyScaleReset = undefined;\n };\n };\n }, [isOpen, config.shouldScaleBackground, config.scaleBackgroundAmount, prefersReducedMotion]);\n};\n","import type { SnapPoint } from \"./types\";\n\nconst SNAP_POINT_RE = /^(?<value>\\d+(?:\\.\\d+)?)(?<unit>px|rem|em|vh|%)$/u;\n\nconst getRootFontSize = (): number =>\n typeof document === \"undefined\"\n ? 16\n : Number.parseFloat(getComputedStyle(document.documentElement).fontSize);\n\nconst resolveUnitPx = (value: number, unit: string, viewportHeight: number): number => {\n if (unit === \"px\") {\n return value;\n }\n if (unit === \"rem\" || unit === \"em\") {\n return value * getRootFontSize();\n }\n if (unit === \"vh\" || unit === \"%\") {\n return (value / 100) * viewportHeight;\n }\n return 0;\n};\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 */\nconst resolveSnapPointPx = (point: SnapPoint, viewportHeight: number): number => {\n if (typeof point === \"number\") {\n return point <= 1 ? point * viewportHeight : point;\n }\n if (typeof point === \"string\") {\n const match = SNAP_POINT_RE.exec(point);\n const rawValue = match?.groups?.value;\n const unit = match?.groups?.unit;\n if (rawValue === undefined || unit === undefined) {\n return 0;\n }\n return resolveUnitPx(Number.parseFloat(rawValue), unit, viewportHeight);\n }\n return 0;\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 const resolveSnapPoints = (points: SnapPoint[], viewportHeight: number): number[] => {\n if (points.length === 0) {\n return [];\n }\n const resolved: number[] = [];\n for (const point of points) {\n const px = resolveSnapPointPx(point, viewportHeight);\n if (px > 0) {\n resolved.push(px);\n }\n }\n // Sort ascending (smallest snap point first)\n resolved.sort((a, b) => a - b);\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 return deduped;\n};\n/** Velocity threshold (px/ms) for skipping intermediate snap points */\nconst SNAP_VELOCITY_THRESHOLD = 0.4;\n/** Max velocity to consider for snap offset calculation */\nconst MAX_SNAP_VELOCITY = 2;\n/** Multiplier to convert velocity to pixel offset for snap target */\nconst SNAP_VELOCITY_MULTIPLIER = 150;\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 const 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 // 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 // Current position = dragOffset from fully open\n const currentPos = dragOffset;\n if (sequential) {\n // Sequential mode: only snap to adjacent points\n // Positive velocity means dismissing.\n const direction = velocity > 0 ? 1 : -1;\n // Snap heights are ascending, so -1 moves toward the more closed point.\n const nextIndex = currentIndex - direction;\n if (nextIndex < 0) {\n // Dismiss.\n return -1;\n }\n if (nextIndex >= snapHeights.length) {\n // Fully open.\n return snapHeights.length - 1;\n }\n return nextIndex;\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 const projectedPos = currentPos + velocityOffset;\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 for (let i = 1; i < snapOffsets.length; i += 1) {\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 // 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 return bestIndex;\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 const 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 { getSnapOffset } from \"./snap-points\";\nimport type { getStackTransform, SlideValues } from \"./stacking\";\nimport type { Side, StacksheetClassNames } from \"./types\";\n\n// `header` is deprecated (the header bar is gone) and intentionally dropped\n// from the resolved shape — nothing applies it anymore.\nexport type ResolvedClassNames = Required<Omit<StacksheetClassNames, \"header\">>;\nconst EMPTY_CLASSNAMES: ResolvedClassNames = {\n backdrop: \"\",\n panel: \"\",\n};\nexport const resolveClassNames = (cn?: StacksheetClassNames): ResolvedClassNames => {\n if (!cn) {\n return EMPTY_CLASSNAMES;\n }\n return {\n backdrop: cn.backdrop ?? \"\",\n panel: cn.panel ?? \"\",\n };\n};\nexport const buildAriaProps = ({\n ariaLabel,\n hasDescription,\n hasTitle,\n isComposable,\n isModal,\n isTop,\n panelId,\n}: {\n ariaLabel: string;\n hasDescription: boolean;\n hasTitle: boolean;\n isComposable: boolean;\n isModal: boolean;\n isTop: boolean;\n panelId: string;\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 // Only reference the title element when a Sheet.Title is actually\n // mounted — otherwise fall back to the sheet's aria-label so the\n // dialog is never left with a dangling aria-labelledby.\n if (hasTitle) {\n props[\"aria-labelledby\"] = `${panelId}-title`;\n } else {\n props[\"aria-label\"] = ariaLabel;\n }\n if (hasDescription) {\n props[\"aria-describedby\"] = `${panelId}-desc`;\n }\n } else {\n props[\"aria-label\"] = ariaLabel;\n }\n return props;\n};\nexport const getDragTransform = (\n side: Side,\n offset: number,\n): {\n x?: number;\n y?: number;\n} => {\n if (offset === 0) {\n return {};\n }\n switch (side) {\n case \"right\": {\n return { x: offset };\n }\n case \"left\": {\n return { x: -offset };\n }\n case \"bottom\": {\n return { y: offset };\n }\n default: {\n return {};\n }\n }\n};\nexport const VISUAL_TWEEN = {\n duration: 0.25,\n ease: \"easeOut\" as const,\n type: \"tween\" as const,\n};\nconst SHADOW_SM = \"0px 1px 3px 0px rgba(0,0,0,0.06), 0px 6px 12px 0px rgba(0,0,0,0.06)\";\nconst SHADOW_LG =\n \"0px 8px 24px 0px rgba(0,0,0,0.06), 0px 24px 48px 0px rgba(0,0,0,0.04), 0px 48px 96px 0px rgba(0,0,0,0.03)\";\nexport const getShadow = (isNested: boolean): string => (isNested ? SHADOW_SM : SHADOW_LG);\n\n/**\n * Clear the on-screen keyboard. Plain sheets stay anchored at bottom: 0 and\n * pad their content up instead — the panel surface extends under the keyboard\n * (and iOS Safari's floating URL-pill chrome), so no backdrop gap ever shows\n * between sheet and keyboard, and measurement error hides behind the keyboard.\n * Snap sheets are transform-anchored, so they lift via `bottom` (not the\n * Motion `y` transform) and keep their viewport-driven sizing untouched.\n */\nconst getKeyboardClearance = (keyboardInset: number, padForKeyboard: boolean): CSSProperties => {\n if (keyboardInset <= 0) {\n return {};\n }\n return padForKeyboard ? { paddingBottom: keyboardInset } : { bottom: keyboardInset };\n};\n\nexport const buildPanelStyle = (\n panelStyles: CSSProperties,\n isTop: boolean,\n hasPanelClass: boolean,\n isDragging: boolean,\n keyboardInset: number,\n padForKeyboard: boolean,\n): CSSProperties => ({\n ...panelStyles,\n ...getKeyboardClearance(keyboardInset, padForKeyboard),\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});\nexport const buildPanelTransition = (\n isDragging: boolean,\n isTop: boolean,\n spring: Record<string, unknown>,\n stackSpring: Record<string, unknown>,\n) => {\n if (isDragging) {\n return { duration: 0, type: \"tween\" as const };\n }\n const base = isTop ? spring : stackSpring;\n return { ...base, borderRadius: VISUAL_TWEEN, boxShadow: VISUAL_TWEEN };\n};\nexport const 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};\nexport const 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};\nexport const 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};\nexport const buildAnimateTarget = (\n slideTarget: SlideValues,\n stackOffset: {\n x?: number;\n y?: number;\n },\n dragOffset: {\n x?: number;\n y?: number;\n },\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 ...animatedRadius,\n boxShadow: getShadow(!isTop),\n opacity: transform.opacity,\n scale: transform.scale,\n transition,\n };\n if (snapYOffset > 0) {\n return { ...base, y: (dragOffset.y ?? 0) + snapYOffset };\n }\n return base;\n};\nexport const getInitialRadius = (side: Side): Record<string, number> => {\n if (side === \"bottom\") {\n return {\n borderBottomLeftRadius: 0,\n borderBottomRightRadius: 0,\n borderTopLeftRadius: 0,\n borderTopRightRadius: 0,\n };\n }\n return { borderRadius: 0 };\n};\n","/** Elements that should never initiate a drag */\nexport const INTERACTIVE_TAGS = new Set([\"INPUT\", \"TEXTAREA\", \"SELECT\", \"BUTTON\", \"A\"]);\n\n/** Dead zone in px before committing to drag vs text selection */\nexport const DEAD_ZONE = 10;\n\n/** Max angle (degrees) from dismiss axis to qualify as drag intent */\nexport const MAX_ANGLE_DEG = 35;\n\n/** Rubber-band resistance factor for dragging past resting position */\nexport const RUBBER_BAND_FACTOR = 0.6;\n","import type { Side } from \"../types\";\nimport { INTERACTIVE_TAGS, MAX_ANGLE_DEG } from \"./drag-constants\";\nimport type { DragAxis, DragSign } from \"./drag-types\";\n\nexport const isInteractiveElement = (el: Element): boolean => {\n if (INTERACTIVE_TAGS.has(el.tagName)) {\n return true;\n }\n if (el instanceof HTMLElement && el.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 * Walk up from `el` to find the nearest scrollable ancestor.\n * Returns null if nothing is scrollable in the dismiss axis.\n */\nexport const findScrollableAncestor = (el: Element, axis: DragAxis): 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 * 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 */\nconst isAtScrollEdge = (el: Element, axis: DragAxis, sign: DragSign): 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 ? el.scrollTop <= 0 : el.scrollTop + el.clientHeight >= el.scrollHeight - 1;\n }\n return sign === 1 ? el.scrollLeft <= 0 : el.scrollLeft + el.clientWidth >= el.scrollWidth - 1;\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 */\nexport const getDismissAxis = (\n side: Side,\n): {\n axis: DragAxis;\n sign: DragSign;\n} => {\n switch (side) {\n case \"right\": {\n return { axis: \"x\", sign: 1 };\n }\n case \"left\": {\n return { axis: \"x\", sign: -1 };\n }\n case \"bottom\": {\n return { axis: \"y\", sign: 1 };\n }\n default: {\n return { axis: \"x\", sign: 1 };\n }\n }\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 */\nconst classifyGesture = (\n dx: number,\n dy: number,\n axis: DragAxis,\n sign: DragSign,\n): \"drag\" | \"none\" => {\n const absDx = Math.abs(dx);\n const absDy = Math.abs(dy);\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 if (angleDeg > MAX_ANGLE_DEG) {\n return \"none\";\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 return \"drag\";\n};\n/** Decide whether a pointer gesture commits as a drag or should be ignored. */\nexport const commitGesture = (\n dx: number,\n dy: number,\n axis: DragAxis,\n sign: DragSign,\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 !== null && !isAtScrollEdge(scrollEl, axis, sign)) {\n return \"none\";\n }\n return \"drag\";\n};\nexport const getPanelDimension = (panel: HTMLDivElement | null, axis: DragAxis): number => {\n if (!panel) {\n return 300;\n }\n return axis === \"x\" ? panel.offsetWidth : panel.offsetHeight;\n};\n","/** A single pointer sample recorded during a drag gesture. */\nexport interface VelocitySample {\n /** Drag offset in the dismiss direction (px) at sample time */\n offset: number;\n /** Timestamp in ms (Date.now()) */\n time: number;\n}\n\n/** Sliding window (ms) of samples used to compute release velocity. */\nexport const VELOCITY_WINDOW_MS = 100;\n\n/** Upper bound on retained samples — plenty for a 100ms window at 120Hz. */\nconst MAX_SAMPLES = 20;\n\n/**\n * Append a pointer sample, pruning entries that fall outside the sliding\n * window (plus a hard cap as a memory guard). Mutates and returns `samples`.\n */\nexport const appendVelocitySample = (\n samples: VelocitySample[],\n sample: VelocitySample,\n): VelocitySample[] => {\n samples.push(sample);\n const cutoff = sample.time - VELOCITY_WINDOW_MS;\n while (samples.length > MAX_SAMPLES || (samples.length > 2 && (samples[0]?.time ?? 0) < cutoff)) {\n samples.shift();\n }\n return samples;\n};\n\n/**\n * Compute release velocity (px/ms, positive = dismiss direction) from the\n * samples recorded within the sliding window before `releaseTime`.\n *\n * Using only recent samples means a pause followed by a flick reports the\n * flick's velocity — not the whole-gesture average, which would dilute it\n * to near zero.\n */\nexport const getReleaseVelocity = (samples: VelocitySample[], releaseTime: number): number => {\n const cutoff = releaseTime - VELOCITY_WINDOW_MS;\n const recent = samples.filter((sample) => sample.time >= cutoff);\n const [first] = recent;\n const last = recent.at(-1);\n if (first === undefined || last === undefined || last.time <= first.time) {\n return 0;\n }\n return (last.offset - first.offset) / (last.time - first.time);\n};\n","import { useEffect, useRef } from \"react\";\nimport type { RefObject } from \"react\";\nimport { findSnapTarget } from \"../snap-points\";\nimport { DEAD_ZONE, RUBBER_BAND_FACTOR } from \"./drag-constants\";\nimport {\n commitGesture,\n findScrollableAncestor,\n getDismissAxis,\n getPanelDimension,\n isInteractiveElement,\n} from \"./drag-geometry\";\nimport type { DragConfig, DragState } from \"./drag-types\";\nimport { appendVelocitySample, getReleaseVelocity } from \"./drag-velocity\";\nimport type { VelocitySample } from \"./drag-velocity\";\n\ntype DragCommit = \"drag\" | \"none\";\n\ninterface DragRefs {\n committedRef: RefObject<DragCommit | null>;\n offsetRef: RefObject<number>;\n samplesRef: RefObject<VelocitySample[]>;\n scrollTargetRef: RefObject<Element | null>;\n startRef: RefObject<{\n x: number;\n y: number;\n } | null>;\n}\n\nconst resetDragRefs = ({\n committedRef,\n offsetRef,\n samplesRef,\n scrollTargetRef,\n startRef,\n}: DragRefs) => {\n startRef.current = null;\n committedRef.current = null;\n offsetRef.current = 0;\n samplesRef.current = [];\n scrollTargetRef.current = null;\n};\n\nconst createDragHandlers = ({\n axis,\n config,\n onDragUpdate,\n panelRef,\n refs,\n sign,\n}: {\n axis: \"x\" | \"y\";\n config: DragConfig;\n onDragUpdate: (state: DragState) => void;\n panelRef: RefObject<HTMLDivElement | null>;\n refs: DragRefs;\n sign: 1 | -1;\n}) => {\n const dismiss = () => {\n if (config.isNested) {\n config.onPop();\n } else {\n config.onClose();\n }\n };\n const handlePointerDown = (e: PointerEvent) => {\n if (!config.enabled || e.button !== 0 || !(e.target instanceof Element)) {\n return;\n }\n const { target } = e;\n const isHandle = target.closest(\"[data-stacksheet-handle]\") !== null;\n if (!isHandle && isInteractiveElement(target)) {\n return;\n }\n refs.scrollTargetRef.current = isHandle ? null : findScrollableAncestor(target, axis);\n refs.startRef.current = { x: e.clientX, y: e.clientY };\n refs.committedRef.current = null;\n refs.offsetRef.current = 0;\n refs.samplesRef.current = [{ offset: 0, time: Date.now() }];\n // Pointer capture is deferred until the gesture commits as a drag —\n // capturing here would retarget plain taps away from non-native\n // clickable children (e.g. ARIA-pattern buttons), swallowing their clicks.\n };\n const handlePointerMove = (e: PointerEvent) => {\n if (refs.startRef.current === null) {\n return;\n }\n const dx = e.clientX - refs.startRef.current.x;\n const dy = e.clientY - refs.startRef.current.y;\n const dist = Math.hypot(dx, dy);\n if (refs.committedRef.current === null && dist < DEAD_ZONE) {\n return;\n }\n if (refs.committedRef.current === null) {\n refs.committedRef.current = commitGesture(dx, dy, axis, sign, refs.scrollTargetRef.current);\n if (refs.committedRef.current !== \"drag\") {\n refs.startRef.current = null;\n return;\n }\n // The gesture is now a real drag — capture so the panel keeps\n // receiving pointer events even when the pointer leaves it.\n if (e.currentTarget instanceof HTMLElement) {\n e.currentTarget.setPointerCapture(e.pointerId);\n }\n }\n if (refs.committedRef.current !== \"drag\") {\n return;\n }\n const rawOffset = axis === \"x\" ? dx : dy;\n const directional = rawOffset * sign;\n const clampedOffset =\n directional >= 0 ? directional : -Math.sqrt(Math.abs(directional)) * RUBBER_BAND_FACTOR;\n refs.offsetRef.current = clampedOffset;\n appendVelocitySample(refs.samplesRef.current, { offset: clampedOffset, time: Date.now() });\n onDragUpdate({ isDragging: true, offset: clampedOffset });\n e.preventDefault();\n };\n const handlePointerUp = () => {\n if (refs.startRef.current === null || refs.committedRef.current !== \"drag\") {\n resetDragRefs(refs);\n return;\n }\n const offset = Math.max(0, refs.offsetRef.current);\n // Release velocity comes from a sliding window of recent samples, so a\n // pause followed by a flick still dismisses (a whole-gesture average\n // would dilute the flick to near zero).\n const velocity = getReleaseVelocity(refs.samplesRef.current, Date.now());\n resetDragRefs(refs);\n const panelSize = getPanelDimension(panelRef.current, axis);\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({ isDragging: false, offset: 0 });\n }\n return;\n }\n const pastThreshold = offset / panelSize > config.closeThreshold;\n const fastEnough = velocity > config.velocityThreshold;\n if (pastThreshold || fastEnough) {\n dismiss();\n } else {\n onDragUpdate({ isDragging: false, offset: 0 });\n }\n };\n const handlePointerCancel = () => {\n resetDragRefs(refs);\n onDragUpdate({ isDragging: false, offset: 0 });\n };\n return { handlePointerCancel, handlePointerDown, handlePointerMove, handlePointerUp };\n};\n\n/**\n * Hook that manages drag gestures that can dismiss 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 const useDrag = (\n panelRef: RefObject<HTMLDivElement | null>,\n config: DragConfig,\n onDragUpdate: (state: DragState) => void,\n) => {\n const startRef = useRef<{\n x: number;\n y: number;\n } | null>(null);\n const committedRef = useRef<DragCommit | null>(null);\n const offsetRef = useRef(0);\n const samplesRef = useRef<VelocitySample[]>([]);\n const scrollTargetRef = useRef<Element | null>(null);\n const { axis, sign } = getDismissAxis(config.side);\n const refs = { committedRef, offsetRef, samplesRef, scrollTargetRef, startRef };\n const { handlePointerCancel, handlePointerDown, handlePointerMove, handlePointerUp } =\n createDragHandlers({ axis, config, onDragUpdate, panelRef, refs, sign });\n const handlersRef = useRef({\n handlePointerCancel,\n handlePointerDown,\n handlePointerMove,\n handlePointerUp,\n });\n handlersRef.current = {\n handlePointerCancel,\n handlePointerDown,\n handlePointerMove,\n handlePointerUp,\n };\n // Attach pointer events to the panel element\n useEffect(() => {\n const el = panelRef.current;\n const onPointerDown = (event: PointerEvent) => {\n handlersRef.current.handlePointerDown(event);\n };\n const onPointerMove = (event: PointerEvent) => {\n handlersRef.current.handlePointerMove(event);\n };\n const onPointerUp = () => {\n handlersRef.current.handlePointerUp();\n };\n const onPointerCancel = () => {\n handlersRef.current.handlePointerCancel();\n };\n const canListen = el !== null && config.enabled;\n if (canListen) {\n el.addEventListener(\"pointerdown\", onPointerDown);\n el.addEventListener(\"pointermove\", onPointerMove);\n el.addEventListener(\"pointerup\", onPointerUp);\n el.addEventListener(\"pointercancel\", onPointerCancel);\n }\n return () => {\n if (canListen) {\n el.removeEventListener(\"pointerdown\", onPointerDown);\n el.removeEventListener(\"pointermove\", onPointerMove);\n el.removeEventListener(\"pointerup\", onPointerUp);\n el.removeEventListener(\"pointercancel\", onPointerCancel);\n }\n };\n }, [panelRef, config.enabled]);\n};\n","import { createContext, use } from \"react\";\nimport type { Side } from \"./types\";\n\nexport interface SheetPanelContextValue {\n /** Pop the top sheet (go back one level) */\n back: () => void;\n /** Close the entire sheet stack */\n close: () => void;\n /** Whether a Sheet.Description is mounted inside this panel */\n hasDescription: boolean;\n /** Whether a Sheet.Title is mounted inside this panel */\n hasTitle: boolean;\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 /** Called by Sheet.Description on mount to register its presence */\n registerDescription: () => () => void;\n /** Called by Sheet.Title on mount to register its presence */\n registerTitle: () => () => void;\n /** Current resolved side (left/right/bottom) */\n side: Side;\n}\nexport const SheetPanelContext = createContext<SheetPanelContextValue | null>(null);\n/**\n * Access the current sheet panel's context.\n * Must be called inside a component rendered by the sheet stack.\n */\nexport const useSheetPanel = (): SheetPanelContextValue => {\n const ctx = use(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 { CSSProperties } from \"react\";\nimport type { ResolvedConfig, Side, StackingConfig } from \"./types\";\n\n/**\n * Resting height of a bottom sheet. `dvh` tracks the dynamic viewport on iOS\n * Safari (accounts for browser chrome). Shared so the keyboard-inset `calc()`\n * in `buildPanelStyle` can't drift from the panel's base height.\n */\nexport const BOTTOM_SHEET_HEIGHT = \"85dvh\";\n// ── Depth transforms ────────────────────────────\nexport interface StackTransform {\n borderRadius: number;\n offset: number;\n opacity: number;\n scale: number;\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 const getStackTransform = (depth: number, stacking: StackingConfig): StackTransform => {\n if (depth <= 0) {\n return { borderRadius: 0, offset: 0, opacity: 1, scale: 1 };\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 return {\n borderRadius: stacking.radius,\n offset: visualDepth * stacking.offsetStep,\n opacity: beyondThreshold ? 0 : Math.max(0, 1 - visualDepth * stacking.opacityStep),\n scale: Math.max(0.5, 1 - visualDepth * stacking.scaleStep),\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 const 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 borderBottomLeftRadius: 0,\n borderBottomRightRadius: 0,\n borderTopLeftRadius: radius,\n borderTopRightRadius: radius,\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// ── Slide directions ────────────────────────────\nexport interface SlideValues {\n x?: string | number;\n y?: string | number;\n}\n/** Motion initial/exit values for sliding from the given side. */\nexport const getSlideFrom = (side: string): SlideValues => {\n switch (side) {\n case \"right\": {\n return { x: \"100%\" };\n }\n case \"left\": {\n return { x: \"-100%\" };\n }\n case \"bottom\": {\n return { y: \"100%\" };\n }\n default: {\n return { x: \"100%\" };\n }\n }\n};\n/** Motion animate target — the resting position. */\nexport const getSlideTarget = (): SlideValues => ({ x: 0, y: 0 });\n/** Translate offset that pushes stacked panels away from the stack edge. */\nexport const getStackOffset = (\n side: string,\n offset: number,\n): {\n x?: number;\n y?: number;\n} => {\n if (offset === 0) {\n return {};\n }\n switch (side) {\n case \"right\": {\n return { x: -offset };\n }\n case \"left\": {\n return { x: offset };\n }\n case \"bottom\": {\n return { y: -offset };\n }\n default: {\n return {};\n }\n }\n};\n// ── Transform origin ────────────────────────────\n/** Opposite-side origin so stacked panels recede away from the stack edge. */\nconst 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// ── Panel positioning ───────────────────────────\n/**\n * Fixed-position styles for a panel, accounting for side, width, and depth.\n */\nexport const getPanelStyles = (\n side: Side,\n config: ResolvedConfig,\n index: number,\n): CSSProperties => {\n const { width, maxWidth, zIndex } = config;\n const base: CSSProperties = {\n display: \"flex\",\n flexDirection: \"column\",\n // The panel is focused programmatically on open (to move focus into the\n // dialog); it's not a keyboard tab stop, so suppress the container ring.\n outline: \"none\",\n position: \"fixed\",\n transformOrigin: getTransformOrigin(side),\n willChange: \"transform\",\n zIndex: zIndex + 10 + index,\n };\n if (side === \"bottom\") {\n return {\n ...base,\n bottom: 0,\n // dvh tracks the dynamic viewport on iOS Safari (accounts for browser chrome).\n height: BOTTOM_SHEET_HEIGHT,\n left: 0,\n // borderRadius is animated via Motion's animate prop for scale correction\n maxHeight: BOTTOM_SHEET_HEIGHT,\n right: 0,\n };\n }\n // Left or right side panel\n const sideStyles: CSSProperties =\n side === \"right\" ? { bottom: 0, right: 0, top: 0 } : { bottom: 0, left: 0, top: 0 };\n return {\n ...base,\n ...sideStyles,\n maxWidth,\n width,\n };\n};\n","/** Inline SVG icons — no external dependency */\nexport const ArrowLeftIcon = () => (\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);\nexport const XIcon = () => (\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","import { ArrowLeftIcon, XIcon } from \"../icons\";\nimport type { HeaderRenderProps } from \"../types\";\n\n// No header bar: back and close float in the panel corners so there is no\n// row to fill and no divider. The title lives in the sheet's own content.\nexport const DefaultHeader = ({ isNested, onBack, onClose }: HeaderRenderProps) => (\n <>\n {isNested && (\n <button\n aria-label=\"Back\"\n className=\"absolute left-2 top-2 z-20 flex min-h-11 min-w-11 cursor-pointer items-center justify-center rounded-md border-none bg-transparent p-0 text-inherit opacity-50 transition-opacity duration-150 hover:opacity-100\"\n onClick={onBack}\n type=\"button\"\n >\n <ArrowLeftIcon />\n </button>\n )}\n <button\n aria-label=\"Close\"\n className=\"absolute right-2 top-2 z-20 flex min-h-11 min-w-11 cursor-pointer items-center justify-center rounded-md border-none bg-transparent p-0 text-inherit opacity-50 transition-opacity duration-150 hover:opacity-100\"\n onClick={onClose}\n type=\"button\"\n >\n <XIcon />\n </button>\n </>\n);\n","import type { ComponentType, ReactNode } from \"react\";\n\nimport type { HeaderRenderProps } from \"../types\";\nimport { DefaultHeader } from \"./default-header\";\n\nexport const PanelInnerContent = ({\n isComposable,\n shouldRender,\n Content,\n data,\n renderHeader,\n headerProps,\n}: {\n isComposable: boolean;\n shouldRender: boolean;\n Content: ComponentType<Record<string, unknown>> | undefined;\n data: Record<string, unknown>;\n renderHeader?: false | ((props: HeaderRenderProps) => ReactNode);\n headerProps: HeaderRenderProps;\n}) => {\n if (isComposable) {\n return shouldRender && Content !== undefined ? <Content {...data} /> : null;\n }\n const customHeader =\n renderHeader !== undefined && renderHeader !== false ? renderHeader : undefined;\n\n return (\n <>\n {customHeader === undefined ? <DefaultHeader {...headerProps} /> : customHeader(headerProps)}\n {shouldRender && Content !== undefined && (\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\nPanelInnerContent.displayName = \"PanelInnerContent\";\n","import { FocusTrap } from \"focus-trap-react\";\nimport type { ReactNode, RefObject } from \"react\";\nimport { useSyncExternalStore } from \"react\";\n\n// Selectors matched against the focused element to detect when a layer stacked\n// on top of the sheet (a nested dialog/popover) has focus, so the sheet's own\n// focus trap pauses instead of yanking focus back.\nconst LAYERED_MODAL_SELECTORS = [\n // Base UI dialogs (e.g. aperto) mark the open popup with `data-open`.\n '[role=\"dialog\"][data-open]',\n '[role=\"alertdialog\"][data-open]',\n // Base UI wraps every floating layer in focus guards.\n \"[data-base-ui-focus-guard]\",\n // Patternmode popovers whose popup intentionally strips `role=\"dialog\"` to\n // host a combobox/listbox pattern (tags), so they are not caught above.\n '[data-slot=\"tag-selector-content\"]',\n // Third-party Radix content nested inside a sheet still emits these.\n '[role=\"dialog\"][data-state=\"open\"]',\n '[role=\"alertdialog\"][data-state=\"open\"]',\n \"[data-radix-popper-content-wrapper]\",\n \"[data-radix-focus-guard]\",\n].join(\", \");\n\nconst subscribeToFocusTarget = (onStoreChange: () => void): (() => void) => {\n document.addEventListener(\"focusin\", onStoreChange, true);\n return () => {\n document.removeEventListener(\"focusin\", onStoreChange, true);\n };\n};\nconst getServerLayeredModalFocused = (): boolean => false;\nconst getLayeredModalFocused = (): boolean => {\n if (typeof document === \"undefined\") {\n return false;\n }\n const target = document.activeElement;\n return (\n !!target &&\n target !== document.body &&\n target instanceof Element &&\n target.closest(LAYERED_MODAL_SELECTORS) !== null\n );\n};\nconst useLayeredModalFocused = (active: boolean): boolean => {\n const layered = useSyncExternalStore(\n subscribeToFocusTarget,\n getLayeredModalFocused,\n getServerLayeredModalFocused,\n );\n return active && layered;\n};\n\nexport const ModalFocusTrap = ({\n enabled,\n active,\n fallbackRef,\n children,\n}: {\n enabled: boolean;\n active: boolean;\n fallbackRef: RefObject<HTMLElement | null>;\n children: ReactNode;\n}): ReactNode => {\n const paused = useLayeredModalFocused(enabled && active);\n if (!enabled) {\n return children;\n }\n return (\n <FocusTrap\n active={active}\n focusTrapOptions={{\n allowOutsideClick: true,\n escapeDeactivates: false,\n fallbackFocus: () => {\n if (fallbackRef.current !== null) {\n return fallbackRef.current;\n }\n return document.body;\n },\n // Focus the panel element itself (it has tabIndex={-1}) so screen\n // readers announce the dialog when it opens.\n initialFocus: () => fallbackRef.current ?? undefined,\n returnFocusOnDeactivate: true,\n }}\n paused={paused}\n >\n {children}\n </FocusTrap>\n );\n};\n","import { joinClassNames } from \"@patternmode/system\";\nimport { m } from \"motion/react\";\nimport type { CSSProperties } from \"react\";\nimport type { HandlePosition, Side } from \"../types\";\n\nexport const BottomHandle = ({\n onDismiss,\n position = \"inside\",\n}: {\n onDismiss?: () => void;\n position?: HandlePosition;\n}) => (\n <button\n aria-label=\"Dismiss\"\n className={joinClassNames(\n // text-inherit matters: the pill is bg-current/15, and without it the\n // button falls back to the UA color — iOS Safari's system blue.\n \"absolute inset-x-0 z-10 flex w-full cursor-grab touch-none items-center justify-center border-none bg-transparent text-inherit\",\n // `outside` floats the pill above the sheet on the backdrop; `inside`\n // tucks it just below the top edge.\n position === \"outside\" ? \"bottom-full pt-1 pb-2\" : \"top-0 pt-2.5 pb-2\",\n )}\n data-stacksheet-handle=\"\"\n onClick={onDismiss}\n type=\"button\"\n >\n <div aria-hidden=\"true\" className=\"h-[5px] w-9 rounded-full bg-current/15\" />\n </button>\n);\nexport const SideHandle = ({\n side,\n isHovered,\n onDismiss,\n}: {\n side: Side;\n isHovered: boolean;\n onDismiss?: () => void;\n}) => {\n const position: CSSProperties = side === \"right\" ? { right: \"100%\" } : { left: \"100%\" };\n return (\n <m.button\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 border-none bg-transparent p-0 text-inherit\"\n data-stacksheet-handle=\"\"\n onClick={onDismiss}\n style={position}\n transition={{ duration: isHovered ? 0.15 : 0.4, ease: \"easeOut\" }}\n type=\"button\"\n >\n <div aria-hidden=\"true\" className=\"h-8 w-1 rounded-full bg-current/20\" />\n </m.button>\n );\n};\n","import type { ReactNode } from \"react\";\nimport type { HeaderRenderProps, StacksheetLayout } from \"../types\";\n\nexport const resolvePanelLayout = (\n layout: StacksheetLayout | undefined,\n renderHeader?: false | ((props: HeaderRenderProps) => ReactNode),\n): StacksheetLayout => {\n if (layout) {\n return layout;\n }\n return renderHeader === false ? \"composable\" : \"classic\";\n};\n","import { m } from \"motion/react\";\nimport { useCallback, useEffect, useMemo, useRef, useState } from \"react\";\nimport type { ReactNode, RefObject } from \"react\";\n\nimport type { DragState } from \"../Drag/drag-types\";\nimport { useDrag } from \"../Drag/use-drag\";\nimport { SheetPanelContext } from \"../panel-context\";\nimport { usePanelHeight } from \"../renderer-effects\";\nimport {\n buildAnimateTarget,\n buildAriaProps,\n buildPanelStyle,\n buildPanelTransition,\n computeSnapYOffset,\n getDragTransform,\n getInitialRadius,\n getShadow,\n resolveSlideFrom,\n VISUAL_TWEEN,\n} from \"../renderer-helpers\";\nimport {\n getAnimatedBorderRadius,\n getPanelStyles,\n getStackOffset,\n getStackTransform,\n} from \"../stacking\";\nimport type { HandlePosition, HeaderRenderProps } from \"../types\";\nimport { PanelInnerContent } from \"./sheet-panel-content\";\nimport { ModalFocusTrap } from \"./sheet-panel-focus\";\nimport { BottomHandle, SideHandle } from \"./sheet-panel-handles\";\nimport { resolvePanelLayout } from \"./sheet-panel-layout\";\nimport type { SheetPanelProps } from \"./sheet-panel-types\";\n\nconst getPanelAriaLabel = (item: SheetPanelProps[\"item\"], fallbackLabel: string): string =>\n item.ariaLabel ??\n (typeof item.data?.__ariaLabel === \"string\" ? item.data.__ariaLabel : undefined) ??\n fallbackLabel;\n\nconst getPanelHoverProps = (enabled: boolean, setIsHovered: (value: boolean) => void) =>\n enabled\n ? {\n onBlur: () => {\n setIsHovered(false);\n },\n onFocus: () => {\n setIsHovered(true);\n },\n onMouseEnter: () => {\n setIsHovered(true);\n },\n onMouseLeave: () => {\n setIsHovered(false);\n },\n }\n : {};\n\nconst getInactivePanelProps = (isTop: boolean) =>\n isTop ? {} : { \"aria-hidden\": \"true\" as const, inert: true };\n\nconst getHeaderProps = ({\n close,\n isNested,\n pop,\n side,\n}: Pick<SheetPanelProps, \"close\" | \"isNested\" | \"pop\" | \"side\">): HeaderRenderProps => ({\n isNested,\n onBack: pop,\n onClose: close,\n side,\n});\n\nconst getPanelContext = ({\n close,\n hasDescription,\n hasTitle,\n isNested,\n isTop,\n panelId,\n pop,\n registerDescription,\n registerTitle,\n side,\n}: Pick<SheetPanelProps, \"close\" | \"isNested\" | \"isTop\" | \"pop\" | \"side\"> & {\n hasDescription: boolean;\n hasTitle: boolean;\n panelId: string;\n registerDescription: () => () => void;\n registerTitle: () => () => void;\n}) => ({\n back: pop,\n close,\n hasDescription,\n hasTitle,\n isNested,\n isTop,\n panelId,\n registerDescription,\n registerTitle,\n side,\n});\n\nconst getOptionalSideHandle = ({\n isHovered,\n onDismiss,\n show,\n side,\n}: {\n isHovered: boolean;\n onDismiss: () => void;\n show: boolean;\n side: SheetPanelProps[\"side\"];\n}): ReactNode =>\n show ? <SideHandle isHovered={isHovered} onDismiss={onDismiss} side={side} /> : null;\n\nconst getOptionalBottomHandle = (\n show: boolean,\n onDismiss: () => void,\n position: HandlePosition,\n): ReactNode => (show ? <BottomHandle onDismiss={onDismiss} position={position} /> : null);\n\nconst completeOpeningAnimation = (\n hasEnteredRef: RefObject<boolean>,\n isTop: boolean,\n onOpenCompleteRef: RefObject<(() => void) | undefined>,\n) => {\n if (isTop && !hasEnteredRef.current) {\n hasEnteredRef.current = true;\n onOpenCompleteRef.current?.();\n }\n};\n\nconst useOpeningCompletion = (isTop: boolean, onOpenComplete: (() => void) | undefined) => {\n const hasEnteredRef = useRef(false);\n const onOpenCompleteRef = useRef(onOpenComplete);\n\n if (!isTop && hasEnteredRef.current) {\n hasEnteredRef.current = false;\n }\n useEffect(() => {\n onOpenCompleteRef.current = onOpenComplete;\n }, [onOpenComplete]);\n\n return () => {\n completeOpeningAnimation(hasEnteredRef, isTop, onOpenCompleteRef);\n };\n};\n\nconst useSheetPanelDrag = (\n {\n activeSnapIndex,\n config,\n isNested,\n isTop,\n onSnap,\n prefersReducedMotion,\n side,\n snapHeights,\n swipeClose,\n swipePop,\n }: SheetPanelProps,\n panelRef: RefObject<HTMLDivElement | null>,\n): DragState => {\n const [dragState, setDragState] = useState<DragState>({\n isDragging: false,\n offset: 0,\n });\n\n useDrag(\n panelRef,\n {\n activeSnapIndex,\n closeThreshold: config.closeThreshold,\n enabled: isTop && config.drag && config.dismissible && !prefersReducedMotion,\n isNested,\n onClose: swipeClose,\n onPop: swipePop,\n onSnap,\n sequential: config.snapToSequentialPoints,\n side,\n snapHeights,\n velocityThreshold: config.velocityThreshold,\n },\n setDragState,\n );\n\n return dragState;\n};\n\nconst useSheetPanelContext = (\n { close, isNested, isTop, pop, side }: SheetPanelProps,\n panelId: string,\n) => {\n const [hasDescription, setHasDescription] = useState(false);\n const [hasTitle, setHasTitle] = useState(false);\n // oxlint-disable-next-line react-doctor/react-compiler-no-manual-memoization -- the library build does not run React Compiler; a stable identity keeps Sheet.Description effects from re-running on every drag re-render.\n const registerDescription = useCallback(() => {\n setHasDescription(true);\n return () => {\n setHasDescription(false);\n };\n }, []);\n // oxlint-disable-next-line react-doctor/react-compiler-no-manual-memoization -- the library build does not run React Compiler; a stable identity keeps Sheet.Title effects from re-running on every drag re-render.\n const registerTitle = useCallback(() => {\n setHasTitle(true);\n return () => {\n setHasTitle(false);\n };\n }, []);\n // Memoized so drag-driven re-renders don't churn the context value (and\n // with it every Sheet.* consumer's effects).\n // oxlint-disable-next-line react-doctor/react-compiler-no-manual-memoization -- the library build does not run React Compiler; without useMemo the panel context is a new object on every pointermove re-render.\n const panelContext = useMemo(\n () =>\n getPanelContext({\n close,\n hasDescription,\n hasTitle,\n isNested,\n isTop,\n panelId,\n pop,\n registerDescription,\n registerTitle,\n side,\n }),\n [\n close,\n hasDescription,\n hasTitle,\n isNested,\n isTop,\n panelId,\n pop,\n registerDescription,\n registerTitle,\n side,\n ],\n );\n\n return { hasDescription, hasTitle, panelContext };\n};\n\nconst useSheetPanelModel = (props: SheetPanelProps) => {\n const {\n item,\n index,\n depth,\n isTop,\n isNested,\n side,\n config,\n classNames,\n pop,\n close,\n snapHeights,\n keyboardInset,\n activeSnapIndex,\n layout,\n renderHeader,\n slideFrom,\n slideTarget,\n spring,\n stackSpring,\n } = props;\n const panelRef = useRef<HTMLDivElement>(null);\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 const handleAnimationComplete = useOpeningCompletion(isTop, config.onOpenComplete);\n const dragState = useSheetPanelDrag(props, panelRef);\n\n const ariaLabel = getPanelAriaLabel(item, config.ariaLabel);\n\n const panelId = `stacksheet-${item.id}`;\n const { hasDescription, hasTitle, panelContext } = useSheetPanelContext(props, panelId);\n\n const panelLayout = resolvePanelLayout(layout, renderHeader);\n const isComposable = panelLayout === \"composable\";\n const hasPanelClass = classNames.panel !== \"\";\n const dragOffset = getDragTransform(side, dragState.offset);\n // Only the top bottom-sheet reacts to the keyboard (background panels are\n // inert and can't hold focus). Plain sheets pad content above the keyboard;\n // snap sheets lift instead — they already track the shrunk visual viewport.\n const activeKeyboardInset = isTop && side === \"bottom\" ? keyboardInset : 0;\n const panelStyle = buildPanelStyle(\n panelStyles,\n isTop,\n hasPanelClass,\n dragState.isDragging,\n activeKeyboardInset,\n snapHeights.length === 0,\n );\n\n const headerProps = getHeaderProps({ close, isNested, pop, side });\n\n const ariaProps = buildAriaProps({\n ariaLabel,\n hasDescription,\n hasTitle,\n isComposable,\n isModal: config.modal,\n isTop,\n panelId,\n });\n\n const transition = buildPanelTransition(dragState.isDragging, isTop, spring, stackSpring);\n\n const animatedRadius = getAnimatedBorderRadius(side, depth, config.stacking);\n const snapYOffset = computeSnapYOffset(side, snapHeights, activeSnapIndex, measuredHeight);\n const resolvedSlideFrom = resolveSlideFrom(side, slideFrom, measuredHeight);\n\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 // Composable layouts own their chrome — Sheet.Handle renders the pill, so\n // the auto handle would duplicate it.\n const showBottomHandle = isTop && side === \"bottom\" && !isComposable;\n const dismiss = isNested ? pop : close;\n const sideHandle = getOptionalSideHandle({\n isHovered,\n onDismiss: dismiss,\n show: showSideHandle,\n side,\n });\n const bottomHandle = getOptionalBottomHandle(showBottomHandle, dismiss, config.handle);\n // Outside handles must render above the overflow-hidden content wrapper, so\n // the panel places them at the panel level rather than inside it.\n const bottomHandleOutside = showBottomHandle && config.handle === \"outside\";\n const hoverProps = getPanelHoverProps(showSideHandle, setIsHovered);\n const inactivePanelProps = getInactivePanelProps(isTop);\n\n return {\n animateTarget,\n ariaProps,\n bottomHandle,\n bottomHandleOutside,\n handleAnimationComplete,\n headerProps,\n hoverProps,\n inactivePanelProps,\n initialRadius,\n isComposable,\n panelContext,\n panelRef,\n panelStyle,\n resolvedSlideFrom,\n sideHandle,\n };\n};\n\nexport const SheetPanel = (props: SheetPanelProps) => {\n const {\n item,\n isTop,\n config,\n classNames,\n Content,\n shouldRender,\n renderHeader,\n prefersReducedMotion,\n } = props;\n const {\n animateTarget,\n ariaProps,\n bottomHandle,\n bottomHandleOutside,\n handleAnimationComplete,\n headerProps,\n hoverProps,\n inactivePanelProps,\n initialRadius,\n isComposable,\n panelContext,\n panelRef,\n panelStyle,\n resolvedSlideFrom,\n sideHandle,\n } = useSheetPanelModel(props);\n\n const panelContent = (\n <m.div\n animate={animateTarget}\n className={classNames.panel || undefined}\n exit={{\n ...resolvedSlideFrom,\n boxShadow: getShadow(false),\n opacity: 0.6,\n transition: {\n boxShadow: VISUAL_TWEEN,\n duration: prefersReducedMotion ? 0 : 0.24,\n ease: \"easeOut\",\n type: \"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 ref={panelRef}\n style={panelStyle}\n tabIndex={isTop ? -1 : undefined}\n {...hoverProps}\n {...inactivePanelProps}\n {...ariaProps}\n >\n {sideHandle}\n {bottomHandleOutside ? bottomHandle : null}\n <div className=\"relative flex min-h-0 flex-1 flex-col overflow-hidden rounded-[inherit]\">\n {bottomHandleOutside ? null : bottomHandle}\n <PanelInnerContent\n Content={Content}\n data={item.data}\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 active={isTop} enabled={config.modal} fallbackRef={panelRef}>\n {panelContent}\n </ModalFocusTrap>\n </SheetPanelContext.Provider>\n );\n};\n","import { AnimatePresence, domMax, LazyMotion, m, useReducedMotion } from \"motion/react\";\nimport { useEffect, useRef, useState } from \"react\";\nimport type { ComponentType, CSSProperties, ReactNode, RefObject } from \"react\";\nimport { RemoveScroll } from \"react-remove-scroll\";\nimport type { StoreApi } from \"zustand\";\nimport { useStore } from \"zustand\";\nimport { useShallow } from \"zustand/react/shallow\";\nimport { useResolvedSide } from \"./media\";\nimport { useBodyScale, useKeyboardInset, useViewportHeight } from \"./renderer-effects\";\nimport { resolveClassNames } from \"./renderer-helpers\";\nimport { SheetPanel } from \"./sheet-panel\";\nimport { resolveSnapPoints } from \"./snap-points\";\nimport { getSlideFrom, getSlideTarget } from \"./stacking\";\nimport type {\n CloseReason,\n ContentMap,\n HeaderRenderProps,\n ResolvedConfig,\n SheetActions,\n Side,\n StacksheetClassNames,\n StacksheetLayout,\n StacksheetSnapshot,\n} from \"./types\";\n\n// CloseWatcher — ambient type for browsers that support it (Chromium 120+)\ndeclare global {\n var CloseWatcher:\n | (new () => {\n addEventListener: (type: \"close\", listener: () => void) => void;\n destroy: () => void;\n removeEventListener: (type: \"close\", listener: () => void) => void;\n })\n | undefined;\n}\n\nconst handleBackdropExitComplete = () => {\n requestAnimationFrame(() => {\n void document.body.offsetHeight;\n });\n};\n\nconst getResolvedSnapHeights = (\n side: Side,\n snapPoints: ResolvedConfig[\"snapPoints\"],\n viewportHeight: number,\n) =>\n side === \"bottom\" && snapPoints.length > 0 ? resolveSnapPoints(snapPoints, viewportHeight) : [];\n\nconst getActiveInternalSnapIndex = ({\n defaultSnapIndex,\n internalSnap,\n snapContext,\n snapHeights,\n}: {\n defaultSnapIndex: number;\n internalSnap: { context: string; index: number; snapCount: number };\n snapContext: string;\n snapHeights: number[];\n}) =>\n internalSnap.context === snapContext && internalSnap.snapCount === snapHeights.length\n ? internalSnap.index\n : defaultSnapIndex;\n\nconst getMotionSpring = (prefersReducedMotion: boolean, config: ResolvedConfig) =>\n prefersReducedMotion\n ? ({ duration: 0, type: \"tween\" as const } as const)\n : ({\n damping: config.spring.damping,\n mass: config.spring.mass,\n stiffness: config.spring.stiffness,\n type: \"spring\" as const,\n } as const);\n\nconst getBackdropStyle = (config: ResolvedConfig, hasBackdropClass: boolean): CSSProperties => ({\n cursor: config.closeOnBackdrop && config.dismissible ? \"pointer\" : undefined,\n willChange: \"opacity\",\n zIndex: config.zIndex,\n ...(hasBackdropClass ? {} : { background: \"var(--overlay, rgba(0, 0, 0, 0.15))\" }),\n});\n\ninterface SheetRendererProps<TMap extends object> {\n classNames?: StacksheetClassNames;\n /** Ad-hoc component map (type key → component) */\n componentMap: Map<string, ComponentType<Record<string, unknown>>>;\n config: ResolvedConfig;\n layout?: StacksheetLayout;\n renderHeader?: false | ((props: HeaderRenderProps) => ReactNode);\n sheets?: ContentMap<TMap>;\n store: StoreApi<StacksheetSnapshot<TMap> & SheetActions<TMap>>;\n}\n\nconst isContentComponent = (content: unknown): content is ComponentType<Record<string, unknown>> =>\n typeof content === \"function\";\n\nconst getStaticContent = <TMap extends object>(\n sheets: ContentMap<TMap> | undefined,\n type: string,\n): ComponentType<Record<string, unknown>> | undefined => {\n if (sheets === undefined) {\n return undefined;\n }\n const match = Object.entries(sheets).find(([sheetType]) => sheetType === type);\n const content = match?.[1];\n return isContentComponent(content) ? content : undefined;\n};\n\nconst useRendererStore = <TMap extends object>(\n store: StoreApi<StacksheetSnapshot<TMap> & SheetActions<TMap>>,\n) => {\n const isOpen = useStore(store, (s) => s.isOpen);\n const stack = useStore(store, (s) => s.stack);\n const { rawClose, rawPop } = useStore(\n store,\n useShallow((s) => ({\n rawClose: s.close,\n rawPop: s.pop,\n })),\n );\n return { isOpen, rawClose, rawPop, stack };\n};\n\nconst useSnapState = (\n config: ResolvedConfig,\n isOpen: boolean,\n side: Side,\n stack: StacksheetSnapshot<object>[\"stack\"],\n) => {\n const viewportHeight = useViewportHeight(\n isOpen && side === \"bottom\" && config.snapPoints.length > 0,\n );\n const snapHeights = getResolvedSnapHeights(side, config.snapPoints, viewportHeight);\n const snapContext = isOpen ? stack.map((item) => item.id).join(\"\\u0000\") : \"\";\n const defaultSnapIndex = snapHeights.length > 0 ? snapHeights.length - 1 : 0;\n const [internalSnap, setInternalSnap] = useState({\n context: \"\",\n index: defaultSnapIndex,\n snapCount: snapHeights.length,\n });\n const internalSnapIndex = getActiveInternalSnapIndex({\n defaultSnapIndex,\n internalSnap,\n snapContext,\n snapHeights,\n });\n const activeSnapIndex = config.snapPointIndex ?? internalSnapIndex;\n const handleSnap = (index: number) => {\n setInternalSnap({\n context: snapContext,\n index,\n snapCount: snapHeights.length,\n });\n config.onSnapPointChange?.(index);\n };\n return { activeSnapIndex, handleSnap, snapHeights };\n};\n\nconst usePanelKeyboardInset = (config: ResolvedConfig, isOpen: boolean, side: Side) => {\n const panelWrapperRef = useRef<HTMLDivElement>(null);\n const keyboardInset = useKeyboardInset(\n isOpen && side === \"bottom\" && config.repositionInputs,\n panelWrapperRef,\n );\n return { keyboardInset, panelWrapperRef };\n};\n\nconst useCloseControls = (rawClose: () => void, rawPop: () => void) => {\n const closeReasonRef = useRef<CloseReason>(\"programmatic\");\n const closeWith = (reason: CloseReason) => {\n closeReasonRef.current = reason;\n rawClose();\n };\n const popWith = (reason: CloseReason) => {\n closeReasonRef.current = reason;\n rawPop();\n };\n return {\n close: () => {\n closeWith(\"programmatic\");\n },\n closeReasonRef,\n closeWith,\n pop: () => {\n popWith(\"programmatic\");\n },\n popWith,\n };\n};\n\nconst useFocusRestore = (isOpen: boolean) => {\n const triggerRef = useRef<Element | null>(null);\n const wasOpenRef = useRef(false);\n useEffect(() => {\n if (isOpen && !wasOpenRef.current) {\n triggerRef.current = document.activeElement;\n } else if (!isOpen && wasOpenRef.current) {\n const el = triggerRef.current;\n if (el && el instanceof HTMLElement && el !== document.body && el.tagName !== \"BODY\") {\n el.focus();\n }\n triggerRef.current = null;\n }\n wasOpenRef.current = isOpen;\n }, [isOpen]);\n};\n\nconst dismissFromEscape = ({\n closeReasonRef,\n rawClose,\n rawPop,\n stackLengthRef,\n}: {\n closeReasonRef: RefObject<CloseReason>;\n rawClose: () => void;\n rawPop: () => void;\n stackLengthRef: RefObject<number>;\n}) => {\n closeReasonRef.current = \"escape\";\n if (stackLengthRef.current > 1) {\n rawPop();\n } else {\n rawClose();\n }\n};\n\nconst useDismissalEffects = ({\n closeReasonRef,\n config,\n isOpen,\n rawClose,\n rawPop,\n stackLength,\n}: {\n closeReasonRef: RefObject<CloseReason>;\n config: ResolvedConfig;\n isOpen: boolean;\n rawClose: () => void;\n rawPop: () => void;\n stackLength: number;\n}) => {\n const stackLengthRef = useRef(stackLength);\n useEffect(() => {\n stackLengthRef.current = stackLength;\n }, [stackLength]);\n useEffect(() => {\n const shouldListen = isOpen && config.closeOnEscape && config.dismissible;\n const handleKeyDown = (e: KeyboardEvent) => {\n // An inner layer (popover, select, menu) already consumed this Escape —\n // don't also pop the sheet.\n if (e.key !== \"Escape\" || e.defaultPrevented) {\n return;\n }\n e.preventDefault();\n dismissFromEscape({ closeReasonRef, rawClose, rawPop, stackLengthRef });\n };\n if (shouldListen) {\n document.addEventListener(\"keydown\", handleKeyDown);\n }\n return () => {\n if (shouldListen) {\n document.removeEventListener(\"keydown\", handleKeyDown);\n }\n };\n }, [isOpen, config.closeOnEscape, config.dismissible, rawPop, rawClose, closeReasonRef]);\n useEffect(() => {\n const CloseWatcherConstructor = globalThis.CloseWatcher;\n // CloseWatcher cannot distinguish Escape from other close requests (e.g.\n // the Android back gesture), so gating on `closeOnEscape` conservatively\n // disables back-gesture dismissal too when Escape dismissal is turned off.\n const shouldListen =\n isOpen && config.closeOnEscape && config.dismissible && CloseWatcherConstructor !== undefined;\n let watcher: InstanceType<NonNullable<typeof CloseWatcherConstructor>> | undefined;\n const handleClose = () => {\n dismissFromEscape({ closeReasonRef, rawClose, rawPop, stackLengthRef });\n };\n if (shouldListen) {\n watcher = new CloseWatcherConstructor();\n watcher.addEventListener(\"close\", handleClose);\n }\n return () => {\n if (watcher !== undefined) {\n watcher.removeEventListener(\"close\", handleClose);\n watcher.destroy();\n }\n };\n }, [isOpen, config.closeOnEscape, config.dismissible, rawPop, rawClose, closeReasonRef]);\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 const SheetRenderer = <TMap extends object>({\n store,\n config,\n sheets,\n componentMap,\n classNames: classNamesProp,\n layout,\n renderHeader,\n}: SheetRendererProps<TMap>) => {\n const { isOpen, rawClose, rawPop, stack } = useRendererStore(store);\n const side = useResolvedSide(config);\n const prefersReducedMotion = useReducedMotion() ?? false;\n const classNames = resolveClassNames(classNamesProp);\n const { activeSnapIndex, handleSnap, snapHeights } = useSnapState(config, isOpen, side, stack);\n const { close, closeReasonRef, closeWith, pop, popWith } = useCloseControls(rawClose, rawPop);\n const { panelWrapperRef, keyboardInset } = usePanelKeyboardInset(config, isOpen, side);\n useBodyScale(config, isOpen, prefersReducedMotion);\n useFocusRestore(isOpen);\n useDismissalEffects({\n closeReasonRef,\n config,\n isOpen,\n rawClose,\n rawPop,\n stackLength: stack.length,\n });\n const slideFrom = getSlideFrom(side);\n const slideTarget = getSlideTarget();\n const spring = getMotionSpring(prefersReducedMotion, config);\n const stackSpring = spring;\n const isModal = config.modal;\n const showOverlay = isModal && config.showOverlay;\n const hasBackdropClass = classNames.backdrop !== \"\";\n const backdropStyle = getBackdropStyle(config, hasBackdropClass);\n const handleExitComplete = () => {\n if (stack.length === 0) {\n config.onCloseComplete?.(closeReasonRef.current);\n }\n };\n const swipeClose = () => {\n closeWith(\"swipe\");\n };\n const swipePop = () => {\n popWith(\"swipe\");\n };\n const shouldLockScroll = isOpen && isModal && config.lockScroll;\n return (\n <LazyMotion features={domMax}>\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 ? () => {\n closeWith(\"backdrop\");\n }\n : undefined\n }\n style={backdropStyle}\n transition={spring}\n />\n )}\n </AnimatePresence>\n )}\n\n <RemoveScroll enabled={shouldLockScroll} forwardProps ref={panelWrapperRef}>\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 const shouldRender = depth <= config.stacking.renderThreshold;\n const Content = componentMap.get(item.type) ?? getStaticContent(sheets, item.type);\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 keyboardInset={keyboardInset}\n layout={layout}\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 </LazyMotion>\n );\n};\n","import type { ReactNode } from \"react\";\nimport { useEffect, useState } from \"react\";\nimport { createPortal } from \"react-dom\";\n\n/**\n * Minimal client-only portal into `document.body`. Replaces\n * `@radix-ui/react-portal` — Base UI ships no standalone portal primitive, and\n * the sheet renderer only ever runs on the client. Mounting is deferred to an\n * effect so server render and first client render agree (no hydration\n * mismatch).\n */\nexport const SheetPortal = ({ children }: { children: ReactNode }): ReactNode => {\n const [mounted, setMounted] = useState(false);\n useEffect(() => {\n setMounted(true);\n }, []);\n if (!mounted || typeof document === \"undefined\") {\n return null;\n }\n return createPortal(children, document.body);\n};\n","import type { SheetPresentationOptions } from \"../types\";\nimport type { AnyComponent, ResolvedItem } from \"./store-types\";\n\ndeclare global {\n var process:\n | undefined\n | {\n env?: {\n NODE_ENV?: string;\n };\n };\n}\n\nconst isRecord = (value: unknown): value is Record<string, unknown> =>\n typeof value === \"object\" && value !== null;\n\nexport const toRecord = (value: unknown): Record<string, unknown> => (isRecord(value) ? value : {});\n\nexport const isComponent = (value: unknown): value is AnyComponent => typeof value === \"function\";\n\nconst getComponentName = (component: AnyComponent): string | undefined => {\n const name = component.displayName ?? component.name;\n return name === \"\" ? undefined : name;\n};\n\nconst getNodeEnv = (): string | undefined => globalThis.process?.env?.NODE_ENV;\n\n/**\n * Generate a unique sheet id. `crypto.randomUUID` is only available in\n * secure contexts, so fall back to a timestamp + random suffix on\n * non-secure origins (e.g. plain-HTTP LAN dev servers).\n */\nexport const generateSheetId = (): string => {\n if (typeof globalThis.crypto?.randomUUID === \"function\") {\n return globalThis.crypto.randomUUID();\n }\n return `sheet-${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 10)}`;\n};\n\nexport const getStringArg = (value: unknown, name: string): string => {\n if (typeof value !== \"string\") {\n throw new TypeError(`Expected ${name} to be a string.`);\n }\n return value;\n};\n\nexport const resolvePresentationOptions = (\n value: unknown,\n): SheetPresentationOptions | undefined => {\n if (!isRecord(value)) {\n return undefined;\n }\n const { ariaLabel } = value;\n if (ariaLabel !== undefined && typeof ariaLabel !== \"string\") {\n return undefined;\n }\n return ariaLabel === undefined ? {} : { ariaLabel };\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 */\nexport const warnInlineComponent = (\n component: AnyComponent,\n componentRegistry: Map<AnyComponent, string>,\n warnedNames: Set<string>,\n): void => {\n if (getNodeEnv() === \"production\") {\n return;\n }\n const name = getComponentName(component);\n if (name === undefined) {\n return;\n }\n if (warnedNames.has(name)) {\n return;\n }\n for (const [existing, key] of componentRegistry) {\n const existingName = getComponentName(existing);\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\nexport const registerComponent = (\n component: AnyComponent,\n componentRegistry: Map<AnyComponent, string>,\n componentMap: Map<string, AnyComponent>,\n getNextKey: () => string,\n warnedNames: Set<string>,\n): string => {\n const existingKey = componentRegistry.get(component);\n if (existingKey !== undefined) {\n return existingKey;\n }\n\n warnInlineComponent(component, componentRegistry, warnedNames);\n const nextKey = getNextKey();\n componentRegistry.set(component, nextKey);\n componentMap.set(nextKey, component);\n return nextKey;\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 */\nexport const 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 fourth?: unknown,\n): ResolvedItem => {\n if (isComponent(first)) {\n const typeKey = registerComponent(\n first,\n componentRegistry,\n componentMap,\n getNextKey,\n warnedNames,\n );\n if (typeof second === \"string\") {\n return {\n ariaLabel: resolvePresentationOptions(fourth)?.ariaLabel,\n data: toRecord(third),\n id: second,\n type: typeKey,\n };\n }\n return {\n ariaLabel: resolvePresentationOptions(third)?.ariaLabel,\n data: toRecord(second),\n id: generateSheetId(),\n type: typeKey,\n };\n }\n return {\n ariaLabel: resolvePresentationOptions(fourth)?.ariaLabel,\n data: toRecord(third),\n id: getStringArg(second, \"sheet id\"),\n type: getStringArg(first, \"sheet type\"),\n };\n};\n","import { createStore } from \"zustand\";\nimport type { StateCreator } from \"zustand\";\nimport type { ResolvedConfig, SheetItem } from \"../types\";\nimport {\n getStringArg,\n isComponent,\n registerComponent,\n resolveArgs,\n resolvePresentationOptions,\n toRecord,\n} from \"./store-args\";\nimport type { AnyComponent, ResolvedItem, SheetStoreBundle, StoreState } from \"./store-types\";\n\nconst createItem = ({ type, id, data, ariaLabel }: ResolvedItem): SheetItem => ({\n ariaLabel,\n data,\n id,\n type,\n});\n\ninterface StoreInternals {\n componentMap: Map<string, AnyComponent>;\n componentRegistry: Map<AnyComponent, string>;\n config: ResolvedConfig;\n getNextKey: () => string;\n pruneRegistry: (remainingStack: readonly SheetItem[]) => void;\n resolve: (first: unknown, second: unknown, third: unknown, fourth?: unknown) => ResolvedItem;\n warnedNames: Set<string>;\n}\n\ntype StoreSet<TMap extends object> = Parameters<StateCreator<StoreState<TMap>>>[0];\ntype StoreGet<TMap extends object> = Parameters<StateCreator<StoreState<TMap>>>[1];\n\ninterface ResolvedWriters {\n openResolved: (resolved: ResolvedItem) => void;\n pushResolved: (resolved: ResolvedItem) => void;\n replaceResolved: (resolved: ResolvedItem) => void;\n}\n\nconst createResolvedWriters = <TMap extends object>(\n set: StoreSet<TMap>,\n config: ResolvedConfig,\n): ResolvedWriters => ({\n openResolved: (resolved) => {\n set({\n isOpen: true,\n stack: [createItem(resolved)],\n });\n },\n pushResolved: (resolved) => {\n set((state) => {\n const item = createItem(resolved);\n if (Number.isFinite(config.maxDepth) && state.stack.length >= config.maxDepth) {\n return {\n isOpen: true,\n stack: [...state.stack.slice(0, -1), item],\n };\n }\n return {\n isOpen: true,\n stack: [...state.stack, item],\n };\n });\n },\n replaceResolved: (resolved) => {\n set((state) => {\n const item = createItem(resolved);\n if (state.stack.length === 0) {\n return { isOpen: true, stack: [item] };\n }\n return {\n isOpen: true,\n stack: [...state.stack.slice(0, -1), item],\n };\n });\n },\n});\n\nconst createNavigate =\n <TMap extends object>(\n componentMap: Map<string, AnyComponent>,\n get: StoreGet<TMap>,\n resolve: StoreInternals[\"resolve\"],\n writers: ResolvedWriters,\n ): StoreState<TMap>[\"navigate\"] =>\n (first: unknown, second?: unknown, third?: unknown, fourth?: unknown) => {\n const resolved = resolve(first, second, third, fourth);\n const { stack } = get();\n const top = stack.at(-1);\n if (stack.length === 0) {\n writers.openResolved(resolved);\n return;\n }\n let isSameType = top?.type === resolved.type;\n if (!isSameType && isComponent(first)) {\n const topComponent = componentMap.get(top?.type ?? \"\");\n isSameType = topComponent === first;\n }\n if (isSameType) {\n writers.replaceResolved(resolved);\n return;\n }\n writers.pushResolved(resolved);\n };\n\nconst createPop =\n <TMap extends object>(\n set: StoreSet<TMap>,\n pruneRegistry: StoreInternals[\"pruneRegistry\"],\n ): StoreState<TMap>[\"pop\"] =>\n () => {\n set((state) => {\n if (state.stack.length <= 1) {\n pruneRegistry([]);\n return { isOpen: false, stack: [] };\n }\n const next = state.stack.slice(0, -1);\n pruneRegistry(next);\n return { isOpen: true, stack: next };\n });\n };\n\nconst createRemove =\n <TMap extends object>(\n set: StoreSet<TMap>,\n pruneRegistry: StoreInternals[\"pruneRegistry\"],\n ): StoreState<TMap>[\"remove\"] =>\n (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 return next.length === 0 ? { isOpen: false, stack: [] } : { stack: next };\n });\n };\n\nconst createSetData =\n <TMap extends object>(\n set: StoreSet<TMap>,\n resolve: StoreInternals[\"resolve\"],\n ): StoreState<TMap>[\"setData\"] =>\n (first: unknown, second?: unknown, third?: unknown) => {\n const { id, data } = resolve(first, second, third);\n set((state) => {\n const index = state.stack.findIndex((item) => item.id === id);\n const existing = state.stack[index];\n if (existing === undefined) {\n return state;\n }\n const updated = [...state.stack];\n updated[index] = { ...existing, data };\n return { stack: updated };\n });\n };\n\nconst createSwap =\n <TMap extends object>(\n set: StoreSet<TMap>,\n internals: Pick<\n StoreInternals,\n \"componentMap\" | \"componentRegistry\" | \"getNextKey\" | \"warnedNames\"\n >,\n ): StoreState<TMap>[\"swap\"] =>\n (first: unknown, second?: unknown, third?: unknown) => {\n const type = isComponent(first)\n ? registerComponent(\n first,\n internals.componentRegistry,\n internals.componentMap,\n internals.getNextKey,\n internals.warnedNames,\n )\n : getStringArg(first, \"sheet type\");\n const data = toRecord(second);\n const ariaLabel = resolvePresentationOptions(third)?.ariaLabel;\n set((state) => {\n const top = state.stack.at(-1);\n if (top === undefined) {\n return state;\n }\n const newStack = [...state.stack];\n newStack[newStack.length - 1] = {\n ariaLabel: ariaLabel ?? top.ariaLabel,\n data,\n id: top.id,\n type,\n };\n return { stack: newStack };\n });\n };\n\nconst createStoreState =\n <TMap extends object>({\n componentMap,\n componentRegistry,\n config,\n getNextKey,\n pruneRegistry,\n resolve,\n warnedNames,\n }: StoreInternals): StateCreator<StoreState<TMap>> =>\n (set, get) => {\n const writers = createResolvedWriters(set, config);\n\n return {\n close: () => {\n pruneRegistry([]);\n set({ isOpen: false, stack: [] });\n },\n isOpen: false,\n navigate: createNavigate(componentMap, get, resolve, writers),\n open: (first: unknown, second?: unknown, third?: unknown, fourth?: unknown) => {\n writers.openResolved(resolve(first, second, third, fourth));\n },\n pop: createPop(set, pruneRegistry),\n push: (first: unknown, second?: unknown, third?: unknown, fourth?: unknown) => {\n writers.pushResolved(resolve(first, second, third, fourth));\n },\n remove: createRemove(set, pruneRegistry),\n replace: (first: unknown, second?: unknown, third?: unknown, fourth?: unknown) => {\n writers.replaceResolved(resolve(first, second, third, fourth));\n },\n setData: createSetData(set, resolve),\n stack: [],\n swap: createSwap(set, { componentMap, componentRegistry, getNextKey, warnedNames }),\n };\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 const createSheetStore = <TMap extends object>(\n config: ResolvedConfig,\n): SheetStoreBundle<TMap> => {\n const componentRegistry = new Map<AnyComponent, string>();\n const componentMap = new Map<string, AnyComponent>();\n // Per-instance counter (not module-level) — prevents identity leaks across instances/tests\n let adhocCounter = 0;\n const getNextKey = () => {\n const key = `__adhoc_${adhocCounter}`;\n adhocCounter += 1;\n return key;\n };\n // Set of component names already warned about (avoid log spam)\n const warnedNames = new Set<string>();\n const resolve = (first: unknown, second: unknown, third: unknown, fourth?: unknown) =>\n resolveArgs(\n componentRegistry,\n componentMap,\n getNextKey,\n warnedNames,\n first,\n second,\n third,\n fourth,\n );\n /** Remove registry entries for type keys no longer in the stack */\n const 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 const store = createStore<StoreState<TMap>>()(\n createStoreState<TMap>({\n componentMap,\n componentRegistry,\n config,\n getNextKey,\n pruneRegistry,\n resolve,\n warnedNames,\n }),\n );\n return { componentMap, componentRegistry, store };\n};\n","import { createContext, use } 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 { SheetPortal } from \"./sheet-portal\";\nimport { createSheetStore } from \"./store\";\nimport type {\n ResolvedConfig,\n SheetActions,\n StacksheetConfig,\n StacksheetInstance,\n StacksheetProviderProps,\n StacksheetSnapshot,\n} from \"./types\";\n\ntype StoreState<TMap extends object> = StacksheetSnapshot<TMap> & SheetActions<TMap>;\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 const createStacksheet = <TMap extends object>(\n config?: StacksheetConfig,\n): StacksheetInstance<TMap> => {\n const resolved = resolveConfig(config);\n const { store, componentMap } = createSheetStore<TMap>(resolved);\n // Context for the store — allows multiple instances\n const StoreContext = createContext<{\n store: StoreApi<StoreState<TMap>>;\n config: ResolvedConfig;\n } | null>(null);\n const useStoreContext = () => {\n const ctx = use(StoreContext);\n if (!ctx) {\n throw new Error(\"useSheet/useStacksheetState must be used within <StacksheetProvider>\");\n }\n return ctx;\n };\n // ── Provider ────────────────────────────────\n const providerValue = { config: resolved, store };\n const StacksheetProvider = ({\n sheets,\n children,\n classNames,\n layout,\n renderHeader,\n }: StacksheetProviderProps<TMap>) => (\n <StoreContext.Provider value={providerValue}>\n {children}\n <SheetPortal>\n <SheetRenderer<TMap>\n classNames={classNames}\n componentMap={componentMap}\n config={resolved}\n layout={layout}\n renderHeader={renderHeader}\n sheets={sheets}\n store={store}\n />\n </SheetPortal>\n </StoreContext.Provider>\n );\n // ── Hooks ───────────────────────────────────\n const useSheet = (): SheetActions<TMap> => {\n const { store: s } = useStoreContext();\n // Actions are stable refs in Zustand v5 — read once, no subscription needed\n const state = s.getState();\n return {\n close: state.close,\n navigate: state.navigate,\n open: state.open,\n pop: state.pop,\n push: state.push,\n remove: state.remove,\n replace: state.replace,\n setData: state.setData,\n swap: state.swap,\n };\n };\n const useStacksheetState = (): StacksheetSnapshot<TMap> => {\n const { store: s } = useStoreContext();\n return useStore(\n s,\n useShallow((state) => ({\n isOpen: state.isOpen,\n stack: state.stack,\n })),\n );\n };\n return { StacksheetProvider, store, useSheet, useStacksheetState };\n};\n","import type { JSX } from \"react\";\nimport { useRender } from \"../render\";\nimport type { RenderProp } from \"../render\";\n\n/**\n * Renders a sheet part through `render` (or its default tag) via Base UI's\n * `useRender`. Centralising the hook here lets each part early-return before\n * constructing the element without tripping the Rules of Hooks.\n */\nexport const SheetPartElement = ({\n defaultTagName,\n props,\n render,\n}: {\n defaultTagName: keyof JSX.IntrinsicElements;\n props: Record<string, unknown>;\n render: RenderProp | undefined;\n}) => useRender({ defaultTagName, props, render });\n","import { joinClassNames } from \"@patternmode/system\";\nimport { ArrowLeftIcon } from \"../icons\";\nimport { useSheetPanel } from \"../panel-context\";\nimport { SheetPartElement } from \"./sheet-part-element\";\nimport type { SheetOptionalContentPartProps } from \"./sheet-part-types\";\n\nexport const SheetBack = ({\n render,\n className,\n style,\n children,\n}: SheetOptionalContentPartProps) => {\n const { back, isNested } = useSheetPanel();\n if (!isNested) {\n return null;\n }\n const defaults = render\n ? undefined\n : \"flex min-h-11 min-w-11 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 return (\n <SheetPartElement\n defaultTagName=\"button\"\n props={{\n \"aria-label\": children === undefined || children === null ? \"Back\" : undefined,\n children: children ?? <ArrowLeftIcon />,\n className: joinClassNames(defaults, className),\n onClick: back,\n style,\n type: render ? undefined : \"button\",\n }}\n render={render}\n />\n );\n};\n","import { ScrollArea } from \"@base-ui/react/scroll-area\";\nimport { joinClassNames } from \"@patternmode/system\";\nimport { useRender } from \"../render\";\nimport type { RenderProp } from \"../render\";\nimport type { SheetPartProps } from \"./sheet-part-types\";\n\n// When `render` is provided the consumer supplies their own scroll container,\n// so the body just forwards the structural flex classes onto it. Isolated so\n// the `useRender` hook is only ever called unconditionally.\nconst SheetBodyRendered = ({\n render,\n className,\n style,\n children,\n}: {\n render: RenderProp;\n className?: string;\n style?: SheetPartProps[\"style\"];\n children: SheetPartProps[\"children\"];\n}) =>\n useRender({\n props: {\n // `relative min-h-0 flex-1` is structural for the panel flex layout.\n children,\n className: joinClassNames(\"relative min-h-0 flex-1\", className),\n \"data-stacksheet-no-drag\": \"\",\n style,\n },\n render,\n });\n\nexport const SheetBody = ({ render, className, style, children }: SheetPartProps) => {\n if (render !== undefined) {\n return (\n <SheetBodyRendered className={className} render={render} style={style}>\n {children}\n </SheetBodyRendered>\n );\n }\n return (\n <ScrollArea.Root\n className={joinClassNames(\"relative flex min-h-0 flex-1 flex-col overflow-hidden\", className)}\n data-stacksheet-no-drag=\"\"\n style={style}\n >\n <ScrollArea.Viewport className=\"min-h-0 w-full flex-1 overscroll-contain\">\n {children}\n </ScrollArea.Viewport>\n <ScrollArea.Scrollbar\n className=\"flex w-2 touch-none select-none p-0.5 opacity-0 transition-opacity data-[hovering]:opacity-100 data-[scrolling]:opacity-100\"\n orientation=\"vertical\"\n >\n <ScrollArea.Thumb className=\"relative flex-1 rounded bg-current/15\" />\n </ScrollArea.Scrollbar>\n </ScrollArea.Root>\n );\n};\n","import { joinClassNames } from \"@patternmode/system\";\nimport { XIcon } from \"../icons\";\nimport { useSheetPanel } from \"../panel-context\";\nimport { SheetPartElement } from \"./sheet-part-element\";\nimport type { SheetOptionalContentPartProps } from \"./sheet-part-types\";\n\nexport const SheetClose = ({\n render,\n className,\n style,\n children,\n}: SheetOptionalContentPartProps) => {\n const { close } = useSheetPanel();\n const defaults = render\n ? undefined\n : \"absolute right-2 top-2 z-20 flex min-h-11 min-w-11 cursor-pointer items-center justify-center rounded-md border-none bg-transparent p-0 text-inherit opacity-50 transition-opacity duration-150 hover:opacity-100\";\n return (\n <SheetPartElement\n defaultTagName=\"button\"\n props={{\n \"aria-label\": children === undefined || children === null ? \"Close\" : undefined,\n children: children ?? <XIcon />,\n className: joinClassNames(defaults, className),\n onClick: close,\n style,\n type: render ? undefined : \"button\",\n }}\n render={render}\n />\n );\n};\n","import { useEffect } from \"react\";\nimport { useSheetPanel } from \"../panel-context\";\nimport { SheetPartElement } from \"./sheet-part-element\";\nimport type { SheetPartProps } from \"./sheet-part-types\";\n\nexport const SheetDescription = ({ render, className, style, children }: SheetPartProps) => {\n const { panelId, registerDescription } = useSheetPanel();\n useEffect(() => registerDescription(), [registerDescription]);\n return (\n <SheetPartElement\n defaultTagName=\"p\"\n props={{ children, className, id: `${panelId}-desc`, style }}\n render={render}\n />\n );\n};\n","import { joinClassNames } from \"@patternmode/system\";\nimport { SheetPartElement } from \"./sheet-part-element\";\nimport type { SheetPartProps } from \"./sheet-part-types\";\n\nexport const SheetFooter = ({ render, className, style, children }: SheetPartProps) => {\n const defaults = render ? \"shrink-0\" : \"flex shrink-0 items-center gap-2 border-t px-6 py-3\";\n return (\n <SheetPartElement\n defaultTagName=\"footer\"\n props={{ children, className: joinClassNames(defaults, className), style }}\n render={render}\n />\n );\n};\n","import { joinClassNames } from \"@patternmode/system\";\nimport { useSheetPanel } from \"../panel-context\";\nimport { SheetPartElement } from \"./sheet-part-element\";\nimport type { SheetOptionalContentPartProps } from \"./sheet-part-types\";\n\nexport const SheetHandle = ({\n render,\n className,\n style,\n children,\n}: SheetOptionalContentPartProps) => {\n const { close, back, isNested, side } = useSheetPanel();\n // The grab pill is a top-of-sheet, drag-down affordance — it only belongs on\n // a bottom sheet. Side sheets drag horizontally, so a horizontal pill at the\n // top reads as wrong; render nothing rather than misplaced chrome.\n if (side !== \"bottom\") {\n return null;\n }\n const dismiss = isNested ? back : close;\n const defaults = render\n ? undefined\n : \"flex shrink-0 cursor-grab touch-none items-center justify-center border-none bg-transparent pt-4 pb-1 text-inherit\";\n return (\n <SheetPartElement\n defaultTagName=\"button\"\n props={{\n \"aria-label\": \"Dismiss\",\n children: children ?? (\n <div aria-hidden=\"true\" className=\"h-1 w-9 rounded-sm bg-current/25\" />\n ),\n className: joinClassNames(defaults, className),\n \"data-stacksheet-handle\": \"\",\n onClick: dismiss,\n style,\n type: render ? undefined : \"button\",\n }}\n render={render}\n />\n );\n};\n","import { joinClassNames } from \"@patternmode/system\";\nimport { SheetPartElement } from \"./sheet-part-element\";\nimport type { SheetPartProps } from \"./sheet-part-types\";\n\nexport const SheetHeader = ({ render, className, style, children }: SheetPartProps) => {\n // Keep `shrink-0` even in render mode; without it, the header collapses in a\n // flex-column panel layout. No bar, no divider — just a minimal top region.\n const defaults = render ? \"shrink-0\" : \"flex shrink-0 items-center justify-between gap-3\";\n return (\n <SheetPartElement\n defaultTagName=\"header\"\n props={{ children, className: joinClassNames(defaults, className), style }}\n render={render}\n />\n );\n};\n","import { joinClassNames } from \"@patternmode/system\";\nimport { useEffect } from \"react\";\nimport { useSheetPanel } from \"../panel-context\";\nimport { SheetPartElement } from \"./sheet-part-element\";\nimport type { SheetPartProps } from \"./sheet-part-types\";\n\nexport const SheetTitle = ({ render, className, style, children }: SheetPartProps) => {\n const { panelId, registerTitle } = useSheetPanel();\n useEffect(() => registerTitle(), [registerTitle]);\n const defaults = render ? undefined : \"font-semibold text-sm\";\n return (\n <SheetPartElement\n defaultTagName=\"h2\"\n props={{\n children,\n className: joinClassNames(defaults, className),\n id: `${panelId}-title`,\n style,\n }}\n render={render}\n />\n );\n};\n","import { SheetBack } from \"./sheet-back\";\nimport { SheetBody } from \"./sheet-body\";\nimport { SheetClose } from \"./sheet-close\";\nimport { SheetDescription } from \"./sheet-description\";\nimport { SheetFooter } from \"./sheet-footer\";\nimport { SheetHandle } from \"./sheet-handle\";\nimport { SheetHeader } from \"./sheet-header\";\nimport { SheetTitle } from \"./sheet-title\";\n\n/**\n * Composable Sheet Parts for building custom Sheet layouts.\n *\n * Use with `layout=\"composable\"` on the provider to opt into composable mode:\n * no auto header or scroll wrapper, full control over the Sheet 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 Back: SheetBack,\n Body: SheetBody,\n Close: SheetClose,\n Description: SheetDescription,\n Footer: SheetFooter,\n Handle: SheetHandle,\n Header: SheetHeader,\n Title: SheetTitle,\n} as const;\n"],"mappings":";;;;;;;;;;;;;;;;AAKA,MAAM,kBAAkB,YAIH;CACnB,SAAS,OAAO;CAChB,MAAM,OAAO;CACb,WAAW,OAAO;AACpB;;;;;;;;;AAUA,MAAa,UAAU;CACrB,QAAQ,eAAeA,UAAc,MAAM;CAC3C,OAAO;EAAE,SAAS;EAAI,MAAM;EAAG,WAAW;CAAI;CAC9C,QAAQ,eAAeA,UAAc,MAAM;AAC7C;;;AChBA,MAAM,mBAAmC;CACvC,YAAY;CACZ,aAAa;CACb,QAAQ;CACR,iBAAiB;CACjB,WAAW;AACb;AACA,MAAM,eAA+B;CACnC,SAAS;CACT,QAAQ;AACV;AACA,MAAM,iBAAuE;CAC3E,WAAW;CACX,YAAY;CACZ,iBAAiB;CACjB,eAAe;CACf,gBAAgB;CAChB,aAAa;CACb,MAAM;CACN,QAAQ;CACR,YAAY;CACZ,UAAU,OAAO;CACjB,UAAU;CACV,OAAO;CACP,kBAAkB;CAClB,uBAAuB;CACvB,uBAAuB;CACvB,aAAa;CACb,YAAY,CAAC;CACb,wBAAwB;CACxB,mBAAmB;CACnB,OAAO;CACP,QAAQ;AACV;;AAGA,MAAM,eAAe,SAAiD;CACpE,IAAI,OAAO,SAAS,UAClB,OAAO;EAAE,SAAS;EAAM,QAAQ;CAAK;CAEvC,OAAO;EAAE,GAAG;EAAc,GAAG;CAAK;AACpC;;AAEA,MAAM,iBAAiB,WAA2E;CAChG,IAAI,OAAO,WAAW,UACpB,OAAO,QAAQ;CAEjB,OAAO;EAAE,GAAG,QAAQ;EAAO,GAAG;CAAO;AACvC;;AAGA,MAAa,iBAAiB,SAA2B,CAAC,MAAsB;CAC9E,MAAM,EAAE,MAAM,QAAQ,UAAU,GAAG,iBAAiB;CACpD,MAAM,gBAAgB,OAAO,YAC3B,OAAO,QAAQ,YAAY,EAAE,QAAQ,GAAG,WAAW,UAAU,KAAA,CAAS,CACxE;CAEA,OAAO;EACL,GAAG;EACH,GAAG;EACH,MAAM,YAAY,IAAI;EACtB,QAAQ,cAAc,MAAM;EAC5B,UAAU;GAAE,GAAG;GAAkB,GAAG;EAAS;CAC/C;AACF;;;;;;;ACrEA,MAAa,eAAe,eAAgC;CAC1D,MAAM,CAAC,UAAU,eAAe,SAAS,KAAK;CAC9C,gBAAgB;EACd,MAAM,MAAM,OAAO,WAAW,eAAe,aAAa,EAAE,IAAI;EAChE,YAAY,IAAI,OAAO;EACvB,MAAM,WAAW,MAA2B;GAC1C,YAAY,EAAE,OAAO;EACvB;EACA,IAAI,iBAAiB,UAAU,OAAO;EACtC,aAAa;GACX,IAAI,oBAAoB,UAAU,OAAO;EAC3C;CACF,GAAG,CAAC,UAAU,CAAC;CACf,OAAO;AACT;;AAEA,MAAa,mBAAmB,WAAiC;CAE/D,OADiB,YAAY,OAAO,UACtB,IAAI,OAAO,KAAK,SAAS,OAAO,KAAK;AACrD;;;ACrBA,MAAa,kBACX,UACA,kBACW;CACX,MAAM,CAAC,QAAQ,aAAa,SAAS,CAAC;CACtC,gBAAgB;EACd,MAAM,KAAK,SAAS;EACpB,IAAI;EACJ,IAAI,OAAO,QAAQ,eAAe;GAChC,UAAU,GAAG,YAAY;GACzB,WAAW,IAAI,gBAAgB,CAAC,WAAW;IACzC,IAAI,OACF,UAAU,MAAM,YAAY,MAAM;GAEtC,CAAC;GACD,SAAS,QAAQ,EAAE;EACrB;EACA,aAAa;GACX,UAAU,WAAW;EACvB;CACF,GAAG,CAAC,UAAU,aAAa,CAAC;CAC5B,OAAO;AACT;AACA,MAAM,0BACJ,OAAO,WAAW,cAAc,IAAK,OAAO,gBAAgB,UAAU,OAAO;AAE/E,MAAa,qBAAqB,WAA4B;CAC5D,MAAM,CAAC,QAAQ,aAAa,eAC1B,OAAO,WAAW,cAAc,KAAA,IAAY,kBAAkB,CAChE;CACA,gBAAgB;EACd,MAAM,eAAe;GACnB,UAAU,kBAAkB,CAAC;EAC/B;EACA,MAAM,YAAY,OAAO,WAAW;EACpC,IAAI,WAAW;GACb,OAAO,iBAAiB,UAAU,MAAM;GACxC,OAAO,gBAAgB,iBAAiB,UAAU,MAAM;EAC1D;EACA,aAAa;GACX,IAAI,WAAW;IACb,OAAO,oBAAoB,UAAU,MAAM;IAC3C,OAAO,gBAAgB,oBAAoB,UAAU,MAAM;GAC7D;EACF;CACF,GAAG,CAAC,CAAC;CACL,OAAO,SAAU,UAAU,IAAK;AAClC;;AAGA,MAAM,uBAAuB,IAAI,IAAI;CACnC;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;AACF,CAAC;;AAGD,MAAM,qBAAqB,OAAgC;CACzD,IAAI,EAAE,cAAc,cAClB,OAAO;CAET,IAAI,GAAG,mBACL,OAAO;CAET,IAAI,cAAc,qBAChB,OAAO;CAET,IAAI,cAAc,kBAChB,OAAO,CAAC,qBAAqB,IAAI,GAAG,IAAI;CAE1C,OAAO;AACT;;;;;;;;;;;;AAaA,MAAa,oBACX,QACA,iBACW;CACX,MAAM,CAAC,OAAO,YAAY,SAAS,CAAC;CACpC,gBAAgB;EACd,MAAM,YAAY,UAAU,OAAO,WAAW;EAC9C,MAAM,YAAY,aAAa;EAC/B,MAAM,WAAW,YAAY,OAAO,iBAAiB,KAAA;EACrD,IAAI,QAAQ;EACZ,IAAI,YAAY;EAChB,MAAM,gBAAgB;GACpB,MAAM,KAAK,SAAS;GACpB,MAAM,UAAU,kBAAkB,EAAE,KAAK,cAAc,QAAQ,UAAU,SAAS,EAAE;GAEpF,MAAM,UAAU,UAAU,SAAS,KAAK;GACxC,MAAM,gBAAgB,UAAU,UAAU,OAAO;GAGjD,MAAM,MAAM,OAAO,eAAe,UAAU,aAAa,KAAK;GAC9D,SAAS,WAAW,CAAC,SAAS,KAAK,IAAI,GAAG,GAAG,IAAI,CAAC;EACpD;EACA,MAAM,iBAAiB;GACrB,IAAI,WACF;GAEF,YAAY;GACZ,QAAQ,OAAO,4BAA4B;IACzC,YAAY;IACZ,QAAQ;GACV,CAAC;EACH;EACA,IAAI,WAAW;GACb,WAAW,iBAAiB,WAAW,QAAQ;GAC/C,WAAW,iBAAiB,YAAY,QAAQ;GAChD,UAAU,iBAAiB,UAAU,UAAU,EAAE,SAAS,KAAK,CAAC;GAEhE,UAAU,iBAAiB,UAAU,UAAU,EAAE,SAAS,KAAK,CAAC;GAGhE,SAAS;EACX;EACA,aAAa;GACX,IAAI,UAAU,GACZ,OAAO,qBAAqB,KAAK;GAEnC,WAAW,oBAAoB,WAAW,QAAQ;GAClD,WAAW,oBAAoB,YAAY,QAAQ;GACnD,UAAU,oBAAoB,UAAU,QAAQ;GAChD,UAAU,oBAAoB,UAAU,QAAQ;EAClD;CACF,GAAG,CAAC,QAAQ,YAAY,CAAC;CACzB,OAAO,SAAS,QAAQ;AAC1B;AACA,MAAM,wBACJ;;AAEF,MAAM,+BAA+B;;AAGrC,IAAI;AAEJ,MAAa,gBACX,QACA,QACA,yBACG;CACH,gBAAgB;EACd,MAAM,UAAU,SAAS,cAAc,2BAA2B;EAGlE,MAAM,WADJ,OAAO,yBAAyB,CAAC,wBAAwB,mBAAmB,eACjD,SAAS,UAAU;EAChD,IAAI,aAAa,MAAM;GACrB,8BAA8B;GAC9B,SAAS,MAAM,aAAa;GAC5B,SAAS,MAAM,YAAY,SAAS,OAAO,sBAAsB;GACjE,SAAS,MAAM,eAAe;GAC9B,SAAS,MAAM,WAAW;GAC1B,SAAS,MAAM,kBAAkB;EACnC;EACA,aAAa;GACX,IAAI,aAAa,MACf;GAKF,SAAS,MAAM,aAAa;GAC5B,SAAS,MAAM,YAAY;GAC3B,SAAS,MAAM,eAAe;GAC9B,MAAM,aAAa,IAAI,gBAAgB;GACvC,MAAM,EAAE,WAAW;GACnB,MAAM,eAAe;IACnB,WAAW,MAAM;IACjB,8BAA8B,KAAA;IAC9B,SAAS,MAAM,aAAa;IAC5B,SAAS,MAAM,WAAW;IAC1B,SAAS,MAAM,kBAAkB;GACnC;GACA,SAAS,iBACP,kBACC,UAAU;IACT,IAAI,MAAM,WAAW,YAAY,MAAM,iBAAiB,aACtD,OAAO;GAEX,GACA,EAAE,OAAO,CACX;GACA,MAAM,YAAY,iBAAiB;IACjC,IAAI,CAAC,OAAO,SACV,OAAO;GAEX,GAAG,4BAA4B;GAC/B,OAAO,iBAAiB,eAAe;IACrC,aAAa,SAAS;GACxB,CAAC;GACD,oCAAoC;IAClC,WAAW,MAAM;IACjB,8BAA8B,KAAA;GAChC;EACF;CACF,GAAG;EAAC;EAAQ,OAAO;EAAuB,OAAO;EAAuB;CAAoB,CAAC;AAC/F;;;ACvNA,MAAM,gBAAgB;AAEtB,MAAM,wBACJ,OAAO,aAAa,cAChB,KACA,OAAO,WAAW,iBAAiB,SAAS,eAAe,EAAE,QAAQ;AAE3E,MAAM,iBAAiB,OAAe,MAAc,mBAAmC;CACrF,IAAI,SAAS,MACX,OAAO;CAET,IAAI,SAAS,SAAS,SAAS,MAC7B,OAAO,QAAQ,gBAAgB;CAEjC,IAAI,SAAS,QAAQ,SAAS,KAC5B,OAAQ,QAAQ,MAAO;CAEzB,OAAO;AACT;;;;;;;AAQA,MAAM,sBAAsB,OAAkB,mBAAmC;CAC/E,IAAI,OAAO,UAAU,UACnB,OAAO,SAAS,IAAI,QAAQ,iBAAiB;CAE/C,IAAI,OAAO,UAAU,UAAU;EAC7B,MAAM,QAAQ,cAAc,KAAK,KAAK;EACtC,MAAM,WAAW,OAAO,QAAQ;EAChC,MAAM,OAAO,OAAO,QAAQ;EAC5B,IAAI,aAAa,KAAA,KAAa,SAAS,KAAA,GACrC,OAAO;EAET,OAAO,cAAc,OAAO,WAAW,QAAQ,GAAG,MAAM,cAAc;CACxE;CACA,OAAO;AACT;;;;;AAKA,MAAa,qBAAqB,QAAqB,mBAAqC;CAC1F,IAAI,OAAO,WAAW,GACpB,OAAO,CAAC;CAEV,MAAM,WAAqB,CAAC;CAC5B,KAAK,MAAM,SAAS,QAAQ;EAC1B,MAAM,KAAK,mBAAmB,OAAO,cAAc;EACnD,IAAI,KAAK,GACP,SAAS,KAAK,EAAE;CAEpB;CAEA,SAAS,MAAM,GAAG,MAAM,IAAI,CAAC;CAE7B,MAAM,UAAoB,CAAC;CAC3B,KAAK,MAAM,MAAM,UAAU;EACzB,MAAM,OAAO,QAAQ,GAAG,EAAE;EAC1B,IAAI,SAAS,KAAA,KAAa,KAAK,IAAI,KAAK,IAAI,IAAI,GAC9C,QAAQ,KAAK,EAAE;CAEnB;CACA,OAAO;AACT;;AAEA,MAAM,0BAA0B;;AAEhC,MAAM,oBAAoB;;AAE1B,MAAM,2BAA2B;;;;;;;;;;AAUjC,MAAa,kBACX,YACA,aACA,aACA,UACA,cACA,eACW;CACX,IAAI,YAAY,WAAW,GACzB,OAAO;CAIT,MAAM,cAAc,YAAY,KAAK,MAAM,cAAc,CAAC;CAE1D,MAAM,aAAa;CACnB,IAAI,YAAY;EAKd,MAAM,YAAY,gBAFA,WAAW,IAAI,IAAI;EAGrC,IAAI,YAAY,GAEd,OAAO;EAET,IAAI,aAAa,YAAY,QAE3B,OAAO,YAAY,SAAS;EAE9B,OAAO;CACT;CAOA,MAAM,eAAe,cAJnB,KAAK,IAAI,QAAQ,KAAK,0BAClB,KAAK,IAAI,KAAK,IAAI,UAAU,EAAkB,GAAG,iBAAiB,IAClE,2BACA;CAGN,MAAM,QAAQ,YAAY,MAAM;CAChC,IAAI,YAAY;CAChB,IAAI,WAAW,KAAK,IAAI,eAAe,KAAK;CAC5C,KAAK,IAAI,IAAI,GAAG,IAAI,YAAY,QAAQ,KAAK,GAAG;EAC9C,MAAM,SAAS,YAAY,MAAM;EACjC,MAAM,OAAO,KAAK,IAAI,eAAe,MAAM;EAC3C,IAAI,OAAO,UAAU;GACnB,WAAW;GACX,YAAY;EACd;CACF;CAIA,IADoB,KAAK,IAAI,eAAe,WAC9B,KAAK,UACjB,OAAO;CAET,OAAO;AACT;;;;;AAKA,MAAa,iBACX,WACA,aACA,gBACW;CACX,IAAI,YAAY,KAAK,aAAa,YAAY,QAC5C,OAAO;CAGT,OAAO,eADc,YAAY,cAAc;AAEjD;;;ACtJA,MAAM,mBAAuC;CAC3C,UAAU;CACV,OAAO;AACT;AACA,MAAa,qBAAqB,OAAkD;CAClF,IAAI,CAAC,IACH,OAAO;CAET,OAAO;EACL,UAAU,GAAG,YAAY;EACzB,OAAO,GAAG,SAAS;CACrB;AACF;AACA,MAAa,kBAAkB,EAC7B,WACA,gBACA,UACA,cACA,SACA,OACA,cASwC;CACxC,IAAI,CAAC,OACH,OAAO,CAAC;CAEV,MAAM,QAA4C,EAAE,MAAM,SAAS;CACnE,IAAI,SACF,MAAM,gBAAgB;CAExB,IAAI,cAAc;EAIhB,IAAI,UACF,MAAM,qBAAqB,GAAG,QAAQ;OAEtC,MAAM,gBAAgB;EAExB,IAAI,gBACF,MAAM,sBAAsB,GAAG,QAAQ;CAE3C,OACE,MAAM,gBAAgB;CAExB,OAAO;AACT;AACA,MAAa,oBACX,MACA,WAIG;CACH,IAAI,WAAW,GACb,OAAO,CAAC;CAEV,QAAQ,MAAR;EACE,KAAK,SACH,OAAO,EAAE,GAAG,OAAO;EAErB,KAAK,QACH,OAAO,EAAE,GAAG,CAAC,OAAO;EAEtB,KAAK,UACH,OAAO,EAAE,GAAG,OAAO;EAErB,SACE,OAAO,CAAC;CAEZ;AACF;AACA,MAAa,eAAe;CAC1B,UAAU;CACV,MAAM;CACN,MAAM;AACR;AACA,MAAM,YAAY;AAClB,MAAM,YACJ;AACF,MAAa,aAAa,aAA+B,WAAW,YAAY;;;;;;;;;AAUhF,MAAM,wBAAwB,eAAuB,mBAA2C;CAC9F,IAAI,iBAAiB,GACnB,OAAO,CAAC;CAEV,OAAO,iBAAiB,EAAE,eAAe,cAAc,IAAI,EAAE,QAAQ,cAAc;AACrF;AAEA,MAAa,mBACX,aACA,OACA,eACA,YACA,eACA,oBACmB;CACnB,GAAG;CACH,GAAG,qBAAqB,eAAe,cAAc;CACrD,eAAe,QAAQ,SAAS;CAChC,GAAI,QAAQ,CAAC,IAAI,EAAE,SAAS,qBAAqB;CACjD,GAAI,aAAa,EAAE,YAAY,OAAO,IAAI,CAAC;CAC3C,GAAI,gBACA,CAAC,IACD;EACE,YAAY;EACZ,aAAa;CACf;AACN;AACA,MAAa,wBACX,YACA,OACA,QACA,gBACG;CACH,IAAI,YACF,OAAO;EAAE,UAAU;EAAG,MAAM;CAAiB;CAG/C,OAAO;EAAE,GADI,QAAQ,SAAS;EACZ,cAAc;EAAc,WAAW;CAAa;AACxE;AACA,MAAa,sBACX,MACA,aACA,iBACA,mBACW;CACX,IAAI,SAAS,YAAY,YAAY,WAAW,KAAK,kBAAkB,GACrE,OAAO;CAET,OAAO,cAAc,iBAAiB,aAAa,cAAc;AACnE;AACA,MAAa,0BAA0B,mBAAmC;CACxE,IAAI,iBAAiB,GACnB,OAAO;CAET,IAAI,OAAO,WAAW,aACpB,OAAO,OAAO;CAEhB,OAAO;AACT;AACA,MAAa,oBACX,MACA,WACA,mBACgB;CAChB,IAAI,SAAS,UACX,OAAO;CAET,OAAO,EAAE,GAAG,uBAAuB,cAAc,EAAE;AACrD;AACA,MAAa,sBACX,aACA,aAIA,YAIA,WACA,gBACA,YACA,aACA,UACG;CACH,MAAM,OAAO;EACX,GAAG;EACH,GAAG;EACH,GAAG;EACH,GAAG;EACH,WAAW,UAAU,CAAC,KAAK;EAC3B,SAAS,UAAU;EACnB,OAAO,UAAU;EACjB;CACF;CACA,IAAI,cAAc,GAChB,OAAO;EAAE,GAAG;EAAM,IAAI,WAAW,KAAK,KAAK;CAAY;CAEzD,OAAO;AACT;AACA,MAAa,oBAAoB,SAAuC;CACtE,IAAI,SAAS,UACX,OAAO;EACL,wBAAwB;EACxB,yBAAyB;EACzB,qBAAqB;EACrB,sBAAsB;CACxB;CAEF,OAAO,EAAE,cAAc,EAAE;AAC3B;;;;ACtNA,MAAa,mBAAmB,IAAI,IAAI;CAAC;CAAS;CAAY;CAAU;CAAU;AAAG,CAAC;;AAStF,MAAa,qBAAqB;;;ACNlC,MAAa,wBAAwB,OAAyB;CAC5D,IAAI,iBAAiB,IAAI,GAAG,OAAO,GACjC,OAAO;CAET,IAAI,cAAc,eAAe,GAAG,mBAClC,OAAO;CAGT,IAAI,GAAG,QAAQ,uDAAuD,GACpE,OAAO;CAET,IAAI,GAAG,QAAQ,2BAA2B,GACxC,OAAO;CAET,OAAO;AACT;;;;;AAKA,MAAa,0BAA0B,IAAa,SAAmC;CACrF,IAAI,UAA0B;CAC9B,OAAO,SAAS;EACd,IAAI,mBAAmB,aAAa;GAClC,MAAM,QAAQ,iBAAiB,OAAO;GACtC,MAAM,WAAW,SAAS,MAAM,MAAM,YAAY,MAAM;GACxD,IAAI,aAAa,UAAU,aAAa;QAEpC,SAAS,MACL,QAAQ,eAAe,QAAQ,eAC/B,QAAQ,cAAc,QAAQ,aAElC,OAAO;GAAA;EAGb;EACA,UAAU,QAAQ;CACpB;CACA,OAAO;AACT;;;;;;AAMA,MAAM,kBAAkB,IAAa,MAAgB,SAA4B;CAC/E,IAAI,SAAS,KAGX,OAAO,SAAS,IAAI,GAAG,aAAa,IAAI,GAAG,YAAY,GAAG,gBAAgB,GAAG,eAAe;CAE9F,OAAO,SAAS,IAAI,GAAG,cAAc,IAAI,GAAG,aAAa,GAAG,eAAe,GAAG,cAAc;AAC9F;;;;;;;AAOA,MAAa,kBACX,SAIG;CACH,QAAQ,MAAR;EACE,KAAK,SACH,OAAO;GAAE,MAAM;GAAK,MAAM;EAAE;EAE9B,KAAK,QACH,OAAO;GAAE,MAAM;GAAK,MAAM;EAAG;EAE/B,KAAK,UACH,OAAO;GAAE,MAAM;GAAK,MAAM;EAAE;EAE9B,SACE,OAAO;GAAE,MAAM;GAAK,MAAM;EAAE;CAEhC;AACF;;;;;;AAMA,MAAM,mBACJ,IACA,IACA,MACA,SACoB;CACpB,MAAM,QAAQ,KAAK,IAAI,EAAE;CACzB,MAAM,QAAQ,KAAK,IAAI,EAAE;CAEzB,IAAI;CACJ,IAAI,SAAS,KACX,WAAW,UAAU,IAAI,KAAM,KAAK,KAAK,QAAQ,KAAK,IAAI,MAAO,KAAK;MAEtE,WAAW,UAAU,IAAI,KAAM,KAAK,KAAK,QAAQ,KAAK,IAAI,MAAO,KAAK;CAExE,IAAI,WAAA,IACF,OAAO;CAIT,KADmB,SAAS,MAAM,KAAK,MACtB,OAAO,GACtB,OAAO;CAET,OAAO;AACT;;AAEA,MAAa,iBACX,IACA,IACA,MACA,MACA,aACoB;CAEpB,IADgB,gBAAgB,IAAI,IAAI,MAAM,IACpC,MAAM,QACd,OAAO;CAET,IAAI,aAAa,QAAQ,CAAC,eAAe,UAAU,MAAM,IAAI,GAC3D,OAAO;CAET,OAAO;AACT;AACA,MAAa,qBAAqB,OAA8B,SAA2B;CACzF,IAAI,CAAC,OACH,OAAO;CAET,OAAO,SAAS,MAAM,MAAM,cAAc,MAAM;AAClD;;AC5HA,MAAM,cAAc;;;;;AAMpB,MAAa,wBACX,SACA,WACqB;CACrB,QAAQ,KAAK,MAAM;CACnB,MAAM,SAAS,OAAO,OAAA;CACtB,OAAO,QAAQ,SAAS,eAAgB,QAAQ,SAAS,MAAM,QAAQ,IAAI,QAAQ,KAAK,QACtF,QAAQ,MAAM;CAEhB,OAAO;AACT;;;;;;;;;AAUA,MAAa,sBAAsB,SAA2B,gBAAgC;CAC5F,MAAM,SAAS,cAAA;CACf,MAAM,SAAS,QAAQ,QAAQ,WAAW,OAAO,QAAQ,MAAM;CAC/D,MAAM,CAAC,SAAS;CAChB,MAAM,OAAO,OAAO,GAAG,EAAE;CACzB,IAAI,UAAU,KAAA,KAAa,SAAS,KAAA,KAAa,KAAK,QAAQ,MAAM,MAClE,OAAO;CAET,QAAQ,KAAK,SAAS,MAAM,WAAW,KAAK,OAAO,MAAM;AAC3D;;;ACnBA,MAAM,iBAAiB,EACrB,cACA,WACA,YACA,iBACA,eACc;CACd,SAAS,UAAU;CACnB,aAAa,UAAU;CACvB,UAAU,UAAU;CACpB,WAAW,UAAU,CAAC;CACtB,gBAAgB,UAAU;AAC5B;AAEA,MAAM,sBAAsB,EAC1B,MACA,QACA,cACA,UACA,MACA,WAQI;CACJ,MAAM,gBAAgB;EACpB,IAAI,OAAO,UACT,OAAO,MAAM;OAEb,OAAO,QAAQ;CAEnB;CACA,MAAM,qBAAqB,MAAoB;EAC7C,IAAI,CAAC,OAAO,WAAW,EAAE,WAAW,KAAK,EAAE,EAAE,kBAAkB,UAC7D;EAEF,MAAM,EAAE,WAAW;EACnB,MAAM,WAAW,OAAO,QAAQ,0BAA0B,MAAM;EAChE,IAAI,CAAC,YAAY,qBAAqB,MAAM,GAC1C;EAEF,KAAK,gBAAgB,UAAU,WAAW,OAAO,uBAAuB,QAAQ,IAAI;EACpF,KAAK,SAAS,UAAU;GAAE,GAAG,EAAE;GAAS,GAAG,EAAE;EAAQ;EACrD,KAAK,aAAa,UAAU;EAC5B,KAAK,UAAU,UAAU;EACzB,KAAK,WAAW,UAAU,CAAC;GAAE,QAAQ;GAAG,MAAM,KAAK,IAAI;EAAE,CAAC;CAI5D;CACA,MAAM,qBAAqB,MAAoB;EAC7C,IAAI,KAAK,SAAS,YAAY,MAC5B;EAEF,MAAM,KAAK,EAAE,UAAU,KAAK,SAAS,QAAQ;EAC7C,MAAM,KAAK,EAAE,UAAU,KAAK,SAAS,QAAQ;EAC7C,MAAM,OAAO,KAAK,MAAM,IAAI,EAAE;EAC9B,IAAI,KAAK,aAAa,YAAY,QAAQ,OAAA,IACxC;EAEF,IAAI,KAAK,aAAa,YAAY,MAAM;GACtC,KAAK,aAAa,UAAU,cAAc,IAAI,IAAI,MAAM,MAAM,KAAK,gBAAgB,OAAO;GAC1F,IAAI,KAAK,aAAa,YAAY,QAAQ;IACxC,KAAK,SAAS,UAAU;IACxB;GACF;GAGA,IAAI,EAAE,yBAAyB,aAC7B,EAAE,cAAc,kBAAkB,EAAE,SAAS;EAEjD;EACA,IAAI,KAAK,aAAa,YAAY,QAChC;EAGF,MAAM,eADY,SAAS,MAAM,KAAK,MACN;EAChC,MAAM,gBACJ,eAAe,IAAI,cAAc,CAAC,KAAK,KAAK,KAAK,IAAI,WAAW,CAAC,IAAI;EACvE,KAAK,UAAU,UAAU;EACzB,qBAAqB,KAAK,WAAW,SAAS;GAAE,QAAQ;GAAe,MAAM,KAAK,IAAI;EAAE,CAAC;EACzF,aAAa;GAAE,YAAY;GAAM,QAAQ;EAAc,CAAC;EACxD,EAAE,eAAe;CACnB;CACA,MAAM,wBAAwB;EAC5B,IAAI,KAAK,SAAS,YAAY,QAAQ,KAAK,aAAa,YAAY,QAAQ;GAC1E,cAAc,IAAI;GAClB;EACF;EACA,MAAM,SAAS,KAAK,IAAI,GAAG,KAAK,UAAU,OAAO;EAIjD,MAAM,WAAW,mBAAmB,KAAK,WAAW,SAAS,KAAK,IAAI,CAAC;EACvE,cAAc,IAAI;EAClB,MAAM,YAAY,kBAAkB,SAAS,SAAS,IAAI;EAC1D,IAAI,OAAO,YAAY,SAAS,GAAG;GACjC,MAAM,cAAc,eAClB,QACA,WACA,OAAO,aACP,UACA,OAAO,iBACP,OAAO,UACT;GACA,IAAI,gBAAgB,IAClB,QAAQ;QACH;IACL,OAAO,OAAO,WAAW;IACzB,aAAa;KAAE,YAAY;KAAO,QAAQ;IAAE,CAAC;GAC/C;GACA;EACF;EACA,MAAM,gBAAgB,SAAS,YAAY,OAAO;EAClD,MAAM,aAAa,WAAW,OAAO;EACrC,IAAI,iBAAiB,YACnB,QAAQ;OAER,aAAa;GAAE,YAAY;GAAO,QAAQ;EAAE,CAAC;CAEjD;CACA,MAAM,4BAA4B;EAChC,cAAc,IAAI;EAClB,aAAa;GAAE,YAAY;GAAO,QAAQ;EAAE,CAAC;CAC/C;CACA,OAAO;EAAE;EAAqB;EAAmB;EAAmB;CAAgB;AACtF;;;;;;;;;;;;;;;;;AAkBA,MAAa,WACX,UACA,QACA,iBACG;CACH,MAAM,WAAW,OAGP,IAAI;CACd,MAAM,eAAe,OAA0B,IAAI;CACnD,MAAM,YAAY,OAAO,CAAC;CAC1B,MAAM,aAAa,OAAyB,CAAC,CAAC;CAC9C,MAAM,kBAAkB,OAAuB,IAAI;CACnD,MAAM,EAAE,MAAM,SAAS,eAAe,OAAO,IAAI;CAEjD,MAAM,EAAE,qBAAqB,mBAAmB,mBAAmB,oBACjE,mBAAmB;EAAE;EAAM;EAAQ;EAAc;EAAU,MAAA;GAF9C;GAAc;GAAW;GAAY;GAAiB;EAEL;EAAG;CAAK,CAAC;CACzE,MAAM,cAAc,OAAO;EACzB;EACA;EACA;EACA;CACF,CAAC;CACD,YAAY,UAAU;EACpB;EACA;EACA;EACA;CACF;CAEA,gBAAgB;EACd,MAAM,KAAK,SAAS;EACpB,MAAM,iBAAiB,UAAwB;GAC7C,YAAY,QAAQ,kBAAkB,KAAK;EAC7C;EACA,MAAM,iBAAiB,UAAwB;GAC7C,YAAY,QAAQ,kBAAkB,KAAK;EAC7C;EACA,MAAM,oBAAoB;GACxB,YAAY,QAAQ,gBAAgB;EACtC;EACA,MAAM,wBAAwB;GAC5B,YAAY,QAAQ,oBAAoB;EAC1C;EACA,MAAM,YAAY,OAAO,QAAQ,OAAO;EACxC,IAAI,WAAW;GACb,GAAG,iBAAiB,eAAe,aAAa;GAChD,GAAG,iBAAiB,eAAe,aAAa;GAChD,GAAG,iBAAiB,aAAa,WAAW;GAC5C,GAAG,iBAAiB,iBAAiB,eAAe;EACtD;EACA,aAAa;GACX,IAAI,WAAW;IACb,GAAG,oBAAoB,eAAe,aAAa;IACnD,GAAG,oBAAoB,eAAe,aAAa;IACnD,GAAG,oBAAoB,aAAa,WAAW;IAC/C,GAAG,oBAAoB,iBAAiB,eAAe;GACzD;EACF;CACF,GAAG,CAAC,UAAU,OAAO,OAAO,CAAC;AAC/B;;;ACnNA,MAAa,oBAAoB,cAA6C,IAAI;;;;;AAKlF,MAAa,sBAA8C;CACzD,MAAM,MAAM,IAAI,iBAAiB;CACjC,IAAI,CAAC,KACH,MAAM,IAAI,MACR,sIAEF;CAEF,OAAO;AACT;;;;;;;;AC/BA,MAAa,sBAAsB;;;;;;AAanC,MAAa,qBAAqB,OAAe,aAA6C;CAC5F,IAAI,SAAS,GACX,OAAO;EAAE,cAAc;EAAG,QAAQ;EAAG,SAAS;EAAG,OAAO;CAAE;CAE5D,MAAM,kBAAkB,SAAS,SAAS;CAE1C,MAAM,cAAc,kBAAkB,SAAS,kBAAkB,IAAI;CACrE,OAAO;EACL,cAAc,SAAS;EACvB,QAAQ,cAAc,SAAS;EAC/B,SAAS,kBAAkB,IAAI,KAAK,IAAI,GAAG,IAAI,cAAc,SAAS,WAAW;EACjF,OAAO,KAAK,IAAI,IAAK,IAAI,cAAc,SAAS,SAAS;CAC3D;AACF;;;;;;AAMA,MAAa,2BACX,MACA,OACA,aAC2B;CAC3B,IAAI,SAAS,UAAU;EACrB,MAAM,SAAS,QAAQ,IAAI,SAAS,SAAS;EAC7C,OAAO;GACL,wBAAwB;GACxB,yBAAyB;GACzB,qBAAqB;GACrB,sBAAsB;EACxB;CACF;CAEA,IAAI,QAAQ,GACV,OAAO,EAAE,cAAc,SAAS,OAAO;CAEzC,OAAO,EAAE,cAAc,EAAE;AAC3B;;AAOA,MAAa,gBAAgB,SAA8B;CACzD,QAAQ,MAAR;EACE,KAAK,SACH,OAAO,EAAE,GAAG,OAAO;EAErB,KAAK,QACH,OAAO,EAAE,GAAG,QAAQ;EAEtB,KAAK,UACH,OAAO,EAAE,GAAG,OAAO;EAErB,SACE,OAAO,EAAE,GAAG,OAAO;CAEvB;AACF;;AAEA,MAAa,wBAAqC;CAAE,GAAG;CAAG,GAAG;AAAE;;AAE/D,MAAa,kBACX,MACA,WAIG;CACH,IAAI,WAAW,GACb,OAAO,CAAC;CAEV,QAAQ,MAAR;EACE,KAAK,SACH,OAAO,EAAE,GAAG,CAAC,OAAO;EAEtB,KAAK,QACH,OAAO,EAAE,GAAG,OAAO;EAErB,KAAK,UACH,OAAO,EAAE,GAAG,CAAC,OAAO;EAEtB,SACE,OAAO,CAAC;CAEZ;AACF;;AAGA,MAAM,sBAAsB,SAAuB;CACjD,IAAI,SAAS,SACX,OAAO;CAET,IAAI,SAAS,QACX,OAAO;CAET,OAAO;AACT;;;;AAKA,MAAa,kBACX,MACA,QACA,UACkB;CAClB,MAAM,EAAE,OAAO,UAAU,WAAW;CACpC,MAAM,OAAsB;EAC1B,SAAS;EACT,eAAe;EAGf,SAAS;EACT,UAAU;EACV,iBAAiB,mBAAmB,IAAI;EACxC,YAAY;EACZ,QAAQ,SAAS,KAAK;CACxB;CACA,IAAI,SAAS,UACX,OAAO;EACL,GAAG;EACH,QAAQ;EAER,QAAQ;EACR,MAAM;EAEN,WAAW;EACX,OAAO;CACT;CAGF,MAAM,aACJ,SAAS,UAAU;EAAE,QAAQ;EAAG,OAAO;EAAG,KAAK;CAAE,IAAI;EAAE,QAAQ;EAAG,MAAM;EAAG,KAAK;CAAE;CACpF,OAAO;EACL,GAAG;EACH,GAAG;EACH;EACA;CACF;AACF;;;;AClKA,MAAa,sBACX,oBAAC,OAAD;CACE,eAAY;CACZ,MAAK;CACL,QAAQ;CACR,QAAO;CACP,eAAc;CACd,gBAAe;CACf,aAAa;CACb,SAAQ;CACR,OAAO;WAEP,oBAAC,QAAD,EAAM,GAAE,0BAA2B,CAAA;AAChC,CAAA;AAEP,MAAa,cACX,oBAAC,OAAD;CACE,eAAY;CACZ,MAAK;CACL,QAAQ;CACR,QAAO;CACP,eAAc;CACd,gBAAe;CACf,aAAa;CACb,SAAQ;CACR,OAAO;WAEP,oBAAC,QAAD,EAAM,GAAE,uBAAwB,CAAA;AAC7B,CAAA;;;ACxBP,MAAa,iBAAiB,EAAE,UAAU,QAAQ,cAChD,qBAAA,UAAA,EAAA,UAAA,CACG,YACC,oBAAC,UAAD;CACE,cAAW;CACX,WAAU;CACV,SAAS;CACT,MAAK;WAEL,oBAAC,eAAD,CAAgB,CAAA;AACV,CAAA,GAEV,oBAAC,UAAD;CACE,cAAW;CACX,WAAU;CACV,SAAS;CACT,MAAK;WAEL,oBAAC,OAAD,CAAQ,CAAA;AACF,CAAA,CACR,EAAA,CAAA;;;ACpBJ,MAAa,qBAAqB,EAChC,cACA,cACA,SACA,MACA,cACA,kBAQI;CACJ,IAAI,cACF,OAAO,gBAAgB,YAAY,KAAA,IAAY,oBAAC,SAAD,EAAS,GAAI,KAAO,CAAA,IAAI;CAEzE,MAAM,eACJ,iBAAiB,KAAA,KAAa,iBAAiB,QAAQ,eAAe,KAAA;CAExE,OACE,qBAAA,UAAA,EAAA,UAAA,CACG,iBAAiB,KAAA,IAAY,oBAAC,eAAD,EAAe,GAAI,YAAc,CAAA,IAAI,aAAa,WAAW,GAC1F,gBAAgB,YAAY,KAAA,KAC3B,oBAAC,OAAD;EACE,WAAU;EACV,2BAAwB;YAExB,oBAAC,SAAD,EAAS,GAAI,KAAO,CAAA;CACjB,CAAA,CAEP,EAAA,CAAA;AAEN;AAEA,kBAAkB,cAAc;;;AClChC,MAAM,0BAA0B;CAE9B;CACA;CAEA;CAGA;CAEA;CACA;CACA;CACA;AACF,EAAE,KAAK,IAAI;AAEX,MAAM,0BAA0B,kBAA4C;CAC1E,SAAS,iBAAiB,WAAW,eAAe,IAAI;CACxD,aAAa;EACX,SAAS,oBAAoB,WAAW,eAAe,IAAI;CAC7D;AACF;AACA,MAAM,qCAA8C;AACpD,MAAM,+BAAwC;CAC5C,IAAI,OAAO,aAAa,aACtB,OAAO;CAET,MAAM,SAAS,SAAS;CACxB,OACE,CAAC,CAAC,UACF,WAAW,SAAS,QACpB,kBAAkB,WAClB,OAAO,QAAQ,uBAAuB,MAAM;AAEhD;AACA,MAAM,0BAA0B,WAA6B;CAC3D,MAAM,UAAU,qBACd,wBACA,wBACA,4BACF;CACA,OAAO,UAAU;AACnB;AAEA,MAAa,kBAAkB,EAC7B,SACA,QACA,aACA,eAMe;CACf,MAAM,SAAS,uBAAuB,WAAW,MAAM;CACvD,IAAI,CAAC,SACH,OAAO;CAET,OACE,oBAAC,WAAD;EACU;EACR,kBAAkB;GAChB,mBAAmB;GACnB,mBAAmB;GACnB,qBAAqB;IACnB,IAAI,YAAY,YAAY,MAC1B,OAAO,YAAY;IAErB,OAAO,SAAS;GAClB;GAGA,oBAAoB,YAAY,WAAW,KAAA;GAC3C,yBAAyB;EAC3B;EACQ;EAEP;CACQ,CAAA;AAEf;;;ACnFA,MAAa,gBAAgB,EAC3B,WACA,WAAW,eAKX,oBAAC,UAAD;CACE,cAAW;CACX,WAAW,eAGT,kIAGA,aAAa,YAAY,0BAA0B,mBACrD;CACA,0BAAuB;CACvB,SAAS;CACT,MAAK;WAEL,oBAAC,OAAD;EAAK,eAAY;EAAO,WAAU;CAA0C,CAAA;AACtE,CAAA;AAEV,MAAa,cAAc,EACzB,MACA,WACA,gBAKI;CACJ,MAAM,WAA0B,SAAS,UAAU,EAAE,OAAO,OAAO,IAAI,EAAE,MAAM,OAAO;CACtF,OACE,oBAAC,EAAE,QAAH;EACE,SAAS,EAAE,SAAS,YAAY,IAAI,EAAE;EACtC,cAAW;EACX,WAAU;EACV,0BAAuB;EACvB,SAAS;EACT,OAAO;EACP,YAAY;GAAE,UAAU,YAAY,MAAO;GAAK,MAAM;EAAU;EAChE,MAAK;YAEL,oBAAC,OAAD;GAAK,eAAY;GAAO,WAAU;EAAsC,CAAA;CAChE,CAAA;AAEd;;;AClDA,MAAa,sBACX,QACA,iBACqB;CACrB,IAAI,QACF,OAAO;CAET,OAAO,iBAAiB,QAAQ,eAAe;AACjD;;;ACsBA,MAAM,qBAAqB,MAA+B,kBACxD,KAAK,cACJ,OAAO,KAAK,MAAM,gBAAgB,WAAW,KAAK,KAAK,cAAc,KAAA,MACtE;AAEF,MAAM,sBAAsB,SAAkB,iBAC5C,UACI;CACE,cAAc;EACZ,aAAa,KAAK;CACpB;CACA,eAAe;EACb,aAAa,IAAI;CACnB;CACA,oBAAoB;EAClB,aAAa,IAAI;CACnB;CACA,oBAAoB;EAClB,aAAa,KAAK;CACpB;AACF,IACA,CAAC;AAEP,MAAM,yBAAyB,UAC7B,QAAQ,CAAC,IAAI;CAAE,eAAe;CAAiB,OAAO;AAAK;AAE7D,MAAM,kBAAkB,EACtB,OACA,UACA,KACA,YACsF;CACtF;CACA,QAAQ;CACR,SAAS;CACT;AACF;AAEA,MAAM,mBAAmB,EACvB,OACA,gBACA,UACA,UACA,OACA,SACA,KACA,qBACA,eACA,YAOK;CACL,MAAM;CACN;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;AACF;AAEA,MAAM,yBAAyB,EAC7B,WACA,WACA,MACA,WAOA,OAAO,oBAAC,YAAD;CAAuB;CAAsB;CAAiB;AAAO,CAAA,IAAI;AAElF,MAAM,2BACJ,MACA,WACA,aACe,OAAO,oBAAC,cAAD;CAAyB;CAAqB;AAAW,CAAA,IAAI;AAErF,MAAM,4BACJ,eACA,OACA,sBACG;CACH,IAAI,SAAS,CAAC,cAAc,SAAS;EACnC,cAAc,UAAU;EACxB,kBAAkB,UAAU;CAC9B;AACF;AAEA,MAAM,wBAAwB,OAAgB,mBAA6C;CACzF,MAAM,gBAAgB,OAAO,KAAK;CAClC,MAAM,oBAAoB,OAAO,cAAc;CAE/C,IAAI,CAAC,SAAS,cAAc,SAC1B,cAAc,UAAU;CAE1B,gBAAgB;EACd,kBAAkB,UAAU;CAC9B,GAAG,CAAC,cAAc,CAAC;CAEnB,aAAa;EACX,yBAAyB,eAAe,OAAO,iBAAiB;CAClE;AACF;AAEA,MAAM,qBACJ,EACE,iBACA,QACA,UACA,OACA,QACA,sBACA,MACA,aACA,YACA,YAEF,aACc;CACd,MAAM,CAAC,WAAW,gBAAgB,SAAoB;EACpD,YAAY;EACZ,QAAQ;CACV,CAAC;CAED,QACE,UACA;EACE;EACA,gBAAgB,OAAO;EACvB,SAAS,SAAS,OAAO,QAAQ,OAAO,eAAe,CAAC;EACxD;EACA,SAAS;EACT,OAAO;EACP;EACA,YAAY,OAAO;EACnB;EACA;EACA,mBAAmB,OAAO;CAC5B,GACA,YACF;CAEA,OAAO;AACT;AAEA,MAAM,wBACJ,EAAE,OAAO,UAAU,OAAO,KAAK,QAC/B,YACG;CACH,MAAM,CAAC,gBAAgB,qBAAqB,SAAS,KAAK;CAC1D,MAAM,CAAC,UAAU,eAAe,SAAS,KAAK;CAE9C,MAAM,sBAAsB,kBAAkB;EAC5C,kBAAkB,IAAI;EACtB,aAAa;GACX,kBAAkB,KAAK;EACzB;CACF,GAAG,CAAC,CAAC;CAEL,MAAM,gBAAgB,kBAAkB;EACtC,YAAY,IAAI;EAChB,aAAa;GACX,YAAY,KAAK;EACnB;CACF,GAAG,CAAC,CAAC;CAgCL,OAAO;EAAE;EAAgB;EAAU,cA5Bd,cAEjB,gBAAgB;GACd;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;EACF,CAAC,GACH;GACE;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;EACF,CAG4C;CAAE;AAClD;AAEA,MAAM,sBAAsB,UAA2B;CACrD,MAAM,EACJ,MACA,OACA,OACA,OACA,UACA,MACA,QACA,YACA,KACA,OACA,aACA,eACA,iBACA,QACA,cACA,WACA,aACA,QACA,gBACE;CACJ,MAAM,WAAW,OAAuB,IAAI;CAC5C,MAAM,CAAC,WAAW,gBAAgB,SAAS,KAAK;CAEhD,MAAM,iBAAiB,eAAe,UAAU,YAAY,SAAS,CAAC;CAEtE,MAAM,YAAY,kBAAkB,OAAO,OAAO,QAAQ;CAC1D,MAAM,cAAc,eAAe,MAAM,QAAQ,KAAK;CAEtD,MAAM,0BAA0B,qBAAqB,OAAO,OAAO,cAAc;CACjF,MAAM,YAAY,kBAAkB,OAAO,QAAQ;CAEnD,MAAM,YAAY,kBAAkB,MAAM,OAAO,SAAS;CAE1D,MAAM,UAAU,cAAc,KAAK;CACnC,MAAM,EAAE,gBAAgB,UAAU,iBAAiB,qBAAqB,OAAO,OAAO;CAGtF,MAAM,eADc,mBAAmB,QAAQ,YAChB,MAAM;CACrC,MAAM,gBAAgB,WAAW,UAAU;CAC3C,MAAM,aAAa,iBAAiB,MAAM,UAAU,MAAM;CAI1D,MAAM,sBAAsB,SAAS,SAAS,WAAW,gBAAgB;CACzE,MAAM,aAAa,gBACjB,aACA,OACA,eACA,UAAU,YACV,qBACA,YAAY,WAAW,CACzB;CAEA,MAAM,cAAc,eAAe;EAAE;EAAO;EAAU;EAAK;CAAK,CAAC;CAEjE,MAAM,YAAY,eAAe;EAC/B;EACA;EACA;EACA;EACA,SAAS,OAAO;EAChB;EACA;CACF,CAAC;CAED,MAAM,aAAa,qBAAqB,UAAU,YAAY,OAAO,QAAQ,WAAW;CAExF,MAAM,iBAAiB,wBAAwB,MAAM,OAAO,OAAO,QAAQ;CAC3E,MAAM,cAAc,mBAAmB,MAAM,aAAa,iBAAiB,cAAc;CACzF,MAAM,oBAAoB,iBAAiB,MAAM,WAAW,cAAc;CAG1E,MAAM,gBAAgB,mBACpB,aAFkB,eAAe,MAAM,UAAU,MAGvC,GACV,YACA,WACA,gBACA,YACA,aACA,KACF;CAEA,MAAM,gBAAgB,iBAAiB,IAAI;CAC3C,MAAM,iBAAiB,SAAS,SAAS;CAGzC,MAAM,mBAAmB,SAAS,SAAS,YAAY,CAAC;CACxD,MAAM,UAAU,WAAW,MAAM;CACjC,MAAM,aAAa,sBAAsB;EACvC;EACA,WAAW;EACX,MAAM;EACN;CACF,CAAC;CAQD,OAAO;EACL;EACA;EACA,cAVmB,wBAAwB,kBAAkB,SAAS,OAAO,MAUlE;EACX,qBAR0B,oBAAoB,OAAO,WAAW;EAShE;EACA;EACA,YAViB,mBAAmB,gBAAgB,YAU3C;EACT,oBAVyB,sBAAsB,KAU9B;EACjB;EACA;EACA;EACA;EACA;EACA;EACA;CACF;AACF;AAEA,MAAa,cAAc,UAA2B;CACpD,MAAM,EACJ,MACA,OACA,QACA,YACA,SACA,cACA,cACA,yBACE;CACJ,MAAM,EACJ,eACA,WACA,cACA,qBACA,yBACA,aACA,YACA,oBACA,eACA,cACA,cACA,UACA,YACA,mBACA,eACE,mBAAmB,KAAK;CAE5B,MAAM,eACJ,qBAAC,EAAE,KAAH;EACE,SAAS;EACT,WAAW,WAAW,SAAS,KAAA;EAC/B,MAAM;GACJ,GAAG;GACH,WAAW,UAAU,KAAK;GAC1B,SAAS;GACT,YAAY;IACV,WAAW;IACX,UAAU,uBAAuB,IAAI;IACrC,MAAM;IACN,MAAM;GACR;EACF;EACA,SAAS;GACP,GAAG;GACH,SAAS;GACT,GAAG;GACH,WAAW,UAAU,KAAK;EAC5B;EAEA,qBAAqB;EACrB,KAAK;EACL,OAAO;EACP,UAAU,QAAQ,KAAK,KAAA;EACvB,GAAI;EACJ,GAAI;EACJ,GAAI;YA3BN;GA6BG;GACA,sBAAsB,eAAe;GACtC,qBAAC,OAAD;IAAK,WAAU;cAAf,CACG,sBAAsB,OAAO,cAC9B,oBAAC,mBAAD;KACW;KACT,MAAM,KAAK;KACE;KACC;KACA;KACA;IACf,CAAA,CACE;;EACA;IAtBA,KAAK,EAsBL;CAGT,OACE,oBAAC,kBAAkB,UAAnB;EAA4B,OAAO;YACjC,oBAAC,gBAAD;GAAgB,QAAQ;GAAO,SAAS,OAAO;GAAO,aAAa;aAChE;EACa,CAAA;CACU,CAAA;AAEhC;;;AC3ZA,MAAM,mCAAmC;CACvC,4BAA4B;EAC1B,SAAc,KAAK;CACrB,CAAC;AACH;AAEA,MAAM,0BACJ,MACA,YACA,mBAEA,SAAS,YAAY,WAAW,SAAS,IAAI,kBAAkB,YAAY,cAAc,IAAI,CAAC;AAEhG,MAAM,8BAA8B,EAClC,kBACA,cACA,aACA,kBAOA,aAAa,YAAY,eAAe,aAAa,cAAc,YAAY,SAC3E,aAAa,QACb;AAEN,MAAM,mBAAmB,sBAA+B,WACtD,uBACK;CAAE,UAAU;CAAG,MAAM;AAAiB,IACtC;CACC,SAAS,OAAO,OAAO;CACvB,MAAM,OAAO,OAAO;CACpB,WAAW,OAAO,OAAO;CACzB,MAAM;AACR;AAEN,MAAM,oBAAoB,QAAwB,sBAA8C;CAC9F,QAAQ,OAAO,mBAAmB,OAAO,cAAc,YAAY,KAAA;CACnE,YAAY;CACZ,QAAQ,OAAO;CACf,GAAI,mBAAmB,CAAC,IAAI,EAAE,YAAY,sCAAsC;AAClF;AAaA,MAAM,sBAAsB,YAC1B,OAAO,YAAY;AAErB,MAAM,oBACJ,QACA,SACuD;CACvD,IAAI,WAAW,KAAA,GACb;CAGF,MAAM,UADQ,OAAO,QAAQ,MAAM,EAAE,MAAM,CAAC,eAAe,cAAc,IACrD,IAAI;CACxB,OAAO,mBAAmB,OAAO,IAAI,UAAU,KAAA;AACjD;AAEA,MAAM,oBACJ,UACG;CACH,MAAM,SAAS,SAAS,QAAQ,MAAM,EAAE,MAAM;CAC9C,MAAM,QAAQ,SAAS,QAAQ,MAAM,EAAE,KAAK;CAC5C,MAAM,EAAE,UAAU,WAAW,SAC3B,OACA,YAAY,OAAO;EACjB,UAAU,EAAE;EACZ,QAAQ,EAAE;CACZ,EAAE,CACJ;CACA,OAAO;EAAE;EAAQ;EAAU;EAAQ;CAAM;AAC3C;AAEA,MAAM,gBACJ,QACA,QACA,MACA,UACG;CACH,MAAM,iBAAiB,kBACrB,UAAU,SAAS,YAAY,OAAO,WAAW,SAAS,CAC5D;CACA,MAAM,cAAc,uBAAuB,MAAM,OAAO,YAAY,cAAc;CAClF,MAAM,cAAc,SAAS,MAAM,KAAK,SAAS,KAAK,EAAE,EAAE,KAAK,IAAQ,IAAI;CAC3E,MAAM,mBAAmB,YAAY,SAAS,IAAI,YAAY,SAAS,IAAI;CAC3E,MAAM,CAAC,cAAc,mBAAmB,SAAS;EAC/C,SAAS;EACT,OAAO;EACP,WAAW,YAAY;CACzB,CAAC;CACD,MAAM,oBAAoB,2BAA2B;EACnD;EACA;EACA;EACA;CACF,CAAC;CACD,MAAM,kBAAkB,OAAO,kBAAkB;CACjD,MAAM,cAAc,UAAkB;EACpC,gBAAgB;GACd,SAAS;GACT;GACA,WAAW,YAAY;EACzB,CAAC;EACD,OAAO,oBAAoB,KAAK;CAClC;CACA,OAAO;EAAE;EAAiB;EAAY;CAAY;AACpD;AAEA,MAAM,yBAAyB,QAAwB,QAAiB,SAAe;CACrF,MAAM,kBAAkB,OAAuB,IAAI;CAKnD,OAAO;EAAE,eAJa,iBACpB,UAAU,SAAS,YAAY,OAAO,kBACtC,eAEmB;EAAG;CAAgB;AAC1C;AAEA,MAAM,oBAAoB,UAAsB,WAAuB;CACrE,MAAM,iBAAiB,OAAoB,cAAc;CACzD,MAAM,aAAa,WAAwB;EACzC,eAAe,UAAU;EACzB,SAAS;CACX;CACA,MAAM,WAAW,WAAwB;EACvC,eAAe,UAAU;EACzB,OAAO;CACT;CACA,OAAO;EACL,aAAa;GACX,UAAU,cAAc;EAC1B;EACA;EACA;EACA,WAAW;GACT,QAAQ,cAAc;EACxB;EACA;CACF;AACF;AAEA,MAAM,mBAAmB,WAAoB;CAC3C,MAAM,aAAa,OAAuB,IAAI;CAC9C,MAAM,aAAa,OAAO,KAAK;CAC/B,gBAAgB;EACd,IAAI,UAAU,CAAC,WAAW,SACxB,WAAW,UAAU,SAAS;OACzB,IAAI,CAAC,UAAU,WAAW,SAAS;GACxC,MAAM,KAAK,WAAW;GACtB,IAAI,MAAM,cAAc,eAAe,OAAO,SAAS,QAAQ,GAAG,YAAY,QAC5E,GAAG,MAAM;GAEX,WAAW,UAAU;EACvB;EACA,WAAW,UAAU;CACvB,GAAG,CAAC,MAAM,CAAC;AACb;AAEA,MAAM,qBAAqB,EACzB,gBACA,UACA,QACA,qBAMI;CACJ,eAAe,UAAU;CACzB,IAAI,eAAe,UAAU,GAC3B,OAAO;MAEP,SAAS;AAEb;AAEA,MAAM,uBAAuB,EAC3B,gBACA,QACA,QACA,UACA,QACA,kBAQI;CACJ,MAAM,iBAAiB,OAAO,WAAW;CACzC,gBAAgB;EACd,eAAe,UAAU;CAC3B,GAAG,CAAC,WAAW,CAAC;CAChB,gBAAgB;EACd,MAAM,eAAe,UAAU,OAAO,iBAAiB,OAAO;EAC9D,MAAM,iBAAiB,MAAqB;GAG1C,IAAI,EAAE,QAAQ,YAAY,EAAE,kBAC1B;GAEF,EAAE,eAAe;GACjB,kBAAkB;IAAE;IAAgB;IAAU;IAAQ;GAAe,CAAC;EACxE;EACA,IAAI,cACF,SAAS,iBAAiB,WAAW,aAAa;EAEpD,aAAa;GACX,IAAI,cACF,SAAS,oBAAoB,WAAW,aAAa;EAEzD;CACF,GAAG;EAAC;EAAQ,OAAO;EAAe,OAAO;EAAa;EAAQ;EAAU;CAAc,CAAC;CACvF,gBAAgB;EACd,MAAM,0BAA0B,WAAW;EAI3C,MAAM,eACJ,UAAU,OAAO,iBAAiB,OAAO,eAAe,4BAA4B,KAAA;EACtF,IAAI;EACJ,MAAM,oBAAoB;GACxB,kBAAkB;IAAE;IAAgB;IAAU;IAAQ;GAAe,CAAC;EACxE;EACA,IAAI,cAAc;GAChB,UAAU,IAAI,wBAAwB;GACtC,QAAQ,iBAAiB,SAAS,WAAW;EAC/C;EACA,aAAa;GACX,IAAI,YAAY,KAAA,GAAW;IACzB,QAAQ,oBAAoB,SAAS,WAAW;IAChD,QAAQ,QAAQ;GAClB;EACF;CACF,GAAG;EAAC;EAAQ,OAAO;EAAe,OAAO;EAAa;EAAQ;EAAU;CAAc,CAAC;AACzF;;;;;;;;AASA,MAAa,iBAAsC,EACjD,OACA,QACA,QACA,cACA,YAAY,gBACZ,QACA,mBAC8B;CAC9B,MAAM,EAAE,QAAQ,UAAU,QAAQ,UAAU,iBAAiB,KAAK;CAClE,MAAM,OAAO,gBAAgB,MAAM;CACnC,MAAM,uBAAuB,iBAAiB,KAAK;CACnD,MAAM,aAAa,kBAAkB,cAAc;CACnD,MAAM,EAAE,iBAAiB,YAAY,gBAAgB,aAAa,QAAQ,QAAQ,MAAM,KAAK;CAC7F,MAAM,EAAE,OAAO,gBAAgB,WAAW,KAAK,YAAY,iBAAiB,UAAU,MAAM;CAC5F,MAAM,EAAE,iBAAiB,kBAAkB,sBAAsB,QAAQ,QAAQ,IAAI;CACrF,aAAa,QAAQ,QAAQ,oBAAoB;CACjD,gBAAgB,MAAM;CACtB,oBAAoB;EAClB;EACA;EACA;EACA;EACA;EACA,aAAa,MAAM;CACrB,CAAC;CACD,MAAM,YAAY,aAAa,IAAI;CACnC,MAAM,cAAc,eAAe;CACnC,MAAM,SAAS,gBAAgB,sBAAsB,MAAM;CAC3D,MAAM,cAAc;CACpB,MAAM,UAAU,OAAO;CACvB,MAAM,cAAc,WAAW,OAAO;CAEtC,MAAM,gBAAgB,iBAAiB,QADd,WAAW,aAAa,EACc;CAC/D,MAAM,2BAA2B;EAC/B,IAAI,MAAM,WAAW,GACnB,OAAO,kBAAkB,eAAe,OAAO;CAEnD;CACA,MAAM,mBAAmB;EACvB,UAAU,OAAO;CACnB;CACA,MAAM,iBAAiB;EACrB,QAAQ,OAAO;CACjB;CACA,MAAM,mBAAmB,UAAU,WAAW,OAAO;CACrD,OACE,qBAAC,YAAD;EAAY,UAAU;YAAtB,CACG,eACC,oBAAC,iBAAD;GAAiB,gBAAgB;aAC9B,UACC,oBAAC,EAAE,KAAH;IACE,SAAS,EAAE,SAAS,EAAE;IACtB,WAAW,iBAAiB,WAAW,YAAY;IACnD,MAAM,EAAE,SAAS,EAAE;IACnB,SAAS,EAAE,SAAS,EAAE;IAEtB,SACE,OAAO,mBAAmB,OAAO,oBACvB;KACJ,UAAU,UAAU;IACtB,IACA,KAAA;IAEN,OAAO;IACP,YAAY;GACb,GAVK,qBAUL;EAEY,CAAA,GAGnB,oBAAC,cAAD;GAAc,SAAS;GAAkB,cAAA;GAAa,KAAK;aACzD,oBAAC,OAAD;IACE,WAAU;IACV,OAAO,EAAE,QAAQ,OAAO,SAAS,EAAE;cAEnC,oBAAC,iBAAD;KAAiB,gBAAgB;eAC9B,MAAM,KAAK,MAAM,UAAU;MAC1B,MAAM,QAAQ,MAAM,SAAS,IAAI;MACjC,MAAM,QAAQ,UAAU;MACxB,MAAM,WAAW,QAAQ;MACzB,MAAM,eAAe,SAAS,OAAO,SAAS;MAE9C,OACE,oBAAC,YAAD;OACmB;OACjB,SAJY,aAAa,IAAI,KAAK,IAAI,KAAK,iBAAiB,QAAQ,KAAK,IAAI;OAKjE;OACL;OACC;OACD;OACA;OACG;OACH;OACD;OAES;OACP;OACR,QAAQ;OACH;OACiB;OACR;OACA;OACR;OACK;OACE;OACA;OACL;OACK;OACD;OACF;MACX,GAhBM,KAAK,EAgBX;KAEL,CAAC;IACc,CAAA;GACd,CAAA;EACO,CAAA,CACJ;;AAEhB;;;;;;;;;;ACnZA,MAAa,eAAe,EAAE,eAAmD;CAC/E,MAAM,CAAC,SAAS,cAAc,SAAS,KAAK;CAC5C,gBAAgB;EACd,WAAW,IAAI;CACjB,GAAG,CAAC,CAAC;CACL,IAAI,CAAC,WAAW,OAAO,aAAa,aAClC,OAAO;CAET,OAAO,aAAa,UAAU,SAAS,IAAI;AAC7C;;;ACPA,MAAM,YAAY,UAChB,OAAO,UAAU,YAAY,UAAU;AAEzC,MAAa,YAAY,UAA6C,SAAS,KAAK,IAAI,QAAQ,CAAC;AAEjG,MAAa,eAAe,UAA0C,OAAO,UAAU;AAEvF,MAAM,oBAAoB,cAAgD;CACxE,MAAM,OAAO,UAAU,eAAe,UAAU;CAChD,OAAO,SAAS,KAAK,KAAA,IAAY;AACnC;AAEA,MAAM,mBAAuC,WAAW,SAAS,KAAK;;;;;;AAOtE,MAAa,wBAAgC;CAC3C,IAAI,OAAO,WAAW,QAAQ,eAAe,YAC3C,OAAO,WAAW,OAAO,WAAW;CAEtC,OAAO,SAAS,KAAK,IAAI,EAAE,SAAS,EAAE,EAAE,GAAG,KAAK,OAAO,EAAE,SAAS,EAAE,EAAE,MAAM,GAAG,EAAE;AACnF;AAEA,MAAa,gBAAgB,OAAgB,SAAyB;CACpE,IAAI,OAAO,UAAU,UACnB,MAAM,IAAI,UAAU,YAAY,KAAK,iBAAiB;CAExD,OAAO;AACT;AAEA,MAAa,8BACX,UACyC;CACzC,IAAI,CAAC,SAAS,KAAK,GACjB;CAEF,MAAM,EAAE,cAAc;CACtB,IAAI,cAAc,KAAA,KAAa,OAAO,cAAc,UAClD;CAEF,OAAO,cAAc,KAAA,IAAY,CAAC,IAAI,EAAE,UAAU;AACpD;;;;;;AAMA,MAAa,uBACX,WACA,mBACA,gBACS;CACT,IAAI,WAAW,MAAM,cACnB;CAEF,MAAM,OAAO,iBAAiB,SAAS;CACvC,IAAI,SAAS,KAAA,GACX;CAEF,IAAI,YAAY,IAAI,IAAI,GACtB;CAEF,KAAK,MAAM,CAAC,UAAU,QAAQ,mBAE5B,IADqB,iBAAiB,QACvB,MAAM,MAAM;EACzB,YAAY,IAAI,IAAI;EACpB,QAAQ,KACN,qDAAqD,KAAK,yBAC/C,IAAI,mQAIjB;EACA;CACF;AAEJ;AAEA,MAAa,qBACX,WACA,mBACA,cACA,YACA,gBACW;CACX,MAAM,cAAc,kBAAkB,IAAI,SAAS;CACnD,IAAI,gBAAgB,KAAA,GAClB,OAAO;CAGT,oBAAoB,WAAW,mBAAmB,WAAW;CAC7D,MAAM,UAAU,WAAW;CAC3B,kBAAkB,IAAI,WAAW,OAAO;CACxC,aAAa,IAAI,SAAS,SAAS;CACnC,OAAO;AACT;;;;;AAKA,MAAa,eACX,mBACA,cACA,YACA,aACA,OACA,QACA,OACA,WACiB;CACjB,IAAI,YAAY,KAAK,GAAG;EACtB,MAAM,UAAU,kBACd,OACA,mBACA,cACA,YACA,WACF;EACA,IAAI,OAAO,WAAW,UACpB,OAAO;GACL,WAAW,2BAA2B,MAAM,GAAG;GAC/C,MAAM,SAAS,KAAK;GACpB,IAAI;GACJ,MAAM;EACR;EAEF,OAAO;GACL,WAAW,2BAA2B,KAAK,GAAG;GAC9C,MAAM,SAAS,MAAM;GACrB,IAAI,gBAAgB;GACpB,MAAM;EACR;CACF;CACA,OAAO;EACL,WAAW,2BAA2B,MAAM,GAAG;EAC/C,MAAM,SAAS,KAAK;EACpB,IAAI,aAAa,QAAQ,UAAU;EACnC,MAAM,aAAa,OAAO,YAAY;CACxC;AACF;;;AC9IA,MAAM,cAAc,EAAE,MAAM,IAAI,MAAM,iBAA0C;CAC9E;CACA;CACA;CACA;AACF;AAqBA,MAAM,yBACJ,KACA,YACqB;CACrB,eAAe,aAAa;EAC1B,IAAI;GACF,QAAQ;GACR,OAAO,CAAC,WAAW,QAAQ,CAAC;EAC9B,CAAC;CACH;CACA,eAAe,aAAa;EAC1B,KAAK,UAAU;GACb,MAAM,OAAO,WAAW,QAAQ;GAChC,IAAI,OAAO,SAAS,OAAO,QAAQ,KAAK,MAAM,MAAM,UAAU,OAAO,UACnE,OAAO;IACL,QAAQ;IACR,OAAO,CAAC,GAAG,MAAM,MAAM,MAAM,GAAG,EAAE,GAAG,IAAI;GAC3C;GAEF,OAAO;IACL,QAAQ;IACR,OAAO,CAAC,GAAG,MAAM,OAAO,IAAI;GAC9B;EACF,CAAC;CACH;CACA,kBAAkB,aAAa;EAC7B,KAAK,UAAU;GACb,MAAM,OAAO,WAAW,QAAQ;GAChC,IAAI,MAAM,MAAM,WAAW,GACzB,OAAO;IAAE,QAAQ;IAAM,OAAO,CAAC,IAAI;GAAE;GAEvC,OAAO;IACL,QAAQ;IACR,OAAO,CAAC,GAAG,MAAM,MAAM,MAAM,GAAG,EAAE,GAAG,IAAI;GAC3C;EACF,CAAC;CACH;AACF;AAEA,MAAM,kBAEF,cACA,KACA,SACA,aAED,OAAgB,QAAkB,OAAiB,WAAqB;CACvE,MAAM,WAAW,QAAQ,OAAO,QAAQ,OAAO,MAAM;CACrD,MAAM,EAAE,UAAU,IAAI;CACtB,MAAM,MAAM,MAAM,GAAG,EAAE;CACvB,IAAI,MAAM,WAAW,GAAG;EACtB,QAAQ,aAAa,QAAQ;EAC7B;CACF;CACA,IAAI,aAAa,KAAK,SAAS,SAAS;CACxC,IAAI,CAAC,cAAc,YAAY,KAAK,GAElC,aADqB,aAAa,IAAI,KAAK,QAAQ,EAC3B,MAAM;CAEhC,IAAI,YAAY;EACd,QAAQ,gBAAgB,QAAQ;EAChC;CACF;CACA,QAAQ,aAAa,QAAQ;AAC/B;AAEF,MAAM,aAEF,KACA,wBAEI;CACJ,KAAK,UAAU;EACb,IAAI,MAAM,MAAM,UAAU,GAAG;GAC3B,cAAc,CAAC,CAAC;GAChB,OAAO;IAAE,QAAQ;IAAO,OAAO,CAAC;GAAE;EACpC;EACA,MAAM,OAAO,MAAM,MAAM,MAAM,GAAG,EAAE;EACpC,cAAc,IAAI;EAClB,OAAO;GAAE,QAAQ;GAAM,OAAO;EAAK;CACrC,CAAC;AACH;AAEF,MAAM,gBAEF,KACA,mBAED,OAAO;CACN,KAAK,UAAU;EACb,MAAM,OAAO,MAAM,MAAM,QAAQ,SAAS,KAAK,OAAO,EAAE;EACxD,IAAI,KAAK,WAAW,MAAM,MAAM,QAC9B,OAAO;EAET,cAAc,IAAI;EAClB,OAAO,KAAK,WAAW,IAAI;GAAE,QAAQ;GAAO,OAAO,CAAC;EAAE,IAAI,EAAE,OAAO,KAAK;CAC1E,CAAC;AACH;AAEF,MAAM,iBAEF,KACA,aAED,OAAgB,QAAkB,UAAoB;CACrD,MAAM,EAAE,IAAI,SAAS,QAAQ,OAAO,QAAQ,KAAK;CACjD,KAAK,UAAU;EACb,MAAM,QAAQ,MAAM,MAAM,WAAW,SAAS,KAAK,OAAO,EAAE;EAC5D,MAAM,WAAW,MAAM,MAAM;EAC7B,IAAI,aAAa,KAAA,GACf,OAAO;EAET,MAAM,UAAU,CAAC,GAAG,MAAM,KAAK;EAC/B,QAAQ,SAAS;GAAE,GAAG;GAAU;EAAK;EACrC,OAAO,EAAE,OAAO,QAAQ;CAC1B,CAAC;AACH;AAEF,MAAM,cAEF,KACA,eAKD,OAAgB,QAAkB,UAAoB;CACrD,MAAM,OAAO,YAAY,KAAK,IAC1B,kBACE,OACA,UAAU,mBACV,UAAU,cACV,UAAU,YACV,UAAU,WACZ,IACA,aAAa,OAAO,YAAY;CACpC,MAAM,OAAO,SAAS,MAAM;CAC5B,MAAM,YAAY,2BAA2B,KAAK,GAAG;CACrD,KAAK,UAAU;EACb,MAAM,MAAM,MAAM,MAAM,GAAG,EAAE;EAC7B,IAAI,QAAQ,KAAA,GACV,OAAO;EAET,MAAM,WAAW,CAAC,GAAG,MAAM,KAAK;EAChC,SAAS,SAAS,SAAS,KAAK;GAC9B,WAAW,aAAa,IAAI;GAC5B;GACA,IAAI,IAAI;GACR;EACF;EACA,OAAO,EAAE,OAAO,SAAS;CAC3B,CAAC;AACH;AAEF,MAAM,oBACkB,EACpB,cACA,mBACA,QACA,YACA,eACA,SACA,mBAED,KAAK,QAAQ;CACZ,MAAM,UAAU,sBAAsB,KAAK,MAAM;CAEjD,OAAO;EACL,aAAa;GACX,cAAc,CAAC,CAAC;GAChB,IAAI;IAAE,QAAQ;IAAO,OAAO,CAAC;GAAE,CAAC;EAClC;EACA,QAAQ;EACR,UAAU,eAAe,cAAc,KAAK,SAAS,OAAO;EAC5D,OAAO,OAAgB,QAAkB,OAAiB,WAAqB;GAC7E,QAAQ,aAAa,QAAQ,OAAO,QAAQ,OAAO,MAAM,CAAC;EAC5D;EACA,KAAK,UAAU,KAAK,aAAa;EACjC,OAAO,OAAgB,QAAkB,OAAiB,WAAqB;GAC7E,QAAQ,aAAa,QAAQ,OAAO,QAAQ,OAAO,MAAM,CAAC;EAC5D;EACA,QAAQ,aAAa,KAAK,aAAa;EACvC,UAAU,OAAgB,QAAkB,OAAiB,WAAqB;GAChF,QAAQ,gBAAgB,QAAQ,OAAO,QAAQ,OAAO,MAAM,CAAC;EAC/D;EACA,SAAS,cAAc,KAAK,OAAO;EACnC,OAAO,CAAC;EACR,MAAM,WAAW,KAAK;GAAE;GAAc;GAAmB;GAAY;EAAY,CAAC;CACpF;AACF;;;;;;;;;;;;AAaF,MAAa,oBACX,WAC2B;CAC3B,MAAM,oCAAoB,IAAI,IAA0B;CACxD,MAAM,+BAAe,IAAI,IAA0B;CAEnD,IAAI,eAAe;CACnB,MAAM,mBAAmB;EACvB,MAAM,MAAM,WAAW;EACvB,gBAAgB;EAChB,OAAO;CACT;CAEA,MAAM,8BAAc,IAAI,IAAY;CACpC,MAAM,WAAW,OAAgB,QAAiB,OAAgB,WAChE,YACE,mBACA,cACA,YACA,aACA,OACA,QACA,OACA,MACF;;CAEF,MAAM,iBAAiB,mBAAyC;EAC9D,MAAM,YAAY,IAAI,IAAI,eAAe,KAAK,SAAS,KAAK,IAAI,CAAC;EACjE,KAAK,MAAM,CAAC,WAAW,YAAY,mBACjC,IAAI,CAAC,UAAU,IAAI,OAAO,GAAG;GAC3B,kBAAkB,OAAO,SAAS;GAClC,aAAa,OAAO,OAAO;EAC7B;CAEJ;CAYA,OAAO;EAAE;EAAc;EAAmB,OAX5B,YAA8B,EAC1C,iBAAuB;GACrB;GACA;GACA;GACA;GACA;GACA;GACA;EACF,CAAC,CAE2C;CAAE;AAClD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AChPA,MAAa,oBACX,WAC6B;CAC7B,MAAM,WAAW,cAAc,MAAM;CACrC,MAAM,EAAE,OAAO,iBAAiB,iBAAuB,QAAQ;CAE/D,MAAM,eAAe,cAGX,IAAI;CACd,MAAM,wBAAwB;EAC5B,MAAM,MAAM,IAAI,YAAY;EAC5B,IAAI,CAAC,KACH,MAAM,IAAI,MAAM,sEAAsE;EAExF,OAAO;CACT;CAEA,MAAM,gBAAgB;EAAE,QAAQ;EAAU;CAAM;CAChD,MAAM,sBAAsB,EAC1B,QACA,UACA,YACA,QACA,mBAEA,qBAAC,aAAa,UAAd;EAAuB,OAAO;YAA9B,CACG,UACD,oBAAC,aAAD,EAAA,UACE,oBAAC,eAAD;GACc;GACE;GACd,QAAQ;GACA;GACM;GACN;GACD;EACR,CAAA,EACU,CAAA,CACQ;;CAGzB,MAAM,iBAAqC;EACzC,MAAM,EAAE,OAAO,MAAM,gBAAgB;EAErC,MAAM,QAAQ,EAAE,SAAS;EACzB,OAAO;GACL,OAAO,MAAM;GACb,UAAU,MAAM;GAChB,MAAM,MAAM;GACZ,KAAK,MAAM;GACX,MAAM,MAAM;GACZ,QAAQ,MAAM;GACd,SAAS,MAAM;GACf,SAAS,MAAM;GACf,MAAM,MAAM;EACd;CACF;CACA,MAAM,2BAAqD;EACzD,MAAM,EAAE,OAAO,MAAM,gBAAgB;EACrC,OAAO,SACL,GACA,YAAY,WAAW;GACrB,QAAQ,MAAM;GACd,OAAO,MAAM;EACf,EAAE,CACJ;CACF;CACA,OAAO;EAAE;EAAoB;EAAO;EAAU;CAAmB;AACnE;;;;;;;;AC5GA,MAAa,oBAAoB,EAC/B,gBACA,OACA,aAKI,UAAU;CAAE;CAAgB;CAAO;AAAO,CAAC;;;ACXjD,MAAa,aAAa,EACxB,QACA,WACA,OACA,eACmC;CACnC,MAAM,EAAE,MAAM,aAAa,cAAc;CACzC,IAAI,CAAC,UACH,OAAO;CAKT,OACE,oBAAC,kBAAD;EACE,gBAAe;EACf,OAAO;GACL,cAAc,aAAa,KAAA,KAAa,aAAa,OAAO,SAAS,KAAA;GACrE,UAAU,YAAY,oBAAC,eAAD,CAAgB,CAAA;GACtC,WAAW,eATA,SACb,KAAA,IACA,kMAOsC,SAAS;GAC7C,SAAS;GACT;GACA,MAAM,SAAS,KAAA,IAAY;EAC7B;EACQ;CACT,CAAA;AAEL;;;ACxBA,MAAM,qBAAqB,EACzB,QACA,WACA,OACA,eAOA,UAAU;CACR,OAAO;EAEL;EACA,WAAW,eAAe,2BAA2B,SAAS;EAC9D,2BAA2B;EAC3B;CACF;CACA;AACF,CAAC;AAEH,MAAa,aAAa,EAAE,QAAQ,WAAW,OAAO,eAA+B;CACnF,IAAI,WAAW,KAAA,GACb,OACE,oBAAC,mBAAD;EAA8B;EAAmB;EAAe;EAC7D;CACgB,CAAA;CAGvB,OACE,qBAAC,WAAW,MAAZ;EACE,WAAW,eAAe,yDAAyD,SAAS;EAC5F,2BAAwB;EACjB;YAHT,CAKE,oBAAC,WAAW,UAAZ;GAAqB,WAAU;GAC5B;EACkB,CAAA,GACrB,oBAAC,WAAW,WAAZ;GACE,WAAU;GACV,aAAY;aAEZ,oBAAC,WAAW,OAAZ,EAAkB,WAAU,wCAAyC,CAAA;EACjD,CAAA,CACP;;AAErB;;;AClDA,MAAa,cAAc,EACzB,QACA,WACA,OACA,eACmC;CACnC,MAAM,EAAE,UAAU,cAAc;CAIhC,OACE,oBAAC,kBAAD;EACE,gBAAe;EACf,OAAO;GACL,cAAc,aAAa,KAAA,KAAa,aAAa,OAAO,UAAU,KAAA;GACtE,UAAU,YAAY,oBAAC,OAAD,CAAQ,CAAA;GAC9B,WAAW,eATA,SACb,KAAA,IACA,qNAOsC,SAAS;GAC7C,SAAS;GACT;GACA,MAAM,SAAS,KAAA,IAAY;EAC7B;EACQ;CACT,CAAA;AAEL;;;ACzBA,MAAa,oBAAoB,EAAE,QAAQ,WAAW,OAAO,eAA+B;CAC1F,MAAM,EAAE,SAAS,wBAAwB,cAAc;CACvD,gBAAgB,oBAAoB,GAAG,CAAC,mBAAmB,CAAC;CAC5D,OACE,oBAAC,kBAAD;EACE,gBAAe;EACf,OAAO;GAAE;GAAU;GAAW,IAAI,GAAG,QAAQ;GAAQ;EAAM;EACnD;CACT,CAAA;AAEL;;;ACXA,MAAa,eAAe,EAAE,QAAQ,WAAW,OAAO,eAA+B;CAErF,OACE,oBAAC,kBAAD;EACE,gBAAe;EACf,OAAO;GAAE;GAAU,WAAW,eAJjB,SAAS,aAAa,uDAIoB,SAAS;GAAG;EAAM;EACjE;CACT,CAAA;AAEL;;;ACRA,MAAa,eAAe,EAC1B,QACA,WACA,OACA,eACmC;CACnC,MAAM,EAAE,OAAO,MAAM,UAAU,SAAS,cAAc;CAItD,IAAI,SAAS,UACX,OAAO;CAET,MAAM,UAAU,WAAW,OAAO;CAIlC,OACE,oBAAC,kBAAD;EACE,gBAAe;EACf,OAAO;GACL,cAAc;GACd,UAAU,YACR,oBAAC,OAAD;IAAK,eAAY;IAAO,WAAU;GAAoC,CAAA;GAExE,WAAW,eAXA,SACb,KAAA,IACA,sHASsC,SAAS;GAC7C,0BAA0B;GAC1B,SAAS;GACT;GACA,MAAM,SAAS,KAAA,IAAY;EAC7B;EACQ;CACT,CAAA;AAEL;;;ACnCA,MAAa,eAAe,EAAE,QAAQ,WAAW,OAAO,eAA+B;CAIrF,OACE,oBAAC,kBAAD;EACE,gBAAe;EACf,OAAO;GAAE;GAAU,WAAW,eAJjB,SAAS,aAAa,oDAIoB,SAAS;GAAG;EAAM;EACjE;CACT,CAAA;AAEL;;;ACTA,MAAa,cAAc,EAAE,QAAQ,WAAW,OAAO,eAA+B;CACpF,MAAM,EAAE,SAAS,kBAAkB,cAAc;CACjD,gBAAgB,cAAc,GAAG,CAAC,aAAa,CAAC;CAEhD,OACE,oBAAC,kBAAD;EACE,gBAAe;EACf,OAAO;GACL;GACA,WAAW,eANA,SAAS,KAAA,IAAY,yBAMI,SAAS;GAC7C,IAAI,GAAG,QAAQ;GACf;EACF;EACQ;CACT,CAAA;AAEL;;;;;;;;;;;;ACJA,MAAa,QAAQ;CACnB,MAAM;CACN,MAAM;CACN,OAAO;CACP,aAAa;CACb,QAAQ;CACR,QAAQ;CACR,QAAQ;CACR,OAAO;AACT"}