@stackshift-ui/navigation 6.0.13 → 6.1.0-alpha.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.
Files changed (56) hide show
  1. package/dist/chunk-4N6ET2I6.mjs +1 -0
  2. package/dist/{chunk-YNDJK4RH.mjs → chunk-67XVPRGX.mjs} +1 -1
  3. package/dist/chunk-6QSBJPEW.mjs +1 -0
  4. package/dist/{chunk-6XDFQS4J.mjs → chunk-EASZP4S2.mjs} +1 -1
  5. package/dist/{chunk-DJV2UTMZ.mjs → chunk-LBUYM4NV.mjs} +1 -1
  6. package/dist/chunk-MSVUIX4E.mjs +1 -0
  7. package/dist/chunk-OXF5VEOU.mjs +1 -0
  8. package/dist/chunk-P3TZNIE6.mjs +1 -0
  9. package/dist/chunk-PCTXJCVP.mjs +1 -0
  10. package/dist/{chunk-KB2HS5UA.mjs → chunk-SVLHEWIY.mjs} +1 -1
  11. package/dist/chunk-V7KKZJMX.mjs +1 -0
  12. package/dist/context/megaNavContext.d.ts +14 -0
  13. package/dist/context/megaNavContext.mjs +1 -0
  14. package/dist/helper/index.d.ts +2 -1
  15. package/dist/helper/index.mjs +1 -1
  16. package/dist/helper.d.ts +6 -0
  17. package/dist/helper.mjs +1 -0
  18. package/dist/index.d.ts +3 -0
  19. package/dist/index.mjs +1 -1
  20. package/dist/navigation.d.ts +9 -1
  21. package/dist/navigation.mjs +1 -1
  22. package/dist/navigation_a.mjs +1 -1
  23. package/dist/navigation_b.mjs +1 -1
  24. package/dist/navigation_c.mjs +1 -1
  25. package/dist/navigation_d.mjs +1 -1
  26. package/dist/navigation_e.mjs +1 -1
  27. package/dist/navigation_f.d.ts +3 -0
  28. package/dist/navigation_f.mjs +1 -0
  29. package/dist/navigation_g.d.ts +3 -0
  30. package/dist/navigation_g.mjs +1 -0
  31. package/dist/navigation_h.d.ts +3 -0
  32. package/dist/navigation_h.mjs +1 -0
  33. package/dist/types.d.ts +104 -1
  34. package/package.json +14 -6
  35. package/src/context/megaNavContext.tsx +78 -0
  36. package/src/helper/index.tsx +130 -0
  37. package/src/helper.ts +14 -0
  38. package/src/index.ts +3 -0
  39. package/src/navigation.tsx +29 -1
  40. package/src/navigation_f.tsx +531 -0
  41. package/src/navigation_g.tsx +607 -0
  42. package/src/navigation_h.tsx +742 -0
  43. package/src/types.ts +113 -1
  44. package/dist/chunk-KQFO7OZP.mjs +0 -1
  45. package/dist/chunk-TTJMPYYC.mjs +0 -1
  46. package/dist/helper/blockStyle.js +0 -1
  47. package/dist/helper/index.js +0 -1
  48. package/dist/index.js +0 -2
  49. package/dist/navigation.js +0 -1
  50. package/dist/navigation_a.js +0 -1
  51. package/dist/navigation_b.js +0 -1
  52. package/dist/navigation_c.js +0 -1
  53. package/dist/navigation_d.js +0 -1
  54. package/dist/navigation_e.js +0 -1
  55. package/dist/types.js +0 -1
  56. package/src/helper/index.ts +0 -14
