@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
|
@@ -38,11 +38,11 @@ const Avatar = forwardRef<HTMLDivElement, AvatarProps>(({
|
|
|
38
38
|
shape,
|
|
39
39
|
});
|
|
40
40
|
|
|
41
|
-
const avatarStyleArray = [avatarStyles.avatar, style];
|
|
41
|
+
const avatarStyleArray = [(avatarStyles.avatar as any)({}), style];
|
|
42
42
|
const avatarProps = getWebProps(avatarStyleArray);
|
|
43
43
|
|
|
44
44
|
// Generate fallback text styles with proper theming and size
|
|
45
|
-
const fallbackStyleArray = [avatarStyles.fallback];
|
|
45
|
+
const fallbackStyleArray = [(avatarStyles.fallback as any)({})];
|
|
46
46
|
const fallbackProps = getWebProps(fallbackStyleArray);
|
|
47
47
|
|
|
48
48
|
const handleImageError = () => {
|
|
@@ -21,8 +21,8 @@ const Badge = forwardRef<View, BadgeProps>(({
|
|
|
21
21
|
});
|
|
22
22
|
|
|
23
23
|
// Call dynamic styles with color variant
|
|
24
|
-
const badgeStyle = badgeStyles.badge({ color });
|
|
25
|
-
const textStyle = badgeStyles.text({ color });
|
|
24
|
+
const badgeStyle = (badgeStyles.badge as any)({ color });
|
|
25
|
+
const textStyle = (badgeStyles.text as any)({ color });
|
|
26
26
|
|
|
27
27
|
// Map badge size to icon size
|
|
28
28
|
const iconSize = size === 'sm' ? 12 : size === 'md' ? 14 : 16;
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { StyleSheet } from 'react-native-unistyles';
|
|
2
2
|
import { Theme, StylesheetStyles, getColorFromString, Size, Color } from '@idealyst/theme';
|
|
3
3
|
import { buildSizeVariants } from '../utils/buildSizeVariants';
|
|
4
|
+
import { applyExtensions } from '../extensions/applyExtension';
|
|
4
5
|
|
|
5
6
|
type BadgeType = 'filled' | 'outlined' | 'dot';
|
|
6
7
|
|
|
@@ -112,29 +113,49 @@ function createTextStyles(theme: Theme) {
|
|
|
112
113
|
};
|
|
113
114
|
}
|
|
114
115
|
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
justifyContent: 'center',
|
|
116
|
+
/**
|
|
117
|
+
* Create content styles
|
|
118
|
+
*/
|
|
119
|
+
function createContentStyles() {
|
|
120
|
+
return () => ({
|
|
121
|
+
display: 'flex' as const,
|
|
122
|
+
flexDirection: 'row' as const,
|
|
123
|
+
alignItems: 'center' as const,
|
|
124
|
+
justifyContent: 'center' as const,
|
|
125
125
|
gap: 4,
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
126
|
+
});
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
/**
|
|
130
|
+
* Create icon styles
|
|
131
|
+
*/
|
|
132
|
+
function createIconStyles(theme: Theme) {
|
|
133
|
+
return () => ({
|
|
134
|
+
display: 'flex' as const,
|
|
135
|
+
alignItems: 'center' as const,
|
|
136
|
+
justifyContent: 'center' as const,
|
|
131
137
|
variants: {
|
|
132
138
|
size: buildSizeVariants(theme, 'badge', (size) => ({
|
|
133
139
|
width: size.iconSize,
|
|
134
140
|
height: size.iconSize,
|
|
135
141
|
})),
|
|
136
142
|
},
|
|
137
|
-
}
|
|
143
|
+
});
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
// Styles are inlined here instead of in @idealyst/theme because Unistyles' Babel
|
|
147
|
+
// transform on native cannot resolve function calls to extract variant structures.
|
|
148
|
+
export const badgeStyles = StyleSheet.create((theme: Theme) => {
|
|
149
|
+
// Apply extensions to main visual elements
|
|
150
|
+
const extended = applyExtensions('Badge', theme, {
|
|
151
|
+
badge: createBadgeStyles(theme),
|
|
138
152
|
text: createTextStyles(theme),
|
|
153
|
+
});
|
|
154
|
+
|
|
155
|
+
return {
|
|
156
|
+
...extended,
|
|
157
|
+
// Minor utility styles (not extended)
|
|
158
|
+
content: createContentStyles()(),
|
|
159
|
+
icon: createIconStyles(theme)(),
|
|
139
160
|
};
|
|
140
161
|
});
|
package/src/Badge/Badge.web.tsx
CHANGED
|
@@ -28,13 +28,13 @@ const Badge = forwardRef<HTMLSpanElement, BadgeProps>((props: InternalBadgeProps
|
|
|
28
28
|
type,
|
|
29
29
|
});
|
|
30
30
|
|
|
31
|
-
const badgeStyle = badgeStyles.badge({ color });
|
|
31
|
+
const badgeStyle = (badgeStyles.badge as any)({ color });
|
|
32
32
|
const contentStyle = badgeStyles.content;
|
|
33
|
-
const textStyle = badgeStyles.text({ color });
|
|
34
|
-
|
|
35
|
-
const badgeProps = getWebProps(badgeStyle);
|
|
36
|
-
const contentProps = getWebProps(contentStyle);
|
|
37
|
-
const textProps = getWebProps(textStyle);
|
|
33
|
+
const textStyle = (badgeStyles.text as any)({ color });
|
|
34
|
+
|
|
35
|
+
const badgeProps = getWebProps([badgeStyle]);
|
|
36
|
+
const contentProps = getWebProps([contentStyle]);
|
|
37
|
+
const textProps = getWebProps([textStyle]);
|
|
38
38
|
const iconProps = getWebProps([badgeStyles.icon, textStyle]);
|
|
39
39
|
|
|
40
40
|
// Helper to render icon
|
|
@@ -22,13 +22,20 @@ interface BreadcrumbItemProps {
|
|
|
22
22
|
}
|
|
23
23
|
|
|
24
24
|
const BreadcrumbItem: React.FC<BreadcrumbItemProps> = ({ item, isLast, size, intent, itemStyle }) => {
|
|
25
|
-
|
|
25
|
+
const isClickable = !!item.onPress && !item.disabled;
|
|
26
|
+
const isDisabled = item.disabled || false;
|
|
27
|
+
|
|
28
|
+
// Apply size variant
|
|
26
29
|
breadcrumbItemStyles.useVariants({
|
|
27
30
|
size,
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
// Get dynamic item text style
|
|
34
|
+
const itemTextStyle = (breadcrumbItemStyles.itemText as any)({
|
|
28
35
|
intent,
|
|
29
|
-
disabled: item.disabled || false,
|
|
30
36
|
isLast,
|
|
31
|
-
|
|
37
|
+
disabled: isDisabled,
|
|
38
|
+
clickable: isClickable,
|
|
32
39
|
});
|
|
33
40
|
|
|
34
41
|
const iconStyle = breadcrumbItemStyles.icon;
|
|
@@ -55,11 +62,11 @@ const BreadcrumbItem: React.FC<BreadcrumbItemProps> = ({ item, isLast, size, int
|
|
|
55
62
|
const content = (
|
|
56
63
|
<View style={[breadcrumbItemStyles.item, itemStyle]}>
|
|
57
64
|
{item.icon && <View style={iconStyle}>{renderIcon()}</View>}
|
|
58
|
-
<Text style={
|
|
65
|
+
<Text style={itemTextStyle}>{item.label}</Text>
|
|
59
66
|
</View>
|
|
60
67
|
);
|
|
61
68
|
|
|
62
|
-
if (
|
|
69
|
+
if (isClickable) {
|
|
63
70
|
return (
|
|
64
71
|
<Pressable
|
|
65
72
|
onPress={item.onPress}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { StyleSheet } from 'react-native-unistyles';
|
|
2
|
-
import { Theme, StylesheetStyles,
|
|
2
|
+
import { Theme, StylesheetStyles, Size } from '@idealyst/theme';
|
|
3
3
|
import { buildSizeVariants } from '../utils/buildSizeVariants';
|
|
4
|
+
import { applyExtensions } from '../extensions/applyExtension';
|
|
4
5
|
|
|
5
6
|
type BreadcrumbSize = Size;
|
|
6
7
|
type BreadcrumbIntent = 'primary' | 'neutral';
|
|
@@ -27,6 +28,13 @@ export type BreadcrumbStylesheet = {
|
|
|
27
28
|
menuButtonIcon: ExpandedBreadcrumbStyles;
|
|
28
29
|
}
|
|
29
30
|
|
|
31
|
+
type ItemTextDynamicProps = {
|
|
32
|
+
intent?: BreadcrumbIntent;
|
|
33
|
+
isLast?: boolean;
|
|
34
|
+
disabled?: boolean;
|
|
35
|
+
clickable?: boolean;
|
|
36
|
+
};
|
|
37
|
+
|
|
30
38
|
/**
|
|
31
39
|
* Create size variants for item text
|
|
32
40
|
*/
|
|
@@ -38,31 +46,19 @@ function createItemTextSizeVariants(theme: Theme) {
|
|
|
38
46
|
}
|
|
39
47
|
|
|
40
48
|
/**
|
|
41
|
-
*
|
|
49
|
+
* Get item text color based on state
|
|
42
50
|
*/
|
|
43
|
-
function
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
intent: 'neutral',
|
|
55
|
-
isLast: false,
|
|
56
|
-
disabled: false,
|
|
57
|
-
styles: { color: theme.colors.text.secondary },
|
|
58
|
-
},
|
|
59
|
-
{
|
|
60
|
-
clickable: false,
|
|
61
|
-
isLast: false,
|
|
62
|
-
disabled: false,
|
|
63
|
-
styles: { color: theme.colors.text.secondary },
|
|
64
|
-
},
|
|
65
|
-
];
|
|
51
|
+
function getItemTextColor(theme: Theme, intent: BreadcrumbIntent, isLast: boolean, disabled: boolean, clickable: boolean): string {
|
|
52
|
+
if (disabled) {
|
|
53
|
+
return theme.colors.text.secondary;
|
|
54
|
+
}
|
|
55
|
+
if (isLast) {
|
|
56
|
+
return theme.colors.text.primary;
|
|
57
|
+
}
|
|
58
|
+
if (clickable) {
|
|
59
|
+
return intent === 'primary' ? theme.intents.primary.primary : theme.colors.text.secondary;
|
|
60
|
+
}
|
|
61
|
+
return theme.colors.text.secondary;
|
|
66
62
|
}
|
|
67
63
|
|
|
68
64
|
/**
|
|
@@ -86,25 +82,16 @@ function getIconColor(theme: Theme, intent: BreadcrumbIntent) {
|
|
|
86
82
|
}
|
|
87
83
|
|
|
88
84
|
const createItemTextStyles = (theme: Theme) => {
|
|
89
|
-
return {
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
disabled:
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
color: theme.colors.text.secondary,
|
|
97
|
-
},
|
|
98
|
-
false: {},
|
|
99
|
-
},
|
|
100
|
-
isLast: {
|
|
101
|
-
true: { color: theme.colors.text.primary },
|
|
102
|
-
false: {},
|
|
85
|
+
return ({ intent = 'primary', isLast = false, disabled = false, clickable = true }: ItemTextDynamicProps) => {
|
|
86
|
+
const color = getItemTextColor(theme, intent, isLast, disabled, clickable);
|
|
87
|
+
return {
|
|
88
|
+
color,
|
|
89
|
+
opacity: disabled ? 0.5 : 1,
|
|
90
|
+
variants: {
|
|
91
|
+
size: createItemTextSizeVariants(theme),
|
|
103
92
|
},
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
compoundVariants: createItemTextCompoundVariants(theme),
|
|
107
|
-
} as const;
|
|
93
|
+
} as const;
|
|
94
|
+
};
|
|
108
95
|
}
|
|
109
96
|
|
|
110
97
|
const createIconStyles = (theme: Theme) => {
|
|
@@ -146,24 +133,38 @@ const createMenuButtonIconStyles = (theme: Theme) => {
|
|
|
146
133
|
}
|
|
147
134
|
}
|
|
148
135
|
|
|
136
|
+
// Style creators for extension support
|
|
137
|
+
function createContainerStyles() {
|
|
138
|
+
return () => ({
|
|
139
|
+
display: 'flex' as const,
|
|
140
|
+
flexDirection: 'row' as const,
|
|
141
|
+
alignItems: 'center' as const,
|
|
142
|
+
flexWrap: 'wrap' as const,
|
|
143
|
+
gap: 8,
|
|
144
|
+
});
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
function createItemStyles() {
|
|
148
|
+
return () => ({
|
|
149
|
+
display: 'flex' as const,
|
|
150
|
+
flexDirection: 'row' as const,
|
|
151
|
+
alignItems: 'center' as const,
|
|
152
|
+
gap: 4,
|
|
153
|
+
});
|
|
154
|
+
}
|
|
155
|
+
|
|
149
156
|
// Styles are inlined here instead of in @idealyst/theme because Unistyles' Babel transform on native cannot resolve function calls to extract variant structures.
|
|
150
|
-
// @ts-ignore - TS language server needs restart to pick up theme structure changes
|
|
151
157
|
export const breadcrumbStyles = StyleSheet.create((theme: Theme) => {
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
alignItems: 'center',
|
|
157
|
-
flexWrap: 'wrap',
|
|
158
|
-
gap: 8,
|
|
159
|
-
},
|
|
160
|
-
item: {
|
|
161
|
-
display: 'flex',
|
|
162
|
-
flexDirection: 'row',
|
|
163
|
-
alignItems: 'center',
|
|
164
|
-
gap: 4,
|
|
165
|
-
},
|
|
158
|
+
// Apply extensions to main visual elements
|
|
159
|
+
const extended = applyExtensions('Breadcrumb', theme, {
|
|
160
|
+
container: createContainerStyles(),
|
|
161
|
+
item: createItemStyles(),
|
|
166
162
|
itemText: createItemTextStyles(theme),
|
|
163
|
+
});
|
|
164
|
+
|
|
165
|
+
return {
|
|
166
|
+
...extended,
|
|
167
|
+
// Minor utility styles (not extended)
|
|
167
168
|
icon: createIconStyles(theme),
|
|
168
169
|
separator: createSeparatorStyles(theme),
|
|
169
170
|
ellipsis: {
|
|
@@ -22,17 +22,24 @@ interface BreadcrumbItemProps {
|
|
|
22
22
|
}
|
|
23
23
|
|
|
24
24
|
const BreadcrumbItem: React.FC<BreadcrumbItemProps> = ({ item, isLast, size, intent, itemStyle }) => {
|
|
25
|
-
|
|
25
|
+
const isClickable = !!item.onPress && !item.disabled;
|
|
26
|
+
const isDisabled = item.disabled || false;
|
|
27
|
+
|
|
28
|
+
// Apply size variant
|
|
26
29
|
breadcrumbItemStyles.useVariants({
|
|
27
30
|
size,
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
// Get dynamic item text style
|
|
34
|
+
const itemTextStyle = (breadcrumbItemStyles.itemText as any)({
|
|
28
35
|
intent,
|
|
29
|
-
disabled: item.disabled || false,
|
|
30
36
|
isLast,
|
|
31
|
-
|
|
37
|
+
disabled: isDisabled,
|
|
38
|
+
clickable: isClickable,
|
|
32
39
|
});
|
|
33
40
|
|
|
34
41
|
const itemProps = getWebProps([breadcrumbItemStyles.item]);
|
|
35
|
-
const itemTextProps = getWebProps([
|
|
42
|
+
const itemTextProps = getWebProps([itemTextStyle, itemStyle]);
|
|
36
43
|
const iconProps = getWebProps([breadcrumbItemStyles.icon]);
|
|
37
44
|
|
|
38
45
|
const handleClick = () => {
|
|
@@ -80,7 +87,7 @@ const BreadcrumbItem: React.FC<BreadcrumbItemProps> = ({ item, isLast, size, int
|
|
|
80
87
|
</div>
|
|
81
88
|
);
|
|
82
89
|
|
|
83
|
-
if (
|
|
90
|
+
if (isClickable) {
|
|
84
91
|
return (
|
|
85
92
|
<button
|
|
86
93
|
onClick={handleClick}
|
|
@@ -91,7 +98,7 @@ const BreadcrumbItem: React.FC<BreadcrumbItemProps> = ({ item, isLast, size, int
|
|
|
91
98
|
cursor: 'pointer',
|
|
92
99
|
textDecoration: 'none',
|
|
93
100
|
}}
|
|
94
|
-
disabled={
|
|
101
|
+
disabled={isDisabled}
|
|
95
102
|
aria-current={isLast ? 'page' : undefined}
|
|
96
103
|
>
|
|
97
104
|
{content}
|
|
@@ -34,29 +34,30 @@ const Button = forwardRef<ComponentRef<typeof TouchableOpacity>, ButtonProps>((p
|
|
|
34
34
|
accessibilityPressed,
|
|
35
35
|
} = props;
|
|
36
36
|
|
|
37
|
-
// Apply variants
|
|
37
|
+
// Apply variants for size, disabled, gradient
|
|
38
38
|
buttonStyles.useVariants({
|
|
39
|
-
type,
|
|
40
|
-
intent,
|
|
41
39
|
size,
|
|
42
40
|
disabled,
|
|
43
41
|
gradient,
|
|
44
42
|
});
|
|
45
43
|
|
|
46
|
-
// Compute dynamic styles
|
|
47
|
-
const
|
|
48
|
-
const
|
|
49
|
-
const
|
|
44
|
+
// Compute dynamic styles with all props for full flexibility
|
|
45
|
+
const dynamicProps = { intent, type, size, disabled, gradient };
|
|
46
|
+
const buttonStyle = (buttonStyles.button as any)(dynamicProps);
|
|
47
|
+
const textStyle = (buttonStyles.text as any)(dynamicProps);
|
|
48
|
+
const iconStyle = (buttonStyles.icon as any)(dynamicProps);
|
|
49
|
+
const iconContainerStyle = (buttonStyles.iconContainer as any)(dynamicProps);
|
|
50
50
|
|
|
51
51
|
// Gradient is only applicable to contained buttons
|
|
52
52
|
const showGradient = gradient && type === 'contained';
|
|
53
53
|
|
|
54
54
|
// Get gradient overlay colors (transparent to semi-transparent black/white)
|
|
55
|
+
// Note: Use explicit rgba(0,0,0,0) instead of 'transparent' for RN SVG compatibility
|
|
55
56
|
const getGradientColors = (): [string, string] => {
|
|
56
57
|
switch (gradient) {
|
|
57
|
-
case 'darken': return ['
|
|
58
|
-
case 'lighten': return ['
|
|
59
|
-
default: return ['
|
|
58
|
+
case 'darken': return ['rgba(0, 0, 0, 0)', 'rgba(0, 0, 0, 0.15)'];
|
|
59
|
+
case 'lighten': return ['rgba(255, 255, 255, 0)', 'rgba(255, 255, 255, 0.2)'];
|
|
60
|
+
default: return ['rgba(0, 0, 0, 0)', 'rgba(0, 0, 0, 0)'];
|
|
60
61
|
}
|
|
61
62
|
};
|
|
62
63
|
|
|
@@ -133,14 +134,38 @@ const Button = forwardRef<ComponentRef<typeof TouchableOpacity>, ButtonProps>((p
|
|
|
133
134
|
const renderGradientLayer = () => {
|
|
134
135
|
if (!showGradient) return null;
|
|
135
136
|
|
|
136
|
-
const [startColor, endColor] =
|
|
137
|
+
const [startColor, endColor] = useMemo(() => {
|
|
138
|
+
switch (gradient) {
|
|
139
|
+
case 'darken': return [{
|
|
140
|
+
stopColor: 'black',
|
|
141
|
+
stopOpacity: 0,
|
|
142
|
+
}, {
|
|
143
|
+
stopColor: 'black',
|
|
144
|
+
stopOpacity: 0.15,
|
|
145
|
+
}];
|
|
146
|
+
case 'lighten': return [{
|
|
147
|
+
stopColor: 'white',
|
|
148
|
+
stopOpacity: 0,
|
|
149
|
+
}, {
|
|
150
|
+
stopColor: 'white',
|
|
151
|
+
stopOpacity: 0.2,
|
|
152
|
+
}];
|
|
153
|
+
default: return [{
|
|
154
|
+
stopColor: 'black',
|
|
155
|
+
stopOpacity: 0,
|
|
156
|
+
}, {
|
|
157
|
+
stopColor: 'black',
|
|
158
|
+
stopOpacity: 0,
|
|
159
|
+
}];
|
|
160
|
+
}
|
|
161
|
+
}, [gradient]);
|
|
137
162
|
|
|
138
163
|
return (
|
|
139
164
|
<Svg style={RNStyleSheet.absoluteFill}>
|
|
140
165
|
<Defs>
|
|
141
166
|
<LinearGradient id="buttonGradient" x1="0%" y1="0%" x2="100%" y2="100%">
|
|
142
|
-
<Stop offset="0%"
|
|
143
|
-
<Stop offset="100%"
|
|
167
|
+
<Stop offset="0%" {...startColor} />
|
|
168
|
+
<Stop offset="100%" {...endColor} />
|
|
144
169
|
</LinearGradient>
|
|
145
170
|
</Defs>
|
|
146
171
|
<Rect
|
|
@@ -174,7 +199,7 @@ const Button = forwardRef<ComponentRef<typeof TouchableOpacity>, ButtonProps>((p
|
|
|
174
199
|
<TouchableOpacity {...touchableProps as any}>
|
|
175
200
|
{renderGradientLayer()}
|
|
176
201
|
{hasIcons ? (
|
|
177
|
-
<View style={
|
|
202
|
+
<View style={iconContainerStyle}>
|
|
178
203
|
{leftIcon && renderIcon(leftIcon)}
|
|
179
204
|
<Text style={textStyle}>
|
|
180
205
|
{buttonContent}
|