@donotdev/ui 0.0.2 → 0.0.4

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.
Files changed (119) hide show
  1. package/dist/components/auth/AuthMenu.d.ts.map +1 -1
  2. package/dist/components/auth/AuthMenu.js +19 -32
  3. package/dist/components/common/FeatureCard.d.ts +7 -19
  4. package/dist/components/common/FeatureCard.d.ts.map +1 -1
  5. package/dist/components/common/FeatureCard.js +5 -29
  6. package/dist/components/common/TechBento.d.ts +15 -3
  7. package/dist/components/common/TechBento.d.ts.map +1 -1
  8. package/dist/components/common/TechBento.js +20 -2
  9. package/dist/components/cookie-consent/CookieConsent.d.ts.map +1 -1
  10. package/dist/components/cookie-consent/CookieConsent.js +2 -41
  11. package/dist/components/cookie-consent/index.d.ts +0 -1
  12. package/dist/components/cookie-consent/index.d.ts.map +1 -1
  13. package/dist/components/cookie-consent/index.js +1 -1
  14. package/dist/components/layout/components/DropdownNavigation.d.ts.map +1 -1
  15. package/dist/components/layout/components/header/ThemeToggle.d.ts +1 -1
  16. package/dist/components/layout/components/header/ThemeToggle.d.ts.map +1 -1
  17. package/dist/components/layout/components/header/ThemeToggle.js +5 -4
  18. package/dist/dndev.css +373 -249
  19. package/dist/index.js +4 -4
  20. package/dist/internal/devtools/DebugTools.d.ts.map +1 -1
  21. package/dist/internal/devtools/DebugTools.js +8 -4
  22. package/dist/internal/devtools/components/ConfigTab.d.ts.map +1 -1
  23. package/dist/internal/devtools/components/ConfigTab.js +33 -133
  24. package/dist/internal/devtools/components/DebugDialog.d.ts.map +1 -1
  25. package/dist/internal/devtools/components/DebugDialog.js +11 -520
  26. package/dist/internal/devtools/components/DesignTab.d.ts +2 -0
  27. package/dist/internal/devtools/components/DesignTab.d.ts.map +1 -0
  28. package/dist/internal/devtools/components/DesignTab.js +431 -0
  29. package/dist/internal/devtools/components/StoresTab.d.ts.map +1 -1
  30. package/dist/internal/devtools/components/StoresTab.js +54 -102
  31. package/dist/internal/devtools/components/index.d.ts +1 -6
  32. package/dist/internal/devtools/components/index.d.ts.map +1 -1
  33. package/dist/internal/devtools/components/index.js +1 -6
  34. package/dist/internal/devtools/utils/index.d.ts +0 -1
  35. package/dist/internal/devtools/utils/index.d.ts.map +1 -1
  36. package/dist/internal/devtools/utils/index.js +0 -1
  37. package/dist/internal/initializers/BaseStoresInitializer.d.ts.map +1 -1
  38. package/dist/internal/initializers/BaseStoresInitializer.js +36 -59
  39. package/dist/internal/layout/DnDevLayout.js +3 -3
  40. package/dist/internal/layout/components/AutoMetaTags.d.ts.map +1 -1
  41. package/dist/internal/layout/components/AutoMetaTags.js +6 -1
  42. package/dist/internal/layout/components/footer/FooterBranding.d.ts.map +1 -1
  43. package/dist/internal/layout/components/footer/FooterBranding.js +3 -1
  44. package/dist/internal/layout/zones/DnDevFooter.js +2 -2
  45. package/dist/routing/AuthGuard.d.ts +14 -10
  46. package/dist/routing/AuthGuard.d.ts.map +1 -1
  47. package/dist/routing/AuthGuard.js +25 -22
  48. package/dist/routing/Link.d.ts +2 -2
  49. package/dist/routing/Link.js +2 -2
  50. package/dist/routing/hooks/hooks.next.js +1 -1
  51. package/dist/routing/hooks/hooks.vite.js +1 -1
  52. package/dist/routing/hooks/useRedirectGuard.next.d.ts +2 -36
  53. package/dist/routing/hooks/useRedirectGuard.next.d.ts.map +1 -1
  54. package/dist/routing/hooks/useRedirectGuard.next.js +14 -55
  55. package/dist/routing/hooks/useRedirectGuard.vite.d.ts +2 -36
  56. package/dist/routing/hooks/useRedirectGuard.vite.d.ts.map +1 -1
  57. package/dist/routing/hooks/useRedirectGuard.vite.js +14 -55
  58. package/dist/routing/index.d.ts +0 -1
  59. package/dist/routing/index.d.ts.map +1 -1
  60. package/dist/routing/index.js +1 -1
  61. package/dist/styles/index.css +373 -249
  62. package/dist/utils/assetResolver.d.ts +5 -5
  63. package/dist/utils/assetResolver.d.ts.map +1 -1
  64. package/dist/utils/assetResolver.js +26 -15
  65. package/dist/utils/index.d.ts +1 -0
  66. package/dist/utils/index.d.ts.map +1 -1
  67. package/dist/utils/index.js +1 -0
  68. package/dist/utils/tList.d.ts +30 -0
  69. package/dist/utils/tList.d.ts.map +1 -0
  70. package/dist/utils/tList.js +51 -0
  71. package/dist/utils/useAuthSafe.d.ts +25 -12
  72. package/dist/utils/useAuthSafe.d.ts.map +1 -1
  73. package/dist/utils/useAuthSafe.js +3 -1
  74. package/dist/utils/useAuthVisibility.d.ts +3 -3
  75. package/dist/utils/useAuthVisibility.d.ts.map +1 -1
  76. package/dist/utils/useAuthVisibility.js +25 -21
  77. package/dist/utils/useBillingVisibility.d.ts +2 -2
  78. package/dist/utils/useBillingVisibility.d.ts.map +1 -1
  79. package/dist/utils/useBillingVisibility.js +12 -13
  80. package/dist/utils/useCrudSafe.d.ts +1 -1
  81. package/dist/utils/useCrudSafe.d.ts.map +1 -1
  82. package/dist/utils/useCrudSafe.js +26 -13
  83. package/dist/utils/useOAuthSafe.d.ts +25 -12
  84. package/dist/utils/useOAuthSafe.d.ts.map +1 -1
  85. package/dist/utils/useStripeBillingSafe.d.ts +30 -18
  86. package/dist/utils/useStripeBillingSafe.d.ts.map +1 -1
  87. package/dist/utils/useStripeBillingSafe.js +5 -6
  88. package/dist/vite-routing/AppRoutes.d.ts.map +1 -1
  89. package/dist/vite-routing/AppRoutes.js +5 -5
  90. package/dist/vite-routing/RootLayout.d.ts.map +1 -1
  91. package/dist/vite-routing/RootLayout.js +34 -7
  92. package/package.json +9 -9
  93. package/dist/internal/devtools/components/AuthTab.d.ts +0 -2
  94. package/dist/internal/devtools/components/AuthTab.d.ts.map +0 -1
  95. package/dist/internal/devtools/components/AuthTab.js +0 -98
  96. package/dist/internal/devtools/components/ColorRatioTab.d.ts +0 -2
  97. package/dist/internal/devtools/components/ColorRatioTab.d.ts.map +0 -1
  98. package/dist/internal/devtools/components/ColorRatioTab.js +0 -322
  99. package/dist/internal/devtools/components/DebugToggle.d.ts +0 -2
  100. package/dist/internal/devtools/components/DebugToggle.d.ts.map +0 -1
  101. package/dist/internal/devtools/components/DebugToggle.js +0 -57
  102. package/dist/internal/devtools/components/EnvironmentTab.d.ts +0 -2
  103. package/dist/internal/devtools/components/EnvironmentTab.d.ts.map +0 -1
  104. package/dist/internal/devtools/components/EnvironmentTab.js +0 -26
  105. package/dist/internal/devtools/components/I18nTab.d.ts +0 -2
  106. package/dist/internal/devtools/components/I18nTab.d.ts.map +0 -1
  107. package/dist/internal/devtools/components/I18nTab.js +0 -76
  108. package/dist/internal/devtools/components/OAuthGuideButton.d.ts +0 -10
  109. package/dist/internal/devtools/components/OAuthGuideButton.d.ts.map +0 -1
  110. package/dist/internal/devtools/components/OAuthGuideButton.js +0 -71
  111. package/dist/internal/devtools/components/StripeDebugTab.d.ts +0 -2
  112. package/dist/internal/devtools/components/StripeDebugTab.d.ts.map +0 -1
  113. package/dist/internal/devtools/components/StripeDebugTab.js +0 -175
  114. package/dist/internal/devtools/components/ThemesTab.d.ts +0 -2
  115. package/dist/internal/devtools/components/ThemesTab.d.ts.map +0 -1
  116. package/dist/internal/devtools/components/ThemesTab.js +0 -77
  117. package/dist/internal/devtools/utils/spacingAnalyzer.d.ts +0 -15
  118. package/dist/internal/devtools/utils/spacingAnalyzer.d.ts.map +0 -1
  119. package/dist/internal/devtools/utils/spacingAnalyzer.js +0 -88
