@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,76 @@
1
+ import { createElement, forwardRef, useEffect, useRef } from "react";
2
+ import {
3
+ type ResponsiveProp,
4
+ generateResponsiveDataAttr,
5
+ isResponsiveObject,
6
+ resolveResponsiveValue,
7
+ } from "../primitives/responsive.js";
8
+
9
+ export type IconSize = "xs" | "sm" | "md" | "lg" | "xl";
10
+
11
+ /**
12
+ * Icon name from Lucide library (kebab-case format).
13
+ * This is a nominal type alias to document the expected format.
14
+ */
15
+ export type IconName = string;
16
+
17
+ export interface IconProps {
18
+ /** Icon name from Lucide library (kebab-case) */
19
+ name: string;
20
+ /**
21
+ * Icon size - supports responsive object syntax
22
+ * @example
23
+ * ```tsx
24
+ * // Single value
25
+ * <Icon name="check" size="md" />
26
+ *
27
+ * // Responsive
28
+ * <Icon name="check" size={{ base: "sm", md: "md", lg: "lg" }} />
29
+ * ```
30
+ */
31
+ size?: ResponsiveProp<IconSize>;
32
+ /** Accessible label. When omitted, icon is decorative. */
33
+ label?: string;
34
+ /** Custom color (CSS value) */
35
+ color?: string;
36
+ /** Additional CSS classes */
37
+ className?: string;
38
+ }
39
+
40
+ /**
41
+ * React wrapper for ds-icon Web Component.
42
+ * Provides type-safe props for icon display.
43
+ */
44
+ export const Icon = forwardRef<HTMLElement, IconProps>((props, forwardedRef) => {
45
+ const { name, size = "md", label, color, className, ...rest } = props;
46
+
47
+ const internalRef = useRef<HTMLElement>(null);
48
+
49
+ // Merge refs
50
+ useEffect(() => {
51
+ if (typeof forwardedRef === "function") {
52
+ forwardedRef(internalRef.current);
53
+ } else if (forwardedRef) {
54
+ (forwardedRef as React.MutableRefObject<HTMLElement | null>).current = internalRef.current;
55
+ }
56
+ }, [forwardedRef]);
57
+
58
+ // Resolve responsive size - use base value for the WC attribute
59
+ const resolvedSize = resolveResponsiveValue(size, "md");
60
+ const isResponsive = isResponsiveObject(size);
61
+ const responsiveSizeAttr = isResponsive ? generateResponsiveDataAttr(size) : undefined;
62
+
63
+ return createElement("ds-icon", {
64
+ ref: internalRef,
65
+ name,
66
+ size: resolvedSize,
67
+ label: label || undefined,
68
+ color: color || undefined,
69
+ class: className,
70
+ // Add responsive data attribute for CSS targeting
71
+ "data-size-responsive": responsiveSizeAttr,
72
+ ...rest,
73
+ });
74
+ });
75
+
76
+ Icon.displayName = "Icon";
@@ -0,0 +1,108 @@
1
+ /**
2
+ * Icon Adapter for Lucide Icons
3
+ *
4
+ * Provides a unified interface for accessing icons from the Lucide library.
5
+ * Uses createElement() for efficient SVG generation.
6
+ */
7
+
8
+ import { createElement, icons } from "lucide";
9
+ import type { IconNode } from "lucide";
10
+
11
+ /**
12
+ * Convert kebab-case to PascalCase for Lucide icon names
13
+ * e.g., "arrow-right" -> "ArrowRight"
14
+ */
15
+ function toPascalCase(str: string): string {
16
+ return str
17
+ .split("-")
18
+ .map((word) => word.charAt(0).toUpperCase() + word.slice(1).toLowerCase())
19
+ .join("");
20
+ }
21
+
22
+ /**
23
+ * Get an SVG element for the specified icon name.
24
+ *
25
+ * @param name - The icon name in kebab-case (e.g., "arrow-right", "search", "external-link")
26
+ * @param options - Optional attributes to apply to the SVG
27
+ * @returns SVGSVGElement or null if icon not found
28
+ *
29
+ * @example
30
+ * ```typescript
31
+ * const svg = getIconSvg("search");
32
+ * if (svg) {
33
+ * container.appendChild(svg);
34
+ * }
35
+ * ```
36
+ */
37
+ export function getIconSvg(
38
+ name: string,
39
+ options?: {
40
+ size?: number | string;
41
+ color?: string;
42
+ strokeWidth?: number | string;
43
+ }
44
+ ): SVGSVGElement | null {
45
+ // Convert kebab-case name to PascalCase for Lucide lookup
46
+ const pascalName = toPascalCase(name);
47
+
48
+ // Check if icon exists in Lucide
49
+ const iconNode = icons[pascalName as keyof typeof icons] as IconNode | undefined;
50
+
51
+ if (!iconNode) {
52
+ if (process.env.NODE_ENV !== "production") {
53
+ console.warn(`[ds-icon] Icon "${name}" not found in Lucide library.`);
54
+ }
55
+ return null;
56
+ }
57
+
58
+ // Build custom attributes to merge with default icon attrs
59
+ const customAttrs: Record<string, string | number> = {};
60
+
61
+ if (options?.size) {
62
+ customAttrs.width = options.size;
63
+ customAttrs.height = options.size;
64
+ }
65
+
66
+ if (options?.color) {
67
+ customAttrs.color = options.color;
68
+ }
69
+
70
+ if (options?.strokeWidth) {
71
+ customAttrs["stroke-width"] = options.strokeWidth;
72
+ }
73
+
74
+ // Merge custom attributes with the icon's default attributes
75
+ // IconNode is [tag, attrs, children?]
76
+ const [tag, defaultAttrs, children] = iconNode;
77
+ const mergedAttrs = { ...defaultAttrs, ...customAttrs };
78
+ const modifiedIconNode: IconNode = children ? [tag, mergedAttrs, children] : [tag, mergedAttrs];
79
+
80
+ const element = createElement(modifiedIconNode);
81
+
82
+ return element as SVGSVGElement;
83
+ }
84
+
85
+ /**
86
+ * Check if an icon name exists in the Lucide library.
87
+ *
88
+ * @param name - The icon name in kebab-case
89
+ * @returns True if the icon exists
90
+ */
91
+ export function hasIcon(name: string): boolean {
92
+ const pascalName = toPascalCase(name);
93
+ return pascalName in icons;
94
+ }
95
+
96
+ /**
97
+ * Get all available icon names.
98
+ *
99
+ * @returns Array of icon names in kebab-case
100
+ */
101
+ export function getAvailableIcons(): string[] {
102
+ return Object.keys(icons).map((name) =>
103
+ name
104
+ .replace(/([A-Z])/g, "-$1")
105
+ .toLowerCase()
106
+ .replace(/^-/, "")
107
+ );
108
+ }
@@ -0,0 +1,161 @@
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 { define } from "../../registry/define.js";
6
+ import { getIconSvg, hasIcon } from "./icon-adapter.js";
7
+
8
+ export type IconSize = "xs" | "sm" | "md" | "lg" | "xl";
9
+
10
+ /**
11
+ * Size mappings in pixels for SVG generation
12
+ */
13
+ const SIZE_MAP: Record<IconSize, number> = {
14
+ xs: 12,
15
+ sm: 16,
16
+ md: 20,
17
+ lg: 24,
18
+ xl: 32,
19
+ };
20
+
21
+ /**
22
+ * An accessible icon component with Lucide integration.
23
+ *
24
+ * @element ds-icon
25
+ *
26
+ * @example
27
+ * ```html
28
+ * <!-- Decorative icon (hidden from screen readers) -->
29
+ * <ds-icon name="search"></ds-icon>
30
+ *
31
+ * <!-- Meaningful icon (announced to screen readers) -->
32
+ * <ds-icon name="alert-triangle" label="Warning"></ds-icon>
33
+ * ```
34
+ */
35
+ export class DsIcon extends DSElement {
36
+ static override styles = [];
37
+
38
+ /**
39
+ * The icon name from Lucide library (kebab-case).
40
+ * e.g., "search", "arrow-right", "external-link"
41
+ */
42
+ @property({ type: String, reflect: true })
43
+ name = "";
44
+
45
+ /**
46
+ * The icon size.
47
+ */
48
+ @property({ type: String, reflect: true })
49
+ size: IconSize = "md";
50
+
51
+ /**
52
+ * Accessible label for meaningful icons.
53
+ * When provided, the icon is announced to screen readers.
54
+ * When omitted, the icon is decorative and hidden from screen readers.
55
+ */
56
+ @property({ type: String })
57
+ label = "";
58
+
59
+ /**
60
+ * Custom color for the icon.
61
+ * Accepts any valid CSS color value.
62
+ * Default is currentColor (inherits from text color).
63
+ */
64
+ @property({ type: String })
65
+ color = "";
66
+
67
+ /**
68
+ * Cached SVG element
69
+ */
70
+ @state()
71
+ private _svgElement: SVGSVGElement | null = null;
72
+
73
+ /**
74
+ * Track if icon is valid
75
+ */
76
+ @state()
77
+ private _isValidIcon = true;
78
+
79
+ override willUpdate(changedProperties: Map<string, unknown>): void {
80
+ if (changedProperties.has("name") || changedProperties.has("size")) {
81
+ this.updateSvg();
82
+ }
83
+ }
84
+
85
+ private updateSvg(): void {
86
+ if (!this.name) {
87
+ this._svgElement = null;
88
+ this._isValidIcon = false;
89
+ return;
90
+ }
91
+
92
+ if (!hasIcon(this.name)) {
93
+ this._svgElement = null;
94
+ this._isValidIcon = false;
95
+ return;
96
+ }
97
+
98
+ this._svgElement = getIconSvg(this.name, {
99
+ size: SIZE_MAP[this.size],
100
+ });
101
+ this._isValidIcon = this._svgElement !== null;
102
+ }
103
+
104
+ override render(): TemplateResult {
105
+ const isDecorative = !this.label;
106
+
107
+ const classes = {
108
+ "ds-icon": true,
109
+ [`ds-icon--${this.size}`]: true,
110
+ "ds-icon--fallback": !this._isValidIcon,
111
+ };
112
+
113
+ const style = this.color ? `color: ${this.color}` : "";
114
+
115
+ // Render fallback if icon not found
116
+ if (!this._isValidIcon) {
117
+ return html`
118
+ <span
119
+ class=${classMap(classes)}
120
+ style=${style || nothing}
121
+ aria-hidden="true"
122
+ ></span>
123
+ `;
124
+ }
125
+
126
+ // Decorative icon (no label)
127
+ if (isDecorative) {
128
+ return html`
129
+ <span
130
+ class=${classMap(classes)}
131
+ style=${style || nothing}
132
+ aria-hidden="true"
133
+ >
134
+ ${this._svgElement}
135
+ </span>
136
+ `;
137
+ }
138
+
139
+ // Meaningful icon (with label)
140
+ return html`
141
+ <span
142
+ class=${classMap(classes)}
143
+ style=${style || nothing}
144
+ role="img"
145
+ aria-label=${this.label}
146
+ >
147
+ ${this._svgElement}
148
+ </span>
149
+ `;
150
+ }
151
+ }
152
+
153
+ // Register the component
154
+ define("ds-icon", DsIcon);
155
+
156
+ // TypeScript declaration for HTML
157
+ declare global {
158
+ interface HTMLElementTagNameMap {
159
+ "ds-icon": DsIcon;
160
+ }
161
+ }
@@ -0,0 +1,130 @@
1
+ import type React from "react";
2
+ import { type InputHTMLAttributes, createElement, forwardRef, useEffect, useRef } from "react";
3
+ import {
4
+ type ResponsiveProp,
5
+ generateResponsiveDataAttr,
6
+ isResponsiveObject,
7
+ resolveResponsiveValue,
8
+ } from "@/lib/primitives/responsive";
9
+
10
+ export type InputType = "text" | "email" | "password" | "number" | "tel" | "url" | "search";
11
+ export type InputSize = "sm" | "md" | "lg";
12
+
13
+ export interface InputProps
14
+ extends Omit<InputHTMLAttributes<HTMLInputElement>, "size" | "onChange" | "onInput"> {
15
+ /** Input type */
16
+ type?: InputType;
17
+ /**
18
+ * Input size - supports responsive object syntax
19
+ * @example
20
+ * ```tsx
21
+ * // Single value
22
+ * <Input size="md" />
23
+ *
24
+ * // Responsive
25
+ * <Input size={{ base: "sm", md: "md", lg: "lg" }} />
26
+ * ```
27
+ */
28
+ size?: ResponsiveProp<InputSize>;
29
+ /** Error state */
30
+ error?: boolean;
31
+ /** Change handler - fires when input loses focus with changed value */
32
+ onChange?: (value: string, event: Event) => void;
33
+ /** Value change handler - fires on every keystroke */
34
+ onValueChange?: (value: string, event: Event) => void;
35
+ }
36
+
37
+ /**
38
+ * React wrapper for ds-input Web Component.
39
+ * Provides type-safe props and event handling.
40
+ */
41
+ export const Input = forwardRef<HTMLElement, InputProps>((props, forwardedRef) => {
42
+ const {
43
+ type = "text",
44
+ size = "md",
45
+ name,
46
+ value,
47
+ placeholder,
48
+ disabled = false,
49
+ readOnly = false,
50
+ required = false,
51
+ error = false,
52
+ minLength,
53
+ maxLength,
54
+ pattern,
55
+ onChange,
56
+ onValueChange,
57
+ className,
58
+ ...rest
59
+ } = props;
60
+
61
+ const internalRef = useRef<HTMLElement>(null);
62
+
63
+ // Merge refs
64
+ useEffect(() => {
65
+ if (typeof forwardedRef === "function") {
66
+ forwardedRef(internalRef.current);
67
+ } else if (forwardedRef) {
68
+ (forwardedRef as React.MutableRefObject<HTMLElement | null>).current = internalRef.current;
69
+ }
70
+ }, [forwardedRef]);
71
+
72
+ // Handle input events
73
+ useEffect(() => {
74
+ const element = internalRef.current;
75
+ if (!element) return;
76
+
77
+ const handleInputEvent = (event: Event) => {
78
+ const customEvent = event as CustomEvent<{ value: string }>;
79
+ onValueChange?.(customEvent.detail.value, event);
80
+ };
81
+
82
+ const handleChangeEvent = (event: Event) => {
83
+ const customEvent = event as CustomEvent<{ value: string }>;
84
+ onChange?.(customEvent.detail.value, event);
85
+ };
86
+
87
+ if (onValueChange) {
88
+ element.addEventListener("input", handleInputEvent);
89
+ }
90
+ if (onChange) {
91
+ element.addEventListener("change", handleChangeEvent);
92
+ }
93
+
94
+ return () => {
95
+ if (onValueChange) {
96
+ element.removeEventListener("input", handleInputEvent);
97
+ }
98
+ if (onChange) {
99
+ element.removeEventListener("change", handleChangeEvent);
100
+ }
101
+ };
102
+ }, [onValueChange, onChange]);
103
+
104
+ // Resolve responsive size - use base value for the WC attribute
105
+ const resolvedSize = resolveResponsiveValue(size, "md");
106
+ const isResponsive = isResponsiveObject(size);
107
+ const responsiveSizeAttr = isResponsive ? generateResponsiveDataAttr(size) : undefined;
108
+
109
+ return createElement("ds-input", {
110
+ ref: internalRef,
111
+ type,
112
+ size: resolvedSize,
113
+ name,
114
+ value,
115
+ placeholder,
116
+ disabled: disabled || undefined,
117
+ readonly: readOnly || undefined,
118
+ required: required || undefined,
119
+ error: error || undefined,
120
+ minlength: minLength,
121
+ maxlength: maxLength,
122
+ pattern,
123
+ class: className,
124
+ // Add responsive data attribute for CSS targeting
125
+ "data-size-responsive": responsiveSizeAttr,
126
+ ...rest,
127
+ });
128
+ });
129
+
130
+ Input.displayName = "Input";
@@ -0,0 +1,216 @@
1
+ import { html } from "lit";
2
+ import { property, state } from "lit/decorators.js";
3
+ import { ifDefined } from "lit/directives/if-defined.js";
4
+ import { DSElement } from "../../base/ds-element.js";
5
+ import { StandardEvents, emitEvent } from "../../events/emit.js";
6
+ import { define } from "../../registry/define.js";
7
+ import { devWarn, hasAccessibleLabel, Warnings } from "../../utils/dev-warnings.js";
8
+
9
+ export type InputType = "text" | "email" | "password" | "number" | "tel" | "url" | "search";
10
+ export type InputSize = "sm" | "md" | "lg";
11
+
12
+ /**
13
+ * A text input field component.
14
+ *
15
+ * @element ds-input
16
+ * @fires input - Fired when the input value changes
17
+ * @fires change - Fired when the input value is committed
18
+ *
19
+ * @example
20
+ * ```html
21
+ * <ds-field>
22
+ * <ds-label>Email</ds-label>
23
+ * <ds-input type="email" name="email"></ds-input>
24
+ * </ds-field>
25
+ * ```
26
+ */
27
+ export class DsInput extends DSElement {
28
+ /** Input type */
29
+ @property({ type: String, reflect: true })
30
+ type: InputType = "text";
31
+
32
+ /** Input size */
33
+ @property({ type: String, reflect: true })
34
+ size: InputSize = "md";
35
+
36
+ /** Input name */
37
+ @property({ type: String, reflect: true })
38
+ name = "";
39
+
40
+ /** Input value */
41
+ @property({ type: String })
42
+ value = "";
43
+
44
+ /** Placeholder text */
45
+ @property({ type: String })
46
+ placeholder = "";
47
+
48
+ /** Disabled state */
49
+ @property({ type: Boolean, reflect: true })
50
+ disabled = false;
51
+
52
+ /** Read-only state */
53
+ @property({ type: Boolean, reflect: true })
54
+ readonly = false;
55
+
56
+ /** Required state */
57
+ @property({ type: Boolean, reflect: true })
58
+ required = false;
59
+
60
+ /** Error state */
61
+ @property({ type: Boolean, reflect: true })
62
+ error = false;
63
+
64
+ /** Minimum length */
65
+ @property({ type: Number })
66
+ minlength?: number;
67
+
68
+ /** Maximum length */
69
+ @property({ type: Number })
70
+ maxlength?: number;
71
+
72
+ /** Pattern for validation */
73
+ @property({ type: String })
74
+ pattern?: string;
75
+
76
+ /** ARIA labelledby - ID of element that labels this input */
77
+ @state()
78
+ private ariaLabelledBy?: string;
79
+
80
+ /** ARIA describedby - IDs of elements that describe this input */
81
+ @state()
82
+ private ariaDescribedBy?: string;
83
+
84
+ private attributeObserver: MutationObserver | null = null;
85
+
86
+ override connectedCallback(): void {
87
+ super.connectedCallback();
88
+
89
+ // Observe ARIA attribute changes on the host element
90
+ this.attributeObserver = new MutationObserver((mutations) => {
91
+ for (const mutation of mutations) {
92
+ if (mutation.type === "attributes") {
93
+ this.syncAriaAttributes();
94
+ }
95
+ }
96
+ });
97
+
98
+ this.attributeObserver.observe(this, {
99
+ attributes: true,
100
+ attributeFilter: [
101
+ "aria-labelledby",
102
+ "aria-describedby",
103
+ "aria-invalid",
104
+ "aria-required",
105
+ "aria-disabled",
106
+ ],
107
+ });
108
+
109
+ // Initial sync
110
+ this.syncAriaAttributes();
111
+
112
+ // Dev warning: Check for accessible label after DOM is ready
113
+ requestAnimationFrame(() => {
114
+ if (!hasAccessibleLabel(this)) {
115
+ // Also check if inside a ds-field with a label
116
+ const field = this.closest("ds-field");
117
+ const hasFieldLabel = field?.querySelector("ds-label") !== null;
118
+ if (!hasFieldLabel) {
119
+ devWarn(Warnings.inputMissingLabel("ds-input"));
120
+ }
121
+ }
122
+ });
123
+ }
124
+
125
+ override disconnectedCallback(): void {
126
+ super.disconnectedCallback();
127
+ this.attributeObserver?.disconnect();
128
+ this.attributeObserver = null;
129
+ }
130
+
131
+ /**
132
+ * Syncs ARIA attributes from the host element to internal state.
133
+ * The render method will apply these to the native input.
134
+ */
135
+ private syncAriaAttributes(): void {
136
+ this.ariaLabelledBy = this.getAttribute("aria-labelledby") ?? undefined;
137
+ this.ariaDescribedBy = this.getAttribute("aria-describedby") ?? undefined;
138
+
139
+ // Sync error state from aria-invalid
140
+ const ariaInvalid = this.getAttribute("aria-invalid");
141
+ if (ariaInvalid === "true") {
142
+ this.error = true;
143
+ } else if (ariaInvalid === "false") {
144
+ this.error = false;
145
+ }
146
+
147
+ // Sync required state from aria-required
148
+ const ariaRequired = this.getAttribute("aria-required");
149
+ if (ariaRequired === "true") {
150
+ this.required = true;
151
+ }
152
+
153
+ // Sync disabled state from aria-disabled
154
+ const ariaDisabled = this.getAttribute("aria-disabled");
155
+ if (ariaDisabled === "true") {
156
+ this.disabled = true;
157
+ }
158
+ }
159
+
160
+ private handleInput(event: Event) {
161
+ const input = event.target as HTMLInputElement;
162
+ this.value = input.value;
163
+ // Also emit native input event for compatibility
164
+ this.dispatchEvent(
165
+ new CustomEvent("input", {
166
+ detail: { value: this.value },
167
+ bubbles: true,
168
+ composed: true,
169
+ })
170
+ );
171
+ }
172
+
173
+ private handleChange(event: Event) {
174
+ const input = event.target as HTMLInputElement;
175
+ this.value = input.value;
176
+ // Emit ds:change event using standard convention
177
+ emitEvent(this, StandardEvents.CHANGE, {
178
+ detail: { value: this.value },
179
+ });
180
+ }
181
+
182
+ override render() {
183
+ return html`
184
+ <div class="ds-input" part="container" data-size=${this.size}>
185
+ <input
186
+ part="input"
187
+ class="ds-input__field"
188
+ type=${this.type}
189
+ name=${this.name}
190
+ .value=${this.value}
191
+ placeholder=${this.placeholder}
192
+ ?disabled=${this.disabled}
193
+ ?readonly=${this.readonly}
194
+ ?required=${this.required}
195
+ aria-invalid=${this.error ? "true" : "false"}
196
+ aria-labelledby=${ifDefined(this.ariaLabelledBy)}
197
+ aria-describedby=${ifDefined(this.ariaDescribedBy)}
198
+ aria-required=${this.required ? "true" : "false"}
199
+ minlength=${this.minlength ?? ""}
200
+ maxlength=${this.maxlength ?? ""}
201
+ pattern=${this.pattern ?? ""}
202
+ @input=${this.handleInput}
203
+ @change=${this.handleChange}
204
+ />
205
+ </div>
206
+ `;
207
+ }
208
+ }
209
+
210
+ define("ds-input", DsInput);
211
+
212
+ declare global {
213
+ interface HTMLElementTagNameMap {
214
+ "ds-input": DsInput;
215
+ }
216
+ }