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