@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.
- package/package.json +3 -3
- package/src/Accordion/Accordion.web.tsx +1 -1
- package/src/ActivityIndicator/ActivityIndicator.native.tsx +3 -3
- package/src/ActivityIndicator/ActivityIndicator.web.tsx +3 -3
- package/src/Alert/Alert.native.tsx +1 -1
- package/src/Alert/Alert.web.tsx +1 -1
- package/src/Avatar/Avatar.native.tsx +1 -1
- package/src/Badge/Badge.web.tsx +6 -2
- package/src/Badge/types.ts +5 -0
- package/src/Breadcrumb/Breadcrumb.native.tsx +20 -21
- package/src/Button/Button.native.tsx +3 -3
- package/src/Button/Button.web.tsx +5 -1
- package/src/Button/types.ts +5 -0
- package/src/Card/Card.web.tsx +4 -1
- package/src/Card/types.ts +5 -0
- package/src/Dialog/Dialog.native.tsx +3 -3
- package/src/Divider/Divider.web.tsx +2 -2
- package/src/Icon/Icon.web.tsx +2 -2
- package/src/Icon/types.ts +3 -0
- package/src/Image/Image.styles.tsx +5 -5
- package/src/Image/Image.web.tsx +3 -3
- package/src/List/List.native.tsx +1 -2
- package/src/List/List.web.tsx +1 -2
- package/src/List/ListSection.web.tsx +3 -3
- package/src/Menu/Menu.web.tsx +8 -10
- package/src/Menu/MenuItem.web.tsx +1 -1
- package/src/Popover/Popover.web.tsx +1 -1
- package/src/Pressable/Pressable.web.tsx +1 -1
- package/src/Progress/Progress.styles.tsx +76 -30
- package/src/Progress/Progress.web.tsx +13 -15
- package/src/SVGImage/SVGImage.web.tsx +1 -1
- package/src/Select/Select.web.tsx +2 -2
- package/src/Skeleton/Skeleton.native.tsx +3 -3
- package/src/Skeleton/Skeleton.web.tsx +3 -3
- package/src/Slider/Slider.native.tsx +2 -2
- package/src/Slider/Slider.styles.tsx +131 -44
- package/src/Slider/Slider.web.tsx +22 -22
- package/src/TabBar/TabBar.native.tsx +2 -2
- package/src/Text/Text.web.tsx +29 -3
- package/src/Text/types.ts +14 -1
- package/src/TextArea/TextArea.styles.tsx +96 -57
- package/src/TextArea/TextArea.web.tsx +19 -28
- package/src/Tooltip/Tooltip.web.tsx +3 -3
- package/src/Video/Video.styles.tsx +3 -3
- package/src/Video/Video.web.tsx +1 -1
- package/src/View/View.styles.tsx +2 -2
- package/src/View/View.web.tsx +93 -9
- package/src/View/types.ts +5 -1
- package/src/examples/ViewExamples.tsx +34 -0
- package/src/extensions/index.ts +0 -7
- package/src/hooks/useMergeRefs.ts +12 -6
- package/src/index.native.ts +1 -1
- package/src/index.ts +1 -1
- package/src/utils/accessibility/keyboardPatterns.ts +4 -0
- package/src/utils/accessibility/types.ts +5 -1
- package/src/utils/accessibility/useAnnounce.ts +1 -1
- package/src/utils/accessibility/useKeyboardNavigation.ts +1 -1
- package/src/utils/index.ts +0 -3
- package/src/utils/viewStyleProps.ts +2 -0
- package/src/Accordion/Accordion.styles.old.tsx +0 -298
- package/src/ActivityIndicator/ActivityIndicator.styles.old.tsx +0 -94
- package/src/Alert/Alert.styles.old.tsx +0 -209
- package/src/Avatar/Avatar.styles.old.tsx +0 -99
- package/src/Badge/Badge.styles.old.tsx +0 -157
- package/src/Breadcrumb/Breadcrumb.styles.old.tsx +0 -231
- package/src/Card/Card.styles.old.tsx +0 -160
- package/src/Checkbox/Checkbox.styles.old.tsx +0 -271
- package/src/Chip/Chip.styles.old.tsx +0 -184
- package/src/Dialog/Dialog.styles.old.tsx +0 -202
- package/src/Divider/Divider.styles.old.tsx +0 -172
- package/src/Icon/Icon.styles.old.tsx +0 -81
- package/src/Image/Image.styles.old.tsx +0 -69
- package/src/Input/Input.styles.old.tsx +0 -289
- package/src/List/List.styles.old.tsx +0 -242
- package/src/Menu/Menu.styles.old.tsx +0 -197
- package/src/Menu/MenuItem.styles.old.tsx +0 -114
- package/src/Popover/Popover.styles.old.tsx +0 -135
- package/src/Pressable/Pressable.styles.old.tsx +0 -27
- package/src/Progress/Progress.styles.old.tsx +0 -200
- package/src/RadioButton/RadioButton.styles.old.tsx +0 -175
- package/src/SVGImage/SVGImage.styles.old.tsx +0 -86
- package/src/Screen/Screen.styles.old.tsx +0 -87
- package/src/Select/Select.styles.old.tsx +0 -353
- package/src/Skeleton/Skeleton.styles.old.tsx +0 -67
- package/src/Slider/Slider.styles.old.tsx +0 -259
- package/src/Switch/Switch.styles.old.tsx +0 -203
- package/src/TabBar/TabBar.styles.old.tsx +0 -343
- package/src/Table/Table.styles.old.tsx +0 -311
- package/src/Text/Text.styles.old.tsx +0 -219
- package/src/TextArea/TextArea.styles.old.tsx +0 -213
- package/src/Tooltip/Tooltip.styles.old.tsx +0 -82
- package/src/Video/Video.styles.old.tsx +0 -51
- package/src/View/View.styles.old.tsx +0 -125
- package/src/extensions/applyExtension.ts +0 -210
- 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([
|
|
65
|
-
const wrapperProps = getWebProps([sliderStyles.sliderWrapper]);
|
|
66
|
-
const trackProps = getWebProps([
|
|
67
|
-
const thumbIconProps = getWebProps([
|
|
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
|
|
145
|
+
if (matchesKey(e, SLIDER_KEYS.increase)) {
|
|
146
146
|
e.preventDefault();
|
|
147
147
|
newValue = clampValue(value + step);
|
|
148
|
-
} else if (SLIDER_KEYS.decrease
|
|
148
|
+
} else if (matchesKey(e, SLIDER_KEYS.decrease)) {
|
|
149
149
|
e.preventDefault();
|
|
150
150
|
newValue = clampValue(value - step);
|
|
151
|
-
} else if (SLIDER_KEYS.min
|
|
151
|
+
} else if (matchesKey(e, SLIDER_KEYS.min)) {
|
|
152
152
|
e.preventDefault();
|
|
153
153
|
newValue = min;
|
|
154
|
-
} else if (SLIDER_KEYS.max
|
|
154
|
+
} else if (matchesKey(e, SLIDER_KEYS.max)) {
|
|
155
155
|
e.preventDefault();
|
|
156
156
|
newValue = max;
|
|
157
|
-
} else if (
|
|
157
|
+
} else if (matchesKey(e, SLIDER_KEYS.increaseLarge)) {
|
|
158
158
|
e.preventDefault();
|
|
159
159
|
newValue = clampValue(value + largeStep);
|
|
160
|
-
} else if (
|
|
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([
|
|
218
|
+
const filledTrackProps = getWebProps([sliderStyles.filledTrack as any, { width: `${percentage}%` }]);
|
|
219
219
|
const thumbProps = getWebProps([
|
|
220
|
-
|
|
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
|
}}
|
package/src/Text/Text.web.tsx
CHANGED
|
@@ -1,20 +1,43 @@
|
|
|
1
1
|
import React, { forwardRef } from 'react';
|
|
2
2
|
import { getWebProps } from 'react-native-unistyles/web';
|
|
3
|
-
import {
|
|
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
|
|
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
|
|
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
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
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
|
|
37
|
+
* TextArea styles with static styles and variants.
|
|
32
38
|
*/
|
|
33
39
|
export const textAreaStyles = defineStyle('TextArea', (theme: Theme) => ({
|
|
34
|
-
container:
|
|
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:
|
|
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:
|
|
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:
|
|
94
|
+
opacity: 0.5,
|
|
95
|
+
_web: {
|
|
96
|
+
cursor: 'not-allowed',
|
|
97
|
+
},
|
|
66
98
|
},
|
|
67
99
|
false: {
|
|
68
|
-
opacity:
|
|
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
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
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:
|
|
116
|
+
helperText: {
|
|
98
117
|
fontSize: 12,
|
|
99
|
-
|
|
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:
|
|
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:
|
|
134
|
+
characterCount: {
|
|
111
135
|
fontSize: 12,
|
|
112
|
-
color:
|
|
113
|
-
|
|
114
|
-
:
|
|
115
|
-
|
|
116
|
-
:
|
|
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
|
-
|
|
127
|
-
|
|
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
|
|
135
|
-
const
|
|
136
|
-
const
|
|
137
|
-
const
|
|
138
|
-
const
|
|
139
|
-
const
|
|
140
|
-
const
|
|
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
|
|
197
|
-
textareaStyle,
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
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<
|
|
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[
|
|
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[
|
|
41
|
-
color: theme.colors[
|
|
40
|
+
backgroundColor: theme.colors.pallet.gray[300],
|
|
41
|
+
color: theme.colors.pallet.gray[600],
|
|
42
42
|
}),
|
|
43
43
|
}));
|
package/src/Video/Video.web.tsx
CHANGED
|
@@ -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
|
package/src/View/View.styles.tsx
CHANGED
|
@@ -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[
|
|
64
|
-
thick: { borderWidth: 2, borderStyle: 'solid' as const, borderColor: theme.colors[
|
|
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: {
|