@impulse-ui-native/flyout 2.1.0 → 2.1.1

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,9 @@
1
+ import * as react from 'react';
2
+ import * as react_jsx_runtime from 'react/jsx-runtime';
3
+
4
+ interface FlyoutHandleProps {
5
+ placement: "top" | "bottom";
6
+ }
7
+ declare const FlyoutHandle: react.MemoExoticComponent<(props: FlyoutHandleProps) => react_jsx_runtime.JSX.Element>;
8
+
9
+ export { FlyoutHandle };
@@ -0,0 +1,35 @@
1
+ import { jsx } from "react/jsx-runtime";
2
+ import { memo } from "react";
3
+ import { StyleSheet } from "react-native";
4
+ import Animated from "react-native-reanimated";
5
+ import { View } from "@impulse-ui-native/primitives";
6
+ import { useThemedStyles } from "@impulse-ui-native/theme";
7
+ const FlyoutHandle = memo(function FlyoutHandle2(props) {
8
+ const styles = useThemedStyles(themedStyles, props, [props.placement]);
9
+ return /* @__PURE__ */ jsx(Animated.View, { style: styles.flyoutHandleContainer, children: /* @__PURE__ */ jsx(View, { style: styles.flyoutHandle }) });
10
+ });
11
+ function themedStyles(theme, { placement }) {
12
+ const handleTokens = theme.components.flyout.handle;
13
+ return StyleSheet.create({
14
+ flyoutHandle: {
15
+ alignSelf: "center",
16
+ backgroundColor: handleTokens.backgroundColor,
17
+ width: handleTokens.width,
18
+ height: handleTokens.height,
19
+ borderRadius: handleTokens.borderRadius
20
+ },
21
+ flyoutHandleContainer: {
22
+ position: "absolute",
23
+ top: placement === "bottom" ? -handleTokens.containerHeight : void 0,
24
+ bottom: placement === "top" ? -handleTokens.containerHeight : void 0,
25
+ width: "100%",
26
+ justifyContent: "center",
27
+ alignItems: "center",
28
+ height: handleTokens.containerHeight
29
+ }
30
+ });
31
+ }
32
+ export {
33
+ FlyoutHandle
34
+ };
35
+ //# sourceMappingURL=flyout-handle.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/components/flyout-handle.tsx"],"sourcesContent":["import { memo } from \"react\";\r\nimport { StyleSheet } from \"react-native\";\r\nimport Animated from \"react-native-reanimated\";\r\n\r\nimport { View } from \"@impulse-ui-native/primitives\";\r\nimport { AppTheme, useThemedStyles } from \"@impulse-ui-native/theme\";\r\n\r\ninterface FlyoutHandleProps {\r\n placement: \"top\" | \"bottom\";\r\n}\r\n\r\nexport const FlyoutHandle = memo(function FlyoutHandle(\r\n props: FlyoutHandleProps,\r\n) {\r\n const styles = useThemedStyles(themedStyles, props, [props.placement]);\r\n\r\n return (\r\n <Animated.View style={styles.flyoutHandleContainer}>\r\n <View style={styles.flyoutHandle} />\r\n </Animated.View>\r\n );\r\n});\r\n\r\nfunction themedStyles(\r\n theme: AppTheme,\r\n { placement }: { placement: \"top\" | \"bottom\" },\r\n) {\r\n const handleTokens = theme.components.flyout.handle;\r\n\r\n return StyleSheet.create({\r\n flyoutHandle: {\r\n alignSelf: \"center\",\r\n backgroundColor: handleTokens.backgroundColor,\r\n width: handleTokens.width,\r\n height: handleTokens.height,\r\n borderRadius: handleTokens.borderRadius,\r\n },\r\n flyoutHandleContainer: {\r\n position: \"absolute\",\r\n top: placement === \"bottom\" ? -handleTokens.containerHeight : undefined,\r\n bottom: placement === \"top\" ? -handleTokens.containerHeight : undefined,\r\n width: \"100%\",\r\n justifyContent: \"center\",\r\n alignItems: \"center\",\r\n height: handleTokens.containerHeight,\r\n },\r\n });\r\n}\r\n"],"mappings":"AAkBM;AAlBN,SAAS,YAAY;AACrB,SAAS,kBAAkB;AAC3B,OAAO,cAAc;AAErB,SAAS,YAAY;AACrB,SAAmB,uBAAuB;AAMnC,MAAM,eAAe,KAAK,SAASA,cACxC,OACA;AACA,QAAM,SAAS,gBAAgB,cAAc,OAAO,CAAC,MAAM,SAAS,CAAC;AAErE,SACE,oBAAC,SAAS,MAAT,EAAc,OAAO,OAAO,uBAC3B,8BAAC,QAAK,OAAO,OAAO,cAAc,GACpC;AAEJ,CAAC;AAED,SAAS,aACP,OACA,EAAE,UAAU,GACZ;AACA,QAAM,eAAe,MAAM,WAAW,OAAO;AAE7C,SAAO,WAAW,OAAO;AAAA,IACvB,cAAc;AAAA,MACZ,WAAW;AAAA,MACX,iBAAiB,aAAa;AAAA,MAC9B,OAAO,aAAa;AAAA,MACpB,QAAQ,aAAa;AAAA,MACrB,cAAc,aAAa;AAAA,IAC7B;AAAA,IACA,uBAAuB;AAAA,MACrB,UAAU;AAAA,MACV,KAAK,cAAc,WAAW,CAAC,aAAa,kBAAkB;AAAA,MAC9D,QAAQ,cAAc,QAAQ,CAAC,aAAa,kBAAkB;AAAA,MAC9D,OAAO;AAAA,MACP,gBAAgB;AAAA,MAChB,YAAY;AAAA,MACZ,QAAQ,aAAa;AAAA,IACvB;AAAA,EACF,CAAC;AACH;","names":["FlyoutHandle"]}
@@ -0,0 +1,10 @@
1
+ import * as react from 'react';
2
+ import { ReactNode } from 'react';
3
+ import * as react_jsx_runtime from 'react/jsx-runtime';
4
+
5
+ interface FlyoutTitleProps {
6
+ title?: ReactNode | string;
7
+ }
8
+ declare const FlyoutTitle: react.MemoExoticComponent<(props: FlyoutTitleProps) => react_jsx_runtime.JSX.Element | null>;
9
+
10
+ export { FlyoutTitle };
@@ -0,0 +1,32 @@
1
+ import { jsx } from "react/jsx-runtime";
2
+ import { memo, useMemo } from "react";
3
+ import { StyleSheet } from "react-native";
4
+ import { Typography, View } from "@impulse-ui-native/primitives";
5
+ import { useThemedStyles } from "@impulse-ui-native/theme";
6
+ const FlyoutTitle = memo(function FlyoutTitle2(props) {
7
+ const styles = useThemedStyles(themedStyles);
8
+ const title = useMemo(() => {
9
+ if (typeof props.title === "string") {
10
+ return /* @__PURE__ */ jsx(Typography.Title3, { children: props.title });
11
+ }
12
+ return props.title;
13
+ }, [props.title]);
14
+ if (!props.title) {
15
+ return null;
16
+ }
17
+ return /* @__PURE__ */ jsx(View, { style: styles.container, children: title });
18
+ });
19
+ function themedStyles(theme) {
20
+ const titleTokens = theme.components.flyout.title;
21
+ return StyleSheet.create({
22
+ container: {
23
+ paddingVertical: titleTokens.paddingVertical,
24
+ paddingHorizontal: titleTokens.paddingHorizontal,
25
+ alignItems: "center"
26
+ }
27
+ });
28
+ }
29
+ export {
30
+ FlyoutTitle
31
+ };
32
+ //# sourceMappingURL=flyout-title.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/components/flyout-title.tsx"],"sourcesContent":["import { memo, ReactNode, useMemo } from \"react\";\r\nimport { StyleSheet } from \"react-native\";\r\n\r\nimport { Typography, View } from \"@impulse-ui-native/primitives\";\r\nimport { AppTheme, useThemedStyles } from \"@impulse-ui-native/theme\";\r\n\r\ninterface FlyoutTitleProps {\r\n title?: ReactNode | string;\r\n}\r\n\r\nexport const FlyoutTitle = memo(function FlyoutTitle(props: FlyoutTitleProps) {\r\n const styles = useThemedStyles(themedStyles);\r\n\r\n const title = useMemo(() => {\r\n if (typeof props.title === \"string\") {\r\n return <Typography.Title3>{props.title}</Typography.Title3>;\r\n }\r\n\r\n return props.title;\r\n }, [props.title]);\r\n\r\n if (!props.title) {\r\n return null;\r\n }\r\n\r\n return <View style={styles.container}>{title}</View>;\r\n});\r\n\r\nfunction themedStyles(theme: AppTheme) {\r\n const titleTokens = theme.components.flyout.title;\r\n\r\n return StyleSheet.create({\r\n container: {\r\n paddingVertical: titleTokens.paddingVertical,\r\n paddingHorizontal: titleTokens.paddingHorizontal,\r\n alignItems: \"center\",\r\n },\r\n });\r\n}\r\n"],"mappings":"AAea;AAfb,SAAS,MAAiB,eAAe;AACzC,SAAS,kBAAkB;AAE3B,SAAS,YAAY,YAAY;AACjC,SAAmB,uBAAuB;AAMnC,MAAM,cAAc,KAAK,SAASA,aAAY,OAAyB;AAC5E,QAAM,SAAS,gBAAgB,YAAY;AAE3C,QAAM,QAAQ,QAAQ,MAAM;AAC1B,QAAI,OAAO,MAAM,UAAU,UAAU;AACnC,aAAO,oBAAC,WAAW,QAAX,EAAmB,gBAAM,OAAM;AAAA,IACzC;AAEA,WAAO,MAAM;AAAA,EACf,GAAG,CAAC,MAAM,KAAK,CAAC;AAEhB,MAAI,CAAC,MAAM,OAAO;AAChB,WAAO;AAAA,EACT;AAEA,SAAO,oBAAC,QAAK,OAAO,OAAO,WAAY,iBAAM;AAC/C,CAAC;AAED,SAAS,aAAa,OAAiB;AACrC,QAAM,cAAc,MAAM,WAAW,OAAO;AAE5C,SAAO,WAAW,OAAO;AAAA,IACvB,WAAW;AAAA,MACT,iBAAiB,YAAY;AAAA,MAC7B,mBAAmB,YAAY;AAAA,MAC/B,YAAY;AAAA,IACd;AAAA,EACF,CAAC;AACH;","names":["FlyoutTitle"]}
@@ -0,0 +1,9 @@
1
+ import * as react from 'react';
2
+ import { PropsWithChildren } from 'react';
3
+ import * as react_jsx_runtime from 'react/jsx-runtime';
4
+ import { FlyoutProps } from '../types/flyout.types.mjs';
5
+ import '@impulse-ui-native/types';
6
+
7
+ declare const Flyout: react.MemoExoticComponent<(props: PropsWithChildren<FlyoutProps>) => react_jsx_runtime.JSX.Element | null>;
8
+
9
+ export { Flyout };
@@ -0,0 +1,277 @@
1
+ import { jsx, jsxs } from "react/jsx-runtime";
2
+ import {
3
+ Fragment,
4
+ memo,
5
+ useCallback,
6
+ useEffect,
7
+ useMemo,
8
+ useRef,
9
+ useState
10
+ } from "react";
11
+ import {
12
+ Pressable,
13
+ StyleSheet,
14
+ useWindowDimensions
15
+ } from "react-native";
16
+ import { Gesture, GestureDetector } from "react-native-gesture-handler";
17
+ import Animated, {
18
+ Easing,
19
+ useAnimatedStyle,
20
+ useSharedValue,
21
+ withSpring,
22
+ withTiming
23
+ } from "react-native-reanimated";
24
+ import {
25
+ SafeAreaView,
26
+ useSafeAreaInsets
27
+ } from "react-native-safe-area-context";
28
+ import { scheduleOnRN } from "react-native-worklets";
29
+ import { View } from "@impulse-ui-native/primitives";
30
+ import { useTheme } from "@impulse-ui-native/theme";
31
+ import { FlyoutHandleHeight } from "../constants";
32
+ import { FlyoutHandle } from "./flyout-handle";
33
+ import { FlyoutTitle } from "./flyout-title";
34
+ const EnterAnimationConfig = {
35
+ damping: 50,
36
+ stiffness: 300,
37
+ mass: 1,
38
+ overshootClamping: true
39
+ };
40
+ const ExitAnimationConfig = {
41
+ duration: 150,
42
+ easing: Easing.in(Easing.quad)
43
+ };
44
+ const Flyout = memo(function Flyout2(props) {
45
+ const {
46
+ id,
47
+ children,
48
+ placement = "bottom",
49
+ layer = 0,
50
+ title,
51
+ open,
52
+ topOffset,
53
+ bottomOffset,
54
+ onCloseFinished,
55
+ onClose,
56
+ onOpen,
57
+ onOpenFinished
58
+ } = props;
59
+ const theme = useTheme();
60
+ const insets = useSafeAreaInsets();
61
+ const windowDimensions = useWindowDimensions();
62
+ const flyoutTokens = theme.components.flyout;
63
+ const placementOffset = placement === "top" ? topOffset : bottomOffset;
64
+ const screenHeight = windowDimensions.height;
65
+ const maxHeight = screenHeight * flyoutTokens.maxHeightRatio;
66
+ const zIndex = flyoutTokens.zIndexBase + layer;
67
+ const [mounted, setMounted] = useState(open);
68
+ const [measuredHeight, setMeasuredHeight] = useState(null);
69
+ const [hasMeasured, setHasMeasured] = useState(false);
70
+ const [isTouchable, setIsTouchable] = useState(false);
71
+ const didOpen = useRef(false);
72
+ const isClosing = useRef(false);
73
+ const translateY = useSharedValue(
74
+ placement === "top" ? -screenHeight : screenHeight
75
+ );
76
+ const opacity = useSharedValue(0);
77
+ const onLayout = useCallback(
78
+ (event) => {
79
+ if (measuredHeight !== null) {
80
+ return;
81
+ }
82
+ const rawHeight = event.nativeEvent.layout.height;
83
+ const clampedHeight = rawHeight + insets[placement] + FlyoutHandleHeight;
84
+ translateY.value = placement === "top" ? -clampedHeight : clampedHeight;
85
+ setMeasuredHeight(clampedHeight);
86
+ setHasMeasured(true);
87
+ },
88
+ [insets, measuredHeight, placement, translateY]
89
+ );
90
+ const animateOut = useCallback(() => {
91
+ if (measuredHeight === null || isClosing.current) {
92
+ return;
93
+ }
94
+ isClosing.current = true;
95
+ setIsTouchable(false);
96
+ onClose?.(id);
97
+ const target = placement === "top" ? -measuredHeight : measuredHeight;
98
+ translateY.value = withTiming(target, ExitAnimationConfig, (finished) => {
99
+ if (finished) {
100
+ if (onCloseFinished) {
101
+ scheduleOnRN(onCloseFinished, id);
102
+ }
103
+ scheduleOnRN(setMounted, false);
104
+ scheduleOnRN(setMeasuredHeight, null);
105
+ scheduleOnRN(setHasMeasured, false);
106
+ }
107
+ });
108
+ opacity.value = withTiming(0, ExitAnimationConfig);
109
+ didOpen.current = false;
110
+ }, [
111
+ id,
112
+ measuredHeight,
113
+ onClose,
114
+ onCloseFinished,
115
+ opacity,
116
+ placement,
117
+ translateY
118
+ ]);
119
+ const dragGesture = useMemo(
120
+ () => Gesture.Pan().enabled(hasMeasured).onUpdate((event) => {
121
+ if (placement === "bottom") {
122
+ translateY.value = Math.max(0, event.translationY);
123
+ return;
124
+ }
125
+ translateY.value = Math.min(0, event.translationY);
126
+ }).onEnd((event) => {
127
+ if (measuredHeight === null) {
128
+ return;
129
+ }
130
+ let shouldClose = false;
131
+ if (placement === "bottom") {
132
+ shouldClose = event.translationY > measuredHeight * 0.5 || event.velocityY > 1500;
133
+ }
134
+ if (placement === "top") {
135
+ shouldClose = event.translationY < -measuredHeight * 0.5 || event.velocityY < -1500;
136
+ }
137
+ if (shouldClose) {
138
+ scheduleOnRN(animateOut);
139
+ return;
140
+ }
141
+ translateY.value = withSpring(0, EnterAnimationConfig);
142
+ opacity.value = withSpring(
143
+ flyoutTokens.overlayVisibleOpacity,
144
+ EnterAnimationConfig
145
+ );
146
+ }),
147
+ [
148
+ animateOut,
149
+ flyoutTokens.overlayVisibleOpacity,
150
+ hasMeasured,
151
+ measuredHeight,
152
+ opacity,
153
+ placement,
154
+ translateY
155
+ ]
156
+ );
157
+ const animatedStyle = useAnimatedStyle(() => {
158
+ const offset = placement === "bottom" ? -(placementOffset ?? 0) : placementOffset ?? 0;
159
+ return {
160
+ transform: [{ translateY: translateY.value + offset }],
161
+ zIndex
162
+ };
163
+ });
164
+ const overlayStyle = useAnimatedStyle(() => ({
165
+ opacity: opacity.value,
166
+ zIndex,
167
+ backgroundColor: flyoutTokens.overlayColor
168
+ }));
169
+ const edges = useMemo(() => {
170
+ return [placement, "left", "right"];
171
+ }, [placement]);
172
+ const styles = useMemo(() => {
173
+ return themedStyles(theme, placement, maxHeight);
174
+ }, [theme, placement, maxHeight]);
175
+ useEffect(() => {
176
+ if (!open) {
177
+ return;
178
+ }
179
+ setMounted(true);
180
+ setIsTouchable(false);
181
+ setMeasuredHeight(null);
182
+ setHasMeasured(false);
183
+ isClosing.current = false;
184
+ didOpen.current = false;
185
+ translateY.value = placement === "top" ? -screenHeight : screenHeight;
186
+ opacity.value = 0;
187
+ }, [open, opacity, placement, screenHeight, translateY]);
188
+ useEffect(() => {
189
+ if (!open || measuredHeight === null || !hasMeasured || didOpen.current) {
190
+ return;
191
+ }
192
+ setIsTouchable(true);
193
+ onOpen?.(id);
194
+ translateY.value = withSpring(0, EnterAnimationConfig, (finished) => {
195
+ if (finished && onOpenFinished) {
196
+ scheduleOnRN(onOpenFinished, id);
197
+ }
198
+ });
199
+ opacity.value = withSpring(
200
+ flyoutTokens.overlayVisibleOpacity,
201
+ EnterAnimationConfig
202
+ );
203
+ didOpen.current = true;
204
+ }, [
205
+ flyoutTokens.overlayVisibleOpacity,
206
+ hasMeasured,
207
+ id,
208
+ measuredHeight,
209
+ onOpen,
210
+ onOpenFinished,
211
+ opacity,
212
+ open,
213
+ translateY
214
+ ]);
215
+ useEffect(() => {
216
+ if (!open && didOpen.current) {
217
+ animateOut();
218
+ }
219
+ }, [animateOut, open]);
220
+ if (!mounted) {
221
+ return null;
222
+ }
223
+ return /* @__PURE__ */ jsxs(Fragment, { children: [
224
+ /* @__PURE__ */ jsx(
225
+ Animated.View,
226
+ {
227
+ pointerEvents: isTouchable ? "auto" : "none",
228
+ style: [StyleSheet.absoluteFill, overlayStyle],
229
+ children: /* @__PURE__ */ jsx(Pressable, { onPress: animateOut, style: StyleSheet.absoluteFill })
230
+ }
231
+ ),
232
+ /* @__PURE__ */ jsx(GestureDetector, { gesture: dragGesture, children: /* @__PURE__ */ jsx(
233
+ Animated.View,
234
+ {
235
+ onLayout,
236
+ style: [
237
+ styles.container,
238
+ !hasMeasured && styles.hidden,
239
+ animatedStyle
240
+ ],
241
+ children: /* @__PURE__ */ jsxs(SafeAreaView, { edges, children: [
242
+ placement === "bottom" ? /* @__PURE__ */ jsx(FlyoutHandle, { placement }) : null,
243
+ title ? /* @__PURE__ */ jsx(FlyoutTitle, { title }) : null,
244
+ /* @__PURE__ */ jsx(View, { style: styles.content, children }),
245
+ placement === "top" ? /* @__PURE__ */ jsx(FlyoutHandle, { placement }) : null
246
+ ] })
247
+ }
248
+ ) })
249
+ ] });
250
+ });
251
+ function themedStyles(theme, placement, maxHeight) {
252
+ const flyoutTokens = theme.components.flyout;
253
+ return StyleSheet.create({
254
+ container: {
255
+ position: "absolute",
256
+ [placement]: 0,
257
+ left: 0,
258
+ right: 0,
259
+ backgroundColor: flyoutTokens.backgroundColor,
260
+ borderTopLeftRadius: placement === "bottom" ? flyoutTokens.borderRadius : 0,
261
+ borderTopRightRadius: placement === "bottom" ? flyoutTokens.borderRadius : 0,
262
+ borderBottomLeftRadius: placement === "top" ? flyoutTokens.borderRadius : 0,
263
+ borderBottomRightRadius: placement === "top" ? flyoutTokens.borderRadius : 0
264
+ },
265
+ content: {
266
+ paddingHorizontal: flyoutTokens.contentPaddingHorizontal,
267
+ maxHeight
268
+ },
269
+ hidden: {
270
+ opacity: flyoutTokens.hiddenOpacity
271
+ }
272
+ });
273
+ }
274
+ export {
275
+ Flyout
276
+ };
277
+ //# sourceMappingURL=flyout.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/components/flyout.tsx"],"sourcesContent":["import {\r\n Fragment,\r\n memo,\r\n PropsWithChildren,\r\n useCallback,\r\n useEffect,\r\n useMemo,\r\n useRef,\r\n useState,\r\n} from \"react\";\r\nimport {\r\n LayoutChangeEvent,\r\n Pressable,\r\n StyleSheet,\r\n useWindowDimensions,\r\n} from \"react-native\";\r\nimport { Gesture, GestureDetector } from \"react-native-gesture-handler\";\r\nimport Animated, {\r\n Easing,\r\n useAnimatedStyle,\r\n useSharedValue,\r\n withSpring,\r\n withTiming,\r\n} from \"react-native-reanimated\";\r\nimport {\r\n Edge,\r\n SafeAreaView,\r\n useSafeAreaInsets,\r\n} from \"react-native-safe-area-context\";\r\nimport { scheduleOnRN } from \"react-native-worklets\";\r\n\r\nimport { View } from \"@impulse-ui-native/primitives\";\r\nimport { AppTheme, useTheme } from \"@impulse-ui-native/theme\";\r\n\r\nimport { FlyoutHandleHeight } from \"../constants\";\r\nimport { FlyoutProps } from \"../types\";\r\nimport { FlyoutHandle } from \"./flyout-handle\";\r\nimport { FlyoutTitle } from \"./flyout-title\";\r\n\r\nconst EnterAnimationConfig = {\r\n damping: 50,\r\n stiffness: 300,\r\n mass: 1,\r\n overshootClamping: true,\r\n};\r\n\r\nconst ExitAnimationConfig = {\r\n duration: 150,\r\n easing: Easing.in(Easing.quad),\r\n};\r\n\r\nexport const Flyout = memo(function Flyout(\r\n props: PropsWithChildren<FlyoutProps>,\r\n) {\r\n const {\r\n id,\r\n children,\r\n placement = \"bottom\",\r\n layer = 0,\r\n title,\r\n open,\r\n topOffset,\r\n bottomOffset,\r\n onCloseFinished,\r\n onClose,\r\n onOpen,\r\n onOpenFinished,\r\n } = props;\r\n\r\n const theme = useTheme();\r\n const insets = useSafeAreaInsets();\r\n\r\n const windowDimensions = useWindowDimensions();\r\n\r\n const flyoutTokens = theme.components.flyout;\r\n\r\n const placementOffset = placement === \"top\" ? topOffset : bottomOffset;\r\n const screenHeight = windowDimensions.height;\r\n const maxHeight = screenHeight * flyoutTokens.maxHeightRatio;\r\n const zIndex = flyoutTokens.zIndexBase + layer;\r\n\r\n const [mounted, setMounted] = useState(open);\r\n const [measuredHeight, setMeasuredHeight] = useState<number | null>(null);\r\n const [hasMeasured, setHasMeasured] = useState(false);\r\n const [isTouchable, setIsTouchable] = useState(false);\r\n\r\n const didOpen = useRef(false);\r\n const isClosing = useRef(false);\r\n\r\n const translateY = useSharedValue(\r\n placement === \"top\" ? -screenHeight : screenHeight,\r\n );\r\n const opacity = useSharedValue(0);\r\n\r\n const onLayout = useCallback(\r\n (event: LayoutChangeEvent) => {\r\n if (measuredHeight !== null) {\r\n return;\r\n }\r\n\r\n const rawHeight = event.nativeEvent.layout.height;\r\n const clampedHeight = rawHeight + insets[placement] + FlyoutHandleHeight;\r\n\r\n translateY.value = placement === \"top\" ? -clampedHeight : clampedHeight;\r\n\r\n setMeasuredHeight(clampedHeight);\r\n setHasMeasured(true);\r\n },\r\n [insets, measuredHeight, placement, translateY],\r\n );\r\n\r\n const animateOut = useCallback(() => {\r\n if (measuredHeight === null || isClosing.current) {\r\n return;\r\n }\r\n\r\n isClosing.current = true;\r\n setIsTouchable(false);\r\n onClose?.(id);\r\n\r\n const target = placement === \"top\" ? -measuredHeight : measuredHeight;\r\n\r\n translateY.value = withTiming(target, ExitAnimationConfig, (finished) => {\r\n if (finished) {\r\n if (onCloseFinished) {\r\n scheduleOnRN(onCloseFinished, id);\r\n }\r\n\r\n scheduleOnRN(setMounted, false);\r\n scheduleOnRN(setMeasuredHeight, null);\r\n scheduleOnRN(setHasMeasured, false);\r\n }\r\n });\r\n\r\n opacity.value = withTiming(0, ExitAnimationConfig);\r\n didOpen.current = false;\r\n }, [\r\n id,\r\n measuredHeight,\r\n onClose,\r\n onCloseFinished,\r\n opacity,\r\n placement,\r\n translateY,\r\n ]);\r\n\r\n const dragGesture = useMemo(\r\n () =>\r\n Gesture.Pan()\r\n .enabled(hasMeasured)\r\n .onUpdate((event) => {\r\n if (placement === \"bottom\") {\r\n translateY.value = Math.max(0, event.translationY);\r\n return;\r\n }\r\n\r\n translateY.value = Math.min(0, event.translationY);\r\n })\r\n .onEnd((event) => {\r\n if (measuredHeight === null) {\r\n return;\r\n }\r\n\r\n let shouldClose = false;\r\n\r\n if (placement === \"bottom\") {\r\n shouldClose =\r\n event.translationY > measuredHeight * 0.5 ||\r\n event.velocityY > 1500;\r\n }\r\n\r\n if (placement === \"top\") {\r\n shouldClose =\r\n event.translationY < -measuredHeight * 0.5 ||\r\n event.velocityY < -1500;\r\n }\r\n\r\n if (shouldClose) {\r\n scheduleOnRN(animateOut);\r\n return;\r\n }\r\n\r\n translateY.value = withSpring(0, EnterAnimationConfig);\r\n opacity.value = withSpring(\r\n flyoutTokens.overlayVisibleOpacity,\r\n EnterAnimationConfig,\r\n );\r\n }),\r\n [\r\n animateOut,\r\n flyoutTokens.overlayVisibleOpacity,\r\n hasMeasured,\r\n measuredHeight,\r\n opacity,\r\n placement,\r\n translateY,\r\n ],\r\n );\r\n\r\n const animatedStyle = useAnimatedStyle(() => {\r\n const offset =\r\n placement === \"bottom\" ? -(placementOffset ?? 0) : (placementOffset ?? 0);\r\n\r\n return {\r\n transform: [{ translateY: translateY.value + offset }],\r\n zIndex,\r\n };\r\n });\r\n\r\n const overlayStyle = useAnimatedStyle(() => ({\r\n opacity: opacity.value,\r\n zIndex,\r\n backgroundColor: flyoutTokens.overlayColor,\r\n }));\r\n\r\n const edges = useMemo<Edge[]>(() => {\r\n return [placement, \"left\", \"right\"];\r\n }, [placement]);\r\n\r\n const styles = useMemo(() => {\r\n return themedStyles(theme, placement, maxHeight);\r\n }, [theme, placement, maxHeight]);\r\n\r\n useEffect(() => {\r\n if (!open) {\r\n return;\r\n }\r\n\r\n setMounted(true);\r\n setIsTouchable(false);\r\n setMeasuredHeight(null);\r\n setHasMeasured(false);\r\n\r\n isClosing.current = false;\r\n didOpen.current = false;\r\n\r\n translateY.value = placement === \"top\" ? -screenHeight : screenHeight;\r\n opacity.value = 0;\r\n }, [open, opacity, placement, screenHeight, translateY]);\r\n\r\n useEffect(() => {\r\n if (!open || measuredHeight === null || !hasMeasured || didOpen.current) {\r\n return;\r\n }\r\n\r\n setIsTouchable(true);\r\n onOpen?.(id);\r\n\r\n translateY.value = withSpring(0, EnterAnimationConfig, (finished) => {\r\n if (finished && onOpenFinished) {\r\n scheduleOnRN(onOpenFinished, id);\r\n }\r\n });\r\n\r\n opacity.value = withSpring(\r\n flyoutTokens.overlayVisibleOpacity,\r\n EnterAnimationConfig,\r\n );\r\n\r\n didOpen.current = true;\r\n }, [\r\n flyoutTokens.overlayVisibleOpacity,\r\n hasMeasured,\r\n id,\r\n measuredHeight,\r\n onOpen,\r\n onOpenFinished,\r\n opacity,\r\n open,\r\n translateY,\r\n ]);\r\n\r\n useEffect(() => {\r\n if (!open && didOpen.current) {\r\n animateOut();\r\n }\r\n }, [animateOut, open]);\r\n\r\n if (!mounted) {\r\n return null;\r\n }\r\n\r\n return (\r\n <Fragment>\r\n <Animated.View\r\n pointerEvents={isTouchable ? \"auto\" : \"none\"}\r\n style={[StyleSheet.absoluteFill, overlayStyle]}\r\n >\r\n <Pressable onPress={animateOut} style={StyleSheet.absoluteFill} />\r\n </Animated.View>\r\n\r\n <GestureDetector gesture={dragGesture}>\r\n <Animated.View\r\n onLayout={onLayout}\r\n style={[\r\n styles.container,\r\n !hasMeasured && styles.hidden,\r\n animatedStyle,\r\n ]}\r\n >\r\n <SafeAreaView edges={edges}>\r\n {placement === \"bottom\" ? (\r\n <FlyoutHandle placement={placement} />\r\n ) : null}\r\n\r\n {title ? <FlyoutTitle title={title} /> : null}\r\n\r\n <View style={styles.content}>{children}</View>\r\n\r\n {placement === \"top\" ? (\r\n <FlyoutHandle placement={placement} />\r\n ) : null}\r\n </SafeAreaView>\r\n </Animated.View>\r\n </GestureDetector>\r\n </Fragment>\r\n );\r\n});\r\n\r\nfunction themedStyles(\r\n theme: AppTheme,\r\n placement: \"top\" | \"bottom\",\r\n maxHeight: number,\r\n) {\r\n const flyoutTokens = theme.components.flyout;\r\n\r\n return StyleSheet.create({\r\n container: {\r\n position: \"absolute\",\r\n [placement]: 0,\r\n left: 0,\r\n right: 0,\r\n backgroundColor: flyoutTokens.backgroundColor,\r\n borderTopLeftRadius:\r\n placement === \"bottom\" ? flyoutTokens.borderRadius : 0,\r\n borderTopRightRadius:\r\n placement === \"bottom\" ? flyoutTokens.borderRadius : 0,\r\n borderBottomLeftRadius:\r\n placement === \"top\" ? flyoutTokens.borderRadius : 0,\r\n borderBottomRightRadius:\r\n placement === \"top\" ? flyoutTokens.borderRadius : 0,\r\n },\r\n content: {\r\n paddingHorizontal: flyoutTokens.contentPaddingHorizontal,\r\n maxHeight,\r\n },\r\n hidden: {\r\n opacity: flyoutTokens.hiddenOpacity,\r\n },\r\n });\r\n}\r\n"],"mappings":"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","names":["Flyout"]}
@@ -0,0 +1,5 @@
1
+ export { Flyout } from './flyout.mjs';
2
+ import 'react';
3
+ import 'react/jsx-runtime';
4
+ import '../types/flyout.types.mjs';
5
+ import '@impulse-ui-native/types';
@@ -0,0 +1,5 @@
1
+ import { Flyout } from "./flyout";
2
+ export {
3
+ Flyout
4
+ };
5
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/components/index.ts"],"sourcesContent":["export { Flyout } from \"./flyout\";\r\n"],"mappings":"AAAA,SAAS,cAAc;","names":[]}
@@ -0,0 +1,3 @@
1
+ declare const FlyoutHandleHeight = 32;
2
+
3
+ export { FlyoutHandleHeight };
@@ -0,0 +1,5 @@
1
+ const FlyoutHandleHeight = 32;
2
+ export {
3
+ FlyoutHandleHeight
4
+ };
5
+ //# sourceMappingURL=flyout-handle.constants.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/constants/flyout-handle.constants.ts"],"sourcesContent":["export const FlyoutHandleHeight = 32;\r\n"],"mappings":"AAAO,MAAM,qBAAqB;","names":[]}
@@ -0,0 +1 @@
1
+ export { FlyoutHandleHeight } from './flyout-handle.constants.mjs';
@@ -0,0 +1,2 @@
1
+ export * from "./flyout-handle.constants";
2
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/constants/index.ts"],"sourcesContent":["export * from \"./flyout-handle.constants\";\r\n"],"mappings":"AAAA,cAAc;","names":[]}
package/dist/index.d.mts CHANGED
@@ -1,15 +1,5 @@
1
- import * as react from 'react';
2
- import { PropsWithChildren } from 'react';
3
- import * as react_jsx_runtime from 'react/jsx-runtime';
4
- import { LayerComponentBaseProps } from '@impulse-ui-native/types';
5
-
6
- interface FlyoutProps extends LayerComponentBaseProps {
7
- open?: boolean;
8
- placement?: "top" | "bottom";
9
- topOffset?: number;
10
- bottomOffset?: number;
11
- }
12
-
13
- declare const Flyout: react.MemoExoticComponent<(props: PropsWithChildren<FlyoutProps>) => react_jsx_runtime.JSX.Element | null>;
14
-
15
- export { Flyout, type FlyoutProps };
1
+ export { Flyout } from './components/flyout.mjs';
2
+ export { FlyoutProps } from './types/flyout.types.mjs';
3
+ import 'react';
4
+ import 'react/jsx-runtime';
5
+ import '@impulse-ui-native/types';
package/dist/index.js CHANGED
@@ -1,343 +1,3 @@
1
- // src/components/flyout.tsx
2
- import {
3
- Fragment,
4
- memo as memo3,
5
- useCallback,
6
- useEffect,
7
- useMemo as useMemo2,
8
- useRef,
9
- useState
10
- } from "react";
11
- import {
12
- Pressable,
13
- StyleSheet as StyleSheet3,
14
- useWindowDimensions
15
- } from "react-native";
16
- import { Gesture, GestureDetector } from "react-native-gesture-handler";
17
- import Animated2, {
18
- Easing,
19
- useAnimatedStyle,
20
- useSharedValue,
21
- withSpring,
22
- withTiming
23
- } from "react-native-reanimated";
24
- import {
25
- SafeAreaView,
26
- useSafeAreaInsets
27
- } from "react-native-safe-area-context";
28
- import { scheduleOnRN } from "react-native-worklets";
29
- import { View as View3 } from "@impulse-ui-native/primitives";
30
- import { useTheme } from "@impulse-ui-native/theme";
31
-
32
- // src/constants/flyout-handle.constants.ts
33
- var FlyoutHandleHeight = 32;
34
-
35
- // src/components/flyout-handle.tsx
36
- import { memo } from "react";
37
- import { StyleSheet } from "react-native";
38
- import Animated from "react-native-reanimated";
39
- import { View } from "@impulse-ui-native/primitives";
40
- import { useThemedStyles } from "@impulse-ui-native/theme";
41
- import { jsx } from "react/jsx-runtime";
42
- var FlyoutHandle = memo(function FlyoutHandle2(props) {
43
- const styles = useThemedStyles(themedStyles, props, [props.placement]);
44
- return /* @__PURE__ */ jsx(Animated.View, { style: styles.flyoutHandleContainer, children: /* @__PURE__ */ jsx(View, { style: styles.flyoutHandle }) });
45
- });
46
- function themedStyles(theme, { placement }) {
47
- const handleTokens = theme.components.flyout.handle;
48
- return StyleSheet.create({
49
- flyoutHandle: {
50
- alignSelf: "center",
51
- backgroundColor: handleTokens.backgroundColor,
52
- width: handleTokens.width,
53
- height: handleTokens.height,
54
- borderRadius: handleTokens.borderRadius
55
- },
56
- flyoutHandleContainer: {
57
- position: "absolute",
58
- top: placement === "bottom" ? -handleTokens.containerHeight : void 0,
59
- bottom: placement === "top" ? -handleTokens.containerHeight : void 0,
60
- width: "100%",
61
- justifyContent: "center",
62
- alignItems: "center",
63
- height: handleTokens.containerHeight
64
- }
65
- });
66
- }
67
-
68
- // src/components/flyout-title.tsx
69
- import { memo as memo2, useMemo } from "react";
70
- import { StyleSheet as StyleSheet2 } from "react-native";
71
- import { Typography, View as View2 } from "@impulse-ui-native/primitives";
72
- import { useThemedStyles as useThemedStyles2 } from "@impulse-ui-native/theme";
73
- import { jsx as jsx2 } from "react/jsx-runtime";
74
- var FlyoutTitle = memo2(function FlyoutTitle2(props) {
75
- const styles = useThemedStyles2(themedStyles2);
76
- const title = useMemo(() => {
77
- if (typeof props.title === "string") {
78
- return /* @__PURE__ */ jsx2(Typography.Title3, { children: props.title });
79
- }
80
- return props.title;
81
- }, [props.title]);
82
- if (!props.title) {
83
- return null;
84
- }
85
- return /* @__PURE__ */ jsx2(View2, { style: styles.container, children: title });
86
- });
87
- function themedStyles2(theme) {
88
- const titleTokens = theme.components.flyout.title;
89
- return StyleSheet2.create({
90
- container: {
91
- paddingVertical: titleTokens.paddingVertical,
92
- paddingHorizontal: titleTokens.paddingHorizontal,
93
- alignItems: "center"
94
- }
95
- });
96
- }
97
-
98
- // src/components/flyout.tsx
99
- import { jsx as jsx3, jsxs } from "react/jsx-runtime";
100
- var EnterAnimationConfig = {
101
- damping: 50,
102
- stiffness: 300,
103
- mass: 1,
104
- overshootClamping: true
105
- };
106
- var ExitAnimationConfig = {
107
- duration: 150,
108
- easing: Easing.in(Easing.quad)
109
- };
110
- var Flyout = memo3(function Flyout2(props) {
111
- const {
112
- id,
113
- children,
114
- placement = "bottom",
115
- layer = 0,
116
- title,
117
- open,
118
- topOffset,
119
- bottomOffset,
120
- onCloseFinished,
121
- onClose,
122
- onOpen,
123
- onOpenFinished
124
- } = props;
125
- const theme = useTheme();
126
- const insets = useSafeAreaInsets();
127
- const windowDimensions = useWindowDimensions();
128
- const flyoutTokens = theme.components.flyout;
129
- const placementOffset = placement === "top" ? topOffset : bottomOffset;
130
- const screenHeight = windowDimensions.height;
131
- const maxHeight = screenHeight * flyoutTokens.maxHeightRatio;
132
- const zIndex = flyoutTokens.zIndexBase + layer;
133
- const [mounted, setMounted] = useState(open);
134
- const [measuredHeight, setMeasuredHeight] = useState(null);
135
- const [hasMeasured, setHasMeasured] = useState(false);
136
- const [isTouchable, setIsTouchable] = useState(false);
137
- const didOpen = useRef(false);
138
- const isClosing = useRef(false);
139
- const translateY = useSharedValue(
140
- placement === "top" ? -screenHeight : screenHeight
141
- );
142
- const opacity = useSharedValue(0);
143
- const onLayout = useCallback(
144
- (event) => {
145
- if (measuredHeight !== null) {
146
- return;
147
- }
148
- const rawHeight = event.nativeEvent.layout.height;
149
- const clampedHeight = rawHeight + insets[placement] + FlyoutHandleHeight;
150
- translateY.value = placement === "top" ? -clampedHeight : clampedHeight;
151
- setMeasuredHeight(clampedHeight);
152
- setHasMeasured(true);
153
- },
154
- [insets, measuredHeight, placement, translateY]
155
- );
156
- const animateOut = useCallback(() => {
157
- if (measuredHeight === null || isClosing.current) {
158
- return;
159
- }
160
- isClosing.current = true;
161
- setIsTouchable(false);
162
- onClose?.(id);
163
- const target = placement === "top" ? -measuredHeight : measuredHeight;
164
- translateY.value = withTiming(target, ExitAnimationConfig, (finished) => {
165
- if (finished) {
166
- if (onCloseFinished) {
167
- scheduleOnRN(onCloseFinished, id);
168
- }
169
- scheduleOnRN(setMounted, false);
170
- scheduleOnRN(setMeasuredHeight, null);
171
- scheduleOnRN(setHasMeasured, false);
172
- }
173
- });
174
- opacity.value = withTiming(0, ExitAnimationConfig);
175
- didOpen.current = false;
176
- }, [
177
- id,
178
- measuredHeight,
179
- onClose,
180
- onCloseFinished,
181
- opacity,
182
- placement,
183
- translateY
184
- ]);
185
- const dragGesture = useMemo2(
186
- () => Gesture.Pan().enabled(hasMeasured).onUpdate((event) => {
187
- if (placement === "bottom") {
188
- translateY.value = Math.max(0, event.translationY);
189
- return;
190
- }
191
- translateY.value = Math.min(0, event.translationY);
192
- }).onEnd((event) => {
193
- if (measuredHeight === null) {
194
- return;
195
- }
196
- let shouldClose = false;
197
- if (placement === "bottom") {
198
- shouldClose = event.translationY > measuredHeight * 0.5 || event.velocityY > 1500;
199
- }
200
- if (placement === "top") {
201
- shouldClose = event.translationY < -measuredHeight * 0.5 || event.velocityY < -1500;
202
- }
203
- if (shouldClose) {
204
- scheduleOnRN(animateOut);
205
- return;
206
- }
207
- translateY.value = withSpring(0, EnterAnimationConfig);
208
- opacity.value = withSpring(
209
- flyoutTokens.overlayVisibleOpacity,
210
- EnterAnimationConfig
211
- );
212
- }),
213
- [
214
- animateOut,
215
- flyoutTokens.overlayVisibleOpacity,
216
- hasMeasured,
217
- measuredHeight,
218
- opacity,
219
- placement,
220
- translateY
221
- ]
222
- );
223
- const animatedStyle = useAnimatedStyle(() => {
224
- const offset = placement === "bottom" ? -(placementOffset ?? 0) : placementOffset ?? 0;
225
- return {
226
- transform: [{ translateY: translateY.value + offset }],
227
- zIndex
228
- };
229
- });
230
- const overlayStyle = useAnimatedStyle(() => ({
231
- opacity: opacity.value,
232
- zIndex,
233
- backgroundColor: flyoutTokens.overlayColor
234
- }));
235
- const edges = useMemo2(() => {
236
- return [placement, "left", "right"];
237
- }, [placement]);
238
- const styles = useMemo2(() => {
239
- return themedStyles3(theme, placement, maxHeight);
240
- }, [theme, placement, maxHeight]);
241
- useEffect(() => {
242
- if (!open) {
243
- return;
244
- }
245
- setMounted(true);
246
- setIsTouchable(false);
247
- setMeasuredHeight(null);
248
- setHasMeasured(false);
249
- isClosing.current = false;
250
- didOpen.current = false;
251
- translateY.value = placement === "top" ? -screenHeight : screenHeight;
252
- opacity.value = 0;
253
- }, [open, opacity, placement, screenHeight, translateY]);
254
- useEffect(() => {
255
- if (!open || measuredHeight === null || !hasMeasured || didOpen.current) {
256
- return;
257
- }
258
- setIsTouchable(true);
259
- onOpen?.(id);
260
- translateY.value = withSpring(0, EnterAnimationConfig, (finished) => {
261
- if (finished && onOpenFinished) {
262
- scheduleOnRN(onOpenFinished, id);
263
- }
264
- });
265
- opacity.value = withSpring(
266
- flyoutTokens.overlayVisibleOpacity,
267
- EnterAnimationConfig
268
- );
269
- didOpen.current = true;
270
- }, [
271
- flyoutTokens.overlayVisibleOpacity,
272
- hasMeasured,
273
- id,
274
- measuredHeight,
275
- onOpen,
276
- onOpenFinished,
277
- opacity,
278
- open,
279
- translateY
280
- ]);
281
- useEffect(() => {
282
- if (!open && didOpen.current) {
283
- animateOut();
284
- }
285
- }, [animateOut, open]);
286
- if (!mounted) {
287
- return null;
288
- }
289
- return /* @__PURE__ */ jsxs(Fragment, { children: [
290
- /* @__PURE__ */ jsx3(
291
- Animated2.View,
292
- {
293
- pointerEvents: isTouchable ? "auto" : "none",
294
- style: [StyleSheet3.absoluteFill, overlayStyle],
295
- children: /* @__PURE__ */ jsx3(Pressable, { onPress: animateOut, style: StyleSheet3.absoluteFill })
296
- }
297
- ),
298
- /* @__PURE__ */ jsx3(GestureDetector, { gesture: dragGesture, children: /* @__PURE__ */ jsx3(
299
- Animated2.View,
300
- {
301
- onLayout,
302
- style: [
303
- styles.container,
304
- !hasMeasured && styles.hidden,
305
- animatedStyle
306
- ],
307
- children: /* @__PURE__ */ jsxs(SafeAreaView, { edges, children: [
308
- placement === "bottom" ? /* @__PURE__ */ jsx3(FlyoutHandle, { placement }) : null,
309
- title ? /* @__PURE__ */ jsx3(FlyoutTitle, { title }) : null,
310
- /* @__PURE__ */ jsx3(View3, { style: styles.content, children }),
311
- placement === "top" ? /* @__PURE__ */ jsx3(FlyoutHandle, { placement }) : null
312
- ] })
313
- }
314
- ) })
315
- ] });
316
- });
317
- function themedStyles3(theme, placement, maxHeight) {
318
- const flyoutTokens = theme.components.flyout;
319
- return StyleSheet3.create({
320
- container: {
321
- position: "absolute",
322
- [placement]: 0,
323
- left: 0,
324
- right: 0,
325
- backgroundColor: flyoutTokens.backgroundColor,
326
- borderTopLeftRadius: placement === "bottom" ? flyoutTokens.borderRadius : 0,
327
- borderTopRightRadius: placement === "bottom" ? flyoutTokens.borderRadius : 0,
328
- borderBottomLeftRadius: placement === "top" ? flyoutTokens.borderRadius : 0,
329
- borderBottomRightRadius: placement === "top" ? flyoutTokens.borderRadius : 0
330
- },
331
- content: {
332
- paddingHorizontal: flyoutTokens.contentPaddingHorizontal,
333
- maxHeight
334
- },
335
- hidden: {
336
- opacity: flyoutTokens.hiddenOpacity
337
- }
338
- });
339
- }
340
- export {
341
- Flyout
342
- };
1
+ export * from "./components";
2
+ export * from "./types";
343
3
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/components/flyout.tsx","../src/constants/flyout-handle.constants.ts","../src/components/flyout-handle.tsx","../src/components/flyout-title.tsx"],"sourcesContent":["import {\r\n Fragment,\r\n memo,\r\n PropsWithChildren,\r\n useCallback,\r\n useEffect,\r\n useMemo,\r\n useRef,\r\n useState,\r\n} from \"react\";\r\nimport {\r\n LayoutChangeEvent,\r\n Pressable,\r\n StyleSheet,\r\n useWindowDimensions,\r\n} from \"react-native\";\r\nimport { Gesture, GestureDetector } from \"react-native-gesture-handler\";\r\nimport Animated, {\r\n Easing,\r\n useAnimatedStyle,\r\n useSharedValue,\r\n withSpring,\r\n withTiming,\r\n} from \"react-native-reanimated\";\r\nimport {\r\n Edge,\r\n SafeAreaView,\r\n useSafeAreaInsets,\r\n} from \"react-native-safe-area-context\";\r\nimport { scheduleOnRN } from \"react-native-worklets\";\r\n\r\nimport { View } from \"@impulse-ui-native/primitives\";\r\nimport { AppTheme, useTheme } from \"@impulse-ui-native/theme\";\r\n\r\nimport { FlyoutHandleHeight } from \"../constants\";\r\nimport { FlyoutProps } from \"../types\";\r\nimport { FlyoutHandle } from \"./flyout-handle\";\r\nimport { FlyoutTitle } from \"./flyout-title\";\r\n\r\nconst EnterAnimationConfig = {\r\n damping: 50,\r\n stiffness: 300,\r\n mass: 1,\r\n overshootClamping: true,\r\n};\r\n\r\nconst ExitAnimationConfig = {\r\n duration: 150,\r\n easing: Easing.in(Easing.quad),\r\n};\r\n\r\nexport const Flyout = memo(function Flyout(\r\n props: PropsWithChildren<FlyoutProps>,\r\n) {\r\n const {\r\n id,\r\n children,\r\n placement = \"bottom\",\r\n layer = 0,\r\n title,\r\n open,\r\n topOffset,\r\n bottomOffset,\r\n onCloseFinished,\r\n onClose,\r\n onOpen,\r\n onOpenFinished,\r\n } = props;\r\n\r\n const theme = useTheme();\r\n const insets = useSafeAreaInsets();\r\n\r\n const windowDimensions = useWindowDimensions();\r\n\r\n const flyoutTokens = theme.components.flyout;\r\n\r\n const placementOffset = placement === \"top\" ? topOffset : bottomOffset;\r\n const screenHeight = windowDimensions.height;\r\n const maxHeight = screenHeight * flyoutTokens.maxHeightRatio;\r\n const zIndex = flyoutTokens.zIndexBase + layer;\r\n\r\n const [mounted, setMounted] = useState(open);\r\n const [measuredHeight, setMeasuredHeight] = useState<number | null>(null);\r\n const [hasMeasured, setHasMeasured] = useState(false);\r\n const [isTouchable, setIsTouchable] = useState(false);\r\n\r\n const didOpen = useRef(false);\r\n const isClosing = useRef(false);\r\n\r\n const translateY = useSharedValue(\r\n placement === \"top\" ? -screenHeight : screenHeight,\r\n );\r\n const opacity = useSharedValue(0);\r\n\r\n const onLayout = useCallback(\r\n (event: LayoutChangeEvent) => {\r\n if (measuredHeight !== null) {\r\n return;\r\n }\r\n\r\n const rawHeight = event.nativeEvent.layout.height;\r\n const clampedHeight = rawHeight + insets[placement] + FlyoutHandleHeight;\r\n\r\n translateY.value = placement === \"top\" ? -clampedHeight : clampedHeight;\r\n\r\n setMeasuredHeight(clampedHeight);\r\n setHasMeasured(true);\r\n },\r\n [insets, measuredHeight, placement, translateY],\r\n );\r\n\r\n const animateOut = useCallback(() => {\r\n if (measuredHeight === null || isClosing.current) {\r\n return;\r\n }\r\n\r\n isClosing.current = true;\r\n setIsTouchable(false);\r\n onClose?.(id);\r\n\r\n const target = placement === \"top\" ? -measuredHeight : measuredHeight;\r\n\r\n translateY.value = withTiming(target, ExitAnimationConfig, (finished) => {\r\n if (finished) {\r\n if (onCloseFinished) {\r\n scheduleOnRN(onCloseFinished, id);\r\n }\r\n\r\n scheduleOnRN(setMounted, false);\r\n scheduleOnRN(setMeasuredHeight, null);\r\n scheduleOnRN(setHasMeasured, false);\r\n }\r\n });\r\n\r\n opacity.value = withTiming(0, ExitAnimationConfig);\r\n didOpen.current = false;\r\n }, [\r\n id,\r\n measuredHeight,\r\n onClose,\r\n onCloseFinished,\r\n opacity,\r\n placement,\r\n translateY,\r\n ]);\r\n\r\n const dragGesture = useMemo(\r\n () =>\r\n Gesture.Pan()\r\n .enabled(hasMeasured)\r\n .onUpdate((event) => {\r\n if (placement === \"bottom\") {\r\n translateY.value = Math.max(0, event.translationY);\r\n return;\r\n }\r\n\r\n translateY.value = Math.min(0, event.translationY);\r\n })\r\n .onEnd((event) => {\r\n if (measuredHeight === null) {\r\n return;\r\n }\r\n\r\n let shouldClose = false;\r\n\r\n if (placement === \"bottom\") {\r\n shouldClose =\r\n event.translationY > measuredHeight * 0.5 ||\r\n event.velocityY > 1500;\r\n }\r\n\r\n if (placement === \"top\") {\r\n shouldClose =\r\n event.translationY < -measuredHeight * 0.5 ||\r\n event.velocityY < -1500;\r\n }\r\n\r\n if (shouldClose) {\r\n scheduleOnRN(animateOut);\r\n return;\r\n }\r\n\r\n translateY.value = withSpring(0, EnterAnimationConfig);\r\n opacity.value = withSpring(\r\n flyoutTokens.overlayVisibleOpacity,\r\n EnterAnimationConfig,\r\n );\r\n }),\r\n [\r\n animateOut,\r\n flyoutTokens.overlayVisibleOpacity,\r\n hasMeasured,\r\n measuredHeight,\r\n opacity,\r\n placement,\r\n translateY,\r\n ],\r\n );\r\n\r\n const animatedStyle = useAnimatedStyle(() => {\r\n const offset =\r\n placement === \"bottom\" ? -(placementOffset ?? 0) : (placementOffset ?? 0);\r\n\r\n return {\r\n transform: [{ translateY: translateY.value + offset }],\r\n zIndex,\r\n };\r\n });\r\n\r\n const overlayStyle = useAnimatedStyle(() => ({\r\n opacity: opacity.value,\r\n zIndex,\r\n backgroundColor: flyoutTokens.overlayColor,\r\n }));\r\n\r\n const edges = useMemo<Edge[]>(() => {\r\n return [placement, \"left\", \"right\"];\r\n }, [placement]);\r\n\r\n const styles = useMemo(() => {\r\n return themedStyles(theme, placement, maxHeight);\r\n }, [theme, placement, maxHeight]);\r\n\r\n useEffect(() => {\r\n if (!open) {\r\n return;\r\n }\r\n\r\n setMounted(true);\r\n setIsTouchable(false);\r\n setMeasuredHeight(null);\r\n setHasMeasured(false);\r\n\r\n isClosing.current = false;\r\n didOpen.current = false;\r\n\r\n translateY.value = placement === \"top\" ? -screenHeight : screenHeight;\r\n opacity.value = 0;\r\n }, [open, opacity, placement, screenHeight, translateY]);\r\n\r\n useEffect(() => {\r\n if (!open || measuredHeight === null || !hasMeasured || didOpen.current) {\r\n return;\r\n }\r\n\r\n setIsTouchable(true);\r\n onOpen?.(id);\r\n\r\n translateY.value = withSpring(0, EnterAnimationConfig, (finished) => {\r\n if (finished && onOpenFinished) {\r\n scheduleOnRN(onOpenFinished, id);\r\n }\r\n });\r\n\r\n opacity.value = withSpring(\r\n flyoutTokens.overlayVisibleOpacity,\r\n EnterAnimationConfig,\r\n );\r\n\r\n didOpen.current = true;\r\n }, [\r\n flyoutTokens.overlayVisibleOpacity,\r\n hasMeasured,\r\n id,\r\n measuredHeight,\r\n onOpen,\r\n onOpenFinished,\r\n opacity,\r\n open,\r\n translateY,\r\n ]);\r\n\r\n useEffect(() => {\r\n if (!open && didOpen.current) {\r\n animateOut();\r\n }\r\n }, [animateOut, open]);\r\n\r\n if (!mounted) {\r\n return null;\r\n }\r\n\r\n return (\r\n <Fragment>\r\n <Animated.View\r\n pointerEvents={isTouchable ? \"auto\" : \"none\"}\r\n style={[StyleSheet.absoluteFill, overlayStyle]}\r\n >\r\n <Pressable onPress={animateOut} style={StyleSheet.absoluteFill} />\r\n </Animated.View>\r\n\r\n <GestureDetector gesture={dragGesture}>\r\n <Animated.View\r\n onLayout={onLayout}\r\n style={[\r\n styles.container,\r\n !hasMeasured && styles.hidden,\r\n animatedStyle,\r\n ]}\r\n >\r\n <SafeAreaView edges={edges}>\r\n {placement === \"bottom\" ? (\r\n <FlyoutHandle placement={placement} />\r\n ) : null}\r\n\r\n {title ? <FlyoutTitle title={title} /> : null}\r\n\r\n <View style={styles.content}>{children}</View>\r\n\r\n {placement === \"top\" ? (\r\n <FlyoutHandle placement={placement} />\r\n ) : null}\r\n </SafeAreaView>\r\n </Animated.View>\r\n </GestureDetector>\r\n </Fragment>\r\n );\r\n});\r\n\r\nfunction themedStyles(\r\n theme: AppTheme,\r\n placement: \"top\" | \"bottom\",\r\n maxHeight: number,\r\n) {\r\n const flyoutTokens = theme.components.flyout;\r\n\r\n return StyleSheet.create({\r\n container: {\r\n position: \"absolute\",\r\n [placement]: 0,\r\n left: 0,\r\n right: 0,\r\n backgroundColor: flyoutTokens.backgroundColor,\r\n borderTopLeftRadius:\r\n placement === \"bottom\" ? flyoutTokens.borderRadius : 0,\r\n borderTopRightRadius:\r\n placement === \"bottom\" ? flyoutTokens.borderRadius : 0,\r\n borderBottomLeftRadius:\r\n placement === \"top\" ? flyoutTokens.borderRadius : 0,\r\n borderBottomRightRadius:\r\n placement === \"top\" ? flyoutTokens.borderRadius : 0,\r\n },\r\n content: {\r\n paddingHorizontal: flyoutTokens.contentPaddingHorizontal,\r\n maxHeight,\r\n },\r\n hidden: {\r\n opacity: flyoutTokens.hiddenOpacity,\r\n },\r\n });\r\n}\r\n","export const FlyoutHandleHeight = 32;\r\n","import { memo } from \"react\";\r\nimport { StyleSheet } from \"react-native\";\r\nimport Animated from \"react-native-reanimated\";\r\n\r\nimport { View } from \"@impulse-ui-native/primitives\";\r\nimport { AppTheme, useThemedStyles } from \"@impulse-ui-native/theme\";\r\n\r\ninterface FlyoutHandleProps {\r\n placement: \"top\" | \"bottom\";\r\n}\r\n\r\nexport const FlyoutHandle = memo(function FlyoutHandle(\r\n props: FlyoutHandleProps,\r\n) {\r\n const styles = useThemedStyles(themedStyles, props, [props.placement]);\r\n\r\n return (\r\n <Animated.View style={styles.flyoutHandleContainer}>\r\n <View style={styles.flyoutHandle} />\r\n </Animated.View>\r\n );\r\n});\r\n\r\nfunction themedStyles(\r\n theme: AppTheme,\r\n { placement }: { placement: \"top\" | \"bottom\" },\r\n) {\r\n const handleTokens = theme.components.flyout.handle;\r\n\r\n return StyleSheet.create({\r\n flyoutHandle: {\r\n alignSelf: \"center\",\r\n backgroundColor: handleTokens.backgroundColor,\r\n width: handleTokens.width,\r\n height: handleTokens.height,\r\n borderRadius: handleTokens.borderRadius,\r\n },\r\n flyoutHandleContainer: {\r\n position: \"absolute\",\r\n top: placement === \"bottom\" ? -handleTokens.containerHeight : undefined,\r\n bottom: placement === \"top\" ? -handleTokens.containerHeight : undefined,\r\n width: \"100%\",\r\n justifyContent: \"center\",\r\n alignItems: \"center\",\r\n height: handleTokens.containerHeight,\r\n },\r\n });\r\n}\r\n","import { memo, ReactNode, useMemo } from \"react\";\r\nimport { StyleSheet } from \"react-native\";\r\n\r\nimport { Typography, View } from \"@impulse-ui-native/primitives\";\r\nimport { AppTheme, useThemedStyles } from \"@impulse-ui-native/theme\";\r\n\r\ninterface FlyoutTitleProps {\r\n title?: ReactNode | string;\r\n}\r\n\r\nexport const FlyoutTitle = memo(function FlyoutTitle(props: FlyoutTitleProps) {\r\n const styles = useThemedStyles(themedStyles);\r\n\r\n const title = useMemo(() => {\r\n if (typeof props.title === \"string\") {\r\n return <Typography.Title3>{props.title}</Typography.Title3>;\r\n }\r\n\r\n return props.title;\r\n }, [props.title]);\r\n\r\n if (!props.title) {\r\n return null;\r\n }\r\n\r\n return <View style={styles.container}>{title}</View>;\r\n});\r\n\r\nfunction themedStyles(theme: AppTheme) {\r\n const titleTokens = theme.components.flyout.title;\r\n\r\n return StyleSheet.create({\r\n container: {\r\n paddingVertical: titleTokens.paddingVertical,\r\n paddingHorizontal: titleTokens.paddingHorizontal,\r\n alignItems: \"center\",\r\n },\r\n });\r\n}\r\n"],"mappings":"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","names":["memo","useMemo","StyleSheet","Animated","View","FlyoutHandle","memo","StyleSheet","View","useThemedStyles","jsx","FlyoutTitle","themedStyles","jsx","memo","Flyout","useMemo","themedStyles","Animated","StyleSheet","View"]}
1
+ {"version":3,"sources":["../src/index.ts"],"sourcesContent":["export * from \"./components\";\r\nexport * from \"./types\";\r\n"],"mappings":"AAAA,cAAc;AACd,cAAc;","names":[]}
@@ -0,0 +1,10 @@
1
+ import { LayerComponentBaseProps } from '@impulse-ui-native/types';
2
+
3
+ interface FlyoutProps extends LayerComponentBaseProps {
4
+ open?: boolean;
5
+ placement?: "top" | "bottom";
6
+ topOffset?: number;
7
+ bottomOffset?: number;
8
+ }
9
+
10
+ export type { FlyoutProps };
@@ -0,0 +1 @@
1
+ //# sourceMappingURL=flyout.types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
@@ -0,0 +1,2 @@
1
+ export { FlyoutProps } from './flyout.types.mjs';
2
+ import '@impulse-ui-native/types';
@@ -0,0 +1,2 @@
1
+ export * from "./flyout.types";
2
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/types/index.ts"],"sourcesContent":["export * from \"./flyout.types\";\r\n"],"mappings":"AAAA,cAAc;","names":[]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@impulse-ui-native/flyout",
3
- "version": "2.1.0",
3
+ "version": "2.1.1",
4
4
  "source": "src/index.ts",
