@chassis-ui/react 0.1.2 → 0.2.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 (353) hide show
  1. package/dist/accordion.d.ts +2 -0
  2. package/dist/accordion.js +1 -0
  3. package/dist/autocomplete.d.ts +2 -0
  4. package/dist/autocomplete.js +1 -0
  5. package/dist/avatar.d.ts +2 -0
  6. package/dist/avatar.js +1 -0
  7. package/dist/badge.d.ts +2 -0
  8. package/dist/badge.js +1 -0
  9. package/dist/breadcrumb.d.ts +2 -0
  10. package/dist/breadcrumb.js +1 -0
  11. package/dist/button-group.d.ts +2 -0
  12. package/dist/button-group.js +1 -0
  13. package/dist/button.d.ts +3 -0
  14. package/dist/button.js +1 -0
  15. package/dist/calendar.d.ts +3 -0
  16. package/dist/calendar.js +1 -0
  17. package/dist/card.d.ts +2 -0
  18. package/dist/card.js +1 -0
  19. package/dist/carousel.d.ts +2 -0
  20. package/dist/carousel.js +1 -0
  21. package/dist/checkbox.d.ts +3 -0
  22. package/dist/checkbox.js +1 -0
  23. package/dist/chip-input.d.ts +2 -0
  24. package/dist/chip-input.js +1 -0
  25. package/dist/chip.d.ts +2 -0
  26. package/dist/chip.js +1 -0
  27. package/dist/chunks/Button-Cptd4Yk7.d.ts +65 -0
  28. package/dist/chunks/Button-I0aUy5h-.js +1 -0
  29. package/dist/chunks/Chip-D0Cw0mAr.js +1 -0
  30. package/dist/chunks/CloseButton-DJM7FRKh.js +1 -0
  31. package/dist/chunks/ComboboxItem-C9TpoJOI.d.ts +54 -0
  32. package/dist/chunks/ComboboxListBox-BhO8uRNg.js +1 -0
  33. package/dist/chunks/FormHelp-Be2PQL0y.js +1 -0
  34. package/dist/chunks/FormLabel-CYcQiFUI.js +1 -0
  35. package/dist/chunks/Icon-BIwkD-kx.js +1 -0
  36. package/dist/chunks/Icon-CioraWLF.d.ts +36 -0
  37. package/dist/chunks/Link-B0Y1xgYi.d.ts +69 -0
  38. package/dist/chunks/Link-Cq7FNWpm.js +1 -0
  39. package/dist/chunks/MenuItemDef-D0VDtYIQ.d.ts +82 -0
  40. package/dist/chunks/RangeCalendar-COnSfurr.js +1 -0
  41. package/dist/chunks/accordion-okRicuG5.js +1 -0
  42. package/dist/chunks/autocomplete-B0xTc6kg.js +1 -0
  43. package/dist/chunks/avatar-Bjm0DlPO.js +1 -0
  44. package/dist/chunks/badge-Bj8mf8lu.js +1 -0
  45. package/dist/chunks/breadcrumb-DDxnx_iS.js +1 -0
  46. package/dist/chunks/breakpoints-SLMTNHF9.d.ts +5 -0
  47. package/dist/chunks/breakpoints-o_2Ev7ir.js +1 -0
  48. package/dist/chunks/button-group-CPZYA6aZ.js +1 -0
  49. package/dist/chunks/card-DfF2K_5p.js +1 -0
  50. package/dist/chunks/carousel-DEvwcA7H.js +1 -0
  51. package/dist/chunks/checkbox-BFPS0pD6.js +1 -0
  52. package/dist/chunks/chip-input-CB1lE6vP.js +1 -0
  53. package/dist/chunks/collapse-WifcChO8.js +1 -0
  54. package/dist/chunks/color-input-CyRaLR_G.js +1 -0
  55. package/dist/chunks/combobox-DWEj-Sv7.js +1 -0
  56. package/dist/chunks/datagrid-nbnNThsT.js +2 -0
  57. package/dist/chunks/dateRangePresets-R1FtA1zp.d.ts +41 -0
  58. package/dist/chunks/datepicker-CslLKMm1.js +1 -0
  59. package/dist/chunks/dialogTransition-i9vw0i2Z.js +1 -0
  60. package/dist/chunks/direction-CPhdeL3A.js +1 -0
  61. package/dist/chunks/drawer-zReFjoJG.js +1 -0
  62. package/dist/chunks/file-input-RRqZSzjH.js +1 -0
  63. package/dist/chunks/flex-BTvpgaRv.js +1 -0
  64. package/dist/chunks/floating-input-CIC9Lm2a.js +1 -0
  65. package/dist/chunks/focus-ring-SR_LwaN7.js +1 -0
  66. package/dist/chunks/focusRedirect-BrvK3U_o.js +1 -0
  67. package/dist/chunks/form-GpdAyWWi.js +1 -0
  68. package/dist/chunks/form-field-BjQ9SIjx.js +1 -0
  69. package/dist/chunks/grid-CuFw89yV.js +1 -0
  70. package/dist/chunks/icon-mxYpL5nL.js +1 -0
  71. package/dist/chunks/iconConfig-Bu6Pt9o3.d.ts +69 -0
  72. package/dist/chunks/iconSlot-BmWxJh27.js +1 -0
  73. package/dist/chunks/index--0_IpTDT.d.ts +17 -0
  74. package/dist/chunks/index-6uob77s9.d.ts +80 -0
  75. package/dist/chunks/index-8PhBSbNQ.d.ts +93 -0
  76. package/dist/chunks/index-B0-8n-Gs.d.ts +105 -0
  77. package/dist/chunks/index-B8uaSJA9.d.ts +95 -0
  78. package/dist/chunks/index-BA-raEMm.d.ts +28 -0
  79. package/dist/chunks/index-BDfh8YBc.d.ts +39 -0
  80. package/dist/chunks/index-BKMW0rkw.d.ts +80 -0
  81. package/dist/chunks/index-BO9jLOIb.d.ts +58 -0
  82. package/dist/chunks/index-BO_1MN66.d.ts +87 -0
  83. package/dist/chunks/index-BTDgfLxK.d.ts +94 -0
  84. package/dist/chunks/index-BTTeKpiE.d.ts +363 -0
  85. package/dist/chunks/index-BVGGIaPX.d.ts +110 -0
  86. package/dist/chunks/index-Bi8FFadV.d.ts +98 -0
  87. package/dist/chunks/index-Bkj17NEQ.d.ts +50 -0
  88. package/dist/chunks/index-BlgkO3dn.d.ts +280 -0
  89. package/dist/chunks/index-BxTlIaZu.d.ts +301 -0
  90. package/dist/chunks/index-C61tPIJ-.d.ts +50 -0
  91. package/dist/chunks/index-CCXJXToc.d.ts +52 -0
  92. package/dist/chunks/index-CJzKu7QI.d.ts +40 -0
  93. package/dist/chunks/index-COsIPd8L.d.ts +62 -0
  94. package/dist/chunks/index-COsYSDrz.d.ts +109 -0
  95. package/dist/chunks/index-CRfm7W6C.d.ts +230 -0
  96. package/dist/chunks/index-CVUMS0x7.d.ts +73 -0
  97. package/dist/chunks/index-CaQ1JY5D.d.ts +49 -0
  98. package/dist/chunks/index-Cf2n0l0U.d.ts +138 -0
  99. package/dist/chunks/index-CftERHnE.d.ts +24 -0
  100. package/dist/chunks/index-ClT3E_hv.d.ts +302 -0
  101. package/dist/chunks/index-CsMIgBsd.d.ts +39 -0
  102. package/dist/chunks/index-Ctuk1xBU.d.ts +99 -0
  103. package/dist/chunks/index-D2VVO8rx.d.ts +49 -0
  104. package/dist/chunks/index-D949AidR.d.ts +40 -0
  105. package/dist/chunks/index-D9PZHY_I.d.ts +135 -0
  106. package/dist/chunks/index-DAoPg59I.d.ts +80 -0
  107. package/dist/chunks/index-DB_ToPdz.d.ts +202 -0
  108. package/dist/chunks/index-DEb9zXlC.d.ts +210 -0
  109. package/dist/chunks/index-DHGgezXU.d.ts +58 -0
  110. package/dist/chunks/index-DJJocp_q.d.ts +132 -0
  111. package/dist/chunks/index-DKma0jQw.d.ts +104 -0
  112. package/dist/chunks/index-DPV62IdF.d.ts +118 -0
  113. package/dist/chunks/index-DR8sYtvd.d.ts +296 -0
  114. package/dist/chunks/index-Dcc_W6Kv.d.ts +146 -0
  115. package/dist/chunks/index-Dfg4Ftb8.d.ts +68 -0
  116. package/dist/chunks/index-Dfy1YW5j.d.ts +73 -0
  117. package/dist/chunks/index-Dh5CaHTP.d.ts +44 -0
  118. package/dist/chunks/index-DtbUXxjz.d.ts +53 -0
  119. package/dist/chunks/index-Dum6Y9XR.d.ts +187 -0
  120. package/dist/chunks/index-HrKN6s8z.d.ts +66 -0
  121. package/dist/chunks/index-JllMXhVx.d.ts +176 -0
  122. package/dist/chunks/index-XjLvaH4G.d.ts +67 -0
  123. package/dist/chunks/index-dh3TKanY.d.ts +235 -0
  124. package/dist/chunks/index-nklPDKlC.d.ts +137 -0
  125. package/dist/chunks/index-qgZ5VGmc.d.ts +177 -0
  126. package/dist/chunks/index-tOodmT36.d.ts +129 -0
  127. package/dist/chunks/index-t_x6jj7l.d.ts +96 -0
  128. package/dist/chunks/input-adorn-C_EHML68.js +1 -0
  129. package/dist/chunks/input-group-iI7azfvE.js +1 -0
  130. package/dist/chunks/list-CMr-wB9d.js +1 -0
  131. package/dist/chunks/menu-CXUc-Gva.js +1 -0
  132. package/dist/chunks/modal-ByIj71Mq.js +1 -0
  133. package/dist/chunks/nav-BldxFo_B.js +1 -0
  134. package/dist/chunks/navbar-BwcsQuBk.js +1 -0
  135. package/dist/chunks/notification-DdqigVB1.js +1 -0
  136. package/dist/chunks/otp-input-CXe_wkII.js +1 -0
  137. package/dist/chunks/overlayPlacement-B7843a-Q.d.ts +6 -0
  138. package/dist/chunks/overlayPlacement-BtS90IVf.js +1 -0
  139. package/dist/chunks/pagination-BOpEAYW2.js +1 -0
  140. package/dist/chunks/password-strength-BfLiYiGj.js +1 -0
  141. package/dist/chunks/placeholder-pg95KELl.js +1 -0
  142. package/dist/chunks/polymorphic-CACPOv1_.js +1 -0
  143. package/dist/chunks/polymorphic-CVHbTHSN.d.ts +40 -0
  144. package/dist/chunks/popover-BpSfnZzk.js +1 -0
  145. package/dist/chunks/progress-DlrZ71aV.js +1 -0
  146. package/dist/chunks/radio-BV7Sq6D1.js +1 -0
  147. package/dist/chunks/range-input-BN3430j-.js +1 -0
  148. package/dist/chunks/renderFormCheck-BXBs6_ov.js +1 -0
  149. package/dist/chunks/renderFormCheck-CYWG-Rbt.d.ts +23 -0
  150. package/dist/chunks/renderFormField-fBEny6JV.d.ts +14 -0
  151. package/dist/chunks/renderFormField-wiaxvvLG.js +1 -0
  152. package/dist/chunks/renderMenuItemContent-CmqT3YUQ.js +1 -0
  153. package/dist/chunks/select-CclIIux8.js +1 -0
  154. package/dist/chunks/skeleton-CKq76sE_.js +1 -0
  155. package/dist/chunks/spacingClassName-DVhk8m3P.js +1 -0
  156. package/dist/chunks/spinner-BEq4PAlu.js +1 -0
  157. package/dist/chunks/stack-D3retZ-W.js +1 -0
  158. package/dist/chunks/static-table-D0M4oc_t.js +1 -0
  159. package/dist/chunks/stepper-CTa6e8uv.js +1 -0
  160. package/dist/chunks/switch-BmHpq4tL.js +1 -0
  161. package/dist/chunks/table-Fme9GbAR.js +1 -0
  162. package/dist/chunks/tableClassName-CZA2Bse8.js +1 -0
  163. package/dist/chunks/tabs-BnbMJM_b.js +1 -0
  164. package/dist/chunks/text-input-DD3d08Yf.js +1 -0
  165. package/dist/chunks/textarea-C0qQdCcu.js +1 -0
  166. package/dist/chunks/toast-BQhZ2pv5.js +1 -0
  167. package/dist/chunks/tooltip-DHtVAYUo.js +1 -0
  168. package/dist/chunks/triggerElement-BIqA4KqZ.js +1 -0
  169. package/dist/chunks/types-CS_40Txv.d.ts +34 -0
  170. package/dist/chunks/useButtonSemantics-CILM_lhi.js +1 -0
  171. package/dist/chunks/useDialogElement-BRIU60cT.js +1 -0
  172. package/dist/chunks/useDisabledAnchorGuard-Cz58UCXy.js +1 -0
  173. package/dist/chunks/useFloatingOverlay-CcmDZKMK.js +1 -0
  174. package/dist/chunks/useForkedRef-DVEfT-KI.js +1 -0
  175. package/dist/chunks/useFormField-BOqmBTC4.js +1 -0
  176. package/dist/chunks/useIsomorphicLayoutEffect-BbqRwuqn.js +1 -0
  177. package/dist/chunks/useToastRegionQueue-BH6bWZ73.js +1 -0
  178. package/dist/chunks/validationClassName-gRGs4KBm.js +1 -0
  179. package/dist/close-button.d.ts +2 -0
  180. package/dist/close-button.js +1 -0
  181. package/dist/collapse.d.ts +2 -0
  182. package/dist/collapse.js +1 -0
  183. package/dist/color-input.d.ts +2 -0
  184. package/dist/color-input.js +1 -0
  185. package/dist/combobox.d.ts +3 -0
  186. package/dist/combobox.js +1 -0
  187. package/dist/datagrid.d.ts +2 -0
  188. package/dist/datagrid.js +1 -0
  189. package/dist/datepicker.d.ts +2 -0
  190. package/dist/datepicker.js +1 -0
  191. package/dist/drawer.d.ts +2 -0
  192. package/dist/drawer.js +1 -0
  193. package/dist/file-input.d.ts +2 -0
  194. package/dist/file-input.js +1 -0
  195. package/dist/flex.d.ts +2 -0
  196. package/dist/flex.js +1 -0
  197. package/dist/floating-input.d.ts +2 -0
  198. package/dist/floating-input.js +1 -0
  199. package/dist/form-field.d.ts +2 -0
  200. package/dist/form-field.js +1 -0
  201. package/dist/form.d.ts +2 -0
  202. package/dist/form.js +1 -0
  203. package/dist/grid.d.ts +2 -0
  204. package/dist/grid.js +1 -0
  205. package/dist/icon.d.ts +4 -0
  206. package/dist/icon.js +1 -0
  207. package/dist/index.d.ts +72 -6354
  208. package/dist/index.js +1 -2
  209. package/dist/input-adorn.d.ts +2 -0
  210. package/dist/input-adorn.js +1 -0
  211. package/dist/input-group.d.ts +2 -0
  212. package/dist/input-group.js +1 -0
  213. package/dist/link.d.ts +3 -0
  214. package/dist/link.js +1 -0
  215. package/dist/list.d.ts +2 -0
  216. package/dist/list.js +1 -0
  217. package/dist/menu.d.ts +3 -0
  218. package/dist/menu.js +1 -0
  219. package/dist/modal.d.ts +2 -0
  220. package/dist/modal.js +1 -0
  221. package/dist/nav.d.ts +2 -0
  222. package/dist/nav.js +1 -0
  223. package/dist/navbar.d.ts +2 -0
  224. package/dist/navbar.js +1 -0
  225. package/dist/notification.d.ts +2 -0
  226. package/dist/notification.js +1 -0
  227. package/dist/otp-input.d.ts +2 -0
  228. package/dist/otp-input.js +1 -0
  229. package/dist/pagination.d.ts +2 -0
  230. package/dist/pagination.js +1 -0
  231. package/dist/password-strength.d.ts +2 -0
  232. package/dist/password-strength.js +1 -0
  233. package/dist/placeholder.d.ts +2 -0
  234. package/dist/placeholder.js +1 -0
  235. package/dist/popover.d.ts +2 -0
  236. package/dist/popover.js +1 -0
  237. package/dist/progress.d.ts +2 -0
  238. package/dist/progress.js +1 -0
  239. package/dist/radio.d.ts +2 -0
  240. package/dist/radio.js +1 -0
  241. package/dist/range-input.d.ts +2 -0
  242. package/dist/range-input.js +1 -0
  243. package/dist/select.d.ts +2 -0
  244. package/dist/select.js +1 -0
  245. package/dist/skeleton.d.ts +2 -0
  246. package/dist/skeleton.js +1 -0
  247. package/dist/spinner.d.ts +2 -0
  248. package/dist/spinner.js +1 -0
  249. package/dist/stack.d.ts +2 -0
  250. package/dist/stack.js +1 -0
  251. package/dist/static-table.d.ts +2 -0
  252. package/dist/static-table.js +1 -0
  253. package/dist/stepper.d.ts +2 -0
  254. package/dist/stepper.js +1 -0
  255. package/dist/style.css +1 -1
  256. package/dist/switch.d.ts +2 -0
  257. package/dist/switch.js +1 -0
  258. package/dist/table.d.ts +2 -0
  259. package/dist/table.js +1 -0
  260. package/dist/tabs.d.ts +2 -0
  261. package/dist/tabs.js +1 -0
  262. package/dist/text-input.d.ts +2 -0
  263. package/dist/text-input.js +1 -0
  264. package/dist/textarea.d.ts +2 -0
  265. package/dist/textarea.js +1 -0
  266. package/dist/toast.d.ts +2 -0
  267. package/dist/toast.js +1 -0
  268. package/dist/tooltip.d.ts +2 -0
  269. package/dist/tooltip.js +1 -0
  270. package/package.json +62 -4
  271. package/src/components/accordion/index.ts +4 -0
  272. package/src/components/autocomplete/index.ts +4 -0
  273. package/src/components/avatar/index.ts +4 -0
  274. package/src/components/badge/index.ts +4 -0
  275. package/src/components/breadcrumb/index.ts +4 -0
  276. package/src/components/button/index.ts +4 -0
  277. package/src/components/button-group/index.ts +4 -0
  278. package/src/components/calendar/index.ts +4 -0
  279. package/src/components/card/index.ts +4 -0
  280. package/src/components/carousel/CarouselControlButton.tsx +11 -4
  281. package/src/components/carousel/CarouselControlNext.tsx +6 -0
  282. package/src/components/carousel/CarouselControlPrev.tsx +6 -0
  283. package/src/components/carousel/CarouselPlayPause.tsx +27 -4
  284. package/src/components/carousel/index.ts +4 -0
  285. package/src/components/checkbox/Checkbox.tsx +19 -4
  286. package/src/components/checkbox/index.ts +4 -0
  287. package/src/components/chip/index.ts +4 -0
  288. package/src/components/chip-input/index.ts +4 -0
  289. package/src/components/close-button/index.ts +4 -0
  290. package/src/components/collapse/index.ts +4 -0
  291. package/src/components/color-input/index.ts +4 -0
  292. package/src/components/combobox/ComboboxListBox.tsx +2 -2
  293. package/src/components/combobox/index.ts +4 -0
  294. package/src/components/datagrid/index.ts +4 -0
  295. package/src/components/datepicker/index.ts +4 -0
  296. package/src/components/drawer/index.ts +8 -0
  297. package/src/components/file-input/index.ts +4 -0
  298. package/src/components/flex/index.ts +4 -0
  299. package/src/components/floating-input/index.ts +4 -0
  300. package/src/components/form/index.ts +4 -0
  301. package/src/components/form-field/index.ts +4 -0
  302. package/src/components/grid/index.ts +4 -0
  303. package/src/components/icon/Icon.tsx +69 -38
  304. package/src/components/icon/IconProvider.tsx +40 -0
  305. package/src/components/icon/index.ts +7 -0
  306. package/src/components/input-adorn/index.ts +4 -0
  307. package/src/components/input-group/index.ts +4 -0
  308. package/src/components/link/index.ts +4 -0
  309. package/src/components/list/index.ts +4 -0
  310. package/src/components/menu/index.ts +4 -0
  311. package/src/components/modal/index.ts +8 -0
  312. package/src/components/nav/index.ts +4 -0
  313. package/src/components/navbar/NavbarToggler.tsx +9 -3
  314. package/src/components/navbar/index.ts +4 -0
  315. package/src/components/notification/Notification.tsx +6 -5
  316. package/src/components/notification/index.ts +8 -0
  317. package/src/components/otp-input/index.ts +4 -0
  318. package/src/components/pagination/Pagination.tsx +16 -3
  319. package/src/components/pagination/index.ts +8 -0
  320. package/src/components/password-strength/index.ts +4 -0
  321. package/src/components/placeholder/index.ts +4 -0
  322. package/src/components/popover/index.ts +4 -0
  323. package/src/components/progress/index.ts +4 -0
  324. package/src/components/radio/Radio.tsx +13 -3
  325. package/src/components/radio/index.ts +4 -0
  326. package/src/components/range-input/index.ts +4 -0
  327. package/src/components/select/index.ts +4 -0
  328. package/src/components/skeleton/SkeletonLoader.tsx +13 -6
  329. package/src/components/skeleton/index.ts +4 -0
  330. package/src/components/spinner/index.ts +4 -0
  331. package/src/components/stack/index.ts +4 -0
  332. package/src/components/static-table/StaticTable.tsx +78 -0
  333. package/src/components/static-table/index.ts +8 -0
  334. package/src/components/stepper/index.ts +4 -0
  335. package/src/components/switch/Switch.tsx +16 -3
  336. package/src/components/switch/index.ts +4 -0
  337. package/src/components/table/Table.tsx +14 -22
  338. package/src/components/table/index.ts +4 -0
  339. package/src/components/tabs/index.ts +4 -0
  340. package/src/components/text-input/index.ts +4 -0
  341. package/src/components/textarea/index.ts +4 -0
  342. package/src/components/toast/Toast.tsx +2 -1
  343. package/src/components/toast/ToastHeader.tsx +4 -3
  344. package/src/components/toast/index.ts +8 -0
  345. package/src/components/tooltip/index.ts +4 -0
  346. package/src/hooks/useIconConfig.ts +6 -0
  347. package/src/index.ts +24 -4
  348. package/src/utils/iconConfig.ts +88 -0
  349. package/src/utils/iconSlot.tsx +41 -0
  350. package/src/utils/polymorphic.ts +49 -2
  351. package/src/utils/renderMenuItemContent.tsx +4 -9
  352. package/src/utils/slot.tsx +78 -0
  353. package/src/utils/tableClassName.ts +93 -0
