@donotdev/ui 0.0.3 → 0.0.5
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/dist/components/auth/AuthMenu.d.ts.map +1 -1
- package/dist/components/auth/AuthMenu.js +4 -4
- package/dist/components/common/FeatureCard.d.ts +7 -19
- package/dist/components/common/FeatureCard.d.ts.map +1 -1
- package/dist/components/common/FeatureCard.js +4 -28
- package/dist/components/common/TechBento.d.ts +15 -3
- package/dist/components/common/TechBento.d.ts.map +1 -1
- package/dist/components/common/TechBento.js +20 -2
- package/dist/dndev.css +600 -163
- package/dist/index.js +4 -4
- package/dist/internal/devtools/DebugTools.js +1 -1
- package/dist/internal/devtools/components/ConfigTab.d.ts.map +1 -1
- package/dist/internal/devtools/components/ConfigTab.js +8 -6
- package/dist/internal/devtools/components/DesignTab.d.ts.map +1 -1
- package/dist/internal/devtools/components/DesignTab.js +256 -45
- package/dist/internal/devtools/components/StoresTab.d.ts.map +1 -1
- package/dist/internal/initializers/BaseStoresInitializer.d.ts.map +1 -1
- package/dist/internal/initializers/BaseStoresInitializer.js +11 -1
- package/dist/internal/layout/DnDevLayout.d.ts.map +1 -1
- package/dist/internal/layout/DnDevLayout.js +1 -5
- package/dist/internal/layout/components/AutoMetaTags.d.ts.map +1 -1
- package/dist/internal/layout/components/AutoMetaTags.js +6 -1
- package/dist/internal/layout/zones/DnDevFooter.js +2 -2
- package/dist/styles/index.css +600 -163
- package/dist/utils/assetResolver.d.ts.map +1 -1
- package/dist/utils/assetResolver.js +22 -11
- package/dist/utils/index.d.ts +1 -0
- package/dist/utils/index.d.ts.map +1 -1
- package/dist/utils/index.js +1 -0
- package/dist/utils/tList.d.ts +30 -0
- package/dist/utils/tList.d.ts.map +1 -0
- package/dist/utils/tList.js +51 -0
- package/dist/vite-routing/AppRoutes.d.ts.map +1 -1
- package/package.json +9 -9
|
@@ -119,7 +119,7 @@ const DebugTools = ({ className }) => {
|
|
|
119
119
|
? 'Reset consent (show banner)'
|
|
120
120
|
: 'Consent banner visible', children: hasConsented
|
|
121
121
|
? 'Show Cookie Banner'
|
|
122
|
-
: 'Cookie Banner Visible' })] }) }), footer: _jsx(Stack, { align: "center", justify: "center", className: cn('drag-handle', current === 'mobile' && 'dndev-text-destructive', current === 'tablet' && 'dndev-text-primary', current === '
|
|
122
|
+
: 'Cookie Banner Visible' })] }) }), footer: _jsx(Stack, { align: "center", justify: "center", className: cn('drag-handle', current === 'mobile' && 'dndev-text-destructive', current === 'tablet' && 'dndev-text-primary', current === 'laptop' && 'dndev-text-secondary-foreground', current === 'desktop' && 'dndev-text-muted-foreground'), style: {
|
|
123
123
|
cursor: 'grab',
|
|
124
124
|
}, children: _jsxs(Label, { className: "dndev-font-mono dndev-text-lg", children: [current.toUpperCase(), " : ", width, " \u00D7 ", height, "px"] }) }) }) }) }));
|
|
125
125
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ConfigTab.d.ts","sourceRoot":"","sources":["../../../../src/internal/devtools/components/ConfigTab.tsx"],"names":[],"mappings":"AAwBA,eAAO,MAAM,SAAS,+
|
|
1
|
+
{"version":3,"file":"ConfigTab.d.ts","sourceRoot":"","sources":["../../../../src/internal/devtools/components/ConfigTab.tsx"],"names":[],"mappings":"AAwBA,eAAO,MAAM,SAAS,+CAqGrB,CAAC"}
|
|
@@ -26,29 +26,31 @@ export const ConfigTab = () => {
|
|
|
26
26
|
},
|
|
27
27
|
{
|
|
28
28
|
label: 'Mode',
|
|
29
|
-
value: _jsx(Badge, { variant: config.mode === 'development'
|
|
29
|
+
value: (_jsx(Badge, { variant: config.mode === 'development'
|
|
30
|
+
? BADGE_VARIANT.DEFAULT
|
|
31
|
+
: BADGE_VARIANT.SECONDARY, children: config.mode })),
|
|
30
32
|
},
|
|
31
33
|
{
|
|
32
34
|
label: 'Version',
|
|
33
|
-
value: _jsx(Text, { className: "dndev-font-mono dndev-text-sm", children: config.version }),
|
|
35
|
+
value: (_jsx(Text, { className: "dndev-font-mono dndev-text-sm", children: config.version })),
|
|
34
36
|
},
|
|
35
37
|
];
|
|
36
38
|
const summaryItems = [
|
|
37
39
|
config.themes && {
|
|
38
40
|
label: 'Themes',
|
|
39
|
-
value: _jsx(Text, { className: "dndev-font-mono dndev-text-sm", children: config.themes.discovered?.length || 0 }),
|
|
41
|
+
value: (_jsx(Text, { className: "dndev-font-mono dndev-text-sm", children: config.themes.discovered?.length || 0 })),
|
|
40
42
|
},
|
|
41
43
|
config.routes && {
|
|
42
44
|
label: 'Routes',
|
|
43
|
-
value: _jsx(Text, { className: "dndev-font-mono dndev-text-sm", children: config.routes.mapping?.length || 0 }),
|
|
45
|
+
value: (_jsx(Text, { className: "dndev-font-mono dndev-text-sm", children: config.routes.mapping?.length || 0 })),
|
|
44
46
|
},
|
|
45
47
|
config.i18n && {
|
|
46
48
|
label: 'Languages',
|
|
47
|
-
value: _jsx(Text, { className: "dndev-font-mono dndev-text-sm", children: config.i18n.languages?.join(', ') }),
|
|
49
|
+
value: (_jsx(Text, { className: "dndev-font-mono dndev-text-sm", children: config.i18n.languages?.join(', ') })),
|
|
48
50
|
},
|
|
49
51
|
config.features && {
|
|
50
52
|
label: 'Features',
|
|
51
|
-
value: _jsx(Text, { className: "dndev-font-mono dndev-text-sm", children: config.features.available?.length || 0 }),
|
|
53
|
+
value: (_jsx(Text, { className: "dndev-font-mono dndev-text-sm", children: config.features.available?.length || 0 })),
|
|
52
54
|
},
|
|
53
55
|
].filter(Boolean);
|
|
54
56
|
const envItems = Object.entries(envVars).map(([key, value]) => ({
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"DesignTab.d.ts","sourceRoot":"","sources":["../../../../src/internal/devtools/components/DesignTab.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"DesignTab.d.ts","sourceRoot":"","sources":["../../../../src/internal/devtools/components/DesignTab.tsx"],"names":[],"mappings":"AA8CA,eAAO,MAAM,SAAS,+CAsuBrB,CAAC"}
|
|
@@ -10,7 +10,7 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
|
10
10
|
* @author AMBROISE PARK Consulting
|
|
11
11
|
*/
|
|
12
12
|
import { Palette, Type } from 'lucide-react';
|
|
13
|
-
import { useState } from 'react';
|
|
13
|
+
import { useState, useEffect } from 'react';
|
|
14
14
|
import { Card, Button, BUTTON_VARIANT, Stack, Label, Badge, BADGE_VARIANT, Alert, ALERT_VARIANT, DescriptionList, Text, ScrollArea, Accordion, CopyToClipboard, toast, } from '@donotdev/components';
|
|
15
15
|
import { useTheme, useThemeReady } from '@donotdev/core';
|
|
16
16
|
export const DesignTab = () => {
|
|
@@ -18,9 +18,137 @@ export const DesignTab = () => {
|
|
|
18
18
|
const availableThemes = useTheme('availableThemes');
|
|
19
19
|
const isDarkMode = useTheme('isDarkMode');
|
|
20
20
|
const isReady = useThemeReady();
|
|
21
|
+
// Load cached analysis from localStorage
|
|
22
|
+
const loadCachedAnalysis = () => {
|
|
23
|
+
try {
|
|
24
|
+
const cached = localStorage.getItem('dndev-design-analysis');
|
|
25
|
+
if (cached) {
|
|
26
|
+
const parsed = JSON.parse(cached);
|
|
27
|
+
if (parsed.colorRatio)
|
|
28
|
+
setColorRatio(parsed.colorRatio);
|
|
29
|
+
if (parsed.typography)
|
|
30
|
+
setTypography(parsed.typography);
|
|
31
|
+
if (parsed.fontSizeColors)
|
|
32
|
+
setFontSizeColors(parsed.fontSizeColors);
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
catch (e) {
|
|
36
|
+
// Ignore cache errors
|
|
37
|
+
}
|
|
38
|
+
};
|
|
39
|
+
// Save analysis to localStorage
|
|
40
|
+
const saveAnalysis = (colorRatioData, typographyData, fontSizeColorsData) => {
|
|
41
|
+
try {
|
|
42
|
+
localStorage.setItem('dndev-design-analysis', JSON.stringify({
|
|
43
|
+
colorRatio: colorRatioData,
|
|
44
|
+
typography: typographyData,
|
|
45
|
+
fontSizeColors: fontSizeColorsData,
|
|
46
|
+
timestamp: new Date().toISOString(),
|
|
47
|
+
}));
|
|
48
|
+
}
|
|
49
|
+
catch (e) {
|
|
50
|
+
// Ignore save errors
|
|
51
|
+
}
|
|
52
|
+
};
|
|
53
|
+
useEffect(() => {
|
|
54
|
+
loadCachedAnalysis();
|
|
55
|
+
}, []);
|
|
21
56
|
const [colorRatio, setColorRatio] = useState(null);
|
|
22
57
|
const [typography, setTypography] = useState(null);
|
|
23
58
|
const [isAnalyzing, setIsAnalyzing] = useState(false);
|
|
59
|
+
const [highlightedSize, setHighlightedSize] = useState(null);
|
|
60
|
+
const [fontSizeColors, setFontSizeColors] = useState({});
|
|
61
|
+
// Normalize font size for comparison (round to 2 decimals)
|
|
62
|
+
const normalizeFontSize = (size) => {
|
|
63
|
+
return parseFloat(size).toFixed(2) + 'px';
|
|
64
|
+
};
|
|
65
|
+
// Highlight/unhighlight elements by font size
|
|
66
|
+
const toggleHighlight = (size) => {
|
|
67
|
+
// Clear previous highlights
|
|
68
|
+
document.querySelectorAll('[data-dndev-highlight]').forEach((el) => {
|
|
69
|
+
el.style.outline = '';
|
|
70
|
+
el.removeAttribute('data-dndev-highlight');
|
|
71
|
+
});
|
|
72
|
+
if (highlightedSize === size) {
|
|
73
|
+
setHighlightedSize(null);
|
|
74
|
+
return;
|
|
75
|
+
}
|
|
76
|
+
// Highlight elements with matching font size - ONLY leaf nodes
|
|
77
|
+
const elements = document.querySelectorAll('*');
|
|
78
|
+
let count = 0;
|
|
79
|
+
const normalizedSize = normalizeFontSize(size);
|
|
80
|
+
elements.forEach((el) => {
|
|
81
|
+
if (isOverlayElement(el))
|
|
82
|
+
return;
|
|
83
|
+
// Only highlight leaf nodes (same logic as analysis)
|
|
84
|
+
const hasText = el.textContent && el.textContent.trim().length > 0;
|
|
85
|
+
const hasChildElements = el.children.length > 0;
|
|
86
|
+
if (!hasText || hasChildElements)
|
|
87
|
+
return;
|
|
88
|
+
const style = getComputedStyle(el);
|
|
89
|
+
if (normalizeFontSize(style.fontSize) === normalizedSize) {
|
|
90
|
+
el.style.outline = '2px solid var(--primary)';
|
|
91
|
+
el.setAttribute('data-dndev-highlight', 'true');
|
|
92
|
+
count++;
|
|
93
|
+
}
|
|
94
|
+
});
|
|
95
|
+
setHighlightedSize(size);
|
|
96
|
+
toast('info', `Highlighting ${count} elements with ${size}`);
|
|
97
|
+
};
|
|
98
|
+
// Apply color to elements with matching font size
|
|
99
|
+
const applyFontSizeColor = (size, color) => {
|
|
100
|
+
// Clear previous color for this size
|
|
101
|
+
document
|
|
102
|
+
.querySelectorAll(`[data-dndev-font-size-color="${size}"]`)
|
|
103
|
+
.forEach((el) => {
|
|
104
|
+
el.style.color = '';
|
|
105
|
+
el.removeAttribute('data-dndev-font-size-color');
|
|
106
|
+
});
|
|
107
|
+
if (!color) {
|
|
108
|
+
setFontSizeColors((prev) => {
|
|
109
|
+
const next = { ...prev };
|
|
110
|
+
delete next[size];
|
|
111
|
+
return next;
|
|
112
|
+
});
|
|
113
|
+
return;
|
|
114
|
+
}
|
|
115
|
+
// Apply color to all elements with this font size - ONLY leaf nodes
|
|
116
|
+
const elements = document.querySelectorAll('*');
|
|
117
|
+
let count = 0;
|
|
118
|
+
const normalizedSize = normalizeFontSize(size);
|
|
119
|
+
elements.forEach((el) => {
|
|
120
|
+
if (isOverlayElement(el))
|
|
121
|
+
return;
|
|
122
|
+
// Only color leaf nodes (same logic as analysis)
|
|
123
|
+
const hasText = el.textContent && el.textContent.trim().length > 0;
|
|
124
|
+
const hasChildElements = el.children.length > 0;
|
|
125
|
+
if (!hasText || hasChildElements)
|
|
126
|
+
return;
|
|
127
|
+
const style = getComputedStyle(el);
|
|
128
|
+
if (normalizeFontSize(style.fontSize) === normalizedSize) {
|
|
129
|
+
el.style.color = color;
|
|
130
|
+
el.setAttribute('data-dndev-font-size-color', size);
|
|
131
|
+
count++;
|
|
132
|
+
}
|
|
133
|
+
});
|
|
134
|
+
const newColors = { ...fontSizeColors, [size]: color };
|
|
135
|
+
setFontSizeColors(newColors);
|
|
136
|
+
saveAnalysis(colorRatio, typography, newColors);
|
|
137
|
+
};
|
|
138
|
+
// Clear highlights on unmount or when dialog closes
|
|
139
|
+
const clearHighlights = () => {
|
|
140
|
+
document.querySelectorAll('[data-dndev-highlight]').forEach((el) => {
|
|
141
|
+
el.style.outline = '';
|
|
142
|
+
el.removeAttribute('data-dndev-highlight');
|
|
143
|
+
});
|
|
144
|
+
document.querySelectorAll('[data-dndev-font-size-color]').forEach((el) => {
|
|
145
|
+
el.style.color = '';
|
|
146
|
+
el.removeAttribute('data-dndev-font-size-color');
|
|
147
|
+
});
|
|
148
|
+
setHighlightedSize(null);
|
|
149
|
+
setFontSizeColors({});
|
|
150
|
+
saveAnalysis(colorRatio, typography, {});
|
|
151
|
+
};
|
|
24
152
|
// Get CSS variables from :root
|
|
25
153
|
const getCSSVariables = () => {
|
|
26
154
|
const root = document.documentElement;
|
|
@@ -66,45 +194,34 @@ export const DesignTab = () => {
|
|
|
66
194
|
const analyzeTypography = () => {
|
|
67
195
|
const elements = document.querySelectorAll('*');
|
|
68
196
|
const fontSizeMap = new Map();
|
|
69
|
-
const fontWeightMap = new Map();
|
|
70
|
-
const fontFamilyMap = new Map();
|
|
71
197
|
let analyzedCount = 0;
|
|
72
198
|
elements.forEach((el) => {
|
|
73
|
-
// Skip overlay/devtools elements
|
|
74
199
|
if (isOverlayElement(el))
|
|
75
200
|
return;
|
|
201
|
+
if (el.tagName === 'SCRIPT' ||
|
|
202
|
+
el.tagName === 'STYLE' ||
|
|
203
|
+
el.tagName === 'NOSCRIPT')
|
|
204
|
+
return;
|
|
76
205
|
const style = getComputedStyle(el);
|
|
77
206
|
const rect = el.getBoundingClientRect();
|
|
78
|
-
// Skip invisible elements
|
|
79
207
|
if (rect.width === 0 || rect.height === 0)
|
|
80
208
|
return;
|
|
209
|
+
if (style.display === 'none' || style.visibility === 'hidden')
|
|
210
|
+
return;
|
|
211
|
+
// ONLY leaf nodes with text, no children
|
|
212
|
+
const hasText = el.textContent && el.textContent.trim().length > 0;
|
|
213
|
+
if (!hasText || el.children.length > 0)
|
|
214
|
+
return;
|
|
81
215
|
analyzedCount++;
|
|
82
|
-
// Font size
|
|
83
216
|
const fontSize = style.fontSize;
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
const fontWeight = style.fontWeight;
|
|
87
|
-
fontWeightMap.set(fontWeight, (fontWeightMap.get(fontWeight) || 0) + 1);
|
|
88
|
-
// Font family (simplified)
|
|
89
|
-
const fontFamily = style.fontFamily.split(',')[0]?.trim().replace(/"/g, '') || 'unknown';
|
|
90
|
-
fontFamilyMap.set(fontFamily, (fontFamilyMap.get(fontFamily) || 0) + 1);
|
|
217
|
+
const fontSizeRounded = parseFloat(fontSize).toFixed(2) + 'px';
|
|
218
|
+
fontSizeMap.set(fontSizeRounded, (fontSizeMap.get(fontSizeRounded) || 0) + 1);
|
|
91
219
|
});
|
|
92
|
-
// Sort by count descending
|
|
93
220
|
const fontSizes = Array.from(fontSizeMap.entries())
|
|
94
221
|
.map(([size, count]) => ({ size, count }))
|
|
95
|
-
.sort((a, b) => b.count - a.count)
|
|
96
|
-
.slice(0, 10);
|
|
97
|
-
const fontWeights = Array.from(fontWeightMap.entries())
|
|
98
|
-
.map(([weight, count]) => ({ weight, count }))
|
|
99
222
|
.sort((a, b) => b.count - a.count);
|
|
100
|
-
const fontFamilies = Array.from(fontFamilyMap.entries())
|
|
101
|
-
.map(([family, count]) => ({ family, count }))
|
|
102
|
-
.sort((a, b) => b.count - a.count)
|
|
103
|
-
.slice(0, 5);
|
|
104
223
|
return {
|
|
105
224
|
fontSizes,
|
|
106
|
-
fontWeights,
|
|
107
|
-
fontFamilies,
|
|
108
225
|
totalElements: analyzedCount,
|
|
109
226
|
};
|
|
110
227
|
};
|
|
@@ -121,7 +238,10 @@ export const DesignTab = () => {
|
|
|
121
238
|
const area = rect.width * rect.height;
|
|
122
239
|
if (bg && bg !== 'rgba(0, 0, 0, 0)' && bg !== 'transparent' && area > 0) {
|
|
123
240
|
const existing = colorMap.get(bg) || { count: 0, area: 0 };
|
|
124
|
-
colorMap.set(bg, {
|
|
241
|
+
colorMap.set(bg, {
|
|
242
|
+
count: existing.count + 1,
|
|
243
|
+
area: existing.area + area,
|
|
244
|
+
});
|
|
125
245
|
}
|
|
126
246
|
});
|
|
127
247
|
const totalArea = Array.from(colorMap.values()).reduce((sum, v) => sum + v.area, 0);
|
|
@@ -134,8 +254,12 @@ export const DesignTab = () => {
|
|
|
134
254
|
}))
|
|
135
255
|
.sort((a, b) => b.percentage - a.percentage);
|
|
136
256
|
// Simplified categorization based on percentage
|
|
137
|
-
const dominant = colors
|
|
138
|
-
|
|
257
|
+
const dominant = colors
|
|
258
|
+
.slice(0, 2)
|
|
259
|
+
.reduce((sum, c) => sum + c.percentage, 0);
|
|
260
|
+
const secondary = colors
|
|
261
|
+
.slice(2, 5)
|
|
262
|
+
.reduce((sum, c) => sum + c.percentage, 0);
|
|
139
263
|
const accent = colors.slice(5).reduce((sum, c) => sum + c.percentage, 0);
|
|
140
264
|
return {
|
|
141
265
|
dominant,
|
|
@@ -143,15 +267,22 @@ export const DesignTab = () => {
|
|
|
143
267
|
accent,
|
|
144
268
|
details: colors.slice(0, 15).map((c) => ({
|
|
145
269
|
...c,
|
|
146
|
-
category: c.percentage > 30
|
|
270
|
+
category: c.percentage > 30
|
|
271
|
+
? 'dominant'
|
|
272
|
+
: c.percentage > 10
|
|
273
|
+
? 'secondary'
|
|
274
|
+
: 'accent',
|
|
147
275
|
})),
|
|
148
276
|
};
|
|
149
277
|
};
|
|
150
278
|
const runAnalysis = () => {
|
|
151
279
|
setIsAnalyzing(true);
|
|
152
280
|
try {
|
|
153
|
-
|
|
154
|
-
|
|
281
|
+
const colorRatioData = analyzeColorRatio();
|
|
282
|
+
const typographyData = analyzeTypography();
|
|
283
|
+
setColorRatio(colorRatioData);
|
|
284
|
+
setTypography(typographyData);
|
|
285
|
+
saveAnalysis(colorRatioData, typographyData, fontSizeColors);
|
|
155
286
|
toast('success', 'Analysis complete');
|
|
156
287
|
}
|
|
157
288
|
catch (error) {
|
|
@@ -178,18 +309,33 @@ export const DesignTab = () => {
|
|
|
178
309
|
}, null, 2);
|
|
179
310
|
};
|
|
180
311
|
const copyAnalysis = () => {
|
|
181
|
-
navigator.clipboard
|
|
312
|
+
navigator.clipboard
|
|
313
|
+
.writeText(getAnalysisJson())
|
|
314
|
+
.then(() => {
|
|
182
315
|
toast('success', 'Analysis copied to clipboard');
|
|
183
|
-
})
|
|
316
|
+
})
|
|
317
|
+
.catch(() => {
|
|
184
318
|
toast('error', 'Failed to copy');
|
|
185
319
|
});
|
|
186
320
|
};
|
|
187
321
|
const cssVars = getCSSVariables();
|
|
188
322
|
const themeItems = [
|
|
189
|
-
{
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
323
|
+
{
|
|
324
|
+
label: 'Current',
|
|
325
|
+
value: _jsx(Text, { className: "dndev-font-mono", children: currentTheme }),
|
|
326
|
+
},
|
|
327
|
+
{
|
|
328
|
+
label: 'Dark Mode',
|
|
329
|
+
value: (_jsx(Badge, { variant: isDarkMode ? BADGE_VARIANT.DEFAULT : BADGE_VARIANT.SECONDARY, children: isDarkMode ? 'Yes' : 'No' })),
|
|
330
|
+
},
|
|
331
|
+
{
|
|
332
|
+
label: 'Ready',
|
|
333
|
+
value: (_jsx(Badge, { variant: isReady ? BADGE_VARIANT.DEFAULT : BADGE_VARIANT.DESTRUCTIVE, children: isReady ? 'Yes' : 'No' })),
|
|
334
|
+
},
|
|
335
|
+
{
|
|
336
|
+
label: 'Available',
|
|
337
|
+
value: (_jsxs(Text, { className: "dndev-font-mono", children: [availableThemes.length, " themes"] })),
|
|
338
|
+
},
|
|
193
339
|
];
|
|
194
340
|
const isColorCompliant = colorRatio &&
|
|
195
341
|
colorRatio.dominant >= 50 &&
|
|
@@ -198,16 +344,30 @@ export const DesignTab = () => {
|
|
|
198
344
|
colorRatio.secondary <= 40 &&
|
|
199
345
|
colorRatio.accent >= 5 &&
|
|
200
346
|
colorRatio.accent <= 20;
|
|
201
|
-
return (_jsxs(Stack, { gap: "medium", style: { padding: 'var(--gap-md)' }, children: [_jsx(
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
347
|
+
return (_jsxs(Stack, { gap: "medium", style: { padding: 'var(--gap-md)' }, children: [_jsx(Accordion, { type: "single", collapsible: true, items: [
|
|
348
|
+
{
|
|
349
|
+
value: 'theme',
|
|
350
|
+
trigger: _jsx("span", { children: "Theme Info" }),
|
|
351
|
+
content: (_jsxs(Stack, { gap: "medium", children: [_jsx(Card, { title: "Theme", subtitle: currentTheme, children: _jsx(DescriptionList, { items: themeItems }) }), _jsx(Card, { title: "CSS Variables", subtitle: `${Object.keys(cssVars).length} variables`, children: _jsx(ScrollArea, { className: "dndev-max-h-48", children: _jsx(Stack, { gap: "tight", children: Object.entries(cssVars).map(([name, value]) => (_jsxs(Stack, { direction: "row", align: "center", justify: "between", gap: "tight", children: [_jsx(Text, { className: "dndev-font-mono dndev-text-xs", children: name }), _jsxs(Stack, { direction: "row", align: "center", gap: "tight", children: [_jsx("div", { style: {
|
|
352
|
+
width: '1rem',
|
|
353
|
+
height: '1rem',
|
|
354
|
+
backgroundColor: `var(${name})`,
|
|
355
|
+
border: '1px solid var(--border)',
|
|
356
|
+
borderRadius: 'var(--radius-sm)',
|
|
357
|
+
} }), _jsx(Text, { className: "dndev-font-mono dndev-text-xs dndev-text-muted-foreground", children: value })] })] }, name))) }) }) })] })),
|
|
358
|
+
},
|
|
359
|
+
] }), _jsxs(Stack, { direction: "row", gap: "tight", children: [_jsx(Button, { onClick: runAnalysis, variant: BUTTON_VARIANT.DEFAULT, icon: Palette, disabled: isAnalyzing, style: { flex: 1 }, children: isAnalyzing ? 'Analyzing...' : 'Analyze Page' }), _jsx(Button, { onClick: copyAnalysis, variant: BUTTON_VARIANT.OUTLINE, disabled: !colorRatio && !typography, children: "Copy JSON" })] }), colorRatio && (_jsx(Card, { content: _jsxs(Stack, { direction: "row", align: "center", justify: "between", className: "dndev-w-full", children: [_jsx("span", { children: "60/30/10 Color Ratio" }), _jsx(Badge, { variant: isColorCompliant
|
|
360
|
+
? BADGE_VARIANT.DEFAULT
|
|
361
|
+
: BADGE_VARIANT.SECONDARY, children: isColorCompliant ? '✓ Balanced' : '⚠ Review' })] }), children: _jsxs(Stack, { gap: "tight", children: [_jsxs(Stack, { direction: "row", justify: "between", children: [_jsx("span", { children: "Dominant (60%)" }), _jsxs("span", { className: colorRatio.dominant >= 50 && colorRatio.dominant <= 70
|
|
362
|
+
? 'dndev-text-primary'
|
|
363
|
+
: 'dndev-text-destructive', children: [colorRatio.dominant.toFixed(1), "%"] })] }), _jsxs(Stack, { direction: "row", justify: "between", children: [_jsx("span", { children: "Secondary (30%)" }), _jsxs("span", { className: colorRatio.secondary >= 20 && colorRatio.secondary <= 40
|
|
364
|
+
? 'dndev-text-primary'
|
|
365
|
+
: 'dndev-text-destructive', children: [colorRatio.secondary.toFixed(1), "%"] })] }), _jsxs(Stack, { direction: "row", justify: "between", children: [_jsx("span", { children: "Accent (10%)" }), _jsxs("span", { className: colorRatio.accent >= 5 && colorRatio.accent <= 20
|
|
366
|
+
? 'dndev-text-primary'
|
|
367
|
+
: 'dndev-text-destructive', children: [colorRatio.accent.toFixed(1), "%"] })] }), colorRatio.details.length > 0 && (_jsx(Accordion, { type: "single", collapsible: true, items: [
|
|
208
368
|
{
|
|
209
369
|
value: 'colors',
|
|
210
|
-
trigger: _jsxs("span", { className: "dndev-text-sm", children: ["Top Colors (", colorRatio.details.length, ")"] }),
|
|
370
|
+
trigger: (_jsxs("span", { className: "dndev-text-sm", children: ["Top Colors (", colorRatio.details.length, ")"] })),
|
|
211
371
|
content: (_jsx(Stack, { gap: "tight", children: colorRatio.details.map((c, i) => (_jsxs(Stack, { direction: "row", align: "center", gap: "tight", children: [_jsx("div", { style: {
|
|
212
372
|
width: '1rem',
|
|
213
373
|
height: '1rem',
|
|
@@ -216,5 +376,56 @@ export const DesignTab = () => {
|
|
|
216
376
|
flexShrink: 0,
|
|
217
377
|
} }), _jsxs(Text, { className: "dndev-text-xs dndev-font-mono", style: { flex: 1 }, children: [c.percentage.toFixed(1), "%"] }), _jsx(Badge, { variant: BADGE_VARIANT.SECONDARY, children: c.category })] }, i))) })),
|
|
218
378
|
},
|
|
219
|
-
] }))] }) })), typography && (
|
|
379
|
+
] }))] }) })), typography && (_jsxs(Card, { content: _jsxs(Stack, { direction: "row", align: "center", justify: "between", className: "dndev-w-full", children: [_jsx("span", { children: "Font Sizes" }), _jsxs(Badge, { variant: BADGE_VARIANT.SECONDARY, children: [typography.totalElements, " elements"] })] }), children: [_jsxs(Stack, { direction: "row", align: "center", justify: "between", children: [_jsxs(Label, { className: "dndev-text-sm dndev-font-semibold", children: [typography.fontSizes.length, " sizes"] }), (highlightedSize || Object.keys(fontSizeColors).length > 0) && (_jsx(Button, { variant: BUTTON_VARIANT.GHOST, onClick: clearHighlights, style: { padding: '0 var(--gap-xs)', height: 'auto' }, children: _jsx(Text, { className: "dndev-text-xs", children: "Clear All" }) }))] }), _jsx(Stack, { gap: "tight", className: "dndev-mt-xs", children: typography.fontSizes.map((f, i) => {
|
|
380
|
+
const isOrphan = f.count < 5;
|
|
381
|
+
const isHighlighted = highlightedSize === f.size;
|
|
382
|
+
const currentColor = fontSizeColors[f.size] || '';
|
|
383
|
+
const findOrphanElements = () => {
|
|
384
|
+
const normalizedSize = normalizeFontSize(f.size);
|
|
385
|
+
const found = Array.from(document.querySelectorAll('*')).filter((el) => {
|
|
386
|
+
if (el.closest('[data-dndev-devtools]') ||
|
|
387
|
+
el.closest('[data-radix-portal]') ||
|
|
388
|
+
el.closest('[role="dialog"]'))
|
|
389
|
+
return false;
|
|
390
|
+
const style = getComputedStyle(el);
|
|
391
|
+
const hasText = el.textContent && el.textContent.trim().length > 0;
|
|
392
|
+
if (!hasText || el.children.length > 0)
|
|
393
|
+
return false;
|
|
394
|
+
return normalizeFontSize(style.fontSize) === normalizedSize;
|
|
395
|
+
});
|
|
396
|
+
found.forEach((el) => {
|
|
397
|
+
console.log(el, el.textContent?.trim().substring(0, 50));
|
|
398
|
+
el.style.outline = '2px solid red';
|
|
399
|
+
});
|
|
400
|
+
console.log(`Found ${found.length} elements with ${f.size}`);
|
|
401
|
+
};
|
|
402
|
+
return (_jsxs(Stack, { direction: "row", justify: "between", align: "center", gap: "tight", style: {
|
|
403
|
+
padding: 'var(--gap-xs)',
|
|
404
|
+
borderRadius: 'var(--radius-sm)',
|
|
405
|
+
backgroundColor: isHighlighted
|
|
406
|
+
? 'var(--primary)'
|
|
407
|
+
: 'transparent',
|
|
408
|
+
color: isHighlighted
|
|
409
|
+
? 'var(--primary-foreground)'
|
|
410
|
+
: 'inherit',
|
|
411
|
+
}, children: [_jsxs(Stack, { direction: "row", align: "center", gap: "tight", onClick: () => toggleHighlight(f.size), style: { cursor: 'pointer', flex: 1 }, children: [_jsx(Text, { className: "dndev-font-mono dndev-text-xs", children: f.size }), isOrphan && (_jsx(Badge, { variant: BADGE_VARIANT.DESTRUCTIVE, children: "orphan" }))] }), isOrphan ? (_jsx(Button, { variant: BUTTON_VARIANT.GHOST, onClick: (e) => {
|
|
412
|
+
e.stopPropagation();
|
|
413
|
+
findOrphanElements();
|
|
414
|
+
}, style: {
|
|
415
|
+
padding: '0 var(--gap-xs)',
|
|
416
|
+
height: '1.5rem',
|
|
417
|
+
minWidth: '2rem',
|
|
418
|
+
}, title: `Find ${f.size} elements in console`, children: _jsx(Text, { className: "dndev-text-xs", children: "\uD83D\uDD0D" }) })) : (_jsx("input", { type: "color", value: currentColor || '#000000', onChange: (e) => applyFontSizeColor(f.size, e.target.value), onClick: (e) => e.stopPropagation(), style: {
|
|
419
|
+
width: '2rem',
|
|
420
|
+
height: '1.5rem',
|
|
421
|
+
border: '1px solid var(--border)',
|
|
422
|
+
borderRadius: 'var(--radius-sm)',
|
|
423
|
+
cursor: 'pointer',
|
|
424
|
+
padding: 0,
|
|
425
|
+
}, title: `Color elements with ${f.size}` })), _jsxs(Text, { className: "dndev-text-xs", style: {
|
|
426
|
+
opacity: isHighlighted ? 1 : 0.6,
|
|
427
|
+
minWidth: '2rem',
|
|
428
|
+
textAlign: 'end',
|
|
429
|
+
}, children: [f.count, "\u00D7"] })] }, i));
|
|
430
|
+
}) })] })), !colorRatio && !typography && (_jsx(Alert, { variant: ALERT_VARIANT.INFO, children: "Click \"Analyze Page\" to check color ratio and typography" }))] }));
|
|
220
431
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"StoresTab.d.ts","sourceRoot":"","sources":["../../../../src/internal/devtools/components/StoresTab.tsx"],"names":[],"mappings":"AAwCA,eAAO,MAAM,SAAS,+
|
|
1
|
+
{"version":3,"file":"StoresTab.d.ts","sourceRoot":"","sources":["../../../../src/internal/devtools/components/StoresTab.tsx"],"names":[],"mappings":"AAwCA,eAAO,MAAM,SAAS,+CAoHrB,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"BaseStoresInitializer.d.ts","sourceRoot":"","sources":["../../../src/internal/initializers/BaseStoresInitializer.tsx"],"names":[],"mappings":"AAkCA,OAAO,KAAK,EAAa,iBAAiB,EAAE,MAAM,gBAAgB,CAAC;AAEnE,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AA6DvC;;;;;;GAMG;AACH,MAAM,WAAW,aAAa;IAC5B,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED;;;;;;GAMG;AACH,MAAM,WAAW,0BAA0B;IACzC,QAAQ,EAAE,SAAS,CAAC;IACpB,QAAQ,EAAE,aAAa,CAAC;IACxB,YAAY,CAAC,EAAE,iBAAiB,EAAE,CAAC;IACnC,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AAyGD;;;;;;;;;GASG;AACH,wBAAgB,qBAAqB,CAAC,EACpC,QAAQ,EACR,QAAQ,EACR,YAAiB,EACjB,aAAqB,EACrB,aAAa,GACd,EAAE,0BAA0B,
|
|
1
|
+
{"version":3,"file":"BaseStoresInitializer.d.ts","sourceRoot":"","sources":["../../../src/internal/initializers/BaseStoresInitializer.tsx"],"names":[],"mappings":"AAkCA,OAAO,KAAK,EAAa,iBAAiB,EAAE,MAAM,gBAAgB,CAAC;AAEnE,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AA6DvC;;;;;;GAMG;AACH,MAAM,WAAW,aAAa;IAC5B,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED;;;;;;GAMG;AACH,MAAM,WAAW,0BAA0B;IACzC,QAAQ,EAAE,SAAS,CAAC;IACpB,QAAQ,EAAE,aAAa,CAAC;IACxB,YAAY,CAAC,EAAE,iBAAiB,EAAE,CAAC;IACnC,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AAyGD;;;;;;;;;GASG;AACH,wBAAgB,qBAAqB,CAAC,EACpC,QAAQ,EACR,QAAQ,EACR,YAAiB,EACjB,aAAqB,EACrB,aAAa,GACd,EAAE,0BAA0B,kDAgJ5B"}
|
|
@@ -5,7 +5,7 @@ import { Fragment as _Fragment, jsx as _jsx } from "react/jsx-runtime";
|
|
|
5
5
|
* @fileoverview Base stores initializer for framework state management
|
|
6
6
|
* @description Initializes and coordinates all framework stores with proper error handling and readiness checks
|
|
7
7
|
*
|
|
8
|
-
* @version 0.0.
|
|
8
|
+
* @version 0.0.2
|
|
9
9
|
* @since 0.0.1
|
|
10
10
|
* @author AMBROISE PARK Consulting
|
|
11
11
|
*/
|
|
@@ -244,6 +244,16 @@ export function BaseStoresInitializer({ children, handlers, customStores = [], s
|
|
|
244
244
|
return;
|
|
245
245
|
removed = true;
|
|
246
246
|
removeShellLoader({ fade: true }); // Always fade
|
|
247
|
+
// Focus main so PageUp/PageDown works (CSR/SSR safe)
|
|
248
|
+
if (isClient()) {
|
|
249
|
+
requestAnimationFrame(() => {
|
|
250
|
+
const main = document.querySelector('main');
|
|
251
|
+
if (main) {
|
|
252
|
+
main.setAttribute('tabindex', '-1'); // Focusable but not in tab order
|
|
253
|
+
main.focus();
|
|
254
|
+
}
|
|
255
|
+
});
|
|
256
|
+
}
|
|
247
257
|
};
|
|
248
258
|
const checkBothReady = () => {
|
|
249
259
|
if (!frameworkReady || !routeReady || removed)
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"DnDevLayout.d.ts","sourceRoot":"","sources":["../../../src/internal/layout/DnDevLayout.tsx"],"names":[],"mappings":"AAGA;;;;;;;;GAQG;AAEH,OAAO,EAQL,KAAK,SAAS,EACf,MAAM,OAAO,CAAC;AAIf,OAAO,KAAK,EAIV,YAAY,EACb,MAAM,gBAAgB,CAAC;AA2CxB,UAAU,yBAAyB;IACjC,MAAM,CAAC,EAAE,YAAY,CAAC;IACtB,QAAQ,CAAC,EAAE,SAAS,CAAC;IACrB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED;;;;;;;;;;;;;;GAcG;AACH,eAAO,MAAM,WAAW,GAAI,kCAIzB,yBAAyB,
|
|
1
|
+
{"version":3,"file":"DnDevLayout.d.ts","sourceRoot":"","sources":["../../../src/internal/layout/DnDevLayout.tsx"],"names":[],"mappings":"AAGA;;;;;;;;GAQG;AAEH,OAAO,EAQL,KAAK,SAAS,EACf,MAAM,OAAO,CAAC;AAIf,OAAO,KAAK,EAIV,YAAY,EACb,MAAM,gBAAgB,CAAC;AA2CxB,UAAU,yBAAyB;IACjC,MAAM,CAAC,EAAE,YAAY,CAAC;IACtB,QAAQ,CAAC,EAAE,SAAS,CAAC;IACrB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED;;;;;;;;;;;;;;GAcG;AACH,eAAO,MAAM,WAAW,GAAI,kCAIzB,yBAAyB,4CAsT3B,CAAC"}
|
|
@@ -247,9 +247,5 @@ export const DnDevLayout = ({ children, layout, className, }) => {
|
|
|
247
247
|
};
|
|
248
248
|
startTransition(updateDOM);
|
|
249
249
|
}, [effectivePreset]);
|
|
250
|
-
return (_jsxs("div", { className: cn('dndev-layout', className), children: [resolvedHeader, resolvedSidebar, _jsxs("main", { ref: mainRef, role: "main", className: "main", children: [breadcrumbs !==
|
|
251
|
-
? 'smart'
|
|
252
|
-
: breadcrumbs === 'always'
|
|
253
|
-
? 'default'
|
|
254
|
-
: 'smart' }) })), isDev() && (_jsx(Suspense, { fallback: null, children: _jsx(DebugTools, {}) })), _jsx(Stack, { flex: "1", className: "dndev-min-h-0", children: content }, pathname)] }), resolvedFooter, resolvedMergedBar, _jsx(GoToWrapper, {})] }));
|
|
250
|
+
return (_jsxs("div", { className: cn('dndev-layout', className), children: [resolvedHeader, resolvedSidebar, _jsxs("main", { ref: mainRef, role: "main", className: "main", children: [breadcrumbs !== 'never' && (_jsx("div", { className: "breadcrumbs-container", children: _jsx(Breadcrumbs, { variant: breadcrumbs === 'always' ? 'default' : 'smart' }) })), isDev() && (_jsx(Suspense, { fallback: null, children: _jsx(DebugTools, {}) })), _jsx(Stack, { flex: "1", className: "dndev-min-h-0", children: content }, pathname)] }), resolvedFooter, resolvedMergedBar, _jsx(GoToWrapper, {})] }));
|
|
255
251
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AutoMetaTags.d.ts","sourceRoot":"","sources":["../../../../src/internal/layout/components/AutoMetaTags.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"AutoMetaTags.d.ts","sourceRoot":"","sources":["../../../../src/internal/layout/components/AutoMetaTags.tsx"],"names":[],"mappings":"AA2DA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,OAAO,CAAC;AAwC3C;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,YAAY,EAAE,aAoN1B,CAAC;AAEF;;;GAGG;AAEH,eAAe,YAAY,CAAC"}
|
|
@@ -50,6 +50,7 @@ import { Helmet } from 'react-helmet-async';
|
|
|
50
50
|
import { useTranslation, useIsClient } from '@donotdev/core';
|
|
51
51
|
import { getDndevConfig } from '@donotdev/core';
|
|
52
52
|
import { useSeoConfig, useAppConfig } from '@donotdev/core';
|
|
53
|
+
import { AssetResolver } from '@donotdev/ui';
|
|
53
54
|
// Platform-specific hooks via conditional exports
|
|
54
55
|
import { useLocation } from '@donotdev/ui/routing/hooks';
|
|
55
56
|
/**
|
|
@@ -176,7 +177,11 @@ export const AutoMetaTags = () => {
|
|
|
176
177
|
name: siteName,
|
|
177
178
|
logo: {
|
|
178
179
|
'@type': 'ImageObject',
|
|
179
|
-
url: '/
|
|
180
|
+
url: AssetResolver.assetExists('/icon-512x512.png')
|
|
181
|
+
? '/icon-512x512.png'
|
|
182
|
+
: AssetResolver.assetExists('/icon-192x192.png')
|
|
183
|
+
? '/icon-192x192.png'
|
|
184
|
+
: '/logo.svg',
|
|
180
185
|
},
|
|
181
186
|
},
|
|
182
187
|
}) })] }));
|
|
@@ -34,7 +34,7 @@ import { useLegalLinks, } from '../components/footer/useLegalLinks';
|
|
|
34
34
|
*/
|
|
35
35
|
function DnDevFooterComponent({ app = {} }) {
|
|
36
36
|
const { t } = useTranslation('dndev');
|
|
37
|
-
const
|
|
37
|
+
const isLaptopOrDesktop = useBreakpoint('isLaptopOrDesktop');
|
|
38
38
|
// Explicit null hides footer
|
|
39
39
|
if (app?.footer === null) {
|
|
40
40
|
return null;
|
|
@@ -48,7 +48,7 @@ function DnDevFooterComponent({ app = {} }) {
|
|
|
48
48
|
? `© ${new Date().getFullYear()} ${app.name || 'App'}. ${t('footer.legal.allRightsReserved')}`
|
|
49
49
|
: copyrightConfig;
|
|
50
50
|
// Desktop/Wide: 2-zone layout [Copyright] | [Links + DoNotDev]
|
|
51
|
-
if (
|
|
51
|
+
if (isLaptopOrDesktop) {
|
|
52
52
|
return (_jsx("footer", { role: "contentinfo", className: "footer", children: _jsxs(Stack, { direction: "row", align: "center", justify: "between", gap: "none", children: [showCopyright && (_jsx("div", { className: "dndev-flex dndev-justify-start", children: _jsx("span", { className: "footer-copyright", children: copyrightText }) })), _jsx("div", { className: "dndev-flex dndev-justify-end", children: _jsxs(Stack, { direction: "row", gap: "medium", align: "center", children: [links.map((link) => (_jsx(Link, { path: link.path, children: maybeTranslate(t, link.label) }, link.path))), _jsx(FooterBranding, {})] }) })] }) }));
|
|
53
53
|
}
|
|
54
54
|
// Mobile/Tablet: stacked layout
|