@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.
- package/dist/src/animations/card.motion.d.ts +2 -0
- package/dist/src/animations/card.motion.js +7 -0
- package/dist/src/components/AvatarUpload.d.ts +7 -0
- package/dist/src/components/AvatarUpload.js +67 -0
- package/dist/src/components/Button.d.ts +5 -0
- package/dist/src/components/Button.js +5 -0
- package/dist/src/components/Calendar.d.ts +35 -0
- package/dist/src/components/Calendar.js +10 -0
- package/dist/src/components/CardsSelect.d.ts +23 -0
- package/dist/src/components/CardsSelect.js +46 -0
- package/dist/src/components/CollapsibleSidebarMenuItem.d.ts +9 -0
- package/dist/src/components/CollapsibleSidebarMenuItem.js +11 -0
- package/dist/src/components/ColorPicker.d.ts +4 -0
- package/dist/src/components/ColorPicker.js +21 -0
- package/dist/src/components/CopyButton.d.ts +6 -0
- package/dist/src/components/CopyButton.js +24 -0
- package/dist/src/components/CropDialog.d.ts +10 -0
- package/dist/src/components/CropDialog.js +67 -0
- package/dist/src/components/DialogProvider.d.ts +15 -0
- package/dist/src/components/DialogProvider.js +50 -0
- package/dist/src/components/ErrorFallback.d.ts +4 -0
- package/dist/src/components/ErrorFallback.js +5 -0
- package/dist/src/components/FileDropzone.d.ts +6 -0
- package/dist/src/components/FileDropzone.js +63 -0
- package/dist/src/components/MultiSelectDropdown.d.ts +26 -0
- package/dist/src/components/MultiSelectDropdown.js +53 -0
- package/dist/src/components/Orb.d.ts +6 -0
- package/{src/components/Orb.tsx → dist/src/components/Orb.js} +107 -136
- package/dist/src/components/PageAlert.d.ts +18 -0
- package/dist/src/components/PageAlert.js +48 -0
- package/dist/src/components/SelectChips.d.ts +10 -0
- package/dist/src/components/SelectChips.js +11 -0
- package/dist/src/components/SidebarItem.d.ts +7 -0
- package/dist/src/components/SidebarItem.js +6 -0
- package/dist/src/components/Steps.d.ts +19 -0
- package/dist/src/components/Steps.js +34 -0
- package/dist/src/components/TablerIconPicker.d.ts +2 -0
- package/dist/src/components/TablerIconPicker.js +4238 -0
- package/dist/src/components/app-header.d.ts +6 -0
- package/dist/src/components/app-header.js +8 -0
- package/dist/src/components/blur-card.d.ts +13 -0
- package/dist/src/components/blur-card.js +34 -0
- package/dist/src/components/features-section-demo-1.d.ts +6 -0
- package/dist/src/components/features-section-demo-1.js +53 -0
- package/dist/src/components/features-section-demo-2.d.ts +1 -0
- package/dist/src/components/features-section-demo-2.js +51 -0
- package/dist/src/components/features-section-demo-3.d.ts +8 -0
- package/dist/src/components/features-section-demo-3.js +116 -0
- package/dist/src/components/mode-toggle.d.ts +1 -0
- package/dist/src/components/mode-toggle.js +9 -0
- package/dist/src/components/nav-main.d.ts +13 -0
- package/dist/src/components/nav-main.js +9 -0
- package/dist/src/components/pricing-cards.d.ts +1 -0
- package/dist/src/components/pricing-cards.js +27 -0
- package/dist/src/components/shared/ButtonCopy.d.ts +6 -0
- package/dist/src/components/shared/ButtonCopy.js +24 -0
- package/dist/src/components/team-switcher.d.ts +8 -0
- package/dist/src/components/team-switcher.js +10 -0
- package/dist/src/components/theme-provider.d.ts +13 -0
- package/dist/src/components/theme-provider.js +41 -0
- package/dist/src/components/typewriter.d.ts +18 -0
- package/dist/src/components/typewriter.js +38 -0
- package/dist/src/components/ui/alert-dialog.d.ts +14 -0
- package/dist/src/components/ui/alert-dialog.js +38 -0
- package/dist/src/components/ui/alert.d.ts +9 -0
- package/dist/src/components/ui/alert.js +24 -0
- package/dist/src/components/ui/avatar.d.ts +6 -0
- package/dist/src/components/ui/avatar.js +12 -0
- package/dist/src/components/ui/badge.d.ts +9 -0
- package/dist/src/components/ui/badge.js +20 -0
- package/dist/src/components/ui/bento-grid.d.ts +11 -0
- package/dist/src/components/ui/bento-grid.js +8 -0
- package/dist/src/components/ui/bento-grid2.d.ts +15 -0
- package/dist/src/components/ui/bento-grid2.js +13 -0
- package/dist/src/components/ui/breadcrumb.d.ts +19 -0
- package/dist/src/components/ui/breadcrumb.js +23 -0
- package/dist/src/components/ui/button.d.ts +11 -0
- package/dist/src/components/ui/button.js +33 -0
- package/dist/src/components/ui/card.d.ts +8 -0
- package/dist/src/components/ui/card.js +16 -0
- package/dist/src/components/ui/checkbox.d.ts +4 -0
- package/dist/src/components/ui/checkbox.js +8 -0
- package/dist/src/components/ui/collapsible.d.ts +5 -0
- package/{src/components/ui/collapsible.tsx → dist/src/components/ui/collapsible.js} +5 -9
- package/dist/src/components/ui/dialog.d.ts +13 -0
- package/dist/src/components/ui/dialog.js +35 -0
- package/dist/src/components/ui/dropdown-menu.d.ts +27 -0
- package/dist/src/components/ui/dropdown-menu.js +32 -0
- package/dist/src/components/ui/floating-navbar.d.ts +9 -0
- package/dist/src/components/ui/floating-navbar.js +38 -0
- package/dist/src/components/ui/form.d.ts +23 -0
- package/dist/src/components/ui/form.js +60 -0
- package/dist/src/components/ui/image.d.ts +6 -0
- package/dist/src/components/ui/image.js +15 -0
- package/dist/src/components/ui/input.d.ts +3 -0
- package/dist/src/components/ui/input.js +8 -0
- package/dist/src/components/ui/label.d.ts +5 -0
- package/dist/src/components/ui/label.js +9 -0
- package/dist/src/components/ui/pagination.d.ts +13 -0
- package/dist/src/components/ui/pagination.js +29 -0
- package/dist/src/components/ui/progress.d.ts +4 -0
- package/dist/src/components/ui/progress.js +7 -0
- package/dist/src/components/ui/resizable-navbar.d.ts +56 -0
- package/dist/src/components/ui/resizable-navbar.js +86 -0
- package/dist/src/components/ui/segment-control.d.ts +9 -0
- package/dist/src/components/ui/segment-control.js +42 -0
- package/dist/src/components/ui/select.d.ts +13 -0
- package/dist/src/components/ui/select.js +26 -0
- package/dist/src/components/ui/separator.d.ts +4 -0
- package/dist/src/components/ui/separator.js +7 -0
- package/dist/src/components/ui/sheet.d.ts +25 -0
- package/dist/src/components/ui/sheet.js +37 -0
- package/dist/src/components/ui/sidebar.d.ts +66 -0
- package/dist/src/components/ui/sidebar.js +222 -0
- package/dist/src/components/ui/skeleton.d.ts +2 -0
- package/dist/src/components/ui/skeleton.js +6 -0
- package/dist/src/components/ui/slider.d.ts +4 -0
- package/dist/src/components/ui/slider.js +7 -0
- package/dist/src/components/ui/sonner.d.ts +4 -0
- package/dist/src/components/ui/sonner.js +15 -0
- package/dist/src/components/ui/spinner.d.ts +14 -0
- package/dist/src/components/ui/spinner.js +30 -0
- package/dist/src/components/ui/switch.d.ts +4 -0
- package/dist/src/components/ui/switch.js +7 -0
- package/dist/src/components/ui/table.d.ts +10 -0
- package/dist/src/components/ui/table.js +27 -0
- package/dist/src/components/ui/tabs.d.ts +7 -0
- package/dist/src/components/ui/tabs.js +16 -0
- package/dist/src/components/ui/textarea.d.ts +3 -0
- package/dist/src/components/ui/textarea.js +6 -0
- package/dist/src/components/ui/timeline.d.ts +11 -0
- package/dist/src/components/ui/timeline.js +27 -0
- package/dist/src/components/ui/toast.d.ts +15 -0
- package/dist/src/components/ui/toast.js +33 -0
- package/dist/src/components/ui/tooltip.d.ts +7 -0
- package/dist/src/components/ui/tooltip.js +16 -0
- package/dist/src/components/ui/typewriter-effect.d.ts +16 -0
- package/dist/src/components/ui/typewriter-effect.js +76 -0
- package/dist/src/hooks/use-mobile.d.ts +1 -0
- package/dist/src/hooks/use-mobile.js +15 -0
- package/dist/src/hooks/useDialog.d.ts +4 -0
- package/dist/src/hooks/useDialog.js +22 -0
- package/dist/src/icons/GoogleIcon.d.ts +5 -0
- package/dist/src/icons/GoogleIcon.js +4 -0
- package/dist/src/icons/LinkedInIcon.d.ts +5 -0
- package/dist/src/icons/LinkedInIcon.js +4 -0
- package/dist/src/icons/MicrosoftIcon.d.ts +5 -0
- package/dist/src/icons/MicrosoftIcon.js +4 -0
- package/dist/src/lib/chatwoot.d.ts +11 -0
- package/dist/src/lib/chatwoot.js +28 -0
- package/dist/src/lib/utils.d.ts +2 -0
- package/dist/src/lib/utils.js +5 -0
- package/dist/src/modules/app/components/AppLoader.d.ts +2 -0
- package/dist/src/modules/app/components/AppLoader.js +5 -0
- package/dist/src/modules/app/components/AppShell.d.ts +7 -0
- package/dist/src/modules/app/components/AppShell.js +7 -0
- package/dist/src/modules/app/components/AppSidebar.d.ts +7 -0
- package/dist/src/modules/app/components/AppSidebar.js +5 -0
- package/dist/src/modules/app/components/AppSidebarContent.d.ts +16 -0
- package/dist/src/modules/app/components/AppSidebarContent.js +7 -0
- package/dist/src/modules/app/components/AppSidebarHeader.d.ts +8 -0
- package/dist/src/modules/app/components/AppSidebarHeader.js +10 -0
- package/dist/src/modules/app/components/AppSidebarInvites.d.ts +3 -0
- package/dist/src/modules/app/components/AppSidebarInvites.js +12 -0
- package/dist/src/modules/app/components/AppSidebarUser.d.ts +11 -0
- package/dist/src/modules/app/components/AppSidebarUser.js +16 -0
- package/dist/src/modules/auth/components/AdminUserManagement.d.ts +6 -0
- package/dist/src/modules/auth/components/AdminUserManagement.js +422 -0
- package/dist/src/modules/auth/components/AdminWaitlist.d.ts +6 -0
- package/dist/src/modules/auth/components/AdminWaitlist.js +118 -0
- package/dist/src/modules/auth/components/AuthLayout.d.ts +4 -0
- package/dist/src/modules/auth/components/AuthLayout.js +5 -0
- package/dist/src/modules/auth/components/AuthProviders.d.ts +6 -0
- package/dist/src/modules/auth/components/AuthProviders.js +45 -0
- package/dist/src/modules/auth/components/AuthRouter.d.ts +9 -0
- package/dist/src/modules/auth/components/AuthRouter.js +12 -0
- package/dist/src/modules/auth/components/ClaimAccountRoute.d.ts +4 -0
- package/dist/src/modules/auth/components/ClaimAccountRoute.js +143 -0
- package/dist/src/modules/auth/components/ErrorAuthRoute.d.ts +1 -0
- package/dist/src/modules/auth/components/ErrorAuthRoute.js +93 -0
- package/dist/src/modules/auth/components/ForgotPasswordForm.d.ts +1 -0
- package/dist/src/modules/auth/components/ForgotPasswordForm.js +27 -0
- package/dist/src/modules/auth/components/ForgotPasswordRoute.d.ts +1 -0
- package/dist/src/modules/auth/components/ForgotPasswordRoute.js +9 -0
- package/dist/src/modules/auth/components/InviteFriends.d.ts +5 -0
- package/dist/src/modules/auth/components/InviteFriends.js +74 -0
- package/dist/src/modules/auth/components/LastUsedBadge.d.ts +5 -0
- package/dist/src/modules/auth/components/LastUsedBadge.js +9 -0
- package/dist/src/modules/auth/components/LoginForm.d.ts +3 -0
- package/dist/src/modules/auth/components/LoginForm.js +44 -0
- package/dist/src/modules/auth/components/LoginRoute.d.ts +3 -0
- package/dist/src/modules/auth/components/LoginRoute.js +11 -0
- package/dist/src/modules/auth/components/LogoutRoute.d.ts +1 -0
- package/dist/src/modules/auth/components/LogoutRoute.js +15 -0
- package/dist/src/modules/auth/components/OrganizationAcceptInvitationRoute.d.ts +9 -0
- package/dist/src/modules/auth/components/OrganizationAcceptInvitationRoute.js +102 -0
- package/dist/src/modules/auth/components/OrganizationMembersRoute.d.ts +51 -0
- package/dist/src/modules/auth/components/OrganizationMembersRoute.js +359 -0
- package/dist/src/modules/auth/components/OrganizationSettingsRoute.d.ts +20 -0
- package/dist/src/modules/auth/components/OrganizationSettingsRoute.js +153 -0
- package/dist/src/modules/auth/components/OrganizationSwitcher.d.ts +7 -0
- package/dist/src/modules/auth/components/OrganizationSwitcher.js +74 -0
- package/dist/src/modules/auth/components/ProfileRoute.d.ts +1 -0
- package/dist/src/modules/auth/components/ProfileRoute.js +42 -0
- package/dist/src/modules/auth/components/RangeNuqsDatePicker.d.ts +31 -0
- package/dist/src/modules/auth/components/RangeNuqsDatePicker.js +236 -0
- package/dist/src/modules/auth/components/ResetPasswordForm.d.ts +1 -0
- package/dist/src/modules/auth/components/ResetPasswordForm.js +39 -0
- package/dist/src/modules/auth/components/ResetPasswordRoute.d.ts +1 -0
- package/dist/src/modules/auth/components/ResetPasswordRoute.js +9 -0
- package/dist/src/modules/auth/components/SignupFormRoute.d.ts +5 -0
- package/dist/src/modules/auth/components/SignupFormRoute.js +106 -0
- package/dist/src/modules/auth/components/SignupRoute.d.ts +7 -0
- package/dist/src/modules/auth/components/SignupRoute.js +16 -0
- package/dist/src/modules/auth/components/UserPreferences.d.ts +30 -0
- package/dist/src/modules/auth/components/UserPreferences.js +60 -0
- package/dist/src/modules/auth/components/WaitlistCard.d.ts +6 -0
- package/dist/src/modules/auth/components/WaitlistCard.js +32 -0
- package/dist/src/modules/auth/components/WaitlistCodeValidation.d.ts +7 -0
- package/dist/src/modules/auth/components/WaitlistCodeValidation.js +43 -0
- package/dist/src/modules/billing/components/BillingBetaPage.d.ts +8 -0
- package/dist/src/modules/billing/components/BillingBetaPage.js +11 -0
- package/dist/src/modules/billing/components/BillingInvoicePage.d.ts +7 -0
- package/dist/src/modules/billing/components/BillingInvoicePage.js +32 -0
- package/dist/src/modules/billing/components/BillingPlanSelect.d.ts +6 -0
- package/dist/src/modules/billing/components/BillingPlanSelect.js +8 -0
- package/dist/src/modules/billing/components/BillingRouter.d.ts +9 -0
- package/dist/src/modules/billing/components/BillingRouter.js +8 -0
- package/dist/src/modules/billing/components/BillingSinglePlanSelect.d.ts +8 -0
- package/dist/src/modules/billing/components/BillingSinglePlanSelect.js +46 -0
- package/dist/src/modules/table/components/ColumnOrderAndVisibility.d.ts +10 -0
- package/dist/src/modules/table/components/ColumnOrderAndVisibility.js +42 -0
- package/dist/src/modules/table/components/NuqsTable.d.ts +23 -0
- package/dist/src/modules/table/components/NuqsTable.js +198 -0
- package/dist/src/modules/table/components/TableFiltering.d.ts +23 -0
- package/dist/src/modules/table/components/TableFiltering.js +236 -0
- package/dist/src/modules/table/components/TablePagination.d.ts +9 -0
- package/dist/src/modules/table/components/TablePagination.js +21 -0
- package/{src/modules/table/components/table.types.ts → dist/src/modules/table/components/table.types.d.ts} +12 -11
- package/dist/src/modules/table/components/table.types.js +1 -0
- package/dist/src/modules/table/filterTransformers.d.ts +53 -0
- package/dist/src/modules/table/filterTransformers.js +276 -0
- package/{src/types.ts → dist/src/types.d.ts} +3 -4
- package/dist/src/types.js +1 -0
- package/dist/tsconfig.lib.tsbuildinfo +1 -1
- package/package.json +8 -5
- package/.cursor/rules/web-ui.mdc +0 -126
- package/.turbo/turbo-build.log +0 -5
- package/.turbo/turbo-check-types.log +0 -5
- package/.turbo/turbo-lint$colon$fix.log +0 -381
- package/.turbo/turbo-lint.log +0 -361
- package/CHANGELOG.md +0 -19
- package/components.json +0 -21
- package/src/animations/card.motion.ts +0 -9
- package/src/components/AvatarUpload.tsx +0 -133
- package/src/components/Button.tsx +0 -14
- package/src/components/Calendar.css +0 -684
- package/src/components/Calendar.tsx +0 -32
- package/src/components/CardsSelect.tsx +0 -155
- package/src/components/CollapsibleSidebarMenuItem.tsx +0 -57
- package/src/components/ColorPicker.tsx +0 -56
- package/src/components/CopyButton.tsx +0 -45
- package/src/components/CropDialog.tsx +0 -154
- package/src/components/DialogProvider.tsx +0 -105
- package/src/components/ErrorFallback.tsx +0 -17
- package/src/components/FileDropzone.tsx +0 -120
- package/src/components/MultiSelectDropdown.tsx +0 -233
- package/src/components/PageAlert.tsx +0 -121
- package/src/components/SelectChips.tsx +0 -40
- package/src/components/SidebarItem.tsx +0 -26
- package/src/components/Steps.tsx +0 -340
- package/src/components/TablerIconPicker.tsx +0 -4260
- package/src/components/app-header.tsx +0 -40
- package/src/components/blur-card.tsx +0 -132
- package/src/components/features-section-demo-1.tsx +0 -127
- package/src/components/features-section-demo-2.tsx +0 -102
- package/src/components/features-section-demo-3.tsx +0 -272
- package/src/components/mode-toggle.tsx +0 -31
- package/src/components/nav-main.tsx +0 -69
- package/src/components/pricing-cards.tsx +0 -133
- package/src/components/shared/ButtonCopy.tsx +0 -50
- package/src/components/team-switcher.tsx +0 -83
- package/src/components/theme-provider.tsx +0 -74
- package/src/components/typewriter.tsx +0 -90
- package/src/components/ui/alert-dialog.tsx +0 -133
- package/src/components/ui/alert.tsx +0 -60
- package/src/components/ui/avatar.tsx +0 -47
- package/src/components/ui/badge.tsx +0 -33
- package/src/components/ui/bento-grid.tsx +0 -54
- package/src/components/ui/bento-grid2.tsx +0 -66
- package/src/components/ui/breadcrumb.tsx +0 -101
- package/src/components/ui/button.tsx +0 -50
- package/src/components/ui/card.tsx +0 -55
- package/src/components/ui/checkbox.tsx +0 -26
- package/src/components/ui/dialog.tsx +0 -119
- package/src/components/ui/dropdown-menu.tsx +0 -186
- package/src/components/ui/floating-navbar.tsx +0 -78
- package/src/components/ui/form.tsx +0 -167
- package/src/components/ui/image.tsx +0 -55
- package/src/components/ui/input.tsx +0 -22
- package/src/components/ui/label.tsx +0 -19
- package/src/components/ui/pagination.tsx +0 -105
- package/src/components/ui/progress.tsx +0 -23
- package/src/components/ui/resizable-navbar.tsx +0 -260
- package/src/components/ui/segment-control.tsx +0 -143
- package/src/components/ui/select.tsx +0 -153
- package/src/components/ui/separator.tsx +0 -24
- package/src/components/ui/sheet.tsx +0 -121
- package/src/components/ui/sidebar.tsx +0 -736
- package/src/components/ui/skeleton.tsx +0 -7
- package/src/components/ui/slider.tsx +0 -23
- package/src/components/ui/sonner.tsx +0 -27
- package/src/components/ui/spinner.tsx +0 -45
- package/src/components/ui/switch.tsx +0 -27
- package/src/components/ui/table.tsx +0 -90
- package/src/components/ui/tabs.tsx +0 -52
- package/src/components/ui/textarea.tsx +0 -18
- package/src/components/ui/timeline.tsx +0 -95
- package/src/components/ui/toast.tsx +0 -126
- package/src/components/ui/tooltip.tsx +0 -55
- package/src/components/ui/typewriter-effect.tsx +0 -181
- package/src/hooks/use-mobile.ts +0 -19
- package/src/hooks/useDialog.ts +0 -25
- package/src/icons/GoogleIcon.tsx +0 -32
- package/src/icons/LinkedInIcon.tsx +0 -30
- package/src/icons/MicrosoftIcon.tsx +0 -21
- package/src/lib/chatwoot.ts +0 -51
- package/src/lib/utils.ts +0 -6
- package/src/modules/app/components/AppLoader.tsx +0 -9
- package/src/modules/app/components/AppShell.tsx +0 -21
- package/src/modules/app/components/AppSidebar.tsx +0 -26
- package/src/modules/app/components/AppSidebarContent.tsx +0 -73
- package/src/modules/app/components/AppSidebarHeader.tsx +0 -57
- package/src/modules/app/components/AppSidebarInvites.tsx +0 -32
- package/src/modules/app/components/AppSidebarUser.tsx +0 -128
- package/src/modules/auth/components/AdminUserManagement.tsx +0 -1136
- package/src/modules/auth/components/AdminWaitlist.tsx +0 -358
- package/src/modules/auth/components/AuthLayout.tsx +0 -13
- package/src/modules/auth/components/AuthProviders.tsx +0 -105
- package/src/modules/auth/components/AuthRouter.tsx +0 -29
- package/src/modules/auth/components/ClaimAccountRoute.tsx +0 -242
- package/src/modules/auth/components/ErrorAuthRoute.tsx +0 -121
- package/src/modules/auth/components/ForgotPasswordForm.tsx +0 -58
- package/src/modules/auth/components/ForgotPasswordRoute.tsx +0 -27
- package/src/modules/auth/components/InviteFriends.tsx +0 -273
- package/src/modules/auth/components/LastUsedBadge.tsx +0 -22
- package/src/modules/auth/components/LoginForm.tsx +0 -104
- package/src/modules/auth/components/LoginRoute.tsx +0 -31
- package/src/modules/auth/components/LogoutRoute.tsx +0 -21
- package/src/modules/auth/components/OrganizationAcceptInvitationRoute.tsx +0 -161
- package/src/modules/auth/components/OrganizationMembersRoute.tsx +0 -730
- package/src/modules/auth/components/OrganizationSettingsRoute.tsx +0 -280
- package/src/modules/auth/components/OrganizationSwitcher.tsx +0 -148
- package/src/modules/auth/components/ProfileRoute.tsx +0 -104
- package/src/modules/auth/components/RangeNuqsDatePicker.tsx +0 -365
- package/src/modules/auth/components/ResetPasswordForm.tsx +0 -103
- package/src/modules/auth/components/ResetPasswordRoute.tsx +0 -27
- package/src/modules/auth/components/SignupFormRoute.tsx +0 -189
- package/src/modules/auth/components/SignupRoute.tsx +0 -53
- package/src/modules/auth/components/UserPreferences.tsx +0 -144
- package/src/modules/auth/components/WaitlistCard.tsx +0 -78
- package/src/modules/auth/components/WaitlistCodeValidation.tsx +0 -79
- package/src/modules/billing/components/BillingBetaPage.tsx +0 -124
- package/src/modules/billing/components/BillingInvoicePage.tsx +0 -180
- package/src/modules/billing/components/BillingPlanSelect.tsx +0 -14
- package/src/modules/billing/components/BillingRouter.tsx +0 -20
- package/src/modules/billing/components/BillingSinglePlanSelect.tsx +0 -172
- package/src/modules/table/components/ColumnOrderAndVisibility.tsx +0 -127
- package/src/modules/table/components/NuqsTable.tsx +0 -396
- package/src/modules/table/components/TableFiltering.tsx +0 -520
- package/src/modules/table/components/TablePagination.tsx +0 -59
- package/src/modules/table/filterTransformers.ts +0 -323
- package/src/vite-env.d.ts +0 -1
- package/translations/en/web-ui.json +0 -192
- package/tsconfig.json +0 -30
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import type { QueryFilters } from "@m5kdev/commons/modules/schemas/query.schema";
|
|
2
|
+
import type { ColumnDataType, FilterMethods } from "@m5kdev/commons/modules/table/filter.types";
|
|
3
|
+
type TableFilteringProps = {
|
|
4
|
+
columns: {
|
|
5
|
+
id: string;
|
|
6
|
+
label: string;
|
|
7
|
+
type?: ColumnDataType | null;
|
|
8
|
+
options?: {
|
|
9
|
+
label: string;
|
|
10
|
+
value: string;
|
|
11
|
+
}[] | null;
|
|
12
|
+
endColumnId?: string | null;
|
|
13
|
+
periodStartColumnId?: string | null;
|
|
14
|
+
periodEndColumnId?: string | null;
|
|
15
|
+
}[];
|
|
16
|
+
onFiltersChange: (filters: QueryFilters) => void;
|
|
17
|
+
filters: QueryFilters;
|
|
18
|
+
onClose?: () => void;
|
|
19
|
+
singleFilter?: boolean;
|
|
20
|
+
filterMethods?: Partial<FilterMethods>;
|
|
21
|
+
};
|
|
22
|
+
export declare const TableFiltering: ({ columns, onFiltersChange, filters: initialFilters, onClose, singleFilter, filterMethods, }: TableFilteringProps) => import("react/jsx-runtime").JSX.Element;
|
|
23
|
+
export {};
|
|
@@ -0,0 +1,236 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { DatePicker, DateRangePicker, Input, Select, SelectItem, } from "@heroui/react";
|
|
3
|
+
import { getLocalTimeZone, today } from "@internationalized/date";
|
|
4
|
+
import { PlusIcon, XIcon } from "lucide-react";
|
|
5
|
+
import { useCallback, useEffect, useMemo, useState } from "react";
|
|
6
|
+
import { Button } from "#components/ui/button";
|
|
7
|
+
import { transformFiltersFromHeroUI, transformFiltersToHeroUI, } from "../filterTransformers";
|
|
8
|
+
const componentForFilterMethod = {
|
|
9
|
+
text: (value, onChange) => (_jsx(Input, { size: "sm", "aria-label": "Select Value", className: "flex-1 min-w-0 text-sm", value: value ?? "", onChange: (e) => onChange(e.target.value) })),
|
|
10
|
+
number: (value, onChange) => (_jsx(Input, { size: "sm", "aria-label": "Select Value", type: "number", className: "flex-1 min-w-0 text-sm", value: value?.toString() ?? "", onChange: (e) => onChange(Number.parseFloat(e.target.value) || 0) })),
|
|
11
|
+
date: (value, onChange) => (_jsx(DatePicker, { size: "sm", "aria-label": "Select Value", className: "flex-1 min-w-0 text-sm", value: value ?? undefined, onChange: (date) => date && onChange(date), maxValue: today(getLocalTimeZone()) })),
|
|
12
|
+
range: (value, onChange) => (_jsx(DateRangePicker, { size: "sm", "aria-label": "Select Value", className: "flex-1 min-w-0 text-sm", value: value ?? undefined, onChange: (range) => range && onChange(range), maxValue: today(getLocalTimeZone()) })),
|
|
13
|
+
radio: (value, onChange) => (_jsxs(Select, { size: "sm", "aria-label": "Select Value", className: "flex-1 min-w-0 text-sm", selectedKeys: value ? ["true"] : ["false"], onSelectionChange: (keys) => onChange(keys.currentKey === "true"), children: [_jsx(SelectItem, { className: "text-sm", children: "True" }, "true"), _jsx(SelectItem, { className: "text-sm", children: "False" }, "false")] })),
|
|
14
|
+
select: (value, onChange, options = []) => (_jsx(Select, { size: "sm", "aria-label": "Select Value", className: "flex-1 min-w-0 text-sm", selectedKeys: value ?? new Set(), onSelectionChange: (keys) => keys && onChange(keys), children: options.map((option) => (_jsx(SelectItem, { className: "text-sm", children: option.label }, option.value))) })),
|
|
15
|
+
multiSelect: (value, onChange, options = []) => (_jsx(Select, { size: "sm", "aria-label": "Select Value", selectionMode: "multiple", className: "flex-1 min-w-0 text-sm", selectedKeys: value ? new Set(value) : new Set(), onSelectionChange: (keys) => onChange(keys), children: options.map((option) => (_jsx(SelectItem, { className: "text-sm", children: option.label }, option.value))) })),
|
|
16
|
+
};
|
|
17
|
+
const defaultFilterMethods = {
|
|
18
|
+
string: [
|
|
19
|
+
{ value: "contains", label: "Contains", component: "text" },
|
|
20
|
+
{ value: "equals", label: "Equals", component: "text" },
|
|
21
|
+
{ value: "starts_with", label: "Starts With", component: "text" },
|
|
22
|
+
{ value: "ends_with", label: "Ends With", component: "text" },
|
|
23
|
+
],
|
|
24
|
+
number: [
|
|
25
|
+
{ value: "equals", label: "Equals", component: "number" },
|
|
26
|
+
{ value: "greater_than", label: "Greater Than", component: "number" },
|
|
27
|
+
{ value: "less_than", label: "Less Than", component: "number" },
|
|
28
|
+
],
|
|
29
|
+
date: [
|
|
30
|
+
{ value: "on", label: "On", component: "date" },
|
|
31
|
+
{ value: "between", label: "Between", component: "range" },
|
|
32
|
+
{ value: "before", label: "Before", component: "date" },
|
|
33
|
+
{ value: "after", label: "After", component: "date" },
|
|
34
|
+
{ value: "intersect", label: "During", component: "range" },
|
|
35
|
+
],
|
|
36
|
+
boolean: [{ value: "equals", label: "Equals", component: "radio" }],
|
|
37
|
+
enum: [
|
|
38
|
+
{ value: "oneOf", label: "One Of", component: "multiSelect" },
|
|
39
|
+
{ value: "equals", label: "Equals", component: "select" },
|
|
40
|
+
],
|
|
41
|
+
};
|
|
42
|
+
const SINGLE_FILTER_KEY = "single-filter";
|
|
43
|
+
const mergeFilterMethods = (overrides) => ({
|
|
44
|
+
string: overrides?.string && overrides.string.length > 0
|
|
45
|
+
? overrides.string
|
|
46
|
+
: defaultFilterMethods.string,
|
|
47
|
+
number: overrides?.number && overrides.number.length > 0
|
|
48
|
+
? overrides.number
|
|
49
|
+
: defaultFilterMethods.number,
|
|
50
|
+
date: overrides?.date && overrides.date.length > 0 ? overrides.date : defaultFilterMethods.date,
|
|
51
|
+
boolean: overrides?.boolean && overrides.boolean.length > 0
|
|
52
|
+
? overrides.boolean
|
|
53
|
+
: defaultFilterMethods.boolean,
|
|
54
|
+
enum: overrides?.enum && overrides.enum.length > 0 ? overrides.enum : defaultFilterMethods.enum,
|
|
55
|
+
});
|
|
56
|
+
export const TableFiltering = ({ columns, onFiltersChange, filters: initialFilters = [], onClose, singleFilter = false, filterMethods, }) => {
|
|
57
|
+
const [filters, setFilters] = useState({});
|
|
58
|
+
const effectiveFilterMethods = useMemo(() => mergeFilterMethods(filterMethods), [filterMethods]);
|
|
59
|
+
const createEmptyFilter = useCallback(() => ({
|
|
60
|
+
columnId: "",
|
|
61
|
+
type: null,
|
|
62
|
+
value: null,
|
|
63
|
+
method: null,
|
|
64
|
+
options: null,
|
|
65
|
+
endColumnId: null,
|
|
66
|
+
periodStartColumnId: null,
|
|
67
|
+
periodEndColumnId: null,
|
|
68
|
+
}), []);
|
|
69
|
+
const addFilter = useCallback(() => {
|
|
70
|
+
setFilters((prev) => {
|
|
71
|
+
if (!singleFilter) {
|
|
72
|
+
const filterId = crypto.randomUUID();
|
|
73
|
+
return {
|
|
74
|
+
...prev,
|
|
75
|
+
[filterId]: createEmptyFilter(),
|
|
76
|
+
};
|
|
77
|
+
}
|
|
78
|
+
// single filter mode
|
|
79
|
+
return Object.keys(prev).length > 0 ? prev : { [SINGLE_FILTER_KEY]: createEmptyFilter() };
|
|
80
|
+
});
|
|
81
|
+
}, [createEmptyFilter, singleFilter]);
|
|
82
|
+
const removeFilter = useCallback((filterId) => {
|
|
83
|
+
setFilters((prev) => {
|
|
84
|
+
if (!singleFilter) {
|
|
85
|
+
const { [filterId]: _, ...rest } = prev;
|
|
86
|
+
return rest;
|
|
87
|
+
}
|
|
88
|
+
// single filter mode resets the lone filter
|
|
89
|
+
return { [SINGLE_FILTER_KEY]: createEmptyFilter() };
|
|
90
|
+
});
|
|
91
|
+
}, [createEmptyFilter, singleFilter]);
|
|
92
|
+
const columnsMap = useMemo(() => new Map(columns.map((column) => [column.id, column])), [columns]);
|
|
93
|
+
useEffect(() => {
|
|
94
|
+
// Transform initialFilters from FiltersToApply format to HeroUIFilter format
|
|
95
|
+
const transformedFilters = transformFiltersToHeroUI(initialFilters, columnsMap, effectiveFilterMethods);
|
|
96
|
+
if (!singleFilter) {
|
|
97
|
+
setFilters(Object.fromEntries(transformedFilters.map((filter) => [filter.columnId, filter])));
|
|
98
|
+
return;
|
|
99
|
+
}
|
|
100
|
+
const firstFilter = transformedFilters[0];
|
|
101
|
+
setFilters({
|
|
102
|
+
[SINGLE_FILTER_KEY]: firstFilter ?? createEmptyFilter(),
|
|
103
|
+
});
|
|
104
|
+
}, [createEmptyFilter, initialFilters, singleFilter, columnsMap, effectiveFilterMethods]);
|
|
105
|
+
const selectColumn = useCallback((filterId, columnId) => {
|
|
106
|
+
setFilters((prev) => {
|
|
107
|
+
const oldFilter = prev[filterId];
|
|
108
|
+
if (!oldFilter)
|
|
109
|
+
return prev;
|
|
110
|
+
const column = columnsMap.get(columnId);
|
|
111
|
+
if (!column)
|
|
112
|
+
return prev;
|
|
113
|
+
// If Period column, auto-set intersect method
|
|
114
|
+
const isPeriodColumn = columnId.endsWith("__period");
|
|
115
|
+
const intersectMethod = isPeriodColumn
|
|
116
|
+
? (effectiveFilterMethods.date.find((m) => m.value === "intersect") ?? null)
|
|
117
|
+
: null;
|
|
118
|
+
return {
|
|
119
|
+
...prev,
|
|
120
|
+
[filterId]: {
|
|
121
|
+
...oldFilter,
|
|
122
|
+
columnId,
|
|
123
|
+
type: column.type ?? null,
|
|
124
|
+
options: column.options ?? null,
|
|
125
|
+
endColumnId: column.endColumnId ?? null,
|
|
126
|
+
periodStartColumnId: column.periodStartColumnId ?? null,
|
|
127
|
+
periodEndColumnId: column.periodEndColumnId ?? null,
|
|
128
|
+
method: intersectMethod,
|
|
129
|
+
value: null,
|
|
130
|
+
},
|
|
131
|
+
};
|
|
132
|
+
});
|
|
133
|
+
}, [columnsMap, effectiveFilterMethods]);
|
|
134
|
+
const selectMethod = useCallback((filterId, method) => {
|
|
135
|
+
setFilters((prev) => {
|
|
136
|
+
const oldFilter = prev[filterId];
|
|
137
|
+
if (!oldFilter)
|
|
138
|
+
return prev;
|
|
139
|
+
return {
|
|
140
|
+
...prev,
|
|
141
|
+
[filterId]: { ...oldFilter, method, value: null },
|
|
142
|
+
};
|
|
143
|
+
});
|
|
144
|
+
}, []);
|
|
145
|
+
const selectValue = useCallback((filterId, value) => {
|
|
146
|
+
setFilters((prev) => {
|
|
147
|
+
const oldFilter = prev[filterId];
|
|
148
|
+
if (!oldFilter)
|
|
149
|
+
return prev;
|
|
150
|
+
return {
|
|
151
|
+
...prev,
|
|
152
|
+
[filterId]: { ...oldFilter, value },
|
|
153
|
+
};
|
|
154
|
+
});
|
|
155
|
+
}, []);
|
|
156
|
+
const filterEntries = useMemo(() => Object.entries(filters), [filters]);
|
|
157
|
+
const availableColumnsMap = useMemo(() => {
|
|
158
|
+
const map = new Map();
|
|
159
|
+
filterEntries.forEach(([filterId]) => {
|
|
160
|
+
const columnsUsedByOtherFilters = new Set(filterEntries
|
|
161
|
+
.filter(([id]) => id !== filterId)
|
|
162
|
+
.map(([_, f]) => f.columnId)
|
|
163
|
+
.filter((id) => id !== ""));
|
|
164
|
+
map.set(filterId, columns.filter((column) => !columnsUsedByOtherFilters.has(column.id)));
|
|
165
|
+
});
|
|
166
|
+
return map;
|
|
167
|
+
}, [filterEntries, columns]);
|
|
168
|
+
const applyFilters = useCallback(() => {
|
|
169
|
+
const heroUIFilters = Object.values(filters);
|
|
170
|
+
const filtersToApply = transformFiltersFromHeroUI(heroUIFilters);
|
|
171
|
+
onFiltersChange(filtersToApply);
|
|
172
|
+
onClose?.();
|
|
173
|
+
}, [filters, onFiltersChange, onClose]);
|
|
174
|
+
return (_jsxs("div", { className: "flex flex-col gap-2 p-1 min-w-[600px]", children: [filterEntries.map(([filterId, filter]) => {
|
|
175
|
+
const availableColumns = availableColumnsMap.get(filterId) ?? columns;
|
|
176
|
+
return (_jsx(TableFilteringItem, { id: filterId, filter: filter, columns: availableColumns, selectColumn: selectColumn, selectMethod: selectMethod, removeFilter: removeFilter, selectValue: selectValue, filterMethods: effectiveFilterMethods }, filterId));
|
|
177
|
+
}), !singleFilter && (_jsxs(Button, { variant: "outline", size: "sm", onClick: addFilter, children: [_jsx(PlusIcon, { className: "h-4 w-4" }), "Add Filter"] })), _jsx(Button, { onClick: applyFilters, children: singleFilter ? "Apply Filter" : "Apply Filters" })] }));
|
|
178
|
+
};
|
|
179
|
+
const TableFilteringItem = ({ id, filter, columns, selectColumn, selectMethod, selectValue, removeFilter, filterMethods, }) => {
|
|
180
|
+
const handleColumnChange = useCallback((keys) => {
|
|
181
|
+
const columnId = String(keys.currentKey);
|
|
182
|
+
selectColumn(id, columnId);
|
|
183
|
+
}, [id, selectColumn]);
|
|
184
|
+
const methodsForType = useMemo(() => {
|
|
185
|
+
if (!filter.type)
|
|
186
|
+
return [];
|
|
187
|
+
// Period columns only support intersect method
|
|
188
|
+
const isPeriodColumn = filter.columnId.endsWith("__period");
|
|
189
|
+
if (isPeriodColumn) {
|
|
190
|
+
const intersectMethod = filterMethods.date.find((m) => m.value === "intersect");
|
|
191
|
+
return intersectMethod ? [intersectMethod] : [];
|
|
192
|
+
}
|
|
193
|
+
const baseMethods = filterMethods[filter.type] ?? [];
|
|
194
|
+
const emptyMethods = [
|
|
195
|
+
{ value: "isEmpty", label: "Is Empty", component: null },
|
|
196
|
+
{ value: "isNotEmpty", label: "Is Not Empty", component: null },
|
|
197
|
+
];
|
|
198
|
+
if (filter.type !== "boolean" && filter.type !== "date") {
|
|
199
|
+
return [...baseMethods, ...emptyMethods];
|
|
200
|
+
}
|
|
201
|
+
return baseMethods;
|
|
202
|
+
}, [filter.type, filter.columnId, filter.method?.value, filterMethods]);
|
|
203
|
+
const handleMethodChange = useCallback((keys) => {
|
|
204
|
+
if (!filter.type)
|
|
205
|
+
return;
|
|
206
|
+
// Use methodsForType instead of filterMethods to include dynamically added methods
|
|
207
|
+
const method = methodsForType.find((currentMethod) => currentMethod.value === String(keys.currentKey));
|
|
208
|
+
if (method) {
|
|
209
|
+
selectMethod(id, method);
|
|
210
|
+
}
|
|
211
|
+
}, [id, filter.type, selectMethod, methodsForType]);
|
|
212
|
+
const handleValueChange = useCallback((value) => {
|
|
213
|
+
selectValue(id, value);
|
|
214
|
+
}, [id, selectValue]);
|
|
215
|
+
const methodSelect = useMemo(() => {
|
|
216
|
+
if (!filter.type)
|
|
217
|
+
return null;
|
|
218
|
+
return (_jsx(Select, { size: "sm", "aria-label": "Select Method", className: "w-40 flex-shrink-0 text-sm", selectedKeys: filter.method?.value ? [filter.method.value] : [], onSelectionChange: handleMethodChange, popoverProps: {
|
|
219
|
+
className: "w-auto min-w-max",
|
|
220
|
+
}, children: methodsForType.map((method) => (_jsx(SelectItem, { className: "text-sm", children: method.label }, method.value))) }));
|
|
221
|
+
}, [filter.type, filter.method?.value, methodsForType, handleMethodChange]);
|
|
222
|
+
const filterValueComponent = useMemo(() => {
|
|
223
|
+
if (!filter.method?.component) {
|
|
224
|
+
return _jsx("div", { className: "flex-1 min-w-0" });
|
|
225
|
+
}
|
|
226
|
+
const component = filter.method.component;
|
|
227
|
+
const ComponentFn = componentForFilterMethod[component];
|
|
228
|
+
if (!ComponentFn)
|
|
229
|
+
return _jsx("div", { className: "flex-1 min-w-0" });
|
|
230
|
+
return ComponentFn(filter.value, handleValueChange, filter.options ?? []);
|
|
231
|
+
}, [filter.method?.component, filter.value, filter.options, handleValueChange]);
|
|
232
|
+
const columnSelectItems = useMemo(() => columns.map((column) => (_jsx(SelectItem, { className: "text-sm", children: String(column.label) }, column.id))), [columns]);
|
|
233
|
+
return (_jsxs("div", { className: "flex items-center gap-2 w-full", children: [_jsxs("div", { className: "flex flex-1 items-center gap-2 min-w-0", children: [_jsx(Select, { size: "sm", "aria-label": "Select Column", className: "w-40 flex-shrink-0 text-sm", selectedKeys: filter.columnId ? [filter.columnId] : [], onSelectionChange: handleColumnChange, popoverProps: {
|
|
234
|
+
className: "w-auto min-w-max",
|
|
235
|
+
}, children: columnSelectItems }), methodSelect, filterValueComponent] }), _jsx(Button, { variant: "outline", size: "sm", onClick: () => removeFilter(id), children: _jsx(XIcon, { className: "h-4 w-4" }) })] }));
|
|
236
|
+
};
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { TableProps } from "@m5kdev/frontend/modules/table/hooks/useNuqsTable";
|
|
2
|
+
interface TablePaginationProps {
|
|
3
|
+
pageCount: number;
|
|
4
|
+
page: TableProps["page"];
|
|
5
|
+
limit: TableProps["limit"];
|
|
6
|
+
setPagination: TableProps["setPagination"];
|
|
7
|
+
}
|
|
8
|
+
export declare const TablePagination: ({ pageCount, page, limit, setPagination, }: TablePaginationProps) => import("react/jsx-runtime").JSX.Element;
|
|
9
|
+
export {};
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { Input } from "#components/ui/input";
|
|
3
|
+
import { Pagination, PaginationContent, PaginationNext, PaginationPrevious, } from "#components/ui/pagination";
|
|
4
|
+
export const TablePagination = ({ pageCount, page = 1, limit = 10, setPagination, }) => {
|
|
5
|
+
const isFirstPage = page === 1;
|
|
6
|
+
const isLastPage = page >= pageCount;
|
|
7
|
+
return (_jsx(Pagination, { children: _jsxs(PaginationContent, { children: [_jsx(PaginationPrevious, { isActive: !isFirstPage, onClick: () => {
|
|
8
|
+
if (!isFirstPage) {
|
|
9
|
+
setPagination?.({ pageIndex: page - 2, pageSize: limit });
|
|
10
|
+
}
|
|
11
|
+
} }), _jsx(Input, { type: "number", value: page, min: 1, max: pageCount, onChange: (e) => {
|
|
12
|
+
const newPage = e.target.valueAsNumber;
|
|
13
|
+
if (newPage >= 1 && newPage <= pageCount) {
|
|
14
|
+
setPagination?.({ pageIndex: newPage - 1, pageSize: limit });
|
|
15
|
+
}
|
|
16
|
+
} }), _jsx(PaginationNext, { isActive: !isLastPage, onClick: () => {
|
|
17
|
+
if (!isLastPage) {
|
|
18
|
+
setPagination?.({ pageIndex: page, pageSize: limit });
|
|
19
|
+
}
|
|
20
|
+
} })] }) }));
|
|
21
|
+
};
|
|
@@ -1,11 +1,12 @@
|
|
|
1
|
-
import type { ColumnDataType as CommonColumnDataType } from "@m5kdev/commons/modules/table/filter.types";
|
|
2
|
-
|
|
3
|
-
export type
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
1
|
+
import type { ColumnDataType as CommonColumnDataType } from "@m5kdev/commons/modules/table/filter.types";
|
|
2
|
+
export type ColumnDataType = CommonColumnDataType;
|
|
3
|
+
export type ColumnItem = {
|
|
4
|
+
id: string;
|
|
5
|
+
label: string;
|
|
6
|
+
visibility: boolean;
|
|
7
|
+
options?: {
|
|
8
|
+
label: string;
|
|
9
|
+
value: string;
|
|
10
|
+
}[];
|
|
11
|
+
type?: ColumnDataType;
|
|
12
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import type { DateValue, RangeValue, SharedSelection } from "@heroui/react";
|
|
2
|
+
import { CalendarDate } from "@internationalized/date";
|
|
3
|
+
import type { QueryFilters } from "@m5kdev/commons/modules/schemas/query.schema";
|
|
4
|
+
import type { ColumnDataType, FilterMethod } from "@m5kdev/commons/modules/table/filter.types";
|
|
5
|
+
export type FilterValue = string | number | string[] | DateValue | RangeValue<DateValue> | boolean | SharedSelection | null;
|
|
6
|
+
export interface HeroUIFilter {
|
|
7
|
+
columnId: string;
|
|
8
|
+
type: ColumnDataType | null;
|
|
9
|
+
value: FilterValue;
|
|
10
|
+
method: FilterMethod | null;
|
|
11
|
+
options?: {
|
|
12
|
+
label: string;
|
|
13
|
+
value: string;
|
|
14
|
+
}[] | null;
|
|
15
|
+
endColumnId?: string | null;
|
|
16
|
+
periodStartColumnId?: string | null;
|
|
17
|
+
periodEndColumnId?: string | null;
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Convert CalendarDate to UTC ISO string at midnight UTC
|
|
21
|
+
*/
|
|
22
|
+
export declare const calendarDateToUTC: (date: CalendarDate) => string;
|
|
23
|
+
/**
|
|
24
|
+
* Convert CalendarDate to end of day UTC ISO string
|
|
25
|
+
*/
|
|
26
|
+
export declare const calendarDateToEndOfDayUTC: (date: CalendarDate) => string;
|
|
27
|
+
/**
|
|
28
|
+
* Convert any date filter method from URL to a RangeValue for DateRangePicker
|
|
29
|
+
* Handles: on, before, after, between, intersect
|
|
30
|
+
* Parses UTC ISO strings as UTC to avoid timezone shifts
|
|
31
|
+
*/
|
|
32
|
+
export declare const dateFilterToRangeValue: (filters: QueryFilters | undefined, columnId: string) => RangeValue<DateValue> | null;
|
|
33
|
+
/**
|
|
34
|
+
* Transform filters from backend format (QueryFilter[]) to HeroUI format (HeroUIFilter[])
|
|
35
|
+
* Used when loading filters from URL/backend to populate HeroUI components
|
|
36
|
+
*/
|
|
37
|
+
export declare const transformFiltersToHeroUI: (filtersToTransform: QueryFilters, columnsMap: Map<string, {
|
|
38
|
+
id: string;
|
|
39
|
+
label: string;
|
|
40
|
+
type?: ColumnDataType | null;
|
|
41
|
+
options?: {
|
|
42
|
+
label: string;
|
|
43
|
+
value: string;
|
|
44
|
+
}[] | null;
|
|
45
|
+
endColumnId?: string | null;
|
|
46
|
+
periodStartColumnId?: string | null;
|
|
47
|
+
periodEndColumnId?: string | null;
|
|
48
|
+
}>, filterMethods: Record<ColumnDataType, FilterMethod[]>) => HeroUIFilter[];
|
|
49
|
+
/**
|
|
50
|
+
* Transform filters from HeroUI format (HeroUIFilter[]) to backend format (QueryFilter[])
|
|
51
|
+
* Used when applying filters to send to backend/URL
|
|
52
|
+
*/
|
|
53
|
+
export declare const transformFiltersFromHeroUI: (filters: HeroUIFilter[]) => QueryFilters;
|
|
@@ -0,0 +1,276 @@
|
|
|
1
|
+
import { CalendarDate, getLocalTimeZone, today } from "@internationalized/date";
|
|
2
|
+
import { DateTime } from "luxon";
|
|
3
|
+
/**
|
|
4
|
+
* Convert CalendarDate to UTC ISO string at midnight UTC
|
|
5
|
+
*/
|
|
6
|
+
export const calendarDateToUTC = (date) => {
|
|
7
|
+
return DateTime.utc(date.year, date.month, date.day).toISO() ?? "";
|
|
8
|
+
};
|
|
9
|
+
/**
|
|
10
|
+
* Convert CalendarDate to end of day UTC ISO string
|
|
11
|
+
*/
|
|
12
|
+
export const calendarDateToEndOfDayUTC = (date) => {
|
|
13
|
+
return DateTime.utc(date.year, date.month, date.day).endOf("day").toISO() ?? "";
|
|
14
|
+
};
|
|
15
|
+
/**
|
|
16
|
+
* Parse UTC ISO string to CalendarDate (preserves UTC date, no timezone shift)
|
|
17
|
+
*/
|
|
18
|
+
const parseUTCToCalendarDate = (isoString) => {
|
|
19
|
+
try {
|
|
20
|
+
const dt = DateTime.fromISO(isoString, { zone: "utc" });
|
|
21
|
+
if (!dt.isValid)
|
|
22
|
+
return null;
|
|
23
|
+
return new CalendarDate(dt.year, dt.month, dt.day);
|
|
24
|
+
}
|
|
25
|
+
catch {
|
|
26
|
+
return null;
|
|
27
|
+
}
|
|
28
|
+
};
|
|
29
|
+
/**
|
|
30
|
+
* Convert any date filter method from URL to a RangeValue for DateRangePicker
|
|
31
|
+
* Handles: on, before, after, between, intersect
|
|
32
|
+
* Parses UTC ISO strings as UTC to avoid timezone shifts
|
|
33
|
+
*/
|
|
34
|
+
export const dateFilterToRangeValue = (filters, columnId) => {
|
|
35
|
+
if (!filters)
|
|
36
|
+
return null;
|
|
37
|
+
const filter = filters.find((f) => f.columnId === columnId);
|
|
38
|
+
if (!filter || filter.type !== "date")
|
|
39
|
+
return null;
|
|
40
|
+
const todayDate = today(getLocalTimeZone());
|
|
41
|
+
const epochStart = new CalendarDate(1970, 1, 1);
|
|
42
|
+
try {
|
|
43
|
+
switch (filter.method) {
|
|
44
|
+
case "on": {
|
|
45
|
+
// Same day range
|
|
46
|
+
if (typeof filter.value !== "string" || !filter.value)
|
|
47
|
+
return null;
|
|
48
|
+
const day = parseUTCToCalendarDate(filter.value);
|
|
49
|
+
if (!day)
|
|
50
|
+
return null;
|
|
51
|
+
return {
|
|
52
|
+
start: day,
|
|
53
|
+
end: day,
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
case "before": {
|
|
57
|
+
// [epochStart, selectedDay]
|
|
58
|
+
if (typeof filter.value !== "string" || !filter.value)
|
|
59
|
+
return null;
|
|
60
|
+
const day = parseUTCToCalendarDate(filter.value);
|
|
61
|
+
if (!day)
|
|
62
|
+
return null;
|
|
63
|
+
return {
|
|
64
|
+
start: epochStart,
|
|
65
|
+
end: day,
|
|
66
|
+
};
|
|
67
|
+
}
|
|
68
|
+
case "after": {
|
|
69
|
+
// [selectedDay, today]
|
|
70
|
+
if (typeof filter.value !== "string" || !filter.value)
|
|
71
|
+
return null;
|
|
72
|
+
const day = parseUTCToCalendarDate(filter.value);
|
|
73
|
+
if (!day)
|
|
74
|
+
return null;
|
|
75
|
+
return {
|
|
76
|
+
start: day,
|
|
77
|
+
end: todayDate,
|
|
78
|
+
};
|
|
79
|
+
}
|
|
80
|
+
case "between":
|
|
81
|
+
case "intersect": {
|
|
82
|
+
// [value, valueTo]
|
|
83
|
+
if (typeof filter.value !== "string" || !filter.value || !filter.valueTo)
|
|
84
|
+
return null;
|
|
85
|
+
const startDate = parseUTCToCalendarDate(filter.value);
|
|
86
|
+
const endDate = parseUTCToCalendarDate(filter.valueTo);
|
|
87
|
+
if (!startDate || !endDate)
|
|
88
|
+
return null;
|
|
89
|
+
return {
|
|
90
|
+
start: startDate,
|
|
91
|
+
end: endDate,
|
|
92
|
+
};
|
|
93
|
+
}
|
|
94
|
+
default:
|
|
95
|
+
return null;
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
catch {
|
|
99
|
+
return null;
|
|
100
|
+
}
|
|
101
|
+
};
|
|
102
|
+
/**
|
|
103
|
+
* Transform filters from backend format (QueryFilter[]) to HeroUI format (HeroUIFilter[])
|
|
104
|
+
* Used when loading filters from URL/backend to populate HeroUI components
|
|
105
|
+
*/
|
|
106
|
+
export const transformFiltersToHeroUI = (filtersToTransform, columnsMap, filterMethods) => {
|
|
107
|
+
return filtersToTransform.map((filter) => {
|
|
108
|
+
let value = null;
|
|
109
|
+
let method = null;
|
|
110
|
+
let columnId = filter.columnId;
|
|
111
|
+
// Check if this intersect filter should map to Period pseudo-column
|
|
112
|
+
if (filter.type === "date" && filter.method === "intersect" && filter.endColumnId) {
|
|
113
|
+
const periodColumnId = `${filter.columnId}__period`;
|
|
114
|
+
const periodColumn = columnsMap.get(periodColumnId);
|
|
115
|
+
if (periodColumn) {
|
|
116
|
+
// Map to Period pseudo-column
|
|
117
|
+
columnId = periodColumnId;
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
// Find the method object from the methods configuration
|
|
121
|
+
if (filter.type) {
|
|
122
|
+
const availableMethods = filterMethods[filter.type];
|
|
123
|
+
const methodObj = availableMethods?.find((m) => m.value === filter.method);
|
|
124
|
+
if (methodObj) {
|
|
125
|
+
method = methodObj;
|
|
126
|
+
}
|
|
127
|
+
else if (filter.method === "isEmpty" || filter.method === "isNotEmpty") {
|
|
128
|
+
// Handle isEmpty/isNotEmpty even if not in the provided method list
|
|
129
|
+
method = {
|
|
130
|
+
value: filter.method,
|
|
131
|
+
label: filter.method === "isEmpty" ? "Is Empty" : "Is Not Empty",
|
|
132
|
+
component: null,
|
|
133
|
+
};
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
// Transform value based on type
|
|
137
|
+
switch (filter.type) {
|
|
138
|
+
case "string":
|
|
139
|
+
value = filter.value;
|
|
140
|
+
break;
|
|
141
|
+
case "number":
|
|
142
|
+
value = filter.value;
|
|
143
|
+
break;
|
|
144
|
+
case "date":
|
|
145
|
+
// Use the shared helper for range conversion, or parse single dates as UTC
|
|
146
|
+
if (filter.method === "between" || filter.method === "intersect") {
|
|
147
|
+
// For range methods, use the helper function
|
|
148
|
+
const range = dateFilterToRangeValue([filter], filter.columnId);
|
|
149
|
+
value = range;
|
|
150
|
+
}
|
|
151
|
+
else {
|
|
152
|
+
// Single date value: parse UTC ISO string and extract UTC calendar date
|
|
153
|
+
if (typeof filter.value === "string" && filter.value) {
|
|
154
|
+
const day = parseUTCToCalendarDate(filter.value);
|
|
155
|
+
value = day ? day : null;
|
|
156
|
+
}
|
|
157
|
+
else {
|
|
158
|
+
value = null;
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
break;
|
|
162
|
+
case "boolean":
|
|
163
|
+
value = filter.value;
|
|
164
|
+
break;
|
|
165
|
+
case "enum":
|
|
166
|
+
if (filter.method === "oneOf" && Array.isArray(filter.value)) {
|
|
167
|
+
// Multi-select: array of strings to SharedSelection (Set)
|
|
168
|
+
value = new Set(filter.value);
|
|
169
|
+
}
|
|
170
|
+
else {
|
|
171
|
+
// Single select: string to SharedSelection with currentKey
|
|
172
|
+
const selection = new Set([filter.value]);
|
|
173
|
+
// Set currentKey property
|
|
174
|
+
Object.defineProperty(selection, "currentKey", {
|
|
175
|
+
value: filter.value,
|
|
176
|
+
writable: true,
|
|
177
|
+
enumerable: false,
|
|
178
|
+
configurable: true,
|
|
179
|
+
});
|
|
180
|
+
value = selection;
|
|
181
|
+
}
|
|
182
|
+
break;
|
|
183
|
+
default:
|
|
184
|
+
value = filter.value;
|
|
185
|
+
}
|
|
186
|
+
const column = columnsMap.get(columnId);
|
|
187
|
+
return {
|
|
188
|
+
columnId,
|
|
189
|
+
type: filter.type,
|
|
190
|
+
value,
|
|
191
|
+
method,
|
|
192
|
+
options: column?.options ?? null,
|
|
193
|
+
endColumnId: column?.endColumnId ?? null,
|
|
194
|
+
periodStartColumnId: column?.periodStartColumnId ?? null,
|
|
195
|
+
periodEndColumnId: column?.periodEndColumnId ?? null,
|
|
196
|
+
};
|
|
197
|
+
});
|
|
198
|
+
};
|
|
199
|
+
/**
|
|
200
|
+
* Transform filters from HeroUI format (HeroUIFilter[]) to backend format (QueryFilter[])
|
|
201
|
+
* Used when applying filters to send to backend/URL
|
|
202
|
+
*/
|
|
203
|
+
export const transformFiltersFromHeroUI = (filters) => {
|
|
204
|
+
const filtersToApply = [];
|
|
205
|
+
for (const filter of filters) {
|
|
206
|
+
let value;
|
|
207
|
+
let valueTo;
|
|
208
|
+
// Handle isEmpty/isNotEmpty methods - they don't need a value
|
|
209
|
+
if (filter.method?.value === "isEmpty" || filter.method?.value === "isNotEmpty") {
|
|
210
|
+
if (filter.columnId === "")
|
|
211
|
+
continue;
|
|
212
|
+
const result = {
|
|
213
|
+
columnId: filter.columnId,
|
|
214
|
+
type: filter.type,
|
|
215
|
+
method: filter.method.value,
|
|
216
|
+
value: "",
|
|
217
|
+
};
|
|
218
|
+
filtersToApply.push(result);
|
|
219
|
+
continue;
|
|
220
|
+
}
|
|
221
|
+
// Handle Period pseudo-column: map to intersect on real columns
|
|
222
|
+
const isPeriodColumn = filter.columnId.endsWith("__period");
|
|
223
|
+
const actualColumnId = isPeriodColumn && filter.periodStartColumnId ? filter.periodStartColumnId : filter.columnId;
|
|
224
|
+
const actualEndColumnId = isPeriodColumn && filter.periodEndColumnId ? filter.periodEndColumnId : filter.endColumnId;
|
|
225
|
+
switch (filter.type) {
|
|
226
|
+
case "date":
|
|
227
|
+
if (filter.method?.value === "between" ||
|
|
228
|
+
filter.method?.value === "intersect" ||
|
|
229
|
+
isPeriodColumn) {
|
|
230
|
+
const range = filter.value;
|
|
231
|
+
if (range?.start && range?.end) {
|
|
232
|
+
value = calendarDateToUTC(range.start);
|
|
233
|
+
valueTo = calendarDateToUTC(range.end);
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
else {
|
|
237
|
+
const dateValue = filter.value;
|
|
238
|
+
if (dateValue?.year) {
|
|
239
|
+
value = calendarDateToUTC(dateValue);
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
break;
|
|
243
|
+
case "enum": {
|
|
244
|
+
const selection = filter.value;
|
|
245
|
+
if (selection) {
|
|
246
|
+
value =
|
|
247
|
+
filter.method?.value === "oneOf"
|
|
248
|
+
? Array.from(selection).map(String)
|
|
249
|
+
: String(selection.currentKey);
|
|
250
|
+
}
|
|
251
|
+
break;
|
|
252
|
+
}
|
|
253
|
+
default:
|
|
254
|
+
value = filter.value;
|
|
255
|
+
}
|
|
256
|
+
// Skip filters without valid values
|
|
257
|
+
if (!value || value === "" || filter.columnId === "")
|
|
258
|
+
continue;
|
|
259
|
+
if (filter.type === "enum" && Array.isArray(value) && value.length === 0)
|
|
260
|
+
continue;
|
|
261
|
+
// For Period columns, always use intersect method
|
|
262
|
+
const actualMethod = isPeriodColumn ? "intersect" : filter.method.value;
|
|
263
|
+
const result = {
|
|
264
|
+
columnId: actualColumnId,
|
|
265
|
+
type: filter.type,
|
|
266
|
+
method: actualMethod,
|
|
267
|
+
value: value,
|
|
268
|
+
...(valueTo && { valueTo: valueTo }),
|
|
269
|
+
...(actualMethod === "intersect" && actualEndColumnId
|
|
270
|
+
? { endColumnId: actualEndColumnId }
|
|
271
|
+
: {}),
|
|
272
|
+
};
|
|
273
|
+
filtersToApply.push(result);
|
|
274
|
+
}
|
|
275
|
+
return filtersToApply;
|
|
276
|
+
};
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import type { BackendTRPCRouter } from "@m5kdev/backend/types";
|
|
2
|
-
import type { createTRPCContext } from "@trpc/tanstack-react-query";
|
|
3
|
-
|
|
4
|
-
export type UseBackendTRPC = ReturnType<typeof createTRPCContext<BackendTRPCRouter>>["useTRPC"];
|
|
1
|
+
import type { BackendTRPCRouter } from "@m5kdev/backend/types";
|
|
2
|
+
import type { createTRPCContext } from "@trpc/tanstack-react-query";
|
|
3
|
+
export type UseBackendTRPC = ReturnType<typeof createTRPCContext<BackendTRPCRouter>>["useTRPC"];
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|