use-go-back 1.0.0 → 1.1.0

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.
@@ -0,0 +1,46 @@
1
+ //#region src/index.d.ts
2
+ type PathnameMatcher = string | ((url: URL) => boolean);
3
+ interface UseGoBackOptions {
4
+ /**
5
+ * The target pathname to go back to. Can be:
6
+ * - A string: exact pathname match (e.g., "/")
7
+ * - A function: custom matcher function that receives the full URL object (e.g., (url) => url.pathname === "/" || url.pathname.startsWith("/search") || url.searchParams.has("filter"))
8
+ * @default "/"
9
+ */
10
+ targetPathname?: PathnameMatcher;
11
+ /**
12
+ * Fallback URL to navigate to if Navigation API is not available and no matching history entry is found
13
+ */
14
+ fallbackUrl?: string;
15
+ }
16
+ /**
17
+ * Hook that provides a function to navigate back to a specific route in browser history.
18
+ * Uses the Navigation API to find the closest matching history entry and navigates back to it,
19
+ * which automatically restores scroll position.
20
+ *
21
+ * @param options - Configuration options
22
+ * @returns A function that navigates back to the target route
23
+ *
24
+ * @example
25
+ * ```tsx
26
+ * // Go back to the index page
27
+ * const goBack = useGoBack({ targetPathname: "/" });
28
+ *
29
+ * // Go back to any search-related page
30
+ * const goBack = useGoBack({
31
+ * targetPathname: (url) => url.pathname.startsWith("/search")
32
+ * });
33
+ *
34
+ * // Match based on search params or origin
35
+ * const goBack = useGoBack({
36
+ * targetPathname: (url) => url.origin === "https://app.example.com" || url.searchParams.has("filter")
37
+ * });
38
+ *
39
+ * // Use with a button
40
+ * <Button onClick={goBack}>Back</Button>
41
+ * ```
42
+ */
43
+ declare function useGoBack(options?: UseGoBackOptions): () => void;
44
+ //#endregion
45
+ export { useGoBack };
46
+ //# sourceMappingURL=index-BbEcjnjB.d.ts.map
package/dist/index.js CHANGED
@@ -16,7 +16,12 @@ import { useCallback } from "react";
16
16
  *
17
17
  * // Go back to any search-related page
18
18
  * const goBack = useGoBack({
19
- * targetPathname: (pathname) => pathname.startsWith("/search")
19
+ * targetPathname: (url) => url.pathname.startsWith("/search")
20
+ * });
21
+ *
22
+ * // Match based on search params or origin
23
+ * const goBack = useGoBack({
24
+ * targetPathname: (url) => url.origin === "https://app.example.com" || url.searchParams.has("filter")
20
25
  * });
21
26
  *
22
27
  * // Use with a button
@@ -25,9 +30,9 @@ import { useCallback } from "react";
25
30
  */
