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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "rnnovaui",
3
- "version": "0.1.0",
3
+ "version": "0.1.2",
4
4
  "description": "",
5
5
  "main": "src/index.js",
6
6
  "react-native": "src/index.js",
@@ -4,12 +4,7 @@ import { ActivityIndicator, Pressable, StyleSheet, View } from "react-native";
4
4
 
5
5
  import { useUITheme } from "../../theme";
6
6
 
7
- import { UIText } from "../Text";
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 = VARIANTS.solid,
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
- testID,
65
-
66
- accessibilityLabel,
67
-
68
- accessibilityHint,
46
+ activeOpacity = 0.82,
69
47
 
70
- accessibilityRole = "button",
48
+ android_ripple = true,
71
49
 
72
50
  hitSlop,
73
51
 
74
- pressRetentionOffset,
75
-
76
- android_ripple = true,
52
+ accessibilityLabel,
53
+ accessibilityHint,
77
54
 
78
- activeOpacity = 0.9,
55
+ testID,
79
56
 
80
57
  ...props
81
58
  }) => {
82
59
  const { theme } = useUITheme();
83
60
 
84
- /**
85
- * Prevent callbacks when button
86
- * cannot currently be interacted with.
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
- * Resolve invalid variant safely.
92
- */
93
- const safeVariant = VARIANTS[variant] ? variant : VARIANTS.solid;
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: colors.ripple,
176
-
125
+ color: variantStyle.ripple,
177
126
  borderless: false,
178
127
  }
179
128
  : undefined;
180
129
 
181
- const label = title ?? children;
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={accessibilityRole}
143
+ accessibilityRole="button"
196
144
  accessibilityLabel={
197
- accessibilityLabel ?? (typeof label === "string" ? label : undefined)
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.base,
153
+ styles.button,
206
154
 
207
155
  {
208
- minHeight: dimensions.height,
156
+ minHeight: sizeStyle.height,
209
157
 
210
- paddingHorizontal: dimensions.paddingHorizontal,
158
+ paddingHorizontal: sizeStyle.paddingHorizontal,
211
159
 
212
- borderRadius: theme.radius.button,
160
+ borderRadius: sizeStyle.borderRadius,
213
161
 
214
- backgroundColor: colors.background,
162
+ backgroundColor: variantStyle.background,
215
163
 
216
- borderColor: colors.border,
164
+ borderColor: variantStyle.border,
217
165
 
218
- borderWidth: colors.border ? 1 : 0,
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: dimensions.height - 2,
181
+ minHeight: sizeStyle.height - 2,
234
182
 
235
- gap: dimensions.gap,
183
+ gap: sizeStyle.gap,
236
184
  },
237
185
 
238
186
  contentStyle,
239
187
  ]}
240
188
  >
241
189
  {loading ? (
242
- <ActivityIndicator size="small" color={indicatorColor} />
243
- ) : (
244
- leftIcon
245
- )}
246
-
247
- {!loading && label != null && (
248
- <UIText
249
- variant={dimensions.textVariant}
250
- color={colors.text}
251
- style={[styles.label, textStyle]}
252
- numberOfLines={1}
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
- {label}
255
- </UIText>
256
- )}
203
+ {title}
204
+ </ButtonText>
205
+ ) : null}
257
206
 
258
- {!loading && rightIcon && <View>{rightIcon}</View>}
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
- * Variant colors.
266
- */
267
- function getVariantColors(variant, colors) {
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 VARIANTS.outline:
276
+ case BUTTON_VARIANTS.outline:
270
277
  return {
271
- background: colors.transparent,
278
+ background: colors.transparent || "transparent",
272
279
 
273
- border: colors.primary,
280
+ border: primary,
274
281
 
275
- text: colors.primary,
282
+ text: primary,
276
283
 
277
- ripple: colors.primarySoft,
284
+ ripple: primarySoft,
278
285
  };
279
286
 
280
- case VARIANTS.ghost:
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: colors.primary,
293
+ text: primary,
287
294
 
288
- ripple: colors.primarySoft,
295
+ ripple: primarySoft,
289
296
  };
290
297
 
291
- case VARIANTS.soft:
298
+ case BUTTON_VARIANTS.soft:
292
299
  return {
293
- background: colors.primarySoft,
300
+ background: primarySoft,
294
301
 
295
302
  border: null,
296
303
 
297
- text: colors.primary,
304
+ text: primary,
298
305
 
299
- ripple: colors.primary,
306
+ ripple: primary,
300
307
  };
301
308
 
