@hitachivantara/app-shell-ui 2.3.2 → 2.3.3

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.
Files changed (62) hide show
  1. package/dist/components/AppShell/AppShell.js +16 -5
  2. package/dist/components/AppShell/AppShellContainer.js +75 -66
  3. package/dist/components/AppShell/AppShellRouter.js +98 -109
  4. package/dist/components/AppShellI18nProvider/AppShellI18nProvider.js +19 -25
  5. package/dist/components/AppShellProvider/AppShellProvider.js +84 -91
  6. package/dist/components/AppShellViewProvider/AppShellViewProvider.js +10 -7
  7. package/dist/components/ConfigIcon.js +13 -15
  8. package/dist/components/CustomHooksInitializer/CustomHooksInitializer.js +7 -7
  9. package/dist/components/GlobalStyles.js +11 -9
  10. package/dist/components/IconUiKit/IconUiKit.js +10 -8
  11. package/dist/components/InitErrorFallback/InitErrorFallback.js +31 -23
  12. package/dist/components/SnackbarProvider/SnackbarProvider.js +17 -20
  13. package/dist/components/layout/AppShellLayout.js +50 -65
  14. package/dist/components/layout/BrandLogo/BrandLogo.js +25 -35
  15. package/dist/components/layout/BrandLogo/logos.js +38 -55
  16. package/dist/components/layout/Header/Header.js +55 -74
  17. package/dist/components/layout/HeaderActions/AppSwitcherToggle/AppSwitcherToggle.js +66 -74
  18. package/dist/components/layout/HeaderActions/AppSwitcherToggle/styles.js +12 -12
  19. package/dist/components/layout/HeaderActions/ColorModeSwitcher.js +23 -26
  20. package/dist/components/layout/HeaderActions/DynamicAction.js +22 -21
  21. package/dist/components/layout/HeaderActions/HeaderActions.js +15 -22
  22. package/dist/components/layout/HeaderActions/HelpButton/HelpButton.js +22 -31
  23. package/dist/components/layout/HeaderActions/InternalAction/InternalAction.js +25 -36
  24. package/dist/components/layout/VerticalNavigation/NavigationCollapse.js +29 -34
  25. package/dist/components/layout/VerticalNavigation/NavigationHeader.js +18 -20
  26. package/dist/components/layout/VerticalNavigation/VerticalNavigation.js +96 -130
  27. package/dist/hooks/useClearLocationState.js +10 -12
  28. package/dist/hooks/useConditionsEvaluator.js +67 -81
  29. package/dist/hooks/useCustomEventListener.js +16 -28
  30. package/dist/hooks/useFilteredModel.js +30 -27
  31. package/dist/hooks/useLocalStorage.js +26 -26
  32. package/dist/hooks/useModelFromConfig.js +43 -39
  33. package/dist/hooks/useNavigationMenuItems.js +27 -30
  34. package/dist/hooks/useNotificationsEventListener.js +35 -42
  35. package/dist/hooks/useResizeObserver.js +13 -13
  36. package/dist/hooks/useThemeEventListener.js +17 -18
  37. package/dist/i18n/constants.js +5 -6
  38. package/dist/i18n/index.js +26 -20
  39. package/dist/i18n/useI18nInit.js +72 -66
  40. package/dist/index.js +4 -3
  41. package/dist/pages/ErrorPage/ErrorPage.js +33 -32
  42. package/dist/pages/ErrorPage/Footer.js +46 -55
  43. package/dist/pages/GenericError/CatServer.js +585 -569
  44. package/dist/pages/GenericError/GenericError.js +25 -26
  45. package/dist/pages/LoadingPage/LoadingPage.js +9 -17
  46. package/dist/pages/LoadingPage/index.js +4 -3
  47. package/dist/pages/NotFound/DogeSpace.js +505 -540
  48. package/dist/pages/NotFound/NotFound.js +17 -20
  49. package/dist/pages/NotFound/index.js +2 -4
  50. package/dist/pages/RootRoute.js +32 -19
  51. package/dist/providers/BannerProvider.js +98 -123
  52. package/dist/providers/LayoutProvider.js +26 -32
  53. package/dist/providers/NavigationProvider.js +96 -107
  54. package/dist/utils/CombinedProviders.js +12 -18
  55. package/dist/utils/documentUtil.js +12 -12
  56. package/dist/utils/filterModel.js +134 -170
  57. package/dist/utils/lazyImport.js +31 -36
  58. package/dist/utils/navigationUtil.js +68 -53
  59. package/dist/utils/processConfig.js +119 -153
  60. package/package.json +8 -8
  61. package/dist/components/IconUiKit/index.js +0 -6
  62. package/dist/pages/LoadingPage/styles.js +0 -30
