@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
@@ -0,0 +1,119 @@
1
+ <script>
2
+ export const value = $props.value || ''
3
+ export const onChange = $props.onChange || (() => {})
4
+ export const placeholder = $props.placeholder || ''
5
+ export const disabled = $props.disabled || false
6
+ export const readonly = $props.readonly || false
7
+ export const rows = $props.rows || 4
8
+ export const autoResize = $props.autoResize || false
9
+ export const maxRows = $props.maxRows || 10
10
+ export const error = $props.error || false
11
+ export const label = $props.label || ''
12
+ export const helperText = $props.helperText || ''
13
+ export const required = $props.required || false
14
+ export const maxLength = $props.maxLength
15
+ export const showCount = $props.showCount || false
16
+ export const resize = $props.resize || 'vertical' // 'none' | 'vertical' | 'horizontal' | 'both'
17
+ export const className = $props.className || ''
18
+
19
+ // Resize classes
20
+ const resizeClasses = {
21
+ none: 'resize-none',
22
+ vertical: 'resize-y',
23
+ horizontal: 'resize-x',
24
+ both: 'resize',
25
+ }
26
+
27
+ // Base and state classes
28
+ const baseClasses = 'block w-full border-0 rounded-md shadow-sm ring-1 ring-inset transition-colors duration-200 focus:ring-2 focus:ring-inset px-4 py-2 text-base dark:bg-blue-gray-700 dark:text-gray-100'
29
+
30
+ const stateClasses = error
31
+ ? 'ring-red-300 dark:ring-red-600 text-red-900 dark:text-red-300 placeholder-red-300 dark:placeholder-red-500 focus:ring-red-500 dark:focus:ring-red-400'
32
+ : 'ring-gray-300 dark:ring-gray-600 text-gray-900 dark:text-gray-100 placeholder-gray-400 dark:placeholder-gray-500 focus:ring-indigo-600 dark:focus:ring-indigo-400'
33
+
34
+ const disabledClasses = disabled
35
+ ? 'opacity-50 cursor-not-allowed bg-gray-50 dark:bg-gray-800'
36
+ : readonly
37
+ ? 'bg-gray-50 dark:bg-gray-800 cursor-default'
38
+ : 'bg-white dark:bg-blue-gray-700'
39
+
40
+ export const textareaClasses = `${baseClasses} ${stateClasses} ${disabledClasses} ${resizeClasses[resize]} ${className}`.trim()
41
+ export const labelClasses = `block text-sm font-medium leading-6 mb-2 ${error ? 'text-red-600 dark:text-red-400' : 'text-gray-900 dark:text-gray-100'}`.trim()
42
+ export const helperClasses = `mt-2 text-sm ${error ? 'text-red-600 dark:text-red-400' : 'text-gray-500 dark:text-gray-400'}`.trim()
43
+ </script>
44
+
45
+ <div class="w-full">
46
+ @if(label)
47
+ <label for="textarea-input" class="{{ labelClasses }}">
48
+ {{ label }}
49
+ @if(required)
50
+ <span class="text-red-500 ml-1">*</span>
51
+ @endif
52
+ </label>
53
+ @endif
54
+
55
+ <textarea
56
+ id="textarea-input"
57
+ class="{{ textareaClasses }}"
58
+ rows="{{ rows }}"
59
+ placeholder="{{ placeholder }}"
60
+ disabled="{{ disabled }}"
61
+ readonly="{{ readonly }}"
62
+ required="{{ required }}"
63
+ @if(maxLength)maxlength="{{ maxLength }}"@endif
64
+ oninput="handleInput(event)"
65
+ aria-invalid="{{ error ? 'true' : 'false' }}"
66
+ @if(helperText)aria-describedby="helper-text"@endif
67
+ >{{ value }}</textarea>
68
+
69
+ @if(helperText || (showCount && maxLength))
70
+ <div class="flex items-center justify-between mt-2">
71
+ @if(helperText)
72
+ <p id="helper-text" class="{{ helperClasses }}">
73
+ {{ helperText }}
74
+ </p>
75
+ @else
76
+ <span></span>
77
+ @endif
78
+
79
+ @if(showCount && maxLength)
80
+ <p class="text-sm text-gray-500 dark:text-gray-400">
81
+ {{ value.length }} / {{ maxLength }}
82
+ </p>
83
+ @endif
84
+ </div>
85
+ @endif
86
+ </div>
87
+
88
+ <script>
89
+ function handleInput(event) {
90
+ const textarea = event.target
91
+ const newValue = textarea.value
92
+
93
+ if (autoResize && typeof window !== 'undefined') {
94
+ // Auto-resize functionality
95
+ textarea.style.height = 'auto'
96
+ const scrollHeight = textarea.scrollHeight
97
+ const lineHeight = parseInt(window.getComputedStyle(textarea).lineHeight)
98
+ const maxHeight = lineHeight * maxRows
99
+
100
+ textarea.style.height = Math.min(scrollHeight, maxHeight) + 'px'
101
+ textarea.style.overflowY = scrollHeight > maxHeight ? 'auto' : 'hidden'
102
+ }
103
+
104
+ if (onChange) {
105
+ onChange(newValue)
106
+ }
107
+ }
108
+
109
+ // Initialize auto-resize on mount
110
+ if (autoResize && typeof window !== 'undefined') {
111
+ window.addEventListener('DOMContentLoaded', () => {
112
+ const textarea = document.getElementById('textarea-input')
113
+ if (textarea && value) {
114
+ // Trigger initial resize
115
+ textarea.dispatchEvent(new Event('input'))
116
+ }
117
+ })
118
+ }
119
+ </script>
@@ -0,0 +1,20 @@
1
+ export { default as Textarea } from './Textarea.stx'
2
+
3
+ export interface TextareaProps {
4
+ value?: string
5
+ onChange?: (value: string) => void
6
+ placeholder?: string
7
+ disabled?: boolean
8
+ readonly?: boolean
9
+ rows?: number
10
+ autoResize?: boolean
11
+ maxRows?: number
12
+ error?: boolean
13
+ label?: string
14
+ helperText?: string
15
+ required?: boolean
16
+ maxLength?: number
17
+ showCount?: boolean
18
+ resize?: 'none' | 'vertical' | 'horizontal' | 'both'
19
+ className?: string
20
+ }
@@ -0,0 +1,76 @@
1
+ <script>
2
+ export const content = $props.content || ''
3
+ export const position = $props.position || 'top'
4
+ export const delay = $props.delay || 0
5
+ export const className = $props.className || ''
6
+ export const show = $props.show || false
7
+ export const disabled = $props.disabled || false
8
+
9
+ // Position classes
10
+ const positionClasses = {
11
+ top: 'bottom-full left-1/2 -translate-x-1/2 mb-2',
12
+ bottom: 'top-full left-1/2 -translate-x-1/2 mt-2',
13
+ left: 'right-full top-1/2 -translate-y-1/2 mr-2',
14
+ right: 'left-full top-1/2 -translate-y-1/2 ml-2',
15
+ }
16
+
17
+ // Arrow classes
18
+ const arrowClasses = {
19
+ top: 'top-full left-1/2 -translate-x-1/2 border-t-gray-900 dark:border-t-gray-700',
20
+ bottom: 'bottom-full left-1/2 -translate-x-1/2 border-b-gray-900 dark:border-b-gray-700',
21
+ left: 'left-full top-1/2 -translate-y-1/2 border-l-gray-900 dark:border-l-gray-700',
22
+ right: 'right-full top-1/2 -translate-y-1/2 border-r-gray-900 dark:border-r-gray-700',
23
+ }
24
+
25
+ export const tooltipClasses = `absolute z-50 px-3 py-2 text-sm font-medium text-white bg-gray-900 dark:bg-gray-700 rounded-lg shadow-lg whitespace-nowrap pointer-events-none opacity-0 transition-opacity duration-200 ${positionClasses[position]} ${className}`.trim()
26
+ export const arrowClass = `absolute w-0 h-0 border-4 border-transparent ${arrowClasses[position]}`.trim()
27
+
28
+ let isVisible = show
29
+ let timeoutId = null
30
+ </script>
31
+
32
+ <div class="relative inline-block {{ disabled ? 'cursor-not-allowed' : '' }}">
33
+ <!-- Trigger element (slot) -->
34
+ <div
35
+ onmouseenter="handleMouseEnter()"
36
+ onmouseleave="handleMouseLeave()"
37
+ onfocus="handleMouseEnter()"
38
+ onblur="handleMouseLeave()"
39
+ >
40
+ <slot />
41
+ </div>
42
+
43
+ <!-- Tooltip -->
44
+ @if(isVisible && !disabled)
45
+ <div
46
+ class="{{ tooltipClasses }}"
47
+ role="tooltip"
48
+ style="opacity: 1"
49
+ >
50
+ {{ content }}
51
+ <div class="{{ arrowClass }}"></div>
52
+ </div>
53
+ @endif
54
+ </div>
55
+
56
+ <script>
57
+ function handleMouseEnter() {
58
+ if (disabled) return
59
+
60
+ if (delay > 0) {
61
+ timeoutId = setTimeout(() => {
62
+ isVisible = true
63
+ }, delay)
64
+ } else {
65
+ isVisible = true
66
+ }
67
+ }
68
+
69
+ function handleMouseLeave() {
70
+ if (timeoutId) {
71
+ clearTimeout(timeoutId)
72
+ timeoutId = null
73
+ }
74
+ isVisible = false
75
+ }
76
+ </script>
@@ -0,0 +1,10 @@
1
+ export { default as Tooltip } from './Tooltip.stx'
2
+
3
+ export interface TooltipProps {
4
+ content: string
5
+ position?: 'top' | 'bottom' | 'left' | 'right'
6
+ delay?: number
7
+ show?: boolean
8
+ disabled?: boolean
9
+ className?: string
10
+ }
@@ -0,0 +1,30 @@
1
+ # Transition Component
2
+
3
+ Smooth enter/leave transitions for showing and hiding content.
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ bun add @stacksjs/components
9
+ ```
10
+
11
+ ## Usage
12
+
13
+ ```stx
14
+ <script>
15
+ export let isOpen = true
16
+ </script>
17
+
18
+ @component('Transition', { show: isOpen })
19
+ <div class="p-4 bg-white rounded-lg shadow-lg">
20
+ Content with fade transition
21
+ </div>
22
+ @endcomponent
23
+ ```
24
+
25
+ ## Features
26
+
27
+ - Enter/leave animations
28
+ - Customizable transition classes
29
+ - Dark mode support
30
+ - Headwind utility classes
@@ -0,0 +1,174 @@
1
+ <script>
2
+ export const show = $props.show !== false
3
+ export const enter = $props.enter || 'transition-opacity duration-300'
4
+ export const enterFrom = $props.enterFrom || 'opacity-0'
5
+ export const enterTo = $props.enterTo || 'opacity-100'
6
+ export const leave = $props.leave || 'transition-opacity duration-200'
7
+ export const leaveFrom = $props.leaveFrom || 'opacity-100'
8
+ export const leaveTo = $props.leaveTo || 'opacity-0'
9
+ export const appear = $props.appear || false
10
+ export const appearFrom = $props.appearFrom || enterFrom
11
+ export const appearTo = $props.appearTo || enterTo
12
+ export const mode = $props.mode || 'in-out' // 'in-out' | 'out-in' | 'default'
13
+ export const duration = $props.duration || 300
14
+ export const delay = $props.delay || 0
15
+ export const preset = $props.preset || ''
16
+ export const onBeforeEnter = $props.onBeforeEnter
17
+ export const onEnter = $props.onEnter
18
+ export const onAfterEnter = $props.onAfterEnter
19
+ export const onBeforeLeave = $props.onBeforeLeave
20
+ export const onLeave = $props.onLeave
21
+ export const onAfterLeave = $props.onAfterLeave
22
+ export const className = $props.className || ''
23
+
24
+ // Preset transitions
25
+ const presets = {
26
+ fade: {
27
+ enter: 'transition-opacity',
28
+ enterFrom: 'opacity-0',
29
+ enterTo: 'opacity-100',
30
+ leave: 'transition-opacity',
31
+ leaveFrom: 'opacity-100',
32
+ leaveTo: 'opacity-0',
33
+ },
34
+ slide: {
35
+ enter: 'transition-transform',
36
+ enterFrom: 'translate-y-2',
37
+ enterTo: 'translate-y-0',
38
+ leave: 'transition-transform',
39
+ leaveFrom: 'translate-y-0',
40
+ leaveTo: 'translate-y-2',
41
+ },
42
+ slideLeft: {
43
+ enter: 'transition-transform',
44
+ enterFrom: 'translate-x-full',
45
+ enterTo: 'translate-x-0',
46
+ leave: 'transition-transform',
47
+ leaveFrom: 'translate-x-0',
48
+ leaveTo: '-translate-x-full',
49
+ },
50
+ slideRight: {
51
+ enter: 'transition-transform',
52
+ enterFrom: '-translate-x-full',
53
+ enterTo: 'translate-x-0',
54
+ leave: 'transition-transform',
55
+ leaveFrom: 'translate-x-0',
56
+ leaveTo: 'translate-x-full',
57
+ },
58
+ scale: {
59
+ enter: 'transition-transform',
60
+ enterFrom: 'scale-95',
61
+ enterTo: 'scale-100',
62
+ leave: 'transition-transform',
63
+ leaveFrom: 'scale-100',
64
+ leaveTo: 'scale-95',
65
+ },
66
+ rotate: {
67
+ enter: 'transition-transform',
68
+ enterFrom: 'rotate-12 scale-95',
69
+ enterTo: 'rotate-0 scale-100',
70
+ leave: 'transition-transform',
71
+ leaveFrom: 'rotate-0 scale-100',
72
+ leaveTo: '-rotate-12 scale-95',
73
+ },
74
+ zoom: {
75
+ enter: 'transition-all',
76
+ enterFrom: 'scale-0 opacity-0',
77
+ enterTo: 'scale-100 opacity-100',
78
+ leave: 'transition-all',
79
+ leaveFrom: 'scale-100 opacity-100',
80
+ leaveTo: 'scale-0 opacity-0',
81
+ },
82
+ }
83
+
84
+ // Apply preset if specified
85
+ const presetTransition = preset && presets[preset] ? presets[preset] : {}
86
+ const finalEnter = presetTransition.enter || enter
87
+ const finalEnterFrom = presetTransition.enterFrom || enterFrom
88
+ const finalEnterTo = presetTransition.enterTo || enterTo
89
+ const finalLeave = presetTransition.leave || leave
90
+ const finalLeaveFrom = presetTransition.leaveFrom || leaveFrom
91
+ const finalLeaveTo = presetTransition.leaveTo || leaveTo
92
+
93
+ export let isEntering = false
94
+ export let isLeaving = false
95
+ export let shouldRender = show
96
+ export let hasAppeared = false
97
+
98
+ const transitionClasses = show
99
+ ? isEntering
100
+ ? `${finalEnter} ${finalEnterFrom}`
101
+ : `${finalEnterTo}`
102
+ : isLeaving
103
+ ? `${finalLeave} ${finalLeaveFrom}`
104
+ : `${finalLeaveTo}`
105
+
106
+ const componentClasses = `${transitionClasses} ${className}`.trim()
107
+ const durationStyle = `transition-duration: ${duration}ms; transition-delay: ${delay}ms;`
108
+ </script>
109
+
110
+ @if(shouldRender)
111
+ <div class="{{ componentClasses }}" style="{{ durationStyle }}">
112
+ <slot />
113
+ </div>
114
+ @endif
115
+
116
+ <script>
117
+ // Handle transitions with lifecycle callbacks
118
+ if (typeof window !== 'undefined') {
119
+ let previousShow = show
120
+
121
+ // Watch for show changes
122
+ function checkTransition() {
123
+ if (show !== previousShow) {
124
+ if (show && !shouldRender) {
125
+ // Entering
126
+ if (onBeforeEnter) onBeforeEnter()
127
+
128
+ shouldRender = true
129
+ isEntering = true
130
+
131
+ setTimeout(() => {
132
+ if (onEnter) onEnter()
133
+ }, delay)
134
+
135
+ setTimeout(() => {
136
+ isEntering = false
137
+ if (onAfterEnter) onAfterEnter()
138
+ }, duration + delay)
139
+
140
+ } else if (!show && shouldRender) {
141
+ // Leaving
142
+ if (onBeforeLeave) onBeforeLeave()
143
+
144
+ isLeaving = true
145
+
146
+ setTimeout(() => {
147
+ if (onLeave) onLeave()
148
+ }, delay)
149
+
150
+ setTimeout(() => {
151
+ isLeaving = false
152
+ shouldRender = false
153
+ if (onAfterLeave) onAfterLeave()
154
+ }, duration + delay)
155
+ }
156
+
157
+ previousShow = show
158
+ }
159
+
160
+ requestAnimationFrame(checkTransition)
161
+ }
162
+
163
+ requestAnimationFrame(checkTransition)
164
+
165
+ // Handle initial appear
166
+ if (appear && show && !hasAppeared) {
167
+ hasAppeared = true
168
+ isEntering = true
169
+ setTimeout(() => {
170
+ isEntering = false
171
+ }, duration + delay)
172
+ }
173
+ }
174
+ </script>
@@ -0,0 +1,25 @@
1
+ export { default as Transition } from './Transition.stx'
2
+
3
+ export interface TransitionProps {
4
+ show?: boolean
5
+ enter?: string
6
+ enterFrom?: string
7
+ enterTo?: string
8
+ leave?: string
9
+ leaveFrom?: string
10
+ leaveTo?: string
11
+ appear?: boolean
12
+ appearFrom?: string
13
+ appearTo?: string
14
+ mode?: 'in-out' | 'out-in' | 'default'
15
+ duration?: number
16
+ delay?: number
17
+ preset?: 'fade' | 'slide' | 'slideLeft' | 'slideRight' | 'scale' | 'rotate' | 'zoom' | ''
18
+ onBeforeEnter?: () => void
19
+ onEnter?: () => void
20
+ onAfterEnter?: () => void
21
+ onBeforeLeave?: () => void
22
+ onLeave?: () => void
23
+ onAfterLeave?: () => void
24
+ className?: string
25
+ }
@@ -0,0 +1,48 @@
1
+ # Video Component
2
+
3
+ A responsive video player with aspect ratio support and poster images.
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ bun add @stacksjs/components
9
+ ```
10
+
11
+ ## Usage
12
+
13
+ ```stx
14
+ @component('Video', {
15
+ src: '/videos/demo.mp4',
16
+ poster: '/images/video-thumbnail.jpg',
17
+ title: 'Product Demo',
18
+ aspectRatio: '16/9',
19
+ controls: true
20
+ })
21
+ @endcomponent
22
+ ```
23
+
24
+ ## Props
25
+
26
+ | Prop | Type | Default | Description |
27
+ |------|------|---------|-------------|
28
+ | `src` | `string` | - | Video file URL (required) |
29
+ | `poster` | `string` | `''` | Poster image URL |
30
+ | `autoplay` | `boolean` | `false` | Auto-play on load |
31
+ | `loop` | `boolean` | `false` | Loop playback |
32
+ | `muted` | `boolean` | `false` | Start muted |
33
+ | `controls` | `boolean` | `true` | Show native controls |
34
+ | `preload` | `'none' \| 'metadata' \| 'auto'` | `'metadata'` | Preload strategy |
35
+ | `width` | `number \| string` | - | Video width |
36
+ | `height` | `number \| string` | - | Video height |
37
+ | `aspectRatio` | `'16/9' \| '4/3' \| '1/1' \| string` | `'16/9'` | Aspect ratio |
38
+ | `className` | `string` | `''` | Additional CSS classes |
39
+ | `title` | `string` | `''` | Optional title above player |
40
+
41
+ ## Features
42
+
43
+ - **Aspect ratios** - 16:9, 4:3, 1:1 built-in
44
+ - **Poster images** - Show thumbnail before play
45
+ - **Native controls** - Uses browser's native video controls
46
+ - **Dark mode** - Styled for dark mode
47
+ - **Responsive** - Full-width with aspect ratio
48
+ - **Accessible** - Proper fallback text
@@ -0,0 +1,45 @@
1
+ <script>
2
+ export const src = $props.src || ''
3
+ export const poster = $props.poster || ''
4
+ export const autoplay = $props.autoplay || false
5
+ export const loop = $props.loop || false
6
+ export const muted = $props.muted || false
7
+ export const controls = $props.controls ?? true
8
+ export const preload = $props.preload || 'metadata'
9
+ export const width = $props.width
10
+ export const height = $props.height
11
+ export const aspectRatio = $props.aspectRatio || '16/9'
12
+ export const className = $props.className || ''
13
+ export const title = $props.title || ''
14
+
15
+ export const containerClasses = `relative w-full overflow-hidden rounded-lg ${className}`.trim()
16
+ export const videoClasses = 'w-full h-full object-cover bg-gray-900 dark:bg-gray-950'
17
+ export const aspectRatioClass = aspectRatio === '16/9' ? 'aspect-video' : aspectRatio === '4/3' ? 'aspect-[4/3]' : aspectRatio === '1/1' ? 'aspect-square' : ''
18
+ </script>
19
+
20
+ <div class="{{ containerClasses }}">
21
+ @if(title)
22
+ <div class="mb-2 px-1">
23
+ <h3 class="text-sm font-medium text-gray-900 dark:text-gray-100">
24
+ {{ title }}
25
+ </h3>
26
+ </div>
27
+ @endif
28
+
29
+ <div class="{{ aspectRatioClass }}">
30
+ <video
31
+ class="{{ videoClasses }}"
32
+ src="{{ src }}"
33
+ poster="{{ poster }}"
34
+ controls="{{ controls }}"
35
+ autoplay="{{ autoplay }}"
36
+ loop="{{ loop }}"
37
+ muted="{{ muted }}"
38
+ preload="{{ preload }}"
39
+ width="{{ width }}"
40
+ height="{{ height }}"
41
+ >
42
+ Your browser does not support the video element.
43
+ </video>
44
+ </div>
45
+ </div>
@@ -0,0 +1,16 @@
1
+ export { default as Video } from './Video.stx'
2
+
3
+ export interface VideoProps {
4
+ src: string
5
+ poster?: string
6
+ autoplay?: boolean
7
+ loop?: boolean
8
+ muted?: boolean
9
+ controls?: boolean
10
+ preload?: 'none' | 'metadata' | 'auto'
11
+ width?: number | string
12
+ height?: number | string
13
+ aspectRatio?: '16/9' | '4/3' | '1/1' | string
14
+ className?: string
15
+ title?: string
16
+ }
@@ -0,0 +1,83 @@
1
+ <script>
2
+ export const items = $props.items || []
3
+ export const itemHeight = $props.itemHeight || 50
4
+ export const height = $props.height || 400
5
+ export const overscan = $props.overscan || 3
6
+ export const renderItem = $props.renderItem
7
+ export const className = $props.className || ''
8
+
9
+ // Calculate visible range
10
+ let scrollTop = 0
11
+ const visibleCount = Math.ceil(height / itemHeight)
12
+ const totalHeight = items.length * itemHeight
13
+
14
+ // Calculate start and end indices with overscan
15
+ function getVisibleRange() {
16
+ const startIndex = Math.max(0, Math.floor(scrollTop / itemHeight) - overscan)
17
+ const endIndex = Math.min(items.length - 1, Math.floor((scrollTop + height) / itemHeight) + overscan)
18
+ return { startIndex, endIndex }
19
+ }
20
+
21
+ const { startIndex, endIndex } = getVisibleRange()
22
+ const visibleItems = items.slice(startIndex, endIndex + 1)
23
+ const offsetY = startIndex * itemHeight
24
+
25
+ // Handle scroll
26
+ function handleScroll(event) {
27
+ const target = event.target
28
+ scrollTop = target.scrollTop
29
+ }
30
+
31
+ export const containerClasses = `overflow-auto ${className}`.trim()
32
+ export const innerClasses = `relative`.trim()
33
+ export const itemClasses = `absolute left-0 right-0`.trim()
34
+ </script>
35
+
36
+ <div
37
+ class="{{ containerClasses }}"
38
+ style="height: {{ height }}px"
39
+ onscroll="handleScroll(event)"
40
+ >
41
+ <div
42
+ class="{{ innerClasses }}"
43
+ style="height: {{ totalHeight }}px"
44
+ >
45
+ @foreach(item in visibleItems)
46
+ <div
47
+ class="{{ itemClasses }}"
48
+ style="top: {{ (startIndex + $loop.index) * itemHeight }}px; height: {{ itemHeight }}px"
49
+ data-index="{{ startIndex + $loop.index }}"
50
+ >
51
+ @if(renderItem)
52
+ {!! renderItem(item, startIndex + $loop.index) !!}
53
+ @else
54
+ <slot item="{{ item }}" index="{{ startIndex + $loop.index }}" />
55
+ @endif
56
+ </div>
57
+ @endforeach
58
+ </div>
59
+ </div>
60
+
61
+ <script>
62
+ // Re-render on scroll (simplified reactivity)
63
+ if (typeof window !== 'undefined') {
64
+ let ticking = false
65
+
66
+ function updateVisibleItems() {
67
+ const range = getVisibleRange()
68
+ // Trigger re-render by updating visible range
69
+ // In a real implementation, this would update reactive state
70
+ ticking = false
71
+ }
72
+
73
+ const scrollContainer = document.querySelector('.overflow-auto')
74
+ if (scrollContainer) {
75
+ scrollContainer.addEventListener('scroll', () => {
76
+ if (!ticking) {
77
+ window.requestAnimationFrame(updateVisibleItems)
78
+ ticking = true
79
+ }
80
+ })
81
+ }
82
+ }
83
+ </script>
@@ -0,0 +1,10 @@
1
+ export { default as VirtualList } from './VirtualList.stx'
2
+
3
+ export interface VirtualListProps<T = any> {
4
+ items: T[]
5
+ itemHeight: number
6
+ height: number
7
+ overscan?: number
8
+ renderItem?: (item: T, index: number) => string
9
+ className?: string
10
+ }