@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.
Files changed (142) hide show
  1. package/dist/index.cjs.js +1092 -473
  2. package/dist/index.cjs.js.map +1 -1
  3. package/dist/index.esm.js +1095 -476
  4. package/dist/index.esm.js.map +1 -1
  5. package/dist/ui/Alert/Alert.d.ts.map +1 -1
  6. package/dist/ui/Avatar/Avatar.d.ts.map +1 -1
  7. package/dist/ui/Badge/Badge.d.ts.map +1 -1
  8. package/dist/ui/Banner/Banner.d.ts.map +1 -1
  9. package/dist/ui/Breadcrumb/Breadcrumb.d.ts.map +1 -1
  10. package/dist/ui/BreadcrumbNav/BreadcrumbNav.d.ts.map +1 -1
  11. package/dist/ui/CTASection/CTASection.d.ts.map +1 -1
  12. package/dist/ui/Calendar/Calendar.d.ts.map +1 -1
  13. package/dist/ui/ChainBadge/ChainBadge.d.ts.map +1 -1
  14. package/dist/ui/Checkbox/Checkbox.d.ts +0 -22
  15. package/dist/ui/Checkbox/Checkbox.d.ts.map +1 -1
  16. package/dist/ui/Code/Code.d.ts +0 -17
  17. package/dist/ui/Code/Code.d.ts.map +1 -1
  18. package/dist/ui/CodeDisplay/CodeDisplay.d.ts +0 -21
  19. package/dist/ui/CodeDisplay/CodeDisplay.d.ts.map +1 -1
  20. package/dist/ui/CollapsibleSection/CollapsibleSection.d.ts.map +1 -1
  21. package/dist/ui/Combobox/Combobox.d.ts.map +1 -1
  22. package/dist/ui/Command/Command.d.ts.map +1 -1
  23. package/dist/ui/DashboardStatCard/DashboardStatCard.d.ts +0 -17
  24. package/dist/ui/DashboardStatCard/DashboardStatCard.d.ts.map +1 -1
  25. package/dist/ui/DataList/DataList.d.ts.map +1 -1
  26. package/dist/ui/Divider/Divider.d.ts.map +1 -1
  27. package/dist/ui/Dropdown/Dropdown.d.ts.map +1 -1
  28. package/dist/ui/ExternalLink/ExternalLink.d.ts.map +1 -1
  29. package/dist/ui/FeatureCard/FeatureCard.d.ts.map +1 -1
  30. package/dist/ui/FeatureGrid/FeatureGrid.d.ts.map +1 -1
  31. package/dist/ui/GradientIconContainer/GradientIconContainer.d.ts +0 -13
  32. package/dist/ui/GradientIconContainer/GradientIconContainer.d.ts.map +1 -1
  33. package/dist/ui/Heading/Heading.d.ts.map +1 -1
  34. package/dist/ui/HelperText/HelperText.d.ts.map +1 -1
  35. package/dist/ui/IconContainer/IconContainer.d.ts +0 -13
  36. package/dist/ui/IconContainer/IconContainer.d.ts.map +1 -1
  37. package/dist/ui/IconText/IconText.d.ts.map +1 -1
  38. package/dist/ui/InfiniteScroll/InfiniteScroll.d.ts.map +1 -1
  39. package/dist/ui/InfoBox/InfoBox.d.ts.map +1 -1
  40. package/dist/ui/Input/Input.d.ts.map +1 -1
  41. package/dist/ui/KeyValuePair/KeyValuePair.d.ts.map +1 -1
  42. package/dist/ui/Label/Label.d.ts.map +1 -1
  43. package/dist/ui/Link/Link.d.ts.map +1 -1
  44. package/dist/ui/ListItemWithAction/ListItemWithAction.d.ts.map +1 -1
  45. package/dist/ui/Modal/Modal.d.ts.map +1 -1
  46. package/dist/ui/MultiSelect/MultiSelect.d.ts.map +1 -1
  47. package/dist/ui/NavigationList/NavigationList.d.ts.map +1 -1
  48. package/dist/ui/PageSectionHeader/PageSectionHeader.d.ts.map +1 -1
  49. package/dist/ui/Pagination/Pagination.d.ts.map +1 -1
  50. package/dist/ui/PhoneInput/PhoneInput.d.ts.map +1 -1
  51. package/dist/ui/PopupSelect/PopupSelect.d.ts.map +1 -1
  52. package/dist/ui/Progress/Progress.d.ts +0 -15
  53. package/dist/ui/Progress/Progress.d.ts.map +1 -1
  54. package/dist/ui/ProgressCircle/ProgressCircle.d.ts.map +1 -1
  55. package/dist/ui/PromotionalBanner/PromotionalBanner.d.ts.map +1 -1
  56. package/dist/ui/QuickActions/QuickActions.d.ts.map +1 -1
  57. package/dist/ui/SearchInput/SearchInput.d.ts.map +1 -1
  58. package/dist/ui/SectionHeader/SectionHeader.d.ts.map +1 -1
  59. package/dist/ui/Select/Select.d.ts.map +1 -1
  60. package/dist/ui/SettingsList/SettingsList.d.ts.map +1 -1
  61. package/dist/ui/Sheet/Sheet.d.ts.map +1 -1
  62. package/dist/ui/SideNav/SideNav.d.ts.map +1 -1
  63. package/dist/ui/SmartLink/SmartLink.d.ts.map +1 -1
  64. package/dist/ui/Spinner/Spinner.d.ts.map +1 -1
  65. package/dist/ui/StatDisplay/StatDisplay.d.ts +0 -12
  66. package/dist/ui/StatDisplay/StatDisplay.d.ts.map +1 -1
  67. package/dist/ui/StepList/StepList.d.ts.map +1 -1
  68. package/dist/ui/Table/Table.d.ts.map +1 -1
  69. package/dist/ui/Tabs/Tabs.d.ts.map +1 -1
  70. package/dist/ui/Text/Text.d.ts.map +1 -1
  71. package/dist/ui/TextArea/TextArea.d.ts.map +1 -1
  72. package/dist/ui/TextInputModal/TextInputModal.d.ts.map +1 -1
  73. package/dist/ui/Toast/Toast.d.ts.map +1 -1
  74. package/dist/ui/Tooltip/Tooltip.d.ts +0 -20
  75. package/dist/ui/Tooltip/Tooltip.d.ts.map +1 -1
  76. package/dist/ui/TransferList/TransferList.d.ts.map +1 -1
  77. package/package.json +5 -4
  78. package/src/__tests__/alert.test.tsx +20 -10
  79. package/src/ui/Alert/Alert.tsx +13 -5
  80. package/src/ui/Avatar/Avatar.tsx +6 -5
  81. package/src/ui/Badge/Badge.tsx +61 -26
  82. package/src/ui/Banner/Banner.tsx +36 -25
  83. package/src/ui/Breadcrumb/Breadcrumb.tsx +8 -5
  84. package/src/ui/BreadcrumbNav/BreadcrumbNav.tsx +22 -3
  85. package/src/ui/CTASection/CTASection.tsx +8 -6
  86. package/src/ui/Calendar/Calendar.tsx +35 -6
  87. package/src/ui/Card/Card.tsx +2 -2
  88. package/src/ui/ChainBadge/ChainBadge.tsx +67 -42
  89. package/src/ui/Checkbox/Checkbox.tsx +47 -20
  90. package/src/ui/Code/Code.tsx +51 -21
  91. package/src/ui/CodeDisplay/CodeDisplay.tsx +46 -20
  92. package/src/ui/CollapsibleSection/CollapsibleSection.tsx +7 -3
  93. package/src/ui/Combobox/Combobox.tsx +2 -1
  94. package/src/ui/Command/Command.tsx +2 -1
  95. package/src/ui/DashboardStatCard/DashboardStatCard.tsx +29 -11
  96. package/src/ui/DataList/DataList.tsx +23 -5
  97. package/src/ui/Divider/Divider.tsx +12 -17
  98. package/src/ui/Dropdown/Dropdown.tsx +4 -1
  99. package/src/ui/ExternalLink/ExternalLink.tsx +5 -4
  100. package/src/ui/FeatureCard/FeatureCard.tsx +60 -29
  101. package/src/ui/FeatureGrid/FeatureGrid.tsx +7 -7
  102. package/src/ui/GradientIconContainer/GradientIconContainer.tsx +33 -8
  103. package/src/ui/Heading/Heading.tsx +15 -38
  104. package/src/ui/HelperText/HelperText.tsx +9 -8
  105. package/src/ui/IconContainer/IconContainer.tsx +26 -9
  106. package/src/ui/IconText/IconText.tsx +6 -5
  107. package/src/ui/InfiniteScroll/InfiniteScroll.tsx +2 -1
  108. package/src/ui/InfoBox/InfoBox.tsx +35 -17
  109. package/src/ui/Input/Input.tsx +10 -3
  110. package/src/ui/KeyValuePair/KeyValuePair.tsx +12 -5
  111. package/src/ui/Label/Label.tsx +3 -1
  112. package/src/ui/Link/Link.tsx +6 -5
  113. package/src/ui/ListItemWithAction/ListItemWithAction.tsx +2 -1
  114. package/src/ui/Modal/Modal.tsx +16 -2
  115. package/src/ui/MultiSelect/MultiSelect.tsx +2 -1
  116. package/src/ui/NavigationList/NavigationList.tsx +17 -3
  117. package/src/ui/PageSectionHeader/PageSectionHeader.tsx +2 -1
  118. package/src/ui/Pagination/Pagination.tsx +9 -6
  119. package/src/ui/PhoneInput/PhoneInput.tsx +3 -2
  120. package/src/ui/PopupSelect/PopupSelect.tsx +15 -14
  121. package/src/ui/Progress/Progress.tsx +63 -14
  122. package/src/ui/ProgressCircle/ProgressCircle.tsx +7 -6
  123. package/src/ui/PromotionalBanner/PromotionalBanner.tsx +7 -4
  124. package/src/ui/QuickActions/QuickActions.tsx +13 -9
  125. package/src/ui/SearchInput/SearchInput.tsx +3 -2
  126. package/src/ui/SectionHeader/SectionHeader.tsx +4 -1
  127. package/src/ui/Select/Select.tsx +20 -5
  128. package/src/ui/SettingsList/SettingsList.tsx +4 -1
  129. package/src/ui/Sheet/Sheet.tsx +20 -3
  130. package/src/ui/SideNav/SideNav.tsx +11 -2
  131. package/src/ui/SmartLink/SmartLink.tsx +6 -3
  132. package/src/ui/Spinner/Spinner.tsx +8 -6
  133. package/src/ui/StatDisplay/StatDisplay.tsx +59 -23
  134. package/src/ui/StepList/StepList.tsx +25 -3
  135. package/src/ui/Table/Table.tsx +22 -9
  136. package/src/ui/Tabs/Tabs.tsx +7 -2
  137. package/src/ui/Text/Text.tsx +19 -52
  138. package/src/ui/TextArea/TextArea.tsx +2 -1
  139. package/src/ui/TextInputModal/TextInputModal.tsx +2 -1
  140. package/src/ui/Toast/Toast.tsx +49 -14
  141. package/src/ui/Tooltip/Tooltip.tsx +47 -9
  142. 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: 'bg-blue-600 dark:bg-blue-500',
