@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,4 @@
1
+ export { Field, type FieldProps } from "./field.js";
2
+ export { Label, type LabelProps } from "./label.js";
3
+ export { FieldDescription, type FieldDescriptionProps } from "./field-description.js";
4
+ export { FieldError, type FieldErrorProps } from "./field-error.js";
@@ -0,0 +1,40 @@
1
+ import type React from "react";
2
+ import { type HTMLAttributes, createElement, forwardRef, useEffect, useRef } from "react";
3
+
4
+ export interface LabelProps extends HTMLAttributes<HTMLElement> {
5
+ /** For attribute linking to input */
6
+ htmlFor?: string;
7
+ /** Label content */
8
+ children?: React.ReactNode;
9
+ }
10
+
11
+ /**
12
+ * React wrapper for ds-label Web Component.
13
+ * Label for form fields with automatic ID association.
14
+ */
15
+ export const Label = forwardRef<HTMLElement, LabelProps>((props, forwardedRef) => {
16
+ const { htmlFor, children, className, ...rest } = props;
17
+
18
+ const internalRef = useRef<HTMLElement>(null);
19
+
20
+ useEffect(() => {
21
+ if (typeof forwardedRef === "function") {
22
+ forwardedRef(internalRef.current);
23
+ } else if (forwardedRef) {
24
+ (forwardedRef as React.MutableRefObject<HTMLElement | null>).current = internalRef.current;
25
+ }
26
+ }, [forwardedRef]);
27
+
28
+ return createElement(
29
+ "ds-label",
30
+ {
31
+ ref: internalRef,
32
+ for: htmlFor,
33
+ class: className,
34
+ ...rest,
35
+ },
36
+ children
37
+ );
38
+ });
39
+
40
+ Label.displayName = "Label";
@@ -0,0 +1,42 @@
1
+ import { html } from "lit";
2
+ import { DSElement } from "../../base/ds-element.js";
3
+ import { define } from "../../registry/define.js";
4
+
5
+ /**
6
+ * Description/help text component for form fields.
7
+ *
8
+ * Used within ds-field to provide supplementary help text that is
9
+ * automatically associated with the form control via aria-describedby.
10
+ *
11
+ * @element ds-field-description
12
+ *
13
+ * @slot - Description text content
14
+ *
15
+ * @example
16
+ * ```html
17
+ * <ds-field>
18
+ * <ds-label>Password</ds-label>
19
+ * <ds-input type="password"></ds-input>
20
+ * <ds-field-description>
21
+ * Must be at least 8 characters with one number
22
+ * </ds-field-description>
23
+ * </ds-field>
24
+ * ```
25
+ */
26
+ export class DsFieldDescription extends DSElement {
27
+ override render() {
28
+ return html`
29
+ <div class="ds-field-description" part="description">
30
+ <slot></slot>
31
+ </div>
32
+ `;
33
+ }
34
+ }
35
+
36
+ define("ds-field-description", DsFieldDescription);
37
+
38
+ declare global {
39
+ interface HTMLElementTagNameMap {
40
+ "ds-field-description": DsFieldDescription;
41
+ }
42
+ }
@@ -0,0 +1,46 @@
1
+ import { html } from "lit";
2
+ import { DSElement } from "../../base/ds-element.js";
3
+ import { define } from "../../registry/define.js";
4
+
5
+ /**
6
+ * Error message component for form fields.
7
+ *
8
+ * Used within ds-field to display validation error messages that are
9
+ * automatically associated with the form control via aria-describedby.
10
+ * Error messages take precedence over descriptions in the ARIA description.
11
+ *
12
+ * @element ds-field-error
13
+ *
14
+ * @slot - Error message text content
15
+ *
16
+ * @example
17
+ * ```html
18
+ * <ds-field>
19
+ * <ds-label>Email</ds-label>
20
+ * <ds-input type="email" error></ds-input>
21
+ * <ds-field-error>Please enter a valid email address</ds-field-error>
22
+ * </ds-field>
23
+ * ```
24
+ */
25
+ export class DsFieldError extends DSElement {
26
+ override render() {
27
+ return html`
28
+ <div
29
+ class="ds-field-error"
30
+ part="error"
31
+ role="alert"
32
+ aria-live="polite"
33
+ >
34
+ <slot></slot>
35
+ </div>
36
+ `;
37
+ }
38
+ }
39
+
40
+ define("ds-field-error", DsFieldError);
41
+
42
+ declare global {
43
+ interface HTMLElementTagNameMap {
44
+ "ds-field-error": DsFieldError;
45
+ }
46
+ }
@@ -0,0 +1,210 @@
1
+ import { html } from "lit";
2
+ import { property, state } from "lit/decorators.js";
3
+ import { DSElement } from "../../base/ds-element.js";
4
+ import { define } from "../../registry/define.js";
5
+
6
+ // Import child components to ensure they're registered
7
+ import "./label.js";
8
+ import "./field-description.js";
9
+ import "./field-error.js";
10
+
11
+ /**
12
+ * Field container component for form controls.
13
+ *
14
+ * Provides consistent layout and automatic ARIA attribute composition
15
+ * for form fields. Associates labels, descriptions, and error messages
16
+ * with the form control for accessibility.
17
+ *
18
+ * @element ds-field
19
+ *
20
+ * @slot - Field contents (label, form control, description, error)
21
+ *
22
+ * @csspart container - The field container element
23
+ *
24
+ * @cssprop --ds-field-gap - Gap between field children (default: 0.5rem)
25
+ * @cssprop --ds-field-error-color - Error message color
26
+ *
27
+ * @example
28
+ * ```html
29
+ * <ds-field required>
30
+ * <ds-label>Email address</ds-label>
31
+ * <ds-field-description>We'll never share your email</ds-field-description>
32
+ * <ds-input type="email" name="email"></ds-input>
33
+ * <ds-field-error>Please enter a valid email</ds-field-error>
34
+ * </ds-field>
35
+ * ```
36
+ */
37
+ export class DsField extends DSElement {
38
+ /** Marks the field as required */
39
+ @property({ type: Boolean, reflect: true })
40
+ required = false;
41
+
42
+ /** Whether the field is disabled */
43
+ @property({ type: Boolean, reflect: true })
44
+ disabled = false;
45
+
46
+ /** Generated unique ID for ARIA associations */
47
+ @state()
48
+ private fieldId = "";
49
+
50
+ /** Whether an error child is present */
51
+ @state()
52
+ private hasError = false;
53
+
54
+ /** Whether a description child is present */
55
+ @state()
56
+ private hasDescription = false;
57
+
58
+ private observer: MutationObserver | null = null;
59
+
60
+ override connectedCallback(): void {
61
+ super.connectedCallback();
62
+
63
+ // Generate unique ID for this field instance
64
+ this.fieldId = `field-${crypto.randomUUID().slice(0, 8)}`;
65
+
66
+ // Set up mutation observer to track child changes
67
+ this.observer = new MutationObserver(() => this.updateChildComponents());
68
+ this.observer.observe(this, { childList: true, subtree: true });
69
+
70
+ // Initial setup after first render
71
+ this.updateComplete.then(() => {
72
+ this.updateChildComponents();
73
+ });
74
+ }
75
+
76
+ override disconnectedCallback(): void {
77
+ super.disconnectedCallback();
78
+ this.observer?.disconnect();
79
+ this.observer = null;
80
+ }
81
+
82
+ /**
83
+ * Updates ARIA attributes on child components based on field structure.
84
+ */
85
+ private updateChildComponents(): void {
86
+ // Find child components
87
+ const label = this.querySelector("ds-label");
88
+ const description = this.querySelector("ds-field-description");
89
+ const error = this.querySelector("ds-field-error");
90
+ const formControl = this.querySelector(
91
+ "ds-input, ds-textarea, ds-checkbox, ds-radio-group, ds-switch, ds-select, ds-combobox, ds-date-picker, ds-slider, ds-number-input, ds-file-upload, ds-time-picker, ds-pin-input, input, textarea, select"
92
+ );
93
+
94
+ // Track which components are present
95
+ this.hasError = !!error && error.textContent?.trim() !== "";
96
+ this.hasDescription = !!description && description.textContent?.trim() !== "";
97
+
98
+ // Assign IDs to components
99
+ if (label) {
100
+ const labelId = `${this.fieldId}-label`;
101
+ label.id = labelId;
102
+
103
+ // Set data-required on label for styling
104
+ if (this.required) {
105
+ label.setAttribute("data-required", "");
106
+ } else {
107
+ label.removeAttribute("data-required");
108
+ }
109
+ }
110
+
111
+ if (description) {
112
+ description.id = `${this.fieldId}-desc`;
113
+ }
114
+
115
+ if (error) {
116
+ error.id = `${this.fieldId}-error`;
117
+ }
118
+
119
+ // Compose ARIA attributes for form control
120
+ if (formControl) {
121
+ // Build aria-labelledby
122
+ if (label) {
123
+ formControl.setAttribute("aria-labelledby", label.id);
124
+ }
125
+
126
+ // Build aria-describedby (error first, then description)
127
+ const describedByIds: string[] = [];
128
+ if (this.hasError && error) {
129
+ describedByIds.push(error.id);
130
+ }
131
+ if (this.hasDescription && description) {
132
+ describedByIds.push(description.id);
133
+ }
134
+
135
+ if (describedByIds.length > 0) {
136
+ formControl.setAttribute("aria-describedby", describedByIds.join(" "));
137
+ } else {
138
+ formControl.removeAttribute("aria-describedby");
139
+ }
140
+
141
+ // Set aria-invalid if error is present
142
+ if (this.hasError) {
143
+ formControl.setAttribute("aria-invalid", "true");
144
+ // Also set error property if it's a design system component
145
+ if ("error" in formControl) {
146
+ (formControl as { error: boolean }).error = true;
147
+ }
148
+ } else {
149
+ formControl.setAttribute("aria-invalid", "false");
150
+ if ("error" in formControl) {
151
+ (formControl as { error: boolean }).error = false;
152
+ }
153
+ }
154
+
155
+ // Set aria-required if field is required
156
+ if (this.required) {
157
+ formControl.setAttribute("aria-required", "true");
158
+ if ("required" in formControl) {
159
+ (formControl as { required: boolean }).required = true;
160
+ }
161
+ }
162
+
163
+ // Set disabled state
164
+ if (this.disabled) {
165
+ formControl.setAttribute("aria-disabled", "true");
166
+ if ("disabled" in formControl) {
167
+ (formControl as { disabled: boolean }).disabled = true;
168
+ }
169
+ }
170
+ }
171
+
172
+ // Update data attributes on self for CSS styling
173
+ if (this.hasError) {
174
+ this.setAttribute("data-error", "");
175
+ } else {
176
+ this.removeAttribute("data-error");
177
+ }
178
+
179
+ if (this.disabled) {
180
+ this.setAttribute("data-disabled", "");
181
+ } else {
182
+ this.removeAttribute("data-disabled");
183
+ }
184
+ }
185
+
186
+ override updated(changedProperties: Map<string, unknown>): void {
187
+ super.updated(changedProperties);
188
+
189
+ // Re-apply ARIA attributes when required or disabled changes
190
+ if (changedProperties.has("required") || changedProperties.has("disabled")) {
191
+ this.updateChildComponents();
192
+ }
193
+ }
194
+
195
+ override render() {
196
+ return html`
197
+ <div class="ds-field" part="container">
198
+ <slot @slotchange=${this.updateChildComponents}></slot>
199
+ </div>
200
+ `;
201
+ }
202
+ }
203
+
204
+ define("ds-field", DsField);
205
+
206
+ declare global {
207
+ interface HTMLElementTagNameMap {
208
+ "ds-field": DsField;
209
+ }
210
+ }
@@ -0,0 +1,54 @@
1
+ import { html } from "lit";
2
+ import { property } from "lit/decorators.js";
3
+ import { DSElement } from "../../base/ds-element.js";
4
+ import { define } from "../../registry/define.js";
5
+
6
+ /**
7
+ * Label component for form fields.
8
+ *
9
+ * Used within ds-field to provide an accessible label that is
10
+ * automatically associated with the form control via aria-labelledby.
11
+ *
12
+ * @element ds-label
13
+ *
14
+ * @slot - Label text content
15
+ *
16
+ * @example
17
+ * ```html
18
+ * <ds-field>
19
+ * <ds-label>Email address</ds-label>
20
+ * <ds-input type="email"></ds-input>
21
+ * </ds-field>
22
+ * ```
23
+ */
24
+ export class DsLabel extends DSElement {
25
+ /**
26
+ * ID of the associated form control.
27
+ * Typically set automatically by the parent ds-field component.
28
+ */
29
+ @property({ type: String, attribute: "for" })
30
+ for = "";
31
+
32
+ override render() {
33
+ return html`
34
+ <label
35
+ class="ds-label"
36
+ part="label"
37
+ for=${this.for || nothing}
38
+ >
39
+ <slot></slot>
40
+ </label>
41
+ `;
42
+ }
43
+ }
44
+
45
+ // Import nothing for conditional attributes
46
+ import { nothing } from "lit";
47
+
48
+ define("ds-label", DsLabel);
49
+
50
+ declare global {
51
+ interface HTMLElementTagNameMap {
52
+ "ds-label": DsLabel;
53
+ }
54
+ }
@@ -0,0 +1,26 @@
1
+ /**
2
+ * FileUpload context for compound component pattern.
3
+ */
4
+
5
+ import type { FileInfo, FileUploadBehavior } from "@hypoth-ui/primitives-dom";
6
+ import { createCompoundContext } from "../../utils/create-context.js";
7
+
8
+ export interface FileUploadContextValue {
9
+ /** FileUpload behavior instance */
10
+ behavior: FileUploadBehavior;
11
+ /** Current files */
12
+ files: FileInfo[];
13
+ /** Is dragging over dropzone */
14
+ isDragging: boolean;
15
+ /** Set dragging state */
16
+ setIsDragging: (dragging: boolean) => void;
17
+ /** Input ref for triggering file dialog */
18
+ inputRef: React.RefObject<HTMLInputElement>;
19
+ /** Open file dialog */
20
+ openFileDialog: () => void;
21
+ /** Disabled state */
22
+ disabled: boolean;
23
+ }
24
+
25
+ export const [FileUploadProvider, useFileUploadContext] =
26
+ createCompoundContext<FileUploadContextValue>("FileUpload");
@@ -0,0 +1,111 @@
1
+ /**
2
+ * FileUpload Dropzone component - the drop target area.
3
+ */
4
+
5
+ import {
6
+ type DragEvent,
7
+ type HTMLAttributes,
8
+ type KeyboardEvent,
9
+ type ReactNode,
10
+ forwardRef,
11
+ useCallback,
12
+ } from "react";
13
+ import { useFileUploadContext } from "./file-upload-context.js";
14
+
15
+ export interface FileUploadDropzoneProps extends HTMLAttributes<HTMLDivElement> {
16
+ /** Dropzone content */
17
+ children?: ReactNode;
18
+ }
19
+
20
+ /**
21
+ * The dropzone area for drag-and-drop file uploads.
22
+ * Also handles click-to-upload functionality.
23
+ *
24
+ * @example
25
+ * ```tsx
26
+ * <FileUpload.Dropzone className="dropzone">
27
+ * <p>Drop files here or click to upload</p>
28
+ * </FileUpload.Dropzone>
29
+ * ```
30
+ */
31
+ export const FileUploadDropzone = forwardRef<HTMLDivElement, FileUploadDropzoneProps>(
32
+ ({ children, className, onClick, onKeyDown, ...restProps }, ref) => {
33
+ const { behavior, isDragging, setIsDragging, openFileDialog, disabled } =
34
+ useFileUploadContext("FileUpload.Dropzone");
35
+
36
+ const dropzoneProps = behavior.getDropzoneProps();
37
+
38
+ const handleClick = useCallback(
39
+ (event: React.MouseEvent<HTMLDivElement>) => {
40
+ openFileDialog();
41
+ onClick?.(event);
42
+ },
43
+ [openFileDialog, onClick]
44
+ );
45
+
46
+ const handleKeyDown = useCallback(
47
+ (event: KeyboardEvent<HTMLDivElement>) => {
48
+ if (behavior.handleKeyDown(event.nativeEvent)) {
49
+ openFileDialog();
50
+ }
51
+ onKeyDown?.(event);
52
+ },
53
+ [behavior, openFileDialog, onKeyDown]
54
+ );
55
+
56
+ const handleDragEnter = useCallback(
57
+ (event: DragEvent<HTMLDivElement>) => {
58
+ behavior.handleDragEnter(event.nativeEvent);
59
+ setIsDragging(behavior.state.isDragging);
60
+ },
61
+ [behavior, setIsDragging]
62
+ );
63
+
64
+ const handleDragLeave = useCallback(
65
+ (event: DragEvent<HTMLDivElement>) => {
66
+ behavior.handleDragLeave(event.nativeEvent);
67
+ setIsDragging(behavior.state.isDragging);
68
+ },
69
+ [behavior, setIsDragging]
70
+ );
71
+
72
+ const handleDragOver = useCallback(
73
+ (event: DragEvent<HTMLDivElement>) => {
74
+ behavior.handleDragOver(event.nativeEvent);
75
+ },
76
+ [behavior]
77
+ );
78
+
79
+ const handleDrop = useCallback(
80
+ (event: DragEvent<HTMLDivElement>) => {
81
+ behavior.handleDrop(event.nativeEvent);
82
+ setIsDragging(false);
83
+ },
84
+ [behavior, setIsDragging]
85
+ );
86
+
87
+ return (
88
+ <div
89
+ ref={ref}
90
+ role={dropzoneProps.role}
91
+ tabIndex={dropzoneProps.tabIndex}
92
+ aria-label={dropzoneProps["aria-label"]}
93
+ aria-disabled={dropzoneProps["aria-disabled"]}
94
+ className={className}
95
+ data-dragging={isDragging || undefined}
96
+ data-disabled={disabled || undefined}
97
+ onClick={handleClick}
98
+ onKeyDown={handleKeyDown}
99
+ onDragEnter={handleDragEnter}
100
+ onDragLeave={handleDragLeave}
101
+ onDragOver={handleDragOver}
102
+ onDrop={handleDrop}
103
+ {...restProps}
104
+ >
105
+ {children}
106
+ </div>
107
+ );
108
+ }
109
+ );
110
+
111
+ FileUploadDropzone.displayName = "FileUpload.Dropzone";
@@ -0,0 +1,86 @@
1
+ /**
2
+ * FileUpload Input component - hidden file input element.
3
+ */
4
+
5
+ import { type ChangeEvent, type InputHTMLAttributes, forwardRef, useCallback } from "react";
6
+ import { useFileUploadContext } from "./file-upload-context.js";
7
+
8
+ export interface FileUploadInputProps
9
+ extends Omit<InputHTMLAttributes<HTMLInputElement>, "type" | "onChange"> {}
10
+
11
+ /**
12
+ * Hidden file input element that handles file selection.
13
+ * Must be rendered within FileUpload.Root.
14
+ *
15
+ * @example
16
+ * ```tsx
17
+ * <FileUpload.Root>
18
+ * <FileUpload.Input />
19
+ * <FileUpload.Dropzone>...</FileUpload.Dropzone>
20
+ * </FileUpload.Root>
21
+ * ```
22
+ */
23
+ export const FileUploadInput = forwardRef<HTMLInputElement, FileUploadInputProps>(
24
+ ({ className, style, ...restProps }, ref) => {
25
+ const { behavior, inputRef, disabled } = useFileUploadContext("FileUpload.Input");
26
+
27
+ const inputProps = behavior.getInputProps();
28
+
29
+ const handleChange = useCallback(
30
+ (event: ChangeEvent<HTMLInputElement>) => {
31
+ const input = event.target;
32
+ if (input.files && input.files.length > 0) {
33
+ behavior.addFiles(input.files);
34
+ // Reset input so the same file can be selected again
35
+ input.value = "";
36
+ }
37
+ },
38
+ [behavior]
39
+ );
40
+
41
+ // Merge refs
42
+ const mergedRef = useCallback(
43
+ (element: HTMLInputElement | null) => {
44
+ (inputRef as React.MutableRefObject<HTMLInputElement | null>).current = element;
45
+ if (typeof ref === "function") {
46
+ ref(element);
47
+ } else if (ref) {
48
+ (ref as React.MutableRefObject<HTMLInputElement | null>).current = element;
49
+ }
50
+ },
51
+ [inputRef, ref]
52
+ );
53
+
54
+ // Default hidden styles
55
+ const hiddenStyles: React.CSSProperties = {
56
+ position: "absolute",
57
+ width: 1,
58
+ height: 1,
59
+ padding: 0,
60
+ margin: -1,
61
+ overflow: "hidden",
62
+ clip: "rect(0, 0, 0, 0)",
63
+ whiteSpace: "nowrap",
64
+ border: 0,
65
+ ...style,
66
+ };
67
+
68
+ return (
69
+ <input
70
+ ref={mergedRef}
71
+ type={inputProps.type}
72
+ accept={inputProps.accept}
73
+ multiple={inputProps.multiple}
74
+ disabled={disabled || inputProps.disabled}
75
+ aria-hidden={inputProps["aria-hidden"]}
76
+ tabIndex={inputProps.tabIndex}
77
+ className={className}
78
+ style={hiddenStyles}
79
+ onChange={handleChange}
80
+ {...restProps}
81
+ />
82
+ );
83
+ }
84
+ );
85
+
86
+ FileUploadInput.displayName = "FileUpload.Input";