@donotdev/ui 0.0.14 → 0.0.16

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 (61) hide show
  1. package/dist/components/common/TechBento.d.ts.map +1 -1
  2. package/dist/components/common/TechBento.js +1 -1
  3. package/dist/components/layout/components/header/HeaderNavigation.d.ts.map +1 -1
  4. package/dist/components/layout/components/header/HeaderNavigation.js +2 -2
  5. package/dist/components/layout/components/index.d.ts +3 -0
  6. package/dist/components/layout/components/index.d.ts.map +1 -1
  7. package/dist/components/layout/components/index.js +3 -0
  8. package/dist/crud/components/CrudCardLink.d.ts.map +1 -1
  9. package/dist/crud/components/EntityCardList.d.ts +1 -1
  10. package/dist/crud/components/EntityCardList.d.ts.map +1 -1
  11. package/dist/crud/components/EntityCardList.js +24 -35
  12. package/dist/crud/components/EntityDisplayRenderer.d.ts +1 -1
  13. package/dist/crud/components/EntityDisplayRenderer.d.ts.map +1 -1
  14. package/dist/crud/components/EntityDisplayRenderer.js +6 -2
  15. package/dist/crud/components/EntityFormRenderer.d.ts +1 -1
  16. package/dist/crud/components/EntityFormRenderer.d.ts.map +1 -1
  17. package/dist/crud/components/EntityFormRenderer.js +12 -29
  18. package/dist/crud/components/EntityList.d.ts.map +1 -1
  19. package/dist/crud/components/EntityList.js +7 -43
  20. package/dist/crud/components/EntityRecommendations.d.ts +1 -0
  21. package/dist/crud/components/EntityRecommendations.d.ts.map +1 -1
  22. package/dist/crud/components/EntityRecommendations.js +3 -2
  23. package/dist/dndev.css +11581 -0
  24. package/dist/index.js +4 -4
  25. package/dist/internal/devtools/components/DesignTab.d.ts.map +1 -1
  26. package/dist/internal/layout/components/AutoMetaTags.d.ts.map +1 -1
  27. package/dist/internal/layout/components/AutoMetaTags.js +2 -9
  28. package/dist/internal/layout/components/FontPreloadLinks.d.ts.map +1 -1
  29. package/dist/internal/layout/components/FontPreloadLinks.js +1 -0
  30. package/dist/internal/layout/components/footer/useLegalLinks.d.ts.map +1 -1
  31. package/dist/internal/providers/NavigationProvider.d.ts.map +1 -1
  32. package/dist/internal/providers/NavigationProvider.js +3 -5
  33. package/dist/providers/ViteAppProviders.d.ts.map +1 -1
  34. package/dist/providers/ViteAppProviders.js +3 -5
  35. package/dist/routing/GoToInput.d.ts.map +1 -1
  36. package/dist/routing/GoToInput.js +6 -6
  37. package/dist/routing/Link.d.ts.map +1 -1
  38. package/dist/routing/hooks/hooks.next.js +1 -1
  39. package/dist/routing/hooks/hooks.vite.js +1 -1
  40. package/dist/routing/hooks/useNavigate.next.d.ts +1 -1
  41. package/dist/routing/hooks/useNavigate.next.d.ts.map +1 -1
  42. package/dist/routing/hooks/useNavigate.next.js +1 -7
  43. package/dist/routing/hooks/useNavigate.vite.d.ts +1 -1
  44. package/dist/routing/hooks/useNavigate.vite.d.ts.map +1 -1
  45. package/dist/routing/hooks/useNavigate.vite.js +1 -7
  46. package/dist/routing/useRouteDiscovery.d.ts +4 -15
  47. package/dist/routing/useRouteDiscovery.d.ts.map +1 -1
  48. package/dist/routing/useRouteDiscovery.js +6 -5
  49. package/dist/styles/index.css +96 -63
  50. package/dist/utils/sanitizeSvg.d.ts.map +1 -1
  51. package/dist/utils/useFormStoreSafe.d.ts +2 -15
  52. package/dist/utils/useFormStoreSafe.d.ts.map +1 -1
  53. package/dist/utils/useFormStoreSafe.js +3 -33
  54. package/dist/vite-routing/AppRoutes.d.ts.map +1 -1
  55. package/dist/vite-routing/AppRoutes.js +1 -1
  56. package/dist/vite-routing/RootLayout.d.ts.map +1 -1
  57. package/dist/vite-routing/RootLayout.js +10 -15
  58. package/package.json +10 -10
  59. package/dist/routing/hooks/useFormNavigationBlocker.d.ts +0 -14
  60. package/dist/routing/hooks/useFormNavigationBlocker.d.ts.map +0 -1
  61. package/dist/routing/hooks/useFormNavigationBlocker.js +0 -42
