@webority-technologies/mobile 0.0.6 → 0.0.8

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.
Files changed (92) hide show
  1. package/README.md +3 -463
  2. package/lib/commonjs/components/Badge/Badge.js +23 -13
  3. package/lib/commonjs/components/BottomSheet/BottomSheet.js +39 -5
  4. package/lib/commonjs/components/Button/Button.js +25 -6
  5. package/lib/commonjs/components/Card/Card.js +13 -1
  6. package/lib/commonjs/components/Checkbox/Checkbox.js +5 -3
  7. package/lib/commonjs/components/Chip/Chip.js +12 -3
  8. package/lib/commonjs/components/Dialog/Dialog.js +15 -8
  9. package/lib/commonjs/components/EmptyState/EmptyState.js +32 -26
  10. package/lib/commonjs/components/FormField/FormField.js +3 -3
  11. package/lib/commonjs/components/Input/Input.js +13 -5
  12. package/lib/commonjs/components/ListItem/ListItem.js +33 -27
  13. package/lib/commonjs/components/OTPInput/OTPInput.js +6 -3
  14. package/lib/commonjs/components/Radio/Radio.js +7 -6
  15. package/lib/commonjs/components/SearchBar/SearchBar.js +9 -5
  16. package/lib/commonjs/components/Skeleton/Skeleton.js +20 -12
  17. package/lib/commonjs/components/Skeleton/SkeletonContent.js +25 -9
  18. package/lib/commonjs/components/Skeleton/SkeletonList.js +7 -2
  19. package/lib/commonjs/components/Skeleton/SkeletonProvider.js +48 -0
  20. package/lib/commonjs/components/Skeleton/SkeletonSkip.js +37 -0
  21. package/lib/commonjs/components/Skeleton/index.js +20 -0
  22. package/lib/commonjs/components/Switch/Switch.js +31 -2
  23. package/lib/commonjs/components/Toast/Toast.js +16 -11
  24. package/lib/commonjs/components/index.js +18 -0
  25. package/lib/commonjs/theme/Gradient.js +57 -0
  26. package/lib/commonjs/theme/index.js +20 -0
  27. package/lib/commonjs/theme/textStyle.js +37 -0
  28. package/lib/commonjs/theme/tokens.js +260 -2
  29. package/lib/module/components/Badge/Badge.js +24 -14
  30. package/lib/module/components/BottomSheet/BottomSheet.js +40 -6
  31. package/lib/module/components/Button/Button.js +26 -7
  32. package/lib/module/components/Card/Card.js +14 -2
  33. package/lib/module/components/Checkbox/Checkbox.js +5 -3
  34. package/lib/module/components/Chip/Chip.js +13 -4
  35. package/lib/module/components/Dialog/Dialog.js +16 -9
  36. package/lib/module/components/EmptyState/EmptyState.js +33 -27
  37. package/lib/module/components/FormField/FormField.js +4 -4
  38. package/lib/module/components/Input/Input.js +14 -6
  39. package/lib/module/components/ListItem/ListItem.js +34 -28
  40. package/lib/module/components/OTPInput/OTPInput.js +7 -4
  41. package/lib/module/components/Radio/Radio.js +7 -6
  42. package/lib/module/components/SearchBar/SearchBar.js +10 -6
  43. package/lib/module/components/Skeleton/Skeleton.js +20 -12
  44. package/lib/module/components/Skeleton/SkeletonContent.js +25 -9
  45. package/lib/module/components/Skeleton/SkeletonList.js +7 -2
  46. package/lib/module/components/Skeleton/SkeletonProvider.js +41 -0
  47. package/lib/module/components/Skeleton/SkeletonSkip.js +31 -0
  48. package/lib/module/components/Skeleton/index.js +2 -0
  49. package/lib/module/components/Switch/Switch.js +31 -2
  50. package/lib/module/components/Toast/Toast.js +17 -12
  51. package/lib/module/components/index.js +1 -1
  52. package/lib/module/theme/Gradient.js +50 -0
  53. package/lib/module/theme/index.js +2 -0
  54. package/lib/module/theme/textStyle.js +32 -0
  55. package/lib/module/theme/tokens.js +260 -2
  56. package/lib/typescript/commonjs/components/BottomSheet/BottomSheet.d.ts +10 -0
  57. package/lib/typescript/commonjs/components/Button/Button.d.ts +8 -0
  58. package/lib/typescript/commonjs/components/Card/Card.d.ts +8 -0
  59. package/lib/typescript/commonjs/components/Dialog/Dialog.d.ts +5 -0
  60. package/lib/typescript/commonjs/components/Input/Input.d.ts +12 -0
  61. package/lib/typescript/commonjs/components/Skeleton/Skeleton.d.ts +9 -0
  62. package/lib/typescript/commonjs/components/Skeleton/SkeletonContent.d.ts +6 -0
  63. package/lib/typescript/commonjs/components/Skeleton/SkeletonList.d.ts +3 -0
  64. package/lib/typescript/commonjs/components/Skeleton/SkeletonProvider.d.ts +32 -0
  65. package/lib/typescript/commonjs/components/Skeleton/SkeletonSkip.d.ts +25 -0
  66. package/lib/typescript/commonjs/components/Skeleton/index.d.ts +4 -0
  67. package/lib/typescript/commonjs/components/Switch/Switch.d.ts +5 -0
  68. package/lib/typescript/commonjs/components/Toast/Toast.d.ts +5 -0
  69. package/lib/typescript/commonjs/components/index.d.ts +2 -2
  70. package/lib/typescript/commonjs/theme/Gradient.d.ts +11 -0
  71. package/lib/typescript/commonjs/theme/index.d.ts +5 -1
  72. package/lib/typescript/commonjs/theme/textStyle.d.ts +18 -0
  73. package/lib/typescript/commonjs/theme/types.d.ts +178 -0
  74. package/lib/typescript/module/components/BottomSheet/BottomSheet.d.ts +10 -0
  75. package/lib/typescript/module/components/Button/Button.d.ts +8 -0
  76. package/lib/typescript/module/components/Card/Card.d.ts +8 -0
  77. package/lib/typescript/module/components/Dialog/Dialog.d.ts +5 -0
  78. package/lib/typescript/module/components/Input/Input.d.ts +12 -0
  79. package/lib/typescript/module/components/Skeleton/Skeleton.d.ts +9 -0
  80. package/lib/typescript/module/components/Skeleton/SkeletonContent.d.ts +6 -0
  81. package/lib/typescript/module/components/Skeleton/SkeletonList.d.ts +3 -0
  82. package/lib/typescript/module/components/Skeleton/SkeletonProvider.d.ts +32 -0
  83. package/lib/typescript/module/components/Skeleton/SkeletonSkip.d.ts +25 -0
  84. package/lib/typescript/module/components/Skeleton/index.d.ts +4 -0
  85. package/lib/typescript/module/components/Switch/Switch.d.ts +5 -0
  86. package/lib/typescript/module/components/Toast/Toast.d.ts +5 -0
  87. package/lib/typescript/module/components/index.d.ts +2 -2
  88. package/lib/typescript/module/theme/Gradient.d.ts +11 -0
  89. package/lib/typescript/module/theme/index.d.ts +5 -1
  90. package/lib/typescript/module/theme/textStyle.d.ts +18 -0
  91. package/lib/typescript/module/theme/types.d.ts +178 -0
  92. package/package.json +5 -1
