@hoddy-ui/core 2.0.0 → 2.0.35

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/next/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hoddy-ui/next",
3
- "version": "2.0.47",
3
+ "version": "2.0.61",
4
4
  "description": "Core rich react native components written in typescript, with support for expo-router",
5
5
  "main": "./dist/index.js",
6
6
  "module": "./dist/index.mjs",
@@ -19,8 +19,9 @@
19
19
  },
20
20
  "peerDependencies": {
21
21
  "@expo/vector-icons": ">=13.0.0",
22
+ "@react-native-async-storage/async-storage": ">=1.18.1",
22
23
  "@types/react": ">=18.2.6",
23
- "@types/react-native": "^0.72.0",
24
+ "@types/react-native": ">=0.72.0",
24
25
  "expo-haptics": ">=12.4.0",
25
26
  "expo-location": ">=15.1.1",
26
27
  "expo-navigation-bar": ">=2.1.1",
@@ -28,6 +29,7 @@
28
29
  "expo-system-ui": ">=2.2.1",
29
30
  "react": ">=18.2.0",
30
31
  "react-native": ">=0.71.8",
32
+ "react-native-reanimated": ">=3.17.4",
31
33
  "react-native-safe-area-context": ">=4.5.3",
32
34
  "typescript": ">=5.0.4"
33
35
  },
@@ -39,7 +41,6 @@
39
41
  "kinghoddy"
40
42
  ],
41
43
  "dependencies": {
42
- "@react-native-async-storage/async-storage": "^1.18.1",
43
44
  "react-native-size-matters": "^0.4.0"
44
45
  },
