@idealyst/components 1.1.6 → 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 (144) hide show
  1. package/package.json +8 -3
  2. package/src/Accordion/Accordion.native.tsx +22 -14
  3. package/src/Accordion/Accordion.styles.old.tsx +298 -0
  4. package/src/Accordion/Accordion.styles.tsx +139 -248
  5. package/src/Accordion/Accordion.web.tsx +12 -7
  6. package/src/ActivityIndicator/ActivityIndicator.native.tsx +3 -2
  7. package/src/ActivityIndicator/ActivityIndicator.styles.old.tsx +94 -0
  8. package/src/ActivityIndicator/ActivityIndicator.styles.tsx +43 -62
  9. package/src/ActivityIndicator/ActivityIndicator.web.tsx +2 -2
  10. package/src/Alert/Alert.native.tsx +26 -15
  11. package/src/Alert/Alert.styles.old.tsx +209 -0
  12. package/src/Alert/Alert.styles.tsx +108 -281
  13. package/src/Alert/Alert.web.tsx +6 -10
  14. package/src/Avatar/Avatar.native.tsx +5 -2
  15. package/src/Avatar/Avatar.styles.old.tsx +99 -0
  16. package/src/Avatar/Avatar.styles.tsx +47 -62
  17. package/src/Avatar/Avatar.web.tsx +2 -2
  18. package/src/Badge/Badge.native.tsx +2 -2
  19. package/src/Badge/Badge.styles.old.tsx +157 -0
  20. package/src/Badge/Badge.styles.tsx +69 -108
  21. package/src/Badge/Badge.web.tsx +6 -6
  22. package/src/Breadcrumb/Breadcrumb.native.tsx +12 -5
  23. package/src/Breadcrumb/Breadcrumb.styles.old.tsx +231 -0
  24. package/src/Breadcrumb/Breadcrumb.styles.tsx +93 -209
  25. package/src/Breadcrumb/Breadcrumb.web.tsx +39 -27
  26. package/src/Button/Button.native.tsx +39 -14
  27. package/src/Button/Button.styles.tsx +99 -253
  28. package/src/Button/Button.web.tsx +10 -8
  29. package/src/Card/Card.native.tsx +8 -4
  30. package/src/Card/Card.styles.old.tsx +160 -0
  31. package/src/Card/Card.styles.tsx +107 -142
  32. package/src/Card/Card.web.tsx +6 -4
  33. package/src/Checkbox/Checkbox.native.tsx +14 -6
  34. package/src/Checkbox/Checkbox.styles.old.tsx +271 -0
  35. package/src/Checkbox/Checkbox.styles.tsx +109 -197
  36. package/src/Checkbox/Checkbox.web.tsx +7 -7
  37. package/src/Chip/Chip.native.tsx +5 -5
  38. package/src/Chip/Chip.styles.old.tsx +184 -0
  39. package/src/Chip/Chip.styles.tsx +34 -22
  40. package/src/Chip/Chip.web.tsx +5 -5
  41. package/src/Dialog/Dialog.native.tsx +16 -7
  42. package/src/Dialog/Dialog.styles.old.tsx +202 -0
  43. package/src/Dialog/Dialog.styles.tsx +108 -132
  44. package/src/Dialog/Dialog.web.tsx +4 -4
  45. package/src/Divider/Divider.native.tsx +29 -42
  46. package/src/Divider/Divider.styles.old.tsx +172 -0
  47. package/src/Divider/Divider.styles.tsx +116 -242
  48. package/src/Divider/Divider.web.tsx +17 -14
  49. package/src/Icon/Icon.native.tsx +12 -4
  50. package/src/Icon/Icon.styles.old.tsx +81 -0
  51. package/src/Icon/Icon.styles.tsx +52 -60
  52. package/src/Icon/Icon.web.tsx +43 -7
  53. package/src/Icon/IconSvg/IconSvg.web.tsx +2 -0
  54. package/src/Image/Image.styles.old.tsx +69 -0
  55. package/src/Image/Image.styles.tsx +45 -43
  56. package/src/Input/Input.native.tsx +140 -56
  57. package/src/Input/Input.styles.old.tsx +289 -0
  58. package/src/Input/Input.styles.tsx +177 -228
  59. package/src/Input/Input.web.tsx +5 -8
  60. package/src/Link/Link.native.tsx +4 -1
  61. package/src/List/List.native.tsx +5 -2
  62. package/src/List/List.styles.old.tsx +242 -0
  63. package/src/List/List.styles.tsx +178 -240
  64. package/src/List/ListItem.native.tsx +16 -8
  65. package/src/List/ListItem.web.tsx +26 -15
  66. package/src/Menu/Menu.native.tsx +1 -1
  67. package/src/Menu/Menu.styles.old.tsx +197 -0
  68. package/src/Menu/Menu.styles.tsx +90 -156
  69. package/src/Menu/Menu.web.tsx +2 -2
  70. package/src/Menu/MenuItem.native.tsx +9 -5
  71. package/src/Menu/MenuItem.styles.old.tsx +114 -0
  72. package/src/Menu/MenuItem.styles.tsx +71 -104
  73. package/src/Menu/MenuItem.web.tsx +23 -5
  74. package/src/Popover/Popover.native.tsx +10 -4
  75. package/src/Popover/Popover.styles.old.tsx +135 -0
  76. package/src/Popover/Popover.styles.tsx +46 -96
  77. package/src/Popover/Popover.web.tsx +1 -1
  78. package/src/Pressable/Pressable.native.tsx +3 -1
  79. package/src/Pressable/Pressable.styles.old.tsx +27 -0
  80. package/src/Pressable/Pressable.styles.tsx +35 -20
  81. package/src/Pressable/Pressable.web.tsx +1 -1
  82. package/src/Progress/Progress.native.tsx +15 -6
  83. package/src/Progress/Progress.styles.old.tsx +200 -0
  84. package/src/Progress/Progress.styles.tsx +69 -118
  85. package/src/Progress/Progress.web.tsx +10 -9
  86. package/src/RadioButton/RadioButton.native.tsx +10 -4
  87. package/src/RadioButton/RadioButton.styles.old.tsx +175 -0
  88. package/src/RadioButton/RadioButton.styles.tsx +81 -145
  89. package/src/RadioButton/RadioButton.web.tsx +4 -4
  90. package/src/SVGImage/SVGImage.styles.old.tsx +86 -0
  91. package/src/SVGImage/SVGImage.styles.tsx +35 -66
  92. package/src/Screen/Screen.native.tsx +30 -27
  93. package/src/Screen/Screen.styles.old.tsx +87 -0
  94. package/src/Screen/Screen.styles.tsx +120 -71
  95. package/src/Screen/Screen.web.tsx +2 -2
  96. package/src/Select/Select.native.tsx +44 -29
  97. package/src/Select/Select.styles.old.tsx +353 -0
  98. package/src/Select/Select.styles.tsx +244 -293
  99. package/src/Select/Select.web.tsx +5 -5
  100. package/src/Skeleton/Skeleton.styles.old.tsx +67 -0
  101. package/src/Skeleton/Skeleton.styles.tsx +31 -43
  102. package/src/Slider/Slider.native.tsx +9 -5
  103. package/src/Slider/Slider.styles.old.tsx +259 -0
  104. package/src/Slider/Slider.styles.tsx +157 -227
  105. package/src/Slider/Slider.web.tsx +5 -5
  106. package/src/Switch/Switch.native.tsx +11 -5
  107. package/src/Switch/Switch.styles.old.tsx +203 -0
  108. package/src/Switch/Switch.styles.tsx +103 -149
  109. package/src/Switch/Switch.web.tsx +8 -8
  110. package/src/TabBar/TabBar.native.tsx +24 -31
  111. package/src/TabBar/TabBar.styles.old.tsx +343 -0
  112. package/src/TabBar/TabBar.styles.tsx +204 -494
  113. package/src/TabBar/TabBar.web.tsx +21 -33
  114. package/src/Table/Table.native.tsx +18 -9
  115. package/src/Table/Table.styles.old.tsx +311 -0
  116. package/src/Table/Table.styles.tsx +151 -278
  117. package/src/Table/Table.web.tsx +1 -1
  118. package/src/Text/Text.native.tsx +1 -4
  119. package/src/Text/Text.style.demo.tsx +16 -0
  120. package/src/Text/Text.styles.old.tsx +219 -0
  121. package/src/Text/Text.styles.tsx +94 -78
  122. package/src/Text/Text.web.tsx +2 -2
  123. package/src/Text/index.ts +1 -0
  124. package/src/TextArea/TextArea.styles.old.tsx +213 -0
  125. package/src/TextArea/TextArea.styles.tsx +101 -157
  126. package/src/Tooltip/Tooltip.native.tsx +2 -2
  127. package/src/Tooltip/Tooltip.styles.old.tsx +82 -0
  128. package/src/Tooltip/Tooltip.styles.tsx +38 -53
  129. package/src/Tooltip/Tooltip.web.tsx +2 -2
  130. package/src/Video/Video.styles.old.tsx +51 -0
  131. package/src/Video/Video.styles.tsx +32 -28
  132. package/src/View/View.native.tsx +12 -12
  133. package/src/View/View.styles.old.tsx +125 -0
  134. package/src/View/View.styles.tsx +84 -103
  135. package/src/View/View.web.tsx +14 -2
  136. package/src/examples/CardExamples.tsx +0 -6
  137. package/src/extensions/applyExtension.ts +210 -0
  138. package/src/extensions/extendComponent.ts +438 -0
  139. package/src/extensions/index.ts +102 -0
  140. package/src/extensions/types.ts +497 -0
  141. package/src/globals.ts +16 -0
  142. package/src/index.native.ts +4 -0
  143. package/src/index.ts +28 -0
  144. package/src/utils/deepMerge.ts +54 -2
