@cdx-ui/components 0.0.1-beta.65 → 0.0.1-beta.67

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 (242) 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/Switch/BaseSwitch.js +23 -13
  43. package/lib/commonjs/components/Switch/BaseSwitch.js.map +1 -1
  44. package/lib/commonjs/components/Switch/BaseSwitch.web.js +25 -21
  45. package/lib/commonjs/components/Switch/BaseSwitch.web.js.map +1 -1
  46. package/lib/commonjs/components/Switch/index.js +34 -3
  47. package/lib/commonjs/components/Switch/index.js.map +1 -1
  48. package/lib/commonjs/components/Tile/index.js +150 -77
  49. package/lib/commonjs/components/Tile/index.js.map +1 -1
  50. package/lib/commonjs/figma/Chip.figma.js +2 -2
  51. package/lib/commonjs/figma/Chip.figma.js.map +1 -1
  52. package/lib/commonjs/utils/positionToDataIcon.js +41 -0
  53. package/lib/commonjs/utils/positionToDataIcon.js.map +1 -0
  54. package/lib/module/components/AlertDialog/index.js +13 -11
  55. package/lib/module/components/AlertDialog/index.js.map +1 -1
  56. package/lib/module/components/Avatar/index.js +128 -28
  57. package/lib/module/components/Avatar/index.js.map +1 -1
  58. package/lib/module/components/Button/index.js +130 -32
  59. package/lib/module/components/Button/index.js.map +1 -1
  60. package/lib/module/components/Button/styles.js +8 -2
  61. package/lib/module/components/Button/styles.js.map +1 -1
  62. package/lib/module/components/CLAUDE.md +115 -11
  63. package/lib/module/components/Checkbox/index.js +72 -25
  64. package/lib/module/components/Checkbox/index.js.map +1 -1
  65. package/lib/module/components/Checkbox/styles.js +1 -1
  66. package/lib/module/components/Checkbox/styles.js.map +1 -1
  67. package/lib/module/components/Chip/index.js +47 -39
  68. package/lib/module/components/Chip/index.js.map +1 -1
  69. package/lib/module/components/Chip/styles.js +6 -35
  70. package/lib/module/components/Chip/styles.js.map +1 -1
  71. package/lib/module/components/Dialog/index.js +96 -76
  72. package/lib/module/components/Dialog/index.js.map +1 -1
  73. package/lib/module/components/Field/index.js +74 -31
  74. package/lib/module/components/Field/index.js.map +1 -1
  75. package/lib/module/components/Form/index.js +7 -14
  76. package/lib/module/components/Form/index.js.map +1 -1
  77. package/lib/module/components/IconButton/index.js +6 -34
  78. package/lib/module/components/IconButton/index.js.map +1 -1
  79. package/lib/module/components/Input/index.js +53 -23
  80. package/lib/module/components/Input/index.js.map +1 -1
  81. package/lib/module/components/Link/index.js +16 -8
  82. package/lib/module/components/Link/index.js.map +1 -1
  83. package/lib/module/components/ListItem/index.js +134 -59
  84. package/lib/module/components/ListItem/index.js.map +1 -1
  85. package/lib/module/components/OtpInput/index.js +94 -28
  86. package/lib/module/components/OtpInput/index.js.map +1 -1
  87. package/lib/module/components/ProgressBar/index.js +9 -14
  88. package/lib/module/components/ProgressBar/index.js.map +1 -1
  89. package/lib/module/components/Radio/index.js +54 -57
  90. package/lib/module/components/Radio/index.js.map +1 -1
  91. package/lib/module/components/Select/index.js +118 -52
  92. package/lib/module/components/Select/index.js.map +1 -1
  93. package/lib/module/components/Select/styles.js +2 -2
  94. package/lib/module/components/Select/styles.js.map +1 -1
  95. package/lib/module/components/Switch/BaseSwitch.js +24 -14
  96. package/lib/module/components/Switch/BaseSwitch.js.map +1 -1
  97. package/lib/module/components/Switch/BaseSwitch.web.js +26 -22
  98. package/lib/module/components/Switch/BaseSwitch.web.js.map +1 -1
  99. package/lib/module/components/Switch/index.js +35 -4
  100. package/lib/module/components/Switch/index.js.map +1 -1
  101. package/lib/module/components/Tile/index.js +155 -83
  102. package/lib/module/components/Tile/index.js.map +1 -1
  103. package/lib/module/figma/Chip.figma.js +2 -2
  104. package/lib/module/figma/Chip.figma.js.map +1 -1
  105. package/lib/module/utils/positionToDataIcon.js +38 -0
  106. package/lib/module/utils/positionToDataIcon.js.map +1 -0
  107. package/lib/typescript/components/AlertDialog/index.d.ts.map +1 -1
  108. package/lib/typescript/components/Avatar/index.d.ts +6 -2
  109. package/lib/typescript/components/Avatar/index.d.ts.map +1 -1
  110. package/lib/typescript/components/Button/index.d.ts +31 -8
  111. package/lib/typescript/components/Button/index.d.ts.map +1 -1
  112. package/lib/typescript/components/Button/styles.d.ts +2 -1
  113. package/lib/typescript/components/Button/styles.d.ts.map +1 -1
  114. package/lib/typescript/components/Checkbox/index.d.ts +3 -1
  115. package/lib/typescript/components/Checkbox/index.d.ts.map +1 -1
  116. package/lib/typescript/components/Chip/index.d.ts +19 -9
  117. package/lib/typescript/components/Chip/index.d.ts.map +1 -1
  118. package/lib/typescript/components/Chip/styles.d.ts +0 -1
  119. package/lib/typescript/components/Chip/styles.d.ts.map +1 -1
  120. package/lib/typescript/components/Dialog/index.d.ts +12 -6
  121. package/lib/typescript/components/Dialog/index.d.ts.map +1 -1
  122. package/lib/typescript/components/Dialog/styles.d.ts +1 -1
  123. package/lib/typescript/components/Field/index.d.ts +14 -7
  124. package/lib/typescript/components/Field/index.d.ts.map +1 -1
  125. package/lib/typescript/components/Form/index.d.ts +4 -4
  126. package/lib/typescript/components/Form/index.d.ts.map +1 -1
  127. package/lib/typescript/components/IconButton/index.d.ts.map +1 -1
  128. package/lib/typescript/components/Input/index.d.ts +11 -3
  129. package/lib/typescript/components/Input/index.d.ts.map +1 -1
  130. package/lib/typescript/components/Link/index.d.ts +2 -0
  131. package/lib/typescript/components/Link/index.d.ts.map +1 -1
  132. package/lib/typescript/components/ListItem/index.d.ts +28 -6
  133. package/lib/typescript/components/ListItem/index.d.ts.map +1 -1
  134. package/lib/typescript/components/OtpInput/index.d.ts +1 -1
  135. package/lib/typescript/components/OtpInput/index.d.ts.map +1 -1
  136. package/lib/typescript/components/ProgressBar/index.d.ts +4 -4
  137. package/lib/typescript/components/ProgressBar/index.d.ts.map +1 -1
  138. package/lib/typescript/components/Radio/index.d.ts +4 -0
  139. package/lib/typescript/components/Radio/index.d.ts.map +1 -1
  140. package/lib/typescript/components/Select/index.d.ts +35 -2
  141. package/lib/typescript/components/Select/index.d.ts.map +1 -1
  142. package/lib/typescript/components/Select/styles.d.ts.map +1 -1
  143. package/lib/typescript/components/Switch/BaseSwitch.d.ts +12 -5
  144. package/lib/typescript/components/Switch/BaseSwitch.d.ts.map +1 -1
  145. package/lib/typescript/components/Switch/BaseSwitch.web.d.ts +11 -5
  146. package/lib/typescript/components/Switch/BaseSwitch.web.d.ts.map +1 -1
  147. package/lib/typescript/components/Switch/index.d.ts +5 -1
  148. package/lib/typescript/components/Switch/index.d.ts.map +1 -1
  149. package/lib/typescript/components/Tile/index.d.ts +8 -2
  150. package/lib/typescript/components/Tile/index.d.ts.map +1 -1
  151. package/lib/typescript/utils/positionToDataIcon.d.ts +29 -0
  152. package/lib/typescript/utils/positionToDataIcon.d.ts.map +1 -0
  153. package/package.json +5 -5
  154. package/src/components/AlertDialog/index.tsx +13 -14
  155. package/src/components/Avatar/index.tsx +134 -44
  156. package/src/components/Button/index.tsx +216 -44
  157. package/src/components/Button/styles.ts +50 -38
  158. package/src/components/CLAUDE.md +115 -11
  159. package/src/components/Checkbox/index.tsx +93 -32
  160. package/src/components/Checkbox/styles.ts +1 -1
  161. package/src/components/Chip/index.tsx +88 -61
  162. package/src/components/Chip/styles.ts +6 -18
  163. package/src/components/Dialog/index.tsx +139 -99
  164. package/src/components/Field/index.tsx +113 -49
  165. package/src/components/Form/index.tsx +18 -14
  166. package/src/components/IconButton/index.tsx +7 -31
  167. package/src/components/Input/index.tsx +75 -32
  168. package/src/components/Link/index.tsx +38 -12
  169. package/src/components/ListItem/index.tsx +158 -73
  170. package/src/components/OtpInput/index.tsx +126 -43
  171. package/src/components/ProgressBar/index.tsx +11 -16
  172. package/src/components/Radio/index.tsx +76 -54
  173. package/src/components/Select/index.tsx +174 -59
  174. package/src/components/Select/styles.ts +1 -2
  175. package/src/components/Switch/BaseSwitch.tsx +38 -16
  176. package/src/components/Switch/BaseSwitch.web.tsx +28 -35
  177. package/src/components/Switch/index.tsx +51 -4
  178. package/src/components/Tile/index.tsx +145 -94
  179. package/src/utils/positionToDataIcon.ts +34 -0
  180. package/lib/commonjs/components/Field/FieldLabel.js +0 -33
  181. package/lib/commonjs/components/Field/FieldLabel.js.map +0 -1
  182. package/lib/commonjs/components/Field/FieldLabel.web.js +0 -22
  183. package/lib/commonjs/components/Field/FieldLabel.web.js.map +0 -1
  184. package/lib/commonjs/components/Form/FormRoot.js +0 -25
  185. package/lib/commonjs/components/Form/FormRoot.js.map +0 -1
  186. package/lib/commonjs/components/Form/FormRoot.web.js +0 -17
  187. package/lib/commonjs/components/Form/FormRoot.web.js.map +0 -1
  188. package/lib/commonjs/components/Input/BaseInput.android.js +0 -20
  189. package/lib/commonjs/components/Input/BaseInput.android.js.map +0 -1
  190. package/lib/commonjs/components/Input/BaseInput.js +0 -13
  191. package/lib/commonjs/components/Input/BaseInput.js.map +0 -1
  192. package/lib/commonjs/components/Input/BaseInput.web.js +0 -50
  193. package/lib/commonjs/components/Input/BaseInput.web.js.map +0 -1
  194. package/lib/commonjs/components/Select/SelectTriggerHost.js +0 -10
  195. package/lib/commonjs/components/Select/SelectTriggerHost.js.map +0 -1
  196. package/lib/commonjs/components/Select/SelectTriggerHost.web.js +0 -102
  197. package/lib/commonjs/components/Select/SelectTriggerHost.web.js.map +0 -1
  198. package/lib/module/components/Field/FieldLabel.js +0 -29
  199. package/lib/module/components/Field/FieldLabel.js.map +0 -1
  200. package/lib/module/components/Field/FieldLabel.web.js +0 -17
  201. package/lib/module/components/Field/FieldLabel.web.js.map +0 -1
  202. package/lib/module/components/Form/FormRoot.js +0 -21
  203. package/lib/module/components/Form/FormRoot.js.map +0 -1
  204. package/lib/module/components/Form/FormRoot.web.js +0 -12
  205. package/lib/module/components/Form/FormRoot.web.js.map +0 -1
  206. package/lib/module/components/Input/BaseInput.android.js +0 -16
  207. package/lib/module/components/Input/BaseInput.android.js.map +0 -1
  208. package/lib/module/components/Input/BaseInput.js +0 -4
  209. package/lib/module/components/Input/BaseInput.js.map +0 -1
  210. package/lib/module/components/Input/BaseInput.web.js +0 -45
  211. package/lib/module/components/Input/BaseInput.web.js.map +0 -1
  212. package/lib/module/components/Select/SelectTriggerHost.js +0 -7
  213. package/lib/module/components/Select/SelectTriggerHost.js.map +0 -1
  214. package/lib/module/components/Select/SelectTriggerHost.web.js +0 -97
  215. package/lib/module/components/Select/SelectTriggerHost.web.js.map +0 -1
  216. package/lib/typescript/components/Field/FieldLabel.d.ts +0 -18
  217. package/lib/typescript/components/Field/FieldLabel.d.ts.map +0 -1
  218. package/lib/typescript/components/Field/FieldLabel.web.d.ts +0 -16
  219. package/lib/typescript/components/Field/FieldLabel.web.d.ts.map +0 -1
  220. package/lib/typescript/components/Form/FormRoot.d.ts +0 -14
  221. package/lib/typescript/components/Form/FormRoot.d.ts.map +0 -1
  222. package/lib/typescript/components/Form/FormRoot.web.d.ts +0 -10
  223. package/lib/typescript/components/Form/FormRoot.web.d.ts.map +0 -1
  224. package/lib/typescript/components/Input/BaseInput.android.d.ts +0 -3
  225. package/lib/typescript/components/Input/BaseInput.android.d.ts.map +0 -1
  226. package/lib/typescript/components/Input/BaseInput.d.ts +0 -2
  227. package/lib/typescript/components/Input/BaseInput.d.ts.map +0 -1
  228. package/lib/typescript/components/Input/BaseInput.web.d.ts +0 -3
  229. package/lib/typescript/components/Input/BaseInput.web.d.ts.map +0 -1
  230. package/lib/typescript/components/Select/SelectTriggerHost.d.ts +0 -3
  231. package/lib/typescript/components/Select/SelectTriggerHost.d.ts.map +0 -1
  232. package/lib/typescript/components/Select/SelectTriggerHost.web.d.ts +0 -16
  233. package/lib/typescript/components/Select/SelectTriggerHost.web.d.ts.map +0 -1
  234. package/src/components/Field/FieldLabel.tsx +0 -33
  235. package/src/components/Field/FieldLabel.web.tsx +0 -25
  236. package/src/components/Form/FormRoot.tsx +0 -20
  237. package/src/components/Form/FormRoot.web.tsx +0 -12
  238. package/src/components/Input/BaseInput.android.tsx +0 -13
  239. package/src/components/Input/BaseInput.tsx +0 -1
  240. package/src/components/Input/BaseInput.web.tsx +0 -41
  241. package/src/components/Select/SelectTriggerHost.tsx +0 -4
  242. package/src/components/Select/SelectTriggerHost.web.tsx +0 -143
