@webority-technologies/mobile 0.0.7 → 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.
- package/lib/commonjs/components/Badge/Badge.js +23 -13
- package/lib/commonjs/components/BottomSheet/BottomSheet.js +39 -5
- package/lib/commonjs/components/Button/Button.js +25 -6
- package/lib/commonjs/components/Card/Card.js +13 -1
- package/lib/commonjs/components/Checkbox/Checkbox.js +5 -3
- package/lib/commonjs/components/Chip/Chip.js +12 -3
- package/lib/commonjs/components/Dialog/Dialog.js +15 -8
- package/lib/commonjs/components/EmptyState/EmptyState.js +32 -26
- package/lib/commonjs/components/FormField/FormField.js +3 -3
- package/lib/commonjs/components/Input/Input.js +13 -5
- package/lib/commonjs/components/ListItem/ListItem.js +33 -27
- package/lib/commonjs/components/OTPInput/OTPInput.js +6 -3
- package/lib/commonjs/components/Radio/Radio.js +7 -6
- package/lib/commonjs/components/SearchBar/SearchBar.js +9 -5
- package/lib/commonjs/components/Switch/Switch.js +31 -2
- package/lib/commonjs/components/Toast/Toast.js +16 -11
- package/lib/commonjs/theme/Gradient.js +57 -0
- package/lib/commonjs/theme/index.js +20 -0
- package/lib/commonjs/theme/textStyle.js +37 -0
- package/lib/commonjs/theme/tokens.js +260 -2
- package/lib/module/components/Badge/Badge.js +24 -14
- package/lib/module/components/BottomSheet/BottomSheet.js +40 -6
- package/lib/module/components/Button/Button.js +26 -7
- package/lib/module/components/Card/Card.js +14 -2
- package/lib/module/components/Checkbox/Checkbox.js +5 -3
- package/lib/module/components/Chip/Chip.js +13 -4
- package/lib/module/components/Dialog/Dialog.js +16 -9
- package/lib/module/components/EmptyState/EmptyState.js +33 -27
- package/lib/module/components/FormField/FormField.js +4 -4
- package/lib/module/components/Input/Input.js +14 -6
- package/lib/module/components/ListItem/ListItem.js +34 -28
- package/lib/module/components/OTPInput/OTPInput.js +7 -4
- package/lib/module/components/Radio/Radio.js +7 -6
- package/lib/module/components/SearchBar/SearchBar.js +10 -6
- package/lib/module/components/Switch/Switch.js +31 -2
- package/lib/module/components/Toast/Toast.js +17 -12
- package/lib/module/theme/Gradient.js +50 -0
- package/lib/module/theme/index.js +2 -0
- package/lib/module/theme/textStyle.js +32 -0
- package/lib/module/theme/tokens.js +260 -2
- package/lib/typescript/commonjs/components/BottomSheet/BottomSheet.d.ts +10 -0
- package/lib/typescript/commonjs/components/Button/Button.d.ts +8 -0
- package/lib/typescript/commonjs/components/Card/Card.d.ts +8 -0
- package/lib/typescript/commonjs/components/Dialog/Dialog.d.ts +5 -0
- package/lib/typescript/commonjs/components/Input/Input.d.ts +12 -0
- package/lib/typescript/commonjs/components/Switch/Switch.d.ts +5 -0
- package/lib/typescript/commonjs/components/Toast/Toast.d.ts +5 -0
- package/lib/typescript/commonjs/theme/Gradient.d.ts +11 -0
- package/lib/typescript/commonjs/theme/index.d.ts +5 -1
- package/lib/typescript/commonjs/theme/textStyle.d.ts +18 -0
- package/lib/typescript/commonjs/theme/types.d.ts +178 -0
- package/lib/typescript/module/components/BottomSheet/BottomSheet.d.ts +10 -0
- package/lib/typescript/module/components/Button/Button.d.ts +8 -0
- package/lib/typescript/module/components/Card/Card.d.ts +8 -0
- package/lib/typescript/module/components/Dialog/Dialog.d.ts +5 -0
- package/lib/typescript/module/components/Input/Input.d.ts +12 -0
- package/lib/typescript/module/components/Switch/Switch.d.ts +5 -0
- package/lib/typescript/module/components/Toast/Toast.d.ts +5 -0
- package/lib/typescript/module/theme/Gradient.d.ts +11 -0
- package/lib/typescript/module/theme/index.d.ts +5 -1
- package/lib/typescript/module/theme/textStyle.d.ts +18 -0
- package/lib/typescript/module/theme/types.d.ts +178 -0
- package/package.json +5 -1
|
@@ -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:
|
|
64
|
-
left:
|
|
64
|
+
top: o,
|
|
65
|
+
left: o
|
|
65
66
|
};
|
|
66
67
|
case 'bottomRight':
|
|
67
68
|
return {
|
|
68
|
-
bottom:
|
|
69
|
-
right:
|
|
69
|
+
bottom: o,
|
|
70
|
+
right: o
|
|
70
71
|
};
|
|
71
72
|
case 'bottomLeft':
|
|
72
73
|
return {
|
|
73
|
-
bottom:
|
|
74
|
-
left:
|
|
74
|
+
bottom: o,
|
|
75
|
+
left: o
|
|
75
76
|
};
|
|
76
77
|
case 'topRight':
|
|
77
78
|
default:
|
|
78
79
|
return {
|
|
79
|
-
top:
|
|
80
|
-
right:
|
|
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
|
|
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:
|
|
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
|
-
|
|
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
|
-
|
|
241
|
-
|
|
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 =
|
|
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
|
-
|
|
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__*/
|
|
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
|
-
|
|
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:
|
|
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
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
191
|
+
...fontFor(theme, 'bold'),
|
|
183
192
|
lineHeight: sz.closeFont + 2
|
|
184
193
|
},
|
|
185
194
|
allowFontScaling: false,
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
import React, { useCallback, useMemo } from 'react';
|
|
4
4
|
import { ActivityIndicator, 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 { triggerHaptic } from "../../utils/hapticUtils.js";
|
|
7
7
|
import { Modal } from "../Modal/Modal.js";
|
|
8
8
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
@@ -17,11 +17,17 @@ const Dialog = props => {
|
|
|
17
17
|
actions,
|
|
18
18
|
dismissOnAction = true,
|
|
19
19
|
accessibilityLabel,
|
|
20
|
+
contentStyle,
|
|
21
|
+
containerStyle,
|
|
20
22
|
testID
|
|
21
23
|
} = props;
|
|
22
24
|
const theme = useTheme();
|
|
23
25
|
const styles = useMemo(() => buildStyles(theme), [theme]);
|
|
24
26
|
const variantTint = useMemo(() => tintForVariant(theme, variant), [theme, variant]);
|
|
27
|
+
const dialogTokens = theme.components.dialog;
|
|
28
|
+
const iconWrapperSize = dialogTokens?.iconWrapperSize ?? 48;
|
|
29
|
+
const iconWrapperBorderRadius = dialogTokens?.iconWrapperBorderRadius ?? 24;
|
|
30
|
+
const actionButtonMinHeight = dialogTokens?.actionButtonMinHeight ?? 44;
|
|
25
31
|
const handleAction = useCallback(action => {
|
|
26
32
|
if (action.loading) return;
|
|
27
33
|
triggerHaptic('selection');
|
|
@@ -35,13 +41,17 @@ const Dialog = props => {
|
|
|
35
41
|
onRequestClose: onClose,
|
|
36
42
|
presentation: "centered",
|
|
37
43
|
accessibilityLabel: accessibilityLabel ?? title,
|
|
44
|
+
contentStyle: contentStyle,
|
|
38
45
|
testID: testID,
|
|
39
46
|
children: /*#__PURE__*/_jsxs(View, {
|
|
40
47
|
accessibilityRole: 'alertdialog',
|
|
41
48
|
accessibilityLabel: accessibilityLabel ?? title,
|
|
42
|
-
style: styles.container,
|
|
49
|
+
style: [styles.container, containerStyle],
|
|
43
50
|
children: [icon ? /*#__PURE__*/_jsx(View, {
|
|
44
51
|
style: [styles.iconWrapper, {
|
|
52
|
+
width: iconWrapperSize,
|
|
53
|
+
height: iconWrapperSize,
|
|
54
|
+
borderRadius: iconWrapperBorderRadius,
|
|
45
55
|
backgroundColor: variantTint.muted,
|
|
46
56
|
marginBottom: theme.spacing.md
|
|
47
57
|
}],
|
|
@@ -50,7 +60,7 @@ const Dialog = props => {
|
|
|
50
60
|
style: [styles.title, {
|
|
51
61
|
color: theme.colors.text.primary,
|
|
52
62
|
fontSize: theme.typography.fontSize.xl,
|
|
53
|
-
|
|
63
|
+
...fontFor(theme, 'semibold'),
|
|
54
64
|
marginBottom: message ? theme.spacing.sm : theme.spacing.md
|
|
55
65
|
}],
|
|
56
66
|
accessibilityRole: "header",
|
|
@@ -86,6 +96,7 @@ const Dialog = props => {
|
|
|
86
96
|
style: ({
|
|
87
97
|
pressed
|
|
88
98
|
}) => [styles.actionButton, {
|
|
99
|
+
minHeight: actionButtonMinHeight,
|
|
89
100
|
backgroundColor: buttonStyle.backgroundColor,
|
|
90
101
|
borderColor: buttonStyle.borderColor,
|
|
91
102
|
borderWidth: buttonStyle.borderWidth,
|
|
@@ -102,7 +113,7 @@ const Dialog = props => {
|
|
|
102
113
|
style: {
|
|
103
114
|
color: buttonStyle.textColor,
|
|
104
115
|
fontSize: theme.typography.fontSize.base,
|
|
105
|
-
|
|
116
|
+
...fontFor(theme, 'semibold'),
|
|
106
117
|
textAlign: 'center'
|
|
107
118
|
},
|
|
108
119
|
numberOfLines: 1,
|
|
@@ -180,9 +191,6 @@ const buildStyles = _theme => StyleSheet.create({
|
|
|
180
191
|
alignItems: 'stretch'
|
|
181
192
|
},
|
|
182
193
|
iconWrapper: {
|
|
183
|
-
width: 48,
|
|
184
|
-
height: 48,
|
|
185
|
-
borderRadius: 24,
|
|
186
194
|
alignItems: 'center',
|
|
187
195
|
justifyContent: 'center',
|
|
188
196
|
alignSelf: 'center'
|
|
@@ -201,8 +209,7 @@ const buildStyles = _theme => StyleSheet.create({
|
|
|
201
209
|
actionButton: {
|
|
202
210
|
flex: 1,
|
|
203
211
|
alignItems: 'center',
|
|
204
|
-
justifyContent: 'center'
|
|
205
|
-
minHeight: 44
|
|
212
|
+
justifyContent: 'center'
|
|
206
213
|
}
|
|
207
214
|
});
|
|
208
215
|
export { Dialog };
|
|
@@ -2,36 +2,42 @@
|
|
|
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 { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
9
|
-
const
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
return {
|
|
28
|
-
iconSize: 64,
|
|
29
|
-
titleSize: theme.typography.fontSize.xl,
|
|
30
|
-
descriptionSize: theme.typography.fontSize.base,
|
|
31
|
-
paddingVertical: theme.spacing.xl
|
|
32
|
-
};
|
|
9
|
+
const SIZE_FALLBACK = {
|
|
10
|
+
sm: {
|
|
11
|
+
iconSize: 48,
|
|
12
|
+
titleFontSize: 'lg',
|
|
13
|
+
descriptionFontSize: 'sm',
|
|
14
|
+
paddingVertical: 'lg'
|
|
15
|
+
},
|
|
16
|
+
md: {
|
|
17
|
+
iconSize: 64,
|
|
18
|
+
titleFontSize: 'xl',
|
|
19
|
+
descriptionFontSize: 'base',
|
|
20
|
+
paddingVertical: 'xl'
|
|
21
|
+
},
|
|
22
|
+
lg: {
|
|
23
|
+
iconSize: 80,
|
|
24
|
+
titleFontSize: '2xl',
|
|
25
|
+
descriptionFontSize: 'base',
|
|
26
|
+
paddingVertical: '2xl'
|
|
33
27
|
}
|
|
34
28
|
};
|
|
29
|
+
const sizeFor = (theme, size) => {
|
|
30
|
+
const tokens = {
|
|
31
|
+
...SIZE_FALLBACK[size],
|
|
32
|
+
...(theme.components.emptyState?.[size] ?? {})
|
|
33
|
+
};
|
|
34
|
+
return {
|
|
35
|
+
iconSize: tokens.iconSize,
|
|
36
|
+
titleSize: theme.typography.fontSize[tokens.titleFontSize],
|
|
37
|
+
descriptionSize: theme.typography.fontSize[tokens.descriptionFontSize],
|
|
38
|
+
paddingVertical: theme.spacing[tokens.paddingVertical]
|
|
39
|
+
};
|
|
40
|
+
};
|
|
35
41
|
const ActionButton = ({
|
|
36
42
|
action,
|
|
37
43
|
variant
|
|
@@ -110,7 +116,7 @@ const EmptyState = /*#__PURE__*/forwardRef((props, ref) => {
|
|
|
110
116
|
}) : null, /*#__PURE__*/_jsx(Text, {
|
|
111
117
|
style: [styles.title, {
|
|
112
118
|
fontSize: sz.titleSize,
|
|
113
|
-
|
|
119
|
+
...fontFor(theme, 'semibold')
|
|
114
120
|
}],
|
|
115
121
|
children: title
|
|
116
122
|
}), description ? /*#__PURE__*/_jsx(Text, {
|
|
@@ -183,7 +189,7 @@ const buildActionStyles = theme => StyleSheet.create({
|
|
|
183
189
|
},
|
|
184
190
|
buttonText: {
|
|
185
191
|
fontSize: theme.typography.fontSize.base,
|
|
186
|
-
|
|
192
|
+
...fontFor(theme, 'semibold')
|
|
187
193
|
},
|
|
188
194
|
buttonTextPrimary: {
|
|
189
195
|
color: theme.colors.text.inverse
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
import React, { forwardRef, useEffect, useMemo, useRef } from 'react';
|
|
4
4
|
import { Animated, StyleSheet, Text, View } from 'react-native';
|
|
5
|
-
import { useTheme } from "../../theme/index.js";
|
|
5
|
+
import { fontFor, useTheme } from "../../theme/index.js";
|
|
6
6
|
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
7
7
|
const FormField = /*#__PURE__*/forwardRef((props, ref) => {
|
|
8
8
|
const {
|
|
@@ -92,15 +92,15 @@ const buildStyles = theme => StyleSheet.create({
|
|
|
92
92
|
},
|
|
93
93
|
label: {
|
|
94
94
|
fontSize: theme.typography.fontSize.sm,
|
|
95
|
-
|
|
95
|
+
...fontFor(theme, 'medium'),
|
|
96
96
|
color: theme.colors.text.secondary
|
|
97
97
|
},
|
|
98
98
|
labelInline: {
|
|
99
|
-
width: '35%'
|
|
99
|
+
width: theme.components.formField?.inlineLabelWidth ?? '35%'
|
|
100
100
|
},
|
|
101
101
|
requiredMark: {
|
|
102
102
|
color: theme.colors.error,
|
|
103
|
-
|
|
103
|
+
...fontFor(theme, 'medium')
|
|
104
104
|
},
|
|
105
105
|
inputStacked: {
|
|
106
106
|
width: '100%'
|
|
@@ -5,7 +5,7 @@ import { Animated, Easing, Pressable, StyleSheet, Text, TextInput, View } from '
|
|
|
5
5
|
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
6
6
|
// @ts-ignore - react-native-vector-icons ships no bundled types in this version
|
|
7
7
|
import Feather from 'react-native-vector-icons/Feather';
|
|
8
|
-
import { useTheme } from "../../theme/index.js";
|
|
8
|
+
import { fontFor, useTheme } from "../../theme/index.js";
|
|
9
9
|
import { triggerHaptic } from "../../utils/index.js";
|
|
10
10
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
11
11
|
const sizeMap = {
|
|
@@ -55,6 +55,8 @@ const Input = /*#__PURE__*/forwardRef((props, ref) => {
|
|
|
55
55
|
variant = 'outlined',
|
|
56
56
|
required = false,
|
|
57
57
|
maxLength,
|
|
58
|
+
format,
|
|
59
|
+
parse,
|
|
58
60
|
style,
|
|
59
61
|
inputStyle,
|
|
60
62
|
labelStyle,
|
|
@@ -67,7 +69,10 @@ const Input = /*#__PURE__*/forwardRef((props, ref) => {
|
|
|
67
69
|
} = props;
|
|
68
70
|
const theme = useTheme();
|
|
69
71
|
const styles = useMemo(() => buildStyles(theme), [theme]);
|
|
70
|
-
const sizeStyles =
|
|
72
|
+
const sizeStyles = {
|
|
73
|
+
...sizeMap[size],
|
|
74
|
+
...(theme.components.input?.[size] ?? {})
|
|
75
|
+
};
|
|
71
76
|
const [isFocused, setIsFocused] = useState(false);
|
|
72
77
|
const [isPasswordVisible, setIsPasswordVisible] = useState(false);
|
|
73
78
|
const hasValue = typeof value === 'string' && value.length > 0;
|
|
@@ -217,7 +222,7 @@ const Input = /*#__PURE__*/forwardRef((props, ref) => {
|
|
|
217
222
|
style: [styles.staticLabel, {
|
|
218
223
|
color: hasError ? theme.colors.error : isFocused ? theme.colors.border.focus : theme.colors.text.secondary,
|
|
219
224
|
fontSize: theme.typography.fontSize.sm,
|
|
220
|
-
|
|
225
|
+
...fontFor(theme, 'medium'),
|
|
221
226
|
marginBottom: theme.spacing.xxs
|
|
222
227
|
}, labelStyle],
|
|
223
228
|
children: [label, required ? /*#__PURE__*/_jsx(Text, {
|
|
@@ -251,7 +256,7 @@ const Input = /*#__PURE__*/forwardRef((props, ref) => {
|
|
|
251
256
|
left: leftPad,
|
|
252
257
|
color: labelColor,
|
|
253
258
|
fontSize: sizeStyles.fontSize,
|
|
254
|
-
|
|
259
|
+
...fontFor(theme, 'medium'),
|
|
255
260
|
backgroundColor: shouldFloat && variant === 'outlined' ? theme.colors.background.primary : 'transparent',
|
|
256
261
|
paddingHorizontal: shouldFloat && variant === 'outlined' ? 4 : 0,
|
|
257
262
|
transform: [{
|
|
@@ -277,8 +282,11 @@ const Input = /*#__PURE__*/forwardRef((props, ref) => {
|
|
|
277
282
|
}, inputStyle],
|
|
278
283
|
placeholder: showFloatingLabel && !shouldFloat ? undefined : placeholder,
|
|
279
284
|
placeholderTextColor: placeholderTextColor,
|
|
280
|
-
value: value,
|
|
281
|
-
onChangeText:
|
|
285
|
+
value: format && value != null ? format(value) : value,
|
|
286
|
+
onChangeText: text => {
|
|
287
|
+
if (!onChangeText) return;
|
|
288
|
+
onChangeText(parse ? parse(text) : text);
|
|
289
|
+
},
|
|
282
290
|
onFocus: handleFocus,
|
|
283
291
|
onBlur: handleBlur,
|
|
284
292
|
editable: isEditable,
|