@@ -1 +1 @@
1
- {"version":3,"file":"DesignTab.d.ts","sourceRoot":"","sources":["../../../../src/internal/devtools/components/DesignTab.tsx"],"names":[],"mappings":"AA+CA,eAAO,MAAM,SAAS,+CA4yBrB,CAAC"}
1
+ {"version":3,"file":"DesignTab.d.ts","sourceRoot":"","sources":["../../../../src/internal/devtools/components/DesignTab.tsx"],"names":[],"mappings":"AA+CA,eAAO,MAAM,SAAS,+CAizBrB,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"AutoMetaTags.d.ts","sourceRoot":"","sources":["../../../../src/internal/layout/components/AutoMetaTags.tsx"],"names":[],"mappings":"AA0DA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,OAAO,CAAC;AAyE3C;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,YAAY,EAAE,aAmN1B,CAAC;AAEF;;;GAGG;AAEH,eAAe,YAAY,CAAC"}
1
+ {"version":3,"file":"AutoMetaTags.d.ts","sourceRoot":"","sources":["../../../../src/internal/layout/components/AutoMetaTags.tsx"],"names":[],"mappings":"AA0DA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,OAAO,CAAC;AAyE3C;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,YAAY,EAAE,aAyM1B,CAAC;AAEF;;;GAGG;AAEH,eAAe,YAAY,CAAC"}
@@ -130,7 +130,7 @@ export const AutoMetaTags = () => {
130
130
  const metaData = useMemo(() => {
131
131
  if (!seoConfig)
132
132
  return null;
133
- const { defaultNamespace = 'home', defaultImage, } = seoConfig;
133
+ const { defaultNamespace = 'home', defaultImage } = seoConfig;
134
134
  // Construct absolute URL for canonical link
135
135
  const currentUrl = `${baseUrl}${location.pathname}`;
136
136
  const ns = routeMeta.ns || defaultNamespace;
@@ -169,14 +169,7 @@ export const AutoMetaTags = () => {
169
169
  publishDate: routeMeta.publishDate,
170
170
  modifiedDate: routeMeta.modifiedDate,
171
171
  };
172
- }, [
173
- location.pathname,
174
- routeMeta,
175
- siteName,
176
- baseUrl,
177
- seoConfig,
178
- t,
179
- ]);
172
+ }, [location.pathname, routeMeta, siteName, baseUrl, seoConfig, t]);
180
173
  // Return null if SEO is disabled — after all hooks have been called
181
174
  if (!seoConfig || !metaData)
182
175
  return null;
