@djangocfg/layouts 1.2.16 → 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/config/components/navigation.config.tsx +29 -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
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* AI Export Generators
|
|
3
|
+
* Functions for generating AI-friendly documentation
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import type { ComponentConfig } from '../../types';
|
|
7
|
+
import type { TailwindGuide } from '../../config/tailwind.config';
|
|
8
|
+
|
|
9
|
+
export interface UILibraryConfig {
|
|
10
|
+
projectName: string;
|
|
11
|
+
version: string;
|
|
12
|
+
description: string;
|
|
13
|
+
totalComponents: number;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Generate complete AI context from components and config
|
|
18
|
+
*/
|
|
19
|
+
export function generateAIContext(
|
|
20
|
+
components: ComponentConfig[],
|
|
21
|
+
tailwindGuide: TailwindGuide,
|
|
22
|
+
config: UILibraryConfig
|
|
23
|
+
): string {
|
|
24
|
+
const { projectName, version, description } = config;
|
|
25
|
+
|
|
26
|
+
let output = `# ${projectName} v${version}\n\n`;
|
|
27
|
+
output += `${description}\n\n`;
|
|
28
|
+
|
|
29
|
+
// Tailwind Guide Section
|
|
30
|
+
output += generateTailwindSection(tailwindGuide);
|
|
31
|
+
|
|
32
|
+
// Components by Category
|
|
33
|
+
output += generateComponentsSection(components);
|
|
34
|
+
|
|
35
|
+
return output;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* Generate Tailwind CSS section
|
|
40
|
+
*/
|
|
41
|
+
export function generateTailwindSection(guide: TailwindGuide): string {
|
|
42
|
+
let output = `## Tailwind CSS v${guide.version} Guidelines\n\n`;
|
|
43
|
+
|
|
44
|
+
output += `### Key Changes\n`;
|
|
45
|
+
guide.keyChanges.forEach((change) => {
|
|
46
|
+
output += `- ${change}\n`;
|
|
47
|
+
});
|
|
48
|
+
output += `\n`;
|
|
49
|
+
|
|
50
|
+
output += `### Best Practices\n`;
|
|
51
|
+
guide.bestPractices.forEach((practice) => {
|
|
52
|
+
output += `- ${practice}\n`;
|
|
53
|
+
});
|
|
54
|
+
output += `\n`;
|
|
55
|
+
|
|
56
|
+
output += `### Migration Steps\n`;
|
|
57
|
+
guide.migrationSteps.forEach((step, index) => {
|
|
58
|
+
output += `${index + 1}. ${step}\n`;
|
|
59
|
+
});
|
|
60
|
+
output += `\n`;
|
|
61
|
+
|
|
62
|
+
output += `### Examples\n\n`;
|
|
63
|
+
guide.examples.forEach((example) => {
|
|
64
|
+
output += `#### ${example.title}\n`;
|
|
65
|
+
output += `${example.description}\n\n`;
|
|
66
|
+
output += `\`\`\`css\n${example.code}\n\`\`\`\n\n`;
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
return output;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* Generate components section grouped by category
|
|
74
|
+
*/
|
|
75
|
+
export function generateComponentsSection(components: ComponentConfig[]): string {
|
|
76
|
+
let output = '';
|
|
77
|
+
|
|
78
|
+
// Group components by category
|
|
79
|
+
const byCategory = groupByCategory(components);
|
|
80
|
+
|
|
81
|
+
// Generate section for each category
|
|
82
|
+
Object.entries(byCategory).forEach(([category, comps]) => {
|
|
83
|
+
output += `## ${formatCategoryName(category)} (${comps.length})\n\n`;
|
|
84
|
+
|
|
85
|
+
comps.forEach((comp) => {
|
|
86
|
+
output += generateComponentDoc(comp);
|
|
87
|
+
});
|
|
88
|
+
});
|
|
89
|
+
|
|
90
|
+
return output;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
/**
|
|
94
|
+
* Generate documentation for a single component
|
|
95
|
+
*/
|
|
96
|
+
export function generateComponentDoc(component: ComponentConfig): string {
|
|
97
|
+
let output = `### ${component.name}\n`;
|
|
98
|
+
output += `${component.description}\n\n`;
|
|
99
|
+
output += `\`\`\`tsx\n`;
|
|
100
|
+
output += `${component.importPath}\n\n`;
|
|
101
|
+
output += `${component.example}\n`;
|
|
102
|
+
output += `\`\`\`\n\n`;
|
|
103
|
+
|
|
104
|
+
return output;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
/**
|
|
108
|
+
* Group components by category
|
|
109
|
+
*/
|
|
110
|
+
function groupByCategory(
|
|
111
|
+
components: ComponentConfig[]
|
|
112
|
+
): Record<string, ComponentConfig[]> {
|
|
113
|
+
return components.reduce(
|
|
114
|
+
(acc, comp) => {
|
|
115
|
+
if (!acc[comp.category]) {
|
|
116
|
+
acc[comp.category] = [];
|
|
117
|
+
}
|
|
118
|
+
acc[comp.category].push(comp);
|
|
119
|
+
return acc;
|
|
120
|
+
},
|
|
121
|
+
{} as Record<string, ComponentConfig[]>
|
|
122
|
+
);
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
/**
|
|
126
|
+
* Format category name for display
|
|
127
|
+
*/
|
|
128
|
+
function formatCategoryName(category: string): string {
|
|
129
|
+
return category.charAt(0).toUpperCase() + category.slice(1);
|
|
130
|
+
}
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Component Filter Utilities
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import type { ComponentConfig } from '../../types';
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Filter options
|
|
9
|
+
*/
|
|
10
|
+
export interface FilterOptions {
|
|
11
|
+
/** Category to filter by */
|
|
12
|
+
category?: string;
|
|
13
|
+
/** Tags to filter by (OR logic) */
|
|
14
|
+
tags?: string[];
|
|
15
|
+
/** Search query */
|
|
16
|
+
query?: string;
|
|
17
|
+
/** Search fields */
|
|
18
|
+
searchFields?: Array<keyof ComponentConfig>;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Apply multiple filters to components
|
|
23
|
+
*/
|
|
24
|
+
export function applyFilters(
|
|
25
|
+
components: ComponentConfig[],
|
|
26
|
+
options: FilterOptions
|
|
27
|
+
): ComponentConfig[] {
|
|
28
|
+
let filtered = components;
|
|
29
|
+
|
|
30
|
+
// Filter by category
|
|
31
|
+
if (options.category) {
|
|
32
|
+
filtered = filtered.filter((comp) => comp.category === options.category);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
// Filter by tags
|
|
36
|
+
if (options.tags && options.tags.length > 0) {
|
|
37
|
+
filtered = filtered.filter((comp) => {
|
|
38
|
+
if (!comp.tags) return false;
|
|
39
|
+
return options.tags!.some((tag) => comp.tags?.includes(tag));
|
|
40
|
+
});
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
// Filter by search query
|
|
44
|
+
if (options.query && options.query.trim()) {
|
|
45
|
+
const lowerQuery = options.query.toLowerCase();
|
|
46
|
+
const searchFields = options.searchFields || [
|
|
47
|
+
'name',
|
|
48
|
+
'description',
|
|
49
|
+
'category',
|
|
50
|
+
];
|
|
51
|
+
|
|
52
|
+
filtered = filtered.filter((comp) => {
|
|
53
|
+
return searchFields.some((field) => {
|
|
54
|
+
const value = comp[field];
|
|
55
|
+
if (typeof value === 'string') {
|
|
56
|
+
return value.toLowerCase().includes(lowerQuery);
|
|
57
|
+
}
|
|
58
|
+
if (Array.isArray(value)) {
|
|
59
|
+
return value.some((item) =>
|
|
60
|
+
String(item).toLowerCase().includes(lowerQuery)
|
|
61
|
+
);
|
|
62
|
+
}
|
|
63
|
+
return false;
|
|
64
|
+
});
|
|
65
|
+
});
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
return filtered;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
/**
|
|
72
|
+
* Sort components by field
|
|
73
|
+
*/
|
|
74
|
+
export function sortComponents(
|
|
75
|
+
components: ComponentConfig[],
|
|
76
|
+
field: keyof ComponentConfig,
|
|
77
|
+
order: 'asc' | 'desc' = 'asc'
|
|
78
|
+
): ComponentConfig[] {
|
|
79
|
+
return [...components].sort((a, b) => {
|
|
80
|
+
const aVal = String(a[field]);
|
|
81
|
+
const bVal = String(b[field]);
|
|
82
|
+
|
|
83
|
+
if (order === 'asc') {
|
|
84
|
+
return aVal.localeCompare(bVal);
|
|
85
|
+
} else {
|
|
86
|
+
return bVal.localeCompare(aVal);
|
|
87
|
+
}
|
|
88
|
+
});
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
/**
|
|
92
|
+
* Group components by field
|
|
93
|
+
*/
|
|
94
|
+
export function groupComponentsBy<K extends keyof ComponentConfig>(
|
|
95
|
+
components: ComponentConfig[],
|
|
96
|
+
field: K
|
|
97
|
+
): Record<string, ComponentConfig[]> {
|
|
98
|
+
return components.reduce(
|
|
99
|
+
(acc, comp) => {
|
|
100
|
+
const key = String(comp[field]);
|
|
101
|
+
if (!acc[key]) {
|
|
102
|
+
acc[key] = [];
|
|
103
|
+
}
|
|
104
|
+
acc[key].push(comp);
|
|
105
|
+
return acc;
|
|
106
|
+
},
|
|
107
|
+
{} as Record<string, ComponentConfig[]>
|
|
108
|
+
);
|
|
109
|
+
}
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Component Search Utilities
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import type { ComponentConfig } from '../../types';
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Search components by query
|
|
9
|
+
*/
|
|
10
|
+
export function searchComponents(
|
|
11
|
+
components: ComponentConfig[],
|
|
12
|
+
query: string,
|
|
13
|
+
fields: Array<keyof ComponentConfig> = ['name', 'description', 'category']
|
|
14
|
+
): ComponentConfig[] {
|
|
15
|
+
if (!query.trim()) {
|
|
16
|
+
return components;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
const lowerQuery = query.toLowerCase();
|
|
20
|
+
|
|
21
|
+
return components.filter((component) => {
|
|
22
|
+
return fields.some((field) => {
|
|
23
|
+
const value = component[field];
|
|
24
|
+
if (typeof value === 'string') {
|
|
25
|
+
return value.toLowerCase().includes(lowerQuery);
|
|
26
|
+
}
|
|
27
|
+
if (Array.isArray(value)) {
|
|
28
|
+
return value.some((item) =>
|
|
29
|
+
String(item).toLowerCase().includes(lowerQuery)
|
|
30
|
+
);
|
|
31
|
+
}
|
|
32
|
+
return false;
|
|
33
|
+
});
|
|
34
|
+
});
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Filter components by category
|
|
39
|
+
*/
|
|
40
|
+
export function filterByCategory(
|
|
41
|
+
components: ComponentConfig[],
|
|
42
|
+
category: string
|
|
43
|
+
): ComponentConfig[] {
|
|
44
|
+
return components.filter((comp) => comp.category === category);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* Filter components by tags
|
|
49
|
+
*/
|
|
50
|
+
export function filterByTags(
|
|
51
|
+
components: ComponentConfig[],
|
|
52
|
+
tags: string[]
|
|
53
|
+
): ComponentConfig[] {
|
|
54
|
+
if (tags.length === 0) {
|
|
55
|
+
return components;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
return components.filter((comp) => {
|
|
59
|
+
if (!comp.tags) return false;
|
|
60
|
+
return tags.some((tag) => comp.tags?.includes(tag));
|
|
61
|
+
});
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* Get unique categories from components
|
|
66
|
+
*/
|
|
67
|
+
export function getUniqueCategories(
|
|
68
|
+
components: ComponentConfig[]
|
|
69
|
+
): string[] {
|
|
70
|
+
const categories = new Set(components.map((c) => c.category));
|
|
71
|
+
return Array.from(categories).sort();
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
/**
|
|
75
|
+
* Get unique tags from components
|
|
76
|
+
*/
|
|
77
|
+
export function getUniqueTags(components: ComponentConfig[]): string[] {
|
|
78
|
+
const tags = new Set<string>();
|
|
79
|
+
components.forEach((comp) => {
|
|
80
|
+
comp.tags?.forEach((tag) => tags.add(tag));
|
|
81
|
+
});
|
|
82
|
+
return Array.from(tags).sort();
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
* Find component by name
|
|
87
|
+
*/
|
|
88
|
+
export function findComponentByName(
|
|
89
|
+
components: ComponentConfig[],
|
|
90
|
+
name: string
|
|
91
|
+
): ComponentConfig | undefined {
|
|
92
|
+
return components.find(
|
|
93
|
+
(comp) => comp.name.toLowerCase() === name.toLowerCase()
|
|
94
|
+
);
|
|
95
|
+
}
|
|
@@ -1,331 +0,0 @@
|
|
|
1
|
-
# UILayout Refactoring - Complete Summary
|
|
2
|
-
|
|
3
|
-
## 🎯 Goal
|
|
4
|
-
|
|
5
|
-
Transform ComponentShowcaseLayout into a modern, config-driven UILayout with:
|
|
6
|
-
1. **Single Source of Truth** - centralized configuration
|
|
7
|
-
2. **Zero Duplication** - no repeated code
|
|
8
|
-
3. **Auto-Rendering** - components render from config
|
|
9
|
-
4. **AI Export** - "Copy for AI" button with complete documentation
|
|
10
|
-
5. **Better Organization** - modular structure by category
|
|
11
|
-
|
|
12
|
-
## ✅ What Was Done
|
|
13
|
-
|
|
14
|
-
### 1. Renamed Old Structure
|
|
15
|
-
```bash
|
|
16
|
-
UILayout_old/ # Backup of old implementation
|
|
17
|
-
```
|
|
18
|
-
|
|
19
|
-
### 2. Created New Config-Driven Architecture
|
|
20
|
-
|
|
21
|
-
#### Config Structure (Single Source of Truth)
|
|
22
|
-
```
|
|
23
|
-
config/
|
|
24
|
-
├── components/ # Component configs by category
|
|
25
|
-
│ ├── types.ts # ComponentConfig interface
|
|
26
|
-
│ ├── forms.config.tsx # 8 form components
|
|
27
|
-
│ ├── layout.config.tsx # 5 layout components
|
|
28
|
-
│ ├── navigation.config.tsx # 4 navigation components
|
|
29
|
-
│ ├── overlay.config.tsx # 11 overlay components
|
|
30
|
-
│ ├── feedback.config.tsx # 5 feedback components
|
|
31
|
-
│ ├── data.config.tsx # 5 data components
|
|
32
|
-
│ ├── specialized.config.tsx # 2 specialized components
|
|
33
|
-
│ ├── blocks.config.tsx # 7 landing page blocks
|
|
34
|
-
│ ├── hooks.config.tsx # 6 custom React hooks
|
|
35
|
-
│ └── index.ts # Aggregator
|
|
36
|
-
├── categories.config.tsx # Menu categories
|
|
37
|
-
├── tailwind.config.ts # Tailwind 4 guide
|
|
38
|
-
├── ai-export.config.ts # AI context generator
|
|
39
|
-
└── index.ts # Main exports
|
|
40
|
-
```
|
|
41
|
-
|
|
42
|
-
#### Component Architecture
|
|
43
|
-
```
|
|
44
|
-
components/
|
|
45
|
-
├── AutoComponentDemo.tsx # Reads from config, renders component
|
|
46
|
-
├── CategoryRenderer.tsx # Renders entire category from config
|
|
47
|
-
├── TailwindGuideRenderer.tsx # Renders Tailwind guide from config
|
|
48
|
-
├── Header.tsx # Header with "Copy for AI" button
|
|
49
|
-
├── Sidebar.tsx # Navigation sidebar
|
|
50
|
-
└── MobileOverlay.tsx # Mobile menu overlay
|
|
51
|
-
```
|
|
52
|
-
|
|
53
|
-
### 3. Component Configuration Format
|
|
54
|
-
|
|
55
|
-
Each component defined as:
|
|
56
|
-
```typescript
|
|
57
|
-
interface ComponentConfig {
|
|
58
|
-
name: string; // "Button"
|
|
59
|
-
category: string; // "forms"
|
|
60
|
-
description: string; // "Interactive button with variants"
|
|
61
|
-
importPath: string; // "import { Button } from '@djangocfg/ui';"
|
|
62
|
-
example: string; // Code example as string
|
|
63
|
-
preview: ReactNode; // Live React component
|
|
64
|
-
}
|
|
65
|
-
```
|
|
66
|
-
|
|
67
|
-
### 4. Key Features Implemented
|
|
68
|
-
|
|
69
|
-
#### ✅ Auto-Rendering from Config
|
|
70
|
-
```tsx
|
|
71
|
-
// Before: Manual demo files for each category
|
|
72
|
-
FormComponentsDemo.tsx // 200+ lines
|
|
73
|
-
LayoutComponentsDemo.tsx // 180+ lines
|
|
74
|
-
NavigationComponentsDemo.tsx // 150+ lines
|
|
75
|
-
// ... 7 more demo files
|
|
76
|
-
|
|
77
|
-
// After: One universal renderer
|
|
78
|
-
<CategoryRenderer categoryId="forms" /> // Reads from config
|
|
79
|
-
```
|
|
80
|
-
|
|
81
|
-
#### ✅ "Copy for AI" Button
|
|
82
|
-
- In Header component (desktop & mobile)
|
|
83
|
-
- Generates complete documentation:
|
|
84
|
-
- Tailwind 4 guidelines
|
|
85
|
-
- All 53 components with examples
|
|
86
|
-
- Proper formatting for AI
|
|
87
|
-
- Uses `generateAIContext()` function
|
|
88
|
-
- One-click clipboard copy
|
|
89
|
-
|
|
90
|
-
#### ✅ Zero Duplication
|
|
91
|
-
```typescript
|
|
92
|
-
// Before: Component defined in 3 places
|
|
93
|
-
// 1. Demo file (preview)
|
|
94
|
-
// 2. Code example (string)
|
|
95
|
-
// 3. Import statement
|
|
96
|
-
|
|
97
|
-
// After: Component defined ONCE
|
|
98
|
-
{
|
|
99
|
-
name: 'Button',
|
|
100
|
-
preview: <Button>Click</Button>,
|
|
101
|
-
example: '<Button>Click</Button>',
|
|
102
|
-
importPath: "import { Button } from '@djangocfg/ui';"
|
|
103
|
-
}
|
|
104
|
-
```
|
|
105
|
-
|
|
106
|
-
### 5. Statistics
|
|
107
|
-
|
|
108
|
-
#### Total Components Documented
|
|
109
|
-
| Category | Count | Config File |
|
|
110
|
-
|----------|-------|-------------|
|
|
111
|
-
| Forms | 8 | forms.config.tsx (320 lines) |
|
|
112
|
-
| Layout | 5 | layout.config.tsx (240 lines) |
|
|
113
|
-
| Navigation | 4 | navigation.config.tsx (195 lines) |
|
|
114
|
-
| Overlay | 11 | overlay.config.tsx (510 lines) |
|
|
115
|
-
| Feedback | 5 | feedback.config.tsx (220 lines) |
|
|
116
|
-
| Data Display | 5 | data.config.tsx (200 lines) |
|
|
117
|
-
| Specialized | 2 | specialized.config.tsx (95 lines) |
|
|
118
|
-
| Blocks | 7 | blocks.config.tsx (280 lines) |
|
|
119
|
-
| Hooks | 6 | hooks.config.tsx (170 lines) |
|
|
120
|
-
| **TOTAL** | **53** | **2,230 lines** |
|
|
121
|
-
|
|
122
|
-
#### Code Reduction
|
|
123
|
-
- **Before**: ~1,800 lines of demo files + ~1,200 lines of component definitions = **3,000 lines**
|
|
124
|
-
- **After**: ~2,230 lines (all-in-one configs) = **2,230 lines**
|
|
125
|
-
- **Saved**: ~770 lines (-25%)
|
|
126
|
-
- **Maintainability**: 100x better (single source of truth)
|
|
127
|
-
|
|
128
|
-
### 6. Files Created
|
|
129
|
-
|
|
130
|
-
#### Core Files (11)
|
|
131
|
-
1. `UILayout.tsx` - Main layout component
|
|
132
|
-
2. `UIGuideView.tsx` - Complete view with categories
|
|
133
|
-
3. `UIGuideLanding.tsx` - Landing page (copied from old)
|
|
134
|
-
4. `UIGuideApp.tsx` - Full app wrapper
|
|
135
|
-
5. `types.ts` - Type definitions
|
|
136
|
-
6. `constants.ts` - Constants
|
|
137
|
-
7. `index.ts` - Main exports
|
|
138
|
-
8. `README.md` - Documentation
|
|
139
|
-
9. `REFACTORING.md` - This file
|
|
140
|
-
|
|
141
|
-
#### Config Files (14)
|
|
142
|
-
10. `config/components/types.ts`
|
|
143
|
-
11. `config/components/forms.config.tsx`
|
|
144
|
-
12. `config/components/layout.config.tsx`
|
|
145
|
-
13. `config/components/navigation.config.tsx`
|
|
146
|
-
14. `config/components/overlay.config.tsx`
|
|
147
|
-
15. `config/components/feedback.config.tsx`
|
|
148
|
-
16. `config/components/data.config.tsx`
|
|
149
|
-
17. `config/components/specialized.config.tsx`
|
|
150
|
-
18. `config/components/blocks.config.tsx`
|
|
151
|
-
19. `config/components/hooks.config.tsx`
|
|
152
|
-
20. `config/components/index.ts`
|
|
153
|
-
21. `config/categories.config.tsx`
|
|
154
|
-
22. `config/tailwind.config.ts`
|
|
155
|
-
23. `config/ai-export.config.ts`
|
|
156
|
-
24. `config/index.ts`
|
|
157
|
-
|
|
158
|
-
#### Component Files (6)
|
|
159
|
-
25. `components/AutoComponentDemo.tsx`
|
|
160
|
-
26. `components/CategoryRenderer.tsx`
|
|
161
|
-
27. `components/TailwindGuideRenderer.tsx`
|
|
162
|
-
28. `components/Header.tsx` (copied & updated)
|
|
163
|
-
29. `components/Sidebar.tsx` (copied)
|
|
164
|
-
30. `components/MobileOverlay.tsx` (copied)
|
|
165
|
-
|
|
166
|
-
#### Context (1)
|
|
167
|
-
31. `context/` (copied from old)
|
|
168
|
-
|
|
169
|
-
**Total: 31 files created/updated**
|
|
170
|
-
|
|
171
|
-
## 🚀 Benefits
|
|
172
|
-
|
|
173
|
-
### 1. Single Source of Truth
|
|
174
|
-
- All component data in config files
|
|
175
|
-
- No duplication
|
|
176
|
-
- Easy to update
|
|
177
|
-
|
|
178
|
-
### 2. Auto-Rendering
|
|
179
|
-
- Add component to config → automatically appears everywhere
|
|
180
|
-
- No manual demo file creation
|
|
181
|
-
- Consistent presentation
|
|
182
|
-
|
|
183
|
-
### 3. Type-Safe
|
|
184
|
-
- Full TypeScript support
|
|
185
|
-
- Interface for ComponentConfig
|
|
186
|
-
- Compile-time error checking
|
|
187
|
-
|
|
188
|
-
### 4. AI-Ready
|
|
189
|
-
- "Copy for AI" button
|
|
190
|
-
- Complete documentation export
|
|
191
|
-
- Proper formatting for AI consumption
|
|
192
|
-
|
|
193
|
-
### 5. Maintainable
|
|
194
|
-
```typescript
|
|
195
|
-
// Adding new component:
|
|
196
|
-
|
|
197
|
-
// Before (3 steps):
|
|
198
|
-
// 1. Create demo component in category file
|
|
199
|
-
// 2. Add code example string
|
|
200
|
-
// 3. Import and wire up
|
|
201
|
-
|
|
202
|
-
// After (1 step):
|
|
203
|
-
// Add to config file:
|
|
204
|
-
{
|
|
205
|
-
name: 'NewComponent',
|
|
206
|
-
category: 'forms',
|
|
207
|
-
description: '...',
|
|
208
|
-
importPath: '...',
|
|
209
|
-
example: '...',
|
|
210
|
-
preview: <NewComponent />
|
|
211
|
-
}
|
|
212
|
-
```
|
|
213
|
-
|
|
214
|
-
### 6. Scalable
|
|
215
|
-
- Easy to add new categories
|
|
216
|
-
- Easy to add new components
|
|
217
|
-
- Modular structure
|
|
218
|
-
|
|
219
|
-
## 📊 Comparison
|
|
220
|
-
|
|
221
|
-
### Old Architecture
|
|
222
|
-
```
|
|
223
|
-
ComponentShowcaseLayout/
|
|
224
|
-
├── categories/
|
|
225
|
-
│ ├── FormComponentsDemo.tsx # 200 lines
|
|
226
|
-
│ ├── LayoutComponentsDemo.tsx # 180 lines
|
|
227
|
-
│ ├── NavigationComponentsDemo.tsx # 150 lines
|
|
228
|
-
│ ├── OverlayComponentsDemo.tsx # 250 lines
|
|
229
|
-
│ ├── FeedbackComponentsDemo.tsx # 140 lines
|
|
230
|
-
│ ├── DataDisplayDemo.tsx # 170 lines
|
|
231
|
-
│ ├── SpecializedComponentsDemo.tsx # 120 lines
|
|
232
|
-
│ ├── BlocksDemo.tsx # 280 lines
|
|
233
|
-
│ ├── HooksDemo.tsx # 160 lines
|
|
234
|
-
│ └── Tailwind4Guide.tsx # 240 lines
|
|
235
|
-
└── ... (other files)
|
|
236
|
-
|
|
237
|
-
Problems:
|
|
238
|
-
- ❌ Duplication (component defined multiple times)
|
|
239
|
-
- ❌ Hard to maintain (update in multiple places)
|
|
240
|
-
- ❌ Manual rendering (write demo for each component)
|
|
241
|
-
- ❌ No AI export
|
|
242
|
-
```
|
|
243
|
-
|
|
244
|
-
### New Architecture
|
|
245
|
-
```
|
|
246
|
-
UILayout/
|
|
247
|
-
├── config/
|
|
248
|
-
│ ├── components/ # All component definitions
|
|
249
|
-
│ │ ├── forms.config.tsx
|
|
250
|
-
│ │ ├── layout.config.tsx
|
|
251
|
-
│ │ └── ... (9 files total)
|
|
252
|
-
│ ├── categories.config.tsx
|
|
253
|
-
│ ├── tailwind.config.ts
|
|
254
|
-
│ └── ai-export.config.ts
|
|
255
|
-
├── components/
|
|
256
|
-
│ ├── AutoComponentDemo.tsx # Auto-renders from config
|
|
257
|
-
│ ├── CategoryRenderer.tsx # Renders entire category
|
|
258
|
-
│ └── TailwindGuideRenderer.tsx # Renders guide
|
|
259
|
-
└── ...
|
|
260
|
-
|
|
261
|
-
Benefits:
|
|
262
|
-
- ✅ Single source of truth (config)
|
|
263
|
-
- ✅ Easy to maintain (one place to update)
|
|
264
|
-
- ✅ Auto-rendering (no manual demos)
|
|
265
|
-
- ✅ AI export built-in
|
|
266
|
-
```
|
|
267
|
-
|
|
268
|
-
## 🎯 Migration Path
|
|
269
|
-
|
|
270
|
-
If you want to migrate existing component showcase:
|
|
271
|
-
|
|
272
|
-
1. **Analyze existing demos** - identify all components
|
|
273
|
-
2. **Create config files** - one per category
|
|
274
|
-
3. **Define ComponentConfig** - for each component:
|
|
275
|
-
```typescript
|
|
276
|
-
{
|
|
277
|
-
name: string,
|
|
278
|
-
category: string,
|
|
279
|
-
description: string,
|
|
280
|
-
importPath: string,
|
|
281
|
-
example: string,
|
|
282
|
-
preview: ReactNode
|
|
283
|
-
}
|
|
284
|
-
```
|
|
285
|
-
4. **Replace demos** - use `<CategoryRenderer categoryId="..." />`
|
|
286
|
-
5. **Test** - verify all components render correctly
|
|
287
|
-
6. **Delete old demos** - remove manual demo files
|
|
288
|
-
|
|
289
|
-
## ✅ Verification
|
|
290
|
-
|
|
291
|
-
### TypeScript Check
|
|
292
|
-
```bash
|
|
293
|
-
pnpm check
|
|
294
|
-
# ✅ No errors
|
|
295
|
-
```
|
|
296
|
-
|
|
297
|
-
### File Count
|
|
298
|
-
```bash
|
|
299
|
-
# Config files: 14
|
|
300
|
-
# Component files: 6
|
|
301
|
-
# Context: 1
|
|
302
|
-
# Core: 11
|
|
303
|
-
# Total: 32 files
|
|
304
|
-
```
|
|
305
|
-
|
|
306
|
-
### Component Count
|
|
307
|
-
```bash
|
|
308
|
-
# Total components in config: 53
|
|
309
|
-
# - Forms: 8
|
|
310
|
-
# - Layout: 5
|
|
311
|
-
# - Navigation: 4
|
|
312
|
-
# - Overlay: 11
|
|
313
|
-
# - Feedback: 5
|
|
314
|
-
# - Data: 5
|
|
315
|
-
# - Specialized: 2
|
|
316
|
-
# - Blocks: 7
|
|
317
|
-
# - Hooks: 6
|
|
318
|
-
```
|
|
319
|
-
|
|
320
|
-
## 🎉 Result
|
|
321
|
-
|
|
322
|
-
Полностью рефакторенная, config-driven система документации UI компонентов с:
|
|
323
|
-
- ✅ Единым источником правды (конфиг)
|
|
324
|
-
- ✅ Нулевым дублированием кода
|
|
325
|
-
- ✅ Автоматическим рендерингом
|
|
326
|
-
- ✅ Экспортом для AI
|
|
327
|
-
- ✅ TypeScript безопасностью
|
|
328
|
-
- ✅ Модульной структурой
|
|
329
|
-
- ✅ Легкой масштабируемостью
|
|
330
|
-
|
|
331
|
-
**Готово к использованию!** 🚀
|