@umituz/react-native-design-system 2.6.88 → 2.6.89
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/package.json +1 -1
- package/src/molecules/FormField.README.md +424 -273
- package/src/molecules/List/README.md +568 -0
- package/src/molecules/StepProgress/README.md +522 -0
- package/src/molecules/emoji/README.md +580 -0
- package/src/molecules/splash/types/index.ts +5 -8
- package/src/molecules/swipe-actions/README.md +672 -0
- package/src/theme/core/colors/DarkColors.ts +0 -3
- package/src/theme/core/colors/LightColors.ts +0 -3
- package/src/theme/core/themes.ts +1 -8
- package/src/theme/infrastructure/providers/DesignSystemProvider.tsx +1 -1
|
@@ -0,0 +1,672 @@
|
|
|
1
|
+
# Swipe Actions
|
|
2
|
+
|
|
3
|
+
Swipe Actions system provides swipeable action buttons for list items. Users can swipe left or right to reveal quick actions like delete, edit, archive, etc.
|
|
4
|
+
|
|
5
|
+
## Features
|
|
6
|
+
|
|
7
|
+
- 👆 **Swipe Gestures**: Left and right swipe support
|
|
8
|
+
- 🎨 **Customizable Colors**: Theme-aware or custom colors
|
|
9
|
+
- 📳 **Haptic Feedback**: Built-in haptic feedback support
|
|
10
|
+
- 🎯 **Multiple Actions**: Support for multiple actions
|
|
11
|
+
- 🔄 **Animated**: Smooth swipe animations
|
|
12
|
+
- ♿ **Accessible**: Full accessibility support
|
|
13
|
+
- 🎭 **Icon & Label**: Visual icons and text labels
|
|
14
|
+
|
|
15
|
+
## Installation
|
|
16
|
+
|
|
17
|
+
```tsx
|
|
18
|
+
import { SwipeActionButton } from 'react-native-design-system';
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
## Basic Usage
|
|
22
|
+
|
|
23
|
+
```tsx
|
|
24
|
+
import React from 'react';
|
|
25
|
+
import { View } from 'react-native';
|
|
26
|
+
import { SwipeActionButton } from 'react-native-design-system';
|
|
27
|
+
|
|
28
|
+
export const BasicExample = () => {
|
|
29
|
+
const deleteAction = {
|
|
30
|
+
label: 'Delete',
|
|
31
|
+
icon: 'trash-outline',
|
|
32
|
+
color: '#ef4444',
|
|
33
|
+
onPress: () => console.log('Deleted'),
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
return (
|
|
37
|
+
<SwipeActionButton
|
|
38
|
+
action={deleteAction}
|
|
39
|
+
position={0}
|
|
40
|
+
totalActions={1}
|
|
41
|
+
direction="right"
|
|
42
|
+
/>
|
|
43
|
+
);
|
|
44
|
+
};
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
## Action Button
|
|
48
|
+
|
|
49
|
+
```tsx
|
|
50
|
+
const deleteAction = {
|
|
51
|
+
label: 'Delete',
|
|
52
|
+
icon: 'trash-outline',
|
|
53
|
+
color: '#ef4444',
|
|
54
|
+
onPress: () => handleDelete(),
|
|
55
|
+
};
|
|
56
|
+
|
|
57
|
+
<SwipeActionButton
|
|
58
|
+
action={deleteAction}
|
|
59
|
+
position={0}
|
|
60
|
+
totalActions={1}
|
|
61
|
+
direction="right"
|
|
62
|
+
/>
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
## Theme Color
|
|
66
|
+
|
|
67
|
+
```tsx
|
|
68
|
+
const editAction = {
|
|
69
|
+
label: 'Edit',
|
|
70
|
+
icon: 'create-outline',
|
|
71
|
+
colorKey: 'primary',
|
|
72
|
+
onPress: () => handleEdit(),
|
|
73
|
+
};
|
|
74
|
+
|
|
75
|
+
<SwipeActionButton
|
|
76
|
+
action={editAction}
|
|
77
|
+
position={0}
|
|
78
|
+
totalActions={1}
|
|
79
|
+
direction="left"
|
|
80
|
+
/>
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
## With Haptics
|
|
84
|
+
|
|
85
|
+
```tsx
|
|
86
|
+
const archiveAction = {
|
|
87
|
+
label: 'Archive',
|
|
88
|
+
icon: 'archive-outline',
|
|
89
|
+
colorKey: 'tertiary',
|
|
90
|
+
enableHaptics: true,
|
|
91
|
+
hapticsIntensity: 'Medium',
|
|
92
|
+
onPress: () => handleArchive(),
|
|
93
|
+
};
|
|
94
|
+
|
|
95
|
+
<SwipeActionButton
|
|
96
|
+
action={archiveAction}
|
|
97
|
+
position={0}
|
|
98
|
+
totalActions={1}
|
|
99
|
+
direction="right"
|
|
100
|
+
/>
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
## Example Usages
|
|
104
|
+
|
|
105
|
+
### Email Actions
|
|
106
|
+
|
|
107
|
+
```tsx
|
|
108
|
+
export const EmailSwipeActions = ({ emailId }) => {
|
|
109
|
+
const handleDelete = async () => {
|
|
110
|
+
await deleteEmail(emailId);
|
|
111
|
+
};
|
|
112
|
+
|
|
113
|
+
const handleArchive = async () => {
|
|
114
|
+
await archiveEmail(emailId);
|
|
115
|
+
};
|
|
116
|
+
|
|
117
|
+
const handleMarkRead = async () => {
|
|
118
|
+
await markAsRead(emailId);
|
|
119
|
+
};
|
|
120
|
+
|
|
121
|
+
return (
|
|
122
|
+
<>
|
|
123
|
+
{/* Right swipe actions */}
|
|
124
|
+
<SwipeActionButton
|
|
125
|
+
action={{
|
|
126
|
+
label: 'Archive',
|
|
127
|
+
icon: 'archive-outline',
|
|
128
|
+
colorKey: 'primary',
|
|
129
|
+
onPress: handleArchive,
|
|
130
|
+
}}
|
|
131
|
+
position={0}
|
|
132
|
+
totalActions={2}
|
|
133
|
+
direction="right"
|
|
134
|
+
/>
|
|
135
|
+
|
|
136
|
+
<SwipeActionButton
|
|
137
|
+
action={{
|
|
138
|
+
label: 'Delete',
|
|
139
|
+
icon: 'trash-outline',
|
|
140
|
+
colorKey: 'error',
|
|
141
|
+
onPress: handleDelete,
|
|
142
|
+
}}
|
|
143
|
+
position={1}
|
|
144
|
+
totalActions={2}
|
|
145
|
+
direction="right"
|
|
146
|
+
/>
|
|
147
|
+
</>
|
|
148
|
+
);
|
|
149
|
+
};
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
### Task Actions
|
|
153
|
+
|
|
154
|
+
```tsx
|
|
155
|
+
export const TaskSwipeActions = ({ taskId }) => {
|
|
156
|
+
const handleComplete = async () => {
|
|
157
|
+
await completeTask(taskId);
|
|
158
|
+
showSuccessToast('Task completed!');
|
|
159
|
+
};
|
|
160
|
+
|
|
161
|
+
const handleSnooze = async () => {
|
|
162
|
+
await snoozeTask(taskId);
|
|
163
|
+
};
|
|
164
|
+
|
|
165
|
+
return (
|
|
166
|
+
<>
|
|
167
|
+
<SwipeActionButton
|
|
168
|
+
action={{
|
|
169
|
+
label: 'Complete',
|
|
170
|
+
icon: 'checkmark-circle-outline',
|
|
171
|
+
colorKey: 'success',
|
|
172
|
+
enableHaptics: true,
|
|
173
|
+
hapticsIntensity: 'Heavy',
|
|
174
|
+
onPress: handleComplete,
|
|
175
|
+
}}
|
|
176
|
+
position={0}
|
|
177
|
+
totalActions={1}
|
|
178
|
+
direction="right"
|
|
179
|
+
/>
|
|
180
|
+
|
|
181
|
+
<SwipeActionButton
|
|
182
|
+
action={{
|
|
183
|
+
label: 'Snooze',
|
|
184
|
+
icon: 'time-outline',
|
|
185
|
+
colorKey: 'warning',
|
|
186
|
+
onPress: handleSnooze,
|
|
187
|
+
}}
|
|
188
|
+
position={0}
|
|
189
|
+
totalActions={1}
|
|
190
|
+
direction="left"
|
|
191
|
+
/>
|
|
192
|
+
</>
|
|
193
|
+
);
|
|
194
|
+
};
|
|
195
|
+
```
|
|
196
|
+
|
|
197
|
+
### Message Actions
|
|
198
|
+
|
|
199
|
+
```tsx
|
|
200
|
+
export const MessageSwipeActions = ({ message }) => {
|
|
201
|
+
const handleReply = () => {
|
|
202
|
+
navigation.navigate('Reply', { messageId: message.id });
|
|
203
|
+
};
|
|
204
|
+
|
|
205
|
+
const handleForward = () => {
|
|
206
|
+
navigation.navigate('Forward', { messageId: message.id });
|
|
207
|
+
};
|
|
208
|
+
|
|
209
|
+
const handleDelete = async () => {
|
|
210
|
+
showAlert({
|
|
211
|
+
variant: 'error',
|
|
212
|
+
title: 'Delete Message',
|
|
213
|
+
message: 'Are you sure you want to delete this message?',
|
|
214
|
+
onConfirm: async () => {
|
|
215
|
+
await deleteMessage(message.id);
|
|
216
|
+
},
|
|
217
|
+
});
|
|
218
|
+
};
|
|
219
|
+
|
|
220
|
+
return (
|
|
221
|
+
<>
|
|
222
|
+
<SwipeActionButton
|
|
223
|
+
action={{
|
|
224
|
+
label: 'Reply',
|
|
225
|
+
icon: 'arrow-undo-outline',
|
|
226
|
+
colorKey: 'primary',
|
|
227
|
+
onPress: handleReply,
|
|
228
|
+
}}
|
|
229
|
+
position={0}
|
|
230
|
+
totalActions={2}
|
|
231
|
+
direction="left"
|
|
232
|
+
/>
|
|
233
|
+
|
|
234
|
+
<SwipeActionButton
|
|
235
|
+
action={{
|
|
236
|
+
label: 'Forward',
|
|
237
|
+
icon: 'arrow-redo-outline',
|
|
238
|
+
colorKey: 'primary',
|
|
239
|
+
onPress: handleForward,
|
|
240
|
+
}}
|
|
241
|
+
position={1}
|
|
242
|
+
totalActions={2}
|
|
243
|
+
direction="left"
|
|
244
|
+
/>
|
|
245
|
+
|
|
246
|
+
<SwipeActionButton
|
|
247
|
+
action={{
|
|
248
|
+
label: 'Delete',
|
|
249
|
+
icon: 'trash-outline',
|
|
250
|
+
colorKey: 'error',
|
|
251
|
+
onPress: handleDelete,
|
|
252
|
+
}}
|
|
253
|
+
position={0}
|
|
254
|
+
totalActions={1}
|
|
255
|
+
direction="right"
|
|
256
|
+
/>
|
|
257
|
+
</>
|
|
258
|
+
);
|
|
259
|
+
};
|
|
260
|
+
```
|
|
261
|
+
|
|
262
|
+
### Contact Actions
|
|
263
|
+
|
|
264
|
+
```tsx
|
|
265
|
+
export const ContactSwipeActions = ({ contact }) => {
|
|
266
|
+
const handleCall = () => {
|
|
267
|
+
Linking.openURL(`tel:${contact.phone}`);
|
|
268
|
+
};
|
|
269
|
+
|
|
270
|
+
const handleMessage = () => {
|
|
271
|
+
navigation.navigate('Message', { contactId: contact.id });
|
|
272
|
+
};
|
|
273
|
+
|
|
274
|
+
const handleFavorite = async () => {
|
|
275
|
+
await toggleFavorite(contact.id);
|
|
276
|
+
showToast({
|
|
277
|
+
variant: 'success',
|
|
278
|
+
title: contact.isFavorite ? 'Removed from Favorites' : 'Added to Favorites',
|
|
279
|
+
});
|
|
280
|
+
};
|
|
281
|
+
|
|
282
|
+
return (
|
|
283
|
+
<>
|
|
284
|
+
<SwipeActionButton
|
|
285
|
+
action={{
|
|
286
|
+
label: 'Call',
|
|
287
|
+
icon: 'call-outline',
|
|
288
|
+
colorKey: 'success',
|
|
289
|
+
onPress: handleCall,
|
|
290
|
+
}}
|
|
291
|
+
position={0}
|
|
292
|
+
totalActions={2}
|
|
293
|
+
direction="left"
|
|
294
|
+
/>
|
|
295
|
+
|
|
296
|
+
<SwipeActionButton
|
|
297
|
+
action={{
|
|
298
|
+
label: 'Message',
|
|
299
|
+
icon: 'chatbubble-outline',
|
|
300
|
+
colorKey: 'primary',
|
|
301
|
+
onPress: handleMessage,
|
|
302
|
+
}}
|
|
303
|
+
position={1}
|
|
304
|
+
totalActions={2}
|
|
305
|
+
direction="left"
|
|
306
|
+
/>
|
|
307
|
+
|
|
308
|
+
<SwipeActionButton
|
|
309
|
+
action={{
|
|
310
|
+
label: contact.isFavorite ? 'Unfavorite' : 'Favorite',
|
|
311
|
+
icon: contact.isFavorite ? 'heart' : 'heart-outline',
|
|
312
|
+
colorKey: contact.isFavorite ? 'error' : 'error',
|
|
313
|
+
onPress: handleFavorite,
|
|
314
|
+
}}
|
|
315
|
+
position={0}
|
|
316
|
+
totalActions={1}
|
|
317
|
+
direction="right"
|
|
318
|
+
/>
|
|
319
|
+
</>
|
|
320
|
+
);
|
|
321
|
+
};
|
|
322
|
+
```
|
|
323
|
+
|
|
324
|
+
### File Actions
|
|
325
|
+
|
|
326
|
+
```tsx
|
|
327
|
+
export const FileSwipeActions = ({ file }) => {
|
|
328
|
+
const handleShare = async () => {
|
|
329
|
+
await shareFile(file.uri);
|
|
330
|
+
};
|
|
331
|
+
|
|
332
|
+
const handleRename = () => {
|
|
333
|
+
navigation.navigate('RenameFile', { fileId: file.id });
|
|
334
|
+
};
|
|
335
|
+
|
|
336
|
+
const handleDelete = async () => {
|
|
337
|
+
showAlert({
|
|
338
|
+
variant: 'error',
|
|
339
|
+
title: 'Delete File',
|
|
340
|
+
message: `Are you sure you want to delete ${file.name}?`,
|
|
341
|
+
onConfirm: async () => {
|
|
342
|
+
await deleteFile(file.id);
|
|
343
|
+
},
|
|
344
|
+
});
|
|
345
|
+
};
|
|
346
|
+
|
|
347
|
+
return (
|
|
348
|
+
<>
|
|
349
|
+
<SwipeActionButton
|
|
350
|
+
action={{
|
|
351
|
+
label: 'Share',
|
|
352
|
+
icon: 'share-outline',
|
|
353
|
+
colorKey: 'primary',
|
|
354
|
+
onPress: handleShare,
|
|
355
|
+
}}
|
|
356
|
+
position={0}
|
|
357
|
+
totalActions={2}
|
|
358
|
+
direction="left"
|
|
359
|
+
/>
|
|
360
|
+
|
|
361
|
+
<SwipeActionButton
|
|
362
|
+
action={{
|
|
363
|
+
label: 'Rename',
|
|
364
|
+
icon: 'create-outline',
|
|
365
|
+
colorKey: 'tertiary',
|
|
366
|
+
onPress: handleRename,
|
|
367
|
+
}}
|
|
368
|
+
position={1}
|
|
369
|
+
totalActions={2}
|
|
370
|
+
direction="left"
|
|
371
|
+
/>
|
|
372
|
+
|
|
373
|
+
<SwipeActionButton
|
|
374
|
+
action={{
|
|
375
|
+
label: 'Delete',
|
|
376
|
+
icon: 'trash-outline',
|
|
377
|
+
colorKey: 'error',
|
|
378
|
+
onPress: handleDelete,
|
|
379
|
+
}}
|
|
380
|
+
position={0}
|
|
381
|
+
totalActions={1}
|
|
382
|
+
direction="right"
|
|
383
|
+
/>
|
|
384
|
+
</>
|
|
385
|
+
);
|
|
386
|
+
};
|
|
387
|
+
```
|
|
388
|
+
|
|
389
|
+
### Notification Actions
|
|
390
|
+
|
|
391
|
+
```tsx
|
|
392
|
+
export const NotificationSwipeActions = ({ notification }) => {
|
|
393
|
+
const handleMarkRead = async () => {
|
|
394
|
+
await markAsRead(notification.id);
|
|
395
|
+
};
|
|
396
|
+
|
|
397
|
+
const handleMute = async () => {
|
|
398
|
+
await muteNotification(notification.id);
|
|
399
|
+
showToast({
|
|
400
|
+
variant: 'info',
|
|
401
|
+
title: 'Notification muted',
|
|
402
|
+
});
|
|
403
|
+
};
|
|
404
|
+
|
|
405
|
+
const handleDelete = async () => {
|
|
406
|
+
await deleteNotification(notification.id);
|
|
407
|
+
};
|
|
408
|
+
|
|
409
|
+
return (
|
|
410
|
+
<>
|
|
411
|
+
<SwipeActionButton
|
|
412
|
+
action={{
|
|
413
|
+
label: 'Mark Read',
|
|
414
|
+
icon: 'checkmark-done-outline',
|
|
415
|
+
colorKey: 'success',
|
|
416
|
+
onPress: handleMarkRead,
|
|
417
|
+
}}
|
|
418
|
+
position={0}
|
|
419
|
+
totalActions={2}
|
|
420
|
+
direction="left"
|
|
421
|
+
/>
|
|
422
|
+
|
|
423
|
+
<SwipeActionButton
|
|
424
|
+
action={{
|
|
425
|
+
label: 'Mute',
|
|
426
|
+
icon: 'volume-mute-outline',
|
|
427
|
+
colorKey: 'warning',
|
|
428
|
+
onPress: handleMute,
|
|
429
|
+
}}
|
|
430
|
+
position={1}
|
|
431
|
+
totalActions={2}
|
|
432
|
+
direction="left"
|
|
433
|
+
/>
|
|
434
|
+
|
|
435
|
+
<SwipeActionButton
|
|
436
|
+
action={{
|
|
437
|
+
label: 'Delete',
|
|
438
|
+
icon: 'trash-outline',
|
|
439
|
+
colorKey: 'error',
|
|
440
|
+
onPress: handleDelete,
|
|
441
|
+
}}
|
|
442
|
+
position={0}
|
|
443
|
+
totalActions={1}
|
|
444
|
+
direction="right"
|
|
445
|
+
/>
|
|
446
|
+
</>
|
|
447
|
+
);
|
|
448
|
+
};
|
|
449
|
+
```
|
|
450
|
+
|
|
451
|
+
### Cart Item Actions
|
|
452
|
+
|
|
453
|
+
```tsx
|
|
454
|
+
export const CartItemSwipeActions = ({ item }) => {
|
|
455
|
+
const handleMoveToWishlist = async () => {
|
|
456
|
+
await moveToWishlist(item.id);
|
|
457
|
+
showToast({
|
|
458
|
+
variant: 'success',
|
|
459
|
+
title: 'Moved to wishlist',
|
|
460
|
+
});
|
|
461
|
+
};
|
|
462
|
+
|
|
463
|
+
const handleRemove = async () => {
|
|
464
|
+
showAlert({
|
|
465
|
+
variant: 'warning',
|
|
466
|
+
title: 'Remove Item',
|
|
467
|
+
message: 'Remove this item from your cart?',
|
|
468
|
+
onConfirm: async () => {
|
|
469
|
+
await removeFromCart(item.id);
|
|
470
|
+
},
|
|
471
|
+
});
|
|
472
|
+
};
|
|
473
|
+
|
|
474
|
+
return (
|
|
475
|
+
<>
|
|
476
|
+
<SwipeActionButton
|
|
477
|
+
action={{
|
|
478
|
+
label: 'Wishlist',
|
|
479
|
+
icon: 'heart-outline',
|
|
480
|
+
colorKey: 'error',
|
|
481
|
+
onPress: handleMoveToWishlist,
|
|
482
|
+
}}
|
|
483
|
+
position={0}
|
|
484
|
+
totalActions={1}
|
|
485
|
+
direction="left"
|
|
486
|
+
/>
|
|
487
|
+
|
|
488
|
+
<SwipeActionButton
|
|
489
|
+
action={{
|
|
490
|
+
label: 'Remove',
|
|
491
|
+
icon: 'trash-outline',
|
|
492
|
+
colorKey: 'error',
|
|
493
|
+
onPress: handleRemove,
|
|
494
|
+
}}
|
|
495
|
+
position={0}
|
|
496
|
+
totalActions={1}
|
|
497
|
+
direction="right"
|
|
498
|
+
/>
|
|
499
|
+
</>
|
|
500
|
+
);
|
|
501
|
+
};
|
|
502
|
+
```
|
|
503
|
+
|
|
504
|
+
### Order Actions
|
|
505
|
+
|
|
506
|
+
```tsx
|
|
507
|
+
export const OrderSwipeActions = ({ order }) => {
|
|
508
|
+
const handleTrack = () => {
|
|
509
|
+
navigation.navigate('OrderTracking', { orderId: order.id });
|
|
510
|
+
};
|
|
511
|
+
|
|
512
|
+
const handleReorder = async () => {
|
|
513
|
+
await reorderItems(order.items);
|
|
514
|
+
showToast({
|
|
515
|
+
variant: 'success',
|
|
516
|
+
title: 'Items added to cart',
|
|
517
|
+
});
|
|
518
|
+
};
|
|
519
|
+
|
|
520
|
+
const handleCancel = async () => {
|
|
521
|
+
if (order.canCancel) {
|
|
522
|
+
showAlert({
|
|
523
|
+
variant: 'error',
|
|
524
|
+
title: 'Cancel Order',
|
|
525
|
+
message: 'Are you sure you want to cancel this order?',
|
|
526
|
+
onConfirm: async () => {
|
|
527
|
+
await cancelOrder(order.id);
|
|
528
|
+
},
|
|
529
|
+
});
|
|
530
|
+
}
|
|
531
|
+
};
|
|
532
|
+
|
|
533
|
+
return (
|
|
534
|
+
<>
|
|
535
|
+
<SwipeActionButton
|
|
536
|
+
action={{
|
|
537
|
+
label: 'Track',
|
|
538
|
+
icon: 'locate-outline',
|
|
539
|
+
colorKey: 'primary',
|
|
540
|
+
onPress: handleTrack,
|
|
541
|
+
}}
|
|
542
|
+
position={0}
|
|
543
|
+
totalActions={2}
|
|
544
|
+
direction="left"
|
|
545
|
+
/>
|
|
546
|
+
|
|
547
|
+
{order.canReorder && (
|
|
548
|
+
<SwipeActionButton
|
|
549
|
+
action={{
|
|
550
|
+
label: 'Reorder',
|
|
551
|
+
icon: 'refresh-outline',
|
|
552
|
+
colorKey: 'success',
|
|
553
|
+
onPress: handleReorder,
|
|
554
|
+
}}
|
|
555
|
+
position={1}
|
|
556
|
+
totalActions={2}
|
|
557
|
+
direction="left"
|
|
558
|
+
/>
|
|
559
|
+
)}
|
|
560
|
+
|
|
561
|
+
{order.canCancel && (
|
|
562
|
+
<SwipeActionButton
|
|
563
|
+
action={{
|
|
564
|
+
label: 'Cancel',
|
|
565
|
+
icon: 'close-circle-outline',
|
|
566
|
+
colorKey: 'error',
|
|
567
|
+
onPress: handleCancel,
|
|
568
|
+
}}
|
|
569
|
+
position={0}
|
|
570
|
+
totalActions={1}
|
|
571
|
+
direction="right"
|
|
572
|
+
/>
|
|
573
|
+
)}
|
|
574
|
+
</>
|
|
575
|
+
);
|
|
576
|
+
};
|
|
577
|
+
```
|
|
578
|
+
|
|
579
|
+
## Props
|
|
580
|
+
|
|
581
|
+
### SwipeActionButtonProps
|
|
582
|
+
|
|
583
|
+
| Prop | Type | Default | Description |
|
|
584
|
+
|------|------|---------|-------------|
|
|
585
|
+
| `action` | `SwipeActionConfig` | - **(Required)** | Action configuration |
|
|
586
|
+
| `position` | `number` | - **(Required)** | Button position index |
|
|
587
|
+
| `totalActions` | `number` | - **(Required)** | Total number of actions |
|
|
588
|
+
| `direction` | `'left' \| 'right'` | - **(Required)** | Swipe direction |
|
|
589
|
+
| `style` | `ViewStyle` | - | Custom container style |
|
|
590
|
+
|
|
591
|
+
### SwipeActionConfig
|
|
592
|
+
|
|
593
|
+
| Prop | Type | Default | Description |
|
|
594
|
+
|------|------|---------|-------------|
|
|
595
|
+
| `label` | `string` | - **(Required)** | Button label |
|
|
596
|
+
| `icon` | `string` | - **(Required)** | Icon name (Ionicons) |
|
|
597
|
+
| `onPress` | `() => void` | - **(Required)** | Press callback |
|
|
598
|
+
| `color` | `string` | - | Custom color |
|
|
599
|
+
| `colorKey` | `string` | - | Theme color key |
|
|
600
|
+
| `enableHaptics` | `boolean` | `true` | Enable haptic feedback |
|
|
601
|
+
| `hapticsIntensity` | `'Light' \| 'Medium' \| 'Heavy'` | `'Medium'` | Haptic intensity |
|
|
602
|
+
|
|
603
|
+
## Best Practices
|
|
604
|
+
|
|
605
|
+
### 1. Action Placement
|
|
606
|
+
|
|
607
|
+
```tsx
|
|
608
|
+
// Destructive actions on right swipe
|
|
609
|
+
<SwipeActionButton
|
|
610
|
+
action={{ label: 'Delete', icon: 'trash' }}
|
|
611
|
+
direction="right" // ✅
|
|
612
|
+
/>
|
|
613
|
+
|
|
614
|
+
// Common actions on left swipe
|
|
615
|
+
<SwipeActionButton
|
|
616
|
+
action={{ label: 'Edit', icon: 'create' }}
|
|
617
|
+
direction="left" // ✅
|
|
618
|
+
/>
|
|
619
|
+
```
|
|
620
|
+
|
|
621
|
+
### 2. Haptic Feedback
|
|
622
|
+
|
|
623
|
+
```tsx
|
|
624
|
+
// Important actions: Heavy haptics
|
|
625
|
+
action={{
|
|
626
|
+
hapticsIntensity: 'Heavy',
|
|
627
|
+
}}
|
|
628
|
+
|
|
629
|
+
// Secondary actions: Medium haptics
|
|
630
|
+
action={{
|
|
631
|
+
hapticsIntensity: 'Medium',
|
|
632
|
+
}}
|
|
633
|
+
```
|
|
634
|
+
|
|
635
|
+
### 3. Clear Labels
|
|
636
|
+
|
|
637
|
+
```tsx
|
|
638
|
+
// ✅ Good: Clear action
|
|
639
|
+
label: 'Delete'
|
|
640
|
+
|
|
641
|
+
// ❌ Bad: Vague
|
|
642
|
+
label: 'OK'
|
|
643
|
+
```
|
|
644
|
+
|
|
645
|
+
## Accessibility
|
|
646
|
+
|
|
647
|
+
SwipeActionButton provides full accessibility support:
|
|
648
|
+
|
|
649
|
+
- ✅ Screen reader support
|
|
650
|
+
- ✅ Accessibility labels
|
|
651
|
+
- ✅ Touch target size
|
|
652
|
+
- ✅ Semantic actions
|
|
653
|
+
|
|
654
|
+
## Performance Tips
|
|
655
|
+
|
|
656
|
+
1. **Memoization**: Memo action callbacks
|
|
657
|
+
2. **Optimize**: Minimize re-renders
|
|
658
|
+
3. **Debounce**: Debounce rapid actions
|
|
659
|
+
|
|
660
|
+
## Related Components
|
|
661
|
+
|
|
662
|
+
- [`ListItem`](../listitem/README.md) - List item component
|
|
663
|
+
- [`BaseModal`](../BaseModal/README.md) - Modal component
|
|
664
|
+
- [`AlertInline`](../alerts/README.md) - Alert components
|
|
665
|
+
|
|
666
|
+
## Dependencies
|
|
667
|
+
|
|
668
|
+
- `@umituz/react-native-haptics` - Haptic feedback service
|
|
669
|
+
|
|
670
|
+
## License
|
|
671
|
+
|
|
672
|
+
MIT
|
package/src/theme/core/themes.ts
CHANGED
|
@@ -8,19 +8,12 @@ import { BASE_TOKENS } from './BaseTokens';
|
|
|
8
8
|
import { lightColors, darkColors } from './ColorPalette';
|
|
9
9
|
import type { ColorPalette } from './ColorPalette';
|
|
10
10
|
|
|
11
|
-
/**
|
|
12
|
-
* Extended color palette for theme customization
|
|
13
|
-
*/
|
|
14
|
-
export interface ExtendedColorPalette extends ColorPalette {
|
|
15
|
-
customGradients?: Record<string, [string, string]>;
|
|
16
|
-
}
|
|
17
|
-
|
|
18
11
|
/**
|
|
19
12
|
* Complete Theme Object
|
|
20
13
|
* Combines colors, spacing, typography, borders, and design tokens
|
|
21
14
|
*/
|
|
22
15
|
export interface Theme {
|
|
23
|
-
colors:
|
|
16
|
+
colors: ColorPalette;
|
|
24
17
|
spacing: typeof BASE_TOKENS.spacing;
|
|
25
18
|
typography: typeof BASE_TOKENS.typography;
|
|
26
19
|
borders: typeof BASE_TOKENS.borders;
|
|
@@ -22,7 +22,7 @@ interface DesignSystemProviderProps {
|
|
|
22
22
|
/** Show loading indicator while initializing (default: true) */
|
|
23
23
|
showLoadingIndicator?: boolean;
|
|
24
24
|
/** Splash screen configuration (used when showLoadingIndicator is true) */
|
|
25
|
-
splashConfig?: Pick<SplashScreenProps, 'appName' | 'tagline' | 'icon' | 'colors'
|
|
25
|
+
splashConfig?: Pick<SplashScreenProps, 'appName' | 'tagline' | 'icon' | 'colors'>;
|
|
26
26
|
/** Custom loading component (overrides splash screen) */
|
|
27
27
|
loadingComponent?: ReactNode;
|
|
28
28
|
/** Callback when initialization completes */
|