@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.
- package/package.json +8 -3
- package/src/Accordion/Accordion.native.tsx +15 -9
- package/src/Accordion/Accordion.styles.tsx +193 -168
- package/src/Accordion/Accordion.web.tsx +12 -7
- package/src/ActivityIndicator/ActivityIndicator.native.tsx +3 -2
- package/src/ActivityIndicator/ActivityIndicator.styles.tsx +22 -11
- package/src/ActivityIndicator/ActivityIndicator.web.tsx +2 -2
- package/src/Alert/Alert.native.tsx +11 -10
- package/src/Alert/Alert.styles.tsx +162 -253
- package/src/Alert/Alert.web.tsx +6 -10
- package/src/Avatar/Avatar.native.tsx +5 -2
- package/src/Avatar/Avatar.styles.tsx +48 -18
- package/src/Avatar/Avatar.web.tsx +2 -2
- package/src/Badge/Badge.native.tsx +2 -2
- package/src/Badge/Badge.styles.tsx +37 -16
- package/src/Badge/Badge.web.tsx +6 -6
- package/src/Breadcrumb/Breadcrumb.native.tsx +12 -5
- package/src/Breadcrumb/Breadcrumb.styles.tsx +59 -58
- package/src/Breadcrumb/Breadcrumb.web.tsx +13 -6
- package/src/Button/Button.native.tsx +39 -14
- package/src/Button/Button.styles.tsx +106 -208
- package/src/Button/Button.web.tsx +10 -8
- package/src/Card/Card.native.tsx +14 -6
- package/src/Card/Card.styles.tsx +64 -62
- package/src/Card/Card.web.tsx +5 -4
- package/src/Checkbox/Checkbox.native.tsx +7 -3
- package/src/Checkbox/Checkbox.styles.tsx +49 -25
- package/src/Checkbox/Checkbox.web.tsx +3 -3
- package/src/Chip/Chip.native.tsx +5 -5
- package/src/Chip/Chip.styles.tsx +71 -21
- package/src/Chip/Chip.web.tsx +5 -5
- package/src/Dialog/Dialog.native.tsx +10 -4
- package/src/Dialog/Dialog.styles.tsx +130 -90
- package/src/Dialog/Dialog.web.tsx +4 -4
- package/src/Divider/Divider.native.tsx +29 -42
- package/src/Divider/Divider.styles.tsx +138 -242
- package/src/Divider/Divider.web.tsx +17 -14
- package/src/Icon/Icon.native.tsx +11 -3
- package/src/Icon/Icon.styles.tsx +10 -4
- package/src/Image/Image.styles.tsx +53 -37
- package/src/Input/Input.native.tsx +6 -7
- package/src/Input/Input.styles.tsx +194 -174
- package/src/Input/Input.web.tsx +5 -8
- package/src/Link/Link.native.tsx +4 -1
- package/src/List/List.styles.tsx +79 -105
- package/src/List/ListItem.native.tsx +5 -3
- package/src/List/ListItem.web.tsx +4 -3
- package/src/Menu/Menu.native.tsx +1 -1
- package/src/Menu/Menu.styles.tsx +53 -37
- package/src/Menu/Menu.web.tsx +2 -2
- package/src/Menu/MenuItem.native.tsx +5 -3
- package/src/Menu/MenuItem.styles.tsx +68 -69
- package/src/Menu/MenuItem.web.tsx +16 -3
- package/src/Popover/Popover.native.tsx +1 -1
- package/src/Popover/Popover.styles.tsx +40 -29
- package/src/Popover/Popover.web.tsx +1 -1
- package/src/Pressable/Pressable.native.tsx +3 -1
- package/src/Pressable/Pressable.styles.tsx +20 -13
- package/src/Pressable/Pressable.web.tsx +1 -1
- package/src/Progress/Progress.native.tsx +15 -6
- package/src/Progress/Progress.styles.tsx +125 -85
- package/src/Progress/Progress.web.tsx +10 -9
- package/src/RadioButton/RadioButton.native.tsx +8 -3
- package/src/RadioButton/RadioButton.styles.tsx +44 -37
- package/src/RadioButton/RadioButton.web.tsx +3 -3
- package/src/SVGImage/SVGImage.styles.tsx +28 -16
- package/src/Screen/Screen.native.tsx +23 -13
- package/src/Screen/Screen.styles.tsx +57 -46
- package/src/Screen/Screen.web.tsx +1 -1
- package/src/Select/Select.native.tsx +11 -5
- package/src/Select/Select.styles.tsx +72 -52
- package/src/Select/Select.web.tsx +5 -5
- package/src/Skeleton/Skeleton.styles.tsx +26 -14
- package/src/Slider/Slider.native.tsx +9 -5
- package/src/Slider/Slider.styles.tsx +59 -48
- package/src/Slider/Slider.web.tsx +5 -5
- package/src/Switch/Switch.native.tsx +6 -2
- package/src/Switch/Switch.styles.tsx +46 -19
- package/src/Switch/Switch.web.tsx +4 -4
- package/src/TabBar/TabBar.native.tsx +23 -31
- package/src/TabBar/TabBar.styles.tsx +215 -371
- package/src/TabBar/TabBar.web.tsx +21 -33
- package/src/Table/Table.native.tsx +1 -1
- package/src/Table/Table.styles.tsx +11 -4
- package/src/Table/Table.web.tsx +1 -1
- package/src/Text/Text.native.tsx +3 -4
- package/src/Text/Text.styles.tsx +7 -1
- package/src/Text/Text.web.tsx +1 -1
- package/src/TextArea/TextArea.styles.tsx +90 -58
- package/src/Tooltip/Tooltip.native.tsx +2 -2
- package/src/Tooltip/Tooltip.styles.tsx +21 -12
- package/src/Tooltip/Tooltip.web.tsx +2 -2
- package/src/Video/Video.styles.tsx +39 -23
- package/src/View/View.native.tsx +4 -2
- package/src/View/View.styles.tsx +33 -22
- package/src/View/View.web.tsx +13 -2
- package/src/extensions/applyExtension.ts +210 -0
- package/src/extensions/extendComponent.ts +377 -0
- package/src/extensions/index.ts +102 -0
- package/src/extensions/types.ts +497 -0
- package/src/globals.ts +16 -0
- package/src/index.native.ts +4 -0
- package/src/index.ts +28 -0
- package/src/utils/deepMerge.ts +54 -2
|
@@ -7,6 +7,7 @@ import {
|
|
|
7
7
|
buildMarginHorizontalVariants,
|
|
8
8
|
} from '../utils/buildViewStyleVariants';
|
|
9
9
|
import { SliderIntentVariant } from './types';
|
|
10
|
+
import { applyExtensions } from '../extensions/applyExtension';
|
|
10
11
|
|
|
11
12
|
/**
|
|
12
13
|
* Create size variants for track
|
|
@@ -155,69 +156,79 @@ const createThumbIconStyles = (theme: Theme) => {
|
|
|
155
156
|
}
|
|
156
157
|
}
|
|
157
158
|
|
|
159
|
+
// Container style creator for extension support
|
|
160
|
+
function createContainerStyles(theme: Theme) {
|
|
161
|
+
return () => ({
|
|
162
|
+
gap: 4,
|
|
163
|
+
paddingVertical: 8,
|
|
164
|
+
variants: {
|
|
165
|
+
margin: buildMarginVariants(theme),
|
|
166
|
+
marginVertical: buildMarginVerticalVariants(theme),
|
|
167
|
+
marginHorizontal: buildMarginHorizontalVariants(theme),
|
|
168
|
+
},
|
|
169
|
+
});
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
// Track style creator for extension support
|
|
173
|
+
function createTrackStyles(theme: Theme) {
|
|
174
|
+
return () => ({
|
|
175
|
+
backgroundColor: theme.colors.surface.tertiary,
|
|
176
|
+
borderRadius: 9999,
|
|
177
|
+
position: 'relative' as const,
|
|
178
|
+
variants: {
|
|
179
|
+
size: createTrackSizeVariants(theme),
|
|
180
|
+
disabled: {
|
|
181
|
+
true: {
|
|
182
|
+
opacity: 0.5,
|
|
183
|
+
_web: { cursor: 'not-allowed' },
|
|
184
|
+
},
|
|
185
|
+
false: {
|
|
186
|
+
opacity: 1,
|
|
187
|
+
_web: { cursor: 'pointer' },
|
|
188
|
+
},
|
|
189
|
+
},
|
|
190
|
+
} as const,
|
|
191
|
+
});
|
|
192
|
+
}
|
|
193
|
+
|
|
158
194
|
// Styles are inlined here instead of in @idealyst/theme because Unistyles' Babel transform on native cannot resolve function calls to extract variant structures.
|
|
159
|
-
// @ts-ignore - TS language server needs restart to pick up theme structure changes
|
|
160
195
|
export const sliderStyles = StyleSheet.create((theme: Theme) => {
|
|
196
|
+
// Apply extensions to main visual elements
|
|
197
|
+
const extended = applyExtensions('Slider', theme, {
|
|
198
|
+
container: createContainerStyles(theme),
|
|
199
|
+
track: createTrackStyles(theme),
|
|
200
|
+
filledTrack: createFilledTrackStyles(theme),
|
|
201
|
+
thumb: createThumbStyles(theme),
|
|
202
|
+
thumbIcon: createThumbIconStyles(theme),
|
|
203
|
+
});
|
|
204
|
+
|
|
161
205
|
return {
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
paddingVertical: 8,
|
|
165
|
-
variants: {
|
|
166
|
-
// Spacing variants from FormInputStyleProps
|
|
167
|
-
margin: buildMarginVariants(theme),
|
|
168
|
-
marginVertical: buildMarginVerticalVariants(theme),
|
|
169
|
-
marginHorizontal: buildMarginHorizontalVariants(theme),
|
|
170
|
-
},
|
|
171
|
-
},
|
|
206
|
+
...extended,
|
|
207
|
+
// Minor utility styles
|
|
172
208
|
sliderWrapper: {
|
|
173
209
|
position: 'relative',
|
|
174
210
|
paddingVertical: 4,
|
|
175
211
|
},
|
|
176
|
-
track: {
|
|
177
|
-
backgroundColor: theme.colors.surface.tertiary,
|
|
178
|
-
borderRadius: 9999,
|
|
179
|
-
position: 'relative',
|
|
180
|
-
variants: {
|
|
181
|
-
size: createTrackSizeVariants(theme),
|
|
182
|
-
disabled: {
|
|
183
|
-
true: {
|
|
184
|
-
opacity: 0.5,
|
|
185
|
-
_web: {
|
|
186
|
-
cursor: 'not-allowed',
|
|
187
|
-
},
|
|
188
|
-
},
|
|
189
|
-
false: {
|
|
190
|
-
opacity: 1,
|
|
191
|
-
_web: {
|
|
192
|
-
cursor: 'pointer',
|
|
193
|
-
},
|
|
194
|
-
},
|
|
195
|
-
},
|
|
196
|
-
} as const,
|
|
197
|
-
} as const,
|
|
198
|
-
filledTrack: createFilledTrackStyles(theme),
|
|
199
|
-
thumb: createThumbStyles(theme),
|
|
200
212
|
thumbActive: {
|
|
201
213
|
_web: {
|
|
202
214
|
transform: 'translate(-50%, -50%) scale(1.1)',
|
|
203
215
|
},
|
|
204
216
|
},
|
|
205
|
-
thumbIcon: createThumbIconStyles(theme),
|
|
206
217
|
valueLabel: {
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
218
|
+
fontSize: 12,
|
|
219
|
+
fontWeight: '600',
|
|
220
|
+
color: theme.colors.text.primary,
|
|
221
|
+
textAlign: 'center',
|
|
222
|
+
},
|
|
212
223
|
minMaxLabels: {
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
224
|
+
flexDirection: 'row',
|
|
225
|
+
justifyContent: 'space-between',
|
|
226
|
+
marginTop: 4,
|
|
227
|
+
},
|
|
217
228
|
minMaxLabel: {
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
229
|
+
fontSize: 12,
|
|
230
|
+
color: theme.colors.text.secondary,
|
|
231
|
+
},
|
|
221
232
|
mark: {
|
|
222
233
|
position: 'absolute',
|
|
223
234
|
width: 2,
|
|
@@ -57,10 +57,10 @@ const Slider = forwardRef<HTMLDivElement, SliderProps>(({
|
|
|
57
57
|
marginHorizontal,
|
|
58
58
|
});
|
|
59
59
|
|
|
60
|
-
const containerProps = getWebProps([sliderStyles.container, style as any]);
|
|
60
|
+
const containerProps = getWebProps([(sliderStyles.container as any)({}), style as any]);
|
|
61
61
|
const wrapperProps = getWebProps([sliderStyles.sliderWrapper]);
|
|
62
|
-
const trackProps = getWebProps([sliderStyles.track]);
|
|
63
|
-
const thumbIconProps = getWebProps([sliderStyles.thumbIcon({ intent })]);
|
|
62
|
+
const trackProps = getWebProps([(sliderStyles.track as any)({})]);
|
|
63
|
+
const thumbIconProps = getWebProps([(sliderStyles.thumbIcon as any)({ intent })]);
|
|
64
64
|
const valueLabelProps = getWebProps([sliderStyles.valueLabel]);
|
|
65
65
|
const minMaxLabelsProps = getWebProps([sliderStyles.minMaxLabels]);
|
|
66
66
|
const minMaxLabelProps = getWebProps([sliderStyles.minMaxLabel]);
|
|
@@ -211,9 +211,9 @@ const Slider = forwardRef<HTMLDivElement, SliderProps>(({
|
|
|
211
211
|
const percentage = ((value - min) / (max - min)) * 100;
|
|
212
212
|
|
|
213
213
|
// Dynamic styles with percentage
|
|
214
|
-
const filledTrackProps = getWebProps([sliderStyles.filledTrack({ intent }), { width: `${percentage}%` }]);
|
|
214
|
+
const filledTrackProps = getWebProps([(sliderStyles.filledTrack as any)({ intent }), { width: `${percentage}%` }]);
|
|
215
215
|
const thumbProps = getWebProps([
|
|
216
|
-
sliderStyles.thumb({ intent, disabled }),
|
|
216
|
+
(sliderStyles.thumb as any)({ intent, disabled }),
|
|
217
217
|
isDragging && sliderStyles.thumbActive,
|
|
218
218
|
{ left: `${percentage}%` }
|
|
219
219
|
]);
|
|
@@ -118,6 +118,10 @@ const Switch = forwardRef<ComponentRef<typeof Pressable>, SwitchProps>(({
|
|
|
118
118
|
};
|
|
119
119
|
});
|
|
120
120
|
|
|
121
|
+
// Get dynamic styles
|
|
122
|
+
const switchTrackStyle = (switchStyles.switchTrack as any)({ checked, intent });
|
|
123
|
+
const containerStyle = (switchStyles.container as any)({});
|
|
124
|
+
|
|
121
125
|
const switchElement = (
|
|
122
126
|
<Pressable
|
|
123
127
|
ref={!label ? ref : undefined}
|
|
@@ -128,7 +132,7 @@ const Switch = forwardRef<ComponentRef<typeof Pressable>, SwitchProps>(({
|
|
|
128
132
|
testID={testID}
|
|
129
133
|
{...nativeA11yProps}
|
|
130
134
|
>
|
|
131
|
-
<Animated.View style={
|
|
135
|
+
<Animated.View style={switchTrackStyle}>
|
|
132
136
|
<Animated.View
|
|
133
137
|
style={[
|
|
134
138
|
{
|
|
@@ -158,7 +162,7 @@ const Switch = forwardRef<ComponentRef<typeof Pressable>, SwitchProps>(({
|
|
|
158
162
|
nativeID={id}
|
|
159
163
|
onPress={handlePress}
|
|
160
164
|
disabled={disabled}
|
|
161
|
-
style={[
|
|
165
|
+
style={[containerStyle, style]}
|
|
162
166
|
>
|
|
163
167
|
{labelPosition === 'left' && (
|
|
164
168
|
<Text style={switchStyles.label}>{label}</Text>
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { StyleSheet } from 'react-native-unistyles';
|
|
2
|
-
import { Theme, StylesheetStyles, Intent, Size} from '@idealyst/theme';
|
|
2
|
+
import { Theme, StylesheetStyles, Intent, Size } from '@idealyst/theme';
|
|
3
3
|
import { buildSizeVariants } from '../utils/buildSizeVariants';
|
|
4
4
|
import {
|
|
5
5
|
buildMarginVariants,
|
|
@@ -7,6 +7,7 @@ import {
|
|
|
7
7
|
buildMarginHorizontalVariants,
|
|
8
8
|
} from '../utils/buildViewStyleVariants';
|
|
9
9
|
import { SwitchIntentVariant, SwitchSizeVariant } from './types';
|
|
10
|
+
import { applyExtensions } from '../extensions/applyExtension';
|
|
10
11
|
|
|
11
12
|
function createTrackSizeVariants(theme: Theme) {
|
|
12
13
|
return buildSizeVariants(theme, 'switch', (size) => ({
|
|
@@ -127,34 +128,42 @@ function createThumbIconStyles(theme: Theme) {
|
|
|
127
128
|
}
|
|
128
129
|
}
|
|
129
130
|
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
flexDirection: 'row',
|
|
136
|
-
alignItems: 'center',
|
|
131
|
+
/**
|
|
132
|
+
* Create container styles
|
|
133
|
+
*/
|
|
134
|
+
function createContainerStyles(theme: Theme) {
|
|
135
|
+
return () => ({
|
|
136
|
+
flexDirection: 'row' as const,
|
|
137
|
+
alignItems: 'center' as const,
|
|
137
138
|
gap: 8,
|
|
138
139
|
variants: {
|
|
139
|
-
// Spacing variants from FormInputStyleProps
|
|
140
140
|
margin: buildMarginVariants(theme),
|
|
141
141
|
marginVertical: buildMarginVerticalVariants(theme),
|
|
142
142
|
marginHorizontal: buildMarginHorizontalVariants(theme),
|
|
143
143
|
},
|
|
144
|
-
}
|
|
145
|
-
|
|
146
|
-
|
|
144
|
+
});
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
/**
|
|
148
|
+
* Create switch container styles
|
|
149
|
+
*/
|
|
150
|
+
function createSwitchContainerStyles() {
|
|
151
|
+
return () => ({
|
|
152
|
+
justifyContent: 'center' as const,
|
|
147
153
|
_web: {
|
|
148
154
|
border: 'none',
|
|
149
155
|
padding: 0,
|
|
150
156
|
backgroundColor: 'transparent',
|
|
151
157
|
width: 'fit-content',
|
|
152
|
-
}
|
|
153
|
-
}
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
+
},
|
|
159
|
+
});
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
/**
|
|
163
|
+
* Create label styles
|
|
164
|
+
*/
|
|
165
|
+
function createLabelStyles(theme: Theme) {
|
|
166
|
+
return () => ({
|
|
158
167
|
fontSize: 14,
|
|
159
168
|
color: theme.colors.text.primary,
|
|
160
169
|
variants: {
|
|
@@ -175,6 +184,24 @@ export const switchStyles = StyleSheet.create((theme: Theme) => {
|
|
|
175
184
|
},
|
|
176
185
|
},
|
|
177
186
|
} as const,
|
|
178
|
-
}
|
|
187
|
+
});
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
// Styles are inlined here instead of in @idealyst/theme because Unistyles' Babel
|
|
191
|
+
// transform on native cannot resolve function calls to extract variant structures.
|
|
192
|
+
export const switchStyles = StyleSheet.create((theme: Theme) => {
|
|
193
|
+
// Apply extensions to main visual elements
|
|
194
|
+
const extended = applyExtensions('Switch', theme, {
|
|
195
|
+
container: createContainerStyles(theme),
|
|
196
|
+
switchTrack: createSwitchTrackStyles(theme),
|
|
197
|
+
switchThumb: createSwitchThumbStyles(theme),
|
|
198
|
+
});
|
|
199
|
+
|
|
200
|
+
return {
|
|
201
|
+
...extended,
|
|
202
|
+
// Minor utility styles (not extended)
|
|
203
|
+
switchContainer: createSwitchContainerStyles()(),
|
|
204
|
+
thumbIcon: createThumbIconStyles(theme),
|
|
205
|
+
label: createLabelStyles(theme)(),
|
|
179
206
|
};
|
|
180
207
|
});
|
|
@@ -82,9 +82,9 @@ const Switch = forwardRef<HTMLDivElement | HTMLButtonElement, SwitchProps>(({
|
|
|
82
82
|
marginHorizontal,
|
|
83
83
|
});
|
|
84
84
|
|
|
85
|
-
const trackProps = getWebProps([switchStyles.switchTrack({ checked, intent })]);
|
|
86
|
-
const thumbProps = getWebProps([switchStyles.switchThumb({ size, checked })]);
|
|
87
|
-
const thumbIconProps = getWebProps([switchStyles.thumbIcon({ checked, intent })]);
|
|
85
|
+
const trackProps = getWebProps([(switchStyles.switchTrack as any)({ checked, intent })]);
|
|
86
|
+
const thumbProps = getWebProps([(switchStyles.switchThumb as any)({ size, checked })]);
|
|
87
|
+
const thumbIconProps = getWebProps([(switchStyles.thumbIcon as any)({ checked, intent })]);
|
|
88
88
|
const labelProps = getWebProps([switchStyles.label]);
|
|
89
89
|
|
|
90
90
|
// Helper to render icon
|
|
@@ -115,7 +115,7 @@ const Switch = forwardRef<HTMLDivElement | HTMLButtonElement, SwitchProps>(({
|
|
|
115
115
|
|
|
116
116
|
// Computed container props with dynamic styles (for when label exists)
|
|
117
117
|
const computedContainerProps = getWebProps([
|
|
118
|
-
switchStyles.container,
|
|
118
|
+
(switchStyles.container as any)({}),
|
|
119
119
|
style as any,
|
|
120
120
|
{
|
|
121
121
|
cursor: disabled ? 'not-allowed' : 'pointer',
|
|
@@ -88,11 +88,11 @@ const TabBar = forwardRef<View, TabBarProps>(({
|
|
|
88
88
|
const containerPadding = type === 'pills' ? 4 : 0;
|
|
89
89
|
|
|
90
90
|
indicatorPosition.value = withSpring(layout.x + containerPadding, {
|
|
91
|
-
damping:
|
|
91
|
+
damping: 100,
|
|
92
92
|
stiffness: 300,
|
|
93
93
|
});
|
|
94
94
|
indicatorWidth.value = withSpring(layout.width, {
|
|
95
|
-
damping:
|
|
95
|
+
damping: 100,
|
|
96
96
|
stiffness: 300,
|
|
97
97
|
});
|
|
98
98
|
}
|
|
@@ -128,11 +128,8 @@ const TabBar = forwardRef<View, TabBarProps>(({
|
|
|
128
128
|
};
|
|
129
129
|
});
|
|
130
130
|
|
|
131
|
-
// Apply container
|
|
131
|
+
// Apply container variants (for spacing only)
|
|
132
132
|
tabBarContainerStyles.useVariants({
|
|
133
|
-
type,
|
|
134
|
-
size,
|
|
135
|
-
pillMode,
|
|
136
133
|
justify,
|
|
137
134
|
gap,
|
|
138
135
|
padding,
|
|
@@ -142,46 +139,37 @@ const TabBar = forwardRef<View, TabBarProps>(({
|
|
|
142
139
|
marginVertical,
|
|
143
140
|
marginHorizontal,
|
|
144
141
|
});
|
|
145
|
-
|
|
142
|
+
|
|
143
|
+
// Compute dynamic container and indicator styles
|
|
144
|
+
const containerStyle = (tabBarContainerStyles.container as any)({ type, pillMode });
|
|
145
|
+
const indicatorStyle = (tabBarIndicatorStyles.indicator as any)({ type, pillMode });
|
|
146
146
|
|
|
147
147
|
return (
|
|
148
148
|
<ScrollView
|
|
149
149
|
horizontal
|
|
150
150
|
showsHorizontalScrollIndicator={false}
|
|
151
|
-
contentContainerStyle={{
|
|
151
|
+
contentContainerStyle={{
|
|
152
|
+
position: 'relative',
|
|
153
|
+
flexGrow: 1,
|
|
154
|
+
}}
|
|
155
|
+
style={{ width: '100%' }}
|
|
152
156
|
>
|
|
153
|
-
<View ref={ref} nativeID={id} style={[
|
|
157
|
+
<View ref={ref} nativeID={id} style={[containerStyle, style]} testID={testID} {...nativeA11yProps}>
|
|
154
158
|
{/* Animated indicator - render first so it's behind */}
|
|
155
159
|
<Animated.View
|
|
156
160
|
style={[
|
|
157
|
-
|
|
161
|
+
indicatorStyle,
|
|
158
162
|
indicatorAnimatedStyle,
|
|
159
163
|
]}
|
|
160
164
|
/>
|
|
161
165
|
|
|
162
166
|
{/* Tabs - render second so they're on top */}
|
|
163
|
-
<View style={{ flexDirection: 'row' }}>
|
|
167
|
+
<View style={{ flexDirection: 'row', flex: 1 }}>
|
|
164
168
|
{items.map((item) => {
|
|
165
169
|
const isActive = value === item.value;
|
|
166
170
|
const iconSize = ICON_SIZES[size] || 18;
|
|
167
171
|
|
|
168
|
-
// Apply
|
|
169
|
-
tabBarTabStyles.useVariants({
|
|
170
|
-
size,
|
|
171
|
-
type,
|
|
172
|
-
active: isActive,
|
|
173
|
-
disabled: Boolean(item.disabled),
|
|
174
|
-
pillMode,
|
|
175
|
-
iconPosition,
|
|
176
|
-
justify,
|
|
177
|
-
});
|
|
178
|
-
tabBarLabelStyles.useVariants({
|
|
179
|
-
size,
|
|
180
|
-
type,
|
|
181
|
-
pillMode,
|
|
182
|
-
active: isActive,
|
|
183
|
-
disabled: Boolean(item.disabled),
|
|
184
|
-
});
|
|
172
|
+
// Apply icon variants (size, disabled, iconPosition)
|
|
185
173
|
tabBarIconStyles.useVariants({
|
|
186
174
|
size,
|
|
187
175
|
active: isActive,
|
|
@@ -189,6 +177,10 @@ const TabBar = forwardRef<View, TabBarProps>(({
|
|
|
189
177
|
iconPosition,
|
|
190
178
|
});
|
|
191
179
|
|
|
180
|
+
// Compute dynamic styles for this tab
|
|
181
|
+
const tabStyle = (tabBarTabStyles.tab as any)({ type, size, active: isActive, pillMode, justify });
|
|
182
|
+
const labelStyle = (tabBarLabelStyles.tabLabel as any)({ type, active: isActive, pillMode });
|
|
183
|
+
|
|
192
184
|
const icon = renderIcon(item.icon, isActive, iconSize);
|
|
193
185
|
|
|
194
186
|
return (
|
|
@@ -198,7 +190,7 @@ const TabBar = forwardRef<View, TabBarProps>(({
|
|
|
198
190
|
const { x, width } = event.nativeEvent.layout;
|
|
199
191
|
handleTabLayout(item.value, x, width);
|
|
200
192
|
}}
|
|
201
|
-
style={
|
|
193
|
+
style={tabStyle}
|
|
202
194
|
onPress={() => handleTabClick(item.value, item.disabled)}
|
|
203
195
|
disabled={item.disabled}
|
|
204
196
|
activeOpacity={0.7}
|
|
@@ -207,8 +199,8 @@ const TabBar = forwardRef<View, TabBarProps>(({
|
|
|
207
199
|
accessibilityLabel={item.label}
|
|
208
200
|
accessibilityState={{ selected: isActive, disabled: item.disabled }}
|
|
209
201
|
>
|
|
210
|
-
{icon && <View style={tabBarIconStyles.tabIcon}>{icon}</View>}
|
|
211
|
-
<Text style={
|
|
202
|
+
{icon && <View style={tabBarIconStyles.tabIcon as any}>{icon}</View>}
|
|
203
|
+
<Text style={labelStyle}>{item.label}</Text>
|
|
212
204
|
</TouchableOpacity>
|
|
213
205
|
);
|
|
214
206
|
})}
|