@idealyst/components 1.1.7 → 1.1.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (105) hide show
  1. package/package.json +3 -3
  2. package/src/Accordion/Accordion.native.tsx +8 -6
  3. package/src/Accordion/Accordion.styles.old.tsx +298 -0
  4. package/src/Accordion/Accordion.styles.tsx +102 -236
  5. package/src/ActivityIndicator/ActivityIndicator.styles.old.tsx +94 -0
  6. package/src/ActivityIndicator/ActivityIndicator.styles.tsx +44 -74
  7. package/src/Alert/Alert.native.tsx +16 -6
  8. package/src/Alert/Alert.styles.old.tsx +209 -0
  9. package/src/Alert/Alert.styles.tsx +67 -149
  10. package/src/Avatar/Avatar.styles.old.tsx +99 -0
  11. package/src/Avatar/Avatar.styles.tsx +35 -80
  12. package/src/Badge/Badge.styles.old.tsx +157 -0
  13. package/src/Badge/Badge.styles.tsx +61 -121
  14. package/src/Breadcrumb/Breadcrumb.styles.old.tsx +231 -0
  15. package/src/Breadcrumb/Breadcrumb.styles.tsx +83 -200
  16. package/src/Breadcrumb/Breadcrumb.web.tsx +28 -23
  17. package/src/Button/Button.styles.tsx +89 -141
  18. package/src/Card/Card.native.tsx +7 -11
  19. package/src/Card/Card.styles.old.tsx +160 -0
  20. package/src/Card/Card.styles.tsx +105 -142
  21. package/src/Card/Card.web.tsx +5 -4
  22. package/src/Checkbox/Checkbox.native.tsx +9 -5
  23. package/src/Checkbox/Checkbox.styles.old.tsx +271 -0
  24. package/src/Checkbox/Checkbox.styles.tsx +104 -216
  25. package/src/Checkbox/Checkbox.web.tsx +6 -6
  26. package/src/Chip/Chip.styles.old.tsx +184 -0
  27. package/src/Chip/Chip.styles.tsx +34 -72
  28. package/src/Dialog/Dialog.native.tsx +7 -4
  29. package/src/Dialog/Dialog.styles.old.tsx +202 -0
  30. package/src/Dialog/Dialog.styles.tsx +69 -133
  31. package/src/Divider/Divider.styles.old.tsx +172 -0
  32. package/src/Divider/Divider.styles.tsx +62 -84
  33. package/src/Icon/Icon.native.tsx +8 -8
  34. package/src/Icon/Icon.styles.old.tsx +81 -0
  35. package/src/Icon/Icon.styles.tsx +52 -66
  36. package/src/Icon/Icon.web.tsx +43 -7
  37. package/src/Icon/IconSvg/IconSvg.web.tsx +2 -0
  38. package/src/Image/Image.styles.old.tsx +69 -0
  39. package/src/Image/Image.styles.tsx +46 -60
  40. package/src/Input/Input.native.tsx +138 -53
  41. package/src/Input/Input.styles.old.tsx +289 -0
  42. package/src/Input/Input.styles.tsx +127 -198
  43. package/src/List/List.native.tsx +5 -2
  44. package/src/List/List.styles.old.tsx +242 -0
  45. package/src/List/List.styles.tsx +179 -215
  46. package/src/List/ListItem.native.tsx +12 -6
  47. package/src/List/ListItem.web.tsx +23 -13
  48. package/src/Menu/Menu.styles.old.tsx +197 -0
  49. package/src/Menu/Menu.styles.tsx +68 -150
  50. package/src/Menu/MenuItem.native.tsx +5 -3
  51. package/src/Menu/MenuItem.styles.old.tsx +114 -0
  52. package/src/Menu/MenuItem.styles.tsx +57 -89
  53. package/src/Menu/MenuItem.web.tsx +8 -3
  54. package/src/Popover/Popover.native.tsx +10 -4
  55. package/src/Popover/Popover.styles.old.tsx +135 -0
  56. package/src/Popover/Popover.styles.tsx +51 -112
  57. package/src/Pressable/Pressable.styles.old.tsx +27 -0
  58. package/src/Pressable/Pressable.styles.tsx +35 -27
  59. package/src/Progress/Progress.styles.old.tsx +200 -0
  60. package/src/Progress/Progress.styles.tsx +75 -164
  61. package/src/RadioButton/RadioButton.native.tsx +4 -3
  62. package/src/RadioButton/RadioButton.styles.old.tsx +175 -0
  63. package/src/RadioButton/RadioButton.styles.tsx +83 -154
  64. package/src/RadioButton/RadioButton.web.tsx +2 -2
  65. package/src/SVGImage/SVGImage.styles.old.tsx +86 -0
  66. package/src/SVGImage/SVGImage.styles.tsx +35 -78
  67. package/src/Screen/Screen.native.tsx +18 -25
  68. package/src/Screen/Screen.styles.old.tsx +87 -0
  69. package/src/Screen/Screen.styles.tsx +105 -67
  70. package/src/Screen/Screen.web.tsx +1 -1
  71. package/src/Select/Select.native.tsx +42 -33
  72. package/src/Select/Select.styles.old.tsx +353 -0
  73. package/src/Select/Select.styles.tsx +223 -292
  74. package/src/Skeleton/Skeleton.styles.old.tsx +67 -0
  75. package/src/Skeleton/Skeleton.styles.tsx +29 -53
  76. package/src/Slider/Slider.styles.old.tsx +259 -0
  77. package/src/Slider/Slider.styles.tsx +153 -234
  78. package/src/Switch/Switch.native.tsx +7 -5
  79. package/src/Switch/Switch.styles.old.tsx +203 -0
  80. package/src/Switch/Switch.styles.tsx +101 -174
  81. package/src/Switch/Switch.web.tsx +5 -5
  82. package/src/TabBar/TabBar.native.tsx +3 -2
  83. package/src/TabBar/TabBar.styles.old.tsx +343 -0
  84. package/src/TabBar/TabBar.styles.tsx +145 -279
  85. package/src/Table/Table.native.tsx +18 -9
  86. package/src/Table/Table.styles.old.tsx +311 -0
  87. package/src/Table/Table.styles.tsx +152 -286
  88. package/src/Text/Text.native.tsx +1 -3
  89. package/src/Text/Text.style.demo.tsx +16 -0
  90. package/src/Text/Text.styles.old.tsx +219 -0
  91. package/src/Text/Text.styles.tsx +94 -84
  92. package/src/Text/Text.web.tsx +2 -2
  93. package/src/Text/index.ts +1 -0
  94. package/src/TextArea/TextArea.styles.old.tsx +213 -0
  95. package/src/TextArea/TextArea.styles.tsx +93 -181
  96. package/src/Tooltip/Tooltip.styles.old.tsx +82 -0
  97. package/src/Tooltip/Tooltip.styles.tsx +32 -56
  98. package/src/Video/Video.styles.old.tsx +51 -0
  99. package/src/Video/Video.styles.tsx +32 -44
  100. package/src/View/View.native.tsx +12 -14
  101. package/src/View/View.styles.old.tsx +125 -0
  102. package/src/View/View.styles.tsx +76 -106
  103. package/src/View/View.web.tsx +1 -0
  104. package/src/examples/CardExamples.tsx +0 -6
  105. package/src/extensions/extendComponent.ts +61 -0
