@vandenberghinc/volt 1.1.2

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 (451) hide show
  1. package/.vrepo +28 -0
  2. package/.vscode/tasks.json +87 -0
  3. package/README.md +67 -0
  4. package/backend/dist/cjs/blacklist.d.ts +10 -0
  5. package/backend/dist/cjs/blacklist.js +53 -0
  6. package/backend/dist/cjs/cli.d.ts +2 -0
  7. package/backend/dist/cjs/cli.js +263 -0
  8. package/backend/dist/cjs/database.d.ts +364 -0
  9. package/backend/dist/cjs/database.js +1962 -0
  10. package/backend/dist/cjs/endpoint.d.ts +57 -0
  11. package/backend/dist/cjs/endpoint.js +425 -0
  12. package/backend/dist/cjs/file_watcher.d.ts +44 -0
  13. package/backend/dist/cjs/file_watcher.js +348 -0
  14. package/backend/dist/cjs/frontend.d.ts +13 -0
  15. package/backend/dist/cjs/frontend.js +30 -0
  16. package/backend/dist/cjs/image_endpoint.d.ts +24 -0
  17. package/backend/dist/cjs/image_endpoint.js +210 -0
  18. package/backend/dist/cjs/logger.d.ts +5 -0
  19. package/backend/dist/cjs/logger.js +16 -0
  20. package/backend/dist/cjs/meta.d.ts +50 -0
  21. package/backend/dist/cjs/meta.js +153 -0
  22. package/backend/dist/cjs/mutex.d.ts +24 -0
  23. package/backend/dist/cjs/mutex.js +52 -0
  24. package/backend/dist/cjs/package.json +1 -0
  25. package/backend/dist/cjs/payments/paddle.d.ts +161 -0
  26. package/backend/dist/cjs/payments/paddle.js +2301 -0
  27. package/backend/dist/cjs/plugins/browser.d.ts +36 -0
  28. package/backend/dist/cjs/plugins/browser.js +183 -0
  29. package/backend/dist/cjs/plugins/communication.d.ts +70 -0
  30. package/backend/dist/cjs/plugins/communication.js +177 -0
  31. package/backend/dist/cjs/plugins/css.d.ts +10 -0
  32. package/backend/dist/cjs/plugins/css.js +71 -0
  33. package/backend/dist/cjs/plugins/mail.d.ts +277 -0
  34. package/backend/dist/cjs/plugins/mail.js +1419 -0
  35. package/backend/dist/cjs/plugins/pdf.d.ts +757 -0
  36. package/backend/dist/cjs/plugins/pdf.js +1694 -0
  37. package/backend/dist/cjs/plugins/thread_monitor.d.ts +18 -0
  38. package/backend/dist/cjs/plugins/thread_monitor.js +127 -0
  39. package/backend/dist/cjs/plugins/ts/compiler.d.ts +132 -0
  40. package/backend/dist/cjs/plugins/ts/compiler.js +944 -0
  41. package/backend/dist/cjs/plugins/ts/preprocessing.d.ts +14 -0
  42. package/backend/dist/cjs/plugins/ts/preprocessing.js +762 -0
  43. package/backend/dist/cjs/rate_limit.d.ts +65 -0
  44. package/backend/dist/cjs/rate_limit.js +463 -0
  45. package/backend/dist/cjs/request.deprc.d.ts +48 -0
  46. package/backend/dist/cjs/request.deprc.js +572 -0
  47. package/backend/dist/cjs/response.deprc.d.ts +55 -0
  48. package/backend/dist/cjs/response.deprc.js +275 -0
  49. package/backend/dist/cjs/server.d.ts +311 -0
  50. package/backend/dist/cjs/server.js +3475 -0
  51. package/backend/dist/cjs/splash_screen.d.ts +35 -0
  52. package/backend/dist/cjs/splash_screen.js +152 -0
  53. package/backend/dist/cjs/status.d.ts +60 -0
  54. package/backend/dist/cjs/status.js +199 -0
  55. package/backend/dist/cjs/stream.d.ts +75 -0
  56. package/backend/dist/cjs/stream.js +954 -0
  57. package/backend/dist/cjs/users.d.ts +111 -0
  58. package/backend/dist/cjs/users.js +1945 -0
  59. package/backend/dist/cjs/utils.d.ts +27 -0
  60. package/backend/dist/cjs/utils.js +329 -0
  61. package/backend/dist/cjs/view.d.ts +52 -0
  62. package/backend/dist/cjs/view.js +568 -0
  63. package/backend/dist/cjs/vinc.d.ts +2 -0
  64. package/backend/dist/cjs/vinc.dev.d.ts +2 -0
  65. package/backend/dist/cjs/vinc.dev.js +42 -0
  66. package/backend/dist/cjs/vinc.js +42 -0
  67. package/backend/dist/cjs/volt.d.ts +15 -0
  68. package/backend/dist/cjs/volt.js +64 -0
  69. package/backend/dist/css/adyen.css +92 -0
  70. package/backend/dist/css/volt.css +65 -0
  71. package/backend/dist/esm/blacklist.d.ts +10 -0
  72. package/backend/dist/esm/blacklist.js +49 -0
  73. package/backend/dist/esm/cli.d.ts +2 -0
  74. package/backend/dist/esm/cli.js +228 -0
  75. package/backend/dist/esm/database.d.ts +364 -0
  76. package/backend/dist/esm/database.js +1957 -0
  77. package/backend/dist/esm/endpoint.d.ts +57 -0
  78. package/backend/dist/esm/endpoint.js +421 -0
  79. package/backend/dist/esm/file_watcher.d.ts +44 -0
  80. package/backend/dist/esm/file_watcher.js +313 -0
  81. package/backend/dist/esm/frontend.d.ts +13 -0
  82. package/backend/dist/esm/frontend.js +27 -0
  83. package/backend/dist/esm/image_endpoint.d.ts +24 -0
  84. package/backend/dist/esm/image_endpoint.js +206 -0
  85. package/backend/dist/esm/logger.d.ts +5 -0
  86. package/backend/dist/esm/logger.js +13 -0
  87. package/backend/dist/esm/meta.d.ts +50 -0
  88. package/backend/dist/esm/meta.js +149 -0
  89. package/backend/dist/esm/mutex.d.ts +24 -0
  90. package/backend/dist/esm/mutex.js +48 -0
  91. package/backend/dist/esm/payments/paddle.d.ts +161 -0
  92. package/backend/dist/esm/payments/paddle.js +2261 -0
  93. package/backend/dist/esm/plugins/browser.d.ts +36 -0
  94. package/backend/dist/esm/plugins/browser.js +176 -0
  95. package/backend/dist/esm/plugins/communication.d.ts +70 -0
  96. package/backend/dist/esm/plugins/communication.js +169 -0
  97. package/backend/dist/esm/plugins/css.d.ts +10 -0
  98. package/backend/dist/esm/plugins/css.js +64 -0
  99. package/backend/dist/esm/plugins/mail.d.ts +277 -0
  100. package/backend/dist/esm/plugins/mail.js +1403 -0
  101. package/backend/dist/esm/plugins/pdf.d.ts +757 -0
  102. package/backend/dist/esm/plugins/pdf.js +1694 -0
  103. package/backend/dist/esm/plugins/thread_monitor.d.ts +18 -0
  104. package/backend/dist/esm/plugins/thread_monitor.js +120 -0
  105. package/backend/dist/esm/plugins/ts/compiler.d.ts +132 -0
  106. package/backend/dist/esm/plugins/ts/compiler.js +907 -0
  107. package/backend/dist/esm/plugins/ts/preprocessing.d.ts +14 -0
  108. package/backend/dist/esm/plugins/ts/preprocessing.js +724 -0
  109. package/backend/dist/esm/rate_limit.d.ts +65 -0
  110. package/backend/dist/esm/rate_limit.js +425 -0
  111. package/backend/dist/esm/request.deprc.d.ts +48 -0
  112. package/backend/dist/esm/request.deprc.js +572 -0
  113. package/backend/dist/esm/response.deprc.d.ts +55 -0
  114. package/backend/dist/esm/response.deprc.js +275 -0
  115. package/backend/dist/esm/server.d.ts +311 -0
  116. package/backend/dist/esm/server.js +3435 -0
  117. package/backend/dist/esm/splash_screen.d.ts +35 -0
  118. package/backend/dist/esm/splash_screen.js +148 -0
  119. package/backend/dist/esm/status.d.ts +60 -0
  120. package/backend/dist/esm/status.js +196 -0
  121. package/backend/dist/esm/stream.d.ts +75 -0
  122. package/backend/dist/esm/stream.js +947 -0
  123. package/backend/dist/esm/users.d.ts +111 -0
  124. package/backend/dist/esm/users.js +1908 -0
  125. package/backend/dist/esm/utils.d.ts +27 -0
  126. package/backend/dist/esm/utils.js +324 -0
  127. package/backend/dist/esm/view.d.ts +52 -0
  128. package/backend/dist/esm/view.js +561 -0
  129. package/backend/dist/esm/vinc.d.ts +2 -0
  130. package/backend/dist/esm/vinc.dev.d.ts +2 -0
  131. package/backend/dist/esm/vinc.dev.js +6 -0
  132. package/backend/dist/esm/vinc.js +6 -0
  133. package/backend/dist/esm/volt.d.ts +15 -0
  134. package/backend/dist/esm/volt.js +23 -0
  135. package/backend/dist/esm-dev/blacklist.d.ts +10 -0
  136. package/backend/dist/esm-dev/blacklist.js +49 -0
  137. package/backend/dist/esm-dev/cli.d.ts +2 -0
  138. package/backend/dist/esm-dev/cli.js +228 -0
  139. package/backend/dist/esm-dev/database.d.ts +364 -0
  140. package/backend/dist/esm-dev/database.js +1957 -0
  141. package/backend/dist/esm-dev/endpoint.d.ts +57 -0
  142. package/backend/dist/esm-dev/endpoint.js +421 -0
  143. package/backend/dist/esm-dev/file_watcher.d.ts +44 -0
  144. package/backend/dist/esm-dev/file_watcher.js +313 -0
  145. package/backend/dist/esm-dev/frontend.d.ts +13 -0
  146. package/backend/dist/esm-dev/frontend.js +27 -0
  147. package/backend/dist/esm-dev/image_endpoint.d.ts +24 -0
  148. package/backend/dist/esm-dev/image_endpoint.js +206 -0
  149. package/backend/dist/esm-dev/logger.d.ts +5 -0
  150. package/backend/dist/esm-dev/logger.js +13 -0
  151. package/backend/dist/esm-dev/meta.d.ts +50 -0
  152. package/backend/dist/esm-dev/meta.js +149 -0
  153. package/backend/dist/esm-dev/mutex.d.ts +24 -0
  154. package/backend/dist/esm-dev/mutex.js +48 -0
  155. package/backend/dist/esm-dev/payments/paddle.d.ts +161 -0
  156. package/backend/dist/esm-dev/payments/paddle.js +2261 -0
  157. package/backend/dist/esm-dev/plugins/browser.d.ts +36 -0
  158. package/backend/dist/esm-dev/plugins/browser.js +176 -0
  159. package/backend/dist/esm-dev/plugins/communication.d.ts +70 -0
  160. package/backend/dist/esm-dev/plugins/communication.js +169 -0
  161. package/backend/dist/esm-dev/plugins/css.d.ts +10 -0
  162. package/backend/dist/esm-dev/plugins/css.js +64 -0
  163. package/backend/dist/esm-dev/plugins/mail.d.ts +277 -0
  164. package/backend/dist/esm-dev/plugins/mail.js +1403 -0
  165. package/backend/dist/esm-dev/plugins/pdf.d.ts +757 -0
  166. package/backend/dist/esm-dev/plugins/pdf.js +1694 -0
  167. package/backend/dist/esm-dev/plugins/thread_monitor.d.ts +18 -0
  168. package/backend/dist/esm-dev/plugins/thread_monitor.js +120 -0
  169. package/backend/dist/esm-dev/plugins/ts/compiler.d.ts +132 -0
  170. package/backend/dist/esm-dev/plugins/ts/compiler.js +907 -0
  171. package/backend/dist/esm-dev/plugins/ts/preprocessing.d.ts +14 -0
  172. package/backend/dist/esm-dev/plugins/ts/preprocessing.js +724 -0
  173. package/backend/dist/esm-dev/rate_limit.d.ts +65 -0
  174. package/backend/dist/esm-dev/rate_limit.js +425 -0
  175. package/backend/dist/esm-dev/request.deprc.d.ts +48 -0
  176. package/backend/dist/esm-dev/request.deprc.js +572 -0
  177. package/backend/dist/esm-dev/response.deprc.d.ts +55 -0
  178. package/backend/dist/esm-dev/response.deprc.js +275 -0
  179. package/backend/dist/esm-dev/server.d.ts +311 -0
  180. package/backend/dist/esm-dev/server.js +3435 -0
  181. package/backend/dist/esm-dev/splash_screen.d.ts +35 -0
  182. package/backend/dist/esm-dev/splash_screen.js +148 -0
  183. package/backend/dist/esm-dev/status.d.ts +60 -0
  184. package/backend/dist/esm-dev/status.js +196 -0
  185. package/backend/dist/esm-dev/stream.d.ts +75 -0
  186. package/backend/dist/esm-dev/stream.js +947 -0
  187. package/backend/dist/esm-dev/users.d.ts +111 -0
  188. package/backend/dist/esm-dev/users.js +1908 -0
  189. package/backend/dist/esm-dev/utils.d.ts +27 -0
  190. package/backend/dist/esm-dev/utils.js +324 -0
  191. package/backend/dist/esm-dev/view.d.ts +52 -0
  192. package/backend/dist/esm-dev/view.js +561 -0
  193. package/backend/dist/esm-dev/vinc.d.ts +2 -0
  194. package/backend/dist/esm-dev/vinc.dev.d.ts +2 -0
  195. package/backend/dist/esm-dev/vinc.dev.js +6 -0
  196. package/backend/dist/esm-dev/vinc.js +6 -0
  197. package/backend/dist/esm-dev/volt.d.ts +15 -0
  198. package/backend/dist/esm-dev/volt.js +23 -0
  199. package/backend/src/blacklist.ts +69 -0
  200. package/backend/src/cli.js +245 -0
  201. package/backend/src/database.ts +2241 -0
  202. package/backend/src/endpoint.ts +494 -0
  203. package/backend/src/file_watcher.ts +359 -0
  204. package/backend/src/frontend.ts +35 -0
  205. package/backend/src/globals.d.ts +8 -0
  206. package/backend/src/image_endpoint.ts +258 -0
  207. package/backend/src/logger.ts +18 -0
  208. package/backend/src/meta.ts +202 -0
  209. package/backend/src/mutex.ts +51 -0
  210. package/backend/src/payments/paddle.ts +2659 -0
  211. package/backend/src/plugins/browser.ts +188 -0
  212. package/backend/src/plugins/communication.ts +204 -0
  213. package/backend/src/plugins/css.ts +84 -0
  214. package/backend/src/plugins/fonts/Menlo-Bold.ttf +0 -0
  215. package/backend/src/plugins/fonts/Menlo-Regular.ttf +0 -0
  216. package/backend/src/plugins/mail.ts +1720 -0
  217. package/backend/src/plugins/pdf.js +1932 -0
  218. package/backend/src/plugins/thread_monitor.ts +164 -0
  219. package/backend/src/plugins/ts/compiler.ts +1242 -0
  220. package/backend/src/plugins/ts/preprocessing.ts +812 -0
  221. package/backend/src/rate_limit.ts +503 -0
  222. package/backend/src/request.deprc.js +626 -0
  223. package/backend/src/response.deprc.js +354 -0
  224. package/backend/src/server.ts +4149 -0
  225. package/backend/src/splash_screen.ts +192 -0
  226. package/backend/src/status.ts +199 -0
  227. package/backend/src/stream.ts +1070 -0
  228. package/backend/src/users.ts +2077 -0
  229. package/backend/src/utils.ts +359 -0
  230. package/backend/src/view.ts +655 -0
  231. package/backend/src/vinc.dev.js +6 -0
  232. package/backend/src/vinc.ts +6 -0
  233. package/backend/src/volt.js +25 -0
  234. package/backend/tsconfig.cjs.json +29 -0
  235. package/backend/tsconfig.esm.dev.json +34 -0
  236. package/backend/tsconfig.esm.json +30 -0
  237. package/backend/tsconfig.json +2 -0
  238. package/frontend/compile.js +436 -0
  239. package/frontend/dist/elements/base.d.ts +9891 -0
  240. package/frontend/dist/elements/base.js +8818 -0
  241. package/frontend/dist/elements/module.d.ts +16 -0
  242. package/frontend/dist/elements/module.js +178 -0
  243. package/frontend/dist/modules/array.d.ts +37 -0
  244. package/frontend/dist/modules/array.js +284 -0
  245. package/frontend/dist/modules/auth.d.ts +45 -0
  246. package/frontend/dist/modules/auth.js +138 -0
  247. package/frontend/dist/modules/colors.d.ts +26 -0
  248. package/frontend/dist/modules/colors.js +340 -0
  249. package/frontend/dist/modules/compression.d.ts +6 -0
  250. package/frontend/dist/modules/compression.js +999 -0
  251. package/frontend/dist/modules/cookies.d.ts +17 -0
  252. package/frontend/dist/modules/cookies.js +166 -0
  253. package/frontend/dist/modules/date.d.ts +142 -0
  254. package/frontend/dist/modules/date.js +493 -0
  255. package/frontend/dist/modules/events.d.ts +7 -0
  256. package/frontend/dist/modules/events.js +90 -0
  257. package/frontend/dist/modules/google.d.ts +10 -0
  258. package/frontend/dist/modules/google.js +53 -0
  259. package/frontend/dist/modules/meta.d.ts +9 -0
  260. package/frontend/dist/modules/meta.js +45 -0
  261. package/frontend/dist/modules/mutex.d.ts +8 -0
  262. package/frontend/dist/modules/mutex.js +52 -0
  263. package/frontend/dist/modules/number.d.ts +12 -0
  264. package/frontend/dist/modules/number.js +8 -0
  265. package/frontend/dist/modules/object.d.ts +50 -0
  266. package/frontend/dist/modules/object.js +147 -0
  267. package/frontend/dist/modules/paddle.d.ts +1403 -0
  268. package/frontend/dist/modules/paddle.js +2641 -0
  269. package/frontend/dist/modules/scheme.d.ts +207 -0
  270. package/frontend/dist/modules/scheme.js +649 -0
  271. package/frontend/dist/modules/settings.d.ts +3 -0
  272. package/frontend/dist/modules/settings.js +4 -0
  273. package/frontend/dist/modules/statics.d.ts +4 -0
  274. package/frontend/dist/modules/statics.js +45 -0
  275. package/frontend/dist/modules/string.d.ts +163 -0
  276. package/frontend/dist/modules/string.js +291 -0
  277. package/frontend/dist/modules/support.d.ts +18 -0
  278. package/frontend/dist/modules/support.js +102 -0
  279. package/frontend/dist/modules/themes.d.ts +8 -0
  280. package/frontend/dist/modules/themes.js +17 -0
  281. package/frontend/dist/modules/user.d.ts +58 -0
  282. package/frontend/dist/modules/user.js +279 -0
  283. package/frontend/dist/modules/utils.d.ts +58 -0
  284. package/frontend/dist/modules/utils.js +1159 -0
  285. package/frontend/dist/types/gradient.d.ts +12 -0
  286. package/frontend/dist/types/gradient.js +79 -0
  287. package/frontend/dist/ui/border_button.d.ts +177 -0
  288. package/frontend/dist/ui/border_button.js +235 -0
  289. package/frontend/dist/ui/button.d.ts +42 -0
  290. package/frontend/dist/ui/button.js +114 -0
  291. package/frontend/dist/ui/canvas.d.ts +56 -0
  292. package/frontend/dist/ui/canvas.js +411 -0
  293. package/frontend/dist/ui/checkbox.d.ts +72 -0
  294. package/frontend/dist/ui/checkbox.js +277 -0
  295. package/frontend/dist/ui/code.d.ts +232 -0
  296. package/frontend/dist/ui/code.js +977 -0
  297. package/frontend/dist/ui/color.d.ts +1 -0
  298. package/frontend/dist/ui/color.js +110 -0
  299. package/frontend/dist/ui/context_menu.d.ts +30 -0
  300. package/frontend/dist/ui/context_menu.js +211 -0
  301. package/frontend/dist/ui/css.d.ts +10 -0
  302. package/frontend/dist/ui/css.js +44 -0
  303. package/frontend/dist/ui/divider.d.ts +18 -0
  304. package/frontend/dist/ui/divider.js +82 -0
  305. package/frontend/dist/ui/dropdown.d.ts +115 -0
  306. package/frontend/dist/ui/dropdown.js +446 -0
  307. package/frontend/dist/ui/for_each.d.ts +38 -0
  308. package/frontend/dist/ui/for_each.js +97 -0
  309. package/frontend/dist/ui/form.d.ts +25 -0
  310. package/frontend/dist/ui/form.js +227 -0
  311. package/frontend/dist/ui/frame_modes.d.ts +28 -0
  312. package/frontend/dist/ui/frame_modes.js +116 -0
  313. package/frontend/dist/ui/google_map.d.ts +31 -0
  314. package/frontend/dist/ui/google_map.js +111 -0
  315. package/frontend/dist/ui/gradient.d.ts +24 -0
  316. package/frontend/dist/ui/gradient.js +115 -0
  317. package/frontend/dist/ui/image.d.ts +138 -0
  318. package/frontend/dist/ui/image.js +570 -0
  319. package/frontend/dist/ui/input.d.ts +316 -0
  320. package/frontend/dist/ui/input.js +1187 -0
  321. package/frontend/dist/ui/link.d.ts +39 -0
  322. package/frontend/dist/ui/link.js +146 -0
  323. package/frontend/dist/ui/list.d.ts +33 -0
  324. package/frontend/dist/ui/list.js +161 -0
  325. package/frontend/dist/ui/loader_button.d.ts +108 -0
  326. package/frontend/dist/ui/loader_button.js +207 -0
  327. package/frontend/dist/ui/loaders.d.ts +60 -0
  328. package/frontend/dist/ui/loaders.js +150 -0
  329. package/frontend/dist/ui/popup.d.ts +84 -0
  330. package/frontend/dist/ui/popup.js +331 -0
  331. package/frontend/dist/ui/pseudo.d.ts +16 -0
  332. package/frontend/dist/ui/pseudo.js +81 -0
  333. package/frontend/dist/ui/scroller.d.ts +131 -0
  334. package/frontend/dist/ui/scroller.js +1251 -0
  335. package/frontend/dist/ui/slider.d.ts +35 -0
  336. package/frontend/dist/ui/slider.js +203 -0
  337. package/frontend/dist/ui/spacer.d.ts +20 -0
  338. package/frontend/dist/ui/spacer.js +83 -0
  339. package/frontend/dist/ui/span.d.ts +11 -0
  340. package/frontend/dist/ui/span.js +75 -0
  341. package/frontend/dist/ui/stack.d.ts +123 -0
  342. package/frontend/dist/ui/stack.js +344 -0
  343. package/frontend/dist/ui/steps.d.ts +72 -0
  344. package/frontend/dist/ui/steps.js +306 -0
  345. package/frontend/dist/ui/style.d.ts +12 -0
  346. package/frontend/dist/ui/style.js +78 -0
  347. package/frontend/dist/ui/switch.d.ts +44 -0
  348. package/frontend/dist/ui/switch.js +280 -0
  349. package/frontend/dist/ui/table.d.ts +118 -0
  350. package/frontend/dist/ui/table.js +411 -0
  351. package/frontend/dist/ui/tabs.d.ts +85 -0
  352. package/frontend/dist/ui/tabs.js +392 -0
  353. package/frontend/dist/ui/text.d.ts +19 -0
  354. package/frontend/dist/ui/text.js +88 -0
  355. package/frontend/dist/ui/theme.d.ts +25 -0
  356. package/frontend/dist/ui/theme.js +237 -0
  357. package/frontend/dist/ui/title.d.ts +36 -0
  358. package/frontend/dist/ui/title.js +127 -0
  359. package/frontend/dist/ui/ui.d.ts +38 -0
  360. package/frontend/dist/ui/ui.js +41 -0
  361. package/frontend/dist/ui/view.d.ts +25 -0
  362. package/frontend/dist/ui/view.js +93 -0
  363. package/frontend/dist/volt.d.ts +22 -0
  364. package/frontend/dist/volt.js +27 -0
  365. package/frontend/exports.json +1340 -0
  366. package/frontend/src/css/adyen.css +92 -0
  367. package/frontend/src/css/volt.css +65 -0
  368. package/frontend/src/elements/base.ts +16790 -0
  369. package/frontend/src/elements/module.ts +184 -0
  370. package/frontend/src/elements/types.d.ts +155 -0
  371. package/frontend/src/modules/array.ts +366 -0
  372. package/frontend/src/modules/auth.ts +188 -0
  373. package/frontend/src/modules/colors.ts +449 -0
  374. package/frontend/src/modules/compression.ts +67 -0
  375. package/frontend/src/modules/cookies.ts +182 -0
  376. package/frontend/src/modules/date.js +535 -0
  377. package/frontend/src/modules/date.ts +583 -0
  378. package/frontend/src/modules/events.ts +96 -0
  379. package/frontend/src/modules/google.ts +60 -0
  380. package/frontend/src/modules/meta.ts +59 -0
  381. package/frontend/src/modules/mutex.ts +59 -0
  382. package/frontend/src/modules/number.ts +20 -0
  383. package/frontend/src/modules/object.ts +212 -0
  384. package/frontend/src/modules/paddle.ts +2990 -0
  385. package/frontend/src/modules/scheme.ts +740 -0
  386. package/frontend/src/modules/settings.ts +5 -0
  387. package/frontend/src/modules/statics.ts +47 -0
  388. package/frontend/src/modules/string.ts +500 -0
  389. package/frontend/src/modules/support.ts +118 -0
  390. package/frontend/src/modules/themes.ts +24 -0
  391. package/frontend/src/modules/user.ts +321 -0
  392. package/frontend/src/modules/utils.ts +1260 -0
  393. package/frontend/src/static/admin/admin.png +0 -0
  394. package/frontend/src/static/admin/password.webp +0 -0
  395. package/frontend/src/static/icons/copy.webp +0 -0
  396. package/frontend/src/static/payments/arrow.long.webp +0 -0
  397. package/frontend/src/static/payments/arrow.long2.webp +0 -0
  398. package/frontend/src/static/payments/cancelled.webp +0 -0
  399. package/frontend/src/static/payments/check.sign.webp +0 -0
  400. package/frontend/src/static/payments/check.webp +0 -0
  401. package/frontend/src/static/payments/close.webp +0 -0
  402. package/frontend/src/static/payments/error.webp +0 -0
  403. package/frontend/src/static/payments/exclamation.webp +0 -0
  404. package/frontend/src/static/payments/minus.webp +0 -0
  405. package/frontend/src/static/payments/party.webp +0 -0
  406. package/frontend/src/static/payments/plus.webp +0 -0
  407. package/frontend/src/static/payments/shopping_cart.webp +0 -0
  408. package/frontend/src/static/payments/trash.webp +0 -0
  409. package/frontend/src/types/global.d.ts +4 -0
  410. package/frontend/src/types/gradient.ts +87 -0
  411. package/frontend/src/ui/any_element.d.ts +5 -0
  412. package/frontend/src/ui/border_button.ts +320 -0
  413. package/frontend/src/ui/button.ts +62 -0
  414. package/frontend/src/ui/canvas.ts +431 -0
  415. package/frontend/src/ui/checkbox.ts +284 -0
  416. package/frontend/src/ui/code.ts +1049 -0
  417. package/frontend/src/ui/color.ts +117 -0
  418. package/frontend/src/ui/context_menu.ts +194 -0
  419. package/frontend/src/ui/css.ts +57 -0
  420. package/frontend/src/ui/divider.ts +28 -0
  421. package/frontend/src/ui/dropdown.ts +503 -0
  422. package/frontend/src/ui/for_each.ts +71 -0
  423. package/frontend/src/ui/form.ts +208 -0
  424. package/frontend/src/ui/frame_modes.ts +140 -0
  425. package/frontend/src/ui/google_map.ts +70 -0
  426. package/frontend/src/ui/gradient.ts +73 -0
  427. package/frontend/src/ui/image.ts +587 -0
  428. package/frontend/src/ui/input.ts +1284 -0
  429. package/frontend/src/ui/link.ts +77 -0
  430. package/frontend/src/ui/list.ts +88 -0
  431. package/frontend/src/ui/loader_button.ts +192 -0
  432. package/frontend/src/ui/loaders.ts +126 -0
  433. package/frontend/src/ui/popup.ts +370 -0
  434. package/frontend/src/ui/pseudo.ts +33 -0
  435. package/frontend/src/ui/scroller.ts +1324 -0
  436. package/frontend/src/ui/slider.ts +215 -0
  437. package/frontend/src/ui/spacer.ts +29 -0
  438. package/frontend/src/ui/span.ts +23 -0
  439. package/frontend/src/ui/stack.ts +238 -0
  440. package/frontend/src/ui/steps.ts +334 -0
  441. package/frontend/src/ui/style.ts +26 -0
  442. package/frontend/src/ui/switch.ts +286 -0
  443. package/frontend/src/ui/table.ts +323 -0
  444. package/frontend/src/ui/tabs.ts +441 -0
  445. package/frontend/src/ui/text.ts +38 -0
  446. package/frontend/src/ui/theme.ts +279 -0
  447. package/frontend/src/ui/title.ts +64 -0
  448. package/frontend/src/ui/ui.ts +47 -0
  449. package/frontend/src/ui/view.ts +44 -0
  450. package/frontend/src/volt.ts +31 -0
  451. package/package.json +58 -0
