rnnovaui 0.1.7 → 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,6 +1,6 @@
1
1
  {
2
2
  "name": "rnnovaui",
3
- "version": "0.1.7",
3
+ "version": "0.2.0",
4
4
  "description": "",
5
5
  "main": "src/index.js",
6
6
  "react-native": "src/index.js",
@@ -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 UIIconButtonComponent = ({
31
- icon,
31
+ const FALLBACK_COLORS = {
32
+ primary: "#FF5A1F",
33
+ primarySoft: "#FFF0EA",
34
+ primaryPressed: "#E94D17",
32
35
 
33
- size = "md",
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
- activeOpacity = 0.82,
56
-
57
- android_ripple = true,
75
+ hitSlop,
58
76
 
59
- hitSlop = 8,
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 safeSize = SIZES[size] ? size : SIZES.md;
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 dimensions = getDimensions(safeSize, theme);
80
-
81
- const colors = getColors(safeVariant, theme.colors);
91
+ const resolvedColors = useMemo(
92
+ () => getVariantColors(variant, colors, isDisabled),
93
+ [variant, colors, isDisabled],
94
+ );
82
95
 
83
- const borderRadius = getBorderRadius(safeShape, theme);
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 ripple = android_ripple
130
- ? {
131
- color: colors.ripple,
132
- borderless: false,
133
- }
134
- : undefined;
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={({ pressed }) => [
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={colors.icon} />
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 getDimensions(size, theme) {
188
- switch (size) {
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
- case SIZES.sm:
195
- return {
196
- size: theme.sizes.button.sm,
197
- };
208
+ const primarySoft = colors.primarySoft || FALLBACK_COLORS.primarySoft;
198
209
 
199
- case SIZES.lg:
200
- return {
201
- size: theme.sizes.button.lg,
202
- };
210
+ const primaryPressed =
211
+ colors.primaryPressed || FALLBACK_COLORS.primaryPressed;
203
212
 
204
- case SIZES.xl:
205
- return {
206
- size: theme.sizes.button.xl,
207
- };
213
+ const success = colors.success || FALLBACK_COLORS.success;
208
214
 
209
- case SIZES.md:
210
- default:
211
- return {
212
- size: theme.sizes.button.md,
213
- };
214
- }
215
- }
215
+ const successPressed =
216
+ colors.successPressed || FALLBACK_COLORS.successPressed;
216
217
 
217
- function getBorderRadius(shape, theme) {
218
- switch (shape) {
219
- case SHAPES.rounded:
220
- return theme.radius.lg;
218
+ const danger = colors.danger || FALLBACK_COLORS.danger;
221
219
 
222
- case SHAPES.square:
223
- return theme.radius.sm;
220
+ const dangerPressed = colors.dangerPressed || FALLBACK_COLORS.dangerPressed;
224
221
 
225
- case SHAPES.circle:
226
- default:
227
- return theme.radius.circle;
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
- icon: colors.onPrimary,
247
+ borderWidth: 1,
240
248
 
241
- ripple: colors.primaryPressed,
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: colors.transparent,
256
+ background: "transparent",
257
+
258
+ border: colors.buttonOutlineBorder || primary,
247
259
 
248
- border: colors.borderStrong,
260
+ borderWidth: 1,
249
261
 
250
- icon: colors.text,
262
+ icon: colors.buttonOutlineText || primary,
251
263
 
252
- ripple: colors.surfaceSecondary,
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: null,
271
+ border: colors.buttonSoftBackground || primarySoft,
260
272
 
261
- icon: colors.primary,
273
+ borderWidth: 1,
262
274
 
263
- ripple: colors.primary,
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
- border: colors.danger,
286
+ borderWidth: 1,
271
287
 
272
- icon: colors.onPrimary,
288
+ icon: colors.buttonDangerText || white,
273
289
 
274
- ripple: colors.dangerSoft,
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
- icon: colors.onPrimary,
299
+ borderWidth: 1,
284
300
 
285
- ripple: colors.successSoft,
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: colors.transparent,
309
+ background: "transparent",
310
+
311
+ border: "transparent",
292
312
 
293
- border: null,
313
+ borderWidth: 0,
294
314
 
295
- icon: colors.text,
315
+ icon: colors.buttonGhostText || primary,
296
316
 
297
- ripple: colors.surfaceSecondary,
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;
@@ -1,6 +1,6 @@
1
1
  export {
2
2
  UIIconButton,
3
- UIIconButtonSizes,
4
3
  UIIconButtonVariants,
4
+ UIIconButtonSizes,
5
5
  UIIconButtonShapes,
6
6
  } from "./UIIconButton";
@@ -2,7 +2,7 @@ export { UIText } from "./Text";
2
2
  export { UIButton, UIButtonVariants, UIButtonSizes } from "./Button";
3
3
  export {
4
4
  UIIconButton,
5
- UIIconButtonSizes,
6
5
  UIIconButtonVariants,
6
+ UIIconButtonSizes,
7
7
  UIIconButtonShapes,
8
8
  } from "./IconButton";
package/src/index.js CHANGED
@@ -21,7 +21,7 @@ export {
21
21
  UIButtonVariants,
22
22
  UIButtonSizes,
23
23
  UIIconButton,
24
- UIIconButtonSizes,
25
24
  UIIconButtonVariants,
25
+ UIIconButtonSizes,
26
26
  UIIconButtonShapes,
27
27
  } from "./components";