@herca/rn-kit 0.1.7 → 0.1.8

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 +11 -7
  2. package/lib/module/Accordion/README.md +1 -0
  3. package/lib/module/Alert/README.md +1 -0
  4. package/lib/module/Avatar/README_AVATAR.md +1 -1
  5. package/lib/module/Avatar/README_AVATARGROUP.md +3 -1
  6. package/lib/module/BottomSheet/README.md +1 -1
  7. package/lib/module/Button/README.md +3 -1
  8. package/lib/module/Calendar/README.md +1 -0
  9. package/lib/module/Chip/README.md +2 -1
  10. package/lib/module/Color/README.md +97 -46
  11. package/lib/module/DatePicker/{README.md → README_DATEPICKER.md} +1 -0
  12. package/lib/module/DatePicker/README_MONTHPICKER.md +90 -0
  13. package/lib/module/DatePicker/README_TIMEPICKER.md +83 -0
  14. package/lib/module/DatePicker/README_YEARPICKER.md +106 -0
  15. package/lib/module/DropDown/README.md +107 -0
  16. package/lib/module/Label/README.md +65 -0
  17. package/lib/module/RadioButton/README.md +2 -1
  18. package/lib/module/Ui/README_DEVIDER.md +62 -0
  19. package/lib/module/Ui/README_FOOTER.md +0 -0
  20. package/package.json +1 -1
  21. package/src/Accordion/README.md +1 -0
  22. package/src/Alert/README.md +1 -0
  23. package/src/Avatar/README_AVATAR.md +1 -1
  24. package/src/Avatar/README_AVATARGROUP.md +3 -1
  25. package/src/BottomSheet/README.md +1 -1
  26. package/src/Button/README.md +3 -1
  27. package/src/Calendar/README.md +1 -0
  28. package/src/Chip/README.md +2 -1
  29. package/src/Color/README.md +97 -46
  30. package/src/DatePicker/{README.md → README_DATEPICKER.md} +1 -0
  31. package/src/DatePicker/README_MONTHPICKER.md +90 -0
  32. package/src/DatePicker/README_TIMEPICKER.md +83 -0
  33. package/src/DatePicker/README_YEARPICKER.md +106 -0
  34. package/src/DropDown/README.md +107 -0
  35. package/src/Label/README.md +65 -0
  36. package/src/RadioButton/README.md +2 -1
  37. package/src/Ui/README_DEVIDER.md +62 -0
  38. package/src/Ui/README_FOOTER.md +0 -0
@@ -1 +1,108 @@
1
1
  # Dropdown
