@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
@@ -7,7 +7,6 @@
7
7
  * @author AMBROISE PARK Consulting
8
8
  */
9
9
  export * from './envVarDiscovery';
10
- export * from './spacingAnalyzer';
11
10
  export * from './virtualModuleInspector';
12
11
  export * from './maskSensitive';
13
12
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/internal/devtools/utils/index.ts"],"names":[],"mappings":"AAEA;;;;;;;GAOG;AAEH,cAAc,mBAAmB,CAAC;AAClC,cAAc,mBAAmB,CAAC;AAClC,cAAc,0BAA0B,CAAC;AACzC,cAAc,iBAAiB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/internal/devtools/utils/index.ts"],"names":[],"mappings":"AAEA;;;;;;;GAOG;AAEH,cAAc,mBAAmB,CAAC;AAClC,cAAc,0BAA0B,CAAC;AACzC,cAAc,iBAAiB,CAAC"}
@@ -8,6 +8,5 @@
8
8
  * @author AMBROISE PARK Consulting
9
9
  */
10
10
  export * from './envVarDiscovery';
11
- export * from './spacingAnalyzer';
12
11
  export * from './virtualModuleInspector';
13
12
  export * from './maskSensitive';
@@ -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,kDA0K5B"}
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.1
8
+ * @version 0.0.2
9
9
  * @since 0.0.1
10
10
  * @author AMBROISE PARK Consulting
11
11
  */
@@ -232,77 +232,54 @@ export function BaseStoresInitializer({ children, handlers, customStores = [], s
232
232
  const allCustomReady = criticalCustomStores.length === 0 ||
233
233
  customReadiness.every((ready) => ready === true);
234
234
  const criticalReady = consentReady && themeReady && i18nReady && allCustomReady;
235
+ // Two-phase loader: wait for BOTH framework AND route to be ready
235
236
  useLayoutEffect(() => {
236
237
  if (!isClient() || !criticalReady)
237
238
  return;
238
239
  let removed = false;
239
- const removeLoader = (fade = false) => {
240
+ let frameworkReady = false;
241
+ let routeReady = false;
242
+ const removeLoader = () => {
240
243
  if (removed)
241
244
  return;
242
245
  removed = true;
243
- removeShellLoader({ fade });
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
+ }
244
257
  };
245
- const handleFrameworkReady = () => {
246
- if (removed)
258
+ const checkBothReady = () => {
259
+ if (!frameworkReady || !routeReady || removed)
247
260
  return;
248
- removeLoader(false);
261
+ removeLoader();
249
262
  };
250
- const unsubscribe = globalEmitter.on('DNDEV_FRAMEWORK_READY', handleFrameworkReady);
251
- const root = document.getElementById('root');
252
- if (!root) {
253
- setTimeout(() => removeLoader(true), 300);
254
- return () => {
255
- unsubscribe();
256
- };
257
- }
258
- const hasReactContent = () => {
259
- // Zero reflow content detection - only uses properties that don't trigger layout
260
- const children = Array.from(root.children);
261
- // Check for non-shell-loader children without forcing reflow
262
- // React content will have:
263
- // 1. Child elements (components mount as DOM nodes)
264
- // 2. Data attributes (React adds data-reactroot, etc.)
265
- // NOTE: We avoid textContent checks as they force layout recalculation
266
- const hasContent = children.some((child) => {
267
- if (child.id === 'shell-loader')
268
- return false;
269
- // Zero-reflow detection strategies:
270
- // - Child elements exist (no layout needed)
271
- // - React data attributes (no layout needed)
272
- // - Custom data attributes from framework (no layout needed)
273
- return (child.children.length > 0 ||
274
- child.hasAttribute('data-reactroot') ||
275
- child.hasAttribute('data-dndev-mounted'));
276
- });
277
- return hasContent;
263
+ const handleFrameworkReady = () => {
264
+ frameworkReady = true;
265
+ checkBothReady();
278
266
  };
279
- const checkAndRemove = () => {
280
- if (hasReactContent()) {
281
- removeLoader(false);
282
- return true;
283
- }
284
- return false;
267
+ const handleRouteReady = () => {
268
+ routeReady = true;
269
+ checkBothReady();
285
270
  };
286
- let fallbackTimeout = null;
287
- requestAnimationFrame(() => {
288
- requestAnimationFrame(() => {
289
- if (!checkAndRemove()) {
290
- fallbackTimeout = setTimeout(() => {
291
- if (hasReactContent()) {
292
- removeLoader(false);
293
- }
294
- else {
295
- removeLoader(true);
296
- }
297
- }, 1000);
298
- }
299
- });
300
- });
301
- return () => {
302
- unsubscribe();
303
- if (fallbackTimeout) {
304
- clearTimeout(fallbackTimeout);
271
+ const unsubFramework = globalEmitter.on('DNDEV_FRAMEWORK_READY', handleFrameworkReady);
272
+ const unsubRoute = globalEmitter.on('DNDEV_ROUTE_READY', handleRouteReady);
273
+ // Fallback timeout: if route doesn't signal within 2s, remove anyway
274
+ const fallbackTimeout = setTimeout(() => {
275
+ if (!removed) {
276
+ removeLoader();
305
277
  }
278
+ }, 2000);
279
+ return () => {
280
+ unsubFramework();
281
+ unsubRoute();
282
+ clearTimeout(fallbackTimeout);
306
283
  };
307
284
  }, [criticalReady]);
308
285
  if (!criticalReady)
@@ -226,13 +226,13 @@ export const DnDevLayout = ({ children, layout, className, }) => {
226
226
  DEFAULT_SLOTS.sidebar.bottom;
227
227
  return (_jsx(DnDevMergedBar, { position: mergedBarConfig.position, height: mergedBarConfig.height, trigger: triggerSlot(), top: topSlot(), content: contentSlot(), bottom: bottomSlot() }));
228
228
  }, [layout?.mergedbar, config]);
229
- // Apply routing animation data attribute
230
- useEffect(() => {
229
+ // Apply routing animation data attribute (useLayoutEffect = before paint)
230
+ useLayoutEffect(() => {
231
231
  if (!isClient() || !mainRef.current)
232
232
  return;
233
233
  const routingAnimation = getComputedStyle(document.documentElement)
234
234
  .getPropertyValue('--routing-animation')
235
- .trim() || 'fade';
235
+ .trim() || 'none';
236
236
  mainRef.current.setAttribute('data-routing-animation', routingAnimation);
237
237
  }, [pathname]);
238
238
  // Apply data attributes
@@ -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;AAwC3C;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,YAAY,EAAE,aAgN1B,CAAC;AAEF;;;GAGG;AAEH,eAAe,YAAY,CAAC"}
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: '/logo.png',
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
  }) })] }));
