@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.
- package/package.json +8 -3
- package/src/Accordion/Accordion.native.tsx +22 -14
- package/src/Accordion/Accordion.styles.old.tsx +298 -0
- package/src/Accordion/Accordion.styles.tsx +139 -248
- package/src/Accordion/Accordion.web.tsx +12 -7
- package/src/ActivityIndicator/ActivityIndicator.native.tsx +3 -2
- package/src/ActivityIndicator/ActivityIndicator.styles.old.tsx +94 -0
- package/src/ActivityIndicator/ActivityIndicator.styles.tsx +43 -62
- package/src/ActivityIndicator/ActivityIndicator.web.tsx +2 -2
- package/src/Alert/Alert.native.tsx +26 -15
- package/src/Alert/Alert.styles.old.tsx +209 -0
- package/src/Alert/Alert.styles.tsx +108 -281
- package/src/Alert/Alert.web.tsx +6 -10
- package/src/Avatar/Avatar.native.tsx +5 -2
- package/src/Avatar/Avatar.styles.old.tsx +99 -0
- package/src/Avatar/Avatar.styles.tsx +47 -62
- package/src/Avatar/Avatar.web.tsx +2 -2
- package/src/Badge/Badge.native.tsx +2 -2
- package/src/Badge/Badge.styles.old.tsx +157 -0
- package/src/Badge/Badge.styles.tsx +69 -108
- package/src/Badge/Badge.web.tsx +6 -6
- package/src/Breadcrumb/Breadcrumb.native.tsx +12 -5
- package/src/Breadcrumb/Breadcrumb.styles.old.tsx +231 -0
- package/src/Breadcrumb/Breadcrumb.styles.tsx +93 -209
- package/src/Breadcrumb/Breadcrumb.web.tsx +39 -27
- package/src/Button/Button.native.tsx +39 -14
- package/src/Button/Button.styles.tsx +99 -253
- package/src/Button/Button.web.tsx +10 -8
- package/src/Card/Card.native.tsx +8 -4
- package/src/Card/Card.styles.old.tsx +160 -0
- package/src/Card/Card.styles.tsx +107 -142
- package/src/Card/Card.web.tsx +6 -4
- package/src/Checkbox/Checkbox.native.tsx +14 -6
- package/src/Checkbox/Checkbox.styles.old.tsx +271 -0
- package/src/Checkbox/Checkbox.styles.tsx +109 -197
- package/src/Checkbox/Checkbox.web.tsx +7 -7
- package/src/Chip/Chip.native.tsx +5 -5
- package/src/Chip/Chip.styles.old.tsx +184 -0
- package/src/Chip/Chip.styles.tsx +34 -22
- package/src/Chip/Chip.web.tsx +5 -5
- package/src/Dialog/Dialog.native.tsx +16 -7
- package/src/Dialog/Dialog.styles.old.tsx +202 -0
- package/src/Dialog/Dialog.styles.tsx +108 -132
- package/src/Dialog/Dialog.web.tsx +4 -4
- package/src/Divider/Divider.native.tsx +29 -42
- package/src/Divider/Divider.styles.old.tsx +172 -0
- package/src/Divider/Divider.styles.tsx +116 -242
- package/src/Divider/Divider.web.tsx +17 -14
- package/src/Icon/Icon.native.tsx +12 -4
- package/src/Icon/Icon.styles.old.tsx +81 -0
- package/src/Icon/Icon.styles.tsx +52 -60
- package/src/Icon/Icon.web.tsx +43 -7
- package/src/Icon/IconSvg/IconSvg.web.tsx +2 -0
- package/src/Image/Image.styles.old.tsx +69 -0
- package/src/Image/Image.styles.tsx +45 -43
- package/src/Input/Input.native.tsx +140 -56
- package/src/Input/Input.styles.old.tsx +289 -0
- package/src/Input/Input.styles.tsx +177 -228
- package/src/Input/Input.web.tsx +5 -8
- package/src/Link/Link.native.tsx +4 -1
- package/src/List/List.native.tsx +5 -2
- package/src/List/List.styles.old.tsx +242 -0
- package/src/List/List.styles.tsx +178 -240
- package/src/List/ListItem.native.tsx +16 -8
- package/src/List/ListItem.web.tsx +26 -15
- package/src/Menu/Menu.native.tsx +1 -1
- package/src/Menu/Menu.styles.old.tsx +197 -0
- package/src/Menu/Menu.styles.tsx +90 -156
- package/src/Menu/Menu.web.tsx +2 -2
- package/src/Menu/MenuItem.native.tsx +9 -5
- package/src/Menu/MenuItem.styles.old.tsx +114 -0
- package/src/Menu/MenuItem.styles.tsx +71 -104
- package/src/Menu/MenuItem.web.tsx +23 -5
- package/src/Popover/Popover.native.tsx +10 -4
- package/src/Popover/Popover.styles.old.tsx +135 -0
- package/src/Popover/Popover.styles.tsx +46 -96
- package/src/Popover/Popover.web.tsx +1 -1
- package/src/Pressable/Pressable.native.tsx +3 -1
- package/src/Pressable/Pressable.styles.old.tsx +27 -0
- package/src/Pressable/Pressable.styles.tsx +35 -20
- package/src/Pressable/Pressable.web.tsx +1 -1
- package/src/Progress/Progress.native.tsx +15 -6
- package/src/Progress/Progress.styles.old.tsx +200 -0
- package/src/Progress/Progress.styles.tsx +69 -118
- package/src/Progress/Progress.web.tsx +10 -9
- package/src/RadioButton/RadioButton.native.tsx +10 -4
- package/src/RadioButton/RadioButton.styles.old.tsx +175 -0
- package/src/RadioButton/RadioButton.styles.tsx +81 -145
- package/src/RadioButton/RadioButton.web.tsx +4 -4
- package/src/SVGImage/SVGImage.styles.old.tsx +86 -0
- package/src/SVGImage/SVGImage.styles.tsx +35 -66
- package/src/Screen/Screen.native.tsx +30 -27
- package/src/Screen/Screen.styles.old.tsx +87 -0
- package/src/Screen/Screen.styles.tsx +120 -71
- package/src/Screen/Screen.web.tsx +2 -2
- package/src/Select/Select.native.tsx +44 -29
- package/src/Select/Select.styles.old.tsx +353 -0
- package/src/Select/Select.styles.tsx +244 -293
- package/src/Select/Select.web.tsx +5 -5
- package/src/Skeleton/Skeleton.styles.old.tsx +67 -0
- package/src/Skeleton/Skeleton.styles.tsx +31 -43
- package/src/Slider/Slider.native.tsx +9 -5
- package/src/Slider/Slider.styles.old.tsx +259 -0
- package/src/Slider/Slider.styles.tsx +157 -227
- package/src/Slider/Slider.web.tsx +5 -5
- package/src/Switch/Switch.native.tsx +11 -5
- package/src/Switch/Switch.styles.old.tsx +203 -0
- package/src/Switch/Switch.styles.tsx +103 -149
- package/src/Switch/Switch.web.tsx +8 -8
- package/src/TabBar/TabBar.native.tsx +24 -31
- package/src/TabBar/TabBar.styles.old.tsx +343 -0
- package/src/TabBar/TabBar.styles.tsx +204 -494
- package/src/TabBar/TabBar.web.tsx +21 -33
- package/src/Table/Table.native.tsx +18 -9
- package/src/Table/Table.styles.old.tsx +311 -0
- package/src/Table/Table.styles.tsx +151 -278
- package/src/Table/Table.web.tsx +1 -1
- package/src/Text/Text.native.tsx +1 -4
- package/src/Text/Text.style.demo.tsx +16 -0
- package/src/Text/Text.styles.old.tsx +219 -0
- package/src/Text/Text.styles.tsx +94 -78
- package/src/Text/Text.web.tsx +2 -2
- package/src/Text/index.ts +1 -0
- package/src/TextArea/TextArea.styles.old.tsx +213 -0
- package/src/TextArea/TextArea.styles.tsx +101 -157
- package/src/Tooltip/Tooltip.native.tsx +2 -2
- package/src/Tooltip/Tooltip.styles.old.tsx +82 -0
- package/src/Tooltip/Tooltip.styles.tsx +38 -53
- package/src/Tooltip/Tooltip.web.tsx +2 -2
- package/src/Video/Video.styles.old.tsx +51 -0
- package/src/Video/Video.styles.tsx +32 -28
- package/src/View/View.native.tsx +12 -12
- package/src/View/View.styles.old.tsx +125 -0
- package/src/View/View.styles.tsx +84 -103
- package/src/View/View.web.tsx +14 -2
- package/src/examples/CardExamples.tsx +0 -6
- package/src/extensions/applyExtension.ts +210 -0
- package/src/extensions/extendComponent.ts +438 -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
|
@@ -0,0 +1,197 @@
|
|
|
1
|
+
import { StyleSheet } from 'react-native-unistyles';
|
|
2
|
+
import { Theme, StylesheetStyles, CompoundVariants, Intent, Size } from '@idealyst/theme';
|
|
3
|
+
import { buildSizeVariants } from '../utils/buildSizeVariants';
|
|
4
|
+
import { applyExtensions } from '../extensions/applyExtension';
|
|
5
|
+
|
|
6
|
+
type MenuSize = Size;
|
|
7
|
+
type MenuIntent = Intent;
|
|
8
|
+
|
|
9
|
+
type MenuVariants = {
|
|
10
|
+
size: MenuSize;
|
|
11
|
+
intent: MenuIntent;
|
|
12
|
+
disabled: boolean;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export type ExpandedMenuStyles = StylesheetStyles<keyof MenuVariants>;
|
|
16
|
+
|
|
17
|
+
export type MenuStylesheet = {
|
|
18
|
+
overlay: ExpandedMenuStyles;
|
|
19
|
+
menu: ExpandedMenuStyles;
|
|
20
|
+
separator: ExpandedMenuStyles;
|
|
21
|
+
item: ExpandedMenuStyles;
|
|
22
|
+
icon: ExpandedMenuStyles;
|
|
23
|
+
label: ExpandedMenuStyles;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Create size variants for menu item
|
|
28
|
+
*/
|
|
29
|
+
function createItemSizeVariants(theme: Theme) {
|
|
30
|
+
return buildSizeVariants(theme, 'menu', (size) => ({
|
|
31
|
+
paddingVertical: size.paddingVertical,
|
|
32
|
+
paddingHorizontal: size.paddingHorizontal,
|
|
33
|
+
}));
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* Get hover styles for menu item based on intent
|
|
38
|
+
*/
|
|
39
|
+
function getItemHoverStyles(theme: Theme, intent: MenuIntent) {
|
|
40
|
+
if (intent === 'neutral') {
|
|
41
|
+
return {};
|
|
42
|
+
}
|
|
43
|
+
const intentValue = theme.intents[intent];
|
|
44
|
+
return {
|
|
45
|
+
_web: {
|
|
46
|
+
_hover: {
|
|
47
|
+
backgroundColor: intentValue.light + '20',
|
|
48
|
+
color: intentValue.primary,
|
|
49
|
+
},
|
|
50
|
+
},
|
|
51
|
+
} as const;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* Create compound variants for menu item
|
|
56
|
+
*/
|
|
57
|
+
function createItemCompoundVariants(theme: Theme): CompoundVariants<keyof MenuVariants> {
|
|
58
|
+
return [
|
|
59
|
+
{
|
|
60
|
+
disabled: true,
|
|
61
|
+
styles: {
|
|
62
|
+
_web: {
|
|
63
|
+
_hover: {
|
|
64
|
+
backgroundColor: 'transparent',
|
|
65
|
+
},
|
|
66
|
+
},
|
|
67
|
+
},
|
|
68
|
+
},
|
|
69
|
+
] as const;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* Create size variants for icon
|
|
74
|
+
*/
|
|
75
|
+
function createIconSizeVariants(theme: Theme) {
|
|
76
|
+
return buildSizeVariants(theme, 'menu', (size) => ({
|
|
77
|
+
width: size.iconSize,
|
|
78
|
+
height: size.iconSize,
|
|
79
|
+
fontSize: size.iconSize,
|
|
80
|
+
}));
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
/**
|
|
84
|
+
* Create size variants for label
|
|
85
|
+
*/
|
|
86
|
+
function createLabelSizeVariants(theme: Theme) {
|
|
87
|
+
return buildSizeVariants(theme, 'menu', (size) => ({
|
|
88
|
+
fontSize: size.labelFontSize,
|
|
89
|
+
}));
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
// Main element style creators (for extension support)
|
|
93
|
+
function createOverlayStyles(theme: Theme) {
|
|
94
|
+
return () => ({
|
|
95
|
+
backgroundColor: 'transparent',
|
|
96
|
+
_web: {
|
|
97
|
+
position: 'fixed' as const,
|
|
98
|
+
top: 0,
|
|
99
|
+
left: 0,
|
|
100
|
+
right: 0,
|
|
101
|
+
bottom: 0,
|
|
102
|
+
zIndex: 999,
|
|
103
|
+
},
|
|
104
|
+
});
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
function createMenuStyles(theme: Theme) {
|
|
108
|
+
return () => ({
|
|
109
|
+
position: 'absolute' as const,
|
|
110
|
+
zIndex: 1000,
|
|
111
|
+
backgroundColor: theme.colors.surface.primary,
|
|
112
|
+
borderWidth: 1,
|
|
113
|
+
borderStyle: 'solid' as const,
|
|
114
|
+
borderColor: theme.colors.border.primary,
|
|
115
|
+
borderRadius: 8,
|
|
116
|
+
minWidth: 120,
|
|
117
|
+
maxWidth: 400,
|
|
118
|
+
padding: 4,
|
|
119
|
+
display: 'flex' as const,
|
|
120
|
+
flexDirection: 'column' as const,
|
|
121
|
+
_web: {
|
|
122
|
+
border: `1px solid ${theme.colors.border.primary}`,
|
|
123
|
+
boxShadow: '0 4px 12px rgba(0, 0, 0, 0.15)',
|
|
124
|
+
width: 'fit-content',
|
|
125
|
+
},
|
|
126
|
+
});
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
function createItemStyles(theme: Theme) {
|
|
130
|
+
return ({ intent }: Partial<MenuVariants>) => {
|
|
131
|
+
const hoverStyles = getItemHoverStyles(theme, intent ?? 'neutral');
|
|
132
|
+
return {
|
|
133
|
+
flexDirection: 'row',
|
|
134
|
+
alignItems: 'center',
|
|
135
|
+
backgroundColor: 'transparent',
|
|
136
|
+
borderRadius: 4,
|
|
137
|
+
minHeight: 44,
|
|
138
|
+
variants: {
|
|
139
|
+
size: createItemSizeVariants(theme),
|
|
140
|
+
disabled: {
|
|
141
|
+
true: {
|
|
142
|
+
opacity: 0.5,
|
|
143
|
+
_web: {
|
|
144
|
+
cursor: 'not-allowed',
|
|
145
|
+
},
|
|
146
|
+
},
|
|
147
|
+
false: {},
|
|
148
|
+
},
|
|
149
|
+
},
|
|
150
|
+
compoundVariants: createItemCompoundVariants(theme),
|
|
151
|
+
_web: {
|
|
152
|
+
cursor: 'pointer',
|
|
153
|
+
border: 'none',
|
|
154
|
+
outline: 'none',
|
|
155
|
+
transition: 'background-color 0.2s ease',
|
|
156
|
+
textAlign: 'left',
|
|
157
|
+
_hover: {
|
|
158
|
+
backgroundColor: theme.colors.surface.secondary,
|
|
159
|
+
},
|
|
160
|
+
},
|
|
161
|
+
...hoverStyles,
|
|
162
|
+
} as const;
|
|
163
|
+
};
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
// Styles are inlined here instead of in @idealyst/theme because Unistyles' Babel transform on native cannot resolve function calls to extract variant structures.
|
|
167
|
+
export const menuStyles = StyleSheet.create((theme: Theme) => {
|
|
168
|
+
// Apply extensions to main visual elements
|
|
169
|
+
|
|
170
|
+
return applyExtensions('Menu', theme, {overlay: createOverlayStyles(theme),
|
|
171
|
+
menu: createMenuStyles(theme),
|
|
172
|
+
item: createItemStyles(theme),
|
|
173
|
+
// Additional styles (merged from return)
|
|
174
|
+
// Minor utility styles (not extended)
|
|
175
|
+
separator: {
|
|
176
|
+
height: 1,
|
|
177
|
+
backgroundColor: theme.colors.border.primary,
|
|
178
|
+
marginTop: 4,
|
|
179
|
+
marginBottom: 4,
|
|
180
|
+
},
|
|
181
|
+
icon: {
|
|
182
|
+
alignItems: 'center',
|
|
183
|
+
justifyContent: 'center',
|
|
184
|
+
flexShrink: 0,
|
|
185
|
+
marginRight: 8,
|
|
186
|
+
variants: {
|
|
187
|
+
size: createIconSizeVariants(theme),
|
|
188
|
+
} as const,
|
|
189
|
+
} as const,
|
|
190
|
+
label: {
|
|
191
|
+
flex: 1,
|
|
192
|
+
color: theme.colors.text.primary,
|
|
193
|
+
variants: {
|
|
194
|
+
size: createLabelSizeVariants(theme),
|
|
195
|
+
} as const,
|
|
196
|
+
} as const});
|
|
197
|
+
});
|
package/src/Menu/Menu.styles.tsx
CHANGED
|
@@ -1,185 +1,119 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Menu styles using defineStyle with dynamic props.
|
|
3
|
+
*/
|
|
1
4
|
import { StyleSheet } from 'react-native-unistyles';
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
5
|
+
import { defineStyle, ThemeStyleWrapper } from '@idealyst/theme';
|
|
6
|
+
import type { Theme as BaseTheme, Intent, Size } from '@idealyst/theme';
|
|
4
7
|
|
|
5
|
-
|
|
6
|
-
|
|
8
|
+
// Required: Unistyles must see StyleSheet usage in original source to process this file
|
|
9
|
+
void StyleSheet;
|
|
7
10
|
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
intent: MenuIntent;
|
|
11
|
-
disabled: boolean;
|
|
12
|
-
}
|
|
11
|
+
// Wrap theme for $iterator support
|
|
12
|
+
type Theme = ThemeStyleWrapper<BaseTheme>;
|
|
13
13
|
|
|
14
|
-
export type
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
separator: ExpandedMenuStyles;
|
|
20
|
-
item: ExpandedMenuStyles;
|
|
21
|
-
icon: ExpandedMenuStyles;
|
|
22
|
-
label: ExpandedMenuStyles;
|
|
23
|
-
}
|
|
14
|
+
export type MenuDynamicProps = {
|
|
15
|
+
size?: Size;
|
|
16
|
+
intent?: Intent;
|
|
17
|
+
disabled?: boolean;
|
|
18
|
+
};
|
|
24
19
|
|
|
25
20
|
/**
|
|
26
|
-
*
|
|
21
|
+
* Menu styles with intent/disabled handling.
|
|
27
22
|
*/
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
paddingHorizontal: size.paddingHorizontal,
|
|
32
|
-
}));
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
/**
|
|
36
|
-
* Get hover styles for menu item based on intent
|
|
37
|
-
*/
|
|
38
|
-
function getItemHoverStyles(theme: Theme, intent: MenuIntent) {
|
|
39
|
-
if (intent === 'neutral') {
|
|
40
|
-
return {};
|
|
41
|
-
}
|
|
42
|
-
const intentValue = theme.intents[intent];
|
|
43
|
-
return {
|
|
23
|
+
export const menuStyles = defineStyle('Menu', (theme: Theme) => ({
|
|
24
|
+
overlay: (_props: MenuDynamicProps) => ({
|
|
25
|
+
backgroundColor: 'transparent' as const,
|
|
44
26
|
_web: {
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
27
|
+
position: 'fixed' as const,
|
|
28
|
+
top: 0,
|
|
29
|
+
left: 0,
|
|
30
|
+
right: 0,
|
|
31
|
+
bottom: 0,
|
|
32
|
+
zIndex: 999,
|
|
49
33
|
},
|
|
50
|
-
}
|
|
51
|
-
}
|
|
34
|
+
}),
|
|
52
35
|
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
36
|
+
menu: (_props: MenuDynamicProps) => ({
|
|
37
|
+
position: 'absolute' as const,
|
|
38
|
+
zIndex: 1000,
|
|
39
|
+
backgroundColor: theme.colors.surface.primary,
|
|
40
|
+
borderWidth: 1,
|
|
41
|
+
borderStyle: 'solid' as const,
|
|
42
|
+
borderColor: theme.colors.border.primary,
|
|
43
|
+
borderRadius: 8,
|
|
44
|
+
minWidth: 120,
|
|
45
|
+
maxWidth: 400,
|
|
46
|
+
padding: 4,
|
|
47
|
+
display: 'flex' as const,
|
|
48
|
+
flexDirection: 'column' as const,
|
|
49
|
+
_web: {
|
|
50
|
+
border: `1px solid ${theme.colors.border.primary}`,
|
|
51
|
+
boxShadow: '0 4px 12px rgba(0, 0, 0, 0.15)',
|
|
52
|
+
width: 'fit-content',
|
|
67
53
|
},
|
|
68
|
-
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
/**
|
|
72
|
-
* Create size variants for icon
|
|
73
|
-
*/
|
|
74
|
-
function createIconSizeVariants(theme: Theme) {
|
|
75
|
-
return buildSizeVariants(theme, 'menu', (size) => ({
|
|
76
|
-
width: size.iconSize,
|
|
77
|
-
height: size.iconSize,
|
|
78
|
-
fontSize: size.iconSize,
|
|
79
|
-
}));
|
|
80
|
-
}
|
|
54
|
+
}),
|
|
81
55
|
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
}
|
|
56
|
+
item: ({ intent = 'neutral', disabled = false }: MenuDynamicProps) => {
|
|
57
|
+
const intentValue = theme.intents[intent];
|
|
58
|
+
const hoverStyles = intent !== 'neutral' ? {
|
|
59
|
+
backgroundColor: intentValue.light + '20',
|
|
60
|
+
color: intentValue.primary,
|
|
61
|
+
} : {
|
|
62
|
+
backgroundColor: theme.colors.surface.secondary,
|
|
63
|
+
};
|
|
90
64
|
|
|
91
|
-
const createItemStyles = (theme: Theme) => {
|
|
92
|
-
return ({ intent }: MenuVariants) => {
|
|
93
|
-
const hoverStyles = getItemHoverStyles(theme, intent);
|
|
94
65
|
return {
|
|
95
|
-
flexDirection: 'row',
|
|
96
|
-
alignItems: 'center',
|
|
97
|
-
backgroundColor: 'transparent',
|
|
66
|
+
flexDirection: 'row' as const,
|
|
67
|
+
alignItems: 'center' as const,
|
|
68
|
+
backgroundColor: 'transparent' as const,
|
|
98
69
|
borderRadius: 4,
|
|
99
70
|
minHeight: 44,
|
|
71
|
+
opacity: disabled ? 0.5 : 1,
|
|
100
72
|
variants: {
|
|
101
|
-
size:
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
opacity: 0.5,
|
|
105
|
-
_web: {
|
|
106
|
-
cursor: 'not-allowed',
|
|
107
|
-
},
|
|
108
|
-
},
|
|
109
|
-
false: {},
|
|
73
|
+
size: {
|
|
74
|
+
paddingVertical: theme.sizes.$menu.paddingVertical,
|
|
75
|
+
paddingHorizontal: theme.sizes.$menu.paddingHorizontal,
|
|
110
76
|
},
|
|
111
77
|
},
|
|
112
|
-
compoundVariants: createItemCompoundVariants(theme),
|
|
113
78
|
_web: {
|
|
114
|
-
cursor: 'pointer',
|
|
79
|
+
cursor: disabled ? 'not-allowed' : 'pointer',
|
|
115
80
|
border: 'none',
|
|
116
81
|
outline: 'none',
|
|
117
82
|
transition: 'background-color 0.2s ease',
|
|
118
83
|
textAlign: 'left',
|
|
119
|
-
_hover: {
|
|
120
|
-
backgroundColor: theme.colors.surface.secondary,
|
|
121
|
-
},
|
|
84
|
+
_hover: disabled ? { backgroundColor: 'transparent' } : hoverStyles,
|
|
122
85
|
},
|
|
123
|
-
...hoverStyles,
|
|
124
86
|
} as const;
|
|
125
|
-
}
|
|
126
|
-
}
|
|
87
|
+
},
|
|
127
88
|
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
backgroundColor: theme.colors.surface.primary,
|
|
146
|
-
borderWidth: 1,
|
|
147
|
-
borderStyle: 'solid',
|
|
148
|
-
borderColor: theme.colors.border.primary,
|
|
149
|
-
borderRadius: 8,
|
|
150
|
-
minWidth: 120,
|
|
151
|
-
maxWidth: 400,
|
|
152
|
-
padding: 4,
|
|
153
|
-
display: 'flex',
|
|
154
|
-
flexDirection: 'column',
|
|
155
|
-
_web: {
|
|
156
|
-
border: `1px solid ${theme.colors.border.primary}`,
|
|
157
|
-
boxShadow: '0 4px 12px rgba(0, 0, 0, 0.15)',
|
|
158
|
-
width: 'fit-content',
|
|
89
|
+
separator: (_props: MenuDynamicProps) => ({
|
|
90
|
+
height: 1,
|
|
91
|
+
backgroundColor: theme.colors.border.primary,
|
|
92
|
+
marginTop: 4,
|
|
93
|
+
marginBottom: 4,
|
|
94
|
+
}),
|
|
95
|
+
|
|
96
|
+
icon: (_props: MenuDynamicProps) => ({
|
|
97
|
+
alignItems: 'center' as const,
|
|
98
|
+
justifyContent: 'center' as const,
|
|
99
|
+
flexShrink: 0,
|
|
100
|
+
marginRight: 8,
|
|
101
|
+
variants: {
|
|
102
|
+
size: {
|
|
103
|
+
width: theme.sizes.$menu.iconSize,
|
|
104
|
+
height: theme.sizes.$menu.iconSize,
|
|
105
|
+
fontSize: theme.sizes.$menu.iconSize,
|
|
159
106
|
},
|
|
160
|
-
} as const,
|
|
161
|
-
separator: {
|
|
162
|
-
height: 1,
|
|
163
|
-
backgroundColor: theme.colors.border.primary,
|
|
164
|
-
marginTop: 4,
|
|
165
|
-
marginBottom: 4,
|
|
166
107
|
},
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
}
|
|
176
|
-
}
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
color: theme.colors.text.primary,
|
|
180
|
-
variants: {
|
|
181
|
-
size: createLabelSizeVariants(theme),
|
|
182
|
-
} as const,
|
|
183
|
-
} as const,
|
|
184
|
-
} as const;
|
|
185
|
-
});
|
|
108
|
+
}),
|
|
109
|
+
|
|
110
|
+
label: (_props: MenuDynamicProps) => ({
|
|
111
|
+
flex: 1,
|
|
112
|
+
color: theme.colors.text.primary,
|
|
113
|
+
variants: {
|
|
114
|
+
size: {
|
|
115
|
+
fontSize: theme.sizes.$menu.labelFontSize,
|
|
116
|
+
},
|
|
117
|
+
},
|
|
118
|
+
}),
|
|
119
|
+
}));
|
package/src/Menu/Menu.web.tsx
CHANGED
|
@@ -113,8 +113,8 @@ const Menu = forwardRef<HTMLDivElement, MenuProps>(({
|
|
|
113
113
|
size,
|
|
114
114
|
});
|
|
115
115
|
|
|
116
|
-
const overlayProps = getWebProps([menuStyles.overlay]);
|
|
117
|
-
const menuProps = getWebProps([menuStyles.menu, style as any]);
|
|
116
|
+
const overlayProps = getWebProps([(menuStyles.overlay as any)({})]);
|
|
117
|
+
const menuProps = getWebProps([(menuStyles.menu as any)({}), style as any]);
|
|
118
118
|
const separatorProps = getWebProps([menuStyles.separator]);
|
|
119
119
|
|
|
120
120
|
const handleTriggerClick = () => {
|
|
@@ -13,13 +13,17 @@ interface MenuItemProps {
|
|
|
13
13
|
}
|
|
14
14
|
|
|
15
15
|
const MenuItem = forwardRef<ComponentRef<typeof Pressable>, MenuItemProps>(({ item, onPress, size = 'md', testID }, ref) => {
|
|
16
|
-
// Initialize styles with useVariants
|
|
16
|
+
// Initialize styles with useVariants (for size and disabled)
|
|
17
17
|
menuItemStyles.useVariants({
|
|
18
18
|
size,
|
|
19
19
|
disabled: Boolean(item.disabled),
|
|
20
|
-
intent: item.intent || 'neutral',
|
|
21
20
|
});
|
|
22
21
|
|
|
22
|
+
// Call styles as functions to get theme-reactive styles
|
|
23
|
+
const itemStyle = (menuItemStyles.item as any)({ intent: item.intent || 'neutral' });
|
|
24
|
+
const iconStyle = (menuItemStyles.icon as any)({});
|
|
25
|
+
const labelStyle = (menuItemStyles.label as any)({});
|
|
26
|
+
|
|
23
27
|
const renderIcon = () => {
|
|
24
28
|
if (!item.icon) return null;
|
|
25
29
|
|
|
@@ -27,7 +31,7 @@ const MenuItem = forwardRef<ComponentRef<typeof Pressable>, MenuItemProps>(({ it
|
|
|
27
31
|
return (
|
|
28
32
|
<MaterialDesignIcons
|
|
29
33
|
name={item.icon as any}
|
|
30
|
-
style={
|
|
34
|
+
style={iconStyle}
|
|
31
35
|
/>
|
|
32
36
|
);
|
|
33
37
|
} else if (isValidElement(item.icon)) {
|
|
@@ -39,7 +43,7 @@ const MenuItem = forwardRef<ComponentRef<typeof Pressable>, MenuItemProps>(({ it
|
|
|
39
43
|
return (
|
|
40
44
|
<Pressable
|
|
41
45
|
ref={ref}
|
|
42
|
-
style={
|
|
46
|
+
style={itemStyle}
|
|
43
47
|
onPress={() => onPress(item)}
|
|
44
48
|
disabled={item.disabled}
|
|
45
49
|
accessibilityRole="menuitem"
|
|
@@ -54,7 +58,7 @@ const MenuItem = forwardRef<ComponentRef<typeof Pressable>, MenuItemProps>(({ it
|
|
|
54
58
|
{renderIcon()}
|
|
55
59
|
</View>
|
|
56
60
|
)}
|
|
57
|
-
<Text style={
|
|
61
|
+
<Text style={labelStyle}>
|
|
58
62
|
{item.label}
|
|
59
63
|
</Text>
|
|
60
64
|
</Pressable>
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
import { StyleSheet } from 'react-native-unistyles';
|
|
2
|
+
import { Theme, Intent } from '@idealyst/theme';
|
|
3
|
+
import { buildSizeVariants } from '../utils/buildSizeVariants';
|
|
4
|
+
import { applyExtensions } from '../extensions/applyExtension';
|
|
5
|
+
|
|
6
|
+
type MenuItemDynamicProps = {
|
|
7
|
+
intent?: Intent;
|
|
8
|
+
};
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Get hover styles for menu item based on intent
|
|
12
|
+
*/
|
|
13
|
+
function getItemHoverStyles(theme: Theme, intent: Intent) {
|
|
14
|
+
if (intent === 'neutral') {
|
|
15
|
+
return {
|
|
16
|
+
_web: {
|
|
17
|
+
_hover: {
|
|
18
|
+
backgroundColor: theme.colors.surface.secondary,
|
|
19
|
+
},
|
|
20
|
+
},
|
|
21
|
+
} as const;
|
|
22
|
+
}
|
|
23
|
+
const intentValue = theme.intents[intent];
|
|
24
|
+
return {
|
|
25
|
+
_web: {
|
|
26
|
+
_hover: {
|
|
27
|
+
backgroundColor: intentValue.light,
|
|
28
|
+
color: intentValue.primary,
|
|
29
|
+
},
|
|
30
|
+
},
|
|
31
|
+
} as const;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Create dynamic item styles
|
|
36
|
+
*/
|
|
37
|
+
function createItemStyles(theme: Theme) {
|
|
38
|
+
return ({ intent = 'neutral' }: MenuItemDynamicProps) => {
|
|
39
|
+
const hoverStyles = getItemHoverStyles(theme, intent);
|
|
40
|
+
return {
|
|
41
|
+
flexDirection: 'row',
|
|
42
|
+
alignItems: 'center',
|
|
43
|
+
backgroundColor: 'transparent',
|
|
44
|
+
borderRadius: 4,
|
|
45
|
+
minHeight: 44,
|
|
46
|
+
variants: {
|
|
47
|
+
size: buildSizeVariants(theme, 'menu', (size) => ({
|
|
48
|
+
paddingVertical: size.paddingVertical,
|
|
49
|
+
paddingHorizontal: size.paddingHorizontal,
|
|
50
|
+
})),
|
|
51
|
+
disabled: {
|
|
52
|
+
true: {
|
|
53
|
+
opacity: 0.5,
|
|
54
|
+
_web: {
|
|
55
|
+
cursor: 'not-allowed',
|
|
56
|
+
_hover: {
|
|
57
|
+
backgroundColor: 'transparent',
|
|
58
|
+
},
|
|
59
|
+
},
|
|
60
|
+
},
|
|
61
|
+
false: {},
|
|
62
|
+
},
|
|
63
|
+
},
|
|
64
|
+
_web: {
|
|
65
|
+
display: 'flex',
|
|
66
|
+
width: '100%',
|
|
67
|
+
cursor: 'pointer',
|
|
68
|
+
border: 'none',
|
|
69
|
+
borderWidth: 0,
|
|
70
|
+
outline: 'none',
|
|
71
|
+
transition: 'background-color 0.2s ease',
|
|
72
|
+
textAlign: 'left',
|
|
73
|
+
_hover: {
|
|
74
|
+
backgroundColor: theme.colors.surface.secondary,
|
|
75
|
+
},
|
|
76
|
+
},
|
|
77
|
+
...hoverStyles,
|
|
78
|
+
} as const;
|
|
79
|
+
};
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
// Styles are inlined here instead of in @idealyst/theme because Unistyles' Babel transform on native cannot resolve function calls to extract variant structures.
|
|
83
|
+
export const menuItemStyles = StyleSheet.create((theme: Theme) => {
|
|
84
|
+
// Apply extensions to main visual elements
|
|
85
|
+
|
|
86
|
+
return applyExtensions('MenuItem', theme, {item: createItemStyles(theme),
|
|
87
|
+
// Additional styles (merged from return)
|
|
88
|
+
// Minor utility styles (not extended)
|
|
89
|
+
icon: {
|
|
90
|
+
alignItems: 'center',
|
|
91
|
+
justifyContent: 'center',
|
|
92
|
+
flexShrink: 0,
|
|
93
|
+
marginRight: 12,
|
|
94
|
+
variants: {
|
|
95
|
+
size: buildSizeVariants(theme, 'menu', (size) => ({
|
|
96
|
+
width: size.iconSize,
|
|
97
|
+
height: size.iconSize,
|
|
98
|
+
fontSize: size.iconSize,
|
|
99
|
+
}))
|
|
100
|
+
},
|
|
101
|
+
_web: {
|
|
102
|
+
display: 'flex',
|
|
103
|
+
},
|
|
104
|
+
},
|
|
105
|
+
label: {
|
|
106
|
+
flex: 1,
|
|
107
|
+
color: theme.colors.text.primary,
|
|
108
|
+
variants: {
|
|
109
|
+
size: buildSizeVariants(theme, 'menu', (size) => ({
|
|
110
|
+
fontSize: size.labelFontSize,
|
|
111
|
+
})),
|
|
112
|
+
},
|
|
113
|
+
}});
|
|
114
|
+
});
|