rnnovaui 0.1.6 → 0.2.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.
package/package.json
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import React, { memo, useCallback } from "react";
|
|
1
|
+
import React, { memo, useCallback, useMemo } from "react";
|
|
2
2
|
|
|
3
3
|
import {
|
|
4
4
|
ActivityIndicator,
|
|
@@ -10,7 +10,7 @@ import {
|
|
|
10
10
|
|
|
11
11
|
import { useUITheme } from "../../theme";
|
|
12
12
|
|
|
13
|
-
const
|
|
13
|
+
const VARIANTS = {
|
|
14
14
|
solid: "solid",
|
|
15
15
|
outline: "outline",
|
|
16
16
|
ghost: "ghost",
|
|
@@ -19,171 +19,224 @@ const BUTTON_VARIANTS = {
|
|
|
19
19
|
success: "success",
|
|
20
20
|
};
|
|
21
21
|
|
|
22
|
-
const
|
|
22
|
+
const SIZES = {
|
|
23
23
|
sm: "sm",
|
|
24
24
|
md: "md",
|
|
25
25
|
lg: "lg",
|
|
26
26
|
xl: "xl",
|
|
27
27
|
};
|
|
28
28
|
|
|
29
|
-
const
|
|
30
|
-
|
|
29
|
+
const FALLBACK = {
|
|
30
|
+
primary: "#FF5A1F",
|
|
31
|
+
primaryPressed: "#E94D17",
|
|
32
|
+
primarySoft: "#FFF0EA",
|
|
31
33
|
|
|
32
|
-
|
|
34
|
+
success: "#16A34A",
|
|
35
|
+
successPressed: "#128238",
|
|
33
36
|
|
|
34
|
-
|
|
37
|
+
danger: "#DC2626",
|
|
38
|
+
dangerPressed: "#B91C1C",
|
|
35
39
|
|
|
36
|
-
|
|
40
|
+
white: "#FFFFFF",
|
|
37
41
|
|
|
38
|
-
|
|
42
|
+
disabledBackground: "#E5E5E5",
|
|
43
|
+
disabledText: "#A3A3A3",
|
|
44
|
+
};
|
|
39
45
|
|
|
40
|
-
|
|
46
|
+
function UIButton({
|
|
47
|
+
title,
|
|
48
|
+
children,
|
|
41
49
|
|
|
42
|
-
|
|
50
|
+
variant = "solid",
|
|
51
|
+
size = "md",
|
|
43
52
|
|
|
44
|
-
|
|
53
|
+
disabled = false,
|
|
54
|
+
loading = false,
|
|
45
55
|
|
|
46
|
-
|
|
56
|
+
fullWidth = false,
|
|
47
57
|
|
|
48
|
-
|
|
58
|
+
leftIcon,
|
|
59
|
+
rightIcon,
|
|
49
60
|
|
|
50
|
-
|
|
61
|
+
onPress,
|
|
62
|
+
onLongPress,
|
|
51
63
|
|
|
52
|
-
|
|
64
|
+
style,
|
|
65
|
+
contentStyle,
|
|
66
|
+
textStyle,
|
|
53
67
|
|
|
54
|
-
|
|
68
|
+
testID,
|
|
55
69
|
|
|
56
|
-
|
|
70
|
+
...props
|
|
71
|
+
}) {
|
|
72
|
+
const { theme } = useUITheme();
|
|
57
73
|
|
|
58
|
-
|
|
74
|
+
const colors = theme?.colors || {};
|
|
59
75
|
|
|
60
|
-
|
|
76
|
+
const primary = colors.primary || FALLBACK.primary;
|
|
61
77
|
|
|
62
|
-
|
|
78
|
+
const primaryPressed = colors.primaryPressed || FALLBACK.primaryPressed;
|
|
63
79
|
|
|
64
|
-
|
|
80
|
+
const primarySoft = colors.primarySoft || FALLBACK.primarySoft;
|
|
65
81
|
|
|
66
|
-
|
|
82
|
+
const success = colors.success || FALLBACK.success;
|
|
67
83
|
|
|
68
|
-
|
|
69
|
-
};
|
|
84
|
+
const successPressed = colors.successPressed || FALLBACK.successPressed;
|
|
70
85
|
|
|
71
|
-
const
|
|
72
|
-
title,
|
|
86
|
+
const danger = colors.danger || FALLBACK.danger;
|
|
73
87
|
|
|
74
|
-
|
|
88
|
+
const dangerPressed = colors.dangerPressed || FALLBACK.dangerPressed;
|
|
75
89
|
|
|
76
|
-
|
|
90
|
+
const white = colors.onPrimary || FALLBACK.white;
|
|
77
91
|
|
|
78
|
-
|
|
92
|
+
const isDisabled = disabled || loading;
|
|
79
93
|
|
|
80
|
-
|
|
94
|
+
const buttonColors = useMemo(() => {
|
|
95
|
+
if (isDisabled) {
|
|
96
|
+
return {
|
|
97
|
+
background:
|
|
98
|
+
colors.buttonDisabledBackground || FALLBACK.disabledBackground,
|
|
81
99
|
|
|
82
|
-
|
|
100
|
+
border: colors.buttonDisabledBorder || FALLBACK.disabledBackground,
|
|
83
101
|
|
|
84
|
-
|
|
102
|
+
text: colors.buttonDisabledText || FALLBACK.disabledText,
|
|
85
103
|
|
|
86
|
-
|
|
104
|
+
borderWidth: 1,
|
|
105
|
+
};
|
|
106
|
+
}
|
|
87
107
|
|
|
88
|
-
|
|
108
|
+
switch (variant) {
|
|
109
|
+
case "outline":
|
|
110
|
+
return {
|
|
111
|
+
background: "transparent",
|
|
89
112
|
|
|
90
|
-
|
|
113
|
+
border: colors.buttonOutlineBorder || primary,
|
|
91
114
|
|
|
92
|
-
|
|
115
|
+
text: colors.buttonOutlineText || primary,
|
|
93
116
|
|
|
94
|
-
|
|
117
|
+
borderWidth: 1,
|
|
118
|
+
};
|
|
95
119
|
|
|
96
|
-
|
|
120
|
+
case "ghost":
|
|
121
|
+
return {
|
|
122
|
+
background: "transparent",
|
|
97
123
|
|
|
98
|
-
|
|
124
|
+
border: "transparent",
|
|
99
125
|
|
|
100
|
-
|
|
126
|
+
text: colors.buttonGhostText || primary,
|
|
101
127
|
|
|
102
|
-
|
|
128
|
+
borderWidth: 0,
|
|
129
|
+
};
|
|
103
130
|
|
|
104
|
-
|
|
131
|
+
case "soft":
|
|
132
|
+
return {
|
|
133
|
+
background: colors.buttonSoftBackground || primarySoft,
|
|
105
134
|
|
|
106
|
-
|
|
135
|
+
border: colors.buttonSoftBackground || primarySoft,
|
|
107
136
|
|
|
108
|
-
|
|
137
|
+
text: colors.buttonSoftText || primary,
|
|
109
138
|
|
|
110
|
-
|
|
139
|
+
borderWidth: 1,
|
|
140
|
+
};
|
|
111
141
|
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
142
|
+
case "danger":
|
|
143
|
+
return {
|
|
144
|
+
background: colors.buttonDangerBackground || danger,
|
|
115
145
|
|
|
116
|
-
|
|
117
|
-
...DEFAULT_COLORS,
|
|
118
|
-
...(theme?.colors || {}),
|
|
119
|
-
};
|
|
146
|
+
border: colors.buttonDangerBackground || danger,
|
|
120
147
|
|
|
121
|
-
|
|
122
|
-
? variant
|
|
123
|
-
: BUTTON_VARIANTS.solid;
|
|
148
|
+
text: colors.buttonDangerText || white,
|
|
124
149
|
|
|
125
|
-
|
|
150
|
+
borderWidth: 1,
|
|
151
|
+
};
|
|
126
152
|
|
|
127
|
-
|
|
153
|
+
case "success":
|
|
154
|
+
return {
|
|
155
|
+
background: colors.buttonSuccessBackground || success,
|
|
128
156
|
|
|
129
|
-
|
|
157
|
+
border: colors.buttonSuccessBackground || success,
|
|
130
158
|
|
|
131
|
-
|
|
159
|
+
text: colors.buttonSuccessText || white,
|
|
132
160
|
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
if (isDisabled) {
|
|
136
|
-
return;
|
|
137
|
-
}
|
|
161
|
+
borderWidth: 1,
|
|
162
|
+
};
|
|
138
163
|
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
[isDisabled, onPress],
|
|
144
|
-
);
|
|
164
|
+
case "solid":
|
|
165
|
+
default:
|
|
166
|
+
return {
|
|
167
|
+
background: colors.buttonPrimaryBackground || primary,
|
|
145
168
|
|
|
146
|
-
|
|
147
|
-
(event) => {
|
|
148
|
-
if (isDisabled) {
|
|
149
|
-
return;
|
|
150
|
-
}
|
|
169
|
+
border: colors.buttonPrimaryBackground || primary,
|
|
151
170
|
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
171
|
+
text: colors.buttonPrimaryText || white,
|
|
172
|
+
|
|
173
|
+
borderWidth: 1,
|
|
174
|
+
};
|
|
175
|
+
}
|
|
176
|
+
}, [
|
|
177
|
+
variant,
|
|
178
|
+
isDisabled,
|
|
179
|
+
colors,
|
|
180
|
+
primary,
|
|
181
|
+
primarySoft,
|
|
182
|
+
success,
|
|
183
|
+
danger,
|
|
184
|
+
white,
|
|
185
|
+
]);
|
|
186
|
+
|
|
187
|
+
const dimensions = useMemo(() => getDimensions(size, theme), [size, theme]);
|
|
188
|
+
|
|
189
|
+
const buttonStyle = useMemo(
|
|
190
|
+
() => [
|
|
191
|
+
styles.button,
|
|
192
|
+
|
|
193
|
+
{
|
|
194
|
+
height: dimensions.height,
|
|
195
|
+
|
|
196
|
+
minHeight: dimensions.height,
|
|
197
|
+
|
|
198
|
+
paddingHorizontal: dimensions.paddingHorizontal,
|
|
199
|
+
|
|
200
|
+
borderRadius: dimensions.borderRadius,
|
|
201
|
+
|
|
202
|
+
backgroundColor: buttonColors.background,
|
|
203
|
+
|
|
204
|
+
borderColor: buttonColors.border,
|
|
205
|
+
|
|
206
|
+
borderWidth: buttonColors.borderWidth,
|
|
207
|
+
|
|
208
|
+
width: fullWidth ? "100%" : undefined,
|
|
209
|
+
|
|
210
|
+
opacity: isDisabled ? 0.55 : 1,
|
|
211
|
+
},
|
|
212
|
+
|
|
213
|
+
style,
|
|
214
|
+
],
|
|
215
|
+
[dimensions, buttonColors, fullWidth, isDisabled, style],
|
|
157
216
|
);
|
|
158
217
|
|
|
159
|
-
const
|
|
218
|
+
const handlePress = useCallback(
|
|
160
219
|
(event) => {
|
|
161
220
|
if (isDisabled) {
|
|
162
221
|
return;
|
|
163
222
|
}
|
|
164
223
|
|
|
165
|
-
|
|
166
|
-
onPressIn(event);
|
|
167
|
-
}
|
|
224
|
+
onPress?.(event);
|
|
168
225
|
},
|
|
169
|
-
[isDisabled,
|
|
226
|
+
[isDisabled, onPress],
|
|
170
227
|
);
|
|
171
228
|
|
|
172
|
-
const
|
|
229
|
+
const handleLongPress = useCallback(
|
|
173
230
|
(event) => {
|
|
174
231
|
if (isDisabled) {
|
|
175
232
|
return;
|
|
176
233
|
}
|
|
177
234
|
|
|
178
|
-
|
|
179
|
-
onPressOut(event);
|
|
180
|
-
}
|
|
235
|
+
onLongPress?.(event);
|
|
181
236
|
},
|
|
182
|
-
[isDisabled,
|
|
237
|
+
[isDisabled, onLongPress],
|
|
183
238
|
);
|
|
184
239
|
|
|
185
|
-
const hasChildren = children !== undefined && children !== null;
|
|
186
|
-
|
|
187
240
|
return (
|
|
188
241
|
<Pressable
|
|
189
242
|
{...props}
|
|
@@ -191,281 +244,118 @@ const UIButtonComponent = ({
|
|
|
191
244
|
disabled={isDisabled}
|
|
192
245
|
onPress={handlePress}
|
|
193
246
|
onLongPress={handleLongPress}
|
|
194
|
-
|
|
195
|
-
onPressOut={handlePressOut}
|
|
196
|
-
accessibilityRole="button"
|
|
197
|
-
accessibilityLabel={
|
|
198
|
-
accessibilityLabel || (typeof title === "string" ? title : undefined)
|
|
199
|
-
}
|
|
200
|
-
accessibilityHint={accessibilityHint}
|
|
201
|
-
accessibilityState={{
|
|
202
|
-
disabled: isDisabled,
|
|
203
|
-
|
|
204
|
-
busy: loading,
|
|
205
|
-
}}
|
|
206
|
-
style={({ pressed }) => {
|
|
207
|
-
const backgroundColor = isDisabled
|
|
208
|
-
? colors.buttonDisabledBackground
|
|
209
|
-
: pressed
|
|
210
|
-
? variantStyle.pressedBackground
|
|
211
|
-
: variantStyle.backgroundColor;
|
|
212
|
-
|
|
213
|
-
const borderColor = isDisabled
|
|
214
|
-
? colors.buttonDisabledBorder
|
|
215
|
-
: variantStyle.borderColor;
|
|
216
|
-
|
|
217
|
-
const textColor = isDisabled
|
|
218
|
-
? colors.buttonDisabledText
|
|
219
|
-
: variantStyle.textColor;
|
|
220
|
-
|
|
221
|
-
return [
|
|
222
|
-
styles.button,
|
|
223
|
-
|
|
224
|
-
{
|
|
225
|
-
height: sizeStyle.height,
|
|
226
|
-
|
|
227
|
-
minHeight: sizeStyle.height,
|
|
228
|
-
|
|
229
|
-
paddingHorizontal: sizeStyle.paddingHorizontal,
|
|
230
|
-
|
|
231
|
-
borderRadius: sizeStyle.borderRadius,
|
|
232
|
-
|
|
233
|
-
backgroundColor,
|
|
234
|
-
|
|
235
|
-
borderColor,
|
|
236
|
-
|
|
237
|
-
borderWidth: variantStyle.borderWidth,
|
|
238
|
-
|
|
239
|
-
width: fullWidth ? "100%" : undefined,
|
|
240
|
-
|
|
241
|
-
opacity: isDisabled ? 0.55 : 1,
|
|
242
|
-
},
|
|
243
|
-
|
|
244
|
-
style,
|
|
245
|
-
];
|
|
246
|
-
}}
|
|
247
|
+
style={buttonStyle}
|
|
247
248
|
>
|
|
248
249
|
<View
|
|
249
250
|
style={[
|
|
250
251
|
styles.content,
|
|
251
252
|
|
|
252
253
|
{
|
|
253
|
-
gap:
|
|
254
|
+
gap: dimensions.gap,
|
|
254
255
|
},
|
|
255
256
|
|
|
256
257
|
contentStyle,
|
|
257
258
|
]}
|
|
258
259
|
>
|
|
259
260
|
{loading ? (
|
|
260
|
-
<ActivityIndicator size="small" color={
|
|
261
|
+
<ActivityIndicator size="small" color={buttonColors.text} />
|
|
261
262
|
) : (
|
|
262
263
|
leftIcon && <View style={styles.icon}>{leftIcon}</View>
|
|
263
264
|
)}
|
|
264
265
|
|
|
265
|
-
{
|
|
266
|
+
{children !== undefined && children !== null ? (
|
|
266
267
|
<View style={styles.children}>{children}</View>
|
|
267
|
-
) : (
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
style={[
|
|
273
|
-
styles.text,
|
|
274
|
-
|
|
275
|
-
{
|
|
276
|
-
color: isDisabled
|
|
277
|
-
? colors.buttonDisabledText
|
|
278
|
-
: variantStyle.textColor,
|
|
279
|
-
|
|
280
|
-
fontSize: sizeStyle.fontSize,
|
|
281
|
-
|
|
282
|
-
lineHeight: sizeStyle.lineHeight,
|
|
283
|
-
},
|
|
284
|
-
|
|
285
|
-
textStyle,
|
|
286
|
-
]}
|
|
287
|
-
>
|
|
288
|
-
{title}
|
|
289
|
-
</Text>
|
|
290
|
-
)
|
|
291
|
-
)}
|
|
292
|
-
|
|
293
|
-
{!loading && rightIcon && <View style={styles.icon}>{rightIcon}</View>}
|
|
294
|
-
</View>
|
|
295
|
-
</Pressable>
|
|
296
|
-
);
|
|
297
|
-
};
|
|
298
|
-
|
|
299
|
-
function getVariantStyle(variant, colors, disabled) {
|
|
300
|
-
if (disabled) {
|
|
301
|
-
return {
|
|
302
|
-
backgroundColor: colors.buttonDisabledBackground,
|
|
303
|
-
|
|
304
|
-
pressedBackground: colors.buttonDisabledBackground,
|
|
305
|
-
|
|
306
|
-
borderColor: colors.buttonDisabledBorder,
|
|
307
|
-
|
|
308
|
-
borderWidth: 1,
|
|
309
|
-
|
|
310
|
-
textColor: colors.buttonDisabledText,
|
|
311
|
-
};
|
|
312
|
-
}
|
|
313
|
-
|
|
314
|
-
switch (variant) {
|
|
315
|
-
case BUTTON_VARIANTS.outline:
|
|
316
|
-
return {
|
|
317
|
-
backgroundColor: colors.buttonOutlineBackground,
|
|
318
|
-
|
|
319
|
-
pressedBackground: colors.buttonSoftBackground,
|
|
320
|
-
|
|
321
|
-
borderColor: colors.buttonOutlineBorder,
|
|
268
|
+
) : title !== undefined && title !== null ? (
|
|
269
|
+
<Text
|
|
270
|
+
numberOfLines={1}
|
|
271
|
+
style={[
|
|
272
|
+
styles.text,
|
|
322
273
|
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
textColor: colors.buttonOutlineText,
|
|
326
|
-
};
|
|
327
|
-
|
|
328
|
-
case BUTTON_VARIANTS.ghost:
|
|
329
|
-
return {
|
|
330
|
-
backgroundColor: colors.buttonGhostBackground,
|
|
331
|
-
|
|
332
|
-
pressedBackground: colors.buttonSoftBackground,
|
|
274
|
+
{
|
|
275
|
+
color: buttonColors.text,
|
|
333
276
|
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
borderWidth: 0,
|
|
337
|
-
|
|
338
|
-
textColor: colors.buttonGhostText,
|
|
339
|
-
};
|
|
340
|
-
|
|
341
|
-
case BUTTON_VARIANTS.soft:
|
|
342
|
-
return {
|
|
343
|
-
backgroundColor: colors.buttonSoftBackground,
|
|
277
|
+
fontSize: dimensions.fontSize,
|
|
344
278
|
|
|
345
|
-
|
|
279
|
+
lineHeight: dimensions.lineHeight,
|
|
280
|
+
},
|
|
346
281
|
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
case BUTTON_VARIANTS.danger:
|
|
355
|
-
return {
|
|
356
|
-
backgroundColor: colors.buttonDangerBackground,
|
|
357
|
-
|
|
358
|
-
pressedBackground: colors.buttonDangerPressed,
|
|
359
|
-
|
|
360
|
-
borderColor: colors.buttonDangerBackground,
|
|
361
|
-
|
|
362
|
-
borderWidth: 1,
|
|
282
|
+
textStyle,
|
|
283
|
+
]}
|
|
284
|
+
>
|
|
285
|
+
{title}
|
|
286
|
+
</Text>
|
|
287
|
+
) : null}
|
|
363
288
|
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
return {
|
|
369
|
-
backgroundColor: colors.buttonSuccessBackground,
|
|
370
|
-
|
|
371
|
-
pressedBackground: colors.buttonSuccessPressed,
|
|
372
|
-
|
|
373
|
-
borderColor: colors.buttonSuccessBackground,
|
|
374
|
-
|
|
375
|
-
borderWidth: 1,
|
|
376
|
-
|
|
377
|
-
textColor: colors.buttonSuccessText,
|
|
378
|
-
};
|
|
379
|
-
|
|
380
|
-
case BUTTON_VARIANTS.solid:
|
|
381
|
-
default:
|
|
382
|
-
return {
|
|
383
|
-
backgroundColor: colors.buttonPrimaryBackground,
|
|
384
|
-
|
|
385
|
-
pressedBackground: colors.buttonPrimaryPressed,
|
|
386
|
-
|
|
387
|
-
borderColor: colors.buttonPrimaryBackground,
|
|
388
|
-
|
|
389
|
-
borderWidth: 1,
|
|
390
|
-
|
|
391
|
-
textColor: colors.buttonPrimaryText,
|
|
392
|
-
};
|
|
393
|
-
}
|
|
289
|
+
{!loading && rightIcon && <View style={styles.icon}>{rightIcon}</View>}
|
|
290
|
+
</View>
|
|
291
|
+
</Pressable>
|
|
292
|
+
);
|
|
394
293
|
}
|
|
395
294
|
|
|
396
|
-
function
|
|
295
|
+
function getDimensions(size, theme) {
|
|
397
296
|
const buttonSizes = theme?.sizes?.button || {};
|
|
398
297
|
|
|
399
|
-
const
|
|
400
|
-
|
|
401
|
-
const buttonRadius = typeof themeRadius === "number" ? themeRadius : 12;
|
|
298
|
+
const radius =
|
|
299
|
+
typeof theme?.radius?.button === "number" ? theme.radius.button : 12;
|
|
402
300
|
|
|
403
301
|
const spacing = theme?.spacing || {};
|
|
404
302
|
|
|
405
|
-
const spacingSM = typeof spacing.sm === "number" ? spacing.sm : 8;
|
|
406
|
-
|
|
407
|
-
const spacingMD = typeof spacing.md === "number" ? spacing.md : 16;
|
|
408
|
-
|
|
409
|
-
const spacingLG = typeof spacing.lg === "number" ? spacing.lg : 20;
|
|
410
|
-
|
|
411
|
-
const spacingXL = typeof spacing.xl === "number" ? spacing.xl : 24;
|
|
412
|
-
|
|
413
303
|
switch (size) {
|
|
414
|
-
case
|
|
304
|
+
case "sm":
|
|
415
305
|
return {
|
|
416
|
-
height: buttonSizes.sm
|
|
306
|
+
height: buttonSizes.sm || 36,
|
|
417
307
|
|
|
418
|
-
paddingHorizontal:
|
|
308
|
+
paddingHorizontal: spacing.md || 16,
|
|
419
309
|
|
|
420
|
-
gap:
|
|
310
|
+
gap: 6,
|
|
421
311
|
|
|
422
|
-
borderRadius:
|
|
312
|
+
borderRadius: radius,
|
|
423
313
|
|
|
424
314
|
fontSize: 13,
|
|
425
315
|
|
|
426
316
|
lineHeight: 18,
|
|
427
317
|
};
|
|
428
318
|
|
|
429
|
-
case
|
|
319
|
+
case "lg":
|
|
430
320
|
return {
|
|
431
|
-
height: buttonSizes.lg
|
|
321
|
+
height: buttonSizes.lg || 52,
|
|
432
322
|
|
|
433
|
-
paddingHorizontal:
|
|
323
|
+
paddingHorizontal: spacing.lg || 20,
|
|
434
324
|
|
|
435
|
-
gap:
|
|
325
|
+
gap: 8,
|
|
436
326
|
|
|
437
|
-
borderRadius:
|
|
327
|
+
borderRadius: radius,
|
|
438
328
|
|
|
439
329
|
fontSize: 16,
|
|
440
330
|
|
|
441
331
|
lineHeight: 22,
|
|
442
332
|
};
|
|
443
333
|
|
|
444
|
-
case
|
|
334
|
+
case "xl":
|
|
445
335
|
return {
|
|
446
|
-
height: buttonSizes.xl
|
|
336
|
+
height: buttonSizes.xl || 60,
|
|
447
337
|
|
|
448
|
-
paddingHorizontal:
|
|
338
|
+
paddingHorizontal: spacing.xl || 24,
|
|
449
339
|
|
|
450
|
-
gap:
|
|
340
|
+
gap: 8,
|
|
451
341
|
|
|
452
|
-
borderRadius:
|
|
342
|
+
borderRadius: radius,
|
|
453
343
|
|
|
454
344
|
fontSize: 17,
|
|
455
345
|
|
|
456
346
|
lineHeight: 24,
|
|
457
347
|
};
|
|
458
348
|
|
|
459
|
-
case
|
|
349
|
+
case "md":
|
|
460
350
|
default:
|
|
461
351
|
return {
|
|
462
|
-
height: buttonSizes.md
|
|
352
|
+
height: buttonSizes.md || 44,
|
|
463
353
|
|
|
464
|
-
paddingHorizontal:
|
|
354
|
+
paddingHorizontal: spacing.md || 16,
|
|
465
355
|
|
|
466
|
-
gap:
|
|
356
|
+
gap: 8,
|
|
467
357
|
|
|
468
|
-
borderRadius:
|
|
358
|
+
borderRadius: radius,
|
|
469
359
|
|
|
470
360
|
fontSize: 14,
|
|
471
361
|
|
|
@@ -476,13 +366,15 @@ function getSizeStyle(size, theme) {
|
|
|
476
366
|
|
|
477
367
|
const styles = StyleSheet.create({
|
|
478
368
|
button: {
|
|
479
|
-
|
|
369
|
+
flexDirection: "row",
|
|
480
370
|
|
|
481
371
|
alignItems: "center",
|
|
482
372
|
|
|
483
373
|
justifyContent: "center",
|
|
484
374
|
|
|
485
375
|
overflow: "hidden",
|
|
376
|
+
|
|
377
|
+
flexShrink: 0,
|
|
486
378
|
},
|
|
487
379
|
|
|
488
380
|
content: {
|
|
@@ -496,11 +388,11 @@ const styles = StyleSheet.create({
|
|
|
496
388
|
},
|
|
497
389
|
|
|
498
390
|
children: {
|
|
499
|
-
flexShrink: 1,
|
|
500
|
-
|
|
501
391
|
alignItems: "center",
|
|
502
392
|
|
|
503
393
|
justifyContent: "center",
|
|
394
|
+
|
|
395
|
+
flexShrink: 1,
|
|
504
396
|
},
|
|
505
397
|
|
|
506
398
|
icon: {
|
|
@@ -512,18 +404,16 @@ const styles = StyleSheet.create({
|
|
|
512
404
|
},
|
|
513
405
|
|
|
514
406
|
text: {
|
|
515
|
-
flexShrink: 1,
|
|
516
|
-
|
|
517
407
|
fontWeight: "600",
|
|
518
408
|
|
|
519
409
|
textAlign: "center",
|
|
520
410
|
|
|
521
411
|
includeFontPadding: false,
|
|
412
|
+
|
|
413
|
+
flexShrink: 1,
|
|
522
414
|
},
|
|
523
415
|
});
|
|
524
416
|
|
|
525
|
-
export
|
|
526
|
-
|
|
527
|
-
UIButton.displayName = "UIButton";
|
|
417
|
+
export default memo(UIButton);
|
|
528
418
|
|
|
529
|
-
export {
|
|
419
|
+
export { UIButton, VARIANTS as UIButtonVariants, SIZES as UIButtonSizes };
|
|
@@ -1,17 +1,9 @@
|
|
|
1
|
-
import React, { memo, useCallback } from "react";
|
|
1
|
+
import React, { memo, useCallback, useMemo } from "react";
|
|
2
2
|
|
|
3
3
|
import { ActivityIndicator, Pressable, StyleSheet, View } from "react-native";
|
|
4
4
|
|
|
5
5
|
import { useUITheme } from "../../theme";
|
|
6
6
|
|
|
7
|
-
const SIZES = {
|
|
8
|
-
xs: "xs",
|
|
9
|
-
sm: "sm",
|
|
10
|
-
md: "md",
|
|
11
|
-
lg: "lg",
|
|
12
|
-
xl: "xl",
|
|
13
|
-
};
|
|
14
|
-
|
|
15
7
|
const VARIANTS = {
|
|
16
8
|
solid: "solid",
|
|
17
9
|
outline: "outline",
|
|
@@ -21,19 +13,47 @@ const VARIANTS = {
|
|
|
21
13
|
success: "success",
|
|
22
14
|
};
|
|
23
15
|
|
|
16
|
+
const SIZES = {
|
|
17
|
+
xs: "xs",
|
|
18
|
+
sm: "sm",
|
|
19
|
+
md: "md",
|
|
20
|
+
lg: "lg",
|
|
21
|
+
xl: "xl",
|
|
22
|
+
xxl: "xxl",
|
|
23
|
+
};
|
|
24
|
+
|
|
24
25
|
const SHAPES = {
|
|
25
26
|
circle: "circle",
|
|
26
27
|
rounded: "rounded",
|
|
27
28
|
square: "square",
|
|
28
29
|
};
|
|
29
30
|
|
|
30
|
-
const
|
|
31
|
-
|
|
31
|
+
const FALLBACK_COLORS = {
|
|
32
|
+
primary: "#FF5A1F",
|
|
33
|
+
primarySoft: "#FFF0EA",
|
|
34
|
+
primaryPressed: "#E94D17",
|
|
32
35
|
|
|
33
|
-
|
|
36
|
+
success: "#16A34A",
|
|
37
|
+
successPressed: "#128238",
|
|
38
|
+
|
|
39
|
+
danger: "#DC2626",
|
|
40
|
+
dangerPressed: "#B91C1C",
|
|
41
|
+
|
|
42
|
+
white: "#FFFFFF",
|
|
43
|
+
|
|
44
|
+
border: "#E5E5E5",
|
|
45
|
+
|
|
46
|
+
disabledBackground: "#E5E5E5",
|
|
47
|
+
disabledBorder: "#E5E5E5",
|
|
48
|
+
};
|
|
49
|
+
|
|
50
|
+
function UIIconButtonComponent({
|
|
51
|
+
icon,
|
|
34
52
|
|
|
35
53
|
variant = "ghost",
|
|
36
54
|
|
|
55
|
+
size = "md",
|
|
56
|
+
|
|
37
57
|
shape = "circle",
|
|
38
58
|
|
|
39
59
|
disabled = false,
|
|
@@ -52,35 +72,31 @@ const UIIconButtonComponent = ({
|
|
|
52
72
|
|
|
53
73
|
iconContainerStyle,
|
|
54
74
|
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
android_ripple = true,
|
|
75
|
+
hitSlop,
|
|
58
76
|
|
|
59
|
-
|
|
77
|
+
testID,
|
|
60
78
|
|
|
61
79
|
accessibilityLabel,
|
|
62
80
|
|
|
63
81
|
accessibilityHint,
|
|
64
82
|
|
|
65
|
-
testID,
|
|
66
|
-
|
|
67
83
|
...props
|
|
68
|
-
})
|
|
84
|
+
}) {
|
|
69
85
|
const { theme } = useUITheme();
|
|
70
86
|
|
|
71
|
-
const
|
|
72
|
-
|
|
73
|
-
const safeVariant = VARIANTS[variant] ? variant : VARIANTS.ghost;
|
|
74
|
-
|
|
75
|
-
const safeShape = SHAPES[shape] ? shape : SHAPES.circle;
|
|
87
|
+
const colors = theme?.colors || {};
|
|
76
88
|
|
|
77
89
|
const isDisabled = disabled || loading;
|
|
78
90
|
|
|
79
|
-
const
|
|
80
|
-
|
|
81
|
-
|
|
91
|
+
const resolvedColors = useMemo(
|
|
92
|
+
() => getVariantColors(variant, colors, isDisabled),
|
|
93
|
+
[variant, colors, isDisabled],
|
|
94
|
+
);
|
|
82
95
|
|
|
83
|
-
const
|
|
96
|
+
const dimensions = useMemo(
|
|
97
|
+
() => getDimensions(size, shape, theme),
|
|
98
|
+
[size, shape, theme],
|
|
99
|
+
);
|
|
84
100
|
|
|
85
101
|
const handlePress = useCallback(
|
|
86
102
|
(event) => {
|
|
@@ -126,12 +142,34 @@ const UIIconButtonComponent = ({
|
|
|
126
142
|
[isDisabled, onPressOut],
|
|
127
143
|
);
|
|
128
144
|
|
|
129
|
-
const
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
145
|
+
const buttonStyle = useMemo(
|
|
146
|
+
() => [
|
|
147
|
+
styles.button,
|
|
148
|
+
|
|
149
|
+
{
|
|
150
|
+
width: dimensions.size,
|
|
151
|
+
|
|
152
|
+
height: dimensions.size,
|
|
153
|
+
|
|
154
|
+
minWidth: dimensions.size,
|
|
155
|
+
|
|
156
|
+
minHeight: dimensions.size,
|
|
157
|
+
|
|
158
|
+
borderRadius: dimensions.borderRadius,
|
|
159
|
+
|
|
160
|
+
backgroundColor: resolvedColors.background,
|
|
161
|
+
|
|
162
|
+
borderColor: resolvedColors.border,
|
|
163
|
+
|
|
164
|
+
borderWidth: resolvedColors.borderWidth,
|
|
165
|
+
|
|
166
|
+
opacity: isDisabled ? 0.55 : 1,
|
|
167
|
+
},
|
|
168
|
+
|
|
169
|
+
style,
|
|
170
|
+
],
|
|
171
|
+
[dimensions, resolvedColors, isDisabled, style],
|
|
172
|
+
);
|
|
135
173
|
|
|
136
174
|
return (
|
|
137
175
|
<Pressable
|
|
@@ -143,173 +181,221 @@ const UIIconButtonComponent = ({
|
|
|
143
181
|
onPressIn={handlePressIn}
|
|
144
182
|
onPressOut={handlePressOut}
|
|
145
183
|
hitSlop={hitSlop}
|
|
146
|
-
android_ripple={ripple}
|
|
147
184
|
accessibilityRole="button"
|
|
148
185
|
accessibilityLabel={accessibilityLabel}
|
|
149
186
|
accessibilityHint={accessibilityHint}
|
|
150
187
|
accessibilityState={{
|
|
151
188
|
disabled: isDisabled,
|
|
189
|
+
|
|
152
190
|
busy: loading,
|
|
153
191
|
}}
|
|
154
|
-
style={
|
|
155
|
-
styles.button,
|
|
156
|
-
|
|
157
|
-
{
|
|
158
|
-
width: dimensions.size,
|
|
159
|
-
|
|
160
|
-
height: dimensions.size,
|
|
161
|
-
|
|
162
|
-
borderRadius,
|
|
163
|
-
|
|
164
|
-
backgroundColor: colors.background,
|
|
165
|
-
|
|
166
|
-
borderColor: colors.border,
|
|
167
|
-
|
|
168
|
-
borderWidth: colors.border ? 1 : 0,
|
|
169
|
-
|
|
170
|
-
opacity: isDisabled ? 0.5 : pressed ? activeOpacity : 1,
|
|
171
|
-
},
|
|
172
|
-
|
|
173
|
-
style,
|
|
174
|
-
]}
|
|
192
|
+
style={buttonStyle}
|
|
175
193
|
>
|
|
176
194
|
<View style={[styles.iconContainer, iconContainerStyle]}>
|
|
177
195
|
{loading ? (
|
|
178
|
-
<ActivityIndicator size="small" color={
|
|
196
|
+
<ActivityIndicator size="small" color={resolvedColors.icon} />
|
|
179
197
|
) : (
|
|
180
198
|
icon
|
|
181
199
|
)}
|
|
182
200
|
</View>
|
|
183
201
|
</Pressable>
|
|
184
202
|
);
|
|
185
|
-
}
|
|
203
|
+
}
|
|
186
204
|
|
|
187
|
-
function
|
|
188
|
-
|
|
189
|
-
case SIZES.xs:
|
|
190
|
-
return {
|
|
191
|
-
size: theme.sizes.icon.lg + theme.spacing.sm,
|
|
192
|
-
};
|
|
205
|
+
function getVariantColors(variant, colors, disabled) {
|
|
206
|
+
const primary = colors.primary || FALLBACK_COLORS.primary;
|
|
193
207
|
|
|
194
|
-
|
|
195
|
-
return {
|
|
196
|
-
size: theme.sizes.button.sm,
|
|
197
|
-
};
|
|
208
|
+
const primarySoft = colors.primarySoft || FALLBACK_COLORS.primarySoft;
|
|
198
209
|
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
size: theme.sizes.button.lg,
|
|
202
|
-
};
|
|
210
|
+
const primaryPressed =
|
|
211
|
+
colors.primaryPressed || FALLBACK_COLORS.primaryPressed;
|
|
203
212
|
|
|
204
|
-
|
|
205
|
-
return {
|
|
206
|
-
size: theme.sizes.button.xl,
|
|
207
|
-
};
|
|
213
|
+
const success = colors.success || FALLBACK_COLORS.success;
|
|
208
214
|
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
return {
|
|
212
|
-
size: theme.sizes.button.md,
|
|
213
|
-
};
|
|
214
|
-
}
|
|
215
|
-
}
|
|
215
|
+
const successPressed =
|
|
216
|
+
colors.successPressed || FALLBACK_COLORS.successPressed;
|
|
216
217
|
|
|
217
|
-
|
|
218
|
-
switch (shape) {
|
|
219
|
-
case SHAPES.rounded:
|
|
220
|
-
return theme.radius.lg;
|
|
218
|
+
const danger = colors.danger || FALLBACK_COLORS.danger;
|
|
221
219
|
|
|
222
|
-
|
|
223
|
-
return theme.radius.sm;
|
|
220
|
+
const dangerPressed = colors.dangerPressed || FALLBACK_COLORS.dangerPressed;
|
|
224
221
|
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
222
|
+
const white = colors.onPrimary || FALLBACK_COLORS.white;
|
|
223
|
+
|
|
224
|
+
if (disabled) {
|
|
225
|
+
return {
|
|
226
|
+
background:
|
|
227
|
+
colors.buttonDisabledBackground || FALLBACK_COLORS.disabledBackground,
|
|
228
|
+
|
|
229
|
+
border: colors.buttonDisabledBorder || FALLBACK_COLORS.disabledBorder,
|
|
230
|
+
|
|
231
|
+
borderWidth: 1,
|
|
232
|
+
|
|
233
|
+
icon: colors.buttonDisabledText || "#A3A3A3",
|
|
234
|
+
|
|
235
|
+
pressed:
|
|
236
|
+
colors.buttonDisabledBackground || FALLBACK_COLORS.disabledBackground,
|
|
237
|
+
};
|
|
228
238
|
}
|
|
229
|
-
}
|
|
230
239
|
|
|
231
|
-
function getColors(variant, colors) {
|
|
232
240
|
switch (variant) {
|
|
233
241
|
case VARIANTS.solid:
|
|
234
242
|
return {
|
|
235
|
-
background: colors.primary,
|
|
243
|
+
background: colors.buttonPrimaryBackground || primary,
|
|
236
244
|
|
|
237
|
-
border: colors.primary,
|
|
245
|
+
border: colors.buttonPrimaryBackground || primary,
|
|
238
246
|
|
|
239
|
-
|
|
247
|
+
borderWidth: 1,
|
|
240
248
|
|
|
241
|
-
|
|
249
|
+
icon: colors.buttonPrimaryText || white,
|
|
250
|
+
|
|
251
|
+
pressed: colors.buttonPrimaryPressed || primaryPressed,
|
|
242
252
|
};
|
|
243
253
|
|
|
244
254
|
case VARIANTS.outline:
|
|
245
255
|
return {
|
|
246
|
-
background:
|
|
256
|
+
background: "transparent",
|
|
257
|
+
|
|
258
|
+
border: colors.buttonOutlineBorder || primary,
|
|
247
259
|
|
|
248
|
-
|
|
260
|
+
borderWidth: 1,
|
|
249
261
|
|
|
250
|
-
icon: colors.
|
|
262
|
+
icon: colors.buttonOutlineText || primary,
|
|
251
263
|
|
|
252
|
-
|
|
264
|
+
pressed: colors.buttonSoftBackground || primarySoft,
|
|
253
265
|
};
|
|
254
266
|
|
|
255
267
|
case VARIANTS.soft:
|
|
256
268
|
return {
|
|
257
|
-
background: colors.primarySoft,
|
|
269
|
+
background: colors.buttonSoftBackground || primarySoft,
|
|
258
270
|
|
|
259
|
-
border:
|
|
271
|
+
border: colors.buttonSoftBackground || primarySoft,
|
|
260
272
|
|
|
261
|
-
|
|
273
|
+
borderWidth: 1,
|
|
262
274
|
|
|
263
|
-
|
|
275
|
+
icon: colors.buttonSoftText || primary,
|
|
276
|
+
|
|
277
|
+
pressed: colors.primaryMuted || primarySoft,
|
|
264
278
|
};
|
|
265
279
|
|
|
266
280
|
case VARIANTS.danger:
|
|
267
281
|
return {
|
|
268
|
-
background: colors.danger,
|
|
282
|
+
background: colors.buttonDangerBackground || danger,
|
|
283
|
+
|
|
284
|
+
border: colors.buttonDangerBackground || danger,
|
|
269
285
|
|
|
270
|
-
|
|
286
|
+
borderWidth: 1,
|
|
271
287
|
|
|
272
|
-
icon: colors.
|
|
288
|
+
icon: colors.buttonDangerText || white,
|
|
273
289
|
|
|
274
|
-
|
|
290
|
+
pressed: colors.buttonDangerPressed || dangerPressed,
|
|
275
291
|
};
|
|
276
292
|
|
|
277
293
|
case VARIANTS.success:
|
|
278
294
|
return {
|
|
279
|
-
background: colors.success,
|
|
295
|
+
background: colors.buttonSuccessBackground || success,
|
|
280
296
|
|
|
281
|
-
border: colors.success,
|
|
297
|
+
border: colors.buttonSuccessBackground || success,
|
|
282
298
|
|
|
283
|
-
|
|
299
|
+
borderWidth: 1,
|
|
284
300
|
|
|
285
|
-
|
|
301
|
+
icon: colors.buttonSuccessText || white,
|
|
302
|
+
|
|
303
|
+
pressed: colors.buttonSuccessPressed || successPressed,
|
|
286
304
|
};
|
|
287
305
|
|
|
288
306
|
case VARIANTS.ghost:
|
|
289
307
|
default:
|
|
290
308
|
return {
|
|
291
|
-
background:
|
|
309
|
+
background: "transparent",
|
|
310
|
+
|
|
311
|
+
border: "transparent",
|
|
292
312
|
|
|
293
|
-
|
|
313
|
+
borderWidth: 0,
|
|
294
314
|
|
|
295
|
-
icon: colors.
|
|
315
|
+
icon: colors.buttonGhostText || primary,
|
|
296
316
|
|
|
297
|
-
|
|
317
|
+
pressed: colors.buttonSoftBackground || primarySoft,
|
|
298
318
|
};
|
|
299
319
|
}
|
|
300
320
|
}
|
|
301
321
|
|
|
322
|
+
function getDimensions(size, shape, theme) {
|
|
323
|
+
const iconSizes = theme?.sizes?.icon || {};
|
|
324
|
+
|
|
325
|
+
const radius = theme?.radius || {};
|
|
326
|
+
|
|
327
|
+
let resolvedSize;
|
|
328
|
+
|
|
329
|
+
switch (size) {
|
|
330
|
+
case SIZES.xs:
|
|
331
|
+
resolvedSize = iconSizes.xs ? iconSizes.xs + 16 : 32;
|
|
332
|
+
break;
|
|
333
|
+
|
|
334
|
+
case SIZES.sm:
|
|
335
|
+
resolvedSize = iconSizes.sm ? iconSizes.sm + 16 : 40;
|
|
336
|
+
break;
|
|
337
|
+
|
|
338
|
+
case SIZES.lg:
|
|
339
|
+
resolvedSize = iconSizes.lg ? iconSizes.lg + 20 : 52;
|
|
340
|
+
break;
|
|
341
|
+
|
|
342
|
+
case SIZES.xl:
|
|
343
|
+
resolvedSize = iconSizes.xl ? iconSizes.xl + 24 : 60;
|
|
344
|
+
break;
|
|
345
|
+
|
|
346
|
+
case SIZES.xxl:
|
|
347
|
+
resolvedSize = iconSizes.xxl ? iconSizes.xxl + 28 : 72;
|
|
348
|
+
break;
|
|
349
|
+
|
|
350
|
+
case SIZES.md:
|
|
351
|
+
default:
|
|
352
|
+
resolvedSize = iconSizes.md ? iconSizes.md + 20 : 44;
|
|
353
|
+
break;
|
|
354
|
+
}
|
|
355
|
+
|
|
356
|
+
let borderRadius;
|
|
357
|
+
|
|
358
|
+
switch (shape) {
|
|
359
|
+
case SHAPES.square:
|
|
360
|
+
borderRadius = radius.sm ?? 6;
|
|
361
|
+
break;
|
|
362
|
+
|
|
363
|
+
case SHAPES.rounded:
|
|
364
|
+
borderRadius = radius.button ?? 12;
|
|
365
|
+
break;
|
|
366
|
+
|
|
367
|
+
case SHAPES.circle:
|
|
368
|
+
default:
|
|
369
|
+
borderRadius = resolvedSize / 2;
|
|
370
|
+
break;
|
|
371
|
+
}
|
|
372
|
+
|
|
373
|
+
return {
|
|
374
|
+
size: resolvedSize,
|
|
375
|
+
|
|
376
|
+
borderRadius,
|
|
377
|
+
};
|
|
378
|
+
}
|
|
379
|
+
|
|
302
380
|
const styles = StyleSheet.create({
|
|
303
381
|
button: {
|
|
304
382
|
alignItems: "center",
|
|
383
|
+
|
|
305
384
|
justifyContent: "center",
|
|
385
|
+
|
|
306
386
|
overflow: "hidden",
|
|
387
|
+
|
|
388
|
+
flexShrink: 0,
|
|
307
389
|
},
|
|
308
390
|
|
|
309
391
|
iconContainer: {
|
|
392
|
+
width: "100%",
|
|
393
|
+
|
|
394
|
+
height: "100%",
|
|
395
|
+
|
|
310
396
|
alignItems: "center",
|
|
397
|
+
|
|
311
398
|
justifyContent: "center",
|
|
312
|
-
flex: 1,
|
|
313
399
|
},
|
|
314
400
|
});
|
|
315
401
|
|
|
@@ -318,7 +404,9 @@ export const UIIconButton = memo(UIIconButtonComponent);
|
|
|
318
404
|
UIIconButton.displayName = "UIIconButton";
|
|
319
405
|
|
|
320
406
|
export {
|
|
321
|
-
SIZES as UIIconButtonSizes,
|
|
322
407
|
VARIANTS as UIIconButtonVariants,
|
|
408
|
+
SIZES as UIIconButtonSizes,
|
|
323
409
|
SHAPES as UIIconButtonShapes,
|
|
324
410
|
};
|
|
411
|
+
|
|
412
|
+
export default UIIconButton;
|
package/src/components/index.js
CHANGED