ripal-ui 1.0.0 → 1.0.2
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 +0 -0
- package/components/BottomSheet.tsx +197 -0
- package/components/Carousel.tsx +61 -0
- package/components/Circle.tsx +44 -0
- package/components/Tab.tsx +90 -0
- package/components/{Table.jsx → Table.tsx} +32 -10
- package/components/index.ts +5 -0
- package/config.js +4 -0
- package/dist/BottomSheet.js +186 -0
- package/dist/Carousel.js +52 -0
- package/dist/Toast.js +72 -0
- package/dist/index.js +74 -12
- package/elements/{Button.jsx → Button.tsx} +51 -26
- package/elements/Dialog.tsx +87 -0
- package/elements/Dropdown.tsx +88 -0
- package/elements/Inline.tsx +38 -0
- package/elements/Input.tsx +75 -0
- package/elements/ProgressBar.tsx +52 -0
- package/elements/Separator.tsx +72 -0
- package/elements/Skeleton.tsx +64 -0
- package/elements/Switch.tsx +64 -0
- package/elements/Text.tsx +73 -0
- package/elements/Toast.tsx +65 -0
- package/elements/Toggle.tsx +59 -0
- package/elements/index.js +2 -1
- package/package.json +8 -4
- package/scripts/generateConfig.js +79 -0
- package/components/Circle.jsx +0 -24
- package/components/Tab.jsx +0 -71
- package/components/index.js +0 -4
- package/elements/Dialog.jsx +0 -64
- package/elements/Dropdown.jsx +0 -66
- package/elements/Inline.jsx +0 -16
- package/elements/Input.jsx +0 -48
- package/elements/ProgressBar.jsx +0 -29
- package/elements/Separator.jsx +0 -32
- package/elements/Skeleton.jsx +0 -50
- package/elements/Switch.jsx +0 -49
- package/elements/Text.jsx +0 -42
- package/elements/Toggle.jsx +0 -48
|
@@ -0,0 +1,52 @@
|
|
|
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;
|
|
@@ -0,0 +1,72 @@
|
|
|
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
|
+
console.log(theWidth);
|
|
38
|
+
}
|
|
39
|
+
return (
|
|
40
|
+
<Inline justifyContent="center">
|
|
41
|
+
<View
|
|
42
|
+
style={{
|
|
43
|
+
backgroundColor: color,
|
|
44
|
+
width: theWidth,
|
|
45
|
+
height: height,
|
|
46
|
+
marginVertical: space,
|
|
47
|
+
...style,
|
|
48
|
+
}}
|
|
49
|
+
></View>
|
|
50
|
+
{children && (
|
|
51
|
+
<Text
|
|
52
|
+
size={12}
|
|
53
|
+
style={{
|
|
54
|
+
position: "absolute",
|
|
55
|
+
backgroundColor: "#fff",
|
|
56
|
+
padding: 10,
|
|
57
|
+
paddingHorizontal: 20,
|
|
58
|
+
}}
|
|
59
|
+
{...textProps}
|
|
60
|
+
>
|
|
61
|
+
{children}
|
|
62
|
+
</Text>
|
|
63
|
+
)}
|
|
64
|
+
</Inline>
|
|
65
|
+
);
|
|
66
|
+
};
|
|
67
|
+
|
|
68
|
+
const styles = StyleSheet.create({
|
|
69
|
+
// Define your styles here if needed
|
|
70
|
+
});
|
|
71
|
+
|
|
72
|
+
export default Separator;
|
|
@@ -0,0 +1,64 @@
|
|
|
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;
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import React, { useState } from "react";
|
|
2
|
+
import { Pressable, StyleSheet, View, ViewStyle } from "react-native";
|
|
3
|
+
import config from "../config";
|
|
4
|
+
import Inline from "./Inline";
|
|
5
|
+
|
|
6
|
+
interface SwitchProps {
|
|
7
|
+
active?: boolean;
|
|
8
|
+
size?: number;
|
|
9
|
+
spacer?: number;
|
|
10
|
+
onChange?: () => void;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
const Switch: React.FC<SwitchProps> = ({
|
|
14
|
+
active = false,
|
|
15
|
+
size = 24,
|
|
16
|
+
spacer = 5,
|
|
17
|
+
onChange = null,
|
|
18
|
+
}) => {
|
|
19
|
+
const [isActive, setActive] = useState(active);
|
|
20
|
+
|
|
21
|
+
return (
|
|
22
|
+
<Pressable
|
|
23
|
+
onPress={() => {
|
|
24
|
+
setActive(!isActive);
|
|
25
|
+
if (onChange) {
|
|
26
|
+
onChange();
|
|
27
|
+
}
|
|
28
|
+
console.log('hehe');
|
|
29
|
+
}}
|
|
30
|
+
>
|
|
31
|
+
<Inline
|
|
32
|
+
style={{
|
|
33
|
+
backgroundColor: isActive ? config.colors.green[500] : config.colors.slate[200],
|
|
34
|
+
padding: spacer,
|
|
35
|
+
borderRadius: 999,
|
|
36
|
+
width: size * 2 + spacer + 5,
|
|
37
|
+
}}
|
|
38
|
+
>
|
|
39
|
+
{isActive && <View style={{ flexGrow: 1 }}></View>}
|
|
40
|
+
<View
|
|
41
|
+
style={{
|
|
42
|
+
height: size,
|
|
43
|
+
...styles.circle,
|
|
44
|
+
}}
|
|
45
|
+
>
|
|
46
|
+
{/* Add any inner content here if needed */}
|
|
47
|
+
</View>
|
|
48
|
+
</Inline>
|
|
49
|
+
</Pressable>
|
|
50
|
+
);
|
|
51
|
+
};
|
|
52
|
+
|
|
53
|
+
const styles = StyleSheet.create({
|
|
54
|
+
area: {
|
|
55
|
+
backgroundColor: config.colors.slate[100],
|
|
56
|
+
},
|
|
57
|
+
circle: {
|
|
58
|
+
backgroundColor: '#fff',
|
|
59
|
+
aspectRatio: 1,
|
|
60
|
+
borderRadius: 9999,
|
|
61
|
+
},
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
export default Switch;
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import React, { FC } from "react";
|
|
2
|
+
import { Text as RNText, TextStyle } from "react-native";
|
|
3
|
+
import { useFonts, Poppins_300Light, Poppins_400Regular, Poppins_500Medium, Poppins_600SemiBold, Poppins_700Bold, Poppins_900Black } from "@expo-google-fonts/poppins";
|
|
4
|
+
import config from "../config";
|
|
5
|
+
|
|
6
|
+
interface TextProps {
|
|
7
|
+
children: React.ReactNode;
|
|
8
|
+
weight?: '300Light' | '400Regular' | '500Medium' | '600SemiBold' | '700Bold' | '900Black';
|
|
9
|
+
size?: number;
|
|
10
|
+
color?: string;
|
|
11
|
+
align?: 'left' | 'right' | 'center' | 'justify';
|
|
12
|
+
limit?: number;
|
|
13
|
+
spacing?: number;
|
|
14
|
+
lineHeight?: number | null;
|
|
15
|
+
style?: TextStyle;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
const Text: FC<TextProps> = ({
|
|
19
|
+
children,
|
|
20
|
+
weight = "400Regular",
|
|
21
|
+
size,
|
|
22
|
+
color = config.colors.slate[500],
|
|
23
|
+
align = "left",
|
|
24
|
+
limit = 0,
|
|
25
|
+
spacing = 0,
|
|
26
|
+
lineHeight = null,
|
|
27
|
+
style
|
|
28
|
+
}) => {
|
|
29
|
+
const fontName = "Poppins";
|
|
30
|
+
const [fontsLoaded] = useFonts({
|
|
31
|
+
Poppins_300Light,
|
|
32
|
+
Poppins_400Regular,
|
|
33
|
+
Poppins_500Medium,
|
|
34
|
+
Poppins_600SemiBold,
|
|
35
|
+
Poppins_700Bold,
|
|
36
|
+
Poppins_900Black
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
if (config.appLangs.default !== null) {
|
|
40
|
+
const ogChildren = children;
|
|
41
|
+
if (typeof children === "string") {
|
|
42
|
+
children = children.split('.').reduce((acc, key) => {
|
|
43
|
+
return acc && acc[key] !== undefined ? acc[key] : ogChildren;
|
|
44
|
+
}, config.appLangs[config.appLangs.default]);
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
if (!fontsLoaded) {
|
|
49
|
+
return <RNText>{children}</RNText>; // Return statement added to properly handle loading state
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
if (limit > 0 && typeof children === "string" && children.length > limit) {
|
|
53
|
+
children = children.substr(0, limit) + '...';
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
return (
|
|
57
|
+
<RNText
|
|
58
|
+
style={{
|
|
59
|
+
fontSize: size,
|
|
60
|
+
color: color,
|
|
61
|
+
letterSpacing: spacing,
|
|
62
|
+
lineHeight: lineHeight,
|
|
63
|
+
...style,
|
|
64
|
+
fontFamily: `${fontName}_${weight}`,
|
|
65
|
+
textAlign: align
|
|
66
|
+
}}
|
|
67
|
+
>
|
|
68
|
+
{children}
|
|
69
|
+
</RNText>
|
|
70
|
+
);
|
|
71
|
+
};
|
|
72
|
+
|
|
73
|
+
export default Text;
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import React, { useEffect } from "react";
|
|
2
|
+
import { StyleSheet, View, ViewStyle } from "react-native";
|
|
3
|
+
import Inline from "./Inline";
|
|
4
|
+
import Text from "./Text";
|
|
5
|
+
import config from "../config";
|
|
6
|
+
|
|
7
|
+
interface ToastProps {
|
|
8
|
+
label?: string;
|
|
9
|
+
right?: React.ReactNode; // Allows for any valid React node
|
|
10
|
+
visible?: boolean;
|
|
11
|
+
setVisible: (visible: boolean) => void;
|
|
12
|
+
timeout?: number;
|
|
13
|
+
containerStyle?: ViewStyle; // Style for the container View
|
|
14
|
+
style?: ViewStyle; // Additional style for the Toast
|
|
15
|
+
textProps?: React.ComponentProps<typeof Text>; // Props for the Text component
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
const Toast: React.FC<ToastProps> = ({
|
|
19
|
+
label = "Percakapan berhasil dihapus",
|
|
20
|
+
right = null,
|
|
21
|
+
visible = true,
|
|
22
|
+
setVisible,
|
|
23
|
+
timeout = 3000,
|
|
24
|
+
containerStyle,
|
|
25
|
+
textProps,
|
|
26
|
+
}) => {
|
|
27
|
+
useEffect(() => {
|
|
28
|
+
if (visible) {
|
|
29
|
+
const timer = setTimeout(() => {
|
|
30
|
+
setVisible(false);
|
|
31
|
+
}, timeout);
|
|
32
|
+
|
|
33
|
+
return () => clearTimeout(timer);
|
|
34
|
+
}
|
|
35
|
+
}, [visible, setVisible, timeout]);
|
|
36
|
+
|
|
37
|
+
return visible ? (
|
|
38
|
+
<View style={{ ...styles.container, ...containerStyle }}>
|
|
39
|
+
<Inline style={styles.area}>
|
|
40
|
+
<Text size={12} style={{ flexGrow: 1 }} color="#fff" {...textProps}>
|
|
41
|
+
{label}
|
|
42
|
+
</Text>
|
|
43
|
+
{right}
|
|
44
|
+
</Inline>
|
|
45
|
+
</View>
|
|
46
|
+
) : null;
|
|
47
|
+
};
|
|
48
|
+
|
|
49
|
+
const styles = StyleSheet.create({
|
|
50
|
+
container: {
|
|
51
|
+
position: 'absolute',
|
|
52
|
+
bottom: 0,
|
|
53
|
+
left: 0,
|
|
54
|
+
right: 0,
|
|
55
|
+
padding: 20,
|
|
56
|
+
},
|
|
57
|
+
area: {
|
|
58
|
+
backgroundColor: config.colors.slate[800],
|
|
59
|
+
borderRadius: 999,
|
|
60
|
+
padding: 20,
|
|
61
|
+
paddingHorizontal: 30,
|
|
62
|
+
},
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
export default Toast;
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import { Pressable, StyleSheet, View, ViewStyle } from "react-native";
|
|
3
|
+
import config from "../config";
|
|
4
|
+
import Text from "./Text";
|
|
5
|
+
import Inline from "./Inline";
|
|
6
|
+
|
|
7
|
+
interface ToggleProps {
|
|
8
|
+
options: string[];
|
|
9
|
+
value: any;
|
|
10
|
+
setValue: (value: string) => void;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
const Toggle: React.FC<ToggleProps> = ({ options, value, setValue }) => {
|
|
14
|
+
return (
|
|
15
|
+
<Inline style={styles.area}>
|
|
16
|
+
{options.map((opt, o) => {
|
|
17
|
+
const isActive = value === opt;
|
|
18
|
+
return (
|
|
19
|
+
<Pressable
|
|
20
|
+
key={o}
|
|
21
|
+
style={[styles.item, isActive ? styles.item_active : null]}
|
|
22
|
+
onPress={() => setValue(opt)}
|
|
23
|
+
>
|
|
24
|
+
<Text
|
|
25
|
+
color={isActive ? config.colors.primary : config.colors.slate[500]}
|
|
26
|
+
weight={isActive ? '600SemiBold' : '400Regular'}
|
|
27
|
+
>
|
|
28
|
+
{opt}
|
|
29
|
+
</Text>
|
|
30
|
+
</Pressable>
|
|
31
|
+
);
|
|
32
|
+
})}
|
|
33
|
+
</Inline>
|
|
34
|
+
);
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
const styles = StyleSheet.create({
|
|
38
|
+
area: {
|
|
39
|
+
padding: 10,
|
|
40
|
+
backgroundColor: config.colors.slate[100],
|
|
41
|
+
borderRadius: 12,
|
|
42
|
+
},
|
|
43
|
+
item: {
|
|
44
|
+
flexGrow: 1,
|
|
45
|
+
flexDirection: 'row',
|
|
46
|
+
alignItems: 'center',
|
|
47
|
+
justifyContent: 'center',
|
|
48
|
+
paddingVertical: 10,
|
|
49
|
+
borderRadius: 12,
|
|
50
|
+
},
|
|
51
|
+
item_active: {
|
|
52
|
+
backgroundColor: '#fff',
|
|
53
|
+
shadowColor: config.colors.slate[300],
|
|
54
|
+
shadowOpacity: 0.4,
|
|
55
|
+
shadowRadius: 12,
|
|
56
|
+
},
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
export default Toggle;
|
package/elements/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
export { default as Button } from './Button';
|
|
2
|
-
export {
|
|
2
|
+
export { Dialog, DialogActions } from './Dialog';
|
|
3
3
|
export { default as Dropdown } from './Dropdown';
|
|
4
4
|
export { default as Inline } from './Inline';
|
|
5
5
|
export { default as Input } from './Input';
|
|
@@ -8,4 +8,5 @@ export { default as Separator } from './Separator';
|
|
|
8
8
|
export { default as Skeleton } from './Skeleton';
|
|
9
9
|
export { default as Switch } from './Switch';
|
|
10
10
|
export { default as Text } from './Text';
|
|
11
|
+
export { default as Toast } from './Toast';
|
|
11
12
|
export { default as Toggle } from './Toggle';
|
package/package.json
CHANGED
|
@@ -1,19 +1,23 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "ripal-ui",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.2",
|
|
4
4
|
"description": "A collection of React elements and components",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"scripts": {
|
|
7
|
-
"build": "babel elements components --out-dir dist"
|
|
7
|
+
"build": "babel elements components --out-dir dist",
|
|
8
|
+
"postinstall": "node ./scripts/generateConfig.js"
|
|
8
9
|
},
|
|
9
10
|
"dependencies": {
|
|
10
11
|
"react": "^18.0.0",
|
|
11
|
-
"react-native": "^0.
|
|
12
|
+
"react-native": "^0.74.2"
|
|
12
13
|
},
|
|
13
14
|
"devDependencies": {
|
|
14
15
|
"@babel/cli": "^7.25.6",
|
|
15
16
|
"@babel/core": "^7.25.2",
|
|
16
17
|
"@babel/preset-env": "^7.25.4",
|
|
17
|
-
"@babel/preset-react": "^7.24.7"
|
|
18
|
+
"@babel/preset-react": "^7.24.7",
|
|
19
|
+
"@types/react": "^18.3.10",
|
|
20
|
+
"@types/react-native": "^0.73.0",
|
|
21
|
+
"typescript": "^5.6.2"
|
|
18
22
|
}
|
|
19
23
|
}
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
// ./scripts/generateConfig.js
|
|
2
|
+
const fs = require('fs');
|
|
3
|
+
const path = require('path');
|
|
4
|
+
|
|
5
|
+
// Define the config file content
|
|
6
|
+
const configContent = `const config = {
|
|
7
|
+
appName: "",
|
|
8
|
+
appLangs: {
|
|
9
|
+
default: null,
|
|
10
|
+
en: require('./lang/en.json')
|
|
11
|
+
},
|
|
12
|
+
colors: {
|
|
13
|
+
primary: "#3B82F6",
|
|
14
|
+
transparent: "#ffffff00",
|
|
15
|
+
white: "#fff",
|
|
16
|
+
slate: {
|
|
17
|
+
100: "#F1F5F9",200: "#E2E8F0",300: "#CBD5E1",
|
|
18
|
+
400: "#94A3B8",500: "#64748B",600: "#475569",
|
|
19
|
+
700: "#334155",800: "#1E293B",900: "#0F172A",
|
|
20
|
+
},
|
|
21
|
+
green: {
|
|
22
|
+
100: "#DCFCE7",200: "#BBF7D0",300: "#86EFAC ",
|
|
23
|
+
400: "#4ADE7F",500: "#22C55E",600: "#16A34A",
|
|
24
|
+
700: "#15803D",800: "#166534",900: "#14532D",
|
|
25
|
+
},
|
|
26
|
+
orange: {
|
|
27
|
+
100: "#FFEDD5",200: "#FED7AA",300: "#FDBA74",
|
|
28
|
+
400: "#FB923C",500: "#F87316",600: "#EA580C",
|
|
29
|
+
700: "#C2410C",800: "#9A3412",900: "#7C2D12",
|
|
30
|
+
},
|
|
31
|
+
purple: {
|
|
32
|
+
100: "#F3E8FF",200: "#E9D5FF",300: "#D8B4FE",
|
|
33
|
+
400: "#C084FC",500: "#A855F7",600: "#9333EA",
|
|
34
|
+
700: "#7E22CE",800: "#6B21A8",900: "#581C87",
|
|
35
|
+
},
|
|
36
|
+
blue: {
|
|
37
|
+
100: "#D8EAFE",200: "#BFD8FE",300: "#94C5FD",
|
|
38
|
+
400: "#60A5FA",500: "#3B82F6",600: "#2563EB",
|
|
39
|
+
700: "#1D4ED8",800: "#1E41AF",900: "#1E3A8A",
|
|
40
|
+
},
|
|
41
|
+
red: {
|
|
42
|
+
100: "#FEE2E2",200: "#FECACA",300: "#FCA5A5",
|
|
43
|
+
400: "#F87171",500: "#EF4444",600: "#DC2626",
|
|
44
|
+
700: "#B91C1C",800: "#991B1B",900: "#7F1D1D",
|
|
45
|
+
},
|
|
46
|
+
lime: {
|
|
47
|
+
100: "#ECFCCB",200: "#D9F99D",300: "#BEF264",
|
|
48
|
+
400: "#A3E635",500: "#84CC16",600: "#65A30D",
|
|
49
|
+
700: "#4D7C0F",800: "#3F6212",900: "#365314",
|
|
50
|
+
},
|
|
51
|
+
yellow: {
|
|
52
|
+
100: "#FEF9C3",200: "#FEF08A",300: "#FDE047",
|
|
53
|
+
400: "#FACC15",500: "#EAB308",600: "#CA8A04",
|
|
54
|
+
700: "#A16207",800: "#854D0E",900: "#713F12",
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
export default config
|
|
60
|
+
`;
|
|
61
|
+
|
|
62
|
+
// Path to generate the config file in the user's project root
|
|
63
|
+
const configFilePath = path.resolve(process.cwd(), '../../ripal-ui.config.js');
|
|
64
|
+
const langDirPath = path.resolve(process.cwd(), '../../lang');
|
|
65
|
+
const enJsonFilePath = path.resolve(langDirPath, 'en.json');
|
|
66
|
+
|
|
67
|
+
// Check if the config file already exists
|
|
68
|
+
if (!fs.existsSync(configFilePath)) {
|
|
69
|
+
// Write the config file
|
|
70
|
+
fs.writeFileSync(configFilePath, configContent);
|
|
71
|
+
console.log('ripal-ui.config.js has been generated in the root project.');
|
|
72
|
+
|
|
73
|
+
fs.mkdirSync(langDirPath, {recursive: true});
|
|
74
|
+
|
|
75
|
+
const enContent = JSON.stringify({ say_hello: "Hello world"}, null, 4);
|
|
76
|
+
fs.writeFileSync(enJsonFilePath, enContent);
|
|
77
|
+
} else {
|
|
78
|
+
console.log('ripal-ui.config.js already exists. No changes made.');
|
|
79
|
+
}
|
package/components/Circle.jsx
DELETED
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
import React from "react";
|
|
2
|
-
import { Pressable, StyleSheet } from "react-native";
|
|
3
|
-
import config from "../config";
|
|
4
|
-
|
|
5
|
-
const Circle = ({size = 24, color = config.colors.primary, children, onPress, rounded = 999}) => {
|
|
6
|
-
return (
|
|
7
|
-
<Pressable onPress={onPress} style={{
|
|
8
|
-
...styles.area,
|
|
9
|
-
backgroundColor: color,
|
|
10
|
-
height: size,
|
|
11
|
-
borderRadius: rounded
|
|
12
|
-
}}>{children}</Pressable>
|
|
13
|
-
)
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
const styles = StyleSheet.create({
|
|
17
|
-
area: {
|
|
18
|
-
aspectRatio: 1,
|
|
19
|
-
alignItems: 'center',
|
|
20
|
-
justifyContent: 'center',
|
|
21
|
-
}
|
|
22
|
-
})
|
|
23
|
-
|
|
24
|
-
export default Circle;
|
package/components/Tab.jsx
DELETED
|
@@ -1,71 +0,0 @@
|
|
|
1
|
-
import React, { useState } from "react";
|
|
2
|
-
import { Pressable, ScrollView, StyleSheet, View } from "react-native";
|
|
3
|
-
import Text from "../elements/Text";
|
|
4
|
-
import Inline from "../elements/Inline";
|
|
5
|
-
import config from "../config";
|
|
6
|
-
|
|
7
|
-
const TabScreen = ({children}) => {
|
|
8
|
-
return children;
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
const Tab = ({children}) => {
|
|
12
|
-
const [index, setIndex] = useState(0);
|
|
13
|
-
|
|
14
|
-
return (
|
|
15
|
-
<View>
|
|
16
|
-
{
|
|
17
|
-
children.length > 3 ?
|
|
18
|
-
<ScrollView horizontal showsHorizontalScrollIndicator={false} contentContainerStyle={styles.tab_area}>
|
|
19
|
-
{ children.map((child, c) => {
|
|
20
|
-
let isActive = c === index;
|
|
21
|
-
return (
|
|
22
|
-
<Pressable key={c} style={{
|
|
23
|
-
...styles.tab_item,
|
|
24
|
-
borderBottomColor: isActive ? config.colors.primary : config.colors.slate[200],
|
|
25
|
-
}} onPress={() => setIndex(c)}>
|
|
26
|
-
<Text
|
|
27
|
-
color={isActive ? config.colors.primary : config.colors.slate[500]}
|
|
28
|
-
weight={isActive ? "600SemiBold" : "400Regular"}
|
|
29
|
-
>{child.props.title}</Text>
|
|
30
|
-
</Pressable>
|
|
31
|
-
)
|
|
32
|
-
})}
|
|
33
|
-
</ScrollView>
|
|
34
|
-
:
|
|
35
|
-
<Inline style={styles.tab_area} gap={0}>
|
|
36
|
-
{ children.map((child, c) => {
|
|
37
|
-
let isActive = c === index;
|
|
38
|
-
return (
|
|
39
|
-
<Inline justifyContent="center" key={c} style={{
|
|
40
|
-
...styles.tab_item,
|
|
41
|
-
borderBottomColor: isActive ? config.colors.primary : config.colors.slate[200],
|
|
42
|
-
}} onPress={() => setIndex(c)}>
|
|
43
|
-
<Text
|
|
44
|
-
color={isActive ? config.colors.primary : config.colors.slate[500]}
|
|
45
|
-
weight={isActive ? "600SemiBold" : "400Regular"}
|
|
46
|
-
>{child.props.title}</Text>
|
|
47
|
-
</Inline>
|
|
48
|
-
)
|
|
49
|
-
})}
|
|
50
|
-
</Inline>
|
|
51
|
-
}
|
|
52
|
-
{
|
|
53
|
-
children[index]
|
|
54
|
-
}
|
|
55
|
-
</View>
|
|
56
|
-
)
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
const styles = StyleSheet.create({
|
|
60
|
-
tab_area: {
|
|
61
|
-
marginBottom: 10,
|
|
62
|
-
},
|
|
63
|
-
tab_item: {
|
|
64
|
-
paddingHorizontal: 20,
|
|
65
|
-
paddingVertical: 12,
|
|
66
|
-
flexGrow: 1,
|
|
67
|
-
borderBottomWidth: 1,
|
|
68
|
-
}
|
|
69
|
-
})
|
|
70
|
-
|
|
71
|
-
export { Tab, TabScreen }
|
package/components/index.js
DELETED