@herca/rn-kit 0.1.63 → 0.1.65

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 (38) hide show
  1. package/README.md +8 -0
  2. package/lib/module/DatePicker/DatePicker.js +2 -2
  3. package/lib/module/DatePicker/DatePicker.js.map +1 -1
  4. package/lib/module/Input/InputDate.js +170 -0
  5. package/lib/module/Input/InputDate.js.map +1 -0
  6. package/lib/module/Input/README_INPUT_DATE.md +265 -0
  7. package/lib/module/Modal/Modal.js +24 -22
  8. package/lib/module/Modal/Modal.js.map +1 -1
  9. package/lib/module/Ui/README_VIEWINSETS.md +126 -0
  10. package/lib/module/Ui/ViewInsets.js +33 -0
  11. package/lib/module/Ui/ViewInsets.js.map +1 -0
  12. package/lib/module/function/README_DATE_FORMATTER.md +397 -0
  13. package/lib/module/function/dateFormatter.js +38 -0
  14. package/lib/module/function/dateFormatter.js.map +1 -0
  15. package/lib/module/index.js +3 -0
  16. package/lib/module/index.js.map +1 -1
  17. package/lib/typescript/src/Calendar/CalendarPropsType.d.ts +5 -0
  18. package/lib/typescript/src/Calendar/CalendarPropsType.d.ts.map +1 -1
  19. package/lib/typescript/src/Input/InputDate.d.ts +27 -0
  20. package/lib/typescript/src/Input/InputDate.d.ts.map +1 -0
  21. package/lib/typescript/src/Modal/Modal.d.ts.map +1 -1
  22. package/lib/typescript/src/Ui/ViewInsets.d.ts +13 -0
  23. package/lib/typescript/src/Ui/ViewInsets.d.ts.map +1 -0
  24. package/lib/typescript/src/function/dateFormatter.d.ts +14 -0
  25. package/lib/typescript/src/function/dateFormatter.d.ts.map +1 -0
  26. package/lib/typescript/src/index.d.ts +4 -1
  27. package/lib/typescript/src/index.d.ts.map +1 -1
  28. package/package.json +1 -1
  29. package/src/Calendar/CalendarPropsType.tsx +6 -0
  30. package/src/DatePicker/DatePicker.tsx +2 -2
  31. package/src/Input/InputDate.tsx +216 -0
  32. package/src/Input/README_INPUT_DATE.md +265 -0
  33. package/src/Modal/Modal.tsx +31 -46
  34. package/src/Ui/README_VIEWINSETS.md +126 -0
  35. package/src/Ui/ViewInsets.tsx +46 -0
  36. package/src/function/README_DATE_FORMATTER.md +397 -0
  37. package/src/function/dateFormatter.ts +54 -0
  38. package/src/index.tsx +8 -1
@@ -1,3 +1,4 @@
1
+ import { Color, Icon } from '@herca/rn-kit';
1
2
  import React, { useState, useEffect, useCallback } from 'react';
