@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
|
@@ -18,6 +18,10 @@ export interface DnDevSidebarProps {
|
|
|
18
18
|
*
|
|
19
19
|
* Structure: aside.sidebar > nav.sidebar-nav + div.resize-handle
|
|
20
20
|
* Resize logic lives on aside directly. No wrapper components.
|
|
21
|
+
*
|
|
22
|
+
* @critical The `<aside>` MUST have `role="navigation"` — ALL CSS in layout-variables.css
|
|
23
|
+
* targets `aside[role='navigation'].sidebar`. Removing it silently breaks every sidebar feature.
|
|
24
|
+
* DO NOT remove or change role="navigation" under any circumstance.
|
|
21
25
|
*/
|
|
22
26
|
declare function DnDevSidebarComponent({ top, content, bottom, defaultWidth, minWidth, maxWidth, }: DnDevSidebarProps): ReactNode;
|
|
23
27
|
export declare const DnDevSidebar: import("react").MemoExoticComponent<typeof DnDevSidebarComponent>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"DnDevSidebar.d.ts","sourceRoot":"","sources":["../../../../src/internal/layout/zones/DnDevSidebar.tsx"],"names":[],"mappings":"AAsBA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAKvC,MAAM,WAAW,iBAAiB;IAChC,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;IAC1B,6CAA6C;IAC7C,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,gDAAgD;IAChD,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,iDAAiD;IACjD,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED
|
|
1
|
+
{"version":3,"file":"DnDevSidebar.d.ts","sourceRoot":"","sources":["../../../../src/internal/layout/zones/DnDevSidebar.tsx"],"names":[],"mappings":"AAsBA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAKvC,MAAM,WAAW,iBAAiB;IAChC,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;IAC1B,6CAA6C;IAC7C,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,gDAAgD;IAChD,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,iDAAiD;IACjD,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED;;;;;;;;;GASG;AACH,iBAAS,qBAAqB,CAAC,EAC7B,GAAG,EACH,OAAO,EACP,MAAM,EACN,YAAiD,EACjD,QAAyC,EACzC,QAAyC,GAC1C,EAAE,iBAAiB,GAAG,SAAS,CAyM/B;AAED,eAAO,MAAM,YAAY,mEAA8B,CAAC"}
|
|
@@ -23,6 +23,10 @@ const RESIZE_HANDLE_WIDTH = 6;
|
|
|
23
23
|
*
|
|
24
24
|
* Structure: aside.sidebar > nav.sidebar-nav + div.resize-handle
|
|
25
25
|
* Resize logic lives on aside directly. No wrapper components.
|
|
26
|
+
*
|
|
27
|
+
* @critical The `<aside>` MUST have `role="navigation"` — ALL CSS in layout-variables.css
|
|
28
|
+
* targets `aside[role='navigation'].sidebar`. Removing it silently breaks every sidebar feature.
|
|
29
|
+
* DO NOT remove or change role="navigation" under any circumstance.
|
|
26
30
|
*/
|
|
27
31
|
function DnDevSidebarComponent({ top, content, bottom, defaultWidth = DEFAULT_SLOTS.sidebar.defaultWidth, minWidth = DEFAULT_SLOTS.sidebar.minWidth, maxWidth = DEFAULT_SLOTS.sidebar.maxWidth, }) {
|
|
28
32
|
// Resize state
|
|
@@ -158,6 +162,14 @@ function DnDevSidebarComponent({ top, content, bottom, defaultWidth = DEFAULT_SL
|
|
|
158
162
|
break;
|
|
159
163
|
}
|
|
160
164
|
};
|
|
161
|
-
return (
|
|
165
|
+
return (
|
|
166
|
+
/**
|
|
167
|
+
* CRITICAL: role="navigation" is required.
|
|
168
|
+
* ALL sidebar CSS selectors in layout-variables.css use `aside[role='navigation'].sidebar`.
|
|
169
|
+
* Removing role="navigation" breaks: grid placement, display:none for no-sidebar presets,
|
|
170
|
+
* resize handle styles, collapsed styles — essentially ALL sidebar behavior.
|
|
171
|
+
* aria-label provides the accessible name. Both attributes are required.
|
|
172
|
+
*/
|
|
173
|
+
_jsxs("aside", { ref: asideRef, role: "navigation", "aria-label": "Site navigation", className: "sidebar", "data-dragging": isDragging, "data-collapsed": isCollapsed, children: [top && _jsx("div", { className: "sidebar-top", children: top }), _jsx("div", { className: "sidebar-content", children: content }), bottom && _jsx("div", { className: "sidebar-bottom", children: bottom }), _jsx("div", { className: "dndev-sidebar-resize-handle", onPointerDown: handlePointerDown, onDoubleClick: toggleCollapse, onKeyDown: handleKeyDown, role: "separator", "aria-label": "Resize sidebar. Double-click or Enter to toggle. Home to collapse, End to fit content.", "aria-valuenow": sidebarWidth, "aria-valuemin": minWidth, "aria-valuemax": maxWidth, "aria-orientation": "vertical", tabIndex: 0 })] }));
|
|
162
174
|
}
|
|
163
175
|
export const DnDevSidebar = memo(DnDevSidebarComponent);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"NavigationProvider.d.ts","sourceRoot":"","sources":["../../../src/internal/providers/NavigationProvider.tsx"],"names":[],"mappings":"AAgCA,OAAO,EAAkB,mBAAmB,EAAE,MAAM,kBAAkB,CAAC;AAIvE,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;
|
|
1
|
+
{"version":3,"file":"NavigationProvider.d.ts","sourceRoot":"","sources":["../../../src/internal/providers/NavigationProvider.tsx"],"names":[],"mappings":"AAgCA,OAAO,EAAkB,mBAAmB,EAAE,MAAM,kBAAkB,CAAC;AAIvE,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAIvC;;GAEG;AACH,KAAK,SAAS,GAAG,UAAU,CAAC,OAAO,mBAAmB,CAAC,CAAC;AAExD;;GAEG;AACH,UAAU,uBAAuB;IAC/B,6CAA6C;IAC7C,MAAM,EAAE,SAAS,CAAC;IAClB,iFAAiF;IACjF,QAAQ,CAAC,EAAE,SAAS,CAAC;CACtB;AAED;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAgB,kBAAkB,CAAC,EAAE,MAAM,EAAE,EAAE,uBAAuB,2CAkBrE"}
|
|
@@ -53,20 +53,18 @@ import { useAbortControllerStore, useOverlayStore } from '@donotdev/core';
|
|
|
53
53
|
* @author AMBROISE PARK Consulting
|
|
54
54
|
*/
|
|
55
55
|
export function NavigationProvider({ router }) {
|
|
56
|
-
const abortAll = useAbortControllerStore((state) => state.abortAll);
|
|
57
|
-
const closeAll = useOverlayStore((state) => state.closeAll);
|
|
58
56
|
useEffect(() => {
|
|
59
57
|
// Subscribe to navigation events using router.subscribe()
|
|
60
58
|
// This replaces the useLocation() + useEffect pattern from the old implementation
|
|
61
59
|
const unsubscribe = router.subscribe(() => {
|
|
62
60
|
// When navigation occurs, abort all pending requests and close overlays
|
|
63
61
|
// This prevents memory leaks and race conditions
|
|
64
|
-
abortAll();
|
|
65
|
-
closeAll();
|
|
62
|
+
useAbortControllerStore.getState().abortAll();
|
|
63
|
+
useOverlayStore.getState().closeAll();
|
|
66
64
|
});
|
|
67
65
|
// Cleanup subscription on unmount
|
|
68
66
|
return unsubscribe;
|
|
69
|
-
}, [router
|
|
67
|
+
}, [router]);
|
|
70
68
|
// RouterProvider manages its own children from the router configuration
|
|
71
69
|
// No need to render children prop (kept for backwards compatibility)
|
|
72
70
|
return _jsx(RouterProvider, { router: router });
|
package/dist/next.d.ts
CHANGED
package/dist/next.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"next.d.ts","sourceRoot":"","sources":["../src/next.ts"],"names":[],"mappings":"AAEA;;;;;;;GAOG;AAEH,OAAO,EAAE,kBAAkB,EAAE,MAAM,gCAAgC,CAAC"}
|
|
1
|
+
{"version":3,"file":"next.d.ts","sourceRoot":"","sources":["../src/next.ts"],"names":[],"mappings":"AAEA;;;;;;;GAOG;AAEH,OAAO,EAAE,kBAAkB,EAAE,MAAM,gCAAgC,CAAC;AACpE,OAAO,EACL,gBAAgB,EAChB,OAAO,IAAI,uBAAuB,GACnC,MAAM,+CAA+C,CAAC"}
|
package/dist/next.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ViteAppProviders.d.ts","sourceRoot":"","sources":["../../src/providers/ViteAppProviders.tsx"],"names":[],"mappings":"AAcA,OAAO,aAAa,CAAC;AACrB,OAAO,gBAAgB,CAAC;AACxB,OAAO,sBAAsB,CAAC;AAC9B,OAAO,gBAAgB,CAAC;AACxB,OAAO,gBAAgB,CAAC;AAGxB,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,gBAAgB,CAAC;AA2BxD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAmCG;AACH,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,iBAAiB,
|
|
1
|
+
{"version":3,"file":"ViteAppProviders.d.ts","sourceRoot":"","sources":["../../src/providers/ViteAppProviders.tsx"],"names":[],"mappings":"AAcA,OAAO,aAAa,CAAC;AACrB,OAAO,gBAAgB,CAAC;AACxB,OAAO,sBAAsB,CAAC;AAC9B,OAAO,gBAAgB,CAAC;AACxB,OAAO,gBAAgB,CAAC;AAGxB,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,gBAAgB,CAAC;AA2BxD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAmCG;AACH,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,iBAAiB,2CAmCxD"}
|
|
@@ -8,7 +8,7 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
|
8
8
|
* @since 0.0.1
|
|
9
9
|
* @author AMBROISE PARK Consulting
|
|
10
10
|
*/
|
|
11
|
-
import { lazy, Suspense } from 'react';
|
|
11
|
+
import { lazy, Suspense, useMemo } from 'react';
|
|
12
12
|
// Import virtual modules to populate globalThis._DNDEV_CONFIG_ before any components load
|
|
13
13
|
import 'virtual:env';
|
|
14
14
|
import 'virtual:themes';
|
|
@@ -76,9 +76,7 @@ export function ViteAppProviders(props) {
|
|
|
76
76
|
// Create router instance using React Router v7 data router pattern
|
|
77
77
|
// Virtual modules are loaded at module level (lines 20-26), so routes are available
|
|
78
78
|
// HomePage.tsx is automatically assigned path "/" by RouteDiscovery convention
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
layout,
|
|
82
|
-
});
|
|
79
|
+
// Memoized so the router instance is stable across re-renders (Item 86)
|
|
80
|
+
const router = useMemo(() => createAppRouter({ routeGroups, layout }), [routeGroups, layout]);
|
|
83
81
|
return (_jsxs(AppConfigProvider, { config: config, platform: "vite", children: [_jsx(SentryInitializer, {}), _jsx(ViteStoresInitializer, { customStores: customStores, children: _jsx(Suspense, { fallback: null, children: _jsxs(HelmetProvider, { children: [_jsx(FaviconHead, {}), _jsx(PerformanceHints, {}), _jsx(NavigationProvider, { router: router })] }) }) })] }));
|
|
84
82
|
}
|
|
@@ -78,7 +78,7 @@ export declare function useHasRole(role: typeof USER_ROLES.GUEST | typeof USER_R
|
|
|
78
78
|
export declare function useAuthState(): {
|
|
79
79
|
authenticated: boolean;
|
|
80
80
|
role: string | undefined;
|
|
81
|
-
tier:
|
|
81
|
+
tier: string;
|
|
82
82
|
loading: boolean;
|
|
83
83
|
userId: string | undefined;
|
|
84
84
|
};
|
|
@@ -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;AAEf,OAAO,EAGL,UAAU,EACV,kBAAkB,EAClB,KAAK,QAAQ,EACd,MAAM,gBAAgB,CAAC;AAaxB;;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,
|
|
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;AAEf,OAAO,EAGL,UAAU,EACV,kBAAkB,EAClB,KAAK,QAAQ,EACd,MAAM,gBAAgB,CAAC;AAaxB;;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,2CA6HhB;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"}
|
|
@@ -53,7 +53,9 @@ export function AuthGuard({ auth, children, fallback: Fallback = Loader, }) {
|
|
|
53
53
|
const timer = setTimeout(() => {
|
|
54
54
|
if (status === FEATURE_STATUS.INITIALIZING) {
|
|
55
55
|
setSlowWarning(true);
|
|
56
|
-
|
|
56
|
+
if (process.env.NODE_ENV === 'development') {
|
|
57
|
+
console.warn('[AuthGuard] Auth taking longer than usual (>5s)');
|
|
58
|
+
}
|
|
57
59
|
}
|
|
58
60
|
}, 5000);
|
|
59
61
|
return () => clearTimeout(timer);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"GoTo.d.ts","sourceRoot":"","sources":["../../src/routing/GoTo.tsx"],"names":[],"mappings":"AAaA,OAAO,EAA0B,OAAO,EAAE,MAAM,sBAAsB,CAAC;AAGvE,MAAM,WAAW,SAAS;IACxB;;;OAGG;IACH,OAAO,CAAC,EAAE,CAAC,OAAO,OAAO,CAAC,CAAC,MAAM,OAAO,OAAO,CAAC,CAAC;IACjD,2BAA2B;IAC3B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,6FAA6F;IAC7F,MAAM,CAAC,EAAE,MAAM,IAAI,CAAC;CACrB;AAED;;;;;GAKG;AACH,eAAO,MAAM,IAAI,GAAI,iCAIlB,SAAS,
|
|
1
|
+
{"version":3,"file":"GoTo.d.ts","sourceRoot":"","sources":["../../src/routing/GoTo.tsx"],"names":[],"mappings":"AAaA,OAAO,EAA0B,OAAO,EAAE,MAAM,sBAAsB,CAAC;AAGvE,MAAM,WAAW,SAAS;IACxB;;;OAGG;IACH,OAAO,CAAC,EAAE,CAAC,OAAO,OAAO,CAAC,CAAC,MAAM,OAAO,OAAO,CAAC,CAAC;IACjD,2BAA2B;IAC3B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,6FAA6F;IAC7F,MAAM,CAAC,EAAE,MAAM,IAAI,CAAC;CACrB;AAED;;;;;GAKG;AACH,eAAO,MAAM,IAAI,GAAI,iCAIlB,SAAS,4CA0CX,CAAC;AAEF,eAAe,IAAI,CAAC"}
|
package/dist/routing/GoTo.js
CHANGED
|
@@ -21,8 +21,10 @@ export const GoTo = ({ display = DISPLAY.AUTO, className, onOpen, }) => {
|
|
|
21
21
|
const { t } = useTranslation('dndev');
|
|
22
22
|
const openCommandDialog = useOverlayStore((state) => state.openCommandDialog);
|
|
23
23
|
// Platform-aware shortcut (Mac: ⌘K, others: Ctrl+K)
|
|
24
|
+
// navigator.userAgentData?.platform is modern; navigator.platform is the deprecated fallback
|
|
24
25
|
const isMac = typeof navigator !== 'undefined' &&
|
|
25
|
-
/Mac|iPhone|iPad/.test(navigator
|
|
26
|
+
/Mac|iPhone|iPad/.test(navigator
|
|
27
|
+
.userAgentData?.platform ?? navigator.platform);
|
|
26
28
|
const shortcut = isMac ? '⌘K' : 'Ctrl+K';
|
|
27
29
|
const handleClick = () => {
|
|
28
30
|
openCommandDialog();
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"GoToDialog.d.ts","sourceRoot":"","sources":["../../src/routing/GoToDialog.tsx"],"names":[],"mappings":"AAyBA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,OAAO,CAAC;
|
|
1
|
+
{"version":3,"file":"GoToDialog.d.ts","sourceRoot":"","sources":["../../src/routing/GoToDialog.tsx"],"names":[],"mappings":"AAyBA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,OAAO,CAAC;AAwJ3C;;;GAGG;AACH,QAAA,MAAM,UAAU,EAAE,aAUjB,CAAC;AAEF,eAAe,UAAU,CAAC"}
|
|
@@ -8,7 +8,7 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
|
8
8
|
* @since 0.0.1
|
|
9
9
|
* @author AMBROISE PARK Consulting
|
|
10
10
|
*/
|
|
11
|
-
import {
|
|
11
|
+
import { Link as LinkIcon, Star } from 'lucide-react';
|
|
12
12
|
import { useCallback, useEffect, useRef } from 'react';
|
|
13
13
|
import { Badge, Command, CommandDialog } from '@donotdev/components';
|
|
14
14
|
import { useOverlayStore, useTranslation } from '@donotdev/core';
|
|
@@ -64,12 +64,7 @@ const GoToDialogContent = () => {
|
|
|
64
64
|
});
|
|
65
65
|
}
|
|
66
66
|
if (recentItems.length > 0) {
|
|
67
|
-
const recentCommandItems = recentItems
|
|
68
|
-
.flatMap((item) => createItems([item], true))
|
|
69
|
-
.map((item) => ({
|
|
70
|
-
...item,
|
|
71
|
-
icon: _jsx(Icon, { icon: Clock, className: "dndev-size-sm" }),
|
|
72
|
-
}));
|
|
67
|
+
const recentCommandItems = recentItems.flatMap((item) => createItems([item], true));
|
|
73
68
|
if (recentCommandItems.length > 0) {
|
|
74
69
|
commandGroups.push({
|
|
75
70
|
heading: t('globalGoTo.recent', 'Recent'),
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"GoToInput.d.ts","sourceRoot":"","sources":["../../src/routing/GoToInput.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"GoToInput.d.ts","sourceRoot":"","sources":["../../src/routing/GoToInput.tsx"],"names":[],"mappings":"AA+BA,QAAA,MAAM,SAAS,+CAwEd,CAAC;AAEF,eAAe,SAAS,CAAC"}
|
|
@@ -16,11 +16,12 @@ import { useTranslation } from '@donotdev/core';
|
|
|
16
16
|
/**
|
|
17
17
|
* Navigation input - typeable search that syncs with command dialog
|
|
18
18
|
*/
|
|
19
|
+
/** Detect macOS/iOS for keyboard shortcut label (defaults to ⌘K during SSR) */
|
|
20
|
+
const isMac = typeof navigator !== 'undefined' && /Mac|iPhone|iPad/.test(navigator.userAgent);
|
|
19
21
|
const GoToInput = () => {
|
|
20
22
|
const { t } = useTranslation('dndev');
|
|
21
23
|
const [value, setValue] = useState('');
|
|
22
24
|
const inputRef = useRef(null);
|
|
23
|
-
const openCommandDialog = useOverlayStore((state) => state.openCommandDialog);
|
|
24
25
|
const isCommandDialogOpen = useOverlayStore((state) => state.isCommandDialogOpen);
|
|
25
26
|
// Clear input when dialog closes
|
|
26
27
|
useEffect(() => {
|
|
@@ -29,19 +30,19 @@ const GoToInput = () => {
|
|
|
29
30
|
}
|
|
30
31
|
}, [isCommandDialogOpen]);
|
|
31
32
|
const handleFocus = useCallback(() => {
|
|
32
|
-
openCommandDialog(value);
|
|
33
|
-
}, [
|
|
33
|
+
useOverlayStore.getState().openCommandDialog(value);
|
|
34
|
+
}, [value]);
|
|
34
35
|
const handleKeyDown = useCallback((e) => {
|
|
35
36
|
if (e.key === 'Enter') {
|
|
36
37
|
e.preventDefault();
|
|
37
|
-
openCommandDialog(value);
|
|
38
|
+
useOverlayStore.getState().openCommandDialog(value);
|
|
38
39
|
}
|
|
39
|
-
}, [
|
|
40
|
-
return (_jsxs(Stack, { direction: "row", align: "center", className: "dndev-relative dndev-w-full dndev-max-w-sm", role: "search", children: [_jsx(Search, { className: "dndev-absolute dndev-size-md", style: {
|
|
40
|
+
}, [value]);
|
|
41
|
+
return (_jsxs(Stack, { direction: "row", align: "center", className: "dndev-relative dndev-w-full dndev-max-w-sm", role: "search", children: [_jsx(Search, { className: "dndev-absolute dndev-size-md", style: { insetInlineStart: '0.75rem', opacity: 0.5 }, "aria-hidden": "true" }), _jsx("input", { ref: inputRef, type: "text", value: value, onChange: (e) => setValue(e.target.value), onFocus: handleFocus, onKeyDown: handleKeyDown, placeholder: t('globalGoTo.searchPlaceholder', 'Search pages...'), className: "dndev-input dndev-w-full", style: { paddingInlineStart: '2.5rem', paddingInlineEnd: '5rem' }, "aria-label": t('globalGoTo.ariaLabel', 'Search navigation') }), _jsx("div", { className: "dndev-absolute dndev-flex dndev-items-center dndev-text-sm", style: { insetInlineEnd: '0.75rem', gap: '0.25rem', opacity: 0.5 }, "aria-hidden": "true", children: _jsx("kbd", { style: {
|
|
41
42
|
padding: '0.25rem 0.5rem',
|
|
42
43
|
fontSize: 'var(--font-size-xs)',
|
|
43
44
|
fontFamily: 'var(--font-mono)',
|
|
44
45
|
borderRadius: 'var(--radius-sm)',
|
|
45
|
-
}, children:
|
|
46
|
+
}, children: isMac ? '⌘K' : 'Ctrl+K' }) })] }));
|
|
46
47
|
};
|
|
47
48
|
export default GoToInput;
|
package/dist/routing/Link.js
CHANGED
|
@@ -25,9 +25,9 @@ import { Icon } from '../components/common/icon';
|
|
|
25
25
|
*/
|
|
26
26
|
export const Link = ({ path, replace, prefetch = true, children, icon, label, onClick, className, 'aria-label': ariaLabel, 'aria-describedby': ariaDescribedBy, target, rel, ...rest }) => {
|
|
27
27
|
const navigate = useNavigate();
|
|
28
|
+
const showCookieBanner = useConsent('showCookieBanner');
|
|
28
29
|
// Special framework trigger: #cookie-settings
|
|
29
30
|
if (path === '#cookie-settings') {
|
|
30
|
-
const showCookieBanner = useConsent('showCookieBanner');
|
|
31
31
|
const handleCookieSettings = (e) => {
|
|
32
32
|
e.preventDefault();
|
|
33
33
|
e.stopPropagation();
|
|
@@ -1,18 +1,40 @@
|
|
|
1
1
|
import type { NavigationRoute } from '@donotdev/core';
|
|
2
2
|
import type { ComponentType } from 'react';
|
|
3
|
-
|
|
3
|
+
/**
|
|
4
|
+
* Props for NavigationItemComponent.
|
|
5
|
+
*
|
|
6
|
+
* Source (mutually exclusive):
|
|
7
|
+
* - `path` — auto-resolves label, icon, and active state from the navigation store
|
|
8
|
+
* - `route` — explicit route object (use when the route is not registered in the store)
|
|
9
|
+
*/
|
|
10
|
+
export type NavigationItemProps = ({
|
|
11
|
+
path: string;
|
|
12
|
+
route?: never;
|
|
13
|
+
} | {
|
|
4
14
|
route: NavigationRoute;
|
|
15
|
+
path?: never;
|
|
16
|
+
}) & {
|
|
5
17
|
showIcons?: boolean;
|
|
6
|
-
}
|
|
18
|
+
};
|
|
7
19
|
/**
|
|
8
|
-
* Universal NavigationItem component
|
|
9
|
-
* Handles icon + label + link in one place
|
|
10
|
-
* Used everywhere in the framework
|
|
20
|
+
* Universal NavigationItem component — nav-trigger style link with icon + label.
|
|
11
21
|
*
|
|
12
|
-
*
|
|
22
|
+
* Used internally in menus, sidebars, and dropdowns.
|
|
23
|
+
* Pass `path` to auto-resolve label, icon, and active state from the navigation store.
|
|
24
|
+
* Pass `route` for an explicit one-off item not registered in the store.
|
|
25
|
+
*
|
|
26
|
+
* For standalone Button-style navigation (e.g. header end slot), use
|
|
27
|
+
* `useNavigationRoute(path)` and compose with `Button` + `render` prop directly.
|
|
28
|
+
*
|
|
29
|
+
* @version 0.0.2
|
|
13
30
|
* @since 0.0.1
|
|
14
31
|
* @author AMBROISE PARK Consulting
|
|
32
|
+
*
|
|
33
|
+
* @example
|
|
34
|
+
* ```tsx
|
|
35
|
+
* <NavigationItemComponent path="/pricing" />
|
|
36
|
+
* <NavigationItemComponent route={{ path: '/pricing', label: t('pricing'), icon: Tag }} />
|
|
37
|
+
* ```
|
|
15
38
|
*/
|
|
16
39
|
export declare const NavigationItemComponent: ComponentType<NavigationItemProps>;
|
|
17
|
-
export {};
|
|
18
40
|
//# sourceMappingURL=NavigationItem.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"NavigationItem.d.ts","sourceRoot":"","sources":["../../src/routing/NavigationItem.tsx"],"names":[],"mappings":"AAcA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC;
|
|
1
|
+
{"version":3,"file":"NavigationItem.d.ts","sourceRoot":"","sources":["../../src/routing/NavigationItem.tsx"],"names":[],"mappings":"AAcA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC;AAMtD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,OAAO,CAAC;AAE3C;;;;;;GAMG;AACH,MAAM,MAAM,mBAAmB,GAAG,CAC9B;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,KAAK,CAAA;CAAE,GAC/B;IAAE,KAAK,EAAE,eAAe,CAAC;IAAC,IAAI,CAAC,EAAE,KAAK,CAAA;CAAE,CAC3C,GAAG;IACF,SAAS,CAAC,EAAE,OAAO,CAAC;CACrB,CAAC;AAEF;;;;;;;;;;;;;;;;;;;GAmBG;AACH,eAAO,MAAM,uBAAuB,EAAE,aAAa,CAAC,mBAAmB,CAuBtE,CAAC"}
|
|
@@ -4,7 +4,7 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
|
4
4
|
* @fileoverview NavigationItem component
|
|
5
5
|
* @description Universal navigation item component with icon and label
|
|
6
6
|
*
|
|
7
|
-
* @version 0.0.
|
|
7
|
+
* @version 0.0.2
|
|
8
8
|
* @since 0.0.1
|
|
9
9
|
* @author AMBROISE PARK Consulting
|
|
10
10
|
*/
|
|
@@ -12,16 +12,32 @@ import { Link as LinkIcon } from 'lucide-react';
|
|
|
12
12
|
import { navigationMenuTriggerStylePrimitive } from '@donotdev/components';
|
|
13
13
|
import { Link } from './Link';
|
|
14
14
|
import { Icon } from '../components/common/icon';
|
|
15
|
+
import { useNavigationItems } from './useNavigation';
|
|
15
16
|
/**
|
|
16
|
-
* Universal NavigationItem component
|
|
17
|
-
* Handles icon + label + link in one place
|
|
18
|
-
* Used everywhere in the framework
|
|
17
|
+
* Universal NavigationItem component — nav-trigger style link with icon + label.
|
|
19
18
|
*
|
|
20
|
-
*
|
|
19
|
+
* Used internally in menus, sidebars, and dropdowns.
|
|
20
|
+
* Pass `path` to auto-resolve label, icon, and active state from the navigation store.
|
|
21
|
+
* Pass `route` for an explicit one-off item not registered in the store.
|
|
22
|
+
*
|
|
23
|
+
* For standalone Button-style navigation (e.g. header end slot), use
|
|
24
|
+
* `useNavigationRoute(path)` and compose with `Button` + `render` prop directly.
|
|
25
|
+
*
|
|
26
|
+
* @version 0.0.2
|
|
21
27
|
* @since 0.0.1
|
|
22
28
|
* @author AMBROISE PARK Consulting
|
|
29
|
+
*
|
|
30
|
+
* @example
|
|
31
|
+
* ```tsx
|
|
32
|
+
* <NavigationItemComponent path="/pricing" />
|
|
33
|
+
* <NavigationItemComponent route={{ path: '/pricing', label: t('pricing'), icon: Tag }} />
|
|
34
|
+
* ```
|
|
23
35
|
*/
|
|
24
|
-
export const NavigationItemComponent = ({ route, showIcons = true, }) => {
|
|
36
|
+
export const NavigationItemComponent = ({ path, route: routeProp, showIcons = true, }) => {
|
|
37
|
+
const allItems = useNavigationItems();
|
|
38
|
+
const route = routeProp ?? allItems.find((item) => item.path === path);
|
|
39
|
+
if (!route)
|
|
40
|
+
return null;
|
|
25
41
|
const hasIcon = showIcons && !!route.icon;
|
|
26
42
|
const hasLabel = !!route.label;
|
|
27
43
|
return (_jsxs(Link, { path: route.path, className: navigationMenuTriggerStylePrimitive(), ...(hasIcon && !hasLabel && { 'data-display': 'compact' }), children: [showIcons && _jsx(Icon, { icon: route.icon, fallback: LinkIcon }), _jsx("span", { children: route.label })] }));
|
|
@@ -1 +1 @@
|
|
|
1
|
-
"use client";import{useRouter as
|
|
1
|
+
"use client";import{useRouter as f}from"next/navigation";import{useCallback as h}from"react";import{isClient as S,useOverlayStore as y}from"@donotdev/core";function d(){let e=f(),t=y(r=>r.closeAll);return h((r,i)=>{if(r==="back")return t(),e.back();if(t(),i?.preserveScroll&&S()){let s=window.scrollY;i?.replace?e.replace(r):e.push(r),requestAnimationFrame(()=>{window.scrollTo({top:s,behavior:"auto"})});return}return i?.replace?e.replace(r):e.push(r)},[e,t])}function k(){let e=f();return h(()=>e.back(),[e])}function T(){let e=f();return h(()=>e.refresh(),[e])}function v(){let e=f();return h(t=>e.prefetch(t),[e])}import{usePathname as b,useSearchParams as N}from"next/navigation";function l(){let e=b(),t=N(),r=t.toString()?`?${t.toString()}`:"";return{pathname:e||"/",search:r,hash:"",state:null}}import{useParams as w}from"next/navigation";function g(){return w()}function C(e){let r=g()[e];if(typeof r=="string")return r;if(Array.isArray(r)&&r.length>0)return r[0]}import{useSearchParams as I}from"next/navigation";function R(){return I()}import{usePathname as G}from"next/navigation";function $(e){let t=G(),r=e.replace(/:[^/]+/g,"([^/]+)").replace(/\*/g,".*"),i=new RegExp(`^${r}$`),s=t.match(i);if(!s)return null;let o=e.match(/:[^/]+/g)?.map(a=>a.slice(1))||[],n={};return o.forEach((a,c)=>{n[a]=s[c+1]||""}),{params:n,pathname:t,pattern:e}}import{useCallback as P}from"react";function K(){let e=R(),t=d(),r=l(),i=P((n,a)=>{let c=new URLSearchParams(e.toString());c.set(n,a);let m=c.toString(),x=`${r.pathname||"/"}${m?`?${m}`:""}`;t(x)},[e,t,r.pathname]),s=P(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]),o=P(()=>{let n=r.pathname||"/";t(n)},[t,r.pathname]);return{query:e,setQuery:i,removeQuery:s,clearQueries:o}}import{useMemo as E}from"react";import{isClient as Q,FEATURE_STATUS as F}from"@donotdev/core";import{useAuthConfig as M}from"@donotdev/core";import*as O from"@donotdev/auth";import{DEGRADED_AUTH_API as U}from"@donotdev/core";var A=O?.useAuth;function L(e){return U[e]}function p(e){return A?A(e):L(e)}function j(e={}){let{auth:t,redirectTo:r,condition:i}=e,s=l(),o=M(),n=p("user"),a=p("can"),c=p("status");return E(()=>{if(!Q())return{shouldRedirect:!1,redirectTo:null,isChecking:!1};if(c===F.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?s.search.includes("code=")||s.search.includes("state=")||s.search.includes("error=")?u=`${o.authRoute}${s.search}`:u=o.authRoute:typeof t=="object"&&t.role?u=o.roleRoute:typeof t=="object"&&t.tier?u=o.tierRoute:u=o.roleRoute,{shouldRedirect:!0,redirectTo:r||u,isChecking:!1}}}return{shouldRedirect:!1,redirectTo:null,isChecking:!1}},[t,c,n,a,i,r,s.search,o.authRoute,o.roleRoute,o.tierRoute])}export{k as useBack,l as useLocation,$ as useMatch,d as useNavigate,g as useParams,v as usePrefetch,K as useQueryParams,j as useRedirectGuard,T as useRefresh,C as useRouteParam,R as useSearchParams};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
"use client";import{useCallback as
|
|
1
|
+
"use client";import{useCallback as m}from"react";import{useNavigate as P}from"react-router-dom";import{isClient as y,useOverlayStore as S}from"@donotdev/core";function h(){let e=P(),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 v(){let e=P();return m(()=>e(-1),[e])}function k(){return m(()=>{y()&&window.location.reload()},[])}function T(){return m(e=>{},[])}import{useLocation as C}from"react-router-dom";function f(){return C()}import{useParams as I}from"react-router-dom";function d(){return I()}function b(e){let r=d()[e];if(typeof r=="string")return r;if(Array.isArray(r)&&r.length>0)return r[0]}import{useSearchParams as G}from"react-router-dom";function g(){return G()[0]}import{useMatch as w}from"react-router-dom";function L(e){return w(e)}import{useCallback as R}from"react";function N(){let e=g(),t=h(),r=f(),i=R((n,u)=>{let a=new URLSearchParams(e.toString());a.set(n,u);let l=a.toString(),A=`${r.pathname||"/"}${l?`?${l}`:""}`;t(A)},[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,FEATURE_STATUS as Q}from"@donotdev/core";import{useAuthConfig as E}from"@donotdev/core";import*as K from"@donotdev/auth";import{DEGRADED_AUTH_API as O}from"@donotdev/core";var x=K?.useAuth;function U(e){return O[e]}function p(e){return x?x(e):U(e)}function _(e={}){let{auth:t,redirectTo:r,condition:i}=e,c=f(),s=E(),n=p("user"),u=p("can"),a=p("status");return $(()=>{if(!M())return{shouldRedirect:!1,redirectTo:null,isChecking:!1};if(a===Q.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{v as useBack,f as useLocation,L as useMatch,h as useNavigate,d as useParams,T as usePrefetch,N as useQueryParams,_ as useRedirectGuard,k as useRefresh,b as useRouteParam,g as useSearchParams};
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { NavigateOptions } from './types';
|
|
2
|
-
export declare function useNavigate(): (to: string, options?: NavigateOptions) =>
|
|
2
|
+
export declare function useNavigate(): (to: string, options?: NavigateOptions) => void;
|
|
3
3
|
export declare function useBack(): () => void;
|
|
4
4
|
export declare function useRefresh(): () => void;
|
|
5
5
|
export declare function usePrefetch(): (to: string) => void;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useNavigate.next.d.ts","sourceRoot":"","sources":["../../../src/routing/hooks/useNavigate.next.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"useNavigate.next.d.ts","sourceRoot":"","sources":["../../../src/routing/hooks/useNavigate.next.ts"],"names":[],"mappings":"AAiBA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,SAAS,CAAC;AAE/C,wBAAgB,WAAW,SAKlB,MAAM,YAAY,eAAe,UA0BzC;AAED,wBAAgB,OAAO,eAGtB;AAED,wBAAgB,UAAU,eAGzB;AAED,wBAAgB,WAAW,SAED,MAAM,UAC/B"}
|
|
@@ -11,20 +11,14 @@
|
|
|
11
11
|
import { useRouter as useNextRouter } from 'next/navigation';
|
|
12
12
|
import { useCallback } from 'react';
|
|
13
13
|
import { isClient, useOverlayStore } from '@donotdev/core';
|
|
14
|
-
import { checkFormNavigationSafe } from '../../utils/useFormStoreSafe';
|
|
15
14
|
export function useNavigate() {
|
|
16
15
|
const router = useNextRouter();
|
|
17
16
|
const closeAll = useOverlayStore((state) => state.closeAll);
|
|
18
|
-
return useCallback(
|
|
17
|
+
return useCallback((to, options) => {
|
|
19
18
|
if (to === 'back') {
|
|
20
19
|
closeAll();
|
|
21
20
|
return router.back();
|
|
22
21
|
}
|
|
23
|
-
// Check FormStore for dirty forms before navigation (safe - works if CRUD not installed)
|
|
24
|
-
const shouldProceed = await checkFormNavigationSafe();
|
|
25
|
-
if (!shouldProceed) {
|
|
26
|
-
return; // Navigation blocked by user
|
|
27
|
-
}
|
|
28
22
|
closeAll();
|
|
29
23
|
if (options?.preserveScroll && isClient()) {
|
|
30
24
|
const scrollY = window.scrollY;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { NavigateOptions } from './types';
|
|
2
|
-
export declare function useNavigate(): (to: string, options?: NavigateOptions) => Promise<void>;
|
|
2
|
+
export declare function useNavigate(): (to: string, options?: NavigateOptions) => void | Promise<void>;
|
|
3
3
|
export declare function useBack(): () => void | Promise<void>;
|
|
4
4
|
export declare function useRefresh(): () => void;
|
|
5
5
|
export declare function usePrefetch(): (_to: string) => void;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useNavigate.vite.d.ts","sourceRoot":"","sources":["../../../src/routing/hooks/useNavigate.vite.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"useNavigate.vite.d.ts","sourceRoot":"","sources":["../../../src/routing/hooks/useNavigate.vite.ts"],"names":[],"mappings":"AAiBA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,SAAS,CAAC;AAE/C,wBAAgB,WAAW,SAKlB,MAAM,YAAY,eAAe,0BAazC;AAED,wBAAgB,OAAO,+BAGtB;AAED,wBAAgB,UAAU,eAIzB;AAED,wBAAgB,WAAW,UACA,MAAM,UAGhC"}
|
|
@@ -11,20 +11,14 @@
|
|
|
11
11
|
import { useCallback } from 'react';
|
|
12
12
|
import { useNavigate as useRouterNavigate } from 'react-router-dom';
|
|
13
13
|
import { isClient, useOverlayStore } from '@donotdev/core';
|
|
14
|
-
import { checkFormNavigationSafe } from '../../utils/useFormStoreSafe';
|
|
15
14
|
export function useNavigate() {
|
|
16
15
|
const navigate = useRouterNavigate();
|
|
17
16
|
const closeAll = useOverlayStore((state) => state.closeAll);
|
|
18
|
-
return useCallback(
|
|
17
|
+
return useCallback((to, options) => {
|
|
19
18
|
if (to === 'back') {
|
|
20
19
|
closeAll();
|
|
21
20
|
return navigate(-1);
|
|
22
21
|
}
|
|
23
|
-
// Check FormStore for dirty forms before navigation (safe - works if CRUD not installed)
|
|
24
|
-
const shouldProceed = await checkFormNavigationSafe();
|
|
25
|
-
if (!shouldProceed) {
|
|
26
|
-
return; // Navigation blocked by user
|
|
27
|
-
}
|
|
28
22
|
closeAll();
|
|
29
23
|
if (options?.replace)
|
|
30
24
|
return navigate(to, { replace: true });
|
|
@@ -1 +1 @@
|
|
|
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,
|
|
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,CA6GrB"}
|
|
@@ -24,14 +24,7 @@ import { useAuthSafe } from '../../utils/useAuthSafe';
|
|
|
24
24
|
*/
|
|
25
25
|
export function useRedirectGuard(options = {}) {
|
|
26
26
|
const { auth, redirectTo: customRedirectTo, condition } = options;
|
|
27
|
-
//
|
|
28
|
-
if (!isClient()) {
|
|
29
|
-
return {
|
|
30
|
-
shouldRedirect: false,
|
|
31
|
-
redirectTo: null,
|
|
32
|
-
isChecking: false,
|
|
33
|
-
};
|
|
34
|
-
}
|
|
27
|
+
// Hooks must be called unconditionally (Rules of Hooks)
|
|
35
28
|
const location = useLocation();
|
|
36
29
|
const authConfig = useAuthConfig();
|
|
37
30
|
const user = useAuthSafe('user');
|
|
@@ -39,6 +32,14 @@ export function useRedirectGuard(options = {}) {
|
|
|
39
32
|
const status = useAuthSafe('status');
|
|
40
33
|
// Determine redirect state
|
|
41
34
|
const redirectState = useMemo(() => {
|
|
35
|
+
// SSR-safe: return safe defaults on server
|
|
36
|
+
if (!isClient()) {
|
|
37
|
+
return {
|
|
38
|
+
shouldRedirect: false,
|
|
39
|
+
redirectTo: null,
|
|
40
|
+
isChecking: false,
|
|
41
|
+
};
|
|
42
|
+
}
|
|
42
43
|
// Only INITIALIZING = still checking. DEGRADED/ERROR/READY = auth resolved (proceed with current user)
|
|
43
44
|
if (status === FEATURE_STATUS.INITIALIZING) {
|
|
44
45
|
return {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useRedirectGuard.vite.d.ts","sourceRoot":"","sources":["../../../src/routing/hooks/useRedirectGuard.vite.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,
|
|
1
|
+
{"version":3,"file":"useRedirectGuard.vite.d.ts","sourceRoot":"","sources":["../../../src/routing/hooks/useRedirectGuard.vite.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,CA6GrB"}
|
|
@@ -24,14 +24,7 @@ import { useAuthSafe } from '../../utils/useAuthSafe';
|
|
|
24
24
|
*/
|
|
25
25
|
export function useRedirectGuard(options = {}) {
|
|
26
26
|
const { auth, redirectTo: customRedirectTo, condition } = options;
|
|
27
|
-
//
|
|
28
|
-
if (!isClient()) {
|
|
29
|
-
return {
|
|
30
|
-
shouldRedirect: false,
|
|
31
|
-
redirectTo: null,
|
|
32
|
-
isChecking: false,
|
|
33
|
-
};
|
|
34
|
-
}
|
|
27
|
+
// Hooks must be called unconditionally (Rules of Hooks)
|
|
35
28
|
const location = useLocation();
|
|
36
29
|
const authConfig = useAuthConfig();
|
|
37
30
|
const user = useAuthSafe('user');
|
|
@@ -39,6 +32,14 @@ export function useRedirectGuard(options = {}) {
|
|
|
39
32
|
const status = useAuthSafe('status');
|
|
40
33
|
// Determine redirect state
|
|
41
34
|
const redirectState = useMemo(() => {
|
|
35
|
+
// SSR-safe: return safe defaults on server
|
|
36
|
+
if (!isClient()) {
|
|
37
|
+
return {
|
|
38
|
+
shouldRedirect: false,
|
|
39
|
+
redirectTo: null,
|
|
40
|
+
isChecking: false,
|
|
41
|
+
};
|
|
42
|
+
}
|
|
42
43
|
// Only INITIALIZING = still checking. DEGRADED/ERROR/READY = auth resolved (proceed with current user)
|
|
43
44
|
if (status === FEATURE_STATUS.INITIALIZING) {
|
|
44
45
|
return {
|
|
@@ -1,2 +1,19 @@
|
|
|
1
|
-
|
|
1
|
+
import { useSearchParams as useNextSearchParams } from 'next/navigation';
|
|
2
|
+
/**
|
|
3
|
+
* Get current URL search parameters (read-only).
|
|
4
|
+
* Returns a ReadonlyURLSearchParams instance directly (NOT a tuple).
|
|
5
|
+
*
|
|
6
|
+
* To modify search params, use `useNavigate()` with a query string
|
|
7
|
+
* or `useQueryParams()` for a key-value API with defaults.
|
|
8
|
+
*
|
|
9
|
+
* @returns ReadonlyURLSearchParams instance with `.get()`, `.has()`, `.getAll()`, etc.
|
|
10
|
+
*
|
|
11
|
+
* @example
|
|
12
|
+
* ```tsx
|
|
13
|
+
* const searchParams = useSearchParams();
|
|
14
|
+
* const page = searchParams.get('page');
|
|
15
|
+
* const sort = searchParams.get('sort');
|
|
16
|
+
* ```
|
|
17
|
+
*/
|
|
18
|
+
export declare function useSearchParams(): ReturnType<typeof useNextSearchParams>;
|
|
2
19
|
//# sourceMappingURL=useSearchParams.next.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useSearchParams.next.d.ts","sourceRoot":"","sources":["../../../src/routing/hooks/useSearchParams.next.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"useSearchParams.next.d.ts","sourceRoot":"","sources":["../../../src/routing/hooks/useSearchParams.next.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,eAAe,IAAI,mBAAmB,EAAE,MAAM,iBAAiB,CAAC;AAEzE;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,eAAe,IAAI,UAAU,CAAC,OAAO,mBAAmB,CAAC,CAExE"}
|