@idealyst/components 1.1.7 → 1.1.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (105) hide show
  1. package/package.json +3 -3
  2. package/src/Accordion/Accordion.native.tsx +8 -6
  3. package/src/Accordion/Accordion.styles.old.tsx +298 -0
  4. package/src/Accordion/Accordion.styles.tsx +102 -236
  5. package/src/ActivityIndicator/ActivityIndicator.styles.old.tsx +94 -0
  6. package/src/ActivityIndicator/ActivityIndicator.styles.tsx +44 -74
  7. package/src/Alert/Alert.native.tsx +16 -6
  8. package/src/Alert/Alert.styles.old.tsx +209 -0
  9. package/src/Alert/Alert.styles.tsx +67 -149
  10. package/src/Avatar/Avatar.styles.old.tsx +99 -0
  11. package/src/Avatar/Avatar.styles.tsx +35 -80
  12. package/src/Badge/Badge.styles.old.tsx +157 -0
  13. package/src/Badge/Badge.styles.tsx +61 -121
  14. package/src/Breadcrumb/Breadcrumb.styles.old.tsx +231 -0
  15. package/src/Breadcrumb/Breadcrumb.styles.tsx +83 -200
  16. package/src/Breadcrumb/Breadcrumb.web.tsx +28 -23
  17. package/src/Button/Button.styles.tsx +89 -141
  18. package/src/Card/Card.native.tsx +7 -11
  19. package/src/Card/Card.styles.old.tsx +160 -0
  20. package/src/Card/Card.styles.tsx +105 -142
  21. package/src/Card/Card.web.tsx +5 -4
  22. package/src/Checkbox/Checkbox.native.tsx +9 -5
  23. package/src/Checkbox/Checkbox.styles.old.tsx +271 -0
  24. package/src/Checkbox/Checkbox.styles.tsx +104 -216
  25. package/src/Checkbox/Checkbox.web.tsx +6 -6
  26. package/src/Chip/Chip.styles.old.tsx +184 -0
  27. package/src/Chip/Chip.styles.tsx +34 -72
  28. package/src/Dialog/Dialog.native.tsx +7 -4
  29. package/src/Dialog/Dialog.styles.old.tsx +202 -0
  30. package/src/Dialog/Dialog.styles.tsx +69 -133
  31. package/src/Divider/Divider.styles.old.tsx +172 -0
  32. package/src/Divider/Divider.styles.tsx +62 -84
  33. package/src/Icon/Icon.native.tsx +8 -8
  34. package/src/Icon/Icon.styles.old.tsx +81 -0
  35. package/src/Icon/Icon.styles.tsx +52 -66
  36. package/src/Icon/Icon.web.tsx +43 -7
  37. package/src/Icon/IconSvg/IconSvg.web.tsx +2 -0
  38. package/src/Image/Image.styles.old.tsx +69 -0
  39. package/src/Image/Image.styles.tsx +46 -60
  40. package/src/Input/Input.native.tsx +138 -53
  41. package/src/Input/Input.styles.old.tsx +289 -0
  42. package/src/Input/Input.styles.tsx +127 -198
  43. package/src/List/List.native.tsx +5 -2
  44. package/src/List/List.styles.old.tsx +242 -0
  45. package/src/List/List.styles.tsx +179 -215
  46. package/src/List/ListItem.native.tsx +12 -6
  47. package/src/List/ListItem.web.tsx +23 -13
  48. package/src/Menu/Menu.styles.old.tsx +197 -0
  49. package/src/Menu/Menu.styles.tsx +68 -150
  50. package/src/Menu/MenuItem.native.tsx +5 -3
  51. package/src/Menu/MenuItem.styles.old.tsx +114 -0
  52. package/src/Menu/MenuItem.styles.tsx +57 -89
  53. package/src/Menu/MenuItem.web.tsx +8 -3
  54. package/src/Popover/Popover.native.tsx +10 -4
  55. package/src/Popover/Popover.styles.old.tsx +135 -0
  56. package/src/Popover/Popover.styles.tsx +51 -112
  57. package/src/Pressable/Pressable.styles.old.tsx +27 -0
  58. package/src/Pressable/Pressable.styles.tsx +35 -27
  59. package/src/Progress/Progress.styles.old.tsx +200 -0
  60. package/src/Progress/Progress.styles.tsx +75 -164
  61. package/src/RadioButton/RadioButton.native.tsx +4 -3
  62. package/src/RadioButton/RadioButton.styles.old.tsx +175 -0
  63. package/src/RadioButton/RadioButton.styles.tsx +83 -154
  64. package/src/RadioButton/RadioButton.web.tsx +2 -2
  65. package/src/SVGImage/SVGImage.styles.old.tsx +86 -0
  66. package/src/SVGImage/SVGImage.styles.tsx +35 -78
  67. package/src/Screen/Screen.native.tsx +18 -25
  68. package/src/Screen/Screen.styles.old.tsx +87 -0
  69. package/src/Screen/Screen.styles.tsx +105 -67
  70. package/src/Screen/Screen.web.tsx +1 -1
  71. package/src/Select/Select.native.tsx +42 -33
  72. package/src/Select/Select.styles.old.tsx +353 -0
  73. package/src/Select/Select.styles.tsx +223 -292
  74. package/src/Skeleton/Skeleton.styles.old.tsx +67 -0
  75. package/src/Skeleton/Skeleton.styles.tsx +29 -53
  76. package/src/Slider/Slider.styles.old.tsx +259 -0
  77. package/src/Slider/Slider.styles.tsx +153 -234
  78. package/src/Switch/Switch.native.tsx +7 -5
  79. package/src/Switch/Switch.styles.old.tsx +203 -0
  80. package/src/Switch/Switch.styles.tsx +101 -174
  81. package/src/Switch/Switch.web.tsx +5 -5
  82. package/src/TabBar/TabBar.native.tsx +3 -2
  83. package/src/TabBar/TabBar.styles.old.tsx +343 -0
  84. package/src/TabBar/TabBar.styles.tsx +145 -279
  85. package/src/Table/Table.native.tsx +18 -9
  86. package/src/Table/Table.styles.old.tsx +311 -0
  87. package/src/Table/Table.styles.tsx +152 -286
  88. package/src/Text/Text.native.tsx +1 -3
  89. package/src/Text/Text.style.demo.tsx +16 -0
  90. package/src/Text/Text.styles.old.tsx +219 -0
  91. package/src/Text/Text.styles.tsx +94 -84
  92. package/src/Text/Text.web.tsx +2 -2
  93. package/src/Text/index.ts +1 -0
  94. package/src/TextArea/TextArea.styles.old.tsx +213 -0
  95. package/src/TextArea/TextArea.styles.tsx +93 -181
  96. package/src/Tooltip/Tooltip.styles.old.tsx +82 -0
  97. package/src/Tooltip/Tooltip.styles.tsx +32 -56
  98. package/src/Video/Video.styles.old.tsx +51 -0
  99. package/src/Video/Video.styles.tsx +32 -44
  100. package/src/View/View.native.tsx +12 -14
  101. package/src/View/View.styles.old.tsx +125 -0
  102. package/src/View/View.styles.tsx +76 -106
  103. package/src/View/View.web.tsx +1 -0
  104. package/src/examples/CardExamples.tsx +0 -6
  105. package/src/extensions/extendComponent.ts +61 -0
