@kukkim/react-native-ui 0.1.4 → 0.1.6

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.
Files changed (87) hide show
  1. package/lib/module/components/badge/index.js +2 -1
  2. package/lib/module/components/badge/index.js.map +1 -1
  3. package/lib/module/components/card/foldableCard.js +9 -18
  4. package/lib/module/components/card/foldableCard.js.map +1 -1
  5. package/lib/module/components/icon/index.js +3 -2
  6. package/lib/module/components/icon/index.js.map +1 -1
  7. package/lib/module/components/index.js +3 -1
  8. package/lib/module/components/index.js.map +1 -1
  9. package/lib/module/components/list/commonList.js +17 -0
  10. package/lib/module/components/list/commonList.js.map +1 -0
  11. package/lib/module/components/list/imageList.js +25 -0
  12. package/lib/module/components/list/imageList.js.map +1 -0
  13. package/lib/module/components/list/index.js +6 -0
  14. package/lib/module/components/list/index.js.map +1 -0
  15. package/lib/module/components/list/types.js +7 -0
  16. package/lib/module/components/list/types.js.map +1 -0
  17. package/lib/module/components/progressBar/circularProgressBar.js +16 -3
  18. package/lib/module/components/progressBar/circularProgressBar.js.map +1 -1
  19. package/lib/module/components/progressBar/index.js +0 -1
  20. package/lib/module/components/progressBar/index.js.map +1 -1
  21. package/lib/module/components/progressBar/linearProgressBar.js +15 -3
  22. package/lib/module/components/progressBar/linearProgressBar.js.map +1 -1
  23. package/lib/module/components/select/commonSelect.js +135 -0
  24. package/lib/module/components/select/commonSelect.js.map +1 -0
  25. package/lib/module/components/select/index.js +5 -0
  26. package/lib/module/components/select/index.js.map +1 -0
  27. package/lib/module/components/select/types.js +4 -0
  28. package/lib/module/components/select/types.js.map +1 -0
  29. package/lib/module/components/slider/index.js +103 -1
  30. package/lib/module/components/slider/index.js.map +1 -1
  31. package/lib/module/components/slider/types.js +2 -0
  32. package/lib/module/components/switch/commonSwitch.js +13 -17
  33. package/lib/module/components/switch/commonSwitch.js.map +1 -1
  34. package/lib/module/index.js +1 -1
  35. package/lib/module/index.js.map +1 -1
  36. package/lib/typescript/src/components/badge/index.d.ts +2 -1
  37. package/lib/typescript/src/components/badge/index.d.ts.map +1 -1
  38. package/lib/typescript/src/components/card/foldableCard.d.ts.map +1 -1
  39. package/lib/typescript/src/components/icon/index.d.ts.map +1 -1
  40. package/lib/typescript/src/components/icon/types.d.ts +1 -1
  41. package/lib/typescript/src/components/icon/types.d.ts.map +1 -1
  42. package/lib/typescript/src/components/index.d.ts +3 -1
  43. package/lib/typescript/src/components/index.d.ts.map +1 -1
  44. package/lib/typescript/src/components/list/commonList.d.ts +4 -0
  45. package/lib/typescript/src/components/list/commonList.d.ts.map +1 -0
  46. package/lib/typescript/src/components/list/imageList.d.ts +4 -0
  47. package/lib/typescript/src/components/list/imageList.d.ts.map +1 -0
  48. package/lib/typescript/src/components/list/index.d.ts +4 -0
  49. package/lib/typescript/src/components/list/index.d.ts.map +1 -0
  50. package/lib/typescript/src/components/list/types.d.ts +10 -0
  51. package/lib/typescript/src/components/list/types.d.ts.map +1 -0
  52. package/lib/typescript/src/components/progressBar/circularProgressBar.d.ts.map +1 -1
  53. package/lib/typescript/src/components/progressBar/index.d.ts.map +1 -1
  54. package/lib/typescript/src/components/progressBar/linearProgressBar.d.ts.map +1 -1
  55. package/lib/typescript/src/components/select/commonSelect.d.ts +5 -0
  56. package/lib/typescript/src/components/select/commonSelect.d.ts.map +1 -0
  57. package/lib/typescript/src/components/select/index.d.ts +3 -0
  58. package/lib/typescript/src/components/select/index.d.ts.map +1 -0
  59. package/lib/typescript/src/components/select/types.d.ts +16 -0
  60. package/lib/typescript/src/components/select/types.d.ts.map +1 -0
  61. package/lib/typescript/src/components/slider/index.d.ts +2 -0
  62. package/lib/typescript/src/components/slider/index.d.ts.map +1 -1
  63. package/lib/typescript/src/components/slider/types.d.ts +9 -0
  64. package/lib/typescript/src/components/slider/types.d.ts.map +1 -1
  65. package/lib/typescript/src/components/switch/commonSwitch.d.ts.map +1 -1
  66. package/lib/typescript/src/index.d.ts +1 -1
  67. package/lib/typescript/src/index.d.ts.map +1 -1
  68. package/package.json +3 -1
  69. package/src/components/badge/index.ts +2 -1
  70. package/src/components/card/foldableCard.tsx +14 -18
  71. package/src/components/icon/index.tsx +2 -1
  72. package/src/components/icon/types.ts +1 -0
  73. package/src/components/index.ts +3 -1
  74. package/src/components/list/commonList.tsx +14 -0
  75. package/src/components/list/imageList.tsx +25 -0
  76. package/src/components/list/index.ts +4 -0
  77. package/src/components/list/types.ts +14 -0
  78. package/src/components/progressBar/circularProgressBar.tsx +23 -3
  79. package/src/components/progressBar/index.ts +0 -1
  80. package/src/components/progressBar/linearProgressBar.tsx +31 -10
  81. package/src/components/select/commonSelect.tsx +170 -0
  82. package/src/components/select/index.ts +3 -0
  83. package/src/components/select/types.ts +18 -0
  84. package/src/components/slider/index.tsx +118 -1
  85. package/src/components/slider/types.ts +10 -0
  86. package/src/components/switch/commonSwitch.tsx +17 -13
  87. package/src/index.tsx +4 -0
