@cdx-ui/primitives 0.0.1-beta.6 → 0.0.1-beta.60

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 (297) hide show
  1. package/README.md +51 -25
  2. package/lib/commonjs/CLAUDE.md +32 -0
  3. package/lib/commonjs/avatar/createAvatarText.js +9 -1
  4. package/lib/commonjs/avatar/createAvatarText.js.map +1 -1
  5. package/lib/commonjs/button/createButtonText.js +1 -0
  6. package/lib/commonjs/button/createButtonText.js.map +1 -1
  7. package/lib/commonjs/checkbox/createCheckboxRoot.web.js +8 -3
  8. package/lib/commonjs/checkbox/createCheckboxRoot.web.js.map +1 -1
  9. package/lib/commonjs/chip/createChipRoot.js +132 -0
  10. package/lib/commonjs/chip/createChipRoot.js.map +1 -0
  11. package/lib/commonjs/chip/index.js +16 -0
  12. package/lib/commonjs/chip/index.js.map +1 -0
  13. package/lib/commonjs/chip/types.js +6 -0
  14. package/lib/commonjs/chip/types.js.map +1 -0
  15. package/lib/commonjs/dialog/createDialogContent.js +7 -127
  16. package/lib/commonjs/dialog/createDialogContent.js.map +1 -1
  17. package/lib/commonjs/dialog/createDialogPopup.js +157 -0
  18. package/lib/commonjs/dialog/createDialogPopup.js.map +1 -0
  19. package/lib/commonjs/dialog/index.js +8 -8
  20. package/lib/commonjs/dialog/index.js.map +1 -1
  21. package/lib/commonjs/field/createFieldLabel.js.map +1 -1
  22. package/lib/commonjs/index.js +45 -1
  23. package/lib/commonjs/index.js.map +1 -1
  24. package/lib/commonjs/input/createInputField.js +5 -0
  25. package/lib/commonjs/input/createInputField.js.map +1 -1
  26. package/lib/commonjs/link/context.js +11 -0
  27. package/lib/commonjs/link/context.js.map +1 -0
  28. package/lib/commonjs/link/createLink.js +28 -14
  29. package/lib/commonjs/link/createLink.js.map +1 -1
  30. package/lib/commonjs/link/index.js +13 -0
  31. package/lib/commonjs/link/index.js.map +1 -1
  32. package/lib/commonjs/list-item/createListItemRoot.js +64 -37
  33. package/lib/commonjs/list-item/createListItemRoot.js.map +1 -1
  34. package/lib/commonjs/list-item/index.js.map +1 -1
  35. package/lib/commonjs/radio/context.js +14 -0
  36. package/lib/commonjs/radio/context.js.map +1 -0
  37. package/lib/commonjs/radio/createRadioGroup.js +66 -0
  38. package/lib/commonjs/radio/createRadioGroup.js.map +1 -0
  39. package/lib/commonjs/radio/createRadioIndicator.js +43 -0
  40. package/lib/commonjs/radio/createRadioIndicator.js.map +1 -0
  41. package/lib/commonjs/radio/createRadioLabel.js +38 -0
  42. package/lib/commonjs/radio/createRadioLabel.js.map +1 -0
  43. package/lib/commonjs/radio/createRadioRoot.js +95 -0
  44. package/lib/commonjs/radio/createRadioRoot.js.map +1 -0
  45. package/lib/commonjs/radio/createRadioRoot.web.js +87 -0
  46. package/lib/commonjs/radio/createRadioRoot.web.js.map +1 -0
  47. package/lib/commonjs/radio/index.js +26 -0
  48. package/lib/commonjs/radio/index.js.map +1 -0
  49. package/lib/commonjs/radio/types.js +6 -0
  50. package/lib/commonjs/radio/types.js.map +1 -0
  51. package/lib/commonjs/radio/useRadioRoot.js +64 -0
  52. package/lib/commonjs/radio/useRadioRoot.js.map +1 -0
  53. package/lib/commonjs/select/createSelectIcon.js +3 -1
  54. package/lib/commonjs/select/createSelectIcon.js.map +1 -1
  55. package/lib/commonjs/select/createSelectTrigger.js +17 -4
  56. package/lib/commonjs/select/createSelectTrigger.js.map +1 -1
  57. package/lib/commonjs/tile/context.js +30 -0
  58. package/lib/commonjs/tile/context.js.map +1 -0
  59. package/lib/commonjs/tile/createTileContent.js +30 -0
  60. package/lib/commonjs/tile/createTileContent.js.map +1 -0
  61. package/lib/commonjs/tile/createTileDescription.js +28 -0
  62. package/lib/commonjs/tile/createTileDescription.js.map +1 -0
  63. package/lib/commonjs/tile/createTileGroup.js +112 -0
  64. package/lib/commonjs/tile/createTileGroup.js.map +1 -0
  65. package/lib/commonjs/tile/createTileIndicator.js +46 -0
  66. package/lib/commonjs/tile/createTileIndicator.js.map +1 -0
  67. package/lib/commonjs/tile/createTileLeadingSlot.js +34 -0
  68. package/lib/commonjs/tile/createTileLeadingSlot.js.map +1 -0
  69. package/lib/commonjs/tile/createTileRoot.js +133 -0
  70. package/lib/commonjs/tile/createTileRoot.js.map +1 -0
  71. package/lib/commonjs/{dialog/createDialogBody.js → tile/createTileTitle.js} +18 -11
  72. package/lib/commonjs/tile/createTileTitle.js.map +1 -0
  73. package/lib/commonjs/tile/createTileTrailingSlot.js +35 -0
  74. package/lib/commonjs/tile/createTileTrailingSlot.js.map +1 -0
  75. package/lib/commonjs/tile/index.js +55 -0
  76. package/lib/commonjs/tile/index.js.map +1 -0
  77. package/lib/commonjs/tile/types.js +6 -0
  78. package/lib/commonjs/tile/types.js.map +1 -0
  79. package/lib/commonjs/utils/dataAttributes.js +6 -25
  80. package/lib/commonjs/utils/dataAttributes.js.map +1 -1
  81. package/lib/commonjs/utils/domDataAttributes.js +34 -0
  82. package/lib/commonjs/utils/domDataAttributes.js.map +1 -0
  83. package/lib/module/CLAUDE.md +32 -0
  84. package/lib/module/avatar/createAvatarText.js +9 -1
  85. package/lib/module/avatar/createAvatarText.js.map +1 -1
  86. package/lib/module/button/createButtonText.js +1 -0
  87. package/lib/module/button/createButtonText.js.map +1 -1
  88. package/lib/module/checkbox/createCheckboxRoot.web.js +8 -2
  89. package/lib/module/checkbox/createCheckboxRoot.web.js.map +1 -1
  90. package/lib/module/chip/createChipRoot.js +126 -0
  91. package/lib/module/chip/createChipRoot.js.map +1 -0
  92. package/lib/module/chip/index.js +12 -0
  93. package/lib/module/chip/index.js.map +1 -0
  94. package/lib/module/chip/types.js +4 -0
  95. package/lib/module/chip/types.js.map +1 -0
  96. package/lib/module/dialog/createDialogContent.js +7 -128
  97. package/lib/module/dialog/createDialogContent.js.map +1 -1
  98. package/lib/module/dialog/createDialogPopup.js +152 -0
  99. package/lib/module/dialog/createDialogPopup.js.map +1 -0
  100. package/lib/module/dialog/index.js +8 -8
  101. package/lib/module/dialog/index.js.map +1 -1
  102. package/lib/module/field/createFieldLabel.js.map +1 -1
  103. package/lib/module/index.js +4 -0
  104. package/lib/module/index.js.map +1 -1
  105. package/lib/module/input/createInputField.js +5 -0
  106. package/lib/module/input/createInputField.js.map +1 -1
  107. package/lib/module/link/context.js +5 -0
  108. package/lib/module/link/context.js.map +1 -0
  109. package/lib/module/link/createLink.js +29 -15
  110. package/lib/module/link/createLink.js.map +1 -1
  111. package/lib/module/link/index.js +1 -0
  112. package/lib/module/link/index.js.map +1 -1
  113. package/lib/module/list-item/createListItemRoot.js +64 -37
  114. package/lib/module/list-item/createListItemRoot.js.map +1 -1
  115. package/lib/module/list-item/index.js.map +1 -1
  116. package/lib/module/radio/context.js +7 -0
  117. package/lib/module/radio/context.js.map +1 -0
  118. package/lib/module/radio/createRadioGroup.js +61 -0
  119. package/lib/module/radio/createRadioGroup.js.map +1 -0
  120. package/lib/module/radio/createRadioIndicator.js +38 -0
  121. package/lib/module/radio/createRadioIndicator.js.map +1 -0
  122. package/lib/module/radio/createRadioLabel.js +33 -0
  123. package/lib/module/radio/createRadioLabel.js.map +1 -0
  124. package/lib/module/radio/createRadioRoot.js +90 -0
  125. package/lib/module/radio/createRadioRoot.js.map +1 -0
  126. package/lib/module/radio/createRadioRoot.web.js +82 -0
  127. package/lib/module/radio/createRadioRoot.web.js.map +1 -0
  128. package/lib/module/radio/index.js +22 -0
  129. package/lib/module/radio/index.js.map +1 -0
  130. package/lib/module/radio/types.js +4 -0
  131. package/lib/module/radio/types.js.map +1 -0
  132. package/lib/module/radio/useRadioRoot.js +60 -0
  133. package/lib/module/radio/useRadioRoot.js.map +1 -0
  134. package/lib/module/select/createSelectIcon.js +3 -1
  135. package/lib/module/select/createSelectIcon.js.map +1 -1
  136. package/lib/module/select/createSelectTrigger.js +19 -6
  137. package/lib/module/select/createSelectTrigger.js.map +1 -1
  138. package/lib/module/tile/context.js +21 -0
  139. package/lib/module/tile/context.js.map +1 -0
  140. package/lib/module/tile/createTileContent.js +24 -0
  141. package/lib/module/tile/createTileContent.js.map +1 -0
  142. package/lib/module/tile/createTileDescription.js +22 -0
  143. package/lib/module/tile/createTileDescription.js.map +1 -0
  144. package/lib/module/tile/createTileGroup.js +106 -0
  145. package/lib/module/tile/createTileGroup.js.map +1 -0
  146. package/lib/module/tile/createTileIndicator.js +40 -0
  147. package/lib/module/tile/createTileIndicator.js.map +1 -0
  148. package/lib/module/tile/createTileLeadingSlot.js +28 -0
  149. package/lib/module/tile/createTileLeadingSlot.js.map +1 -0
  150. package/lib/module/tile/createTileRoot.js +127 -0
  151. package/lib/module/tile/createTileRoot.js.map +1 -0
  152. package/lib/module/tile/createTileTitle.js +22 -0
  153. package/lib/module/tile/createTileTitle.js.map +1 -0
  154. package/lib/module/tile/createTileTrailingSlot.js +29 -0
  155. package/lib/module/tile/createTileTrailingSlot.js.map +1 -0
  156. package/lib/module/tile/index.js +39 -0
  157. package/lib/module/tile/index.js.map +1 -0
  158. package/lib/module/tile/types.js +4 -0
  159. package/lib/module/tile/types.js.map +1 -0
  160. package/lib/module/utils/dataAttributes.js +4 -22
  161. package/lib/module/utils/dataAttributes.js.map +1 -1
  162. package/lib/module/utils/domDataAttributes.js +30 -0
  163. package/lib/module/utils/domDataAttributes.js.map +1 -0
  164. package/lib/typescript/avatar/createAvatarText.d.ts.map +1 -1
  165. package/lib/typescript/button/createButtonText.d.ts.map +1 -1
  166. package/lib/typescript/checkbox/createCheckboxRoot.web.d.ts +4 -0
  167. package/lib/typescript/checkbox/createCheckboxRoot.web.d.ts.map +1 -1
  168. package/lib/typescript/checkbox/useCheckboxRoot.d.ts +2 -0
  169. package/lib/typescript/checkbox/useCheckboxRoot.d.ts.map +1 -1
  170. package/lib/typescript/chip/createChipRoot.d.ts +4 -0
  171. package/lib/typescript/chip/createChipRoot.d.ts.map +1 -0
  172. package/lib/typescript/chip/index.d.ts +9 -0
  173. package/lib/typescript/chip/index.d.ts.map +1 -0
  174. package/lib/typescript/chip/types.d.ts +17 -0
  175. package/lib/typescript/chip/types.d.ts.map +1 -0
  176. package/lib/typescript/dialog/createDialogContent.d.ts +2 -2
  177. package/lib/typescript/dialog/createDialogContent.d.ts.map +1 -1
  178. package/lib/typescript/dialog/createDialogPopup.d.ts +4 -0
  179. package/lib/typescript/dialog/createDialogPopup.d.ts.map +1 -0
  180. package/lib/typescript/dialog/index.d.ts +5 -5
  181. package/lib/typescript/dialog/index.d.ts.map +1 -1
  182. package/lib/typescript/dialog/types.d.ts +16 -5
  183. package/lib/typescript/dialog/types.d.ts.map +1 -1
  184. package/lib/typescript/field/createFieldLabel.d.ts.map +1 -1
  185. package/lib/typescript/index.d.ts +4 -0
  186. package/lib/typescript/index.d.ts.map +1 -1
  187. package/lib/typescript/input/createInputField.d.ts.map +1 -1
  188. package/lib/typescript/link/context.d.ts +10 -0
  189. package/lib/typescript/link/context.d.ts.map +1 -0
  190. package/lib/typescript/link/createLink.d.ts.map +1 -1
  191. package/lib/typescript/link/index.d.ts +2 -0
  192. package/lib/typescript/link/index.d.ts.map +1 -1
  193. package/lib/typescript/link/types.d.ts +1 -0
  194. package/lib/typescript/link/types.d.ts.map +1 -1
  195. package/lib/typescript/list-item/createListItemRoot.d.ts.map +1 -1
  196. package/lib/typescript/list-item/index.d.ts +1 -1
  197. package/lib/typescript/list-item/index.d.ts.map +1 -1
  198. package/lib/typescript/list-item/types.d.ts +1 -7
  199. package/lib/typescript/list-item/types.d.ts.map +1 -1
  200. package/lib/typescript/radio/context.d.ts +21 -0
  201. package/lib/typescript/radio/context.d.ts.map +1 -0
  202. package/lib/typescript/radio/createRadioGroup.d.ts +3 -0
  203. package/lib/typescript/radio/createRadioGroup.d.ts.map +1 -0
  204. package/lib/typescript/radio/createRadioIndicator.d.ts +5 -0
  205. package/lib/typescript/radio/createRadioIndicator.d.ts.map +1 -0
  206. package/lib/typescript/radio/createRadioLabel.d.ts +5 -0
  207. package/lib/typescript/radio/createRadioLabel.d.ts.map +1 -0
  208. package/lib/typescript/radio/createRadioRoot.d.ts +3 -0
  209. package/lib/typescript/radio/createRadioRoot.d.ts.map +1 -0
  210. package/lib/typescript/radio/createRadioRoot.web.d.ts +3 -0
  211. package/lib/typescript/radio/createRadioRoot.web.d.ts.map +1 -0
  212. package/lib/typescript/radio/index.d.ts +10 -0
  213. package/lib/typescript/radio/index.d.ts.map +1 -0
  214. package/lib/typescript/radio/types.d.ts +54 -0
  215. package/lib/typescript/radio/types.d.ts.map +1 -0
  216. package/lib/typescript/radio/useRadioRoot.d.ts +151 -0
  217. package/lib/typescript/radio/useRadioRoot.d.ts.map +1 -0
  218. package/lib/typescript/select/createSelectIcon.d.ts.map +1 -1
  219. package/lib/typescript/select/createSelectTrigger.d.ts.map +1 -1
  220. package/lib/typescript/tile/context.d.ts +9 -0
  221. package/lib/typescript/tile/context.d.ts.map +1 -0
  222. package/lib/typescript/tile/createTileContent.d.ts +3 -0
  223. package/lib/typescript/tile/createTileContent.d.ts.map +1 -0
  224. package/lib/typescript/tile/createTileDescription.d.ts +3 -0
  225. package/lib/typescript/tile/createTileDescription.d.ts.map +1 -0
  226. package/lib/typescript/tile/createTileGroup.d.ts +4 -0
  227. package/lib/typescript/tile/createTileGroup.d.ts.map +1 -0
  228. package/lib/typescript/tile/createTileIndicator.d.ts +4 -0
  229. package/lib/typescript/tile/createTileIndicator.d.ts.map +1 -0
  230. package/lib/typescript/tile/createTileLeadingSlot.d.ts +4 -0
  231. package/lib/typescript/tile/createTileLeadingSlot.d.ts.map +1 -0
  232. package/lib/typescript/tile/createTileRoot.d.ts +4 -0
  233. package/lib/typescript/tile/createTileRoot.d.ts.map +1 -0
  234. package/lib/typescript/tile/createTileTitle.d.ts +3 -0
  235. package/lib/typescript/tile/createTileTitle.d.ts.map +1 -0
  236. package/lib/typescript/tile/createTileTrailingSlot.d.ts +9 -0
  237. package/lib/typescript/tile/createTileTrailingSlot.d.ts.map +1 -0
  238. package/lib/typescript/tile/index.d.ts +15 -0
  239. package/lib/typescript/tile/index.d.ts.map +1 -0
  240. package/lib/typescript/tile/types.d.ts +119 -0
  241. package/lib/typescript/tile/types.d.ts.map +1 -0
  242. package/lib/typescript/utils/dataAttributes.d.ts +4 -10
  243. package/lib/typescript/utils/dataAttributes.d.ts.map +1 -1
  244. package/lib/typescript/utils/domDataAttributes.d.ts +15 -0
  245. package/lib/typescript/utils/domDataAttributes.d.ts.map +1 -0
  246. package/package.json +5 -2
  247. package/src/CLAUDE.md +32 -0
  248. package/src/avatar/createAvatarText.tsx +10 -1
  249. package/src/button/createButtonText.tsx +1 -0
  250. package/src/checkbox/createCheckboxRoot.web.tsx +6 -2
  251. package/src/chip/createChipRoot.tsx +144 -0
  252. package/src/chip/index.ts +18 -0
  253. package/src/chip/types.ts +23 -0
  254. package/src/dialog/createDialogContent.tsx +6 -117
  255. package/src/dialog/createDialogPopup.tsx +146 -0
  256. package/src/dialog/index.tsx +16 -16
  257. package/src/dialog/types.ts +20 -9
  258. package/src/field/createFieldLabel.tsx +4 -1
  259. package/src/index.ts +4 -0
  260. package/src/input/createInputField.tsx +6 -0
  261. package/src/link/context.tsx +10 -0
  262. package/src/link/createLink.tsx +41 -23
  263. package/src/link/index.tsx +2 -0
  264. package/src/link/types.ts +1 -0
  265. package/src/list-item/createListItemRoot.tsx +68 -36
  266. package/src/list-item/index.ts +0 -1
  267. package/src/list-item/types.ts +1 -8
  268. package/src/radio/context.tsx +21 -0
  269. package/src/radio/createRadioGroup.tsx +67 -0
  270. package/src/radio/createRadioIndicator.tsx +32 -0
  271. package/src/radio/createRadioLabel.tsx +28 -0
  272. package/src/radio/createRadioRoot.tsx +100 -0
  273. package/src/radio/createRadioRoot.web.tsx +81 -0
  274. package/src/radio/index.ts +37 -0
  275. package/src/radio/types.ts +67 -0
  276. package/src/radio/useRadioRoot.ts +69 -0
  277. package/src/select/createSelectIcon.tsx +2 -1
  278. package/src/select/createSelectTrigger.tsx +26 -3
  279. package/src/tile/context.tsx +23 -0
  280. package/src/tile/createTileContent.tsx +23 -0
  281. package/src/tile/createTileDescription.tsx +19 -0
  282. package/src/tile/createTileGroup.tsx +134 -0
  283. package/src/tile/createTileIndicator.tsx +38 -0
  284. package/src/tile/createTileLeadingSlot.tsx +30 -0
  285. package/src/tile/createTileRoot.tsx +124 -0
  286. package/src/tile/createTileTitle.tsx +19 -0
  287. package/src/tile/createTileTrailingSlot.tsx +25 -0
  288. package/src/tile/index.ts +88 -0
  289. package/src/tile/types.ts +153 -0
  290. package/src/utils/dataAttributes.ts +4 -25
  291. package/src/utils/domDataAttributes.ts +32 -0
  292. package/lib/commonjs/dialog/createDialogBody.js.map +0 -1
  293. package/lib/module/dialog/createDialogBody.js +0 -15
  294. package/lib/module/dialog/createDialogBody.js.map +0 -1
  295. package/lib/typescript/dialog/createDialogBody.d.ts +0 -4
  296. package/lib/typescript/dialog/createDialogBody.d.ts.map +0 -1
  297. package/src/dialog/createDialogBody.tsx +0 -11
