@hoddy-ui/core 1.1.3 → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -9,13 +9,19 @@ import {
9
9
  View,
10
10
  } from "react-native";
11
11
 
12
- import React, { useState } from "react";
12
+ import React, { useEffect, useState } from "react";
13
+ import Animated, {
14
+ runOnJS,
15
+ useAnimatedStyle,
16
+ useSharedValue,
17
+ withTiming,
18
+ } from "react-native-reanimated";
13
19
  import { ScaledSheet } from "react-native-size-matters";
14
20
  import { useColors, useTheme } from "../hooks";
21
+ import { UIThemeProvider } from "../theme";
15
22
  import { PopupProps } from "../types";
16
23
  import { IconButton } from "./Button";
17
24
  import Typography from "./Typography";
18
- import { UIThemeProvider } from "../theme";
19
25
 
20
26
  export const Popup: React.FC<PopupProps> = ({
21
27
  title,
@@ -26,11 +32,48 @@ export const Popup: React.FC<PopupProps> = ({
26
32
  open,
27
33
  onClose = () => {},
28
34
  style,
35
+ onModalShow,
36
+ onModalHide,
29
37
  }) => {
30
38
  const theme = useTheme();
31
39
  const colors = useColors();
32
- const [show, setShow] = useState(open);
33
- const [showSecondary, setShowSecondary] = useState(false);
40
+ const [modalVisible, setModalVisible] = useState(false);
41
+
42
+ // Animation values
43
+ const backdropOpacity = useSharedValue(0);
44
+ const contentTranslateY = useSharedValue(1000);
45
+
46
+ // Trigger animations when open prop changes
47
+ useEffect(() => {
48
+ if (open) {
49
+ setModalVisible(true);
50
+ // Opening animation
51
+ backdropOpacity.value = withTiming(1, { duration: 300 });
52
+ contentTranslateY.value = withTiming(0, { duration: 300 }, () => {
53
+ if (onModalShow) {
54
+ runOnJS(onModalShow)();
55
+ }
56
+ });
57
+ } else {
58
+ // Closing animation
59
+ backdropOpacity.value = withTiming(0, { duration: 200 });
60
+ contentTranslateY.value = withTiming(1000, { duration: 200 }, () => {
61
+ runOnJS(setModalVisible)(false);
62
+ if (onModalHide) {
63
+ runOnJS(onModalHide)();
64
+ }
65
+ });
66
+ }
67
+ }, [open]);
68
+
69
+ // Animated styles
70
+ const backdropAnimatedStyle = useAnimatedStyle(() => ({
71
+ opacity: backdropOpacity.value,
72
+ }));
73
+
74
+ const contentAnimatedStyle = useAnimatedStyle(() => ({
75
+ transform: [{ translateY: contentTranslateY.value }],
76
+ }));
34
77
 
35
78
  const styles: any = ScaledSheet.create({
36
79
  root: {
@@ -44,11 +87,10 @@ export const Popup: React.FC<PopupProps> = ({
44
87
  zIndex: 1000,
45
88
  alignSelf: "center",
46
89
  maxWidth: sheet ? undefined : "90%",
47
-
48
90
  width: sheet ? "100%" : undefined,
49
91
  },
50
92
  container: {
51
- paddingBottom: sheet ? "30@ms" : 0,
93
+ paddingBottom: sheet ? "30@ms" : undefined,
52
94
  backgroundColor: theme === "dark" ? "#111" : colors.white[2],
53
95
  borderTopLeftRadius: 20,
54
96
  borderTopRightRadius: 20,
@@ -59,7 +101,6 @@ export const Popup: React.FC<PopupProps> = ({
59
101
  },
60
102
  content: {
61
103
  paddingHorizontal: bare ? undefined : "15@ms",
62
- // flex: 1,
63
104
  },
64
105
  title: {
65
106
  flexDirection: "row",
@@ -80,81 +121,57 @@ export const Popup: React.FC<PopupProps> = ({
80
121
  },
81
122
  });
82
123
 
83
- React.useEffect(() => {
84
- if (open) {
85
- setShow(open);
86
- setTimeout(() => {
87
- setShowSecondary(open);
88
- }, 500);
89
- } else {
90
- closeAction();
91
- }
92
- }, [open]);
93
-
94
124
  const closeAction = () => {
95
- setShowSecondary(false);
96
- setTimeout(() => {
97
- setShow(false);
98
- onClose();
99
- }, 300);
125
+ onClose();
100
126
  };
101
127
 
102
128
  return (
103
- <>
104
- <Modal
105
- transparent
106
- animationType="fade"
107
- statusBarTranslucent
108
- visible={show}
109
- onRequestClose={closeAction}
110
- >
111
- <View style={styles.backdrop} />
112
- <UIThemeProvider>
113
- <Modal
114
- transparent
115
- animationType="slide"
116
- statusBarTranslucent
117
- visible={showSecondary}
118
- onRequestClose={closeAction}
119
- >
120
- <TouchableWithoutFeedback onPress={Keyboard.dismiss}>
121
- <View style={styles.root}>
122
- {open && (
123
- <Pressable
124
- style={StyleSheet.absoluteFill}
125
- onPress={closeAction}
126
- />
127
- )}
129
+ <Modal
130
+ transparent
131
+ animationType="none"
132
+ statusBarTranslucent
133
+ visible={modalVisible}
134
+ onRequestClose={closeAction}
135
+ >
136
+ <Animated.View style={[styles.backdrop, backdropAnimatedStyle]} />
137
+ <UIThemeProvider>
138
+ <TouchableWithoutFeedback onPress={Keyboard.dismiss}>
139
+ <View style={styles.root}>
140
+ {open && (
141
+ <Pressable
142
+ style={StyleSheet.absoluteFill}
143
+ onPress={closeAction}
144
+ />
145
+ )}
128
146
 
129
- <KeyboardAvoidingView
130
- style={styles.avoidingView}
131
- keyboardVerticalOffset={keyboardVerticalOffset}
132
- behavior={Platform.OS === "ios" ? "position" : "padding"}
133
- >
134
- <View style={styles.container}>
135
- {!bare && (
136
- <View style={styles.title}>
137
- <View style={styles.titleIcon}>
138
- <IconButton
139
- size={20}
140
- icon="close"
141
- onPress={closeAction}
142
- />
143
- </View>
144
- <Typography align="center" fontWeight={500}>
145
- {title}
146
- </Typography>
147
+ <Animated.View style={[styles.avoidingView, contentAnimatedStyle]}>
148
+ <KeyboardAvoidingView
149
+ keyboardVerticalOffset={keyboardVerticalOffset}
150
+ behavior={Platform.OS === "ios" ? "position" : "padding"}
151
+ >
152
+ <View style={styles.container}>
153
+ {!bare && (
154
+ <View style={styles.title}>
155
+ <View style={styles.titleIcon}>
156
+ <IconButton
157
+ size={20}
158
+ icon="close"
159
+ onPress={closeAction}
160
+ />
147
161
  </View>
148
- )}
162
+ <Typography align="center" fontWeight={500}>
163
+ {title}
164
+ </Typography>
165
+ </View>
166
+ )}
149
167
 
150
- <View style={styles.content}>{children}</View>
151
- </View>
152
- </KeyboardAvoidingView>
153
- </View>
154
- </TouchableWithoutFeedback>
155
- </Modal>
156
- </UIThemeProvider>
157
- </Modal>
158
- </>
168
+ <View style={styles.content}>{children}</View>
169
+ </View>
170
+ </KeyboardAvoidingView>
171
+ </Animated.View>
172
+ </View>
173
+ </TouchableWithoutFeedback>
174
+ </UIThemeProvider>
175
+ </Modal>
159
176
  );
160
177
  };
package/src/types.ts CHANGED
@@ -214,6 +214,9 @@ export interface PopupProps {
214
214
  open: boolean;
215
215
  onClose?: () => void;
216
216
  style?: ViewStyle;
217
+
218
+ onModalShow?: () => void;
219
+ onModalHide?: () => void;
217
220
  }
218
221
 
219
222
  export interface SpinnerProps {
@@ -1,137 +0,0 @@
1
- # Unified Animator Component
2
-
3
- The `Animator` component provides a single interface for all animation types with generic props.
4
-
5
- ## Features
6
-
7
- - **Single Component**: One component handles all animation types
8
- - **Generic Props**: Consistent prop naming across all animations (e.g., `closeAfter` instead of animation-specific names)
9
- - **Modular Hooks**: Animation logic is separated into individual custom hooks
10
- - **Type Safety**: Full TypeScript support with proper typing
11
- - **Performance**: Only the specified animation runs, others are not loaded
12
-
13
- ## Basic Usage
14
-
15
- ```tsx
16
- import { Animator } from 'hoddy-ui';
17
-
18
- // Fade animation
19
- <Animator type="fade" duration={1000} closeAfter={3000}>
20
- <Text>This will fade in and out</Text>
21
- </Animator>
22
-
23
- // Slide animation
24
- <Animator type="slide" direction="up" duration={800} closeAfter={2000}>
25
- <View>This will slide up from bottom</View>
26
- </Animator>
27
-
28
- // Grow animation
29
- <Animator type="grow" initialScale={0.5} duration={600}>
30
- <Button>This will grow from 50% scale</Button>
31
- </Animator>
32
-
33
- // Blink animation (continuous)
34
- <Animator type="blink" blinkDuration={1000} minOpacity={0.3}>
35
- <Icon>This will blink continuously</Icon>
36
- </Animator>
37
-
38
- // Float animation
39
- <Animator type="float" floatDistance={20} floatDuration={2000} closeAfter={5000}>
40
- <View>This will float up and down</View>
41
- </Animator>
42
-
43
- // Roll animation
44
- <Animator type="roll" initialRotate="45deg" duration={800}>
45
- <Image>This will roll and rotate</Image>
46
- </Animator>
47
-
48
- // Thrown up animation
49
- <Animator type="thrownup" delay={500} closeAfter={4000}>
50
- <Notification>This will spring up from bottom</Notification>
51
- </Animator>
52
- ```
53
-
54
- ## Generic Props
55
-
56
- All animation types support these generic props:
57
-
58
- - `type`: Animation type ("fade" | "grow" | "slide" | "blink" | "float" | "roll" | "thrownup")
59
- - `duration`: Animation duration in milliseconds
60
- - `delay`: Delay before animation starts
61
- - `closeAfter`: Time after which the exit animation starts (null for no exit)
62
- - `style`: Additional styles for the animated view
63
-
64
- ## Animation-Specific Props
65
-
66
- ### Slide Animation
67
-
68
- - `direction`: "up" | "down" | "left" | "right"
69
- - `initialValue`: Custom initial position value
70
-
71
- ### Grow Animation
72
-
73
- - `initialScale`: Starting scale (default: 0)
74
-
75
- ### Blink Animation
76
-
77
- - `blinkDuration`: Duration of one blink cycle
78
- - `minOpacity`: Minimum opacity value
79
- - `maxOpacity`: Maximum opacity value
80
-
81
- ### Float Animation
82
-
83
- - `closeDuration`: Duration of exit animation
84
- - `floatDistance`: Distance to float up/down
85
- - `floatDuration`: Duration of one float cycle
86
-
87
- ### Roll Animation
88
-
89
- - `initialTranslateY`: Initial vertical position
90
- - `initialRotate`: Initial rotation value
91
-
92
- ## Custom Hooks
93
-
94
- You can also use the animation hooks directly:
95
-
96
- ```tsx
97
- import { useFadeAnimation, useSlideAnimation } from "hoddy-ui";
98
-
99
- const MyComponent = () => {
100
- const { animatedStyle } = useFadeAnimation({
101
- duration: 800,
102
- closeAfter: 2000,
103
- });
104
-
105
- return (
106
- <Animated.View style={animatedStyle}>
107
- <Text>Custom animated content</Text>
108
- </Animated.View>
109
- );
110
- };
111
- ```
112
-
113
- ## Migration from Old Components
114
-
115
- Replace old individual animation components:
116
-
117
- ```tsx
118
- // Old way
119
- <AnimatedFade fadeOutAfter={2000}>
120
- <Text>Content</Text>
121
- </AnimatedFade>
122
-
123
- // New way
124
- <Animator type="fade" closeAfter={2000}>
125
- <Text>Content</Text>
126
- </Animator>
127
- ```
128
-
129
- ## Available Animation Types
130
-
131
- 1. **fade**: Simple fade in/out
132
- 2. **grow**: Scale-based growth animation
133
- 3. **slide**: Directional slide animations
134
- 4. **blink**: Continuous opacity blinking
135
- 5. **float**: Floating up/down motion with fade
136
- 6. **roll**: Combined rotation and translation
137
- 7. **thrownup**: Spring-based upward animation