@djangocfg/layouts 1.2.18 → 1.2.19
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/components/layout/Header/Header.tsx +25 -32
- package/src/layouts/UILayout/config/components/navigation.config.tsx +29 -8
- package/src/layouts/UILayout/context/ShowcaseContext.tsx +1 -11
- package/src/layouts/UILayout/core/UIGuideView.tsx +2 -2
- package/src/layouts/UILayout/core/UILayout.tsx +44 -47
- package/src/layouts/UILayout/hooks/index.ts +1 -1
- package/src/layouts/UILayout/types/layout.ts +1 -3
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@djangocfg/layouts",
|
|
3
|
-
"version": "1.2.
|
|
3
|
+
"version": "1.2.19",
|
|
4
4
|
"description": "Layout system and components for Unrealon applications",
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "DjangoCFG",
|
|
@@ -53,9 +53,9 @@
|
|
|
53
53
|
"check": "tsc --noEmit"
|
|
54
54
|
},
|
|
55
55
|
"peerDependencies": {
|
|
56
|
-
"@djangocfg/api": "^1.2.
|
|
57
|
-
"@djangocfg/og-image": "^1.2.
|
|
58
|
-
"@djangocfg/ui": "^1.2.
|
|
56
|
+
"@djangocfg/api": "^1.2.19",
|
|
57
|
+
"@djangocfg/og-image": "^1.2.19",
|
|
58
|
+
"@djangocfg/ui": "^1.2.19",
|
|
59
59
|
"@hookform/resolvers": "^5.2.0",
|
|
60
60
|
"consola": "^3.4.2",
|
|
61
61
|
"lucide-react": "^0.468.0",
|
|
@@ -76,7 +76,7 @@
|
|
|
76
76
|
"vidstack": "0.6.15"
|
|
77
77
|
},
|
|
78
78
|
"devDependencies": {
|
|
79
|
-
"@djangocfg/typescript-config": "^1.2.
|
|
79
|
+
"@djangocfg/typescript-config": "^1.2.19",
|
|
80
80
|
"@types/node": "^24.7.2",
|
|
81
81
|
"@types/react": "19.2.2",
|
|
82
82
|
"@types/react-dom": "19.2.1",
|
|
@@ -16,36 +16,36 @@ export interface PackageInfo {
|
|
|
16
16
|
/**
|
|
17
17
|
* Package versions registry
|
|
18
18
|
* Auto-synced from package.json files
|
|
19
|
-
* Last updated: 2025-11-
|
|
19
|
+
* Last updated: 2025-11-02T05:58:03.758Z
|
|
20
20
|
*/
|
|
21
21
|
const PACKAGE_VERSIONS: PackageInfo[] = [
|
|
22
22
|
{
|
|
23
23
|
"name": "@djangocfg/ui",
|
|
24
|
-
"version": "1.2.
|
|
24
|
+
"version": "1.2.19"
|
|
25
25
|
},
|
|
26
26
|
{
|
|
27
27
|
"name": "@djangocfg/api",
|
|
28
|
-
"version": "1.2.
|
|
28
|
+
"version": "1.2.19"
|
|
29
29
|
},
|
|
30
30
|
{
|
|
31
31
|
"name": "@djangocfg/layouts",
|
|
32
|
-
"version": "1.2.
|
|
32
|
+
"version": "1.2.19"
|
|
33
33
|
},
|
|
34
34
|
{
|
|
35
35
|
"name": "@djangocfg/markdown",
|
|
36
|
-
"version": "1.2.
|
|
36
|
+
"version": "1.2.19"
|
|
37
37
|
},
|
|
38
38
|
{
|
|
39
39
|
"name": "@djangocfg/og-image",
|
|
40
|
-
"version": "1.2.
|
|
40
|
+
"version": "1.2.19"
|
|
41
41
|
},
|
|
42
42
|
{
|
|
43
43
|
"name": "@djangocfg/eslint-config",
|
|
44
|
-
"version": "1.2.
|
|
44
|
+
"version": "1.2.19"
|
|
45
45
|
},
|
|
46
46
|
{
|
|
47
47
|
"name": "@djangocfg/typescript-config",
|
|
48
|
-
"version": "1.2.
|
|
48
|
+
"version": "1.2.19"
|
|
49
49
|
}
|
|
50
50
|
];
|
|
51
51
|
|
|
@@ -1,60 +1,53 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Header Component
|
|
3
|
-
*
|
|
3
|
+
* Simple unified header for UI documentation
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
6
|
'use client';
|
|
7
7
|
|
|
8
8
|
import React from 'react';
|
|
9
|
-
import {
|
|
10
|
-
import { HeaderMobile } from './HeaderMobile';
|
|
11
|
-
import { HeaderDesktop } from './HeaderDesktop';
|
|
9
|
+
import { CopyAIButton } from './CopyAIButton';
|
|
12
10
|
|
|
13
11
|
export interface HeaderProps {
|
|
14
|
-
/** Page title
|
|
12
|
+
/** Page title */
|
|
15
13
|
title?: string;
|
|
16
|
-
/** Project name
|
|
14
|
+
/** Project name */
|
|
17
15
|
projectName?: string;
|
|
18
|
-
/** Logo component
|
|
16
|
+
/** Logo component */
|
|
19
17
|
logo?: React.ReactNode;
|
|
20
|
-
/** Is sidebar open (mobile only) */
|
|
21
|
-
isSidebarOpen?: boolean;
|
|
22
|
-
/** Toggle sidebar callback (mobile only) */
|
|
23
|
-
onToggleSidebar?: () => void;
|
|
24
18
|
/** Copy for AI callback - must return string */
|
|
25
19
|
onCopyForAI?: () => string;
|
|
26
20
|
}
|
|
27
21
|
|
|
28
22
|
/**
|
|
29
23
|
* Header Component
|
|
30
|
-
*
|
|
24
|
+
* Displays title and Copy for AI button
|
|
31
25
|
*/
|
|
32
26
|
export function Header({
|
|
33
27
|
title = 'UI Component Library',
|
|
34
28
|
projectName = 'Django CFG',
|
|
35
29
|
logo,
|
|
36
|
-
isSidebarOpen = false,
|
|
37
|
-
onToggleSidebar,
|
|
38
30
|
onCopyForAI,
|
|
39
31
|
}: HeaderProps) {
|
|
40
|
-
const isMobile = useIsMobile();
|
|
41
|
-
|
|
42
|
-
if (isMobile) {
|
|
43
|
-
return (
|
|
44
|
-
<HeaderMobile
|
|
45
|
-
projectName={projectName}
|
|
46
|
-
logo={logo}
|
|
47
|
-
isSidebarOpen={isSidebarOpen}
|
|
48
|
-
onToggleSidebar={onToggleSidebar}
|
|
49
|
-
onCopyForAI={onCopyForAI}
|
|
50
|
-
/>
|
|
51
|
-
);
|
|
52
|
-
}
|
|
53
|
-
|
|
54
32
|
return (
|
|
55
|
-
<
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
33
|
+
<header className="w-full border-b bg-background">
|
|
34
|
+
<div className="container mx-auto max-w-7xl px-4 sm:px-6 lg:px-8">
|
|
35
|
+
<div className="flex items-center justify-between h-16">
|
|
36
|
+
{/* Left: Logo and Title */}
|
|
37
|
+
<div className="flex items-center gap-3">
|
|
38
|
+
{logo && <div className="flex-shrink-0">{logo}</div>}
|
|
39
|
+
<div className="flex flex-col">
|
|
40
|
+
<h1 className="text-lg font-semibold tracking-tight">{title}</h1>
|
|
41
|
+
<p className="text-xs text-muted-foreground hidden sm:block">{projectName}</p>
|
|
42
|
+
</div>
|
|
43
|
+
</div>
|
|
44
|
+
|
|
45
|
+
{/* Right: Copy for AI Button */}
|
|
46
|
+
{onCopyForAI && (
|
|
47
|
+
<CopyAIButton onCopyForAI={onCopyForAI} />
|
|
48
|
+
)}
|
|
49
|
+
</div>
|
|
50
|
+
</div>
|
|
51
|
+
</header>
|
|
59
52
|
);
|
|
60
53
|
}
|
|
@@ -147,12 +147,13 @@ export const NAVIGATION_COMPONENTS: ComponentConfig[] = [
|
|
|
147
147
|
{
|
|
148
148
|
name: 'Tabs',
|
|
149
149
|
category: 'navigation',
|
|
150
|
-
description: 'Tab navigation for switching between different views',
|
|
150
|
+
description: 'Tab navigation for switching between different views. Supports mobile sheet mode, sticky positioning, and auto-responsive behavior.',
|
|
151
151
|
importPath: `import { Tabs, TabsContent, TabsList, TabsTrigger } from '@djangocfg/ui';`,
|
|
152
|
-
example:
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
<TabsTrigger value="
|
|
152
|
+
example: `// Basic tabs with equal-width tabs
|
|
153
|
+
<Tabs defaultValue="account" className="w-[400px]">
|
|
154
|
+
<TabsList fullWidth>
|
|
155
|
+
<TabsTrigger value="account" flexEqual>Account</TabsTrigger>
|
|
156
|
+
<TabsTrigger value="password" flexEqual>Password</TabsTrigger>
|
|
156
157
|
</TabsList>
|
|
157
158
|
<TabsContent value="account">
|
|
158
159
|
<div className="p-4 border rounded-md">
|
|
@@ -164,12 +165,32 @@ export const NAVIGATION_COMPONENTS: ComponentConfig[] = [
|
|
|
164
165
|
<p className="text-sm">Change your password here.</p>
|
|
165
166
|
</div>
|
|
166
167
|
</TabsContent>
|
|
168
|
+
</Tabs>
|
|
169
|
+
|
|
170
|
+
// Mobile-responsive tabs with sticky positioning
|
|
171
|
+
<Tabs
|
|
172
|
+
defaultValue="account"
|
|
173
|
+
mobileSheet
|
|
174
|
+
mobileTitleText="Settings"
|
|
175
|
+
mobileSheetTitle="Navigation"
|
|
176
|
+
sticky
|
|
177
|
+
>
|
|
178
|
+
<TabsList fullWidth>
|
|
179
|
+
<TabsTrigger value="account" flexEqual>Account</TabsTrigger>
|
|
180
|
+
<TabsTrigger value="password" flexEqual>Password</TabsTrigger>
|
|
181
|
+
</TabsList>
|
|
182
|
+
<TabsContent value="account">
|
|
183
|
+
Account content
|
|
184
|
+
</TabsContent>
|
|
185
|
+
<TabsContent value="password">
|
|
186
|
+
Password content
|
|
187
|
+
</TabsContent>
|
|
167
188
|
</Tabs>`,
|
|
168
189
|
preview: (
|
|
169
190
|
<Tabs defaultValue="account" className="w-[400px]">
|
|
170
|
-
<TabsList
|
|
171
|
-
<TabsTrigger value="account">Account</TabsTrigger>
|
|
172
|
-
<TabsTrigger value="password">Password</TabsTrigger>
|
|
191
|
+
<TabsList fullWidth>
|
|
192
|
+
<TabsTrigger value="account" flexEqual>Account</TabsTrigger>
|
|
193
|
+
<TabsTrigger value="password" flexEqual>Password</TabsTrigger>
|
|
173
194
|
</TabsList>
|
|
174
195
|
<TabsContent value="account">
|
|
175
196
|
<div className="p-4 border rounded-md">
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Showcase Context
|
|
3
|
-
* Manages navigation state for
|
|
3
|
+
* Manages navigation state for UILayout
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
6
|
'use client';
|
|
@@ -10,9 +10,6 @@ import React, { createContext, useContext, useState, ReactNode } from 'react';
|
|
|
10
10
|
interface ShowcaseContextValue {
|
|
11
11
|
currentCategory: string;
|
|
12
12
|
setCurrentCategory: (category: string) => void;
|
|
13
|
-
isSidebarOpen: boolean;
|
|
14
|
-
toggleSidebar: () => void;
|
|
15
|
-
closeSidebar: () => void;
|
|
16
13
|
}
|
|
17
14
|
|
|
18
15
|
const ShowcaseContext = createContext<ShowcaseContextValue | undefined>(undefined);
|
|
@@ -24,19 +21,12 @@ interface ShowcaseProviderProps {
|
|
|
24
21
|
|
|
25
22
|
export function ShowcaseProvider({ children, defaultCategory = 'overview' }: ShowcaseProviderProps) {
|
|
26
23
|
const [currentCategory, setCurrentCategory] = useState(defaultCategory);
|
|
27
|
-
const [isSidebarOpen, setIsSidebarOpen] = useState(false);
|
|
28
|
-
|
|
29
|
-
const toggleSidebar = () => setIsSidebarOpen(prev => !prev);
|
|
30
|
-
const closeSidebar = () => setIsSidebarOpen(false);
|
|
31
24
|
|
|
32
25
|
return (
|
|
33
26
|
<ShowcaseContext.Provider
|
|
34
27
|
value={{
|
|
35
28
|
currentCategory,
|
|
36
29
|
setCurrentCategory,
|
|
37
|
-
isSidebarOpen,
|
|
38
|
-
toggleSidebar,
|
|
39
|
-
closeSidebar,
|
|
40
30
|
}}
|
|
41
31
|
>
|
|
42
32
|
{children}
|
|
@@ -17,7 +17,7 @@ import { TailwindGuideRenderer } from '../components/TailwindGuideRenderer';
|
|
|
17
17
|
function UIGuideContent() {
|
|
18
18
|
const { currentCategory, setCurrentCategory } = useShowcase();
|
|
19
19
|
|
|
20
|
-
// For overview, show
|
|
20
|
+
// For overview, show landing page without layout
|
|
21
21
|
if (currentCategory === 'overview') {
|
|
22
22
|
return <UIGuideLanding />;
|
|
23
23
|
}
|
|
@@ -44,7 +44,7 @@ function UIGuideContent() {
|
|
|
44
44
|
{currentCategory === 'tailwind4' && <TailwindGuideRenderer />}
|
|
45
45
|
|
|
46
46
|
{/* All other categories use CategoryRenderer */}
|
|
47
|
-
{currentCategory !== 'tailwind4' &&
|
|
47
|
+
{currentCategory !== 'tailwind4' && (
|
|
48
48
|
<CategoryRenderer categoryId={currentCategory} />
|
|
49
49
|
)}
|
|
50
50
|
</div>
|
|
@@ -6,11 +6,9 @@
|
|
|
6
6
|
'use client';
|
|
7
7
|
|
|
8
8
|
import React from 'react';
|
|
9
|
-
import {
|
|
9
|
+
import { Tabs, TabsList, TabsTrigger } from '@djangocfg/ui';
|
|
10
10
|
import { Header } from '../components/layout/Header';
|
|
11
|
-
import { MobileOverlay } from '../components/layout/MobileOverlay';
|
|
12
11
|
import { generateAIContext } from '../config';
|
|
13
|
-
import { useShowcase } from '../context';
|
|
14
12
|
import type { UILayoutProps } from '../types';
|
|
15
13
|
|
|
16
14
|
|
|
@@ -20,7 +18,7 @@ import type { UILayoutProps } from '../types';
|
|
|
20
18
|
* Features:
|
|
21
19
|
* - Config-driven: All component data comes from centralized config
|
|
22
20
|
* - "Copy for AI": One-click export of all documentation
|
|
23
|
-
* - Responsive:
|
|
21
|
+
* - Responsive: Auto-converts to mobile sheet menu on mobile
|
|
24
22
|
* - Type-safe: Full TypeScript support
|
|
25
23
|
*
|
|
26
24
|
* @example
|
|
@@ -45,59 +43,58 @@ export function UILayout({
|
|
|
45
43
|
logo,
|
|
46
44
|
projectName = "Django CFG UI",
|
|
47
45
|
}: UILayoutProps) {
|
|
48
|
-
const { isSidebarOpen, toggleSidebar, closeSidebar } = useShowcase();
|
|
49
|
-
|
|
50
|
-
const handleCategoryChange = (categoryId: string) => {
|
|
51
|
-
onCategoryChange?.(categoryId);
|
|
52
|
-
closeSidebar();
|
|
53
|
-
};
|
|
54
|
-
|
|
55
46
|
const handleCopyForAI = () => {
|
|
56
47
|
return generateAIContext();
|
|
57
48
|
};
|
|
58
49
|
|
|
59
50
|
return (
|
|
60
|
-
<div className="flex bg-background">
|
|
61
|
-
{/*
|
|
62
|
-
<
|
|
63
|
-
|
|
64
|
-
|
|
51
|
+
<div className="flex flex-col min-h-screen bg-background">
|
|
52
|
+
{/* Header with Copy for AI button */}
|
|
53
|
+
<Header
|
|
54
|
+
title={title}
|
|
55
|
+
projectName={projectName}
|
|
56
|
+
logo={logo}
|
|
57
|
+
onCopyForAI={handleCopyForAI}
|
|
65
58
|
/>
|
|
66
59
|
|
|
67
|
-
{/*
|
|
68
|
-
<div className="
|
|
69
|
-
<
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
60
|
+
{/* Category Navigation Tabs */}
|
|
61
|
+
<div className="container mx-auto max-w-7xl px-4 sm:px-6 lg:px-8 py-3">
|
|
62
|
+
<Tabs
|
|
63
|
+
value={currentCategory}
|
|
64
|
+
onValueChange={onCategoryChange}
|
|
65
|
+
mobileSheet
|
|
66
|
+
mobileTitleText="UI Library"
|
|
67
|
+
mobileSheetTitle="Categories"
|
|
68
|
+
sticky
|
|
69
|
+
>
|
|
70
|
+
<TabsList fullWidth className="h-auto flex-wrap">
|
|
71
|
+
{categories.map((category) => (
|
|
72
|
+
<TabsTrigger
|
|
73
|
+
key={category.id}
|
|
74
|
+
value={category.id}
|
|
75
|
+
flexEqual
|
|
76
|
+
className="gap-2 whitespace-nowrap"
|
|
77
|
+
>
|
|
78
|
+
{category.icon}
|
|
79
|
+
<span>{category.label}</span>
|
|
80
|
+
{category.count !== undefined && (
|
|
81
|
+
<span className="ml-1 text-xs opacity-60">({category.count})</span>
|
|
82
|
+
)}
|
|
83
|
+
</TabsTrigger>
|
|
84
|
+
))}
|
|
85
|
+
</TabsList>
|
|
86
|
+
</Tabs>
|
|
77
87
|
</div>
|
|
78
88
|
|
|
79
89
|
{/* Main Content */}
|
|
80
|
-
<main className="flex-1
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
onCopyForAI={handleCopyForAI}
|
|
89
|
-
/>
|
|
90
|
-
|
|
91
|
-
{/* Content Area */}
|
|
92
|
-
<div className="flex-1">
|
|
93
|
-
<div className="container max-w-7xl mx-auto p-6">
|
|
94
|
-
{description && (
|
|
95
|
-
<p className="text-sm text-muted-foreground mb-6">
|
|
96
|
-
{description}
|
|
97
|
-
</p>
|
|
98
|
-
)}
|
|
99
|
-
{children}
|
|
100
|
-
</div>
|
|
90
|
+
<main className="flex-1">
|
|
91
|
+
<div className="container max-w-7xl mx-auto p-6">
|
|
92
|
+
{description && (
|
|
93
|
+
<p className="text-sm text-muted-foreground mb-6">
|
|
94
|
+
{description}
|
|
95
|
+
</p>
|
|
96
|
+
)}
|
|
97
|
+
{children}
|
|
101
98
|
</div>
|
|
102
99
|
</main>
|
|
103
100
|
</div>
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
* Custom hooks for UILayout functionality
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
|
-
export { useSidebarState } from './useSidebarState';
|
|
7
6
|
export { useAIExport } from './useAIExport';
|
|
8
7
|
export { useCategoryNavigation } from './useCategoryNavigation';
|
|
9
8
|
export { useComponentSearch } from './useComponentSearch';
|
|
9
|
+
export { useSidebarState } from './useSidebarState';
|
|
@@ -33,13 +33,11 @@ export interface UILayoutProps {
|
|
|
33
33
|
* Defines layout dimensions and behavior
|
|
34
34
|
*/
|
|
35
35
|
export interface LayoutConfig {
|
|
36
|
-
/** Sidebar width in pixels */
|
|
37
|
-
sidebarWidth?: number;
|
|
38
36
|
/** Header height in pixels */
|
|
39
37
|
headerHeight?: number;
|
|
40
38
|
/** Container max width */
|
|
41
39
|
containerMaxWidth?: string;
|
|
42
|
-
/** Enable sticky
|
|
40
|
+
/** Enable sticky header */
|
|
43
41
|
stickyHeader?: boolean;
|
|
44
42
|
}
|
|
45
43
|
|