@@ -1 +1 @@
1
- {"version":3,"file":"FooterBranding.d.ts","sourceRoot":"","sources":["../../../../../src/internal/layout/components/footer/FooterBranding.tsx"],"names":[],"mappings":"AAeA,MAAM,WAAW,mBAAmB;IAClC,6BAA6B;IAC7B,SAAS,CAAC,EAAE,MAAM,CAAC;IAEnB,gBAAgB;IAChB,IAAI,CAAC,EAAE,IAAI,GAAG,IAAI,CAAC;CACpB;AAED;;;;;;;;;GASG;AACH,eAAO,MAAM,cAAc,EAAE,KAAK,CAAC,aAAa,CAAC,mBAAmB,CAgCnE,CAAC;AAEF,eAAe,cAAc,CAAC"}
1
+ {"version":3,"file":"FooterBranding.d.ts","sourceRoot":"","sources":["../../../../../src/internal/layout/components/footer/FooterBranding.tsx"],"names":[],"mappings":"AAeA,MAAM,WAAW,mBAAmB;IAClC,6BAA6B;IAC7B,SAAS,CAAC,EAAE,MAAM,CAAC;IAEnB,gBAAgB;IAChB,IAAI,CAAC,EAAE,IAAI,GAAG,IAAI,CAAC;CACpB;AAED;;;;;;;;;GASG;AACH,eAAO,MAAM,cAAc,EAAE,KAAK,CAAC,aAAa,CAAC,mBAAmB,CAoCnE,CAAC;AAEF,eAAe,cAAc,CAAC"}
@@ -27,7 +27,9 @@ export const FooterBranding = ({ className, size = 'xs', }) => {
27
27
  xs: { fontSize: 'var(--font-size-xs)' },
28
28
  sm: { fontSize: 'var(--font-size-sm)' },
29
29
  };
