@hypoth-ui/cli 0.0.1 → 0.1.1

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 (375) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +19 -115
  3. package/dist/{add-PDBC4JTE.js → add-V5PW73GC.js} +29 -17
  4. package/dist/{chunk-5LTQ2XVL.js → chunk-27CLUUVC.js} +0 -2
  5. package/dist/{chunk-YPKFYE45.js → chunk-NWIRSZUQ.js} +6 -13
  6. package/dist/{chunk-GJ6JOQ3Q.js → chunk-PBK72SJJ.js} +1 -1
  7. package/dist/{diff-BQEXG7HU.js → diff-776UATCA.js} +2 -2
  8. package/dist/index.js +5 -5
  9. package/dist/{init-7AZXYAPJ.js → init-GDU2PW7K.js} +10 -13
  10. package/dist/{list-X6ZLM2NQ.js → list-XDP5I537.js} +3 -3
  11. package/package.json +16 -12
  12. package/registry/components.json +1820 -206
  13. package/templates/accordion/index.tsx +266 -0
  14. package/templates/accordion/wc/accordion-content.ts +113 -0
  15. package/templates/accordion/wc/accordion-item.ts +111 -0
  16. package/templates/accordion/wc/accordion-trigger.ts +105 -0
  17. package/templates/accordion/wc/accordion.ts +213 -0
  18. package/templates/accordion/wc/index.ts +12 -0
  19. package/templates/alert/index.tsx +177 -0
  20. package/templates/alert/wc/alert.ts +167 -0
  21. package/templates/alert/wc/index.ts +1 -0
  22. package/templates/alert-dialog/index.tsx +360 -0
  23. package/templates/alert-dialog/wc/alert-dialog-action.ts +43 -0
  24. package/templates/alert-dialog/wc/alert-dialog-cancel.ts +43 -0
  25. package/templates/alert-dialog/wc/alert-dialog-content.ts +42 -0
  26. package/templates/alert-dialog/wc/alert-dialog-description.ts +34 -0
  27. package/templates/alert-dialog/wc/alert-dialog-footer.ts +25 -0
  28. package/templates/alert-dialog/wc/alert-dialog-header.ts +25 -0
  29. package/templates/alert-dialog/wc/alert-dialog-title.ts +34 -0
  30. package/templates/alert-dialog/wc/alert-dialog-trigger.ts +46 -0
  31. package/templates/alert-dialog/wc/alert-dialog.ts +302 -0
  32. package/templates/alert-dialog/wc/index.ts +13 -0
  33. package/templates/aspect-ratio/index.tsx +50 -0
  34. package/templates/aspect-ratio/wc/aspect-ratio.ts +78 -0
  35. package/templates/aspect-ratio/wc/index.ts +5 -0
  36. package/templates/avatar/avatar-group.tsx +88 -0
  37. package/templates/avatar/avatar.tsx +124 -0
  38. package/templates/avatar/index.tsx +33 -0
  39. package/templates/avatar/wc/avatar-group.ts +112 -0
  40. package/templates/avatar/wc/avatar.ts +184 -0
  41. package/templates/avatar/wc/index.ts +5 -0
  42. package/templates/badge/index.tsx +140 -0
  43. package/templates/badge/wc/badge.ts +119 -0
  44. package/templates/badge/wc/index.ts +9 -0
  45. package/templates/breadcrumb/index.tsx +157 -0
  46. package/templates/breadcrumb/wc/breadcrumb-item.ts +30 -0
  47. package/templates/breadcrumb/wc/breadcrumb-link.ts +70 -0
  48. package/templates/breadcrumb/wc/breadcrumb-list.ts +30 -0
  49. package/templates/breadcrumb/wc/breadcrumb-page.ts +32 -0
  50. package/templates/breadcrumb/wc/breadcrumb-separator.ts +31 -0
  51. package/templates/breadcrumb/wc/breadcrumb.ts +55 -0
  52. package/templates/breadcrumb/wc/index.ts +10 -0
  53. package/templates/button/button.tsx +119 -0
  54. package/templates/button/index.ts +1 -0
  55. package/templates/button/wc/button.ts +169 -0
  56. package/templates/calendar/index.tsx +149 -0
  57. package/templates/calendar/wc/calendar.ts +316 -0
  58. package/templates/calendar/wc/index.ts +4 -0
  59. package/templates/card/index.tsx +108 -0
  60. package/templates/card/wc/card-content.ts +25 -0
  61. package/templates/card/wc/card-footer.ts +25 -0
  62. package/templates/card/wc/card-header.ts +25 -0
  63. package/templates/card/wc/card.ts +43 -0
  64. package/templates/card/wc/index.ts +8 -0
  65. package/templates/checkbox/checkbox.tsx +85 -0
  66. package/templates/checkbox/wc/checkbox.ts +247 -0
  67. package/templates/collapsible/index.tsx +172 -0
  68. package/templates/collapsible/wc/collapsible-content.ts +97 -0
  69. package/templates/collapsible/wc/collapsible-trigger.ts +39 -0
  70. package/templates/collapsible/wc/collapsible.ts +143 -0
  71. package/templates/collapsible/wc/index.ts +7 -0
  72. package/templates/combobox/combobox-content.tsx +141 -0
  73. package/templates/combobox/combobox-context.ts +36 -0
  74. package/templates/combobox/combobox-empty.tsx +38 -0
  75. package/templates/combobox/combobox-input.tsx +159 -0
  76. package/templates/combobox/combobox-loading.tsx +38 -0
  77. package/templates/combobox/combobox-option.tsx +99 -0
  78. package/templates/combobox/combobox-root.tsx +207 -0
  79. package/templates/combobox/combobox-tag.tsx +62 -0
  80. package/templates/combobox/index.ts +62 -0
  81. package/templates/combobox/wc/combobox-content.ts +97 -0
  82. package/templates/combobox/wc/combobox-input.ts +134 -0
  83. package/templates/combobox/wc/combobox-option.ts +111 -0
  84. package/templates/combobox/wc/combobox-tag.ts +103 -0
  85. package/templates/combobox/wc/combobox.ts +981 -0
  86. package/templates/combobox/wc/index.ts +5 -0
  87. package/templates/command/index.tsx +279 -0
  88. package/templates/command/wc/command-empty.ts +24 -0
  89. package/templates/command/wc/command-group.ts +60 -0
  90. package/templates/command/wc/command-input.ts +136 -0
  91. package/templates/command/wc/command-item.ts +78 -0
  92. package/templates/command/wc/command-list.ts +103 -0
  93. package/templates/command/wc/command-loading.ts +24 -0
  94. package/templates/command/wc/command-separator.ts +23 -0
  95. package/templates/command/wc/command.ts +176 -0
  96. package/templates/context-menu/index.tsx +262 -0
  97. package/templates/context-menu/wc/context-menu-content.ts +41 -0
  98. package/templates/context-menu/wc/context-menu-item.ts +83 -0
  99. package/templates/context-menu/wc/context-menu-label.ts +30 -0
  100. package/templates/context-menu/wc/context-menu-separator.ts +28 -0
  101. package/templates/context-menu/wc/context-menu.ts +324 -0
  102. package/templates/context-menu/wc/index.ts +9 -0
  103. package/templates/data-table/index.tsx +263 -0
  104. package/templates/data-table/wc/data-table.ts +405 -0
  105. package/templates/data-table/wc/index.ts +10 -0
  106. package/templates/date-picker/date-picker-calendar.tsx +352 -0
  107. package/templates/date-picker/date-picker-content.tsx +121 -0
  108. package/templates/date-picker/date-picker-context.ts +46 -0
  109. package/templates/date-picker/date-picker-root.tsx +201 -0
  110. package/templates/date-picker/date-picker-trigger.tsx +95 -0
  111. package/templates/date-picker/index.ts +44 -0
  112. package/templates/date-picker/wc/date-picker-calendar.ts +457 -0
  113. package/templates/date-picker/wc/date-picker.ts +592 -0
  114. package/templates/date-picker/wc/date-utils.ts +467 -0
  115. package/templates/date-picker/wc/index.ts +3 -0
  116. package/templates/dialog/dialog-close.tsx +57 -0
  117. package/templates/dialog/dialog-content.tsx +106 -0
  118. package/templates/dialog/dialog-context.ts +24 -0
  119. package/templates/dialog/dialog-description.tsx +51 -0
  120. package/templates/dialog/dialog-root.tsx +104 -0
  121. package/templates/dialog/dialog-title.tsx +38 -0
  122. package/templates/dialog/dialog-trigger.tsx +94 -0
  123. package/templates/dialog/index.ts +52 -0
  124. package/templates/dialog/wc/dialog-content.ts +59 -0
  125. package/templates/dialog/wc/dialog-description.ts +58 -0
  126. package/templates/dialog/wc/dialog-title.ts +56 -0
  127. package/templates/dialog/wc/dialog.ts +411 -0
  128. package/templates/drawer/index.tsx +263 -0
  129. package/templates/drawer/wc/drawer-content.ts +150 -0
  130. package/templates/drawer/wc/drawer-description.ts +34 -0
  131. package/templates/drawer/wc/drawer-footer.ts +25 -0
  132. package/templates/drawer/wc/drawer-header.ts +25 -0
  133. package/templates/drawer/wc/drawer-title.ts +34 -0
  134. package/templates/drawer/wc/drawer.ts +348 -0
  135. package/templates/drawer/wc/index.ts +10 -0
  136. package/templates/dropdown-menu/index.tsx +454 -0
  137. package/templates/dropdown-menu/wc/dropdown-menu-checkbox-item.ts +93 -0
  138. package/templates/dropdown-menu/wc/dropdown-menu-content.ts +43 -0
  139. package/templates/dropdown-menu/wc/dropdown-menu-item.ts +85 -0
  140. package/templates/dropdown-menu/wc/dropdown-menu-label.ts +31 -0
  141. package/templates/dropdown-menu/wc/dropdown-menu-radio-group.ts +80 -0
  142. package/templates/dropdown-menu/wc/dropdown-menu-radio-item.ts +101 -0
  143. package/templates/dropdown-menu/wc/dropdown-menu-separator.ts +28 -0
  144. package/templates/dropdown-menu/wc/dropdown-menu.ts +358 -0
  145. package/templates/dropdown-menu/wc/index.ts +12 -0
  146. package/templates/field/field-description.tsx +39 -0
  147. package/templates/field/field-error.tsx +37 -0
  148. package/templates/field/field.tsx +46 -0
  149. package/templates/field/index.ts +4 -0
  150. package/templates/field/label.tsx +40 -0
  151. package/templates/field/wc/field-description.ts +42 -0
  152. package/templates/field/wc/field-error.ts +46 -0
  153. package/templates/field/wc/field.ts +210 -0
  154. package/templates/field/wc/label.ts +54 -0
  155. package/templates/file-upload/file-upload-context.ts +26 -0
  156. package/templates/file-upload/file-upload-dropzone.tsx +111 -0
  157. package/templates/file-upload/file-upload-input.tsx +86 -0
  158. package/templates/file-upload/file-upload-item.tsx +105 -0
  159. package/templates/file-upload/file-upload-root.tsx +115 -0
  160. package/templates/file-upload/index.ts +50 -0
  161. package/templates/file-upload/wc/file-upload.ts +380 -0
  162. package/templates/file-upload/wc/index.ts +1 -0
  163. package/templates/hover-card/index.tsx +203 -0
  164. package/templates/hover-card/wc/hover-card-content.ts +50 -0
  165. package/templates/hover-card/wc/hover-card.ts +382 -0
  166. package/templates/hover-card/wc/index.ts +6 -0
  167. package/templates/icon/icon.tsx +76 -0
  168. package/templates/icon/wc/icon-adapter.ts +108 -0
  169. package/templates/icon/wc/icon.ts +161 -0
  170. package/templates/input/input.tsx +130 -0
  171. package/templates/input/wc/input.ts +216 -0
  172. package/templates/layout/app-shell.tsx +177 -0
  173. package/templates/layout/box.tsx +53 -0
  174. package/templates/layout/center.tsx +42 -0
  175. package/templates/layout/container.tsx +43 -0
  176. package/templates/layout/flow.tsx +83 -0
  177. package/templates/layout/grid.tsx +79 -0
  178. package/templates/layout/index.ts +33 -0
  179. package/templates/layout/inline.tsx +16 -0
  180. package/templates/layout/page.tsx +43 -0
  181. package/templates/layout/section.tsx +39 -0
  182. package/templates/layout/spacer.tsx +30 -0
  183. package/templates/layout/split.tsx +47 -0
  184. package/templates/layout/stack.tsx +16 -0
  185. package/templates/layout/wc/app-shell.ts +58 -0
  186. package/templates/layout/wc/box.ts +117 -0
  187. package/templates/layout/wc/center.ts +78 -0
  188. package/templates/layout/wc/container.ts +77 -0
  189. package/templates/layout/wc/flow.ts +149 -0
  190. package/templates/layout/wc/footer.ts +57 -0
  191. package/templates/layout/wc/grid.ts +142 -0
  192. package/templates/layout/wc/header.ts +57 -0
  193. package/templates/layout/wc/index.ts +41 -0
  194. package/templates/layout/wc/main.ts +46 -0
  195. package/templates/layout/wc/page.ts +81 -0
  196. package/templates/layout/wc/section.ts +65 -0
  197. package/templates/layout/wc/spacer.ts +77 -0
  198. package/templates/layout/wc/split.ts +94 -0
  199. package/templates/layout/wc/wrap.ts +93 -0
  200. package/templates/layout/wrap.tsx +46 -0
  201. package/templates/link/link.tsx +109 -0
  202. package/templates/link/wc/link.ts +124 -0
  203. package/templates/list/index.tsx +55 -0
  204. package/templates/list/list-item.tsx +117 -0
  205. package/templates/list/list.tsx +115 -0
  206. package/templates/list/wc/index.ts +5 -0
  207. package/templates/list/wc/list-item.ts +127 -0
  208. package/templates/list/wc/list.ts +114 -0
  209. package/templates/menu/index.ts +49 -0
  210. package/templates/menu/menu-content.tsx +109 -0
  211. package/templates/menu/menu-context.ts +17 -0
  212. package/templates/menu/menu-item.tsx +108 -0
  213. package/templates/menu/menu-label.tsx +32 -0
  214. package/templates/menu/menu-root.tsx +108 -0
  215. package/templates/menu/menu-separator.tsx +24 -0
  216. package/templates/menu/menu-trigger.tsx +104 -0
  217. package/templates/menu/wc/menu-content.ts +67 -0
  218. package/templates/menu/wc/menu-item.ts +109 -0
  219. package/templates/menu/wc/menu.ts +449 -0
  220. package/templates/navigation-menu/index.tsx +328 -0
  221. package/templates/navigation-menu/wc/index.ts +12 -0
  222. package/templates/navigation-menu/wc/navigation-menu-content.ts +30 -0
  223. package/templates/navigation-menu/wc/navigation-menu-indicator.ts +30 -0
  224. package/templates/navigation-menu/wc/navigation-menu-item.ts +60 -0
  225. package/templates/navigation-menu/wc/navigation-menu-link.ts +97 -0
  226. package/templates/navigation-menu/wc/navigation-menu-list.ts +30 -0
  227. package/templates/navigation-menu/wc/navigation-menu-trigger.ts +110 -0
  228. package/templates/navigation-menu/wc/navigation-menu-viewport.ts +85 -0
  229. package/templates/navigation-menu/wc/navigation-menu.ts +272 -0
  230. package/templates/number-input/index.ts +46 -0
  231. package/templates/number-input/number-input-context.ts +38 -0
  232. package/templates/number-input/number-input-decrement.tsx +53 -0
  233. package/templates/number-input/number-input-field.tsx +93 -0
  234. package/templates/number-input/number-input-increment.tsx +53 -0
  235. package/templates/number-input/number-input-root.tsx +137 -0
  236. package/templates/number-input/wc/index.ts +1 -0
  237. package/templates/number-input/wc/number-input.ts +283 -0
  238. package/templates/pagination/index.tsx +198 -0
  239. package/templates/pagination/wc/index.ts +11 -0
  240. package/templates/pagination/wc/pagination-content.ts +30 -0
  241. package/templates/pagination/wc/pagination-ellipsis.ts +28 -0
  242. package/templates/pagination/wc/pagination-item.ts +30 -0
  243. package/templates/pagination/wc/pagination-link.ts +76 -0
  244. package/templates/pagination/wc/pagination-next.ts +69 -0
  245. package/templates/pagination/wc/pagination-previous.ts +69 -0
  246. package/templates/pagination/wc/pagination.ts +156 -0
  247. package/templates/pin-input/index.ts +39 -0
  248. package/templates/pin-input/pin-input-context.ts +30 -0
  249. package/templates/pin-input/pin-input-field.tsx +186 -0
  250. package/templates/pin-input/pin-input-root.tsx +120 -0
  251. package/templates/pin-input/wc/index.ts +1 -0
  252. package/templates/pin-input/wc/pin-input.ts +259 -0
  253. package/templates/popover/popover.tsx +121 -0
  254. package/templates/popover/wc/popover-content.ts +66 -0
  255. package/templates/popover/wc/popover.ts +343 -0
  256. package/templates/progress/index.tsx +117 -0
  257. package/templates/progress/wc/index.ts +4 -0
  258. package/templates/progress/wc/progress.ts +174 -0
  259. package/templates/radio/radio.tsx +43 -0
  260. package/templates/radio/wc/radio-group.ts +261 -0
  261. package/templates/radio/wc/radio.ts +145 -0
  262. package/templates/scroll-area/index.tsx +144 -0
  263. package/templates/scroll-area/wc/index.ts +8 -0
  264. package/templates/scroll-area/wc/scroll-area-scrollbar.ts +143 -0
  265. package/templates/scroll-area/wc/scroll-area-thumb.ts +225 -0
  266. package/templates/scroll-area/wc/scroll-area-viewport.ts +120 -0
  267. package/templates/scroll-area/wc/scroll-area.ts +63 -0
  268. package/templates/select/index.ts +57 -0
  269. package/templates/select/select-content.tsx +243 -0
  270. package/templates/select/select-context.ts +30 -0
  271. package/templates/select/select-group.tsx +53 -0
  272. package/templates/select/select-label.tsx +34 -0
  273. package/templates/select/select-option.tsx +97 -0
  274. package/templates/select/select-root.tsx +153 -0
  275. package/templates/select/select-separator.tsx +27 -0
  276. package/templates/select/select-trigger.tsx +112 -0
  277. package/templates/select/select-value.tsx +48 -0
  278. package/templates/select/wc/index.ts +6 -0
  279. package/templates/select/wc/select-content.ts +89 -0
  280. package/templates/select/wc/select-group.ts +82 -0
  281. package/templates/select/wc/select-label.ts +49 -0
  282. package/templates/select/wc/select-option.ts +111 -0
  283. package/templates/select/wc/select-trigger.ts +101 -0
  284. package/templates/select/wc/select.ts +840 -0
  285. package/templates/separator/index.tsx +49 -0
  286. package/templates/separator/wc/index.ts +5 -0
  287. package/templates/separator/wc/separator.ts +60 -0
  288. package/templates/sheet/index.tsx +291 -0
  289. package/templates/sheet/wc/index.ts +12 -0
  290. package/templates/sheet/wc/sheet-close.ts +43 -0
  291. package/templates/sheet/wc/sheet-content.ts +47 -0
  292. package/templates/sheet/wc/sheet-description.ts +34 -0
  293. package/templates/sheet/wc/sheet-footer.ts +25 -0
  294. package/templates/sheet/wc/sheet-header.ts +25 -0
  295. package/templates/sheet/wc/sheet-overlay.ts +23 -0
  296. package/templates/sheet/wc/sheet-title.ts +34 -0
  297. package/templates/sheet/wc/sheet.ts +336 -0
  298. package/templates/skeleton/index.tsx +131 -0
  299. package/templates/skeleton/wc/index.ts +10 -0
  300. package/templates/skeleton/wc/skeleton.ts +107 -0
  301. package/templates/slider/index.ts +41 -0
  302. package/templates/slider/slider-context.ts +36 -0
  303. package/templates/slider/slider-range.tsx +59 -0
  304. package/templates/slider/slider-root.tsx +166 -0
  305. package/templates/slider/slider-thumb.tsx +213 -0
  306. package/templates/slider/slider-track.tsx +113 -0
  307. package/templates/slider/wc/index.ts +1 -0
  308. package/templates/slider/wc/slider.ts +465 -0
  309. package/templates/spinner/spinner.tsx +64 -0
  310. package/templates/spinner/wc/spinner.ts +70 -0
  311. package/templates/stepper/index.tsx +230 -0
  312. package/templates/stepper/wc/index.ts +12 -0
  313. package/templates/stepper/wc/stepper-content.ts +30 -0
  314. package/templates/stepper/wc/stepper-description.ts +25 -0
  315. package/templates/stepper/wc/stepper-indicator.ts +30 -0
  316. package/templates/stepper/wc/stepper-item.ts +55 -0
  317. package/templates/stepper/wc/stepper-separator.ts +29 -0
  318. package/templates/stepper/wc/stepper-title.ts +25 -0
  319. package/templates/stepper/wc/stepper-trigger.ts +67 -0
  320. package/templates/stepper/wc/stepper.ts +164 -0
  321. package/templates/switch/switch.tsx +90 -0
  322. package/templates/switch/wc/switch.ts +228 -0
  323. package/templates/table/body.tsx +21 -0
  324. package/templates/table/cell.tsx +44 -0
  325. package/templates/table/head.tsx +112 -0
  326. package/templates/table/header.tsx +21 -0
  327. package/templates/table/index.tsx +93 -0
  328. package/templates/table/root.tsx +82 -0
  329. package/templates/table/row.tsx +36 -0
  330. package/templates/table/wc/index.ts +9 -0
  331. package/templates/table/wc/table-body.ts +32 -0
  332. package/templates/table/wc/table-cell.ts +58 -0
  333. package/templates/table/wc/table-head.ts +129 -0
  334. package/templates/table/wc/table-header.ts +32 -0
  335. package/templates/table/wc/table-row.ts +50 -0
  336. package/templates/table/wc/table.ts +93 -0
  337. package/templates/tabs/index.tsx +222 -0
  338. package/templates/tabs/wc/index.ts +8 -0
  339. package/templates/tabs/wc/tabs-content.ts +82 -0
  340. package/templates/tabs/wc/tabs-list.ts +56 -0
  341. package/templates/tabs/wc/tabs-trigger.ts +136 -0
  342. package/templates/tabs/wc/tabs.ts +202 -0
  343. package/templates/tag/index.tsx +186 -0
  344. package/templates/tag/wc/index.ts +4 -0
  345. package/templates/tag/wc/tag.ts +166 -0
  346. package/templates/text/text.tsx +100 -0
  347. package/templates/text/wc/text.ts +94 -0
  348. package/templates/textarea/textarea.tsx +134 -0
  349. package/templates/textarea/wc/textarea.ts +280 -0
  350. package/templates/time-picker/index.ts +42 -0
  351. package/templates/time-picker/time-picker-context.ts +28 -0
  352. package/templates/time-picker/time-picker-root.tsx +113 -0
  353. package/templates/time-picker/time-picker-segment.tsx +91 -0
  354. package/templates/time-picker/wc/index.ts +1 -0
  355. package/templates/time-picker/wc/time-picker.ts +221 -0
  356. package/templates/toast/index.tsx +71 -0
  357. package/templates/toast/provider.tsx +228 -0
  358. package/templates/toast/toast.tsx +142 -0
  359. package/templates/toast/use-toast.ts +89 -0
  360. package/templates/toast/wc/index.ts +15 -0
  361. package/templates/toast/wc/toast-controller.ts +282 -0
  362. package/templates/toast/wc/toast-provider.ts +161 -0
  363. package/templates/toast/wc/toast.ts +165 -0
  364. package/templates/tooltip/tooltip.tsx +62 -0
  365. package/templates/tooltip/wc/tooltip-content.ts +64 -0
  366. package/templates/tooltip/wc/tooltip.ts +289 -0
  367. package/templates/tree/index.tsx +60 -0
  368. package/templates/tree/tree-item.tsx +131 -0
  369. package/templates/tree/tree.tsx +138 -0
  370. package/templates/tree/wc/index.ts +11 -0
  371. package/templates/tree/wc/tree-item.ts +273 -0
  372. package/templates/tree/wc/tree-utils.ts +143 -0
  373. package/templates/tree/wc/tree.ts +139 -0
  374. package/templates/visually-hidden/visually-hidden.tsx +45 -0
  375. package/templates/visually-hidden/wc/visually-hidden.ts +64 -0