@@ -1,4 +1,9 @@
1
- import { StyleSheet, View } from 'react-native';
1
+ import { useState } from 'react';
2
+ import { StyleSheet, View, type LayoutChangeEvent } from 'react-native';
3
+ import Animated, {
4
+ useAnimatedStyle,
5
+ withTiming,
6
+ } from 'react-native-reanimated';
2
7
  import { type ProgressBarProps } from './types';
3
8
  import { useTheme } from '../../hooks/useTheme';
4
9
 
@@ -11,6 +16,18 @@ const LinearProgressBar = ({
11
16
  const { theme } = useTheme();
12
17
  const progress = Math.min(Math.max(value, 0), 1);
13
18
 
19
+ const [containerWidth, setContainerWidth] = useState(0);
20
+
21
+ const animatedStyle = useAnimatedStyle(() => ({
22
+ width: withTiming(containerWidth * progress, {
23
+ duration: 1000,
24
+ }),
25
+ }));
26
+
27
+ const onLayout = (e: LayoutChangeEvent) => {
28
+ setContainerWidth(e.nativeEvent.layout.width);
29
+ };
30
+
14
31
  return (
15
32
  <View
16
33
  style={[
@@ -20,17 +37,21 @@ const LinearProgressBar = ({
20
37
  },
21
38
  style,
22
39
  ]}
40
+ onLayout={onLayout}
23
41
  {...props}
24
42
  >
25
- <View
26
- style={[
27
- styles.progress,
28
- {
29
- width: `${progress * 100}%`,
30
- backgroundColor: theme.colors[type],
31
- },
32
- ]}
33
- />
43
+ {containerWidth > 0 && (
44
+ <Animated.View
45
+ style={[
46
+ styles.progress,
47
+ {
48
+ width: containerWidth,
49
+ backgroundColor: theme.colors[type],
50
+ },
51
+ animatedStyle,
52
+ ]}
53
+ />
54
+ )}
34
55
  </View>
35
56
  );
36
57
  };
@@ -0,0 +1,170 @@
1
+ import React, { type ReactElement, useState } from 'react';
2
+ import { Pressable, StyleSheet, View } from 'react-native';
3
+ import { useTheme } from '../../hooks/useTheme';
4
+ import { CommonIcon } from '../icon';
5
+ import { CommonText } from '../text';
6
+ import { type CommonSelectItemProps, type CommonSelectProps } from './types';
7
+ import Animated, {
8
+ useAnimatedStyle,
9
+ useSharedValue,
10
+ withTiming,
11
+ } from 'react-native-reanimated';
12
+
13
+ export const SelectItem = (_props: CommonSelectItemProps) => {
14
+ return null;
15
+ };
16
+ export const CommonSelect = ({
17
+ children,
18
+ placeholder = 'Select',
19
+ value,
20
+ // defaultValue,
21
+ onChange,
22
+ style,
23
+ }: CommonSelectProps) => {
24
+ const { theme } = useTheme();
25
+ const [open, setOpen] = useState(false);
26
+ const [internalValue, setInternalValue] = useState<string | undefined>(
27
+ // defaultValue
28
+ ''
29
+ );
30
+
31
+ const selectedValue = value ?? internalValue;
32
+
33
+ const items = React.Children.toArray(children).filter(
34
+ React.isValidElement
35
+ ) as ReactElement<CommonSelectItemProps>[];
36
+
37
+ const selectedItem = items.find((item) => item.props.value === selectedValue);
38
+
39
+ const handleSelect = (nextValue: string) => {
40
+ if (value === undefined) {
41
+ setInternalValue(nextValue);
42
+ }
43
+
44
+ onChange?.(nextValue);
45
+ setOpen(false);
46
+ };
47
+
48
+ const rotate = useSharedValue(0);
49
+ const arrowAnimatedStyle = useAnimatedStyle(() => {
50
+ return {
51
+ transform: [
52
+ {
53
+ rotate: `${rotate.value}deg`,
54
+ },
55
+ ],
56
+ };
57
+ });
58
+
59
+ return (
60
+ <View style={[styles.container, style]}>
61
+ <Pressable
62
+ style={[
63
+ styles.trigger,
64
+ {
65
+ borderColor: theme.colors.border,
66
+ backgroundColor: theme.colors.background,
67
+ },
68
+ ]}
69
+ onPress={() => {
70
+ const nextOpen = !open;
71
+
72
+ rotate.value = withTiming(nextOpen ? 180 : 0, {
73
+ duration: 200,
74
+ });
75
+
76
+ setOpen(nextOpen);
77
+ }}
78
+ >
79
+ <CommonText
80
+ size="m"
81
+ style={[!selectedItem && { color: theme.colors.disabled }]}
82
+ >
83
+ {selectedItem?.props.label ?? placeholder}
84
+ </CommonText>
85
+ <Animated.View style={arrowAnimatedStyle}>
86
+ <CommonIcon iconType="down" />
87
+ </Animated.View>
88
+ </Pressable>
89
+
90
+ {open && (
91
+ <View
92
+ style={[
93
+ {
94
+ borderColor: theme.colors.border,
95
+ backgroundColor: theme.colors.background,
96
+ },
97
+ styles.dropdown,
98
+ ]}
99
+ >
100
+ {items.map((item) => {
101
+ const isSelected = item.props.value === selectedValue;
102
+
103
+ return (
104
+ <Pressable
105
+ key={String(item.props.value)}
106
+ style={[styles.option, isSelected && styles.selectedOption]}
107
+ onPress={() => handleSelect(item.props.value)}
108
+ >
109
+ <CommonText
110
+ style={[
111
+ styles.optionText,
112
+ isSelected && styles.selectedOptionText,
113
+ ]}
114
+ >
115
+ {item.props.label}
116
+ </CommonText>
117
+ </Pressable>
118
+ );
119
+ })}
120
+ </View>
121
+ )}
122
+ </View>
123
+ );
124
+ };
125
+
126
+ const styles = StyleSheet.create({
127
+ container: {
128
+ position: 'relative',
129
+ width: '100%',
130
+ zIndex: 999,
131
+ },
132
+ trigger: {
133
+ minHeight: 44,
134
+ borderWidth: 1,
135
+ borderRadius: 8,
136
+ paddingHorizontal: 10,
137
+ flexDirection: 'row',
138
+ alignItems: 'center',
139
+ justifyContent: 'space-between',
140
+ },
141
+ arrow: {
142
+ fontSize: 12,
143
+ color: '#667085',
144
+ },
145
+ dropdown: {
146
+ position: 'absolute',
147
+ top: 46,
148
+ left: 0,
149
+ right: 0,
150
+
151
+ borderWidth: 1,
152
+ borderRadius: 8,
153
+ zIndex: 999,
154
+ elevation: 10,
155
+ },
156
+ option: {
157
+ paddingVertical: 12,
158
+ paddingHorizontal: 12,
159
+ },
160
+ selectedOption: {
161
+ backgroundColor: '#F2F4F7',
162
+ },
163
+ optionText: {
164
+ fontSize: 14,
165
+ color: '#101828',
166
+ },
167
+ selectedOptionText: {
168
+ fontWeight: '600',
169
+ },
170
+ });
@@ -0,0 +1,3 @@
1
+ import { CommonSelect, SelectItem } from './commonSelect';
2
+
3
+ export { CommonSelect, SelectItem };
@@ -0,0 +1,18 @@
1
+ import { type ReactNode } from 'react';
2
+ import { type ViewProps } from 'react-native';
3
+
4
+ // type Variant = 'primary' | 'secondary';
5
+ type SizeVariant = 's' | 'm' | 'l';
6
+
7
+ export interface CommonSelectProps extends ViewProps {
8
+ size?: SizeVariant;
9
+ value?: string;
10
+ placeholder?: string;
11
+ onChange?: (value: string) => void;
12
+ children: ReactNode;
13
+ }
14
+
15
+ export interface CommonSelectItemProps extends ViewProps {
16
+ label: string;
17
+ value: string;
18
+ }
@@ -1 +1,118 @@
1
- // TODO: slider 구현 필요
1
+ import { View, StyleSheet } from 'react-native';
2
+ import { Gesture, GestureDetector } from 'react-native-gesture-handler';
3
+ import Animated, {
4
+ useAnimatedStyle,
5
+ useSharedValue,
6
+ } from 'react-native-reanimated';
7
+ import { CommonText } from '../text';
8
+ import { type SliderProps } from './types';
9
+ import { useTheme } from '../../hooks/useTheme';
10
+
11
+ // TODO: Thumb가 범위 바깥으로 넘어가는 것 수정 필요.
12
+ export const CommonSlider = ({ labels = [] }: SliderProps) => {
13
+ const { theme } = useTheme();
14
+ const position = useSharedValue(0);
15
+ const startPosition = useSharedValue(0);
16
+
17
+ const panGesture = Gesture.Pan()
18
+ .onBegin(() => {
19
+ startPosition.value = position.value;
20
+ })
21
+ .onUpdate((event) => {
22
+ const nextValue = startPosition.value + event.translationX;
23
+ if (nextValue < 0) {
24
+ position.value = 0;
25
+ } else {
26
+ position.value = nextValue;
27
+ }
28
+ });
29
+ const animatedStyle = useAnimatedStyle(() => ({
30
+ transform: [{ translateX: position.value }],
31
+ }));
32
+ const activeTrackStyle = useAnimatedStyle(() => ({
33
+ width: position.value + 15,
34
+ }));
35
+
36
+ return (
37
+ <View style={styles.container}>
38
+ <View
39
+ style={[styles.sliderBar, { backgroundColor: theme.colors.secondary }]}
40
+ >
41
+ <Animated.View
42
+ style={[
43
+ {
44
+ backgroundColor: theme.colors.primary,
45
+ },
46
+ styles.filledSliderBar,
47
+ activeTrackStyle,
48
+ ]}
49
+ />
50
+ <GestureDetector gesture={panGesture}>
51
+ <Animated.View
52
+ style={[
53
+ animatedStyle,
54
+ {
55
+ backgroundColor: theme.colors.text,
56
+ },
57
+ styles.thumb,
58
+ ]}
59
+ />
60
+ </GestureDetector>
61
+ </View>
62
+
63
+ <View style={styles.labelBar}>
64
+ {labels.map((label, index) => {
65
+ const percent = labels.length === 1 ? 0 : index / (labels.length - 1);
66
+ return (
67
+ <CommonText
68
+ size="s"
69
+ key={`${label}-${index}`}
70
+ style={[
71
+ styles.labelText,
72
+ {
73
+ color: theme.colors.text,
74
+ left: `${percent * 100}%`,
75
+ },
76
+ ]}
77
+ >
78
+ {label}
79
+ </CommonText>
80
+ );
81
+ })}
82
+ </View>
83
+ </View>
84
+ );
85
+ };
86
+
87
+ const styles = StyleSheet.create({
88
+ container: {
89
+ padding: 20,
90
+ width: '100%',
91
+ },
92
+ sliderBar: {
93
+ width: '100%',
94
+ height: 10,
95
+ },
96
+ filledSliderBar: {
97
+ position: 'absolute',
98
+ left: 0,
99
+ top: 0,
100
+ height: 10,
101
+ borderRadius: 5,
102
+ },
103
+ labelBar: {
104
+ position: 'relative',
105
+ height: 24,
106
+ marginTop: 12,
107
+ },
108
+ labelText: {
109
+ position: 'absolute',
110
+ transform: [{ translateX: -8 }],
111
+ },
112
+ thumb: {
113
+ bottom: 10,
114
+ width: 30,
115
+ height: 30,
116
+ borderRadius: 15,
117
+ },
118
+ });
@@ -0,0 +1,10 @@
1
+ import { type ViewProps } from 'react-native';
2
+
3
+ type Variant = 'primary' | 'secondary';
4
+ type SizeVariant = 's' | 'm' | 'l';
5
+
6
+ export interface SliderProps extends ViewProps {
7
+ type?: Variant;
8
+ size?: SizeVariant;
9
+ labels?: (string | number)[];
10
+ }
@@ -1,9 +1,11 @@
1
- import { useEffect, useRef } from 'react';
2
- import { Animated, Pressable, StyleSheet } from 'react-native';
1
+ import { Pressable, StyleSheet } from 'react-native';
3
2
  import { type SwitchProps, sizeType } from './types';
4
3
  import { useTheme } from '../../hooks/useTheme';
4
+ import Animated, {
5
+ useAnimatedStyle,
6
+ withTiming,
7
+ } from 'react-native-reanimated';
5
8
 
6
- //TODO: react-native-reanimated로 수정필요
7
9
  export default function CommonSwitch({
8
10
  type = 'primary',
9
11
  size = 'm',
@@ -14,20 +16,22 @@ export default function CommonSwitch({
14
16
  }: SwitchProps) {
15
17
  const { theme } = useTheme();
16
18
 
17
- const animValue = useRef(new Animated.Value(value ? 1 : 0)).current;
18
-
19
19
  const sizeValue = sizeType[size];
20
20
  const containerWidth = (sizeValue + 2) * 2;
21
21
  const thumbSize = sizeValue;
22
22
  const translateX = containerWidth - thumbSize - 2;
23
23
 
24
- useEffect(() => {
25
- Animated.timing(animValue, {
26
- toValue: value ? translateX : 0,
27
- duration: 200,
28
- useNativeDriver: true,
29
- }).start();
30
- }, [value, translateX, animValue]);
24
+ const thumbAnimatedStyle = useAnimatedStyle(() => {
25
+ return {
26
+ transform: [
27
+ {
28
+ translateX: withTiming(value ? translateX : 0, {
29
+ duration: 200,
30
+ }),
31
+ },
32
+ ],
33
+ };
34
+ }, [value, translateX]);
31
35
 
32
36
  const toggleValue = () => {
33
37
  if (disabled) return;
@@ -57,8 +61,8 @@ export default function CommonSwitch({
57
61
  height: thumbSize,
58
62
  borderRadius: thumbSize / 2,
59
63
  backgroundColor: value ? theme.colors[type] : theme.colors.disabled,
60
- transform: [{ translateX: animValue }],
61
64
  },
65
+ thumbAnimatedStyle,
62
66
  ]}
63
67
  />
64
68
  </Pressable>
package/src/index.tsx CHANGED
@@ -19,5 +19,9 @@ export {
19
19
  CommonSwitch,
20
20
  SocialLoginButton,
21
21
  CommonSpinner,
22
+ CommonSlider,
23
+ CommonSelect,
24
+ SelectItem,
25
+ NumberBadge,
22
26
  } from './components';
23
27
  export { ThemeProvider } from './theme/themeProvider';