@c-rex/components 0.1.38 → 0.1.39

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 (71) hide show
  1. package/README.md +73 -73
  2. package/package.json +250 -218
  3. package/src/article/article-action-bar.tsx +110 -110
  4. package/src/article/article-content.tsx +18 -46
  5. package/src/autocomplete.tsx +201 -201
  6. package/src/breadcrumb.tsx +124 -124
  7. package/src/carousel/carousel.tsx +353 -353
  8. package/src/check-article-lang.tsx +47 -47
  9. package/src/directoryNodes/directory-tree-context.tsx +388 -0
  10. package/src/directoryNodes/tree-of-content.tsx +68 -67
  11. package/src/documents/result-list.tsx +124 -127
  12. package/src/favorites/bookmark-button.tsx +97 -94
  13. package/src/favorites/favorite-button.tsx +137 -120
  14. package/src/footer/footer-shell.tsx +52 -0
  15. package/src/footer/footer.tsx +7 -0
  16. package/src/footer/legal-links-block.tsx +25 -0
  17. package/src/footer/organization-contact-block.tsx +94 -0
  18. package/src/footer/social-links-block.tsx +38 -0
  19. package/src/footer/types.ts +10 -0
  20. package/src/footer/vcard-footer.tsx +72 -0
  21. package/src/generated/client-components.tsx +1366 -1350
  22. package/src/generated/create-client-request.tsx +116 -113
  23. package/src/generated/create-server-request.tsx +70 -61
  24. package/src/generated/create-suggestions-request.tsx +55 -55
  25. package/src/generated/server-components.tsx +1056 -1056
  26. package/src/generated/suggestions.tsx +302 -299
  27. package/src/icons/file-icon.tsx +8 -8
  28. package/src/icons/flag-icon.tsx +15 -15
  29. package/src/icons/loading.tsx +11 -11
  30. package/src/icons/social-icon.tsx +24 -0
  31. package/src/info/info-card.tsx +43 -0
  32. package/src/info/{info-table.tsx → information-unit-metadata-grid.tsx} +157 -168
  33. package/src/info/shared.tsx +49 -25
  34. package/src/navbar/language-switcher/content-language-switch.tsx +92 -92
  35. package/src/navbar/language-switcher/shared.tsx +33 -33
  36. package/src/navbar/language-switcher/ui-language-switch.tsx +37 -37
  37. package/src/navbar/navbar.tsx +157 -152
  38. package/src/navbar/settings.tsx +62 -62
  39. package/src/navbar/sign-in-out-btns.tsx +35 -35
  40. package/src/navbar/user-menu.tsx +60 -60
  41. package/src/page-wrapper.tsx +54 -31
  42. package/src/render-article.module.css +155 -0
  43. package/src/render-article.tsx +75 -68
  44. package/src/renditions/file-download.tsx +83 -83
  45. package/src/renditions/html.tsx +64 -64
  46. package/src/renditions/image/container.tsx +54 -54
  47. package/src/renditions/image/rendition.tsx +55 -55
  48. package/src/restriction-menu/restriction-menu-container.tsx +117 -53
  49. package/src/restriction-menu/restriction-menu-item.tsx +155 -147
  50. package/src/restriction-menu/restriction-menu.tsx +341 -156
  51. package/src/results/dialog-filter.tsx +166 -166
  52. package/src/results/empty.tsx +15 -15
  53. package/src/results/filter-navbar.tsx +294 -261
  54. package/src/results/filter-sidebar/__tests__/utils.test.ts +129 -0
  55. package/src/results/filter-sidebar/index.tsx +270 -126
  56. package/src/results/filter-sidebar/utils.ts +196 -164
  57. package/src/results/generic/table-result-list.tsx +97 -99
  58. package/src/results/{table-with-images.tsx → information-unit-search-results-card-list.tsx} +125 -127
  59. package/src/results/{cards.tsx → information-unit-search-results-cards.tsx} +99 -99
  60. package/src/results/{table.tsx → information-unit-search-results-table.tsx} +104 -104
  61. package/src/results/pagination.tsx +81 -81
  62. package/src/results/summary.ts +30 -0
  63. package/src/results/utils.ts +54 -54
  64. package/src/search-input.tsx +70 -70
  65. package/src/share-button.tsx +49 -49
  66. package/src/stores/favorites-store.ts +88 -88
  67. package/src/stores/highlight-store.ts +15 -15
  68. package/src/stores/language-store.ts +14 -14
  69. package/src/stores/restriction-store.ts +11 -11
  70. package/src/stores/search-settings-store.ts +68 -64
  71. package/src/info/set-available-versions.tsx +0 -19
