@hypoth-ui/cli 0.0.1 → 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (375) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +19 -115
  3. package/dist/{add-PDBC4JTE.js → add-V5PW73GC.js} +29 -17
  4. package/dist/{chunk-5LTQ2XVL.js → chunk-27CLUUVC.js} +0 -2
  5. package/dist/{chunk-YPKFYE45.js → chunk-NWIRSZUQ.js} +6 -13
  6. package/dist/{chunk-GJ6JOQ3Q.js → chunk-PBK72SJJ.js} +1 -1
  7. package/dist/{diff-BQEXG7HU.js → diff-776UATCA.js} +2 -2
  8. package/dist/index.js +5 -5
  9. package/dist/{init-7AZXYAPJ.js → init-GDU2PW7K.js} +10 -13
  10. package/dist/{list-X6ZLM2NQ.js → list-XDP5I537.js} +3 -3
  11. package/package.json +16 -12
  12. package/registry/components.json +1820 -206
  13. package/templates/accordion/index.tsx +266 -0
  14. package/templates/accordion/wc/accordion-content.ts +113 -0
  15. package/templates/accordion/wc/accordion-item.ts +111 -0
  16. package/templates/accordion/wc/accordion-trigger.ts +105 -0
  17. package/templates/accordion/wc/accordion.ts +213 -0
  18. package/templates/accordion/wc/index.ts +12 -0
  19. package/templates/alert/index.tsx +177 -0
  20. package/templates/alert/wc/alert.ts +167 -0
  21. package/templates/alert/wc/index.ts +1 -0
  22. package/templates/alert-dialog/index.tsx +360 -0
  23. package/templates/alert-dialog/wc/alert-dialog-action.ts +43 -0
  24. package/templates/alert-dialog/wc/alert-dialog-cancel.ts +43 -0
  25. package/templates/alert-dialog/wc/alert-dialog-content.ts +42 -0
  26. package/templates/alert-dialog/wc/alert-dialog-description.ts +34 -0
  27. package/templates/alert-dialog/wc/alert-dialog-footer.ts +25 -0
  28. package/templates/alert-dialog/wc/alert-dialog-header.ts +25 -0
  29. package/templates/alert-dialog/wc/alert-dialog-title.ts +34 -0
  30. package/templates/alert-dialog/wc/alert-dialog-trigger.ts +46 -0
  31. package/templates/alert-dialog/wc/alert-dialog.ts +302 -0
  32. package/templates/alert-dialog/wc/index.ts +13 -0
  33. package/templates/aspect-ratio/index.tsx +50 -0
  34. package/templates/aspect-ratio/wc/aspect-ratio.ts +78 -0
  35. package/templates/aspect-ratio/wc/index.ts +5 -0
  36. package/templates/avatar/avatar-group.tsx +88 -0
  37. package/templates/avatar/avatar.tsx +124 -0
  38. package/templates/avatar/index.tsx +33 -0
  39. package/templates/avatar/wc/avatar-group.ts +112 -0
  40. package/templates/avatar/wc/avatar.ts +184 -0
  41. package/templates/avatar/wc/index.ts +5 -0
  42. package/templates/badge/index.tsx +140 -0
  43. package/templates/badge/wc/badge.ts +119 -0
  44. package/templates/badge/wc/index.ts +9 -0
  45. package/templates/breadcrumb/index.tsx +157 -0
  46. package/templates/breadcrumb/wc/breadcrumb-item.ts +30 -0
  47. package/templates/breadcrumb/wc/breadcrumb-link.ts +70 -0
  48. package/templates/breadcrumb/wc/breadcrumb-list.ts +30 -0
  49. package/templates/breadcrumb/wc/breadcrumb-page.ts +32 -0
  50. package/templates/breadcrumb/wc/breadcrumb-separator.ts +31 -0
  51. package/templates/breadcrumb/wc/breadcrumb.ts +55 -0
  52. package/templates/breadcrumb/wc/index.ts +10 -0
  53. package/templates/button/button.tsx +119 -0
  54. package/templates/button/index.ts +1 -0
  55. package/templates/button/wc/button.ts +169 -0
  56. package/templates/calendar/index.tsx +149 -0
  57. package/templates/calendar/wc/calendar.ts +316 -0
  58. package/templates/calendar/wc/index.ts +4 -0
  59. package/templates/card/index.tsx +108 -0
  60. package/templates/card/wc/card-content.ts +25 -0
  61. package/templates/card/wc/card-footer.ts +25 -0
  62. package/templates/card/wc/card-header.ts +25 -0
  63. package/templates/card/wc/card.ts +43 -0
  64. package/templates/card/wc/index.ts +8 -0
  65. package/templates/checkbox/checkbox.tsx +85 -0
  66. package/templates/checkbox/wc/checkbox.ts +247 -0
  67. package/templates/collapsible/index.tsx +172 -0
  68. package/templates/collapsible/wc/collapsible-content.ts +97 -0
  69. package/templates/collapsible/wc/collapsible-trigger.ts +39 -0
  70. package/templates/collapsible/wc/collapsible.ts +143 -0
  71. package/templates/collapsible/wc/index.ts +7 -0
  72. package/templates/combobox/combobox-content.tsx +141 -0
  73. package/templates/combobox/combobox-context.ts +36 -0
  74. package/templates/combobox/combobox-empty.tsx +38 -0
  75. package/templates/combobox/combobox-input.tsx +159 -0
  76. package/templates/combobox/combobox-loading.tsx +38 -0
  77. package/templates/combobox/combobox-option.tsx +99 -0
  78. package/templates/combobox/combobox-root.tsx +207 -0
  79. package/templates/combobox/combobox-tag.tsx +62 -0
  80. package/templates/combobox/index.ts +62 -0
  81. package/templates/combobox/wc/combobox-content.ts +97 -0
  82. package/templates/combobox/wc/combobox-input.ts +134 -0
  83. package/templates/combobox/wc/combobox-option.ts +111 -0
  84. package/templates/combobox/wc/combobox-tag.ts +103 -0
  85. package/templates/combobox/wc/combobox.ts +981 -0
  86. package/templates/combobox/wc/index.ts +5 -0
  87. package/templates/command/index.tsx +279 -0
  88. package/templates/command/wc/command-empty.ts +24 -0
  89. package/templates/command/wc/command-group.ts +60 -0
  90. package/templates/command/wc/command-input.ts +136 -0
  91. package/templates/command/wc/command-item.ts +78 -0
  92. package/templates/command/wc/command-list.ts +103 -0
  93. package/templates/command/wc/command-loading.ts +24 -0
  94. package/templates/command/wc/command-separator.ts +23 -0
  95. package/templates/command/wc/command.ts +176 -0
  96. package/templates/context-menu/index.tsx +262 -0
  97. package/templates/context-menu/wc/context-menu-content.ts +41 -0
  98. package/templates/context-menu/wc/context-menu-item.ts +83 -0
  99. package/templates/context-menu/wc/context-menu-label.ts +30 -0
  100. package/templates/context-menu/wc/context-menu-separator.ts +28 -0
  101. package/templates/context-menu/wc/context-menu.ts +324 -0
  102. package/templates/context-menu/wc/index.ts +9 -0
  103. package/templates/data-table/index.tsx +263 -0
  104. package/templates/data-table/wc/data-table.ts +405 -0
  105. package/templates/data-table/wc/index.ts +10 -0
  106. package/templates/date-picker/date-picker-calendar.tsx +352 -0
  107. package/templates/date-picker/date-picker-content.tsx +121 -0
  108. package/templates/date-picker/date-picker-context.ts +46 -0
  109. package/templates/date-picker/date-picker-root.tsx +201 -0
  110. package/templates/date-picker/date-picker-trigger.tsx +95 -0
  111. package/templates/date-picker/index.ts +44 -0
  112. package/templates/date-picker/wc/date-picker-calendar.ts +457 -0
  113. package/templates/date-picker/wc/date-picker.ts +592 -0
  114. package/templates/date-picker/wc/date-utils.ts +467 -0
  115. package/templates/date-picker/wc/index.ts +3 -0
  116. package/templates/dialog/dialog-close.tsx +57 -0
  117. package/templates/dialog/dialog-content.tsx +106 -0
  118. package/templates/dialog/dialog-context.ts +24 -0
  119. package/templates/dialog/dialog-description.tsx +51 -0
  120. package/templates/dialog/dialog-root.tsx +104 -0
  121. package/templates/dialog/dialog-title.tsx +38 -0
  122. package/templates/dialog/dialog-trigger.tsx +94 -0
  123. package/templates/dialog/index.ts +52 -0
  124. package/templates/dialog/wc/dialog-content.ts +59 -0
  125. package/templates/dialog/wc/dialog-description.ts +58 -0
  126. package/templates/dialog/wc/dialog-title.ts +56 -0
  127. package/templates/dialog/wc/dialog.ts +411 -0
  128. package/templates/drawer/index.tsx +263 -0
  129. package/templates/drawer/wc/drawer-content.ts +150 -0
  130. package/templates/drawer/wc/drawer-description.ts +34 -0
  131. package/templates/drawer/wc/drawer-footer.ts +25 -0
  132. package/templates/drawer/wc/drawer-header.ts +25 -0
  133. package/templates/drawer/wc/drawer-title.ts +34 -0
  134. package/templates/drawer/wc/drawer.ts +348 -0
  135. package/templates/drawer/wc/index.ts +10 -0
  136. package/templates/dropdown-menu/index.tsx +454 -0
  137. package/templates/dropdown-menu/wc/dropdown-menu-checkbox-item.ts +93 -0
  138. package/templates/dropdown-menu/wc/dropdown-menu-content.ts +43 -0
  139. package/templates/dropdown-menu/wc/dropdown-menu-item.ts +85 -0
  140. package/templates/dropdown-menu/wc/dropdown-menu-label.ts +31 -0
  141. package/templates/dropdown-menu/wc/dropdown-menu-radio-group.ts +80 -0
  142. package/templates/dropdown-menu/wc/dropdown-menu-radio-item.ts +101 -0
  143. package/templates/dropdown-menu/wc/dropdown-menu-separator.ts +28 -0
  144. package/templates/dropdown-menu/wc/dropdown-menu.ts +358 -0
  145. package/templates/dropdown-menu/wc/index.ts +12 -0
  146. package/templates/field/field-description.tsx +39 -0
  147. package/templates/field/field-error.tsx +37 -0
  148. package/templates/field/field.tsx +46 -0
  149. package/templates/field/index.ts +4 -0
  150. package/templates/field/label.tsx +40 -0
  151. package/templates/field/wc/field-description.ts +42 -0
  152. package/templates/field/wc/field-error.ts +46 -0
  153. package/templates/field/wc/field.ts +210 -0
  154. package/templates/field/wc/label.ts +54 -0
  155. package/templates/file-upload/file-upload-context.ts +26 -0
  156. package/templates/file-upload/file-upload-dropzone.tsx +111 -0
  157. package/templates/file-upload/file-upload-input.tsx +86 -0
  158. package/templates/file-upload/file-upload-item.tsx +105 -0
  159. package/templates/file-upload/file-upload-root.tsx +115 -0
  160. package/templates/file-upload/index.ts +50 -0
  161. package/templates/file-upload/wc/file-upload.ts +380 -0
  162. package/templates/file-upload/wc/index.ts +1 -0
  163. package/templates/hover-card/index.tsx +203 -0
  164. package/templates/hover-card/wc/hover-card-content.ts +50 -0
  165. package/templates/hover-card/wc/hover-card.ts +382 -0
  166. package/templates/hover-card/wc/index.ts +6 -0
  167. package/templates/icon/icon.tsx +76 -0
  168. package/templates/icon/wc/icon-adapter.ts +108 -0
  169. package/templates/icon/wc/icon.ts +161 -0
  170. package/templates/input/input.tsx +130 -0
  171. package/templates/input/wc/input.ts +216 -0
  172. package/templates/layout/app-shell.tsx +177 -0
  173. package/templates/layout/box.tsx +53 -0
  174. package/templates/layout/center.tsx +42 -0
  175. package/templates/layout/container.tsx +43 -0
  176. package/templates/layout/flow.tsx +83 -0
  177. package/templates/layout/grid.tsx +79 -0
  178. package/templates/layout/index.ts +33 -0
  179. package/templates/layout/inline.tsx +16 -0
  180. package/templates/layout/page.tsx +43 -0
  181. package/templates/layout/section.tsx +39 -0
  182. package/templates/layout/spacer.tsx +30 -0
  183. package/templates/layout/split.tsx +47 -0
  184. package/templates/layout/stack.tsx +16 -0
  185. package/templates/layout/wc/app-shell.ts +58 -0
  186. package/templates/layout/wc/box.ts +117 -0
  187. package/templates/layout/wc/center.ts +78 -0
  188. package/templates/layout/wc/container.ts +77 -0
  189. package/templates/layout/wc/flow.ts +149 -0
  190. package/templates/layout/wc/footer.ts +57 -0
  191. package/templates/layout/wc/grid.ts +142 -0
  192. package/templates/layout/wc/header.ts +57 -0
  193. package/templates/layout/wc/index.ts +41 -0
  194. package/templates/layout/wc/main.ts +46 -0
  195. package/templates/layout/wc/page.ts +81 -0
  196. package/templates/layout/wc/section.ts +65 -0
  197. package/templates/layout/wc/spacer.ts +77 -0
  198. package/templates/layout/wc/split.ts +94 -0
  199. package/templates/layout/wc/wrap.ts +93 -0
  200. package/templates/layout/wrap.tsx +46 -0
  201. package/templates/link/link.tsx +109 -0
  202. package/templates/link/wc/link.ts +124 -0
  203. package/templates/list/index.tsx +55 -0
  204. package/templates/list/list-item.tsx +117 -0
  205. package/templates/list/list.tsx +115 -0
  206. package/templates/list/wc/index.ts +5 -0
  207. package/templates/list/wc/list-item.ts +127 -0
  208. package/templates/list/wc/list.ts +114 -0
  209. package/templates/menu/index.ts +49 -0
  210. package/templates/menu/menu-content.tsx +109 -0
  211. package/templates/menu/menu-context.ts +17 -0
  212. package/templates/menu/menu-item.tsx +108 -0
  213. package/templates/menu/menu-label.tsx +32 -0
  214. package/templates/menu/menu-root.tsx +108 -0
  215. package/templates/menu/menu-separator.tsx +24 -0
  216. package/templates/menu/menu-trigger.tsx +104 -0
  217. package/templates/menu/wc/menu-content.ts +67 -0
  218. package/templates/menu/wc/menu-item.ts +109 -0
  219. package/templates/menu/wc/menu.ts +449 -0
  220. package/templates/navigation-menu/index.tsx +328 -0
  221. package/templates/navigation-menu/wc/index.ts +12 -0
  222. package/templates/navigation-menu/wc/navigation-menu-content.ts +30 -0
  223. package/templates/navigation-menu/wc/navigation-menu-indicator.ts +30 -0
  224. package/templates/navigation-menu/wc/navigation-menu-item.ts +60 -0
  225. package/templates/navigation-menu/wc/navigation-menu-link.ts +97 -0
  226. package/templates/navigation-menu/wc/navigation-menu-list.ts +30 -0
  227. package/templates/navigation-menu/wc/navigation-menu-trigger.ts +110 -0
  228. package/templates/navigation-menu/wc/navigation-menu-viewport.ts +85 -0
  229. package/templates/navigation-menu/wc/navigation-menu.ts +272 -0
  230. package/templates/number-input/index.ts +46 -0
  231. package/templates/number-input/number-input-context.ts +38 -0
  232. package/templates/number-input/number-input-decrement.tsx +53 -0
  233. package/templates/number-input/number-input-field.tsx +93 -0
  234. package/templates/number-input/number-input-increment.tsx +53 -0
  235. package/templates/number-input/number-input-root.tsx +137 -0
  236. package/templates/number-input/wc/index.ts +1 -0
  237. package/templates/number-input/wc/number-input.ts +283 -0
  238. package/templates/pagination/index.tsx +198 -0
  239. package/templates/pagination/wc/index.ts +11 -0
  240. package/templates/pagination/wc/pagination-content.ts +30 -0
  241. package/templates/pagination/wc/pagination-ellipsis.ts +28 -0
  242. package/templates/pagination/wc/pagination-item.ts +30 -0
  243. package/templates/pagination/wc/pagination-link.ts +76 -0
  244. package/templates/pagination/wc/pagination-next.ts +69 -0
  245. package/templates/pagination/wc/pagination-previous.ts +69 -0
  246. package/templates/pagination/wc/pagination.ts +156 -0
  247. package/templates/pin-input/index.ts +39 -0
  248. package/templates/pin-input/pin-input-context.ts +30 -0
  249. package/templates/pin-input/pin-input-field.tsx +186 -0
  250. package/templates/pin-input/pin-input-root.tsx +120 -0
  251. package/templates/pin-input/wc/index.ts +1 -0
  252. package/templates/pin-input/wc/pin-input.ts +259 -0
  253. package/templates/popover/popover.tsx +121 -0
  254. package/templates/popover/wc/popover-content.ts +66 -0
  255. package/templates/popover/wc/popover.ts +343 -0
  256. package/templates/progress/index.tsx +117 -0
  257. package/templates/progress/wc/index.ts +4 -0
  258. package/templates/progress/wc/progress.ts +174 -0
  259. package/templates/radio/radio.tsx +43 -0
  260. package/templates/radio/wc/radio-group.ts +261 -0
  261. package/templates/radio/wc/radio.ts +145 -0
  262. package/templates/scroll-area/index.tsx +144 -0
  263. package/templates/scroll-area/wc/index.ts +8 -0
  264. package/templates/scroll-area/wc/scroll-area-scrollbar.ts +143 -0
  265. package/templates/scroll-area/wc/scroll-area-thumb.ts +225 -0
  266. package/templates/scroll-area/wc/scroll-area-viewport.ts +120 -0
  267. package/templates/scroll-area/wc/scroll-area.ts +63 -0
  268. package/templates/select/index.ts +57 -0
  269. package/templates/select/select-content.tsx +243 -0
  270. package/templates/select/select-context.ts +30 -0
  271. package/templates/select/select-group.tsx +53 -0
  272. package/templates/select/select-label.tsx +34 -0
  273. package/templates/select/select-option.tsx +97 -0
  274. package/templates/select/select-root.tsx +153 -0
  275. package/templates/select/select-separator.tsx +27 -0
  276. package/templates/select/select-trigger.tsx +112 -0
  277. package/templates/select/select-value.tsx +48 -0
  278. package/templates/select/wc/index.ts +6 -0
  279. package/templates/select/wc/select-content.ts +89 -0
  280. package/templates/select/wc/select-group.ts +82 -0
  281. package/templates/select/wc/select-label.ts +49 -0
  282. package/templates/select/wc/select-option.ts +111 -0
  283. package/templates/select/wc/select-trigger.ts +101 -0
  284. package/templates/select/wc/select.ts +840 -0
  285. package/templates/separator/index.tsx +49 -0
  286. package/templates/separator/wc/index.ts +5 -0
  287. package/templates/separator/wc/separator.ts +60 -0
  288. package/templates/sheet/index.tsx +291 -0
  289. package/templates/sheet/wc/index.ts +12 -0
  290. package/templates/sheet/wc/sheet-close.ts +43 -0
  291. package/templates/sheet/wc/sheet-content.ts +47 -0
  292. package/templates/sheet/wc/sheet-description.ts +34 -0
  293. package/templates/sheet/wc/sheet-footer.ts +25 -0
  294. package/templates/sheet/wc/sheet-header.ts +25 -0
  295. package/templates/sheet/wc/sheet-overlay.ts +23 -0
  296. package/templates/sheet/wc/sheet-title.ts +34 -0
  297. package/templates/sheet/wc/sheet.ts +336 -0
  298. package/templates/skeleton/index.tsx +131 -0
  299. package/templates/skeleton/wc/index.ts +10 -0
  300. package/templates/skeleton/wc/skeleton.ts +107 -0
  301. package/templates/slider/index.ts +41 -0
  302. package/templates/slider/slider-context.ts +36 -0
  303. package/templates/slider/slider-range.tsx +59 -0
  304. package/templates/slider/slider-root.tsx +166 -0
  305. package/templates/slider/slider-thumb.tsx +213 -0
  306. package/templates/slider/slider-track.tsx +113 -0
  307. package/templates/slider/wc/index.ts +1 -0
  308. package/templates/slider/wc/slider.ts +465 -0
  309. package/templates/spinner/spinner.tsx +64 -0
  310. package/templates/spinner/wc/spinner.ts +70 -0
  311. package/templates/stepper/index.tsx +230 -0
  312. package/templates/stepper/wc/index.ts +12 -0
  313. package/templates/stepper/wc/stepper-content.ts +30 -0
  314. package/templates/stepper/wc/stepper-description.ts +25 -0
  315. package/templates/stepper/wc/stepper-indicator.ts +30 -0
  316. package/templates/stepper/wc/stepper-item.ts +55 -0
  317. package/templates/stepper/wc/stepper-separator.ts +29 -0
  318. package/templates/stepper/wc/stepper-title.ts +25 -0
  319. package/templates/stepper/wc/stepper-trigger.ts +67 -0
  320. package/templates/stepper/wc/stepper.ts +164 -0
  321. package/templates/switch/switch.tsx +90 -0
  322. package/templates/switch/wc/switch.ts +228 -0
  323. package/templates/table/body.tsx +21 -0
  324. package/templates/table/cell.tsx +44 -0
  325. package/templates/table/head.tsx +112 -0
  326. package/templates/table/header.tsx +21 -0
  327. package/templates/table/index.tsx +93 -0
  328. package/templates/table/root.tsx +82 -0
  329. package/templates/table/row.tsx +36 -0
  330. package/templates/table/wc/index.ts +9 -0
  331. package/templates/table/wc/table-body.ts +32 -0
  332. package/templates/table/wc/table-cell.ts +58 -0
  333. package/templates/table/wc/table-head.ts +129 -0
  334. package/templates/table/wc/table-header.ts +32 -0
  335. package/templates/table/wc/table-row.ts +50 -0
  336. package/templates/table/wc/table.ts +93 -0
  337. package/templates/tabs/index.tsx +222 -0
  338. package/templates/tabs/wc/index.ts +8 -0
  339. package/templates/tabs/wc/tabs-content.ts +82 -0
  340. package/templates/tabs/wc/tabs-list.ts +56 -0
  341. package/templates/tabs/wc/tabs-trigger.ts +136 -0
  342. package/templates/tabs/wc/tabs.ts +202 -0
  343. package/templates/tag/index.tsx +186 -0
  344. package/templates/tag/wc/index.ts +4 -0
  345. package/templates/tag/wc/tag.ts +166 -0
  346. package/templates/text/text.tsx +100 -0
  347. package/templates/text/wc/text.ts +94 -0
  348. package/templates/textarea/textarea.tsx +134 -0
  349. package/templates/textarea/wc/textarea.ts +280 -0
  350. package/templates/time-picker/index.ts +42 -0
  351. package/templates/time-picker/time-picker-context.ts +28 -0
  352. package/templates/time-picker/time-picker-root.tsx +113 -0
  353. package/templates/time-picker/time-picker-segment.tsx +91 -0
  354. package/templates/time-picker/wc/index.ts +1 -0
  355. package/templates/time-picker/wc/time-picker.ts +221 -0
  356. package/templates/toast/index.tsx +71 -0
  357. package/templates/toast/provider.tsx +228 -0
  358. package/templates/toast/toast.tsx +142 -0
  359. package/templates/toast/use-toast.ts +89 -0
  360. package/templates/toast/wc/index.ts +15 -0
  361. package/templates/toast/wc/toast-controller.ts +282 -0
  362. package/templates/toast/wc/toast-provider.ts +161 -0
  363. package/templates/toast/wc/toast.ts +165 -0
  364. package/templates/tooltip/tooltip.tsx +62 -0
  365. package/templates/tooltip/wc/tooltip-content.ts +64 -0
  366. package/templates/tooltip/wc/tooltip.ts +289 -0
  367. package/templates/tree/index.tsx +60 -0
  368. package/templates/tree/tree-item.tsx +131 -0
  369. package/templates/tree/tree.tsx +138 -0
  370. package/templates/tree/wc/index.ts +11 -0
  371. package/templates/tree/wc/tree-item.ts +273 -0
  372. package/templates/tree/wc/tree-utils.ts +143 -0
  373. package/templates/tree/wc/tree.ts +139 -0
  374. package/templates/visually-hidden/visually-hidden.tsx +45 -0
  375. package/templates/visually-hidden/wc/visually-hidden.ts +64 -0
