@popp0102/nova 0.10.0 → 0.11.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.
@@ -76,4 +76,7 @@ export const styles = StyleSheet.create({
76
76
  pressed: {
77
77
  opacity: 0.5,
78
78
  },
79
+ disabled: {
80
+ opacity: 0.5,
81
+ },
79
82
  });
@@ -11,7 +11,8 @@ export default function Button({
11
11
  style,
12
12
  onPress,
13
13
  children,
14
- icon
14
+ icon,
15
+ disabled = false
15
16
  }) {
16
17
  const buttonColors = colors[type];
17
18
  const buttonSizes = sizes[size];
@@ -59,8 +60,15 @@ export default function Button({
59
60
 
60
61
  return (
61
62
  <Pressable
62
- onPress={onPress}
63
- style={({ pressed }) => [styles.button, backgroundStyle, pressed && styles.pressed, style]}
63
+ onPress={disabled ? undefined : onPress}
64
+ disabled={disabled}
65
+ style={({ pressed }) => [
66
+ styles.button,
67
+ backgroundStyle,
68
+ pressed && !disabled && styles.pressed,
69
+ disabled && styles.disabled,
70
+ style
71
+ ]}
64
72
  >
65
73
  {isGradient ? (
66
74
  <LinearGradient colors={color} style={{ padding: buttonSizes.padding }}>
@@ -0,0 +1,81 @@
1
+ import { StyleSheet } from 'react-native';
2
+
3
+ export const styles = StyleSheet.create({
4
+ card: {
5
+ marginHorizontal: 16,
6
+ },
7
+ description: {
8
+ textAlign: 'center',
9
+ marginBottom: 16,
10
+ fontSize: 16,
11
+ },
12
+ inputContainerHorizontal: {
13
+ width: "100%",
14
+ flexDirection: 'row',
15
+ alignItems: 'center',
16
+ gap: 8,
17
+ marginBottom: 24,
18
+ paddingBottom: 8,
19
+ },
20
+ inputContainerVertical: {
21
+ width: "100%",
22
+ flexDirection: 'column',
23
+ gap: 4,
24
+ marginBottom: 24,
25
+ paddingBottom: 8,
26
+ },
27
+ label: {
28
+ fontSize: 14,
29
+ fontWeight: '800',
30
+ color: '#333',
31
+ },
32
+ labelHorizontal: {
33
+ minWidth: 80,
34
+ },
35
+ required: {
36
+ color: '#dc3545',
37
+ marginLeft: 4,
38
+ fontSize: 16,
39
+ fontWeight: '700',
40
+ },
41
+ input: {
42
+ borderWidth: 1,
43
+ borderColor: "#ccc",
44
+ borderRadius: 6,
45
+ backgroundColor: "#fff",
46
+ color: "#000",
47
+ width: '100%',
48
+ paddingVertical: 14,
49
+ paddingHorizontal: 16,
50
+ fontSize: 16,
51
+ minHeight: 50,
52
+ },
53
+ textArea: {
54
+ minHeight: 100,
55
+ paddingTop: 14,
56
+ },
57
+ inputError: {
58
+ borderColor: "#dc3545",
59
+ borderWidth: 2,
60
+ },
61
+ inputHorizontal: {
62
+ flex: 1,
63
+ },
64
+ errorText: {
65
+ color: "#dc3545",
66
+ fontSize: 14,
67
+ marginTop: 4,
68
+ },
69
+ title: {
70
+ marginBottom: 16,
71
+ },
72
+ buttonContainer: {
73
+ flexDirection: 'row',
74
+ justifyContent: 'flex-end',
75
+ width: '100%',
76
+ marginTop: 4,
77
+ },
78
+ submitButton: {
79
+ minWidth: 100,
80
+ },
81
+ });
@@ -0,0 +1,117 @@
1
+ import { Text, TextInput, View } from 'react-native';
2
+ import Card from '../Card';
3
+ import Heading from '../Heading';
4
+ import Button from '../Button';
5
+ import { styles } from './config';
6
+
7
+ export default function Form({ children, style }) {
8
+ return (
9
+ <Card style={[styles.card, style]}>
10
+ {children}
11
+ </Card>
12
+ );
13
+ }
14
+
15
+ Form.Title = function FormTitle({ children, ...props }) {
16
+ return (
17
+ <View style={styles.title}>
18
+ <Heading size="h3" {...props}>{children}</Heading>
19
+ </View>
20
+ );
21
+ };
22
+
23
+ Form.Description = function FormDescription({ children, style }) {
24
+ return <Text style={[styles.description, style]}>{children}</Text>;
25
+ };
26
+
27
+ Form.TextInput = function FormTextInput({ label, labelPosition = 'vertical', labelStyle: customLabelStyle, style, placeholderTextColor = '#999', value, onChangeText, keyboardType = 'default', error, required, ...props }) {
28
+ const isHorizontal = labelPosition === 'horizontal';
29
+ const containerStyle = isHorizontal ? styles.inputContainerHorizontal : styles.inputContainerVertical;
30
+ const labelStyle = isHorizontal ? [styles.label, styles.labelHorizontal, customLabelStyle] : [styles.label, customLabelStyle];
31
+ const inputStyle = isHorizontal ? [styles.input, styles.inputHorizontal] : styles.input;
32
+ const hasError = error && error.length > 0;
33
+ const wrapperStyle = isHorizontal ? { flex: 1 } : { width: '100%' };
34
+
35
+ const inputField = (
36
+ <View style={wrapperStyle}>
37
+ <TextInput
38
+ style={[inputStyle, hasError && styles.inputError, style]}
39
+ placeholderTextColor={placeholderTextColor}
40
+ value={value}
41
+ onChangeText={onChangeText}
42
+ keyboardType={keyboardType}
43
+ {...props}
44
+ />
45
+ {hasError && <Text style={styles.errorText}>{error}</Text>}
46
+ </View>
47
+ );
48
+
49
+ if (!label) {
50
+ return (
51
+ <View style={{ width: '100%', marginBottom: 16 }}>
52
+ {inputField}
53
+ </View>
54
+ );
55
+ }
56
+
57
+ return (
58
+ <View style={containerStyle}>
59
+ <View style={{ flexDirection: 'row', alignItems: 'center' }}>
60
+ <Text style={labelStyle}>{label}</Text>
61
+ <Text style={[styles.required, !required && { opacity: 0 }]}>*</Text>
62
+ </View>
63
+ {inputField}
64
+ </View>
65
+ );
66
+ };
67
+
68
+ Form.TextArea = function FormTextArea({ label, labelPosition = 'vertical', style, placeholderTextColor = '#999', value, onChangeText, error, required, ...props }) {
69
+ const isHorizontal = labelPosition === 'horizontal';
70
+ const containerStyle = isHorizontal ? styles.inputContainerHorizontal : styles.inputContainerVertical;
71
+ const labelStyle = isHorizontal ? [styles.label, styles.labelHorizontal] : styles.label;
72
+ const inputStyle = isHorizontal ? [styles.input, styles.inputHorizontal] : styles.input;
73
+ const hasError = error && error.length > 0;
74
+ const wrapperStyle = isHorizontal ? { flex: 1 } : { width: '100%' };
75
+
76
+ const inputField = (
77
+ <View style={wrapperStyle}>
78
+ <TextInput
79
+ style={[inputStyle, styles.textArea, hasError && styles.inputError, style]}
80
+ placeholderTextColor={placeholderTextColor}
81
+ value={value}
82
+ onChangeText={onChangeText}
83
+ multiline
84
+ numberOfLines={4}
85
+ textAlignVertical="top"
86
+ {...props}
87
+ />
88
+ {hasError && <Text style={styles.errorText}>{error}</Text>}
89
+ </View>
90
+ );
91
+
92
+ if (!label) {
93
+ return (
94
+ <View style={{ width: '100%', marginBottom: 16 }}>
95
+ {inputField}
96
+ </View>
97
+ );
98
+ }
99
+
100
+ return (
101
+ <View style={containerStyle}>
102
+ <View style={{ flexDirection: 'row', alignItems: 'center' }}>
103
+ <Text style={labelStyle}>{label}</Text>
104
+ <Text style={[styles.required, !required && { opacity: 0 }]}>*</Text>
105
+ </View>
106
+ {inputField}
107
+ </View>
108
+ );
109
+ };
110
+
111
+ Form.SubmitButton = function FormSubmitButton({ children, icon, disabled, style, ...props }) {
112
+ return (
113
+ <View style={styles.buttonContainer}>
114
+ <Button icon={icon} disabled={disabled} style={[styles.submitButton, style]} {...props}>{children}</Button>
115
+ </View>
116
+ );
117
+ };
@@ -17,7 +17,7 @@ export default function FadeView({ children, direction = directions.IN, duration
17
17
  duration,
18
18
  useNativeDriver: true
19
19
  }).start();
20
- }, []);
20
+ }, [direction, duration, fadeAnimationValue]);
21
21
 
22
22
  return (
23
23
  <Animated.View style={[style, { opacity: fadeAnimationValue }]}>
@@ -39,7 +39,7 @@ export default function ShakeView({
39
39
 
40
40
  Animated.sequence(shakeSequence).start();
41
41
  }
42
- }, [shake, duration, distance, intensity]);
42
+ }, [shake, duration, distance, intensity, shakeAnim]);
43
43
 
