@herca/rn-kit 0.1.50 → 0.1.52
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/lib/module/Icon/Icon.js +15 -1
- package/lib/module/Icon/Icon.js.map +1 -1
- package/lib/module/Icon/icons/AlignCenter.js +25 -0
- package/lib/module/Icon/icons/AlignCenter.js.map +1 -0
- package/lib/module/Icon/icons/AlignLeft.js +25 -0
- package/lib/module/Icon/icons/AlignLeft.js.map +1 -0
- package/lib/module/Icon/icons/AlignRight.js +25 -0
- package/lib/module/Icon/icons/AlignRight.js.map +1 -0
- package/lib/module/Icon/icons/Bold.js +3 -3
- package/lib/module/Icon/icons/Bold.js.map +1 -1
- package/lib/module/Icon/icons/Italic.js +3 -3
- package/lib/module/Icon/icons/Italic.js.map +1 -1
- package/lib/module/Icon/icons/Link.js +25 -0
- package/lib/module/Icon/icons/Link.js.map +1 -0
- package/lib/module/Icon/icons/ListOrdered.js +34 -0
- package/lib/module/Icon/icons/ListOrdered.js.map +1 -0
- package/lib/module/Icon/icons/ListUnOrdered.js +25 -0
- package/lib/module/Icon/icons/ListUnOrdered.js.map +1 -0
- package/lib/module/Icon/icons/StrikeThrough.js +25 -0
- package/lib/module/Icon/icons/StrikeThrough.js.map +1 -0
- package/lib/module/Icon/icons/UnderLine.js +3 -3
- package/lib/module/Icon/icons/UnderLine.js.map +1 -1
- package/lib/module/TextEditor/README.md +263 -0
- package/lib/module/TextEditor/TextEditor.js +538 -63
- package/lib/module/TextEditor/TextEditor.js.map +1 -1
- package/lib/typescript/src/Icon/Icon.d.ts.map +1 -1
- package/lib/typescript/src/Icon/icons/AlignCenter.d.ts +9 -0
- package/lib/typescript/src/Icon/icons/AlignCenter.d.ts.map +1 -0
- package/lib/typescript/src/Icon/icons/AlignLeft.d.ts +9 -0
- package/lib/typescript/src/Icon/icons/AlignLeft.d.ts.map +1 -0
- package/lib/typescript/src/Icon/icons/AlignRight.d.ts +9 -0
- package/lib/typescript/src/Icon/icons/AlignRight.d.ts.map +1 -0
- package/lib/typescript/src/Icon/icons/Bold.d.ts.map +1 -1
- package/lib/typescript/src/Icon/icons/Italic.d.ts.map +1 -1
- package/lib/typescript/src/Icon/icons/Link.d.ts +9 -0
- package/lib/typescript/src/Icon/icons/Link.d.ts.map +1 -0
- package/lib/typescript/src/Icon/icons/ListOrdered.d.ts +9 -0
- package/lib/typescript/src/Icon/icons/ListOrdered.d.ts.map +1 -0
- package/lib/typescript/src/Icon/icons/ListUnOrdered.d.ts +9 -0
- package/lib/typescript/src/Icon/icons/ListUnOrdered.d.ts.map +1 -0
- package/lib/typescript/src/Icon/icons/StrikeThrough.d.ts +9 -0
- package/lib/typescript/src/Icon/icons/StrikeThrough.d.ts.map +1 -0
- package/lib/typescript/src/Icon/icons/UnderLine.d.ts.map +1 -1
- package/lib/typescript/src/Icon/type.d.ts +1 -1
- package/lib/typescript/src/Icon/type.d.ts.map +1 -1
- package/lib/typescript/src/TextEditor/TextEditor.d.ts +20 -1
- package/lib/typescript/src/TextEditor/TextEditor.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/Icon/Icon.tsx +14 -0
- package/src/Icon/icons/AlignCenter.tsx +22 -0
- package/src/Icon/icons/AlignLeft.tsx +28 -0
- package/src/Icon/icons/AlignRight.tsx +22 -0
- package/src/Icon/icons/Bold.tsx +8 -2
- package/src/Icon/icons/Italic.tsx +8 -2
- package/src/Icon/icons/Link.tsx +22 -0
- package/src/Icon/icons/ListOrdered.tsx +38 -0
- package/src/Icon/icons/ListUnOrdered.tsx +32 -0
- package/src/Icon/icons/StrikeThrough.tsx +26 -0
- package/src/Icon/icons/UnderLine.tsx +8 -2
- package/src/Icon/type.tsx +7 -0
- package/src/TextEditor/README.md +263 -0
- package/src/TextEditor/TextEditor.tsx +685 -133
package/src/TextEditor/README.md
CHANGED
|
@@ -0,0 +1,263 @@
|
|
|
1
|
+
# TextEditor Component
|
|
2
|
+
|
|
3
|
+
Rich text editor component untuk React Native dengan toolbar formatting yang lengkap dan support untuk link, list, dan text alignment.
|
|
4
|
+
|
|
5
|
+
## Features
|
|
6
|
+
|
|
7
|
+
- ✅ Rich text formatting (Bold, Italic, Underline, Strikethrough)
|
|
8
|
+
- ✅ Insert dan edit hyperlinks
|
|
9
|
+
- ✅ Bullet dan numbered lists
|
|
10
|
+
- ✅ Text alignment (Left, Center, Right)
|
|
11
|
+
- ✅ Character counter dengan max length validation
|
|
12
|
+
- ✅ Custom placeholder
|
|
13
|
+
- ✅ WebView-based editor dengan contenteditable
|
|
14
|
+
- ✅ Toolbar otomatis muncul saat keyboard aktif
|
|
15
|
+
- ✅ Support iOS dan Android
|
|
16
|
+
- ✅ Imperative methods (getContent, setContent, clearContent)
|
|
17
|
+
|
|
18
|
+
## Installation
|
|
19
|
+
|
|
20
|
+
Pastikan dependencies berikut sudah terinstall:
|
|
21
|
+
|
|
22
|
+
```bash
|
|
23
|
+
npm install react-native-webview
|
|
24
|
+
# atau
|
|
25
|
+
yarn add react-native-webview
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
## Basic Usage
|
|
29
|
+
|
|
30
|
+
```tsx
|
|
31
|
+
import { TextEditor } from '@herca/rn-kit';
|
|
32
|
+
|
|
33
|
+
export default function MyScreen() {
|
|
34
|
+
const handleChange = (html: string) => {
|
|
35
|
+
console.log('Content:', html);
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
return (
|
|
39
|
+
<TextEditor
|
|
40
|
+
label="Deskripsi"
|
|
41
|
+
placeholder="Tulis sesuatu di sini..."
|
|
42
|
+
onChange={handleChange}
|
|
43
|
+
maxLength={4000}
|
|
44
|
+
height={300}
|
|
45
|
+
/>
|
|
46
|
+
);
|
|
47
|
+
}
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
## Props
|
|
51
|
+
|
|
52
|
+
| Prop | Type | Default | Description |
|
|
53
|
+
| ------------------------- | ------------------------ | ---------------------------- | -------------------------------------------- |
|
|
54
|
+
| `label` | `string` | - | Label yang ditampilkan di atas editor |
|
|
55
|
+
| `height` | `number` | `300` | Tinggi editor dalam pixels |
|
|
56
|
+
| `initialValue` | `string` | `''` | Konten HTML awal |
|
|
57
|
+
| `placeholder` | `string` | `'Tulis sesuatu di sini...'` | Placeholder text |
|
|
58
|
+
| `maxLength` | `number` | - | Maksimal karakter (dihitung tanpa HTML tags) |
|
|
59
|
+
| `hasError` | `boolean` | - | Menampilkan state error |
|
|
60
|
+
| `hint` | `string` | - | Hint text di bawah editor |
|
|
61
|
+
| `onChange` | `(html: string) => void` | - | Callback saat konten berubah |
|
|
62
|
+
| `onFocus` | `() => void` | - | Callback saat editor focus |
|
|
63
|
+
| `onBlur` | `() => void` | - | Callback saat editor blur |
|
|
64
|
+
| `inputLabelLinkText` | `string` | `'Teks Link'` | Label untuk input teks link |
|
|
65
|
+
| `inputLabelLinkUrl` | `string` | `'Link URL'` | Label untuk input URL link |
|
|
66
|
+
| `inputLinkTextPlacholder` | `string` | `'Link URL'` | Placeholder untuk input teks link |
|
|
67
|
+
| `inputLinkUrlPlacholder` | `string` | `'https://www.example.com'` | Placeholder untuk input URL |
|
|
68
|
+
| `saveLinkButtonText` | `string` | `'Simpan'` | Text tombol simpan link |
|
|
69
|
+
| `cancelLinkButtonText` | `string` | `'Batal'` | Text tombol batal link |
|
|
70
|
+
|
|
71
|
+
## Advanced Usage
|
|
72
|
+
|
|
73
|
+
### Using Ref Methods
|
|
74
|
+
|
|
75
|
+
```tsx
|
|
76
|
+
import { useRef } from 'react';
|
|
77
|
+
import { TextEditor, TextEditorRef } from '@herca/rn-kit';
|
|
78
|
+
|
|
79
|
+
export default function MyScreen() {
|
|
80
|
+
const editorRef = useRef<TextEditorRef>(null);
|
|
81
|
+
|
|
82
|
+
const getContent = () => {
|
|
83
|
+
editorRef.current?.getContent();
|
|
84
|
+
};
|
|
85
|
+
|
|
86
|
+
const setContent = () => {
|
|
87
|
+
editorRef.current?.setContent('<p><strong>Bold text</strong></p>');
|
|
88
|
+
};
|
|
89
|
+
|
|
90
|
+
const clearContent = () => {
|
|
91
|
+
editorRef.current?.clearContent();
|
|
92
|
+
};
|
|
93
|
+
|
|
94
|
+
return (
|
|
95
|
+
<>
|
|
96
|
+
<TextEditor
|
|
97
|
+
ref={editorRef}
|
|
98
|
+
label="Deskripsi"
|
|
99
|
+
onChange={(html) => console.log(html)}
|
|
100
|
+
/>
|
|
101
|
+
|
|
102
|
+
<Button title="Get Content" onPress={getContent} />
|
|
103
|
+
<Button title="Set Content" onPress={setContent} />
|
|
104
|
+
<Button title="Clear" onPress={clearContent} />
|
|
105
|
+
</>
|
|
106
|
+
);
|
|
107
|
+
}
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
### With Initial Value
|
|
111
|
+
|
|
112
|
+
```tsx
|
|
113
|
+
<TextEditor
|
|
114
|
+
label="Edit Description"
|
|
115
|
+
initialValue="<p>Konten awal dengan <strong>bold</strong> dan <em>italic</em></p>"
|
|
116
|
+
onChange={handleChange}
|
|
117
|
+
/>
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
### With Max Length and Error State
|
|
121
|
+
|
|
122
|
+
```tsx
|
|
123
|
+
<TextEditor
|
|
124
|
+
label="Bio"
|
|
125
|
+
maxLength={500}
|
|
126
|
+
hasError={error}
|
|
127
|
+
hint={error ? 'Bio terlalu panjang' : 'Ceritakan tentang dirimu'}
|
|
128
|
+
onChange={handleChange}
|
|
129
|
+
/>
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
### Custom Link Labels
|
|
133
|
+
|
|
134
|
+
```tsx
|
|
135
|
+
<TextEditor
|
|
136
|
+
label="Content"
|
|
137
|
+
inputLabelLinkText="Display Text"
|
|
138
|
+
inputLabelLinkUrl="Web Address"
|
|
139
|
+
inputLinkTextPlacholder="Enter text to display"
|
|
140
|
+
inputLinkUrlPlacholder="https://example.com"
|
|
141
|
+
saveLinkButtonText="Insert Link"
|
|
142
|
+
cancelLinkButtonText="Cancel"
|
|
143
|
+
onChange={handleChange}
|
|
144
|
+
/>
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
## Toolbar Commands
|
|
148
|
+
|
|
149
|
+
Editor menyediakan toolbar dengan commands berikut:
|
|
150
|
+
|
|
151
|
+
- **Bold** - Membuat teks tebal
|
|
152
|
+
- **Italic** - Membuat teks miring
|
|
153
|
+
- **Underline** - Membuat garis bawah
|
|
154
|
+
- **Strikethrough** - Membuat teks tercoret
|
|
155
|
+
- **Link** - Insert atau edit hyperlink
|
|
156
|
+
- **Bullet List** - Membuat unordered list
|
|
157
|
+
- **Numbered List** - Membuat ordered list
|
|
158
|
+
- **Align Left** - Align teks ke kiri
|
|
159
|
+
- **Align Center** - Align teks ke tengah
|
|
160
|
+
- **Align Right** - Align teks ke kanan
|
|
161
|
+
|
|
162
|
+
## Ref Methods
|
|
163
|
+
|
|
164
|
+
### `getContent()`
|
|
165
|
+
|
|
166
|
+
Mendapatkan konten HTML dari editor.
|
|
167
|
+
|
|
168
|
+
```tsx
|
|
169
|
+
editorRef.current?.getContent();
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
### `setContent(html: string)`
|
|
173
|
+
|
|
174
|
+
Set konten HTML ke editor.
|
|
175
|
+
|
|
176
|
+
```tsx
|
|
177
|
+
editorRef.current?.setContent('<p>New content</p>');
|
|
178
|
+
```
|
|
179
|
+
|
|
180
|
+
### `clearContent()`
|
|
181
|
+
|
|
182
|
+
Menghapus semua konten dari editor.
|
|
183
|
+
|
|
184
|
+
```tsx
|
|
185
|
+
editorRef.current?.clearContent();
|
|
186
|
+
```
|
|
187
|
+
|
|
188
|
+
## Important Notes
|
|
189
|
+
|
|
190
|
+
### Height Prop
|
|
191
|
+
|
|
192
|
+
- ⚠️ **Disarankan Jangan** ubah prop `height` secara dinamis saat keyboard muncul/hilang
|
|
193
|
+
- Gunakan fixed height atau hitung sekali di awal component
|
|
194
|
+
- Mengubah height akan menyebabkan WebView reload dan keyboard hilang
|
|
195
|
+
|
|
196
|
+
### Character Count
|
|
197
|
+
|
|
198
|
+
- Character count dihitung dari plain text (tanpa HTML tags)
|
|
199
|
+
- Jika `maxLength` diset, user tidak bisa mengetik lebih dari limit tersebut
|
|
200
|
+
- Counter akan berubah warna merah saat melebihi `maxLength`
|
|
201
|
+
|
|
202
|
+
### Link Insertion
|
|
203
|
+
|
|
204
|
+
- User bisa select text kemudian klik tombol link untuk menambahkan hyperlink
|
|
205
|
+
- Jika tidak ada text yang diselect, link text akan sama dengan URL
|
|
206
|
+
- Protocol `https://` akan otomatis ditambahkan jika tidak ada
|
|
207
|
+
- User bisa edit existing link dengan cara klik link tersebut dan tekan tombol link di toolbar
|
|
208
|
+
|
|
209
|
+
## Styling
|
|
210
|
+
|
|
211
|
+
Component menggunakan styling internal yang sudah optimal. Jika perlu custom styling, wrap component dengan View:
|
|
212
|
+
|
|
213
|
+
```tsx
|
|
214
|
+
<View style={{ padding: 16, backgroundColor: '#f5f5f5' }}>
|
|
215
|
+
<TextEditor label="Content" />
|
|
216
|
+
</View>
|
|
217
|
+
```
|
|
218
|
+
|
|
219
|
+
## Platform-Specific Behavior
|
|
220
|
+
|
|
221
|
+
### iOS
|
|
222
|
+
|
|
223
|
+
- Menggunakan `KeyboardAvoidingView` dengan behavior `'padding'`
|
|
224
|
+
- Toolbar positioning disesuaikan dengan keyboard height
|
|
225
|
+
- `injectJavaScript` digunakan untuk commands
|
|
226
|
+
|
|
227
|
+
### Android
|
|
228
|
+
|
|
229
|
+
- `KeyboardAvoidingView` tanpa behavior khusus
|
|
230
|
+
- `postMessage` digunakan untuk commands
|
|
231
|
+
- Pastikan `android:windowSoftInputMode="adjustResize"` di AndroidManifest.xml
|
|
232
|
+
|
|
233
|
+
## Troubleshooting
|
|
234
|
+
|
|
235
|
+
### Keyboard Langsung Hilang
|
|
236
|
+
|
|
237
|
+
**Problem:** Keyboard hilang setelah muncul
|
|
238
|
+
|
|
239
|
+
**Solution:** Jangan ubah prop `height` secara dinamis. Gunakan fixed value.
|
|
240
|
+
|
|
241
|
+
### Content Tidak Ter-update
|
|
242
|
+
|
|
243
|
+
**Problem:** Perubahan konten tidak terdeteksi
|
|
244
|
+
|
|
245
|
+
**Solution:** Pastikan `onChange` callback di-implement dengan benar.
|
|
246
|
+
|
|
247
|
+
### Toolbar Tidak Muncul
|
|
248
|
+
|
|
249
|
+
**Problem:** Toolbar tidak tampil saat keyboard aktif
|
|
250
|
+
|
|
251
|
+
**Solution:** Pastikan component tidak di-wrap dengan View yang membatasi positioning absolute.
|
|
252
|
+
|
|
253
|
+
## Performance Tips
|
|
254
|
+
|
|
255
|
+
1. Gunakan `useCallback` untuk `onChange` handler jika parent component sering re-render
|
|
256
|
+
2. Jangan pass object atau array baru sebagai props setiap render
|
|
257
|
+
3. Untuk list besar, pertimbangkan lazy loading atau pagination
|
|
258
|
+
4. Batasi `maxLength` sesuai kebutuhan untuk performa optimal
|
|
259
|
+
|
|
260
|
+
## Dependencies
|
|
261
|
+
|
|
262
|
+
- `react-native-webview` - WebView component
|
|
263
|
+
- Internal components: `BottomSheet`, `Button`, `Icon`, `Input`, `LabelForm`, `Typography`
|