design-system-next 2.9.7 → 2.9.9

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.
@@ -139,7 +139,7 @@
139
139
  </div>
140
140
 
141
141
  <!-- Grouped Nav Links -->
142
- <template v-for="(navLink, navLinkIndex) in props.navLinks.top" :key="navLinkIndex">
142
+ <template v-for="(navLink, navLinkIndex) in navLinks.top" :key="navLinkIndex">
143
143
  <template v-for="(parentLink, parentLinkIndex) in navLink.parentLinks" :key="parentLinkIndex">
144
144
  <!-- Parent link with menu links -->
145
145
  <template v-if="parentLink.menuLinks && parentLink.menuLinks.length > 0">
@@ -352,7 +352,7 @@
352
352
  </template>
353
353
  </template>
354
354
  <div
355
- v-if="props.navLinks.top.length > 0 && navLinkIndex < props.navLinks.top.length - 1"
355
+ v-if="navLinks.top.length > 0 && navLinkIndex < navLinks.top.length - 1"
356
356
  class="spr-background-color-hover spr-h-[2px] spr-w-full"
357
357
  ></div>
358
358
  </template>
@@ -360,11 +360,11 @@
360
360
 
361
361
  <!-- Bottom Section -->
362
362
  <div
363
- v-if="props.navLinks.bottom && props.navLinks.bottom.length > 0"
363
+ v-if="navLinks.bottom && navLinks.bottom.length > 0"
364
364
  class="spr-grid spr-justify-center spr-gap-2 spr-px-3 spr-pb-4 spr-pt-0"
365
365
  >
366
366
  <!-- Grouped Nav Links -->
367
- <template v-for="(navLink, navLinkIndex) in props.navLinks.bottom" :key="navLinkIndex">
367
+ <template v-for="(navLink, navLinkIndex) in navLinks.bottom" :key="navLinkIndex">
368
368
  <template v-for="(parentLink, parentLinkIndex) in navLink.parentLinks" :key="parentLinkIndex">
369
369
  <!-- Parent link with menu links -->
370
370
  <template v-if="parentLink.menuLinks && parentLink.menuLinks.length > 0">
@@ -573,7 +573,7 @@
573
573
  </template>
574
574
  </template>
575
575
  <div
576
- v-if="props.navLinks.bottom.length > 0 && navLinkIndex < props.navLinks.bottom.length - 1"
576
+ v-if="navLinks.bottom.length > 0 && navLinkIndex < navLinks.bottom.length - 1"
577
577
  class="spr-background-color-hover spr-h-[2px] spr-w-full"
578
578
  ></div>
579
579
  </template>
@@ -767,7 +767,7 @@ import SprBadge from '../badge/badge.vue';
767
767
  const props = defineProps(sidenavPropTypes);
768
768
  const emit = defineEmits(sidenavEmitTypes);
769
769
 
