@djangocfg/layouts 1.2.17 → 1.2.18
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 +5 -5
- package/src/layouts/AppLayout/components/PackageVersions/packageVersions.config.ts +8 -8
- package/src/layouts/UILayout/SUMMARY.md +298 -0
- package/src/layouts/UILayout/components/index.ts +15 -0
- package/src/layouts/UILayout/components/layout/Header/CopyAIButton.tsx +58 -0
- package/src/layouts/UILayout/components/layout/Header/Header.tsx +60 -0
- package/src/layouts/UILayout/components/layout/Header/HeaderDesktop.tsx +44 -0
- package/src/layouts/UILayout/components/layout/Header/HeaderMobile.tsx +71 -0
- package/src/layouts/UILayout/components/layout/Header/index.ts +9 -0
- package/src/layouts/UILayout/components/layout/MobileOverlay/MobileOverlay.tsx +46 -0
- package/src/layouts/UILayout/components/layout/MobileOverlay/index.ts +6 -0
- package/src/layouts/UILayout/components/layout/Sidebar/Sidebar.tsx +94 -0
- package/src/layouts/UILayout/components/layout/Sidebar/SidebarCategory.tsx +54 -0
- package/src/layouts/UILayout/components/layout/Sidebar/SidebarContent.tsx +86 -0
- package/src/layouts/UILayout/components/layout/Sidebar/SidebarFooter.tsx +49 -0
- package/src/layouts/UILayout/components/layout/Sidebar/index.ts +9 -0
- package/src/layouts/UILayout/components/layout/index.ts +8 -0
- package/src/layouts/UILayout/components/shared/Badge/CountBadge.tsx +38 -0
- package/src/layouts/UILayout/components/shared/Badge/index.ts +5 -0
- package/src/layouts/UILayout/components/shared/CodeBlock/CodeBlock.tsx +48 -0
- package/src/layouts/UILayout/components/shared/CodeBlock/CopyButton.tsx +49 -0
- package/src/layouts/UILayout/components/shared/CodeBlock/index.ts +6 -0
- package/src/layouts/UILayout/components/shared/Section/Section.tsx +63 -0
- package/src/layouts/UILayout/components/shared/Section/index.ts +5 -0
- package/src/layouts/UILayout/components/shared/index.ts +8 -0
- package/src/layouts/UILayout/{UIGuideLanding.tsx → core/UIGuideLanding.tsx} +1 -1
- package/src/layouts/UILayout/{UIGuideView.tsx → core/UIGuideView.tsx} +4 -4
- package/src/layouts/UILayout/{UILayout.tsx → core/UILayout.tsx} +8 -25
- package/src/layouts/UILayout/core/index.ts +9 -0
- package/src/layouts/UILayout/hooks/index.ts +9 -0
- package/src/layouts/UILayout/hooks/useAIExport.ts +78 -0
- package/src/layouts/UILayout/hooks/useCategoryNavigation.ts +92 -0
- package/src/layouts/UILayout/hooks/useComponentSearch.ts +81 -0
- package/src/layouts/UILayout/hooks/useSidebarState.ts +36 -0
- package/src/layouts/UILayout/index.ts +121 -22
- package/src/layouts/UILayout/types/component.ts +45 -0
- package/src/layouts/UILayout/types/index.ts +23 -0
- package/src/layouts/UILayout/types/layout.ts +59 -0
- package/src/layouts/UILayout/types/navigation.ts +33 -0
- package/src/layouts/UILayout/utils/ai-export/formatters.ts +71 -0
- package/src/layouts/UILayout/utils/ai-export/generators.ts +130 -0
- package/src/layouts/UILayout/utils/ai-export/index.ts +6 -0
- package/src/layouts/UILayout/utils/component-helpers/filter.ts +109 -0
- package/src/layouts/UILayout/utils/component-helpers/index.ts +6 -0
- package/src/layouts/UILayout/utils/component-helpers/search.ts +95 -0
- package/src/layouts/UILayout/utils/index.ts +6 -0
- package/src/layouts/UILayout/REFACTORING.md +0 -331
- package/src/layouts/UILayout/components/Header.tsx +0 -114
- package/src/layouts/UILayout/components/MobileOverlay.tsx +0 -33
- package/src/layouts/UILayout/components/Sidebar.tsx +0 -188
- package/src/layouts/UILayout/types.ts +0 -13
- /package/src/layouts/UILayout/{UIGuideApp.tsx → core/UIGuideApp.tsx} +0 -0
|
@@ -1,114 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Header Component
|
|
3
|
-
* Top header for mobile and page title with Copy for AI button
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
'use client';
|
|
7
|
-
|
|
8
|
-
import React, { useState } from 'react';
|
|
9
|
-
import { Button, useIsMobile, useCopy } from '@djangocfg/ui';
|
|
10
|
-
import { Menu, X, Sparkles, Check } from 'lucide-react';
|
|
11
|
-
|
|
12
|
-
interface HeaderProps {
|
|
13
|
-
title?: string;
|
|
14
|
-
projectName?: string;
|
|
15
|
-
logo?: React.ReactNode;
|
|
16
|
-
isSidebarOpen?: boolean;
|
|
17
|
-
onToggleSidebar?: () => void;
|
|
18
|
-
onCopyForAI?: () => void;
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
export function Header({
|
|
22
|
-
title = 'UI Component Library',
|
|
23
|
-
projectName = 'Django CFG',
|
|
24
|
-
logo,
|
|
25
|
-
isSidebarOpen = false,
|
|
26
|
-
onToggleSidebar,
|
|
27
|
-
onCopyForAI,
|
|
28
|
-
}: HeaderProps) {
|
|
29
|
-
const isMobile = useIsMobile();
|
|
30
|
-
const { copyToClipboard } = useCopy();
|
|
31
|
-
const [copied, setCopied] = useState(false);
|
|
32
|
-
|
|
33
|
-
const handleCopyForAI = async () => {
|
|
34
|
-
if (onCopyForAI) {
|
|
35
|
-
onCopyForAI();
|
|
36
|
-
}
|
|
37
|
-
setCopied(true);
|
|
38
|
-
setTimeout(() => setCopied(false), 2000);
|
|
39
|
-
};
|
|
40
|
-
|
|
41
|
-
return (
|
|
42
|
-
<>
|
|
43
|
-
{/* Mobile Header - only on mobile */}
|
|
44
|
-
{isMobile && (
|
|
45
|
-
<header className="w-full border-b bg-background/95 backdrop-blur supports-[backdrop-filter]:bg-background/60">
|
|
46
|
-
<div className="flex h-14 items-center px-4 gap-4">
|
|
47
|
-
<Button
|
|
48
|
-
variant="ghost"
|
|
49
|
-
size="icon"
|
|
50
|
-
className="h-9 w-9"
|
|
51
|
-
onClick={onToggleSidebar}
|
|
52
|
-
>
|
|
53
|
-
{isSidebarOpen ? <X className="h-5 w-5" /> : <Menu className="h-5 w-5" />}
|
|
54
|
-
</Button>
|
|
55
|
-
|
|
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
|
-
<Button
|
|
62
|
-
variant="outline"
|
|
63
|
-
size="sm"
|
|
64
|
-
onClick={handleCopyForAI}
|
|
65
|
-
className="gap-2"
|
|
66
|
-
>
|
|
67
|
-
{copied ? (
|
|
68
|
-
<>
|
|
69
|
-
<Check className="h-4 w-4" />
|
|
70
|
-
<span className="hidden xs:inline">Copied!</span>
|
|
71
|
-
</>
|
|
72
|
-
) : (
|
|
73
|
-
<>
|
|
74
|
-
<Sparkles className="h-4 w-4" />
|
|
75
|
-
<span className="hidden xs:inline">Copy for AI</span>
|
|
76
|
-
</>
|
|
77
|
-
)}
|
|
78
|
-
</Button>
|
|
79
|
-
</div>
|
|
80
|
-
</header>
|
|
81
|
-
)}
|
|
82
|
-
|
|
83
|
-
{/* Desktop Page Header - only on desktop */}
|
|
84
|
-
{!isMobile && (
|
|
85
|
-
<div className="border-b bg-background/95 backdrop-blur supports-[backdrop-filter]:bg-background/60">
|
|
86
|
-
<div className="flex h-14 items-center gap-4 px-6">
|
|
87
|
-
<div className="flex-1">
|
|
88
|
-
<h1 className="text-lg font-semibold">{title}</h1>
|
|
89
|
-
</div>
|
|
90
|
-
|
|
91
|
-
<Button
|
|
92
|
-
variant="outline"
|
|
93
|
-
size="sm"
|
|
94
|
-
onClick={handleCopyForAI}
|
|
95
|
-
className="gap-2"
|
|
96
|
-
>
|
|
97
|
-
{copied ? (
|
|
98
|
-
<>
|
|
99
|
-
<Check className="h-4 w-4" />
|
|
100
|
-
Copied!
|
|
101
|
-
</>
|
|
102
|
-
) : (
|
|
103
|
-
<>
|
|
104
|
-
<Sparkles className="h-4 w-4" />
|
|
105
|
-
Copy for AI
|
|
106
|
-
</>
|
|
107
|
-
)}
|
|
108
|
-
</Button>
|
|
109
|
-
</div>
|
|
110
|
-
</div>
|
|
111
|
-
)}
|
|
112
|
-
</>
|
|
113
|
-
);
|
|
114
|
-
}
|
|
@@ -1,33 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Mobile Overlay Component
|
|
3
|
-
* Backdrop overlay for mobile sidebar
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
'use client';
|
|
7
|
-
|
|
8
|
-
import React from 'react';
|
|
9
|
-
import { cn } from '@djangocfg/ui/lib';
|
|
10
|
-
import { useIsMobile } from '@djangocfg/ui';
|
|
11
|
-
|
|
12
|
-
interface MobileOverlayProps {
|
|
13
|
-
isOpen: boolean;
|
|
14
|
-
onClose: () => void;
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
export function MobileOverlay({ isOpen, onClose }: MobileOverlayProps) {
|
|
18
|
-
const isMobile = useIsMobile();
|
|
19
|
-
|
|
20
|
-
// Only show on mobile when sidebar is open
|
|
21
|
-
if (!isMobile || !isOpen) return null;
|
|
22
|
-
|
|
23
|
-
return (
|
|
24
|
-
<div
|
|
25
|
-
className={cn(
|
|
26
|
-
"fixed inset-0 z-[150] bg-background/80 backdrop-blur-sm",
|
|
27
|
-
"animate-in fade-in duration-300"
|
|
28
|
-
)}
|
|
29
|
-
onClick={onClose}
|
|
30
|
-
aria-hidden="true"
|
|
31
|
-
/>
|
|
32
|
-
);
|
|
33
|
-
}
|
|
@@ -1,188 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Sidebar Component
|
|
3
|
-
* Navigation sidebar for component categories
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
'use client';
|
|
7
|
-
|
|
8
|
-
import React from 'react';
|
|
9
|
-
import { createPortal } from 'react-dom';
|
|
10
|
-
import { cn } from '@djangocfg/ui/lib';
|
|
11
|
-
import { useIsMobile } from '@djangocfg/ui';
|
|
12
|
-
import type { ComponentCategory } from '../types';
|
|
13
|
-
|
|
14
|
-
interface SidebarProps {
|
|
15
|
-
categories: ComponentCategory[];
|
|
16
|
-
currentCategory?: string;
|
|
17
|
-
onCategoryChange?: (categoryId: string) => void;
|
|
18
|
-
isOpen?: boolean;
|
|
19
|
-
projectName?: string;
|
|
20
|
-
logo?: React.ReactNode;
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
interface SidebarContentProps {
|
|
24
|
-
categories: ComponentCategory[];
|
|
25
|
-
currentCategory?: string;
|
|
26
|
-
onCategoryChange?: (categoryId: string) => void;
|
|
27
|
-
projectName?: string;
|
|
28
|
-
logo?: React.ReactNode;
|
|
29
|
-
isMobile: boolean;
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
/**
|
|
33
|
-
* Sidebar Content Component
|
|
34
|
-
* Extracted content for reuse in desktop and mobile versions
|
|
35
|
-
*/
|
|
36
|
-
function SidebarContent({
|
|
37
|
-
categories,
|
|
38
|
-
currentCategory,
|
|
39
|
-
onCategoryChange,
|
|
40
|
-
projectName,
|
|
41
|
-
logo,
|
|
42
|
-
isMobile,
|
|
43
|
-
}: SidebarContentProps) {
|
|
44
|
-
return (
|
|
45
|
-
<div className={cn("flex flex-col overflow-hidden", isMobile ? "h-full" : "h-screen")}>
|
|
46
|
-
{/* Logo - Desktop only */}
|
|
47
|
-
{!isMobile && (
|
|
48
|
-
<div className="flex h-14 items-center border-b px-6 gap-2 flex-shrink-0">
|
|
49
|
-
{logo}
|
|
50
|
-
<span className="font-semibold text-sm">{projectName}</span>
|
|
51
|
-
</div>
|
|
52
|
-
)}
|
|
53
|
-
|
|
54
|
-
{/* Navigation */}
|
|
55
|
-
<div className="flex-1 overflow-y-auto scrollbar-thin">
|
|
56
|
-
<div className="p-4">
|
|
57
|
-
<nav>
|
|
58
|
-
<div className="mb-4">
|
|
59
|
-
<h3 className="mb-2 px-2 text-xs font-semibold text-muted-foreground uppercase tracking-wider">
|
|
60
|
-
Component Categories
|
|
61
|
-
</h3>
|
|
62
|
-
</div>
|
|
63
|
-
|
|
64
|
-
<div className="space-y-1">
|
|
65
|
-
{categories.map((category) => (
|
|
66
|
-
<button
|
|
67
|
-
key={category.id}
|
|
68
|
-
onClick={() => onCategoryChange?.(category.id)}
|
|
69
|
-
className={cn(
|
|
70
|
-
"w-full flex items-center gap-3 px-3 py-2 rounded-md text-sm font-medium transition-colors",
|
|
71
|
-
currentCategory === category.id
|
|
72
|
-
? "bg-primary text-primary-foreground"
|
|
73
|
-
: "text-muted-foreground hover:bg-muted hover:text-foreground"
|
|
74
|
-
)}
|
|
75
|
-
title={category.description}
|
|
76
|
-
>
|
|
77
|
-
<span className="flex-shrink-0">{category.icon}</span>
|
|
78
|
-
<span className="flex-1 text-left break-words">{category.label}</span>
|
|
79
|
-
{category.count && (
|
|
80
|
-
<span className={cn(
|
|
81
|
-
"text-xs px-2 py-0.5 rounded-full flex-shrink-0",
|
|
82
|
-
currentCategory === category.id
|
|
83
|
-
? "bg-primary-foreground/20 text-primary-foreground"
|
|
84
|
-
: "bg-muted text-muted-foreground"
|
|
85
|
-
)}>
|
|
86
|
-
{category.count}
|
|
87
|
-
</span>
|
|
88
|
-
)}
|
|
89
|
-
</button>
|
|
90
|
-
))}
|
|
91
|
-
</div>
|
|
92
|
-
</nav>
|
|
93
|
-
</div>
|
|
94
|
-
</div>
|
|
95
|
-
|
|
96
|
-
{/* Tailwind 4 Info Section */}
|
|
97
|
-
<div className="border-t p-4 bg-muted/30">
|
|
98
|
-
<div className="mb-3">
|
|
99
|
-
<h4 className="text-xs font-semibold text-foreground uppercase tracking-wider mb-2">
|
|
100
|
-
Tailwind CSS v4
|
|
101
|
-
</h4>
|
|
102
|
-
<p className="text-xs text-muted-foreground leading-relaxed mb-3">
|
|
103
|
-
This UI library uses Tailwind CSS v4 with CSS-first configuration
|
|
104
|
-
</p>
|
|
105
|
-
</div>
|
|
106
|
-
|
|
107
|
-
<div className="space-y-2 text-xs">
|
|
108
|
-
<div className="flex items-start gap-2">
|
|
109
|
-
<span className="text-primary mt-0.5">✓</span>
|
|
110
|
-
<span className="text-muted-foreground">CSS-first @theme configuration</span>
|
|
111
|
-
</div>
|
|
112
|
-
<div className="flex items-start gap-2">
|
|
113
|
-
<span className="text-primary mt-0.5">✓</span>
|
|
114
|
-
<span className="text-muted-foreground">10x faster build times</span>
|
|
115
|
-
</div>
|
|
116
|
-
<div className="flex items-start gap-2">
|
|
117
|
-
<span className="text-primary mt-0.5">✓</span>
|
|
118
|
-
<span className="text-muted-foreground">Modern CSS features (color-mix, @property)</span>
|
|
119
|
-
</div>
|
|
120
|
-
<div className="flex items-start gap-2">
|
|
121
|
-
<span className="text-primary mt-0.5">✓</span>
|
|
122
|
-
<span className="text-muted-foreground">Responsive: px-4 sm:px-6 lg:px-8</span>
|
|
123
|
-
</div>
|
|
124
|
-
</div>
|
|
125
|
-
</div>
|
|
126
|
-
</div>
|
|
127
|
-
);
|
|
128
|
-
}
|
|
129
|
-
|
|
130
|
-
export function Sidebar({
|
|
131
|
-
categories,
|
|
132
|
-
currentCategory,
|
|
133
|
-
onCategoryChange,
|
|
134
|
-
isOpen = false,
|
|
135
|
-
projectName = 'Django CFG',
|
|
136
|
-
logo,
|
|
137
|
-
}: SidebarProps) {
|
|
138
|
-
const isMobile = useIsMobile();
|
|
139
|
-
const [mounted, setMounted] = React.useState(false);
|
|
140
|
-
|
|
141
|
-
React.useEffect(() => {
|
|
142
|
-
setMounted(true);
|
|
143
|
-
}, []);
|
|
144
|
-
|
|
145
|
-
// Desktop sidebar - always visible, no portal
|
|
146
|
-
if (!isMobile) {
|
|
147
|
-
return (
|
|
148
|
-
<aside className="w-64 border-r bg-background flex-shrink-0">
|
|
149
|
-
<SidebarContent
|
|
150
|
-
categories={categories}
|
|
151
|
-
currentCategory={currentCategory}
|
|
152
|
-
onCategoryChange={onCategoryChange}
|
|
153
|
-
projectName={projectName}
|
|
154
|
-
logo={logo}
|
|
155
|
-
isMobile={false}
|
|
156
|
-
/>
|
|
157
|
-
</aside>
|
|
158
|
-
);
|
|
159
|
-
}
|
|
160
|
-
|
|
161
|
-
// Mobile sidebar - use portal when open
|
|
162
|
-
if (!isOpen || !mounted) {
|
|
163
|
-
return null;
|
|
164
|
-
}
|
|
165
|
-
|
|
166
|
-
if (typeof window === 'undefined') {
|
|
167
|
-
return null;
|
|
168
|
-
}
|
|
169
|
-
|
|
170
|
-
return createPortal(
|
|
171
|
-
<aside
|
|
172
|
-
className={cn(
|
|
173
|
-
"fixed inset-y-0 left-0 w-64 z-[200] bg-background border-r shadow-lg transition-transform duration-300",
|
|
174
|
-
isOpen ? "translate-x-0" : "-translate-x-full"
|
|
175
|
-
)}
|
|
176
|
-
>
|
|
177
|
-
<SidebarContent
|
|
178
|
-
categories={categories}
|
|
179
|
-
currentCategory={currentCategory}
|
|
180
|
-
onCategoryChange={onCategoryChange}
|
|
181
|
-
projectName={projectName}
|
|
182
|
-
logo={logo}
|
|
183
|
-
isMobile={true}
|
|
184
|
-
/>
|
|
185
|
-
</aside>,
|
|
186
|
-
document.body
|
|
187
|
-
);
|
|
188
|
-
}
|
|
File without changes
|