package/src/CLAUDE.md ADDED
@@ -0,0 +1,32 @@
1
+ # Primitive Authoring
2
+
3
+ Auto-loaded when working in `packages/primitives/src/**`.
4
+
5
+ Primitives in `@cdx-ui/primitives` are unstyled behavioral components that handle accessibility and interactions. Read the full guides before making changes:
6
+
7
+ - `docs/internal/practices/composition.md` — compound component structure
8
+ - `docs/internal/practices/types.md` — `I*Props` convention, extending RN base types
9
+ - `docs/internal/practices/accessibility.md` — ARIA roles, keyboard nav, screen reader support
10
+ - `docs/internal/practices/as-child.md` — `asChild` prop pattern
11
+
12
+ ## Pattern summary
13
+
14
+ Each primitive follows the factory function pattern (see `createButtonRoot.tsx` as the canonical example):
15
+
16
+ 1. **Factory function** — `export const createComponentPart = <T,>(BaseComponent: ComponentType<T>) => forwardRef(...)` — accepts a host element type, returns a wrapped component with behavior
17
+ 2. **Interaction hooks** — `useFocus`, `useFocusRing`, `useHover`, `usePress` from `@react-native-aria/*`
18
+ 3. **Data attributes** — `dataAttributes({ hover, focus, active, disabled, focusVisible })` emitted on the rendered element for Uniwind `data-[state]` selectors
19
+ 4. **Context provider** — interaction state exposed via context so child primitives can react to parent state
20
+ 5. **Barrel export** — `index.tsx` re-exports the factory, context, and types
21
+
22
+ ## Key rules
23
+
24
+ - **Unstyled** — no visual styling (no `className`, no color/spacing classes). Only behavioral and a11y concerns.
25
+ - **`I*Props` convention** — public prop types are aliased with `I` prefix (e.g., `IButtonProps`, `ICheckboxProps`), exported from `types.ts`
26
+ - **`Interface*Props` pattern** — the full interface (e.g., `InterfaceButtonProps`, `InterfaceCheckbox`) extends the appropriate RN base type (`PressableProps`, `ViewProps`, etc.) with interaction state booleans (`isHovered`, `isActive`, `isFocused`, `isFocusVisible`, `isDisabled`); re-exported as `I*Props` (e.g., `export type IButtonProps = InterfaceButtonProps`)
27
+ - **`dataAttributes()` helper** — always use the helper from `../utils/dataAttributes` to emit `data-*` props; it handles platform differences (native vs web)
28
+ - **`composeEventHandlers`** from `@cdx-ui/utils` — merge consumer handlers with internal handlers; never silently override
29
+ - **`forwardRef`** on every component — refs forwarded to the underlying host element
30
+ - **ARIA roles** — set `role` with a sensible default (e.g., `role={props?.role || 'button'}`)
31
+ - **Render children as function** — support `children` as `(state: InteractionState) => ReactNode` for state-driven rendering
32
+ - **Consumable independently** of `@cdx-ui/components` — no imports from the styled layer
@@ -4,7 +4,16 @@ import { useAvatarContext } from './context';
4
4
  import type { IAvatarTextProps } from './types';
