Sign In

scrollsheet

Package Overview
Dependencies
Maintainers
1
Versions
7
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

scrollsheet - npm Package Compare versions

Comparing version
1.0.0-beta.5
to
1.0.0
+230
dist/auto/drawer-D2Y44hut.mjs
"use client";
import { c as Slot, d as useSheetContext, i as Content$1, n as Description, r as Title, s as Trigger, t as Close, u as Root$1 } from "./misc-B6wh-cJ4.mjs";
import { t as cn } from "./cn-DgpbGWy-.mjs";
import * as React from "react";
import { Fragment, jsx } from "react/jsx-runtime";
import { createPortal } from "react-dom";
//#region packages/scrollsheet/src/handle.tsx
function detentLabel(spec) {
if (spec === "full") return "Full";
if (spec === "medium") return "Half";
if (spec === "content") return "Fit content";
if (typeof spec === "number") return `${Math.round(spec * 100)}%`;
return spec ?? "";
}
const Handle$1 = React.forwardRef(function Handle({ asChild, onClick, onKeyDown, className, variant = "inside", ...props }, ref) {
const ctx = useSheetContext("Handle");
const [mounted, setMounted] = React.useState(false);
React.useEffect(() => setMounted(true), []);
const outside = variant === "outside" && ctx.side === "bottom" && !(mounted && !ctx.canvasEl);
const variantAttr = outside ? "outside" : variant === "floating" ? "floating" : void 0;
const specs = ctx.detents;
const horizontal = ctx.side === "left" || ctx.side === "right";
const multi = specs.length >= 2;
const activeIndex = specs.findIndex((s) => Object.is(s, ctx.activeDetent));
const move = (delta) => {
if (!multi) return false;
const index = specs.findIndex((s) => Object.is(s, ctx.activeDetent));
const next = specs[index + delta];
if (next === void 0) return false;
ctx.setActiveDetent(next);
return true;
};
const sliderAria = multi ? {
role: "slider",
"aria-orientation": horizontal ? "horizontal" : "vertical",
"aria-valuemin": 0,
"aria-valuemax": specs.length - 1,
...activeIndex >= 0 ? {
"aria-valuenow": activeIndex,
"aria-valuetext": detentLabel(specs[activeIndex])
} : {}
} : {};
const button = jsx(asChild ? Slot : "button", {
...asChild ? {} : { type: "button" },
"aria-label": horizontal ? "Adjust sheet width" : "Adjust sheet height",
...sliderAria,
...props,
ref,
className: cn("scrollsheet-handle", className),
"data-scrollsheet-handle": true,
"data-scrollsheet-handle-variant": variantAttr,
onClick: (event) => {
onClick?.(event);
if (event.defaultPrevented) return;
if (!multi) return;
const index = specs.findIndex((s) => Object.is(s, ctx.activeDetent));
const next = specs[(index + 1) % specs.length];
if (next !== void 0) ctx.setActiveDetent(next);
},
onKeyDown: (event) => {
onKeyDown?.(event);
if (event.defaultPrevented) return;
const expandKey = horizontal ? "ArrowRight" : "ArrowUp";
const collapseKey = horizontal ? "ArrowLeft" : "ArrowDown";
if (event.key === expandKey) {
event.preventDefault();
move(1);
} else if (event.key === collapseKey) {
event.preventDefault();
if (!move(-1) && ctx.dismissible) ctx.setOpen(false);
} else if (multi && event.key === "Home") {
event.preventDefault();
const first = specs[0];
if (first !== void 0) ctx.setActiveDetent(first);
} else if (multi && event.key === "End") {
event.preventDefault();
const last = specs[specs.length - 1];
if (last !== void 0) ctx.setActiveDetent(last);
}
}
});
if (outside) return ctx.canvasEl ? createPortal(button, ctx.canvasEl) : null;
return button;
});
//#endregion
//#region packages/scrollsheet/src/drawer/index.tsx
const wrapperClaims = new Map();
const VAUL_CLOSE_THRESHOLD = .25;
function toDetentSpec(point) {
if (typeof point === "number") return point;
if (point === "fit-content" || point === "content") return "content";
if (/^\d+(\.\d+)?px$/.test(point)) return `${Number.parseFloat(point)}px`;
const parsed = Number.parseFloat(point);
return Number.isFinite(parsed) ? parsed : "content";
}
function resolveFadeFromIndex(snapPoints, fadeFromIndex) {
if (!snapPoints || snapPoints.length === 0) return void 0;
const point = snapPoints[fadeFromIndex ?? snapPoints.length - 1];
return point !== void 0 ? toDetentSpec(point) : void 0;
}
function resolveCloseThreshold(snapPoints, closeThreshold) {
if (snapPoints !== void 0 && snapPoints.length > 0) return void 0;
return Math.min(1, Math.max(0, 1 - (closeThreshold ?? VAUL_CLOSE_THRESHOLD)));
}
function composeOpenChange(onOpenChange, onClose) {
if (!onOpenChange && !onClose) return void 0;
return (next) => {
if (!next) onClose?.();
onOpenChange?.(next);
};
}
function Root(props) {
const { children, open, defaultOpen, onOpenChange, onClose, dismissible, snapPoints, activeSnapPoint, setActiveSnapPoint, onAnimationEnd, autoFocus, nested, direction, modal, shouldScaleBackground, setBackgroundColorOnScale, noBodyStyles, disablePreventScroll, preventScrollRestoration, repositionInputs, scrollLockTimeout, closeThreshold, fadeFromIndex, snapToSequentialPoint, handleOnly, onDrag, onRelease, container, fixed, actionsRef, backdropDismissible, escapeDismissible, keyboardExpands, onTravel, scrollbar } = props;
const detents = snapPoints && snapPoints.length > 0 ? snapPoints.map(toDetentSpec) : void 0;
const activeDetent = activeSnapPoint != null ? toDetentSpec(activeSnapPoint) : void 0;
const largestUndimmedDetent = resolveFadeFromIndex(snapPoints, fadeFromIndex);
const resolvedCloseThreshold = resolveCloseThreshold(snapPoints, closeThreshold);
const handleRelease = onRelease ? (event, willRemainOpen) => onRelease(event, willRemainOpen) : void 0;
const handleOpenChange = composeOpenChange(onOpenChange, onClose);
const handleActiveDetentChange = (detent) => {
if (!setActiveSnapPoint) return;
const match = snapPoints?.find((point) => Object.is(toDetentSpec(point), detent));
setActiveSnapPoint(match ?? detent);
};
React.useEffect(() => {
if (!shouldScaleBackground) return;
const existing = document.querySelector("[data-scrollsheet-background]");
if (existing && !wrapperClaims.has(existing)) return;
const wrapper = existing ?? document.querySelector("[data-vaul-drawer-wrapper]");
if (!wrapper) return;
const count = wrapperClaims.get(wrapper) ?? 0;
wrapperClaims.set(wrapper, count + 1);
if (count === 0) wrapper.setAttribute("data-scrollsheet-background", "");
return () => {
const remaining = (wrapperClaims.get(wrapper) ?? 1) - 1;
if (remaining <= 0) {
wrapperClaims.delete(wrapper);
wrapper.removeAttribute("data-scrollsheet-background");
} else wrapperClaims.set(wrapper, remaining);
};
}, [shouldScaleBackground]);
return jsx(DirectionContext.Provider, {
value: direction ?? "bottom",
children: jsx(Root$1, {
open,
defaultOpen,
onOpenChange: handleOpenChange,
onOpenChangeComplete: onAnimationEnd,
dismissible,
detents,
activeDetent,
onActiveDetentChange: setActiveSnapPoint ? handleActiveDetentChange : void 0,
side: direction,
modal,
backgroundEffect: shouldScaleBackground ? "scale" : "none",
largestUndimmedDetent,
handleOnly,
sequentialDetents: snapToSequentialPoint,
closeThreshold: resolvedCloseThreshold,
onRelease: handleRelease,
actionsRef,
backdropDismissible,
escapeDismissible,
keyboardExpands,
onTravel,
scrollbar,
children
})
});
}
const DirectionContext = React.createContext("bottom");
const NestedRoot = Root;
function Portal({ children, container }) {
return jsx(Fragment, { children });
}
function Overlay(_props) {
return null;
}
function hasMultipleSnapPoints(detents) {
return detents.length > 1;
}
const Content = React.forwardRef(function Content({ onPointerDownOutside, onOpenAutoFocus, onEscapeKeyDown, onCloseAutoFocus, onInteractOutside, onFocusOutside, forceMount, ...props }, ref) {
const ctx = useSheetContext("Content");
const direction = React.useContext(DirectionContext);
const snapPointsActive = hasMultipleSnapPoints(ctx.detents);
return jsx(Content$1, {
...props,
ref,
"data-vaul-drawer": "",
"data-vaul-drawer-direction": direction,
"data-vaul-snap-points": snapPointsActive ? "true" : "false"
});
});
function composeHandleClick(preventCycle, onClick) {
return (event) => {
onClick?.(event);
if (preventCycle) event.preventDefault();
};
}
const Handle = React.forwardRef(function Handle({ preventCycle, onClick, ...props }, ref) {
const ctx = useSheetContext("Handle");
return jsx(Handle$1, {
...props,
ref,
"data-vaul-handle": "",
"data-vaul-drawer-visible": ctx.open ? "true" : "false",
onClick: composeHandleClick(preventCycle, onClick)
});
});
const DrawerClose = React.forwardRef(function DrawerClose({ children, ...props }, ref) {
return jsx(Close, {
...props,
ref,
children: children ?? null
});
});
const Drawer = {
Root,
NestedRoot,
Trigger,
Portal,
Overlay,
Content,
Close: DrawerClose,
Title,
Description,
Handle
};
//#endregion
export { NestedRoot as a, Root as c, hasMultipleSnapPoints as d, resolveCloseThreshold as f, Handle as i, composeHandleClick as l, Handle$1 as m, Drawer as n, Overlay as o, resolveFadeFromIndex as p, DrawerClose as r, Portal as s, Content as t, composeOpenChange as u };

Sorry, the diff of this file is too big to display

