@donotdev/ui 0.0.7 → 0.0.9
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/assets/fonts/fonts.css +4 -4
- package/dist/components/auth/AuthHeader.d.ts +5 -0
- package/dist/components/auth/AuthHeader.d.ts.map +1 -1
- package/dist/components/auth/AuthHeader.js +22 -8
- package/dist/components/auth/AuthMenu.d.ts +6 -1
- package/dist/components/auth/AuthMenu.d.ts.map +1 -1
- package/dist/components/auth/AuthMenu.js +3 -3
- package/dist/components/common/AppLoading.d.ts +1 -1
- package/dist/components/common/AppLoading.d.ts.map +1 -1
- package/dist/components/common/AppLoading.js +0 -1
- package/dist/components/common/Loader.d.ts +4 -4
- package/dist/components/common/Loader.d.ts.map +1 -1
- package/dist/components/common/Loader.js +11 -12
- package/dist/components/common/LoadingMessage.d.ts +1 -9
- package/dist/components/common/LoadingMessage.d.ts.map +1 -1
- package/dist/components/common/LoadingMessage.js +0 -1
- package/dist/components/common/LoadingScreen.d.ts +1 -9
- package/dist/components/common/LoadingScreen.d.ts.map +1 -1
- package/dist/components/common/LoadingScreen.js +0 -1
- package/dist/components/common/RedirectOverlay.d.ts +37 -0
- package/dist/components/common/RedirectOverlay.d.ts.map +1 -0
- package/dist/components/common/RedirectOverlay.js +243 -0
- package/dist/components/common/TechBento.d.ts.map +1 -1
- package/dist/components/common/TechBento.js +1 -0
- package/dist/components/common/index.d.ts +1 -0
- package/dist/components/common/index.d.ts.map +1 -1
- package/dist/components/common/index.js +1 -0
- package/dist/components/layout/components/FloatingLanguageSwitcher.d.ts +1 -9
- package/dist/components/layout/components/FloatingLanguageSwitcher.d.ts.map +1 -1
- package/dist/components/layout/components/FloatingLanguageSwitcher.js +0 -1
- package/dist/components/layout/components/header/CacheSettings.d.ts.map +1 -1
- package/dist/components/layout/components/header/HeaderMenu.d.ts.map +1 -1
- package/dist/components/layout/components/header/SettingsMenu.d.ts.map +1 -1
- package/dist/components/layout/components/header/SettingsMenu.js +1 -2
- package/dist/components/layout/components/header/ThemeToggle.d.ts +1 -1
- package/dist/components/layout/components/header/ThemeToggle.d.ts.map +1 -1
- package/dist/components/layout/components/header/ThemeToggle.js +5 -4
- package/dist/crud/components/DisplayFieldRenderer.d.ts +3 -11
- package/dist/crud/components/DisplayFieldRenderer.d.ts.map +1 -1
- package/dist/crud/components/DisplayFieldRenderer.js +4 -3
- package/dist/crud/components/EntityDisplayRenderer.d.ts +2 -2
- package/dist/crud/components/fields/display/AvatarFieldDisplay.d.ts +2 -2
- package/dist/crud/components/fields/display/BadgeFieldDisplay.d.ts +2 -2
- package/dist/crud/components/fields/display/ButtonFieldDisplay.d.ts +2 -2
- package/dist/crud/components/fields/display/CheckboxFieldDisplay.d.ts +2 -2
- package/dist/crud/components/fields/display/DateFieldDisplay.d.ts +3 -11
- package/dist/crud/components/fields/display/DateFieldDisplay.d.ts.map +1 -1
- package/dist/crud/components/fields/display/DateFieldDisplay.js +0 -1
- package/dist/crud/components/fields/display/DropdownDisplay.d.ts +2 -2
- package/dist/crud/components/fields/display/FileFieldDisplay.d.ts +2 -2
- package/dist/crud/components/fields/display/GeoPointFieldDisplay.d.ts +3 -11
- package/dist/crud/components/fields/display/GeoPointFieldDisplay.d.ts.map +1 -1
- package/dist/crud/components/fields/display/GeoPointFieldDisplay.js +0 -1
- package/dist/crud/components/fields/display/HiddenFieldDisplay.d.ts +3 -3
- package/dist/crud/components/fields/display/HiddenFieldDisplay.d.ts.map +1 -1
- package/dist/crud/components/fields/display/HiddenFieldDisplay.js +0 -9
- package/dist/crud/components/fields/display/ImageFieldDisplay.d.ts +3 -11
- package/dist/crud/components/fields/display/ImageFieldDisplay.d.ts.map +1 -1
- package/dist/crud/components/fields/display/ImageFieldDisplay.js +0 -1
- package/dist/crud/components/fields/display/LinkFieldDisplay.d.ts +3 -11
- package/dist/crud/components/fields/display/LinkFieldDisplay.d.ts.map +1 -1
- package/dist/crud/components/fields/display/LinkFieldDisplay.js +0 -1
- package/dist/crud/components/fields/display/MapFieldDisplay.d.ts +3 -11
- package/dist/crud/components/fields/display/MapFieldDisplay.d.ts.map +1 -1
- package/dist/crud/components/fields/display/MapFieldDisplay.js +0 -1
- package/dist/crud/components/fields/display/MultiDropdownDisplay.d.ts +3 -11
- package/dist/crud/components/fields/display/MultiDropdownDisplay.d.ts.map +1 -1
- package/dist/crud/components/fields/display/MultiDropdownDisplay.js +0 -1
- package/dist/crud/components/fields/display/MultiInputTextFieldDisplay.d.ts +3 -11
- package/dist/crud/components/fields/display/MultiInputTextFieldDisplay.d.ts.map +1 -1
- package/dist/crud/components/fields/display/MultiInputTextFieldDisplay.js +0 -1
- package/dist/crud/components/fields/display/NumberFieldDisplay.d.ts +3 -11
- package/dist/crud/components/fields/display/NumberFieldDisplay.d.ts.map +1 -1
- package/dist/crud/components/fields/display/NumberFieldDisplay.js +0 -1
- package/dist/crud/components/fields/display/PasswordFieldDisplay.d.ts +3 -3
- package/dist/crud/components/fields/display/PasswordFieldDisplay.d.ts.map +1 -1
- package/dist/crud/components/fields/display/PasswordFieldDisplay.js +0 -1
- package/dist/crud/components/fields/display/PhoneNumberDisplay.d.ts +3 -11
- package/dist/crud/components/fields/display/PhoneNumberDisplay.d.ts.map +1 -1
- package/dist/crud/components/fields/display/PhoneNumberDisplay.js +0 -1
- package/dist/crud/components/fields/display/RadioFieldDisplay.d.ts +3 -11
- package/dist/crud/components/fields/display/RadioFieldDisplay.d.ts.map +1 -1
- package/dist/crud/components/fields/display/RadioFieldDisplay.js +0 -1
- package/dist/crud/components/fields/display/RangeFieldDisplay.d.ts +3 -11
- package/dist/crud/components/fields/display/RangeFieldDisplay.d.ts.map +1 -1
- package/dist/crud/components/fields/display/RangeFieldDisplay.js +0 -1
- package/dist/crud/components/fields/display/ReferenceFieldDisplay.d.ts +3 -11
- package/dist/crud/components/fields/display/ReferenceFieldDisplay.d.ts.map +1 -1
- package/dist/crud/components/fields/display/ReferenceFieldDisplay.js +0 -1
- package/dist/crud/components/fields/display/RichTextDisplay.d.ts +25 -0
- package/dist/crud/components/fields/display/RichTextDisplay.d.ts.map +1 -0
- package/dist/crud/components/fields/display/RichTextDisplay.js +104 -0
- package/dist/crud/components/fields/display/TextAreaDisplay.d.ts +3 -11
- package/dist/crud/components/fields/display/TextAreaDisplay.d.ts.map +1 -1
- package/dist/crud/components/fields/display/TextAreaDisplay.js +0 -1
- package/dist/crud/components/fields/display/TextFieldDisplay.d.ts +2 -2
- package/dist/crud/components/fields/display/TimestampFieldDisplay.d.ts +3 -11
- package/dist/crud/components/fields/display/TimestampFieldDisplay.d.ts.map +1 -1
- package/dist/crud/components/fields/display/TimestampFieldDisplay.js +0 -1
- package/dist/crud/components/fields/display/index.d.ts +1 -0
- package/dist/crud/components/fields/display/index.d.ts.map +1 -1
- package/dist/crud/components/fields/display/index.js +1 -0
- package/dist/dndev.css +827 -126
- package/dist/index.js +64 -4
- package/dist/internal/common/ErrorFallback.d.ts +1 -10
- package/dist/internal/common/ErrorFallback.d.ts.map +1 -1
- package/dist/internal/common/GlobalErrorFallback.d.ts +1 -9
- package/dist/internal/common/GlobalErrorFallback.d.ts.map +1 -1
- package/dist/internal/common/RouteErrorFallback.js +1 -1
- package/dist/internal/devtools/components/DebugDialog.d.ts.map +1 -1
- package/dist/internal/devtools/components/DebugDialog.js +3 -1
- package/dist/internal/devtools/components/DesignTab.d.ts.map +1 -1
- package/dist/internal/devtools/components/DesignTab.js +25 -3
- package/dist/internal/devtools/components/MaskedValue.d.ts.map +1 -1
- package/dist/internal/devtools/components/MaskedValue.js +1 -1
- package/dist/internal/devtools/components/StoresTab.js +1 -1
- package/dist/internal/initializers/BaseStoresInitializer.d.ts.map +1 -1
- package/dist/internal/initializers/BaseStoresInitializer.js +1 -2
- package/dist/internal/initializers/NextJsStoresInitializer.d.ts.map +1 -1
- package/dist/internal/layout/DnDevLayout.d.ts.map +1 -1
- package/dist/internal/layout/DnDevLayout.js +4 -5
- package/dist/internal/layout/components/AutoMetaTags.d.ts.map +1 -1
- package/dist/internal/layout/components/PerformanceHints.d.ts.map +1 -1
- package/dist/internal/layout/components/PerformanceHints.js +3 -2
- package/dist/internal/layout/components/footer/FooterLegalLinks.js +2 -2
- package/dist/internal/layout/config/defaults.d.ts +0 -10
- package/dist/internal/layout/config/defaults.d.ts.map +1 -1
- package/dist/internal/layout/config/defaults.js +12 -1
- package/dist/internal/layout/config/presets/admin.d.ts +2 -2
- package/dist/internal/layout/config/presets/admin.d.ts.map +1 -1
- package/dist/internal/layout/config/presets/admin.js +15 -6
- package/dist/internal/layout/config/presets/blog.d.ts.map +1 -1
- package/dist/internal/layout/config/presets/blog.js +7 -1
- package/dist/internal/layout/config/presets/docs.d.ts.map +1 -1
- package/dist/internal/layout/config/presets/docs.js +7 -5
- package/dist/internal/layout/config/presets/game.d.ts.map +1 -1
- package/dist/internal/layout/config/presets/game.js +7 -2
- package/dist/internal/layout/config/presets/moolti.d.ts.map +1 -1
- package/dist/internal/layout/config/presets/moolti.js +10 -3
- package/dist/internal/layout/zones/DnDevFooter.d.ts +1 -13
- package/dist/internal/layout/zones/DnDevFooter.d.ts.map +1 -1
- package/dist/internal/layout/zones/DnDevHeader.d.ts +1 -14
- package/dist/internal/layout/zones/DnDevHeader.d.ts.map +1 -1
- package/dist/internal/layout/zones/DnDevMergedBar.d.ts +2 -14
- package/dist/internal/layout/zones/DnDevMergedBar.d.ts.map +1 -1
- package/dist/internal/layout/zones/DnDevMergedBar.js +11 -3
- package/dist/internal/layout/zones/DnDevSidebar.d.ts +1 -14
- package/dist/internal/layout/zones/DnDevSidebar.d.ts.map +1 -1
- package/dist/providers/NextJsAppProviders.d.ts.map +1 -1
- package/dist/providers/NextJsAppProviders.js +4 -1
- package/dist/routing/AuthGuard.d.ts.map +1 -1
- package/dist/routing/GoTo.d.ts +3 -1
- package/dist/routing/GoTo.d.ts.map +1 -1
- package/dist/routing/GoTo.js +6 -2
- package/dist/routing/GoToDialog.d.ts +1 -1
- package/dist/routing/GoToDialog.d.ts.map +1 -1
- package/dist/routing/GoToDialog.js +3 -5
- package/dist/routing/NavigationItem.d.ts +1 -1
- package/dist/routing/NavigationItem.d.ts.map +1 -1
- package/dist/routing/NavigationItem.js +0 -1
- package/dist/routing/hooks/hooks.next.d.ts +1 -0
- package/dist/routing/hooks/hooks.next.d.ts.map +1 -1
- package/dist/routing/hooks/hooks.next.js +1 -1
- package/dist/routing/hooks/hooks.vite.d.ts +1 -0
- package/dist/routing/hooks/hooks.vite.d.ts.map +1 -1
- package/dist/routing/hooks/hooks.vite.js +1 -1
- package/dist/routing/hooks/useNavigate.next.d.ts.map +1 -1
- package/dist/routing/hooks/useNavigate.next.js +1 -1
- package/dist/routing/hooks/useNavigate.vite.d.ts.map +1 -1
- package/dist/routing/hooks/useRouteParam.next.d.ts +18 -0
- package/dist/routing/hooks/useRouteParam.next.d.ts.map +1 -0
- package/dist/routing/hooks/useRouteParam.next.js +38 -0
- package/dist/routing/hooks/useRouteParam.vite.d.ts +18 -0
- package/dist/routing/hooks/useRouteParam.vite.d.ts.map +1 -0
- package/dist/routing/hooks/useRouteParam.vite.js +38 -0
- package/dist/routing/index.d.ts +1 -1
- package/dist/routing/index.d.ts.map +1 -1
- package/dist/routing/index.js +1 -1
- package/dist/routing/useGoTo.d.ts.map +1 -1
- package/dist/styles/index.css +823 -122
- package/dist/utils/assetResolver.d.ts +1 -1
- package/dist/utils/assetResolver.d.ts.map +1 -1
- package/dist/utils/assetResolver.js +1 -2
- package/dist/utils/index.d.ts +0 -1
- package/dist/utils/index.d.ts.map +1 -1
- package/dist/utils/index.js +0 -1
- package/dist/utils/tList.d.ts +1 -1
- package/dist/utils/tList.d.ts.map +1 -1
- package/dist/utils/useAuthSafe.d.ts +0 -33
- package/dist/utils/useAuthSafe.d.ts.map +1 -1
- package/dist/utils/useAuthSafe.js +34 -1
- package/dist/utils/useCrudSafe.d.ts +12 -6
- package/dist/utils/useCrudSafe.d.ts.map +1 -1
- package/dist/utils/useCrudSafe.js +11 -7
- package/dist/utils/useOAuthSafe.d.ts.map +1 -1
- package/dist/utils/useStripeBillingSafe.d.ts +1 -34
- package/dist/utils/useStripeBillingSafe.d.ts.map +1 -1
- package/dist/utils/useStripeBillingSafe.js +34 -1
- package/dist/vite-routing/AppRoutes.d.ts +1 -1
- package/dist/vite-routing/AppRoutes.d.ts.map +1 -1
- package/dist/vite-routing/AppRoutes.js +0 -1
- package/dist/vite-routing/RootLayout.d.ts.map +1 -1
- package/dist/vite-routing/RootLayout.js +6 -6
- package/package.json +9 -9
package/assets/fonts/fonts.css
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
font-family: Roboto;
|
|
5
5
|
font-style: normal;
|
|
6
6
|
font-weight: 400;
|
|
7
|
-
font-display:
|
|
7
|
+
font-display: swap;
|
|
8
8
|
src: url('/fonts/Roboto-400-latin.woff2') format('woff2');
|
|
9
9
|
unicode-range: U+0000-00FF; /* Basic Latin - loads first for performance */
|
|
10
10
|
}
|
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
font-family: Roboto;
|
|
14
14
|
font-style: normal;
|
|
15
15
|
font-weight: 700;
|
|
16
|
-
font-display:
|
|
16
|
+
font-display: swap;
|
|
17
17
|
src: url('/fonts/Roboto-700-latin.woff2') format('woff2');
|
|
18
18
|
unicode-range: U+0000-00FF; /* Basic Latin - loads first for performance */
|
|
19
19
|
}
|
|
@@ -153,7 +153,7 @@
|
|
|
153
153
|
font-family: Inter;
|
|
154
154
|
font-style: normal;
|
|
155
155
|
font-weight: 400 700;
|
|
156
|
-
font-display: optional
|
|
156
|
+
font-display: swap; /* Changed from optional to swap - we preload this font */
|
|
157
157
|
src: url('/fonts/Inter-latin.woff2') format('woff2');
|
|
158
158
|
unicode-range:
|
|
159
159
|
U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC,
|
|
@@ -184,7 +184,7 @@
|
|
|
184
184
|
font-family: 'Playfair Display';
|
|
185
185
|
font-style: normal;
|
|
186
186
|
font-weight: 400 700;
|
|
187
|
-
font-display:
|
|
187
|
+
font-display: swap;
|
|
188
188
|
src: url('/fonts/PlayfairDisplay-latin.woff2') format('woff2');
|
|
189
189
|
unicode-range:
|
|
190
190
|
U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC,
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { DISPLAY } from '@donotdev/components';
|
|
2
|
+
import type { CSSProperties } from 'react';
|
|
2
3
|
import type { ComponentType } from 'react';
|
|
3
4
|
/**
|
|
4
5
|
* AuthHeader - Simple, powerful authentication component for headers
|
|
@@ -46,6 +47,10 @@ export interface AuthHeaderProps {
|
|
|
46
47
|
* @default 'auto'
|
|
47
48
|
*/
|
|
48
49
|
display?: (typeof DISPLAY)[keyof typeof DISPLAY];
|
|
50
|
+
/** Optional className for styling the button */
|
|
51
|
+
className?: string;
|
|
52
|
+
/** Optional inline styles for the button */
|
|
53
|
+
style?: CSSProperties;
|
|
49
54
|
}
|
|
50
55
|
/**
|
|
51
56
|
* Auth header component
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AuthHeader.d.ts","sourceRoot":"","sources":["../../../src/components/auth/AuthHeader.tsx"],"names":[],"mappings":"AAgBA,OAAO,
|
|
1
|
+
{"version":3,"file":"AuthHeader.d.ts","sourceRoot":"","sources":["../../../src/components/auth/AuthHeader.tsx"],"names":[],"mappings":"AAgBA,OAAO,EAKL,OAAO,EACR,MAAM,sBAAsB,CAAC;AAU9B,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,OAAO,CAAC;AAC3C,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,OAAO,CAAC;AAyB3C;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAoCG;AACH,MAAM,WAAW,eAAe;IAC9B;;;;;;OAMG;IACH,OAAO,CAAC,EAAE,CAAC,OAAO,OAAO,CAAC,CAAC,MAAM,OAAO,OAAO,CAAC,CAAC;IACjD,gDAAgD;IAChD,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,4CAA4C;IAC5C,KAAK,CAAC,EAAE,aAAa,CAAC;CACvB;AAED;;;;;;GAMG;AACH,eAAO,MAAM,UAAU,EAAE,aAAa,CAAC,eAAe,CA4IrD,CAAC;AAEF,eAAe,UAAU,CAAC"}
|
|
@@ -10,8 +10,8 @@
|
|
|
10
10
|
'use client';
|
|
11
11
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
12
12
|
import { User } from 'lucide-react';
|
|
13
|
-
import React, { Suspense, lazy } from 'react';
|
|
14
|
-
import { Button, BUTTON_VARIANT, DropdownMenu, DISPLAY, } from '@donotdev/components';
|
|
13
|
+
import React, { Suspense, lazy, useState } from 'react';
|
|
14
|
+
import { Button, BUTTON_VARIANT, DropdownMenu, Dialog, DISPLAY, } from '@donotdev/components';
|
|
15
15
|
import { useTranslation } from '@donotdev/core';
|
|
16
16
|
import { useAuthConfig } from '@donotdev/core';
|
|
17
17
|
import { getEnabledAuthPartners } from '@donotdev/core';
|
|
@@ -47,34 +47,48 @@ const MultipleAuthProviders = lazy(async () => {
|
|
|
47
47
|
* @since 0.0.1
|
|
48
48
|
* @author AMBROISE PARK Consulting
|
|
49
49
|
*/
|
|
50
|
-
export const AuthHeader = ({ display = DISPLAY.AUTO, }) => {
|
|
50
|
+
export const AuthHeader = ({ display = DISPLAY.AUTO, className, style, }) => {
|
|
51
51
|
const { t } = useTranslation('dndev');
|
|
52
52
|
const { shouldHide, isLoading, isReady, isAuthenticated } = useAuthVisibility();
|
|
53
53
|
const authConfig = useAuthConfig();
|
|
54
54
|
const enabled = getEnabledAuthPartners();
|
|
55
|
+
const [dialogOpen, setDialogOpen] = useState(false);
|
|
55
56
|
const loginPath = authConfig.loginPath;
|
|
56
57
|
const signInLabel = t('auth.signIn', { defaultValue: 'Sign In' });
|
|
57
58
|
const loadingLabel = t('auth.loading', { defaultValue: 'Loading...' });
|
|
59
|
+
const hasPasswordProvider = enabled.includes('password') || enabled.includes('emailLink');
|
|
58
60
|
if (shouldHide || !isReady) {
|
|
59
61
|
return null;
|
|
60
62
|
}
|
|
63
|
+
// Local component for Sign In button (DRY)
|
|
64
|
+
const SignInButton = ({ children, ...props }) => (_jsx(Button, { variant: BUTTON_VARIANT.OUTLINE, icon: User, display: display, tooltip: signInLabel, className: className, style: style, ...props, children: children ?? signInLabel }));
|
|
61
65
|
// NOT AUTHENTICATED
|
|
62
66
|
// Button's display prop + CSS container queries handle responsive label visibility
|
|
63
67
|
if (!isAuthenticated) {
|
|
64
68
|
if (loginPath !== undefined) {
|
|
65
|
-
return (_jsx(Link, { path: loginPath, prefetch: true, children: _jsx(
|
|
69
|
+
return (_jsx(Link, { path: loginPath, prefetch: true, children: _jsx(SignInButton, {}) }));
|
|
66
70
|
}
|
|
71
|
+
const targetProvider = enabled[0];
|
|
72
|
+
// Use Dialog if password/emailLink provider is present (better UX for forms)
|
|
73
|
+
if (hasPasswordProvider) {
|
|
74
|
+
return (_jsx(Dialog, { trigger: _jsx(SignInButton, {}), title: signInLabel, open: dialogOpen, onOpenChange: setDialogOpen, "data-content-size": "form", children: _jsx(Suspense, { fallback: _jsx("div", { style: {
|
|
75
|
+
padding: 'var(--gap-md)',
|
|
76
|
+
fontSize: 'var(--font-size-sm)',
|
|
77
|
+
color: 'var(--muted-foreground)',
|
|
78
|
+
}, children: loadingLabel }), children: _jsx(MultipleAuthProviders, { spacing: "medium", onSuccess: () => setDialogOpen(false) }) }) }));
|
|
79
|
+
}
|
|
80
|
+
// Use DropdownMenu if multiple OAuth providers (no password/emailLink)
|
|
67
81
|
if (enabled.length > 1) {
|
|
68
|
-
return (_jsx(DropdownMenu, { trigger: _jsx(
|
|
82
|
+
return (_jsx(DropdownMenu, { trigger: _jsx(SignInButton, {}), children: _jsx(Suspense, { fallback: _jsx("div", { style: {
|
|
69
83
|
padding: 'var(--gap-md)',
|
|
70
84
|
fontSize: 'var(--font-size-sm)',
|
|
71
85
|
color: 'var(--muted-foreground)',
|
|
72
86
|
}, children: loadingLabel }), children: _jsx(MultipleAuthProviders, { spacing: "tight" }) }) }));
|
|
73
87
|
}
|
|
74
|
-
|
|
75
|
-
return (_jsx(Suspense, { fallback: _jsx(
|
|
88
|
+
// Normal case: single non-password provider → use AuthPartnerButton directly
|
|
89
|
+
return (_jsx(Suspense, { fallback: _jsx(SignInButton, { disabled: isLoading, tooltip: isLoading ? loadingLabel : signInLabel, children: isLoading ? loadingLabel : signInLabel }), children: _jsx(AuthPartnerButton, { partnerId: targetProvider, display: display, className: className, style: style }) }));
|
|
76
90
|
}
|
|
77
91
|
// AUTHENTICATED - Delegate to AuthMenu
|
|
78
|
-
return _jsx(AuthMenu, { display: display, loginPath: loginPath });
|
|
92
|
+
return (_jsx(AuthMenu, { display: display, loginPath: loginPath, className: className, style: style }));
|
|
79
93
|
};
|
|
80
94
|
export default AuthHeader;
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
import { DISPLAY } from '@donotdev/components';
|
|
3
|
+
import type { CSSProperties } from 'react';
|
|
3
4
|
import type { ComponentType } from 'react';
|
|
4
5
|
/**
|
|
5
6
|
* Custom menu item for AuthMenu
|
|
@@ -53,7 +54,11 @@ export interface AuthMenuProps {
|
|
|
53
54
|
* Order: Profile (if configured) → authMenuItems → customItems → Delete Account → Sign Out
|
|
54
55
|
*/
|
|
55
56
|
customItems?: AuthMenuCustomItem[];
|
|
57
|
+
/** Optional className for styling the button */
|
|
58
|
+
className?: string;
|
|
59
|
+
/** Optional inline styles for the button */
|
|
60
|
+
style?: CSSProperties;
|
|
56
61
|
}
|
|
57
|
-
export declare const AuthMenu: ({ loginPath, display, "no-tooltip": noTooltip, customItems, }: AuthMenuProps) => import("react/jsx-runtime").JSX.Element | null;
|
|
62
|
+
export declare const AuthMenu: ({ loginPath, display, "no-tooltip": noTooltip, customItems, className, style, }: AuthMenuProps) => import("react/jsx-runtime").JSX.Element | null;
|
|
58
63
|
export default AuthMenu;
|
|
59
64
|
//# sourceMappingURL=AuthMenu.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AuthMenu.d.ts","sourceRoot":"","sources":["../../../src/components/auth/AuthMenu.tsx"],"names":[],"mappings":"AA4EA,OAAO,KAAkC,MAAM,OAAO,CAAC;AAEvD,OAAO,EAML,OAAO,EACR,MAAM,sBAAsB,CAAC;AAc9B,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,OAAO,CAAC;AAqE3C;;;;;;;;;GASG;AACH,MAAM,WAAW,kBAAkB;IACjC,sBAAsB;IACtB,KAAK,EAAE,MAAM,CAAC;IACd,mDAAmD;IACnD,IAAI,CAAC,EAAE,MAAM,GAAG,aAAa,CAAC;QAAE,SAAS,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IACtD,6DAA6D;IAC7D,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;IACrB,8DAA8D;IAC9D,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,+BAA+B;IAC/B,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,mBAAmB;IACnB,KAAK,CAAC,EAAE,KAAK,CAAC,aAAa,CAAC;CAC7B;AAED;;;;;;GAMG;AACH,MAAM,WAAW,aAAa;IAC5B,qFAAqF;IACrF,SAAS,CAAC,EAAE,MAAM,CAAC;IAEnB;;;;;;OAMG;IACH,OAAO,CAAC,EAAE,CAAC,OAAO,OAAO,CAAC,CAAC,MAAM,OAAO,OAAO,CAAC,CAAC;IAEjD,sBAAsB;IACtB,YAAY,CAAC,EAAE,OAAO,CAAC;IAEvB;;;;OAIG;IACH,WAAW,CAAC,EAAE,kBAAkB,EAAE,CAAC;
|
|
1
|
+
{"version":3,"file":"AuthMenu.d.ts","sourceRoot":"","sources":["../../../src/components/auth/AuthMenu.tsx"],"names":[],"mappings":"AA4EA,OAAO,KAAkC,MAAM,OAAO,CAAC;AAEvD,OAAO,EAML,OAAO,EACR,MAAM,sBAAsB,CAAC;AAc9B,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,OAAO,CAAC;AAC3C,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,OAAO,CAAC;AAqE3C;;;;;;;;;GASG;AACH,MAAM,WAAW,kBAAkB;IACjC,sBAAsB;IACtB,KAAK,EAAE,MAAM,CAAC;IACd,mDAAmD;IACnD,IAAI,CAAC,EAAE,MAAM,GAAG,aAAa,CAAC;QAAE,SAAS,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IACtD,6DAA6D;IAC7D,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;IACrB,8DAA8D;IAC9D,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,+BAA+B;IAC/B,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,mBAAmB;IACnB,KAAK,CAAC,EAAE,KAAK,CAAC,aAAa,CAAC;CAC7B;AAED;;;;;;GAMG;AACH,MAAM,WAAW,aAAa;IAC5B,qFAAqF;IACrF,SAAS,CAAC,EAAE,MAAM,CAAC;IAEnB;;;;;;OAMG;IACH,OAAO,CAAC,EAAE,CAAC,OAAO,OAAO,CAAC,CAAC,MAAM,OAAO,OAAO,CAAC,CAAC;IAEjD,sBAAsB;IACtB,YAAY,CAAC,EAAE,OAAO,CAAC;IAEvB;;;;OAIG;IACH,WAAW,CAAC,EAAE,kBAAkB,EAAE,CAAC;IAEnC,gDAAgD;IAChD,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,4CAA4C;IAC5C,KAAK,CAAC,EAAE,aAAa,CAAC;CACvB;AAsBD,eAAO,MAAM,QAAQ,GAAI,iFAOtB,aAAa,mDA0Of,CAAC;AAEF,eAAe,QAAQ,CAAC"}
|
|
@@ -77,8 +77,8 @@ import { Avatar, Button, BUTTON_VARIANT, DropdownMenu, Text, DISPLAY, } from '@d
|
|
|
77
77
|
import { useTranslation } from '@donotdev/core';
|
|
78
78
|
import { getEnabledAuthPartners, useAuthConfig, isClient, } from '@donotdev/core';
|
|
79
79
|
import { useBreakpoint } from '@donotdev/core';
|
|
80
|
-
import { useNavigationItems } from '../../routing';
|
|
81
80
|
import { useNavigate } from '@donotdev/ui/routing/hooks';
|
|
81
|
+
import { useNavigationItems } from '../../routing';
|
|
82
82
|
import { useAuthSafe, useAuthVisibility } from '../../utils';
|
|
83
83
|
const NullComponent = () => null;
|
|
84
84
|
// @ts-expect-error - lazy() type doesn't account for graceful degradation fallback
|
|
@@ -154,7 +154,7 @@ const getIcon = (iconName) => {
|
|
|
154
154
|
const cleanIconName = iconName.replace(/['"]/g, '');
|
|
155
155
|
return LucideIcons[cleanIconName] || Settings;
|
|
156
156
|
};
|
|
157
|
-
export const AuthMenu = ({ loginPath, display = DISPLAY.AUTO, 'no-tooltip': noTooltip = false, customItems = [], }) => {
|
|
157
|
+
export const AuthMenu = ({ loginPath, display = DISPLAY.AUTO, 'no-tooltip': noTooltip = false, customItems = [], className, style, }) => {
|
|
158
158
|
const { t } = useTranslation('dndev');
|
|
159
159
|
const { shouldHide, isReady, isAuthenticated } = useAuthVisibility();
|
|
160
160
|
const authConfig = useAuthConfig();
|
|
@@ -312,6 +312,6 @@ export const AuthMenu = ({ loginPath, display = DISPLAY.AUTO, 'no-tooltip': noTo
|
|
|
312
312
|
? getUserTooltip()
|
|
313
313
|
: !noTooltip
|
|
314
314
|
? t('auth.userMenu', { defaultValue: 'User menu' })
|
|
315
|
-
: undefined, children: getUserDisplayName() }), items: menuItems, contentAlign: "end" })] }));
|
|
315
|
+
: undefined, className: className, style: style, children: getUserDisplayName() }), items: menuItems, contentAlign: "end" })] }));
|
|
316
316
|
};
|
|
317
317
|
export default AuthMenu;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AppLoading.d.ts","sourceRoot":"","sources":["../../../src/components/common/AppLoading.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"AppLoading.d.ts","sourceRoot":"","sources":["../../../src/components/common/AppLoading.tsx"],"names":[],"mappings":"AAeA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,OAAO,CAAC;AAE3C;;;;;;;GAOG;AACH,QAAA,MAAM,UAAU,EAAE,aAAa,CAAC;IAAE,SAAS,CAAC,EAAE,MAAM,CAAA;CAAE,CA2BrD,CAAC;AAEF,eAAe,UAAU,CAAC"}
|
|
@@ -9,7 +9,6 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
|
9
9
|
* @author AMBROISE PARK Consulting
|
|
10
10
|
*/
|
|
11
11
|
import { RefreshCw } from 'lucide-react';
|
|
12
|
-
import {} from 'react';
|
|
13
12
|
import { cn } from '@donotdev/components';
|
|
14
13
|
/**
|
|
15
14
|
* AppLoading - Framework-level, context-free loading fallback for Suspense boundaries.
|
|
@@ -17,11 +17,11 @@ declare const SimpleLoader: ComponentType<{
|
|
|
17
17
|
className?: string;
|
|
18
18
|
}>;
|
|
19
19
|
/**
|
|
20
|
-
* Loader -
|
|
20
|
+
* Loader - Simple loading spinner component
|
|
21
21
|
*
|
|
22
|
-
*
|
|
23
|
-
*
|
|
24
|
-
*
|
|
22
|
+
* Used for Suspense fallbacks and explicit loading states.
|
|
23
|
+
* Components should use `useCrudList().loading` or `useCrudList().fetching`
|
|
24
|
+
* for reactive loading states from TanStack Query.
|
|
25
25
|
*
|
|
26
26
|
* @version 0.0.1
|
|
27
27
|
* @since 0.0.1
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Loader.d.ts","sourceRoot":"","sources":["../../../src/components/common/Loader.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"Loader.d.ts","sourceRoot":"","sources":["../../../src/components/common/Loader.tsx"],"names":[],"mappings":"AAiBA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,OAAO,CAAC;AAE3C,UAAU,WAAW;IACnB,OAAO,CAAC,EAAE,UAAU,GAAG,QAAQ,CAAC;IAChC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,OAAO,CAAC;CACrB;AAED;;;;;;;GAOG;AACH,QAAA,MAAM,YAAY,EAAE,aAAa,CAAC;IAChC,OAAO,CAAC,EAAE,UAAU,GAAG,QAAQ,CAAC;IAChC,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB,CAiDA,CAAC;AAwBF;;;;;;;;;;GAUG;AACH,QAAA,MAAM,MAAM,EAAE,aAAa,CAAC,WAAW,CAEtC,CAAC;AAGF,eAAe,MAAM,CAAC;AACtB,OAAO,EAAE,YAAY,EAAE,CAAC"}
|
|
@@ -12,7 +12,6 @@ import { jsx as _jsx } from "react/jsx-runtime";
|
|
|
12
12
|
import { RefreshCw } from 'lucide-react';
|
|
13
13
|
import { Suspense } from 'react';
|
|
14
14
|
import { cn } from '@donotdev/components';
|
|
15
|
-
import { useLoadingState } from '@donotdev/core';
|
|
16
15
|
/**
|
|
17
16
|
* Simple fallback loader that doesn't depend on any stores
|
|
18
17
|
* Used internally for Suspense fallbacks and initial loading states
|
|
@@ -48,34 +47,34 @@ const SimpleLoader = ({ variant = 'fullPage', className }) => {
|
|
|
48
47
|
} }) }));
|
|
49
48
|
};
|
|
50
49
|
/**
|
|
51
|
-
*
|
|
50
|
+
* Loader component - renders spinner based on isLoading prop
|
|
52
51
|
*
|
|
53
52
|
* @version 0.0.1
|
|
54
53
|
* @since 0.0.1
|
|
55
54
|
* @author AMBROISE PARK Consulting
|
|
56
55
|
*/
|
|
57
|
-
const
|
|
58
|
-
//
|
|
59
|
-
|
|
60
|
-
const shouldRenderLoader = propIsLoading ?? storeIsLoading;
|
|
61
|
-
if (!shouldRenderLoader) {
|
|
56
|
+
const LoaderComponent = ({ variant = 'fullPage', className, isLoading, }) => {
|
|
57
|
+
// If isLoading is explicitly false, don't render
|
|
58
|
+
if (isLoading === false) {
|
|
62
59
|
return null;
|
|
63
60
|
}
|
|
61
|
+
// If isLoading is undefined or true, show loader
|
|
62
|
+
// (undefined means always show - useful for Suspense fallbacks)
|
|
64
63
|
return _jsx(SimpleLoader, { variant: variant, className: className });
|
|
65
64
|
};
|
|
66
65
|
/**
|
|
67
|
-
* Loader -
|
|
66
|
+
* Loader - Simple loading spinner component
|
|
68
67
|
*
|
|
69
|
-
*
|
|
70
|
-
*
|
|
71
|
-
*
|
|
68
|
+
* Used for Suspense fallbacks and explicit loading states.
|
|
69
|
+
* Components should use `useCrudList().loading` or `useCrudList().fetching`
|
|
70
|
+
* for reactive loading states from TanStack Query.
|
|
72
71
|
*
|
|
73
72
|
* @version 0.0.1
|
|
74
73
|
* @since 0.0.1
|
|
75
74
|
* @author AMBROISE PARK Consulting
|
|
76
75
|
*/
|
|
77
76
|
const Loader = (props) => {
|
|
78
|
-
return
|
|
77
|
+
return _jsx(LoaderComponent, { ...props });
|
|
79
78
|
};
|
|
80
79
|
// Export both components for flexibility
|
|
81
80
|
export default Loader;
|
|
@@ -1,12 +1,4 @@
|
|
|
1
|
-
|
|
2
|
-
* @fileoverview LoadingMessage component
|
|
3
|
-
* @description Loading message component with state indicators
|
|
4
|
-
*
|
|
5
|
-
* @version 0.0.1
|
|
6
|
-
* @since 0.0.1
|
|
7
|
-
* @author AMBROISE PARK Consulting
|
|
8
|
-
*/
|
|
9
|
-
import { type ComponentType } from 'react';
|
|
1
|
+
import type { ComponentType } from 'react';
|
|
10
2
|
interface LoadingMessageProps {
|
|
11
3
|
/** The current loading state */
|
|
12
4
|
state?: 'initial' | 'loading' | 'processing' | 'almost-done' | 'complete';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"LoadingMessage.d.ts","sourceRoot":"","sources":["../../../src/components/common/LoadingMessage.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"LoadingMessage.d.ts","sourceRoot":"","sources":["../../../src/components/common/LoadingMessage.tsx"],"names":[],"mappings":"AAcA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,OAAO,CAAC;AAE3C,UAAU,mBAAmB;IAC3B,gCAAgC;IAChC,KAAK,CAAC,EAAE,SAAS,GAAG,SAAS,GAAG,YAAY,GAAG,aAAa,GAAG,UAAU,CAAC;IAC1E,gCAAgC;IAChC,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,kCAAkC;IAClC,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,4CAA4C;IAC5C,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,iDAAiD;IACjD,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,0BAA0B;IAC1B,WAAW,CAAC,EAAE,IAAI,GAAG,IAAI,GAAG,IAAI,CAAC;CAClC;AAED;;;;;;;;;;;;;GAaG;AACH,QAAA,MAAM,cAAc,EAAE,aAAa,CAAC,mBAAmB,CA8DtD,CAAC;AAEF;;;;;;GAMG;AACH,eAAO,MAAM,oBAAoB,EAAE,aAAa,CAC9C,IAAI,CAAC,mBAAmB,EAAE,OAAO,CAAC,GAAG;IACnC,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB,CAGF,CAAC;AAEF;;;;;;GAMG;AACH,eAAO,MAAM,wBAAwB,EAAE,aAAa,CAClD,IAAI,CAAC,mBAAmB,EAAE,OAAO,CAAC,GAAG;IACnC,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB,CAGF,CAAC;AAEF;;;;;;GAMG;AACH,eAAO,MAAM,wBAAwB,EAAE,aAAa,CAClD,IAAI,CAAC,mBAAmB,EAAE,OAAO,CAAC,GAAG;IACnC,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB,CAGF,CAAC;AAEF;;;;;;GAMG;AACH,eAAO,MAAM,sBAAsB,EAAE,aAAa,CAChD,IAAI,CAAC,mBAAmB,EAAE,OAAO,CAAC,GAAG;IACnC,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB,CAGF,CAAC;AAEF;;;;;;GAMG;AACH,eAAO,MAAM,oBAAoB,EAAE,aAAa,CAC9C,IAAI,CAAC,mBAAmB,EAAE,OAAO,GAAG,SAAS,CAAC,GAAG;IAC/C,WAAW,CAAC,EAAE,OAAO,CAAC;CACvB,CAQF,CAAC;AAEF;;;;;;GAMG;AACH,eAAO,MAAM,uBAAuB,EAAE,aAAa,CACjD,IAAI,CAAC,mBAAmB,EAAE,OAAO,GAAG,SAAS,CAAC,GAAG;IAC/C,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB,CAQF,CAAC;AAEF;;;;;;GAMG;AACH,eAAO,MAAM,uBAAuB,EAAE,aAAa,CACjD,IAAI,CAAC,mBAAmB,EAAE,OAAO,GAAG,SAAS,CAAC,GAAG;IAC/C,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB,CAQF,CAAC;AAEF;;;;;;GAMG;AACH,eAAO,MAAM,wBAAwB,EAAE,aAAa,CAClD,IAAI,CAAC,mBAAmB,EAAE,OAAO,GAAG,SAAS,CAAC,GAAG;IAC/C,WAAW,CAAC,EAAE,OAAO,CAAC;CACvB,CAQF,CAAC;AAEF,eAAe,cAAc,CAAC"}
|
|
@@ -9,7 +9,6 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
|
9
9
|
* @since 0.0.1
|
|
10
10
|
* @author AMBROISE PARK Consulting
|
|
11
11
|
*/
|
|
12
|
-
import {} from 'react';
|
|
13
12
|
import { cn } from '@donotdev/components';
|
|
14
13
|
/**
|
|
15
14
|
* LoadingMessage - Displays contextual loading messages with microcopy
|
|
@@ -1,12 +1,4 @@
|
|
|
1
|
-
|
|
2
|
-
* @fileoverview LoadingScreen component
|
|
3
|
-
* @description Full-page loading screen component
|
|
4
|
-
*
|
|
5
|
-
* @version 0.0.1
|
|
6
|
-
* @since 0.0.1
|
|
7
|
-
* @author AMBROISE PARK Consulting
|
|
8
|
-
*/
|
|
9
|
-
import { type ComponentType } from 'react';
|
|
1
|
+
import type { ComponentType } from 'react';
|
|
10
2
|
interface LoadingScreenProps {
|
|
11
3
|
/** Determines whether to render a full-page or inline loader */
|
|
12
4
|
variant?: 'fullPage' | 'inline';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"LoadingScreen.d.ts","sourceRoot":"","sources":["../../../src/components/common/LoadingScreen.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"LoadingScreen.d.ts","sourceRoot":"","sources":["../../../src/components/common/LoadingScreen.tsx"],"names":[],"mappings":"AAcA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,OAAO,CAAC;AAE3C,UAAU,kBAAkB;IAC1B,gEAAgE;IAChE,OAAO,CAAC,EAAE,UAAU,GAAG,QAAQ,CAAC;IAChC,gDAAgD;IAChD,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,qDAAqD;IACrD,SAAS,CAAC,EAAE,OAAO,CAAC;CACrB;AAED;;;;;;;GAOG;AACH,QAAA,MAAM,aAAa,EAAE,aAAa,CAAC,kBAAkB,CA0CpD,CAAC;AAEF,eAAe,aAAa,CAAC"}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* RedirectOverlay - Industry-standard redirect overlay with phase progression
|
|
3
|
+
*
|
|
4
|
+
* Features:
|
|
5
|
+
* - Phase-based progress: connecting → preparing → redirecting → timeout
|
|
6
|
+
* - Cancel button appears after 10s (configurable)
|
|
7
|
+
* - i18n support with operation-specific messaging
|
|
8
|
+
* - Browser event handling (popstate, visibilitychange)
|
|
9
|
+
* - Accessible (ARIA labels, role="status")
|
|
10
|
+
* - RTL-safe styling
|
|
11
|
+
*
|
|
12
|
+
* @example
|
|
13
|
+
* ```tsx
|
|
14
|
+
* // Include once in app root (layout.tsx or App.tsx)
|
|
15
|
+
* import { RedirectOverlay } from '@donotdev/ui';
|
|
16
|
+
*
|
|
17
|
+
* function RootLayout({ children }) {
|
|
18
|
+
* return (
|
|
19
|
+
* <>
|
|
20
|
+
* {children}
|
|
21
|
+
* <RedirectOverlay />
|
|
22
|
+
* </>
|
|
23
|
+
* );
|
|
24
|
+
* }
|
|
25
|
+
*
|
|
26
|
+
* // Hooks trigger it automatically
|
|
27
|
+
* const checkout = useStripeBilling('checkout', authState);
|
|
28
|
+
* await checkout({ priceId: 'price_123' }); // Shows overlay automatically
|
|
29
|
+
* ```
|
|
30
|
+
*
|
|
31
|
+
* @version 0.0.1
|
|
32
|
+
* @since 0.0.1
|
|
33
|
+
* @author AMBROISE PARK Consulting
|
|
34
|
+
*/
|
|
35
|
+
export declare function RedirectOverlay(): import("react/jsx-runtime").JSX.Element | null;
|
|
36
|
+
export default RedirectOverlay;
|
|
37
|
+
//# sourceMappingURL=RedirectOverlay.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"RedirectOverlay.d.ts","sourceRoot":"","sources":["../../../src/components/common/RedirectOverlay.tsx"],"names":[],"mappings":"AAoEA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiCG;AACH,wBAAgB,eAAe,mDA+P9B;AAED,eAAe,eAAe,CAAC"}
|
|
@@ -0,0 +1,243 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
+
// packages/ui/src/components/common/RedirectOverlay.tsx
|
|
4
|
+
/**
|
|
5
|
+
* @fileoverview RedirectOverlay component
|
|
6
|
+
* @description Industry-standard fullscreen overlay for redirect operations (payments, OAuth, etc.).
|
|
7
|
+
* Features phase-based progress, 10s cancel timeout, i18n support, and browser event handling.
|
|
8
|
+
*
|
|
9
|
+
* @version 0.0.1
|
|
10
|
+
* @since 0.0.1
|
|
11
|
+
* @author AMBROISE PARK Consulting
|
|
12
|
+
*/
|
|
13
|
+
import { Lock, Shield } from 'lucide-react';
|
|
14
|
+
import { useEffect, useRef, useCallback } from 'react';
|
|
15
|
+
import { Portal, Spinner, Stack, Text, Button } from '@donotdev/components';
|
|
16
|
+
import { useTranslation, useOverlay, } from '@donotdev/core';
|
|
17
|
+
/** Phase progression timings (ms from start) */
|
|
18
|
+
const PHASE_TIMINGS = {
|
|
19
|
+
connecting: 0,
|
|
20
|
+
preparing: 2000,
|
|
21
|
+
redirecting: 5000,
|
|
22
|
+
};
|
|
23
|
+
/** Default timeout before showing cancel button (10 seconds) */
|
|
24
|
+
const DEFAULT_CANCEL_TIMEOUT = 10000;
|
|
25
|
+
/**
|
|
26
|
+
* Get icon component based on operation type
|
|
27
|
+
*/
|
|
28
|
+
function getOperationIcon(operation, configIcon) {
|
|
29
|
+
if (configIcon === 'none')
|
|
30
|
+
return null;
|
|
31
|
+
if (configIcon === 'shield')
|
|
32
|
+
return Shield;
|
|
33
|
+
if (configIcon === 'lock')
|
|
34
|
+
return Lock;
|
|
35
|
+
// Infer from operation
|
|
36
|
+
if (!operation)
|
|
37
|
+
return Lock;
|
|
38
|
+
if (operation.startsWith('stripe-') ||
|
|
39
|
+
operation.includes('payment') ||
|
|
40
|
+
operation.includes('checkout')) {
|
|
41
|
+
return Lock;
|
|
42
|
+
}
|
|
43
|
+
if (operation.startsWith('oauth-') || operation.startsWith('auth-')) {
|
|
44
|
+
return Shield;
|
|
45
|
+
}
|
|
46
|
+
return Lock;
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Get i18n key for operation
|
|
50
|
+
*/
|
|
51
|
+
function getOperationKey(operation) {
|
|
52
|
+
if (!operation)
|
|
53
|
+
return 'default';
|
|
54
|
+
// Check if operation has a specific translation, otherwise use default
|
|
55
|
+
return operation;
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* RedirectOverlay - Industry-standard redirect overlay with phase progression
|
|
59
|
+
*
|
|
60
|
+
* Features:
|
|
61
|
+
* - Phase-based progress: connecting → preparing → redirecting → timeout
|
|
62
|
+
* - Cancel button appears after 10s (configurable)
|
|
63
|
+
* - i18n support with operation-specific messaging
|
|
64
|
+
* - Browser event handling (popstate, visibilitychange)
|
|
65
|
+
* - Accessible (ARIA labels, role="status")
|
|
66
|
+
* - RTL-safe styling
|
|
67
|
+
*
|
|
68
|
+
* @example
|
|
69
|
+
* ```tsx
|
|
70
|
+
* // Include once in app root (layout.tsx or App.tsx)
|
|
71
|
+
* import { RedirectOverlay } from '@donotdev/ui';
|
|
72
|
+
*
|
|
73
|
+
* function RootLayout({ children }) {
|
|
74
|
+
* return (
|
|
75
|
+
* <>
|
|
76
|
+
* {children}
|
|
77
|
+
* <RedirectOverlay />
|
|
78
|
+
* </>
|
|
79
|
+
* );
|
|
80
|
+
* }
|
|
81
|
+
*
|
|
82
|
+
* // Hooks trigger it automatically
|
|
83
|
+
* const checkout = useStripeBilling('checkout', authState);
|
|
84
|
+
* await checkout({ priceId: 'price_123' }); // Shows overlay automatically
|
|
85
|
+
* ```
|
|
86
|
+
*
|
|
87
|
+
* @version 0.0.1
|
|
88
|
+
* @since 0.0.1
|
|
89
|
+
* @author AMBROISE PARK Consulting
|
|
90
|
+
*/
|
|
91
|
+
export function RedirectOverlay() {
|
|
92
|
+
const { t } = useTranslation('dndev');
|
|
93
|
+
// Subscribe to overlay store
|
|
94
|
+
const isOpen = useOverlay('isRedirectOverlayOpen');
|
|
95
|
+
const operation = useOverlay('redirectOperation');
|
|
96
|
+
const phase = useOverlay('redirectPhase');
|
|
97
|
+
const showCancelButton = useOverlay('showCancelButton');
|
|
98
|
+
const config = useOverlay('redirectConfig');
|
|
99
|
+
const startTime = useOverlay('redirectStartTime');
|
|
100
|
+
// Actions
|
|
101
|
+
const setRedirectPhase = useOverlay('setRedirectPhase');
|
|
102
|
+
const setShowCancelButton = useOverlay('setShowCancelButton');
|
|
103
|
+
const hideRedirectOverlay = useOverlay('hideRedirectOverlay');
|
|
104
|
+
// Refs for cleanup
|
|
105
|
+
const phaseTimersRef = useRef([]);
|
|
106
|
+
const cancelTimerRef = useRef(null);
|
|
107
|
+
// Cancel handler
|
|
108
|
+
const handleCancel = useCallback(() => {
|
|
109
|
+
hideRedirectOverlay();
|
|
110
|
+
}, [hideRedirectOverlay]);
|
|
111
|
+
// Setup phase progression and cancel timer when overlay opens
|
|
112
|
+
useEffect(() => {
|
|
113
|
+
if (!isOpen || !startTime)
|
|
114
|
+
return;
|
|
115
|
+
const cancelTimeout = config?.cancelTimeout ?? DEFAULT_CANCEL_TIMEOUT;
|
|
116
|
+
const elapsed = Date.now() - startTime;
|
|
117
|
+
// Clear any existing timers
|
|
118
|
+
phaseTimersRef.current.forEach(clearTimeout);
|
|
119
|
+
phaseTimersRef.current = [];
|
|
120
|
+
if (cancelTimerRef.current) {
|
|
121
|
+
clearTimeout(cancelTimerRef.current);
|
|
122
|
+
cancelTimerRef.current = null;
|
|
123
|
+
}
|
|
124
|
+
// Schedule phase transitions
|
|
125
|
+
const schedulePhase = (targetPhase, delay) => {
|
|
126
|
+
const adjustedDelay = Math.max(0, delay - elapsed);
|
|
127
|
+
if (adjustedDelay > 0) {
|
|
128
|
+
const timer = setTimeout(() => {
|
|
129
|
+
setRedirectPhase(targetPhase);
|
|
130
|
+
}, adjustedDelay);
|
|
131
|
+
phaseTimersRef.current.push(timer);
|
|
132
|
+
}
|
|
133
|
+
else {
|
|
134
|
+
// Already past this phase
|
|
135
|
+
setRedirectPhase(targetPhase);
|
|
136
|
+
}
|
|
137
|
+
};
|
|
138
|
+
schedulePhase('preparing', PHASE_TIMINGS.preparing);
|
|
139
|
+
schedulePhase('redirecting', PHASE_TIMINGS.redirecting);
|
|
140
|
+
// Schedule cancel button
|
|
141
|
+
const cancelDelay = Math.max(0, cancelTimeout - elapsed);
|
|
142
|
+
cancelTimerRef.current = setTimeout(() => {
|
|
143
|
+
setShowCancelButton(true);
|
|
144
|
+
setRedirectPhase('timeout');
|
|
145
|
+
}, cancelDelay);
|
|
146
|
+
// Cleanup
|
|
147
|
+
return () => {
|
|
148
|
+
phaseTimersRef.current.forEach(clearTimeout);
|
|
149
|
+
phaseTimersRef.current = [];
|
|
150
|
+
if (cancelTimerRef.current) {
|
|
151
|
+
clearTimeout(cancelTimerRef.current);
|
|
152
|
+
cancelTimerRef.current = null;
|
|
153
|
+
}
|
|
154
|
+
};
|
|
155
|
+
}, [
|
|
156
|
+
isOpen,
|
|
157
|
+
startTime,
|
|
158
|
+
config?.cancelTimeout,
|
|
159
|
+
setRedirectPhase,
|
|
160
|
+
setShowCancelButton,
|
|
161
|
+
]);
|
|
162
|
+
// Handle browser back button (popstate)
|
|
163
|
+
useEffect(() => {
|
|
164
|
+
if (!isOpen)
|
|
165
|
+
return;
|
|
166
|
+
const handlePopState = () => {
|
|
167
|
+
// User pressed back - hide overlay
|
|
168
|
+
hideRedirectOverlay();
|
|
169
|
+
};
|
|
170
|
+
window.addEventListener('popstate', handlePopState);
|
|
171
|
+
return () => window.removeEventListener('popstate', handlePopState);
|
|
172
|
+
}, [isOpen, hideRedirectOverlay]);
|
|
173
|
+
// Handle tab visibility change
|
|
174
|
+
useEffect(() => {
|
|
175
|
+
if (!isOpen)
|
|
176
|
+
return;
|
|
177
|
+
const handleVisibilityChange = () => {
|
|
178
|
+
// If user switches away and comes back, the redirect probably failed
|
|
179
|
+
// We could add logic here to show a "retry" state, but for now we keep overlay visible
|
|
180
|
+
// This prevents the overlay from disappearing when user tabs away briefly
|
|
181
|
+
};
|
|
182
|
+
document.addEventListener('visibilitychange', handleVisibilityChange);
|
|
183
|
+
return () => document.removeEventListener('visibilitychange', handleVisibilityChange);
|
|
184
|
+
}, [isOpen]);
|
|
185
|
+
// Don't render if not open
|
|
186
|
+
if (!isOpen)
|
|
187
|
+
return null;
|
|
188
|
+
// Get operation-specific translations
|
|
189
|
+
const operationKey = getOperationKey(operation);
|
|
190
|
+
// Try operation-specific translation, fallback to default
|
|
191
|
+
const title = config?.title ??
|
|
192
|
+
t(`redirectOverlay.${operationKey}.title`, {
|
|
193
|
+
defaultValue: t('redirectOverlay.default.title'),
|
|
194
|
+
});
|
|
195
|
+
const message = config?.message ??
|
|
196
|
+
t(`redirectOverlay.${operationKey}.message`, {
|
|
197
|
+
defaultValue: t('redirectOverlay.default.message'),
|
|
198
|
+
});
|
|
199
|
+
const subtitle = config?.subtitle ??
|
|
200
|
+
t(`redirectOverlay.${operationKey}.subtitle`, {
|
|
201
|
+
defaultValue: t('redirectOverlay.default.subtitle'),
|
|
202
|
+
});
|
|
203
|
+
const ariaLabel = t(`redirectOverlay.${operationKey}.ariaLabel`, {
|
|
204
|
+
defaultValue: t('redirectOverlay.default.ariaLabel'),
|
|
205
|
+
});
|
|
206
|
+
// Get phase message
|
|
207
|
+
const phaseMessage = t(`redirectOverlay.phases.${phase}`);
|
|
208
|
+
// Get icon
|
|
209
|
+
const IconComponent = getOperationIcon(operation, config?.icon);
|
|
210
|
+
return (_jsx(Portal, { children: _jsx("div", { className: "dndev-spinner-overlay", role: "status", "aria-busy": "true", "aria-label": ariaLabel, style: {
|
|
211
|
+
// Ensure highest z-index for redirect overlay
|
|
212
|
+
zIndex: 'var(--z-overlay, 9999)',
|
|
213
|
+
}, children: _jsxs("div", { style: {
|
|
214
|
+
display: 'flex',
|
|
215
|
+
flexDirection: 'column',
|
|
216
|
+
alignItems: 'center',
|
|
217
|
+
justifyContent: 'center',
|
|
218
|
+
gap: 'var(--gap-md)',
|
|
219
|
+
textAlign: 'center',
|
|
220
|
+
maxWidth: '400px',
|
|
221
|
+
padding: 'var(--gap-lg)',
|
|
222
|
+
}, children: [_jsxs(Stack, { direction: "row", gap: "medium", align: "center", children: [IconComponent && (_jsx(IconComponent, { style: {
|
|
223
|
+
width: '1.5rem',
|
|
224
|
+
height: '1.5rem',
|
|
225
|
+
color: 'var(--primary)',
|
|
226
|
+
}, "aria-hidden": "true" })), _jsx(Spinner, { variant: "primary" })] }), _jsx(Text, { as: "h3", style: {
|
|
227
|
+
color: 'var(--foreground)',
|
|
228
|
+
margin: 0,
|
|
229
|
+
}, children: title }), _jsx(Text, { variant: "muted", style: {
|
|
230
|
+
color: 'var(--foreground)',
|
|
231
|
+
minHeight: '1.5em',
|
|
232
|
+
}, children: phaseMessage }), _jsx(Text, { variant: "muted", level: "small", style: {
|
|
233
|
+
opacity: 0.8,
|
|
234
|
+
}, children: message }), _jsx(Text, { variant: "muted", level: "small", style: {
|
|
235
|
+
opacity: 0.6,
|
|
236
|
+
}, children: subtitle }), _jsx(Text, { variant: "muted", level: "small", style: {
|
|
237
|
+
opacity: 0.5,
|
|
238
|
+
marginTop: 'var(--gap-sm)',
|
|
239
|
+
}, children: t('redirectOverlay.doNotRefresh') }), showCancelButton && (_jsx(Button, { variant: "ghost", onClick: handleCancel, style: {
|
|
240
|
+
marginTop: 'var(--gap-md)',
|
|
241
|
+
}, children: t('redirectOverlay.cancel') }))] }) }) }));
|
|
242
|
+
}
|
|
243
|
+
export default RedirectOverlay;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"TechBento.d.ts","sourceRoot":"","sources":["../../../src/components/common/TechBento.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"TechBento.d.ts","sourceRoot":"","sources":["../../../src/components/common/TechBento.tsx"],"names":[],"mappings":"AAKA,OAAO,KAAK,EACV,YAAY,EACZ,QAAQ,EACR,WAAW,EACX,cAAc,EACf,MAAM,sBAAsB,CAAC;AAE9B,OAAO,EAAa,KAAK,OAAO,EAAE,MAAM,sBAAsB,CAAC;AAI/D,MAAM,MAAM,cAAc,GAAG;IAC3B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,KAAK,CAAC;QACX,IAAI,EAAE,OAAO,CAAC;QACd,IAAI,CAAC,EAAE,QAAQ,GAAG,MAAM,GAAG,MAAM,GAAG,MAAM,CAAC;QAC3C,OAAO,CAAC,EAAE,WAAW,CAAC;KACvB,CAAC,CAAC;IACH;;;;;;;OAOG;IACH,IAAI,CAAC,EAAE,MAAM,GAAG,cAAc,CAAC;IAC/B;;OAEG;IACH,OAAO,CAAC,EAAE,YAAY,CAAC;IACvB,GAAG,CAAC,EAAE,QAAQ,CAAC;IACf,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB,CAAC;AAwCF,wBAAgB,SAAS,CAAC,EACxB,KAAK,EACL,KAAK,EACL,IAAQ,EACR,OAAO,EACP,GAAc,EACd,SAAiB,EACjB,SAAS,GACV,EAAE,cAAc,2CAsDhB;AAED,eAAe,SAAS,CAAC"}
|