@stacksjs/components 0.2.3

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 (342) hide show
  1. package/README.md +477 -0
  2. package/dist/Accordion-x2gjedap.stx +108 -0
  3. package/dist/Audio-0fk6p9tn.stx +50 -0
  4. package/dist/Avatar-5m0v0s4x.stx +88 -0
  5. package/dist/Badge-ynes82vv.stx +70 -0
  6. package/dist/Breadcrumb-h9n427sk.stx +79 -0
  7. package/dist/Button-7xtrzn14.stx +89 -0
  8. package/dist/Calendar-egvx1pma.stx +232 -0
  9. package/dist/Card-r9w7vy1a.stx +74 -0
  10. package/dist/Checkbox-m8v46pmx.stx +92 -0
  11. package/dist/Checkout-vcnnr176.stx +39 -0
  12. package/dist/CodeBlock-mwex82cm.stx +57 -0
  13. package/dist/Combobox-npb08vkp.stx +13 -0
  14. package/dist/ComboboxButton-vcdyq4zw.stx +13 -0
  15. package/dist/ComboboxInput-c9d2p02m.stx +25 -0
  16. package/dist/ComboboxOption-7d0h9ash.stx +52 -0
  17. package/dist/ComboboxOptions-4dtqc0qa.stx +12 -0
  18. package/dist/CommandPalette-ah00bf8v.stx +39 -0
  19. package/dist/CommandPaletteItem-2yx0gvtj.stx +32 -0
  20. package/dist/DefaultPaymentMethod-emw5fg8s.stx +62 -0
  21. package/dist/Dialog-1w4rz7x0.stx +19 -0
  22. package/dist/DialogBackdrop-qbm3y5ab.stx +9 -0
  23. package/dist/DialogDescription-01w5j74b.stx +11 -0
  24. package/dist/DialogPanel-brsszrrs.stx +16 -0
  25. package/dist/DialogTitle-3rxhwg21.stx +11 -0
  26. package/dist/Drawer-yfaz8q7f.stx +137 -0
  27. package/dist/Dropdown-ng7nx556.stx +24 -0
  28. package/dist/DropdownButton-vc4zpyrb.stx +23 -0
  29. package/dist/DropdownItem-z491y23c.stx +43 -0
  30. package/dist/DropdownItems-7ykf29sj.stx +18 -0
  31. package/dist/EmailInput-bfshpj92.stx +41 -0
  32. package/dist/Footer-xdaf02nr.stx +66 -0
  33. package/dist/Form-z4f7w6r1.stx +209 -0
  34. package/dist/Hero-9vvp7pxf.stx +25 -0
  35. package/dist/Image-ktk0451c.stx +197 -0
  36. package/dist/Installation-33bj4rm7.stx +39 -0
  37. package/dist/Listbox-xcejcmyc.stx +14 -0
  38. package/dist/ListboxButton-nx5kmw19.stx +17 -0
  39. package/dist/ListboxLabel-aky8a73n.stx +11 -0
  40. package/dist/ListboxOption-6h4hsdz5.stx +57 -0
  41. package/dist/ListboxOptions-2sacdtm5.stx +16 -0
  42. package/dist/Login-s2jkvd9y.stx +163 -0
  43. package/dist/Navigator-tqqdgdkw.stx +138 -0
  44. package/dist/Notification-sry8egea.stx +71 -0
  45. package/dist/NumberInput-zm93ddfw.stx +138 -0
  46. package/dist/Pagination-yza9v4qw.stx +183 -0
  47. package/dist/PasswordInput-4xnndp5y.stx +155 -0
  48. package/dist/PaymentMethods-jxba6kek.stx +113 -0
  49. package/dist/Popover-scbqatjq.stx +24 -0
  50. package/dist/PopoverButton-rbxhzj4k.stx +23 -0
  51. package/dist/PopoverPanel-9ng1rm6e.stx +23 -0
  52. package/dist/Portal-j111yvqp.stx +74 -0
  53. package/dist/Progress-gbmw3akr.stx +142 -0
  54. package/dist/Radio-1n9qamv1.stx +81 -0
  55. package/dist/RadioGroup-12dw2vhk.stx +13 -0
  56. package/dist/RadioGroupDescription-bjm3mdht.stx +11 -0
  57. package/dist/RadioGroupLabel-aky8a73n.stx +11 -0
  58. package/dist/RadioGroupOption-9pcxgwmd.stx +51 -0
  59. package/dist/SearchInput-g240e2nq.stx +63 -0
  60. package/dist/Select-p9f94b20.stx +89 -0
  61. package/dist/Sidebar-gwxw8q38.stx +288 -0
  62. package/dist/SidebarFooter-887kxret.stx +95 -0
  63. package/dist/SidebarHeader-qjeyx0hv.stx +100 -0
  64. package/dist/SidebarItem-4dpwtmb4.stx +118 -0
  65. package/dist/SidebarSection-kh92fk4m.stx +108 -0
  66. package/dist/Signup-3nxq5zag.stx +161 -0
  67. package/dist/Skeleton-g0nx1njm.stx +48 -0
  68. package/dist/Spinner-w4zj58xp.stx +109 -0
  69. package/dist/Stepper-rwc5actp.stx +17 -0
  70. package/dist/StepperStep-h0k657nm.stx +53 -0
  71. package/dist/SubscriptionCheckout-4cbxdg7w.stx +353 -0
  72. package/dist/Switch-kjq8qd2p.stx +74 -0
  73. package/dist/Table-59j9qwp0.stx +14 -0
  74. package/dist/TableBody-reka2gwv.stx +10 -0
  75. package/dist/TableCell-j7nh4sgr.stx +10 -0
  76. package/dist/TableHead-ecbrwpqm.stx +10 -0
  77. package/dist/TableHeader-jn2shwsv.stx +13 -0
  78. package/dist/TableRow-xz8rrxhc.stx +11 -0
  79. package/dist/Tabs-kb6ex6m7.stx +145 -0
  80. package/dist/Teleport-819cg9zm.stx +101 -0
  81. package/dist/TextInput-zx9kgr79.stx +146 -0
  82. package/dist/Textarea-5xvmrb0z.stx +119 -0
  83. package/dist/Tooltip-5ehqsy49.stx +76 -0
  84. package/dist/Transition-2j39s044.stx +174 -0
  85. package/dist/TwoFactorChallenge-2q4gg89m.stx +125 -0
  86. package/dist/Video-6aq4shh4.stx +45 -0
  87. package/dist/VirtualList-weh5qtm1.stx +83 -0
  88. package/dist/VirtualTable-59a1eskc.stx +113 -0
  89. package/dist/components/index.d.ts +4 -0
  90. package/dist/composables/index.d.ts +4 -0
  91. package/dist/composables/index.js +3 -0
  92. package/dist/composables/useCopyCode.d.ts +19 -0
  93. package/dist/composables/useDarkMode.d.ts +25 -0
  94. package/dist/composables/useSEO.d.ts +36 -0
  95. package/dist/composables/utilities/index.d.ts +5 -0
  96. package/dist/composables/utilities/useClickOutside.d.ts +28 -0
  97. package/dist/composables/utilities/useFocusTrap.d.ts +34 -0
  98. package/dist/composables/utilities/useKeyboard.d.ts +55 -0
  99. package/dist/composables/utilities/useLocalStorage.d.ts +33 -0
  100. package/dist/composables/utilities/useMediaQuery.d.ts +64 -0
  101. package/dist/index.d.ts +86 -0
  102. package/dist/index.js +19 -0
  103. package/dist/ui/accordion/index.d.ts +12 -0
  104. package/dist/ui/audio/index.d.ts +12 -0
  105. package/dist/ui/auth/index.d.ts +29 -0
  106. package/dist/ui/avatar/index.d.ts +11 -0
  107. package/dist/ui/badge/index.d.ts +9 -0
  108. package/dist/ui/breadcrumb/index.d.ts +13 -0
  109. package/dist/ui/button/index.d.ts +45 -0
  110. package/dist/ui/calendar/index.d.ts +13 -0
  111. package/dist/ui/card/index.d.ts +12 -0
  112. package/dist/ui/checkbox/index.d.ts +15 -0
  113. package/dist/ui/combobox/index.d.ts +35 -0
  114. package/dist/ui/command-palette/index.d.ts +13 -0
  115. package/dist/ui/dialog/index.d.ts +27 -0
  116. package/dist/ui/drawer/index.d.ts +8 -0
  117. package/dist/ui/dropdown/index.d.ts +25 -0
  118. package/dist/ui/form/index.d.ts +48 -0
  119. package/dist/ui/image/index.d.ts +21 -0
  120. package/dist/ui/input/index.d.ts +73 -0
  121. package/dist/ui/listbox/index.d.ts +34 -0
  122. package/dist/ui/navigator/index.d.ts +18 -0
  123. package/dist/ui/notification/index.d.ts +11 -0
  124. package/dist/ui/pagination/index.d.ts +10 -0
  125. package/dist/ui/payment/index.d.ts +53 -0
  126. package/dist/ui/popover/index.d.ts +19 -0
  127. package/dist/ui/portal/index.d.ts +5 -0
  128. package/dist/ui/progress/index.d.ts +11 -0
  129. package/dist/ui/radio/index.d.ts +14 -0
  130. package/dist/ui/radio-group/index.d.ts +26 -0
  131. package/dist/ui/select/index.d.ts +19 -0
  132. package/dist/ui/sidebar/index.d.ts +129 -0
  133. package/dist/ui/skeleton/index.d.ts +10 -0
  134. package/dist/ui/spinner/index.d.ts +8 -0
  135. package/dist/ui/stepper/index.d.ts +17 -0
  136. package/dist/ui/storage/index.d.ts +40 -0
  137. package/dist/ui/switch/index.d.ts +9 -0
  138. package/dist/ui/table/index.d.ts +29 -0
  139. package/dist/ui/tabs/index.d.ts +14 -0
  140. package/dist/ui/teleport/index.d.ts +6 -0
  141. package/dist/ui/textarea/index.d.ts +19 -0
  142. package/dist/ui/tooltip/index.d.ts +9 -0
  143. package/dist/ui/transition/index.d.ts +24 -0
  144. package/dist/ui/video/index.d.ts +15 -0
  145. package/dist/ui/virtual-list/index.d.ts +9 -0
  146. package/dist/ui/virtual-table/index.d.ts +19 -0
  147. package/dist/utils/accessibility.d.ts +285 -0
  148. package/dist/utils/animation/easing.d.ts +112 -0
  149. package/dist/utils/animation/helpers.d.ts +119 -0
  150. package/dist/utils/animation/index.d.ts +3 -0
  151. package/dist/utils/animation/keyframes.d.ts +334 -0
  152. package/dist/utils/error-handling.d.ts +182 -0
  153. package/dist/utils/highlighter.d.ts +27 -0
  154. package/dist/utils/highlighter.js +2 -0
  155. package/dist/utils/i18n.d.ts +245 -0
  156. package/dist/utils/keep-alive.d.ts +171 -0
  157. package/dist/utils/lazy-loading.d.ts +174 -0
  158. package/dist/utils/prop-validation.d.ts +106 -0
  159. package/dist/utils/theme.d.ts +234 -0
  160. package/package.json +69 -0
  161. package/src/components/CodeBlock.stx +57 -0
  162. package/src/components/Footer.stx +66 -0
  163. package/src/components/Hero.stx +25 -0
  164. package/src/components/Installation.stx +39 -0
  165. package/src/components/index.ts +4 -0
  166. package/src/composables/index.ts +4 -0
  167. package/src/composables/useCopyCode.ts +73 -0
  168. package/src/composables/useDarkMode.ts +100 -0
  169. package/src/composables/useSEO.ts +229 -0
  170. package/src/composables/utilities/index.ts +7 -0
  171. package/src/composables/utilities/useClickOutside.ts +72 -0
  172. package/src/composables/utilities/useFocusTrap.ts +159 -0
  173. package/src/composables/utilities/useKeyboard.ts +124 -0
  174. package/src/composables/utilities/useLocalStorage.ts +132 -0
  175. package/src/composables/utilities/useMediaQuery.ts +118 -0
  176. package/src/index.ts +99 -0
  177. package/src/stx.d.ts +4 -0
  178. package/src/ui/accordion/Accordion.stx +108 -0
  179. package/src/ui/accordion/index.ts +14 -0
  180. package/src/ui/audio/Audio.stx +50 -0
  181. package/src/ui/audio/README.md +42 -0
  182. package/src/ui/audio/index.ts +13 -0
  183. package/src/ui/auth/Login.stx +163 -0
  184. package/src/ui/auth/README.md +145 -0
  185. package/src/ui/auth/Signup.stx +161 -0
  186. package/src/ui/auth/TwoFactorChallenge.stx +125 -0
  187. package/src/ui/auth/index.ts +32 -0
  188. package/src/ui/avatar/Avatar.stx +88 -0
  189. package/src/ui/avatar/index.ts +12 -0
  190. package/src/ui/badge/Badge.stx +70 -0
  191. package/src/ui/badge/index.ts +10 -0
  192. package/src/ui/breadcrumb/Breadcrumb.stx +79 -0
  193. package/src/ui/breadcrumb/index.ts +15 -0
  194. package/src/ui/button/Button.stx +89 -0
  195. package/src/ui/button/README.md +100 -0
  196. package/src/ui/button/index.ts +85 -0
  197. package/src/ui/calendar/Calendar.stx +232 -0
  198. package/src/ui/calendar/README.md +254 -0
  199. package/src/ui/calendar/index.ts +14 -0
  200. package/src/ui/card/Card.stx +74 -0
  201. package/src/ui/card/index.ts +13 -0
  202. package/src/ui/checkbox/Checkbox.stx +92 -0
  203. package/src/ui/checkbox/index.ts +16 -0
  204. package/src/ui/combobox/Combobox.stx +13 -0
  205. package/src/ui/combobox/ComboboxButton.stx +13 -0
  206. package/src/ui/combobox/ComboboxInput.stx +25 -0
  207. package/src/ui/combobox/ComboboxOption.stx +52 -0
  208. package/src/ui/combobox/ComboboxOptions.stx +12 -0
  209. package/src/ui/combobox/README.md +154 -0
  210. package/src/ui/combobox/index.ts +40 -0
  211. package/src/ui/command-palette/CommandPalette.stx +39 -0
  212. package/src/ui/command-palette/CommandPaletteItem.stx +32 -0
  213. package/src/ui/command-palette/README.md +42 -0
  214. package/src/ui/command-palette/index.ts +15 -0
  215. package/src/ui/dialog/Dialog.stx +19 -0
  216. package/src/ui/dialog/DialogBackdrop.stx +9 -0
  217. package/src/ui/dialog/DialogDescription.stx +11 -0
  218. package/src/ui/dialog/DialogPanel.stx +16 -0
  219. package/src/ui/dialog/DialogTitle.stx +11 -0
  220. package/src/ui/dialog/README.md +133 -0
  221. package/src/ui/dialog/index.ts +32 -0
  222. package/src/ui/drawer/Drawer.stx +137 -0
  223. package/src/ui/drawer/README.md +110 -0
  224. package/src/ui/drawer/index.ts +9 -0
  225. package/src/ui/dropdown/Dropdown.stx +24 -0
  226. package/src/ui/dropdown/DropdownButton.stx +23 -0
  227. package/src/ui/dropdown/DropdownItem.stx +43 -0
  228. package/src/ui/dropdown/DropdownItems.stx +18 -0
  229. package/src/ui/dropdown/README.md +142 -0
  230. package/src/ui/dropdown/index.ts +29 -0
  231. package/src/ui/form/Form.stx +209 -0
  232. package/src/ui/form/index.ts +67 -0
  233. package/src/ui/heatmap/Heatmap.stx +315 -0
  234. package/src/ui/image/Image.stx +197 -0
  235. package/src/ui/image/README.md +171 -0
  236. package/src/ui/image/index.ts +22 -0
  237. package/src/ui/input/EmailInput.stx +41 -0
  238. package/src/ui/input/NumberInput.stx +138 -0
  239. package/src/ui/input/PasswordInput.stx +155 -0
  240. package/src/ui/input/SearchInput.stx +63 -0
  241. package/src/ui/input/TextInput.stx +146 -0
  242. package/src/ui/input/index.ts +180 -0
  243. package/src/ui/listbox/Listbox.stx +14 -0
  244. package/src/ui/listbox/ListboxButton.stx +17 -0
  245. package/src/ui/listbox/ListboxLabel.stx +11 -0
  246. package/src/ui/listbox/ListboxOption.stx +57 -0
  247. package/src/ui/listbox/ListboxOptions.stx +16 -0
  248. package/src/ui/listbox/README.md +143 -0
  249. package/src/ui/listbox/index.ts +39 -0
  250. package/src/ui/navigator/Navigator.stx +138 -0
  251. package/src/ui/navigator/README.md +352 -0
  252. package/src/ui/navigator/index.ts +20 -0
  253. package/src/ui/notification/Notification.stx +71 -0
  254. package/src/ui/notification/README.md +118 -0
  255. package/src/ui/notification/index.ts +12 -0
  256. package/src/ui/pagination/Pagination.stx +183 -0
  257. package/src/ui/pagination/index.ts +11 -0
  258. package/src/ui/payment/Checkout.stx +39 -0
  259. package/src/ui/payment/DefaultPaymentMethod.stx +62 -0
  260. package/src/ui/payment/PaymentMethods.stx +113 -0
  261. package/src/ui/payment/README.md +427 -0
  262. package/src/ui/payment/SubscriptionCheckout.stx +353 -0
  263. package/src/ui/payment/index.ts +59 -0
  264. package/src/ui/popover/Popover.stx +24 -0
  265. package/src/ui/popover/PopoverButton.stx +23 -0
  266. package/src/ui/popover/PopoverPanel.stx +23 -0
  267. package/src/ui/popover/README.md +95 -0
  268. package/src/ui/popover/index.ts +22 -0
  269. package/src/ui/portal/Portal.stx +74 -0
  270. package/src/ui/portal/index.ts +6 -0
  271. package/src/ui/progress/Progress.stx +142 -0
  272. package/src/ui/progress/index.ts +12 -0
  273. package/src/ui/radio/Radio.stx +81 -0
  274. package/src/ui/radio/index.ts +15 -0
  275. package/src/ui/radio-group/README.md +145 -0
  276. package/src/ui/radio-group/RadioGroup.stx +13 -0
  277. package/src/ui/radio-group/RadioGroupDescription.stx +11 -0
  278. package/src/ui/radio-group/RadioGroupLabel.stx +11 -0
  279. package/src/ui/radio-group/RadioGroupOption.stx +51 -0
  280. package/src/ui/radio-group/index.ts +30 -0
  281. package/src/ui/select/README.md +204 -0
  282. package/src/ui/select/Select.stx +89 -0
  283. package/src/ui/select/index.ts +21 -0
  284. package/src/ui/sidebar/Sidebar.stx +288 -0
  285. package/src/ui/sidebar/SidebarFooter.stx +95 -0
  286. package/src/ui/sidebar/SidebarHeader.stx +100 -0
  287. package/src/ui/sidebar/SidebarItem.stx +118 -0
  288. package/src/ui/sidebar/SidebarSection.stx +108 -0
  289. package/src/ui/sidebar/index.ts +175 -0
  290. package/src/ui/skeleton/Skeleton.stx +48 -0
  291. package/src/ui/skeleton/index.ts +11 -0
  292. package/src/ui/spinner/Spinner.stx +109 -0
  293. package/src/ui/spinner/index.ts +9 -0
  294. package/src/ui/stepper/README.md +36 -0
  295. package/src/ui/stepper/Stepper.stx +17 -0
  296. package/src/ui/stepper/StepperStep.stx +53 -0
  297. package/src/ui/stepper/index.ts +19 -0
  298. package/src/ui/storage/README.md +193 -0
  299. package/src/ui/storage/index.ts +347 -0
  300. package/src/ui/switch/README.md +133 -0
  301. package/src/ui/switch/Switch.stx +74 -0
  302. package/src/ui/switch/index.ts +10 -0
  303. package/src/ui/table/README.md +39 -0
  304. package/src/ui/table/Table.stx +14 -0
  305. package/src/ui/table/TableBody.stx +10 -0
  306. package/src/ui/table/TableCell.stx +10 -0
  307. package/src/ui/table/TableHead.stx +10 -0
  308. package/src/ui/table/TableHeader.stx +13 -0
  309. package/src/ui/table/TableRow.stx +11 -0
  310. package/src/ui/table/index.ts +35 -0
  311. package/src/ui/tabs/Tabs.stx +145 -0
  312. package/src/ui/tabs/index.ts +16 -0
  313. package/src/ui/teleport/Teleport.stx +101 -0
  314. package/src/ui/teleport/index.ts +7 -0
  315. package/src/ui/textarea/Textarea.stx +119 -0
  316. package/src/ui/textarea/index.ts +20 -0
  317. package/src/ui/tooltip/Tooltip.stx +76 -0
  318. package/src/ui/tooltip/index.ts +10 -0
  319. package/src/ui/transition/README.md +30 -0
  320. package/src/ui/transition/Transition.stx +174 -0
  321. package/src/ui/transition/index.ts +25 -0
  322. package/src/ui/video/README.md +48 -0
  323. package/src/ui/video/Video.stx +45 -0
  324. package/src/ui/video/index.ts +16 -0
  325. package/src/ui/virtual-list/VirtualList.stx +83 -0
  326. package/src/ui/virtual-list/index.ts +10 -0
  327. package/src/ui/virtual-table/VirtualTable.stx +113 -0
  328. package/src/ui/virtual-table/index.ts +21 -0
  329. package/src/utils/PROP_VALIDATION.md +458 -0
  330. package/src/utils/THEME_SYSTEM.md +702 -0
  331. package/src/utils/accessibility.ts +841 -0
  332. package/src/utils/animation/easing.ts +368 -0
  333. package/src/utils/animation/helpers.ts +223 -0
  334. package/src/utils/animation/index.ts +5 -0
  335. package/src/utils/animation/keyframes.ts +230 -0
  336. package/src/utils/error-handling.ts +473 -0
  337. package/src/utils/highlighter.ts +93 -0
  338. package/src/utils/i18n.ts +634 -0
  339. package/src/utils/keep-alive.ts +818 -0
  340. package/src/utils/lazy-loading.ts +530 -0
  341. package/src/utils/prop-validation.ts +478 -0
  342. package/src/utils/theme.ts +626 -0
