@idealyst/components 1.2.13 → 1.2.15

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 (95) hide show
  1. package/package.json +3 -3
  2. package/src/Accordion/Accordion.web.tsx +1 -1
  3. package/src/ActivityIndicator/ActivityIndicator.native.tsx +3 -3
  4. package/src/ActivityIndicator/ActivityIndicator.web.tsx +3 -3
  5. package/src/Alert/Alert.native.tsx +1 -1
  6. package/src/Alert/Alert.web.tsx +1 -1
  7. package/src/Avatar/Avatar.native.tsx +1 -1
  8. package/src/Badge/Badge.web.tsx +6 -2
  9. package/src/Badge/types.ts +5 -0
  10. package/src/Breadcrumb/Breadcrumb.native.tsx +20 -21
  11. package/src/Button/Button.native.tsx +3 -3
  12. package/src/Button/Button.web.tsx +5 -1
  13. package/src/Button/types.ts +5 -0
  14. package/src/Card/Card.web.tsx +4 -1
  15. package/src/Card/types.ts +5 -0
  16. package/src/Dialog/Dialog.native.tsx +3 -3
  17. package/src/Divider/Divider.web.tsx +2 -2
  18. package/src/Icon/Icon.web.tsx +2 -2
  19. package/src/Icon/types.ts +3 -0
  20. package/src/Image/Image.styles.tsx +5 -5
  21. package/src/Image/Image.web.tsx +3 -3
  22. package/src/List/List.native.tsx +1 -2
  23. package/src/List/List.web.tsx +1 -2
  24. package/src/List/ListSection.web.tsx +3 -3
  25. package/src/Menu/Menu.web.tsx +8 -10
  26. package/src/Menu/MenuItem.web.tsx +1 -1
  27. package/src/Popover/Popover.web.tsx +1 -1
  28. package/src/Pressable/Pressable.web.tsx +1 -1
  29. package/src/Progress/Progress.styles.tsx +76 -30
  30. package/src/Progress/Progress.web.tsx +13 -15
  31. package/src/SVGImage/SVGImage.web.tsx +1 -1
  32. package/src/Select/Select.web.tsx +2 -2
  33. package/src/Skeleton/Skeleton.native.tsx +3 -3
  34. package/src/Skeleton/Skeleton.web.tsx +3 -3
  35. package/src/Slider/Slider.native.tsx +2 -2
  36. package/src/Slider/Slider.styles.tsx +131 -44
  37. package/src/Slider/Slider.web.tsx +22 -22
  38. package/src/TabBar/TabBar.native.tsx +2 -2
  39. package/src/Text/Text.web.tsx +29 -3
  40. package/src/Text/types.ts +14 -1
  41. package/src/TextArea/TextArea.styles.tsx +96 -57
  42. package/src/TextArea/TextArea.web.tsx +19 -28
  43. package/src/Tooltip/Tooltip.web.tsx +3 -3
  44. package/src/Video/Video.styles.tsx +3 -3
  45. package/src/Video/Video.web.tsx +1 -1
  46. package/src/View/View.styles.tsx +2 -2
  47. package/src/View/View.web.tsx +93 -9
  48. package/src/View/types.ts +5 -1
  49. package/src/examples/ViewExamples.tsx +34 -0
  50. package/src/extensions/index.ts +0 -7
  51. package/src/hooks/useMergeRefs.ts +12 -6
  52. package/src/index.native.ts +1 -1
  53. package/src/index.ts +1 -1
  54. package/src/utils/accessibility/keyboardPatterns.ts +4 -0
  55. package/src/utils/accessibility/types.ts +5 -1
  56. package/src/utils/accessibility/useAnnounce.ts +1 -1
  57. package/src/utils/accessibility/useKeyboardNavigation.ts +1 -1
  58. package/src/utils/index.ts +0 -3
  59. package/src/utils/viewStyleProps.ts +2 -0
  60. package/src/Accordion/Accordion.styles.old.tsx +0 -298
  61. package/src/ActivityIndicator/ActivityIndicator.styles.old.tsx +0 -94
  62. package/src/Alert/Alert.styles.old.tsx +0 -209
  63. package/src/Avatar/Avatar.styles.old.tsx +0 -99
  64. package/src/Badge/Badge.styles.old.tsx +0 -157
  65. package/src/Breadcrumb/Breadcrumb.styles.old.tsx +0 -231
  66. package/src/Card/Card.styles.old.tsx +0 -160
  67. package/src/Checkbox/Checkbox.styles.old.tsx +0 -271
  68. package/src/Chip/Chip.styles.old.tsx +0 -184
  69. package/src/Dialog/Dialog.styles.old.tsx +0 -202
  70. package/src/Divider/Divider.styles.old.tsx +0 -172
  71. package/src/Icon/Icon.styles.old.tsx +0 -81
  72. package/src/Image/Image.styles.old.tsx +0 -69
  73. package/src/Input/Input.styles.old.tsx +0 -289
  74. package/src/List/List.styles.old.tsx +0 -242
  75. package/src/Menu/Menu.styles.old.tsx +0 -197
  76. package/src/Menu/MenuItem.styles.old.tsx +0 -114
  77. package/src/Popover/Popover.styles.old.tsx +0 -135
  78. package/src/Pressable/Pressable.styles.old.tsx +0 -27
  79. package/src/Progress/Progress.styles.old.tsx +0 -200
  80. package/src/RadioButton/RadioButton.styles.old.tsx +0 -175
  81. package/src/SVGImage/SVGImage.styles.old.tsx +0 -86
  82. package/src/Screen/Screen.styles.old.tsx +0 -87
  83. package/src/Select/Select.styles.old.tsx +0 -353
  84. package/src/Skeleton/Skeleton.styles.old.tsx +0 -67
  85. package/src/Slider/Slider.styles.old.tsx +0 -259
  86. package/src/Switch/Switch.styles.old.tsx +0 -203
  87. package/src/TabBar/TabBar.styles.old.tsx +0 -343
  88. package/src/Table/Table.styles.old.tsx +0 -311
  89. package/src/Text/Text.styles.old.tsx +0 -219
  90. package/src/TextArea/TextArea.styles.old.tsx +0 -213
  91. package/src/Tooltip/Tooltip.styles.old.tsx +0 -82
  92. package/src/Video/Video.styles.old.tsx +0 -51
  93. package/src/View/View.styles.old.tsx +0 -125
  94. package/src/extensions/applyExtension.ts +0 -210
  95. package/src/utils/buildSizeVariants.ts +0 -16
