@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
@@ -1,13 +1,17 @@
1
- import { StyleSheet } from "react-native-unistyles";
2
- import { Theme, Typography } from '@idealyst/theme';
3
- import {
4
- buildGapVariants,
5
- buildPaddingVariants,
6
- buildPaddingVerticalVariants,
7
- buildPaddingHorizontalVariants,
8
- } from '../utils/buildViewStyleVariants';
1
+ /**
2
+ * Text styles using defineStyle with $iterator expansion.
3
+ */
4
+ import { StyleSheet } from 'react-native-unistyles';
5
+ import { defineStyle, ThemeStyleWrapper } from '@idealyst/theme';
6
+
7
+ // Required: Unistyles must see StyleSheet usage in original source to process this file
8
+ void StyleSheet;
9
+ import type { Theme as BaseTheme } from '@idealyst/theme';
10
+ import type { TextStyle, ViewStyle } from 'react-native';
9
11
  import { TextAlignVariant, TextColorVariant, TextWeightVariant, TextTypographyVariant } from "./types";
10
- import { applyExtensions } from '../extensions/applyExtension';
12
+
13
+ // Wrap theme for $iterator support
14
+ type Theme = ThemeStyleWrapper<BaseTheme>;
11
15
 
12
16
  export type TextVariants = {
13
17
  typography: TextTypographyVariant;
@@ -16,87 +20,93 @@ export type TextVariants = {
16
20
  }
17
21
 
18
22
  /**
19
- * Create typography variants from theme
23
+ * All props available to dynamic Text style functions.
24
+ * Extensions and overrides receive these to make conditional styling decisions.
20
25
  */
21
- function createTypographyVariants(theme: Theme) {
22
- const variants: Record<string, object> = {};
26
+ export type TextStyleParams = {
27
+ /** Text color variant */
28
+ color?: TextColorVariant;
29
+ /** Typography variant (h1, h2, body1, etc.) */
30
+ typography?: TextTypographyVariant;
31
+ /** Font weight override */
32
+ weight?: TextWeightVariant;
33
+ /** Text alignment */
34
+ align?: TextAlignVariant;
35
+ }
23
36
 
24
- for (const key in theme.sizes.typography) {
25
- const typo = theme.sizes.typography[key as Typography];
26
- variants[key] = {
27
- fontSize: typo.fontSize,
28
- lineHeight: typo.lineHeight,
29
- fontWeight: typo.fontWeight,
37
+ /**
38
+ * Text style definition type for use with extendStyle/overrideStyle.
39
+ */
40
+ export interface TextStyleDef {
41
+ text: (params: TextStyleParams) => TextStyle & {
42
+ variants?: {
43
+ typography?: Record<string, TextStyle>;
44
+ weight?: Record<string, TextStyle>;
45
+ align?: Record<string, TextStyle>;
46
+ gap?: Record<string, ViewStyle>;
47
+ padding?: Record<string, ViewStyle>;
48
+ paddingVertical?: Record<string, ViewStyle>;
49
+ paddingHorizontal?: Record<string, ViewStyle>;
30
50
  };
31
- }
32
-
33
- return variants;
51
+ };
34
52
  }
35
53
 
36
- type TextStyleParams = {
37
- color?: TextColorVariant;
54
+ // Register Text style types for type-safe extendStyle/overrideStyle
55
+ declare module '@idealyst/theme' {
56
+ interface ComponentStyleRegistry {
57
+ Text: TextStyleDef;
58
+ }
38
59
  }
39
60
 
40
- function createTextStyles(theme: Theme) {
41
- return ({ color }: TextStyleParams) => {
42
- const colorValue = theme.colors.text[color ?? 'primary'] || theme.colors.text.primary;
43
-
44
- return {
45
- margin: 0,
46
- padding: 0,
47
- color: colorValue,
48
- variants: {
49
- typography: createTypographyVariants(theme),
50
- weight: {
51
- light: {
52
- fontWeight: '300',
53
- },
54
- normal: {
55
- fontWeight: '400',
56
- },
57
- medium: {
58
- fontWeight: '500',
59
- },
60
- semibold: {
61
- fontWeight: '600',
62
- },
63
- bold: {
64
- fontWeight: '700',
65
- },
66
- } as const,
67
- align: {
68
- left: {
69
- textAlign: 'left',
70
- },
71
- center: {
72
- textAlign: 'center',
73
- },
74
- right: {
75
- textAlign: 'right',
76
- },
77
- } as const,
78
- // Spacing variants from TextSpacingStyleProps
79
- gap: buildGapVariants(theme),
80
- padding: buildPaddingVariants(theme),
81
- paddingVertical: buildPaddingVerticalVariants(theme),
82
- paddingHorizontal: buildPaddingHorizontalVariants(theme),
61
+ /**
62
+ * Text styles with $iterator expansion.
63
+ *
64
+ * Babel expands:
65
+ * - theme.sizes.$typography.X → all typography keys (h1, h2, body1, etc.)
66
+ * - theme.sizes.$view.X → all view size keys (xs, sm, md, lg, xl)
67
+ */
68
+ // @ts-ignore - $iterator patterns are expanded by Babel
69
+ export const textStyles = defineStyle('Text', (theme: Theme) => ({
70
+ text: ({ color, typography, weight, align }: TextStyleParams) => ({
71
+ margin: 0,
72
+ padding: 0,
73
+ // Base color - can be overridden by extensions using any of the params
74
+ color: theme.colors.text[color ?? 'primary'] || theme.colors.text.primary,
75
+ variants: {
76
+ // Typography variants - $iterator expands for each typography key
77
+ typography: {
78
+ fontSize: theme.sizes.$typography.fontSize,
79
+ lineHeight: theme.sizes.$typography.lineHeight,
80
+ fontWeight: theme.sizes.$typography.fontWeight,
81
+ },
82
+ weight: {
83
+ light: { fontWeight: '300' },
84
+ normal: { fontWeight: '400' },
85
+ medium: { fontWeight: '500' },
86
+ semibold: { fontWeight: '600' },
87
+ bold: { fontWeight: '700' },
88
+ } as const,
89
+ align: {
90
+ left: { textAlign: 'left' },
91
+ center: { textAlign: 'center' },
92
+ right: { textAlign: 'right' },
83
93
  } as const,
84
- _web: {
85
- fontFamily: 'inherit',
94
+ // Spacing variants - $iterator expands for each view size key
95
+ gap: {
96
+ gap: theme.sizes.$view.spacing,
86
97
  },
87
- };
88
- }
89
- }
90
-
91
- // Styles are inlined here instead of in @idealyst/theme because Unistyles' Babel
92
- // transform on native cannot resolve function calls to extract variant structures.
93
- export const textStyles = StyleSheet.create((theme: Theme) => {
94
- // Apply extensions to main visual elements
95
- const extended = applyExtensions('Text', theme, {
96
- text: createTextStyles(theme),
97
- });
98
-
99
- return {
100
- ...extended,
101
- };
102
- });
98
+ padding: {
99
+ padding: theme.sizes.$view.padding,
100
+ },
101
+ paddingVertical: {
102
+ paddingVertical: theme.sizes.$view.padding,
103
+ },
104
+ paddingHorizontal: {
105
+ paddingHorizontal: theme.sizes.$view.padding,
106
+ },
107
+ } as const,
108
+ _web: {
109
+ fontFamily: 'inherit',
110
+ },
111
+ }),
112
+ }));
@@ -10,6 +10,7 @@ const Text = forwardRef<HTMLSpanElement, TextProps>(({
10
10
  weight,
11
11
  color = 'primary',
12
12
  align = 'left',
13
+ pre = false,
13
14
  // Spacing variants from TextSpacingStyleProps
14
15
  gap,
15
16
  padding,
@@ -29,9 +30,9 @@ const Text = forwardRef<HTMLSpanElement, TextProps>(({
29
30
  paddingHorizontal,
30
31
  });
31
32
 
32
- // Create the style array
33
+ // Create the style array - pass all style-affecting props to dynamic style function
33
34
  const textStyleArray = [
34
- (textStyles.text as any)({ color }),
35
+ (textStyles.text as any)({ color, typography, weight, align }),
35
36
  style,
36
37
  ];
37
38
 
package/src/Text/index.ts CHANGED
@@ -3,3 +3,4 @@ import TextComponent from './Text.web';
3
3
  export default TextComponent;
4
4
  export { TextComponent as Text };
5
5
  export * from './types';
6
+ export type { TextStyleDef, TextStyleParams, TextVariants } from './Text.styles';
@@ -129,20 +129,33 @@ const TextArea = forwardRef<TextInput, TextAreaProps>(({
129
129
 
130
130
  const showFooter = (error || helperText) || (showCharacterCount && maxLength);
131
131
 
132
+ // Get dynamic styles - call as functions for theme reactivity
133
+ const containerStyleComputed = (textAreaStyles.container as any)({});
134
+ const labelStyleComputed = (textAreaStyles.label as any)({ disabled });
135
+ const textareaContainerStyleComputed = (textAreaStyles.textareaContainer as any)({});
136
+ const textareaStyleComputed = (textAreaStyles.textarea as any)({ intent, disabled, hasError });
137
+ const footerStyleComputed = (textAreaStyles.footer as any)({});
138
+ const helperTextStyleComputed = (textAreaStyles.helperText as any)({ hasError });
139
+ const characterCountStyleComputed = (textAreaStyles.characterCount as any)({
140
+ isNearLimit: maxLength ? value.length >= maxLength * 0.9 : false,
141
+ isAtLimit: maxLength ? value.length >= maxLength : false,
142
+ });
143
+
132
144
  return (
133
- <View nativeID={id} style={[textAreaStyles.container, style]} testID={testID}>
145
+ <View nativeID={id} style={[containerStyleComputed, style]} testID={testID}>
134
146
  {label && (
135
- <Text style={textAreaStyles.label}>{label}</Text>
147
+ <Text style={labelStyleComputed}>{label}</Text>
136
148
  )}
137
149
 
138
- <View style={textAreaStyles.textareaContainer}>
150
+ <View style={textareaContainerStyleComputed}>
139
151
  <TextInput
140
152
  ref={ref}
141
153
  {...nativeA11yProps}
142
154
  style={[
143
- textAreaStyles.textarea({ intent, disabled, hasError }),
155
+ textareaStyleComputed,
144
156
  {
145
157
  textAlignVertical: 'top',
158
+ backgroundColor: 'transparent',
146
159
  },
147
160
  maxHeight && { maxHeight },
148
161
  { height: autoGrow ? contentHeight : rows * 24 },
@@ -161,22 +174,22 @@ const TextArea = forwardRef<TextInput, TextAreaProps>(({
161
174
  </View>
162
175
 
163
176
  {showFooter && (
164
- <View style={textAreaStyles.footer}>
177
+ <View style={footerStyleComputed}>
165
178
  <View style={{ flex: 1 }}>
166
179
  {error && (
167
- <Text style={textAreaStyles.helperText}>
180
+ <Text style={helperTextStyleComputed}>
168
181
  {error}
169
182
  </Text>
170
183
  )}
171
184
  {!error && helperText && (
172
- <Text style={textAreaStyles.helperText}>
185
+ <Text style={helperTextStyleComputed}>
173
186
  {helperText}
174
187
  </Text>
175
188
  )}
176
189
  </View>
177
190
 
178
191
  {showCharacterCount && maxLength && (
179
- <Text style={textAreaStyles.characterCount}>
192
+ <Text style={characterCountStyleComputed}>
180
193
  {value.length}/{maxLength}
181
194
  </Text>
182
195
  )}
@@ -0,0 +1,213 @@
1
+ import { StyleSheet } from 'react-native-unistyles';
2
+ import { Theme, StylesheetStyles, Intent, Size } from '@idealyst/theme';
3
+ import { buildSizeVariants } from '../utils/buildSizeVariants';
4
+ import {
5
+ buildMarginVariants,
6
+ buildMarginVerticalVariants,
7
+ buildMarginHorizontalVariants,
8
+ } from '../utils/buildViewStyleVariants';
9
+ import { TextAreaIntentVariant } from './types';
10
+ import { applyExtensions } from '../extensions/applyExtension';
11
+
12
+ /**
13
+ * Create size variants for textarea
14
+ */
15
+ function createTextareaSizeVariants(theme: Theme) {
16
+ return buildSizeVariants(theme, 'textarea', (size) => ({
17
+ fontSize: size.fontSize,
18
+ padding: size.padding,
19
+ lineHeight: size.lineHeight,
20
+ minHeight: size.minHeight,
21
+ }));
22
+ }
23
+
24
+ /**
25
+ * Get textarea styles based on intent, disabled, and hasError state
26
+ */
27
+ function getTextareaIntentStyles(theme: Theme, intent: TextAreaIntentVariant, disabled: boolean, hasError: boolean) {
28
+ if (disabled || hasError) {
29
+ return {} as const;
30
+ }
31
+
32
+ const intentValue = theme.intents[intent];
33
+ const baseStyles: any = {};
34
+
35
+ // For success and warning, set border color
36
+ if (intent === 'success' || intent === 'warning') {
37
+ baseStyles.borderColor = intentValue.primary;
38
+ }
39
+
40
+ // Focus styles for all intents when not disabled and not in error
41
+ baseStyles._web = {
42
+ _focus: {
43
+ borderColor: intentValue.primary,
44
+ boxShadow: `0 0 0 2px ${intentValue.primary}33`,
45
+ },
46
+ };
47
+
48
+ return baseStyles;
49
+ }
50
+
51
+ const createTextareaStyles = (theme: Theme) => {
52
+ return ({ intent, disabled, hasError }: { intent: TextAreaIntentVariant, disabled: boolean, hasError: boolean }) => {
53
+ const intentStyles = getTextareaIntentStyles(theme, intent, disabled, hasError);
54
+
55
+ return {
56
+ width: '100%',
57
+ color: theme.colors.text.primary,
58
+ backgroundColor: theme.colors.surface.primary,
59
+ borderWidth: 1,
60
+ borderStyle: 'solid',
61
+ borderColor: theme.colors.border.primary,
62
+ borderRadius: 8,
63
+ lineHeight: 'normal',
64
+ ...intentStyles,
65
+ variants: {
66
+ size: createTextareaSizeVariants(theme),
67
+ disabled: {
68
+ true: {
69
+ opacity: 0.5,
70
+ backgroundColor: theme.colors.surface.secondary,
71
+ _web: {
72
+ cursor: 'not-allowed',
73
+ },
74
+ },
75
+ false: {},
76
+ },
77
+ hasError: {
78
+ true: {
79
+ borderColor: theme.intents.error.primary,
80
+ },
81
+ false: {},
82
+ },
83
+ resize: {
84
+ none: {
85
+ _web: {
86
+ resize: 'none',
87
+ },
88
+ },
89
+ vertical: {
90
+ _web: {
91
+ resize: 'vertical',
92
+ },
93
+ },
94
+ horizontal: {
95
+ _web: {
96
+ resize: 'horizontal',
97
+ },
98
+ },
99
+ both: {
100
+ _web: {
101
+ resize: 'both',
102
+ },
103
+ },
104
+ },
105
+ },
106
+ _web: {
107
+ fontFamily: 'inherit',
108
+ outline: 'none',
109
+ transition: 'border-color 0.2s ease, box-shadow 0.2s ease',
110
+ boxSizing: 'border-box',
111
+ overflowY: 'hidden',
112
+ },
113
+ } as const;
114
+ }
115
+ }
116
+
117
+ // Helper functions to create static styles wrapped in dynamic functions
118
+ function createContainerStyles(theme: Theme) {
119
+ return () => ({
120
+ display: 'flex' as const,
121
+ flexDirection: 'column' as const,
122
+ gap: 4,
123
+ variants: {
124
+ // Spacing variants from FormInputStyleProps
125
+ margin: buildMarginVariants(theme),
126
+ marginVertical: buildMarginVerticalVariants(theme),
127
+ marginHorizontal: buildMarginHorizontalVariants(theme),
128
+ },
129
+ });
130
+ }
131
+
132
+ function createLabelStyles(theme: Theme) {
133
+ return () => ({
134
+ fontSize: 14,
135
+ fontWeight: '500' as const,
136
+ color: theme.colors.text.primary,
137
+ variants: {
138
+ disabled: {
139
+ true: {
140
+ opacity: 0.5,
141
+ },
142
+ false: {},
143
+ },
144
+ },
145
+ });
146
+ }
147
+
148
+ function createTextareaContainerStyles() {
149
+ return () => ({
150
+ position: 'relative' as const,
151
+ });
152
+ }
153
+
154
+ function createHelperTextStyles(theme: Theme) {
155
+ return () => ({
156
+ fontSize: 12,
157
+ color: theme.colors.text.secondary,
158
+ variants: {
159
+ hasError: {
160
+ true: {
161
+ color: theme.intents.error.primary,
162
+ },
163
+ false: {},
164
+ },
165
+ },
166
+ });
167
+ }
168
+
169
+ function createFooterStyles() {
170
+ return () => ({
171
+ display: 'flex' as const,
172
+ flexDirection: 'row' as const,
173
+ justifyContent: 'space-between' as const,
174
+ alignItems: 'center' as const,
175
+ gap: 4,
176
+ });
177
+ }
178
+
179
+ function createCharacterCountStyles(theme: Theme) {
180
+ return () => ({
181
+ fontSize: 12,
182
+ color: theme.colors.text.secondary,
183
+ variants: {
184
+ isNearLimit: {
185
+ true: {
186
+ color: theme.intents.warning.primary,
187
+ },
188
+ false: {},
189
+ },
190
+ isAtLimit: {
191
+ true: {
192
+ color: theme.intents.error.primary,
193
+ },
194
+ false: {},
195
+ },
196
+ },
197
+ });
198
+ }
199
+
200
+ // Styles are inlined here instead of in @idealyst/theme because Unistyles' Babel transform on native cannot resolve function calls to extract variant structures.
201
+ export const textAreaStyles = StyleSheet.create((theme: Theme) => {
202
+ // Apply extensions to main visual elements
203
+
204
+ return applyExtensions('TextArea', theme, {container: createContainerStyles(theme),
205
+ textarea: createTextareaStyles(theme),
206
+ // Additional styles (merged from return)
207
+ // Minor utility styles (not extended)
208
+ label: createLabelStyles(theme)(),
209
+ textareaContainer: createTextareaContainerStyles()(),
210
+ helperText: createHelperTextStyles(theme)(),
211
+ footer: createFooterStyles()(),
212
+ characterCount: createCharacterCountStyles(theme)()});
213
+ });