package/README.md ADDED
@@ -0,0 +1,477 @@
1
+ # @stacksjs/components
2
+
3
+ A modern, accessible component library built with STX, featuring headwind utility classes and TypeScript syntax highlighting.
4
+
5
+ ## Features
6
+
7
+ - 🚀 Built with STX templating engine
8
+ - 🎨 Styled with headwind utility-first CSS
9
+ - 🎯 TypeScript syntax highlighting with ts-syntax-highlighter
10
+ - ♿ Accessible by default (WAI-ARIA compliant)
11
+ - 🌙 Dark mode support
12
+ - 📦 Tree-shakeable
13
+ - 🔧 Fully customizable
14
+ - ⚡ Optimized for performance
15
+
16
+ ## Installation
17
+
18
+ ```bash
19
+ bun add @stacksjs/components
20
+ ```
21
+
22
+ Or with other package managers:
23
+
24
+ ```bash
25
+ npm install @stacksjs/components
26
+ pnpm add @stacksjs/components
27
+ yarn add @stacksjs/components
28
+ ```
29
+
30
+ ## Components
31
+
32
+ ### UI Components (35)
33
+
34
+ - **Accordion** - Expandable content sections with keyboard navigation
35
+ - **Auth** - Login, Signup, and 2FA components
36
+ - **Audio** - Audio player with waveform visualization
37
+ - **Avatar** - User avatars with fallback initials and status indicators
38
+ - **Badge** - Labels and tags with color variants and removable option
39
+ - **Breadcrumb** - Navigation breadcrumbs with collapse support
40
+ - **Button** - Versatile button with loading, icons, 5 sizes (xs-xl), full-width
41
+ - **Calendar** - Date picker with localization, min/max dates, disabled dates, dark mode ✨ NEW
42
+ - **Card** - Content cards with images, variants, and hover effects
43
+ - **Drawer** - Slide-out panel from any direction
44
+ - **Form** - Form wrapper with validation, error handling, and submit management
45
+ - **Image** - Optimized images with lazy loading, srcset, WebP, blur placeholder
46
+ - **Pagination** - Page navigation with customizable display
47
+ - **Portal** - Render content outside DOM hierarchy
48
+ - **Teleport** - Move content to different DOM nodes
49
+ - **Payment** - Stripe checkout and payment management (3 components)
50
+ - **Progress** - Linear and circular progress indicators
51
+ - **Select** - Native-style select dropdown
52
+ - **Skeleton** - Loading placeholders with multiple variants
53
+ - **Spinner** - Loading spinners with multiple styles (circle, dots, bars, ring)
54
+ - **Storage** - Enhanced storage with watch, compression, encryption, batch operations, quota checking
55
+ - **Switch** - Modern toggle switch component
56
+ - **Tabs** - Tabbed content with horizontal/vertical layouts and multiple variants
57
+ - **Tooltip** - Contextual tooltips with positioning options
58
+ - **Video** - Video player with aspect ratio support
59
+ - **VirtualList** - Windowed list for rendering large datasets efficiently
60
+ - **VirtualTable** - Windowed table with columns for large datasets
61
+ - **Dropdown** - Menu dropdown component with keyboard navigation
62
+ - **Dialog** - Modal dialog component with backdrop
63
+ - **Radio Group** - Radio button group with single selection
64
+ - **Popover** - Floating panel component with positioning
65
+ - **Listbox** - Custom select component with keyboard support
66
+ - **Combobox** - Searchable select with filtering
67
+ - **Navigator** - Navigation component with 4 variants (default, pills, underline, sidebar), icons, badges ✨ NEW
68
+ - **Notification** - Toast notifications with auto-hide
69
+ - **Stepper** - Multi-step progress indicator
70
+ - **Transition** - Enter/leave animations with 7 presets, lifecycle hooks, and custom timing
71
+ - **Table** - Responsive table with sorting/filtering
72
+ - **Command Palette** - Searchable command menu
73
+
74
+ ### Input Components (5)
75
+
76
+ - **TextInput** - Base input with icons, clear button, character counter
77
+ - **EmailInput** - Email input with validation
78
+ - **PasswordInput** - Password input with show/hide toggle & strength indicator
79
+ - **NumberInput** - Number input with increment/decrement controls
80
+ - **SearchInput** - Search with debounced callback
81
+
82
+ ### Form Components (3)
83
+
84
+ - **Textarea** - Multi-line input with auto-resize
85
+ - **Checkbox** - Checkbox with indeterminate state
86
+ - **Radio** - Radio button with descriptions
87
+
88
+ ### Utility Components
89
+
90
+ - **CodeBlock** - Syntax highlighted code blocks with copy functionality
91
+ - **Hero** - Hero section component
92
+ - **Footer** - Footer component with social links
93
+ - **Installation** - Installation instructions component
94
+
95
+ ## Component Syntax
96
+
97
+ stx provides multiple ways to use components, giving you flexibility to choose the syntax that best fits your project:
98
+
99
+ ### 1. @component Directive with Object Shorthand (Recommended)
100
+
101
+ The most concise syntax using ES6 object shorthand:
102
+
103
+ ```stx
104
+ <script>
105
+ export const title = 'Welcome'
106
+ export const variant = 'primary'
107
+ export const onClick = () => console.log('clicked')
108
+ </script>
109
+
110
+ @component('Button', {
111
+ title,
112
+ variant,
113
+ onClick
114
+ })
115
+ @endcomponent
116
+ ```
117
+
118
+ ### 2. @component Directive with Full Props
119
+
120
+ Traditional explicit prop mapping:
121
+
122
+ ```stx
123
+ @component('Button', {
124
+ title: title,
125
+ variant: variant,
126
+ onClick: onClick
127
+ })
128
+ @endcomponent
129
+ ```
130
+
131
+ ### 3. PascalCase Component Tags with Dynamic Binding (Vue-like)
132
+
133
+ Use `:prop` syntax for dynamic values from context:
134
+
135
+ ```stx
136
+ <script>
137
+ export const title = 'Welcome'
138
+ export const variant = 'primary'
139
+ </script>
140
+
141
+ <Button
142
+ :title="title"
143
+ :variant="variant"
144
+ :onClick="onClick"
145
+ />
146
+ ```
147
+
148
+ ### 4. PascalCase Component Tags with Static Values
149
+
150
+ Use regular attributes for static strings:
151
+
152
+ ```stx
153
+ <Button
154
+ title="Welcome"
155
+ variant="primary"
156
+ />
157
+ ```
158
+
159
+ ### 5. Mixed Static and Dynamic Props
160
+
161
+ Combine static strings and dynamic bindings:
162
+
163
+ ```stx
164
+ <Button
165
+ title="Static Title"
166
+ :variant="dynamicVariant"
167
+ size="large"
168
+ />
169
+ ```
170
+
171
+ All these syntaxes are equivalent and fully interchangeable. Choose the one that fits your coding style!
172
+
173
+ ## Usage
174
+
175
+ ### Basic Example
176
+
177
+ ```stx
178
+ <script>
179
+ import { Button, Switch } from '@stacksjs/components'
180
+
181
+ let notifications = true
182
+
183
+ function handleNotificationChange(checked) {
184
+ notifications = checked
185
+ }
186
+
187
+ module.exports = { notifications, handleNotificationChange }
188
+ </script>
189
+
190
+ <div class="p-6">
191
+ <h1 class="text-2xl font-bold mb-4">Settings</h1>
192
+
193
+ @component('Switch', {
194
+ checked: notifications,
195
+ label: 'Enable notifications',
196
+ onChange: handleNotificationChange
197
+ })
198
+
199
+ <div class="mt-4">
200
+ @component('Button', { variant: 'primary' })
201
+ Save Changes
202
+ @endcomponent
203
+ </div>
204
+ </div>
205
+ ```
206
+
207
+ ### With Code Highlighting
208
+
209
+ ```stx
210
+ <script>
211
+ import { CodeBlock } from '@stacksjs/components'
212
+
213
+ const code = `
214
+ function greet(name: string) {
215
+ console.log(\`Hello, \${name}!\`)
216
+ }
217
+ `
218
+
219
+ module.exports = { code }
220
+ </script>
221
+
222
+ @component('CodeBlock', {
223
+ code: code,
224
+ language: 'typescript',
225
+ copyable: true
226
+ })
227
+ ```
228
+
229
+ ### Using Composables
230
+
231
+ ```stx
232
+ <script>
233
+ import { useDarkMode, useCopyCode } from '@stacksjs/components'
234
+
235
+ const { isDark, toggle } = useDarkMode()
236
+
237
+ module.exports = { isDark, toggle }
238
+ </script>
239
+
240
+ <button @click="toggle">
241
+ @if(isDark)
242
+ Switch to Light Mode
243
+ @else
244
+ Switch to Dark Mode
245
+ @endif
246
+ </button>
247
+ ```
248
+
249
+ ## Configuration
250
+
251
+ ### Headwind Configuration
252
+
253
+ The components use headwind for utility classes. You can customize the design system by creating a `headwind.config.ts` file:
254
+
255
+ ```typescript
256
+ import type { HeadwindConfig } from '@stacksjs/headwind'
257
+
258
+ export default {
259
+ theme: {
260
+ extend: {
261
+ colors: {
262
+ primary: {
263
+ 500: '#your-color',
264
+ },
265
+ },
266
+ },
267
+ },
268
+ } satisfies HeadwindConfig
269
+ ```
270
+
271
+ ### Syntax Highlighting Themes
272
+
273
+ Configure syntax highlighting themes for code blocks:
274
+
275
+ ```typescript
276
+ import { createHighlighter } from 'ts-syntax-highlighter'
277
+
278
+ const highlighter = await createHighlighter({
279
+ themes: ['github-light', 'github-dark'],
280
+ languages: ['typescript', 'javascript', 'html'],
281
+ })
282
+ ```
283
+
284
+ ## Component APIs
285
+
286
+ ### Button
287
+
288
+ ```typescript
289
+ interface ButtonProps {
290
+ variant?: 'primary' | 'secondary' | 'outline' | 'ghost' | 'danger'
291
+ size?: 'sm' | 'md' | 'lg'
292
+ disabled?: boolean
293
+ type?: 'button' | 'submit' | 'reset'
294
+ className?: string
295
+ onClick?: () => void
296
+ }
297
+ ```
298
+
299
+ ### Switch
300
+
301
+ ```typescript
302
+ interface SwitchProps {
303
+ checked?: boolean
304
+ disabled?: boolean
305
+ size?: 'sm' | 'md' | 'lg'
306
+ className?: string
307
+ onChange?: (checked: boolean) => void
308
+ label?: string
309
+ }
310
+ ```
311
+
312
+ ### CodeBlock
313
+
314
+ ```typescript
315
+ interface CodeBlockProps {
316
+ code: string
317
+ language?: string
318
+ theme?: 'light' | 'dark' | 'auto'
319
+ lineNumbers?: boolean
320
+ copyable?: boolean
321
+ className?: string
322
+ }
323
+ ```
324
+
325
+ ## Composables
326
+
327
+ ### Core Composables
328
+
329
+ #### useDarkMode
330
+
331
+ ```typescript
332
+ const { isDark, theme, toggle, setTheme } = useDarkMode({
333
+ storageKey: 'theme',
334
+ defaultTheme: 'system',
335
+ })
336
+ ```
337
+
338
+ #### useCopyCode
339
+
340
+ ```typescript
341
+ const { copied, copy, reset } = useCopyCode({
342
+ code: 'const foo = "bar"',
343
+ onSuccess: () => console.log('Copied!'),
344
+ timeout: 2000,
345
+ })
346
+ ```
347
+
348
+ #### useSEO
349
+
350
+ ```typescript
351
+ useSEO({
352
+ title: 'My Page',
353
+ description: 'Page description',
354
+ ogImage: 'https://example.com/og.png',
355
+ })
356
+ ```
357
+
358
+ ### Utility Composables (5 new)
359
+
360
+ #### useClickOutside
361
+
362
+ ```typescript
363
+ const cleanup = useClickOutside(
364
+ elementRef,
365
+ () => console.log('Clicked outside!'),
366
+ { enabled: true, ignore: ['.modal'] }
367
+ )
368
+ ```
369
+
370
+ #### useKeyboard
371
+
372
+ ```typescript
373
+ useKeyboard([
374
+ { key: 'Escape', handler: () => closeModal() },
375
+ { key: 's', ctrl: true, handler: () => save() },
376
+ ])
377
+ ```
378
+
379
+ #### useFocusTrap
380
+
381
+ ```typescript
382
+ const { activate, deactivate } = useFocusTrap(containerRef, {
383
+ initialFocus: firstInputRef,
384
+ returnFocus: true,
385
+ })
386
+ ```
387
+
388
+ #### useMediaQuery
389
+
390
+ ```typescript
391
+ const { matches } = useMediaQuery('(min-width: 768px)')
392
+ const { matches: isDark } = useIsDarkMode()
393
+ const { matches: isMobile } = useIsMobile()
394
+ ```
395
+
396
+ #### useLocalStorage
397
+
398
+ ```typescript
399
+ const { value, setValue, removeValue } = useLocalStorage('key', 'initial')
400
+ setValue('new value')
401
+ ```
402
+
403
+ ## Animation Utilities (3 modules)
404
+
405
+ ### Easing Functions (33 functions)
406
+
407
+ ```typescript
408
+ import { Easing } from '@stacksjs/components'
409
+
410
+ // Linear, Quad, Cubic, Quart, Quint, Sine, Expo, Circ, Elastic, Back, Bounce
411
+ const value = Easing.easeInOutCubic(time, start, change, duration)
412
+ ```
413
+
414
+ ### Keyframe Animations (15 presets)
415
+
416
+ ```typescript
417
+ import { animate, KeyframeAnimations } from '@stacksjs/components'
418
+
419
+ // Predefined animations: fadeIn, fadeOut, slideInUp, slideInDown, zoom, bounce, pulse, shake, etc.
420
+ animate(element, 'fadeIn', { duration: 500 })
421
+ ```
422
+
423
+ ### CSS Animation Helpers
424
+
425
+ ```typescript
426
+ import { applyAnimation, staggerAnimation, sequenceAnimations } from '@stacksjs/components'
427
+
428
+ applyAnimation(element, 'slide-in', { duration: '300ms' })
429
+ staggerAnimation(elements, 'fade-in', { stagger: 100 })
430
+ ```
431
+
432
+ ## Development
433
+
434
+ ```bash
435
+ # Install dependencies
436
+ bun install
437
+
438
+ # Build the library
439
+ bun run build
440
+
441
+ # Run tests
442
+ bun test
443
+
444
+ # Watch mode
445
+ bun run dev
446
+ ```
447
+
448
+ ## Contributing
449
+
450
+ Contributions are welcome! Please read our [contributing guidelines](../../CONTRIBUTING.md) before submitting a PR.
451
+
452
+ ## Migration Status
453
+
454
+ This library is actively being migrated from Vue to STX. Check our [TODO.md](../../TODO.md) for the complete migration roadmap and progress.
455
+
456
+ **Completed:**
457
+
458
+ - ✅ Infrastructure setup
459
+ - ✅ Composables (useDarkMode, useCopyCode, useSEO)
460
+ - ✅ Base components (CodeBlock, Hero, Footer, Installation)
461
+ - ✅ 35 UI Components (Accordion, Auth, Audio, Avatar, Badge, Breadcrumb, Button, Card, Drawer, Form, Image, Pagination, Portal, Teleport, Payment, Progress, Select, Skeleton, Spinner, Storage, Switch, Tabs, Tooltip, Video, VirtualList, VirtualTable, Dropdown, Dialog, Radio Group, Popover, Listbox, Combobox, Notification, Stepper, Transition, Table, Command Palette)
462
+ - ✅ 5 Input Components (TextInput, EmailInput, PasswordInput, NumberInput, SearchInput)
463
+ - ✅ 3 Form Components (Textarea, Checkbox, Radio)
464
+ - ✅ 8 Composables (useDarkMode, useCopyCode, useSEO, useClickOutside, useKeyboard, useFocusTrap, useMediaQuery, useLocalStorage)
465
+ - ✅ Animation Utilities (33 easing functions, 15 keyframe presets, CSS helpers)
466
+ - ✅ **Total: 47 Components + 8 Composables + Animation Utils**
467
+
468
+ ## License
469
+
470
+ MIT © [Chris Breuer](https://github.com/chrisbbreuer)
471
+
472
+ ## Credits
473
+
474
+ - Built with [STX](https://github.com/stacksjs/stx)
475
+ - Styled with [Headwind](https://github.com/stacksjs/headwind)
476
+ - Syntax highlighting by [ts-syntax-highlighter](https://github.com/stacksjs/ts-syntax-highlighter)
477
+ - Inspired by [Headless UI](https://headlessui.com)
@@ -0,0 +1,108 @@
1
+ <script>
2
+ export const items = $props.items || []
3
+ export const allowMultiple = $props.allowMultiple || false
4
+ export const defaultOpen = $props.defaultOpen || []
5
+ export const className = $props.className || ''
6
+ export const onChange = $props.onChange
7
+
8
+ // Track which items are open
9
+ let openItems = defaultOpen
10
+
11
+ // Toggle an item
12
+ function toggleItem(index) {
13
+ if (allowMultiple) {
14
+ // Multiple items can be open
15
+ if (openItems.includes(index)) {
16
+ openItems = openItems.filter(i => i !== index)
17
+ } else {
18
+ openItems = [...openItems, index]
19
+ }
20
+ } else {
21
+ // Only one item can be open
22
+ if (openItems.includes(index)) {
23
+ openItems = []
24
+ } else {
25
+ openItems = [index]
26
+ }
27
+ }
28
+
29
+ if (onChange) {
30
+ onChange(openItems)
31
+ }
32
+ }
33
+
34
+ // Check if item is open
35
+ function isOpen(index) {
36
+ return openItems.includes(index)
37
+ }
38
+
39
+ export const accordionClasses = `divide-y divide-gray-200 dark:divide-gray-700 border border-gray-200 dark:border-gray-700 rounded-lg ${className}`.trim()
40
+ export const itemClasses = ``.trim()
41
+ export const headerClasses = `w-full flex items-center justify-between px-4 py-3 text-left font-medium text-gray-900 dark:text-gray-100 hover:bg-gray-50 dark:hover:bg-gray-800 transition-colors duration-150 focus:outline-none focus:ring-2 focus:ring-blue-500 focus:ring-offset-2 dark:focus:ring-offset-gray-900`.trim()
42
+ export const iconClasses = `w-5 h-5 text-gray-500 dark:text-gray-400 transition-transform duration-200`.trim()
43
+ export const contentClasses = `px-4 py-3 text-gray-700 dark:text-gray-300`.trim()
44
+ </script>
45
+
46
+ <div class="{{ accordionClasses }}" role="region">
47
+ @foreach(item in items)
48
+ <div class="{{ itemClasses }}">
49
+ <button
50
+ type="button"
51
+ class="{{ headerClasses }}"
52
+ onclick="toggleItem({{ $loop.index }})"
53
+ aria-expanded="{{ isOpen($loop.index) ? 'true' : 'false' }}"
54
+ aria-controls="accordion-content-{{ $loop.index }}"
55
+ >
56
+ <span>{{ item.title }}</span>
57
+ <svg
58
+ class="{{ iconClasses }}"
59
+ style="transform: rotate({{ isOpen($loop.index) ? '180' : '0' }}deg)"
60
+ fill="none"
61
+ viewBox="0 0 24 24"
62
+ stroke="currentColor"
63
+ >
64
+ <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 9l-7 7-7-7" />
65
+ </svg>
66
+ </button>
67
+
68
+ @if(isOpen($loop.index))
69
+ <div
70
+ id="accordion-content-{{ $loop.index }}"
71
+ class="{{ contentClasses }}"
72
+ role="region"
73
+ >
74
+ {!! item.content !!}
75
+ </div>
76
+ @endif
77
+ </div>
78
+ @endforeach
79
+ </div>
80
+
81
+ <script>
82
+ // Keyboard navigation
83
+ if (typeof window !== 'undefined') {
84
+ window.addEventListener('DOMContentLoaded', () => {
85
+ const buttons = document.querySelectorAll('[aria-expanded]')
86
+
87
+ buttons.forEach((button, index) => {
88
+ button.addEventListener('keydown', (event) => {
89
+ if (event.key === 'ArrowDown') {
90
+ event.preventDefault()
91
+ const nextButton = buttons[index + 1]
92
+ if (nextButton) nextButton.focus()
93
+ } else if (event.key === 'ArrowUp') {
94
+ event.preventDefault()
95
+ const prevButton = buttons[index - 1]
96
+ if (prevButton) prevButton.focus()
97
+ } else if (event.key === 'Home') {
98
+ event.preventDefault()
99
+ buttons[0].focus()
100
+ } else if (event.key === 'End') {
101
+ event.preventDefault()
102
+ buttons[buttons.length - 1].focus()
103
+ }
104
+ })
105
+ })
106
+ })
107
+ }
108
+ </script>
@@ -0,0 +1,50 @@
1
+ <script>
2
+ export const src = $props.src || ''
3
+ export const autoplay = $props.autoplay || false
4
+ export const loop = $props.loop || false
5
+ export const muted = $props.muted || false
6
+ export const controls = $props.controls ?? true
7
+ export const preload = $props.preload || 'metadata'
8
+ export const className = $props.className || ''
9
+ export const showWaveform = $props.showWaveform || false
10
+ export const title = $props.title || ''
11
+
12
+ export const containerClasses = `relative w-full ${className}`.trim()
13
+ export const audioClasses = 'w-full rounded-md bg-gray-100 dark:bg-gray-800'
14
+ </script>
15
+
16
+ <div class="{{ containerClasses }}">
17
+ @if(title)
18
+ <div class="mb-2 px-1">
19
+ <h3 class="text-sm font-medium text-gray-900 dark:text-gray-100">
20
+ {{ title }}
21
+ </h3>
22
+ </div>
23
+ @endif
24
+
25
+ <audio
26
+ class="{{ audioClasses }}"
27
+ src="{{ src }}"
28
+ controls="{{ controls }}"
29
+ autoplay="{{ autoplay }}"
30
+ loop="{{ loop }}"
31
+ muted="{{ muted }}"
32
+ preload="{{ preload }}"
33
+ >
34
+ Your browser does not support the audio element.
35
+ </audio>
36
+
37
+ @if(showWaveform)
38
+ <div class="mt-2 h-16 bg-gray-100 dark:bg-gray-800 rounded-md flex items-center justify-center">
39
+ <svg class="w-full h-full px-4" viewBox="0 0 100 40" preserveAspectRatio="none">
40
+ <path
41
+ d="M 0,20 L 10,15 L 20,10 L 30,5 L 40,15 L 50,20 L 60,25 L 70,30 L 80,20 L 90,15 L 100,20"
42
+ fill="none"
43
+ stroke="currentColor"
44
+ stroke-width="2"
45
+ class="text-indigo-500 dark:text-indigo-400"
46
+ />
47
+ </svg>
48
+ </div>
49
+ @endif
50
+ </div>