@idealyst/components 1.2.29 → 1.2.31
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/README.md +3 -3
- package/package.json +4 -4
- package/plugin/__tests__/web.test.ts +2 -2
- package/plugin/web.js +2 -0
- package/src/Accordion/Accordion.native.tsx +3 -2
- package/src/ActivityIndicator/ActivityIndicator.native.tsx +4 -2
- package/src/ActivityIndicator/ActivityIndicator.styles.tsx +22 -27
- package/src/ActivityIndicator/ActivityIndicator.web.tsx +17 -29
- package/src/Alert/Alert.native.tsx +20 -10
- package/src/Alert/Alert.styles.tsx +173 -86
- package/src/Alert/Alert.web.tsx +34 -30
- package/src/Alert/types.ts +53 -3
- package/src/Avatar/Avatar.native.tsx +3 -2
- package/src/Avatar/Avatar.web.tsx +2 -1
- package/src/Avatar/types.ts +1 -1
- package/src/Badge/Badge.native.tsx +18 -6
- package/src/Badge/Badge.styles.tsx +22 -5
- package/src/Badge/Badge.web.tsx +12 -4
- package/src/Badge/types.ts +14 -2
- package/src/Breadcrumb/Breadcrumb.native.tsx +3 -2
- package/src/Button/Button.native.tsx +16 -6
- package/src/Button/Button.styles.tsx +2 -2
- package/src/Button/Button.web.tsx +19 -15
- package/src/Button/types.ts +6 -10
- package/src/Card/Card.native.tsx +27 -3
- package/src/Card/Card.web.tsx +30 -4
- package/src/Card/types.ts +15 -0
- package/src/Checkbox/Checkbox.native.tsx +5 -4
- package/src/Checkbox/Checkbox.styles.tsx +62 -52
- package/src/Checkbox/Checkbox.web.tsx +4 -3
- package/src/Checkbox/types.ts +1 -1
- package/src/Chip/Chip.native.tsx +30 -7
- package/src/Chip/Chip.web.tsx +28 -5
- package/src/Chip/types.ts +15 -0
- package/src/Dialog/Dialog.native.tsx +6 -6
- package/src/Dialog/Dialog.web.tsx +5 -5
- package/src/Dialog/types.ts +2 -2
- package/src/Divider/Divider.native.tsx +20 -17
- package/src/Divider/Divider.styles.tsx +51 -29
- package/src/Divider/Divider.web.tsx +5 -4
- package/src/Divider/types.ts +3 -3
- package/src/Icon/Icon.native.tsx +3 -2
- package/src/Icon/Icon.web.tsx +2 -1
- package/src/Icon/IconSvg/IconSvg.native.tsx +3 -2
- package/src/IconButton/IconButton.native.tsx +219 -0
- package/src/IconButton/IconButton.styles.tsx +127 -0
- package/src/IconButton/IconButton.web.tsx +198 -0
- package/src/IconButton/index.native.ts +5 -0
- package/src/IconButton/index.ts +5 -0
- package/src/IconButton/index.web.ts +5 -0
- package/src/IconButton/types.ts +84 -0
- package/src/Image/Image.native.tsx +3 -2
- package/src/Input/Input.native.tsx +42 -290
- package/src/Input/Input.styles.tsx +1 -1
- package/src/Input/Input.web.tsx +37 -288
- package/src/Input/index.native.ts +9 -2
- package/src/Input/index.ts +8 -1
- package/src/Input/index.web.ts +8 -1
- package/src/Input/types.ts +1 -1
- package/src/List/List.native.tsx +3 -2
- package/src/List/ListItem.native.tsx +3 -2
- package/src/List/ListSection.native.tsx +3 -2
- package/src/Menu/Menu.native.tsx +2 -1
- package/src/Menu/Menu.styles.tsx +79 -29
- package/src/Menu/Menu.web.tsx +2 -1
- package/src/Menu/MenuItem.native.tsx +4 -3
- package/src/Menu/MenuItem.styles.tsx +81 -32
- package/src/Menu/MenuItem.web.tsx +2 -1
- package/src/Menu/docs.ts +1 -1
- package/src/Popover/Popover.native.tsx +2 -1
- package/src/Popover/Popover.web.tsx +2 -1
- package/src/Popover/types.ts +15 -4
- package/src/Pressable/Pressable.native.tsx +3 -2
- package/src/Pressable/Pressable.web.tsx +3 -5
- package/src/Progress/Progress.native.tsx +5 -4
- package/src/Progress/Progress.web.tsx +3 -3
- package/src/Progress/types.ts +3 -3
- package/src/RadioButton/RadioButton.native.tsx +4 -3
- package/src/RadioButton/RadioButton.styles.tsx +53 -33
- package/src/RadioButton/RadioGroup.native.tsx +3 -2
- package/src/SVGImage/SVGImage.native.tsx +5 -4
- package/src/SVGImage/SVGImage.styles.tsx +44 -10
- package/src/SVGImage/SVGImage.web.tsx +2 -1
- package/src/Screen/Screen.native.tsx +2 -1
- package/src/Screen/Screen.web.tsx +2 -1
- package/src/Select/Select.native.tsx +6 -5
- package/src/Select/Select.styles.tsx +1 -1
- package/src/Select/Select.web.tsx +4 -3
- package/src/Select/types.ts +1 -1
- package/src/Skeleton/Skeleton.native.tsx +2 -1
- package/src/Skeleton/Skeleton.web.tsx +1 -1
- package/src/Slider/Slider.native.tsx +9 -8
- package/src/Slider/Slider.web.tsx +10 -9
- package/src/Slider/types.ts +9 -2
- package/src/Switch/Switch.native.tsx +7 -6
- package/src/Switch/Switch.styles.tsx +52 -17
- package/src/Switch/Switch.web.tsx +15 -16
- package/src/Switch/types.ts +44 -4
- package/src/TabBar/TabBar.native.tsx +3 -2
- package/src/Text/Text.native.tsx +3 -2
- package/src/Text/Text.web.tsx +2 -1
- package/src/TextArea/TextArea.native.tsx +3 -2
- package/src/TextArea/TextArea.styles.tsx +2 -2
- package/src/TextArea/TextArea.web.tsx +2 -1
- package/src/TextInput/TextInput.native.tsx +300 -0
- package/src/TextInput/TextInput.styles.tsx +207 -0
- package/src/TextInput/TextInput.web.tsx +301 -0
- package/src/TextInput/index.native.ts +3 -0
- package/src/TextInput/index.ts +5 -0
- package/src/TextInput/index.web.ts +5 -0
- package/src/TextInput/types.ts +163 -0
- package/src/Tooltip/Tooltip.native.tsx +3 -2
- package/src/Video/Video.native.tsx +4 -3
- package/src/View/View.native.tsx +2 -1
- package/src/View/View.styles.tsx +1 -0
- package/src/View/View.web.tsx +9 -2
- package/src/examples/ActivityIndicatorExamples.tsx +177 -0
- package/src/examples/AlertExamples.tsx +5 -5
- package/src/examples/ButtonExamples.tsx +12 -12
- package/src/examples/CardExamples.tsx +1 -1
- package/src/examples/CheckboxExamples.tsx +2 -2
- package/src/examples/ChipExamples.tsx +6 -6
- package/src/examples/DialogExamples.tsx +1 -1
- package/src/examples/DividerExamples.tsx +1 -1
- package/src/examples/InputExamples.tsx +1 -1
- package/src/examples/LinkExamples.tsx +1 -1
- package/src/examples/ListExamples.tsx +1 -1
- package/src/examples/MenuExamples.tsx +2 -2
- package/src/examples/ProgressExamples.tsx +1 -1
- package/src/examples/RadioButtonExamples.tsx +5 -5
- package/src/examples/SVGImageExamples.tsx +1 -1
- package/src/examples/SelectExamples.tsx +1 -1
- package/src/examples/SliderExamples.tsx +5 -5
- package/src/examples/SwitchExamples.tsx +26 -26
- package/src/examples/TableExamples.tsx +1 -1
- package/src/examples/TooltipExamples.tsx +2 -2
- package/src/examples/index.ts +1 -0
- package/src/extensions/index.ts +1 -0
- package/src/extensions/types.ts +22 -3
- package/src/index.native.ts +4 -0
- package/src/index.ts +27 -2
- package/src/utils/index.ts +12 -0
- package/src/utils/refTypes.ts +50 -0
|
@@ -49,60 +49,80 @@ export const radioButtonStyles = defineStyle('RadioButton', (theme: Theme) => ({
|
|
|
49
49
|
},
|
|
50
50
|
}),
|
|
51
51
|
|
|
52
|
-
radio: (
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
height: theme.sizes.$radioButton.radioSize,
|
|
52
|
+
radio: (_props: RadioButtonDynamicProps) => ({
|
|
53
|
+
borderRadius: 9999,
|
|
54
|
+
borderWidth: 1.5,
|
|
55
|
+
borderStyle: 'solid' as const,
|
|
56
|
+
alignItems: 'center' as const,
|
|
57
|
+
justifyContent: 'center' as const,
|
|
58
|
+
variants: {
|
|
59
|
+
size: {
|
|
60
|
+
width: theme.sizes.$radioButton.radioSize,
|
|
61
|
+
height: theme.sizes.$radioButton.radioSize,
|
|
62
|
+
},
|
|
63
|
+
checked: {
|
|
64
|
+
true: {
|
|
65
|
+
borderColor: theme.$intents.primary,
|
|
66
|
+
},
|
|
67
|
+
false: {
|
|
68
|
+
borderColor: theme.colors.border.primary,
|
|
70
69
|
},
|
|
71
70
|
},
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
71
|
+
disabled: {
|
|
72
|
+
true: {
|
|
73
|
+
backgroundColor: theme.colors.surface.tertiary,
|
|
74
|
+
opacity: 0.5,
|
|
75
|
+
},
|
|
76
|
+
false: {
|
|
77
|
+
backgroundColor: theme.colors.surface.primary,
|
|
78
|
+
opacity: 1,
|
|
79
|
+
},
|
|
77
80
|
},
|
|
78
|
-
}
|
|
79
|
-
|
|
81
|
+
},
|
|
82
|
+
_web: {
|
|
83
|
+
transition: 'all 0.2s ease',
|
|
84
|
+
},
|
|
85
|
+
}),
|
|
80
86
|
|
|
81
|
-
radioDot: (
|
|
87
|
+
radioDot: (_props: RadioButtonDynamicProps) => ({
|
|
82
88
|
borderRadius: 9999,
|
|
83
|
-
backgroundColor: theme.intents[intent].primary,
|
|
84
89
|
variants: {
|
|
85
90
|
size: {
|
|
86
91
|
width: theme.sizes.$radioButton.radioDotSize,
|
|
87
92
|
height: theme.sizes.$radioButton.radioDotSize,
|
|
88
93
|
},
|
|
94
|
+
intent: {
|
|
95
|
+
backgroundColor: theme.$intents.primary,
|
|
96
|
+
},
|
|
89
97
|
},
|
|
90
98
|
}),
|
|
91
99
|
|
|
92
|
-
label: (
|
|
100
|
+
label: (_props: RadioButtonDynamicProps) => ({
|
|
93
101
|
color: theme.colors.text.primary,
|
|
94
|
-
opacity: disabled ? 0.5 : 1,
|
|
95
102
|
variants: {
|
|
96
103
|
size: {
|
|
97
104
|
fontSize: theme.sizes.$radioButton.fontSize,
|
|
98
105
|
},
|
|
106
|
+
disabled: {
|
|
107
|
+
true: { opacity: 0.5 },
|
|
108
|
+
false: { opacity: 1 },
|
|
109
|
+
},
|
|
99
110
|
},
|
|
100
111
|
}),
|
|
101
112
|
|
|
102
|
-
groupContainer: (
|
|
113
|
+
groupContainer: (_props: RadioButtonDynamicProps) => ({
|
|
103
114
|
gap: 4,
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
115
|
+
variants: {
|
|
116
|
+
orientation: {
|
|
117
|
+
horizontal: {
|
|
118
|
+
flexDirection: 'row' as const,
|
|
119
|
+
flexWrap: 'wrap' as const,
|
|
120
|
+
gap: 16,
|
|
121
|
+
},
|
|
122
|
+
vertical: {
|
|
123
|
+
flexDirection: 'column' as const,
|
|
124
|
+
},
|
|
125
|
+
},
|
|
126
|
+
},
|
|
107
127
|
}),
|
|
108
128
|
}));
|
|
@@ -3,6 +3,7 @@ import { View } from 'react-native';
|
|
|
3
3
|
import { radioButtonStyles } from './RadioButton.styles';
|
|
4
4
|
import type { RadioGroupProps } from './types';
|
|
5
5
|
import { getNativeAccessibilityProps } from '../utils/accessibility';
|
|
6
|
+
import type { IdealystElement } from '../utils/refTypes';
|
|
6
7
|
|
|
7
8
|
const RadioGroupContext = React.createContext<{
|
|
8
9
|
value?: string;
|
|
@@ -12,7 +13,7 @@ const RadioGroupContext = React.createContext<{
|
|
|
12
13
|
|
|
13
14
|
export const useRadioGroup = () => React.useContext(RadioGroupContext);
|
|
14
15
|
|
|
15
|
-
const RadioGroup = forwardRef<
|
|
16
|
+
const RadioGroup = forwardRef<IdealystElement, RadioGroupProps>(({
|
|
16
17
|
value,
|
|
17
18
|
onValueChange,
|
|
18
19
|
disabled = false,
|
|
@@ -43,7 +44,7 @@ const RadioGroup = forwardRef<View, RadioGroupProps>(({
|
|
|
43
44
|
return (
|
|
44
45
|
<RadioGroupContext.Provider value={{ value, onValueChange, disabled }}>
|
|
45
46
|
<View
|
|
46
|
-
ref={ref}
|
|
47
|
+
ref={ref as any}
|
|
47
48
|
nativeID={id}
|
|
48
49
|
style={[
|
|
49
50
|
radioButtonStyles.groupContainer,
|
|
@@ -3,8 +3,9 @@ import { View } from 'react-native';
|
|
|
3
3
|
import { SvgUri } from 'react-native-svg';
|
|
4
4
|
import { SVGImageProps } from './types';
|
|
5
5
|
import { svgImageStyles } from './SVGImage.styles';
|
|
6
|
+
import type { IdealystElement } from '../utils/refTypes';
|
|
6
7
|
|
|
7
|
-
const SVGImage = forwardRef<
|
|
8
|
+
const SVGImage = forwardRef<IdealystElement, SVGImageProps>(({
|
|
8
9
|
source,
|
|
9
10
|
width,
|
|
10
11
|
height,
|
|
@@ -19,7 +20,7 @@ const SVGImage = forwardRef<View, SVGImageProps>(({
|
|
|
19
20
|
// Apply variants using Unistyles 3.0 pattern
|
|
20
21
|
if (intent) {
|
|
21
22
|
svgImageStyles.useVariants({
|
|
22
|
-
intent: intent as 'primary' | 'success' | '
|
|
23
|
+
intent: intent as 'primary' | 'success' | 'danger' | 'warning' | 'neutral',
|
|
23
24
|
});
|
|
24
25
|
}
|
|
25
26
|
|
|
@@ -31,7 +32,7 @@ const SVGImage = forwardRef<View, SVGImageProps>(({
|
|
|
31
32
|
if (typeof source === 'function') {
|
|
32
33
|
const SvgComponent = source;
|
|
33
34
|
return (
|
|
34
|
-
<View ref={ref} nativeID={id} style={[svgImageStyles.container, style]} testID={testID} {...props}>
|
|
35
|
+
<View ref={ref as any} nativeID={id} style={[svgImageStyles.container, style]} testID={testID} {...props}>
|
|
35
36
|
<SvgComponent
|
|
36
37
|
width={finalWidth}
|
|
37
38
|
height={finalHeight}
|
|
@@ -46,7 +47,7 @@ const SVGImage = forwardRef<View, SVGImageProps>(({
|
|
|
46
47
|
const sourceUri = typeof source === 'string' ? source : source.uri;
|
|
47
48
|
|
|
48
49
|
return (
|
|
49
|
-
<View ref={ref} nativeID={id} style={[svgImageStyles.container, style]} testID={testID} {...props}>
|
|
50
|
+
<View ref={ref as any} nativeID={id} style={[svgImageStyles.container, style]} testID={testID} {...props}>
|
|
50
51
|
<SvgUri
|
|
51
52
|
uri={sourceUri}
|
|
52
53
|
width={finalWidth}
|
|
@@ -18,22 +18,56 @@ export type SVGImageDynamicProps = {
|
|
|
18
18
|
/**
|
|
19
19
|
* SVGImage styles with intent-based coloring.
|
|
20
20
|
* Uses CSS filters on web and tintColor on native.
|
|
21
|
+
*
|
|
22
|
+
* Note: CSS filters are hardcoded per-intent because they can't be
|
|
23
|
+
* dynamically computed from color values.
|
|
21
24
|
*/
|
|
22
25
|
export const svgImageStyles = defineStyle('SVGImage', (theme: Theme) => ({
|
|
23
|
-
container: (
|
|
26
|
+
container: (_props: SVGImageDynamicProps) => ({
|
|
24
27
|
alignItems: 'center' as const,
|
|
25
28
|
justifyContent: 'center' as const,
|
|
26
|
-
|
|
27
|
-
|
|
29
|
+
variants: {
|
|
30
|
+
intent: {
|
|
31
|
+
primary: {
|
|
32
|
+
tintColor: theme.intents.primary.primary,
|
|
33
|
+
_web: {
|
|
34
|
+
filter: 'brightness(0) saturate(100%) invert(27%) sepia(51%) saturate(2878%) hue-rotate(346deg) brightness(104%) contrast(97%)',
|
|
35
|
+
},
|
|
36
|
+
},
|
|
37
|
+
success: {
|
|
38
|
+
tintColor: theme.intents.success.primary,
|
|
39
|
+
_web: {
|
|
40
|
+
filter: 'brightness(0) saturate(100%) invert(64%) sepia(88%) saturate(3323%) hue-rotate(84deg) brightness(119%) contrast(119%)',
|
|
41
|
+
},
|
|
42
|
+
},
|
|
43
|
+
danger: {
|
|
44
|
+
tintColor: theme.intents.danger.primary,
|
|
45
|
+
_web: {
|
|
46
|
+
filter: 'brightness(0) saturate(100%) invert(23%) sepia(89%) saturate(7395%) hue-rotate(4deg) brightness(102%) contrast(118%)',
|
|
47
|
+
},
|
|
48
|
+
},
|
|
49
|
+
warning: {
|
|
50
|
+
tintColor: theme.intents.warning.primary,
|
|
51
|
+
_web: {
|
|
52
|
+
filter: 'brightness(0) saturate(100%) invert(54%) sepia(98%) saturate(4341%) hue-rotate(21deg) brightness(101%) contrast(101%)',
|
|
53
|
+
},
|
|
54
|
+
},
|
|
55
|
+
neutral: {
|
|
56
|
+
tintColor: theme.intents.neutral.primary,
|
|
57
|
+
_web: {
|
|
58
|
+
filter: 'brightness(0) saturate(100%) invert(52%) sepia(23%) saturate(3207%) hue-rotate(314deg) brightness(99%) contrast(96%)',
|
|
59
|
+
},
|
|
60
|
+
},
|
|
61
|
+
info: {
|
|
62
|
+
tintColor: theme.intents.info.primary,
|
|
63
|
+
_web: {
|
|
64
|
+
filter: 'brightness(0) saturate(100%) invert(58%) sepia(96%) saturate(2582%) hue-rotate(165deg) brightness(99%) contrast(91%)',
|
|
65
|
+
},
|
|
66
|
+
},
|
|
67
|
+
},
|
|
68
|
+
},
|
|
28
69
|
_web: {
|
|
29
70
|
userSelect: 'none',
|
|
30
|
-
// Web: use CSS filters for intent coloring
|
|
31
|
-
...(intent === 'primary' ? { filter: 'brightness(0) saturate(100%) invert(27%) sepia(51%) saturate(2878%) hue-rotate(346deg) brightness(104%) contrast(97%)' } : {}),
|
|
32
|
-
...(intent === 'success' ? { filter: 'brightness(0) saturate(100%) invert(64%) sepia(88%) saturate(3323%) hue-rotate(84deg) brightness(119%) contrast(119%)' } : {}),
|
|
33
|
-
...(intent === 'error' ? { filter: 'brightness(0) saturate(100%) invert(23%) sepia(89%) saturate(7395%) hue-rotate(4deg) brightness(102%) contrast(118%)' } : {}),
|
|
34
|
-
...(intent === 'warning' ? { filter: 'brightness(0) saturate(100%) invert(54%) sepia(98%) saturate(4341%) hue-rotate(21deg) brightness(101%) contrast(101%)' } : {}),
|
|
35
|
-
...(intent === 'neutral' ? { filter: 'brightness(0) saturate(100%) invert(52%) sepia(23%) saturate(3207%) hue-rotate(314deg) brightness(99%) contrast(96%)' } : {}),
|
|
36
|
-
...(intent === 'info' ? { filter: 'brightness(0) saturate(100%) invert(58%) sepia(96%) saturate(2582%) hue-rotate(165deg) brightness(99%) contrast(91%)' } : {}),
|
|
37
71
|
},
|
|
38
72
|
}),
|
|
39
73
|
|
|
@@ -3,8 +3,9 @@ import { getWebProps } from 'react-native-unistyles/web';
|
|
|
3
3
|
import { SVGImageProps } from './types';
|
|
4
4
|
import { svgImageStyles } from './SVGImage.styles';
|
|
5
5
|
import useMergeRefs from '../hooks/useMergeRefs';
|
|
6
|
+
import type { IdealystElement } from '../utils/refTypes';
|
|
6
7
|
|
|
7
|
-
const SVGImage = forwardRef<
|
|
8
|
+
const SVGImage = forwardRef<IdealystElement, SVGImageProps>(({
|
|
8
9
|
source,
|
|
9
10
|
width,
|
|
10
11
|
height,
|
|
@@ -3,8 +3,9 @@ import { View as RNView, ScrollView as RNScrollView } from 'react-native';
|
|
|
3
3
|
import { useSafeAreaInsets } from 'react-native-safe-area-context';
|
|
4
4
|
import { ScreenProps } from './types';
|
|
5
5
|
import { screenStyles } from './Screen.styles';
|
|
6
|
+
import type { IdealystElement } from '../utils/refTypes';
|
|
6
7
|
|
|
7
|
-
const Screen = forwardRef<
|
|
8
|
+
const Screen = forwardRef<IdealystElement, ScreenProps>(({
|
|
8
9
|
children,
|
|
9
10
|
background = 'screen',
|
|
10
11
|
safeArea = true,
|
|
@@ -3,12 +3,13 @@ import { getWebProps } from 'react-native-unistyles/web';
|
|
|
3
3
|
import { ScreenProps } from './types';
|
|
4
4
|
import { screenStyles } from './Screen.styles';
|
|
5
5
|
import useMergeRefs from '../hooks/useMergeRefs';
|
|
6
|
+
import type { IdealystElement } from '../utils/refTypes';
|
|
6
7
|
|
|
7
8
|
/**
|
|
8
9
|
* Full-screen container for page layouts with background color and safe area support.
|
|
9
10
|
* Provides the outermost wrapper for screen-level content.
|
|
10
11
|
*/
|
|
11
|
-
const Screen = forwardRef<
|
|
12
|
+
const Screen = forwardRef<IdealystElement, ScreenProps>(({
|
|
12
13
|
children,
|
|
13
14
|
background = 'screen',
|
|
14
15
|
safeArea = false,
|
|
@@ -16,11 +16,12 @@ import { selectStyles } from './Select.styles';
|
|
|
16
16
|
import { BoundedModalContent } from '../internal/BoundedModalContent.native';
|
|
17
17
|
import { useSmartPosition } from '../hooks/useSmartPosition.native';
|
|
18
18
|
import useMergeRefs from '../hooks/useMergeRefs';
|
|
19
|
+
import type { IdealystElement } from '../utils/refTypes';
|
|
19
20
|
|
|
20
|
-
const Select = forwardRef<
|
|
21
|
+
const Select = forwardRef<IdealystElement, SelectProps>(({
|
|
21
22
|
options,
|
|
22
23
|
value,
|
|
23
|
-
|
|
24
|
+
onChange,
|
|
24
25
|
placeholder = 'Select an option',
|
|
25
26
|
disabled = false,
|
|
26
27
|
error = false,
|
|
@@ -146,7 +147,7 @@ const Select = forwardRef<View, SelectProps>(({
|
|
|
146
147
|
if (buttonIndex !== cancelButtonIndex && buttonIndex < options.length) {
|
|
147
148
|
const selectedOption = options[buttonIndex];
|
|
148
149
|
if (!selectedOption.disabled) {
|
|
149
|
-
|
|
150
|
+
onChange?.(selectedOption.value);
|
|
150
151
|
}
|
|
151
152
|
}
|
|
152
153
|
}
|
|
@@ -155,7 +156,7 @@ const Select = forwardRef<View, SelectProps>(({
|
|
|
155
156
|
|
|
156
157
|
const handleOptionSelect = (option: SelectOption) => {
|
|
157
158
|
if (!option.disabled) {
|
|
158
|
-
|
|
159
|
+
onChange?.(option.value);
|
|
159
160
|
closeDropdown();
|
|
160
161
|
}
|
|
161
162
|
};
|
|
@@ -318,7 +319,7 @@ const Select = forwardRef<View, SelectProps>(({
|
|
|
318
319
|
};
|
|
319
320
|
|
|
320
321
|
return (
|
|
321
|
-
<View ref={ref} nativeID={id} style={[containerStyle, style]} testID={testID}>
|
|
322
|
+
<View ref={ref as any} nativeID={id} style={[containerStyle, style]} testID={testID}>
|
|
322
323
|
{label && (
|
|
323
324
|
<Text style={labelStyle}>
|
|
324
325
|
{label}
|
|
@@ -260,7 +260,7 @@ export const selectStyles = defineStyle('Select', (theme: Theme) => ({
|
|
|
260
260
|
helperText: ({ error = false }: SelectDynamicProps) => ({
|
|
261
261
|
fontSize: 12,
|
|
262
262
|
marginTop: 4,
|
|
263
|
-
color: error ? theme.intents.
|
|
263
|
+
color: error ? theme.intents.danger.primary : theme.colors.text.secondary,
|
|
264
264
|
}),
|
|
265
265
|
|
|
266
266
|
overlay: (_props: SelectDynamicProps) => ({
|
|
@@ -6,15 +6,16 @@ import useMergeRefs from '../hooks/useMergeRefs';
|
|
|
6
6
|
import { PositionedPortal } from '../internal/PositionedPortal';
|
|
7
7
|
import { selectStyles } from './Select.styles';
|
|
8
8
|
import { SelectOption, SelectProps } from './types';
|
|
9
|
+
import type { IdealystElement } from '../utils/refTypes';
|
|
9
10
|
|
|
10
11
|
/**
|
|
11
12
|
* Dropdown selection component with search, keyboard navigation, and custom option rendering.
|
|
12
13
|
* Supports single selection with filterable options list.
|
|
13
14
|
*/
|
|
14
|
-
const Select = forwardRef<
|
|
15
|
+
const Select = forwardRef<IdealystElement, SelectProps>(({
|
|
15
16
|
options,
|
|
16
17
|
value,
|
|
17
|
-
|
|
18
|
+
onChange,
|
|
18
19
|
placeholder = 'Select an option',
|
|
19
20
|
disabled = false,
|
|
20
21
|
error = false,
|
|
@@ -166,7 +167,7 @@ const Select = forwardRef<HTMLDivElement, SelectProps>(({
|
|
|
166
167
|
|
|
167
168
|
const handleOptionSelect = (option: SelectOption) => {
|
|
168
169
|
if (!option.disabled) {
|
|
169
|
-
|
|
170
|
+
onChange?.(option.value);
|
|
170
171
|
setIsOpen(false);
|
|
171
172
|
setSearchTerm('');
|
|
172
173
|
triggerRef.current?.focus();
|
package/src/Select/types.ts
CHANGED
|
@@ -49,7 +49,7 @@ export interface SelectProps extends FormInputStyleProps, FormAccessibilityProps
|
|
|
49
49
|
/**
|
|
50
50
|
* Called when the selected value changes
|
|
51
51
|
*/
|
|
52
|
-
|
|
52
|
+
onChange?: (value: string) => void;
|
|
53
53
|
|
|
54
54
|
/**
|
|
55
55
|
* Placeholder text when no value is selected
|
|
@@ -11,8 +11,9 @@ import Animated, {
|
|
|
11
11
|
import { skeletonStyles } from './Skeleton.styles';
|
|
12
12
|
import type { SkeletonProps, SkeletonGroupProps } from './types';
|
|
13
13
|
import { getNativeLiveRegionAccessibilityProps } from '../utils/accessibility';
|
|
14
|
+
import type { IdealystElement } from '../utils/refTypes';
|
|
14
15
|
|
|
15
|
-
const Skeleton = forwardRef<
|
|
16
|
+
const Skeleton = forwardRef<IdealystElement, SkeletonProps>(({
|
|
16
17
|
width: _width = '100%',
|
|
17
18
|
height: _height = 20,
|
|
18
19
|
shape = 'rectangle',
|
|
@@ -39,7 +39,7 @@ const Skeleton: React.FC<SkeletonProps> = ({
|
|
|
39
39
|
animation,
|
|
40
40
|
});
|
|
41
41
|
|
|
42
|
-
const skeletonProps = getWebProps([skeletonStyles.skeleton, style as any]);
|
|
42
|
+
const skeletonProps = getWebProps([skeletonStyles.skeleton({}), style as any]);
|
|
43
43
|
|
|
44
44
|
// Apply custom border radius if provided and shape is 'rounded'
|
|
45
45
|
const customStyles: React.CSSProperties = {
|
|
@@ -8,8 +8,9 @@ import Text from '../Text';
|
|
|
8
8
|
import type { SliderProps } from './types';
|
|
9
9
|
import { isIconName } from '../Icon/icon-resolver';
|
|
10
10
|
import { getNativeRangeAccessibilityProps } from '../utils/accessibility';
|
|
11
|
+
import type { IdealystElement } from '../utils/refTypes';
|
|
11
12
|
|
|
12
|
-
const Slider = forwardRef<
|
|
13
|
+
const Slider = forwardRef<IdealystElement, SliderProps>(({
|
|
13
14
|
value: controlledValue,
|
|
14
15
|
defaultValue = 0,
|
|
15
16
|
min = 0,
|
|
@@ -26,8 +27,8 @@ const Slider = forwardRef<View, SliderProps>(({
|
|
|
26
27
|
margin,
|
|
27
28
|
marginVertical,
|
|
28
29
|
marginHorizontal,
|
|
29
|
-
|
|
30
|
-
|
|
30
|
+
onChange,
|
|
31
|
+
onChangeCommit,
|
|
31
32
|
style,
|
|
32
33
|
testID,
|
|
33
34
|
id,
|
|
@@ -79,12 +80,12 @@ const Slider = forwardRef<View, SliderProps>(({
|
|
|
79
80
|
setInternalValue(newValue);
|
|
80
81
|
}
|
|
81
82
|
|
|
82
|
-
|
|
83
|
-
}, [controlledValue,
|
|
83
|
+
onChange?.(newValue);
|
|
84
|
+
}, [controlledValue, onChange]);
|
|
84
85
|
|
|
85
86
|
const commitValue = useCallback((finalValue: number) => {
|
|
86
|
-
|
|
87
|
-
}, [
|
|
87
|
+
onChangeCommit?.(finalValue);
|
|
88
|
+
}, [onChangeCommit]);
|
|
88
89
|
|
|
89
90
|
// Generate native accessibility props
|
|
90
91
|
const nativeA11yProps = useMemo(() => {
|
|
@@ -211,7 +212,7 @@ const Slider = forwardRef<View, SliderProps>(({
|
|
|
211
212
|
const trackStyle = (sliderStyles.track as any)({});
|
|
212
213
|
|
|
213
214
|
return (
|
|
214
|
-
<View ref={ref} nativeID={id} style={[containerStyle, style]} testID={testID} {...nativeA11yProps}>
|
|
215
|
+
<View ref={ref as any} nativeID={id} style={[containerStyle, style]} testID={testID} {...nativeA11yProps}>
|
|
215
216
|
{showValue && (
|
|
216
217
|
<View style={sliderStyles.valueLabel as any}>
|
|
217
218
|
<Text>{value}</Text>
|
|
@@ -6,12 +6,13 @@ import { IconSvg } from '../Icon/IconSvg/IconSvg.web';
|
|
|
6
6
|
import { isIconName } from '../Icon/icon-resolver';
|
|
7
7
|
import useMergeRefs from '../hooks/useMergeRefs';
|
|
8
8
|
import { getWebRangeAriaProps, generateAccessibilityId, SLIDER_KEYS, matchesKey } from '../utils/accessibility';
|
|
9
|
+
import type { IdealystElement } from '../utils/refTypes';
|
|
9
10
|
|
|
10
11
|
/**
|
|
11
12
|
* Range slider for selecting numeric values within a min/max range.
|
|
12
13
|
* Supports marks, value labels, keyboard navigation, and custom step increments.
|
|
13
14
|
*/
|
|
14
|
-
const Slider = forwardRef<
|
|
15
|
+
const Slider = forwardRef<IdealystElement, SliderProps>(({
|
|
15
16
|
value: controlledValue,
|
|
16
17
|
defaultValue = 0,
|
|
17
18
|
min = 0,
|
|
@@ -28,8 +29,8 @@ const Slider = forwardRef<HTMLDivElement, SliderProps>(({
|
|
|
28
29
|
margin,
|
|
29
30
|
marginVertical,
|
|
30
31
|
marginHorizontal,
|
|
31
|
-
|
|
32
|
-
|
|
32
|
+
onChange,
|
|
33
|
+
onChangeCommit,
|
|
33
34
|
style,
|
|
34
35
|
testID,
|
|
35
36
|
id,
|
|
@@ -93,8 +94,8 @@ const Slider = forwardRef<HTMLDivElement, SliderProps>(({
|
|
|
93
94
|
setInternalValue(clampedValue);
|
|
94
95
|
}
|
|
95
96
|
|
|
96
|
-
|
|
97
|
-
}, [controlledValue, clampValue,
|
|
97
|
+
onChange?.(clampedValue);
|
|
98
|
+
}, [controlledValue, clampValue, onChange]);
|
|
98
99
|
|
|
99
100
|
const handleMouseDown = useCallback((e: React.MouseEvent) => {
|
|
100
101
|
if (disabled) return;
|
|
@@ -129,11 +130,11 @@ const Slider = forwardRef<HTMLDivElement, SliderProps>(({
|
|
|
129
130
|
if (isDragging) {
|
|
130
131
|
setIsDragging(false);
|
|
131
132
|
if (hasMoved.current) {
|
|
132
|
-
|
|
133
|
+
onChangeCommit?.(value);
|
|
133
134
|
}
|
|
134
135
|
hasMoved.current = false;
|
|
135
136
|
}
|
|
136
|
-
}, [isDragging, value,
|
|
137
|
+
}, [isDragging, value, onChangeCommit]);
|
|
137
138
|
|
|
138
139
|
// Handle keyboard navigation for accessibility
|
|
139
140
|
const handleKeyDown = useCallback((e: React.KeyboardEvent) => {
|
|
@@ -164,9 +165,9 @@ const Slider = forwardRef<HTMLDivElement, SliderProps>(({
|
|
|
164
165
|
|
|
165
166
|
if (newValue !== value) {
|
|
166
167
|
updateValue(newValue);
|
|
167
|
-
|
|
168
|
+
onChangeCommit?.(newValue);
|
|
168
169
|
}
|
|
169
|
-
}, [disabled, value, step, min, max, clampValue, updateValue,
|
|
170
|
+
}, [disabled, value, step, min, max, clampValue, updateValue, onChangeCommit]);
|
|
170
171
|
|
|
171
172
|
// Generate unique ID for accessibility
|
|
172
173
|
const sliderId = useMemo(() => id || generateAccessibilityId('slider'), [id]);
|
package/src/Slider/types.ts
CHANGED
|
@@ -28,8 +28,15 @@ export interface SliderProps extends FormInputStyleProps, RangeAccessibilityProp
|
|
|
28
28
|
intent?: SliderIntentVariant;
|
|
29
29
|
size?: SliderSizeVariant;
|
|
30
30
|
icon?: IconName | React.ReactNode;
|
|
31
|
-
|
|
32
|
-
|
|
31
|
+
/**
|
|
32
|
+
* Called when the slider value changes during interaction
|
|
33
|
+
*/
|
|
34
|
+
onChange?: (value: number) => void;
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* Called when the user finishes interacting with the slider
|
|
38
|
+
*/
|
|
39
|
+
onChangeCommit?: (value: number) => void;
|
|
33
40
|
style?: StyleProp<ViewStyle>;
|
|
34
41
|
testID?: string;
|
|
35
42
|
}
|
|
@@ -1,14 +1,15 @@
|
|
|
1
|
-
import React, {
|
|
1
|
+
import React, { forwardRef, useMemo } from 'react';
|
|
2
2
|
import { Pressable } from 'react-native';
|
|
3
3
|
import Animated, { useSharedValue, useAnimatedStyle, withSpring } from 'react-native-reanimated';
|
|
4
4
|
import { switchStyles } from './Switch.styles';
|
|
5
5
|
import Text from '../Text';
|
|
6
6
|
import type { SwitchProps } from './types';
|
|
7
7
|
import { getNativeSelectionAccessibilityProps } from '../utils/accessibility';
|
|
8
|
+
import type { IdealystElement } from '../utils/refTypes';
|
|
8
9
|
|
|
9
|
-
const Switch = forwardRef<
|
|
10
|
+
const Switch = forwardRef<IdealystElement, SwitchProps>(({
|
|
10
11
|
checked = false,
|
|
11
|
-
|
|
12
|
+
onChange,
|
|
12
13
|
disabled = false,
|
|
13
14
|
label,
|
|
14
15
|
labelPosition = 'right',
|
|
@@ -50,8 +51,8 @@ const Switch = forwardRef<ComponentRef<typeof Pressable>, SwitchProps>(({
|
|
|
50
51
|
}, [checked, progress]);
|
|
51
52
|
|
|
52
53
|
const handlePress = () => {
|
|
53
|
-
if (!disabled &&
|
|
54
|
-
|
|
54
|
+
if (!disabled && onChange) {
|
|
55
|
+
onChange(!checked);
|
|
55
56
|
}
|
|
56
57
|
};
|
|
57
58
|
|
|
@@ -160,7 +161,7 @@ const Switch = forwardRef<ComponentRef<typeof Pressable>, SwitchProps>(({
|
|
|
160
161
|
if (label) {
|
|
161
162
|
return (
|
|
162
163
|
<Pressable
|
|
163
|
-
ref={ref}
|
|
164
|
+
ref={ref as any}
|
|
164
165
|
nativeID={id}
|
|
165
166
|
onPress={handlePress}
|
|
166
167
|
disabled={disabled}
|