@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.
Files changed (143) hide show
  1. package/README.md +3 -3
  2. package/package.json +4 -4
  3. package/plugin/__tests__/web.test.ts +2 -2
  4. package/plugin/web.js +2 -0
  5. package/src/Accordion/Accordion.native.tsx +3 -2
  6. package/src/ActivityIndicator/ActivityIndicator.native.tsx +4 -2
  7. package/src/ActivityIndicator/ActivityIndicator.styles.tsx +22 -27
  8. package/src/ActivityIndicator/ActivityIndicator.web.tsx +17 -29
  9. package/src/Alert/Alert.native.tsx +20 -10
  10. package/src/Alert/Alert.styles.tsx +173 -86
  11. package/src/Alert/Alert.web.tsx +34 -30
  12. package/src/Alert/types.ts +53 -3
  13. package/src/Avatar/Avatar.native.tsx +3 -2
  14. package/src/Avatar/Avatar.web.tsx +2 -1
  15. package/src/Avatar/types.ts +1 -1
  16. package/src/Badge/Badge.native.tsx +18 -6
  17. package/src/Badge/Badge.styles.tsx +22 -5
  18. package/src/Badge/Badge.web.tsx +12 -4
  19. package/src/Badge/types.ts +14 -2
  20. package/src/Breadcrumb/Breadcrumb.native.tsx +3 -2
  21. package/src/Button/Button.native.tsx +16 -6
  22. package/src/Button/Button.styles.tsx +2 -2
  23. package/src/Button/Button.web.tsx +19 -15
  24. package/src/Button/types.ts +6 -10
  25. package/src/Card/Card.native.tsx +27 -3
  26. package/src/Card/Card.web.tsx +30 -4
  27. package/src/Card/types.ts +15 -0
  28. package/src/Checkbox/Checkbox.native.tsx +5 -4
  29. package/src/Checkbox/Checkbox.styles.tsx +62 -52
  30. package/src/Checkbox/Checkbox.web.tsx +4 -3
  31. package/src/Checkbox/types.ts +1 -1
  32. package/src/Chip/Chip.native.tsx +30 -7
  33. package/src/Chip/Chip.web.tsx +28 -5
  34. package/src/Chip/types.ts +15 -0
  35. package/src/Dialog/Dialog.native.tsx +6 -6
  36. package/src/Dialog/Dialog.web.tsx +5 -5
  37. package/src/Dialog/types.ts +2 -2
  38. package/src/Divider/Divider.native.tsx +20 -17
  39. package/src/Divider/Divider.styles.tsx +51 -29
  40. package/src/Divider/Divider.web.tsx +5 -4
  41. package/src/Divider/types.ts +3 -3
  42. package/src/Icon/Icon.native.tsx +3 -2
  43. package/src/Icon/Icon.web.tsx +2 -1
  44. package/src/Icon/IconSvg/IconSvg.native.tsx +3 -2
  45. package/src/IconButton/IconButton.native.tsx +219 -0
  46. package/src/IconButton/IconButton.styles.tsx +127 -0
  47. package/src/IconButton/IconButton.web.tsx +198 -0
  48. package/src/IconButton/index.native.ts +5 -0
  49. package/src/IconButton/index.ts +5 -0
  50. package/src/IconButton/index.web.ts +5 -0
  51. package/src/IconButton/types.ts +84 -0
  52. package/src/Image/Image.native.tsx +3 -2
  53. package/src/Input/Input.native.tsx +42 -290
  54. package/src/Input/Input.styles.tsx +1 -1
  55. package/src/Input/Input.web.tsx +37 -288
  56. package/src/Input/index.native.ts +9 -2
  57. package/src/Input/index.ts +8 -1
  58. package/src/Input/index.web.ts +8 -1
  59. package/src/Input/types.ts +1 -1
  60. package/src/List/List.native.tsx +3 -2
  61. package/src/List/ListItem.native.tsx +3 -2
  62. package/src/List/ListSection.native.tsx +3 -2
  63. package/src/Menu/Menu.native.tsx +2 -1
  64. package/src/Menu/Menu.styles.tsx +79 -29
  65. package/src/Menu/Menu.web.tsx +2 -1
  66. package/src/Menu/MenuItem.native.tsx +4 -3
  67. package/src/Menu/MenuItem.styles.tsx +81 -32
  68. package/src/Menu/MenuItem.web.tsx +2 -1
  69. package/src/Menu/docs.ts +1 -1
  70. package/src/Popover/Popover.native.tsx +2 -1
  71. package/src/Popover/Popover.web.tsx +2 -1
  72. package/src/Popover/types.ts +15 -4
  73. package/src/Pressable/Pressable.native.tsx +3 -2
  74. package/src/Pressable/Pressable.web.tsx +3 -5
  75. package/src/Progress/Progress.native.tsx +5 -4
  76. package/src/Progress/Progress.web.tsx +3 -3
  77. package/src/Progress/types.ts +3 -3
  78. package/src/RadioButton/RadioButton.native.tsx +4 -3
  79. package/src/RadioButton/RadioButton.styles.tsx +53 -33
  80. package/src/RadioButton/RadioGroup.native.tsx +3 -2
  81. package/src/SVGImage/SVGImage.native.tsx +5 -4
  82. package/src/SVGImage/SVGImage.styles.tsx +44 -10
  83. package/src/SVGImage/SVGImage.web.tsx +2 -1
  84. package/src/Screen/Screen.native.tsx +2 -1
  85. package/src/Screen/Screen.web.tsx +2 -1
  86. package/src/Select/Select.native.tsx +6 -5
  87. package/src/Select/Select.styles.tsx +1 -1
  88. package/src/Select/Select.web.tsx +4 -3
  89. package/src/Select/types.ts +1 -1
  90. package/src/Skeleton/Skeleton.native.tsx +2 -1
  91. package/src/Skeleton/Skeleton.web.tsx +1 -1
  92. package/src/Slider/Slider.native.tsx +9 -8
  93. package/src/Slider/Slider.web.tsx +10 -9
  94. package/src/Slider/types.ts +9 -2
  95. package/src/Switch/Switch.native.tsx +7 -6
  96. package/src/Switch/Switch.styles.tsx +52 -17
  97. package/src/Switch/Switch.web.tsx +15 -16
  98. package/src/Switch/types.ts +44 -4
  99. package/src/TabBar/TabBar.native.tsx +3 -2
  100. package/src/Text/Text.native.tsx +3 -2
  101. package/src/Text/Text.web.tsx +2 -1
  102. package/src/TextArea/TextArea.native.tsx +3 -2
  103. package/src/TextArea/TextArea.styles.tsx +2 -2
  104. package/src/TextArea/TextArea.web.tsx +2 -1
  105. package/src/TextInput/TextInput.native.tsx +300 -0
  106. package/src/TextInput/TextInput.styles.tsx +207 -0
  107. package/src/TextInput/TextInput.web.tsx +301 -0
  108. package/src/TextInput/index.native.ts +3 -0
  109. package/src/TextInput/index.ts +5 -0
  110. package/src/TextInput/index.web.ts +5 -0
  111. package/src/TextInput/types.ts +163 -0
  112. package/src/Tooltip/Tooltip.native.tsx +3 -2
  113. package/src/Video/Video.native.tsx +4 -3
  114. package/src/View/View.native.tsx +2 -1
  115. package/src/View/View.styles.tsx +1 -0
  116. package/src/View/View.web.tsx +9 -2
  117. package/src/examples/ActivityIndicatorExamples.tsx +177 -0
  118. package/src/examples/AlertExamples.tsx +5 -5
  119. package/src/examples/ButtonExamples.tsx +12 -12
  120. package/src/examples/CardExamples.tsx +1 -1
  121. package/src/examples/CheckboxExamples.tsx +2 -2
  122. package/src/examples/ChipExamples.tsx +6 -6
  123. package/src/examples/DialogExamples.tsx +1 -1
  124. package/src/examples/DividerExamples.tsx +1 -1
  125. package/src/examples/InputExamples.tsx +1 -1
  126. package/src/examples/LinkExamples.tsx +1 -1
  127. package/src/examples/ListExamples.tsx +1 -1
  128. package/src/examples/MenuExamples.tsx +2 -2
  129. package/src/examples/ProgressExamples.tsx +1 -1
  130. package/src/examples/RadioButtonExamples.tsx +5 -5
  131. package/src/examples/SVGImageExamples.tsx +1 -1
  132. package/src/examples/SelectExamples.tsx +1 -1
  133. package/src/examples/SliderExamples.tsx +5 -5
  134. package/src/examples/SwitchExamples.tsx +26 -26
  135. package/src/examples/TableExamples.tsx +1 -1
  136. package/src/examples/TooltipExamples.tsx +2 -2
  137. package/src/examples/index.ts +1 -0
  138. package/src/extensions/index.ts +1 -0
  139. package/src/extensions/types.ts +22 -3
  140. package/src/index.native.ts +4 -0
  141. package/src/index.ts +27 -2
  142. package/src/utils/index.ts +12 -0
  143. 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: ({ intent = 'primary', checked = false, disabled = false }: RadioButtonDynamicProps) => {
53
- const intentValue = theme.intents[intent];
54
-
55
- return {
56
- borderRadius: 9999,
57
- borderWidth: 1.5,
58
- borderStyle: 'solid' as const,
59
- alignItems: 'center' as const,
60
- justifyContent: 'center' as const,
61
- backgroundColor: disabled
62
- ? theme.colors.surface.tertiary
63
- : theme.colors.surface.primary,
64
- borderColor: checked ? intentValue.primary : theme.colors.border.primary,
65
- opacity: disabled ? 0.5 : 1,
66
- variants: {
67
- size: {
68
- width: theme.sizes.$radioButton.radioSize,
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
- _web: {
73
- transition: 'all 0.2s ease',
74
- cursor: disabled ? 'not-allowed' : 'pointer',
75
- _hover: disabled ? {} : { opacity: 0.8 },
76
- _active: disabled ? {} : { opacity: 0.6 },
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
- } as const;
79
- },
81
+ },
82
+ _web: {
83
+ transition: 'all 0.2s ease',
84
+ },
85
+ }),
80
86
 