@@ -0,0 +1,2641 @@
1
+ /*
2
+ * @author: Daan van den Bergh
3
+ * @copyright: © 2022 - 2024 Daan van den Bergh.
4
+ */
5
+ // Imports.
6
+ import { Utils } from "./utils.js";
7
+ import { User } from "./user.js";
8
+ import { HStack, VStack, } from "../ui/stack";
9
+ import { Text } from "../ui/text";
10
+ import { Title } from "../ui/title";
11
+ import { ForEach } from "../ui/for_each";
12
+ import { Image, ImageMask } from "../ui/image";
13
+ import { RingLoader } from "../ui/loaders";
14
+ import { BorderButton } from "../ui/border_button";
15
+ import { LoaderButton } from "../ui/loader_button";
16
+ import { Divider } from "../ui/divider";
17
+ import { Input, ExtendedSelect, ExtendedInput } from "../ui/input";
18
+ import { Spacer } from "../ui/spacer";
19
+ import { Form } from "../ui/form";
20
+ import { Popup } from "../ui/popup";
21
+ // ---------------------------------------------------------
22
+ // Payments Object.
23
+ const Payments = {
24
+ // ---------------------------------------------------------
25
+ // Private Properties.
26
+ client_key: "{{PADDLE_CLIENT_KEY}}",
27
+ // @ts-ignore
28
+ sandbox: "{{PADDLE_SANDBOX}}" === "true",
29
+ // @ts-ignore
30
+ tax_inclusive: "{{PADDLE_INCLUSIVE_TAX}}" === "true",
31
+ countries: {
32
+ "AD": { name: "🇦🇩 Andorra", calling_code: "+376" },
33
+ "AE": { name: "🇦🇪 United Arab Emirates", calling_code: "+971" },
34
+ "AF": { name: "🇦🇫 Afghanistan", calling_code: "+93" },
35
+ "AG": { name: "🇦🇬 Antigua and Barbuda", calling_code: "+1-268" },
36
+ "AI": { name: "🇦🇮 Anguilla", calling_code: "+1-264" },
37
+ "AL": { name: "🇦🇱 Albania", calling_code: "+355" },
38
+ "AM": { name: "🇦🇲 Armenia", calling_code: "+374" },
39
+ "AO": { name: "🇦🇴 Angola", calling_code: "+244" },
40
+ "AQ": { name: "🇦🇶 Antarctica", calling_code: "+672" },
41
+ "AR": { name: "🇦🇷 Argentina", calling_code: "+54" },
42
+ "AS": { name: "🇦🇸 American Samoa", calling_code: "+1-684" },
43
+ "AT": { name: "🇦🇹 Austria", calling_code: "+43" },
44
+ "AU": { name: "🇦🇺 Australia", calling_code: "+61" },
45
+ "AW": { name: "🇦🇼 Aruba", calling_code: "+297" },
46
+ "AX": { name: "🇦🇽 Åland Islands", calling_code: "+358-18" },
47
+ "AZ": { name: "🇦🇿 Azerbaijan", calling_code: "+994" },
48
+ "BA": { name: "🇧🇦 Bosnia and Herzegovina", calling_code: "+387" },
49
+ "BB": { name: "🇧🇧 Barbados", calling_code: "+1-246" },
50
+ "BD": { name: "🇧🇩 Bangladesh", calling_code: "+880" },
51
+ "BE": { name: "🇧🇪 Belgium", calling_code: "+32" },
52
+ "BF": { name: "🇧🇫 Burkina Faso", calling_code: "+226" },
53
+ "BG": { name: "🇧🇬 Bulgaria", calling_code: "+359" },
54
+ "BH": { name: "🇧🇭 Bahrain", calling_code: "+973" },
55
+ "BI": { name: "🇧🇮 Burundi", calling_code: "+257" },
56
+ "BJ": { name: "🇧🇯 Benin", calling_code: "+229" },
57
+ "BL": { name: "🇧🇱 Saint Barthélemy", calling_code: "+590" },
58
+ "BM": { name: "🇧🇲 Bermuda", calling_code: "+1-441" },
59
+ "BN": { name: "🇧🇳 Brunei", calling_code: "+673" },
60
+ "BO": { name: "🇧🇴 Bolivia", calling_code: "+591" },
61
+ "BQ": { name: "🇧🇶 Caribbean Netherlands", calling_code: "+599" },
62
+ "BR": { name: "🇧🇷 Brazil", calling_code: "+55" },
63
+ "BS": { name: "🇧🇸 Bahamas", calling_code: "+1-242" },
64
+ "BT": { name: "🇧🇹 Bhutan", calling_code: "+975" },
65
+ "BV": { name: "🇧🇻 Bouvet Island", calling_code: "+47" },
66
+ "BW": { name: "🇧🇼 Botswana", calling_code: "+267" },
67
+ "BY": { name: "🇧🇾 Belarus", calling_code: "+375" },
68
+ "BZ": { name: "🇧🇿 Belize", calling_code: "+501" },
69
+ "CA": { name: "🇨🇦 Canada", calling_code: "+1" },
70
+ "CC": { name: "🇨🇨 Cocos (Keeling) Islands", calling_code: "+61" },
71
+ "CD": { name: "🇨🇩 Congo (DRC)", calling_code: "+243" },
72
+ "CF": { name: "🇨🇫 Central African Republic", calling_code: "+236" },
73
+ "CG": { name: "🇨🇬 Congo (Republic)", calling_code: "+242" },
74
+ "CH": { name: "🇨🇭 Switzerland", calling_code: "+41" },
75
+ "CI": { name: "🇨🇮 Côte d'Ivoire", calling_code: "+225" },
76
+ "CK": { name: "🇨🇰 Cook Islands", calling_code: "+682" },
77
+ "CL": { name: "🇨🇱 Chile", calling_code: "+56" },
78
+ "CM": { name: "🇨🇲 Cameroon", calling_code: "+237" },
79
+ "CN": { name: "🇨🇳 China", calling_code: "+86" },
80
+ "CO": { name: "🇨🇴 Colombia", calling_code: "+57" },
81
+ "CR": { name: "🇨🇷 Costa Rica", calling_code: "+506" },
82
+ "CU": { name: "🇨🇺 Cuba", calling_code: "+53" },
83
+ "CV": { name: "🇨🇻 Cape Verde", calling_code: "+238" },
84
+ "CW": { name: "🇨🇼 Curaçao", calling_code: "+599" },
85
+ "CX": { name: "🇨🇽 Christmas Island", calling_code: "+61" },
86
+ "CY": { name: "🇨🇾 Cyprus", calling_code: "+357" },
87
+ "CZ": { name: "🇨🇿 Czech Republic", calling_code: "+420" },
88
+ "DE": { name: "🇩🇪 Germany", calling_code: "+49" },
89
+ "DJ": { name: "🇩🇯 Djibouti", calling_code: "+253" },
90
+ "DK": { name: "🇩🇰 Denmark", calling_code: "+45" },
91
+ "DM": { name: "🇩🇲 Dominica", calling_code: "+1-767" },
92
+ "DO": { name: "🇩🇴 Dominican Republic", calling_code: "+1-809" },
93
+ "DZ": { name: "🇩🇿 Algeria", calling_code: "+213" },
94
+ "EC": { name: "🇪🇨 Ecuador", calling_code: "+593" },
95
+ "EE": { name: "🇪🇪 Estonia", calling_code: "+372" },
96
+ "EG": { name: "🇪🇬 Egypt", calling_code: "+20" },
97
+ "EH": { name: "🇪🇭 Western Sahara", calling_code: "+212" },
98
+ "ER": { name: "🇪🇷 Eritrea", calling_code: "+291" },
99
+ "ES": { name: "🇪🇸 Spain", calling_code: "+34" },
100
+ "ET": { name: "🇪🇹 Ethiopia", calling_code: "+251" },
101
+ "FI": { name: "🇫🇮 Finland", calling_code: "+358" },
102
+ "FJ": { name: "🇫🇯 Fiji", calling_code: "+679" },
103
+ "FK": { name: "🇫🇰 Falkland Islands (Malvinas)", calling_code: "+500" },
104
+ "FM": { name: "🇫🇲 Micronesia", calling_code: "+691" },
105
+ "FO": { name: "🇫🇴 Faroe Islands", calling_code: "+298" },
106
+ "FR": { name: "🇫🇷 France", calling_code: "+33" },
107
+ "GA": { name: "🇬🇦 Gabon", calling_code: "+241" },
108
+ "GB": { name: "🇬🇧 United Kingdom", calling_code: "+44" },
109
+ "GD": { name: "🇬🇩 Grenada", calling_code: "+1-473" },
110
+ "GE": { name: "🇬🇪 Georgia", calling_code: "+995" },
111
+ "GF": { name: "🇬🇫 French Guiana", calling_code: "+594" },
112
+ "GG": { name: "🇬🇬 Guernsey", calling_code: "+44" },
113
+ "GH": { name: "🇬🇭 Ghana", calling_code: "+233" },
114
+ "GI": { name: "🇬🇮 Gibraltar", calling_code: "+350" },
115
+ "GL": { name: "🇬🇱 Greenland", calling_code: "+299" },
116
+ "GM": { name: "🇬🇲 Gambia", calling_code: "+220" },
117
+ "GN": { name: "🇬🇳 Guinea", calling_code: "+224" },
118
+ "GP": { name: "🇬🇵 Guadeloupe", calling_code: "+590" },
119
+ "GQ": { name: "🇬🇶 Equatorial Guinea", calling_code: "+240" },
120
+ "GR": { name: "🇬🇷 Greece", calling_code: "+30" },
121
+ "GS": { name: "🇬🇸 South Georgia and the South Sandwich Islands", calling_code: "+500" },
122
+ "GT": { name: "🇬🇹 Guatemala", calling_code: "+502" },
123
+ "GU": { name: "🇬🇺 Guam", calling_code: "+1-671" },
124
+ "GW": { name: "🇬🇼 Guinea-Bissau", calling_code: "+245" },
125
+ "GY": { name: "🇬🇾 Guyana", calling_code: "+592" },
126
+ "HK": { name: "🇭🇰 Hong Kong", calling_code: "+852" },
127
+ "HM": { name: "🇭🇲 Heard Island and McDonald Islands", calling_code: "+672" },
128
+ "HN": { name: "🇭🇳 Honduras", calling_code: "+504" },
129
+ "HR": { name: "🇭🇷 Croatia", calling_code: "+385" },
130
+ "HT": { name: "🇭🇹 Haiti", calling_code: "+509" },
131
+ "HU": { name: "🇭🇺 Hungary", calling_code: "+36" },
132
+ "ID": { name: "🇮🇩 Indonesia", calling_code: "+62" },
133
+ "IE": { name: "🇮🇪 Ireland", calling_code: "+353" },
134
+ "IL": { name: "🇮🇱 Israel", calling_code: "+972" },
135
+ "IM": { name: "🇮🇲 Isle of Man", calling_code: "+44" },
136
+ "IN": { name: "🇮🇳 India", calling_code: "+91" },
137
+ "IO": { name: "🇮🇴 British Indian Ocean Territory", calling_code: "+246" },
138
+ "IQ": { name: "🇮🇶 Iraq", calling_code: "+964" },
139
+ "IR": { name: "🇮🇷 Iran", calling_code: "+98" },
140
+ "IS": { name: "🇮🇸 Iceland", calling_code: "+354" },
141
+ "IT": { name: "🇮🇹 Italy", calling_code: "+39" },
142
+ "JE": { name: "🇯🇪 Jersey", calling_code: "+44" },
143
+ "JM": { name: "🇯🇲 Jamaica", calling_code: "+1-876" },
144
+ "JO": { name: "🇯🇴 Jordan", calling_code: "+962" },
145
+ "JP": { name: "🇯🇵 Japan", calling_code: "+81" },
146
+ "KE": { name: "🇰🇪 Kenya", calling_code: "+254" },
147
+ "KG": { name: "🇰🇬 Kyrgyzstan", calling_code: "+996" },
148
+ "KH": { name: "🇰🇭 Cambodia", calling_code: "+855" },
149
+ "KI": { name: "🇰🇮 Kiribati", calling_code: "+686" },
150
+ "KM": { name: "🇰🇲 Comoros", calling_code: "+269" },
151
+ "KN": { name: "🇰🇳 Saint Kitts and Nevis", calling_code: "+1-869" },
152
+ "KP": { name: "🇰🇵 North Korea", calling_code: "+850" },
153
+ "KR": { name: "🇰🇷 South Korea", calling_code: "+82" },
154
+ "KW": { name: "🇰🇼 Kuwait", calling_code: "+965" },
155
+ "KY": { name: "🇰🇾 Cayman Islands", calling_code: "+1-345" },
156
+ "KZ": { name: "🇰🇿 Kazakhstan", calling_code: "+7" },
157
+ "LA": { name: "🇱🇦 Laos", calling_code: "+856" },
158
+ "LB": { name: "🇱🇧 Lebanon", calling_code: "+961" },
159
+ "LC": { name: "🇱🇨 Saint Lucia", calling_code: "+1-758" },
160
+ "LI": { name: "🇱🇮 Liechtenstein", calling_code: "+423" },
161
+ "LK": { name: "🇱🇰 Sri Lanka", calling_code: "+94" },
162
+ "LR": { name: "🇱🇷 Liberia", calling_code: "+231" },
163
+ "LS": { name: "🇱🇸 Lesotho", calling_code: "+266" },
164
+ "LT": { name: "🇱🇹 Lithuania", calling_code: "+370" },
165
+ "LU": { name: "🇱🇺 Luxembourg", calling_code: "+352" },
166
+ "LV": { name: "🇱🇻 Latvia", calling_code: "+371" },
167
+ "LY": { name: "🇱🇾 Libya", calling_code: "+218" },
168
+ "MA": { name: "🇲🇦 Morocco", calling_code: "+212" },
169
+ "MC": { name: "🇲🇨 Monaco", calling_code: "+377" },
170
+ "MD": { name: "🇲🇩 Moldova", calling_code: "+373" },
171
+ "ME": { name: "🇲🇪 Montenegro", calling_code: "+382" },
172
+ "MF": { name: "🇲🇫 Saint Martin", calling_code: "+590" },
173
+ "MG": { name: "🇲🇬 Madagascar", calling_code: "+261" },
174
+ "MH": { name: "🇲🇭 Marshall Islands", calling_code: "+692" },
175
+ "MK": { name: "🇲🇰 North Macedonia", calling_code: "+389" },
176
+ "ML": { name: "🇲🇱 Mali", calling_code: "+223" },
177
+ "MM": { name: "🇲🇲 Myanmar (Burma)", calling_code: "+95" },
178
+ "MN": { name: "🇲🇳 Mongolia", calling_code: "+976" },
179
+ "MO": { name: "🇲🇴 Macao", calling_code: "+853" },
180
+ "MP": { name: "🇲🇵 Northern Mariana Islands", calling_code: "+1-670" },
181
+ "MQ": { name: "🇲🇶 Martinique", calling_code: "+596" },
182
+ "MR": { name: "🇲🇷 Mauritania", calling_code: "+222" },
183
+ "MS": { name: "🇲🇸 Montserrat", calling_code: "+1-664" },
184
+ "MT": { name: "🇲🇹 Malta", calling_code: "+356" },
185
+ "MU": { name: "🇲🇺 Mauritius", calling_code: "+230" },
186
+ "MV": { name: "🇲🇻 Maldives", calling_code: "+960" },
187
+ "MW": { name: "🇲🇼 Malawi", calling_code: "+265" },
188
+ "MX": { name: "🇲🇽 Mexico", calling_code: "+52" },
189
+ "MY": { name: "🇲🇾 Malaysia", calling_code: "+60" },
190
+ "MZ": { name: "🇲🇿 Mozambique", calling_code: "+258" },
191
+ "NA": { name: "🇳🇦 Namibia", calling_code: "+264" },
192
+ "NC": { name: "🇳🇨 New Caledonia", calling_code: "+687" },
193
+ "NE": { name: "🇳🇪 Niger", calling_code: "+227" },
194
+ "NF": { name: "🇳🇫 Norfolk Island", calling_code: "+672" },
195
+ "NG": { name: "🇳🇬 Nigeria", calling_code: "+234" },
196
+ "NI": { name: "🇳🇮 Nicaragua", calling_code: "+505" },
197
+ "NL": { name: "🇳🇱 Netherlands", calling_code: "+31" },
198
+ "NO": { name: "🇳🇴 Norway", calling_code: "+47" },
199
+ "NP": { name: "🇳🇵 Nepal", calling_code: "+977" },
200
+ "NR": { name: "🇳🇷 Nauru", calling_code: "+674" },
201
+ "NU": { name: "🇳🇺 Niue", calling_code: "+683" },
202
+ "NZ": { name: "🇳🇿 New Zealand", calling_code: "+64" },
203
+ "OM": { name: "🇴🇲 Oman", calling_code: "+968" },
204
+ "PA": { name: "🇵🇦 Panama", calling_code: "+507" },
205
+ "PE": { name: "🇵🇪 Peru", calling_code: "+51" },
206
+ "PF": { name: "🇵🇫 French Polynesia", calling_code: "+689" },
207
+ "PG": { name: "🇵🇬 Papua New Guinea", calling_code: "+675" },
208
+ "PH": { name: "🇵🇭 Philippines", calling_code: "+63" },
209
+ "PK": { name: "🇵🇰 Pakistan", calling_code: "+92" },
210
+ "PL": { name: "🇵🇱 Poland", calling_code: "+48" },
211
+ "PM": { name: "🇵🇲 Saint Pierre and Miquelon", calling_code: "+508" },
212
+ "PN": { name: "🇵🇳 Pitcairn Islands", calling_code: "+64" },
213
+ "PR": { name: "🇵🇷 Puerto Rico", calling_code: "+1-787" },
214
+ "PS": { name: "🇵🇸 Palestine", calling_code: "+970" },
215
+ "PT": { name: "🇵🇹 Portugal", calling_code: "+351" },
216
+ "PW": { name: "🇵🇼 Palau", calling_code: "+680" },
217
+ "PY": { name: "🇵🇾 Paraguay", calling_code: "+595" },
218
+ "QA": { name: "🇶🇦 Qatar", calling_code: "+974" },
219
+ "RE": { name: "🇷🇪 Réunion", calling_code: "+262" },
220
+ "RO": { name: "🇷🇴 Romania", calling_code: "+40" },
221
+ "RS": { name: "🇷🇸 Serbia", calling_code: "+381" },
222
+ "RU": { name: "🇷🇺 Russia", calling_code: "+7" },
223
+ "RW": { name: "🇷🇼 Rwanda", calling_code: "+250" },
224
+ "SA": { name: "🇸🇦 Saudi Arabia", calling_code: "+966" },
225
+ "SB": { name: "🇸🇧 Solomon Islands", calling_code: "+677" },
226
+ "SC": { name: "🇸🇨 Seychelles", calling_code: "+248" },
227
+ "SD": { name: "🇸🇩 Sudan", calling_code: "+249" },
228
+ "SE": { name: "🇸🇪 Sweden", calling_code: "+46" },
229
+ "SG": { name: "🇸🇬 Singapore", calling_code: "+65" },
230
+ "SH": { name: "🇸🇭 Saint Helena, Ascension and Tristan da Cunha", calling_code: "+290" },
231
+ "SI": { name: "🇸🇮 Slovenia", calling_code: "+386" },
232
+ "SJ": { name: "🇸🇯 Svalbard and Jan Mayen", calling_code: "+47" },
233
+ "SK": { name: "🇸🇰 Slovakia", calling_code: "+421" },
234
+ "SL": { name: "🇸🇱 Sierra Leone", calling_code: "+232" },
235
+ "SM": { name: "🇸🇲 San Marino", calling_code: "+378" },
236
+ "SN": { name: "🇸🇳 Senegal", calling_code: "+221" },
237
+ "SO": { name: "🇸🇴 Somalia", calling_code: "+252" },
238
+ "SR": { name: "🇸🇷 Suriname", calling_code: "+597" },
239
+ "SS": { name: "🇸🇸 South Sudan", calling_code: "+211" },
240
+ "ST": { name: "🇸🇹 São Tomé and Príncipe", calling_code: "+239" },
241
+ "SV": { name: "🇸🇻 El Salvador", calling_code: "+503" },
242
+ "SX": { name: "🇸🇽 Sint Maarten", calling_code: "+1-721" },
243
+ "SY": { name: "🇸🇾 Syria", calling_code: "+963" },
244
+ "SZ": { name: "🇸🇿 Eswatini", calling_code: "+268" },
245
+ "TC": { name: "🇹🇨 Turks and Caicos Islands", calling_code: "+1-649" },
246
+ "TD": { name: "🇹🇩 Chad", calling_code: "+235" },
247
+ "TF": { name: "🇹🇫 French Southern and Antarctic Lands", calling_code: "+262" },
248
+ "TG": { name: "🇹🇬 Togo", calling_code: "+228" },
249
+ "TH": { name: "🇹🇭 Thailand", calling_code: "+66" },
250
+ "TJ": { name: "🇹🇯 Tajikistan", calling_code: "+992" },
251
+ "TK": { name: "🇹🇰 Tokelau", calling_code: "+690" },
252
+ "TL": { name: "🇹🇱 Timor-Leste", calling_code: "+670" },
253
+ "TM": { name: "🇹🇲 Turkmenistan", calling_code: "+993" },
254
+ "TN": { name: "🇹🇳 Tunisia", calling_code: "+216" },
255
+ "TO": { name: "🇹🇴 Tonga", calling_code: "+676" },
256
+ "TR": { name: "🇹🇷 Turkey", calling_code: "+90" },
257
+ "TT": { name: "🇹🇹 Trinidad and Tobago", calling_code: "+1-868" },
258
+ "TV": { name: "🇹🇻 Tuvalu", calling_code: "+688" },
259
+ "TW": { name: "🇹🇼 Taiwan", calling_code: "+886" },
260
+ "TZ": { name: "🇹🇿 Tanzania", calling_code: "+255" },
261
+ "UA": { name: "🇺🇦 Ukraine", calling_code: "+380" },
262
+ "UG": { name: "🇺🇬 Uganda", calling_code: "+256" },
263
+ "UM": { name: "🇺🇲 U.S. Minor Outlying Islands", calling_code: "+1" },
264
+ "US": { name: "🇺🇸 United States", calling_code: "+1" },
265
+ "UY": { name: "🇺🇾 Uruguay", calling_code: "+598" },
266
+ "UZ": { name: "🇺🇿 Uzbekistan", calling_code: "+998" },
267
+ "VA": { name: "🇻🇦 Vatican City", calling_code: "+379" },
268
+ "VC": { name: "🇻🇨 Saint Vincent and the Grenadines", calling_code: "+1-784" },
269
+ "VE": { name: "🇻🇪 Venezuela", calling_code: "+58" },
270
+ "VG": { name: "🇻🇬 British Virgin Islands", calling_code: "+1-284" },
271
+ "VI": { name: "🇻🇮 U.S. Virgin Islands", calling_code: "+1-340" },
272
+ "VN": { name: "🇻🇳 Vietnam", calling_code: "+84" },
273
+ "VU": { name: "🇻🇺 Vanuatu", calling_code: "+678" },
274
+ "WF": { name: "🇼🇫 Wallis and Futuna", calling_code: "+681" },
275
+ "WS": { name: "🇼🇸 Samoa", calling_code: "+685" },
276
+ "YE": { name: "🇾🇪 Yemen", calling_code: "+967" },
277
+ "YT": { name: "🇾🇹 Mayotte", calling_code: "+262" },
278
+ "ZA": { name: "🇿🇦 South Africa", calling_code: "+27" },
279
+ "ZM": { name: "🇿🇲 Zambia", calling_code: "+260" },
280
+ "ZW": { name: "🇿🇼 Zimbabwe", calling_code: "+263" }
281
+ },
282
+ _paddle_initialized: false,
283
+ _payment_element: undefined, // Replace 'any' with the actual type if known.
284
+ _sign_in_redirect: undefined,
285
+ _step: 0,
286
+ _steps_element: undefined,
287
+ _steps_container: undefined,
288
+ _overview_container: undefined,
289
+ _order_container: undefined,
290
+ _billing_container: undefined,
291
+ _payment_container: undefined,
292
+ _processing_container: undefined,
293
+ _checkout_button: undefined,
294
+ _prev_step_button: undefined,
295
+ _style: undefined,
296
+ _currency_symbol: undefined,
297
+ _render_payment_element_reject: undefined,
298
+ _render_payment_element_resolve: undefined,
299
+ _refunds_element: undefined,
300
+ _refunds_container: undefined,
301
+ _processing_element: undefined,
302
+ _theme: undefined,
303
+ _products: undefined,
304
+ _days_refundable: 30, // **Added Property**
305
+ on_error: (data) => { },
306
+ // Additional properties that might be inferred from function bodies:
307
+ _refund_policy: undefined, // Used in commented code
308
+ _cancellation_policy: undefined, // Used in commented code
309
+ // cart: {
310
+ // items: [] as any[], // Replace 'any' with the actual item type.
311
+ // refresh: function() { /* Implement refresh logic */ },
312
+ // save: function() { /* Implement save logic */ },
313
+ // add: async function(productId: string, quantity: number) { /* Implement add logic */ },
314
+ // remove: async function(productId: string, quantity: number | "all") { /* Implement remove logic */ },
315
+ // },
316
+ _billing_element: undefined, // Replace 'any' with the actual type if known.
317
+ _billing_details: undefined, // Replace 'any' with the actual type if known.
318
+ _overview_subtotal: undefined, // Replace 'any' with the actual type if known.
319
+ _overview_total: undefined, // Replace 'any' with the actual type if known.
320
+ _overview_subtotal_tax: undefined, // Replace 'any' with the actual type if known.
321
+ _overview_tax_container: undefined, // Replace 'any' with the actual type if known.
322
+ _overview_incl_excl_tax: undefined, // Replace 'any' with the actual type if known.
323
+ _overview_element: undefined, // Replace 'any' with the actual type if known.
324
+ _order_element: undefined, // Replace 'any' with the actual type if known.
325
+ // ---------------------------------------------------------
326
+ // Private Methods.
327
+ /**
328
+ * Initialize Paddle with the provided client key and set up event callbacks.
329
+ */
330
+ _initialize_paddle: function () {
331
+ if (this._paddle_initialized !== true) {
332
+ if (this.sandbox) {
333
+ Paddle.Environment.set("sandbox");
334
+ }
335
+ Paddle.Setup({
336
+ token: this.client_key,
337
+ eventCallback: (data) => {
338
+ if (data.name === "checkout.loaded") {
339
+ this._render_payment_element_resolve();
340
+ }
341
+ else if (data.name === "checkout.completed") {
342
+ this._show_processing("success");
343
+ }
344
+ else if (data.name === "checkout.payment.initiated") {
345
+ // Uncomment and implement if needed.
346
+ // this._show_processing("processing");
347
+ }
348
+ else if (data.name === "checkout.payment.failed") {
349
+ this._show_processing("error");
350
+ }
351
+ else if (data.type === "checkout.error") {
352
+ if (data.error?.detail) {
353
+ console.error(data);
354
+ this.on_error(data.error.detail);
355
+ }
356
+ else {
357
+ console.error(data);
358
+ this.on_error(new Error("Unknown error"));
359
+ }
360
+ this._render_payment_element_reject(data.detail.split("|")[0]);
361
+ }
362
+ else if (data.type === "checkout.warning") {
363
+ if (this.sandbox) {
364
+ console.log("Checkout warning:", data);
365
+ }
366
+ }
367
+ else {
368
+ // Handle other events if necessary.
369
+ // Uncomment for debugging.
370
+ // if (this.sandbox) {
371
+ // console.log("Event", data);
372
+ // }
373
+ }
374
+ }
375
+ });
376
+ this._paddle_initialized = true;
377
+ }
378
+ },
379
+ /**
380
+ * Reset the payment element by removing it if it exists.
381
+ */
382
+ _reset: function () {
383
+ if (this._payment_element !== undefined) {
384
+ this._payment_element.remove();
385
+ }
386
+ this._payment_element = undefined;
387
+ },
388
+ /**
389
+ * Initialize the order by verifying authentication and making a POST request.
390
+ */
391
+ _init_order: async function () {
392
+ try {
393
+ if (this._sign_in_redirect != null && !User.is_authenticated()) {
394
+ Utils.redirect(this._sign_in_redirect);
395
+ }
396
+ const response = await Utils.request({
397
+ method: "POST",
398
+ url: "/volt/payments/init",
399
+ data: {
400
+ items: this.cart.items,
401
+ }
402
+ });
403
+ // Handle response if necessary.
404
+ }
405
+ catch (err) {
406
+ if (typeof err === "object" && err.error != null) {
407
+ err = err.error;
408
+ }
409
+ throw new Error(err);
410
+ }
411
+ },
412
+ /**
413
+ * Set the current step in the payment process.
414
+ */
415
+ _set_step: async function () {
416
+ // Switch step.
417
+ switch (this._step) {
418
+ // Order.
419
+ case 0: {
420
+ // Select the current step.
421
+ this._steps_element.select(this._step);
422
+ // Show and hide relevant containers.
423
+ this._overview_container.show();
424
+ this._order_container.show();
425
+ this._billing_container.hide();
426
+ this._payment_container.hide();
427
+ this._processing_container.hide();
428
+ this._checkout_button.nodes.text.text("Next");
429
+ // this._policy_checkbox.hide();
430
+ this._prev_step_button.hide();
431
+ break;
432
+ }
433
+ // Address.
434
+ case 1: {
435
+ // Minimum duration for the loader.
436
+ const min_duration = new Promise(resolve => setTimeout(resolve, 350));
437
+ // Verify the order.
438
+ try {
439
+ await this._init_order();
440
+ }
441
+ catch (err) {
442
+ --this._step;
443
+ console.error(err);
444
+ this.on_error(err);
445
+ return null;
446
+ }
447
+ // Render billing element.
448
+ this._render_billing_element();
449
+ // Await minimum duration.
450
+ await min_duration;
451
+ // Select the current step.
452
+ this._steps_element.select(this._step);
453
+ // Show and hide relevant containers.
454
+ this._overview_container.show();
455
+ this._order_container.hide();
456
+ this._billing_container.show();
457
+ this._payment_container.hide();
458
+ this._processing_container.hide();
459
+ this._checkout_button.nodes.text.text("Next");
460
+ // this._policy_checkbox.hide();
461
+ this._prev_step_button.show();
462
+ break;
463
+ }
464
+ // Payment.
465
+ case 2: {
466
+ // Check if the billing details are entered correctly.
467
+ try {
468
+ this._billing_details = this._billing_element.data();
469
+ this._billing_details.phone_number = this._billing_details.phone_country_code + this._billing_details.phone_number;
470
+ delete this._billing_details.phone_country_code;
471
+ }
472
+ catch (error) {
473
+ --this._step;
474
+ console.error(error);
475
+ this.on_error(error);
476
+ return null;
477
+ }
478
+ // Render payment element.
479
+ try {
480
+ await this._render_payment_element();
481
+ }
482
+ catch (error) {
483
+ --this._step;
484
+ console.error(error);
485
+ this.on_error(error);
486
+ return null;
487
+ }
488
+ // Select the current step.
489
+ this._steps_element.select(this._step);
490
+ // Show and hide relevant containers.
491
+ this._overview_container.hide();
492
+ this._order_container.hide();
493
+ this._billing_container.hide();
494
+ this._payment_container.show();
495
+ this._processing_container.hide();
496
+ this._checkout_button.nodes.text.text("Checkout");
497
+ // this._policy_checkbox.show();
498
+ this._prev_step_button.show();
499
+ break;
500
+ }
501
+ }
502
+ },
503
+ /**
504
+ * Navigate to the next step in the payment process.
505
+ */
506
+ _next: async function () {
507
+ if (this._step < 3) {
508
+ ++this._step;
509
+ return this._set_step();
510
+ }
511
+ else if (this._step === 3) {
512
+ return this._set_step();
513
+ }
514
+ },
515
+ /**
516
+ * Navigate to the previous step in the payment process.
517
+ */
518
+ _prev: async function () {
519
+ if (this._step > 0) {
520
+ --this._step;
521
+ return this._set_step();
522
+ }
523
+ },
524
+ /**
525
+ * Render the steps element in the UI.
526
+ */
527
+ _render_steps_element: function () {
528
+ // Shortcuts.
529
+ const style = this._style;
530
+ // The previous step button.
531
+ this._prev_step_button = HStack(ImageMask("/volt_static/payments/arrow.long.webp")
532
+ .frame(15, 15)
533
+ .mask_color(this._style.fg_1)
534
+ .transition_mask("background 300ms ease-in-out")
535
+ .transform("rotate(180deg)")
536
+ .margin_right(10), Text("Previous Step")
537
+ .color(this._style.fg_1)
538
+ .transition("color 300ms ease-in-out")
539
+ .padding(0)
540
+ .margin(0)
541
+ .font_size(14))
542
+ .hide()
543
+ .on_mouse_over_out((e) => {
544
+ e.child(0).color(this._style.fg);
545
+ e.child(1).color(this._style.fg);
546
+ }, (e) => {
547
+ e.child(0).color(this._style.fg_1);
548
+ e.child(1).color(this._style.fg_1);
549
+ })
550
+ .on_click(() => {
551
+ this._prev()
552
+ .catch((err) => console.error(err));
553
+ })
554
+ .center_vertical();
555
+ // The steps element.
556
+ this._steps_element = HStack(ForEach(["Order Details", "Billing Details", "Payment Details", "Processing Details"], (item, index) => {
557
+ const stack = HStack(VStack((index + 1).toString())
558
+ .font_size(11)
559
+ .padding(0)
560
+ .margin(0)
561
+ .color(index === 0 ? this._style.selected.fg : this._style.fg_1)
562
+ .frame(17.5, 17.5)
563
+ .background(index === 0 ? this._style.selected.bg : this._style.bg_1)
564
+ .transition("color 300ms ease-in-out, background 300ms ease-in-out")
565
+ .border_radius("50%")
566
+ .margin_right(15)
567
+ .flex_shrink(0)
568
+ .center()
569
+ .center_vertical()
570
+ .border(1, this._style.divider_bg), Text(item)
571
+ .color(index === 0 ? this._style.fg : this._style.fg_1)
572
+ .transition("color 300ms ease-in-out")
573
+ .padding(0)
574
+ .font_size(14)
575
+ .line_height(16))
576
+ .center_vertical()
577
+ .margin_right(25);
578
+ return stack;
579
+ }), Spacer().min_frame(10, 1), this._prev_step_button)
580
+ .overflow_x("scroll")
581
+ .class("hide_scrollbar")
582
+ .extend({
583
+ selected_index: 0,
584
+ /**
585
+ * Select the current step index and update UI accordingly.
586
+ * @param index - The index of the step to select.
587
+ */
588
+ select(index) {
589
+ let e = this.child(this.selected_index);
590
+ e.child(0)
591
+ .color(style.fg_1)
592
+ .background(style.bg_1);
593
+ e.child(1)
594
+ .color(style.fg_1);
595
+ this.selected_index = index;
596
+ e = this.child(this.selected_index);
597
+ e.child(0)
598
+ .color(style.selected.fg)
599
+ .background(style.selected.bg);
600
+ e.child(1)
601
+ .color(style.fg);
602
+ return this;
603
+ },
604
+ });
605
+ // Append the steps element to the steps container.
606
+ this._steps_container.append(this._steps_element);
607
+ },
608
+ /**
609
+ * Render the overview element in the UI.
610
+ */
611
+ _render_overview_element: function () {
612
+ // The subtotal price from the overview.
613
+ this._overview_subtotal = Text(`${this._currency_symbol == null ? "$" : this._currency_symbol} 0.00`)
614
+ .color(this._style.fg)
615
+ .font_size(this._style.font_size)
616
+ .flex_shrink(0)
617
+ .margin(0)
618
+ .padding(0);
619
+ // The total price from the overview.
620
+ this._overview_total = Text(`${this._currency_symbol == null ? "$" : this._currency_symbol} 0.00`)
621
+ .font_weight("bold")
622
+ .color(this._style.fg)
623
+ .font_size(this._style.font_size)
624
+ .flex_shrink(0)
625
+ .margin(0)
626
+ .padding(0);
627
+ // The subtotal VAT price from the overview.
628
+ this._overview_subtotal_tax = Text(`${this._currency_symbol == null ? "$" : this._currency_symbol} 0.00`)
629
+ .color(this._style.fg)
630
+ .font_size(this._style.font_size)
631
+ .flex_shrink(0)
632
+ .margin(0)
633
+ .padding(0);
634
+ // The tax stack.
635
+ this._overview_tax_container = HStack(Text("Tax:")
636
+ .color(this._style.fg)
637
+ .font_size(this._style.font_size)
638
+ .stretch(true)
639
+ .flex_shrink(0)
640
+ .margin(0, 5, 0, 0)
641
+ .padding(0)
642
+ .wrap(false)
643
+ .overflow("hidden")
644
+ .text_overflow("ellipsis"), this._overview_subtotal_tax)
645
+ .margin_top(5);
646
+ // The incl/excl tax text.
647
+ this._overview_incl_excl_tax = Text(this.tax_inclusive ? "incl. tax" : "excl. tax")
648
+ .color(this._style.fg_2)
649
+ .font_size(this._style.font_size - 6)
650
+ .margin(2.5, 0, 0, 0)
651
+ .padding(0)
652
+ .flex_shrink(0)
653
+ .text_trailing();
654
+ // The checkout button.
655
+ this._checkout_button = LoaderButton("Next")
656
+ .color(this._style.button.fg)
657
+ .background(this._style.button.bg)
658
+ .border_radius(this._style.button.border_radius)
659
+ .border(this._style.button.border_inset ? `${this._style.button.border_width} inset ${this._style.button.border_color}` : `${this._style.button.border_width} solid ${this._style.button.border_color}`)
660
+ .hover_brightness(...this._style.button.hover_brightness)
661
+ .nodes.loader
662
+ .background(this._style.button.fg)
663
+ .update()
664
+ .parent()
665
+ .on_click(async () => {
666
+ this._checkout_button.show_loader();
667
+ Payments._next()
668
+ .then(() => {
669
+ this._checkout_button.hide_loader();
670
+ })
671
+ .catch((err) => {
672
+ console.error(err);
673
+ this._checkout_button.hide_loader();
674
+ });
675
+ });
676
+ // Accept agreements (currently commented out).
677
+ // this._policy_checkbox = CheckBox({
678
+ // text: "I agree to the Terms and Conditions and the " +
679
+ // Link("Refund", this._refund_policy) +
680
+ // " and " +
681
+ // Link("Cancellation", this._cancellation_policy) +
682
+ // " policy. I agree that my payment method may be used for recurring subscriptions.",
683
+ // required: true
684
+ // }) // @todo check text.
685
+ // .color(this._style.fg_2)
686
+ // .border_color(this._style.divider_bg)
687
+ // .font_size(this._style.font_size - 6)
688
+ // .focus_color(this._style.theme_fg)
689
+ // .missing_color(this._style.missing_fg)
690
+ // .inner_bg(this._style.bg)
691
+ // .margin_bottom(15)
692
+ // .hide();
693
+ // The overview element.
694
+ this._overview_element = VStack(Title("Overview")
695
+ .color(this._style.fg)
696
+ .width("fit-content")
697
+ .font_size(this._style.font_size - 2)
698
+ .flex_shrink(0)
699
+ .margin(0, 0, 15, 0)
700
+ .letter_spacing("1px")
701
+ .text_transform("uppercase")
702
+ .ellipsis_overflow(true), HStack(Text("Subtotal:")
703
+ .color(this._style.fg)
704
+ .font_size(this._style.font_size)
705
+ .stretch(true)
706
+ .flex_shrink(0)
707
+ .margin(0, 5, 0, 0)
708
+ .padding(0)
709
+ .wrap(false)
710
+ .overflow("hidden")
711
+ .text_overflow("ellipsis"), this._overview_subtotal),
712
+ // Uncomment and define Shipping if needed.
713
+ // HStack(
714
+ // Text("Shipping:")
715
+ // .color(this._style.fg_1)
716
+ // .font_size(this._style.font_size)
717
+ // .stretch(true)
718
+ // .flex_shrink(0)
719
+ // .margin(0, 5, 0, 0)
720
+ // .padding(0)
721
+ // .wrap(false)
722
+ // .overflow("hidden")
723
+ // .text_overflow("ellipsis"),
724
+ // Text("free")
725
+ // .color(this._style.fg_1)
726
+ // .font_size(this._style.font_size)
727
+ // .flex_shrink(0)
728
+ // .margin(0)
729
+ // .padding(0)
730
+ // .wrap(false)
731
+ // .overflow("hidden")
732
+ // .text_overflow("ellipsis"),
733
+ // )
734
+ // .margin_top(5),
735
+ this._overview_tax_container, Divider()
736
+ .margin(20, 0, 20, 0)
737
+ .background(this._style.divider_bg), HStack(Text("Total:")
738
+ .font_weight("bold")
739
+ .color(this._style.fg)
740
+ .font_size(this._style.font_size)
741
+ .stretch(true)
742
+ .flex_shrink(0)
743
+ .margin(0, 5, 0, 0)
744
+ .padding(0)
745
+ .wrap(false)
746
+ .overflow("hidden")
747
+ .text_overflow("ellipsis"), VStack(this._overview_total, this._overview_incl_excl_tax))
748
+ .margin_bottom(25),
749
+ // this._policy_checkbox,
750
+ this._checkout_button)
751
+ .extend({
752
+ total: 0,
753
+ tax: 0,
754
+ /**
755
+ * Handle unknown tax scenarios by updating the UI accordingly.
756
+ */
757
+ unknown_tax: () => {
758
+ this._overview_incl_excl_tax.text(this.tax_inclusive ? "incl. tax" : "excl. tax");
759
+ this._overview_tax_container.hide();
760
+ this._overview_element.tax = 0;
761
+ this._overview_total.text(`${this._currency_symbol} ${this._overview_element.total.toFixed(2)}`);
762
+ },
763
+ /**
764
+ * Calculate tax based on the provided country code.
765
+ * @param country - The country code to calculate tax for.
766
+ */
767
+ calc_tax: async (country) => {
768
+ this._initialize_paddle();
769
+ try {
770
+ const result = await Paddle.PricePreview({
771
+ items: this.cart.items.map((item) => {
772
+ return { priceId: item.product.price_id, quantity: item.quantity };
773
+ }),
774
+ address: { countryCode: country },
775
+ });
776
+ this._overview_element.tax = 0;
777
+ result.data.details.lineItems.forEach((item) => {
778
+ this._overview_element.tax += parseInt(item.totals.tax) / 100;
779
+ });
780
+ this._overview_tax_container.show();
781
+ this._overview_incl_excl_tax.text("incl. tax");
782
+ this._overview_subtotal_tax.text(`${this._currency_symbol} ${this._overview_element.tax.toFixed(2)}`);
783
+ this._overview_total.text(`${this._currency_symbol} ${(this._overview_element.total + this._overview_element.tax).toFixed(2)}`);
784
+ }
785
+ catch (error) {
786
+ if (error?.error?.detail) {
787
+ this.on_error(error.error.detail);
788
+ console.error(error);
789
+ }
790
+ else {
791
+ console.error(error);
792
+ }
793
+ this._overview_element.unknown_tax();
794
+ }
795
+ },
796
+ });
797
+ // Append the overview element to the overview container.
798
+ this._overview_container.append(this._overview_element);
799
+ },
800
+ /**
801
+ * Render the order element in the UI.
802
+ */
803
+ _render_order_element: function () {
804
+ this._order_element = VStack()
805
+ .extend({
806
+ /**
807
+ * Refresh the order element by updating the cart and UI elements.
808
+ */
809
+ refresh() {
810
+ // Refresh the cart.
811
+ Payments.cart.refresh();
812
+ // Shortcuts.
813
+ const style = Payments._style;
814
+ const cart = Payments.cart;
815
+ const cart_items = Payments.cart.items;
816
+ // Shopping cart view.
817
+ let currency_symbol = null;
818
+ let subtotal = 0;
819
+ cart_items.forEach((item) => {
820
+ if (currency_symbol === null) {
821
+ currency_symbol = Payments.get_currency_symbol(item.product.currency);
822
+ }
823
+ subtotal += item.product.price * item.quantity;
824
+ });
825
+ if (currency_symbol === null) {
826
+ currency_symbol = "$";
827
+ }
828
+ Payments._currency_symbol = currency_symbol;
829
+ // Set the overview prices.
830
+ Payments._overview_subtotal.text(`${currency_symbol} ${subtotal.toFixed(2)}`);
831
+ Payments._overview_element.total = subtotal;
832
+ Payments._overview_element.unknown_tax();
833
+ // Add the products.
834
+ this.remove_children();
835
+ if (cart_items.length === 0) {
836
+ this.height(160);
837
+ this.append(VStack(Title("Empty Shopping Cart")
838
+ .color(style.fg_1)
839
+ .font_size(style.font_size - 2)
840
+ .flex_shrink(0)
841
+ .letter_spacing("1px")
842
+ .text_transform("uppercase")
843
+ .ellipsis_overflow(true)
844
+ .margin(0)
845
+ .padding(0)
846
+ .assign_to_parent_as("title_e"), Text(`Your shopping cart is empty.`)
847
+ .color(style.fg_2)
848
+ .font_size(style.font_size - 2)
849
+ .line_height(style.font_size)
850
+ .margin(5, 0, 0, 0)
851
+ .padding(0)
852
+ .assign_to_parent_as("text_e")
853
+ .white_space("pre")
854
+ .line_height("1.4em")
855
+ .center(), ImageMask("/volt_static/payments/shopping_cart.webp")
856
+ .frame(35, 35)
857
+ .margin_top(20)
858
+ .mask_color(style.theme_fg))
859
+ .frame("100%", "100%")
860
+ .center()
861
+ .center_vertical());
862
+ }
863
+ else {
864
+ // Uncomment and adjust height if necessary.
865
+ // this.height("100%");
866
+ this.append(Title("Order Details")
867
+ .color(style.fg)
868
+ .width("fit-content")
869
+ .font_size(style.font_size - 2)
870
+ .flex_shrink(0)
871
+ .margin(0, 0, 0, 0)
872
+ .letter_spacing("1px")
873
+ .text_transform("uppercase")
874
+ .ellipsis_overflow(true), Divider()
875
+ .background(style.divider_bg)
876
+ .margin(10, 0, 20, 0), ForEach(cart_items, (item, index) => {
877
+ let focus = false, mouse_over = false;
878
+ const quantity_input = Input("Quantity")
879
+ .value(item.quantity)
880
+ .font_size(16)
881
+ .color(style.fg_1)
882
+ .font_size(style.font_size - 2)
883
+ .border(1, style.divider_bg)
884
+ // .padding(12.5, 10, 12.5, 10)
885
+ .padding(2.5, 7.5)
886
+ .margin_right(25)
887
+ .flex_shrink(0)
888
+ .width(`calc(${item.quantity.toString().length}ch + 17.5px)`) // add padding.
889
+ .background(style.bg_1)
890
+ .display("inline")
891
+ .transition("color 300ms ease-in-out")
892
+ .center()
893
+ .on_input((_, event) => {
894
+ const value = quantity_input.value();
895
+ quantity_input.width(`calc(${value.length}ch + 17.5px)`); // add padding.
896
+ clearTimeout(quantity_input._timeout);
897
+ quantity_input._timeout = setTimeout(() => {
898
+ const quantity = parseInt(value);
899
+ if (isNaN(quantity)) {
900
+ console.error(`Specified quantity "${value}" is not a number.`);
901
+ Payments.on_error(new Error(`Specified quantity "${value}" is not a number.`));
902
+ quantity_input.value(item.quantity.toString());
903
+ return null;
904
+ }
905
+ item.quantity = quantity;
906
+ cart.save();
907
+ this.refresh();
908
+ }, 500);
909
+ })
910
+ .on_mouse_over_out((e) => {
911
+ e.color(style.fg);
912
+ mouse_over = true;
913
+ e.mask_color(style.fg);
914
+ }, (e) => {
915
+ mouse_over = false;
916
+ if (!mouse_over && !focus) {
917
+ e.color(style.fg_1);
918
+ }
919
+ })
920
+ .on_focus((e) => {
921
+ e.color(style.fg);
922
+ focus = true;
923
+ })
924
+ .on_blur((e) => {
925
+ focus = false;
926
+ if (!mouse_over && !focus) {
927
+ e.color(style.fg_1);
928
+ }
929
+ });
930
+ let per_item = " per item" + (Payments.tax_inclusive ? " incl. tax" : " excl. tax") + ",";
931
+ let renews_every = null;
932
+ if (item.product.interval) {
933
+ if (item.product.frequency === 1) {
934
+ renews_every = `renews ${item.product.interval}ly.`;
935
+ }
936
+ else {
937
+ renews_every = `renews every ${item.product.frequency} ${item.product.interval}s.`;
938
+ }
939
+ }
940
+ let trial_text = null;
941
+ if (item.product.trial) {
942
+ if (item.product.trial.frequency === 1) {
943
+ trial_text = `${item.product.trial.frequency} ${item.product.trial.interval} free`;
944
+ }
945
+ else {
946
+ trial_text = `${item.product.trial.frequency} ${item.product.trial.interval}s free`;
947
+ }
948
+ }
949
+ const stack = HStack(item.product.icon == null ? null :
950
+ ImageMask(item.product.icon)
951
+ .frame(30, 30)
952
+ .flex_shrink(0)
953
+ .margin(0, 25, 0, 0), VStack(Title(item.product.name)
954
+ .color(style.fg)
955
+ .font_size(style.font_size)
956
+ .margin(0, 10, 0, 0)
957
+ .padding(0)
958
+ .wrap(false)
959
+ .overflow("hidden")
960
+ .text_overflow("ellipsis"), Text(item.product.description)
961
+ .color(style.fg_1)
962
+ .font_size(style.font_size - 2)
963
+ .line_height(style.font_size)
964
+ .margin(10, 10, 0, 0)
965
+ .wrap(true)
966
+ .padding(0), HStack(Text("Quantity:")
967
+ .color(style.fg_1)
968
+ .font_size(style.font_size - 2)
969
+ // .line_height(style.font_size)
970
+ .margin(0, 10, 2, 0)
971
+ .padding(0)
972
+ .flex_shrink(0), quantity_input, ImageMask("/volt_static/payments/minus.webp")
973
+ .frame(20, 20)
974
+ .padding(5)
975
+ .margin_right(5)
976
+ .mask_color(style.fg_1)
977
+ .background(style.bg_1)
978
+ .border(1, style.divider_bg)
979
+ .border_radius("50%")
980
+ .flex_shrink(0)
981
+ .transition_mask("background 300ms ease-in-out")
982
+ .on_mouse_over_out((e) => e.mask_color(style.fg), (e) => e.mask_color(style.fg_1))
983
+ .on_click(async () => {
984
+ if (item.quantity === 1) {
985
+ await cart.remove(item.product.id, "all");
986
+ this.refresh();
987
+ }
988
+ else {
989
+ await cart.remove(item.product.id, 1);
990
+ this.refresh();
991
+ }
992
+ }), ImageMask("/volt_static/payments/plus.webp")
993
+ .frame(20, 20)
994
+ .padding(5)
995
+ .margin_right(5)
996
+ .mask_color(style.fg_1)
997
+ .background(style.bg_1)
998
+ .border(1, style.divider_bg)
999
+ .border_radius("50%")
1000
+ .flex_shrink(0)
1001
+ .transition_mask("background 300ms ease-in-out")
1002
+ .on_mouse_over_out((e) => e.mask_color(style.fg), (e) => e.mask_color(style.fg_1))
1003
+ .on_click(async () => {
1004
+ await cart.add(item.product.id, 1);
1005
+ this.refresh();
1006
+ }), ImageMask("/volt_static/payments/trash.webp")
1007
+ .frame(20, 20)
1008
+ .padding(5)
1009
+ .margin_right(5)
1010
+ .mask_color(style.fg_1)
1011
+ .background(style.bg_1)
1012
+ .border(1, style.divider_bg)
1013
+ .border_radius("50%")
1014
+ .flex_shrink(0)
1015
+ .transition_mask("background 300ms ease-in-out")
1016
+ .on_mouse_over_out((e) => e.mask_color(style.fg), (e) => e.mask_color(style.fg_1))
1017
+ .on_click(async () => {
1018
+ await cart.remove(item.product.id, "all");
1019
+ this.refresh();
1020
+ }))
1021
+ .center_vertical()
1022
+ .wrap(true)
1023
+ .margin_top(17.5))
1024
+ .stretch(true), VStack(Title(trial_text ? trial_text : `${currency_symbol} ${(item.product.price * item.quantity).toFixed(2)}`)
1025
+ .color(style.fg)
1026
+ .font_size(style.font_size)
1027
+ .margin(0)
1028
+ .padding(0)
1029
+ .flex_shrink(0)
1030
+ .wrap(false)
1031
+ .overflow("hidden")
1032
+ .text_overflow("ellipsis"), Text(`${trial_text ? "Then " : ""}${currency_symbol} ${item.product.price} ${per_item}`)
1033
+ .color(style.fg_1)
1034
+ .font_size(style.font_size - 6)
1035
+ .margin(5, 0, 0, 0)
1036
+ .padding(0)
1037
+ .flex_shrink(0), renews_every == null ? null : Text(renews_every)
1038
+ .color(style.fg_1)
1039
+ .font_size(style.font_size - 6)
1040
+ .margin(2.5, 0, 0, 0)
1041
+ .padding(0)
1042
+ .flex_shrink(0)))
1043
+ .overflow_x("scroll")
1044
+ .class("hide_scrollbar")
1045
+ .width("100%")
1046
+ .media("width >= 800px", (e) => {
1047
+ e.wrap(false);
1048
+ e.child(2).min_width("none")
1049
+ .margin(0);
1050
+ }, (e) => {
1051
+ e.wrap(true);
1052
+ e.child(2)
1053
+ .min_width("100%")
1054
+ .margin(15, 0, 0, 55);
1055
+ });
1056
+ return [
1057
+ stack,
1058
+ index === cart_items.length - 1 ? null : Divider()
1059
+ .background(style.divider_bg)
1060
+ .margin(20, 0, 20, 0)
1061
+ ];
1062
+ }));
1063
+ }
1064
+ return this;
1065
+ }
1066
+ });
1067
+ // Append the order element to the order container.
1068
+ this._order_container.append(this._order_element.refresh());
1069
+ },
1070
+ // Render the refunds element.
1071
+ _render_refunds_element: function () {
1072
+ // Render.
1073
+ const style = this._style;
1074
+ this._refunds_element = VStack()
1075
+ .extend({
1076
+ /**
1077
+ * Refresh the refunds element by fetching and displaying refundable, refunding, and refunded payments.
1078
+ */
1079
+ async refresh() {
1080
+ // Reset.
1081
+ this.inner_html("");
1082
+ // Create containers.
1083
+ let payments = await Payments.get_refundable_payments({
1084
+ days: Payments._days_refundable,
1085
+ });
1086
+ const refundable_container = VStack()
1087
+ .extend({
1088
+ title: "Refundable Payments",
1089
+ payments: payments,
1090
+ is_refundable: true,
1091
+ });
1092
+ payments = await Payments.get_refunding_payments();
1093
+ const refunding_container = VStack()
1094
+ .hide()
1095
+ .extend({
1096
+ title: "Processing Refunds",
1097
+ payments: payments,
1098
+ is_refunding: true,
1099
+ });
1100
+ payments = await Payments.get_refunded_payments();
1101
+ const refunded_container = VStack()
1102
+ .hide()
1103
+ .extend({
1104
+ title: "Refunded Payments",
1105
+ payments: payments,
1106
+ is_refunded: true,
1107
+ });
1108
+ // Option bar.
1109
+ const option_bar = HStack(Text("Refundable")
1110
+ .font_size(style.font_size)
1111
+ .color(style.fg_1)
1112
+ .background(style.bg_1)
1113
+ .padding(8, 6)
1114
+ .margin(0)
1115
+ .stretch(true)
1116
+ .text_center()
1117
+ .transition("color 350ms ease, background 350ms ease")
1118
+ .on_mouse_over((e) => {
1119
+ if (e.background() === "transparent") {
1120
+ e.color(style.fg);
1121
+ }
1122
+ })
1123
+ .on_mouse_out((e) => {
1124
+ if (e.background() === "transparent") {
1125
+ e.color(style.fg_1);
1126
+ }
1127
+ })
1128
+ .on_click((e) => {
1129
+ e.color(Payments._style.fg_1);
1130
+ e.background(Payments._style.bg_1);
1131
+ [e.parentElement.child(1), e.parentElement.child(2)].forEach((child) => {
1132
+ child.color(Payments._style.fg_1);
1133
+ child.background("none");
1134
+ });
1135
+ refundable_container.show();
1136
+ refunding_container.hide();
1137
+ refunded_container.hide();
1138
+ }), Text("Processing")
1139
+ .font_size(style.font_size)
1140
+ .color(style.fg_1)
1141
+ .background("transparent")
1142
+ .padding(8, 6)
1143
+ .margin(0)
1144
+ .stretch(true)
1145
+ .text_center()
1146
+ .transition("color 350ms ease, background 350ms ease")
1147
+ .on_mouse_over((e) => {
1148
+ if (e.background() === "transparent") {
1149
+ e.color(style.fg);
1150
+ }
1151
+ })
1152
+ .on_mouse_out((e) => {
1153
+ if (e.background() === "transparent") {
1154
+ e.color(style.fg_1);
1155
+ }
1156
+ })
1157
+ .on_click((e) => {
1158
+ e.color(Payments._style.fg_1);
1159
+ e.background(Payments._style.bg_1);
1160
+ [e.parentElement.child(0), e.parentElement.child(2)].forEach((child) => {
1161
+ child.color(Payments._style.fg_1);
1162
+ child.background("none");
1163
+ });
1164
+ refundable_container.hide();
1165
+ refunding_container.show();
1166
+ refunded_container.hide();
1167
+ }), Text("Refunded")
1168
+ .font_size(style.font_size)
1169
+ .color(style.fg_1)
1170
+ .background("transparent")
1171
+ .padding(8, 6)
1172
+ .margin(0)
1173
+ .stretch(true)
1174
+ .text_center()
1175
+ .transition("color 350ms ease, background 350ms ease")
1176
+ .on_mouse_over((e) => {
1177
+ if (e.background() === "transparent") {
1178
+ e.color(style.fg);
1179
+ }
1180
+ })
1181
+ .on_mouse_out((e) => {
1182
+ if (e.background() === "transparent") {
1183
+ e.color(style.fg_1);
1184
+ }
1185
+ })
1186
+ .on_click((e) => {
1187
+ e.color(Payments._style.fg_1);
1188
+ e.background(Payments._style.bg_1);
1189
+ [e.parentElement.child(0), e.parentElement.child(1)].forEach((child) => {
1190
+ child.color(Payments._style.fg_1);
1191
+ child.background("none");
1192
+ });
1193
+ refundable_container.hide();
1194
+ refunding_container.hide();
1195
+ refunded_container.show();
1196
+ }))
1197
+ .overflow("hidden")
1198
+ .border(1, style.divider_bg)
1199
+ .border_radius(style.border_radius)
1200
+ .margin_bottom(30)
1201
+ .flex_shrink(0);
1202
+ // Assign to parent.
1203
+ const refundable_option = option_bar.child(0);
1204
+ const refunding_option = option_bar.child(1);
1205
+ const refunded_option = option_bar.child(2);
1206
+ // Add elements.
1207
+ this.append(option_bar, refundable_container, refunding_container, refunded_container);
1208
+ // Separate payments.
1209
+ let currency_symbol = null;
1210
+ await Promise.all([refundable_container, refunding_container, refunded_container].map(async (container) => {
1211
+ if (container.payments.length === 0) {
1212
+ container.append(VStack(Title("No Payments")
1213
+ .color(style.fg)
1214
+ .font_size(style.font_size - 2)
1215
+ .flex_shrink(0)
1216
+ .letter_spacing("1px")
1217
+ .text_transform("uppercase")
1218
+ .ellipsis_overflow(true)
1219
+ .margin(0)
1220
+ .padding(0)
1221
+ .assign_to_parent_as("title_e"), Text(`There are no ${container.title.toLowerCase()}.`)
1222
+ .color(style.fg_1)
1223
+ .font_size(style.font_size - 2)
1224
+ .line_height(style.font_size)
1225
+ .margin(5, 0, 0, 0)
1226
+ .padding(0)
1227
+ .assign_to_parent_as("text_e")
1228
+ .white_space("pre")
1229
+ .line_height("1.4em")
1230
+ .center(), Image("/volt_static/payments/check.webp")
1231
+ .frame(30, 30)
1232
+ .margin_top(15)
1233
+ .assign_to_parent_as("success_image_e"))
1234
+ .min_height(160)
1235
+ .frame("100%", "100%")
1236
+ .center()
1237
+ .center_vertical());
1238
+ }
1239
+ else {
1240
+ await Promise.all(container.payments.map(async (payment) => {
1241
+ await Promise.all(payment.line_items.map(async (item) => {
1242
+ item.product = await Payments.get_product(item.product);
1243
+ }));
1244
+ }));
1245
+ container.append(Title(container.title)
1246
+ .color(style.fg)
1247
+ .width("fit-content")
1248
+ .font_size(style.font_size - 2)
1249
+ .flex_shrink(0)
1250
+ .margin(0, 0, 0, 0)
1251
+ .letter_spacing("1px")
1252
+ .text_transform("uppercase")
1253
+ .ellipsis_overflow(true), Divider()
1254
+ .background(style.divider_bg)
1255
+ .margin(10, 0, 20, 0), ForEach(container.payments, (payment, index) => {
1256
+ // Line items.
1257
+ const items = VStack(ForEach(payment.line_items, (item, index) => {
1258
+ if (currency_symbol == null) {
1259
+ currency_symbol = Payments.get_currency_symbol(item.product.currency);
1260
+ }
1261
+ return [
1262
+ HStack(item.product.icon == null ? null :
1263
+ Image(item.product.icon)
1264
+ .frame(25, 25)
1265
+ .flex_shrink(0)
1266
+ .margin(0, 20, 0, 0), VStack(Title(item.product.name)
1267
+ .color(style.fg)
1268
+ .font_size(style.font_size - 2)
1269
+ .line_height(style.font_size)
1270
+ .margin(0, 10, 0, 0)
1271
+ .padding(0)
1272
+ .font_weight("bold")
1273
+ .ellipsis_overflow(true), Text(item.product.description)
1274
+ .color(style.fg_1)
1275
+ .font_size(style.font_size - 4)
1276
+ .line_height(style.font_size - 2)
1277
+ .margin(5, 0, 0, 0)
1278
+ .wrap(true)
1279
+ .padding(0))
1280
+ .stretch(true), VStack(Text(`${currency_symbol} ${(item.total).toFixed(2)}`)
1281
+ .color(style.fg_1)
1282
+ .font_size(style.font_size - 4)
1283
+ .line_height(style.font_size - 2)
1284
+ .margin(0)
1285
+ .padding(0)
1286
+ .flex_shrink(0)
1287
+ .ellipsis_overflow(true))),
1288
+ index === payment.line_items.length - 1 ? null : Divider()
1289
+ .background(style.divider_bg)
1290
+ .margin(15, 0, 15, 0),
1291
+ ];
1292
+ }))
1293
+ .background(style.bg_1)
1294
+ .border_radius(style.border_radius)
1295
+ .border(1, style.divider_bg)
1296
+ .padding(20);
1297
+ // Payment.
1298
+ const stack = VStack(HStack(Title("Payment")
1299
+ .color(style.fg)
1300
+ .font_size(style.font_size)
1301
+ .margin(0, 10, 0, 0)
1302
+ .padding(0)
1303
+ .wrap(false)
1304
+ .overflow("hidden")
1305
+ .text_overflow("ellipsis")
1306
+ .stretch(true), !container.is_refundable ? null : BorderButton("Refund")
1307
+ .font_size(style.font_size - 4)
1308
+ .padding(7.5, 10)
1309
+ .margin(0, 5, 0, 0)
1310
+ .color(style.button.bg)
1311
+ .border_radius(style.button.border_radius)
1312
+ .border_color(style.button.bg)
1313
+ .hover_brightness(...style.button.hover_brightness)
1314
+ .font_weight("bold")
1315
+ .on_click(() => {
1316
+ document.body.appendChild(Popup({
1317
+ title: "Request Refund",
1318
+ text: `You are about to request a refund for payment <span style='border-radius: 7px; background: ${style.bg_1}; padding: 1px 4px; font-size: 0.9em;'>${payment.id}</span>, do you wish to proceed?`,
1319
+ no: "No",
1320
+ yes: "Yes",
1321
+ image: "/volt_static/payments/error.webp",
1322
+ blur: 5,
1323
+ animation_duration: 300,
1324
+ on_yes: async () => {
1325
+ try {
1326
+ await Payments.create_refund(payment);
1327
+ }
1328
+ catch (err) {
1329
+ console.error(err);
1330
+ Payments.on_error(err);
1331
+ return null;
1332
+ }
1333
+ this.refresh().then(() => {
1334
+ refunding_option.click();
1335
+ });
1336
+ },
1337
+ })
1338
+ .font(window.getComputedStyle(Payments._refunds_container).font)
1339
+ .widget
1340
+ .background(style.bg)
1341
+ .color(style.fg_1)
1342
+ .border_bottom("4px solid #E8454E")
1343
+ // .leading()
1344
+ .parent()
1345
+ .title
1346
+ .color(style.fg)
1347
+ // .width("fit-content")
1348
+ .font_size(style.font_size + 2)
1349
+ .flex_shrink(0)
1350
+ .margin(0, 0, 0, 10)
1351
+ // .letter_spacing("1px")
1352
+ // .text_transform("uppercase")
1353
+ // .ellipsis_overflow(true)
1354
+ // .color(style.fg_1)
1355
+ .center()
1356
+ .parent()
1357
+ .text
1358
+ .color(style.fg_1)
1359
+ .font_size(style.font_size)
1360
+ .margin_left(10)
1361
+ .center()
1362
+ .parent()
1363
+ .image
1364
+ .padding(10)
1365
+ .mask_color(style.bg)
1366
+ .border_radius("50%")
1367
+ .background("#E8454E")
1368
+ .frame(40, 40)
1369
+ .box_shadow('0 0 0 4px #E8454E50')
1370
+ .parent()
1371
+ .no_button
1372
+ .padding(10, 0)
1373
+ .font_size(style.font_size)
1374
+ .background(style.bg_1)
1375
+ .color(style.fg_1)
1376
+ .border(1, style.divider_bg)
1377
+ .hover_brightness(...style.button.hover_brightness)
1378
+ .box_shadow('0px 0px 5px #00000030')
1379
+ .parent()
1380
+ .yes_button
1381
+ .padding(10, 0)
1382
+ .font_size(style.font_size)
1383
+ .background("#E8454E")
1384
+ .color(style.fg_1)
1385
+ .border(1, style.divider_bg)
1386
+ .hover_brightness(...style.button.hover_brightness)
1387
+ .box_shadow('0px 0px 5px #00000030')
1388
+ .parent());
1389
+ }), !container.is_refunding ? null : RingLoader()
1390
+ .frame(20, 20)
1391
+ .background(style.theme_fg)
1392
+ .margin(0, 5, 0, 0)
1393
+ .update(), !container.is_refunded ? null : Image("/volt_static/payments/check.webp")
1394
+ .frame(20, 20)
1395
+ .margin(0, 5, 0, 0))
1396
+ .min_height(30), Text("")
1397
+ .inner_html(`Purchased at ${Utils.unix_to_date(payment.timestamp / 1000)} <span style='font-size: 0.8em'>${payment.id}<span>.`)
1398
+ .color(style.fg_1)
1399
+ .font_size(style.font_size - 6)
1400
+ .line_height(style.font_size - 4)
1401
+ .margin(-5, 0, 10, 0)
1402
+ .wrap(true)
1403
+ .padding(0)
1404
+ .white_space("pre")
1405
+ .line_height("1.4em")
1406
+ .center(), items)
1407
+ .width("100%");
1408
+ // Elements.
1409
+ return [
1410
+ stack,
1411
+ index === container.payments.length - 1 ? null : Divider()
1412
+ .background(style.divider_bg)
1413
+ .margin(20, 0, 20, 0),
1414
+ ];
1415
+ }));
1416
+ }
1417
+ }));
1418
+ return this;
1419
+ }
1420
+ });
1421
+ // Append.
1422
+ this._refunds_element.refresh();
1423
+ this._refunds_container.append(this._refunds_element);
1424
+ },
1425
+ // Render the address element.
1426
+ _render_billing_element: function () {
1427
+ if (this._billing_element !== undefined) {
1428
+ return;
1429
+ }
1430
+ // Utils.
1431
+ const CreateInput = (args) => {
1432
+ return ExtendedInput(args)
1433
+ .color(this._style.fg)
1434
+ .font_size(this._style.font_size)
1435
+ .missing_color(this._style.missing_fg)
1436
+ .focus_color(this._style.theme_fg)
1437
+ .border_color(this._style.divider_bg)
1438
+ .border_radius(this._style.border_radius)
1439
+ .input
1440
+ .color(this._style.fg_1)
1441
+ .parent();
1442
+ };
1443
+ const CreateSelect = (args) => {
1444
+ return ExtendedSelect(args)
1445
+ .background(this._style.bg)
1446
+ .color(this._style.fg)
1447
+ .font_size(this._style.font_size)
1448
+ .missing_color(this._style.missing_fg)
1449
+ .focus_color(this._style.theme_fg)
1450
+ .border_color(this._style.divider_bg)
1451
+ .border_radius(this._style.border_radius)
1452
+ .dropdown_height(150)
1453
+ .background("transparent")
1454
+ .dropdown
1455
+ .background(this._style.bg_1)
1456
+ .background_blur(20)
1457
+ .parent()
1458
+ .input
1459
+ .white_space("pre")
1460
+ // .border_radius(0)
1461
+ .color(this._style.fg_1)
1462
+ .parent();
1463
+ };
1464
+ // Create element.
1465
+ const input_spacing = 15;
1466
+ let country_code;
1467
+ this._billing_element = Form(Title("Billing Details")
1468
+ .color(this._style.fg)
1469
+ .width("fit-content")
1470
+ .font_size(this._style.font_size - 2)
1471
+ .flex_shrink(0)
1472
+ .margin(0, 0, 0, 0)
1473
+ .letter_spacing("1px")
1474
+ .text_transform("uppercase")
1475
+ .ellipsis_overflow(true), Divider()
1476
+ .background(this._style.divider_bg)
1477
+ .margin(10, 0, 10, 0), HStack(Text("Personal")
1478
+ .font_size(this._style.font_size)
1479
+ .color(this._style.fg)
1480
+ .background(this._style.bg_1)
1481
+ .padding(8, 6)
1482
+ .margin(0)
1483
+ .stretch(true)
1484
+ .text_center()
1485
+ .transition("color 350ms ease, background 350ms ease")
1486
+ .on_mouse_over((e) => {
1487
+ if (e.background() === "transparent") {
1488
+ e.color(this._style.fg);
1489
+ }
1490
+ })
1491
+ .on_mouse_out((e) => {
1492
+ if (e.background() === "transparent") {
1493
+ e.color(this._style.fg_1);
1494
+ }
1495
+ })
1496
+ .on_click((e) => {
1497
+ e.color(this._style.fg_1);
1498
+ e.background(this._style.bg_1);
1499
+ const other = e.parentElement.child(1);
1500
+ other.color(this._style.fg_1);
1501
+ other.background("none");
1502
+ this._billing_element.name_input.show();
1503
+ this._billing_element.name_input.required(true);
1504
+ this._billing_element.business_input.hide();
1505
+ this._billing_element.business_input.required(false);
1506
+ this._billing_element.vat_id_input.hide();
1507
+ this._billing_element.vat_id_input.required(false);
1508
+ }), Text("Business")
1509
+ .font_size(this._style.font_size)
1510
+ .color(this._style.fg_1)
1511
+ .background("transparent")
1512
+ .padding(8, 6)
1513
+ .margin(0)
1514
+ .stretch(true)
1515
+ .text_center()
1516
+ .transition("color 350ms ease, background 350ms ease")
1517
+ .on_mouse_over((e) => {
1518
+ if (e.background() === "transparent") {
1519
+ e.color(this._style.fg);
1520
+ }
1521
+ })
1522
+ .on_mouse_out((e) => {
1523
+ if (e.background() === "transparent") {
1524
+ e.color(this._style.fg_1);
1525
+ }
1526
+ })
1527
+ .on_click((e) => {
1528
+ e.color(this._style.fg_1);
1529
+ e.background(this._style.bg_1);
1530
+ const other = e.parentElement.child(0);
1531
+ other.color(this._style.fg_1);
1532
+ other.background("transparent");
1533
+ this._billing_element.name_input.hide();
1534
+ this._billing_element.name_input.required(false);
1535
+ this._billing_element.business_input.show();
1536
+ this._billing_element.business_input.required(true);
1537
+ this._billing_element.vat_id_input.show();
1538
+ this._billing_element.vat_id_input.required(true);
1539
+ }))
1540
+ .overflow("hidden")
1541
+ .border(1, this._style.divider_bg)
1542
+ .border_radius(this._style.border_radius)
1543
+ .margin_top(10)
1544
+ .margin_bottom(10)
1545
+ .flex_shrink(0), CreateInput({
1546
+ label: "Full Name",
1547
+ placeholder: "John Doe",
1548
+ })
1549
+ .value(User.first_name() === undefined ? "" : (User.first_name() + " " + User.last_name()))
1550
+ .margin_top(input_spacing)
1551
+ .required(true)
1552
+ .id("name")
1553
+ .assign_to_parent_as("name_input"), CreateInput({
1554
+ label: "Business Name",
1555
+ placeholder: "Company Inc.",
1556
+ })
1557
+ .margin_top(input_spacing)
1558
+ .required(false)
1559
+ .id("business")
1560
+ .hide()
1561
+ .assign_to_parent_as("business_input"), CreateInput({
1562
+ label: "VAT ID",
1563
+ placeholder: "VAT ID",
1564
+ })
1565
+ .margin_top(input_spacing)
1566
+ .required(false)
1567
+ .id("vat_id")
1568
+ .hide()
1569
+ .assign_to_parent_as("vat_id_input"), CreateInput({
1570
+ label: "Email",
1571
+ placeholder: "my@email.com",
1572
+ })
1573
+ .value(User.email() ?? "")
1574
+ .margin_top(input_spacing)
1575
+ .required(true)
1576
+ .id("email"), CreateInput({
1577
+ label: "Street",
1578
+ placeholder: "123 Park Avenue",
1579
+ })
1580
+ .margin_top(input_spacing)
1581
+ .required(true)
1582
+ .id("street"), CreateInput({
1583
+ label: "House Number",
1584
+ placeholder: "Suite 405",
1585
+ })
1586
+ .margin_top(input_spacing)
1587
+ .required(true)
1588
+ .id("house_number"), CreateInput({
1589
+ label: "Postal Code",
1590
+ placeholder: "10001",
1591
+ })
1592
+ .margin_top(input_spacing)
1593
+ .required(true)
1594
+ .id("postal_code"), CreateInput({
1595
+ label: "City",
1596
+ placeholder: "New York",
1597
+ })
1598
+ .margin_top(input_spacing)
1599
+ .required(true)
1600
+ .id("city"), CreateInput({
1601
+ label: "Province",
1602
+ placeholder: "New York",
1603
+ })
1604
+ .margin_top(input_spacing)
1605
+ .required(true)
1606
+ .id("province"), CreateSelect({
1607
+ label: "Country",
1608
+ placeholder: "United States",
1609
+ items: Object.fromEntries(Object.entries(Payments.countries).map(([key, value]) => [key, value.name])),
1610
+ })
1611
+ .on_change((_, country) => {
1612
+ this._overview_element.calc_tax(country);
1613
+ country_code.value(Payments.countries[country].calling_code);
1614
+ })
1615
+ .margin_top(input_spacing)
1616
+ .required(true)
1617
+ .id("country"), HStack(country_code = CreateInput({
1618
+ label: "Country Code",
1619
+ placeholder: "+1",
1620
+ type: "tel",
1621
+ })
1622
+ .max_width("fit-content")
1623
+ .margin_top(input_spacing)
1624
+ .margin_right(input_spacing)
1625
+ .required(true)
1626
+ .input
1627
+ .readonly(true)
1628
+ .parent()
1629
+ .id("phone_country_code"), CreateInput({
1630
+ label: "Phone Number",
1631
+ placeholder: "1234567890",
1632
+ type: "tel",
1633
+ })
1634
+ .margin_top(input_spacing)
1635
+ .stretch(true)
1636
+ .required(true)
1637
+ .id("phone_number"))
1638
+ .width("100%"));
1639
+ // Append.
1640
+ this._billing_container.append(this._billing_element);
1641
+ },
1642
+ // Render the payment element.
1643
+ _render_payment_element: async function () {
1644
+ return new Promise((resolve, reject) => {
1645
+ this._render_payment_element_resolve = resolve;
1646
+ this._render_payment_element_reject = reject;
1647
+ // Already rendered.
1648
+ if (this._payment_element !== undefined) {
1649
+ return resolve();
1650
+ }
1651
+ // Checks.
1652
+ if (this.client_key == null) {
1653
+ return reject(new Error(`No client key has been assigned to "Payments.client_key".`));
1654
+ }
1655
+ if (this.cart.items.length === 0) {
1656
+ return reject(new Error("Shopping cart is empty."));
1657
+ }
1658
+ // Check subscription or one time payment.
1659
+ let is_subscription = false;
1660
+ this.cart.items.forEach((item) => {
1661
+ if (item.is_subscription === true) {
1662
+ is_subscription = true;
1663
+ return false;
1664
+ }
1665
+ });
1666
+ // Initialize paddle.
1667
+ this._initialize_paddle();
1668
+ // Create element.
1669
+ this._payment_element = VStack()
1670
+ .class("checkout-container");
1671
+ // Append.
1672
+ this._payment_container.append(this._payment_element);
1673
+ // Initialize.
1674
+ let custom_data = {
1675
+ customer_name: this._billing_details.name,
1676
+ };
1677
+ if (User.is_authenticated()) {
1678
+ custom_data.uid = User.uid();
1679
+ }
1680
+ try {
1681
+ let business = undefined;
1682
+ if (this._billing_details.business !== "") {
1683
+ business = {
1684
+ name: this._billing_details.business,
1685
+ taxIdentifier: this._billing_details.vat_id === "" ? undefined : this._billing_details.vat_id,
1686
+ };
1687
+ }
1688
+ Paddle.Checkout.open({
1689
+ settings: {
1690
+ displayMode: "inline",
1691
+ theme: this._theme,
1692
+ locale: "en",
1693
+ frameTarget: "checkout-container",
1694
+ frameInitialHeight: "450",
1695
+ frameStyle: "width: 100%; min-width: 312px; background-color: transparent; border: none;",
1696
+ // successUrl: this.return_url,
1697
+ // successUrl: "http://test.vandenberghinc.com/checkout?payment_status=success",
1698
+ },
1699
+ items: this.cart.items.map((item) => { return { priceId: item.product.price_id, quantity: item.quantity }; }),
1700
+ customer: {
1701
+ email: this._billing_details.email,
1702
+ address: {
1703
+ countryCode: this._billing_details.country,
1704
+ postalCode: this._billing_details.postal_code,
1705
+ region: this._billing_details.province,
1706
+ city: this._billing_details.city,
1707
+ firstLine: `${this._billing_details.street} ${this._billing_details.house_number}`,
1708
+ },
1709
+ business,
1710
+ },
1711
+ customData: custom_data,
1712
+ });
1713
+ }
1714
+ catch (err) {
1715
+ return reject(err);
1716
+ }
1717
+ // const iframe = this._payment_element.children[0];
1718
+ // iframe.onload = () => {
1719
+ // console.log("ON LOAD");
1720
+ // let doc = iframe.contentDocument || iframe.contentWindow.document;
1721
+ // let elementInsideIframe = doc.getElementById('cardNumber');
1722
+ // elementInsideIframe.style.background = 'red'; // Example of editing an element
1723
+ // }
1724
+ });
1725
+ },
1726
+ // Render the processing element.
1727
+ _render_processing_element: function () {
1728
+ // Already defined.
1729
+ if (this._processing_element !== undefined) {
1730
+ this._processing_element.set_processing();
1731
+ return;
1732
+ }
1733
+ // Create element.
1734
+ this._processing_element = VStack(Title("Processing")
1735
+ .color(this._style.fg)
1736
+ .font_size(this._style.font_size - 2)
1737
+ .flex_shrink(0)
1738
+ .letter_spacing("1px")
1739
+ .text_transform("uppercase")
1740
+ .ellipsis_overflow(true)
1741
+ .margin(0)
1742
+ .padding(0)
1743
+ .assign_to_parent_as("title_e"), Text("Processing your payment, please wait.")
1744
+ .color(this._style.fg_1)
1745
+ .font_size(this._style.font_size - 2)
1746
+ .line_height(this._style.font_size)
1747
+ .margin(5, 0, 0, 0)
1748
+ .padding(0)
1749
+ .assign_to_parent_as("text_e")
1750
+ .white_space("pre")
1751
+ .line_height("1.4em")
1752
+ .center(), ImageMask("/volt_static/payments/error.webp")
1753
+ .hide()
1754
+ .frame(40, 40)
1755
+ .padding(5)
1756
+ .mask_color(this._style.missing_fg)
1757
+ .margin_top(15)
1758
+ .assign_to_parent_as("error_image_e"), Image("/volt_static/payments/party.webp")
1759
+ .hide()
1760
+ .frame(40, 40)
1761
+ .margin_top(15)
1762
+ .assign_to_parent_as("success_image_e"), RingLoader()
1763
+ .background(this._style.theme_fg)
1764
+ .frame(40, 40)
1765
+ .update()
1766
+ .margin_top(15)
1767
+ .assign_to_parent_as("loader_e"))
1768
+ .padding(15, 0)
1769
+ .center()
1770
+ .center_vertical()
1771
+ .extend({
1772
+ timestamp: Date.now(),
1773
+ /**
1774
+ * Set the processing element to display an error message.
1775
+ * @param message - The error message to display.
1776
+ */
1777
+ set_error(message = "The payment has failed, please check your information and try again.\n If the problem persists, contact support for assistance.") {
1778
+ this.loader_e.hide();
1779
+ this.error_image_e.src("/volt_static/payments/error.webp");
1780
+ this.error_image_e.show();
1781
+ this.success_image_e.hide();
1782
+ this.title_e.text("Error");
1783
+ this.text_e.text(message);
1784
+ },
1785
+ /**
1786
+ * Set the processing element to display a cancelled message.
1787
+ * @param message - The cancellation message to display.
1788
+ */
1789
+ set_cancelled(message = "The payment has been cancelled.") {
1790
+ this.loader_e.hide();
1791
+ this.error_image_e.src("/volt_static/payments/cancelled.webp");
1792
+ this.error_image_e.show();
1793
+ this.success_image_e.hide();
1794
+ this.title_e.text("Cancelled");
1795
+ this.text_e.text(message);
1796
+ },
1797
+ /**
1798
+ * Set the processing element to display a success message.
1799
+ * @param message - The success message to display.
1800
+ */
1801
+ set_success(message = "The payment has succeeded and is currently processing.\n Thank you for your purchase!") {
1802
+ this.loader_e.hide();
1803
+ this.error_image_e.hide();
1804
+ this.success_image_e.show();
1805
+ this.title_e.text("Success");
1806
+ this.text_e.text(message);
1807
+ },
1808
+ /**
1809
+ * Set the processing element to display a processing message.
1810
+ * @param message - The processing message to display.
1811
+ */
1812
+ set_processing(message = "Processing your payment, please wait.") {
1813
+ this.loader_e.show();
1814
+ this.error_image_e.hide();
1815
+ this.success_image_e.hide();
1816
+ this.title_e.text("Processing");
1817
+ this.text_e.text(message);
1818
+ },
1819
+ });
1820
+ // Append.
1821
+ this._processing_container.append(this._processing_element);
1822
+ },
1823
+ // Show the processing container.
1824
+ _show_processing: async function (status = null) {
1825
+ // Select step.
1826
+ this._step = 3;
1827
+ this._steps_element.select(this._step);
1828
+ // Render the processing element.
1829
+ this._render_processing_element();
1830
+ // Set elements.
1831
+ this._order_container.hide();
1832
+ this._billing_container.hide();
1833
+ this._payment_container.hide();
1834
+ this._processing_container.show();
1835
+ this._overview_container.hide();
1836
+ this._prev_step_button.hide();
1837
+ // Update.
1838
+ if (status != null) {
1839
+ this._update_processing(status);
1840
+ }
1841
+ },
1842
+ // Update the processing container.
1843
+ _update_processing: async function (status) {
1844
+ // Handle result code.
1845
+ switch (status) {
1846
+ case "success":
1847
+ this._processing_element.set_success();
1848
+ break;
1849
+ case "processing":
1850
+ this._processing_element.set_processing();
1851
+ break;
1852
+ case "cancelled":
1853
+ this._processing_element.set_cancelled();
1854
+ break;
1855
+ case "error":
1856
+ this._processing_element.set_error();
1857
+ break;
1858
+ default:
1859
+ console.error(`Unknown session result code "${status}".`);
1860
+ this._processing_element.set_error("An unknown error has occurred.");
1861
+ break;
1862
+ }
1863
+ },
1864
+ // Initialize checkout page.
1865
+ style: function ({ theme = "light", // light or dark
1866
+ font_size = 16, border_radius = 10, bg = "#FFFFFF", bg_1 = "#00000099", divider_bg = "gray", fg = "#687282", fg_1 = "black", fg_2 = "#6D6E77", theme_fg = "#8EB8EB", missing_fg = "#E8454E", selected = {
1867
+ fg: null,
1868
+ bg: null,
1869
+ }, button = {
1870
+ fg: null,
1871
+ bg: null,
1872
+ border_color: null,
1873
+ border_radius: 25,
1874
+ border_width: 1,
1875
+ border_inset: false,
1876
+ hover_brightness: [1.1, 1.2],
1877
+ }, } = {}) {
1878
+ // Set selected defaults.
1879
+ if (selected == null) {
1880
+ selected = { fg: null, bg: null };
1881
+ }
1882
+ selected.fg ??= fg;
1883
+ selected.bg ??= theme_fg;
1884
+ // Set button defaults.
1885
+ if (button == null) {
1886
+ button = {
1887
+ fg: null,
1888
+ bg: null,
1889
+ border_radius: null,
1890
+ border_color: null,
1891
+ border_width: 1,
1892
+ hover_brightness: [1, 1],
1893
+ border_inset: false,
1894
+ };
1895
+ }
1896
+ button.fg ??= fg;
1897
+ button.bg ??= bg_1; // Corrected bg_2 to bg_1 as bg_2 is not defined
1898
+ button.border_radius ??= 25;
1899
+ button.border_color ??= fg;
1900
+ button.border_width ??= 1;
1901
+ button.border_inset ??= false;
1902
+ button.hover_brightness ??= [1.1, 1.2];
1903
+ if (typeof button.border_width === "number") {
1904
+ button.border_width = `${button.border_width}px`;
1905
+ }
1906
+ // Save style.
1907
+ this._style = {};
1908
+ this._theme = theme;
1909
+ this._style.font_size = font_size;
1910
+ this._style.border_radius = border_radius;
1911
+ this._style.bg = bg;
1912
+ this._style.bg_1 = bg_1;
1913
+ this._style.divider_bg = divider_bg;
1914
+ this._style.fg = fg;
1915
+ this._style.fg_1 = fg_1;
1916
+ this._style.fg_2 = fg_2;
1917
+ this._style.theme_fg = theme_fg;
1918
+ this._style.missing_fg = missing_fg;
1919
+ this._style.selected = selected;
1920
+ this._style.button = button;
1921
+ // Set CSS variables.
1922
+ Object.keys(this._style).forEach((key) => {
1923
+ if (typeof this._style[key] === "number") {
1924
+ document.documentElement.style.setProperty(`--vpayments_${key}`, `${this._style[key]}px`);
1925
+ }
1926
+ else {
1927
+ document.documentElement.style.setProperty(`--vpayments_${key}`, this._style[key]);
1928
+ }
1929
+ });
1930
+ document.documentElement.style.setProperty(`--vpayments_theme_fg_80`, `${this._style.theme_fg}80`);
1931
+ document.documentElement.style.setProperty(`--vpayments_missing_fg_80`, `${this._style.missing_fg}80`);
1932
+ },
1933
+ // Initialize checkout page.
1934
+ create_checkout_dropin: function ({ steps_container, order_container, billing_container, payment_container, processing_container, overview_container, sign_in_redirect = null, on_error = (error) => { }, }) {
1935
+ // Check args.
1936
+ if (!(steps_container instanceof Node)) {
1937
+ throw new Error('The "steps_container" must be assigned with a container node.');
1938
+ }
1939
+ if (!(order_container instanceof Node)) {
1940
+ throw new Error('The "order_container" must be assigned with a container node.');
1941
+ }
1942
+ if (!(billing_container instanceof Node)) {
1943
+ throw new Error('The "billing_container" must be assigned with a container node.');
1944
+ }
1945
+ if (!(payment_container instanceof Node)) {
1946
+ throw new Error('The "payment_container" must be assigned with a container node.');
1947
+ }
1948
+ if (!(processing_container instanceof Node)) {
1949
+ throw new Error('The "processing_container" must be assigned with a container node.');
1950
+ }
1951
+ if (!(overview_container instanceof Node)) {
1952
+ throw new Error('The "overview_container" must be assigned with a container node.');
1953
+ }
1954
+ // Args.
1955
+ this._steps_container = steps_container;
1956
+ this._order_container = order_container;
1957
+ // @ts-ignore
1958
+ this._billing_container = billing_container.hide();
1959
+ // @ts-ignore
1960
+ this._payment_container = payment_container.hide();
1961
+ // @ts-ignore
1962
+ this._processing_container = processing_container.hide();
1963
+ this._overview_container = overview_container;
1964
+ // Settings.
1965
+ this._sign_in_redirect = sign_in_redirect;
1966
+ // Events.
1967
+ this.on_error = on_error;
1968
+ // Check style.
1969
+ if (this._style === undefined) {
1970
+ this.style();
1971
+ }
1972
+ // Other attributes.
1973
+ this._step = 0;
1974
+ // Render the steps element.
1975
+ this._render_steps_element();
1976
+ // When the user was redirected the URL params are defined, if so only render the processing view.
1977
+ if (Utils.url_param("payment_status", null) != null) {
1978
+ this._show_processing(Utils.url_param("payment_status", null));
1979
+ }
1980
+ // No redirect.
1981
+ else {
1982
+ // Render the overview element.
1983
+ this._render_overview_element();
1984
+ // Render the order element.
1985
+ // Must be rendered after the overview element is rendered.
1986
+ this._render_order_element();
1987
+ }
1988
+ },
1989
+ // Initialize refund page.
1990
+ create_refunds_dropin: function ({
1991
+ // The element containers.
1992
+ refunds_container,
1993
+ // Refundable settings.
1994
+ days_refundable = 30,
1995
+ // Events.
1996
+ on_error = (error) => { }, }) {
1997
+ // Check args.
1998
+ if (!(refunds_container instanceof Node)) {
1999
+ throw new Error('The "refunds_container" must be assigned with a container node.');
2000
+ }
2001
+ // Args.
2002
+ this._refunds_container = refunds_container;
2003
+ this._days_refundable = days_refundable;
2004
+ // Events.
2005
+ this.on_error = on_error;
2006
+ // Check style.
2007
+ if (this._style === undefined) {
2008
+ this.style();
2009
+ }
2010
+ // Other attributes.
2011
+ this._step = 0;
2012
+ // Render the refunds element.
2013
+ this._render_refunds_element();
2014
+ },
2015
+ // Backend API.
2016
+ // Get the currency symbol for a product currency.
2017
+ // Returns `null` when the currency is not supported.
2018
+ /**
2019
+ * @docs:
2020
+ * @nav: Frontend
2021
+ * @chapter: Payments
2022
+ * @title: Get Currency Symbol
2023
+ * @description: Get the currency symbol for a product currency.
2024
+ * @type: string | null
2025
+ * @return: Returns the currency symbol when the currency is supported, otherwise `null`
2026
+ * @param:
2027
+ * @name: currency
2028
+ * @description: The currency from the product object.
2029
+ */
2030
+ get_currency_symbol: function (currency) {
2031
+ switch (currency.toLowerCase()) {
2032
+ case "aed": return "د.إ";
2033
+ case "afn": return "Af";
2034
+ case "all": return "L";
2035
+ case "amd": return "֏";
2036
+ case "ang": return "ƒ";
2037
+ case "aoa": return "Kz";
2038
+ case "ars": return "$";
2039
+ case "aud": return "$";
2040
+ case "awg": return "ƒ";
2041
+ case "azn": return "₼";
2042
+ case "bam": return "KM";
2043
+ case "bbd": return "Bds$";
2044
+ case "bdt": return "৳";
2045
+ case "bgn": return "лв";
2046
+ case "bhd": return ".د.ب";
2047
+ case "bif": return "FBu";
2048
+ case "bmd": return "BD$";
2049
+ case "bnd": return "B$";
2050
+ case "bob": return "Bs";
2051
+ case "brl": return "R$";
2052
+ case "bsd": return "B$";
2053
+ case "btn": return "Nu.";
2054
+ case "bwp": return "P";
2055
+ case "byn": return "Br";
2056
+ case "bzd": return "BZ$";
2057
+ case "cad": return "$";
2058
+ case "cdf": return "FC";
2059
+ case "chf": return "Fr";
2060
+ case "clf": return "UF";
2061
+ case "clp": return "$";
2062
+ case "cny": return "¥";
2063
+ case "cop": return "$";
2064
+ case "crc": return "₡";
2065
+ case "cuc": return "CUC$";
2066
+ case "cup": return "CUP$";
2067
+ case "cve": return "$";
2068
+ case "czk": return "Kč";
2069
+ case "djf": return "Fdj";
2070
+ case "dkk": return "kr";
2071
+ case "dop": return "RD$";
2072
+ case "dzd": return "دج";
2073
+ case "egp": return "E£";
2074
+ case "ern": return "Nfk";
2075
+ case "etb": return "Br";
2076
+ case "eur": return "€";
2077
+ case "fjd": return "FJ$";
2078
+ case "fkp": return "£";
2079
+ case "fok": return "F$";
2080
+ case "gbp": return "£";
2081
+ case "gel": return "₾";
2082
+ case "ghc": return "₵";
2083
+ case "gip": return "£";
2084
+ case "gmd": return "D";
2085
+ case "gnf": return "FG";
2086
+ case "gtq": return "Q";
2087
+ case "gyd": return "GY$";
2088
+ case "hkd": return "HK$";
2089
+ case "hnl": return "L";
2090
+ case "hrk": return "kn";
2091
+ case "htg": return "G";
2092
+ case "huf": return "Ft";
2093
+ case "idr": return "Rp";
2094
+ case "ils": return "₪";
2095
+ case "inr": return "₹";
2096
+ case "iqd": return "د.ع";
2097
+ case "irr": return "﷼";
2098
+ case "isk": return "kr";
2099
+ case "jmd": return "J$";
2100
+ case "jod": return "JD";
2101
+ case "jpy": return "¥";
2102
+ case "kes": return "Ksh";
2103
+ case "kgs": return "с";
2104
+ case "khr": return "៛";
2105
+ case "kmf": return "CF";
2106
+ case "kpw": return "₩";
2107
+ case "krw": return "₩";
2108
+ case "kwd": return "KD";
2109
+ case "kyd": return "CI$";
2110
+ case "kzt": return "₸";
2111
+ case "lak": return "₭";
2112
+ case "lbp": return "L£";
2113
+ case "lkr": return "Rs";
2114
+ case "lrd": return "L$";
2115
+ case "lsl": return "L";
2116
+ case "lyd": return "ل.د";
2117
+ case "mad": return "د.م.";
2118
+ case "mdl": return "L";
2119
+ case "mnt": return "₮";
2120
+ case "mop": return "MOP$";
2121
+ case "mur": return "Rs";
2122
+ case "mvr": return "Rf";
2123
+ case "mwk": return "MK";
2124
+ case "mxn": return "$";
2125
+ case "myr": return "RM";
2126
+ case "mzn": return "MTn";
2127
+ case "nad": return "N$";
2128
+ case "ngn": return "₦";
2129
+ case "nio": return "C$";
2130
+ case "nok": return "kr";
2131
+ case "npr": return "रू";
2132
+ case "nzd": return "$";
2133
+ case "omr": return "ر.ع.";
2134
+ case "pab": return "B/.";
2135
+ case "pen": return "S/.";
2136
+ case "pgk": return "K";
2137
+ case "php": return "₱";
2138
+ case "pkr": return "Rs";
2139
+ case "pln": return "zł";
2140
+ case "pyg": return "₲";
2141
+ case "qar": return "ر.ق";
2142
+ case "ron": return "lei";
2143
+ case "rsd": return "din.";
2144
+ case "rub": return "₽";
2145
+ case "rwf": return "FRw";
2146
+ case "sar": return "ر.س";
2147
+ case "sbd": return "SI$";
2148
+ case "scr": return "Sr";
2149
+ case "sdg": return "ج.س.";
2150
+ case "sek": return "kr";
2151
+ case "sgd": return "S$";
2152
+ case "shp": return "£";
2153
+ case "sll": return "Le";
2154
+ case "sos": return "S";
2155
+ case "srd": return "SRD$";
2156
+ case "ssp": return "£";
2157
+ case "std": return "Db";
2158
+ case "syp": return "S£";
2159
+ case "szl": return "L";
2160
+ case "thb": return "฿";
2161
+ case "tjs": return "ЅМ";
2162
+ case "tmt": return "m";
2163
+ case "tnd": return "د.ت";
2164
+ case "top": return "T$";
2165
+ case "try": return "₺";
2166
+ case "ttd": return "TT$";
2167
+ case "twd": return "NT$";
2168
+ case "tzs": return "TSh";
2169
+ case "uah": return "₴";
2170
+ case "ugx": return "USh";
2171
+ case "usd": return "$";
2172
+ case "uyu": return "$U";
2173
+ case "uzs": return "лв";
2174
+ case "ves": return "Bs.S.";
2175
+ case "vnd": return "₫";
2176
+ case "vuv": return "VT";
2177
+ case "wst": return "WS$";
2178
+ case "xaf": return "FCFA";
2179
+ case "xcd": return "EC$";
2180
+ case "xof": return "CFA";
2181
+ case "xpf": return "CFP";
2182
+ case "yer": return "﷼";
2183
+ case "zar": return "R";
2184
+ case "zmw": return "ZK";
2185
+ }
2186
+ return null;
2187
+ },
2188
+ // Fetch the payment products.
2189
+ /**
2190
+ * @docs:
2191
+ * @nav: Frontend
2192
+ * @chapter: Payments
2193
+ * @title: Payment Products
2194
+ * @description: Get the backend defined payment products asynchronously.
2195
+ * @type: array[object]
2196
+ * @return: Returns the backend defined payment products.
2197
+ */
2198
+ get_products: async function () {
2199
+ return new Promise((resolve, reject) => {
2200
+ if (this._products !== undefined) {
2201
+ return resolve(this._products);
2202
+ }
2203
+ Utils.request({
2204
+ method: "GET",
2205
+ url: "/volt/payments/products",
2206
+ })
2207
+ .then((products) => {
2208
+ this._products = products;
2209
+ resolve(this._products);
2210
+ })
2211
+ .catch((err) => {
2212
+ reject(err);
2213
+ });
2214
+ });
2215
+ },
2216
+ // Fetch a payment product by id.
2217
+ /**
2218
+ * @docs:
2219
+ * @nav: Frontend
2220
+ * @chapter: Payments
2221
+ * @title: Get Payment Product
2222
+ * @description: Get the backend defined payment product by id asynchronously.
2223
+ * @type: object
2224
+ * @return: Returns the backend defined payment product.
2225
+ * @param:
2226
+ * @name: id
2227
+ * @required: true
2228
+ * @type: string
2229
+ * @desc: The id of the payment product.
2230
+ */
2231
+ get_product: async function (id) {
2232
+ return new Promise(async (resolve, reject) => {
2233
+ const products = await this.get_products();
2234
+ let product = null;
2235
+ for (const p of products) {
2236
+ if (p.id === id) {
2237
+ product = p;
2238
+ break;
2239
+ }
2240
+ if (p.is_subscription) {
2241
+ for (const plan of p.plans) {
2242
+ if (plan.id === id) {
2243
+ product = plan;
2244
+ break;
2245
+ }
2246
+ }
2247
+ if (product)
2248
+ break;
2249
+ }
2250
+ }
2251
+ if (product == null) {
2252
+ return reject(new Error(`Product "${id}" does not exist.`));
2253
+ }
2254
+ resolve(product);
2255
+ });
2256
+ },
2257
+ // Fetch a payment object by id.
2258
+ /**
2259
+ * @docs:
2260
+ * @nav: Frontend
2261
+ * @chapter: Payments
2262
+ * @title: Get Payment.
2263
+ * @desc: Get a payment by id.
2264
+ * @param:
2265
+ * @name: id
2266
+ * @required: true
2267
+ * @type: string
2268
+ * @desc: The id of the payment.
2269
+ */
2270
+ get_payment: async function (id) {
2271
+ return Utils.request({
2272
+ method: "GET",
2273
+ url: "/volt/payments/payment",
2274
+ data: {
2275
+ id: id,
2276
+ }
2277
+ });
2278
+ },
2279
+ // Get all payments.
2280
+ /**
2281
+ * @docs:
2282
+ * @nav: Frontend
2283
+ * @chapter: Payments
2284
+ * @title: Get Refunded Payments.
2285
+ * @desc:
2286
+ * Get all payments of the authenticated user
2287
+ *
2288
+ * All failed payments are no longer stored in the database.
2289
+ * @param:
2290
+ * @name: days
2291
+ * @type: number
2292
+ * @desc: Retrieve payments from the last amount of days.
2293
+ * @param:
2294
+ * @name: limit
2295
+ * @type: number
2296
+ * @desc: Limit the amount of response payment objects.
2297
+ * @param:
2298
+ * @name: status
2299
+ * @type: string
2300
+ * @desc: Filter the payments by status. Be aware that the line items of a payment also have a status with possible values of `open`, `cancelled`, `refunding` or `refunded.`
2301
+ * @enum:
2302
+ * @value: "open"
2303
+ * @desc: Payments that are still open and unpaid.
2304
+ * @enum:
2305
+ * @value: "paid"
2306
+ * @desc: Payments that are paid.
2307
+ */
2308
+ get_payments: async function ({ days = 30, limit = null, status = null, } = {}) {
2309
+ return Utils.request({
2310
+ method: "GET",
2311
+ url: "/volt/payments/payments",
2312
+ data: {
2313
+ days,
2314
+ limit,
2315
+ status,
2316
+ }
2317
+ });
2318
+ },
2319
+ // Get refundable payments.
2320
+ /**
2321
+ * @docs:
2322
+ * @nav: Frontend
2323
+ * @chapter: Payments
2324
+ * @title: Get Refundable Payments.
2325
+ * @desc: Get all payments that are refundable for the authenticated user.
2326
+ * @param:
2327
+ * @name: days
2328
+ * @type: number
2329
+ * @desc: Retrieve payments from the last amount of days.
2330
+ * @param:
2331
+ * @name: limit
2332
+ * @type: number
2333
+ * @desc: Limit the amount of response payment objects.
2334
+ */
2335
+ get_refundable_payments: async function ({ days = 30, limit = null, } = {}) {
2336
+ return Utils.request({
2337
+ method: "GET",
2338
+ url: "/volt/payments/payments/refundable",
2339
+ data: {
2340
+ days,
2341
+ limit,
2342
+ }
2343
+ });
2344
+ },
2345
+ // Get refunded payments.
2346
+ /**
2347
+ * @docs:
2348
+ * @nav: Frontend
2349
+ * @chapter: Payments
2350
+ * @title: Get Refunded Payments.
2351
+ * @desc: Get all successfully refunded payments of the authenticated user.
2352
+ * @param:
2353
+ * @name: days
2354
+ * @type: number
2355
+ * @desc: Retrieve payments from the last amount of days.
2356
+ * @param:
2357
+ * @name: limit
2358
+ * @type: number
2359
+ * @desc: Limit the amount of response payment objects.
2360
+ */
2361
+ get_refunded_payments: async function ({ days = 30, limit = null, } = {}) {
2362
+ return Utils.request({
2363
+ method: "GET",
2364
+ url: "/volt/payments/payments/refunded",
2365
+ data: {
2366
+ days,
2367
+ limit,
2368
+ }
2369
+ });
2370
+ },
2371
+ // Get refunding payments.
2372
+ /**
2373
+ * @docs:
2374
+ * @nav: Frontend
2375
+ * @chapter: Payments
2376
+ * @title: Get Refunding Payments.
2377
+ * @desc: Get all payments that are currently in the refunding process of the authenticated user.
2378
+ * @param:
2379
+ * @name: days
2380
+ * @type: number
2381
+ * @desc: Retrieve payments from the last amount of days.
2382
+ * @param:
2383
+ * @name: limit
2384
+ * @type: number
2385
+ * @desc: Limit the amount of response payment objects.
2386
+ */
2387
+ get_refunding_payments: async function ({ days = null, limit = null, } = {}) {
2388
+ return Utils.request({
2389
+ method: "GET",
2390
+ url: "/volt/payments/payments/refunding",
2391
+ data: {
2392
+ days,
2393
+ limit,
2394
+ }
2395
+ });
2396
+ },
2397
+ // Create refund.
2398
+ /**
2399
+ * @docs:
2400
+ * @nav: Frontend
2401
+ * @chapter: Payments
2402
+ * @title: Refund Payment.
2403
+ * @desc: Refund a payment based on the payment id for the authenticated user.
2404
+ * @warning: Refunding a subscription will also cancel all other subscriptions that were created by the same payment request.
2405
+ * @param:
2406
+ * @name: payment
2407
+ * @required: true
2408
+ * @type: number | string
2409
+ * @desc: The id of the payment object or the payment object itself.
2410
+ * @param:
2411
+ * @name: line_items
2412
+ * @required: true
2413
+ * @type: array[object]
2414
+ * @desc: The line items to refund, these must be retrieved from the original payment line items otherwise it may cause undefined behaviour. When undefined the entire payment will be refunded.
2415
+ * @param:
2416
+ * @name: reason
2417
+ * @type: string
2418
+ * @desc: The refund reason.
2419
+ */
2420
+ create_refund: async function (payment, line_items = null, reason = "refund") {
2421
+ return Utils.request({
2422
+ method: "POST",
2423
+ url: "/volt/payments/refund",
2424
+ data: {
2425
+ payment,
2426
+ line_items,
2427
+ reason,
2428
+ }
2429
+ });
2430
+ },
2431
+ // Cancel subscription.
2432
+ /**
2433
+ * @docs:
2434
+ * @nav: Frontend
2435
+ * @chapter: Payments
2436
+ * @title: Cancel Subscription.
2437
+ * @desc: Cancel a subscription based on the product id.
2438
+ * @warning: Cancelling a subscription will also cancel all other subscriptions that were created by the same payment request.
2439
+ * @param:
2440
+ * @name: product
2441
+ * @required: true
2442
+ * @type: string
2443
+ * @desc: The product id.
2444
+ */
2445
+ cancel_subscription: async function (product) {
2446
+ return Utils.request({
2447
+ method: "DELETE",
2448
+ url: "/volt/payments/subscription",
2449
+ data: {
2450
+ product,
2451
+ }
2452
+ });
2453
+ },
2454
+ // Is subscribed.
2455
+ /**
2456
+ * @docs:
2457
+ * @nav: Frontend
2458
+ * @chapter: Payments
2459
+ * @title: Is Subscribed.
2460
+ * @desc: Check if the authenticated user is subscribed to a product plan.
2461
+ * @param:
2462
+ * @name: product
2463
+ * @required: true
2464
+ * @type: string
2465
+ * @desc: The product id.
2466
+ */
2467
+ is_subscribed: async function (product) {
2468
+ return Utils.request({
2469
+ method: "GET",
2470
+ url: "/volt/payments/subscribed",
2471
+ data: {
2472
+ product,
2473
+ }
2474
+ });
2475
+ },
2476
+ // Get active subscriptions.
2477
+ /**
2478
+ * @docs:
2479
+ * @nav: Frontend
2480
+ * @chapter: Payments
2481
+ * @title: Get active subscriptions
2482
+ * @desc: Get the active subscriptions of the authenticated user.
2483
+ */
2484
+ get_active_subscriptions: async function () {
2485
+ return Utils.request({
2486
+ method: "GET",
2487
+ url: "/volt/payments/active_subscriptions",
2488
+ });
2489
+ },
2490
+ // Shopping cart.
2491
+ // The shopping cart object.
2492
+ cart: {
2493
+ items: [],
2494
+ // Refresh the shopping cart.
2495
+ /**
2496
+ * @docs:
2497
+ * @nav: Frontend
2498
+ * @chapter: Payments
2499
+ * @title: Refresh Cart
2500
+ * @description:
2501
+ * Refresh the shopping cart.
2502
+ *
2503
+ * The current cart items are accessible as `Payments.cart.items`.
2504
+ */
2505
+ refresh: function () {
2506
+ // Load from local storage.
2507
+ try {
2508
+ this.items = JSON.parse(localStorage.getItem("volt_shopping_cart")) || [];
2509
+ }
2510
+ catch (err) {
2511
+ this.items = [];
2512
+ }
2513
+ // Reset the charge objects.
2514
+ Payments._reset();
2515
+ },
2516
+ // Save the shopping cart.
2517
+ /**
2518
+ * @docs:
2519
+ * @nav: Frontend
2520
+ * @chapter: Payments
2521
+ * @title: Save Cart
2522
+ * @description:
2523
+ * Save the shopping cart in the local storage.
2524
+ *
2525
+ * The current cart items are accessible as `Payments.cart.items`.
2526
+ */
2527
+ save: function () {
2528
+ // Save to local storage.
2529
+ localStorage.setItem("volt_shopping_cart", JSON.stringify(this.items));
2530
+ // Reset the charge objects.
2531
+ Payments._reset();
2532
+ },
2533
+ // Add a product to the shopping cart.
2534
+ /**
2535
+ * @docs:
2536
+ * @nav: Frontend
2537
+ * @chapter: Payments
2538
+ * @title: Add to Cart
2539
+ * @description:
2540
+ * Add a product to the shopping cart.
2541
+ *
2542
+ * When the product was already added to the shopping cart only the quantity will be incremented.
2543
+ *
2544
+ * An error will be thrown if the product id does not exist.
2545
+ *
2546
+ * The current cart items are accessible as `Payments.cart.items`.
2547
+ * @param:
2548
+ * @name: id
2549
+ * @description: The product's id.
2550
+ * @type: string
2551
+ * @param:
2552
+ * @name: quantity
2553
+ * @description: The quantity to add.
2554
+ * @type: number
2555
+ */
2556
+ add: async function (id, quantity = 1) {
2557
+ this.refresh(); // Update in case another window has updated the cart.
2558
+ const found = this.items.some((item) => {
2559
+ if (item.product.id === id) {
2560
+ item.quantity += quantity;
2561
+ return true;
2562
+ }
2563
+ return false;
2564
+ });
2565
+ if (!found) {
2566
+ try {
2567
+ const product = await Payments.get_product(id);
2568
+ this.items.push({
2569
+ product: product,
2570
+ quantity: quantity,
2571
+ });
2572
+ }
2573
+ catch (error) {
2574
+ console.error(error);
2575
+ Payments.on_error(error);
2576
+ throw new Error(`Failed to add product with id "${id}" to the cart.`);
2577
+ }
2578
+ }
2579
+ this.save();
2580
+ },
2581
+ // Remove a product from the shopping cart.
2582
+ /**
2583
+ * @docs:
2584
+ * @nav: Frontend
2585
+ * @chapter: Payments
2586
+ * @title: Remove from Cart
2587
+ * @description:
2588
+ * Remove a product from the shopping cart.
2589
+ *
2590
+ * Does not throw an error when the product was not added to the shopping cart.
2591
+ *
2592
+ * The current cart items are accessible as `Payments.cart.items`.
2593
+ * @param:
2594
+ * @name: id
2595
+ * @description: The product's id.
2596
+ * @type: string
2597
+ * @param:
2598
+ * @name: quantity
2599
+ * @description: The quantity to remove. When the quantity value is "all", the entire product will be removed from the shopping cart.
2600
+ * @type: number | "all"
2601
+ */
2602
+ remove: async function (id, quantity = 1) {
2603
+ this.refresh(); // Update in case another window has updated the cart.
2604
+ let new_cart = [];
2605
+ this.items.forEach((item) => {
2606
+ if (item.product.id === id) {
2607
+ if (quantity === "all") {
2608
+ item.quantity = 0;
2609
+ }
2610
+ else {
2611
+ item.quantity -= quantity;
2612
+ }
2613
+ }
2614
+ if (item.quantity > 0) {
2615
+ new_cart.push(item);
2616
+ }
2617
+ });
2618
+ this.items = new_cart;
2619
+ this.save();
2620
+ },
2621
+ // Clear the shopping cart.
2622
+ /**
2623
+ * @docs:
2624
+ * @nav: Frontend
2625
+ * @chapter: Payments
2626
+ * @title: Clear Cart
2627
+ * @description:
2628
+ * Clear the shopping cart.
2629
+ *
2630
+ * Will automatically be called if `Payments.confirm_charge()` finishes without any errors.
2631
+ *
2632
+ * The current cart items are accessible as `Payments.cart.items`.
2633
+ */
2634
+ clear: async function () {
2635
+ this.items = [];
2636
+ this.save();
2637
+ }
2638
+ },
2639
+ };
2640
+ // Exports.
2641
+ export { Payments };