@@ -1,277 +1,168 @@
1
+ /**
2
+ * Accordion styles using defineStyle with dynamic props.
3
+ */
1
4
  import { StyleSheet } from 'react-native-unistyles';
2
- import { Theme, StylesheetStyles, CompoundVariants, Size} 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 { AccordionType } from './types';
5
+ import { defineStyle, ThemeStyleWrapper } from '@idealyst/theme';
6
+ import type { Theme as BaseTheme, Size } from '@idealyst/theme';
7
+ import { ViewStyleSize } from '../utils/viewStyleProps';
14
8
 
15
- type AccordionSize = Size;
9
+ // Required: Unistyles must see StyleSheet usage in original source to process this file
10
+ void StyleSheet;
16
11
 
17
- type AccordionVariants = {
18
- size: AccordionSize;
19
- type: AccordionType;
20
- expanded: boolean;
21
- disabled: boolean;
22
- isLast: boolean;
23
- }
12
+ // Wrap theme for $iterator support
13
+ type Theme = ThemeStyleWrapper<BaseTheme>;
24
14
 
25
- export type ExpandedAccordionStyles = StylesheetStyles<keyof AccordionVariants>;
15
+ type AccordionType = 'standard' | 'separated' | 'bordered';
26
16
 
27
- /**
28
- * Create type variants for container
29
- */
30
- function createContainerTypeVariants(theme: Theme) {
31
- return {
32
- standard: {
33
- gap: 0,
34
- },
35
- separated: {
36
- gap: 8,
37
- },
38
- bordered: {
39
- gap: 0,
40
- borderWidth: 1,
41
- borderStyle: 'solid' as const,
42
- borderColor: theme.colors.border.primary,
43
- borderRadius: 8,
44
- overflow: 'hidden' as const,
45
- },
46
- } as const;
47
- }
17
+ export type AccordionDynamicProps = {
18
+ size?: Size;
19
+ type?: AccordionType;
20
+ expanded?: boolean;
21
+ disabled?: boolean;
22
+ isLast?: boolean;
23
+ gap?: ViewStyleSize;
24
+ padding?: ViewStyleSize;
25
+ paddingVertical?: ViewStyleSize;
26
+ paddingHorizontal?: ViewStyleSize;
27
+ margin?: ViewStyleSize;
28
+ marginVertical?: ViewStyleSize;
29
+ marginHorizontal?: ViewStyleSize;
30
+ };
48
31
 
