@sudobility/components-rn 1.0.42 → 1.0.44

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 (115) hide show
  1. package/dist/index.cjs.js +895 -299
  2. package/dist/index.cjs.js.map +1 -1
  3. package/dist/index.esm.js +896 -300
  4. package/dist/index.esm.js.map +1 -1
  5. package/dist/ui/Avatar/Avatar.d.ts.map +1 -1
  6. package/dist/ui/Breadcrumb/Breadcrumb.d.ts.map +1 -1
  7. package/dist/ui/BreadcrumbNav/BreadcrumbNav.d.ts.map +1 -1
  8. package/dist/ui/CTASection/CTASection.d.ts.map +1 -1
  9. package/dist/ui/Calendar/Calendar.d.ts.map +1 -1
  10. package/dist/ui/ChainBadge/ChainBadge.d.ts.map +1 -1
  11. package/dist/ui/Checkbox/Checkbox.d.ts +0 -22
  12. package/dist/ui/Checkbox/Checkbox.d.ts.map +1 -1
  13. package/dist/ui/Code/Code.d.ts +0 -17
  14. package/dist/ui/Code/Code.d.ts.map +1 -1
  15. package/dist/ui/CodeDisplay/CodeDisplay.d.ts +0 -21
  16. package/dist/ui/CodeDisplay/CodeDisplay.d.ts.map +1 -1
  17. package/dist/ui/CollapsibleSection/CollapsibleSection.d.ts.map +1 -1
  18. package/dist/ui/Combobox/Combobox.d.ts.map +1 -1
  19. package/dist/ui/Command/Command.d.ts.map +1 -1
  20. package/dist/ui/DashboardStatCard/DashboardStatCard.d.ts +0 -17
  21. package/dist/ui/DashboardStatCard/DashboardStatCard.d.ts.map +1 -1
  22. package/dist/ui/DataList/DataList.d.ts.map +1 -1
  23. package/dist/ui/Dropdown/Dropdown.d.ts.map +1 -1
  24. package/dist/ui/ExternalLink/ExternalLink.d.ts.map +1 -1
  25. package/dist/ui/FeatureCard/FeatureCard.d.ts.map +1 -1
  26. package/dist/ui/FeatureGrid/FeatureGrid.d.ts.map +1 -1
  27. package/dist/ui/GradientIconContainer/GradientIconContainer.d.ts +0 -13
  28. package/dist/ui/GradientIconContainer/GradientIconContainer.d.ts.map +1 -1
  29. package/dist/ui/HelperText/HelperText.d.ts.map +1 -1
  30. package/dist/ui/IconContainer/IconContainer.d.ts +0 -13
  31. package/dist/ui/IconContainer/IconContainer.d.ts.map +1 -1
  32. package/dist/ui/IconText/IconText.d.ts.map +1 -1
  33. package/dist/ui/InfiniteScroll/InfiniteScroll.d.ts.map +1 -1
  34. package/dist/ui/KeyValuePair/KeyValuePair.d.ts.map +1 -1
  35. package/dist/ui/Link/Link.d.ts.map +1 -1
  36. package/dist/ui/ListItemWithAction/ListItemWithAction.d.ts.map +1 -1
  37. package/dist/ui/Modal/Modal.d.ts.map +1 -1
  38. package/dist/ui/MultiSelect/MultiSelect.d.ts.map +1 -1
  39. package/dist/ui/NavigationList/NavigationList.d.ts.map +1 -1
  40. package/dist/ui/PageSectionHeader/PageSectionHeader.d.ts.map +1 -1
  41. package/dist/ui/Pagination/Pagination.d.ts.map +1 -1
  42. package/dist/ui/PhoneInput/PhoneInput.d.ts.map +1 -1
  43. package/dist/ui/PopupSelect/PopupSelect.d.ts.map +1 -1
  44. package/dist/ui/Progress/Progress.d.ts +0 -15
  45. package/dist/ui/Progress/Progress.d.ts.map +1 -1
  46. package/dist/ui/PromotionalBanner/PromotionalBanner.d.ts.map +1 -1
  47. package/dist/ui/SearchInput/SearchInput.d.ts.map +1 -1
  48. package/dist/ui/SectionHeader/SectionHeader.d.ts.map +1 -1
  49. package/dist/ui/Select/Select.d.ts.map +1 -1
  50. package/dist/ui/SettingsList/SettingsList.d.ts.map +1 -1
  51. package/dist/ui/Sheet/Sheet.d.ts.map +1 -1
  52. package/dist/ui/SideNav/SideNav.d.ts.map +1 -1
  53. package/dist/ui/SmartLink/SmartLink.d.ts.map +1 -1
  54. package/dist/ui/StatDisplay/StatDisplay.d.ts +0 -12
  55. package/dist/ui/StatDisplay/StatDisplay.d.ts.map +1 -1
  56. package/dist/ui/StepList/StepList.d.ts.map +1 -1
  57. package/dist/ui/Table/Table.d.ts.map +1 -1
  58. package/dist/ui/Tabs/Tabs.d.ts.map +1 -1
  59. package/dist/ui/TextArea/TextArea.d.ts.map +1 -1
  60. package/dist/ui/TextInputModal/TextInputModal.d.ts.map +1 -1
  61. package/dist/ui/Tooltip/Tooltip.d.ts +0 -20
  62. package/dist/ui/Tooltip/Tooltip.d.ts.map +1 -1
  63. package/dist/ui/TransferList/TransferList.d.ts.map +1 -1
  64. package/package.json +3 -3
  65. package/src/ui/Avatar/Avatar.tsx +6 -5
  66. package/src/ui/Breadcrumb/Breadcrumb.tsx +8 -5
  67. package/src/ui/BreadcrumbNav/BreadcrumbNav.tsx +22 -3
  68. package/src/ui/CTASection/CTASection.tsx +8 -6
  69. package/src/ui/Calendar/Calendar.tsx +35 -6
  70. package/src/ui/ChainBadge/ChainBadge.tsx +67 -42
  71. package/src/ui/Checkbox/Checkbox.tsx +47 -20
  72. package/src/ui/Code/Code.tsx +51 -21
  73. package/src/ui/CodeDisplay/CodeDisplay.tsx +46 -20
  74. package/src/ui/CollapsibleSection/CollapsibleSection.tsx +7 -3
  75. package/src/ui/Combobox/Combobox.tsx +2 -1
  76. package/src/ui/Command/Command.tsx +2 -1
  77. package/src/ui/DashboardStatCard/DashboardStatCard.tsx +29 -11
  78. package/src/ui/DataList/DataList.tsx +23 -5
  79. package/src/ui/Dropdown/Dropdown.tsx +4 -1
  80. package/src/ui/ExternalLink/ExternalLink.tsx +5 -4
  81. package/src/ui/FeatureCard/FeatureCard.tsx +60 -29
  82. package/src/ui/FeatureGrid/FeatureGrid.tsx +7 -7
  83. package/src/ui/GradientIconContainer/GradientIconContainer.tsx +33 -8
  84. package/src/ui/HelperText/HelperText.tsx +9 -8
  85. package/src/ui/IconContainer/IconContainer.tsx +26 -9
  86. package/src/ui/IconText/IconText.tsx +6 -5
  87. package/src/ui/InfiniteScroll/InfiniteScroll.tsx +2 -1
  88. package/src/ui/KeyValuePair/KeyValuePair.tsx +12 -5
  89. package/src/ui/Link/Link.tsx +6 -5
  90. package/src/ui/ListItemWithAction/ListItemWithAction.tsx +2 -1
  91. package/src/ui/Modal/Modal.tsx +16 -2
  92. package/src/ui/MultiSelect/MultiSelect.tsx +2 -1
  93. package/src/ui/NavigationList/NavigationList.tsx +17 -3
  94. package/src/ui/PageSectionHeader/PageSectionHeader.tsx +2 -1
  95. package/src/ui/Pagination/Pagination.tsx +9 -6
  96. package/src/ui/PhoneInput/PhoneInput.tsx +3 -2
  97. package/src/ui/PopupSelect/PopupSelect.tsx +15 -14
  98. package/src/ui/Progress/Progress.tsx +63 -14
  99. package/src/ui/PromotionalBanner/PromotionalBanner.tsx +7 -4
  100. package/src/ui/SearchInput/SearchInput.tsx +3 -2
  101. package/src/ui/SectionHeader/SectionHeader.tsx +4 -1
  102. package/src/ui/Select/Select.tsx +20 -5
  103. package/src/ui/SettingsList/SettingsList.tsx +4 -1
  104. package/src/ui/Sheet/Sheet.tsx +20 -3
  105. package/src/ui/SideNav/SideNav.tsx +11 -2
  106. package/src/ui/SmartLink/SmartLink.tsx +6 -3
  107. package/src/ui/Spinner/Spinner.tsx +1 -1
  108. package/src/ui/StatDisplay/StatDisplay.tsx +59 -23
  109. package/src/ui/StepList/StepList.tsx +25 -3
  110. package/src/ui/Table/Table.tsx +22 -9
  111. package/src/ui/Tabs/Tabs.tsx +7 -2
  112. package/src/ui/TextArea/TextArea.tsx +2 -1
  113. package/src/ui/TextInputModal/TextInputModal.tsx +2 -1
  114. package/src/ui/Tooltip/Tooltip.tsx +47 -9
  115. package/src/ui/TransferList/TransferList.tsx +2 -1