44
44
  return (
45
45
  <Animated.View style={[style, { transform: [{ translateX: shakeAnim }] }]}>
@@ -30,17 +30,13 @@ export default function SlideView({ children, direction = directions.LEFT, durat
30
30
 
31
31
  const slideAnimationValue = useRef(new Animated.Value(initialValue)).current;
32
32
 
33
- const slideIn = () => {
33
+ useEffect(() => {
34
34
  Animated.timing(slideAnimationValue, {
35
35
  toValue: 0,
36
36
  duration: duration,
37
37
  useNativeDriver: true,
38
38
  }).start();
39
- };
40
-
41
- useEffect(() => {
42
- slideIn();
43
- }, []);
39
+ }, [slideAnimationValue, duration]);
44
40
 
45
41
  return (
46
42
  <Animated.View style={[style, { transform: [{ [transformProperty]: slideAnimationValue }] }]}>
package/lib/index.js CHANGED
@@ -7,6 +7,7 @@ export { default as Screen } from './components/Screen';
7
7
  export { default as ScreenHeader } from './components/ScreenHeader';
8
8
  export { default as Subtitle } from './components/Subtitle';
9
9
  export { default as Heading } from './components/Heading';
10
+ export { default as Form } from './components/Form';
10
11
  export { default as FadeView } from './components/animations/FadeView';
11
12
  export { default as SlideView } from './components/animations/SlideView';
12
13
  export { default as ShakeView } from './components/animations/ShakeView';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@popp0102/nova",
3
- "version": "0.10.0",
3
+ "version": "0.11.0",
4
4
  "description": "React Native component library",
5
5
  "main": "lib/index.js",
6
6
  "module": "lib/index.js",