@cdx-ui/components 0.0.1-beta.64 → 0.0.1-beta.66

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 (263) hide show
  1. package/lib/commonjs/components/AlertDialog/index.js +12 -10
  2. package/lib/commonjs/components/AlertDialog/index.js.map +1 -1
  3. package/lib/commonjs/components/Avatar/index.js +125 -25
  4. package/lib/commonjs/components/Avatar/index.js.map +1 -1
  5. package/lib/commonjs/components/Button/index.js +127 -28
  6. package/lib/commonjs/components/Button/index.js.map +1 -1
  7. package/lib/commonjs/components/Button/styles.js +9 -3
  8. package/lib/commonjs/components/Button/styles.js.map +1 -1
  9. package/lib/commonjs/components/CLAUDE.md +115 -11
  10. package/lib/commonjs/components/Checkbox/index.js +69 -22
  11. package/lib/commonjs/components/Checkbox/index.js.map +1 -1
  12. package/lib/commonjs/components/Checkbox/styles.js +1 -1
  13. package/lib/commonjs/components/Checkbox/styles.js.map +1 -1
  14. package/lib/commonjs/components/Chip/index.js +44 -36
  15. package/lib/commonjs/components/Chip/index.js.map +1 -1
  16. package/lib/commonjs/components/Chip/styles.js +6 -35
  17. package/lib/commonjs/components/Chip/styles.js.map +1 -1
  18. package/lib/commonjs/components/Dialog/index.js +92 -72
  19. package/lib/commonjs/components/Dialog/index.js.map +1 -1
  20. package/lib/commonjs/components/Field/index.js +70 -26
  21. package/lib/commonjs/components/Field/index.js.map +1 -1
  22. package/lib/commonjs/components/Form/index.js +5 -12
  23. package/lib/commonjs/components/Form/index.js.map +1 -1
  24. package/lib/commonjs/components/IconButton/index.js +5 -33
  25. package/lib/commonjs/components/IconButton/index.js.map +1 -1
  26. package/lib/commonjs/components/Input/index.js +50 -20
  27. package/lib/commonjs/components/Input/index.js.map +1 -1
  28. package/lib/commonjs/components/Link/index.js +14 -7
  29. package/lib/commonjs/components/Link/index.js.map +1 -1
  30. package/lib/commonjs/components/ListItem/index.js +129 -54
  31. package/lib/commonjs/components/ListItem/index.js.map +1 -1
  32. package/lib/commonjs/components/OtpInput/index.js +94 -28
  33. package/lib/commonjs/components/OtpInput/index.js.map +1 -1
  34. package/lib/commonjs/components/ProgressBar/index.js +8 -13
  35. package/lib/commonjs/components/ProgressBar/index.js.map +1 -1
  36. package/lib/commonjs/components/Radio/index.js +51 -53
  37. package/lib/commonjs/components/Radio/index.js.map +1 -1
  38. package/lib/commonjs/components/Select/index.js +112 -46
  39. package/lib/commonjs/components/Select/index.js.map +1 -1
  40. package/lib/commonjs/components/Select/styles.js +2 -2
  41. package/lib/commonjs/components/Select/styles.js.map +1 -1
  42. package/lib/commonjs/components/Skeleton/index.js +37 -0
  43. package/lib/commonjs/components/Skeleton/index.js.map +1 -0
  44. package/lib/commonjs/components/Skeleton/styles.js +9 -0
  45. package/lib/commonjs/components/Skeleton/styles.js.map +1 -0
  46. package/lib/commonjs/components/Switch/BaseSwitch.js +23 -13
  47. package/lib/commonjs/components/Switch/BaseSwitch.js.map +1 -1
  48. package/lib/commonjs/components/Switch/BaseSwitch.web.js +25 -21
  49. package/lib/commonjs/components/Switch/BaseSwitch.web.js.map +1 -1
  50. package/lib/commonjs/components/Switch/index.js +34 -3
  51. package/lib/commonjs/components/Switch/index.js.map +1 -1
  52. package/lib/commonjs/components/Tile/index.js +150 -77
  53. package/lib/commonjs/components/Tile/index.js.map +1 -1
  54. package/lib/commonjs/components/index.js +12 -0
  55. package/lib/commonjs/components/index.js.map +1 -1
  56. package/lib/commonjs/figma/Chip.figma.js +2 -2
  57. package/lib/commonjs/figma/Chip.figma.js.map +1 -1
  58. package/lib/commonjs/utils/positionToDataIcon.js +41 -0
  59. package/lib/commonjs/utils/positionToDataIcon.js.map +1 -0
  60. package/lib/module/components/AlertDialog/index.js +13 -11
  61. package/lib/module/components/AlertDialog/index.js.map +1 -1
  62. package/lib/module/components/Avatar/index.js +128 -28
  63. package/lib/module/components/Avatar/index.js.map +1 -1
  64. package/lib/module/components/Button/index.js +130 -32
  65. package/lib/module/components/Button/index.js.map +1 -1
  66. package/lib/module/components/Button/styles.js +8 -2
  67. package/lib/module/components/Button/styles.js.map +1 -1
  68. package/lib/module/components/CLAUDE.md +115 -11
  69. package/lib/module/components/Checkbox/index.js +72 -25
  70. package/lib/module/components/Checkbox/index.js.map +1 -1
  71. package/lib/module/components/Checkbox/styles.js +1 -1
  72. package/lib/module/components/Checkbox/styles.js.map +1 -1
  73. package/lib/module/components/Chip/index.js +47 -39
  74. package/lib/module/components/Chip/index.js.map +1 -1
  75. package/lib/module/components/Chip/styles.js +6 -35
  76. package/lib/module/components/Chip/styles.js.map +1 -1
  77. package/lib/module/components/Dialog/index.js +96 -76
  78. package/lib/module/components/Dialog/index.js.map +1 -1
  79. package/lib/module/components/Field/index.js +74 -31
  80. package/lib/module/components/Field/index.js.map +1 -1
  81. package/lib/module/components/Form/index.js +7 -14
  82. package/lib/module/components/Form/index.js.map +1 -1
  83. package/lib/module/components/IconButton/index.js +6 -34
  84. package/lib/module/components/IconButton/index.js.map +1 -1
  85. package/lib/module/components/Input/index.js +53 -23
  86. package/lib/module/components/Input/index.js.map +1 -1
  87. package/lib/module/components/Link/index.js +16 -8
  88. package/lib/module/components/Link/index.js.map +1 -1
  89. package/lib/module/components/ListItem/index.js +134 -59
  90. package/lib/module/components/ListItem/index.js.map +1 -1
  91. package/lib/module/components/OtpInput/index.js +94 -28
  92. package/lib/module/components/OtpInput/index.js.map +1 -1
  93. package/lib/module/components/ProgressBar/index.js +9 -14
  94. package/lib/module/components/ProgressBar/index.js.map +1 -1
  95. package/lib/module/components/Radio/index.js +54 -57
  96. package/lib/module/components/Radio/index.js.map +1 -1
  97. package/lib/module/components/Select/index.js +118 -52
  98. package/lib/module/components/Select/index.js.map +1 -1
  99. package/lib/module/components/Select/styles.js +2 -2
  100. package/lib/module/components/Select/styles.js.map +1 -1
  101. package/lib/module/components/Skeleton/index.js +32 -0
  102. package/lib/module/components/Skeleton/index.js.map +1 -0
  103. package/lib/module/components/Skeleton/styles.js +5 -0
  104. package/lib/module/components/Skeleton/styles.js.map +1 -0
  105. package/lib/module/components/Switch/BaseSwitch.js +24 -14
  106. package/lib/module/components/Switch/BaseSwitch.js.map +1 -1
  107. package/lib/module/components/Switch/BaseSwitch.web.js +26 -22
  108. package/lib/module/components/Switch/BaseSwitch.web.js.map +1 -1
  109. package/lib/module/components/Switch/index.js +35 -4
  110. package/lib/module/components/Switch/index.js.map +1 -1
  111. package/lib/module/components/Tile/index.js +155 -83
  112. package/lib/module/components/Tile/index.js.map +1 -1
  113. package/lib/module/components/index.js +1 -0
  114. package/lib/module/components/index.js.map +1 -1
  115. package/lib/module/figma/Chip.figma.js +2 -2
  116. package/lib/module/figma/Chip.figma.js.map +1 -1
  117. package/lib/module/utils/positionToDataIcon.js +38 -0
  118. package/lib/module/utils/positionToDataIcon.js.map +1 -0
  119. package/lib/typescript/components/AlertDialog/index.d.ts.map +1 -1
  120. package/lib/typescript/components/Avatar/index.d.ts +6 -2
  121. package/lib/typescript/components/Avatar/index.d.ts.map +1 -1
  122. package/lib/typescript/components/Button/index.d.ts +31 -8
  123. package/lib/typescript/components/Button/index.d.ts.map +1 -1
  124. package/lib/typescript/components/Button/styles.d.ts +2 -1
  125. package/lib/typescript/components/Button/styles.d.ts.map +1 -1
  126. package/lib/typescript/components/Checkbox/index.d.ts +3 -1
  127. package/lib/typescript/components/Checkbox/index.d.ts.map +1 -1
  128. package/lib/typescript/components/Chip/index.d.ts +19 -9
  129. package/lib/typescript/components/Chip/index.d.ts.map +1 -1
  130. package/lib/typescript/components/Chip/styles.d.ts +0 -1
  131. package/lib/typescript/components/Chip/styles.d.ts.map +1 -1
  132. package/lib/typescript/components/Dialog/index.d.ts +12 -6
  133. package/lib/typescript/components/Dialog/index.d.ts.map +1 -1
  134. package/lib/typescript/components/Dialog/styles.d.ts +1 -1
  135. package/lib/typescript/components/Field/index.d.ts +14 -7
  136. package/lib/typescript/components/Field/index.d.ts.map +1 -1
  137. package/lib/typescript/components/Form/index.d.ts +4 -4
  138. package/lib/typescript/components/Form/index.d.ts.map +1 -1
  139. package/lib/typescript/components/IconButton/index.d.ts.map +1 -1
  140. package/lib/typescript/components/Input/index.d.ts +11 -3
  141. package/lib/typescript/components/Input/index.d.ts.map +1 -1
  142. package/lib/typescript/components/Link/index.d.ts +2 -0
  143. package/lib/typescript/components/Link/index.d.ts.map +1 -1
  144. package/lib/typescript/components/ListItem/index.d.ts +28 -6
  145. package/lib/typescript/components/ListItem/index.d.ts.map +1 -1
  146. package/lib/typescript/components/OtpInput/index.d.ts +1 -1
  147. package/lib/typescript/components/OtpInput/index.d.ts.map +1 -1
  148. package/lib/typescript/components/ProgressBar/index.d.ts +4 -4
  149. package/lib/typescript/components/ProgressBar/index.d.ts.map +1 -1
  150. package/lib/typescript/components/Radio/index.d.ts +4 -0
  151. package/lib/typescript/components/Radio/index.d.ts.map +1 -1
  152. package/lib/typescript/components/Select/index.d.ts +35 -2
  153. package/lib/typescript/components/Select/index.d.ts.map +1 -1
  154. package/lib/typescript/components/Select/styles.d.ts.map +1 -1
  155. package/lib/typescript/components/Skeleton/index.d.ts +9 -0
  156. package/lib/typescript/components/Skeleton/index.d.ts.map +1 -0
  157. package/lib/typescript/components/Skeleton/styles.d.ts +4 -0
  158. package/lib/typescript/components/Skeleton/styles.d.ts.map +1 -0
  159. package/lib/typescript/components/Switch/BaseSwitch.d.ts +12 -5
  160. package/lib/typescript/components/Switch/BaseSwitch.d.ts.map +1 -1
  161. package/lib/typescript/components/Switch/BaseSwitch.web.d.ts +11 -5
  162. package/lib/typescript/components/Switch/BaseSwitch.web.d.ts.map +1 -1
  163. package/lib/typescript/components/Switch/index.d.ts +5 -1
  164. package/lib/typescript/components/Switch/index.d.ts.map +1 -1
  165. package/lib/typescript/components/Tile/index.d.ts +8 -2
  166. package/lib/typescript/components/Tile/index.d.ts.map +1 -1
  167. package/lib/typescript/components/index.d.ts +1 -0
  168. package/lib/typescript/components/index.d.ts.map +1 -1
  169. package/lib/typescript/utils/positionToDataIcon.d.ts +29 -0
  170. package/lib/typescript/utils/positionToDataIcon.d.ts.map +1 -0
  171. package/package.json +5 -5
  172. package/src/components/AlertDialog/index.tsx +13 -14
  173. package/src/components/Avatar/index.tsx +134 -44
  174. package/src/components/Button/index.tsx +216 -44
  175. package/src/components/Button/styles.ts +50 -38
  176. package/src/components/CLAUDE.md +115 -11
  177. package/src/components/Checkbox/index.tsx +93 -32
  178. package/src/components/Checkbox/styles.ts +1 -1
  179. package/src/components/Chip/index.tsx +88 -61
  180. package/src/components/Chip/styles.ts +6 -18
  181. package/src/components/Dialog/index.tsx +139 -99
  182. package/src/components/Field/index.tsx +113 -49
  183. package/src/components/Form/index.tsx +18 -14
  184. package/src/components/IconButton/index.tsx +7 -31
  185. package/src/components/Input/index.tsx +75 -32
  186. package/src/components/Link/index.tsx +38 -12
  187. package/src/components/ListItem/index.tsx +158 -73
  188. package/src/components/OtpInput/index.tsx +126 -43
  189. package/src/components/ProgressBar/index.tsx +11 -16
  190. package/src/components/Radio/index.tsx +76 -54
  191. package/src/components/Select/index.tsx +174 -59
  192. package/src/components/Select/styles.ts +1 -2
  193. package/src/components/Skeleton/index.tsx +42 -0
  194. package/src/components/Skeleton/styles.ts +5 -0
  195. package/src/components/Switch/BaseSwitch.tsx +38 -16
  196. package/src/components/Switch/BaseSwitch.web.tsx +28 -35
  197. package/src/components/Switch/index.tsx +51 -4
  198. package/src/components/Tile/index.tsx +145 -94
  199. package/src/components/index.ts +1 -0
  200. package/src/utils/positionToDataIcon.ts +34 -0
  201. package/lib/commonjs/components/Field/FieldLabel.js +0 -33
  202. package/lib/commonjs/components/Field/FieldLabel.js.map +0 -1
  203. package/lib/commonjs/components/Field/FieldLabel.web.js +0 -22
  204. package/lib/commonjs/components/Field/FieldLabel.web.js.map +0 -1
  205. package/lib/commonjs/components/Form/FormRoot.js +0 -25
  206. package/lib/commonjs/components/Form/FormRoot.js.map +0 -1
  207. package/lib/commonjs/components/Form/FormRoot.web.js +0 -17
  208. package/lib/commonjs/components/Form/FormRoot.web.js.map +0 -1
  209. package/lib/commonjs/components/Input/BaseInput.android.js +0 -20
  210. package/lib/commonjs/components/Input/BaseInput.android.js.map +0 -1
  211. package/lib/commonjs/components/Input/BaseInput.js +0 -13
  212. package/lib/commonjs/components/Input/BaseInput.js.map +0 -1
  213. package/lib/commonjs/components/Input/BaseInput.web.js +0 -50
  214. package/lib/commonjs/components/Input/BaseInput.web.js.map +0 -1
  215. package/lib/commonjs/components/Select/SelectTriggerHost.js +0 -10
  216. package/lib/commonjs/components/Select/SelectTriggerHost.js.map +0 -1
  217. package/lib/commonjs/components/Select/SelectTriggerHost.web.js +0 -102
  218. package/lib/commonjs/components/Select/SelectTriggerHost.web.js.map +0 -1
  219. package/lib/module/components/Field/FieldLabel.js +0 -29
  220. package/lib/module/components/Field/FieldLabel.js.map +0 -1
  221. package/lib/module/components/Field/FieldLabel.web.js +0 -17
  222. package/lib/module/components/Field/FieldLabel.web.js.map +0 -1
  223. package/lib/module/components/Form/FormRoot.js +0 -21
  224. package/lib/module/components/Form/FormRoot.js.map +0 -1
  225. package/lib/module/components/Form/FormRoot.web.js +0 -12
  226. package/lib/module/components/Form/FormRoot.web.js.map +0 -1
  227. package/lib/module/components/Input/BaseInput.android.js +0 -16
  228. package/lib/module/components/Input/BaseInput.android.js.map +0 -1
  229. package/lib/module/components/Input/BaseInput.js +0 -4
  230. package/lib/module/components/Input/BaseInput.js.map +0 -1
  231. package/lib/module/components/Input/BaseInput.web.js +0 -45
  232. package/lib/module/components/Input/BaseInput.web.js.map +0 -1
  233. package/lib/module/components/Select/SelectTriggerHost.js +0 -7
  234. package/lib/module/components/Select/SelectTriggerHost.js.map +0 -1
  235. package/lib/module/components/Select/SelectTriggerHost.web.js +0 -97
  236. package/lib/module/components/Select/SelectTriggerHost.web.js.map +0 -1
  237. package/lib/typescript/components/Field/FieldLabel.d.ts +0 -18
  238. package/lib/typescript/components/Field/FieldLabel.d.ts.map +0 -1
  239. package/lib/typescript/components/Field/FieldLabel.web.d.ts +0 -16
  240. package/lib/typescript/components/Field/FieldLabel.web.d.ts.map +0 -1
  241. package/lib/typescript/components/Form/FormRoot.d.ts +0 -14
  242. package/lib/typescript/components/Form/FormRoot.d.ts.map +0 -1
  243. package/lib/typescript/components/Form/FormRoot.web.d.ts +0 -10
  244. package/lib/typescript/components/Form/FormRoot.web.d.ts.map +0 -1
  245. package/lib/typescript/components/Input/BaseInput.android.d.ts +0 -3
  246. package/lib/typescript/components/Input/BaseInput.android.d.ts.map +0 -1
  247. package/lib/typescript/components/Input/BaseInput.d.ts +0 -2
  248. package/lib/typescript/components/Input/BaseInput.d.ts.map +0 -1
  249. package/lib/typescript/components/Input/BaseInput.web.d.ts +0 -3
  250. package/lib/typescript/components/Input/BaseInput.web.d.ts.map +0 -1
  251. package/lib/typescript/components/Select/SelectTriggerHost.d.ts +0 -3
  252. package/lib/typescript/components/Select/SelectTriggerHost.d.ts.map +0 -1
  253. package/lib/typescript/components/Select/SelectTriggerHost.web.d.ts +0 -16
  254. package/lib/typescript/components/Select/SelectTriggerHost.web.d.ts.map +0 -1
  255. package/src/components/Field/FieldLabel.tsx +0 -33
  256. package/src/components/Field/FieldLabel.web.tsx +0 -25
  257. package/src/components/Form/FormRoot.tsx +0 -20
  258. package/src/components/Form/FormRoot.web.tsx +0 -12
  259. package/src/components/Input/BaseInput.android.tsx +0 -13
  260. package/src/components/Input/BaseInput.tsx +0 -1
  261. package/src/components/Input/BaseInput.web.tsx +0 -41
  262. package/src/components/Select/SelectTriggerHost.tsx +0 -4
  263. package/src/components/Select/SelectTriggerHost.web.tsx +0 -143