2
+
3
+ **Dropdown** merupakan komponen menu pilihan (select) berbasis **React Native** yang menampilkan daftar opsi di atas modal transparan. Komponen ini otomatis men‐posisikan daftar ke kiri atau ke kanan bergantung pada posisi tombol pemicu agar tidak terpotong layar.
4
+
5
+ ---
6
+
7
+ ## Instalasi
8
+
9
+ Komponen ini mengandalkan dependensi internal:
10
+
11
+ * `Color` – sistem warna.
12
+ * `ChipOptionProps` – tipe opsi.
13
+
14
+ Serta modul standar React Native: `Modal`, `ScrollView`, dll. Tidak memerlukan library eksternal.
15
+
16
+ ---
17
+
18
+ ## API Reference
19
+
20
+ | Prop | Tipe | Default | Deskripsi |
21
+ | -------------- | ----------------------------------- | ----------- | ------------------------------------------------------------------- |
22
+ | `options` | `ChipOptionProps[]` | `[]` | Daftar objek `{ label, value }` yang akan ditampilkan sebagai opsi. |
23
+ | `maxHeight` | `number` | `200` | Tinggi maksimum daftar sebelum dapat di‐scroll. |
24
+ | `onSelect` | `(value: string \| number) => void` | `undefined` | Callback saat pengguna memilih opsi. |
25
+ | `renderButton` | `React.ReactNode` | **(wajib)** | Elemen yang dipakai sebagai tombol pemicu dropdown. |
26
+
27
+ ### Struktur `ChipOptionProps`
28
+
29
+ ```ts
30
+ interface ChipOptionProps {
31
+ label: string;
32
+ value: string | number;
33
+ }
34
+ ```
35
+
36
+ ---
37
+
38
+ ## Cara Kerja Singkat
39
+
40
+ 1. **Posisi & Alignment**
41
+
42
+ * Saat tombol ditekan, komponen mengukur posisi tombol (`UIManager.measureInWindow`).
43
+ * Jika titik tengah tombol berada di sisi kanan layar, daftar disejajarkan ke kanan; sebaliknya ke kiri.
44
+ 2. **Modal & Pressable Overlay**
45
+
46
+ * Daftar opsi dibungkus `Modal` transparan.
47
+ * `Pressable` penuh layar di belakang daftar menangani klik di luar untuk menutup menu.
48
+ 3. **Scroll & Batas Tinggi**
49
+
50
+ * Daftar opsi di dalam `ScrollView` dengan properti `nestedScrollEnabled` agar tetap dapat di‐scroll di dalam modalsheet lain.
51
+ 4. **Highlight Opsi Terpilih**
52
+
53
+ * Opsi aktif diberi style `optionSelected` – background `Color.primary[50]` & border `Color.primary[300]`.
54
+
55
+ ---
56
+
57
+ ## Contoh Penggunaan
58
+
59
+ ```tsx
60
+ import { useState } from 'react';
61
+ import { View, Text } from 'react-native';
62
+ import Dropdown from '@/components/Dropdown/Dropdown';
63
+
64
+ const options = [
65
+ { label: 'Apple', value: 'apple' },
66
+ { label: 'Banana', value: 'banana' },
67
+ { label: 'Cherry', value: 'cherry' },
68
+ ];
69
+
70
+ export default function DropdownExample() {
71
+ const [fruit, setFruit] = useState<string | number>('apple');
72
+
73
+ return (
74
+ <View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
75
+ <Dropdown
76
+ options={options}
77
+ maxHeight={150}
78
+ onSelect={(val) => setFruit(val)}
79
+ renderButton={
80
+ <View style={{ padding: 12, borderWidth: 1, borderRadius: 8 }}>
81
+ <Text>{options.find((o) => o.value === fruit)?.label}</Text>
82
+ </View>
83
+ }
84
+ />
85
+ </View>
86
+ );
87
+ }
88
+ ```
89
+
90
+ ---
91
+
92
+ ## Kustomisasi Tampilan
93
+
94
+ | Style Key | Fungsi | Cara Ubah |
95
+ | ---------------- | ---------------------- | ------------------------------------------------- |
96
+ | `dropdownList` | Container daftar opsi. | Ubah `width`, `borderRadius`, `borderColor`, dll. |
97
+ | `option` | Setiap baris opsi. | Ubah `padding` atau `gap` sesuai kebutuhan. |
98
+ | `optionSelected` | Style opsi terpilih. | Sesuaikan warna highlight dengan brand. |
99
+
100
+ ---
101
+
102
+ ## Tips Implementasi
103
+
104
+ * **Kontrol Render Button**: Anda bebas menggunakan komponen apa pun sebagai `renderButton` (ikon, input field, card, dll.). Dropdown akan menggunakan posisi & ukuran elemen ini.
105
+ * **Close on Scroll Parent**: Jika dropdown dipakai dalam layar yang di‐scroll, pertimbangkan menutup dropdown saat parent di‐scroll untuk mencegah posisi meleset.
106
+ * **Validasi**: Komponen tidak memaksa nilai default. Anda dapat men‐set `selected` manual via `useState` agar kontrol tetap ter‐sinkron.
107
+
108
+ ---
@@ -0,0 +1,65 @@
1
+ # Label
2
+
3
+ **Label** adalah komponen kecil berbentuk badge untuk menampilkan status, kategori, atau metadata ringkas. Komponen ini mendukung ikon, variasi warna, dan konten kustom.
4
+
5
+ ## API Reference
6
+
7
+ | Prop | Tipe | Default | Deskripsi |
8
+ | ---------- | ------------------------------------------------------------------------------------------------ | ----------- | ------------------------------------------------------------------------------ |
9
+ | `label` | `string` | `''` | Teks yang ditampilkan jika `children` tidak disediakan. |
10
+ | `children` | `React.ReactNode` | `undefined` | Menampilkan elemen kustom sebagai isi label. Jika ada, `label` akan diabaikan. |
11
+ | `color` | `'default' \| 'success' \| 'danger' \| 'primary' \| 'warning' \| 'info' \| 'purple' \| 'orange'` | `'default'` | Variasi warna latar dan teks. |
12
+ | `icon` | `IconNameProps` | `undefined` | Menampilkan ikon di sebelah kiri teks. |
13
+ | `size` | `'small' \| 'medium'` | `'medium'` | (Belum digunakan – untuk ekspansi ukuran ke depan.) |
14
+
15
+ ---
16
+
17
+ ## Warna yang Didukung
18
+
19
+ | Warna | Background | Teks |
20
+ | --------- | ------------------- | -------------------- |
21
+ | `default` | `Color.gray[50]` | `Color.gray[900]` |
22
+ | `success` | `Color.success[50]` | `Color.success[300]` |
23
+ | `danger` | `Color.danger[50]` | `Color.danger[300]` |
24
+ | `primary` | `Color.primary[50]` | `Color.primary[300]` |
25
+ | `warning` | `Color.warning[50]` | `Color.warning[300]` |
26
+ | `info` | `Color.info[50]` | `Color.info[300]` |
27
+ | `purple` | `Color.purple[50]` | `Color.purple[300]` |
28
+ | `orange` | `Color.orange[50]` | `Color.orange[300]` |
29
+
30
+ ---
31
+
32
+ ## Contoh Penggunaan
33
+
34
+ ### Label Sederhana
35
+
36
+ ```tsx
37
+ <Label label="Active" color="success" />
38
+ ```
39
+
40
+ ### Label dengan Ikon
41
+
42
+ ```tsx
43
+ <Label label="Error" color="danger" icon="AlertCircle" />
44
+ ```
45
+
46
+ ### Kustom Isi (Children)
47
+
48
+ ```tsx
49
+ <Label color="primary">
50
+ <View style={{ flexDirection: 'row', alignItems: 'center' }}>
51
+ <Icon name="Check" color={Color.primary[300]} size={12} />
52
+ <Text style={{ color: Color.primary[300], marginLeft: 4 }}>Custom</Text>
53
+ </View>
54
+ </Label>
55
+ ```
56
+
57
+ ---
58
+
59
+ ## Catatan Tambahan
60
+
61
+ * Jika Anda memberikan `children`, maka `label` dan `icon` akan diabaikan.
62
+ * Komponen ini menggunakan `alignSelf: 'flex-start'` agar ukuran label tidak penuh.
63
+ * Prop `size` belum aktif, namun sudah disiapkan jika ke depan ingin mendukung skala `small`/`large`.
64
+
65
+ ---
@@ -1,7 +1,8 @@
1
1
  # 📦 RadioButton – Komponen React Native