@@ -1,13 +1,13 @@
1
- const createAppContainerElement = (id) => {
2
- const panelContainerId = "app-shell-panel-container";
3
- let panelContainerElement = document.getElementById(panelContainerId);
4
- if (!panelContainerElement) {
5
- panelContainerElement = document.createElement("div");
6
- panelContainerElement.id = panelContainerId;
7
- document.body.appendChild(panelContainerElement);
8
- }
9
- return panelContainerElement;
10
- };
11
- export {
12
- createAppContainerElement as default
1
+ //#region src/utils/documentUtil.ts
2
+ var createAppContainerElement = (id) => {
3
+ const panelContainerId = "app-shell-panel-container";
4
+ let panelContainerElement = document.getElementById(id ?? panelContainerId);
5
+ if (!panelContainerElement) {
6
+ panelContainerElement = document.createElement("div");
7
+ panelContainerElement.id = panelContainerId;
8
+ document.body.appendChild(panelContainerElement);
9
+ }
10
+ return panelContainerElement;
13
11
  };
12
+ //#endregion
13
+ export { createAppContainerElement as default };
@@ -1,178 +1,142 @@
1
- const shouldInclude = (conditions, conditionResults) => {
2
- if (!conditions || conditions.length === 0) {
3
- return true;
4
- }
5
- for (const condition of conditions) {
6
- if (!conditionResults[condition.globalIndex]) {
7
- return false;
8
- }
9
- }
10
- return true;
1
+ //#region src/utils/filterModel.ts
2
+ var shouldInclude = (conditions, conditionResults) => {
3
+ if (!conditions || conditions.length === 0) return true;
4
+ for (const condition of conditions) if (!conditionResults[condition.globalIndex]) return false;
5
+ return true;
11
6
  };
12
- const filterViews = (views, conditionResults) => {
13
- const filteredViews = [];
14
- let hasChanged = false;
15
- for (const view of views) {
16
- const include = shouldInclude(view.conditions, conditionResults);
17
- if (!include) {
18
- hasChanged = true;
19
- continue;
20
- }
21
- if (!view.views) {
22
- filteredViews.push(view);
23
- continue;
24
- }
25
- const [filteredSubViews, subViewsChanged] = filterViews(
26
- view.views,
27
- conditionResults
28
- );
29
- if (subViewsChanged) {
30
- filteredViews.push({ ...view, views: filteredSubViews });
31
- hasChanged = true;
32
- } else {
33
- filteredViews.push(view);
34
- }
35
- }
36
- return [hasChanged ? filteredViews : views, hasChanged];
7
+ var filterViews = (views, conditionResults) => {
8
+ const filteredViews = [];
9
+ let hasChanged = false;
10
+ for (const view of views) {
11
+ if (!shouldInclude(view.conditions, conditionResults)) {
12
+ hasChanged = true;
13
+ continue;
14
+ }
15
+ if (!view.views) {
16
+ filteredViews.push(view);
17
+ continue;
18
+ }
19
+ const [filteredSubViews, subViewsChanged] = filterViews(view.views, conditionResults);
20
+ if (subViewsChanged) {
21
+ filteredViews.push({
22
+ ...view,
23
+ views: filteredSubViews
24
+ });
25
+ hasChanged = true;
26
+ } else filteredViews.push(view);
27
+ }
28
+ return [hasChanged ? filteredViews : views, hasChanged];
37
29
  };
38
- const filterMenus = (menus, conditionResults) => {
39
- const filteredMenus = [];
40
- let hasChanged = false;
41
- for (const menu of menus) {
42
- const include = shouldInclude(menu.conditions, conditionResults);
43
- const hasSubmenus = menu.submenus && menu.submenus.length > 0;
44
- if (!include || !menu.target && !hasSubmenus) {
45
- hasChanged = true;
46
- continue;
47
- }
48
- if (!hasSubmenus) {
49
- filteredMenus.push(menu);
50
- continue;
51
- }
52
- const [filteredSubmenus, submenusChanged] = filterMenus(
53
- menu.submenus,
54
- conditionResults
55
- );
56
- if (filteredSubmenus.length === 0) {
57
- hasChanged = true;
58
- continue;
59
- }
60
- if (submenusChanged) {
61
- filteredMenus.push({
62
- ...menu,
63
- submenus: filteredSubmenus
64
- });
65
- hasChanged = true;
66
- } else {
67
- filteredMenus.push(menu);
68
- }
69
- }
70
- return [hasChanged ? filteredMenus : menus, hasChanged];
30
+ /**
31
+ * Recursively filters menu entries based on condition results and structural validity.
32
+ *
33
+ * A menu is excluded when:
34
+ * 1. Its conditions evaluate to false (condition-based filtering), or
35
+ * 2. It has no `target` and no `submenus` (invalid config guard), or
36
+ * 3. It is a parent whose children were all filtered out, leaving it empty.
37
+ *
38
+ * Preserves object references when no changes occur to minimize re-renders.
39
+ */
40
+ var filterMenus = (menus, conditionResults) => {
41
+ const filteredMenus = [];
42
+ let hasChanged = false;
43
+ for (const menu of menus) {
44
+ const include = shouldInclude(menu.conditions, conditionResults);
45
+ const hasSubmenus = menu.submenus && menu.submenus.length > 0;
46
+ if (!include || !menu.target && !hasSubmenus) {
47
+ hasChanged = true;
48
+ continue;
49
+ }
50
+ if (!hasSubmenus) {
51
+ filteredMenus.push(menu);
52
+ continue;
53
+ }
54
+ const [filteredSubmenus, submenusChanged] = filterMenus(menu.submenus, conditionResults);
55
+ if (filteredSubmenus.length === 0) {
56
+ hasChanged = true;
57
+ continue;
58
+ }
59
+ if (submenusChanged) {
60
+ filteredMenus.push({
61
+ ...menu,
62
+ submenus: filteredSubmenus
63
+ });
64
+ hasChanged = true;
65
+ } else filteredMenus.push(menu);
66
+ }
67
+ return [hasChanged ? filteredMenus : menus, hasChanged];
71
68
  };
72
- const filterActions = (actions, conditionResults) => {
73
- const filteredHeaderActions = [];
74
- for (const action of actions) {
75
- const include = shouldInclude(action.conditions, conditionResults);
76
- if (include) filteredHeaderActions.push(action);
77
- }
78
- const hasChanged = filteredHeaderActions.length !== actions.length;
79
- return [hasChanged ? filteredHeaderActions : actions, hasChanged];
69
+ var filterActions = (actions, conditionResults) => {
70
+ const filteredHeaderActions = [];
71
+ for (const action of actions) if (shouldInclude(action.conditions, conditionResults)) filteredHeaderActions.push(action);
72
+ const hasChanged = filteredHeaderActions.length !== actions.length;
73
+ return [hasChanged ? filteredHeaderActions : actions, hasChanged];
80
74
  };
81
- const filterProviders = (providers, conditionResults) => {
82
- const filteredProviders = [];
83
- for (const provider of providers) {
84
- const include = shouldInclude(provider.conditions, conditionResults);
85
- if (include) filteredProviders.push(provider);
86
- }
87
- const hasChanged = filteredProviders.length !== providers.length;
88
- return [hasChanged ? filteredProviders : providers, hasChanged];
75
+ var filterProviders = (providers, conditionResults) => {
76
+ const filteredProviders = [];
77
+ for (const provider of providers) if (shouldInclude(provider.conditions, conditionResults)) filteredProviders.push(provider);
78
+ const hasChanged = filteredProviders.length !== providers.length;
79
+ return [hasChanged ? filteredProviders : providers, hasChanged];
89
80
  };
90
- const filterServices = (services, conditionResults) => {
91
- if (!services) {
92
- return [services, false];
93
- }
94
- const filteredServices = {};
95
- let hasChanged = false;
96
- for (const [serviceId, serviceProviderModels] of Object.entries(services)) {
97
- const result = [];
98
- let localChanged = false;
99
- for (const serviceConfigModel of serviceProviderModels) {
100
- const include = shouldInclude(
101
- serviceConfigModel.conditions,
102
- conditionResults
103
- );
104
- if (include) {
105
- result.push(serviceConfigModel);
106
- } else {
107
- localChanged = true;
108
- }
109
- }
110
- if (localChanged) hasChanged = true;
111
- filteredServices[serviceId] = localChanged ? result : serviceProviderModels;
112
- }
113
- return [hasChanged ? filteredServices : services, hasChanged];
81
+ var filterServices = (services, conditionResults) => {
82
+ if (!services) return [services, false];
83
+ const filteredServices = {};
84
+ let hasChanged = false;
85
+ for (const [serviceId, serviceProviderModels] of Object.entries(services)) {
86
+ const result = [];
87
+ let localChanged = false;
88
+ for (const serviceConfigModel of serviceProviderModels) if (shouldInclude(serviceConfigModel.conditions, conditionResults)) result.push(serviceConfigModel);
89
+ else localChanged = true;
90
+ if (localChanged) hasChanged = true;
91
+ filteredServices[serviceId] = localChanged ? result : serviceProviderModels;
92
+ }
93
+ return [hasChanged ? filteredServices : services, hasChanged];
114
94
  };
115
95
  function filterModel(model, conditionResults) {
116
- let hasChanged = false;
117
- const filtered = { ...model };
118
- if (model.mainPanel?.views) {
119
- const [filteredViews, viewsChanged] = filterViews(
120
- model.mainPanel.views,
121
- conditionResults
122
- );
123
- if (viewsChanged) {
124
- filtered.mainPanel = {
125
- ...model.mainPanel,
126
- views: filteredViews
127
- };
128
- hasChanged = true;
129
- }
130
- }
131
- if (model.menu) {
132
- const [filteredMenus, menusChanged] = filterMenus(
133
- model.menu,
134
- conditionResults
135
- );
136
- if (menusChanged) {
137
- filtered.menu = filteredMenus;
138
- hasChanged = true;
139
- }
140
- }
141
- if (model.header?.actions) {
142
- const [filteredActions, actionsChanged] = filterActions(
143
- model.header.actions,
144
- conditionResults
145
- );
146
- if (actionsChanged) {
147
- filtered.header = {
148
- ...model.header,
149
- actions: filteredActions
150
- };
151
- hasChanged = true;
152
- }
153
- }
154
- if (model.providers) {
155
- const [filteredProviders, providersChanged] = filterProviders(
156
- model.providers,
157
- conditionResults
158
- );
159
- if (providersChanged) {
160
- filtered.providers = filteredProviders;
161
- hasChanged = true;
162
- }
163
- }
164
- if (model.services) {
165
- const [filteredServices, servicesChanged] = filterServices(
166
- model.services,
167
- conditionResults
168
- );
169
- if (servicesChanged) {
170
- filtered.services = filteredServices;
171
- hasChanged = true;
172
- }
173
- }
174
- return hasChanged ? filtered : model;
96
+ let hasChanged = false;
97
+ const filtered = { ...model };
98
+ if (model.mainPanel?.views) {
99
+ const [filteredViews, viewsChanged] = filterViews(model.mainPanel.views, conditionResults);
100
+ if (viewsChanged) {
101
+ filtered.mainPanel = {
102
+ ...model.mainPanel,
103
+ views: filteredViews
104
+ };
105
+ hasChanged = true;
106
+ }
107
+ }
108
+ if (model.menu) {
109
+ const [filteredMenus, menusChanged] = filterMenus(model.menu, conditionResults);
110
+ if (menusChanged) {
111
+ filtered.menu = filteredMenus;
112
+ hasChanged = true;
113
+ }
114
+ }
115
+ if (model.header?.actions) {
116
+ const [filteredActions, actionsChanged] = filterActions(model.header.actions, conditionResults);
117
+ if (actionsChanged) {
118
+ filtered.header = {
119
+ ...model.header,
120
+ actions: filteredActions
121
+ };
122
+ hasChanged = true;
123
+ }
124
+ }
125
+ if (model.providers) {
126
+ const [filteredProviders, providersChanged] = filterProviders(model.providers, conditionResults);
127
+ if (providersChanged) {
128
+ filtered.providers = filteredProviders;
129
+ hasChanged = true;
130
+ }
131
+ }
132
+ if (model.services) {
133
+ const [filteredServices, servicesChanged] = filterServices(model.services, conditionResults);
134
+ if (servicesChanged) {
135
+ filtered.services = filteredServices;
136
+ hasChanged = true;
137
+ }
138
+ }
139
+ return hasChanged ? filtered : model;
175
140
  }
176
- export {
177
- filterModel as default
178
- };
141
+ //#endregion
142
+ export { filterModel as default };
@@ -1,40 +1,35 @@
1
+ //#region src/utils/lazyImport.ts
1
2
  async function lazyImport(bundle) {
2
- try {
3
- const module = await import(
4
- /* @vite-ignore */
5
- bundle
6
- );
7
- return {
8
- isPending: false,
9
- error: null,
10
- module: module.default
11
- };
12
- } catch (err) {
13
- const error = err instanceof Error ? err : new Error(String(err));
14
- return {
15
- isPending: false,
16
- error,
17
- module: void 0
18
- };
19
- }
3
+ try {
4
+ return {
5
+ isPending: false,
6
+ error: null,
7
+ module: (await import(
8
+ /* @vite-ignore */
9
+ bundle
10
+ )).default
11
+ };
12
+ } catch (err) {
13
+ return {
14
+ isPending: false,
15
+ error: err instanceof Error ? err : new Error(String(err)),
16
+ module: void 0
17
+ };
18
+ }
20
19
  }
21
20
  async function importAllBundles(bundles) {
22
- const results = await Promise.all(
23
- bundles.map((bundle) => lazyImport(bundle))
24
- );
25
- const preloadedBundles = /* @__PURE__ */ new Map();
26
- for (let i = 0; i < results.length; i++) {
27
- const result = results[i];
28
- const bundle = bundles[i];
29
- if (result.error) {
30
- console.error(`Failed to load bundle ${bundle}:`, result.error);
31
- continue;
32
- }
33
- preloadedBundles.set(bundle, result.module);
34
- }
35
- return preloadedBundles;
21
+ const results = await Promise.all(bundles.map((bundle) => lazyImport(bundle)));
22
+ const preloadedBundles = /* @__PURE__ */ new Map();
23
+ for (let i = 0; i < results.length; i++) {
24
+ const result = results[i];
25
+ const bundle = bundles[i];
26
+ if (result.error) {
27
+ console.error(`Failed to load bundle ${bundle}:`, result.error);
28
+ continue;
29
+ }
30
+ preloadedBundles.set(bundle, result.module);
31
+ }
32
+ return preloadedBundles;
36
33
  }
37
- export {
38
- importAllBundles,
39
- lazyImport
40
- };
34
+ //#endregion
35
+ export { importAllBundles };
@@ -1,58 +1,73 @@
1
- import { jsx } from "react/jsx-runtime";
2
1
  import { ConfigIcon } from "../components/ConfigIcon.js";
3
- const createNavigationMenuItems = (t, menuItems, maxDepth) => {
4
- if (maxDepth !== void 0 && maxDepth <= 0) {
5
- return [];
6
- }
7
- return menuItems?.reduce((accumulator, currentValue) => {
8
- const updatedDepth = maxDepth !== void 0 ? maxDepth - 1 : void 0;
9
- const navItem = {
10
- ...currentValue,
11
- icon: currentValue.icon && /* @__PURE__ */ jsx(ConfigIcon, { icon: currentValue.icon }),
12
- data: currentValue.data ? createNavigationMenuItems(t, currentValue.data, updatedDepth) : void 0
13
- };
14
- accumulator.push(navItem);
15
- return accumulator;
16
- }, []) ?? [];
17
- };
18
- const findItemById = (data, itemId) => {
19
- let foundItem = null;
20
- data.some((obj) => {
21
- const { id: objId, data: childData } = obj;
22
- if (objId === itemId) {
23
- foundItem = obj;
24
- return true;
25
- }
26
- if (childData && childData.length > 0) {
27
- foundItem = findItemById(childData, itemId);
28
- return foundItem !== null;
29
- }
30
- return false;
31
- });
32
- return foundItem;
2
+ import { jsx } from "react/jsx-runtime";
3
+ //#region src/utils/navigationUtil.tsx
4
+ /**
5
+ * Creates a navigation data structure ({@link MenuItem}) from the provided menu configuration ({@link NavigationMenuItem}).
6
+ *
7
+ * @param t
8
+ * @param menuItems The set of menu items from configuration.
9
+ * @param maxDepth The maximum depth up until the recursiveness should occur for the creation of the menu items.
10
+ *
11
+ * @returns An array of {@link MenuItem}.
12
+ */
13
+ var createNavigationMenuItems = (t, menuItems, maxDepth) => {
14
+ if (maxDepth !== void 0 && maxDepth <= 0) return [];
15
+ return menuItems?.reduce((accumulator, currentValue) => {
16
+ const updatedDepth = maxDepth !== void 0 ? maxDepth - 1 : void 0;
17
+ const navItem = {
18
+ ...currentValue,
19
+ icon: currentValue.icon && /* @__PURE__ */ jsx(ConfigIcon, { icon: currentValue.icon }),
20
+ data: currentValue.data ? createNavigationMenuItems(t, currentValue.data, updatedDepth) : void 0
21
+ };
22
+ accumulator.push(navItem);
23
+ return accumulator;
24
+ }, []) ?? [];
33
25
  };
34
- const getAppIdFromBundle = (bundle) => {
35
- const bundleTokens = bundle.split("/");
36
- let appId;
37
- if (bundleTokens[0].startsWith("@")) {
38
- appId = `${bundleTokens[0]}/${bundleTokens[1]}`;
39
- } else {
40
- [appId] = bundleTokens;
41
- }
42
- return appId;
26
+ /**
27
+ * Searches for an item with the specified id.
28
+ *
29
+ * @param {NavigationMenuItem[]} data - The navigation data structure.
30
+ * @param {string} itemId - The item id.
31
+ * @returns The item with matching id.
32
+ */
33
+ var findItemById = (data, itemId) => {
34
+ let foundItem = null;
35
+ data.some((obj) => {
36
+ const { id: objId, data: childData } = obj;
37
+ if (objId === itemId) {
38
+ foundItem = obj;
39
+ return true;
40
+ }
41
+ if (childData && childData.length > 0) {
42
+ foundItem = findItemById(childData, itemId);
43
+ return foundItem !== null;
44
+ }
45
+ return false;
46
+ });
47
+ return foundItem;
43
48
  };
44
- const removeHrefFromMenuItemsWithChildren = (items) => {
45
- return items.map((item) => {
46
- const { href, data, ...rest } = item;
47
- if (data && data.length > 0) {
48
- return { ...rest, data: removeHrefFromMenuItemsWithChildren(data) };
49
- }
50
- return item;
51
- });
49
+ var getAppIdFromBundle = (bundle) => {
50
+ const bundleTokens = bundle.split("/");
51
+ let appId;
52
+ if (bundleTokens[0].startsWith("@")) appId = `${bundleTokens[0]}/${bundleTokens[1]}`;
53
+ else [appId] = bundleTokens;
54
+ return appId;
52
55
  };
53
- export {
54
- createNavigationMenuItems,
55
- findItemById,
56
- getAppIdFromBundle,
57
- removeHrefFromMenuItemsWithChildren
56
+ /**
57
+ * Recursively removes the href property from items in the array if they have a non-empty data property.
58
+ *
59
+ * @param items - The array of items.
60
+ * @returns The new array with the href property removed from items with children.
61
+ */
62
+ var removeHrefFromMenuItemsWithChildren = (items) => {
63
+ return items.map((item) => {
64
+ const { href, data, ...rest } = item;
65
+ if (data && data.length > 0) return {
66
+ ...rest,
67
+ data: removeHrefFromMenuItemsWithChildren(data)
68
+ };
69
+ return item;
70
+ });
58
71
  };
72
+ //#endregion
73
+ export { createNavigationMenuItems, findItemById, getAppIdFromBundle, removeHrefFromMenuItemsWithChildren };