@donotdev/ui 0.0.13 → 0.0.15
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 +19 -20
- package/dist/components/common/FeatureCard.d.ts +3 -1
- package/dist/components/common/FeatureCard.d.ts.map +1 -1
- package/dist/components/common/FeatureCard.js +2 -2
- package/dist/components/common/ProgressBar.js +2 -2
- package/dist/components/common/TechBento.d.ts +14 -2
- package/dist/components/common/TechBento.d.ts.map +1 -1
- package/dist/components/common/TechBento.js +8 -9
- package/dist/components/cookie-consent/CookieConsent.d.ts.map +1 -1
- package/dist/components/cookie-consent/CookieConsent.js +3 -4
- package/dist/components/layout/components/DropdownNavigation.d.ts.map +1 -1
- package/dist/components/layout/components/DropdownNavigation.js +3 -12
- package/dist/components/layout/components/FloatingLanguageSwitcher.js +1 -1
- package/dist/components/layout/components/Notifications.d.ts +1 -3
- package/dist/components/layout/components/Notifications.d.ts.map +1 -1
- package/dist/components/layout/components/Notifications.js +4 -2
- package/dist/components/layout/components/header/AppBranding.d.ts.map +1 -1
- package/dist/components/layout/components/header/AppBranding.js +2 -1
- package/dist/components/layout/components/header/AppIcon.d.ts.map +1 -1
- package/dist/components/layout/components/header/AppIcon.js +5 -2
- package/dist/components/layout/components/header/CacheSettings.d.ts.map +1 -1
- package/dist/components/layout/components/header/CacheSettings.js +3 -1
- package/dist/components/layout/components/header/HeaderNavigation.d.ts +6 -0
- package/dist/components/layout/components/header/HeaderNavigation.d.ts.map +1 -1
- package/dist/components/layout/components/header/HeaderNavigation.js +12 -2
- package/dist/components/layout/components/index.d.ts +3 -0
- package/dist/components/layout/components/index.d.ts.map +1 -1
- package/dist/components/layout/components/index.js +3 -0
- package/dist/components/license/LicenseWatermark.d.ts.map +1 -1
- package/dist/components/license/LicenseWatermark.js +3 -1
- package/dist/crud/components/CrudCardLink.d.ts +17 -0
- package/dist/crud/components/CrudCardLink.d.ts.map +1 -0
- package/dist/crud/components/CrudCardLink.js +17 -0
- package/dist/crud/components/EntityCardList.d.ts +1 -1
- package/dist/crud/components/EntityCardList.d.ts.map +1 -1
- package/dist/crud/components/EntityCardList.js +38 -90
- package/dist/crud/components/EntityDisplayRenderer.d.ts +1 -1
- package/dist/crud/components/EntityDisplayRenderer.d.ts.map +1 -1
- package/dist/crud/components/EntityDisplayRenderer.js +11 -3
- package/dist/crud/components/EntityFormRenderer.d.ts +1 -1
- package/dist/crud/components/EntityFormRenderer.d.ts.map +1 -1
- package/dist/crud/components/EntityFormRenderer.js +34 -40
- package/dist/crud/components/EntityList.d.ts +1 -1
- package/dist/crud/components/EntityList.d.ts.map +1 -1
- package/dist/crud/components/EntityList.js +1 -1
- package/dist/crud/components/EntityRecommendations.d.ts +29 -0
- package/dist/crud/components/EntityRecommendations.d.ts.map +1 -0
- package/dist/crud/components/EntityRecommendations.js +32 -0
- package/dist/crud/components/index.d.ts +2 -1
- package/dist/crud/components/index.d.ts.map +1 -1
- package/dist/crud/components/index.js +1 -0
- package/dist/dndev.css +1021 -196
- package/dist/index.js +4 -4
- package/dist/internal/common/RouteErrorFallback.d.ts.map +1 -1
- package/dist/internal/devtools/components/AuthDebugButton.js +1 -1
- package/dist/internal/devtools/components/DesignTab.d.ts.map +1 -1
- package/dist/internal/devtools/components/DesignTab.js +3 -2
- package/dist/internal/devtools/components/LayoutReset.d.ts.map +1 -1
- package/dist/internal/devtools/components/LayoutReset.js +2 -0
- package/dist/internal/devtools/components/StoresTab.d.ts.map +1 -1
- package/dist/internal/devtools/components/StoresTab.js +3 -0
- package/dist/internal/devtools/utils/envVarDiscovery.d.ts +1 -0
- package/dist/internal/devtools/utils/envVarDiscovery.d.ts.map +1 -1
- package/dist/internal/devtools/utils/envVarDiscovery.js +5 -0
- package/dist/internal/devtools/utils/virtualModuleInspector.d.ts.map +1 -1
- package/dist/internal/devtools/utils/virtualModuleInspector.js +27 -21
- package/dist/internal/initializers/BaseStoresInitializer.d.ts.map +1 -1
- package/dist/internal/initializers/BaseStoresInitializer.js +30 -6
- package/dist/internal/layout/components/AutoMetaTags.d.ts.map +1 -1
- package/dist/internal/layout/components/AutoMetaTags.js +10 -8
- package/dist/internal/layout/components/FontPreloadLinks.d.ts +16 -0
- package/dist/internal/layout/components/FontPreloadLinks.d.ts.map +1 -0
- package/dist/internal/layout/components/FontPreloadLinks.js +32 -0
- package/dist/internal/layout/components/PerformanceHints.d.ts +7 -12
- package/dist/internal/layout/components/PerformanceHints.d.ts.map +1 -1
- package/dist/internal/layout/components/PerformanceHints.js +8 -12
- package/dist/internal/layout/components/footer/useLegalLinks.d.ts +6 -5
- package/dist/internal/layout/components/footer/useLegalLinks.d.ts.map +1 -1
- package/dist/internal/layout/components/footer/useLegalLinks.js +6 -2
- package/dist/internal/layout/zones/DnDevFooter.d.ts +6 -0
- package/dist/internal/layout/zones/DnDevFooter.d.ts.map +1 -1
- package/dist/internal/layout/zones/DnDevFooter.js +10 -4
- package/dist/internal/layout/zones/DnDevHeader.d.ts +7 -0
- package/dist/internal/layout/zones/DnDevHeader.d.ts.map +1 -1
- package/dist/internal/layout/zones/DnDevHeader.js +7 -0
- package/dist/internal/layout/zones/DnDevMergedBar.d.ts +7 -0
- package/dist/internal/layout/zones/DnDevMergedBar.d.ts.map +1 -1
- package/dist/internal/layout/zones/DnDevMergedBar.js +9 -0
- package/dist/internal/layout/zones/DnDevSidebar.d.ts +4 -0
- package/dist/internal/layout/zones/DnDevSidebar.d.ts.map +1 -1
- package/dist/internal/layout/zones/DnDevSidebar.js +13 -1
- package/dist/internal/providers/NavigationProvider.d.ts.map +1 -1
- package/dist/internal/providers/NavigationProvider.js +3 -5
- package/dist/next.d.ts +1 -0
- package/dist/next.d.ts.map +1 -1
- package/dist/next.js +1 -0
- package/dist/providers/ViteAppProviders.d.ts.map +1 -1
- package/dist/providers/ViteAppProviders.js +3 -5
- package/dist/routing/AuthGuard.d.ts +1 -1
- package/dist/routing/AuthGuard.d.ts.map +1 -1
- package/dist/routing/AuthGuard.js +3 -1
- package/dist/routing/GoTo.d.ts.map +1 -1
- package/dist/routing/GoTo.js +3 -1
- package/dist/routing/GoToDialog.d.ts.map +1 -1
- package/dist/routing/GoToDialog.js +2 -7
- package/dist/routing/GoToInput.d.ts +0 -3
- package/dist/routing/GoToInput.d.ts.map +1 -1
- package/dist/routing/GoToInput.js +8 -7
- package/dist/routing/Link.js +1 -1
- package/dist/routing/NavigationItem.d.ts +29 -7
- package/dist/routing/NavigationItem.d.ts.map +1 -1
- package/dist/routing/NavigationItem.js +22 -6
- package/dist/routing/hooks/hooks.next.js +1 -1
- package/dist/routing/hooks/hooks.vite.js +1 -1
- package/dist/routing/hooks/useNavigate.next.d.ts +1 -1
- package/dist/routing/hooks/useNavigate.next.d.ts.map +1 -1
- package/dist/routing/hooks/useNavigate.next.js +1 -7
- package/dist/routing/hooks/useNavigate.vite.d.ts +1 -1
- package/dist/routing/hooks/useNavigate.vite.d.ts.map +1 -1
- package/dist/routing/hooks/useNavigate.vite.js +1 -7
- package/dist/routing/hooks/useRedirectGuard.next.d.ts.map +1 -1
- package/dist/routing/hooks/useRedirectGuard.next.js +9 -8
- package/dist/routing/hooks/useRedirectGuard.vite.d.ts.map +1 -1
- package/dist/routing/hooks/useRedirectGuard.vite.js +9 -8
- package/dist/routing/hooks/useSearchParams.next.d.ts +18 -1
- package/dist/routing/hooks/useSearchParams.next.d.ts.map +1 -1
- package/dist/routing/hooks/useSearchParams.next.js +16 -0
- package/dist/routing/hooks/useSearchParams.vite.d.ts +16 -0
- package/dist/routing/hooks/useSearchParams.vite.d.ts.map +1 -1
- package/dist/routing/hooks/useSearchParams.vite.js +17 -1
- package/dist/routing/index.d.ts.map +1 -1
- package/dist/routing/index.js +2 -0
- package/dist/routing/useNavigation.d.ts +30 -0
- package/dist/routing/useNavigation.d.ts.map +1 -1
- package/dist/routing/useNavigation.js +40 -3
- package/dist/routing/useRouteDiscovery.d.ts +6 -17
- package/dist/routing/useRouteDiscovery.d.ts.map +1 -1
- package/dist/routing/useRouteDiscovery.js +16 -9
- package/dist/styles/index.css +284 -88
- 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/sanitizeSvg.d.ts +13 -0
- package/dist/utils/sanitizeSvg.d.ts.map +1 -0
- package/dist/utils/sanitizeSvg.js +47 -0
- package/dist/utils/useBillingVisibility.d.ts.map +1 -1
- package/dist/utils/useBillingVisibility.js +0 -7
- package/dist/utils/useCrudSafe.d.ts +0 -2
- package/dist/utils/useCrudSafe.d.ts.map +1 -1
- package/dist/utils/useFormStoreSafe.d.ts +5 -16
- package/dist/utils/useFormStoreSafe.d.ts.map +1 -1
- package/dist/utils/useFormStoreSafe.js +6 -37
- package/dist/vite-routing/AppRoutes.d.ts +19 -8
- package/dist/vite-routing/AppRoutes.d.ts.map +1 -1
- package/dist/vite-routing/AppRoutes.js +0 -3
- package/dist/vite-routing/RootLayout.d.ts.map +1 -1
- package/dist/vite-routing/RootLayout.js +10 -15
- package/package.json +16 -12
- package/assets/fonts/fonts.css +0 -206
- package/dist/routing/Navigate.d.ts +0 -10
- package/dist/routing/Navigate.d.ts.map +0 -1
- package/dist/routing/Navigate.js +0 -10
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"RouteErrorFallback.d.ts","sourceRoot":"","sources":["../../../src/internal/common/RouteErrorFallback.tsx"],"names":[],"mappings":"AAqCA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,OAAO,CAAC;AAE3C,UAAU,uBAAuB;IAC/B,KAAK,EAAE,OAAO,CAAC;IACf,UAAU,EAAE,MAAM,IAAI,CAAC;IACvB,cAAc,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC/B,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CACzB;AAED;;;;;;;;;GASG;AACH,eAAO,MAAM,kBAAkB,EAAE,aAAa,CAAC,uBAAuB,
|
|
1
|
+
{"version":3,"file":"RouteErrorFallback.d.ts","sourceRoot":"","sources":["../../../src/internal/common/RouteErrorFallback.tsx"],"names":[],"mappings":"AAqCA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,OAAO,CAAC;AAE3C,UAAU,uBAAuB;IAC/B,KAAK,EAAE,OAAO,CAAC;IACf,UAAU,EAAE,MAAM,IAAI,CAAC;IACvB,cAAc,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC/B,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CACzB;AAED;;;;;;;;;GASG;AACH,eAAO,MAAM,kBAAkB,EAAE,aAAa,CAAC,uBAAuB,CAoPrE,CAAC;AAEF,eAAe,kBAAkB,CAAC"}
|
|
@@ -62,7 +62,7 @@ export const AuthDebugButton = () => {
|
|
|
62
62
|
zIndex: 'calc(var(--z-toast) + 100)',
|
|
63
63
|
marginBottom: 'var(--gap-sm)',
|
|
64
64
|
padding: 'var(--gap-md)',
|
|
65
|
-
|
|
65
|
+
insetInlineEnd: 0,
|
|
66
66
|
backgroundColor: 'rgba(0, 0, 0, 0.9)',
|
|
67
67
|
color: 'white',
|
|
68
68
|
borderRadius: 'var(--radius-lg)',
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"DesignTab.d.ts","sourceRoot":"","sources":["../../../../src/internal/devtools/components/DesignTab.tsx"],"names":[],"mappings":"AA+CA,eAAO,MAAM,SAAS,+
|
|
1
|
+
{"version":3,"file":"DesignTab.d.ts","sourceRoot":"","sources":["../../../../src/internal/devtools/components/DesignTab.tsx"],"names":[],"mappings":"AA+CA,eAAO,MAAM,SAAS,+CA4yBrB,CAAC"}
|
|
@@ -416,10 +416,11 @@ export const DesignTab = () => {
|
|
|
416
416
|
return normalizeFontSize(style.fontSize) === normalizedSize;
|
|
417
417
|
});
|
|
418
418
|
found.forEach((el) => {
|
|
419
|
-
|
|
419
|
+
// Log text content only (not the DOM node) to avoid memory leaks from retained element refs
|
|
420
|
+
console.log('[DesignTab]', el.textContent?.trim().substring(0, 50));
|
|
420
421
|
el.style.outline = '2px solid red';
|
|
421
422
|
});
|
|
422
|
-
console.log(`Found ${found.length} elements with ${f.size}`);
|
|
423
|
+
console.log(`[DesignTab] Found ${found.length} elements with ${f.size}`);
|
|
423
424
|
};
|
|
424
425
|
return (_jsxs(Stack, { direction: "row", justify: "between", align: "center", gap: "tight", style: {
|
|
425
426
|
padding: 'var(--gap-sm)',
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"LayoutReset.d.ts","sourceRoot":"","sources":["../../../../src/internal/devtools/components/LayoutReset.tsx"],"names":[],"mappings":"AAkBA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,OAAO,CAAC;AAE3C,eAAO,MAAM,WAAW,EAAE,
|
|
1
|
+
{"version":3,"file":"LayoutReset.d.ts","sourceRoot":"","sources":["../../../../src/internal/devtools/components/LayoutReset.tsx"],"names":[],"mappings":"AAkBA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,OAAO,CAAC;AAE3C,eAAO,MAAM,WAAW,EAAE,aAqOxB,CAAC"}
|
|
@@ -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,+CAsHrB,CAAC"}
|
|
@@ -53,6 +53,9 @@ export const StoresTab = () => {
|
|
|
53
53
|
setStoreStates(states);
|
|
54
54
|
}, []);
|
|
55
55
|
useEffect(() => {
|
|
56
|
+
// StoresTab is only rendered inside DevTools (dev-only), but guard defensively
|
|
57
|
+
if (process.env.NODE_ENV !== 'development')
|
|
58
|
+
return;
|
|
56
59
|
refreshStores();
|
|
57
60
|
const interval = setInterval(refreshStores, 1000);
|
|
58
61
|
return () => clearInterval(interval);
|
|
@@ -15,6 +15,7 @@ export declare function discoverEnvVarsByPattern(env: Record<string, string>, pa
|
|
|
15
15
|
export declare function groupEnvVarsByCategory(env: Record<string, string>): {
|
|
16
16
|
stripe?: Record<string, string>;
|
|
17
17
|
firebase?: Record<string, string>;
|
|
18
|
+
supabase?: Record<string, string>;
|
|
18
19
|
oauth?: Record<string, string>;
|
|
19
20
|
emulator?: Record<string, string>;
|
|
20
21
|
other?: Record<string, string>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"envVarDiscovery.d.ts","sourceRoot":"","sources":["../../../../src/internal/devtools/utils/envVarDiscovery.ts"],"names":[],"mappings":"AA8BA;;;;;;GAMG;AACH,wBAAgB,wBAAwB,CACtC,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,EAC3B,QAAQ,EAAE,MAAM,EAAE,GACjB,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAWxB;AAED;;;;;GAKG;AACH,wBAAgB,sBAAsB,CAAC,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG;IACnE,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAChC,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAClC,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC/B,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAClC,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAChC,
|
|
1
|
+
{"version":3,"file":"envVarDiscovery.d.ts","sourceRoot":"","sources":["../../../../src/internal/devtools/utils/envVarDiscovery.ts"],"names":[],"mappings":"AA8BA;;;;;;GAMG;AACH,wBAAgB,wBAAwB,CACtC,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,EAC3B,QAAQ,EAAE,MAAM,EAAE,GACjB,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAWxB;AAED;;;;;GAKG;AACH,wBAAgB,sBAAsB,CAAC,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG;IACnE,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAChC,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAClC,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAClC,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC/B,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAClC,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAChC,CA+CA;AAED;;;;;;GAMG;AACH,wBAAgB,wBAAwB,CACtC,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,EAC3B,QAAQ,EAAE,MAAM,EAAE,GACjB,MAAM,GAAG,SAAS,CAOpB"}
|
|
@@ -62,6 +62,11 @@ export function groupEnvVarsByCategory(env) {
|
|
|
62
62
|
result.firebase = {};
|
|
63
63
|
result.firebase[key] = value;
|
|
64
64
|
}
|
|
65
|
+
else if (matchesPattern(key, '*SUPABASE*')) {
|
|
66
|
+
if (!result.supabase)
|
|
67
|
+
result.supabase = {};
|
|
68
|
+
result.supabase[key] = value;
|
|
69
|
+
}
|
|
65
70
|
else if (matchesPattern(key, '*OAUTH*') ||
|
|
66
71
|
matchesPattern(key, '*GOOGLE*CLIENT*') ||
|
|
67
72
|
matchesPattern(key, '*GITHUB*CLIENT*') ||
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"virtualModuleInspector.d.ts","sourceRoot":"","sources":["../../../../src/internal/devtools/utils/virtualModuleInspector.ts"],"names":[],"mappings":"AAoBA,OAAO,KAAK,EACV,mBAAmB,EACnB,iBAAiB,EACjB,UAAU,EACV,OAAO,EAER,MAAM,UAAU,CAAC;AAElB,qBAAa,sBAAsB;WACpB,eAAe,IAAI,OAAO,CAAC,mBAAmB,CAAC;
|
|
1
|
+
{"version":3,"file":"virtualModuleInspector.d.ts","sourceRoot":"","sources":["../../../../src/internal/devtools/utils/virtualModuleInspector.ts"],"names":[],"mappings":"AAoBA,OAAO,KAAK,EACV,mBAAmB,EACnB,iBAAiB,EACjB,UAAU,EACV,OAAO,EAER,MAAM,UAAU,CAAC;AAElB,qBAAa,sBAAsB;WACpB,eAAe,IAAI,OAAO,CAAC,mBAAmB,CAAC;WA4E/C,cAAc,IAAI,OAAO,CAAC,mBAAmB,CAAC;IA2D3D,MAAM,CAAC,sBAAsB,IAAI,UAAU;IAoB3C,MAAM,CAAC,kBAAkB,IAAI,OAAO;WAgGvB,kBAAkB,IAAI,OAAO,CAAC,iBAAiB,CAAC;CAgF9D"}
|
|
@@ -36,12 +36,14 @@ export class VirtualModuleInspector {
|
|
|
36
36
|
}
|
|
37
37
|
}
|
|
38
38
|
const tokenCount = Object.keys(designTokens).length;
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
39
|
+
if (process.env.NODE_ENV === 'development') {
|
|
40
|
+
console.log('[VirtualModuleInspector] Design Tokens:', {
|
|
41
|
+
platform,
|
|
42
|
+
tokenCount,
|
|
43
|
+
sampleTokens: Object.keys(designTokens).slice(0, 5),
|
|
44
|
+
source,
|
|
45
|
+
});
|
|
46
|
+
}
|
|
45
47
|
return {
|
|
46
48
|
success: true,
|
|
47
49
|
data: {
|
|
@@ -58,16 +60,18 @@ export class VirtualModuleInspector {
|
|
|
58
60
|
}
|
|
59
61
|
catch (error) {
|
|
60
62
|
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
63
|
+
if (process.env.NODE_ENV === 'development') {
|
|
64
|
+
console.group('[VirtualModuleInspector] Design Tokens Failed');
|
|
65
|
+
console.error('Error:', errorMessage);
|
|
66
|
+
console.log('Platform:', detectPlatform());
|
|
67
|
+
console.log('Environment:', {
|
|
68
|
+
isClient: typeof window !== 'undefined',
|
|
69
|
+
hasConfig: !!getDndevConfig(),
|
|
70
|
+
hasThemes: !!getDndevConfig()?.themes,
|
|
71
|
+
hasVariables: !!getDndevConfig()?.themes?.variables,
|
|
72
|
+
});
|
|
73
|
+
console.groupEnd();
|
|
74
|
+
}
|
|
71
75
|
return {
|
|
72
76
|
success: false,
|
|
73
77
|
data: null,
|
|
@@ -100,11 +104,13 @@ export class VirtualModuleInspector {
|
|
|
100
104
|
console.warn('Failed to fetch i18n from API route:', error);
|
|
101
105
|
}
|
|
102
106
|
}
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
107
|
+
if (process.env.NODE_ENV === 'development') {
|
|
108
|
+
console.log('🌐 i18n Mapping:', {
|
|
109
|
+
platform,
|
|
110
|
+
namespaces: Object.keys(i18nMapping),
|
|
111
|
+
source,
|
|
112
|
+
});
|
|
113
|
+
}
|
|
108
114
|
return {
|
|
109
115
|
success: true,
|
|
110
116
|
data: {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"BaseStoresInitializer.d.ts","sourceRoot":"","sources":["../../../src/internal/initializers/BaseStoresInitializer.tsx"],"names":[],"mappings":"AAiCA,OAAO,KAAK,EAAa,iBAAiB,EAAE,MAAM,gBAAgB,CAAC;AAEnE,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AA4DvC;;;;;;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":"AAiCA,OAAO,KAAK,EAAa,iBAAiB,EAAE,MAAM,gBAAgB,CAAC;AAEnE,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AA4DvC;;;;;;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,kDA+K5B"}
|
|
@@ -9,7 +9,7 @@ import { Fragment as _Fragment, jsx as _jsx } from "react/jsx-runtime";
|
|
|
9
9
|
* @since 0.0.1
|
|
10
10
|
* @author AMBROISE PARK Consulting
|
|
11
11
|
*/
|
|
12
|
-
import { useEffect, useLayoutEffect, useRef } from 'react';
|
|
12
|
+
import { useEffect, useLayoutEffect, useRef, useState } from 'react';
|
|
13
13
|
import { useThemeStore, useNavigationStore, useOverlayStore, useNetworkStore, useAbortControllerStore, useConsentStore, useConsentReady, useThemeReady, getPlatformEnvVar, } from '@donotdev/core';
|
|
14
14
|
import { useI18nReady } from '@donotdev/core';
|
|
15
15
|
import { handleError, isClient, getDndevConfig, globalEmitter, } from '@donotdev/core';
|
|
@@ -224,12 +224,36 @@ export function BaseStoresInitializer({ children, handlers, customStores = [], s
|
|
|
224
224
|
const themeReady = useThemeReady();
|
|
225
225
|
const i18nReady = useI18nReady();
|
|
226
226
|
const criticalCustomStores = customStores.filter((config) => config.type === 'critical');
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
227
|
+
// Track custom store readiness via subscriptions — never call hooks inside .map()
|
|
228
|
+
const [allCustomReady, setAllCustomReady] = useState(() => {
|
|
229
|
+
if (criticalCustomStores.length === 0)
|
|
230
|
+
return true;
|
|
231
|
+
return criticalCustomStores.every((config) => {
|
|
232
|
+
const state = config.store.getState();
|
|
233
|
+
return 'isReady' in state && state.isReady === true;
|
|
234
|
+
});
|
|
230
235
|
});
|
|
231
|
-
|
|
232
|
-
|
|
236
|
+
useEffect(() => {
|
|
237
|
+
if (criticalCustomStores.length === 0) {
|
|
238
|
+
setAllCustomReady(true);
|
|
239
|
+
return;
|
|
240
|
+
}
|
|
241
|
+
const checkAll = () => criticalCustomStores.every((config) => {
|
|
242
|
+
const state = config.store.getState();
|
|
243
|
+
return 'isReady' in state && state.isReady === true;
|
|
244
|
+
});
|
|
245
|
+
// Subscribe to each critical custom store for readiness updates
|
|
246
|
+
const unsubscribers = criticalCustomStores.map((config) => config.store.subscribe(() => {
|
|
247
|
+
setAllCustomReady(checkAll());
|
|
248
|
+
}));
|
|
249
|
+
// Initial check in case stores became ready before subscriptions were set up
|
|
250
|
+
setAllCustomReady(checkAll());
|
|
251
|
+
return () => {
|
|
252
|
+
unsubscribers.forEach((unsub) => unsub());
|
|
253
|
+
};
|
|
254
|
+
// criticalCustomStores reference changes only when customStores prop changes
|
|
255
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
256
|
+
}, [customStores]);
|
|
233
257
|
const criticalReady = consentReady && themeReady && i18nReady && allCustomReady;
|
|
234
258
|
// Two-phase loader: wait for BOTH framework AND route to be ready
|
|
235
259
|
useLayoutEffect(() => {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AutoMetaTags.d.ts","sourceRoot":"","sources":["../../../../src/internal/layout/components/AutoMetaTags.tsx"],"names":[],"mappings":"AA0DA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,OAAO,CAAC;AAyE3C;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,YAAY,EAAE,
|
|
1
|
+
{"version":3,"file":"AutoMetaTags.d.ts","sourceRoot":"","sources":["../../../../src/internal/layout/components/AutoMetaTags.tsx"],"names":[],"mappings":"AA0DA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,OAAO,CAAC;AAyE3C;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,YAAY,EAAE,aAmN1B,CAAC;AAEF;;;GAGG;AAEH,eAAe,YAAY,CAAC"}
|
|
@@ -122,16 +122,15 @@ export const AutoMetaTags = () => {
|
|
|
122
122
|
const location = useLocation();
|
|
123
123
|
const seoConfig = useSeoConfig();
|
|
124
124
|
const isClient = useIsClient();
|
|
125
|
-
// Return null if SEO is disabled
|
|
126
|
-
if (!seoConfig)
|
|
127
|
-
return null;
|
|
128
|
-
const { defaultNamespace = 'home', defaultImage, twitterHandle, staticTags = {}, } = seoConfig;
|
|
129
125
|
const siteName = useAppConfig('name');
|
|
130
126
|
const baseUrl = getPlatformEnvVar('APP_URL') || '';
|
|
131
|
-
// Get route metadata
|
|
127
|
+
// Get route metadata — computed from current pathname and client flag
|
|
132
128
|
const routeMeta = getRouteMetadata(location.pathname, isClient);
|
|
133
|
-
// Memoize computed values for performance
|
|
129
|
+
// Memoize computed values for performance — must be called before any early return
|
|
134
130
|
const metaData = useMemo(() => {
|
|
131
|
+
if (!seoConfig)
|
|
132
|
+
return null;
|
|
133
|
+
const { defaultNamespace = 'home', defaultImage, } = seoConfig;
|
|
135
134
|
// Construct absolute URL for canonical link
|
|
136
135
|
const currentUrl = `${baseUrl}${location.pathname}`;
|
|
137
136
|
const ns = routeMeta.ns || defaultNamespace;
|
|
@@ -175,10 +174,13 @@ export const AutoMetaTags = () => {
|
|
|
175
174
|
routeMeta,
|
|
176
175
|
siteName,
|
|
177
176
|
baseUrl,
|
|
178
|
-
|
|
179
|
-
defaultImage,
|
|
177
|
+
seoConfig,
|
|
180
178
|
t,
|
|
181
179
|
]);
|
|
180
|
+
// Return null if SEO is disabled — after all hooks have been called
|
|
181
|
+
if (!seoConfig || !metaData)
|
|
182
|
+
return null;
|
|
183
|
+
const { twitterHandle, staticTags = {} } = seoConfig;
|
|
182
184
|
return (_jsxs(Helmet, { children: [_jsx("title", { children: metaData.title }), metaData.description && (_jsx("meta", { name: "description", content: metaData.description })), _jsx("link", { rel: "canonical", href: metaData.url }), metaData.keywords && (_jsx("meta", { name: "keywords", content: Array.isArray(metaData.keywords)
|
|
183
185
|
? metaData.keywords.join(', ')
|
|
184
186
|
: metaData.keywords })), metaData.author && _jsx("meta", { name: "author", content: metaData.author }), metaData.noindex && _jsx("meta", { name: "robots", content: "noindex, nofollow" }), _jsx("meta", { property: "og:title", content: metaData.title }), metaData.description && (_jsx("meta", { property: "og:description", content: metaData.description })), _jsx("meta", { property: "og:url", content: metaData.url }), _jsx("meta", { property: "og:type", content: metaData.type }), metaData.image && _jsx("meta", { property: "og:image", content: metaData.image }), _jsx("meta", { property: "og:site_name", content: siteName }), metaData.type === 'article' && (_jsxs(_Fragment, { children: [metaData.author && (_jsx("meta", { property: "article:author", content: metaData.author })), metaData.publishDate && (_jsx("meta", { property: "article:published_time", content: metaData.publishDate })), metaData.modifiedDate && (_jsx("meta", { property: "article:modified_time", content: metaData.modifiedDate }))] })), _jsx("meta", { name: "twitter:card", content: "summary_large_image" }), _jsx("meta", { name: "twitter:title", content: metaData.title }), metaData.description && (_jsx("meta", { name: "twitter:description", content: metaData.description })), metaData.image && _jsx("meta", { name: "twitter:image", content: metaData.image }), twitterHandle && (_jsx("meta", { name: "twitter:site", content: `@${twitterHandle}` })), metaData.author && (_jsx("meta", { name: "twitter:creator", content: metaData.author })), _jsx("meta", { name: "format-detection", content: "telephone=no" }), _jsx("meta", { name: "mobile-web-app-capable", content: "yes" }), _jsx("meta", { name: "apple-mobile-web-app-status-bar-style", content: "default" }), Object.entries(staticTags).map(([name, content]) => (_jsx("meta", { name: name, content: content }, name))), metaData.image && metaData.image.startsWith('http') && (_jsx("link", { rel: "dns-prefetch", href: new URL(metaData.image).origin })), _jsx("script", { type: "application/ld+json", children: JSON.stringify({
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview FontPreloadLinks - Server-only component for Next.js
|
|
3
|
+
* @description Reads public/dndev-font-preloads.json (written at build by FontPreloadWebpackPlugin) and renders preload link tags for Lighthouse-friendly LCP. Include in root layout so initial HTML contains the links.
|
|
4
|
+
*
|
|
5
|
+
* @version 0.0.1
|
|
6
|
+
* @since 0.0.1
|
|
7
|
+
* @author AMBROISE PARK Consulting
|
|
8
|
+
*/
|
|
9
|
+
import type { ReactNode } from 'react';
|
|
10
|
+
/**
|
|
11
|
+
* Server component: renders preload links for fonts listed in public/dndev-font-preloads.json.
|
|
12
|
+
* No-op if manifest is missing or empty. Use in root layout.tsx for SSR preload in initial HTML.
|
|
13
|
+
*/
|
|
14
|
+
export declare function FontPreloadLinks(): Promise<ReactNode>;
|
|
15
|
+
export default FontPreloadLinks;
|
|
16
|
+
//# sourceMappingURL=FontPreloadLinks.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"FontPreloadLinks.d.ts","sourceRoot":"","sources":["../../../../src/internal/layout/components/FontPreloadLinks.tsx"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAKH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AASvC;;;GAGG;AACH,wBAAsB,gBAAgB,IAAI,OAAO,CAAC,SAAS,CAAC,CA6B3D;AAED,eAAe,gBAAgB,CAAC"}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { jsx as _jsx, Fragment as _Fragment } from "react/jsx-runtime";
|
|
2
|
+
/**
|
|
3
|
+
* @fileoverview FontPreloadLinks - Server-only component for Next.js
|
|
4
|
+
* @description Reads public/dndev-font-preloads.json (written at build by FontPreloadWebpackPlugin) and renders preload link tags for Lighthouse-friendly LCP. Include in root layout so initial HTML contains the links.
|
|
5
|
+
*
|
|
6
|
+
* @version 0.0.1
|
|
7
|
+
* @since 0.0.1
|
|
8
|
+
* @author AMBROISE PARK Consulting
|
|
9
|
+
*/
|
|
10
|
+
import fs from 'node:fs/promises';
|
|
11
|
+
import path from 'node:path';
|
|
12
|
+
const MANIFEST_FILENAME = 'dndev-font-preloads.json';
|
|
13
|
+
/**
|
|
14
|
+
* Server component: renders preload links for fonts listed in public/dndev-font-preloads.json.
|
|
15
|
+
* No-op if manifest is missing or empty. Use in root layout.tsx for SSR preload in initial HTML.
|
|
16
|
+
*/
|
|
17
|
+
export async function FontPreloadLinks() {
|
|
18
|
+
const manifestPath = path.join(process.cwd(), 'public', MANIFEST_FILENAME);
|
|
19
|
+
let entries = [];
|
|
20
|
+
try {
|
|
21
|
+
const content = await fs.readFile(manifestPath, 'utf8');
|
|
22
|
+
const parsed = JSON.parse(content);
|
|
23
|
+
entries = Array.isArray(parsed) ? parsed : [];
|
|
24
|
+
}
|
|
25
|
+
catch {
|
|
26
|
+
return null;
|
|
27
|
+
}
|
|
28
|
+
if (entries.length === 0)
|
|
29
|
+
return null;
|
|
30
|
+
return (_jsx(_Fragment, { children: entries.map((e) => (_jsx("link", { rel: "preload", as: "font", href: e.href, type: e.type ?? 'font/woff2', crossOrigin: "anonymous" }, e.href))) }));
|
|
31
|
+
}
|
|
32
|
+
export default FontPreloadLinks;
|
|
@@ -19,9 +19,9 @@ interface PerformanceHintsProps {
|
|
|
19
19
|
*/
|
|
20
20
|
dnsPrefetch?: string[];
|
|
21
21
|
/**
|
|
22
|
-
*
|
|
23
|
-
*
|
|
24
|
-
* @default [
|
|
22
|
+
* Additional fonts to preload (optional). Framework injects preloads at build time for Vite/Next;
|
|
23
|
+
* use this prop only for extra or custom font URLs.
|
|
24
|
+
* @default []
|
|
25
25
|
*/
|
|
26
26
|
fontPreloads?: (string | FontPreload)[];
|
|
27
27
|
/**
|
|
@@ -43,18 +43,13 @@ interface PerformanceHintsProps {
|
|
|
43
43
|
*
|
|
44
44
|
* @example
|
|
45
45
|
* ```tsx
|
|
46
|
-
* //
|
|
46
|
+
* // Default: preconnect/dns-prefetch only; font preload handled by framework build (Vite/Next)
|
|
47
47
|
* <PerformanceHints />
|
|
48
48
|
*
|
|
49
|
-
* //
|
|
50
|
-
* <PerformanceHints fontPreloads={[
|
|
49
|
+
* // Add custom font preload URLs
|
|
50
|
+
* <PerformanceHints fontPreloads={[customFontUrl]} />
|
|
51
51
|
*
|
|
52
|
-
* //
|
|
53
|
-
* <PerformanceHints
|
|
54
|
-
* fontPreloads={[{ href: '/fonts/Custom.woff2', type: 'font/woff2' }]}
|
|
55
|
-
* />
|
|
56
|
-
*
|
|
57
|
-
* // Disable font preloads (e.g., when using next/font)
|
|
52
|
+
* // Disable font preloads
|
|
58
53
|
* <PerformanceHints disableFontPreloads />
|
|
59
54
|
* ```
|
|
60
55
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"PerformanceHints.d.ts","sourceRoot":"","sources":["../../../../src/internal/layout/components/PerformanceHints.tsx"],"names":[],"mappings":"AAkBA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,OAAO,CAAC;
|
|
1
|
+
{"version":3,"file":"PerformanceHints.d.ts","sourceRoot":"","sources":["../../../../src/internal/layout/components/PerformanceHints.tsx"],"names":[],"mappings":"AAkBA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,OAAO,CAAC;AAoC3C,UAAU,WAAW;IACnB,2DAA2D;IAC3D,IAAI,EAAE,MAAM,CAAC;IACb,2CAA2C;IAC3C,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,gDAAgD;IAChD,WAAW,CAAC,EAAE,WAAW,GAAG,iBAAiB,CAAC;CAC/C;AAED,UAAU,qBAAqB;IAC7B;;;OAGG;IACH,WAAW,CAAC,EAAE,MAAM,EAAE,CAAC;IACvB;;;OAGG;IACH,WAAW,CAAC,EAAE,MAAM,EAAE,CAAC;IACvB;;;;OAIG;IACH,YAAY,CAAC,EAAE,CAAC,MAAM,GAAG,WAAW,CAAC,EAAE,CAAC;IACxC;;;OAGG;IACH,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B;;;OAGG;IACH,mBAAmB,CAAC,EAAE,OAAO,CAAC;CAC/B;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,QAAA,MAAM,gBAAgB,EAAE,aAAa,CAAC,qBAAqB,CA6D1D,CAAC;AAEF,eAAe,gBAAgB,CAAC;AAChC,YAAY,EAAE,WAAW,EAAE,qBAAqB,EAAE,CAAC"}
|
|
@@ -39,9 +39,10 @@ const DEFAULT_DNS_PREFETCH = [
|
|
|
39
39
|
'https://www.googletagmanager.com',
|
|
40
40
|
];
|
|
41
41
|
/**
|
|
42
|
-
* Default critical fonts to preload
|
|
43
|
-
* Empty
|
|
44
|
-
*
|
|
42
|
+
* Default critical fonts to preload.
|
|
43
|
+
* Empty: when using the framework's Vite or Next setup, font preload is handled by build-time
|
|
44
|
+
* injection (Vite: FontPreloadPlugin patches index.html; Next: FontPreloadLinks in root layout
|
|
45
|
+
* reads public/dndev-font-preloads.json). Pass fontPreloads only for extra/custom URLs.
|
|
45
46
|
*/
|
|
46
47
|
const DEFAULT_FONT_PRELOADS = [];
|
|
47
48
|
/**
|
|
@@ -52,18 +53,13 @@ const DEFAULT_FONT_PRELOADS = [];
|
|
|
52
53
|
*
|
|
53
54
|
* @example
|
|
54
55
|
* ```tsx
|
|
55
|
-
* //
|
|
56
|
+
* // Default: preconnect/dns-prefetch only; font preload handled by framework build (Vite/Next)
|
|
56
57
|
* <PerformanceHints />
|
|
57
58
|
*
|
|
58
|
-
* //
|
|
59
|
-
* <PerformanceHints fontPreloads={[
|
|
59
|
+
* // Add custom font preload URLs
|
|
60
|
+
* <PerformanceHints fontPreloads={[customFontUrl]} />
|
|
60
61
|
*
|
|
61
|
-
* //
|
|
62
|
-
* <PerformanceHints
|
|
63
|
-
* fontPreloads={[{ href: '/fonts/Custom.woff2', type: 'font/woff2' }]}
|
|
64
|
-
* />
|
|
65
|
-
*
|
|
66
|
-
* // Disable font preloads (e.g., when using next/font)
|
|
62
|
+
* // Disable font preloads
|
|
67
63
|
* <PerformanceHints disableFontPreloads />
|
|
68
64
|
* ```
|
|
69
65
|
*/
|
|
@@ -4,11 +4,12 @@ export interface FooterLegalLink {
|
|
|
4
4
|
label: string;
|
|
5
5
|
}
|
|
6
6
|
/**
|
|
7
|
-
*
|
|
7
|
+
* Returns the configured legal links for the footer.
|
|
8
8
|
* Handles the logic: null = hide, undefined = defaults, array = custom
|
|
9
|
+
*
|
|
10
|
+
* @remarks Not a hook — no React state or effects. Named with `get` prefix.
|
|
9
11
|
*/
|
|
10
|
-
export declare const
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
}[];
|
|
12
|
+
export declare const getLegalLinks: (footerConfig: AppMetadata["footer"]) => FooterLegalLink[];
|
|
13
|
+
/** @deprecated Use getLegalLinks instead */
|
|
14
|
+
export declare const useLegalLinks: (footerConfig: AppMetadata["footer"]) => FooterLegalLink[];
|
|
14
15
|
//# sourceMappingURL=useLegalLinks.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useLegalLinks.d.ts","sourceRoot":"","sources":["../../../../../src/internal/layout/components/footer/useLegalLinks.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAElD,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;CACf;AAQD
|
|
1
|
+
{"version":3,"file":"useLegalLinks.d.ts","sourceRoot":"","sources":["../../../../../src/internal/layout/components/footer/useLegalLinks.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAElD,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;CACf;AAQD;;;;;GAKG;AACH,eAAO,MAAM,aAAa,GAAI,cAAc,WAAW,CAAC,QAAQ,CAAC,KAAG,eAAe,EAQlF,CAAC;AAEF,4CAA4C;AAC5C,eAAO,MAAM,aAAa,iBAXkB,WAAW,CAAC,QAAQ,CAAC,KAAG,eAAe,EAWzC,CAAC"}
|
|
@@ -5,10 +5,12 @@ const DEFAULT_LINKS = [
|
|
|
5
5
|
{ label: 'footer.legal.termsOfService', path: '/terms' },
|
|
6
6
|
];
|
|
7
7
|
/**
|
|
8
|
-
*
|
|
8
|
+
* Returns the configured legal links for the footer.
|
|
9
9
|
* Handles the logic: null = hide, undefined = defaults, array = custom
|
|
10
|
+
*
|
|
11
|
+
* @remarks Not a hook — no React state or effects. Named with `get` prefix.
|
|
10
12
|
*/
|
|
11
|
-
export const
|
|
13
|
+
export const getLegalLinks = (footerConfig) => {
|
|
12
14
|
// If explicitly null, return empty array (hidden)
|
|
13
15
|
if (footerConfig?.legalLinks === null) {
|
|
14
16
|
return [];
|
|
@@ -16,3 +18,5 @@ export const useLegalLinks = (footerConfig) => {
|
|
|
16
18
|
// Use configured links or defaults
|
|
17
19
|
return footerConfig?.legalLinks ?? DEFAULT_LINKS;
|
|
18
20
|
};
|
|
21
|
+
/** @deprecated Use getLegalLinks instead */
|
|
22
|
+
export const useLegalLinks = getLegalLinks;
|
|
@@ -17,6 +17,12 @@ export interface DnDevFooterProps {
|
|
|
17
17
|
* 4. app.footer.copyright === string -> custom copyright
|
|
18
18
|
* 5. LegalLinks from app.footer.legalLinks (defaults if undefined)
|
|
19
19
|
* 6. DoNotDev branding always appended
|
|
20
|
+
*
|
|
21
|
+
* @critical The `<footer>` MUST have `role="contentinfo"` and className `"footer"`.
|
|
22
|
+
* ALL footer CSS in layout-variables.css targets `footer[role='contentinfo']`.
|
|
23
|
+
* This controls: grid placement, height, border, footer-mode scroll behavior,
|
|
24
|
+
* preset-specific visibility (moolti/plain hide footer, blog hides on mobile).
|
|
25
|
+
* DO NOT change role, tag, or className.
|
|
20
26
|
*/
|
|
21
27
|
declare function DnDevFooterComponent({ app }: DnDevFooterProps): ReactNode;
|
|
22
28
|
export declare const DnDevFooter: import("react").MemoExoticComponent<typeof DnDevFooterComponent>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"DnDevFooter.d.ts","sourceRoot":"","sources":["../../../../src/internal/layout/zones/DnDevFooter.tsx"],"names":[],"mappings":"AAkBA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAUlD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAGvC,MAAM,WAAW,gBAAgB;IAC/B,uCAAuC;IACvC,GAAG,CAAC,EAAE,WAAW,CAAC;CACnB;AAED
|
|
1
|
+
{"version":3,"file":"DnDevFooter.d.ts","sourceRoot":"","sources":["../../../../src/internal/layout/zones/DnDevFooter.tsx"],"names":[],"mappings":"AAkBA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAUlD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAGvC,MAAM,WAAW,gBAAgB;IAC/B,uCAAuC;IACvC,GAAG,CAAC,EAAE,WAAW,CAAC;CACnB;AAED;;;;;;;;;;;;;;;;;;;GAmBG;AACH,iBAAS,oBAAoB,CAAC,EAAE,GAAQ,EAAE,EAAE,gBAAgB,GAAG,SAAS,CA8EvE;AAED,eAAO,MAAM,WAAW,kEAA6B,CAAC"}
|
|
@@ -17,7 +17,7 @@ import { Stack } from '@donotdev/components';
|
|
|
17
17
|
import { useBreakpoint, useTranslation, maybeTranslate } from '@donotdev/core';
|
|
18
18
|
import { Link } from '../../../routing/Link';
|
|
19
19
|
import { FooterBranding } from '../components/footer/FooterBranding';
|
|
20
|
-
import {
|
|
20
|
+
import { getLegalLinks, } from '../components/footer/useLegalLinks';
|
|
21
21
|
/**
|
|
22
22
|
* DnDevFooter - Simple footer: Copyright (left) | LegalLinks + DoNotDev (right)
|
|
23
23
|
*
|
|
@@ -31,16 +31,22 @@ import { useLegalLinks, } from '../components/footer/useLegalLinks';
|
|
|
31
31
|
* 4. app.footer.copyright === string -> custom copyright
|
|
32
32
|
* 5. LegalLinks from app.footer.legalLinks (defaults if undefined)
|
|
33
33
|
* 6. DoNotDev branding always appended
|
|
34
|
+
*
|
|
35
|
+
* @critical The `<footer>` MUST have `role="contentinfo"` and className `"footer"`.
|
|
36
|
+
* ALL footer CSS in layout-variables.css targets `footer[role='contentinfo']`.
|
|
37
|
+
* This controls: grid placement, height, border, footer-mode scroll behavior,
|
|
38
|
+
* preset-specific visibility (moolti/plain hide footer, blog hides on mobile).
|
|
39
|
+
* DO NOT change role, tag, or className.
|
|
34
40
|
*/
|
|
35
41
|
function DnDevFooterComponent({ app = {} }) {
|
|
36
42
|
const { t } = useTranslation('dndev');
|
|
37
43
|
const isLaptopOrDesktop = useBreakpoint('isLaptopOrDesktop');
|
|
44
|
+
// Get legal links (defaults or custom) — must be called before any return
|
|
45
|
+
const links = getLegalLinks(app?.footer);
|
|
38
46
|
// Explicit null hides footer
|
|
39
47
|
if (app?.footer === null) {
|
|
40
48
|
return null;
|
|
41
49
|
}
|
|
42
|
-
// Get legal links (defaults or custom)
|
|
43
|
-
const links = useLegalLinks(app.footer);
|
|
44
50
|
// Copyright: null = hide, undefined = default, string = custom
|
|
45
51
|
const copyrightConfig = app.footer?.copyright;
|
|
46
52
|
const showCopyright = copyrightConfig !== null;
|
|
@@ -49,7 +55,7 @@ function DnDevFooterComponent({ app = {} }) {
|
|
|
49
55
|
: copyrightConfig;
|
|
50
56
|
// Desktop/Wide: 2-zone layout [Copyright] | [Links + DoNotDev]
|
|
51
57
|
if (isLaptopOrDesktop) {
|
|
52
|
-
return (_jsx("footer", { role: "contentinfo", className: "footer", children: _jsxs(Stack, { direction: "row", align: "center", justify: "between", gap: "none", children: [showCopyright && (_jsx("div", {
|
|
58
|
+
return (_jsx("footer", { role: "contentinfo", className: "footer", children: _jsxs(Stack, { direction: "row", align: "center", justify: "between", gap: "none", children: [showCopyright && (_jsx("div", { style: { display: 'flex', justifyContent: 'flex-start' }, children: _jsx("span", { className: "footer-copyright", children: copyrightText }) })), _jsx("div", { style: { display: 'flex', justifyContent: 'flex-end' }, children: _jsxs(Stack, { direction: "row", align: "center", children: [links.map((link) => (_jsx(Link, { path: link.path, style: { fontSize: 'var(--font-size-xs)' }, children: maybeTranslate(t, link.label) }, link.path))), _jsx(FooterBranding, {})] }) })] }) }));
|
|
53
59
|
}
|
|
54
60
|
// Mobile/Tablet: stacked layout
|
|
55
61
|
return (_jsx("footer", { role: "contentinfo", className: "footer", children: _jsxs(Stack, { align: "center", gap: "tight", children: [showCopyright && (_jsx("span", { className: "footer-copyright", children: copyrightText })), _jsxs(Stack, { direction: "row", wrap: "wrap", gap: "tight", justify: "center", align: "center", children: [links.map((link) => (_jsx(Link, { path: link.path, style: { fontSize: 'var(--font-size-xs)' }, children: maybeTranslate(t, link.label) }, link.path))), _jsx(FooterBranding, {})] })] }) }));
|
|
@@ -12,6 +12,13 @@ export interface DnDevHeaderProps {
|
|
|
12
12
|
*
|
|
13
13
|
* Layout: start (start-aligned) | center (absolutely centered) | end (end-aligned)
|
|
14
14
|
* Center is absolutely positioned overlay, independent of start/end content.
|
|
15
|
+
*
|
|
16
|
+
* @critical The `<header>` MUST have `role="banner"` and className `"header"`.
|
|
17
|
+
* ALL header CSS in layout-variables.css targets `header[role='banner']`.
|
|
18
|
+
* The inner divs MUST use classNames `"header-start"`, `"header-center"`, `"header-end"`.
|
|
19
|
+
* Removing or renaming any of these silently breaks header layout, spacing, visibility,
|
|
20
|
+
* and preset-specific rules (e.g. landing compact mode, mergedBar hiding).
|
|
21
|
+
* DO NOT change role, tag, or classNames.
|
|
15
22
|
*/
|
|
16
23
|
declare function DnDevHeaderComponent({ start, center, end, }: DnDevHeaderProps): ReactNode;
|
|
17
24
|
export declare const DnDevHeader: import("react").MemoExoticComponent<typeof DnDevHeaderComponent>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"DnDevHeader.d.ts","sourceRoot":"","sources":["../../../../src/internal/layout/zones/DnDevHeader.tsx"],"names":[],"mappings":"AAoBA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAEvC,MAAM,WAAW,gBAAgB;IAC/B,8DAA8D;IAC9D,KAAK,CAAC,EAAE,SAAS,GAAG,IAAI,CAAC;IACzB,+DAA+D;IAC/D,MAAM,CAAC,EAAE,SAAS,GAAG,IAAI,CAAC;IAC1B,4DAA4D;IAC5D,GAAG,CAAC,EAAE,SAAS,GAAG,IAAI,CAAC;CACxB;AAED
|
|
1
|
+
{"version":3,"file":"DnDevHeader.d.ts","sourceRoot":"","sources":["../../../../src/internal/layout/zones/DnDevHeader.tsx"],"names":[],"mappings":"AAoBA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAEvC,MAAM,WAAW,gBAAgB;IAC/B,8DAA8D;IAC9D,KAAK,CAAC,EAAE,SAAS,GAAG,IAAI,CAAC;IACzB,+DAA+D;IAC/D,MAAM,CAAC,EAAE,SAAS,GAAG,IAAI,CAAC;IAC1B,4DAA4D;IAC5D,GAAG,CAAC,EAAE,SAAS,GAAG,IAAI,CAAC;CACxB;AAED;;;;;;;;;;;;GAYG;AACH,iBAAS,oBAAoB,CAAC,EAC5B,KAAK,EACL,MAAM,EACN,GAAG,GACJ,EAAE,gBAAgB,GAAG,SAAS,CAgB9B;AAED,eAAO,MAAM,WAAW,kEAA6B,CAAC"}
|
|
@@ -20,6 +20,13 @@ import { cn } from '@donotdev/components';
|
|
|
20
20
|
*
|
|
21
21
|
* Layout: start (start-aligned) | center (absolutely centered) | end (end-aligned)
|
|
22
22
|
* Center is absolutely positioned overlay, independent of start/end content.
|
|
23
|
+
*
|
|
24
|
+
* @critical The `<header>` MUST have `role="banner"` and className `"header"`.
|
|
25
|
+
* ALL header CSS in layout-variables.css targets `header[role='banner']`.
|
|
26
|
+
* The inner divs MUST use classNames `"header-start"`, `"header-center"`, `"header-end"`.
|
|
27
|
+
* Removing or renaming any of these silently breaks header layout, spacing, visibility,
|
|
28
|
+
* and preset-specific rules (e.g. landing compact mode, mergedBar hiding).
|
|
29
|
+
* DO NOT change role, tag, or classNames.
|
|
23
30
|
*/
|
|
24
31
|
function DnDevHeaderComponent({ start, center, end, }) {
|
|
25
32
|
// Check if center has content
|
|
@@ -20,6 +20,13 @@ export interface DnDevMergedBarProps {
|
|
|
20
20
|
* Slots are customizable per-preset with smart defaults:
|
|
21
21
|
* - trigger: What shows in the fixed bar (default: header.start or AppBranding)
|
|
22
22
|
* - top/content/bottom: Sheet content (default: derived from sidebar)
|
|
23
|
+
*
|
|
24
|
+
* @critical The outer `<div>` MUST have className `"merged-bar"` and `data-position`.
|
|
25
|
+
* ALL mergedBar CSS in layout-variables.css targets `.merged-bar` and `.merged-bar[data-position]`.
|
|
26
|
+
* This controls: position:fixed placement, display:none/flex toggling per preset + breakpoint,
|
|
27
|
+
* safe area padding, border, and z-index. Inner divs MUST keep `"merged-bar-trigger"`,
|
|
28
|
+
* `"merged-bar-sheet-content"`, `"merged-bar-sheet-scroll"` classNames.
|
|
29
|
+
* DO NOT change classNames or data attributes.
|
|
23
30
|
*/
|
|
24
31
|
declare function DnDevMergedBarComponent({ position, height, trigger, top, content, bottom, }: DnDevMergedBarProps): ReactNode;
|
|
25
32
|
export declare const DnDevMergedBar: import("react").MemoExoticComponent<typeof DnDevMergedBarComponent>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"DnDevMergedBar.d.ts","sourceRoot":"","sources":["../../../../src/internal/layout/zones/DnDevMergedBar.tsx"],"names":[],"mappings":"AA6BA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAEvC,MAAM,WAAW,mBAAmB;IAClC,mBAAmB;IACnB,QAAQ,EAAE,KAAK,GAAG,QAAQ,CAAC;IAC3B,mFAAmF;IACnF,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,gEAAgE;IAChE,OAAO,CAAC,EAAE,SAAS,GAAG,IAAI,CAAC;IAC3B,4DAA4D;IAC5D,GAAG,CAAC,EAAE,SAAS,GAAG,IAAI,CAAC;IACvB,gEAAgE;IAChE,OAAO,CAAC,EAAE,SAAS,GAAG,IAAI,CAAC;IAC3B,+DAA+D;IAC/D,MAAM,CAAC,EAAE,SAAS,GAAG,IAAI,CAAC;CAC3B;AAED
|
|
1
|
+
{"version":3,"file":"DnDevMergedBar.d.ts","sourceRoot":"","sources":["../../../../src/internal/layout/zones/DnDevMergedBar.tsx"],"names":[],"mappings":"AA6BA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAEvC,MAAM,WAAW,mBAAmB;IAClC,mBAAmB;IACnB,QAAQ,EAAE,KAAK,GAAG,QAAQ,CAAC;IAC3B,mFAAmF;IACnF,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,gEAAgE;IAChE,OAAO,CAAC,EAAE,SAAS,GAAG,IAAI,CAAC;IAC3B,4DAA4D;IAC5D,GAAG,CAAC,EAAE,SAAS,GAAG,IAAI,CAAC;IACvB,gEAAgE;IAChE,OAAO,CAAC,EAAE,SAAS,GAAG,IAAI,CAAC;IAC3B,+DAA+D;IAC/D,MAAM,CAAC,EAAE,SAAS,GAAG,IAAI,CAAC;CAC3B;AAED;;;;;;;;;;;;;;GAcG;AACH,iBAAS,uBAAuB,CAAC,EAC/B,QAAQ,EACR,MAAM,EACN,OAAO,EACP,GAAG,EACH,OAAO,EACP,MAAM,GACP,EAAE,mBAAmB,GAAG,SAAS,CAgEjC;AAED,eAAO,MAAM,cAAc,qEAAgC,CAAC"}
|
|
@@ -24,10 +24,19 @@ import { useLocation } from '@donotdev/ui/routing/hooks';
|
|
|
24
24
|
* Slots are customizable per-preset with smart defaults:
|
|
25
25
|
* - trigger: What shows in the fixed bar (default: header.start or AppBranding)
|
|
26
26
|
* - top/content/bottom: Sheet content (default: derived from sidebar)
|
|
27
|
+
*
|
|
28
|
+
* @critical The outer `<div>` MUST have className `"merged-bar"` and `data-position`.
|
|
29
|
+
* ALL mergedBar CSS in layout-variables.css targets `.merged-bar` and `.merged-bar[data-position]`.
|
|
30
|
+
* This controls: position:fixed placement, display:none/flex toggling per preset + breakpoint,
|
|
31
|
+
* safe area padding, border, and z-index. Inner divs MUST keep `"merged-bar-trigger"`,
|
|
32
|
+
* `"merged-bar-sheet-content"`, `"merged-bar-sheet-scroll"` classNames.
|
|
33
|
+
* DO NOT change classNames or data attributes.
|
|
27
34
|
*/
|
|
28
35
|
function DnDevMergedBarComponent({ position, height, trigger, top, content, bottom, }) {
|
|
29
36
|
const { t } = useTranslation('dndev');
|
|
30
37
|
const Icon = position === 'top' ? Menu : ChevronUp;
|
|
38
|
+
// Sheet component accepts 'left'|'right'|'top'|'bottom' (physical), not logical properties.
|
|
39
|
+
// For RTL apps, this would need Sheet to support 'start'/'end' sides — tracked separately.
|
|
31
40
|
const sheetSide = position === 'top' ? 'left' : position;
|
|
32
41
|
const [open, setOpen] = useState(false);
|
|
33
42
|
const location = useLocation();
|