@idealyst/components 1.2.29 → 1.2.30

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 (131) hide show
  1. package/README.md +3 -3
  2. package/package.json +3 -3
  3. package/plugin/__tests__/web.test.ts +2 -2
  4. package/src/Accordion/Accordion.native.tsx +3 -2
  5. package/src/ActivityIndicator/ActivityIndicator.native.tsx +3 -2
  6. package/src/ActivityIndicator/ActivityIndicator.styles.tsx +25 -26
  7. package/src/ActivityIndicator/ActivityIndicator.web.tsx +2 -1
  8. package/src/Alert/Alert.native.tsx +20 -10
  9. package/src/Alert/Alert.styles.tsx +148 -86
  10. package/src/Alert/Alert.web.tsx +10 -5
  11. package/src/Alert/types.ts +53 -3
  12. package/src/Avatar/Avatar.native.tsx +3 -2
  13. package/src/Avatar/Avatar.web.tsx +2 -1
  14. package/src/Avatar/types.ts +1 -1
  15. package/src/Badge/Badge.native.tsx +18 -6
  16. package/src/Badge/Badge.styles.tsx +22 -5
  17. package/src/Badge/Badge.web.tsx +12 -4
  18. package/src/Badge/types.ts +14 -2
  19. package/src/Breadcrumb/Breadcrumb.native.tsx +3 -2
  20. package/src/Button/Button.native.tsx +16 -6
  21. package/src/Button/Button.styles.tsx +2 -2
  22. package/src/Button/Button.web.tsx +19 -15
  23. package/src/Button/types.ts +6 -10
  24. package/src/Card/Card.native.tsx +27 -3
  25. package/src/Card/Card.web.tsx +30 -4
  26. package/src/Card/types.ts +15 -0
  27. package/src/Checkbox/Checkbox.native.tsx +5 -4
  28. package/src/Checkbox/Checkbox.styles.tsx +62 -52
  29. package/src/Checkbox/Checkbox.web.tsx +4 -3
  30. package/src/Checkbox/types.ts +1 -1
  31. package/src/Chip/Chip.native.tsx +30 -7
  32. package/src/Chip/Chip.styles.tsx +142 -124
  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/Image/Image.native.tsx +3 -2
  46. package/src/Input/Input.native.tsx +42 -290
  47. package/src/Input/Input.styles.tsx +1 -1
  48. package/src/Input/Input.web.tsx +37 -288
  49. package/src/Input/index.native.ts +9 -2
  50. package/src/Input/index.ts +8 -1
  51. package/src/Input/index.web.ts +8 -1
  52. package/src/Input/types.ts +1 -1
  53. package/src/List/List.native.tsx +3 -2
  54. package/src/List/ListItem.native.tsx +3 -2
  55. package/src/List/ListSection.native.tsx +3 -2
  56. package/src/Menu/Menu.native.tsx +2 -1
  57. package/src/Menu/Menu.styles.tsx +79 -29
  58. package/src/Menu/Menu.web.tsx +2 -1
  59. package/src/Menu/MenuItem.native.tsx +4 -3
  60. package/src/Menu/MenuItem.styles.tsx +81 -32
  61. package/src/Menu/MenuItem.web.tsx +2 -1
  62. package/src/Menu/docs.ts +1 -1
  63. package/src/Popover/Popover.native.tsx +2 -1
  64. package/src/Popover/Popover.web.tsx +2 -1
  65. package/src/Popover/types.ts +15 -4
  66. package/src/Pressable/Pressable.native.tsx +3 -2
  67. package/src/Pressable/Pressable.web.tsx +3 -5
  68. package/src/Progress/Progress.native.tsx +5 -4
  69. package/src/Progress/Progress.web.tsx +3 -3
  70. package/src/Progress/types.ts +3 -3
  71. package/src/RadioButton/RadioButton.native.tsx +4 -3
  72. package/src/RadioButton/RadioButton.styles.tsx +53 -33
  73. package/src/RadioButton/RadioGroup.native.tsx +3 -2
  74. package/src/SVGImage/SVGImage.native.tsx +5 -4
  75. package/src/SVGImage/SVGImage.styles.tsx +44 -10
  76. package/src/SVGImage/SVGImage.web.tsx +2 -1
  77. package/src/Screen/Screen.native.tsx +2 -1
  78. package/src/Screen/Screen.web.tsx +2 -1
  79. package/src/Select/Select.native.tsx +6 -5
  80. package/src/Select/Select.styles.tsx +1 -1
  81. package/src/Select/Select.web.tsx +4 -3
  82. package/src/Select/types.ts +1 -1
  83. package/src/Skeleton/Skeleton.native.tsx +2 -1
  84. package/src/Slider/Slider.native.tsx +9 -8
  85. package/src/Slider/Slider.web.tsx +10 -9
  86. package/src/Slider/types.ts +9 -2
  87. package/src/Switch/Switch.native.tsx +7 -6
  88. package/src/Switch/Switch.styles.tsx +35 -17
  89. package/src/Switch/Switch.web.tsx +8 -7
  90. package/src/Switch/types.ts +44 -4
  91. package/src/TabBar/TabBar.native.tsx +3 -2
  92. package/src/Text/Text.native.tsx +3 -2
  93. package/src/Text/Text.web.tsx +2 -1
  94. package/src/TextArea/TextArea.native.tsx +3 -2
  95. package/src/TextArea/TextArea.styles.tsx +2 -2
  96. package/src/TextArea/TextArea.web.tsx +2 -1
  97. package/src/TextInput/TextInput.native.tsx +300 -0
  98. package/src/TextInput/TextInput.styles.tsx +207 -0
  99. package/src/TextInput/TextInput.web.tsx +301 -0
  100. package/src/TextInput/index.native.ts +3 -0
  101. package/src/TextInput/index.ts +5 -0
  102. package/src/TextInput/index.web.ts +5 -0
  103. package/src/TextInput/types.ts +163 -0
  104. package/src/Tooltip/Tooltip.native.tsx +3 -2
  105. package/src/Video/Video.native.tsx +4 -3
  106. package/src/View/View.native.tsx +2 -1
  107. package/src/View/View.web.tsx +2 -1
  108. package/src/examples/AlertExamples.tsx +5 -5
  109. package/src/examples/ButtonExamples.tsx +12 -12
  110. package/src/examples/CardExamples.tsx +1 -1
  111. package/src/examples/CheckboxExamples.tsx +2 -2
  112. package/src/examples/ChipExamples.tsx +6 -6
  113. package/src/examples/DialogExamples.tsx +1 -1
  114. package/src/examples/DividerExamples.tsx +1 -1
  115. package/src/examples/InputExamples.tsx +1 -1
  116. package/src/examples/LinkExamples.tsx +1 -1
  117. package/src/examples/ListExamples.tsx +1 -1
  118. package/src/examples/MenuExamples.tsx +2 -2
  119. package/src/examples/ProgressExamples.tsx +1 -1
  120. package/src/examples/RadioButtonExamples.tsx +5 -5
  121. package/src/examples/SVGImageExamples.tsx +1 -1
  122. package/src/examples/SelectExamples.tsx +1 -1
  123. package/src/examples/SliderExamples.tsx +5 -5
  124. package/src/examples/SwitchExamples.tsx +2 -2
  125. package/src/examples/TableExamples.tsx +1 -1
  126. package/src/examples/TooltipExamples.tsx +2 -2
  127. package/src/extensions/index.ts +1 -0
  128. package/src/extensions/types.ts +10 -3
  129. package/src/index.ts +23 -2
  130. package/src/utils/index.ts +12 -0
  131. package/src/utils/refTypes.ts +50 -0