@@ -5,7 +5,7 @@ import type { SliderProps } from './types';
5
5
  import { IconSvg } from '../Icon/IconSvg/IconSvg.web';
6
6
  import { isIconName } from '../Icon/icon-resolver';
7
7
  import useMergeRefs from '../hooks/useMergeRefs';
8
- import { getWebRangeAriaProps, generateAccessibilityId, SLIDER_KEYS } from '../utils/accessibility';
8
+ import { getWebRangeAriaProps, generateAccessibilityId, SLIDER_KEYS, matchesKey } from '../utils/accessibility';
9
9
 
10
10
  /**
11
11
  * Range slider for selecting numeric values within a min/max range.
@@ -55,20 +55,21 @@ const Slider = forwardRef<HTMLDivElement, SliderProps>(({
55
55
  // Apply variants
56
56
  sliderStyles.useVariants({
57
57
  size,
58
+ intent,
58
59
  disabled,
59
60
  margin,
60
61
  marginVertical,
61
62
  marginHorizontal,
62
63
  });
63
64
 
64
- const containerProps = getWebProps([(sliderStyles.container as any)({}), style as any]);
65
- const wrapperProps = getWebProps([sliderStyles.sliderWrapper]);
66
- const trackProps = getWebProps([(sliderStyles.track as any)({})]);
67
- const thumbIconProps = getWebProps([(sliderStyles.thumbIcon as any)({ intent })]);
68
- const valueLabelProps = getWebProps([sliderStyles.valueLabel]);
69
- const minMaxLabelsProps = getWebProps([sliderStyles.minMaxLabels]);
70
- const minMaxLabelProps = getWebProps([sliderStyles.minMaxLabel]);
71
- const marksProps = getWebProps([sliderStyles.marks]);
65
+ const containerProps = getWebProps([sliderStyles.container as any, style as any]);
66
+ const wrapperProps = getWebProps([sliderStyles.sliderWrapper as any]);
67
+ const trackProps = getWebProps([sliderStyles.track as any]);
68
+ const thumbIconProps = getWebProps([sliderStyles.thumbIcon as any]);
69
+ const valueLabelProps = getWebProps([sliderStyles.valueLabel as any]);
70
+ const minMaxLabelsProps = getWebProps([sliderStyles.minMaxLabels as any]);
71
+ const minMaxLabelProps = getWebProps([sliderStyles.minMaxLabel as any]);
72
+ const marksProps = getWebProps([sliderStyles.marks as any]);
72
73
 
73
74
  const clampValue = useCallback((val: number) => {
74
75
  const clampedValue = Math.min(Math.max(val, min), max);
@@ -138,26 +139,25 @@ const Slider = forwardRef<HTMLDivElement, SliderProps>(({
138
139
  const handleKeyDown = useCallback((e: React.KeyboardEvent) => {
139
140
  if (disabled) return;
140
141
 
141
- const key = e.key;
142
142
  let newValue = value;
143
143
  const largeStep = (max - min) / 10; // 10% of range for PageUp/PageDown
144
144
 
145
- if (SLIDER_KEYS.increase.includes(key)) {
145
+ if (matchesKey(e, SLIDER_KEYS.increase)) {
146
146
  e.preventDefault();
147
147
  newValue = clampValue(value + step);
148
- } else if (SLIDER_KEYS.decrease.includes(key)) {
148
+ } else if (matchesKey(e, SLIDER_KEYS.decrease)) {
149
149
  e.preventDefault();
150
150
  newValue = clampValue(value - step);
151
- } else if (SLIDER_KEYS.min.includes(key)) {
151
+ } else if (matchesKey(e, SLIDER_KEYS.min)) {
152
152
  e.preventDefault();
153
153
  newValue = min;
154
- } else if (SLIDER_KEYS.max.includes(key)) {
154
+ } else if (matchesKey(e, SLIDER_KEYS.max)) {
155
155
  e.preventDefault();
156
156
  newValue = max;
157
- } else if (key === 'PageUp') {
157
+ } else if (matchesKey(e, SLIDER_KEYS.increaseLarge)) {
158
158
  e.preventDefault();
159
159
  newValue = clampValue(value + largeStep);
160
- } else if (key === 'PageDown') {
160
+ } else if (matchesKey(e, SLIDER_KEYS.decreaseLarge)) {
161
161
  e.preventDefault();
162
162
  newValue = clampValue(value - largeStep);
163
163
  }
@@ -215,10 +215,10 @@ const Slider = forwardRef<HTMLDivElement, SliderProps>(({
215
215
  const percentage = ((value - min) / (max - min)) * 100;
216
216
 
217
217
  // Dynamic styles with percentage
218
- const filledTrackProps = getWebProps([(sliderStyles.filledTrack as any)({ intent }), { width: `${percentage}%` }]);
218
+ const filledTrackProps = getWebProps([sliderStyles.filledTrack as any, { width: `${percentage}%` }]);
219
219
  const thumbProps = getWebProps([
220
- (sliderStyles.thumb as any)({ intent, disabled }),
221
- isDragging && sliderStyles.thumbActive,
220
+ sliderStyles.thumb as any,
221
+ isDragging && (sliderStyles.thumbActive as any),
222
222
  { left: `${percentage}%` }
223
223
  ]);
224
224
 
@@ -269,8 +269,8 @@ const Slider = forwardRef<HTMLDivElement, SliderProps>(({
269
269
  <div {...marksProps}>
270
270
  {marks.map((mark) => {
271
271
  const markPercentage = ((mark.value - min) / (max - min)) * 100;
272
- const markProps = getWebProps([sliderStyles.mark, { left: `${markPercentage}%` }]);
273
- const markLabelProps = getWebProps([sliderStyles.markLabel, { left: `${markPercentage}%` }]);
272
+ const markProps = getWebProps([sliderStyles.mark as any, { left: `${markPercentage}%` }]);
273
+ const markLabelProps = getWebProps([sliderStyles.markLabel as any, { left: `${markPercentage}%` }]);
274
274
  return (
275
275
  <div key={mark.value}>
276
276
  <div {...markProps} />
@@ -287,8 +287,8 @@ const Slider = forwardRef<HTMLDivElement, SliderProps>(({
287
287
 
288
288
  {/* Thumb */}
