@hypoth-ui/cli 0.0.1 → 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 (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,114 @@
1
+ import { type TemplateResult, html, nothing } from "lit";
2
+ import { property, state } from "lit/decorators.js";
3
+ import { classMap } from "lit/directives/class-map.js";
4
+ import { DSElement } from "../../base/ds-element.js";
5
+ import { emitEvent } from "../../events/emit.js";
6
+ import { define } from "../../registry/define.js";
7
+
8
+ export type ListSelectionMode = "single" | "multiple" | "none";
9
+ export type ListOrientation = "vertical" | "horizontal";
10
+ export type ListSize = "default" | "compact" | "spacious";
11
+
12
+ /**
13
+ * List root component for collection display.
14
+ *
15
+ * @element ds-list
16
+ *
17
+ * @slot - ListItem elements
18
+ *
19
+ * @fires ds-selection-change - When selection changes
20
+ *
21
+ * @cssprop --ds-list-gap - Gap between items
22
+ */
23
+ export class DsList extends DSElement {
24
+ static override styles = [];
25
+
26
+ /**
27
+ * Selection mode.
28
+ */
29
+ @property({ type: String, attribute: "selection-mode", reflect: true })
30
+ selectionMode: ListSelectionMode = "single";
31
+
32
+ /**
33
+ * List orientation.
34
+ */
35
+ @property({ type: String, reflect: true })
36
+ orientation: ListOrientation = "vertical";
37
+
38
+ /**
39
+ * Size variant.
40
+ */
41
+ @property({ type: String, reflect: true })
42
+ size: ListSize = "default";
43
+
44
+ /**
45
+ * Show border around list.
46
+ */
47
+ @property({ type: Boolean, reflect: true })
48
+ bordered = false;
49
+
50
+ /**
51
+ * Accessible label.
52
+ */
53
+ @property({ type: String })
54
+ label = "List";
55
+
56
+ @state()
57
+ private selectedItems: Set<string> = new Set();
58
+
59
+ handleItemSelect(itemId: string): void {
60
+ if (this.selectionMode === "none") return;
61
+
62
+ if (this.selectionMode === "single") {
63
+ this.selectedItems.clear();
64
+ this.selectedItems.add(itemId);
65
+ } else {
66
+ if (this.selectedItems.has(itemId)) {
67
+ this.selectedItems.delete(itemId);
68
+ } else {
69
+ this.selectedItems.add(itemId);
70
+ }
71
+ }
72
+
73
+ emitEvent(this, "selection-change", {
74
+ detail: { selectedItems: Array.from(this.selectedItems) },
75
+ });
76
+
77
+ this.requestUpdate();
78
+ }
79
+
80
+ isItemSelected(itemId: string): boolean {
81
+ return this.selectedItems.has(itemId);
82
+ }
83
+
84
+ override render(): TemplateResult {
85
+ const classes = {
86
+ "ds-list": true,
87
+ };
88
+
89
+ return html`
90
+ <ul
91
+ class=${classMap(classes)}
92
+ role="listbox"
93
+ aria-label=${this.label}
94
+ aria-multiselectable=${this.selectionMode === "multiple" ? "true" : nothing}
95
+ aria-orientation=${this.orientation}
96
+ data-size=${this.size !== "default" ? this.size : nothing}
97
+ data-orientation=${this.orientation !== "vertical" ? this.orientation : nothing}
98
+ ?data-bordered=${this.bordered}
99
+ >
100
+ <slot></slot>
101
+ </ul>
102
+ `;
103
+ }
104
+ }
105
+
106
+ // Register the component
107
+ define("ds-list", DsList);
108
+
109
+ // TypeScript declaration for HTML
110
+ declare global {
111
+ interface HTMLElementTagNameMap {
112
+ "ds-list": DsList;
113
+ }
114
+ }
@@ -0,0 +1,49 @@
1
+ /**
2
+ * Menu compound component exports.
3
+ *
4
+ * @example
5
+ * ```tsx
6
+ * import { Menu } from "@/components/ui";
7
+ *
8
+ * <Menu.Root onSelect={(value) => console.log(value)}>
9
+ * <Menu.Trigger>Actions</Menu.Trigger>
10
+ * <Menu.Content>
11
+ * <Menu.Label>Options</Menu.Label>
12
+ * <Menu.Item value="edit">Edit</Menu.Item>
13
+ * <Menu.Item value="duplicate">Duplicate</Menu.Item>
14
+ * <Menu.Separator />
15
+ * <Menu.Item value="delete">Delete</Menu.Item>
16
+ * </Menu.Content>
17
+ * </Menu.Root>
18
+ * ```
19
+ */
20
+
21
+ import { MenuContent, type MenuContentProps } from "./menu-content.js";
22
+ import { MenuItem, type MenuItemProps } from "./menu-item.js";
23
+ import { MenuLabel, type MenuLabelProps } from "./menu-label.js";
24
+ import { MenuRoot, type MenuRootProps } from "./menu-root.js";
25
+ import { MenuSeparator, type MenuSeparatorProps } from "./menu-separator.js";
26
+ import { MenuTrigger, type MenuTriggerProps } from "./menu-trigger.js";
27
+
28
+ // Compound component
29
+ export const Menu = {
30
+ Root: MenuRoot,
31
+ Trigger: MenuTrigger,
32
+ Content: MenuContent,
33
+ Item: MenuItem,
34
+ Separator: MenuSeparator,
35
+ Label: MenuLabel,
36
+ };
37
+
38
+ // Type exports
39
+ export type {
40
+ MenuContentProps,
41
+ MenuItemProps,
42
+ MenuLabelProps,
43
+ MenuRootProps,
44
+ MenuSeparatorProps,
45
+ MenuTriggerProps,
46
+ };
47
+
48
+ // Re-export Placement from primitives-dom
49
+ export type { Placement } from "@hypoth-ui/primitives-dom";
@@ -0,0 +1,109 @@
1
+ /**
2
+ * Menu Content component - the menu panel with items.
3
+ */
4
+
5
+ import {
6
+ type HTMLAttributes,
7
+ type ReactNode,
8
+ forwardRef,
9
+ useCallback,
10
+ useEffect,
11
+ useRef,
12
+ } from "react";
13
+ import { createPortal } from "react-dom";
14
+ import { useMenuContext } from "./menu-context.js";
15
+
16
+ export interface MenuContentProps extends HTMLAttributes<HTMLDivElement> {
17
+ /** Menu content */
18
+ children?: ReactNode;
19
+ /** Container element for portal (defaults to document.body) */
20
+ container?: HTMLElement | null;
21
+ /** Force mount even when closed (for animations) */
22
+ forceMount?: boolean;
23
+ }
24
+
25
+ /**
26
+ * Menu content panel with roving focus and type-ahead.
27
+ * Renders in a portal by default.
28
+ *
29
+ * @example
30
+ * ```tsx
31
+ * <Menu.Content>
32
+ * <Menu.Item value="edit">Edit</Menu.Item>
33
+ * <Menu.Item value="delete">Delete</Menu.Item>
34
+ * </Menu.Content>
35
+ * ```
36
+ */
37
+ export const MenuContent = forwardRef<HTMLDivElement, MenuContentProps>(
38
+ ({ children, container, forceMount = false, onKeyDown, ...restProps }, ref) => {
39
+ const { behavior, open } = useMenuContext("Menu.Content");
40
+ const internalRef = useRef<HTMLDivElement>(null);
41
+
42
+ // Register content element with behavior
43
+ useEffect(() => {
44
+ if (open) {
45
+ const element = internalRef.current;
46
+ behavior.setContentElement(element);
47
+ return () => {
48
+ behavior.setContentElement(null);
49
+ };
50
+ }
51
+ }, [behavior, open]);
52
+
53
+ // Handle keyboard events
54
+ const handleKeyDown = useCallback(
55
+ (event: React.KeyboardEvent<HTMLDivElement>) => {
56
+ behavior.handleContentKeyDown(event.nativeEvent);
57
+ onKeyDown?.(event);
58
+ },
59
+ [behavior, onKeyDown]
60
+ );
61
+
62
+ // Get content props from behavior
63
+ const contentProps = behavior.getContentProps();
64
+
65
+ // Merge refs
66
+ const mergedRef = useCallback(
67
+ (element: HTMLDivElement | null) => {
68
+ (internalRef as React.MutableRefObject<HTMLDivElement | null>).current = element;
69
+ if (typeof ref === "function") {
70
+ ref(element);
71
+ } else if (ref) {
72
+ (ref as React.MutableRefObject<HTMLDivElement | null>).current = element;
73
+ }
74
+ },
75
+ [ref]
76
+ );
77
+
78
+ // Don't render if closed and not force mounted
79
+ if (!open && !forceMount) {
80
+ return null;
81
+ }
82
+
83
+ const content = (
84
+ <div
85
+ ref={mergedRef}
86
+ id={contentProps.id}
87
+ role={contentProps.role}
88
+ aria-labelledby={contentProps["aria-labelledby"]}
89
+ aria-orientation={contentProps["aria-orientation"]}
90
+ tabIndex={contentProps.tabIndex}
91
+ data-state={open ? "open" : "closed"}
92
+ onKeyDown={handleKeyDown}
93
+ {...restProps}
94
+ >
95
+ {children}
96
+ </div>
97
+ );
98
+
99
+ // Render in portal
100
+ const portalContainer = container ?? (typeof document !== "undefined" ? document.body : null);
101
+ if (portalContainer) {
102
+ return createPortal(content, portalContainer);
103
+ }
104
+
105
+ return content;
106
+ }
107
+ );
108
+
109
+ MenuContent.displayName = "Menu.Content";
@@ -0,0 +1,17 @@
1
+ /**
2
+ * Menu context for compound component pattern.
3
+ */
4
+
5
+ import type { MenuBehavior } from "@hypoth-ui/primitives-dom";
6
+ import { createCompoundContext } from "../../utils/create-context.js";
7
+
8
+ export interface MenuContextValue {
9
+ /** Menu behavior instance */
10
+ behavior: MenuBehavior;
11
+ /** Whether menu is open */
12
+ open: boolean;
13
+ /** Set open state */
14
+ setOpen: (open: boolean) => void;
15
+ }
16
+
17
+ export const [MenuProvider, useMenuContext] = createCompoundContext<MenuContextValue>("Menu");
@@ -0,0 +1,108 @@
1
+ /**
2
+ * Menu Item component - a selectable item in the menu.
3
+ */
4
+
5
+ import {
6
+ type HTMLAttributes,
7
+ type ReactNode,
8
+ forwardRef,
9
+ useCallback,
10
+ useEffect,
11
+ useRef,
12
+ } from "react";
13
+ import { useMenuContext } from "./menu-context.js";
14
+
15
+ export interface MenuItemProps extends HTMLAttributes<HTMLDivElement> {
16
+ /** Item content */
17
+ children?: ReactNode;
18
+ /** Value passed to onSelect */
19
+ value?: string;
20
+ /** Whether item is disabled */
21
+ disabled?: boolean;
22
+ }
23
+
24
+ /**
25
+ * A selectable item in the menu.
26
+ *
27
+ * @example
28
+ * ```tsx
29
+ * <Menu.Item value="edit">Edit</Menu.Item>
30
+ * <Menu.Item value="delete" disabled>Delete</Menu.Item>
31
+ * ```
32
+ */
33
+ export const MenuItem = forwardRef<HTMLDivElement, MenuItemProps>(
34
+ ({ children, value = "", disabled = false, onClick, onPointerEnter, ...restProps }, ref) => {
35
+ const { behavior } = useMenuContext("Menu.Item");
36
+ const internalRef = useRef<HTMLDivElement>(null);
37
+ const indexRef = useRef<number>(-1);
38
+
39
+ // Register item with behavior
40
+ useEffect(() => {
41
+ const element = internalRef.current;
42
+ if (element) {
43
+ behavior.registerItem(element);
44
+ // Get index after registration
45
+ indexRef.current = behavior.context.items.indexOf(element);
46
+ return () => {
47
+ behavior.unregisterItem(element);
48
+ };
49
+ }
50
+ }, [behavior]);
51
+
52
+ // Handle click
53
+ const handleClick = useCallback(
54
+ (event: React.MouseEvent<HTMLDivElement>) => {
55
+ if (!disabled) {
56
+ behavior.handleItemClick(indexRef.current, value);
57
+ }
58
+ onClick?.(event);
59
+ },
60
+ [behavior, disabled, value, onClick]
61
+ );
62
+
63
+ // Handle pointer enter (hover)
64
+ const handlePointerEnter = useCallback(
65
+ (event: React.PointerEvent<HTMLDivElement>) => {
66
+ if (!disabled) {
67
+ behavior.handleItemPointerEnter(indexRef.current);
68
+ }
69
+ onPointerEnter?.(event);
70
+ },
71
+ [behavior, disabled, onPointerEnter]
72
+ );
73
+
74
+ // Get item props from behavior (need index)
75
+ const itemProps = behavior.getItemProps(indexRef.current, { disabled });
76
+
77
+ // Merge refs
78
+ const mergedRef = useCallback(
79
+ (element: HTMLDivElement | null) => {
80
+ (internalRef as React.MutableRefObject<HTMLDivElement | null>).current = element;
81
+ if (typeof ref === "function") {
82
+ ref(element);
83
+ } else if (ref) {
84
+ (ref as React.MutableRefObject<HTMLDivElement | null>).current = element;
85
+ }
86
+ },
87
+ [ref]
88
+ );
89
+
90
+ return (
91
+ <div
92
+ ref={mergedRef}
93
+ role={itemProps.role}
94
+ tabIndex={itemProps.tabIndex}
95
+ aria-disabled={itemProps["aria-disabled"]}
96
+ data-highlighted={itemProps["data-highlighted"]}
97
+ data-value={value}
98
+ onClick={handleClick}
99
+ onPointerEnter={handlePointerEnter}
100
+ {...restProps}
101
+ >
102
+ {children}
103
+ </div>
104
+ );
105
+ }
106
+ );
107
+
108
+ MenuItem.displayName = "Menu.Item";
@@ -0,0 +1,32 @@
1
+ /**
2
+ * Menu Label component - non-interactive label for a group of items.
3
+ */
4
+
5
+ import { type HTMLAttributes, type ReactNode, forwardRef } from "react";
6
+
7
+ export interface MenuLabelProps extends HTMLAttributes<HTMLDivElement> {
8
+ /** Label content */
9
+ children?: ReactNode;
10
+ }
11
+
12
+ /**
13
+ * Non-interactive label for a group of menu items.
14
+ *
15
+ * @example
16
+ * ```tsx
17
+ * <Menu.Label>Actions</Menu.Label>
18
+ * <Menu.Item value="edit">Edit</Menu.Item>
19
+ * <Menu.Item value="delete">Delete</Menu.Item>
20
+ * ```
21
+ */
22
+ export const MenuLabel = forwardRef<HTMLDivElement, MenuLabelProps>(
23
+ ({ children, ...restProps }, ref) => {
24
+ return (
25
+ <div ref={ref} role="presentation" {...restProps}>
26
+ {children}
27
+ </div>
28
+ );
29
+ }
30
+ );
31
+
32
+ MenuLabel.displayName = "Menu.Label";
@@ -0,0 +1,108 @@
1
+ /**
2
+ * Menu Root component - provides context to all Menu compound components.
3
+ */
4
+
5
+ import { type Placement, createMenuBehavior } from "@hypoth-ui/primitives-dom";
6
+ import { type ReactNode, useCallback, useMemo, useState } from "react";
7
+ import { useStableId } from "../../hooks/use-stable-id.js";
8
+ import { MenuProvider } from "./menu-context.js";
9
+
10
+ export interface MenuRootProps {
11
+ /** Menu content */
12
+ children?: ReactNode;
13
+ /** Custom ID for the menu (SSR-safe auto-generated if not provided) */
14
+ id?: string;
15
+ /** Controlled open state */
16
+ open?: boolean;
17
+ /** Default open state (uncontrolled) */
18
+ defaultOpen?: boolean;
19
+ /** Called when open state changes */
20
+ onOpenChange?: (open: boolean) => void;
21
+ /** Called when an item is selected */
22
+ onSelect?: (value: string) => void;
23
+ /** Placement relative to trigger */
24
+ placement?: Placement;
25
+ /** Offset from trigger in pixels */
26
+ offset?: number;
27
+ /** Whether to flip placement on viewport edge */
28
+ flip?: boolean;
29
+ /** Whether to loop navigation at ends */
30
+ loop?: boolean;
31
+ }
32
+
33
+ /**
34
+ * Root component for Menu compound pattern.
35
+ * Provides context to Trigger, Content, and Item.
36
+ *
37
+ * @example
38
+ * ```tsx
39
+ * <Menu.Root onSelect={(value) => console.log(value)}>
40
+ * <Menu.Trigger>Open Menu</Menu.Trigger>
41
+ * <Menu.Content>
42
+ * <Menu.Item value="edit">Edit</Menu.Item>
43
+ * <Menu.Item value="delete">Delete</Menu.Item>
44
+ * </Menu.Content>
45
+ * </Menu.Root>
46
+ * ```
47
+ */
48
+ export function MenuRoot({
49
+ children,
50
+ id,
51
+ open: controlledOpen,
52
+ defaultOpen = false,
53
+ onOpenChange,
54
+ onSelect,
55
+ placement = "bottom-start",
56
+ offset = 4,
57
+ flip = true,
58
+ loop = true,
59
+ }: MenuRootProps) {
60
+ // Generate SSR-safe stable ID using React 18's useId under the hood
61
+ const stableId = useStableId({ id, prefix: "menu" });
62
+
63
+ // Support both controlled and uncontrolled modes
64
+ const [internalOpen, setInternalOpen] = useState(defaultOpen);
65
+ const isControlled = controlledOpen !== undefined;
66
+ const open = isControlled ? controlledOpen : internalOpen;
67
+
68
+ const setOpen = useCallback(
69
+ (nextOpen: boolean) => {
70
+ if (!isControlled) {
71
+ setInternalOpen(nextOpen);
72
+ }
73
+ onOpenChange?.(nextOpen);
74
+ },
75
+ [isControlled, onOpenChange]
76
+ );
77
+
78
+ // Create behavior instance - intentionally created once with initial values
79
+ // biome-ignore lint/correctness/useExhaustiveDependencies: behavior is created once, open state synced via setOpen callback
80
+ const behavior = useMemo(
81
+ () =>
82
+ createMenuBehavior({
83
+ defaultOpen: open,
84
+ placement,
85
+ offset,
86
+ flip,
87
+ loop,
88
+ onOpenChange: setOpen,
89
+ onSelect,
90
+ // Use SSR-safe stable ID generator
91
+ generateId: () => stableId,
92
+ }),
93
+ [stableId]
94
+ );
95
+
96
+ const contextValue = useMemo(
97
+ () => ({
98
+ behavior,
99
+ open,
100
+ setOpen,
101
+ }),
102
+ [behavior, open, setOpen]
103
+ );
104
+
105
+ return <MenuProvider value={contextValue}>{children}</MenuProvider>;
106
+ }
107
+
108
+ MenuRoot.displayName = "Menu.Root";
@@ -0,0 +1,24 @@
1
+ /**
2
+ * Menu Separator component - visual separator between items.
3
+ */
4
+
5
+ import { type HTMLAttributes, forwardRef } from "react";
6
+
7
+ export interface MenuSeparatorProps extends HTMLAttributes<HTMLDivElement> {}
8
+
9
+ /**
10
+ * Visual separator between menu items.
11
+ *
12
+ * @example
13
+ * ```tsx
14
+ * <Menu.Item value="edit">Edit</Menu.Item>
15
+ * <Menu.Separator />
16
+ * <Menu.Item value="delete">Delete</Menu.Item>
17
+ * ```
18
+ */
19
+ export const MenuSeparator = forwardRef<HTMLDivElement, MenuSeparatorProps>((props, ref) => {
20
+ // biome-ignore lint/a11y/useFocusableInteractive: separator is decorative, not interactive
21
+ return <div ref={ref} role="separator" aria-orientation="horizontal" {...props} />;
22
+ });
23
+
24
+ MenuSeparator.displayName = "Menu.Separator";
@@ -0,0 +1,104 @@
1
+ /**
2
+ * Menu Trigger component - opens the menu when activated.
3
+ */
4
+
5
+ import {
6
+ type ButtonHTMLAttributes,
7
+ type ReactNode,
8
+ forwardRef,
9
+ useCallback,
10
+ useEffect,
11
+ useRef,
12
+ } from "react";
13
+ import { Slot } from "../../primitives/slot.js";
14
+ import { useMenuContext } from "./menu-context.js";
15
+
16
+ export interface MenuTriggerProps extends ButtonHTMLAttributes<HTMLButtonElement> {
17
+ /** Trigger content */
18
+ children?: ReactNode;
19
+ /** Render as child element (polymorphic) */
20
+ asChild?: boolean;
21
+ }
22
+
23
+ /**
24
+ * Trigger button that opens the menu.
25
+ * Supports asChild for custom trigger elements.
26
+ *
27
+ * @example
28
+ * ```tsx
29
+ * <Menu.Trigger>Open Menu</Menu.Trigger>
30
+ *
31
+ * <Menu.Trigger asChild>
32
+ * <button className="custom-button">Custom Trigger</button>
33
+ * </Menu.Trigger>
34
+ * ```
35
+ */
36
+ export const MenuTrigger = forwardRef<HTMLButtonElement, MenuTriggerProps>(
37
+ ({ children, asChild = false, onClick, onKeyDown, ...restProps }, ref) => {
38
+ const { behavior } = useMenuContext("Menu.Trigger");
39
+ const internalRef = useRef<HTMLButtonElement>(null);
40
+
41
+ // Register trigger element with behavior
42
+ useEffect(() => {
43
+ const element = internalRef.current;
44
+ behavior.setTriggerElement(element);
45
+ return () => {
46
+ behavior.setTriggerElement(null);
47
+ };
48
+ }, [behavior]);
49
+
50
+ // Handle click to toggle menu
51
+ const handleClick = useCallback(
52
+ (event: React.MouseEvent<HTMLButtonElement>) => {
53
+ behavior.toggle();
54
+ onClick?.(event);
55
+ },
56
+ [behavior, onClick]
57
+ );
58
+
59
+ // Handle keyboard navigation
60
+ const handleKeyDown = useCallback(
61
+ (event: React.KeyboardEvent<HTMLButtonElement>) => {
62
+ behavior.handleTriggerKeyDown(event.nativeEvent);
63
+ onKeyDown?.(event);
64
+ },
65
+ [behavior, onKeyDown]
66
+ );
67
+
68
+ // Get trigger props from behavior
69
+ const triggerProps = behavior.getTriggerProps();
70
+
71
+ const Component = asChild ? Slot : "button";
72
+
73
+ // Merge refs
74
+ const mergedRef = useCallback(
75
+ (element: HTMLButtonElement | null) => {
76
+ (internalRef as React.MutableRefObject<HTMLButtonElement | null>).current = element;
77
+ if (typeof ref === "function") {
78
+ ref(element);
79
+ } else if (ref) {
80
+ (ref as React.MutableRefObject<HTMLButtonElement | null>).current = element;
81
+ }
82
+ },
83
+ [ref]
84
+ );
85
+
86
+ return (
87
+ <Component
88
+ ref={mergedRef}
89
+ type={asChild ? undefined : "button"}
90
+ id={triggerProps.id}
91
+ aria-haspopup={triggerProps["aria-haspopup"]}
92
+ aria-expanded={triggerProps["aria-expanded"]}
93
+ aria-controls={triggerProps["aria-controls"]}
94
+ onClick={handleClick}
95
+ onKeyDown={handleKeyDown}
96
+ {...restProps}
97
+ >
98
+ {children}
99
+ </Component>
100
+ );
101
+ }
102
+ );
103
+
104
+ MenuTrigger.displayName = "Menu.Trigger";