"use client";
import { c as Slot, d as useSheetContext, i as Content$1, n as Description, r as Title, s as Trigger, t as Close, u as Root$1 } from "./misc-DiVXSPuI.mjs";
import { h as warnOnce, t as cn } from "./cn-Cs7ZylHz.mjs";
import * as React from "react";
import { Fragment, jsx } from "react/jsx-runtime";
import { createPortal } from "react-dom";
//#region packages/scrollsheet/src/handle.tsx
function detentLabel(spec) {
if (spec === "full") return "Full";
if (spec === "medium") return "Half";
if (spec === "content") return "Fit content";
if (typeof spec === "number") return `${Math.round(spec * 100)}%`;
return spec ?? "";
}
const Handle$1 = React.forwardRef(function Handle({ asChild, onClick, onKeyDown, className, variant = "inside", ...props }, ref) {
const ctx = useSheetContext("Handle");
const [mounted, setMounted] = React.useState(false);
React.useEffect(() => setMounted(true), []);
const outside = variant === "outside" && ctx.side === "bottom" && !(mounted && !ctx.canvasEl);
const variantAttr = outside ? "outside" : variant === "floating" ? "floating" : void 0;
const specs = ctx.detents;
const horizontal = ctx.side === "left" || ctx.side === "right";
const multi = specs.length >= 2;
const activeIndex = specs.findIndex((s) => Object.is(s, ctx.activeDetent));
const move = (delta) => {
if (!multi) return false;
const index = specs.findIndex((s) => Object.is(s, ctx.activeDetent));
const next = specs[index + delta];
if (next === void 0) return false;
ctx.setActiveDetent(next);
return true;
};
const sliderAria = multi ? {
role: "slider",
"aria-orientation": horizontal ? "horizontal" : "vertical",
"aria-valuemin": 0,
"aria-valuemax": specs.length - 1,
...activeIndex >= 0 ? {
"aria-valuenow": activeIndex,
"aria-valuetext": detentLabel(specs[activeIndex])
} : {}
} : {};
const button = jsx(asChild ? Slot : "button", {
...asChild ? {} : { type: "button" },
"aria-label": horizontal ? "Adjust sheet width" : "Adjust sheet height",
...sliderAria,
...props,
ref,
className: cn("scrollsheet-handle", className),
"data-scrollsheet-handle": true,
"data-scrollsheet-handle-variant": variantAttr,
onClick: (event) => {
onClick?.(event);
if (event.defaultPrevented) return;
if (!multi) return;
const index = specs.findIndex((s) => Object.is(s, ctx.activeDetent));
const next = specs[(index + 1) % specs.length];
if (next !== void 0) ctx.setActiveDetent(next);
},
onKeyDown: (event) => {
onKeyDown?.(event);
if (event.defaultPrevented) return;
const expandKey = horizontal ? "ArrowRight" : "ArrowUp";
const collapseKey = horizontal ? "ArrowLeft" : "ArrowDown";
if (event.key === expandKey) {
event.preventDefault();
move(1);
} else if (event.key === collapseKey) {
event.preventDefault();
if (!move(-1) && ctx.dismissible) ctx.setOpen(false);
} else if (multi && event.key === "Home") {
event.preventDefault();
const first = specs[0];
if (first !== void 0) ctx.setActiveDetent(first);
} else if (multi && event.key === "End") {
event.preventDefault();
const last = specs[specs.length - 1];
if (last !== void 0) ctx.setActiveDetent(last);
}
}
});
if (outside) return ctx.canvasEl ? createPortal(button, ctx.canvasEl) : null;
return button;
});
//#endregion
//#region packages/scrollsheet/src/drawer/index.tsx
const wrapperClaims = new Map();
const VAUL_CLOSE_THRESHOLD = .25;
const collectIgnored = (entries) => entries.filter(([, v]) => v !== void 0).map(([k]) => k);
function toDetentSpec(point) {
if (typeof point === "number") return point;
if (point === "fit-content" || point === "content") return "content";
if (/^\d+(\.\d+)?px$/.test(point)) return `${Number.parseFloat(point)}px`;
const parsed = Number.parseFloat(point);
return Number.isFinite(parsed) ? parsed : "content";
}
function resolveFadeFromIndex(snapPoints, fadeFromIndex) {
if (!snapPoints || snapPoints.length === 0) return void 0;
const point = snapPoints[fadeFromIndex ?? snapPoints.length - 1];
return point !== void 0 ? toDetentSpec(point) : void 0;
}
function resolveCloseThreshold(snapPoints, closeThreshold) {
if (snapPoints !== void 0 && snapPoints.length > 0) return void 0;
return Math.min(1, Math.max(0, 1 - (closeThreshold ?? VAUL_CLOSE_THRESHOLD)));
}
function composeOpenChange(onOpenChange, onClose) {
if (!onOpenChange && !onClose) return void 0;
return (next) => {
if (!next) onClose?.();
onOpenChange?.(next);
};
}
function Root(props) {
const { children, open, defaultOpen, onOpenChange, onClose, dismissible, snapPoints, activeSnapPoint, setActiveSnapPoint, onAnimationEnd, autoFocus, nested, direction, modal, shouldScaleBackground, setBackgroundColorOnScale, noBodyStyles, disablePreventScroll, preventScrollRestoration, repositionInputs, scrollLockTimeout, closeThreshold, fadeFromIndex, snapToSequentialPoint, handleOnly, onDrag, onRelease, container, fixed, actionsRef, backdropDismissible, escapeDismissible, keyboardExpands, onTravel, scrollbar } = props;
{
const ignored = collectIgnored([
["setBackgroundColorOnScale", setBackgroundColorOnScale],
["noBodyStyles", noBodyStyles],
["disablePreventScroll", disablePreventScroll],
["preventScrollRestoration", preventScrollRestoration],
["repositionInputs", repositionInputs],
["scrollLockTimeout", scrollLockTimeout],
["onDrag", onDrag],
["container", container],
["fixed", fixed],
["autoFocus", autoFocus],
["nested", nested]
]);
if (ignored.length > 0) warnOnce("root-ignored-props", `[scrollsheet Drawer] These <Drawer.Root> props from vaul have no effect in this compat layer and are ignored: ${ignored.join(", ")}. See the vaul migration notes in the README.${onDrag !== void 0 ? " onDrag: the native onTravel prop works on this same <Drawer.Root>." : ""}`);
}
const detents = snapPoints && snapPoints.length > 0 ? snapPoints.map(toDetentSpec) : void 0;
const activeDetent = activeSnapPoint != null ? toDetentSpec(activeSnapPoint) : void 0;
const largestUndimmedDetent = resolveFadeFromIndex(snapPoints, fadeFromIndex);
const resolvedCloseThreshold = resolveCloseThreshold(snapPoints, closeThreshold);
if (snapPoints !== void 0 && snapPoints.length > 0 && closeThreshold !== void 0) warnOnce("close-threshold-with-snap-points", "[scrollsheet Drawer] <Drawer.Root closeThreshold> has no effect when snapPoints is set — this matches real vaul, where closeThreshold is dead code once snapPoints exist (its onRelease returns through the snap-points branch before ever reading it). Use the native Sheet.Root `closeThreshold` (a live 0-1 fraction of the first detent, works alongside detents) if you want the upgrade.");
const handleRelease = onRelease ? (event, willRemainOpen) => onRelease(event, willRemainOpen) : void 0;
const handleOpenChange = composeOpenChange(onOpenChange, onClose);
const handleActiveDetentChange = (detent) => {
if (!setActiveSnapPoint) return;
const match = snapPoints?.find((point) => Object.is(toDetentSpec(point), detent));
setActiveSnapPoint(match ?? detent);
};
React.useEffect(() => {
if (!shouldScaleBackground) return;
const existing = document.querySelector("[data-scrollsheet-background]");
if (existing && !wrapperClaims.has(existing)) return;
const wrapper = existing ?? document.querySelector("[data-vaul-drawer-wrapper]");
if (!wrapper) return;
const count = wrapperClaims.get(wrapper) ?? 0;
wrapperClaims.set(wrapper, count + 1);
if (count === 0) wrapper.setAttribute("data-scrollsheet-background", "");
return () => {
const remaining = (wrapperClaims.get(wrapper) ?? 1) - 1;
if (remaining <= 0) {
wrapperClaims.delete(wrapper);
wrapper.removeAttribute("data-scrollsheet-background");
} else wrapperClaims.set(wrapper, remaining);
};
}, [shouldScaleBackground]);
return jsx(DirectionContext.Provider, {
value: direction ?? "bottom",
children: jsx(Root$1, {
open,
defaultOpen,
onOpenChange: handleOpenChange,
onOpenChangeComplete: onAnimationEnd,
dismissible,
detents,
activeDetent,
onActiveDetentChange: setActiveSnapPoint ? handleActiveDetentChange : void 0,
side: direction,
modal,
backgroundEffect: shouldScaleBackground ? "scale" : "none",
largestUndimmedDetent,
handleOnly,
sequentialDetents: snapToSequentialPoint,
closeThreshold: resolvedCloseThreshold,
onRelease: handleRelease,
actionsRef,
backdropDismissible,
escapeDismissible,
keyboardExpands,
onTravel,
scrollbar,
children
})
});
}
const DirectionContext = React.createContext("bottom");
const NestedRoot = Root;
function Portal({ children, container }) {
if (container !== void 0) warnOnce("portal-container", "[scrollsheet Drawer] <Drawer.Portal container> has no effect — scrollsheet's <dialog> always renders into the browser's top layer (effectively document.body), so there's no separate container to portal into.");
return jsx(Fragment, { children });
}
function Overlay(_props) {
return null;
}
function hasMultipleSnapPoints(detents) {
return detents.length > 1;
}
const Content = React.forwardRef(function Content({ onPointerDownOutside, onOpenAutoFocus, onEscapeKeyDown, onCloseAutoFocus, onInteractOutside, onFocusOutside, forceMount, ...props }, ref) {
const ctx = useSheetContext("Content");
const direction = React.useContext(DirectionContext);
const snapPointsActive = hasMultipleSnapPoints(ctx.detents);
{
const ignored = collectIgnored([
["onPointerDownOutside", onPointerDownOutside],
["onOpenAutoFocus", onOpenAutoFocus],
["onEscapeKeyDown", onEscapeKeyDown],
["onCloseAutoFocus", onCloseAutoFocus],
["onInteractOutside", onInteractOutside],
["onFocusOutside", onFocusOutside],
["forceMount", forceMount]
]);
if (ignored.length > 0) warnOnce("content-ignored-props", `[scrollsheet Drawer] These <Drawer.Content> props from vaul have no effect in this compat layer and are stripped before reaching the DOM: ${ignored.join(", ")}. See the vaul migration notes in the README.${onPointerDownOutside !== void 0 || onInteractOutside !== void 0 || onEscapeKeyDown !== void 0 ? " To block backdrop-tap dismissal, set backdropDismissible={false} on <Drawer.Root>; to block Esc, escapeDismissible={false}." : ""}`);
}
return jsx(Content$1, {
...props,
ref,
"data-vaul-drawer": "",
"data-vaul-drawer-direction": direction,
"data-vaul-snap-points": snapPointsActive ? "true" : "false"
});
});
function composeHandleClick(preventCycle, onClick) {
return (event) => {
onClick?.(event);
if (preventCycle) event.preventDefault();
};
}
const Handle = React.forwardRef(function Handle({ preventCycle, onClick, ...props }, ref) {
const ctx = useSheetContext("Handle");
return jsx(Handle$1, {
...props,
ref,
"data-vaul-handle": "",
"data-vaul-drawer-visible": ctx.open ? "true" : "false",
onClick: composeHandleClick(preventCycle, onClick)
});
});
const DrawerClose = React.forwardRef(function DrawerClose({ children, ...props }, ref) {
return jsx(Close, {
...props,
ref,
children: children ?? null
});
});
const Drawer = {
Root,
NestedRoot,
Trigger,
Portal,
Overlay,
Content,
Close: DrawerClose,
Title,
Description,
Handle
};
//#endregion
export { NestedRoot as a, Root as c, hasMultipleSnapPoints as d, resolveCloseThreshold as f, Handle as i, composeHandleClick as l, Handle$1 as m, Drawer as n, Overlay as o, resolveFadeFromIndex as p, DrawerClose as r, Portal as s, Content as t, composeOpenChange as u };

Sorry, the diff of this file is too big to display

+1
-1
"use client";
"use client";
import { d as useSheetContext, i as Content$1, l as composeRefs, n as Description, r as Title, s as Trigger, t as Close, u as Root$1 } from "./misc-Bf6n3Ykh.mjs";
import { d as useSheetContext, i as Content$1, l as composeRefs, n as Description, r as Title, s as Trigger, t as Close, u as Root$1 } from "./misc-B6wh-cJ4.mjs";
import * as React from "react";

@@ -5,0 +5,0 @@ import { Fragment, jsx } from "react/jsx-runtime";

"use client";
"use client";
import { n as Description, r as Title, s as Trigger } from "./misc-Bf6n3Ykh.mjs";
import { a as NestedRoot, c as Root, d as hasMultipleSnapPoints, f as resolveCloseThreshold, i as Handle, l as composeHandleClick, n as Drawer, o as Overlay, p as resolveFadeFromIndex, r as DrawerClose, s as Portal, t as Content, u as composeOpenChange } from "./drawer-Daga_OBC.mjs";
import { n as Description, r as Title, s as Trigger } from "./misc-B6wh-cJ4.mjs";
import { a as NestedRoot, c as Root, d as hasMultipleSnapPoints, f as resolveCloseThreshold, i as Handle, l as composeHandleClick, n as Drawer, o as Overlay, p as resolveFadeFromIndex, r as DrawerClose, s as Portal, t as Content, u as composeOpenChange } from "./drawer-D2Y44hut.mjs";
export { DrawerClose as Close, Content, Description, Drawer, Handle, NestedRoot, Overlay, Portal, Root, Title, Trigger, composeHandleClick, composeOpenChange, hasMultipleSnapPoints, resolveCloseThreshold, resolveFadeFromIndex };
"use client";
import { a as injectStylesInto, i as Content, n as Description, o as spring, r as Title, s as Trigger, t as Close, u as Root } from "./misc-Bf6n3Ykh.mjs";
import { a as injectStylesInto, i as Content, n as Description, o as spring, r as Title, s as Trigger, t as Close, u as Root } from "./misc-B6wh-cJ4.mjs";
import { o as hasDialogSupport } from "./cn-DgpbGWy-.mjs";
import { m as Handle, n as Drawer } from "./drawer-Daga_OBC.mjs";
import { m as Handle, n as Drawer } from "./drawer-D2Y44hut.mjs";
import { Dialog } from "./dialog.mjs";

@@ -6,0 +6,0 @@ import { a as useSonner, i as toast, o as useToasts, r as injectToastStylesInto, t as ToasterShell } from "./toast-BEuD1_sZ.mjs";

"use client";
"use client";
import { d as useSheetContext, i as Content$1, l as composeRefs, n as Description, r as Title, s as Trigger, t as Close, u as Root$1 } from "./misc-VkdphfSa.mjs";
import { d as useSheetContext, i as Content$1, l as composeRefs, n as Description, r as Title, s as Trigger, t as Close, u as Root$1 } from "./misc-DiVXSPuI.mjs";
import { h as warnOnce } from "./cn-Cs7ZylHz.mjs";

@@ -5,0 +5,0 @@ import * as React from "react";

"use client";
"use client";
import { n as Description, r as Title, s as Trigger } from "./misc-VkdphfSa.mjs";
import { a as NestedRoot, c as Root, d as hasMultipleSnapPoints, f as resolveCloseThreshold, i as Handle, l as composeHandleClick, n as Drawer, o as Overlay, p as resolveFadeFromIndex, r as DrawerClose, s as Portal, t as Content, u as composeOpenChange } from "./drawer-DqGJtMsN.mjs";
import { n as Description, r as Title, s as Trigger } from "./misc-DiVXSPuI.mjs";
import { a as NestedRoot, c as Root, d as hasMultipleSnapPoints, f as resolveCloseThreshold, i as Handle, l as composeHandleClick, n as Drawer, o as Overlay, p as resolveFadeFromIndex, r as DrawerClose, s as Portal, t as Content, u as composeOpenChange } from "./drawer-V3SkmxkW.mjs";
export { DrawerClose as Close, Content, Description, Drawer, Handle, NestedRoot, Overlay, Portal, Root, Title, Trigger, composeHandleClick, composeOpenChange, hasMultipleSnapPoints, resolveCloseThreshold, resolveFadeFromIndex };
"use client";
import { a as injectStylesInto, i as Content, n as Description, o as spring, r as Title, s as Trigger, t as Close, u as Root } from "./misc-VkdphfSa.mjs";
import { a as injectStylesInto, i as Content, n as Description, o as spring, r as Title, s as Trigger, t as Close, u as Root } from "./misc-DiVXSPuI.mjs";
import { o as hasDialogSupport } from "./cn-Cs7ZylHz.mjs";
import { m as Handle, n as Drawer } from "./drawer-DqGJtMsN.mjs";
import { m as Handle, n as Drawer } from "./drawer-V3SkmxkW.mjs";
import { Dialog } from "./dialog.mjs";

@@ -6,0 +6,0 @@ import { a as useSonner, i as toast, o as useToasts, r as injectToastStylesInto, t as ToasterShell } from "./toast-o4mAr-oF.mjs";

@@ -1,1 +0,1 @@

