@m5kdev/web-ui 0.1.3 → 0.1.5

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 (375) hide show
  1. package/dist/src/animations/card.motion.d.ts +2 -0
  2. package/dist/src/animations/card.motion.js +7 -0
  3. package/dist/src/components/AvatarUpload.d.ts +7 -0
  4. package/dist/src/components/AvatarUpload.js +67 -0
  5. package/dist/src/components/Button.d.ts +5 -0
  6. package/dist/src/components/Button.js +5 -0
  7. package/dist/src/components/Calendar.d.ts +35 -0
  8. package/dist/src/components/Calendar.js +10 -0
  9. package/dist/src/components/CardsSelect.d.ts +23 -0
  10. package/dist/src/components/CardsSelect.js +46 -0
  11. package/dist/src/components/CollapsibleSidebarMenuItem.d.ts +9 -0
  12. package/dist/src/components/CollapsibleSidebarMenuItem.js +11 -0
  13. package/dist/src/components/ColorPicker.d.ts +4 -0
  14. package/dist/src/components/ColorPicker.js +21 -0
  15. package/dist/src/components/CopyButton.d.ts +6 -0
  16. package/dist/src/components/CopyButton.js +24 -0
  17. package/dist/src/components/CropDialog.d.ts +10 -0
  18. package/dist/src/components/CropDialog.js +67 -0
  19. package/dist/src/components/DialogProvider.d.ts +15 -0
  20. package/dist/src/components/DialogProvider.js +50 -0
  21. package/dist/src/components/ErrorFallback.d.ts +4 -0
  22. package/dist/src/components/ErrorFallback.js +5 -0
  23. package/dist/src/components/FileDropzone.d.ts +6 -0
  24. package/dist/src/components/FileDropzone.js +63 -0
  25. package/dist/src/components/MultiSelectDropdown.d.ts +26 -0
  26. package/dist/src/components/MultiSelectDropdown.js +53 -0
  27. package/dist/src/components/Orb.d.ts +6 -0
  28. package/{src/components/Orb.tsx → dist/src/components/Orb.js} +107 -136
  29. package/dist/src/components/PageAlert.d.ts +18 -0
  30. package/dist/src/components/PageAlert.js +48 -0
  31. package/dist/src/components/SelectChips.d.ts +10 -0
  32. package/dist/src/components/SelectChips.js +11 -0
  33. package/dist/src/components/SidebarItem.d.ts +7 -0
  34. package/dist/src/components/SidebarItem.js +6 -0
  35. package/dist/src/components/Steps.d.ts +19 -0
  36. package/dist/src/components/Steps.js +34 -0
  37. package/dist/src/components/TablerIconPicker.d.ts +2 -0
  38. package/dist/src/components/TablerIconPicker.js +4238 -0
  39. package/dist/src/components/app-header.d.ts +6 -0
  40. package/dist/src/components/app-header.js +8 -0
  41. package/dist/src/components/blur-card.d.ts +13 -0
  42. package/dist/src/components/blur-card.js +34 -0
  43. package/dist/src/components/features-section-demo-1.d.ts +6 -0
  44. package/dist/src/components/features-section-demo-1.js +53 -0
  45. package/dist/src/components/features-section-demo-2.d.ts +1 -0
  46. package/dist/src/components/features-section-demo-2.js +51 -0
  47. package/dist/src/components/features-section-demo-3.d.ts +8 -0
  48. package/dist/src/components/features-section-demo-3.js +116 -0
  49. package/dist/src/components/mode-toggle.d.ts +1 -0
  50. package/dist/src/components/mode-toggle.js +9 -0
  51. package/dist/src/components/nav-main.d.ts +13 -0
  52. package/dist/src/components/nav-main.js +9 -0
  53. package/dist/src/components/pricing-cards.d.ts +1 -0
  54. package/dist/src/components/pricing-cards.js +27 -0
  55. package/dist/src/components/shared/ButtonCopy.d.ts +6 -0
  56. package/dist/src/components/shared/ButtonCopy.js +24 -0
  57. package/dist/src/components/team-switcher.d.ts +8 -0
  58. package/dist/src/components/team-switcher.js +10 -0
  59. package/dist/src/components/theme-provider.d.ts +13 -0
  60. package/dist/src/components/theme-provider.js +41 -0
  61. package/dist/src/components/typewriter.d.ts +18 -0
  62. package/dist/src/components/typewriter.js +38 -0
  63. package/dist/src/components/ui/alert-dialog.d.ts +14 -0
  64. package/dist/src/components/ui/alert-dialog.js +38 -0
  65. package/dist/src/components/ui/alert.d.ts +9 -0
  66. package/dist/src/components/ui/alert.js +24 -0
  67. package/dist/src/components/ui/avatar.d.ts +6 -0
  68. package/dist/src/components/ui/avatar.js +12 -0
  69. package/dist/src/components/ui/badge.d.ts +9 -0
  70. package/dist/src/components/ui/badge.js +20 -0
  71. package/dist/src/components/ui/bento-grid.d.ts +11 -0
  72. package/dist/src/components/ui/bento-grid.js +8 -0
  73. package/dist/src/components/ui/bento-grid2.d.ts +15 -0
  74. package/dist/src/components/ui/bento-grid2.js +13 -0
  75. package/dist/src/components/ui/breadcrumb.d.ts +19 -0
  76. package/dist/src/components/ui/breadcrumb.js +23 -0
  77. package/dist/src/components/ui/button.d.ts +11 -0
  78. package/dist/src/components/ui/button.js +33 -0
  79. package/dist/src/components/ui/card.d.ts +8 -0
  80. package/dist/src/components/ui/card.js +16 -0
  81. package/dist/src/components/ui/checkbox.d.ts +4 -0
  82. package/dist/src/components/ui/checkbox.js +8 -0
  83. package/dist/src/components/ui/collapsible.d.ts +5 -0
  84. package/{src/components/ui/collapsible.tsx → dist/src/components/ui/collapsible.js} +5 -9
  85. package/dist/src/components/ui/dialog.d.ts +13 -0
  86. package/dist/src/components/ui/dialog.js +35 -0
  87. package/dist/src/components/ui/dropdown-menu.d.ts +27 -0
  88. package/dist/src/components/ui/dropdown-menu.js +32 -0
  89. package/dist/src/components/ui/floating-navbar.d.ts +9 -0
  90. package/dist/src/components/ui/floating-navbar.js +38 -0
  91. package/dist/src/components/ui/form.d.ts +23 -0
  92. package/dist/src/components/ui/form.js +60 -0
  93. package/dist/src/components/ui/image.d.ts +6 -0
  94. package/dist/src/components/ui/image.js +15 -0
  95. package/dist/src/components/ui/input.d.ts +3 -0
  96. package/dist/src/components/ui/input.js +8 -0
  97. package/dist/src/components/ui/label.d.ts +5 -0
  98. package/dist/src/components/ui/label.js +9 -0
  99. package/dist/src/components/ui/pagination.d.ts +13 -0
  100. package/dist/src/components/ui/pagination.js +29 -0
  101. package/dist/src/components/ui/progress.d.ts +4 -0
  102. package/dist/src/components/ui/progress.js +7 -0
  103. package/dist/src/components/ui/resizable-navbar.d.ts +56 -0
  104. package/dist/src/components/ui/resizable-navbar.js +86 -0
  105. package/dist/src/components/ui/segment-control.d.ts +9 -0
  106. package/dist/src/components/ui/segment-control.js +42 -0
  107. package/dist/src/components/ui/select.d.ts +13 -0
  108. package/dist/src/components/ui/select.js +26 -0
  109. package/dist/src/components/ui/separator.d.ts +4 -0
  110. package/dist/src/components/ui/separator.js +7 -0
  111. package/dist/src/components/ui/sheet.d.ts +25 -0
  112. package/dist/src/components/ui/sheet.js +37 -0
  113. package/dist/src/components/ui/sidebar.d.ts +66 -0
  114. package/dist/src/components/ui/sidebar.js +222 -0
  115. package/dist/src/components/ui/skeleton.d.ts +2 -0
  116. package/dist/src/components/ui/skeleton.js +6 -0
  117. package/dist/src/components/ui/slider.d.ts +4 -0
  118. package/dist/src/components/ui/slider.js +7 -0
  119. package/dist/src/components/ui/sonner.d.ts +4 -0
  120. package/dist/src/components/ui/sonner.js +15 -0
  121. package/dist/src/components/ui/spinner.d.ts +14 -0
  122. package/dist/src/components/ui/spinner.js +30 -0
  123. package/dist/src/components/ui/switch.d.ts +4 -0
  124. package/dist/src/components/ui/switch.js +7 -0
  125. package/dist/src/components/ui/table.d.ts +10 -0
  126. package/dist/src/components/ui/table.js +27 -0
  127. package/dist/src/components/ui/tabs.d.ts +7 -0
  128. package/dist/src/components/ui/tabs.js +16 -0
  129. package/dist/src/components/ui/textarea.d.ts +3 -0
  130. package/dist/src/components/ui/textarea.js +6 -0
  131. package/dist/src/components/ui/timeline.d.ts +11 -0
  132. package/dist/src/components/ui/timeline.js +27 -0
  133. package/dist/src/components/ui/toast.d.ts +15 -0
  134. package/dist/src/components/ui/toast.js +33 -0
  135. package/dist/src/components/ui/tooltip.d.ts +7 -0
  136. package/dist/src/components/ui/tooltip.js +16 -0
  137. package/dist/src/components/ui/typewriter-effect.d.ts +16 -0
  138. package/dist/src/components/ui/typewriter-effect.js +76 -0
  139. package/dist/src/hooks/use-mobile.d.ts +1 -0
  140. package/dist/src/hooks/use-mobile.js +15 -0
  141. package/dist/src/hooks/useDialog.d.ts +4 -0
  142. package/dist/src/hooks/useDialog.js +22 -0
  143. package/dist/src/icons/GoogleIcon.d.ts +5 -0
  144. package/dist/src/icons/GoogleIcon.js +4 -0
  145. package/dist/src/icons/LinkedInIcon.d.ts +5 -0
  146. package/dist/src/icons/LinkedInIcon.js +4 -0
  147. package/dist/src/icons/MicrosoftIcon.d.ts +5 -0
  148. package/dist/src/icons/MicrosoftIcon.js +4 -0
  149. package/dist/src/lib/chatwoot.d.ts +11 -0
  150. package/dist/src/lib/chatwoot.js +28 -0
  151. package/dist/src/lib/utils.d.ts +2 -0
  152. package/dist/src/lib/utils.js +5 -0
  153. package/dist/src/modules/app/components/AppLoader.d.ts +2 -0
  154. package/dist/src/modules/app/components/AppLoader.js +5 -0
  155. package/dist/src/modules/app/components/AppShell.d.ts +7 -0
  156. package/dist/src/modules/app/components/AppShell.js +7 -0
  157. package/dist/src/modules/app/components/AppSidebar.d.ts +7 -0
  158. package/dist/src/modules/app/components/AppSidebar.js +5 -0
  159. package/dist/src/modules/app/components/AppSidebarContent.d.ts +16 -0
  160. package/dist/src/modules/app/components/AppSidebarContent.js +7 -0
  161. package/dist/src/modules/app/components/AppSidebarHeader.d.ts +8 -0
  162. package/dist/src/modules/app/components/AppSidebarHeader.js +10 -0
  163. package/dist/src/modules/app/components/AppSidebarInvites.d.ts +3 -0
  164. package/dist/src/modules/app/components/AppSidebarInvites.js +12 -0
  165. package/dist/src/modules/app/components/AppSidebarUser.d.ts +11 -0
  166. package/dist/src/modules/app/components/AppSidebarUser.js +16 -0
  167. package/dist/src/modules/auth/components/AdminUserManagement.d.ts +6 -0
  168. package/dist/src/modules/auth/components/AdminUserManagement.js +422 -0
  169. package/dist/src/modules/auth/components/AdminWaitlist.d.ts +6 -0
  170. package/dist/src/modules/auth/components/AdminWaitlist.js +118 -0
  171. package/dist/src/modules/auth/components/AuthLayout.d.ts +4 -0
  172. package/dist/src/modules/auth/components/AuthLayout.js +5 -0
  173. package/dist/src/modules/auth/components/AuthProviders.d.ts +6 -0
  174. package/dist/src/modules/auth/components/AuthProviders.js +45 -0
  175. package/dist/src/modules/auth/components/AuthRouter.d.ts +9 -0
  176. package/dist/src/modules/auth/components/AuthRouter.js +12 -0
  177. package/dist/src/modules/auth/components/ClaimAccountRoute.d.ts +4 -0
  178. package/dist/src/modules/auth/components/ClaimAccountRoute.js +143 -0
  179. package/dist/src/modules/auth/components/ErrorAuthRoute.d.ts +1 -0
  180. package/dist/src/modules/auth/components/ErrorAuthRoute.js +93 -0
  181. package/dist/src/modules/auth/components/ForgotPasswordForm.d.ts +1 -0
  182. package/dist/src/modules/auth/components/ForgotPasswordForm.js +27 -0
  183. package/dist/src/modules/auth/components/ForgotPasswordRoute.d.ts +1 -0
  184. package/dist/src/modules/auth/components/ForgotPasswordRoute.js +9 -0
  185. package/dist/src/modules/auth/components/InviteFriends.d.ts +5 -0
  186. package/dist/src/modules/auth/components/InviteFriends.js +74 -0
  187. package/dist/src/modules/auth/components/LastUsedBadge.d.ts +5 -0
  188. package/dist/src/modules/auth/components/LastUsedBadge.js +9 -0
  189. package/dist/src/modules/auth/components/LoginForm.d.ts +3 -0
  190. package/dist/src/modules/auth/components/LoginForm.js +44 -0
  191. package/dist/src/modules/auth/components/LoginRoute.d.ts +3 -0
  192. package/dist/src/modules/auth/components/LoginRoute.js +11 -0
  193. package/dist/src/modules/auth/components/LogoutRoute.d.ts +1 -0
  194. package/dist/src/modules/auth/components/LogoutRoute.js +15 -0
  195. package/dist/src/modules/auth/components/OrganizationAcceptInvitationRoute.d.ts +9 -0
  196. package/dist/src/modules/auth/components/OrganizationAcceptInvitationRoute.js +102 -0
  197. package/dist/src/modules/auth/components/OrganizationMembersRoute.d.ts +51 -0
  198. package/dist/src/modules/auth/components/OrganizationMembersRoute.js +359 -0
  199. package/dist/src/modules/auth/components/OrganizationSettingsRoute.d.ts +20 -0
  200. package/dist/src/modules/auth/components/OrganizationSettingsRoute.js +153 -0
  201. package/dist/src/modules/auth/components/OrganizationSwitcher.d.ts +7 -0
  202. package/dist/src/modules/auth/components/OrganizationSwitcher.js +74 -0
  203. package/dist/src/modules/auth/components/ProfileRoute.d.ts +1 -0
  204. package/dist/src/modules/auth/components/ProfileRoute.js +42 -0
  205. package/dist/src/modules/auth/components/RangeNuqsDatePicker.d.ts +31 -0
  206. package/dist/src/modules/auth/components/RangeNuqsDatePicker.js +236 -0
  207. package/dist/src/modules/auth/components/ResetPasswordForm.d.ts +1 -0
  208. package/dist/src/modules/auth/components/ResetPasswordForm.js +39 -0
  209. package/dist/src/modules/auth/components/ResetPasswordRoute.d.ts +1 -0
  210. package/dist/src/modules/auth/components/ResetPasswordRoute.js +9 -0
  211. package/dist/src/modules/auth/components/SignupFormRoute.d.ts +5 -0
  212. package/dist/src/modules/auth/components/SignupFormRoute.js +106 -0
  213. package/dist/src/modules/auth/components/SignupRoute.d.ts +7 -0
  214. package/dist/src/modules/auth/components/SignupRoute.js +16 -0
  215. package/dist/src/modules/auth/components/UserPreferences.d.ts +30 -0
  216. package/dist/src/modules/auth/components/UserPreferences.js +60 -0
  217. package/dist/src/modules/auth/components/WaitlistCard.d.ts +6 -0
  218. package/dist/src/modules/auth/components/WaitlistCard.js +32 -0
  219. package/dist/src/modules/auth/components/WaitlistCodeValidation.d.ts +7 -0
  220. package/dist/src/modules/auth/components/WaitlistCodeValidation.js +43 -0
  221. package/dist/src/modules/billing/components/BillingBetaPage.d.ts +8 -0
  222. package/dist/src/modules/billing/components/BillingBetaPage.js +11 -0
  223. package/dist/src/modules/billing/components/BillingInvoicePage.d.ts +7 -0
  224. package/dist/src/modules/billing/components/BillingInvoicePage.js +32 -0
  225. package/dist/src/modules/billing/components/BillingPlanSelect.d.ts +6 -0
  226. package/dist/src/modules/billing/components/BillingPlanSelect.js +8 -0
  227. package/dist/src/modules/billing/components/BillingRouter.d.ts +9 -0
  228. package/dist/src/modules/billing/components/BillingRouter.js +8 -0
  229. package/dist/src/modules/billing/components/BillingSinglePlanSelect.d.ts +8 -0
  230. package/dist/src/modules/billing/components/BillingSinglePlanSelect.js +46 -0
  231. package/dist/src/modules/table/components/ColumnOrderAndVisibility.d.ts +10 -0
  232. package/dist/src/modules/table/components/ColumnOrderAndVisibility.js +42 -0
  233. package/dist/src/modules/table/components/NuqsTable.d.ts +23 -0
  234. package/dist/src/modules/table/components/NuqsTable.js +198 -0
  235. package/dist/src/modules/table/components/TableFiltering.d.ts +23 -0
  236. package/dist/src/modules/table/components/TableFiltering.js +236 -0
  237. package/dist/src/modules/table/components/TablePagination.d.ts +9 -0
  238. package/dist/src/modules/table/components/TablePagination.js +21 -0
  239. package/{src/modules/table/components/table.types.ts → dist/src/modules/table/components/table.types.d.ts} +12 -11
  240. package/dist/src/modules/table/components/table.types.js +1 -0
  241. package/dist/src/modules/table/filterTransformers.d.ts +53 -0
  242. package/dist/src/modules/table/filterTransformers.js +276 -0
  243. package/{src/types.ts → dist/src/types.d.ts} +3 -4
  244. package/dist/src/types.js +1 -0
  245. package/dist/tsconfig.lib.tsbuildinfo +1 -1
  246. package/package.json +8 -5
  247. package/.cursor/rules/web-ui.mdc +0 -126
  248. package/.turbo/turbo-build.log +0 -5
  249. package/.turbo/turbo-check-types.log +0 -5
  250. package/.turbo/turbo-lint$colon$fix.log +0 -381
  251. package/.turbo/turbo-lint.log +0 -361
  252. package/CHANGELOG.md +0 -19
  253. package/components.json +0 -21
  254. package/src/animations/card.motion.ts +0 -9
  255. package/src/components/AvatarUpload.tsx +0 -133
  256. package/src/components/Button.tsx +0 -14
  257. package/src/components/Calendar.css +0 -684
  258. package/src/components/Calendar.tsx +0 -32
  259. package/src/components/CardsSelect.tsx +0 -155
  260. package/src/components/CollapsibleSidebarMenuItem.tsx +0 -57
  261. package/src/components/ColorPicker.tsx +0 -56
  262. package/src/components/CopyButton.tsx +0 -45
  263. package/src/components/CropDialog.tsx +0 -154
  264. package/src/components/DialogProvider.tsx +0 -105
  265. package/src/components/ErrorFallback.tsx +0 -17
  266. package/src/components/FileDropzone.tsx +0 -120
  267. package/src/components/MultiSelectDropdown.tsx +0 -233
  268. package/src/components/PageAlert.tsx +0 -121
  269. package/src/components/SelectChips.tsx +0 -40
  270. package/src/components/SidebarItem.tsx +0 -26
  271. package/src/components/Steps.tsx +0 -340
  272. package/src/components/TablerIconPicker.tsx +0 -4260
  273. package/src/components/app-header.tsx +0 -40
  274. package/src/components/blur-card.tsx +0 -132
  275. package/src/components/features-section-demo-1.tsx +0 -127
  276. package/src/components/features-section-demo-2.tsx +0 -102
  277. package/src/components/features-section-demo-3.tsx +0 -272
  278. package/src/components/mode-toggle.tsx +0 -31
  279. package/src/components/nav-main.tsx +0 -69
  280. package/src/components/pricing-cards.tsx +0 -133
  281. package/src/components/shared/ButtonCopy.tsx +0 -50
  282. package/src/components/team-switcher.tsx +0 -83
  283. package/src/components/theme-provider.tsx +0 -74
  284. package/src/components/typewriter.tsx +0 -90
  285. package/src/components/ui/alert-dialog.tsx +0 -133
  286. package/src/components/ui/alert.tsx +0 -60
  287. package/src/components/ui/avatar.tsx +0 -47
  288. package/src/components/ui/badge.tsx +0 -33
  289. package/src/components/ui/bento-grid.tsx +0 -54
  290. package/src/components/ui/bento-grid2.tsx +0 -66
  291. package/src/components/ui/breadcrumb.tsx +0 -101
  292. package/src/components/ui/button.tsx +0 -50
  293. package/src/components/ui/card.tsx +0 -55
  294. package/src/components/ui/checkbox.tsx +0 -26
  295. package/src/components/ui/dialog.tsx +0 -119
  296. package/src/components/ui/dropdown-menu.tsx +0 -186
  297. package/src/components/ui/floating-navbar.tsx +0 -78
  298. package/src/components/ui/form.tsx +0 -167
  299. package/src/components/ui/image.tsx +0 -55
  300. package/src/components/ui/input.tsx +0 -22
  301. package/src/components/ui/label.tsx +0 -19
  302. package/src/components/ui/pagination.tsx +0 -105
  303. package/src/components/ui/progress.tsx +0 -23
  304. package/src/components/ui/resizable-navbar.tsx +0 -260
  305. package/src/components/ui/segment-control.tsx +0 -143
  306. package/src/components/ui/select.tsx +0 -153
  307. package/src/components/ui/separator.tsx +0 -24
  308. package/src/components/ui/sheet.tsx +0 -121
  309. package/src/components/ui/sidebar.tsx +0 -736
  310. package/src/components/ui/skeleton.tsx +0 -7
  311. package/src/components/ui/slider.tsx +0 -23
  312. package/src/components/ui/sonner.tsx +0 -27
  313. package/src/components/ui/spinner.tsx +0 -45
  314. package/src/components/ui/switch.tsx +0 -27
  315. package/src/components/ui/table.tsx +0 -90
  316. package/src/components/ui/tabs.tsx +0 -52
  317. package/src/components/ui/textarea.tsx +0 -18
  318. package/src/components/ui/timeline.tsx +0 -95
  319. package/src/components/ui/toast.tsx +0 -126
  320. package/src/components/ui/tooltip.tsx +0 -55
  321. package/src/components/ui/typewriter-effect.tsx +0 -181
  322. package/src/hooks/use-mobile.ts +0 -19
  323. package/src/hooks/useDialog.ts +0 -25
  324. package/src/icons/GoogleIcon.tsx +0 -32
  325. package/src/icons/LinkedInIcon.tsx +0 -30
  326. package/src/icons/MicrosoftIcon.tsx +0 -21
  327. package/src/lib/chatwoot.ts +0 -51
  328. package/src/lib/utils.ts +0 -6
  329. package/src/modules/app/components/AppLoader.tsx +0 -9
  330. package/src/modules/app/components/AppShell.tsx +0 -21
  331. package/src/modules/app/components/AppSidebar.tsx +0 -26
  332. package/src/modules/app/components/AppSidebarContent.tsx +0 -73
  333. package/src/modules/app/components/AppSidebarHeader.tsx +0 -57
  334. package/src/modules/app/components/AppSidebarInvites.tsx +0 -32
  335. package/src/modules/app/components/AppSidebarUser.tsx +0 -128
  336. package/src/modules/auth/components/AdminUserManagement.tsx +0 -1136
  337. package/src/modules/auth/components/AdminWaitlist.tsx +0 -358
  338. package/src/modules/auth/components/AuthLayout.tsx +0 -13
  339. package/src/modules/auth/components/AuthProviders.tsx +0 -105
  340. package/src/modules/auth/components/AuthRouter.tsx +0 -29
  341. package/src/modules/auth/components/ClaimAccountRoute.tsx +0 -242
  342. package/src/modules/auth/components/ErrorAuthRoute.tsx +0 -121
  343. package/src/modules/auth/components/ForgotPasswordForm.tsx +0 -58
  344. package/src/modules/auth/components/ForgotPasswordRoute.tsx +0 -27
  345. package/src/modules/auth/components/InviteFriends.tsx +0 -273
  346. package/src/modules/auth/components/LastUsedBadge.tsx +0 -22
  347. package/src/modules/auth/components/LoginForm.tsx +0 -104
  348. package/src/modules/auth/components/LoginRoute.tsx +0 -31
  349. package/src/modules/auth/components/LogoutRoute.tsx +0 -21
  350. package/src/modules/auth/components/OrganizationAcceptInvitationRoute.tsx +0 -161
  351. package/src/modules/auth/components/OrganizationMembersRoute.tsx +0 -730
  352. package/src/modules/auth/components/OrganizationSettingsRoute.tsx +0 -280
  353. package/src/modules/auth/components/OrganizationSwitcher.tsx +0 -148
  354. package/src/modules/auth/components/ProfileRoute.tsx +0 -104
  355. package/src/modules/auth/components/RangeNuqsDatePicker.tsx +0 -365
  356. package/src/modules/auth/components/ResetPasswordForm.tsx +0 -103
  357. package/src/modules/auth/components/ResetPasswordRoute.tsx +0 -27
  358. package/src/modules/auth/components/SignupFormRoute.tsx +0 -189
  359. package/src/modules/auth/components/SignupRoute.tsx +0 -53
  360. package/src/modules/auth/components/UserPreferences.tsx +0 -144
  361. package/src/modules/auth/components/WaitlistCard.tsx +0 -78
  362. package/src/modules/auth/components/WaitlistCodeValidation.tsx +0 -79
  363. package/src/modules/billing/components/BillingBetaPage.tsx +0 -124
  364. package/src/modules/billing/components/BillingInvoicePage.tsx +0 -180
  365. package/src/modules/billing/components/BillingPlanSelect.tsx +0 -14
  366. package/src/modules/billing/components/BillingRouter.tsx +0 -20
  367. package/src/modules/billing/components/BillingSinglePlanSelect.tsx +0 -172
  368. package/src/modules/table/components/ColumnOrderAndVisibility.tsx +0 -127
  369. package/src/modules/table/components/NuqsTable.tsx +0 -396
  370. package/src/modules/table/components/TableFiltering.tsx +0 -520
  371. package/src/modules/table/components/TablePagination.tsx +0 -59
  372. package/src/modules/table/filterTransformers.ts +0 -323
  373. package/src/vite-env.d.ts +0 -1
  374. package/translations/en/web-ui.json +0 -192
  375. package/tsconfig.json +0 -30
