@primitiv-ui/react 0.1.0

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 (585) hide show
  1. package/README.md +79 -0
  2. package/package.json +59 -0
  3. package/src/AccessibleIcon/AccessibleIcon.tsx +40 -0
  4. package/src/AccessibleIcon/README.md +42 -0
  5. package/src/AccessibleIcon/__tests__/AccessibleIcon.test.tsx +47 -0
  6. package/src/AccessibleIcon/index.ts +2 -0
  7. package/src/AccessibleIcon/types.ts +8 -0
  8. package/src/Accordion/Accordion.tsx +412 -0
  9. package/src/Accordion/AccordionContext.ts +12 -0
  10. package/src/Accordion/README.md +202 -0
  11. package/src/Accordion/__tests__/Accordion.asChild.test.tsx +237 -0
  12. package/src/Accordion/__tests__/Accordion.basic-rendering.test.tsx +333 -0
  13. package/src/Accordion/__tests__/Accordion.controlled-state.test.tsx +175 -0
  14. package/src/Accordion/__tests__/Accordion.data-attributes.test.tsx +272 -0
  15. package/src/Accordion/__tests__/Accordion.disabled-items.test.tsx +311 -0
  16. package/src/Accordion/__tests__/Accordion.error-handling.test.tsx +119 -0
  17. package/src/Accordion/__tests__/Accordion.forceMount.test.tsx +119 -0
  18. package/src/Accordion/__tests__/Accordion.keyboard-interaction.test.tsx +736 -0
  19. package/src/Accordion/__tests__/Accordion.mouse-interaction.test.tsx +212 -0
  20. package/src/Accordion/__tests__/Accordion.multiple-mode.test.tsx +90 -0
  21. package/src/Accordion/__tests__/Accordion.reading-direction.test.tsx +139 -0
  22. package/src/Accordion/__tests__/Accordion.uncontrolled-state.test.tsx +154 -0
  23. package/src/Accordion/hooks/index.ts +6 -0
  24. package/src/Accordion/hooks/useAccordionContext.ts +1 -0
  25. package/src/Accordion/hooks/useAccordionHeaderContext.ts +10 -0
  26. package/src/Accordion/hooks/useAccordionItem.ts +22 -0
  27. package/src/Accordion/hooks/useAccordionItemContext.ts +1 -0
  28. package/src/Accordion/hooks/useAccordionRoot.ts +151 -0
  29. package/src/Accordion/hooks/useAccordionTrigger.ts +90 -0
  30. package/src/Accordion/index.ts +1 -0
  31. package/src/Accordion/types.ts +81 -0
  32. package/src/Alert/Alert.tsx +43 -0
  33. package/src/Alert/README.md +54 -0
  34. package/src/Alert/__tests__/Alert.test.tsx +28 -0
  35. package/src/Alert/index.ts +2 -0
  36. package/src/Alert/types.ts +5 -0
  37. package/src/Avatar/Avatar.tsx +149 -0
  38. package/src/Avatar/AvatarContext.ts +20 -0
  39. package/src/Avatar/README.md +116 -0
  40. package/src/Avatar/__tests__/Avatar.asChild.test.tsx +53 -0
  41. package/src/Avatar/__tests__/Avatar.basic-rendering.test.tsx +14 -0
  42. package/src/Avatar/__tests__/Avatar.error-handling.test.tsx +30 -0
  43. package/src/Avatar/__tests__/Avatar.fallback.test.tsx +75 -0
  44. package/src/Avatar/__tests__/Avatar.image-loading.test.tsx +81 -0
  45. package/src/Avatar/hooks/index.ts +2 -0
  46. package/src/Avatar/hooks/useAvatarContext.ts +1 -0
  47. package/src/Avatar/hooks/useAvatarImage.ts +40 -0
  48. package/src/Avatar/index.ts +3 -0
  49. package/src/Avatar/types.ts +44 -0
  50. package/src/Breadcrumb/Breadcrumb.tsx +234 -0
  51. package/src/Breadcrumb/README.md +111 -0
  52. package/src/Breadcrumb/__tests__/Breadcrumb.asChild.test.tsx +33 -0
  53. package/src/Breadcrumb/__tests__/Breadcrumb.basic-rendering.test.tsx +132 -0
  54. package/src/Breadcrumb/index.ts +2 -0
  55. package/src/Breadcrumb/types.ts +22 -0
  56. package/src/Button/Button.tsx +95 -0
  57. package/src/Button/README.md +112 -0
  58. package/src/Button/__tests__/Button.asChild.test.tsx +91 -0
  59. package/src/Button/__tests__/Button.basic-rendering.test.tsx +126 -0
  60. package/src/Button/__tests__/Button.contract.test.tsx +72 -0
  61. package/src/Button/__tests__/Button.disabled.test.tsx +52 -0
  62. package/src/Button/__tests__/Button.icon-usage.test.tsx +57 -0
  63. package/src/Button/__tests__/Button.keyboard-interaction.test.tsx +70 -0
  64. package/src/Button/index.ts +2 -0
  65. package/src/Button/types.ts +8 -0
  66. package/src/Carousel/Carousel.tsx +708 -0
  67. package/src/Carousel/CarouselContext.ts +11 -0
  68. package/src/Carousel/README.md +848 -0
  69. package/src/Carousel/__tests__/Carousel.asChild.test.tsx +178 -0
  70. package/src/Carousel/__tests__/Carousel.auto-play.test.tsx +617 -0
  71. package/src/Carousel/__tests__/Carousel.basic-rendering.test.tsx +569 -0
  72. package/src/Carousel/__tests__/Carousel.controlled-state.test.tsx +137 -0
  73. package/src/Carousel/__tests__/Carousel.error-handling.test.tsx +81 -0
  74. package/src/Carousel/__tests__/Carousel.ids.test.tsx +111 -0
  75. package/src/Carousel/__tests__/Carousel.imperative-api.test.tsx +213 -0
  76. package/src/Carousel/__tests__/Carousel.indicators.test.tsx +560 -0
  77. package/src/Carousel/__tests__/Carousel.intersection-observer.test.tsx +276 -0
  78. package/src/Carousel/__tests__/Carousel.keyboard-navigation.test.tsx +158 -0
  79. package/src/Carousel/__tests__/Carousel.play-pause.test.tsx +232 -0
  80. package/src/Carousel/__tests__/Carousel.prev-next.test.tsx +68 -0
  81. package/src/Carousel/__tests__/Carousel.reduced-motion.test.tsx +49 -0
  82. package/src/Carousel/__tests__/Carousel.refresh-progress.test.tsx +87 -0
  83. package/src/Carousel/__tests__/Carousel.scroll-snap-change.test.tsx +179 -0
  84. package/src/Carousel/__tests__/Carousel.scroll-sync.test.tsx +109 -0
  85. package/src/Carousel/__tests__/Carousel.slides-per-move.test.tsx +151 -0
  86. package/src/Carousel/__tests__/Carousel.slides-per-page.test.tsx +183 -0
  87. package/src/Carousel/__tests__/Carousel.touch-interaction.test.tsx +96 -0
  88. package/src/Carousel/__tests__/Carousel.transition-modes.test.tsx +70 -0
  89. package/src/Carousel/__tests__/Carousel.translations.test.tsx +157 -0
  90. package/src/Carousel/__tests__/Carousel.uncontrolled-state.test.tsx +146 -0
  91. package/src/Carousel/hooks/index.ts +4 -0
  92. package/src/Carousel/hooks/useCarouselContext.ts +13 -0
  93. package/src/Carousel/hooks/useCarouselRoot.ts +450 -0
  94. package/src/Carousel/hooks/useCarouselSlide.ts +45 -0
  95. package/src/Carousel/hooks/useCarouselViewport.ts +290 -0
  96. package/src/Carousel/index.ts +3 -0
  97. package/src/Carousel/types.ts +400 -0
  98. package/src/Checkbox/Checkbox.tsx +228 -0
  99. package/src/Checkbox/CheckboxContext.ts +12 -0
  100. package/src/Checkbox/README.md +156 -0
  101. package/src/Checkbox/__tests__/Checkbox.asChild.test.tsx +69 -0
  102. package/src/Checkbox/__tests__/Checkbox.basic-rendering.test.tsx +41 -0
  103. package/src/Checkbox/__tests__/Checkbox.controlled-state.test.tsx +82 -0
  104. package/src/Checkbox/__tests__/Checkbox.disabled.test.tsx +15 -0
  105. package/src/Checkbox/__tests__/Checkbox.indeterminate.test.tsx +82 -0
  106. package/src/Checkbox/__tests__/Checkbox.indicator.test.tsx +117 -0
  107. package/src/Checkbox/__tests__/Checkbox.uncontrolled-state.test.tsx +89 -0
  108. package/src/Checkbox/hooks/index.ts +2 -0
  109. package/src/Checkbox/hooks/useCheckboxContext.ts +1 -0
  110. package/src/Checkbox/hooks/useCheckboxRoot.ts +32 -0
  111. package/src/Checkbox/index.ts +1 -0
  112. package/src/Checkbox/types.ts +33 -0
  113. package/src/CheckboxCard/CheckboxCard.tsx +208 -0
  114. package/src/CheckboxCard/CheckboxCardContext.ts +12 -0
  115. package/src/CheckboxCard/README.md +114 -0
  116. package/src/CheckboxCard/__tests__/CheckboxCard.asChild.test.tsx +54 -0
  117. package/src/CheckboxCard/__tests__/CheckboxCard.basic-rendering.test.tsx +58 -0
  118. package/src/CheckboxCard/__tests__/CheckboxCard.controlled-state.test.tsx +77 -0
  119. package/src/CheckboxCard/__tests__/CheckboxCard.disabled.test.tsx +55 -0
  120. package/src/CheckboxCard/__tests__/CheckboxCard.error-handling.test.tsx +20 -0
  121. package/src/CheckboxCard/__tests__/CheckboxCard.indeterminate.test.tsx +60 -0
  122. package/src/CheckboxCard/__tests__/CheckboxCard.indicator.test.tsx +136 -0
  123. package/src/CheckboxCard/__tests__/CheckboxCard.uncontrolled-state.test.tsx +73 -0
  124. package/src/CheckboxCard/hooks/index.ts +2 -0
  125. package/src/CheckboxCard/hooks/useCheckboxCardContext.ts +1 -0
  126. package/src/CheckboxCard/hooks/useCheckboxCardRoot.ts +30 -0
  127. package/src/CheckboxCard/index.ts +3 -0
  128. package/src/CheckboxCard/types.ts +33 -0
  129. package/src/Collapsible/Collapsible.tsx +316 -0
  130. package/src/Collapsible/CollapsibleContext.ts +7 -0
  131. package/src/Collapsible/README.md +174 -0
  132. package/src/Collapsible/__tests__/Collapsible.asChild.test.tsx +240 -0
  133. package/src/Collapsible/__tests__/Collapsible.basic-rendering.test.tsx +118 -0
  134. package/src/Collapsible/__tests__/Collapsible.controlled-state.test.tsx +134 -0
  135. package/src/Collapsible/__tests__/Collapsible.disabled.test.tsx +132 -0
  136. package/src/Collapsible/__tests__/Collapsible.error-handling.test.tsx +40 -0
  137. package/src/Collapsible/__tests__/Collapsible.forceMount.test.tsx +111 -0
  138. package/src/Collapsible/__tests__/Collapsible.triggerIcon.test.tsx +93 -0
  139. package/src/Collapsible/__tests__/Collapsible.uncontrolled-state.test.tsx +125 -0
  140. package/src/Collapsible/hooks/index.ts +2 -0
  141. package/src/Collapsible/hooks/useCollapsibleRoot.ts +34 -0
  142. package/src/Collapsible/hooks/useCollapsibleTrigger.ts +49 -0
  143. package/src/Collapsible/index.ts +1 -0
  144. package/src/Collapsible/types.ts +48 -0
  145. package/src/ContextMenu/ContextMenu.tsx +1004 -0
  146. package/src/ContextMenu/ContextMenuContentContext.ts +15 -0
  147. package/src/ContextMenu/ContextMenuContext.ts +21 -0
  148. package/src/ContextMenu/ContextMenuGroupContext.ts +8 -0
  149. package/src/ContextMenu/ContextMenuItemIndicatorContext.ts +8 -0
  150. package/src/ContextMenu/ContextMenuRadioGroupContext.ts +9 -0
  151. package/src/ContextMenu/ContextMenuSubContext.ts +15 -0
  152. package/src/ContextMenu/README.md +275 -0
  153. package/src/ContextMenu/__tests__/ContextMenu.asChild.test.tsx +186 -0
  154. package/src/ContextMenu/__tests__/ContextMenu.basic-rendering.test.tsx +39 -0
  155. package/src/ContextMenu/__tests__/ContextMenu.checkbox-item.test.tsx +145 -0
  156. package/src/ContextMenu/__tests__/ContextMenu.error-handling.test.tsx +113 -0
  157. package/src/ContextMenu/__tests__/ContextMenu.group-label.test.tsx +48 -0
  158. package/src/ContextMenu/__tests__/ContextMenu.item-indicator.test.tsx +88 -0
  159. package/src/ContextMenu/__tests__/ContextMenu.item.test.tsx +106 -0
  160. package/src/ContextMenu/__tests__/ContextMenu.keyboard-interaction.test.tsx +172 -0
  161. package/src/ContextMenu/__tests__/ContextMenu.mouse-interaction.test.tsx +227 -0
  162. package/src/ContextMenu/__tests__/ContextMenu.radio-item.test.tsx +127 -0
  163. package/src/ContextMenu/__tests__/ContextMenu.reading-direction.test.tsx +152 -0
  164. package/src/ContextMenu/__tests__/ContextMenu.separator.test.tsx +47 -0
  165. package/src/ContextMenu/__tests__/ContextMenu.state-modes.test.tsx +119 -0
  166. package/src/ContextMenu/__tests__/ContextMenu.sub.test.tsx +262 -0
  167. package/src/ContextMenu/__tests__/ContextMenu.typeahead.test.tsx +89 -0
  168. package/src/ContextMenu/constants.ts +4 -0
  169. package/src/ContextMenu/index.ts +1 -0
  170. package/src/ContextMenu/types.ts +199 -0
  171. package/src/DirectionProvider/DirectionContext.ts +21 -0
  172. package/src/DirectionProvider/DirectionProvider.tsx +31 -0
  173. package/src/DirectionProvider/README.md +62 -0
  174. package/src/DirectionProvider/__tests__/DirectionProvider.test.tsx +29 -0
  175. package/src/DirectionProvider/index.ts +3 -0
  176. package/src/DirectionProvider/types.ts +10 -0
  177. package/src/Divider/Divider.tsx +57 -0
  178. package/src/Divider/README.md +57 -0
  179. package/src/Divider/__tests__/Divider.test.tsx +41 -0
  180. package/src/Divider/index.ts +1 -0
  181. package/src/Divider/types.ts +5 -0
  182. package/src/Dropdown/Dropdown.tsx +842 -0
  183. package/src/Dropdown/DropdownContentContext.ts +15 -0
  184. package/src/Dropdown/DropdownContext.ts +17 -0
  185. package/src/Dropdown/DropdownGroupContext.ts +8 -0
  186. package/src/Dropdown/DropdownItemIndicatorContext.ts +13 -0
  187. package/src/Dropdown/DropdownRadioGroupContext.ts +9 -0
  188. package/src/Dropdown/DropdownSubContext.ts +15 -0
  189. package/src/Dropdown/README.md +284 -0
  190. package/src/Dropdown/__tests__/Dropdown.asChild.test.tsx +286 -0
  191. package/src/Dropdown/__tests__/Dropdown.basic-rendering.test.tsx +43 -0
  192. package/src/Dropdown/__tests__/Dropdown.checkbox-item.test.tsx +121 -0
  193. package/src/Dropdown/__tests__/Dropdown.disabled.test.tsx +143 -0
  194. package/src/Dropdown/__tests__/Dropdown.error-handling.test.tsx +85 -0
  195. package/src/Dropdown/__tests__/Dropdown.group-label.test.tsx +68 -0
  196. package/src/Dropdown/__tests__/Dropdown.item-indicator.test.tsx +260 -0
  197. package/src/Dropdown/__tests__/Dropdown.item.test.tsx +72 -0
  198. package/src/Dropdown/__tests__/Dropdown.keyboard-edge-cases.test.tsx +77 -0
  199. package/src/Dropdown/__tests__/Dropdown.keyboard-interaction.test.tsx +310 -0
  200. package/src/Dropdown/__tests__/Dropdown.mouse-interaction.test.tsx +347 -0
  201. package/src/Dropdown/__tests__/Dropdown.radio-item.test.tsx +134 -0
  202. package/src/Dropdown/__tests__/Dropdown.reading-direction.test.tsx +153 -0
  203. package/src/Dropdown/__tests__/Dropdown.separator.test.tsx +46 -0
  204. package/src/Dropdown/__tests__/Dropdown.state-modes.test.tsx +100 -0
  205. package/src/Dropdown/__tests__/Dropdown.sub.test.tsx +185 -0
  206. package/src/Dropdown/__tests__/Dropdown.trigger.test.tsx +110 -0
  207. package/src/Dropdown/__tests__/Dropdown.typeahead.test.tsx +133 -0
  208. package/src/Dropdown/constants.ts +4 -0
  209. package/src/Dropdown/hooks/index.ts +9 -0
  210. package/src/Dropdown/hooks/useCloseSiblingSub.ts +13 -0
  211. package/src/Dropdown/hooks/useDropdownContent.ts +162 -0
  212. package/src/Dropdown/hooks/useDropdownContext.ts +1 -0
  213. package/src/Dropdown/hooks/useDropdownGroup.ts +18 -0
  214. package/src/Dropdown/hooks/useDropdownItem.ts +49 -0
  215. package/src/Dropdown/hooks/useDropdownLabel.ts +15 -0
  216. package/src/Dropdown/hooks/useDropdownRoot.ts +57 -0
  217. package/src/Dropdown/hooks/useDropdownSubContext.ts +1 -0
  218. package/src/Dropdown/hooks/useDropdownTrigger.ts +31 -0
  219. package/src/Dropdown/index.ts +1 -0
  220. package/src/Dropdown/types.ts +200 -0
  221. package/src/EmptyState/EmptyState.tsx +245 -0
  222. package/src/EmptyState/README.md +129 -0
  223. package/src/EmptyState/__tests__/EmptyState.Actions.test.tsx +32 -0
  224. package/src/EmptyState/__tests__/EmptyState.Description.test.tsx +30 -0
  225. package/src/EmptyState/__tests__/EmptyState.Media.test.tsx +34 -0
  226. package/src/EmptyState/__tests__/EmptyState.Root.test.tsx +28 -0
  227. package/src/EmptyState/__tests__/EmptyState.Title.test.tsx +26 -0
  228. package/src/EmptyState/index.ts +2 -0
  229. package/src/EmptyState/types.ts +21 -0
  230. package/src/Field/Field.tsx +239 -0
  231. package/src/Field/FieldContext.ts +22 -0
  232. package/src/Field/README.md +167 -0
  233. package/src/Field/__tests__/Field.asChild.test.tsx +83 -0
  234. package/src/Field/__tests__/Field.basic-rendering.test.tsx +104 -0
  235. package/src/Field/__tests__/Field.state-cascade.test.tsx +75 -0
  236. package/src/Field/hooks/index.ts +2 -0
  237. package/src/Field/hooks/useFieldContext.ts +1 -0
  238. package/src/Field/hooks/useFieldProps.ts +57 -0
  239. package/src/Field/index.ts +2 -0
  240. package/src/Field/types.ts +33 -0
  241. package/src/Fieldset/Fieldset.tsx +104 -0
  242. package/src/Fieldset/README.md +74 -0
  243. package/src/Fieldset/__tests__/Fieldset.basic-rendering.test.tsx +81 -0
  244. package/src/Fieldset/__tests__/Fieldset.disabled.test.tsx +41 -0
  245. package/src/Fieldset/index.ts +2 -0
  246. package/src/Fieldset/types.ts +5 -0
  247. package/src/Input/Input.tsx +120 -0
  248. package/src/Input/README.md +180 -0
  249. package/src/Input/__tests__/Input.asChild.test.tsx +85 -0
  250. package/src/Input/__tests__/Input.basic-rendering.test.tsx +118 -0
  251. package/src/Input/__tests__/Input.disabled.test.tsx +49 -0
  252. package/src/Input/__tests__/Input.field-integration.test.tsx +148 -0
  253. package/src/Input/index.ts +2 -0
  254. package/src/Input/types.ts +7 -0
  255. package/src/InputGroup/InputGroup.tsx +228 -0
  256. package/src/InputGroup/README.md +178 -0
  257. package/src/InputGroup/__tests__/InputGroup.asChild.test.tsx +109 -0
  258. package/src/InputGroup/__tests__/InputGroup.basic-rendering.test.tsx +106 -0
  259. package/src/InputGroup/index.ts +2 -0
  260. package/src/InputGroup/types.ts +13 -0
  261. package/src/MillerColumns/MillerColumns.tsx +329 -0
  262. package/src/MillerColumns/MillerColumnsContext.ts +25 -0
  263. package/src/MillerColumns/README.md +278 -0
  264. package/src/MillerColumns/__tests__/MillerColumns.aria.test.tsx +82 -0
  265. package/src/MillerColumns/__tests__/MillerColumns.asChild.test.tsx +106 -0
  266. package/src/MillerColumns/__tests__/MillerColumns.auto-scroll.test.tsx +68 -0
  267. package/src/MillerColumns/__tests__/MillerColumns.basic-rendering.test.tsx +52 -0
  268. package/src/MillerColumns/__tests__/MillerColumns.column-projection.test.tsx +161 -0
  269. package/src/MillerColumns/__tests__/MillerColumns.controlled-state.test.tsx +90 -0
  270. package/src/MillerColumns/__tests__/MillerColumns.data-attributes.test.tsx +77 -0
  271. package/src/MillerColumns/__tests__/MillerColumns.disabled-items.test.tsx +65 -0
  272. package/src/MillerColumns/__tests__/MillerColumns.error-handling.test.tsx +57 -0
  273. package/src/MillerColumns/__tests__/MillerColumns.fixtures.ts +15 -0
  274. package/src/MillerColumns/__tests__/MillerColumns.item-indicator.test.tsx +57 -0
  275. package/src/MillerColumns/__tests__/MillerColumns.keyboard-interaction.test.tsx +181 -0
  276. package/src/MillerColumns/__tests__/MillerColumns.preview-panel.test.tsx +47 -0
  277. package/src/MillerColumns/__tests__/MillerColumns.resize.test.tsx +137 -0
  278. package/src/MillerColumns/__tests__/MillerColumns.roving-tabindex.test.tsx +91 -0
  279. package/src/MillerColumns/__tests__/MillerColumns.selection.test.tsx +54 -0
  280. package/src/MillerColumns/__tests__/MillerColumns.uncontrolled-state.test.tsx +70 -0
  281. package/src/MillerColumns/hooks/index.ts +7 -0
  282. package/src/MillerColumns/hooks/useMillerColumnsColumn.ts +23 -0
  283. package/src/MillerColumns/hooks/useMillerColumnsColumnContext.ts +1 -0
  284. package/src/MillerColumns/hooks/useMillerColumnsContext.ts +1 -0
  285. package/src/MillerColumns/hooks/useMillerColumnsItem.ts +157 -0
  286. package/src/MillerColumns/hooks/useMillerColumnsItemContext.ts +1 -0
  287. package/src/MillerColumns/hooks/useMillerColumnsResizeHandle.ts +76 -0
  288. package/src/MillerColumns/hooks/useMillerColumnsRoot.ts +0 -0
  289. package/src/MillerColumns/index.ts +3 -0
  290. package/src/MillerColumns/types.ts +93 -0
  291. package/src/MillerColumns/useMillerColumnsSelection.ts +31 -0
  292. package/src/MillerColumns/utils.ts +75 -0
  293. package/src/Modal/Modal.tsx +474 -0
  294. package/src/Modal/ModalContext.ts +13 -0
  295. package/src/Modal/README.md +207 -0
  296. package/src/Modal/__tests__/Modal.accessibility.test.tsx +167 -0
  297. package/src/Modal/__tests__/Modal.asChild.test.tsx +162 -0
  298. package/src/Modal/__tests__/Modal.click-outside.test.tsx +115 -0
  299. package/src/Modal/__tests__/Modal.content.test.tsx +193 -0
  300. package/src/Modal/__tests__/Modal.controlled-state.test.tsx +120 -0
  301. package/src/Modal/__tests__/Modal.error-handling.test.tsx +30 -0
  302. package/src/Modal/__tests__/Modal.escape-hatches.test.tsx +99 -0
  303. package/src/Modal/__tests__/Modal.imperative-api.test.tsx +119 -0
  304. package/src/Modal/__tests__/Modal.nested.test.tsx +106 -0
  305. package/src/Modal/__tests__/Modal.overlay.test.tsx +99 -0
  306. package/src/Modal/__tests__/Modal.portal.test.tsx +90 -0
  307. package/src/Modal/__tests__/Modal.presence.test.tsx +111 -0
  308. package/src/Modal/__tests__/Modal.trigger.test.tsx +70 -0
  309. package/src/Modal/__tests__/Modal.uncontrolled-state.test.tsx +72 -0
  310. package/src/Modal/__tests__/dialog-polyfill.ts +40 -0
  311. package/src/Modal/hooks/index.ts +4 -0
  312. package/src/Modal/hooks/useModalContent.ts +62 -0
  313. package/src/Modal/hooks/useModalContext.ts +1 -0
  314. package/src/Modal/hooks/useModalRoot.ts +81 -0
  315. package/src/Modal/hooks/useModalTrigger.ts +25 -0
  316. package/src/Modal/index.ts +3 -0
  317. package/src/Modal/types.ts +76 -0
  318. package/src/Portal/Portal.tsx +28 -0
  319. package/src/Portal/README.md +70 -0
  320. package/src/Portal/__tests__/Portal.basic-rendering.test.tsx +17 -0
  321. package/src/Portal/index.ts +2 -0
  322. package/src/Portal/types.ts +6 -0
  323. package/src/Progress/Progress.tsx +178 -0
  324. package/src/Progress/ProgressContext.ts +15 -0
  325. package/src/Progress/README.md +112 -0
  326. package/src/Progress/__tests__/Progress.asChild.test.tsx +37 -0
  327. package/src/Progress/__tests__/Progress.basic-rendering.test.tsx +65 -0
  328. package/src/Progress/__tests__/Progress.error-handling.test.tsx +40 -0
  329. package/src/Progress/__tests__/Progress.fixtures.ts +7 -0
  330. package/src/Progress/__tests__/Progress.value.test.tsx +83 -0
  331. package/src/Progress/hooks/index.ts +2 -0
  332. package/src/Progress/hooks/useProgressContext.ts +1 -0
  333. package/src/Progress/hooks/useProgressRoot.ts +45 -0
  334. package/src/Progress/index.ts +3 -0
  335. package/src/Progress/types.ts +43 -0
  336. package/src/RadioCard/README.md +133 -0
  337. package/src/RadioCard/RadioCard.tsx +334 -0
  338. package/src/RadioCard/RadioCardContext.ts +23 -0
  339. package/src/RadioCard/RadioCardItemContext.ts +10 -0
  340. package/src/RadioCard/__tests__/RadioCard.asChild.test.tsx +76 -0
  341. package/src/RadioCard/__tests__/RadioCard.basic-rendering.test.tsx +87 -0
  342. package/src/RadioCard/__tests__/RadioCard.controlled-state.test.tsx +107 -0
  343. package/src/RadioCard/__tests__/RadioCard.disabled-items.test.tsx +61 -0
  344. package/src/RadioCard/__tests__/RadioCard.error-handling.test.tsx +35 -0
  345. package/src/RadioCard/__tests__/RadioCard.indicator.test.tsx +119 -0
  346. package/src/RadioCard/__tests__/RadioCard.keyboard-interaction.test.tsx +158 -0
  347. package/src/RadioCard/__tests__/RadioCard.orientation.test.tsx +90 -0
  348. package/src/RadioCard/__tests__/RadioCard.reading-direction.test.tsx +65 -0
  349. package/src/RadioCard/__tests__/RadioCard.uncontrolled-state.test.tsx +108 -0
  350. package/src/RadioCard/hooks/index.ts +3 -0
  351. package/src/RadioCard/hooks/useRadioCardContext.ts +1 -0
  352. package/src/RadioCard/hooks/useRadioCardItemContext.ts +1 -0
  353. package/src/RadioCard/hooks/useRadioCardRoot.ts +77 -0
  354. package/src/RadioCard/index.ts +4 -0
  355. package/src/RadioCard/types.ts +51 -0
  356. package/src/RadioGroup/README.md +185 -0
  357. package/src/RadioGroup/RadioGroup.tsx +353 -0
  358. package/src/RadioGroup/RadioGroupContext.ts +23 -0
  359. package/src/RadioGroup/RadioGroupItemContext.ts +10 -0
  360. package/src/RadioGroup/__tests__/RadioGroup.asChild.test.tsx +105 -0
  361. package/src/RadioGroup/__tests__/RadioGroup.basic-rendering.test.tsx +72 -0
  362. package/src/RadioGroup/__tests__/RadioGroup.controlled-state.test.tsx +109 -0
  363. package/src/RadioGroup/__tests__/RadioGroup.disabled-keydown-guards.test.tsx +68 -0
  364. package/src/RadioGroup/__tests__/RadioGroup.disabled.test.tsx +79 -0
  365. package/src/RadioGroup/__tests__/RadioGroup.error-handling.test.tsx +33 -0
  366. package/src/RadioGroup/__tests__/RadioGroup.indicator.test.tsx +85 -0
  367. package/src/RadioGroup/__tests__/RadioGroup.keyboard-interaction.test.tsx +135 -0
  368. package/src/RadioGroup/__tests__/RadioGroup.orientation.test.tsx +90 -0
  369. package/src/RadioGroup/__tests__/RadioGroup.reading-direction.test.tsx +65 -0
  370. package/src/RadioGroup/__tests__/RadioGroup.ref-forwarding.test.tsx +45 -0
  371. package/src/RadioGroup/__tests__/RadioGroup.roving-tabindex.test.tsx +105 -0
  372. package/src/RadioGroup/__tests__/RadioGroup.uncontrolled-state.test.tsx +96 -0
  373. package/src/RadioGroup/hooks/index.ts +3 -0
  374. package/src/RadioGroup/hooks/useRadioGroupContext.ts +1 -0
  375. package/src/RadioGroup/hooks/useRadioGroupItemContext.ts +1 -0
  376. package/src/RadioGroup/hooks/useRadioGroupRoot.ts +87 -0
  377. package/src/RadioGroup/index.ts +1 -0
  378. package/src/RadioGroup/types.ts +51 -0
  379. package/src/Select/README.md +203 -0
  380. package/src/Select/Select.tsx +204 -0
  381. package/src/Select/__tests__/Select.asChild.test.tsx +36 -0
  382. package/src/Select/__tests__/Select.basic-rendering.test.tsx +17 -0
  383. package/src/Select/__tests__/Select.controlled-state.test.tsx +69 -0
  384. package/src/Select/__tests__/Select.data-attributes.test.tsx +29 -0
  385. package/src/Select/__tests__/Select.field-integration.test.tsx +150 -0
  386. package/src/Select/__tests__/Select.group.test.tsx +42 -0
  387. package/src/Select/__tests__/Select.placeholder.test.tsx +32 -0
  388. package/src/Select/index.ts +2 -0
  389. package/src/Select/types.ts +89 -0
  390. package/src/SkipNav/README.md +87 -0
  391. package/src/SkipNav/SkipNav.tsx +116 -0
  392. package/src/SkipNav/__tests__/SkipNav.basic-rendering.test.tsx +23 -0
  393. package/src/SkipNav/__tests__/SkipNav.ids.test.tsx +19 -0
  394. package/src/SkipNav/index.ts +1 -0
  395. package/src/SkipNav/types.ts +26 -0
  396. package/src/Slider/README.md +215 -0
  397. package/src/Slider/Slider.tsx +308 -0
  398. package/src/Slider/SliderContext.ts +24 -0
  399. package/src/Slider/__tests__/Slider.asChild.test.tsx +119 -0
  400. package/src/Slider/__tests__/Slider.basic-rendering.test.tsx +157 -0
  401. package/src/Slider/__tests__/Slider.controlled-state.test.tsx +78 -0
  402. package/src/Slider/__tests__/Slider.disabled.test.tsx +82 -0
  403. package/src/Slider/__tests__/Slider.error-handling.test.tsx +45 -0
  404. package/src/Slider/__tests__/Slider.fixtures.ts +53 -0
  405. package/src/Slider/__tests__/Slider.form.test.tsx +67 -0
  406. package/src/Slider/__tests__/Slider.inverted.test.tsx +112 -0
  407. package/src/Slider/__tests__/Slider.keyboard-interaction.test.tsx +118 -0
  408. package/src/Slider/__tests__/Slider.multiple-thumbs.test.tsx +84 -0
  409. package/src/Slider/__tests__/Slider.orientation.test.tsx +101 -0
  410. package/src/Slider/__tests__/Slider.pointer-interaction.test.tsx +205 -0
  411. package/src/Slider/__tests__/Slider.reading-direction.test.tsx +99 -0
  412. package/src/Slider/__tests__/Slider.uncontrolled-state.test.tsx +69 -0
  413. package/src/Slider/__tests__/Slider.value-commit.test.tsx +103 -0
  414. package/src/Slider/hooks/index.ts +3 -0
  415. package/src/Slider/hooks/useSliderContext.ts +1 -0
  416. package/src/Slider/hooks/useSliderRoot.ts +197 -0
  417. package/src/Slider/hooks/useSliderThumb.ts +77 -0
  418. package/src/Slider/index.ts +3 -0
  419. package/src/Slider/types.ts +48 -0
  420. package/src/Slider/utils.ts +155 -0
  421. package/src/Slot/Slot.tsx +158 -0
  422. package/src/Slot/__tests__/Slot.test.tsx +163 -0
  423. package/src/Slot/__tests__/composeEventHandlers.test.ts +74 -0
  424. package/src/Slot/composeEventHandlers.ts +38 -0
  425. package/src/Slot/index.ts +3 -0
  426. package/src/Slot/types.ts +5 -0
  427. package/src/Status/README.md +50 -0
  428. package/src/Status/Status.tsx +44 -0
  429. package/src/Status/__tests__/Status.test.tsx +28 -0
  430. package/src/Status/index.ts +2 -0
  431. package/src/Status/types.ts +5 -0
  432. package/src/Switch/README.md +121 -0
  433. package/src/Switch/Switch.tsx +167 -0
  434. package/src/Switch/SwitchContext.ts +10 -0
  435. package/src/Switch/__tests__/Switch.asChild.test.tsx +56 -0
  436. package/src/Switch/__tests__/Switch.basic-rendering.test.tsx +76 -0
  437. package/src/Switch/__tests__/Switch.contract.test.tsx +109 -0
  438. package/src/Switch/__tests__/Switch.controlled-state.test.tsx +79 -0
  439. package/src/Switch/__tests__/Switch.disabled.test.tsx +60 -0
  440. package/src/Switch/__tests__/Switch.error-handling.test.tsx +20 -0
  441. package/src/Switch/__tests__/Switch.keyboard-interaction.test.tsx +56 -0
  442. package/src/Switch/__tests__/Switch.thumb.test.tsx +84 -0
  443. package/src/Switch/__tests__/Switch.uncontrolled-state.test.tsx +83 -0
  444. package/src/Switch/hooks/index.ts +2 -0
  445. package/src/Switch/hooks/useSwitchContext.ts +1 -0
  446. package/src/Switch/hooks/useSwitchRoot.ts +28 -0
  447. package/src/Switch/index.ts +3 -0
  448. package/src/Switch/types.ts +37 -0
  449. package/src/Table/README.md +205 -0
  450. package/src/Table/Table.tsx +380 -0
  451. package/src/Table/__tests__/Table.Body.test.tsx +61 -0
  452. package/src/Table/__tests__/Table.Caption.test.tsx +70 -0
  453. package/src/Table/__tests__/Table.Cell.test.tsx +73 -0
  454. package/src/Table/__tests__/Table.Footer.test.tsx +61 -0
  455. package/src/Table/__tests__/Table.Head.test.tsx +61 -0
  456. package/src/Table/__tests__/Table.Header.test.tsx +73 -0
  457. package/src/Table/__tests__/Table.Root.test.tsx +49 -0
  458. package/src/Table/__tests__/Table.Row.test.tsx +67 -0
  459. package/src/Table/__tests__/Table.ScrollArea.test.tsx +83 -0
  460. package/src/Table/index.ts +1 -0
  461. package/src/Table/types.ts +63 -0
  462. package/src/Tabs/README.md +110 -0
  463. package/src/Tabs/Tabs.tsx +434 -0
  464. package/src/Tabs/TabsContext.ts +13 -0
  465. package/src/Tabs/__tests__/Tabs.activation-mode.test.tsx +114 -0
  466. package/src/Tabs/__tests__/Tabs.asChild.test.tsx +91 -0
  467. package/src/Tabs/__tests__/Tabs.basic-rendering.test.tsx +483 -0
  468. package/src/Tabs/__tests__/Tabs.change-event-callbacks.test.tsx +133 -0
  469. package/src/Tabs/__tests__/Tabs.controlled-state.test.tsx +152 -0
  470. package/src/Tabs/__tests__/Tabs.disabled-tabs.test.tsx +203 -0
  471. package/src/Tabs/__tests__/Tabs.error-handling.test.tsx +82 -0
  472. package/src/Tabs/__tests__/Tabs.fixtures.ts +171 -0
  473. package/src/Tabs/__tests__/Tabs.imperative-api.test.tsx +118 -0
  474. package/src/Tabs/__tests__/Tabs.keyboard-interaction.test.tsx +192 -0
  475. package/src/Tabs/__tests__/Tabs.lazy-mount.test.tsx +61 -0
  476. package/src/Tabs/__tests__/Tabs.mouse-interaction.test.tsx +216 -0
  477. package/src/Tabs/__tests__/Tabs.reading-direction.test.tsx +58 -0
  478. package/src/Tabs/__tests__/Tabs.uncontrolled-state.test.tsx +197 -0
  479. package/src/Tabs/hooks/index.ts +4 -0
  480. package/src/Tabs/hooks/useTabsContent.ts +27 -0
  481. package/src/Tabs/hooks/useTabsContext.ts +1 -0
  482. package/src/Tabs/hooks/useTabsRoot.ts +148 -0
  483. package/src/Tabs/hooks/useTabsTrigger.ts +111 -0
  484. package/src/Tabs/index.ts +3 -0
  485. package/src/Tabs/types.ts +99 -0
  486. package/src/Tabs/utils.ts +8 -0
  487. package/src/Textarea/README.md +98 -0
  488. package/src/Textarea/Textarea.tsx +93 -0
  489. package/src/Textarea/__tests__/Textarea.asChild.test.tsx +85 -0
  490. package/src/Textarea/__tests__/Textarea.basic-rendering.test.tsx +107 -0
  491. package/src/Textarea/__tests__/Textarea.disabled.test.tsx +49 -0
  492. package/src/Textarea/__tests__/Textarea.field-integration.test.tsx +134 -0
  493. package/src/Textarea/index.ts +2 -0
  494. package/src/Textarea/types.ts +7 -0
  495. package/src/Toggle/README.md +97 -0
  496. package/src/Toggle/Toggle.tsx +81 -0
  497. package/src/Toggle/__tests__/Toggle.asChild.test.tsx +42 -0
  498. package/src/Toggle/__tests__/Toggle.basic-rendering.test.tsx +28 -0
  499. package/src/Toggle/__tests__/Toggle.controlled-state.test.tsx +60 -0
  500. package/src/Toggle/__tests__/Toggle.disabled.test.tsx +34 -0
  501. package/src/Toggle/__tests__/Toggle.keyboard-interaction.test.tsx +42 -0
  502. package/src/Toggle/__tests__/Toggle.uncontrolled-state.test.tsx +40 -0
  503. package/src/Toggle/index.ts +2 -0
  504. package/src/Toggle/types.ts +23 -0
  505. package/src/ToggleGroup/README.md +137 -0
  506. package/src/ToggleGroup/ToggleGroup.tsx +298 -0
  507. package/src/ToggleGroup/ToggleGroupContext.ts +9 -0
  508. package/src/ToggleGroup/__tests__/ToggleGroup.asChild.test.tsx +65 -0
  509. package/src/ToggleGroup/__tests__/ToggleGroup.basic-rendering.test.tsx +50 -0
  510. package/src/ToggleGroup/__tests__/ToggleGroup.disabled.test.tsx +54 -0
  511. package/src/ToggleGroup/__tests__/ToggleGroup.keyboard-interaction.test.tsx +151 -0
  512. package/src/ToggleGroup/__tests__/ToggleGroup.multiple-mode.test.tsx +144 -0
  513. package/src/ToggleGroup/__tests__/ToggleGroup.reading-direction.test.tsx +28 -0
  514. package/src/ToggleGroup/__tests__/ToggleGroup.single-mode.test.tsx +139 -0
  515. package/src/ToggleGroup/hooks/index.ts +2 -0
  516. package/src/ToggleGroup/hooks/useToggleGroupContext.ts +1 -0
  517. package/src/ToggleGroup/hooks/useToggleGroupRoot.ts +110 -0
  518. package/src/ToggleGroup/index.ts +2 -0
  519. package/src/ToggleGroup/types.ts +72 -0
  520. package/src/Tooltip/README.md +214 -0
  521. package/src/Tooltip/Tooltip.tsx +260 -0
  522. package/src/Tooltip/TooltipContext.ts +20 -0
  523. package/src/Tooltip/__tests__/Tooltip.asChild.test.tsx +77 -0
  524. package/src/Tooltip/__tests__/Tooltip.basic-rendering.test.tsx +180 -0
  525. package/src/Tooltip/__tests__/Tooltip.controlled-state.test.tsx +128 -0
  526. package/src/Tooltip/__tests__/Tooltip.escape-hatches.test.tsx +73 -0
  527. package/src/Tooltip/__tests__/Tooltip.focus-interaction.test.tsx +88 -0
  528. package/src/Tooltip/__tests__/Tooltip.hover-interaction.test.tsx +179 -0
  529. package/src/Tooltip/__tests__/Tooltip.keyboard-interaction.test.tsx +85 -0
  530. package/src/Tooltip/__tests__/Tooltip.uncontrolled-state.test.tsx +67 -0
  531. package/src/Tooltip/hooks/index.ts +4 -0
  532. package/src/Tooltip/hooks/useTooltipContent.ts +53 -0
  533. package/src/Tooltip/hooks/useTooltipProvider.ts +41 -0
  534. package/src/Tooltip/hooks/useTooltipRoot.ts +106 -0
  535. package/src/Tooltip/hooks/useTooltipTrigger.ts +44 -0
  536. package/src/Tooltip/index.ts +1 -0
  537. package/src/Tooltip/types.ts +64 -0
  538. package/src/Tree/README.md +339 -0
  539. package/src/Tree/Tree.tsx +571 -0
  540. package/src/Tree/TreeContext.ts +24 -0
  541. package/src/Tree/__tests__/Tree.aria.test.tsx +53 -0
  542. package/src/Tree/__tests__/Tree.asChild.test.tsx +134 -0
  543. package/src/Tree/__tests__/Tree.basic-rendering.test.tsx +111 -0
  544. package/src/Tree/__tests__/Tree.branch-behaviour.test.tsx +87 -0
  545. package/src/Tree/__tests__/Tree.controlled-expansion.test.tsx +92 -0
  546. package/src/Tree/__tests__/Tree.data-attributes.test.tsx +88 -0
  547. package/src/Tree/__tests__/Tree.disabled-items.test.tsx +196 -0
  548. package/src/Tree/__tests__/Tree.error-handling.test.tsx +71 -0
  549. package/src/Tree/__tests__/Tree.forceMount.test.tsx +72 -0
  550. package/src/Tree/__tests__/Tree.keyboard-interaction.test.tsx +150 -0
  551. package/src/Tree/__tests__/Tree.multiple-selection.test.tsx +151 -0
  552. package/src/Tree/__tests__/Tree.range-selection.test.tsx +200 -0
  553. package/src/Tree/__tests__/Tree.recursion-depth.test.tsx +73 -0
  554. package/src/Tree/__tests__/Tree.roving-tabindex.test.tsx +117 -0
  555. package/src/Tree/__tests__/Tree.selection-path.test.tsx +404 -0
  556. package/src/Tree/__tests__/Tree.single-selection.test.tsx +108 -0
  557. package/src/Tree/__tests__/Tree.uncontrolled-expansion.test.tsx +69 -0
  558. package/src/Tree/hooks/index.ts +3 -0
  559. package/src/Tree/hooks/useTreeItemKeyboard.ts +86 -0
  560. package/src/Tree/hooks/useTreePath.ts +68 -0
  561. package/src/Tree/hooks/useTreeRoot.ts +279 -0
  562. package/src/Tree/index.ts +3 -0
  563. package/src/Tree/types.ts +224 -0
  564. package/src/Tree/utils.ts +59 -0
  565. package/src/VisuallyHidden/README.md +58 -0
  566. package/src/VisuallyHidden/VisuallyHidden.tsx +67 -0
  567. package/src/VisuallyHidden/__tests__/VisuallyHidden.test.tsx +59 -0
  568. package/src/VisuallyHidden/index.ts +2 -0
  569. package/src/VisuallyHidden/types.ts +5 -0
  570. package/src/hooks/index.ts +3 -0
  571. package/src/hooks/useCollection.ts +74 -0
  572. package/src/hooks/useControllableState.ts +81 -0
  573. package/src/hooks/useRovingTabindex.ts +178 -0
  574. package/src/index.ts +38 -0
  575. package/src/test/intersectionObserverPolyfill.ts +83 -0
  576. package/src/test/popoverPolyfill.ts +86 -0
  577. package/src/test/scrollPolyfill.ts +23 -0
  578. package/src/types.ts +13 -0
  579. package/src/utils/__tests__/createStrictContext.test.tsx +69 -0
  580. package/src/utils/__tests__/deriveId.test.ts +28 -0
  581. package/src/utils/__tests__/getKeyToActionMap.test.ts +106 -0
  582. package/src/utils/createStrictContext.ts +49 -0
  583. package/src/utils/deriveId.ts +31 -0
  584. package/src/utils/getKeyToActionMap.ts +95 -0
  585. package/src/utils/index.ts +3 -0
