@djangocfg/layouts 1.4.29 → 2.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (119) hide show
  1. package/README.md +277 -18
  2. package/package.json +15 -24
  3. package/src/auth/context/AuthContext.tsx +8 -5
  4. package/src/auth/hooks/useAuthGuard.ts +1 -1
  5. package/src/auth/hooks/useAutoAuth.ts +8 -7
  6. package/src/components/ErrorBoundary.tsx +78 -0
  7. package/src/components/JsonLd.tsx +31 -0
  8. package/src/components/LucideIcon.tsx +91 -0
  9. package/src/components/PageProgress.tsx +127 -0
  10. package/src/components/Suspense.tsx +29 -0
  11. package/src/{layouts/AppLayout/components → components}/UpdateNotifier/UpdateNotifier.tsx +56 -49
  12. package/src/components/index.ts +10 -0
  13. package/src/index.ts +25 -7
  14. package/src/layouts/AdminLayout/AdminLayout.tsx +46 -0
  15. package/src/layouts/AdminLayout/index.ts +7 -0
  16. package/src/layouts/AppLayout/AppLayout.tsx +278 -326
  17. package/src/layouts/AppLayout/index.ts +2 -39
  18. package/src/layouts/{AppLayout/layouts/AuthLayout → AuthLayout}/AuthContext.tsx +3 -2
  19. package/src/layouts/{AppLayout/layouts/AuthLayout → AuthLayout}/AuthHelp.tsx +1 -0
  20. package/src/layouts/AuthLayout/AuthLayout.tsx +61 -0
  21. package/src/layouts/{AppLayout/layouts/AuthLayout → AuthLayout}/IdentifierForm.tsx +47 -34
  22. package/src/layouts/{AppLayout/layouts/AuthLayout → AuthLayout}/OTPForm.tsx +2 -3
  23. package/src/layouts/AuthLayout/index.ts +24 -0
  24. package/src/layouts/{AppLayout/layouts/AuthLayout → AuthLayout}/types.ts +1 -0
  25. package/src/layouts/PrivateLayout/PrivateLayout.tsx +144 -0
  26. package/src/layouts/PrivateLayout/components/PrivateContent.tsx +32 -0
  27. package/src/layouts/PrivateLayout/components/PrivateHeader.tsx +57 -0
  28. package/src/layouts/PrivateLayout/components/PrivateSidebar.tsx +141 -0
  29. package/src/layouts/PrivateLayout/components/index.ts +8 -0
  30. package/src/layouts/PrivateLayout/index.ts +7 -0
  31. package/src/layouts/ProfileLayout/ProfileLayout.tsx +15 -7
  32. package/src/layouts/PublicLayout/PublicLayout.tsx +121 -0
  33. package/src/layouts/PublicLayout/components/PublicFooter.tsx +190 -0
  34. package/src/layouts/PublicLayout/components/PublicMobileDrawer.tsx +117 -0
  35. package/src/layouts/PublicLayout/components/PublicNavigation.tsx +101 -0
  36. package/src/layouts/PublicLayout/components/index.ts +8 -0
  37. package/src/layouts/PublicLayout/index.ts +7 -0
  38. package/src/layouts/_components/UserMenu.tsx +160 -0
  39. package/src/layouts/_components/index.ts +7 -0
  40. package/src/layouts/index.ts +15 -8
  41. package/src/snippets/Analytics/AnalyticsProvider.tsx +8 -4
  42. package/src/snippets/Analytics/useAnalytics.ts +11 -21
  43. package/src/snippets/Chat/ChatWidget.tsx +4 -4
  44. package/src/snippets/ContactForm/ContactFormProvider.tsx +32 -19
  45. package/src/snippets/ContactForm/ContactPage.tsx +2 -4
  46. package/src/snippets/ContactForm/types.ts +3 -2
  47. package/src/snippets/index.ts +0 -1
  48. package/src/layouts/AppLayout/README.md +0 -204
  49. package/src/layouts/AppLayout/SUMMARY.md +0 -240
  50. package/src/layouts/AppLayout/USAGE.md +0 -312
  51. package/src/layouts/AppLayout/components/ErrorBoundary.tsx +0 -112
  52. package/src/layouts/AppLayout/components/PageProgress.tsx +0 -123
  53. package/src/layouts/AppLayout/components/Seo.tsx +0 -171
  54. package/src/layouts/AppLayout/components/UserMenu.tsx +0 -385
  55. package/src/layouts/AppLayout/components/index.ts +0 -11
  56. package/src/layouts/AppLayout/context/AppContext.tsx +0 -151
  57. package/src/layouts/AppLayout/context/index.ts +0 -5
  58. package/src/layouts/AppLayout/hooks/index.ts +0 -8
  59. package/src/layouts/AppLayout/hooks/useLayoutMode.ts +0 -26
  60. package/src/layouts/AppLayout/hooks/useNavigation.ts +0 -51
  61. package/src/layouts/AppLayout/layouts/AdminLayout/AdminLayout.tsx +0 -224
  62. package/src/layouts/AppLayout/layouts/AdminLayout/README.md +0 -409
  63. package/src/layouts/AppLayout/layouts/AdminLayout/components/PagePreloader.example.tsx +0 -98
  64. package/src/layouts/AppLayout/layouts/AdminLayout/components/PagePreloader.tsx +0 -149
  65. package/src/layouts/AppLayout/layouts/AdminLayout/components/ParentSync.tsx +0 -146
  66. package/src/layouts/AppLayout/layouts/AdminLayout/components/index.ts +0 -3
  67. package/src/layouts/AppLayout/layouts/AdminLayout/context/CfgAppContext.tsx +0 -48
  68. package/src/layouts/AppLayout/layouts/AdminLayout/context/index.ts +0 -2
  69. package/src/layouts/AppLayout/layouts/AdminLayout/hooks/index.ts +0 -6
  70. package/src/layouts/AppLayout/layouts/AdminLayout/hooks/useApp.ts +0 -279
  71. package/src/layouts/AppLayout/layouts/AdminLayout/index.ts +0 -24
  72. package/src/layouts/AppLayout/layouts/AdminLayout/lottie/energizing.json +0 -1
  73. package/src/layouts/AppLayout/layouts/AdminLayout/types/index.ts +0 -45
  74. package/src/layouts/AppLayout/layouts/AuthLayout/AuthLayout.tsx +0 -41
  75. package/src/layouts/AppLayout/layouts/AuthLayout/index.ts +0 -15
  76. package/src/layouts/AppLayout/layouts/PrivateLayout/PrivateLayout.tsx +0 -82
  77. package/src/layouts/AppLayout/layouts/PrivateLayout/components/DashboardContent.tsx +0 -62
  78. package/src/layouts/AppLayout/layouts/PrivateLayout/components/DashboardHeader.tsx +0 -89
  79. package/src/layouts/AppLayout/layouts/PrivateLayout/components/DashboardSidebar.tsx +0 -181
  80. package/src/layouts/AppLayout/layouts/PrivateLayout/components/index.ts +0 -9
  81. package/src/layouts/AppLayout/layouts/PrivateLayout/index.ts +0 -5
  82. package/src/layouts/AppLayout/layouts/PublicLayout/PublicLayout.tsx +0 -44
  83. package/src/layouts/AppLayout/layouts/PublicLayout/components/Footer.tsx +0 -242
  84. package/src/layouts/AppLayout/layouts/PublicLayout/components/MobileDrawer.tsx +0 -150
  85. package/src/layouts/AppLayout/layouts/PublicLayout/components/Navigation.tsx +0 -169
  86. package/src/layouts/AppLayout/layouts/PublicLayout/index.ts +0 -5
  87. package/src/layouts/AppLayout/layouts/index.ts +0 -7
  88. package/src/layouts/AppLayout/providers/CoreProviders.tsx +0 -80
  89. package/src/layouts/AppLayout/providers/index.ts +0 -5
  90. package/src/layouts/AppLayout/types/config.ts +0 -79
  91. package/src/layouts/AppLayout/types/index.ts +0 -11
  92. package/src/layouts/AppLayout/types/layout.ts +0 -54
  93. package/src/layouts/AppLayout/types/navigation.ts +0 -43
  94. package/src/layouts/AppLayout/types/page.ts +0 -80
  95. package/src/layouts/AppLayout/types/routes.ts +0 -43
  96. package/src/layouts/AppLayout/utils/index.ts +0 -5
  97. package/src/layouts/AppLayout/utils/routeDetection.ts +0 -31
  98. package/src/layouts/ErrorLayout/ErrorLayout.tsx +0 -173
  99. package/src/layouts/ErrorLayout/errorConfig.tsx +0 -152
  100. package/src/layouts/ErrorLayout/index.ts +0 -8
  101. package/src/layouts/SimpleLayout/SimpleLayout.tsx +0 -72
  102. package/src/layouts/SimpleLayout/index.ts +0 -3
  103. package/src/snippets/VideoPlayer/README.md +0 -238
  104. package/src/snippets/VideoPlayer/VideoControls.tsx +0 -137
  105. package/src/snippets/VideoPlayer/VideoPlayer.tsx +0 -248
  106. package/src/snippets/VideoPlayer/index.ts +0 -8
  107. package/src/snippets/VideoPlayer/types.ts +0 -61
  108. package/src/types/index.ts +0 -2
  109. package/src/types/pageConfig.ts +0 -100
  110. /package/src/{validation → components/ErrorsTracker}/README.md +0 -0
  111. /package/src/{validation → components/ErrorsTracker}/components/ErrorButtons.tsx +0 -0
  112. /package/src/{validation → components/ErrorsTracker}/components/ErrorToast.tsx +0 -0
  113. /package/src/{validation → components/ErrorsTracker}/hooks.ts +0 -0
  114. /package/src/{validation → components/ErrorsTracker}/index.ts +0 -0
  115. /package/src/{validation → components/ErrorsTracker}/providers/ErrorTrackingProvider.tsx +0 -0
  116. /package/src/{validation → components/ErrorsTracker}/types.ts +0 -0
  117. /package/src/{validation → components/ErrorsTracker}/utils/curl-generator.ts +0 -0
  118. /package/src/{validation → components/ErrorsTracker}/utils/formatters.ts +0 -0
  119. /package/src/{layouts/AppLayout/components → components}/UpdateNotifier/index.ts +0 -0