@@ -0,0 +1,78 @@
1
+ import React, { forwardRef, ReactNode, TableHTMLAttributes } from 'react'
2
+
3
+ import { TableStyleProps, tableClassName, tableWrapperClassName } from '../../utils/tableClassName'
4
+
5
+ export interface StaticTableProps
6
+ extends TableStyleProps, Omit<TableHTMLAttributes<HTMLTableElement>, 'align' | 'color'> {
7
+ /**
8
+ * Content shown above the table, functioning as a heading for it.
9
+ */
10
+ caption?: ReactNode
11
+ /**
12
+ * The table's own markup — plain `<thead>`/`<tbody>`/`<tfoot>`/`<tr>`/`<th>`/`<td>` elements,
13
+ * rendered as-is.
14
+ */
15
+ children?: ReactNode
16
+ /**
17
+ * Convert rows into stacked label/value blocks below a container width, for tables with too
18
+ * many columns to read comfortably even with horizontal scrolling. `true` always stacks; a
19
+ * breakpoint name stacks only below it. Implies `responsive` when `responsive` isn't set
20
+ * separately. Unlike `Table`, which derives each cell's label from its column header, a static
21
+ * table has no collection to read labels from — give each `<td>` a `data-cell` attribute with
22
+ * the label to show before its value.
23
+ */
24
+ stacked?: TableStyleProps['stacked']
25
+ }
26
+
27
+ // A plain, server-renderable `<table>` with `Table`'s styling props and none of its behavior — no
28
+ // sorting, selection, or keyboard grid navigation, and no hooks, so it needs no client JavaScript
29
+ // at all. Imported from `@chassis-ui/react/static-table`, whose entry deliberately has no
30
+ // `'use client'` directive (see `RSC.md`). `forwardRef` is fine here: React Server Components
31
+ // render forwardRef components like any other function component (a ref just can't be passed
32
+ // from the server side).
33
+ export const StaticTable = forwardRef<HTMLTableElement, StaticTableProps>(
34
+ (
35
+ {
36
+ align,
37
+ bordered,
38
+ borderless,
39
+ caption,
40
+ children,
41
+ className,
42
+ color,
43
+ hover,
44
+ responsive,
45
+ sm,
46
+ stacked,
47
+ striped,
48
+ ...rest
49
+ },
50
+ ref
51
+ ) => {
52
+ const table = (
53
+ <table
54
+ {...rest}
55
+ className={tableClassName({
56
+ align,
57
+ bordered,
58
+ borderless,
59
+ className,
60
+ color,
61
+ hover,
62
+ sm,
63
+ stacked,
64
+ striped
65
+ })}
66
+ ref={ref}
67
+ >
68
+ {caption && <caption>{caption}</caption>}
69
+ {children}
70
+ </table>
71
+ )
72
+
73
+ const wrapperClassName = tableWrapperClassName({ responsive, stacked })
74
+ return wrapperClassName ? <div className={wrapperClassName}>{table}</div> : table
75
+ }
76
+ )
77
+
78
+ StaticTable.displayName = 'StaticTable'
@@ -0,0 +1,8 @@
1
+ // Deliberately no 'use client' directive — unlike every other component folder's barrel, this one
2
+ // is the server-safe entry point, `@chassis-ui/react/static-table`, and must stay importable from
3
+ // a React Server Component without creating a client boundary (see RSC.md). Nothing reachable from
4
+ // here may use hooks, context, or browser APIs; `scripts/check-rsc-directive.ts` fails the build if
5
+ // the built entry ever gains a directive. For the same reason it skips the
6
+ // `suppressFocusRingGlobally` import the other barrels carry — there's no client module to run it.
7
+ export { StaticTable } from './StaticTable'
8
+ export type { StaticTableProps } from './StaticTable'
@@ -1,3 +1,7 @@
1
+ 'use client'
2
+
3
+ import '../../utils/suppressFocusRingGlobally'
4
+
1
5
  export { Stepper } from './Stepper'