@@ -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
+ });
@@ -1,98 +1,28 @@
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
1
  /**
27
- * Create size variants for menu item
2
+ * Menu styles using defineStyle with dynamic props.
28
3
  */
29
- function createItemSizeVariants(theme: Theme) {
30
- return buildSizeVariants(theme, 'menu', (size) => ({
31
- paddingVertical: size.paddingVertical,
32
- paddingHorizontal: size.paddingHorizontal,
33
- }));
34
- }
4
+ import { StyleSheet } from 'react-native-unistyles';
5
+ import { defineStyle, ThemeStyleWrapper } from '@idealyst/theme';
6
+ import type { Theme as BaseTheme, Intent, Size } from '@idealyst/theme';
35
7
 
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
- }
8
+ // Required: Unistyles must see StyleSheet usage in original source to process this file
9
+ void StyleSheet;
53
10
 
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
- }
11
+ // Wrap theme for $iterator support
12
+ type Theme = ThemeStyleWrapper<BaseTheme>;
71
13
 
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
- }
14
+ export type MenuDynamicProps = {
15
+ size?: Size;
16
+ intent?: Intent;
17
+ disabled?: boolean;
18
+ };
82
19
 
83
20
  /**
84
- * Create size variants for label
21
+ * Menu styles with intent/disabled handling.
85
22
  */
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',
23
+ export const menuStyles = defineStyle('Menu', (theme: Theme) => ({
24
+ overlay: (_props: MenuDynamicProps) => ({
25
+ backgroundColor: 'transparent' as const,
96
26
  _web: {
97
27
  position: 'fixed' as const,
98
28
  top: 0,
@@ -101,11 +31,9 @@ function createOverlayStyles(theme: Theme) {
101
31
  bottom: 0,
102
32
  zIndex: 999,
103
33
  },
104
- });
105
- }
34
+ }),
106
35
 
107
- function createMenuStyles(theme: Theme) {
108
- return () => ({
36
+ menu: (_props: MenuDynamicProps) => ({
109
37
  position: 'absolute' as const,
110
38
  zIndex: 1000,
111
39
  backgroundColor: theme.colors.surface.primary,
@@ -123,79 +51,69 @@ function createMenuStyles(theme: Theme) {
123
51
  boxShadow: '0 4px 12px rgba(0, 0, 0, 0.15)',
124
52
  width: 'fit-content',
125
53
  },
126
- });
127
- }
54
+ }),
55
+
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
+ };
128
64
 