2
2
 
3
3
  Komponen `RadioButton` ini digunakan untuk menampilkan daftar pilihan dalam bentuk radio button di aplikasi React Native.
4
- ![Deskripsi Alt](../../assets/doc/RadioButton/RadioButton.png)
4
+ <img src="../../assets/doc/RadioButton/RadioButton.png" width=200>
5
+
5
6
 
6
7
  ## 📄 Import
7
8
 
@@ -0,0 +1,62 @@
1
+ # Divider
2
+
3
+ **Divider** adalah komponen garis horizontal sederhana yang digunakan untuk memisahkan konten secara visual dalam antarmuka pengguna.
4
+
5
+ ---
6
+
7
+ ## Instalasi
8
+
9
+ Komponen ini tidak memerlukan dependensi eksternal. Hanya menggunakan:
10
+
11
+ * `Color` – untuk warna garis.
12
+ * `View` dan `StyleSheet` dari `react-native`.
13
+
14
+ ---
15
+
16
+ ## API Reference
17
+
18
+ Tidak memiliki properti (props) khusus. Komponen ini dapat digunakan langsung dan bisa dikustomisasi melalui `style` eksternal jika diperlukan.
19
+
20
+ ---
21
+
22
+ ## Contoh Penggunaan
23
+
24
+ ### Divider Default
25
+
26
+ ```tsx
27
+ import Divider from '@/components/Divider/Divider';
28
+
29
+ <View>
30
+ <Text>Bagian Atas</Text>
31
+ <Divider />
32
+ <Text>Bagian Bawah</Text>
33
+ </View>
34
+ ```
35
+
36
+ ### Divider dengan Margin
37
+
38
+ ```tsx
39
+ <View style={{ marginVertical: 12 }}>
40
+ <Divider />
41
+ </View>
42
+ ```
43
+
44
+ ### Divider yang Dikustomisasi
45
+
46
+ ```tsx
47
+ <Divider style={{ backgroundColor: 'red', height: 2 }} />
48
+ ```
49
+
50
+ > Catatan: Untuk mengubah gaya `Divider`, bungkus komponen dengan `View` tambahan atau tambahkan prop `style` melalui wrapper jika perlu.
51
+
52
+ ---
53
+
54
+ ## Style Default
55
+
56
+ ```ts
57
+ {
58
+ height: 1,
59
+ backgroundColor: Color.gray[200],
60
+ }
61
+ ```
62
+
File without changes
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@herca/rn-kit",
3
- "version": "0.1.7",
3
+ "version": "0.1.8",
4
4
  "description": "React Native UI Kit",