@@ -1,248 +1,212 @@
1
- import { StyleSheet } from 'react-native-unistyles';
2
- import { Theme } from '@idealyst/theme';
3
- import { buildSizeVariants } from '../utils/buildSizeVariants';
4
- import {
5
- buildGapVariants,
6
- buildPaddingVariants,
7
- buildPaddingVerticalVariants,
8
- buildPaddingHorizontalVariants,
9
- buildMarginVariants,
10
- buildMarginVerticalVariants,
11
- buildMarginHorizontalVariants,
12
- } from '../utils/buildViewStyleVariants';
13
- import { ListSizeVariant, ListType } from './types';
14
- import { applyExtensions } from '../extensions/applyExtension';
15
-
16
- type ListVariants = {
17
- type: ListType;
18
- size: ListSizeVariant;
19
- scrollable: boolean;
20
- active: boolean;
21
- selected: boolean;
22
- disabled: boolean;
23
- clickable: boolean;
24
- };
25
-
26
1
  /**
27
- * Create type variants for container
2
+ * List styles using defineStyle with dynamic props.
28
3
  */
29
- function createContainerTypeVariants(theme: Theme) {
30
- return {
31
- default: {
32
- backgroundColor: 'transparent',
33
- },
34
- bordered: {
35
- backgroundColor: theme.colors.surface.primary,
36
- borderWidth: 1,
37
- borderColor: theme.colors.border.primary,
38
- borderRadius: 8,
39
- _web: {
40
- overflow: 'hidden',
41
- border: `1px solid ${theme.colors.border.primary}`,
42
- },
43
- },
44
- divided: {
45
- backgroundColor: 'transparent',
46
- },
47
- };
48
- }
4
+ import { StyleSheet } from 'react-native-unistyles';
5
+ import { defineStyle, ThemeStyleWrapper } from '@idealyst/theme';
6
+ import type { Theme as BaseTheme, Size } from '@idealyst/theme';
7
+ import { ViewStyleSize } from '../utils/viewStyleProps';
8
+
9
+ // Required: Unistyles must see StyleSheet usage in original source to process this file
10
+ void StyleSheet;
49
11
 
