@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.
@@ -1,18 +1,14 @@
1
1
  "use client";
2
2
  import { useRouter as useNextRouter } from "next/navigation";
3
- import { useNavigationFallback } from "../providers/navigation.provider";
3
+ import { useNavigationContext } from "../providers/navigation.provider";
4
4
  function useRouter() {
5
5
  const router = useNextRouter();
6
- const defaultFallback = useNavigationFallback();
6
+ const { defaultFallback, internalNavCountRef, expectingBackRef } = useNavigationContext();
7
7
  function back(options) {
8
8
  const fallback = typeof options === "string" ? options : options?.fallback || defaultFallback;
9
- let isInternalReferrer = false;
10
- try {
11
- isInternalReferrer = !!document.referrer && new URL(document.referrer).origin === window.location.origin;
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 { useNavigationFallback } 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 = useNavigationFallback();\n\n function back(options?: SafeBackOptions | string) {\n const fallback =\n typeof options === \"string\"\n ? options\n : options?.fallback || defaultFallback;\n\n let isInternalReferrer = false;\n\n try {\n isInternalReferrer =\n !!document.referrer &&\n new URL(document.referrer).origin === window.location.origin;\n } catch {\n isInternalReferrer = false;\n }\n\n if (isInternalReferrer && window.history.length > 1) {\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,6BAA6B;AAW/B,SAAS,YAA2B;AACzC,QAAM,SAAS,cAAc;AAC7B,QAAM,kBAAkB,sBAAsB;AAE9C,WAAS,KAAK,SAAoC;AAChD,UAAM,WACJ,OAAO,YAAY,WACf,UACA,SAAS,YAAY;AAE3B,QAAI,qBAAqB;AAEzB,QAAI;AACF,2BACE,CAAC,CAAC,SAAS,YACX,IAAI,IAAI,SAAS,QAAQ,EAAE,WAAW,OAAO,SAAS;AAAA,IAC1D,QAAQ;AACN,2BAAqB;AAAA,IACvB;AAEA,QAAI,sBAAsB,OAAO,QAAQ,SAAS,GAAG;AACnD,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
+ {"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 { createContext, useContext } from "react";
4
- const NavigationContext = createContext({
5
- defaultFallback: "/"
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
- return /* @__PURE__ */ jsx(NavigationContext.Provider, { value: { defaultFallback }, children });
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 useContext(NavigationContext).defaultFallback;
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 { createContext, ReactNode, useContext } from \"react\";\n\ninterface NavigationContextValue {\n defaultFallback: string;\n}\n\nconst NavigationContext = createContext<NavigationContextValue>({\n defaultFallback: \"/\",\n});\n\ninterface NavigationProviderProps {\n children: ReactNode;\n defaultFallback?: string;\n}\n\nexport function NavigationProvider({\n children,\n defaultFallback = \"/\",\n}: NavigationProviderProps) {\n return (\n <NavigationContext.Provider value={{ defaultFallback }}>\n {children}\n </NavigationContext.Provider>\n );\n}\n\nexport function useNavigationFallback(): string {\n return useContext(NavigationContext).defaultFallback;\n}\n"],"mappings":";AAsBI;AApBJ,SAAS,eAA0B,kBAAkB;AAMrD,MAAM,oBAAoB,cAAsC;AAAA,EAC9D,iBAAiB;AACnB,CAAC;AAOM,SAAS,mBAAmB;AAAA,EACjC;AAAA,EACA,kBAAkB;AACpB,GAA4B;AAC1B,SACE,oBAAC,kBAAkB,UAAlB,EAA2B,OAAO,EAAE,gBAAgB,GAClD,UACH;AAEJ;AAEO,SAAS,wBAAgC;AAC9C,SAAO,WAAW,iBAAiB,EAAE;AACvC;","names":[]}
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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@greatapps/common",
3
- "version": "1.1.641",
3
+ "version": "1.1.642",
4
4
  "description": "Shared library for GreatApps frontend applications",
5
5
  "main": "./dist/index.mjs",
6
6
  "types": "./src/index.ts",
@@ -1,7 +1,7 @@
1
1
  "use client";
2
2
 
3
3
  import { useRouter as useNextRouter } from "next/navigation";
4
- import { useNavigationFallback } from "../providers/navigation.provider";
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 = useNavigationFallback();
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
- let isInternalReferrer = false;
26
-
27
- try {
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 { createContext, ReactNode, useContext } from "react";
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 value={{ defaultFallback }}>
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 useContext(NavigationContext).defaultFallback;
70
+ return useNavigationContext().defaultFallback;
31
71
  }