@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,155 @@
1
+ <script>
2
+ export const value = $props.value || ''
3
+ export const onChange = $props.onChange || (() => {})
4
+ export const placeholder = $props.placeholder || 'Enter your password'
5
+ export const disabled = $props.disabled || false
6
+ export const readonly = $props.readonly || false
7
+ export const size = $props.size || 'md'
8
+ export const error = $props.error || false
9
+ export const label = $props.label || ''
10
+ export const helperText = $props.helperText || ''
11
+ export const required = $props.required || false
12
+ export const showStrength = $props.showStrength || false
13
+ export const className = $props.className || ''
14
+ export const inputClassName = $props.inputClassName || ''
15
+
16
+ // State
17
+ let showPassword = false
18
+
19
+ // Size classes
20
+ const sizeClasses = {
21
+ sm: 'px-3 py-1.5 text-sm h-8',
22
+ md: 'px-4 py-2 text-base h-10',
23
+ lg: 'px-5 py-3 text-lg h-12',
24
+ }
25
+
26
+ // Icon size classes
27
+ const iconSizeClasses = {
28
+ sm: 'h-4 w-4',
29
+ md: 'h-5 w-5',
30
+ lg: 'h-6 w-6',
31
+ }
32
+
33
+ // Base and state classes
34
+ 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 dark:bg-blue-gray-700 dark:text-gray-100 pr-10'
35
+
36
+ const stateClasses = error
37
+ ? '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'
38
+ : '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'
39
+
40
+ const disabledClasses = disabled
41
+ ? 'opacity-50 cursor-not-allowed bg-gray-50 dark:bg-gray-800'
42
+ : readonly
43
+ ? 'bg-gray-50 dark:bg-gray-800 cursor-default'
44
+ : 'bg-white dark:bg-blue-gray-700'
45
+
46
+ export const inputClasses = `${baseClasses} ${sizeClasses[size]} ${stateClasses} ${disabledClasses} ${inputClassName}`.trim()
47
+ 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()
48
+ export const helperClasses = `mt-2 text-sm ${error ? 'text-red-600 dark:text-red-400' : 'text-gray-500 dark:text-gray-400'}`.trim()
49
+ export const iconClasses = iconSizeClasses[size]
50
+
51
+ // Password strength calculation
52
+ function calculateStrength(password) {
53
+ if (!password) return 0
54
+ let strength = 0
55
+ if (password.length >= 8) strength += 25
56
+ if (password.length >= 12) strength += 25
57
+ if (/[a-z]/.test(password) && /[A-Z]/.test(password)) strength += 25
58
+ if (/\d/.test(password)) strength += 15
59
+ if (/[^a-zA-Z\d]/.test(password)) strength += 10
60
+ return Math.min(strength, 100)
61
+ }
62
+
63
+ export const strength = calculateStrength(value)
64
+ export const strengthColor = strength < 40 ? 'bg-red-500' : strength < 70 ? 'bg-yellow-500' : 'bg-green-500'
65
+ export const strengthText = strength < 40 ? 'Weak' : strength < 70 ? 'Medium' : 'Strong'
66
+ </script>
67
+
68
+ <div class="w-full {{ className }}">
69
+ @if(label)
70
+ <label for="password-input" class="{{ labelClasses }}">
71
+ {{ label }}
72
+ @if(required)
73
+ <span class="text-red-500 ml-1">*</span>
74
+ @endif
75
+ </label>
76
+ @endif
77
+
78
+ <div class="relative">
79
+ <input
80
+ type="{{ showPassword ? 'text' : 'password' }}"
81
+ id="password-input"
82
+ class="{{ inputClasses }}"
83
+ value="{{ value }}"
84
+ placeholder="{{ placeholder }}"
85
+ disabled="{{ disabled }}"
86
+ readonly="{{ readonly }}"
87
+ required="{{ required }}"
88
+ oninput="handleInput(event)"
89
+ aria-invalid="{{ error ? 'true' : 'false' }}"
90
+ @if(helperText)aria-describedby="helper-text"@endif
91
+ />
92
+
93
+ <!-- Toggle visibility button -->
94
+ <div class="absolute inset-y-0 right-0 flex items-center pr-3">
95
+ <button
96
+ type="button"
97
+ onclick="toggleVisibility()"
98
+ class="text-gray-400 hover:text-gray-600 dark:text-gray-500 dark:hover:text-gray-300 focus:outline-none"
99
+ aria-label="{{ showPassword ? 'Hide password' : 'Show password' }}"
100
+ >
101
+ @if(showPassword)
102
+ <!-- Eye slash icon (hide) -->
103
+ <svg class="{{ iconClasses }}" fill="none" viewBox="0 0 24 24" stroke="currentColor">
104
+ <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M13.875 18.825A10.05 10.05 0 0112 19c-4.478 0-8.268-2.943-9.543-7a9.97 9.97 0 011.563-3.029m5.858.908a3 3 0 114.243 4.243M9.878 9.878l4.242 4.242M9.88 9.88l-3.29-3.29m7.532 7.532l3.29 3.29M3 3l3.59 3.59m0 0A9.953 9.953 0 0112 5c4.478 0 8.268 2.943 9.543 7a10.025 10.025 0 01-4.132 5.411m0 0L21 21" />
105
+ </svg>
106
+ @else
107
+ <!-- Eye icon (show) -->
108
+ <svg class="{{ iconClasses }}" fill="none" viewBox="0 0 24 24" stroke="currentColor">
109
+ <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15 12a3 3 0 11-6 0 3 3 0 016 0z" />
110
+ <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M2.458 12C3.732 7.943 7.523 5 12 5c4.478 0 8.268 2.943 9.542 7-1.274 4.057-5.064 7-9.542 7-4.477 0-8.268-2.943-9.542-7z" />
111
+ </svg>
112
+ @endif
113
+ </button>
114
+ </div>
115
+ </div>
116
+
117
+ @if(showStrength && value.length > 0)
118
+ <!-- Password strength indicator -->
119
+ <div class="mt-2">
120
+ <div class="flex items-center justify-between mb-1">
121
+ <span class="text-xs text-gray-600 dark:text-gray-400">Password strength</span>
122
+ <span class="text-xs font-medium {{ strength < 40 ? 'text-red-600' : strength < 70 ? 'text-yellow-600' : 'text-green-600' }}">
123
+ {{ strengthText }}
124
+ </span>
125
+ </div>
126
+ <div class="w-full h-1.5 bg-gray-200 dark:bg-gray-700 rounded-full overflow-hidden">
127
+ <div
128
+ class="{{ strengthColor }} h-full transition-all duration-300 rounded-full"
129
+ style="width: {{ strength }}%"
130
+ ></div>
131
+ </div>
132
+ </div>
133
+ @endif
134
+
135
+ @if(helperText)
136
+ <p id="helper-text" class="{{ helperClasses }}">
137
+ {{ helperText }}
138
+ </p>
139
+ @endif
140
+ </div>
141
+
142
+ <script>
143
+ function handleInput(event) {
144
+ const newValue = event.target.value
145
+
146
+ if (onChange) {
147
+ onChange(newValue)
148
+ }
149
+ }
150
+
151
+ function toggleVisibility() {
152
+ showPassword = !showPassword
153
+ // Re-render would be handled by the framework
154
+ }
155
+ </script>
@@ -0,0 +1,63 @@
1
+ <script>
2
+ export const value = $props.value || ''
3
+ export const onChange = $props.onChange || (() => {})
4
+ export const onSearch = $props.onSearch || (() => {})
5
+ export const placeholder = $props.placeholder || 'Search...'
6
+ export const disabled = $props.disabled || false
7
+ export const size = $props.size || 'md'
8
+ export const error = $props.error || false
9
+ export const label = $props.label || ''
10
+ export const helperText = $props.helperText || ''
11
+ export const loading = $props.loading || false
12
+ export const className = $props.className || ''
13
+
14
+ // Search icon SVG
15
+ const searchIcon = '<svg fill="none" viewBox="0 0 24 24" stroke="currentColor"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z" /></svg>'
16
+
17
+ // Loading spinner SVG
18
+ const spinnerIcon = '<svg class="animate-spin" fill="none" viewBox="0 0 24 24"><circle class="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" stroke-width="4"></circle><path class="opacity-75" fill="currentColor" d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"></path></svg>'
19
+
20
+ export const rightIcon = loading ? spinnerIcon : undefined
21
+ </script>
22
+
23
+ @component('TextInput', {
24
+ value,
25
+ onChange,
26
+ placeholder,
27
+ disabled,
28
+ size,
29
+ error,
30
+ label,
31
+ helperText,
32
+ leftIcon: searchIcon,
33
+ rightIcon,
34
+ clearable: !loading,
35
+ className,
36
+ inputClassName: 'pr-20'
37
+ })
38
+ @endcomponent
39
+
40
+ <script>
41
+ // Debounce search to avoid excessive calls
42
+ let searchTimeout = null
43
+
44
+ function handleSearchInput(newValue) {
45
+ if (onChange) {
46
+ onChange(newValue)
47
+ }
48
+
49
+ // Debounce the onSearch callback
50
+ if (searchTimeout) {
51
+ clearTimeout(searchTimeout)
52
+ }
53
+
54
+ searchTimeout = setTimeout(() => {
55
+ if (onSearch) {
56
+ onSearch(newValue)
57
+ }
58
+ }, 300) // 300ms debounce
59
+ }
60
+
61
+ // Expose enhanced onChange handler
62
+ export const enhancedOnChange = handleSearchInput
63
+ </script>
@@ -0,0 +1,146 @@
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 size = $props.size || 'md'
8
+ export const error = $props.error || false
9
+ export const label = $props.label || ''
10
+ export const helperText = $props.helperText || ''
11
+ export const required = $props.required || false
12
+ export const leftIcon = $props.leftIcon || ''
13
+ export const rightIcon = $props.rightIcon || ''
14
+ export const clearable = $props.clearable || false
15
+ export const maxLength = $props.maxLength
16
+ export const showCount = $props.showCount || false
17
+ export const className = $props.className || ''
18
+ export const inputClassName = $props.inputClassName || ''
19
+
20
+ // Size classes
21
+ const sizeClasses = {
22
+ sm: 'px-3 py-1.5 text-sm h-8',
23
+ md: 'px-4 py-2 text-base h-10',
24
+ lg: 'px-5 py-3 text-lg h-12',
25
+ }
26
+
27
+ // Icon size classes
28
+ const iconSizeClasses = {
29
+ sm: 'h-4 w-4',
30
+ md: 'h-5 w-5',
31
+ lg: 'h-6 w-6',
32
+ }
33
+
34
+ // Base and state classes
35
+ 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 dark:bg-blue-gray-700 dark:text-gray-100'
36
+
37
+ const stateClasses = error
38
+ ? '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'
39
+ : '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'
40
+
41
+ const disabledClasses = disabled
42
+ ? 'opacity-50 cursor-not-allowed bg-gray-50 dark:bg-gray-800'
43
+ : readonly
44
+ ? 'bg-gray-50 dark:bg-gray-800 cursor-default'
45
+ : 'bg-white dark:bg-blue-gray-700'
46
+
47
+ const paddingClasses = leftIcon ? 'pl-10' : rightIcon || clearable ? 'pr-10' : ''
48
+
49
+ export const inputClasses = `${baseClasses} ${sizeClasses[size]} ${stateClasses} ${disabledClasses} ${paddingClasses} ${inputClassName}`.trim()
50
+ 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()
51
+ export const helperClasses = `mt-2 text-sm ${error ? 'text-red-600 dark:text-red-400' : 'text-gray-500 dark:text-gray-400'}`.trim()
52
+ export const iconClasses = iconSizeClasses[size]
53
+ export const hasValue = value && value.length > 0
54
+ </script>
55
+
56
+ <div class="w-full {{ className }}">
57
+ @if(label)
58
+ <label for="input-{{ label }}" class="{{ labelClasses }}">
59
+ {{ label }}
60
+ @if(required)
61
+ <span class="text-red-500 ml-1">*</span>
62
+ @endif
63
+ </label>
64
+ @endif
65
+
66
+ <div class="relative">
67
+ @if(leftIcon)
68
+ <!-- Left icon -->
69
+ <div class="pointer-events-none absolute inset-y-0 left-0 flex items-center pl-3">
70
+ <span class="{{ iconClasses }} text-gray-400 dark:text-gray-500" innerHTML="{!! leftIcon !!}"></span>
71
+ </div>
72
+ @endif
73
+
74
+ <input
75
+ type="text"
76
+ id="input-{{ label }}"
77
+ class="{{ inputClasses }}"
78
+ value="{{ value }}"
79
+ placeholder="{{ placeholder }}"
80
+ disabled="{{ disabled }}"
81
+ readonly="{{ readonly }}"
82
+ required="{{ required }}"
83
+ @if(maxLength)maxlength="{{ maxLength }}"@endif
84
+ oninput="handleInput(event)"
85
+ aria-invalid="{{ error ? 'true' : 'false' }}"
86
+ @if(helperText)aria-describedby="helper-text"@endif
87
+ />
88
+
89
+ @if(clearable && hasValue && !disabled && !readonly)
90
+ <!-- Clear button -->
91
+ <div class="absolute inset-y-0 right-0 flex items-center pr-3">
92
+ <button
93
+ type="button"
94
+ onclick="handleClear()"
95
+ class="text-gray-400 hover:text-gray-600 dark:text-gray-500 dark:hover:text-gray-300 focus:outline-none"
96
+ aria-label="Clear input"
97
+ >
98
+ <svg class="{{ iconClasses }}" fill="none" viewBox="0 0 24 24" stroke="currentColor">
99
+ <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 18L18 6M6 6l12 12" />
100
+ </svg>
101
+ </button>
102
+ </div>
103
+ @else
104
+ @if(rightIcon && !clearable)
105
+ <!-- Right icon -->
106
+ <div class="pointer-events-none absolute inset-y-0 right-0 flex items-center pr-3">
107
+ <span class="{{ iconClasses }} text-gray-400 dark:text-gray-500" innerHTML="{!! rightIcon !!}"></span>
108
+ </div>
109
+ @endif
110
+ @endif
111
+ </div>
112
+
113
+ @if(helperText || (showCount && maxLength))
114
+ <div class="flex items-center justify-between mt-2">
115
+ @if(helperText)
116
+ <p id="helper-text" class="{{ helperClasses }}">
117
+ {{ helperText }}
118
+ </p>
119
+ @else
120
+ <span></span>
121
+ @endif
122
+
123
+ @if(showCount && maxLength)
124
+ <p class="text-sm text-gray-500 dark:text-gray-400">
125
+ {{ value.length }} / {{ maxLength }}
126
+ </p>
127
+ @endif
128
+ </div>
129
+ @endif
130
+ </div>
131
+
132
+ <script>
133
+ function handleInput(event) {
134
+ const newValue = event.target.value
135
+
136
+ if (onChange) {
137
+ onChange(newValue)
138
+ }
139
+ }
140
+
141
+ function handleClear() {
142
+ if (onChange) {
143
+ onChange('')
144
+ }
145
+ }
146
+ </script>
@@ -0,0 +1,180 @@
1
+ import type { PropSchema, ValidationResult } from '../../utils/prop-validation'
2
+ import { createPropValidator, PropTypes } from '../../utils/prop-validation'
3
+
4
+ export { default as EmailInput } from './EmailInput.stx'
5
+ export { default as NumberInput } from './NumberInput.stx'
6
+ export { default as PasswordInput } from './PasswordInput.stx'
7
+ export { default as SearchInput } from './SearchInput.stx'
8
+ export { default as TextInput } from './TextInput.stx'
9
+
10
+ export interface BaseInputProps {
11
+ value?: string
12
+ onChange?: (value: string) => void
13
+ placeholder?: string
14
+ disabled?: boolean
15
+ readonly?: boolean
16
+ size?: 'sm' | 'md' | 'lg'
17
+ error?: boolean
18
+ label?: string
19
+ helperText?: string
20
+ required?: boolean
21
+ className?: string
22
+ inputClassName?: string
23
+ }
24
+
25
+ export interface TextInputProps extends BaseInputProps {
26
+ leftIcon?: string
27
+ rightIcon?: string
28
+ clearable?: boolean
29
+ maxLength?: number
30
+ showCount?: boolean
31
+ }
32
+
33
+ export interface EmailInputProps extends Omit<BaseInputProps, 'placeholder'> {
34
+ placeholder?: string
35
+ }
36
+
37
+ export interface PasswordInputProps extends Omit<BaseInputProps, 'placeholder'> {
38
+ placeholder?: string
39
+ showStrength?: boolean
40
+ }
41
+
42
+ export interface NumberInputProps extends BaseInputProps {
43
+ min?: number
44
+ max?: number
45
+ step?: number
46
+ showControls?: boolean
47
+ }
48
+
49
+ export interface SearchInputProps extends Omit<BaseInputProps, 'placeholder'> {
50
+ placeholder?: string
51
+ onSearch?: (value: string) => void
52
+ loading?: boolean
53
+ }
54
+
55
+ /**
56
+ * Base input prop validation schema
57
+ */
58
+ const baseInputPropSchema: PropSchema = {
59
+ value: PropTypes.string,
60
+ onChange: PropTypes.func,
61
+ placeholder: PropTypes.string,
62
+ disabled: PropTypes.boolean,
63
+ readonly: PropTypes.boolean,
64
+ size: PropTypes.oneOf(['sm', 'md', 'lg']),
65
+ error: PropTypes.boolean,
66
+ label: PropTypes.string,
67
+ helperText: PropTypes.string,
68
+ required: PropTypes.boolean,
69
+ className: PropTypes.string,
70
+ inputClassName: PropTypes.string,
71
+ }
72
+
73
+ /**
74
+ * TextInput prop validation schema
75
+ */
76
+ export const textInputPropSchema: PropSchema = {
77
+ value: PropTypes.string,
78
+ onChange: PropTypes.func,
79
+ placeholder: PropTypes.string,
80
+ disabled: PropTypes.boolean,
81
+ readonly: PropTypes.boolean,
82
+ size: PropTypes.oneOf(['sm', 'md', 'lg']),
83
+ error: PropTypes.boolean,
84
+ label: PropTypes.string,
85
+ helperText: PropTypes.string,
86
+ required: PropTypes.boolean,
87
+ className: PropTypes.string,
88
+ inputClassName: PropTypes.string,
89
+ leftIcon: PropTypes.string,
90
+ rightIcon: PropTypes.string,
91
+ clearable: PropTypes.boolean,
92
+ maxLength: PropTypes.number,
93
+ showCount: PropTypes.boolean,
94
+ }
95
+
96
+ /**
97
+ * NumberInput prop validation schema
98
+ */
99
+ export const numberInputPropSchema: PropSchema = {
100
+ value: PropTypes.string,
101
+ onChange: PropTypes.func,
102
+ placeholder: PropTypes.string,
103
+ disabled: PropTypes.boolean,
104
+ readonly: PropTypes.boolean,
105
+ size: PropTypes.oneOf(['sm', 'md', 'lg']),
106
+ error: PropTypes.boolean,
107
+ label: PropTypes.string,
108
+ helperText: PropTypes.string,
109
+ required: PropTypes.boolean,
110
+ className: PropTypes.string,
111
+ inputClassName: PropTypes.string,
112
+ min: PropTypes.number,
113
+ max: PropTypes.number,
114
+ step: PropTypes.number,
115
+ showControls: PropTypes.boolean,
116
+ }
117
+
118
+ /**
119
+ * PasswordInput prop validation schema
120
+ */
121
+ const passwordInputPropSchema: PropSchema = {
122
+ value: PropTypes.string,
123
+ onChange: PropTypes.func,
124
+ placeholder: PropTypes.string,
125
+ disabled: PropTypes.boolean,
126
+ readonly: PropTypes.boolean,
127
+ size: PropTypes.oneOf(['sm', 'md', 'lg']),
128
+ error: PropTypes.boolean,
129
+ label: PropTypes.string,
130
+ helperText: PropTypes.string,
131
+ required: PropTypes.boolean,
132
+ className: PropTypes.string,
133
+ inputClassName: PropTypes.string,
134
+ showStrength: PropTypes.boolean,
135
+ }
136
+
137
+ /**
138
+ * SearchInput prop validation schema
139
+ */
140
+ const searchInputPropSchema: PropSchema = {
141
+ value: PropTypes.string,
142
+ onChange: PropTypes.func,
143
+ placeholder: PropTypes.string,
144
+ disabled: PropTypes.boolean,
145
+ readonly: PropTypes.boolean,
146
+ size: PropTypes.oneOf(['sm', 'md', 'lg']),
147
+ error: PropTypes.boolean,
148
+ label: PropTypes.string,
149
+ helperText: PropTypes.string,
150
+ required: PropTypes.boolean,
151
+ className: PropTypes.string,
152
+ inputClassName: PropTypes.string,
153
+ onSearch: PropTypes.func,
154
+ loading: PropTypes.boolean,
155
+ }
156
+
157
+ /**
158
+ * Validate TextInput component props
159
+ */
160
+ export const validateTextInputProps: (props: Record<string, any>) => ValidationResult = createPropValidator('TextInput', textInputPropSchema)
161
+
162
+ /**
163
+ * Validate EmailInput component props
164
+ */
165
+ export const validateEmailInputProps: (props: Record<string, any>) => ValidationResult = createPropValidator('EmailInput', baseInputPropSchema)
166
+
167
+ /**
168
+ * Validate PasswordInput component props
169
+ */
170
+ export const validatePasswordInputProps: (props: Record<string, any>) => ValidationResult = createPropValidator('PasswordInput', passwordInputPropSchema)
171
+
172
+ /**
173
+ * Validate NumberInput component props
174
+ */
175
+ export const validateNumberInputProps: (props: Record<string, any>) => ValidationResult = createPropValidator('NumberInput', numberInputPropSchema)
176
+
177
+ /**
178
+ * Validate SearchInput component props
179
+ */
180
+ export const validateSearchInputProps: (props: Record<string, any>) => ValidationResult = createPropValidator('SearchInput', searchInputPropSchema)
@@ -0,0 +1,14 @@
1
+ <script>
2
+ export const value = $props.value
3
+ export const onChange = $props.onChange
4
+ export const multiple = $props.multiple || false
5
+ export const className = $props.className || ''
6
+ export const as = $props.as || 'div'
7
+
8
+ const baseClasses = 'relative'
9
+ const listboxClasses = `${baseClasses} ${className}`.trim()
10
+ </script>
11
+
12
+ <component :is="{{ as }}" class="{{ listboxClasses }}">
13
+ <slot :value="value" :onChange="onChange" :multiple="multiple" />
14
+ </component>
@@ -0,0 +1,17 @@
1
+ <script>
2
+ export const className = $props.className || ''
3
+ export const as = $props.as || 'button'
4
+ export const disabled = $props.disabled || false
5
+
6
+ const baseClasses = 'relative w-full cursor-pointer rounded-lg bg-white dark:bg-neutral-800 py-2 pl-3 pr-10 text-left shadow-md focus:outline-none focus-visible:border-blue-500 focus-visible:ring-2 focus-visible:ring-white focus-visible:ring-opacity-75 focus-visible:ring-offset-2 focus-visible:ring-offset-blue-300'
7
+ const disabledClasses = disabled ? 'opacity-50 cursor-not-allowed' : ''
8
+ const buttonClasses = `${baseClasses} ${disabledClasses} ${className}`.trim()
9
+ </script>
10
+
11
+ <component
12
+ :is="{{ as }}"
13
+ class="{{ buttonClasses }}"
14
+ @if(disabled)disabled aria-disabled="true"@endif
15
+ >
16
+ <slot />
17
+ </component>
@@ -0,0 +1,11 @@
1
+ <script>
2
+ export const className = $props.className || ''
3
+ export const as = $props.as || 'label'
4
+
5
+ const baseClasses = 'block text-sm font-medium text-neutral-900 dark:text-white'
6
+ const labelClasses = `${baseClasses} ${className}`.trim()
7
+ </script>
8
+
9
+ <component :is="{{ as }}" class="{{ labelClasses }}">
10
+ <slot />
11
+ </component>
@@ -0,0 +1,57 @@
1
+ <script>
2
+ export const value = $props.value
3
+ export const disabled = $props.disabled || false
4
+ export const className = $props.className || ''
5
+ export const as = $props.as || 'li'
6
+ export const currentValue = $props.currentValue
7
+ export const onChange = $props.onChange
8
+
9
+ export let active = false
10
+ export const selected = Array.isArray(currentValue)
11
+ ? currentValue.includes(value)
12
+ : currentValue === value
13
+
14
+ const baseClasses = 'relative cursor-pointer select-none py-2 pl-10 pr-4'
15
+ const stateClasses = active
16
+ ? 'bg-blue-100 text-blue-900 dark:bg-blue-900 dark:text-blue-100'
17
+ : 'text-neutral-900 dark:text-neutral-100'
18
+ const disabledClasses = disabled
19
+ ? 'opacity-50 cursor-not-allowed'
20
+ : ''
21
+
22
+ const optionClasses = `${baseClasses} ${stateClasses} ${disabledClasses} ${className}`.trim()
23
+
24
+ export function handleClick() {
25
+ if (disabled) return
26
+ onChange?.(value)
27
+ }
28
+
29
+ export function handleMouseEnter() {
30
+ if (!disabled) active = true
31
+ }
32
+
33
+ export function handleMouseLeave() {
34
+ active = false
35
+ }
36
+ </script>
37
+
38
+ <component
39
+ :is="{{ as }}"
40
+ class="{{ optionClasses }}"
41
+ role="option"
42
+ aria-selected="{{ selected ? 'true' : 'false' }}"
43
+ @if(disabled)aria-disabled="true"@endif
44
+ @click="handleClick"
45
+ @mouseenter="handleMouseEnter"
46
+ @mouseleave="handleMouseLeave"
47
+ >
48
+ @if(selected)
49
+ <span class="absolute inset-y-0 left-0 flex items-center pl-3 text-blue-600 dark:text-blue-400">
50
+ <svg class="h-5 w-5" viewBox="0 0 20 20" fill="currentColor">
51
+ <path fill-rule="evenodd" d="M16.707 5.293a1 1 0 010 1.414l-8 8a1 1 0 01-1.414 0l-4-4a1 1 0 011.414-1.414L8 12.586l7.293-7.293a1 1 0 011.414 0z" clip-rule="evenodd" />
52
+ </svg>
53
+ </span>
54
+ @endif
55
+
56
+ <slot :active="active" :selected="selected" :disabled="disabled" />
57
+ </component>
@@ -0,0 +1,16 @@
1
+ <script>
2
+ export const className = $props.className || ''
3
+ export const as = $props.as || 'ul'
4
+ export const static_ = $props.static || false
5
+
6
+ const baseClasses = 'absolute z-10 mt-1 max-h-60 w-full overflow-auto rounded-md bg-white dark:bg-neutral-800 py-1 text-base shadow-lg ring-1 ring-black ring-opacity-5 focus:outline-none'
7
+ const optionsClasses = `${baseClasses} ${className}`.trim()
8
+ </script>
9
+
10
+ <component
11
+ :is="{{ as }}"
12
+ class="{{ optionsClasses }}"
13
+ role="listbox"
14
+ >
15
+ <slot />
16
+ </component>