@idealyst/components 1.1.7 → 1.1.9

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 (129) hide show
  1. package/package.json +3 -3
  2. package/plugin/web.js +280 -532
  3. package/src/Accordion/Accordion.native.tsx +8 -6
  4. package/src/Accordion/Accordion.styles.old.tsx +298 -0
  5. package/src/Accordion/Accordion.styles.tsx +102 -236
  6. package/src/Accordion/Accordion.web.tsx +1 -3
  7. package/src/ActivityIndicator/ActivityIndicator.styles.old.tsx +94 -0
  8. package/src/ActivityIndicator/ActivityIndicator.styles.tsx +44 -74
  9. package/src/Alert/Alert.native.tsx +16 -6
  10. package/src/Alert/Alert.styles.old.tsx +209 -0
  11. package/src/Alert/Alert.styles.tsx +67 -149
  12. package/src/Alert/Alert.web.tsx +3 -4
  13. package/src/Avatar/Avatar.styles.old.tsx +99 -0
  14. package/src/Avatar/Avatar.styles.tsx +35 -80
  15. package/src/Badge/Badge.styles.old.tsx +157 -0
  16. package/src/Badge/Badge.styles.tsx +61 -121
  17. package/src/Badge/Badge.web.tsx +8 -15
  18. package/src/Breadcrumb/Breadcrumb.styles.old.tsx +231 -0
  19. package/src/Breadcrumb/Breadcrumb.styles.tsx +83 -200
  20. package/src/Breadcrumb/Breadcrumb.web.tsx +31 -30
  21. package/src/Button/Button.native.tsx +14 -21
  22. package/src/Button/Button.styles.tsx +103 -140
  23. package/src/Button/Button.web.tsx +9 -19
  24. package/src/Card/Card.native.tsx +7 -11
  25. package/src/Card/Card.styles.old.tsx +160 -0
  26. package/src/Card/Card.styles.tsx +105 -142
  27. package/src/Card/Card.web.tsx +5 -4
  28. package/src/Checkbox/Checkbox.native.tsx +9 -5
  29. package/src/Checkbox/Checkbox.styles.old.tsx +271 -0
  30. package/src/Checkbox/Checkbox.styles.tsx +104 -216
  31. package/src/Checkbox/Checkbox.web.tsx +7 -8
  32. package/src/Chip/Chip.styles.old.tsx +184 -0
  33. package/src/Chip/Chip.styles.tsx +34 -72
  34. package/src/Chip/Chip.web.tsx +3 -5
  35. package/src/Dialog/Dialog.native.tsx +7 -4
  36. package/src/Dialog/Dialog.styles.old.tsx +202 -0
  37. package/src/Dialog/Dialog.styles.tsx +69 -133
  38. package/src/Dialog/Dialog.web.tsx +3 -3
  39. package/src/Dialog/types.ts +1 -1
  40. package/src/Divider/Divider.styles.old.tsx +172 -0
  41. package/src/Divider/Divider.styles.tsx +62 -84
  42. package/src/Icon/Icon.native.tsx +8 -8
  43. package/src/Icon/Icon.styles.old.tsx +81 -0
  44. package/src/Icon/Icon.styles.tsx +52 -66
  45. package/src/Icon/Icon.web.tsx +62 -21
  46. package/src/Icon/IconRegistry.native.ts +41 -0
  47. package/src/Icon/IconRegistry.ts +107 -0
  48. package/src/Icon/IconSvg/IconSvg.web.tsx +28 -5
  49. package/src/Icon/icon-resolver.ts +12 -43
  50. package/src/Icon/index.native.ts +2 -1
  51. package/src/Icon/index.ts +1 -0
  52. package/src/Icon/index.web.ts +1 -0
  53. package/src/Image/Image.styles.old.tsx +69 -0
  54. package/src/Image/Image.styles.tsx +46 -60
  55. package/src/Input/Input.native.tsx +138 -53
  56. package/src/Input/Input.styles.old.tsx +289 -0
  57. package/src/Input/Input.styles.tsx +134 -232
  58. package/src/Input/Input.web.tsx +5 -8
  59. package/src/List/List.native.tsx +5 -2
  60. package/src/List/List.styles.old.tsx +242 -0
  61. package/src/List/List.styles.tsx +179 -215
  62. package/src/List/ListItem.native.tsx +16 -11
  63. package/src/List/ListItem.web.tsx +26 -16
  64. package/src/Menu/Menu.styles.old.tsx +197 -0
  65. package/src/Menu/Menu.styles.tsx +68 -150
  66. package/src/Menu/MenuItem.native.tsx +5 -3
  67. package/src/Menu/MenuItem.styles.old.tsx +114 -0
  68. package/src/Menu/MenuItem.styles.tsx +57 -89
  69. package/src/Menu/MenuItem.web.tsx +10 -7
  70. package/src/Popover/Popover.native.tsx +10 -4
  71. package/src/Popover/Popover.styles.old.tsx +135 -0
  72. package/src/Popover/Popover.styles.tsx +51 -112
  73. package/src/Pressable/Pressable.styles.old.tsx +27 -0
  74. package/src/Pressable/Pressable.styles.tsx +35 -27
  75. package/src/Progress/Progress.styles.old.tsx +200 -0
  76. package/src/Progress/Progress.styles.tsx +75 -164
  77. package/src/RadioButton/RadioButton.native.tsx +4 -3
  78. package/src/RadioButton/RadioButton.styles.old.tsx +175 -0
  79. package/src/RadioButton/RadioButton.styles.tsx +83 -154
  80. package/src/RadioButton/RadioButton.web.tsx +2 -2
  81. package/src/SVGImage/SVGImage.styles.old.tsx +86 -0
  82. package/src/SVGImage/SVGImage.styles.tsx +35 -78
  83. package/src/Screen/Screen.native.tsx +19 -26
  84. package/src/Screen/Screen.styles.old.tsx +87 -0
  85. package/src/Screen/Screen.styles.tsx +103 -68
  86. package/src/Screen/Screen.web.tsx +2 -2
  87. package/src/Select/Select.native.tsx +42 -33
  88. package/src/Select/Select.styles.old.tsx +353 -0
  89. package/src/Select/Select.styles.tsx +214 -300
  90. package/src/Select/Select.web.tsx +45 -33
  91. package/src/Skeleton/Skeleton.styles.old.tsx +67 -0
  92. package/src/Skeleton/Skeleton.styles.tsx +29 -53
  93. package/src/Slider/Slider.styles.old.tsx +259 -0
  94. package/src/Slider/Slider.styles.tsx +153 -234
  95. package/src/Slider/Slider.web.tsx +2 -4
  96. package/src/Switch/Switch.native.tsx +9 -7
  97. package/src/Switch/Switch.styles.old.tsx +203 -0
  98. package/src/Switch/Switch.styles.tsx +101 -174
  99. package/src/Switch/Switch.web.tsx +7 -8
  100. package/src/TabBar/TabBar.native.tsx +3 -2
  101. package/src/TabBar/TabBar.styles.old.tsx +343 -0
  102. package/src/TabBar/TabBar.styles.tsx +145 -279
  103. package/src/Table/Table.native.tsx +180 -68
  104. package/src/Table/Table.styles.old.tsx +311 -0
  105. package/src/Table/Table.styles.tsx +140 -281
  106. package/src/Table/Table.web.tsx +169 -70
  107. package/src/Text/Text.native.tsx +1 -3
  108. package/src/Text/Text.style.demo.tsx +16 -0
  109. package/src/Text/Text.styles.old.tsx +219 -0
  110. package/src/Text/Text.styles.tsx +94 -84
  111. package/src/Text/Text.web.tsx +3 -2
  112. package/src/Text/index.ts +1 -0
  113. package/src/TextArea/TextArea.native.tsx +21 -8
  114. package/src/TextArea/TextArea.styles.old.tsx +213 -0
  115. package/src/TextArea/TextArea.styles.tsx +87 -187
  116. package/src/TextArea/TextArea.web.tsx +17 -6
  117. package/src/Tooltip/Tooltip.styles.old.tsx +82 -0
  118. package/src/Tooltip/Tooltip.styles.tsx +32 -56
  119. package/src/Video/Video.styles.old.tsx +51 -0
  120. package/src/Video/Video.styles.tsx +32 -44
  121. package/src/View/View.native.tsx +41 -13
  122. package/src/View/View.styles.old.tsx +125 -0
  123. package/src/View/View.styles.tsx +76 -106
  124. package/src/View/View.web.tsx +5 -21
  125. package/src/View/types.ts +31 -3
  126. package/src/examples/ButtonExamples.tsx +20 -0
  127. package/src/examples/CardExamples.tsx +0 -6
  128. package/src/extensions/extendComponent.ts +61 -0
  129. package/src/index.ts +1 -1