@@ -3,18 +3,31 @@
3
3
  * @description Provides billing functionality when @donotdev/billing is installed,
4
4
  * gracefully degrades to no-op when not installed.
5
5
  *
6
- * **How it works:**
7
- * 1. Import @donotdev/billing (Vite aliases to empty module if not installed)
8
- * 2. Check if useStripeBilling export exists
9
- * 3. If exists use real hook | If not → use stub
10
- *
11
- * **Why this pattern:**
12
- * - Vite aliases missing packages to empty modules at build time
13
- * - Decision is made ONCE at import time, never changes
14
- * - No conditional hook calls = no Rules of Hooks violations
15
- * - Real hook handles all runtime state (auth, consent) internally
16
- *
17
- * @version 0.0.1
6
+ * ## CRITICAL: DO NOT USE DYNAMIC IMPORTS
7
+ *
8
+ * This file MUST use sync `import * as billingModule from '@donotdev/billing'`
9
+ * at module level. DO NOT refactor to use async `import('@donotdev/billing').then(...)`.
10
+ *
11
+ * ### Why sync import is required:
12
+ *
13
+ * 1. **Bundler aliasing**: Vite/webpack alias missing packages to empty modules
14
+ * at BUILD TIME. The import completes immediately (no async).
15
+ *
16
+ * 2. **Rules of Hooks**: If we use async dynamic import:
17
+ * - First render: `realUseStripeBilling = null` → uses stub (0 hooks)
18
+ * - Async completes: `realUseStripeBilling = useStripeBilling` → now has hooks
19
+ * - Next render: React sees different hook count → CRASH
20
+ *
21
+ * 3. **Monorepo gotcha**: Dynamic imports resolve workspace packages even when
22
+ * the consuming app doesn't have them as dependencies. This causes the
23
+ * real hook to activate unexpectedly → Rules of Hooks violation.
24
+ *
25
+ * 4. **Decision is immutable**: With sync import, `billingModule?.useStripeBilling`
26
+ * is evaluated ONCE at module load. It's either the real hook or undefined.
27
+ * This never changes during the app lifecycle.
28
+ *
29
+ * @see docs/development/GRACEFUL_DEGRADATION.md
30
+ * @version 0.0.4
18
31
  * @since 0.0.1