@@ -0,0 +1,121 @@
1
+ /**
2
+ * Public Layout
3
+ *
4
+ * Simple layout for public pages (home, docs, contact, legal pages)
5
+ * Import and use directly with props - no complex configs needed!
6
+ *
7
+ * Features:
8
+ * - Responsive navigation with mobile drawer
9
+ * - Footer with links and copyright
10
+ * - User menu integration
11
+ *
12
+ * @example
13
+ * ```tsx
14
+ * import { PublicLayout } from '@djangocfg/layouts';
15
+ *
16
+ * <PublicLayout
17
+ * logo="/logo.svg"
18
+ * siteName="My App"
19
+ * navigation={[
20
+ * { label: 'Home', href: '/' },
21
+ * { label: 'Docs', href: '/docs' }
22
+ * ]}
23
+ * footer={{
24
+ * links: { privacy: '/privacy', terms: '/terms' }
25
+ * }}
26
+ * >
27
+ * {children}
28
+ * </PublicLayout>
29
+ * ```
30
+ */
31
+
32
+ 'use client';
33
+
34
+ import { ReactNode, useState } from 'react';
35
+ import {
36
+ PublicNavigation,
37
+ PublicMobileDrawer,
38
+ PublicFooter,
39
+ } from './components';
40
+
41
+ export interface NavigationItem {
42
+ label: string;
43
+ href: string;
44
+ icon?: string;
45
+ }
46
+
47
+ export interface FooterConfig {
48
+ links?: {
49
+ privacy?: string;
50
+ terms?: string;
51
+ security?: string;
52
+ cookies?: string;
53
+ docs?: string;
54
+ };
55
+ /** Copyright text (optional, auto-generated from siteName if not provided) */
56
+ copyright?: string;
57
+ }
58
+
59
+ export interface PublicLayoutProps {
60
+ children: ReactNode;
61
+ /** Logo path or URL */
62
+ logo?: string;
63
+ /** Site name */
64
+ siteName?: string;
65
+ /** Navigation items */
66
+ navigation?: NavigationItem[];
67
+ /** Footer configuration */
68
+ footer?: FooterConfig;
69
+ /** User menu paths (optional, uses useAuth() for authentication state) */
70
+ userMenu?: {
71
+ /** Profile page path */
72
+ profilePath?: string;
73
+ /** Dashboard page path */
74
+ dashboardPath?: string;
75
+ /** Auth page path (for sign in button) */
76
+ authPath?: string;
77
+ };
78
+ }
79
+
80
+ export function PublicLayout({
81
+ children,
82
+ logo,
83
+ siteName = 'App',
84
+ navigation = [],
85
+ footer,
86
+ userMenu,
87
+ }: PublicLayoutProps) {
88
+ const [mobileMenuOpen, setMobileMenuOpen] = useState(false);
89
+
90
+ return (
91
+ <div className="min-h-screen flex flex-col">
92
+ {/* Navigation */}
93
+ <PublicNavigation
94
+ logo={logo}
95
+ siteName={siteName}
96
+ navigation={navigation}
97
+ userMenu={userMenu}
98
+ onMobileMenuClick={() => setMobileMenuOpen(true)}
99
+ />
100
+
101
+ {/* Mobile Drawer */}
102
+ <PublicMobileDrawer
103
+ isOpen={mobileMenuOpen}
104
+ onClose={() => setMobileMenuOpen(false)}
105
+ logo={logo}
106
+ siteName={siteName}
107
+ navigation={navigation}
108
+ userMenu={userMenu}
109
+ />
110
+
111
+ {/* Main Content */}
112
+ <main className="flex-1">{children}</main>
113
+
114
+ {/* Footer */}
115
+ {footer && (
116
+ <PublicFooter logo={logo} siteName={siteName} footer={footer} />
117
+ )}
118
+ </div>
119
+ );
120
+ }
121
+
@@ -0,0 +1,190 @@
1
+ /**
2
+ * Public Layout Footer
3
+ *
4
+ * Footer component for PublicLayout
5
+ */
6
+
7
+ 'use client';
8
+
9
+ import React from 'react';
10
+ import Link from 'next/link';
11
+ import { useIsMobile } from '@djangocfg/ui/hooks';
12
+
13
+ interface FooterConfig {
14
+ links?: {
15
+ privacy?: string;
16
+ terms?: string;
17
+ security?: string;
18
+ cookies?: string;
19
+ docs?: string;
20
+ };
21
+ copyright?: string;
22
+ }
23
+
24
+ interface PublicFooterProps {
25
+ logo?: string;
26
+ siteName: string;
27
+ footer?: FooterConfig;
28
+ }
29
+
30
+ export function PublicFooter({
31
+ logo,
32
+ siteName,
33
+ footer,
34
+ }: PublicFooterProps) {
35
+ const isMobile = useIsMobile();
36
+ const currentYear = new Date().getFullYear();
37
+ const copyright =
38
+ footer?.copyright ||
39
+ `© ${currentYear} ${siteName}. All rights reserved.`;
40
+
41
+ if (isMobile) {
42
+ return (
43
+ <footer className="lg:hidden bg-background border-t border-border mt-auto">
44
+ <div className="w-full px-4 py-8">
45
+ {/* Project Info */}
46
+ <div className="text-center space-y-4 mb-6">
47
+ <div className="flex items-center justify-center gap-2">
48
+ {logo && (
49
+ <div className="w-6 h-6 flex items-center justify-center">
50
+ <img
51
+ src={logo}
52
+ alt={`${siteName} Logo`}
53
+ className="w-full h-full object-contain"
54
+ />
55
+ </div>
56
+ )}
57
+ <span className="text-lg font-bold text-foreground">
58
+ {siteName}
59
+ </span>
60
+ </div>
61
+ </div>
62
+
63
+ {/* Quick Links */}
64
+ <div className="flex flex-wrap justify-center gap-4 mb-6 items-center">
65
+ {footer?.links?.docs && (
66
+ <a
67
+ href={footer.links.docs}
68
+ target="_blank"
69
+ rel="noopener noreferrer"
70
+ className="text-sm text-muted-foreground hover:text-primary transition-colors"
71
+ title="Documentation"
72
+ >
73
+ Docs
74
+ </a>
75
+ )}
76
+ {footer?.links?.privacy && (
77
+ <Link
78
+ href={footer.links.privacy}
79
+ className="text-sm text-muted-foreground hover:text-primary transition-colors"
80
+ >
81
+ Privacy
82
+ </Link>
83
+ )}
84
+ {footer?.links?.terms && (
85
+ <Link
86
+ href={footer.links.terms}
87
+ className="text-sm text-muted-foreground hover:text-primary transition-colors"
88
+ >
89
+ Terms
90
+ </Link>
91
+ )}
92
+ </div>
93
+
94
+ {/* Bottom Section */}
95
+ <div className="border-t border-border pt-4">
96
+ <div className="text-center space-y-2">
97
+ <div className="text-xs text-muted-foreground">{copyright}</div>
98
+ </div>
99
+ </div>
100
+ </div>
101
+ </footer>
102
+ );
103
+ }
104
+
105
+ // Desktop Footer
106
+ return (
107
+ <footer className="max-lg:hidden bg-background border-t border-border mt-auto">
108
+ <div className="w-full px-8 lg:px-16 xl:px-24 py-12">
109
+ <div className="flex flex-col gap-8">
110
+ {/* Top Section */}
111
+ <div className="flex gap-8">
112
+ {/* Left Column - Project Info */}
113
+ <div className="space-y-4" style={{ width: '30%', minWidth: '300px' }}>
114
+ <div className="flex items-center gap-2">
115
+ {logo && (
116
+ <div className="w-8 h-8 flex items-center justify-center">
117
+ <img
118
+ src={logo}
119
+ alt={`${siteName} Logo`}
120
+ className="w-full h-full object-contain"
121
+ />
122
+ </div>
123
+ )}
124
+ <span className="text-xl font-bold text-foreground">
125
+ {siteName}
126
+ </span>
127
+ </div>
128
+ </div>
129
+ </div>
130
+
131
+ {/* Bottom Section */}
132
+ <div
133
+ className="border-t border-border"
134
+ style={{ marginTop: '2rem', paddingTop: '2rem' }}
135
+ >
136
+ <div className="flex justify-between items-center gap-4">
137
+ <div className="text-xs text-muted-foreground">{copyright}</div>
138
+ <div className="flex flex-wrap items-center gap-4">
139
+ {footer?.links?.docs && (
140
+ <a
141
+ href={footer.links.docs}
142
+ target="_blank"
143
+ rel="noopener noreferrer"
144
+ className="text-xs text-muted-foreground hover:text-primary transition-colors"
145
+ title="Documentation"
146
+ >
147
+ Docs
148
+ </a>
149
+ )}
150
+ {footer?.links?.privacy && (
151
+ <Link
152
+ href={footer.links.privacy}
153
+ className="text-xs text-muted-foreground hover:text-primary transition-colors"
154
+ >
155
+ Privacy Policy
156
+ </Link>
157
+ )}
158
+ {footer?.links?.terms && (
159
+ <Link
160
+ href={footer.links.terms}
161
+ className="text-xs text-muted-foreground hover:text-primary transition-colors"
162
+ >
163
+ Terms of Service
164
+ </Link>
165
+ )}
166
+ {footer?.links?.security && (
167
+ <Link
168
+ href={footer.links.security}
169
+ className="text-xs text-muted-foreground hover:text-primary transition-colors"
170
+ >
171
+ Security
172
+ </Link>
173
+ )}
174
+ {footer?.links?.cookies && (
175
+ <Link
176
+ href={footer.links.cookies}
177
+ className="text-xs text-muted-foreground hover:text-primary transition-colors"
178
+ >
179
+ Cookies
180
+ </Link>
181
+ )}
182
+ </div>
183
+ </div>
184
+ </div>
185
+ </div>
186
+ </div>
187
+ </footer>
188
+ );
189
+ }
190
+
@@ -0,0 +1,117 @@
1
+ /**
2
+ * Public Layout Mobile Drawer
3
+ *
4
+ * Mobile drawer component for PublicLayout navigation
5
+ */
6
+
7
+ 'use client';
8
+
9
+ import React from 'react';
10
+ import Link from 'next/link';
11
+ import { X } from 'lucide-react';
12
+ import {
13
+ Drawer,
14
+ DrawerContent,
15
+ DrawerHeader,
16
+ DrawerTitle,
17
+ DrawerClose,
18
+ Button,
19
+ } from '@djangocfg/ui/components';
20
+ import { ThemeToggle } from '@djangocfg/ui/theme';
21
+ import { useAuth } from '../../../auth';
22
+ import { UserMenu } from '../../_components/UserMenu';
23
+ import type { NavigationItem } from '../PublicLayout';
24
+
25
+ interface PublicMobileDrawerProps {
26
+ isOpen: boolean;
27
+ onClose: () => void;
28
+ logo?: string;
29
+ siteName: string;
30
+ navigation: NavigationItem[];
31
+ userMenu?: {
32
+ profilePath?: string;
33
+ dashboardPath?: string;
34
+ authPath?: string;
35
+ };
36
+ }
37
+
38
+ export function PublicMobileDrawer({
39
+ isOpen,
40
+ onClose,
41
+ logo,
42
+ siteName,
43
+ navigation,
44
+ userMenu,
45
+ }: PublicMobileDrawerProps) {
46
+ const { isAuthenticated } = useAuth();
47
+
48
+ const handleNavigate = () => {
49
+ onClose();
50
+ };
51
+
52
+ return (
53
+ <Drawer open={isOpen} onOpenChange={(open) => !open && onClose()} direction="right">
54
+ <DrawerContent direction="right" className="w-80 lg:hidden">
55
+ {/* Header */}
56
+ <DrawerHeader className="flex flex-row items-center justify-between p-4 border-b border-border/30">
57
+ <div className="flex items-center gap-3">
58
+ {logo && (
59
+ <img
60
+ src={logo}
61
+ alt={`${siteName} Logo`}
62
+ className="h-8 w-auto object-contain"
63
+ />
64
+ )}
65
+ <DrawerTitle className="text-lg font-bold text-foreground">
66
+ {siteName}
67
+ </DrawerTitle>
68
+ </div>
69
+ <DrawerClose className="p-2 rounded-sm transition-colors hover:bg-accent/50">
70
+ <X className="size-5" />
71
+ <span className="sr-only">Close menu</span>
72
+ </DrawerClose>
73
+ </DrawerHeader>
74
+
75
+ {/* Scrollable Content */}
76
+ <div className="flex-1 overflow-y-auto p-4 space-y-6">
77
+ {/* Theme Toggle */}
78
+ <div className="flex items-center justify-between px-4 py-3 border-b border-border/30">
79
+ <span className="text-sm font-medium text-foreground">Theme</span>
80
+ <ThemeToggle />
81
+ </div>
82
+
83
+ {/* User Menu */}
84
+ <UserMenu
85
+ variant="mobile"
86
+ profilePath={userMenu?.profilePath}
87
+ dashboardPath={userMenu?.dashboardPath}
88
+ authPath={userMenu?.authPath}
89
+ />
90
+
91
+ {/* Navigation Items */}
92
+ <div className="space-y-3">
93
+ <h3 className="px-2 text-xs font-semibold uppercase tracking-wider text-muted-foreground">
94
+ Menu
95
+ </h3>
96
+ <div className="space-y-1">
97
+ {navigation.map((item) => (
98
+ <Link
99
+ key={item.href}
100
+ href={item.href}
101
+ className="block px-4 py-3 rounded-sm text-base font-medium transition-colors text-foreground hover:bg-accent hover:text-accent-foreground"
102
+ onClick={handleNavigate}
103
+ >
104
+ {item.label}
105
+ </Link>
106
+ ))}
107
+ </div>
108
+ </div>
109
+
110
+ {/* Bottom spacer */}
111
+ <div style={{ height: '15vh' }}></div>
112
+ </div>
113
+ </DrawerContent>
114
+ </Drawer>
115
+ );
116
+ }
117
+
@@ -0,0 +1,101 @@
1
+ /**
2
+ * Public Layout Navigation
3
+ *
4
+ * Navigation component for PublicLayout with mobile drawer support
5
+ */
6
+
7
+ 'use client';
8
+
9
+ import React from 'react';
10
+ import Link from 'next/link';
11
+ import { Menu } from 'lucide-react';
12
+ import { Button } from '@djangocfg/ui/components';
13
+ import { ThemeToggle } from '@djangocfg/ui/theme';
14
+ import { cn } from '@djangocfg/ui/lib';
15
+ import { useIsMobile } from '@djangocfg/ui/hooks';
16
+ import { useAuth } from '../../../auth';
17
+ import { UserMenu } from '../../_components/UserMenu';
18
+ import type { NavigationItem } from '../PublicLayout';
19
+
20
+ interface PublicNavigationProps {
21
+ logo?: string;
22
+ siteName: string;
23
+ navigation: NavigationItem[];
24
+ userMenu?: {
25
+ profilePath?: string;
26
+ dashboardPath?: string;
27
+ authPath?: string;
28
+ };
29
+ onMobileMenuClick: () => void;
30
+ }
31
+
32
+ export function PublicNavigation({
33
+ logo,
34
+ siteName,
35
+ navigation,
36
+ userMenu,
37
+ onMobileMenuClick,
38
+ }: PublicNavigationProps) {
39
+ const { isAuthenticated } = useAuth();
40
+ const isMobile = useIsMobile();
41
+
42
+ return (
43
+ <nav className="sticky top-0 w-full backdrop-blur-xl z-50 border-b bg-background/80">
44
+ <div className="w-full px-4 sm:px-6 lg:px-8">
45
+ <div className="flex items-center justify-between py-4">
46
+ {/* Logo */}
47
+ <Link href="/" className="flex items-center gap-2">
48
+ {logo && (
49
+ <img src={logo} alt={siteName} className="h-8 w-8" />
50
+ )}
51
+ <span className="font-bold text-lg">{siteName}</span>
52
+ </Link>
53
+
54
+ {/* Desktop Navigation */}
55
+ <div className="hidden md:flex items-center gap-6">
56
+ {navigation.map((item) => (
57
+ <Link
58
+ key={item.href}
59
+ href={item.href}
60
+ className="text-sm font-medium hover:text-primary transition-colors"
61
+ >
62
+ {item.label}
63
+ </Link>
64
+ ))}
65
+ </div>
66
+
67
+ {/* User Menu / Actions */}
68
+ <div className="flex items-center gap-4">
69
+ {!isMobile && (
70
+ <>
71
+ {/* Theme Toggle */}
72
+ <ThemeToggle />
73
+
74
+ {/* User Menu */}
75
+ <UserMenu
76
+ variant="desktop"
77
+ profilePath={userMenu?.profilePath}
78
+ dashboardPath={userMenu?.dashboardPath}
79
+ authPath={userMenu?.authPath}
80
+ />
81
+ </>
82
+ )}
83
+
84
+ {/* Mobile Menu Button */}
85
+ {isMobile && (
86
+ <Button
87
+ variant="ghost"
88
+ size="icon"
89
+ onClick={onMobileMenuClick}
90
+ aria-label="Toggle mobile menu"
91
+ >
92
+ <Menu className="h-5 w-5" />
93
+ </Button>
94
+ )}
95
+ </div>
96
+ </div>
97
+ </div>
98
+ </nav>
99
+ );
100
+ }
101
+
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Public Layout Components
3
+ */
4
+
5
+ export { PublicNavigation } from './PublicNavigation';
6
+ export { PublicMobileDrawer } from './PublicMobileDrawer';
7
+ export { PublicFooter } from './PublicFooter';
8
+
@@ -0,0 +1,7 @@
1
+ /**
2
+ * Public Layout exports
3
+ */
4
+
5
+ export { PublicLayout } from './PublicLayout';
6
+ export type { PublicLayoutProps, NavigationItem, FooterConfig } from './PublicLayout';
7
+