@cdx-ui/primitives 0.0.1-alpha.2 → 0.0.1-alpha.20

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 (273) hide show
  1. package/lib/commonjs/avatar/context.js +11 -0
  2. package/lib/commonjs/avatar/context.js.map +1 -0
  3. package/lib/commonjs/avatar/createAvatarBadge.js +20 -0
  4. package/lib/commonjs/avatar/createAvatarBadge.js.map +1 -0
  5. package/lib/commonjs/avatar/createAvatarIcon.js +30 -0
  6. package/lib/commonjs/avatar/createAvatarIcon.js.map +1 -0
  7. package/lib/commonjs/avatar/createAvatarImage.js +51 -0
  8. package/lib/commonjs/avatar/createAvatarImage.js.map +1 -0
  9. package/lib/commonjs/avatar/createAvatarRoot.js +34 -0
  10. package/lib/commonjs/avatar/createAvatarRoot.js.map +1 -0
  11. package/lib/commonjs/avatar/createAvatarText.js +42 -0
  12. package/lib/commonjs/avatar/createAvatarText.js.map +1 -0
  13. package/lib/commonjs/avatar/index.js +30 -0
  14. package/lib/commonjs/avatar/index.js.map +1 -0
  15. package/lib/commonjs/avatar/types.js +6 -0
  16. package/lib/commonjs/avatar/types.js.map +1 -0
  17. package/lib/commonjs/button/createButtonRoot.js +3 -3
  18. package/lib/commonjs/button/createButtonRoot.js.map +1 -1
  19. package/lib/commonjs/button/index.js +18 -19
  20. package/lib/commonjs/button/index.js.map +1 -1
  21. package/lib/commonjs/checkbox/context.js +14 -0
  22. package/lib/commonjs/checkbox/context.js.map +1 -0
  23. package/lib/commonjs/checkbox/createCheckboxGroup.js +44 -0
  24. package/lib/commonjs/checkbox/createCheckboxGroup.js.map +1 -0
  25. package/lib/commonjs/checkbox/createCheckboxIcon.js +29 -0
  26. package/lib/commonjs/checkbox/createCheckboxIcon.js.map +1 -0
  27. package/lib/commonjs/checkbox/createCheckboxIndicator.js +47 -0
  28. package/lib/commonjs/checkbox/createCheckboxIndicator.js.map +1 -0
  29. package/lib/commonjs/checkbox/createCheckboxLabel.js +46 -0
  30. package/lib/commonjs/checkbox/createCheckboxLabel.js.map +1 -0
  31. package/lib/commonjs/checkbox/createCheckboxRoot.js +99 -0
  32. package/lib/commonjs/checkbox/createCheckboxRoot.js.map +1 -0
  33. package/lib/commonjs/checkbox/createCheckboxRoot.web.js +90 -0
  34. package/lib/commonjs/checkbox/createCheckboxRoot.web.js.map +1 -0
  35. package/lib/commonjs/checkbox/index.js +30 -0
  36. package/lib/commonjs/checkbox/index.js.map +1 -0
  37. package/lib/commonjs/checkbox/types.js +6 -0
  38. package/lib/commonjs/checkbox/types.js.map +1 -0
  39. package/lib/commonjs/checkbox/useCheckboxRoot.js +82 -0
  40. package/lib/commonjs/checkbox/useCheckboxRoot.js.map +1 -0
  41. package/lib/commonjs/index.js +49 -1
  42. package/lib/commonjs/index.js.map +1 -1
  43. package/lib/commonjs/input/index.js +13 -19
  44. package/lib/commonjs/input/index.js.map +1 -1
  45. package/lib/commonjs/link/LinkProvider.js +28 -0
  46. package/lib/commonjs/link/LinkProvider.js.map +1 -0
  47. package/lib/commonjs/link/createLink.js +74 -0
  48. package/lib/commonjs/link/createLink.js.map +1 -0
  49. package/lib/commonjs/link/index.js +27 -0
  50. package/lib/commonjs/link/index.js.map +1 -0
  51. package/lib/commonjs/link/types.js +6 -0
  52. package/lib/commonjs/link/types.js.map +1 -0
  53. package/lib/commonjs/link/useLink.js +56 -0
  54. package/lib/commonjs/link/useLink.js.map +1 -0
  55. package/lib/commonjs/overlay/OverlayContainer.js +6 -4
  56. package/lib/commonjs/overlay/OverlayContainer.js.map +1 -1
  57. package/lib/commonjs/select/context.js +8 -43
  58. package/lib/commonjs/select/context.js.map +1 -1
  59. package/lib/commonjs/select/createSelectItem.js +1 -1
  60. package/lib/commonjs/select/createSelectItem.js.map +1 -1
  61. package/lib/commonjs/select/createSelectRoot.js +1 -1
  62. package/lib/commonjs/select/createSelectRoot.js.map +1 -1
  63. package/lib/commonjs/select/createSelectTrigger.js +2 -8
  64. package/lib/commonjs/select/createSelectTrigger.js.map +1 -1
  65. package/lib/commonjs/switch/createSwitchRoot.js +73 -0
  66. package/lib/commonjs/switch/createSwitchRoot.js.map +1 -0
  67. package/lib/commonjs/switch/index.js +15 -0
  68. package/lib/commonjs/switch/index.js.map +1 -0
  69. package/lib/commonjs/switch/types.js +6 -0
  70. package/lib/commonjs/switch/types.js.map +1 -0
  71. package/lib/commonjs/types.js +2 -0
  72. package/lib/commonjs/types.js.map +1 -0
  73. package/lib/commonjs/utils/dataAttributes.web.js +1 -4
  74. package/lib/commonjs/utils/dataAttributes.web.js.map +1 -1
  75. package/lib/module/avatar/context.js +5 -0
  76. package/lib/module/avatar/context.js.map +1 -0
  77. package/lib/module/{input/createInputIcon.js → avatar/createAvatarBadge.js} +3 -3
  78. package/lib/module/avatar/createAvatarBadge.js.map +1 -0
  79. package/lib/module/avatar/createAvatarIcon.js +25 -0
  80. package/lib/module/avatar/createAvatarIcon.js.map +1 -0
  81. package/lib/module/avatar/createAvatarImage.js +46 -0
  82. package/lib/module/avatar/createAvatarImage.js.map +1 -0
  83. package/lib/module/avatar/createAvatarRoot.js +29 -0
  84. package/lib/module/avatar/createAvatarRoot.js.map +1 -0
  85. package/lib/module/avatar/createAvatarText.js +37 -0
  86. package/lib/module/avatar/createAvatarText.js.map +1 -0
  87. package/lib/module/avatar/index.js +26 -0
  88. package/lib/module/avatar/index.js.map +1 -0
  89. package/lib/module/avatar/types.js +4 -0
  90. package/lib/module/avatar/types.js.map +1 -0
  91. package/lib/module/button/createButtonRoot.js +3 -3
  92. package/lib/module/button/createButtonRoot.js.map +1 -1
  93. package/lib/module/button/index.js +18 -19
  94. package/lib/module/button/index.js.map +1 -1
  95. package/lib/module/checkbox/context.js +7 -0
  96. package/lib/module/checkbox/context.js.map +1 -0
  97. package/lib/module/checkbox/createCheckboxGroup.js +39 -0
  98. package/lib/module/checkbox/createCheckboxGroup.js.map +1 -0
  99. package/lib/module/checkbox/createCheckboxIcon.js +24 -0
  100. package/lib/module/checkbox/createCheckboxIcon.js.map +1 -0
  101. package/lib/module/checkbox/createCheckboxIndicator.js +42 -0
  102. package/lib/module/checkbox/createCheckboxIndicator.js.map +1 -0
  103. package/lib/module/checkbox/createCheckboxLabel.js +41 -0
  104. package/lib/module/checkbox/createCheckboxLabel.js.map +1 -0
  105. package/lib/module/checkbox/createCheckboxRoot.js +94 -0
  106. package/lib/module/checkbox/createCheckboxRoot.js.map +1 -0
  107. package/lib/module/checkbox/createCheckboxRoot.web.js +85 -0
  108. package/lib/module/checkbox/createCheckboxRoot.web.js.map +1 -0
  109. package/lib/module/checkbox/index.js +26 -0
  110. package/lib/module/checkbox/index.js.map +1 -0
  111. package/lib/module/checkbox/types.js +4 -0
  112. package/lib/module/checkbox/types.js.map +1 -0
  113. package/lib/module/checkbox/useCheckboxRoot.js +78 -0
  114. package/lib/module/checkbox/useCheckboxRoot.js.map +1 -0
  115. package/lib/module/index.js +5 -1
  116. package/lib/module/index.js.map +1 -1
  117. package/lib/module/input/index.js +12 -17
  118. package/lib/module/input/index.js.map +1 -1
  119. package/lib/module/link/LinkProvider.js +23 -0
  120. package/lib/module/link/LinkProvider.js.map +1 -0
  121. package/lib/module/link/createLink.js +68 -0
  122. package/lib/module/link/createLink.js.map +1 -0
  123. package/lib/module/link/index.js +6 -0
  124. package/lib/module/link/index.js.map +1 -0
  125. package/lib/module/link/types.js +4 -0
  126. package/lib/module/link/types.js.map +1 -0
  127. package/lib/module/link/useLink.js +52 -0
  128. package/lib/module/link/useLink.js.map +1 -0
  129. package/lib/module/overlay/OverlayContainer.js +7 -5
  130. package/lib/module/overlay/OverlayContainer.js.map +1 -1
  131. package/lib/module/select/context.js +4 -42
  132. package/lib/module/select/context.js.map +1 -1
  133. package/lib/module/select/createSelectItem.js +2 -2
  134. package/lib/module/select/createSelectItem.js.map +1 -1
  135. package/lib/module/select/createSelectRoot.js +2 -2
  136. package/lib/module/select/createSelectRoot.js.map +1 -1
  137. package/lib/module/select/createSelectTrigger.js +3 -9
  138. package/lib/module/select/createSelectTrigger.js.map +1 -1
  139. package/lib/module/switch/createSwitchRoot.js +67 -0
  140. package/lib/module/switch/createSwitchRoot.js.map +1 -0
  141. package/lib/module/switch/index.js +11 -0
  142. package/lib/module/switch/index.js.map +1 -0
  143. package/lib/module/switch/types.js +4 -0
  144. package/lib/module/switch/types.js.map +1 -0
  145. package/lib/module/types.js +2 -0
  146. package/lib/module/types.js.map +1 -0
  147. package/lib/module/utils/dataAttributes.web.js +1 -4
  148. package/lib/module/utils/dataAttributes.web.js.map +1 -1
  149. package/lib/typescript/avatar/context.d.ts +6 -0
  150. package/lib/typescript/avatar/context.d.ts.map +1 -0
  151. package/lib/typescript/avatar/createAvatarBadge.d.ts +4 -0
  152. package/lib/typescript/avatar/createAvatarBadge.d.ts.map +1 -0
  153. package/lib/typescript/avatar/createAvatarIcon.d.ts +4 -0
  154. package/lib/typescript/avatar/createAvatarIcon.d.ts.map +1 -0
  155. package/lib/typescript/avatar/createAvatarImage.d.ts +4 -0
  156. package/lib/typescript/avatar/createAvatarImage.d.ts.map +1 -0
  157. package/lib/typescript/avatar/createAvatarRoot.d.ts +4 -0
  158. package/lib/typescript/avatar/createAvatarRoot.d.ts.map +1 -0
  159. package/lib/typescript/avatar/createAvatarText.d.ts +4 -0
  160. package/lib/typescript/avatar/createAvatarText.d.ts.map +1 -0
  161. package/lib/typescript/avatar/index.d.ts +11 -0
  162. package/lib/typescript/avatar/index.d.ts.map +1 -0
  163. package/lib/typescript/avatar/types.d.ts +33 -0
  164. package/lib/typescript/avatar/types.d.ts.map +1 -0
  165. package/lib/typescript/button/context.d.ts +1 -1
  166. package/lib/typescript/button/context.d.ts.map +1 -1
  167. package/lib/typescript/button/createButtonRoot.d.ts +1 -1
  168. package/lib/typescript/button/createButtonRoot.d.ts.map +1 -1
  169. package/lib/typescript/button/index.d.ts +1 -1
  170. package/lib/typescript/button/index.d.ts.map +1 -1
  171. package/lib/typescript/button/types.d.ts +0 -7
  172. package/lib/typescript/button/types.d.ts.map +1 -1
  173. package/lib/typescript/checkbox/context.d.ts +18 -0
  174. package/lib/typescript/checkbox/context.d.ts.map +1 -0
  175. package/lib/typescript/checkbox/createCheckboxGroup.d.ts +3 -0
  176. package/lib/typescript/checkbox/createCheckboxGroup.d.ts.map +1 -0
  177. package/lib/typescript/checkbox/createCheckboxIcon.d.ts +3 -0
  178. package/lib/typescript/checkbox/createCheckboxIcon.d.ts.map +1 -0
  179. package/lib/typescript/checkbox/createCheckboxIndicator.d.ts +5 -0
  180. package/lib/typescript/checkbox/createCheckboxIndicator.d.ts.map +1 -0
  181. package/lib/typescript/checkbox/createCheckboxLabel.d.ts +5 -0
  182. package/lib/typescript/checkbox/createCheckboxLabel.d.ts.map +1 -0
  183. package/lib/typescript/checkbox/createCheckboxRoot.d.ts +2 -0
  184. package/lib/typescript/checkbox/createCheckboxRoot.d.ts.map +1 -0
  185. package/lib/typescript/checkbox/createCheckboxRoot.web.d.ts +2 -0
  186. package/lib/typescript/checkbox/createCheckboxRoot.web.d.ts.map +1 -0
  187. package/lib/typescript/checkbox/index.d.ts +11 -0
  188. package/lib/typescript/checkbox/index.d.ts.map +1 -0
  189. package/lib/typescript/checkbox/types.d.ts +57 -0
  190. package/lib/typescript/checkbox/types.d.ts.map +1 -0
  191. package/lib/typescript/checkbox/useCheckboxRoot.d.ts +147 -0
  192. package/lib/typescript/checkbox/useCheckboxRoot.d.ts.map +1 -0
  193. package/lib/typescript/index.d.ts +6 -1
  194. package/lib/typescript/index.d.ts.map +1 -1
  195. package/lib/typescript/input/index.d.ts +3 -3
  196. package/lib/typescript/input/index.d.ts.map +1 -1
  197. package/lib/typescript/input/types.d.ts +1 -2
  198. package/lib/typescript/input/types.d.ts.map +1 -1
  199. package/lib/typescript/link/LinkProvider.d.ts +36 -0
  200. package/lib/typescript/link/LinkProvider.d.ts.map +1 -0
  201. package/lib/typescript/link/createLink.d.ts +6 -0
  202. package/lib/typescript/link/createLink.d.ts.map +1 -0
  203. package/lib/typescript/link/index.d.ts +6 -0
  204. package/lib/typescript/link/index.d.ts.map +1 -0
  205. package/lib/typescript/link/types.d.ts +45 -0
  206. package/lib/typescript/link/types.d.ts.map +1 -0
  207. package/lib/typescript/link/useLink.d.ts +9 -0
  208. package/lib/typescript/link/useLink.d.ts.map +1 -0
  209. package/lib/typescript/overlay/OverlayContainer.d.ts +5 -1
  210. package/lib/typescript/overlay/OverlayContainer.d.ts.map +1 -1
  211. package/lib/typescript/select/context.d.ts +14 -7
  212. package/lib/typescript/select/context.d.ts.map +1 -1
  213. package/lib/typescript/select/createSelectTrigger.d.ts +2 -7
  214. package/lib/typescript/select/createSelectTrigger.d.ts.map +1 -1
  215. package/lib/typescript/select/types.d.ts +1 -7
  216. package/lib/typescript/select/types.d.ts.map +1 -1
  217. package/lib/typescript/switch/createSwitchRoot.d.ts +3 -0
  218. package/lib/typescript/switch/createSwitchRoot.d.ts.map +1 -0
  219. package/lib/typescript/switch/index.d.ts +7 -0
  220. package/lib/typescript/switch/index.d.ts.map +1 -0
  221. package/lib/typescript/switch/types.d.ts +38 -0
  222. package/lib/typescript/switch/types.d.ts.map +1 -0
  223. package/lib/typescript/types.d.ts +8 -0
  224. package/lib/typescript/types.d.ts.map +1 -0
  225. package/lib/typescript/utils/dataAttributes.web.d.ts.map +1 -1
  226. package/package.json +12 -8
  227. package/src/avatar/context.tsx +5 -0
  228. package/src/avatar/createAvatarBadge.tsx +12 -0
  229. package/src/avatar/createAvatarIcon.tsx +16 -0
  230. package/src/avatar/createAvatarImage.tsx +40 -0
  231. package/src/avatar/createAvatarRoot.tsx +23 -0
  232. package/src/avatar/createAvatarText.tsx +30 -0
  233. package/src/avatar/index.ts +43 -0
  234. package/src/avatar/types.ts +77 -0
  235. package/src/button/context.tsx +1 -1
  236. package/src/button/createButtonRoot.tsx +5 -4
  237. package/src/button/index.tsx +18 -19
  238. package/src/button/types.ts +0 -8
  239. package/src/checkbox/context.tsx +18 -0
  240. package/src/checkbox/createCheckboxGroup.tsx +32 -0
  241. package/src/checkbox/createCheckboxIcon.tsx +18 -0
  242. package/src/checkbox/createCheckboxIndicator.tsx +43 -0
  243. package/src/checkbox/createCheckboxLabel.tsx +42 -0
  244. package/src/checkbox/createCheckboxRoot.tsx +100 -0
  245. package/src/checkbox/createCheckboxRoot.web.tsx +79 -0
  246. package/src/checkbox/index.ts +43 -0
  247. package/src/checkbox/types.ts +74 -0
  248. package/src/checkbox/useCheckboxRoot.ts +85 -0
  249. package/src/index.ts +6 -1
  250. package/src/input/index.tsx +15 -28
  251. package/src/input/types.ts +0 -4
  252. package/src/link/LinkProvider.tsx +50 -0
  253. package/src/link/createLink.tsx +71 -0
  254. package/src/link/index.tsx +5 -0
  255. package/src/link/types.ts +47 -0
  256. package/src/link/useLink.ts +54 -0
  257. package/src/overlay/OverlayContainer.tsx +7 -8
  258. package/src/select/context.tsx +9 -44
  259. package/src/select/createSelectItem.tsx +3 -3
  260. package/src/select/createSelectRoot.tsx +3 -3
  261. package/src/select/createSelectTrigger.tsx +6 -31
  262. package/src/select/types.ts +1 -10
  263. package/src/switch/createSwitchRoot.tsx +72 -0
  264. package/src/switch/index.ts +16 -0
  265. package/src/switch/types.ts +42 -0
  266. package/src/types.ts +7 -0
  267. package/src/utils/dataAttributes.web.ts +2 -4
  268. package/lib/commonjs/input/createInputIcon.js +0 -20
  269. package/lib/commonjs/input/createInputIcon.js.map +0 -1
  270. package/lib/module/input/createInputIcon.js.map +0 -1
  271. package/lib/typescript/input/createInputIcon.d.ts +0 -4
  272. package/lib/typescript/input/createInputIcon.d.ts.map +0 -1
  273. package/src/input/createInputIcon.tsx +0 -12