@@ -1,13 +1,14 @@
1
- import { forwardRef, type ReactNode } from 'react';
2
- import { Pressable, Text, View, type TextProps, type ViewProps } from 'react-native';
1
+ import { forwardRef, useMemo, type ReactNode } from 'react';
2
+ import { Text, View, type TextProps, type ViewProps } from 'react-native';
3
3
  import {
4
- createListItem,
5
- type IListItemLeadingSlotProps,
4
+ ListItemRoot as ListItemRootPrimitive,
5
+ Slot,
6
+ dataAttributes,
7
+ mergeDataAttributes,
6
8
  type IListItemProps,
7
- type IListItemSectionHeaderProps,
8
9
  type ListItemCrossAlign,
9
10
  } from '@cdx-ui/primitives';
10
- import { cn, useStyleContext, withStyleContext, type WithStyleContextProps } from '@cdx-ui/utils';
11
+ import { cn, ParentContext, useParentContext, useStyleContext } from '@cdx-ui/utils';
11
12
  import {
12
13
  listItemContentVariants,
13
14
  listItemDescriptionVariants,
@@ -23,21 +24,6 @@ import {
23
24
 
24
25
  const SCOPE = 'LIST_ITEM';
25
26
 
26
- const RootView = withStyleContext(View, SCOPE);
27
- const RootPressable = withStyleContext(Pressable, SCOPE);
28
-
29
- const ListItemPrimitive = createListItem({
30
- View: RootView,
31
- Pressable: RootPressable,
32
- LeadingSlot: View,
33
- Content: View,
34
- Title: Text,
35
- Description: Text,
36
- Meta: Text,
37
- TrailingSlot: View,
38
- SectionHeader: View,
39
- });
40
-
41
27
  const useListItemStyleContext = (): Pick<ListItemVariantProps, 'crossAlign'> => {
42
28
  const ctx = useStyleContext(SCOPE) as ListItemVariantProps | undefined;
43
29
  return { crossAlign: ctx?.crossAlign ?? 'center' };
@@ -47,31 +33,42 @@ const useListItemStyleContext = (): Pick<ListItemVariantProps, 'crossAlign'> =>
47
33
  // ROOT
48
34
  // =============================================================================
49
35
 
50
- export interface ListItemProps extends IListItemProps, WithStyleContextProps {
36
+ export interface ListItemProps extends Omit<IListItemProps, 'crossAlign'>, ListItemVariantProps {
51
37
  className?: string;
52
38
  }
53
39
 
54
40
  const ListItemRoot = forwardRef<View, ListItemProps>(
55
41
  (
56
- { size = 'default', showSeparator = true, crossAlign = 'center', className, style, ...props },
42
+ {
43
+ size = 'default',
44
+ showSeparator = true,
45
+ crossAlign: crossAlignProp = 'center',
46
+ className,
47
+ style,
48
+ ...props
49
+ },
57
50
  ref,
58
51
  ) => {
52
+ const crossAlign: ListItemCrossAlign = crossAlignProp ?? 'center';
53
+ const parent = useParentContext();
54
+ const ctx = useMemo(() => ({ ...parent, [SCOPE]: { crossAlign } }), [parent, crossAlign]);
55
+
59
56
  const computedClassName = cn(
60
57
  listItemRootVariants({ size, showSeparator, crossAlign }),
61
58
  className,
62
59
  );
63
60
 
64
61
  return (
65
- <ListItemPrimitive
66
- ref={ref as never}
67
- className={computedClassName}
68
- context={{ crossAlign }}
69
- crossAlign={crossAlign}
70
- showSeparator={showSeparator}
71
- size={size}
72
- style={style}
73
- {...props}
74
- />
62
+ <ParentContext.Provider value={ctx}>
63
+ <ListItemRootPrimitive
64
+ ref={ref}
65
+ className={computedClassName}
66
+ crossAlign={crossAlign}
67
+ style={style}
68
+ {...props}
69
+ {...mergeDataAttributes(props, dataAttributes({ slot: 'list-item' }))}
70
+ />
71
+ </ParentContext.Provider>
75
72
  );
76
73
  },
77
74
  );
@@ -82,37 +79,62 @@ ListItemRoot.displayName = 'ListItem';
82
79
  // SLOTS & TEXT
83
80
  // =============================================================================
84
81
 
85
- export interface ListItemLeadingSlotProps extends IListItemLeadingSlotProps {
82
+ const leadingSlotStyle = { flexShrink: 0 as const };
83
+
84
+ export interface ListItemLeadingSlotProps extends ViewProps {
85
+ asChild?: boolean;
86
86
  className?: string;
87
+ /**
88
+ * Decorative leading content defaults to hidden from the accessibility tree.
89
+ * Set to `false` when the leading region contains meaningful controls.
90
+ * @default true
91
+ */
92
+ 'aria-hidden'?: boolean;
87
93
  }
88
94
 
89
95
  const ListItemLeadingSlot = forwardRef<View, ListItemLeadingSlotProps>(
90
- ({ className, style, ...props }, ref) => (
91
- <ListItemPrimitive.LeadingSlot
92
- ref={ref as never}
93
- className={cn(listItemLeadingSlotVariants(), className)}
94
- style={style}
95
- {...props}
96
- />
97
- ),
96
+ ({ asChild, className, style, 'aria-hidden': ariaHidden, ...props }, ref) => {
97
+ const accessibilityElementsHidden = ariaHidden !== false;
98
+ const Comp = asChild ? Slot : View;
99
+ return (
100
+ <Comp
101
+ ref={ref}
102
+ accessibilityElementsHidden={accessibilityElementsHidden}
103
+ aria-hidden={ariaHidden ?? true}
104
+ className={cn(listItemLeadingSlotVariants(), className)}
105
+ style={[leadingSlotStyle, style]}
106
+ {...props}
107
+ {...mergeDataAttributes(props, dataAttributes({ slot: 'list-item-leading' }))}
108
+ />
109
+ );
110
+ },
98
111
  );
99
112
 
100
113
  ListItemLeadingSlot.displayName = 'ListItem.LeadingSlot';
101
114
 
115
+ const contentStyle = {
116
+ flex: 1,
117
+ flexDirection: 'column' as const,
118
+ minWidth: 0,
119
+ };
120
+
102
121
  export interface ListItemContentProps extends ViewProps {
122
+ asChild?: boolean;
103
123
  className?: string;
104
124
  }
105
125
 
106
126
  const ListItemContent = forwardRef<View, ListItemContentProps>(
107
- ({ className, style, ...props }, ref) => {
127
+ ({ asChild, className, style, ...props }, ref) => {
108
128
  const { crossAlign } = useListItemStyleContext();
129
+ const Comp = asChild ? Slot : View;
109
130
 
110
131
  return (
111
- <ListItemPrimitive.Content
112
- ref={ref as never}
132
+ <Comp
133
+ ref={ref}
113
134
  className={cn(listItemContentVariants({ crossAlign }), className)}
114
- style={style}
135
+ style={[contentStyle, style]}
115
136
  {...props}
137
+ {...mergeDataAttributes(props, dataAttributes({ slot: 'list-item-content' }))}
116
138
  />
117
139
  );
118
140
  },
@@ -121,18 +143,21 @@ const ListItemContent = forwardRef<View, ListItemContentProps>(
121
143
  ListItemContent.displayName = 'ListItem.Content';
122
144
 
123
145
  export interface ListItemTitleProps extends TextProps {
146
+ asChild?: boolean;
124
147
  className?: string;
125
148
  }
126
149
 
127
150
  const ListItemTitle = forwardRef<Text, ListItemTitleProps>(
128
- ({ className, numberOfLines = 1, style, ...props }, ref) => {
151
+ ({ asChild, className, numberOfLines = 1, style, ...props }, ref) => {
152
+ const Comp = asChild ? Slot : Text;
129
153
  return (
130
- <ListItemPrimitive.Title
131
- ref={ref as never}
154
+ <Comp
155
+ ref={ref}
132
156
  className={cn(listItemTitleVariants(), className)}
133
157
  numberOfLines={numberOfLines}
134
158
  style={style}
135
159
  {...props}
160
+ {...mergeDataAttributes(props, dataAttributes({ slot: 'list-item-title' }))}
136
161
  />
137
162
  );
138
163
  },
@@ -141,17 +166,20 @@ const ListItemTitle = forwardRef<Text, ListItemTitleProps>(
141
166
  ListItemTitle.displayName = 'ListItem.Title';
142
167
 
143
168
  export interface ListItemDescriptionProps extends TextProps {
169
+ asChild?: boolean;
144
170
  className?: string;
145
171
  }
146
172
 
147
173
  const ListItemDescription = forwardRef<Text, ListItemDescriptionProps>(
148
- ({ className, style, ...props }, ref) => {
174
+ ({ asChild, className, style, ...props }, ref) => {
175
+ const Comp = asChild ? Slot : Text;
149
176
  return (
150
- <ListItemPrimitive.Description
151
- ref={ref as never}
177
+ <Comp
178
+ ref={ref}
152
179
  className={cn(listItemDescriptionVariants(), className)}
153
180
  style={style}
154
181
  {...props}
182
+ {...mergeDataAttributes(props, dataAttributes({ slot: 'list-item-description' }))}
155
183
  />
156
184
  );
157
185
  },
@@ -160,18 +188,21 @@ const ListItemDescription = forwardRef<Text, ListItemDescriptionProps>(
160
188
  ListItemDescription.displayName = 'ListItem.Description';
161
189
 
162
190
  export interface ListItemMetaProps extends TextProps {
191
+ asChild?: boolean;
163
192
  className?: string;
164
193
  }
165
194
 
166
195
  const ListItemMeta = forwardRef<Text, ListItemMetaProps>(
167
- ({ className, numberOfLines = 1, style, ...props }, ref) => {
196
+ ({ asChild, className, numberOfLines = 1, style, ...props }, ref) => {
197
+ const Comp = asChild ? Slot : Text;
168
198
  return (
169
- <ListItemPrimitive.Meta
170
- ref={ref as never}
199
+ <Comp
200
+ ref={ref}
171
201
  className={cn(listItemMetaVariants(), className)}
172
202
  numberOfLines={numberOfLines}
173
203
  style={style}
174
204
  {...props}
205
+ {...mergeDataAttributes(props, dataAttributes({ slot: 'list-item-meta' }))}
175
206
  />
176
207
  );
177
208
  },
@@ -180,19 +211,22 @@ const ListItemMeta = forwardRef<Text, ListItemMetaProps>(
180
211
  ListItemMeta.displayName = 'ListItem.Meta';
181
212
 
182
213
  export interface ListItemTrailingSlotProps extends ViewProps {
214
+ asChild?: boolean;
183
215
  className?: string;
184
216
  }
185
217
 
186
218
  const ListItemTrailingSlot = forwardRef<View, ListItemTrailingSlotProps>(
187
- ({ className, style, ...props }, ref) => {
219
+ ({ asChild, className, style, ...props }, ref) => {
188
220
  const { crossAlign } = useListItemStyleContext();
221
+ const Comp = asChild ? Slot : View;
189
222
 
190
223
  return (
191
- <ListItemPrimitive.TrailingSlot
192
- ref={ref as never}
224
+ <Comp
225
+ ref={ref}
193
226
  className={cn(listItemTrailingSlotVariants({ crossAlign }), className)}
194
- style={style}
227
+ style={[{ flexShrink: 0 }, style]}
195
228
  {...props}
229
+ {...mergeDataAttributes(props, dataAttributes({ slot: 'list-item-trailing' }))}
196
230
  />
197
231
  );
198
232
  },
@@ -211,23 +245,74 @@ const wrapSectionHeaderLabel = (children: ReactNode): ReactNode => {
211
245
  // SECTION HEADER
212
246
  // =============================================================================
213
247
 
214
- export interface ListItemSectionHeaderComponentProps extends IListItemSectionHeaderProps {
248
+ // TODO: ListItem.SectionHeader doesn't follow composition patterns (composing text, trailing prop, etc).
249
+
250
+ const sectionHeaderRow = {
251
+ flexDirection: 'row' as const,
252
+ alignItems: 'center' as const,
253
+ justifyContent: 'space-between' as const,
254
+ gap: 8,
255
+ };
256
+
257
+ const sectionHeaderLabelCell = {
258
+ flex: 1,
259
+ minWidth: 0,
260
+ /** Keeps the label column from stretching to a taller trailing sibling (e.g. Chip). */
261
+ alignSelf: 'center' as const,
262
+ };
263
+
264
+ const sectionHeaderTrailingCell = {
265
+ flexShrink: 0,
266
+ /** Prevents the trailing slot from stretching vertically and “filling” the row. */
267
+ alignSelf: 'center' as const,
268
+ };
269
+
270
+ export interface ListItemSectionHeaderProps extends ViewProps {
271
+ asChild?: boolean;
215
272
  className?: string;
273
+ /** Primary section label (e.g. date heading). */
274
+ children: ReactNode;
275
+ /** Optional right-aligned adornment (e.g. section Chip). */
276
+ trailing?: ReactNode;
277
+ /**
278
+ * Whether to expose the top divider marker for styling.
279
+ * @default true
280
+ */
281
+ showDivider?: boolean;
216
282
  }
217
283
 
218
- const ListItemSectionHeader = forwardRef<View, ListItemSectionHeaderComponentProps>(
219
- ({ children, className, showDivider = true, style, trailing, ...props }, ref) => (
220
- <ListItemPrimitive.SectionHeader
221
- ref={ref as never}
222
- className={cn(listItemSectionHeaderVariants({ showDivider }), className)}
223
- showDivider={showDivider}
224
- style={style}
225
- trailing={trailing}
226
- {...props}
227
- >
228
- {wrapSectionHeaderLabel(children)}
229
- </ListItemPrimitive.SectionHeader>
230
- ),
284
+ const ListItemSectionHeader = forwardRef<View, ListItemSectionHeaderProps>(
285
+ (
286
+ {
287
+ asChild,
288
+ children,
289
+ className,
290
+ showDivider = true,
291
+ style,
292
+ trailing,
293
+ accessibilityRole = 'header',
294
+ ...props
295
+ },
296
+ ref,
297
+ ) => {
298
+ const Comp = asChild ? Slot : View;
299
+ return (
300
+ <Comp
301
+ ref={ref}
302
+ accessibilityRole={accessibilityRole}
303
+ className={cn(listItemSectionHeaderVariants({ showDivider }), className)}
304
+ style={[sectionHeaderRow, style]}
305
+ {...props}
306
+ {...mergeDataAttributes(
307
+ props,
308
+ dataAttributes({ slot: 'list-section-header', divider: showDivider }),
309
+ )}
310
+ >
311
+ <View style={sectionHeaderLabelCell}>{wrapSectionHeaderLabel(children)}</View>
312
+ {trailing ? <View style={sectionHeaderTrailingCell}>{trailing}</View> : null}
313
+ </Comp>
314
+ );
315
+ },
231
316
  );
232
317
 
233
318
  ListItemSectionHeader.displayName = 'ListItem.SectionHeader';
@@ -1,11 +1,20 @@
1
- import type { ComponentProps, ComponentRef, ForwardedRef } from 'react';
2
- import { forwardRef } from 'react';
3
- import type { View } from 'react-native';
4
- import { createOtpInput, type IOtpInputRootProps } from '@cdx-ui/primitives';
5
- import { cn, useStyleContext, withStyleContext } from '@cdx-ui/utils';
6
- import { HStack } from '../Stack/HStack';
1
+ import type { ForwardedRef } from 'react';
2
+ import { forwardRef, useMemo } from 'react';
3
+ import { View, type TextInput, type ViewProps } from 'react-native';
4
+ import {
5
+ OtpCellIndexProvider,
6
+ OtpInputField,
7
+ OtpInputProvider,
8
+ dataAttributes,
9
+ mergeDataAttributes,
10
+ useInputContext,
11
+ useOtpInput,
12
+ type IOtpInputRootProps,
13
+ type OtpInputFieldProps,
14
+ } from '@cdx-ui/primitives';
15
+ import { ParentContext, cn, useParentContext, useStyleContext } from '@cdx-ui/utils';
7
16
  import { Input, type InputProps } from '../Input';
8
- import type { InputVariantProps } from '../Input/styles';
17
+ import { type InputVariantProps, inputFieldVariants } from '../Input/styles';
9
18
  import {
10
19
  otpCellVariants,
11
20
  otpFieldVariants,
@@ -15,45 +24,56 @@ import {
15
24
 
16
25
  const SCOPE = 'OTP_INPUT';
17
26
 
18
- const OtpRoot = withStyleContext(HStack, SCOPE);
19
-
20
27
  const useOtpInputStyleContext = () => useStyleContext(SCOPE) as InputVariantProps;
21
28
 
22
- const OtpStyledCell = forwardRef<View, InputProps>(
23
- ({ className, children, ...props }, ref: ForwardedRef<View>) => {
24
- const { size, variant } = useOtpInputStyleContext();
29
+ const OtpStyledCell = forwardRef<
30
+ View,
31
+ ViewProps & { className?: string; children?: React.ReactNode }
32
+ >(({ className, children, ...props }, ref: ForwardedRef<View>) => {
33
+ const { size, variant } = useOtpInputStyleContext();
34
+ return (
35
+ <Input
36
+ ref={ref}
37
+ variant={variant}
38
+ size={size}
39
+ className={cn(otpCellVariants({ size }), className)}
40
+ {...props}
41
+ >
42
+ {children}
43
+ </Input>
44
+ );
45
+ });
46
+
47
+ OtpStyledCell.displayName = 'OtpInput.Cell';
48
+
49
+ /**
50
+ * Bridges OtpInputField focus/blur events to the parent Input's context so
51
+ * InputRoot emits `data-focus=true` and the `border-stroke-action` CSS activates.
52
+ * The primitive OtpInputField doesn't know about InputContext — that coupling
53
+ * belongs here in the styled layer.
54
+ */
55
+ const OtpStyledField = forwardRef<TextInput, OtpInputFieldProps & { className?: string }>(
56
+ (props, ref) => {
57
+ const { setIsFocused } = useInputContext();
25
58
  return (
26
- <Input
59
+ <OtpInputField
27
60
  ref={ref}
28
- variant={variant}
29
- size={size}
30
- className={cn(otpCellVariants({ size }), className)}
31
61
  {...props}
32
- >
33
- {children}
34
- </Input>
62
+ onFocus={(e) => {
63
+ setIsFocused?.(true);
64
+ props.onFocus?.(e);
65
+ }}
66
+ onBlur={(e) => {
67
+ setIsFocused?.(false);
68
+ props.onBlur?.(e);
69
+ }}
70
+ />
35
71
  );
36
72
  },
37
73
  );
38
74
 
39
- OtpStyledCell.displayName = 'OtpInput.Cell';
40
-
41
- const OtpStyledField = forwardRef<
42
- ComponentRef<typeof Input.Field>,
43
- ComponentProps<typeof Input.Field>
44
- >(({ className, ...props }, ref) => {
45
- const { size } = useOtpInputStyleContext();
46
- return <Input.Field ref={ref} className={cn(otpFieldVariants({ size }), className)} {...props} />;
47
- });
48
-
49
75
  OtpStyledField.displayName = 'OtpInput.Field';
50
76
 
51
- const OtpPrimitive = createOtpInput({
52
- Root: OtpRoot,
53
- Cell: OtpStyledCell,
54
- Field: OtpStyledField,
55
- });
56
-
57
77
  export interface OtpInputProps extends Omit<IOtpInputRootProps, 'size'>, OtpInputVariantProps {
58
78
  variant?: NonNullable<InputProps['variant']>;
59
79
  size?: NonNullable<InputProps['size']>;
@@ -61,17 +81,80 @@ export interface OtpInputProps extends Omit<IOtpInputRootProps, 'size'>, OtpInpu
61
81
  }
62
82
 
63
83
  export const OtpInput = forwardRef<View, OtpInputProps>(
64
- ({ variant = 'outline', size = 'default', fullWidth = true, className, style, ...rest }, ref) => {
84
+ (
85
+ {
86
+ variant = 'outline',
87
+ size = 'default',
88
+ fullWidth = true,
89
+ className,
90
+ style,
91
+ cellCount,
92
+ value,
93
+ onChangeText,
94
+ onComplete,
95
+ isDisabled,
96
+ isInvalid,
97
+ isReadOnly,
98
+ smsOtpAutofill,
99
+ filterInput,
100
+ allowedCharacters,
101
+ characterPattern,
102
+ getCellProps,
103
+ cellTestIdPrefix,
104
+ accessibilityLabel,
105
+ ...rest
106
+ },
107
+ ref,
108
+ ) => {
109
+ const otpContext = useOtpInput({
110
+ cellCount,
111
+ value,
112
+ onChangeText,
113
+ onComplete,
114
+ isDisabled,
115
+ isInvalid,
116
+ isReadOnly,
117
+ smsOtpAutofill,
118
+ filterInput,
119
+ allowedCharacters,
120
+ characterPattern,
121
+ getCellProps,
122
+ cellTestIdPrefix,
123
+ accessibilityLabel,
124
+ });
125
+
65
126
  const rootClassName = cn(otpRootVariants({ size, fullWidth }), className);
66
127
 
128
+ const parent = useParentContext();
129
+ const ctx = useMemo(() => ({ ...parent, [SCOPE]: { variant, size } }), [parent, variant, size]);
130
+
131
+ const fieldClassName = cn(inputFieldVariants({ size }), otpFieldVariants({ size }));
132
+
133
+ const cells: React.ReactElement[] = [];
134
+ for (let i = 0; i < cellCount; i++) {
135
+ cells.push(
136
+ <OtpCellIndexProvider key={i} value={{ cellIndex: i }}>
137
+ <OtpStyledCell>
138
+ <OtpStyledField className={fieldClassName} />
139
+ </OtpStyledCell>
140
+ </OtpCellIndexProvider>,
141
+ );
142
+ }
143
+
67
144
  return (
68
- <OtpPrimitive
69
- ref={ref}
70
- className={rootClassName}
71
- style={style}
72
- context={{ variant, size }}
73
- {...rest}
74
- />
145
+ <ParentContext.Provider value={ctx}>
146
+ <OtpInputProvider value={otpContext}>
147
+ <View
148
+ ref={ref}
149
+ className={rootClassName}
150
+ style={style}
151
+ {...rest}
152
+ {...mergeDataAttributes(rest, dataAttributes({ slot: 'otp-input' }))}
153
+ >
154
+ {cells}
155
+ </View>
156
+ </OtpInputProvider>
157
+ </ParentContext.Provider>
75
158
  );
76
159
  },
77
160
  );
@@ -1,6 +1,6 @@
1
1
  import { forwardRef } from 'react';
2
2
  import { View, type ViewProps } from 'react-native';
3
- import { createProgress, type IProgressProps } from '@cdx-ui/primitives';
3
+ import { ProgressBarRoot, ProgressBarIndicator, type IProgressProps } from '@cdx-ui/primitives';
4
4
  import { cn } from '@cdx-ui/utils';
5
5
  import {
6
6
  progressBarIndicatorVariants,
@@ -8,11 +8,6 @@ import {
8
8
  type ProgressBarTrackVariantProps,
9
9
  } from './styles';
10
10
 
11
- const ProgressPrimitive = createProgress({
12
- Root: View,
13
- Indicator: View,
14
- });
15
-
16
11
  export interface ProgressBarProps extends IProgressProps, ProgressBarTrackVariantProps {
17
12
  readonly className?: string;
18
13
  }
@@ -21,19 +16,19 @@ export interface ProgressBarIndicatorProps extends ViewProps {
21
16
  readonly className?: string;
22
17
  }
23
18
 
24
- const ProgressBarRoot = forwardRef<View, ProgressBarProps>(
19
+ const ProgressBarRootComponent = forwardRef<View, ProgressBarProps>(
25
20
  ({ className, style, ...props }, ref) => {
26
21
  const trackClass = cn(progressBarTrackVariants(), className);
27
22
 
28
- return <ProgressPrimitive ref={ref} className={trackClass} style={style} {...props} />;
23
+ return <ProgressBarRoot ref={ref} className={trackClass} style={style} {...props} />;
29
24
  },
30
25
  );
31
26
 
32
- ProgressBarRoot.displayName = 'ProgressBar';
27
+ ProgressBarRootComponent.displayName = 'ProgressBar';
33
28
 
34
- const ProgressBarIndicator = forwardRef<View, ProgressBarIndicatorProps>(
29
+ const ProgressBarIndicatorComponent = forwardRef<View, ProgressBarIndicatorProps>(
35
30
  ({ className, style, ...props }, ref) => (
36
- <ProgressPrimitive.Indicator
31
+ <ProgressBarIndicator
37
32
  ref={ref}
38
33
  className={cn(progressBarIndicatorVariants(), className)}
39
34
  style={style}
@@ -42,12 +37,12 @@ const ProgressBarIndicator = forwardRef<View, ProgressBarIndicatorProps>(
42
37
  ),
43
38
  );
44
39
 
45
- ProgressBarIndicator.displayName = 'ProgressBar.Indicator';
40
+ ProgressBarIndicatorComponent.displayName = 'ProgressBar.Indicator';
46
41
 
47
- type ProgressBarCompoundComponent = typeof ProgressBarRoot & {
48
- Indicator: typeof ProgressBarIndicator;
42
+ type ProgressBarCompoundComponent = typeof ProgressBarRootComponent & {
43
+ Indicator: typeof ProgressBarIndicatorComponent;
49
44
  };
50
45
 
51
- export const ProgressBar = Object.assign(ProgressBarRoot, {
52
- Indicator: ProgressBarIndicator,
46
+ export const ProgressBar = Object.assign(ProgressBarRootComponent, {
47
+ Indicator: ProgressBarIndicatorComponent,
53
48
  }) as ProgressBarCompoundComponent;