@sudobility/components-rn 1.0.41 → 1.0.43
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/dist/index.cjs.js +1092 -473
- package/dist/index.cjs.js.map +1 -1
- package/dist/index.esm.js +1095 -476
- package/dist/index.esm.js.map +1 -1
- package/dist/ui/Alert/Alert.d.ts.map +1 -1
- package/dist/ui/Avatar/Avatar.d.ts.map +1 -1
- package/dist/ui/Badge/Badge.d.ts.map +1 -1
- package/dist/ui/Banner/Banner.d.ts.map +1 -1
- package/dist/ui/Breadcrumb/Breadcrumb.d.ts.map +1 -1
- package/dist/ui/BreadcrumbNav/BreadcrumbNav.d.ts.map +1 -1
- package/dist/ui/CTASection/CTASection.d.ts.map +1 -1
- package/dist/ui/Calendar/Calendar.d.ts.map +1 -1
- package/dist/ui/ChainBadge/ChainBadge.d.ts.map +1 -1
- package/dist/ui/Checkbox/Checkbox.d.ts +0 -22
- package/dist/ui/Checkbox/Checkbox.d.ts.map +1 -1
- package/dist/ui/Code/Code.d.ts +0 -17
- package/dist/ui/Code/Code.d.ts.map +1 -1
- package/dist/ui/CodeDisplay/CodeDisplay.d.ts +0 -21
- package/dist/ui/CodeDisplay/CodeDisplay.d.ts.map +1 -1
- package/dist/ui/CollapsibleSection/CollapsibleSection.d.ts.map +1 -1
- package/dist/ui/Combobox/Combobox.d.ts.map +1 -1
- package/dist/ui/Command/Command.d.ts.map +1 -1
- package/dist/ui/DashboardStatCard/DashboardStatCard.d.ts +0 -17
- package/dist/ui/DashboardStatCard/DashboardStatCard.d.ts.map +1 -1
- package/dist/ui/DataList/DataList.d.ts.map +1 -1
- package/dist/ui/Divider/Divider.d.ts.map +1 -1
- package/dist/ui/Dropdown/Dropdown.d.ts.map +1 -1
- package/dist/ui/ExternalLink/ExternalLink.d.ts.map +1 -1
- package/dist/ui/FeatureCard/FeatureCard.d.ts.map +1 -1
- package/dist/ui/FeatureGrid/FeatureGrid.d.ts.map +1 -1
- package/dist/ui/GradientIconContainer/GradientIconContainer.d.ts +0 -13
- package/dist/ui/GradientIconContainer/GradientIconContainer.d.ts.map +1 -1
- package/dist/ui/Heading/Heading.d.ts.map +1 -1
- package/dist/ui/HelperText/HelperText.d.ts.map +1 -1
- package/dist/ui/IconContainer/IconContainer.d.ts +0 -13
- package/dist/ui/IconContainer/IconContainer.d.ts.map +1 -1
- package/dist/ui/IconText/IconText.d.ts.map +1 -1
- package/dist/ui/InfiniteScroll/InfiniteScroll.d.ts.map +1 -1
- package/dist/ui/InfoBox/InfoBox.d.ts.map +1 -1
- package/dist/ui/Input/Input.d.ts.map +1 -1
- package/dist/ui/KeyValuePair/KeyValuePair.d.ts.map +1 -1
- package/dist/ui/Label/Label.d.ts.map +1 -1
- package/dist/ui/Link/Link.d.ts.map +1 -1
- package/dist/ui/ListItemWithAction/ListItemWithAction.d.ts.map +1 -1
- package/dist/ui/Modal/Modal.d.ts.map +1 -1
- package/dist/ui/MultiSelect/MultiSelect.d.ts.map +1 -1
- package/dist/ui/NavigationList/NavigationList.d.ts.map +1 -1
- package/dist/ui/PageSectionHeader/PageSectionHeader.d.ts.map +1 -1
- package/dist/ui/Pagination/Pagination.d.ts.map +1 -1
- package/dist/ui/PhoneInput/PhoneInput.d.ts.map +1 -1
- package/dist/ui/PopupSelect/PopupSelect.d.ts.map +1 -1
- package/dist/ui/Progress/Progress.d.ts +0 -15
- package/dist/ui/Progress/Progress.d.ts.map +1 -1
- package/dist/ui/ProgressCircle/ProgressCircle.d.ts.map +1 -1
- package/dist/ui/PromotionalBanner/PromotionalBanner.d.ts.map +1 -1
- package/dist/ui/QuickActions/QuickActions.d.ts.map +1 -1
- package/dist/ui/SearchInput/SearchInput.d.ts.map +1 -1
- package/dist/ui/SectionHeader/SectionHeader.d.ts.map +1 -1
- package/dist/ui/Select/Select.d.ts.map +1 -1
- package/dist/ui/SettingsList/SettingsList.d.ts.map +1 -1
- package/dist/ui/Sheet/Sheet.d.ts.map +1 -1
- package/dist/ui/SideNav/SideNav.d.ts.map +1 -1
- package/dist/ui/SmartLink/SmartLink.d.ts.map +1 -1
- package/dist/ui/Spinner/Spinner.d.ts.map +1 -1
- package/dist/ui/StatDisplay/StatDisplay.d.ts +0 -12
- package/dist/ui/StatDisplay/StatDisplay.d.ts.map +1 -1
- package/dist/ui/StepList/StepList.d.ts.map +1 -1
- package/dist/ui/Table/Table.d.ts.map +1 -1
- package/dist/ui/Tabs/Tabs.d.ts.map +1 -1
- package/dist/ui/Text/Text.d.ts.map +1 -1
- package/dist/ui/TextArea/TextArea.d.ts.map +1 -1
- package/dist/ui/TextInputModal/TextInputModal.d.ts.map +1 -1
- package/dist/ui/Toast/Toast.d.ts.map +1 -1
- package/dist/ui/Tooltip/Tooltip.d.ts +0 -20
- package/dist/ui/Tooltip/Tooltip.d.ts.map +1 -1
- package/dist/ui/TransferList/TransferList.d.ts.map +1 -1
- package/package.json +5 -4
- package/src/__tests__/alert.test.tsx +20 -10
- package/src/ui/Alert/Alert.tsx +13 -5
- package/src/ui/Avatar/Avatar.tsx +6 -5
- package/src/ui/Badge/Badge.tsx +61 -26
- package/src/ui/Banner/Banner.tsx +36 -25
- package/src/ui/Breadcrumb/Breadcrumb.tsx +8 -5
- package/src/ui/BreadcrumbNav/BreadcrumbNav.tsx +22 -3
- package/src/ui/CTASection/CTASection.tsx +8 -6
- package/src/ui/Calendar/Calendar.tsx +35 -6
- package/src/ui/Card/Card.tsx +2 -2
- package/src/ui/ChainBadge/ChainBadge.tsx +67 -42
- package/src/ui/Checkbox/Checkbox.tsx +47 -20
- package/src/ui/Code/Code.tsx +51 -21
- package/src/ui/CodeDisplay/CodeDisplay.tsx +46 -20
- package/src/ui/CollapsibleSection/CollapsibleSection.tsx +7 -3
- package/src/ui/Combobox/Combobox.tsx +2 -1
- package/src/ui/Command/Command.tsx +2 -1
- package/src/ui/DashboardStatCard/DashboardStatCard.tsx +29 -11
- package/src/ui/DataList/DataList.tsx +23 -5
- package/src/ui/Divider/Divider.tsx +12 -17
- package/src/ui/Dropdown/Dropdown.tsx +4 -1
- package/src/ui/ExternalLink/ExternalLink.tsx +5 -4
- package/src/ui/FeatureCard/FeatureCard.tsx +60 -29
- package/src/ui/FeatureGrid/FeatureGrid.tsx +7 -7
- package/src/ui/GradientIconContainer/GradientIconContainer.tsx +33 -8
- package/src/ui/Heading/Heading.tsx +15 -38
- package/src/ui/HelperText/HelperText.tsx +9 -8
- package/src/ui/IconContainer/IconContainer.tsx +26 -9
- package/src/ui/IconText/IconText.tsx +6 -5
- package/src/ui/InfiniteScroll/InfiniteScroll.tsx +2 -1
- package/src/ui/InfoBox/InfoBox.tsx +35 -17
- package/src/ui/Input/Input.tsx +10 -3
- package/src/ui/KeyValuePair/KeyValuePair.tsx +12 -5
- package/src/ui/Label/Label.tsx +3 -1
- package/src/ui/Link/Link.tsx +6 -5
- package/src/ui/ListItemWithAction/ListItemWithAction.tsx +2 -1
- package/src/ui/Modal/Modal.tsx +16 -2
- package/src/ui/MultiSelect/MultiSelect.tsx +2 -1
- package/src/ui/NavigationList/NavigationList.tsx +17 -3
- package/src/ui/PageSectionHeader/PageSectionHeader.tsx +2 -1
- package/src/ui/Pagination/Pagination.tsx +9 -6
- package/src/ui/PhoneInput/PhoneInput.tsx +3 -2
- package/src/ui/PopupSelect/PopupSelect.tsx +15 -14
- package/src/ui/Progress/Progress.tsx +63 -14
- package/src/ui/ProgressCircle/ProgressCircle.tsx +7 -6
- package/src/ui/PromotionalBanner/PromotionalBanner.tsx +7 -4
- package/src/ui/QuickActions/QuickActions.tsx +13 -9
- package/src/ui/SearchInput/SearchInput.tsx +3 -2
- package/src/ui/SectionHeader/SectionHeader.tsx +4 -1
- package/src/ui/Select/Select.tsx +20 -5
- package/src/ui/SettingsList/SettingsList.tsx +4 -1
- package/src/ui/Sheet/Sheet.tsx +20 -3
- package/src/ui/SideNav/SideNav.tsx +11 -2
- package/src/ui/SmartLink/SmartLink.tsx +6 -3
- package/src/ui/Spinner/Spinner.tsx +8 -6
- package/src/ui/StatDisplay/StatDisplay.tsx +59 -23
- package/src/ui/StepList/StepList.tsx +25 -3
- package/src/ui/Table/Table.tsx +22 -9
- package/src/ui/Tabs/Tabs.tsx +7 -2
- package/src/ui/Text/Text.tsx +19 -52
- package/src/ui/TextArea/TextArea.tsx +2 -1
- package/src/ui/TextInputModal/TextInputModal.tsx +2 -1
- package/src/ui/Toast/Toast.tsx +49 -14
- package/src/ui/Tooltip/Tooltip.tsx +47 -9
- package/src/ui/TransferList/TransferList.tsx +2 -1
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import * as React from 'react';
|
|
2
2
|
import { View, Text, Animated } from 'react-native';
|
|
3
3
|
import { cn } from '../../lib/utils';
|
|
4
|
+
import { colors, designTokens } from '@sudobility/design';
|
|
4
5
|
|
|
5
6
|
export interface ProgressProps {
|
|
6
7
|
/** Progress value (0-100) */
|
|
@@ -36,6 +37,48 @@ export interface ProgressProps {
|
|
|
36
37
|
* <Progress indeterminate />
|
|
37
38
|
* ```
|
|
38
39
|
*/
|
|
40
|
+
|
|
41
|
+
// Lazily derive progress colors from DS to avoid ESM issues in tests.
|
|
42
|
+
let _progressColors: ReturnType<typeof buildProgressColors> | null = null;
|
|
43
|
+
function getProgressColors() {
|
|
44
|
+
if (!_progressColors) _progressColors = buildProgressColors();
|
|
45
|
+
return _progressColors;
|
|
46
|
+
}
|
|
47
|
+
function buildProgressColors() {
|
|
48
|
+
// Extract the leading bg-* class from DS button base strings
|
|
49
|
+
function extractBg(base: string, darkStr: string) {
|
|
50
|
+
const bg =
|
|
51
|
+
base
|
|
52
|
+
.split(' ')
|
|
53
|
+
.find(
|
|
54
|
+
c =>
|
|
55
|
+
c.startsWith('bg-') &&
|
|
56
|
+
!c.includes('hover:') &&
|
|
57
|
+
!c.includes('active:')
|
|
58
|
+
) || '';
|
|
59
|
+
const darkBg =
|
|
60
|
+
darkStr
|
|
61
|
+
.split(' ')
|
|
62
|
+
.find(
|
|
63
|
+
c =>
|
|
64
|
+
c.startsWith('dark:bg-') &&
|
|
65
|
+
!c.includes('hover:') &&
|
|
66
|
+
!c.includes('active:')
|
|
67
|
+
) || '';
|
|
68
|
+
return `${bg} ${darkBg}`;
|
|
69
|
+
}
|
|
70
|
+
const btn = colors.component.button;
|
|
71
|
+
return {
|
|
72
|
+
default: extractBg(btn.primary.base, btn.primary.dark),
|
|
73
|
+
primary: extractBg(btn.primary.base, btn.primary.dark),
|
|
74
|
+
success: extractBg(btn.success.base, btn.success.dark),
|
|
75
|
+
warning: 'bg-yellow-600 dark:bg-yellow-500', // DS has no yellow button; local fallback
|
|
76
|
+
danger: extractBg(btn.destructive.base, btn.destructive.dark),
|
|
77
|
+
purple: 'bg-purple-600 dark:bg-purple-500', // DS has no purple button; local fallback
|
|
78
|
+
gray: 'bg-gray-600 dark:bg-gray-500', // local fallback
|
|
79
|
+
} as Record<string, string>;
|
|
80
|
+
}
|
|
81
|
+
|
|
39
82
|
export const Progress: React.FC<ProgressProps> = ({
|
|
40
83
|
value = 0,
|
|
41
84
|
max = 100,
|
|
@@ -71,12 +114,13 @@ export const Progress: React.FC<ProgressProps> = ({
|
|
|
71
114
|
// Clamp value between 0 and 100
|
|
72
115
|
const percentage = Math.min(Math.max((value / max) * 100, 0), 100);
|
|
73
116
|
|
|
74
|
-
// Color configurations
|
|
117
|
+
// Color configurations from DS
|
|
118
|
+
const allColors = getProgressColors();
|
|
75
119
|
const colorClasses = {
|
|
76
|
-
default:
|
|
77
|
-
success:
|
|
78
|
-
warning:
|
|
79
|
-
danger:
|
|
120
|
+
default: allColors.default,
|
|
121
|
+
success: allColors.success,
|
|
122
|
+
warning: allColors.warning,
|
|
123
|
+
danger: allColors.danger,
|
|
80
124
|
};
|
|
81
125
|
|
|
82
126
|
// Size configurations
|
|
@@ -119,7 +163,9 @@ export const Progress: React.FC<ProgressProps> = ({
|
|
|
119
163
|
</View>
|
|
120
164
|
{(showLabel || label) && (
|
|
121
165
|
<View className='mt-1'>
|
|
122
|
-
<Text
|
|
166
|
+
<Text
|
|
167
|
+
className={`${designTokens.typography.size.xs} text-gray-600 dark:text-gray-400 text-right`}
|
|
168
|
+
>
|
|
123
169
|
{label || `${Math.round(percentage)}%`}
|
|
124
170
|
</Text>
|
|
125
171
|
</View>
|
|
@@ -173,14 +219,15 @@ export const ProgressBar: React.FC<ProgressBarProps> = ({
|
|
|
173
219
|
const percentage = Math.min(Math.max((value / max) * 100, 0), 100);
|
|
174
220
|
const displayLabel = label || `${Math.round(percentage)}%`;
|
|
175
221
|
|
|
176
|
-
// Color variant configurations
|
|
222
|
+
// Color variant configurations from DS
|
|
223
|
+
const progressColors = getProgressColors();
|
|
177
224
|
const variantClasses = {
|
|
178
|
-
primary:
|
|
179
|
-
success:
|
|
180
|
-
warning:
|
|
181
|
-
danger:
|
|
182
|
-
purple:
|
|
183
|
-
gray:
|
|
225
|
+
primary: progressColors.primary,
|
|
226
|
+
success: progressColors.success,
|
|
227
|
+
warning: progressColors.warning,
|
|
228
|
+
danger: progressColors.danger,
|
|
229
|
+
purple: progressColors.purple,
|
|
230
|
+
gray: progressColors.gray,
|
|
184
231
|
};
|
|
185
232
|
|
|
186
233
|
// Size configurations
|
|
@@ -211,7 +258,9 @@ export const ProgressBar: React.FC<ProgressBarProps> = ({
|
|
|
211
258
|
/>
|
|
212
259
|
</View>
|
|
213
260
|
{showLabel && labelPosition === 'outside' && (
|
|
214
|
-
<Text
|
|
261
|
+
<Text
|
|
262
|
+
className={`${designTokens.typography.size.sm} ${designTokens.typography.weight.medium} text-gray-600 dark:text-gray-400`}
|
|
263
|
+
>
|
|
215
264
|
{displayLabel}
|
|
216
265
|
</Text>
|
|
217
266
|
)}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import * as React from 'react';
|
|
2
2
|
import { View, Text } from 'react-native';
|
|
3
3
|
import { cn } from '../../lib/utils';
|
|
4
|
+
import { colors } from '@sudobility/design';
|
|
4
5
|
|
|
5
6
|
export interface ProgressCircleProps {
|
|
6
7
|
/** Progress value (0-100) */
|
|
@@ -48,18 +49,18 @@ export const ProgressCircle: React.FC<ProgressCircleProps> = ({
|
|
|
48
49
|
label,
|
|
49
50
|
variant = 'primary',
|
|
50
51
|
color,
|
|
51
|
-
trackColor =
|
|
52
|
+
trackColor = colors.raw.neutral[200],
|
|
52
53
|
className,
|
|
53
54
|
}) => {
|
|
54
55
|
// Clamp value between 0 and 100
|
|
55
56
|
const progress = Math.min(100, Math.max(0, value));
|
|
56
57
|
|
|
57
|
-
// Color variants
|
|
58
|
+
// Color variants from design system raw palette
|
|
58
59
|
const variantColors = {
|
|
59
|
-
primary:
|
|
60
|
-
success:
|
|
61
|
-
warning:
|
|
62
|
-
danger:
|
|
60
|
+
primary: colors.raw.blue[600],
|
|
61
|
+
success: colors.raw.green[600],
|
|
62
|
+
warning: colors.raw.amber[600],
|
|
63
|
+
danger: colors.raw.red[600],
|
|
63
64
|
};
|
|
64
65
|
|
|
65
66
|
const progressColor = color || variantColors[variant];
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import * as React from 'react';
|
|
2
2
|
import { View, Text, Pressable } from 'react-native';
|
|
3
3
|
import { cn } from '../../lib/utils';
|
|
4
|
+
import { colors } from '@sudobility/design';
|
|
4
5
|
|
|
5
6
|
export interface PromotionalBannerProps {
|
|
6
7
|
/** Banner title */
|
|
@@ -52,8 +53,10 @@ export const PromotionalBanner: React.FC<PromotionalBannerProps> = ({
|
|
|
52
53
|
return (
|
|
53
54
|
<View
|
|
54
55
|
className={cn(
|
|
55
|
-
|
|
56
|
-
|
|
56
|
+
// Derive green palette from DS alert.success colors
|
|
57
|
+
colors.component.alert.success.base,
|
|
58
|
+
colors.component.alert.success.dark,
|
|
59
|
+
'border-b',
|
|
57
60
|
isProminent && 'border-b-2',
|
|
58
61
|
className
|
|
59
62
|
)}
|
|
@@ -62,7 +65,7 @@ export const PromotionalBanner: React.FC<PromotionalBannerProps> = ({
|
|
|
62
65
|
<View className='flex-row items-center justify-between gap-4 flex-wrap'>
|
|
63
66
|
{/* Left side: Badge + Title */}
|
|
64
67
|
<View className='flex-row items-center flex-1'>
|
|
65
|
-
{/* Badge */}
|
|
68
|
+
{/* Badge -- green-500 from colors.raw.green */}
|
|
66
69
|
<View className='bg-green-500 px-3 py-1 rounded-full mr-3'>
|
|
67
70
|
<Text className='text-white text-xs font-bold'>{badgeText}</Text>
|
|
68
71
|
</View>
|
|
@@ -85,7 +88,7 @@ export const PromotionalBanner: React.FC<PromotionalBannerProps> = ({
|
|
|
85
88
|
</View>
|
|
86
89
|
</View>
|
|
87
90
|
|
|
88
|
-
{/* CTA Button */}
|
|
91
|
+
{/* CTA Button -- success button from DS */}
|
|
89
92
|
<Pressable
|
|
90
93
|
onPress={onButtonPress}
|
|
91
94
|
className={cn(
|
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
import * as React from 'react';
|
|
2
2
|
import { View, Text, Pressable } from 'react-native';
|
|
3
3
|
import { cn } from '../../lib/utils';
|
|
4
|
+
import { designTokens } from '@sudobility/design';
|
|
5
|
+
|
|
6
|
+
const { typography } = designTokens;
|
|
4
7
|
|
|
5
8
|
export interface QuickAction {
|
|
6
9
|
/** Unique identifier */
|
|
@@ -53,6 +56,7 @@ export const QuickActions: React.FC<QuickActionsProps> = ({
|
|
|
53
56
|
columns = 3,
|
|
54
57
|
className,
|
|
55
58
|
}) => {
|
|
59
|
+
// Variant styles aligned with DS button colors (colors.component.button)
|
|
56
60
|
const variantStyles = {
|
|
57
61
|
default: {
|
|
58
62
|
bg: 'bg-white dark:bg-gray-900 border-gray-200 dark:border-gray-700',
|
|
@@ -60,23 +64,23 @@ export const QuickActions: React.FC<QuickActionsProps> = ({
|
|
|
60
64
|
text: 'text-gray-900 dark:text-white',
|
|
61
65
|
},
|
|
62
66
|
primary: {
|
|
63
|
-
bg: 'bg-blue-
|
|
64
|
-
bgActive: 'active:bg-blue-
|
|
67
|
+
bg: 'bg-blue-600 border-blue-600',
|
|
68
|
+
bgActive: 'active:bg-blue-800',
|
|
65
69
|
text: 'text-white',
|
|
66
70
|
},
|
|
67
71
|
success: {
|
|
68
|
-
bg: 'bg-green-
|
|
69
|
-
bgActive: 'active:bg-green-
|
|
72
|
+
bg: 'bg-green-600 border-green-600',
|
|
73
|
+
bgActive: 'active:bg-green-800',
|
|
70
74
|
text: 'text-white',
|
|
71
75
|
},
|
|
72
76
|
warning: {
|
|
73
|
-
bg: 'bg-
|
|
74
|
-
bgActive: 'active:bg-
|
|
77
|
+
bg: 'bg-orange-600 border-orange-600',
|
|
78
|
+
bgActive: 'active:bg-orange-800',
|
|
75
79
|
text: 'text-white',
|
|
76
80
|
},
|
|
77
81
|
danger: {
|
|
78
|
-
bg: 'bg-red-
|
|
79
|
-
bgActive: 'active:bg-red-
|
|
82
|
+
bg: 'bg-red-600 border-red-600',
|
|
83
|
+
bgActive: 'active:bg-red-800',
|
|
80
84
|
text: 'text-white',
|
|
81
85
|
},
|
|
82
86
|
};
|
|
@@ -121,7 +125,7 @@ export const QuickActions: React.FC<QuickActionsProps> = ({
|
|
|
121
125
|
accessibilityState={{ disabled: action.disabled }}
|
|
122
126
|
>
|
|
123
127
|
{action.icon && <View className='w-5 h-5'>{action.icon}</View>}
|
|
124
|
-
<Text className={cn(
|
|
128
|
+
<Text className={cn(typography.weight.medium, styles.text)}>
|
|
125
129
|
{action.label}
|
|
126
130
|
</Text>
|
|
127
131
|
</Pressable>
|
|
@@ -9,6 +9,7 @@ import {
|
|
|
9
9
|
TextInputProps,
|
|
10
10
|
} from 'react-native';
|
|
11
11
|
import { cn } from '../../lib/utils';
|
|
12
|
+
import { colors } from '@sudobility/design';
|
|
12
13
|
|
|
13
14
|
export interface SearchInputProps extends Omit<TextInputProps, 'onChange'> {
|
|
14
15
|
/** Current search query */
|
|
@@ -137,7 +138,7 @@ export const SearchInput: React.FC<SearchInputProps> = ({
|
|
|
137
138
|
disabled && 'opacity-50',
|
|
138
139
|
loading && 'opacity-60'
|
|
139
140
|
)}
|
|
140
|
-
placeholderTextColor=
|
|
141
|
+
placeholderTextColor={colors.raw.neutral[400]}
|
|
141
142
|
accessibilityRole='search'
|
|
142
143
|
accessibilityState={{ disabled }}
|
|
143
144
|
{...textInputProps}
|
|
@@ -159,7 +160,7 @@ export const SearchInput: React.FC<SearchInputProps> = ({
|
|
|
159
160
|
{/* Loading Spinner */}
|
|
160
161
|
{loading && (
|
|
161
162
|
<View className='absolute inset-y-0 right-0 flex items-center justify-center pr-3'>
|
|
162
|
-
<ActivityIndicator size='small' color=
|
|
163
|
+
<ActivityIndicator size='small' color={colors.raw.neutral[400]} />
|
|
163
164
|
</View>
|
|
164
165
|
)}
|
|
165
166
|
</View>
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import * as React from 'react';
|
|
2
2
|
import { View, Text, Pressable, ActivityIndicator } from 'react-native';
|
|
3
3
|
import { cn } from '../../lib/utils';
|
|
4
|
+
import { colors } from '@sudobility/design';
|
|
4
5
|
|
|
5
6
|
export interface SectionHeaderProps {
|
|
6
7
|
/** The header text/title */
|
|
@@ -53,7 +54,9 @@ export const SectionHeader: React.FC<SectionHeaderProps> = ({
|
|
|
53
54
|
{title}
|
|
54
55
|
</Text>
|
|
55
56
|
<View className='flex-row items-center gap-2'>
|
|
56
|
-
{loading &&
|
|
57
|
+
{loading && (
|
|
58
|
+
<ActivityIndicator size='small' color={colors.raw.blue[600]} />
|
|
59
|
+
)}
|
|
57
60
|
{actions}
|
|
58
61
|
{onAdd && (
|
|
59
62
|
<Pressable
|
package/src/ui/Select/Select.tsx
CHANGED
|
@@ -9,6 +9,9 @@ import {
|
|
|
9
9
|
SafeAreaView,
|
|
10
10
|
} from 'react-native';
|
|
11
11
|
import { cn } from '../../lib/utils';
|
|
12
|
+
import { designTokens } from '@sudobility/design';
|
|
13
|
+
|
|
14
|
+
const { typography } = designTokens;
|
|
12
15
|
|
|
13
16
|
export interface SelectOption {
|
|
14
17
|
label: string;
|
|
@@ -92,9 +95,9 @@ export const Select: React.FC<SelectProps> = ({
|
|
|
92
95
|
<View className='flex flex-row items-center justify-between'>
|
|
93
96
|
<Text
|
|
94
97
|
className={cn(
|
|
95
|
-
|
|
98
|
+
typography.size.base,
|
|
96
99
|
item.value === value
|
|
97
|
-
?
|
|
100
|
+
? `text-blue-600 dark:text-blue-400 ${typography.weight.medium}`
|
|
98
101
|
: 'text-gray-900 dark:text-gray-100'
|
|
99
102
|
)}
|
|
100
103
|
>
|
|
@@ -125,7 +128,8 @@ export const Select: React.FC<SelectProps> = ({
|
|
|
125
128
|
>
|
|
126
129
|
<Text
|
|
127
130
|
className={cn(
|
|
128
|
-
|
|
131
|
+
typography.size.base,
|
|
132
|
+
'flex-1',
|
|
129
133
|
selectedOption
|
|
130
134
|
? 'text-gray-900 dark:text-gray-100'
|
|
131
135
|
: 'text-gray-400 dark:text-gray-500'
|
|
@@ -149,11 +153,22 @@ export const Select: React.FC<SelectProps> = ({
|
|
|
149
153
|
{/* Header */}
|
|
150
154
|
<View className='flex flex-row items-center justify-between px-4 py-3 border-b border-gray-200 dark:border-gray-700'>
|
|
151
155
|
<Pressable onPress={() => setIsOpen(false)}>
|
|
152
|
-
<Text
|
|
156
|
+
<Text
|
|
157
|
+
className={cn(
|
|
158
|
+
'text-blue-600 dark:text-blue-400',
|
|
159
|
+
typography.size.base
|
|
160
|
+
)}
|
|
161
|
+
>
|
|
153
162
|
Cancel
|
|
154
163
|
</Text>
|
|
155
164
|
</Pressable>
|
|
156
|
-
<Text
|
|
165
|
+
<Text
|
|
166
|
+
className={cn(
|
|
167
|
+
typography.size.base,
|
|
168
|
+
typography.weight.semibold,
|
|
169
|
+
'text-gray-900 dark:text-white'
|
|
170
|
+
)}
|
|
171
|
+
>
|
|
157
172
|
{title}
|
|
158
173
|
</Text>
|
|
159
174
|
<View style={{ width: 60 }} />
|
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
import * as React from 'react';
|
|
2
2
|
import { View, Text, Pressable } from 'react-native';
|
|
3
3
|
import { cn } from '../../lib/utils';
|
|
4
|
+
import { designTokens } from '@sudobility/design';
|
|
5
|
+
|
|
6
|
+
const { typography } = designTokens;
|
|
4
7
|
|
|
5
8
|
/**
|
|
6
9
|
* Setting item interface
|
|
@@ -88,7 +91,7 @@ export const SettingsList: React.FC<SettingsListProps> = ({
|
|
|
88
91
|
<View className='flex-1 min-w-0'>
|
|
89
92
|
<Text
|
|
90
93
|
className={cn(
|
|
91
|
-
|
|
94
|
+
typography.size.sm,
|
|
92
95
|
isSelected
|
|
93
96
|
? 'text-orange-700 dark:text-orange-300'
|
|
94
97
|
: 'text-gray-700 dark:text-gray-300'
|
package/src/ui/Sheet/Sheet.tsx
CHANGED
|
@@ -11,6 +11,9 @@ import {
|
|
|
11
11
|
PanResponder,
|
|
12
12
|
} from 'react-native';
|
|
13
13
|
import { cn } from '../../lib/utils';
|
|
14
|
+
import { designTokens } from '@sudobility/design';
|
|
15
|
+
|
|
16
|
+
const { typography } = designTokens;
|
|
14
17
|
|
|
15
18
|
const { height: SCREEN_HEIGHT, width: SCREEN_WIDTH } = Dimensions.get('window');
|
|
16
19
|
|
|
@@ -267,12 +270,24 @@ export const Sheet: React.FC<SheetProps> = ({
|
|
|
267
270
|
<View className='flex flex-row items-start justify-between'>
|
|
268
271
|
<View className='flex-1'>
|
|
269
272
|
{title && (
|
|
270
|
-
<Text
|
|
273
|
+
<Text
|
|
274
|
+
className={cn(
|
|
275
|
+
typography.size.lg,
|
|
276
|
+
typography.weight.semibold,
|
|
277
|
+
'text-gray-900 dark:text-white'
|
|
278
|
+
)}
|
|
279
|
+
>
|
|
271
280
|
{title}
|
|
272
281
|
</Text>
|
|
273
282
|
)}
|
|
274
283
|
{description && (
|
|
275
|
-
<Text
|
|
284
|
+
<Text
|
|
285
|
+
className={cn(
|
|
286
|
+
'mt-1',
|
|
287
|
+
typography.size.sm,
|
|
288
|
+
'text-gray-600 dark:text-gray-400'
|
|
289
|
+
)}
|
|
290
|
+
>
|
|
276
291
|
{description}
|
|
277
292
|
</Text>
|
|
278
293
|
)}
|
|
@@ -284,7 +299,9 @@ export const Sheet: React.FC<SheetProps> = ({
|
|
|
284
299
|
accessibilityRole='button'
|
|
285
300
|
accessibilityLabel='Close sheet'
|
|
286
301
|
>
|
|
287
|
-
<Text className=
|
|
302
|
+
<Text className={cn(typography.size.xl, 'text-gray-400')}>
|
|
303
|
+
✕
|
|
304
|
+
</Text>
|
|
288
305
|
</Pressable>
|
|
289
306
|
)}
|
|
290
307
|
</View>
|
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
import * as React from 'react';
|
|
2
2
|
import { View, Text, Pressable } from 'react-native';
|
|
3
3
|
import { cn } from '../../lib/utils';
|
|
4
|
+
import { designTokens } from '@sudobility/design';
|
|
5
|
+
|
|
6
|
+
const { typography } = designTokens;
|
|
4
7
|
|
|
5
8
|
export interface NavItem {
|
|
6
9
|
/** Unique identifier */
|
|
@@ -60,7 +63,8 @@ export const SideNav: React.FC<SideNavProps> = ({ items, className }) => {
|
|
|
60
63
|
{item.icon && <View className='w-5 h-5'>{item.icon}</View>}
|
|
61
64
|
<Text
|
|
62
65
|
className={cn(
|
|
63
|
-
'flex-1
|
|
66
|
+
'flex-1',
|
|
67
|
+
typography.weight.medium,
|
|
64
68
|
item.active
|
|
65
69
|
? 'text-blue-600 dark:text-blue-400'
|
|
66
70
|
: 'text-gray-700 dark:text-gray-300'
|
|
@@ -70,7 +74,12 @@ export const SideNav: React.FC<SideNavProps> = ({ items, className }) => {
|
|
|
70
74
|
</Text>
|
|
71
75
|
{item.badge !== undefined && (
|
|
72
76
|
<View className='px-2 py-0.5 bg-gray-200 dark:bg-gray-700 rounded'>
|
|
73
|
-
<Text
|
|
77
|
+
<Text
|
|
78
|
+
className={cn(
|
|
79
|
+
typography.size.xs,
|
|
80
|
+
'text-gray-700 dark:text-gray-300'
|
|
81
|
+
)}
|
|
82
|
+
>
|
|
74
83
|
{item.badge}
|
|
75
84
|
</Text>
|
|
76
85
|
</View>
|
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
import * as React from 'react';
|
|
2
2
|
import { Text, Pressable, Linking, Alert } from 'react-native';
|
|
3
3
|
import { cn } from '../../lib/utils';
|
|
4
|
+
import { designTokens } from '@sudobility/design';
|
|
5
|
+
|
|
6
|
+
const { typography } = designTokens;
|
|
4
7
|
|
|
5
8
|
export interface SmartLinkProps {
|
|
6
9
|
/** Link destination - URL or internal path */
|
|
@@ -61,9 +64,9 @@ export const SmartLink: React.FC<SmartLinkProps> = ({
|
|
|
61
64
|
};
|
|
62
65
|
|
|
63
66
|
const sizeClasses = {
|
|
64
|
-
sm:
|
|
65
|
-
default:
|
|
66
|
-
lg:
|
|
67
|
+
sm: typography.size.sm,
|
|
68
|
+
default: typography.size.base,
|
|
69
|
+
lg: typography.size.lg,
|
|
67
70
|
};
|
|
68
71
|
|
|
69
72
|
const handlePress = async () => {
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
import { View, ActivityIndicator, Text, type ViewProps } from 'react-native';
|
|
3
3
|
import { cn } from '../../lib/utils';
|
|
4
|
+
import { colors, textVariants } from '@sudobility/design';
|
|
4
5
|
|
|
5
6
|
/**
|
|
6
7
|
* Props for the Spinner loading indicator component.
|
|
@@ -25,12 +26,13 @@ const sizeMap = {
|
|
|
25
26
|
extraLarge: 'large' as const,
|
|
26
27
|
};
|
|
27
28
|
|
|
29
|
+
// Spinner colors from design system raw palette
|
|
28
30
|
const colorMap = {
|
|
29
|
-
default:
|
|
30
|
-
white:
|
|
31
|
-
success:
|
|
32
|
-
warning:
|
|
33
|
-
error:
|
|
31
|
+
default: colors.raw.blue[600],
|
|
32
|
+
white: colors.raw.neutral[0],
|
|
33
|
+
success: colors.raw.green[600],
|
|
34
|
+
warning: colors.raw.orange[600],
|
|
35
|
+
error: colors.raw.red[600],
|
|
34
36
|
};
|
|
35
37
|
|
|
36
38
|
/**
|
|
@@ -62,7 +64,7 @@ export const Spinner: React.FC<SpinnerProps> = ({
|
|
|
62
64
|
>
|
|
63
65
|
<ActivityIndicator size={activitySize} color={color} />
|
|
64
66
|
{showText && (
|
|
65
|
-
<Text className='mt-2
|
|
67
|
+
<Text className={cn(textVariants.body.sm(), 'mt-2')}>
|
|
66
68
|
{loadingText}
|
|
67
69
|
</Text>
|
|
68
70
|
)}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import * as React from 'react';
|
|
2
2
|
import { View, Text } from 'react-native';
|
|
3
3
|
import { cn } from '../../lib/utils';
|
|
4
|
+
import { colors, designTokens } from '@sudobility/design';
|
|
4
5
|
|
|
5
6
|
export interface StatDisplayProps {
|
|
6
7
|
/** The main value/number to display */
|
|
@@ -33,31 +34,31 @@ export interface StatDisplayProps {
|
|
|
33
34
|
* <StatDisplay value="42" label="Active Users" variant="success" size="lg" />
|
|
34
35
|
* ```
|
|
35
36
|
*/
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
37
|
+
|
|
38
|
+
// Lazily derive stat display colors from DS to avoid ESM issues in tests.
|
|
39
|
+
let _statColors: ReturnType<typeof buildStatColors> | null = null;
|
|
40
|
+
function getStatColors() {
|
|
41
|
+
if (!_statColors) _statColors = buildStatColors();
|
|
42
|
+
return _statColors;
|
|
43
|
+
}
|
|
44
|
+
function buildStatColors() {
|
|
45
|
+
const alert = colors.component.alert;
|
|
46
|
+
// Extract text-* classes from DS alert icon strings
|
|
47
|
+
return {
|
|
47
48
|
primary: {
|
|
48
|
-
value:
|
|
49
|
+
value: `${alert.info.icon}`,
|
|
49
50
|
label: 'text-blue-600/70 dark:text-blue-400/70',
|
|
50
51
|
},
|
|
51
52
|
success: {
|
|
52
|
-
value:
|
|
53
|
+
value: `${alert.success.icon}`,
|
|
53
54
|
label: 'text-green-600/70 dark:text-green-400/70',
|
|
54
55
|
},
|
|
55
56
|
warning: {
|
|
56
|
-
value:
|
|
57
|
-
label: 'text-
|
|
57
|
+
value: `${alert.warning.icon}`,
|
|
58
|
+
label: 'text-orange-600/70 dark:text-orange-400/70',
|
|
58
59
|
},
|
|
59
60
|
danger: {
|
|
60
|
-
value:
|
|
61
|
+
value: `${alert.error.icon}`,
|
|
61
62
|
label: 'text-red-600/70 dark:text-red-400/70',
|
|
62
63
|
},
|
|
63
64
|
neutral: {
|
|
@@ -68,13 +69,38 @@ export const StatDisplay: React.FC<StatDisplayProps> = ({
|
|
|
68
69
|
value: 'text-white',
|
|
69
70
|
label: 'text-white/70',
|
|
70
71
|
},
|
|
71
|
-
};
|
|
72
|
+
} as Record<string, { value: string; label: string }>;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
export const StatDisplay: React.FC<StatDisplayProps> = ({
|
|
76
|
+
value,
|
|
77
|
+
label,
|
|
78
|
+
variant = 'neutral',
|
|
79
|
+
size = 'md',
|
|
80
|
+
align = 'center',
|
|
81
|
+
icon,
|
|
82
|
+
iconPosition = 'top',
|
|
83
|
+
className,
|
|
84
|
+
}) => {
|
|
85
|
+
const variantClasses = getStatColors();
|
|
72
86
|
|
|
73
87
|
const sizeClasses = {
|
|
74
|
-
sm: {
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
88
|
+
sm: {
|
|
89
|
+
value: designTokens.typography.size.xl,
|
|
90
|
+
label: designTokens.typography.size.xs,
|
|
91
|
+
},
|
|
92
|
+
md: {
|
|
93
|
+
value: designTokens.typography.size['2xl'],
|
|
94
|
+
label: designTokens.typography.size.sm,
|
|
95
|
+
},
|
|
96
|
+
lg: {
|
|
97
|
+
value: designTokens.typography.size['3xl'],
|
|
98
|
+
label: designTokens.typography.size.base,
|
|
99
|
+
},
|
|
100
|
+
xl: {
|
|
101
|
+
value: designTokens.typography.size['4xl'],
|
|
102
|
+
label: designTokens.typography.size.lg,
|
|
103
|
+
},
|
|
78
104
|
};
|
|
79
105
|
|
|
80
106
|
const alignClasses = {
|
|
@@ -98,7 +124,11 @@ export const StatDisplay: React.FC<StatDisplayProps> = ({
|
|
|
98
124
|
<View className={variantConfig.value}>{icon}</View>
|
|
99
125
|
<View>
|
|
100
126
|
<Text
|
|
101
|
-
className={cn(
|
|
127
|
+
className={cn(
|
|
128
|
+
designTokens.typography.weight.bold,
|
|
129
|
+
sizeConfig.value,
|
|
130
|
+
variantConfig.value
|
|
131
|
+
)}
|
|
102
132
|
>
|
|
103
133
|
{value}
|
|
104
134
|
</Text>
|
|
@@ -115,7 +145,13 @@ export const StatDisplay: React.FC<StatDisplayProps> = ({
|
|
|
115
145
|
{icon && iconPosition === 'top' && (
|
|
116
146
|
<View className={cn('mb-2', variantConfig.value)}>{icon}</View>
|
|
117
147
|
)}
|
|
118
|
-
<Text
|
|
148
|
+
<Text
|
|
149
|
+
className={cn(
|
|
150
|
+
designTokens.typography.weight.bold,
|
|
151
|
+
sizeConfig.value,
|
|
152
|
+
variantConfig.value
|
|
153
|
+
)}
|
|
154
|
+
>
|
|
119
155
|
{value}
|
|
120
156
|
</Text>
|
|
121
157
|
<Text className={cn(sizeConfig.label, variantConfig.label)}>{label}</Text>
|