@@ -0,0 +1,79 @@
1
+ import { forwardRef } from 'react';
2
+ import { VisuallyHidden } from '@react-aria/visually-hidden';
3
+ import { useFocusRing } from '@react-native-aria/focus';
4
+ import { dataAttributes } from '../utils/dataAttributes';
5
+ import { CheckboxProvider } from './context';
6
+ import type { ICheckboxProps } from './types';
7
+ import { useCheckboxRoot } from './useCheckboxRoot';
8
+
9
+ // TODO: Label is taking focus on keyboard navigation
10
+
11
+ export const createCheckboxRoot = <T,>(BaseCheckbox: React.ComponentType<T>) =>
12
+ forwardRef(({ children, ...props }: ICheckboxProps, ref?: React.Ref<T>) => {
13
+ const {
14
+ isHovered: isHoveredProp,
15
+ isFocusVisible: isFocusVisibleProp,
16
+ isChecked: isCheckedProp,
17
+ isDisabled: isDisabledProp,
18
+ isInvalid: isInvalidProp,
19
+ isReadOnly: isReadOnlyProp,
20
+ isIndeterminate: isIndeterminateProp,
21
+ isFocused,
22
+ isPressed,
23
+ } = props;
24
+
25
+ const {
26
+ combinedProps,
27
+ isInvalid,
28
+ isReadOnly,
29
+ isIndeterminate,
30
+ groupItemInputProps,
31
+ isChecked,
32
+ isDisabled,
33
+ isHovered,
34
+ mergedRef,
35
+ inputRef,
36
+ } = useCheckboxRoot(props, ref, { useInputRefForAria: true });
37
+
38
+ const { focusProps, isFocusVisible } = useFocusRing();
39
+
40
+ return (
41
+ <BaseCheckbox
42
+ {...(combinedProps as T)}
43
+ ref={mergedRef}
44
+ role="label"
45
+ // eslint-disable-next-line react-native-a11y/has-valid-accessibility-role
46
+ accessibilityRole="label"
47
+ {...dataAttributes({
48
+ checked: isChecked || isCheckedProp,
49
+ disabled: isDisabled || isDisabledProp,
50
+ hover: isHovered || isHoveredProp,
51
+ invalid: isInvalid || isInvalidProp,
52
+ readonly: isReadOnly || isReadOnlyProp,
53
+ active: isPressed,
54
+ focus: isFocused,
55
+ indeterminate: isIndeterminate || isIndeterminateProp,
56
+ focusVisible: isFocusVisible,
57
+ })}
58
+ >
59
+ <CheckboxProvider
60
+ value={{
61
+ isChecked: isChecked || isCheckedProp,
62
+ isDisabled: isDisabled || isDisabledProp,
63
+ isFocusVisible: isFocusVisible || isFocusVisibleProp,
64
+ isHovered: isHovered || isHoveredProp,
65
+ isInvalid: isInvalid || isInvalidProp,
66
+ isReadOnly: isReadOnly || isReadOnlyProp,
67
+ isIndeterminate: isIndeterminate || isIndeterminateProp,
68
+ isPressed,
69
+ isFocused,
70
+ }}
71
+ >
72
+ <VisuallyHidden>
73
+ <input {...groupItemInputProps} {...focusProps} ref={inputRef} />
74
+ </VisuallyHidden>
75
+ {children}
76
+ </CheckboxProvider>
77
+ </BaseCheckbox>
78
+ );
79
+ });
@@ -0,0 +1,43 @@
1
+ import type React from 'react';
2
+ import { createCheckboxGroup } from './createCheckboxGroup';
3
+ import { createCheckboxIcon } from './createCheckboxIcon';
4
+ import { createCheckboxIndicator } from './createCheckboxIndicator';
5
+ import { createCheckboxLabel } from './createCheckboxLabel';
6
+ import { createCheckboxRoot } from './createCheckboxRoot';
7
+ import type { ICheckboxComponentType } from './types';
8
+
9
+ export type {
10
+ ICheckboxComponentType,
11
+ ICheckboxGroupProps,
12
+ ICheckboxIconProps,
13
+ ICheckboxIndicatorProps,
14
+ ICheckboxLabelProps,
15
+ ICheckboxProps,
16
+ } from './types';
17
+
18
+ export function createCheckbox<Root, Indicator, Icon, Label, Group>(BaseComponents: {
19
+ Root: React.ComponentType<Root>;
20
+ Indicator: React.ComponentType<Indicator>;
21
+ Icon: React.ComponentType<Icon>;
22
+ Label: React.ComponentType<Label>;
23
+ Group: React.ComponentType<Group>;
24
+ }) {
25
+ const Checkbox = createCheckboxRoot(BaseComponents.Root);
26
+ const Indicator = createCheckboxIndicator(BaseComponents.Indicator);
27
+ const Icon = createCheckboxIcon(BaseComponents.Icon);
28
+ const Label = createCheckboxLabel(BaseComponents.Label);
29
+ const Group = createCheckboxGroup(BaseComponents.Group);
30
+
31
+ Checkbox.displayName = 'CheckboxPrimitive';
32
+ Indicator.displayName = 'CheckboxPrimitive.Indicator';
33
+ Icon.displayName = 'CheckboxPrimitive.Icon';
34
+ Label.displayName = 'CheckboxPrimitive.Label';
35
+ Group.displayName = 'CheckboxPrimitive.Group';
36
+
37
+ return Object.assign(Checkbox, {
38
+ Indicator,
39
+ Icon,
40
+ Label,
41
+ Group,
42
+ }) as ICheckboxComponentType<Root, Indicator, Icon, Label, Group>;
43
+ }
@@ -0,0 +1,74 @@
1
+ import type { PressableProps } from 'react-native';
2
+ export interface InterfaceCheckbox extends PressableProps {
3
+ value: string;
4
+ onChange?: (isSelected: boolean) => void;
5
+ children?: React.ReactNode;
6
+ defaultIsChecked?: boolean;
7
+ isChecked?: boolean;
8
+ isDisabled?: boolean;
9
+ isInvalid?: boolean;
10
+ isReadOnly?: boolean;
11
+ isHovered?: boolean;
12
+ isFocused?: boolean;
13
+ isPressed?: boolean;
14
+ isRequired?: boolean;
15
+ isIndeterminate?: boolean;
16
+ isFocusVisible?: boolean;
17
+ }
18
+
19
+ export interface ICheckboxGroupProps {
20
+ value: string[];
21
+ onChange?: (values: string[]) => void;
22
+ children?: React.ReactNode;
23
+ isDisabled?: boolean;
24
+ isInvalid?: boolean;
25
+ isReadOnly?: boolean;
26
+ isRequired?: boolean;
27
+ 'aria-label'?: string;
28
+ }
29
+
30
+ export type ICheckboxComponentType<Root, Indicator, Icon, Label, Group> =
31
+ React.ForwardRefExoticComponent<
32
+ React.RefAttributes<Root> & React.PropsWithoutRef<Root> & InterfaceCheckbox
33
+ > & {
34
+ Indicator: React.ForwardRefExoticComponent<
35
+ React.RefAttributes<Indicator> & React.PropsWithoutRef<Indicator> & ICheckboxIndicatorProps
36
+ >;
37
+ Icon: React.ForwardRefExoticComponent<
38
+ React.RefAttributes<Icon> & React.PropsWithoutRef<Icon> & ICheckboxIconProps
39
+ >;
40
+ Label: React.ForwardRefExoticComponent<
41
+ React.RefAttributes<Label> & React.PropsWithoutRef<Label> & ICheckboxLabelProps
42
+ >;
43
+ Group: React.ForwardRefExoticComponent<
44
+ React.RefAttributes<Group> & React.PropsWithoutRef<Group> & ICheckboxGroupProps
45
+ >;
46
+ };
47
+
48
+ export interface ICheckboxIndicatorProps {
49
+ children?: React.ReactNode;
50
+ }
51
+
52
+ export interface ICheckboxIconProps {
53
+ children?: React.ReactNode;
54
+ /** Render the icon even when unchecked */
55
+ forceMount?: boolean;
56
+ }
57
+
58
+ export interface ICheckboxLabelProps {
59
+ children?: React.ReactNode;
60
+ }
61
+
62
+ export type ICheckboxProps = InterfaceCheckbox;
63
+
64
+ export interface ICheckboxContextValue {
65
+ isChecked?: boolean;
66
+ isDisabled?: boolean;
67
+ isHovered?: boolean;
68
+ isInvalid?: boolean;
69
+ isReadOnly?: boolean;
70
+ isPressed?: boolean;
71
+ isFocused?: boolean;
72
+ isIndeterminate?: boolean;
73
+ isFocusVisible?: boolean;
74
+ }
@@ -0,0 +1,85 @@
1
+ import { useContext, useRef } from 'react';
2
+ import { mergeRefs, useFormControlContext } from '@cdx-ui/utils';
3
+ import { useCheckbox } from '@react-native-aria/checkbox';
4
+ import { useHover } from '@react-native-aria/interactions';
5
+ import { useToggleState } from '@react-stately/toggle';
6
+ import { CheckboxGroupContext } from './context';
7
+ import type { ICheckboxProps } from './types';
8
+
9
+ interface UseCheckboxRootOptions {
10
+ useInputRefForAria?: boolean;
11
+ }
12
+
13
+ export function useCheckboxRoot(
14
+ props: ICheckboxProps,
15
+ ref?: React.Ref<unknown>,
16
+ { useInputRefForAria = false }: UseCheckboxRootOptions = {},
17
+ ) {
18
+ const formControlContext = useFormControlContext();
19
+
20
+ const { isInvalid, isReadOnly, isIndeterminate, ...combinedProps } = {
21
+ ...formControlContext,
22
+ ...props,
23
+ };
24
+
25
+ const checkboxGroupContext = useContext(CheckboxGroupContext);
26
+
27
+ const state = useToggleState({
28
+ ...combinedProps,
29
+ defaultSelected: props.defaultIsChecked,
30
+ isSelected: props.isChecked,
31
+ });
32
+
33
+ const rootRef = useRef(null);
34
+ const inputRef = useRef<HTMLInputElement | null>(null);
35
+ const mergedRootRef = mergeRefs(ref as any, rootRef as any);
36
+ const ariaLabel = combinedProps['aria-label'] || combinedProps.value || 'Checkbox';
37
+
38
+ const groupToggleState = useToggleState(
39
+ checkboxGroupContext
40
+ ? {
41
+ isReadOnly: isReadOnly || checkboxGroupContext.state.isReadOnly,
42
+ isSelected: checkboxGroupContext.state.isSelected(combinedProps.value),
43
+ onChange(isSelected: boolean) {
44
+ if (isSelected) {
45
+ checkboxGroupContext.state.addValue(combinedProps.value);
46
+ } else {
47
+ checkboxGroupContext.state.removeValue(combinedProps.value);
48
+ }
49
+ combinedProps.onChange?.(isSelected);
50
+ },
51
+ }
52
+ : { isSelected: false },
53
+ );
54
+
55
+ const { inputProps: groupItemInputProps } = useCheckbox(
56
+ {
57
+ ...combinedProps,
58
+ 'aria-label': ariaLabel,
59
+ ...(checkboxGroupContext && {
60
+ isReadOnly: isReadOnly || checkboxGroupContext.state.isReadOnly,
61
+ isDisabled: combinedProps.isDisabled || checkboxGroupContext.state.isDisabled,
62
+ }),
63
+ } as any,
64
+ checkboxGroupContext ? groupToggleState : state,
65
+ (useInputRefForAria ? inputRef : rootRef) as any,
66
+ );
67
+
68
+ const { checked: isChecked, disabled: isDisabled } = groupItemInputProps;
69
+
70
+ const { hoverProps, isHovered } = useHover({}, rootRef);
71
+
72
+ return {
73
+ combinedProps,
74
+ isInvalid,
75
+ isReadOnly,
76
+ isIndeterminate,
77
+ groupItemInputProps,
78
+ isChecked,
79
+ isDisabled,
80
+ isHovered,
81
+ hoverProps,
82
+ mergedRef: mergedRootRef,
83
+ inputRef,
84
+ };
85
+ }
package/src/index.ts CHANGED
@@ -1,4 +1,9 @@
1
+ export * from './avatar';
1
2
  export * from './button';