@@ -6,7 +6,7 @@ import { screenStyles } from './Screen.styles';
6
6
 
7
7
  const Screen = forwardRef<RNView | RNScrollView, ScreenProps>(({
8
8
  children,
9
- background = 'primary',
9
+ background = 'screen',
10
10
  safeArea = true,
11
11
  scrollable = true,
12
12
  contentInset,
@@ -24,6 +24,7 @@ const Screen = forwardRef<RNView | RNScrollView, ScreenProps>(({
24
24
  }, ref) => {
25
25
  const insets = useSafeAreaInsets();
26
26
 
27
+ // Set active variants for this render
27
28
  screenStyles.useVariants({
28
29
  background,
29
30
  safeArea,
@@ -36,6 +37,9 @@ const Screen = forwardRef<RNView | RNScrollView, ScreenProps>(({
36
37
  marginHorizontal,
37
38
  });
38
39
 
40
+ // Call styles as functions to get theme-reactive styles
41
+ const screenStyle = (screenStyles.screen as any)({});
42
+
39
43
  // Calculate safe area padding
40
44
  const safeAreaStyle = safeArea ? {
41
45
  paddingTop: insets.top,
@@ -45,43 +49,32 @@ const Screen = forwardRef<RNView | RNScrollView, ScreenProps>(({
45
49
  } : undefined;
46
50
 
47
51
  if (scrollable) {
48
- // For ScrollView, flex: 1 goes on the ScrollView style
49
- // Background and padding go on contentContainerStyle (without flex: 1)
50
- const scrollViewStyle = [{ flex: 1 }, style];
51
-
52
- const contentContainerStyleArray = [
53
- screenStyles.screenContent,
54
- safeAreaStyle,
55
- contentInset ? {
56
- paddingTop: (safeArea ? insets.top : 0) + (contentInset.top ?? 0),
57
- paddingBottom: (safeArea ? insets.bottom : 0) + (contentInset.bottom ?? 0),
58
- paddingLeft: (safeArea ? insets.left : 0) + (contentInset.left ?? 0),
59
- paddingRight: (safeArea ? insets.right : 0) + (contentInset.right ?? 0),
60
- } : undefined,
61
- ];
52
+ // Content styles applied via View wrapper for Unistyles reactivity
53
+ // (contentContainerStyle isn't reactive, only style prop is)
54
+ const contentInsetStyle = contentInset ? {
55
+ paddingTop: (safeArea ? insets.top : 0) + (contentInset.top ?? 0),
56
+ paddingBottom: (safeArea ? insets.bottom : 0) + (contentInset.bottom ?? 0),
57
+ paddingLeft: (safeArea ? insets.left : 0) + (contentInset.left ?? 0),
58
+ paddingRight: (safeArea ? insets.right : 0) + (contentInset.right ?? 0),
59
+ } : safeAreaStyle;
62
60
 
63
61
  return (
64
62
  <RNScrollView
65
63
  ref={ref as any}
66
64
  nativeID={id}
67
- style={scrollViewStyle}
68
- contentContainerStyle={contentContainerStyleArray}
65
+ style={[screenStyle, style]}
66
+ contentContainerStyle={{ flexGrow: 1 }}
69
67
  testID={testID}
70
68
  >
71
- {children}
69
+ <RNView style={[contentInsetStyle, { flex: 1 }]}>
70
+ {children}
71
+ </RNView>
72
72
  </RNScrollView>
73
73
  );
74
74
  }
75
75
 
76
- const screenStyle = (screenStyles.screen as any)({});
77
- const containerStyle = [
78
- screenStyle,
79
- safeAreaStyle,
80
- style,
81
- ];
82
-
83
76
  return (
84
- <RNView ref={ref as any} nativeID={id} style={containerStyle} testID={testID}>
77
+ <RNView ref={ref as any} nativeID={id} style={[screenStyle, safeAreaStyle, style]} testID={testID}>
85
78
  {children}
86
79
  </RNView>
87
80
  );
@@ -0,0 +1,87 @@
1
+ import { StyleSheet } from 'react-native-unistyles';
2
+ import { Theme } from '@idealyst/theme';
3
+ import {
4
+ buildGapVariants,
5
+ buildPaddingVariants,
6
+ buildPaddingVerticalVariants,
7
+ buildPaddingHorizontalVariants,
8
+ buildMarginVariants,
9
+ buildMarginVerticalVariants,
10
+ buildMarginHorizontalVariants,
11
+ } from '../utils/buildViewStyleVariants';
12
+ import { applyExtensions } from '../extensions/applyExtension';
13
+
14
+ function generateBackgroundVariants(theme: Theme) {
15
+ return {
16
+ primary: { backgroundColor: theme.colors.surface.primary },
17
+ secondary: { backgroundColor: theme.colors.surface.secondary },
18
+ tertiary: { backgroundColor: theme.colors.surface.tertiary },
19
+ inverse: { backgroundColor: theme.colors.surface.inverse },
20
+ 'inverse-secondary': { backgroundColor: theme.colors.surface['inverse-secondary'] },
21
+ 'inverse-tertiary': { backgroundColor: theme.colors.surface['inverse-tertiary'] },
22
+ transparent: { backgroundColor: 'transparent' },
23
+ };
24
+ }
25
+
26
+ /**
27
+ * Create dynamic screen styles.
28
+ * Returns a function to ensure Unistyles can track theme changes.
29
+ */
30
+ function createScreenStyles(theme: Theme) {
31
+ return (_props?: {}) => ({
32
+ flex: 1,
33
+ variants: {
34
+ background: generateBackgroundVariants(theme),
35
+ safeArea: {
36
+ true: {},
37
+ false: {},
38
+ },
39
+ gap: buildGapVariants(theme),
40
+ padding: buildPaddingVariants(theme),
41
+ paddingVertical: buildPaddingVerticalVariants(theme),
42
+ paddingHorizontal: buildPaddingHorizontalVariants(theme),
43
+ margin: buildMarginVariants(theme),
44
+ marginVertical: buildMarginVerticalVariants(theme),
45
+ marginHorizontal: buildMarginHorizontalVariants(theme),
46
+ },
47
+ _web: {
48
+ overflow: 'auto',
49
+ display: 'flex',
50
+ flexDirection: 'column',
51
+ minHeight: '100%',
52
+ boxSizing: 'border-box',
53
+ },
54
+ });
55
+ }
56
+
57
+ /**
58
+ * Create dynamic screen content styles for ScrollView.
59
+ * No flex: 1 so content can grow beyond screen height.
60
+ */
61
+ function createScreenContentStyles(theme: Theme) {
62
+ return (_props?: {}) => ({
63
+ variants: {
64
+ background: generateBackgroundVariants(theme),
65
+ safeArea: {
66
+ true: {},
67
+ false: {},
68
+ },
69
+ gap: buildGapVariants(theme),
70
+ padding: buildPaddingVariants(theme),
71
+ paddingVertical: buildPaddingVerticalVariants(theme),
72
+ paddingHorizontal: buildPaddingHorizontalVariants(theme),
73
+ margin: buildMarginVariants(theme),
74
+ marginVertical: buildMarginVerticalVariants(theme),
75
+ marginHorizontal: buildMarginHorizontalVariants(theme),
76
+ },
77
+ });
78
+ }
79
+
80
+ // Styles use applyExtensions to enable theme extensions and ensure proper
81
+ // reactivity with Unistyles' native Shadow Tree updates.
82
+ export const screenStyles = StyleSheet.create((theme: Theme) => {
83
+ return applyExtensions('Screen', theme, {
84
+ screen: createScreenStyles(theme),
85
+ screenContent: createScreenContentStyles(theme),
86
+ });
87
+ });
@@ -1,87 +1,122 @@
1
+ /**
2
+ * Screen styles using defineStyle with $iterator expansion.
3
+ */
1
4
  import { StyleSheet } from 'react-native-unistyles';
2
- import { Theme } from '@idealyst/theme';
3
- import {
4
- buildGapVariants,
5
- buildPaddingVariants,
6
- buildPaddingVerticalVariants,
7
- buildPaddingHorizontalVariants,
8
- buildMarginVariants,
9
- buildMarginVerticalVariants,
10
- buildMarginHorizontalVariants,
11
- } from '../utils/buildViewStyleVariants';
12
- import { applyExtensions } from '../extensions/applyExtension';
5
+ import { defineStyle, ThemeStyleWrapper } from '@idealyst/theme';
6
+ import type { Theme as BaseTheme } from '@idealyst/theme';
7
+ import { ViewStyleSize } from '../utils/viewStyleProps';
13
8
 
14
- function generateBackgroundVariants(theme: Theme) {
15
- return {
16
- primary: { backgroundColor: theme.colors.surface.primary },
17
- secondary: { backgroundColor: theme.colors.surface.secondary },
18
- tertiary: { backgroundColor: theme.colors.surface.tertiary },
19
- inverse: { backgroundColor: theme.colors.surface.inverse },
20
- 'inverse-secondary': { backgroundColor: theme.colors.surface['inverse-secondary'] },
21
- 'inverse-tertiary': { backgroundColor: theme.colors.surface['inverse-tertiary'] },
22
- transparent: { backgroundColor: 'transparent' },
23
- };
24
- }
9
+ // Required: Unistyles must see StyleSheet usage in original source to process this file
10
+ void StyleSheet;
25
11
 
26
- // Style creators for extension support
27
- function createScreenStyles(theme: Theme) {
28
- return () => ({
12
+ // Wrap theme for $iterator support
13
+ type Theme = ThemeStyleWrapper<BaseTheme>;
14
+
15
+ type ScreenBackground = 'screen' | 'primary' | 'secondary' | 'tertiary' | 'inverse' | 'inverse-secondary' | 'inverse-tertiary' | 'transparent';
16
+
17
+ export type ScreenDynamicProps = {
18
+ background?: ScreenBackground;
19
+ safeArea?: boolean;
20
+ gap?: ViewStyleSize;
21
+ padding?: ViewStyleSize;
22
+ paddingVertical?: ViewStyleSize;
23
+ paddingHorizontal?: ViewStyleSize;
24
+ margin?: ViewStyleSize;
25
+ marginVertical?: ViewStyleSize;
26
+ marginHorizontal?: ViewStyleSize;
27
+ };
28
+
29
+ /**
30
+ * Screen styles with $iterator expansion for spacing variants.
31
+ *
32
+ * NOTE: Top-level theme access required for Unistyles reactivity.
33
+ */
34
+ export const screenStyles = defineStyle('Screen', (theme: Theme) => ({
35
+ screen: (_props: ScreenDynamicProps) => ({
29
36
  flex: 1,
30
37
  variants: {
31
- background: generateBackgroundVariants(theme),
38
+ background: {
39
+ screen: { backgroundColor: theme.colors.surface.screen },
40
+ primary: { backgroundColor: theme.colors.surface.primary },
41
+ secondary: { backgroundColor: theme.colors.surface.secondary },
42
+ tertiary: { backgroundColor: theme.colors.surface.tertiary },
43
+ inverse: { backgroundColor: theme.colors.surface.inverse },
44
+ 'inverse-secondary': { backgroundColor: theme.colors.surface['inverse-secondary'] },
45
+ 'inverse-tertiary': { backgroundColor: theme.colors.surface['inverse-tertiary'] },
46
+ transparent: { backgroundColor: 'transparent' },
47
+ },
32
48
  safeArea: {
33
49
  true: {},
34
50
  false: {},
35
51
  },
36
- // Spacing variants from ContainerStyleProps
37
- gap: buildGapVariants(theme),
38
- padding: buildPaddingVariants(theme),
39
- paddingVertical: buildPaddingVerticalVariants(theme),
40
- paddingHorizontal: buildPaddingHorizontalVariants(theme),
41
- margin: buildMarginVariants(theme),
42
- marginVertical: buildMarginVerticalVariants(theme),
43
- marginHorizontal: buildMarginHorizontalVariants(theme),
52
+ // $iterator expands for each view size
53
+ gap: {
54
+ gap: theme.sizes.$view.spacing,
55
+ },
56
+ padding: {
57
+ padding: theme.sizes.$view.padding,
58
+ },
59
+ paddingVertical: {
60
+ paddingVertical: theme.sizes.$view.padding,
61
+ },
62
+ paddingHorizontal: {
63
+ paddingHorizontal: theme.sizes.$view.padding,
64
+ },
65
+ margin: {
66
+ margin: theme.sizes.$view.padding,
67
+ },
68
+ marginVertical: {
69
+ marginVertical: theme.sizes.$view.padding,
70
+ },
71
+ marginHorizontal: {
72
+ marginHorizontal: theme.sizes.$view.padding,
73
+ },
44
74
  },
45
75
  _web: {
46
- overflow: 'auto',
47
76
  display: 'flex',
48
77
  flexDirection: 'column',
49
78
  minHeight: '100%',
50
79
  boxSizing: 'border-box',
51
80
  },
52
- });
53
- }
54
-
55
- // Styles are inlined here instead of in @idealyst/theme because Unistyles' Babel
56
- // transform on native cannot resolve function calls to extract variant structures.
57
- // @ts-ignore - TS language server needs restart to pick up theme structure changes
58
- export const screenStyles = StyleSheet.create((theme: Theme) => {
59
- // Apply extensions to main visual elements
60
- const extended = applyExtensions('Screen', theme, {
61
- screen: createScreenStyles(theme),
62
- });
81
+ }),
63
82
 
64
- return {
65
- ...extended,
66
- // Minor utility styles (not extended)
67
- // Content style for ScrollView - no flex: 1 so content can grow
68
- screenContent: {
69
- backgroundColor: theme.colors.surface.primary,
70
- variants: {
71
- background: generateBackgroundVariants(theme),
72
- safeArea: {
73
- true: {},
74
- false: {},
75
- },
76
- // Spacing variants from ContainerStyleProps
77
- gap: buildGapVariants(theme),
78
- padding: buildPaddingVariants(theme),
79
- paddingVertical: buildPaddingVerticalVariants(theme),
80
- paddingHorizontal: buildPaddingHorizontalVariants(theme),
81
- margin: buildMarginVariants(theme),
82
- marginVertical: buildMarginVerticalVariants(theme),
83
- marginHorizontal: buildMarginHorizontalVariants(theme),
83
+ screenContent: (_props: ScreenDynamicProps) => ({
84
+ variants: {
85
+ background: {
86
+ screen: { backgroundColor: theme.colors.surface.screen },
87
+ primary: { backgroundColor: theme.colors.surface.primary },
88
+ secondary: { backgroundColor: theme.colors.surface.secondary },
89
+ tertiary: { backgroundColor: theme.colors.surface.tertiary },
90
+ inverse: { backgroundColor: theme.colors.surface.inverse },
91
+ 'inverse-secondary': { backgroundColor: theme.colors.surface['inverse-secondary'] },
92
+ 'inverse-tertiary': { backgroundColor: theme.colors.surface['inverse-tertiary'] },
93
+ transparent: { backgroundColor: 'transparent' },
94
+ },
95
+ safeArea: {
96
+ true: {},
97
+ false: {},
98
+ },
99
+ gap: {
100
+ gap: theme.sizes.$view.spacing,
101
+ },
102
+ padding: {
103
+ padding: theme.sizes.$view.padding,
104
+ },
105
+ paddingVertical: {
106
+ paddingVertical: theme.sizes.$view.padding,
107
+ },
108
+ paddingHorizontal: {
109
+ paddingHorizontal: theme.sizes.$view.padding,
110
+ },
111
+ margin: {
112
+ margin: theme.sizes.$view.padding,
113
+ },
114
+ marginVertical: {
115
+ marginVertical: theme.sizes.$view.padding,
116
+ },
117
+ marginHorizontal: {
118
+ marginHorizontal: theme.sizes.$view.padding,
84
119
  },
85
120
  },
86
- };
87
- });
121
+ }),
122
+ }));
@@ -6,7 +6,7 @@ import useMergeRefs from '../hooks/useMergeRefs';
6
6
 
7
7
  const Screen = forwardRef<HTMLDivElement, ScreenProps>(({
8
8
  children,
9
- background = 'primary',
9
+ background = 'screen',
10
10
  safeArea = false,
11
11
  // Spacing variants from ContainerStyleProps
12
12
  gap,
@@ -32,7 +32,7 @@ const Screen = forwardRef<HTMLDivElement, ScreenProps>(({
32
32
  marginHorizontal,
33
33
  });
34
34
 
35
- // Use getWebProps to generate className and ref for web
35
+ // Call style as function to get theme-reactive styles
36
36
  const webProps = getWebProps([(screenStyles.screen as any)({}), style as any]);
37
37
 
38
38
  const mergedRef = useMergeRefs(ref, webProps.ref);
@@ -86,6 +86,27 @@ const Select = forwardRef<View, SelectProps>(({
86
86
  marginHorizontal,
87
87
  });
88
88
 
89
+ // Get dynamic styles - call as functions for theme reactivity
90
+ const containerStyle = (selectStyles.container as any)({});
91
+ const labelStyle = (selectStyles.label as any)({});
92
+ const triggerStyle = (selectStyles.trigger as any)({ type, intent, disabled, error, focused: isOpen });
93
+ const triggerContentStyle = (selectStyles.triggerContent as any)({});
94
+ const triggerTextStyle = (selectStyles.triggerText as any)({});
95
+ const placeholderStyle = (selectStyles.placeholder as any)({});
96
+ const iconStyle = (selectStyles.icon as any)({});
97
+ const chevronStyle = (selectStyles.chevron as any)({});
98
+ const dropdownStyle = (selectStyles.dropdown as any)({});
99
+ const searchContainerStyle = (selectStyles.searchContainer as any)({});
100
+ const searchInputStyle = (selectStyles.searchInput as any)({});
101
+ const optionsListStyle = (selectStyles.optionsList as any)({});
102
+ const optionStyle = (selectStyles.option as any)({});
103
+ const optionContentStyle = (selectStyles.optionContent as any)({});
104
+ const optionIconStyle = (selectStyles.optionIcon as any)({});
105
+ const optionTextStyle = (selectStyles.optionText as any)({});
106
+ const optionTextDisabledStyle = (selectStyles.optionTextDisabled as any)({});
107
+ const helperTextStyle = (selectStyles.helperText as any)({ error });
108
+ const overlayStyle = (selectStyles.overlay as any)({});
109
+
89
110
  const handleTriggerPress = () => {
90
111
  if (disabled) return;
91
112
 
@@ -158,10 +179,10 @@ const Select = forwardRef<View, SelectProps>(({
158
179
 
159
180
  const renderChevron = () => {
160
181
  return (
161
- <View style={selectStyles.chevron}>
182
+ <View style={chevronStyle}>
162
183
  <MaterialCommunityIcons
163
184
  name="chevron-down"
164
- style={selectStyles.chevron}
185
+ style={chevronStyle}
165
186
  />
166
187
  </View>
167
188
  );
@@ -172,7 +193,6 @@ const Select = forwardRef<View, SelectProps>(({
172
193
 
173
194
  // If it's a string, render as MaterialCommunityIcons
174
195
  if (typeof icon === 'string') {
175
- const iconStyle = selectStyles.icon;
176
196
  return (
177
197
  <View style={iconStyle}>
178
198
  <MaterialCommunityIcons
@@ -184,7 +204,7 @@ const Select = forwardRef<View, SelectProps>(({
184
204
  }
185
205
 
186
206
  // Otherwise render the React element directly
187
- return <View style={selectStyles.icon}>{icon}</View>;
207
+ return <View style={iconStyle}>{icon}</View>;
188
208
  };
189
209
 
190
210
  const renderOptionIcon = (icon: any) => {
@@ -192,11 +212,10 @@ const Select = forwardRef<View, SelectProps>(({
192
212
 
193
213
  // If it's a string, render as MaterialCommunityIcons
194
214
  if (typeof icon === 'string') {
195
- const iconStyle = selectStyles.optionIcon;
196
215
  return (
197
- <View style={iconStyle}>
216
+ <View style={optionIconStyle}>
198
217
  <MaterialCommunityIcons
199
- style={iconStyle}
218
+ style={optionIconStyle}
200
219
  name={icon}
201
220
  />
202
221
  </View>
@@ -204,7 +223,7 @@ const Select = forwardRef<View, SelectProps>(({
204
223
  }
205
224
 
206
225
  // Otherwise render the React element directly
207
- return <View style={selectStyles.optionIcon}>{icon}</View>;
226
+ return <View style={optionIconStyle}>{icon}</View>;
208
227
  };
209
228
 
210
229
  const renderDropdown = () => {
@@ -222,7 +241,7 @@ const Select = forwardRef<View, SelectProps>(({
222
241
  onRequestClose={closeDropdown}
223
242
  >
224
243
  <Pressable
225
- style={selectStyles.overlay}
244
+ style={overlayStyle}
226
245
  onPress={closeDropdown}
227
246
  >
228
247
  <BoundedModalContent
@@ -233,7 +252,7 @@ const Select = forwardRef<View, SelectProps>(({
233
252
  >
234
253
  <Animated.View
235
254
  style={[
236
- (selectStyles.dropdown as any)({}),
255
+ dropdownStyle,
237
256
  {
238
257
  position: 'relative', // Override absolute positioning from styles
239
258
  top: 0, // Override top: '100%' from styles
@@ -246,9 +265,9 @@ const Select = forwardRef<View, SelectProps>(({
246
265
  onLayout={handleDropdownLayout}
247
266
  >
248
267
  {searchable && (
249
- <View style={selectStyles.searchContainer}>
268
+ <View style={searchContainerStyle}>
250
269
  <TextInput
251
- style={selectStyles.searchInput}
270
+ style={searchInputStyle}
252
271
  placeholder="Search options..."
253
272
  value={searchTerm}
254
273
  onChangeText={handleSearchChange}
@@ -258,23 +277,23 @@ const Select = forwardRef<View, SelectProps>(({
258
277
  )}
259
278
 
260
279
  <ScrollView
261
- style={selectStyles.optionsList}
280
+ style={optionsListStyle}
262
281
  showsVerticalScrollIndicator={true}
263
282
  >
264
283
  {filteredOptions.map((option) => (
265
284
  <Pressable
266
285
  key={option.value}
267
- style={(selectStyles.option as any)({})}
286
+ style={optionStyle}
268
287
  onPress={() => handleOptionSelect(option)}
269
288
  disabled={option.disabled}
270
289
  android_ripple={{ color: 'rgba(0, 0, 0, 0.1)' }}
271
290
  >
272
- <View style={selectStyles.optionContent}>
291
+ <View style={optionContentStyle}>
273
292
  {renderOptionIcon(option.icon)}
274
293
  <Text
275
294
  style={[
276
- selectStyles.optionText,
277
- option.disabled && selectStyles.optionTextDisabled,
295
+ optionTextStyle,
296
+ option.disabled && optionTextDisabledStyle,
278
297
  ]}
279
298
  >
280
299
  {option.label}
@@ -284,8 +303,8 @@ const Select = forwardRef<View, SelectProps>(({
284
303
  ))}
285
304
 
286
305
  {filteredOptions.length === 0 && (
287
- <View style={(selectStyles.option as any)({})}>
288
- <Text style={selectStyles.optionText}>
306
+ <View style={optionStyle}>
307
+ <Text style={optionTextStyle}>
289
308
  No options found
290
309
  </Text>
291
310
  </View>
@@ -298,16 +317,10 @@ const Select = forwardRef<View, SelectProps>(({
298
317
  );
299
318
  };
300
319
 
301
- // Get dynamic styles
302
- const containerStyle = (selectStyles.container as any)({});
303
- const triggerStyle = (selectStyles.trigger as any)({ type, intent });
304
- const dropdownStyle = (selectStyles.dropdown as any)({});
305
- const optionStyle = (selectStyles.option as any)({});
306
-
307
320
  return (
308
321
  <View ref={ref} nativeID={id} style={[containerStyle, style]} testID={testID}>
309
322
  {label && (
310
- <Text style={selectStyles.label}>
323
+ <Text style={labelStyle}>
311
324
  {label}
312
325
  </Text>
313
326
  )}
@@ -325,11 +338,11 @@ const Select = forwardRef<View, SelectProps>(({
325
338
  }}
326
339
  android_ripple={{ color: 'rgba(0, 0, 0, 0.1)' }}
327
340
  >
328
- <View style={selectStyles.triggerContent}>
341
+ <View style={triggerContentStyle}>
329
342
  {renderTriggerIcon(selectedOption?.icon)}
330
343
  <Text
331
344
  style={[
332
- selectedOption ? selectStyles.triggerText : selectStyles.placeholder,
345
+ selectedOption ? triggerTextStyle : placeholderStyle,
333
346
  ]}
334
347
  numberOfLines={1}
335
348
  >
@@ -344,11 +357,7 @@ const Select = forwardRef<View, SelectProps>(({
344
357
  {!(Platform.OS === 'ios' && presentationMode === 'actionSheet') && renderDropdown()}
345
358
 
346
359
  {helperText && (
347
- <Text
348
- style={[
349
- selectStyles.helperText,
350
- ]}
351
- >
360
+ <Text style={helperTextStyle}>
352
361
  {helperText}
353
362
  </Text>
354
363
  )}