@@ -1,16 +1,16 @@
1
1
  import { forwardRef, useMemo, type ReactNode } from 'react';
2
- import { Pressable, Text as RNText, View, type TextProps } from 'react-native';
3
- import { createChip, type IChipProps } from '@cdx-ui/primitives';
2
+ import { Text, View, type TextProps } from 'react-native';
4
3
  import {
5
- cn,
6
- ParentContext,
7
- useParentContext,
8
- useStyleContext,
9
- withStyleContext,
10
- type WithStyleContextProps,
11
- } from '@cdx-ui/utils';
4
+ ChipRoot as ChipRootPrimitive,
5
+ Slot,
6
+ dataAttributes,
7
+ mergeDataAttributes,
8
+ type IChipProps,
9
+ } from '@cdx-ui/primitives';
10
+ import { cn, ParentContext, useParentContext, useStyleContext } from '@cdx-ui/utils';
12
11
  import { Avatar, type AvatarProps } from '../Avatar';
13
12
  import { Icon, type IconProps } from '../Icon';
13
+ import { positionToDataIcon, type IconSlotPosition } from '../../utils/positionToDataIcon';
14
14
  import {
15
15
  chipAvatarVariants,
16
16
  chipIconVariants,
@@ -21,65 +21,43 @@ import {
21
21
 
22
22
  const SCOPE = 'CHIP';
23
23
 
24
- const RootView = withStyleContext(View, SCOPE);
25
- const RootPressable = withStyleContext(Pressable, SCOPE);
26
-
27
- const ChipPrimitive = createChip({
28
- View: RootView,
29
- Pressable: RootPressable,
30
- });
31
-
32
24
  const useChipStyleContext = () => useStyleContext(SCOPE) as ChipVariantProps;
33
25
 
34
26
  // =============================================================================
35
27
  // ROOT
36
28
  // =============================================================================
37
29
 
38
- export interface ChipProps extends IChipProps, ChipVariantProps, WithStyleContextProps {
30
+ export interface ChipProps extends IChipProps, ChipVariantProps {
39
31
  className?: string;
40
32
  children?: ReactNode;
41
33
  }
42
34
 
43
35
  const ChipRoot = forwardRef<View, ChipProps>(
44
36
  (
45
- {
46
- children,
47
- variant = 'tint',
48
- size = 'default',
49
- color = 'default',
50
- className,
51
- style,
52
- asChild,
53
- ...props
54
- },
37
+ { children, variant = 'tint', size = 'default', color = 'default', className, style, ...props },
55
38
  ref,
56
39
  ) => {
57
- const parentContextValues = useParentContext();
58
- const styleContextValues = useMemo(
59
- () => ({ ...parentContextValues, [SCOPE]: { variant, size, color } }),
60
- [parentContextValues, variant, size, color],
40
+ const parent = useParentContext();
41
+ const ctx = useMemo(
42
+ () => ({ ...parent, [SCOPE]: { variant, size, color } }),
43
+ [parent, variant, size, color],
61
44
  );
62
45
 
63
46
  const computedClassName = cn(chipRootVariants({ variant, size, color }), className);
64
47
 
65
- const root = (
66
- <ChipPrimitive
67
- ref={ref as never}
68
- asChild={asChild}
69
- className={computedClassName}
70
- context={{ variant, size, color }}
71
- style={style}
72
- {...props}
73
- >
74
- {children}
75
- </ChipPrimitive>
48
+ return (
49
+ <ParentContext.Provider value={ctx}>
50
+ <ChipRootPrimitive
51
+ ref={ref}
52
+ className={computedClassName}
53
+ style={style}
54
+ {...props}
55
+ {...mergeDataAttributes(props, dataAttributes({ slot: 'chip' }))}
56
+ >
57
+ {children}
58
+ </ChipRootPrimitive>
59
+ </ParentContext.Provider>
76
60
  );
77
-
78
- if (asChild) {
79
- return <ParentContext.Provider value={styleContextValues}>{root}</ParentContext.Provider>;
80
- }
81
-
82
- return root;
83
61
  },
84
62
  );
85
63
 
@@ -90,19 +68,27 @@ ChipRoot.displayName = 'Chip';
90
68
  // =============================================================================
91
69
 
92
70
  export interface ChipLabelProps extends TextProps {
71
+ asChild?: boolean;
93
72
  className?: string;
94
73
  children?: ReactNode;
95
74
  }
96
75
 
97
- const ChipLabel = forwardRef<RNText, ChipLabelProps>(
98
- ({ className, children, style, ...props }, ref) => {
76
+ const ChipLabel = forwardRef<Text, ChipLabelProps>(
77
+ ({ asChild, className, children, style, ...props }, ref) => {
99
78
  const { size, variant, color } = useChipStyleContext();
100
79
  const computedClassName = cn(chipLabelVariants({ size, variant, color }), className);
80
+ const Comp = asChild ? Slot : Text;
101
81
 
102
82
  return (
103
- <RNText ref={ref} className={computedClassName} style={style} {...props}>
83
+ <Comp
84
+ ref={ref}
85
+ className={computedClassName}
86
+ style={style}
87
+ {...props}
88
+ {...mergeDataAttributes(props, dataAttributes({ slot: 'chip-label' }))}
89
+ >
104
90
  {children}
105
- </RNText>
91
+ </Comp>
106
92
  );
107
93
  },
108
94
  );
@@ -113,16 +99,57 @@ ChipLabel.displayName = 'Chip.Label';
113
99
  // ICON
114
100
  // =============================================================================
115
101
 
116
- export interface ChipIconProps extends Omit<IconProps, 'children'> {
117
- /** Leading (default) or trailing slot — applies the correct negative margin offset. */
118
- slot?: 'leading' | 'trailing';
119
- className?: string;
102
+ export interface ChipIconProps extends Omit<IconProps, 'children' | 'as'> {
103
+ asChild?: boolean;
104
+ /**
105
+ * Forge icon component to render. Required unless `asChild` is set, in which
106
+ * case the consumer's substituted element is rendered instead.
107
+ */
108
+ as?: IconProps['as'];
109
+ /**
110
+ * Position hint that emits `data-icon="inline-start"` or `data-icon="inline-end"`.
111
+ * CVA uses this attribute to apply leading/trailing margin offsets logically
112
+ * (RTL-aware). Omit when the icon is freely positioned within a custom layout.
113
+ */
114
+ position?: IconSlotPosition;
120
115
  }
121
116
 
122
- const ChipIcon = ({ className, style, as, slot, ...props }: ChipIconProps) => {
117
+ const ChipIcon = ({ asChild, className, style, as, position, ...props }: ChipIconProps) => {
123
118
  const { size, color } = useChipStyleContext();
124
- const computedClassName = cn(chipIconVariants({ size, color, slot }), className);
125
- return <Icon as={as} className={computedClassName} style={style} {...props} />;
119
+ const computedClassName = cn(chipIconVariants({ size, color }), className);
120
+
121
+ if (asChild) {
122
+ return (
123
+ <Slot
124
+ className={computedClassName}
125
+ style={style}
126
+ {...props}
127
+ {...mergeDataAttributes(
128
+ props,
129
+ dataAttributes({ slot: 'chip-icon' }),
130
+ positionToDataIcon(position),
131
+ )}
132
+ />
133
+ );
134
+ }
135
+
136
+ if (!as) {
137
+ return null;
138
+ }
139
+
140
+ return (
141
+ <Icon
142
+ as={as}
143
+ className={computedClassName}
144
+ style={style}
145
+ {...props}
146
+ {...mergeDataAttributes(
147
+ props,
148
+ dataAttributes({ slot: 'chip-icon' }),
149
+ positionToDataIcon(position),
150
+ )}
151
+ />
152
+ );
126
153
  };
127
154
 
128
155
  ChipIcon.displayName = 'Chip.Icon';
@@ -135,7 +162,7 @@ export interface ChipAvatarProps extends Omit<AvatarProps, 'size'> {}
135
162
 
136
163
  const ChipAvatar = ({ className, style, children, ...props }: ChipAvatarProps) => {
137
164
  const { size } = useChipStyleContext();
138
- // chipAvatarVariants sets w/h and the leading slot negative margin.
165
+ // chipAvatarVariants sets w/h and the leading-edge negative margin.
139
166
  // Avatar renders with size="sm" (its smallest named size) but chipAvatarVariants
140
167
  // overrides the w/h via tailwind-merge so the chip size wins.
141
168
  const computedClassName = cn(chipAvatarVariants({ size }), className);
@@ -219,9 +219,9 @@ export const chipLabelVariants = cva(['font-medium'], {
219
219
  export const chipIconVariants = cva(['shrink-0'], {
220
220
  variants: {
221
221
  size: {
222
- default: 'size-5',
223
- small: 'size-4',
224
- xsmall: 'size-2.5',
222
+ default: 'size-5 data-[icon=inline-start]:-ms-1.5 data-[icon=inline-end]:-me-1.5',
223
+ small: 'size-4 data-[icon=inline-start]:-ms-0.5 data-[icon=inline-end]:-me-0.5',
224
+ xsmall: 'size-2.5 data-[icon=inline-start]:-ms-px data-[icon=inline-end]:-me-px',
225
225
  },
226
226
  color: {
227
227
  default: 'text-content-primary',
@@ -231,19 +231,7 @@ export const chipIconVariants = cva(['shrink-0'], {
231
231
  success: 'text-content-success',
232
232
  info: 'text-content-info',
233
233
  },
234
- slot: {
235
- leading: '',
236
- trailing: '',
237
- },
238
234
  },
239
- compoundVariants: [
240
- { slot: 'leading', size: 'default', className: '-ml-1.5' },
241
- { slot: 'leading', size: 'small', className: '-ml-0.5' },
242
- { slot: 'leading', size: 'xsmall', className: '-ml-px' },
243
- { slot: 'trailing', size: 'default', className: '-mr-1.5' },
244
- { slot: 'trailing', size: 'small', className: '-mr-0.5' },
245
- { slot: 'trailing', size: 'xsmall', className: '-mr-px' },
246
- ],
247
235
  defaultVariants: {
248
236
  size: 'default',
249
237
  color: 'default',
@@ -253,9 +241,9 @@ export const chipIconVariants = cva(['shrink-0'], {
253
241
  export const chipAvatarVariants = cva(['shrink-0 rounded-full overflow-hidden'], {
254
242
  variants: {
255
243
  size: {
256
- default: 'size-5 -ml-1.5',
257
- small: 'size-4 -ml-0.5',
258
- xsmall: 'size-2.5 -ml-px',
244
+ default: 'size-5 -ms-1.5',
245
+ small: 'size-4 -ms-0.5',
246
+ xsmall: 'size-2.5 -ms-px',
259
247
  },
260
248
  },
261
249
  defaultVariants: {
@@ -1,26 +1,21 @@
1
- import { forwardRef, type ReactNode } from 'react';
2
- import {
3
- Pressable,
4
- Text,
5
- View,
6
- type PressableProps,
7
- type TextProps,
8
- type ViewProps,
9
- } from 'react-native';
1
+ import { forwardRef, useMemo, type ReactNode } from 'react';
2
+ import { Text, View, type TextProps, type ViewProps } from 'react-native';
10
3
  import { CheckCircle, Close as CloseIcon, EmergencyHome, Warning } from '@cdx-ui/icons';
11
4
  import {
12
- createDialog,
5
+ DialogClose as DialogClosePrimitive,
6
+ DialogPopup as DialogPopupPrimitive,
7
+ DialogRoot as DialogRootPrimitive,
8
+ DialogTrigger as DialogTriggerPrimitive,
9
+ Slot,
10
+ dataAttributes,
11
+ mergeDataAttributes,
12
+ useDialog,
13
13
  type IDialogCloseProps,
14
- type IDialogContentProps,
15
- type IDialogDescriptionProps,
16
- type IDialogFooterProps,
17
- type IDialogHeaderProps,
18
14
  type IDialogPopupProps,
19
15
  type IDialogRootProps,
20
- type IDialogTitleProps,
21
16
  type IDialogTriggerProps,
22
17
  } from '@cdx-ui/primitives';
23
- import { cn, useStyleContext, withStyleContext } from '@cdx-ui/utils';
18
+ import { cn, ParentContext, useParentContext, useStyleContext } from '@cdx-ui/utils';
24
19
  import { Icon } from '../Icon';
25
20
  import {
26
21
  type DialogTitleVariantProps,
@@ -46,38 +41,8 @@ export { useDialog } from '@cdx-ui/primitives';
46
41
 
47
42
  const SCOPE = 'DIALOG';
48
43
 
49
- const Root = withStyleContext(View, SCOPE);
50
-
51
44
  const useDialogStyleContext = () => useStyleContext(SCOPE) as DialogVariantProps;
52
45
 
53
- // =============================================================================
54
- // STYLED OVERLAY (internal — not consumer-facing)
55
- // =============================================================================
56
-
57
- const StyledOverlay = forwardRef<View, PressableProps & { className?: string }>(
58
- ({ className, ...props }, ref) => (
59
- <Pressable ref={ref} className={cn(dialogOverlayVariants(), className)} {...props} />
60
- ),
61
- );
62
- StyledOverlay.displayName = 'Dialog.Overlay';
63
-
64
- // =============================================================================
65
- // CREATE DIALOG PRIMITIVE
66
- // =============================================================================
67
-
68
- const DialogPrimitive = createDialog({
69
- Root,
70
- Trigger: Pressable,
71
- Overlay: StyledOverlay,
72
- Popup: View,
73
- Header: View,
74
- Title: Text,
75
- Description: Text,
76
- Content: View,
77
- Footer: View,
78
- Close: Pressable,
79
- });
80
-
81
46
  // =============================================================================
82
47
  // STYLED ROOT
83
48
  // =============================================================================
@@ -88,17 +53,27 @@ export interface DialogRootProps
88
53
  }
89
54
 
90
55
  const DialogRoot = forwardRef<View, DialogRootProps>(
91
- ({ size = 'md', fullBleed = false, className, children, style, ...props }, ref) => (
92
- <DialogPrimitive
93
- ref={ref}
94
- className={className}
95
- style={style}
96
- context={{ size, fullBleed }}
97
- {...props}
98
- >
99
- {children}
100
- </DialogPrimitive>
101
- ),
56
+ ({ size = 'md', fullBleed = false, className, children, style, ...props }, ref) => {
57
+ const parent = useParentContext();
58
+ const ctx = useMemo(
59
+ () => ({ ...parent, [SCOPE]: { size, fullBleed } }),
60
+ [parent, size, fullBleed],
61
+ );
62
+
63
+ return (
64
+ <ParentContext.Provider value={ctx}>
65
+ <DialogRootPrimitive
66
+ ref={ref}
67
+ className={className}
68
+ style={style}
69
+ {...props}
70
+ {...mergeDataAttributes(props, dataAttributes({ slot: 'dialog' }))}
71
+ >
72
+ {children}
73
+ </DialogRootPrimitive>
74
+ </ParentContext.Provider>
75
+ );
76
+ },
102
77
  );
103
78
 
104
79
  DialogRoot.displayName = 'Dialog';
@@ -114,16 +89,22 @@ export interface DialogTriggerProps extends IDialogTriggerProps {
114
89
 
115
90
  const DialogTrigger = forwardRef<View, DialogTriggerProps>(
116
91
  ({ className, children, style, ...props }, ref) => (
117
- <DialogPrimitive.Trigger ref={ref} className={className} style={style} {...props}>
92
+ <DialogTriggerPrimitive
93
+ ref={ref}
94
+ className={className}
95
+ style={style}
96
+ {...props}
97
+ {...mergeDataAttributes(props, dataAttributes({ slot: 'dialog-trigger' }))}
98
+ >
118
99
  {children}
119
- </DialogPrimitive.Trigger>
100
+ </DialogTriggerPrimitive>
120
101
  ),
121
102
  );
122
103
 
123
104
  DialogTrigger.displayName = 'Dialog.Trigger';
124
105
 
125
106
  // =============================================================================
126
- // STYLED POPUP (wraps DialogPrimitive.Popup)
107
+ // STYLED POPUP
127
108
  // =============================================================================
128
109
 
129
110
  export interface DialogPopupProps extends IDialogPopupProps, Pick<DialogVariantProps, 'size'> {
@@ -136,11 +117,19 @@ const DialogPopup = forwardRef<View, DialogPopupProps>(
136
117
  const { size: contextSize } = useDialogStyleContext();
137
118
  const size = sizeProp ?? contextSize;
138
119
  const computedClassName = cn(dialogPopupVariants({ size }), className);
120
+ const overlayClassName = cn(dialogOverlayVariants());
139
121
 
140
122
  return (
141
- <DialogPrimitive.Popup ref={ref} className={computedClassName} style={style} {...props}>
123
+ <DialogPopupPrimitive
124
+ ref={ref}
125
+ className={computedClassName}
126
+ style={style}
127
+ overlayClassName={overlayClassName}
128
+ {...props}
129
+ {...mergeDataAttributes(props, dataAttributes({ slot: 'dialog-popup' }))}
130
+ >
142
131
  {children}
143
- </DialogPrimitive.Popup>
132
+ </DialogPopupPrimitive>
144
133
  );
145
134
  },
146
135
  );
@@ -148,22 +137,30 @@ const DialogPopup = forwardRef<View, DialogPopupProps>(
148
137
  DialogPopup.displayName = 'Dialog.Popup';
149
138
 
150
139
  // =============================================================================
151
- // STYLED HEADER
140
+ // STYLED HEADER (styled-only sub-slot)
152
141
  // =============================================================================
153
142
 
154
- export interface DialogHeaderProps extends IDialogHeaderProps {
143
+ export interface DialogHeaderProps extends ViewProps {
144
+ asChild?: boolean;
155
145
  className?: string;
156
146
  children?: ReactNode;
157
147
  }
158
148
 
159
149
  const DialogHeader = forwardRef<View, DialogHeaderProps>(
160
- ({ className, children, style, ...props }, ref) => {
150
+ ({ asChild, className, children, style, ...props }, ref) => {
161
151
  const computedClassName = cn(dialogHeaderVariants(), className);
152
+ const Comp = asChild ? Slot : View;
162
153
 
163
154
  return (
164
- <DialogPrimitive.Header ref={ref} className={computedClassName} style={style} {...props}>
155
+ <Comp
156
+ ref={ref}
157
+ className={computedClassName}
158
+ style={style}
159
+ {...props}
160
+ {...mergeDataAttributes(props, dataAttributes({ slot: 'dialog-header' }))}
161
+ >
165
162
  {children}
166
- </DialogPrimitive.Header>
163
+ </Comp>
167
164
  );
168
165
  },
169
166
  );
@@ -171,7 +168,7 @@ const DialogHeader = forwardRef<View, DialogHeaderProps>(
171
168
  DialogHeader.displayName = 'Dialog.Header';
172
169
 
173
170
  // =============================================================================
174
- // STYLED TITLE
171
+ // STYLED TITLE (styled-only sub-slot with appearance variants)
175
172
  // =============================================================================
176
173
 
177
174
  const APPEARANCE_ICON_MAP = {
@@ -180,57 +177,75 @@ const APPEARANCE_ICON_MAP = {
180
177
  success: CheckCircle,
181
178
  } as const;
182
179
 
183
- export interface DialogTitleProps extends IDialogTitleProps, DialogTitleVariantProps {
180
+ export interface DialogTitleProps extends TextProps, DialogTitleVariantProps {
181
+ asChild?: boolean;
184
182
  className?: string;
185
183
  children?: ReactNode;
186
184
  }
187
185
 
188
186
  const DialogTitle = forwardRef<Text, DialogTitleProps>(
189
- ({ appearance = 'default', className, children, style, ...props }, ref) => {
187
+ ({ asChild, appearance = 'default', className, children, style, ...props }, ref) => {
190
188
  const computedClassName = cn(dialogTitleVariants({ appearance }), className);
191
189
  const IconComponent =
192
190
  appearance && appearance in APPEARANCE_ICON_MAP
193
191
  ? APPEARANCE_ICON_MAP[appearance as keyof typeof APPEARANCE_ICON_MAP]
194
192
  : null;
193
+ const Comp = asChild ? Slot : Text;
194
+
195
+ const titleElement = (
196
+ <Comp
197
+ ref={ref}
198
+ className={computedClassName}
199
+ style={style}
200
+ {...props}
201
+ {...mergeDataAttributes(props, dataAttributes({ slot: 'dialog-title' }))}
202
+ >
203
+ {children}
204
+ </Comp>
205
+ );
195
206
 
196
207
  if (IconComponent) {
197
208
  return (
198
209
  <View className="flex-row items-center gap-1">
199
210
  <Icon as={IconComponent} className={dialogTitleIconVariants({ appearance })} />
200
- <DialogPrimitive.Title ref={ref} className={computedClassName} style={style} {...props}>
201
- {children}
202
- </DialogPrimitive.Title>
211
+ {titleElement}
203
212
  </View>
204
213
  );
205
214
  }
206
215
 
207
- return (
208
- <DialogPrimitive.Title ref={ref} className={computedClassName} style={style} {...props}>
209
- {children}
210
- </DialogPrimitive.Title>
211
- );
216
+ return titleElement;
212
217
  },
213
218
  );
214
219
 
215
220
  DialogTitle.displayName = 'Dialog.Title';
216
221
 
217
222
  // =============================================================================
218
- // STYLED DESCRIPTION
223
+ // STYLED DESCRIPTION (styled-only sub-slot — reads dialog context for nativeID)
219
224
  // =============================================================================
220
225
 
221
- export interface DialogDescriptionProps extends IDialogDescriptionProps {
226
+ export interface DialogDescriptionProps extends TextProps {
227
+ asChild?: boolean;
222
228
  className?: string;
223
229
  children?: ReactNode;
224
230
  }
225
231
 
226
232
  const DialogDescription = forwardRef<Text, DialogDescriptionProps>(
227
- ({ className, children, style, ...props }, ref) => {
233
+ ({ asChild, className, children, style, ...props }, ref) => {
234
+ const { nativeID } = useDialog();
228
235
  const computedClassName = cn(dialogDescriptionVariants(), className);
236
+ const Comp = asChild ? Slot : Text;
229
237
 
230
238
  return (
231
- <DialogPrimitive.Description ref={ref} className={computedClassName} style={style} {...props}>
239
+ <Comp
240
+ ref={ref}
241
+ nativeID={`${nativeID}-description`}
242
+ className={computedClassName}
243
+ style={style}
244
+ {...props}
245
+ {...mergeDataAttributes(props, dataAttributes({ slot: 'dialog-description' }))}
246
+ >
232
247
  {children}
233
- </DialogPrimitive.Description>
248
+ </Comp>
234
249
  );
235
250
  },
236
251
  );
@@ -238,26 +253,34 @@ const DialogDescription = forwardRef<Text, DialogDescriptionProps>(
238
253
  DialogDescription.displayName = 'Dialog.Description';
239
254
 
240
255
  // =============================================================================
241
- // STYLED CONTENT (wraps DialogPrimitive.Content)
256
+ // STYLED CONTENT (styled-only sub-slot — reads variant context for fullBleed)
242
257
  // =============================================================================
243
258
 
244
- export interface DialogContentProps extends IDialogContentProps {
259
+ export interface DialogContentProps extends ViewProps {
260
+ asChild?: boolean;
245
261
  className?: string;
246
262
  children?: ReactNode;
247
263
  }
248
264
 
249
265
  const DialogContent = forwardRef<View, DialogContentProps>(
250
- ({ className, children, style, ...props }, ref) => {
266
+ ({ asChild, className, children, style, ...props }, ref) => {
251
267
  const { fullBleed } = useDialogStyleContext();
252
268
  const computedClassName = cn(
253
269
  dialogContentVariants({ fullBleed: fullBleed ?? false }),
254
270
  className,
255
271
  );
272
+ const Comp = asChild ? Slot : View;
256
273
 
257
274
  return (
258
- <DialogPrimitive.Content ref={ref} className={computedClassName} style={style} {...props}>
275
+ <Comp
276
+ ref={ref}
277
+ className={computedClassName}
278
+ style={style}
279
+ {...props}
280
+ {...mergeDataAttributes(props, dataAttributes({ slot: 'dialog-content' }))}
281
+ >
259
282
  {children}
260
- </DialogPrimitive.Content>
283
+ </Comp>
261
284
  );
262
285
  },
263
286
  );
@@ -265,22 +288,30 @@ const DialogContent = forwardRef<View, DialogContentProps>(
265
288
  DialogContent.displayName = 'Dialog.Content';
266
289
 
267
290
  // =============================================================================
268
- // STYLED TEXT
291
+ // STYLED TEXT (convenience text styling, styled-only)
269
292
  // =============================================================================
270
293
 
271
294
  export interface DialogTextProps extends TextProps {
295
+ asChild?: boolean;
272
296
  className?: string;
273
297
  children?: ReactNode;
274
298
  }
275
299
 
276
300
  const DialogText = forwardRef<Text, DialogTextProps>(
277
- ({ className, children, style, ...props }, ref) => {
301
+ ({ asChild, className, children, style, ...props }, ref) => {
278
302
  const computedClassName = cn(dialogTextVariants(), className);
303
+ const Comp = asChild ? Slot : Text;
279
304
 
280
305
  return (
281
- <Text ref={ref} className={computedClassName} style={style} {...props}>
306
+ <Comp
307
+ ref={ref}
308
+ className={computedClassName}
309
+ style={style}
310
+ {...props}
311
+ {...mergeDataAttributes(props, dataAttributes({ slot: 'dialog-text' }))}
312
+ >
282
313
  {children}
283
- </Text>
314
+ </Comp>
284
315
  );
285
316
  },
286
317
  );
@@ -288,22 +319,30 @@ const DialogText = forwardRef<Text, DialogTextProps>(
288
319
  DialogText.displayName = 'Dialog.Text';
289
320
 
290
321
  // =============================================================================
291
- // STYLED FOOTER
322
+ // STYLED FOOTER (styled-only sub-slot)
292
323
  // =============================================================================
293
324
 
294
- export interface DialogFooterProps extends IDialogFooterProps {
325
+ export interface DialogFooterProps extends ViewProps {
326
+ asChild?: boolean;
295
327
  className?: string;
296
328
  children?: ReactNode;
297
329
  }
298
330
 
299
331
  const DialogFooter = forwardRef<View, DialogFooterProps>(
300
- ({ className, children, style, ...props }, ref) => {
332
+ ({ asChild, className, children, style, ...props }, ref) => {
301
333
  const computedClassName = cn(dialogFooterVariants(), className);
334
+ const Comp = asChild ? Slot : View;
302
335
 
303
336
  return (
304
- <DialogPrimitive.Footer ref={ref} className={computedClassName} style={style} {...props}>
337
+ <Comp
338
+ ref={ref}
339
+ className={computedClassName}
340
+ style={style}
341
+ {...props}
342
+ {...mergeDataAttributes(props, dataAttributes({ slot: 'dialog-footer' }))}
343
+ >
305
344
  {children}
306
- </DialogPrimitive.Footer>
345
+ </Comp>
307
346
  );
308
347
  },
309
348
  );
@@ -324,7 +363,7 @@ const DialogClose = forwardRef<View, DialogCloseProps>(
324
363
  const computedClassName = cn(dialogCloseVariants(), className);
325
364
 
326
365
  return (
327
- <DialogPrimitive.Close
366
+ <DialogClosePrimitive
328
367
  ref={ref}
329
368
  className={computedClassName}
330
369
  style={style}
@@ -332,9 +371,10 @@ const DialogClose = forwardRef<View, DialogCloseProps>(
332
371
  accessibilityRole="button"
333
372
  accessibilityLabel={accessibilityLabel}
334
373
  {...props}
374
+ {...mergeDataAttributes(props, dataAttributes({ slot: 'dialog-close' }))}
335
375
  >
336
376
  {children ?? <Icon as={CloseIcon} className={dialogCloseIconVariants()} />}
337
- </DialogPrimitive.Close>
377
+ </DialogClosePrimitive>
338
378
  );
339
379
  },
340
380
  );