@idealyst/components 1.1.6 → 1.1.7

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 (104) hide show
  1. package/package.json +8 -3
  2. package/src/Accordion/Accordion.native.tsx +15 -9
  3. package/src/Accordion/Accordion.styles.tsx +193 -168
  4. package/src/Accordion/Accordion.web.tsx +12 -7
  5. package/src/ActivityIndicator/ActivityIndicator.native.tsx +3 -2
  6. package/src/ActivityIndicator/ActivityIndicator.styles.tsx +22 -11
  7. package/src/ActivityIndicator/ActivityIndicator.web.tsx +2 -2
  8. package/src/Alert/Alert.native.tsx +11 -10
  9. package/src/Alert/Alert.styles.tsx +162 -253
  10. package/src/Alert/Alert.web.tsx +6 -10
  11. package/src/Avatar/Avatar.native.tsx +5 -2
  12. package/src/Avatar/Avatar.styles.tsx +48 -18
  13. package/src/Avatar/Avatar.web.tsx +2 -2
  14. package/src/Badge/Badge.native.tsx +2 -2
  15. package/src/Badge/Badge.styles.tsx +37 -16
  16. package/src/Badge/Badge.web.tsx +6 -6
  17. package/src/Breadcrumb/Breadcrumb.native.tsx +12 -5
  18. package/src/Breadcrumb/Breadcrumb.styles.tsx +59 -58
  19. package/src/Breadcrumb/Breadcrumb.web.tsx +13 -6
  20. package/src/Button/Button.native.tsx +39 -14
  21. package/src/Button/Button.styles.tsx +106 -208
  22. package/src/Button/Button.web.tsx +10 -8
  23. package/src/Card/Card.native.tsx +14 -6
  24. package/src/Card/Card.styles.tsx +64 -62
  25. package/src/Card/Card.web.tsx +5 -4
  26. package/src/Checkbox/Checkbox.native.tsx +7 -3
  27. package/src/Checkbox/Checkbox.styles.tsx +49 -25
  28. package/src/Checkbox/Checkbox.web.tsx +3 -3
  29. package/src/Chip/Chip.native.tsx +5 -5
  30. package/src/Chip/Chip.styles.tsx +71 -21
  31. package/src/Chip/Chip.web.tsx +5 -5
  32. package/src/Dialog/Dialog.native.tsx +10 -4
  33. package/src/Dialog/Dialog.styles.tsx +130 -90
  34. package/src/Dialog/Dialog.web.tsx +4 -4
  35. package/src/Divider/Divider.native.tsx +29 -42
  36. package/src/Divider/Divider.styles.tsx +138 -242
  37. package/src/Divider/Divider.web.tsx +17 -14
  38. package/src/Icon/Icon.native.tsx +11 -3
  39. package/src/Icon/Icon.styles.tsx +10 -4
  40. package/src/Image/Image.styles.tsx +53 -37
  41. package/src/Input/Input.native.tsx +6 -7
  42. package/src/Input/Input.styles.tsx +194 -174
  43. package/src/Input/Input.web.tsx +5 -8
  44. package/src/Link/Link.native.tsx +4 -1
  45. package/src/List/List.styles.tsx +79 -105
  46. package/src/List/ListItem.native.tsx +5 -3
  47. package/src/List/ListItem.web.tsx +4 -3
  48. package/src/Menu/Menu.native.tsx +1 -1
  49. package/src/Menu/Menu.styles.tsx +53 -37
  50. package/src/Menu/Menu.web.tsx +2 -2
  51. package/src/Menu/MenuItem.native.tsx +5 -3
  52. package/src/Menu/MenuItem.styles.tsx +68 -69
  53. package/src/Menu/MenuItem.web.tsx +16 -3
  54. package/src/Popover/Popover.native.tsx +1 -1
  55. package/src/Popover/Popover.styles.tsx +40 -29
  56. package/src/Popover/Popover.web.tsx +1 -1
  57. package/src/Pressable/Pressable.native.tsx +3 -1
  58. package/src/Pressable/Pressable.styles.tsx +20 -13
  59. package/src/Pressable/Pressable.web.tsx +1 -1
  60. package/src/Progress/Progress.native.tsx +15 -6
  61. package/src/Progress/Progress.styles.tsx +125 -85
  62. package/src/Progress/Progress.web.tsx +10 -9
  63. package/src/RadioButton/RadioButton.native.tsx +8 -3
  64. package/src/RadioButton/RadioButton.styles.tsx +44 -37
  65. package/src/RadioButton/RadioButton.web.tsx +3 -3
  66. package/src/SVGImage/SVGImage.styles.tsx +28 -16
  67. package/src/Screen/Screen.native.tsx +23 -13
  68. package/src/Screen/Screen.styles.tsx +57 -46
  69. package/src/Screen/Screen.web.tsx +1 -1
  70. package/src/Select/Select.native.tsx +11 -5
  71. package/src/Select/Select.styles.tsx +72 -52
  72. package/src/Select/Select.web.tsx +5 -5
  73. package/src/Skeleton/Skeleton.styles.tsx +26 -14
  74. package/src/Slider/Slider.native.tsx +9 -5
  75. package/src/Slider/Slider.styles.tsx +59 -48
  76. package/src/Slider/Slider.web.tsx +5 -5
  77. package/src/Switch/Switch.native.tsx +6 -2
  78. package/src/Switch/Switch.styles.tsx +46 -19
  79. package/src/Switch/Switch.web.tsx +4 -4
  80. package/src/TabBar/TabBar.native.tsx +23 -31
  81. package/src/TabBar/TabBar.styles.tsx +215 -371
  82. package/src/TabBar/TabBar.web.tsx +21 -33
  83. package/src/Table/Table.native.tsx +1 -1
  84. package/src/Table/Table.styles.tsx +11 -4
  85. package/src/Table/Table.web.tsx +1 -1
  86. package/src/Text/Text.native.tsx +3 -4
  87. package/src/Text/Text.styles.tsx +7 -1
  88. package/src/Text/Text.web.tsx +1 -1
  89. package/src/TextArea/TextArea.styles.tsx +90 -58
  90. package/src/Tooltip/Tooltip.native.tsx +2 -2
  91. package/src/Tooltip/Tooltip.styles.tsx +21 -12
  92. package/src/Tooltip/Tooltip.web.tsx +2 -2
  93. package/src/Video/Video.styles.tsx +39 -23
  94. package/src/View/View.native.tsx +4 -2
  95. package/src/View/View.styles.tsx +33 -22
  96. package/src/View/View.web.tsx +13 -2
  97. package/src/extensions/applyExtension.ts +210 -0
  98. package/src/extensions/extendComponent.ts +377 -0
  99. package/src/extensions/index.ts +102 -0
  100. package/src/extensions/types.ts +497 -0
  101. package/src/globals.ts +16 -0
  102. package/src/index.native.ts +4 -0
  103. package/src/index.ts +28 -0
  104. package/src/utils/deepMerge.ts +54 -2
