@hitachivantara/app-shell-shared 2.2.5 → 2.3.1

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,15 @@
1
- import { createContext } from "react";
1
+ import { createContext, useContext } from "react";
2
2
  const HvAppShellRuntimeContext = createContext(void 0);
3
+ const useHvAppShellRuntimeContext = () => {
4
+ const context = useContext(HvAppShellRuntimeContext);
5
+ if (!context) {
6
+ throw new Error(
7
+ "useHvAppShellRuntimeContext must be used within HvAppShellRuntimeContext.Provider"
8
+ );
9
+ }
10
+ return context;
11
+ };
3
12
  export {
4
- HvAppShellRuntimeContext
13
+ HvAppShellRuntimeContext,
14
+ useHvAppShellRuntimeContext
5
15
  };
@@ -17,13 +17,32 @@ const useHvAppShellModel = () => {
17
17
  };
18
18
  const HvAppShellViewContext = createContext(void 0);
19
19
  const HvAppShellRuntimeContext = createContext(void 0);
20
+ const useHvAppShellRuntimeContext = () => {
21
+ const context = useContext(HvAppShellRuntimeContext);
22
+ if (!context) {
23
+ throw new Error(
24
+ "useHvAppShellRuntimeContext must be used within HvAppShellRuntimeContext.Provider"
25
+ );
26
+ }
27
+ return context;
28
+ };
20
29
  const HvAppShellCombinedProvidersContext = createContext(void 0);
21
30
  const useHvAppShellCombinedProviders = () => {
22
31
  return useContext(
23
32
  HvAppShellCombinedProvidersContext
24
33
  );
25
34
  };