@@ -0,0 +1,742 @@
1
+ import { Button } from "@stackshift-ui/button";
2
+ import { Flex } from "@stackshift-ui/flex";
3
+ import { Grid } from "@stackshift-ui/grid";
4
+ import { Heading } from "@stackshift-ui/heading";
5
+ import { Image } from "@stackshift-ui/image";
6
+ import { Link } from "@stackshift-ui/link";
7
+ import { Section } from "@stackshift-ui/section";
8
+ import { Text } from "@stackshift-ui/text";
9
+ import { useClickAway, useWindowScroll } from "@uidotdev/usehooks";
10
+ import cn from "classnames";
11
+ import React, { createContext, forwardRef, Fragment, SVGProps, useMemo, useState } from "react";
12
+ import { GoPerson } from "react-icons/go";
13
+ import { LiaSearchSolid } from "react-icons/lia";
14
+ import { SlLocationPin } from "react-icons/sl";
15
+ import { NavigationProps } from ".";
16
+ import { MegaNavContextProvider, useMegaNavContext } from "./context/megaNavContext";
17
+ import { getImageProperty, logoLink } from "./helper";
18
+ import { LabeledRouteWithKey, Logo, MegaMenu } from "./types";
19
+
20
+ // Accordion Types
21
+ interface AccordionProps {
22
+ className?: string;
23
+ children: React.ReactNode;
24
+ defaultValue?: string[];
25
+ onValueChange?: (value: string[]) => void;
26
+ }
27
+
28
+ interface AccordionItemProps {
29
+ value: string;
30
+ className?: string;
31
+ children: React.ReactNode;
32
+ }
33
+
34
+ interface AccordionTriggerProps {
35
+ className?: string;
36
+ children: React.ReactNode;
37
+ onClick?: () => void;
38
+ }
39
+
40
+ interface AccordionContentProps {
41
+ className?: string;
42
+ children: React.ReactNode;
43
+ }
44
+
45
+ // Accordion Context
46
+ interface AccordionContextType {
47
+ openItems: string[];
48
+ toggleItem: (value: string) => void;
49
+ }
50
+
51
+ const AccordionContext = createContext<AccordionContextType | undefined>(undefined);
52
+
53
+ const useAccordion = () => {
54
+ const context = React.useContext(AccordionContext);
55
+ if (!context) {
56
+ throw new Error("useAccordion must be used within an Accordion");
57
+ }
58
+ return context;
59
+ };
60
+
61
+ const Accordion = ({ className, children, defaultValue = [], onValueChange }: AccordionProps) => {
62
+ const [openItems, setOpenItems] = useState<string[]>(defaultValue);
63
+
64
+ const toggleItem = React.useCallback(
65
+ (value: string) => {
66
+ setOpenItems(prev => {
67
+ const newValue = prev.includes(value)
68
+ ? prev.filter(item => item !== value)
69
+ : [...prev, value];
70
+ onValueChange?.(newValue);
71
+ return newValue;
72
+ });
73
+ },
74
+ [onValueChange],
75
+ );
76
+
77
+ const value = React.useMemo(
78
+ () => ({
79
+ openItems,
80
+ toggleItem,
81
+ }),
82
+ [openItems, toggleItem],
83
+ );
84
+
85
+ return (
86
+ <AccordionContext.Provider value={value}>
87
+ <div className={cn("w-full", className)}>{children}</div>
88
+ </AccordionContext.Provider>
89
+ );
90
+ };
91
+
92
+ const AccordionItem = ({ value, className, children }: AccordionItemProps) => {
93
+ const { openItems, toggleItem } = useAccordion();
94
+ const isOpen = openItems.includes(value);
95
+
96
+ return (
97
+ <div className={cn("border-b border-gray-200", className)}>
98
+ {React.Children.map(children, child => {
99
+ if (!React.isValidElement(child)) return child;
100
+
101
+ return React.cloneElement(child as React.ReactElement<any>, {
102
+ isOpen,
103
+ onClick: () => toggleItem(value),
104
+ });
105
+ })}
106
+ </div>
107
+ );
108
+ };
109
+
110
+ const AccordionTrigger = React.forwardRef<
111
+ HTMLButtonElement,
112
+ AccordionTriggerProps & { isOpen?: boolean }
113
+ >(({ className, children, isOpen, onClick, ...props }, ref) => {
114
+ return (
115
+ <button
116
+ ref={ref}
117
+ type="button"
118
+ onClick={onClick}
119
+ className={cn("flex w-full items-center justify-between py-4 text-left", className)}
120
+ {...props}>
121
+ {children}
122
+ <svg
123
+ className={cn(
124
+ "h-5 w-5 transform transition-transform duration-200",
125
+ isOpen ? "rotate-180" : "",
126
+ )}
127
+ fill="none"
128
+ viewBox="0 0 24 24"
129
+ stroke="currentColor">
130
+ <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M19 9l-7 7-7-7" />
131
+ </svg>
132
+ </button>
133
+ );
134
+ });
135
+
136
+ const AccordionContent = React.forwardRef<
137
+ HTMLDivElement,
138
+ AccordionContentProps & { isOpen?: boolean }
139
+ >(({ className, children, isOpen }, ref) => {
140
+ return (
141
+ <div
142
+ ref={ref}
143
+ className={cn(
144
+ "overflow-hidden transition-all duration-200 ease-in-out",
145
+ isOpen ? "max-h-[1000px] opacity-100" : "max-h-0 opacity-0",
146
+ className,
147
+ )}>
148
+ <div className="pb-4">{children}</div>
149
+ </div>
150
+ );
151
+ });
152
+
153
+ interface MobileMenuContentProps {
154
+ data?: MegaMenu[];
155
+ }
156
+
157
+ const MobileMenuContent = ({ data }: MobileMenuContentProps) => {
158
+ const { showMobileMenu, setShowMobileMenu } = useMegaNavContext();
159
+ const ref = useClickAway<HTMLDivElement>(() => {
160
+ if (showMobileMenu) {
161
+ setShowMobileMenu(false);
162
+ }
163
+ });
164
+
165
+ if (!showMobileMenu) return null;
166
+
167
+ return (
168
+ <div
169
+ ref={ref}
170
+ className="fixed w-[75%] h-screen top-0 right-0 bg-white md:hidden z-50 py-10 px-5 overflow-y-auto">
171
+ <Accordion>
172
+ {data?.map(item => <MobileMenuContentItem key={item._key} megaMenu={item} />)}
173
+ </Accordion>
174
+ </div>
175
+ );
176
+ };
177
+
178
+ interface MobileMenuContentItemProps {
179
+ megaMenu: MegaMenu;
180
+ }
181
+
182
+ const MobileMenuContentItem = React.memo(({ megaMenu }: MobileMenuContentItemProps) => {
183
+ if (megaMenu._type === "link") {
184
+ return (
185
+ <Link
186
+ href={megaMenu.linkExternal || "#"}
187
+ target={megaMenu.linkTarget}
188
+ className="block py-4 text-base font-medium text-gray-900 hover:text-gray-700 uppercase">
189
+ {megaMenu.label}
190
+ </Link>
191
+ );
192
+ }
193
+
194
+ return (
195
+ <AccordionItem value={megaMenu._key}>
196
+ <AccordionTrigger className="text-base font-medium text-gray-900 uppercase w-full py-4">
197
+ {megaMenu.title}
198
+ </AccordionTrigger>
199
+ <AccordionContent>
200
+ {megaMenu.groupOfLinks?.map(group => (
201
+ <div key={group._key} className="mt-4 pl-4">
202
+ <Text className="text-black font-medium leading-[30px]">{group.title}</Text>
203
+ <Flex
204
+ direction="col"
205
+ align="start"
206
+ justify="start"
207
+ gap={1}
208
+ className="relative w-full pl-4">
209
+ {group.links?.[0]?.links?.map(link => (
210
+ <Button
211
+ key={`MobileMenuContent-Item-Group-Link-${link._key}`}
212
+ ariaLabel={link.label ?? ""}
213
+ as="link"
214
+ link={link ?? {}}
215
+ variant="unstyled"
216
+ className="text-black text-sm font-normal font-heading-kb leading-[30px] hover:underline">
217
+ {link.label}
218
+ </Button>
219
+ ))}
220
+ </Flex>
221
+ </div>
222
+ ))}
223
+
224
+ {megaMenu.showcaseLink?.map((link, i) => (
225
+ <div key={`MobileMenuContent-Item-Images-${link._key}-${i}`} className="mt-4 pl-4">
226
+ <Button
227
+ ariaLabel={link.primaryButton?.label ?? ""}
228
+ as="link"
229
+ link={link.primaryButton ?? {}}
230
+ variant="unstyled"
231
+ className="text-black text-sm font-normal font-heading-kb leading-[30px]">
232
+ <Flex direction="col" gap={3}>
233
+ <Image
234
+ key={i}
235
+ src={link.mainImage?.image}
236
+ alt={link.mainImage?.alt ?? ""}
237
+ width={200}
238
+ height={150}
239
+ className="w-[188px] h-[147px] object-cover object-center"
240
+ />
241
+ {link.primaryButton?.label}
242
+ </Flex>
243
+ </Button>
244
+ </div>
245
+ ))}
246
+ </AccordionContent>
247
+ </AccordionItem>
248
+ );
249
+ });
250
+
251
+ MobileMenuContentItem.displayName = "MobileMenuContentItem";
252
+
253
+ export default function Navigation_H({ logo, iconLinks, megaMenu }: NavigationProps) {
254
+ const [{ y }] = useWindowScroll();
255
+ const sticky =
256
+ y && y > 80
257
+ ? "fixed w-full transition-all duration-300 ease-in-out"
258
+ : "sticky transition-all duration-300 ease-in-out";
259
+
260
+ return (
261
+ <MegaNavContextProvider>
262
+ <header
263
+ className={cn(
264
+ "relative top-0 left-0 border-t md:pb-3 z-50 bg-white transition-all ease-in-out duration-300",
265
+ sticky,
266
+ )}>
267
+ <NavContainer logo={logo} iconLinks={iconLinks} megaMenu={megaMenu} />
268
+ </header>
269
+ <MobileMenuContent data={megaMenu} />
270
+ </MegaNavContextProvider>
271
+ );
272
+ }
273
+
274
+ interface NavContainerProps {
275
+ logo?: Logo;
276
+ iconLinks?: LabeledRouteWithKey[];
277
+ megaMenu?: MegaMenu[];
278
+ }
279
+
280
+ const NavContainer = ({ logo, iconLinks, megaMenu }: NavContainerProps) => {
281
+ const { setShowMobileMenu } = useMegaNavContext();
282
+ const [{ x: _, y }] = useWindowScroll();
283
+ const hideLogo = y && y > 80 ? "md:hidden" : "";
284
+
285
+ return (
286
+ <div className="px-0 w-full h-full transition-all duration-300 ease-in-out overflow-y-auto">
287
+ <Grid
288
+ columns={2}
289
+ align="center"
290
+ justify="between"
291
+ gap={5}
292
+ className={cn(
293
+ "lg:pt-4 py-2 grid-cols-2 md:grid-cols-3 w-full h-full transition-all ease-in-out duration-300 px-4",
294
+ hideLogo,
295
+ )}>
296
+ {logo?.image && (
297
+ <div className="relative w-20 flex items-center h-20 md:w-fit md:h-full place-self-start md:place-self-center col-start-1 md:col-start-2">
298
+ <Link
299
+ aria-label={`Go to ${logoLink(logo) === "/" ? "home page" : logoLink(logo)}`}
300
+ className="text-3xl font-bold leading-none"
301
+ href={logoLink(logo)}
302
+ target={logo?.linkTarget}
303
+ rel={logo?.linkTarget === "_blank" ? "noopener noreferrer" : ""}>
304
+ <Image
305
+ src={logo?.image}
306
+ width={135}
307
+ height={135}
308
+ className="object-cover transition-all ease-in-out duration-300"
309
+ alt={logo?.alt ?? "navigation-logo"}
310
+ />
311
+ </Link>
312
+ </div>
313
+ )}
314
+ <button
315
+ onClick={() => setShowMobileMenu(true)}
316
+ className="md:hidden h-fit self-center place-self-end">
317
+ <MdiLightMenu className="w-8 h-8" />
318
+ </button>
319
+ {iconLinks && iconLinks.length > 0 && (
320
+ <Flex
321
+ align="center"
322
+ gap={5}
323
+ className="hidden md:flex place-self-center max-w-[144px] h-32 w-full">
324
+ <ul className="flex gap-5">
325
+ {iconLinks?.map(link =>
326
+ link && link.label ? <NavItem key={link._key} link={link} isIcon={true} /> : null,
327
+ )}
328
+ </ul>
329
+ </Flex>
330
+ )}
331
+ </Grid>
332
+ <MegaMenuNavLinks data={megaMenu ?? []} />
333
+ <MegaMenuDropdownContents data={megaMenu ?? []} />
334
+ </div>
335
+ );
336
+ };
337
+
338
+ interface NavItemProps {
339
+ link: LabeledRouteWithKey;
340
+ isIcon: boolean;
341
+ }
342
+
343
+ const NavItem = ({ link, isIcon }: NavItemProps) => {
344
+ const icon = navItemIcons[link?.label as keyof typeof navItemIcons] || null;
345
+
346
+ return (
347
+ <li>
348
+ <Button
349
+ as="link"
350
+ ariaLabel={link?.label}
351
+ link={link}
352
+ className="text-sm font-label tracking-wide">
353
+ {!isIcon ? link?.label : icon}
354
+ </Button>
355
+ </li>
356
+ );
357
+ };
358
+
359
+ const navItemIcons = {
360
+ search: <LiaSearchSolid className="w-4 h-4" />,
361
+ location: <SlLocationPin className="w-4 h-4" />,
362
+ person: <GoPerson className="w-4 h-4" />,
363
+ };
364
+
365
+ interface MegaMenuNavLinksProps {
366
+ data: MegaMenu[];
367
+ }
368
+
369
+ const MegaMenuNavLinks = ({ data }: MegaMenuNavLinksProps) => {
370
+ const { currentDropdown, setCurrentDropdown } = useMegaNavContext();
371
+ const [{ x: _, y }] = useWindowScroll();
372
+ const hide = (y && y < 80) || y === 0 ? "hidden" : "";
373
+
374
+ return (
375
+ <Flex
376
+ align="center"
377
+ justify="between"
378
+ gap={5}
379
+ className="relative w-full h-full max-w-7xl mx-auto hidden md:flex pt-4 px-4 transition-all duration-300 ease-in-out">
380
+ {data && data.length > 0
381
+ ? data
382
+ ?.slice(0, 3)
383
+ .map(megaMenuItem => (
384
+ <Fragment key={`MegaMenuNavLink-${megaMenuItem._key}`}>
385
+ {megaMenuItem._type === "dropdown" ? (
386
+ <MegaMenuDropdownTrigger
387
+ key={`MegaMenuDropdownTrigger-${megaMenuItem._key}`}
388
+ dropdown={megaMenuItem}
389
+ aria-expanded={currentDropdown === megaMenuItem.title}
390
+ onMouseEnter={() => setCurrentDropdown(megaMenuItem.title ?? "")}
391
+ onMouseLeave={() => setCurrentDropdown("")}
392
+ />
393
+ ) : (
394
+ <MegaMenuNavLink key={`MegaMenuLink-${megaMenuItem._key}`} link={megaMenuItem} />
395
+ )}
396
+ </Fragment>
397
+ ))
398
+ : null}
399
+ {data && data.length > 0
400
+ ? data
401
+ ?.slice(3, 6)
402
+ .map(megaMenuItem => (
403
+ <Fragment key={`MegaMenuNavLink-${megaMenuItem._key}`}>
404
+ {megaMenuItem._type === "dropdown" ? (
405
+ <MegaMenuDropdownTrigger
406
+ key={`MegaMenuDropdownTrigger-${megaMenuItem._key}`}
407
+ dropdown={megaMenuItem}
408
+ aria-expanded={currentDropdown === megaMenuItem.title}
409
+ onMouseEnter={() => setCurrentDropdown(megaMenuItem.title ?? "")}
410
+ onMouseLeave={() => setCurrentDropdown("")}
411
+ />
412
+ ) : (
413
+ <MegaMenuNavLink key={`MegaMenuLink-${megaMenuItem._key}`} link={megaMenuItem} />
414
+ )}
415
+ </Fragment>
416
+ ))
417
+ : null}
418
+ </Flex>
419
+ );
420
+ };
421
+
422
+ interface MegaMenuNavLinkProps {
423
+ link: MegaMenu;
424
+ className?: string;
425
+ }
426
+
427
+ const MegaMenuNavLink = ({ link, className }: MegaMenuNavLinkProps) => {
428
+ return (
429
+ <Button
430
+ ariaLabel={`Go to ${link.label}`}
431
+ as="link"
432
+ variant="unstyled"
433
+ link={link}
434
+ className={cn(
435
+ "relative text-black text-sm font-normal font-label uppercase tracking-widest group",
436
+ className,
437
+ )}>
438
+ {link.label}
439
+ </Button>
440
+ );
441
+ };
442
+
443
+ interface MegaMenuDropdownTriggerProps {
444
+ dropdown: MegaMenu;
445
+ onClick?: () => void;
446
+ onMouseEnter?: () => void;
447
+ onMouseLeave?: () => void;
448
+ className?: string;
449
+ "aria-expanded"?: boolean;
450
+ }
451
+
452
+ const MegaMenuDropdownTrigger = forwardRef<HTMLButtonElement, MegaMenuDropdownTriggerProps>(
453
+ (props, ref) => {
454
+ const { dropdown, onClick, onMouseEnter, onMouseLeave, className, ...restProps } = props;
455
+
456
+ return dropdown.linkExternal ? (
457
+ <Link
458
+ href={dropdown.linkExternal}
459
+ onClick={onClick}
460
+ onMouseEnter={onMouseEnter}
461
+ onMouseLeave={onMouseLeave}
462
+ aria-label={`Open the ${dropdown.title} menu`}
463
+ className={cn(
464
+ "relative text-black text-sm font-normal font-label uppercase tracking-widest group",
465
+ className,
466
+ )}
467
+ {...restProps}>
468
+ {dropdown.title}
469
+ </Link>
470
+ ) : (
471
+ <button
472
+ ref={ref}
473
+ onClick={onClick}
474
+ onMouseEnter={onMouseEnter}
475
+ onMouseLeave={onMouseLeave}
476
+ aria-label={`Open the ${dropdown.title} menu`}
477
+ className={cn(
478
+ "relative text-black text-sm font-normal font-label uppercase tracking-widest group",
479
+ className,
480
+ )}
481
+ {...restProps}>
482
+ {dropdown.title}
483
+ </button>
484
+ );
485
+ },
486
+ );
487
+
488
+ interface MegaMenuDropdownContentsProps {
489
+ data: MegaMenu[];
490
+ }
491
+
492
+ const MegaMenuDropdownContents = ({ data }: MegaMenuDropdownContentsProps) => {
493
+ const { currentDropdown } = useMegaNavContext();
494
+
495
+ return (
496
+ <>
497
+ {data && data.length > 0
498
+ ? data?.map(megaMenuDropdown => {
499
+ const show =
500
+ currentDropdown === megaMenuDropdown.title && megaMenuDropdown.title !== "";
501
+ return (
502
+ <MegaDropdownContent
503
+ key={`MegaMenuDropdown-${megaMenuDropdown._key}`}
504
+ label={megaMenuDropdown.title ?? ""}
505
+ links={megaMenuDropdown.links ?? []}
506
+ showcaseLink={megaMenuDropdown.showcaseLink ?? []}
507
+ groupedLinks={megaMenuDropdown.groupOfLinks ?? []}
508
+ />
509
+ );
510
+ })
511
+ : null}
512
+ </>
513
+ );
514
+ };
515
+
516
+ interface MegaDropdownContentProps {
517
+ label: string;
518
+ links: any[];
519
+ showcaseLink: any[];
520
+ groupedLinks: any[];
521
+ }
522
+
523
+ function MegaDropdownContent({
524
+ label,
525
+ links,
526
+ showcaseLink,
527
+ groupedLinks,
528
+ }: MegaDropdownContentProps) {
529
+ const { currentDropdown, setCurrentDropdown } = useMegaNavContext();
530
+ const show = currentDropdown === label && label !== "";
531
+
532
+ const isGroupLinks = groupedLinks.length > 0 && links.length === 0;
533
+ const hasShowcaseLinks = showcaseLink.length > 0;
534
+
535
+ const groupedLinksGridColumns = useMemo(() => {
536
+ if (groupedLinks.length > 0) {
537
+ return groupedLinks
538
+ .map(group => {
539
+ return group.links.length > 2 ? "3fr" : "1fr";
540
+ })
541
+ .join(" ");
542
+ } else {
543
+ return "1fr";
544
+ }
545
+ }, [groupedLinks]);
546
+
547
+ const normalLinksGridColumns = links.length > 0 ? `repeat(${links.length}, 1fr)` : "1fr";
548
+ const gridColumns =
549
+ links.length > 0 || groupedLinks.length > 0
550
+ ? `${isGroupLinks ? groupedLinksGridColumns : normalLinksGridColumns} ${
551
+ hasShowcaseLinks ? "2fr" : ""
552
+ }`
553
+ : "1fr";
554
+
555
+ return (
556
+ <Section
557
+ data-show={show}
558
+ onMouseEnter={() => setCurrentDropdown(label)}
559
+ onMouseLeave={() => setCurrentDropdown("")}
560
+ className={`relative top-6 left-0 w-full overflow-hidden z-50 bg-primary/5 !transition-[max-height] !duration-300 !ease-in-out ${
561
+ show ? "max-h-[500px]" : "max-h-0"
562
+ }`}>
563
+ <div
564
+ style={{
565
+ display: "grid",
566
+ gridTemplateColumns: gridColumns,
567
+ gridTemplateRows: "1fr",
568
+ }}
569
+ className="relative w-full h-auto max-w-[90rem] mx-auto">
570
+ <MegaDropDownLinks links={links} />
571
+ <MegaDropdownGroupedLinks groupedLinks={groupedLinks} />
572
+ <MegaDropdownShowcaseLinks
573
+ hasShowcaseLinks={hasShowcaseLinks}
574
+ showcaseLink={showcaseLink}
575
+ />
576
+ </div>
577
+ </Section>
578
+ );
579
+ }
580
+
581
+ function MegaDropDownLinks({ links }: { links: LabeledRouteWithKey[] }) {
582
+ return (
583
+ <Fragment>
584
+ {links &&
585
+ links.length > 0 &&
586
+ links?.map((item: any, index: number) => {
587
+ return (
588
+ <div
589
+ key={`MegaDropdownContent-Item-${item._key}-${index}`}
590
+ className="relative pt-10 pl-5 flex flex-col items-end justify-start w-full h-full border-r border-black last:border-r-0">
591
+ {item.primaryButton?.label ? (
592
+ <Button
593
+ as="link"
594
+ ariaLabel={item.primaryButton?.label}
595
+ link={item.primaryButton}
596
+ className="text-sm text-black font-normal uppercase tracking-widest font-label self-start mb-4 border-b border-transparent hover:border-black">
597
+ {item.primaryButton?.label}
598
+ </Button>
599
+ ) : (
600
+ <Heading
601
+ fontSize="sm"
602
+ className="text-black font-normal uppercase tracking-widest font-label self-start pb-4">
603
+ {item.title}
604
+ </Heading>
605
+ )}
606
+ <Flex direction="col" align="start" justify="start" gap={2} className="w-full h-full">
607
+ {item.links?.map((link: any, i: number) => {
608
+ return (
609
+ <Button
610
+ key={`MegaDropdownContent-Item-Link-${item._key}-${i}`}
611
+ ariaLabel={link.label ?? ""}
612
+ as="link"
613
+ link={link ?? {}}
614
+ variant="unstyled"
615
+ className="text-black text-sm font-normal font-heading-kb leading-[30px] hover:underline">
616
+ {link?.label}
617
+ </Button>
618
+ );
619
+ })}
620
+ </Flex>
621
+ </div>
622
+ );
623
+ })}
624
+ </Fragment>
625
+ );
626
+ }
627
+
628
+ function MegaDropdownGroupedLinks({ groupedLinks }: { groupedLinks: LabeledRouteWithKey[] }) {
629
+ return (
630
+ <Fragment>
631
+ {groupedLinks &&
632
+ groupedLinks.length > 0 &&
633
+ groupedLinks?.map((groupedLink: any, i: number) => {
634
+ return (
635
+ <div
636
+ key={`MegaDropdownContent-Item-${groupedLink._key}-${i}`}
637
+ className="relative py-10 pl-5 flex flex-col items-end justify-start h-full w-full border-r border-black last:border-r-0">
638
+ <Heading
639
+ fontSize="sm"
640
+ className="text-black font-normal uppercase tracking-widest font-label self-start pb-4">
641
+ {groupedLink.title}
642
+ </Heading>
643
+ <Flex
644
+ direction="row"
645
+ align="start"
646
+ justify="start"
647
+ gap={4}
648
+ className="relative w-full h-full grid-flow-row">
649
+ {groupedLink.links?.map((link: any, i: number) => {
650
+ return (
651
+ <Flex
652
+ key={`MegaDropdownContent-Item-Link-${link._key}-${i}`}
653
+ direction="col"
654
+ className="h-fit w-fit">
655
+ <Button
656
+ ariaLabel={link.title ?? ""}
657
+ as="link"
658
+ link={link?.primaryButton ?? {}}
659
+ variant="unstyled"
660
+ className="text-black text-sm font-normal font-heading-kb leading-[30px] underline uppercase underline-offset-2">
661
+ {link?.title}
662
+ </Button>
663
+ <Flex
664
+ direction="col"
665
+ align="start"
666
+ justify="start"
667
+ gap={2}
668
+ className="w-fit h-full">
669
+ {link.links?.map((link: any, i: number) => {
670
+ return (
671
+ <Button
672
+ key={`MegaDropdownContent-Item-Link-${link._key}-${i}`}
673
+ ariaLabel={link.label ?? ""}
674
+ as="link"
675
+ link={link ?? {}}
676
+ variant="unstyled"
677
+ className="text-black text-sm font-normal font-heading-kb leading-[30px] hover:underline">
678
+ {link?.label}
679
+ </Button>
680
+ );
681
+ })}
682
+ </Flex>
683
+ </Flex>
684
+ );
685
+ })}
686
+ </Flex>
687
+ </div>
688
+ );
689
+ })}
690
+ </Fragment>
691
+ );
692
+ }
693
+
694
+ function MegaDropdownShowcaseLinks({
695
+ hasShowcaseLinks,
696
+ showcaseLink,
697
+ }: {
698
+ hasShowcaseLinks: boolean;
699
+ showcaseLink: LabeledRouteWithKey[];
700
+ }) {
701
+ if (!hasShowcaseLinks) return null;
702
+
703
+ return (
704
+ <Flex direction="row" align="start" justify="start" className="w-full h-full gap-6 pl-5 py-10">
705
+ {showcaseLink?.map((link: any, i: number) => {
706
+ const imageUrl = link.mainImage?.image;
707
+ const imageProperty = getImageProperty(link.mainImage?.image.asset);
708
+
709
+ return (
710
+ <Button
711
+ key={`MegaDropdownContent-Item-Images-${link._key}-${i}`}
712
+ ariaLabel={link.primaryButton?.label ?? ""}
713
+ as="link"
714
+ link={link.primaryButton ?? {}}
715
+ variant="unstyled"
716
+ className="text-center text-black text-sm font-normal font-heading-kb leading-[30px] hover:underline">
717
+ <Flex direction="col" align="center" justify="center" gap={3}>
718
+ <Image
719
+ key={i}
720
+ src={imageUrl}
721
+ alt={link.mainImage?.alt ?? ""}
722
+ width={imageProperty?.width ?? 0}
723
+ height={imageProperty?.height ?? 0}
724
+ className="w-[188px] h-[147px] object-cover object-center"></Image>
725
+ {link.primaryButton?.label}
726
+ </Flex>
727
+ </Button>
728
+ );
729
+ })}
730
+ </Flex>
731
+ );
732
+ }
733
+
734
+ function MdiLightMenu(props: SVGProps<SVGSVGElement>) {
735
+ return (
736
+ <svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24" {...props}>
737
+ <path fill="currentColor" d="M3 8V7h17v1zm17 4v1H3v-1zM3 17h17v1H3z"></path>
738
+ </svg>
739
+ );
740
+ }
741
+
742
+ export { Navigation_H };