@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,71 @@
1
+ <script>
2
+ export const show = $props.show !== false
3
+ export const title = $props.title || ''
4
+ export const message = $props.message || ''
5
+ export const type = $props.type || 'info'
6
+ export const position = $props.position || 'top-right'
7
+ export const duration = $props.duration || 5000
8
+ export const onClose = $props.onClose
9
+ export const className = $props.className || ''
10
+
11
+ const typeColors = {
12
+ info: 'bg-blue-50 text-blue-900 dark:bg-blue-900 dark:text-blue-100',
13
+ success: 'bg-green-50 text-green-900 dark:bg-green-900 dark:text-green-100',
14
+ warning: 'bg-yellow-50 text-yellow-900 dark:bg-yellow-900 dark:text-yellow-100',
15
+ error: 'bg-red-50 text-red-900 dark:bg-red-900 dark:text-red-100',
16
+ }
17
+
18
+ const positions = {
19
+ 'top-left': 'top-0 left-0',
20
+ 'top-right': 'top-0 right-0',
21
+ 'top-center': 'top-0 left-1/2 -translate-x-1/2',
22
+ 'bottom-left': 'bottom-0 left-0',
23
+ 'bottom-right': 'bottom-0 right-0',
24
+ 'bottom-center': 'bottom-0 left-1/2 -translate-x-1/2',
25
+ }
26
+
27
+ const baseClasses = 'fixed z-50 m-4 max-w-md w-full pointer-events-auto rounded-lg p-4 shadow-lg ring-1 ring-black ring-opacity-5 transition-all'
28
+ const notificationClasses = `${baseClasses} ${typeColors[type]} ${positions[position]} ${className}`.trim()
29
+
30
+ export function handleClose() {
31
+ onClose?.()
32
+ }
33
+ </script>
34
+
35
+ @if(show)
36
+ <div class="{{ notificationClasses }}" role="alert">
37
+ <div class="flex items-start">
38
+ <div class="flex-1">
39
+ @if(title)
40
+ <p class="text-sm font-medium">{{ title }}</p>
41
+ @endif
42
+ @if(message)
43
+ <p class="mt-1 text-sm {{ title ? 'opacity-90' : '' }}">{{ message }}</p>
44
+ @endif
45
+ @if(!title && !message)
46
+ <slot />
47
+ @endif
48
+ </div>
49
+
50
+ <button
51
+ type="button"
52
+ @click="handleClose"
53
+ class="ml-4 inline-flex rounded-md focus:outline-none focus:ring-2 focus:ring-offset-2"
54
+ >
55
+ <span class="sr-only">Close</span>
56
+ <svg class="h-5 w-5" viewBox="0 0 20 20" fill="currentColor">
57
+ <path fill-rule="evenodd" d="M4.293 4.293a1 1 0 011.414 0L10 8.586l4.293-4.293a1 1 0 111.414 1.414L11.414 10l4.293 4.293a1 1 0 01-1.414 1.414L10 11.414l-4.293 4.293a1 1 0 01-1.414-1.414L8.586 10 4.293 5.707a1 1 0 010-1.414z" clip-rule="evenodd" />
58
+ </svg>
59
+ </button>
60
+ </div>
61
+ </div>
62
+
63
+ <script>
64
+ // Auto-hide after duration (client-side only)
65
+ if (typeof window !== 'undefined' && duration > 0) {
66
+ setTimeout(() => {
67
+ handleClose()
68
+ }, duration)
69
+ }
70
+ </script>
71
+ @endif
@@ -0,0 +1,118 @@
1
+ # Notification Component
2
+
3
+ Toast notifications for user feedback and alerts.
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ bun add @stacksjs/components
9
+ ```
10
+
11
+ ## Usage
12
+
13
+ ```stx
14
+ <script>
15
+ export let showNotification = true
16
+
17
+ export function closeNotification() {
18
+ showNotification = false
19
+ }
20
+ </script>
21
+
22
+ @component('Notification', {
23
+ show: showNotification,
24
+ title: 'Success!',
25
+ message: 'Your changes have been saved.',
26
+ type: 'success',
27
+ onClose: closeNotification
28
+ })
29
+ ```
30
+
31
+ ## Props
32
+
33
+ | Prop | Type | Default | Description |
34
+ |------|------|---------|-------------|
35
+ | `show` | `boolean` | `true` | Whether notification is visible |
36
+ | `title` | `string` | `''` | Notification title |
37
+ | `message` | `string` | `''` | Notification message |
38
+ | `type` | `'info' \| 'success' \| 'warning' \| 'error'` | `'info'` | Notification type |
39
+ | `position` | `'top-left' \| 'top-right' \| 'top-center' \| 'bottom-left' \| 'bottom-right' \| 'bottom-center'` | `'top-right'` | Position on screen |
40
+ | `duration` | `number` | `5000` | Auto-hide duration (0 = no auto-hide) |
41
+ | `onClose` | `() => void` | - | Close handler |
42
+ | `className` | `string` | `''` | Additional CSS classes |
43
+
44
+ ## Examples
45
+
46
+ ### Types
47
+
48
+ ```stx
49
+ @component('Notification', { type: 'info', title: 'Information', message: 'This is an info message' })
50
+
51
+ @component('Notification', { type: 'success', title: 'Success', message: 'Operation completed' })
52
+
53
+ @component('Notification', { type: 'warning', title: 'Warning', message: 'Please be careful' })
54
+
55
+ @component('Notification', { type: 'error', title: 'Error', message: 'Something went wrong' })
56
+ ```
57
+
58
+ ### Positions
59
+
60
+ ```stx
61
+ @component('Notification', { position: 'top-left', title: 'Top Left' })
62
+ @component('Notification', { position: 'top-center', title: 'Top Center' })
63
+ @component('Notification', { position: 'bottom-right', title: 'Bottom Right' })
64
+ ```
65
+
66
+ ### No Auto-Hide
67
+
68
+ ```stx
69
+ @component('Notification', {
70
+ duration: 0,
71
+ title: 'Important',
72
+ message: 'This will not auto-hide'
73
+ })
74
+ ```
75
+
76
+ ### Custom Content
77
+
78
+ ```stx
79
+ @component('Notification', { type: 'info' })
80
+ <div class="flex items-start gap-3">
81
+ <svg class="w-6 h-6" fill="none" stroke="currentColor" viewBox="0 0 24 24">
82
+ <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M13 16h-1v-4h-1m1-4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z" />
83
+ </svg>
84
+ <div>
85
+ <p class="font-medium">Custom notification</p>
86
+ <p class="mt-1 text-sm">With custom content and layout</p>
87
+ </div>
88
+ </div>
89
+ @endcomponent
90
+ ```
91
+
92
+ ### With Actions
93
+
94
+ ```stx
95
+ @component('Notification', { type: 'info', title: 'New message' })
96
+ <p>You have a new message from John</p>
97
+ <div class="mt-3 flex gap-2">
98
+ @component('Button', { size: 'sm', variant: 'primary' })
99
+ View
100
+ @endcomponent
101
+ @component('Button', { size: 'sm', variant: 'ghost' })
102
+ Dismiss
103
+ @endcomponent
104
+ </div>
105
+ @endcomponent
106
+ ```
107
+
108
+ ## Features
109
+
110
+ - 4 types (info, success, warning, error)
111
+ - 6 position options
112
+ - Auto-hide with configurable duration
113
+ - Dark mode support
114
+ - Accessible (WAI-ARIA)
115
+ - Close button
116
+ - Custom content support
117
+ - Smooth transitions
118
+ - Customizable styling
@@ -0,0 +1,12 @@
1
+ export { default as Notification } from './Notification.stx'
2
+
3
+ export interface NotificationProps {
4
+ show?: boolean
5
+ title?: string
6
+ message?: string
7
+ type?: 'info' | 'success' | 'warning' | 'error'
8
+ position?: 'top-left' | 'top-right' | 'top-center' | 'bottom-left' | 'bottom-right' | 'bottom-center'
9
+ duration?: number
10
+ onClose?: () => void
11
+ className?: string
12
+ }
@@ -0,0 +1,183 @@
1
+ <script>
2
+ export const currentPage = $props.currentPage || 1
3
+ export const totalPages = $props.totalPages || 1
4
+ export const siblingCount = $props.siblingCount || 1
5
+ export const showFirstLast = $props.showFirstLast ?? true
6
+ export const showPrevNext = $props.showPrevNext ?? true
7
+ export const className = $props.className || ''
8
+ export const onChange = $props.onChange
9
+
10
+ // Generate page numbers to display
11
+ function generatePageNumbers() {
12
+ const pages = []
13
+ const totalNumbers = siblingCount * 2 + 3 // siblings on each side + current + first + last
14
+ const totalBlocks = totalNumbers + 2 // + 2 for ellipsis
15
+
16
+ if (totalPages <= totalBlocks) {
17
+ // Show all pages
18
+ for (let i = 1; i <= totalPages; i++) {
19
+ pages.push(i)
20
+ }
21
+ } else {
22
+ const leftSiblingIndex = Math.max(currentPage - siblingCount, 1)
23
+ const rightSiblingIndex = Math.min(currentPage + siblingCount, totalPages)
24
+
25
+ const showLeftEllipsis = leftSiblingIndex > 2
26
+ const showRightEllipsis = rightSiblingIndex < totalPages - 1
27
+
28
+ if (!showLeftEllipsis && showRightEllipsis) {
29
+ // Show left pages + ellipsis + last
30
+ const leftCount = 3 + 2 * siblingCount
31
+ for (let i = 1; i <= leftCount; i++) {
32
+ pages.push(i)
33
+ }
34
+ pages.push('ellipsis-right')
35
+ pages.push(totalPages)
36
+ } else if (showLeftEllipsis && !showRightEllipsis) {
37
+ // Show first + ellipsis + right pages
38
+ pages.push(1)
39
+ pages.push('ellipsis-left')
40
+ const rightCount = 3 + 2 * siblingCount
41
+ for (let i = totalPages - rightCount + 1; i <= totalPages; i++) {
42
+ pages.push(i)
43
+ }
44
+ } else {
45
+ // Show first + ellipsis + middle + ellipsis + last
46
+ pages.push(1)
47
+ pages.push('ellipsis-left')
48
+ for (let i = leftSiblingIndex; i <= rightSiblingIndex; i++) {
49
+ pages.push(i)
50
+ }
51
+ pages.push('ellipsis-right')
52
+ pages.push(totalPages)
53
+ }
54
+ }
55
+
56
+ return pages
57
+ }
58
+
59
+ const pageNumbers = generatePageNumbers()
60
+
61
+ function goToPage(page) {
62
+ if (page >= 1 && page <= totalPages && page !== currentPage) {
63
+ if (onChange) {
64
+ onChange(page)
65
+ }
66
+ }
67
+ }
68
+
69
+ function goToPrevious() {
70
+ goToPage(currentPage - 1)
71
+ }
72
+
73
+ function goToNext() {
74
+ goToPage(currentPage + 1)
75
+ }
76
+
77
+ function goToFirst() {
78
+ goToPage(1)
79
+ }
80
+
81
+ function goToLast() {
82
+ goToPage(totalPages)
83
+ }
84
+
85
+ export const paginationClasses = `flex items-center gap-1 ${className}`.trim()
86
+ export const buttonClasses = `px-3 py-2 text-sm font-medium text-gray-700 dark:text-gray-300 bg-white dark:bg-gray-800 border border-gray-300 dark:border-gray-600 rounded-md hover:bg-gray-50 dark:hover:bg-gray-700 focus:outline-none focus:ring-2 focus:ring-blue-500 focus:ring-offset-2 dark:focus:ring-offset-gray-900 disabled:opacity-50 disabled:cursor-not-allowed disabled:hover:bg-white dark:disabled:hover:bg-gray-800 transition-colors duration-150`.trim()
87
+ export const activeButtonClasses = `px-3 py-2 text-sm font-medium text-white bg-blue-600 dark:bg-blue-500 border border-blue-600 dark:border-blue-500 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 focus:ring-offset-2 dark:focus:ring-offset-gray-900`.trim()
88
+ export const ellipsisClasses = `px-3 py-2 text-sm font-medium text-gray-400 dark:text-gray-600`.trim()
89
+ export const iconClasses = `w-5 h-5`.trim()
90
+ </script>
91
+
92
+ <nav class="{{ paginationClasses }}" role="navigation" aria-label="Pagination">
93
+ <!-- First page button -->
94
+ @if(showFirstLast)
95
+ <button
96
+ type="button"
97
+ onclick="goToFirst()"
98
+ class="{{ buttonClasses }}"
99
+ aria-label="Go to first page"
100
+ disabled="{{ currentPage === 1 }}"
101
+ >
102
+ <svg class="{{ iconClasses }}" fill="none" viewBox="0 0 24 24" stroke="currentColor">
103
+ <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M11 19l-7-7 7-7m8 14l-7-7 7-7" />
104
+ </svg>
105
+ </button>
106
+ @endif
107
+
108
+ <!-- Previous button -->
109
+ @if(showPrevNext)
110
+ <button
111
+ type="button"
112
+ onclick="goToPrevious()"
113
+ class="{{ buttonClasses }}"
114
+ aria-label="Go to previous page"
115
+ disabled="{{ currentPage === 1 }}"
116
+ >
117
+ <svg class="{{ iconClasses }}" fill="none" viewBox="0 0 24 24" stroke="currentColor">
118
+ <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15 19l-7-7 7-7" />
119
+ </svg>
120
+ </button>
121
+ @endif
122
+
123
+ <!-- Page numbers -->
124
+ @foreach(page in pageNumbers)
125
+ @if(typeof page === 'string')
126
+ <!-- Ellipsis -->
127
+ <span class="{{ ellipsisClasses }}" aria-hidden="true">...</span>
128
+ @else
129
+ @if(page === currentPage)
130
+ <!-- Current page -->
131
+ <button
132
+ type="button"
133
+ class="{{ activeButtonClasses }}"
134
+ aria-label="Page {{ page }}"
135
+ aria-current="page"
136
+ disabled
137
+ >
138
+ {{ page }}
139
+ </button>
140
+ @else
141
+ <!-- Other pages -->
142
+ <button
143
+ type="button"
144
+ onclick="goToPage({{ page }})"
145
+ class="{{ buttonClasses }}"
146
+ aria-label="Go to page {{ page }}"
147
+ >
148
+ {{ page }}
149
+ </button>
150
+ @endif
151
+ @endif
152
+ @endforeach
153
+
154
+ <!-- Next button -->
155
+ @if(showPrevNext)
156
+ <button
157
+ type="button"
158
+ onclick="goToNext()"
159
+ class="{{ buttonClasses }}"
160
+ aria-label="Go to next page"
161
+ disabled="{{ currentPage === totalPages }}"
162
+ >
163
+ <svg class="{{ iconClasses }}" fill="none" viewBox="0 0 24 24" stroke="currentColor">
164
+ <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 5l7 7-7 7" />
165
+ </svg>
166
+ </button>
167
+ @endif
168
+
169
+ <!-- Last page button -->
170
+ @if(showFirstLast)
171
+ <button
172
+ type="button"
173
+ onclick="goToLast()"
174
+ class="{{ buttonClasses }}"
175
+ aria-label="Go to last page"
176
+ disabled="{{ currentPage === totalPages }}"
177
+ >
178
+ <svg class="{{ iconClasses }}" fill="none" viewBox="0 0 24 24" stroke="currentColor">
179
+ <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M13 5l7 7-7 7M5 5l7 7-7 7" />
180
+ </svg>
181
+ </button>
182
+ @endif
183
+ </nav>
@@ -0,0 +1,11 @@
1
+ export { default as Pagination } from './Pagination.stx'
2
+
3
+ export interface PaginationProps {
4
+ currentPage: number
5
+ totalPages: number
6
+ siblingCount?: number
7
+ showFirstLast?: boolean
8
+ showPrevNext?: boolean
9
+ onChange?: (page: number) => void
10
+ className?: string
11
+ }
@@ -0,0 +1,39 @@
1
+ <script>
2
+ export const products = $props.products || []
3
+ export const redirectUrl = $props.redirectUrl || ''
4
+ export const mode = $props.mode || 'subscription'
5
+ export const stripePublicKey = $props.stripePublicKey || ''
6
+ export const apiUrl = $props.apiUrl || ''
7
+ export const onSubmit = $props.onSubmit
8
+ export const onRemoveProduct = $props.onRemoveProduct
9
+ export const shipping = $props.shipping || 0
10
+ export const taxes = $props.taxes || 0
11
+ export const className = $props.className || ''
12
+
13
+ // For future expansion - one-time payment support
14
+ export const isSubscription = mode === 'subscription'
15
+ export const isOneTime = mode === 'one-time'
16
+ </script>
17
+
18
+ @if(isSubscription)
19
+ @component('SubscriptionCheckout', {
20
+ products,
21
+ stripePublicKey,
22
+ apiUrl,
23
+ onSubmit,
24
+ onRemoveProduct,
25
+ shipping,
26
+ taxes,
27
+ className
28
+ })
29
+ @endcomponent
30
+ @endif
31
+
32
+ @if(isOneTime)
33
+ <!-- One-time payment component can be implemented here in the future -->
34
+ <div class="p-8 text-center">
35
+ <p class="text-gray-600 dark:text-gray-400">
36
+ One-time payment mode is not yet implemented.
37
+ </p>
38
+ </div>
39
+ @endif
@@ -0,0 +1,62 @@
1
+ <script>
2
+ export const paymentMethod = $props.paymentMethod
3
+ export const isLoading = $props.isLoading || false
4
+ export const className = $props.className || ''
5
+
6
+ const brandIcons = {
7
+ visa: '💳',
8
+ mastercard: '💳',
9
+ amex: '💳',
10
+ discover: '💳',
11
+ default: '💳',
12
+ }
13
+
14
+ export const containerClasses = `mt-16 w-2/3 bg-white dark:bg-blue-gray-800 px-8 py-6 shadow ring-1 ring-black dark:ring-gray-700 ring-opacity-5 sm:rounded-lg ${className}`.trim()
15
+ </script>
16
+
17
+ <div class="{{ containerClasses }}">
18
+ <h2 class="text-lg text-gray-900 dark:text-gray-100 font-medium">
19
+ Payment Info
20
+ </h2>
21
+
22
+ @if(isLoading)
23
+ <!-- Loading skeleton -->
24
+ <div class="mt-8 animate-pulse">
25
+ <div class="h-20 bg-gray-200 dark:bg-gray-700 rounded-lg"></div>
26
+ </div>
27
+ @else
28
+ @if(paymentMethod)
29
+ <div class="col-span-1 mt-8 border border-gray-200 dark:border-gray-700 rounded-lg bg-white dark:bg-blue-gray-800 shadow divide-y divide-gray-200 dark:divide-gray-700">
30
+ <div class="w-full p-3">
31
+ <div class="flex items-center justify-between">
32
+ <div class="flex items-center space-x-4">
33
+ <!-- Card Brand Icon -->
34
+ <div class="flex-shrink-0 h-10 w-10 flex items-center justify-center bg-gray-100 dark:bg-gray-700 rounded-md">
35
+ <span class="text-2xl">{{ brandIcons[paymentMethod.brand.toLowerCase()] || brandIcons.default }}</span>
36
+ </div>
37
+
38
+ <!-- Card Details -->
39
+ <div>
40
+ <h2 class="text-sm text-gray-600 dark:text-gray-300">
41
+ {{ paymentMethod.brand }} •••• {{ paymentMethod.last_four }}
42
+ <span class="ml-4 inline-flex items-center rounded-md bg-indigo-50 dark:bg-indigo-900/30 px-2 py-1 text-xs text-indigo-700 dark:text-indigo-300 font-medium ring-1 ring-indigo-700/10 dark:ring-indigo-300/20 ring-inset">Default</span>
43
+ <br>
44
+ <span class="text-xs text-gray-500 dark:text-gray-400 italic">Expires {{ paymentMethod.exp_month }} / {{ paymentMethod.exp_year }}</span>
45
+ </h2>
46
+ </div>
47
+ </div>
48
+ </div>
49
+ </div>
50
+ </div>
51
+ @else
52
+ <!-- Empty state -->
53
+ <div class="col-span-1 mt-8 border border-gray-200 dark:border-gray-700 rounded-lg bg-white dark:bg-blue-gray-800 shadow divide-y divide-gray-200 dark:divide-gray-700">
54
+ <div class="w-full px-4 py-5">
55
+ <h2 class="text-center text-sm text-gray-600 dark:text-gray-300">
56
+ You haven't added any payment methods yet.
57
+ </h2>
58
+ </div>
59
+ </div>
60
+ @endif
61
+ @endif
62
+ </div>
@@ -0,0 +1,113 @@
1
+ <script>
2
+ export const paymentMethods = $props.paymentMethods || []
3
+ export const onDeletePaymentMethod = $props.onDeletePaymentMethod
4
+ export const onMakeDefault = $props.onMakeDefault
5
+ export const isLoading = $props.isLoading || false
6
+ export const className = $props.className || ''
7
+
8
+ // Card brand icon mapping
9
+ const brandIcons = {
10
+ visa: '💳',
11
+ mastercard: '💳',
12
+ amex: '💳',
13
+ discover: '💳',
14
+ default: '💳',
15
+ }
16
+
17
+ export const containerClasses = `mt-4 ${className}`.trim()
18
+ </script>
19
+
20
+ <div class="{{ containerClasses }}">
21
+ @if(isLoading)
22
+ <!-- Loading state -->
23
+ <div class="animate-pulse">
24
+ <div class="h-24 bg-gray-200 dark:bg-gray-700 rounded-lg"></div>
25
+ </div>
26
+ @else
27
+ @if(paymentMethods.length > 0)
28
+ <ul role="list" class="grid grid-cols-1 gap-6 lg:grid-cols-1 sm:grid-cols-1">
29
+ @foreach(method in paymentMethods)
30
+ <li class="col-span-1 border border-gray-200 dark:border-gray-700 rounded-lg bg-white dark:bg-blue-gray-800 shadow divide-y divide-gray-200 dark:divide-gray-700">
31
+ <div class="w-full p-3">
32
+ <div class="flex items-center justify-between">
33
+ <div class="flex items-center space-x-4">
34
+ <!-- Card Brand Icon -->
35
+ <div class="flex-shrink-0 h-10 w-10 flex items-center justify-center bg-gray-100 dark:bg-gray-700 rounded-md">
36
+ <span class="text-2xl">{{ brandIcons[method.brand.toLowerCase()] || brandIcons.default }}</span>
37
+ </div>
38
+
39
+ <!-- Card Details -->
40
+ <div>
41
+ <h2 class="text-sm text-gray-600 dark:text-gray-300">
42
+ {{ method.brand }} •••• {{ method.last_four }}
43
+ </h2>
44
+ <span class="text-xs text-gray-500 dark:text-gray-400 italic">
45
+ Expires {{ method.exp_month }} / {{ method.exp_year }}
46
+ </span>
47
+ </div>
48
+ </div>
49
+
50
+ <div class="flex justify-end space-x-4">
51
+ <!-- Make Default Button -->
52
+ @if(onMakeDefault)
53
+ <button
54
+ type="button"
55
+ class="border border-gray-300 dark:border-gray-600 rounded-md bg-white dark:bg-blue-gray-700 px-2 py-1 text-sm text-gray-700 dark:text-gray-300 font-semibold shadow-sm hover:bg-gray-50 dark:hover:bg-blue-gray-600 focus-visible:outline-2 focus-visible:outline-blue-600 focus-visible:outline-offset-2 disabled:opacity-50 disabled:cursor-not-allowed"
56
+ onclick="handleMakeDefault('{{ method.id }}')"
57
+ title="Make default"
58
+ >
59
+ <svg class="h-5 w-5" fill="none" viewBox="0 0 24 24" stroke="currentColor">
60
+ <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M11.049 2.927c.3-.921 1.603-.921 1.902 0l1.519 4.674a1 1 0 00.95.69h4.915c.969 0 1.371 1.24.588 1.81l-3.976 2.888a1 1 0 00-.363 1.118l1.518 4.674c.3.922-.755 1.688-1.538 1.118l-3.976-2.888a1 1 0 00-1.176 0l-3.976 2.888c-.783.57-1.838-.197-1.538-1.118l1.518-4.674a1 1 0 00-.363-1.118l-3.976-2.888c-.784-.57-.38-1.81.588-1.81h4.914a1 1 0 00.951-.69l1.519-4.674z" />
61
+ </svg>
62
+ </button>
63
+ @endif
64
+
65
+ <!-- Delete Button -->
66
+ @if(onDeletePaymentMethod)
67
+ <button
68
+ type="button"
69
+ class="border border-gray-300 dark:border-gray-600 rounded-md bg-white dark:bg-blue-gray-700 px-2 py-1 text-sm text-red-600 dark:text-red-400 font-semibold shadow-sm hover:bg-red-50 dark:hover:bg-red-900/20 focus-visible:outline-2 focus-visible:outline-red-600 focus-visible:outline-offset-2 disabled:opacity-50 disabled:cursor-not-allowed"
70
+ onclick="handleDelete('{{ method.id }}')"
71
+ title="Delete payment method"
72
+ >
73
+ <svg class="h-5 w-5" fill="none" viewBox="0 0 24 24" stroke="currentColor">
74
+ <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 7l-.867 12.142A2 2 0 0116.138 21H7.862a2 2 0 01-1.995-1.858L5 7m5 4v6m4-6v6m1-10V4a1 1 0 00-1-1h-4a1 1 0 00-1 1v3M4 7h16" />
75
+ </svg>
76
+ </button>
77
+ @endif
78
+ </div>
79
+ </div>
80
+ </div>
81
+ </li>
82
+ @endforeach
83
+ </ul>
84
+ @else
85
+ <!-- Empty state -->
86
+ <div class="text-center py-12 bg-white dark:bg-blue-gray-800 rounded-lg border border-gray-200 dark:border-gray-700">
87
+ <svg class="mx-auto h-12 w-12 text-gray-400 dark:text-gray-500" fill="none" viewBox="0 0 24 24" stroke="currentColor">
88
+ <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M3 10h18M7 15h1m4 0h1m-7 4h12a3 3 0 003-3V8a3 3 0 00-3-3H6a3 3 0 00-3 3v8a3 3 0 003 3z" />
89
+ </svg>
90
+ <h3 class="mt-2 text-sm text-gray-900 dark:text-gray-100 font-medium">No payment methods</h3>
91
+ <p class="mt-1 text-sm text-gray-500 dark:text-gray-400">
92
+ You haven't added any payment methods yet.
93
+ </p>
94
+ </div>
95
+ @endif
96
+ @endif
97
+ </div>
98
+
99
+ <script>
100
+ function handleMakeDefault(methodId) {
101
+ if (onMakeDefault) {
102
+ onMakeDefault(methodId)
103
+ }
104
+ }
105
+
106
+ function handleDelete(methodId) {
107
+ if (onDeletePaymentMethod) {
108
+ if (confirm('Are you sure you want to delete this payment method?')) {
109
+ onDeletePaymentMethod(methodId)
110
+ }
111
+ }
112
+ }
113
+ </script>