@@ -54,6 +54,260 @@ const radius = {
54
54
  '2xl': 28,
55
55
  full: 9999
56
56
  };
57
+ const components = {
58
+ button: {
59
+ xs: {
60
+ paddingHorizontal: 10,
61
+ paddingVertical: 4,
62
+ minHeight: 28,
63
+ fontSize: 12,
64
+ borderRadius: 8
65
+ },
66
+ sm: {
67
+ paddingHorizontal: 12,
68
+ paddingVertical: 6,
69
+ minHeight: 34,
70
+ fontSize: 13,
71
+ borderRadius: 10
72
+ },
73
+ md: {
74
+ paddingHorizontal: 16,
75
+ paddingVertical: 9,
76
+ minHeight: 42,
77
+ fontSize: 15,
78
+ borderRadius: 12
79
+ },
80
+ lg: {
81
+ paddingHorizontal: 20,
82
+ paddingVertical: 12,
83
+ minHeight: 50,
84
+ fontSize: 16,
85
+ borderRadius: 14
86
+ },
87
+ xl: {
88
+ paddingHorizontal: 24,
89
+ paddingVertical: 14,
90
+ minHeight: 58,
91
+ fontSize: 17,
92
+ borderRadius: 16
93
+ }
94
+ },
95
+ input: {
96
+ sm: {
97
+ paddingHorizontal: 12,
98
+ paddingVertical: 8,
99
+ minHeight: 38,
100
+ multilineMinHeight: 72,
101
+ fontSize: 13,
102
+ borderRadius: 10,
103
+ iconSize: 16
104
+ },
105
+ md: {
106
+ paddingHorizontal: 14,
107
+ paddingVertical: 11,
108
+ minHeight: 46,
109
+ multilineMinHeight: 92,
110
+ fontSize: 15,
111
+ borderRadius: 12,
112
+ iconSize: 18
113
+ },
114
+ lg: {
115
+ paddingHorizontal: 16,
116
+ paddingVertical: 14,
117
+ minHeight: 54,
118
+ multilineMinHeight: 110,
119
+ fontSize: 16,
120
+ borderRadius: 14,
121
+ iconSize: 20
122
+ }
123
+ },
124
+ searchBar: {
125
+ sm: {
126
+ height: 36,
127
+ paddingHorizontal: 10,
128
+ fontSize: 13,
129
+ iconSize: 16,
130
+ gap: 6
131
+ },
132
+ md: {
133
+ height: 44,
134
+ paddingHorizontal: 12,
135
+ fontSize: 15,
136
+ iconSize: 18,
137
+ gap: 8
138
+ },
139
+ lg: {
140
+ height: 52,
141
+ paddingHorizontal: 14,
142
+ fontSize: 16,
143
+ iconSize: 20,
144
+ gap: 10
145
+ },
146
+ cancelButtonWidth: 72
147
+ },
148
+ emptyState: {
149
+ sm: {
150
+ iconSize: 48,
151
+ titleFontSize: 'lg',
152
+ descriptionFontSize: 'sm',
153
+ paddingVertical: 'lg'
154
+ },
155
+ md: {
156
+ iconSize: 64,
157
+ titleFontSize: 'xl',
158
+ descriptionFontSize: 'base',
159
+ paddingVertical: 'xl'
160
+ },
161
+ lg: {
162
+ iconSize: 80,
163
+ titleFontSize: '2xl',
164
+ descriptionFontSize: 'base',
165
+ paddingVertical: '2xl'
166
+ }
167
+ },
168
+ listItem: {
169
+ sm: {
170
+ paddingVertical: 'sm',
171
+ titleFontSize: 'sm',
172
+ subtitleFontSize: 'xs',
173
+ minHeight: 44
174
+ },
175
+ md: {
176
+ paddingVertical: 'md',
177
+ titleFontSize: 'base',
178
+ subtitleFontSize: 'sm',
179
+ minHeight: 56
180
+ },
181
+ lg: {
182
+ paddingVertical: 'lg',
183
+ titleFontSize: 'lg',
184
+ subtitleFontSize: 'sm',
185
+ minHeight: 72
186
+ }
187
+ },
188
+ badge: {
189
+ sm: {
190
+ fontSize: 10,
191
+ minWidth: 16,
192
+ height: 16,
193
+ paddingHorizontal: 5,
194
+ dotSize: 8
195
+ },
196
+ md: {
197
+ fontSize: 11,
198
+ minWidth: 20,
199
+ height: 20,
200
+ paddingHorizontal: 6,
201
+ dotSize: 10
202
+ },
203
+ borderWidth: 1.5,
204
+ anchorOffset: 4
205
+ },
206
+ chip: {
207
+ sm: {
208
+ paddingHorizontal: 10,
209
+ paddingVertical: 4,
210
+ fontSize: 12,
211
+ minHeight: 26,
212
+ closeSize: 16,
213
+ closeFontSize: 12,
214
+ gap: 6
215
+ },
216
+ md: {
217
+ paddingHorizontal: 12,
218
+ paddingVertical: 6,
219
+ fontSize: 13,
220
+ minHeight: 32,
221
+ closeSize: 18,
222
+ closeFontSize: 13,
223
+ gap: 8
224
+ }
225
+ },
226
+ checkbox: {
227
+ sm: {
228
+ boxSize: 16
229
+ },
230
+ md: {
231
+ boxSize: 20
232
+ },
233
+ lg: {
234
+ boxSize: 24
235
+ },
236
+ borderWidth: 1.5,
237
+ labelGap: 10
238
+ },
239
+ radio: {
240
+ sm: {
241
+ outer: 16,
242
+ inner: 8
243
+ },
244
+ md: {
245
+ outer: 20,
246
+ inner: 10
247
+ },
248
+ lg: {
249
+ outer: 24,
250
+ inner: 12
251
+ },
252
+ borderWidth: 1.5,
253
+ labelGap: 10
254
+ },
255
+ switch: {
256
+ sm: {
257
+ trackWidth: 42,
258
+ trackHeight: 26,
259
+ thumbSize: 22,
260
+ padding: 2
261
+ },
262
+ md: {
263
+ trackWidth: 51,
264
+ trackHeight: 31,
265
+ thumbSize: 27,
266
+ padding: 2
267
+ },
268
+ lg: {
269
+ trackWidth: 60,
270
+ trackHeight: 36,
271
+ thumbSize: 32,
272
+ padding: 2
273
+ },
274
+ thumbColor: '#FFFFFF'
275
+ },
276
+ otpInput: {
277
+ sm: {
278
+ cell: 36,
279
+ fontSize: 16,
280
+ borderRadius: 8,
281
+ gap: 8
282
+ },
283
+ md: {
284
+ cell: 48,
285
+ fontSize: 20,
286
+ borderRadius: 10,
287
+ gap: 10
288
+ },
289
+ lg: {
290
+ cell: 56,
291
+ fontSize: 24,
292
+ borderRadius: 12,
293
+ gap: 12
294
+ }
295
+ },
296
+ dialog: {
297
+ iconWrapperSize: 48,
298
+ iconWrapperBorderRadius: 24,
299
+ actionButtonMinHeight: 44
300
+ },
301
+ toast: {
302
+ iconCircleSize: 28,
303
+ iconCircleBorderRadius: 14,
304
+ iconGlyphFontSize: 16,
305
+ tintBarWidth: 4
306
+ },
307
+ formField: {
308
+ inlineLabelWidth: '35%'
309
+ }
310
+ };
57
311
  const motion = {
58
312
  duration: {
59
313
  instant: 80,
@@ -262,7 +516,9 @@ const lightTheme = exports.lightTheme = {
262
516
  spacing,
263
517
  radius,
264
518
  shadows: lightShadows,
265
- motion
519
+ motion,
520
+ components,
521
+ gradients: {}
266
522
  };
267
523
  const darkTheme = exports.darkTheme = {
268
524
  mode: 'dark',
@@ -314,6 +570,8 @@ const darkTheme = exports.darkTheme = {
314
570
  spacing,
315
571
  radius,
316
572
  shadows: darkShadows,
317
- motion
573
+ motion,
574
+ components,
575
+ gradients: {}
318
576
  };
319
577
  //# sourceMappingURL=tokens.js.map
@@ -2,7 +2,7 @@
2
2
 
3
3
  import React, { forwardRef, useEffect, useMemo, useRef } from 'react';
4
4
  import { Animated, Easing, StyleSheet, Text, View } from 'react-native';
5
- import { useTheme } from "../../theme/index.js";
5
+ import { fontFor, useTheme } from "../../theme/index.js";
6
6
  import { SkeletonContent } from "../Skeleton/index.js";
7
7
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
8
8
  const toneFor = (theme, tone) => {
@@ -56,28 +56,29 @@ const sizeMap = {
56
56
  dot: 10
57
57
  }
58
58
  };
59
- const anchorPosition = anchor => {
59
+ const anchorPosition = (anchor, offset) => {
60
+ const o = -offset;
60
61
  switch (anchor) {
61
62
  case 'topLeft':
62
63
  return {
63
- top: -4,
64
- left: -4
64
+ top: o,
65
+ left: o
65
66
  };
66
67
  case 'bottomRight':
67
68
  return {
68
- bottom: -4,
69
- right: -4
69
+ bottom: o,
70
+ right: o
70
71
  };
71
72
  case 'bottomLeft':
72
73
  return {
73
- bottom: -4,
74
- left: -4
74
+ bottom: o,
75
+ left: o
75
76
  };
76
77
  case 'topRight':
77
78
  default:
78
79
  return {
79
- top: -4,
80
- right: -4
80
+ top: o,
81
+ right: o
81
82
  };
82
83
  }
83
84
  };
@@ -110,7 +111,16 @@ const Badge = /*#__PURE__*/forwardRef((props, ref) => {
110
111
  } = props;
111
112
  const theme = useTheme();
112
113
  const tones = useMemo(() => toneFor(theme, tone), [theme, tone]);
113
- const sz = sizeMap[size];
114
+ const overrides = theme.components.badge?.[size];
115
+ const sz = {
116
+ fontSize: overrides?.fontSize ?? sizeMap[size].fontSize,
117
+ minWidth: overrides?.minWidth ?? sizeMap[size].minWidth,
118
+ height: overrides?.height ?? sizeMap[size].height,
119
+ paddingH: overrides?.paddingHorizontal ?? sizeMap[size].paddingH,
120
+ dot: overrides?.dotSize ?? sizeMap[size].dot
121
+ };
122
+ const badgeBorderWidth = theme.components.badge?.borderWidth ?? 1.5;
123
+ const badgeAnchorOffset = theme.components.badge?.anchorOffset ?? 4;
114
124
  const formatted = variant === 'dot' ? null : formatValue(value, max);
115
125
  const shouldRender = !invisible && (variant === 'dot' || formatted !== null);
116
126
  const pulseScale = useRef(new Animated.Value(1)).current;
@@ -156,9 +166,9 @@ const Badge = /*#__PURE__*/forwardRef((props, ref) => {
156
166
  }]
157
167
  }, children ? {
158
168
  position: 'absolute',
159
- borderWidth: 1.5,
169
+ borderWidth: badgeBorderWidth,
160
170
  borderColor: theme.colors.background.elevated,
161
- ...anchorPosition(anchor)
171
+ ...anchorPosition(anchor, badgeAnchorOffset)
162
172
  } : null, badgeStyle],
163
173
  accessible: true,
164
174
  accessibilityRole: a11yRole,
@@ -167,7 +177,7 @@ const Badge = /*#__PURE__*/forwardRef((props, ref) => {
167
177
  style: [styles.text, {
168
178
  color: tones.text,
169
179
  fontSize: sz.fontSize,
170
- fontWeight: theme.typography.fontWeight.bold
180
+ ...fontFor(theme, 'bold')
171
181
  }, textStyle],
172
182
  numberOfLines: 1,
173
183
  allowFontScaling: false,
@@ -20,7 +20,7 @@
20
20
  */
21
21
 
22
22
  import React, { forwardRef, useCallback, useEffect, useImperativeHandle, useMemo, useRef, useState } from 'react';
23
- import { Dimensions, Pressable, StyleSheet, View } from 'react-native';
23
+ import { Dimensions, Keyboard, Platform, Pressable, StyleSheet, View } from 'react-native';
24
24
  import { Gesture, GestureDetector } from 'react-native-gesture-handler';
25
25
  import Animated, { Extrapolation, interpolate, runOnJS, useAnimatedStyle, useSharedValue, withSpring, withTiming } from 'react-native-reanimated';
26
26
  import { useSafeAreaInsets } from 'react-native-safe-area-context';
@@ -43,6 +43,7 @@ const BottomSheet = /*#__PURE__*/forwardRef((props, ref) => {
43
43
  enablePanDownToClose = true,
44
44
  enableBackdropPress = true,
45
45
  backdropOpacity = 0.5,
46
+ keyboardBehavior = 'none',
46
47
  handleIndicatorStyle,
47
48
  containerStyle,
48
49
  children,
@@ -235,12 +236,45 @@ const BottomSheet = /*#__PURE__*/forwardRef((props, ref) => {
235
236
  });
236
237
  }, [closedY, dragStartY, enablePanDownToClose, handleSnapEnd, minTopY, snapTargets, translateY]);
237
238
 
239
+ // ───────── Keyboard tracking ─────────
240
+ // keyboardOffset is added to translateY in sheetStyle so we don't disturb
241
+ // snap-point math. iOS gets keyboardWillShow/Hide (smoother), Android only
242
+ // emits keyboardDidShow/Hide.
243
+ const keyboardOffset = useSharedValue(0);
244
+ useEffect(() => {
245
+ if (keyboardBehavior === 'none') return;
246
+ const showEvt = Platform.OS === 'ios' ? 'keyboardWillShow' : 'keyboardDidShow';
247
+ const hideEvt = Platform.OS === 'ios' ? 'keyboardWillHide' : 'keyboardDidHide';
248
+ const onShow = e => {
249
+ const h = e.endCoordinates?.height ?? 0;
250
+ keyboardOffset.value = withTiming(-h, {
251
+ duration: 220
252
+ });
253
+ };
254
+ const onHide = () => {
255
+ keyboardOffset.value = withTiming(0, {
256
+ duration: 220
257
+ });
258
+ };
259
+ const showSub = Keyboard.addListener(showEvt, onShow);
260
+ const hideSub = Keyboard.addListener(hideEvt, onHide);
261
+ return () => {
262
+ showSub.remove();
263
+ hideSub.remove();
264
+ };
265
+ }, [keyboardBehavior, keyboardOffset]);
266
+
238
267
  // ───────── Animated styles ─────────
239
- const sheetStyle = useAnimatedStyle(() => ({
240
- transform: [{
241
- translateY: translateY.value
242
- }]
243
- }));
268
+ const sheetStyle = useAnimatedStyle(() => {
269
+ // Don't push past the screen top — keyboard offset is clamped to minTopY.
270
+ const yWithKb = translateY.value + keyboardOffset.value;
271
+ const clamped = yWithKb < minTopY ? minTopY : yWithKb;
272
+ return {
273
+ transform: [{
274
+ translateY: clamped
275
+ }]
276
+ };
277
+ });
244
278
  const backdropStyle = useAnimatedStyle(() => {
245
279
  // 0 opacity when sheet is closed, full backdropOpacity at minSnap height (and above).
246
280
  const closedAt = screenHeight;
@@ -2,7 +2,7 @@
2
2
 
3
3
  import React, { forwardRef, useMemo } from 'react';
4
4
  import { Animated, Pressable, StyleSheet, Text, View } from 'react-native';
5
- import { useTheme } from "../../theme/index.js";
5
+ import { fontFor, Gradient, useTheme } from "../../theme/index.js";
6
6
  import { usePressAnimation } from "../../hooks/usePressAnimation.js";
7
7
  import { triggerHaptic } from "../../utils/hapticUtils.js";
8
8
  import { Spinner } from "../Spinner/index.js";
@@ -21,6 +21,7 @@ const Button = /*#__PURE__*/forwardRef((props, ref) => {
21
21
  rightIcon,
22
22
  haptic = 'selection',
23
23
  rounded = false,
24
+ gradient,
24
25
  style,
25
26
  textStyle,
26
27
  pressAnimation = true,
@@ -40,9 +41,22 @@ const Button = /*#__PURE__*/forwardRef((props, ref) => {
40
41
  enabled: pressAnimation && isInteractive
41
42
  });
42
43
  const styles = useMemo(() => buildStyles(theme), [theme]);
43
- const sizeStyles = sizeMap[size];
44
+ const sizeStyles = {
45
+ ...sizeMap[size],
46
+ ...(theme.components.button?.[size] ?? {})
47
+ };
44
48
  const toneColors = useMemo(() => toneFor(theme, tone), [theme, tone]);
45
49
  const variantStyles = useMemo(() => variantFor(theme, variant, toneColors, disabled), [theme, variant, toneColors, disabled]);
50
+
51
+ // Resolve gradient: string token → theme.gradients[token]; literal passes through.
52
+ // Skipped when disabled (parity with disabled flat-color treatment).
53
+ const resolvedGradient = useMemo(() => {
54
+ if (!gradient || disabled || variant !== 'solid') return null;
55
+ if (typeof gradient === 'string') {
56
+ return theme.gradients[gradient] ?? null;
57
+ }
58
+ return gradient;
59
+ }, [gradient, disabled, variant, theme.gradients]);
46
60
  const handlePress = event => {
47
61
  if (!isInteractive) return;
48
62
  if (haptic !== false) triggerHaptic(haptic);
@@ -64,7 +78,7 @@ const Button = /*#__PURE__*/forwardRef((props, ref) => {
64
78
  style: [styles.label, {
65
79
  color: variantStyles.textColor,
66
80
  fontSize: sizeStyles.fontSize,
67
- fontWeight: theme.typography.fontWeight.semibold
81
+ ...fontFor(theme, 'semibold')
68
82
  }, textStyle],
69
83
  numberOfLines: 1,
70
84
  children: title
@@ -80,7 +94,7 @@ const Button = /*#__PURE__*/forwardRef((props, ref) => {
80
94
  scale
81
95
  }]
82
96
  }, fullWidth ? styles.fullWidth : null],
83
- children: /*#__PURE__*/_jsx(Pressable, {
97
+ children: /*#__PURE__*/_jsxs(Pressable, {
84
98
  ref: ref,
85
99
  onPress: handlePress,
86
100
  onPressIn: pressIn,
@@ -108,15 +122,20 @@ const Button = /*#__PURE__*/forwardRef((props, ref) => {
108
122
  paddingVertical: sizeStyles.paddingVertical,
109
123
  minHeight: sizeStyles.minHeight,
110
124
  borderRadius: rounded ? theme.radius.full : sizeStyles.borderRadius,
111
- backgroundColor: variantStyles.backgroundColor,
125
+ // Hide solid bg when a gradient layer covers it; preserve outline borders.
126
+ backgroundColor: resolvedGradient ? 'transparent' : variantStyles.backgroundColor,
112
127
  borderWidth: variantStyles.borderWidth,
113
128
  borderColor: variantStyles.borderColor,
114
- opacity: !isInteractive ? 0.55 : 1
129
+ opacity: !isInteractive ? 0.55 : 1,
130
+ overflow: resolvedGradient ? 'hidden' : undefined
115
131
  }, pressed && variant !== 'solid' ? {
116
132
  backgroundColor: theme.colors.surface.pressed
117
133
  } : null, fullWidth ? styles.fullWidth : null, style],
118
134
  ...rest,
119
- children: content
135
+ children: [resolvedGradient ? /*#__PURE__*/_jsx(Gradient, {
136
+ gradient: resolvedGradient,
137
+ style: StyleSheet.absoluteFill
138
+ }) : null, content]
120
139
  })
121
140
  });
122
141
  });
@@ -2,7 +2,7 @@
2
2
 
3
3
  import React, { forwardRef, useMemo } from 'react';
4
4
  import { Animated, Image, Pressable, StyleSheet, View } from 'react-native';
5
- import { useTheme } from "../../theme/index.js";
5
+ import { Gradient, useTheme } from "../../theme/index.js";
6
6
  import { usePressAnimation } from "../../hooks/usePressAnimation.js";
7
7
  import { triggerHaptic } from "../../utils/hapticUtils.js";
8
8
  import { SkeletonContent } from "../Skeleton/index.js";
@@ -29,6 +29,7 @@ const Card = /*#__PURE__*/forwardRef((props, ref) => {
29
29
  imageAspectRatio,
30
30
  imageOverlay,
31
31
  loading = false,
32
+ gradient,
32
33
  onPress,
33
34
  accessibilityLabel,
34
35
  accessibilityHint,
@@ -49,6 +50,11 @@ const Card = /*#__PURE__*/forwardRef((props, ref) => {
49
50
  const styles = useMemo(() => buildStyles(theme), [theme]);
50
51
  const hasImage = Boolean(imageSource);
51
52
  const contentPadding = theme.spacing[paddingMap[padding]];
53
+ const resolvedGradient = useMemo(() => {
54
+ if (!gradient) return null;
55
+ if (typeof gradient === 'string') return theme.gradients[gradient] ?? null;
56
+ return gradient;
57
+ }, [gradient, theme.gradients]);
52
58
  const containerStyle = useMemo(() => {
53
59
  const base = {
54
60
  borderRadius: theme.radius[radius],
@@ -108,7 +114,7 @@ const Card = /*#__PURE__*/forwardRef((props, ref) => {
108
114
  children: footer
109
115
  }) : null]
110
116
  });
111
- const content = hasImage ? /*#__PURE__*/_jsxs(_Fragment, {
117
+ const baseContent = hasImage ? /*#__PURE__*/_jsxs(_Fragment, {
112
118
  children: [/*#__PURE__*/_jsxs(View, {
113
119
  style: styles.imageWrapper,
114
120
  children: [/*#__PURE__*/_jsx(Image, {
@@ -129,6 +135,12 @@ const Card = /*#__PURE__*/forwardRef((props, ref) => {
129
135
  children: innerContent
130
136
  })]
131
137
  }) : innerContent;
138
+ const content = resolvedGradient ? /*#__PURE__*/_jsxs(_Fragment, {
139
+ children: [/*#__PURE__*/_jsx(Gradient, {
140
+ gradient: resolvedGradient,
141
+ style: StyleSheet.absoluteFillObject
142
+ }), baseContent]
143
+ }) : baseContent;
132
144
  let rendered;
133
145
  if (isInteractive) {
134
146
  const handlePress = event => {
@@ -41,7 +41,9 @@ const Checkbox = /*#__PURE__*/forwardRef((props, ref) => {
41
41
  } = props;
42
42
  const theme = useTheme();
43
43
  const styles = useMemo(() => buildStyles(theme), [theme]);
44
- const boxSize = sizeMap[size];
44
+ const boxSize = theme.components.checkbox?.[size]?.boxSize ?? sizeMap[size];
45
+ const checkboxBorderWidth = theme.components.checkbox?.borderWidth ?? 1.5;
46
+ const checkboxLabelGap = theme.components.checkbox?.labelGap ?? 10;
45
47
  const fillColor = toneColor(theme, tone);
46
48
  const isActive = checked || indeterminate;
47
49
  const progress = useRef(new Animated.Value(isActive ? 1 : 0)).current;
@@ -93,6 +95,7 @@ const Checkbox = /*#__PURE__*/forwardRef((props, ref) => {
93
95
  style: [styles.box, {
94
96
  width: boxSize,
95
97
  height: boxSize,
98
+ borderWidth: checkboxBorderWidth,
96
99
  borderRadius: theme.radius.xs,
97
100
  borderColor,
98
101
  backgroundColor
@@ -123,6 +126,7 @@ const Checkbox = /*#__PURE__*/forwardRef((props, ref) => {
123
126
  })
124
127
  }), label ? /*#__PURE__*/_jsx(Text, {
125
128
  style: [styles.label, {
129
+ marginLeft: checkboxLabelGap,
126
130
  color: disabled ? theme.colors.text.disabled : theme.colors.text.primary,
127
131
  fontSize: theme.typography.fontSize.base
128
132
  }],
@@ -138,7 +142,6 @@ const buildStyles = _theme => StyleSheet.create({
138
142
  alignItems: 'center'
139
143
  },
140
144
  box: {
141
- borderWidth: 1.5,
142
145
  alignItems: 'center',
143
146
  justifyContent: 'center'
144
147
  },
@@ -152,7 +155,6 @@ const buildStyles = _theme => StyleSheet.create({
152
155
  includeFontPadding: false
153
156
  },
154
157
  label: {
155
- marginLeft: 10,
156
158
  flexShrink: 1
157
159
  }
158
160
  });
@@ -2,7 +2,7 @@
2
2
 
3
3
  import React, { forwardRef, useMemo } from 'react';
4
4
  import { Animated, Pressable, StyleSheet, Text, View } from 'react-native';
5
- import { useTheme } from "../../theme/index.js";
5
+ import { fontFor, useTheme } from "../../theme/index.js";
6
6
  import { usePressAnimation } from "../../hooks/usePressAnimation.js";
7
7
  import { triggerHaptic } from "../../utils/hapticUtils.js";
8
8
  import { SkeletonContent } from "../Skeleton/index.js";
@@ -113,7 +113,16 @@ const Chip = /*#__PURE__*/forwardRef((props, ref) => {
113
113
  enabled: isPressable
114
114
  });
115
115
  const tones = useMemo(() => toneFor(theme, tone), [theme, tone]);
116
- const sz = sizeMap[size];
116
+ const overrides = theme.components.chip?.[size];
117
+ const sz = {
118
+ paddingH: overrides?.paddingHorizontal ?? sizeMap[size].paddingH,
119
+ paddingV: overrides?.paddingVertical ?? sizeMap[size].paddingV,
120
+ fontSize: overrides?.fontSize ?? sizeMap[size].fontSize,
121
+ minHeight: overrides?.minHeight ?? sizeMap[size].minHeight,
122
+ closeSize: overrides?.closeSize ?? sizeMap[size].closeSize,
123
+ closeFont: overrides?.closeFontSize ?? sizeMap[size].closeFont,
124
+ gap: overrides?.gap ?? sizeMap[size].gap
125
+ };
117
126
  const isFilled = variant === 'filled';
118
127
  const backgroundColor = (() => {
119
128
  if (selected) return isFilled ? tones.selectedBg : 'transparent';
@@ -153,7 +162,7 @@ const Chip = /*#__PURE__*/forwardRef((props, ref) => {
153
162
  style: [styles.label, {
154
163
  color: textColor,
155
164
  fontSize: sz.fontSize,
156
- fontWeight: theme.typography.fontWeight.medium
165
+ ...fontFor(theme, 'medium')
157
166
  }, textStyle],
158
167
  numberOfLines: 1,
159
168
  children: label ?? ' '
@@ -179,7 +188,7 @@ const Chip = /*#__PURE__*/forwardRef((props, ref) => {
179
188
  style: {
180
189
  color: textColor,
181
190
  fontSize: sz.closeFont,
182
- fontWeight: theme.typography.fontWeight.bold,
191
+ ...fontFor(theme, 'bold'),
183
192
  lineHeight: sz.closeFont + 2
184
193
  },
185
194
  allowFontScaling: false,