@@ -1,5 +1,12 @@
1
+ /**
2
+ * @ignore
3
+ * @deprecated Use TextInput instead. Input is maintained for backwards compatibility only.
4
+ */
1
5
  import InputComponent from './Input.web';
2
6
 
7
+ // Re-export deprecated Input component
3
8
  export default InputComponent;
4
9
  export { InputComponent as Input };
5
- export * from './types';
10
+
11
+ // Re-export types from TextInput for backwards compatibility
12
+ export * from '../TextInput/types';
@@ -1,5 +1,12 @@
1
+ /**
2
+ * @ignore
3
+ * @deprecated Use TextInput instead. Input is maintained for backwards compatibility only.
4
+ */
1
5
  import InputComponent from './Input.web';
2
6
 
7
+ // Re-export deprecated Input component
3
8
  export default InputComponent;
4
9
  export { InputComponent as Input };
5
- export * from './types';
10
+
11
+ // Re-export types from TextInput for backwards compatibility
12
+ export * from '../TextInput/types';
@@ -98,7 +98,7 @@ export interface InputProps extends FormInputStyleProps, FormAccessibilityProps
98
98
 
99
99
  /**
100
100
  * Whether the input has an error state
101
- * @deprecated Use intent="error" instead
101
+ * @deprecated Use intent="danger" instead
102
102
  */