2
3
  import {
3
4
  View,
@@ -10,8 +11,6 @@ import {
10
11
  Platform,
11
12
  type ViewStyle,
12
13
  } from 'react-native';
13
- import Icon from '../Icon';
14
- import Color from '../Color/Color';
15
14
 
16
15
  interface ModalPopUpProps {
17
16
  isOpen: boolean;
@@ -39,11 +38,10 @@ const ModalPopUp: React.FC<ModalPopUpProps> = ({
39
38
  containerStyle,
40
39
  modalStyle,
41
40
  }) => {
42
- const [isVisible, setIsVisible] = useState(isOpen);
41
+ const [isVisible, setIsVisible] = useState(isOpen ?? false);
43
42
  const scaleAnim = useState(() => new Animated.Value(0))[0];
44
43
 
45
- const showModal = useCallback(() => {
46
- setIsVisible(true);
44
+ const animateIn = useCallback(() => {
47
45
  Animated.spring(scaleAnim, {
48
46
  toValue: 1,
49
47
  useNativeDriver: true,
@@ -52,24 +50,31 @@ const ModalPopUp: React.FC<ModalPopUpProps> = ({
52
50
  }).start();
53
51
  }, [scaleAnim]);
54
52
 
55
- const hideModal = useCallback(() => {
53
+ useEffect(() => {
54
+ if (isOpen) {
55
+ setIsVisible(true);
56
+ animateIn();
57
+ } else if (isVisible) {
58
+ setIsVisible(false);
59
+ onRequestClose?.();
60
+ onClose?.();
61
+ }
62
+ }, [isOpen, isVisible, animateIn, onRequestClose, onClose]);
63
+
64
+ const userClose = useCallback(() => {
65
+ if (!closable) return;
56
66
  setIsVisible(false);
57
67
  onRequestClose?.();
58
68
  onClose?.();
59
- }, [onClose, onRequestClose]);
69
+ }, [closable, onClose, onRequestClose]);
60
70
 
61
- const handleBackdropPress = useCallback(() => {
62
- if (closable) {
63
- hideModal?.();
64
- }
65
- }, [closable, hideModal]);
66
- useEffect(() => {
67
- if (isOpen) {
68
- showModal();
69
- }
71
+ const handleBackdropPress = () => {
72
+ userClose();
73
+ };
70
74
 
71
- // eslint-disable-next-line react-hooks/exhaustive-deps
72
- }, [isOpen]);
75
+ const handleRequestClose = () => {
76
+ userClose();
77
+ };
73
78
 
74
79
  const modalContentStyle = StyleSheet.flatten([
75
80
  {
@@ -85,7 +90,7 @@ const ModalPopUp: React.FC<ModalPopUpProps> = ({
85
90
  <Modal
86
91
  transparent
87
92
  visible={isVisible}
88
- onRequestClose={handleBackdropPress}
93
+ onRequestClose={handleRequestClose}
89
94
  statusBarTranslucent
90
95
  >
91
96
  <View style={[styles.modalContainer, containerStyle]}>
@@ -99,7 +104,7 @@ const ModalPopUp: React.FC<ModalPopUpProps> = ({
99
104
  <Animated.View style={[styles.modalContent, modalContentStyle]}>
100
105
  {closable && (
101
106
  <View style={styles.closeButtonContainer}>
102
- <TouchableOpacity onPress={hideModal} style={styles.closeButton}>
107
+ <TouchableOpacity onPress={userClose} style={styles.closeButton}>
103
108
  <View style={styles.iconButtonClose}>
104
109
  <Icon name="Times" size={13} color={Color.gray[900]} />
105
110
  </View>
@@ -116,11 +121,7 @@ const ModalPopUp: React.FC<ModalPopUpProps> = ({
116
121
  };
117
122
 
118
123
  const styles = StyleSheet.create({
119
- modalContainer: {
120
- flex: 1,
121
- justifyContent: 'center',
122
- alignItems: 'center',
123
- },
124
+ modalContainer: { flex: 1, justifyContent: 'center', alignItems: 'center' },
124
125
  backdrop: {
125
126
  position: 'absolute',
126
127
  top: 0,
@@ -129,39 +130,25 @@ const styles = StyleSheet.create({
129
130
  bottom: 0,
130
131
  backgroundColor: 'rgba(0, 0, 0, 0.5)',
131
132
  },
132
- backdropTouch: {
133
- width: '100%',
134
- height: '100%',
135
- },
133
+ backdropTouch: { width: '100%', height: '100%' },
136
134
  modalContent: {
137
135
  borderRadius: 16,
138
136
  overflow: 'visible',
139
137
  ...Platform.select({
140
138
  ios: {
141
139
  shadowColor: '#000',
142
- shadowOffset: {
143
- width: 0,
144
- height: 2,
145
- },
140
+ shadowOffset: { width: 0, height: 2 },
146
141
  shadowOpacity: 0.25,
147
142
  shadowRadius: 4,
148
143
  },
149
- android: {
150
- elevation: 5,
151
- },
144
+ android: { elevation: 5 },
152
145
  }),
153
146
  },
154
- closeButtonContainer: {
155
- position: 'absolute',
156
- top: 10,
157
- right: 10,
158
- zIndex: 1,
159
- },
147
+ closeButtonContainer: { position: 'absolute', top: 10, right: 10, zIndex: 1 },
160
148
  iconButtonClose: {
161
149
  justifyContent: 'center',
162
150
  alignContent: 'center',
163
151
  alignItems: 'center',
164
- top: 'auto',
165
152
  flex: 1,
166
153
  },
167
154
  closeButton: {
@@ -170,9 +157,7 @@ const styles = StyleSheet.create({
170
157
  borderRadius: 12,
171
158
  backgroundColor: '#ccc',
172
159
  },
173
- contentContainer: {
174
- padding: 16,
175
- },
160
+ contentContainer: { padding: 16 },
176
161
  });
177
162
 
178
163
  export default ModalPopUp;
@@ -0,0 +1,126 @@
1
+ # ViewInsets Component
2
+
3
+ Komponen React Native yang menyediakan padding otomatis berdasarkan safe area insets untuk menghindari area sistem seperti notch, status bar, dan navigation bar.
4
+
5
+ ## Instalasi
6
+
7
+ Komponen ini membutuhkan dependency berikut:
8
+
9
+ ```bash
10
+ npm install react-native-safe-area-context
11
+ # atau
12
+ yarn add react-native-safe-area-context
13
+ ```
14
+
15
+ Pastikan untuk membungkus aplikasi Anda dengan `SafeAreaProvider`:
16
+
17
+ ```jsx
18
+ import { SafeAreaProvider } from 'react-native-safe-area-context';
19
+
20
+ function App() {
21
+ return <SafeAreaProvider>{/* Konten aplikasi Anda */}</SafeAreaProvider>;
22
+ }
23
+ ```
24
+
25
+ ## Penggunaan Dasar
26
+
27
+ ```jsx
28
+ import ViewInsets from './ViewInsets';
29
+
30
+ function MyScreen() {
31
+ return (
32
+ <ViewInsets useTop useBottom>
33
+ {/* Konten Anda */}
34
+ </ViewInsets>
35
+ );
36
+ }
37
+ ```
38
+
39
+ ## Props
40
+
41
+ | Prop | Type | Default | Deskripsi |
42
+ | ----------- | ---------------------- | ------------ | ------------------------------------------------------- |
43
+ | `children` | `React.ReactNode` | **Required** | Konten yang akan ditampilkan di dalam container |
44
+ | `useTop` | `boolean` | `false` | Menambahkan padding top sesuai safe area inset atas |
45
+ | `useBottom` | `boolean` | `false` | Menambahkan padding bottom sesuai safe area inset bawah |
46
+ | `useLeft` | `boolean` | `false` | Menambahkan padding left sesuai safe area inset kiri |
47
+ | `useRight` | `boolean` | `false` | Menambahkan padding right sesuai safe area inset kanan |
48
+ | `style` | `StyleProp<ViewStyle>` | `undefined` | Style tambahan untuk container |
49
+ | `...rest` | `ViewProps` | - | Props lainnya akan diteruskan ke komponen View |
50
+
51
+ ## Contoh Penggunaan
52
+
53
+ ### Layar dengan Safe Area Atas dan Bawah
54
+
55
+ ```jsx
56
+ <ViewInsets useTop useBottom>
57
+ <Text>Konten aman dari notch dan navigation bar</Text>
58
+ </ViewInsets>
59
+ ```
60
+
61
+ ### Layar dengan Safe Area Atas Saja
62
+
63
+ ```jsx
64
+ <ViewInsets useTop>
65
+ <Text>Konten aman dari status bar/notch</Text>
66
+ </ViewInsets>
67
+ ```
68
+
69
+ ### Layar dengan Safe Area di Semua Sisi
70
+
71
+ ```jsx
72
+ <ViewInsets useTop useBottom useLeft useRight>
73
+ <Text>Konten aman dari semua area sistem</Text>
74
+ </ViewInsets>
75
+ ```
76
+
77
+ ### Dengan Custom Style
78
+
79
+ ```jsx
80
+ <ViewInsets
81
+ useTop
82
+ useBottom
83
+ style={{ backgroundColor: '#fff', paddingHorizontal: 16 }}
84
+ >
85
+ <Text>Konten dengan style tambahan</Text>
86
+ </ViewInsets>
87
+ ```
88
+
89
+ ### Dengan Props View Lainnya
90
+
91
+ ```jsx
92
+ <ViewInsets useTop useBottom testID="main-container" accessible={true}>
93
+ <Text>Konten dengan props accessibility</Text>
94
+ </ViewInsets>
95
+ ```
96
+
97
+ ## Fitur
98
+
99
+ - ✅ Otomatis menangani safe area insets
100
+ - ✅ Kontrol granular untuk setiap sisi (atas, bawah, kiri, kanan)
101
+ - ✅ Performa optimal dengan `useMemo` untuk menghindari re-render tidak perlu
102
+ - ✅ Mendukung semua props dari komponen View React Native
103
+ - ✅ TypeScript support dengan type definitions lengkap
104
+ - ✅ Default `flex: 1` untuk kemudahan layout
105
+
106
+ ## Catatan
107
+
108
+ - Komponen ini secara default menggunakan `flex: 1` pada container
109
+ - Safe area insets akan disesuaikan secara otomatis berdasarkan perangkat
110
+ - Berguna untuk menghindari area yang tertutup oleh notch, status bar, home indicator, dll
111
+ - Dapat dikombinasikan dengan style custom untuk kebutuhan layout yang lebih kompleks
112
+
113
+ ## TypeScript
114
+
115
+ Komponen ini sudah dilengkapi dengan TypeScript definitions. Interface `ViewInsetsProps` extends dari `ViewProps` sehingga mendukung semua props dari View React Native.
116
+
117
+ ```typescript
118
+ interface ViewInsetsProps extends ViewProps {
119
+ children: React.ReactNode;
120
+ useTop?: boolean;
121
+ useBottom?: boolean;
122
+ useLeft?: boolean;
123
+ useRight?: boolean;
124
+ bottomType?: 'inset' | 'tabbar'; // Prop ini didefinisikan tapi belum diimplementasikan
125
+ }
126
+ ```
@@ -0,0 +1,46 @@
1
+ import { StyleSheet, View, type ViewProps } from 'react-native';
2
+ import React, { useMemo } from 'react';
3
+ import { useSafeAreaInsets } from 'react-native-safe-area-context';
4
+
5
+ interface ViewInsetsProps extends ViewProps {
6
+ children: React.ReactNode;
7
+ useTop?: boolean;
8
+ useBottom?: boolean;
9
+ useLeft?: boolean;
10
+ useRight?: boolean;
11
+ bottomType?: 'inset' | 'tabbar';
12
+ }
13
+
14
+ const ViewInsets: React.FC<ViewInsetsProps> = ({
15
+ children,
16
+ style,
17
+ useTop = false,
18
+ useBottom = false,
19
+ useLeft = false,
20
+ useRight = false,
21
+ ...rest
22
+ }) => {
23
+ const insets = useSafeAreaInsets();
24
+
25
+ const defaultStyle = useMemo(
26
+ () =>
27
+ StyleSheet.create({
28
+ container: {
29
+ paddingTop: useTop ? insets.top : 0,
30
+ paddingBottom: useBottom ? insets.bottom : 0,
31
+ paddingLeft: useLeft ? insets.left : 0,
32
+ paddingRight: useRight ? insets.right : 0,
33
+ flex: 1,
34
+ },
35
+ }),
36
+ [insets, useTop, useBottom, useLeft, useRight]
37
+ );
38
+
39
+ return (
40
+ <View style={[defaultStyle.container, style]} {...rest}>
41
+ {children}
42
+ </View>
43
+ );
44
+ };
45
+
46
+ export default ViewInsets;