@tamagui/sheet 1.88.13 → 1.89.0-1706308641099

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.
@@ -0,0 +1,50 @@
1
+ import { YStack } from "@tamagui/stacks";
2
+ import { useEffect, useRef } from "react";
3
+ import { View } from "react-native-web";
4
+ import { SheetProvider } from "./SheetContext.mjs";
5
+ import { useSheetOpenState } from "./useSheetOpenState.mjs";
6
+ import { useSheetProviderProps } from "./useSheetProviderProps.mjs";
7
+ import { Fragment, jsx, jsxs } from "react/jsx-runtime";
8
+ const nativeSheets = {
9
+ ios: null
10
+ };
11
+ function getNativeSheet(platform) {
12
+ return nativeSheets[platform];
13
+ }
14
+ function setupNativeSheet(platform, Implementation) {
15
+ platform === "ios" && (nativeSheets[platform] = props => {
16
+ const state = useSheetOpenState(props),
17
+ providerProps = useSheetProviderProps(props, state),
18
+ {
19
+ open,
20
+ setOpen
21
+ } = state,
22
+ ref = useRef();
23
+ return useEffect(() => {
24
+ ref.current?.setVisibility(open);
25
+ }, [open]), /* @__PURE__ */jsx(Fragment, {
26
+ children: /* @__PURE__ */jsxs(SheetProvider, {
27
+ ...providerProps,
28
+ onlyShowFrame: !0,
29
+ children: [/* @__PURE__ */jsx(Implementation, {
30
+ ref,
31
+ onModalDismiss: () => setOpen(!1),
32
+ children: /* @__PURE__ */jsx(View, {
33
+ style: {
34
+ flex: 1
35
+ },
36
+ children: props.children
37
+ })
38
+ }), /* @__PURE__ */jsx(YStack, {
39
+ position: "absolute",
40
+ opacity: 0,
41
+ pointerEvents: "none",
42
+ width: 0,
43
+ height: 0,
44
+ children: props.children
45
+ })]
46
+ })
47
+ });
48
+ });
49
+ }
50
+ export { getNativeSheet, setupNativeSheet };
File without changes
@@ -0,0 +1,3 @@
1
+ import { useSheetContext } from "./SheetContext.mjs";
2
+ const useSheet = () => useSheetContext("", void 0);
3
+ export { useSheet };
@@ -0,0 +1,14 @@
1
+ import { createContext, useContext } from "react";
2
+ const useSheetController = () => {
3
+ const controller = useContext(SheetControllerContext),
4
+ isHidden = controller?.hidden,
5
+ isShowingNonSheet = isHidden && controller?.open;
6
+ return {
7
+ controller,
8
+ isHidden,
9
+ isShowingNonSheet,
10
+ disableDrag: controller?.disableDrag
11
+ };
12
+ },
13
+ SheetControllerContext = createContext(null);
14
+ export { SheetControllerContext, useSheetController };
@@ -0,0 +1,27 @@
1
+ const useSheetOffscreenSize = ({
2
+ snapPoints,
3
+ position,
4
+ screenSize,
5
+ frameSize,
6
+ snapPointsMode
7
+ }) => {
8
+ if (snapPointsMode === "fit") return 0;
9
+ if (snapPointsMode === "constant") {
10
+ const maxSize2 = Number(snapPoints[0]),
11
+ currentSize2 = Number(snapPoints[position] ?? 0);
12
+ return maxSize2 - currentSize2;
13
+ }
14
+ if (snapPointsMode === "percent") {
15
+ const maxPercentOpened = Number(snapPoints[0]) / 100,
16
+ percentOpened = Number(snapPoints[position] ?? 0) / 100;
17
+ return (maxPercentOpened - percentOpened) * screenSize;
18
+ }
19
+ const maxSnapPoint = snapPoints[0];
20
+ if (maxSnapPoint === "fit") return 0;
21
+ const maxSize = typeof maxSnapPoint == "string" ? Number(maxSnapPoint.slice(0, -1)) / 100 * screenSize : maxSnapPoint,
22
+ currentSnapPoint = snapPoints[position] ?? 0,
23
+ currentSize = typeof currentSnapPoint == "string" ? Number(currentSnapPoint.slice(0, -1)) / 100 * screenSize : currentSnapPoint,
24
+ offscreenSize = maxSize - currentSize;
25
+ return Number.isNaN(offscreenSize) ? 0 : offscreenSize;
26
+ };
27
+ export { useSheetOffscreenSize };
@@ -0,0 +1,25 @@
1
+ import { useControllableState } from "@tamagui/use-controllable-state";
2
+ import { useSheetController } from "./useSheetController.mjs";
3
+ const useSheetOpenState = props => {
4
+ const {
5
+ isHidden,
6
+ controller
7
+ } = useSheetController(),
8
+ onOpenChangeInternal = val => {
9
+ controller?.onOpenChange?.(val), props.onOpenChange?.(val);
10
+ },
11
+ [open, setOpen] = useControllableState({
12
+ prop: controller?.open ?? props.open,
13
+ defaultProp: props.defaultOpen ?? !1,
14
+ onChange: onOpenChangeInternal,
15
+ strategy: "most-recent-wins",
16
+ transition: !0
17
+ });
18
+ return {
19
+ open,
20
+ setOpen,
21
+ isHidden,
22
+ controller
23
+ };
24
+ };
25
+ export { useSheetOpenState };
@@ -0,0 +1,86 @@
1
+ import { useConfiguration } from "@tamagui/core";
2
+ import { useConstant } from "@tamagui/use-constant";
3
+ import { useControllableState } from "@tamagui/use-controllable-state";
4
+ import React, { useCallback, useEffect, useMemo, useState } from "react";
5
+ function useSheetProviderProps(props, state, options = {}) {
6
+ const contentRef = React.useRef(null),
7
+ [frameSize, setFrameSize] = useState(0),
8
+ [maxContentSize, setMaxContentSize] = useState(0),
9
+ snapPointsMode = props.snapPointsMode ?? "percent",
10
+ snapPointsProp = props.snapPoints ?? (snapPointsMode === "percent" ? [80] : snapPointsMode === "constant" ? [256] : ["fit"]),
11
+ hasFit = snapPointsProp[0] === "fit",
12
+ snapPoints = useMemo(() => props.dismissOnSnapToBottom ? [...snapPointsProp, 0] : snapPointsProp,
13
+ // eslint-disable-next-line react-hooks/exhaustive-deps
14
+ [JSON.stringify(snapPointsProp), props.dismissOnSnapToBottom]),
15
+ [position_, setPositionImmediate] = useControllableState({
16
+ prop: props.position,
17
+ defaultProp: props.defaultPosition || (state.open ? 0 : -1),
18
+ onChange: props.onPositionChange,
19
+ strategy: "most-recent-wins",
20
+ transition: !0
21
+ }),
22
+ position = state.open === !1 ? -1 : position_,
23
+ {
24
+ open
25
+ } = state,
26
+ setPosition = useCallback(next => {
27
+ props.dismissOnSnapToBottom && next === snapPoints.length - 1 ? state.setOpen(!1) : setPositionImmediate(next);
28
+ }, [props.dismissOnSnapToBottom, snapPoints.length, setPositionImmediate, state.setOpen]);
29
+ process.env.NODE_ENV === "development" && (snapPointsMode === "mixed" && snapPoints.some(p => {
30
+ if (typeof p == "string") {
31
+ if (p === "fit") return !1;
32
+ if (p.endsWith("%")) {
33
+ const n = Number(p.slice(0, -1));
34
+ return n < 0 || n > 100;
35
+ }
36
+ return !0;
37
+ }
38
+ return typeof p != "number" || p < 0;
39
+ }) && console.warn('\u26A0\uFE0F Invalid snapPoint given, snapPoints must be positive numeric values, string percentages between 0-100%, or "fit" when snapPointsMode is mixed'), snapPointsMode === "mixed" && snapPoints.indexOf("fit") > 0 && console.warn('\u26A0\uFE0F Invalid snapPoint given, "fit" must be the first/largest snap point when snapPointsMode is mixed'), snapPointsMode === "fit" && (snapPoints.length !== (props.dismissOnSnapToBottom ? 2 : 1) || snapPoints[0] !== "fit") && console.warn("\u26A0\uFE0F Invalid snapPoint given, there are no snap points when snapPointsMode is fit"), snapPointsMode === "constant" && snapPoints.some(p => typeof p != "number" || p < 0) && console.warn("\u26A0\uFE0F Invalid snapPoint given, snapPoints must be positive numeric values when snapPointsMode is constant"), snapPointsMode === "percent" && snapPoints.some(p => typeof p != "number" || p < 0 || p > 100) && console.warn("\u26A0\uFE0F Invalid snapPoint given, snapPoints must be numeric values between 0 and 100 when snapPointsMode is percent")), open && props.dismissOnSnapToBottom && position === snapPoints.length - 1 && setPositionImmediate(0);
40
+ const shouldSetPositionOpen = open && position < 0;
41
+ useEffect(() => {
42
+ shouldSetPositionOpen && setPosition(0);
43
+ }, [setPosition, shouldSetPositionOpen]);
44
+ const {
45
+ animationDriver
46
+ } = useConfiguration();
47
+ if (!animationDriver) throw new Error("Must set animations in tamagui.config.ts");
48
+ const scrollBridge = useConstant(() => ({
49
+ enabled: !1,
50
+ y: 0,
51
+ paneY: 0,
52
+ paneMinY: 0,
53
+ scrollStartY: -1,
54
+ drag: () => {},
55
+ release: () => {},
56
+ scrollLock: !1
57
+ })),
58
+ removeScrollEnabled = props.forceRemoveScrollEnabled ?? (open && props.modal),
59
+ maxSnapPoint = snapPoints[0];
60
+ return {
61
+ screenSize: snapPointsMode === "percent" ? frameSize / ((typeof maxSnapPoint == "number" ? maxSnapPoint : 100) / 100) : maxContentSize,
62
+ maxSnapPoint,
63
+ removeScrollEnabled,
64
+ scrollBridge,
65
+ modal: !!props.modal,
66
+ open: state.open,
67
+ setOpen: state.setOpen,
68
+ hidden: !!state.isHidden,
69
+ contentRef,
70
+ frameSize,
71
+ setFrameSize,
72
+ dismissOnOverlayPress: props.dismissOnOverlayPress ?? !0,
73
+ dismissOnSnapToBottom: props.dismissOnSnapToBottom ?? !1,
74
+ onOverlayComponent: options.onOverlayComponent,
75
+ scope: props.__scopeSheet,
76
+ hasFit,
77
+ position,
78
+ snapPoints,
79
+ snapPointsMode,
80
+ setMaxContentSize,
81
+ setPosition,
82
+ setPositionImmediate,
83
+ onlyShowFrame: !1
84
+ };
85
+ }
86
+ export { useSheetProviderProps };
@@ -0,0 +1,91 @@
1
+ import { styled } from "@tamagui/core";
2
+ import { ThemeableStack, XStack, YStack } from "@tamagui/stacks";
3
+ import { SHEET_HANDLE_NAME, SHEET_NAME, SHEET_OVERLAY_NAME } from "./constants.mjs";
4
+ import { createSheet } from "./createSheet.mjs";
5
+ import { createSheetScope } from "./SheetContext.mjs";
6
+ export * from "./types.mjs";
7
+ const Handle = styled(XStack, {
8
+ name: SHEET_HANDLE_NAME,
9
+ variants: {
10
+ open: {
11
+ true: {
12
+ pointerEvents: "auto"
13
+ },
14
+ false: {
15
+ opacity: 0,
16
+ pointerEvents: "none"
17
+ }
18
+ },
19
+ unstyled: {
20
+ false: {
21
+ height: 10,
22
+ borderRadius: 100,
23
+ backgroundColor: "$background",
24
+ zIndex: 10,
25
+ marginHorizontal: "35%",
26
+ marginBottom: "$2",
27
+ opacity: 0.5,
28
+ hoverStyle: {
29
+ opacity: 0.7
30
+ }
31
+ }
32
+ }
33
+ },
34
+ defaultVariants: {
35
+ unstyled: process.env.TAMAGUI_HEADLESS === "1"
36
+ }
37
+ }),
38
+ Overlay = styled(ThemeableStack, {
39
+ name: SHEET_OVERLAY_NAME,
40
+ variants: {
41
+ open: {
42
+ true: {
43
+ opacity: 1,
44
+ pointerEvents: "auto"
45
+ },
46
+ false: {
47
+ opacity: 0,
48
+ pointerEvents: "none"
49
+ }
50
+ },
51
+ unstyled: {
52
+ false: {
53
+ fullscreen: !0,
54
+ position: "absolute",
55
+ backgrounded: !0,
56
+ zIndex: 99999,
57
+ pointerEvents: "auto"
58
+ }
59
+ }
60
+ },
61
+ defaultVariants: {
62
+ unstyled: process.env.TAMAGUI_HEADLESS === "1"
63
+ }
64
+ }),
65
+ Frame = styled(YStack, {
66
+ name: SHEET_NAME,
67
+ variants: {
68
+ unstyled: {
69
+ false: {
70
+ flex: 1,
71
+ backgroundColor: "$background",
72
+ borderTopLeftRadius: "$true",
73
+ borderTopRightRadius: "$true",
74
+ width: "100%",
75
+ maxHeight: "100%",
76
+ overflow: "hidden"
77
+ }
78
+ }
79
+ },
80
+ defaultVariants: {
81
+ unstyled: process.env.TAMAGUI_HEADLESS === "1"
82
+ }
83
+ }),
84
+ Sheet = createSheet({
85
+ Frame,
86
+ Handle,
87
+ Overlay
88
+ }),
89
+ SheetOverlayFrame = Overlay,
90
+ SheetHandleFrame = Handle;
91
+ export { Frame, Handle, Overlay, Sheet, SheetHandleFrame, SheetOverlayFrame, createSheetScope };
@@ -0,0 +1,5 @@
1
+ import { createContextScope } from "@tamagui/create-context";
2
+ import { SHEET_NAME } from "./constants.mjs";
3
+ const [createSheetContext, createSheetScope] = createContextScope(SHEET_NAME),
4
+ [SheetProvider, useSheetContext] = createSheetContext(SHEET_NAME, {});
5
+ export { SheetProvider, createSheetContext, createSheetScope, useSheetContext };
@@ -0,0 +1,22 @@
1
+ import { useEvent } from "@tamagui/core";
2
+ import { useMemo } from "react";
3
+ import { SheetControllerContext } from "./useSheetController.mjs";
4
+ import { jsx } from "react/jsx-runtime";
5
+ const SheetController = ({
6
+ children,
7
+ onOpenChange: onOpenChangeProp,
8
+ ...value
9
+ }) => {
10
+ const onOpenChange = useEvent(onOpenChangeProp),
11
+ memoValue = useMemo(() => ({
12
+ open: value.open,
13
+ hidden: value.hidden,
14
+ disableDrag: value.disableDrag,
15
+ onOpenChange
16
+ }), [onOpenChange, value.open, value.hidden, value.disableDrag]);
17
+ return /* @__PURE__ */jsx(SheetControllerContext.Provider, {
18
+ value: memoValue,
19
+ children
20
+ });
21
+ };
22
+ export { SheetController };
@@ -0,0 +1,313 @@
1
+ import { AdaptParentContext } from "@tamagui/adapt";
2
+ import { AnimatePresence } from "@tamagui/animate-presence";
3
+ import { useComposedRefs } from "@tamagui/compose-refs";
4
+ import { isWeb, useIsomorphicLayoutEffect } from "@tamagui/constants";
5
+ import { Stack, Theme, getConfig, themeable, useConfiguration, useEvent, useThemeName } from "@tamagui/core";
6
+ import { Portal } from "@tamagui/portal";
7
+ import { useKeyboardVisible } from "@tamagui/use-keyboard-visible";
8
+ import { forwardRef, useCallback, useContext, useEffect, useMemo, useRef, useState } from "react";
9
+ import { Dimensions, Keyboard, PanResponder, View } from "react-native-web";
10
+ import { SHEET_HIDDEN_STYLESHEET } from "./constants.mjs";
11
+ import { ParentSheetContext, SheetInsideSheetContext } from "./contexts.mjs";
12
+ import { resisted } from "./helpers.mjs";
13
+ import { SheetProvider } from "./SheetContext.mjs";
14
+ import { useSheetOpenState } from "./useSheetOpenState.mjs";
15
+ import { useSheetProviderProps } from "./useSheetProviderProps.mjs";
16
+ import { jsx, jsxs } from "react/jsx-runtime";
17
+ let hiddenSize = 10000.1;
18
+ const SheetImplementationCustom = themeable(forwardRef(function (props, forwardedRef) {
19
+ const parentSheet = useContext(ParentSheetContext),
20
+ {
21
+ animation,
22
+ animationConfig: animationConfigProp,
23
+ modal = !1,
24
+ zIndex = parentSheet.zIndex + 1,
25
+ moveOnKeyboardChange = !1,
26
+ unmountChildrenWhenHidden = !1,
27
+ portalProps
28
+ } = props,
29
+ keyboardIsVisible = useKeyboardVisible(),
30
+ state = useSheetOpenState(props),
31
+ [overlayComponent, setOverlayComponent] = useState(null),
32
+ providerProps = useSheetProviderProps(props, state, {
33
+ onOverlayComponent: setOverlayComponent
34
+ }),
35
+ {
36
+ frameSize,
37
+ setFrameSize,
38
+ snapPoints,
39
+ snapPointsMode,
40
+ hasFit,
41
+ position,
42
+ setPosition,
43
+ scrollBridge,
44
+ screenSize,
45
+ setMaxContentSize,
46
+ maxSnapPoint
47
+ } = providerProps,
48
+ {
49
+ open,
50
+ controller,
51
+ isHidden
52
+ } = state,
53
+ sheetRef = useRef(null),
54
+ ref = useComposedRefs(forwardedRef, sheetRef),
55
+ animationConfig = (() => {
56
+ const [animationProp, animationPropConfig] = animation ? Array.isArray(animation) ? animation : [animation] : [];
57
+ return animationConfigProp ?? (animationProp ? {
58
+ ...getConfig().animations.animations[animationProp],
59
+ ...animationPropConfig
60
+ } : null);
61
+ })(),
62
+ [isShowingInnerSheet, setIsShowingInnerSheet] = useState(!1),
63
+ shouldHideParentSheet = !isWeb && modal && isShowingInnerSheet,
64
+ parentSheetContext = useContext(SheetInsideSheetContext),
65
+ onInnerSheet = useCallback(hasChild => {
66
+ setIsShowingInnerSheet(hasChild);
67
+ }, []),
68
+ positions = useMemo(() => snapPoints.map(point => getYPositions(snapPointsMode, point, screenSize, frameSize)), [screenSize, frameSize, snapPoints, snapPointsMode]),
69
+ {
70
+ animationDriver
71
+ } = useConfiguration(),
72
+ {
73
+ useAnimatedNumber,
74
+ useAnimatedNumberStyle,
75
+ useAnimatedNumberReaction
76
+ } = animationDriver,
77
+ AnimatedView = animationDriver.View ?? Stack;
78
+ useIsomorphicLayoutEffect(() => {
79
+ if (parentSheetContext && open) return parentSheetContext(!0), () => {
80
+ parentSheetContext(!1);
81
+ };
82
+ }, [parentSheetContext, open]);
83
+ const nextParentContext = useMemo(() => ({
84
+ zIndex
85
+ }), [zIndex]),
86
+ animatedNumber = useAnimatedNumber(hiddenSize),
87
+ at = useRef(hiddenSize);
88
+ useAnimatedNumberReaction({
89
+ value: animatedNumber,
90
+ hostRef: sheetRef
91
+ }, useCallback(value => {
92
+ at.current = value, scrollBridge.paneY = value;
93
+ }, [animationDriver]));
94
+ function stopSpring() {
95
+ animatedNumber.stop(), scrollBridge.onFinishAnimate && (scrollBridge.onFinishAnimate(), scrollBridge.onFinishAnimate = void 0);
96
+ }
97
+ const hasntMeasured = at.current === hiddenSize,
98
+ animateTo = useEvent(position2 => {
99
+ if (frameSize === 0) return;
100
+ let toValue = isHidden || position2 === -1 ? screenSize : positions[position2];
101
+ if (at.current !== toValue) {
102
+ if (at.current = toValue, stopSpring(), hasntMeasured || isHidden) {
103
+ if (animatedNumber.setValue(screenSize, {
104
+ type: "timing",
105
+ duration: 0
106
+ }), isHidden) return;
107
+ toValue = positions[position2], at.current = toValue;
108
+ }
109
+ animatedNumber.setValue(toValue, {
110
+ type: "spring",
111
+ ...animationConfig
112
+ });
113
+ }
114
+ });
115
+ useIsomorphicLayoutEffect(() => {
116
+ screenSize && hasntMeasured && animatedNumber.setValue(screenSize, {
117
+ type: "timing",
118
+ duration: 0
119
+ });
120
+ }, [hasntMeasured, screenSize]), useIsomorphicLayoutEffect(() => {
121
+ !frameSize || !screenSize || isHidden || hasntMeasured && !open || animateTo(position);
122
+ }, [isHidden, frameSize, screenSize, open, position]);
123
+ const disableDrag = props.disableDrag ?? controller?.disableDrag,
124
+ themeName = useThemeName(),
125
+ [isDragging, setIsDragging] = useState(!1),
126
+ panResponder = useMemo(() => {
127
+ if (disableDrag || !frameSize || isShowingInnerSheet) return;
128
+ const minY = positions[0];
129
+ scrollBridge.paneMinY = minY;
130
+ let startY = at.current;
131
+ function setPanning(val) {
132
+ setIsDragging(val), SHEET_HIDDEN_STYLESHEET && (val ? SHEET_HIDDEN_STYLESHEET.innerText = ":root * { user-select: none !important; -webkit-user-select: none !important; }" : SHEET_HIDDEN_STYLESHEET.innerText = "");
133
+ }
134
+ const release = ({
135
+ vy,
136
+ dragAt
137
+ }) => {
138
+ isExternalDrag = !1, previouslyScrolling = !1, setPanning(!1);
139
+ const end = dragAt + startY + frameSize * vy * 0.2;
140
+ let closestPoint = 0,
141
+ dist = 1 / 0;
142
+ for (let i = 0; i < positions.length; i++) {
143
+ const position2 = positions[i],
144
+ curDist = end > position2 ? end - position2 : position2 - end;
145
+ curDist < dist && (dist = curDist, closestPoint = i);
146
+ }
147
+ setPosition(closestPoint), animateTo(closestPoint);
148
+ },
149
+ finish = (_e, state2) => {
150
+ release({
151
+ vy: state2.vy,
152
+ dragAt: state2.dy
153
+ });
154
+ };
155
+ let previouslyScrolling = !1;
156
+ const onMoveShouldSet = (_e, {
157
+ dy
158
+ }) => {
159
+ const isScrolled = scrollBridge.y !== 0,
160
+ isDraggingUp = dy < 0,
161
+ isNearTop = scrollBridge.paneY - 5 <= scrollBridge.paneMinY;
162
+ return isScrolled ? (previouslyScrolling = !0, !1) : isNearTop && !isScrolled && isDraggingUp ? !1 : Math.abs(dy) > 5;
163
+ },
164
+ grant = () => {
165
+ setPanning(!0), stopSpring(), startY = at.current;
166
+ };
167
+ let isExternalDrag = !1;
168
+ return scrollBridge.drag = dy => {
169
+ isExternalDrag || (isExternalDrag = !0, grant());
170
+ const to = dy + startY;
171
+ animatedNumber.setValue(resisted(to, minY), {
172
+ type: "direct"
173
+ });
174
+ }, scrollBridge.release = release, PanResponder.create({
175
+ onMoveShouldSetPanResponder: onMoveShouldSet,
176
+ onPanResponderGrant: grant,
177
+ onPanResponderMove: (_e, {
178
+ dy
179
+ }) => {
180
+ const toFull = dy + startY,
181
+ to = resisted(toFull, minY);
182
+ animatedNumber.setValue(to, {
183
+ type: "direct"
184
+ });
185
+ },
186
+ onPanResponderEnd: finish,
187
+ onPanResponderTerminate: finish,
188
+ onPanResponderRelease: finish
189
+ });
190
+ },
191
+ // eslint-disable-next-line react-hooks/exhaustive-deps
192
+ [disableDrag, isShowingInnerSheet, animateTo, frameSize, positions, setPosition]),
193
+ handleAnimationViewLayout = useCallback(e => {
194
+ const next = Math.min(e.nativeEvent?.layout.height, Dimensions.get("window").height);
195
+ next && setFrameSize(next);
196
+ }, [keyboardIsVisible]),
197
+ handleMaxContentViewLayout = useCallback(e => {
198
+ const next = Math.min(e.nativeEvent?.layout.height, Dimensions.get("window").height);
199
+ next && setMaxContentSize(next);
200
+ }, [keyboardIsVisible]),
201
+ animatedStyle = useAnimatedNumberStyle(animatedNumber, val => {
202
+ "worklet";
203
+
204
+ return {
205
+ transform: [{
206
+ translateY: frameSize === 0 ? hiddenSize : val
207
+ }]
208
+ };
209
+ }),
210
+ sizeBeforeKeyboard = useRef(null);
211
+ useEffect(() => {
212
+ if (isWeb || !moveOnKeyboardChange) return;
213
+ const keyboardDidShowListener = Keyboard.addListener("keyboardDidShow", e => {
214
+ sizeBeforeKeyboard.current === null && (sizeBeforeKeyboard.current = animatedNumber.getValue(), animatedNumber.setValue(Math.max(animatedNumber.getValue() - e.endCoordinates.height, 0)));
215
+ }),
216
+ keyboardDidHideListener = Keyboard.addListener("keyboardDidHide", () => {
217
+ sizeBeforeKeyboard.current !== null && (animatedNumber.setValue(sizeBeforeKeyboard.current), sizeBeforeKeyboard.current = null);
218
+ });
219
+ return () => {
220
+ keyboardDidHideListener.remove(), keyboardDidShowListener.remove();
221
+ };
222
+ }, [moveOnKeyboardChange]);
223
+ const [opacity, setOpacity] = useState(open ? 1 : 0);
224
+ open && opacity === 0 && setOpacity(1), useEffect(() => {
225
+ if (!open) {
226
+ const tm = setTimeout(() => {
227
+ setOpacity(0);
228
+ }, 400);
229
+ return () => {
230
+ clearTimeout(tm);
231
+ };
232
+ }
233
+ }, [open]);
234
+ const forcedContentHeight = hasFit ? void 0 : snapPointsMode === "percent" ? `${maxSnapPoint}%` : maxSnapPoint,
235
+ contents = /* @__PURE__ */jsx(ParentSheetContext.Provider, {
236
+ value: nextParentContext,
237
+ children: /* @__PURE__ */jsxs(SheetProvider, {
238
+ ...providerProps,
239
+ children: [/* @__PURE__ */jsx(AnimatePresence, {
240
+ enterExitVariant: "open",
241
+ children: shouldHideParentSheet || !open ? null : overlayComponent
242
+ }), snapPointsMode !== "percent" && /* @__PURE__ */jsx(View, {
243
+ style: {
244
+ opacity: 0,
245
+ position: "absolute",
246
+ top: 0,
247
+ left: 0,
248
+ right: 0,
249
+ bottom: 0,
250
+ pointerEvents: "none"
251
+ },
252
+ pointerEvents: "none",
253
+ onLayout: handleMaxContentViewLayout
254
+ }), /* @__PURE__ */jsx(AnimatedView, {
255
+ ref,
256
+ ...panResponder?.panHandlers,
257
+ onLayout: handleAnimationViewLayout,
258
+ pointerEvents: open && !shouldHideParentSheet ? "auto" : "none",
259
+ ...(!isDragging && {
260
+ // @ts-ignore for CSS driver this is necessary to attach the transition
261
+ animation
262
+ }),
263
+ style: [{
264
+ position: "absolute",
265
+ zIndex,
266
+ width: "100%",
267
+ height: forcedContentHeight,
268
+ minHeight: forcedContentHeight,
269
+ opacity
270
+ }, animatedStyle],
271
+ children: props.children
272
+ })]
273
+ })
274
+ }),
275
+ adaptContext = useContext(AdaptParentContext),
276
+ shouldMountChildren = !!(opacity || !unmountChildrenWhenHidden);
277
+ if (modal) {
278
+ const modalContents = /* @__PURE__ */jsx(Portal, {
279
+ zIndex,
280
+ ...portalProps,
281
+ children: shouldMountChildren && /* @__PURE__ */jsx(Theme, {
282
+ forceClassName: !0,
283
+ name: themeName,
284
+ children: /* @__PURE__ */jsx(AdaptParentContext.Provider, {
285
+ value: adaptContext,
286
+ children: contents
287
+ })
288
+ })
289
+ });
290
+ return isWeb ? modalContents : /* @__PURE__ */jsx(SheetInsideSheetContext.Provider, {
291
+ value: onInnerSheet,
292
+ children: modalContents
293
+ });
294
+ }
295
+ return contents;
296
+ }));
297
+ function getYPositions(mode, point, screenSize, frameSize) {
298
+ if (!screenSize || !frameSize) return 0;
299
+ if (mode === "mixed") {
300
+ if (typeof point == "number") return screenSize - Math.min(screenSize, Math.max(0, point));
301
+ if (point === "fit") return screenSize - Math.min(screenSize, frameSize);
302
+ if (point.endsWith("%")) {
303
+ const pct2 = Math.min(100, Math.max(0, Number(point.slice(0, -1)))) / 100;
304
+ return Number.isNaN(pct2) ? (console.warn("Invalid snapPoint percentage string"), 0) : Math.round(screenSize - pct2 * screenSize);
305
+ }
306
+ return console.warn("Invalid snapPoint unknown value"), 0;
307
+ }
308
+ if (mode === "fit") return point === 0 ? screenSize : screenSize - Math.min(screenSize, frameSize);
309
+ if (mode === "constant" && typeof point == "number") return screenSize - Math.min(screenSize, Math.max(0, point));
310
+ const pct = Math.min(100, Math.max(0, Number(point))) / 100;
311
+ return Number.isNaN(pct) ? (console.warn("Invalid snapPoint percentage"), 0) : Math.round(screenSize - pct * screenSize);
312
+ }
313
+ export { SheetImplementationCustom };