30
- return (_jsxs("a", { href: isFrameworkSite ? 'https://www.ambroise-park.com' : 'https://donotdev.com', target: "_blank", rel: "noopener noreferrer", className: className, style: {
30
+ return (_jsxs("a", { href: isFrameworkSite
31
+ ? 'https://www.ambroise-park.com'
32
+ : 'https://donotdev.com', target: "_blank", rel: "noopener noreferrer", className: className, style: {
31
33
  display: 'inline-flex',
32
34
  alignItems: 'center',
33
35
  gap: 'var(--gap-sm)',
@@ -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 isDesktopOrWide = useBreakpoint('isDesktopOrWide');
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 (isDesktopOrWide) {
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
@@ -2,7 +2,7 @@
2
2
  * @fileoverview AuthGuard component
3
3
  * @description Protects routes based on authentication configuration
4
4
  *
5
- * @version 0.0.1
5
+ * @version 0.0.3
6
6
  * @since 0.0.1
7
7
  * @author AMBROISE PARK Consulting
8
8
  */
@@ -34,24 +34,28 @@ interface AuthGuardProps {
34
34
  * - 'pro': Professional features
35
35
  * - 'premium': Premium features
36
36
  *
37
- * @version 0.0.1
37
+ * @version 0.0.3
38
38
  * @since 0.0.1
39
39
  * @author AMBROISE PARK Consulting
40
40
  */
41
41
  export declare function AuthGuard({ auth, children, fallback: Fallback, }: AuthGuardProps): import("react/jsx-runtime").JSX.Element;
42
42
  /**
43
- * Hook to check if current user can access a route with given auth config
43
+ * Hook to check if current user can navigate to a route with given auth config
44
44
  * ONLY uses store - single source of truth!
45
45
  *
46
- * @version 0.0.1
46
+ * @version 0.0.3
47
47
  * @since 0.0.1
48
48
  * @author AMBROISE PARK Consulting
49
49
  */
50
- export declare function useCanAccess(auth: PageAuth | false): boolean;
50
+ export declare function useCanNavigate(auth: PageAuth | false): boolean;
51
+ /**
52
+ * @deprecated Use useCanNavigate instead
53
+ */
54
+ export declare const useCanAccess: typeof useCanNavigate;
51
55
  /**
52
56
  * Hook to get current user's role - directly from store
53
57
  *
54
- * @version 0.0.1
58
+ * @version 0.0.3
55
59
  * @since 0.0.1
56
60
  * @author AMBROISE PARK Consulting
57
61
  */
@@ -59,7 +63,7 @@ export declare function useUserRole(): typeof USER_ROLES.GUEST | typeof USER_ROL
59
63
  /**
60
64
  * Hook to check specific role - directly from store
61
65
  *
62
- * @version 0.0.1
66
+ * @version 0.0.3
63
67
  * @since 0.0.1
64
68
  * @author AMBROISE PARK Consulting
65
69
  */
@@ -67,7 +71,7 @@ export declare function useHasRole(role: typeof USER_ROLES.GUEST | typeof USER_R
67
71
  /**
68
72
  * Hook to get all auth state for debugging
69
73
  *
70
- * @version 0.0.1
74
+ * @version 0.0.3
71
75
  * @since 0.0.1
72
76
  * @author AMBROISE PARK Consulting
73
77
  */
@@ -81,7 +85,7 @@ export declare function useAuthState(): {
81
85
  /**
82
86
  * HOC to wrap components with auth protection
83
87
  *
84
- * @version 0.0.1
88
+ * @version 0.0.3
85
89
  * @since 0.0.1
86
90
  * @author AMBROISE PARK Consulting
87
91
  */
@@ -89,7 +93,7 @@ export declare function withAuth<P extends object>(Component: ComponentType<P>,
89
93
  /**
90
94
  * Utility to create auth configs
91
95
  *
92
- * @version 0.0.1
96
+ * @version 0.0.3
93
97
  * @since 0.0.1
94
98
  * @author AMBROISE PARK Consulting
95
99
  */
@@ -1 +1 @@
1
- {"version":3,"file":"AuthGuard.d.ts","sourceRoot":"","sources":["../../src/routing/AuthGuard.tsx"],"names":[],"mappings":"AAGA;;;;;;;GAOG;AAEH,OAAO,EAKL,KAAK,SAAS,EACd,KAAK,aAAa,EACnB,MAAM,OAAO,CAAC;AAIf,OAAO,EAAE,UAAU,EAAE,kBAAkB,EAAE,KAAK,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAY/E;;GAEG;AACH,UAAU,cAAc;IACtB,wCAAwC;IACxC,IAAI,EAAE,QAAQ,GAAG,KAAK,CAAC;IACvB,wCAAwC;IACxC,QAAQ,EAAE,SAAS,CAAC;IACpB,6CAA6C;IAC7C,QAAQ,CAAC,EAAE,aAAa,CAAC;CAC1B;AAED;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,SAAS,CAAC,EACxB,IAAI,EACJ,QAAQ,EACR,QAAQ,EAAE,QAAiB,GAC5B,EAAE,cAAc,2CA2HhB;AAED;;;;;;;GAOG;AACH,wBAAgB,YAAY,CAAC,IAAI,EAAE,QAAQ,GAAG,KAAK,GAAG,OAAO,CAG5D;AAED;;;;;;GAMG;AACH,wBAAgB,WAAW,IACvB,OAAO,UAAU,CAAC,KAAK,GACvB,OAAO,UAAU,CAAC,IAAI,GACtB,OAAO,UAAU,CAAC,KAAK,CAS1B;AAED;;;;;;GAMG;AACH,wBAAgB,UAAU,CACxB,IAAI,EACA,OAAO,UAAU,CAAC,KAAK,GACvB,OAAO,UAAU,CAAC,IAAI,GACtB,OAAO,UAAU,CAAC,KAAK,GAC1B,OAAO,CAIT;AAED;;;;;;GAMG;AACH,wBAAgB,YAAY;;;;;;EAW3B;AAED;;;;;;GAMG;AACH,wBAAgB,QAAQ,CAAC,CAAC,SAAS,MAAM,EACvC,SAAS,EAAE,aAAa,CAAC,CAAC,CAAC,EAC3B,IAAI,EAAE,QAAQ,GAAG,KAAK,WAEW,CAAC,6CAOnC;AAED;;;;;;GAMG;AACH,eAAO,MAAM,gBAAgB;IAC3B,iCAAiC;kBACrB,KAAK;IAEjB,oCAAoC;oBACtB,QAAQ;IAEtB,yCAAyC;gBAC/B,QAAQ;IAKlB,uDAAuD;iBAC5C,QAAQ;IAKnB,gCAAgC;iBAExB,CAAC,OAAO,kBAAkB,EAAE,MAAM,OAAO,kBAAkB,CAAC,KACjE,QAAQ;IAKX,eAAe;eACN,QAAQ;IAKjB,mBAAmB;mBACN,QAAQ;IAKrB,sCAAsC;oBACxB,QAAQ;IAMtB,wBAAwB;uBACL,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,KAAK,OAAO,KAAG,QAAQ;CAItE,CAAC;AAEF,eAAe,SAAS,CAAC"}
1
+ {"version":3,"file":"AuthGuard.d.ts","sourceRoot":"","sources":["../../src/routing/AuthGuard.tsx"],"names":[],"mappings":"AAGA;;;;;;;GAOG;AAEH,OAAO,EAKL,KAAK,SAAS,EACd,KAAK,aAAa,EACnB,MAAM,OAAO,CAAC;AAGf,OAAO,EAGL,UAAU,EACV,kBAAkB,EAClB,KAAK,QAAQ,EACd,MAAM,gBAAgB,CAAC;AAYxB;;GAEG;AACH,UAAU,cAAc;IACtB,wCAAwC;IACxC,IAAI,EAAE,QAAQ,GAAG,KAAK,CAAC;IACvB,wCAAwC;IACxC,QAAQ,EAAE,SAAS,CAAC;IACpB,6CAA6C;IAC7C,QAAQ,CAAC,EAAE,aAAa,CAAC;CAC1B;AAED;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,SAAS,CAAC,EACxB,IAAI,EACJ,QAAQ,EACR,QAAQ,EAAE,QAAiB,GAC5B,EAAE,cAAc,2CA2HhB;AAED;;;;;;;GAOG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,QAAQ,GAAG,KAAK,GAAG,OAAO,CAG9D;AAED;;GAEG;AACH,eAAO,MAAM,YAAY,uBAAiB,CAAC;AAE3C;;;;;;GAMG;AACH,wBAAgB,WAAW,IACvB,OAAO,UAAU,CAAC,KAAK,GACvB,OAAO,UAAU,CAAC,IAAI,GACtB,OAAO,UAAU,CAAC,KAAK,CAS1B;AAED;;;;;;GAMG;AACH,wBAAgB,UAAU,CACxB,IAAI,EACA,OAAO,UAAU,CAAC,KAAK,GACvB,OAAO,UAAU,CAAC,IAAI,GACtB,OAAO,UAAU,CAAC,KAAK,GAC1B,OAAO,CAIT;AAED;;;;;;GAMG;AACH,wBAAgB,YAAY;;;;;;EAW3B;AAED;;;;;;GAMG;AACH,wBAAgB,QAAQ,CAAC,CAAC,SAAS,MAAM,EACvC,SAAS,EAAE,aAAa,CAAC,CAAC,CAAC,EAC3B,IAAI,EAAE,QAAQ,GAAG,KAAK,WAEW,CAAC,6CAOnC;AAED;;;;;;GAMG;AACH,eAAO,MAAM,gBAAgB;IAC3B,iCAAiC;kBACrB,KAAK;IAEjB,oCAAoC;oBACtB,QAAQ;IAEtB,yCAAyC;gBAC/B,QAAQ;IAKlB,uDAAuD;iBAC5C,QAAQ;IAKnB,gCAAgC;iBAExB,CAAC,OAAO,kBAAkB,EAAE,MAAM,OAAO,kBAAkB,CAAC,KACjE,QAAQ;IAKX,eAAe;eACN,QAAQ;IAKjB,mBAAmB;mBACN,QAAQ;IAKrB,sCAAsC;oBACxB,QAAQ;IAMtB,wBAAwB;uBACL,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,KAAK,OAAO,KAAG,QAAQ;CAItE,CAAC;AAEF,eAAe,SAAS,CAAC"}
@@ -5,14 +5,13 @@ import { Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs } from "react/jsx-run
5
5
  * @fileoverview AuthGuard component
6
6
  * @description Protects routes based on authentication configuration
7
7
  *
8
- * @version 0.0.1
8
+ * @version 0.0.3
9
9
  * @since 0.0.1
10
10
  * @author AMBROISE PARK Consulting
11
11
  */
12
12
  import { useEffect, useState, lazy, Suspense, } from 'react';
13
13
  import { Stack } from '@donotdev/components';
14
- import { useAuthConfig } from '@donotdev/core';
15
- import { USER_ROLES, SUBSCRIPTION_TIERS } from '@donotdev/core';
14
+ import { useAuthConfig, FEATURE_STATUS, USER_ROLES, SUBSCRIPTION_TIERS, } from '@donotdev/core';
16
15
  // Platform-specific hooks via conditional exports
17
16
  import { useRedirectGuard, useNavigate } from '@donotdev/ui/routing/hooks';
18
17
  import Loader from '../components/common/Loader';
@@ -34,15 +33,15 @@ const CookieConsent = lazy(() => import('../components/cookie-consent/CookieCons
34
33
  * - 'pro': Professional features
35
34
  * - 'premium': Premium features
36
35
  *
37
- * @version 0.0.1
36
+ * @version 0.0.3
38
37
  * @since 0.0.1
39
38
  * @author AMBROISE PARK Consulting
40
39
  */
41
40
  export function AuthGuard({ auth, children, fallback: Fallback = Loader, }) {
42
41
  const navigate = useNavigate();
43
42
  const user = useAuthSafe('user');
44
- const canAccess = useAuthSafe('canAccess');
45
- const authStateChecked = useAuthSafe('authStateChecked');
43
+ const can = useAuthSafe('can');
44
+ const status = useAuthSafe('status');
46
45
  const [slowWarning, setSlowWarning] = useState(false);
47
46
  // Check if redirect should happen BEFORE rendering fallback
48
47
  const { shouldRedirect, redirectTo, isChecking } = useRedirectGuard({
@@ -52,13 +51,13 @@ export function AuthGuard({ auth, children, fallback: Fallback = Loader, }) {
52
51
  // Soft timeout at 5 seconds - show warning, don't force redirect
53
52
  // Firebase auth typically resolves in 200ms-800ms (broadband), 1-3s (cold start)
54
53
  const timer = setTimeout(() => {
55
- if (!authStateChecked) {
54
+ if (status === FEATURE_STATUS.INITIALIZING) {
56
55
  setSlowWarning(true);
57
56
  console.warn('[AuthGuard] Auth taking longer than usual (>5s)');
58
57
  }
59
58
  }, 5000);
60
59
  return () => clearTimeout(timer);
61
- }, [authStateChecked]);
60
+ }, [status]);
62
61
  // Redirect if needed
63
62
  useEffect(() => {
64
63
  if (shouldRedirect && redirectTo) {
@@ -75,7 +74,7 @@ export function AuthGuard({ auth, children, fallback: Fallback = Loader, }) {
75
74
  return _jsx(Loader, {});
76
75
  }
77
76
  // Show slow auth warning after 5s timeout (only if not redirecting)
78
- if (!authStateChecked && slowWarning) {
77
+ if (status === FEATURE_STATUS.INITIALIZING && slowWarning) {
79
78
  return (_jsx(Stack, { align: "center", justify: "center", style: { padding: 'var(--gap-md)', minHeight: '100vh' }, children: _jsxs("div", { className: "dndev-w-full", style: { maxWidth: '28rem', textAlign: 'center' }, children: [_jsx("h2", { style: { marginBottom: 'var(--gap-md)' }, children: "Loading is taking longer than usual" }), _jsx("p", { style: {
80
79
  marginBottom: 'var(--gap-md)',
81
80
  color: 'var(--muted-foreground)',
@@ -89,7 +88,7 @@ export function AuthGuard({ auth, children, fallback: Fallback = Loader, }) {
89
88
  }, children: "Refresh Page" })] }) }));
90
89
  }
91
90
  // Still checking auth state (but not redirecting) - show fallback
92
- if (!authStateChecked) {
91
+ if (status === FEATURE_STATUS.INITIALIZING) {
93
92
  return _jsx(Fallback, {});
94
93
  }
95
94
  // Check if it's a consent issue (no functional cookies for auth)
@@ -98,29 +97,33 @@ export function AuthGuard({ auth, children, fallback: Fallback = Loader, }) {
98
97
  typeof auth === 'object' &&
99
98
  auth.required &&
100
99
  !user &&
101
- canAccess &&
102
- !canAccess(auth)) {
100
+ can &&
101
+ !can.navigate(auth)) {
103
102
  return (_jsx(Stack, { align: "center", justify: "center", style: { padding: 'var(--gap-md)', minHeight: '100vh' }, children: _jsxs("div", { className: "dndev-w-full", style: { maxWidth: '28rem' }, children: [_jsx("h2", { style: { marginBottom: 'var(--gap-md)' }, children: "Authentication Required" }), _jsx("p", { style: { marginBottom: 'var(--gap-md)' }, children: "This page requires authentication. Please accept functional cookies to continue." }), _jsx(Suspense, { fallback: _jsx("div", { children: "Loading consent..." }), children: _jsx(CookieConsent, {}) })] }) }));
104
103
  }
105
104
  // All checks passed, render children
106
105
  return _jsx(_Fragment, { children: children });
107
106
  }
108
107
  /**
109
- * Hook to check if current user can access a route with given auth config
108
+ * Hook to check if current user can navigate to a route with given auth config
110
109
  * ONLY uses store - single source of truth!
111
110
  *
112
- * @version 0.0.1
111
+ * @version 0.0.3
113
112
  * @since 0.0.1
114
113
  * @author AMBROISE PARK Consulting
115
114
  */
116
- export function useCanAccess(auth) {
117
- const canAccess = useAuthSafe('canAccess');
118
- return canAccess?.(auth) ?? false;
115
+ export function useCanNavigate(auth) {
116
+ const can = useAuthSafe('can');
117
+ return can?.navigate(auth) ?? false;
119
118
  }
119
+ /**
120
+ * @deprecated Use useCanNavigate instead
121
+ */
122
+ export const useCanAccess = useCanNavigate;
120
123
  /**
121
124
  * Hook to get current user's role - directly from store
122
125
  *
123
- * @version 0.0.1
126
+ * @version 0.0.3
124
127
  * @since 0.0.1
125
128
  * @author AMBROISE PARK Consulting
126
129
  */
@@ -132,7 +135,7 @@ export function useUserRole() {
132
135
  /**
133
136
  * Hook to check specific role - directly from store
134
137
  *
135
- * @version 0.0.1
138
+ * @version 0.0.3
136
139
  * @since 0.0.1
137
140
  * @author AMBROISE PARK Consulting
138
141
  */
@@ -144,7 +147,7 @@ export function useHasRole(role) {
144
147
  /**
145
148
  * Hook to get all auth state for debugging
146
149
  *
147
- * @version 0.0.1
150
+ * @version 0.0.3
148
151
  * @since 0.0.1
149
152
  * @author AMBROISE PARK Consulting
150
153
  */
@@ -163,7 +166,7 @@ export function useAuthState() {
163
166
  /**
164
167
  * HOC to wrap components with auth protection
165
168
  *
166
- * @version 0.0.1
169
+ * @version 0.0.3
167
170
  * @since 0.0.1
168
171
  * @author AMBROISE PARK Consulting
169
172
  */
@@ -174,7 +177,7 @@ export function withAuth(Component, auth) {
174
177
  /**
175
178
  * Utility to create auth configs
176
179
  *
177
- * @version 0.0.1
180
+ * @version 0.0.3
178
181
  * @since 0.0.1
179
182
  * @author AMBROISE PARK Consulting
180
183
  */
@@ -2,7 +2,7 @@ import { type ReactNode, type ComponentType, type AnchorHTMLAttributes } from 'r
2
2
  /**
3
3
  * Link component props interface
4
4
  *
5
- * @version 0.0.1
5
+ * @version 0.0.3
6
6
  * @since 0.0.1
7
7
  * @author AMBROISE PARK Consulting
8
8
  */
@@ -21,7 +21,7 @@ export interface LinkProps extends AnchorHTMLAttributes<HTMLAnchorElement> {
21
21
  /**
22
22
  * Link component
23
23
  *
24
- * @version 0.0.1
24
+ * @version 0.0.3
25
25
  * @since 0.0.1
26
26
  * @author AMBROISE PARK Consulting
27
27
  */
@@ -5,7 +5,7 @@ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-run
5
5
  * @fileoverview Link component
6
6
  * @description Platform-agnostic link component for navigation
7
7
  *
8
- * @version 0.0.1
8
+ * @version 0.0.3
9
9
  * @since 0.0.1
10
10
  * @author AMBROISE PARK Consulting
11
11
  */
@@ -19,7 +19,7 @@ import { Icon } from '../components/common/icon';
19
19
  /**
20
20
  * Link component
21
21
  *
22
- * @version 0.0.1
22
+ * @version 0.0.3
23
23
  * @since 0.0.1
24
24
  * @author AMBROISE PARK Consulting
25
25
  */
@@ -1 +1 @@
1
- "use client";import{useCallback as h}from"react";import{useRouter as f}from"next/navigation";import{isClient as A,useOverlayStore as S}from"@donotdev/core";function d(){let e=f(),t=S(r=>r.closeAll);return h((r,c)=>{if(r==="back")return t(),e.back();if(t(),c?.preserveScroll&&A()){let o=window.scrollY;c?.replace?e.replace(r):e.push(r),requestAnimationFrame(()=>{window.scrollTo({top:o,behavior:"auto"})});return}return c?.replace?e.replace(r):e.push(r)},[e,t])}function y(){let e=f();return h(()=>e.back(),[e])}function k(){let e=f();return h(()=>e.refresh(),[e])}function C(){let e=f();return h(t=>e.prefetch(t),[e])}import{usePathname as b,useSearchParams as v}from"next/navigation";function l(){let e=b(),t=v(),r=t.toString()?`?${t.toString()}`:"";return{pathname:e||"/",search:r,hash:"",state:null}}import{useParams as w}from"next/navigation";function T(){return w()}import{useSearchParams as N}from"next/navigation";function g(){return N()}import{usePathname as $}from"next/navigation";function G(e){let t=$(),r=e.replace(/:[^/]+/g,"([^/]+)").replace(/\*/g,".*"),c=new RegExp(`^${r}$`),o=t.match(c);if(!o)return null;let s=e.match(/:[^/]+/g)?.map(a=>a.slice(1))||[],n={};return s.forEach((a,i)=>{n[a]=o[i+1]||""}),{params:n,pathname:t,pattern:e}}import{useCallback as R}from"react";function K(){let e=g(),t=d(),r=l(),c=R((n,a)=>{let i=new URLSearchParams(e.toString());i.set(n,a);let m=i.toString(),P=`${r.pathname||"/"}${m?`?${m}`:""}`;t(P)},[e,t,r.pathname]),o=R(n=>{let a=new URLSearchParams(e.toString());a.delete(n);let i=a.toString(),u=`${r.pathname||"/"}${i?`?${i}`:""}`;t(u)},[e,t,r.pathname]),s=R(()=>{let n=r.pathname||"/";t(n)},[t,r.pathname]);return{query:e,setQuery:c,removeQuery:o,clearQueries:s}}import{useMemo as U}from"react";import{isClient as Q}from"@donotdev/core";import{useAuthConfig as E}from"@donotdev/core";import{DEGRADED_AUTH_API as O}from"@donotdev/core";import*as I from"@donotdev/auth";var x=I?.useAuth;function L(e){return O[e]}function p(e){return x?x(e):L(e)}function M(e={}){let{auth:t,redirectTo:r,condition:c}=e;if(!Q())return{shouldRedirect:!1,redirectTo:null,isChecking:!1};let o=l(),s=E(),n=p("user"),a=p("canAccess"),i=p("authStateChecked");return U(()=>{if(!i)return{shouldRedirect:!1,redirectTo:null,isChecking:!0};if(c){let u=c(n,i);return{shouldRedirect:u,redirectTo:u&&r||null,isChecking:!1}}if(t!==!1&&t!==void 0){if(!a)return{shouldRedirect:!1,redirectTo:null,isChecking:!1};if(!a(t)){let u=null;return typeof t=="object"&&t.required&&!n?o.search.includes("code=")||o.search.includes("state=")||o.search.includes("error=")?u=`${s.authRoute}${o.search}`:u=s.authRoute:typeof t=="object"&&t.role?u=s.roleRoute:typeof t=="object"&&t.tier?u=s.tierRoute:u=s.roleRoute,{shouldRedirect:!0,redirectTo:r||u,isChecking:!1}}}return{shouldRedirect:!1,redirectTo:null,isChecking:!1}},[t,i,n,a,c,r,o.search,s.authRoute,s.roleRoute,s.tierRoute])}export{y as useBack,l as useLocation,G as useMatch,d as useNavigate,T as useParams,C as usePrefetch,K as useQueryParams,M as useRedirectGuard,k as useRefresh,g as useSearchParams};
1
+ "use client";import{useCallback as f}from"react";import{useRouter as h}from"next/navigation";import{isClient as x,useOverlayStore as S}from"@donotdev/core";function d(){let e=h(),t=S(r=>r.closeAll);return f((r,i)=>{if(r==="back")return t(),e.back();if(t(),i?.preserveScroll&&x()){let o=window.scrollY;i?.replace?e.replace(r):e.push(r),requestAnimationFrame(()=>{window.scrollTo({top:o,behavior:"auto"})});return}return i?.replace?e.replace(r):e.push(r)},[e,t])}function y(){let e=h();return f(()=>e.back(),[e])}function k(){let e=h();return f(()=>e.refresh(),[e])}function T(){let e=h();return f(t=>e.prefetch(t),[e])}import{usePathname as v,useSearchParams as b}from"next/navigation";function l(){let e=v(),t=b(),r=t.toString()?`?${t.toString()}`:"";return{pathname:e||"/",search:r,hash:"",state:null}}import{useParams as w}from"next/navigation";function C(){return w()}import{useSearchParams as I}from"next/navigation";function g(){return I()}import{usePathname as N}from"next/navigation";function G(e){let t=N(),r=e.replace(/:[^/]+/g,"([^/]+)").replace(/\*/g,".*"),i=new RegExp(`^${r}$`),o=t.match(i);if(!o)return null;let s=e.match(/:[^/]+/g)?.map(a=>a.slice(1))||[],n={};return s.forEach((a,c)=>{n[a]=o[c+1]||""}),{params:n,pathname:t,pattern:e}}import{useCallback as R}from"react";function $(){let e=g(),t=d(),r=l(),i=R((n,a)=>{let c=new URLSearchParams(e.toString());c.set(n,a);let m=c.toString(),P=`${r.pathname||"/"}${m?`?${m}`:""}`;t(P)},[e,t,r.pathname]),o=R(n=>{let a=new URLSearchParams(e.toString());a.delete(n);let c=a.toString(),u=`${r.pathname||"/"}${c?`?${c}`:""}`;t(u)},[e,t,r.pathname]),s=R(()=>{let n=r.pathname||"/";t(n)},[t,r.pathname]);return{query:e,setQuery:i,removeQuery:o,clearQueries:s}}import{useMemo as L}from"react";import{isClient as E,FEATURE_STATUS as Q}from"@donotdev/core";import{useAuthConfig as F}from"@donotdev/core";import{DEGRADED_AUTH_API as K}from"@donotdev/core";import*as O from"@donotdev/auth";var A=O?.useAuth;function U(e){return K[e]}function p(e){return A?A(e):U(e)}function M(e={}){let{auth:t,redirectTo:r,condition:i}=e;if(!E())return{shouldRedirect:!1,redirectTo:null,isChecking:!1};let o=l(),s=F(),n=p("user"),a=p("can"),c=p("status");return L(()=>{if(c===Q.INITIALIZING)return{shouldRedirect:!1,redirectTo:null,isChecking:!0};if(i){let u=i(n,c);return{shouldRedirect:u,redirectTo:u&&r||null,isChecking:!1}}if(t!==!1&&t!==void 0){if(!a)return{shouldRedirect:!1,redirectTo:null,isChecking:!1};if(!a.navigate(t)){let u=null;return typeof t=="object"&&t.required&&!n?o.search.includes("code=")||o.search.includes("state=")||o.search.includes("error=")?u=`${s.authRoute}${o.search}`:u=s.authRoute:typeof t=="object"&&t.role?u=s.roleRoute:typeof t=="object"&&t.tier?u=s.tierRoute:u=s.roleRoute,{shouldRedirect:!0,redirectTo:r||u,isChecking:!1}}}return{shouldRedirect:!1,redirectTo:null,isChecking:!1}},[t,c,n,a,i,r,o.search,s.authRoute,s.roleRoute,s.tierRoute])}export{y as useBack,l as useLocation,G as useMatch,d as useNavigate,C as useParams,T as usePrefetch,$ as useQueryParams,M as useRedirectGuard,k as useRefresh,g as useSearchParams};
@@ -1 +1 @@
1
- "use client";import{useCallback as m}from"react";import{useNavigate as A}from"react-router-dom";import{isClient as x,useOverlayStore as S}from"@donotdev/core";function p(){let e=A(),t=S(r=>r.closeAll);return m((r,i)=>r==="back"?(t(),e(-1)):(t(),i?.replace?e(r,{replace:!0}):e(r)),[e,t])}function y(){let e=A();return m(()=>e(-1),[e])}function k(){return m(()=>{x()&&window.location.reload()},[])}function v(){return m(e=>{},[])}import{useLocation as C}from"react-router-dom";function l(){return C()}import{useParams as b}from"react-router-dom";function T(){return b()}import{useSearchParams as w}from"react-router-dom";function d(){return w()[0]}import{useMatch as G}from"react-router-dom";function K(e){return G(e)}import{useCallback as R}from"react";function O(){let e=d(),t=p(),r=l(),i=R((n,u)=>{let a=new URLSearchParams(e.toString());a.set(n,u);let f=a.toString(),g=`${r.pathname||"/"}${f?`?${f}`:""}`;t(g)},[e,t,r.pathname]),c=R(n=>{let u=new URLSearchParams(e.toString());u.delete(n);let a=u.toString(),o=`${r.pathname||"/"}${a?`?${a}`:""}`;t(o)},[e,t,r.pathname]),s=R(()=>{let n=r.pathname||"/";t(n)},[t,r.pathname]);return{query:e,setQuery:i,removeQuery:c,clearQueries:s}}import{useMemo as $}from"react";import{isClient as M}from"@donotdev/core";import{useAuthConfig as U}from"@donotdev/core";import{DEGRADED_AUTH_API as I}from"@donotdev/core";import*as L from"@donotdev/auth";var P=L?.useAuth;function N(e){return I[e]}function h(e){return P?P(e):N(e)}function Q(e={}){let{auth:t,redirectTo:r,condition:i}=e;if(!M())return{shouldRedirect:!1,redirectTo:null,isChecking:!1};let c=l(),s=U(),n=h("user"),u=h("canAccess"),a=h("authStateChecked");return $(()=>{if(!a)return{shouldRedirect:!1,redirectTo:null,isChecking:!0};if(i){let o=i(n,a);return{shouldRedirect:o,redirectTo:o&&r||null,isChecking:!1}}if(t!==!1&&t!==void 0){if(!u)return{shouldRedirect:!1,redirectTo:null,isChecking:!1};if(!u(t)){let o=null;return typeof t=="object"&&t.required&&!n?c.search.includes("code=")||c.search.includes("state=")||c.search.includes("error=")?o=`${s.authRoute}${c.search}`:o=s.authRoute:typeof t=="object"&&t.role?o=s.roleRoute:typeof t=="object"&&t.tier?o=s.tierRoute:o=s.roleRoute,{shouldRedirect:!0,redirectTo:r||o,isChecking:!1}}}return{shouldRedirect:!1,redirectTo:null,isChecking:!1}},[t,a,n,u,i,r,c.search,s.authRoute,s.roleRoute,s.tierRoute])}export{y as useBack,l as useLocation,K as useMatch,p as useNavigate,T as useParams,v as usePrefetch,O as useQueryParams,Q as useRedirectGuard,k as useRefresh,d as useSearchParams};
1
+ "use client";import{useCallback as m}from"react";import{useNavigate as A}from"react-router-dom";import{isClient as x,useOverlayStore as S}from"@donotdev/core";function p(){let e=A(),t=S(r=>r.closeAll);return m((r,i)=>r==="back"?(t(),e(-1)):(t(),i?.replace?e(r,{replace:!0}):e(r)),[e,t])}function y(){let e=A();return m(()=>e(-1),[e])}function v(){return m(()=>{x()&&window.location.reload()},[])}function k(){return m(e=>{},[])}import{useLocation as T}from"react-router-dom";function l(){return T()}import{useParams as C}from"react-router-dom";function I(){return C()}import{useSearchParams as b}from"react-router-dom";function d(){return b()[0]}import{useMatch as G}from"react-router-dom";function w(e){return G(e)}import{useCallback as R}from"react";function N(){let e=d(),t=p(),r=l(),i=R((n,u)=>{let a=new URLSearchParams(e.toString());a.set(n,u);let f=a.toString(),g=`${r.pathname||"/"}${f?`?${f}`:""}`;t(g)},[e,t,r.pathname]),c=R(n=>{let u=new URLSearchParams(e.toString());u.delete(n);let a=u.toString(),o=`${r.pathname||"/"}${a?`?${a}`:""}`;t(o)},[e,t,r.pathname]),s=R(()=>{let n=r.pathname||"/";t(n)},[t,r.pathname]);return{query:e,setQuery:i,removeQuery:c,clearQueries:s}}import{useMemo as U}from"react";import{isClient as $,FEATURE_STATUS as M}from"@donotdev/core";import{useAuthConfig as Q}from"@donotdev/core";import{DEGRADED_AUTH_API as K}from"@donotdev/core";import*as L from"@donotdev/auth";var P=L?.useAuth;function O(e){return K[e]}function h(e){return P?P(e):O(e)}function E(e={}){let{auth:t,redirectTo:r,condition:i}=e;if(!$())return{shouldRedirect:!1,redirectTo:null,isChecking:!1};let c=l(),s=Q(),n=h("user"),u=h("can"),a=h("status");return U(()=>{if(a===M.INITIALIZING)return{shouldRedirect:!1,redirectTo:null,isChecking:!0};if(i){let o=i(n,a);return{shouldRedirect:o,redirectTo:o&&r||null,isChecking:!1}}if(t!==!1&&t!==void 0){if(!u)return{shouldRedirect:!1,redirectTo:null,isChecking:!1};if(!u.navigate(t)){let o=null;return typeof t=="object"&&t.required&&!n?c.search.includes("code=")||c.search.includes("state=")||c.search.includes("error=")?o=`${s.authRoute}${c.search}`:o=s.authRoute:typeof t=="object"&&t.role?o=s.roleRoute:typeof t=="object"&&t.tier?o=s.tierRoute:o=s.roleRoute,{shouldRedirect:!0,redirectTo:r||o,isChecking:!1}}}return{shouldRedirect:!1,redirectTo:null,isChecking:!1}},[t,a,n,u,i,r,c.search,s.authRoute,s.roleRoute,s.tierRoute])}export{y as useBack,l as useLocation,w as useMatch,p as useNavigate,I as useParams,k as usePrefetch,N as useQueryParams,E as useRedirectGuard,v as useRefresh,d as useSearchParams};
@@ -1,11 +1,11 @@
1
- import type { PageAuth } from '@donotdev/core';
1
+ import type { PageAuth, FeatureStatus } from '@donotdev/core';
2
2
  export interface RedirectGuardOptions {
3
3
  /** Auth configuration for this route */
4
4
  auth?: PageAuth | false;
5
5
  /** Custom redirect target (overrides auth config defaults) */
6
6
  redirectTo?: string | null;
7
7
  /** Custom condition function to check if redirect should happen */
8
- condition?: (user: any, authStateChecked: boolean) => boolean;
8
+ condition?: (user: any, status: FeatureStatus) => boolean;
9
9
  }
10
10
  export interface RedirectGuardResult {
11
11
  /** Whether redirect should happen */
@@ -16,47 +16,13 @@ export interface RedirectGuardResult {
16
16
  isChecking: boolean;
17
17
  }
18
18
  /**
19
-
20
19
  * Hook that checks if redirect should happen before render
21
-
22
20
  *
23
-
24
21
  * Prevents content flash by determining redirect state synchronously.
25
-
26
22
  * Returns safe defaults on server (SSR-safe).
27
-
28
23
  *
29
-
30
24
  * @param options - Redirect guard configuration
31
-
32
25
  * @returns Redirect guard state
33
-
34
- *
35
-
36
- * @example
37
-
38
- * ```tsx
39
-
40
- * // PricingPage: redirect authenticated users to /purchase
41
-
42
- * const { shouldRedirect, redirectTo, isChecking } = useRedirectGuard({
43
-
44
- * condition: (user) => !!user,
45
-
46
- * redirectTo: '/purchase'
47
-
48
- * });
49
-
50
- *
51
-
52
- * if (shouldRedirect || isChecking) {
53
-
54
- * return <Loader />;
55
-
56
- * }
57
-
58
- * ```
59
-
60
26
  */
61
27
  export declare function useRedirectGuard(options?: RedirectGuardOptions): RedirectGuardResult;
62
28
  //# sourceMappingURL=useRedirectGuard.next.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"useRedirectGuard.next.d.ts","sourceRoot":"","sources":["../../../src/routing/hooks/useRedirectGuard.next.ts"],"names":[],"mappings":"AAyBA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAM/C,MAAM,WAAW,oBAAoB;IACnC,wCAAwC;IAExC,IAAI,CAAC,EAAE,QAAQ,GAAG,KAAK,CAAC;IAExB,8DAA8D;IAE9D,UAAU,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAE3B,mEAAmE;IAEnE,SAAS,CAAC,EAAE,CAAC,IAAI,EAAE,GAAG,EAAE,gBAAgB,EAAE,OAAO,KAAK,OAAO,CAAC;CAC/D;AAED,MAAM,WAAW,mBAAmB;IAClC,qCAAqC;IAErC,cAAc,EAAE,OAAO,CAAC;IAExB,uDAAuD;IAEvD,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAE1B,gDAAgD;IAEhD,UAAU,EAAE,OAAO,CAAC;CACrB;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA0CG;AAEH,wBAAgB,gBAAgB,CAC9B,OAAO,GAAE,oBAAyB,GACjC,mBAAmB,CAkJrB"}
1
+ {"version":3,"file":"useRedirectGuard.next.d.ts","sourceRoot":"","sources":["../../../src/routing/hooks/useRedirectGuard.next.ts"],"names":[],"mappings":"AAgBA,OAAO,KAAK,EAAE,QAAQ,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAK9D,MAAM,WAAW,oBAAoB;IACnC,wCAAwC;IACxC,IAAI,CAAC,EAAE,QAAQ,GAAG,KAAK,CAAC;IACxB,8DAA8D;IAC9D,UAAU,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,mEAAmE;IACnE,SAAS,CAAC,EAAE,CAAC,IAAI,EAAE,GAAG,EAAE,MAAM,EAAE,aAAa,KAAK,OAAO,CAAC;CAC3D;AAED,MAAM,WAAW,mBAAmB;IAClC,qCAAqC;IACrC,cAAc,EAAE,OAAO,CAAC;IACxB,uDAAuD;IACvD,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,gDAAgD;IAChD,UAAU,EAAE,OAAO,CAAC;CACrB;AAED;;;;;;;;GAQG;AACH,wBAAgB,gBAAgB,CAC9B,OAAO,GAAE,oBAAyB,GACjC,mBAAmB,CA4GrB"}