45
46
  "devDependencies": {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hoddy-ui/core",
3
- "version": "2.0.0",
3
+ "version": "2.0.35",
4
4
  "description": "Core rich react native components written in typescript",
5
5
  "main": "index.ts",
6
6
  "repository": {
@@ -13,6 +13,7 @@
13
13
  "private": false,
14
14
  "peerDependencies": {
15
15
  "@expo/vector-icons": ">=13.0.0",
16
+ "@react-native-async-storage/async-storage": ">=1.18.1",
16
17
  "@react-navigation/native": ">=6.1.6",
17
18
  "@types/react": ">=18.2.6",
18
19
  "@types/react-native": ">=0.72.0",
@@ -34,7 +35,6 @@
34
35
  "kinghoddy"
35
36
  ],
36
37
  "dependencies": {
37
- "@react-native-async-storage/async-storage": "^1.18.1",
38
38
  "react-native-size-matters": "^0.4.2"
39
39
  },
40
40
  "publishConfig": {
@@ -1,7 +1,7 @@
1
1
  import { MaterialIcons } from "@expo/vector-icons";
2
2
  import React from "react";
3
3
  import { View } from "react-native";
4
- import { ScaledSheet } from "react-native-size-matters";
4
+ import { ms, ScaledSheet } from "react-native-size-matters";
5
5
  import { useColors } from "../hooks";
6
6
  import { AlertXProps } from "../types";
7
7
  import Typography from "./Typography";
@@ -16,7 +16,7 @@ const AlertX: React.FC<AlertXProps> = ({
16
16
  }) => {
17
17
  const colors = useColors();
18
18
 
19
- const styles: any = ScaledSheet.create({
19
+ const styles = ScaledSheet.create({
20
20
  container: {
21
21
  padding: 20,
22
22
  paddingTop: 10,
@@ -24,7 +24,7 @@ const AlertX: React.FC<AlertXProps> = ({
24
24
  borderRadius: 8,
25
25
  alignItems: "center",
26
26
  flexDirection: "row",
27
- marginBottom: gutterBottom + "@ms",
27
+ marginBottom: ms(gutterBottom),
28
28
  backgroundColor: colors[type].main + (variant === "contained" ? "" : "3"),
29
29
  },
30
30
  title: {
@@ -35,7 +35,7 @@ const AlertX: React.FC<AlertXProps> = ({
35
35
  },
36
36
  });
37
37
  return (
38
- <View style={{ ...styles.container, ...style }}>
38
+ <View style={[styles.container, style]}>
39
39
  <View style={{ width: "80%" }}>
40
40
  <Typography style={styles.title} gutterBottom={3} fontWeight={700}>
41
41
  {title}
@@ -40,9 +40,7 @@ export const useFadeAnimation = ({
40
40
  withTiming(1, { duration }, () => {
41
41
  if (closeAfter) {
42
42
  // Schedule fade-out after closeAfter duration
43
- setTimeout(() => {
44
- opacity.value = withTiming(0, { duration });
45
- }, closeAfter);
43
+ opacity.value = withDelay(closeAfter, withTiming(0, { duration }));
46
44
  }
47
45
  })
48
46
  );
@@ -64,11 +64,6 @@ export const useFloatAnimation = ({
64
64
  }
65
65
  };
66
66
 
67
- const stopFloating = () => {
68
- isFloating.current = false;
69
- translateY.value = withTiming(0, { duration: 200 });
70
- };
71
-
72
67
  useEffect(() => {
73
68
  if (!isActive && Platform.OS === "ios") {
74
69
  opacity.value = 0;
@@ -84,10 +79,15 @@ export const useFloatAnimation = ({
84
79
  startFloating();
85
80
 
86
81
  if (closeAfter) {
87
- setTimeout(() => {
88
- stopFloating();
89
- opacity.value = withTiming(0, { duration: closeDuration });
90
- }, closeAfter);
82
+ opacity.value = withDelay(
83
+ closeAfter,
84
+ withTiming(0, { duration: closeDuration })
85
+ );
86
+ translateY.value = withDelay(
87
+ closeAfter,
88
+ withTiming(0, { duration: closeDuration })
89
+ );
90
+ isFloating.current = false;
91
91
  }
92
92
  })
93
93
  );
@@ -48,12 +48,13 @@ export const useGrowAnimation = ({
48
48
  },
49
49
  () => {
50
50
  if (closeAfter) {
51
- setTimeout(() => {
52
- scale.value = withTiming(initialScale, {
51
+ scale.value = withDelay(
52
+ closeAfter,
53
+ withTiming(initialScale, {
53
54
  duration,
54
55
  easing: Easing.out(Easing.ease),
55
- });
56
- }, closeAfter);
56
+ })
57
+ );
57
58
  }
58
59
  }
59
60
  )
@@ -71,16 +71,20 @@ export const useRollAnimation = ({
71
71
  },
72
72
  () => {
73
73
  if (closeAfter) {
74
- setTimeout(() => {
75
- translateY.value = withTiming(initialTranslateY, {
74
+ translateY.value = withDelay(
75
+ closeAfter,
76
+ withTiming(initialTranslateY, {
76
77
  duration,
77
78
  easing: Easing.out(Easing.ease),
78
- });
79
- rotate.value = withTiming(0, {
79
+ })
80
+ );
81
+ rotate.value = withDelay(
82
+ closeAfter,
83
+ withTiming(0, {
80
84
  duration,
81
85
  easing: Easing.out(Easing.ease),
82
- });
83
- }, closeAfter);
86
+ })
87
+ );
84
88
  }
85
89
  }
86
90
  )
@@ -73,16 +73,13 @@ export const useSlideAnimation = ({
73
73
  );
74
74
 
75
75
  if (closeAfter) {
76
- const timer = setTimeout(() => {
77
- translateValue.value = withTiming(initialPosition, {
76
+ translateValue.value = withDelay(
77
+ closeAfter + duration + delay,
78
+ withTiming(initialPosition, {
78
79
  duration,
79
80
  easing: Easing.out(Easing.ease),
80
- });
81
- }, closeAfter + duration + delay);
82
-
83
- return () => {
84
- clearTimeout(timer);
85
- };
81
+ })
82
+ );
86
83
  }
87
84
  }, [
88
85
  translateValue,
@@ -50,22 +50,19 @@ export const useThrownUpAnimation = ({
50
50
  opacity.value = withDelay(delay, withTiming(1, { duration: 500 }));
51
51
 
52
52
  // Start timer to animate out after duration
53
- let timer: NodeJS.Timeout | null = null;
54
53
  if (closeAfter) {
55
- timer = setTimeout(() => {
56
- if (!isUnmounting.current) {
57
- translateY.value = withSpring(800, {
58
- velocity: 1,
59
- stiffness: 200,
60
- damping: 20,
61
- });
62
- opacity.value = withTiming(0, { duration: 500 });
63
- }
64
- }, closeAfter);
54
+ translateY.value = withDelay(
55
+ closeAfter,
56
+ withSpring(800, {
57
+ velocity: 1,
58
+ stiffness: 200,
59
+ damping: 20,
60
+ })
61
+ );
62
+ opacity.value = withDelay(closeAfter, withTiming(0, { duration: 500 }));
65
63
  }
66
64
 
67
65
  return () => {
68
- if (timer) clearTimeout(timer);
69
66
  translateY.value = 600;
70
67
  opacity.value = 0;
71
68
  isUnmounting.current = true;
@@ -1,7 +1,7 @@
1
1
  import { AntDesign } from "@expo/vector-icons";
2
- import React from "react";
2
+ import React, { useState } from "react";
3
3
  import { Image, View } from "react-native";
4
- import { ScaledSheet } from "react-native-size-matters";
4
+ import { ms, ScaledSheet } from "react-native-size-matters";
5
5
  import { useColors } from "../hooks";
6
6
  import { AvatarProps } from "../types";
7
7
  import Typography from "./Typography";
@@ -15,11 +15,12 @@ const Avatar: React.FC<AvatarProps> = ({
15
15
  style = {},
16
16
  }) => {
17
17
  const colors = useColors();
18
+ const [imageError, setImageError] = useState(false);
18
19
  const styles: any = ScaledSheet.create({
19
20
  root: {
20
21
  borderRadius: 150,
21
- height: size + "@ms",
22
- width: size + "@ms",
22
+ height: ms(size),
23
+ width: ms(size),
23
24
  alignItems: "center",
24
25
  justifyContent: "center",
25
26
  overflow: "hidden",
@@ -27,7 +28,7 @@ const Avatar: React.FC<AvatarProps> = ({
27
28
  borderColor: variant === "outlined" ? "#fff" : "#0000",
28
29
  backgroundColor:
29
30
  variant === "outlined"
30
- ? null
31
+ ? undefined
31
32
  : label
32
33
  ? colors[color].main
33
34
  : colors.white[4],
@@ -41,8 +42,13 @@ const Avatar: React.FC<AvatarProps> = ({
41
42
 
42
43
  return (
43
44
  <View style={styles.root}>
44
- {source ? (
45
- <Image resizeMode="cover" style={styles.image} source={source} />
45
+ {source && !imageError ? (
46
+ <Image
47
+ resizeMode="cover"
48
+ style={styles.image}
49
+ source={source}
50
+ onError={() => setImageError(true)}
51
+ />
46
52
  ) : label ? (
47
53
  <Typography style={{ color: colors[color].text }}>
48
54
  {label[0]}
@@ -1,17 +1,18 @@
1
1
  import { Ionicons, MaterialIcons } from "@expo/vector-icons";
2
2
  import React, { forwardRef } from "react";
3
3
  import { ActivityIndicator, Text, TouchableOpacity } from "react-native";
4
- import { ScaledSheet, moderateScale } from "react-native-size-matters";
4
+ import { ScaledSheet, moderateScale, ms } from "react-native-size-matters";
5
5
  import { getConfig } from "../config/KeyManager";
6
6
  import { useColors, useTheme } from "../hooks";
7
7
  import { ButtonProps, IconButtonProps, LinkButtonProps } from "../types";
8
+ import { getFontFamily } from "../utility";
8
9
 
9
10
  export const LinkButton: React.FC<LinkButtonProps> = ({
10
11
  title,
11
12
  style = {},
12
13
  color = "blue",
13
14
  fontSize = 12,
14
- fontWeight = "400",
15
+ fontWeight = 400,
15
16
  disabled,
16
17
  onPress = () => {},
17
18
  }) => {
@@ -20,8 +21,8 @@ export const LinkButton: React.FC<LinkButtonProps> = ({
20
21
  const styles: any = ScaledSheet.create({
21
22
  text: {
22
23
  fontSize: moderateScale(fontSize),
23
- fontWeight: fontWeight,
24
- fontFamily: getConfig().DEFAULT_FONT_FAMILY || "System",
24
+ fontWeight: fontWeight.toString() as any,
25
+ fontFamily: getFontFamily(fontWeight),
25
26
  color: disabled ? "#777" : colors[color].main,
26
27
  },
27
28
  });
@@ -51,7 +52,7 @@ export const IconButton: React.FC<IconButtonProps> = ({
51
52
  container: {
52
53
  alignSelf: "flex-start",
53
54
  flexGrow: 0,
54
- backgroundColor: bg ? bgColor : elevation! > 0 ? bgColor : null,
55
+ backgroundColor: bg ? bgColor : elevation! > 0 ? bgColor : undefined,
55
56
  padding: "5@ms",
56
57
  shadowColor: "#000",
57
58
  shadowOpacity: 0.1,
@@ -59,8 +60,8 @@ export const IconButton: React.FC<IconButtonProps> = ({
59
60
  height: 1,
60
61
  width: 0,
61
62
  },
62
- height: bg ? size + 20 + "@ms" : undefined,
63
- width: bg ? size + 20 + "@ms" : undefined,
63
+ height: bg ? ms(size + 20) : undefined,
64
+ width: bg ? ms(size + 20) : undefined,
64
65
  alignItems: "center",
65
66
  justifyContent: "center",
66
67
  shadowRadius: elevation,
@@ -118,7 +119,7 @@ const Button: React.FC<ButtonProps> = forwardRef(
118
119
  justifyContent: "center",
119
120
  backgroundColor:
120
121
  variant === "text" || variant === "outlined"
121
- ? null
122
+ ? undefined
122
123
  : translucent
123
124
  ? translucent === "dark"
124
125
  ? colors.white[3] + "22"
@@ -131,7 +132,7 @@ const Button: React.FC<ButtonProps> = forwardRef(
131
132
  borderRadius: rounded ? 30 : 10,
132
133
  elevation: variant === "text" ? 0 : elevation,
133
134
  paddingVertical:
134
- size === "small" ? 8 : size === "large" ? "15@ms" : "13@ms",
135
+ size === "small" ? 8 : size === "large" ? "15@mvs" : "13@mvs",
135
136
  paddingHorizontal: size === "small" ? "10@ms" : "18@ms",
136
137
  borderColor: colors[color].main,
137
138
  borderWidth: variant === "outlined" ? 1 : 0,
@@ -143,7 +144,7 @@ const Button: React.FC<ButtonProps> = forwardRef(
143
144
  width: 0,
144
145
  },
145
146
  shadowOpacity: variant === "text" ? 0 : 0.3,
146
- width: fullWidth ? "100%" : null,
147
+ width: fullWidth ? "100%" : undefined,
147
148
  ...style,
148
149
  },
149
150
  text: {
@@ -155,8 +156,8 @@ const Button: React.FC<ButtonProps> = forwardRef(
155
156
  variant === "text" || variant === "outlined" ? "main" : "text"
156
157
  ],
157
158
  fontWeight: variant === "outlined" ? "700" : "500",
158
- fontSize: size === "small" ? "12@ms" : "16@ms",
159
- fontFamily: getConfig().DEFAULT_FONT_FAMILY || "System",
159
+ fontSize: size === "small" ? "12@ms" : "13@ms",
160
+ fontFamily: getFontFamily(variant === "outlined" ? 700 : 500),
160
161
  },
161
162
  });
162
163
 
@@ -1,47 +1,111 @@
1
- import React, { useEffect, useState } from "react";
2
- import {
3
- LayoutAnimation,
4
- Touchable,
5
- TouchableOpacity,
6
- View,
7
- } from "react-native";
1
+ import React, { useEffect, useRef, useState } from "react";
2
+ import { TouchableOpacity, View } from "react-native";
3
+ import Animated, {
4
+ runOnJS,
5
+ useAnimatedStyle,
6
+ useSharedValue,
7
+ withTiming,
8
+ } from "react-native-reanimated";
8
9
  import { useSafeAreaInsets } from "react-native-safe-area-context";
9
10
  import { ScaledSheet } from "react-native-size-matters";
10
11
  import { useColors } from "../hooks";
11
- import { MaterialIcons } from "@expo/vector-icons";
12
12
  import { FlashMessageProps } from "../types";
13
13
  import Typography from "./Typography";
14
14
 
15
- export let showFlashMessage: (msg: FlashMessageProps) => void = () => {};
15
+ // Event-based API to decouple the trigger from the component instance
16
+ type FlashListener = (msg: FlashMessageProps) => void;
17
+ const flashListeners = new Set<FlashListener>();
18
+
19
+ export const showFlashMessage = (msg: FlashMessageProps) => {
20
+ flashListeners.forEach((listener) => listener(msg));
21
+ };
22
+
23
+ const subscribeToFlashMessages = (listener: FlashListener) => {
24
+ flashListeners.add(listener);
25
+ return () => {
26
+ flashListeners.delete(listener);
27
+ };
28
+ };
16
29
 
17
30
  const FlashMessage: React.FC = () => {
18
31
  const { top } = useSafeAreaInsets();
19
32
  const [message, setMessage] = useState<null | FlashMessageProps>(null);
20
- const [show, setShow] = useState(false);
21
33
  const colors = useColors();
22
34
  const type = message?.type || "success";
35
+ const timeoutRef = useRef<NodeJS.Timeout | null>(null);
36
+
37
+ // Animated values
38
+ const translateY = useSharedValue(-200);
39
+ const opacity = useSharedValue(0);
40
+
41
+ const hideMessage = () => {
42
+ setMessage(null);
43
+ };
44
+
45
+ const closeMessage = () => {
46
+ // Clear existing timeout if any
47
+ if (timeoutRef.current) {
48
+ clearTimeout(timeoutRef.current);
49
+ timeoutRef.current = null;
50
+ }
23
51
 
24
- showFlashMessage = (msg: FlashMessageProps) => {
25
- setMessage(msg);
26
- setTimeout(() => {
27
- setShow(true);
28
- }, 50);
29
-
30
- setTimeout(() => {
31
- setShow(false);
32
- setTimeout(() => {
33
- setMessage(null);
34
- }, 500);
35
- }, msg.duration || 3000);
52
+ // Animate out immediately
53
+ translateY.value = withTiming(-200, { duration: 300 });
54
+ opacity.value = withTiming(0, { duration: 300 }, () => {
55
+ runOnJS(hideMessage)();
56
+ });
36
57
  };
58
+
37
59
  useEffect(() => {
38
- LayoutAnimation.configureNext(LayoutAnimation.Presets.easeInEaseOut);
39
- }, [show]);
60
+ const listener: FlashListener = (msg) => {
61
+ // Clear existing timeout if any
62
+ if (timeoutRef.current) {
63
+ clearTimeout(timeoutRef.current);
64
+ timeoutRef.current = null;
65
+ }
66
+
67
+ // Reset position immediately before starting new animation
68
+ translateY.value = -200;
69
+ opacity.value = 0;
70
+
71
+ setMessage(msg);
72
+
73
+ // Animate in
74
+ translateY.value = withTiming(0, { duration: 300 });
75
+ opacity.value = withTiming(1, { duration: 300 });
76
+
77
+ // Animate out after duration
78
+ const duration = msg.duration || 3000;
79
+ timeoutRef.current = setTimeout(() => {
80
+ translateY.value = withTiming(-200, { duration: 300 });
81
+ opacity.value = withTiming(0, { duration: 300 }, () => {
82
+ runOnJS(hideMessage)();
83
+ });
84
+ timeoutRef.current = null;
85
+ }, duration);
86
+ };
87
+
88
+ const unsubscribe = subscribeToFlashMessages(listener);
89
+ return () => {
90
+ if (timeoutRef.current) {
91
+ clearTimeout(timeoutRef.current);
92
+ timeoutRef.current = null;
93
+ }
94
+ unsubscribe();
95
+ };
96
+ }, []);
97
+
98
+ const animatedStyle = useAnimatedStyle(() => {
99
+ return {
100
+ transform: [{ translateY: translateY.value }],
101
+ opacity: opacity.value,
102
+ };
103
+ });
40
104
 
41
105
  const styles = ScaledSheet.create({
42
106
  root: {
43
107
  position: "absolute",
44
- top: show ? 0 : -200,
108
+ top: 0,
45
109
  zIndex: 1000,
46
110
  left: 0,
47
111
  paddingTop: top + 10,
@@ -64,33 +128,46 @@ const FlashMessage: React.FC = () => {
64
128
  },
65
129
  });
66
130
 
131
+ if (!message) return null;
132
+
67
133
  return (
68
- <View style={styles.root}>
69
- <View style={{ flexDirection: "row" }}>
70
- <View style={{ flex: 1, marginRight: 10 }}>
71
- {message?.title && (
72
- <Typography
73
- variant="h6"
74
- fontWeight={600}
75
- gutterBottom={3}
76
- style={{ color: "#fff" }}
77
- >
78
- {message?.title}
134
+ <Animated.View style={[styles.root, animatedStyle]}>
135
+ <TouchableOpacity onPress={closeMessage} activeOpacity={0.9}>
136
+ <View style={{ flexDirection: "row" }}>
137
+ <View style={{ flex: 1, marginRight: 10 }}>
138
+ {message?.title && (
139
+ <Typography
140
+ variant="h6"
141
+ fontWeight={600}
142
+ gutterBottom={3}
143
+ style={{ color: "#fff" }}
144
+ >
145
+ {message?.title}
146
+ </Typography>
147
+ )}
148
+ <Typography style={{ color: "#fff" }}>
149
+ {message?.message}
79
150
  </Typography>
80
- )}
81
- <Typography style={{ color: "#fff" }}>{message?.message}</Typography>
151
+ </View>
152
+ {/* <MaterialIcons color="#fff" size={36} name="error-outline" /> */}
82
153
  </View>
83
- {/* <MaterialIcons color="#fff" size={36} name="error-outline" /> */}
84
- </View>
154
+ </TouchableOpacity>
85
155
 
86
156
  {message?.actions?.map((cur, i) => (
87
- <TouchableOpacity key={i} style={styles.action} onPress={cur.onPress}>
157
+ <TouchableOpacity
158
+ key={i}
159
+ style={styles.action}
160
+ onPress={() => {
161
+ cur.onPress?.();
162
+ closeMessage();
163
+ }}
164
+ >
88
165
  <Typography fontWeight={700} style={{ color: "#fff" }}>
89
166
  {cur.title}
90
167
  </Typography>
91
168
  </TouchableOpacity>
92
169
  ))}
93
- </View>
170
+ </Animated.View>
94
171
  );
95
172
  };
96
173
 
@@ -8,6 +8,7 @@ import {
8
8
  } from "react-native";
9
9
  import { ScaledSheet } from "react-native-size-matters";
10
10
  import { FormWrapperProps } from "../types";
11
+ import { useSafeAreaInsets } from "react-native-safe-area-context";
11
12
  export const FormWrapper: React.FC<FormWrapperProps> = ({
12
13
  children,
13
14
  behavior = Platform.OS === "ios" ? "padding" : "height",
@@ -17,6 +18,9 @@ export const FormWrapper: React.FC<FormWrapperProps> = ({
17
18
  style = {},
18
19
  onScroll,
19
20
  }) => {
21
+ const { bottom } = useSafeAreaInsets();
22
+
23
+ const defaultOffset = Platform.OS === "ios" ? -bottom : -bottom * 2;
20
24
  const styles = ScaledSheet.create({
21
25
  root: {
22
26
  width: "100%",
@@ -24,13 +28,14 @@ export const FormWrapper: React.FC<FormWrapperProps> = ({
24
28
  ...style,
25
29
  },
26
30
  });
31
+
27
32
  return mode === "static" ? (
28
33
  <TouchableWithoutFeedback onPress={Keyboard.dismiss} accessible={false}>
29
34
  <KeyboardAvoidingView
30
35
  style={styles.root}
31
36
  behavior={behavior}
32
37
  contentContainerStyle={styles.root}
33
- keyboardVerticalOffset={keyboardVerticalOffset}
38
+ keyboardVerticalOffset={keyboardVerticalOffset || defaultOffset}
34
39
  >
35
40
  {children}
36
41
  </KeyboardAvoidingView>
@@ -39,7 +44,7 @@ export const FormWrapper: React.FC<FormWrapperProps> = ({
39
44
  <KeyboardAvoidingView
40
45
  behavior={behavior}
41
46
  style={styles.root}
42
- keyboardVerticalOffset={keyboardVerticalOffset}
47
+ keyboardVerticalOffset={keyboardVerticalOffset || defaultOffset}
43
48
  >
44
49
  <ScrollView
45
50
  onScroll={onScroll}
@@ -1,6 +1,6 @@
1
- import { View, Text } from "react-native";
2
1
  import React from "react";
3
- import { ScaledSheet } from "react-native-size-matters";
2
+ import { View } from "react-native";
3
+ import { ms, ScaledSheet } from "react-native-size-matters";
4
4
  import { GridItemProps, GridProps } from "../types";
5
5
 
6
6
  export const GridItem: React.FC<GridItemProps> = ({
@@ -12,8 +12,8 @@ export const GridItem: React.FC<GridItemProps> = ({
12
12
  }) => {
13
13
  const styles = ScaledSheet.create({
14
14
  gridItem: {
15
- width: 100 / col + "%",
16
- padding: spacing * 10 + "@ms",
15
+ width: `${100 / col}%`,
16
+ padding: ms(spacing * 10),
17
17
  alignItems: alignItems,
18
18
  },
19
19
  });
@@ -27,7 +27,7 @@ export const Grid: React.FC<GridProps> = ({
27
27
  const styles = ScaledSheet.create({
28
28
  grid: {
29
29
  flexWrap: "wrap",
30
- margin: -spacing * 10 + "@ms",
30
+ margin: `${-spacing * 10}@ms`,
31
31
  flexDirection: "row",
32
32
  },
33
33
  });