302
- case VARIANTS.danger:
309
+ case BUTTON_VARIANTS.danger:
303
310
  return {
304
- background: colors.danger,
311
+ background: danger,
305
312
 
306
- border: colors.danger,
313
+ border: danger,
307
314
 
308
- text: colors.onPrimary,
315
+ text: onPrimary,
309
316
 
310
- ripple: colors.dangerSoft,
317
+ ripple: danger,
311
318
  };
312
319
 
313
- case VARIANTS.success:
320
+ case BUTTON_VARIANTS.success:
314
321
  return {
315
- background: colors.success,
322
+ background: success,
316
323
 
317
- border: colors.success,
324
+ border: success,
318
325
 
319
- text: colors.onPrimary,
326
+ text: onPrimary,
320
327
 
321
- ripple: colors.successSoft,
328
+ ripple: success,
322
329
  };
323
330
 
324
- case VARIANTS.solid:
331
+ case BUTTON_VARIANTS.solid:
325
332
  default:
326
333
  return {
327
- background: colors.primary,
334
+ background: primary,
328
335
 
329
- border: colors.primary,
336
+ border: primary,
330
337
 
331
- text: colors.onPrimary,
338
+ text: onPrimary,
332
339
 
333
- ripple: colors.primaryPressed,
340
+ ripple: primaryPressed,
334
341
  };
335
342
  }
336
343
  }
337
344
 
338
- /**
339
- * Size dimensions.
340
- */
341
- function getSizeDimensions(size, theme) {
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 SIZES.sm:
353
+ case BUTTON_SIZES.sm:
344
354
  return {
345
- height: theme.sizes.button.sm,
355
+ height: sizes.button.sm,
346
356
 
347
- paddingHorizontal: theme.spacing.md,
357
+ paddingHorizontal: spacing.md,
348
358
 
349
- gap: theme.spacing.xs,
359
+ gap: spacing.xs,
350
360
 
351
- textVariant: "label",
361
+ borderRadius: radius.button,
362
+
363
+ fontSize: 13,
364
+
365
+ lineHeight: 18,
352
366
  };
353
367
 
354
- case SIZES.lg:
368
+ case BUTTON_SIZES.lg:
355
369
  return {
356
- height: theme.sizes.button.lg,
370
+ height: sizes.button.lg,
371
+
372
+ paddingHorizontal: spacing.xl,
357
373
 
358
- paddingHorizontal: theme.spacing.xl,
374
+ gap: spacing.sm,
359
375
 
360
- gap: theme.spacing.sm,
376
+ borderRadius: radius.button,
361
377
 
362
- textVariant: "bodyMedium",
378
+ fontSize: 16,
379
+
380
+ lineHeight: 22,
363
381
  };
364
382
 
365
- case SIZES.xl:
383
+ case BUTTON_SIZES.xl:
366
384
  return {
367
- height: theme.sizes.button.xl,
385
+ height: sizes.button.xl,
386
+
387
+ paddingHorizontal: spacing.xl2,
388
+
389
+ gap: spacing.sm,
368
390
 
369
- paddingHorizontal: theme.spacing.xl2,
391
+ borderRadius: radius.button,
370
392
 
371
- gap: theme.spacing.sm,
393
+ fontSize: 17,
372
394
 
373
- textVariant: "bodyMedium",
395
+ lineHeight: 24,
374
396
  };
375
397
 
376
- case SIZES.md:
398
+ case BUTTON_SIZES.md:
377
399
  default:
378
400
  return {
379
- height: theme.sizes.button.md,
401
+ height: sizes.button.md,
402
+
403
+ paddingHorizontal: spacing.lg,
404
+
405
+ gap: spacing.sm,
380
406
 
381
- paddingHorizontal: theme.spacing.lg,
407
+ borderRadius: radius.button,
382
408
 
383
- gap: theme.spacing.sm,
409
+ fontSize: 14,
384
410
 
385
- textVariant: "label",
411
+ lineHeight: 20,
386
412
  };
387
413
  }
388
414
  }
389
415
 
390
416
  const styles = StyleSheet.create({
391
- base: {
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
- label: {
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 { VARIANTS as UIButtonVariants, SIZES as UIButtonSizes };
453
+ export { BUTTON_VARIANTS as UIButtonVariants, BUTTON_SIZES as UIButtonSizes };
@@ -27,7 +27,7 @@ const UITextComponent = ({
27
27
  }) => {
28
28
  const { theme } = useUITheme();
29
29
 
30
- const typography = theme.typography[variant] || theme.typography.body;
30
+ const typography = theme.typography?.[variant] || theme.typography.body;
31
31
 
32
32
  return (
33
33
  <Text