@@ -0,0 +1,60 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { Button, Form, Input, Select, SelectItem, Switch } from "@heroui/react";
3
+ import { useTranslation } from "react-i18next";
4
+ import { toast } from "sonner";
5
+ export function UserPreferences({ schema, controls, preferences, isLoading, isPending, updatePreferences, }) {
6
+ const { t } = useTranslation("web-ui");
7
+ function handleSubmit(event) {
8
+ event.preventDefault();
9
+ const formData = new FormData(event.currentTarget);
10
+ const keys = Object.keys(controls);
11
+ const raw = {};
12
+ for (const key of keys) {
13
+ const control = controls[key];
14
+ if (control.element === "switch") {
15
+ raw[String(key)] = formData.get(String(key)) != null;
16
+ }
17
+ if (control.element === "select") {
18
+ raw[String(key)] = formData.get(String(key));
19
+ }
20
+ if (control.element === "number") {
21
+ const value = formData.get(String(key));
22
+ raw[String(key)] = value == null || value === "" ? undefined : Number(value);
23
+ }
24
+ }
25
+ const result = schema.safeParse(raw);
26
+ if (result.success) {
27
+ updatePreferences(result.data, {
28
+ noOptimisticUpdate: true,
29
+ onSuccess: () => {
30
+ toast.success("Preferences updated");
31
+ },
32
+ onError: () => {
33
+ toast.error("Failed to update preferences");
34
+ },
35
+ });
36
+ }
37
+ else {
38
+ // eslint-disable-next-line no-console
39
+ console.error(result.error);
40
+ }
41
+ }
42
+ const keys = Object.keys(controls);
43
+ if (isLoading) {
44
+ // FIXME: Add a loading state
45
+ return _jsx("div", { children: "Loading..." });
46
+ }
47
+ return (_jsxs(Form, { onSubmit: handleSubmit, className: "p-6 flex flex-col gap-4", children: [_jsx("h1", { className: "text-2xl font-bold", children: t("web-ui:preferences.title") }), keys.map((key) => {
48
+ const control = controls[key];
49
+ switch (control.element) {
50
+ case "switch":
51
+ return (_jsx(Switch, { name: String(key), value: "on", defaultSelected: Boolean(preferences[key]), children: control.label }, String(key)));
52
+ case "select":
53
+ return (_jsx(Select, { name: String(key), label: control.label, labelPlacement: "outside-top", defaultSelectedKeys: [String(preferences[key])], children: (control.options ?? []).map((option) => (_jsx(SelectItem, { children: option.label }, option.value))) }, String(key)));
54
+ case "number":
55
+ return (_jsx(Input, { name: String(key), type: "number", label: control.label, labelPlacement: "outside-top", defaultValue: String(preferences[key] ?? ""), min: control.min, max: control.max, step: control.step }, String(key)));
56
+ default:
57
+ return _jsx("div", { children: "Invalid control" }, String(key));
58
+ }
59
+ }), _jsx(Button, { type: "submit", color: "success", isLoading: isPending, children: t("web-ui:preferences.submit") })] }));
60
+ }
@@ -0,0 +1,6 @@
1
+ import type { UseBackendTRPC } from "#types";
2
+ interface WaitlistCardProps {
3
+ useTRPC: UseBackendTRPC;
4
+ }
5
+ export declare function WaitlistCard({ useTRPC }: WaitlistCardProps): import("react/jsx-runtime").JSX.Element;
6
+ export {};
@@ -0,0 +1,32 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { Alert, Button, Card, CardBody, CardHeader, Input } from "@heroui/react";
3
+ import { useMutation } from "@tanstack/react-query";
4
+ import { useState } from "react";
5
+ import { useTranslation } from "react-i18next";
6
+ import { toast } from "sonner";
7
+ export function WaitlistCard({ useTRPC }) {
8
+ const { t } = useTranslation();
9
+ const trpc = useTRPC();
10
+ const [email, setEmail] = useState("");
11
+ const [joined, setJoined] = useState(false);
12
+ const { mutate } = useMutation(trpc.auth.joinWaitlist.mutationOptions());
13
+ const handleSubmit = (e) => {
14
+ e.preventDefault();
15
+ mutate({ email }, {
16
+ onSuccess: () => {
17
+ setJoined(true);
18
+ },
19
+ onError: (error) => {
20
+ toast.error(error instanceof Error
21
+ ? error.message
22
+ : t("web-ui:auth.waitlist.error", {
23
+ defaultValue: "Failed to join waitlist. Please try again.",
24
+ }));
25
+ },
26
+ });
27
+ };
28
+ if (joined) {
29
+ return (_jsx(Card, { children: _jsx(CardBody, { className: "pt-6", children: _jsx(Alert, { color: "success", variant: "faded", title: t("web-ui:auth.waitlist.success") }) }) }));
30
+ }
31
+ return (_jsxs(Card, { children: [_jsxs(CardHeader, { className: "text-center flex flex-col gap-1", children: [_jsx("p", { className: "text-xl font-semibold", children: t("web-ui:auth.waitlist.title") }), _jsx("p", { className: "text-sm text-default-600", children: t("web-ui:auth.waitlist.description") })] }), _jsx(CardBody, { children: _jsxs("form", { onSubmit: handleSubmit, className: "grid gap-6", children: [_jsx("div", { className: "grid gap-2", children: _jsx(Input, { type: "email", label: t("web-ui:auth.waitlist.email"), labelPlacement: "outside", placeholder: t("web-ui:auth.waitlist.placeholder.email"), isRequired: true, variant: "bordered", value: email, onChange: (e) => setEmail(e.target.value) }) }), _jsx(Button, { type: "submit", color: "primary", children: t("web-ui:auth.waitlist.button") })] }) })] }));
32
+ }
@@ -0,0 +1,7 @@
1
+ import type { UseBackendTRPC } from "#types";
2
+ interface WaitlistCodeValidationProps {
3
+ useTRPC: UseBackendTRPC;
4
+ code: string;
5
+ }
6
+ export declare function WaitlistCodeValidation({ useTRPC, code }: WaitlistCodeValidationProps): import("react/jsx-runtime").JSX.Element | null;
7
+ export {};
@@ -0,0 +1,43 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { Alert } from "@heroui/react";
3
+ import { useQuery } from "@tanstack/react-query";
4
+ import { useTranslation } from "react-i18next";
5
+ export function WaitlistCodeValidation({ useTRPC, code }) {
6
+ const { t } = useTranslation();
7
+ const trpc = useTRPC();
8
+ const { data, isLoading, error } = useQuery(trpc.auth.validateWaitlistCode.queryOptions({ code }));
9
+ const status = data?.status;
10
+ const className = "p-1";
11
+ if (isLoading) {
12
+ return (_jsx(Alert, { className: className, color: "default", variant: "faded", title: t("web-ui:auth.waitlist.validatingCode", {
13
+ defaultValue: "Validating the invitation code...",
14
+ }) }));
15
+ }
16
+ if (error) {
17
+ return (_jsx(Alert, { className: className, color: "danger", variant: "faded", title: t("web-ui:auth.waitlist.codeError", {
18
+ defaultValue: "An error occurred while validating the invitation code.",
19
+ }) }));
20
+ }
21
+ if (status === "VALID") {
22
+ return (_jsx(Alert, { className: className, color: "success", variant: "faded", title: t("web-ui:auth.waitlist.codeValid", {
23
+ defaultValue: "Invitation code is valid. You can proceed.",
24
+ }) }));
25
+ }
26
+ if (status) {
27
+ let message = t("web-ui:auth.waitlist.invalidCode", {
28
+ defaultValue: "Invalid invitation code.",
29
+ });
30
+ if (status === "EXPIRED") {
31
+ message = t("web-ui:auth.waitlist.expiredCode", {
32
+ defaultValue: "Invitation code has expired.",
33
+ });
34
+ }
35
+ else if (status === "NOT_FOUND") {
36
+ message = t("web-ui:auth.waitlist.codeNotFound", {
37
+ defaultValue: "Invitation code not found.",
38
+ });
39
+ }
40
+ return _jsx(Alert, { className: className, color: "danger", variant: "faded", title: message });
41
+ }
42
+ return null;
43
+ }
@@ -0,0 +1,8 @@
1
+ import type { ReactNode } from "react";
2
+ interface BillingBetaPageProps {
3
+ appName: string;
4
+ className?: string;
5
+ footer?: ReactNode;
6
+ }
7
+ export declare function BillingBetaPage({ appName, className, footer }: BillingBetaPageProps): import("react/jsx-runtime").JSX.Element;
8
+ export {};
@@ -0,0 +1,11 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { Bell, CheckCircle2, Clock3, Sparkles } from "lucide-react";
3
+ import { useTranslation } from "react-i18next";
4
+ import { Badge } from "#components/ui/badge";
5
+ import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "#components/ui/card";
6
+ import { Separator } from "#components/ui/separator";
7
+ import { cn } from "#utils";
8
+ export function BillingBetaPage({ appName, className, footer }) {
9
+ const { t } = useTranslation("web-ui");
10
+ return (_jsxs("div", { className: cn("mx-auto max-w-5xl px-4 py-12 md:py-16", className), children: [_jsxs("div", { className: "flex flex-col items-center text-center gap-4", children: [_jsx(Badge, { variant: "secondary", className: "uppercase tracking-wide", children: t("billing.beta.badge") }), _jsxs("div", { className: "space-y-3", children: [_jsx("h1", { className: "text-3xl md:text-4xl font-semibold tracking-tight", children: t("billing.title") }), _jsx("p", { className: "text-muted-foreground max-w-2xl", children: t("billing.subtitle", { appName }) })] })] }), _jsx(Separator, { className: "my-8" }), _jsxs("div", { className: "grid grid-cols-1 md:grid-cols-3 gap-4 md:gap-6", children: [_jsxs(Card, { children: [_jsxs(CardHeader, { className: "space-y-2", children: [_jsxs("div", { className: "flex items-center gap-2 text-green-600 dark:text-green-500", children: [_jsx(Sparkles, { className: "h-5 w-5 shrink-0" }), _jsx(CardTitle, { children: t("billing.card.free.title") })] }), _jsx(CardDescription, { children: t("billing.card.free.description") })] }), _jsxs(CardContent, { children: [_jsxs("div", { className: "flex items-baseline gap-2", children: [_jsx("span", { className: "text-4xl font-bold tracking-tight", children: t("billing.card.free.price") }), _jsx("span", { className: "text-muted-foreground", children: t("billing.card.free.priceSuffix") })] }), _jsxs("ul", { className: "mt-4 space-y-2 text-sm", children: [_jsxs("li", { className: "flex items-center gap-2", children: [_jsx(CheckCircle2, { className: "h-4 w-4 shrink-0 text-green-600" }), " ", t("billing.card.free.feature.fullAccess")] }), _jsxs("li", { className: "flex items-center gap-2", children: [_jsx(CheckCircle2, { className: "h-4 w-4 shrink-0 text-green-600" }), " ", t("billing.card.free.feature.noCard")] }), _jsxs("li", { className: "flex items-center gap-2", children: [_jsx(CheckCircle2, { className: "h-4 w-4 shrink-0 text-green-600" }), " ", t("billing.card.free.feature.riskFree")] })] })] })] }), _jsxs(Card, { children: [_jsxs(CardHeader, { className: "space-y-2", children: [_jsxs("div", { className: "flex items-center gap-2 text-blue-600 dark:text-blue-500", children: [_jsx(Clock3, { className: "h-5 w-5 shrink-0" }), _jsx(CardTitle, { children: t("billing.card.progress.title") })] }), _jsx(CardDescription, { children: t("billing.card.progress.description") })] }), _jsx(CardContent, { children: _jsxs("ul", { className: "space-y-2 text-sm", children: [_jsxs("li", { className: "flex items-center gap-2", children: [_jsx(CheckCircle2, { className: "h-4 w-4 shrink-0 text-blue-600" }), " ", t("billing.card.progress.feature.transparentPlans")] }), _jsxs("li", { className: "flex items-center gap-2", children: [_jsx(CheckCircle2, { className: "h-4 w-4 shrink-0 text-blue-600" }), " ", t("billing.card.progress.feature.fairValue")] }), _jsxs("li", { className: "flex items-center gap-2", children: [_jsx(CheckCircle2, { className: "h-4 w-4 shrink-0 text-blue-600" }), " ", t("billing.card.progress.feature.simpleBilling")] })] }) })] }), _jsxs(Card, { children: [_jsxs(CardHeader, { className: "space-y-2", children: [_jsxs("div", { className: "flex items-center gap-2 text-amber-600 dark:text-amber-500", children: [_jsx(Bell, { className: "h-5 w-5 shrink-0" }), _jsx(CardTitle, { children: t("billing.card.notice.title") })] }), _jsx(CardDescription, { children: t("billing.card.notice.description") })] }), _jsx(CardContent, { children: _jsxs("ul", { className: "space-y-2 text-sm", children: [_jsxs("li", { className: "flex items-center gap-2", children: [_jsx(CheckCircle2, { className: "h-4 w-4 shrink-0 text-amber-600" }), " ", t("billing.card.notice.feature.timeToDecide")] }), _jsxs("li", { className: "flex items-center gap-2", children: [_jsx(CheckCircle2, { className: "h-4 w-4 shrink-0 text-amber-600" }), " ", t("billing.card.notice.feature.safeData")] }), _jsxs("li", { className: "flex items-center gap-2", children: [_jsx(CheckCircle2, { className: "h-4 w-4 shrink-0 text-amber-600" }), " ", t("billing.card.notice.feature.autoFreeTier")] })] }) })] })] }), footer] }));
11
+ }
@@ -0,0 +1,7 @@
1
+ import type { UseBackendTRPC } from "#types";
2
+ interface BillingInvoicePageProps {
3
+ useTRPC: UseBackendTRPC;
4
+ serverUrl: string;
5
+ }
6
+ export declare function BillingInvoicePage({ useTRPC, serverUrl }: BillingInvoicePageProps): import("react/jsx-runtime").JSX.Element;
7
+ export {};
@@ -0,0 +1,32 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { Button, Card, CardBody, CardHeader, Chip, Link, Spinner, Table, TableBody, TableCell, TableColumn, TableHeader, TableRow, } from "@heroui/react";
3
+ import { useSubscription } from "@m5kdev/frontend/modules/billing/hooks/useSubscription";
4
+ import { useQuery } from "@tanstack/react-query";
5
+ import { AlertCircle, CheckCircle2, ExternalLink } from "lucide-react";
6
+ export function BillingInvoicePage({ useTRPC, serverUrl }) {
7
+ const trpc = useTRPC();
8
+ const { data: invoices, isLoading } = useQuery(trpc.billing.listInvoices.queryOptions());
9
+ const { data: activeSubscription, isLoading: isLoadingSubscriptions } = useSubscription();
10
+ const formatCurrency = (amount, currency) => {
11
+ return new Intl.NumberFormat("en-US", {
12
+ style: "currency",
13
+ currency: currency.toUpperCase(),
14
+ }).format(amount / 100);
15
+ };
16
+ const formatDate = (timestamp) => {
17
+ const date = timestamp instanceof Date ? timestamp : new Date(timestamp * 1000);
18
+ return date.toLocaleDateString(undefined, {
19
+ year: "numeric",
20
+ month: "long",
21
+ day: "numeric",
22
+ });
23
+ };
24
+ const cancelAt = activeSubscription?.cancelAt || activeSubscription?.cancelAtPeriodEnd;
25
+ return (_jsxs("div", { className: "container mx-auto p-10 space-y-8", children: [_jsxs(Card, { children: [_jsxs(CardHeader, { className: "flex flex-col items-start gap-1 px-6 pt-6", children: [_jsx("h1", { className: "text-xl font-bold", children: "Active Subscription" }), _jsx("p", { className: "text-small text-default-500", children: "Manage your active subscription." })] }), _jsx(CardBody, { className: "px-6 pb-6", children: isLoadingSubscriptions ? (_jsx("div", { className: "flex justify-center py-8", children: _jsx(Spinner, {}) })) : !activeSubscription ? (_jsxs("div", { className: "flex flex-col items-center justify-center py-8 text-center gap-4", children: [_jsx("div", { className: "p-4 rounded-full bg-default-100", children: _jsx(AlertCircle, { className: "w-8 h-8 text-default-500" }) }), _jsxs("div", { children: [_jsx("p", { className: "text-lg font-medium", children: "No active subscription" }), _jsx("p", { className: "text-small text-default-500", children: "You are currently on the free tier. Upgrade to access premium features." })] }), _jsx(Button, { as: Link, href: "/pricing", color: "primary", children: "View Plans" })] })) : (_jsx("div", { className: "space-y-6", children: _jsxs("div", { className: "flex flex-col sm:flex-row justify-between items-start sm:items-center gap-4 p-4 rounded-lg bg-default-50 border border-default-200", children: [_jsxs("div", { className: "space-y-1", children: [_jsxs("div", { className: "flex items-center gap-2", children: [_jsx("h3", { className: "text-lg font-semibold capitalize", children: activeSubscription.plan || "Premium Plan" }), _jsx(Chip, { color: cancelAt
26
+ ? "danger"
27
+ : activeSubscription.status === "active"
28
+ ? "success"
29
+ : "warning", variant: "flat", size: "sm", startContent: _jsx(CheckCircle2, { className: "w-3 h-3 ml-1" }), children: cancelAt ? "Cancelled" : activeSubscription.status })] }), _jsxs("p", { className: "text-small text-default-500 flex items-center gap-2", children: [cancelAt ? "Your subscription will end on " : "Next billing date: ", _jsx("span", { className: "font-medium text-foreground", children: activeSubscription.periodEnd
30
+ ? formatDate(activeSubscription.periodEnd)
31
+ : "N/A" }), _jsx("span", { className: "text-small text-default-500", children: `(${activeSubscription.interval === "month" ? "Monthly" : "Annually"})` })] })] }), _jsx("div", { className: "flex gap-3", children: _jsx(Button, { variant: "bordered", as: "a", href: `${serverUrl}/stripe/portal`, children: "Manage Subscription" }) })] }) })) })] }), _jsxs(Card, { children: [_jsxs(CardHeader, { className: "flex flex-col items-start gap-1 px-6 pt-6", children: [_jsx("h1", { className: "text-xl font-bold", children: "Invoices" }), _jsx("p", { className: "text-small text-default-500", children: "View your invoice history and download past invoices." })] }), _jsx(CardBody, { className: "px-6 pb-6", children: isLoading ? (_jsx("div", { className: "flex justify-center py-8", children: _jsx(Spinner, {}) })) : (_jsxs(Table, { "aria-label": "Invoices table", removeWrapper: true, children: [_jsxs(TableHeader, { children: [_jsx(TableColumn, { children: "Date" }), _jsx(TableColumn, { children: "Amount" }), _jsx(TableColumn, { children: "Status" }), _jsx(TableColumn, { align: "end", children: "Action" })] }), _jsx(TableBody, { emptyContent: "No invoices found.", children: (invoices || []).map((invoice) => (_jsxs(TableRow, { children: [_jsx(TableCell, { children: formatDate(invoice.created) }), _jsx(TableCell, { children: formatCurrency(invoice.total, invoice.currency) }), _jsx(TableCell, { children: _jsx(Chip, { color: invoice.status === "paid" ? "success" : "default", variant: "flat", size: "sm", children: invoice.status }) }), _jsx(TableCell, { className: "text-right", children: invoice.hosted_invoice_url && (_jsx(Button, { as: Link, href: invoice.hosted_invoice_url, target: "_blank", rel: "noopener noreferrer", variant: "light", size: "sm", endContent: _jsx(ExternalLink, { className: "h-4 w-4" }), children: "View" })) })] }, invoice.id))) })] })) })] })] }));
32
+ }
@@ -0,0 +1,6 @@
1
+ import type { StripePlan } from "@m5kdev/commons/modules/billing/billing.types";
2
+ interface BillingPlanSelectProps {
3
+ plans: StripePlan[];
4
+ }
5
+ export declare function BillingPlanSelect({ plans }: BillingPlanSelectProps): import("react/jsx-runtime").JSX.Element | "Multiple plans selection not implemented yet";
6
+ export {};
@@ -0,0 +1,8 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { BillingSinglePlanSelect } from "#modules/billing/components/BillingSinglePlanSelect";
3
+ export function BillingPlanSelect({ plans }) {
4
+ if (plans.length === 1) {
5
+ return _jsx(BillingSinglePlanSelect, { plan: plans[0] });
6
+ }
7
+ return "Multiple plans selection not implemented yet";
8
+ }
@@ -0,0 +1,9 @@
1
+ import type { StripePlan } from "@m5kdev/commons/modules/billing/billing.types";
2
+ import type { UseBackendTRPC } from "#types";
3
+ interface BillingRouterProps {
4
+ useTRPC?: UseBackendTRPC;
5
+ serverUrl: string;
6
+ plans: StripePlan[];
7
+ }
8
+ export declare function BillingRouter({ useTRPC, serverUrl }: BillingRouterProps): import("react/jsx-runtime").JSX.Element | null;
9
+ export {};
@@ -0,0 +1,8 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { Route } from "react-router";
3
+ import { BillingInvoicePage } from "#modules/billing/components/BillingInvoicePage";
4
+ export function BillingRouter({ useTRPC, serverUrl }) {
5
+ if (!useTRPC)
6
+ return null;
7
+ return (_jsx(Route, { path: "billing", children: _jsx(Route, { index: true, element: _jsx(BillingInvoicePage, { useTRPC: useTRPC, serverUrl: serverUrl }) }) }));
8
+ }
@@ -0,0 +1,8 @@
1
+ import type { StripePlan } from "@m5kdev/commons/modules/billing/billing.types";
2
+ export interface BillingSinglePlanSelectProps {
3
+ plan: StripePlan;
4
+ features?: string[];
5
+ /** URL for the Terms of Service link. Override for your app's legal page. */
6
+ termsOfServiceUrl?: string;
7
+ }
8
+ export declare function BillingSinglePlanSelect({ plan, termsOfServiceUrl, features, }: BillingSinglePlanSelectProps): import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,46 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { Button } from "@heroui/react";
3
+ import { authClient } from "@m5kdev/frontend/modules/auth/auth.lib";
4
+ import { Check, LogOut } from "lucide-react";
5
+ import { useState } from "react";
6
+ import { useTranslation } from "react-i18next";
7
+ import { Link, useNavigate } from "react-router";
8
+ import { Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle, } from "#components/ui/card";
9
+ import { Tabs, TabsList, TabsTrigger } from "#components/ui/tabs";
10
+ import { cn } from "#utils";
11
+ export function BillingSinglePlanSelect({ plan, termsOfServiceUrl, features = [
12
+ "Unlimited access to all features",
13
+ "Priority support",
14
+ "Early access to new features",
15
+ "Secure data storage",
16
+ "Cancel anytime",
17
+ ], }) {
18
+ const { t } = useTranslation("web-ui");
19
+ const navigate = useNavigate();
20
+ const [billingInterval, setBillingInterval] = useState("annually");
21
+ const handleLogout = async () => {
22
+ await authClient.signOut();
23
+ navigate("/login");
24
+ };
25
+ const isAnnual = billingInterval === "annually";
26
+ const currentPriceId = isAnnual ? plan.annualDiscountPriceId : plan.priceId;
27
+ // Fallback if no annual price ID exists
28
+ const hasAnnualOption = !!plan.annualDiscountPriceId;
29
+ const priceUnitAmount = plan.priceUnitAmount ?? Number.NaN;
30
+ const annualPriceUnitAmount = plan.annualPriceUnitAmount ?? Number.NaN;
31
+ const priceDisplay = {
32
+ monthly: {
33
+ amount: `$${priceUnitAmount / 100}`,
34
+ label: "/ month",
35
+ },
36
+ annually: {
37
+ amount: `$${annualPriceUnitAmount / 100 / 12}`,
38
+ originalAmount: `$${priceUnitAmount / 100}`,
39
+ label: "/ month, billed annually",
40
+ discountLabel: plan.annualPriceUnitAmount
41
+ ? `Save ${Math.floor(((priceUnitAmount - annualPriceUnitAmount / 12) / priceUnitAmount) * 100).toFixed(0)}%`
42
+ : "",
43
+ },
44
+ };
45
+ return (_jsxs("div", { className: "w-full max-w-3xl mx-auto px-4 py-8", children: [_jsxs("div", { className: "flex flex-col items-center gap-8", children: [_jsxs("div", { className: "text-center space-y-2", children: [_jsx("h2", { className: "text-3xl font-bold tracking-tight sm:text-4xl", children: t("billing.plans.title", "Simple, transparent pricing") }), _jsx("p", { className: "text-muted-foreground text-lg", children: t("billing.plans.subtitle", "Choose the plan that's right for you") })] }), hasAnnualOption && (_jsx(Tabs, { defaultValue: "annually", value: billingInterval, onValueChange: (v) => setBillingInterval(v), className: "w-full max-w-xs", children: _jsxs(TabsList, { className: "grid w-full grid-cols-2", children: [_jsx(TabsTrigger, { value: "monthly", children: "Monthly" }), _jsxs(TabsTrigger, { value: "annually", className: "relative", children: ["Annually", priceDisplay.annually.discountLabel && (_jsx("span", { className: "absolute -top-3 -right-3 px-1.5 py-0.5 rounded-full bg-green-500 text-[10px] text-white font-medium transform rotate-12", children: priceDisplay.annually.discountLabel }))] })] }) })), _jsxs(Card, { className: cn("w-full max-w-md border-2 border-primary"), children: [_jsxs(CardHeader, { children: [_jsx(CardTitle, { className: "flex justify-between items-start", children: _jsx("span", { className: "text-xl font-bold", children: plan.name }) }), _jsx(CardDescription, { children: isAnnual ? "Perfect for long-term commitment" : "Flexible monthly billing" })] }), _jsxs(CardContent, { className: "space-y-6", children: [_jsxs("div", { className: "flex items-baseline gap-1", children: [_jsx("span", { className: "text-4xl font-bold", children: isAnnual ? priceDisplay.annually.amount : priceDisplay.monthly.amount }), _jsx("span", { className: "text-muted-foreground", children: isAnnual ? priceDisplay.annually.label : priceDisplay.monthly.label })] }), isAnnual && priceDisplay.annually.originalAmount && (_jsxs("p", { className: "text-sm text-green-500 line-through", children: [" ", priceDisplay.annually.originalAmount, " / month"] })), _jsx("div", { className: "space-y-3", children: features.map((feature) => (_jsxs("div", { className: "flex items-center gap-2", children: [_jsx("div", { className: "h-5 w-5 rounded-full bg-primary/10 flex items-center justify-center shrink-0", children: _jsx(Check, { className: "h-3 w-3 text-primary" }) }), _jsx("span", { className: "text-sm text-muted-foreground", children: feature })] }, feature))) })] }), _jsx(CardFooter, { children: _jsx(Button, { className: "w-full", color: "primary", size: "lg", as: "a", href: `${import.meta.env.VITE_SERVER_URL}/stripe/checkout/${currentPriceId}`, children: isAnnual ? "Subscribe Annually" : "Subscribe Monthly" }) })] }), _jsxs("div", { className: "text-balance text-center text-xs text-muted-foreground [&_a]:underline [&_a]:underline-offset-4 [&_a]:hover:text-primary", children: [_jsx("a", { href: termsOfServiceUrl, rel: "noopener noreferrer", target: "_blank", children: t("common.termsOfService", "Terms of Service") }), " ", t("common.and", "and"), " ", _jsx(Link, { to: "/privacy", children: t("common.privacyPolicy", "Privacy Policy") })] })] }), _jsx("div", { className: "fixed bottom-4 left-4", children: _jsxs(Button, { variant: "light", onPress: handleLogout, className: "gap-2", children: [_jsx(LogOut, { className: "h-4 w-4" }), t("sidebar.user.logout", "Log out")] }) })] }));
46
+ }
@@ -0,0 +1,10 @@
1
+ import type { ColumnOrderState, VisibilityState } from "@tanstack/react-table";
2
+ import type { ColumnItem } from "./table.types";
3
+ interface ColumnOrderAndVisibilityProps {
4
+ layout: ColumnItem[];
5
+ onChangeOrder: (order: ColumnOrderState) => void;
6
+ onChangeVisibility: (visibility: VisibilityState) => void;
7
+ onClose: () => void;
8
+ }
9
+ export declare const ColumnOrderAndVisibility: ({ layout, onChangeOrder, onChangeVisibility, onClose, }: ColumnOrderAndVisibilityProps) => import("react/jsx-runtime").JSX.Element;
10
+ export {};
@@ -0,0 +1,42 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { DndContext, KeyboardSensor, PointerSensor, useSensor, useSensors } from "@dnd-kit/core";
3
+ import { arrayMove, SortableContext, sortableKeyboardCoordinates, useSortable, verticalListSortingStrategy, } from "@dnd-kit/sortable";
4
+ import { CSS } from "@dnd-kit/utilities";
5
+ import { EyeIcon, EyeOffIcon, GripVertical } from "lucide-react";
6
+ import { useCallback, useState } from "react";
7
+ import { Button } from "#components/ui/button";
8
+ const ColumnOrderAndVisibilityItem = ({ column, onChangeVisibilityState, }) => {
9
+ const { attributes, listeners, setNodeRef, transform, transition } = useSortable({
10
+ id: column.id,
11
+ });
12
+ return (_jsxs("div", { ref: setNodeRef, style: { transform: CSS.Transform.toString(transform), transition }, className: "flex justify-between items-center gap-2", children: [column.label, _jsxs("div", { className: "flex items-center gap-2", children: [_jsx("div", { ...attributes, ...listeners, className: "cursor-grab active:cursor-grabbing touch-none", children: _jsx(GripVertical, { className: "h-4 w-4" }) }), _jsx(Button, { variant: "ghost", size: "icon", onClick: () => onChangeVisibilityState(String(column.id)), children: column.visibility ? _jsx(EyeIcon, { className: "h-4 w-4" }) : _jsx(EyeOffIcon, { className: "h-4 w-4" }) })] })] }));
13
+ };
14
+ export const ColumnOrderAndVisibility = ({ layout, onChangeOrder, onChangeVisibility, onClose, }) => {
15
+ const [activeLayout, setActiveLayout] = useState([...layout]);
16
+ const onChangeVisibilityState = useCallback((columnId) => {
17
+ setActiveLayout((prev) => {
18
+ const index = prev.findIndex((c) => c.id === columnId);
19
+ if (index !== -1) {
20
+ const newLayout = [...prev];
21
+ newLayout[index] = { ...prev[index], visibility: !prev[index].visibility };
22
+ return newLayout;
23
+ }
24
+ return prev;
25
+ });
26
+ }, []);
27
+ const sensors = useSensors(useSensor(PointerSensor), useSensor(KeyboardSensor, {
28
+ coordinateGetter: sortableKeyboardCoordinates,
29
+ }));
30
+ const onSubmit = useCallback(() => {
31
+ onChangeOrder(activeLayout.map((column) => column.id));
32
+ onChangeVisibility(Object.fromEntries(activeLayout.map((column) => [column.id, column.visibility])));
33
+ onClose();
34
+ }, [activeLayout, onChangeOrder, onChangeVisibility, onClose]);
35
+ return (_jsxs("div", { className: "flex flex-col gap-2 p-1 min-w-[200px]", children: [_jsx(DndContext, { onDragEnd: ({ active, over }) => {
36
+ if (over && active.id !== over?.id) {
37
+ const activeIndex = activeLayout.findIndex(({ id }) => id === active.id);
38
+ const overIndex = activeLayout.findIndex(({ id }) => id === over.id);
39
+ setActiveLayout(arrayMove(activeLayout, activeIndex, overIndex));
40
+ }
41
+ }, sensors: sensors, children: _jsx(SortableContext, { items: activeLayout.map((column) => column.id), strategy: verticalListSortingStrategy, children: activeLayout.map((column) => (_jsx(ColumnOrderAndVisibilityItem, { column: column, onChangeVisibilityState: onChangeVisibilityState }, column.id))) }) }), _jsx(Button, { onClick: onSubmit, children: "Apply" })] }));
42
+ };
@@ -0,0 +1,23 @@
1
+ import type { FilterMethods } from "@m5kdev/commons/modules/table/filter.types";
2
+ import type { TableParams } from "@m5kdev/frontend/modules/table/hooks/useNuqsTable";
3
+ import type { ColumnDef } from "@tanstack/react-table";
4
+ import type { ColumnDataType } from "./table.types";
5
+ export type NuqsTableColumn<T> = ColumnDef<T> & {
6
+ visible?: boolean;
7
+ type?: ColumnDataType;
8
+ options?: {
9
+ label: string;
10
+ value: string;
11
+ }[];
12
+ endColumnId?: string;
13
+ };
14
+ type NuqsTableParams<T> = {
15
+ data: T[];
16
+ total?: number;
17
+ columns: NuqsTableColumn<T>[];
18
+ tableProps: TableParams;
19
+ singleFilter?: boolean;
20
+ filterMethods?: Partial<FilterMethods>;
21
+ };
22
+ export declare const NuqsTable: <T>({ data, total, columns, tableProps, singleFilter, filterMethods, }: NuqsTableParams<T>) => import("react/jsx-runtime").JSX.Element;
23
+ export {};
@@ -0,0 +1,198 @@
1
+ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
+ import { Checkbox, Popover, PopoverContent, PopoverTrigger } from "@heroui/react";
3
+ import { flexRender, getCoreRowModel, getPaginationRowModel, useReactTable, } from "@tanstack/react-table";
4
+ import { ChevronDown, ChevronUp } from "lucide-react";
5
+ import { useEffect, useMemo, useState } from "react";
6
+ import { Button } from "#components/ui/button";
7
+ import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow, } from "#components/ui/table";
8
+ import { ColumnOrderAndVisibility } from "./ColumnOrderAndVisibility";
9
+ import { TableFiltering } from "./TableFiltering";
10
+ import { TablePagination } from "./TablePagination";
11
+ function getStorageKey(columnIds) {
12
+ const sortedIds = [...columnIds].sort().join(",");
13
+ return `table-column-layout-${sortedIds}`;
14
+ }
15
+ function loadLayoutFromStorage(columnIds) {
16
+ if (typeof window === "undefined")
17
+ return null;
18
+ try {
19
+ const key = getStorageKey(columnIds);
20
+ const stored = localStorage.getItem(key);
21
+ if (!stored)
22
+ return null;
23
+ const parsed = JSON.parse(stored);
24
+ return parsed;
25
+ }
26
+ catch {
27
+ return null;
28
+ }
29
+ }
30
+ function saveLayoutToStorage(columnIds, order, visibility) {
31
+ if (typeof window === "undefined")
32
+ return;
33
+ try {
34
+ const key = getStorageKey(columnIds);
35
+ localStorage.setItem(key, JSON.stringify({ order, visibility }));
36
+ }
37
+ catch {
38
+ // Ignore storage errors
39
+ }
40
+ }
41
+ function applyOrder(prev, nextOrder) {
42
+ const byId = new Map(prev.map((i) => [i.id, i]));
43
+ const ordered = nextOrder.map((id) => byId.get(id)).filter(Boolean);
44
+ // append any newly added columns (if any appear later)
45
+ for (const item of prev)
46
+ if (!nextOrder.includes(item.id))
47
+ ordered.push(item);
48
+ return ordered;
49
+ }
50
+ function applyVisibility(prev, visibility) {
51
+ return prev.map((column) => ({
52
+ ...column,
53
+ visibility: visibility[String(column.id)] ?? column.visibility,
54
+ }));
55
+ }
56
+ export const NuqsTable = ({ data, total, columns, tableProps, singleFilter = false, filterMethods, }) => {
57
+ const columnIds = useMemo(() => columns.map((col) => String(col.id)), [columns]);
58
+ console.log("data", data);
59
+ // const columnsWithId = useMemo(() => {
60
+ // const idColumn: NuqsTableColumn<T> = {
61
+ // id: "__row_id",
62
+ // accessorKey: "id",
63
+ // header: "",
64
+ // enableSorting: false,
65
+ // enableHiding: false,
66
+ // visible: false,
67
+ // };
68
+ // return [idColumn, ...columns];
69
+ // }, [columns]);
70
+ const initialLayout = useMemo(() => {
71
+ const defaultLayout = columns.map((column) => ({
72
+ id: String(column.id),
73
+ label: column.header,
74
+ visibility: column.visible !== undefined ? column.visible : true,
75
+ options: column.options ?? [],
76
+ type: column.type ?? undefined,
77
+ }));
78
+ const saved = loadLayoutFromStorage(columnIds);
79
+ if (!saved)
80
+ return defaultLayout;
81
+ // Merge saved layout with default layout
82
+ const savedById = new Map();
83
+ saved.order.forEach((id, index) => {
84
+ savedById.set(id, { order: index, visibility: saved.visibility[id] ?? true });
85
+ });
86
+ const merged = [];
87
+ const processedIds = new Set();
88
+ // Add columns in saved order
89
+ saved.order.forEach((id) => {
90
+ const defaultCol = defaultLayout.find((col) => col.id === id);
91
+ if (defaultCol) {
92
+ merged.push({
93
+ ...defaultCol,
94
+ visibility: saved.visibility[id] ?? defaultCol.visibility,
95
+ });
96
+ processedIds.add(id);
97
+ }
98
+ });
99
+ // Add any new columns that weren't in saved layout
100
+ defaultLayout.forEach((col) => {
101
+ if (!processedIds.has(col.id)) {
102
+ merged.push(col);
103
+ }
104
+ });
105
+ return merged;
106
+ }, [columns, columnIds]);
107
+ const [layout, setLayout] = useState(initialLayout);
108
+ // Sync layout when columns change
109
+ useEffect(() => {
110
+ setLayout(initialLayout);
111
+ }, [initialLayout]);
112
+ // Save to localStorage whenever layout changes
113
+ useEffect(() => {
114
+ const order = layout.map((col) => col.id);
115
+ const visibility = Object.fromEntries(layout.map((col) => [col.id, col.visibility]));
116
+ saveLayoutToStorage(columnIds, order, visibility);
117
+ }, [layout, columnIds]);
118
+ const columnOrder = useMemo(() => layout.map((column) => column.id), [layout]);
119
+ const columnVisibility = useMemo(() => Object.fromEntries(layout.map((column) => [column.id, column.visibility])), [layout]);
120
+ const { limit = 10, page = 1, sorting, setSorting, setPagination, pagination, rowSelection, setRowSelection, setFilters, filters, } = tableProps;
121
+ // Redirect back if we're on an empty page (past the last page)
122
+ useEffect(() => {
123
+ if (data.length === 0 && page > 1 && total !== undefined) {
124
+ setPagination?.({ pageIndex: page - 2, pageSize: limit });
125
+ }
126
+ }, [data.length, page, limit, total, setPagination]);
127
+ // Calculate pageCount from total if available, otherwise use heuristic
128
+ const pageCount = total !== undefined
129
+ ? Math.ceil(total / limit) || 1
130
+ : data.length === limit
131
+ ? page + 1
132
+ : Math.max(page, Math.ceil(data.length / limit));
133
+ const table = useReactTable({
134
+ data,
135
+ columns,
136
+ getRowId: (row) => String(row.id),
137
+ manualSorting: true,
138
+ manualPagination: true,
139
+ state: { pagination, sorting, rowSelection, columnOrder, columnVisibility },
140
+ pageCount,
141
+ manualFiltering: true,
142
+ onSortingChange: setSorting,
143
+ onPaginationChange: setPagination,
144
+ onRowSelectionChange: setRowSelection,
145
+ getCoreRowModel: getCoreRowModel(),
146
+ getPaginationRowModel: getPaginationRowModel(),
147
+ onColumnOrderChange: (updater) => {
148
+ setLayout((prev) => applyOrder(prev, typeof updater === "function" ? updater(prev.map((i) => i.id)) : updater));
149
+ },
150
+ onColumnVisibilityChange: (updater) => {
151
+ setLayout((prev) => applyVisibility(prev, typeof updater === "function"
152
+ ? updater(Object.fromEntries(prev.map((i) => [i.id, i.visibility])))
153
+ : updater));
154
+ },
155
+ });
156
+ const onChangeOrder = (order) => {
157
+ setLayout((prev) => applyOrder(prev, order));
158
+ };
159
+ const onChangeVisibility = (visibility) => {
160
+ setLayout((prev) => applyVisibility(prev, visibility));
161
+ };
162
+ const onFiltersChange = (filters) => {
163
+ setFilters?.(filters);
164
+ };
165
+ const filterableColumns = useMemo(() => {
166
+ const baseColumns = columns
167
+ .filter((column) => Boolean(column.type))
168
+ .map((column) => ({
169
+ id: String(column.id),
170
+ label: String(column.header),
171
+ type: column.type,
172
+ options: column.options ?? [],
173
+ endColumnId: column.endColumnId,
174
+ periodStartColumnId: null,
175
+ periodEndColumnId: null,
176
+ }));
177
+ // Add Period pseudo-columns for date columns with endColumnId
178
+ const periodColumns = columns
179
+ .filter((column) => column.type === "date" && column.endColumnId)
180
+ .map((column) => ({
181
+ id: `${String(column.id)}__period`,
182
+ label: "Period",
183
+ type: "date",
184
+ options: [],
185
+ endColumnId: null,
186
+ periodStartColumnId: String(column.id),
187
+ periodEndColumnId: column.endColumnId,
188
+ }));
189
+ return [...baseColumns, ...periodColumns];
190
+ }, [columns]);
191
+ const [isFiltersOpen, setIsFiltersOpen] = useState(false);
192
+ const [isColumnsOpen, setIsColumnsOpen] = useState(false);
193
+ return (_jsxs(_Fragment, { children: [_jsxs("div", { className: "flex w-full items-center gap-2 justify-end", children: [_jsxs(Popover, { placement: "bottom", isOpen: isFiltersOpen, onOpenChange: setIsFiltersOpen, portalContainer: document.body, children: [_jsx(PopoverTrigger, { children: _jsx(Button, { variant: "outline", size: "sm", children: _jsxs("div", { className: "flex items-center gap-2", children: ["Filters", _jsx(ChevronDown, { className: "h-4 w-4" })] }) }) }), _jsx(PopoverContent, { children: _jsx(TableFiltering, { columns: filterableColumns, onFiltersChange: onFiltersChange, filters: filters ?? [], onClose: () => setIsFiltersOpen(false), singleFilter: singleFilter, filterMethods: filterMethods }) })] }), _jsxs(Popover, { placement: "bottom", isOpen: isColumnsOpen, onOpenChange: setIsColumnsOpen, portalContainer: document.body, children: [_jsx(PopoverTrigger, { children: _jsx(Button, { variant: "outline", size: "sm", children: _jsxs("div", { className: "flex items-center gap-2", children: ["Columns", _jsx(ChevronDown, { className: "h-4 w-4" })] }) }) }), _jsx(PopoverContent, { children: _jsx(ColumnOrderAndVisibility, { layout: layout, onChangeOrder: onChangeOrder, onChangeVisibility: onChangeVisibility, onClose: () => setIsColumnsOpen(false) }) })] })] }), _jsxs(Table, { children: [_jsx(TableHeader, { children: _jsxs(TableRow, { children: [_jsx(TableHead, { children: _jsx(Checkbox, { isSelected: table.getIsAllRowsSelected(), onValueChange: (checked) => {
194
+ table.toggleAllRowsSelected(checked);
195
+ } }) }), table.getHeaderGroups()[0].headers.map((header) => (_jsxs(TableHead, { onClick: header.column.getCanSort() ? header.column.getToggleSortingHandler() : undefined, children: [flexRender(header.column.columnDef.header, header.getContext()), header.column.getCanSort() && (_jsxs(_Fragment, { children: [header.column.getIsSorted() === "asc" && (_jsx(ChevronUp, { className: "h-4 w-4 inline ml-1" })), header.column.getIsSorted() === "desc" && (_jsx(ChevronDown, { className: "h-4 w-4 inline ml-1" }))] }))] }, header.id)))] }) }), _jsx(TableBody, { children: table.getRowModel().rows.map((row) => (_jsxs(TableRow, { children: [_jsx(TableCell, { children: _jsx(Checkbox, { isSelected: row.getIsSelected(), onValueChange: (checked) => {
196
+ row.toggleSelected(checked);
197
+ } }) }), row.getVisibleCells().map((cell) => (_jsx(TableCell, { children: flexRender(cell.column.columnDef.cell, cell.getContext()) }, cell.id)))] }, row.id))) })] }), _jsx(TablePagination, { pageCount: pageCount, page: page, limit: limit, setPagination: setPagination })] }));
198
+ };