@djangocfg/layouts 1.4.27 โ 1.4.29
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/package.json +8 -8
- package/src/auth/context/AuthContext.tsx +4 -1
- package/src/auth/hooks/index.ts +2 -0
- package/src/auth/hooks/useAuthForm.ts +2 -0
- package/src/auth/hooks/useAuthGuard.ts +2 -0
- package/src/auth/hooks/useAutoAuth.ts +16 -11
- package/src/auth/hooks/useLocalStorage.ts +2 -0
- package/src/auth/hooks/useProfileCache.ts +2 -0
- package/src/auth/hooks/useSessionStorage.ts +2 -0
- package/src/auth/middlewares/index.ts +1 -1
- package/src/auth/middlewares/proxy.ts +10 -2
- package/src/layouts/AppLayout/AppLayout.tsx +9 -7
- package/src/layouts/AppLayout/components/ErrorBoundary.tsx +6 -3
- package/src/layouts/AppLayout/components/PageProgress.tsx +2 -0
- package/src/layouts/AppLayout/components/Seo.tsx +2 -0
- package/src/layouts/AppLayout/components/UpdateNotifier/UpdateNotifier.tsx +3 -2
- package/src/layouts/AppLayout/hooks/index.ts +2 -0
- package/src/layouts/AppLayout/hooks/useNavigation.ts +3 -1
- package/src/layouts/AppLayout/layouts/AdminLayout/AdminLayout.tsx +1 -0
- package/src/layouts/AppLayout/layouts/AuthLayout/AuthContext.tsx +2 -0
- package/src/layouts/AppLayout/layouts/AuthLayout/IdentifierForm.tsx +2 -0
- package/src/layouts/AppLayout/layouts/AuthLayout/OTPForm.tsx +4 -0
- package/src/layouts/AppLayout/layouts/AuthLayout/index.ts +2 -0
- package/src/layouts/AppLayout/layouts/PrivateLayout/PrivateLayout.tsx +1 -0
- package/src/layouts/AppLayout/providers/CoreProviders.tsx +1 -0
- package/src/layouts/PaymentsLayout/PaymentsLayout.tsx +1 -0
- package/src/layouts/PaymentsLayout/components/CreatePaymentDialog.tsx +1 -0
- package/src/layouts/PaymentsLayout/events.ts +2 -0
- package/src/layouts/ProfileLayout/ProfileLayout.tsx +1 -0
- package/src/layouts/ProfileLayout/components/ProfileForm.tsx +1 -0
- package/src/layouts/SimpleLayout/SimpleLayout.tsx +72 -0
- package/src/layouts/SimpleLayout/index.ts +3 -0
- package/src/layouts/SupportLayout/SupportLayout.tsx +1 -0
- package/src/layouts/SupportLayout/components/CreateTicketDialog.tsx +1 -0
- package/src/layouts/SupportLayout/components/TicketList.tsx +6 -5
- package/src/layouts/SupportLayout/events.ts +2 -0
- package/src/layouts/index.ts +1 -3
- package/src/snippets/AuthDialog/useAuthDialog.ts +2 -0
- package/src/snippets/Chat/components/MessageList.tsx +12 -11
- package/src/snippets/Chat/index.tsx +1 -0
- package/src/snippets/ContactForm/ContactForm.tsx +7 -2
- package/src/snippets/ContactForm/ContactPage.tsx +16 -3
- package/src/snippets/VideoPlayer/README.md +35 -0
- package/src/snippets/VideoPlayer/VideoControls.tsx +13 -9
- package/src/snippets/VideoPlayer/VideoPlayer.tsx +159 -25
- package/src/snippets/VideoPlayer/index.ts +1 -1
- package/src/validation/utils/curl-generator.ts +5 -1
- package/src/layouts/UILayout/README.md +0 -267
- package/src/layouts/UILayout/SUMMARY.md +0 -298
- package/src/layouts/UILayout/TOOLS_INTEGRATION.md +0 -216
- package/src/layouts/UILayout/components/AutoComponentDemo.tsx +0 -77
- package/src/layouts/UILayout/components/CategoryRenderer.tsx +0 -45
- package/src/layouts/UILayout/components/TailwindGuideRenderer.tsx +0 -138
- package/src/layouts/UILayout/components/index.ts +0 -15
- package/src/layouts/UILayout/components/layout/Header/CopyAIButton.tsx +0 -58
- package/src/layouts/UILayout/components/layout/Header/Header.tsx +0 -60
- package/src/layouts/UILayout/components/layout/Header/HeaderDesktop.tsx +0 -51
- package/src/layouts/UILayout/components/layout/Header/HeaderMobile.tsx +0 -71
- package/src/layouts/UILayout/components/layout/Header/TestValidationButton.tsx +0 -268
- package/src/layouts/UILayout/components/layout/Header/index.ts +0 -11
- package/src/layouts/UILayout/components/layout/MobileOverlay/MobileOverlay.tsx +0 -47
- package/src/layouts/UILayout/components/layout/MobileOverlay/index.ts +0 -6
- package/src/layouts/UILayout/components/layout/Sidebar/Sidebar.tsx +0 -95
- package/src/layouts/UILayout/components/layout/Sidebar/SidebarCategory.tsx +0 -54
- package/src/layouts/UILayout/components/layout/Sidebar/SidebarContent.tsx +0 -93
- package/src/layouts/UILayout/components/layout/Sidebar/SidebarFooter.tsx +0 -49
- package/src/layouts/UILayout/components/layout/Sidebar/index.ts +0 -9
- package/src/layouts/UILayout/components/layout/index.ts +0 -8
- package/src/layouts/UILayout/components/shared/Badge/CountBadge.tsx +0 -38
- package/src/layouts/UILayout/components/shared/Badge/index.ts +0 -5
- package/src/layouts/UILayout/components/shared/CodeBlock/CodeBlock.tsx +0 -48
- package/src/layouts/UILayout/components/shared/CodeBlock/CopyButton.tsx +0 -49
- package/src/layouts/UILayout/components/shared/CodeBlock/index.ts +0 -6
- package/src/layouts/UILayout/components/shared/Section/Section.tsx +0 -63
- package/src/layouts/UILayout/components/shared/Section/index.ts +0 -5
- package/src/layouts/UILayout/components/shared/index.ts +0 -8
- package/src/layouts/UILayout/config/ai-export.config.ts +0 -89
- package/src/layouts/UILayout/config/categories.config.tsx +0 -122
- package/src/layouts/UILayout/config/components/blocks.config.tsx +0 -239
- package/src/layouts/UILayout/config/components/data.config.tsx +0 -433
- package/src/layouts/UILayout/config/components/feedback.config.tsx +0 -290
- package/src/layouts/UILayout/config/components/forms.config.tsx +0 -996
- package/src/layouts/UILayout/config/components/hooks.config.tsx +0 -168
- package/src/layouts/UILayout/config/components/index.ts +0 -72
- package/src/layouts/UILayout/config/components/layout.config.tsx +0 -246
- package/src/layouts/UILayout/config/components/navigation.config.tsx +0 -352
- package/src/layouts/UILayout/config/components/overlay.config.tsx +0 -569
- package/src/layouts/UILayout/config/components/specialized.config.tsx +0 -400
- package/src/layouts/UILayout/config/components/tools.config.tsx +0 -234
- package/src/layouts/UILayout/config/components/types.ts +0 -14
- package/src/layouts/UILayout/config/index.ts +0 -42
- package/src/layouts/UILayout/config/tailwind.config.ts +0 -131
- package/src/layouts/UILayout/constants.ts +0 -23
- package/src/layouts/UILayout/context/ShowcaseContext.tsx +0 -81
- package/src/layouts/UILayout/context/index.ts +0 -1
- package/src/layouts/UILayout/core/UIGuideApp.client.tsx +0 -18
- package/src/layouts/UILayout/core/UIGuideApp.tsx +0 -33
- package/src/layouts/UILayout/core/UIGuideLanding.tsx +0 -172
- package/src/layouts/UILayout/core/UIGuideView.tsx +0 -61
- package/src/layouts/UILayout/core/UILayout.tsx +0 -125
- package/src/layouts/UILayout/core/UILayoutSidebar.tsx +0 -11
- package/src/layouts/UILayout/core/index.ts +0 -10
- package/src/layouts/UILayout/hooks/index.ts +0 -9
- package/src/layouts/UILayout/hooks/useAIExport.ts +0 -78
- package/src/layouts/UILayout/hooks/useCategoryNavigation.ts +0 -92
- package/src/layouts/UILayout/hooks/useComponentSearch.ts +0 -81
- package/src/layouts/UILayout/hooks/useSidebarState.ts +0 -36
- package/src/layouts/UILayout/index.ts +0 -160
- package/src/layouts/UILayout/types/component.ts +0 -45
- package/src/layouts/UILayout/types/index.ts +0 -23
- package/src/layouts/UILayout/types/layout.ts +0 -57
- package/src/layouts/UILayout/types/navigation.ts +0 -33
- package/src/layouts/UILayout/utils/ai-export/formatters.ts +0 -71
- package/src/layouts/UILayout/utils/ai-export/index.ts +0 -5
- package/src/layouts/UILayout/utils/component-helpers/filter.ts +0 -109
- package/src/layouts/UILayout/utils/component-helpers/index.ts +0 -6
- package/src/layouts/UILayout/utils/component-helpers/search.ts +0 -95
- package/src/layouts/UILayout/utils/index.ts +0 -6
|
@@ -1,138 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* TailwindGuideRenderer
|
|
3
|
-
* Renders Tailwind CSS v4 guide from config
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
'use client';
|
|
7
|
-
|
|
8
|
-
import React from 'react';
|
|
9
|
-
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@djangocfg/ui';
|
|
10
|
-
import { PrettyCode } from '@djangocfg/ui/tools';
|
|
11
|
-
import { TAILWIND_GUIDE } from '../config';
|
|
12
|
-
import { CategorySection } from './AutoComponentDemo';
|
|
13
|
-
|
|
14
|
-
/**
|
|
15
|
-
* TailwindGuideRenderer - Dynamically renders Tailwind guide from config
|
|
16
|
-
*/
|
|
17
|
-
export function TailwindGuideRenderer() {
|
|
18
|
-
return (
|
|
19
|
-
<CategorySection
|
|
20
|
-
title="Tailwind CSS v4 Guide"
|
|
21
|
-
description="Everything you need to know about migrating to and using Tailwind CSS v4"
|
|
22
|
-
>
|
|
23
|
-
{/* Key Changes */}
|
|
24
|
-
<Card>
|
|
25
|
-
<CardHeader>
|
|
26
|
-
<CardTitle>Key Changes in Tailwind CSS v{TAILWIND_GUIDE.version}</CardTitle>
|
|
27
|
-
<CardDescription>
|
|
28
|
-
Major improvements and breaking changes you should know about
|
|
29
|
-
</CardDescription>
|
|
30
|
-
</CardHeader>
|
|
31
|
-
<CardContent>
|
|
32
|
-
<ul className="list-disc list-inside space-y-2 text-muted-foreground">
|
|
33
|
-
{TAILWIND_GUIDE.keyChanges.map((change, index) => (
|
|
34
|
-
<li key={index}>{change}</li>
|
|
35
|
-
))}
|
|
36
|
-
</ul>
|
|
37
|
-
</CardContent>
|
|
38
|
-
</Card>
|
|
39
|
-
|
|
40
|
-
{/* Best Practices */}
|
|
41
|
-
<Card>
|
|
42
|
-
<CardHeader>
|
|
43
|
-
<CardTitle>Best Practices</CardTitle>
|
|
44
|
-
<CardDescription>
|
|
45
|
-
Follow these patterns for clean, maintainable code
|
|
46
|
-
</CardDescription>
|
|
47
|
-
</CardHeader>
|
|
48
|
-
<CardContent>
|
|
49
|
-
<div className="space-y-4">
|
|
50
|
-
<div>
|
|
51
|
-
<h3 className="font-semibold mb-2">โ
Recommended Patterns</h3>
|
|
52
|
-
<ul className="list-disc list-inside space-y-1 text-muted-foreground ml-4">
|
|
53
|
-
{TAILWIND_GUIDE.bestPractices.map((practice, index) => (
|
|
54
|
-
<li key={index}>{practice}</li>
|
|
55
|
-
))}
|
|
56
|
-
</ul>
|
|
57
|
-
</div>
|
|
58
|
-
</div>
|
|
59
|
-
</CardContent>
|
|
60
|
-
</Card>
|
|
61
|
-
|
|
62
|
-
{/* Migration Steps */}
|
|
63
|
-
<Card>
|
|
64
|
-
<CardHeader>
|
|
65
|
-
<CardTitle>Migration Steps (v3 โ v4)</CardTitle>
|
|
66
|
-
<CardDescription>
|
|
67
|
-
Step-by-step guide to upgrade your project
|
|
68
|
-
</CardDescription>
|
|
69
|
-
</CardHeader>
|
|
70
|
-
<CardContent>
|
|
71
|
-
<ol className="list-decimal list-inside space-y-2 text-muted-foreground">
|
|
72
|
-
{TAILWIND_GUIDE.migrationSteps.map((step, index) => (
|
|
73
|
-
<li key={index}>{step}</li>
|
|
74
|
-
))}
|
|
75
|
-
</ol>
|
|
76
|
-
</CardContent>
|
|
77
|
-
</Card>
|
|
78
|
-
|
|
79
|
-
{/* Examples */}
|
|
80
|
-
{TAILWIND_GUIDE.examples.map((example, index) => (
|
|
81
|
-
<Card key={index}>
|
|
82
|
-
<CardHeader>
|
|
83
|
-
<CardTitle>{example.title}</CardTitle>
|
|
84
|
-
<CardDescription>{example.description}</CardDescription>
|
|
85
|
-
</CardHeader>
|
|
86
|
-
<CardContent>
|
|
87
|
-
<PrettyCode
|
|
88
|
-
data={example.code}
|
|
89
|
-
language="css"
|
|
90
|
-
className="text-sm"
|
|
91
|
-
/>
|
|
92
|
-
</CardContent>
|
|
93
|
-
</Card>
|
|
94
|
-
))}
|
|
95
|
-
|
|
96
|
-
{/* Resources */}
|
|
97
|
-
<Card>
|
|
98
|
-
<CardHeader>
|
|
99
|
-
<CardTitle>Official Resources</CardTitle>
|
|
100
|
-
</CardHeader>
|
|
101
|
-
<CardContent>
|
|
102
|
-
<ul className="space-y-2">
|
|
103
|
-
<li>
|
|
104
|
-
<a
|
|
105
|
-
href="https://tailwindcss.com/docs/upgrade-guide"
|
|
106
|
-
target="_blank"
|
|
107
|
-
rel="noopener noreferrer"
|
|
108
|
-
className="text-primary hover:underline"
|
|
109
|
-
>
|
|
110
|
-
Official Upgrade Guide
|
|
111
|
-
</a>
|
|
112
|
-
</li>
|
|
113
|
-
<li>
|
|
114
|
-
<a
|
|
115
|
-
href="https://tailwindcss.com/docs/guides/nextjs"
|
|
116
|
-
target="_blank"
|
|
117
|
-
rel="noopener noreferrer"
|
|
118
|
-
className="text-primary hover:underline"
|
|
119
|
-
>
|
|
120
|
-
Next.js Integration Guide
|
|
121
|
-
</a>
|
|
122
|
-
</li>
|
|
123
|
-
<li>
|
|
124
|
-
<a
|
|
125
|
-
href="https://tailwindcss.com/blog/tailwindcss-v4"
|
|
126
|
-
target="_blank"
|
|
127
|
-
rel="noopener noreferrer"
|
|
128
|
-
className="text-primary hover:underline"
|
|
129
|
-
>
|
|
130
|
-
Tailwind CSS v4.0 Release Notes
|
|
131
|
-
</a>
|
|
132
|
-
</li>
|
|
133
|
-
</ul>
|
|
134
|
-
</CardContent>
|
|
135
|
-
</Card>
|
|
136
|
-
</CategorySection>
|
|
137
|
-
);
|
|
138
|
-
}
|
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* UILayout Components
|
|
3
|
-
* All UI components for UILayout
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
// Layout components
|
|
7
|
-
export * from './layout';
|
|
8
|
-
|
|
9
|
-
// Shared components
|
|
10
|
-
export * from './shared';
|
|
11
|
-
|
|
12
|
-
// Content components (keeping old exports for backward compatibility)
|
|
13
|
-
export { AutoComponentDemo, CategorySection } from './AutoComponentDemo';
|
|
14
|
-
export { CategoryRenderer } from './CategoryRenderer';
|
|
15
|
-
export { TailwindGuideRenderer } from './TailwindGuideRenderer';
|
|
@@ -1,58 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* CopyAIButton Component
|
|
3
|
-
* Button for copying AI context to clipboard
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
'use client';
|
|
7
|
-
|
|
8
|
-
import React from 'react';
|
|
9
|
-
import { Button } from '@djangocfg/ui';
|
|
10
|
-
import { Sparkles, Check } from 'lucide-react';
|
|
11
|
-
import { useAIExport } from '../../../hooks';
|
|
12
|
-
|
|
13
|
-
interface CopyAIButtonProps {
|
|
14
|
-
/** Function to generate AI context - must return string */
|
|
15
|
-
onCopyForAI?: () => string;
|
|
16
|
-
/** Button size */
|
|
17
|
-
size?: 'sm' | 'default' | 'lg';
|
|
18
|
-
/** Show text label */
|
|
19
|
-
showLabel?: boolean;
|
|
20
|
-
/** Custom class name */
|
|
21
|
-
className?: string;
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
/**
|
|
25
|
-
* Copy for AI Button
|
|
26
|
-
* Shows "Copied!" feedback after successful copy
|
|
27
|
-
*/
|
|
28
|
-
export function CopyAIButton({
|
|
29
|
-
onCopyForAI,
|
|
30
|
-
size = 'sm',
|
|
31
|
-
showLabel = true,
|
|
32
|
-
className,
|
|
33
|
-
}: CopyAIButtonProps) {
|
|
34
|
-
const { copied, exportForAI } = useAIExport({
|
|
35
|
-
generateContext: onCopyForAI,
|
|
36
|
-
});
|
|
37
|
-
|
|
38
|
-
return (
|
|
39
|
-
<Button
|
|
40
|
-
variant="outline"
|
|
41
|
-
size={size}
|
|
42
|
-
onClick={exportForAI}
|
|
43
|
-
className={className}
|
|
44
|
-
>
|
|
45
|
-
{copied ? (
|
|
46
|
-
<>
|
|
47
|
-
<Check className="h-4 w-4" />
|
|
48
|
-
{showLabel && <span className="ml-2">Copied!</span>}
|
|
49
|
-
</>
|
|
50
|
-
) : (
|
|
51
|
-
<>
|
|
52
|
-
<Sparkles className="h-4 w-4" />
|
|
53
|
-
{showLabel && <span className="ml-2">Copy for AI</span>}
|
|
54
|
-
</>
|
|
55
|
-
)}
|
|
56
|
-
</Button>
|
|
57
|
-
);
|
|
58
|
-
}
|
|
@@ -1,60 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Header Component
|
|
3
|
-
* Simple unified header for UI documentation
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
'use client';
|
|
7
|
-
|
|
8
|
-
import React from 'react';
|
|
9
|
-
import { CopyAIButton } from './CopyAIButton';
|
|
10
|
-
import { TestValidationButton } from './TestValidationButton';
|
|
11
|
-
|
|
12
|
-
export interface HeaderProps {
|
|
13
|
-
/** Page title */
|
|
14
|
-
title?: string;
|
|
15
|
-
/** Project name */
|
|
16
|
-
projectName?: string;
|
|
17
|
-
/** Logo component */
|
|
18
|
-
logo?: React.ReactNode;
|
|
19
|
-
/** Copy for AI callback - must return string */
|
|
20
|
-
onCopyForAI?: () => string;
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
/**
|
|
24
|
-
* Header Component
|
|
25
|
-
* Displays title and Copy for AI button
|
|
26
|
-
*/
|
|
27
|
-
export function Header({
|
|
28
|
-
title = 'UI Component Library',
|
|
29
|
-
projectName = 'Django CFG',
|
|
30
|
-
logo,
|
|
31
|
-
onCopyForAI,
|
|
32
|
-
}: HeaderProps) {
|
|
33
|
-
return (
|
|
34
|
-
<header className="w-full border-b bg-background">
|
|
35
|
-
<div className="container mx-auto max-w-7xl px-4 sm:px-6 lg:px-8">
|
|
36
|
-
<div className="flex items-center justify-between h-16">
|
|
37
|
-
{/* Left: Logo and Title */}
|
|
38
|
-
<div className="flex items-center gap-3">
|
|
39
|
-
{logo && <div className="flex-shrink-0">{logo}</div>}
|
|
40
|
-
<div className="flex flex-col">
|
|
41
|
-
<h1 className="text-lg font-semibold tracking-tight">{title}</h1>
|
|
42
|
-
<p className="text-xs text-muted-foreground hidden sm:block">{projectName}</p>
|
|
43
|
-
</div>
|
|
44
|
-
</div>
|
|
45
|
-
|
|
46
|
-
{/* Right: Developer Tools */}
|
|
47
|
-
<div className="flex items-center gap-2">
|
|
48
|
-
{/* Test Validation Error Button (dev only) */}
|
|
49
|
-
<TestValidationButton size="sm" />
|
|
50
|
-
|
|
51
|
-
{/* Copy for AI Button */}
|
|
52
|
-
{onCopyForAI && (
|
|
53
|
-
<CopyAIButton onCopyForAI={onCopyForAI} />
|
|
54
|
-
)}
|
|
55
|
-
</div>
|
|
56
|
-
</div>
|
|
57
|
-
</div>
|
|
58
|
-
</header>
|
|
59
|
-
);
|
|
60
|
-
}
|
|
@@ -1,51 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* HeaderDesktop Component
|
|
3
|
-
* Desktop version of the header
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
'use client';
|
|
7
|
-
|
|
8
|
-
import React from 'react';
|
|
9
|
-
import { CopyAIButton } from './CopyAIButton';
|
|
10
|
-
import { TestValidationButton } from './TestValidationButton';
|
|
11
|
-
|
|
12
|
-
interface HeaderDesktopProps {
|
|
13
|
-
/** Page title */
|
|
14
|
-
title?: string;
|
|
15
|
-
/** Copy for AI callback - must return string */
|
|
16
|
-
onCopyForAI?: () => string;
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
/**
|
|
20
|
-
* Desktop Header
|
|
21
|
-
* Full-width header for desktop with page title and actions
|
|
22
|
-
*/
|
|
23
|
-
export function HeaderDesktop({
|
|
24
|
-
title = 'UI Component Library',
|
|
25
|
-
onCopyForAI,
|
|
26
|
-
}: HeaderDesktopProps) {
|
|
27
|
-
return (
|
|
28
|
-
<div className="border-b bg-background/95 backdrop-blur supports-[backdrop-filter]:bg-background/60">
|
|
29
|
-
<div className="flex h-14 items-center gap-4 px-6">
|
|
30
|
-
{/* Page Title */}
|
|
31
|
-
<div className="flex-1">
|
|
32
|
-
<h1 className="text-lg font-semibold">{title}</h1>
|
|
33
|
-
</div>
|
|
34
|
-
|
|
35
|
-
{/* Developer Tools */}
|
|
36
|
-
<div className="flex items-center gap-2">
|
|
37
|
-
{/* Test Validation Error Button (dev only) */}
|
|
38
|
-
<TestValidationButton size="sm" />
|
|
39
|
-
|
|
40
|
-
{/* Copy for AI Button */}
|
|
41
|
-
<CopyAIButton
|
|
42
|
-
onCopyForAI={onCopyForAI}
|
|
43
|
-
size="sm"
|
|
44
|
-
showLabel={true}
|
|
45
|
-
className="gap-2"
|
|
46
|
-
/>
|
|
47
|
-
</div>
|
|
48
|
-
</div>
|
|
49
|
-
</div>
|
|
50
|
-
);
|
|
51
|
-
}
|
|
@@ -1,71 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* HeaderMobile Component
|
|
3
|
-
* Mobile version of the header
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
'use client';
|
|
7
|
-
|
|
8
|
-
import React from 'react';
|
|
9
|
-
import { Button } from '@djangocfg/ui';
|
|
10
|
-
import { Menu, X } from 'lucide-react';
|
|
11
|
-
import { CopyAIButton } from './CopyAIButton';
|
|
12
|
-
|
|
13
|
-
interface HeaderMobileProps {
|
|
14
|
-
/** Project name */
|
|
15
|
-
projectName?: string;
|
|
16
|
-
/** Logo component */
|
|
17
|
-
logo?: React.ReactNode;
|
|
18
|
-
/** Is sidebar open */
|
|
19
|
-
isSidebarOpen?: boolean;
|
|
20
|
-
/** Toggle sidebar callback */
|
|
21
|
-
onToggleSidebar?: () => void;
|
|
22
|
-
/** Copy for AI callback - must return string */
|
|
23
|
-
onCopyForAI?: () => string;
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
/**
|
|
27
|
-
* Mobile Header
|
|
28
|
-
* Compact header for mobile devices with hamburger menu
|
|
29
|
-
*/
|
|
30
|
-
export function HeaderMobile({
|
|
31
|
-
projectName = 'Django CFG',
|
|
32
|
-
logo,
|
|
33
|
-
isSidebarOpen = false,
|
|
34
|
-
onToggleSidebar,
|
|
35
|
-
onCopyForAI,
|
|
36
|
-
}: HeaderMobileProps) {
|
|
37
|
-
return (
|
|
38
|
-
<header className="w-full border-b bg-background/95 backdrop-blur supports-[backdrop-filter]:bg-background/60">
|
|
39
|
-
<div className="flex h-14 items-center px-4 gap-4">
|
|
40
|
-
{/* Hamburger Menu Button */}
|
|
41
|
-
<Button
|
|
42
|
-
variant="ghost"
|
|
43
|
-
size="icon"
|
|
44
|
-
className="h-9 w-9"
|
|
45
|
-
onClick={onToggleSidebar}
|
|
46
|
-
aria-label={isSidebarOpen ? 'Close menu' : 'Open menu'}
|
|
47
|
-
>
|
|
48
|
-
{isSidebarOpen ? (
|
|
49
|
-
<X className="h-5 w-5" />
|
|
50
|
-
) : (
|
|
51
|
-
<Menu className="h-5 w-5" />
|
|
52
|
-
)}
|
|
53
|
-
</Button>
|
|
54
|
-
|
|
55
|
-
{/* Logo and Project Name */}
|
|
56
|
-
<div className="flex items-center gap-2 flex-1">
|
|
57
|
-
{logo}
|
|
58
|
-
<span className="font-semibold text-sm">{projectName}</span>
|
|
59
|
-
</div>
|
|
60
|
-
|
|
61
|
-
{/* Copy for AI Button */}
|
|
62
|
-
<CopyAIButton
|
|
63
|
-
onCopyForAI={onCopyForAI}
|
|
64
|
-
size="sm"
|
|
65
|
-
showLabel={false}
|
|
66
|
-
className="gap-2"
|
|
67
|
-
/>
|
|
68
|
-
</div>
|
|
69
|
-
</header>
|
|
70
|
-
);
|
|
71
|
-
}
|
|
@@ -1,268 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* TestValidationButton Component
|
|
3
|
-
*
|
|
4
|
-
* Developer tool for testing Zod validation error events
|
|
5
|
-
* Dispatches mock CustomEvent to test ValidationErrorProvider
|
|
6
|
-
*
|
|
7
|
-
* Only visible in development mode
|
|
8
|
-
*/
|
|
9
|
-
|
|
10
|
-
'use client';
|
|
11
|
-
|
|
12
|
-
import React, { useState } from 'react';
|
|
13
|
-
import { Button } from '@djangocfg/ui';
|
|
14
|
-
import {
|
|
15
|
-
DropdownMenu,
|
|
16
|
-
DropdownMenuContent,
|
|
17
|
-
DropdownMenuItem,
|
|
18
|
-
DropdownMenuLabel,
|
|
19
|
-
DropdownMenuSeparator,
|
|
20
|
-
DropdownMenuTrigger,
|
|
21
|
-
} from '@djangocfg/ui';
|
|
22
|
-
import { Bug, AlertCircle } from 'lucide-react';
|
|
23
|
-
|
|
24
|
-
/**
|
|
25
|
-
* Mock Zod error factory
|
|
26
|
-
*/
|
|
27
|
-
function createMockZodError(type: 'simple' | 'multiple' | 'nested' | 'array') {
|
|
28
|
-
const errors: Record<string, any> = {
|
|
29
|
-
simple: {
|
|
30
|
-
issues: [
|
|
31
|
-
{
|
|
32
|
-
path: ['email'],
|
|
33
|
-
message: 'Invalid email format',
|
|
34
|
-
code: 'invalid_string',
|
|
35
|
-
expected: 'email',
|
|
36
|
-
received: 'string',
|
|
37
|
-
}
|
|
38
|
-
]
|
|
39
|
-
},
|
|
40
|
-
multiple: {
|
|
41
|
-
issues: [
|
|
42
|
-
{
|
|
43
|
-
path: ['email'],
|
|
44
|
-
message: 'Invalid email format',
|
|
45
|
-
code: 'invalid_string',
|
|
46
|
-
},
|
|
47
|
-
{
|
|
48
|
-
path: ['age'],
|
|
49
|
-
message: 'Number must be greater than 0',
|
|
50
|
-
code: 'too_small',
|
|
51
|
-
minimum: 0,
|
|
52
|
-
},
|
|
53
|
-
{
|
|
54
|
-
path: ['username'],
|
|
55
|
-
message: 'Required field',
|
|
56
|
-
code: 'invalid_type',
|
|
57
|
-
expected: 'string',
|
|
58
|
-
received: 'undefined',
|
|
59
|
-
}
|
|
60
|
-
]
|
|
61
|
-
},
|
|
62
|
-
nested: {
|
|
63
|
-
issues: [
|
|
64
|
-
{
|
|
65
|
-
path: ['address', 'street'],
|
|
66
|
-
message: 'Street is required',
|
|
67
|
-
code: 'invalid_type',
|
|
68
|
-
},
|
|
69
|
-
{
|
|
70
|
-
path: ['address', 'zipCode'],
|
|
71
|
-
message: 'Invalid zip code format',
|
|
72
|
-
code: 'invalid_string',
|
|
73
|
-
}
|
|
74
|
-
]
|
|
75
|
-
},
|
|
76
|
-
array: {
|
|
77
|
-
issues: [
|
|
78
|
-
{
|
|
79
|
-
path: ['items', 0, 'quantity'],
|
|
80
|
-
message: 'Quantity must be at least 1',
|
|
81
|
-
code: 'too_small',
|
|
82
|
-
minimum: 1,
|
|
83
|
-
},
|
|
84
|
-
{
|
|
85
|
-
path: ['items', 1, 'price'],
|
|
86
|
-
message: 'Price is required',
|
|
87
|
-
code: 'invalid_type',
|
|
88
|
-
}
|
|
89
|
-
]
|
|
90
|
-
},
|
|
91
|
-
};
|
|
92
|
-
|
|
93
|
-
return errors[type];
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
/**
|
|
97
|
-
* Dispatch validation error event
|
|
98
|
-
*/
|
|
99
|
-
function dispatchValidationError(type: 'simple' | 'multiple' | 'nested' | 'array') {
|
|
100
|
-
const operations: Record<string, { operation: string; path: string; method: string; response: any }> = {
|
|
101
|
-
simple: {
|
|
102
|
-
operation: 'createUser',
|
|
103
|
-
path: '/api/users',
|
|
104
|
-
method: 'POST',
|
|
105
|
-
response: { email: 'not-an-email@' },
|
|
106
|
-
},
|
|
107
|
-
multiple: {
|
|
108
|
-
operation: 'updateProfile',
|
|
109
|
-
path: '/api/profile/123',
|
|
110
|
-
method: 'PATCH',
|
|
111
|
-
response: { email: 'bad', age: -5 },
|
|
112
|
-
},
|
|
113
|
-
nested: {
|
|
114
|
-
operation: 'createAddress',
|
|
115
|
-
path: '/api/addresses',
|
|
116
|
-
method: 'POST',
|
|
117
|
-
response: { address: { street: null, zipCode: '12' } },
|
|
118
|
-
},
|
|
119
|
-
array: {
|
|
120
|
-
operation: 'createOrder',
|
|
121
|
-
path: '/api/orders',
|
|
122
|
-
method: 'POST',
|
|
123
|
-
response: { items: [{ quantity: 0 }, { price: undefined }] },
|
|
124
|
-
},
|
|
125
|
-
};
|
|
126
|
-
|
|
127
|
-
const config = operations[type];
|
|
128
|
-
const error = createMockZodError(type);
|
|
129
|
-
|
|
130
|
-
const event = new CustomEvent('zod-validation-error', {
|
|
131
|
-
detail: {
|
|
132
|
-
operation: config.operation,
|
|
133
|
-
path: config.path,
|
|
134
|
-
method: config.method,
|
|
135
|
-
error: error,
|
|
136
|
-
response: config.response,
|
|
137
|
-
timestamp: new Date(),
|
|
138
|
-
},
|
|
139
|
-
bubbles: true,
|
|
140
|
-
cancelable: false,
|
|
141
|
-
});
|
|
142
|
-
|
|
143
|
-
window.dispatchEvent(event);
|
|
144
|
-
|
|
145
|
-
console.group('๐งช Test Validation Error Dispatched');
|
|
146
|
-
console.log('Type:', type);
|
|
147
|
-
console.log('Operation:', config.operation);
|
|
148
|
-
console.log('Endpoint:', config.method, config.path);
|
|
149
|
-
console.log('Issues:', error.issues);
|
|
150
|
-
console.groupEnd();
|
|
151
|
-
}
|
|
152
|
-
|
|
153
|
-
export interface TestValidationButtonProps {
|
|
154
|
-
/** Show in production (default: false - dev only) */
|
|
155
|
-
showInProduction?: boolean;
|
|
156
|
-
/** Button size */
|
|
157
|
-
size?: 'default' | 'sm' | 'lg' | 'icon';
|
|
158
|
-
/** Additional CSS classes */
|
|
159
|
-
className?: string;
|
|
160
|
-
/** Always show label (default: responsive - hidden on mobile) */
|
|
161
|
-
showLabel?: boolean;
|
|
162
|
-
}
|
|
163
|
-
|
|
164
|
-
/**
|
|
165
|
-
* Test Validation Button
|
|
166
|
-
*
|
|
167
|
-
* Dropdown menu with different validation error test cases
|
|
168
|
-
* Only visible in development by default
|
|
169
|
-
*/
|
|
170
|
-
export function TestValidationButton({
|
|
171
|
-
showInProduction = false,
|
|
172
|
-
size = 'sm',
|
|
173
|
-
className,
|
|
174
|
-
showLabel = false,
|
|
175
|
-
}: TestValidationButtonProps) {
|
|
176
|
-
const [isOpen, setIsOpen] = useState(false);
|
|
177
|
-
|
|
178
|
-
// Hide in production unless explicitly enabled
|
|
179
|
-
if (!showInProduction && process.env.NODE_ENV === 'production') {
|
|
180
|
-
return null;
|
|
181
|
-
}
|
|
182
|
-
|
|
183
|
-
return (
|
|
184
|
-
<DropdownMenu open={isOpen} onOpenChange={setIsOpen}>
|
|
185
|
-
<DropdownMenuTrigger asChild>
|
|
186
|
-
<Button
|
|
187
|
-
variant="outline"
|
|
188
|
-
size={size}
|
|
189
|
-
className={className}
|
|
190
|
-
>
|
|
191
|
-
<Bug className="h-4 w-4" />
|
|
192
|
-
<span className={showLabel ? "ml-2" : "ml-2 hidden sm:inline"}>Test Validation</span>
|
|
193
|
-
</Button>
|
|
194
|
-
</DropdownMenuTrigger>
|
|
195
|
-
|
|
196
|
-
<DropdownMenuContent align="end" className="w-[240px]">
|
|
197
|
-
<DropdownMenuLabel className="flex items-center gap-2">
|
|
198
|
-
<AlertCircle className="h-4 w-4 text-orange-500" />
|
|
199
|
-
<span>Test Validation Errors</span>
|
|
200
|
-
</DropdownMenuLabel>
|
|
201
|
-
|
|
202
|
-
<DropdownMenuSeparator />
|
|
203
|
-
|
|
204
|
-
<DropdownMenuItem
|
|
205
|
-
onClick={() => {
|
|
206
|
-
dispatchValidationError('simple');
|
|
207
|
-
setIsOpen(false);
|
|
208
|
-
}}
|
|
209
|
-
>
|
|
210
|
-
<div className="flex flex-col gap-1">
|
|
211
|
-
<div className="font-medium">Simple Error</div>
|
|
212
|
-
<div className="text-xs text-muted-foreground">
|
|
213
|
-
Single field validation
|
|
214
|
-
</div>
|
|
215
|
-
</div>
|
|
216
|
-
</DropdownMenuItem>
|
|
217
|
-
|
|
218
|
-
<DropdownMenuItem
|
|
219
|
-
onClick={() => {
|
|
220
|
-
dispatchValidationError('multiple');
|
|
221
|
-
setIsOpen(false);
|
|
222
|
-
}}
|
|
223
|
-
>
|
|
224
|
-
<div className="flex flex-col gap-1">
|
|
225
|
-
<div className="font-medium">Multiple Errors</div>
|
|
226
|
-
<div className="text-xs text-muted-foreground">
|
|
227
|
-
3 validation errors
|
|
228
|
-
</div>
|
|
229
|
-
</div>
|
|
230
|
-
</DropdownMenuItem>
|
|
231
|
-
|
|
232
|
-
<DropdownMenuItem
|
|
233
|
-
onClick={() => {
|
|
234
|
-
dispatchValidationError('nested');
|
|
235
|
-
setIsOpen(false);
|
|
236
|
-
}}
|
|
237
|
-
>
|
|
238
|
-
<div className="flex flex-col gap-1">
|
|
239
|
-
<div className="font-medium">Nested Object</div>
|
|
240
|
-
<div className="text-xs text-muted-foreground">
|
|
241
|
-
Nested property errors
|
|
242
|
-
</div>
|
|
243
|
-
</div>
|
|
244
|
-
</DropdownMenuItem>
|
|
245
|
-
|
|
246
|
-
<DropdownMenuItem
|
|
247
|
-
onClick={() => {
|
|
248
|
-
dispatchValidationError('array');
|
|
249
|
-
setIsOpen(false);
|
|
250
|
-
}}
|
|
251
|
-
>
|
|
252
|
-
<div className="flex flex-col gap-1">
|
|
253
|
-
<div className="font-medium">Array Validation</div>
|
|
254
|
-
<div className="text-xs text-muted-foreground">
|
|
255
|
-
Array item errors
|
|
256
|
-
</div>
|
|
257
|
-
</div>
|
|
258
|
-
</DropdownMenuItem>
|
|
259
|
-
|
|
260
|
-
<DropdownMenuSeparator />
|
|
261
|
-
|
|
262
|
-
<div className="px-2 py-1.5 text-xs text-muted-foreground">
|
|
263
|
-
๐ก Check console and toast notifications
|
|
264
|
-
</div>
|
|
265
|
-
</DropdownMenuContent>
|
|
266
|
-
</DropdownMenu>
|
|
267
|
-
);
|
|
268
|
-
}
|
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Header Components
|
|
3
|
-
*/
|
|
4
|
-
|
|
5
|
-
export { Header } from './Header';
|
|
6
|
-
export type { HeaderProps } from './Header';
|
|
7
|
-
export { HeaderMobile } from './HeaderMobile';
|
|
8
|
-
export { HeaderDesktop } from './HeaderDesktop';
|
|
9
|
-
export { CopyAIButton } from './CopyAIButton';
|
|
10
|
-
export { TestValidationButton } from './TestValidationButton';
|
|
11
|
-
export type { TestValidationButtonProps } from './TestValidationButton';
|