26
31
  function useGoBack(options = {}) {
27
32
  const { targetPathname = "/", fallbackUrl } = options;
28
- const matchesPathname = useCallback((pathname) => {
29
- if (typeof targetPathname === "string") return pathname === targetPathname;
30
- return targetPathname(pathname);
33
+ const matchesUrl = useCallback((url) => {
34
+ if (typeof targetPathname === "string") return url.pathname === targetPathname;
35
+ return targetPathname(url);
31
36
  }, [targetPathname]);
32
37
  return useCallback(() => {
33
38
  const nav = window.navigation;
@@ -37,7 +42,7 @@ function useGoBack(options = {}) {
37
42
  for (let i = currentIndex - 1; i >= 0; i--) {
38
43
  const entry = entries[i];
39
44
  if (entry) {
40
- if (matchesPathname(new URL(entry.url).pathname)) {
45
+ if (matchesUrl(new URL(entry.url))) {
41
46
  const stepsBack = currentIndex - i;
42
47
  window.history.go(-stepsBack);
43
48
  return;
@@ -49,7 +54,7 @@ function useGoBack(options = {}) {
49
54
  if (finalFallback) window.location.href = finalFallback;
50
55
  else window.history.back();
51
56
  }, [
52
- matchesPathname,
57
+ matchesUrl,
53
58
  fallbackUrl,
54
59
  targetPathname
55
60
  ]);
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":[],"sources":["../src/index.ts"],"sourcesContent":["import { useCallback } from \"react\"\n\ntype PathnameMatcher = string | ((pathname: string) => boolean)\n\ninterface UseGoBackOptions {\n\t/**\n\t * The target pathname to go back to. Can be:\n\t * - A string: exact pathname match (e.g., \"/\")\n\t * - A function: custom matcher function (e.g., (pathname) => pathname === \"/\" || pathname.startsWith(\"/search\"))\n\t * @default \"/\"\n\t */\n\ttargetPathname?: PathnameMatcher\n\t/**\n\t * Fallback URL to navigate to if Navigation API is not available and no matching history entry is found\n\t */\n\tfallbackUrl?: string\n}\n\n/**\n * Hook that provides a function to navigate back to a specific route in browser history.\n * Uses the Navigation API to find the closest matching history entry and navigates back to it,\n * which automatically restores scroll position.\n *\n * @param options - Configuration options\n * @returns A function that navigates back to the target route\n *\n * @example\n * ```tsx\n * // Go back to the index page\n * const goBack = useGoBack({ targetPathname: \"/\" });\n *\n * // Go back to any search-related page\n * const goBack = useGoBack({\n * targetPathname: (pathname) => pathname.startsWith(\"/search\")\n * });\n *\n * // Use with a button\n * <Button onClick={goBack}>Back</Button>\n * ```\n */\nexport function useGoBack(options: UseGoBackOptions = {}) {\n\tconst { targetPathname = \"/\", fallbackUrl } = options\n\n\tconst matchesPathname = useCallback(\n\t\t(pathname: string): boolean => {\n\t\t\tif (typeof targetPathname === \"string\") {\n\t\t\t\treturn pathname === targetPathname\n\t\t\t}\n\t\t\treturn targetPathname(pathname)\n\t\t},\n\t\t[targetPathname]\n\t)\n\n\tconst goBack = useCallback(() => {\n\t\t// Check if Navigation API is available\n\t\t// @ts-expect-error - Navigation API is not yet in all TypeScript definitions\n\t\tconst nav = window.navigation\n\t\tif (nav && typeof nav === \"object\" && \"currentEntry\" in nav) {\n\t\t\tconst currentIndex = nav.currentEntry?.index ?? -1\n\t\t\tconst entries = nav.entries()\n\n\t\t\t// Look backwards through history to find the closest matching entry\n\t\t\tfor (let i = currentIndex - 1; i >= 0; i--) {\n\t\t\t\tconst entry = entries[i]\n\t\t\t\tif (entry) {\n\t\t\t\t\tconst url = new URL(entry.url)\n\t\t\t\t\t// Check if this entry matches the target pathname\n\t\t\t\t\tif (matchesPathname(url.pathname)) {\n\t\t\t\t\t\t// Calculate how many steps back we need to go\n\t\t\t\t\t\tconst stepsBack = currentIndex - i\n\t\t\t\t\t\t// Use browser navigation to go back, which restores scroll position\n\t\t\t\t\t\twindow.history.go(-stepsBack)\n\t\t\t\t\t\treturn\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Fallback: if Navigation API is not available or no matching entry found\n\t\t// Use fallbackUrl if provided, otherwise use targetPathname if it's a string, otherwise use history.back()\n\t\tconst finalFallback = fallbackUrl ?? (typeof targetPathname === \"string\" ? targetPathname : undefined)\n\t\tif (finalFallback) {\n\t\t\twindow.location.href = finalFallback\n\t\t} else {\n\t\t\twindow.history.back()\n\t\t}\n\t}, [matchesPathname, fallbackUrl, targetPathname])\n\n\treturn goBack\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;AAwCA,SAAgB,UAAU,UAA4B,EAAE,EAAE;CACzD,MAAM,EAAE,iBAAiB,KAAK,gBAAgB;CAE9C,MAAM,kBAAkB,aACtB,aAA8B;AAC9B,MAAI,OAAO,mBAAmB,SAC7B,QAAO,aAAa;AAErB,SAAO,eAAe,SAAS;IAEhC,CAAC,eAAe,CAChB;AAqCD,QAnCe,kBAAkB;EAGhC,MAAM,MAAM,OAAO;AACnB,MAAI,OAAO,OAAO,QAAQ,YAAY,kBAAkB,KAAK;GAC5D,MAAM,eAAe,IAAI,cAAc,SAAS;GAChD,MAAM,UAAU,IAAI,SAAS;AAG7B,QAAK,IAAI,IAAI,eAAe,GAAG,KAAK,GAAG,KAAK;IAC3C,MAAM,QAAQ,QAAQ;AACtB,QAAI,OAGH;SAAI,gBAFQ,IAAI,IAAI,MAAM,IAAI,CAEN,SAAS,EAAE;MAElC,MAAM,YAAY,eAAe;AAEjC,aAAO,QAAQ,GAAG,CAAC,UAAU;AAC7B;;;;;EAQJ,MAAM,gBAAgB,gBAAgB,OAAO,mBAAmB,WAAW,iBAAiB;AAC5F,MAAI,cACH,QAAO,SAAS,OAAO;MAEvB,QAAO,QAAQ,MAAM;IAEpB;EAAC;EAAiB;EAAa;EAAe,CAAC"}
1
+ {"version":3,"file":"index.js","names":[],"sources":["../src/index.ts"],"sourcesContent":["import { useCallback } from \"react\"\n\ntype PathnameMatcher = string | ((url: URL) => boolean)\n\ninterface UseGoBackOptions {\n\t/**\n\t * The target pathname to go back to. Can be:\n\t * - A string: exact pathname match (e.g., \"/\")\n\t * - A function: custom matcher function that receives the full URL object (e.g., (url) => url.pathname === \"/\" || url.pathname.startsWith(\"/search\") || url.searchParams.has(\"filter\"))\n\t * @default \"/\"\n\t */\n\ttargetPathname?: PathnameMatcher\n\t/**\n\t * Fallback URL to navigate to if Navigation API is not available and no matching history entry is found\n\t */\n\tfallbackUrl?: string\n}\n\n/**\n * Hook that provides a function to navigate back to a specific route in browser history.\n * Uses the Navigation API to find the closest matching history entry and navigates back to it,\n * which automatically restores scroll position.\n *\n * @param options - Configuration options\n * @returns A function that navigates back to the target route\n *\n * @example\n * ```tsx\n * // Go back to the index page\n * const goBack = useGoBack({ targetPathname: \"/\" });\n *\n * // Go back to any search-related page\n * const goBack = useGoBack({\n * targetPathname: (url) => url.pathname.startsWith(\"/search\")\n * });\n *\n * // Match based on search params or origin\n * const goBack = useGoBack({\n * targetPathname: (url) => url.origin === \"https://app.example.com\" || url.searchParams.has(\"filter\")\n * });\n *\n * // Use with a button\n * <Button onClick={goBack}>Back</Button>\n * ```\n */\nexport function useGoBack(options: UseGoBackOptions = {}) {\n\tconst { targetPathname = \"/\", fallbackUrl } = options\n\n\tconst matchesUrl = useCallback(\n\t\t(url: URL): boolean => {\n\t\t\tif (typeof targetPathname === \"string\") {\n\t\t\t\treturn url.pathname === targetPathname\n\t\t\t}\n\t\t\treturn targetPathname(url)\n\t\t},\n\t\t[targetPathname]\n\t)\n\n\tconst goBack = useCallback(() => {\n\t\t// Check if Navigation API is available\n\t\t// @ts-expect-error - Navigation API is not yet in all TypeScript definitions\n\t\tconst nav = window.navigation\n\t\tif (nav && typeof nav === \"object\" && \"currentEntry\" in nav) {\n\t\t\tconst currentIndex = nav.currentEntry?.index ?? -1\n\t\t\tconst entries = nav.entries()\n\n\t\t\t// Look backwards through history to find the closest matching entry\n\t\t\tfor (let i = currentIndex - 1; i >= 0; i--) {\n\t\t\t\tconst entry = entries[i]\n\t\t\t\tif (entry) {\n\t\t\t\t\tconst url = new URL(entry.url)\n\t\t\t\t\t// Check if this entry matches the target pathname\n\t\t\t\t\tif (matchesUrl(url)) {\n\t\t\t\t\t\t// Calculate how many steps back we need to go\n\t\t\t\t\t\tconst stepsBack = currentIndex - i\n\t\t\t\t\t\t// Use browser navigation to go back, which restores scroll position\n\t\t\t\t\t\twindow.history.go(-stepsBack)\n\t\t\t\t\t\treturn\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Fallback: if Navigation API is not available or no matching entry found\n\t\t// Use fallbackUrl if provided, otherwise use targetPathname if it's a string, otherwise use history.back()\n\t\tconst finalFallback = fallbackUrl ?? (typeof targetPathname === \"string\" ? targetPathname : undefined)\n\t\tif (finalFallback) {\n\t\t\twindow.location.href = finalFallback\n\t\t} else {\n\t\t\twindow.history.back()\n\t\t}\n\t}, [matchesUrl, fallbackUrl, targetPathname])\n\n\treturn goBack\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA6CA,SAAgB,UAAU,UAA4B,EAAE,EAAE;CACzD,MAAM,EAAE,iBAAiB,KAAK,gBAAgB;CAE9C,MAAM,aAAa,aACjB,QAAsB;AACtB,MAAI,OAAO,mBAAmB,SAC7B,QAAO,IAAI,aAAa;AAEzB,SAAO,eAAe,IAAI;IAE3B,CAAC,eAAe,CAChB;AAqCD,QAnCe,kBAAkB;EAGhC,MAAM,MAAM,OAAO;AACnB,MAAI,OAAO,OAAO,QAAQ,YAAY,kBAAkB,KAAK;GAC5D,MAAM,eAAe,IAAI,cAAc,SAAS;GAChD,MAAM,UAAU,IAAI,SAAS;AAG7B,QAAK,IAAI,IAAI,eAAe,GAAG,KAAK,GAAG,KAAK;IAC3C,MAAM,QAAQ,QAAQ;AACtB,QAAI,OAGH;SAAI,WAFQ,IAAI,IAAI,MAAM,IAAI,CAEX,EAAE;MAEpB,MAAM,YAAY,eAAe;AAEjC,aAAO,QAAQ,GAAG,CAAC,UAAU;AAC7B;;;;;EAQJ,MAAM,gBAAgB,gBAAgB,OAAO,mBAAmB,WAAW,iBAAiB;AAC5F,MAAI,cACH,QAAO,SAAS,OAAO;MAEvB,QAAO,QAAQ,MAAM;IAEpB;EAAC;EAAY;EAAa;EAAe,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "use-go-back",
3
- "version": "1.0.0",
3
+ "version": "1.1.0",
4
4
  "description": "A React hook that navigates back to a specific route in browser history using the Navigation API, preserving scroll position",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",