5
5
  "main": "./lib/module/index.js",
6
6
  "types": "./lib/typescript/src/index.d.ts",
@@ -1,6 +1,7 @@
1
1
  # 📂 Accordion
2
2
 
3
3
  Komponen **Accordion** digunakan untuk menyembunyikan atau menampilkan konten secara dinamis. Biasanya digunakan untuk struktur seperti FAQ atau daftar konten bertingkat.
4
+
4
5
  <img src="../../assets/doc/Accordion/Accordion.gif" alt="Deskripsi Alt" width="200" />
5
6
 
6
7
  ## 📦 USAGE
@@ -1,6 +1,7 @@
1
1
  # 📢 Alert Component
2
2
 
3
3
  Komponen `Alert` digunakan untuk menampilkan pesan notifikasi dengan ikon, judul, dan pesan yang dapat dikustomisasi warnanya sesuai konteks (seperti *success*, *info*, *warning*, dll).
4
+
4
5
  <img src="../../assets/doc/Alert/Alert.png" alt="Deskripsi Alt" width="200" />
5
6
 
6
7
  ## ✨ Fitur
@@ -1,7 +1,7 @@
1
1
  # 🧑‍🎨 Avatar Component
2
2
 
3
3
  Komponen `Avatar` digunakan untuk menampilkan foto pengguna atau inisial nama jika foto tidak tersedia.
4
- ![Deskripsi Alt](../../assets/doc/Avatar/Avatar.png)
4
+ <img src="../../assets/doc/Avatar/Avatar.png" width=200>
5
5
 
6
6
  ## ✨ Fitur
7
7
 
@@ -2,7 +2,9 @@
2
2
  # AvatarGroup Component (React Native)
3
3
 
4
4
  The `AvatarGroup` component displays a group of user avatars. It supports image avatars, initials-based avatars, and a fallback icon. If there are more avatars than the maximum visible count, it displays a "+X" bubble.
5
- ![Deskripsi Alt](../../assets/doc/Avatar/AvatarGroup.png)
5
+
6
+ <img src="../../assets/doc/Avatar/AvatarGroup.png" width=200>
7
+
6
8
  ---
7
9
 
8
10
  ## 📦 Props
@@ -1,8 +1,8 @@
1
1
  # ⬆️ BottomSheet Component
2
2
 
3
3
  Komponen `BottomSheet` adalah modal bawah (slide-up) untuk menampilkan konten dinamis, form, konfirmasi, dll, dengan berbagai fitur interaktif seperti gesture drag, keyboard-aware, dan customizable height.
4
- ![Deskripsi Alt](../../assets/doc/BottomSheet/BottomSheet.gif)
5
4
 
5
+ <img src="../../assets/doc/BottomSheet/BottomSheet.gif" width=200>
6
6
  ---
7
7
 
8
8
  ## 📦 Props
@@ -2,7 +2,9 @@
2
2
  # 🔘 Komponen Button (React Native)
3
3
 
4
4
  Komponen `Button` ini adalah tombol serbaguna untuk aplikasi React Native. Mendukung berbagai ukuran, varian, warna, dan status seperti `disabled` dan `loading`.
5
- ![Deskripsi Alt](../../assets/doc/Button/Button.png)
5
+
6
+
7
+ <img src="../../assets/doc/Button/Button.png" width=200>
6
8
 
7
9
  ---
8
10
 
@@ -1,6 +1,7 @@
1
1
  # 📆 Komponen Kalender Kustom (React Native)
2
2
 