77
- success: 'bg-green-600 dark:bg-green-500',
78
- warning: 'bg-yellow-600 dark:bg-yellow-500',
79
- danger: 'bg-red-600 dark:bg-red-500',
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 className='text-xs text-gray-600 dark:text-gray-400 text-right'>
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: 'bg-blue-600 dark:bg-blue-500',
179
- success: 'bg-green-600 dark:bg-green-500',
180
- warning: 'bg-yellow-600 dark:bg-yellow-500',
181
- danger: 'bg-red-600 dark:bg-red-500',
182
- purple: 'bg-purple-600 dark:bg-purple-500',
183
- gray: 'bg-gray-600 dark:bg-gray-500',
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 className='text-sm font-medium text-gray-600 dark:text-gray-400'>
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 = '#e5e7eb',
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: '#2563eb',
60
- success: '#16a34a',
61
- warning: '#ca8a04',
62
- danger: '#dc2626',
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
- 'bg-green-50 dark:bg-green-900/20',
56
- 'border-b border-green-200 dark:border-green-700',
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-500 border-blue-500',
64
- bgActive: 'active:bg-blue-600',
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-500 border-green-500',
69
- bgActive: 'active:bg-green-600',
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-yellow-500 border-yellow-500',
74
- bgActive: 'active:bg-yellow-600',
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-500 border-red-500',
79
- bgActive: 'active:bg-red-600',
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('font-medium', styles.text)}>
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='#9CA3AF'
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='#9CA3AF' />
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 && <ActivityIndicator size='small' color='#2563eb' />}
57
+ {loading && (
58
+ <ActivityIndicator size='small' color={colors.raw.blue[600]} />
59
+ )}
57
60
  {actions}