19
32
  * @author AMBROISE PARK Consulting
20
33
  */
@@ -28,23 +41,22 @@ export type { BillingAuthState } from '@donotdev/billing';
28
41
  * - If not installed → returns degraded API values
29
42
  *
30
43
  * **IMPORTANT:** For `isAvailable` to return `true`, you must pass `authState`.
31
- * Without auth state, billing will return `isAvailable: false` until auth resolves.
44
+ * Without auth state, billing will return `isAvailable: false` until auth status is `ready`.
32
45
  *
33
46
  * @param key - Property name to access from billing API
34
- * @param authState - Auth state from useAuthSafe (user, initialized, authStateChecked)
47
+ * @param authState - Auth state from useAuthSafe (user, status)
35
48
  * @returns The billing API value, or degraded value if billing unavailable
36
49
  *
37
50
  * @example
38
51
  * ```typescript
39
52
  * // Get auth state first
40
53
  * const user = useAuthSafe('user');
41
- * const initialized = useAuthSafe('initialized');
42
- * const authStateChecked = useAuthSafe('authStateChecked');
43
- * const authState = { user, initialized, authStateChecked };
54
+ * const status = useAuthSafe('status'); // 'initializing' | 'ready' | 'degraded' | 'error'
55
+ * const authState = { user, status };
44
56
  *
45
57
  * // Pass to billing
46
58
  * const checkout = useStripeBillingSafe('checkout', authState);
47
- * const loading = useStripeBillingSafe('loading', authState);
59
+ * const billingStatus = useStripeBillingSafe('status', authState);
48
60
  * const isAvailable = useStripeBillingSafe('isAvailable', authState);
49
61
  * ```
50
62
  */
