ripal-ui 1.1.394 → 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.
- package/README.md +3 -0
- package/components/Alert.jsx +74 -0
- package/components/Avatar.jsx +157 -0
- package/components/Button.jsx +58 -0
- package/components/COLORS.js +138 -0
- package/components/Checkbox.jsx +51 -0
- package/components/Dialog.jsx +221 -0
- package/components/Divider.jsx +62 -0
- package/components/Dropdown.jsx +229 -0
- package/components/Inline.jsx +37 -0
- package/components/Input.jsx +89 -0
- package/components/Rate.jsx +39 -0
- package/components/Slider.jsx +219 -0
- package/components/Switch.jsx +45 -0
- package/components/Table.jsx +67 -0
- package/components/Text.jsx +56 -0
- package/components/Toggle.jsx +88 -0
- package/index.js +16 -2
- package/package.json +20 -20
- package/babel.config.js +0 -3
- package/components/BottomSheet.tsx +0 -197
- package/components/Carousel.tsx +0 -61
- package/components/Circle.tsx +0 -44
- package/components/DatePicker.jsx +0 -181
- package/components/Tab.tsx +0 -90
- package/components/Table.tsx +0 -95
- package/components/index.ts +0 -5
- package/config.js +0 -4
- package/dist/BottomSheet.js +0 -186
- package/dist/Button.js +0 -109
- package/dist/Carousel.js +0 -52
- package/dist/Circle.js +0 -42
- package/dist/DatePicker.js +0 -199
- package/dist/Dialog.js +0 -81
- package/dist/Dropdown.js +0 -97
- package/dist/Inline.js +0 -38
- package/dist/Input.js +0 -88
- package/dist/ProgressBar.js +0 -64
- package/dist/Separator.js +0 -47
- package/dist/Skeleton.js +0 -62
- package/dist/Switch.js +0 -74
- package/dist/Tab.js +0 -85
- package/dist/Table.js +0 -96
- package/dist/Text.js +0 -78
- package/dist/Toast.js +0 -72
- package/dist/Toggle.js +0 -54
- package/dist/index.js +0 -96
- package/elements/Button.tsx +0 -121
- package/elements/ColorPicker.tsx +0 -70
- package/elements/Dialog.tsx +0 -87
- package/elements/Dropdown.tsx +0 -88
- package/elements/Inline.tsx +0 -52
- package/elements/Input.tsx +0 -83
- package/elements/ProgressBar.tsx +0 -52
- package/elements/SecureStorage.js +0 -27
- package/elements/Separator.tsx +0 -71
- package/elements/Skeleton.tsx +0 -64
- package/elements/Slider.tsx +0 -133
- package/elements/Switch.tsx +0 -63
- package/elements/Text.tsx +0 -95
- package/elements/Toast.tsx +0 -71
- package/elements/Toggle.tsx +0 -59
- package/elements/index.js +0 -14
- package/index.d.ts +0 -237
- package/scripts/generateConfig.js +0 -80
package/elements/Dialog.tsx
DELETED
|
@@ -1,87 +0,0 @@
|
|
|
1
|
-
import React from "react";
|
|
2
|
-
import { Pressable, StyleSheet, View, TouchableOpacity, ViewStyle } from "react-native";
|
|
3
|
-
import config from "../config";
|
|
4
|
-
import Text from "./Text";
|
|
5
|
-
import Inline from "./Inline";
|
|
6
|
-
|
|
7
|
-
interface DialogActionsProps {
|
|
8
|
-
children: React.ReactNode;
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
const DialogActions: React.FC<DialogActionsProps> = ({ children }) => {
|
|
12
|
-
return (
|
|
13
|
-
<Inline
|
|
14
|
-
justifyContent="flex-end"
|
|
15
|
-
gap={0}
|
|
16
|
-
style={{
|
|
17
|
-
...styles.action_area,
|
|
18
|
-
paddingTop: 20,
|
|
19
|
-
marginTop: 20 / 2,
|
|
20
|
-
}}
|
|
21
|
-
>
|
|
22
|
-
{children}
|
|
23
|
-
</Inline>
|
|
24
|
-
);
|
|
25
|
-
};
|
|
26
|
-
|
|
27
|
-
interface DialogProps {
|
|
28
|
-
spacer?: number;
|
|
29
|
-
children: React.ReactNode;
|
|
30
|
-
visible: boolean;
|
|
31
|
-
onDismiss: () => void;
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
const Dialog: React.FC<DialogProps> = ({ spacer = 20, children, visible, onDismiss }) => {
|
|
35
|
-
if (visible) {
|
|
36
|
-
return (
|
|
37
|
-
<>
|
|
38
|
-
<TouchableOpacity style={styles.overlay} />
|
|
39
|
-
<Pressable style={styles.container} onPress={onDismiss}>
|
|
40
|
-
<Pressable
|
|
41
|
-
style={{
|
|
42
|
-
...styles.content,
|
|
43
|
-
padding: spacer,
|
|
44
|
-
gap: spacer / 2,
|
|
45
|
-
}}
|
|
46
|
-
>
|
|
47
|
-
{children}
|
|
48
|
-
</Pressable>
|
|
49
|
-
</Pressable>
|
|
50
|
-
</>
|
|
51
|
-
);
|
|
52
|
-
}
|
|
53
|
-
return null; // Return null when not visible
|
|
54
|
-
};
|
|
55
|
-
|
|
56
|
-
const styles = StyleSheet.create({
|
|
57
|
-
overlay: {
|
|
58
|
-
backgroundColor: `#000000aa`,
|
|
59
|
-
position: 'absolute',
|
|
60
|
-
top: 0,
|
|
61
|
-
left: 0,
|
|
62
|
-
right: 0,
|
|
63
|
-
bottom: 0,
|
|
64
|
-
zIndex: 10,
|
|
65
|
-
},
|
|
66
|
-
container: {
|
|
67
|
-
position: 'absolute',
|
|
68
|
-
top: 0,
|
|
69
|
-
left: 0,
|
|
70
|
-
right: 0,
|
|
71
|
-
bottom: 0,
|
|
72
|
-
zIndex: 15,
|
|
73
|
-
alignItems: 'center',
|
|
74
|
-
justifyContent: 'center',
|
|
75
|
-
},
|
|
76
|
-
content: {
|
|
77
|
-
backgroundColor: '#fff',
|
|
78
|
-
width: '90%',
|
|
79
|
-
borderRadius: 12,
|
|
80
|
-
},
|
|
81
|
-
action_area: {
|
|
82
|
-
borderTopWidth: 1,
|
|
83
|
-
borderTopColor: config.colors.slate[200],
|
|
84
|
-
},
|
|
85
|
-
});
|
|
86
|
-
|
|
87
|
-
export { Dialog, DialogActions };
|
package/elements/Dropdown.tsx
DELETED
|
@@ -1,88 +0,0 @@
|
|
|
1
|
-
import React, { useState } from "react";
|
|
2
|
-
import { ScrollView, StyleSheet, View } from "react-native";
|
|
3
|
-
import config from "../config";
|
|
4
|
-
import Text from "./Text";
|
|
5
|
-
import Inline from "./Inline";
|
|
6
|
-
import Ionicons from "@expo/vector-icons/Ionicons";
|
|
7
|
-
|
|
8
|
-
type OptionType<T> =
|
|
9
|
-
| T[] // Array of objects
|
|
10
|
-
| string[]; // Array of strings
|
|
11
|
-
|
|
12
|
-
interface DropdownProps<T> {
|
|
13
|
-
options: OptionType<T>;
|
|
14
|
-
value: T | null;
|
|
15
|
-
setValue: (value: T) => void;
|
|
16
|
-
onChange?: (value: T) => void;
|
|
17
|
-
color?: string;
|
|
18
|
-
label?: string | null;
|
|
19
|
-
placeholder?: string;
|
|
20
|
-
objectKey?: keyof T | null; // Key for accessing properties if options are objects
|
|
21
|
-
withSearch?: boolean;
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
const Dropdown = <T,>({
|
|
25
|
-
options,
|
|
26
|
-
value,
|
|
27
|
-
setValue,
|
|
28
|
-
onChange,
|
|
29
|
-
color = config.colors.primary,
|
|
30
|
-
label = null,
|
|
31
|
-
placeholder = 'Choose',
|
|
32
|
-
objectKey = null,
|
|
33
|
-
withSearch = false,
|
|
34
|
-
}: DropdownProps<T>) => {
|
|
35
|
-
const [isExpanded, setExpanded] = useState(false);
|
|
36
|
-
const isObject = Array.isArray(options) && typeof options[0] === 'object';
|
|
37
|
-
|
|
38
|
-
return (
|
|
39
|
-
<View style={{ gap: 5 }}>
|
|
40
|
-
{label !== null && <Text size={12} weight="400Regular">{label}</Text>}
|
|
41
|
-
<View style={styles.area}>
|
|
42
|
-
<Inline onPress={() => setExpanded(!isExpanded)}>
|
|
43
|
-
<Text style={{ flexGrow: 1 }}>{value || placeholder}</Text>
|
|
44
|
-
<Ionicons name={isExpanded ? 'chevron-up-outline' : 'chevron-down-outline'} />
|
|
45
|
-
</Inline>
|
|
46
|
-
|
|
47
|
-
{isExpanded && (
|
|
48
|
-
<ScrollView style={{ maxHeight: 200 }}>
|
|
49
|
-
{(options as OptionType<T>).map((opt, o) => {
|
|
50
|
-
const isActive = isObject ? opt[objectKey as keyof T] === value : opt === value;
|
|
51
|
-
const displayValue = isObject ? opt[objectKey as keyof T] : opt;
|
|
52
|
-
|
|
53
|
-
return (
|
|
54
|
-
<Inline key={o} style={styles.item} onPress={() => {
|
|
55
|
-
if (onChange) {
|
|
56
|
-
onChange(opt);
|
|
57
|
-
} else {
|
|
58
|
-
setValue(isObject ? opt[objectKey as keyof T] : opt);
|
|
59
|
-
}
|
|
60
|
-
setExpanded(false);
|
|
61
|
-
}}>
|
|
62
|
-
<Text weight={isActive ? '600SemiBold' : '400Regular'} color={isActive ? color : config.colors.slate[500]}>
|
|
63
|
-
{displayValue}
|
|
64
|
-
</Text>
|
|
65
|
-
</Inline>
|
|
66
|
-
);
|
|
67
|
-
})}
|
|
68
|
-
</ScrollView>
|
|
69
|
-
)}
|
|
70
|
-
</View>
|
|
71
|
-
</View>
|
|
72
|
-
);
|
|
73
|
-
};
|
|
74
|
-
|
|
75
|
-
const styles = StyleSheet.create({
|
|
76
|
-
area: {
|
|
77
|
-
padding: 15,
|
|
78
|
-
borderWidth: 1,
|
|
79
|
-
borderColor: config.colors.slate[200],
|
|
80
|
-
borderRadius: 12,
|
|
81
|
-
gap: 15,
|
|
82
|
-
},
|
|
83
|
-
item: {
|
|
84
|
-
height: 40,
|
|
85
|
-
},
|
|
86
|
-
});
|
|
87
|
-
|
|
88
|
-
export default Dropdown;
|
package/elements/Inline.tsx
DELETED
|
@@ -1,52 +0,0 @@
|
|
|
1
|
-
import React from "react";
|
|
2
|
-
import { Pressable, PressableProps, StyleSheet, View, ViewStyle } from "react-native";
|
|
3
|
-
|
|
4
|
-
interface InlineProps extends PressableProps {
|
|
5
|
-
children: React.ReactNode;
|
|
6
|
-
alignItems?: "flex-start" | "flex-end" | "center" | "baseline" | "stretch";
|
|
7
|
-
justifyContent?: "flex-start" | "flex-end" | "center" | "space-between" | "space-around" | "space-evenly";
|
|
8
|
-
gap?: number;
|
|
9
|
-
style?: ViewStyle;
|
|
10
|
-
onPress?: () => void;
|
|
11
|
-
onLongPress?: () => void;
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
const Inline: React.FC<InlineProps> = ({
|
|
15
|
-
children,
|
|
16
|
-
alignItems = "center",
|
|
17
|
-
justifyContent = "flex-start",
|
|
18
|
-
gap = 20,
|
|
19
|
-
style,
|
|
20
|
-
onPress,
|
|
21
|
-
onLayout,
|
|
22
|
-
}) => {
|
|
23
|
-
return onPress ? (
|
|
24
|
-
<Pressable
|
|
25
|
-
style={{
|
|
26
|
-
flexDirection: 'row',
|
|
27
|
-
alignItems,
|
|
28
|
-
justifyContent,
|
|
29
|
-
gap,
|
|
30
|
-
...style,
|
|
31
|
-
}}
|
|
32
|
-
onPress={onPress}
|
|
33
|
-
onLayout={onLayout}
|
|
34
|
-
>
|
|
35
|
-
{children}
|
|
36
|
-
</Pressable>
|
|
37
|
-
) :
|
|
38
|
-
<View
|
|
39
|
-
style={{
|
|
40
|
-
flexDirection: 'row',
|
|
41
|
-
alignItems,
|
|
42
|
-
justifyContent,
|
|
43
|
-
gap,
|
|
44
|
-
...style,
|
|
45
|
-
}}
|
|
46
|
-
onLayout={onLayout}
|
|
47
|
-
>
|
|
48
|
-
{children}
|
|
49
|
-
</View>
|
|
50
|
-
};
|
|
51
|
-
|
|
52
|
-
export default Inline;
|
package/elements/Input.tsx
DELETED
|
@@ -1,83 +0,0 @@
|
|
|
1
|
-
import React, { useState } from "react";
|
|
2
|
-
import { View, TextInput, StyleSheet, TextInputProps, ViewStyle } from "react-native";
|
|
3
|
-
import Text from "./Text";
|
|
4
|
-
import Inline from "./Inline";
|
|
5
|
-
import config from "../config";
|
|
6
|
-
|
|
7
|
-
interface InputProps {
|
|
8
|
-
value?: string;
|
|
9
|
-
label?: string | null;
|
|
10
|
-
left?: React.ReactNode | null; // Allows for any valid React node
|
|
11
|
-
right?: React.ReactNode | null; // Allows for any valid React node
|
|
12
|
-
height?: number;
|
|
13
|
-
placeholder?: string | null;
|
|
14
|
-
mode?: TextInputProps["keyboardType"]; // Use keyboardType from TextInputProps
|
|
15
|
-
secureTextEntry?: boolean;
|
|
16
|
-
multiline?: boolean;
|
|
17
|
-
gap?: number;
|
|
18
|
-
onChangeText: (text: string) => void; // Function to handle text changes
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
const Input: React.FC<InputProps> = ({
|
|
22
|
-
value="",
|
|
23
|
-
label = null,
|
|
24
|
-
left = null,
|
|
25
|
-
right = null,
|
|
26
|
-
height = 50,
|
|
27
|
-
gap = 20,
|
|
28
|
-
placeholder = null,
|
|
29
|
-
mode = "default",
|
|
30
|
-
multiline = false,
|
|
31
|
-
secureTextEntry = false,
|
|
32
|
-
onChangeText,
|
|
33
|
-
}) => {
|
|
34
|
-
const [isFocused, setFocused] = useState(false);
|
|
35
|
-
|
|
36
|
-
return (
|
|
37
|
-
<View style={{ gap: 5 }}>
|
|
38
|
-
{label !== null && (
|
|
39
|
-
<Text size={12} weight="400Regular" color={isFocused ? config.colors.primary : config.colors.slate[500]}>
|
|
40
|
-
{label}
|
|
41
|
-
</Text>
|
|
42
|
-
)}
|
|
43
|
-
<Inline
|
|
44
|
-
style={{
|
|
45
|
-
...styles.input,
|
|
46
|
-
borderColor: isFocused ? config.colors.primary : config.colors.slate[200],
|
|
47
|
-
}}
|
|
48
|
-
gap={gap}
|
|
49
|
-
>
|
|
50
|
-
{left !== null && left}
|
|
51
|
-
<TextInput
|
|
52
|
-
value={value}
|
|
53
|
-
placeholder={placeholder}
|
|
54
|
-
style={{
|
|
55
|
-
height: multiline ? 'auto' : height,
|
|
56
|
-
minHeight: height,
|
|
57
|
-
paddingVertical: multiline ? 20 : 0,
|
|
58
|
-
flexGrow: 1,
|
|
59
|
-
}}
|
|
60
|
-
onFocus={() => setFocused(true)}
|
|
61
|
-
onChangeText={onChangeText}
|
|
62
|
-
onBlur={() => setFocused(false)}
|
|
63
|
-
// Using 'default' for generic mode
|
|
64
|
-
keyboardType={mode}
|
|
65
|
-
multiline={multiline}
|
|
66
|
-
secureTextEntry={secureTextEntry}
|
|
67
|
-
/>
|
|
68
|
-
{right !== null && right}
|
|
69
|
-
</Inline>
|
|
70
|
-
</View>
|
|
71
|
-
);
|
|
72
|
-
};
|
|
73
|
-
|
|
74
|
-
const styles = StyleSheet.create({
|
|
75
|
-
input: {
|
|
76
|
-
flexGrow: 1,
|
|
77
|
-
borderWidth: 1,
|
|
78
|
-
borderRadius: 12,
|
|
79
|
-
paddingHorizontal: 20,
|
|
80
|
-
},
|
|
81
|
-
});
|
|
82
|
-
|
|
83
|
-
export default Input;
|
package/elements/ProgressBar.tsx
DELETED
|
@@ -1,52 +0,0 @@
|
|
|
1
|
-
import React, { useState, useEffect } from "react";
|
|
2
|
-
import { View, StyleSheet, ViewStyle } from "react-native";
|
|
3
|
-
import config from "../config";
|
|
4
|
-
|
|
5
|
-
interface ProgressBarProps {
|
|
6
|
-
value: number;
|
|
7
|
-
from?: number;
|
|
8
|
-
size?: number;
|
|
9
|
-
style?: ViewStyle;
|
|
10
|
-
percentage?: number | null;
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
const ProgressBar: React.FC<ProgressBarProps> = ({
|
|
14
|
-
value,
|
|
15
|
-
from = 100,
|
|
16
|
-
size = 5,
|
|
17
|
-
style,
|
|
18
|
-
percentage = null,
|
|
19
|
-
}) => {
|
|
20
|
-
const [percent, setPercent] = useState<number | null>(null);
|
|
21
|
-
|
|
22
|
-
useEffect(() => {
|
|
23
|
-
if (percent == null) {
|
|
24
|
-
setPercent((value / from) * 100);
|
|
25
|
-
}
|
|
26
|
-
}, [value, from, percent]); // Add dependencies to useEffect
|
|
27
|
-
|
|
28
|
-
return (
|
|
29
|
-
<View style={{ ...barStyle.area, ...style, height: size }}>
|
|
30
|
-
<View
|
|
31
|
-
style={{
|
|
32
|
-
...barStyle.value,
|
|
33
|
-
width: `${percent !== null ? percent : 0}%`,
|
|
34
|
-
height: size,
|
|
35
|
-
}}
|
|
36
|
-
></View>
|
|
37
|
-
</View>
|
|
38
|
-
);
|
|
39
|
-
};
|
|
40
|
-
|
|
41
|
-
const barStyle = StyleSheet.create({
|
|
42
|
-
area: {
|
|
43
|
-
backgroundColor: config.colors.slate[200],
|
|
44
|
-
height: 5,
|
|
45
|
-
flexGrow: 1,
|
|
46
|
-
},
|
|
47
|
-
value: {
|
|
48
|
-
backgroundColor: config.colors.primary,
|
|
49
|
-
},
|
|
50
|
-
});
|
|
51
|
-
|
|
52
|
-
export default ProgressBar;
|
|
@@ -1,27 +0,0 @@
|
|
|
1
|
-
import * as SecureStore from 'expo-secure-store';
|
|
2
|
-
|
|
3
|
-
const SecureStorage = {
|
|
4
|
-
async getItem(key) {
|
|
5
|
-
return await SecureStore.getItemAsync(key);
|
|
6
|
-
},
|
|
7
|
-
|
|
8
|
-
async setItem(key, value) {
|
|
9
|
-
return await SecureStore.setItemAsync(key, value);
|
|
10
|
-
},
|
|
11
|
-
|
|
12
|
-
async removeItem(key) {
|
|
13
|
-
return await SecureStore.deleteItemAsync(key);
|
|
14
|
-
},
|
|
15
|
-
|
|
16
|
-
// optional: to match AsyncStorage signature
|
|
17
|
-
async clear() {
|
|
18
|
-
console.warn('SecureStorage.clear() is not supported – SecureStore has no clearAll.');
|
|
19
|
-
},
|
|
20
|
-
|
|
21
|
-
async getAllKeys() {
|
|
22
|
-
console.warn('SecureStorage.getAllKeys() is not supported – SecureStore cannot list keys.');
|
|
23
|
-
return [];
|
|
24
|
-
},
|
|
25
|
-
};
|
|
26
|
-
|
|
27
|
-
export default SecureStorage;
|
package/elements/Separator.tsx
DELETED
|
@@ -1,71 +0,0 @@
|
|
|
1
|
-
import React from "react";
|
|
2
|
-
import { Dimensions, StyleSheet, View, ViewStyle } from "react-native";
|
|
3
|
-
import Inline from "./Inline";
|
|
4
|
-
import config from "../config";
|
|
5
|
-
import Text from "./Text";
|
|
6
|
-
|
|
7
|
-
interface SeparatorProps {
|
|
8
|
-
width?: any;
|
|
9
|
-
space?: number;
|
|
10
|
-
height?: number;
|
|
11
|
-
color?: string;
|
|
12
|
-
textProps?: React.ComponentProps<typeof Text>;
|
|
13
|
-
style?: ViewStyle;
|
|
14
|
-
children?: React.ReactNode;
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
const Separator: React.FC<SeparatorProps> = ({
|
|
18
|
-
children,
|
|
19
|
-
width = "100%",
|
|
20
|
-
space = 20,
|
|
21
|
-
height = 1,
|
|
22
|
-
color = config.colors.slate[200],
|
|
23
|
-
textProps,
|
|
24
|
-
style,
|
|
25
|
-
}) => {
|
|
26
|
-
let theWidth = width;
|
|
27
|
-
if (typeof width === "string") {
|
|
28
|
-
let toReturn = [];
|
|
29
|
-
let w = width.split("");
|
|
30
|
-
w.map((wi, w) => {
|
|
31
|
-
if (!isNaN(wi)) {
|
|
32
|
-
toReturn.push(wi);
|
|
33
|
-
}
|
|
34
|
-
});
|
|
35
|
-
toReturn = parseInt(toReturn.join(""));
|
|
36
|
-
theWidth = toReturn / 100 * Dimensions.get('screen').width;
|
|
37
|
-
}
|
|
38
|
-
return (
|
|
39
|
-
<Inline justifyContent="center">
|
|
40
|
-
<View
|
|
41
|
-
style={{
|
|
42
|
-
backgroundColor: color,
|
|
43
|
-
width: theWidth,
|
|
44
|
-
height: height,
|
|
45
|
-
marginVertical: space,
|
|
46
|
-
...style,
|
|
47
|
-
}}
|
|
48
|
-
></View>
|
|
49
|
-
{children && (
|
|
50
|
-
<Text
|
|
51
|
-
size={12}
|
|
52
|
-
style={{
|
|
53
|
-
position: "absolute",
|
|
54
|
-
backgroundColor: "#fff",
|
|
55
|
-
padding: 10,
|
|
56
|
-
paddingHorizontal: 20,
|
|
57
|
-
}}
|
|
58
|
-
{...textProps}
|
|
59
|
-
>
|
|
60
|
-
{children}
|
|
61
|
-
</Text>
|
|
62
|
-
)}
|
|
63
|
-
</Inline>
|
|
64
|
-
);
|
|
65
|
-
};
|
|
66
|
-
|
|
67
|
-
const styles = StyleSheet.create({
|
|
68
|
-
// Define your styles here if needed
|
|
69
|
-
});
|
|
70
|
-
|
|
71
|
-
export default Separator;
|
package/elements/Skeleton.tsx
DELETED
|
@@ -1,64 +0,0 @@
|
|
|
1
|
-
import React, { useEffect, useRef } from "react";
|
|
2
|
-
import { Animated, StyleSheet, View, ViewStyle } from "react-native";
|
|
3
|
-
import config from "../config";
|
|
4
|
-
|
|
5
|
-
interface SkeletonProps {
|
|
6
|
-
color?: string;
|
|
7
|
-
rounded?: number;
|
|
8
|
-
width?: any;
|
|
9
|
-
height?: number;
|
|
10
|
-
aspectRatio?: number | null;
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
const Skeleton: React.FC<SkeletonProps> = ({
|
|
14
|
-
color = config.colors.slate[200],
|
|
15
|
-
rounded = 8,
|
|
16
|
-
width = `${Math.floor(Math.random() * (99 - 11 + 1)) + 11}%`,
|
|
17
|
-
height = 20,
|
|
18
|
-
aspectRatio = null,
|
|
19
|
-
}) => {
|
|
20
|
-
const aspectRatioStyles: ViewStyle = { aspectRatio: aspectRatio ?? 1 };
|
|
21
|
-
const heightStyles: ViewStyle = { height: height };
|
|
22
|
-
const opacity = useRef(new Animated.Value(1)).current;
|
|
23
|
-
const defaultStyles: ViewStyle = {
|
|
24
|
-
backgroundColor: color,
|
|
25
|
-
width,
|
|
26
|
-
borderRadius: rounded,
|
|
27
|
-
opacity,
|
|
28
|
-
};
|
|
29
|
-
|
|
30
|
-
useEffect(() => {
|
|
31
|
-
const bounce = () => {
|
|
32
|
-
opacity.setValue(1);
|
|
33
|
-
Animated.timing(opacity, {
|
|
34
|
-
toValue: 0.4,
|
|
35
|
-
duration: 1000,
|
|
36
|
-
useNativeDriver: true,
|
|
37
|
-
}).start(() => {
|
|
38
|
-
Animated.timing(opacity, {
|
|
39
|
-
toValue: 0.8,
|
|
40
|
-
duration: 1000,
|
|
41
|
-
useNativeDriver: true,
|
|
42
|
-
}).start(bounce);
|
|
43
|
-
});
|
|
44
|
-
};
|
|
45
|
-
|
|
46
|
-
bounce();
|
|
47
|
-
}, [opacity]);
|
|
48
|
-
|
|
49
|
-
return (
|
|
50
|
-
<Animated.View
|
|
51
|
-
style={
|
|
52
|
-
aspectRatio === null
|
|
53
|
-
? [defaultStyles, heightStyles]
|
|
54
|
-
: [defaultStyles, aspectRatioStyles]
|
|
55
|
-
}
|
|
56
|
-
/>
|
|
57
|
-
);
|
|
58
|
-
};
|
|
59
|
-
|
|
60
|
-
const styles = StyleSheet.create({
|
|
61
|
-
// Add your styles here if needed
|
|
62
|
-
});
|
|
63
|
-
|
|
64
|
-
export default Skeleton;
|
package/elements/Slider.tsx
DELETED
|
@@ -1,133 +0,0 @@
|
|
|
1
|
-
import React, { useRef } from 'react';
|
|
2
|
-
import {
|
|
3
|
-
View,
|
|
4
|
-
StyleSheet,
|
|
5
|
-
PanResponder,
|
|
6
|
-
Animated,
|
|
7
|
-
Dimensions,
|
|
8
|
-
GestureResponderEvent,
|
|
9
|
-
PanResponderGestureState
|
|
10
|
-
} from 'react-native';
|
|
11
|
-
import config from '../config';
|
|
12
|
-
|
|
13
|
-
type SliderProps = {
|
|
14
|
-
start?: number;
|
|
15
|
-
end?: number;
|
|
16
|
-
value?: number;
|
|
17
|
-
rounded?: number;
|
|
18
|
-
trackColor?: string;
|
|
19
|
-
color?: string;
|
|
20
|
-
height?: number;
|
|
21
|
-
thumbOpacity?: number;
|
|
22
|
-
thumbColor?: string;
|
|
23
|
-
onChange?: (value: number) => void;
|
|
24
|
-
setScrollEnabled?: (enabled: boolean) => void;
|
|
25
|
-
};
|
|
26
|
-
|
|
27
|
-
const Slider: React.FC<SliderProps> = ({
|
|
28
|
-
start = 0,
|
|
29
|
-
end = 100,
|
|
30
|
-
value = 25,
|
|
31
|
-
rounded = 8,
|
|
32
|
-
trackColor = '#ecf0f1',
|
|
33
|
-
color = config.colors.primary,
|
|
34
|
-
height = 40,
|
|
35
|
-
onChange,
|
|
36
|
-
thumbOpacity = 0.7,
|
|
37
|
-
thumbColor = '#fff',
|
|
38
|
-
setScrollEnabled = () => {}
|
|
39
|
-
}) => {
|
|
40
|
-
const pan = useRef(new Animated.ValueXY()).current;
|
|
41
|
-
const screenWidth = Dimensions.get('window').width;
|
|
42
|
-
|
|
43
|
-
const panResponder = useRef(
|
|
44
|
-
PanResponder.create({
|
|
45
|
-
onStartShouldSetPanResponder: () => true,
|
|
46
|
-
onMoveShouldSetPanResponder: (_: GestureResponderEvent, gestureState: PanResponderGestureState) => {
|
|
47
|
-
return Math.abs(gestureState.dx) > Math.abs(gestureState.dy);
|
|
48
|
-
},
|
|
49
|
-
onPanResponderGrant: () => {
|
|
50
|
-
setScrollEnabled(false);
|
|
51
|
-
},
|
|
52
|
-
onPanResponderMove: (_: GestureResponderEvent, gestureState: PanResponderGestureState) => {
|
|
53
|
-
const clampedX = Math.max(0, Math.min(screenWidth, gestureState.moveX));
|
|
54
|
-
let percent = clampedX / screenWidth;
|
|
55
|
-
let newValue = Math.round(start + percent * (end - start));
|
|
56
|
-
onChange?.(newValue);
|
|
57
|
-
},
|
|
58
|
-
onPanResponderRelease: () => {
|
|
59
|
-
setScrollEnabled(true);
|
|
60
|
-
Animated.spring(pan, {
|
|
61
|
-
toValue: { x: 0, y: 0 },
|
|
62
|
-
useNativeDriver: false
|
|
63
|
-
}).start();
|
|
64
|
-
},
|
|
65
|
-
onPanResponderTerminate: () => {
|
|
66
|
-
setScrollEnabled(true);
|
|
67
|
-
Animated.spring(pan, {
|
|
68
|
-
toValue: { x: 0, y: 0 },
|
|
69
|
-
useNativeDriver: false
|
|
70
|
-
}).start();
|
|
71
|
-
},
|
|
72
|
-
onPanResponderTerminationRequest: () => false
|
|
73
|
-
})
|
|
74
|
-
).current;
|
|
75
|
-
|
|
76
|
-
return (
|
|
77
|
-
<View
|
|
78
|
-
style={[styles.touchArea, { height }]}
|
|
79
|
-
{...panResponder.panHandlers}
|
|
80
|
-
>
|
|
81
|
-
<View
|
|
82
|
-
style={[
|
|
83
|
-
styles.container,
|
|
84
|
-
{ height, backgroundColor: trackColor, borderRadius: rounded }
|
|
85
|
-
]}
|
|
86
|
-
>
|
|
87
|
-
<View
|
|
88
|
-
style={{
|
|
89
|
-
backgroundColor: color,
|
|
90
|
-
width: `${value / (end - start) * 100}%`,
|
|
91
|
-
height,
|
|
92
|
-
alignItems: 'flex-end',
|
|
93
|
-
justifyContent: 'center',
|
|
94
|
-
borderRadius: rounded
|
|
95
|
-
}}
|
|
96
|
-
>
|
|
97
|
-
<View
|
|
98
|
-
style={{
|
|
99
|
-
...styles.thumb,
|
|
100
|
-
height: (60 / 100) * height,
|
|
101
|
-
marginRight: (rounded / height) * 100 > 25 ? 20 : 10,
|
|
102
|
-
opacity: thumbOpacity,
|
|
103
|
-
backgroundColor: thumbColor
|
|
104
|
-
}}
|
|
105
|
-
/>
|
|
106
|
-
</View>
|
|
107
|
-
</View>
|
|
108
|
-
</View>
|
|
109
|
-
);
|
|
110
|
-
};
|
|
111
|
-
|
|
112
|
-
const styles = StyleSheet.create({
|
|
113
|
-
touchArea: {
|
|
114
|
-
width: '100%'
|
|
115
|
-
},
|
|
116
|
-
container: {
|
|
117
|
-
width: '100%',
|
|
118
|
-
position: 'relative'
|
|
119
|
-
},
|
|
120
|
-
thumb_dot: {
|
|
121
|
-
width: 4,
|
|
122
|
-
height: 4,
|
|
123
|
-
backgroundColor: '#fff',
|
|
124
|
-
borderRadius: 9
|
|
125
|
-
},
|
|
126
|
-
thumb: {
|
|
127
|
-
width: 3,
|
|
128
|
-
backgroundColor: '#fff',
|
|
129
|
-
borderRadius: 9
|
|
130
|
-
}
|
|
131
|
-
});
|
|
132
|
-
|
|
133
|
-
export default Slider;
|