2
6
  export type { StepperProps, StepperItemDef } from './Stepper'
3
7
  export { StepperItem } from './StepperItem'
@@ -39,6 +39,11 @@ export interface SwitchProps extends Omit<
39
39
  isSelected?: boolean
40
40
  /**
41
41
  * The element represents a caption for a component.
42
+ *
43
+ * Children are accepted as an alias for this prop — `label` wins when both are given.
44
+ * react-aria, which backs this component, calls the same thing `children`; this package renames
45
+ * it to `label`, and honouring both means the shape React developers reach for first still
46
+ * names the control instead of silently producing an unlabelled one.
42
47
  */
43
48
  label?: ReactNode
44
49
  /**
@@ -135,6 +140,7 @@ const SwitchCheckbox = forwardRef<HTMLInputElement, SwitchVariantProps>(
135
140
  (
136
141
  {
137
142
  className,
143
+ children,
138
144
  color,
139
145
  defaultSelected,
140
146
  disabled,
@@ -151,6 +157,9 @@ const SwitchCheckbox = forwardRef<HTMLInputElement, SwitchVariantProps>(
151
157
  ) => {
152
158
  const inputRef = useRef<HTMLInputElement>(null)
153
159
  const forkedRef = useForkedRef(ref, inputRef)
160
+ // `label` is this package's name for what react-aria calls `children`. Accept either, so the
161
+ // shape React developers reach for first names the control instead of vanishing.
162
+ const resolvedLabel = label ?? children
154
163
 
155
164
  const toggleState = useToggleState({
156
165
  defaultSelected,
@@ -162,7 +171,7 @@ const SwitchCheckbox = forwardRef<HTMLInputElement, SwitchVariantProps>(
162
171
  const { inputProps: switchProps } = useSwitch(
163
172
  {
164
173
  ...rest,
165
- children: label,
174
+ children: resolvedLabel,
166
175
  isDisabled: disabled,
167
176
  isInvalid: invalid,
168
177
  value: rest.value as string | undefined
@@ -178,7 +187,7 @@ const SwitchCheckbox = forwardRef<HTMLInputElement, SwitchVariantProps>(
178
187
  id,
179
188
  inputProps: switchProps,
180
189
  invalid,
181
- label,
190
+ label: resolvedLabel,
182
191
  size,
183
192
  valid
184
193
  })
@@ -192,6 +201,7 @@ SwitchCheckbox.displayName = 'SwitchCheckbox'
192
201
  const SwitchRadio = forwardRef<HTMLInputElement, SwitchVariantProps>(
193
202
  (
194
203
  {
204
+ children,
195
205
  className,
196
206
  color,
197
207
  defaultSelected,
@@ -209,6 +219,9 @@ const SwitchRadio = forwardRef<HTMLInputElement, SwitchVariantProps>(
209
219
  ) => {
210
220
  const inputRef = useRef<HTMLInputElement>(null)
211
221
  const forkedRef = useForkedRef(ref, inputRef)
222
+ // `label` is this package's name for what react-aria calls `children`. Accept either, so the
223
+ // shape React developers reach for first names the control instead of vanishing.
224
+ const resolvedLabel = label ?? children
212
225
 
213
226
  const radioProps = {
214
227
  ...rest,
@@ -230,7 +243,7 @@ const SwitchRadio = forwardRef<HTMLInputElement, SwitchVariantProps>(
230
243
  id,
231
244
  inputProps: radioProps,
232
245
  invalid,
233
- label,
246
+ label: resolvedLabel,
234
247
  size,
235
248
  valid
236
249
  })
@@ -1,2 +1,6 @@
1
+ 'use client'
2
+
3
+ import '../../utils/suppressFocusRingGlobally'
4
+
1
5
  export { Switch } from './Switch'
2
6
  export type { SwitchProps } from './Switch'
@@ -25,6 +25,7 @@ import {
25
25
 
26
26
  import { useForkedRef } from '../../hooks/useForkedRef'
27
27
  import { ContextColor } from '../../types'
28
+ import { tableClassName, tableWrapperClassName } from '../../utils/tableClassName'
28
29
  import './Table.css'
29
30
 
30
31
  // `GridNode<T>` (from `@react-types/shared`) isn't re-exported by either package's public
@@ -179,24 +180,20 @@ const TableInner = <T extends object>(
179
180
  internalRef
180
181
  )
181
182
 
182
- const _className = classNames(
183
- 'table',
183
+ const _className = tableClassName({
184
+ align,
185
+ bordered,
186
+ borderless,
187
+ className,
184
188
  color,
185
- {
186
- [`align-${align}`]: align,
187
- bordered,
188
- borderless,
189
- hoverable: hover,
190
- sm,
191
- stacked: stacked === true,
192
- striped
193
- },
194
- typeof stacked === 'string' ? `max-${stacked}:stacked` : undefined,
195
- className
196
- )
189
+ hover,
190
+ sm,
191
+ stacked,
192
+ striped
193
+ })
197
194
 
198
195
  const tableEl = (
199
- <table {...gridProps} className={_className || undefined} ref={ref}>
196
+ <table {...gridProps} className={_className} ref={ref}>
200
197
  {caption && <caption>{caption}</caption>}
201
198
  <TableRowGroup className={children[0].props.className} type="thead">
202
199
  {state.collection.headerRows.map((headerRow) => (
@@ -228,13 +225,8 @@ const TableInner = <T extends object>(
228
225
  </table>
229
226
  )
230
227
 
231
- if (!responsive && !stacked) return tableEl
232
-
233
- const wrapperClassName = responsive
234
- ? typeof responsive === 'boolean'
235
- ? 'table-responsive'
236
- : `max-${responsive}:table-responsive`
237
- : 'table-responsive'
228
+ const wrapperClassName = tableWrapperClassName({ responsive, stacked })
229
+ if (!wrapperClassName) return tableEl
238
230
 
239
231
  return <div className={wrapperClassName}>{tableEl}</div>
240
232
  }
@@ -1,3 +1,7 @@
1
+ 'use client'
2
+
3
+ import '../../utils/suppressFocusRingGlobally'
4
+
1
5
  export { Table } from './Table'
2
6
  export type { TableProps } from './Table'
3
7
  export { TableBody } from './TableBody'
@@ -1,3 +1,7 @@
1
+ 'use client'
2
+
3
+ import '../../utils/suppressFocusRingGlobally'
4
+
1
5
  export { Tabs } from './Tabs'
2
6
  export type { TabsProps } from './Tabs'
3
7
  export { Tab } from './Tab'
@@ -1,2 +1,6 @@
1
+ 'use client'
2
+
3
+ import '../../utils/suppressFocusRingGlobally'
4
+
1
5
  export { TextInput } from './TextInput'
2
6
  export type { TextInputProps } from './TextInput'
@@ -1,2 +1,6 @@
1
+ 'use client'
2
+
3
+ import '../../utils/suppressFocusRingGlobally'
4
+
1
5
  export { Textarea } from './Textarea'
2
6
  export type { TextareaProps } from './Textarea'
@@ -51,7 +51,8 @@ export interface ToastProps extends Omit<HTMLAttributes<HTMLDivElement>, 'title'
51
51
  */