5
5
 
6
6
  function getInitials(name: string): string {
7
- const words = name.trim().split(/\s+/);
7
+ const trimmed = name.trim();
8
+ const words = trimmed.split(/\s+/);
9
+
10
+ // Pre-composed initials (e.g. "JD", "AB") — single token, at most 2 chars.
11
+ // Figma Code Connect surfaces the raw text property which is already initials;
12
+ // passing them through a derivation step would truncate to the first letter.
13
+ if (words.length === 1 && trimmed.length <= 2) {
14
+ return trimmed.toUpperCase();
15
+ }
16
+
8
17
  let result = '';
9
18
  for (const word of words) {
10
19
  if (word.length > 0) {
@@ -5,6 +5,7 @@ import { useButtonContext } from './context';
5
5
  import type { IButtonTextProps } from './types';
6
6
 
7
7
  // TODO: Rename to ButtonLabel
8
+ // TODO: Can we remove the dataAttributes here?
8
9
 
9
10
  export const createButtonText = <T,>(BaseButtonText: React.ComponentType<T>) =>
10
11
  forwardRef<unknown, IButtonTextProps>(({ children, ...props }, ref) => {
@@ -6,8 +6,10 @@ import { CheckboxProvider } from './context';
6
6
  import type { ICheckboxProps } from './types';
7
7
  import { useCheckboxRoot } from './useCheckboxRoot';
8
8
 
9
- // TODO: Label is taking focus on keyboard navigation
10
-
9
+ /**
10
+ * Web uses a native checkbox input (VisuallyHidden) for ARIA + focus management. The outer
11
+ * `Pressable` must not be in the tab order or each control consumes two Tab stops (wrapper + input).
12
+ */
11
13
  export const createCheckboxRoot = <T,>(BaseCheckbox: React.ComponentType<T>) =>
12
14
  forwardRef(({ children, ...props }: ICheckboxProps, ref?: React.Ref<T>) => {
13
15
  const {
@@ -41,6 +43,8 @@ export const createCheckboxRoot = <T,>(BaseCheckbox: React.ComponentType<T>) =>
41
43
  <BaseCheckbox
42
44
  {...(combinedProps as T)}
43
45
  ref={mergedRef}
46
+ // Native input is the only tab stop; Pressable is still clickable (mouse / screen reader).
47
+ tabIndex={-1}
44
48
  role="label"
45
49
  // eslint-disable-next-line react-native-a11y/has-valid-accessibility-role
46
50
  accessibilityRole="label"
@@ -0,0 +1,144 @@
1
+ import React, { forwardRef } from 'react';
2
+ import type { PressableProps } from 'react-native';
3
+ import { composeEventHandlers, mergeRefs } from '@cdx-ui/utils';
4
+ import { useFocus, useFocusRing } from '@react-native-aria/focus';
5
+ import { useHover, usePress } from '@react-native-aria/interactions';
6
+ import { dataAttributes } from '../utils/dataAttributes';
7
+ import type { IChipPressablePassthrough, IChipProps } from './types';
8
+
9
+ const rowStyle = {
10
+ flexDirection: 'row' as const,
11
+ alignItems: 'center' as const,
12
+ alignSelf: 'flex-start' as const,
13
+ };
14
+
15
+ const chipSlotAttrs = dataAttributes({ slot: 'chip' });
16
+
17
+ export const createChipRoot = <V, P>(
18
+ BaseView: React.ComponentType<V>,
19
+ BasePressable: React.ComponentType<P>,
20
+ ) =>
21
+ forwardRef(
22
+ (
23
+ {
24
+ asChild = false,
25
+ children,
26
+ onPress,
27
+ disabled = false,
28
+ accessibilityRole,
29
+ style,
30
+ ...restProps
31
+ }: IChipProps,
32
+ ref: React.Ref<unknown>,
33
+ ) => {
34
+ const childOnPress = React.isValidElement(children)
35
+ ? ((children.props as { onPress?: unknown }).onPress as IChipProps['onPress'] | undefined)
36
+ : undefined;
37
+
38
+ const asChildInteractive = asChild && React.isValidElement(children);
39
+ const isPressableRoot = !!onPress && !asChildInteractive;
40
+
41
+ const pressState = usePress({
42
+ isDisabled: !isPressableRoot || disabled,
43
+ });
44
+ const isPressed = pressState.isPressed;
45
+ const pressProps = pressState.pressProps as Pick<PressableProps, 'onPressIn' | 'onPressOut'>;
46
+
47
+ const { hoverProps, isHovered } = useHover();
48
+ const { isFocused, focusProps } = useFocus();
49
+ const { isFocusVisible, focusProps: focusRingProps } = useFocusRing() as {
50
+ isFocusVisible: boolean;
51
+ focusProps: typeof focusProps;
52
+ };
53
+
54
+ if (asChildInteractive) {
55
+ const child = children as React.ReactElement<Record<string, unknown>>;
56
+
57
+ const childDisabled = !!(child.props as { disabled?: boolean }).disabled;
58
+ const resolvedDisabled = disabled || childDisabled;
59
+
60
+ const cloneProps: Record<string, unknown> = {
61
+ ...restProps,
62
+ ...chipSlotAttrs,
63
+ ...dataAttributes({
64
+ active: false,
65
+ hover: false,
66
+ disabled: resolvedDisabled,
67
+ focused: false,
68
+ focusVisible: false,
69
+ }),
70
+ ...(resolvedDisabled && { accessibilityState: { disabled: true } }),
71
+ disabled: resolvedDisabled,
72
+ ref: mergeRefs(ref, child.props.ref as React.Ref<unknown>),
73
+ style: [rowStyle, style, child.props.style],
74
+ };
75
+
76
+ if (resolvedDisabled) {
77
+ cloneProps.onPress = undefined;
78
+ } else if (onPress) {
79
+ cloneProps.onPress = composeEventHandlers(childOnPress, onPress);
80
+ }
81
+
82
+ return React.cloneElement(child, cloneProps);
83
+ }
84
+
85
+ if (isPressableRoot) {
86
+ const interactionAttrs = dataAttributes({
87
+ active: isPressed,
88
+ hover: isHovered,
89
+ disabled,
90
+ focused: isFocused,
91
+ focusVisible: isFocusVisible,
92
+ });
93
+
94
+ const {
95
+ onPressIn: onPressInProp,
96
+ onPressOut: onPressOutProp,
97
+ onHoverIn: onHoverInProp,
98
+ onHoverOut: onHoverOutProp,
99
+ onFocus: onFocusProp,
100
+ onBlur: onBlurProp,
101
+ } = restProps as IChipPressablePassthrough & Pick<PressableProps, 'onFocus' | 'onBlur'>;
102
+
103
+ return (
104
+ <BasePressable
105
+ {...(restProps as P)}
106
+ {...chipSlotAttrs}
107
+ {...interactionAttrs}
108
+ accessibilityRole={accessibilityRole ?? 'button'}
109
+ {...(disabled && { accessibilityState: { disabled: true } })}
110
+ disabled={disabled}
111
+ ref={ref as React.Ref<P>}
112
+ style={[rowStyle, style]}
113
+ onPress={disabled ? undefined : onPress}
114
+ onPressIn={composeEventHandlers(onPressInProp, pressProps.onPressIn)}
115
+ onPressOut={composeEventHandlers(onPressOutProp, pressProps.onPressOut)}
116
+ onHoverIn={composeEventHandlers(onHoverInProp, hoverProps.onHoverIn)}
117
+ onHoverOut={composeEventHandlers(onHoverOutProp, hoverProps.onHoverOut)}
118
+ onFocus={composeEventHandlers(
119
+ composeEventHandlers(onFocusProp, focusProps.onFocus),
120
+ focusRingProps.onFocus,
121
+ )}
122
+ onBlur={composeEventHandlers(
123
+ composeEventHandlers(onBlurProp, focusProps.onBlur),
124
+ focusRingProps.onBlur,
125
+ )}
126
+ >
127
+ {children}
128
+ </BasePressable>
129
+ );
130
+ }
131
+
132
+ return (
133
+ <BaseView
134
+ {...(restProps as V)}
135
+ {...chipSlotAttrs}
136
+ {...(disabled ? dataAttributes({ disabled: true }) : undefined)}
137
+ ref={ref as React.Ref<V>}
138
+ style={[rowStyle, style]}
139
+ >
140
+ {children}
141
+ </BaseView>
142
+ );
143
+ },
144
+ );
@@ -0,0 +1,18 @@
1
+ import type React from 'react';
2
+ import type { PressableProps, ViewProps } from 'react-native';
3
+ import { createChipRoot } from './createChipRoot';
4
+ import type { IChipComponentType } from './types';
5
+
6
+ export type { IChipComponentType, IChipPressablePassthrough, IChipProps } from './types';
7
+
8
+ export function createChip({
9
+ View,
10
+ Pressable,
11
+ }: {
12
+ View: React.ComponentType<ViewProps>;
13
+ Pressable: React.ComponentType<PressableProps>;
14
+ }) {
15
+ const Chip = createChipRoot(View, Pressable);
16
+ Chip.displayName = 'ChipPrimitive';
17
+ return Chip as IChipComponentType<ViewProps | PressableProps>;
18
+ }
@@ -0,0 +1,23 @@
1
+ import type { ForwardRefExoticComponent, RefAttributes } from 'react';
2
+ import type { PressableProps, ViewProps } from 'react-native';
3
+
4
+ export type IChipPressablePassthrough = Partial<
5
+ Pick<PressableProps, 'onPressIn' | 'onPressOut' | 'onHoverIn' | 'onHoverOut'>
6
+ >;
7
+
8
+ export interface IChipProps extends ViewProps, IChipPressablePassthrough {
9
+ /**
10
+ * When set (and `asChild` is not used with a valid element), root renders as pressable.
11
+ */
12
+ onPress?: PressableProps['onPress'];
13
+ /** Disables press handling when the root is pressable. */
14
+ disabled?: boolean;
15
+ /**
16
+ * Merge slot + interaction props onto a single child instead of rendering the default pressable root.
17
+ */
18
+ asChild?: boolean;
19
+ }
20
+
21
+ export type IChipComponentType<RootRef> = ForwardRefExoticComponent<
22
+ RefAttributes<RootRef> & IChipProps
23
+ >;
@@ -1,122 +1,11 @@
1
- import type React from 'react';
2
- import { forwardRef, useCallback } from 'react';
3
- import { Modal, Platform, StyleSheet, View } from 'react-native';
4
- import { FocusScope } from '@react-native-aria/focus';
5
- import { useEscapeKey } from '../overlay';
6
- import { createPortalFn } from '../utils/createPortal';
7
- import { dataAttributes } from '../utils/dataAttributes';
8
- import { useDialog } from './context';
1
+ import React, { forwardRef } from 'react';
9
2
  import type { IDialogContentProps } from './types';
10
3
 
11
- export const createDialogContent = <ContentProps, OverlayProps>(
12
- BaseContent: React.ComponentType<ContentProps>,
13
- BaseOverlay: React.ComponentType<OverlayProps>,
14
- ) =>
15
- forwardRef(({ children, forceMount = false, ...props }: IDialogContentProps, ref?: any) => {
16
- const { open, onOpenChange, closeOnBackdropPress, closeOnEscKey, nativeID, role } = useDialog();
17
-
18
- const handleClose = useCallback(() => {
19
- onOpenChange(false);
20
- }, [onOpenChange]);
21
-
22
- useEscapeKey(open && closeOnEscKey, handleClose);
23
-
24
- if (!(open || forceMount)) {
25
- return null;
26
- }
27
-
28
- const overlayProps = {
29
- ...(closeOnBackdropPress ? { onPress: handleClose } : {}),
30
- accessible: false,
31
- importantForAccessibility: 'no-hide-descendants' as const,
32
- ...dataAttributes({ slot: 'dialog-overlay' }),
33
- };
34
-
35
- const contentSlotAttrs = dataAttributes({
36
- slot: 'dialog-content',
37
- state: open ? 'open' : 'closed',
38
- });
39
-
40
- const ariaProps = {
41
- role,
42
- 'aria-modal': true,
43
- 'aria-labelledby': `${nativeID}-title`,
44
- 'aria-describedby': `${nativeID}-description`,
45
- };
46
-
47
- if (Platform.OS === 'web' && createPortalFn) {
48
- return createPortalFn(
49
- <FocusScope contain={open} restoreFocus autoFocus={open}>
50
- <View
51
- style={{
52
- position: 'fixed' as any,
53
- inset: 0 as any,
54
- zIndex: 50,
55
- display: 'flex' as any,
56
- alignItems: 'center',
57
- justifyContent: 'center',
58
- }}
59
- >
60
- <BaseOverlay {...(overlayProps as any)} />
61
- <BaseContent
62
- ref={ref}
63
- {...contentSlotAttrs}
64
- {...(props as ContentProps)}
65
- {...ariaProps}
66
- >
67
- {children}
68
- </BaseContent>
69
- </View>
70
- </FocusScope>,
71
- document.body,
72
- );
73
- }
74
-
75
- // Native layout uses two layers to support both backdrop dismiss and
76
- // scrollable body content. The overlay Pressable fills the Modal via
77
- // absolute positioning and handles backdrop taps. A second absolute-fill
78
- // View with pointerEvents="box-none" centers the content panel — "box-none"
79
- // lets taps outside the panel pass through to the overlay while allowing
80
- // the panel and its children to receive touches normally.
81
- //
82
- // Critically, the content panel must NOT claim the JS touch responder
83
- // (e.g. via onStartShouldSetResponder). Doing so triggers React Native's
84
- // blockNativeResponder, which suppresses the native UIScrollView /
85
- // ScrollView pan gesture recognizer and breaks any ScrollView inside
86
- // Dialog.Body.
87
- //
88
- // Static StyleSheet used here because these are structural layout concerns
89
- // of the primitive's modal chrome — not themeable styles. They must remain
90
- // stable regardless of the styled layer's className.
4
+ export const createDialogContent = <T,>(BaseContent: React.ComponentType<T>) =>
5
+ forwardRef<unknown, IDialogContentProps>(({ children, ...props }, ref) => {
91
6
  return (
92
- <Modal visible={open} transparent statusBarTranslucent onRequestClose={handleClose}>
93
- <FocusScope contain={open} restoreFocus autoFocus={open}>
94
- <View style={styles.fill}>
95
- <BaseOverlay {...(overlayProps as any)} />
96
- <View style={styles.center} pointerEvents="box-none">
97
- <BaseContent
98
- ref={ref}
99
- {...contentSlotAttrs}
100
- {...(props as ContentProps)}
101
- {...ariaProps}
102
- >
103
- {children}
104
- </BaseContent>
105
- </View>
106
- </View>
107
- </FocusScope>
108
- </Modal>
7
+ <BaseContent ref={ref} {...(props as T)}>
8
+ {children}
9
+ </BaseContent>
109
10
  );
110
11
  });
111
-
112
- // Structural layout for the native Modal chrome. These are not themeable —
113
- // they position the overlay and centering layers that the primitive manages
114
- // internally. Matches the pattern in OverlayContainer.tsx.
115
- const styles = StyleSheet.create({
116
- fill: { flex: 1 },
117
- center: {
118
- ...StyleSheet.absoluteFillObject,
119
- alignItems: 'center',
120
- justifyContent: 'center',
121
- },
122
- });
@@ -0,0 +1,146 @@
1
+ import type React from 'react';
2
+ import { forwardRef, useCallback } from 'react';
3
+ import { KeyboardAvoidingView, Modal, Platform, StyleSheet, View } from 'react-native';
4
+ import { FocusScope } from '@react-native-aria/focus';
5
+ import { useEscapeKey } from '../overlay';
6
+ import { createPortalFn } from '../utils/createPortal';
7
+ import { dataAttributes } from '../utils/dataAttributes';
8
+ import { useDialog } from './context';
9
+ import type { IDialogPopupProps } from './types';
10
+
11
+ export const createDialogPopup = <PopupProps, OverlayProps>(
12
+ BasePopup: React.ComponentType<PopupProps>,
13
+ BaseOverlay: React.ComponentType<OverlayProps>,
14
+ ) =>
15
+ forwardRef(
16
+ (
17
+ {
18
+ children,
19
+ forceMount = false,
20
+ avoidKeyboard = true,
21
+ keyboardVerticalOffset = 0,
22
+ ...props
23
+ }: IDialogPopupProps,
24
+ ref?: any,
25
+ ) => {
26
+ const { open, onOpenChange, closeOnBackdropPress, closeOnEscKey, nativeID, role } =
27
+ useDialog();
28
+
29
+ const handleClose = useCallback(() => {
30
+ onOpenChange(false);
31
+ }, [onOpenChange]);
32
+
33
+ useEscapeKey(open && closeOnEscKey, handleClose);
34
+
35
+ if (!(open || forceMount)) {
36
+ return null;
37
+ }
38
+
39
+ const overlayProps = {
40
+ ...(closeOnBackdropPress ? { onPress: handleClose } : {}),
41
+ accessible: false,
42
+ importantForAccessibility: 'no-hide-descendants' as const,
43
+ ...dataAttributes({ slot: 'dialog-overlay' }),
44
+ };
45
+
46
+ const contentSlotAttrs = dataAttributes({
47
+ slot: 'dialog-popup',
48
+ state: open ? 'open' : 'closed',
49
+ });
50
+
51
+ const ariaProps = {
52
+ role,
53
+ 'aria-modal': true,
54
+ 'aria-labelledby': `${nativeID}-title`,
55
+ 'aria-describedby': `${nativeID}-description`,
56
+ };
57
+
58
+ if (Platform.OS === 'web' && createPortalFn) {
59
+ return createPortalFn(
60
+ <FocusScope contain={open} restoreFocus autoFocus={open}>
61
+ <View
62
+ style={{
63
+ position: 'fixed' as any,
64
+ inset: 0 as any,
65
+ zIndex: 50,
66
+ display: 'flex' as any,
67
+ alignItems: 'center',
68
+ justifyContent: 'center',
69
+ }}
70
+ >
71
+ <BaseOverlay {...(overlayProps as any)} />
72
+ <BasePopup ref={ref} {...contentSlotAttrs} {...(props as PopupProps)} {...ariaProps}>
73
+ {children}
74
+ </BasePopup>
75
+ </View>
76
+ </FocusScope>,
77
+ document.body,
78
+ );
79
+ }
80
+
81
+ // Native layout uses two layers to support both backdrop dismiss and
82
+ // scrollable body content. The overlay Pressable fills the Modal via
83
+ // absolute positioning and handles backdrop taps. A second flex layer with
84
+ // pointerEvents="box-none" centers the content panel — "box-none" lets taps
85
+ // outside the panel pass through to the overlay while allowing the panel and
86
+ // its children to receive touches normally.
87
+ //
88
+ // That centering layer is a KeyboardAvoidingView so the panel (including its
89
+ // footer/actions, which sit at the bottom of a centered, max-h-capped panel)
90
+ // shifts up to clear the on-screen keyboard. `behavior` is platform-specific
91
+ // and the layer is a no-op while no input is focused. The RN Modal renders in
92
+ // its own window, so this MUST live here — a KeyboardAvoidingView wrapping the
93
+ // <Dialog> at the usage level cannot reach this subtree. Web is unaffected
94
+ // (the browser handles focus scrolling; there is no occluding keyboard).
95
+ //
96
+ // Critically, the content panel must NOT claim the JS touch responder
97
+ // (e.g. via onStartShouldSetResponder). Doing so triggers React Native's
98
+ // blockNativeResponder, which suppresses the native UIScrollView /
99
+ // ScrollView pan gesture recognizer and breaks any ScrollView inside
100
+ // Dialog.Content.
101
+ //
102
+ // Static StyleSheet used here because these are structural layout concerns
103
+ // of the primitive's modal chrome — not themeable styles. They must remain
104
+ // stable regardless of the styled layer's className.
105
+ const keyboardBehavior = avoidKeyboard
106
+ ? Platform.select<'padding' | 'height'>({ ios: 'padding', default: 'height' })
107
+ : undefined;
108
+
109
+ return (
110
+ <Modal visible={open} transparent statusBarTranslucent onRequestClose={handleClose}>
111
+ <FocusScope contain={open} restoreFocus autoFocus={open}>
112
+ <View style={styles.fill}>
113
+ <BaseOverlay {...(overlayProps as any)} />
114
+ <KeyboardAvoidingView
115
+ style={styles.center}
116
+ pointerEvents="box-none"
117
+ behavior={keyboardBehavior}
118
+ keyboardVerticalOffset={keyboardVerticalOffset}
119
+ >
120
+ <BasePopup
121
+ ref={ref}
122
+ {...contentSlotAttrs}
123
+ {...(props as PopupProps)}
124
+ {...ariaProps}
125
+ >
126
+ {children}
127
+ </BasePopup>
128
+ </KeyboardAvoidingView>
129
+ </View>
130
+ </FocusScope>
131
+ </Modal>
132
+ );
133
+ },
134
+ );
135
+
136
+ // Structural layout for the native Modal chrome. These are not themeable —
137
+ // they position the overlay and centering layers that the primitive manages
138
+ // internally. Matches the pattern in OverlayContainer.tsx.
139
+ const styles = StyleSheet.create({
140
+ fill: { flex: 1 },
141
+ center: {
142
+ flex: 1,
143
+ alignItems: 'center',
144
+ justifyContent: 'center',
145
+ },
146
+ });
@@ -1,11 +1,11 @@
1
1
  import type React from 'react';
2
2
  import { createDialogRoot } from './createDialogRoot';
3
3
  import { createDialogTrigger } from './createDialogTrigger';
4
- import { createDialogContent } from './createDialogContent';
4
+ import { createDialogPopup } from './createDialogPopup';
5
5
  import { createDialogHeader } from './createDialogHeader';
6
6
  import { createDialogTitle } from './createDialogTitle';
7
7
  import { createDialogDescription } from './createDialogDescription';
8
- import { createDialogBody } from './createDialogBody';
8
+ import { createDialogContent } from './createDialogContent';
9
9
  import { createDialogFooter } from './createDialogFooter';
10
10
  import { createDialogClose } from './createDialogClose';
11
11
  import { DialogProvider, useDialog } from './context';
@@ -16,12 +16,12 @@ export type {
16
16
  IDialogContextType,
17
17
  IDialogRootProps,
18
18
  IDialogTriggerProps,
19
- IDialogContentProps,
19
+ IDialogPopupProps,
20
20
  IDialogOverlayProps,
21
21
  IDialogHeaderProps,
22
22
  IDialogTitleProps,
23
23
  IDialogDescriptionProps,
24
- IDialogBodyProps,
24
+ IDialogContentProps,
25
25
  IDialogFooterProps,
26
26
  IDialogCloseProps,
27
27
  } from './types';
@@ -29,64 +29,64 @@ export type {
29
29
  export function createDialog<
30
30
  RootProps,
31
31
  TriggerProps,
32
- ContentProps,
32
+ PopupProps,
33
33
  OverlayProps,
34
34
  HeaderProps,
35
35
  TitleProps,
36
36
  DescriptionProps,
37
- BodyProps,
37
+ ContentProps,
38
38
  FooterProps,
39
39
  CloseProps,
40
40
  >(BaseComponents: {
41
41
  Root: React.ComponentType<RootProps>;
42
42
  Trigger: React.ComponentType<TriggerProps>;
43
- Content: React.ComponentType<ContentProps>;
43
+ Popup: React.ComponentType<PopupProps>;
44
44
  Overlay: React.ComponentType<OverlayProps>;
45
45
  Header: React.ComponentType<HeaderProps>;
46
46
  Title: React.ComponentType<TitleProps>;
47
47
  Description: React.ComponentType<DescriptionProps>;
48
- Body: React.ComponentType<BodyProps>;
48
+ Content: React.ComponentType<ContentProps>;
49
49
  Footer: React.ComponentType<FooterProps>;
50
50
  Close: React.ComponentType<CloseProps>;
51
51
  }) {
52
52
  const Root = createDialogRoot(BaseComponents.Root);
53
53
  const Trigger = createDialogTrigger(BaseComponents.Trigger);
54
- const Content = createDialogContent(BaseComponents.Content, BaseComponents.Overlay);
54
+ const Popup = createDialogPopup(BaseComponents.Popup, BaseComponents.Overlay);
55
55
  const Header = createDialogHeader(BaseComponents.Header);
56
56
  const Title = createDialogTitle(BaseComponents.Title);
57
57
  const Description = createDialogDescription(BaseComponents.Description);
58
- const Body = createDialogBody(BaseComponents.Body);
58
+ const Content = createDialogContent(BaseComponents.Content);
59
59
  const Footer = createDialogFooter(BaseComponents.Footer);
60
60
  const Close = createDialogClose(BaseComponents.Close);
61
61
 
62
62
  Root.displayName = 'DialogPrimitive.Root';
63
63
  Trigger.displayName = 'DialogPrimitive.Trigger';
64
- Content.displayName = 'DialogPrimitive.Content';
64
+ Popup.displayName = 'DialogPrimitive.Popup';
65
65
  Header.displayName = 'DialogPrimitive.Header';
66
66
  Title.displayName = 'DialogPrimitive.Title';
67
67
  Description.displayName = 'DialogPrimitive.Description';
68
- Body.displayName = 'DialogPrimitive.Body';
68
+ Content.displayName = 'DialogPrimitive.Content';
69
69
  Footer.displayName = 'DialogPrimitive.Footer';
70
70
  Close.displayName = 'DialogPrimitive.Close';
71
71
 
72
72
  return Object.assign(Root, {
73
73
  Root,
74
74
  Trigger,
75
- Content,
75
+ Popup,
76
76
  Header,
77
77
  Title,
78
78
  Description,
79
- Body,
79
+ Content,
80
80
  Footer,
81
81
  Close,
82
82
  }) as IDialogComponentType<
83
83
  RootProps,
84
84
  TriggerProps,
85
- ContentProps,
85
+ PopupProps,
86
86
  HeaderProps,
87
87
  TitleProps,
88
88
  DescriptionProps,
89
- BodyProps,
89
+ ContentProps,
90
90
  FooterProps,
91
91
  CloseProps
92
92
  >;