289
289
  <div
290
- ref={thumbRef}
291
290
  {...thumbProps}
291
+ ref={thumbRef}
292
292
  >
293
293
  {renderIcon()}
294
294
  </div>
@@ -1,5 +1,5 @@
1
1
  import React, { useState, useRef, useEffect, forwardRef, ReactNode, useMemo } from 'react';
2
- import { View, TouchableOpacity, Text, ScrollView } from 'react-native';
2
+ import { View, TouchableOpacity, Text, ScrollView, LayoutChangeEvent } from 'react-native';
3
3
  import Animated, { useSharedValue, useAnimatedStyle, withSpring } from 'react-native-reanimated';
4
4
  import {
5
5
  tabBarContainerStyles,
@@ -187,7 +187,7 @@ const TabBar = forwardRef<View, TabBarProps>(({
187
187
  return (
188
188
  <TouchableOpacity
189
189
  key={item.value}
190
- onLayout={(event) => {
190
+ onLayout={(event: LayoutChangeEvent) => {
191
191
  const { x, width } = event.nativeEvent.layout;
192
192
  handleTabLayout(item.value, x, width);
193
193
  }}
@@ -1,20 +1,43 @@
1
1
  import React, { forwardRef } from 'react';
2
2
  import { getWebProps } from 'react-native-unistyles/web';
3
- import { TextProps } from './types';
3
+ import type { Typography, Size } from '@idealyst/theme';
4
+ import { TextProps, TextSizeVariant } from './types';
4
5
  import { textStyles } from './Text.styles';
5
6
  import useMergeRefs from '../hooks/useMergeRefs';
6
7
 
8
+ // Map Size values to Typography values
9
+ const SIZE_TO_TYPOGRAPHY: Record<Size, Typography> = {
10
+ 'xs': 'caption',
11
+ 'sm': 'body2',
12
+ 'md': 'body1',
13
+ 'lg': 'subtitle1',
14
+ 'xl': 'h5',
15
+ '2xl': 'h4',
16
+ '3xl': 'h3',
17
+ };
18
+
19
+ // Convert TextSizeVariant to Typography (handles both Size and Typography values)
20
+ function resolveTypography(value: TextSizeVariant | undefined): Typography {
21
+ if (!value) return 'body1';
22
+ // If it's a Size value, map it to Typography
23
+ if (value in SIZE_TO_TYPOGRAPHY) {
24
+ return SIZE_TO_TYPOGRAPHY[value as Size];
25
+ }
26
+ // Otherwise it's already a Typography value
27
+ return value as Typography;
28
+ }
29
+
7
30
  /**
8
31
  * Typography component for displaying text with predefined styles and semantic variants.
9
32
  * Supports multiple typography scales, colors, weights, and alignments.
10
33
  */
11
34
  const Text = forwardRef<HTMLSpanElement, TextProps>(({
12
35
  children,
13
- typography = 'body1',
36
+ typography: typographyProp,
37
+ size,
14
38
  weight,
15
39
  color = 'primary',
16
40
  align = 'left',
17
- pre = false,
18
41
  // Spacing variants from TextSpacingStyleProps
19
42
  gap,
20
43
  padding,
@@ -24,6 +47,9 @@ const Text = forwardRef<HTMLSpanElement, TextProps>(({
24
47
  testID,
25
48
  id,
26
49
  }, ref) => {
50
+ // size is an alias for typography - size takes precedence if both are set
51
+ const typography = resolveTypography(size ?? typographyProp);
52
+
27
53
  textStyles.useVariants({
28
54
  typography,
29
55
  weight,
package/src/Text/types.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { Text, Typography } from '@idealyst/theme';
1
+ import { Text, Typography, Size } from '@idealyst/theme';
2
2
  import type { ReactNode } from 'react';
3
3
  import type { StyleProp, TextStyle } from 'react-native';
4
4
  import { TextSpacingStyleProps } from '../utils/viewStyleProps';
@@ -8,6 +8,12 @@ export type TextColorVariant = Text;
8
8
  export type TextWeightVariant = 'light' | 'normal' | 'medium' | 'semibold' | 'bold';
9
9
  export type TextAlignVariant = 'left' | 'center' | 'right';
10
10
  export type TextTypographyVariant = Typography;
11
+ /**
12
+ * Text size variant - accepts both Typography values and Size shorthand
13
+ * Typography: 'h1', 'h2', 'body1', 'caption', etc.
14
+ * Size: 'xs', 'sm', 'md', 'lg', 'xl', '2xl', '3xl'
15
+ */
16
+ export type TextSizeVariant = Typography | Size;
11
17
 
12
18
  /**
13
19
  * Typography component for rendering text with consistent styling.
@@ -25,6 +31,13 @@ export interface TextProps extends TextSpacingStyleProps {
25
31
  */
26
32
  typography?: TextTypographyVariant;
27
33
 
34
+ /**
35
+ * Text size - accepts Typography names or Size shorthand.
36
+ * Typography: 'h1', 'h2', 'body1', 'caption', etc.
37
+ * Size: 'xs', 'sm', 'md', 'lg', 'xl', '2xl', '3xl'
38
+ */
39
+ size?: TextSizeVariant;
40
+
28
41
  /**
29
42
  * The weight of the text.
30
43
  * Overrides the weight from typography if both are set.
@@ -1,8 +1,8 @@
1
1
  /**
2
- * TextArea styles using defineStyle with dynamic props.
2
+ * TextArea styles using static styles with variants.
3
3
  */
4
4
  import { StyleSheet } from 'react-native-unistyles';
5
- import { defineStyle, ThemeStyleWrapper } from '@idealyst/theme';
5
+ import { defineStyle, ThemeStyleWrapper, CompoundVariants } from '@idealyst/theme';
6
6
  import type { Theme as BaseTheme, Intent, Size } from '@idealyst/theme';
7
7
  import { ViewStyleSize } from '../utils/viewStyleProps';
8
8
 
@@ -12,26 +12,32 @@ void StyleSheet;
12
12
  // Wrap theme for $iterator support
13
13
  type Theme = ThemeStyleWrapper<BaseTheme>;
14
14
 
15
- type ResizeMode = 'none' | 'vertical' | 'horizontal' | 'both';
16
-
17
- export type TextAreaDynamicProps = {
18
- size?: Size;
19
- intent?: Intent;
20
- disabled?: boolean;
21
- hasError?: boolean;
22
- resize?: ResizeMode;
23
- isNearLimit?: boolean;
24
- isAtLimit?: boolean;
15
+ export type TextAreaVariants = {
16
+ size: Size;
17
+ intent: Intent;
18
+ disabled: boolean;
19
+ hasError: boolean;
20
+ isNearLimit: boolean;
21
+ isAtLimit: boolean;
25
22
  margin?: ViewStyleSize;
26
23
  marginVertical?: ViewStyleSize;
27
24
  marginHorizontal?: ViewStyleSize;
28
25
  };
29
26
 
27
+ // Create intent variants dynamically from theme
28
+ function createIntentVariants(theme: Theme) {
29
+ const variants: Record<string, object> = {};
30
+ for (const intent in theme.intents) {
31
+ variants[intent] = {};
32
+ }
33
+ return variants;
34
+ }
35
+
30
36
  /**
31
- * TextArea styles with intent/disabled/error handling.
37
+ * TextArea styles with static styles and variants.
32
38
  */
33
39
  export const textAreaStyles = defineStyle('TextArea', (theme: Theme) => ({
34
- container: (_props: TextAreaDynamicProps) => ({
40
+ container: {
35
41
  display: 'flex' as const,
36
42
  flexDirection: 'column' as const,
37
43
  gap: 4,
@@ -49,70 +55,103 @@ export const textAreaStyles = defineStyle('TextArea', (theme: Theme) => ({
49
55
  marginHorizontal: theme.sizes.$view.padding,
50
56
  },
51
57
  },
52
- }),
58
+ },
53
59
 
54
- label: ({ disabled = false }: TextAreaDynamicProps) => ({
60
+ label: {
55
61
  fontSize: 14,
56
62
  fontWeight: '500' as const,
57
63
  color: theme.colors.text.primary,
58
- }),
64
+ variants: {
65
+ disabled: {
66
+ true: { opacity: 0.5 },
67
+ false: { opacity: 1 },
68
+ },
69
+ },
70
+ },
59
71
 
60
- textareaContainer: (_props: TextAreaDynamicProps) => ({
72
+ textareaContainer: {
61
73
  position: 'relative' as const,
62
74
  variants: {
75
+ disabled: {
76
+ true: { opacity: 0.8 },
77
+ false: { opacity: 1 },
78
+ },
79
+ },
80
+ },
81
+
82
+ textarea: {
83
+ width: '100%',
84
+ color: theme.colors.text.primary,
85
+ variants: {
86
+ size: {
87
+ fontSize: theme.sizes.$textarea.fontSize,
88
+ padding: theme.sizes.$textarea.padding,
89
+ lineHeight: theme.sizes.$textarea.lineHeight,
90
+ minHeight: theme.sizes.$textarea.minHeight,
91
+ },
63
92
  disabled: {
64
93
  true: {
65
- opacity: 1,
94
+ opacity: 0.5,
95
+ _web: {
96
+ cursor: 'not-allowed',
97
+ },
66
98
  },
67
99
  false: {
68
- opacity: 0.8,
69
- },
70
- },
71
- }
72
- }),
73
-
74
- textarea: ({ disabled = false, resize = 'none' }: TextAreaDynamicProps) => ({
75
- width: '100%',
76
- color: theme.colors.text.primary,
77
- opacity: disabled ? 0.5 : 1,
78
- variants: {
79
- size: {
80
- fontSize: theme.sizes.$textarea.fontSize,
81
- padding: theme.sizes.$textarea.padding,
82
- lineHeight: theme.sizes.$textarea.lineHeight,
83
- minHeight: theme.sizes.$textarea.minHeight,
100
+ opacity: 1,
101
+ _web: {
102
+ cursor: 'text',
103
+ },
84
104
  },
85
105
  },
86
- _web: {
87
- fontFamily: 'inherit',
88
- outline: 'none',
89
- transition: 'border-color 0.2s ease, box-shadow 0.2s ease',
90
- boxSizing: 'border-box',
91
- overflowY: 'hidden',
92
- cursor: disabled ? 'not-allowed' : 'text',
93
- resize: resize,
94
- },
95
- }),
106
+ },
107
+ _web: {
108
+ fontFamily: 'inherit',
109
+ outline: 'none',
110
+ transition: 'border-color 0.2s ease, box-shadow 0.2s ease',
111
+ boxSizing: 'border-box',
112
+ overflowY: 'hidden',
113
+ },
114
+ },
96
115
 
97
- helperText: ({ hasError = false }: TextAreaDynamicProps) => ({
116
+ helperText: {
98
117
  fontSize: 12,
99
- color: hasError ? theme.intents.error.primary : theme.colors.text.secondary,
100
- }),
118
+ variants: {
119
+ hasError: {
120
+ true: { color: theme.intents.error.primary },
121
+ false: { color: theme.colors.text.secondary },
122
+ },
123
+ },
124
+ },
101
125
 
102
- footer: (_props: TextAreaDynamicProps) => ({
126
+ footer: {
103
127
  display: 'flex' as const,
104
128
  flexDirection: 'row' as const,
105
129
  justifyContent: 'space-between' as const,
106
130
  alignItems: 'center' as const,
107
131
  gap: 4,
108
- }),
132
+ },
109
133
 
110
- characterCount: ({ isNearLimit = false, isAtLimit = false }: TextAreaDynamicProps) => ({
134
+ characterCount: {
111
135
  fontSize: 12,
112
- color: isAtLimit
113
- ? theme.intents.error.primary
114
- : isNearLimit
115
- ? theme.intents.warning.primary
116
- : theme.colors.text.secondary,
117
- }),
136
+ color: theme.colors.text.secondary,
137
+ variants: {
138
+ isAtLimit: {
139
+ true: { color: theme.intents.error.primary },
140
+ false: {},
141
+ },
142
+ isNearLimit: {
143
+ true: {},
144
+ false: {},
145
+ },
146
+ },
147
+ compoundVariants: [
148
+ {
149
+ isNearLimit: true,
150
+ isAtLimit: false,
151
+ styles: {
152
+ color: theme.intents.warning.primary,
153
+ },
154
+ },
155
+ ] as CompoundVariants<keyof TextAreaVariants>,
156
+ },
118
157
  }));
@@ -117,37 +117,29 @@ const TextArea = forwardRef<HTMLDivElement, TextAreaProps>(({
117
117
  accessibilityAutoComplete,
118
118
  ]);
119
119
 
120
+ const isNearLimit = maxLength ? value.length >= maxLength * 0.9 : false;
121
+ const isAtLimit = maxLength ? value.length >= maxLength : false;
122
+
120
123
  // Apply variants
121
124
  textAreaStyles.useVariants({
122
125
  size,
123
126
  intent,
124
127
  disabled,
125
128
  hasError,
126
- resize,
127
- isNearLimit: maxLength ? value.length >= maxLength * 0.9 : false,
128
- isAtLimit: maxLength ? value.length >= maxLength : false,
129
+ isNearLimit,
130
+ isAtLimit,
129
131
  margin,
130
132
  marginVertical,
131
133
  marginHorizontal,
132
134
  });
133
135
 
134
- // Get dynamic styles - call as functions for theme reactivity
135
- const containerStyle = (textAreaStyles.container as any)({});
136
- const labelStyle = (textAreaStyles.label as any)({ disabled });
137
- const textareaContainerStyle = (textAreaStyles.textareaContainer as any)({});
138
- const footerStyle = (textAreaStyles.footer as any)({});
139
- const helperTextStyle = (textAreaStyles.helperText as any)({ hasError });
140
- const characterCountStyle = (textAreaStyles.characterCount as any)({
141
- isNearLimit: maxLength ? value.length >= maxLength * 0.9 : false,
142
- isAtLimit: maxLength ? value.length >= maxLength : false,
143
- });
144
-
145
- const containerProps = getWebProps([containerStyle, style as any]);
146
- const labelProps = getWebProps([labelStyle]);
147
- const textareaContainerProps = getWebProps([textareaContainerStyle]);
148
- const footerProps = getWebProps([footerStyle]);
149
- const helperTextProps = getWebProps([helperTextStyle]);
150
- const characterCountProps = getWebProps([characterCountStyle]);
136
+ // Get static styles (cast to any for Unistyles variant compatibility)
137
+ const containerProps = getWebProps([textAreaStyles.container as any, style as any]);
138
+ const labelProps = getWebProps([textAreaStyles.label as any]);
139
+ const textareaContainerProps = getWebProps([textAreaStyles.textareaContainer as any]);
140
+ const footerProps = getWebProps([textAreaStyles.footer as any]);
141
+ const helperTextProps = getWebProps([textAreaStyles.helperText as any]);
142
+ const characterCountProps = getWebProps([textAreaStyles.characterCount as any]);
151
143
 
152
144
  const adjustHeight = () => {
153
145
  if (!autoGrow || !textareaRef.current) return;
@@ -189,16 +181,15 @@ const TextArea = forwardRef<HTMLDivElement, TextAreaProps>(({
189
181
  };
190
182
 
191
183
  const showFooter = (error || helperText) || (showCharacterCount && maxLength);
192
- const isNearLimit = maxLength ? value.length >= maxLength * 0.9 : false;
193
- const isAtLimit = maxLength ? value.length >= maxLength : false;
194
184
 
195
185
  const computedTextareaProps = getWebProps([
196
- textAreaStyles.textarea({ intent, disabled, hasError }),
197
- textareaStyle,
198
- minHeight && { minHeight: `${minHeight}px` },
199
- maxHeight && { maxHeight: `${maxHeight}px` },
200
- autoGrow && maxHeight && textareaRef.current && textareaRef.current.scrollHeight > maxHeight && { overflowY: 'auto' as const },
201
- ]);
186
+ textAreaStyles.textarea as any,
187
+ textareaStyle as any,
188
+ { resize } as any, // Apply resize as inline style since it's CSS-only
189
+ minHeight ? { minHeight: `${minHeight}px` } : null,
190
+ maxHeight ? { maxHeight: `${maxHeight}px` } : null,
191
+ autoGrow && maxHeight && textareaRef.current && textareaRef.current.scrollHeight > maxHeight ? { overflowY: 'auto' as const } : null,
192
+ ].filter(Boolean));
202
193
 
203
194
  const mergedRef = useMergeRefs(ref, containerProps.ref);
204
195
  const mergedTextareaRef = useMergeRefs(textareaRef, computedTextareaProps.ref);
@@ -27,7 +27,7 @@ const Tooltip: React.FC<TooltipProps> = ({
27
27
  accessibilityRole,
28
28
  }) => {
29
29
  const [visible, setVisible] = useState(false);
30
- const timeoutRef = useRef<NodeJS.Timeout | null>(null);
30
+ const timeoutRef = useRef<ReturnType<typeof setTimeout> | null>(null);
31
31
  const anchorRef = useRef<HTMLDivElement>(null);
32
32
 
33
33
  // Generate unique ID for tooltip
@@ -105,9 +105,9 @@ const Tooltip: React.FC<TooltipProps> = ({
105
105
  return (
106
106
  <>
107
107
  <div
108
- ref={anchorRef}
109
108
  {...containerProps}
110
109
  {...ariaProps}
110
+ ref={anchorRef}
111
111
  id={triggerId}
112
112
  onMouseEnter={handleMouseEnter}
113
113
  onMouseLeave={handleMouseLeave}
@@ -123,7 +123,7 @@ const Tooltip: React.FC<TooltipProps> = ({
123
123
 
124
124
  <PositionedPortal
125
125
  open={visible}
126
- anchor={anchorRef}
126
+ anchor={anchorRef as React.RefObject<HTMLElement>}
127
127
  placement={placement}
128
128
  offset={8}
129
129
  zIndex={1000}
@@ -20,7 +20,7 @@ export const videoStyles = defineStyle('Video', (theme: Theme) => ({
20
20
  container: (_props: VideoDynamicProps) => ({
21
21
  position: 'relative' as const,
22
22
  overflow: 'hidden' as const,
23
- backgroundColor: theme.colors['black'],
23
+ backgroundColor: theme.colors.pallet.gray[900],
24
24
  }),
25
25
 
26
26
  video: (_props: VideoDynamicProps) => ({
@@ -37,7 +37,7 @@ export const videoStyles = defineStyle('Video', (theme: Theme) => ({
37
37
  display: 'flex' as const,
38
38
  alignItems: 'center' as const,
39
39
  justifyContent: 'center' as const,
40
- backgroundColor: theme.colors['gray.300'],
41
- color: theme.colors['gray.600'],
40
+ backgroundColor: theme.colors.pallet.gray[300],
41
+ color: theme.colors.pallet.gray[600],
42
42
  }),
43
43
  }));
@@ -45,7 +45,7 @@ const Video: React.FC<VideoProps> = ({
45
45
  const videoRef = useRef<HTMLVideoElement>(null);
46
46
 
47
47
  const containerProps = getWebProps([videoStyles.container, style as any]);
48
- const videoProps = getWebProps([videoStyles.video]);
48
+ const videoProps = getWebProps([videoStyles.video as any]);
49
49
 
50
50
  const videoSource = typeof source === 'string'
51
51
  ? source
@@ -60,8 +60,8 @@ export const viewStyles = defineStyle('View', (theme: Theme) => ({
60
60
  },
61
61
  border: {
62
62
  none: { borderWidth: 0 },
63
- thin: { borderWidth: 1, borderStyle: 'solid' as const, borderColor: theme.colors['gray.300'] },
64
- thick: { borderWidth: 2, borderStyle: 'solid' as const, borderColor: theme.colors['gray.300'] },
63
+ thin: { borderWidth: 1, borderStyle: 'solid' as const, borderColor: theme.colors.pallet.gray[300] },
64
+ thick: { borderWidth: 2, borderStyle: 'solid' as const, borderColor: theme.colors.pallet.gray[300] },
65
65
  },
66
66
  // $iterator expands for each view size
67
67
  gap: {