770
- const { isQuckActionMenuVisible, isUserMenuVisible, userProfileError, getUserInitials, handleRedirect, generateId } = useSidenav(
770
+ const { navLinks, isQuckActionMenuVisible, isUserMenuVisible, userProfileError, getUserInitials, handleRedirect, generateId } = useSidenav(
771
771
  props,
772
772
  emit,
773
773
  );
@@ -1,7 +1,7 @@
1
- import { ref } from 'vue';
1
+ import { ref, onMounted } from 'vue';
2
2
  import type { SetupContext } from 'vue';
3
3
 
4
- import type { SidenavPropTypes, SidenavEmitTypes } from './sidenav';
4
+ import type { SidenavPropTypes, SidenavEmitTypes, ParentLinkItem, NavLinks, NavItem } from './sidenav';
5
5
 
6
6
  interface ObjectItem {
7
7
  redirect: {
@@ -17,6 +17,7 @@ interface ObjectItem {
17
17
  }
18
18
 
19
19
  export const useSidenav = (props: SidenavPropTypes, emit: SetupContext<SidenavEmitTypes>['emit']) => {
20
+ const navLinks = ref<NavLinks>(props.navLinks);
20
21
  const isQuckActionMenuVisible = ref(false);
21
22
 
22
23
  const isUserMenuVisible = ref(false);
@@ -67,13 +68,106 @@ export const useSidenav = (props: SidenavPropTypes, emit: SetupContext<SidenavEm
67
68
  const generateId = (...titles: string[]): string => {
68
69
  return titles.map(transformToCamelCaseId).join('_');
69
70
  }
71
+ const confirmIfOwnDomain = (url: string) => {
72
+ const domain = window.location.href;
73
+ const urlHostname = new URL(url).hostname;
74
+ const isOwnDomain = domain === urlHostname || window.location.hostname === 'localhost'
75
+ return isOwnDomain;
76
+ }
77
+
78
+ const getPathFromUrl = (url: string): string => {
79
+ const parsedUrl = new URL(url);
80
+ return parsedUrl ? parsedUrl.pathname : '';
81
+
82
+ }
83
+
84
+ const navLinkCondition = (link: NavItem) => {
85
+ if (confirmIfOwnDomain(link.url as string)) {
86
+ return getPathFromUrl(link.url as string);
87
+ } else {
88
+ return link.url;
89
+ }
90
+ }
91
+
92
+ const groupByGroupId = (items: NavItem[]) => {
93
+ const groups: Record<string, NavItem[]> = {};
94
+ items.forEach(item => {
95
+ if (!groups[item.groupId]) {
96
+ groups[item.groupId] = [];
97
+ }
98
+ groups[item.groupId].push(item);
99
+ });
100
+ return Object.values(groups).map(group => ({ parentLinks: group.map(mapItemToNav) }));
101
+ }
102
+
103
+ const mapItemToNav = (item: NavItem): ParentLinkItem => {
104
+ return {
105
+ title: item.label,
106
+ icon: item.icon || "",
107
+ redirect: item.url
108
+ ? {
109
+ openInNewTab: item.isNewTab || false,
110
+ isAbsoluteURL: !confirmIfOwnDomain(item.url),
111
+ link: navLinkCondition(item) || "",
112
+ }
113
+ : undefined,
114
+ menuLinks: item.children && item.children.length > 0
115
+ ? [{
116
+ menuHeading: '',
117
+ items: item.children.map(child => mapItemToNav(child))
118
+ }]
119
+ : [],
120
+ submenuLinks: item.children && item.children.length > 0 && !item.children.some(c => c.children)
121
+ ? [{
122
+ subMenuHeading: '',
123
+ items: item.children.map(child => mapItemToNav(child)),
124
+ }]
125
+ : [],
126
+ }
127
+ }
128
+
129
+ // Helper function to extract valid NavItems from an array of objects
130
+ const extractValidNavItems = <T extends Record<string, unknown>>(items: T[]): NavItem[] => {
131
+ return items.filter((item): item is NavItem & T => (
132
+ item !== null &&
133
+ 'groupId' in item &&
134
+ 'label' in item &&
135
+ typeof item.groupId === 'string' &&
136
+ typeof item.label === 'string'
137
+ )) as NavItem[];
138
+ };
139
+
140
+ const transformedNavItems = async (apiData: NavLinks) => {
141
+ // Output type matches navLinks ref type
142
+ const transformedData: NavLinks = { top: [], bottom: [] };
143
+
144
+ if (apiData.top && Array.isArray(apiData.top)) {
145
+ const validTopItems = extractValidNavItems(apiData.top);
146
+ transformedData.top = groupByGroupId(validTopItems);
147
+ }
148
+
149
+ if (apiData.bottom && Array.isArray(apiData.bottom)) {
150
+ const validBottomItems = extractValidNavItems(apiData.bottom);
151
+ transformedData.bottom = groupByGroupId(validBottomItems);
152
+ }
153
+
154
+ return transformedData;
155
+ }
156
+
157
+ onMounted(async () => {
158
+ if (props.isNavApi) {
159
+ navLinks.value = await transformedNavItems(props.navLinks);
160
+ }
161
+ })
70
162
 
71
163
  return {
164
+ navLinks,
72
165
  isQuckActionMenuVisible,
73
166
  isUserMenuVisible,
74
167
  userProfileError,
75
168
  getUserInitials,
76
169
  handleRedirect,
77
- generateId
170
+ generateId,
171
+ transformedNavItems,
78
172
  };
79
173
  };
@@ -0,0 +1,6 @@
1
+ interface ImportMeta { readonly glob: ImportMetaGlob }
2
+
3
+ interface ImportMetaGlob {
4
+ (pattern: string, options?: { eager?: boolean }): Record<string, () => Promise<unknown>>
5
+ (pattern: string, options?: { eager: true }): Record<string, unknown>
6
+ }