@djangocfg/layouts 2.1.37 → 2.1.38
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/README.md +204 -18
- package/package.json +5 -5
- package/src/components/errors/index.ts +9 -0
- package/src/components/errors/types.ts +38 -0
- package/src/layouts/AppLayout/AppLayout.tsx +33 -45
- package/src/layouts/AppLayout/BaseApp.tsx +104 -33
- package/src/layouts/AuthLayout/AuthContext.tsx +7 -1
- package/src/layouts/AuthLayout/OAuthProviders.tsx +1 -10
- package/src/layouts/AuthLayout/OTPForm.tsx +1 -0
- package/src/layouts/PrivateLayout/PrivateLayout.tsx +1 -1
- package/src/layouts/PublicLayout/PublicLayout.tsx +1 -1
- package/src/layouts/PublicLayout/components/PublicMobileDrawer.tsx +1 -1
- package/src/layouts/PublicLayout/components/PublicNavigation.tsx +1 -1
- package/src/layouts/_components/UserMenu.tsx +1 -1
- package/src/layouts/index.ts +1 -1
- package/src/layouts/types/index.ts +47 -0
- package/src/layouts/types/layout.types.ts +61 -0
- package/src/layouts/types/providers.types.ts +65 -0
- package/src/layouts/types/ui.types.ts +103 -0
- package/src/snippets/Analytics/index.ts +1 -0
- package/src/snippets/Analytics/types.ts +10 -0
- package/src/snippets/PWAInstall/@docs/README.md +92 -0
- package/src/snippets/PWAInstall/README.md +185 -0
- package/src/snippets/{PWA → PWAInstall}/components/A2HSHint.tsx +85 -84
- package/src/snippets/PWAInstall/components/DesktopGuide.tsx +229 -0
- package/src/snippets/PWAInstall/context/InstallContext.tsx +102 -0
- package/src/snippets/{PWA → PWAInstall}/hooks/useInstallPrompt.ts +3 -0
- package/src/snippets/{PWA → PWAInstall}/index.ts +12 -31
- package/src/snippets/{PWA → PWAInstall}/types/components.ts +0 -6
- package/src/snippets/PWAInstall/types/config.ts +22 -0
- package/src/snippets/{PWA → PWAInstall}/types/index.ts +4 -4
- package/src/snippets/{PWA → PWAInstall}/utils/localStorage.ts +1 -23
- package/src/snippets/PushNotifications/@docs/README.md +191 -0
- package/src/snippets/PushNotifications/@docs/guides/django-integration.md +648 -0
- package/src/snippets/PushNotifications/@docs/guides/service-worker.md +467 -0
- package/src/snippets/PushNotifications/@docs/guides/vapid-setup.md +352 -0
- package/src/snippets/PushNotifications/README.md +328 -0
- package/src/snippets/{PWA → PushNotifications}/config.ts +2 -2
- package/src/snippets/PushNotifications/context/DjangoPushContext.tsx +190 -0
- package/src/snippets/{PWA → PushNotifications}/hooks/useDjangoPush.ts +63 -81
- package/src/snippets/{PWA → PushNotifications}/hooks/usePushNotifications.ts +12 -8
- package/src/snippets/PushNotifications/index.ts +87 -0
- package/src/snippets/PushNotifications/types/config.ts +28 -0
- package/src/snippets/PushNotifications/types/index.ts +9 -0
- package/src/snippets/PushNotifications/utils/localStorage.ts +60 -0
- package/src/snippets/PushNotifications/utils/logger.ts +149 -0
- package/src/snippets/PushNotifications/utils/platform.ts +151 -0
- package/src/snippets/index.ts +37 -12
- package/src/layouts/shared/index.ts +0 -21
- package/src/layouts/shared/types.ts +0 -247
- package/src/snippets/PWA/@refactoring/ARCHITECTURE_ANALYSIS.md +0 -1179
- package/src/snippets/PWA/@refactoring/EXECUTIVE_SUMMARY.md +0 -271
- package/src/snippets/PWA/@refactoring/README.md +0 -204
- package/src/snippets/PWA/@refactoring/REFACTORING_PROPOSALS.md +0 -1109
- package/src/snippets/PWA/@refactoring2/COMPARISON-WITH-NEXTJS.md +0 -718
- package/src/snippets/PWA/@refactoring2/P1-FIXES-COMPLETED.md +0 -188
- package/src/snippets/PWA/@refactoring2/POST-P0-ANALYSIS.md +0 -362
- package/src/snippets/PWA/@refactoring2/README.md +0 -85
- package/src/snippets/PWA/@refactoring2/RECOMMENDATIONS.md +0 -1321
- package/src/snippets/PWA/@refactoring2/REMAINING-ISSUES.md +0 -557
- package/src/snippets/PWA/README.md +0 -387
- package/src/snippets/PWA/context/DjangoPushContext.tsx +0 -105
- package/src/snippets/PWA/context/InstallContext.tsx +0 -118
- package/src/snippets/PWA/context/PushContext.tsx +0 -156
- /package/src/layouts/{shared → types}/README.md +0 -0
- /package/src/snippets/{PWA/@docs/research.md → PWAInstall/@docs/research/ios-android-install-flows.md} +0 -0
- /package/src/snippets/{PWA → PWAInstall}/components/IOSGuide.tsx +0 -0
- /package/src/snippets/{PWA → PWAInstall}/components/IOSGuideDrawer.tsx +0 -0
- /package/src/snippets/{PWA → PWAInstall}/components/IOSGuideModal.tsx +0 -0
- /package/src/snippets/{PWA → PWAInstall}/hooks/useIsPWA.ts +0 -0
- /package/src/snippets/{PWA → PWAInstall}/types/install.ts +0 -0
- /package/src/snippets/{PWA → PWAInstall}/types/platform.ts +0 -0
- /package/src/snippets/{PWA → PWAInstall}/utils/logger.ts +0 -0
- /package/src/snippets/{PWA → PWAInstall}/utils/platform.ts +0 -0
- /package/src/snippets/{PWA → PushNotifications}/components/PushPrompt.tsx +0 -0
- /package/src/snippets/{PWA → PushNotifications}/types/push.ts +0 -0
- /package/src/snippets/{PWA → PushNotifications}/utils/vapid.ts +0 -0
|
@@ -6,7 +6,11 @@
|
|
|
6
6
|
* - TooltipProvider (tooltip positioning)
|
|
7
7
|
* - SWRConfig (data fetching)
|
|
8
8
|
* - AuthProvider (authentication context)
|
|
9
|
-
* -
|
|
9
|
+
* - AuthDialog (global auth prompt dialog)
|
|
10
|
+
* - AnalyticsProvider (Google Analytics, optional)
|
|
11
|
+
* - CentrifugoProvider (WebSocket real-time, optional)
|
|
12
|
+
* - PwaProvider (PWA installation, optional)
|
|
13
|
+
* - DjangoPushProvider (Django web push integration, optional)
|
|
10
14
|
* - ErrorTrackingProvider (error handling)
|
|
11
15
|
* - ErrorBoundary (React error boundary, enabled by default)
|
|
12
16
|
* - MCP Chat Widget (optional, lazy loaded)
|
|
@@ -15,11 +19,17 @@
|
|
|
15
19
|
* ```tsx
|
|
16
20
|
* import { BaseApp } from '@djangocfg/layouts';
|
|
17
21
|
*
|
|
18
|
-
* // With PWA and
|
|
22
|
+
* // With PWA Install and Push Notifications
|
|
19
23
|
* <BaseApp
|
|
20
24
|
* theme={{ defaultTheme: 'system' }}
|
|
21
25
|
* auth={{ loginPath: '/auth/login' }}
|
|
22
|
-
*
|
|
26
|
+
* analytics={{ googleTrackingId: 'G-XXXXXXXXXX' }}
|
|
27
|
+
* pwaInstall={{ enabled: true, logo: '/logo192.png' }}
|
|
28
|
+
* pushNotifications={{
|
|
29
|
+
* enabled: true,
|
|
30
|
+
* vapidPublicKey: process.env.NEXT_PUBLIC_VAPID_KEY,
|
|
31
|
+
* requirePWA: true
|
|
32
|
+
* }}
|
|
23
33
|
* mcpChat={{ enabled: true, autoDetectEnvironment: true }}
|
|
24
34
|
* >
|
|
25
35
|
* {children}
|
|
@@ -37,13 +47,18 @@
|
|
|
37
47
|
import { ReactNode } from 'react';
|
|
38
48
|
import dynamic from 'next/dynamic';
|
|
39
49
|
import { SWRConfig } from 'swr';
|
|
40
|
-
import { ThemeProvider,
|
|
50
|
+
import { ThemeProvider, SonnerToaster, TooltipProvider } from '@djangocfg/ui-nextjs';
|
|
41
51
|
import { AuthProvider } from '@djangocfg/api/auth';
|
|
52
|
+
import { CentrifugoProvider } from '@djangocfg/centrifugo';
|
|
53
|
+
import { getCentrifugoAuthTokenRetrieve } from '@djangocfg/api';
|
|
42
54
|
import { ErrorTrackingProvider } from '../../components/errors/ErrorsTracker';
|
|
43
55
|
import { ErrorBoundary } from '../../components/errors/ErrorBoundary';
|
|
44
56
|
import { PageProgress } from '../../components/core/PageProgress';
|
|
45
|
-
import {
|
|
46
|
-
import
|
|
57
|
+
import { AnalyticsProvider } from '../../snippets/Analytics';
|
|
58
|
+
import { PwaProvider, A2HSHint } from '../../snippets/PWAInstall';
|
|
59
|
+
import { DjangoPushProvider, PushPrompt } from '../../snippets/PushNotifications';
|
|
60
|
+
import { AuthDialog } from '../../snippets/AuthDialog';
|
|
61
|
+
import type { BaseLayoutProps } from '../types/layout.types';
|
|
47
62
|
|
|
48
63
|
// Lazy load MCP Chat Widget with dynamic import
|
|
49
64
|
const AIChatWidget = dynamic(
|
|
@@ -57,22 +72,38 @@ export type BaseAppProps = BaseLayoutProps;
|
|
|
57
72
|
/**
|
|
58
73
|
* BaseApp - Core providers wrapper for any React/Next.js app
|
|
59
74
|
*
|
|
60
|
-
* Includes: ThemeProvider, TooltipProvider, SWRConfig, AuthProvider,
|
|
75
|
+
* Includes: ThemeProvider, TooltipProvider, SWRConfig, AuthProvider, AnalyticsProvider,
|
|
76
|
+
* CentrifugoProvider, PwaProvider, PushProvider, ErrorTrackingProvider,
|
|
77
|
+
* ErrorBoundary (optional), MCP Chat (optional)
|
|
61
78
|
* Also renders global Toaster and PageProgress components
|
|
62
79
|
*/
|
|
63
80
|
export function BaseApp({
|
|
64
81
|
children,
|
|
65
82
|
theme,
|
|
66
83
|
auth,
|
|
84
|
+
analytics,
|
|
85
|
+
centrifugo,
|
|
67
86
|
errorTracking,
|
|
68
87
|
errorBoundary,
|
|
69
88
|
swr,
|
|
70
89
|
mcpChat,
|
|
71
|
-
|
|
90
|
+
pwaInstall,
|
|
91
|
+
pushNotifications,
|
|
72
92
|
}: BaseAppProps) {
|
|
73
93
|
// ErrorBoundary is enabled by default
|
|
74
94
|
const enableErrorBoundary = errorBoundary?.enabled !== false;
|
|
75
95
|
|
|
96
|
+
// Check if PWA Install is enabled
|
|
97
|
+
const pwaInstallEnabled = pwaInstall?.enabled !== false;
|
|
98
|
+
const showInstallHint = pwaInstallEnabled && pwaInstall?.showInstallHint !== false;
|
|
99
|
+
|
|
100
|
+
// Check if Push Notifications is enabled
|
|
101
|
+
const pushEnabled = pushNotifications?.enabled !== false && !!pushNotifications?.vapidPublicKey;
|
|
102
|
+
|
|
103
|
+
// Centrifugo configuration
|
|
104
|
+
const centrifugoUrl = centrifugo?.url || process.env.NEXT_PUBLIC_CENTRIFUGO_URL;
|
|
105
|
+
const centrifugoEnabled = centrifugo?.enabled !== false;
|
|
106
|
+
|
|
76
107
|
const content = (
|
|
77
108
|
<ThemeProvider
|
|
78
109
|
defaultTheme={theme?.defaultTheme || 'system'}
|
|
@@ -87,33 +118,73 @@ export function BaseApp({
|
|
|
87
118
|
}}
|
|
88
119
|
>
|
|
89
120
|
<AuthProvider config={auth}>
|
|
90
|
-
<
|
|
91
|
-
<
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
121
|
+
<AnalyticsProvider trackingId={analytics?.googleTrackingId}>
|
|
122
|
+
<CentrifugoProvider
|
|
123
|
+
enabled={centrifugoEnabled}
|
|
124
|
+
autoConnect={centrifugoEnabled && centrifugo?.autoConnect}
|
|
125
|
+
url={centrifugoUrl}
|
|
126
|
+
onTokenRefresh={async () => {
|
|
127
|
+
const response = await getCentrifugoAuthTokenRetrieve();
|
|
128
|
+
return response.token;
|
|
129
|
+
}}
|
|
96
130
|
>
|
|
97
|
-
{
|
|
98
|
-
|
|
99
|
-
|
|
131
|
+
<PwaProvider enabled={pwaInstallEnabled}>
|
|
132
|
+
<DjangoPushProvider
|
|
133
|
+
vapidPublicKey={pushNotifications?.vapidPublicKey || ''}
|
|
134
|
+
autoSubscribe={pushNotifications?.autoSubscribe}
|
|
135
|
+
>
|
|
136
|
+
<ErrorTrackingProvider
|
|
137
|
+
validation={errorTracking?.validation}
|
|
138
|
+
cors={errorTracking?.cors}
|
|
139
|
+
network={errorTracking?.network}
|
|
140
|
+
onError={errorTracking?.onError}
|
|
141
|
+
>
|
|
142
|
+
{children}
|
|
143
|
+
<PageProgress />
|
|
144
|
+
<SonnerToaster />
|
|
145
|
+
|
|
146
|
+
{/* PWA Install Hint */}
|
|
147
|
+
{showInstallHint && (
|
|
148
|
+
<A2HSHint
|
|
149
|
+
resetAfterDays={pwaInstall?.resetAfterDays}
|
|
150
|
+
delayMs={pwaInstall?.delayMs}
|
|
151
|
+
logo={pwaInstall?.logo}
|
|
152
|
+
/>
|
|
153
|
+
)}
|
|
154
|
+
|
|
155
|
+
{/* Push Notifications Prompt */}
|
|
156
|
+
{pushEnabled && (
|
|
157
|
+
<PushPrompt
|
|
158
|
+
vapidPublicKey={pushNotifications!.vapidPublicKey}
|
|
159
|
+
subscribeEndpoint={pushNotifications?.subscribeEndpoint}
|
|
160
|
+
requirePWA={pushNotifications?.requirePWA ?? true}
|
|
161
|
+
delayMs={pushNotifications?.delayMs}
|
|
162
|
+
resetAfterDays={pushNotifications?.resetAfterDays}
|
|
163
|
+
/>
|
|
164
|
+
)}
|
|
165
|
+
|
|
166
|
+
{/* MCP Chat Widget - lazy loaded */}
|
|
167
|
+
{mcpChat?.enabled && (
|
|
168
|
+
<AIChatWidget
|
|
169
|
+
apiEndpoint={mcpChat.apiEndpoint}
|
|
170
|
+
title={mcpChat.title}
|
|
171
|
+
placeholder={mcpChat.placeholder}
|
|
172
|
+
greeting={mcpChat.greeting}
|
|
173
|
+
position={mcpChat.position}
|
|
174
|
+
variant={mcpChat.variant}
|
|
175
|
+
enableStreaming={mcpChat.enableStreaming}
|
|
176
|
+
autoDetectEnvironment={mcpChat.autoDetectEnvironment}
|
|
177
|
+
className={mcpChat.className}
|
|
178
|
+
/>
|
|
179
|
+
)}
|
|
100
180
|
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
position={mcpChat.position}
|
|
109
|
-
variant={mcpChat.variant}
|
|
110
|
-
enableStreaming={mcpChat.enableStreaming}
|
|
111
|
-
autoDetectEnvironment={mcpChat.autoDetectEnvironment}
|
|
112
|
-
className={mcpChat.className}
|
|
113
|
-
/>
|
|
114
|
-
)}
|
|
115
|
-
</ErrorTrackingProvider>
|
|
116
|
-
</PwaProvider>
|
|
181
|
+
{/* Auth Dialog - global auth prompt */}
|
|
182
|
+
<AuthDialog authPath={auth?.routes?.auth} />
|
|
183
|
+
</ErrorTrackingProvider>
|
|
184
|
+
</DjangoPushProvider>
|
|
185
|
+
</PwaProvider>
|
|
186
|
+
</CentrifugoProvider>
|
|
187
|
+
</AnalyticsProvider>
|
|
117
188
|
</AuthProvider>
|
|
118
189
|
</SWRConfig>
|
|
119
190
|
</TooltipProvider>
|
|
@@ -16,18 +16,24 @@ export const AuthProvider: React.FC<AuthProps> = ({
|
|
|
16
16
|
privacyUrl,
|
|
17
17
|
enablePhoneAuth = false, // Default to false for backward compatibility
|
|
18
18
|
enableGithubAuth = false, // Default to false for backward compatibility
|
|
19
|
+
redirectUrl, // URL to redirect after successful OTP auth
|
|
19
20
|
onIdentifierSuccess,
|
|
20
21
|
onOTPSuccess,
|
|
21
22
|
onError,
|
|
22
23
|
}) => {
|
|
23
24
|
const sourceUrl = sourceUrlProp || (typeof window !== 'undefined' ? window.location.origin : '');
|
|
24
25
|
|
|
25
|
-
//
|
|
26
|
+
// Require terms acceptance only if terms or privacy URL is provided
|
|
27
|
+
const requireTermsAcceptance = Boolean(termsUrl || privacyUrl);
|
|
28
|
+
|
|
29
|
+
// Use the auth form hook with required sourceUrl and redirectUrl
|
|
26
30
|
const authForm = useAuthForm({
|
|
27
31
|
onIdentifierSuccess,
|
|
28
32
|
onOTPSuccess,
|
|
29
33
|
onError,
|
|
30
34
|
sourceUrl,
|
|
35
|
+
redirectUrl,
|
|
36
|
+
requireTermsAcceptance,
|
|
31
37
|
});
|
|
32
38
|
|
|
33
39
|
const value: AuthContextType = {
|
|
@@ -15,11 +15,10 @@ import { useAuthContext } from './AuthContext';
|
|
|
15
15
|
* Handles the OAuth flow initiation.
|
|
16
16
|
*/
|
|
17
17
|
export const OAuthProviders: React.FC = () => {
|
|
18
|
-
const { enableGithubAuth, sourceUrl,
|
|
18
|
+
const { enableGithubAuth, sourceUrl, setError } = useAuthContext();
|
|
19
19
|
|
|
20
20
|
const {
|
|
21
21
|
isLoading: isGithubLoading,
|
|
22
|
-
error: githubError,
|
|
23
22
|
startGithubAuth,
|
|
24
23
|
} = useGithubAuth({
|
|
25
24
|
sourceUrl,
|
|
@@ -33,8 +32,6 @@ export const OAuthProviders: React.FC = () => {
|
|
|
33
32
|
return null;
|
|
34
33
|
}
|
|
35
34
|
|
|
36
|
-
const error = githubError || contextError;
|
|
37
|
-
|
|
38
35
|
return (
|
|
39
36
|
<div className="space-y-4">
|
|
40
37
|
{/* Divider */}
|
|
@@ -74,12 +71,6 @@ export const OAuthProviders: React.FC = () => {
|
|
|
74
71
|
)}
|
|
75
72
|
</div>
|
|
76
73
|
|
|
77
|
-
{/* Error Message */}
|
|
78
|
-
{error && (
|
|
79
|
-
<div className="text-sm text-destructive bg-destructive/10 p-3 rounded-md border border-destructive/20">
|
|
80
|
-
{error}
|
|
81
|
-
</div>
|
|
82
|
-
)}
|
|
83
74
|
</div>
|
|
84
75
|
);
|
|
85
76
|
};
|
|
@@ -51,7 +51,7 @@ import { SidebarProvider, SidebarInset, Preloader, ButtonLink } from '@djangocfg
|
|
|
51
51
|
import { useAuth } from '@djangocfg/api/auth';
|
|
52
52
|
import { PrivateSidebar, PrivateHeader, PrivateContent } from './components';
|
|
53
53
|
import type { LucideIcon as LucideIconType } from 'lucide-react';
|
|
54
|
-
import { UserMenuConfig } from '../
|
|
54
|
+
import { UserMenuConfig } from '../types';
|
|
55
55
|
|
|
56
56
|
export interface SidebarItem {
|
|
57
57
|
label: string;
|
|
@@ -30,7 +30,7 @@
|
|
|
30
30
|
|
|
31
31
|
import { ReactNode, useState, useEffect } from 'react';
|
|
32
32
|
import { usePathname } from 'next/navigation';
|
|
33
|
-
import type { NavigationItem, UserMenuConfig } from '../
|
|
33
|
+
import type { NavigationItem, UserMenuConfig } from '../types';
|
|
34
34
|
import {
|
|
35
35
|
PublicNavigation,
|
|
36
36
|
PublicMobileDrawer,
|
|
@@ -20,7 +20,7 @@ import {
|
|
|
20
20
|
import { ThemeToggle } from '@djangocfg/ui-nextjs/theme';
|
|
21
21
|
import { useAuth } from '@djangocfg/api/auth';
|
|
22
22
|
import { UserMenu } from '../../_components/UserMenu';
|
|
23
|
-
import type { NavigationItem, UserMenuConfig } from '../../
|
|
23
|
+
import type { NavigationItem, UserMenuConfig } from '../../types';
|
|
24
24
|
|
|
25
25
|
interface PublicMobileDrawerProps {
|
|
26
26
|
isOpen: boolean;
|
|
@@ -15,7 +15,7 @@ import { cn } from '@djangocfg/ui-nextjs/lib';
|
|
|
15
15
|
import { useIsMobile } from '@djangocfg/ui-nextjs/hooks';
|
|
16
16
|
import { useAuth } from '@djangocfg/api/auth';
|
|
17
17
|
import { UserMenu } from '../../_components/UserMenu';
|
|
18
|
-
import type { NavigationItem, UserMenuConfig } from '../../
|
|
18
|
+
import type { NavigationItem, UserMenuConfig } from '../../types';
|
|
19
19
|
|
|
20
20
|
interface PublicNavigationProps {
|
|
21
21
|
logo?: string;
|
|
@@ -47,7 +47,7 @@ import {
|
|
|
47
47
|
Button,
|
|
48
48
|
} from '@djangocfg/ui-nextjs/components';
|
|
49
49
|
import { useAuth } from '@djangocfg/api/auth';
|
|
50
|
-
import type { UserMenuGroup } from '../
|
|
50
|
+
import type { UserMenuGroup } from '../types';
|
|
51
51
|
|
|
52
52
|
export interface UserMenuProps {
|
|
53
53
|
/** Display variant */
|
package/src/layouts/index.ts
CHANGED
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared Layout Types - Central Export
|
|
3
|
+
*
|
|
4
|
+
* This is the main entry point for all layout types.
|
|
5
|
+
* Types are organized by category and imported from their source modules.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
// ============================================================================
|
|
9
|
+
// Provider Configuration Types
|
|
10
|
+
// ============================================================================
|
|
11
|
+
|
|
12
|
+
// Local provider configs
|
|
13
|
+
export type { ThemeConfig, SWRConfigOptions, McpChatConfig, CentrifugoConfig } from './providers.types';
|
|
14
|
+
|
|
15
|
+
// External provider configs (re-export for convenience)
|
|
16
|
+
export type { AnalyticsConfig } from '../../snippets/Analytics/types';
|
|
17
|
+
export type { PwaInstallConfig } from '../../snippets/PWAInstall/types';
|
|
18
|
+
export type { PushNotificationsConfig } from '../../snippets/PushNotifications/types';
|
|
19
|
+
export type {
|
|
20
|
+
ErrorBoundaryConfig,
|
|
21
|
+
ErrorTrackingConfig,
|
|
22
|
+
ValidationErrorConfig,
|
|
23
|
+
CORSErrorConfig,
|
|
24
|
+
NetworkErrorConfig,
|
|
25
|
+
} from '../../components/errors/types';
|
|
26
|
+
|
|
27
|
+
// ============================================================================
|
|
28
|
+
// UI Component Types
|
|
29
|
+
// ============================================================================
|
|
30
|
+
|
|
31
|
+
export type {
|
|
32
|
+
NavigationItem,
|
|
33
|
+
NavigationSection,
|
|
34
|
+
FooterLink,
|
|
35
|
+
FooterMenuSection,
|
|
36
|
+
FooterSocialLinks,
|
|
37
|
+
FooterConfig,
|
|
38
|
+
UserMenuItem,
|
|
39
|
+
UserMenuGroup,
|
|
40
|
+
UserMenuConfig,
|
|
41
|
+
} from './ui.types';
|
|
42
|
+
|
|
43
|
+
// ============================================================================
|
|
44
|
+
// Layout Types
|
|
45
|
+
// ============================================================================
|
|
46
|
+
|
|
47
|
+
export type { BaseLayoutProps } from './layout.types';
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Base Layout Types
|
|
3
|
+
*
|
|
4
|
+
* Core layout configuration that combines all provider configs
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import type { ReactNode } from 'react';
|
|
8
|
+
import type { AuthConfig } from '@djangocfg/api/auth';
|
|
9
|
+
|
|
10
|
+
// Import provider configs from their modules
|
|
11
|
+
import type { AnalyticsConfig } from '../../snippets/Analytics/types';
|
|
12
|
+
import type { PwaInstallConfig } from '../../snippets/PWAInstall/types';
|
|
13
|
+
import type { PushNotificationsConfig } from '../../snippets/PushNotifications/types';
|
|
14
|
+
import type { ErrorBoundaryConfig, ErrorTrackingConfig } from '../../components/errors/types';
|
|
15
|
+
|
|
16
|
+
// Import local provider configs
|
|
17
|
+
import type { ThemeConfig, SWRConfigOptions, McpChatConfig, CentrifugoConfig } from './providers.types';
|
|
18
|
+
|
|
19
|
+
// ============================================================================
|
|
20
|
+
// Base Layout Props
|
|
21
|
+
// ============================================================================
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Base Layout Props
|
|
25
|
+
*
|
|
26
|
+
* Core configuration for BaseApp component.
|
|
27
|
+
* All provider configs are imported from their respective modules.
|
|
28
|
+
*/
|
|
29
|
+
export interface BaseLayoutProps {
|
|
30
|
+
children: ReactNode;
|
|
31
|
+
|
|
32
|
+
/** Theme configuration */
|
|
33
|
+
theme?: ThemeConfig;
|
|
34
|
+
|
|
35
|
+
/** Auth configuration */
|
|
36
|
+
auth?: AuthConfig;
|
|
37
|
+
|
|
38
|
+
/** Analytics configuration (from snippets/Analytics) */
|
|
39
|
+
analytics?: AnalyticsConfig;
|
|
40
|
+
|
|
41
|
+
/** Centrifugo configuration */
|
|
42
|
+
centrifugo?: CentrifugoConfig;
|
|
43
|
+
|
|
44
|
+
/** Error tracking configuration (from components/errors) */
|
|
45
|
+
errorTracking?: ErrorTrackingConfig;
|
|
46
|
+
|
|
47
|
+
/** SWR configuration */
|
|
48
|
+
swr?: SWRConfigOptions;
|
|
49
|
+
|
|
50
|
+
/** Error boundary configuration (from components/errors, enabled by default) */
|
|
51
|
+
errorBoundary?: ErrorBoundaryConfig;
|
|
52
|
+
|
|
53
|
+
/** MCP chat configuration */
|
|
54
|
+
mcpChat?: McpChatConfig;
|
|
55
|
+
|
|
56
|
+
/** PWA Install configuration (from snippets/PWAInstall) */
|
|
57
|
+
pwaInstall?: PwaInstallConfig;
|
|
58
|
+
|
|
59
|
+
/** Push Notifications configuration (from snippets/PushNotifications) */
|
|
60
|
+
pushNotifications?: PushNotificationsConfig;
|
|
61
|
+
}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Provider Configuration Types
|
|
3
|
+
*
|
|
4
|
+
* Configuration types for layout providers (theme, SWR, MCP chat, Centrifugo)
|
|
5
|
+
* Note: Analytics, PWA, Push, and Error types are defined in their respective modules
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
// ============================================================================
|
|
9
|
+
// Theme Configuration
|
|
10
|
+
// ============================================================================
|
|
11
|
+
|
|
12
|
+
export interface ThemeConfig {
|
|
13
|
+
defaultTheme?: 'light' | 'dark' | 'system';
|
|
14
|
+
storageKey?: string;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
// ============================================================================
|
|
18
|
+
// SWR Configuration
|
|
19
|
+
// ============================================================================
|
|
20
|
+
|
|
21
|
+
export interface SWRConfigOptions {
|
|
22
|
+
revalidateOnFocus?: boolean;
|
|
23
|
+
revalidateOnReconnect?: boolean;
|
|
24
|
+
dedupingInterval?: number;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
// ============================================================================
|
|
28
|
+
// MCP Chat Configuration
|
|
29
|
+
// ============================================================================
|
|
30
|
+
|
|
31
|
+
export interface McpChatConfig {
|
|
32
|
+
/** Enable MCP chat widget */
|
|
33
|
+
enabled?: boolean;
|
|
34
|
+
/** API endpoint for chat */
|
|
35
|
+
apiEndpoint?: string;
|
|
36
|
+
/** Chat widget title */
|
|
37
|
+
title?: string;
|
|
38
|
+
/** Input placeholder */
|
|
39
|
+
placeholder?: string;
|
|
40
|
+
/** Greeting message */
|
|
41
|
+
greeting?: string;
|
|
42
|
+
/** Widget position */
|
|
43
|
+
position?: 'bottom-right' | 'bottom-left';
|
|
44
|
+
/** Widget variant */
|
|
45
|
+
variant?: 'default' | 'minimal';
|
|
46
|
+
/** Enable streaming responses */
|
|
47
|
+
enableStreaming?: boolean;
|
|
48
|
+
/** Auto-detect environment (dev/prod) */
|
|
49
|
+
autoDetectEnvironment?: boolean;
|
|
50
|
+
/** Custom class name */
|
|
51
|
+
className?: string;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
// ============================================================================
|
|
55
|
+
// Centrifugo Configuration
|
|
56
|
+
// ============================================================================
|
|
57
|
+
|
|
58
|
+
export interface CentrifugoConfig {
|
|
59
|
+
/** Enable Centrifugo (default: true) */
|
|
60
|
+
enabled?: boolean;
|
|
61
|
+
/** Auto-connect on mount (default: false) */
|
|
62
|
+
autoConnect?: boolean;
|
|
63
|
+
/** Centrifugo server URL */
|
|
64
|
+
url?: string;
|
|
65
|
+
}
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* UI Component Types
|
|
3
|
+
*
|
|
4
|
+
* Types for layout UI components (navigation, footer, user menu)
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import type { LucideIcon } from 'lucide-react';
|
|
8
|
+
|
|
9
|
+
// ============================================================================
|
|
10
|
+
// Navigation Types
|
|
11
|
+
// ============================================================================
|
|
12
|
+
|
|
13
|
+
export interface NavigationItem {
|
|
14
|
+
label: string;
|
|
15
|
+
href: string;
|
|
16
|
+
icon?: LucideIcon | string;
|
|
17
|
+
badge?: string | number;
|
|
18
|
+
external?: boolean;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export interface NavigationSection {
|
|
22
|
+
title?: string;
|
|
23
|
+
items: NavigationItem[];
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
// ============================================================================
|
|
27
|
+
// Footer Types
|
|
28
|
+
// ============================================================================
|
|
29
|
+
|
|
30
|
+
export interface FooterLink {
|
|
31
|
+
label: string;
|
|
32
|
+
path: string;
|
|
33
|
+
external?: boolean;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
export interface FooterMenuSection {
|
|
37
|
+
title: string;
|
|
38
|
+
items: FooterLink[];
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
export interface FooterSocialLinks {
|
|
42
|
+
github?: string;
|
|
43
|
+
linkedin?: string;
|
|
44
|
+
twitter?: string;
|
|
45
|
+
telegram?: string;
|
|
46
|
+
youtube?: string;
|
|
47
|
+
facebook?: string;
|
|
48
|
+
instagram?: string;
|
|
49
|
+
whatsapp?: string;
|
|
50
|
+
email?: string;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
export interface FooterConfig {
|
|
54
|
+
siteName?: string;
|
|
55
|
+
description?: string;
|
|
56
|
+
logo?: string;
|
|
57
|
+
badge?: {
|
|
58
|
+
icon: LucideIcon;
|
|
59
|
+
text: string;
|
|
60
|
+
};
|
|
61
|
+
socialLinks?: FooterSocialLinks;
|
|
62
|
+
links?: FooterLink[];
|
|
63
|
+
menuSections?: FooterMenuSection[];
|
|
64
|
+
copyright?: string;
|
|
65
|
+
credits?: {
|
|
66
|
+
text: string;
|
|
67
|
+
url?: string;
|
|
68
|
+
};
|
|
69
|
+
variant?: 'full' | 'simple';
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
// ============================================================================
|
|
73
|
+
// User Menu Types
|
|
74
|
+
// ============================================================================
|
|
75
|
+
|
|
76
|
+
export interface UserMenuItem {
|
|
77
|
+
/** Menu item label */
|
|
78
|
+
label: string;
|
|
79
|
+
/** Link href (optional if onClick is provided) */
|
|
80
|
+
href?: string;
|
|
81
|
+
/** Icon component */
|
|
82
|
+
icon?: LucideIcon;
|
|
83
|
+
/** Visual variant */
|
|
84
|
+
variant?: 'default' | 'destructive';
|
|
85
|
+
/** Click handler (optional if href is provided) */
|
|
86
|
+
onClick?: () => void;
|
|
87
|
+
/** Open link in new tab */
|
|
88
|
+
external?: boolean;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
export interface UserMenuGroup {
|
|
92
|
+
/** Optional group title (renders DropdownMenuLabel) */
|
|
93
|
+
title?: string;
|
|
94
|
+
/** Menu items in this group */
|
|
95
|
+
items: UserMenuItem[];
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
export interface UserMenuConfig {
|
|
99
|
+
/** Menu groups for authenticated users */
|
|
100
|
+
groups?: UserMenuGroup[];
|
|
101
|
+
/** Auth page path (for sign in button) */
|
|
102
|
+
authPath?: string;
|
|
103
|
+
}
|
|
@@ -8,3 +8,4 @@ export { useAnalytics, Analytics } from './useAnalytics';
|
|
|
8
8
|
export { AnalyticsProvider } from './AnalyticsProvider';
|
|
9
9
|
export { AnalyticsEvent, AnalyticsCategory } from './events';
|
|
10
10
|
export type { AnalyticsEventType, AnalyticsCategoryType } from './events';
|
|
11
|
+
export type { AnalyticsConfig } from './types';
|