@@ -1,5 +1,5 @@
1
1
  import { StyleSheet } from 'react-native-unistyles';
2
- import { Theme, StylesheetStyles, CompoundVariants, Size } from '@idealyst/theme';
2
+ import { Theme } from '@idealyst/theme';
3
3
  import { buildSizeVariants } from '../utils/buildSizeVariants';
4
4
  import {
5
5
  buildGapVariants,
@@ -11,64 +11,85 @@ import {
11
11
  buildMarginHorizontalVariants,
12
12
  } from '../utils/buildViewStyleVariants';
13
13
  import { TabBarPillMode, TabBarSizeVariant, TabBarType, TabBarIconPosition, TabBarJustify } from './types';
14
+ import { applyExtensions } from '../extensions/applyExtension';
14
15
 
15
- type TabBarContainerVariants = {
16
- type: TabBarType;
17
- size: TabBarSizeVariant;
18
- pillMode: TabBarPillMode;
19
- justify: TabBarJustify;
20
- }
16
+ type ContainerDynamicProps = {
17
+ type?: TabBarType;
18
+ pillMode?: TabBarPillMode;
19
+ };
20
+
21
+ type TabDynamicProps = {
22
+ type?: TabBarType;
23
+ size?: TabBarSizeVariant;
24
+ active?: boolean;
25
+ pillMode?: TabBarPillMode;
26
+ };
27
+
28
+ type LabelDynamicProps = {
29
+ type?: TabBarType;
30
+ active?: boolean;
31
+ pillMode?: TabBarPillMode;
32
+ };
33
+
34
+ type IndicatorDynamicProps = {
35
+ type?: TabBarType;
36
+ pillMode?: TabBarPillMode;
37
+ };
21
38
 
22
- type TabBarTabVariants = {
23
- size: TabBarSizeVariant;
24
- type: TabBarType;
25
- active: boolean;
26
- disabled: boolean;
27
- pillMode: TabBarPillMode;
28
- iconPosition: TabBarIconPosition;
29
- justify: TabBarJustify;
39
+ /**
40
+ * Get container background color based on type and pillMode
41
+ */
42
+ function getContainerBackgroundColor(theme: Theme, type: TabBarType, pillMode: TabBarPillMode): string | undefined {
43
+ if (type === 'pills') {
44
+ return pillMode === 'dark' ? theme.colors.surface.inverse : theme.colors.surface.secondary;
45
+ }
46
+ return undefined;
30
47
  }
31
48
 
32
- type TabBarIconVariants = {
33
- size: TabBarSizeVariant;
34
- active: boolean;
35
- disabled: boolean;
36
- iconPosition: TabBarIconPosition;
49
+ /**
50
+ * Get tab padding based on type and size (pills have compact padding)
51
+ */
52
+ function getTabPadding(type: TabBarType, size: TabBarSizeVariant): { paddingVertical?: number; paddingHorizontal?: number } {
53
+ if (type !== 'pills') return {};
54
+
55
+ const paddingMap: Record<TabBarSizeVariant, { paddingVertical: number; paddingHorizontal: number }> = {
56
+ xs: { paddingVertical: 2, paddingHorizontal: 10 },
57
+ sm: { paddingVertical: 4, paddingHorizontal: 12 },
58
+ md: { paddingVertical: 6, paddingHorizontal: 16 },
59
+ lg: { paddingVertical: 8, paddingHorizontal: 20 },
60
+ xl: { paddingVertical: 10, paddingHorizontal: 24 },
61
+ };
62
+ return paddingMap[size] || paddingMap.md;
37
63
  }
38
64
 
39
- type TabBarLabelVariants = {
40
- size: TabBarSizeVariant;
41
- type: TabBarType;
42
- active: boolean;
43
- disabled: boolean;
44
- pillMode: TabBarPillMode;
65
+ /**
66
+ * Get tab text color based on type and active state
67
+ */
68
+ function getTabColor(theme: Theme, type: TabBarType, active: boolean): string | undefined {
69
+ if (!active) return undefined;
70
+ if (type === 'pills') return theme.intents.primary.contrast;
71
+ if (type === 'underline') return theme.intents.primary.primary;
72
+ return theme.colors.text.primary;
45
73
  }
46
74
 
47
- type TabBarIndicatorVariants = {
48
- type: TabBarType;
49
- pillMode: TabBarPillMode;
75
+ /**
76
+ * Get label color based on type, pillMode, and active state
77
+ */
78
+ function getLabelColor(theme: Theme, type: TabBarType, pillMode: TabBarPillMode, active: boolean): string | undefined {
79
+ if (!active) return undefined;
80
+ if (type === 'pills') return theme.colors.text.primary;
81
+ if (type === 'underline') return theme.intents.primary.primary;
82
+ return theme.colors.text.primary;
50
83
  }
51
84
 
52
85
  /**
53
- * Create compound variants for container
86
+ * Get indicator background color based on type and pillMode
54
87
  */
55
- function createContainerCompoundVariants(theme: Theme): CompoundVariants<keyof TabBarContainerVariants> {
56
- return [
57
- {
58
- type: 'pills',
59
- pillMode: 'light',
60
- styles: {
61
- backgroundColor: theme.colors.surface.secondary,
62
- },
63
- },
64
- {
65
- type: 'pills',
66
- pillMode: 'dark',
67
- styles: {
68
- backgroundColor: theme.colors.surface.inverse,
69
- },
70
- },
71
- ];
88
+ function getIndicatorBackgroundColor(theme: Theme, type: TabBarType, pillMode: TabBarPillMode): string | undefined {
89
+ if (type === 'pills') {
90
+ return pillMode === 'dark' ? theme.colors.surface.secondary : theme.colors.surface.tertiary;
91
+ }
92
+ return undefined;
72
93
  }
73
94
 
74
95
  /**
@@ -82,71 +103,6 @@ function createTabSizeVariants(theme: Theme) {
82
103
  }));
83
104
  }
84
105
 
85
- /**
86
- * Create compound variants for tab
87
- */
88
- function createTabCompoundVariants(theme: Theme): CompoundVariants<keyof TabBarTabVariants> {
89
- return [
90
- // Pills variant - compact padding for all sizes
91
- {
92
- type: 'pills',
93
- size: 'xs',
94
- styles: {
95
- paddingVertical: 2,
96
- paddingHorizontal: 10,
97
- },
98
- },
99
- {
100
- type: 'pills',
101
- size: 'sm',
102
- styles: {
103
- paddingVertical: 4,
104
- paddingHorizontal: 12,
105
- },
106
- },
107
- {
108
- type: 'pills',
109
- size: 'md',
110
- styles: {
111
- paddingVertical: 6,
112
- paddingHorizontal: 16,
113
- },
114
- },
115
- {
116
- type: 'pills',
117
- size: 'lg',
118
- styles: {
119
- paddingVertical: 8,
120
- paddingHorizontal: 20,
121
- },
122
- },
123
- {
124
- type: 'pills',
125
- size: 'xl',
126
- styles: {
127
- paddingVertical: 10,
128
- paddingHorizontal: 24,
129
- },
130
- },
131
- // Pills variant - active text color
132
- {
133
- type: 'pills',
134
- active: true,
135
- styles: {
136
- color: theme.intents.primary.contrast,
137
- },
138
- },
139
- // Underline variant - active text color
140
- {
141
- type: 'underline',
142
- active: true,
143
- styles: {
144
- color: theme.intents.primary.primary,
145
- },
146
- },
147
- ] as const;
148
- }
149
-
150
106
  /**
151
107
  * Create size variants for label
152
108
  */
@@ -158,281 +114,168 @@ function createLabelSizeVariants(theme: Theme) {
158
114
  }
159
115
 
160
116
  /**
161
- * Create compound variants for label
117
+ * Create size variants for icon
162
118
  */
163
- function createLabelCompoundVariants(theme: Theme): CompoundVariants<keyof TabBarLabelVariants> {
164
- return [
165
- // Pills light mode - light text on active (dark pill)
166
- {
167
- type: 'pills',
168
- pillMode: 'light',
169
- active: true,
170
- styles: {
171
- color: theme.colors.text.primary,
172
- },
173
- },
174
- // Pills dark mode - dark text on active (light pill)
175
- {
176
- type: 'pills',
177
- pillMode: 'dark',
178
- active: true,
179
- styles: {
180
- color: theme.colors.text.primary,
181
- },
182
- },
183
- // Underline variant - active text color
184
- {
185
- type: 'underline',
186
- active: true,
187
- styles: {
188
- color: theme.intents.primary.primary,
189
- },
190
- },
191
- ] as const;
119
+ function createIconSizeVariants(theme: Theme) {
120
+ return buildSizeVariants(theme, 'tabBar', (size) => ({
121
+ width: size.fontSize,
122
+ height: size.fontSize,
123
+ }));
192
124
  }
193
125
 
194
126
  /**
195
- * Create compound variants for indicator
127
+ * Create dynamic container styles
196
128
  */
197
- function createIndicatorCompoundVariants(theme: Theme): CompoundVariants<keyof TabBarIndicatorVariants> {
198
- return [
199
- // Pills light mode - darker pill
200
- {
201
- type: 'pills',
202
- pillMode: 'light',
203
- styles: {
204
- backgroundColor: theme.colors.surface.tertiary,
205
- },
206
- },
207
- // Pills dark mode - lighter pill
208
- {
209
- type: 'pills',
210
- pillMode: 'dark',
211
- styles: {
212
- backgroundColor: theme.colors.surface.secondary,
213
- },
214
- },
215
- ] as const;
216
- }
129
+ function createContainerStyles(theme: Theme) {
130
+ return ({ type = 'standard', pillMode = 'light' }: ContainerDynamicProps) => {
131
+ const bgColor = getContainerBackgroundColor(theme, type, pillMode);
217
132
 
218
- const createContainerStyles = (theme: Theme) => {
219
- return {
220
- display: 'flex',
221
- flexDirection: 'row',
222
- gap: 0,
223
- position: 'relative',
224
- borderBottomWidth: 1,
225
- borderBottomStyle: 'solid',
226
- borderBottomColor: theme.colors.border.primary,
227
- variants: {
228
- type: {
229
- standard: {},
230
- pills: {
231
- borderBottomWidth: 0,
232
- padding: 4,
233
- gap: 4,
234
- backgroundColor: theme.colors.surface.secondary,
235
- overflow: 'hidden',
236
- alignSelf: 'flex-start',
237
- },
238
- underline: {},
239
- },
240
- size: {
241
- xs: {},
242
- sm: {},
243
- md: {},
244
- lg: {},
245
- xl: {},
246
- },
247
- pillMode: {
248
- light: {},
249
- dark: {},
250
- },
251
- justify: {
252
- start: {
253
- justifyContent: 'flex-start',
133
+ return {
134
+ display: 'flex',
135
+ flexDirection: 'row',
136
+ gap: type === 'pills' ? 4 : 0,
137
+ position: 'relative',
138
+ borderBottomWidth: type === 'pills' ? 0 : 1,
139
+ borderBottomStyle: 'solid' as const,
140
+ borderBottomColor: theme.colors.border.primary,
141
+ padding: type === 'pills' ? 4 : undefined,
142
+ backgroundColor: bgColor || (type === 'pills' ? theme.colors.surface.secondary : undefined),
143
+ overflow: type === 'pills' ? 'hidden' as const : undefined,
144
+ alignSelf: type === 'pills' ? 'flex-start' as const : undefined,
145
+ width: type === 'pills' ? undefined : '100%',
146
+ borderRadius: type === 'pills' ? 9999 : undefined,
147
+ variants: {
148
+ justify: {
149
+ start: { justifyContent: 'flex-start' },
150
+ center: { justifyContent: 'center' },
151
+ equal: { justifyContent: 'stretch', width: '100%' },
152
+ 'space-between': { justifyContent: 'space-between', width: '100%' },
254
153
  },
255
- center: {
256
- justifyContent: 'center',
257
- },
258
- equal: {
259
- justifyContent: 'stretch',
260
- width: '100%',
261
- },
262
- 'space-between': {
263
- justifyContent: 'space-between',
264
- width: '100%',
265
- },
266
- },
267
- // Spacing variants from ContainerStyleProps
268
- gap: buildGapVariants(theme),
269
- padding: buildPaddingVariants(theme),
270
- paddingVertical: buildPaddingVerticalVariants(theme),
271
- paddingHorizontal: buildPaddingHorizontalVariants(theme),
272
- margin: buildMarginVariants(theme),
273
- marginVertical: buildMarginVerticalVariants(theme),
274
- marginHorizontal: buildMarginHorizontalVariants(theme),
275
- } as const,
276
- compoundVariants: createContainerCompoundVariants(theme),
277
- } as const;
154
+ // Spacing variants from ContainerStyleProps
155
+ gap: buildGapVariants(theme),
156
+ padding: buildPaddingVariants(theme),
157
+ paddingVertical: buildPaddingVerticalVariants(theme),
158
+ paddingHorizontal: buildPaddingHorizontalVariants(theme),
159
+ margin: buildMarginVariants(theme),
160
+ marginVertical: buildMarginVerticalVariants(theme),
161
+ marginHorizontal: buildMarginHorizontalVariants(theme),
162
+ } as const,
163
+ } as const;
164
+ };
278
165
  }
279
166
 
280
- const createTabStyles = (theme: Theme) => {
281
- return {
282
- display: 'flex',
283
- flexDirection: 'row',
284
- alignItems: 'center',
285
- justifyContent: 'center',
286
- fontWeight: '500',
287
- color: theme.colors.text.secondary,
288
- position: 'relative',
289
- zIndex: 2,
290
- backgroundColor: 'transparent',
291
- gap: 6,
292
- variants: {
293
- size: createTabSizeVariants(theme),
294
- type: {
295
- standard: {},
296
- pills: {
297
- borderRadius: 9999,
298
- marginRight: 0,
299
- backgroundColor: 'transparent',
300
- },
301
- underline: {},
302
- },
303
- active: {
304
- true: {
305
- color: theme.colors.text.primary,
306
- },
307
- false: {},
308
- },
309
- disabled: {
310
- true: {
311
- opacity: 0.5,
312
- _web: {
313
- cursor: 'not-allowed',
167
+ /**
168
+ * Create dynamic tab styles
169
+ */
170
+ function createTabStyles(theme: Theme) {
171
+ return ({ type = 'standard', size = 'md', active = false, pillMode = 'light', justify = 'start' }: TabDynamicProps) => {
172
+ const tabPadding = getTabPadding(type, size);
173
+ const color = getTabColor(theme, type, active);
174
+
175
+ return {
176
+ display: 'flex',
177
+ flexDirection: 'row',
178
+ alignItems: 'center',
179
+ justifyContent: 'center',
180
+ fontWeight: '500',
181
+ flex: justify === 'equal' ? 1 : undefined,
182
+ color: color || (active ? theme.colors.text.primary : theme.colors.text.secondary),
183
+ position: 'relative',
184
+ zIndex: 2,
185
+ backgroundColor: 'transparent',
186
+ gap: 6,
187
+ borderRadius: type === 'pills' ? 9999 : undefined,
188
+ ...tabPadding,
189
+ variants: {
190
+ size: createTabSizeVariants(theme),
191
+ disabled: {
192
+ true: {
193
+ opacity: 0.5,
194
+ _web: { cursor: 'not-allowed' },
314
195
  },
315
- },
316
- false: {
317
- _web: {
318
- _hover: {
319
- color: theme.colors.text.primary,
320
- },
196
+ false: {
197
+ _web: { _hover: { color: theme.colors.text.primary } },
321
198
  },
322
199
  },
323
- },
324
- pillMode: {
325
- light: {},
326
- dark: {},
327
- },
328
- iconPosition: {
329
- left: {
330
- flexDirection: 'row',
200
+ iconPosition: {
201
+ left: { flexDirection: 'row' },
202
+ top: { flexDirection: 'column' },
331
203
  },
332
- top: {
333
- flexDirection: 'column',
204
+ justify: {
205
+ start: {},
206
+ center: {},
207
+ equal: { flex: 1 },
208
+ 'space-between': {},
334
209
  },
335
- },
336
- justify: {
337
- start: {},
338
- center: {},
339
- equal: {
340
- flex: 1,
341
- },
342
- 'space-between': {},
343
- },
344
- } as const,
345
- compoundVariants: createTabCompoundVariants(theme),
346
- _web: {
347
- border: 'none',
348
- cursor: 'pointer',
349
- outline: 'none',
350
- transition: 'color 0.2s ease',
351
- },
352
- } as const;
210
+ } as const,
211
+ _web: {
212
+ border: 'none',
213
+ cursor: 'pointer',
214
+ outline: 'none',
215
+ transition: 'color 0.2s ease',
216
+ },
217
+ } as const;
218
+ };
353
219
  }
354
220
 
355
- const createTabLabelStyles = (theme: Theme) => {
356
- return {
357
- position: 'relative',
358
- zIndex: 3,
359
- fontWeight: '500',
360
- color: theme.colors.text.secondary,
361
- variants: {
362
- size: createLabelSizeVariants(theme),
363
- type: {
364
- standard: {},
365
- pills: {},
366
- underline: {},
367
- },
368
- active: {
369
- true: {
370
- color: theme.colors.text.primary,
371
- },
372
- false: {},
373
- },
374
- disabled: {
375
- true: {
376
- opacity: 0.5,
377
- },
378
- false: {},
379
- },
380
- pillMode: {
381
- light: {},
382
- dark: {},
383
- },
384
- },
385
- compoundVariants: createLabelCompoundVariants(theme),
386
- } as const;
387
- }
221
+ /**
222
+ * Create dynamic tab label styles
223
+ */
224
+ function createTabLabelStyles(theme: Theme) {
225
+ return ({ type = 'standard', active = false, pillMode = 'light' }: LabelDynamicProps) => {
226
+ const color = getLabelColor(theme, type, pillMode, active);
388
227
 
389
- const createIndicatorStyles = (theme: Theme) => {
390
- return {
391
- position: 'absolute',
392
- pointerEvents: 'none',
393
- zIndex: 1,
394
- variants: {
395
- type: {
396
- standard: {
397
- bottom: -1,
398
- height: 2,
399
- backgroundColor: theme.intents.primary.primary,
400
- },
401
- pills: {
402
- borderRadius: 9999,
403
- bottom: 4,
404
- top: 4,
405
- left: 0,
406
- },
407
- underline: {
408
- bottom: -1,
409
- height: 2,
410
- backgroundColor: theme.intents.primary.primary,
228
+ return {
229
+ position: 'relative',
230
+ zIndex: 3,
231
+ fontWeight: '500',
232
+ color: color || (active ? theme.colors.text.primary : theme.colors.text.secondary),
233
+ variants: {
234
+ size: createLabelSizeVariants(theme),
235
+ disabled: {
236
+ true: { opacity: 0.5 },
237
+ false: {},
411
238
  },
412
239
  },
413
- pillMode: {
414
- light: {},
415
- dark: {},
416
- },
417
- },
418
- compoundVariants: createIndicatorCompoundVariants(theme),
419
- _web: {
420
- transition: 'all 0.3s cubic-bezier(0.4, 0, 0.2, 1)',
421
- },
422
- } as const;
240
+ } as const;
241
+ };
423
242
  }
424
243
 
425
244
  /**
426
- * Create size variants for icon
245
+ * Create dynamic indicator styles
427
246
  */
428
- function createIconSizeVariants(theme: Theme) {
429
- return buildSizeVariants(theme, 'tabBar', (size) => ({
430
- width: size.iconSize || size.fontSize,
431
- height: size.iconSize || size.fontSize,
432
- }));
247
+ function createIndicatorStyles(theme: Theme) {
248
+ return ({ type = 'standard', pillMode = 'light' }: IndicatorDynamicProps) => {
249
+ const bgColor = getIndicatorBackgroundColor(theme, type, pillMode);
250
+
251
+ const typeStyles = type === 'pills' ? {
252
+ borderRadius: 9999,
253
+ bottom: 4,
254
+ top: 4,
255
+ left: 0,
256
+ backgroundColor: bgColor,
257
+ } : {
258
+ bottom: -1,
259
+ height: 2,
260
+ backgroundColor: theme.intents.primary.primary,
261
+ };
262
+
263
+ return {
264
+ position: 'absolute',
265
+ pointerEvents: 'none',
266
+ zIndex: 1,
267
+ ...typeStyles,
268
+ _web: {
269
+ transition: 'all 0.3s cubic-bezier(0.4, 0, 0.2, 1)',
270
+ },
271
+ } as const;
272
+ };
433
273
  }
434
274
 
435
- const createIconStyles = (theme: Theme) => {
275
+ /**
276
+ * Create icon styles (static, no compound variants)
277
+ */
278
+ function createIconStyles(theme: Theme) {
436
279
  return {
437
280
  display: 'flex',
438
281
  alignItems: 'center',
@@ -444,30 +287,31 @@ const createIconStyles = (theme: Theme) => {
444
287
  false: {},
445
288
  },
446
289
  disabled: {
447
- true: {
448
- opacity: 0.5,
449
- },
290
+ true: { opacity: 0.5 },
450
291
  false: {},
451
292
  },
452
293
  iconPosition: {
453
294
  left: {},
454
- top: {
455
- marginBottom: 2,
456
- },
295
+ top: { marginBottom: 2 },
457
296
  },
458
297
  } as const,
459
298
  } as const;
460
299
  }
461
300
 
462
301
  // Styles are inlined here instead of in @idealyst/theme because Unistyles' Babel transform on native cannot resolve function calls to extract variant structures.
463
- // @ts-ignore - TS language server needs restart to pick up theme structure changes
464
302
  export const tabBarStyles = StyleSheet.create((theme: Theme) => {
465
- return {
303
+ // Apply extensions to main visual elements
304
+ const extended = applyExtensions('TabBar', theme, {
466
305
  container: createContainerStyles(theme),
467
306
  tab: createTabStyles(theme),
307
+ indicator: createIndicatorStyles(theme),
308
+ });
309
+
310
+ return {
311
+ ...extended,
312
+ // Minor utility styles (not extended)
468
313
  tabLabel: createTabLabelStyles(theme),
469
314
  tabIcon: createIconStyles(theme),
470
- indicator: createIndicatorStyles(theme),
471
315
  };
472
316
  });
473
317