3
+ export * from './checkbox';
2
4
  export * from './input';
5
+ export * from './link';
6
+ export { type EdgeInsets, OverlayInsetsProvider } from './overlay';
3
7
  export * from './select';
4
- export { OverlayInsetsProvider, type EdgeInsets } from './overlay';
8
+ export * from './switch';
9
+ export type { InteractionState } from './types';
@@ -1,5 +1,5 @@
1
+ import type React from 'react';
1
2
  import { createInputField } from './createInputField';
2
- import { createInputIcon } from './createInputIcon';
3
3
  import { createInputRoot } from './createInputRoot';
4
4
  import { createInputSlot } from './createInputSlot';
5
5
  import type { IInputComponentType } from './types';
@@ -12,40 +12,27 @@ export type {
12
12
  IInputSlotProps,
13
13
  } from './types';
14
14
 
15
- export const createInput = <
15
+ export function createInput<
16
16
  RootProps,
17
- IconProps,
18
17
  SlotProps,
19
18
  FieldProps,
20
19
  RootRef = unknown,
21
20
  FieldRef = unknown,
22
- >({
23
- Root,
24
- Icon,
25
- Slot,
26
- Field,
27
- }: {
21
+ >(BaseComponents: {
28
22
  Root: React.ComponentType<RootProps>;
29
- Icon: React.ComponentType<IconProps>;
30
23
  Slot: React.ComponentType<SlotProps>;
31
24
  Field: React.ComponentType<FieldProps>;
32
- }) => {
33
- const Input = createInputRoot(Root) as any;
34
- Input.Icon = createInputIcon(Icon);
35
- Input.Slot = createInputSlot(Slot);
36
- Input.Field = createInputField(Field);
25
+ }) {
26
+ const Input = createInputRoot(BaseComponents.Root);
27
+ const Slot = createInputSlot(BaseComponents.Slot);
28
+ const Field = createInputField(BaseComponents.Field);
37
29
 
38
- Input.displayName = 'Input';
39
- Input.Icon.displayName = 'Input.Icon';
40
- Input.Slot.displayName = 'Input.Slot';
41
- Input.Field.displayName = 'Input.Field';
30
+ Input.displayName = 'InputPrimitive';
31
+ Slot.displayName = 'InputPrimitive.Slot';
32
+ Field.displayName = 'InputPrimitive.Field';
42
33
 
43
- return Input as IInputComponentType<
44
- RootProps,
45
- IconProps,
46
- SlotProps,
47
- FieldProps,
48
- RootRef,
49
- FieldRef
50
- >;
51
- };
34
+ return Object.assign(Input, {
35
+ Slot,
36
+ Field,
37
+ }) as IInputComponentType<RootProps, SlotProps, FieldProps, RootRef, FieldRef>;
38
+ }
@@ -93,7 +93,6 @@ export interface IInputSlotProps extends ViewProps {
93
93
 
94
94
  export type IInputComponentType<
95
95
  RootProps,
96
- IconProps,
97
96
  SlotProps,
98
97
  FieldProps,
99
98
  RootRef = unknown,
@@ -101,9 +100,6 @@ export type IInputComponentType<
101
100
  > = React.ForwardRefExoticComponent<
102
101
  React.PropsWithoutRef<RootProps & IInputFieldProps> & React.RefAttributes<RootRef>
103
102
  > & {
104
- Icon: React.ForwardRefExoticComponent<
105
- React.PropsWithoutRef<IconProps> & React.RefAttributes<unknown>
106
- >;
107
103
  Slot: React.ForwardRefExoticComponent<
108
104
  React.PropsWithoutRef<SlotProps & IInputSlotProps> & React.RefAttributes<unknown>
109
105
  >;
@@ -0,0 +1,50 @@
1
+ import { createContext, useContext, type ReactNode } from 'react';
2
+ import type { LinkAction } from './types';
3
+
4
+ export interface LinkConfig {
5
+ /**
6
+ * Global navigation handler for `<Link>` instances whose `href` passes the
7
+ * `shouldNavigate` check. Called with the `href` and the per-instance `action`.
8
+ *
9
+ * @param href - The URL or path to navigate to.
10
+ * @param action - Navigation intent from the per-instance `action` prop:
11
+ * `'navigate'` (default) — smart navigation, avoids duplicates.
12
+ * `'push'` — always pushes a new entry onto the stack.
13
+ * `'replace'` — replaces the current entry without stacking.
14
+ */
15
+ navigate: (href: string, action: LinkAction) => void | Promise<void>;
16
+
17
+ /**
18
+ * Optional predicate evaluated at **render time** to decide whether the
19
+ * provider should handle a given `href`.
20
+ *
21
+ * - Returns `true` → the provider's `navigate` is called on press;
22
+ * on web the native `<a href>` is **removed** so the browser doesn't
23
+ * follow the link.
24
+ * - Returns `false` → the provider is bypassed; on web the `<a href>` is
25
+ * preserved (cmd-click, SEO, etc.); on native `Linking.openURL` is used.
26
+ *
27
+ * Defaults to `() => true` when omitted (all hrefs go through the provider).
28
+ */
29
+ shouldNavigate?: (href: string) => boolean;
30
+ }
31
+
32
+ const LinkConfigContext = createContext<LinkConfig | undefined>(undefined);
33
+
34
+ export function LinkProvider({
35
+ navigate,
36
+ shouldNavigate,
37
+ children,
38
+ }: LinkConfig & { children: ReactNode }) {
39
+ return (
40
+ <LinkConfigContext.Provider value={{ navigate, shouldNavigate }}>
41
+ {children}
42
+ </LinkConfigContext.Provider>
43
+ );
44
+ }
45
+
46
+ LinkProvider.displayName = 'LinkProvider';
47
+
48
+ export function useLinkConfig(): LinkConfig | undefined {
49
+ return useContext(LinkConfigContext);
50
+ }
@@ -0,0 +1,71 @@
1
+ import React, { forwardRef } from 'react';
2
+ import { composeEventHandlers } from '@cdx-ui/utils';
3
+ import { useFocusRing, useFocus } from '@react-native-aria/focus';
4
+ import { useHover, usePress } from '@react-native-aria/interactions';
5
+ import { dataAttributes } from '../utils/dataAttributes';
6
+ import { useLink } from './useLink';
7
+ import type { ILinkProps } from './types';
8
+
9
+ export const createLink = <RootT, R = unknown>({ Root }: { Root: React.ComponentType<RootT> }) =>
10
+ forwardRef(
11
+ (
12
+ {
13
+ children,
14
+ isHovered: isHoveredProp,
15
+ isPressed: isPressedProp,
16
+ isFocused: isFocusedProp,
17
+ isFocusVisible: isFocusVisibleProp,
18
+ href,
19
+ onPress,
20
+ action,
21
+ webProps,
22
+ ...props
23
+ }: ILinkProps,
24
+ ref: React.ForwardedRef<R>,
25
+ ) => {
26
+ const { isFocused, focusProps } = useFocus();
27
+ const { isFocusVisible, focusProps: focusRingProps } = useFocusRing() as {
28
+ isFocusVisible: boolean;
29
+ focusProps: typeof focusProps;
30
+ };
31
+ const { pressProps, isPressed } = usePress({});
32
+ const { isHovered, hoverProps } = useHover();
33
+
34
+ const { linkProps } = useLink({
35
+ href,
36
+ onPress,
37
+ action,
38
+ webProps,
39
+ });
40
+
41
+ const interactionAttrs = dataAttributes({
42
+ hover: isHoveredProp || isHovered,
43
+ focus: isFocusedProp || isFocused,
44
+ active: isPressedProp || isPressed,
45
+ focusVisible: isFocusVisibleProp || isFocusVisible,
46
+ });
47
+
48
+ return (
49
+ <Root
50
+ ref={ref}
51
+ {...interactionAttrs}
52
+ {...linkProps}
53
+ {...(props as RootT)}
54
+ onPressIn={composeEventHandlers(props?.onPressIn, pressProps.onPressIn)}
55
+ onPressOut={composeEventHandlers(props?.onPressOut, pressProps.onPressOut)}
56
+ onHoverIn={composeEventHandlers(props?.onHoverIn, hoverProps.onHoverIn)}
57
+ onHoverOut={composeEventHandlers(props?.onHoverOut, hoverProps.onHoverOut)}
58
+ onFocus={composeEventHandlers(
59
+ composeEventHandlers(props?.onFocus, focusProps.onFocus),
60
+ focusRingProps.onFocus,
61
+ )}
62
+ onBlur={composeEventHandlers(
63
+ composeEventHandlers(props?.onBlur, focusProps.onBlur),
64
+ focusRingProps.onBlur,
65
+ )}
66
+ >
67
+ {children}
68
+ </Root>
69
+ );
70
+ },
71
+ );
@@ -0,0 +1,5 @@
1
+ export { createLink } from './createLink';
2
+ export { LinkProvider } from './LinkProvider';
3
+ export type { LinkConfig } from './LinkProvider';
4
+ export { useLink } from './useLink';
5
+ export type { ILinkProps, IUseLinkProp, LinkAction } from './types';
@@ -0,0 +1,47 @@
1
+ import type React from 'react';
2
+ import type { GestureResponderEvent, PressableProps } from 'react-native';
3
+
4
+ /**
5
+ * Navigation action forwarded to the `LinkProvider.navigate` callback.
6
+ *
7
+ * - `'navigate'` — (default) Smart navigation. In React Navigation this
8
+ * avoids duplicating a screen that is already in the stack. In expo-router
9
+ * it maps to `router.navigate()`.
10
+ * - `'push'` — Always pushes a new screen onto the navigation stack,
11
+ * even if the destination is already present.
12
+ * - `'replace'` — Replaces the current screen without adding to the stack.
13
+ * Useful for post-login redirects or wizard flows.
14
+ */
15
+ export type LinkAction = 'navigate' | 'push' | 'replace';
16
+
17
+ export interface ILinkProps extends PressableProps {
18
+ /**
19
+ * URL that should be opened on Link press
20
+ */
21
+ href?: string | undefined;
22
+ /**
23
+ * Callback that will be invoked on Link press
24
+ */
25
+ onPress?: ((event?: GestureResponderEvent) => void) | null | undefined;
26
+ /**
27
+ * Navigation action forwarded to the `LinkProvider`.
28
+ * Defaults to `'navigate'`.
29
+ */
30
+ action?: LinkAction;
31
+ isPressed?: boolean;
32
+ isHovered?: boolean;
33
+ isFocused?: boolean;
34
+ isFocusVisible?: boolean;
35
+ /**
36
+ * HTML anchor attributes applied only on web. Ignored on native platforms.
37
+ * `target`, `rel`, and `download` are forwarded via react-native-web's `hrefAttrs`.
38
+ */
39
+ webProps?: React.AnchorHTMLAttributes<HTMLAnchorElement>;
40
+ }
41
+
42
+ export interface IUseLinkProp {
43
+ href?: string;
44
+ onPress: ((event?: GestureResponderEvent) => void) | null | undefined;
45
+ action?: LinkAction;
46
+ webProps?: React.AnchorHTMLAttributes<HTMLAnchorElement>;
47
+ }
@@ -0,0 +1,54 @@
1
+ import { Linking, Platform } from 'react-native';
2
+ import type { AccessibilityRole, GestureResponderEvent } from 'react-native';
3
+ import { useLinkConfig } from './LinkProvider';
4
+ import type { IUseLinkProp } from './types';
5
+
6
+ function defaultNavigate(href: string): void {
7
+ Linking.canOpenURL(href)
8
+ .then((supported) => {
9
+ if (supported) return Linking.openURL(href);
10
+ console.warn(`Cannot open URL: ${href}`);
11
+ })
12
+ .catch((err: unknown) => console.error('Failed to open URL', err));
13
+ }
14
+
15
+ export function useLink(props: IUseLinkProp) {
16
+ const { href, onPress, action = 'navigate', webProps } = props;
17
+ const config = useLinkConfig();
18
+
19
+ const providerHandles = !!config && !!href && (config.shouldNavigate?.(href) ?? true);
20
+
21
+ let platformLinkProps = {};
22
+
23
+ if (Platform.OS === 'web') {
24
+ platformLinkProps = {
25
+ href: providerHandles ? undefined : href,
26
+ hrefAttrs: webProps,
27
+ onPress: (event: GestureResponderEvent) => {
28
+ onPress?.(event);
29
+ if (providerHandles) void config.navigate(href, action);
30
+ },
31
+ };
32
+ } else {
33
+ platformLinkProps = {
34
+ onPress: (event: GestureResponderEvent) => {
35
+ onPress?.(event);
36
+ if (href) {
37
+ if (providerHandles) {
38
+ void config.navigate(href, action);
39
+ } else {
40
+ defaultNavigate(href);
41
+ }
42
+ }
43
+ },
44
+ };
45
+ }
46
+
47
+ return {
48
+ linkProps: {
49
+ ...platformLinkProps,
50
+ role: 'link' as AccessibilityRole,
51
+ accessible: true,
52
+ },
53
+ };
54
+ }
@@ -5,6 +5,7 @@ import {
5
5
  Pressable,
6
6
  type StyleProp,
7
7
  StyleSheet,
8
+ View,
8
9
  type ViewStyle,
9
10
  } from 'react-native';
10
11
  import Animated, { type EntryOrExitLayoutType } from 'react-native-reanimated';
@@ -30,7 +31,11 @@ export interface OverlayContainerProps {
30
31
  * Cross-platform overlay container.
31
32
  *
32
33
  * - Web: renders children into a `createPortal` at `document.body` with
33
- * `position: fixed` and `zIndex: 50`.
34
+ * `position: fixed` and `zIndex: 50`. Uses a plain `View` rather than
35
+ * Reanimated's `Animated.View` because Reanimated's layout animations
36
+ * (`entering`/`exiting`) rely on `require()` calls that break silently
37
+ * in Vite production bundles, leaving elements stuck at opacity 0.
38
+ * See: https://github.com/software-mansion/react-native-reanimated/issues/6775
34
39
  * - Native: renders children inside a transparent `<Modal>` with a
35
40
  * backdrop `<Pressable>` that calls `onDismiss` on press.
36
41
  *
@@ -46,13 +51,7 @@ export function OverlayContainer({
46
51
  }: Readonly<OverlayContainerProps>) {
47
52
  if (Platform.OS === 'web' && createPortalFn) {
48
53
  return createPortalFn(
49
- <Animated.View
50
- entering={entering}
51
- exiting={exiting}
52
- style={[{ position: 'fixed' as any, zIndex: 50 }, style]}
53
- >
54
- {children}
55
- </Animated.View>,
54
+ <View style={[{ position: 'fixed' as any, zIndex: 50 }, style]}>{children}</View>,
56
55
  document.body,
57
56
  );
58
57
  }