@greatapps/common 1.1.641 → 1.1.642
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/hooks/useRouter.mjs +5 -9
- package/dist/hooks/useRouter.mjs.map +1 -1
- package/dist/providers/navigation.provider.mjs +43 -6
- package/dist/providers/navigation.provider.mjs.map +1 -1
- package/package.json +1 -1
- package/src/hooks/useRouter.ts +6 -13
- package/src/providers/navigation.provider.tsx +46 -6
package/dist/hooks/useRouter.mjs
CHANGED
|
@@ -1,18 +1,14 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { useRouter as useNextRouter } from "next/navigation";
|
|
3
|
-
import {
|
|
3
|
+
import { useNavigationContext } from "../providers/navigation.provider";
|
|
4
4
|
function useRouter() {
|
|
5
5
|
const router = useNextRouter();
|
|
6
|
-
const defaultFallback =
|
|
6
|
+
const { defaultFallback, internalNavCountRef, expectingBackRef } = useNavigationContext();
|
|
7
7
|
function back(options) {
|
|
8
8
|
const fallback = typeof options === "string" ? options : options?.fallback || defaultFallback;
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
} catch {
|
|
13
|
-
isInternalReferrer = false;
|
|
14
|
-
}
|
|
15
|
-
if (isInternalReferrer && window.history.length > 1) {
|
|
9
|
+
if (internalNavCountRef.current > 0) {
|
|
10
|
+
internalNavCountRef.current -= 1;
|
|
11
|
+
expectingBackRef.current = true;
|
|
16
12
|
router.back();
|
|
17
13
|
return;
|
|
18
14
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/hooks/useRouter.ts"],"sourcesContent":["\"use client\";\n\nimport { useRouter as useNextRouter } from \"next/navigation\";\nimport {
|
|
1
|
+
{"version":3,"sources":["../../src/hooks/useRouter.ts"],"sourcesContent":["\"use client\";\n\nimport { useRouter as useNextRouter } from \"next/navigation\";\nimport { useNavigationContext } from \"../providers/navigation.provider\";\n\ntype SafeBackOptions = { fallback?: string };\n\ntype AppRouter = ReturnType<typeof useNextRouter>;\n\nexport interface SafeAppRouter extends Omit<AppRouter, \"back\"> {\n back: (options?: SafeBackOptions | string) => void;\n safeBack: (options?: SafeBackOptions | string) => void;\n}\n\nexport function useRouter(): SafeAppRouter {\n const router = useNextRouter();\n const { defaultFallback, internalNavCountRef, expectingBackRef } =\n useNavigationContext();\n\n function back(options?: SafeBackOptions | string) {\n const fallback =\n typeof options === \"string\"\n ? options\n : options?.fallback || defaultFallback;\n\n if (internalNavCountRef.current > 0) {\n internalNavCountRef.current -= 1;\n expectingBackRef.current = true;\n router.back();\n return;\n }\n\n router.replace(fallback);\n }\n\n return {\n ...router,\n back,\n safeBack: back,\n };\n}\n"],"mappings":";AAEA,SAAS,aAAa,qBAAqB;AAC3C,SAAS,4BAA4B;AAW9B,SAAS,YAA2B;AACzC,QAAM,SAAS,cAAc;AAC7B,QAAM,EAAE,iBAAiB,qBAAqB,iBAAiB,IAC7D,qBAAqB;AAEvB,WAAS,KAAK,SAAoC;AAChD,UAAM,WACJ,OAAO,YAAY,WACf,UACA,SAAS,YAAY;AAE3B,QAAI,oBAAoB,UAAU,GAAG;AACnC,0BAAoB,WAAW;AAC/B,uBAAiB,UAAU;AAC3B,aAAO,KAAK;AACZ;AAAA,IACF;AAEA,WAAO,QAAQ,QAAQ;AAAA,EACzB;AAEA,SAAO;AAAA,IACL,GAAG;AAAA,IACH;AAAA,IACA,UAAU;AAAA,EACZ;AACF;","names":[]}
|
|
@@ -1,20 +1,57 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { jsx } from "react/jsx-runtime";
|
|
3
|
-
import {
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
3
|
+
import {
|
|
4
|
+
createContext,
|
|
5
|
+
useContext,
|
|
6
|
+
useEffect,
|
|
7
|
+
useRef
|
|
8
|
+
} from "react";
|
|
9
|
+
import { usePathname } from "next/navigation";
|
|
10
|
+
const NavigationContext = createContext(null);
|
|
7
11
|
function NavigationProvider({
|
|
8
12
|
children,
|
|
9
13
|
defaultFallback = "/"
|
|
10
14
|
}) {
|
|
11
|
-
|
|
15
|
+
const pathname = usePathname();
|
|
16
|
+
const internalNavCountRef = useRef(0);
|
|
17
|
+
const expectingBackRef = useRef(false);
|
|
18
|
+
const lastPathnameRef = useRef(null);
|
|
19
|
+
useEffect(() => {
|
|
20
|
+
if (lastPathnameRef.current === null) {
|
|
21
|
+
lastPathnameRef.current = pathname;
|
|
22
|
+
return;
|
|
23
|
+
}
|
|
24
|
+
if (lastPathnameRef.current === pathname) return;
|
|
25
|
+
if (expectingBackRef.current) {
|
|
26
|
+
expectingBackRef.current = false;
|
|
27
|
+
} else {
|
|
28
|
+
internalNavCountRef.current += 1;
|
|
29
|
+
}
|
|
30
|
+
lastPathnameRef.current = pathname;
|
|
31
|
+
}, [pathname]);
|
|
32
|
+
return /* @__PURE__ */ jsx(
|
|
33
|
+
NavigationContext.Provider,
|
|
34
|
+
{
|
|
35
|
+
value: { defaultFallback, internalNavCountRef, expectingBackRef },
|
|
36
|
+
children
|
|
37
|
+
}
|
|
38
|
+
);
|
|
39
|
+
}
|
|
40
|
+
function useNavigationContext() {
|
|
41
|
+
const ctx = useContext(NavigationContext);
|
|
42
|
+
if (!ctx) {
|
|
43
|
+
throw new Error(
|
|
44
|
+
"useNavigationContext must be used inside <NavigationProvider>"
|
|
45
|
+
);
|
|
46
|
+
}
|
|
47
|
+
return ctx;
|
|
12
48
|
}
|
|
13
49
|
function useNavigationFallback() {
|
|
14
|
-
return
|
|
50
|
+
return useNavigationContext().defaultFallback;
|
|
15
51
|
}
|
|
16
52
|
export {
|
|
17
53
|
NavigationProvider,
|
|
54
|
+
useNavigationContext,
|
|
18
55
|
useNavigationFallback
|
|
19
56
|
};
|
|
20
57
|
//# sourceMappingURL=navigation.provider.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/providers/navigation.provider.tsx"],"sourcesContent":["\"use client\";\n\nimport {
|
|
1
|
+
{"version":3,"sources":["../../src/providers/navigation.provider.tsx"],"sourcesContent":["\"use client\";\n\nimport {\n createContext,\n ReactNode,\n useContext,\n useEffect,\n useRef,\n type RefObject,\n} from \"react\";\nimport { usePathname } from \"next/navigation\";\n\ninterface NavigationContextValue {\n defaultFallback: string;\n internalNavCountRef: RefObject<number>;\n expectingBackRef: RefObject<boolean>;\n}\n\nconst NavigationContext = createContext<NavigationContextValue | null>(null);\n\ninterface NavigationProviderProps {\n children: ReactNode;\n defaultFallback?: string;\n}\n\nexport function NavigationProvider({\n children,\n defaultFallback = \"/\",\n}: NavigationProviderProps) {\n const pathname = usePathname();\n const internalNavCountRef = useRef(0);\n const expectingBackRef = useRef(false);\n const lastPathnameRef = useRef<string | null>(null);\n\n useEffect(() => {\n if (lastPathnameRef.current === null) {\n lastPathnameRef.current = pathname;\n return;\n }\n if (lastPathnameRef.current === pathname) return;\n\n if (expectingBackRef.current) {\n expectingBackRef.current = false;\n } else {\n internalNavCountRef.current += 1;\n }\n lastPathnameRef.current = pathname;\n }, [pathname]);\n\n return (\n <NavigationContext.Provider\n value={{ defaultFallback, internalNavCountRef, expectingBackRef }}\n >\n {children}\n </NavigationContext.Provider>\n );\n}\n\nexport function useNavigationContext(): NavigationContextValue {\n const ctx = useContext(NavigationContext);\n if (!ctx) {\n throw new Error(\n \"useNavigationContext must be used inside <NavigationProvider>\"\n );\n }\n return ctx;\n}\n\nexport function useNavigationFallback(): string {\n return useNavigationContext().defaultFallback;\n}\n"],"mappings":";AAkDI;AAhDJ;AAAA,EACE;AAAA,EAEA;AAAA,EACA;AAAA,EACA;AAAA,OAEK;AACP,SAAS,mBAAmB;AAQ5B,MAAM,oBAAoB,cAA6C,IAAI;AAOpE,SAAS,mBAAmB;AAAA,EACjC;AAAA,EACA,kBAAkB;AACpB,GAA4B;AAC1B,QAAM,WAAW,YAAY;AAC7B,QAAM,sBAAsB,OAAO,CAAC;AACpC,QAAM,mBAAmB,OAAO,KAAK;AACrC,QAAM,kBAAkB,OAAsB,IAAI;AAElD,YAAU,MAAM;AACd,QAAI,gBAAgB,YAAY,MAAM;AACpC,sBAAgB,UAAU;AAC1B;AAAA,IACF;AACA,QAAI,gBAAgB,YAAY,SAAU;AAE1C,QAAI,iBAAiB,SAAS;AAC5B,uBAAiB,UAAU;AAAA,IAC7B,OAAO;AACL,0BAAoB,WAAW;AAAA,IACjC;AACA,oBAAgB,UAAU;AAAA,EAC5B,GAAG,CAAC,QAAQ,CAAC;AAEb,SACE;AAAA,IAAC,kBAAkB;AAAA,IAAlB;AAAA,MACC,OAAO,EAAE,iBAAiB,qBAAqB,iBAAiB;AAAA,MAE/D;AAAA;AAAA,EACH;AAEJ;AAEO,SAAS,uBAA+C;AAC7D,QAAM,MAAM,WAAW,iBAAiB;AACxC,MAAI,CAAC,KAAK;AACR,UAAM,IAAI;AAAA,MACR;AAAA,IACF;AAAA,EACF;AACA,SAAO;AACT;AAEO,SAAS,wBAAgC;AAC9C,SAAO,qBAAqB,EAAE;AAChC;","names":[]}
|
package/package.json
CHANGED
package/src/hooks/useRouter.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
|
|
3
3
|
import { useRouter as useNextRouter } from "next/navigation";
|
|
4
|
-
import {
|
|
4
|
+
import { useNavigationContext } from "../providers/navigation.provider";
|
|
5
5
|
|
|
6
6
|
type SafeBackOptions = { fallback?: string };
|
|
7
7
|
|
|
@@ -14,7 +14,8 @@ export interface SafeAppRouter extends Omit<AppRouter, "back"> {
|
|
|
14
14
|
|
|
15
15
|
export function useRouter(): SafeAppRouter {
|
|
16
16
|
const router = useNextRouter();
|
|
17
|
-
const defaultFallback =
|
|
17
|
+
const { defaultFallback, internalNavCountRef, expectingBackRef } =
|
|
18
|
+
useNavigationContext();
|
|
18
19
|
|
|
19
20
|
function back(options?: SafeBackOptions | string) {
|
|
20
21
|
const fallback =
|
|
@@ -22,17 +23,9 @@ export function useRouter(): SafeAppRouter {
|
|
|
22
23
|
? options
|
|
23
24
|
: options?.fallback || defaultFallback;
|
|
24
25
|
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
isInternalReferrer =
|
|
29
|
-
!!document.referrer &&
|
|
30
|
-
new URL(document.referrer).origin === window.location.origin;
|
|
31
|
-
} catch {
|
|
32
|
-
isInternalReferrer = false;
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
if (isInternalReferrer && window.history.length > 1) {
|
|
26
|
+
if (internalNavCountRef.current > 0) {
|
|
27
|
+
internalNavCountRef.current -= 1;
|
|
28
|
+
expectingBackRef.current = true;
|
|
36
29
|
router.back();
|
|
37
30
|
return;
|
|
38
31
|
}
|
|
@@ -1,14 +1,22 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
|
|
3
|
-
import {
|
|
3
|
+
import {
|
|
4
|
+
createContext,
|
|
5
|
+
ReactNode,
|
|
6
|
+
useContext,
|
|
7
|
+
useEffect,
|
|
8
|
+
useRef,
|
|
9
|
+
type RefObject,
|
|
10
|
+
} from "react";
|
|
11
|
+
import { usePathname } from "next/navigation";
|
|
4
12
|
|
|
5
13
|
interface NavigationContextValue {
|
|
6
14
|
defaultFallback: string;
|
|
15
|
+
internalNavCountRef: RefObject<number>;
|
|
16
|
+
expectingBackRef: RefObject<boolean>;
|
|
7
17
|
}
|
|
8
18
|
|
|
9
|
-
const NavigationContext = createContext<NavigationContextValue>(
|
|
10
|
-
defaultFallback: "/",
|
|
11
|
-
});
|
|
19
|
+
const NavigationContext = createContext<NavigationContextValue | null>(null);
|
|
12
20
|
|
|
13
21
|
interface NavigationProviderProps {
|
|
14
22
|
children: ReactNode;
|
|
@@ -19,13 +27,45 @@ export function NavigationProvider({
|
|
|
19
27
|
children,
|
|
20
28
|
defaultFallback = "/",
|
|
21
29
|
}: NavigationProviderProps) {
|
|
30
|
+
const pathname = usePathname();
|
|
31
|
+
const internalNavCountRef = useRef(0);
|
|
32
|
+
const expectingBackRef = useRef(false);
|
|
33
|
+
const lastPathnameRef = useRef<string | null>(null);
|
|
34
|
+
|
|
35
|
+
useEffect(() => {
|
|
36
|
+
if (lastPathnameRef.current === null) {
|
|
37
|
+
lastPathnameRef.current = pathname;
|
|
38
|
+
return;
|
|
39
|
+
}
|
|
40
|
+
if (lastPathnameRef.current === pathname) return;
|
|
41
|
+
|
|
42
|
+
if (expectingBackRef.current) {
|
|
43
|
+
expectingBackRef.current = false;
|
|
44
|
+
} else {
|
|
45
|
+
internalNavCountRef.current += 1;
|
|
46
|
+
}
|
|
47
|
+
lastPathnameRef.current = pathname;
|
|
48
|
+
}, [pathname]);
|
|
49
|
+
|
|
22
50
|
return (
|
|
23
|
-
<NavigationContext.Provider
|
|
51
|
+
<NavigationContext.Provider
|
|
52
|
+
value={{ defaultFallback, internalNavCountRef, expectingBackRef }}
|
|
53
|
+
>
|
|
24
54
|
{children}
|
|
25
55
|
</NavigationContext.Provider>
|
|
26
56
|
);
|
|
27
57
|
}
|
|
28
58
|
|
|
59
|
+
export function useNavigationContext(): NavigationContextValue {
|
|
60
|
+
const ctx = useContext(NavigationContext);
|
|
61
|
+
if (!ctx) {
|
|
62
|
+
throw new Error(
|
|
63
|
+
"useNavigationContext must be used inside <NavigationProvider>"
|
|
64
|
+
);
|
|
65
|
+
}
|
|
66
|
+
return ctx;
|
|
67
|
+
}
|
|
68
|
+
|
|
29
69
|
export function useNavigationFallback(): string {
|
|
30
|
-
return
|
|
70
|
+
return useNavigationContext().defaultFallback;
|
|
31
71
|
}
|