49
32
  /**
50
- * Create type variants for items
33
+ * Accordion styles with type/expanded/disabled handling.
51
34
  */
52
- function createItemTypeVariants(theme: Theme) {
53
- return {
54
- standard: {
55
- borderBottomWidth: 1,
56
- borderBottomStyle: 'solid' as const,
57
- borderBottomColor: theme.colors.border.primary,
58
- },
59
- separated: {
35
+ export const accordionStyles = defineStyle('Accordion', (theme: Theme) => ({
36
+ container: ({ type = 'standard' }: AccordionDynamicProps) => {
37
+ const typeStyles = type === 'bordered' ? {
60
38
  borderWidth: 1,
61
39
  borderStyle: 'solid' as const,
62
40
  borderColor: theme.colors.border.primary,
63
41
  borderRadius: 8,
64
42
  overflow: 'hidden' as const,
65
- },
66
- bordered: {
67
- borderBottomWidth: 1,
68
- borderBottomStyle: 'solid' as const,
69
- borderBottomColor: theme.colors.border.primary,
70
- },
71
- } as const;
72
- }
43
+ } : {};
73
44
 
74
- /**
75
- * Create compound variants for item (type + isLast)
76
- */
77
- function createItemCompoundVariants(): CompoundVariants<keyof AccordionVariants> {
78
- return [
79
- {
80
- type: 'standard',
81
- isLast: true,
82
- styles: {
83
- borderBottomWidth: 0,
84
- },
85
- },
86
- {
87
- type: 'bordered',
88
- isLast: true,
89
- styles: {
90
- borderBottomWidth: 0,
91
- },
92
- },
93
- ];
94
- }
95
-
96
- /**
97
- * Create size variants for header
98
- */
99
- function createHeaderSizeVariants(theme: Theme) {
100
- return buildSizeVariants(theme, 'accordion', (size) => ({
101
- fontSize: size.headerFontSize,
102
- padding: size.headerPadding,
103
- }));
104
- }
105
-
106
- /**
107
- * Create size variants for icon
108
- */
109
- function createIconSizeVariants(theme: Theme) {
110
- return buildSizeVariants(theme, 'accordion', (size) => ({
111
- width: size.iconSize,
112
- height: size.iconSize,
113
- }));
114
- }
115
-
116
- /**
117
- * Create size variants for content inner
118
- */
119
- function createContentInnerSizeVariants(theme: Theme) {
120
- return buildSizeVariants(theme, 'accordion', (size) => ({
121
- fontSize: size.headerFontSize,
122
- padding: size.contentPadding,
123
- paddingTop: 0,
124
- }));
125
- }
126
-
127
- // Styles are inlined here instead of in @idealyst/theme because Unistyles' Babel transform on native cannot resolve function calls to extract variant structures.
128
- export const accordionStyles = StyleSheet.create((theme: Theme) => {
129
- return {
130
- container: {
45
+ return {
131
46
  display: 'flex' as const,
132
47
  flexDirection: 'column' as const,
48
+ gap: type === 'separated' ? 8 : 0,
49
+ ...typeStyles,
133
50
  variants: {
134
- size: { xs: {}, sm: {}, md: {}, lg: {}, xl: {} },
135
- type: createContainerTypeVariants(theme),
136
- expanded: { true: {}, false: {} },
137
- disabled: { true: {}, false: {} },
138
- isLast: { true: {}, false: {} },
139
- // Spacing variants from ContainerStyleProps
140
- gap: buildGapVariants(theme),
141
- padding: buildPaddingVariants(theme),
142
- paddingVertical: buildPaddingVerticalVariants(theme),
143
- paddingHorizontal: buildPaddingHorizontalVariants(theme),
144
- margin: buildMarginVariants(theme),
145
- marginVertical: buildMarginVerticalVariants(theme),
146
- marginHorizontal: buildMarginHorizontalVariants(theme),
51
+ gap: {
52
+ gap: theme.sizes.$view.padding,
53
+ },
54
+ padding: {
55
+ padding: theme.sizes.$view.padding,
56
+ },
57
+ paddingVertical: {
58
+ paddingVertical: theme.sizes.$view.padding,
59
+ },
60
+ paddingHorizontal: {
61
+ paddingHorizontal: theme.sizes.$view.padding,
62
+ },
63
+ margin: {
64
+ margin: theme.sizes.$view.padding,
65
+ },
66
+ marginVertical: {
67
+ marginVertical: theme.sizes.$view.padding,
68
+ },
69
+ marginHorizontal: {
70
+ marginHorizontal: theme.sizes.$view.padding,
71
+ },
147
72
  },
148
- },
149
- item: {
73
+ } as const;
74
+ },
75
+
76
+ item: ({ type = 'standard', isLast = false }: AccordionDynamicProps) => {
77
+ let typeStyles = {};
78
+
79
+ if (type === 'standard' || type === 'bordered') {
80
+ typeStyles = {
81
+ borderBottomWidth: isLast ? 0 : 1,
82
+ borderBottomStyle: 'solid' as const,
83
+ borderBottomColor: theme.colors.border.primary,
84
+ };
85
+ } else if (type === 'separated') {
86
+ typeStyles = {
87
+ borderWidth: 1,
88
+ borderStyle: 'solid' as const,
89
+ borderColor: theme.colors.border.primary,
90
+ borderRadius: 8,
91
+ overflow: 'hidden' as const,
92
+ };
93
+ }
94
+
95
+ return {
150
96
  display: 'flex' as const,
151
97
  flexDirection: 'column' as const,
152
- variants: {
153
- size: { xs: {}, sm: {}, md: {}, lg: {}, xl: {} },
154
- type: createItemTypeVariants(theme),
155
- expanded: { true: {}, false: {} },
156
- disabled: { true: {}, false: {} },
157
- isLast: {
158
- true: {},
159
- false: {},
160
- },
98
+ ...typeStyles,
99
+ } as const;
100
+ },
101
+
102
+ header: ({ expanded = false, disabled = false }: AccordionDynamicProps) => ({
103
+ display: 'flex' as const,
104
+ flexDirection: 'row' as const,
105
+ alignItems: 'center' as const,
106
+ justifyContent: 'space-between' as const,
107
+ width: '100%',
108
+ backgroundColor: 'transparent' as const,
109
+ color: theme.colors.text.primary,
110
+ textAlign: 'left' as const,
111
+ fontWeight: expanded ? ('600' as const) : ('500' as const),
112
+ opacity: disabled ? 0.5 : 1,
113
+ variants: {
114
+ size: {
115
+ fontSize: theme.sizes.$accordion.headerFontSize,
116
+ padding: theme.sizes.$accordion.headerPadding,
161
117
  },
162
- compoundVariants: createItemCompoundVariants(),
163
118
  },
164
- header: {
165
- display: 'flex' as const,
166
- flexDirection: 'row' as const,
167
- alignItems: 'center' as const,
168
- justifyContent: 'space-between' as const,
169
- width: '100%' as const,
170
- backgroundColor: 'transparent' as const,
171
- color: theme.colors.text.primary,
172
- textAlign: 'left' as const,
173
- variants: {
174
- size: createHeaderSizeVariants(theme),
175
- type: { standard: {}, separated: {}, bordered: {} },
176
- expanded: {
177
- true: {
178
- fontWeight: '600' as const,
179
- },
180
- false: {
181
- fontWeight: '500' as const,
182
- },
183
- },
184
- disabled: {
185
- true: {
186
- opacity: 0.5,
187
- _web: {
188
- cursor: 'not-allowed' as const,
189
- },
190
- },
191
- false: {
192
- _web: {
193
- cursor: 'pointer' as const,
194
- _hover: {
195
- backgroundColor: theme.colors.surface.secondary,
196
- },
197
- },
198
- },
199
- },
200
- isLast: { true: {}, false: {} },
201
- } as const,
202
- _web: {
203
- border: 'none' as const,
204
- outline: 'none' as const,
205
- transition: 'background-color 0.2s ease' as const,
206
- },
119
+ _web: {
120
+ border: 'none',
121
+ outline: 'none',
122
+ cursor: disabled ? 'not-allowed' : 'pointer',
123
+ transition: 'background-color 0.2s ease',
124
+ _hover: disabled ? {} : { backgroundColor: theme.colors.surface.secondary },
207
125
  },
208
- title: {
209
- flex: 1,
210
- variants: {
211
- size: { xs: {}, sm: {}, md: {}, lg: {}, xl: {} },
212
- type: { standard: {}, separated: {}, bordered: {} },
213
- expanded: { true: {}, false: {} },
214
- disabled: { true: {}, false: {} },
215
- isLast: { true: {}, false: {} },
126
+ }),
127
+
128
+ title: (_props: AccordionDynamicProps) => ({
129
+ flex: 1,
130
+ }),
131
+
132
+ icon: ({ expanded = false }: AccordionDynamicProps) => ({
133
+ display: 'flex' as const,
134
+ alignItems: 'center' as const,
135
+ justifyContent: 'center' as const,
136
+ marginLeft: 8,
137
+ color: theme.intents.primary.primary,
138
+ variants: {
139
+ size: {
140
+ width: theme.sizes.$accordion.iconSize,
141
+ height: theme.sizes.$accordion.iconSize,
216
142
  },
217
143
  },
218
- icon: {
219
- display: 'flex' as const,
220
- alignItems: 'center' as const,
221
- justifyContent: 'center' as const,
222
- marginLeft: 8,
223
- color: theme.intents.primary.primary,
224
- variants: {
225
- size: createIconSizeVariants(theme),
226
- type: { standard: {}, separated: {}, bordered: {} },
227
- expanded: {
228
- true: {
229
- _web: {
230
- transform: 'rotate(180deg)' as const,
231
- },
232
- },
233
- false: {
234
- _web: {
235
- transform: 'rotate(0deg)' as const,
236
- },
237
- },
238
- },
239
- disabled: { true: {}, false: {} },
240
- isLast: { true: {}, false: {} },
241
- },
242
- _web: {
243
- transition: 'transform 0.2s ease' as const,
244
- },
144
+ _web: {
145
+ transition: 'transform 0.2s ease',
146
+ transform: expanded ? 'rotate(180deg)' : 'rotate(0deg)',
245
147
  },
246
- content: {
247
- overflow: 'hidden' as const,
248
- variants: {
249
- size: { xs: {}, sm: {}, md: {}, lg: {}, xl: {} },
250
- type: { standard: {}, separated: {}, bordered: {} },
251
- expanded: {
252
- true: {
253
- maxHeight: 2000,
254
- },
255
- false: {
256
- maxHeight: 0,
257
- },
258
- },
259
- disabled: { true: {}, false: {} },
260
- isLast: { true: {}, false: {} },
261
- },
262
- _web: {
263
- transition: 'height 0.15s ease, padding 0.3s ease' as const,
264
- },
148
+ }),
149
+
150
+ content: ({ expanded = false }: AccordionDynamicProps) => ({
151
+ overflow: 'hidden' as const,
152
+ maxHeight: expanded ? 2000 : 0,
153
+ _web: {
154
+ transition: 'height 0.15s ease, padding 0.3s ease',
265
155
  },
266
- contentInner: {
267
- color: theme.colors.text.secondary,
268
- variants: {
269
- size: createContentInnerSizeVariants(theme),
270
- type: { standard: {}, separated: {}, bordered: {} },
271
- expanded: { true: {}, false: {} },
272
- disabled: { true: {}, false: {} },
273
- isLast: { true: {}, false: {} },
156
+ }),
157
+
158
+ contentInner: (_props: AccordionDynamicProps) => ({
159
+ color: theme.colors.text.secondary,
160
+ variants: {
161
+ size: {
162
+ fontSize: theme.sizes.$accordion.headerFontSize,
163
+ padding: theme.sizes.$accordion.contentPadding,
164
+ paddingTop: 0,
274
165
  },
275
166
  },
276
- };
277
- });
167
+ }),
168
+ }));
@@ -12,6 +12,7 @@ interface AccordionItemProps {
12
12
  isExpanded: boolean;
13
13
  onToggle: () => void;
14
14
  size: AccordionProps['size'];
15
+ isLast: boolean;
15
16
  testID?: string;
16
17
  headerId: string;
17
18
  panelId: string;
@@ -24,6 +25,7 @@ const AccordionItem: React.FC<AccordionItemProps> = ({
24
25
  onToggle,
25
26
  type,
26
27
  size,
28
+ isLast,
27
29
  testID,
28
30
  headerId,
29
31
  panelId,
@@ -33,19 +35,21 @@ const AccordionItem: React.FC<AccordionItemProps> = ({
33
35
  const [contentHeight, setContentHeight] = useState(0);
34
36
  const chevronIconPath = resolveIconPath('chevron-down');
35
37
 
38
+ // Apply item-specific variants (for size, expanded, disabled)
36
39
  accordionStyles.useVariants({
37
40
  size,
38
- type,
39
41
  expanded: isExpanded,
40
42
  disabled: Boolean(item.disabled),
41
43
  });
42
44
 
43
- const itemProps = getWebProps([accordionStyles.item]);
44
- const headerProps = getWebProps([accordionStyles.header]);
45
+ // Get dynamic item style with type and isLast props
46
+ const itemStyle = (accordionStyles.item as any)({ type, isLast });
47
+ const itemProps = getWebProps([itemStyle]);
48
+ const headerProps = getWebProps([(accordionStyles.header as any)({})]);
45
49
  const titleProps = getWebProps([accordionStyles.title]);
46
- const iconProps = getWebProps([accordionStyles.icon]);
50
+ const iconProps = getWebProps([(accordionStyles.icon as any)({})]);
47
51
  const contentProps = getWebProps([
48
- accordionStyles.content,
52
+ (accordionStyles.content as any)({}),
49
53
  {
50
54
  height: isExpanded ? contentHeight : 0,
51
55
  overflow: 'hidden' as const,
@@ -193,7 +197,7 @@ const Accordion: React.FC<AccordionProps> = ({
193
197
  marginHorizontal,
194
198
  });
195
199
 
196
- const containerProps = getWebProps([accordionStyles.container, style as any]);
200
+ const containerProps = getWebProps([(accordionStyles.container as any)({}), style as any]);
197
201
 
198
202
  const toggleItem = (itemId: string, disabled?: boolean) => {
199
203
  if (disabled) return;
@@ -213,7 +217,7 @@ const Accordion: React.FC<AccordionProps> = ({
213
217
 
214
218
  return (
215
219
  <div {...containerProps} {...ariaProps} id={accordionId} data-testid={testID}>
216
- {items.map((item) => (
220
+ {items.map((item, index) => (
217
221
  <AccordionItem
218
222
  key={item.id}
219
223
  item={item}
@@ -221,6 +225,7 @@ const Accordion: React.FC<AccordionProps> = ({
221
225
  isExpanded={expandedItems.includes(item.id)}
222
226
  onToggle={() => toggleItem(item.id, item.disabled)}
223
227
  size={size}
228
+ isLast={index === items.length - 1}
224
229
  testID={`${testID}-item-${item.id}`}
225
230
  headerId={getHeaderId(item.id)}
226
231
  panelId={getPanelId(item.id)}
@@ -39,7 +39,8 @@ const ActivityIndicator = forwardRef<View, ActivityIndicatorProps>(({
39
39
  });
40
40
 
41
41
  // Call dynamic style with intent variant
42
- const spinnerStyle = activityIndicatorStyles.spinner({ intent });
42
+ const spinnerStyle = (activityIndicatorStyles.spinner as any)({ intent });
43
+ const containerStyle = (activityIndicatorStyles.container as any)({});
43
44
 
44
45
  // Get the color from styles or use custom color
45
46
  const indicatorColor = color || spinnerStyle.color;
@@ -47,7 +48,7 @@ const ActivityIndicator = forwardRef<View, ActivityIndicatorProps>(({
47
48
  return (
48
49
  <View
49
50
  style={[
50
- activityIndicatorStyles.container,
51
+ containerStyle,
51
52
  customSize && {
52
53
  width: customSize,
53
54
  height: customSize,
@@ -0,0 +1,94 @@
1
+ import { StyleSheet } from 'react-native-unistyles';
2
+ import { Theme, StylesheetStyles, Intent, Size} from '@idealyst/theme';
3
+ import { buildSizeVariants } from '../utils/buildSizeVariants';
4
+ import { applyExtensions } from '../extensions/applyExtension';
5
+
6
+ type ActivityIndicatorSize = Size;
7
+ type ActivityIndicatorIntent = Intent;
8
+
9
+ type ActivityIndicatorVariants = {
10
+ size: ActivityIndicatorSize;
11
+ intent: ActivityIndicatorIntent;
12
+ animating: boolean;
13
+ }
14
+
15
+ export type ExpandedActivityIndicatorStyles = StylesheetStyles<keyof ActivityIndicatorVariants>;
16
+
17
+ export type ActivityIndicatorStylesheet = {
18
+ container: ExpandedActivityIndicatorStyles;
19
+ spinner: ExpandedActivityIndicatorStyles;
20
+ }
21
+
22
+ function createContainerSizeVariants(theme: Theme) {
23
+ return buildSizeVariants(theme, 'activityIndicator', (size) => ({
24
+ width: size.size,
25
+ height: size.size,
26
+ }));
27
+ }
28
+
29
+ function createSpinnerSizeVariants(theme: Theme) {
30
+ return buildSizeVariants(theme, 'activityIndicator', (size) => ({
31
+ width: size.size,
32
+ height: size.size,
33
+ borderWidth: size.borderWidth,
34
+ }));
35
+ }
36
+
37
+ function getSpinnerColor(theme: Theme, intent: ActivityIndicatorIntent) {
38
+ return theme.intents[intent].primary;
39
+ }
40
+
41
+ function createSpinnerStyles(theme: Theme) {
42
+ return ({ intent }: Partial<ActivityIndicatorVariants>) => {
43
+ const color = getSpinnerColor(theme, intent);
44
+ return {
45
+ borderRadius: 9999,
46
+ borderStyle: 'solid',
47
+ color,
48
+ variants: {
49
+ size: createSpinnerSizeVariants(theme),
50
+ animating: {
51
+ true: {},
52
+ false: {},
53
+ },
54
+ },
55
+ _web: {
56
+ borderColor: 'transparent',
57
+ borderTopColor: color,
58
+ borderRightColor: color,
59
+ animation: 'spin 1s linear infinite',
60
+ boxSizing: 'border-box',
61
+ },
62
+ } as const;
63
+ }
64
+ }
65
+
66
+ // Style creators for extension support
67
+ function createContainerStyles(theme: Theme) {
68
+ return () => ({
69
+ alignItems: 'center' as const,
70
+ justifyContent: 'center' as const,
71
+ variants: {
72
+ size: createContainerSizeVariants(theme),
73
+ animating: {
74
+ true: {
75
+ opacity: 1,
76
+ },
77
+ false: {
78
+ opacity: 0,
79
+ },
80
+ },
81
+ },
82
+ });
83
+ }
84
+
85
+ // Styles are inlined here instead of in @idealyst/theme because Unistyles' Babel
86
+ // transform on native cannot resolve function calls to extract variant structures.
87
+ // @ts-ignore - TS language server needs restart to pick up theme structure changes
88
+ export const activityIndicatorStyles = StyleSheet.create((theme: Theme) => {
89
+ // Apply extensions to main visual elements
90
+ return applyExtensions('ActivityIndicator', theme, {
91
+ container: createContainerStyles(theme),
92
+ spinner: createSpinnerStyles(theme),
93
+ });
94
+ });