@@ -0,0 +1,465 @@
1
+ /**
2
+ * Slider component for numeric value selection via draggable thumb(s).
3
+ *
4
+ * @element ds-slider
5
+ * @fires ds:change - Fired on value change with { value } or { min, max } for range mode
6
+ *
7
+ * @example
8
+ * ```html
9
+ * <!-- Single value slider -->
10
+ * <ds-slider min="0" max="100" value="50"></ds-slider>
11
+ *
12
+ * <!-- Range slider -->
13
+ * <ds-slider range min="0" max="1000" range-min="200" range-max="800"></ds-slider>
14
+ *
15
+ * <!-- Vertical slider -->
16
+ * <ds-slider orientation="vertical" min="0" max="100"></ds-slider>
17
+ * ```
18
+ */
19
+
20
+ import { type SliderBehavior, type ThumbType, createSliderBehavior } from "@hypoth-ui/primitives-dom";
21
+ import { html, nothing } from "lit";
22
+ import { property, state } from "lit/decorators.js";
23
+ import { DSElement } from "../../base/ds-element.js";
24
+ import { StandardEvents, emitEvent } from "../../events/emit.js";
25
+ import { define } from "../../registry/define.js";
26
+
27
+ export class DsSlider extends DSElement {
28
+ /** Minimum allowed value */
29
+ @property({ type: Number, reflect: true })
30
+ min = 0;
31
+
32
+ /** Maximum allowed value */
33
+ @property({ type: Number, reflect: true })
34
+ max = 100;
35
+
36
+ /** Step increment */
37
+ @property({ type: Number, reflect: true })
38
+ step = 1;
39
+
40
+ /** Current value (single mode) */
41
+ @property({ type: Number, reflect: true })
42
+ value = 0;
43
+
44
+ /** Range mode (two thumbs) */
45
+ @property({ type: Boolean, reflect: true })
46
+ range = false;
47
+
48
+ /** Minimum value in range mode */
49
+ @property({ type: Number, reflect: true, attribute: "range-min" })
50
+ rangeMin = 0;
51
+
52
+ /** Maximum value in range mode */
53
+ @property({ type: Number, reflect: true, attribute: "range-max" })
54
+ rangeMax = 100;
55
+
56
+ /** Orientation */
57
+ @property({ type: String, reflect: true })
58
+ orientation: "horizontal" | "vertical" = "horizontal";
59
+
60
+ /** Disabled state */
61
+ @property({ type: Boolean, reflect: true })
62
+ disabled = false;
63
+
64
+ /** Optional label */
65
+ @property({ type: String })
66
+ label = "";
67
+
68
+ /** ARIA label */
69
+ @property({ type: String, attribute: "aria-label" })
70
+ override ariaLabel: string | null = null;
71
+
72
+ /** Value text formatter for screen readers */
73
+ @property({ attribute: false })
74
+ formatValueText?: (value: number) => string;
75
+
76
+ /** Show tick marks */
77
+ @property({ type: Boolean, reflect: true, attribute: "show-ticks" })
78
+ showTicks = false;
79
+
80
+ /** Show value tooltip on focus/drag */
81
+ @property({ type: Boolean, reflect: true, attribute: "show-tooltip" })
82
+ showTooltip = false;
83
+
84
+ /** Number of tick marks (defaults to (max-min)/step if step > 1) */
85
+ @property({ type: Number, attribute: "tick-count" })
86
+ tickCount?: number;
87
+
88
+ @state()
89
+ private behavior: SliderBehavior | null = null;
90
+
91
+ @state()
92
+ private focusedThumb: ThumbType | null = null;
93
+
94
+ @state()
95
+ private dragging = false;
96
+
97
+ private trackRef: HTMLElement | null = null;
98
+ private boundHandlePointerMove: ((e: PointerEvent) => void) | null = null;
99
+ private boundHandlePointerUp: (() => void) | null = null;
100
+
101
+ override connectedCallback(): void {
102
+ super.connectedCallback();
103
+ this.initBehavior();
104
+ }
105
+
106
+ override disconnectedCallback(): void {
107
+ super.disconnectedCallback();
108
+ this.behavior?.destroy();
109
+ this.behavior = null;
110
+ this.removeGlobalListeners();
111
+ }
112
+
113
+ override updated(changedProperties: Map<string, unknown>): void {
114
+ super.updated(changedProperties);
115
+
116
+ // Re-init behavior if key props change
117
+ if (
118
+ changedProperties.has("min") ||
119
+ changedProperties.has("max") ||
120
+ changedProperties.has("step") ||
121
+ changedProperties.has("range") ||
122
+ changedProperties.has("orientation") ||
123
+ changedProperties.has("disabled")
124
+ ) {
125
+ this.initBehavior();
126
+ }
127
+ }
128
+
129
+ private initBehavior(): void {
130
+ this.behavior?.destroy();
131
+
132
+ this.behavior = createSliderBehavior({
133
+ min: this.min,
134
+ max: this.max,
135
+ step: this.step,
136
+ defaultValue: this.value,
137
+ defaultRange: { min: this.rangeMin, max: this.rangeMax },
138
+ range: this.range,
139
+ orientation: this.orientation,
140
+ disabled: this.disabled,
141
+ onValueChange: (value) => {
142
+ this.value = value;
143
+ emitEvent(this, StandardEvents.CHANGE, { detail: { value } });
144
+ },
145
+ onRangeChange: (range) => {
146
+ this.rangeMin = range.min;
147
+ this.rangeMax = range.max;
148
+ emitEvent(this, StandardEvents.CHANGE, { detail: range });
149
+ },
150
+ });
151
+
152
+ // Set track reference after render
153
+ this.updateComplete.then(() => {
154
+ const track = this.querySelector<HTMLElement>(".ds-slider__track");
155
+ if (track && this.behavior) {
156
+ this.trackRef = track;
157
+ this.behavior.trackElement = track;
158
+ }
159
+ });
160
+ }
161
+
162
+ private handleThumbPointerDown(thumb: ThumbType, event: PointerEvent): void {
163
+ if (this.disabled || !this.behavior) return;
164
+
165
+ event.preventDefault();
166
+ (event.target as HTMLElement).setPointerCapture(event.pointerId);
167
+
168
+ this.behavior.startDrag(thumb, event);
169
+ this.dragging = true;
170
+ this.addGlobalListeners();
171
+ }
172
+
173
+ private handlePointerMove = (event: PointerEvent): void => {
174
+ if (!this.dragging || !this.behavior) return;
175
+ this.behavior.drag(event);
176
+ this.requestUpdate();
177
+ };
178
+
179
+ private handlePointerUp = (): void => {
180
+ if (!this.behavior) return;
181
+ this.behavior.endDrag();
182
+ this.dragging = false;
183
+ this.removeGlobalListeners();
184
+ this.requestUpdate();
185
+ };
186
+
187
+ private handleTrackClick(event: PointerEvent): void {
188
+ if (this.disabled || !this.behavior) return;
189
+
190
+ // Determine which thumb to move (closest in range mode)
191
+ const thumb = this.getClosestThumb(event);
192
+ this.behavior.startDrag(thumb, event);
193
+ this.behavior.endDrag();
194
+ this.requestUpdate();
195
+ }
196
+
197
+ private getClosestThumb(event: PointerEvent): ThumbType {
198
+ if (!this.range || !this.behavior) return "single";
199
+
200
+ const { rangeValue, min, max, orientation } = this.behavior.state;
201
+ const track = this.trackRef;
202
+ if (!track) return "min";
203
+
204
+ const rect = track.getBoundingClientRect();
205
+ let percent: number;
206
+
207
+ if (orientation === "horizontal") {
208
+ percent = ((event.clientX - rect.left) / rect.width) * 100;
209
+ } else {
210
+ percent = 100 - ((event.clientY - rect.top) / rect.height) * 100;
211
+ }
212
+
213
+ const clickValue = (percent / 100) * (max - min) + min;
214
+ const minDist = Math.abs(clickValue - rangeValue.min);
215
+ const maxDist = Math.abs(clickValue - rangeValue.max);
216
+
217
+ return minDist <= maxDist ? "min" : "max";
218
+ }
219
+
220
+ private handleThumbKeyDown(thumb: ThumbType, event: KeyboardEvent): void {
221
+ if (this.disabled || !this.behavior) return;
222
+
223
+ const isVertical = this.orientation === "vertical";
224
+
225
+ switch (event.key) {
226
+ case "ArrowRight":
227
+ case "ArrowUp":
228
+ event.preventDefault();
229
+ if (isVertical ? event.key === "ArrowUp" : event.key === "ArrowRight") {
230
+ this.behavior.increment(thumb);
231
+ } else {
232
+ this.behavior.decrement(thumb);
233
+ }
234
+ break;
235
+ case "ArrowLeft":
236
+ case "ArrowDown":
237
+ event.preventDefault();
238
+ if (isVertical ? event.key === "ArrowDown" : event.key === "ArrowLeft") {
239
+ this.behavior.decrement(thumb);
240
+ } else {
241
+ this.behavior.increment(thumb);
242
+ }
243
+ break;
244
+ case "PageUp":
245
+ event.preventDefault();
246
+ this.behavior.increment(thumb, true);
247
+ break;
248
+ case "PageDown":
249
+ event.preventDefault();
250
+ this.behavior.decrement(thumb, true);
251
+ break;
252
+ case "Home":
253
+ event.preventDefault();
254
+ this.behavior.setToMin(thumb);
255
+ break;
256
+ case "End":
257
+ event.preventDefault();
258
+ this.behavior.setToMax(thumb);
259
+ break;
260
+ }
261
+
262
+ this.requestUpdate();
263
+ }
264
+
265
+ private addGlobalListeners(): void {
266
+ this.boundHandlePointerMove = this.handlePointerMove;
267
+ this.boundHandlePointerUp = this.handlePointerUp;
268
+ document.addEventListener("pointermove", this.boundHandlePointerMove);
269
+ document.addEventListener("pointerup", this.boundHandlePointerUp);
270
+ }
271
+
272
+ private removeGlobalListeners(): void {
273
+ if (this.boundHandlePointerMove) {
274
+ document.removeEventListener("pointermove", this.boundHandlePointerMove);
275
+ }
276
+ if (this.boundHandlePointerUp) {
277
+ document.removeEventListener("pointerup", this.boundHandlePointerUp);
278
+ }
279
+ this.boundHandlePointerMove = null;
280
+ this.boundHandlePointerUp = null;
281
+ }
282
+
283
+ private getValueText(value: number): string {
284
+ if (this.formatValueText) {
285
+ return this.formatValueText(value);
286
+ }
287
+ return String(value);
288
+ }
289
+
290
+ private handleThumbFocus(thumb: ThumbType): void {
291
+ this.focusedThumb = thumb;
292
+ }
293
+
294
+ private handleThumbBlur(): void {
295
+ this.focusedThumb = null;
296
+ }
297
+
298
+ private getTickPositions(): number[] {
299
+ const count = this.tickCount ?? Math.floor((this.max - this.min) / this.step) + 1;
300
+ // Limit to reasonable number of ticks
301
+ const effectiveCount = Math.min(count, 21);
302
+ const positions: number[] = [];
303
+
304
+ for (let i = 0; i < effectiveCount; i++) {
305
+ positions.push((i / (effectiveCount - 1)) * 100);
306
+ }
307
+ return positions;
308
+ }
309
+
310
+ private renderTicks() {
311
+ if (!this.showTicks) return nothing;
312
+
313
+ const positions = this.getTickPositions();
314
+ const isVertical = this.orientation === "vertical";
315
+
316
+ return html`
317
+ <div class="ds-slider__ticks">
318
+ ${positions.map(
319
+ (pos) => html`
320
+ <div
321
+ class="ds-slider__tick"
322
+ style=${isVertical ? `bottom: ${pos}%` : `left: ${pos}%`}
323
+ ></div>
324
+ `
325
+ )}
326
+ </div>
327
+ `;
328
+ }
329
+
330
+ private renderTooltip(value: number, percent: number, isVisible: boolean) {
331
+ if (!this.showTooltip) return nothing;
332
+
333
+ const isVertical = this.orientation === "vertical";
334
+ const style = isVertical ? `bottom: ${percent}%` : `left: ${percent}%`;
335
+
336
+ return html`
337
+ <div
338
+ class="ds-slider__tooltip"
339
+ style=${style}
340
+ data-visible=${isVisible || nothing}
341
+ >
342
+ ${this.getValueText(value)}
343
+ </div>
344
+ `;
345
+ }
346
+
347
+ override render() {
348
+ if (!this.behavior) return nothing;
349
+
350
+ const { state } = this.behavior;
351
+ const singlePercent = this.behavior.valueToPercent(state.value);
352
+ const minPercent = this.behavior.valueToPercent(state.rangeValue.min);
353
+ const maxPercent = this.behavior.valueToPercent(state.rangeValue.max);
354
+
355
+ const isVertical = this.orientation === "vertical";
356
+ const thumbStyle = (percent: number) =>
357
+ isVertical ? `bottom: ${percent}%` : `left: ${percent}%`;
358
+
359
+ const rangeStyle = this.range
360
+ ? isVertical
361
+ ? `bottom: ${minPercent}%; height: ${maxPercent - minPercent}%`
362
+ : `left: ${minPercent}%; width: ${maxPercent - minPercent}%`
363
+ : isVertical
364
+ ? `height: ${singlePercent}%`
365
+ : `width: ${singlePercent}%`;
366
+
367
+ return html`
368
+ <div
369
+ class="ds-slider"
370
+ data-orientation=${this.orientation}
371
+ data-disabled=${this.disabled || nothing}
372
+ data-dragging=${this.dragging || nothing}
373
+ >
374
+ <div
375
+ class="ds-slider__track"
376
+ @pointerdown=${(e: PointerEvent) => this.handleTrackClick(e)}
377
+ >
378
+ <div class="ds-slider__range" style=${rangeStyle}></div>
379
+
380
+ ${this.renderTicks()}
381
+
382
+ ${
383
+ this.range
384
+ ? html`
385
+ <!-- Min thumb -->
386
+ <div
387
+ class="ds-slider__thumb"
388
+ role="slider"
389
+ tabindex=${this.disabled ? -1 : 0}
390
+ aria-label=${this.ariaLabel || this.label || "Minimum value"}
391
+ aria-valuemin=${this.min}
392
+ aria-valuemax=${state.rangeValue.max}
393
+ aria-valuenow=${state.rangeValue.min}
394
+ aria-valuetext=${this.getValueText(state.rangeValue.min)}
395
+ aria-orientation=${this.orientation}
396
+ aria-disabled=${this.disabled}
397
+ data-thumb="min"
398
+ style=${thumbStyle(minPercent)}
399
+ @pointerdown=${(e: PointerEvent) => this.handleThumbPointerDown("min", e)}
400
+ @keydown=${(e: KeyboardEvent) => this.handleThumbKeyDown("min", e)}
401
+ @focus=${() => this.handleThumbFocus("min")}
402
+ @blur=${() => this.handleThumbBlur()}
403
+ >
404
+ ${this.renderTooltip(state.rangeValue.min, minPercent, this.focusedThumb === "min" || this.dragging)}
405
+ </div>
406
+
407
+ <!-- Max thumb -->
408
+ <div
409
+ class="ds-slider__thumb"
410
+ role="slider"
411
+ tabindex=${this.disabled ? -1 : 0}
412
+ aria-label=${this.ariaLabel || this.label || "Maximum value"}
413
+ aria-valuemin=${state.rangeValue.min}
414
+ aria-valuemax=${this.max}
415
+ aria-valuenow=${state.rangeValue.max}
416
+ aria-valuetext=${this.getValueText(state.rangeValue.max)}
417
+ aria-orientation=${this.orientation}
418
+ aria-disabled=${this.disabled}
419
+ data-thumb="max"
420
+ style=${thumbStyle(maxPercent)}
421
+ @pointerdown=${(e: PointerEvent) => this.handleThumbPointerDown("max", e)}
422
+ @keydown=${(e: KeyboardEvent) => this.handleThumbKeyDown("max", e)}
423
+ @focus=${() => this.handleThumbFocus("max")}
424
+ @blur=${() => this.handleThumbBlur()}
425
+ >
426
+ ${this.renderTooltip(state.rangeValue.max, maxPercent, this.focusedThumb === "max" || this.dragging)}
427
+ </div>
428
+ `
429
+ : html`
430
+ <!-- Single thumb -->
431
+ <div
432
+ class="ds-slider__thumb"
433
+ role="slider"
434
+ tabindex=${this.disabled ? -1 : 0}
435
+ aria-label=${this.ariaLabel || this.label || "Value"}
436
+ aria-valuemin=${this.min}
437
+ aria-valuemax=${this.max}
438
+ aria-valuenow=${state.value}
439
+ aria-valuetext=${this.getValueText(state.value)}
440
+ aria-orientation=${this.orientation}
441
+ aria-disabled=${this.disabled}
442
+ data-thumb="single"
443
+ style=${thumbStyle(singlePercent)}
444
+ @pointerdown=${(e: PointerEvent) => this.handleThumbPointerDown("single", e)}
445
+ @keydown=${(e: KeyboardEvent) => this.handleThumbKeyDown("single", e)}
446
+ @focus=${() => this.handleThumbFocus("single")}
447
+ @blur=${() => this.handleThumbBlur()}
448
+ >
449
+ ${this.renderTooltip(state.value, singlePercent, this.focusedThumb === "single" || this.dragging)}
450
+ </div>
451
+ `
452
+ }
453
+ </div>
454
+ </div>
455
+ `;
456
+ }
457
+ }
458
+
459
+ define("ds-slider", DsSlider);
460
+
461
+ declare global {
462
+ interface HTMLElementTagNameMap {
463
+ "ds-slider": DsSlider;
464
+ }
465
+ }
@@ -0,0 +1,64 @@
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 SpinnerSize = "sm" | "md" | "lg";
10
+
11
+ export interface SpinnerProps {
12
+ /**
13
+ * Spinner size - supports responsive object syntax
14
+ * @example
15
+ * ```tsx
16
+ * // Single value
17
+ * <Spinner size="md" />
18
+ *
19
+ * // Responsive
20
+ * <Spinner size={{ base: "sm", md: "md" }} />
21
+ * ```
22
+ */
23
+ size?: ResponsiveProp<SpinnerSize>;
24
+ /** Accessible label for screen readers */
25
+ label?: string;
26
+ /** Additional CSS classes */
27
+ className?: string;
28
+ }
29
+
30
+ /**
31
+ * React wrapper for ds-spinner Web Component.
32
+ * Provides type-safe props for loading indicator.
33
+ */
34
+ export const Spinner = forwardRef<HTMLElement, SpinnerProps>((props, forwardedRef) => {
35
+ const { size = "md", label = "Loading", className, ...rest } = props;
36
+
37
+ const internalRef = useRef<HTMLElement>(null);
38
+
39
+ // Merge refs
40
+ useEffect(() => {
41
+ if (typeof forwardedRef === "function") {
42
+ forwardedRef(internalRef.current);
43
+ } else if (forwardedRef) {
44
+ (forwardedRef as React.MutableRefObject<HTMLElement | null>).current = internalRef.current;
45
+ }
46
+ }, [forwardedRef]);
47
+
48
+ // Resolve responsive size - use base value for the WC attribute
49
+ const resolvedSize = resolveResponsiveValue(size, "md");
50
+ const isResponsive = isResponsiveObject(size);
51
+ const responsiveSizeAttr = isResponsive ? generateResponsiveDataAttr(size) : undefined;
52
+
53
+ return createElement("ds-spinner", {
54
+ ref: internalRef,
55
+ size: resolvedSize,
56
+ label,
57
+ class: className,
58
+ // Add responsive data attribute for CSS targeting
59
+ "data-size-responsive": responsiveSizeAttr,
60
+ ...rest,
61
+ });
62
+ });
63
+
64
+ Spinner.displayName = "Spinner";
@@ -0,0 +1,70 @@
1
+ import { type TemplateResult, html } from "lit";
2
+ import { property } 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
+
7
+ export type SpinnerSize = "sm" | "md" | "lg";
8
+
9
+ /**
10
+ * A loading spinner component with accessibility support.
11
+ *
12
+ * Automatically respects prefers-reduced-motion by replacing
13
+ * rotation with an opacity pulse animation.
14
+ *
15
+ * @element ds-spinner
16
+ *
17
+ * @example
18
+ * ```html
19
+ * <ds-spinner label="Loading content"></ds-spinner>
20
+ * ```
21
+ *
22
+ * @example
23
+ * ```html
24
+ * <!-- In a loading region -->
25
+ * <div aria-busy="true">
26
+ * <ds-spinner label="Fetching data"></ds-spinner>
27
+ * </div>
28
+ * ```
29
+ */
30
+ export class DsSpinner extends DSElement {
31
+ static override styles = [];
32
+
33
+ /**
34
+ * The spinner size.
35
+ */
36
+ @property({ type: String, reflect: true })
37
+ size: SpinnerSize = "md";
38
+
39
+ /**
40
+ * Accessible label for the spinner.
41
+ * Announced by screen readers to indicate loading state.
42
+ */
43
+ @property({ type: String })
44
+ label = "Loading";
45
+
46
+ override render(): TemplateResult {
47
+ const classes = {
48
+ "ds-spinner": true,
49
+ [`ds-spinner--${this.size}`]: true,
50
+ };
51
+
52
+ return html`
53
+ <span
54
+ class=${classMap(classes)}
55
+ role="status"
56
+ aria-label=${this.label}
57
+ ></span>
58
+ `;
59
+ }
60
+ }
61
+
62
+ // Register the component
63
+ define("ds-spinner", DsSpinner);
64
+
65
+ // TypeScript declaration for HTML
66
+ declare global {
67
+ interface HTMLElementTagNameMap {
68
+ "ds-spinner": DsSpinner;
69
+ }
70
+ }