@pagamio/frontend-commons-lib 0.8.244 → 0.8.246
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/lib/auth/components/AppBanner.js +1 -1
- package/lib/auth/components/AuthFormUtils.d.ts +2 -0
- package/lib/auth/components/AuthFormUtils.js +2 -1
- package/lib/auth/components/AuthPageLayout.d.ts +2 -0
- package/lib/auth/components/AuthPageLayout.js +3 -3
- package/lib/auth/components/ChangePasswordPage.js +2 -1
- package/lib/auth/components/CustomerRegistrationPage.js +2 -1
- package/lib/auth/components/FeatureCarousel.js +2 -1
- package/lib/auth/components/LoginPage.js +2 -1
- package/lib/auth/components/OtpVerification.d.ts +2 -0
- package/lib/auth/components/OtpVerification.js +3 -3
- package/lib/auth/shared/layout/AuthPageLayout.js +1 -1
- package/lib/components/charts/LineGraph.js +1 -1
- package/lib/components/layout/AuthPageLayout.js +1 -1
- package/lib/components/layout/BreadcrumbNav.js +2 -2
- package/lib/components/layout/Navbar.d.ts +1 -1
- package/lib/components/layout/Navbar.js +8 -7
- package/lib/components/layout/PageHeader.js +1 -1
- package/lib/components/layout/SessionExpiryModal.js +2 -2
- package/lib/components/layout/Sidebar.js +20 -30
- package/lib/components/layout/index.d.ts +0 -1
- package/lib/components/layout/index.js +0 -1
- package/lib/components/sidebar-v2/NavbarV2.d.ts +1 -1
- package/lib/components/sidebar-v2/NavbarV2.js +16 -8
- package/lib/components/sidebar-v2/SidebarV2.js +1 -1
- package/lib/components/sidebar-v2/SidebarV2Primitives.js +13 -16
- package/lib/components/ui/Button.d.ts +14 -1
- package/lib/components/ui/Button.js +26 -12
- package/lib/components/ui/Card.d.ts +35 -26
- package/lib/components/ui/Card.js +46 -29
- package/lib/components/ui/Chart.js +1 -1
- package/lib/components/ui/Checkbox.js +1 -1
- package/lib/components/ui/DashboardCard.js +2 -1
- package/lib/components/ui/DatePicker.js +10 -10
- package/lib/components/ui/DateRangeModal.js +2 -2
- package/lib/components/ui/DateRangePickerWithPresets.js +1 -1
- package/lib/components/ui/DetailsCard.js +1 -1
- package/lib/components/ui/EmptyState.js +1 -1
- package/lib/components/ui/FilterComponent.js +6 -17
- package/lib/components/ui/FilterList.js +5 -2
- package/lib/components/ui/FilterSection.js +2 -1
- package/lib/components/ui/FilterWrapper.js +1 -1
- package/lib/components/ui/HoverableValue.js +2 -1
- package/lib/components/ui/ImageComponent.d.ts +10 -4
- package/lib/components/ui/ImageComponent.js +15 -3
- package/lib/components/ui/ImageUploader.js +1 -1
- package/lib/components/ui/Input.js +1 -1
- package/lib/components/ui/LegacyCard.js +1 -1
- package/lib/components/ui/Loader.js +2 -2
- package/lib/components/ui/Modal.js +2 -2
- package/lib/components/ui/MultiSelect.js +5 -4
- package/lib/components/ui/NotificationModal.js +3 -3
- package/lib/components/ui/PagamioTabs.d.ts +50 -0
- package/lib/components/ui/PagamioTabs.js +126 -0
- package/lib/components/ui/PhoneInput.js +3 -3
- package/lib/components/ui/RangeDatePicker.js +1 -1
- package/lib/components/ui/Select.js +5 -9
- package/lib/components/ui/Sheet.d.ts +1 -1
- package/lib/components/ui/StatCard.d.ts +2 -2
- package/lib/components/ui/StatCard.js +7 -6
- package/lib/components/ui/Switch.js +4 -4
- package/lib/components/ui/TableDownload.js +2 -2
- package/lib/components/ui/TextField.js +2 -1
- package/lib/components/ui/Textarea.js +1 -1
- package/lib/components/ui/Toast.js +11 -10
- package/lib/components/ui/Tooltip.js +1 -4
- package/lib/components/ui/UploadField.js +2 -2
- package/lib/components/ui/index.d.ts +2 -4
- package/lib/components/ui/index.js +2 -4
- package/lib/context/ColorModeContext.d.ts +18 -0
- package/lib/context/ColorModeContext.js +89 -0
- package/lib/context/index.d.ts +1 -0
- package/lib/context/index.js +1 -0
- package/lib/dashboard-visuals/components/CardWrapper.js +3 -2
- package/lib/dashboard-visuals/components/ChartDetailsModal.js +3 -3
- package/lib/dashboard-visuals/components/DashboardFilter.js +1 -1
- package/lib/dashboard-visuals/components/EmptyState.js +1 -1
- package/lib/dashboard-visuals/components/ErrorState.js +2 -1
- package/lib/dashboard-visuals/components/Pagination.js +2 -1
- package/lib/dashboard-visuals/components/Switch.js +1 -1
- package/lib/dashboard-visuals/components/molecules/DataGrid.js +44 -68
- package/lib/dashboard-visuals/components/molecules/NoChartData.js +2 -1
- package/lib/dashboard-visuals/components/molecules/VisualChart.js +1 -1
- package/lib/dashboard-visuals/components/types.d.ts +5 -50
- package/lib/dashboard-visuals/index.js +2 -2
- package/lib/dashboard-visuals/utils/chartOptions.d.ts +23 -0
- package/lib/dashboard-visuals/utils/chartOptions.js +11 -0
- package/lib/dashboard-visuals/utils/tooltipUtils.js +4 -4
- package/lib/dashboard-visuals/v2/components/ApexChartWrapper.js +37 -4
- package/lib/dashboard-visuals/v2/components/DashboardStatCardRow.js +8 -23
- package/lib/dashboard-visuals/v2/components/DashboardWrapperV2.js +2 -1
- package/lib/dashboard-visuals/visuals/BarChart.js +3 -3
- package/lib/dashboard-visuals/visuals/DistributionChart.js +1 -1
- package/lib/dashboard-visuals/visuals/DonutChart.js +4 -4
- package/lib/dashboard-visuals/visuals/ItemPerformanceCard.js +7 -6
- package/lib/dashboard-visuals/visuals/LineChart.js +5 -5
- package/lib/dashboard-visuals/visuals/MetricSummaryCard.js +1 -1
- package/lib/dashboard-visuals/visuals/MultiGaugeChart.js +2 -2
- package/lib/dashboard-visuals/visuals/SelectedEventTile.js +1 -1
- package/lib/dashboard-visuals/visuals/Table.d.ts +2 -1
- package/lib/dashboard-visuals/visuals/Table.js +38 -54
- package/lib/dashboard-visuals/visuals/WaterfallChart.js +1 -1
- package/lib/feedback/FeedbackPage.js +1 -1
- package/lib/form-engine/FormEngine.js +2 -2
- package/lib/form-engine/components/inputs/card-expiry-input/CardExpiryInput.js +1 -1
- package/lib/form-engine/components/inputs/checkbox-input/CheckboxInput.js +1 -1
- package/lib/form-engine/components/inputs/credit-card-input/CreditCardInput.js +1 -1
- package/lib/form-engine/components/inputs/date-input/DateInput.js +1 -1
- package/lib/form-engine/components/inputs/email-input/EmailInput.js +1 -1
- package/lib/form-engine/components/inputs/label-input/LabelInput.js +1 -1
- package/lib/form-engine/components/inputs/multi-select-input/MultiSelectInput.js +1 -1
- package/lib/form-engine/components/inputs/number-input/NumberInput.js +1 -1
- package/lib/form-engine/components/inputs/password-input/PasswordInput.js +2 -2
- package/lib/form-engine/components/inputs/radio-button/RadioInput.js +1 -1
- package/lib/form-engine/components/inputs/select/SelectInput.js +1 -1
- package/lib/form-engine/components/inputs/textarea-input/TextareaInput.js +1 -1
- package/lib/form-engine/components/inputs/time-input/TimeInput.d.ts +1 -1
- package/lib/form-engine/components/inputs/time-input/TimeInput.js +15 -3
- package/lib/form-engine/components/inputs/toggle-switch-input/ToggleSwitchInput.js +1 -1
- package/lib/form-engine/components/inputs/upload-field/UploadFieldForm.js +3 -3
- package/lib/index.d.ts +3 -1
- package/lib/index.js +2 -0
- package/lib/pagamio-drawer/TopUpWalletDrawer/TopUpWalletContent.js +4 -4
- package/lib/pagamio-drawer/components/BaseDrawer.js +3 -2
- package/lib/pagamio-drawer/components/DrawerContent.js +2 -2
- package/lib/pagamio-table/data-table/Defaults.d.ts +11 -0
- package/lib/pagamio-table/data-table/Defaults.js +35 -0
- package/lib/pagamio-table/data-table/ExportButton.js +7 -7
- package/lib/pagamio-table/data-table/TableDownload.js +2 -2
- package/lib/pagamio-table/data-table/index.d.ts +2 -4
- package/lib/pagamio-table/data-table/index.js +178 -5
- package/lib/pagamio-table/data-table/types.d.ts +171 -129
- package/lib/pagamio-table/index.d.ts +1 -0
- package/lib/pagamio-table/index.js +1 -0
- package/lib/shared/hooks/useImageUpload.d.ts +4 -2
- package/lib/shared/hooks/useImageUpload.js +5 -4
- package/lib/shared/hooks/usePagamioTable.d.ts +3 -156
- package/lib/shared/hooks/usePagamioTable.js +250 -390
- package/lib/shared/utils/functionHelper.d.ts +10 -2
- package/lib/shared/utils/functionHelper.js +44 -2
- package/lib/styles.css +901 -1213
- package/lib/translations/components/LocaleSwitcher.js +2 -2
- package/package.json +13 -13
- package/lib/components/layout/VerticalTabsLayout.d.ts +0 -12
- package/lib/components/layout/VerticalTabsLayout.js +0 -13
- package/lib/components/ui/ContainedTab.d.ts +0 -21
- package/lib/components/ui/ContainedTab.js +0 -37
- package/lib/components/ui/Tab.d.ts +0 -15
- package/lib/components/ui/Tab.js +0 -13
- package/lib/components/ui/VerticalTab.d.ts +0 -16
- package/lib/components/ui/VerticalTab.js +0 -13
- package/lib/dashboard-visuals/components/DataTable.d.ts +0 -3
- package/lib/dashboard-visuals/components/DataTable.js +0 -57
- package/lib/pagamio-table/data-table/MantineCoreTable.d.ts +0 -44
- package/lib/pagamio-table/data-table/MantineCoreTable.js +0 -123
- package/lib/pagamio-table/data-table/Pagination.d.ts +0 -10
- package/lib/pagamio-table/data-table/Pagination.js +0 -5
- package/lib/pagamio-table/data-table/TableToolbar.d.ts +0 -3
- package/lib/pagamio-table/data-table/TableToolbar.js +0 -24
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
2
|
const AppBanner = ({ text = 'EVENTS!', backgroundColor = '#b45dae' }) => {
|
|
3
|
-
return (_jsx("div", { className: "flex w-full justify-end mr-[29%] mt-[-7%]", children: _jsx("div", { className: "inline-block px-6 py-2 text-white font-bold uppercase text-[15px] relative bg-primary
|
|
3
|
+
return (_jsx("div", { className: "flex w-full justify-end mr-[29%] mt-[-7%]", children: _jsx("div", { className: "inline-block px-6 py-2 text-white font-bold uppercase text-[15px] relative bg-primary", style: {
|
|
4
4
|
// backgroundColor: backgroundColor,
|
|
5
5
|
// This clip-path creates the right arrow shape
|
|
6
6
|
clipPath: 'polygon(14% 18%, 85% 18%, 97% 51%, 85% 85%, 14% 85%)',
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { Button } from '../..';
|
|
2
3
|
import { detectErrorType } from '../utils/errorDetection';
|
|
3
4
|
/**
|
|
4
5
|
* Common password validation for authentication forms
|
|
@@ -12,7 +13,7 @@ export const passwordValidation = {
|
|
|
12
13
|
/**
|
|
13
14
|
* Renders a back to login button
|
|
14
15
|
*/
|
|
15
|
-
export const BackToLoginButton = ({ onBackToLogin, label }) => (_jsx("div", { className: "flex items-center justify-center mt-4", children: _jsx(
|
|
16
|
+
export const BackToLoginButton = ({ onBackToLogin, label }) => (_jsx("div", { className: "flex items-center justify-center mt-4", children: _jsx(Button, { type: "button", variant: "link", onClick: onBackToLogin, className: "text-right text-sm text-primary hover:underline", children: label }) }));
|
|
16
17
|
/**
|
|
17
18
|
* Creates a standardized form submission handler
|
|
18
19
|
* @param config Form submission configuration
|
|
@@ -7,11 +7,11 @@ export function AuthPageLayout({ title, subtitle, errorMessage, showLogo = true,
|
|
|
7
7
|
width: 280,
|
|
8
8
|
height: 250,
|
|
9
9
|
className: 'mb-[2.5em]',
|
|
10
|
-
}, renderInAppLayout = false, className = '', horizontal = true, children, appLabel, sideContent, sideContentClass = 'bg-gradient-to-br from-primary-600 to-primary-800'
|
|
10
|
+
}, renderInAppLayout = false, className = '', horizontal = true, children, appLabel, sideContent, sideContentClass = 'bg-gradient-to-br from-primary-600 to-primary-800' /* TODO: migrate gradient */, footer, }) {
|
|
11
11
|
// Split-screen layout for when sideContent is provided
|
|
12
12
|
if (sideContent) {
|
|
13
|
-
return (_jsxs("div", { className: `flex h-screen overflow-hidden bg-
|
|
13
|
+
return (_jsxs("div", { className: `flex h-screen overflow-hidden bg-background ${className}`, children: [_jsx("div", { className: "flex flex-1 flex-col px-4 py-8 sm:px-6 lg:w-1/2 lg:flex-none lg:px-16 xl:px-24 bg-background overflow-y-auto", children: _jsxs("div", { className: "flex flex-col justify-center mx-auto w-full max-w-sm lg:w-[420px] my-auto", children: [_jsxs("div", { className: "flex flex-col items-center text-center", children: [showLogo && logo && (_jsxs("div", { className: "flex flex-col items-center mb-8", children: [_jsx("img", { src: logo.src, alt: logo.alt, width: 180, height: 160, className: `mb-4${logo.darkSrc ? ' dark:hidden' : ''}` }), logo.darkSrc && (_jsx("img", { src: logo.darkSrc, alt: logo.alt, width: 180, height: 160, className: "mb-4 hidden dark:block" })), appLabel && _jsx(AppBanner, { text: appLabel })] })), _jsx("h2", { "data-testid": "auth-page-title", className: "text-2xl font-bold tracking-tight text-neutral-900 sm:text-3xl", children: title }), _jsx("p", { "data-testid": "auth-page-subtitle", className: "mt-2 text-sm text-neutral-600 dark:text-neutral-400", children: subtitle })] }), errorMessage && (_jsx("div", { "data-testid": "login-error-alert", className: "mt-6 rounded-md bg-red-50 p-4 text-sm text-red-700", children: errorMessage })), _jsx("div", { className: "mt-8", children: children }), footer && _jsx("div", { className: "mt-8", children: footer })] }) }), _jsx("div", { className: `relative hidden w-0 flex-1 lg:block lg:w-1/2 overflow-hidden ${sideContentClass}`, children: sideContent })] }));
|
|
14
14
|
}
|
|
15
15
|
// Original Centered Card Layout
|
|
16
|
-
return (_jsxs("div", { className: `-my-4 mx-auto flex w-full max-w-[640px] flex-col items-center justify-center px-4 py-8 sm:px-6 ${renderInAppLayout ? 'h-[calc(100vh-64px)]' : 'min-h-screen md:h-screen'} ${className}`, children: [showLogo && logo && (_jsxs("div", { className: "flex flex-col items-center mb-5", children: [_jsx("img", { src: logo.src, alt: logo.alt, width: logo.width, height: logo.height }), _jsx(AppBanner, { text: appLabel })] })), _jsxs(AuthCard, { className: "p-2 sm:p-3", horizontal: horizontal, children: [_jsxs("div", { children: [_jsx("h2", { "data-testid": "auth-page-title", className: "text-[1.5em] font-bold text-
|
|
16
|
+
return (_jsxs("div", { className: `-my-4 mx-auto flex w-full max-w-[640px] flex-col items-center justify-center px-4 py-8 sm:px-6 ${renderInAppLayout ? 'h-[calc(100vh-64px)]' : 'min-h-screen md:h-screen'} ${className}`, children: [showLogo && logo && (_jsxs("div", { className: "flex flex-col items-center mb-5", children: [_jsx("img", { src: logo.src, alt: logo.alt, width: logo.width, height: logo.height, className: logo.darkSrc ? 'dark:hidden' : undefined }), logo.darkSrc && (_jsx("img", { src: logo.darkSrc, alt: logo.alt, width: logo.width, height: logo.height, className: "hidden dark:block" })), _jsx(AppBanner, { text: appLabel })] })), _jsxs(AuthCard, { className: "p-2 sm:p-3", horizontal: horizontal, children: [_jsxs("div", { children: [_jsx("h2", { "data-testid": "auth-page-title", className: "text-[1.5em] font-bold text-foreground sm:text-[1.875em]", children: title }), _jsx("h2", { "data-testid": "auth-page-subtitle", className: "text-[1em] font-medium text-muted-foreground sm:text-[1em]", children: subtitle })] }), errorMessage && (_jsx("div", { "data-testid": "login-error-alert", className: "mt-4 rounded border border-red-400 bg-red-100 p-2 text-red-700", children: errorMessage })), children] })] }));
|
|
17
17
|
}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
2
|
import { useRef, useState } from 'react';
|
|
3
|
+
import { Button } from '../..';
|
|
3
4
|
import { useToast } from '../../context';
|
|
4
5
|
import { FormEngine } from '../../form-engine';
|
|
5
6
|
import { createFormSubmissionHandler, passwordValidation } from './AuthFormUtils';
|
|
@@ -54,6 +55,6 @@ const ChangePasswordPage = ({ backHome = 'Back Home', submitButtonText = 'Change
|
|
|
54
55
|
confirmationPassword,
|
|
55
56
|
});
|
|
56
57
|
}, 'Password changed successfully', 'Failed to change password. Please try again.');
|
|
57
|
-
return (_jsx(AuthPageLayout, { title: "Change Password", subtitle: "Ready for a new password? Enter your current password, then create a new one to update it!", errorMessage: error, showLogo: false, renderInAppLayout: true, horizontal: false, children: _jsxs("div", { className: "mt-8", children: [_jsx(FormEngine, { fields: changePasswordFields, onSubmit: handleSubmit, layout: "vertical", className: "mb-0 p-0", submitButtonClass: "w-full", submitButtonText: isLoading ? 'Updating...' : submitButtonText, onCancel: () => { }, showCancelButton: false, showSubmittingText: false, formRef: formRef }), showBackHomeButton && (_jsx("div", { className: "flex items-center justify-center mt-4", children: _jsx(
|
|
58
|
+
return (_jsx(AuthPageLayout, { title: "Change Password", subtitle: "Ready for a new password? Enter your current password, then create a new one to update it!", errorMessage: error, showLogo: false, renderInAppLayout: true, horizontal: false, children: _jsxs("div", { className: "mt-8", children: [_jsx(FormEngine, { fields: changePasswordFields, onSubmit: handleSubmit, layout: "vertical", className: "mb-0 p-0", submitButtonClass: "w-full", submitButtonText: isLoading ? 'Updating...' : submitButtonText, onCancel: () => { }, showCancelButton: false, showSubmittingText: false, formRef: formRef }), showBackHomeButton && (_jsx("div", { className: "flex items-center justify-center mt-4", children: _jsx(Button, { type: "button", variant: "ghost", onClick: onClickBackHome, className: "text-sm text-primary hover:underline dark:text-primary", children: backHome }) }))] }) }));
|
|
58
59
|
};
|
|
59
60
|
export default ChangePasswordPage;
|
|
@@ -22,6 +22,7 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
|
22
22
|
* ```
|
|
23
23
|
*/
|
|
24
24
|
import { useRef, useState } from 'react';
|
|
25
|
+
import { Button } from '../..';
|
|
25
26
|
import { useToast } from '../../context';
|
|
26
27
|
import { FormEngine } from '../../form-engine';
|
|
27
28
|
import { useAuth } from '../context';
|
|
@@ -136,6 +137,6 @@ export function PagamioCustomerRegistrationPage({ logo, text = customerRegistrat
|
|
|
136
137
|
// Use the transformed data directly when custom mapper is provided
|
|
137
138
|
return authService.register(registrationData);
|
|
138
139
|
}, 'Registration successful', 'Registration failed. Please try again.');
|
|
139
|
-
return (_jsx(AuthPageLayout, { title: text.registerTitle, subtitle: text.registerSubtitle, errorMessage: error?.message, logo: logo, appLabel: appLabel, className: className, horizontal: false, sideContent: features && features.length > 0 ? _jsx(FeatureCarousel, { features: features }) : undefined, sideContentClass: sideContentClass, footer: footer, children: _jsxs("div", { className: "mt-8", children: [_jsx(FormEngine, { fields: customRegistrationFields ?? registrationFields, onSubmit: handleSubmit, layout: "vertical", className: "mb-0 px-0", submitButtonClass: "w-full", submitButtonText: isLoading ? text.loadingButtonLabel : text.registerButtonLabel, onCancel: () => { }, showCancelButton: false, showSubmittingText: false, formRef: formRef }), onBackToLogin && (_jsxs("div", { className: "mt-6 text-center text-sm", children: [_jsx("span", { className: "text-
|
|
140
|
+
return (_jsx(AuthPageLayout, { title: text.registerTitle, subtitle: text.registerSubtitle, errorMessage: error?.message, logo: logo, appLabel: appLabel, className: className, horizontal: false, sideContent: features && features.length > 0 ? _jsx(FeatureCarousel, { features: features }) : undefined, sideContentClass: sideContentClass, footer: footer, children: _jsxs("div", { className: "mt-8", children: [_jsx(FormEngine, { fields: customRegistrationFields ?? registrationFields, onSubmit: handleSubmit, layout: "vertical", className: "mb-0 px-0", submitButtonClass: "w-full", submitButtonText: isLoading ? text.loadingButtonLabel : text.registerButtonLabel, onCancel: () => { }, showCancelButton: false, showSubmittingText: false, formRef: formRef }), onBackToLogin && (_jsxs("div", { className: "mt-6 text-center text-sm", children: [_jsx("span", { className: "text-muted-foreground", children: "Already have an account? " }), _jsx(Button, { type: "button", variant: "link", onClick: onBackToLogin, className: "font-medium text-primary hover:underline", children: text.backToLoginLabel })] }))] }) }));
|
|
140
141
|
}
|
|
141
142
|
export default PagamioCustomerRegistrationPage;
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
2
|
import { useEffect, useState } from 'react';
|
|
3
|
+
import { Button } from '../..';
|
|
3
4
|
import { cn } from '../../helpers';
|
|
4
5
|
export function FeatureCarousel({ features, className, interval = 5000 }) {
|
|
5
6
|
const [activeIndex, setActiveIndex] = useState(0);
|
|
@@ -13,5 +14,5 @@ export function FeatureCarousel({ features, className, interval = 5000 }) {
|
|
|
13
14
|
return null;
|
|
14
15
|
return (_jsx("div", { className: cn('relative h-full flex flex-col justify-center items-center px-12 text-white text-center overflow-hidden', className), children: _jsxs("div", { className: "relative z-10 w-full max-w-md mx-auto", children: [features.map((feature, index) => (_jsxs("div", { className: cn('transition-all duration-700 ease-in-out absolute top-0 left-0 w-full transform flex flex-col items-center', index === activeIndex
|
|
15
16
|
? 'opacity-100 translate-y-0 relative'
|
|
16
|
-
: 'opacity-0 translate-y-8 absolute pointer-events-none'), "aria-hidden": index !== activeIndex, children: [feature.icon && (_jsx("div", { className: "mb-8 flex h-24 w-24 items-center justify-center rounded-2xl bg-white/10 backdrop-blur-md shadow-xl border border-white/20", children: feature.icon })), _jsx("h2", { className: "mb-4 text-3xl font-bold tracking-tight", children: feature.title }), _jsx("p", { className: "text-lg text-primary-
|
|
17
|
+
: 'opacity-0 translate-y-8 absolute pointer-events-none'), "aria-hidden": index !== activeIndex, children: [feature.icon && (_jsx("div", { className: "mb-8 flex h-24 w-24 items-center justify-center rounded-2xl bg-white/10 backdrop-blur-md shadow-xl border border-white/20", children: feature.icon })), _jsx("h2", { className: "mb-4 text-3xl font-bold tracking-tight", children: feature.title }), _jsx("p", { className: "text-lg text-primary-foreground/80 leading-relaxed font-light opacity-90", children: feature.description })] }, index))), _jsx("div", { className: "mt-16 flex gap-3 justify-center", children: features.map((_, index) => (_jsx(Button, { type: "button", size: "icon", variant: "ghost", onClick: () => setActiveIndex(index), className: cn('h-2 rounded-full transition-all duration-300', index === activeIndex ? 'w-8 bg-background' : 'w-2 bg-white/40 hover:bg-white/60'), "aria-label": `Go to slide ${index + 1}` }, index))) })] }) }));
|
|
17
18
|
}
|
|
@@ -22,6 +22,7 @@ import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-run
|
|
|
22
22
|
* ```
|
|
23
23
|
*/
|
|
24
24
|
import { useRef, useState } from 'react';
|
|
25
|
+
import { Button } from '../..';
|
|
25
26
|
import { useToast } from '../../context';
|
|
26
27
|
import { FormEngine } from '../../form-engine';
|
|
27
28
|
import { AuthenticatorFactory } from '../authenticators';
|
|
@@ -139,6 +140,6 @@ export function PagamioLoginPage({ logo, text = loginPageDefaultText, appLabel,
|
|
|
139
140
|
...(loginFieldType === 'email' ? { email: '' } : { username: '' }),
|
|
140
141
|
password: '',
|
|
141
142
|
rememberMe: false,
|
|
142
|
-
} }), _jsxs("div", { className: "flex items-center justify-center gap-x-4 mt-4", children: [onForgotPassword && (_jsx(
|
|
143
|
+
} }), _jsxs("div", { className: "flex items-center justify-center gap-x-4 mt-4", children: [onForgotPassword && (_jsx(Button, { type: "button", variant: "link", onClick: onForgotPassword, className: "text-sm text-primary hover:underline", children: text.forgotPasswordLabel })), hasCreateAccount && (_jsxs(_Fragment, { children: [onForgotPassword && _jsx("span", { className: "text-muted-foreground", children: "|" }), _jsx(Button, { type: "button", variant: "link", onClick: handleCreateAccount, className: "text-sm text-primary hover:underline", children: text.createAccountLabel })] }))] })] }) }));
|
|
143
144
|
}
|
|
144
145
|
export default PagamioLoginPage;
|
|
@@ -68,7 +68,7 @@ export const OtpInput = ({ length = 6, value, onChange, disabled = false, inputC
|
|
|
68
68
|
const focusIndex = Math.min(pastedData.length, length - 1);
|
|
69
69
|
inputRefs.current[focusIndex]?.focus();
|
|
70
70
|
};
|
|
71
|
-
const defaultInputClassName = 'h-12 w-12 rounded-lg border border-
|
|
71
|
+
const defaultInputClassName = 'h-12 w-12 rounded-lg border border-input text-center text-lg font-semibold focus:border-ring focus:outline-none focus:ring-2 focus:ring-ring/20 disabled:bg-muted disabled:text-muted-foreground';
|
|
72
72
|
return (_jsx("div", { className: "flex justify-center gap-2", children: Array.from({ length }).map((_, index) => (_jsx("input", { ref: (el) => {
|
|
73
73
|
inputRefs.current[index] = el;
|
|
74
74
|
}, type: "text", inputMode: "numeric", maxLength: 1, value: value[index] || '', onChange: (e) => handleChange(index, e.target.value), onKeyDown: (e) => handleKeyDown(index, e), onPaste: handlePaste, disabled: disabled, className: inputClassName ?? defaultInputClassName, autoComplete: "one-time-code", "aria-label": `Digit ${index + 1} of ${length}` }, `otp-input-${index}`))) }));
|
|
@@ -135,9 +135,9 @@ export const OtpVerificationPage = ({ email, onVerifySuccess, onBack, handlers,
|
|
|
135
135
|
setIsResending(false);
|
|
136
136
|
}
|
|
137
137
|
};
|
|
138
|
-
return (_jsx("div", { className: `flex min-h-screen items-center justify-center bg-
|
|
138
|
+
return (_jsx("div", { className: `flex min-h-screen items-center justify-center bg-muted px-4 py-12 ${classNames.container ?? ''}`, children: _jsxs("div", { className: "w-full max-w-md", children: [logo && (_jsxs("div", { className: "mb-8 flex justify-center", children: [_jsx("img", { src: logo.src, alt: logo.alt, width: logo.width, height: logo.height, className: `h-auto max-h-16${logo.darkSrc ? ' dark:hidden' : ''}` }), logo.darkSrc && (_jsx("img", { src: logo.darkSrc, alt: logo.alt, width: logo.width, height: logo.height, className: "h-auto max-h-16 hidden dark:block" }))] })), _jsxs("div", { className: `rounded-2xl border border-border bg-background p-8 shadow-sm ${classNames.card ?? ''}`, children: [_jsxs("div", { className: `mb-6 text-center ${classNames.header ?? ''}`, children: [_jsx("div", { className: `mx-auto mb-4 flex h-16 w-16 items-center justify-center rounded-full bg-primary/15 ${classNames.icon ?? ''}`, children: _jsx(HiOutlineMail, { className: "h-8 w-8 text-primary" }) }), _jsx("h1", { className: "text-2xl font-bold text-foreground", children: text.title }), _jsx("p", { className: "mt-2 text-sm text-muted-foreground", children: text.subtitle }), _jsx("p", { className: "mt-1 font-medium text-foreground", children: email })] }), error && _jsx("div", { className: "mb-4 rounded-lg bg-red-50 p-4 text-sm text-red-600", children: error }), _jsxs("div", { className: "mb-6", children: [_jsx("p", { className: "mb-2 block text-sm font-medium text-foreground", children: text.codeLabel }), _jsx(OtpInput, { length: otpLength, value: otpValue, onChange: (value) => {
|
|
139
139
|
setOtpValue(value);
|
|
140
140
|
clearError();
|
|
141
|
-
}, disabled: isVerifying })] }), _jsx(Button, { onClick: handleVerify, disabled: otpValue.length !== otpLength || isVerifying, className: "w-full", size: "lg", children: isVerifying ? (_jsxs(_Fragment, { children: [_jsx(Loader, { size: "sm", className: "mr-2" }), text.verifyingButton] })) : (text.verifyButton) }), _jsx("div", { className: "mt-6 text-center", children: canResend ? (_jsx("button",
|
|
141
|
+
}, disabled: isVerifying })] }), _jsx(Button, { onClick: handleVerify, disabled: otpValue.length !== otpLength || isVerifying, className: "w-full", size: "lg", children: isVerifying ? (_jsxs(_Fragment, { children: [_jsx(Loader, { size: "sm", className: "mr-2" }), text.verifyingButton] })) : (text.verifyButton) }), _jsx("div", { className: "mt-6 text-center", children: canResend ? (_jsx(Button, { type: "button", variant: "ghost", onClick: handleResend, disabled: isResending, className: "text-sm font-medium text-primary hover:text-primary/90 disabled:text-muted-foreground", children: isResending ? text.resendingButton : text.resendButton })) : (_jsxs("p", { className: "text-sm text-muted-foreground", children: [text.resendCountdownText, " ", _jsxs("span", { className: "font-medium text-foreground", children: [countdown, "s"] })] })) }), _jsx("div", { className: "mt-6 border-t border-border pt-6", children: _jsxs(Button, { type: "button", variant: "ghost", onClick: onBack, className: "flex w-full items-center justify-center gap-2 text-sm text-foreground/70 hover:text-foreground", children: [_jsx(HiOutlineArrowLeft, { className: "h-4 w-4" }), text.backButton] }) })] })] }) }));
|
|
142
142
|
};
|
|
143
143
|
export default OtpVerificationPage;
|
|
@@ -10,6 +10,6 @@ const AuthPageLayout = ({ title, subtitle, errorMessage, showLogo = true, render
|
|
|
10
10
|
on: 'hidden w-2/3 rounded-l-lg md:w-96 md:p-0 lg:block',
|
|
11
11
|
},
|
|
12
12
|
},
|
|
13
|
-
}, children: [_jsxs("div", { className: "space-y-2", children: [_jsx("h2", { className: "text-[1.5em] sm:text-[1.875em] font-bold text-
|
|
13
|
+
}, children: [_jsxs("div", { className: "space-y-2", children: [_jsx("h2", { className: "text-[1.5em] sm:text-[1.875em] font-bold text-foreground", children: title }), _jsx("p", { className: "text-[1em] font-medium text-muted-foreground", children: subtitle })] }), errorMessage && (_jsx("div", { className: "mt-4 rounded border border-red-400 bg-red-100 p-2 text-red-700", children: errorMessage })), children] })] }));
|
|
14
14
|
};
|
|
15
15
|
export default AuthPageLayout;
|
|
@@ -124,7 +124,7 @@ className = '', loading = false, }) => {
|
|
|
124
124
|
return (_jsx("div", { className: `animate-pulse ${className}`, children: _jsx("div", { className: "w-full aspect-[16/9] bg-gray-200 rounded-lg" }) }));
|
|
125
125
|
}
|
|
126
126
|
if (!data?.length) {
|
|
127
|
-
return (_jsx("div", { className: `flex items-center justify-center w-full aspect-[16/9] bg-
|
|
127
|
+
return (_jsx("div", { className: `flex items-center justify-center w-full aspect-[16/9] bg-muted rounded-lg ${className}`, children: _jsx("p", { className: "text-muted-foreground", children: "No data available" }) }));
|
|
128
128
|
}
|
|
129
129
|
return (_jsx("div", { className: `relative ${className}`, children: _jsx(ReactECharts, { option: chartOptions, style: { height: '100%' }, className: "w-full aspect-[16/9] sm:aspect-[16/9]", opts: { renderer: 'canvas' }, notMerge: true }) }));
|
|
130
130
|
};
|
|
@@ -10,6 +10,6 @@ const AuthPageLayout = ({ title, subtitle, errorMessage, logo, showLogo = true,
|
|
|
10
10
|
on: 'hidden w-2/3 rounded-l-lg md:w-96 md:p-0 lg:block',
|
|
11
11
|
},
|
|
12
12
|
},
|
|
13
|
-
}, children: [_jsxs("div", { children: [_jsx("h2", { className: "text-[1.5em] font-bold text-
|
|
13
|
+
}, children: [_jsxs("div", { children: [_jsx("h2", { className: "text-[1.5em] font-bold text-foreground sm:text-[1.875em]", children: title }), _jsx("h2", { className: "text-[1em] font-medium text-muted-foreground sm:text-[1em]", children: subtitle })] }), errorMessage && (_jsx("div", { className: "mt-4 rounded border border-red-400 bg-red-100 p-2 text-red-700", children: errorMessage })), children] })] }));
|
|
14
14
|
};
|
|
15
15
|
export default AuthPageLayout;
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
-
import { Breadcrumb } from 'flowbite-react';
|
|
2
|
+
import { Breadcrumb, BreadcrumbItem } from 'flowbite-react';
|
|
3
3
|
import { useAppBreadcrumbs } from '../../context';
|
|
4
4
|
import { useTranslation } from '../../translations';
|
|
5
5
|
const AppBreadcrumbNav = () => {
|
|
6
6
|
const { breadcrumbs, pathname, rootPageIcon: PageIcon } = useAppBreadcrumbs();
|
|
7
7
|
const { t } = useTranslation();
|
|
8
|
-
return (_jsx(Breadcrumb, { className: "mb-5", children: breadcrumbs.map((item, index) => (_jsx(
|
|
8
|
+
return (_jsx(Breadcrumb, { className: "mb-5", children: breadcrumbs.map((item, index) => (_jsx(BreadcrumbItem, { href: index === breadcrumbs.length - 1 || !item.path ? undefined : item.path, children: _jsxs("div", { className: "flex items-center gap-x-3 text-2xl", children: [index === 0 && PageIcon && _jsx(PageIcon, {}), _jsx("span", { className: "text-sm", children: t(item.label) })] }) }, `breadcrumb-item-${item.path || item.key || index}-${item.label}`))) }, pathname));
|
|
9
9
|
};
|
|
10
10
|
export default AppBreadcrumbNav;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
2
|
-
import { Avatar, DarkThemeToggle, Dropdown, Navbar, Tooltip } from 'flowbite-react';
|
|
2
|
+
import { Avatar, DarkThemeToggle, Dropdown, DropdownDivider, DropdownHeader, DropdownItem, Navbar, NavbarBrand, Tooltip, } from 'flowbite-react';
|
|
3
3
|
import { HiLockClosed, HiLogout, HiMenuAlt1, HiUser, HiX } from 'react-icons/hi';
|
|
4
4
|
import { v4 as uuidv4 } from 'uuid';
|
|
5
5
|
import React, { useCallback } from 'react';
|
|
@@ -7,13 +7,14 @@ import { useAuth } from '../../auth';
|
|
|
7
7
|
import { useAppSidebarContext } from '../../context';
|
|
8
8
|
import { useMediaQueries } from '../../shared';
|
|
9
9
|
import { LocaleSwitcher, useLibTranslations, useTranslation } from '../../translations';
|
|
10
|
+
import Button from '../ui/Button';
|
|
10
11
|
const AppSidebarToggleButton = React.memo(({ isMobileOpen, onToggle }) => {
|
|
11
12
|
const { tLib } = useLibTranslations();
|
|
12
|
-
return (_jsxs("button",
|
|
13
|
+
return (_jsxs(Button, { type: "button", variant: "ghost", onClick: onToggle, className: "mr-3 cursor-pointer rounded p-2 text-foreground/70 hover:bg-accent hover:text-foreground", children: [_jsx("span", { className: "sr-only", children: tLib('sidebar.toggle', 'Toggle sidebar') }), _jsx("div", { className: "md:hidden", children: isMobileOpen ? _jsx(HiX, { className: "h-6 w-6" }) : _jsx(HiMenuAlt1, { className: "h-6 w-6" }) }), _jsx("div", { className: "hidden md:block", children: _jsx(HiMenuAlt1, { className: "h-6 w-6" }) })] }));
|
|
13
14
|
});
|
|
14
15
|
const AppDarkThemeToggleWithTooltip = React.memo(() => {
|
|
15
16
|
const { tLib } = useLibTranslations();
|
|
16
|
-
return (_jsxs(_Fragment, { children: [_jsx("div", { className: "hidden dark:block", children: _jsx(Tooltip, { content: tLib('theme.toggleLight', 'Toggle light mode'), children: _jsx(DarkThemeToggle, {}) }) }), _jsx("div", { className: "dark:hidden", children: _jsx(Tooltip, { content: tLib('theme.toggleDark', 'Toggle dark mode'), children: _jsx(DarkThemeToggle, {}) }) })] }));
|
|
17
|
+
return (_jsxs(_Fragment, { children: [_jsx("div", { className: "hidden dark:block", children: _jsx(Tooltip, { content: tLib('theme.toggleLight', 'Toggle light mode'), children: _jsx(DarkThemeToggle, {}) }) }), _jsx("div", { className: "hidden dark:hidden", children: _jsx(Tooltip, { content: tLib('theme.toggleDark', 'Toggle dark mode'), children: _jsx(DarkThemeToggle, {}) }) })] }));
|
|
17
18
|
});
|
|
18
19
|
const AppUserDropdown = React.memo(({ onLogout, onSelectChangePassword, onSelectProfile, navbarTextColors = { general: 'text-white' }, }) => {
|
|
19
20
|
const { user, logout } = useAuth();
|
|
@@ -28,7 +29,7 @@ const AppUserDropdown = React.memo(({ onLogout, onSelectChangePassword, onSelect
|
|
|
28
29
|
await logout();
|
|
29
30
|
onLogout?.();
|
|
30
31
|
}, [logout, onLogout]);
|
|
31
|
-
return (_jsxs(Dropdown, { className: "rounded", arrowIcon: false, inline: true, label: _jsxs("span", { className: navbarTextColors.general, children: [_jsx("span", { className: "sr-only", children: user?.userName }), _jsx(Avatar, { rounded: true, size: "sm", placeholderInitials: initials })] }), children: [_jsx(
|
|
32
|
+
return (_jsxs(Dropdown, { className: "rounded", arrowIcon: false, inline: true, label: _jsxs("span", { className: navbarTextColors.general, children: [_jsx("span", { className: "sr-only", children: user?.userName }), _jsx(Avatar, { rounded: true, size: "sm", placeholderInitials: initials })] }), children: [_jsx(DropdownHeader, { className: "px-4 py-3", children: _jsx("span", { className: "block text-sm font-medium capitalize text-primary", children: user?.userName }) }), _jsx(DropdownItem, { onClick: () => onSelectProfile(), children: _jsxs("div", { className: "flex items-center space-x-2", children: [_jsx(HiUser, { className: "text-foreground/70", size: 18 }), _jsx("span", { children: tLib('userProfile', 'User Profile') })] }) }), _jsx(DropdownItem, { onClick: () => onSelectChangePassword?.(), children: _jsxs("div", { className: "flex items-center space-x-2", children: [_jsx(HiLockClosed, { className: "text-foreground/70", size: 18 }), _jsx("span", { children: tLib('changePassword', 'Change Password') })] }) }), _jsx(DropdownDivider, {}), _jsx(DropdownItem, { onClick: handleLogout, children: _jsxs("div", { className: "flex items-center space-x-2", children: [_jsx(HiLogout, { className: "text-foreground/70", size: 18 }), _jsx("span", { children: tLib('signOut', 'Sign Out') })] }) })] }));
|
|
32
33
|
});
|
|
33
34
|
const EnvironmentBanner = ({ show = false, text, bgColor = 'red', color = 'black', }) => {
|
|
34
35
|
if (!show)
|
|
@@ -47,7 +48,7 @@ const EnvironmentBanner = ({ show = false, text, bgColor = 'red', color = 'black
|
|
|
47
48
|
letterSpacing: '0.1em',
|
|
48
49
|
}, children: text }) }) }));
|
|
49
50
|
};
|
|
50
|
-
const AppDashboardNavbar = ({ dashboardLink = '/dashboard', brandImage, linkComponent, showThemeToggler = true, appLabel, onSelectChangePassword, onSelectProfile, onLogout, hideSidebarToggle = false, navBarActionComponents = [], showLocaleSwitcher = false, localeNames, environmentBanner = { show: false, text: '' }, navbarBackground = { light: 'bg-purple', dark: '
|
|
51
|
+
const AppDashboardNavbar = ({ dashboardLink = '/dashboard', brandImage, linkComponent, showThemeToggler = true, appLabel, onSelectChangePassword, onSelectProfile, onLogout, hideSidebarToggle = false, navBarActionComponents = [], showLocaleSwitcher = false, localeNames, environmentBanner = { show: false, text: '' }, navbarBackground = { light: 'bg-purple', dark: '' }, navbarTextColors = { brand: 'text-white', general: 'text-white' }, }) => {
|
|
51
52
|
const sidebar = useAppSidebarContext();
|
|
52
53
|
const { isMd } = useMediaQueries();
|
|
53
54
|
const { t } = useTranslation();
|
|
@@ -59,8 +60,8 @@ const AppDashboardNavbar = ({ dashboardLink = '/dashboard', brandImage, linkComp
|
|
|
59
60
|
sidebar.mobile.toggle();
|
|
60
61
|
}
|
|
61
62
|
}, [isMd, sidebar.desktop, sidebar.mobile]);
|
|
62
|
-
const navbarClasses = `fixed top-0 w-full border-b border-
|
|
63
|
-
return (_jsxs(_Fragment, { children: [_jsx(Navbar, { fluid: true, className: navbarClasses, style: { zIndex: 100 }, children: _jsx("div", { className: "w-full p-3 pr-4", children: _jsxs("div", { className: "flex items-center justify-between", children: [_jsxs("div", { className: "flex items-center", children: [!hideSidebarToggle && (_jsx(AppSidebarToggleButton, { isMobileOpen: sidebar.mobile.isOpen, onToggle: handleToggleSidebar })), _jsxs(
|
|
63
|
+
const navbarClasses = `fixed top-0 w-full border-b border-border ${navbarBackground.light} p-0 ${navbarBackground.dark} sm:p-0`;
|
|
64
|
+
return (_jsxs(_Fragment, { children: [_jsx(Navbar, { fluid: true, className: navbarClasses, style: { zIndex: 100 }, children: _jsx("div", { className: "w-full p-3 pr-4", children: _jsxs("div", { className: "flex items-center justify-between", children: [_jsxs("div", { className: "flex items-center", children: [!hideSidebarToggle && (_jsx(AppSidebarToggleButton, { isMobileOpen: sidebar.mobile.isOpen, onToggle: handleToggleSidebar })), _jsxs(NavbarBrand, { as: linkComponent, href: dashboardLink, className: "mr-14", children: [brandImage && (_jsx("img", { src: brandImage.src, alt: t(brandImage.alt), width: brandImage.width, height: brandImage.height, className: "h-8" })), _jsx("p", { className: `font-bold ${navbarTextColors.brand} text-[15px] mb-0`, children: t(appLabel) })] })] }), _jsxs("div", { className: "flex items-center lg:gap-3", children: [navBarActionComponents.map((action) => (_jsx(React.Fragment, { children: action }, `app-nav-bar-component-${uuidv4()}`))), showThemeToggler && _jsx(AppDarkThemeToggleWithTooltip, {}), showLocaleSwitcher && (_jsx("div", { className: `mx-2 ${navbarTextColors.general}`, children: _jsx(LocaleSwitcher, { localeNames: localeNames, className: "min-w-[120px] text-sm text-white bg-background z-50" }) })), _jsx("div", { className: "flex items-center", children: _jsx(AppUserDropdown, { onLogout: onLogout, onSelectChangePassword: onSelectChangePassword, onSelectProfile: onSelectProfile, navbarTextColors: navbarTextColors }) })] })] }) }) }), _jsx(EnvironmentBanner, { ...environmentBanner })] }));
|
|
64
65
|
};
|
|
65
66
|
export default AppDashboardNavbar;
|
|
66
67
|
export { AppSidebarToggleButton, AppDarkThemeToggleWithTooltip, AppUserDropdown, AppDashboardNavbar };
|
|
@@ -2,6 +2,6 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
|
2
2
|
import { useTranslation } from '../../translations';
|
|
3
3
|
const AppPageHeader = ({ title, description }) => {
|
|
4
4
|
const { t } = useTranslation();
|
|
5
|
-
return (_jsxs("div", { className: "mb-4", children: [_jsx("h1", { className: "text-2xl font-bold", children: t(title) }), description && _jsx("p", { className: "text-1xl text-
|
|
5
|
+
return (_jsxs("div", { className: "mb-4", children: [_jsx("h1", { className: "text-2xl font-bold", children: t(title) }), description && _jsx("p", { className: "text-1xl text-muted-foreground", children: t(description) })] }));
|
|
6
6
|
};
|
|
7
7
|
export default AppPageHeader;
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
-
import { Modal } from 'flowbite-react';
|
|
2
|
+
import { Modal, ModalBody, ModalFooter, ModalHeader } from 'flowbite-react';
|
|
3
3
|
import { useLibTranslations } from '../../translations';
|
|
4
4
|
import { Button } from '../ui';
|
|
5
5
|
const SessionExpiryModal = ({ show, countdown, loading, onDismiss, onRenew }) => {
|
|
6
6
|
const { tLib } = useLibTranslations();
|
|
7
|
-
return (_jsxs(Modal, { show: show, onClose: onDismiss, children: [_jsx(
|
|
7
|
+
return (_jsxs(Modal, { show: show, onClose: onDismiss, children: [_jsx(ModalHeader, { children: tLib('sessionExpiryModal.title', 'Session about to expire due to inactivity') }), _jsx(ModalBody, { children: _jsx("div", { className: "space-y-6 p-6", children: _jsx("p", { className: "text-base leading-relaxed text-muted-foreground", children: tLib('sessionExpiryModal.message', `Your session will end in ${countdown} seconds and you will be automatically logged out.`) }) }) }), _jsx(ModalFooter, { children: _jsxs("div", { className: "flex w-full justify-end space-x-2", children: [_jsx(Button, { onClick: onDismiss, variant: "outline", disabled: loading, children: tLib('sessionExpiryModal.dismiss', 'Log Out') }), _jsx(Button, { onClick: onRenew, variant: "primary", disabled: loading, children: tLib('sessionExpiryModal.renew', 'Stay logged in') })] }) })] }));
|
|
8
8
|
};
|
|
9
9
|
export default SessionExpiryModal;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
2
|
-
import { Sidebar } from 'flowbite-react';
|
|
2
|
+
import { Sidebar, SidebarCollapse, SidebarItem, SidebarItemGroup, SidebarItems } from 'flowbite-react';
|
|
3
3
|
import { twMerge } from 'tailwind-merge';
|
|
4
4
|
import React, { useEffect, useState } from 'react';
|
|
5
5
|
import { useAppSidebarContext } from '../../context';
|
|
@@ -10,14 +10,14 @@ const AppSidebarMenu = () => {
|
|
|
10
10
|
const getItemKey = (item, index) => item.key || item.href || `${item.label}-${index}`;
|
|
11
11
|
// If groupByItem is true each item gets its own ItemGroup
|
|
12
12
|
if (groupByItem) {
|
|
13
|
-
return (_jsx(
|
|
13
|
+
return (_jsx(SidebarItems, { children: pages.map((item, index) => {
|
|
14
14
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
15
15
|
const { key, ...itemProps } = item;
|
|
16
|
-
return (_jsx(
|
|
16
|
+
return (_jsx(SidebarItemGroup, { children: _jsx(AppSidebarItem, { ...itemProps }) }, getItemKey(item, index)));
|
|
17
17
|
}) }));
|
|
18
18
|
}
|
|
19
19
|
// Default behavior all items in one ItemGroup
|
|
20
|
-
return (_jsx(
|
|
20
|
+
return (_jsx(SidebarItems, { children: _jsx(SidebarItemGroup, { children: pages.map((item, index) => {
|
|
21
21
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
22
22
|
const { key, ...itemProps } = item;
|
|
23
23
|
return _jsx(AppSidebarItem, { ...itemProps }, getItemKey(item, index));
|
|
@@ -32,7 +32,7 @@ const AppSidebarItem = ({ href, target, icon, label, items, badge, forceDropdown
|
|
|
32
32
|
if (desktop.isCollapsed) {
|
|
33
33
|
return null;
|
|
34
34
|
}
|
|
35
|
-
return (_jsxs("div", { className: "pt-3 first:pt-0", children: [_jsx("hr", { className: "mb-2 border-t border-
|
|
35
|
+
return (_jsxs("div", { className: "pt-3 first:pt-0", children: [_jsx("hr", { className: "mb-2 border-t border-border" }), _jsx("span", { className: "px-3 text-[10px] font-semibold uppercase tracking-wider text-foreground/70", children: t(label) })] }));
|
|
36
36
|
}
|
|
37
37
|
// Check if current path matches this item or any of its descendants
|
|
38
38
|
const isParentActive = href ? pathname === href || pathname.startsWith(`${href}/`) : false;
|
|
@@ -51,69 +51,59 @@ const AppSidebarItem = ({ href, target, icon, label, items, badge, forceDropdown
|
|
|
51
51
|
const singleItem = items[0];
|
|
52
52
|
if (!singleItem.href) {
|
|
53
53
|
// If single item has no href, render without link
|
|
54
|
-
return (_jsx(
|
|
54
|
+
return (_jsx(SidebarItem, { icon: icon, label: badge && t(badge), className: twMerge('text-foreground/70 cursor-default'), children: t(label) }));
|
|
55
55
|
}
|
|
56
|
-
return (_jsx(
|
|
57
|
-
'text-primary-700 bg-primary-100/80 hover:bg-primary-100/80 dark:text-primary-300 dark:bg-primary-900/40 dark:hover:bg-primary-900/40'), children: t(label) }));
|
|
56
|
+
return (_jsx(SidebarItem, { as: Link, href: singleItem.href, icon: icon, label: badge && t(badge), className: twMerge('text-foreground/70 hover:text-primary/80 hover:bg-primary/10', pathname === singleItem.href && 'text-primary bg-primary/15 hover:bg-primary/15'), children: t(label) }));
|
|
58
57
|
}
|
|
59
58
|
// Handle non-collapsible sections - render as section header with always-visible links
|
|
60
59
|
if (items?.length && collapsible === false) {
|
|
61
|
-
return (_jsxs("div", { className: "space-y-1", children: [showSeparator && _jsx("hr", { className: "my-3 border-t border-
|
|
60
|
+
return (_jsxs("div", { className: "space-y-1", children: [showSeparator && _jsx("hr", { className: "my-3 border-t border-border" }), _jsxs("div", { className: twMerge('flex items-center gap-3 px-3 py-2 text-sm font-semibold uppercase tracking-wider', 'text-muted-foreground'), children: [icon && React.createElement(icon, { className: 'h-5 w-5' }), _jsx("span", { children: t(label) })] }), _jsx("div", { className: "space-y-1 pl-2", children: items.map((child, childIndex) => {
|
|
62
61
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
63
62
|
const { key, ...childProps } = child;
|
|
64
63
|
return (_jsx(React.Fragment, { children: child.items?.length ? (
|
|
65
64
|
// Recursively render nested items
|
|
66
65
|
_jsx("div", { className: "pl-3", children: _jsx(AppSidebarItem, { ...childProps }) })) : child.href ? (
|
|
67
66
|
// Render leaf item with link
|
|
68
|
-
_jsx(
|
|
69
|
-
'text-primary-700 bg-primary-100/80 hover:bg-primary-100/80 dark:text-primary-300 dark:bg-primary-900/40 dark:hover:bg-primary-900/40'), children: t(child.label) })) : (
|
|
67
|
+
_jsx(SidebarItem, { as: Link, href: child.href, icon: child.icon, className: twMerge('justify-center [&>*]:font-normal', 'text-foreground/70 hover:text-primary/80 hover:bg-primary/10', pathname === child.href && 'text-primary bg-primary/15 hover:bg-primary/15'), children: t(child.label) })) : (
|
|
70
68
|
// Render leaf item without link
|
|
71
|
-
_jsx(
|
|
69
|
+
_jsx(SidebarItem, { icon: child.icon, className: twMerge('justify-center [&>*]:font-normal', 'text-foreground/70 cursor-default'), children: t(child.label) })) }, child.key || child.href || `${child.label}-${childIndex}`));
|
|
72
70
|
}) })] }));
|
|
73
71
|
}
|
|
74
72
|
if (items?.length) {
|
|
75
73
|
const isOpen = isParentActive || hasActiveChild(items);
|
|
76
|
-
return (_jsx(
|
|
74
|
+
return (_jsx(SidebarCollapse, { icon: icon, label: t(label), open: isOpen, className: twMerge('text-foreground/70 hover:text-primary/80 hover:bg-primary/10',
|
|
77
75
|
// Parent styling when its child is active
|
|
78
|
-
hasActiveChild(items) && 'text-primary
|
|
76
|
+
hasActiveChild(items) && 'text-primary',
|
|
79
77
|
// Parent styling when it's directly active
|
|
80
|
-
isParentActive &&
|
|
81
|
-
!hasActiveChild(items) &&
|
|
82
|
-
'text-primary-700 bg-primary-100/80 hover:bg-primary-100/80 dark:text-primary-300 dark:bg-primary-900/40 dark:hover:bg-primary-900/40'), theme: { list: 'space-y-2 py-2 [&>li>div]:w-full' }, children: items.map((child, childIndex) => {
|
|
78
|
+
isParentActive && !hasActiveChild(items) && 'text-primary bg-primary/15 hover:bg-primary/15'), theme: { list: 'space-y-2 py-2 [&>li>div]:w-full' }, children: items.map((child, childIndex) => {
|
|
83
79
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
84
80
|
const { key, ...childProps } = child;
|
|
85
81
|
return (_jsx(React.Fragment, { children: child.items?.length ? (
|
|
86
82
|
// Recursively render nested items
|
|
87
83
|
_jsx("div", { className: "pl-3", children: _jsx(AppSidebarItem, { ...childProps }) })) : child.href ? (
|
|
88
84
|
// Render leaf item with link
|
|
89
|
-
_jsx(
|
|
90
|
-
'text-primary-700 bg-primary-100/80 hover:bg-primary-100/80 dark:text-primary-300 dark:bg-primary-900/40 dark:hover:bg-primary-900/40'), children: t(child.label) })) : (
|
|
85
|
+
_jsx(SidebarItem, { as: Link, href: child.href, icon: child.icon, className: twMerge('justify-center [&>*]:font-normal', 'text-foreground/70 hover:text-primary/80 hover:bg-primary/10', pathname === child.href && 'text-primary bg-primary/15 hover:bg-primary/15'), children: t(child.label) })) : (
|
|
91
86
|
// Render leaf item without link
|
|
92
|
-
_jsx(
|
|
87
|
+
_jsx(SidebarItem, { icon: child.icon, className: twMerge('justify-center [&>*]:font-normal', 'text-foreground/70 cursor-default'), children: t(child.label) })) }, child.key || child.href || `${child.label}-${childIndex}`));
|
|
93
88
|
}) }));
|
|
94
89
|
}
|
|
95
90
|
// Render leaf item
|
|
96
91
|
// If no href, render as a non-link item
|
|
97
92
|
if (!href) {
|
|
98
|
-
return (_jsx(
|
|
93
|
+
return (_jsx(SidebarItem, { icon: icon, label: badge && t(badge), className: twMerge('text-foreground/70 hover:text-primary/80 hover:bg-primary/10', 'cursor-default'), children: t(label) }));
|
|
99
94
|
}
|
|
100
95
|
// Handle coming soon items - disabled with badge
|
|
101
96
|
if (comingSoon) {
|
|
102
|
-
return (_jsx(
|
|
103
|
-
backgroundColor: 'rgb(254 243 199)', // amber-100
|
|
104
|
-
color: 'rgb(180 83 9)', // amber-700
|
|
105
|
-
border: '1px solid rgb(252 211 77)', // amber-300
|
|
106
|
-
}, children: t('sidebar.comingSoon', 'Soon') }), className: twMerge('text-gray-400 cursor-not-allowed', 'dark:text-gray-500'), children: t(label) }));
|
|
97
|
+
return (_jsx(SidebarItem, { icon: icon, label: t('sidebar.comingSoon', 'Soon'), className: twMerge('text-muted-foreground cursor-not-allowed'), children: t(label) }));
|
|
107
98
|
}
|
|
108
|
-
return (_jsx(
|
|
109
|
-
'text-primary-700 bg-primary-100/80 hover:bg-primary-100/80 dark:text-primary-300 dark:bg-primary-900/40 dark:hover:bg-primary-900/40'), children: t(label) }));
|
|
99
|
+
return (_jsx(SidebarItem, { as: Link, href: href, icon: icon, label: badge && t(badge), className: twMerge('text-foreground/70 hover:text-primary/80 hover:bg-primary/10', isParentActive && 'text-primary bg-primary/15 hover:bg-primary/15'), children: t(label) }));
|
|
110
100
|
};
|
|
111
101
|
const AppMobileSidebar = () => {
|
|
112
102
|
const { mobile: { isOpen, close }, sidebarHeader, sidebarFooter, } = useAppSidebarContext();
|
|
113
103
|
const { t } = useTranslation();
|
|
114
104
|
if (!isOpen)
|
|
115
105
|
return null;
|
|
116
|
-
return (_jsxs(_Fragment, { children: [_jsx(Sidebar, { "aria-label": t('sidebar.mobileAriaLabel', 'Sidebar with multi-level dropdown example'), className: twMerge('fixed inset-y-0 left-0 z-20 hidden h-full shrink-0 flex-col border-r border-
|
|
106
|
+
return (_jsxs(_Fragment, { children: [_jsx(Sidebar, { "aria-label": t('sidebar.mobileAriaLabel', 'Sidebar with multi-level dropdown example'), className: twMerge('fixed inset-y-0 left-0 z-20 hidden h-full shrink-0 flex-col border-r border-border pt-16 md:flex', isOpen && 'flex'), id: "sidebar", children: _jsxs("div", { className: "flex h-full flex-col justify-between", children: [_jsxs("div", { className: "flex-1 overflow-y-auto py-2 scrollbar-hide [&::-webkit-scrollbar]:hidden [-ms-overflow-style:none] [scrollbar-width:none]", children: [sidebarHeader && _jsx("div", { className: "mb-4 px-3", children: sidebarHeader }), _jsx("div", { className: "px-3", children: _jsx(AppSidebarMenu, {}) })] }), sidebarFooter && _jsx("div", { className: "border-t border-border p-3", children: sidebarFooter })] }) }), _jsx("div", { onClick: close, "aria-hidden": "true", className: "fixed inset-0 z-10 h-full w-full bg-gray-900/50 pt-16" })] }));
|
|
117
107
|
};
|
|
118
108
|
const AppDesktopSidebar = () => {
|
|
119
109
|
const { desktop: { isCollapsed, setCollapsed }, sidebarHeader, sidebarFooter, } = useAppSidebarContext();
|
|
@@ -136,7 +126,7 @@ const AppDesktopSidebar = () => {
|
|
|
136
126
|
setCollapsed(true);
|
|
137
127
|
},
|
|
138
128
|
};
|
|
139
|
-
return (_jsx(Sidebar, { onMouseEnter: preview.enable, onMouseLeave: preview.disable, "aria-label": tLib('sidebar.desktopAriaLabel', 'Sidebar with multi-level dropdown example'), collapsed: isCollapsed, className: twMerge('fixed inset-y-0 left-0 z-20 flex h-full shrink-0 flex-col border-r border-
|
|
129
|
+
return (_jsx(Sidebar, { onMouseEnter: preview.enable, onMouseLeave: preview.disable, "aria-label": tLib('sidebar.desktopAriaLabel', 'Sidebar with multi-level dropdown example'), collapsed: isCollapsed, className: twMerge('fixed inset-y-0 left-0 z-20 flex h-full shrink-0 flex-col border-r border-border pt-16 duration-75 bg-background', isCollapsed && 'hidden w-16'), id: "sidebar", children: _jsxs("div", { className: "flex h-full flex-col justify-between", children: [_jsxs("div", { className: "flex-1 overflow-y-auto py-2 scrollbar-hide [&::-webkit-scrollbar]:hidden [-ms-overflow-style:none] [scrollbar-width:none]", children: [sidebarHeader && _jsx("div", { className: "mb-4 px-3", children: sidebarHeader }), _jsx("div", { className: "px-2", children: _jsx(AppSidebarMenu, {}) })] }), sidebarFooter && _jsx("div", { className: "border-t border-border p-3", children: sidebarFooter })] }) }));
|
|
140
130
|
};
|
|
141
131
|
const AppDashboardSidebar = () => {
|
|
142
132
|
return (_jsxs(_Fragment, { children: [_jsx("div", { className: "md:hidden", children: _jsx(AppMobileSidebar, {}) }), _jsx("div", { className: "hidden md:block", children: _jsx(AppDesktopSidebar, {}) })] }));
|
|
@@ -4,6 +4,5 @@ export { default as AppBreadcrumbNav } from './BreadcrumbNav';
|
|
|
4
4
|
export { default as AppLayoutContent } from './LayoutContent';
|
|
5
5
|
export { default as AppPageHeader, type AppPageHeaderProps } from './PageHeader';
|
|
6
6
|
export { default as AppDashboardSidebar, AppDesktopSidebar, AppMobileSidebar, AppSidebarMenu } from './Sidebar';
|
|
7
|
-
export { default as VerticalTabsLayout, type VerticalTabsLayoutProps } from './VerticalTabsLayout';
|
|
8
7
|
export { default as AppLayout, type AppLayoutProps } from './AppLayout';
|
|
9
8
|
export { default as SessionExpiryModal, type SessionExpiryModalProps } from './SessionExpiryModal';
|
|
@@ -4,6 +4,5 @@ export { default as AppBreadcrumbNav } from './BreadcrumbNav';
|
|
|
4
4
|
export { default as AppLayoutContent } from './LayoutContent';
|
|
5
5
|
export { default as AppPageHeader } from './PageHeader';
|
|
6
6
|
export { default as AppDashboardSidebar, AppDesktopSidebar, AppMobileSidebar, AppSidebarMenu } from './Sidebar';
|
|
7
|
-
export { default as VerticalTabsLayout } from './VerticalTabsLayout';
|
|
8
7
|
export { default as AppLayout } from './AppLayout';
|
|
9
8
|
export { default as SessionExpiryModal } from './SessionExpiryModal';
|
|
@@ -549,7 +549,7 @@ interface NavbarV2DarkThemeToggleProps {
|
|
|
549
549
|
className?: string;
|
|
550
550
|
}
|
|
551
551
|
/**
|
|
552
|
-
* Dark theme toggle with tooltip
|
|
552
|
+
* Dark theme toggle with tooltip — uses ColorModeProvider (behavioral only).
|
|
553
553
|
*/
|
|
554
554
|
declare const NavbarV2DarkThemeToggle: React.FC<NavbarV2DarkThemeToggleProps>;
|
|
555
555
|
/**
|