@@ -1,156 +1,341 @@
1
- "use client";
2
-
3
- import { FC, useEffect, useMemo, useState } from "react"
4
- import {
5
- NavigationMenu,
6
- NavigationMenuList,
7
- NavigationMenuItem,
8
- NavigationMenuTrigger,
9
- NavigationMenuContent,
10
- } from "@c-rex/ui/navigation-menu";
11
- import { RestrictionDropdownItem, RestrictionNavigationItem } from "./restriction-menu-item";
12
- import { parseAsString, useQueryStates } from "nuqs";
13
- import { InformationSubjectModel } from "@c-rex/interfaces";
14
- import { useLocale, useTranslations } from 'next-intl'
15
- import { cn, getLabelByLang } from "@c-rex/utils";
16
- import { useRestrictionStore } from "../stores/restriction-store";
17
- import { useBreakpoint } from "@c-rex/ui/hooks";
18
- import { DEVICE_OPTIONS } from "@c-rex/constants";
19
-
20
-
21
- type Props = {
22
- restrictField: string
23
- navigationMenuListClassName?: string
24
- items: InformationSubjectModel[],
25
- itemsByRow?: {
26
- [DEVICE_OPTIONS.MOBILE]: number,
27
- [DEVICE_OPTIONS.TABLET]: number,
28
- [DEVICE_OPTIONS.DESKTOP]: number,
29
- }
30
- }
31
-
32
- export const RestrictionMenu: FC<Props> = ({
33
- items,
34
- restrictField,
35
- navigationMenuListClassName = "items-center justify-between flex-row",
36
- itemsByRow = {
37
- [DEVICE_OPTIONS.MOBILE]: 2,
38
- [DEVICE_OPTIONS.TABLET]: 5,
39
- [DEVICE_OPTIONS.DESKTOP]: 7,
40
- }
41
- }) => {
42
- const t = useTranslations();
43
- const setRestrictionList = useRestrictionStore((state) => state.setRestrictionList);
44
-
45
- const [params] = useQueryStates({
46
- restrict: parseAsString,
47
- }, {
48
- history: 'push',
49
- shallow: false,
50
- });
51
-
52
- const restrictionValues = useMemo(() => params.restrict?.split(`${restrictField}=`)[1]?.split(",") || [], [params.restrict, restrictField]);
53
-
54
- const uiLang = useLocale();
55
- const lang = uiLang?.split("-")[0] ?? "";
56
-
57
- useEffect(() => {
58
- const map = new Map<string, string>();
59
- items.forEach((item) => {
60
- const label = getLabelByLang(item.labels, lang);
61
- if (item.shortId && label) {
62
- map.set(item.shortId, label);
63
- }
64
- });
65
- setRestrictionList(map);
66
- }, [items, lang, setRestrictionList]);
67
-
68
- const sortedItems = useMemo(() => {
69
- //if shortId it is on the restrictionValues, it should be on top of the list, otherwise keep the original order
70
-
71
- const sorted = [...items].sort((a, b) => {
72
- const aShortId = a.shortId || "";
73
- const bShortId = b.shortId || "";
74
-
75
- const aIndex = restrictionValues.indexOf(aShortId);
76
- const bIndex = restrictionValues.indexOf(bShortId);
77
-
78
- if (aIndex === -1 && bIndex === -1) {
79
- return 0; // keep original order if neither is in restrictionValues
80
- }
81
- if (aIndex === -1) {
82
- return 1; // a goes after b
83
- }
84
- if (bIndex === -1) {
85
- return -1; // a goes before b
86
- }
87
- return aIndex - bIndex; // sort by index in restrictionValues
88
- });
89
- return sorted;
90
- }, [items, restrictionValues]);
91
-
92
- const device = useBreakpoint();
93
- const [visibleCount, setVisibleCount] = useState(0);
94
- const [visibleItems, setVisibleItems] = useState(sortedItems.slice(0, visibleCount));
95
- const [hiddenItems, setHiddenItems] = useState(sortedItems.slice(visibleCount));
96
-
97
- useEffect(() => {
98
- if (device == null) return
99
- setVisibleCount(itemsByRow[device as keyof typeof DEVICE_OPTIONS] as number);
100
-
101
- }, [device, itemsByRow]);
102
-
103
- useEffect(() => {
104
- if (visibleCount == 0) return;
105
-
106
- setVisibleItems(sortedItems.slice(0, visibleCount));
107
- setHiddenItems(sortedItems.slice(visibleCount));
108
- }, [sortedItems, visibleCount]);
109
-
110
- return (
111
- <NavigationMenu viewport={false} className="max-w-full w-full c-rex-restriction-menu">
112
- <NavigationMenuList className={cn("w-full", navigationMenuListClassName)}>
113
-
114
-
115
- <RestrictionNavigationItem
116
- removeRestrictParam
117
- label={t('all')}
118
- selected={restrictionValues.length === 0}
119
- />
120
-
121
- {visibleItems.map((item) => (
122
- <RestrictionNavigationItem
123
- key={item.shortId}
124
- shortId={item.shortId!}
125
- restrictField={restrictField as string}
126
- label={getLabelByLang(item.labels, lang)}
127
- selected={restrictionValues.includes(item.shortId!)}
128
- />
129
- ))}
130
-
131
- <NavigationMenuItem>
132
- <NavigationMenuTrigger>
133
- {t('more')}
134
- </NavigationMenuTrigger>
135
- <NavigationMenuContent className="w-96 sm:w-[] md:w-[700px] lg:w-[65rem]">
136
- <ul className="grid gap-1 sm:grid-cols-3 md:grid-cols-4 lg:grid-cols-4">
137
- {hiddenItems.map((item) => (
138
- <li
139
- key={item.shortId}
140
- className="flex items-center"
141
- >
142
- <RestrictionDropdownItem
143
- shortId={item.shortId!}
144
- restrictField={restrictField as string}
145
- label={getLabelByLang(item.labels, lang)}
146
- selected={restrictionValues.includes(item.shortId!)}
147
- />
148
- </li>
149
- ))}
150
- </ul>
151
- </NavigationMenuContent>
152
- </NavigationMenuItem>
153
- </NavigationMenuList>
154
- </NavigationMenu>
155
- );
156
- };
1
+ "use client";
2
+
3
+ import { FC, useEffect, useMemo, useState } from "react"
4
+ import {
5
+ NavigationMenu,
6
+ NavigationMenuList,
7
+ NavigationMenuItem,
8
+ NavigationMenuTrigger,
9
+ NavigationMenuContent,
10
+ } from "@c-rex/ui/navigation-menu";
11
+ import { RestrictionDropdownItem, RestrictionNavigationItem } from "./restriction-menu-item";
12
+ import { parseAsString, useQueryStates } from "nuqs";
13
+ import { DomainEntityModel, ObjectRefModel } from "@c-rex/interfaces";
14
+ import { useLocale, useTranslations } from 'next-intl'
15
+ import { cn, getLabelByLang } from "@c-rex/utils";
16
+ import { useRestrictionStore } from "../stores/restriction-store";
17
+ import { useBreakpoint } from "@c-rex/ui/hooks";
18
+ import { DEVICE_OPTIONS } from "@c-rex/constants";
19
+ import { ChevronDown, ChevronRight } from "lucide-react";
20
+
21
+
22
+ type Props = {
23
+ restrictField: string
24
+ navigationMenuListClassName?: string
25
+ items: DomainEntityModel[],
26
+ enableHierarchy?: boolean,
27
+ hasMoreItems?: boolean,
28
+ showAllWhenEmpty?: boolean,
29
+ onRequestMore?: () => void,
30
+ itemsByRow?: {
31
+ [DEVICE_OPTIONS.MOBILE]: number,
32
+ [DEVICE_OPTIONS.TABLET]: number,
33
+ [DEVICE_OPTIONS.DESKTOP]: number,
34
+ }
35
+ }
36
+
37
+ type RestrictionTreeNode = {
38
+ item: DomainEntityModel;
39
+ children: RestrictionTreeNode[];
40
+ };
41
+
42
+ const getNodeKeys = (item: DomainEntityModel): string[] => {
43
+ const keys = new Set<string>();
44
+ if (item.shortId) keys.add(`short:${item.shortId}`);
45
+ if (item.id) keys.add(`id:${item.id}`);
46
+ return Array.from(keys);
47
+ };
48
+
49
+ const extractParentKeys = (item: DomainEntityModel): string[] => {
50
+ const withParents = item as DomainEntityModel & { parents?: ObjectRefModel[] | null };
51
+ return (withParents.parents || [])
52
+ .flatMap((parent) => {
53
+ const keys: string[] = [];
54
+ if (parent.shortId) keys.push(`short:${parent.shortId}`);
55
+ if (parent.id) keys.push(`id:${parent.id}`);
56
+ return keys;
57
+ });
58
+ };
59
+
60
+ const buildRestrictionTree = (items: DomainEntityModel[]): RestrictionTreeNode[] => {
61
+ const nodes = new Map<string, RestrictionTreeNode>();
62
+ items.forEach((item) => {
63
+ const keys = getNodeKeys(item);
64
+ if (keys.length === 0) return;
65
+ const node: RestrictionTreeNode = { item, children: [] };
66
+ keys.forEach((key) => nodes.set(key, node));
67
+ });
68
+
69
+ const roots: RestrictionTreeNode[] = [];
70
+ const linked = new Set<RestrictionTreeNode>();
71
+ const rootSet = new Set<RestrictionTreeNode>();
72
+
73
+ items.forEach((item) => {
74
+ const [firstKey] = getNodeKeys(item);
75
+ if (!firstKey) return;
76
+ const node = nodes.get(firstKey);
77
+ if (!node) return;
78
+
79
+ const parentKeys = extractParentKeys(item);
80
+ const parentNode = parentKeys
81
+ .map((parentKey) => nodes.get(parentKey))
82
+ .find((candidate) => candidate !== undefined);
83
+
84
+ if (parentNode) {
85
+ if (!parentNode.children.includes(node)) {
86
+ parentNode.children.push(node);
87
+ }
88
+ linked.add(node);
89
+ return;
90
+ }
91
+
92
+ rootSet.add(node);
93
+ });
94
+
95
+ rootSet.forEach((root) => {
96
+ if (!linked.has(root) || root.item.shortId) {
97
+ roots.push(root);
98
+ }
99
+ });
100
+
101
+ return roots;
102
+ };
103
+
104
+ export const RestrictionMenu: FC<Props> = ({
105
+ items,
106
+ restrictField,
107
+ enableHierarchy = false,
108
+ hasMoreItems = false,
109
+ showAllWhenEmpty = true,
110
+ onRequestMore,
111
+ navigationMenuListClassName = "items-center justify-between flex-row",
112
+ itemsByRow = {
113
+ [DEVICE_OPTIONS.MOBILE]: 2,
114
+ [DEVICE_OPTIONS.TABLET]: 5,
115
+ [DEVICE_OPTIONS.DESKTOP]: 7,
116
+ }
117
+ }) => {
118
+ const t = useTranslations();
119
+ const setRestrictionList = useRestrictionStore((state) => state.setRestrictionList);
120
+
121
+ const [params] = useQueryStates({
122
+ restrict: parseAsString,
123
+ }, {
124
+ history: 'push',
125
+ shallow: false,
126
+ });
127
+
128
+ const restrictionValues = useMemo(() => params.restrict?.split(`${restrictField}=`)[1]?.split(",") || [], [params.restrict, restrictField]);
129
+
130
+ const uiLang = useLocale();
131
+ const lang = uiLang?.split("-")[0] ?? "";
132
+
133
+ useEffect(() => {
134
+ const map = new Map<string, string>();
135
+ items.forEach((item) => {
136
+ const label = getLabelByLang(item.labels, lang);
137
+ if (item.shortId && label) {
138
+ map.set(item.shortId, label);
139
+ }
140
+ });
141
+ setRestrictionList(map);
142
+ }, [items, lang, setRestrictionList]);
143
+
144
+ const sortedItems = useMemo(() => {
145
+ //if shortId it is on the restrictionValues, it should be on top of the list, otherwise keep the original order
146
+
147
+ const sorted = [...items].sort((a, b) => {
148
+ const aShortId = a.shortId || "";
149
+ const bShortId = b.shortId || "";
150
+
151
+ const aIndex = restrictionValues.indexOf(aShortId);
152
+ const bIndex = restrictionValues.indexOf(bShortId);
153
+
154
+ if (aIndex === -1 && bIndex === -1) {
155
+ return 0; // keep original order if neither is in restrictionValues
156
+ }
157
+ if (aIndex === -1) {
158
+ return 1; // a goes after b
159
+ }
160
+ if (bIndex === -1) {
161
+ return -1; // a goes before b
162
+ }
163
+ return aIndex - bIndex; // sort by index in restrictionValues
164
+ });
165
+ return sorted;
166
+ }, [items, restrictionValues]);
167
+
168
+ const hierarchyRoots = useMemo(() => {
169
+ if (!enableHierarchy) return [];
170
+ return buildRestrictionTree(sortedItems);
171
+ }, [enableHierarchy, sortedItems]);
172
+
173
+ const device = useBreakpoint();
174
+ const [visibleCount, setVisibleCount] = useState(0);
175
+ const [visibleItems, setVisibleItems] = useState(sortedItems.slice(0, visibleCount));
176
+ const [hiddenItems, setHiddenItems] = useState(sortedItems.slice(visibleCount));
177
+
178
+ useEffect(() => {
179
+ if (device == null) return
180
+ setVisibleCount(itemsByRow[device as keyof typeof DEVICE_OPTIONS] as number);
181
+
182
+ }, [device, itemsByRow]);
183
+
184
+ useEffect(() => {
185
+ if (visibleCount == 0) return;
186
+
187
+ if (enableHierarchy) {
188
+ const roots = hierarchyRoots.map((node) => node.item);
189
+ setVisibleItems(roots.slice(0, visibleCount));
190
+ setHiddenItems(roots.slice(visibleCount));
191
+ return;
192
+ }
193
+
194
+ setVisibleItems(sortedItems.slice(0, visibleCount));
195
+ setHiddenItems(sortedItems.slice(visibleCount));
196
+ }, [enableHierarchy, hierarchyRoots, sortedItems, visibleCount]);
197
+
198
+ const visibleHierarchyRoots = useMemo(() => {
199
+ if (!enableHierarchy) return [];
200
+ const visibleRootShortIds = new Set(visibleItems.map((item) => item.shortId).filter(Boolean));
201
+ return hierarchyRoots.filter((root) => root.item.shortId && visibleRootShortIds.has(root.item.shortId));
202
+ }, [enableHierarchy, hierarchyRoots, visibleItems]);
203
+
204
+ const hiddenHierarchyRoots = useMemo(() => {
205
+ if (!enableHierarchy) return [];
206
+ const hiddenRootShortIds = new Set(hiddenItems.map((item) => item.shortId).filter(Boolean));
207
+ return hierarchyRoots.filter((root) => root.item.shortId && hiddenRootShortIds.has(root.item.shortId));
208
+ }, [enableHierarchy, hierarchyRoots, hiddenItems]);
209
+
210
+ const [expandedNodes, setExpandedNodes] = useState<Record<string, boolean>>({});
211
+ const toggleExpanded = (shortId: string) => {
212
+ setExpandedNodes((prev) => ({ ...prev, [shortId]: !prev[shortId] }));
213
+ };
214
+
215
+ const renderTreeNode = (node: RestrictionTreeNode, depth = 0) => {
216
+ const shortId = node.item.shortId || "";
217
+ const hasChildren = node.children.length > 0;
218
+ const isRootNode = depth === 0;
219
+ const isExpanded = isRootNode || expandedNodes[shortId] === true;
220
+
221
+ return (
222
+ <li key={`tree-node-${shortId}`} className="flex flex-col w-full">
223
+ <div className="flex items-center gap-1">
224
+ {hasChildren && !isRootNode ? (
225
+ <button
226
+ type="button"
227
+ onClick={() => toggleExpanded(shortId)}
228
+ className="shrink-0 rounded p-1 hover:bg-muted"
229
+ aria-label={isExpanded ? "Collapse" : "Expand"}
230
+ >
231
+ {isExpanded ? <ChevronDown className="h-4 w-4" /> : <ChevronRight className="h-4 w-4" />}
232
+ </button>
233
+ ) : (
234
+ <span className="inline-block w-6" />
235
+ )}
236
+ <div style={{ marginLeft: depth * 10 }} className="w-full">
237
+ <RestrictionDropdownItem
238
+ shortId={shortId}
239
+ restrictField={restrictField}
240
+ label={getLabelByLang(node.item.labels, lang)}
241
+ selected={restrictionValues.includes(shortId)}
242
+ />
243
+ </div>
244
+ </div>
245
+ {hasChildren && isExpanded && (
246
+ <ul className="pl-2">
247
+ {node.children.map((child) => renderTreeNode(child, depth + 1))}
248
+ </ul>
249
+ )}
250
+ </li>
251
+ );
252
+ };
253
+
254
+ return (
255
+ <NavigationMenu viewport={false} className="max-w-full w-full c-rex-restriction-menu">
256
+ <NavigationMenuList className={cn("w-full", navigationMenuListClassName)}>
257
+
258
+
259
+ {(showAllWhenEmpty || items.length > 0) && (
260
+ <RestrictionNavigationItem
261
+ removeRestrictParam
262
+ label={t('all')}
263
+ selected={restrictionValues.length === 0}
264
+ />
265
+ )}
266
+
267
+ {!enableHierarchy && visibleItems.map((item) => (
268
+ <RestrictionNavigationItem
269
+ key={item.shortId}
270
+ shortId={item.shortId!}
271
+ restrictField={restrictField as string}
272
+ label={getLabelByLang(item.labels, lang)}
273
+ selected={restrictionValues.includes(item.shortId!)}
274
+ />
275
+ ))}
276
+
277
+ {enableHierarchy && visibleHierarchyRoots.map((rootNode) => {
278
+ const shortId = rootNode.item.shortId || "";
279
+ const hasChildren = rootNode.children.length > 0;
280
+ const label = getLabelByLang(rootNode.item.labels, lang);
281
+
282
+ if (!hasChildren) {
283
+ return (
284
+ <RestrictionNavigationItem
285
+ key={shortId}
286
+ shortId={shortId}
287
+ restrictField={restrictField}
288
+ label={label}
289
+ selected={restrictionValues.includes(shortId)}
290
+ />
291
+ );
292
+ }
293
+
294
+ return (
295
+ <NavigationMenuItem key={`root-dropdown-${shortId}`}>
296
+ <NavigationMenuTrigger>
297
+ {label}
298
+ </NavigationMenuTrigger>
299
+ <NavigationMenuContent className="w-96 sm:w-[420px] md:w-[520px]">
300
+ <ul className="grid gap-1">
301
+ {renderTreeNode(rootNode, 0)}
302
+ </ul>
303
+ </NavigationMenuContent>
304
+ </NavigationMenuItem>
305
+ );
306
+ })}
307
+
308
+ {(enableHierarchy ? hiddenHierarchyRoots.length > 0 : hiddenItems.length > 0) || hasMoreItems ? (
309
+ <NavigationMenuItem>
310
+ <NavigationMenuTrigger onClick={onRequestMore}>
311
+ {t('more')}
312
+ </NavigationMenuTrigger>
313
+ <NavigationMenuContent className="w-96 sm:w-[] md:w-[700px] lg:w-[65rem]">
314
+ {enableHierarchy ? (
315
+ <ul className="grid gap-1 sm:grid-cols-2 md:grid-cols-2 lg:grid-cols-3">
316
+ {hiddenHierarchyRoots.map((node) => renderTreeNode(node, 0))}
317
+ </ul>
318
+ ) : (
319
+ <ul className="grid gap-1 sm:grid-cols-3 md:grid-cols-4 lg:grid-cols-4">
320
+ {hiddenItems.map((item) => (
321
+ <li
322
+ key={item.shortId}
323
+ className="flex items-center"
324
+ >
325
+ <RestrictionDropdownItem
326
+ shortId={item.shortId!}
327
+ restrictField={restrictField as string}
328
+ label={getLabelByLang(item.labels, lang)}
329
+ selected={restrictionValues.includes(item.shortId!)}
330
+ />
331
+ </li>
332
+ ))}
333
+ </ul>
334
+ )}
335
+ </NavigationMenuContent>
336
+ </NavigationMenuItem>
337
+ ) : null}
338
+ </NavigationMenuList>
339
+ </NavigationMenu>
340
+ );
341
+ };