ripal-ui 1.0.86 → 1.1.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/elements/ColorPicker.tsx +70 -0
- package/elements/Input.tsx +3 -0
- package/elements/Slider.tsx +133 -0
- package/elements/index.js +2 -0
- package/package.json +1 -1
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import React, { useState } from 'react';
|
|
2
|
+
import { View, Pressable } from 'react-native';
|
|
3
|
+
import Inline from './Inline';
|
|
4
|
+
import Text from './Text';
|
|
5
|
+
import config from '../config';
|
|
6
|
+
|
|
7
|
+
type ColorPickerProps = {
|
|
8
|
+
value?: string;
|
|
9
|
+
label?: string;
|
|
10
|
+
onChange?: (color: string) => void;
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
const ColorPicker: React.FC<ColorPickerProps> = ({
|
|
14
|
+
value = '#fff',
|
|
15
|
+
label = 'Pilih Warna',
|
|
16
|
+
onChange = () => {}
|
|
17
|
+
}) => {
|
|
18
|
+
const [isPicking, setPicking] = useState(false);
|
|
19
|
+
|
|
20
|
+
return (
|
|
21
|
+
<View style={{ gap: 5 }}>
|
|
22
|
+
<Inline>
|
|
23
|
+
<Text style={{ flexGrow: 1, fontSize: 11 }}>{label}</Text>
|
|
24
|
+
<Pressable
|
|
25
|
+
style={{
|
|
26
|
+
backgroundColor: value,
|
|
27
|
+
height: 24,
|
|
28
|
+
aspectRatio: 16 / 9,
|
|
29
|
+
borderRadius: 8,
|
|
30
|
+
borderWidth: 1,
|
|
31
|
+
borderColor: '#ddd',
|
|
32
|
+
padding: 4
|
|
33
|
+
}}
|
|
34
|
+
onPress={() => setPicking(true)}
|
|
35
|
+
/>
|
|
36
|
+
</Inline>
|
|
37
|
+
|
|
38
|
+
{isPicking && (
|
|
39
|
+
<View style={{ marginTop: 20 }}>
|
|
40
|
+
{Object.entries(config.colors).map((item, i) => {
|
|
41
|
+
if (typeof item[1] === 'object') {
|
|
42
|
+
return (
|
|
43
|
+
<Inline key={i} gap={0}>
|
|
44
|
+
{Object.entries(item[1] as Record<string, string>).map((sub, s) => (
|
|
45
|
+
<Pressable
|
|
46
|
+
key={s}
|
|
47
|
+
style={{
|
|
48
|
+
flexBasis: 30,
|
|
49
|
+
flexGrow: 1,
|
|
50
|
+
aspectRatio: 1,
|
|
51
|
+
backgroundColor: sub[1]
|
|
52
|
+
}}
|
|
53
|
+
onPress={() => {
|
|
54
|
+
onChange(sub[1]);
|
|
55
|
+
setPicking(false);
|
|
56
|
+
}}
|
|
57
|
+
/>
|
|
58
|
+
))}
|
|
59
|
+
</Inline>
|
|
60
|
+
);
|
|
61
|
+
}
|
|
62
|
+
return null;
|
|
63
|
+
})}
|
|
64
|
+
</View>
|
|
65
|
+
)}
|
|
66
|
+
</View>
|
|
67
|
+
);
|
|
68
|
+
};
|
|
69
|
+
|
|
70
|
+
export default ColorPicker;
|
package/elements/Input.tsx
CHANGED
|
@@ -14,6 +14,7 @@ interface InputProps {
|
|
|
14
14
|
mode?: TextInputProps["keyboardType"]; // Use keyboardType from TextInputProps
|
|
15
15
|
secureTextEntry?: boolean;
|
|
16
16
|
multiline?: boolean;
|
|
17
|
+
gap?: number;
|
|
17
18
|
onChangeText: (text: string) => void; // Function to handle text changes
|
|
18
19
|
}
|
|
19
20
|
|
|
@@ -23,6 +24,7 @@ const Input: React.FC<InputProps> = ({
|
|
|
23
24
|
left = null,
|
|
24
25
|
right = null,
|
|
25
26
|
height = 50,
|
|
27
|
+
gap = 20,
|
|
26
28
|
placeholder = null,
|
|
27
29
|
mode = "default",
|
|
28
30
|
multiline = false,
|
|
@@ -43,6 +45,7 @@ const Input: React.FC<InputProps> = ({
|
|
|
43
45
|
...styles.input,
|
|
44
46
|
borderColor: isFocused ? config.colors.primary : config.colors.slate[200],
|
|
45
47
|
}}
|
|
48
|
+
gap={gap}
|
|
46
49
|
>
|
|
47
50
|
{left !== null && left}
|
|
48
51
|
<TextInput
|
|
@@ -0,0 +1,133 @@
|
|
|
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;
|
package/elements/index.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
export { default as Button } from './Button';
|
|
2
|
+
export { default as ColorPicker } from './ColorPicker';
|
|
2
3
|
export { Dialog, DialogActions } from './Dialog';
|
|
3
4
|
export { default as Dropdown } from './Dropdown';
|
|
4
5
|
export { default as Inline } from './Inline';
|
|
@@ -6,6 +7,7 @@ export { default as Input } from './Input';
|
|
|
6
7
|
export { default as ProgressBar } from './ProgressBar';
|
|
7
8
|
export { default as Separator } from './Separator';
|
|
8
9
|
export { default as Skeleton } from './Skeleton';
|
|
10
|
+
export { default as Slider } from './Slider';
|
|
9
11
|
export { default as Switch } from './Switch';
|
|
10
12
|
export { default as Text } from './Text';
|
|
11
13
|
export { default as Toast } from './Toast';
|