52
52
  footer?: ReactNode | ((close: () => void) => ReactNode)
53
53
  /**
54
- * Leading icon for the header. A string is rendered as `<ToastIcon name={icon} />`; pass
54
+ * Leading icon for the header. A string is an icon name, rendered like
55
+ * `<ToastIcon name={icon} />` (or by `IconProvider`'s `component`); pass
55
56
  * any other node for a fully custom icon (typically a logo or avatar). Shorthand for
56
57
  * `ToastHeader`'s `icon` prop; hidden from assistive technology by default, since it
57
58
  * duplicates `title` visually.
@@ -8,7 +8,7 @@ import {
8
8
  PolymorphicComponentProps,
9
9
  PolymorphicRef
10
10
  } from '../../utils/polymorphic'
11
- import { ToastIcon } from './ToastIcon'
11
+ import { ResolvedIcon } from '../../utils/iconSlot'
12
12
 
13
13
  type ToastHeaderOwnProps<C extends ElementType> = {
14
14
  /**
@@ -33,7 +33,8 @@ type ToastHeaderOwnProps<C extends ElementType> = {
33
33
  */
34
34
  component?: C
35
35
  /**
36
- * Leading icon. A string is rendered as `<ToastIcon name={icon} />` and hidden from
36
+ * Leading icon. A string is an icon name, rendered like `<ToastIcon name={icon} />` (or by
37
+ * `IconProvider`'s `component`) and hidden from
37
38
  * assistive technology by default, since it duplicates the heading visually. Pass any other
38
39
  * node for a fully custom icon (typically a logo or avatar) — a custom node is left as-is,
39
40
  * since it may carry its own meaningful accessible name (e.g. an avatar's `alt` text).
@@ -82,7 +83,7 @@ function ToastHeaderRender<C extends ElementType = 'div'>(
82
83
  {icon != null &&
83
84
  (typeof icon === 'string' ? (
84
85
  <span aria-hidden="true" className="me-sm">
85
- <ToastIcon name={icon} />
86
+ <ResolvedIcon value={icon} className="toast-icon" />
86
87
  </span>
87
88
  ) : (
88
89
  <span className="me-sm">{icon}</span>
@@ -1,3 +1,7 @@
1
+ 'use client'
2
+
3
+ import '../../utils/suppressFocusRingGlobally'
4
+
1
5
  export { Toast } from './Toast'
2
6
  export type { ToastProps } from './Toast'
3
7
  export { ToastBody } from './ToastBody'
@@ -16,3 +20,7 @@ export { Toaster } from './Toaster'
16
20
  export type { ToasterProps } from './Toaster'
17
21
  export { addToast, closeToast, toastQueue } from './toastQueue'
18
22
  export type { ToastContent } from './toastQueue'
23
+ // Also exported from the package root; repeated here so this folder's subpath entry
24
+ // (`@chassis-ui/react/<folder>`) covers the whole family without reaching back to the root.
25
+ export { useToast } from '../../hooks/useToast'
26
+ export type { UseToastResult } from '../../hooks/useToast'
@@ -1,2 +1,6 @@
1
+ 'use client'
2
+
3
+ import '../../utils/suppressFocusRingGlobally'
4
+
1
5
  export { Tooltip } from './Tooltip'
2
6
  export type { TooltipProps } from './Tooltip'
@@ -0,0 +1,6 @@
1
+ import { useContext } from 'react'
2
+
3
+ import { IconConfig, IconContext } from '../utils/iconConfig'
4
+
5
+ // The nearest `IconProvider`'s settings, merged with every provider above it; empty outside one.
6
+ export const useIconConfig = (): IconConfig => useContext(IconContext)
package/src/index.ts CHANGED
@@ -2,8 +2,9 @@
2
2
 
3
3
  // Side-effect only: installs the single document-level pointerdown listener that works around the
4
4
  // browser's `:focus-visible` first-click heuristic misfire — see the module's own comment. Needs to
5
- // run once wherever this package is used, not per-component, so it's imported here rather than
6
- // from any individual component.
5
+ // run once wherever this package is used, not per-component, so it's imported by entry points
6
+ // (here, and every component folder's `index.ts` barrel, each of which is also a subpath entry)
7
+ // rather than from any individual component.
7
8
  import './utils/suppressFocusRingGlobally'
8
9
 
9
10
  import { Accordion, AccordionBody, AccordionHeader, AccordionItem } from './components/accordion'
@@ -91,7 +92,7 @@ import { Select } from './components/select'
91
92
  import { Switch } from './components/switch'
92
93
  import { TextInput } from './components/text-input'
93
94
  import { Textarea } from './components/textarea'
94
- import { Icon } from './components/icon'
95
+ import { Icon, IconProvider } from './components/icon'
95
96
  import { Placeholder } from './components/placeholder'
96
97
  import { Link } from './components/link'
97
98
  import { List, ListItem } from './components/list'
@@ -104,6 +105,7 @@ import { Progress, ProgressBar } from './components/progress'
104
105
  import { Drawer, DrawerBody, DrawerFooter, DrawerHeader, DrawerTitle } from './components/drawer'
105
106
  import { Skeleton, SkeletonLoader } from './components/skeleton'
106
107
  import { Spinner } from './components/spinner'
108
+ import { StaticTable } from './components/static-table'
107
109
  import { Stepper, StepperItem } from './components/stepper'
108
110
  import { Table, TableBody, TableCell, TableColumn, TableHeader, TableRow } from './components/table'
109
111
  import { Tabs, Tab, TabList, TabPanel } from './components/tabs'
@@ -224,6 +226,7 @@ export {
224
226
  FormHelp,
225
227
  FormLabel,
226
228
  Icon,
229
+ IconProvider,
227
230
  Placeholder,
228
231
  InputGroup,
229
232
  InputGroupAddon,
@@ -265,6 +268,7 @@ export {
265
268
  Skeleton,
266
269
  SkeletonLoader,
267
270
  Spinner,
271
+ StaticTable,
268
272
  Stepper,
269
273
  StepperItem,
270
274
  Switch,
@@ -367,6 +371,15 @@ export type { CloseButtonProps } from './components/close-button'
367
371
  export type { CollapseProps } from './components/collapse'
368
372
  export type { ColorInputProps } from './components/color-input'
369
373
  export type { ComboboxGroupProps, ComboboxItemProps, ComboboxProps } from './components/combobox'
374
+ export type {
375
+ DataGridBodyProps,
376
+ DataGridCellProps,
377
+ DataGridColumnProps,
378
+ DataGridHeaderProps,
379
+ DataGridProps,
380
+ DataGridRowProps,
381
+ DataGridSelectionCellProps
382
+ } from './components/datagrid'
370
383
  export type {
371
384
  DatePickerMultipleProps,
372
385
  DatePickerProps,
@@ -393,7 +406,13 @@ export type {
393
406
  GridProps,
394
407
  RowProps
395
408
  } from './components/grid'
396
- export type { IconProps } from './components/icon'
409
+ export type {
410
+ IconComponentProps,
411
+ IconKey,
412
+ IconProps,
413
+ IconProviderProps,
414
+ IconValue
415
+ } from './components/icon'
397
416
  export type { InputAdornProps } from './components/input-adorn'
398
417
  export type { InputGroupAddonProps, InputGroupProps } from './components/input-group'
399
418
  export type { LinkProps } from './components/link'
@@ -449,6 +468,7 @@ export type { RangeInputProps } from './components/range-input'
449
468
  export type { SelectOptionDef, SelectProps } from './components/select'
450
469
  export type { SkeletonLoaderProps, SkeletonProps } from './components/skeleton'
451
470
  export type { SpinnerProps } from './components/spinner'
471
+ export type { StaticTableProps } from './components/static-table'
452
472
  export type { StackProps } from './components/stack'
453
473
  export type { StepperItemDef, StepperItemProps, StepperProps } from './components/stepper'
454
474
  export type { SwitchProps } from './components/switch'
@@ -0,0 +1,88 @@
1
+ import { ComponentType, createContext, ReactElement } from 'react'
2
+
3
+ /**
4
+ * The icons this library's own components draw, by purpose rather than by icon name — so a
5
+ * consumer can map each one onto any icon set (see `IconProvider`'s `icons`).
6
+ */
7
+ export type IconKey = 'check' | 'previous' | 'next' | 'menu' | 'play' | 'pause'
8
+
9
+ /**
10
+ * An icon given to `IconProvider`'s `icons` or to a component's icon prop: a string is an icon
11
+ * name, rendered by `IconProvider`'s `component` (or the built-in `Icon`); an element is rendered
12
+ * as-is, with the component's own class names merged onto it.
13
+ */
14
+ export type IconValue = string | ReactElement
15
+
16
+ /**
17
+ * Props `IconProvider`'s `component` receives for every icon name it's asked to render.
18
+ */
19
+ export interface IconComponentProps {
20
+ /**
21
+ * The icon name — an `IconValue` string, or `IconProvider`'s default for that icon.
22
+ */
23
+ name: string
24
+ /**
25
+ * The class names the rendering component needs on the icon (e.g. `menu-item-check`,
26
+ * `directional-icon`) for chassis-css to position and flip it.
27
+ */
28
+ className?: string
29
+ [prop: string]: unknown
30
+ }
31
+
32
+ export interface IconConfig {
33
+ /**
34
+ * Class names added to every `Icon`, alongside its own `icon` class.
35
+ */
36
+ className?: string
37
+ /**
38
+ * Replaces the built-in `Icon` for every icon this library's components render by name — the
39
+ * strings in `icons` and their defaults, and a string `icon` on `Toast`/`Notification`. A
40
+ * component reference can't be passed from a React Server Component, so set this in a
41
+ * `'use client'` module.
42
+ */
43
+ component?: ComponentType<IconComponentProps>
44
+ /**
45
+ * Render `Icon` as an icon-font glyph instead of an SVG sprite reference, unless an `Icon` sets
46
+ * `font` itself. Needs the icon font's stylesheet loaded.
47
+ */
48
+ font?: boolean
49
+ /**
50
+ * Class-name prefix of the icon font's glyphs: an icon named `check-solid` renders as
51
+ * `{fontPrefix}check-solid`.
52
+ *
53
+ * @default 'cx-'
54
+ */
55
+ fontPrefix?: string
56
+ /**
57
+ * The icon to render for each of the library's own icons, by purpose. Unset ones keep their
58
+ * defaults (`check-solid`, `chevron-left-outline`, `chevron-right-outline`, `bars-outline`,
59
+ * `play-solid`, `pause-solid`).
60
+ */
61
+ icons?: Partial<Record<IconKey, IconValue>>
62
+ /**
63
+ * URL of the SVG sprite `Icon` references, e.g. `/static/icons/chassis-icons.svg`. Leave empty
64
+ * (the default) when the sprite is embedded in the page, so icons render as `href="#name"`.
65
+ * Browsers don't load an external sprite from another origin.
66
+ *
67
+ * @default ''
68
+ */
69
+ sprite?: string
70
+ }
71
+
72
+ // The chassis-icons names this library used before its icons became configurable. Both
73
+ // previous/next consumers (Pagination, Carousel) now share the outline chevrons — Pagination used
74
+ // the solid ones.
75
+ export const DEFAULT_ICONS: Record<IconKey, string> = {
76
+ check: 'check-solid',
77
+ previous: 'chevron-left-outline',
78
+ next: 'chevron-right-outline',
79
+ menu: 'bars-outline',
80
+ play: 'play-solid',
81
+ pause: 'pause-solid'
82
+ }
83
+
84
+ export const DEFAULT_FONT_PREFIX = 'cx-'
85
+
86
+ // Lives in `utils/` rather than `components/icon/` because it's read outside that folder too —
87
+ // by `IconSlot` (`./iconSlot.tsx`), which every icon-drawing component renders through.
88
+ export const IconContext = createContext<IconConfig>({})
@@ -0,0 +1,41 @@
1
+ import React, { cloneElement, ReactElement } from 'react'
2
+ import { mergeProps } from 'react-aria'
3
+
4
+ import { Icon } from '../components/icon/Icon'
5
+ import { useIconConfig } from '../hooks/useIconConfig'
6
+ import { DEFAULT_ICONS, IconKey, IconValue } from './iconConfig'
7
+
8
+ // Every icon this library's own components draw goes through here, never through `<Icon>`
9
+ // directly, so a consumer can swap in their own icons (`IconProvider`'s `icons`/`component`, or a
10
+ // component's own icon prop). The rendering component passes the class names chassis-css hooks
11
+ // onto (`menu-item-check` positions the check, `navbar-toggler-icon` sizes and colors it,
12
+ // `carousel-icon-play`/`-pause` are toggled by state, `directional-icon` flips in RTL); those are
13
+ // merged onto whatever icon ends up rendered, so a custom icon lands in the same place a built-in
14
+ // one would. `aria-hidden` defaults on: each of these icons sits beside its own visible or
15
+ // visually-hidden label.
16
+ //
17
+ // A custom *element* deliberately doesn't get the `icon` class itself: chassis-css's `.icon` sets
18
+ // `fill`, which would paint over an outline icon set's `fill="none"` (Lucide, Heroicons outline,
19
+ // ...). It keeps its own size and color — `currentColor` icons still follow the control's text.
20
+ type IconRenderProps = { className?: string } & Record<string, unknown>
21
+
22
+ export function ResolvedIcon({ value, ...props }: IconRenderProps & { value: IconValue }) {
23
+ const { component: Component } = useIconConfig()
24
+ const iconProps = { 'aria-hidden': true, ...props }
25
+
26
+ if (typeof value !== 'string') {
27
+ const element = value as ReactElement<Record<string, unknown>>
28
+ return cloneElement(element, mergeProps(iconProps, element.props))
29
+ }
30
+ if (Component) return <Component name={value} {...iconProps} />
31
+ return <Icon name={value} {...iconProps} />
32
+ }
33
+
34
+ export function IconSlot({
35
+ icon,
36
+ override,
37
+ ...props
38
+ }: IconRenderProps & { icon: IconKey; override?: IconValue }) {
39
+ const { icons } = useIconConfig()
40
+ return <ResolvedIcon value={override ?? icons?.[icon] ?? DEFAULT_ICONS[icon]} {...props} />
41
+ }
@@ -1,12 +1,16 @@
1
1
  import {
2
2
  ComponentPropsWithoutRef,
3
3
  ComponentPropsWithRef,
4
+ createElement,
4
5
  ElementType,
5
6
  ForwardRefRenderFunction,
6
7
  forwardRef,
7
8
  Ref
8
9
  } from 'react'
