@patternmode/stacksheet 1.3.8 → 1.4.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/dist/SheetPanel/default-header.d.ts +1 -3
- package/dist/SheetPanel/default-header.d.ts.map +1 -1
- package/dist/SheetPanel/sheet-panel-content.d.ts +1 -2
- package/dist/SheetPanel/sheet-panel-content.d.ts.map +1 -1
- package/dist/SheetPanel/sheet-panel-handles.d.ts +3 -2
- package/dist/SheetPanel/sheet-panel-handles.d.ts.map +1 -1
- package/dist/SheetPanel/sheet-panel-types.d.ts +2 -0
- package/dist/SheetPanel/sheet-panel-types.d.ts.map +1 -1
- package/dist/SheetPanel/sheet-panel.d.ts.map +1 -1
- package/dist/SheetParts/sheet-handle.d.ts +1 -1
- package/dist/SheetParts/sheet-handle.d.ts.map +1 -1
- package/dist/SheetParts/sheet-header.d.ts.map +1 -1
- package/dist/SheetParts/sheet-parts.d.ts +1 -1
- package/dist/config.d.ts.map +1 -1
- package/dist/index.mjs +155 -52
- package/dist/index.mjs.map +1 -1
- package/dist/renderer-effects.d.ts +12 -0
- package/dist/renderer-effects.d.ts.map +1 -1
- package/dist/renderer-helpers.d.ts +2 -2
- package/dist/renderer-helpers.d.ts.map +1 -1
- package/dist/renderer.d.ts.map +1 -1
- package/dist/stacking.d.ts +6 -0
- package/dist/stacking.d.ts.map +1 -1
- package/dist/styles.css +1 -1
- package/dist/types.d.ts +30 -1
- package/dist/types.d.ts.map +1 -1
- package/package.json +1 -1
|
@@ -1,5 +1,3 @@
|
|
|
1
1
|
import type { HeaderRenderProps } from "../types";
|
|
2
|
-
export declare const DefaultHeader: ({ isNested, onBack, onClose
|
|
3
|
-
className?: string;
|
|
4
|
-
}) => import("react").JSX.Element;
|
|
2
|
+
export declare const DefaultHeader: ({ isNested, onBack, onClose }: HeaderRenderProps) => import("react").JSX.Element;
|
|
5
3
|
//# sourceMappingURL=default-header.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"default-header.d.ts","sourceRoot":"","sources":["../../src/SheetPanel/default-header.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,UAAU,CAAC;
|
|
1
|
+
{"version":3,"file":"default-header.d.ts","sourceRoot":"","sources":["../../src/SheetPanel/default-header.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,UAAU,CAAC;AAIlD,eAAO,MAAM,aAAa,GAAI,+BAA+B,iBAAiB,gCAqB7E,CAAC"}
|
|
@@ -1,14 +1,13 @@
|
|
|
1
1
|
import type { ComponentType, ReactNode } from "react";
|
|
2
2
|
import type { HeaderRenderProps } from "../types";
|
|
3
3
|
export declare const PanelInnerContent: {
|
|
4
|
-
({ isComposable, shouldRender, Content, data, renderHeader, headerProps,
|
|
4
|
+
({ isComposable, shouldRender, Content, data, renderHeader, headerProps, }: {
|
|
5
5
|
isComposable: boolean;
|
|
6
6
|
shouldRender: boolean;
|
|
7
7
|
Content: ComponentType<Record<string, unknown>> | undefined;
|
|
8
8
|
data: Record<string, unknown>;
|
|
9
9
|
renderHeader?: false | ((props: HeaderRenderProps) => ReactNode);
|
|
10
10
|
headerProps: HeaderRenderProps;
|
|
11
|
-
headerClassName: string | undefined;
|
|
12
11
|
}): import("react").JSX.Element | null;
|
|
13
12
|
displayName: string;
|
|
14
13
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sheet-panel-content.d.ts","sourceRoot":"","sources":["../../src/SheetPanel/sheet-panel-content.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAEtD,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,UAAU,CAAC;AAGlD,eAAO,MAAM,iBAAiB;
|
|
1
|
+
{"version":3,"file":"sheet-panel-content.d.ts","sourceRoot":"","sources":["../../src/SheetPanel/sheet-panel-content.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAEtD,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,UAAU,CAAC;AAGlD,eAAO,MAAM,iBAAiB;gFAO3B;QACD,YAAY,EAAE,OAAO,CAAC;QACtB,YAAY,EAAE,OAAO,CAAC;QACtB,OAAO,EAAE,aAAa,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,GAAG,SAAS,CAAC;QAC5D,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;QAC9B,YAAY,CAAC,EAAE,KAAK,GAAG,CAAC,CAAC,KAAK,EAAE,iBAAiB,KAAK,SAAS,CAAC,CAAC;QACjE,WAAW,EAAE,iBAAiB,CAAC;KAChC;;CAoBA,CAAC"}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
import type { Side } from "../types";
|
|
2
|
-
export declare const BottomHandle: ({ onDismiss }: {
|
|
1
|
+
import type { HandlePosition, Side } from "../types";
|
|
2
|
+
export declare const BottomHandle: ({ onDismiss, position, }: {
|
|
3
3
|
onDismiss?: () => void;
|
|
4
|
+
position?: HandlePosition;
|
|
4
5
|
}) => import("react").JSX.Element;
|
|
5
6
|
export declare const SideHandle: ({ side, isHovered, onDismiss, }: {
|
|
6
7
|
side: Side;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sheet-panel-handles.d.ts","sourceRoot":"","sources":["../../src/SheetPanel/sheet-panel-handles.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"sheet-panel-handles.d.ts","sourceRoot":"","sources":["../../src/SheetPanel/sheet-panel-handles.tsx"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,cAAc,EAAE,IAAI,EAAE,MAAM,UAAU,CAAC;AAErD,eAAO,MAAM,YAAY,GAAI,0BAG1B;IACD,SAAS,CAAC,EAAE,MAAM,IAAI,CAAC;IACvB,QAAQ,CAAC,EAAE,cAAc,CAAC;CAC3B,gCAiBA,CAAC;AACF,eAAO,MAAM,UAAU,GAAI,iCAIxB;IACD,IAAI,EAAE,IAAI,CAAC;IACX,SAAS,EAAE,OAAO,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,IAAI,CAAC;CACxB,gCAgBA,CAAC"}
|
|
@@ -13,6 +13,8 @@ export interface SheetPanelProps {
|
|
|
13
13
|
isNested: boolean;
|
|
14
14
|
isTop: boolean;
|
|
15
15
|
item: SheetItem;
|
|
16
|
+
/** On-screen keyboard height (px) to lift bottom sheets above; 0 when inactive. */
|
|
17
|
+
keyboardInset: number;
|
|
16
18
|
layout?: StacksheetLayout;
|
|
17
19
|
onSnap: (index: number) => void;
|
|
18
20
|
pop: () => void;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sheet-panel-types.d.ts","sourceRoot":"","sources":["../../src/SheetPanel/sheet-panel-types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAEtD,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,qBAAqB,CAAC;AAC9D,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAC/C,OAAO,KAAK,EACV,iBAAiB,EACjB,cAAc,EACd,SAAS,EACT,IAAI,EACJ,gBAAgB,EACjB,MAAM,UAAU,CAAC;AAElB,MAAM,WAAW,eAAe;IAC9B,eAAe,EAAE,MAAM,CAAC;IACxB,OAAO,EAAE,aAAa,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,GAAG,SAAS,CAAC;IAC5D,UAAU,EAAE,kBAAkB,CAAC;IAC/B,KAAK,EAAE,MAAM,IAAI,CAAC;IAClB,MAAM,EAAE,cAAc,CAAC;IACvB,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,OAAO,CAAC;IAClB,KAAK,EAAE,OAAO,CAAC;IACf,IAAI,EAAE,SAAS,CAAC;IAChB,MAAM,CAAC,EAAE,gBAAgB,CAAC;IAC1B,MAAM,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IAChC,GAAG,EAAE,MAAM,IAAI,CAAC;IAChB,oBAAoB,EAAE,OAAO,CAAC;IAC9B,YAAY,CAAC,EAAE,KAAK,GAAG,CAAC,CAAC,KAAK,EAAE,iBAAiB,KAAK,SAAS,CAAC,CAAC;IACjE,YAAY,EAAE,OAAO,CAAC;IACtB,IAAI,EAAE,IAAI,CAAC;IACX,SAAS,EAAE,WAAW,CAAC;IACvB,WAAW,EAAE,WAAW,CAAC;IACzB,WAAW,EAAE,MAAM,EAAE,CAAC;IACtB,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAChC,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACrC,UAAU,EAAE,MAAM,IAAI,CAAC;IACvB,QAAQ,EAAE,MAAM,IAAI,CAAC;CACtB"}
|
|
1
|
+
{"version":3,"file":"sheet-panel-types.d.ts","sourceRoot":"","sources":["../../src/SheetPanel/sheet-panel-types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAEtD,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,qBAAqB,CAAC;AAC9D,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAC/C,OAAO,KAAK,EACV,iBAAiB,EACjB,cAAc,EACd,SAAS,EACT,IAAI,EACJ,gBAAgB,EACjB,MAAM,UAAU,CAAC;AAElB,MAAM,WAAW,eAAe;IAC9B,eAAe,EAAE,MAAM,CAAC;IACxB,OAAO,EAAE,aAAa,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,GAAG,SAAS,CAAC;IAC5D,UAAU,EAAE,kBAAkB,CAAC;IAC/B,KAAK,EAAE,MAAM,IAAI,CAAC;IAClB,MAAM,EAAE,cAAc,CAAC;IACvB,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,OAAO,CAAC;IAClB,KAAK,EAAE,OAAO,CAAC;IACf,IAAI,EAAE,SAAS,CAAC;IAChB,mFAAmF;IACnF,aAAa,EAAE,MAAM,CAAC;IACtB,MAAM,CAAC,EAAE,gBAAgB,CAAC;IAC1B,MAAM,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IAChC,GAAG,EAAE,MAAM,IAAI,CAAC;IAChB,oBAAoB,EAAE,OAAO,CAAC;IAC9B,YAAY,CAAC,EAAE,KAAK,GAAG,CAAC,CAAC,KAAK,EAAE,iBAAiB,KAAK,SAAS,CAAC,CAAC;IACjE,YAAY,EAAE,OAAO,CAAC;IACtB,IAAI,EAAE,IAAI,CAAC;IACX,SAAS,EAAE,WAAW,CAAC;IACvB,WAAW,EAAE,WAAW,CAAC;IACzB,WAAW,EAAE,MAAM,EAAE,CAAC;IACtB,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAChC,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACrC,UAAU,EAAE,MAAM,IAAI,CAAC;IACvB,QAAQ,EAAE,MAAM,IAAI,CAAC;CACtB"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sheet-panel.d.ts","sourceRoot":"","sources":["../../src/SheetPanel/sheet-panel.tsx"],"names":[],"mappings":"AA+BA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAC;
|
|
1
|
+
{"version":3,"file":"sheet-panel.d.ts","sourceRoot":"","sources":["../../src/SheetPanel/sheet-panel.tsx"],"names":[],"mappings":"AA+BA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAC;AA8U3D,eAAO,MAAM,UAAU,GAAI,OAAO,eAAe,gCAkFhD,CAAC"}
|
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
import type { SheetOptionalContentPartProps } from "./sheet-part-types";
|
|
2
|
-
export declare const SheetHandle: ({ asChild, className, style, children, }: SheetOptionalContentPartProps) => import("react").JSX.Element;
|
|
2
|
+
export declare const SheetHandle: ({ asChild, className, style, children, }: SheetOptionalContentPartProps) => import("react").JSX.Element | null;
|
|
3
3
|
//# sourceMappingURL=sheet-handle.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sheet-handle.d.ts","sourceRoot":"","sources":["../../src/SheetParts/sheet-handle.tsx"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,6BAA6B,EAAE,MAAM,oBAAoB,CAAC;AAExE,eAAO,MAAM,WAAW,GAAI,0CAKzB,6BAA6B,
|
|
1
|
+
{"version":3,"file":"sheet-handle.d.ts","sourceRoot":"","sources":["../../src/SheetParts/sheet-handle.tsx"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,6BAA6B,EAAE,MAAM,oBAAoB,CAAC;AAExE,eAAO,MAAM,WAAW,GAAI,0CAKzB,6BAA6B,uCA0B/B,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sheet-header.d.ts","sourceRoot":"","sources":["../../src/SheetParts/sheet-header.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AAEzD,eAAO,MAAM,WAAW,GAAI,yCAAyC,cAAc,
|
|
1
|
+
{"version":3,"file":"sheet-header.d.ts","sourceRoot":"","sources":["../../src/SheetParts/sheet-header.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AAEzD,eAAO,MAAM,WAAW,GAAI,yCAAyC,cAAc,gCAWlF,CAAC"}
|
|
@@ -13,7 +13,7 @@ export declare const Sheet: {
|
|
|
13
13
|
readonly Close: ({ asChild, className, style, children, }: import("./sheet-part-types").SheetOptionalContentPartProps) => import("react").JSX.Element;
|
|
14
14
|
readonly Description: ({ asChild, className, style, children }: import("./sheet-part-types").SheetPartProps) => import("react").JSX.Element;
|
|
15
15
|
readonly Footer: ({ asChild, className, style, children }: import("./sheet-part-types").SheetPartProps) => import("react").JSX.Element;
|
|
16
|
-
readonly Handle: ({ asChild, className, style, children, }: import("./sheet-part-types").SheetOptionalContentPartProps) => import("react").JSX.Element;
|
|
16
|
+
readonly Handle: ({ asChild, className, style, children, }: import("./sheet-part-types").SheetOptionalContentPartProps) => import("react").JSX.Element | null;
|
|
17
17
|
readonly Header: ({ asChild, className, style, children }: import("./sheet-part-types").SheetPartProps) => import("react").JSX.Element;
|
|
18
18
|
readonly Title: ({ asChild, className, style, children }: import("./sheet-part-types").SheetPartProps) => import("react").JSX.Element;
|
|
19
19
|
};
|
package/dist/config.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EACV,cAAc,EAKd,gBAAgB,EACjB,MAAM,SAAS,CAAC;
|
|
1
|
+
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EACV,cAAc,EAKd,gBAAgB,EACjB,MAAM,SAAS,CAAC;AAoDjB,wGAAwG;AACxG,eAAO,MAAM,aAAa,GAAI,SAAQ,gBAAqB,KAAG,cAa7D,CAAC"}
|
package/dist/index.mjs
CHANGED
|
@@ -56,10 +56,12 @@ const DEFAULT_CONFIG = {
|
|
|
56
56
|
closeThreshold: .25,
|
|
57
57
|
dismissible: true,
|
|
58
58
|
drag: true,
|
|
59
|
+
handle: "inside",
|
|
59
60
|
lockScroll: true,
|
|
60
61
|
maxDepth: Number.POSITIVE_INFINITY,
|
|
61
62
|
maxWidth: "90vw",
|
|
62
63
|
modal: true,
|
|
64
|
+
repositionInputs: true,
|
|
63
65
|
scaleBackgroundAmount: .97,
|
|
64
66
|
shouldScaleBackground: false,
|
|
65
67
|
showOverlay: true,
|
|
@@ -169,6 +171,79 @@ const useViewportHeight = (active) => {
|
|
|
169
171
|
}, []);
|
|
170
172
|
return active ? height ?? 0 : 0;
|
|
171
173
|
};
|
|
174
|
+
/** Input types that don't summon the on-screen keyboard. */
|
|
175
|
+
const NON_TEXT_INPUT_TYPES = new Set([
|
|
176
|
+
"button",
|
|
177
|
+
"checkbox",
|
|
178
|
+
"color",
|
|
179
|
+
"file",
|
|
180
|
+
"hidden",
|
|
181
|
+
"image",
|
|
182
|
+
"radio",
|
|
183
|
+
"range",
|
|
184
|
+
"reset",
|
|
185
|
+
"submit"
|
|
186
|
+
]);
|
|
187
|
+
/** True for elements whose focus raises the on-screen keyboard. */
|
|
188
|
+
const isEditableElement = (el) => {
|
|
189
|
+
if (!(el instanceof HTMLElement)) return false;
|
|
190
|
+
if (el.isContentEditable) return true;
|
|
191
|
+
if (el instanceof HTMLTextAreaElement) return true;
|
|
192
|
+
if (el instanceof HTMLInputElement) return !NON_TEXT_INPUT_TYPES.has(el.type);
|
|
193
|
+
return false;
|
|
194
|
+
};
|
|
195
|
+
/**
|
|
196
|
+
* Height (px) the on-screen keyboard occupies while a field inside `containerRef`
|
|
197
|
+
* is focused, else `0`. Derived from the gap between the layout viewport and the
|
|
198
|
+
* (keyboard-shrunk, possibly panned) visual viewport.
|
|
199
|
+
*
|
|
200
|
+
* Focus-gated to fields *inside the container* so unrelated `visualViewport`
|
|
201
|
+
* changes — Android URL-bar collapse, or typing into the page behind a
|
|
202
|
+
* non-modal sheet — don't move the sheet, and zero while pinch-zoomed since a
|
|
203
|
+
* shrunk visual viewport then isn't a keyboard. rAF-throttled because iOS
|
|
204
|
+
* fires many resize events over the keyboard's open animation.
|
|
205
|
+
*/
|
|
206
|
+
const useKeyboardInset = (active, containerRef) => {
|
|
207
|
+
const [inset, setInset] = useState(0);
|
|
208
|
+
useEffect(() => {
|
|
209
|
+
const canListen = active && typeof window !== "undefined";
|
|
210
|
+
const container = containerRef.current;
|
|
211
|
+
const viewport = canListen ? window.visualViewport : void 0;
|
|
212
|
+
let frame = 0;
|
|
213
|
+
let scheduled = false;
|
|
214
|
+
const measure = () => {
|
|
215
|
+
const el = document.activeElement;
|
|
216
|
+
const focused = isEditableElement(el) && container !== null && container.contains(el);
|
|
217
|
+
const zoomed = (viewport?.scale ?? 1) > 1;
|
|
218
|
+
const visibleHeight = viewport?.height ?? window.innerHeight;
|
|
219
|
+
const gap = window.innerHeight - (viewport?.offsetTop ?? 0) - visibleHeight;
|
|
220
|
+
setInset(focused && !zoomed ? Math.max(0, gap) : 0);
|
|
221
|
+
};
|
|
222
|
+
const schedule = () => {
|
|
223
|
+
if (scheduled) return;
|
|
224
|
+
scheduled = true;
|
|
225
|
+
frame = window.requestAnimationFrame(() => {
|
|
226
|
+
scheduled = false;
|
|
227
|
+
measure();
|
|
228
|
+
});
|
|
229
|
+
};
|
|
230
|
+
if (canListen) {
|
|
231
|
+
container?.addEventListener("focusin", schedule);
|
|
232
|
+
container?.addEventListener("focusout", schedule);
|
|
233
|
+
viewport?.addEventListener("resize", schedule, { passive: true });
|
|
234
|
+
viewport?.addEventListener("scroll", schedule, { passive: true });
|
|
235
|
+
schedule();
|
|
236
|
+
}
|
|
237
|
+
return () => {
|
|
238
|
+
if (frame !== 0) window.cancelAnimationFrame(frame);
|
|
239
|
+
container?.removeEventListener("focusin", schedule);
|
|
240
|
+
container?.removeEventListener("focusout", schedule);
|
|
241
|
+
viewport?.removeEventListener("resize", schedule);
|
|
242
|
+
viewport?.removeEventListener("scroll", schedule);
|
|
243
|
+
};
|
|
244
|
+
}, [active, containerRef]);
|
|
245
|
+
return active ? inset : 0;
|
|
246
|
+
};
|
|
172
247
|
const BODY_SCALE_TRANSITION = "transform 500ms cubic-bezier(0.32, 0.72, 0, 1), border-radius 500ms cubic-bezier(0.32, 0.72, 0, 1)";
|
|
173
248
|
/** Fallback delay (transition duration + margin) if `transitionend` never fires. */
|
|
174
249
|
const BODY_SCALE_RESET_FALLBACK_MS = 600;
|
|
@@ -319,14 +394,12 @@ const getSnapOffset = (snapIndex, snapHeights, panelHeight) => {
|
|
|
319
394
|
//#region src/renderer-helpers.ts
|
|
320
395
|
const EMPTY_CLASSNAMES = {
|
|
321
396
|
backdrop: "",
|
|
322
|
-
header: "",
|
|
323
397
|
panel: ""
|
|
324
398
|
};
|
|
325
399
|
const resolveClassNames = (cn) => {
|
|
326
400
|
if (!cn) return EMPTY_CLASSNAMES;
|
|
327
401
|
return {
|
|
328
402
|
backdrop: cn.backdrop ?? "",
|
|
329
|
-
header: cn.header ?? "",
|
|
330
403
|
panel: cn.panel ?? ""
|
|
331
404
|
};
|
|
332
405
|
};
|
|
@@ -358,8 +431,21 @@ const VISUAL_TWEEN = {
|
|
|
358
431
|
const SHADOW_SM = "0px 1px 3px 0px rgba(0,0,0,0.06), 0px 6px 12px 0px rgba(0,0,0,0.06)";
|
|
359
432
|
const SHADOW_LG = "0px 8px 24px 0px rgba(0,0,0,0.06), 0px 24px 48px 0px rgba(0,0,0,0.04), 0px 48px 96px 0px rgba(0,0,0,0.03)";
|
|
360
433
|
const getShadow = (isNested) => isNested ? SHADOW_SM : SHADOW_LG;
|
|
361
|
-
|
|
434
|
+
/**
|
|
435
|
+
* Clear the on-screen keyboard. Plain sheets stay anchored at bottom: 0 and
|
|
436
|
+
* pad their content up instead — the panel surface extends under the keyboard
|
|
437
|
+
* (and iOS Safari's floating URL-pill chrome), so no backdrop gap ever shows
|
|
438
|
+
* between sheet and keyboard, and measurement error hides behind the keyboard.
|
|
439
|
+
* Snap sheets are transform-anchored, so they lift via `bottom` (not the
|
|
440
|
+
* Motion `y` transform) and keep their viewport-driven sizing untouched.
|
|
441
|
+
*/
|
|
442
|
+
const getKeyboardClearance = (keyboardInset, padForKeyboard) => {
|
|
443
|
+
if (keyboardInset <= 0) return {};
|
|
444
|
+
return padForKeyboard ? { paddingBottom: keyboardInset } : { bottom: keyboardInset };
|
|
445
|
+
};
|
|
446
|
+
const buildPanelStyle = (panelStyles, isTop, hasPanelClass, isDragging, keyboardInset, padForKeyboard) => ({
|
|
362
447
|
...panelStyles,
|
|
448
|
+
...getKeyboardClearance(keyboardInset, padForKeyboard),
|
|
363
449
|
pointerEvents: isTop ? "auto" : "none",
|
|
364
450
|
...isTop ? {} : { contain: "layout style paint" },
|
|
365
451
|
...isDragging ? { transition: "none" } : {},
|
|
@@ -742,6 +828,12 @@ const useSheetPanel = () => {
|
|
|
742
828
|
//#endregion
|
|
743
829
|
//#region src/stacking.ts
|
|
744
830
|
/**
|
|
831
|
+
* Resting height of a bottom sheet. `dvh` tracks the dynamic viewport on iOS
|
|
832
|
+
* Safari (accounts for browser chrome). Shared so the keyboard-inset `calc()`
|
|
833
|
+
* in `buildPanelStyle` can't drift from the panel's base height.
|
|
834
|
+
*/
|
|
835
|
+
const BOTTOM_SHEET_HEIGHT = "85dvh";
|
|
836
|
+
/**
|
|
745
837
|
* Compute visual transforms for a panel at a given depth.
|
|
746
838
|
* depth=0 is the top (foreground) panel.
|
|
747
839
|
* Panels beyond renderThreshold are clamped to the edge position and faded out.
|
|
@@ -818,6 +910,7 @@ const getPanelStyles = (side, config, index) => {
|
|
|
818
910
|
const base = {
|
|
819
911
|
display: "flex",
|
|
820
912
|
flexDirection: "column",
|
|
913
|
+
outline: "none",
|
|
821
914
|
position: "fixed",
|
|
822
915
|
transformOrigin: getTransformOrigin(side),
|
|
823
916
|
willChange: "transform",
|
|
@@ -826,9 +919,9 @@ const getPanelStyles = (side, config, index) => {
|
|
|
826
919
|
if (side === "bottom") return {
|
|
827
920
|
...base,
|
|
828
921
|
bottom: 0,
|
|
829
|
-
height:
|
|
922
|
+
height: BOTTOM_SHEET_HEIGHT,
|
|
830
923
|
left: 0,
|
|
831
|
-
maxHeight:
|
|
924
|
+
maxHeight: BOTTOM_SHEET_HEIGHT,
|
|
832
925
|
right: 0
|
|
833
926
|
};
|
|
834
927
|
const sideStyles = side === "right" ? {
|
|
@@ -876,34 +969,25 @@ const XIcon = () => /* @__PURE__ */ jsx("svg", {
|
|
|
876
969
|
});
|
|
877
970
|
//#endregion
|
|
878
971
|
//#region src/SheetPanel/default-header.tsx
|
|
879
|
-
const DefaultHeader = ({ isNested, onBack, onClose
|
|
880
|
-
|
|
881
|
-
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
|
|
892
|
-
className: "flex min-h-11 min-w-11 shrink-0 cursor-pointer items-center justify-center rounded-full border-none bg-black/5 p-0 text-inherit opacity-70 transition-opacity duration-150 hover:opacity-100",
|
|
893
|
-
onClick: onClose,
|
|
894
|
-
type: "button",
|
|
895
|
-
children: /* @__PURE__ */ jsx(XIcon, {})
|
|
896
|
-
})]
|
|
897
|
-
});
|
|
972
|
+
const DefaultHeader = ({ isNested, onBack, onClose }) => /* @__PURE__ */ jsxs(Fragment, { children: [isNested && /* @__PURE__ */ jsx("button", {
|
|
973
|
+
"aria-label": "Back",
|
|
974
|
+
className: "absolute left-2 top-2 z-20 flex min-h-11 min-w-11 cursor-pointer items-center justify-center rounded-md border-none bg-transparent p-0 text-inherit opacity-50 transition-opacity duration-150 hover:opacity-100",
|
|
975
|
+
onClick: onBack,
|
|
976
|
+
type: "button",
|
|
977
|
+
children: /* @__PURE__ */ jsx(ArrowLeftIcon, {})
|
|
978
|
+
}), /* @__PURE__ */ jsx("button", {
|
|
979
|
+
"aria-label": "Close",
|
|
980
|
+
className: "absolute right-2 top-2 z-20 flex min-h-11 min-w-11 cursor-pointer items-center justify-center rounded-md border-none bg-transparent p-0 text-inherit opacity-50 transition-opacity duration-150 hover:opacity-100",
|
|
981
|
+
onClick: onClose,
|
|
982
|
+
type: "button",
|
|
983
|
+
children: /* @__PURE__ */ jsx(XIcon, {})
|
|
984
|
+
})] });
|
|
898
985
|
//#endregion
|
|
899
986
|
//#region src/SheetPanel/sheet-panel-content.tsx
|
|
900
|
-
const PanelInnerContent = ({ isComposable, shouldRender, Content, data, renderHeader, headerProps
|
|
987
|
+
const PanelInnerContent = ({ isComposable, shouldRender, Content, data, renderHeader, headerProps }) => {
|
|
901
988
|
if (isComposable) return shouldRender && Content !== void 0 ? /* @__PURE__ */ jsx(Content, { ...data }) : null;
|
|
902
989
|
const customHeader = renderHeader !== void 0 && renderHeader !== false ? renderHeader : void 0;
|
|
903
|
-
return /* @__PURE__ */ jsxs(Fragment, { children: [customHeader === void 0 ? /* @__PURE__ */ jsx(DefaultHeader, {
|
|
904
|
-
...headerProps,
|
|
905
|
-
className: headerClassName
|
|
906
|
-
}) : customHeader(headerProps), shouldRender && Content !== void 0 && /* @__PURE__ */ jsx("div", {
|
|
990
|
+
return /* @__PURE__ */ jsxs(Fragment, { children: [customHeader === void 0 ? /* @__PURE__ */ jsx(DefaultHeader, { ...headerProps }) : customHeader(headerProps), shouldRender && Content !== void 0 && /* @__PURE__ */ jsx("div", {
|
|
907
991
|
className: "min-h-0 flex-1 overflow-y-auto overscroll-contain",
|
|
908
992
|
"data-stacksheet-no-drag": "",
|
|
909
993
|
children: /* @__PURE__ */ jsx(Content, { ...data })
|
|
@@ -955,9 +1039,9 @@ const ModalFocusTrap = ({ enabled, active, fallbackRef, children }) => {
|
|
|
955
1039
|
};
|
|
956
1040
|
//#endregion
|
|
957
1041
|
//#region src/SheetPanel/sheet-panel-handles.tsx
|
|
958
|
-
const BottomHandle = ({ onDismiss }) => /* @__PURE__ */ jsx("button", {
|
|
1042
|
+
const BottomHandle = ({ onDismiss, position = "inside" }) => /* @__PURE__ */ jsx("button", {
|
|
959
1043
|
"aria-label": "Dismiss",
|
|
960
|
-
className: "absolute inset-x-0
|
|
1044
|
+
className: joinClassNames("absolute inset-x-0 z-10 flex w-full cursor-grab touch-none items-center justify-center border-none bg-transparent text-inherit", position === "outside" ? "bottom-full pt-1 pb-2" : "top-0 pt-2.5 pb-2"),
|
|
961
1045
|
"data-stacksheet-handle": "",
|
|
962
1046
|
onClick: onDismiss,
|
|
963
1047
|
type: "button",
|
|
@@ -1036,7 +1120,10 @@ const getOptionalSideHandle = ({ isHovered, onDismiss, show, side }) => show ? /
|
|
|
1036
1120
|
onDismiss,
|
|
1037
1121
|
side
|
|
1038
1122
|
}) : null;
|
|
1039
|
-
const getOptionalBottomHandle = (show, onDismiss) => show ? /* @__PURE__ */ jsx(BottomHandle, {
|
|
1123
|
+
const getOptionalBottomHandle = (show, onDismiss, position) => show ? /* @__PURE__ */ jsx(BottomHandle, {
|
|
1124
|
+
onDismiss,
|
|
1125
|
+
position
|
|
1126
|
+
}) : null;
|
|
1040
1127
|
const completeOpeningAnimation = (hasEnteredRef, isTop, onOpenCompleteRef) => {
|
|
1041
1128
|
if (isTop && !hasEnteredRef.current) {
|
|
1042
1129
|
hasEnteredRef.current = true;
|
|
@@ -1118,7 +1205,7 @@ const useSheetPanelContext = ({ close, isNested, isTop, pop, side }, panelId) =>
|
|
|
1118
1205
|
};
|
|
1119
1206
|
};
|
|
1120
1207
|
const useSheetPanelModel = (props) => {
|
|
1121
|
-
const { item, index, depth, isTop, isNested, side, config, classNames, pop, close, snapHeights, activeSnapIndex, layout, renderHeader, slideFrom, slideTarget, spring, stackSpring } = props;
|
|
1208
|
+
const { item, index, depth, isTop, isNested, side, config, classNames, pop, close, snapHeights, keyboardInset, activeSnapIndex, layout, renderHeader, slideFrom, slideTarget, spring, stackSpring } = props;
|
|
1122
1209
|
const panelRef = useRef(null);
|
|
1123
1210
|
const [isHovered, setIsHovered] = useState(false);
|
|
1124
1211
|
const measuredHeight = usePanelHeight(panelRef, snapHeights.length > 0);
|
|
@@ -1132,7 +1219,8 @@ const useSheetPanelModel = (props) => {
|
|
|
1132
1219
|
const isComposable = resolvePanelLayout(layout, renderHeader) === "composable";
|
|
1133
1220
|
const hasPanelClass = classNames.panel !== "";
|
|
1134
1221
|
const dragOffset = getDragTransform(side, dragState.offset);
|
|
1135
|
-
const
|
|
1222
|
+
const activeKeyboardInset = isTop && side === "bottom" ? keyboardInset : 0;
|
|
1223
|
+
const panelStyle = buildPanelStyle(panelStyles, isTop, hasPanelClass, dragState.isDragging, activeKeyboardInset, snapHeights.length === 0);
|
|
1136
1224
|
const headerProps = getHeaderProps({
|
|
1137
1225
|
close,
|
|
1138
1226
|
isNested,
|
|
@@ -1155,7 +1243,7 @@ const useSheetPanelModel = (props) => {
|
|
|
1155
1243
|
const animateTarget = buildAnimateTarget(slideTarget, getStackOffset(side, transform.offset), dragOffset, transform, animatedRadius, transition, snapYOffset, isTop);
|
|
1156
1244
|
const initialRadius = getInitialRadius(side);
|
|
1157
1245
|
const showSideHandle = isTop && side !== "bottom";
|
|
1158
|
-
const showBottomHandle = isTop && side === "bottom";
|
|
1246
|
+
const showBottomHandle = isTop && side === "bottom" && !isComposable;
|
|
1159
1247
|
const dismiss = isNested ? pop : close;
|
|
1160
1248
|
const sideHandle = getOptionalSideHandle({
|
|
1161
1249
|
isHovered,
|
|
@@ -1166,7 +1254,8 @@ const useSheetPanelModel = (props) => {
|
|
|
1166
1254
|
return {
|
|
1167
1255
|
animateTarget,
|
|
1168
1256
|
ariaProps,
|
|
1169
|
-
bottomHandle: getOptionalBottomHandle(showBottomHandle, dismiss),
|
|
1257
|
+
bottomHandle: getOptionalBottomHandle(showBottomHandle, dismiss, config.handle),
|
|
1258
|
+
bottomHandleOutside: showBottomHandle && config.handle === "outside",
|
|
1170
1259
|
handleAnimationComplete,
|
|
1171
1260
|
headerProps,
|
|
1172
1261
|
hoverProps: getPanelHoverProps(showSideHandle, setIsHovered),
|
|
@@ -1182,7 +1271,7 @@ const useSheetPanelModel = (props) => {
|
|
|
1182
1271
|
};
|
|
1183
1272
|
const SheetPanel = (props) => {
|
|
1184
1273
|
const { item, isTop, config, classNames, Content, shouldRender, renderHeader, prefersReducedMotion } = props;
|
|
1185
|
-
const { animateTarget, ariaProps, bottomHandle, handleAnimationComplete, headerProps, hoverProps, inactivePanelProps, initialRadius, isComposable, panelContext, panelRef, panelStyle, resolvedSlideFrom, sideHandle } = useSheetPanelModel(props);
|
|
1274
|
+
const { animateTarget, ariaProps, bottomHandle, bottomHandleOutside, handleAnimationComplete, headerProps, hoverProps, inactivePanelProps, initialRadius, isComposable, panelContext, panelRef, panelStyle, resolvedSlideFrom, sideHandle } = useSheetPanelModel(props);
|
|
1186
1275
|
const panelContent = /* @__PURE__ */ jsxs(m.div, {
|
|
1187
1276
|
animate: animateTarget,
|
|
1188
1277
|
className: classNames.panel || void 0,
|
|
@@ -1210,18 +1299,21 @@ const SheetPanel = (props) => {
|
|
|
1210
1299
|
...hoverProps,
|
|
1211
1300
|
...inactivePanelProps,
|
|
1212
1301
|
...ariaProps,
|
|
1213
|
-
children: [
|
|
1214
|
-
|
|
1215
|
-
|
|
1216
|
-
|
|
1217
|
-
|
|
1218
|
-
|
|
1219
|
-
|
|
1220
|
-
|
|
1221
|
-
|
|
1222
|
-
|
|
1223
|
-
|
|
1224
|
-
|
|
1302
|
+
children: [
|
|
1303
|
+
sideHandle,
|
|
1304
|
+
bottomHandleOutside ? bottomHandle : null,
|
|
1305
|
+
/* @__PURE__ */ jsxs("div", {
|
|
1306
|
+
className: "relative flex min-h-0 flex-1 flex-col overflow-hidden rounded-[inherit]",
|
|
1307
|
+
children: [bottomHandleOutside ? null : bottomHandle, /* @__PURE__ */ jsx(PanelInnerContent, {
|
|
1308
|
+
Content,
|
|
1309
|
+
data: item.data,
|
|
1310
|
+
headerProps,
|
|
1311
|
+
isComposable,
|
|
1312
|
+
renderHeader,
|
|
1313
|
+
shouldRender
|
|
1314
|
+
})]
|
|
1315
|
+
})
|
|
1316
|
+
]
|
|
1225
1317
|
}, item.id);
|
|
1226
1318
|
return /* @__PURE__ */ jsx(SheetPanelContext.Provider, {
|
|
1227
1319
|
value: panelContext,
|
|
@@ -1308,6 +1400,13 @@ const useSnapState = (config, isOpen, side, stack) => {
|
|
|
1308
1400
|
snapHeights
|
|
1309
1401
|
};
|
|
1310
1402
|
};
|
|
1403
|
+
const usePanelKeyboardInset = (config, isOpen, side) => {
|
|
1404
|
+
const panelWrapperRef = useRef(null);
|
|
1405
|
+
return {
|
|
1406
|
+
keyboardInset: useKeyboardInset(isOpen && side === "bottom" && config.repositionInputs, panelWrapperRef),
|
|
1407
|
+
panelWrapperRef
|
|
1408
|
+
};
|
|
1409
|
+
};
|
|
1311
1410
|
const useCloseControls = (rawClose, rawPop) => {
|
|
1312
1411
|
const closeReasonRef = useRef("programmatic");
|
|
1313
1412
|
const closeWith = (reason) => {
|
|
@@ -1422,6 +1521,7 @@ const SheetRenderer = ({ store, config, sheets, componentMap, classNames: classN
|
|
|
1422
1521
|
const classNames = resolveClassNames(classNamesProp);
|
|
1423
1522
|
const { activeSnapIndex, handleSnap, snapHeights } = useSnapState(config, isOpen, side, stack);
|
|
1424
1523
|
const { close, closeReasonRef, closeWith, pop, popWith } = useCloseControls(rawClose, rawPop);
|
|
1524
|
+
const { panelWrapperRef, keyboardInset } = usePanelKeyboardInset(config, isOpen, side);
|
|
1425
1525
|
useBodyScale(config, isOpen, prefersReducedMotion);
|
|
1426
1526
|
useFocusRestore(isOpen);
|
|
1427
1527
|
useDismissalEffects({
|
|
@@ -1467,6 +1567,7 @@ const SheetRenderer = ({ store, config, sheets, componentMap, classNames: classN
|
|
|
1467
1567
|
}), /* @__PURE__ */ jsx(RemoveScroll, {
|
|
1468
1568
|
enabled: shouldLockScroll,
|
|
1469
1569
|
forwardProps: true,
|
|
1570
|
+
ref: panelWrapperRef,
|
|
1470
1571
|
children: /* @__PURE__ */ jsx("div", {
|
|
1471
1572
|
className: "pointer-events-none fixed inset-0 overflow-hidden",
|
|
1472
1573
|
style: { zIndex: config.zIndex + 1 },
|
|
@@ -1488,6 +1589,7 @@ const SheetRenderer = ({ store, config, sheets, componentMap, classNames: classN
|
|
|
1488
1589
|
isNested,
|
|
1489
1590
|
isTop,
|
|
1490
1591
|
item,
|
|
1592
|
+
keyboardInset,
|
|
1491
1593
|
layout,
|
|
1492
1594
|
onSnap: handleSnap,
|
|
1493
1595
|
pop,
|
|
@@ -1918,7 +2020,7 @@ const SheetClose = ({ asChild, className, style, children }) => {
|
|
|
1918
2020
|
const isAsChild = asChild === true;
|
|
1919
2021
|
return /* @__PURE__ */ jsx(isAsChild ? Slot : "button", {
|
|
1920
2022
|
"aria-label": children === void 0 || children === null ? "Close" : void 0,
|
|
1921
|
-
className: joinClassNames(isAsChild ? void 0 : "flex min-h-11 min-w-11
|
|
2023
|
+
className: joinClassNames(isAsChild ? void 0 : "absolute right-2 top-2 z-20 flex min-h-11 min-w-11 cursor-pointer items-center justify-center rounded-md border-none bg-transparent p-0 text-inherit opacity-50 transition-opacity duration-150 hover:opacity-100", className),
|
|
1922
2024
|
onClick: close,
|
|
1923
2025
|
style,
|
|
1924
2026
|
type: isAsChild ? void 0 : "button",
|
|
@@ -1950,7 +2052,8 @@ const SheetFooter = ({ asChild, className, style, children }) => {
|
|
|
1950
2052
|
//#endregion
|
|
1951
2053
|
//#region src/SheetParts/sheet-handle.tsx
|
|
1952
2054
|
const SheetHandle = ({ asChild, className, style, children }) => {
|
|
1953
|
-
const { close, back, isNested } = useSheetPanel();
|
|
2055
|
+
const { close, back, isNested, side } = useSheetPanel();
|
|
2056
|
+
if (side !== "bottom") return null;
|
|
1954
2057
|
const dismiss = isNested ? back : close;
|
|
1955
2058
|
const isAsChild = asChild === true;
|
|
1956
2059
|
return /* @__PURE__ */ jsx(isAsChild ? Slot : "button", {
|
|
@@ -1971,7 +2074,7 @@ const SheetHandle = ({ asChild, className, style, children }) => {
|
|
|
1971
2074
|
const SheetHeader = ({ asChild, className, style, children }) => {
|
|
1972
2075
|
const isAsChild = asChild === true;
|
|
1973
2076
|
return /* @__PURE__ */ jsx(isAsChild ? Slot : "header", {
|
|
1974
|
-
className: joinClassNames(isAsChild ? "shrink-0" : "flex
|
|
2077
|
+
className: joinClassNames(isAsChild ? "shrink-0" : "flex shrink-0 items-center justify-between gap-3", className),
|
|
1975
2078
|
style,
|
|
1976
2079
|
children
|
|
1977
2080
|
});
|