@hoddy-ui/core 1.0.88 → 1.0.90
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/components/AdaptiveStatusBarNext.tsx +38 -0
- package/next/dist/index.d.mts +550 -0
- package/next/dist/index.d.ts +550 -0
- package/next/dist/index.js +2143 -0
- package/next/dist/index.js.map +1 -0
- package/next/dist/index.mjs +2110 -0
- package/next/dist/index.mjs.map +1 -0
- package/next/index.ts +33 -0
- package/next/package.json +51 -0
- package/next/tsup.config.ts +11 -0
- package/package.json +6 -6
- package/src/Components/Button.tsx +94 -81
- package/src/Components/Locator.tsx +3 -8
- package/src/Components/OTPInput.tsx +45 -26
- package/src/Components/Popup.tsx +13 -6
- package/src/Components/TextField.tsx +27 -28
- package/src/Components/Typography.tsx +60 -48
- package/src/config/KeyManager.ts +7 -6
- package/src/config/index.ts +4 -2
- package/src/types.ts +4 -1
|
@@ -9,20 +9,15 @@ import { ScaledSheet } from "react-native-size-matters";
|
|
|
9
9
|
import { useColors } from "../hooks";
|
|
10
10
|
import { LocatorProps } from "../types";
|
|
11
11
|
|
|
12
|
-
import {
|
|
12
|
+
import { getConfig } from "../config/KeyManager";
|
|
13
13
|
import Typography from "./Typography";
|
|
14
14
|
|
|
15
|
-
setTimeout(() => {
|
|
16
|
-
const { GOOGLE_MAP_API_KEY } = getApiKey();
|
|
17
|
-
if (GOOGLE_MAP_API_KEY) Location.setGoogleApiKey(GOOGLE_MAP_API_KEY);
|
|
18
|
-
}, 500);
|
|
19
|
-
|
|
20
15
|
type predictionType = {
|
|
21
16
|
id: string;
|
|
22
17
|
description: string;
|
|
23
18
|
};
|
|
24
19
|
export const getPredictionsFromCoords = async (coords: any) => {
|
|
25
|
-
const { GOOGLE_MAP_API_KEY } =
|
|
20
|
+
const { GOOGLE_MAP_API_KEY } = getConfig();
|
|
26
21
|
|
|
27
22
|
if (!GOOGLE_MAP_API_KEY)
|
|
28
23
|
console.error(
|
|
@@ -63,7 +58,7 @@ export const Locator: React.FC<LocatorProps> = ({
|
|
|
63
58
|
float = true,
|
|
64
59
|
country = "ng",
|
|
65
60
|
}) => {
|
|
66
|
-
const { GOOGLE_MAP_API_KEY } =
|
|
61
|
+
const { GOOGLE_MAP_API_KEY } = getConfig();
|
|
67
62
|
|
|
68
63
|
const [changed, setChanged] = useState(false);
|
|
69
64
|
const [value, setValue] = useState("");
|
|
@@ -1,5 +1,10 @@
|
|
|
1
|
-
import React, { FC, useMemo
|
|
2
|
-
import {
|
|
1
|
+
import React, { FC, useMemo } from "react";
|
|
2
|
+
import {
|
|
3
|
+
TextInput,
|
|
4
|
+
TouchableOpacity,
|
|
5
|
+
TouchableWithoutFeedback,
|
|
6
|
+
View,
|
|
7
|
+
} from "react-native";
|
|
3
8
|
import { ScaledSheet, ms } from "react-native-size-matters";
|
|
4
9
|
import { useColors } from "../hooks";
|
|
5
10
|
import { OTPInputProps } from "../types";
|
|
@@ -20,6 +25,42 @@ export const OTPInput: FC<OTPInputProps> = ({
|
|
|
20
25
|
[length]
|
|
21
26
|
);
|
|
22
27
|
|
|
28
|
+
console.log("v", value);
|
|
29
|
+
|
|
30
|
+
const onChangeHandler = (val: string, index: number) => {
|
|
31
|
+
if (value.length >= length && val.length > 0) return;
|
|
32
|
+
// Handle pasting of full OTP
|
|
33
|
+
if (val.length > 1) {
|
|
34
|
+
console.log("reached", val);
|
|
35
|
+
|
|
36
|
+
const digits = val.replace(/\D/g, "").slice(0, length);
|
|
37
|
+
onChange(digits);
|
|
38
|
+
if (digits.length === length) {
|
|
39
|
+
inputRefs[length - 1].current?.focus();
|
|
40
|
+
}
|
|
41
|
+
return;
|
|
42
|
+
}
|
|
43
|
+
// Handle backspace
|
|
44
|
+
if (val.length === 0) {
|
|
45
|
+
const newValue = value.slice(0, index) + value.slice(index + 1);
|
|
46
|
+
onChange(newValue);
|
|
47
|
+
if (index > 0) {
|
|
48
|
+
inputRefs[index - 1].current?.focus();
|
|
49
|
+
}
|
|
50
|
+
return;
|
|
51
|
+
}
|
|
52
|
+
// Only allow numbers and take first digit
|
|
53
|
+
const digit = val.replace(/\D/g, "").slice(0, 1);
|
|
54
|
+
if (!digit) return;
|
|
55
|
+
// Create new value string
|
|
56
|
+
const newValue = value.slice(0, index) + digit + value.slice(index + 1);
|
|
57
|
+
onChange(newValue);
|
|
58
|
+
// Auto advance to next input if not at end
|
|
59
|
+
if (index < length - 1) {
|
|
60
|
+
inputRefs[index + 1].current?.focus();
|
|
61
|
+
}
|
|
62
|
+
};
|
|
63
|
+
|
|
23
64
|
const colors = useColors();
|
|
24
65
|
const styles = ScaledSheet.create({
|
|
25
66
|
root: {},
|
|
@@ -45,32 +86,10 @@ export const OTPInput: FC<OTPInputProps> = ({
|
|
|
45
86
|
{[...Array(length)].map((_, index) => (
|
|
46
87
|
<TextInput
|
|
47
88
|
ref={inputRefs[index]}
|
|
48
|
-
onChangeText={(val) =>
|
|
49
|
-
if (val.length === 1) {
|
|
50
|
-
if (index !== length - 1) inputRefs[index + 1].current?.focus();
|
|
51
|
-
let text = value;
|
|
52
|
-
|
|
53
|
-
text = text.slice(0, index) + val + text.slice(index + 1);
|
|
54
|
-
onChange(text);
|
|
55
|
-
} else if (val.length === 0) {
|
|
56
|
-
if (index !== 0) {
|
|
57
|
-
inputRefs[index - 1].current?.focus();
|
|
58
|
-
let text = value;
|
|
59
|
-
|
|
60
|
-
text = text.slice(0, index);
|
|
61
|
-
onChange(text);
|
|
62
|
-
} else onChange("");
|
|
63
|
-
} else {
|
|
64
|
-
let text = val.replace(/\D/g, "").slice(0, length);
|
|
65
|
-
onChange(text);
|
|
66
|
-
inputRefs[
|
|
67
|
-
text.length < length - 1 ? text.length : length - 1
|
|
68
|
-
]?.current?.focus();
|
|
69
|
-
}
|
|
70
|
-
}}
|
|
89
|
+
onChangeText={(val) => onChangeHandler(val, index)}
|
|
71
90
|
value={value[index] || ""}
|
|
72
|
-
// maxLength={1}
|
|
73
91
|
blurOnSubmit={false}
|
|
92
|
+
// maxLength={1}
|
|
74
93
|
keyboardType="number-pad"
|
|
75
94
|
key={index}
|
|
76
95
|
style={[styles.input]}
|
package/src/Components/Popup.tsx
CHANGED
|
@@ -75,15 +75,22 @@ export const Popup: React.FC<PopupProps> = ({
|
|
|
75
75
|
});
|
|
76
76
|
|
|
77
77
|
React.useEffect(() => {
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
78
|
+
if (open) {
|
|
79
|
+
setShow(open);
|
|
80
|
+
setTimeout(() => {
|
|
81
|
+
setShowSecondary(open);
|
|
82
|
+
}, 500);
|
|
83
|
+
} else {
|
|
84
|
+
closeAction();
|
|
85
|
+
}
|
|
82
86
|
}, [open]);
|
|
83
87
|
|
|
84
88
|
const closeAction = () => {
|
|
85
|
-
|
|
86
|
-
|
|
89
|
+
setShowSecondary(false);
|
|
90
|
+
setTimeout(() => {
|
|
91
|
+
setShow(false);
|
|
92
|
+
onClose();
|
|
93
|
+
}, 300);
|
|
87
94
|
};
|
|
88
95
|
|
|
89
96
|
return (
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Ionicons, MaterialIcons } from "@expo/vector-icons";
|
|
2
|
-
import React, {
|
|
2
|
+
import React, { useRef, useState } from "react";
|
|
3
3
|
import { Animated, TextInput, TouchableOpacity, View } from "react-native";
|
|
4
4
|
import {
|
|
5
5
|
ScaledSheet,
|
|
@@ -7,6 +7,7 @@ import {
|
|
|
7
7
|
ms,
|
|
8
8
|
verticalScale,
|
|
9
9
|
} from "react-native-size-matters";
|
|
10
|
+
import { getConfig } from "../config/KeyManager";
|
|
10
11
|
import { useColors } from "../hooks";
|
|
11
12
|
import { TextFieldProps } from "../types";
|
|
12
13
|
import SelectMenu from "./SelectMenu";
|
|
@@ -38,13 +39,14 @@ const TextField: React.FC<TextFieldProps> = ({
|
|
|
38
39
|
}) => {
|
|
39
40
|
const colors = useColors();
|
|
40
41
|
const [focused, setFocused] = useState(false);
|
|
41
|
-
|
|
42
|
-
const labelAnim = useRef(new Animated.Value(0)).current;
|
|
43
|
-
|
|
44
42
|
const height =
|
|
45
43
|
moderateScale(variant === "text" ? 50 : 45) *
|
|
46
44
|
(size === "large" ? 1.2 : size === "small" ? 0.8 : 1);
|
|
47
45
|
|
|
46
|
+
const labelAnim = useRef(
|
|
47
|
+
new Animated.Value(height / moderateScale(variant === "text" ? 2.5 : 3.2))
|
|
48
|
+
).current;
|
|
49
|
+
|
|
48
50
|
React.useEffect(() => {
|
|
49
51
|
if (focused || value) {
|
|
50
52
|
Animated.timing(labelAnim, {
|
|
@@ -96,6 +98,7 @@ const TextField: React.FC<TextFieldProps> = ({
|
|
|
96
98
|
paddingLeft: variant === "text" ? 0 : moderateScale(15),
|
|
97
99
|
paddingRight: moderateScale(10),
|
|
98
100
|
paddingTop: "11@vs",
|
|
101
|
+
fontFamily: getConfig().DEFAULT_FONT_FAMILY || "System",
|
|
99
102
|
color: colors.black[1],
|
|
100
103
|
zIndex: 10,
|
|
101
104
|
// backgroundColor: "#284",
|
|
@@ -107,6 +110,7 @@ const TextField: React.FC<TextFieldProps> = ({
|
|
|
107
110
|
paddingTop: "13@ms",
|
|
108
111
|
},
|
|
109
112
|
label: {
|
|
113
|
+
fontFamily: getConfig().DEFAULT_FONT_FAMILY || "System",
|
|
110
114
|
position: "absolute",
|
|
111
115
|
left: variant === "text" ? 0 : moderateScale(15),
|
|
112
116
|
fontSize: focused || value ? "10@s" : "13@s",
|
|
@@ -213,9 +217,23 @@ const TextField: React.FC<TextFieldProps> = ({
|
|
|
213
217
|
style={styles.input}
|
|
214
218
|
/>
|
|
215
219
|
)}
|
|
216
|
-
{end &&
|
|
220
|
+
{end && (
|
|
221
|
+
<View
|
|
222
|
+
style={{
|
|
223
|
+
marginRight: 20,
|
|
224
|
+
paddingTop: variant === "text" ? ms(13) : 0,
|
|
225
|
+
}}
|
|
226
|
+
>
|
|
227
|
+
{end}
|
|
228
|
+
</View>
|
|
229
|
+
)}
|
|
217
230
|
{options && (
|
|
218
|
-
<View
|
|
231
|
+
<View
|
|
232
|
+
style={{
|
|
233
|
+
marginRight: variant === "text" ? 0 : 20,
|
|
234
|
+
paddingTop: variant === "text" ? ms(13) : 0,
|
|
235
|
+
}}
|
|
236
|
+
>
|
|
219
237
|
<Ionicons
|
|
220
238
|
name="chevron-down"
|
|
221
239
|
color={colors.textSecondary.main}
|
|
@@ -260,7 +278,6 @@ const TextField: React.FC<TextFieldProps> = ({
|
|
|
260
278
|
export const TextField2: React.FC<TextFieldProps> = ({
|
|
261
279
|
label,
|
|
262
280
|
keyboardType,
|
|
263
|
-
variant,
|
|
264
281
|
color = "primary",
|
|
265
282
|
value,
|
|
266
283
|
type,
|
|
@@ -284,33 +301,15 @@ export const TextField2: React.FC<TextFieldProps> = ({
|
|
|
284
301
|
const colors = useColors();
|
|
285
302
|
const [focused, _setFocused] = useState(false);
|
|
286
303
|
const [showPassword, setShowPassword] = useState(false);
|
|
287
|
-
const labelAnim = useRef(new Animated.Value(0)).current;
|
|
288
304
|
|
|
289
305
|
const height = moderateScale(
|
|
290
306
|
props.multiline ? 50 + (props.numberOfLines || 1) * 18 : 50
|
|
291
307
|
);
|
|
292
308
|
|
|
293
309
|
const setFocused = (value: boolean) => {
|
|
294
|
-
|
|
295
|
-
_setFocused(value);
|
|
296
|
-
});
|
|
310
|
+
_setFocused(value);
|
|
297
311
|
};
|
|
298
312
|
|
|
299
|
-
React.useEffect(() => {
|
|
300
|
-
if (focused || value) {
|
|
301
|
-
Animated.timing(labelAnim, {
|
|
302
|
-
toValue: verticalScale(5),
|
|
303
|
-
duration: 300,
|
|
304
|
-
useNativeDriver: false,
|
|
305
|
-
}).start();
|
|
306
|
-
} else {
|
|
307
|
-
Animated.timing(labelAnim, {
|
|
308
|
-
toValue: height / moderateScale(3),
|
|
309
|
-
duration: 300,
|
|
310
|
-
useNativeDriver: false,
|
|
311
|
-
}).start();
|
|
312
|
-
}
|
|
313
|
-
}, [focused, value]);
|
|
314
313
|
const styles: any = ScaledSheet.create({
|
|
315
314
|
root: {
|
|
316
315
|
marginBottom: gutterBottom + "@vs",
|
|
@@ -337,13 +336,13 @@ export const TextField2: React.FC<TextFieldProps> = ({
|
|
|
337
336
|
alignSelf: "stretch",
|
|
338
337
|
paddingLeft: moderateScale(10),
|
|
339
338
|
paddingRight: moderateScale(10),
|
|
340
|
-
color: colors.dark.
|
|
339
|
+
color: colors.dark.main,
|
|
341
340
|
zIndex: 10,
|
|
342
341
|
// backgroundColor: "#284",
|
|
343
342
|
},
|
|
344
343
|
inputText: {
|
|
345
344
|
fontSize: "14@ms",
|
|
346
|
-
color: colors.dark.
|
|
345
|
+
color: colors.dark.main,
|
|
347
346
|
paddingLeft: moderateScale(10),
|
|
348
347
|
},
|
|
349
348
|
placeholder: {
|
|
@@ -1,54 +1,66 @@
|
|
|
1
|
-
import React from "react";
|
|
2
|
-
import {
|
|
3
|
-
import { moderateScale,
|
|
1
|
+
import React, { forwardRef } from "react";
|
|
2
|
+
import { StyleSheet, Text } from "react-native";
|
|
3
|
+
import { moderateScale, verticalScale } from "react-native-size-matters";
|
|
4
4
|
import { useColors } from "../hooks";
|
|
5
5
|
import { TypographyProps } from "../types";
|
|
6
|
+
import { getConfig } from "../config/KeyManager";
|
|
6
7
|
|
|
7
|
-
const Typography: React.FC<TypographyProps> = (
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
h2: moderateScale(37),
|
|
23
|
-
h3: moderateScale(32),
|
|
24
|
-
h4: moderateScale(27),
|
|
25
|
-
h5: moderateScale(22),
|
|
26
|
-
h6: moderateScale(17),
|
|
27
|
-
body1: moderateScale(15),
|
|
28
|
-
body2: moderateScale(12),
|
|
29
|
-
caption: moderateScale(10),
|
|
30
|
-
};
|
|
31
|
-
const styles: any = StyleSheet.create({
|
|
32
|
-
text: {
|
|
33
|
-
fontSize: fontSize[variant],
|
|
34
|
-
marginBottom: verticalScale(gutterBottom) || 0,
|
|
35
|
-
color: colors[color]?.main || color,
|
|
36
|
-
textTransform: textCase,
|
|
37
|
-
alignItems: "center",
|
|
38
|
-
textAlign: align,
|
|
39
|
-
fontWeight: fontWeight.toString(),
|
|
8
|
+
const Typography: React.FC<TypographyProps> = forwardRef(
|
|
9
|
+
(
|
|
10
|
+
{
|
|
11
|
+
children,
|
|
12
|
+
color = "dark",
|
|
13
|
+
style = {},
|
|
14
|
+
textCase = null,
|
|
15
|
+
variant = "body1",
|
|
16
|
+
align = "left",
|
|
17
|
+
gutterBottom = 0,
|
|
18
|
+
numberOfLines,
|
|
19
|
+
adjustsFontSizeToFit,
|
|
20
|
+
fontWeight = 400,
|
|
21
|
+
fontFamily, // NEW PROP ADDED
|
|
22
|
+
...props
|
|
40
23
|
},
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
24
|
+
ref
|
|
25
|
+
) => {
|
|
26
|
+
const colors: any = useColors();
|
|
27
|
+
const fontSize = {
|
|
28
|
+
h1: moderateScale(42),
|
|
29
|
+
h2: moderateScale(37),
|
|
30
|
+
h3: moderateScale(32),
|
|
31
|
+
h4: moderateScale(27),
|
|
32
|
+
h5: moderateScale(22),
|
|
33
|
+
h6: moderateScale(17),
|
|
34
|
+
body1: moderateScale(15),
|
|
35
|
+
body2: moderateScale(12),
|
|
36
|
+
caption: moderateScale(10),
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
const styles: any = StyleSheet.create({
|
|
40
|
+
text: {
|
|
41
|
+
fontSize: fontSize[variant],
|
|
42
|
+
marginBottom: verticalScale(gutterBottom) || 0,
|
|
43
|
+
color: colors[color]?.main || color,
|
|
44
|
+
textTransform: textCase,
|
|
45
|
+
alignItems: "center",
|
|
46
|
+
textAlign: align,
|
|
47
|
+
fontWeight: fontWeight.toString(),
|
|
48
|
+
fontFamily: fontFamily || getConfig().DEFAULT_FONT_FAMILY || "System", // Use custom font if provided, else default
|
|
49
|
+
},
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
return (
|
|
53
|
+
<Text
|
|
54
|
+
ref={ref as any}
|
|
55
|
+
numberOfLines={numberOfLines}
|
|
56
|
+
adjustsFontSizeToFit={adjustsFontSizeToFit}
|
|
57
|
+
style={[styles.text, style]} // Ensures external styles are applied
|
|
58
|
+
{...props}
|
|
59
|
+
>
|
|
60
|
+
{children}
|
|
61
|
+
</Text>
|
|
62
|
+
);
|
|
63
|
+
}
|
|
64
|
+
);
|
|
52
65
|
|
|
53
|
-
<Typography color="#f90">col</Typography>;
|
|
54
66
|
export default Typography;
|
package/src/config/KeyManager.ts
CHANGED
|
@@ -1,15 +1,16 @@
|
|
|
1
|
-
type
|
|
1
|
+
type configTypes = {
|
|
2
2
|
GOOGLE_MAP_API_KEY?: string;
|
|
3
|
+
DEFAULT_FONT_FAMILY?: string;
|
|
3
4
|
};
|
|
4
5
|
|
|
5
|
-
let
|
|
6
|
+
let config: configTypes = {
|
|
6
7
|
GOOGLE_MAP_API_KEY: "",
|
|
7
8
|
};
|
|
8
9
|
|
|
9
|
-
export function
|
|
10
|
-
|
|
10
|
+
export function setConfig(key: configTypes): void {
|
|
11
|
+
config = key;
|
|
11
12
|
}
|
|
12
13
|
|
|
13
|
-
export function
|
|
14
|
-
return
|
|
14
|
+
export function getConfig(): configTypes {
|
|
15
|
+
return config;
|
|
15
16
|
}
|
package/src/config/index.ts
CHANGED
|
@@ -1,17 +1,19 @@
|
|
|
1
1
|
// import * as fs from "fs";
|
|
2
2
|
import { setExtraColors } from "../theme/colors";
|
|
3
3
|
import { extraColorTypes } from "../types";
|
|
4
|
-
import {
|
|
4
|
+
import { setConfig } from "./KeyManager";
|
|
5
5
|
|
|
6
6
|
type configProps = {
|
|
7
7
|
googleMapApiKey?: string;
|
|
8
8
|
colors?: extraColorTypes;
|
|
9
|
+
fontFamily?: string;
|
|
9
10
|
};
|
|
10
11
|
|
|
11
12
|
export function initialize(config: configProps): void {
|
|
12
13
|
try {
|
|
13
|
-
|
|
14
|
+
setConfig({
|
|
14
15
|
GOOGLE_MAP_API_KEY: config.googleMapApiKey,
|
|
16
|
+
DEFAULT_FONT_FAMILY: config.fontFamily,
|
|
15
17
|
});
|
|
16
18
|
if (config.colors) setExtraColors(config.colors);
|
|
17
19
|
} catch (error) {
|
package/src/types.ts
CHANGED
|
@@ -2,7 +2,9 @@ import { ReactNode } from "react";
|
|
|
2
2
|
import {
|
|
3
3
|
NativeScrollEvent,
|
|
4
4
|
NativeSyntheticEvent,
|
|
5
|
+
Text,
|
|
5
6
|
TextInputProps,
|
|
7
|
+
TextProps,
|
|
6
8
|
TextStyle,
|
|
7
9
|
ViewStyle,
|
|
8
10
|
} from "react-native";
|
|
@@ -252,7 +254,7 @@ export interface TextFieldProps extends TextInputProps {
|
|
|
252
254
|
onBlur?: () => void;
|
|
253
255
|
}
|
|
254
256
|
|
|
255
|
-
export interface TypographyProps {
|
|
257
|
+
export interface TypographyProps extends TextProps {
|
|
256
258
|
children: ReactNode;
|
|
257
259
|
color?: colorTypes | (string & {});
|
|
258
260
|
style?: TextStyle | ViewStyle;
|
|
@@ -271,6 +273,7 @@ export interface TypographyProps {
|
|
|
271
273
|
gutterBottom?: number;
|
|
272
274
|
numberOfLines?: number;
|
|
273
275
|
adjustsFontSizeToFit?: boolean;
|
|
276
|
+
fontFamily?: string;
|
|
274
277
|
fontWeight?: 200 | 300 | 400 | 500 | 600 | 700 | 800 | 900;
|
|
275
278
|
}
|
|
276
279
|
|