12
+ // Wrap theme for $iterator support
13
+ type Theme = ThemeStyleWrapper<BaseTheme>;
50
14
 
51
- type ItemDynamicProps = {
15
+ type ListType = 'default' | 'bordered' | 'divided';
16
+
17
+ export type ListDynamicProps = {
18
+ size?: Size;
52
19
  type?: ListType;
20
+ scrollable?: boolean;
21
+ active?: boolean;
22
+ selected?: boolean;
53
23
  disabled?: boolean;
54
24
  clickable?: boolean;
25
+ gap?: ViewStyleSize;
26
+ padding?: ViewStyleSize;
27
+ paddingVertical?: ViewStyleSize;
28
+ paddingHorizontal?: ViewStyleSize;
29
+ margin?: ViewStyleSize;
30
+ marginVertical?: ViewStyleSize;
31
+ marginHorizontal?: ViewStyleSize;
55
32
  };
56
33
 
57
34
  /**
58
- * Get item hover styles based on disabled and clickable state
35
+ * List styles with type/state handling.
59
36
  */
60
- function getItemHoverStyles(theme: Theme, disabled: boolean, clickable: boolean) {
61
- if (disabled || !clickable) {
62
- return {
37
+ export const listStyles = defineStyle('List', (theme: Theme) => ({
38
+ container: ({ type = 'default', scrollable = false }: ListDynamicProps) => {
39
+ const typeStyles = type === 'bordered' ? {
40
+ backgroundColor: theme.colors.surface.primary,
41
+ borderWidth: 1,
42
+ borderColor: theme.colors.border.primary,
43
+ borderRadius: 8,
44
+ } : {
63
45
  backgroundColor: 'transparent',
64
- borderRadius: 0,
65
46
  };
66
- }
67
- return {
68
- backgroundColor: theme.colors.surface.secondary,
69
- borderRadius: 4,
70
- };
71
- }
72
-
73
47
 
74
- // Container style creator for extension support
75
- function createContainerStyles(theme: Theme) {
76
- return () => ({
77
- display: 'flex' as const,
78
- flexDirection: 'column' as const,
79
- width: '100%',
80
- variants: {
81
- type: createContainerTypeVariants(theme),
82
- scrollable: {
83
- true: {
84
- _web: {
85
- overflow: 'auto',
86
- },
48
+ return {
49
+ display: 'flex' as const,
50
+ flexDirection: 'column' as const,
51
+ width: '100%',
52
+ ...typeStyles,
53
+ variants: {
54
+ gap: {
55
+ gap: theme.sizes.$view.padding,
56
+ },
57
+ padding: {
58
+ padding: theme.sizes.$view.padding,
59
+ },
60
+ paddingVertical: {
61
+ paddingVertical: theme.sizes.$view.padding,
62
+ },
63
+ paddingHorizontal: {
64
+ paddingHorizontal: theme.sizes.$view.padding,
65
+ },
66
+ margin: {
67
+ margin: theme.sizes.$view.padding,
68
+ },
69
+ marginVertical: {
70
+ marginVertical: theme.sizes.$view.padding,
71
+ },
72
+ marginHorizontal: {
73
+ marginHorizontal: theme.sizes.$view.padding,
87
74
  },
88
- false: {},
89
75
  },
90
- // Spacing variants from ContainerStyleProps
91
- gap: buildGapVariants(theme),
92
- padding: buildPaddingVariants(theme),
93
- paddingVertical: buildPaddingVerticalVariants(theme),
94
- paddingHorizontal: buildPaddingHorizontalVariants(theme),
95
- margin: buildMarginVariants(theme),
96
- marginVertical: buildMarginVerticalVariants(theme),
97
- marginHorizontal: buildMarginHorizontalVariants(theme),
98
- },
99
- });
100
- }
76
+ _web: {
77
+ overflow: type === 'bordered' ? 'hidden' : (scrollable ? 'auto' : undefined),
78
+ border: type === 'bordered' ? `1px solid ${theme.colors.border.primary}` : undefined,
79
+ },
80
+ } as const;
81
+ },
82
+
83
+ item: ({ type = 'default', active = false, selected = false, disabled = false, clickable = true }: ListDynamicProps) => {
84
+ const baseStyles = {
85
+ display: 'flex' as const,
86
+ flexDirection: 'row' as const,
87
+ alignItems: 'center' as const,
88
+ backgroundColor: active ? theme.colors.surface.secondary : 'transparent',
89
+ textAlign: 'left' as const,
90
+ opacity: disabled ? 0.5 : 1,
91
+ };
92
+
93
+ const dividerStyles = type === 'divided' ? {
94
+ borderBottomWidth: 1,
95
+ borderBottomColor: theme.colors.border.primary,
96
+ } : {};
97
+
98
+ const selectedStyles = selected ? {
99
+ backgroundColor: theme.intents.primary.light + '20',
100
+ borderLeftWidth: 3,
101
+ borderLeftColor: theme.intents.primary.primary,
102
+ } : {};
101
103
 
102
- // Item style creator for extension support
103
- function createItemStyles(theme: Theme) {
104
- return ({ type = 'default', disabled = false, clickable = true }: ItemDynamicProps) => {
105
- const hoverStyles = getItemHoverStyles(theme, disabled, clickable);
106
104
  return {
107
- display: 'flex',
108
- flexDirection: 'row',
109
- alignItems: 'center',
110
- backgroundColor: 'transparent',
111
- textAlign: 'left',
112
- borderBottomWidth: type === 'divided' ? 1 : 0,
113
- borderBottomStyle: type === 'divided' ? 'solid' as const : undefined,
114
- borderBottomColor: type === 'divided' ? theme.colors.border.primary : undefined,
105
+ ...baseStyles,
106
+ ...dividerStyles,
107
+ ...selectedStyles,
115
108
  variants: {
116
- size: buildSizeVariants(theme, 'list', (size) => ({
117
- paddingVertical: size.paddingVertical,
118
- paddingHorizontal: size.paddingHorizontal,
119
- minHeight: size.minHeight,
120
- })),
121
- active: {
122
- true: {
123
- backgroundColor: theme.colors.surface.secondary,
124
- },
125
- false: {},
109
+ size: {
110
+ paddingVertical: theme.sizes.$list.paddingVertical,
111
+ paddingHorizontal: theme.sizes.$list.paddingHorizontal,
112
+ minHeight: theme.sizes.$list.minHeight,
126
113
  },
127
- selected: {
128
- true: {
129
- backgroundColor: theme.intents.primary.light + '20',
130
- borderLeftWidth: 3,
131
- borderLeftColor: theme.intents.primary.primary,
132
- _web: {
133
- borderLeft: `3px solid ${theme.intents.primary.primary}`,
134
- },
135
- },
136
- false: {},
137
- },
138
- } as const,
139
- opacity: disabled ? 0.5 : 1,
114
+ },
140
115
  _web: {
141
116
  border: 'none',
142
117
  cursor: disabled ? 'not-allowed' : (clickable ? 'pointer' : 'default'),
143
118
  outline: 'none',
144
119
  transition: 'background-color 0.2s ease, border-color 0.2s ease',
145
120
  borderBottom: type === 'divided' ? `1px solid ${theme.colors.border.primary}` : undefined,
146
- _hover: hoverStyles,
121
+ borderLeft: selected ? `3px solid ${theme.intents.primary.primary}` : undefined,
122
+ _hover: (disabled || !clickable) ? {} : {
123
+ backgroundColor: theme.colors.surface.secondary,
124
+ borderRadius: 4,
125
+ },
147
126
  },
148
127
  } as const;
149
- };
150
- }
151
-
152
- export const listStyles = StyleSheet.create((theme: Theme) => {
153
- // Apply extensions to main visual elements
154
- const extended = applyExtensions('List', theme, {
155
- container: createContainerStyles(theme),
156
- item: createItemStyles(theme),
157
- });
158
-
159
- return {
160
- ...extended,
161
- // Minor utility styles (not extended)
162
- itemContent: {
163
- display: 'flex',
164
- flexDirection: 'row',
165
- alignItems: 'center',
166
- flex: 1,
167
- gap: 8,
168
- },
169
- leading: {
170
- display: 'flex',
171
- alignItems: 'center',
172
- justifyContent: 'center',
173
- marginRight: 8,
174
- color: theme.colors.text.secondary,
175
- variants: {
176
- size: buildSizeVariants(theme, 'list', (size) => ({
177
- width: size.iconSize,
178
- height: size.iconSize,
179
- })),
180
- } as const,
181
- } as const,
182
- labelContainer: {
183
- flex: 1,
184
- display: 'flex',
185
- flexDirection: 'column',
186
- },
187
- label: {
188
- fontWeight: '500',
189
- color: theme.colors.text.primary,
190
- variants: {
191
- size: buildSizeVariants(theme, 'list', (size) => ({
192
- fontSize: size.labelFontSize,
193
- lineHeight: size.labelLineHeight,
194
- })),
195
- disabled: {
196
- true: {
197
- color: theme.colors.text.secondary,
198
- },
199
- false: {},
200
- },
201
- selected: {
202
- true: {
203
- color: theme.intents.primary.primary,
204
- fontWeight: '600',
205
- },
206
- false: {},
207
- },
128
+ },
129
+
130
+ itemContent: (_props: ListDynamicProps) => ({
131
+ display: 'flex' as const,
132
+ flexDirection: 'row' as const,
133
+ alignItems: 'center' as const,
134
+ flex: 1,
135
+ gap: 8,
136
+ }),
137
+
138
+ leading: (_props: ListDynamicProps) => ({
139
+ display: 'flex' as const,
140
+ alignItems: 'center' as const,
141
+ justifyContent: 'center' as const,
142
+ marginRight: 8,
143
+ color: theme.colors.text.secondary,
144
+ variants: {
145
+ size: {
146
+ width: theme.sizes.$list.iconSize,
147
+ height: theme.sizes.$list.iconSize,
148
+ fontSize: theme.sizes.$list.iconSize,
208
149
  },
209
150
  },
210
- trailing: {
211
- display: 'flex',
212
- alignItems: 'center',
213
- justifyContent: 'center',
214
- marginLeft: 8,
215
- color: theme.colors.text.secondary,
216
- flexShrink: 0,
217
- },
218
- trailingIcon: {
219
- display: 'flex',
220
- alignItems: 'center',
221
- justifyContent: 'center',
222
- variants: {
223
- size: buildSizeVariants(theme, 'list', (size) => ({
224
- width: size.iconSize,
225
- height: size.iconSize,
226
- })),
151
+ }),
152
+
153
+ labelContainer: (_props: ListDynamicProps) => ({
154
+ flex: 1,
155
+ display: 'flex' as const,
156
+ flexDirection: 'column' as const,
157
+ }),
158
+
159
+ label: ({ disabled = false, selected = false }: ListDynamicProps) => ({
160
+ fontWeight: selected ? ('600' as const) : ('500' as const),
161
+ color: selected ? theme.intents.primary.primary : (disabled ? theme.colors.text.secondary : theme.colors.text.primary),
162
+ variants: {
163
+ size: {
164
+ fontSize: theme.sizes.$list.labelFontSize,
165
+ lineHeight: theme.sizes.$list.labelLineHeight,
227
166
  },
228
167
  },
229
- section: {
230
- display: 'flex',
231
- flexDirection: 'column',
232
- },
233
- sectionTitle: {
234
- fontWeight: '600',
235
- fontSize: 12,
236
- lineHeight: 16,
237
- textTransform: 'uppercase',
238
- letterSpacing: 0.5,
239
- color: theme.colors.text.secondary,
240
- padding: 8,
241
- paddingBottom: 4,
242
- },
243
- sectionContent: {
244
- display: 'flex',
245
- flexDirection: 'column',
168
+ }),
169
+
170
+ trailing: (_props: ListDynamicProps) => ({
171
+ display: 'flex' as const,
172
+ alignItems: 'center' as const,
173
+ justifyContent: 'center' as const,
174
+ marginLeft: 8,
175
+ color: theme.colors.text.secondary,
176
+ flexShrink: 0,
177
+ }),
178
+
179
+ trailingIcon: (_props: ListDynamicProps) => ({
180
+ display: 'flex' as const,
181
+ alignItems: 'center' as const,
182
+ justifyContent: 'center' as const,
183
+ variants: {
184
+ size: {
185
+ width: theme.sizes.$list.iconSize,
186
+ height: theme.sizes.$list.iconSize,
187
+ fontSize: theme.sizes.$list.iconSize,
188
+ },
246
189
  },
247
- };
248
- });
190
+ }),
191
+
192
+ section: (_props: ListDynamicProps) => ({
193
+ display: 'flex' as const,
194
+ flexDirection: 'column' as const,
195
+ }),
196
+
197
+ sectionTitle: (_props: ListDynamicProps) => ({
198
+ fontWeight: '600' as const,
199
+ fontSize: 12,
200
+ lineHeight: 16,
201
+ textTransform: 'uppercase' as const,
202
+ letterSpacing: 0.5,
203
+ color: theme.colors.text.secondary,
204
+ padding: 8,
205
+ paddingBottom: 4,
206
+ }),
207
+
208
+ sectionContent: (_props: ListDynamicProps) => ({
209
+ display: 'flex' as const,
210
+ flexDirection: 'column' as const,
211
+ }),
212
+ }));
@@ -59,8 +59,14 @@ const ListItem = forwardRef<ComponentRef<typeof View> | ComponentRef<typeof Pres
59
59
  disabled,
60
60
  });
61
61
 
62
- // Get dynamic item style with type, disabled, and clickable props
62
+ // Get dynamic styles - call as functions to get theme-reactive styles
63
63
  const itemStyle = (listStyles.item as any)({ type: effectiveVariant, disabled, clickable: isClickable });
64
+ const labelStyle = (listStyles.label as any)({ disabled, selected });
65
+ const leadingStyle = (listStyles.leading as any)({});
66
+ const trailingStyle = (listStyles.trailing as any)({});
67
+ const trailingIconStyle = (listStyles.trailingIcon as any)({});
68
+ const labelContainerStyle = (listStyles.labelContainer as any)({});
69
+ const itemContentStyle = (listStyles.itemContent as any)({});
64
70
 
65
71
  // Resolve icon color - check intents first, then color palette
66
72
  const resolvedIconColor = (() => {
@@ -79,7 +85,7 @@ const ListItem = forwardRef<ComponentRef<typeof View> | ComponentRef<typeof Pres
79
85
 
80
86
  // If it's a string, treat it as an icon name
81
87
  if (typeof element === 'string') {
82
- const iconStyle = styleKey === 'leading' ? listStyles.leading : listStyles.trailingIcon;
88
+ const iconStyle = styleKey === 'leading' ? leadingStyle : trailingIconStyle;
83
89
  return (
84
90
  <MaterialCommunityIcons
85
91
  name={element}
@@ -98,20 +104,20 @@ const ListItem = forwardRef<ComponentRef<typeof View> | ComponentRef<typeof Pres
98
104
  const content = (
99
105
  <>
100
106
  {leading && (
101
- <View style={listStyles.leading}>
107
+ <View style={leadingStyle}>
102
108
  {renderElement(leading, 'leading')}
103
109
  </View>
104
110
  )}
105
111
 
106
- <View style={listStyles.labelContainer}>
112
+ <View style={labelContainerStyle}>
107
113
  {label && (
108
- <Text style={listStyles.label}>{label}</Text>
114
+ <Text style={labelStyle}>{label}</Text>
109
115
  )}
110
116
  {children}
111
117
  </View>
112
118
 
113
119
  {trailing && (
114
- <View style={listStyles.trailing}>
120
+ <View style={trailingStyle}>
115
121
  {renderElement(trailing, 'trailingIcon')}
116
122
  </View>
117
123
  )}
@@ -40,13 +40,19 @@ const ListItem: React.FC<ListItemProps> = ({
40
40
  disabled,
41
41
  });
42
42
 
43
- // Get dynamic item style with type, disabled, and clickable props
43
+ // Get dynamic styles - call as functions for theme reactivity
44
44
  const itemStyle = (listStyles.item as any)({ type: effectiveVariant, disabled, clickable: isClickable });
45
+ const labelStyle = (listStyles.label as any)({ disabled, selected });
46
+ const leadingStyle = (listStyles.leading as any)({});
47
+ const trailingStyle = (listStyles.trailing as any)({});
48
+ const trailingIconStyle = (listStyles.trailingIcon as any)({});
49
+ const labelContainerStyle = (listStyles.labelContainer as any)({});
50
+
45
51
  const itemProps = getWebProps([itemStyle, style]);
46
- const labelProps = getWebProps([listStyles.label]);
47
- const leadingProps = getWebProps([listStyles.leading]);
48
- const trailingProps = getWebProps([listStyles.trailing]);
49
- const trailingIconProps = getWebProps([listStyles.trailing, listStyles.trailingIcon]);
52
+ const labelProps = getWebProps([labelStyle]);
53
+ const leadingProps = getWebProps([leadingStyle]);
54
+ const trailingProps = getWebProps([trailingStyle]);
55
+ const trailingIconProps = getWebProps([trailingStyle, trailingIconStyle]);
50
56
 
51
57
  const handleClick = () => {
52
58
  if (!disabled && onPress) {
@@ -66,18 +72,16 @@ const ListItem: React.FC<ListItemProps> = ({
66
72
  })();
67
73
 
68
74
  // Helper to render leading/trailing icons
69
- const renderElement = (element: typeof leading | typeof trailing, props: any, isTrailing = false) => {
75
+ // IconSvg uses size="1em" by default, sized by container's fontSize from styles
76
+ const renderElement = (element: typeof leading | typeof trailing, isTrailing = false) => {
70
77
  if (!element) return null;
71
78
 
72
79
  if (isIconName(element)) {
73
80
  const iconPath = resolveIconPath(element);
74
- // Use trailingIconProps for trailing icons to apply size constraints
75
- const iconPropsToUse = isTrailing ? trailingIconProps : props;
76
81
  return (
77
82
  <IconSvg
78
83
  path={iconPath}
79
- {...iconPropsToUse}
80
- color={resolvedIconColor}
84
+ color={resolvedIconColor || 'currentColor'}
81
85
  aria-label={element}
82
86
  />
83
87
  );
@@ -88,11 +92,17 @@ const ListItem: React.FC<ListItemProps> = ({
88
92
  return null;
89
93
  };
90
94
 
95
+ const labelContainerProps = getWebProps([labelContainerStyle]);
96
+
91
97
  const content = (
92
98
  <>
93
- {leading && renderElement(leading, leadingProps)}
99
+ {leading && (
100
+ <span {...leadingProps}>
101
+ {renderElement(leading)}
102
+ </span>
103
+ )}
94
104
 
95
- <div {...getWebProps([listStyles.labelContainer])}>
105
+ <div {...labelContainerProps}>
96
106
  {label && (
97
107
  <span {...labelProps}>{label}</span>
98
108
  )}
@@ -101,7 +111,7 @@ const ListItem: React.FC<ListItemProps> = ({
101
111
 
102
112
  {trailing && (
103
113
  <div {...trailingProps}>
104
- {renderElement(trailing, trailingIconProps, true)}
114
+ {renderElement(trailing, true)}
105
115
  </div>
106
116
  )}
107
117
  </>