@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,125 @@
1
+ <script>
2
+ export const headingText = $props.headingText || 'Two Factor Authentication'
3
+ export const labelText = $props.labelText || 'Authentication code'
4
+ export const instructionText = $props.instructionText || 'Open your Symantec 2FA app to view your authentication code.'
5
+ export const codeLength = $props.codeLength || 6
6
+ export const onSubmit = $props.onSubmit || (() => {})
7
+ export const onUseRecoveryCode = $props.onUseRecoveryCode
8
+ export const className = $props.className || ''
9
+
10
+ export const containerClasses = `py-32 dark:bg-blue-gray-900 ${className}`.trim()
11
+ export const codes = Array(codeLength).fill('')
12
+ </script>
13
+
14
+ <div class="{{ containerClasses }}">
15
+ <div class="mx-auto max-w-sm rounded-md px-8 py-4 shadow-md bg-white dark:bg-blue-gray-800">
16
+ <div class="card-body">
17
+ <div>
18
+ <h3 class="text-center text-sm text-gray-900 dark:text-gray-100 font-semibold">
19
+ {{ headingText }}
20
+ </h3>
21
+ <label for="code-0" class="mt-4 block text-sm text-gray-900 dark:text-gray-100 font-medium leading-6">
22
+ {{ labelText }}
23
+ </label>
24
+ <form onsubmit="event.preventDefault(); handleSubmit(event)">
25
+ <div class="mt-2 flex rounded-md shadow-sm space-x-2">
26
+ @for(i in Array(codeLength).keys())
27
+ <input
28
+ id="code-{{ i }}"
29
+ type="text"
30
+ maxlength="1"
31
+ name="code-{{ i }}"
32
+ placeholder="-"
33
+ class="block w-full border-0 rounded-md px-2 py-2 text-center text-gray-900 dark:text-gray-100 ring-1 ring-gray-300 dark:ring-gray-600 ring-inset sm:text-sm placeholder:text-gray-400 dark:placeholder:text-gray-500 sm:leading-6 focus:ring-2 focus:ring-indigo-600 focus:ring-inset dark:bg-blue-gray-700"
34
+ oninput="handleCodeInput(event, {{ i }})"
35
+ onkeydown="handleKeyDown(event, {{ i }})"
36
+ />
37
+ @endfor
38
+ </div>
39
+ <div class="py-4">
40
+ <button
41
+ type="submit"
42
+ class="relative h-8 w-full flex items-center justify-center rounded-full bg-teal-600 px-4 text-white font-semibold hover:bg-teal-500 focus:outline-none focus:ring-2 focus:ring-teal-600 focus:ring-offset-2"
43
+ >
44
+ Verify
45
+ </button>
46
+ </div>
47
+ </form>
48
+ <div>
49
+ <p class="text-xs text-gray-700 dark:text-gray-300 font-semibold">
50
+ {{ instructionText }}
51
+ </p>
52
+ </div>
53
+ @if(onUseRecoveryCode)
54
+ <div class="mt-4">
55
+ <p class="text-xs text-gray-700 dark:text-gray-300 font-semibold">
56
+ Having Problems?
57
+ </p>
58
+ <a
59
+ href="#"
60
+ onclick="event.preventDefault(); handleRecoveryCode()"
61
+ class="text-xs text-blue-500 hover:underline"
62
+ >
63
+ Use recovery code instead
64
+ </a>
65
+ </div>
66
+ @endif
67
+ </div>
68
+ </div>
69
+ </div>
70
+ </div>
71
+
72
+ <script>
73
+ function handleCodeInput(event, index) {
74
+ const input = event.target
75
+ const value = input.value
76
+
77
+ // Only allow digits
78
+ if (!/^\d*$/.test(value)) {
79
+ input.value = ''
80
+ return
81
+ }
82
+
83
+ // Auto-focus next input
84
+ if (value.length === 1 && index < codeLength - 1) {
85
+ const nextInput = document.getElementById(`code-${index + 1}`)
86
+ if (nextInput) {
87
+ nextInput.focus()
88
+ }
89
+ }
90
+ }
91
+
92
+ function handleKeyDown(event, index) {
93
+ // Handle backspace to move to previous input
94
+ if (event.key === 'Backspace' && !event.target.value && index > 0) {
95
+ const prevInput = document.getElementById(`code-${index - 1}`)
96
+ if (prevInput) {
97
+ prevInput.focus()
98
+ }
99
+ }
100
+ }
101
+
102
+ function handleSubmit(event) {
103
+ const code = []
104
+ for (let i = 0; i < codeLength; i++) {
105
+ const input = document.getElementById(`code-${i}`)
106
+ if (input && input.value) {
107
+ code.push(input.value)
108
+ }
109
+ }
110
+
111
+ if (code.length === codeLength) {
112
+ if (onSubmit) {
113
+ onSubmit(code.join(''))
114
+ }
115
+ } else {
116
+ alert('Please enter all digits')
117
+ }
118
+ }
119
+
120
+ function handleRecoveryCode() {
121
+ if (onUseRecoveryCode) {
122
+ onUseRecoveryCode()
123
+ }
124
+ }
125
+ </script>
@@ -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,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,113 @@
1
+ <script>
2
+ export const columns = $props.columns || []
3
+ export const data = $props.data || []
4
+ export const rowHeight = $props.rowHeight || 48
5
+ export const height = $props.height || 600
6
+ export const headerHeight = $props.headerHeight || 56
7
+ export const overscan = $props.overscan || 5
8
+ export const striped = $props.striped || false
9
+ export const hoverable = $props.hoverable ?? true
10
+ export const className = $props.className || ''
11
+
12
+ // Calculate visible range
13
+ let scrollTop = 0
14
+ const visibleCount = Math.ceil((height - headerHeight) / rowHeight)
15
+ const totalHeight = data.length * rowHeight
16
+
17
+ function getVisibleRange() {
18
+ const startIndex = Math.max(0, Math.floor(scrollTop / rowHeight) - overscan)
19
+ const endIndex = Math.min(data.length - 1, Math.floor((scrollTop + height - headerHeight) / rowHeight) + overscan)
20
+ return { startIndex, endIndex }
21
+ }
22
+
23
+ const { startIndex, endIndex } = getVisibleRange()
24
+ const visibleRows = data.slice(startIndex, endIndex + 1)
25
+ const offsetY = startIndex * rowHeight
26
+
27
+ function handleScroll(event) {
28
+ const target = event.target
29
+ scrollTop = target.scrollTop
30
+ }
31
+
32
+ // Get cell value
33
+ function getCellValue(row, column) {
34
+ if (column.render) {
35
+ return column.render(row[column.key], row)
36
+ }
37
+ return row[column.key]
38
+ }
39
+
40
+ export const containerClasses = `border border-gray-200 dark:border-gray-700 rounded-lg overflow-hidden ${className}`.trim()
41
+ export const headerClasses = `bg-gray-50 dark:bg-gray-800 border-b border-gray-200 dark:border-gray-700 flex`.trim()
42
+ export const headerCellClasses = `px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-400 uppercase tracking-wider`.trim()
43
+ export const bodyClasses = `overflow-auto bg-white dark:bg-gray-900`.trim()
44
+ export const innerClasses = `relative`.trim()
45
+ export const rowClasses = `absolute left-0 right-0 flex border-b border-gray-200 dark:border-gray-700 ${hoverable ? 'hover:bg-gray-50 dark:hover:bg-gray-800' : ''}`.trim()
46
+ export const cellClasses = `px-6 py-4 text-sm text-gray-900 dark:text-gray-100`.trim()
47
+ </script>
48
+
49
+ <div class="{{ containerClasses }}">
50
+ <!-- Header -->
51
+ <div class="{{ headerClasses }}" style="height: {{ headerHeight }}px">
52
+ @foreach(column in columns)
53
+ <div
54
+ class="{{ headerCellClasses }}"
55
+ style="flex: {{ column.width || 1 }}; min-width: {{ column.minWidth || 'auto' }}"
56
+ >
57
+ {{ column.label || column.key }}
58
+ </div>
59
+ @endforeach
60
+ </div>
61
+
62
+ <!-- Body -->
63
+ <div
64
+ class="{{ bodyClasses }}"
65
+ style="height: {{ height - headerHeight }}px"
66
+ onscroll="handleScroll(event)"
67
+ >
68
+ <div
69
+ class="{{ innerClasses }}"
70
+ style="height: {{ totalHeight }}px"
71
+ >
72
+ @foreach(row in visibleRows)
73
+ <div
74
+ class="{{ rowClasses }} {{ striped && ($loop.index % 2 === 1) ? 'bg-gray-50 dark:bg-gray-800' : '' }}"
75
+ style="top: {{ (startIndex + $loop.index) * rowHeight }}px; height: {{ rowHeight }}px"
76
+ data-index="{{ startIndex + $loop.index }}"
77
+ >
78
+ @foreach(column in columns)
79
+ <div
80
+ class="{{ cellClasses }}"
81
+ style="flex: {{ column.width || 1 }}; min-width: {{ column.minWidth || 'auto' }}"
82
+ >
83
+ {!! getCellValue(row, column) !!}
84
+ </div>
85
+ @endforeach
86
+ </div>
87
+ @endforeach
88
+ </div>
89
+ </div>
90
+ </div>
91
+
92
+ <script>
93
+ // Re-render on scroll (simplified reactivity)
94
+ if (typeof window !== 'undefined') {
95
+ let ticking = false
96
+
97
+ function updateVisibleRows() {
98
+ const range = getVisibleRange()
99
+ // Trigger re-render
100
+ ticking = false
101
+ }
102
+
103
+ const bodyContainer = document.querySelector('.overflow-auto')
104
+ if (bodyContainer) {
105
+ bodyContainer.addEventListener('scroll', () => {
106
+ if (!ticking) {
107
+ window.requestAnimationFrame(updateVisibleRows)
108
+ ticking = true
109
+ }
110
+ })
111
+ }
112
+ }
113
+ </script>
@@ -0,0 +1,4 @@
1
+ export { default as CodeBlock } from './CodeBlock.stx';
2
+ export { default as Footer } from './Footer.stx';
3
+ export { default as Hero } from './Hero.stx';
4
+ export { default as Installation } from './Installation.stx';
@@ -0,0 +1,4 @@
1
+ export * from './useCopyCode';
2
+ export * from './useDarkMode';
3
+ export * from './useSEO';
4
+ export * from './utilities';
@@ -0,0 +1,3 @@
1
+ // @bun
2
+ function I(j){let{code:x,onSuccess:O,onError:J,timeout:U=2000}=j,G=!1,Y=null;return{copied:G,copy:async()=>{try{if(!navigator.clipboard)throw Error("Clipboard API not available");await navigator.clipboard.writeText(x),G=!0,O?.(),Y=setTimeout(()=>{G=!1,Y=null},U)}catch(X){let z=X instanceof Error?X:Error("Failed to copy code");J?.(z),console.error("Failed to copy code:",z)}},reset:()=>{if(G=!1,Y)clearTimeout(Y),Y=null}}}async function R(j){try{return await navigator.clipboard.writeText(j),!0}catch(x){return console.error("Failed to copy to clipboard:",x),!1}}function Q(){if(typeof window>"u")return"light";return window.matchMedia("(prefers-color-scheme: dark)").matches?"dark":"light"}function A(j){return j==="system"?Q():j}function M(j={}){let{storageKey:x="theme",defaultTheme:O="system"}=j,J=O;if(typeof window<"u"&&typeof localStorage<"u"){let N=localStorage.getItem(x);if(N)J=N}let U=A(J)==="dark",G=(N)=>{let X=A(N);if(typeof document<"u")if(X==="dark")document.documentElement.classList.add("dark");else document.documentElement.classList.remove("dark");if(typeof localStorage<"u")localStorage.setItem(x,N)},Y=(N)=>{J=N,G(N)},Z=()=>{let X=A(J)==="dark"?"light":"dark";Y(X)};if(G(J),typeof window<"u"&&J==="system")window.matchMedia("(prefers-color-scheme: dark)").addEventListener("change",(N)=>{if(J==="system")G("system")});return{isDark:U,theme:J,toggle:Z,setTheme:Y}}function S(j,x){if(typeof document>"u")return;document.title=x?x.replace("%s",j):j}function D(j,x,O=!1){if(typeof document>"u")return;let J=O?"property":"name",U=document.querySelector(`meta[${J}="${j}"]`);if(!U)U=document.createElement("meta"),U.setAttribute(J,j),document.head.appendChild(U);U.setAttribute("content",x)}function C(j,x){if(typeof document>"u")return;let O=document.querySelector(`link[rel="${j}"]`);if(!O)O=document.createElement("link"),O.setAttribute("rel",j),document.head.appendChild(O);O.setAttribute("href",x)}function T(j){let{title:x,description:O,author:J,keywords:U,ogImage:G,ogImageWidth:Y,ogImageHeight:Z,twitterCard:N="summary_large_image",twitterSite:X,twitterCreator:z,canonical:_}=j;if(x)S(x),D("og:title",x,!0),D("twitter:title",x);if(O)D("description",O),D("og:description",O,!0),D("twitter:description",O);if(J)D("author",J);if(U&&U.length>0)D("keywords",U.join(", "));if(G)D("og:image",G,!0),D("twitter:image",G);if(Y)D("og:image:width",Y,!0);if(Z)D("og:image:height",Z,!0);if(D("twitter:card",N),X)D("twitter:site",X);if(z)D("twitter:creator",z);if(_)C("canonical",_);if(D("og:type","website",!0),typeof window<"u")D("og:url",window.location.href,!0)}function E(j){let x=[],{title:O,description:J,author:U,keywords:G,ogImage:Y,ogImageWidth:Z,ogImageHeight:N,twitterCard:X="summary_large_image",twitterSite:z,twitterCreator:_,canonical:q}=j;if(O)x.push(`<title>${P(O)}</title>`),x.push(`<meta property="og:title" content="${P(O)}" />`),x.push(`<meta name="twitter:title" content="${P(O)}" />`);if(J)x.push(`<meta name="description" content="${P(J)}" />`),x.push(`<meta property="og:description" content="${P(J)}" />`),x.push(`<meta name="twitter:description" content="${P(J)}" />`);if(U)x.push(`<meta name="author" content="${P(U)}" />`);if(G&&G.length>0)x.push(`<meta name="keywords" content="${P(G.join(", "))}" />`);if(Y)x.push(`<meta property="og:image" content="${P(Y)}" />`),x.push(`<meta name="twitter:image" content="${P(Y)}" />`);if(Z)x.push(`<meta property="og:image:width" content="${P(Z)}" />`);if(N)x.push(`<meta property="og:image:height" content="${P(N)}" />`);if(x.push(`<meta name="twitter:card" content="${P(X)}" />`),z)x.push(`<meta name="twitter:site" content="${P(z)}" />`);if(_)x.push(`<meta name="twitter:creator" content="${P(_)}" />`);if(q)x.push(`<link rel="canonical" href="${P(q)}" />`);return x.push('<meta property="og:type" content="website" />'),x.join(`
3
+ `)}function P(j){return j.replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;").replace(/"/g,"&quot;").replace(/'/g,"&#039;")}function w(j,x,O={}){let{enabled:J=!0,ignore:U=[]}=O,G=(Y)=>{if(!J||!j)return;let Z=Y.target;if(!j.contains(Z)){if(!U.some((X)=>{let z=document.querySelectorAll(X);return Array.from(z).some((_)=>_.contains(Z))}))x(Y)}};if(typeof document<"u")document.addEventListener("mousedown",G),document.addEventListener("touchstart",G);return()=>{if(typeof document<"u")document.removeEventListener("mousedown",G),document.removeEventListener("touchstart",G)}}function f(j,x={}){let{enabled:O=!0,initialFocus:J=null,returnFocus:U=!0,fallbackFocus:G=null}=x,Y=null,Z=!1;function N(){if(!j)return[];let $=["a[href]","button:not([disabled])","textarea:not([disabled])","input:not([disabled])","select:not([disabled])",'[tabindex]:not([tabindex="-1"])'].join(",");return Array.from(j.querySelectorAll($))}function X($){if(!O||!Z||!j)return;let K=N();if(K.length===0){$.preventDefault();return}let F=K[0],L=K[K.length-1];if($.shiftKey){if(document.activeElement===F||document.activeElement===j)$.preventDefault(),L.focus()}else if(document.activeElement===L)$.preventDefault(),F.focus()}function z($){if($.key==="Escape"&&O&&Z)q()}function _(){if(!O||!j||Z)return;if(Y=document.activeElement,J)J.focus();else{let $=N();if($.length>0)$[0].focus();else if(G)G.focus();else j.focus()}document.addEventListener("keydown",X),document.addEventListener("keydown",z),Z=!0}function q(){if(!Z)return;if(document.removeEventListener("keydown",X),document.removeEventListener("keydown",z),U&&Y)Y.focus();Z=!1}return{activate:_,deactivate:q}}function v(j,x={}){let{enabled:O=!0,preventDefault:J=!0,stopPropagation:U=!1,target:G=typeof document<"u"?document:null}=x,Y=Array.isArray(j)?j:[j],Z=(N)=>{if(!O)return;Y.forEach((X)=>{if(!(Array.isArray(X.key)?X.key:[X.key]).some((q)=>q.toLowerCase()===N.key.toLowerCase()))return;if(X.ctrl!==void 0&&X.ctrl!==N.ctrlKey)return;if(X.shift!==void 0&&X.shift!==N.shiftKey)return;if(X.alt!==void 0&&X.alt!==N.altKey)return;if(X.meta!==void 0&&X.meta!==N.metaKey)return;if(J)N.preventDefault();if(U)N.stopPropagation();X.handler(N)})};if(G)G.addEventListener("keydown",Z);return()=>{if(G)G.removeEventListener("keydown",Z)}}var g={ESCAPE:"Escape",ENTER:"Enter",SPACE:" ",TAB:"Tab",ARROW_UP:"ArrowUp",ARROW_DOWN:"ArrowDown",ARROW_LEFT:"ArrowLeft",ARROW_RIGHT:"ArrowRight",HOME:"Home",END:"End",PAGE_UP:"PageUp",PAGE_DOWN:"PageDown"};function u(j,x,O={}){let{serializer:J=JSON.stringify,deserializer:U=JSON.parse,onError:G=console.error}=O,Y=x;try{if(typeof window<"u"){let _=window.localStorage.getItem(j);if(_!==null)Y=U(_)}}catch(_){G(_)}let Z=Y,N=new Set;function X(_){try{let q=typeof _==="function"?_(Z):_;if(Z=q,typeof window<"u")window.localStorage.setItem(j,J(q));N.forEach(($)=>$(q))}catch(q){G(q)}}function z(){try{if(Z=x,typeof window<"u")window.localStorage.removeItem(j);N.forEach((_)=>_(x))}catch(_){G(_)}}if(typeof window<"u"){let _=(q)=>{if(q.key===j&&q.newValue!==null)try{let $=U(q.newValue);Z=$,N.forEach((K)=>K($))}catch($){G($)}else if(q.key===j&&q.newValue===null)Z=x,N.forEach(($)=>$(x))};window.addEventListener("storage",_)}return{value:Z,setValue:X,removeValue:z}}function W(j,x={}){let{defaultValue:O=!1}=x,J=O,U=null;if(typeof window<"u"&&"matchMedia"in window){U=window.matchMedia(j),J=U.matches;let Y=(Z)=>{J=Z.matches};if(U.addEventListener)U.addEventListener("change",Y);else U.addListener(Y)}function G(){if(U)J=U.matches}return{matches:J,updateMatches:G}}var B={xs:"(min-width: 320px)",sm:"(min-width: 640px)",md:"(min-width: 768px)",lg:"(min-width: 1024px)",xl:"(min-width: 1280px)","2xl":"(min-width: 1536px)",mobile:"(max-width: 767px)",tablet:"(min-width: 768px) and (max-width: 1023px)",desktop:"(min-width: 1024px)",dark:"(prefers-color-scheme: dark)",light:"(prefers-color-scheme: light)",reducedMotion:"(prefers-reduced-motion: reduce)",portrait:"(orientation: portrait)",landscape:"(orientation: landscape)"};function d(j){return W(B[j])}function m(){return W(B.mobile)}function c(){return W(B.desktop)}function o(){return W(B.dark)}function l(){return W(B.reducedMotion)}export{T as useSEO,l as usePrefersReducedMotion,W as useMediaQuery,u as useLocalStorage,v as useKeyboard,m as useIsMobile,c as useIsDesktop,o as useIsDarkMode,f as useFocusTrap,M as useDarkMode,I as useCopyCode,w as useClickOutside,d as useBreakpoint,S as setTitle,D as setMeta,C as setLink,Q as getSystemTheme,A as getEffectiveTheme,E as generateSEOTags,R as copyToClipboard,g as KeyboardShortcuts,B as Breakpoints};
@@ -0,0 +1,19 @@
1
+ export declare function useCopyCode(options: CopyCodeOptions): CopyCodeResult;
2
+ /**
3
+ * Simple synchronous copy function for direct use
4
+ */
5
+ export declare function copyToClipboard(text: string): Promise<boolean>;
6
+ /**
7
+ * Copy code to clipboard with visual feedback
8
+ */
9
+ export declare interface CopyCodeOptions {
10
+ code: string
11
+ onSuccess?: () => void
12
+ onError?: (error: Error) => void
13
+ timeout?: number
14
+ }
15
+ export declare interface CopyCodeResult {
16
+ copied: boolean
17
+ copy: () => Promise<void>
18
+ reset: () => void
19
+ }
@@ -0,0 +1,25 @@
1
+ /**
2
+ * Check if system prefers dark mode
3
+ */
4
+ export declare function getSystemTheme(): 'light' | 'dark';
5
+ /**
6
+ * Get the effective theme (resolving 'system' to actual theme)
7
+ */
8
+ export declare function getEffectiveTheme(theme: 'light' | 'dark' | 'system'): 'light' | 'dark';
9
+ /**
10
+ * Use dark mode hook
11
+ */
12
+ export declare function useDarkMode(options?: DarkModeOptions): DarkModeResult;
13
+ /**
14
+ * Dark mode utilities for STX components
15
+ */
16
+ export declare interface DarkModeOptions {
17
+ storageKey?: string
18
+ defaultTheme?: 'light' | 'dark' | 'system'
19
+ }
20
+ export declare interface DarkModeResult {
21
+ isDark: boolean
22
+ theme: 'light' | 'dark' | 'system'
23
+ toggle: () => void
24
+ setTheme: (theme: 'light' | 'dark' | 'system') => void
25
+ }
@@ -0,0 +1,36 @@
1
+ /**
2
+ * Set document title
3
+ */
4
+ export declare function setTitle(title: string, template?: string): void;
5
+ /**
6
+ * Set meta tag
7
+ */
8
+ export declare function setMeta(name: string, content: string, isProperty?: any): void;
9
+ /**
10
+ * Set link tag
11
+ */
12
+ export declare function setLink(rel: string, href: string): void;
13
+ /**
14
+ * Use SEO meta tags
15
+ */
16
+ export declare function useSEO(options: SEOMetaOptions): void;
17
+ /**
18
+ * Generate SEO meta tags as HTML string for server-side rendering
19
+ */
20
+ export declare function generateSEOTags(options: SEOMetaOptions): string;
21
+ /**
22
+ * SEO and meta tag utilities for STX components
23
+ */
24
+ export declare interface SEOMetaOptions {
25
+ title?: string
26
+ description?: string
27
+ author?: string
28
+ keywords?: string[]
29
+ ogImage?: string
30
+ ogImageWidth?: string
31
+ ogImageHeight?: string
32
+ twitterCard?: 'summary' | 'summary_large_image' | 'app' | 'player'
33
+ twitterSite?: string
34
+ twitterCreator?: string
35
+ canonical?: string
36
+ }
@@ -0,0 +1,5 @@
1
+ export * from './useClickOutside';
2
+ export * from './useFocusTrap';
3
+ export * from './useKeyboard';
4
+ export * from './useLocalStorage';
5
+ export * from './useMediaQuery';
@@ -0,0 +1,28 @@
1
+ /**
2
+ * Hook to detect clicks outside an element
3
+ *
4
+ * @param elementRef - The element to detect clicks outside of
5
+ * @param callback - Function to call when click occurs outside element
6
+ * @param options - Configuration options
7
+ * @returns Cleanup function to remove event listeners
8
+ */
9
+ export declare function useClickOutside(elementRef: HTMLElement | null, callback: (event: MouseEvent | TouchEvent) => void, options?: UseClickOutsideOptions): () => void;
10
+ /**
11
+ * Detects clicks outside a specified element
12
+ *
13
+ * @example
14
+ * ```ts
15
+ * const cleanup = useClickOutside(
16
+ * modalRef,
17
+ * () => closeModal(),
18
+ * { enabled: isOpen, ignore: ['.tooltip'] }
19
+ * )
20
+ * ```
21
+ */
22
+ /**
23
+ * Options for useClickOutside hook
24
+ */
25
+ export declare interface UseClickOutsideOptions {
26
+ enabled?: boolean
27
+ ignore?: string[]
28
+ }
@@ -0,0 +1,34 @@
1
+ /**
2
+ * Hook to trap focus within an element
3
+ *
4
+ * @param containerRef - The container element to trap focus within
5
+ * @param options - Configuration options
6
+ * @returns Object with activate and deactivate functions
7
+ */
8
+ export declare function useFocusTrap(containerRef: HTMLElement | null, options?: UseFocusTrapOptions): { activate: () => void, deactivate: () => void };
9
+ /**
10
+ * Traps focus within a container element (useful for modals, dialogs, dropdowns)
11
+ *
12
+ * @example
13
+ * ```ts
14
+ * const { activate, deactivate } = useFocusTrap(modalRef, {
15
+ * initialFocus: firstInputRef,
16
+ * returnFocus: true
17
+ * })
18
+ *
19
+ * // When modal opens
20
+ * activate()
21
+ *
22
+ * // When modal closes
23
+ * deactivate()
24
+ * ```
25
+ */
26
+ /**
27
+ * Options for useFocusTrap hook
28
+ */
29
+ export declare interface UseFocusTrapOptions {
30
+ enabled?: boolean
31
+ initialFocus?: HTMLElement | null
32
+ returnFocus?: boolean
33
+ fallbackFocus?: HTMLElement | null
34
+ }
@@ -0,0 +1,55 @@
1
+ /**
2
+ * Hook for keyboard event handling
3
+ *
4
+ * @param handlers - Single handler or array of keyboard handlers
5
+ * @param options - Configuration options
6
+ * @returns Cleanup function to remove event listeners
7
+ */
8
+ export declare function useKeyboard(handlers: KeyboardHandler | KeyboardHandler[], options?: UseKeyboardOptions): () => void;
9
+ // Common keyboard shortcuts
10
+ export declare const KeyboardShortcuts: {
11
+ ESCAPE: 'Escape';
12
+ ENTER: 'Enter';
13
+ SPACE: ' ';
14
+ TAB: 'Tab';
15
+ ARROW_UP: 'ArrowUp';
16
+ ARROW_DOWN: 'ArrowDown';
17
+ ARROW_LEFT: 'ArrowLeft';
18
+ ARROW_RIGHT: 'ArrowRight';
19
+ HOME: 'Home';
20
+ END: 'End';
21
+ PAGE_UP: 'PageUp';
22
+ PAGE_DOWN: 'PageDown'
23
+ };
24
+ /**
25
+ * Hook for keyboard event handling with support for shortcuts and modifiers
26
+ *
27
+ * @example
28
+ * ```ts
29
+ * useKeyboard([
30
+ * { key: 'Escape', handler: () => closeModal() },
31
+ * { key: 's', ctrl: true, handler: () => save() },
32
+ * { key: ['ArrowUp', 'ArrowDown'], handler: (e) => navigate(e.key) }
33
+ * ])
34
+ * ```
35
+ */
36
+ /**
37
+ * Options for useKeyboard hook
38
+ */
39
+ export declare interface UseKeyboardOptions {
40
+ enabled?: boolean
41
+ preventDefault?: boolean
42
+ stopPropagation?: boolean
43
+ target?: HTMLElement | Document | Window | null
44
+ }
45
+ /**
46
+ * Keyboard event handler configuration
47
+ */
48
+ export declare interface KeyboardHandler {
49
+ key: string | string[]
50
+ handler: (event: KeyboardEvent) => void
51
+ ctrl?: boolean
52
+ shift?: boolean
53
+ alt?: boolean
54
+ meta?: boolean
55
+ }
@@ -0,0 +1,33 @@
1
+ /**
2
+ * Hook for reactive localStorage with cross-tab sync
3
+ *
4
+ * @param key - Storage key
5
+ * @param initialValue - Initial value if key doesn't exist
6
+ * @param options - Configuration options
7
+ * @returns Object with value, setValue, and removeValue
8
+ */
9
+ export declare function useLocalStorage<T>(key: string, initialValue: T, options?: UseLocalStorageOptions<T>): {
10
+ value: T
11
+ setValue: (newValue: T | ((prev: T) => T)) => void
12
+ removeValue: () => void
13
+ };
14
+ /**
15
+ * Reactive localStorage hook with cross-tab synchronization
16
+ *
17
+ * @example
18
+ * ```ts
19
+ * const { value, setValue, removeValue } = useLocalStorage('user', { name: 'John' })
20
+ *
21
+ * setValue({ name: 'Jane' })
22
+ * setValue(prev => ({ ...prev, age: 30 }))
23
+ * removeValue()
24
+ * ```
25
+ */
26
+ /**
27
+ * Options for useLocalStorage hook
28
+ */
29
+ export declare interface UseLocalStorageOptions<T> {
30
+ serializer?: (value: T) => string
31
+ deserializer?: (value: string) => T
32
+ onError?: (error: Error) => void
33
+ }