rnnovaui 0.1.0 → 0.1.2
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
|
@@ -4,12 +4,7 @@ import { ActivityIndicator, Pressable, StyleSheet, View } from "react-native";
|
|
|
4
4
|
|
|
5
5
|
import { useUITheme } from "../../theme";
|
|
6
6
|
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
/**
|
|
10
|
-
* Button variants
|
|
11
|
-
*/
|
|
12
|
-
const VARIANTS = {
|
|
7
|
+
const BUTTON_VARIANTS = {
|
|
13
8
|
solid: "solid",
|
|
14
9
|
outline: "outline",
|
|
15
10
|
ghost: "ghost",
|
|
@@ -18,10 +13,7 @@ const VARIANTS = {
|
|
|
18
13
|
success: "success",
|
|
19
14
|
};
|
|
20
15
|
|
|
21
|
-
|
|
22
|
-
* Button sizes
|
|
23
|
-
*/
|
|
24
|
-
const SIZES = {
|
|
16
|
+
const BUTTON_SIZES = {
|
|
25
17
|
sm: "sm",
|
|
26
18
|
md: "md",
|
|
27
19
|
lg: "lg",
|
|
@@ -30,93 +22,59 @@ const SIZES = {
|
|
|
30
22
|
|
|
31
23
|
const UIButtonComponent = ({
|
|
32
24
|
title,
|
|
33
|
-
|
|
34
25
|
children,
|
|
35
26
|
|
|
36
|
-
variant =
|
|
37
|
-
|
|
38
|
-
size = SIZES.md,
|
|
27
|
+
variant = "solid",
|
|
28
|
+
size = "md",
|
|
39
29
|
|
|
40
30
|
disabled = false,
|
|
41
|
-
|
|
42
31
|
loading = false,
|
|
43
|
-
|
|
44
32
|
fullWidth = false,
|
|
45
33
|
|
|
46
34
|
leftIcon = null,
|
|
47
|
-
|
|
48
35
|
rightIcon = null,
|
|
49
36
|
|
|
50
37
|
onPress,
|
|
51
|
-
|
|
52
38
|
onLongPress,
|
|
53
|
-
|
|
54
39
|
onPressIn,
|
|
55
|
-
|
|
56
40
|
onPressOut,
|
|
57
41
|
|
|
58
42
|
style,
|
|
59
|
-
|
|
60
|
-
textStyle,
|
|
61
|
-
|
|
62
43
|
contentStyle,
|
|
44
|
+
textStyle,
|
|
63
45
|
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
accessibilityLabel,
|
|
67
|
-
|
|
68
|
-
accessibilityHint,
|
|
46
|
+
activeOpacity = 0.82,
|
|
69
47
|
|
|
70
|
-
|
|
48
|
+
android_ripple = true,
|
|
71
49
|
|
|
72
50
|
hitSlop,
|
|
73
51
|
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
android_ripple = true,
|
|
52
|
+
accessibilityLabel,
|
|
53
|
+
accessibilityHint,
|
|
77
54
|
|
|
78
|
-
|
|
55
|
+
testID,
|
|
79
56
|
|
|
80
57
|
...props
|
|
81
58
|
}) => {
|
|
82
59
|
const { theme } = useUITheme();
|
|
83
60
|
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
61
|
+
const safeVariant = BUTTON_VARIANTS[variant] || BUTTON_VARIANTS.solid;
|
|
62
|
+
|
|
63
|
+
const safeSize = BUTTON_SIZES[size] || BUTTON_SIZES.md;
|
|
64
|
+
|
|
88
65
|
const isDisabled = disabled || loading;
|
|
89
66
|
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
/**
|
|
96
|
-
* Resolve invalid size safely.
|
|
97
|
-
*/
|
|
98
|
-
const safeSize = SIZES[size] ? size : SIZES.md;
|
|
99
|
-
|
|
100
|
-
/**
|
|
101
|
-
* Theme-dependent colors.
|
|
102
|
-
*/
|
|
103
|
-
const colors = getVariantColors(safeVariant, theme.colors);
|
|
104
|
-
|
|
105
|
-
/**
|
|
106
|
-
* Theme-dependent dimensions.
|
|
107
|
-
*/
|
|
108
|
-
const dimensions = getSizeDimensions(safeSize, theme);
|
|
109
|
-
|
|
110
|
-
/**
|
|
111
|
-
* Stable press callback.
|
|
112
|
-
*/
|
|
67
|
+
const variantStyle = resolveVariant(safeVariant, theme.colors);
|
|
68
|
+
|
|
69
|
+
const sizeStyle = resolveSize(safeSize, theme);
|
|
70
|
+
|
|
113
71
|
const handlePress = useCallback(
|
|
114
72
|
(event) => {
|
|
115
73
|
if (isDisabled) {
|
|
116
74
|
return;
|
|
117
75
|
}
|
|
118
76
|
|
|
119
|
-
if (onPress) {
|
|
77
|
+
if (typeof onPress === "function") {
|
|
120
78
|
onPress(event);
|
|
121
79
|
}
|
|
122
80
|
},
|
|
@@ -129,7 +87,7 @@ const UIButtonComponent = ({
|
|
|
129
87
|
return;
|
|
130
88
|
}
|
|
131
89
|
|
|
132
|
-
if (onLongPress) {
|
|
90
|
+
if (typeof onLongPress === "function") {
|
|
133
91
|
onLongPress(event);
|
|
134
92
|
}
|
|
135
93
|
},
|
|
@@ -142,7 +100,7 @@ const UIButtonComponent = ({
|
|
|
142
100
|
return;
|
|
143
101
|
}
|
|
144
102
|
|
|
145
|
-
if (onPressIn) {
|
|
103
|
+
if (typeof onPressIn === "function") {
|
|
146
104
|
onPressIn(event);
|
|
147
105
|
}
|
|
148
106
|
},
|
|
@@ -155,30 +113,21 @@ const UIButtonComponent = ({
|
|
|
155
113
|
return;
|
|
156
114
|
}
|
|
157
115
|
|
|
158
|
-
if (onPressOut) {
|
|
116
|
+
if (typeof onPressOut === "function") {
|
|
159
117
|
onPressOut(event);
|
|
160
118
|
}
|
|
161
119
|
},
|
|
162
120
|
[isDisabled, onPressOut],
|
|
163
121
|
);
|
|
164
122
|
|
|
165
|
-
/**
|
|
166
|
-
* Loading indicator color.
|
|
167
|
-
*/
|
|
168
|
-
const indicatorColor = colors.text;
|
|
169
|
-
|
|
170
|
-
/**
|
|
171
|
-
* Android ripple.
|
|
172
|
-
*/
|
|
173
123
|
const ripple = android_ripple
|
|
174
124
|
? {
|
|
175
|
-
color:
|
|
176
|
-
|
|
125
|
+
color: variantStyle.ripple,
|
|
177
126
|
borderless: false,
|
|
178
127
|
}
|
|
179
128
|
: undefined;
|
|
180
129
|
|
|
181
|
-
const
|
|
130
|
+
const hasChildren = children !== undefined && children !== null;
|
|
182
131
|
|
|
183
132
|
return (
|
|
184
133
|
<Pressable
|
|
@@ -190,11 +139,10 @@ const UIButtonComponent = ({
|
|
|
190
139
|
onPressIn={handlePressIn}
|
|
191
140
|
onPressOut={handlePressOut}
|
|
192
141
|
hitSlop={hitSlop}
|
|
193
|
-
pressRetentionOffset={pressRetentionOffset}
|
|
194
142
|
android_ripple={ripple}
|
|
195
|
-
accessibilityRole=
|
|
143
|
+
accessibilityRole="button"
|
|
196
144
|
accessibilityLabel={
|
|
197
|
-
accessibilityLabel
|
|
145
|
+
accessibilityLabel || (typeof title === "string" ? title : undefined)
|
|
198
146
|
}
|
|
199
147
|
accessibilityHint={accessibilityHint}
|
|
200
148
|
accessibilityState={{
|
|
@@ -202,24 +150,24 @@ const UIButtonComponent = ({
|
|
|
202
150
|
busy: loading,
|
|
203
151
|
}}
|
|
204
152
|
style={({ pressed }) => [
|
|
205
|
-
styles.
|
|
153
|
+
styles.button,
|
|
206
154
|
|
|
207
155
|
{
|
|
208
|
-
minHeight:
|
|
156
|
+
minHeight: sizeStyle.height,
|
|
209
157
|
|
|
210
|
-
paddingHorizontal:
|
|
158
|
+
paddingHorizontal: sizeStyle.paddingHorizontal,
|
|
211
159
|
|
|
212
|
-
borderRadius:
|
|
160
|
+
borderRadius: sizeStyle.borderRadius,
|
|
213
161
|
|
|
214
|
-
backgroundColor:
|
|
162
|
+
backgroundColor: variantStyle.background,
|
|
215
163
|
|
|
216
|
-
borderColor:
|
|
164
|
+
borderColor: variantStyle.border,
|
|
217
165
|
|
|
218
|
-
borderWidth:
|
|
219
|
-
|
|
220
|
-
opacity: isDisabled ? 0.55 : pressed ? activeOpacity : 1,
|
|
166
|
+
borderWidth: variantStyle.border ? 1 : 0,
|
|
221
167
|
|
|
222
168
|
width: fullWidth ? "100%" : undefined,
|
|
169
|
+
|
|
170
|
+
opacity: isDisabled ? 0.5 : pressed ? activeOpacity : 1,
|
|
223
171
|
},
|
|
224
172
|
|
|
225
173
|
style,
|
|
@@ -230,184 +178,271 @@ const UIButtonComponent = ({
|
|
|
230
178
|
styles.content,
|
|
231
179
|
|
|
232
180
|
{
|
|
233
|
-
minHeight:
|
|
181
|
+
minHeight: sizeStyle.height - 2,
|
|
234
182
|
|
|
235
|
-
gap:
|
|
183
|
+
gap: sizeStyle.gap,
|
|
236
184
|
},
|
|
237
185
|
|
|
238
186
|
contentStyle,
|
|
239
187
|
]}
|
|
240
188
|
>
|
|
241
189
|
{loading ? (
|
|
242
|
-
<ActivityIndicator size="small" color={
|
|
243
|
-
) : (
|
|
244
|
-
leftIcon
|
|
245
|
-
)}
|
|
246
|
-
|
|
247
|
-
{
|
|
248
|
-
<
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
190
|
+
<ActivityIndicator size="small" color={variantStyle.text} />
|
|
191
|
+
) : leftIcon ? (
|
|
192
|
+
<View style={styles.iconContainer}>{leftIcon}</View>
|
|
193
|
+
) : null}
|
|
194
|
+
|
|
195
|
+
{hasChildren ? (
|
|
196
|
+
<View style={styles.children}>{children}</View>
|
|
197
|
+
) : title !== undefined && title !== null ? (
|
|
198
|
+
<ButtonText
|
|
199
|
+
color={variantStyle.text}
|
|
200
|
+
sizeStyle={sizeStyle}
|
|
201
|
+
style={textStyle}
|
|
253
202
|
>
|
|
254
|
-
{
|
|
255
|
-
</
|
|
256
|
-
)}
|
|
203
|
+
{title}
|
|
204
|
+
</ButtonText>
|
|
205
|
+
) : null}
|
|
257
206
|
|
|
258
|
-
{!loading && rightIcon
|
|
207
|
+
{!loading && rightIcon ? (
|
|
208
|
+
<View style={styles.iconContainer}>{rightIcon}</View>
|
|
209
|
+
) : null}
|
|
259
210
|
</View>
|
|
260
211
|
</Pressable>
|
|
261
212
|
);
|
|
262
213
|
};
|
|
263
214
|
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
215
|
+
function ButtonText({ children, color, sizeStyle, style }) {
|
|
216
|
+
return (
|
|
217
|
+
<View style={styles.textWrapper}>
|
|
218
|
+
<ButtonTextNative color={color} sizeStyle={sizeStyle} style={style}>
|
|
219
|
+
{children}
|
|
220
|
+
</ButtonTextNative>
|
|
221
|
+
</View>
|
|
222
|
+
);
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
function ButtonTextNative({ children, color, sizeStyle, style }) {
|
|
226
|
+
const { theme } = useUITheme();
|
|
227
|
+
|
|
228
|
+
const { Text } = require("react-native");
|
|
229
|
+
|
|
230
|
+
return (
|
|
231
|
+
<Text
|
|
232
|
+
numberOfLines={1}
|
|
233
|
+
style={[
|
|
234
|
+
{
|
|
235
|
+
color,
|
|
236
|
+
|
|
237
|
+
fontSize: sizeStyle.fontSize,
|
|
238
|
+
|
|
239
|
+
lineHeight: sizeStyle.lineHeight,
|
|
240
|
+
|
|
241
|
+
fontWeight: "600",
|
|
242
|
+
|
|
243
|
+
textAlign: "center",
|
|
244
|
+
},
|
|
245
|
+
|
|
246
|
+
style,
|
|
247
|
+
]}
|
|
248
|
+
>
|
|
249
|
+
{children}
|
|
250
|
+
</Text>
|
|
251
|
+
);
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
function resolveVariant(variant, colors) {
|
|
255
|
+
const primary = colors.primary || "#FF5A1F";
|
|
256
|
+
|
|
257
|
+
const primarySoft = colors.primarySoft || "#FFF0EA";
|
|
258
|
+
|
|
259
|
+
const primaryPressed = colors.primaryPressed || primary;
|
|
260
|
+
|
|
261
|
+
const success = colors.success || "#16A34A";
|
|
262
|
+
|
|
263
|
+
const danger = colors.danger || "#DC2626";
|
|
264
|
+
|
|
265
|
+
const surface = colors.surface || "#F5F5F5";
|
|
266
|
+
|
|
267
|
+
const border = colors.border || "#E5E5E5";
|
|
268
|
+
|
|
269
|
+
const borderStrong = colors.borderStrong || "#D4D4D4";
|
|
270
|
+
|
|
271
|
+
const text = colors.text || "#111111";
|
|
272
|
+
|
|
273
|
+
const onPrimary = colors.onPrimary || "#FFFFFF";
|
|
274
|
+
|
|
268
275
|
switch (variant) {
|
|
269
|
-
case
|
|
276
|
+
case BUTTON_VARIANTS.outline:
|
|
270
277
|
return {
|
|
271
|
-
background: colors.transparent,
|
|
278
|
+
background: colors.transparent || "transparent",
|
|
272
279
|
|
|
273
|
-
border:
|
|
280
|
+
border: primary,
|
|
274
281
|
|
|
275
|
-
text:
|
|
282
|
+
text: primary,
|
|
276
283
|
|
|
277
|
-
ripple:
|
|
284
|
+
ripple: primarySoft,
|
|
278
285
|
};
|
|
279
286
|
|
|
280
|
-
case
|
|
287
|
+
case BUTTON_VARIANTS.ghost:
|
|
281
288
|
return {
|
|
282
|
-
background: colors.transparent,
|
|
289
|
+
background: colors.transparent || "transparent",
|
|
283
290
|
|
|
284
291
|
border: null,
|
|
285
292
|
|
|
286
|
-
text:
|
|
293
|
+
text: primary,
|
|
287
294
|
|
|
288
|
-
ripple:
|
|
295
|
+
ripple: primarySoft,
|
|
289
296
|
};
|
|
290
297
|
|
|
291
|
-
case
|
|
298
|
+
case BUTTON_VARIANTS.soft:
|
|
292
299
|
return {
|
|
293
|
-
background:
|
|
300
|
+
background: primarySoft,
|
|
294
301
|
|
|
295
302
|
border: null,
|
|
296
303
|
|
|
297
|
-
text:
|
|
304
|
+
text: primary,
|
|
298
305
|
|
|
299
|
-
ripple:
|
|
306
|
+
ripple: primary,
|
|
300
307
|
};
|
|
301
308
|
|
|
302
|
-
case
|
|
309
|
+
case BUTTON_VARIANTS.danger:
|
|
303
310
|
return {
|
|
304
|
-
background:
|
|
311
|
+
background: danger,
|
|
305
312
|
|
|
306
|
-
border:
|
|
313
|
+
border: danger,
|
|
307
314
|
|
|
308
|
-
text:
|
|
315
|
+
text: onPrimary,
|
|
309
316
|
|
|
310
|
-
ripple:
|
|
317
|
+
ripple: danger,
|
|
311
318
|
};
|
|
312
319
|
|
|
313
|
-
case
|
|
320
|
+
case BUTTON_VARIANTS.success:
|
|
314
321
|
return {
|
|
315
|
-
background:
|
|
322
|
+
background: success,
|
|
316
323
|
|
|
317
|
-
border:
|
|
324
|
+
border: success,
|
|
318
325
|
|
|
319
|
-
text:
|
|
326
|
+
text: onPrimary,
|
|
320
327
|
|
|
321
|
-
ripple:
|
|
328
|
+
ripple: success,
|
|
322
329
|
};
|
|
323
330
|
|
|
324
|
-
case
|
|
331
|
+
case BUTTON_VARIANTS.solid:
|
|
325
332
|
default:
|
|
326
333
|
return {
|
|
327
|
-
background:
|
|
334
|
+
background: primary,
|
|
328
335
|
|
|
329
|
-
border:
|
|
336
|
+
border: primary,
|
|
330
337
|
|
|
331
|
-
text:
|
|
338
|
+
text: onPrimary,
|
|
332
339
|
|
|
333
|
-
ripple:
|
|
340
|
+
ripple: primaryPressed,
|
|
334
341
|
};
|
|
335
342
|
}
|
|
336
343
|
}
|
|
337
344
|
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
345
|
+
function resolveSize(size, theme) {
|
|
346
|
+
const spacing = theme.spacing;
|
|
347
|
+
|
|
348
|
+
const sizes = theme.sizes;
|
|
349
|
+
|
|
350
|
+
const radius = theme.radius;
|
|
351
|
+
|
|
342
352
|
switch (size) {
|
|
343
|
-
case
|
|
353
|
+
case BUTTON_SIZES.sm:
|
|
344
354
|
return {
|
|
345
|
-
height:
|
|
355
|
+
height: sizes.button.sm,
|
|
346
356
|
|
|
347
|
-
paddingHorizontal:
|
|
357
|
+
paddingHorizontal: spacing.md,
|
|
348
358
|
|
|
349
|
-
gap:
|
|
359
|
+
gap: spacing.xs,
|
|
350
360
|
|
|
351
|
-
|
|
361
|
+
borderRadius: radius.button,
|
|
362
|
+
|
|
363
|
+
fontSize: 13,
|
|
364
|
+
|
|
365
|
+
lineHeight: 18,
|
|
352
366
|
};
|
|
353
367
|
|
|
354
|
-
case
|
|
368
|
+
case BUTTON_SIZES.lg:
|
|
355
369
|
return {
|
|
356
|
-
height:
|
|
370
|
+
height: sizes.button.lg,
|
|
371
|
+
|
|
372
|
+
paddingHorizontal: spacing.xl,
|
|
357
373
|
|
|
358
|
-
|
|
374
|
+
gap: spacing.sm,
|
|
359
375
|
|
|
360
|
-
|
|
376
|
+
borderRadius: radius.button,
|
|
361
377
|
|
|
362
|
-
|
|
378
|
+
fontSize: 16,
|
|
379
|
+
|
|
380
|
+
lineHeight: 22,
|
|
363
381
|
};
|
|
364
382
|
|
|
365
|
-
case
|
|
383
|
+
case BUTTON_SIZES.xl:
|
|
366
384
|
return {
|
|
367
|
-
height:
|
|
385
|
+
height: sizes.button.xl,
|
|
386
|
+
|
|
387
|
+
paddingHorizontal: spacing.xl2,
|
|
388
|
+
|
|
389
|
+
gap: spacing.sm,
|
|
368
390
|
|
|
369
|
-
|
|
391
|
+
borderRadius: radius.button,
|
|
370
392
|
|
|
371
|
-
|
|
393
|
+
fontSize: 17,
|
|
372
394
|
|
|
373
|
-
|
|
395
|
+
lineHeight: 24,
|
|
374
396
|
};
|
|
375
397
|
|
|
376
|
-
case
|
|
398
|
+
case BUTTON_SIZES.md:
|
|
377
399
|
default:
|
|
378
400
|
return {
|
|
379
|
-
height:
|
|
401
|
+
height: sizes.button.md,
|
|
402
|
+
|
|
403
|
+
paddingHorizontal: spacing.lg,
|
|
404
|
+
|
|
405
|
+
gap: spacing.sm,
|
|
380
406
|
|
|
381
|
-
|
|
407
|
+
borderRadius: radius.button,
|
|
382
408
|
|
|
383
|
-
|
|
409
|
+
fontSize: 14,
|
|
384
410
|
|
|
385
|
-
|
|
411
|
+
lineHeight: 20,
|
|
386
412
|
};
|
|
387
413
|
}
|
|
388
414
|
}
|
|
389
415
|
|
|
390
416
|
const styles = StyleSheet.create({
|
|
391
|
-
|
|
417
|
+
button: {
|
|
392
418
|
alignItems: "center",
|
|
393
419
|
justifyContent: "center",
|
|
394
420
|
overflow: "hidden",
|
|
421
|
+
flexShrink: 0,
|
|
395
422
|
},
|
|
396
423
|
|
|
397
424
|
content: {
|
|
398
425
|
width: "100%",
|
|
399
|
-
|
|
400
426
|
flexDirection: "row",
|
|
427
|
+
alignItems: "center",
|
|
428
|
+
justifyContent: "center",
|
|
429
|
+
flexShrink: 1,
|
|
430
|
+
},
|
|
401
431
|
|
|
432
|
+
children: {
|
|
433
|
+
flexShrink: 1,
|
|
402
434
|
alignItems: "center",
|
|
435
|
+
justifyContent: "center",
|
|
436
|
+
},
|
|
403
437
|
|
|
438
|
+
iconContainer: {
|
|
439
|
+
alignItems: "center",
|
|
404
440
|
justifyContent: "center",
|
|
441
|
+
flexShrink: 0,
|
|
405
442
|
},
|
|
406
443
|
|
|
407
|
-
|
|
444
|
+
textWrapper: {
|
|
408
445
|
flexShrink: 1,
|
|
409
|
-
|
|
410
|
-
textAlign: "center",
|
|
411
446
|
},
|
|
412
447
|
});
|
|
413
448
|
|
|
@@ -415,4 +450,4 @@ export const UIButton = memo(UIButtonComponent);
|
|
|
415
450
|
|
|
416
451
|
UIButton.displayName = "UIButton";
|
|
417
452
|
|
|
418
|
-
export {
|
|
453
|
+
export { BUTTON_VARIANTS as UIButtonVariants, BUTTON_SIZES as UIButtonSizes };
|