@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,120 @@
1
+ /**
2
+ * PinInput Root component - provides context to all PinInput compound components.
3
+ */
4
+
5
+ import { createPinInputBehavior } from "@hypoth-ui/primitives-dom";
6
+ import { type ReactNode, useCallback, useMemo, useRef, useState } from "react";
7
+ import { PinInputProvider } from "./pin-input-context.js";
8
+
9
+ export interface PinInputRootProps {
10
+ /** PinInput content */
11
+ children?: ReactNode;
12
+ /** Number of input fields */
13
+ length?: number;
14
+ /** Controlled value */
15
+ value?: string;
16
+ /** Default value (uncontrolled) */
17
+ defaultValue?: string;
18
+ /** Called when value changes */
19
+ onValueChange?: (value: string) => void;
20
+ /** Called when all digits entered */
21
+ onComplete?: (value: string) => void;
22
+ /** Allow alphanumeric characters */
23
+ alphanumeric?: boolean;
24
+ /** Disabled state */
25
+ disabled?: boolean;
26
+ /** Mask input (like password) */
27
+ mask?: boolean;
28
+ }
29
+
30
+ /**
31
+ * Root component for PinInput compound pattern.
32
+ * Provides context to Field components.
33
+ *
34
+ * @example
35
+ * ```tsx
36
+ * <PinInput.Root length={6} onComplete={(value) => verifyOTP(value)}>
37
+ * <PinInput.Field index={0} />
38
+ * <PinInput.Field index={1} />
39
+ * <PinInput.Field index={2} />
40
+ * <PinInput.Field index={3} />
41
+ * <PinInput.Field index={4} />
42
+ * <PinInput.Field index={5} />
43
+ * </PinInput.Root>
44
+ * ```
45
+ */
46
+ export function PinInputRoot({
47
+ children,
48
+ length = 6,
49
+ value: controlledValue,
50
+ defaultValue = "",
51
+ onValueChange,
52
+ onComplete,
53
+ alphanumeric = false,
54
+ disabled = false,
55
+ mask = false,
56
+ }: PinInputRootProps) {
57
+ // Support controlled and uncontrolled modes
58
+ const [internalValue, setInternalValue] = useState(defaultValue);
59
+ const isControlled = controlledValue !== undefined;
60
+ const value = isControlled ? controlledValue : internalValue;
61
+
62
+ const [focusedIndex, setFocusedIndex] = useState<number | null>(null);
63
+ const inputRefs = useRef<(HTMLInputElement | null)[]>([]);
64
+
65
+ const setValue = useCallback(
66
+ (nextValue: string) => {
67
+ if (!isControlled) {
68
+ setInternalValue(nextValue);
69
+ }
70
+ onValueChange?.(nextValue);
71
+ },
72
+ [isControlled, onValueChange]
73
+ );
74
+
75
+ // Create behavior instance
76
+ // biome-ignore lint/correctness/useExhaustiveDependencies: behavior is created once
77
+ const behavior = useMemo(
78
+ () =>
79
+ createPinInputBehavior({
80
+ length,
81
+ defaultValue: value,
82
+ alphanumeric,
83
+ disabled,
84
+ onValueChange: setValue,
85
+ onComplete,
86
+ }),
87
+ []
88
+ );
89
+
90
+ const registerInput = useCallback((index: number, ref: HTMLInputElement | null) => {
91
+ inputRefs.current[index] = ref;
92
+ }, []);
93
+
94
+ const focusInput = useCallback((index: number) => {
95
+ const input = inputRefs.current[index];
96
+ if (input) {
97
+ input.focus();
98
+ input.select();
99
+ }
100
+ }, []);
101
+
102
+ const contextValue = useMemo(
103
+ () => ({
104
+ behavior,
105
+ value,
106
+ length,
107
+ focusedIndex,
108
+ setFocusedIndex,
109
+ registerInput,
110
+ focusInput,
111
+ disabled,
112
+ mask,
113
+ }),
114
+ [behavior, value, length, focusedIndex, registerInput, focusInput, disabled, mask]
115
+ );
116
+
117
+ return <PinInputProvider value={contextValue}>{children}</PinInputProvider>;
118
+ }
119
+
120
+ PinInputRoot.displayName = "PinInput.Root";
@@ -0,0 +1 @@
1
+ export { DsPinInput } from "./pin-input.js";
@@ -0,0 +1,259 @@
1
+ /**
2
+ * PinInput component for PIN/OTP entry with auto-advance.
3
+ *
4
+ * @element ds-pin-input
5
+ * @fires ds:change - Fired on value change with { value }
6
+ * @fires ds:complete - Fired when all digits entered
7
+ *
8
+ * @example
9
+ * ```html
10
+ * <!-- 6-digit PIN -->
11
+ * <ds-pin-input length="6"></ds-pin-input>
12
+ *
13
+ * <!-- 4-digit with initial value -->
14
+ * <ds-pin-input length="4" value="1234"></ds-pin-input>
15
+ *
16
+ * <!-- Alphanumeric code -->
17
+ * <ds-pin-input length="6" alphanumeric></ds-pin-input>
18
+ * ```
19
+ */
20
+
21
+ import { type PinInputBehavior, createPinInputBehavior } from "@hypoth-ui/primitives-dom";
22
+ import { html, nothing } from "lit";
23
+ import { property, state } from "lit/decorators.js";
24
+ import { DSElement } from "../../base/ds-element.js";
25
+ import { StandardEvents, emitEvent } from "../../events/emit.js";
26
+ import { define } from "../../registry/define.js";
27
+
28
+ export class DsPinInput extends DSElement {
29
+ /** Number of input fields */
30
+ @property({ type: Number, reflect: true })
31
+ length = 6;
32
+
33
+ /** Current value */
34
+ @property({ type: String, reflect: true })
35
+ value = "";
36
+
37
+ /** Allow alphanumeric characters */
38
+ @property({ type: Boolean, reflect: true })
39
+ alphanumeric = false;
40
+
41
+ /** Disabled state */
42
+ @property({ type: Boolean, reflect: true })
43
+ disabled = false;
44
+
45
+ /** Mask input (like password) */
46
+ @property({ type: Boolean, reflect: true })
47
+ mask = false;
48
+
49
+ /** ARIA label */
50
+ @property({ type: String, attribute: "aria-label" })
51
+ override ariaLabel: string | null = null;
52
+
53
+ @state()
54
+ private behavior: PinInputBehavior | null = null;
55
+
56
+ @state()
57
+ private focusedIndex: number | null = null;
58
+
59
+ private inputRefs: (HTMLInputElement | null)[] = [];
60
+
61
+ override connectedCallback(): void {
62
+ super.connectedCallback();
63
+ this.initBehavior();
64
+ }
65
+
66
+ override disconnectedCallback(): void {
67
+ super.disconnectedCallback();
68
+ this.behavior?.destroy();
69
+ this.behavior = null;
70
+ }
71
+
72
+ override updated(changedProperties: Map<string, unknown>): void {
73
+ super.updated(changedProperties);
74
+
75
+ if (
76
+ changedProperties.has("length") ||
77
+ changedProperties.has("alphanumeric") ||
78
+ changedProperties.has("disabled")
79
+ ) {
80
+ this.initBehavior();
81
+ }
82
+ }
83
+
84
+ private initBehavior(): void {
85
+ this.behavior?.destroy();
86
+
87
+ this.behavior = createPinInputBehavior({
88
+ length: this.length,
89
+ defaultValue: this.value,
90
+ alphanumeric: this.alphanumeric,
91
+ disabled: this.disabled,
92
+ onValueChange: (value) => {
93
+ this.value = value;
94
+ emitEvent(this, StandardEvents.CHANGE, { detail: { value } });
95
+ },
96
+ onComplete: (value) => {
97
+ emitEvent(this, "ds:complete", { detail: { value } });
98
+ },
99
+ });
100
+
101
+ this.inputRefs = new Array(this.length).fill(null);
102
+ }
103
+
104
+ /** Public method to clear the input */
105
+ clear(): void {
106
+ this.behavior?.clear();
107
+ this.focusInput(0);
108
+ }
109
+
110
+ /** Public method to set value programmatically */
111
+ setValue(value: string): void {
112
+ this.behavior?.setValue(value);
113
+ }
114
+
115
+ private focusInput(index: number): void {
116
+ const input = this.inputRefs[index];
117
+ if (input) {
118
+ input.focus();
119
+ input.select();
120
+ }
121
+ }
122
+
123
+ private handleInput(index: number, event: InputEvent): void {
124
+ if (!this.behavior) return;
125
+
126
+ const input = event.target as HTMLInputElement;
127
+ const char = input.value.slice(-1); // Get last character
128
+
129
+ if (char) {
130
+ this.behavior.input(index, char);
131
+
132
+ // Auto-advance to next input
133
+ const nextIndex = this.behavior.state.focusedIndex;
134
+ if (nextIndex !== null && nextIndex !== index) {
135
+ this.focusInput(nextIndex);
136
+ }
137
+ }
138
+
139
+ // Clear input to prevent accumulation
140
+ input.value = this.behavior.getValueAt(index);
141
+ }
142
+
143
+ private handleKeyDown(index: number, event: KeyboardEvent): void {
144
+ if (!this.behavior) return;
145
+
146
+ switch (event.key) {
147
+ case "Backspace": {
148
+ event.preventDefault();
149
+ this.behavior.backspace(index);
150
+ const prevIndex = this.behavior.state.focusedIndex;
151
+ if (prevIndex !== null && prevIndex !== index) {
152
+ this.focusInput(prevIndex);
153
+ }
154
+ break;
155
+ }
156
+ case "ArrowLeft":
157
+ event.preventDefault();
158
+ this.behavior.focusPrev();
159
+ if (this.behavior.state.focusedIndex !== null) {
160
+ this.focusInput(this.behavior.state.focusedIndex);
161
+ }
162
+ break;
163
+ case "ArrowRight":
164
+ event.preventDefault();
165
+ this.behavior.focusNext();
166
+ if (this.behavior.state.focusedIndex !== null) {
167
+ this.focusInput(this.behavior.state.focusedIndex);
168
+ }
169
+ break;
170
+ case "Delete": {
171
+ event.preventDefault();
172
+ // Clear current position without moving
173
+ const chars = this.behavior.state.value.split("");
174
+ chars[index] = " ";
175
+ this.behavior.setValue(chars.join(""));
176
+ break;
177
+ }
178
+ }
179
+ }
180
+
181
+ private handlePaste(event: ClipboardEvent): void {
182
+ event.preventDefault();
183
+ const pastedText = event.clipboardData?.getData("text") ?? "";
184
+ if (pastedText && this.behavior) {
185
+ this.behavior.paste(pastedText);
186
+ // Focus last filled position
187
+ const focusedIdx = this.behavior.state.focusedIndex;
188
+ if (focusedIdx !== null) {
189
+ this.focusInput(focusedIdx);
190
+ }
191
+ }
192
+ }
193
+
194
+ private handleFocus(index: number): void {
195
+ this.focusedIndex = index;
196
+ this.behavior?.focus(index);
197
+ }
198
+
199
+ private handleBlur(): void {
200
+ this.focusedIndex = null;
201
+ }
202
+
203
+ override render() {
204
+ if (!this.behavior) return nothing;
205
+
206
+ const containerProps = this.behavior.getContainerProps();
207
+ const inputs = [];
208
+
209
+ for (let i = 0; i < this.length; i++) {
210
+ const inputProps = this.behavior.getInputProps(i);
211
+ const value = this.behavior.getValueAt(i);
212
+ const isFocused = this.focusedIndex === i;
213
+
214
+ inputs.push(html`
215
+ <input
216
+ class="ds-pin-input__field"
217
+ type=${this.mask ? "password" : inputProps.type}
218
+ inputmode=${inputProps.inputMode}
219
+ maxlength=${inputProps.maxLength}
220
+ autocomplete=${inputProps.autoComplete}
221
+ aria-label=${inputProps["aria-label"]}
222
+ tabindex=${inputProps.tabIndex}
223
+ .value=${value}
224
+ ?disabled=${this.disabled}
225
+ data-index=${i}
226
+ data-focused=${isFocused || nothing}
227
+ data-filled=${value ? true : nothing}
228
+ @input=${(e: InputEvent) => this.handleInput(i, e)}
229
+ @keydown=${(e: KeyboardEvent) => this.handleKeyDown(i, e)}
230
+ @paste=${this.handlePaste}
231
+ @focus=${() => this.handleFocus(i)}
232
+ @blur=${this.handleBlur}
233
+ .ref=${(el: HTMLInputElement | null) => {
234
+ this.inputRefs[i] = el;
235
+ }}
236
+ />
237
+ `);
238
+ }
239
+
240
+ return html`
241
+ <div
242
+ class="ds-pin-input"
243
+ role=${containerProps.role}
244
+ aria-label=${this.ariaLabel || containerProps["aria-label"]}
245
+ data-disabled=${this.disabled || nothing}
246
+ >
247
+ ${inputs}
248
+ </div>
249
+ `;
250
+ }
251
+ }
252
+
253
+ define("ds-pin-input", DsPinInput);
254
+
255
+ declare global {
256
+ interface HTMLElementTagNameMap {
257
+ "ds-pin-input": DsPinInput;
258
+ }
259
+ }
@@ -0,0 +1,121 @@
1
+ import type React from "react";
2
+ import {
3
+ type HTMLAttributes,
4
+ createElement,
5
+ forwardRef,
6
+ useCallback,
7
+ useEffect,
8
+ useRef,
9
+ } from "react";
10
+
11
+ export type Placement =
12
+ | "top"
13
+ | "top-start"
14
+ | "top-end"
15
+ | "bottom"
16
+ | "bottom-start"
17
+ | "bottom-end"
18
+ | "left"
19
+ | "left-start"
20
+ | "left-end"
21
+ | "right"
22
+ | "right-start"
23
+ | "right-end";
24
+
25
+ export interface PopoverProps extends HTMLAttributes<HTMLElement> {
26
+ /** Whether the popover is open */
27
+ open?: boolean;
28
+ /** Placement relative to trigger */
29
+ placement?: Placement;
30
+ /** Offset from trigger in pixels */
31
+ offset?: number;
32
+ /** Whether to flip placement when near viewport edge */
33
+ flip?: boolean;
34
+ /** Whether Escape closes the popover */
35
+ closeOnEscape?: boolean;
36
+ /** Whether clicking outside closes the popover */
37
+ closeOnOutsideClick?: boolean;
38
+ /** Handler for open event */
39
+ onOpen?: () => void;
40
+ /** Handler for close event */
41
+ onClose?: () => void;
42
+ /** Popover content */
43
+ children?: React.ReactNode;
44
+ }
45
+
46
+ /**
47
+ * React wrapper for ds-popover Web Component.
48
+ * Non-modal popover with anchor positioning.
49
+ */
50
+ export const Popover = forwardRef<HTMLElement, PopoverProps>((props, forwardedRef) => {
51
+ const {
52
+ open = false,
53
+ placement = "bottom",
54
+ offset = 8,
55
+ flip = true,
56
+ closeOnEscape = true,
57
+ closeOnOutsideClick = true,
58
+ onOpen,
59
+ onClose,
60
+ children,
61
+ className,
62
+ ...rest
63
+ } = props;
64
+
65
+ const internalRef = useRef<HTMLElement>(null);
66
+
67
+ // Store handlers in refs for stable callback references
68
+ const onOpenRef = useRef(onOpen);
69
+ const onCloseRef = useRef(onClose);
70
+ onOpenRef.current = onOpen;
71
+ onCloseRef.current = onClose;
72
+
73
+ useEffect(() => {
74
+ if (typeof forwardedRef === "function") {
75
+ forwardedRef(internalRef.current);
76
+ } else if (forwardedRef) {
77
+ (forwardedRef as React.MutableRefObject<HTMLElement | null>).current = internalRef.current;
78
+ }
79
+ }, [forwardedRef]);
80
+
81
+ // Stable handlers that read from refs
82
+ const handleOpen = useCallback(() => {
83
+ onOpenRef.current?.();
84
+ }, []);
85
+
86
+ const handleClose = useCallback(() => {
87
+ onCloseRef.current?.();
88
+ }, []);
89
+
90
+ // Handle events - no handler deps needed
91
+ useEffect(() => {
92
+ const element = internalRef.current;
93
+ if (!element) return;
94
+
95
+ element.addEventListener("ds:open", handleOpen);
96
+ element.addEventListener("ds:close", handleClose);
97
+
98
+ return () => {
99
+ element.removeEventListener("ds:open", handleOpen);
100
+ element.removeEventListener("ds:close", handleClose);
101
+ };
102
+ }, [handleOpen, handleClose]);
103
+
104
+ return createElement(
105
+ "ds-popover",
106
+ {
107
+ ref: internalRef,
108
+ open: open || undefined,
109
+ placement,
110
+ offset,
111
+ flip: flip || undefined,
112
+ "close-on-escape": closeOnEscape ? undefined : "false",
113
+ "close-on-outside-click": closeOnOutsideClick ? undefined : "false",
114
+ class: className,
115
+ ...rest,
116
+ },
117
+ children
118
+ );
119
+ });
120
+
121
+ Popover.displayName = "Popover";
@@ -0,0 +1,66 @@
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
+ export type PopoverContentState = "open" | "closed";
7
+
8
+ /**
9
+ * Popover content container.
10
+ *
11
+ * @element ds-popover-content
12
+ *
13
+ * @slot - Content to display in the popover
14
+ *
15
+ * @attr {string} data-state - Animation state ("open" or "closed")
16
+ *
17
+ * @example
18
+ * ```html
19
+ * <ds-popover>
20
+ * <button slot="trigger">Open</button>
21
+ * <ds-popover-content>
22
+ * <p>Popover content here</p>
23
+ * <button>Action</button>
24
+ * </ds-popover-content>
25
+ * </ds-popover>
26
+ * ```
27
+ */
28
+ export class DsPopoverContent extends DSElement {
29
+ /** Unique ID for ARIA association */
30
+ @property({ type: String, reflect: true })
31
+ override id = "";
32
+
33
+ /** Animation state (open or closed) - set by parent ds-popover */
34
+ @property({ type: String, reflect: true, attribute: "data-state" })
35
+ dataState: PopoverContentState = "closed";
36
+
37
+ override connectedCallback(): void {
38
+ super.connectedCallback();
39
+
40
+ // Generate ID if not set
41
+ if (!this.id) {
42
+ this.id = `popover-content-${crypto.randomUUID().slice(0, 8)}`;
43
+ }
44
+
45
+ // Hidden by default (parent popover controls visibility)
46
+ this.setAttribute("hidden", "");
47
+ }
48
+
49
+ override render() {
50
+ // Note: No role attribute by default since popover is non-modal
51
+ // Developers can add aria-label or role="dialog" if needed
52
+ return html`
53
+ <div class="ds-popover-content" part="container">
54
+ <slot></slot>
55
+ </div>
56
+ `;
57
+ }
58
+ }
59
+
60
+ define("ds-popover-content", DsPopoverContent);
61
+
62
+ declare global {
63
+ interface HTMLElementTagNameMap {
64
+ "ds-popover-content": DsPopoverContent;
65
+ }
66
+ }