81
- radioDot: ({ intent = 'primary' }: RadioButtonDynamicProps) => ({
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: ({ disabled = false }: RadioButtonDynamicProps) => ({
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: ({ orientation = 'vertical' }: RadioButtonDynamicProps) => ({
113
+ groupContainer: (_props: RadioButtonDynamicProps) => ({
103
114
  gap: 4,
104
- flexDirection: orientation === 'horizontal' ? ('row' as const) : ('column' as const),
105
- flexWrap: orientation === 'horizontal' ? ('wrap' as const) : undefined,
106
- ...(orientation === 'horizontal' ? { gap: 16 } : {}),
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<View, RadioGroupProps>(({
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<View, SVGImageProps>(({
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' | 'error' | 'warning' | 'neutral',
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: ({ intent }: SVGImageDynamicProps) => ({
26
+ container: (_props: SVGImageDynamicProps) => ({
24
27
  alignItems: 'center' as const,
25
28
  justifyContent: 'center' as const,
26
- // Native: use tintColor for intent
27
- ...(intent ? { tintColor: theme.intents[intent].primary } : {}),
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<HTMLDivElement, SVGImageProps>(({
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<RNView | RNScrollView, ScreenProps>(({
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<HTMLDivElement, ScreenProps>(({
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<View, SelectProps>(({
21
+ const Select = forwardRef<IdealystElement, SelectProps>(({
21
22
  options,
22
23
  value,
23
- onValueChange,
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
- onValueChange?.(selectedOption.value);
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
- onValueChange?.(option.value);
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.error.primary : theme.colors.text.secondary,
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<HTMLDivElement, SelectProps>(({
15
+ const Select = forwardRef<IdealystElement, SelectProps>(({
15
16
  options,
16
17
  value,
17
- onValueChange,
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
- onValueChange?.(option.value);
170
+ onChange?.(option.value);
170
171
  setIsOpen(false);
171
172
  setSearchTerm('');
172
173
  triggerRef.current?.focus();
@@ -49,7 +49,7 @@ export interface SelectProps extends FormInputStyleProps, FormAccessibilityProps
49
49
  /**
50
50
  * Called when the selected value changes
51
51
  */
52
- onValueChange?: (value: string) => void;
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<View, SkeletonProps>(({
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<View, SliderProps>(({
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
- onValueChange,
30
- onValueCommit,
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
- onValueChange?.(newValue);
83
- }, [controlledValue, onValueChange]);
83
+ onChange?.(newValue);
84
+ }, [controlledValue, onChange]);
84
85
 
85
86
  const commitValue = useCallback((finalValue: number) => {
86
- onValueCommit?.(finalValue);
87
- }, [onValueCommit]);
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<HTMLDivElement, SliderProps>(({
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
- onValueChange,
32
- onValueCommit,
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
- onValueChange?.(clampedValue);
97
- }, [controlledValue, clampValue, onValueChange]);
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
- onValueCommit?.(value);
133
+ onChangeCommit?.(value);
133
134
  }
134
135
  hasMoved.current = false;
135
136
  }
136
- }, [isDragging, value, onValueCommit]);
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
- onValueCommit?.(newValue);
168
+ onChangeCommit?.(newValue);
168
169
  }
169
- }, [disabled, value, step, min, max, clampValue, updateValue, onValueCommit]);
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]);
@@ -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
- onValueChange?: (value: number) => void;
32
- onValueCommit?: (value: number) => void;
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, { ComponentRef, forwardRef, useMemo } from '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<ComponentRef<typeof Pressable>, SwitchProps>(({
10
+ const Switch = forwardRef<IdealystElement, SwitchProps>(({
10
11
  checked = false,
11
- onCheckedChange,
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 && onCheckedChange) {
54
- onCheckedChange(!checked);
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}