9
10
 
11
+ import { devWarning } from './devWarning'
12
+ import { getSlotChild, Slot, SlotProvider } from './slot'
13
+
10
14
  // Ref type inferred from a polymorphic component's currently-selected `component` element type.
11
15
  export type PolymorphicRef<C extends ElementType> = ComponentPropsWithRef<C>['ref']
12
16
 
@@ -26,6 +30,21 @@ export type PolymorphicRef<C extends ElementType> = ComponentPropsWithRef<C>['re
26
30
  export type PolymorphicRefWithFallback<C extends ElementType, Fallback extends HTMLElement> =
27
31
  PolymorphicRef<C> | Ref<Fallback>
28
32
 
33
+ /**
34
+ * The `asChild` prop every polymorphic component accepts alongside `component` — see
35
+ * `createPolymorphicComponent` below for how it's implemented once for all of them.
36
+ */
37
+ export interface AsChildProps {
38
+ /**
39
+ * Render the single child element in place of this component's own element, with this
40
+ * component's classes, props and ref merged onto it: `<Button asChild><Link href="/login">Log
41
+ * in</Link></Button>`. The alternative to `component` for React Server Components — an element
42
+ * can be passed from the server to this package's client components, a component reference
43
+ * (`component={Link}`) can't.
44
+ */
45
+ asChild?: boolean
46
+ }
47
+
29
48
  /**
30
49
  * Props for a polymorphic component: `OwnProps` (which must declare `component?: C`) plus
31
50
  * whatever props `C` itself accepts, minus any name already claimed by `OwnProps` so the two
@@ -33,7 +52,8 @@ export type PolymorphicRefWithFallback<C extends ElementType, Fallback extends H
33
52
  * type-checking/autocomplete for that component's own props at the call site.
34
53
  */
35
54
  export type PolymorphicComponentProps<C extends ElementType, OwnProps extends object> = OwnProps &
36
- Omit<ComponentPropsWithoutRef<C>, keyof OwnProps>
55
+ AsChildProps &
56
+ Omit<ComponentPropsWithoutRef<C>, keyof OwnProps | keyof AsChildProps>
37
57
 
38
58
  /**
39
59
  * Wraps a polymorphic component's render function in `forwardRef` and stamps `displayName` — the
@@ -41,13 +61,40 @@ export type PolymorphicComponentProps<C extends ElementType, OwnProps extends ob
41
61
  * fully generic component type (e.g. `ButtonComponent`) that `forwardRef`'s own return type can't
42
62
  * express, since `forwardRef` only accepts a non-generic render function — the caller still casts
43
63
  * the render function to a concrete `Element`-typed instance before passing it in here.
64
+ *
65
+ * Also implements `asChild` for every polymorphic component at once (#23): the render function
66
+ * gets `component={Slot}` and the child element's own children, so it computes its classes,
67
+ * props and ref exactly as it would for any component reference (`component={Link}`) — `Slot`
68
+ * then clones the caller's child element with all of that merged on (see `./slot`). No render
69
+ * function needs to know `asChild` exists.
44
70
  */
45
71
  export function createPolymorphicComponent<T>(
46
72
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
47
73
  render: ForwardRefRenderFunction<Element, any>,
48
74
  displayName: string
49
75
  ): T {
50
- const Component = forwardRef(render) as unknown as T & { displayName?: string }
76
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
77
+ const Component = forwardRef<Element, any>(({ asChild, ...props }, ref) => {
78
+ const child = asChild ? getSlotChild(props.children, displayName) : null
79
+ if (!child) return render(props, ref)
80
+
81
+ devWarning(
82
+ props.component !== undefined,
83
+ `${displayName}: both \`asChild\` and \`component\` were passed; \`asChild\` wins and ` +
84
+ `\`component\` is ignored.`
85
+ )
86
+
87
+ return createElement(
88
+ SlotProvider,
89
+ { value: child },
90
+ render(
91
+ { ...props, component: Slot, children: (child.props as PropsWithChildren).children },
92
+ ref
93
+ )
94
+ )
95
+ }) as unknown as T & { displayName?: string }
51
96
  Component.displayName = displayName
52
97
  return Component
53
98
  }
99
+
100
+ type PropsWithChildren = { children?: unknown }