@hitachivantara/app-shell-navigation 1.0.0 → 1.2.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.
@@ -1,5 +1,25 @@
1
+ import { HvAppShellViewsConfig } from '@hitachivantara/app-shell-shared';
2
+ import { Location as Location_2 } from 'react-router-dom';
1
3
  import { Path } from 'react-router-dom';
2
4
 
5
+ declare interface GetViewRouteOptions {
6
+ mode?: ViewSearchMode;
7
+ }
8
+
9
+ declare class LocationWithViews<State = unknown> implements Location_2<State> {
10
+ #private;
11
+ state: State;
12
+ key: string;
13
+ pathname: string;
14
+ search: string;
15
+ hash: string;
16
+ private matches;
17
+ constructor(location: Location_2<State>, views: HvAppShellViewsConfig[] | undefined | null);
18
+ get views(): HvAppShellViewsConfig[];
19
+ }
20
+
21
+ declare type NavigateOptions = GetViewRouteOptions & Partial<NavigationOptions>;
22
+
3
23
  export declare interface NavigationOptions {
4
24
  /**
5
25
  * Whether a history replace action should be performed instead of the default history push.
@@ -18,9 +38,11 @@ export declare const useHvCurrentNavigationPath: () => {
18
38
  path: string | undefined;
19
39
  }[];
20
40
 
41
+ export declare const useHvLocation: () => LocationWithViews<any>;
42
+
21
43
  export declare const useHvNavigation: () => {
22
- getViewRoute: (viewBundleDir: string | ViewDestination) => string | undefined;
23
- navigate: (to: To, options?: Partial<NavigationOptions>) => void;
44
+ getViewRoute: (viewBundleDir: string | ViewDestination, { mode }?: GetViewRouteOptions) => string | undefined;
45
+ navigate: (to: To, options?: NavigateOptions) => void;
24
46
  };
25
47
 
26
48
  export declare type ViewDestination = {
@@ -42,4 +64,6 @@ export declare type ViewDestination = {
42
64
  hash?: string;
43
65
  };
44
66
 
67
+ declare type ViewSearchMode = "auto" | "top";
68
+
45
69
  export { }
package/dist/esm/index.js CHANGED
@@ -1,7 +1,9 @@
1
1
  import { default as e } from "./lib/hooks/useNavigation.js";
2
2
  import { default as r } from "./lib/hooks/useCurrentNavigationPath.js";
3
+ import { default as f } from "./lib/hooks/useLocation.js";
3
4
  export {
4
5
  r as useHvCurrentNavigationPath,
6
+ f as useHvLocation,
5
7
  e as useHvNavigation
6
8
  };
7
9
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;"}
1
+ {"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;"}
@@ -0,0 +1,61 @@
1
+ var l = Object.defineProperty;
2
+ var p = (s, t, e) => t in s ? l(s, t, { enumerable: !0, configurable: !0, writable: !0, value: e }) : s[t] = e;
3
+ var i = (s, t, e) => (p(s, typeof t != "symbol" ? t + "" : t, e), e), o = (s, t, e) => {
4
+ if (!t.has(s))
5
+ throw TypeError("Cannot " + e);
6
+ };
7
+ var r = (s, t, e) => (o(s, t, "read from private field"), e ? e.call(s) : t.get(s)), c = (s, t, e) => {
8
+ if (t.has(s))
9
+ throw TypeError("Cannot add the same private member more than once");
10
+ t instanceof WeakSet ? t.add(s) : t.set(s, e);
11
+ }, u = (s, t, e, n) => (o(s, t, "write to private field"), n ? n.call(s, e) : t.set(s, e), e);
12
+ import { useMemo as f } from "react";
13
+ import { useLocation as d, matchRoutes as w } from "react-router-dom";
14
+ import { useHvAppShellConfig as g } from "@hitachivantara/app-shell-shared";
15
+ function m(s) {
16
+ return s.map((t) => {
17
+ const e = t.route.slice(1);
18
+ return e === "" && (t.views == null || t.views.length === 0) ? {
19
+ path: e,
20
+ view: t
21
+ } : {
22
+ path: e,
23
+ view: t,
24
+ children: t.views ? m(t.views) : void 0
25
+ };
26
+ });
27
+ }
28
+ var a;
29
+ class v {
30
+ constructor(t, e) {
31
+ i(this, "state");
32
+ i(this, "key");
33
+ i(this, "pathname");
34
+ i(this, "search");
35
+ i(this, "hash");
36
+ c(this, a, void 0);
37
+ i(this, "matches", null);
38
+ this.state = t.state, this.key = t.key, this.pathname = t.pathname, this.search = t.search, this.hash = t.hash, u(this, a, e ?? []);
39
+ }
40
+ get views() {
41
+ var t;
42
+ if (this.matches == null) {
43
+ const e = m(r(this, a));
44
+ this.matches = ((t = w(e, this)) == null ? void 0 : t.map((n) => n.route.view)) ?? [];
45
+ }
46
+ return this.matches;
47
+ }
48
+ }
49
+ a = new WeakMap();
50
+ const x = () => {
51
+ var n;
52
+ const s = d(), t = g();
53
+ return f(() => {
54
+ var h;
55
+ return new v(s, (h = t.mainPanel) == null ? void 0 : h.views);
56
+ }, [s, (n = t.mainPanel) == null ? void 0 : n.views]);
57
+ }, R = x;
58
+ export {
59
+ R as default
60
+ };
61
+ //# sourceMappingURL=useLocation.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useLocation.js","sources":["../../../../src/lib/hooks/useLocation.tsx"],"sourcesContent":["import { useMemo } from \"react\";\nimport {\n matchRoutes,\n useLocation as useLocationReactRouter,\n Location\n} from \"react-router-dom\";\n\nimport {\n HvAppShellViewsConfig,\n useHvAppShellConfig\n} from \"@hitachivantara/app-shell-shared\";\n\ninterface IndexedView {\n path: string;\n children?: IndexedView[];\n view: HvAppShellViewsConfig;\n}\n\nfunction indexViews(views: HvAppShellViewsConfig[]): IndexedView[] {\n return views.map(view => {\n // remove prefix slash from view.route\n const path = view.route.slice(1);\n const isIndex =\n path === \"\" && (view.views == null || view.views.length === 0);\n\n if (isIndex) {\n return {\n path,\n view\n };\n }\n\n return {\n path,\n view,\n children: view.views ? indexViews(view.views) : undefined\n };\n });\n}\n\nclass LocationWithViews<State = unknown> implements Location<State> {\n state: State;\n\n key: string;\n\n pathname: string;\n\n search: string;\n\n hash: string;\n\n #configViews: HvAppShellViewsConfig[];\n\n private matches: HvAppShellViewsConfig[] | null = null;\n\n constructor(\n location: Location<State>,\n views: HvAppShellViewsConfig[] | undefined | null\n ) {\n this.state = location.state;\n this.key = location.key;\n this.pathname = location.pathname;\n this.search = location.search;\n this.hash = location.hash;\n\n this.#configViews = views ?? [];\n }\n\n get views() {\n if (this.matches == null) {\n const indexedViews = indexViews(this.#configViews);\n this.matches =\n matchRoutes(indexedViews, this)?.map(match => match.route.view) ?? [];\n }\n\n return this.matches;\n }\n}\n\nconst useLocation = () => {\n const location = useLocationReactRouter();\n const config = useHvAppShellConfig();\n const toReturn = useMemo(() => {\n return new LocationWithViews(location, config.mainPanel?.views);\n }, [location, config.mainPanel?.views]);\n\n return toReturn;\n};\nexport default useLocation;\n"],"names":["indexViews","views","map","view","path","route","slice","length","children","undefined","LocationWithViews","constructor","location","state","key","pathname","search","hash","__privateAdd","_configViews","matches","__privateSet","indexedViews","__privateGet","matchRoutes","match","useLocation","useLocationReactRouter","config","useHvAppShellConfig","toReturn","useMemo","mainPanel","useHvLocation"],"mappings":";;;;;;;;;;;;;;AAkBA,SAASA,EAAWC,GAA+C;AAC1DA,SAAAA,EAAMC,IAAIC,CAAQA,MAAA;AAEvB,UAAMC,IAAOD,EAAKE,MAAMC,MAAM,CAAC;AAI/B,WAFEF,MAAS,OAAOD,EAAKF,SAAS,QAAQE,EAAKF,MAAMM,WAAW,KAGrD;AAAA,MACLH,MAAAA;AAAAA,MACAD,MAAAA;AAAAA,IAAAA,IAIG;AAAA,MACLC,MAAAA;AAAAA,MACAD,MAAAA;AAAAA,MACAK,UAAUL,EAAKF,QAAQD,EAAWG,EAAKF,KAAK,IAAIQ;AAAAA,IAAAA;AAAAA,EAClD,CACD;AACH;;AAEA,MAAMC,EAA8D;AAAA,EAelEC,YACEC,GACAX,GACA;AAjBFY,IAAAA,EAAAA;AAEAC,IAAAA,EAAAA;AAEAC,IAAAA,EAAAA;AAEAC,IAAAA,EAAAA;AAEAC,IAAAA,EAAAA;AAEA,IAAAC,EAAA,MAAAC,GAAA;AAEQC,IAAAA,EAAAA,iBAA0C;AAMhD,SAAKP,QAAQD,EAASC,OACtB,KAAKC,MAAMF,EAASE,KACpB,KAAKC,WAAWH,EAASG,UACzB,KAAKC,SAASJ,EAASI,QACvB,KAAKC,OAAOL,EAASK,MAEhBI,EAAA,MAAAF,GAAelB,KAAS;EAC/B;AAAA,EAEA,IAAIA,QAAQ;;AACN,QAAA,KAAKmB,WAAW,MAAM;AAClBE,YAAAA,IAAetB,EAAWuB,EAAA,MAAKJ,EAAY;AAC5CC,WAAAA,YACHI,IAAAA,EAAYF,GAAc,IAAI,MAA9BE,gBAAAA,EAAiCtB,IAAIuB,CAAAA,MAASA,EAAMpB,MAAMF,UAAS,CAAA;AAAA,IACvE;AAEA,WAAO,KAAKiB;AAAAA,EACd;AACF;AA1BED,IAAA;AA4BF,MAAMO,IAAcA,MAAM;;AACxB,QAAMd,IAAWe,KACXC,IAASC;AAKRC,SAJUC,EAAQ,MAAM;;AAC7B,WAAO,IAAIrB,EAAkBE,IAAUgB,IAAAA,EAAOI,cAAPJ,gBAAAA,EAAkB3B,KAAK;AAAA,KAC7D,CAACW,IAAUgB,IAAAA,EAAOI,cAAPJ,gBAAAA,EAAkB3B,KAAK,CAAC;AAGxC,GACAgC,IAAeP;"}
@@ -1,46 +1,92 @@
1
- import { useContext as v, useCallback as $ } from "react";
2
- import { useNavigate as N } from "react-router-dom";
3
- import { useHvAppShellConfig as P, HvAppShellViewContext as R } from "@hitachivantara/app-shell-shared";
4
- import H from "../utils/navigationUtil.js";
5
- const m = (t) => t.viewBundle !== void 0, S = (t) => typeof t != "string" && !m(t), V = () => {
6
- const t = P(), s = v(R), d = N(), u = $((e) => {
7
- var g, h;
8
- let a, n, l, f;
9
- m(e) ? {
10
- viewBundle: a,
11
- pathParams: n,
12
- search: l,
13
- hash: f
14
- } = e : a = e;
15
- const c = a.replace(/\$/, "_");
16
- let p, i;
17
- c.startsWith("/") ? (p = s == null ? void 0 : s.id, i = c.substring(1)) : i = c;
18
- const o = (h = (g = t.mainPanel) == null ? void 0 : g.views) == null ? void 0 : h.find((r) => r.bundle === `${i}` || r.bundle === `${i}.js` || r.bundle === `${p}/${i}.js` || r.bundle === `${p}/src/${i}`);
19
- return o != null && o.route ? `${H(o.route, n)}${l ?? ""}${f ?? ""}` : void 0;
20
- }, [t, s == null ? void 0 : s.id]), b = $((e, a) => {
21
- let n;
22
- if (S(e))
23
- n = e;
1
+ import { useMemo as N, useContext as y, useRef as A, useCallback as j } from "react";
2
+ import { useNavigate as C } from "react-router-dom";
3
+ import { useHvAppShellConfig as W, HvAppShellViewContext as B } from "@hitachivantara/app-shell-shared";
4
+ import O from "../utils/navigationUtil.js";
5
+ import q from "./useLocation.js";
6
+ const k = (e) => e.viewBundle !== void 0, x = (e) => typeof e != "string" && !k(e);
7
+ function L(e, r) {
8
+ return `/${e.map((n) => n.route.substring(1)).slice(0, r ?? e.length).filter((n) => n !== "").join("/")}`;
9
+ }
10
+ function M(e, r, n) {
11
+ return e.bundle === `${r}` || e.bundle === `${r}.js` || e.bundle === `${n}/${r}.js` || e.bundle === `${n}/${r}`;
12
+ }
13
+ const _ = () => {
14
+ var R;
15
+ const e = W(), r = N(() => {
16
+ var t;
17
+ const i = (l, s = "") => l.reduce((o, u) => {
18
+ const a = `${s}${u.route}`;
19
+ return o.push({
20
+ ...u,
21
+ route: a
22
+ }), u.views != null && o.push(...i(u.views, a)), o;
23
+ }, []);
24
+ return i(((t = e.mainPanel) == null ? void 0 : t.views) ?? []);
25
+ }, [(R = e.mainPanel) == null ? void 0 : R.views]), n = y(B), v = C(), w = q(), b = A(w);
26
+ b.current = w;
27
+ const m = j((i, {
28
+ mode: t = "auto"
29
+ } = {}) => {
30
+ var S;
31
+ let l, s, o, u;
32
+ k(i) ? {
33
+ viewBundle: l,
34
+ pathParams: s,
35
+ search: o,
36
+ hash: u
37
+ } = i : l = i;
38
+ const a = l.replace(/\$/, "_");
39
+ let V, p;
40
+ a.startsWith("/") ? (V = n == null ? void 0 : n.id, p = a.substring(1)) : p = a;
41
+ let P = [];
42
+ t !== "top" && (P = b.current.views);
43
+ let f;
44
+ const h = r.filter((g) => M(g, p, V)).sort((g, c) => {
45
+ const d = (g.route.match(/\//g) ?? []).length, $ = (c.route.match(/\//g) ?? []).length;
46
+ return d - $;
47
+ });
48
+ if (h.length > 0) {
49
+ if (t === "top" || h.length === 1)
50
+ f = h[0].route;
51
+ else if (t === "auto") {
52
+ let c = `${L(P)}/`;
53
+ for (; f == null; ) {
54
+ const d = c;
55
+ if (f = (S = h.find(($) => $.route.startsWith(d))) == null ? void 0 : S.route, c = c.replace(/\/[^/]*\/?$/, "/"), c === "")
56
+ break;
57
+ }
58
+ }
59
+ }
60
+ return f ? `${O(f, s)}${o ?? ""}${u ?? ""}` : void 0;
61
+ }, [r, n == null ? void 0 : n.id]), H = j((i, t) => {
62
+ let l;
63
+ if (x(i))
64
+ l = i;
24
65
  else {
25
- const l = u(e);
26
- if (l == null)
27
- if (typeof e == "string")
28
- n = e;
66
+ const o = m(i, {
67
+ mode: t == null ? void 0 : t.mode
68
+ });
69
+ if (o == null)
70
+ if (typeof i == "string")
71
+ l = i;
29
72
  else {
30
- console.warn(`Navigate request to a non existing path [${e.viewBundle}]. Skipping`);
73
+ console.warn(`Navigate request to a non existing path [${i.viewBundle}]. Skipping`);
31
74
  return;
32
75
  }
33
76
  else
34
- n = l;
77
+ l = o;
35
78
  }
36
- d(n, a);
37
- }, [u, d]);
79
+ let s;
80
+ t != null && (t.mode == null ? s = t : (s = {
81
+ ...t
82
+ }, delete s.mode, Object.keys(s).length === 0 && (s = void 0))), v(l, s);
83
+ }, [m, v]);
38
84
  return {
39
- getViewRoute: u,
40
- navigate: b
85
+ getViewRoute: m,
86
+ navigate: H
41
87
  };
42
- }, A = V;
88
+ }, I = _;
43
89
  export {
44
- A as default
90
+ I as default
45
91
  };
46
92
  //# sourceMappingURL=useNavigation.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"useNavigation.js","sources":["../../../../src/lib/hooks/useNavigation.tsx"],"sourcesContent":["import { useCallback, useContext } from \"react\";\nimport { Path, useNavigate } from \"react-router-dom\";\n\nimport {\n HvAppShellViewContext,\n useHvAppShellConfig\n} from \"@hitachivantara/app-shell-shared\";\n\nimport { NavigationOptions, To, ViewDestination } from \"../types\";\nimport compileHref from \"../utils/navigationUtil\";\n\nconst isViewDestination = (to: To): to is ViewDestination => {\n return (to as ViewDestination).viewBundle !== undefined;\n};\n\nconst isPathDestination = (to: To): to is Partial<Path> => {\n return typeof to !== \"string\" && !isViewDestination(to);\n};\n\nconst useNavigation = () => {\n const config = useHvAppShellConfig();\n const viewContext = useContext(HvAppShellViewContext);\n const navigateReactRouter = useNavigate();\n\n /**\n * Utility to search for the route of an application view bundle directory on the App Shell configuration file.\n *\n * @param viewBundleDir The application view bundle directory name and optional route parameters.\n *\n * @returns The compiled route or undefined if none was found.\n */\n const getViewRoute = useCallback(\n (viewBundleDir: string | ViewDestination): string | undefined => {\n let viewBundle;\n let pathParams;\n let search;\n let hash;\n\n if (isViewDestination(viewBundleDir)) {\n ({ viewBundle, pathParams, search, hash } = viewBundleDir);\n } else {\n viewBundle = viewBundleDir;\n }\n const bundleWithReplacedPlaceholders = viewBundle.replace(/\\$/, \"_\");\n\n let appId: string | undefined;\n let bundle: string;\n\n // local navigation\n if (bundleWithReplacedPlaceholders.startsWith(\"/\")) {\n appId = viewContext?.id;\n bundle = bundleWithReplacedPlaceholders.substring(1);\n } else {\n bundle = bundleWithReplacedPlaceholders;\n }\n\n const view = config.mainPanel?.views?.find(\n v =>\n v.bundle === `${bundle}` ||\n v.bundle === `${bundle}.js` ||\n v.bundle === `${appId}/${bundle}.js` ||\n v.bundle === `${appId}/src/${bundle}`\n );\n\n return view?.route\n ? `${compileHref(view.route, pathParams)}${search ?? \"\"}${hash ?? \"\"}`\n : undefined;\n },\n [config, viewContext?.id]\n );\n\n /**\n * Performs navigation, through 'history.push' or 'history.replace', for the given destination with the passed navigation options.\n * @see https://reactrouter.com/hooks/use-navigate\n *\n * @param to The destination of the navigation. For ViewDestination type see {@link ViewDestination}.\n * @param options The navigation options.\n */\n const navigate = useCallback(\n (to: To, options?: Partial<NavigationOptions>) => {\n let path;\n if (isPathDestination(to)) {\n path = to;\n } else {\n const route = getViewRoute(to);\n\n if (route == null) {\n if (typeof to === \"string\") {\n path = to;\n } else {\n // If route for given module is not found on the App Shell configuration file, do nothing.\n console.warn(\n `Navigate request to a non existing path [${to.viewBundle}]. Skipping`\n );\n return;\n }\n } else {\n path = route;\n }\n }\n\n navigateReactRouter(path, options);\n },\n [getViewRoute, navigateReactRouter]\n );\n\n return { getViewRoute, navigate };\n};\nexport default useNavigation;\n"],"names":["isViewDestination","to","viewBundle","undefined","isPathDestination","useNavigation","config","useHvAppShellConfig","viewContext","useContext","HvAppShellViewContext","navigateReactRouter","useNavigate","getViewRoute","useCallback","viewBundleDir","pathParams","search","hash","bundleWithReplacedPlaceholders","replace","appId","bundle","startsWith","id","substring","view","mainPanel","views","find","v","route","compileHref","navigate","options","path","console","warn","useNavigation$1"],"mappings":";;;;AAWA,MAAMA,IAAoBA,CAACC,MACjBA,EAAuBC,eAAeC,QAG1CC,IAAoBA,CAACH,MAClB,OAAOA,KAAO,YAAY,CAACD,EAAkBC,CAAE,GAGlDI,IAAgBA,MAAM;AAC1B,QAAMC,IAASC,KACTC,IAAcC,EAAWC,CAAqB,GAC9CC,IAAsBC,KAStBC,IAAeC,EACnB,CAACC,MAAgE;;AAC3Db,QAAAA,GACAc,GACAC,GACAC;AAEAlB,IAAAA,EAAkBe,CAAa,IAChC;AAAA,MAAEb,YAAAA;AAAAA,MAAYc,YAAAA;AAAAA,MAAYC,QAAAA;AAAAA,MAAQC,MAAAA;AAAAA,IAASH,IAAAA,IAE/BA,IAAAA;AAEf,UAAMI,IAAiCjB,EAAWkB,QAAQ,MAAM,GAAG;AAE/DC,QAAAA,GACAC;AAGAH,IAAAA,EAA+BI,WAAW,GAAG,KAC/CF,IAAQb,KAAAA,gBAAAA,EAAagB,IACZL,IAAAA,EAA+BM,UAAU,CAAC,KAE1CN,IAAAA;AAGX,UAAMO,KAAOpB,KAAAA,IAAAA,EAAOqB,cAAPrB,gBAAAA,EAAkBsB,UAAlBtB,gBAAAA,EAAyBuB,KACpCC,CAAAA,MACEA,EAAER,WAAY,GAAEA,CAAO,MACvBQ,EAAER,WAAY,GAAEA,CAAO,SACvBQ,EAAER,WAAY,GAAED,CAAM,IAAGC,CAAO,SAChCQ,EAAER,WAAY,GAAED,CAAM,QAAOC,CAAO;AAGxC,WAAOI,KAAAA,QAAAA,EAAMK,QACR,GAAEC,EAAYN,EAAKK,OAAOf,CAAU,CAAE,GAAEC,KAAU,EAAG,GAAEC,KAAQ,EAAG,KACnEf;AAAAA,EAEN,GAAA,CAACG,GAAQE,KAAAA,gBAAAA,EAAagB,EAAE,CAC1B,GASMS,IAAWnB,EACf,CAACb,GAAQiC,MAAyC;AAC5CC,QAAAA;AACA/B,QAAAA,EAAkBH,CAAE;AACfA,MAAAA,IAAAA;AAAAA,SACF;AACC8B,YAAAA,IAAQlB,EAAaZ,CAAE;AAE7B,UAAI8B,KAAS;AACP,YAAA,OAAO9B,KAAO;AACTA,UAAAA,IAAAA;AAAAA,aACF;AAELmC,kBAAQC,KACL,4CAA2CpC,EAAGC,UAAW,aAC5D;AACA;AAAA,QACF;AAAA;AAEO6B,QAAAA,IAAAA;AAAAA,IAEX;AAEApB,IAAAA,EAAoBwB,GAAMD,CAAO;AAAA,EAAA,GAEnC,CAACrB,GAAcF,CAAmB,CACpC;AAEO,SAAA;AAAA,IAAEE,cAAAA;AAAAA,IAAcoB,UAAAA;AAAAA,EAAAA;AACzB,GACAK,IAAejC;"}
1
+ {"version":3,"file":"useNavigation.js","sources":["../../../../src/lib/hooks/useNavigation.tsx"],"sourcesContent":["import { useCallback, useContext, useMemo, useRef } from \"react\";\nimport { Path, useNavigate } from \"react-router-dom\";\n\nimport {\n HvAppShellViewContext,\n HvAppShellViewsConfig,\n useHvAppShellConfig\n} from \"@hitachivantara/app-shell-shared\";\n\nimport { NavigationOptions, To, ViewDestination } from \"../types\";\nimport compileHref from \"../utils/navigationUtil\";\nimport useHvLocation from \"./useLocation\";\n\nconst isViewDestination = (to: To): to is ViewDestination => {\n return (to as ViewDestination).viewBundle !== undefined;\n};\n\nconst isPathDestination = (to: To): to is Partial<Path> => {\n return typeof to !== \"string\" && !isViewDestination(to);\n};\n\ntype ViewSearchMode = \"auto\" | \"top\";\n\ninterface GetViewRouteOptions {\n mode?: ViewSearchMode;\n}\n\ntype NavigateOptions = GetViewRouteOptions & Partial<NavigationOptions>;\n\nfunction getActiveViewRoute(\n activeViews: HvAppShellViewsConfig[],\n depth?: number\n): string {\n return `/${activeViews\n .map(view => view.route.substring(1))\n .slice(0, depth ?? activeViews.length)\n .filter(route => route !== \"\") // remove index routes\n .join(\"/\")}`;\n}\n\nfunction isSameBundle(\n v: HvAppShellViewsConfig,\n bundle: string,\n appId: string | undefined\n) {\n return (\n v.bundle === `${bundle}` ||\n v.bundle === `${bundle}.js` ||\n v.bundle === `${appId}/${bundle}.js` ||\n v.bundle === `${appId}/${bundle}`\n );\n}\n\nconst useNavigation = () => {\n const config = useHvAppShellConfig();\n const flattenViews = useMemo(() => {\n const flatten = (views: HvAppShellViewsConfig[], base = \"\") => {\n return views.reduce<HvAppShellViewsConfig[]>((acc, view) => {\n // concatenate base with view route\n const route = `${base}${view.route}` as HvAppShellViewsConfig[\"route\"];\n acc.push({ ...view, route });\n if (view.views != null) {\n acc.push(...flatten(view.views, route));\n }\n return acc;\n }, []);\n };\n return flatten(config.mainPanel?.views ?? []);\n }, [config.mainPanel?.views]);\n\n const viewContext = useContext(HvAppShellViewContext);\n const navigateReactRouter = useNavigate();\n\n // the returned navigate and getViewRoute functions need to be stable\n // regardless of the location change, but we need to use the most recent location\n // in the getViewRoute algorithm, so we use a ref to store the location\n const location = useHvLocation();\n const locationRef = useRef(location);\n locationRef.current = location;\n\n /**\n * Utility to search for the route of a View on the App Shell configuration.\n *\n * The search can be performed in different modes:\n * - \"auto\": Searches within views whose route is a subpath of the current active view, progressively going up path segments until a match is found.\n * - \"top\": Finds the view closest to the root, i.e. with the least number of path segments.\n *\n * If multiple views match the search criteria, the function returns the one that appears first in the App Shell configuration.\n *\n * @param viewBundleDir The application view bundle directory name and optional route parameters.\n * @param mode The search mode to use. Defaults to \"auto\".\n *\n * @returns The compiled route or undefined if none was found.\n */\n const getViewRoute = useCallback(\n (\n viewBundleDir: string | ViewDestination,\n { mode = \"auto\" }: GetViewRouteOptions = {}\n ): string | undefined => {\n let viewBundle;\n let pathParams;\n let search;\n let hash;\n\n if (isViewDestination(viewBundleDir)) {\n ({ viewBundle, pathParams, search, hash } = viewBundleDir);\n } else {\n viewBundle = viewBundleDir;\n }\n const bundleWithReplacedPlaceholders = viewBundle.replace(/\\$/, \"_\");\n\n let appId: string | undefined;\n let bundle: string;\n\n // local navigation\n if (bundleWithReplacedPlaceholders.startsWith(\"/\")) {\n appId = viewContext?.id;\n bundle = bundleWithReplacedPlaceholders.substring(1);\n } else {\n bundle = bundleWithReplacedPlaceholders;\n }\n\n let activeViews: HvAppShellViewsConfig[] = [];\n if (mode !== \"top\") {\n activeViews = locationRef.current.views;\n }\n\n let route: string | undefined;\n\n const matchingViews = flattenViews\n .filter(v => isSameBundle(v, bundle, appId))\n .sort((a, b) => {\n const aSlashCount = (a.route.match(/\\//g) ?? []).length;\n const bSlashCount = (b.route.match(/\\//g) ?? []).length;\n return aSlashCount - bSlashCount;\n });\n\n if (matchingViews.length > 0) {\n if (mode === \"top\" || matchingViews.length === 1) {\n // no need for search algorithms if there is only one matching view\n route = matchingViews[0].route;\n } else if (mode === \"auto\") {\n const activeViewRoute = getActiveViewRoute(activeViews);\n\n let path = `${activeViewRoute}/`;\n while (route == null) {\n const innerPath = path;\n route = matchingViews.find(v => v.route.startsWith(innerPath))\n ?.route;\n\n // remove last path segment, e.g. /path/segment/ -> /path/ -> /\n path = path.replace(/\\/[^/]*\\/?$/, \"/\");\n\n if (path === \"\") {\n break;\n }\n }\n }\n }\n\n return route\n ? `${compileHref(route, pathParams)}${search ?? \"\"}${hash ?? \"\"}`\n : undefined;\n },\n [flattenViews, viewContext?.id]\n );\n\n /**\n * Performs navigation, through 'history.push' or 'history.replace', for the given destination with the passed navigation options.\n * @see https://reactrouter.com/hooks/use-navigate\n *\n * @param to The destination of the navigation. For ViewDestination type see {@link ViewDestination}.\n * @param options The navigation options:\n * - mode: The search mode to use when searching for the route of a View on the App Shell configuration. Defaults to \"auto\".\n * - replace: If true, the navigation will replace the current entry in the history stack instead of adding a new one.\n * - state: State to associate to the location.\n */\n const navigate = useCallback(\n (to: To, options?: NavigateOptions) => {\n let path;\n if (isPathDestination(to)) {\n path = to;\n } else {\n const route = getViewRoute(to, { mode: options?.mode });\n\n if (route == null) {\n if (typeof to === \"string\") {\n path = to;\n } else {\n // If route for given module is not found on the App Shell configuration file, do nothing.\n console.warn(\n `Navigate request to a non existing path [${to.viewBundle}]. Skipping`\n );\n return;\n }\n } else {\n path = route;\n }\n }\n\n let navigateOptions: NavigateOptions | undefined;\n if (options != null) {\n if (options.mode == null) {\n navigateOptions = options;\n } else {\n navigateOptions = { ...options };\n delete navigateOptions.mode;\n if (Object.keys(navigateOptions).length === 0) {\n navigateOptions = undefined;\n }\n }\n }\n\n navigateReactRouter(path, navigateOptions);\n },\n [getViewRoute, navigateReactRouter]\n );\n\n return { getViewRoute, navigate };\n};\n\nexport default useNavigation;\n"],"names":["isViewDestination","to","viewBundle","undefined","isPathDestination","getActiveViewRoute","activeViews","depth","map","view","route","substring","slice","length","filter","join","isSameBundle","v","bundle","appId","useNavigation","config","useHvAppShellConfig","flattenViews","useMemo","flatten","views","base","reduce","acc","push","mainPanel","viewContext","useContext","HvAppShellViewContext","navigateReactRouter","useNavigate","location","useHvLocation","locationRef","useRef","current","getViewRoute","useCallback","viewBundleDir","mode","pathParams","search","hash","bundleWithReplacedPlaceholders","replace","startsWith","id","matchingViews","sort","a","b","aSlashCount","match","bSlashCount","path","innerPath","find","compileHref","navigate","options","console","warn","navigateOptions","Object","keys","useNavigation$1"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hitachivantara/app-shell-navigation",
3
- "version": "1.0.0",
3
+ "version": "1.2.0",
4
4
  "description": "AppShell Navigation",
5
5
  "author": "Hitachi Vantara - Boba Fett Team",
6
6
  "license": "Apache-2.0",
@@ -35,7 +35,7 @@
35
35
  "coverage": "vitest run --coverage"
36
36
  },
37
37
  "dependencies": {
38
- "@hitachivantara/app-shell-shared": "1.0.0",
38
+ "@hitachivantara/app-shell-shared": "1.1.0",
39
39
  "path-to-regexp": "^6.2.1"
40
40
  },
41
41
  "peerDependencies": {
@@ -56,5 +56,5 @@
56
56
  "vite-plugin-dts": "^3.6.4",
57
57
  "vite-tsconfig-paths": "^4.0.5"
58
58
  },
59
- "gitHead": "eccbbda7fa0fa5cdb38c2665d9d6233dd9fc2eb5"
59
+ "gitHead": "6140d2027f6c2d215f1d3c015a9adafd0cf00de6"
60
60
  }