@@ -1 +1 @@
1
- {"version":3,"file":"FontPreloadLinks.d.ts","sourceRoot":"","sources":["../../../../src/internal/layout/components/FontPreloadLinks.tsx"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAKH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AASvC;;;GAGG;AACH,wBAAsB,gBAAgB,IAAI,OAAO,CAAC,SAAS,CAAC,CA6B3D;AAED,eAAe,gBAAgB,CAAC"}
1
+ {"version":3,"file":"FontPreloadLinks.d.ts","sourceRoot":"","sources":["../../../../src/internal/layout/components/FontPreloadLinks.tsx"],"names":[],"mappings":"AACA;;;;;;;GAOG;AAKH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AASvC;;;GAGG;AACH,wBAAsB,gBAAgB,IAAI,OAAO,CAAC,SAAS,CAAC,CAyB3D;AAED,eAAe,gBAAgB,CAAC"}
@@ -1,4 +1,5 @@
1
1
  import { jsx as _jsx, Fragment as _Fragment } from "react/jsx-runtime";
2
+ // packages/ui/src/internal/layout/components/FontPreloadLinks.tsx
2
3
  /**
3
4
  * @fileoverview FontPreloadLinks - Server-only component for Next.js
4
5
  * @description Reads public/dndev-font-preloads.json (written at build by FontPreloadWebpackPlugin) and renders preload link tags for Lighthouse-friendly LCP. Include in root layout so initial HTML contains the links.
@@ -1 +1 @@
1
- {"version":3,"file":"useLegalLinks.d.ts","sourceRoot":"","sources":["../../../../../src/internal/layout/components/footer/useLegalLinks.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAElD,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;CACf;AAQD;;;;;GAKG;AACH,eAAO,MAAM,aAAa,GAAI,cAAc,WAAW,CAAC,QAAQ,CAAC,KAAG,eAAe,EAQlF,CAAC;AAEF,4CAA4C;AAC5C,eAAO,MAAM,aAAa,iBAXkB,WAAW,CAAC,QAAQ,CAAC,KAAG,eAAe,EAWzC,CAAC"}
1
+ {"version":3,"file":"useLegalLinks.d.ts","sourceRoot":"","sources":["../../../../../src/internal/layout/components/footer/useLegalLinks.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAElD,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;CACf;AAQD;;;;;GAKG;AACH,eAAO,MAAM,aAAa,GACxB,cAAc,WAAW,CAAC,QAAQ,CAAC,KAClC,eAAe,EAQjB,CAAC;AAEF,4CAA4C;AAC5C,eAAO,MAAM,aAAa,iBAZV,WAAW,CAAC,QAAQ,CAAC,KAClC,eAAe,EAWwB,CAAC"}
@@ -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;AAEvC;;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,2CAqBrE"}
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, abortAll, closeAll]);
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 });
@@ -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,2CAkCxD"}
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
- const router = createAppRouter({
80
- routeGroups,
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
  }
@@ -1 +1 @@
1
- {"version":3,"file":"GoToInput.d.ts","sourceRoot":"","sources":["../../src/routing/GoToInput.tsx"],"names":[],"mappings":"AA+BA,QAAA,MAAM,SAAS,+CAyEd,CAAC;AAEF,eAAe,SAAS,CAAC"}
1
+ {"version":3,"file":"GoToInput.d.ts","sourceRoot":"","sources":["../../src/routing/GoToInput.tsx"],"names":[],"mappings":"AAgCA,QAAA,MAAM,SAAS,+CAwEd,CAAC;AAEF,eAAe,SAAS,CAAC"}
@@ -17,12 +17,12 @@ import { useTranslation } from '@donotdev/core';
17
17
  * Navigation input - typeable search that syncs with command dialog
18
18
  */
19
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);
20
+ const isMac = typeof navigator !== 'undefined' &&
21
+ /Mac|iPhone|iPad/.test(navigator.userAgent);
21
22
  const GoToInput = () => {
22
23
  const { t } = useTranslation('dndev');
23
24
  const [value, setValue] = useState('');
24
25
  const inputRef = useRef(null);
25
- const openCommandDialog = useOverlayStore((state) => state.openCommandDialog);
26
26
  const isCommandDialogOpen = useOverlayStore((state) => state.isCommandDialogOpen);
27
27
  // Clear input when dialog closes
28
28
  useEffect(() => {
@@ -31,14 +31,14 @@ const GoToInput = () => {
31
31
  }
32
32
  }, [isCommandDialogOpen]);
33
33
  const handleFocus = useCallback(() => {
34
- openCommandDialog(value);
35
- }, [openCommandDialog, value]);
34
+ useOverlayStore.getState().openCommandDialog(value);
35
+ }, [value]);
36
36
  const handleKeyDown = useCallback((e) => {
37
37
  if (e.key === 'Enter') {
38
38
  e.preventDefault();
39
- openCommandDialog(value);
39
+ useOverlayStore.getState().openCommandDialog(value);
40
40
  }
41
- }, [openCommandDialog, value]);
41
+ }, [value]);
42
42
  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: {
43
43
  padding: '0.25rem 0.5rem',
44
44
  fontSize: 'var(--font-size-xs)',
@@ -1 +1 @@
1
- {"version":3,"file":"Link.d.ts","sourceRoot":"","sources":["../../src/routing/Link.tsx"],"names":[],"mappings":"AAaA,OAAO,EACL,KAAK,SAAS,EACd,KAAK,aAAa,EAElB,KAAK,oBAAoB,EAC1B,MAAM,OAAO,CAAC;AASf;;;;;;GAMG;AACH,MAAM,WAAW,SAAU,SAAQ,oBAAoB,CAAC,iBAAiB,CAAC;IACxE,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,QAAQ,CAAC,EAAE,SAAS,CAAC;IACrB,oCAAoC;IACpC,IAAI,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC1B,gDAAgD;IAChD,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,kBAAkB,CAAC,EAAE,MAAM,CAAC;CAC7B;AAED;;;;;;GAMG;AACH,eAAO,MAAM,IAAI,EAAE,aAAa,CAAC,SAAS,CAwIzC,CAAC"}
1
+ {"version":3,"file":"Link.d.ts","sourceRoot":"","sources":["../../src/routing/Link.tsx"],"names":[],"mappings":"AAaA,OAAO,EACL,KAAK,SAAS,EACd,KAAK,aAAa,EAElB,KAAK,oBAAoB,EAC1B,MAAM,OAAO,CAAC;AASf;;;;;;GAMG;AACH,MAAM,WAAW,SAAU,SAAQ,oBAAoB,CAAC,iBAAiB,CAAC;IACxE,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,QAAQ,CAAC,EAAE,SAAS,CAAC;IACrB,oCAAoC;IACpC,IAAI,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC1B,gDAAgD;IAChD,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,kBAAkB,CAAC,EAAE,MAAM,CAAC;CAC7B;AAED;;;;;;GAMG;AACH,eAAO,MAAM,IAAI,EAAE,aAAa,CAAC,SAAS,CAuIzC,CAAC"}
@@ -1 +1 @@
1
- "use client";import{useRouter as p}from"next/navigation";import{useCallback as h}from"react";import{isClient as D,useOverlayStore as v}from"@donotdev/core";import*as F from"@donotdev/crud";var y={forms:{},startSubmit:()=>{},setUploading:()=>{},setValidating:()=>{},setSubmitting:()=>{},setSuccess:()=>{},setError:()=>{},reset:()=>{},cleanup:()=>{},setIsDirty:()=>{},hasDirtyForms:()=>!1,getDirtyFormIds:()=>[],getStatus:()=>"idle",isLoading:()=>!1,getUploadProgress:()=>0,getError:()=>null,getIsDirty:()=>!1},m=F?.useFormStore;function x(e){return m?m(e):e(y)}x.getState=()=>m&&typeof m.getState=="function"?m.getState():y;async function T(e="You have unsaved changes. Discard them?"){return x.getState().hasDirtyForms()&&typeof window<"u"&&window.confirm?window.confirm(e):!0}function g(){let e=p(),t=v(r=>r.closeAll);return h(async(r,u)=>{if(r==="back")return t(),e.back();if(await T()){if(t(),u?.preserveScroll&&D()){let o=window.scrollY;u?.replace?e.replace(r):e.push(r),requestAnimationFrame(()=>{window.scrollTo({top:o,behavior:"auto"})});return}return u?.replace?e.replace(r):e.push(r)}},[e,t])}function w(){let e=p();return h(()=>e.back(),[e])}function E(){let e=p();return h(()=>e.refresh(),[e])}function b(){let e=p();return h(t=>e.prefetch(t),[e])}import{usePathname as I,useSearchParams as N}from"next/navigation";function f(){let e=I(),t=N(),r=t.toString()?`?${t.toString()}`:"";return{pathname:e||"/",search:r,hash:"",state:null}}import{useParams as O}from"next/navigation";function S(){return O()}function G(e){let r=S()[e];if(typeof r=="string")return r;if(Array.isArray(r)&&r.length>0)return r[0]}import{useSearchParams as C}from"next/navigation";function R(){return C()}import{usePathname as L}from"next/navigation";function _(e){let t=L(),r=e.replace(/:[^/]+/g,"([^/]+)").replace(/\*/g,".*"),u=new RegExp(`^${r}$`),i=t.match(u);if(!i)return null;let o=e.match(/:[^/]+/g)?.map(n=>n.slice(1))||[],s={};return o.forEach((n,c)=>{s[n]=i[c+1]||""}),{params:s,pathname:t,pattern:e}}import{useCallback as A}from"react";function U(){let e=R(),t=g(),r=f(),u=A((s,n)=>{let c=new URLSearchParams(e.toString());c.set(s,n);let l=c.toString(),P=`${r.pathname||"/"}${l?`?${l}`:""}`;t(P)},[e,t,r.pathname]),i=A(s=>{let n=new URLSearchParams(e.toString());n.delete(s);let c=n.toString(),a=`${r.pathname||"/"}${c?`?${c}`:""}`;t(a)},[e,t,r.pathname]),o=A(()=>{let s=r.pathname||"/";t(s)},[t,r.pathname]);return{query:e,setQuery:u,removeQuery:i,clearQueries:o}}import{useMemo as Q}from"react";import{isClient as j,FEATURE_STATUS as q}from"@donotdev/core";import{useAuthConfig as Y}from"@donotdev/core";import*as $ from"@donotdev/auth";import{DEGRADED_AUTH_API as K}from"@donotdev/core";var k=$?.useAuth;function M(e){return K[e]}function d(e){return k?k(e):M(e)}function B(e={}){let{auth:t,redirectTo:r,condition:u}=e,i=f(),o=Y(),s=d("user"),n=d("can"),c=d("status");return Q(()=>{if(!j())return{shouldRedirect:!1,redirectTo:null,isChecking:!1};if(c===q.INITIALIZING)return{shouldRedirect:!1,redirectTo:null,isChecking:!0};if(u){let a=u(s,c);return{shouldRedirect:a,redirectTo:a&&r||null,isChecking:!1}}if(t!==!1&&t!==void 0){if(!n)return{shouldRedirect:!1,redirectTo:null,isChecking:!1};if(!n.navigate(t)){let a=null;return typeof t=="object"&&t.required&&!s?i.search.includes("code=")||i.search.includes("state=")||i.search.includes("error=")?a=`${o.authRoute}${i.search}`:a=o.authRoute:typeof t=="object"&&t.role?a=o.roleRoute:typeof t=="object"&&t.tier?a=o.tierRoute:a=o.roleRoute,{shouldRedirect:!0,redirectTo:r||a,isChecking:!1}}}return{shouldRedirect:!1,redirectTo:null,isChecking:!1}},[t,c,s,n,u,r,i.search,o.authRoute,o.roleRoute,o.tierRoute])}export{w as useBack,f as useLocation,_ as useMatch,g as useNavigate,S as useParams,b as usePrefetch,U as useQueryParams,B as useRedirectGuard,E as useRefresh,G as useRouteParam,R as useSearchParams};
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 p}from"react";import{useNavigate as T}from"react-router-dom";import{isClient as k,useOverlayStore as D}from"@donotdev/core";import*as F from"@donotdev/crud";var y={forms:{},startSubmit:()=>{},setUploading:()=>{},setValidating:()=>{},setSubmitting:()=>{},setSuccess:()=>{},setError:()=>{},reset:()=>{},cleanup:()=>{},setIsDirty:()=>{},hasDirtyForms:()=>!1,getDirtyFormIds:()=>[],getStatus:()=>"idle",isLoading:()=>!1,getUploadProgress:()=>0,getError:()=>null,getIsDirty:()=>!1},f=F?.useFormStore;function P(e){return f?f(e):e(y)}P.getState=()=>f&&typeof f.getState=="function"?f.getState():y;async function x(e="You have unsaved changes. Discard them?"){return P.getState().hasDirtyForms()&&typeof window<"u"&&window.confirm?window.confirm(e):!0}function h(){let e=T(),t=D(r=>r.closeAll);return p(async(r,c)=>{if(r==="back")return t(),e(-1);if(await x())return t(),c?.replace?e(r,{replace:!0}):e(r)},[e,t])}function w(){let e=T();return p(()=>e(-1),[e])}function E(){return p(()=>{k()&&window.location.reload()},[])}function b(){return p(e=>{},[])}import{useLocation as I}from"react-router-dom";function m(){return I()}import{useParams as L}from"react-router-dom";function g(){return L()}function O(e){let r=g()[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 R(){return G()[0]}import{useMatch as C}from"react-router-dom";function _(e){return C(e)}import{useCallback as S}from"react";function N(){let e=R(),t=h(),r=m(),c=S((n,i)=>{let a=new URLSearchParams(e.toString());a.set(n,i);let l=a.toString(),A=`${r.pathname||"/"}${l?`?${l}`:""}`;t(A)},[e,t,r.pathname]),u=S(n=>{let i=new URLSearchParams(e.toString());i.delete(n);let a=i.toString(),o=`${r.pathname||"/"}${a?`?${a}`:""}`;t(o)},[e,t,r.pathname]),s=S(()=>{let n=r.pathname||"/";t(n)},[t,r.pathname]);return{query:e,setQuery:c,removeQuery:u,clearQueries:s}}import{useMemo as $}from"react";import{isClient as Q,FEATURE_STATUS as j}from"@donotdev/core";import{useAuthConfig as q}from"@donotdev/core";import*as U from"@donotdev/auth";import{DEGRADED_AUTH_API as M}from"@donotdev/core";var v=U?.useAuth;function K(e){return M[e]}function d(e){return v?v(e):K(e)}function B(e={}){let{auth:t,redirectTo:r,condition:c}=e,u=m(),s=q(),n=d("user"),i=d("can"),a=d("status");return $(()=>{if(!Q())return{shouldRedirect:!1,redirectTo:null,isChecking:!1};if(a===j.INITIALIZING)return{shouldRedirect:!1,redirectTo:null,isChecking:!0};if(c){let o=c(n,a);return{shouldRedirect:o,redirectTo:o&&r||null,isChecking:!1}}if(t!==!1&&t!==void 0){if(!i)return{shouldRedirect:!1,redirectTo:null,isChecking:!1};if(!i.navigate(t)){let o=null;return typeof t=="object"&&t.required&&!n?u.search.includes("code=")||u.search.includes("state=")||u.search.includes("error=")?o=`${s.authRoute}${u.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,i,c,r,u.search,s.authRoute,s.roleRoute,s.tierRoute])}export{w as useBack,m as useLocation,_ as useMatch,h as useNavigate,g as useParams,b as usePrefetch,N as useQueryParams,B as useRedirectGuard,E as useRefresh,O as useRouteParam,R as useSearchParams};
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) => Promise<void>;
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":"AAmBA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,SAAS,CAAC;AAE/C,wBAAgB,WAAW,SAKZ,MAAM,YAAY,eAAe,mBAgC/C;AAED,wBAAgB,OAAO,eAGtB;AAED,wBAAgB,UAAU,eAGzB;AAED,wBAAgB,WAAW,SAED,MAAM,UAC/B"}
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(async (to, options) => {
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":"AAmBA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,SAAS,CAAC;AAE/C,wBAAgB,WAAW,SAKZ,MAAM,YAAY,eAAe,mBAmB/C;AAED,wBAAgB,OAAO,+BAGtB;AAED,wBAAgB,UAAU,eAIzB;AAED,wBAAgB,WAAW,UACA,MAAM,UAGhC"}
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(async (to, options) => {
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,3 +1,4 @@
1
+ import type { NavigationRoute as CoreNavigationRoute } from '@donotdev/core';
1
2
  import type { JSX } from 'react';
2
3
  import type { ReactNode } from 'react';
3
4
  /**
@@ -41,22 +42,10 @@ export interface RouteGroup {
41
42
  routes: RouteInfo[];
42
43
  }
43
44
  /**
44
- * Navigation route interface for UI components
45
- *
46
- * @version 0.0.1
47
- * @since 0.0.1
48
- * @author AMBROISE PARK Consulting
45
+ * Navigation route - re-exported from @donotdev/core (Item 90)
46
+ * Core's version is the single source of truth with richer fields.
49
47
  */
50
- export interface NavigationRoute {
51
- /** Route path */
52
- path: string;
53
- /** Display label */
54
- label: string;
55
- /** Optional icon component */
56
- icon?: ReactNode;
57
- /** Additional route metadata */
58
- meta?: any;
59
- }
48
+ export type NavigationRoute = CoreNavigationRoute;
60
49
  /**
61
50
  * Hook that provides auto-discovered routes from virtual module system
62
51
  *
@@ -1 +1 @@
1
- {"version":3,"file":"useRouteDiscovery.d.ts","sourceRoot":"","sources":["../../src/routing/useRouteDiscovery.ts"],"names":[],"mappings":"AAsCA,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,OAAO,CAAC;AACjC,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAKvC;;;;;;GAMG;AACH,MAAM,WAAW,SAAS;IACxB,mDAAmD;IACnD,IAAI,EAAE,MAAM,CAAC;IACb,0CAA0C;IAC1C,KAAK,EAAE,MAAM,CAAC;IACd,2DAA2D;IAC3D,IAAI,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC1B,sEAAsE;IACtE,SAAS,EAAE,MAAM,CAAC;IAClB,8DAA8D;IAC9D,UAAU,EAAE,MAAM,CAAC;IACnB,oEAAoE;IACpE,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,iDAAiD;IACjD,IAAI,CAAC,EAAE,OAAO,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACzC,gCAAgC;IAChC,IAAI,CAAC,EAAE,OAAO,CAAC;CAChB;AAED;;;;;;GAMG;AACH,MAAM,WAAW,UAAU;IACzB,0CAA0C;IAC1C,KAAK,EAAE,MAAM,CAAC;IACd,kCAAkC;IAClC,IAAI,CAAC,EAAE,GAAG,CAAC,OAAO,CAAC;IACnB,qCAAqC;IACrC,MAAM,EAAE,SAAS,EAAE,CAAC;CACrB;AAED;;;;;;GAMG;AACH,MAAM,WAAW,eAAe;IAC9B,iBAAiB;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,oBAAoB;IACpB,KAAK,EAAE,MAAM,CAAC;IACd,8BAA8B;IAC9B,IAAI,CAAC,EAAE,SAAS,CAAC;IACjB,gCAAgC;IAChC,IAAI,CAAC,EAAE,GAAG,CAAC;CACZ;AAED;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,wBAAgB,iBAAiB,IAAI,UAAU,EAAE,CA2BhD;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,wBAAgB,mBAAmB,IAAI,UAAU,EAAE,CAmBlD;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,wBAAgB,6BAA6B,IAAI,eAAe,EAAE,CAgBjE;AAED;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAgB,YAAY,gBAK3B;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AACH,wBAAgB,gBAAgB;;;;;;SAQ/B"}
1
+ {"version":3,"file":"useRouteDiscovery.d.ts","sourceRoot":"","sources":["../../src/routing/useRouteDiscovery.ts"],"names":[],"mappings":"AAiCA,OAAO,KAAK,EAEV,eAAe,IAAI,mBAAmB,EACvC,MAAM,gBAAgB,CAAC;AAIxB,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,OAAO,CAAC;AACjC,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAKvC;;;;;;GAMG;AACH,MAAM,WAAW,SAAS;IACxB,mDAAmD;IACnD,IAAI,EAAE,MAAM,CAAC;IACb,0CAA0C;IAC1C,KAAK,EAAE,MAAM,CAAC;IACd,2DAA2D;IAC3D,IAAI,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC1B,sEAAsE;IACtE,SAAS,EAAE,MAAM,CAAC;IAClB,8DAA8D;IAC9D,UAAU,EAAE,MAAM,CAAC;IACnB,oEAAoE;IACpE,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,iDAAiD;IACjD,IAAI,CAAC,EAAE,OAAO,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACzC,gCAAgC;IAChC,IAAI,CAAC,EAAE,OAAO,CAAC;CAChB;AAED;;;;;;GAMG;AACH,MAAM,WAAW,UAAU;IACzB,0CAA0C;IAC1C,KAAK,EAAE,MAAM,CAAC;IACd,kCAAkC;IAClC,IAAI,CAAC,EAAE,GAAG,CAAC,OAAO,CAAC;IACnB,qCAAqC;IACrC,MAAM,EAAE,SAAS,EAAE,CAAC;CACrB;AAED;;;GAGG;AACH,MAAM,MAAM,eAAe,GAAG,mBAAmB,CAAC;AAElD;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,wBAAgB,iBAAiB,IAAI,UAAU,EAAE,CA2BhD;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,wBAAgB,mBAAmB,IAAI,UAAU,EAAE,CAoBlD;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,wBAAgB,6BAA6B,IAAI,eAAe,EAAE,CAcjE;AAED;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAgB,YAAY,gBAK3B;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AACH,wBAAgB,gBAAgB;;;;;;SAQ/B"}
@@ -23,7 +23,7 @@
23
23
  * ```
24
24
  */
25
25
  import { useMemo } from 'react';
26
- import { useNavigationStore, getRoutes, getRouteManifest, buildRoutePath, } from '@donotdev/core';
26
+ import { useNavigationStore, getRoutes, getRouteManifest, } from '@donotdev/core';
27
27
  import { useAuthSafe } from '../utils/useAuthSafe';
28
28
  /**
29
29
  * Hook that provides auto-discovered routes from virtual module system
@@ -108,9 +108,11 @@ export function useAccessibleRoutes() {
108
108
  .map((group) => ({
109
109
  ...group,
110
110
  routes: group.routes.filter((route) => {
111
- // Use same filtering logic as AuthGuard for consistency
111
+ // Use same filtering logic as AuthGuard for consistency (Item 88)
112
112
  if (route.auth === false)
113
113
  return true;
114
+ if (route.auth === true)
115
+ return !!user;
114
116
  if (typeof route.auth === 'object' && route.auth.required) {
115
117
  return !!user;
116
118
  }
@@ -149,9 +151,8 @@ export function useAccessibleRoutes() {
149
151
  */
150
152
  export function useAccessibleNavigationRoutes() {
151
153
  const user = useAuthSafe('user');
152
- const { getFilteredRoutes } = useNavigationStore();
153
154
  return useMemo(() => {
154
- const filteredRoutes = getFilteredRoutes({
155
+ const filteredRoutes = useNavigationStore.getState().getFilteredRoutes({
155
156
  authenticated: !!user,
156
157
  role: user?.role || 'user',
157
158
  });
@@ -161,7 +162,7 @@ export function useAccessibleNavigationRoutes() {
161
162
  icon: route.icon,
162
163
  meta: route.meta,
163
164
  }));
164
- }, [getFilteredRoutes, user]);
165
+ }, [user]);
165
166
  }
166
167
  /**
167
168
  * Hook that returns all discovered routes as a flat list
@@ -3418,80 +3418,120 @@ em {
3418
3418
 
3419
3419
  /* packages/components/src/atomic/Combobox/Combobox.css */
3420
3420
 
3421
- .dndev-combobox-trigger {
3422
- display: flex;
3423
- justify-content: space-between;
3424
- align-items: center;
3425
- width: 100%;
3426
- text-align: start;
3427
- }
3421
+ /* ──────────────────────────────────────────────────
3422
+ Trailing icon group — flex row inside the input area
3423
+ ────────────────────────────────────────────────── */
3428
3424
 
3429
- .dndev-combobox-trigger button {
3425
+ .dndev-combobox-trailing {
3426
+ position: absolute;
3427
+ inset-inline-end: var(--gap-sm);
3428
+ top: 0;
3429
+ height: 100%;
3430
3430
  display: flex;
3431
- justify-content: space-between;
3432
3431
  align-items: center;
3433
- width: 100%;
3432
+ gap: var(--gap-tight, 4px);
3433
+ z-index: 1;
3434
+ pointer-events: none; /* pass clicks through to input by default */
3434
3435
  }
3435
3436
 
3436
- .dndev-combobox-placeholder {
3437
- opacity: var(--opacity-muted);
3438
- }
3437
+ /* Input padding: reserve space for trailing content.
3438
+ --combobox-pad-end is set as an inline CSS variable on .dndev-combobox-wrapper. */
3439
3439
 
3440
- .dndev-combobox-trigger-icons {
3441
- display: flex;
3442
- align-items: center;
3443
- gap: var(--gap-tight);
3444
- margin-inline-start: auto;
3440
+ .dndev-combobox-wrapper .dndev-input {
3441
+ padding-inline-end: var(--combobox-pad-end);
3445
3442
  }
3446
3443
 
3447
- .dndev-combobox-clear {
3444
+ /* Action buttons (create "+", clear "X") */
3445
+
3446
+ .dndev-combobox-action-btn {
3447
+ all: unset;
3448
3448
  display: flex;
3449
3449
  align-items: center;
3450
3450
  justify-content: center;
3451
+ width: var(--icon-md);
3452
+ height: var(--icon-md);
3453
+ border-radius: var(--radius-interactive, var(--radius-sm, 4px));
3451
3454
  cursor: pointer;
3452
- opacity: var(--opacity-muted);
3453
- transition: opacity var(--dur-fast) var(--ease-in-out);
3454
- -webkit-user-select: none;
3455
- -moz-user-select: none;
3456
- user-select: none;
3455
+ pointer-events: auto; /* re-enable clicks on buttons */
3456
+ color: var(--muted-foreground);
3457
+ opacity: var(--opacity-muted, 0.5);
3458
+ transition:
3459
+ opacity var(--dur-fast) var(--ease-in-out),
3460
+ background-color var(--dur-fast) var(--ease-in-out);
3457
3461
  }
3458
3462
 
3459
- .dndev-combobox-clear:hover,
3460
- .dndev-combobox-clear:focus {
3463
+ .dndev-combobox-action-btn:hover {
3464
+ opacity: 1;
3465
+ background-color: var(--accent, rgba(0, 0, 0, 0.06));
3466
+ }
3467
+
3468
+ .dndev-combobox-action-btn:focus-visible {
3461
3469
  opacity: 1;
3462
3470
  outline: none;
3471
+ box-shadow:
3472
+ 0 0 0 2px var(--ring),
3473
+ 0 0 0 4px rgb(from var(--ring) r g b / 0.2);
3463
3474
  }
3464
3475
 
3465
- .dndev-combobox-clear svg {
3466
- width: var(--icon-sm);
3467
- height: var(--icon-sm);
3476
+ .dndev-combobox-action-btn:active {
3477
+ opacity: 0.8;
3468
3478
  }
3469
3479
 
3480
+ .dndev-combobox-action-btn svg {
3481
+ width: var(--size-icon-sm, 16px);
3482
+ height: var(--size-icon-sm, 16px);
3483
+ }
3484
+
3485
+ /* Create button accent color */
3486
+
3487
+ .dndev-combobox-action-btn--create {
3488
+ color: var(--primary);
3489
+ }
3490
+
3491
+ /* Clear button */
3492
+
3493
+ .dndev-combobox-action-btn--clear {
3494
+ color: var(--muted-foreground);
3495
+ }
3496
+
3497
+ /* Chevron indicator (non-interactive, just visual) */
3498
+
3470
3499
  .dndev-combobox-chevron {
3471
3500
  width: var(--icon-md);
3472
3501
  height: var(--icon-md);
3502
+ display: flex;
3503
+ align-items: center;
3504
+ justify-content: center;
3505
+ color: var(--muted-foreground);
3473
3506
  opacity: var(--opacity-muted);
3507
+ pointer-events: none;
3508
+ }
3509
+
3510
+ .dndev-combobox-chevron svg {
3511
+ width: var(--icon-md);
3512
+ height: var(--icon-md);
3474
3513
  transition: transform var(--dur-fast) var(--ease-in-out);
3475
3514
  }
3476
3515
 
3477
- [data-state='open'] .dndev-combobox-chevron {
3516
+ .dndev-combobox-open .dndev-combobox-chevron svg {
3478
3517
  transform: rotate(180deg);
3479
3518
  }
3480
3519
 
3481
- .dndev-combobox-loading-container {
3520
+ /* Spinner replaces chevron */
3521
+
3522
+ .dndev-combobox-spinner {
3482
3523
  display: flex;
3483
3524
  align-items: center;
3484
- gap: var(--gap-sm);
3485
- }
3486
-
3487
- .dndev-combobox-loading-spinner {
3525
+ justify-content: center;
3488
3526
  width: var(--icon-md);
3489
3527
  height: var(--icon-md);
3490
- border-radius: var(--radius-full);
3491
- border: 2px solid currentColor;
3492
- border-top-color: transparent;
3528
+ pointer-events: none;
3493
3529
  }
3494
3530
 
3531
+ /* ──────────────────────────────────────────────────
3532
+ Dropdown content
3533
+ ────────────────────────────────────────────────── */
3534
+
3495
3535
  .dndev-combobox-content {
3496
3536
  width: var(--radix-popover-trigger-width);
3497
3537
  min-width: var(--radix-popover-trigger-width);
@@ -3501,15 +3541,6 @@ em {
3501
3541
  padding: 0;
3502
3542
  }
3503
3543
 
3504
- .dndev-combobox-search-container {
3505
- padding: var(--gap-sm);
3506
- border-bottom: var(--border-width) solid var(--line-2);
3507
- }
3508
-
3509
- .dndev-combobox-search-input {
3510
- width: 100%;
3511
- }
3512
-
3513
3544
  .dndev-combobox-option {
3514
3545
  all: unset;
3515
3546
  display: flex;
@@ -3580,16 +3611,6 @@ em {
3580
3611
  flex-shrink: 0;
3581
3612
  }
3582
3613
 
3583
- .dndev-combobox-open .dndev-input-with-trailing-icon .dndev-input-icon svg,
3584
- .dndev-combobox-open .dndev-input-with-trailing-icon .dndev-input-icon > * {
3585
- transform: rotate(180deg);
3586
- }
3587
-
3588
- .dndev-input-with-trailing-icon .dndev-input-icon svg,
3589
- .dndev-input-with-trailing-icon .dndev-input-icon > * {
3590
- transition: transform var(--dur-fast) var(--ease-in-out);
3591
- }
3592
-
3593
3614
  /* packages/components/src/atomic/DualCard/DualCard.css */
3594
3615
 
3595
3616
  .dndev-dual-card {
@@ -9485,9 +9506,15 @@ main[role='main'][data-routing-animation='none'] {
9485
9506
  /* Desktop: opt-in via data-footer-mode="scroll" */
9486
9507
 
9487
9508
  .dndev-layout[data-footer-mode='scroll'] {
9488
- overflow-y: auto;
9509
+ height: auto;
9510
+ min-height: 100dvh;
9511
+ max-height: none;
9512
+ overflow-y: visible;
9489
9513
  overflow-x: hidden;
9490
- grid-template-rows: var(--header-height) 1fr auto;
9514
+ grid-template-rows: var(--header-height) minmax(
9515
+ calc(100dvh - var(--header-height)),
9516
+ auto
9517
+ ) auto;
9491
9518
  }
9492
9519
 
9493
9520
  .dndev-layout[data-footer-mode='scroll'] header[role='banner'] {
@@ -9511,6 +9538,7 @@ main[role='main'][data-routing-animation='none'] {
9511
9538
  .dndev-layout[data-footer-mode='scroll'] footer[role='contentinfo'] {
9512
9539
  grid-column: 2 / -1;
9513
9540
  height: auto;
9541
+ margin-top: var(--gap-lg);
9514
9542
  }
9515
9543
 
9516
9544
  :is(.dndev-layout[data-footer-mode='scroll'] footer[role='contentinfo']) > * {
@@ -9522,9 +9550,15 @@ main[role='main'][data-routing-animation='none'] {
9522
9550
 
9523
9551
  @media (width <=1023px) {
9524
9552
  .dndev-layout {
9525
- overflow-y: auto;
9553
+ height: auto;
9554
+ min-height: 100dvh;
9555
+ max-height: none;
9556
+ overflow-y: visible;
9526
9557
  overflow-x: hidden;
9527
- grid-template-rows: var(--header-height) 1fr auto;
9558
+ grid-template-rows: var(--header-height) minmax(
9559
+ calc(100dvh - var(--header-height)),
9560
+ auto
9561
+ ) auto;
9528
9562
  }
9529
9563
 
9530
9564
  .dndev-layout header[role='banner'] {
@@ -9540,6 +9574,7 @@ main[role='main'][data-routing-animation='none'] {
9540
9574
 
9541
9575
  .dndev-layout footer[role='contentinfo'] {
9542
9576
  height: auto;
9577
+ margin-top: var(--gap-lg);
9543
9578
  }
9544
9579
 
9545
9580
  :is(.dndev-layout footer[role='contentinfo']) > * {
@@ -9587,7 +9622,6 @@ header[role='banner'] {
9587
9622
  padding-inline-start: var(--content-padding);
9588
9623
  padding-inline-end: var(--content-padding);
9589
9624
 
9590
- /* Theme-aware styling - 100% controlled by theme system */
9591
9625
  background: var(--background);
9592
9626
  border-bottom: var(--border-hairline) solid var(--border);
9593
9627
 
@@ -9936,7 +9970,6 @@ footer[role='contentinfo'] {
9936
9970
  min-height: var(--footer-height);
9937
9971
  z-index: var(--z-footer);
9938
9972
 
9939
- /* Theme-aware styling - 100% controlled by theme system */
9940
9973
  background: var(--background);
9941
9974
  border-top: var(--border-hairline) solid var(--border);
9942
9975
 
@@ -1 +1 @@
1
- {"version":3,"file":"sanitizeSvg.d.ts","sourceRoot":"","sources":["../../src/utils/sanitizeSvg.ts"],"names":[],"mappings":"AA+BA;;;;;;;;;;GAUG;AACH,wBAAgB,WAAW,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAO/C"}
1
+ {"version":3,"file":"sanitizeSvg.d.ts","sourceRoot":"","sources":["../../src/utils/sanitizeSvg.ts"],"names":[],"mappings":"AAiCA;;;;;;;;;;GAUG;AACH,wBAAgB,WAAW,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAO/C"}