5
5
  "module": "dist/index.js",
6
6
  "types": "dist/index.d.mts",
@@ -17,11 +17,12 @@
17
17
  "README.md",
18
18
  "LICENSE"
19
19
  ],
20
+ "sideEffects": false,
20
21
  "dependencies": {
21
- "@impulse-ui-native/theme": "2.1.0",
22
- "@impulse-ui-native/core": "2.1.0",
23
- "@impulse-ui-native/primitives": "2.1.0",
24
- "@impulse-ui-native/types": "2.1.0"
22
+ "@impulse-ui-native/theme": "2.1.1",
23
+ "@impulse-ui-native/core": "2.1.1",
24
+ "@impulse-ui-native/types": "2.1.1",
25
+ "@impulse-ui-native/primitives": "2.1.1"
25
26
  },
26
27
  "devDependencies": {
27
28
  "@types/react": "~19.2.14",
@@ -34,9 +35,9 @@
34
35
  "react-native-safe-area-context": "~5.7.0",
35
36
  "react-native-worklets": "0.10.1",
36
37
  "typescript": "~6.0.3",
37
- "@impulse-ui-native/prettier-config": "1.0.0",
38
38
  "@impulse-ui-native/eslint-config": "1.0.0",
39
- "@impulse-ui-native/tsconfig": "1.0.0"
39
+ "@impulse-ui-native/tsconfig": "1.0.0",
40
+ "@impulse-ui-native/prettier-config": "1.0.0"
40
41
  },
41
42
  "peerDependencies": {
42
43
  "react": ">=18",