58
61
  {onAdd && (
59
62
  <Pressable
@@ -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
- 'text-base',
98
+ typography.size.base,
96
99
  item.value === value
97
- ? 'text-blue-600 dark:text-blue-400 font-medium'
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
- 'text-base flex-1',
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 className='text-blue-600 dark:text-blue-400 text-base'>
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 className='text-base font-semibold text-gray-900 dark:text-white'>
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
- 'text-sm',
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'
@@ -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 className='text-lg font-semibold text-gray-900 dark:text-white'>
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 className='mt-1 text-sm text-gray-600 dark:text-gray-400'>
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='text-xl text-gray-400'>✕</Text>
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 font-medium',
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 className='text-xs text-gray-700 dark:text-gray-300'>
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: 'text-sm',
65
- default: 'text-base',
66
- lg: 'text-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: '#2563eb', // blue-600
30
- white: '#ffffff',
31
- success: '#16a34a', // green-600
32
- warning: '#ea580c', // orange-600
33
- error: '#dc2626', // red-600
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 text-gray-600 dark:text-gray-400 text-sm'>
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
- export const StatDisplay: React.FC<StatDisplayProps> = ({
37
- value,
38
- label,
39
- variant = 'neutral',
40
- size = 'md',
41
- align = 'center',
42
- icon,
43
- iconPosition = 'top',
44
- className,
45
- }) => {
46
- const variantClasses = {
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: 'text-blue-600 dark:text-blue-400',
49
+ value: `${alert.info.icon}`,
49
50
  label: 'text-blue-600/70 dark:text-blue-400/70',
50
51
  },
51
52
  success: {
52
- value: 'text-green-600 dark:text-green-400',
53
+ value: `${alert.success.icon}`,
53
54
  label: 'text-green-600/70 dark:text-green-400/70',
54
55
  },
55
56
  warning: {
56
- value: 'text-yellow-600 dark:text-yellow-400',
57
- label: 'text-yellow-600/70 dark:text-yellow-400/70',
57
+ value: `${alert.warning.icon}`,
58
+ label: 'text-orange-600/70 dark:text-orange-400/70',
58
59
  },
59
60
  danger: {
60
- value: 'text-red-600 dark:text-red-400',
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: { value: 'text-xl', label: 'text-xs' },
75
- md: { value: 'text-2xl', label: 'text-sm' },
76
- lg: { value: 'text-3xl', label: 'text-base' },
77
- xl: { value: 'text-4xl', label: 'text-lg' },
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('font-bold', sizeConfig.value, variantConfig.value)}
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 className={cn('font-bold', sizeConfig.value, variantConfig.value)}>
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>