103
103
  hasError?: boolean;
104
104
 
@@ -4,8 +4,9 @@ import { listStyles } from './List.styles';
4
4
  import type { ListProps } from './types';
5
5
  import { ListProvider } from './ListContext';
6
6
  import { getNativeAccessibilityProps } from '../utils/accessibility';
7
+ import type { IdealystElement } from '../utils/refTypes';
7
8
 
8
- const List = forwardRef<View, ListProps>(({
9
+ const List = forwardRef<IdealystElement, ListProps>(({
9
10
  children,
10
11
  type = 'default',
11
12
  size = 'md',
@@ -92,7 +93,7 @@ const List = forwardRef<View, ListProps>(({
92
93
  }
93
94
 
94
95
  return (
95
- <View ref={ref} nativeID={id} style={containerStyle as any} testID={testID} {...nativeA11yProps}>
96
+ <View ref={ref as any} nativeID={id} style={containerStyle as any} testID={testID} {...nativeA11yProps}>
96
97
  {content}
97
98
  </View>
98
99
  );
@@ -1,4 +1,4 @@
1
- import { isValidElement, forwardRef, ComponentRef, useMemo } from 'react';
1
+ import { isValidElement, forwardRef, useMemo } from 'react';
2
2
  import { View, Pressable, Text } from 'react-native';
3
3
  import { useUnistyles } from 'react-native-unistyles';
4
4
  import MaterialDesignIcons from '@react-native-vector-icons/material-design-icons';
@@ -7,8 +7,9 @@ import { listStyles } from './List.styles';
7
7
  import type { ListItemProps } from './types';
8
8
  import { useListContext } from './ListContext';
9
9
  import { getNativeSelectableAccessibilityProps } from '../utils/accessibility';
10
+ import type { IdealystElement } from '../utils/refTypes';
10
11
 
11
- const ListItem = forwardRef<ComponentRef<typeof View> | ComponentRef<typeof Pressable>, ListItemProps & { isLast?: boolean }>(({
12
+ const ListItem = forwardRef<IdealystElement, ListItemProps & { isLast?: boolean }>(({
12
13
  id,
13
14
  label,
14
15
  children,
@@ -2,8 +2,9 @@ import { forwardRef } from 'react';
2
2
  import { View, Text } from 'react-native';
3
3
  import { listStyles } from './List.styles';
4
4
  import type { ListSectionProps } from './types';
5
+ import type { IdealystElement } from '../utils/refTypes';
5
6
 
6
- const ListSection = forwardRef<View, ListSectionProps>(({
7
+ const ListSection = forwardRef<IdealystElement, ListSectionProps>(({
7
8
  title,
8
9
  children,
9
10
  collapsed = false,
@@ -11,7 +12,7 @@ const ListSection = forwardRef<View, ListSectionProps>(({
11
12
  testID,
12
13
  }, ref) => {
13
14
  return (
14
- <View ref={ref} style={[listStyles.section, style]} testID={testID}>
15
+ <View ref={ref as any} style={[listStyles.section, style]} testID={testID}>
15
16
  {title && (
16
17
  <Text style={listStyles.sectionTitle}>
17
18
  {title}
@@ -12,8 +12,9 @@ import useMergeRefs from '../hooks/useMergeRefs';
12
12
  import { BoundedModalContent } from '../internal/BoundedModalContent.native';
13
13
  import { useSmartPosition } from '../hooks/useSmartPosition.native';
14
14
  import { getNativeInteractiveAccessibilityProps } from '../utils/accessibility';
15
+ import type { IdealystElement } from '../utils/refTypes';
15
16
 
16
- const Menu = forwardRef<View, MenuProps>(({
17
+ const Menu = forwardRef<IdealystElement, MenuProps>(({
17
18
  children,
18
19
  items,
19
20
  open,
@@ -53,38 +53,88 @@ export const menuStyles = defineStyle('Menu', (theme: Theme) => ({
53
53
  },
54
54
  }),
55
55
 
56
- item: ({ intent = 'neutral', disabled = false }: MenuDynamicProps) => {
57
- const intentValue = theme.intents[intent];
58
- const hoverStyles = intent !== 'neutral' ? {
59
- backgroundColor: intentValue.light + '20',
60
- color: intentValue.primary,
61
- } : {
62
- backgroundColor: theme.colors.surface.secondary,
63
- };
64
-
65
- return {
66
- flexDirection: 'row' as const,
67
- alignItems: 'center' as const,
68
- backgroundColor: 'transparent' as const,
69
- borderRadius: 4,
70
- minHeight: 44,
71
- opacity: disabled ? 0.5 : 1,
72
- variants: {
73
- size: {
74
- paddingVertical: theme.sizes.$menu.paddingVertical,
75
- paddingHorizontal: theme.sizes.$menu.paddingHorizontal,
56
+ item: (_props: MenuDynamicProps) => ({
57
+ flexDirection: 'row' as const,
58
+ alignItems: 'center' as const,
59
+ backgroundColor: 'transparent' as const,
60
+ borderRadius: 4,
61
+ minHeight: 44,
62
+ variants: {
63
+ size: {
64
+ paddingVertical: theme.sizes.$menu.paddingVertical,
65
+ paddingHorizontal: theme.sizes.$menu.paddingHorizontal,
66
+ },
67
+ intent: {
68
+ neutral: {
69
+ _web: {
70
+ _hover: {
71
+ backgroundColor: theme.colors.surface.secondary,
72
+ },
73
+ },
74
+ },
75
+ // For non-neutral intents, use light bg with primary text
76
+ primary: {
77
+ _web: {
78
+ _hover: {
79
+ backgroundColor: theme.intents.primary.light + '20',
80
+ color: theme.intents.primary.primary,
81
+ },
82
+ },
83
+ },
84
+ success: {
85
+ _web: {
86
+ _hover: {
87
+ backgroundColor: theme.intents.success.light + '20',
88
+ color: theme.intents.success.primary,
89
+ },
90
+ },
91
+ },
92
+ danger: {
93
+ _web: {
94
+ _hover: {
95
+ backgroundColor: theme.intents.danger.light + '20',
96
+ color: theme.intents.danger.primary,
97
+ },
98
+ },
99
+ },
100
+ warning: {
101
+ _web: {
102
+ _hover: {
103
+ backgroundColor: theme.intents.warning.light + '20',
104
+ color: theme.intents.warning.primary,
105
+ },
106
+ },
107
+ },
108
+ info: {
109
+ _web: {
110
+ _hover: {
111
+ backgroundColor: theme.intents.info.light + '20',
112
+ color: theme.intents.info.primary,
113
+ },
114
+ },
76
115
  },
77
116
  },
78
- _web: {
79
- cursor: disabled ? 'not-allowed' : 'pointer',
80
- border: 'none',
81
- outline: 'none',
82
- transition: 'background-color 0.2s ease',
83
- textAlign: 'left',
84
- _hover: disabled ? { backgroundColor: 'transparent' } : hoverStyles,
117
+ disabled: {
118
+ true: {
119
+ opacity: 0.5,
120
+ _web: {
121
+ cursor: 'not-allowed',
122
+ _hover: { backgroundColor: 'transparent' },
123
+ },
124
+ },
125
+ false: {
126
+ opacity: 1,
127
+ _web: { cursor: 'pointer' },
128
+ },
85
129
  },
86
- } as const;
87
- },
130
+ },
131
+ _web: {
132
+ border: 'none',
133
+ outline: 'none',
134
+ transition: 'background-color 0.2s ease',
135
+ textAlign: 'left',
136
+ },
137
+ }),
88
138
 
89
139
  separator: (_props: MenuDynamicProps) => ({
90
140
  height: 1,
@@ -6,12 +6,13 @@ import MenuItem from './MenuItem.web';
6
6
  import useMergeRefs from '../hooks/useMergeRefs';
7
7
  import { PositionedPortal } from '../internal/PositionedPortal';
8
8
  import { getWebInteractiveAriaProps, generateAccessibilityId, MENU_KEYS, matchesKey } from '../utils/accessibility';
9
+ import type { IdealystElement } from '../utils/refTypes';
9
10
 
10
11
  /**
11
12
  * Dropdown menu for actions and navigation triggered by a button or element.
12
13
  * Includes keyboard navigation, icons, and separator support.
13
14
  */
14
- const Menu = forwardRef<HTMLDivElement, MenuProps>(({
15
+ const Menu = forwardRef<IdealystElement, MenuProps>(({
15
16
  children,
16
17
  items,
17
18
  open = false,
@@ -1,8 +1,9 @@
1
- import { isValidElement, forwardRef, ComponentRef } from 'react';
1
+ import { isValidElement, forwardRef } from 'react';
2
2
  import { Pressable, Text, View } from 'react-native';
3
3
  import { menuItemStyles } from './MenuItem.styles';
4
4
  import type { MenuItem as MenuItemType, MenuSizeVariant } from './types';
5
5
  import MaterialDesignIcons from '@react-native-vector-icons/material-design-icons';
6
+ import type { IdealystElement } from '../utils/refTypes';
6
7
 
7
8
  interface MenuItemProps {
8
9
  item: MenuItemType;
@@ -11,7 +12,7 @@ interface MenuItemProps {
11
12
  testID?: string;
12
13
  }
13
14
 
14
- const MenuItem = forwardRef<ComponentRef<typeof Pressable>, MenuItemProps>(({ item, onPress, size = 'md', testID }, ref) => {
15
+ const MenuItem = forwardRef<IdealystElement, MenuItemProps>(({ item, onPress, size = 'md', testID }, ref) => {
15
16
  // Initialize styles with useVariants (for size and disabled)
16
17
  menuItemStyles.useVariants({
17
18
  size,
@@ -41,7 +42,7 @@ const MenuItem = forwardRef<ComponentRef<typeof Pressable>, MenuItemProps>(({ it
41
42
 
42
43
  return (
43
44
  <Pressable
44
- ref={ref}
45
+ ref={ref as any}
45
46
  style={itemStyle}
46
47
  onPress={() => onPress(item)}
47
48
  disabled={item.disabled}
@@ -21,41 +21,90 @@ export type MenuItemDynamicProps = {
21
21
  * MenuItem styles with intent/disabled handling.
22
22
  */
23
23
  export const menuItemStyles = defineStyle('MenuItem', (theme: Theme) => ({
24
- item: ({ intent = 'neutral', disabled = false }: MenuItemDynamicProps) => {
25
- const intentValue = theme.intents[intent];
26
- const hoverStyles = intent !== 'neutral' ? {
27
- backgroundColor: intentValue.light,
28
- color: intentValue.primary,
29
- } : {
30
- backgroundColor: theme.colors.surface.secondary,
31
- };
32
-
33
- return {
34
- flexDirection: 'row' as const,
35
- alignItems: 'center' as const,
36
- backgroundColor: 'transparent' as const,
37
- borderRadius: 4,
38
- minHeight: 44,
39
- opacity: disabled ? 0.5 : 1,
40
- variants: {
41
- size: {
42
- paddingVertical: theme.sizes.$menu.paddingVertical,
43
- paddingHorizontal: theme.sizes.$menu.paddingHorizontal,
24
+ item: (_props: MenuItemDynamicProps) => ({
25
+ flexDirection: 'row' as const,
26
+ alignItems: 'center' as const,
27
+ backgroundColor: 'transparent' as const,
28
+ borderRadius: 4,
29
+ minHeight: 44,
30
+ variants: {
31
+ size: {
32
+ paddingVertical: theme.sizes.$menu.paddingVertical,
33
+ paddingHorizontal: theme.sizes.$menu.paddingHorizontal,
34
+ },
35
+ intent: {
36
+ neutral: {
37
+ _web: {
38
+ _hover: {
39
+ backgroundColor: theme.colors.surface.secondary,
40
+ },
41
+ },
42
+ },
43
+ primary: {
44
+ _web: {
45
+ _hover: {
46
+ backgroundColor: theme.intents.primary.light,
47
+ color: theme.intents.primary.primary,
48
+ },
49
+ },
50
+ },
51
+ success: {
52
+ _web: {
53
+ _hover: {
54
+ backgroundColor: theme.intents.success.light,
55
+ color: theme.intents.success.primary,
56
+ },
57
+ },
58
+ },
59
+ danger: {
60
+ _web: {
61
+ _hover: {
62
+ backgroundColor: theme.intents.danger.light,
63
+ color: theme.intents.danger.primary,
64
+ },
65
+ },
66
+ },
67
+ warning: {
68
+ _web: {
69
+ _hover: {
70
+ backgroundColor: theme.intents.warning.light,
71
+ color: theme.intents.warning.primary,
72
+ },
73
+ },
74
+ },
75
+ info: {
76
+ _web: {
77
+ _hover: {
78
+ backgroundColor: theme.intents.info.light,
79
+ color: theme.intents.info.primary,
80
+ },
81
+ },
44
82
  },
45
83
  },
46
- _web: {
47
- display: 'flex',
48
- width: '100%',
49
- cursor: disabled ? 'not-allowed' : 'pointer',
50
- border: 'none',
51
- borderWidth: 0,
52
- outline: 'none',
53
- transition: 'background-color 0.2s ease',
54
- textAlign: 'left',
55
- _hover: disabled ? { backgroundColor: 'transparent' } : hoverStyles,
84
+ disabled: {
85
+ true: {
86
+ opacity: 0.5,
87
+ _web: {
88
+ cursor: 'not-allowed',
89
+ _hover: { backgroundColor: 'transparent' },
90
+ },
91
+ },
92
+ false: {
93
+ opacity: 1,
94
+ _web: { cursor: 'pointer' },
95
+ },
56
96
  },
57
- } as const;
58
- },
97
+ },
98
+ _web: {
99
+ display: 'flex',
100
+ width: '100%',
101
+ border: 'none',
102
+ borderWidth: 0,
103
+ outline: 'none',
104
+ transition: 'background-color 0.2s ease',
105
+ textAlign: 'left',
106
+ },
107
+ }),
59
108
 
60
109
  icon: (_props: MenuItemDynamicProps) => ({
61
110
  alignItems: 'center' as const,
@@ -5,6 +5,7 @@ import type { MenuItem as MenuItemType, MenuSizeVariant } 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 type { IdealystElement } from '../utils/refTypes';
8
9
 
9
10
  interface MenuItemProps {
10
11
  item: MenuItemType;
@@ -13,7 +14,7 @@ interface MenuItemProps {
13
14
  testID?: string;
14
15
  }
15
16
 
16
- const MenuItem = forwardRef<HTMLButtonElement, MenuItemProps>(({ item, onPress, size = 'md', testID }, ref) => {
17
+ const MenuItem = forwardRef<IdealystElement, MenuItemProps>(({ item, onPress, size = 'md', testID }, ref) => {
17
18
  // Initialize styles with useVariants (for size and disabled)
18
19
  menuItemStyles.useVariants({
19
20
  size,
package/src/Menu/docs.ts CHANGED
@@ -9,7 +9,7 @@ export const sampleProps: SampleProps = {
9
9
  items: [
10
10
  { id: '1', label: 'Edit' },
11
11
  { id: '2', label: 'Duplicate' },
12
- { id: '3', label: 'Delete', intent: 'error' },
12
+ { id: '3', label: 'Delete', intent: 'danger' },
13
13
  ],
14
14
  },
15
15
  children: 'Click for menu',
@@ -6,8 +6,9 @@ import { popoverStyles } from './Popover.styles';
6
6
  import { calculateSmartPosition } from '../utils/positionUtils.native';
7
7
  import { BoundedModalContent } from '../internal/BoundedModalContent.native';
8
8
  import { getNativeInteractiveAccessibilityProps } from '../utils/accessibility';
9
+ import type { IdealystElement } from '../utils/refTypes';
9
10
 
10
- const Popover = forwardRef<View, PopoverProps>(({
11
+ const Popover = forwardRef<IdealystElement, PopoverProps>(({
11
12
  open,
12
13
  onOpenChange,
13
14
  anchor,
@@ -5,12 +5,13 @@ import { popoverStyles } from './Popover.styles';
5
5
  import useMergeRefs from '../hooks/useMergeRefs';
6
6
  import { PositionedPortal } from '../internal/PositionedPortal';
7
7
  import { getWebInteractiveAriaProps, generateAccessibilityId } from '../utils/accessibility';
8
+ import type { IdealystElement } from '../utils/refTypes';
8
9
 
9
10
  /**
10
11
  * Floating content panel anchored to an element for contextual information or actions.
11
12
  * Supports multiple placements and automatic dismissal behaviors.
12
13
  */
13
- const Popover = forwardRef<HTMLDivElement, PopoverProps>(({
14
+ const Popover = forwardRef<IdealystElement, PopoverProps>(({
14
15
  open,
15
16
  onOpenChange,
16
17
  anchor,
@@ -1,7 +1,11 @@
1
- import type { ReactNode } from 'react';
1
+ import type { ReactNode, RefObject } from 'react';
2
2
  import type { StyleProp, ViewStyle } from 'react-native';
3
3
  import { BaseProps } from '../utils/viewStyleProps';
4
4
  import { InteractiveAccessibilityProps } from '../utils/accessibility';
5
+ import type { IdealystElement } from '../utils/refTypes';
6
+
7
+ // Re-export for convenience
8
+ export type { IdealystElement };
5
9
 
6
10
  export type PopoverPlacement =
7
11
  | 'top' | 'top-start' | 'top-end'
@@ -21,10 +25,17 @@ export interface PopoverProps extends BaseProps, InteractiveAccessibilityProps {
21
25
  onOpenChange: (open: boolean) => void;
22
26
 
23
27
  /**
24
- * The anchor element to position the popover relative to
25
- * Can be a React element or a ref to a DOM element
28
+ * The anchor element to position the popover relative to.
29
+ * Can be a React element or a ref to any DOM/RN element.
30
+ *
31
+ * @example
32
+ * ```tsx
33
+ * const anchorRef = React.useRef<AnchorElement>(null);
34
+ * <Button ref={anchorRef}>Open</Button>
35
+ * <Popover anchor={anchorRef} ... />
36
+ * ```
26
37
  */
27
- anchor: ReactNode | React.RefObject<Element>;
38
+ anchor: ReactNode | RefObject<IdealystElement>;
28
39
 
29
40
  /**
30
41
  * The content to display inside the popover
@@ -2,8 +2,9 @@ import { forwardRef } from 'react';
2
2
  import { TouchableWithoutFeedback, View } from 'react-native';
3
3
  import { PressableProps } from './types';
4
4
  import { pressableStyles } from './Pressable.styles';
5
+ import type { IdealystElement } from '../utils/refTypes';
5
6
 
6
- const Pressable = forwardRef<View, PressableProps>(({
7
+ const Pressable = forwardRef<IdealystElement, PressableProps>(({
7
8
  children,
8
9
  onPress,
9
10
  onPressIn,
@@ -37,7 +38,7 @@ const Pressable = forwardRef<View, PressableProps>(({
37
38
  testID={testID}
38
39
  accessibilityLabel={accessibilityLabel}
39
40
  >
40
- <View ref={ref} nativeID={id} style={[pressableStyle, style]}>
41
+ <View ref={ref as any} nativeID={id} style={[pressableStyle, style]}>
41
42
  {children}
42
43
  </View>
43
44
  </TouchableWithoutFeedback>
@@ -3,8 +3,9 @@ import { getWebProps } from 'react-native-unistyles/web';
3
3
  import { PressableProps } from './types';
4
4
  import { pressableStyles } from './Pressable.styles';
5
5
  import useMergeRefs from '../hooks/useMergeRefs';
6
+ import type { IdealystElement } from '../utils/refTypes';
6
7
 
7
- const Pressable = forwardRef<HTMLDivElement, PressableProps>(({
8
+ const Pressable = forwardRef<IdealystElement, PressableProps>(({
8
9
  children,
9
10
  onPress,
10
11
  onPressIn,
@@ -66,10 +67,7 @@ const Pressable = forwardRef<HTMLDivElement, PressableProps>(({
66
67
  };
67
68
 
68
69
  // Merge ref from getWebProps with forwarded ref
69
- const mergedRef = useMergeRefs<HTMLDivElement>(
70
- ref,
71
- webProps.ref as React.Ref<HTMLDivElement>
72
- );
70
+ const mergedRef = useMergeRefs(ref as any, webProps.ref as any);
73
71
 
74
72
  return (
75
73
  <div
@@ -14,13 +14,14 @@ import Text from '../Text';
14
14
  import { progressStyles } from './Progress.styles';
15
15
  import type { ProgressProps } from './types';
16
16
  import { Theme } from '@idealyst/theme';
17
+ import type { IdealystElement } from '../utils/refTypes';
17
18
 
18
19
  const AnimatedCircle = Animated.createAnimatedComponent(Circle);
19
20
 
20
- const Progress = forwardRef<View, ProgressProps>(({
21
+ const Progress = forwardRef<IdealystElement, ProgressProps>(({
21
22
  value = 0,
22
23
  max = 100,
23
- variant = 'linear',
24
+ type = 'linear',
24
25
  intent = 'primary',
25
26
  size = 'md',
26
27
  indeterminate = false,
@@ -78,7 +79,7 @@ const Progress = forwardRef<View, ProgressProps>(({
78
79
  return 48;
79
80
  };
80
81
 
81
- if (variant === 'circular') {
82
+ if (type === 'circular') {
82
83
  const circularSize = getCircularSize();
83
84
  const strokeWidth = size === 'sm' ? 3 : size === 'lg' ? 5 : 4;
84
85
  const radius = (circularSize - strokeWidth) / 2;
@@ -166,7 +167,7 @@ const Progress = forwardRef<View, ProgressProps>(({
166
167
  const linearTrackStyle = (progressStyles.linearTrack as any)({});
167
168
 
168
169
  return (
169
- <View ref={ref} nativeID={id} style={[containerStyle, style]} testID={testID} accessibilityRole="progressbar">
170
+ <View ref={ref as any} nativeID={id} style={[containerStyle, style]} testID={testID} accessibilityRole="progressbar">
170
171
  <View style={linearTrackStyle}>
171
172
  {indeterminate ? (
172
173
  <Animated.View style={[indeterminateBarStyle, indeterminateAnimatedStyle]} />
@@ -5,12 +5,12 @@ import type { ProgressProps } from './types';
5
5
 
6
6
  /**
7
7
  * Visual indicator for task completion or loading status.
8
- * Supports linear and circular variants with determinate or indeterminate states.
8
+ * Supports linear and circular types with determinate or indeterminate states.
9
9
  */
10
10
  const Progress: React.FC<ProgressProps> = ({
11
11
  value = 0,
12
12
  max = 100,
13
- variant = 'linear',
13
+ type = 'linear',
14
14
  intent = 'primary',
15
15
  size = 'md',
16
16
  indeterminate = false,
@@ -43,7 +43,7 @@ const Progress: React.FC<ProgressProps> = ({
43
43
  return 48;
44
44
  };
45
45
 
46
- if (variant === 'circular') {
46
+ if (type === 'circular') {
47
47
  const circularSize = getCircularSize();
48
48
  const strokeWidth = size === 'sm' ? 3 : size === 'lg' ? 5 : 4;
49
49
  const radius = (circularSize - strokeWidth) / 2;
@@ -5,11 +5,11 @@ import { BaseProps } from '../utils/viewStyleProps';
5
5
  // Component-specific type aliases for future extensibility
6
6
  export type ProgressIntentVariant = Intent;
7
7
  export type ProgressSizeVariant = Size;
8
- export type ProgressVariant = 'linear' | 'circular';
8
+ export type ProgressType = 'linear' | 'circular';
9
9
 
10
10
  /**
11
11
  * Visual indicator for task completion or loading status.
12
- * Supports linear and circular variants with determinate and indeterminate modes.
12
+ * Supports linear and circular types with determinate and indeterminate modes.
13
13
  */
14
14
  export interface ProgressProps extends BaseProps {
15
15
  /**
@@ -17,7 +17,7 @@ export interface ProgressProps extends BaseProps {
17
17
  */
18
18
  value?: number;
19
19
  max?: number;
20
- variant?: ProgressVariant;
20
+ type?: ProgressType;
21
21
  intent?: ProgressIntentVariant;
22
22
  size?: ProgressSizeVariant;
23
23
  indeterminate?: boolean;
@@ -1,12 +1,13 @@
1
- import React, { ComponentRef, forwardRef, useMemo } from 'react';
1
+ import React, { forwardRef, useMemo } from 'react';
2
2
  import { View, Pressable, Animated } from 'react-native';
3
3
  import Text from '../Text';
4
4
  import { radioButtonStyles } from './RadioButton.styles';
5
5
  import type { RadioButtonProps } from './types';
6
6
  import { useRadioGroup } from './RadioGroup.native';
7
7
  import { getNativeSelectionAccessibilityProps } from '../utils/accessibility';
8
+ import type { IdealystElement } from '../utils/refTypes';
8
9
 
9
- const RadioButton = forwardRef<ComponentRef<typeof Pressable>, RadioButtonProps>(({
10
+ const RadioButton = forwardRef<IdealystElement, RadioButtonProps>(({
10
11
  value,
11
12
  checked: checkedProp,
12
13
  onPress,
@@ -109,7 +110,7 @@ const RadioButton = forwardRef<ComponentRef<typeof Pressable>, RadioButtonProps>
109
110
 
110
111
  return (
111
112
  <Pressable
112
- ref={ref}
113
+ ref={ref as any}
113
114
  nativeID={id}
114
115
  onPress={handlePress}
115
116
  disabled={disabled}