26
- const CONFIG_TRANSLATIONS_NAMESPACE = "configTranslations";
35
+ const CONFIG_TRANSLATIONS_NAMESPACE = "app";
36
+ const HvAppShellI18nContext = createContext(void 0);
37
+ const useHvAppShellI18n = () => {
38
+ const context = useContext(HvAppShellI18nContext);
39
+ if (!context) {
40
+ throw new Error(
41
+ "useHvAppShellI18n must be used within HvAppShellI18nContext.Provider"
42
+ );
43
+ }
44
+ return context;
45
+ };
27
46
  const getMenuTargetHref = (menuItem) => {
28
47
  const { target } = menuItem;
29
48
  if (target) {
@@ -171,11 +190,12 @@ const MAX_TOP_MENU_DEPTH = 2;
171
190
  const useHvMenuItems = () => {
172
191
  const { pathname, search, state: locationState } = useLocation();
173
192
  const { navigationMode, menu } = useHvAppShellModel();
174
- const { i18n } = useContext(HvAppShellRuntimeContext) ?? {};
193
+ useHvAppShellI18n();
194
+ const { i18n } = useHvAppShellRuntimeContext();
195
+ const resolvedLanguage = i18n.resolvedLanguage;
175
196
  const tConfig = useMemo(
176
- () => i18n?.getFixedT(i18n.language, CONFIG_TRANSLATIONS_NAMESPACE) ?? // should not happen, but fallback if the i18n instance is not available
177
- ((l) => l),
178
- [i18n]
197
+ () => i18n.getFixedT(resolvedLanguage ?? null, CONFIG_TRANSLATIONS_NAMESPACE),
198
+ [i18n, resolvedLanguage]
179
199
  );
180
200
  const items = useMemo(() => {
181
201
  const menuItemsDepth = navigationMode === "ONLY_TOP" ? MAX_TOP_MENU_DEPTH : void 0;
@@ -268,12 +288,15 @@ export {
268
288
  DynamicHooksEvaluator,
269
289
  HvAppShellCombinedProvidersContext,
270
290
  HvAppShellContext,
291
+ HvAppShellI18nContext,
271
292
  HvAppShellModelContext,
272
293
  HvAppShellRuntimeContext,
273
294
  HvAppShellViewContext,
274
295
  useAsync,
275
296
  useHvAppShellCombinedProviders,
276
297
  useHvAppShellConfig,
298
+ useHvAppShellI18n,
277
299
  useHvAppShellModel,
300
+ useHvAppShellRuntimeContext,
278
301
  useHvMenuItems
279
302
  };
@@ -1,18 +1,19 @@
1
- import { useContext, useMemo, useState, useEffect } from "react";
1
+ import { useMemo, useState, useEffect } from "react";
2
2
  import { useLocation } from "react-router-dom";
3
3
  import { useHvAppShellModel } from "../AppShellModelContext.js";
4
- import { HvAppShellRuntimeContext } from "../AppShellRuntimeContext.js";
5
- import { CONFIG_TRANSLATIONS_NAMESPACE } from "../i18n/index.js";
4
+ import { useHvAppShellRuntimeContext } from "../AppShellRuntimeContext.js";
5
+ import { useHvAppShellI18n, CONFIG_TRANSLATIONS_NAMESPACE } from "../i18n/index.js";
6
6
  import { createMenuItems, searchHrefInMenuItems, addPrefixToHref, getRootIdFromItemId, findItemById, findFirstLeafItem } from "../utils/navigationUtils.js";
7
7
  const MAX_TOP_MENU_DEPTH = 2;
8
8
  const useHvMenuItems = () => {
9
9
  const { pathname, search, state: locationState } = useLocation();
10
10
  const { navigationMode, menu } = useHvAppShellModel();
11
- const { i18n } = useContext(HvAppShellRuntimeContext) ?? {};
11
+ useHvAppShellI18n();
12
+ const { i18n } = useHvAppShellRuntimeContext();
13
+ const resolvedLanguage = i18n.resolvedLanguage;
12
14
  const tConfig = useMemo(
13
- () => i18n?.getFixedT(i18n.language, CONFIG_TRANSLATIONS_NAMESPACE) ?? // should not happen, but fallback if the i18n instance is not available
14
- ((l) => l),
15
- [i18n]
15
+ () => i18n.getFixedT(resolvedLanguage ?? null, CONFIG_TRANSLATIONS_NAMESPACE),
16
+ [i18n, resolvedLanguage]
16
17
  );
17
18
  const items = useMemo(() => {
18
19
  const menuItemsDepth = navigationMode === "ONLY_TOP" ? MAX_TOP_MENU_DEPTH : void 0;
@@ -1,4 +1,17 @@
1
- const CONFIG_TRANSLATIONS_NAMESPACE = "configTranslations";
1
+ import { createContext, useContext } from "react";
2
+ const CONFIG_TRANSLATIONS_NAMESPACE = "app";
3
+ const HvAppShellI18nContext = createContext(void 0);
4
+ const useHvAppShellI18n = () => {
5
+ const context = useContext(HvAppShellI18nContext);
6
+ if (!context) {
7
+ throw new Error(
8
+ "useHvAppShellI18n must be used within HvAppShellI18nContext.Provider"
9
+ );
10
+ }
11
+ return context;
12
+ };
2
13
  export {
3
- CONFIG_TRANSLATIONS_NAMESPACE
14
+ CONFIG_TRANSLATIONS_NAMESPACE,
15
+ HvAppShellI18nContext,
16
+ useHvAppShellI18n
4
17
  };
package/dist/index.d.ts CHANGED
@@ -13,7 +13,7 @@ import { useAsync } from '@hitachivantara/app-shell-services';
13
13
 
14
14
  export { AsyncResult }
15
15
 
16
- export declare const CONFIG_TRANSLATIONS_NAMESPACE = "configTranslations";
16
+ export declare const CONFIG_TRANSLATIONS_NAMESPACE = "app";
17
17
 
18
18
  export declare const DynamicHooksEvaluator: <THook extends (...args: any[]) => TResult, TResult = ReturnType<THook>>({ hooks, onEvaluate, }: DynamicHooksEvaluatorProps<THook, TResult>) => FunctionComponentElement<DynamicHooksEvaluatorProps<THook, TResult>>;
19
19
 
@@ -72,6 +72,27 @@ export declare interface HvAppShellConfig {
72
72
  apps?: Record<string, string>;
73
73
  menu?: HvAppShellMenuConfig[];
74
74
  translations?: Record<string, object>;
75
+ /**
76
+ * Base URL for loading translation files via HTTP.
77
+ *
78
+ * Resolved relative to:
79
+ * - `configUrl` (when the config was loaded from a URL), or
80
+ * - the configured `baseUrl` of the App Shell (including its default).
81
+ *
82
+ * The full path composed internally is:
83
+ * `{translationsBaseUrl}/locales/{{lng}}/{{ns}}.json`
84
+ *
85
+ * Defaults to `"./"`.
86
+ *
87
+ * Can coexist with `translations`, which provides pre-loaded resources.
88
+ * When both are provided, `translations` are shown immediately and then
89
+ * refreshed when the HTTP backend responds.
90
+ *
91
+ * Set to `false` to disable HTTP-based translation loading entirely.
92
+ * Useful when only inline `translations` are used and the extra network
93
+ * requests would cause 404 errors in legacy setups.
94
+ */
95
+ translationsBaseUrl?: string | false;
75
96
  navigationMode?: "TOP_AND_LEFT" | "ONLY_TOP" | "ONLY_LEFT";
76
97
  mainPanel?: HvAppShellMainPanelConfig;
77
98
  theming?: HvAppShellThemingConfig;
@@ -106,8 +127,24 @@ export declare interface HvAppShellHelp {
106
127
  description?: string;
107
128
  }
108
129
 
130
+ export declare const HvAppShellI18nContext: Context<HvAppShellI18nContextValue | undefined>;
131
+
132
+ /**
133
+ * The App Shell I18N context.
134
+ */
135
+ export declare type HvAppShellI18nContextValue = {
136
+ /**
137
+ * Gets the current language of the App Shell, as a BCP 47 language tag.
138
+ */
139
+ language: string;
140
+ /**
141
+ * Sets the App Shell's current language.
142
+ */
143
+ changeLanguage: (newLng?: string) => Promise<void>;
144
+ };
145
+
109
146
  export declare interface HvAppShellIcon {
110
- iconType: "uikit";
147
+ iconType: "uikit" | "unocss";
111
148
  name: string;
112
149
  }
113
150
 
@@ -170,6 +207,36 @@ export declare interface HvAppShellProvidersModel extends HvAppShellConditionalM
170
207
 
171
208
  export declare const HvAppShellRuntimeContext: Context<HvAppShellRuntimeContextValue | undefined>;
172
209
 
210
+ /**
211
+ * Context for providing runtime information and utilities to the App Shell.
212
+ * This context supports the App Shell's internal operations and should not be used outside.
213
+ *
214
+ * Currently, exposes the I18next instance that the App Shell internal modules should use for translations.
215
+ *
216
+ * The reason this is needed, and that the I18next instance installed via `I18nextProvider` by
217
+ * `AppShellContainer` is that the App Shell UI and associated packages is typically compiled
218
+ * together with other custom code, using the App Shell vite plugin. Hence, the I18next library
219
+ * is shared with the custom code. If the custom code installs its own I18next instance at a
220
+ * high enough level in the component tree, for example, inside a global or (even wider impact)
221
+ * system provider, all the internal App Shell UI components beneath it would no longer be guaranteed
222
+ * to access the original, root I18next instance.
223
+ *
224
+ * To use I18next properly from within the App Shell internal code, do, for example:
225
+ * ```ts
226
+ * const { i18n } = useHvAppShellRuntimeContext();
227
+ * const { t } = useTranslation(ns, {i18n});
228
+ * ```
229
+ *
230
+ * The current package, `app-shell-shared`, is a special case as it cannot depend on `i18next` at runtime (only
231
+ * i18next types which are removed when compiling to JS can be referenced). See how {@link useHvMenuItems} handles this.
232
+ *
233
+ * The custom App Shell ultimately compiling the code should not use the root I18next provider.
234
+ * It may not be configured as needed by external code. It can however, have its own I18next instance, which can/should
235
+ * be configured for the same resource bundle repository (of `./locales/{{lng}}/{{ns}}.json`), rooted at the configured
236
+ * translations base path via {@link HvAppShellConfig#translationsBaseUrl}, albeit consuming other namespaces.
237
+ * This repository is required when providing translations outside the App Shell configuration (i.e., not embedded in
238
+ * the configuration via {@link HvAppShellConfig#translations}).
239
+ */
173
240
  export declare interface HvAppShellRuntimeContextValue {
174
241
  i18n: i18n;
175
242
  }
@@ -247,8 +314,15 @@ export declare const useHvAppShellCombinedProviders: () => HvAppShellCombinedPro
247
314
 
248
315
  export declare const useHvAppShellConfig: () => HvAppShellContextValue;
249
316
 
317
+ /**
318
+ * Gets the App Shell's I18N context.
319
+ */
320
+ export declare const useHvAppShellI18n: () => HvAppShellI18nContextValue;
321
+
250
322
  export declare const useHvAppShellModel: () => HvAppShellModel;
251
323
 
324
+ export declare const useHvAppShellRuntimeContext: () => HvAppShellRuntimeContextValue;
325
+
252
326
  export declare const useHvMenuItems: () => MenuItemsContext;
253
327
 
254
328
  export declare interface ViewHvContainerProps extends Omit<HvContainerProps, "children"> {
package/dist/index.js CHANGED
@@ -1,10 +1,10 @@
1
1
  import { HvAppShellContext, useHvAppShellConfig } from "./AppShellContext.js";
2
2
  import { HvAppShellModelContext, useHvAppShellModel } from "./AppShellModelContext.js";
3
3
  import { HvAppShellViewContext } from "./AppShellViewContext.js";
4
- import { HvAppShellRuntimeContext } from "./AppShellRuntimeContext.js";
4
+ import { HvAppShellRuntimeContext, useHvAppShellRuntimeContext } from "./AppShellRuntimeContext.js";
5
5
  import { HvAppShellCombinedProvidersContext, useHvAppShellCombinedProviders } from "./AppShellCombinedProvidersContext.js";
6
6
  import { useAsync } from "@hitachivantara/app-shell-services";
7
- import { CONFIG_TRANSLATIONS_NAMESPACE } from "./i18n/index.js";
7
+ import { CONFIG_TRANSLATIONS_NAMESPACE, HvAppShellI18nContext, useHvAppShellI18n } from "./i18n/index.js";
8
8
  import { useHvMenuItems } from "./hooks/useMenuItems.js";
9
9
  import { DynamicHooksEvaluator } from "./components/DynamicHooksEvaluator/DynamicHooksEvaluator.js";
10
10
  export {
@@ -12,12 +12,15 @@ export {
12
12
  DynamicHooksEvaluator,
13
13
  HvAppShellCombinedProvidersContext,
14
14
  HvAppShellContext,
15
+ HvAppShellI18nContext,
15
16
  HvAppShellModelContext,
16
17
  HvAppShellRuntimeContext,
17
18
  HvAppShellViewContext,
18
19
  useAsync,
19
20
  useHvAppShellCombinedProviders,
20
21
  useHvAppShellConfig,
22
+ useHvAppShellI18n,
21
23
  useHvAppShellModel,
24
+ useHvAppShellRuntimeContext,
22
25
  useHvMenuItems
23
26
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hitachivantara/app-shell-shared",
3
- "version": "2.2.5",
3
+ "version": "2.3.1",
4
4
  "type": "module",
5
5
  "private": false,
6
6
  "author": "Hitachi Vantara UI Kit Team",
@@ -22,7 +22,7 @@
22
22
  "react-router-dom": "^6.9.0"
23
23
  },
24
24
  "optionalDependencies": {
25
- "@hitachivantara/uikit-react-core": "^6.8.0"
25
+ "@hitachivantara/uikit-react-core": "^6.8.2"
26
26
  },
27
27
  "files": [
28
28
  "dist"
@@ -39,7 +39,7 @@
39
39
  "access": "public",
40
40
  "directory": "package"
41
41
  },
42
- "gitHead": "f79885f320f5cdf5b438ef8b2e866965c9626ce7",
42
+ "gitHead": "333e132a9823018d508ebbe71c81d0b467f9008d",
43
43
  "types": "./dist/index.d.ts",
44
44
  "module": "dist/index.js"
45
45
  }