3
3
  Komponen kalender ini dibuat menggunakan React Native dan memungkinkan pengguna untuk memilih tanggal tunggal maupun rentang tanggal, serta mendukung fitur penandaan dan pembatasan tanggal.
4
+ <img src="../../assets/doc/Calendar/Calendar.png" width=200>
4
5
 
5
6
  ---
6
7
 
@@ -1,7 +1,8 @@
1
1
  # 📦 Komponen `Chip` – React Native
2
2
 
3
3
  Komponen `Chip` digunakan untuk menampilkan daftar pilihan seperti tag, filter, atau kategori dalam bentuk tombol kecil (chip). Komponen ini mendukung pilihan tunggal maupun jamak, arah horizontal/vertikal, dan gaya warna yang dapat disesuaikan.
4
- ![Deskripsi Alt](../../assets/doc/Chip/Chip.png)
4
+
5
+ <img src="../../assets/doc/Chip/Chip.png" width=200>
5
6
 
6
7
  ---
7
8
 
@@ -1,54 +1,105 @@
1
- # 📦 Konstanta: Color
2
- Konstanta Color berisi daftar token warna yang digunakan untuk styling antarmuka aplikasi menggunakan React Native. Warna-warna ini disusun berdasarkan tema dan gradasi, cocok digunakan bersama desain sistem seperti Design Token.
1
+ # Color Palette
2
+
3
+ Berikut adalah definisi warna yang digunakan di design system React Native Anda. Palette mencakup warna dasar (*base*), skala abu‐abu (*gray*), kategori semantik (*primary*, *success*, *danger*, *warning*, *info*, *orange*, *purple*), serta utilitas lain seperti `divider` dan `disabled`.
4
+
5
+ Warna tersimpan dalam objek `Color` dengan struktur hierarkis seperti contoh berikut:
6
+
7
+ ```ts
8
+ Color.primary[500] // -> "#4D46FF"
9
+ Color.gray[200] // -> "#EBEBEB"
10
+ ```
11
+
12
+ ---
13
+
14
+ ## Struktur Objek Color
15
+
16
+ ```ts
17
+ const Color = {
18
+ base: { ... },
19
+ gray: { ... },
20
+ primary: { ... },
21
+ warning: { ... },
22
+ danger: { ... },
23
+ success: { ... },
24
+ info: { ... },
25
+ orange: { ... },
26
+ purple: { ... },
27
+ divider: { ... },
28
+ disabled: { ... },
29
+ shadow: { ... },
30
+ };
31
+ ```
32
+
33
+ ### Skema Skala Warna
34
+
35
+ * **0–1000** (atau 0–950) – Semakin besar angka, semakin gelap warna.
36
+ * **50** – Latar paling terang (sering dipakai untuk *background* highlight).
37
+ * **500** – Warna utama (brand color dan teks link normal).
38
+ * **700/800/900** – Warna paling gelap untuk teks di atas latar berkait.
39
+
40
+ ---
41
+
42
+ ## Tabel Ringkasan
43
+
44
+ | Kategori | Contoh Penggunaan | Keterangan |
45
+ | ---------- | --------------------- | ------------------------------------------- |
46
+ | `base` | `Color.base.white100` | Warna putih/ hitam utama UI dasar. |
47
+ | `gray` | `Color.gray[700]` | Teks, ikon sekunder, border netral. |
48
+ | `primary` | `Color.primary[500]` | Aksi utama, tombol brand, ikon utama. |
49
+ | `success` | `Color.success[500]` | Status berhasil: label “Success”, badge OK. |
50
+ | `danger` | `Color.danger[500]` | Error, status gagal. |
51
+ | `warning` | `Color.warning[500]` | Peringatan. |
52
+ | `info` | `Color.info[500]` | Informasi tambahan. |
53
+ | `orange` | `Color.orange[500]` | Aksen/ badge khusus. |
54
+ | `purple` | `Color.purple[500]` | Aksen sekunder/ grafik. |
55
+ | `divider` | `Color.divider[25]` | Garis pemisah tipis. |
56
+ | `disabled` | `Color.disabled[25]` | Kontrol non‐aktif. |
57
+
58
+ > Anda bisa menambahkan `shadow` palette jika diperlukan gradasi drop shadow.
59
+
60
+ ---
61
+
62
+ ## TypeScript Helper
63
+
64
+ ```ts
65
+ export type ColorVariantType =
66
+ | 'default'
67
+ | 'success'
68
+ | 'danger'
69
+ | 'primary'
70
+ | 'warning'
71
+ | 'info'
72
+ | 'purple'
73
+ | 'orange';
74
+ ```
75
+
76
+ Tipe ini dipakai di komponen lain (mis. `Label`) untuk membatasi nama variant.
77
+
78
+ ---
79
+
80
+ ## Contoh Implementasi
3
81
 