@@ -1,6 +1,7 @@
1
1
  import * as React from 'react';
2
2
  import { View, Text, ScrollView } from 'react-native';
3
3
  import { cn } from '../../lib/utils';
4
+ import { colors, designTokens } from '@sudobility/design';
4
5
 
5
6
  export interface CodeDisplayProps {
6
7
  /** Code or text to display */
@@ -40,6 +41,36 @@ export interface CodeDisplayProps {
40
41
  * </CodeDisplay>
41
42
  * ```
42
43
  */
44
+
45
+ // Lazily derive display colors from DS to avoid ESM issues in tests.
46
+ let _displayColors: ReturnType<typeof buildDisplayColors> | null = null;
47
+ function getDisplayColors() {
48
+ if (!_displayColors) _displayColors = buildDisplayColors();
49
+ return _displayColors;
50
+ }
51
+ function buildDisplayColors() {
52
+ const alert = colors.component.alert;
53
+ function splitClasses(base: string, dark: string) {
54
+ const all = `${base} ${dark}`.split(' ');
55
+ return {
56
+ text: all.filter(c => c.includes('text-')).join(' '),
57
+ bg: all.filter(c => c.includes('bg-')).join(' '),
58
+ };
59
+ }
60
+ const info = splitClasses(alert.info.base, alert.info.dark);
61
+ const success = splitClasses(alert.success.base, alert.success.dark);
62
+ const warning = splitClasses(alert.warning.base, alert.warning.dark);
63
+ return {
64
+ primary: `${info.text} ${info.bg}`,
65
+ // secondary uses purple — no DS mapping, keep local
66
+ secondary:
67
+ 'text-purple-600 dark:text-purple-400 bg-purple-50 dark:bg-purple-900/30',
68
+ success: `${success.text} ${success.bg}`,
69
+ warning: `${warning.text} ${warning.bg}`,
70
+ neutral: 'text-gray-700 dark:text-gray-300 bg-gray-100 dark:bg-gray-800',
71
+ } as Record<string, string>;
72
+ }
73
+
43
74
  export const CodeDisplay: React.FC<CodeDisplayProps> = ({
44
75
  children,
45
76
  variant = 'primary',
@@ -49,34 +80,25 @@ export const CodeDisplay: React.FC<CodeDisplayProps> = ({
49
80
  wrap = false,
50
81
  className,
51
82
  }) => {
52
- // Color variant configurations
53
- const variantClasses = {
54
- primary: 'text-blue-600 dark:text-blue-400 bg-blue-50 dark:bg-blue-900/30',
55
- secondary:
56
- 'text-purple-600 dark:text-purple-400 bg-purple-50 dark:bg-purple-900/30',
57
- success:
58
- 'text-green-600 dark:text-green-400 bg-green-50 dark:bg-green-900/30',
59
- warning:
60
- 'text-yellow-700 dark:text-yellow-400 bg-yellow-50 dark:bg-yellow-900/30',
61
- neutral: 'text-gray-700 dark:text-gray-300 bg-gray-100 dark:bg-gray-800',
62
- };
83
+ // Color variant configurations from DS
84
+ const variantClasses = getDisplayColors();
63
85
 
64
- // Size configurations
86
+ // Size configurations using DS typography tokens
65
87
  const sizeClasses = {
66
88
  xs: {
67
- text: 'text-xs',
89
+ text: designTokens.typography.size.xs,
68
90
  padding: inline ? 'px-1.5 py-0.5' : 'px-2 py-1',
69
91
  },
70
92
  sm: {
71
- text: 'text-sm',
93
+ text: designTokens.typography.size.sm,
72
94
  padding: inline ? 'px-2 py-0.5' : 'px-3 py-1.5',
73
95
  },
74
96
  md: {
75
- text: 'text-base',
97
+ text: designTokens.typography.size.base,
76
98
  padding: inline ? 'px-2.5 py-1' : 'px-4 py-2',
77
99
  },
78
100
  lg: {
79
- text: 'text-lg',
101
+ text: designTokens.typography.size.lg,
80
102
  padding: inline ? 'px-3 py-1' : 'px-4 py-2',
81
103
  },
82
104
  };
@@ -90,14 +112,18 @@ export const CodeDisplay: React.FC<CodeDisplayProps> = ({
90
112
 
91
113
  const sizeConfig = sizeClasses[size];
92
114
 
93
- // Extract background and text color classes
94
- const [textColorClass, bgClass] = variantClasses[variant].split(' ');
115
+ // Extract background and text color classes from combined variant string
116
+ const variantParts = variantClasses[variant].split(' ');
117
+ const textColorClass = variantParts
118
+ .filter(c => c.includes('text-'))
119
+ .join(' ');
120
+ const bgClass = variantParts.filter(c => c.includes('bg-')).join(' ');
95
121
 
96
122
  if (inline) {
97
123
  return (
98
124
  <Text
99
125
  className={cn(
100
- 'font-mono rounded-lg',
126
+ `${designTokens.typography.family.mono} rounded-lg`,
101
127
  textColorClass,
102
128
  bgClass,
103
129
  sizeConfig.text,
@@ -113,7 +139,7 @@ export const CodeDisplay: React.FC<CodeDisplayProps> = ({
113
139
  const content = (
114
140
  <Text
115
141
  className={cn(
116
- 'font-mono',
142
+ designTokens.typography.family.mono,
117
143
  textColorClass,
118
144
  sizeConfig.text,
119
145
  !inline && alignClasses[align],
@@ -10,6 +10,9 @@ import {
10
10
  UIManager,
11
11
  } from 'react-native';
12
12
  import { cn } from '../../lib/utils';
13
+ import { designTokens } from '@sudobility/design';
14
+
15
+ const { typography } = designTokens;
13
16
 
14
17
  // Enable LayoutAnimation on Android
15
18
  if (
@@ -126,7 +129,8 @@ export const CollapsibleSection: React.FC<CollapsibleSectionProps> = ({
126
129
  >
127
130
  <Text
128
131
  className={cn(
129
- 'text-base font-medium',
132
+ typography.size.base,
133
+ typography.weight.medium,
130
134
  isSelected && !selectedSubsection
131
135
  ? 'text-blue-700 dark:text-blue-300'
132
136
  : 'text-gray-700 dark:text-gray-300'
@@ -145,7 +149,7 @@ export const CollapsibleSection: React.FC<CollapsibleSectionProps> = ({
145
149
  accessibilityLabel={isExpanded ? 'Collapse' : 'Expand'}
146
150
  >
147
151
  <Animated.View style={{ transform: [{ rotate: rotation }] }}>
148
- <Text className='text-gray-500 text-lg'>›</Text>
152
+ <Text className={cn('text-gray-500', typography.size.lg)}>›</Text>
149
153
  </Animated.View>
150
154
  </Pressable>
151
155
  )}
@@ -172,7 +176,7 @@ export const CollapsibleSection: React.FC<CollapsibleSectionProps> = ({
172
176
  >
173
177
  <Text
174
178
  className={cn(
175
- 'text-sm',
179
+ typography.size.sm,
176
180
  selectedSubsection === subsection.id
177
181
  ? 'text-blue-700 dark:text-blue-300'
178
182
  : 'text-gray-600 dark:text-gray-400'
@@ -10,6 +10,7 @@ import {
10
10
  TouchableWithoutFeedback,
11
11
  } from 'react-native';
12
12
  import { cn } from '../../lib/utils';
13
+ import { colors } from '@sudobility/design';
13
14
 
14
15
  export interface ComboboxOption {
15
16
  /** Option value */
@@ -143,7 +144,7 @@ export const Combobox: React.FC<ComboboxProps> = ({
143
144
  value={searchQuery}
144
145
  onChangeText={setSearchQuery}
145
146
  placeholder={searchPlaceholder}
146
- placeholderTextColor='#9ca3af'
147
+ placeholderTextColor={colors.raw.neutral[400]}
147
148
  autoFocus
148
149
  className='px-3 py-2 text-sm bg-gray-50 dark:bg-gray-800 text-gray-900 dark:text-white rounded-md'
149
150
  />
@@ -11,6 +11,7 @@ import {
11
11
  Platform,
12
12
  } from 'react-native';
13
13
  import { cn } from '../../lib/utils';
14
+ import { colors } from '@sudobility/design';
14
15
 
15
16
  export interface CommandItem {
16
17
  /** Item ID */
@@ -159,7 +160,7 @@ export const Command: React.FC<CommandProps> = ({
159
160
  value={searchQuery}
160
161
  onChangeText={setSearchQuery}
161
162
  placeholder={placeholder}
162
- placeholderTextColor='#9ca3af'
163
+ placeholderTextColor={colors.raw.neutral[400]}
163
164
  className='flex-1 text-gray-900 dark:text-white text-base'
164
165
  autoCapitalize='none'
165
166
  autoCorrect={false}
@@ -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 { designTokens, getCardVariantColors } from '@sudobility/design';
4
5
 
5
6
  export interface DashboardStatCardProps {
6
7
  /** Stat title */
@@ -36,6 +37,22 @@ export interface DashboardStatCardProps {
36
37
  * />
37
38
  * ```
38
39
  */
40
+
41
+ // Lazily derive card variant colors from DS to avoid ESM issues in tests.
42
+ let _cardColors: Record<string, string> | null = null;
43
+ function getDashboardCardColors() {
44
+ if (!_cardColors) {
45
+ _cardColors = {
46
+ default: getCardVariantColors('default'),
47
+ primary: getCardVariantColors('info'),
48
+ success: getCardVariantColors('success'),
49
+ warning: getCardVariantColors('warning'),
50
+ danger: getCardVariantColors('error'),
51
+ };
52
+ }
53
+ return _cardColors;
54
+ }
55
+
39
56
  export const DashboardStatCard: React.FC<DashboardStatCardProps> = ({
40
57
  title,
41
58
  value,
@@ -45,13 +62,7 @@ export const DashboardStatCard: React.FC<DashboardStatCardProps> = ({
45
62
  variant = 'default',
46
63
  className,
47
64
  }) => {
48
- const variantClasses = {
49
- default: 'bg-white dark:bg-gray-900',
50
- primary: 'bg-blue-50 dark:bg-blue-900/20',
51
- success: 'bg-green-50 dark:bg-green-900/20',
52
- warning: 'bg-yellow-50 dark:bg-yellow-900/20',
53
- danger: 'bg-red-50 dark:bg-red-900/20',
54
- };
65
+ const variantClasses = getDashboardCardColors();
55
66
 
56
67
  const isPositive = change !== undefined && change >= 0;
57
68
 
@@ -65,7 +76,9 @@ export const DashboardStatCard: React.FC<DashboardStatCardProps> = ({
65
76
  >
66
77
  {/* Header */}
67
78
  <View className='flex-row items-start justify-between mb-2'>
68
- <Text className='text-sm font-medium text-gray-600 dark:text-gray-400'>
79
+ <Text
80
+ className={`${designTokens.typography.size.sm} ${designTokens.typography.weight.medium} text-gray-600 dark:text-gray-400`}
81
+ >
69
82
  {title}
70
83
  </Text>
71
84
  {icon && (
@@ -74,7 +87,9 @@ export const DashboardStatCard: React.FC<DashboardStatCardProps> = ({
74
87
  </View>
75
88
 
76
89
  {/* Value */}
77
- <Text className='text-3xl font-bold text-gray-900 dark:text-white'>
90
+ <Text
91
+ className={`${designTokens.typography.size['3xl']} ${designTokens.typography.weight.bold} text-gray-900 dark:text-white`}
92
+ >
78
93
  {value}
79
94
  </Text>
80
95
 
@@ -83,7 +98,8 @@ export const DashboardStatCard: React.FC<DashboardStatCardProps> = ({
83
98
  <View className='flex-row items-center gap-1 mt-2'>
84
99
  <Text
85
100
  className={cn(
86
- 'text-sm font-medium',
101
+ designTokens.typography.size.sm,
102
+ designTokens.typography.weight.medium,
87
103
  isPositive
88
104
  ? 'text-green-600 dark:text-green-400'
89
105
  : 'text-red-600 dark:text-red-400'
@@ -91,7 +107,9 @@ export const DashboardStatCard: React.FC<DashboardStatCardProps> = ({
91
107
  >
92
108
  {isPositive ? '↑' : '↓'} {Math.abs(change)}%
93
109
  </Text>
94
- <Text className='text-xs text-gray-500 dark:text-gray-400'>
110
+ <Text
111
+ className={`${designTokens.typography.size.xs} text-gray-500 dark:text-gray-400`}
112
+ >
95
113
  {changePeriod}
96
114
  </Text>
97
115
  </View>
@@ -1,6 +1,7 @@
1
1
  import * as React from 'react';
2
2
  import { View, Text, Pressable, FlatList } from 'react-native';
3
3
  import { cn } from '../../lib/utils';
4
+ import { ui, designTokens } from '@sudobility/design';
4
5
 
5
6
  export interface DataListColumn<T> {
6
7
  /** Column key */
@@ -74,7 +75,13 @@ export function DataList<T extends Record<string, unknown>>({
74
75
  if (!showHeader) return null;
75
76
 
76
77
  return (
77
- <View className='flex-row bg-gray-50 dark:bg-gray-800 border-b border-gray-200 dark:border-gray-700'>
78
+ <View
79
+ className={cn(
80
+ 'flex-row',
81
+ ui.table.thead,
82
+ 'border-b border-gray-200 dark:border-gray-700'
83
+ )}
84
+ >
78
85
  {columns.map(column => (
79
86
  <View
80
87
  key={column.key}
@@ -84,7 +91,15 @@ export function DataList<T extends Record<string, unknown>>({
84
91
  )}
85
92
  style={{ flex: column.flex || 1 }}
86
93
  >
87
- <Text className='text-xs font-medium text-gray-700 dark:text-gray-300 uppercase tracking-wider'>
94
+ <Text
95
+ className={cn(
96
+ designTokens.typography.size.xs,
97
+ designTokens.typography.weight.medium,
98
+ 'text-gray-700 dark:text-gray-300',
99
+ designTokens.typography.transform.uppercase,
100
+ designTokens.typography.tracking.wider
101
+ )}
102
+ >
88
103
  {column.label}
89
104
  </Text>
90
105
  </View>
@@ -101,7 +116,7 @@ export function DataList<T extends Record<string, unknown>>({
101
116
  onPress={() => onRowPress?.(item, index)}
102
117
  className={cn(
103
118
  'flex-row border-b border-gray-200 dark:border-gray-700',
104
- isOdd && 'bg-gray-50 dark:bg-gray-800/50',
119
+ isOdd && ui.table.trAlt,
105
120
  onRowPress && 'active:bg-gray-100 dark:active:bg-gray-800'
106
121
  )}
107
122
  disabled={!onRowPress}
@@ -121,7 +136,10 @@ export function DataList<T extends Record<string, unknown>>({
121
136
  column.render(item, index)
122
137
  ) : (
123
138
  <Text
124
- className='text-sm text-gray-900 dark:text-white'
139
+ className={cn(
140
+ designTokens.typography.size.sm,
141
+ 'text-gray-900 dark:text-white'
142
+ )}
125
143
  numberOfLines={1}
126
144
  >
127
145
  {String(item[column.key] ?? '')}
@@ -142,7 +160,7 @@ export function DataList<T extends Record<string, unknown>>({
142
160
  );
143
161
 
144
162
  return (
145
- <View className={cn('bg-white dark:bg-gray-900', className)}>
163
+ <View className={cn(ui.table.tr, className)}>
146
164
  {renderHeader()}
147
165
  <FlatList
148
166
  data={data}
@@ -8,6 +8,9 @@ import {
8
8
  TouchableWithoutFeedback,
9
9
  } from 'react-native';
10
10
  import { cn } from '../../lib/utils';
11
+ import { designTokens } from '@sudobility/design';
12
+
13
+ const { typography } = designTokens;
11
14
 
12
15
  export interface DropdownItem {
13
16
  /** Unique identifier */
@@ -156,7 +159,7 @@ export const Dropdown: React.FC<DropdownProps> = ({
156
159
  {item.icon && <View className='w-5 h-5'>{item.icon}</View>}
157
160
  <Text
158
161
  className={cn(
159
- 'text-sm',
162
+ typography.size.sm,
160
163
  item.disabled
161
164
  ? 'text-gray-400 dark:text-gray-500'
162
165
  : 'text-gray-700 dark:text-gray-200'
@@ -2,6 +2,7 @@ import * as React from 'react';
2
2
  import { useCallback } from 'react';
3
3
  import { Text, Pressable, Linking } from 'react-native';
4
4
  import { cn } from '../../lib/utils';
5
+ import { textVariants } from '@sudobility/design';
5
6
 
6
7
  export interface ExternalLinkProps {
7
8
  /** Link URL */
@@ -63,11 +64,11 @@ export const ExternalLink: React.FC<ExternalLinkProps> = ({
63
64
  lg: 'text-base',
64
65
  };
65
66
 
66
- // Color variant configurations
67
+ // Color variant configurations using DS textVariants.link
67
68
  const variantClasses = {
68
- default: 'text-blue-600 dark:text-blue-400',
69
- primary: 'text-blue-700 dark:text-blue-300 font-semibold',
70
- muted: 'text-gray-600 dark:text-gray-400',
69
+ default: textVariants.link.external(),
70
+ primary: `${textVariants.link.default()} font-semibold`,
71
+ muted: textVariants.link.muted(),
71
72
  };
72
73
 
73
74
  const handlePress = useCallback(async () => {
@@ -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 { designTokens } from '@sudobility/design';
4
5
 
5
6
  export type FeatureCardColor =
6
7
  | 'green'
@@ -69,57 +70,58 @@ export const FeatureCard: React.FC<FeatureCardProps> = ({
69
70
  borderColor = false,
70
71
  className,
71
72
  }) => {
72
- // Color configurations
73
+ // Color configurations -- derived from colors.raw.* palette
74
+ // Each Tailwind class maps to a colors.raw hex value at the same shade
73
75
  const colorClasses: Record<FeatureCardColor, string> = {
74
- blue: 'text-blue-600 dark:text-blue-400',
75
- green: 'text-green-600 dark:text-green-400',
76
+ blue: 'text-blue-600 dark:text-blue-400', // colors.raw.blue[600] / [400]
77
+ green: 'text-green-600 dark:text-green-400', // colors.raw.green[600] / [400]
76
78
  purple: 'text-purple-600 dark:text-purple-400',
77
- orange: 'text-orange-600 dark:text-orange-400',
79
+ orange: 'text-orange-600 dark:text-orange-400', // colors.raw.orange[600] / [400]
78
80
  pink: 'text-pink-600 dark:text-pink-400',
79
- gray: 'text-gray-600 dark:text-gray-400',
80
- red: 'text-red-600 dark:text-red-400',
81
+ gray: 'text-gray-600 dark:text-gray-400', // colors.raw.neutral[600] / [400]
82
+ red: 'text-red-600 dark:text-red-400', // colors.raw.red[600] / [400]
81
83
  indigo: 'text-indigo-600 dark:text-indigo-400',
82
84
  cyan: 'text-cyan-600 dark:text-cyan-400',
83
85
  emerald: 'text-emerald-600 dark:text-emerald-400',
84
86
  };
85
87
 
86
88
  const borderColorClasses: Record<FeatureCardColor, string> = {
87
- green: 'border-l-4 border-l-green-500',
88
- blue: 'border-l-4 border-l-blue-500',
89
- purple: 'border-l-4 border-l-purple-500',
90
- orange: 'border-l-4 border-l-orange-500',
91
- red: 'border-l-4 border-l-red-500',
89
+ green: 'border-l-4 border-l-green-500', // colors.raw.green[500]
90
+ blue: 'border-l-4 border-l-blue-500', // colors.raw.blue[500]
91
+ purple: 'border-l-4 border-l-purple-500', // colors.raw.purple[500]
92
+ orange: 'border-l-4 border-l-orange-500', // colors.raw.orange[500]
93
+ red: 'border-l-4 border-l-red-500', // colors.raw.red[500]
92
94
  indigo: 'border-l-4 border-l-indigo-500',
93
95
  cyan: 'border-l-4 border-l-cyan-500',
94
96
  emerald: 'border-l-4 border-l-emerald-500',
95
97
  pink: 'border-l-4 border-l-pink-500',
96
- gray: 'border-l-4 border-l-gray-500',
98
+ gray: 'border-l-4 border-l-gray-500', // colors.raw.neutral[500]
97
99
  };
98
100
 
99
101
  const iconBackgroundClasses: Record<FeatureCardColor, string> = {
100
- green: 'bg-green-100 dark:bg-green-900/20',
101
- blue: 'bg-blue-100 dark:bg-blue-900/20',
102
- purple: 'bg-purple-100 dark:bg-purple-900/20',
103
- orange: 'bg-orange-100 dark:bg-orange-900/20',
104
- red: 'bg-red-100 dark:bg-red-900/20',
102
+ green: 'bg-green-100 dark:bg-green-900/20', // colors.raw.green[100] / [900]
103
+ blue: 'bg-blue-100 dark:bg-blue-900/20', // colors.raw.blue[100] / [900]
104
+ purple: 'bg-purple-100 dark:bg-purple-900/20', // colors.raw.purple[100] / [900]
105
+ orange: 'bg-orange-100 dark:bg-orange-900/20', // colors.raw.orange[100] / [900]
106
+ red: 'bg-red-100 dark:bg-red-900/20', // colors.raw.red[100] / [900]
105
107
  indigo: 'bg-indigo-100 dark:bg-indigo-900/20',
106
108
  cyan: 'bg-cyan-100 dark:bg-cyan-900/20',
107
109
  emerald: 'bg-emerald-100 dark:bg-emerald-900/20',
108
110
  pink: 'bg-pink-100 dark:bg-pink-900/20',
109
- gray: 'bg-gray-100 dark:bg-gray-900/20',
111
+ gray: 'bg-gray-100 dark:bg-gray-900/20', // colors.raw.neutral[100] / [900]
110
112
  };
111
113
 
112
114
  const bulletColorClasses: Record<FeatureCardColor, string> = {
113
- green: 'bg-green-500',
114
- blue: 'bg-blue-500',
115
- purple: 'bg-purple-500',
116
- orange: 'bg-orange-500',
117
- red: 'bg-red-500',
115
+ green: 'bg-green-500', // colors.raw.green[500]
116
+ blue: 'bg-blue-500', // colors.raw.blue[500]
117
+ purple: 'bg-purple-500', // colors.raw.purple[500]
118
+ orange: 'bg-orange-500', // colors.raw.orange[500]
119
+ red: 'bg-red-500', // colors.raw.red[500]
118
120
  indigo: 'bg-indigo-500',
119
121
  cyan: 'bg-cyan-500',
120
122
  emerald: 'bg-emerald-500',
121
123
  pink: 'bg-pink-500',
122
- gray: 'bg-gray-500',
124
+ gray: 'bg-gray-500', // colors.raw.neutral[500]
123
125
  };
124
126
 
125
127
  const CardContent = () => (
@@ -139,12 +141,24 @@ export const FeatureCard: React.FC<FeatureCardProps> = ({
139
141
  )}
140
142
 
141
143
  {/* Title */}
142
- <Text className='text-xl font-semibold text-gray-900 dark:text-white mb-3'>
144
+ <Text
145
+ className={cn(
146
+ designTokens.typography.size.xl,
147
+ designTokens.typography.weight.semibold,
148
+ 'text-gray-900 dark:text-white mb-3'
149
+ )}
150
+ >
143
151
  {title}
144
152
  </Text>
145
153
 
146
154
  {/* Description */}
147
- <Text className='text-gray-600 dark:text-gray-300 mb-4 leading-relaxed'>
155
+ <Text
156
+ className={cn(
157
+ designTokens.typography.size.base,
158
+ designTokens.typography.leading.relaxed,
159
+ 'text-gray-600 dark:text-gray-300 mb-4'
160
+ )}
161
+ >
148
162
  {description}
149
163
  </Text>
150
164
 
@@ -162,7 +176,13 @@ export const FeatureCard: React.FC<FeatureCardProps> = ({
162
176
  bulletColorClasses[color]
163
177
  )}
164
178
  />
165
- <Text className='flex-1 text-sm text-gray-600 dark:text-gray-400'>
179
+ <Text
180
+ className={cn(
181
+ 'flex-1',
182
+ designTokens.typography.size.sm,
183
+ 'text-gray-600 dark:text-gray-400'
184
+ )}
185
+ >
166
186
  {benefit}
167
187
  </Text>
168
188
  </View>
@@ -178,10 +198,21 @@ export const FeatureCard: React.FC<FeatureCardProps> = ({
178
198
  key={index}
179
199
  className='flex-1 min-w-[80px] items-center p-3 bg-gray-50 dark:bg-gray-700/50 rounded-lg'
180
200
  >
181
- <Text className={cn('text-lg font-bold', colorClasses[color])}>
201
+ <Text
202
+ className={cn(
203
+ designTokens.typography.size.lg,
204
+ designTokens.typography.weight.bold,
205
+ colorClasses[color]
206
+ )}
207
+ >
182
208
  {value}
183
209
  </Text>
184
- <Text className='text-xs text-gray-500 dark:text-gray-400 mt-1'>
210
+ <Text
211
+ className={cn(
212
+ designTokens.typography.size.xs,
213
+ 'text-gray-500 dark:text-gray-400 mt-1'
214
+ )}
215
+ >
185
216
  {key}
186
217
  </Text>
187
218
  </View>
@@ -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, getCardVariantColors } from '@sudobility/design';
4
5
 
5
6
  export interface Feature {
6
7
  /** Unique identifier */
@@ -72,13 +73,12 @@ export const FeatureGrid: React.FC<FeatureGridProps> = ({
72
73
  lg: 'w-20 h-20',
73
74
  };
74
75
 
76
+ // Badge variants using DS badge colors
75
77
  const badgeVariants = {
76
- success:
77
- 'bg-green-100 dark:bg-green-900/30 text-green-800 dark:text-green-300',
78
- info: 'bg-blue-100 dark:bg-blue-900/30 text-blue-800 dark:text-blue-300',
79
- warning:
80
- 'bg-amber-100 dark:bg-amber-900/30 text-amber-800 dark:text-amber-300',
81
- default: 'bg-gray-100 dark:bg-gray-800 text-gray-800 dark:text-gray-300',
78
+ success: `${colors.component.badge.success.base} ${colors.component.badge.success.dark}`,
79
+ info: `${colors.component.badge.primary.base} ${colors.component.badge.primary.dark}`,
80
+ warning: `${colors.component.badge.attention.base} ${colors.component.badge.attention.dark}`,
81
+ default: `${colors.component.badge.default.base} ${colors.component.badge.default.dark}`,
82
82
  };
83
83
 
84
84
  const renderFeature = (feature: Feature, index: number) => {
@@ -87,7 +87,7 @@ export const FeatureGrid: React.FC<FeatureGridProps> = ({
87
87
  className={cn(
88
88
  'items-center',
89
89
  cardVariant === 'card' &&
90
- 'bg-white dark:bg-gray-800 rounded-2xl p-6 shadow-lg',
90
+ `${getCardVariantColors('elevated')} rounded-2xl p-6`,
91
91
  cardVariant === 'minimal' && 'gap-4'
92
92
  )}
93
93
  >
@@ -1,6 +1,7 @@
1
1
  import * as React from 'react';
2
2
  import { View, StyleSheet } from 'react-native';
3
3
  import { cn } from '../../lib/utils';
4
+ import { colors } from '@sudobility/design';
4
5
 
5
6
  export interface GradientIconContainerProps {
6
7
  /** Icon element */
@@ -28,6 +29,36 @@ export interface GradientIconContainerProps {
28
29
  * </GradientIconContainer>
29
30
  * ```
30
31
  */
32
+
33
+ // Lazily derive gradient icon colors from DS to avoid ESM issues in tests.
34
+ let _gradientIconColors: Record<string, string> | null = null;
35
+ function getGradientIconColors() {
36
+ if (!_gradientIconColors) {
37
+ const btn = colors.component.button;
38
+ // Extract the leading bg-* class from DS button base strings (solid colors)
39
+ function extractBg(base: string) {
40
+ return (
41
+ base
42
+ .split(' ')
43
+ .find(
44
+ c =>
45
+ c.startsWith('bg-') &&
46
+ !c.includes('hover:') &&
47
+ !c.includes('active:')
48
+ ) || ''
49
+ );
50
+ }
51
+ _gradientIconColors = {
52
+ blue: extractBg(btn.primary.base),
53
+ purple: 'bg-purple-600', // DS has no purple button; local fallback
54
+ green: extractBg(btn.success.base),
55
+ orange: 'bg-orange-600', // DS has no orange button; local fallback
56
+ gray: 'bg-gray-700 dark:bg-gray-600',
57
+ };
58
+ }
59
+ return _gradientIconColors;
60
+ }
61
+
31
62
  export const GradientIconContainer: React.FC<GradientIconContainerProps> = ({
32
63
  children,
33
64
  size = 'md',
@@ -50,14 +81,8 @@ export const GradientIconContainer: React.FC<GradientIconContainerProps> = ({
50
81
  circle: 'rounded-full',
51
82
  };
52
83
 
53
- // Color variants (solid colors approximating gradients)
54
- const variantClasses = {
55
- blue: 'bg-blue-600',
56
- purple: 'bg-purple-600',
57
- green: 'bg-green-600',
58
- orange: 'bg-orange-600',
59
- gray: 'bg-gray-700 dark:bg-gray-600',
60
- };
84
+ // Color variants from DS (solid colors approximating gradients)
85
+ const variantClasses = getGradientIconColors();
61
86
 
62
87
  const config = sizeConfig[size];
63
88