@donotdev/ui 0.0.9 → 0.0.10
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/crud/components/fields/display/DateFieldDisplay.d.ts.map +1 -1
- package/dist/crud/components/fields/display/DateFieldDisplay.js +2 -3
- package/dist/crud/components/fields/display/LinkFieldDisplay.d.ts.map +1 -1
- package/dist/crud/components/fields/display/LinkFieldDisplay.js +6 -5
- package/dist/crud/components/fields/display/NumberFieldDisplay.d.ts.map +1 -1
- package/dist/crud/components/fields/display/NumberFieldDisplay.js +2 -3
- package/dist/crud/components/fields/display/PhoneNumberDisplay.d.ts.map +1 -1
- package/dist/crud/components/fields/display/PhoneNumberDisplay.js +1 -2
- package/dist/dndev.css +288 -143
- package/dist/index.js +5 -5
- package/dist/internal/common/RouteErrorFallback.d.ts.map +1 -1
- package/dist/internal/common/RouteErrorFallback.js +1 -2
- package/dist/internal/layout/DnDevLayout.d.ts.map +1 -1
- package/dist/internal/layout/DnDevLayout.js +3 -2
- package/dist/internal/layout/components/footer/FooterBranding.d.ts +0 -2
- package/dist/internal/layout/components/footer/FooterBranding.d.ts.map +1 -1
- package/dist/internal/layout/components/footer/FooterBranding.js +2 -6
- package/dist/internal/layout/components/footer/FooterCopyright.d.ts +0 -2
- package/dist/internal/layout/components/footer/FooterCopyright.d.ts.map +1 -1
- package/dist/internal/layout/components/footer/FooterCopyright.js +2 -6
- package/dist/internal/layout/config/presets/moolti.js +2 -2
- package/dist/internal/layout/zones/DnDevFooter.d.ts.map +1 -1
- package/dist/internal/layout/zones/DnDevFooter.js +2 -2
- package/dist/routing/GoTo.d.ts +1 -1
- package/dist/routing/GoTo.d.ts.map +1 -1
- package/dist/routing/GoTo.js +1 -1
- package/dist/routing/hooks/hooks.next.js +1 -1
- package/dist/routing/hooks/hooks.vite.js +1 -1
- package/dist/routing/hooks/useFormNavigationBlocker.d.ts +14 -0
- package/dist/routing/hooks/useFormNavigationBlocker.d.ts.map +1 -0
- package/dist/routing/hooks/useFormNavigationBlocker.js +42 -0
- 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 +7 -1
- 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 +7 -1
- package/dist/styles/index.css +288 -143
- 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/useFormStoreSafe.d.ts +59 -0
- package/dist/utils/useFormStoreSafe.d.ts.map +1 -0
- package/dist/utils/useFormStoreSafe.js +115 -0
- package/package.json +5 -5
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"RouteErrorFallback.d.ts","sourceRoot":"","sources":["../../../src/internal/common/RouteErrorFallback.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"RouteErrorFallback.d.ts","sourceRoot":"","sources":["../../../src/internal/common/RouteErrorFallback.tsx"],"names":[],"mappings":"AAqCA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,OAAO,CAAC;AAE3C,UAAU,uBAAuB;IAC/B,KAAK,EAAE,OAAO,CAAC;IACf,UAAU,EAAE,MAAM,IAAI,CAAC;IACvB,cAAc,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC/B,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CACzB;AAED;;;;;;;;;GASG;AACH,eAAO,MAAM,kBAAkB,EAAE,aAAa,CAAC,uBAAuB,CAyPrE,CAAC;AAEF,eAAe,kBAAkB,CAAC"}
|
|
@@ -14,7 +14,6 @@ import { useEffect, useState } from 'react';
|
|
|
14
14
|
import { Button, BUTTON_VARIANT, Card, CARD_VARIANT, Alert, ALERT_VARIANT, Stack, } from '@donotdev/components';
|
|
15
15
|
import { handleError, useTranslation } from '@donotdev/core';
|
|
16
16
|
import { useLocation, useBack } from '@donotdev/ui/routing/hooks';
|
|
17
|
-
import { PageContainer } from '../../components/layout/PageContainer';
|
|
18
17
|
// Platform-specific hooks via conditional exports
|
|
19
18
|
import { Link } from '../../routing/Link';
|
|
20
19
|
/**
|
|
@@ -95,7 +94,7 @@ export const RouteErrorFallback = ({ error, resetError, componentStack, eventId,
|
|
|
95
94
|
}
|
|
96
95
|
}
|
|
97
96
|
};
|
|
98
|
-
return (_jsx(
|
|
97
|
+
return (_jsx("div", { className: "dndev-container", "data-variant": "standard", "data-centered": "true", children: _jsx(Card, { variant: CARD_VARIANT.DEFAULT, elevated: true, className: "dndev-w-full", style: { maxWidth: '65ch', margin: '0 auto' }, children: _jsxs(Stack, { gap: "large", align: "center", className: "dndev-text-center", children: [_jsx(Stack, { align: "center", justify: "center", style: {
|
|
99
98
|
width: '5rem',
|
|
100
99
|
height: '5rem',
|
|
101
100
|
backgroundColor: 'rgba(220, 38, 38, 0.1)',
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"DnDevLayout.d.ts","sourceRoot":"","sources":["../../../src/internal/layout/DnDevLayout.tsx"],"names":[],"mappings":"AAGA;;;;;;;;GAQG;AAEH,OAAO,EAQL,KAAK,SAAS,EACf,MAAM,OAAO,CAAC;AAGf,OAAO,KAAK,EAIV,YAAY,EACb,MAAM,gBAAgB,CAAC;AA0CxB,UAAU,yBAAyB;IACjC,MAAM,CAAC,EAAE,YAAY,CAAC;IACtB,QAAQ,CAAC,EAAE,SAAS,CAAC;IACrB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED;;;;;;;;;;;;;;GAcG;AACH,eAAO,MAAM,WAAW,GAAI,kCAIzB,yBAAyB,
|
|
1
|
+
{"version":3,"file":"DnDevLayout.d.ts","sourceRoot":"","sources":["../../../src/internal/layout/DnDevLayout.tsx"],"names":[],"mappings":"AAGA;;;;;;;;GAQG;AAEH,OAAO,EAQL,KAAK,SAAS,EACf,MAAM,OAAO,CAAC;AAGf,OAAO,KAAK,EAIV,YAAY,EACb,MAAM,gBAAgB,CAAC;AA0CxB,UAAU,yBAAyB;IACjC,MAAM,CAAC,EAAE,YAAY,CAAC;IACtB,QAAQ,CAAC,EAAE,SAAS,CAAC;IACrB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED;;;;;;;;;;;;;;GAcG;AACH,eAAO,MAAM,WAAW,GAAI,kCAIzB,yBAAyB,4CAwT3B,CAAC"}
|
|
@@ -66,8 +66,9 @@ export const DnDevLayout = ({ children, layout, className, }) => {
|
|
|
66
66
|
const app = useAppConfig('app');
|
|
67
67
|
// Subscribe to language changes for zone re-renders
|
|
68
68
|
useTranslation('dndev');
|
|
69
|
-
//
|
|
69
|
+
// Layout config props
|
|
70
70
|
const breadcrumbs = layout?.breadcrumbs ?? 'smart';
|
|
71
|
+
const footerMode = layout?.footerMode;
|
|
71
72
|
// Route detection for animations
|
|
72
73
|
const location = useLocation();
|
|
73
74
|
const pathname = location.pathname;
|
|
@@ -246,5 +247,5 @@ export const DnDevLayout = ({ children, layout, className, }) => {
|
|
|
246
247
|
};
|
|
247
248
|
startTransition(updateDOM);
|
|
248
249
|
}, [effectivePreset]);
|
|
249
|
-
return (_jsxs("div", { className: cn('dndev-layout', className), children: [resolvedHeader, resolvedSidebar, _jsxs("main", { ref: mainRef, role: "main", className: "main", children: [breadcrumbs !== 'never' && (_jsx("div", { className: "breadcrumbs-container", children: _jsx(Breadcrumbs, { variant: breadcrumbs === 'always' ? 'default' : 'smart' }) })), isDev() && (_jsx(Suspense, { fallback: null, children: _jsx(DebugTools, {}) })),
|
|
250
|
+
return (_jsxs("div", { className: cn('dndev-layout', className), "data-footer-mode": footerMode, children: [resolvedHeader, resolvedSidebar, _jsxs("main", { ref: mainRef, role: "main", className: "main", children: [breadcrumbs !== 'never' && (_jsx("div", { className: "breadcrumbs-container", children: _jsx(Breadcrumbs, { variant: breadcrumbs === 'always' ? 'default' : 'smart' }) })), isDev() && (_jsx(Suspense, { fallback: null, children: _jsx(DebugTools, {}) })), content] }), resolvedFooter, resolvedMergedBar, _jsx(GoToWrapper, {})] }));
|
|
250
251
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"FooterBranding.d.ts","sourceRoot":"","sources":["../../../../../src/internal/layout/components/footer/FooterBranding.tsx"],"names":[],"mappings":"AAeA,MAAM,WAAW,mBAAmB;IAClC,6BAA6B;IAC7B,SAAS,CAAC,EAAE,MAAM,CAAC;
|
|
1
|
+
{"version":3,"file":"FooterBranding.d.ts","sourceRoot":"","sources":["../../../../../src/internal/layout/components/footer/FooterBranding.tsx"],"names":[],"mappings":"AAeA,MAAM,WAAW,mBAAmB;IAClC,6BAA6B;IAC7B,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED;;;;;;;;;GASG;AACH,eAAO,MAAM,cAAc,EAAE,KAAK,CAAC,aAAa,CAAC,mBAAmB,CA8BnE,CAAC;AAEF,eAAe,cAAc,CAAC"}
|
|
@@ -20,20 +20,16 @@ import { useAppConfig } from '@donotdev/core';
|
|
|
20
20
|
* @since 0.0.1
|
|
21
21
|
* @author AMBROISE PARK Consulting
|
|
22
22
|
*/
|
|
23
|
-
export const FooterBranding = ({ className,
|
|
23
|
+
export const FooterBranding = ({ className, }) => {
|
|
24
24
|
const appUrl = useAppConfig('url');
|
|
25
25
|
const isFrameworkSite = appUrl === 'https://donotdev.com';
|
|
26
|
-
const sizeStyles = {
|
|
27
|
-
xs: { fontSize: 'var(--font-size-xs)' },
|
|
28
|
-
sm: { fontSize: 'var(--font-size-sm)' },
|
|
29
|
-
};
|
|
30
26
|
return (_jsxs("a", { href: isFrameworkSite
|
|
31
27
|
? 'https://www.ambroise-park.com'
|
|
32
28
|
: 'https://donotdev.com', target: "_blank", rel: "noopener noreferrer", className: className, style: {
|
|
33
29
|
display: 'inline-flex',
|
|
34
30
|
alignItems: 'center',
|
|
35
31
|
gap: 'var(--gap-sm)',
|
|
36
|
-
|
|
32
|
+
fontSize: 'var(--font-size-xs)',
|
|
37
33
|
}, children: [isFrameworkSite ? 'AMBROISE-PARK' : 'DoNotDev', _jsx(ExternalLink, { style: { width: '12px', height: '12px' }, "aria-hidden": "true" })] }));
|
|
38
34
|
};
|
|
39
35
|
export default FooterBranding;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"FooterCopyright.d.ts","sourceRoot":"","sources":["../../../../../src/internal/layout/components/footer/FooterCopyright.tsx"],"names":[],"mappings":"AAcA,MAAM,WAAW,oBAAoB;IACnC,wDAAwD;IACxD,OAAO,CAAC,EAAE,MAAM,CAAC;IAEjB,gDAAgD;IAChD,IAAI,CAAC,EAAE,MAAM,CAAC;IAEd,6BAA6B;IAC7B,SAAS,CAAC,EAAE,MAAM,CAAC;
|
|
1
|
+
{"version":3,"file":"FooterCopyright.d.ts","sourceRoot":"","sources":["../../../../../src/internal/layout/components/footer/FooterCopyright.tsx"],"names":[],"mappings":"AAcA,MAAM,WAAW,oBAAoB;IACnC,wDAAwD;IACxD,OAAO,CAAC,EAAE,MAAM,CAAC;IAEjB,gDAAgD;IAChD,IAAI,CAAC,EAAE,MAAM,CAAC;IAEd,6BAA6B;IAC7B,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED;;;;;;;;;GASG;AACH,eAAO,MAAM,eAAe,EAAE,KAAK,CAAC,aAAa,CAAC,oBAAoB,CAqBrE,CAAC;AAEF,eAAe,eAAe,CAAC"}
|
|
@@ -20,18 +20,14 @@ import { useTranslation, useAppConfig } from '@donotdev/core';
|
|
|
20
20
|
* @since 0.0.1
|
|
21
21
|
* @author AMBROISE PARK Consulting
|
|
22
22
|
*/
|
|
23
|
-
export const FooterCopyright = ({ appName, year = new Date().getFullYear(), className,
|
|
23
|
+
export const FooterCopyright = ({ appName, year = new Date().getFullYear(), className, }) => {
|
|
24
24
|
const { t } = useTranslation('dndev');
|
|
25
25
|
const app = useAppConfig('app');
|
|
26
26
|
const resolvedAppName = appName || app?.name || 'App';
|
|
27
|
-
const sizeStyles = {
|
|
28
|
-
xs: { fontSize: 'var(--font-size-xs)' },
|
|
29
|
-
sm: { fontSize: 'var(--font-size-sm)' },
|
|
30
|
-
};
|
|
31
27
|
return (_jsxs("span", { className: cn(className), style: {
|
|
32
28
|
flexShrink: 0,
|
|
33
29
|
color: 'var(--muted-foreground)',
|
|
34
|
-
|
|
30
|
+
fontSize: 'var(--font-size-xs)',
|
|
35
31
|
}, children: ["\u00A9 ", year, " ", resolvedAppName, ". ", t('footer.legal.allRightsReserved')] }));
|
|
36
32
|
};
|
|
37
33
|
export default FooterCopyright;
|
|
@@ -32,7 +32,7 @@ export const mooltiPreset = {
|
|
|
32
32
|
sidebar: {
|
|
33
33
|
top: () => _jsx(AppBranding, { display: DISPLAY.AUTO }),
|
|
34
34
|
content: () => (_jsxs(_Fragment, { children: [_jsx(GoTo, { display: DISPLAY.AUTO }), _jsx(DnDevNavigationMenu, { vertical: true, display: DISPLAY.AUTO })] })),
|
|
35
|
-
bottom: () => (_jsxs(Stack, { direction: "column", gap: "tight", align: "stretch", children: [_jsx(AuthHeader, { display: DISPLAY.AUTO }), _jsx(LanguageSelector, { display: DISPLAY.AUTO }), _jsx(ThemeToggle, { display: DISPLAY.AUTO }), _jsx(FooterCopyright, {
|
|
35
|
+
bottom: () => (_jsxs(Stack, { direction: "column", gap: "tight", align: "stretch", children: [_jsx(AuthHeader, { display: DISPLAY.AUTO }), _jsx(LanguageSelector, { display: DISPLAY.AUTO }), _jsx(ThemeToggle, { display: DISPLAY.AUTO }), _jsx(FooterCopyright, {})] })),
|
|
36
36
|
defaultWidth: 256,
|
|
37
37
|
minWidth: 48,
|
|
38
38
|
maxWidth: 400,
|
|
@@ -48,7 +48,7 @@ export const mooltiPreset = {
|
|
|
48
48
|
_jsxs(_Fragment, { children: [_jsx(GoTo, { display: DISPLAY.AUTO }), _jsx(DnDevNavigationMenu, { vertical: true, display: DISPLAY.AUTO })] })),
|
|
49
49
|
bottom: () => (
|
|
50
50
|
// sidebar.bottom → bottom (Auth, Language, Theme, Footer)
|
|
51
|
-
_jsxs(Stack, { direction: "column", gap: "tight", align: "stretch", children: [_jsx(AuthHeader, { display: DISPLAY.AUTO }), _jsx(LanguageSelector, { display: DISPLAY.AUTO }), _jsx(ThemeToggle, { display: DISPLAY.AUTO }), _jsx(FooterCopyright, {
|
|
51
|
+
_jsxs(Stack, { direction: "column", gap: "tight", align: "stretch", children: [_jsx(AuthHeader, { display: DISPLAY.AUTO }), _jsx(LanguageSelector, { display: DISPLAY.AUTO }), _jsx(ThemeToggle, { display: DISPLAY.AUTO }), _jsx(FooterCopyright, {})] })),
|
|
52
52
|
},
|
|
53
53
|
},
|
|
54
54
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"DnDevFooter.d.ts","sourceRoot":"","sources":["../../../../src/internal/layout/zones/DnDevFooter.tsx"],"names":[],"mappings":"AAkBA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAUlD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAGvC,MAAM,WAAW,gBAAgB;IAC/B,uCAAuC;IACvC,GAAG,CAAC,EAAE,WAAW,CAAC;CACnB;AAED;;;;;;;;;;;;;GAaG;AACH,iBAAS,oBAAoB,CAAC,EAAE,GAAQ,EAAE,EAAE,gBAAgB,GAAG,SAAS,
|
|
1
|
+
{"version":3,"file":"DnDevFooter.d.ts","sourceRoot":"","sources":["../../../../src/internal/layout/zones/DnDevFooter.tsx"],"names":[],"mappings":"AAkBA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAUlD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAGvC,MAAM,WAAW,gBAAgB;IAC/B,uCAAuC;IACvC,GAAG,CAAC,EAAE,WAAW,CAAC;CACnB;AAED;;;;;;;;;;;;;GAaG;AACH,iBAAS,oBAAoB,CAAC,EAAE,GAAQ,EAAE,EAAE,gBAAgB,GAAG,SAAS,CA8EvE;AAED,eAAO,MAAM,WAAW,kEAA6B,CAAC"}
|
|
@@ -49,9 +49,9 @@ function DnDevFooterComponent({ app = {} }) {
|
|
|
49
49
|
: copyrightConfig;
|
|
50
50
|
// Desktop/Wide: 2-zone layout [Copyright] | [Links + DoNotDev]
|
|
51
51
|
if (isLaptopOrDesktop) {
|
|
52
|
-
return (_jsx("footer", { role: "contentinfo", className: "footer", children: _jsxs(Stack, { direction: "row", align: "center", justify: "between", gap: "none", children: [showCopyright && (_jsx("div", { className: "dndev-flex dndev-justify-start", children: _jsx("span", { className: "footer-copyright", children: copyrightText }) })), _jsx("div", { className: "dndev-flex dndev-justify-end", children: _jsxs(Stack, { direction: "row", gap: "medium", align: "center", children: [links.map((link) => (_jsx(Link, { path: link.path, children: maybeTranslate(t, link.label) }, link.path))), _jsx(FooterBranding, {})] }) })] }) }));
|
|
52
|
+
return (_jsx("footer", { role: "contentinfo", className: "footer", children: _jsxs(Stack, { direction: "row", align: "center", justify: "between", gap: "none", children: [showCopyright && (_jsx("div", { className: "dndev-flex dndev-justify-start", children: _jsx("span", { className: "footer-copyright", children: copyrightText }) })), _jsx("div", { className: "dndev-flex dndev-justify-end", children: _jsxs(Stack, { direction: "row", gap: "medium", align: "center", children: [links.map((link) => (_jsx(Link, { path: link.path, style: { fontSize: 'var(--font-size-xs)' }, children: maybeTranslate(t, link.label) }, link.path))), _jsx(FooterBranding, {})] }) })] }) }));
|
|
53
53
|
}
|
|
54
54
|
// Mobile/Tablet: stacked layout
|
|
55
|
-
return (_jsx("footer", { role: "contentinfo", className: "footer", children: _jsxs(Stack, { align: "center", gap: "tight", children: [showCopyright && (_jsx("span", { className: "footer-copyright", children: copyrightText })), _jsxs(Stack, { direction: "row", wrap: "wrap", gap: "tight", justify: "center", align: "center", children: [links.map((link) => (_jsx(Link, { path: link.path, children: maybeTranslate(t, link.label) }, link.path))), _jsx(FooterBranding, {})] })] }) }));
|
|
55
|
+
return (_jsx("footer", { role: "contentinfo", className: "footer", children: _jsxs(Stack, { align: "center", gap: "tight", children: [showCopyright && (_jsx("span", { className: "footer-copyright", children: copyrightText })), _jsxs(Stack, { direction: "row", wrap: "wrap", gap: "tight", justify: "center", align: "center", children: [links.map((link) => (_jsx(Link, { path: link.path, style: { fontSize: 'var(--font-size-xs)' }, children: maybeTranslate(t, link.label) }, link.path))), _jsx(FooterBranding, {})] })] }) }));
|
|
56
56
|
}
|
|
57
57
|
export const DnDevFooter = memo(DnDevFooterComponent);
|
package/dist/routing/GoTo.d.ts
CHANGED
|
@@ -16,6 +16,6 @@ export interface GoToProps {
|
|
|
16
16
|
* Simple button: Search icon + "Go to" label + keyboard shortcut.
|
|
17
17
|
* Opens command dialog on click.
|
|
18
18
|
*/
|
|
19
|
-
export declare const GoTo: ({ display, className, onOpen }: GoToProps) => import("react/jsx-runtime").JSX.Element;
|
|
19
|
+
export declare const GoTo: ({ display, className, onOpen, }: GoToProps) => import("react/jsx-runtime").JSX.Element;
|
|
20
20
|
export default GoTo;
|
|
21
21
|
//# sourceMappingURL=GoTo.d.ts.map
|
|
@@ -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,
|
|
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,4CAsCX,CAAC;AAEF,eAAe,IAAI,CAAC"}
|
package/dist/routing/GoTo.js
CHANGED
|
@@ -17,7 +17,7 @@ import { useOverlayStore, useTranslation } from '@donotdev/core';
|
|
|
17
17
|
* Simple button: Search icon + "Go to" label + keyboard shortcut.
|
|
18
18
|
* Opens command dialog on click.
|
|
19
19
|
*/
|
|
20
|
-
export const GoTo = ({ display = DISPLAY.AUTO, className, onOpen }) => {
|
|
20
|
+
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)
|
|
@@ -1 +1 @@
|
|
|
1
|
-
"use client";import{useRouter as
|
|
1
|
+
"use client";import{useRouter as h}from"next/navigation";import{useCallback as p}from"react";import{isClient as F,useOverlayStore as w}from"@donotdev/core";import*as D from"@donotdev/crud";var m=D?.useFormStore,A={forms:{},startSubmit:()=>{},setUploading:()=>{},setValidating:()=>{},setSubmitting:()=>{},setSuccess:()=>{},setError:()=>{},reset:()=>{},cleanup:()=>{},setIsDirty:()=>{},hasDirtyForms:()=>!1,getDirtyFormIds:()=>[],getStatus:()=>"idle",isLoading:()=>!1,getUploadProgress:()=>0,getError:()=>null,getIsDirty:()=>!1};function x(e){return m?m(e):e(A)}x.getState=()=>m&&typeof m.getState=="function"?m.getState():A;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=h(),t=w(r=>r.closeAll);return p(async(r,u)=>{if(r==="back")return t(),e.back();if(await T()){if(t(),u?.preserveScroll&&F()){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 b(){let e=h();return p(()=>e.back(),[e])}function k(){let e=h();return p(()=>e.refresh(),[e])}function E(){let e=h();return p(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 C}from"next/navigation";function R(){return C()}function G(e){let r=R()[e];if(typeof r=="string")return r;if(Array.isArray(r)&&r.length>0)return r[0]}import{useSearchParams as O}from"next/navigation";function S(){return O()}import{usePathname as U}from"next/navigation";function $(e){let t=U(),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 y}from"react";function K(){let e=S(),t=g(),r=f(),u=y((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=y(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=y(()=>{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 L}from"@donotdev/core";var v=_?.useAuth;function M(e){return L[e]}function d(e){return v?v(e):M(e)}function B(e={}){let{auth:t,redirectTo:r,condition:u}=e;if(!j())return{shouldRedirect:!1,redirectTo:null,isChecking:!1};let i=f(),o=Y(),s=d("user"),n=d("can"),c=d("status");return Q(()=>{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{b as useBack,f as useLocation,$ as useMatch,g as useNavigate,R as useParams,E as usePrefetch,K as useQueryParams,B as useRedirectGuard,k as useRefresh,G as useRouteParam,S as useSearchParams};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
"use client";import{useCallback as
|
|
1
|
+
"use client";import{useCallback as d}from"react";import{useNavigate as T}from"react-router-dom";import{isClient as F,useOverlayStore as k}from"@donotdev/core";import*as D from"@donotdev/crud";var f=D?.useFormStore,A={forms:{},startSubmit:()=>{},setUploading:()=>{},setValidating:()=>{},setSubmitting:()=>{},setSuccess:()=>{},setError:()=>{},reset:()=>{},cleanup:()=>{},setIsDirty:()=>{},hasDirtyForms:()=>!1,getDirtyFormIds:()=>[],getStatus:()=>"idle",isLoading:()=>!1,getUploadProgress:()=>0,getError:()=>null,getIsDirty:()=>!1};function P(e){return f?f(e):e(A)}P.getState=()=>f&&typeof f.getState=="function"?f.getState():A;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=k(r=>r.closeAll);return d(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 d(()=>e(-1),[e])}function b(){return d(()=>{F()&&window.location.reload()},[])}function I(){return d(e=>{},[])}import{useLocation as E}from"react-router-dom";function m(){return E()}import{useParams as C}from"react-router-dom";function g(){return C()}function G(e){let r=g()[e];if(typeof r=="string")return r;if(Array.isArray(r)&&r.length>0)return r[0]}import{useSearchParams as O}from"react-router-dom";function R(){return O()[0]}import{useMatch as N}from"react-router-dom";function U(e){return N(e)}import{useCallback as y}from"react";function L(){let e=R(),t=h(),r=m(),c=y((n,i)=>{let a=new URLSearchParams(e.toString());a.set(n,i);let l=a.toString(),S=`${r.pathname||"/"}${l?`?${l}`:""}`;t(S)},[e,t,r.pathname]),u=y(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=y(()=>{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 _ from"@donotdev/auth";import{DEGRADED_AUTH_API as K}from"@donotdev/core";var v=_?.useAuth;function M(e){return K[e]}function p(e){return v?v(e):M(e)}function B(e={}){let{auth:t,redirectTo:r,condition:c}=e;if(!Q())return{shouldRedirect:!1,redirectTo:null,isChecking:!1};let u=m(),s=q(),n=p("user"),i=p("can"),a=p("status");return $(()=>{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,U as useMatch,h as useNavigate,g as useParams,I as usePrefetch,L as useQueryParams,B as useRedirectGuard,b as useRefresh,G as useRouteParam,R as useSearchParams};
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Hook to block React Router navigation when forms are dirty.
|
|
3
|
+
* Uses FormStore as single source of truth.
|
|
4
|
+
* Safe - gracefully degrades if CRUD package not installed.
|
|
5
|
+
*
|
|
6
|
+
* @example
|
|
7
|
+
* ```tsx
|
|
8
|
+
* // In your app root/layout
|
|
9
|
+
* useFormNavigationBlocker();
|
|
10
|
+
* ```
|
|
11
|
+
*/
|
|
12
|
+
export declare function useFormNavigationBlocker(): void;
|
|
13
|
+
export default useFormNavigationBlocker;
|
|
14
|
+
//# sourceMappingURL=useFormNavigationBlocker.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useFormNavigationBlocker.d.ts","sourceRoot":"","sources":["../../../src/routing/hooks/useFormNavigationBlocker.ts"],"names":[],"mappings":"AAqBA;;;;;;;;;;GAUG;AACH,wBAAgB,wBAAwB,IAAI,IAAI,CAmB/C;AAED,eAAe,wBAAwB,CAAC"}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
// packages/ui/src/routing/hooks/useFormNavigationBlocker.ts
|
|
3
|
+
/**
|
|
4
|
+
* @fileoverview Form Navigation Blocker Hook
|
|
5
|
+
* @description React Router integration for blocking navigation when forms are dirty.
|
|
6
|
+
* Uses FormStore as single source of truth. Safe - works if CRUD package not installed.
|
|
7
|
+
*
|
|
8
|
+
* @version 0.0.1
|
|
9
|
+
* @since 0.0.1
|
|
10
|
+
* @author AMBROISE PARK Consulting
|
|
11
|
+
*/
|
|
12
|
+
import { useBlocker } from 'react-router-dom';
|
|
13
|
+
import { useEffect } from 'react';
|
|
14
|
+
import { useHasDirtyFormsSafe, checkFormNavigationSafe, } from '../../utils/useFormStoreSafe';
|
|
15
|
+
/**
|
|
16
|
+
* Hook to block React Router navigation when forms are dirty.
|
|
17
|
+
* Uses FormStore as single source of truth.
|
|
18
|
+
* Safe - gracefully degrades if CRUD package not installed.
|
|
19
|
+
*
|
|
20
|
+
* @example
|
|
21
|
+
* ```tsx
|
|
22
|
+
* // In your app root/layout
|
|
23
|
+
* useFormNavigationBlocker();
|
|
24
|
+
* ```
|
|
25
|
+
*/
|
|
26
|
+
export function useFormNavigationBlocker() {
|
|
27
|
+
const hasDirtyForms = useHasDirtyFormsSafe();
|
|
28
|
+
const blocker = useBlocker(({ currentLocation, nextLocation }) => hasDirtyForms && currentLocation.pathname !== nextLocation.pathname);
|
|
29
|
+
useEffect(() => {
|
|
30
|
+
if (blocker.state === 'blocked') {
|
|
31
|
+
checkFormNavigationSafe().then((proceed) => {
|
|
32
|
+
if (proceed) {
|
|
33
|
+
blocker.proceed();
|
|
34
|
+
}
|
|
35
|
+
else {
|
|
36
|
+
blocker.reset();
|
|
37
|
+
}
|
|
38
|
+
});
|
|
39
|
+
}
|
|
40
|
+
}, [blocker]);
|
|
41
|
+
}
|
|
42
|
+
export default useFormNavigationBlocker;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { NavigateOptions } from './types';
|
|
2
|
-
export declare function useNavigate(): (to: string, options?: NavigateOptions) => void
|
|
2
|
+
export declare function useNavigate(): (to: string, options?: NavigateOptions) => Promise<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":"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"}
|
|
@@ -11,14 +11,20 @@
|
|
|
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';
|
|
14
15
|
export function useNavigate() {
|
|
15
16
|
const router = useNextRouter();
|
|
16
17
|
const closeAll = useOverlayStore((state) => state.closeAll);
|
|
17
|
-
return useCallback((to, options) => {
|
|
18
|
+
return useCallback(async (to, options) => {
|
|
18
19
|
if (to === 'back') {
|
|
19
20
|
closeAll();
|
|
20
21
|
return router.back();
|
|
21
22
|
}
|
|
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
|
+
}
|
|
22
28
|
closeAll();
|
|
23
29
|
if (options?.preserveScroll && isClient()) {
|
|
24
30
|
const scrollY = window.scrollY;
|
|
@@ -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) => 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":"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"}
|
|
@@ -11,14 +11,20 @@
|
|
|
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';
|
|
14
15
|
export function useNavigate() {
|
|
15
16
|
const navigate = useRouterNavigate();
|
|
16
17
|
const closeAll = useOverlayStore((state) => state.closeAll);
|
|
17
|
-
return useCallback((to, options) => {
|
|
18
|
+
return useCallback(async (to, options) => {
|
|
18
19
|
if (to === 'back') {
|
|
19
20
|
closeAll();
|
|
20
21
|
return navigate(-1);
|
|
21
22
|
}
|
|
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
|
+
}
|
|
22
28
|
closeAll();
|
|
23
29
|
if (options?.replace)
|
|
24
30
|
return navigate(to, { replace: true });
|