.scrollsheet-dialog[data-scrollsheet-side=bottom]{--scrollsheet-keyboard-lift:var(--scrollsheet-keyboard,0px)}.scrollsheet-dialog{width:100%;height:calc(100% + var(--scrollsheet-keyboard-lift,0px));--scrollsheet-ease:linear(0, 0.042 3.4%, 0.136 6.9%, 0.37 13.8%, 0.481 17.2%, 0.58 20.7%, 0.664 24.1%, 0.735 27.6%, 0.793 31%, 0.839 34.5%, 0.876 37.9%, 0.906 41.4%, 0.928 44.8%, 0.946 48.3%, 0.96 51.7%, 0.978 58.6%, 0.988 65.5%, 0.994 72.4%, 0.998 82.8%, 1);--scrollsheet-dur:475ms;background:0 0;border:none;outline:none;max-width:none;max-height:none;margin:0;padding:0;position:fixed;inset:0;overflow:clip}.scrollsheet-dialog::backdrop{background:0 0}:where(.scrollsheet-backdrop){background:var(--scrollsheet-backdrop,#00000052);opacity:0;pointer-events:none;position:fixed;inset:0}.scrollsheet-dialog[data-scrollsheet-state=opening] .scrollsheet-backdrop{opacity:min(var(--scrollsheet-dim,0), 1);transition:opacity var(--scrollsheet-dur) var(--scrollsheet-ease)}.scrollsheet-dialog[data-scrollsheet-state=open] .scrollsheet-backdrop{opacity:min(var(--scrollsheet-dim,0), 1);transition:none}.scrollsheet-dialog[data-scrollsheet-state=closing] .scrollsheet-backdrop{opacity:0;transition:opacity var(--scrollsheet-dur) var(--scrollsheet-ease)}:where(.scrollsheet-top-chrome){height:calc(env(safe-area-inset-top,0px) + 8px);inset:0 0 auto}:where(.scrollsheet-bottom-chrome){height:calc(env(safe-area-inset-bottom,0px) + 32px);inset:auto 0 0}:where(.scrollsheet-top-chrome)~:where([data-scrollsheet-backdrop]){top:calc(env(safe-area-inset-top,0px) + 8px)}:where(.scrollsheet-bottom-chrome)~:where([data-scrollsheet-backdrop]){bottom:calc(env(safe-area-inset-bottom,0px) + 32px)}.scrollsheet-dialog:is([data-scrollsheet-state=pre],[data-scrollsheet-state=opening]) :is(.scrollsheet-top-chrome,.scrollsheet-bottom-chrome){opacity:min(var(--scrollsheet-dim,0), 1);transition:none}.scrollsheet-bottom-sentinel{height:min(calc(max(env(safe-area-inset-bottom,0px), 24px) + 45vh), var(--scrollsheet-reveal,24px));pointer-events:none;position:fixed;inset:auto 0 0}.scrollsheet-track{left:0;right:0;top:var(--scrollsheet-vv-top,0px);height:calc(var(--scrollsheet-vv-height,100%) + var(--scrollsheet-keyboard-lift,0px));overscroll-behavior:contain;scroll-snap-type:y mandatory;scrollbar-width:none;position:fixed;overflow-y:scroll}.scrollsheet-track::-webkit-scrollbar{display:none}.scrollsheet-dialog:is([data-scrollsheet-side=left],[data-scrollsheet-side=right]) .scrollsheet-track{scroll-snap-type:x mandatory;overscroll-behavior-x:none;overflow:scroll hidden}.scrollsheet-dialog[data-scrollsheet-modal=false]{pointer-events:none}.scrollsheet-dialog[data-scrollsheet-modal=false] .scrollsheet-panel{pointer-events:auto;touch-action:none}.scrollsheet-canvas{height:calc(100% + var(--scrollsheet-max-detent,0px));position:relative}.scrollsheet-dialog:is([data-scrollsheet-side=left],[data-scrollsheet-side=right]) .scrollsheet-canvas{width:calc(100% + var(--scrollsheet-max-detent,0px));height:100%}.scrollsheet-canvas:after{content:"";top:calc(100% - var(--scrollsheet-keyboard,0px));--scrollsheet-od:calc(120vh + var(--scrollsheet-keyboard,0px));height:0;box-shadow:0 calc(var(--scrollsheet-od) / 2) 0 calc(var(--scrollsheet-od) / 2) var(--scrollsheet-panel-bg,transparent);pointer-events:none;position:absolute;left:0;right:0}.scrollsheet-dialog[data-scrollsheet-side=top] .scrollsheet-canvas:after{box-shadow:0 -60vh 0 60vh var(--scrollsheet-panel-bg,transparent);top:auto;bottom:100%}.scrollsheet-dialog[data-scrollsheet-side=left] .scrollsheet-canvas:after{width:0;height:auto;box-shadow:-60vw 0 0 60vw var(--scrollsheet-panel-bg,transparent);inset:0 100% 0 auto}.scrollsheet-dialog[data-scrollsheet-side=right] .scrollsheet-canvas:after{width:0;height:auto;box-shadow:60vw 0 0 60vw var(--scrollsheet-panel-bg,transparent);inset:0 auto 0 100%}.scrollsheet-dialog[data-scrollsheet-detached] .scrollsheet-canvas:after{box-shadow:none}.scrollsheet-snap{pointer-events:none;scroll-snap-align:start;width:100%;height:1px;position:absolute;left:0}.scrollsheet-dialog:is([data-scrollsheet-side=left],[data-scrollsheet-side=right]) .scrollsheet-snap{width:1px;height:100%;top:0;left:auto}.scrollsheet-panel{--scrollsheet-eg:calc(var(--scrollsheet-inset-bottom,0px) + var(--scrollsheet-keyboard,0px));bottom:var(--scrollsheet-eg);left:var(--scrollsheet-inset-x,0px);right:var(--scrollsheet-inset-x,0px);height:var(--scrollsheet-max-detent,auto);max-height:var(--scrollsheet-vv-height,none);will-change:transform;padding-bottom:max(var(--scrollsheet-safe-area,env(safe-area-inset-bottom,0px)), 0px);position:absolute;overflow:hidden;transform:translateY(100%)}.scrollsheet-dialog[data-scrollsheet-side=top] .scrollsheet-panel{bottom:auto;top:var(--scrollsheet-inset-top,0px);left:var(--scrollsheet-inset-x,0px);right:var(--scrollsheet-inset-x,0px);height:var(--scrollsheet-max-detent,auto);padding-bottom:0;padding-top:max(var(--scrollsheet-safe-area-top,env(safe-area-inset-top,0px)), 0px);transform:translateY(-100%)}.scrollsheet-dialog:is([data-scrollsheet-side=left],[data-scrollsheet-side=right]) .scrollsheet-panel{top:var(--scrollsheet-inset-y,0px);bottom:var(--scrollsheet-inset-y,0px);width:var(--scrollsheet-max-detent,auto);height:auto;padding-top:max(var(--scrollsheet-safe-area-top,env(safe-area-inset-top,0px)), 0px)}.scrollsheet-dialog[data-scrollsheet-side=left] .scrollsheet-panel{right:auto;left:var(--scrollsheet-inset-left,0px);padding-left:max(var(--scrollsheet-safe-area-left,env(safe-area-inset-left,0px)), 0px);transform:translate(-100%)}.scrollsheet-dialog[data-scrollsheet-side=right] .scrollsheet-panel{left:auto;right:var(--scrollsheet-inset-right,0px);padding-right:max(var(--scrollsheet-safe-area-right,env(safe-area-inset-right,0px)), 0px);transform:translate(100%)}.scrollsheet-dialog:is([data-scrollsheet-side=top],[data-scrollsheet-side=left]) .scrollsheet-panel{justify-content:flex-end;display:flex}.scrollsheet-dialog[data-scrollsheet-side=top] .scrollsheet-panel{flex-direction:column}.scrollsheet-dialog[data-scrollsheet-side=left] .scrollsheet-panel{flex-direction:row}.scrollsheet-dialog[data-scrollsheet-side=left] .scrollsheet-panel>*{flex:0 0 100%;min-width:0}:where(.scrollsheet-panel){scrollbar-width:none}:where(.scrollsheet-panel)::-webkit-scrollbar{display:none}:where([data-scrollsheet-nested-scroll]){scrollbar-width:none}:where([data-scrollsheet-nested-scroll])::-webkit-scrollbar{display:none}:where(.scrollsheet-dialog[data-scrollsheet-scrollbar=overlay] [data-scrollsheet-nested-scroll]){position:relative}:where(.scrollsheet-panel){--scrollsheet-radius:20px;background:var(--scrollsheet-bg,#fff);color:var(--scrollsheet-fg,#1d1d1f);border-radius:var(--scrollsheet-radius) var(--scrollsheet-radius) 0 0;box-shadow:var(--scrollsheet-shadow,0 -8px 32px #00000029)}@media (prefers-color-scheme:dark){:where(.scrollsheet-panel){background:var(--scrollsheet-bg,#1c1c1e);color:var(--scrollsheet-fg,#f5f5f7)}}.scrollsheet-dialog[data-scrollsheet-side=top] :where(.scrollsheet-panel){border-radius:0 0 var(--scrollsheet-radius) var(--scrollsheet-radius);box-shadow:var(--scrollsheet-shadow,0 8px 32px #00000029)}.scrollsheet-dialog[data-scrollsheet-side=left] :where(.scrollsheet-panel){box-shadow:var(--scrollsheet-shadow,8px 0 32px #00000029);border-radius:0}.scrollsheet-dialog[data-scrollsheet-side=right] :where(.scrollsheet-panel){box-shadow:var(--scrollsheet-shadow,-8px 0 32px #00000029);border-radius:0}@media (min-width:768px){:where(.scrollsheet-dialog[data-scrollsheet-side=bottom]) :where(.scrollsheet-panel),:where(.scrollsheet-dialog[data-scrollsheet-side=bottom]) .scrollsheet-canvas:after{width:min(var(--scrollsheet-max-inline,640px), calc(100% - 2 * var(--scrollsheet-desktop-margin,24px)));margin-inline:auto var(--scrollsheet-desktop-margin,24px)}.scrollsheet-dialog[data-scrollsheet-side=bottom] .scrollsheet-panel{--scrollsheet-inset-bottom:var(--scrollsheet-desktop-margin,24px);--scrollsheet-dg:calc(var(--scrollsheet-desktop-margin,24px) + var(--scrollsheet-inset-x,0px) + 32px)}.scrollsheet-dialog[data-scrollsheet-side=bottom]:where([data-scrollsheet-detached]) .scrollsheet-panel,.scrollsheet-dialog[data-scrollsheet-side=bottom][data-scrollsheet-state=closing]:where([data-scrollsheet-detached]) .scrollsheet-panel{transform:translate3d(calc(100% + var(--scrollsheet-dg,32px)), 0, 0)}.scrollsheet-dialog[data-scrollsheet-side=bottom]:where([data-scrollsheet-detached][data-scrollsheet-rtl]) .scrollsheet-panel,.scrollsheet-dialog[data-scrollsheet-side=bottom][data-scrollsheet-state=closing]:where([data-scrollsheet-detached][data-scrollsheet-rtl]) .scrollsheet-panel{transform:translate3d(calc(-100% - var(--scrollsheet-dg,32px)), 0, 0)}.scrollsheet-dialog[data-scrollsheet-side=top] .scrollsheet-panel{top:var(--scrollsheet-desktop-margin,24px);border-radius:var(--scrollsheet-radius)}.scrollsheet-dialog[data-scrollsheet-side=bottom] :where(.scrollsheet-handle){opacity:0;pointer-events:none;width:5px;height:44px;margin:-22px 0 0;position:absolute;top:50%;left:10px}.scrollsheet-dialog[data-scrollsheet-side=bottom] :where(.scrollsheet-handle:focus-visible){opacity:1;pointer-events:auto}.scrollsheet-dialog[data-scrollsheet-side=bottom][data-scrollsheet-has-handle] :where(.scrollsheet-body){padding-top:18px}:where(.scrollsheet-dialog[data-scrollsheet-side=top]) :where(.scrollsheet-panel),:where(.scrollsheet-dialog[data-scrollsheet-side=top]) .scrollsheet-canvas:after{max-width:var(--scrollsheet-max-inline,640px);margin-inline:auto}}.scrollsheet-dialog[data-scrollsheet-detached] :where(.scrollsheet-panel){padding-bottom:max(var(--scrollsheet-safe-area,0px), 0px);border-radius:var(--scrollsheet-radius)}.scrollsheet-dialog[data-scrollsheet-detached][data-scrollsheet-side=bottom] :where(.scrollsheet-panel){--scrollsheet-eg:calc(max(var(--scrollsheet-inset-bottom,0px), env(safe-area-inset-bottom,0px)) + var(--scrollsheet-keyboard,0px));bottom:var(--scrollsheet-eg)}.scrollsheet-dialog[data-scrollsheet-scrollbar=native] .scrollsheet-panel{scrollbar-width:auto}.scrollsheet-dialog[data-scrollsheet-scrollbar=native] .scrollsheet-panel::-webkit-scrollbar{display:block}.scrollsheet-dialog[data-scrollsheet-scrollbar=native] [data-scrollsheet-nested-scroll]{scrollbar-width:auto}.scrollsheet-dialog[data-scrollsheet-scrollbar=native] [data-scrollsheet-nested-scroll]::-webkit-scrollbar{display:block}.scrollsheet-dialog[data-scrollsheet-state=opening] .scrollsheet-panel,.scrollsheet-dialog[data-scrollsheet-state=open] .scrollsheet-panel{transform:translate(0,0)}.scrollsheet-dialog[data-scrollsheet-state=closing] .scrollsheet-panel{transform:translate3d(0, calc(100% + var(--scrollsheet-eg,0px) + 32px), 0)}.scrollsheet-dialog[data-scrollsheet-side=top][data-scrollsheet-state=closing] .scrollsheet-panel{transform:translate3d(0, calc(-100% - var(--scrollsheet-inset-top,0px) - 32px), 0)}.scrollsheet-dialog[data-scrollsheet-side=left][data-scrollsheet-state=closing] .scrollsheet-panel{transform:translate3d(calc(-100% - var(--scrollsheet-inset-left,0px) - 32px), 0, 0)}.scrollsheet-dialog[data-scrollsheet-side=right][data-scrollsheet-state=closing] .scrollsheet-panel{transform:translate3d(calc(100% + var(--scrollsheet-inset-right,0px) + 32px), 0, 0)}.scrollsheet-dialog:is([data-scrollsheet-at-max],[data-scrollsheet-kb]) .scrollsheet-panel{overflow-y:auto}.scrollsheet-dialog[data-scrollsheet-kb][data-scrollsheet-side=bottom] .scrollsheet-panel{--scrollsheet-eg:calc(var(--scrollsheet-inset-bottom,0px) + var(--scrollsheet-keyboard,0px) + var(--scrollsheet-kb-hang,0px));box-shadow:none;border-bottom-right-radius:0;border-bottom-left-radius:0}.scrollsheet-kb-fade{display:none}.scrollsheet-dialog[data-scrollsheet-kb][data-scrollsheet-side=bottom] .scrollsheet-kb-fade{left:var(--scrollsheet-inset-x,0px);right:var(--scrollsheet-inset-x,0px);bottom:calc(var(--scrollsheet-keyboard,0px) + var(--scrollsheet-kb-hang,0px));background:linear-gradient(to bottom, transparent, var(--scrollsheet-panel-bg,#fff) 75%);pointer-events:none;z-index:1;height:18px;display:block;position:absolute}.scrollsheet-dialog:is([data-scrollsheet-handle-only],[data-scrollsheet-disable-drag]):not([data-scrollsheet-at-max],[data-scrollsheet-at-nested-boundary],[data-scrollsheet-kb]) :is(.scrollsheet-track,.scrollsheet-canvas){touch-action:none}.scrollsheet-dialog[data-scrollsheet-handle-only] .scrollsheet-panel,.scrollsheet-dialog[data-scrollsheet-disable-drag] .scrollsheet-panel{touch-action:pan-y}.scrollsheet-dialog[data-scrollsheet-handle-only]:not([data-scrollsheet-at-nested-boundary]) .scrollsheet-panel,.scrollsheet-dialog[data-scrollsheet-disable-drag]:not([data-scrollsheet-at-nested-boundary]) .scrollsheet-panel{overscroll-behavior:contain}.scrollsheet-dialog[data-scrollsheet-at-nested-boundary] .scrollsheet-track,.scrollsheet-dialog[data-scrollsheet-at-nested-boundary] .scrollsheet-canvas{touch-action:pan-y}.scrollsheet-dialog[data-scrollsheet-side=left][data-scrollsheet-at-nested-boundary] .scrollsheet-track,.scrollsheet-dialog[data-scrollsheet-side=left][data-scrollsheet-at-nested-boundary] .scrollsheet-canvas,.scrollsheet-dialog[data-scrollsheet-side=right][data-scrollsheet-at-nested-boundary] .scrollsheet-track,.scrollsheet-dialog[data-scrollsheet-side=right][data-scrollsheet-at-nested-boundary] .scrollsheet-canvas{touch-action:pan-x}:where(.scrollsheet-scrollbar){top:0;width:var(--scrollsheet-scrollbar-width,4px);box-sizing:border-box;background:var(--scrollsheet-scrollbar-color,#00000052);opacity:0;pointer-events:none;z-index:2;background-clip:padding-box;border:1px solid #ffffff38;border-radius:999px;transition:opacity .4s;position:absolute;inset-inline-end:3px}.scrollsheet-scrollbar[data-visible]{opacity:1;transition:opacity .12s}@media (prefers-reduced-motion:reduce){:where(.scrollsheet-scrollbar){transition:none}}.scrollsheet-panel:before{content:"";z-index:1;pointer-events:none;opacity:var(--scrollsheet-recede-dim,0);background:#000;position:absolute;inset:0}.scrollsheet-dialog[data-scrollsheet-behind] .scrollsheet-panel{--scrollsheet-recede-dim:.14;--scrollsheet-stack-progress:1;transform-origin:50% 0;transition:transform var(--scrollsheet-dur) var(--scrollsheet-ease);transform:translateY(8px)scale(.94)}.scrollsheet-dialog[data-scrollsheet-behind] .scrollsheet-panel:before{transition:opacity var(--scrollsheet-dur) var(--scrollsheet-ease)}.scrollsheet-dialog[data-scrollsheet-side=top][data-scrollsheet-behind] .scrollsheet-panel{transform-origin:50% 100%;transform:translateY(-8px)scale(.94)}.scrollsheet-dialog[data-scrollsheet-side=left][data-scrollsheet-behind] .scrollsheet-panel{transform-origin:100%;transform:translate(-8px)scale(.94)}.scrollsheet-dialog[data-scrollsheet-side=right][data-scrollsheet-behind] .scrollsheet-panel{transform-origin:0%;transform:translate(8px)scale(.94)}.scrollsheet-track,.scrollsheet-canvas,.scrollsheet-panel,.scrollsheet-dialog:focus-visible,.scrollsheet-track:focus-visible,.scrollsheet-canvas:focus-visible,.scrollsheet-panel:focus-visible{outline:none}[data-scrollsheet-dragging]{-webkit-user-select:none;user-select:none}[data-scrollsheet-dragging] .scrollsheet-panel{cursor:grabbing}.scrollsheet-dialog:is([data-scrollsheet-side=top],[data-scrollsheet-side=left],[data-scrollsheet-side=right]) .scrollsheet-panel{scroll-padding-bottom:var(--scrollsheet-keyboard,0px)}.scrollsheet-dialog:is([data-scrollsheet-side=top],[data-scrollsheet-side=left],[data-scrollsheet-side=right]) [data-scrollsheet-body]{padding-bottom:var(--scrollsheet-keyboard,0px)}:where([data-scrollsheet-body]){display:flow-root}.scrollsheet-panel[data-scrollsheet-fill]{flex-direction:column;display:flex}[data-scrollsheet-body][data-scrollsheet-fill]{flex-direction:column;flex:1;min-height:0;display:flex}@media (prefers-reduced-motion:reduce){.scrollsheet-dialog .scrollsheet-panel,.scrollsheet-dialog .scrollsheet-backdrop{transition:none!important}}@supports (animation-timeline:scroll()){@property --scrollsheet-progress{syntax:"<number>";inherits:true;initial-value:0}.scrollsheet-dialog[data-scrollsheet-sda]{timeline-scope:--scrollsheet-track}.scrollsheet-dialog[data-scrollsheet-sda] .scrollsheet-track{scroll-timeline:--scrollsheet-track y}.scrollsheet-dialog[data-scrollsheet-sda]:is([data-scrollsheet-side=left],[data-scrollsheet-side=right]) .scrollsheet-track{scroll-timeline:--scrollsheet-track x}.scrollsheet-dialog[data-scrollsheet-sda][data-scrollsheet-state=open] .scrollsheet-backdrop{animation:linear both scrollsheet-fade,linear both scrollsheet-progress-var;animation-timeline:--scrollsheet-track,--scrollsheet-track;animation-range:var(--scrollsheet-fade-start,0px) var(--scrollsheet-fade-end,100%), 0px var(--scrollsheet-first-detent,100%)}.scrollsheet-dialog[data-scrollsheet-sda][data-scrollsheet-state=open]:is([data-scrollsheet-side=top],[data-scrollsheet-side=left]) .scrollsheet-backdrop{animation-direction:reverse,reverse;animation-range:calc(var(--scrollsheet-max-detent,0px) - var(--scrollsheet-fade-end,0px)) calc(var(--scrollsheet-max-detent,0px) - var(--scrollsheet-fade-start,0px)), calc(var(--scrollsheet-max-detent,0px) - var(--scrollsheet-first-detent,0px)) var(--scrollsheet-max-detent,0px)}@keyframes scrollsheet-fade{0%{opacity:0}to{opacity:1}}@keyframes scrollsheet-progress-var{0%{--scrollsheet-progress:0}to{--scrollsheet-progress:1}}}.scrollsheet-fallback{z-index:2147483647;display:flex;position:fixed;inset:0}.scrollsheet-fallback[data-scrollsheet-modal=false]{pointer-events:none}.scrollsheet-fallback[data-scrollsheet-modal=false] .scrollsheet-fallback-panel{pointer-events:auto}.scrollsheet-fallback-backdrop{background:var(--scrollsheet-backdrop,#00000052);position:fixed;inset:0}:where(.scrollsheet-fallback-panel){--scrollsheet-radius:20px;background:var(--scrollsheet-bg,#fff);color:var(--scrollsheet-fg,#1d1d1f);box-shadow:var(--scrollsheet-shadow,0 -8px 32px #00000029);overscroll-behavior:contain;-webkit-overflow-scrolling:touch;outline:none;position:relative;overflow-y:auto}@media (prefers-color-scheme:dark){:where(.scrollsheet-fallback-panel){background:var(--scrollsheet-bg,#1c1c1e);color:var(--scrollsheet-fg,#f5f5f7)}}.scrollsheet-fallback[data-scrollsheet-side=bottom]{align-items:flex-end}.scrollsheet-fallback[data-scrollsheet-side=bottom] :where(.scrollsheet-fallback-panel){border-radius:var(--scrollsheet-radius) var(--scrollsheet-radius) 0 0;width:100%;max-height:85%;padding-bottom:max(var(--scrollsheet-safe-area,env(safe-area-inset-bottom,0px)), 0px)}.scrollsheet-fallback[data-scrollsheet-side=top]{align-items:flex-start}.scrollsheet-fallback[data-scrollsheet-side=top] :where(.scrollsheet-fallback-panel){border-radius:0 0 var(--scrollsheet-radius) var(--scrollsheet-radius);width:100%;max-height:85%;box-shadow:var(--scrollsheet-shadow,0 8px 32px #00000029);padding-top:max(var(--scrollsheet-safe-area-top,env(safe-area-inset-top,0px)), 0px)}.scrollsheet-fallback[data-scrollsheet-side=center]{justify-content:center;align-items:center}.scrollsheet-fallback[data-scrollsheet-side=center] :where(.scrollsheet-fallback-panel){max-inline-size:var(--scrollsheet-center-max-inline,min(560px, calc(100% - 40px)));border-radius:var(--scrollsheet-radius);max-height:85%;box-shadow:var(--scrollsheet-shadow,0 8px 32px #00000029)}.scrollsheet-fallback[data-scrollsheet-side=left]{justify-content:flex-start}.scrollsheet-fallback[data-scrollsheet-side=right]{justify-content:flex-end}.scrollsheet-fallback:is([data-scrollsheet-side=left],[data-scrollsheet-side=right]) :where(.scrollsheet-fallback-panel){max-width:85%;height:100%;padding-top:max(var(--scrollsheet-safe-area-top,env(safe-area-inset-top,0px)), 0px);padding-bottom:max(var(--scrollsheet-safe-area,env(safe-area-inset-bottom,0px)), 0px);border-radius:0}.scrollsheet-fallback[data-scrollsheet-side=left] :where(.scrollsheet-fallback-panel){box-shadow:var(--scrollsheet-shadow,8px 0 32px #00000029)}.scrollsheet-fallback[data-scrollsheet-side=right] :where(.scrollsheet-fallback-panel){box-shadow:var(--scrollsheet-shadow,-8px 0 32px #00000029)}@media (min-width:768px){.scrollsheet-fallback[data-scrollsheet-side=bottom] :where(.scrollsheet-fallback-panel),.scrollsheet-fallback[data-scrollsheet-side=top] :where(.scrollsheet-fallback-panel){max-width:var(--scrollsheet-max-inline,640px);margin-inline:auto}}.scrollsheet-fallback [data-scrollsheet-handle]{display:none}@media (forced-colors:active){:where(.scrollsheet-backdrop),:where(.scrollsheet-fallback-backdrop){forced-color-adjust:none}:where(.scrollsheet-panel),:where(.scrollsheet-fallback-panel){color:canvastext;box-shadow:none;background:canvas;border:1px solid buttonborder}.scrollsheet-dialog:is([data-scrollsheet-side=top],[data-scrollsheet-side=left],[data-scrollsheet-side=right]) :where(.scrollsheet-panel),.scrollsheet-fallback:is([data-scrollsheet-side=top],[data-scrollsheet-side=left],[data-scrollsheet-side=right]) :where(.scrollsheet-fallback-panel){box-shadow:none}:where(.scrollsheet-scrollbar){background:highlight}}.scrollsheet-dialog[data-scrollsheet-side=center] .scrollsheet-track{scroll-snap-type:none;box-sizing:border-box;padding:var(--scrollsheet-center-gutter,20px);padding-bottom:calc(var(--scrollsheet-center-gutter,20px) + var(--scrollsheet-keyboard,0px));place-items:center;display:grid;overflow:hidden}.scrollsheet-dialog[data-scrollsheet-side=center] .scrollsheet-canvas{display:contents}.scrollsheet-dialog[data-scrollsheet-side=center] .scrollsheet-canvas:after{content:none}.scrollsheet-dialog[data-scrollsheet-side=center] .scrollsheet-panel{width:auto;height:auto;max-inline-size:var(--scrollsheet-center-max-inline,min(560px, 100%));max-block-size:var(--scrollsheet-center-max-block,100%);border-radius:var(--scrollsheet-radius,16px);padding-bottom:0;position:static;inset:auto;overflow:auto}.scrollsheet-dialog[data-scrollsheet-side=center] .scrollsheet-handle{display:none}.scrollsheet-dialog[data-scrollsheet-side=center]:is([data-scrollsheet-state=pre],[data-scrollsheet-state=closing]) .scrollsheet-panel{opacity:0;transform:scale(.95)}.scrollsheet-handle:before{content:"";width:max(100%,44px);height:44px;position:absolute;top:50%;left:50%;transform:translate(-50%,-50%)}:where(.scrollsheet-handle){background:var(--scrollsheet-handle,#0003);cursor:grab;width:44px;height:5px;box-shadow:0 0 0 2px transparent, 0 0 0 calc(2px + var(--scrollsheet-focus-ring-width,2px)) transparent;transition:transform .18s var(--scrollsheet-ease), background .18s ease, box-shadow .15s ease;border:none;border-radius:999px;outline:none;margin:8px auto;padding:0;display:block;position:relative}:where(.scrollsheet-handle:hover){background:var(--scrollsheet-handle-hover,#00000052)}:where(.scrollsheet-handle:active){cursor:grabbing;transform:scaleX(1.3)}@media (prefers-color-scheme:dark){:where(.scrollsheet-handle){background:var(--scrollsheet-handle,#ffffff52)}:where(.scrollsheet-handle:hover){background:var(--scrollsheet-handle-hover,#ffffff75)}}:where(.scrollsheet-handle[data-scrollsheet-handle-variant=floating]){z-index:1;margin:0;position:absolute;top:8px;left:50%;translate:-50%}:where(.scrollsheet-canvas>.scrollsheet-handle[data-scrollsheet-handle-variant=outside]){left:50%;bottom:calc(var(--scrollsheet-ib,0px) + var(--scrollsheet-keyboard,0px) + var(--scrollsheet-kb-hang,0px) + var(--scrollsheet-max-detent,0px) + 10px);background:var(--scrollsheet-handle,#fffc);margin:0;position:absolute;translate:-50%}.scrollsheet-dialog:not([data-scrollsheet-state=open]) .scrollsheet-canvas>.scrollsheet-handle[data-scrollsheet-handle-variant=outside]{opacity:0;transition:opacity .12s}.scrollsheet-dialog[data-scrollsheet-modal=false] .scrollsheet-handle[data-scrollsheet-handle-variant=outside]{pointer-events:auto;touch-action:none}:where(.scrollsheet-close){top:12px;z-index:1;background:var(--scrollsheet-close-bg,#0000000f);width:28px;height:28px;color:var(--scrollsheet-close-color,#0000008c);cursor:pointer;box-shadow:0 0 0 2px transparent, 0 0 0 calc(2px + var(--scrollsheet-focus-ring-width,2px)) transparent;border:none;border-radius:999px;outline:none;place-items:center;padding:0;transition:background .15s,color .15s,box-shadow .15s;display:grid;position:absolute;inset-inline-end:12px}.scrollsheet-close:before{content:"";width:44px;height:44px;position:absolute;top:50%;left:50%;transform:translate(-50%,-50%)}:where(.scrollsheet-close:hover){background:var(--scrollsheet-close-bg-hover,#0000001a);color:var(--scrollsheet-close-color-hover,#000000bf)}@media (prefers-color-scheme:dark){:where(.scrollsheet-close){background:var(--scrollsheet-close-bg,#ffffff17);color:var(--scrollsheet-close-color,#ffffff9e)}:where(.scrollsheet-close:hover){background:var(--scrollsheet-close-bg-hover,#ffffff24);color:var(--scrollsheet-close-color-hover,#ffffffd9)}}:where(.scrollsheet-close:focus-visible),:where(.scrollsheet-handle:focus-visible){box-shadow:0 0 0 2px transparent, 0 0 0 calc(2px + var(--scrollsheet-focus-ring-width,2px)) var(--scrollsheet-focus-ring,#6366f199);outline:none}.scrollsheet-dialog[data-scrollsheet-side=left] .scrollsheet-handle:before,.scrollsheet-dialog[data-scrollsheet-side=right] .scrollsheet-handle:before{width:44px;height:max(100%,44px)}.scrollsheet-dialog[data-scrollsheet-side=left] :where(.scrollsheet-handle),.scrollsheet-dialog[data-scrollsheet-side=right] :where(.scrollsheet-handle){width:5px;height:44px;margin:auto 8px}.scrollsheet-dialog[data-scrollsheet-side=left] :where(.scrollsheet-handle:active),.scrollsheet-dialog[data-scrollsheet-side=right] :where(.scrollsheet-handle:active){transform:scaleY(1.3)}@media (forced-colors:active){:where(.scrollsheet-handle){box-shadow:none;background:buttonborder}:where(.scrollsheet-handle:focus-visible){box-shadow:none;outline:2px solid highlight}:where(.scrollsheet-close){color:buttontext;box-shadow:none;background:canvas;border:1px solid buttonborder}:where(.scrollsheet-close:focus-visible){box-shadow:none;outline:2px solid highlight}}
.scrollsheet-dialog[data-scrollsheet-side=bottom]{--scrollsheet-keyboard-lift:var(--scrollsheet-keyboard,0px)}.scrollsheet-dialog{width:100%;height:calc(100% + var(--scrollsheet-keyboard-lift,0px));--scrollsheet-ease:linear(0, 0.042 3.4%, 0.136 6.9%, 0.37 13.8%, 0.481 17.2%, 0.58 20.7%, 0.664 24.1%, 0.735 27.6%, 0.793 31%, 0.839 34.5%, 0.876 37.9%, 0.906 41.4%, 0.928 44.8%, 0.946 48.3%, 0.96 51.7%, 0.978 58.6%, 0.988 65.5%, 0.994 72.4%, 0.998 82.8%, 1);--scrollsheet-dur:475ms;background:0 0;border:none;outline:none;max-width:none;max-height:none;margin:0;padding:0;position:fixed;inset:0;overflow:clip}.scrollsheet-dialog::backdrop{background:0 0}:where(.scrollsheet-backdrop){background:var(--scrollsheet-backdrop,#00000052);opacity:0;pointer-events:none;position:fixed;inset:0}.scrollsheet-dialog[data-scrollsheet-state=opening] .scrollsheet-backdrop{opacity:min(var(--scrollsheet-dim,0), 1);transition:opacity var(--scrollsheet-dur) var(--scrollsheet-ease)}.scrollsheet-dialog[data-scrollsheet-state=open] .scrollsheet-backdrop{opacity:min(var(--scrollsheet-dim,0), 1);transition:none}.scrollsheet-dialog[data-scrollsheet-state=closing] .scrollsheet-backdrop{opacity:0;transition:opacity var(--scrollsheet-dur) var(--scrollsheet-ease)}:where(.scrollsheet-top-chrome){height:calc(env(safe-area-inset-top,0px) + 8px);inset:0 0 auto}:where(.scrollsheet-bottom-chrome){height:calc(env(safe-area-inset-bottom,0px) + 32px);inset:auto 0 0}:where(.scrollsheet-top-chrome)~:where([data-scrollsheet-backdrop]){top:calc(env(safe-area-inset-top,0px) + 8px)}:where(.scrollsheet-bottom-chrome)~:where([data-scrollsheet-backdrop]){bottom:calc(env(safe-area-inset-bottom,0px) + 32px)}.scrollsheet-dialog:is([data-scrollsheet-state=pre],[data-scrollsheet-state=opening]) :is(.scrollsheet-top-chrome,.scrollsheet-bottom-chrome){opacity:min(var(--scrollsheet-dim,0), 1);transition:none}.scrollsheet-bottom-sentinel{height:min(calc(max(env(safe-area-inset-bottom,0px), 24px) + 45vh), var(--scrollsheet-reveal,24px));pointer-events:none;position:fixed;inset:auto 0 0}.scrollsheet-track{left:0;right:0;top:var(--scrollsheet-vv-top,0px);height:calc(var(--scrollsheet-vv-height,100%) + var(--scrollsheet-keyboard-lift,0px));overscroll-behavior:contain;scroll-snap-type:y mandatory;scrollbar-width:none;position:fixed;overflow-y:scroll}.scrollsheet-track::-webkit-scrollbar{display:none}.scrollsheet-dialog:is([data-scrollsheet-side=left],[data-scrollsheet-side=right]) .scrollsheet-track{scroll-snap-type:x mandatory;overscroll-behavior-x:none;overflow:scroll hidden}.scrollsheet-dialog[data-scrollsheet-modal=false]{pointer-events:none}.scrollsheet-dialog[data-scrollsheet-modal=false] .scrollsheet-panel{pointer-events:auto;touch-action:none}.scrollsheet-canvas{height:calc(100% + var(--scrollsheet-max-detent,0px));position:relative}.scrollsheet-dialog:is([data-scrollsheet-side=left],[data-scrollsheet-side=right]) .scrollsheet-canvas{width:calc(100% + var(--scrollsheet-max-detent,0px));height:100%}.scrollsheet-canvas:after{content:"";top:calc(100% - var(--scrollsheet-keyboard,0px));--scrollsheet-od:calc(120vh + var(--scrollsheet-keyboard,0px));height:0;box-shadow:0 calc(var(--scrollsheet-od) / 2) 0 calc(var(--scrollsheet-od) / 2) var(--scrollsheet-panel-bg,transparent);pointer-events:none;position:absolute;left:0;right:0}.scrollsheet-dialog[data-scrollsheet-side=top] .scrollsheet-canvas:after{box-shadow:0 -60vh 0 60vh var(--scrollsheet-panel-bg,transparent);top:auto;bottom:100%}.scrollsheet-dialog[data-scrollsheet-side=left] .scrollsheet-canvas:after{width:0;height:auto;box-shadow:-60vw 0 0 60vw var(--scrollsheet-panel-bg,transparent);inset:0 100% 0 auto}.scrollsheet-dialog[data-scrollsheet-side=right] .scrollsheet-canvas:after{width:0;height:auto;box-shadow:60vw 0 0 60vw var(--scrollsheet-panel-bg,transparent);inset:0 auto 0 100%}.scrollsheet-dialog[data-scrollsheet-detached] .scrollsheet-canvas:after{box-shadow:none}.scrollsheet-snap{pointer-events:none;scroll-snap-align:start;width:100%;height:1px;position:absolute;left:0}.scrollsheet-dialog:is([data-scrollsheet-side=left],[data-scrollsheet-side=right]) .scrollsheet-snap{width:1px;height:100%;top:0;left:auto}.scrollsheet-panel{--scrollsheet-eg:calc(var(--scrollsheet-inset-bottom,0px) + var(--scrollsheet-keyboard,0px));bottom:var(--scrollsheet-eg);left:var(--scrollsheet-inset-x,0px);right:var(--scrollsheet-inset-x,0px);height:var(--scrollsheet-max-detent,auto);max-height:var(--scrollsheet-vv-height,none);will-change:transform;padding-bottom:max(var(--scrollsheet-safe-area,env(safe-area-inset-bottom,0px)), 0px);position:absolute;overflow:hidden;transform:translateY(100%)}.scrollsheet-dialog[data-scrollsheet-side=top] .scrollsheet-panel{bottom:auto;top:var(--scrollsheet-inset-top,0px);left:var(--scrollsheet-inset-x,0px);right:var(--scrollsheet-inset-x,0px);height:var(--scrollsheet-max-detent,auto);padding-bottom:0;padding-top:max(var(--scrollsheet-safe-area-top,env(safe-area-inset-top,0px)), 0px);transform:translateY(-100%)}.scrollsheet-dialog:is([data-scrollsheet-side=left],[data-scrollsheet-side=right]) .scrollsheet-panel{top:var(--scrollsheet-inset-y,0px);bottom:var(--scrollsheet-inset-y,0px);width:var(--scrollsheet-max-detent,auto);height:auto;padding-top:max(var(--scrollsheet-safe-area-top,env(safe-area-inset-top,0px)), 0px)}.scrollsheet-dialog[data-scrollsheet-side=left] .scrollsheet-panel{right:auto;left:var(--scrollsheet-inset-left,0px);padding-left:max(var(--scrollsheet-safe-area-left,env(safe-area-inset-left,0px)), 0px);transform:translate(-100%)}.scrollsheet-dialog[data-scrollsheet-side=right] .scrollsheet-panel{left:auto;right:var(--scrollsheet-inset-right,0px);padding-right:max(var(--scrollsheet-safe-area-right,env(safe-area-inset-right,0px)), 0px);transform:translate(100%)}.scrollsheet-dialog:is([data-scrollsheet-side=top],[data-scrollsheet-side=left]) .scrollsheet-panel{justify-content:flex-end;display:flex}.scrollsheet-dialog[data-scrollsheet-side=top] .scrollsheet-panel{flex-direction:column}.scrollsheet-dialog[data-scrollsheet-side=left] .scrollsheet-panel{flex-direction:row}.scrollsheet-dialog[data-scrollsheet-side=left] .scrollsheet-panel>*{flex:0 0 100%;min-width:0}:where(.scrollsheet-panel){scrollbar-width:none}:where(.scrollsheet-panel)::-webkit-scrollbar{display:none}:where([data-scrollsheet-nested-scroll]){scrollbar-width:none}:where([data-scrollsheet-nested-scroll])::-webkit-scrollbar{display:none}:where(.scrollsheet-dialog[data-scrollsheet-scrollbar=overlay] [data-scrollsheet-nested-scroll]){position:relative}:where(.scrollsheet-panel){--scrollsheet-radius:20px;background:var(--scrollsheet-bg,#fff);color:var(--scrollsheet-fg,#1d1d1f);border-radius:var(--scrollsheet-radius) var(--scrollsheet-radius) 0 0;box-shadow:var(--scrollsheet-shadow,0 -8px 32px #00000029)}:where([data-scrollsheet-theme=dark]) :where(.scrollsheet-panel){background:var(--scrollsheet-bg,#1c1c1e);color:var(--scrollsheet-fg,#f5f5f7)}@media (prefers-color-scheme:dark){:where([data-scrollsheet-theme=system]) :where(.scrollsheet-panel){background:var(--scrollsheet-bg,#1c1c1e);color:var(--scrollsheet-fg,#f5f5f7)}}.scrollsheet-dialog[data-scrollsheet-side=top] :where(.scrollsheet-panel){border-radius:0 0 var(--scrollsheet-radius) var(--scrollsheet-radius);box-shadow:var(--scrollsheet-shadow,0 8px 32px #00000029)}.scrollsheet-dialog[data-scrollsheet-side=left] :where(.scrollsheet-panel){box-shadow:var(--scrollsheet-shadow,8px 0 32px #00000029);border-radius:0}.scrollsheet-dialog[data-scrollsheet-side=right] :where(.scrollsheet-panel){box-shadow:var(--scrollsheet-shadow,-8px 0 32px #00000029);border-radius:0}@media (min-width:768px){:where(.scrollsheet-dialog[data-scrollsheet-side=bottom]) :where(.scrollsheet-panel),:where(.scrollsheet-dialog[data-scrollsheet-side=bottom]) .scrollsheet-canvas:after{width:min(var(--scrollsheet-max-inline,640px), calc(100% - 2 * var(--scrollsheet-desktop-margin,24px)));margin-inline:auto var(--scrollsheet-desktop-margin,24px)}.scrollsheet-dialog[data-scrollsheet-side=bottom] .scrollsheet-panel{--scrollsheet-inset-bottom:var(--scrollsheet-desktop-margin,24px);--scrollsheet-dg:calc(var(--scrollsheet-desktop-margin,24px) + var(--scrollsheet-inset-x,0px) + 32px)}.scrollsheet-dialog[data-scrollsheet-side=bottom]:where([data-scrollsheet-detached]) .scrollsheet-panel,.scrollsheet-dialog[data-scrollsheet-side=bottom][data-scrollsheet-state=closing]:where([data-scrollsheet-detached]) .scrollsheet-panel{transform:translate3d(calc(100% + var(--scrollsheet-dg,32px)), 0, 0)}.scrollsheet-dialog[data-scrollsheet-side=bottom]:where([data-scrollsheet-detached][data-scrollsheet-rtl]) .scrollsheet-panel,.scrollsheet-dialog[data-scrollsheet-side=bottom][data-scrollsheet-state=closing]:where([data-scrollsheet-detached][data-scrollsheet-rtl]) .scrollsheet-panel{transform:translate3d(calc(-100% - var(--scrollsheet-dg,32px)), 0, 0)}.scrollsheet-dialog[data-scrollsheet-side=top] .scrollsheet-panel{top:var(--scrollsheet-desktop-margin,24px);border-radius:var(--scrollsheet-radius)}.scrollsheet-dialog[data-scrollsheet-side=bottom] :where(.scrollsheet-handle){opacity:0;pointer-events:none;width:5px;height:44px;margin:-22px 0 0;position:absolute;top:50%;left:10px}.scrollsheet-dialog[data-scrollsheet-side=bottom] :where(.scrollsheet-handle:focus-visible){opacity:1;pointer-events:auto}.scrollsheet-dialog[data-scrollsheet-side=bottom][data-scrollsheet-has-handle] :where(.scrollsheet-body){padding-top:18px}:where(.scrollsheet-dialog[data-scrollsheet-side=top]) :where(.scrollsheet-panel),:where(.scrollsheet-dialog[data-scrollsheet-side=top]) .scrollsheet-canvas:after{max-width:var(--scrollsheet-max-inline,640px);margin-inline:auto}}.scrollsheet-dialog[data-scrollsheet-detached] :where(.scrollsheet-panel){padding-bottom:max(var(--scrollsheet-safe-area,0px), 0px);border-radius:var(--scrollsheet-radius)}.scrollsheet-dialog[data-scrollsheet-detached][data-scrollsheet-side=bottom] :where(.scrollsheet-panel){--scrollsheet-eg:calc(max(var(--scrollsheet-inset-bottom,0px), env(safe-area-inset-bottom,0px)) + var(--scrollsheet-keyboard,0px));bottom:var(--scrollsheet-eg)}.scrollsheet-dialog[data-scrollsheet-scrollbar=native] .scrollsheet-panel{scrollbar-width:auto}.scrollsheet-dialog[data-scrollsheet-scrollbar=native] .scrollsheet-panel::-webkit-scrollbar{display:block}.scrollsheet-dialog[data-scrollsheet-scrollbar=native] [data-scrollsheet-nested-scroll]{scrollbar-width:auto}.scrollsheet-dialog[data-scrollsheet-scrollbar=native] [data-scrollsheet-nested-scroll]::-webkit-scrollbar{display:block}.scrollsheet-dialog[data-scrollsheet-state=opening] .scrollsheet-panel,.scrollsheet-dialog[data-scrollsheet-state=open] .scrollsheet-panel{transform:translate(0,0)}.scrollsheet-dialog[data-scrollsheet-state=closing] .scrollsheet-panel{transform:translate3d(0, calc(100% + var(--scrollsheet-eg,0px) + 32px), 0)}.scrollsheet-dialog[data-scrollsheet-side=top][data-scrollsheet-state=closing] .scrollsheet-panel{transform:translate3d(0, calc(-100% - var(--scrollsheet-inset-top,0px) - 32px), 0)}.scrollsheet-dialog[data-scrollsheet-side=left][data-scrollsheet-state=closing] .scrollsheet-panel{transform:translate3d(calc(-100% - var(--scrollsheet-inset-left,0px) - 32px), 0, 0)}.scrollsheet-dialog[data-scrollsheet-side=right][data-scrollsheet-state=closing] .scrollsheet-panel{transform:translate3d(calc(100% + var(--scrollsheet-inset-right,0px) + 32px), 0, 0)}.scrollsheet-dialog:is([data-scrollsheet-at-max],[data-scrollsheet-kb]) .scrollsheet-panel{overflow-y:auto}.scrollsheet-dialog[data-scrollsheet-kb][data-scrollsheet-side=bottom] .scrollsheet-panel{--scrollsheet-eg:calc(var(--scrollsheet-inset-bottom,0px) + var(--scrollsheet-keyboard,0px) + var(--scrollsheet-kb-hang,0px));box-shadow:none;border-bottom-right-radius:0;border-bottom-left-radius:0}.scrollsheet-kb-fade{display:none}.scrollsheet-dialog[data-scrollsheet-kb][data-scrollsheet-side=bottom] .scrollsheet-kb-fade{left:var(--scrollsheet-inset-x,0px);right:var(--scrollsheet-inset-x,0px);bottom:calc(var(--scrollsheet-keyboard,0px) + var(--scrollsheet-kb-hang,0px));background:linear-gradient(to bottom, transparent, var(--scrollsheet-panel-bg,#fff) 75%);pointer-events:none;z-index:1;height:18px;display:block;position:absolute}.scrollsheet-dialog:is([data-scrollsheet-handle-only],[data-scrollsheet-disable-drag]):not([data-scrollsheet-at-max],[data-scrollsheet-at-nested-boundary],[data-scrollsheet-kb]) :is(.scrollsheet-track,.scrollsheet-canvas){touch-action:none}.scrollsheet-dialog[data-scrollsheet-handle-only] .scrollsheet-panel,.scrollsheet-dialog[data-scrollsheet-disable-drag] .scrollsheet-panel{touch-action:pan-y}.scrollsheet-dialog[data-scrollsheet-handle-only]:not([data-scrollsheet-at-nested-boundary]) .scrollsheet-panel,.scrollsheet-dialog[data-scrollsheet-disable-drag]:not([data-scrollsheet-at-nested-boundary]) .scrollsheet-panel{overscroll-behavior:contain}.scrollsheet-dialog[data-scrollsheet-at-nested-boundary] .scrollsheet-track,.scrollsheet-dialog[data-scrollsheet-at-nested-boundary] .scrollsheet-canvas{touch-action:pan-y}.scrollsheet-dialog[data-scrollsheet-side=left][data-scrollsheet-at-nested-boundary] .scrollsheet-track,.scrollsheet-dialog[data-scrollsheet-side=left][data-scrollsheet-at-nested-boundary] .scrollsheet-canvas,.scrollsheet-dialog[data-scrollsheet-side=right][data-scrollsheet-at-nested-boundary] .scrollsheet-track,.scrollsheet-dialog[data-scrollsheet-side=right][data-scrollsheet-at-nested-boundary] .scrollsheet-canvas{touch-action:pan-x}:where(.scrollsheet-scrollbar){top:0;width:var(--scrollsheet-scrollbar-width,4px);box-sizing:border-box;background:var(--scrollsheet-scrollbar-color,#00000052);opacity:0;pointer-events:none;z-index:2;background-clip:padding-box;border:1px solid #ffffff38;border-radius:999px;transition:opacity .4s;position:absolute;inset-inline-end:3px}.scrollsheet-scrollbar[data-visible]{opacity:1;transition:opacity .12s}@media (prefers-reduced-motion:reduce){:where(.scrollsheet-scrollbar){transition:none}}.scrollsheet-panel:before{content:"";z-index:1;pointer-events:none;opacity:var(--scrollsheet-recede-dim,0);background:#000;position:absolute;inset:0}.scrollsheet-dialog[data-scrollsheet-behind] .scrollsheet-panel{--scrollsheet-recede-dim:.14;--scrollsheet-stack-progress:1;transform-origin:50% 0;transition:transform var(--scrollsheet-dur) var(--scrollsheet-ease);transform:translateY(8px)scale(.94)}.scrollsheet-dialog[data-scrollsheet-behind] .scrollsheet-panel:before{transition:opacity var(--scrollsheet-dur) var(--scrollsheet-ease)}.scrollsheet-dialog[data-scrollsheet-side=top][data-scrollsheet-behind] .scrollsheet-panel{transform-origin:50% 100%;transform:translateY(-8px)scale(.94)}.scrollsheet-dialog[data-scrollsheet-side=left][data-scrollsheet-behind] .scrollsheet-panel{transform-origin:100%;transform:translate(-8px)scale(.94)}.scrollsheet-dialog[data-scrollsheet-side=right][data-scrollsheet-behind] .scrollsheet-panel{transform-origin:0%;transform:translate(8px)scale(.94)}.scrollsheet-track,.scrollsheet-canvas,.scrollsheet-panel,.scrollsheet-dialog:focus-visible,.scrollsheet-track:focus-visible,.scrollsheet-canvas:focus-visible,.scrollsheet-panel:focus-visible{outline:none}[data-scrollsheet-dragging]{-webkit-user-select:none;user-select:none}[data-scrollsheet-dragging] .scrollsheet-panel{cursor:grabbing}.scrollsheet-dialog:is([data-scrollsheet-side=top],[data-scrollsheet-side=left],[data-scrollsheet-side=right]) .scrollsheet-panel{scroll-padding-bottom:var(--scrollsheet-keyboard,0px)}.scrollsheet-dialog:is([data-scrollsheet-side=top],[data-scrollsheet-side=left],[data-scrollsheet-side=right]) [data-scrollsheet-body]{padding-bottom:var(--scrollsheet-keyboard,0px)}:where([data-scrollsheet-body]){display:flow-root}.scrollsheet-panel[data-scrollsheet-fill]{flex-direction:column;display:flex}[data-scrollsheet-body][data-scrollsheet-fill]{flex-direction:column;flex:1;min-height:0;display:flex}@media (prefers-reduced-motion:reduce){.scrollsheet-dialog .scrollsheet-panel,.scrollsheet-dialog .scrollsheet-backdrop{transition:none!important}}@supports (animation-timeline:scroll()){@property --scrollsheet-progress{syntax:"<number>";inherits:true;initial-value:0}.scrollsheet-dialog[data-scrollsheet-sda]{timeline-scope:--scrollsheet-track}.scrollsheet-dialog[data-scrollsheet-sda] .scrollsheet-track{scroll-timeline:--scrollsheet-track y}.scrollsheet-dialog[data-scrollsheet-sda]:is([data-scrollsheet-side=left],[data-scrollsheet-side=right]) .scrollsheet-track{scroll-timeline:--scrollsheet-track x}.scrollsheet-dialog[data-scrollsheet-sda][data-scrollsheet-state=open] .scrollsheet-backdrop{animation:linear both scrollsheet-fade,linear both scrollsheet-progress-var;animation-timeline:--scrollsheet-track,--scrollsheet-track;animation-range:var(--scrollsheet-fade-start,0px) var(--scrollsheet-fade-end,100%), 0px var(--scrollsheet-first-detent,100%)}.scrollsheet-dialog[data-scrollsheet-sda][data-scrollsheet-state=open]:is([data-scrollsheet-side=top],[data-scrollsheet-side=left]) .scrollsheet-backdrop{animation-direction:reverse,reverse;animation-range:calc(var(--scrollsheet-max-detent,0px) - var(--scrollsheet-fade-end,0px)) calc(var(--scrollsheet-max-detent,0px) - var(--scrollsheet-fade-start,0px)), calc(var(--scrollsheet-max-detent,0px) - var(--scrollsheet-first-detent,0px)) var(--scrollsheet-max-detent,0px)}@keyframes scrollsheet-fade{0%{opacity:0}to{opacity:1}}@keyframes scrollsheet-progress-var{0%{--scrollsheet-progress:0}to{--scrollsheet-progress:1}}}.scrollsheet-fallback{z-index:2147483647;display:flex;position:fixed;inset:0}.scrollsheet-fallback[data-scrollsheet-modal=false]{pointer-events:none}.scrollsheet-fallback[data-scrollsheet-modal=false] .scrollsheet-fallback-panel{pointer-events:auto}.scrollsheet-fallback-backdrop{background:var(--scrollsheet-backdrop,#00000052);position:fixed;inset:0}:where(.scrollsheet-fallback-panel){--scrollsheet-radius:20px;background:var(--scrollsheet-bg,#fff);color:var(--scrollsheet-fg,#1d1d1f);box-shadow:var(--scrollsheet-shadow,0 -8px 32px #00000029);overscroll-behavior:contain;-webkit-overflow-scrolling:touch;outline:none;position:relative;overflow-y:auto}:where([data-scrollsheet-theme=dark]) :where(.scrollsheet-fallback-panel){background:var(--scrollsheet-bg,#1c1c1e);color:var(--scrollsheet-fg,#f5f5f7)}@media (prefers-color-scheme:dark){:where([data-scrollsheet-theme=system]) :where(.scrollsheet-fallback-panel){background:var(--scrollsheet-bg,#1c1c1e);color:var(--scrollsheet-fg,#f5f5f7)}}.scrollsheet-fallback[data-scrollsheet-side=bottom]{align-items:flex-end}.scrollsheet-fallback[data-scrollsheet-side=bottom] :where(.scrollsheet-fallback-panel){border-radius:var(--scrollsheet-radius) var(--scrollsheet-radius) 0 0;width:100%;max-height:85%;padding-bottom:max(var(--scrollsheet-safe-area,env(safe-area-inset-bottom,0px)), 0px)}.scrollsheet-fallback[data-scrollsheet-side=top]{align-items:flex-start}.scrollsheet-fallback[data-scrollsheet-side=top] :where(.scrollsheet-fallback-panel){border-radius:0 0 var(--scrollsheet-radius) var(--scrollsheet-radius);width:100%;max-height:85%;box-shadow:var(--scrollsheet-shadow,0 8px 32px #00000029);padding-top:max(var(--scrollsheet-safe-area-top,env(safe-area-inset-top,0px)), 0px)}.scrollsheet-fallback[data-scrollsheet-side=center]{justify-content:center;align-items:center}.scrollsheet-fallback[data-scrollsheet-side=center] :where(.scrollsheet-fallback-panel){max-inline-size:var(--scrollsheet-center-max-inline,min(560px, calc(100% - 40px)));border-radius:var(--scrollsheet-radius);max-height:85%;box-shadow:var(--scrollsheet-shadow,0 8px 32px #00000029)}.scrollsheet-fallback[data-scrollsheet-side=left]{justify-content:flex-start}.scrollsheet-fallback[data-scrollsheet-side=right]{justify-content:flex-end}.scrollsheet-fallback:is([data-scrollsheet-side=left],[data-scrollsheet-side=right]) :where(.scrollsheet-fallback-panel){max-width:85%;height:100%;padding-top:max(var(--scrollsheet-safe-area-top,env(safe-area-inset-top,0px)), 0px);padding-bottom:max(var(--scrollsheet-safe-area,env(safe-area-inset-bottom,0px)), 0px);border-radius:0}.scrollsheet-fallback[data-scrollsheet-side=left] :where(.scrollsheet-fallback-panel){box-shadow:var(--scrollsheet-shadow,8px 0 32px #00000029)}.scrollsheet-fallback[data-scrollsheet-side=right] :where(.scrollsheet-fallback-panel){box-shadow:var(--scrollsheet-shadow,-8px 0 32px #00000029)}@media (min-width:768px){.scrollsheet-fallback[data-scrollsheet-side=bottom] :where(.scrollsheet-fallback-panel),.scrollsheet-fallback[data-scrollsheet-side=top] :where(.scrollsheet-fallback-panel){max-width:var(--scrollsheet-max-inline,640px);margin-inline:auto}}.scrollsheet-fallback [data-scrollsheet-handle]{display:none}@media (forced-colors:active){:where(.scrollsheet-backdrop),:where(.scrollsheet-fallback-backdrop){forced-color-adjust:none}:where(.scrollsheet-panel),:where(.scrollsheet-fallback-panel){color:canvastext;box-shadow:none;background:canvas;border:1px solid buttonborder}.scrollsheet-dialog:is([data-scrollsheet-side=top],[data-scrollsheet-side=left],[data-scrollsheet-side=right]) :where(.scrollsheet-panel),.scrollsheet-fallback:is([data-scrollsheet-side=top],[data-scrollsheet-side=left],[data-scrollsheet-side=right]) :where(.scrollsheet-fallback-panel){box-shadow:none}:where(.scrollsheet-scrollbar){background:highlight}}.scrollsheet-dialog[data-scrollsheet-side=center] .scrollsheet-track{scroll-snap-type:none;box-sizing:border-box;padding:var(--scrollsheet-center-gutter,20px);padding-bottom:calc(var(--scrollsheet-center-gutter,20px) + var(--scrollsheet-keyboard,0px));place-items:center;display:grid;overflow:hidden}.scrollsheet-dialog[data-scrollsheet-side=center] .scrollsheet-canvas{display:contents}.scrollsheet-dialog[data-scrollsheet-side=center] .scrollsheet-canvas:after{content:none}.scrollsheet-dialog[data-scrollsheet-side=center] .scrollsheet-panel{width:auto;height:auto;max-inline-size:var(--scrollsheet-center-max-inline,min(560px, 100%));max-block-size:var(--scrollsheet-center-max-block,100%);border-radius:var(--scrollsheet-radius,16px);padding-bottom:0;position:static;inset:auto;overflow:auto}.scrollsheet-dialog[data-scrollsheet-side=center] .scrollsheet-handle{display:none}.scrollsheet-dialog[data-scrollsheet-side=center]:is([data-scrollsheet-state=pre],[data-scrollsheet-state=closing]) .scrollsheet-panel{opacity:0;transform:scale(.95)}.scrollsheet-handle:before{content:"";width:max(100%,44px);height:44px;position:absolute;top:50%;left:50%;transform:translate(-50%,-50%)}:where(.scrollsheet-handle){background:var(--scrollsheet-handle,#0003);cursor:grab;width:44px;height:5px;box-shadow:0 0 0 2px transparent, 0 0 0 calc(2px + var(--scrollsheet-focus-ring-width,2px)) transparent;transition:transform .18s var(--scrollsheet-ease), background .18s ease, box-shadow .15s ease;border:none;border-radius:999px;outline:none;margin:8px auto;padding:0;display:block;position:relative}:where(.scrollsheet-handle:hover){background:var(--scrollsheet-handle-hover,#00000052)}:where(.scrollsheet-handle:active){cursor:grabbing;transform:scaleX(1.3)}:where([data-scrollsheet-theme=dark]) :where(.scrollsheet-handle){background:var(--scrollsheet-handle,#ffffff52)}:where([data-scrollsheet-theme=dark]) :where(.scrollsheet-handle:hover){background:var(--scrollsheet-handle-hover,#ffffff75)}@media (prefers-color-scheme:dark){:where([data-scrollsheet-theme=system]) :where(.scrollsheet-handle){background:var(--scrollsheet-handle,#ffffff52)}:where([data-scrollsheet-theme=system]) :where(.scrollsheet-handle:hover){background:var(--scrollsheet-handle-hover,#ffffff75)}}:where(.scrollsheet-handle[data-scrollsheet-handle-variant=floating]){z-index:1;margin:0;position:absolute;top:8px;left:50%;translate:-50%}:where(.scrollsheet-canvas>.scrollsheet-handle[data-scrollsheet-handle-variant=outside]){left:50%;bottom:calc(var(--scrollsheet-ib,0px) + var(--scrollsheet-keyboard,0px) + var(--scrollsheet-kb-hang,0px) + var(--scrollsheet-max-detent,0px) + 10px);background:var(--scrollsheet-handle,#fffc);margin:0;position:absolute;translate:-50%}.scrollsheet-dialog:not([data-scrollsheet-state=open]) .scrollsheet-canvas>.scrollsheet-handle[data-scrollsheet-handle-variant=outside]{opacity:0;transition:opacity .12s}.scrollsheet-dialog[data-scrollsheet-modal=false] .scrollsheet-handle[data-scrollsheet-handle-variant=outside]{pointer-events:auto;touch-action:none}:where(.scrollsheet-close){top:12px;z-index:1;background:var(--scrollsheet-close-bg,#0000000f);width:28px;height:28px;color:var(--scrollsheet-close-color,#0000008c);cursor:pointer;box-shadow:0 0 0 2px transparent, 0 0 0 calc(2px + var(--scrollsheet-focus-ring-width,2px)) transparent;border:none;border-radius:999px;outline:none;place-items:center;padding:0;transition:background .15s,color .15s,box-shadow .15s;display:grid;position:absolute;inset-inline-end:12px}.scrollsheet-close:before{content:"";width:44px;height:44px;position:absolute;top:50%;left:50%;transform:translate(-50%,-50%)}:where(.scrollsheet-close:hover){background:var(--scrollsheet-close-bg-hover,#0000001a);color:var(--scrollsheet-close-color-hover,#000000bf)}:where([data-scrollsheet-theme=dark]) :where(.scrollsheet-close){background:var(--scrollsheet-close-bg,#ffffff17);color:var(--scrollsheet-close-color,#ffffff9e)}:where([data-scrollsheet-theme=dark]) :where(.scrollsheet-close:hover){background:var(--scrollsheet-close-bg-hover,#ffffff24);color:var(--scrollsheet-close-color-hover,#ffffffd9)}@media (prefers-color-scheme:dark){:where([data-scrollsheet-theme=system]) :where(.scrollsheet-close){background:var(--scrollsheet-close-bg,#ffffff17);color:var(--scrollsheet-close-color,#ffffff9e)}:where([data-scrollsheet-theme=system]) :where(.scrollsheet-close:hover){background:var(--scrollsheet-close-bg-hover,#ffffff24);color:var(--scrollsheet-close-color-hover,#ffffffd9)}}:where(.scrollsheet-close:focus-visible),:where(.scrollsheet-handle:focus-visible){box-shadow:0 0 0 2px transparent, 0 0 0 calc(2px + var(--scrollsheet-focus-ring-width,2px)) var(--scrollsheet-focus-ring,#6366f199);outline:none}.scrollsheet-dialog[data-scrollsheet-side=left] .scrollsheet-handle:before,.scrollsheet-dialog[data-scrollsheet-side=right] .scrollsheet-handle:before{width:44px;height:max(100%,44px)}.scrollsheet-dialog[data-scrollsheet-side=left] :where(.scrollsheet-handle),.scrollsheet-dialog[data-scrollsheet-side=right] :where(.scrollsheet-handle){width:5px;height:44px;margin:auto 8px}.scrollsheet-dialog[data-scrollsheet-side=left] :where(.scrollsheet-handle:active),.scrollsheet-dialog[data-scrollsheet-side=right] :where(.scrollsheet-handle:active){transform:scaleY(1.3)}@media (forced-colors:active){:where(.scrollsheet-handle){box-shadow:none;background:buttonborder}:where(.scrollsheet-handle:focus-visible){box-shadow:none;outline:2px solid highlight}:where(.scrollsheet-close){color:buttontext;box-shadow:none;background:canvas;border:1px solid buttonborder}:where(.scrollsheet-close:focus-visible){box-shadow:none;outline:2px solid highlight}}
{
"name": "scrollsheet",
"version": "1.0.0-beta.5",
"publishConfig": {
"tag": "beta"
},
"version": "1.0.0",
"description": "The bottom sheet that scrolls. Native-feeling React drawer built on <dialog> and CSS scroll-snap. Zero dependencies.",

@@ -8,0 +5,0 @@ "license": "MIT",

+21
-10

@@ -5,7 +5,9 @@ # scrollsheet

One primitive for bottom sheets, drawers, modal dialogs, side panels, and toasts. A real `<dialog>` in the top layer. The browser's own scroll engine for gestures. Spring physics compiled to CSS `linear()`. <!--size:index.gzip:1-->17.6<!--/size--> kB gzipped, <!--size:index.brotli:1-->15.7<!--/size--> kB brotli, plus a mandatory 3.8 kB stylesheet: 22.3 kB combined. React 18+.
<img src="docs/public/hero.gif" width="290" align="right" alt="A bottom sheet dragged between detents 1:1 and flick-dismissed, rendered in a native dialog">
One primitive for bottom sheets, drawers, modal dialogs, side panels, and toasts. A real `<dialog>` in the top layer. The browser's own scroll engine for gestures. Spring physics compiled to CSS `linear()`. <!--size:index.gzip:1-->17.6<!--/size--> kB gzipped, <!--size:index.brotli:1-->15.7<!--/size--> kB brotli, plus a 3.9 kB stylesheet. React 18+.
## Why another drawer
[vaul](https://github.com/emilkowalski/vaul) carried the ecosystem for two years and last shipped in December 2024. Its bug tracker tells one story over and over: pointer tracking fights the browser. scrollsheet takes the opposite bet: **don't simulate the gesture, be the scroll.**
[vaul](https://github.com/emilkowalski/vaul) is the React drawer nearly everyone ships: 37 million downloads a week. Its bug tracker tells one story over and over: pointer tracking fights the browser. scrollsheet takes the opposite bet: **don't simulate the gesture, be the scroll.**

@@ -22,3 +24,3 @@ 1. **The sheet is a native `<dialog>`.** Top layer, so no z-index wars. Focus containment, Esc, and background inerting come from the platform.

```sh
bun add scrollsheet@beta # or npm/pnpm/yarn
bun add scrollsheet # or npm/pnpm/yarn
```

@@ -57,2 +59,11 @@

### Centered dialogs
```tsx
<Sheet.Root side="center"> // a content-sized modal, zoom+fade, your CSS owns the width
<Sheet.Root desktopSide="center"> // bottom sheet on phones, that modal at 768px and up
```
Same component, same props, same focus behavior. [Guide](https://scrollsheet.dev/docs/presentation/centered-dialog), [responsive profiles](https://scrollsheet.dev/docs/presentation/responsive-profiles).
### API

@@ -62,3 +73,3 @@

| --- | --- |
| `Sheet.Root` | State owner. `open`, `onOpenChange`, `onOpenChangeComplete`, `actionsRef` (`open()` / `close()` / `snapTo(detent)`), `detents`, `activeDetent`, `onActiveDetentChange`, `dismissible`, `escapeDismissible`, `backdropDismissible`, `onTravel`, `nonce`, `side`, `modal`, `backgroundEffect`, `scrollbar`, `largestUndimmedDetent`, `handleOnly`, `disableDrag`, `sequentialDetents`, `closeThreshold`, `keyboardExpands`, `onRelease` |
| `Sheet.Root` | State owner. `open` / `onOpenChange`, `detents` / `activeDetent`, `side` (any edge or `'center'`), `desktopSide` / `desktopBreakpoint`, `modal`, the `dismissible` family, `actionsRef` (`open()` / `close()` / `snapTo(detent)`), plus travel, keyboard, and gesture tuning props |
| `Sheet.Trigger` | Button wired with `aria-haspopup` / `aria-expanded` |

@@ -78,8 +89,9 @@ | `Sheet.Content` | The `<dialog>`, backdrop, scroll track, and panel |

- **Keyboard engine.** `visualViewport`-tracked insets so the keyboard never reveals the page through a gap (the classic vaul bug). Works on every side; `keyboardExpands` promotes a peek-detent sheet to its tallest detent while the keyboard is up.
- **Desktop mouse drag**, `fill` prop, Shadow DOM injection, `themeColorDimming`, hidden scrollbars with an overlay thumb.
- **Radix Dialog drop-in.** `import { Dialog } from 'scrollsheet'` keeps @radix-ui/react-dialog JSX working against the centered presentation, `data-state` animation CSS included; radix-only props warn once in dev with the replacement recipe. [Migration guide](https://scrollsheet.dev/docs/migrating/from-radix-dialog).
- **vaul drop-in.** `import { Drawer } from 'scrollsheet'` keeps vaul's API and `data-vaul-*` attributes; props that existed to fight the page warn once in dev. [Migration guide](https://scrollsheet.dev/docs/migrating/from-vaul).
- **Toasts, no Sonner knowledge required.** `import { toast, Toaster, useToasts } from 'scrollsheet'` styles with `.scrollsheet-toast` classes and `--scrollsheet-toast-*` custom properties: `.promise()`, update-by-id, all six positions with per-toast overrides, swipe-to-dismiss with a velocity flick. Already on Sonner? Your `.sonner-toast` CSS still matches, unchanged, and `useSonner`/`toasterId` keep working. [Migration guide](https://scrollsheet.dev/docs/migrating/from-sonner).
- **Agent skills.** [`skills/`](skills/) ships `migrate-from-vaul`, `migrate-from-sonner`, and `build-with-scrollsheet` for coding agents.
- **Toasts, no Sonner knowledge required.** `import { toast, Toaster, useToasts } from 'scrollsheet'` styles with `.scrollsheet-toast` classes and `--scrollsheet-toast-*` custom properties: `.promise()`, update-by-id, all six positions with per-toast overrides, swipe-to-dismiss with a velocity flick. Already on Sonner? Your `.sonner-toast` CSS still matches, unchanged, and `useSonner`/`toasterId` keep working; fresh integrations can drop the mirrors with `sonnerCompat={false}`. [Migration guide](https://scrollsheet.dev/docs/migrating/from-sonner).
- **Smaller things.** Desktop mouse drag, the `fill` prop, Shadow DOM injection, `themeColorDimming`, hidden scrollbars with an overlay thumb.
- **Agent skills.** [`skills/`](skills/) ships `migrate-from-vaul`, `migrate-from-sonner`, `migrate-from-radix-dialog`, and `build-with-scrollsheet` for coding agents.
- **Motion core (experimental).** `scrollsheet/motion` is the React-free layer the sheet runs on: closed-form spring solver, interruptible WAAPI wrapper, scroll tween. 1.6 kB gzipped standalone.
- **Zero-config entry.** `scrollsheet/auto` embeds the stylesheet and injects it on first open: no CSS import needed, <!--size:auto.gzip:1-->21.8<!--/size--> kB gzip for `Sheet` against the default entry's <!--size:index.gzip:1-->17.6<!--/size-->.
- **Zero-config entry.** `scrollsheet/auto` embeds the stylesheet and injects it on first open: no CSS import needed, <!--size:auto.gzip:1-->21.9<!--/size--> kB gzip for `Sheet` against the default entry's <!--size:index.gzip:1-->17.6<!--/size-->.

@@ -92,3 +104,2 @@ Focus containment comes from the platform's `showModal()`, not a JS focus trap. On open, focus lands on the panel so mobile keyboards don't pop unasked; use native `autofocus` to override.

| --- | --- | --- | --- | --- |
| Maintained | yes | **no** | yes | yes |
| Runtime deps | **0** | Radix Dialog (+24 transitive) | 0 | Motion (peer) |

@@ -129,3 +140,3 @@ | Native `<dialog>` / top layer | **yes** | no | no | no |

Items: `drawer`, `sheet`, `confirm`, `share-sheet`, `sidebar`, `toast`. Each writes one file into `components/ui/` with shadcn's default styling applied, wrapping the primitives above. Swap `drawer.json` in the URL for any of them. These URLs only resolve once the repo is public.
Items: `drawer`, `sheet`, `dialog`, `confirm`, `share-sheet`, `sidebar`, `toast`. Each writes one file into `components/ui/` with shadcn's default styling applied, wrapping the primitives above. Swap `drawer.json` in the URL for any of them.

@@ -132,0 +143,0 @@ ## Roadmap

"use client";
import { c as Slot, d as useSheetContext, i as Content$1, n as Description, r as Title, s as Trigger, t as Close, u as Root$1 } from "./misc-Bf6n3Ykh.mjs";
import { t as cn } from "./cn-DgpbGWy-.mjs";
import * as React from "react";
import { Fragment, jsx } from "react/jsx-runtime";
import { createPortal } from "react-dom";
//#region packages/scrollsheet/src/handle.tsx
function detentLabel(spec) {
if (spec === "full") return "Full";
if (spec === "medium") return "Half";
if (spec === "content") return "Fit content";
if (typeof spec === "number") return `${Math.round(spec * 100)}%`;
return spec ?? "";
}
const Handle$1 = React.forwardRef(function Handle({ asChild, onClick, onKeyDown, className, variant = "inside", ...props }, ref) {
const ctx = useSheetContext("Handle");
const [mounted, setMounted] = React.useState(false);
React.useEffect(() => setMounted(true), []);
const outside = variant === "outside" && ctx.side === "bottom" && !(mounted && !ctx.canvasEl);
const variantAttr = outside ? "outside" : variant === "floating" ? "floating" : void 0;
const specs = ctx.detents;
const horizontal = ctx.side === "left" || ctx.side === "right";
const multi = specs.length >= 2;
const activeIndex = specs.findIndex((s) => Object.is(s, ctx.activeDetent));
const move = (delta) => {
if (!multi) return false;
const index = specs.findIndex((s) => Object.is(s, ctx.activeDetent));
const next = specs[index + delta];
if (next === void 0) return false;
ctx.setActiveDetent(next);
return true;
};
const sliderAria = multi ? {
role: "slider",
"aria-orientation": horizontal ? "horizontal" : "vertical",
"aria-valuemin": 0,
"aria-valuemax": specs.length - 1,
...activeIndex >= 0 ? {
"aria-valuenow": activeIndex,
"aria-valuetext": detentLabel(specs[activeIndex])
} : {}
} : {};
const button = jsx(asChild ? Slot : "button", {
...asChild ? {} : { type: "button" },
"aria-label": horizontal ? "Adjust sheet width" : "Adjust sheet height",
...sliderAria,
...props,
ref,
className: cn("scrollsheet-handle", className),
"data-scrollsheet-handle": true,
"data-scrollsheet-handle-variant": variantAttr,
onClick: (event) => {
onClick?.(event);
if (event.defaultPrevented) return;
if (!multi) return;
const index = specs.findIndex((s) => Object.is(s, ctx.activeDetent));
const next = specs[(index + 1) % specs.length];
if (next !== void 0) ctx.setActiveDetent(next);
},
onKeyDown: (event) => {
onKeyDown?.(event);
if (event.defaultPrevented) return;
const expandKey = horizontal ? "ArrowRight" : "ArrowUp";
const collapseKey = horizontal ? "ArrowLeft" : "ArrowDown";
if (event.key === expandKey) {
event.preventDefault();
move(1);
} else if (event.key === collapseKey) {
event.preventDefault();
if (!move(-1) && ctx.dismissible) ctx.setOpen(false);
} else if (multi && event.key === "Home") {
event.preventDefault();
const first = specs[0];
if (first !== void 0) ctx.setActiveDetent(first);
} else if (multi && event.key === "End") {
event.preventDefault();
const last = specs[specs.length - 1];
if (last !== void 0) ctx.setActiveDetent(last);
}
}
});
if (outside) return ctx.canvasEl ? createPortal(button, ctx.canvasEl) : null;
return button;
});
//#endregion
//#region packages/scrollsheet/src/drawer/index.tsx
const wrapperClaims = new Map();
const VAUL_CLOSE_THRESHOLD = .25;
function toDetentSpec(point) {
if (typeof point === "number") return point;
if (point === "fit-content" || point === "content") return "content";
if (/^\d+(\.\d+)?px$/.test(point)) return `${Number.parseFloat(point)}px`;
const parsed = Number.parseFloat(point);
return Number.isFinite(parsed) ? parsed : "content";
}
function resolveFadeFromIndex(snapPoints, fadeFromIndex) {
if (!snapPoints || snapPoints.length === 0) return void 0;
const point = snapPoints[fadeFromIndex ?? snapPoints.length - 1];
return point !== void 0 ? toDetentSpec(point) : void 0;
}
function resolveCloseThreshold(snapPoints, closeThreshold) {
if (snapPoints !== void 0 && snapPoints.length > 0) return void 0;
return Math.min(1, Math.max(0, 1 - (closeThreshold ?? VAUL_CLOSE_THRESHOLD)));
}
function composeOpenChange(onOpenChange, onClose) {
if (!onOpenChange && !onClose) return void 0;
return (next) => {
if (!next) onClose?.();
onOpenChange?.(next);
};
}
function Root(props) {
const { children, open, defaultOpen, onOpenChange, onClose, dismissible, snapPoints, activeSnapPoint, setActiveSnapPoint, onAnimationEnd, autoFocus, nested, direction, modal, shouldScaleBackground, setBackgroundColorOnScale, noBodyStyles, disablePreventScroll, preventScrollRestoration, repositionInputs, scrollLockTimeout, closeThreshold, fadeFromIndex, snapToSequentialPoint, handleOnly, onDrag, onRelease, container, fixed, actionsRef, backdropDismissible, escapeDismissible, keyboardExpands, onTravel, scrollbar } = props;
const detents = snapPoints && snapPoints.length > 0 ? snapPoints.map(toDetentSpec) : void 0;
const activeDetent = activeSnapPoint != null ? toDetentSpec(activeSnapPoint) : void 0;
const largestUndimmedDetent = resolveFadeFromIndex(snapPoints, fadeFromIndex);
const resolvedCloseThreshold = resolveCloseThreshold(snapPoints, closeThreshold);
const handleRelease = onRelease ? (event, willRemainOpen) => onRelease(event, willRemainOpen) : void 0;
const handleOpenChange = composeOpenChange(onOpenChange, onClose);
const handleActiveDetentChange = (detent) => {
if (!setActiveSnapPoint) return;
const match = snapPoints?.find((point) => Object.is(toDetentSpec(point), detent));
setActiveSnapPoint(match ?? detent);
};
React.useEffect(() => {
if (!shouldScaleBackground) return;
const existing = document.querySelector("[data-scrollsheet-background]");
if (existing && !wrapperClaims.has(existing)) return;
const wrapper = existing ?? document.querySelector("[data-vaul-drawer-wrapper]");
if (!wrapper) return;
const count = wrapperClaims.get(wrapper) ?? 0;
wrapperClaims.set(wrapper, count + 1);
if (count === 0) wrapper.setAttribute("data-scrollsheet-background", "");
return () => {
const remaining = (wrapperClaims.get(wrapper) ?? 1) - 1;
if (remaining <= 0) {
wrapperClaims.delete(wrapper);
wrapper.removeAttribute("data-scrollsheet-background");
} else wrapperClaims.set(wrapper, remaining);
};
}, [shouldScaleBackground]);
return jsx(DirectionContext.Provider, {
value: direction ?? "bottom",
children: jsx(Root$1, {
open,
defaultOpen,
onOpenChange: handleOpenChange,
onOpenChangeComplete: onAnimationEnd,
dismissible,
detents,
activeDetent,
onActiveDetentChange: setActiveSnapPoint ? handleActiveDetentChange : void 0,
side: direction,
modal,
backgroundEffect: shouldScaleBackground ? "scale" : "none",
largestUndimmedDetent,
handleOnly,
sequentialDetents: snapToSequentialPoint,
closeThreshold: resolvedCloseThreshold,
onRelease: handleRelease,
actionsRef,
backdropDismissible,
escapeDismissible,
keyboardExpands,
onTravel,
scrollbar,
children
})
});
}
const DirectionContext = React.createContext("bottom");
const NestedRoot = Root;
function Portal({ children, container }) {
return jsx(Fragment, { children });
}
function Overlay(_props) {
return null;
}
function hasMultipleSnapPoints(detents) {
return detents.length > 1;
}
const Content = React.forwardRef(function Content({ onPointerDownOutside, onOpenAutoFocus, onEscapeKeyDown, onCloseAutoFocus, onInteractOutside, onFocusOutside, forceMount, ...props }, ref) {
const ctx = useSheetContext("Content");
const direction = React.useContext(DirectionContext);
const snapPointsActive = hasMultipleSnapPoints(ctx.detents);
return jsx(Content$1, {
...props,
ref,
"data-vaul-drawer": "",
"data-vaul-drawer-direction": direction,
"data-vaul-snap-points": snapPointsActive ? "true" : "false"
});
});
function composeHandleClick(preventCycle, onClick) {
return (event) => {
onClick?.(event);
if (preventCycle) event.preventDefault();
};
}
const Handle = React.forwardRef(function Handle({ preventCycle, onClick, ...props }, ref) {
const ctx = useSheetContext("Handle");
return jsx(Handle$1, {
...props,
ref,
"data-vaul-handle": "",
"data-vaul-drawer-visible": ctx.open ? "true" : "false",
onClick: composeHandleClick(preventCycle, onClick)
});
});
const DrawerClose = React.forwardRef(function DrawerClose({ children, ...props }, ref) {
return jsx(Close, {
...props,
ref,
children: children ?? null
});
});
const Drawer = {
Root,
NestedRoot,
Trigger,
Portal,
Overlay,
Content,
Close: DrawerClose,
Title,
Description,
Handle
};
//#endregion
export { NestedRoot as a, Root as c, hasMultipleSnapPoints as d, resolveCloseThreshold as f, Handle as i, composeHandleClick as l, Handle$1 as m, Drawer as n, Overlay as o, resolveFadeFromIndex as p, DrawerClose as r, Portal as s, Content as t, composeOpenChange as u };

Sorry, the diff of this file is too big to display

"use client";
import { c as Slot, d as useSheetContext, i as Content$1, n as Description, r as Title, s as Trigger, t as Close, u as Root$1 } from "./misc-VkdphfSa.mjs";
import { h as warnOnce, t as cn } from "./cn-Cs7ZylHz.mjs";
import * as React from "react";
import { Fragment, jsx } from "react/jsx-runtime";
import { createPortal } from "react-dom";
//#region packages/scrollsheet/src/handle.tsx
function detentLabel(spec) {
if (spec === "full") return "Full";
if (spec === "medium") return "Half";
if (spec === "content") return "Fit content";
if (typeof spec === "number") return `${Math.round(spec * 100)}%`;
return spec ?? "";
}
const Handle$1 = React.forwardRef(function Handle({ asChild, onClick, onKeyDown, className, variant = "inside", ...props }, ref) {
const ctx = useSheetContext("Handle");
const [mounted, setMounted] = React.useState(false);
React.useEffect(() => setMounted(true), []);
const outside = variant === "outside" && ctx.side === "bottom" && !(mounted && !ctx.canvasEl);
const variantAttr = outside ? "outside" : variant === "floating" ? "floating" : void 0;
const specs = ctx.detents;
const horizontal = ctx.side === "left" || ctx.side === "right";
const multi = specs.length >= 2;
const activeIndex = specs.findIndex((s) => Object.is(s, ctx.activeDetent));
const move = (delta) => {
if (!multi) return false;
const index = specs.findIndex((s) => Object.is(s, ctx.activeDetent));
const next = specs[index + delta];
if (next === void 0) return false;
ctx.setActiveDetent(next);
return true;
};
const sliderAria = multi ? {
role: "slider",
"aria-orientation": horizontal ? "horizontal" : "vertical",
"aria-valuemin": 0,
"aria-valuemax": specs.length - 1,
...activeIndex >= 0 ? {
"aria-valuenow": activeIndex,
"aria-valuetext": detentLabel(specs[activeIndex])
} : {}
} : {};
const button = jsx(asChild ? Slot : "button", {
...asChild ? {} : { type: "button" },
"aria-label": horizontal ? "Adjust sheet width" : "Adjust sheet height",
...sliderAria,
...props,
ref,
className: cn("scrollsheet-handle", className),
"data-scrollsheet-handle": true,
"data-scrollsheet-handle-variant": variantAttr,
onClick: (event) => {
onClick?.(event);
if (event.defaultPrevented) return;
if (!multi) return;
const index = specs.findIndex((s) => Object.is(s, ctx.activeDetent));
const next = specs[(index + 1) % specs.length];
if (next !== void 0) ctx.setActiveDetent(next);
},
onKeyDown: (event) => {
onKeyDown?.(event);
if (event.defaultPrevented) return;
const expandKey = horizontal ? "ArrowRight" : "ArrowUp";
const collapseKey = horizontal ? "ArrowLeft" : "ArrowDown";
if (event.key === expandKey) {
event.preventDefault();
move(1);
} else if (event.key === collapseKey) {
event.preventDefault();
if (!move(-1) && ctx.dismissible) ctx.setOpen(false);
} else if (multi && event.key === "Home") {
event.preventDefault();
const first = specs[0];
if (first !== void 0) ctx.setActiveDetent(first);
} else if (multi && event.key === "End") {
event.preventDefault();
const last = specs[specs.length - 1];
if (last !== void 0) ctx.setActiveDetent(last);
}
}
});
if (outside) return ctx.canvasEl ? createPortal(button, ctx.canvasEl) : null;
return button;
});
//#endregion
//#region packages/scrollsheet/src/drawer/index.tsx
const wrapperClaims = new Map();
const VAUL_CLOSE_THRESHOLD = .25;
const collectIgnored = (entries) => entries.filter(([, v]) => v !== void 0).map(([k]) => k);
function toDetentSpec(point) {
if (typeof point === "number") return point;
if (point === "fit-content" || point === "content") return "content";
if (/^\d+(\.\d+)?px$/.test(point)) return `${Number.parseFloat(point)}px`;
const parsed = Number.parseFloat(point);
return Number.isFinite(parsed) ? parsed : "content";
}
function resolveFadeFromIndex(snapPoints, fadeFromIndex) {
if (!snapPoints || snapPoints.length === 0) return void 0;
const point = snapPoints[fadeFromIndex ?? snapPoints.length - 1];
return point !== void 0 ? toDetentSpec(point) : void 0;
}
function resolveCloseThreshold(snapPoints, closeThreshold) {
if (snapPoints !== void 0 && snapPoints.length > 0) return void 0;
return Math.min(1, Math.max(0, 1 - (closeThreshold ?? VAUL_CLOSE_THRESHOLD)));
}
function composeOpenChange(onOpenChange, onClose) {
if (!onOpenChange && !onClose) return void 0;
return (next) => {
if (!next) onClose?.();
onOpenChange?.(next);
};
}
function Root(props) {
const { children, open, defaultOpen, onOpenChange, onClose, dismissible, snapPoints, activeSnapPoint, setActiveSnapPoint, onAnimationEnd, autoFocus, nested, direction, modal, shouldScaleBackground, setBackgroundColorOnScale, noBodyStyles, disablePreventScroll, preventScrollRestoration, repositionInputs, scrollLockTimeout, closeThreshold, fadeFromIndex, snapToSequentialPoint, handleOnly, onDrag, onRelease, container, fixed, actionsRef, backdropDismissible, escapeDismissible, keyboardExpands, onTravel, scrollbar } = props;
{
const ignored = collectIgnored([
["setBackgroundColorOnScale", setBackgroundColorOnScale],
["noBodyStyles", noBodyStyles],
["disablePreventScroll", disablePreventScroll],
["preventScrollRestoration", preventScrollRestoration],
["repositionInputs", repositionInputs],
["scrollLockTimeout", scrollLockTimeout],
["onDrag", onDrag],
["container", container],
["fixed", fixed],
["autoFocus", autoFocus],
["nested", nested]
]);
if (ignored.length > 0) warnOnce("root-ignored-props", `[scrollsheet Drawer] These <Drawer.Root> props from vaul have no effect in this compat layer and are ignored: ${ignored.join(", ")}. See the vaul migration notes in the README.${onDrag !== void 0 ? " onDrag: the native onTravel prop works on this same <Drawer.Root>." : ""}`);
}
const detents = snapPoints && snapPoints.length > 0 ? snapPoints.map(toDetentSpec) : void 0;
const activeDetent = activeSnapPoint != null ? toDetentSpec(activeSnapPoint) : void 0;
const largestUndimmedDetent = resolveFadeFromIndex(snapPoints, fadeFromIndex);
const resolvedCloseThreshold = resolveCloseThreshold(snapPoints, closeThreshold);
if (snapPoints !== void 0 && snapPoints.length > 0 && closeThreshold !== void 0) warnOnce("close-threshold-with-snap-points", "[scrollsheet Drawer] <Drawer.Root closeThreshold> has no effect when snapPoints is set — this matches real vaul, where closeThreshold is dead code once snapPoints exist (its onRelease returns through the snap-points branch before ever reading it). Use the native Sheet.Root `closeThreshold` (a live 0-1 fraction of the first detent, works alongside detents) if you want the upgrade.");
const handleRelease = onRelease ? (event, willRemainOpen) => onRelease(event, willRemainOpen) : void 0;
const handleOpenChange = composeOpenChange(onOpenChange, onClose);
const handleActiveDetentChange = (detent) => {
if (!setActiveSnapPoint) return;
const match = snapPoints?.find((point) => Object.is(toDetentSpec(point), detent));
setActiveSnapPoint(match ?? detent);
};
React.useEffect(() => {
if (!shouldScaleBackground) return;
const existing = document.querySelector("[data-scrollsheet-background]");
if (existing && !wrapperClaims.has(existing)) return;
const wrapper = existing ?? document.querySelector("[data-vaul-drawer-wrapper]");
if (!wrapper) return;
const count = wrapperClaims.get(wrapper) ?? 0;
wrapperClaims.set(wrapper, count + 1);
if (count === 0) wrapper.setAttribute("data-scrollsheet-background", "");
return () => {
const remaining = (wrapperClaims.get(wrapper) ?? 1) - 1;
if (remaining <= 0) {
wrapperClaims.delete(wrapper);
wrapper.removeAttribute("data-scrollsheet-background");
} else wrapperClaims.set(wrapper, remaining);
};
}, [shouldScaleBackground]);
return jsx(DirectionContext.Provider, {
value: direction ?? "bottom",
children: jsx(Root$1, {
open,
defaultOpen,
onOpenChange: handleOpenChange,
onOpenChangeComplete: onAnimationEnd,
dismissible,
detents,
activeDetent,
onActiveDetentChange: setActiveSnapPoint ? handleActiveDetentChange : void 0,
side: direction,
modal,
backgroundEffect: shouldScaleBackground ? "scale" : "none",
largestUndimmedDetent,
handleOnly,
sequentialDetents: snapToSequentialPoint,
closeThreshold: resolvedCloseThreshold,
onRelease: handleRelease,
actionsRef,
backdropDismissible,
escapeDismissible,
keyboardExpands,
onTravel,
scrollbar,
children
})
});
}
const DirectionContext = React.createContext("bottom");
const NestedRoot = Root;
function Portal({ children, container }) {
if (container !== void 0) warnOnce("portal-container", "[scrollsheet Drawer] <Drawer.Portal container> has no effect — scrollsheet's <dialog> always renders into the browser's top layer (effectively document.body), so there's no separate container to portal into.");
return jsx(Fragment, { children });
}
function Overlay(_props) {
return null;
}
function hasMultipleSnapPoints(detents) {
return detents.length > 1;
}
const Content = React.forwardRef(function Content({ onPointerDownOutside, onOpenAutoFocus, onEscapeKeyDown, onCloseAutoFocus, onInteractOutside, onFocusOutside, forceMount, ...props }, ref) {
const ctx = useSheetContext("Content");
const direction = React.useContext(DirectionContext);
const snapPointsActive = hasMultipleSnapPoints(ctx.detents);
{
const ignored = collectIgnored([
["onPointerDownOutside", onPointerDownOutside],
["onOpenAutoFocus", onOpenAutoFocus],
["onEscapeKeyDown", onEscapeKeyDown],
["onCloseAutoFocus", onCloseAutoFocus],
["onInteractOutside", onInteractOutside],
["onFocusOutside", onFocusOutside],
["forceMount", forceMount]
]);
if (ignored.length > 0) warnOnce("content-ignored-props", `[scrollsheet Drawer] These <Drawer.Content> props from vaul have no effect in this compat layer and are stripped before reaching the DOM: ${ignored.join(", ")}. See the vaul migration notes in the README.${onPointerDownOutside !== void 0 || onInteractOutside !== void 0 || onEscapeKeyDown !== void 0 ? " To block backdrop-tap dismissal, set backdropDismissible={false} on <Drawer.Root>; to block Esc, escapeDismissible={false}." : ""}`);
}
return jsx(Content$1, {
...props,
ref,
"data-vaul-drawer": "",
"data-vaul-drawer-direction": direction,
"data-vaul-snap-points": snapPointsActive ? "true" : "false"
});
});
function composeHandleClick(preventCycle, onClick) {
return (event) => {
onClick?.(event);
if (preventCycle) event.preventDefault();
};
}
const Handle = React.forwardRef(function Handle({ preventCycle, onClick, ...props }, ref) {
const ctx = useSheetContext("Handle");
return jsx(Handle$1, {
...props,
ref,
"data-vaul-handle": "",
"data-vaul-drawer-visible": ctx.open ? "true" : "false",
onClick: composeHandleClick(preventCycle, onClick)
});
});
const DrawerClose = React.forwardRef(function DrawerClose({ children, ...props }, ref) {
return jsx(Close, {
...props,
ref,
children: children ?? null
});
});
const Drawer = {
Root,
NestedRoot,
Trigger,
Portal,
Overlay,
Content,
Close: DrawerClose,
Title,
Description,
Handle
};
//#endregion
export { NestedRoot as a, Root as c, hasMultipleSnapPoints as d, resolveCloseThreshold as f, Handle as i, composeHandleClick as l, Handle$1 as m, Drawer as n, Overlay as o, resolveFadeFromIndex as p, DrawerClose as r, Portal as s, Content as t, composeOpenChange as u };

Sorry, the diff of this file is too big to display