@@ -0,0 +1,708 @@
1
+ import { forwardRef, MouseEvent, useCallback } from "react";
2
+
3
+ import { Slot } from "../Slot";
4
+ import { CarouselProvider } from "./CarouselContext";
5
+ import {
6
+ useCarouselContext,
7
+ useCarouselRoot,
8
+ useCarouselSlide,
9
+ useCarouselViewport,
10
+ } from "./hooks";
11
+ import type {
12
+ CarouselImperativeApi,
13
+ CarouselRootProps,
14
+ CarouselViewportProps,
15
+ CarouselSlideProps,
16
+ CarouselNextTriggerProps,
17
+ CarouselPreviousTriggerProps,
18
+ CarouselIndicatorGroupProps,
19
+ CarouselIndicatorProps,
20
+ CarouselIndicatorsProps,
21
+ CarouselPlayPauseTriggerProps,
22
+ } from "./types";
23
+
24
+ /**
25
+ * The root of a Carousel widget. Renders a `<section>` with
26
+ * `aria-roledescription="carousel"` so assistive technology announces
27
+ * the widget as a carousel rather than a generic region, per the
28
+ * WAI-ARIA Carousel pattern.
29
+ *
30
+ * Every carousel must have an accessible name. Pass exactly one of:
31
+ *
32
+ * - `ariaLabel` — a short human-readable description (e.g.
33
+ * `"Featured products"`).
34
+ * - `ariaLabelledBy` — the `id` of an existing heading or label element.
35
+ *
36
+ * The discriminated union on the props type rejects both-or-neither at
37
+ * compile time.
38
+ *
39
+ * Supports two **page-state modes**, statically discriminated at the type
40
+ * level so only one of the two shapes is accepted by TypeScript:
41
+ *
42
+ * - **Uncontrolled** — pass `defaultPage` (or omit it and start at `0`).
43
+ * The component owns and updates the active page internally.
44
+ * - **Controlled** — pass `page` *and* `onPageChange` together. The
45
+ * parent owns the active page; the component defers every state
46
+ * change back through the callback.
47
+ *
48
+ * @example Labelled inline, uncontrolled
49
+ * ```tsx
50
+ * <Carousel.Root ariaLabel="Featured products" defaultPage={0}>…</Carousel.Root>
51
+ * ```
52
+ *
53
+ * @example Controlled
54
+ * ```tsx
55
+ * const [page, setPage] = useState(0);
56
+ *
57
+ * <Carousel.Root
58
+ * ariaLabel="Featured products"
59
+ * page={page}
60
+ * onPageChange={setPage}
61
+ * >
62
+ * …
63
+ * </Carousel.Root>
64
+ * ```
65
+ *
66
+ * @example Labelled by an existing heading
67
+ * ```tsx
68
+ * <h2 id="promos">Promotions</h2>
69
+ * <Carousel.Root ariaLabelledBy="promos">…</Carousel.Root>
70
+ * ```
71
+ */
72
+ export const CarouselRoot = forwardRef<
73
+ CarouselImperativeApi,
74
+ CarouselRootProps
75
+ >(function CarouselRoot(
76
+ {
77
+ className = "",
78
+ ariaLabel,
79
+ ariaLabelledBy,
80
+ defaultPage,
81
+ page,
82
+ onPageChange,
83
+ defaultPlaying,
84
+ playing,
85
+ onPlayingChange,
86
+ autoplay,
87
+ slidesPerPage,
88
+ slidesPerMove,
89
+ translations,
90
+ ids,
91
+ transition,
92
+ snapAlign,
93
+ children,
94
+ ...rest
95
+ },
96
+ imperativeRef,
97
+ ) {
98
+ const { contextValue, rootHandlers } = useCarouselRoot(
99
+ {
100
+ defaultPage,
101
+ page,
102
+ onPageChange,
103
+ defaultPlaying,
104
+ playing,
105
+ onPlayingChange,
106
+ autoplay,
107
+ slidesPerPage,
108
+ slidesPerMove,
109
+ translations,
110
+ ids,
111
+ transition,
112
+ snapAlign,
113
+ },
114
+ imperativeRef,
115
+ );
116
+
117
+ return (
118
+ <CarouselProvider value={contextValue}>
119
+ <section
120
+ aria-roledescription="carousel"
121
+ className={className}
122
+ {...(ariaLabel !== undefined && { "aria-label": ariaLabel })}
123
+ {...(ariaLabelledBy !== undefined && {
124
+ "aria-labelledby": ariaLabelledBy,
125
+ })}
126
+ {...(contextValue.ids.root !== undefined && {
127
+ id: contextValue.ids.root,
128
+ })}
129
+ {...rootHandlers}
130
+ {...rest}
131
+ >
132
+ {children}
133
+ </section>
134
+ </CarouselProvider>
135
+ );
136
+ });
137
+
138
+ CarouselRoot.displayName = "CarouselRoot";
139
+
140
+ /**
141
+ * The slide container — the scrollable surface that holds
142
+ * `Carousel.Slide` children. Rendered as a `<div>` with a
143
+ * `data-carousel-viewport` attribute that the recommended scroll-snap
144
+ * CSS targets (see this component's README for the recipe).
145
+ *
146
+ * The viewport must be rendered as a descendant of `Carousel.Root`;
147
+ * rendering it elsewhere throws a descriptive error so misuse surfaces
148
+ * during development rather than as silent ARIA breakage.
149
+ *
150
+ * **Live region.** The viewport is also the live region for slide
151
+ * changes: `aria-live="polite"` so paged navigation is announced to
152
+ * assistive tech, flipping to `aria-live="off"` while autoplay is
153
+ * actively rotating so screen readers don't get spammed with every
154
+ * tick.
155
+ *
156
+ * **Styling hooks.** `data-carousel-viewport` is set on the rendered
157
+ * element. The component ships no styles — apply your own scroll-snap
158
+ * recipe via this attribute.
159
+ *
160
+ * **Keyboard navigation.** The Viewport is in the tab order
161
+ * (`tabIndex={0}`) so keyboard users can reach the rotation control
162
+ * without first tabbing through every slide's interactive content.
163
+ * With the Viewport focused:
164
+ *
165
+ * - `ArrowRight` advances by one page (same as `Carousel.NextTrigger`).
166
+ * - `ArrowLeft` retreats by one page (same as `Carousel.PreviousTrigger`).
167
+ * - `Home` jumps to the first page.
168
+ * - `End` jumps to the last page.
169
+ *
170
+ * Arrow keys clamp at the boundaries, mirroring the trigger buttons.
171
+ * Keypresses are only intercepted when the Viewport itself is the focus
172
+ * target — focus inside a slide (e.g. on a link or form control) keeps
173
+ * its native arrow-key semantics.
174
+ *
175
+ * @example
176
+ * ```tsx
177
+ * <Carousel.Root ariaLabel="Featured products">
178
+ * <Carousel.Viewport>
179
+ * <Carousel.Slide>…</Carousel.Slide>
180
+ * </Carousel.Viewport>
181
+ * </Carousel.Root>
182
+ * ```
183
+ */
184
+ export function CarouselViewport({
185
+ className = "",
186
+ children,
187
+ ...rest
188
+ }: CarouselViewportProps) {
189
+ const { isAutoRotating, ids } = useCarouselContext();
190
+ const { viewportRef, onKeyDown } = useCarouselViewport();
191
+
192
+ return (
193
+ <div
194
+ ref={viewportRef}
195
+ data-carousel-viewport=""
196
+ tabIndex={0}
197
+ className={className}
198
+ aria-live={isAutoRotating ? "off" : "polite"}
199
+ onKeyDown={onKeyDown}
200
+ {...(ids.viewport !== undefined && { id: ids.viewport })}
201
+ {...rest}
202
+ >
203
+ {children}
204
+ </div>
205
+ );
206
+ }
207
+
208
+ CarouselViewport.displayName = "CarouselViewport";
209
+
210
+ /**
211
+ * An individual slide. Renders a `<div>` with `role="group"` and
212
+ * `aria-roledescription="slide"` per the WAI-ARIA Carousel pattern, so
213
+ * assistive technology announces each slide as a discrete group rather
214
+ * than a generic region.
215
+ *
216
+ * **Self-registration.** On mount, every slide registers itself with
217
+ * `Carousel.Root` via a callback ref. The Root maintains an ordered list
218
+ * of registered slide keys, which is how the slide knows its own
219
+ * zero-based `data-index` and how every slide receives the live
220
+ * `data-total` count. Slides may be added or removed at runtime; the
221
+ * indices and totals update automatically.
222
+ *
223
+ * **Auto-labelling.** Each slide is labelled `"N of M"` (e.g. `"1 of 3"`)
224
+ * using its live index and the live total — the format the WAI-ARIA
225
+ * Carousel APG example uses, and what most screen readers expect. Pass
226
+ * {@link CarouselSlideProps.ariaLabel | `ariaLabel`} to override the
227
+ * auto-label with a more meaningful description (e.g.
228
+ * `"Hand-picked for you"`).
229
+ *
230
+ * **Styling hooks.**
231
+ * - `data-carousel-slide` — CSS-targeting attribute (recommended scroll-snap
232
+ * recipe targets `[data-carousel-slide]`).
233
+ * - `data-index="N"` — the slide's zero-based position in registration order.
234
+ * - `data-total="N"` — the live total slide count.
235
+ *
236
+ * Must be rendered as a descendant of `Carousel.Root`; rendering it
237
+ * elsewhere throws a descriptive error.
238
+ *
239
+ * @example Auto-labelled
240
+ * ```tsx
241
+ * <Carousel.Viewport>
242
+ * <Carousel.Slide>First slide</Carousel.Slide>
243
+ * <Carousel.Slide>Second slide</Carousel.Slide>
244
+ * </Carousel.Viewport>
245
+ * ```
246
+ *
247
+ * @example Override the auto-label
248
+ * ```tsx
249
+ * <Carousel.Slide ariaLabel="Hand-picked for you">…</Carousel.Slide>
250
+ * ```
251
+ */
252
+ export function CarouselSlide({
253
+ className = "",
254
+ ariaLabel,
255
+ children,
256
+ ...rest
257
+ }: CarouselSlideProps) {
258
+ const { slideRef, index, total, state } = useCarouselSlide();
259
+ const { translations } = useCarouselContext();
260
+ const autoLabel =
261
+ index >= 0 && total > 0
262
+ ? translations.slideLabel({ index: index + 1, total })
263
+ : undefined;
264
+ const label = ariaLabel ?? autoLabel;
265
+
266
+ return (
267
+ <div
268
+ ref={slideRef}
269
+ role="group"
270
+ aria-roledescription="slide"
271
+ data-carousel-slide=""
272
+ data-index={index}
273
+ data-total={total}
274
+ data-state={state}
275
+ className={className}
276
+ {...(label !== undefined && { "aria-label": label })}
277
+ {...rest}
278
+ >
279
+ {children}
280
+ </div>
281
+ );
282
+ }
283
+
284
+ CarouselSlide.displayName = "CarouselSlide";
285
+
286
+ /**
287
+ * Advances the active page by one. Renders as
288
+ * `<button type="button">` and dispatches the consumer's `onClick`
289
+ * before invoking the navigation, so analytics handlers and similar
290
+ * still fire when the user advances the carousel.
291
+ *
292
+ * **Boundary clamping.** The trigger is `disabled` once the active page
293
+ * reaches the last slide; the click is also a no-op at boundaries
294
+ * because `next()` short-circuits when there's nowhere to go. The
295
+ * button is always disabled when there are zero or one slides
296
+ * registered. Consumer-supplied `disabled={true}` is also honoured (it
297
+ * OR's with the boundary check).
298
+ *
299
+ * Must be rendered as a descendant of `Carousel.Root`; rendering it
300
+ * elsewhere throws a descriptive error.
301
+ *
302
+ * @example
303
+ * ```tsx
304
+ * <Carousel.NextTrigger>Next</Carousel.NextTrigger>
305
+ * ```
306
+ */
307
+ export function CarouselNextTrigger({
308
+ className = "",
309
+ onClick,
310
+ disabled,
311
+ asChild = false,
312
+ children,
313
+ ...rest
314
+ }: CarouselNextTriggerProps) {
315
+ const { next, canGoNext, ids } = useCarouselContext();
316
+ const isDisabled = disabled === true || !canGoNext;
317
+
318
+ const handleClick = useCallback(
319
+ (event: MouseEvent<HTMLButtonElement>) => {
320
+ onClick?.(event);
321
+ // Guard runs in addition to the HTML disabled attribute on the
322
+ // default <button> path. With asChild on a non-button element
323
+ // there's no native disabled to block the click, so this is the
324
+ // only barrier.
325
+ if (isDisabled) return;
326
+ next();
327
+ },
328
+ [next, onClick, isDisabled],
329
+ );
330
+
331
+ const triggerProps = {
332
+ className,
333
+ onClick: handleClick,
334
+ disabled: isDisabled,
335
+ "aria-disabled": isDisabled,
336
+ ...(ids.nextTrigger !== undefined && { id: ids.nextTrigger }),
337
+ ...rest,
338
+ };
339
+
340
+ if (asChild) {
341
+ return <Slot {...triggerProps}>{children}</Slot>;
342
+ }
343
+
344
+ return (
345
+ <button type="button" {...triggerProps}>
346
+ {children}
347
+ </button>
348
+ );
349
+ }
350
+
351
+ CarouselNextTrigger.displayName = "CarouselNextTrigger";
352
+
353
+ /**
354
+ * Retreats the active page by one. Renders as
355
+ * `<button type="button">` and dispatches the consumer's `onClick`
356
+ * before invoking the navigation, so analytics handlers and similar
357
+ * still fire when the user retreats the carousel.
358
+ *
359
+ * **Boundary clamping.** The trigger is `disabled` while the active
360
+ * page is the first slide; the click is also a no-op at boundaries
361
+ * because `previous()` short-circuits when there's nowhere to go. The
362
+ * button is always disabled when there are zero or one slides
363
+ * registered. Consumer-supplied `disabled={true}` is also honoured.
364
+ *
365
+ * Must be rendered as a descendant of `Carousel.Root`; rendering it
366
+ * elsewhere throws a descriptive error.
367
+ *
368
+ * @example
369
+ * ```tsx
370
+ * <Carousel.PreviousTrigger>Previous</Carousel.PreviousTrigger>
371
+ * ```
372
+ */
373
+ export function CarouselPreviousTrigger({
374
+ className = "",
375
+ onClick,
376
+ disabled,
377
+ asChild = false,
378
+ children,
379
+ ...rest
380
+ }: CarouselPreviousTriggerProps) {
381
+ const { previous, canGoPrevious, ids } = useCarouselContext();
382
+ const isDisabled = disabled === true || !canGoPrevious;
383
+
384
+ const handleClick = useCallback(
385
+ (event: MouseEvent<HTMLButtonElement>) => {
386
+ onClick?.(event);
387
+ if (isDisabled) return;
388
+ previous();
389
+ },
390
+ [previous, onClick, isDisabled],
391
+ );
392
+
393
+ const triggerProps = {
394
+ className,
395
+ onClick: handleClick,
396
+ disabled: isDisabled,
397
+ "aria-disabled": isDisabled,
398
+ ...(ids.previousTrigger !== undefined && { id: ids.previousTrigger }),
399
+ ...rest,
400
+ };
401
+
402
+ if (asChild) {
403
+ return <Slot {...triggerProps}>{children}</Slot>;
404
+ }
405
+
406
+ return (
407
+ <button type="button" {...triggerProps}>
408
+ {children}
409
+ </button>
410
+ );
411
+ }
412
+
413
+ CarouselPreviousTrigger.displayName = "CarouselPreviousTrigger";
414
+
415
+ /**
416
+ * A `<div role="group">` wrapping consumer-mapped `Carousel.Indicator`
417
+ * dots. Use this when you want manual control over how the dots are
418
+ * rendered (e.g. mixing custom content into each one). For the common
419
+ * case of one auto-rendered dot per page, prefer `Carousel.Indicators`.
420
+ *
421
+ * Every group must have an accessible name. Pass exactly one of:
422
+ *
423
+ * - `label` — a short human-readable description of the picker (e.g.
424
+ * `"Choose slide"`).
425
+ * - `ariaLabelledBy` — the `id` of an existing heading or label element.
426
+ *
427
+ * The discriminated union on the props type rejects both-or-neither at
428
+ * compile time.
429
+ *
430
+ * Must be rendered as a descendant of `Carousel.Root`; rendering it
431
+ * elsewhere throws a descriptive error.
432
+ *
433
+ * @example
434
+ * ```tsx
435
+ * <Carousel.IndicatorGroup label="Choose slide">
436
+ * <Carousel.Indicator index={0} />
437
+ * <Carousel.Indicator index={1} />
438
+ * <Carousel.Indicator index={2} />
439
+ * </Carousel.IndicatorGroup>
440
+ * ```
441
+ */
442
+ export function CarouselIndicatorGroup({
443
+ className = "",
444
+ label,
445
+ ariaLabelledBy,
446
+ children,
447
+ ...rest
448
+ }: CarouselIndicatorGroupProps) {
449
+ const { ids } = useCarouselContext();
450
+
451
+ return (
452
+ <div
453
+ role="group"
454
+ className={className}
455
+ {...(label !== undefined && { "aria-label": label })}
456
+ {...(ariaLabelledBy !== undefined && {
457
+ "aria-labelledby": ariaLabelledBy,
458
+ })}
459
+ {...(ids.indicatorGroup !== undefined && { id: ids.indicatorGroup })}
460
+ {...rest}
461
+ >
462
+ {children}
463
+ </div>
464
+ );
465
+ }
466
+
467
+ CarouselIndicatorGroup.displayName = "CarouselIndicatorGroup";
468
+
469
+ /**
470
+ * An individual indicator dot — a `<button>` that jumps to the page at
471
+ * `index` (zero-based) when clicked. Auto-labelled `"Slide N"` (where
472
+ * `N = index + 1`) so the page-position is announced to assistive tech.
473
+ *
474
+ * **Active-state ARIA.** The indicator at `currentPage` carries
475
+ * `aria-disabled="true"` per the WAI-ARIA Carousel APG — a soft disable
476
+ * that tells screen readers "you're already on this slide" without
477
+ * removing it from the focus order. Non-active indicators carry
478
+ * `aria-disabled="false"`. Both states also flip `data-state` between
479
+ * `"active"` and `"inactive"` so consumer CSS can paint the active dot.
480
+ *
481
+ * **Styling hooks.**
482
+ * - `data-carousel-indicator` — CSS-targeting attribute.
483
+ * - `data-state="active" | "inactive"` — tracks the current page.
484
+ *
485
+ * Must be rendered as a descendant of `Carousel.Root`; rendering it
486
+ * elsewhere throws a descriptive error.
487
+ *
488
+ * @example
489
+ * ```tsx
490
+ * <Carousel.Indicator index={0} />
491
+ * ```
492
+ */
493
+ export function CarouselIndicator({
494
+ className = "",
495
+ index,
496
+ onClick,
497
+ asChild = false,
498
+ children,
499
+ ...rest
500
+ }: CarouselIndicatorProps) {
501
+ const { goTo, currentPage, translations } = useCarouselContext();
502
+ const isActive = index === currentPage;
503
+
504
+ const handleClick = useCallback(
505
+ (event: MouseEvent<HTMLButtonElement>) => {
506
+ onClick?.(event);
507
+ goTo(index);
508
+ },
509
+ [goTo, index, onClick],
510
+ );
511
+
512
+ const indicatorProps = {
513
+ className,
514
+ "aria-label": translations.indicatorLabel({ index: index + 1 }),
515
+ "aria-disabled": isActive,
516
+ "data-carousel-indicator": "",
517
+ "data-state": isActive ? "active" : "inactive",
518
+ onClick: handleClick,
519
+ ...rest,
520
+ };
521
+
522
+ if (asChild) {
523
+ return <Slot {...indicatorProps}>{children}</Slot>;
524
+ }
525
+
526
+ return (
527
+ <button type="button" {...indicatorProps}>
528
+ {children}
529
+ </button>
530
+ );
531
+ }
532
+
533
+ CarouselIndicator.displayName = "CarouselIndicator";
534
+
535
+ /**
536
+ * Convenience wrapper that auto-renders one `Carousel.Indicator` per
537
+ * registered slide — the "dots between Prev and Next" you'd reach for
538
+ * in 90% of carousels. Internally renders a `Carousel.IndicatorGroup`
539
+ * containing one `Carousel.Indicator` per entry in the slide-key list,
540
+ * keyed by the slide's stable `useId` so React doesn't shuffle the
541
+ * dots when slides mount or unmount in the middle of the range.
542
+ *
543
+ * For full control over indicator content (e.g. dots that show
544
+ * thumbnail previews on hover), drop down to
545
+ * `Carousel.IndicatorGroup` + `Carousel.Indicator` instead.
546
+ *
547
+ * Must be rendered as a descendant of `Carousel.Root`; rendering it
548
+ * elsewhere throws a descriptive error.
549
+ *
550
+ * @example
551
+ * ```tsx
552
+ * <Carousel.Indicators label="Choose slide" />
553
+ * ```
554
+ */
555
+ export function CarouselIndicators(props: CarouselIndicatorsProps) {
556
+ const { totalPages } = useCarouselContext();
557
+
558
+ return (
559
+ <CarouselIndicatorGroup {...props}>
560
+ {Array.from({ length: totalPages }, (_, index) => (
561
+ <CarouselIndicator key={index} index={index} />
562
+ ))}
563
+ </CarouselIndicatorGroup>
564
+ );
565
+ }
566
+
567
+ CarouselIndicators.displayName = "CarouselIndicators";
568
+
569
+ /**
570
+ * A `<button>` that toggles the carousel's `playing` flag. Renders the
571
+ * accessible name dictated by the WAI-ARIA Carousel APG by default —
572
+ * `"Start automatic slide show"` when paused, `"Stop automatic slide
573
+ * show"` when playing — and exposes the live `playing` flag both as a
574
+ * `data-state="playing" | "paused"` styling hook and to a function
575
+ * `children` render prop, so consumers can swap icons or labels per
576
+ * state without re-implementing the toggle:
577
+ *
578
+ * ```tsx
579
+ * <Carousel.PlayPauseTrigger>
580
+ * {({ playing }) => (playing ? <PauseIcon /> : <PlayIcon />)}
581
+ * </Carousel.PlayPauseTrigger>
582
+ * ```
583
+ *
584
+ * Static children also work — useful when you want a single icon and
585
+ * style it via `[data-state]` selectors.
586
+ *
587
+ * Must be rendered as a descendant of `Carousel.Root`; rendering it
588
+ * elsewhere throws a descriptive error. The autoplay timer that
589
+ * advances the page when `playing` flips to `true` lands in cycle 12.
590
+ */
591
+ export function CarouselPlayPauseTrigger({
592
+ className = "",
593
+ onClick,
594
+ asChild = false,
595
+ children,
596
+ ...rest
597
+ }: CarouselPlayPauseTriggerProps) {
598
+ const { playing, togglePlaying, translations, ids, autoplayEnabled } =
599
+ useCarouselContext();
600
+
601
+ if (!autoplayEnabled) {
602
+ throw new Error(
603
+ "Carousel.PlayPauseTrigger requires autoplay to be enabled on Carousel.Root",
604
+ );
605
+ }
606
+
607
+ const handleClick = useCallback(
608
+ (event: MouseEvent<HTMLButtonElement>) => {
609
+ onClick?.(event);
610
+ togglePlaying();
611
+ },
612
+ [onClick, togglePlaying],
613
+ );
614
+
615
+ const renderedChildren =
616
+ typeof children === "function" ? children({ playing }) : children;
617
+
618
+ const triggerProps = {
619
+ className,
620
+ "aria-label": playing
621
+ ? translations.stopSlideshow
622
+ : translations.startSlideshow,
623
+ "data-state": playing ? "playing" : "paused",
624
+ onClick: handleClick,
625
+ ...(ids.playPauseTrigger !== undefined && { id: ids.playPauseTrigger }),
626
+ ...rest,
627
+ };
628
+
629
+ if (asChild) {
630
+ return <Slot {...triggerProps}>{renderedChildren}</Slot>;
631
+ }
632
+
633
+ return (
634
+ <button type="button" {...triggerProps}>
635
+ {renderedChildren}
636
+ </button>
637
+ );
638
+ }
639
+
640
+ CarouselPlayPauseTrigger.displayName = "CarouselPlayPauseTrigger";
641
+
642
+ type CarouselCompound = typeof CarouselRoot & {
643
+ Root: typeof CarouselRoot;
644
+ Viewport: typeof CarouselViewport;
645
+ Slide: typeof CarouselSlide;
646
+ NextTrigger: typeof CarouselNextTrigger;
647
+ PreviousTrigger: typeof CarouselPreviousTrigger;
648
+ IndicatorGroup: typeof CarouselIndicatorGroup;
649
+ Indicator: typeof CarouselIndicator;
650
+ Indicators: typeof CarouselIndicators;
651
+ PlayPauseTrigger: typeof CarouselPlayPauseTrigger;
652
+ };
653
+
654
+ /**
655
+ * Headless, accessible **Carousel** — a compound component implementing the
656
+ * WAI-ARIA Carousel pattern with zero styles.
657
+ *
658
+ * `Carousel` is both callable (it's an alias of {@link CarouselRoot |
659
+ * `Carousel.Root`}) and carries its sub-components as static properties.
660
+ * Prefer the namespaced form in application code for readability:
661
+ *
662
+ * - {@link CarouselRoot | `Carousel.Root`} — the labelled `<section>`
663
+ * that wraps the entire widget.
664
+ * - {@link CarouselViewport | `Carousel.Viewport`} — the slide
665
+ * container that the recommended scroll-snap CSS targets.
666
+ * - {@link CarouselSlide | `Carousel.Slide`} — an individual slide,
667
+ * self-registering with the Root for live index / total tracking.
668
+ * - {@link CarouselNextTrigger | `Carousel.NextTrigger`} — advances
669
+ * the active page by one.
670
+ * - {@link CarouselPreviousTrigger | `Carousel.PreviousTrigger`} —
671
+ * retreats the active page by one.
672
+ * - {@link CarouselIndicatorGroup | `Carousel.IndicatorGroup`} — a
673
+ * labelled `<div role="group">` for consumer-mapped dot indicators.
674
+ * - {@link CarouselIndicator | `Carousel.Indicator`} — an individual
675
+ * `<button>` that jumps to a target page when clicked.
676
+ * - {@link CarouselIndicators | `Carousel.Indicators`} — convenience
677
+ * wrapper that auto-renders one indicator per registered slide.
678
+ *
679
+ * @example
680
+ * ```tsx
681
+ * import { Carousel } from "@primitiv-ui/react";
682
+ *
683
+ * <Carousel.Root ariaLabel="Featured products">
684
+ * <Carousel.Viewport>
685
+ * <Carousel.Slide>First</Carousel.Slide>
686
+ * <Carousel.Slide>Second</Carousel.Slide>
687
+ * </Carousel.Viewport>
688
+ * <Carousel.PreviousTrigger>Previous</Carousel.PreviousTrigger>
689
+ * <Carousel.Indicators label="Choose slide" />
690
+ * <Carousel.NextTrigger>Next</Carousel.NextTrigger>
691
+ * </Carousel.Root>
692
+ * ```
693
+ */
694
+ const CarouselCompound: CarouselCompound = Object.assign(CarouselRoot, {
695
+ Root: CarouselRoot,
696
+ Viewport: CarouselViewport,
697
+ Slide: CarouselSlide,
698
+ NextTrigger: CarouselNextTrigger,
699
+ PreviousTrigger: CarouselPreviousTrigger,
700
+ IndicatorGroup: CarouselIndicatorGroup,
701
+ Indicator: CarouselIndicator,
702
+ Indicators: CarouselIndicators,
703
+ PlayPauseTrigger: CarouselPlayPauseTrigger,
704
+ });
705
+
706
+ CarouselCompound.displayName = "Carousel";
707
+
708
+ export { CarouselCompound as Carousel };
@@ -0,0 +1,11 @@
1
+ import { createContext } from "react";
2
+
3
+ import type { CarouselContextValue } from "./types";
4
+
5
+ export const CarouselContext = createContext<CarouselContextValue | null>(null);
6
+
7
+ CarouselContext.displayName = "CarouselContext";
8
+
9
+ const CarouselProvider = CarouselContext.Provider;
10
+
11
+ export { CarouselProvider };