@@ -0,0 +1,172 @@
1
+ /**
2
+ * Collapsible compound component exports.
3
+ *
4
+ * @example
5
+ * ```tsx
6
+ * import { Collapsible } from "@/components/ui";
7
+ *
8
+ * <Collapsible.Root>
9
+ * <Collapsible.Trigger>Toggle</Collapsible.Trigger>
10
+ * <Collapsible.Content>
11
+ * <p>Collapsible content here.</p>
12
+ * </Collapsible.Content>
13
+ * </Collapsible.Root>
14
+ * ```
15
+ */
16
+
17
+ import {
18
+ type HTMLAttributes,
19
+ type ReactNode,
20
+ createElement,
21
+ forwardRef,
22
+ useCallback,
23
+ useEffect,
24
+ useRef,
25
+ useState,
26
+ } from "react";
27
+
28
+ // ============================================================================
29
+ // Types
30
+ // ============================================================================
31
+
32
+ export interface CollapsibleRootProps extends HTMLAttributes<HTMLElement> {
33
+ /** Content */
34
+ children?: ReactNode;
35
+ /** Controlled open state */
36
+ open?: boolean;
37
+ /** Default open state (uncontrolled) */
38
+ defaultOpen?: boolean;
39
+ /** Called when open state changes */
40
+ onOpenChange?: (open: boolean) => void;
41
+ /** Disable the collapsible */
42
+ disabled?: boolean;
43
+ }
44
+
45
+ export interface CollapsibleTriggerProps extends HTMLAttributes<HTMLElement> {
46
+ /** Trigger content */
47
+ children?: ReactNode;
48
+ }
49
+
50
+ export interface CollapsibleContentProps extends HTMLAttributes<HTMLElement> {
51
+ /** Content */
52
+ children?: ReactNode;
53
+ /** Keep mounted when collapsed */
54
+ forceMount?: boolean;
55
+ }
56
+
57
+ // ============================================================================
58
+ // Components
59
+ // ============================================================================
60
+
61
+ /**
62
+ * Collapsible root component.
63
+ */
64
+ const CollapsibleRoot = forwardRef<HTMLElement, CollapsibleRootProps>(function CollapsibleRoot(
65
+ {
66
+ children,
67
+ className,
68
+ open: controlledOpen,
69
+ defaultOpen = false,
70
+ onOpenChange,
71
+ disabled = false,
72
+ ...props
73
+ },
74
+ ref
75
+ ) {
76
+ const [internalOpen, setInternalOpen] = useState(defaultOpen);
77
+ const isControlled = controlledOpen !== undefined;
78
+ const open = isControlled ? controlledOpen : internalOpen;
79
+ const elementRef = useRef<HTMLElement>(null);
80
+
81
+ // Combine refs
82
+ const combinedRef = (node: HTMLElement | null) => {
83
+ (elementRef as React.MutableRefObject<HTMLElement | null>).current = node;
84
+ if (typeof ref === "function") {
85
+ ref(node);
86
+ } else if (ref) {
87
+ (ref as React.MutableRefObject<HTMLElement | null>).current = node;
88
+ }
89
+ };
90
+
91
+ const handleOpenChange = useCallback(
92
+ (event: Event) => {
93
+ const customEvent = event as CustomEvent;
94
+ const isOpen = customEvent.type === "ds:open";
95
+
96
+ if (!isControlled) {
97
+ setInternalOpen(isOpen);
98
+ }
99
+ onOpenChange?.(isOpen);
100
+ },
101
+ [isControlled, onOpenChange]
102
+ );
103
+
104
+ // Attach event listeners
105
+ useEffect(() => {
106
+ const element = elementRef.current;
107
+ if (!element) return;
108
+
109
+ element.addEventListener("ds:open", handleOpenChange);
110
+ element.addEventListener("ds:close", handleOpenChange);
111
+
112
+ return () => {
113
+ element.removeEventListener("ds:open", handleOpenChange);
114
+ element.removeEventListener("ds:close", handleOpenChange);
115
+ };
116
+ }, [handleOpenChange]);
117
+
118
+ return createElement(
119
+ "ds-collapsible",
120
+ {
121
+ ref: combinedRef,
122
+ class: className,
123
+ open: open || undefined,
124
+ disabled: disabled || undefined,
125
+ ...props,
126
+ },
127
+ children
128
+ );
129
+ });
130
+ CollapsibleRoot.displayName = "Collapsible.Root";
131
+
132
+ /**
133
+ * Collapsible trigger component.
134
+ */
135
+ const CollapsibleTrigger = forwardRef<HTMLElement, CollapsibleTriggerProps>(
136
+ function CollapsibleTrigger({ children, className, ...props }, ref) {
137
+ return createElement("ds-collapsible-trigger", { ref, class: className, ...props }, children);
138
+ }
139
+ );
140
+ CollapsibleTrigger.displayName = "Collapsible.Trigger";
141
+
142
+ /**
143
+ * Collapsible content component.
144
+ */
145
+ const CollapsibleContent = forwardRef<HTMLElement, CollapsibleContentProps>(
146
+ function CollapsibleContent({ children, className, forceMount = false, ...props }, ref) {
147
+ return createElement(
148
+ "ds-collapsible-content",
149
+ {
150
+ ref,
151
+ class: className,
152
+ "force-mount": forceMount || undefined,
153
+ ...props,
154
+ },
155
+ children
156
+ );
157
+ }
158
+ );
159
+ CollapsibleContent.displayName = "Collapsible.Content";
160
+
161
+ // ============================================================================
162
+ // Compound Component
163
+ // ============================================================================
164
+
165
+ export const Collapsible = {
166
+ Root: CollapsibleRoot,
167
+ Trigger: CollapsibleTrigger,
168
+ Content: CollapsibleContent,
169
+ };
170
+
171
+ // Also export individual components
172
+ export { CollapsibleRoot, CollapsibleTrigger, CollapsibleContent };
@@ -0,0 +1,97 @@
1
+ /**
2
+ * Collapsible Content component - content section that expands/collapses.
3
+ *
4
+ * @element ds-collapsible-content
5
+ *
6
+ * @slot - Content to show/hide
7
+ */
8
+
9
+ import { type Presence, createPresence, prefersReducedMotion } from "@hypoth-ui/primitives-dom";
10
+ import { html } from "lit";
11
+ import { property, state } from "lit/decorators.js";
12
+ import { DSElement } from "../../base/ds-element.js";
13
+ import { define } from "../../registry/define.js";
14
+
15
+ export class DsCollapsibleContent extends DSElement {
16
+ /** Keep mounted when collapsed (for animations) */
17
+ @property({ type: Boolean, attribute: "force-mount" })
18
+ forceMount = false;
19
+
20
+ /** Current state for animations */
21
+ @state()
22
+ dataState: "open" | "closed" = "closed";
23
+
24
+ /** Whether we're currently animating out */
25
+ @state()
26
+ private isAnimatingOut = false;
27
+
28
+ private presence: Presence | null = null;
29
+
30
+ override connectedCallback(): void {
31
+ super.connectedCallback();
32
+ this.setAttribute("role", "region");
33
+ this.updateVisibility();
34
+ }
35
+
36
+ override disconnectedCallback(): void {
37
+ super.disconnectedCallback();
38
+ this.presence?.destroy();
39
+ this.presence = null;
40
+ }
41
+
42
+ override updated(changedProperties: Map<string, unknown>): void {
43
+ if (changedProperties.has("dataState")) {
44
+ this.handleStateChange();
45
+ }
46
+ }
47
+
48
+ private handleStateChange(): void {
49
+ this.setAttribute("data-state", this.dataState);
50
+
51
+ if (this.dataState === "open") {
52
+ this.isAnimatingOut = false;
53
+ this.updateVisibility();
54
+ } else if (!this.forceMount && !prefersReducedMotion()) {
55
+ // Animate out before hiding
56
+ this.isAnimatingOut = true;
57
+
58
+ this.presence?.destroy();
59
+ this.presence = createPresence({
60
+ onExitComplete: () => {
61
+ this.isAnimatingOut = false;
62
+ this.updateVisibility();
63
+ },
64
+ });
65
+ this.presence.hide(this);
66
+ } else {
67
+ this.updateVisibility();
68
+ }
69
+ }
70
+
71
+ private updateVisibility(): void {
72
+ if (this.forceMount) {
73
+ this.hidden = false;
74
+ return;
75
+ }
76
+
77
+ // Stay visible during exit animation
78
+ if (this.isAnimatingOut) {
79
+ this.hidden = false;
80
+ return;
81
+ }
82
+
83
+ this.hidden = this.dataState === "closed";
84
+ }
85
+
86
+ override render() {
87
+ return html`<slot></slot>`;
88
+ }
89
+ }
90
+
91
+ define("ds-collapsible-content", DsCollapsibleContent);
92
+
93
+ declare global {
94
+ interface HTMLElementTagNameMap {
95
+ "ds-collapsible-content": DsCollapsibleContent;
96
+ }
97
+ }
@@ -0,0 +1,39 @@
1
+ /**
2
+ * Collapsible Trigger component - button that toggles collapsible.
3
+ *
4
+ * @element ds-collapsible-trigger
5
+ *
6
+ * @slot - Trigger content
7
+ */
8
+
9
+ import { html } from "lit";
10
+ import { DSElement } from "../../base/ds-element.js";
11
+ import { define } from "../../registry/define.js";
12
+
13
+ export class DsCollapsibleTrigger extends DSElement {
14
+ override connectedCallback(): void {
15
+ super.connectedCallback();
16
+
17
+ // Ensure focusability
18
+ if (!this.hasAttribute("tabindex")) {
19
+ this.setAttribute("tabindex", "0");
20
+ }
21
+
22
+ // Set button role if not already set
23
+ if (!this.hasAttribute("role")) {
24
+ this.setAttribute("role", "button");
25
+ }
26
+ }
27
+
28
+ override render() {
29
+ return html`<slot></slot>`;
30
+ }
31
+ }
32
+
33
+ define("ds-collapsible-trigger", DsCollapsibleTrigger);
34
+
35
+ declare global {
36
+ interface HTMLElementTagNameMap {
37
+ "ds-collapsible-trigger": DsCollapsibleTrigger;
38
+ }
39
+ }
@@ -0,0 +1,143 @@
1
+ /**
2
+ * Collapsible component - toggleable content visibility.
3
+ *
4
+ * Provides an expandable/collapsible content section with animation support.
5
+ *
6
+ * @element ds-collapsible
7
+ *
8
+ * @slot trigger - Button or element that toggles the collapsible
9
+ * @slot - Collapsible content (ds-collapsible-content)
10
+ *
11
+ * @fires ds:open - Fired when collapsible opens
12
+ * @fires ds:close - Fired when collapsible closes
13
+ *
14
+ * @example
15
+ * ```html
16
+ * <ds-collapsible>
17
+ * <button slot="trigger">Toggle Content</button>
18
+ * <ds-collapsible-content>
19
+ * <p>Collapsible content here.</p>
20
+ * </ds-collapsible-content>
21
+ * </ds-collapsible>
22
+ * ```
23
+ */
24
+
25
+ import { html } from "lit";
26
+ import { property, state } from "lit/decorators.js";
27
+ import { DSElement } from "../../base/ds-element.js";
28
+ import { StandardEvents, emitEvent } from "../../events/emit.js";
29
+ import { define } from "../../registry/define.js";
30
+
31
+ // Import child components
32
+ import type { DsCollapsibleContent } from "./collapsible-content.js";
33
+ import "./collapsible-content.js";
34
+ import "./collapsible-trigger.js";
35
+
36
+ export class DsCollapsible extends DSElement {
37
+ /** Whether the collapsible is open */
38
+ @property({ type: Boolean, reflect: true })
39
+ open = false;
40
+
41
+ /** Disable the collapsible */
42
+ @property({ type: Boolean, reflect: true })
43
+ disabled = false;
44
+
45
+ /** Internal ID for ARIA relationships */
46
+ @state()
47
+ private contentId = `collapsible-${crypto.randomUUID().slice(0, 8)}`;
48
+
49
+ override connectedCallback(): void {
50
+ super.connectedCallback();
51
+ this.addEventListener("click", this.handleTriggerClick);
52
+ this.addEventListener("keydown", this.handleKeyDown);
53
+ }
54
+
55
+ override disconnectedCallback(): void {
56
+ super.disconnectedCallback();
57
+ this.removeEventListener("click", this.handleTriggerClick);
58
+ this.removeEventListener("keydown", this.handleKeyDown);
59
+ }
60
+
61
+ /**
62
+ * Toggle the open state.
63
+ */
64
+ public toggle(): void {
65
+ if (this.disabled) return;
66
+ this.setOpen(!this.open);
67
+ }
68
+
69
+ /**
70
+ * Set the open state.
71
+ */
72
+ public setOpen(open: boolean): void {
73
+ if (this.disabled || this.open === open) return;
74
+
75
+ this.open = open;
76
+ emitEvent(this, open ? StandardEvents.OPEN : StandardEvents.CLOSE);
77
+ this.updateContent();
78
+ }
79
+
80
+ private handleTriggerClick = (event: Event): void => {
81
+ const target = event.target as HTMLElement;
82
+ const trigger = target.closest('[slot="trigger"], ds-collapsible-trigger');
83
+
84
+ if (trigger && this.contains(trigger)) {
85
+ this.toggle();
86
+ }
87
+ };
88
+
89
+ private handleKeyDown = (event: KeyboardEvent): void => {
90
+ const target = event.target as HTMLElement;
91
+ const trigger = target.closest('[slot="trigger"], ds-collapsible-trigger');
92
+
93
+ if (trigger && this.contains(trigger)) {
94
+ if (event.key === "Enter" || event.key === " ") {
95
+ event.preventDefault();
96
+ this.toggle();
97
+ }
98
+ }
99
+ };
100
+
101
+ override updated(): void {
102
+ this.updateContent();
103
+ this.updateTrigger();
104
+ }
105
+
106
+ private updateContent(): void {
107
+ const content = this.querySelector("ds-collapsible-content") as DsCollapsibleContent | null;
108
+ if (content) {
109
+ content.id = this.contentId;
110
+ content.dataState = this.open ? "open" : "closed";
111
+ }
112
+ }
113
+
114
+ private updateTrigger(): void {
115
+ const trigger =
116
+ this.querySelector('[slot="trigger"]') || this.querySelector("ds-collapsible-trigger");
117
+
118
+ if (trigger) {
119
+ trigger.setAttribute("aria-expanded", String(this.open));
120
+ trigger.setAttribute("aria-controls", this.contentId);
121
+ if (this.disabled) {
122
+ trigger.setAttribute("aria-disabled", "true");
123
+ } else {
124
+ trigger.removeAttribute("aria-disabled");
125
+ }
126
+ }
127
+ }
128
+
129
+ override render() {
130
+ return html`
131
+ <slot name="trigger"></slot>
132
+ <slot></slot>
133
+ `;
134
+ }
135
+ }
136
+
137
+ define("ds-collapsible", DsCollapsible);
138
+
139
+ declare global {
140
+ interface HTMLElementTagNameMap {
141
+ "ds-collapsible": DsCollapsible;
142
+ }
143
+ }
@@ -0,0 +1,7 @@
1
+ /**
2
+ * Collapsible component barrel exports.
3
+ */
4
+
5
+ export { DsCollapsible } from "./collapsible.js";
6
+ export { DsCollapsibleTrigger } from "./collapsible-trigger.js";
7
+ export { DsCollapsibleContent } from "./collapsible-content.js";
@@ -0,0 +1,141 @@
1
+ /**
2
+ * Combobox Content component - container for combobox options.
3
+ */
4
+
5
+ import {
6
+ type AnchorPosition,
7
+ type DismissableLayer,
8
+ type RovingFocus,
9
+ createAnchorPosition,
10
+ createDismissableLayer,
11
+ createRovingFocus,
12
+ } from "@hypoth-ui/primitives-dom";
13
+ import {
14
+ type HTMLAttributes,
15
+ type ReactNode,
16
+ forwardRef,
17
+ useCallback,
18
+ useEffect,
19
+ useRef,
20
+ } from "react";
21
+ import { useComboboxContext } from "./combobox-context.js";
22
+
23
+ export interface ComboboxContentProps extends HTMLAttributes<HTMLDivElement> {
24
+ /** Content container */
25
+ children?: ReactNode;
26
+ /** Optional label for accessibility */
27
+ "aria-label"?: string;
28
+ }
29
+
30
+ /**
31
+ * Container for combobox options.
32
+ * Handles positioning, dismiss behavior, and keyboard navigation.
33
+ *
34
+ * @example
35
+ * ```tsx
36
+ * <Combobox.Content>
37
+ * <Combobox.Option value="apple">Apple</Combobox.Option>
38
+ * <Combobox.Option value="banana">Banana</Combobox.Option>
39
+ * </Combobox.Content>
40
+ * ```
41
+ */
42
+ export const ComboboxContent = forwardRef<HTMLDivElement, ComboboxContentProps>(
43
+ ({ children, className, ...restProps }, ref) => {
44
+ const { behavior, open, setOpen, loading } = useComboboxContext("Combobox.Content");
45
+ const internalRef = useRef<HTMLDivElement>(null);
46
+
47
+ // Behavior instances
48
+ const anchorPositionRef = useRef<AnchorPosition | null>(null);
49
+ const dismissLayerRef = useRef<DismissableLayer | null>(null);
50
+ const rovingFocusRef = useRef<RovingFocus | null>(null);
51
+ const inputRef = useRef<HTMLElement | null>(null);
52
+
53
+ // Merge refs
54
+ const mergedRef = useCallback(
55
+ (element: HTMLDivElement | null) => {
56
+ (internalRef as React.MutableRefObject<HTMLDivElement | null>).current = element;
57
+ if (typeof ref === "function") {
58
+ ref(element);
59
+ } else if (ref) {
60
+ (ref as React.MutableRefObject<HTMLDivElement | null>).current = element;
61
+ }
62
+ },
63
+ [ref]
64
+ );
65
+
66
+ // Setup and cleanup behaviors when open changes
67
+ useEffect(() => {
68
+ const content = internalRef.current;
69
+ if (!content || !open) return;
70
+
71
+ // Find input element (previous sibling or parent context)
72
+ const input = content.previousElementSibling as HTMLElement;
73
+ inputRef.current = input;
74
+
75
+ // Setup anchor positioning
76
+ if (input) {
77
+ anchorPositionRef.current = createAnchorPosition({
78
+ anchor: input,
79
+ floating: content,
80
+ placement: "bottom-start",
81
+ offset: 4,
82
+ flip: true,
83
+ onPositionChange: (pos) => {
84
+ content.setAttribute("data-placement", pos.placement);
85
+ },
86
+ });
87
+ }
88
+
89
+ // Setup dismiss layer
90
+ dismissLayerRef.current = createDismissableLayer({
91
+ container: content,
92
+ excludeElements: input ? [input] : [],
93
+ onDismiss: () => setOpen(false),
94
+ closeOnEscape: true,
95
+ closeOnOutsideClick: true,
96
+ });
97
+ dismissLayerRef.current.activate();
98
+
99
+ // Setup roving focus
100
+ rovingFocusRef.current = createRovingFocus({
101
+ container: content,
102
+ selector: '[role="option"]:not([aria-disabled="true"])',
103
+ direction: "vertical",
104
+ loop: true,
105
+ skipDisabled: true,
106
+ });
107
+
108
+ // Cleanup
109
+ return () => {
110
+ anchorPositionRef.current?.destroy();
111
+ anchorPositionRef.current = null;
112
+ dismissLayerRef.current?.deactivate();
113
+ dismissLayerRef.current = null;
114
+ rovingFocusRef.current?.destroy();
115
+ rovingFocusRef.current = null;
116
+ };
117
+ }, [open, setOpen]);
118
+
119
+ // Don't render if not open
120
+ if (!open) return null;
121
+
122
+ const listboxProps = behavior.getListboxProps();
123
+
124
+ return (
125
+ <div
126
+ ref={mergedRef}
127
+ role={listboxProps.role}
128
+ id={listboxProps.id}
129
+ aria-multiselectable={listboxProps["aria-multiselectable"]}
130
+ aria-busy={loading || undefined}
131
+ className={className}
132
+ data-state="open"
133
+ {...restProps}
134
+ >
135
+ {children}
136
+ </div>
137
+ );
138
+ }
139
+ );
140
+
141
+ ComboboxContent.displayName = "Combobox.Content";
@@ -0,0 +1,36 @@
1
+ /**
2
+ * Combobox context for compound component pattern.
3
+ */
4
+
5
+ import type { ComboboxBehavior, Option } from "@hypoth-ui/primitives-dom";
6
+ import { createCompoundContext } from "../../utils/create-context.js";
7
+
8
+ export interface ComboboxContextValue<Multi extends boolean = false> {
9
+ /** Combobox behavior instance */
10
+ behavior: ComboboxBehavior<string, Multi>;
11
+ /** Whether combobox is open */
12
+ open: boolean;
13
+ /** Set open state */
14
+ setOpen: (open: boolean) => void;
15
+ /** Current value(s) */
16
+ value: Multi extends true ? string[] : string | null;
17
+ /** Set value(s) */
18
+ setValue: (value: Multi extends true ? string[] : string | null) => void;
19
+ /** Input value */
20
+ inputValue: string;
21
+ /** Set input value */
22
+ setInputValue: (value: string) => void;
23
+ /** Highlighted value for keyboard navigation */
24
+ highlightedValue: string | null;
25
+ /** Set highlighted value */
26
+ setHighlightedValue: (value: string | null) => void;
27
+ /** Whether multi-select mode */
28
+ multiple: Multi;
29
+ /** Filtered options */
30
+ filteredOptions: Option<string>[];
31
+ /** Loading state */
32
+ loading: boolean;
33
+ }
34
+
35
+ export const [ComboboxProvider, useComboboxContext] =
36
+ createCompoundContext<ComboboxContextValue<boolean>>("Combobox");
@@ -0,0 +1,38 @@
1
+ /**
2
+ * Combobox Empty component - shown when no options match.
3
+ */
4
+
5
+ import { type HTMLAttributes, type ReactNode, forwardRef } from "react";
6
+ import { useComboboxContext } from "./combobox-context.js";
7
+
8
+ export interface ComboboxEmptyProps extends HTMLAttributes<HTMLOutputElement> {
9
+ /** Empty state content */
10
+ children?: ReactNode;
11
+ }
12
+
13
+ /**
14
+ * Empty state shown when no options match the search.
15
+ *
16
+ * @example
17
+ * ```tsx
18
+ * <Combobox.Empty>No results found</Combobox.Empty>
19
+ * ```
20
+ */
21
+ export const ComboboxEmpty = forwardRef<HTMLOutputElement, ComboboxEmptyProps>(
22
+ ({ children, className, ...restProps }, ref) => {
23
+ const { filteredOptions, loading, inputValue } = useComboboxContext("Combobox.Empty");
24
+
25
+ // Only show if no options and not loading and has input
26
+ if (filteredOptions.length > 0 || loading || !inputValue) {
27
+ return null;
28
+ }
29
+
30
+ return (
31
+ <output ref={ref} aria-live="polite" className={className} {...restProps}>
32
+ {children}
33
+ </output>
34
+ );
35
+ }
36
+ );
37
+
38
+ ComboboxEmpty.displayName = "Combobox.Empty";