@@ -1 +1 @@
1
- {"version":3,"file":"useStripeBillingSafe.d.ts","sourceRoot":"","sources":["../../src/utils/useStripeBillingSafe.ts"],"names":[],"mappings":"AAEA;;;;;;;;;;;;;;;;;;;GAmBG;AAEH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;AAIjD,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AAG1D,YAAY,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AAoB1D;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,wBAAgB,oBAAoB,CAAC,CAAC,SAAS,MAAM,UAAU,EAC7D,GAAG,EAAE,CAAC,EACN,SAAS,CAAC,EAAE,gBAAgB,GAC3B,UAAU,CAAC,CAAC,CAAC,CAKf;AAED;;GAEG;AACH,eAAO,MAAM,kBAAkB,SAA6C,CAAC"}
1
+ {"version":3,"file":"useStripeBillingSafe.d.ts","sourceRoot":"","sources":["../../src/utils/useStripeBillingSafe.ts"],"names":[],"mappings":"AAEA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgCG;AAEH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;AAIjD,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AAG1D,YAAY,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AAoB1D;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,wBAAgB,oBAAoB,CAAC,CAAC,SAAS,MAAM,UAAU,EAC7D,GAAG,EAAE,CAAC,EACN,SAAS,CAAC,EAAE,gBAAgB,GAC3B,UAAU,CAAC,CAAC,CAAC,CAKf;AAED;;GAEG;AACH,eAAO,MAAM,kBAAkB,SAA6C,CAAC"}
@@ -17,23 +17,22 @@ function useStripeBillingStub(key) {
17
17
  * - If not installed → returns degraded API values
18
18
  *
19
19
  * **IMPORTANT:** For `isAvailable` to return `true`, you must pass `authState`.
20
- * Without auth state, billing will return `isAvailable: false` until auth resolves.
20
+ * Without auth state, billing will return `isAvailable: false` until auth status is `ready`.
21
21
  *
22
22
  * @param key - Property name to access from billing API
23
- * @param authState - Auth state from useAuthSafe (user, initialized, authStateChecked)
23
+ * @param authState - Auth state from useAuthSafe (user, status)
24
24
  * @returns The billing API value, or degraded value if billing unavailable
25
25
  *
26
26
  * @example
27
27
  * ```typescript
28
28
  * // Get auth state first
29
29
  * const user = useAuthSafe('user');
30
- * const initialized = useAuthSafe('initialized');
31
- * const authStateChecked = useAuthSafe('authStateChecked');
32
- * const authState = { user, initialized, authStateChecked };
30
+ * const status = useAuthSafe('status'); // 'initializing' | 'ready' | 'degraded' | 'error'
31
+ * const authState = { user, status };
33
32
  *
34
33
  * // Pass to billing
35
34
  * const checkout = useStripeBillingSafe('checkout', authState);
36
- * const loading = useStripeBillingSafe('loading', authState);
35
+ * const billingStatus = useStripeBillingSafe('status', authState);
37
36
  * const isAvailable = useStripeBillingSafe('isAvailable', authState);
38
37
  * ```
39
38
  */
@@ -1 +1 @@
1
- {"version":3,"file":"AppRoutes.d.ts","sourceRoot":"","sources":["../../src/vite-routing/AppRoutes.tsx"],"names":[],"mappings":"AAyDA,OAAO,EAAiB,KAAK,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAkFlE;;GAEG;AACH,MAAM,WAAW,UAAU;IACzB,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,GAAG,CAAC;IACX,MAAM,EAAE,KAAK,CAAC;QACZ,IAAI,EAAE,MAAM,CAAC;QACb,SAAS,EAAE,GAAG,CAAC;QACf,IAAI,CAAC,EAAE,GAAG,CAAC;QACX,CAAC,GAAG,EAAE,MAAM,GAAG,GAAG,CAAC;KACpB,CAAC,CAAC;CACJ;AAED;;GAEG;AACH,UAAU,sBAAsB;IAC9B,4CAA4C;IAC5C,WAAW,EAAE,UAAU,EAAE,CAAC;IAC1B,0CAA0C;IAC1C,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,oCAAoC;IACpC,MAAM,CAAC,EAAE,YAAY,CAAC;CACvB;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAyCG;AACH,wBAAgB,eAAe,CAAC,OAAO,EAAE,sBAAsB,yCAgE9D"}
1
+ {"version":3,"file":"AppRoutes.d.ts","sourceRoot":"","sources":["../../src/vite-routing/AppRoutes.tsx"],"names":[],"mappings":"AAoDA,OAAO,EAAiB,KAAK,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAsFlE;;GAEG;AACH,MAAM,WAAW,UAAU;IACzB,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,GAAG,CAAC;IACX,MAAM,EAAE,KAAK,CAAC;QACZ,IAAI,EAAE,MAAM,CAAC;QACb,SAAS,EAAE,GAAG,CAAC;QACf,IAAI,CAAC,EAAE,GAAG,CAAC;QACX,CAAC,GAAG,EAAE,MAAM,GAAG,GAAG,CAAC;KACpB,CAAC,CAAC;CACJ;AAED;;GAEG;AACH,UAAU,sBAAsB;IAC9B,4CAA4C;IAC5C,WAAW,EAAE,UAAU,EAAE,CAAC;IAC1B,0CAA0C;IAC1C,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,oCAAoC;IACpC,MAAM,CAAC,EAAE,YAAY,CAAC;CACvB;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAyCG;AACH,wBAAgB,eAAe,CAAC,OAAO,EAAE,sBAAsB,yCA8D9D"}
@@ -32,7 +32,7 @@ import { jsx as _jsx } from "react/jsx-runtime";
32
32
  * - **Suspense Boundaries**: Proper loading states prevent UI flicker
33
33
  * - **Native Scroll Restoration**: Built-in scroll position memory
34
34
  *
35
- * @version 0.0.2
35
+ * @version 0.0.3
36
36
  * @since 0.0.1
37
37
  * @author AMBROISE PARK Consulting
38
38
  * @license Commercial
@@ -46,7 +46,7 @@ import { jsx as _jsx } from "react/jsx-runtime";
46
46
  * <RouterProvider router={router} />
47
47
  * ```
48
48
  */
49
- import { lazy, Suspense, } from 'react';
49
+ import { lazy, Suspense } from 'react';
50
50
  import { createBrowserRouter } from 'react-router-dom';
51
51
  import {} from '@donotdev/core';
52
52
  import { RootLayout } from './RootLayout';
@@ -87,7 +87,7 @@ const LazyRoute = ({ component, path }) => {
87
87
  lazyComponentCache.set(path, lazy(component));
88
88
  }
89
89
  const Component = lazyComponentCache.get(path);
90
- return _jsx(Component, {});
90
+ return (_jsx(Suspense, { fallback: _jsx(Loader, {}), children: _jsx(Component, {}) }));
91
91
  };
92
92
  /**
93
93
  * Parse auth configuration to PageAuth | false for AuthGuard
@@ -177,9 +177,9 @@ export function createAppRouter(options) {
177
177
  element: _jsx(RootLayout, { layout: layout }),
178
178
  children: [
179
179
  {
180
- /** HomePage route - discovered from HomePage.tsx */
180
+ /** HomePage route - lazy loaded, public (no AuthGuard) */
181
181
  index: true,
182
- element: homePageRoute.parsedAuth === false ? (_jsx(LazyRoute, { component: homePageRoute.component, path: homePageRoute.path })) : (_jsx(AuthGuard, { auth: homePageRoute.parsedAuth, children: _jsx(LazyRoute, { component: homePageRoute.component, path: homePageRoute.path }) })),
182
+ element: (_jsx(LazyRoute, { component: homePageRoute.component, path: homePageRoute.path })),
183
183
  },
184
184
  /** All other routes are discovered and rendered here */
185
185
  ...routesWithParsedAuth
@@ -1 +1 @@
1
- {"version":3,"file":"RootLayout.d.ts","sourceRoot":"","sources":["../../src/vite-routing/RootLayout.tsx"],"names":[],"mappings":"AAoBA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AA8JnD;;GAEG;AACH,UAAU,oBAAoB;IAC5B,2BAA2B;IAC3B,MAAM,CAAC,EAAE,YAAY,CAAC;CACvB;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgCG;AACH,wBAAgB,UAAU,CAAC,EAAE,MAAM,EAAE,EAAE,oBAAoB,2CAmC1D"}
1
+ {"version":3,"file":"RootLayout.d.ts","sourceRoot":"","sources":["../../src/vite-routing/RootLayout.tsx"],"names":[],"mappings":"AAoBA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAuLnD;;GAEG;AACH,UAAU,oBAAoB;IAC5B,2BAA2B;IAC3B,MAAM,CAAC,EAAE,YAAY,CAAC;CACvB;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgCG;AACH,wBAAgB,UAAU,CAAC,EAAE,MAAM,EAAE,EAAE,oBAAoB,2CA6B1D"}
@@ -1,4 +1,4 @@
1
- import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
1
+ import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  // packages/ui/src/vite-routing/RootLayout.tsx
3
3
  /**
4
4
  * @fileoverview RootLayout - Root route layout component
@@ -18,11 +18,8 @@ import { Outlet, useLocation } from 'react-router-dom';
18
18
  import { globalEmitter, isClient } from '@donotdev/core';
19
19
  import Loader from '../components/common/Loader';
20
20
  import { DnDevLayout } from '../internal/layout/DnDevLayout';
21
- // Lazy load providers and components
22
- const QueryProviders = lazy(() => import('@donotdev/core').then((m) => ({ default: m.QueryProviders })));
23
- const UIProviders = lazy(() => import('../internal/providers/UIProviders').then((m) => ({
24
- default: m.UIProviders,
25
- })));
21
+ import { UIProviders } from '../internal/providers/UIProviders';
22
+ // Only lazy load non-critical components (not in render path)
26
23
  const AutoMetaTags = lazy(() => import('../internal/layout/components/AutoMetaTags').then((m) => ({
27
24
  default: m.default,
28
25
  })));
@@ -145,6 +142,36 @@ function FrameworkReadySignal({ children }) {
145
142
  }, []);
146
143
  return _jsx("div", { ref: frameworkRef, children: children });
147
144
  }
145
+ /**
146
+ * RouteReadySignal - Signals when route content is painted
147
+ *
148
+ * Emits 'DNDEV_ROUTE_READY' event when route content (inside Suspense) is painted.
149
+ * Used in coordination with FrameworkReadySignal to time shell loader removal.
150
+ *
151
+ * Shell loader removed only when BOTH framework AND route are ready,
152
+ * preventing "late arrival" of route content after Header/Footer paint.
153
+ *
154
+ * @version 0.0.1
155
+ * @since 0.0.1
156
+ * @author AMBROISE PARK Consulting
157
+ */
158
+ function RouteReadySignal({ children }) {
159
+ const hasSignaled = useRef(false);
160
+ useLayoutEffect(() => {
161
+ if (!isClient() || hasSignaled.current)
162
+ return;
163
+ // Wait for two animation frames to ensure paint completion
164
+ requestAnimationFrame(() => {
165
+ requestAnimationFrame(() => {
166
+ if (hasSignaled.current)
167
+ return;
168
+ hasSignaled.current = true;
169
+ globalEmitter.emit('DNDEV_ROUTE_READY');
170
+ });
171
+ });
172
+ }, []);
173
+ return _jsx(_Fragment, { children: children });
174
+ }
148
175
  /**
149
176
  * RootLayout - Root route layout component
150
177
  *
@@ -179,5 +206,5 @@ function FrameworkReadySignal({ children }) {
179
206
  * @author AMBROISE PARK Consulting
180
207
  */
181
208
  export function RootLayout({ layout }) {
182
- return (_jsx(QueryProviders, { children: _jsxs(UIProviders, { children: [_jsx(AutoMetaTags, {}), _jsxs(FrameworkReadySignal, { children: [_jsx(DnDevLayout, { layout: layout, children: _jsx(Suspense, { fallback: _jsx(Loader, {}), children: _jsx(Outlet, {}) }) }), _jsx(CustomScrollRestoration, {}), _jsx(ConsentBanner, {}), _jsx(PWAUpdateNotification, {}), _jsx(LicenseWatermark, {})] })] }) }));
209
+ return (_jsxs(UIProviders, { children: [_jsx(Suspense, { fallback: null, children: _jsx(AutoMetaTags, {}) }), _jsxs(FrameworkReadySignal, { children: [_jsx(DnDevLayout, { layout: layout, children: _jsx(RouteReadySignal, { children: _jsx(Outlet, {}) }) }), _jsx(CustomScrollRestoration, {}), _jsxs(Suspense, { fallback: null, children: [_jsx(ConsentBanner, {}), _jsx(PWAUpdateNotification, {}), _jsx(LicenseWatermark, {})] })] })] }));
183
210
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@donotdev/ui",
3
- "version": "0.0.2",
3
+ "version": "0.0.4",
4
4
  "type": "module",
5
5
  "private": false,
6
6
  "license": "SEE LICENSE IN LICENSE.md",
@@ -53,14 +53,14 @@
53
53
  "react-hook-form": "^7.68.0"
54
54
  },
55
55
  "peerDependencies": {
56
- "@donotdev/adv-comps": "0.0.2",
57
- "@donotdev/auth": "0.0.2",
58
- "@donotdev/billing": "0.0.2",
59
- "@donotdev/components": "0.0.2",
60
- "@donotdev/core": "0.0.2",
61
- "@donotdev/crud": "0.0.2",
62
- "@donotdev/firebase": "0.0.2",
63
- "@donotdev/oauth": "0.0.2",
56
+ "@donotdev/adv-comps": "0.0.4",
57
+ "@donotdev/auth": "0.0.4",
58
+ "@donotdev/billing": "0.0.4",
59
+ "@donotdev/components": "0.0.4",
60
+ "@donotdev/core": "0.0.4",
61
+ "@donotdev/crud": "0.0.4",
62
+ "@donotdev/firebase": "0.0.4",
63
+ "@donotdev/oauth": "0.0.4",
64
64
  "firebase": "^12.5.0",
65
65
  "lucide-react": "^0.562.0",
66
66
  "react": "^19.2.3",
@@ -1,2 +0,0 @@
1
- export declare const AuthTab: () => import("react/jsx-runtime").JSX.Element;
2
- //# sourceMappingURL=AuthTab.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"AuthTab.d.ts","sourceRoot":"","sources":["../../../../src/internal/devtools/components/AuthTab.tsx"],"names":[],"mappings":"AAiCA,eAAO,MAAM,OAAO,+CAyNnB,CAAC"}
@@ -1,98 +0,0 @@
1
- 'use client';
2
- import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
3
- // packages/ui/src/internal/devtools/components/AuthTab.tsx
4
- /**
5
- * @fileoverview Auth Tab Component
6
- * @description User-friendly authentication and OAuth debugging for consumers
7
- *
8
- * @version 0.0.1
9
- * @since 0.0.1
10
- * @author AMBROISE PARK Consulting
11
- */
12
- import { useState, useMemo } from 'react';
13
- import { Card, CARD_VARIANT, Badge, BADGE_VARIANT, Button, BUTTON_VARIANT, DescriptionList, Alert, ALERT_VARIANT, Text, Stack, } from '@donotdev/components';
14
- import { getDndevConfig } from '@donotdev/core';
15
- import { useAuthSafe } from '../../../utils/useAuthSafe';
16
- import { discoverEnvVarsByPattern } from '../utils';
17
- import { MaskedValue } from './MaskedValue';
18
- export const AuthTab = () => {
19
- const user = useAuthSafe('user');
20
- const loading = useAuthSafe('loading');
21
- const error = useAuthSafe('error');
22
- const [isOAuthExpanded, setIsOAuthExpanded] = useState(false);
23
- const config = getDndevConfig();
24
- const envVars = config?.env || {};
25
- const oauthVars = useMemo(() => discoverEnvVarsByPattern(envVars, [
26
- '*OAUTH*',
27
- '*GOOGLE*CLIENT*',
28
- '*GITHUB*CLIENT*',
29
- '*AUTH*PARTNER*',
30
- ]), [envVars]);
31
- const googleClientId = Object.entries(oauthVars).find(([key]) => key.toUpperCase().includes('GOOGLE') &&
32
- key.toUpperCase().includes('CLIENT'))?.[1];
33
- const githubClientId = Object.entries(oauthVars).find(([key]) => key.toUpperCase().includes('GITHUB') &&
34
- key.toUpperCase().includes('CLIENT'))?.[1];
35
- const authPartners = Object.entries(oauthVars).find(([key]) => key.toUpperCase().includes('AUTH') &&
36
- key.toUpperCase().includes('PARTNER'))?.[1];
37
- const getStatusBadge = () => {
38
- if (loading)
39
- return _jsx(Badge, { variant: BADGE_VARIANT.SECONDARY, children: "Loading" });
40
- if (error)
41
- return _jsx(Badge, { variant: BADGE_VARIANT.DESTRUCTIVE, children: "Error" });
42
- if (user)
43
- return _jsx(Badge, { children: "Signed In" });
44
- return _jsx(Badge, { variant: BADGE_VARIANT.OUTLINE, children: "Not Signed In" });
45
- };
46
- const authStatusItems = [{ label: 'Status', value: getStatusBadge() }];
47
- const userInfoItems = user
48
- ? [
49
- {
50
- label: 'Email',
51
- value: (_jsx(Text, { as: "span", className: "dndev-font-mono", children: user.email || 'N/A' })),
52
- },
53
- {
54
- label: 'User ID',
55
- value: (_jsx(Text, { as: "span", className: "dndev-font-mono dndev-text-xs", children: user.id })),
56
- },
57
- ...(user.displayName
58
- ? [{ label: 'Display Name', value: user.displayName }]
59
- : []),
60
- ]
61
- : [];
62
- const oauthConfigItems = Object.keys(oauthVars).length > 0
63
- ? Object.entries(oauthVars).map(([key, value]) => ({
64
- label: key,
65
- value: (_jsxs(Stack, { gap: "tight", children: [_jsx("div", { className: "dndev-flex dndev-items-center dndev-justify-between", children: _jsx(Badge, { children: "Configured" }) }), _jsx(MaskedValue, { keyName: key, value: String(value), textClassName: "dndev-font-mono dndev-text-xs dndev-text-muted-foreground" })] })),
66
- }))
67
- : [
68
- {
69
- label: 'OAuth Variables',
70
- value: (_jsx(Text, { as: "span", className: "dndev-text-sm dndev-text-muted-foreground", children: "No OAuth environment variables detected. Add variables matching patterns: *OAUTH*, *GOOGLE*CLIENT*, *GITHUB*CLIENT*, *AUTH*PARTNER*" })),
71
- },
72
- ];
73
- const setupSteps = [
74
- {
75
- title: '1. Firebase Console',
76
- steps: [
77
- _jsxs(_Fragment, { children: ["Go to", ' ', _jsx("a", { href: "https://console.firebase.google.com", target: "_blank", rel: "noopener noreferrer", className: "dndev-text-primary dndev-underline", children: "Firebase Console" })] }),
78
- 'Authentication → Sign-in method',
79
- 'Enable Google, GitHub, etc.',
80
- ],
81
- },
82
- {
83
- title: '2. GitHub OAuth',
84
- steps: [
85
- _jsxs(_Fragment, { children: ["Create OAuth App at", ' ', _jsx("a", { href: "https://github.com/settings/applications/new", target: "_blank", rel: "noopener noreferrer", className: "dndev-text-primary dndev-underline", children: "GitHub" })] }),
86
- _jsxs(_Fragment, { children: ["Callback URL:", ' ', _jsx("code", { className: "dndev-bg-background dndev-px-sm dndev-rounded dndev-text-xs", children: "https://your-project.firebaseapp.com/__/auth/handler" })] }),
87
- 'Copy Client ID/Secret to Firebase',
88
- ],
89
- },
90
- {
91
- title: '3. Authorized Domains',
92
- steps: [
93
- 'Add localhost, your-domain.com to Firebase Console → Authentication → Settings',
94
- ],
95
- },
96
- ];
97
- return (_jsxs(Stack, { gap: "medium", children: [_jsx(Card, { title: "Authentication Status", subtitle: "Current authentication state", children: _jsxs(Stack, { gap: "medium", children: [_jsx(DescriptionList, { items: authStatusItems }), user && (_jsx(Stack, { gap: "tight", children: _jsx(DescriptionList, { items: userInfoItems }) })), error && (_jsx(Alert, { variant: ALERT_VARIANT.ERROR, title: "Error", children: error.message }))] }) }), _jsx(Card, { title: "OAuth Configuration", subtitle: "OAuth provider setup status", children: _jsxs(Stack, { gap: "medium", children: [_jsx(DescriptionList, { items: oauthConfigItems }), _jsxs(Button, { onClick: () => setIsOAuthExpanded(!isOAuthExpanded), variant: BUTTON_VARIANT.OUTLINE, className: "dndev-w-full", children: [isOAuthExpanded ? 'Hide' : 'Show', " Setup Guide"] }), isOAuthExpanded && (_jsxs(Card, { variant: CARD_VARIANT.MUTED, className: "dndev-grid dndev-gap-md", children: [setupSteps.map((section, idx) => (_jsxs("div", { className: "dndev-grid dndev-gap-sm", children: [_jsx(Text, { as: "span", className: "dndev-font-semibold", children: section.title }), _jsx("ol", { className: "dndev-list dndev-list-decimal dndev-list-inside dndev-text-muted-foreground dndev-text-sm dndev-grid dndev-gap-xs", children: section.steps.map((step, stepIdx) => (_jsx("li", { children: step }, stepIdx))) })] }, idx))), _jsxs(Alert, { variant: ALERT_VARIANT.WARNING, children: [_jsx("strong", { children: "Note:" }), " 400 error = GitHub OAuth not configured in Firebase"] })] }))] }) })] }));
98
- };
@@ -1,2 +0,0 @@
1
- export declare const ColorRatioTab: () => import("react/jsx-runtime").JSX.Element;
2
- //# sourceMappingURL=ColorRatioTab.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"ColorRatioTab.d.ts","sourceRoot":"","sources":["../../../../src/internal/devtools/components/ColorRatioTab.tsx"],"names":[],"mappings":"AAmCA,eAAO,MAAM,aAAa,+CAodzB,CAAC"}