4
- ## 🎨 Struktur Warna
5
- ✅ Base
6
- Warna dasar utama:
7
-
8
- white100: putih solid
9
-
10
- white60: putih transparan 60%
11
-
12
- black100: hitam solid
13
-
14
- black60: hitam transparan 60%
15
-
16
- ### ⚪ Gray (abu-abu)
17
- Gradasi abu-abu dari terang (gray.50) hingga gelap (gray.950), cocok untuk teks, latar, border, dsb.
18
-
19
- ### 🔵 Primary
20
- Gradasi warna utama (biru), digunakan untuk tombol, highlight, atau elemen penting lainnya.
21
-
22
- ### 🟠 Warning
23
- Warna peringatan, digunakan untuk menandai hal-hal seperti alert, notifikasi kuning, dll.
24
-
25
- ### 🔴 Danger
26
- Warna untuk kondisi berbahaya atau error (merah).
27
-
28
- ### 🟢 Success
29
- Digunakan untuk kondisi berhasil atau sukses (hijau).
30
-
31
- ### 🔷 Info
32
- Warna tambahan untuk informasi, notifikasi, atau status sekunder.
33
-
34
- ### 🟧 Orange
35
- Warna oranye, alternatif dari primary/warning.
82
+ ```tsx
83
+ import Color from '@/components/Color/Color';
36
84
 
37
- ### 🟣 Purple
38
- Warna ungu, bisa digunakan untuk status spesial atau branding.
85
+ const MyButton = () => (
86
+ <View style={{ backgroundColor: Color.primary[500], padding: 12 }}>
87
+ <Text style={{ color: Color.base.white100 }}>Click Me</Text>
88
+ </View>
89
+ );
90
+ ```
39
91
 
40
- 🧱 Divider
41
- divider.25: Warna pembatas antar elemen UI.
92
+ ---
42
93
 
43
- 📴 Disabled
44
- disabled.25: Warna untuk elemen non-aktif.
94
+ ## Tips Penggunaan
45
95
 
46
- ## Cara menggunakan
96
+ * Gunakan warna **50** untuk latar lembut (highlight, badge background).
97
+ * Gunakan warna **500** untuk elemen interaktif utama.
98
+ * Gunakan warna **700+** untuk teks di atas warna **50–300**.
99
+ * Gunakan `rgba(..., 0.x)` jika memerlukan translusi.
47
100
 
48
- ```tsx
49
- import Color from '@herca/rn-kit';
101
+ ---
50
102
 
51
- <View style={{ backgroundColor: Color.primary[500] }} />
52
- <Text style={{ color: Color.gray[900] }}>Teks</Text>
103
+ ## Lisensi
53
104
 
54
- ```
105
+ Bagian dari library internal Anda; ikuti lisensi proyek.
@@ -4,6 +4,7 @@ Komponen `DatePicker` adalah antarmuka pemilih tanggal yang dibungkus dalam sebu
4
4
 
5
5
  Komponen ini extend dari Calendar, jadi kalian bisa menggunakan semua props yang ada di Calendar [Calendar](../Calendar/README.md)
6
6
 
7
+ <img src="../../assets/doc/Datepicker/Datepicker.gif" width=200>
7
8
  ---
8
9
 
9
10
  ## ✨ Fitur