129
- function createItemStyles(theme: Theme) {
130
- return ({ intent }: Partial<MenuVariants>) => {
131
- const hoverStyles = getItemHoverStyles(theme, intent ?? 'neutral');
132
65
  return {
133
- flexDirection: 'row',
134
- alignItems: 'center',
135
- backgroundColor: 'transparent',
66
+ flexDirection: 'row' as const,
67
+ alignItems: 'center' as const,
68
+ backgroundColor: 'transparent' as const,
136
69
  borderRadius: 4,
137
70
  minHeight: 44,
71
+ opacity: disabled ? 0.5 : 1,
138
72
  variants: {
139
- size: createItemSizeVariants(theme),
140
- disabled: {
141
- true: {
142
- opacity: 0.5,
143
- _web: {
144
- cursor: 'not-allowed',
145
- },
146
- },
147
- false: {},
73
+ size: {
74
+ paddingVertical: theme.sizes.$menu.paddingVertical,
75
+ paddingHorizontal: theme.sizes.$menu.paddingHorizontal,
148
76
  },
149
77
  },
150
- compoundVariants: createItemCompoundVariants(theme),
151
78
  _web: {
152
- cursor: 'pointer',
79
+ cursor: disabled ? 'not-allowed' : 'pointer',
153
80
  border: 'none',
154
81
  outline: 'none',
155
82
  transition: 'background-color 0.2s ease',
156
83
  textAlign: 'left',
157
- _hover: {
158
- backgroundColor: theme.colors.surface.secondary,
159
- },
84
+ _hover: disabled ? { backgroundColor: 'transparent' } : hoverStyles,
160
85
  },
161
- ...hoverStyles,
162
86
  } as const;
163
- };
164
- }
87
+ },
165
88
 
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
- const extended = applyExtensions('Menu', theme, {
170
- overlay: createOverlayStyles(theme),
171
- menu: createMenuStyles(theme),
172
- item: createItemStyles(theme),
173
- });
89
+ separator: (_props: MenuDynamicProps) => ({
90
+ height: 1,
91
+ backgroundColor: theme.colors.border.primary,
92
+ marginTop: 4,
93
+ marginBottom: 4,
94
+ }),
174
95
 
175
- return {
176
- ...extended,
177
- // Minor utility styles (not extended)
178
- separator: {
179
- height: 1,
180
- backgroundColor: theme.colors.border.primary,
181
- marginTop: 4,
182
- marginBottom: 4,
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,
106
+ },
183
107
  },
184
- icon: {
185
- alignItems: 'center',
186
- justifyContent: 'center',
187
- flexShrink: 0,
188
- marginRight: 8,
189
- variants: {
190
- size: createIconSizeVariants(theme),
191
- } as const,
192
- } as const,
193
- label: {
194
- flex: 1,
195
- color: theme.colors.text.primary,
196
- variants: {
197
- size: createLabelSizeVariants(theme),
198
- } as const,
199
- } as const,
200
- };
201
- });
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
+ }));
@@ -19,8 +19,10 @@ const MenuItem = forwardRef<ComponentRef<typeof Pressable>, MenuItemProps>(({ it
19
19
  disabled: Boolean(item.disabled),
20
20
  });
21
21
 
22
- // Compute dynamic item style with intent
22
+ // Call styles as functions to get theme-reactive styles
23
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)({});
24
26
 
25
27
  const renderIcon = () => {
26
28
  if (!item.icon) return null;
@@ -29,7 +31,7 @@ const MenuItem = forwardRef<ComponentRef<typeof Pressable>, MenuItemProps>(({ it
29
31
  return (
30
32
  <MaterialDesignIcons
31
33
  name={item.icon as any}
32
- style={menuItemStyles.icon}
34
+ style={iconStyle}
33
35
  />
34
36
  );
35
37
  } else if (isValidElement(item.icon)) {
@@ -56,7 +58,7 @@ const MenuItem = forwardRef<ComponentRef<typeof Pressable>, MenuItemProps>(({ it
56
58
  {renderIcon()}
57
59
  </View>
58
60
  )}
59
- <Text style={menuItemStyles.label}>
61
+ <Text style={labelStyle}>
60
62
  {item.label}
61
63
  </Text>
62
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
+ });