@svnrnns/react-bottom-sheets 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +184 -0
- package/dist/api.d.ts +9 -0
- package/dist/components/BottomSheet.d.ts +12 -0
- package/dist/components/BottomSheetScrollable.d.ts +13 -0
- package/dist/context/context.d.ts +21 -0
- package/dist/context/scrollContext.d.ts +19 -0
- package/dist/hooks/useFocusTrap.d.ts +3 -0
- package/dist/index.cjs +2 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.ts +6 -0
- package/dist/index.js +727 -0
- package/dist/index.js.map +1 -0
- package/dist/store/store.d.ts +19 -0
- package/dist/styles.css +1 -0
- package/dist/types.d.ts +47 -0
- package/dist/utils/gestures.d.ts +24 -0
- package/dist/utils/snap.d.ts +16 -0
- package/package.json +43 -0
package/README.md
ADDED
|
@@ -0,0 +1,184 @@
|
|
|
1
|
+
# @svnrnns/react-bottom-sheets
|
|
2
|
+
|
|
3
|
+
Imperative bottom sheets for React: open and close sheets via API, with gestures, snap points, and stacking. Compatible with React 18+ and Next.js.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm install @svnrnns/react-bottom-sheets
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Setup
|
|
12
|
+
|
|
13
|
+
Wrap your app with `BottomSheetRoot` (e.g. in `_app.tsx` or the root layout):
|
|
14
|
+
|
|
15
|
+
```tsx
|
|
16
|
+
import { BottomSheetRoot } from "@svnrnns/react-bottom-sheets";
|
|
17
|
+
import "@svnrnns/react-bottom-sheets/styles.css";
|
|
18
|
+
|
|
19
|
+
export default function App({ Component, pageProps }) {
|
|
20
|
+
return (
|
|
21
|
+
<BottomSheetRoot>
|
|
22
|
+
<Component {...pageProps} />
|
|
23
|
+
</BottomSheetRoot>
|
|
24
|
+
);
|
|
25
|
+
}
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
**`BottomSheetRoot` props:**
|
|
29
|
+
|
|
30
|
+
| Prop | Type | Description |
|
|
31
|
+
| ------- | -------- | ------------------------------------------------------------------------------------------------------------------ |
|
|
32
|
+
| `width` | `string` | Default width for all bottom sheets (e.g. `'50%'`, `'20rem'`, `'400px'`). When set, sheets are centered. Optional. |
|
|
33
|
+
|
|
34
|
+
## Usage
|
|
35
|
+
|
|
36
|
+
### Opening a bottom sheet
|
|
37
|
+
|
|
38
|
+
```tsx
|
|
39
|
+
import { pushBottomSheet } from "@svnrnns/react-bottom-sheets";
|
|
40
|
+
|
|
41
|
+
function MyContent({ title, closeDrawer, snapToIndex }) {
|
|
42
|
+
return (
|
|
43
|
+
<div>
|
|
44
|
+
<h2>{title}</h2>
|
|
45
|
+
<button onClick={() => snapToIndex(0)}>Half</button>
|
|
46
|
+
<button onClick={() => snapToIndex(1)}>Full</button>
|
|
47
|
+
<button onClick={closeDrawer}>Close</button>
|
|
48
|
+
</div>
|
|
49
|
+
);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
const instance = pushBottomSheet({
|
|
53
|
+
component: MyContent,
|
|
54
|
+
props: { title: "Hello" },
|
|
55
|
+
enableBackdrop: true,
|
|
56
|
+
enableClickBackdropToClose: true,
|
|
57
|
+
snapPoint: ["50%", "100%"],
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
instance.close();
|
|
61
|
+
instance.snapToIndex(1);
|
|
62
|
+
instance.openFully();
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
### API
|
|
66
|
+
|
|
67
|
+
- **`pushBottomSheet<T>(options)`** — Opens a new bottom sheet. Returns `BottomSheetInstance`.
|
|
68
|
+
- `options.component` — React component to render inside the sheet.
|
|
69
|
+
- `options.props` — Props passed to the component (type-inferred).
|
|
70
|
+
- `options.height` — Optional fixed height (number in px, or string e.g. `"50%"`, `"20rem"`).
|
|
71
|
+
- `options.width` — Optional width in any CSS unit (`%`, `rem`, `px`, `vw`, etc.). When set, the sheet is centered. Overrides `BottomSheetRoot` default width for this sheet.
|
|
72
|
+
- `options.snapPoint` — Optional array of snap points (e.g. `['25%', '50%', '100%']`). Percent is relative to viewport height; also supports `'200px'`, `'10rem'`. Alias: `snapPoints`.
|
|
73
|
+
- `options.className` — Optional class for the sheet wrapper.
|
|
74
|
+
- `options.onClose` — Callback when the sheet is closed.
|
|
75
|
+
- `options.enableClickBackdropToClose` — If `true`, clicking the backdrop closes the sheet.
|
|
76
|
+
- `options.enableBackdrop` — If `true`, shows an overlay behind the sheet.
|
|
77
|
+
- `options.disableEsc` — If `true`, Escape key does not close this sheet.
|
|
78
|
+
- `options.gestureOnlyOnHandler` — If `true`, only the handler bar is draggable; otherwise the whole sheet is.
|
|
79
|
+
- `options.disableSwipeDownToClose` — If `true`, swipe-down never closes the sheet; it always snaps back to the first snap point or open position.
|
|
80
|
+
|
|
81
|
+
- **`BottomSheetInstance`** (returned by `pushBottomSheet`):
|
|
82
|
+
- `id` — Unique id (symbol). Use with `closeBottomSheet(id)` to close a specific sheet.
|
|
83
|
+
- `close()` — Closes this sheet.
|
|
84
|
+
- `snapToIndex(index)` — Moves the sheet to the given snap point index (0-based).
|
|
85
|
+
- `openFully()` — Opens to the highest snap point (or full height if no snaps). Calls to `snapToIndex` and `openFully` before the sheet is mounted are queued and applied when ready.
|
|
86
|
+
|
|
87
|
+
- **`popBottomSheet()`** — Closes the topmost sheet.
|
|
88
|
+
|
|
89
|
+
- **`closeBottomSheet(id)`** — Closes the sheet with the given `id`.
|
|
90
|
+
|
|
91
|
+
- **`closeAllBottomSheets()`** — Closes all open sheets.
|
|
92
|
+
|
|
93
|
+
### Injected props
|
|
94
|
+
|
|
95
|
+
Every component rendered inside a bottom sheet receives:
|
|
96
|
+
|
|
97
|
+
- **`closeDrawer()`** — Closes this sheet.
|
|
98
|
+
- **`snapToIndex(index: number)`** — Snaps this sheet to the given index.
|
|
99
|
+
|
|
100
|
+
### Scrollable content (`BottomSheetScrollable`)
|
|
101
|
+
|
|
102
|
+
When the sheet content is scrollable, vertical drags can conflict with sheet gestures. Use `BottomSheetScrollable` so scroll and gestures cooperate:
|
|
103
|
+
|
|
104
|
+
- **Scroll not at top (`scrollTop > 0`):** Vertical drags scroll the content only; sheet gestures are disabled.
|
|
105
|
+
- **Scroll at top (`scrollTop === 0`):** Swipe down activates sheet gestures (close or pan); swipe up scrolls the content.
|
|
106
|
+
|
|
107
|
+
```tsx
|
|
108
|
+
import { pushBottomSheet, BottomSheetScrollable } from "@svnrnns/react-bottom-sheets";
|
|
109
|
+
|
|
110
|
+
function MyContent({ closeDrawer }) {
|
|
111
|
+
return (
|
|
112
|
+
<div style={{ display: "flex", flexDirection: "column", height: "100%" }}>
|
|
113
|
+
<h2>Header</h2>
|
|
114
|
+
<BottomSheetScrollable>
|
|
115
|
+
<p>Long scrollable content...</p>
|
|
116
|
+
</BottomSheetScrollable>
|
|
117
|
+
</div>
|
|
118
|
+
);
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
pushBottomSheet({
|
|
122
|
+
component: MyContent,
|
|
123
|
+
snapPoint: ["50%", "100%"],
|
|
124
|
+
enableBackdrop: true,
|
|
125
|
+
});
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
`BottomSheetScrollable` supports `className` and `style` props. It must be used inside a bottom sheet; outside it behaves as a normal scroll container.
|
|
129
|
+
|
|
130
|
+
## CSS variables
|
|
131
|
+
|
|
132
|
+
Override these in your app (e.g. in `:root` or a wrapper) to customize styles:
|
|
133
|
+
|
|
134
|
+
| Variable | Default | Description |
|
|
135
|
+
| -------------------------------------- | ------------------------------------- | ------------------------------------- |
|
|
136
|
+
| `--bottom-sheet-bg` | `#fff` | Sheet background |
|
|
137
|
+
| `--bottom-sheet-padding` | `1rem` | Inner padding |
|
|
138
|
+
| `--bottom-sheet-border-radius` | `12px 12px 0 0` | Sheet corners |
|
|
139
|
+
| `--bottom-sheet-shadow` | `0 25px 50px -12px rgb(0 0 0 / 0.25)` | Box shadow |
|
|
140
|
+
| `--bottom-sheet-overlay-bg` | `rgba(0, 0, 0, 0.3)` | Backdrop color |
|
|
141
|
+
| `--bottom-sheet-overlay-blur-filter` | `blur(8px)` | Backdrop blur |
|
|
142
|
+
| `--bottom-sheet-duration` | `0.5s` | Duration for programmatic animations |
|
|
143
|
+
| `--bottom-sheet-easing` | `cubic-bezier(0.32, 0.72, 0, 1)` | Easing for programmatic animations |
|
|
144
|
+
| `--bottom-sheet-handler-bg` | `#cbd5e1` | Handler bar color |
|
|
145
|
+
| `--bottom-sheet-handler-width` | `40px` | Handler bar width |
|
|
146
|
+
| `--bottom-sheet-handler-height` | `4px` | Handler bar height |
|
|
147
|
+
| `--bottom-sheet-handler-border-radius` | `2px` | Handler bar radius |
|
|
148
|
+
| `--bottom-sheet-handler-padding` | `0.5rem` | Handler padding |
|
|
149
|
+
| `--bottom-sheet-gap` | `0.5rem` | Gap between handler and content |
|
|
150
|
+
| `--bottom-sheet-close-extra-offset` | `0` | Extra offset when animating to closed |
|
|
151
|
+
| `--bottom-sheet-stack-overlay-bg` | `rgba(0, 0, 0, 0.5)` | Overlay on non-top stacked sheets |
|
|
152
|
+
|
|
153
|
+
Example:
|
|
154
|
+
|
|
155
|
+
```css
|
|
156
|
+
:root {
|
|
157
|
+
--bottom-sheet-bg: #1e293b;
|
|
158
|
+
--bottom-sheet-handler-bg: #64748b;
|
|
159
|
+
--bottom-sheet-duration: 0.3s;
|
|
160
|
+
}
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
## Behavior
|
|
164
|
+
|
|
165
|
+
- Sheets open from the bottom and are rendered in a portal above the rest of the page.
|
|
166
|
+
- **Stacking:** Multiple sheets can be open at once. When a new sheet is pushed, all sheets behind it (non-top) get scaled to 90%, translated up by 10%, and display an overlay. Customize the overlay via `--bottom-sheet-stack-overlay-bg`. Only the topmost sheet receives backdrop click (when `enableClickBackdropToClose` is true) and Escape. `popBottomSheet()` closes the top sheet; `closeBottomSheet(id)` closes a specific one.
|
|
167
|
+
- Height is content-based (max 100vh) unless `height` is set. Snap points can be `%`, `px`, or `rem`.
|
|
168
|
+
- Drag with mouse or touch: the sheet follows in real time (no animation during drag). On release, it snaps or closes using the configured duration and easing.
|
|
169
|
+
- Fast swipe down can close the sheet; past 60% travel toward closed also allows close. Use `disableSwipeDownToClose: true` to prevent swipe-to-close. Between snap points, 50% progress decides the target snap.
|
|
170
|
+
- Rubberband effect when dragging beyond min/max (unless moving to another snap point).
|
|
171
|
+
- Escape closes the top sheet (including while dragging). Each sheet can disable this with `disableEsc`.
|
|
172
|
+
|
|
173
|
+
### Accessibility (focus trap)
|
|
174
|
+
|
|
175
|
+
When a bottom sheet is pushed and becomes the top sheet, focus is trapped inside it: Tab/Shift+Tab cycle only through focusable elements within the sheet, and focus is restored to the previously focused element when the sheet closes. The first focusable element is focused when the sheet opens. To avoid auto-focus on a close button, add the class `modals-close` to that button; the trap will then focus the first other focusable element (or the sheet container if none). The top sheet is exposed as a dialog (`role="dialog"`, `aria-modal="true"`) for screen readers.
|
|
176
|
+
|
|
177
|
+
## TypeScript
|
|
178
|
+
|
|
179
|
+
The package exports these types:
|
|
180
|
+
|
|
181
|
+
- `BottomSheetInstance` — Return type of `pushBottomSheet`.
|
|
182
|
+
- `PushOptions<T>` — Options for `pushBottomSheet`; `T` is the props type of your content component.
|
|
183
|
+
- `BottomSheetInjectedProps` — Props injected into the content component (`closeDrawer`, `snapToIndex`).
|
|
184
|
+
- `BottomSheetRootProps` — Props for `BottomSheetRoot` (`width`).
|
package/dist/api.d.ts
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { PushOptions, BottomSheetInstance } from './types';
|
|
2
|
+
import { BottomSheetRoot } from './context/context';
|
|
3
|
+
|
|
4
|
+
export { BottomSheetRoot };
|
|
5
|
+
export type { BottomSheetRootProps } from './context/context';
|
|
6
|
+
export declare function pushBottomSheet<T = Record<string, unknown>>(options: PushOptions<T>): BottomSheetInstance;
|
|
7
|
+
export declare function popBottomSheet(): void;
|
|
8
|
+
export declare function closeBottomSheet(id: string | symbol): void;
|
|
9
|
+
export declare function closeAllBottomSheets(): void;
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { SheetDescriptor } from '../types';
|
|
2
|
+
|
|
3
|
+
export interface BottomSheetProps {
|
|
4
|
+
descriptor: SheetDescriptor & {
|
|
5
|
+
id: symbol;
|
|
6
|
+
};
|
|
7
|
+
index: number;
|
|
8
|
+
isTop: boolean;
|
|
9
|
+
/** 0 = top sheet, 1 = first behind, 2 = second behind, etc. */
|
|
10
|
+
stackDepth: number;
|
|
11
|
+
}
|
|
12
|
+
export declare function BottomSheet({ descriptor, index, isTop, stackDepth }: BottomSheetProps): import("react/jsx-runtime").JSX.Element;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { CSSProperties } from 'react';
|
|
2
|
+
|
|
3
|
+
export interface BottomSheetScrollableProps {
|
|
4
|
+
children: React.ReactNode;
|
|
5
|
+
className?: string;
|
|
6
|
+
style?: CSSProperties;
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* A scrollable container that coordinates with BottomSheet gestures.
|
|
10
|
+
* - When scrollTop > 0: vertical drags scroll the content (sheet gestures disabled)
|
|
11
|
+
* - When scrollTop === 0: swipe down activates sheet gestures (close/pan), swipe up scrolls
|
|
12
|
+
*/
|
|
13
|
+
export declare function BottomSheetScrollable({ children, className, style }: BottomSheetScrollableProps): import("react/jsx-runtime").JSX.Element;
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
export declare const BottomSheetContext: import('react').Context<{
|
|
2
|
+
registerController: (id: symbol | string, ctrl: {
|
|
3
|
+
snapToIndex: (i: number) => void;
|
|
4
|
+
openFully: () => void;
|
|
5
|
+
close: () => void;
|
|
6
|
+
}) => void;
|
|
7
|
+
unregisterController: (id: symbol | string) => void;
|
|
8
|
+
defaultWidth?: string | number;
|
|
9
|
+
setOverlayStyle: (style: {
|
|
10
|
+
opacity: number;
|
|
11
|
+
transition: string;
|
|
12
|
+
pointerEvents: "auto" | "none";
|
|
13
|
+
}) => void;
|
|
14
|
+
topSheetClosingProgress: number | null;
|
|
15
|
+
setTopSheetClosingProgress: (progress: number | null) => void;
|
|
16
|
+
} | null>;
|
|
17
|
+
export interface BottomSheetRootProps {
|
|
18
|
+
/** Default width for all bottom sheets (e.g. '50%', '20rem', 400). Number = px. When set, sheets are centered. */
|
|
19
|
+
width?: string | number;
|
|
20
|
+
}
|
|
21
|
+
export declare function BottomSheetRoot({ width }?: BottomSheetRootProps): import("react/jsx-runtime").JSX.Element | null;
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
export interface ScrollContainerContextValue {
|
|
2
|
+
/** Register a scroll container. Returns unregister function. */
|
|
3
|
+
registerScrollContainer: (el: HTMLElement, getCanDrag: () => boolean) => () => void;
|
|
4
|
+
/** True if target is inside any registered scroll container. */
|
|
5
|
+
isInScrollContainer: (target: Node) => boolean;
|
|
6
|
+
/**
|
|
7
|
+
* Returns true if sheet gestures should be blocked for this target.
|
|
8
|
+
* (e.g. when inside a scrollable that is not at top)
|
|
9
|
+
*/
|
|
10
|
+
shouldBlockGestures: (target: Node) => boolean;
|
|
11
|
+
/**
|
|
12
|
+
* For targets inside a scroll container at top: can we capture for a downward swipe?
|
|
13
|
+
* (scrollTop === 0)
|
|
14
|
+
*/
|
|
15
|
+
canCaptureForDownSwipe: (target: Node) => boolean;
|
|
16
|
+
}
|
|
17
|
+
export declare const ScrollContainerContext: import('react').Context<ScrollContainerContextValue | null>;
|
|
18
|
+
export declare function useScrollContainerContext(): ScrollContainerContextValue | null;
|
|
19
|
+
export declare function useScrollContainerContextValue(): ScrollContainerContextValue;
|
package/dist/index.cjs
ADDED
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const E=require("react/jsx-runtime"),i=require("react"),Ue=require("react-dom");let lt=0;function ft(){return Symbol(`bottom-sheet-${++lt}`)}let K=[];const Se=new Set;function xe(){Se.forEach(e=>e())}function ve(){return K}function dt(e){return Se.add(e),()=>Se.delete(e)}function ht(e){const t=ft(),n={...e,id:t};return K=[...K,n],xe(),t}function V(e){K=K.filter(t=>t.id!==e),xe()}function mt(){K=[],xe()}const ne=new Map,Ce=new Map,ye=new Set;function gt(e,t){ne.set(e,t);const n=Ce.get(e);n!==void 0&&(Ce.delete(e),t.snapToIndex(n)),ye.has(e)&&(ye.delete(e),t.openFully())}function pt(e){ne.delete(e)}function bt(e){return ne.get(e)}function St(e,t){const n=ne.get(e);n?n.snapToIndex(t):Ce.set(e,t)}function vt(e){const t=ne.get(e);t?t.openFully():ye.add(e)}function Ct(e,t,n){const o=e.trim();if(!o)return null;if(o.endsWith("%")){const s=parseFloat(o.slice(0,-1));return Number.isNaN(s)||s<0||s>100?null:s/100*t}if(o.endsWith("px")){const s=parseFloat(o.slice(0,-2));return Number.isNaN(s)?null:s}if(o.endsWith("rem")){const s=parseFloat(o.slice(0,-3));return Number.isNaN(s)?null:s*n}const r=parseFloat(o);return Number.isNaN(r)?null:r}function yt(){if(typeof document>"u")return 16;const e=document.documentElement,t=getComputedStyle(e).fontSize,n=parseFloat(t);return Number.isNaN(n)?16:n}function wt(e,t){if(!(e!=null&&e.length))return[];const n=yt(),o=e.map(s=>Ct(s,t,n)).filter(s=>s!==null&&s>=0),r=[...new Set(o)];return r.sort((s,a)=>s-a),r}const xt=80,Et=.35,He=.08;function je(e){return He+(Et-He)/(1+e/xt)}function pe(e,t,n){if(e>=t&&e<=n)return e;if(e<t){const s=t-e,a=je(s);return t-s*a}const o=e-n,r=je(o);return n+o*r}const _e=.5,We=.6,Tt=.5;function Rt(e,t,n,o,r=0){const s=t+r;if(n.length===0)return e>=s*We?{action:"close"}:{action:"snap",targetY:0};const a=[...n].sort((C,H)=>C-H),g=a[0],h=t-g,y=t+r,d=h,T=y-d,v=d+We*T;if(o>_e){if(e>=v)return{action:"close"};const C=Pt(e,a,t);if(C!==void 0)return{action:"snap",targetY:t-C,targetIndex:n.indexOf(C)}}if(o<-_e){const C=Bt(e,a,t);if(C!==void 0){const H=t-C,re=a.indexOf(C);return{action:"snap",targetY:H,targetIndex:re}}}const B=kt(e,a,t);if(Ft(e,B,a,t)>=Tt&&B<a.length-1){const C=a[B+1];return{action:"snap",targetY:t-C,targetIndex:B+1}}if(B>0||e<d){const C=a[B];return{action:"snap",targetY:t-C,targetIndex:B}}return e>=v?{action:"close"}:{action:"snap",targetY:h,targetIndex:0}}function Pt(e,t,n){const o=n-e;for(let r=t.length-1;r>=0;r--)if(t[r]<o)return t[r]}function Bt(e,t,n){const o=n-e;for(let r=0;r<t.length;r++)if(t[r]>o)return t[r]}function kt(e,t,n){const o=n-e;let r=0,s=1/0;for(let a=0;a<t.length;a++){const g=Math.abs(t[a]-o);g<s&&(s=g,r=a)}return r}function Ft(e,t,n,o){if(t>=n.length-1)return 0;const r=o-e,s=n[t],g=n[t+1]-s;if(g<=0)return 0;const h=(r-s)/g;return Math.max(0,Math.min(1,h))}const Ge=i.createContext(null);function Ot(){return i.useContext(Ge)}function be(e,t){let n=e;for(;n&&n!==document.body;){if(n instanceof HTMLElement&&t.has(n))return{el:n,getCanDrag:t.get(n)};n=n.parentNode}return null}function Dt(){const e=i.useRef(new Map),t=i.useCallback((s,a)=>(e.current.set(s,a),()=>{e.current.delete(s)}),[]),n=i.useCallback(s=>be(s,e.current)!==null,[]),o=i.useCallback(s=>{const a=be(s,e.current);return a?!a.getCanDrag():!1},[]),r=i.useCallback(s=>{const a=be(s,e.current);return a?a.getCanDrag():!1},[]);return{registerScrollContainer:t,isInScrollContainer:n,shouldBlockGestures:o,canCaptureForDownSwipe:r}}const Nt='button, [href], input, select, textarea, [tabindex]:not([tabindex="-1"])',Mt="modals-close";function we(e){return Array.from(e.querySelectorAll(Nt))}function It(e){return we(e).filter(t=>!t.classList.contains(Mt))}function Yt(e,t,n=!1){i.useEffect(()=>{if(!t||!e.current)return;const o=e.current,r=document.activeElement;if(!n){const a=It(o),g=we(o),h=a[0]??g[0];h?h.focus():(o.setAttribute("tabindex","-1"),o.focus())}function s(a){if(a.key!=="Tab")return;const g=we(o),h=g[0],y=g[g.length-1];a.shiftKey?document.activeElement===h&&y&&(a.preventDefault(),y.focus()):document.activeElement===y&&h&&(a.preventDefault(),h.focus())}return o.addEventListener("keydown",s),()=>{o.removeEventListener("keydown",s),r&&typeof r.focus=="function"&&r.focus()}},[t,n])}const Lt=typeof window<"u"?()=>window.innerHeight:()=>800,At=5;function ae(e,t){return typeof document>"u"?t:getComputedStyle(document.documentElement).getPropertyValue(e).trim()||t}function $(){const e=ae("--bottom-sheet-duration","0.5s"),t=e.match(/^([\d.]+)s$/);if(t)return parseFloat(t[1])*1e3;const n=e.match(/^([\d.]+)ms$/);return n?parseFloat(n[1]):500}function $t(e,t,n){const o=1-e;return 3*o*o*e*t+3*o*e*e*n+e*e*e}function Ht(e,t){const n=t.match(/cubic-bezier\s*\(\s*([\d.]+)\s*,\s*([\d.]+)\s*,\s*([\d.]+)\s*,\s*([\d.]+)\s*\)/);if(!n)return e;const o=n.map(Number),r=o[2],s=o[4];return $t(e,r,s)}function ze(e){return e===0?1:Math.max(.5,.9-(e-1)*.05)}function qe(e){return e===0?0:12+(e-1)*8}function jt({descriptor:e,index:t,isTop:n,stackDepth:o}){const r=i.useContext(Xe),{id:s,component:a,props:g,height:h,width:y,snapPoint:d,className:T,onClose:v,enableBackdrop:B,enableClickBackdropToClose:ue,disableEsc:C,gestureOnlyOnHandler:H,disableSwipeDownToClose:re}=e,oe=y??(r==null?void 0:r.defaultWidth),Ee=oe==null?void 0:typeof oe=="number"?`${oe}px`:oe,M=Lt(),D=typeof document<"u"&&parseFloat(ae("--bottom-sheet-close-extra-offset","0"))||0,Ke=!!(d!=null&&d.length),N=h==null&&!Ke,j=i.useRef(null),se=i.useRef(null),_=i.useRef(null),W=Dt(),[m,Z]=i.useState(()=>h!=null?Ve(h):N?0:M),[Te,Re]=i.useState(!N),ce=m+D,b=wt(d,M).filter(c=>c<=m).sort((c,l)=>c-l),J=b.length>0?m-b[0]:0,[z,k]=i.useState(()=>N?M:b.length>0?ce:0),[U,q]=i.useState(!1),[ie,p]=i.useState(!1),[le,Ze]=i.useState(!1),[Je,fe]=i.useState(0),F=i.useRef(null),I=i.useRef(null),P=i.useRef(!1),Y=i.useRef(null);i.useLayoutEffect(()=>{b.length>0&&k(ce)},[]),i.useEffect(()=>{var w;if(h!=null){Z(Ve(h)),Re(!0);return}if(!N){const S=_.current;if(!S)return;const R=new ResizeObserver(()=>{const O=S.getBoundingClientRect().height;Z(A=>Math.min(Math.max(A,O),M))});R.observe(S);const x=S.getBoundingClientRect().height;return Z(O=>Math.min(Math.max(O,x),M)),()=>R.disconnect()}if(!j.current)return;const l=()=>{const S=j.current,R=se.current,x=_.current;if(!S||!R||!x)return;if(m===0){const $e=Math.min(S.getBoundingClientRect().height,M);$e>0&&(Z($e),Re(!0));return}const O=getComputedStyle(S),A=parseFloat(O.paddingTop)||0,ge=parseFloat(O.paddingBottom)||0,X=O.gap||"0.5rem",at=X.endsWith("rem")?parseFloat(X)*(parseFloat(getComputedStyle(document.documentElement).fontSize)||16):parseFloat(X)||8,Le=x.firstElementChild,ut=Le?Le.getBoundingClientRect().height:x.scrollHeight||x.getBoundingClientRect().height,Ae=Math.min(A+ge+R.offsetHeight+at+ut,M);Ae>0&&(Y.current&&(clearTimeout(Y.current),Y.current=null),Z(Ae),p(!0),Y.current=setTimeout(()=>{Y.current=null,p(!1)},$()))},f=new ResizeObserver(l);_.current&&f.observe(_.current);const u=(w=_.current)==null?void 0:w.firstElementChild;return u&&f.observe(u),se.current&&f.observe(se.current),f.observe(j.current),requestAnimationFrame(l),()=>{f.disconnect(),Y.current&&(clearTimeout(Y.current),Y.current=null)}},[h,M,N,m]),i.useEffect(()=>{le||N&&!Te||(Ze(!0),k(ce),requestAnimationFrame(()=>{fe(1),p(!0),k(J);const c=$();setTimeout(()=>p(!1),c)}))},[le,N,Te,J,ce,m]);const Q=i.useCallback(()=>{if(ie)return;fe(0),p(!0);const c=$();if(k(m+D),n&&r){r.setTopSheetClosingProgress(0);const l=Date.now(),f=()=>{const u=Date.now()-l,w=Math.min(1,u/c);r==null||r.setTopSheetClosingProgress(w),w<1?requestAnimationFrame(f):(v==null||v(),V(s),r==null||r.setTopSheetClosingProgress(null),p(!1))};requestAnimationFrame(f)}else{const l=setTimeout(()=>{v==null||v(),V(s),p(!1)},c);return()=>clearTimeout(l)}},[s,m,D,v,ie,n,r]),ee=i.useCallback(c=>{if(ie)return;if(b.length===0){k(0);return}const l=Math.max(0,Math.min(c,b.length-1)),f=m-b[l];p(!0),k(f);const u=$(),w=setTimeout(()=>p(!1),u);return()=>clearTimeout(w)},[b,m,ie]),Pe=i.useCallback(()=>{if(b.length>0)ee(b.length-1);else{p(!0),k(0);const c=setTimeout(()=>p(!1),$());return()=>clearTimeout(c)}},[b.length,ee]);i.useLayoutEffect(()=>{if(r)return r.registerController(s,{snapToIndex:ee,openFully:Pe,close:Q}),()=>r.unregisterController(s)},[s,r,ee,Pe,Q]),i.useEffect(()=>{if(!n)return;const c=l=>{l.key==="Escape"&&!C&&(l.preventDefault(),Ue.flushSync(()=>{q(!1),p(!1)}),F.current=null,I.current=null,Q())};return window.addEventListener("keydown",c),()=>window.removeEventListener("keydown",c)},[n,C,Q]),Yt(j,n&&le);const Be=i.useCallback(c=>{if(P.current&&j.current&&c!=null){try{j.current.releasePointerCapture(c)}catch{}q(!1)}F.current=null,I.current=null,P.current=!1},[]),Qe=i.useCallback(c=>{var u;if(c.button!==0)return;const l=c.pointerType==="touch",f=((u=_.current)==null?void 0:u.contains(c.target))??!1;if(l&&f){if(W.isInScrollContainer(c.target))return;c.currentTarget.setPointerCapture(c.pointerId),P.current=!0,q(!0)}},[W]),et=i.useCallback(c=>{if(c.button!==0)return;const l=c.pointerId;F.current={y:c.clientY,sheetY:z,time:Date.now()},I.current={y:c.clientY,time:Date.now()};const f=u=>{u.pointerId===l&&(window.removeEventListener("pointerup",f),window.removeEventListener("pointercancel",f),Be(l))};window.addEventListener("pointerup",f),window.addEventListener("pointercancel",f)},[z,Be]),tt=i.useCallback(c=>{if(!F.current)return;if(c.buttons===0){P.current&&(c.currentTarget.releasePointerCapture(c.pointerId),q(!1)),F.current=null,I.current=null,P.current=!1;return}I.current={y:c.clientY,time:Date.now()};const l=c.clientY-F.current.y,f=c.pointerType==="touch"?1:At;if(!P.current&&Math.abs(l)>f){const R=c.target;if(W.isInScrollContainer(R)){if(W.shouldBlockGestures(R)||!W.canCaptureForDownSwipe(R)||l<=0)return;c.preventDefault()}c.currentTarget.setPointerCapture(c.pointerId),P.current=!0,q(!0)}if(!P.current)return;let u=F.current.sheetY+l;const w=0,S=m+D;if(b.length>0){const R=Math.max(...b),x=m-R;u>S||u<x?u=pe(u,x,S):u=Math.max(x,Math.min(S,u))}else u>S||u<w?u=pe(u,w,S):u=Math.max(w,Math.min(S,u));k(u)},[m,D,b,W]),nt=i.useCallback(c=>{if(!F.current)return;const l=P.current;l&&(c.currentTarget.releasePointerCapture(c.pointerId),q(!1));const f=I.current,u=f&&f.time!==F.current.time?(c.clientY-f.y)/(Date.now()-f.time):0;if(F.current=null,I.current=null,P.current=!1,!l)return;const w=Rt(z,m,b,u,D);if(w.action==="close"){if(re){const O=b.length>0?m-b[0]:0;p(!0),k(O);const A=$();setTimeout(()=>p(!1),A);return}fe(0),p(!0),k(m+D);const x=$();if(n&&r){r.setTopSheetClosingProgress(0);const O=Date.now(),A=()=>{const ge=Date.now()-O,X=Math.min(1,ge/x);r==null||r.setTopSheetClosingProgress(X),X<1?requestAnimationFrame(A):(v==null||v(),V(s),r==null||r.setTopSheetClosingProgress(null),p(!1))};requestAnimationFrame(A)}else setTimeout(()=>{v==null||v(),V(s),p(!1)},x);return}const S=w.targetY??0;p(!0),k(S);const R=$();setTimeout(()=>p(!1),R)},[z,m,b,D,s,v,re,n,r]),rt=i.useCallback(c=>{P.current&&(c.currentTarget.releasePointerCapture(c.pointerId),q(!1)),F.current=null,I.current=null,P.current=!1},[]);i.useEffect(()=>{if(!U)return;const c=document.body.style.userSelect;return document.body.style.userSelect="none",()=>{document.body.style.userSelect=c}},[U]);const ke={onPointerDownCapture:Qe,onPointerDown:et,onPointerMove:tt,onPointerUp:nt,onPointerCancel:rt},te=ae("--bottom-sheet-duration","0.5s"),G=ae("--bottom-sheet-easing","cubic-bezier(0.32, 0.72, 0, 1)"),Fe=(r==null?void 0:r.topSheetClosingProgress)??null,L=o>=1&&Fe!=null,de=L?Ht(Fe,G):0,ot=U||L?"none":`transform ${te} ${G}, height ${te} ${G}, transform-origin ${te} ${G}`,he=ze(o),st=ze(o-1),me=qe(o),ct=qe(o-1),Oe=L?he+(st-he)*de:he,De=L?me+(ct-me)*de:me,Ne=m+D,it=Ne>J?Math.max(0,Math.min(1,(z-J)/(Ne-J))):0,Me=U?1-it:Je,Ie=U?"none":`opacity ${te} ${G}`,Ye=i.useRef(null);return i.useEffect(()=>{if(!n||!r)return;const c=B?Me:0,l=Ie,f=B&&ue?"auto":"none",u=Ye.current;u&&u.opacity===c&&u.transition===l&&u.pointerEvents===f||(Ye.current={opacity:c,transition:l,pointerEvents:f},r.setOverlayStyle({opacity:c,transition:l,pointerEvents:f}))},[n,r,B,ue,Me,Ie]),E.jsx(E.Fragment,{children:E.jsxs("div",{ref:j,role:n?"dialog":void 0,"aria-modal":n?!0:void 0,className:`bottom-sheet${U?" dragging":""}${o>0?" stacked":""} ${T??""}`.trim(),...o===0&&!H?ke:{},style:{position:"fixed",...Ee?{width:Ee,maxWidth:"100%",left:"50%",transform:`translateX(-50%) translateY(${z}px) scale(${Oe}) translateY(-${De}%)`,transformOrigin:"bottom center"}:{left:0,right:0,transform:`translateY(${z}px) scale(${Oe}) translateY(-${De}%)`,transformOrigin:"bottom center"},bottom:0,...N?{height:m===0?"auto":m,maxHeight:"100vh"}:{height:m,maxHeight:"100vh"},"--bottom-sheet-height":`${m}px`,transition:ot,zIndex:t+1,display:"flex",flexDirection:"column",background:"var(--bottom-sheet-bg)",borderRadius:"var(--bottom-sheet-border-radius)",boxShadow:"var(--bottom-sheet-shadow)",padding:"var(--bottom-sheet-padding)"},children:[E.jsx("div",{ref:se,className:"bottom-sheet-handler",...o===0&&H?ke:{},style:{flexShrink:0,display:"flex",alignItems:"center",justifyContent:"center",padding:"var(--bottom-sheet-handler-padding)",gap:"var(--bottom-sheet-gap)"},children:E.jsx("div",{style:{width:"var(--bottom-sheet-handler-width)",height:"var(--bottom-sheet-handler-height)",borderRadius:"var(--bottom-sheet-handler-border-radius)",background:"var(--bottom-sheet-handler-bg)"}})}),E.jsx("div",{ref:_,className:"bottom-sheet-content",style:{...N&&m===0?{flex:"0 0 auto",overflow:"visible",minHeight:0}:{flex:1,overflow:"auto",minHeight:0}},children:E.jsx(Ge.Provider,{value:W,children:E.jsx(a,{...g,closeDrawer:Q,snapToIndex:ee})})}),E.jsx("div",{className:"bottom-sheet-stack-overlay","aria-hidden":!0,style:{position:"absolute",inset:0,background:"var(--bottom-sheet-stack-overlay-bg)",borderRadius:"inherit",pointerEvents:o===0&&!L?"none":"auto",opacity:L&&o===1?1-de:o===0?0:1,transition:L?"none":`opacity ${te} ${G}`,...o>0||L?{cursor:"default"}:{}}})]})})}function Ve(e){if(typeof e=="number")return e;if(typeof document>"u")return 400;const t=e.trim();if(t.endsWith("%"))return window.innerHeight*parseFloat(t.slice(0,-1))/100;if(t.endsWith("px"))return parseFloat(t.slice(0,-2))||400;if(t.endsWith("rem")){const n=parseFloat(getComputedStyle(document.documentElement).fontSize)||16;return parseFloat(t.slice(0,-3))*n||400}return parseFloat(t)||400}const Xe=i.createContext(null);function _t(){return i.useSyncExternalStore(dt,ve,ve)}function Wt({width:e}={}){const t=_t(),[n,o]=i.useState(null),[r,s]=i.useState({opacity:0,transition:"opacity 0.5s cubic-bezier(0.32, 0.72, 0, 1)",pointerEvents:"none"}),a=i.useCallback((d,T)=>{gt(d,T)},[]),g=i.useCallback(d=>{pt(d)},[]),h=typeof document<"u"?document.body:null;return t.length>0&&h?E.jsx(Xe.Provider,{value:{registerController:a,unregisterController:g,defaultWidth:e,setOverlayStyle:s,topSheetClosingProgress:n,setTopSheetClosingProgress:o},children:Ue.createPortal(E.jsxs("div",{className:"bottom-sheets-portal","aria-hidden":"false",children:[t.length>0&&E.jsx("div",{className:"bottom-sheet-overlay",style:{position:"fixed",inset:0,background:"var(--bottom-sheet-overlay-bg)",backdropFilter:"var(--bottom-sheet-overlay-blur-filter)",zIndex:0,pointerEvents:r.pointerEvents??"none",opacity:r.opacity,transition:r.transition},onClick:()=>{var T;const d=t[t.length-1];d!=null&&d.enableClickBackdropToClose&&((T=bt(d.id))==null||T.close())},"aria-hidden":!0}),t.map((d,T)=>E.jsx(jt,{descriptor:d,index:T,isTop:T===t.length-1,stackDepth:t.length-1-T},d.id.toString()))]}),h)}):null}function zt(e){const t={component:e.component,props:e.props??{},height:e.height,width:e.width,snapPoint:e.snapPoint??e.snapPoints,className:e.className,onClose:e.onClose,enableClickBackdropToClose:e.enableClickBackdropToClose,enableBackdrop:e.enableBackdrop,disableEsc:e.disableEsc,gestureOnlyOnHandler:e.gestureOnlyOnHandler,disableSwipeDownToClose:e.disableSwipeDownToClose},n=ht(t);return{id:n,close:()=>V(n),snapToIndex:o=>St(n,o),openFully:()=>vt(n)}}function qt(){const e=ve();if(e.length>0){const t=e[e.length-1];V(t.id)}}function Vt(e){V(e)}function Ut(){mt()}function Gt({children:e,className:t,style:n}){const o=i.useRef(null),r=i.useRef(0),s=Ot();return i.useEffect(()=>{if(!s||!o.current)return;const a=o.current,g=()=>a.scrollTop===0;return s.registerScrollContainer(a,g)},[s]),i.useEffect(()=>{const a=o.current;if(!a)return;const g=y=>{var d;r.current=((d=y.touches[0])==null?void 0:d.clientY)??0},h=y=>{if(a.scrollTop>0||!y.cancelable)return;const d=y.touches[0];if(!d)return;d.clientY-r.current>8&&y.preventDefault()};return a.addEventListener("touchstart",g,{passive:!0}),a.addEventListener("touchmove",h,{passive:!1,capture:!0}),()=>{a.removeEventListener("touchstart",g),a.removeEventListener("touchmove",h,{capture:!0})}},[]),E.jsx("div",{ref:o,className:t,style:{flex:1,minHeight:0,overflow:"auto",WebkitOverflowScrolling:"touch",overscrollBehaviorY:"contain",...n},children:e})}exports.BottomSheetRoot=Wt;exports.BottomSheetScrollable=Gt;exports.closeAllBottomSheets=Ut;exports.closeBottomSheet=Vt;exports.popBottomSheet=qt;exports.pushBottomSheet=zt;
|
|
2
|
+
//# sourceMappingURL=index.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.cjs","sources":["../lib/store/store.ts","../lib/utils/snap.ts","../lib/utils/gestures.ts","../lib/context/scrollContext.tsx","../lib/hooks/useFocusTrap.ts","../lib/components/BottomSheet.tsx","../lib/context/context.tsx","../lib/api.ts","../lib/components/BottomSheetScrollable.tsx"],"sourcesContent":["import type { SheetDescriptor } from '../types';\n\nexport type SheetController = {\n snapToIndex: (index: number) => void;\n openFully: () => void;\n close: () => void;\n};\n\nlet idCounter = 0;\nfunction nextId(): symbol {\n return Symbol(`bottom-sheet-${++idCounter}`);\n}\n\nlet sheets: Array<SheetDescriptor & { id: symbol }> = [];\nconst listeners = new Set<() => void>();\n\nfunction emit() {\n listeners.forEach((l) => l());\n}\n\nexport function getSheets(): ReadonlyArray<SheetDescriptor & { id: symbol }> {\n return sheets;\n}\n\nexport function subscribe(listener: () => void): () => void {\n listeners.add(listener);\n return () => listeners.delete(listener);\n}\n\nexport function addSheet(descriptor: Omit<SheetDescriptor, 'id'>): symbol {\n const id = nextId();\n const entry = { ...descriptor, id } as SheetDescriptor & { id: symbol };\n sheets = [...sheets, entry];\n emit();\n return id;\n}\n\nexport function removeSheet(id: string | symbol): void {\n sheets = sheets.filter((s) => s.id !== id);\n emit();\n}\n\nexport function removeAllSheets(): void {\n sheets = [];\n emit();\n}\n\nconst sheetControllers = new Map<symbol | string, SheetController>();\nconst pendingSnapIndex = new Map<symbol | string, number>();\nconst pendingOpenFully = new Set<symbol | string>();\n\nexport function registerSheetController(id: symbol | string, controller: SheetController): void {\n sheetControllers.set(id, controller);\n const snap = pendingSnapIndex.get(id);\n if (snap !== undefined) {\n pendingSnapIndex.delete(id);\n controller.snapToIndex(snap);\n }\n if (pendingOpenFully.has(id)) {\n pendingOpenFully.delete(id);\n controller.openFully();\n }\n}\n\nexport function unregisterSheetController(id: symbol | string): void {\n sheetControllers.delete(id);\n}\n\nexport function getSheetController(id: symbol | string): SheetController | undefined {\n return sheetControllers.get(id);\n}\n\nexport function invokeSnapToIndex(id: symbol | string, index: number): void {\n const ctrl = sheetControllers.get(id);\n if (ctrl) ctrl.snapToIndex(index);\n else pendingSnapIndex.set(id, index);\n}\n\nexport function invokeOpenFully(id: symbol | string): void {\n const ctrl = sheetControllers.get(id);\n if (ctrl) ctrl.openFully();\n else pendingOpenFully.add(id);\n}\n","/**\n * Parse a single snap point string to pixels relative to viewport height.\n * Valid: \"50%\", \"100px\", \"20rem\", \"50\" (treated as px).\n * Invalid entries return null.\n */\nfunction parseSnapValue(value: string, viewportHeightPx: number, remPx: number): number | null {\n const trimmed = value.trim();\n if (!trimmed) return null;\n\n if (trimmed.endsWith('%')) {\n const num = parseFloat(trimmed.slice(0, -1));\n if (Number.isNaN(num) || num < 0 || num > 100) return null;\n return (num / 100) * viewportHeightPx;\n }\n\n if (trimmed.endsWith('px')) {\n const num = parseFloat(trimmed.slice(0, -2));\n if (Number.isNaN(num)) return null;\n return num;\n }\n\n if (trimmed.endsWith('rem')) {\n const num = parseFloat(trimmed.slice(0, -3));\n if (Number.isNaN(num)) return null;\n return num * remPx;\n }\n\n const asNumber = parseFloat(trimmed);\n if (!Number.isNaN(asNumber)) return asNumber;\n return null;\n}\n\nfunction getRemPx(): number {\n if (typeof document === 'undefined') return 16;\n const root = document.documentElement;\n const fontSize = getComputedStyle(root).fontSize;\n const rem = parseFloat(fontSize);\n return Number.isNaN(rem) ? 16 : rem;\n}\n\n/**\n * Parse snap point strings to an array of heights in pixels (from bottom of viewport).\n * Sorted ascending (smallest = most closed, largest = most open).\n * viewportHeightPx: window.innerHeight or equivalent.\n */\nexport function parseSnapPoints(\n snapPoint: string[] | undefined,\n viewportHeightPx: number\n): number[] {\n if (!snapPoint?.length) return [];\n const remPx = getRemPx();\n const parsed = snapPoint\n .map((s) => parseSnapValue(s, viewportHeightPx, remPx))\n .filter((v): v is number => v !== null && v >= 0);\n const unique = [...new Set(parsed)];\n unique.sort((a, b) => a - b);\n return unique;\n}\n\n/**\n * Clamp value between min and max. For rubberband, we allow overscroll with resistance.\n */\nexport function clamp(value: number, min: number, max: number): number {\n return Math.min(Math.max(value, min), max);\n}\n\nconst RUBBERBAND_SCALE_PX = 80;\nconst RUBBERBAND_FACTOR_MAX = 0.35;\nconst RUBBERBAND_FACTOR_MIN = 0.08;\n\n/**\n * Resistance factor that decreases as overscroll (over) increases, approaching min but never 0.\n */\nfunction rubberbandFactor(over: number): number {\n return (\n RUBBERBAND_FACTOR_MIN +\n (RUBBERBAND_FACTOR_MAX - RUBBERBAND_FACTOR_MIN) / (1 + over / RUBBERBAND_SCALE_PX)\n );\n}\n\n/**\n * Apply rubberband when beyond bounds. Resistance is incremental: the more you overscroll,\n * the stronger the resistance (smaller movement per pixel), approaching a minimum factor but never zero.\n * Used when swiping past the last (highest) snap point, or past max height when there are no snap points.\n */\nexport function rubberband(value: number, min: number, max: number): number {\n if (value >= min && value <= max) return value;\n if (value < min) {\n const over = min - value;\n const factor = rubberbandFactor(over);\n return min - over * factor;\n }\n const over = value - max;\n const factor = rubberbandFactor(over);\n return max + over * factor;\n}\n","/**\n * Velocity threshold (px/ms) above which we consider it a \"fast swipe\" for closing or snapping.\n */\nexport const VELOCITY_THRESHOLD = 0.5;\n\n/**\n * Fraction of travel (0..1) toward closed position. If past this and velocity is down, can close.\n */\nexport const CLOSE_THRESHOLD = 0.6;\n\n/**\n * Fraction of travel (0..1) between two snap points. If past 50%, go to next snap.\n */\nexport const SNAP_PROGRESS_THRESHOLD = 0.5;\n\nexport interface ReleaseResult {\n action: 'close' | 'snap';\n targetIndex?: number;\n targetY?: number;\n}\n\n/**\n * Given current position (translateY, 0 = top), sheet height, snap points in px (heights from bottom),\n * and velocity (positive = downward), decide whether to close or snap to an index.\n * Snap points are ordered ascending (smallest = most closed). Position is \"how much the sheet is down\"\n * so 0 = fully open (sheet top at viewport top), sheetHeight = fully closed.\n */\nexport function getReleaseTarget(\n currentTranslateY: number,\n sheetHeight: number,\n snapPointsPx: number[],\n velocityY: number,\n closeOffset: number = 0\n): ReleaseResult {\n const closedPosition = sheetHeight + closeOffset;\n\n if (snapPointsPx.length === 0) {\n if (currentTranslateY >= closedPosition * CLOSE_THRESHOLD) {\n return { action: 'close' };\n }\n return { action: 'snap', targetY: 0 };\n }\n\n const sortedSnaps = [...snapPointsPx].sort((a, b) => a - b);\n const firstSnap = sortedSnaps[0];\n const firstSnapTranslateY = sheetHeight - firstSnap;\n const closedPos = sheetHeight + closeOffset;\n const closeZoneStart = firstSnapTranslateY;\n const closeZoneLength = closedPos - closeZoneStart;\n const closeThresholdY = closeZoneStart + CLOSE_THRESHOLD * closeZoneLength;\n\n if (velocityY > VELOCITY_THRESHOLD) {\n if (currentTranslateY >= closeThresholdY) {\n return { action: 'close' };\n }\n const nextSnapDown = findNextSnapDown(currentTranslateY, sortedSnaps, sheetHeight);\n if (nextSnapDown !== undefined) {\n const targetY = sheetHeight - nextSnapDown;\n return { action: 'snap', targetY, targetIndex: snapPointsPx.indexOf(nextSnapDown) };\n }\n }\n\n if (velocityY < -VELOCITY_THRESHOLD) {\n const nextSnapUp = findNextSnapUp(currentTranslateY, sortedSnaps, sheetHeight);\n if (nextSnapUp !== undefined) {\n const targetY = sheetHeight - nextSnapUp;\n const idx = sortedSnaps.indexOf(nextSnapUp);\n return { action: 'snap', targetY, targetIndex: idx };\n }\n }\n\n const currentSnapIndex = findCurrentSnapIndex(currentTranslateY, sortedSnaps, sheetHeight);\n const progress = getProgressToNextSnap(currentTranslateY, currentSnapIndex, sortedSnaps, sheetHeight);\n\n if (progress >= SNAP_PROGRESS_THRESHOLD && currentSnapIndex < sortedSnaps.length - 1) {\n const nextSnap = sortedSnaps[currentSnapIndex + 1];\n return { action: 'snap', targetY: sheetHeight - nextSnap, targetIndex: currentSnapIndex + 1 };\n }\n\n if (currentSnapIndex > 0 || currentTranslateY < closeZoneStart) {\n const snap = sortedSnaps[currentSnapIndex];\n return { action: 'snap', targetY: sheetHeight - snap, targetIndex: currentSnapIndex };\n }\n\n if (currentTranslateY >= closeThresholdY) {\n return { action: 'close' };\n }\n\n return { action: 'snap', targetY: firstSnapTranslateY, targetIndex: 0 };\n}\n\nfunction findNextSnapDown(\n currentY: number,\n sortedSnaps: number[],\n sheetHeight: number\n): number | undefined {\n const currentVisible = sheetHeight - currentY;\n for (let i = sortedSnaps.length - 1; i >= 0; i--) {\n if (sortedSnaps[i] < currentVisible) return sortedSnaps[i];\n }\n return undefined;\n}\n\nfunction findNextSnapUp(\n currentY: number,\n sortedSnaps: number[],\n sheetHeight: number\n): number | undefined {\n const currentVisible = sheetHeight - currentY;\n for (let i = 0; i < sortedSnaps.length; i++) {\n if (sortedSnaps[i] > currentVisible) return sortedSnaps[i];\n }\n return undefined;\n}\n\nfunction findCurrentSnapIndex(\n currentY: number,\n sortedSnaps: number[],\n sheetHeight: number\n): number {\n const currentVisible = sheetHeight - currentY;\n let best = 0;\n let bestDist = Infinity;\n for (let i = 0; i < sortedSnaps.length; i++) {\n const d = Math.abs(sortedSnaps[i] - currentVisible);\n if (d < bestDist) {\n bestDist = d;\n best = i;\n }\n }\n return best;\n}\n\nfunction getProgressToNextSnap(\n currentY: number,\n currentSnapIndex: number,\n sortedSnaps: number[],\n sheetHeight: number\n): number {\n if (currentSnapIndex >= sortedSnaps.length - 1) return 0;\n const currentVisible = sheetHeight - currentY;\n const fromSnap = sortedSnaps[currentSnapIndex];\n const toSnap = sortedSnaps[currentSnapIndex + 1];\n const segment = toSnap - fromSnap;\n if (segment <= 0) return 0;\n const progress = (currentVisible - fromSnap) / segment;\n return Math.max(0, Math.min(1, progress));\n}\n","import { createContext, useCallback, useRef, useContext } from 'react';\n\nexport interface ScrollContainerContextValue {\n /** Register a scroll container. Returns unregister function. */\n registerScrollContainer: (el: HTMLElement, getCanDrag: () => boolean) => () => void;\n /** True if target is inside any registered scroll container. */\n isInScrollContainer: (target: Node) => boolean;\n /**\n * Returns true if sheet gestures should be blocked for this target.\n * (e.g. when inside a scrollable that is not at top)\n */\n shouldBlockGestures: (target: Node) => boolean;\n /**\n * For targets inside a scroll container at top: can we capture for a downward swipe?\n * (scrollTop === 0)\n */\n canCaptureForDownSwipe: (target: Node) => boolean;\n}\n\nexport const ScrollContainerContext = createContext<ScrollContainerContextValue | null>(null);\n\nexport function useScrollContainerContext(): ScrollContainerContextValue | null {\n return useContext(ScrollContainerContext);\n}\n\nfunction findScrollContainer(\n target: Node,\n containers: Map<HTMLElement, () => boolean>\n): { el: HTMLElement; getCanDrag: () => boolean } | null {\n let node: Node | null = target;\n while (node && node !== document.body) {\n if (node instanceof HTMLElement && containers.has(node)) {\n return { el: node, getCanDrag: containers.get(node)! };\n }\n node = node.parentNode;\n }\n return null;\n}\n\nexport function useScrollContainerContextValue(): ScrollContainerContextValue {\n const containersRef = useRef<Map<HTMLElement, () => boolean>>(new Map());\n\n const registerScrollContainer = useCallback((el: HTMLElement, getCanDrag: () => boolean) => {\n containersRef.current.set(el, getCanDrag);\n return () => {\n containersRef.current.delete(el);\n };\n }, []);\n\n const isInScrollContainer = useCallback((target: Node): boolean => {\n return findScrollContainer(target, containersRef.current) !== null;\n }, []);\n\n const shouldBlockGestures = useCallback((target: Node): boolean => {\n const entry = findScrollContainer(target, containersRef.current);\n if (!entry) return false;\n return !entry.getCanDrag();\n }, []);\n\n const canCaptureForDownSwipe = useCallback((target: Node): boolean => {\n const entry = findScrollContainer(target, containersRef.current);\n if (!entry) return false;\n return entry.getCanDrag();\n }, []);\n\n return {\n registerScrollContainer,\n isInScrollContainer,\n shouldBlockGestures,\n canCaptureForDownSwipe,\n };\n}\n","import { useEffect, type RefObject } from \"react\";\n\nconst FOCUSABLE_SELECTOR =\n 'button, [href], input, select, textarea, [tabindex]:not([tabindex=\"-1\"])';\n\nconst CLOSE_BUTTON_CLASS = \"modals-close\";\n\nfunction getFocusableElements(container: HTMLElement): HTMLElement[] {\n return Array.from(container.querySelectorAll<HTMLElement>(FOCUSABLE_SELECTOR));\n}\n\nfunction getFocusableExcludingClose(container: HTMLElement): HTMLElement[] {\n return getFocusableElements(container).filter(\n (el) => !el.classList.contains(CLOSE_BUTTON_CLASS)\n );\n}\n\nexport function useFocusTrap(\n containerRef: RefObject<HTMLElement | null>,\n enabled: boolean,\n disableAutoFocus = false\n): void {\n useEffect(() => {\n if (!enabled || !containerRef.current) return;\n const container = containerRef.current;\n const previouslyFocused = document.activeElement as HTMLElement | null;\n\n if (!disableAutoFocus) {\n const focusableExcludingClose = getFocusableExcludingClose(container);\n const focusable = getFocusableElements(container);\n const first =\n focusableExcludingClose[0] ?? focusable[0];\n\n if (first) {\n first.focus();\n } else {\n container.setAttribute(\"tabindex\", \"-1\");\n container.focus();\n }\n }\n\n function handleKeyDown(e: KeyboardEvent) {\n if (e.key !== \"Tab\") return;\n const focusableNow = getFocusableElements(container);\n const firstNow = focusableNow[0];\n const lastNow = focusableNow[focusableNow.length - 1];\n if (e.shiftKey) {\n if (document.activeElement === firstNow && lastNow) {\n e.preventDefault();\n lastNow.focus();\n }\n } else {\n if (document.activeElement === lastNow && firstNow) {\n e.preventDefault();\n firstNow.focus();\n }\n }\n }\n\n container.addEventListener(\"keydown\", handleKeyDown);\n\n return () => {\n container.removeEventListener(\"keydown\", handleKeyDown);\n if (previouslyFocused && typeof previouslyFocused.focus === \"function\") {\n previouslyFocused.focus();\n }\n };\n // containerRef is intentionally omitted - refs are mutable and should not be in deps\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [enabled, disableAutoFocus]);\n}\n","import {\n useRef,\n useState,\n useEffect,\n useCallback,\n useLayoutEffect,\n useContext,\n} from 'react';\nimport { flushSync } from 'react-dom';\nimport type { SheetDescriptor } from '../types';\nimport { parseSnapPoints, rubberband } from '../utils/snap';\nimport { getReleaseTarget } from '../utils/gestures';\nimport { removeSheet } from '../store/store';\nimport { BottomSheetContext } from '../context/context';\nimport { ScrollContainerContext, useScrollContainerContextValue } from '../context/scrollContext';\nimport { useFocusTrap } from '../hooks/useFocusTrap';\n\nconst VIEWPORT_MAX = typeof window !== 'undefined' ? () => window.innerHeight : () => 800;\nconst DRAG_THRESHOLD = 5;\n\nfunction getCssVar(name: string, fallback: string): string {\n if (typeof document === 'undefined') return fallback;\n const value = getComputedStyle(document.documentElement).getPropertyValue(name).trim();\n return value || fallback;\n}\n\nfunction getDurationMs(): number {\n const s = getCssVar('--bottom-sheet-duration', '0.5s');\n const match = s.match(/^([\\d.]+)s$/);\n if (match) return parseFloat(match[1]) * 1000;\n const matchMs = s.match(/^([\\d.]+)ms$/);\n if (matchMs) return parseFloat(matchMs[1]);\n return 500;\n}\n\nfunction getEaseCubicBezierY(t: number, y1: number, y2: number): number {\n const t2 = 1 - t;\n return 3 * t2 * t2 * t * y1 + 3 * t2 * t * t * y2 + t * t * t;\n}\n\nfunction getEasedProgress(progress: number, easingVar: string): number {\n const match = easingVar.match(/cubic-bezier\\s*\\(\\s*([\\d.]+)\\s*,\\s*([\\d.]+)\\s*,\\s*([\\d.]+)\\s*,\\s*([\\d.]+)\\s*\\)/);\n if (!match) return progress;\n const values = match.map(Number);\n const y1 = values[2];\n const y2 = values[4];\n return getEaseCubicBezierY(progress, y1, y2);\n}\n\nfunction scaleForStackDepth(d: number): number {\n return d === 0 ? 1 : Math.max(0.5, 0.9 - (d - 1) * 0.05);\n}\n\nfunction offsetForStackDepth(d: number): number {\n return d === 0 ? 0 : 12 + (d - 1) * 8;\n}\n\nexport interface BottomSheetProps {\n descriptor: SheetDescriptor & { id: symbol };\n index: number;\n isTop: boolean;\n /** 0 = top sheet, 1 = first behind, 2 = second behind, etc. */\n stackDepth: number;\n}\n\nexport function BottomSheet({ descriptor, index, isTop, stackDepth }: BottomSheetProps) {\n const ctx = useContext(BottomSheetContext);\n const {\n id,\n component: Component,\n props: componentProps,\n height: heightProp,\n width: widthProp,\n snapPoint,\n className,\n onClose,\n enableBackdrop,\n enableClickBackdropToClose,\n disableEsc,\n gestureOnlyOnHandler,\n disableSwipeDownToClose,\n } = descriptor;\n\n const effectiveWidth = widthProp ?? ctx?.defaultWidth;\n const widthCss =\n effectiveWidth == null ? undefined : typeof effectiveWidth === 'number' ? `${effectiveWidth}px` : effectiveWidth;\n\n const viewportHeight = VIEWPORT_MAX();\n const closeOffset =\n typeof document !== 'undefined'\n ? parseFloat(getCssVar('--bottom-sheet-close-extra-offset', '0')) || 0\n : 0;\n\n const hasSnapPoints = Boolean(snapPoint?.length);\n const contentDrivenHeight = heightProp == null && !hasSnapPoints;\n\n const sheetRef = useRef<HTMLDivElement>(null);\n const handlerRef = useRef<HTMLDivElement>(null);\n const contentRef = useRef<HTMLDivElement>(null);\n const scrollCtxValue = useScrollContainerContextValue();\n const [sheetHeight, setSheetHeight] = useState(() => {\n if (heightProp != null) return parseHeight(heightProp);\n if (contentDrivenHeight) return 0;\n return viewportHeight;\n });\n const [contentHeightMeasured, setContentHeightMeasured] = useState(!contentDrivenHeight);\n const closedY = sheetHeight + closeOffset;\n const snapPointsPx = parseSnapPoints(snapPoint, viewportHeight);\n const effectiveSnaps = snapPointsPx\n .filter((s) => s <= sheetHeight)\n .sort((a, b) => a - b);\n const firstSnapY = effectiveSnaps.length > 0 ? sheetHeight - effectiveSnaps[0] : 0;\n const [translateY, setTranslateY] = useState(() =>\n contentDrivenHeight ? viewportHeight : effectiveSnaps.length > 0 ? closedY : 0\n );\n const [isDragging, setIsDragging] = useState(false);\n const [isAnimating, setIsAnimating] = useState(false);\n const [hasOpened, setHasOpened] = useState(false);\n const [backdropOpacity, setBackdropOpacity] = useState(0);\n const dragStartRef = useRef<{ y: number; sheetY: number; time: number } | null>(null);\n const lastMoveRef = useRef<{ y: number; time: number } | null>(null);\n const hasCapturedRef = useRef(false);\n const heightAnimationTimeoutRef = useRef<ReturnType<typeof setTimeout> | null>(null);\n\n useLayoutEffect(() => {\n if (effectiveSnaps.length > 0) setTranslateY(closedY);\n }, []);\n\n useEffect(() => {\n if (heightProp != null) {\n setSheetHeight(parseHeight(heightProp));\n setContentHeightMeasured(true);\n return;\n }\n if (!contentDrivenHeight) {\n const el = contentRef.current;\n if (!el) return;\n const ro = new ResizeObserver(() => {\n const h = el.getBoundingClientRect().height;\n setSheetHeight((prev) => Math.min(Math.max(prev, h), viewportHeight));\n });\n ro.observe(el);\n const h = el.getBoundingClientRect().height;\n setSheetHeight((prev) => Math.min(Math.max(prev, h), viewportHeight));\n return () => ro.disconnect();\n }\n const el = sheetRef.current;\n if (!el) return;\n const updateHeight = () => {\n const sheet = sheetRef.current;\n const handler = handlerRef.current;\n const content = contentRef.current;\n if (!sheet || !handler || !content) return;\n if (sheetHeight === 0) {\n const h = Math.min(sheet.getBoundingClientRect().height, viewportHeight);\n if (h > 0) {\n setSheetHeight(h);\n setContentHeightMeasured(true);\n }\n return;\n }\n const style = getComputedStyle(sheet);\n const paddingTop = parseFloat(style.paddingTop) || 0;\n const paddingBottom = parseFloat(style.paddingBottom) || 0;\n const gapStr = style.gap || '0.5rem';\n const gapPx = gapStr.endsWith('rem')\n ? parseFloat(gapStr) * (parseFloat(getComputedStyle(document.documentElement).fontSize) || 16)\n : parseFloat(gapStr) || 8;\n const contentEl = content.firstElementChild;\n const contentHeight = contentEl\n ? contentEl.getBoundingClientRect().height\n : content.scrollHeight || content.getBoundingClientRect().height;\n const h = Math.min(\n paddingTop + paddingBottom + handler.offsetHeight + gapPx + contentHeight,\n viewportHeight\n );\n if (h > 0) {\n if (heightAnimationTimeoutRef.current) {\n clearTimeout(heightAnimationTimeoutRef.current);\n heightAnimationTimeoutRef.current = null;\n }\n setSheetHeight(h);\n setIsAnimating(true);\n heightAnimationTimeoutRef.current = setTimeout(() => {\n heightAnimationTimeoutRef.current = null;\n setIsAnimating(false);\n }, getDurationMs());\n }\n };\n const ro = new ResizeObserver(updateHeight);\n if (contentRef.current) ro.observe(contentRef.current);\n const firstChild = contentRef.current?.firstElementChild;\n if (firstChild) ro.observe(firstChild);\n if (handlerRef.current) ro.observe(handlerRef.current);\n ro.observe(sheetRef.current);\n requestAnimationFrame(updateHeight);\n return () => {\n ro.disconnect();\n if (heightAnimationTimeoutRef.current) {\n clearTimeout(heightAnimationTimeoutRef.current);\n heightAnimationTimeoutRef.current = null;\n }\n };\n }, [heightProp, viewportHeight, contentDrivenHeight, sheetHeight]);\n\n useEffect(() => {\n if (hasOpened) return;\n if (contentDrivenHeight && !contentHeightMeasured) return;\n setHasOpened(true);\n setTranslateY(closedY);\n requestAnimationFrame(() => {\n setBackdropOpacity(1);\n setIsAnimating(true);\n setTranslateY(firstSnapY);\n const duration = getDurationMs();\n setTimeout(() => setIsAnimating(false), duration);\n });\n }, [hasOpened, contentDrivenHeight, contentHeightMeasured, firstSnapY, closedY, sheetHeight]);\n\n const closeDrawer = useCallback(() => {\n if (isAnimating) return;\n setBackdropOpacity(0);\n setIsAnimating(true);\n const duration = getDurationMs();\n setTranslateY(sheetHeight + closeOffset);\n if (isTop && ctx) {\n ctx.setTopSheetClosingProgress(0);\n const startTime = Date.now();\n const tick = () => {\n const elapsed = Date.now() - startTime;\n const progress = Math.min(1, elapsed / duration);\n ctx?.setTopSheetClosingProgress(progress);\n if (progress < 1) {\n requestAnimationFrame(tick);\n } else {\n onClose?.();\n removeSheet(id);\n ctx?.setTopSheetClosingProgress(null);\n setIsAnimating(false);\n }\n };\n requestAnimationFrame(tick);\n } else {\n const t = setTimeout(() => {\n onClose?.();\n removeSheet(id);\n setIsAnimating(false);\n }, duration);\n return () => clearTimeout(t);\n }\n }, [id, sheetHeight, closeOffset, onClose, isAnimating, isTop, ctx]);\n\n const snapToIndex = useCallback(\n (i: number) => {\n if (isAnimating) return;\n if (effectiveSnaps.length === 0) {\n setTranslateY(0);\n return;\n }\n const idx = Math.max(0, Math.min(i, effectiveSnaps.length - 1));\n const targetY = sheetHeight - effectiveSnaps[idx];\n setIsAnimating(true);\n setTranslateY(targetY);\n const duration = getDurationMs();\n const t = setTimeout(() => setIsAnimating(false), duration);\n return () => clearTimeout(t);\n },\n [effectiveSnaps, sheetHeight, isAnimating]\n );\n\n const openFully = useCallback(() => {\n if (effectiveSnaps.length > 0) {\n snapToIndex(effectiveSnaps.length - 1);\n } else {\n setIsAnimating(true);\n setTranslateY(0);\n const t = setTimeout(() => setIsAnimating(false), getDurationMs());\n return () => clearTimeout(t);\n }\n }, [effectiveSnaps.length, snapToIndex]);\n\n useLayoutEffect(() => {\n if (!ctx) return;\n ctx.registerController(id, { snapToIndex, openFully, close: closeDrawer });\n return () => ctx.unregisterController(id);\n }, [id, ctx, snapToIndex, openFully, closeDrawer]);\n\n useEffect(() => {\n if (!isTop) return;\n const onKeyDown = (e: KeyboardEvent) => {\n if (e.key === 'Escape' && !disableEsc) {\n e.preventDefault();\n flushSync(() => {\n setIsDragging(false);\n setIsAnimating(false);\n });\n dragStartRef.current = null;\n lastMoveRef.current = null;\n closeDrawer();\n }\n };\n window.addEventListener('keydown', onKeyDown);\n return () => window.removeEventListener('keydown', onKeyDown);\n }, [isTop, disableEsc, closeDrawer]);\n\n useFocusTrap(sheetRef, isTop && hasOpened);\n\n const cleanupDragState = useCallback((pointerId?: number) => {\n if (hasCapturedRef.current && sheetRef.current && pointerId != null) {\n try {\n sheetRef.current.releasePointerCapture(pointerId);\n } catch {\n /* ignore if no capture */\n }\n setIsDragging(false);\n }\n dragStartRef.current = null;\n lastMoveRef.current = null;\n hasCapturedRef.current = false;\n }, []);\n\n const handlePointerDownCapture = useCallback(\n (e: React.PointerEvent) => {\n if (e.button !== 0) return;\n const isTouch = e.pointerType === 'touch';\n const isInContent = contentRef.current?.contains(e.target as Node) ?? false;\n if (isTouch && isInContent) {\n // When inside a scroll container, defer capture until we know swipe direction (see handlePointerMove)\n if (scrollCtxValue.isInScrollContainer(e.target as Node)) {\n return;\n }\n e.currentTarget.setPointerCapture(e.pointerId);\n hasCapturedRef.current = true;\n setIsDragging(true);\n }\n },\n [scrollCtxValue]\n );\n\n const handlePointerDown = useCallback(\n (e: React.PointerEvent) => {\n if (e.button !== 0) return;\n const pointerId = e.pointerId;\n dragStartRef.current = { y: e.clientY, sheetY: translateY, time: Date.now() };\n lastMoveRef.current = { y: e.clientY, time: Date.now() };\n const onPointerUpGlobal = (ev: PointerEvent) => {\n if (ev.pointerId !== pointerId) return;\n window.removeEventListener('pointerup', onPointerUpGlobal);\n window.removeEventListener('pointercancel', onPointerUpGlobal);\n cleanupDragState(pointerId);\n };\n window.addEventListener('pointerup', onPointerUpGlobal);\n window.addEventListener('pointercancel', onPointerUpGlobal);\n },\n [translateY, cleanupDragState]\n );\n\n const handlePointerMove = useCallback(\n (e: React.PointerEvent) => {\n if (!dragStartRef.current) return;\n if (e.buttons === 0) {\n if (hasCapturedRef.current) {\n e.currentTarget.releasePointerCapture(e.pointerId);\n setIsDragging(false);\n }\n dragStartRef.current = null;\n lastMoveRef.current = null;\n hasCapturedRef.current = false;\n return;\n }\n lastMoveRef.current = { y: e.clientY, time: Date.now() };\n const delta = e.clientY - dragStartRef.current.y;\n const threshold = e.pointerType === 'touch' ? 1 : DRAG_THRESHOLD;\n if (!hasCapturedRef.current && Math.abs(delta) > threshold) {\n const target = e.target as Node;\n if (scrollCtxValue.isInScrollContainer(target)) {\n if (scrollCtxValue.shouldBlockGestures(target)) return;\n if (!scrollCtxValue.canCaptureForDownSwipe(target) || delta <= 0) return;\n e.preventDefault();\n }\n e.currentTarget.setPointerCapture(e.pointerId);\n hasCapturedRef.current = true;\n setIsDragging(true);\n }\n if (!hasCapturedRef.current) return;\n let next = dragStartRef.current.sheetY + delta;\n const min = 0;\n const max = sheetHeight + closeOffset;\n if (effectiveSnaps.length > 0) {\n const maxSnap = Math.max(...effectiveSnaps);\n const minY = sheetHeight - maxSnap;\n if (next > max) next = rubberband(next, minY, max);\n else if (next < minY) next = rubberband(next, minY, max);\n else next = Math.max(minY, Math.min(max, next));\n } else {\n if (next > max || next < min) next = rubberband(next, min, max);\n else next = Math.max(min, Math.min(max, next));\n }\n setTranslateY(next);\n },\n [sheetHeight, closeOffset, effectiveSnaps, scrollCtxValue]\n );\n\n const handlePointerUp = useCallback(\n (e: React.PointerEvent) => {\n if (!dragStartRef.current) return;\n const didCapture = hasCapturedRef.current;\n if (didCapture) {\n e.currentTarget.releasePointerCapture(e.pointerId);\n setIsDragging(false);\n }\n const last = lastMoveRef.current;\n const velocityY =\n last && last.time !== dragStartRef.current.time\n ? (e.clientY - last.y) / (Date.now() - last.time)\n : 0;\n dragStartRef.current = null;\n lastMoveRef.current = null;\n hasCapturedRef.current = false;\n\n if (!didCapture) return;\n\n const result = getReleaseTarget(\n translateY,\n sheetHeight,\n effectiveSnaps,\n velocityY,\n closeOffset\n );\n\n if (result.action === 'close') {\n if (disableSwipeDownToClose) {\n const targetY = effectiveSnaps.length > 0 ? sheetHeight - effectiveSnaps[0] : 0;\n setIsAnimating(true);\n setTranslateY(targetY);\n const duration = getDurationMs();\n setTimeout(() => setIsAnimating(false), duration);\n return;\n }\n setBackdropOpacity(0);\n setIsAnimating(true);\n setTranslateY(sheetHeight + closeOffset);\n const duration = getDurationMs();\n if (isTop && ctx) {\n ctx.setTopSheetClosingProgress(0);\n const startTime = Date.now();\n const tick = () => {\n const elapsed = Date.now() - startTime;\n const progress = Math.min(1, elapsed / duration);\n ctx?.setTopSheetClosingProgress(progress);\n if (progress < 1) {\n requestAnimationFrame(tick);\n } else {\n onClose?.();\n removeSheet(id);\n ctx?.setTopSheetClosingProgress(null);\n setIsAnimating(false);\n }\n };\n requestAnimationFrame(tick);\n } else {\n setTimeout(() => {\n onClose?.();\n removeSheet(id);\n setIsAnimating(false);\n }, duration);\n }\n return;\n }\n\n const targetY = result.targetY ?? 0;\n setIsAnimating(true);\n setTranslateY(targetY);\n const duration = getDurationMs();\n setTimeout(() => setIsAnimating(false), duration);\n },\n [\n translateY,\n sheetHeight,\n effectiveSnaps,\n closeOffset,\n id,\n onClose,\n disableSwipeDownToClose,\n isTop,\n ctx,\n ]\n );\n\n const handlePointerCancel = useCallback((e: React.PointerEvent) => {\n if (hasCapturedRef.current) {\n e.currentTarget.releasePointerCapture(e.pointerId);\n setIsDragging(false);\n }\n dragStartRef.current = null;\n lastMoveRef.current = null;\n hasCapturedRef.current = false;\n }, []);\n\n useEffect(() => {\n if (!isDragging) return;\n const prev = document.body.style.userSelect;\n document.body.style.userSelect = 'none';\n return () => {\n document.body.style.userSelect = prev;\n };\n }, [isDragging]);\n\n const gestureProps = {\n onPointerDownCapture: handlePointerDownCapture,\n onPointerDown: handlePointerDown,\n onPointerMove: handlePointerMove,\n onPointerUp: handlePointerUp,\n onPointerCancel: handlePointerCancel,\n };\n\n const duration = getCssVar('--bottom-sheet-duration', '0.5s');\n const easing = getCssVar('--bottom-sheet-easing', 'cubic-bezier(0.32, 0.72, 0, 1)');\n const closingProgress = ctx?.topSheetClosingProgress ?? null;\n const isRevealingDuringClose = stackDepth >= 1 && closingProgress != null;\n const easedProgress = isRevealingDuringClose ? getEasedProgress(closingProgress, easing) : 0;\n const transition =\n isDragging || isRevealingDuringClose\n ? 'none'\n : `transform ${duration} ${easing}, height ${duration} ${easing}, transform-origin ${duration} ${easing}`;\n\n const fromScale = scaleForStackDepth(stackDepth);\n const toScale = scaleForStackDepth(stackDepth - 1);\n const fromOffset = offsetForStackDepth(stackDepth);\n const toOffset = offsetForStackDepth(stackDepth - 1);\n const stackScale = isRevealingDuringClose\n ? fromScale + (toScale - fromScale) * easedProgress\n : fromScale;\n const stackOffsetY = isRevealingDuringClose\n ? fromOffset + (toOffset - fromOffset) * easedProgress\n : fromOffset;\n\n const closedYNum = sheetHeight + closeOffset;\n const dragProgress =\n closedYNum > firstSnapY\n ? Math.max(0, Math.min(1, (translateY - firstSnapY) / (closedYNum - firstSnapY)))\n : 0;\n const overlayOpacity = isDragging ? 1 - dragProgress : backdropOpacity;\n const overlayTransition = isDragging ? 'none' : `opacity ${duration} ${easing}`;\n\n const lastOverlayStyleRef = useRef<{ opacity: number; transition: string; pointerEvents: 'auto' | 'none' } | null>(null);\n\n useEffect(() => {\n if (!isTop || !ctx) return;\n const opacity = enableBackdrop ? overlayOpacity : 0;\n const transition = overlayTransition;\n const pointerEvents = enableBackdrop && enableClickBackdropToClose ? 'auto' : 'none';\n const last = lastOverlayStyleRef.current;\n if (last && last.opacity === opacity && last.transition === transition && last.pointerEvents === pointerEvents) return;\n lastOverlayStyleRef.current = { opacity, transition, pointerEvents };\n ctx.setOverlayStyle({ opacity, transition, pointerEvents });\n }, [isTop, ctx, enableBackdrop, enableClickBackdropToClose, overlayOpacity, overlayTransition]);\n\n const content = (\n <>\n <div\n ref={sheetRef}\n role={isTop ? 'dialog' : undefined}\n aria-modal={isTop ? true : undefined}\n className={`bottom-sheet${isDragging ? ' dragging' : ''}${stackDepth > 0 ? ' stacked' : ''} ${className ?? ''}`.trim()}\n {...(stackDepth === 0 && !gestureOnlyOnHandler ? gestureProps : {})}\n style={{\n position: 'fixed',\n ...(widthCss\n ? {\n width: widthCss,\n maxWidth: '100%',\n left: '50%',\n transform: `translateX(-50%) translateY(${translateY}px) scale(${stackScale}) translateY(-${stackOffsetY}%)`,\n transformOrigin: 'bottom center',\n }\n : {\n left: 0,\n right: 0,\n transform: `translateY(${translateY}px) scale(${stackScale}) translateY(-${stackOffsetY}%)`,\n transformOrigin: 'bottom center',\n }),\n bottom: 0,\n ...(contentDrivenHeight\n ? { height: sheetHeight === 0 ? 'auto' : sheetHeight, maxHeight: '100vh' }\n : { height: sheetHeight, maxHeight: '100vh' }),\n ['--bottom-sheet-height' as string]: `${sheetHeight}px`,\n transition,\n zIndex: index + 1,\n display: 'flex',\n flexDirection: 'column',\n background: 'var(--bottom-sheet-bg)',\n borderRadius: 'var(--bottom-sheet-border-radius)',\n boxShadow: 'var(--bottom-sheet-shadow)',\n padding: 'var(--bottom-sheet-padding)',\n }}\n >\n <div\n ref={handlerRef}\n className=\"bottom-sheet-handler\"\n {...(stackDepth === 0 && gestureOnlyOnHandler ? gestureProps : {})}\n style={{\n flexShrink: 0,\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n padding: 'var(--bottom-sheet-handler-padding)',\n gap: 'var(--bottom-sheet-gap)',\n }}\n >\n <div\n style={{\n width: 'var(--bottom-sheet-handler-width)',\n height: 'var(--bottom-sheet-handler-height)',\n borderRadius: 'var(--bottom-sheet-handler-border-radius)',\n background: 'var(--bottom-sheet-handler-bg)',\n }}\n />\n </div>\n <div\n ref={contentRef}\n className=\"bottom-sheet-content\"\n style={{\n ...(contentDrivenHeight && sheetHeight === 0\n ? { flex: '0 0 auto', overflow: 'visible', minHeight: 0 }\n : { flex: 1, overflow: 'auto', minHeight: 0 }),\n }}\n >\n <ScrollContainerContext.Provider value={scrollCtxValue}>\n <Component\n {...(componentProps as object)}\n closeDrawer={closeDrawer}\n snapToIndex={snapToIndex}\n />\n </ScrollContainerContext.Provider>\n </div>\n <div\n className=\"bottom-sheet-stack-overlay\"\n aria-hidden\n style={{\n position: 'absolute',\n inset: 0,\n background: 'var(--bottom-sheet-stack-overlay-bg)',\n borderRadius: 'inherit',\n pointerEvents: stackDepth === 0 && !isRevealingDuringClose ? 'none' : 'auto',\n opacity: isRevealingDuringClose && stackDepth === 1\n ? 1 - easedProgress\n : (stackDepth === 0 ? 0 : 1),\n transition: isRevealingDuringClose ? 'none' : `opacity ${duration} ${easing}`,\n ...((stackDepth > 0 || isRevealingDuringClose) ? { cursor: 'default' as const } : {}),\n }}\n />\n </div>\n </>\n );\n\n return content;\n}\n\nfunction parseHeight(h: string | number): number {\n if (typeof h === 'number') return h;\n if (typeof document === 'undefined') return 400;\n const v = h.trim();\n if (v.endsWith('%')) {\n return (window.innerHeight * parseFloat(v.slice(0, -1))) / 100;\n }\n if (v.endsWith('px')) return parseFloat(v.slice(0, -2)) || 400;\n if (v.endsWith('rem')) {\n const rem = parseFloat(getComputedStyle(document.documentElement).fontSize) || 16;\n return parseFloat(v.slice(0, -3)) * rem || 400;\n }\n return parseFloat(v) || 400;\n}\n","import { createContext, useSyncExternalStore, useCallback, useState } from 'react';\nimport { createPortal } from 'react-dom';\nimport {\n getSheets,\n subscribe,\n registerSheetController,\n unregisterSheetController,\n getSheetController,\n} from '../store/store';\nimport type { SheetDescriptor } from '../types';\nimport { BottomSheet } from '../components/BottomSheet';\n\nexport const BottomSheetContext = createContext<{\n registerController: (id: symbol | string, ctrl: { snapToIndex: (i: number) => void; openFully: () => void; close: () => void }) => void;\n unregisterController: (id: symbol | string) => void;\n defaultWidth?: string | number;\n setOverlayStyle: (style: { opacity: number; transition: string; pointerEvents: 'auto' | 'none' }) => void;\n topSheetClosingProgress: number | null;\n setTopSheetClosingProgress: (progress: number | null) => void;\n} | null>(null);\n\nfunction useSheets(): ReadonlyArray<SheetDescriptor & { id: symbol }> {\n return useSyncExternalStore(subscribe, getSheets, getSheets);\n}\n\nexport interface BottomSheetRootProps {\n /** Default width for all bottom sheets (e.g. '50%', '20rem', 400). Number = px. When set, sheets are centered. */\n width?: string | number;\n}\n\nexport function BottomSheetRoot({ width }: BottomSheetRootProps = {}) {\n const sheets = useSheets();\n const [topSheetClosingProgress, setTopSheetClosingProgress] = useState<number | null>(null);\n const [overlayStyle, setOverlayStyle] = useState<{\n opacity: number;\n transition: string;\n pointerEvents: 'auto' | 'none';\n }>({ opacity: 0, transition: 'opacity 0.5s cubic-bezier(0.32, 0.72, 0, 1)', pointerEvents: 'none' });\n\n const registerController = useCallback(\n (id: symbol | string, ctrl: { snapToIndex: (i: number) => void; openFully: () => void; close: () => void }) => {\n registerSheetController(id, ctrl);\n },\n []\n );\n\n const unregisterController = useCallback((id: symbol | string) => {\n unregisterSheetController(id);\n }, []);\n\n const container = typeof document !== 'undefined' ? document.body : null;\n const hasContent = sheets.length > 0 && container;\n\n if (!hasContent) return null;\n\n return (\n <BottomSheetContext.Provider value={{ registerController, unregisterController, defaultWidth: width, setOverlayStyle, topSheetClosingProgress, setTopSheetClosingProgress }}>\n {createPortal(\n <div className=\"bottom-sheets-portal\" aria-hidden=\"false\">\n {sheets.length > 0 && (\n <div\n className=\"bottom-sheet-overlay\"\n style={{\n position: 'fixed',\n inset: 0,\n background: 'var(--bottom-sheet-overlay-bg)',\n backdropFilter: 'var(--bottom-sheet-overlay-blur-filter)',\n zIndex: 0,\n pointerEvents: overlayStyle.pointerEvents ?? 'none',\n opacity: overlayStyle.opacity,\n transition: overlayStyle.transition,\n }}\n onClick={() => {\n const top = sheets[sheets.length - 1];\n if (top?.enableClickBackdropToClose) {\n getSheetController(top.id)?.close();\n }\n }}\n aria-hidden\n />\n )}\n {sheets.map((descriptor, index) => (\n <BottomSheet\n key={descriptor.id.toString()}\n descriptor={descriptor}\n index={index}\n isTop={index === sheets.length - 1}\n stackDepth={sheets.length - 1 - index}\n />\n ))}\n </div>,\n container\n )}\n </BottomSheetContext.Provider>\n );\n}\n","import {\n addSheet,\n removeSheet,\n removeAllSheets,\n getSheets,\n invokeSnapToIndex,\n invokeOpenFully,\n} from './store/store';\nimport type { PushOptions, BottomSheetInstance, SheetDescriptor } from './types';\nimport { BottomSheetRoot } from './context/context';\n\nexport { BottomSheetRoot };\nexport type { BottomSheetRootProps } from './context/context';\n\nexport function pushBottomSheet<T = Record<string, unknown>>(\n options: PushOptions<T>\n): BottomSheetInstance {\n const descriptor: Omit<SheetDescriptor<T>, 'id'> = {\n component: options.component,\n props: (options.props ?? {}) as T,\n height: options.height,\n width: options.width,\n snapPoint: options.snapPoint ?? options.snapPoints,\n className: options.className,\n onClose: options.onClose,\n enableClickBackdropToClose: options.enableClickBackdropToClose,\n enableBackdrop: options.enableBackdrop,\n disableEsc: options.disableEsc,\n gestureOnlyOnHandler: options.gestureOnlyOnHandler,\n disableSwipeDownToClose: options.disableSwipeDownToClose,\n };\n const id = addSheet(descriptor as Omit<SheetDescriptor, 'id'>);\n return {\n id,\n close: () => removeSheet(id),\n snapToIndex: (index: number) => invokeSnapToIndex(id, index),\n openFully: () => invokeOpenFully(id),\n };\n}\n\nexport function popBottomSheet(): void {\n const sheets = getSheets();\n if (sheets.length > 0) {\n const last = sheets[sheets.length - 1];\n removeSheet(last.id);\n }\n}\n\nexport function closeBottomSheet(id: string | symbol): void {\n removeSheet(id);\n}\n\nexport function closeAllBottomSheets(): void {\n removeAllSheets();\n}\n","import { useRef, useEffect, type CSSProperties } from 'react';\nimport { useScrollContainerContext } from '../context/scrollContext';\n\nexport interface BottomSheetScrollableProps {\n children: React.ReactNode;\n className?: string;\n style?: CSSProperties;\n}\n\n/**\n * A scrollable container that coordinates with BottomSheet gestures.\n * - When scrollTop > 0: vertical drags scroll the content (sheet gestures disabled)\n * - When scrollTop === 0: swipe down activates sheet gestures (close/pan), swipe up scrolls\n */\nexport function BottomSheetScrollable({ children, className, style }: BottomSheetScrollableProps) {\n const scrollRef = useRef<HTMLDivElement>(null);\n const touchStartY = useRef<number>(0);\n const ctx = useScrollContainerContext();\n\n useEffect(() => {\n if (!ctx || !scrollRef.current) return;\n const el = scrollRef.current;\n const getCanDrag = () => el.scrollTop === 0;\n return ctx.registerScrollContainer(el, getCanDrag);\n }, [ctx]);\n\n useEffect(() => {\n const el = scrollRef.current;\n if (!el) return;\n const onTouchStart = (e: TouchEvent) => {\n touchStartY.current = e.touches[0]?.clientY ?? 0;\n };\n const onTouchMove = (e: TouchEvent) => {\n if (el.scrollTop > 0 || !e.cancelable) return;\n const touch = e.touches[0];\n if (!touch) return;\n const deltaY = touch.clientY - touchStartY.current;\n if (deltaY > 8) {\n e.preventDefault();\n }\n };\n el.addEventListener('touchstart', onTouchStart, { passive: true });\n el.addEventListener('touchmove', onTouchMove, { passive: false, capture: true });\n return () => {\n el.removeEventListener('touchstart', onTouchStart);\n el.removeEventListener('touchmove', onTouchMove, { capture: true });\n };\n }, []);\n\n return (\n <div\n ref={scrollRef}\n className={className}\n style={{\n flex: 1,\n minHeight: 0,\n overflow: 'auto',\n WebkitOverflowScrolling: 'touch',\n overscrollBehaviorY: 'contain',\n ...style,\n }}\n >\n {children}\n </div>\n );\n}\n"],"names":["idCounter","nextId","sheets","listeners","emit","l","getSheets","subscribe","listener","addSheet","descriptor","id","entry","removeSheet","s","removeAllSheets","sheetControllers","pendingSnapIndex","pendingOpenFully","registerSheetController","controller","snap","unregisterSheetController","getSheetController","invokeSnapToIndex","index","ctrl","invokeOpenFully","parseSnapValue","value","viewportHeightPx","remPx","trimmed","num","asNumber","getRemPx","root","fontSize","rem","parseSnapPoints","snapPoint","parsed","v","unique","a","b","RUBBERBAND_SCALE_PX","RUBBERBAND_FACTOR_MAX","RUBBERBAND_FACTOR_MIN","rubberbandFactor","over","rubberband","min","max","factor","VELOCITY_THRESHOLD","CLOSE_THRESHOLD","SNAP_PROGRESS_THRESHOLD","getReleaseTarget","currentTranslateY","sheetHeight","snapPointsPx","velocityY","closeOffset","closedPosition","sortedSnaps","firstSnap","firstSnapTranslateY","closedPos","closeZoneStart","closeZoneLength","closeThresholdY","nextSnapDown","findNextSnapDown","nextSnapUp","findNextSnapUp","targetY","idx","currentSnapIndex","findCurrentSnapIndex","getProgressToNextSnap","nextSnap","currentY","currentVisible","i","best","bestDist","d","fromSnap","segment","progress","ScrollContainerContext","createContext","useScrollContainerContext","useContext","findScrollContainer","target","containers","node","useScrollContainerContextValue","containersRef","useRef","registerScrollContainer","useCallback","el","getCanDrag","isInScrollContainer","shouldBlockGestures","canCaptureForDownSwipe","FOCUSABLE_SELECTOR","CLOSE_BUTTON_CLASS","getFocusableElements","container","getFocusableExcludingClose","useFocusTrap","containerRef","enabled","disableAutoFocus","useEffect","previouslyFocused","focusableExcludingClose","focusable","first","handleKeyDown","e","focusableNow","firstNow","lastNow","VIEWPORT_MAX","DRAG_THRESHOLD","getCssVar","name","fallback","getDurationMs","match","matchMs","getEaseCubicBezierY","t","y1","y2","t2","getEasedProgress","easingVar","values","scaleForStackDepth","offsetForStackDepth","BottomSheet","isTop","stackDepth","ctx","BottomSheetContext","Component","componentProps","heightProp","widthProp","className","onClose","enableBackdrop","enableClickBackdropToClose","disableEsc","gestureOnlyOnHandler","disableSwipeDownToClose","effectiveWidth","widthCss","viewportHeight","hasSnapPoints","contentDrivenHeight","sheetRef","handlerRef","contentRef","scrollCtxValue","setSheetHeight","useState","parseHeight","contentHeightMeasured","setContentHeightMeasured","closedY","effectiveSnaps","firstSnapY","translateY","setTranslateY","isDragging","setIsDragging","isAnimating","setIsAnimating","hasOpened","setHasOpened","backdropOpacity","setBackdropOpacity","dragStartRef","lastMoveRef","hasCapturedRef","heightAnimationTimeoutRef","useLayoutEffect","ro","h","prev","updateHeight","sheet","handler","content","style","paddingTop","paddingBottom","gapStr","gapPx","contentEl","contentHeight","firstChild","_a","duration","closeDrawer","startTime","tick","elapsed","snapToIndex","openFully","onKeyDown","flushSync","cleanupDragState","pointerId","handlePointerDownCapture","isTouch","isInContent","handlePointerDown","onPointerUpGlobal","ev","handlePointerMove","delta","threshold","next","maxSnap","minY","handlePointerUp","didCapture","last","result","handlePointerCancel","gestureProps","easing","closingProgress","isRevealingDuringClose","easedProgress","transition","fromScale","toScale","fromOffset","toOffset","stackScale","stackOffsetY","closedYNum","dragProgress","overlayOpacity","overlayTransition","lastOverlayStyleRef","opacity","pointerEvents","jsx","Fragment","jsxs","useSheets","useSyncExternalStore","BottomSheetRoot","width","topSheetClosingProgress","setTopSheetClosingProgress","overlayStyle","setOverlayStyle","registerController","unregisterController","createPortal","top","pushBottomSheet","options","popBottomSheet","closeBottomSheet","closeAllBottomSheets","BottomSheetScrollable","children","scrollRef","touchStartY","onTouchStart","onTouchMove","touch"],"mappings":"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"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
|
|
2
|
+
export { pushBottomSheet, popBottomSheet, closeBottomSheet, closeAllBottomSheets, BottomSheetRoot } from './api';
|
|
3
|
+
export { BottomSheetScrollable } from './components/BottomSheetScrollable';
|
|
4
|
+
export type { BottomSheetInstance, PushOptions, BottomSheetInjectedProps } from './types';
|
|
5
|
+
export type { BottomSheetRootProps } from './api';
|
|
6
|
+
export type { BottomSheetScrollableProps } from './components/BottomSheetScrollable';
|