@@ -0,0 +1,90 @@
1
+ # MonthPicker
2
+
3
+ Komponen **MonthPicker** adalah komponen pemilih bulan berbasis **React Native** yang dapat menampilkan pilihan bulan dalam tiga mode berbeda: **single**, **range**, dan **multiple**. Komponen ini dirancang untuk dipakai di dalam komponen **BottomSheet** dengan tampilan yang konsisten terhadap desain sistem.
4
+
5
+
6
+
7
+ ---
8
+
9
+ ## API Reference
10
+
11
+ | Prop | Tipe | Default | Deskripsi |
12
+ | ---------- | ------------------------------------------------------------------------------------- | ----------- | ---------------------------------------------------------------------------------------------------------------- |
13
+ | `isOpen` | `boolean` | `false` | Menentukan apakah **BottomSheet** terbuka atau tertutup. |
14
+ | `onClose` | `() => void` | `undefined` | Callback yang dipanggil saat pengguna menekan tombol **Batal** atau menutup **BottomSheet**. |
15
+ | `onChange` | `(value: number[] \| { startDate: number \| null; endDate: number \| null }) => void` | `undefined` | Callback yang dipanggil ketika pengguna menekan tombol **Pilih**. Parameter yang dikirim tergantung pada `mode`. |
16
+ | `mode` | `'single' \| 'range' \| 'multiple'` | `'single'` | Menentukan cara pemilihan bulan. |
17
+
18
+ ### Bentuk *value* yang Dikirim oleh `onChange`
19
+
20
+ | `mode` | Bentuk *value* |
21
+ | ---------- | -------------------------------------------------------------------------------------------------------------------------------------------------- |
22
+ | `single` | `number[]` – array yang berisi satu elemen bulan terpilih. Contoh: `[5]` untuk Mei. |
23
+ | `range` | `{ startDate: number \| null; endDate: number \| null }` – objek berisi bulan mulai & akhir. Contoh: `{ startDate: 1, endDate: 3 }` untuk Jan–Mar. |
24
+ | `multiple` | `number[]` – array berisi daftar bulan terpilih. Contoh: `[2, 4, 8]` untuk Feb, Apr, Agt. |
25
+
26
+ ---
27
+
28
+ ## Contoh Penggunaan
29
+
30
+ ```tsx
31
+ import { useState } from 'react';
32
+ import { View, Button } from 'react-native';
33
+ import MonthPicker from '@/components/MonthPicker/MonthPicker';
34
+
35
+ export default function Example() {
36
+ const [open, setOpen] = useState(false);
37
+ const [months, setMonths] = useState<number[]>([]);
38
+
39
+ return (
40
+ <View style={{ flex: 1 }}>
41
+ <Button title="Pilih Bulan" onPress={() => setOpen(true)} />
42
+
43
+ <MonthPicker
44
+ isOpen={open}
45
+ mode="multiple"
46
+ onClose={() => setOpen(false)}
47
+ onChange={(value) => {
48
+ if (Array.isArray(value)) {
49
+ setMonths(value);
50
+ }
51
+ setOpen(false);
52
+ }}
53
+ />
54
+ </View>
55
+ );
56
+ }
57
+ ```
58
+
59
+ ---
60
+
61
+ ## Detail
62
+
63
+ 1. **Single Mode**
64
+
65
+ * Klik satu bulan untuk menandai pilihan.
66
+ * Menekan **Pilih** mengirimkan array dengan satu elemen.
67
+ 2. **Range Mode**
68
+
69
+ * Klik bulan pertama untuk menentukan `startDate`.
70
+ * Klik bulan kedua untuk menentukan `endDate`.
71
+ * Jika `startDate` sudah terisi dan `endDate` belum, tetapi pengguna memilih bulan yang lebih kecil dari `startDate`, maka komponen otomatis menukar posisi dan mengisi `endDate` dengan nilai awal `startDate`.
72
+ 3. **Multiple Mode**
73
+
74
+ * Klik untuk toggle seleksi pada tiap bulan. Bulan yang dipilih disimpan dalam array `multipleValue`.
75
+
76
+ ---
77
+
78
+ ## Kustomisasi Tampilan
79
+
80
+ * **Warna**: Warna latar dan border untuk opsi terpilih mengikuti `Color.primary` pada design system. Anda dapat menyesuaikannya dengan mengubah style `optionSelected` di dalam `MonthPicker`.
81
+ * **Jumlah Kolom**: Saat ini komponen menampilkan `numColumns={3}` pada `FlatList`. Ubah nilai ini untuk menyesuaikan grid.
82
+
83
+ ---
84
+
85
+ ## Tips
86
+
87
+ * Pastikan memanggil `onClose` setelah memproses hasil `onChange` agar **BottomSheet** tertutup.
88
+ * Komponen ini tidak menangani validasi kombinasi bulan secara otomatis (mis. range satu tahun penuh). Tambahkan logika tambahan di tempat Anda memakainya apabila diperlukan.
89
+
90
+ ---
@@ -0,0 +1,83 @@
1
+ # TimePickerWheel
2
+
3
+ **TimePickerWheel** adalah komponen pemilih waktu berbentuk *wheel* (picker bergulir) untuk **React Native**. Komponen ini menampilkan dua kolom (jam & menit) yang dapat digulir secara vertikal, dibungkus di dalam komponen **BottomSheet**.
4
+
5
+ ---
6
+
7
+ ## API Reference
8
+
9
+ | Prop | Tipe | Default | Deskripsi |
10
+ | ---------- | --------------------------------------------------- | ------- | --------------------------------------------------------------------------------------------- |
11
+ | `isOpen` | `boolean` | `false` | Menentukan apakah **BottomSheet** terbuka. |
12
+ | `onClose` | `() => void` | `-` | Callback saat pengguna menutup **BottomSheet** atau menekan tombol **Batal**. |
13
+ | `onChange` | `(value: { hour: number; minute: number }) => void` | `-` | Callback saat pengguna menekan tombol **Pilih**. Objek yang dikirim berisi `hour` & `minute`. |
14
+
15
+ ### Bentuk *value* `onChange`
16
+
17
+ ```ts
18
+ {
19
+ hour: number; // 0–23
20
+ minute: number; // 0–59
21
+ }
22
+ ```
23
+
24
+ ---
25
+
26
+ ## Cara Kerja Singkat
27
+
28
+ 1. **Wheel Padding** – Komponen menambahkan elemen *dummy* di atas & bawah daftar agar item tengah selalu berada di posisi highlight.
29
+ 2. **Highlight** – Baris tengah diberi `backgroundColor` khusus (`Color.primary[50]`) untuk menonjolkan pilihan aktif.
30
+ 3. **Snapping** – Properti `snapToInterval={ITEM_HEIGHT}` memastikan scroll *wheel* berhenti tepat di setiap item.
31
+ 4. **Sync & Loop** – Setelah scroll selesai, komponen menghitung indeks nyata (0‑23 untuk jam, 0‑59 untuk menit) agar wheel terasa tak terbatas.
32
+
33
+ ---
34
+
35
+ ## Contoh Penggunaan
36
+
37
+ ```tsx
38
+ import { useState } from 'react';
39
+ import { View, Button } from 'react-native';
40
+ import TimePickerWheel from '@/components/TimePickerWheel/TimePickerWheel';
41
+
42
+ export default function Example() {
43
+ const [open, setOpen] = useState(false);
44
+ const [time, setTime] = useState<{ hour: number; minute: number } | null>(
45
+ null
46
+ );
47
+
48
+ const formatted = time ? `${time.hour.toString().padStart(2, '0')}:${time.minute.toString().padStart(2, '0')}` : '—';
49
+
50
+ return (
51
+ <View style={{ flex: 1 }}>
52
+ <Button title={`Pilih Waktu (${formatted})`} onPress={() => setOpen(true)} />
53
+
54
+ <TimePickerWheel
55
+ isOpen={open}
56
+ onClose={() => setOpen(false)}
57
+ onChange={(value) => {
58
+ setTime(value);
59
+ setOpen(false);
60
+ }}
61
+ />
62
+ </View>
63
+ );
64
+ }
65
+ ```
66
+
67
+ ---
68
+
69
+ ## Kustomisasi Tampilan
70
+
71
+ * **Jumlah Items Terlihat** (`VISIBLE_ITEMS`): Default 5. Ubah nilai konstanta untuk menambah/kurangi tinggi wheel.
72
+ * **Tinggi Item** (`ITEM_HEIGHT`): Default 40. Pengaturan ini mempengaruhi `snapToInterval`.
73
+ * **Warna & Tipografi**: Edit style `selectedItemText`, `itemText`, dan `highlight` untuk menyesuaikan brand guideline.
74
+
75
+ ---
76
+
77
+ ## Tips Implementasi
78
+
79
+ * Selalu panggil `onClose` setelah menangani hasil `onChange` agar **BottomSheet** menutup.
80
+ * Jika Anda ingin menetapkan waktu awal sebelum picker dibuka, setel `selectedHour` & `selectedMinute` memakai `useState` lalu buka picker.
81
+ * Komponen ini tidak membatasi kombinasi jam‑menit (mis. langkah 5 menit). Tambahkan logika tambahan jika diperlukan.
82
+
83
+ ---