@dnanpm/ui-components 0.6.0 → 0.7.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 (122) hide show
  1. package/dist/components/AccordionItem/AccordionItem.css +16 -16
  2. package/dist/components/AccordionItem/AccordionItem.module.css.cjs +11 -11
  3. package/dist/components/AccordionItem/AccordionItem.module.css.js +11 -11
  4. package/dist/components/Footer/Footer.cjs +272 -0
  5. package/dist/components/Footer/Footer.cjs.map +1 -0
  6. package/dist/components/Footer/Footer.css +466 -0
  7. package/dist/components/Footer/Footer.d.ts +3 -0
  8. package/dist/components/Footer/Footer.d.ts.map +1 -0
  9. package/dist/components/Footer/Footer.js +272 -0
  10. package/dist/components/Footer/Footer.js.map +1 -0
  11. package/dist/components/Footer/Footer.module.css.cjs +80 -0
  12. package/dist/components/Footer/Footer.module.css.cjs.map +1 -0
  13. package/dist/components/Footer/Footer.module.css.js +80 -0
  14. package/dist/components/Footer/Footer.module.css.js.map +1 -0
  15. package/dist/components/Footer/Footer.types.d.ts +128 -0
  16. package/dist/components/Footer/Footer.types.d.ts.map +1 -0
  17. package/dist/components/Footer/Footer.utils.cjs +41 -0
  18. package/dist/components/Footer/Footer.utils.cjs.map +1 -0
  19. package/dist/components/Footer/Footer.utils.d.ts +13 -0
  20. package/dist/components/Footer/Footer.utils.d.ts.map +1 -0
  21. package/dist/components/Footer/Footer.utils.js +41 -0
  22. package/dist/components/Footer/Footer.utils.js.map +1 -0
  23. package/dist/components/Footer/assets/app-store-badge.svg.cjs +4 -0
  24. package/dist/components/Footer/assets/app-store-badge.svg.cjs.map +1 -0
  25. package/dist/components/Footer/assets/app-store-badge.svg.js +5 -0
  26. package/dist/components/Footer/assets/app-store-badge.svg.js.map +1 -0
  27. package/dist/components/Footer/assets/google-play-badge.svg.cjs +4 -0
  28. package/dist/components/Footer/assets/google-play-badge.svg.cjs.map +1 -0
  29. package/dist/components/Footer/assets/google-play-badge.svg.js +5 -0
  30. package/dist/components/Footer/assets/google-play-badge.svg.js.map +1 -0
  31. package/dist/components/Footer/index.d.ts +3 -0
  32. package/dist/components/Footer/index.d.ts.map +1 -0
  33. package/dist/components/Hero/Hero.cjs +44 -30
  34. package/dist/components/Hero/Hero.cjs.map +1 -1
  35. package/dist/components/Hero/Hero.css +89 -100
  36. package/dist/components/Hero/Hero.d.ts +1 -1
  37. package/dist/components/Hero/Hero.d.ts.map +1 -1
  38. package/dist/components/Hero/Hero.js +45 -31
  39. package/dist/components/Hero/Hero.js.map +1 -1
  40. package/dist/components/Hero/Hero.module.css.cjs +17 -20
  41. package/dist/components/Hero/Hero.module.css.cjs.map +1 -1
  42. package/dist/components/Hero/Hero.module.css.js +17 -20
  43. package/dist/components/Hero/Hero.module.css.js.map +1 -1
  44. package/dist/components/Hero/Hero.types.d.ts +8 -3
  45. package/dist/components/Hero/Hero.types.d.ts.map +1 -1
  46. package/dist/components/Hero/Hero.utils.cjs +5 -8
  47. package/dist/components/Hero/Hero.utils.cjs.map +1 -1
  48. package/dist/components/Hero/Hero.utils.d.ts +2 -2
  49. package/dist/components/Hero/Hero.utils.d.ts.map +1 -1
  50. package/dist/components/Hero/Hero.utils.js +5 -8
  51. package/dist/components/Hero/Hero.utils.js.map +1 -1
  52. package/dist/components/MainNavigation/MainNavigation.cjs +1110 -0
  53. package/dist/components/MainNavigation/MainNavigation.cjs.map +1 -0
  54. package/dist/components/MainNavigation/MainNavigation.css +946 -0
  55. package/dist/components/MainNavigation/MainNavigation.d.ts +3 -0
  56. package/dist/components/MainNavigation/MainNavigation.d.ts.map +1 -0
  57. package/dist/components/MainNavigation/MainNavigation.js +1110 -0
  58. package/dist/components/MainNavigation/MainNavigation.js.map +1 -0
  59. package/dist/components/MainNavigation/MainNavigation.module.css.cjs +74 -0
  60. package/dist/components/MainNavigation/MainNavigation.module.css.cjs.map +1 -0
  61. package/dist/components/MainNavigation/MainNavigation.module.css.js +75 -0
  62. package/dist/components/MainNavigation/MainNavigation.module.css.js.map +1 -0
  63. package/dist/components/MainNavigation/MainNavigation.types.d.ts +149 -0
  64. package/dist/components/MainNavigation/MainNavigation.types.d.ts.map +1 -0
  65. package/dist/components/MainNavigation/MainNavigation.utils.cjs +168 -0
  66. package/dist/components/MainNavigation/MainNavigation.utils.cjs.map +1 -0
  67. package/dist/components/MainNavigation/MainNavigation.utils.d.ts +29 -0
  68. package/dist/components/MainNavigation/MainNavigation.utils.d.ts.map +1 -0
  69. package/dist/components/MainNavigation/MainNavigation.utils.js +168 -0
  70. package/dist/components/MainNavigation/MainNavigation.utils.js.map +1 -0
  71. package/dist/components/MainNavigation/index.d.ts +3 -0
  72. package/dist/components/MainNavigation/index.d.ts.map +1 -0
  73. package/dist/components/Pictograph/Pictograph.css +69 -57
  74. package/dist/components/Pictograph/Pictograph.module.css.cjs +11 -11
  75. package/dist/components/Pictograph/Pictograph.module.css.js +11 -11
  76. package/dist/components/Pictograph/Pictograph.types.d.ts +2 -2
  77. package/dist/components/Pictograph/PictographItem.cjs +15 -4
  78. package/dist/components/Pictograph/PictographItem.cjs.map +1 -1
  79. package/dist/components/Pictograph/PictographItem.css +26 -23
  80. package/dist/components/Pictograph/PictographItem.d.ts.map +1 -1
  81. package/dist/components/Pictograph/PictographItem.js +15 -4
  82. package/dist/components/Pictograph/PictographItem.js.map +1 -1
  83. package/dist/components/Pictograph/PictographItem.module.css.cjs +3 -3
  84. package/dist/components/Pictograph/PictographItem.module.css.js +3 -3
  85. package/dist/components/Quote/Quote.cjs +32 -0
  86. package/dist/components/Quote/Quote.cjs.map +1 -0
  87. package/dist/components/Quote/Quote.css +95 -0
  88. package/dist/components/Quote/Quote.d.ts +3 -0
  89. package/dist/components/Quote/Quote.d.ts.map +1 -0
  90. package/dist/components/Quote/Quote.js +32 -0
  91. package/dist/components/Quote/Quote.js.map +1 -0
  92. package/dist/components/Quote/Quote.module.css.cjs +22 -0
  93. package/dist/components/Quote/Quote.module.css.cjs.map +1 -0
  94. package/dist/components/Quote/Quote.module.css.js +22 -0
  95. package/dist/components/Quote/Quote.module.css.js.map +1 -0
  96. package/dist/components/Quote/Quote.types.d.ts +12 -0
  97. package/dist/components/Quote/Quote.types.d.ts.map +1 -0
  98. package/dist/components/Quote/index.d.ts +3 -0
  99. package/dist/components/Quote/index.d.ts.map +1 -0
  100. package/dist/index.cjs +6 -0
  101. package/dist/index.cjs.map +1 -1
  102. package/dist/index.d.ts +6 -0
  103. package/dist/index.d.ts.map +1 -1
  104. package/dist/index.js +6 -0
  105. package/dist/index.js.map +1 -1
  106. package/dist/styles/utils/focus.css +22 -13
  107. package/dist/styles/utils/focus.module.css.cjs +6 -3
  108. package/dist/styles/utils/focus.module.css.cjs.map +1 -1
  109. package/dist/styles/utils/focus.module.css.js +7 -4
  110. package/dist/styles/utils/focus.module.css.js.map +1 -1
  111. package/dist/styles/utils/overlay.css +37 -0
  112. package/dist/styles/utils/overlay.module.css.cjs +13 -0
  113. package/dist/styles/utils/overlay.module.css.cjs.map +1 -0
  114. package/dist/styles/utils/overlay.module.css.js +13 -0
  115. package/dist/styles/utils/overlay.module.css.js.map +1 -0
  116. package/dist/styles/utils/text-decoration.css +8 -1
  117. package/dist/styles/utils/text-decoration.module.css.cjs +5 -2
  118. package/dist/styles/utils/text-decoration.module.css.cjs.map +1 -1
  119. package/dist/styles/utils/text-decoration.module.css.js +6 -3
  120. package/dist/styles/utils/text-decoration.module.css.js.map +1 -1
  121. package/dist/styles.css +24 -7
  122. package/package.json +2 -1
@@ -0,0 +1,1110 @@
1
+ import { jsxs, jsx, Fragment as Fragment$1 } from "react/jsx-runtime";
2
+ import { useState, useRef, useCallback, useEffect, Fragment } from "react";
3
+ import { Globe, Search, Cart, Close, Menu, ChevronRight, Open, ArrowRight } from "@dnanpm/icons";
4
+ import focusStyles from "../../styles/utils/focus.module.css.js";
5
+ import overlayStyles from "../../styles/utils/overlay.module.css.js";
6
+ import elevationStyles from "../../styles/utils/elevation.module.css.js";
7
+ import textDecorationStyles from "../../styles/utils/text-decoration.module.css.js";
8
+ import styles from "./MainNavigation.module.css.js";
9
+ import { assignRef, isMobileViewportByEnvironment, isMobileIosDeviceByEnvironment, isDesktopViewportByEnvironment, getLinkTarget, getLinkRel, toNavigableHref, isExternalLink, isItemInCurrentPath, isExternalTarget, isLinkInCurrentPage } from "./MainNavigation.utils.js";
10
+ import { cn } from "../../utils/cn/cn.js";
11
+ import { Button } from "../Button/Button.js";
12
+ import { IconButton } from "../IconButton/IconButton.js";
13
+ const defaultOrganizations = [];
14
+ const defaultItems = [];
15
+ const defaultLogoSvg = '<svg width="40" height="40" viewBox="0 0 40 40" fill="none" xmlns="http://www.w3.org/2000/svg"><g clip-path="url(#clip0_6509_143)"><g clip-path="url(#clip1_6509_143)"><rect width="40" height="40" fill="white"/><path fill-rule="evenodd" clip-rule="evenodd" d="M-0.0314789 40V0H40.0019V40H-0.0314789ZM9.33519 27.05C11.6685 27.05 13.5685 25.15 13.5685 22.7667V17.1667C13.5685 14.7833 11.6685 12.8833 9.33519 12.8833H5.10186V27.05H9.33519ZM21.6352 27.05H24.1685V17.1167C24.1685 14.7833 22.2685 12.8833 19.9352 12.8833H15.7019V27.05H18.1852V15.4167H19.9352C20.9019 15.4167 21.6352 16.15 21.6352 17.1167V27.05ZM32.4019 27.05H34.9352V17.05C34.9352 14.7167 33.0352 12.8167 30.7019 12.8167H30.6519C28.3185 12.8167 26.4185 14.7167 26.4185 17.05V27.0667H28.9519V22H32.4019V27.05ZM30.65 15.3333H30.7C31.6167 15.3333 32.4 16.1 32.4 17.0333V19.6167H28.95V17.0333C28.95 16.1167 29.6833 15.3333 30.65 15.3333ZM7.56667 15.4333H9.36667C10.3 15.4333 11.0833 16.15 11.0667 17.1333V22.8333C11.0667 23.75 10.3 24.5333 9.36667 24.5333H7.56667V15.4333Z" fill="#FF007D"/></g></g><defs><clipPath id="clip0_6509_143"><rect width="40" height="40" fill="white"/></clipPath><clipPath id="clip1_6509_143"><rect width="40" height="40" fill="white"/></clipPath></defs></svg>';
16
+ const defaultLogoSrc = `data:image/svg+xml,${encodeURIComponent(defaultLogoSvg)}`;
17
+ const mobilePanelAnimationDurationMs = 200;
18
+ const mobileBodyScrollLockClass = "dds-un-scrollable";
19
+ const defaultOverflowCategoryLabel = "Muut kategoriat";
20
+ const desktopMinWidthMediaQuery = "(min-width: 1024px)";
21
+ const defaultRenderLink = (props) => /* @__PURE__ */ jsx("a", { ...props });
22
+ const MainNavigation = ({
23
+ organizations = defaultOrganizations,
24
+ items = defaultItems,
25
+ loginHref = "#",
26
+ loginLabel = "Kirjaudu",
27
+ logoHref = "/",
28
+ languageSelectorLabel = "FI",
29
+ searchLabel = "Haku",
30
+ cartLabel = "Ostoskori",
31
+ showLanguageSelector = false,
32
+ showSearch = false,
33
+ showCart = false,
34
+ cartCounter,
35
+ cartCounterLabel = "tuotetta ostoskorissa",
36
+ onLanguageSelectorClick,
37
+ onSearchClick,
38
+ onCartClick,
39
+ mobileMenuOpenAriaLabel = "Avaa valikko",
40
+ mobileMenuCloseAriaLabel = "Sulje valikko",
41
+ organizationStripAriaLabel = "Sivustot",
42
+ logoAriaLabel = "Siirry etusivulle",
43
+ mobilePrimaryNavigationAriaLabel = "Päävalikko",
44
+ externalLinkAriaLabel = "avautuu uuteen välilehteen",
45
+ defaultMobileMenuOpen = false,
46
+ defaultOpenItemIndex = null,
47
+ currentPathname,
48
+ overflowCategoryLabel = defaultOverflowCategoryLabel,
49
+ onMobileMenuToggle,
50
+ onDesktopItemToggle,
51
+ renderLink = defaultRenderLink,
52
+ className,
53
+ "aria-label": ariaLabel = "Päänavigaatio",
54
+ ref,
55
+ ...props
56
+ }) => {
57
+ const [mobileMenuOpen, setMobileMenuOpen] = useState(defaultMobileMenuOpen);
58
+ const [isMobileMenuClosing, setIsMobileMenuClosing] = useState(false);
59
+ const [openTopLevelItemIndex, setOpenTopLevelItemIndex] = useState(
60
+ defaultOpenItemIndex
61
+ );
62
+ const [isDesktopHeaderOpen, setIsDesktopHeaderOpen] = useState(true);
63
+ const [mobileActiveCategoryIndex, setMobileActiveCategoryIndex] = useState(null);
64
+ const [isMobileSecondPanelClosing, setIsMobileSecondPanelClosing] = useState(false);
65
+ const [isMobileThirdPanelClosing, setIsMobileThirdPanelClosing] = useState(false);
66
+ const mobileSecondPanelCloseTimeoutRef = useRef(null);
67
+ const mobileThirdPanelCloseTimeoutRef = useRef(null);
68
+ const mobileMenuCloseResetTimeoutRef = useRef(null);
69
+ const focusMobileSecondPanelTimeoutRef = useRef(null);
70
+ const focusMobileThirdPanelTimeoutRef = useRef(null);
71
+ const focusReturnToMobileTopLevelItemTimeoutRef = useRef(
72
+ null
73
+ );
74
+ const resetMobileThirdPanelScrollTimeoutRef = useRef(
75
+ null
76
+ );
77
+ const headerElementRef = useRef(null);
78
+ const desktopPanelTriggerButtonRefs = useRef([]);
79
+ const mobilePrimaryNavRef = useRef(null);
80
+ const mobileMenuToggleButtonRef = useRef(null);
81
+ const mobileModalPanelRef = useRef(null);
82
+ const mobileThirdPanelRef = useRef(null);
83
+ const mobilePanelBackButtonRef = useRef(null);
84
+ const mobileThirdPanelBackButtonRef = useRef(null);
85
+ const mobileLevelTwoCategoryButtonRefs = useRef([]);
86
+ const focusMobilePanelBackOnOpenRef = useRef(false);
87
+ const focusMobileThirdPanelBackOnOpenRef = useRef(false);
88
+ const focusReturnToMobileCategoryTimeoutRef = useRef(
89
+ null
90
+ );
91
+ const setHeaderRef = useCallback(
92
+ (node) => {
93
+ headerElementRef.current = node;
94
+ assignRef(ref, node);
95
+ },
96
+ [ref]
97
+ );
98
+ useEffect(() => {
99
+ return () => {
100
+ if (mobileSecondPanelCloseTimeoutRef.current != null) {
101
+ clearTimeout(mobileSecondPanelCloseTimeoutRef.current);
102
+ }
103
+ if (mobileThirdPanelCloseTimeoutRef.current != null) {
104
+ clearTimeout(mobileThirdPanelCloseTimeoutRef.current);
105
+ }
106
+ if (focusMobileSecondPanelTimeoutRef.current != null) {
107
+ clearTimeout(focusMobileSecondPanelTimeoutRef.current);
108
+ }
109
+ if (focusMobileThirdPanelTimeoutRef.current != null) {
110
+ clearTimeout(focusMobileThirdPanelTimeoutRef.current);
111
+ }
112
+ clearTimeout(focusReturnToMobileTopLevelItemTimeoutRef.current ?? void 0);
113
+ if (resetMobileThirdPanelScrollTimeoutRef.current != null) {
114
+ clearTimeout(resetMobileThirdPanelScrollTimeoutRef.current);
115
+ }
116
+ if (mobileMenuCloseResetTimeoutRef.current != null) {
117
+ clearTimeout(mobileMenuCloseResetTimeoutRef.current);
118
+ }
119
+ if (focusReturnToMobileCategoryTimeoutRef.current != null) {
120
+ clearTimeout(focusReturnToMobileCategoryTimeoutRef.current);
121
+ }
122
+ };
123
+ }, []);
124
+ useEffect(() => {
125
+ if (typeof window === "undefined" || typeof window.matchMedia !== "function") {
126
+ return;
127
+ }
128
+ const headerElement = headerElementRef.current;
129
+ const desktopQuery = window.matchMedia(desktopMinWidthMediaQuery);
130
+ let previousScrollY = window.pageYOffset;
131
+ let headerHeight = parseFloat(window.getComputedStyle(headerElement).height.replace("px", "")) || headerElement.offsetHeight;
132
+ const openHeader = () => {
133
+ setIsDesktopHeaderOpen(true);
134
+ };
135
+ const closeHeader = () => {
136
+ setIsDesktopHeaderOpen(false);
137
+ };
138
+ const handleScroll = () => {
139
+ const currentScrollY = window.pageYOffset;
140
+ if (!desktopQuery.matches) {
141
+ openHeader();
142
+ previousScrollY = currentScrollY;
143
+ return;
144
+ }
145
+ if (mobileMenuOpen || openTopLevelItemIndex != null) {
146
+ openHeader();
147
+ previousScrollY = currentScrollY;
148
+ return;
149
+ }
150
+ if (currentScrollY <= headerHeight) {
151
+ openHeader();
152
+ } else if (currentScrollY > previousScrollY) {
153
+ closeHeader();
154
+ } else if (currentScrollY < previousScrollY) {
155
+ openHeader();
156
+ }
157
+ previousScrollY = currentScrollY;
158
+ };
159
+ const handleViewportChange = () => {
160
+ openHeader();
161
+ previousScrollY = window.pageYOffset;
162
+ headerHeight = parseFloat(window.getComputedStyle(headerElement).height.replace("px", "")) || headerElement.offsetHeight;
163
+ };
164
+ window.addEventListener("scroll", handleScroll, { passive: true });
165
+ window.addEventListener("resize", handleViewportChange);
166
+ desktopQuery.addEventListener("change", handleViewportChange);
167
+ handleScroll();
168
+ return () => {
169
+ window.removeEventListener("scroll", handleScroll);
170
+ window.removeEventListener("resize", handleViewportChange);
171
+ desktopQuery.removeEventListener("change", handleViewportChange);
172
+ };
173
+ }, [mobileMenuOpen, openTopLevelItemIndex]);
174
+ useEffect(() => {
175
+ const browserWindow = globalThis.window;
176
+ const browserDocument = globalThis.document;
177
+ if (!mobileMenuOpen || browserWindow == null || browserDocument == null) {
178
+ return;
179
+ }
180
+ const isMobileViewport = isMobileViewportByEnvironment(browserWindow);
181
+ if (!isMobileViewport) {
182
+ return;
183
+ }
184
+ const body = browserDocument.body;
185
+ if (isMobileIosDeviceByEnvironment(browserWindow, globalThis.navigator)) {
186
+ const scrollY = browserWindow.pageYOffset;
187
+ body.style.position = "fixed";
188
+ body.style.top = `-${scrollY}px`;
189
+ body.style.width = "100%";
190
+ return () => {
191
+ const top = body.style.top;
192
+ body.style.position = "";
193
+ body.style.top = "";
194
+ body.style.width = "";
195
+ if (top !== "") {
196
+ browserWindow.scrollTo(0, Number.parseInt(top, 10) * -1);
197
+ }
198
+ };
199
+ }
200
+ body.classList.add(mobileBodyScrollLockClass);
201
+ return () => {
202
+ body.classList.remove(mobileBodyScrollLockClass);
203
+ };
204
+ }, [mobileMenuOpen]);
205
+ useEffect(() => {
206
+ if (typeof window === "undefined" || typeof window.matchMedia !== "function") {
207
+ return;
208
+ }
209
+ const desktopQuery = window.matchMedia(desktopMinWidthMediaQuery);
210
+ const applyViewportModeChange = ({ matches: isDesktopViewport2 }) => {
211
+ if (isDesktopViewport2) {
212
+ clearTimeout(mobileSecondPanelCloseTimeoutRef.current ?? void 0);
213
+ mobileSecondPanelCloseTimeoutRef.current = null;
214
+ clearTimeout(mobileThirdPanelCloseTimeoutRef.current ?? void 0);
215
+ mobileThirdPanelCloseTimeoutRef.current = null;
216
+ clearTimeout(resetMobileThirdPanelScrollTimeoutRef.current ?? void 0);
217
+ resetMobileThirdPanelScrollTimeoutRef.current = null;
218
+ setMobileMenuOpen((previous) => {
219
+ if (previous) {
220
+ onMobileMenuToggle?.(false);
221
+ }
222
+ return false;
223
+ });
224
+ setMobileActiveCategoryIndex(null);
225
+ setIsMobileSecondPanelClosing(false);
226
+ setIsMobileThirdPanelClosing(false);
227
+ return;
228
+ }
229
+ setOpenTopLevelItemIndex((previous) => {
230
+ if (previous !== null) {
231
+ onDesktopItemToggle?.(null);
232
+ }
233
+ return null;
234
+ });
235
+ };
236
+ applyViewportModeChange(desktopQuery);
237
+ desktopQuery.addEventListener("change", applyViewportModeChange);
238
+ return () => {
239
+ desktopQuery.removeEventListener("change", applyViewportModeChange);
240
+ };
241
+ }, [onDesktopItemToggle, onMobileMenuToggle]);
242
+ const resetMobilePanelState = useCallback(() => {
243
+ setOpenTopLevelItemIndex(null);
244
+ setMobileActiveCategoryIndex(null);
245
+ setIsMobileSecondPanelClosing(false);
246
+ setIsMobileThirdPanelClosing(false);
247
+ }, []);
248
+ const closeMobileMenu = useCallback(() => {
249
+ clearTimeout(mobileSecondPanelCloseTimeoutRef.current ?? void 0);
250
+ mobileSecondPanelCloseTimeoutRef.current = null;
251
+ clearTimeout(mobileThirdPanelCloseTimeoutRef.current ?? void 0);
252
+ mobileThirdPanelCloseTimeoutRef.current = null;
253
+ clearTimeout(resetMobileThirdPanelScrollTimeoutRef.current ?? void 0);
254
+ resetMobileThirdPanelScrollTimeoutRef.current = null;
255
+ if (!mobileMenuOpen && openTopLevelItemIndex === null) {
256
+ return;
257
+ }
258
+ const shouldAnimateMobileClose = mobileMenuOpen;
259
+ clearTimeout(mobileMenuCloseResetTimeoutRef.current ?? void 0);
260
+ setIsMobileMenuClosing(shouldAnimateMobileClose);
261
+ setMobileMenuOpen((previous) => {
262
+ if (previous) {
263
+ onMobileMenuToggle?.(false);
264
+ }
265
+ return false;
266
+ });
267
+ setOpenTopLevelItemIndex((previous) => {
268
+ if (previous !== null) {
269
+ onDesktopItemToggle?.(null);
270
+ }
271
+ return null;
272
+ });
273
+ if (shouldAnimateMobileClose) {
274
+ mobileMenuCloseResetTimeoutRef.current = setTimeout(() => {
275
+ resetMobilePanelState();
276
+ setIsMobileMenuClosing(false);
277
+ mobileMenuCloseResetTimeoutRef.current = null;
278
+ }, mobilePanelAnimationDurationMs);
279
+ return;
280
+ }
281
+ resetMobilePanelState();
282
+ setIsMobileMenuClosing(false);
283
+ }, [
284
+ mobileMenuOpen,
285
+ onDesktopItemToggle,
286
+ onMobileMenuToggle,
287
+ openTopLevelItemIndex,
288
+ resetMobilePanelState
289
+ ]);
290
+ const toggleMobileMenu = () => {
291
+ if (mobileMenuOpen) {
292
+ closeMobileMenu();
293
+ return;
294
+ }
295
+ setMobileMenuOpen(true);
296
+ setIsMobileMenuClosing(false);
297
+ onMobileMenuToggle?.(true);
298
+ };
299
+ const toggleTopLevelItem = (index) => {
300
+ setOpenTopLevelItemIndex((previous) => {
301
+ const next = previous === index ? null : index;
302
+ setMobileActiveCategoryIndex(null);
303
+ setIsMobileSecondPanelClosing(false);
304
+ setIsMobileThirdPanelClosing(false);
305
+ onDesktopItemToggle?.(next);
306
+ return next;
307
+ });
308
+ };
309
+ const isDesktopViewport = useCallback(() => {
310
+ return isDesktopViewportByEnvironment(globalThis.window);
311
+ }, []);
312
+ const isFocusable = useCallback((element) => {
313
+ if (element.tabIndex < 0 || element.hasAttribute("disabled")) {
314
+ return false;
315
+ }
316
+ if (element.getAttribute("aria-hidden") === "true") {
317
+ return false;
318
+ }
319
+ if (element.closest("[hidden]") != null) {
320
+ return false;
321
+ }
322
+ let currentElement = element;
323
+ while (currentElement != null) {
324
+ const computedStyle = window.getComputedStyle(currentElement);
325
+ if (computedStyle.display === "none" || computedStyle.visibility === "hidden") {
326
+ return false;
327
+ }
328
+ currentElement = currentElement.parentElement;
329
+ }
330
+ return true;
331
+ }, []);
332
+ const getFocusableElements = useCallback(
333
+ (container, selector) => (
334
+ /* v8 ignore next -- defensive null guard for transient panel refs */
335
+ container == null ? [] : Array.from(container.querySelectorAll(selector)).filter(isFocusable)
336
+ ),
337
+ [isFocusable]
338
+ );
339
+ const getDesktopPanelInteractiveElements = useCallback(() => {
340
+ return getFocusableElements(
341
+ headerElementRef.current,
342
+ `.${styles["main-navigation__panel--desktop"]} a[href], .${styles["main-navigation__panel--desktop"]} button:not([disabled]), .${styles["main-navigation__panel--desktop"]} [tabindex]:not([tabindex="-1"])`
343
+ );
344
+ }, [getFocusableElements]);
345
+ const getDesktopFocusLoopElements = useCallback(
346
+ (openDesktopItemIndex) => {
347
+ const focusLoopElements = /* @__PURE__ */ new Set();
348
+ const triggerButton = desktopPanelTriggerButtonRefs.current[openDesktopItemIndex];
349
+ if (triggerButton != null && isFocusable(triggerButton)) {
350
+ focusLoopElements.add(triggerButton);
351
+ }
352
+ getDesktopPanelInteractiveElements().forEach((element) => {
353
+ focusLoopElements.add(element);
354
+ });
355
+ return Array.from(focusLoopElements);
356
+ },
357
+ [getDesktopPanelInteractiveElements, isFocusable]
358
+ );
359
+ const getMobileFocusableElements = useCallback(() => {
360
+ const focusableElements = [];
361
+ const addFocusableElements = (elements) => {
362
+ focusableElements.push(...elements);
363
+ };
364
+ if (mobileMenuToggleButtonRef.current != null && isFocusable(mobileMenuToggleButtonRef.current)) {
365
+ focusableElements.push(mobileMenuToggleButtonRef.current);
366
+ }
367
+ if (openTopLevelItemIndex == null) {
368
+ addFocusableElements(
369
+ getFocusableElements(
370
+ mobilePrimaryNavRef.current,
371
+ `.${styles["main-navigation__primary-list"]} .${styles["main-navigation__item-toggle"]}, .${styles["main-navigation__primary-list"]} .${styles["main-navigation__item-link"]}`
372
+ )
373
+ );
374
+ return Array.from(new Set(focusableElements));
375
+ }
376
+ if (mobileActiveCategoryIndex == null) {
377
+ addFocusableElements(
378
+ getFocusableElements(
379
+ mobileModalPanelRef.current,
380
+ `.${styles["main-navigation__mobile-back-item"]}, .${styles["main-navigation__mobile-feature-link"]}, .${styles["main-navigation__mobile-level-2-category-button"]}`
381
+ )
382
+ );
383
+ return Array.from(new Set(focusableElements));
384
+ }
385
+ addFocusableElements(
386
+ getFocusableElements(
387
+ mobileThirdPanelRef.current,
388
+ `.${styles["main-navigation__mobile-back-item"]}, .${styles["main-navigation__mobile-level-3-link"]}`
389
+ )
390
+ );
391
+ return Array.from(new Set(focusableElements));
392
+ }, [getFocusableElements, isFocusable, mobileActiveCategoryIndex, openTopLevelItemIndex]);
393
+ const openMobileCategoryPanel = useCallback((index) => {
394
+ clearTimeout(resetMobileThirdPanelScrollTimeoutRef.current ?? void 0);
395
+ setIsMobileThirdPanelClosing(false);
396
+ setMobileActiveCategoryIndex(index);
397
+ resetMobileThirdPanelScrollTimeoutRef.current = setTimeout(() => {
398
+ (mobileThirdPanelRef.current ?? { scrollTop: 0 }).scrollTop = 0;
399
+ resetMobileThirdPanelScrollTimeoutRef.current = null;
400
+ }, 0);
401
+ }, []);
402
+ const closeMenus = useCallback(() => {
403
+ clearTimeout(mobileSecondPanelCloseTimeoutRef.current ?? void 0);
404
+ mobileSecondPanelCloseTimeoutRef.current = null;
405
+ clearTimeout(mobileThirdPanelCloseTimeoutRef.current ?? void 0);
406
+ mobileThirdPanelCloseTimeoutRef.current = null;
407
+ clearTimeout(focusMobileSecondPanelTimeoutRef.current ?? void 0);
408
+ focusMobileSecondPanelTimeoutRef.current = null;
409
+ clearTimeout(focusMobileThirdPanelTimeoutRef.current ?? void 0);
410
+ focusMobileThirdPanelTimeoutRef.current = null;
411
+ clearTimeout(resetMobileThirdPanelScrollTimeoutRef.current ?? void 0);
412
+ resetMobileThirdPanelScrollTimeoutRef.current = null;
413
+ clearTimeout(focusReturnToMobileTopLevelItemTimeoutRef.current ?? void 0);
414
+ focusReturnToMobileTopLevelItemTimeoutRef.current = null;
415
+ clearTimeout(focusReturnToMobileCategoryTimeoutRef.current ?? void 0);
416
+ focusReturnToMobileCategoryTimeoutRef.current = null;
417
+ closeMobileMenu();
418
+ }, [closeMobileMenu]);
419
+ const closeMobilePanel = useCallback(
420
+ ({
421
+ isClosing,
422
+ setIsClosing,
423
+ closeTimeoutRef,
424
+ onClosed
425
+ }) => {
426
+ if (isClosing) {
427
+ return;
428
+ }
429
+ clearTimeout(closeTimeoutRef.current ?? void 0);
430
+ setIsClosing(true);
431
+ closeTimeoutRef.current = setTimeout(() => {
432
+ onClosed?.();
433
+ setIsClosing(false);
434
+ closeTimeoutRef.current = null;
435
+ }, mobilePanelAnimationDurationMs);
436
+ },
437
+ []
438
+ );
439
+ const renderNavigationLink = useCallback(
440
+ ({
441
+ link,
442
+ className: className2,
443
+ children,
444
+ ariaCurrent,
445
+ onKeyDown
446
+ }) => renderLink(
447
+ {
448
+ href: toNavigableHref(link.href),
449
+ className: className2,
450
+ rel: getLinkRel(link.target),
451
+ target: getLinkTarget(link.target),
452
+ "aria-current": ariaCurrent,
453
+ onKeyDown,
454
+ children
455
+ },
456
+ { external: isExternalLink(link) }
457
+ ),
458
+ [renderLink]
459
+ );
460
+ const renderUtilityLink = useCallback(
461
+ (props2) => renderLink(props2, { external: false }),
462
+ [renderLink]
463
+ );
464
+ const openItem = openTopLevelItemIndex != null ? items[openTopLevelItemIndex] : void 0;
465
+ const openPanel = openItem?.panel;
466
+ const isMobilePanelClosingOut = isMobileMenuClosing && !mobileMenuOpen;
467
+ const showPageOverlay = mobileMenuOpen || openPanel != null || isMobilePanelClosingOut;
468
+ const isOverlayClosingOut = isMobilePanelClosingOut && openPanel == null;
469
+ const cartAccessibleLabel = cartCounter != null ? `${cartLabel} ${cartCounter} ${cartCounterLabel}` : cartLabel;
470
+ useEffect(() => {
471
+ if (!showPageOverlay) {
472
+ return;
473
+ }
474
+ const handleOutsidePointerDown = (event) => {
475
+ const target = event.target;
476
+ if (!(target instanceof Node)) {
477
+ return;
478
+ }
479
+ if (headerElementRef.current?.contains(target)) {
480
+ return;
481
+ }
482
+ closeMenus();
483
+ };
484
+ document.addEventListener("pointerdown", handleOutsidePointerDown, true);
485
+ return () => {
486
+ document.removeEventListener("pointerdown", handleOutsidePointerDown, true);
487
+ };
488
+ }, [closeMenus, showPageOverlay]);
489
+ useEffect(() => {
490
+ if (!focusMobilePanelBackOnOpenRef.current || openTopLevelItemIndex == null || mobileMenuOpen === false) {
491
+ return;
492
+ }
493
+ if (isDesktopViewport()) {
494
+ focusMobilePanelBackOnOpenRef.current = false;
495
+ return;
496
+ }
497
+ clearTimeout(focusMobileSecondPanelTimeoutRef.current ?? void 0);
498
+ focusMobileSecondPanelTimeoutRef.current = setTimeout(() => {
499
+ mobilePanelBackButtonRef.current?.focus();
500
+ focusMobilePanelBackOnOpenRef.current = false;
501
+ focusMobileSecondPanelTimeoutRef.current = null;
502
+ }, mobilePanelAnimationDurationMs);
503
+ }, [isDesktopViewport, mobileMenuOpen, openTopLevelItemIndex]);
504
+ useEffect(() => {
505
+ if (!focusMobileThirdPanelBackOnOpenRef.current || mobileActiveCategoryIndex == null) {
506
+ return;
507
+ }
508
+ focusMobileThirdPanelBackOnOpenRef.current = focusMobileThirdPanelBackOnOpenRef.current && !isDesktopViewport();
509
+ if (focusMobileThirdPanelBackOnOpenRef.current) {
510
+ clearTimeout(focusMobileThirdPanelTimeoutRef.current ?? void 0);
511
+ focusMobileThirdPanelTimeoutRef.current = setTimeout(() => {
512
+ mobileThirdPanelBackButtonRef.current?.focus();
513
+ focusMobileThirdPanelBackOnOpenRef.current = false;
514
+ focusMobileThirdPanelTimeoutRef.current = null;
515
+ }, mobilePanelAnimationDurationMs);
516
+ }
517
+ }, [isDesktopViewport, mobileActiveCategoryIndex]);
518
+ useEffect(() => {
519
+ if (!mobileMenuOpen || openTopLevelItemIndex == null || isDesktopViewport()) {
520
+ return;
521
+ }
522
+ const mobileSecondPanel = mobileModalPanelRef.current;
523
+ if (mobileSecondPanel == null) {
524
+ return;
525
+ }
526
+ mobileSecondPanel.scrollTop = 0;
527
+ }, [isDesktopViewport, mobileMenuOpen, openTopLevelItemIndex]);
528
+ const renderPanel = (panelClassName, isMobileModal = false) => {
529
+ if (openPanel == null || openItem == null) {
530
+ return null;
531
+ }
532
+ const hasFeatureLinks = openPanel.featureLinks != null && openPanel.featureLinks.length > 0;
533
+ const panelColumns = openPanel.columns ?? [];
534
+ const lastDesktopVisibleColumnIndex = panelColumns.reduce((lastIndex, column, index) => {
535
+ if (column.mobileOnly) {
536
+ return lastIndex;
537
+ }
538
+ return index;
539
+ }, -1);
540
+ const mobilePanelColumns = panelColumns.filter((column) => !column.desktopOnly);
541
+ const getColumnHeading = (heading, isOverflow) => {
542
+ if (!isOverflow) {
543
+ return heading;
544
+ }
545
+ return heading.trim() === "" ? overflowCategoryLabel : heading;
546
+ };
547
+ if (isMobileModal) {
548
+ const selectedColumn = mobileActiveCategoryIndex != null ? mobilePanelColumns[mobileActiveCategoryIndex] : null;
549
+ const isLevelThreePanelOpen = selectedColumn != null && !isMobileThirdPanelClosing;
550
+ const shouldHideLevelTwoFromAssistiveTech = isLevelThreePanelOpen;
551
+ return /* @__PURE__ */ jsx(
552
+ "div",
553
+ {
554
+ ref: mobileModalPanelRef,
555
+ className: cn(
556
+ panelClassName,
557
+ isMobileSecondPanelClosing && styles["main-navigation__panel--is-closing"]
558
+ ),
559
+ "aria-label": openItem.label,
560
+ "aria-hidden": isMobilePanelClosingOut || void 0,
561
+ children: /* @__PURE__ */ jsxs("div", { className: styles["main-navigation__mobile-level-2-content"], children: [
562
+ /* @__PURE__ */ jsxs(
563
+ "button",
564
+ {
565
+ ref: mobilePanelBackButtonRef,
566
+ type: "button",
567
+ className: cn(
568
+ styles["main-navigation__mobile-back-item"],
569
+ focusStyles.focusableInset,
570
+ focusStyles.focusableRadiusSm
571
+ ),
572
+ onClick: () => closeMobilePanel({
573
+ isClosing: isMobileSecondPanelClosing,
574
+ setIsClosing: setIsMobileSecondPanelClosing,
575
+ closeTimeoutRef: mobileSecondPanelCloseTimeoutRef,
576
+ onClosed: () => {
577
+ const closedTopLevelItemIndex = openTopLevelItemIndex;
578
+ setOpenTopLevelItemIndex(null);
579
+ setMobileActiveCategoryIndex(null);
580
+ onDesktopItemToggle?.(null);
581
+ clearTimeout(
582
+ focusReturnToMobileTopLevelItemTimeoutRef.current ?? void 0
583
+ );
584
+ focusReturnToMobileTopLevelItemTimeoutRef.current = setTimeout(() => {
585
+ desktopPanelTriggerButtonRefs.current[closedTopLevelItemIndex]?.focus();
586
+ focusReturnToMobileTopLevelItemTimeoutRef.current = null;
587
+ }, 0);
588
+ }
589
+ }),
590
+ children: [
591
+ /* @__PURE__ */ jsx(ChevronRight, { className: styles["main-navigation__mobile-back-icon"] }),
592
+ /* @__PURE__ */ jsx("span", { className: styles["main-navigation__mobile-back-label"], children: openItem.label })
593
+ ]
594
+ }
595
+ ),
596
+ hasFeatureLinks && /* @__PURE__ */ jsx(
597
+ "div",
598
+ {
599
+ className: styles["main-navigation__mobile-level-2-feature-links"],
600
+ "aria-hidden": shouldHideLevelTwoFromAssistiveTech || void 0,
601
+ children: /* @__PURE__ */ jsx(
602
+ "ul",
603
+ {
604
+ className: styles["main-navigation__mobile-level-2-feature-list"],
605
+ children: openPanel.featureLinks.map((link, index) => {
606
+ const href = toNavigableHref(link.href);
607
+ const isExternalFeatureLink = isExternalTarget(link.target);
608
+ const MobileFeatureIcon = isExternalFeatureLink ? Open : ArrowRight;
609
+ return /* @__PURE__ */ jsx(
610
+ "li",
611
+ {
612
+ className: styles["main-navigation__mobile-level-2-feature-list-item"],
613
+ children: /* @__PURE__ */ jsxs(
614
+ IconButton,
615
+ {
616
+ href,
617
+ renderLink: (linkProps) => renderLink(linkProps, {
618
+ external: isExternalLink(link)
619
+ }),
620
+ className: styles["main-navigation__mobile-feature-link"],
621
+ icon: MobileFeatureIcon,
622
+ size: "small",
623
+ labelBehavior: "wrap",
624
+ rel: getLinkRel(link.target),
625
+ target: getLinkTarget(link.target),
626
+ children: [
627
+ link.label,
628
+ isExternalFeatureLink && externalLinkAriaLabel && /* @__PURE__ */ jsx(
629
+ "span",
630
+ {
631
+ className: styles["main-navigation__sr-only"],
632
+ children: ` (${externalLinkAriaLabel})`
633
+ }
634
+ )
635
+ ]
636
+ }
637
+ )
638
+ },
639
+ `mobile-feature-${index}`
640
+ );
641
+ })
642
+ }
643
+ )
644
+ }
645
+ ),
646
+ /* @__PURE__ */ jsx(
647
+ "ul",
648
+ {
649
+ className: styles["main-navigation__mobile-level-2-category-list"],
650
+ "aria-hidden": shouldHideLevelTwoFromAssistiveTech || void 0,
651
+ children: mobilePanelColumns.map((column, index) => /* @__PURE__ */ jsx(
652
+ "li",
653
+ {
654
+ className: styles["main-navigation__mobile-level-2-category-item"],
655
+ children: /* @__PURE__ */ jsxs(
656
+ "button",
657
+ {
658
+ ref: (node) => {
659
+ mobileLevelTwoCategoryButtonRefs.current[index] = node;
660
+ },
661
+ type: "button",
662
+ className: cn(
663
+ styles["main-navigation__mobile-level-2-category-button"],
664
+ focusStyles.focusableInset,
665
+ focusStyles.focusableRadiusSm
666
+ ),
667
+ onClick: () => openMobileCategoryPanel(index),
668
+ onKeyDown: (event) => {
669
+ if (event.key !== "Enter" || isDesktopViewport()) {
670
+ return;
671
+ }
672
+ event.preventDefault();
673
+ focusMobileThirdPanelBackOnOpenRef.current = true;
674
+ openMobileCategoryPanel(index);
675
+ },
676
+ children: [
677
+ /* @__PURE__ */ jsx("span", { children: getColumnHeading(column.heading, column.overflow) }),
678
+ /* @__PURE__ */ jsx(ChevronRight, {})
679
+ ]
680
+ }
681
+ )
682
+ },
683
+ `mobile-category-${column.heading}-${index}`
684
+ ))
685
+ }
686
+ ),
687
+ /* @__PURE__ */ jsx(
688
+ "div",
689
+ {
690
+ ref: mobileThirdPanelRef,
691
+ className: cn(
692
+ styles["main-navigation__mobile-level-3-panel"],
693
+ isLevelThreePanelOpen && styles["main-navigation__mobile-level-3-panel--open"],
694
+ isMobileThirdPanelClosing && styles["main-navigation__mobile-level-3-panel--is-closing"]
695
+ ),
696
+ children: selectedColumn != null && /* @__PURE__ */ jsxs(Fragment$1, { children: [
697
+ /* @__PURE__ */ jsxs(
698
+ "button",
699
+ {
700
+ ref: mobileThirdPanelBackButtonRef,
701
+ type: "button",
702
+ className: cn(
703
+ styles["main-navigation__mobile-back-item"],
704
+ focusStyles.focusableInset,
705
+ focusStyles.focusableRadiusSm
706
+ ),
707
+ onClick: () => closeMobilePanel({
708
+ isClosing: isMobileThirdPanelClosing,
709
+ setIsClosing: setIsMobileThirdPanelClosing,
710
+ closeTimeoutRef: mobileThirdPanelCloseTimeoutRef,
711
+ onClosed: () => {
712
+ const closedCategoryIndex = mobileActiveCategoryIndex;
713
+ setMobileActiveCategoryIndex(null);
714
+ clearTimeout(
715
+ focusReturnToMobileCategoryTimeoutRef.current ?? void 0
716
+ );
717
+ focusReturnToMobileCategoryTimeoutRef.current = setTimeout(() => {
718
+ mobileLevelTwoCategoryButtonRefs.current[closedCategoryIndex]?.focus();
719
+ focusReturnToMobileCategoryTimeoutRef.current = null;
720
+ }, 0);
721
+ }
722
+ }),
723
+ children: [
724
+ /* @__PURE__ */ jsx(
725
+ ChevronRight,
726
+ {
727
+ className: styles["main-navigation__mobile-back-icon"]
728
+ }
729
+ ),
730
+ /* @__PURE__ */ jsx(
731
+ "span",
732
+ {
733
+ className: styles["main-navigation__mobile-back-label"],
734
+ children: selectedColumn.heading
735
+ }
736
+ )
737
+ ]
738
+ }
739
+ ),
740
+ /* @__PURE__ */ jsx("ul", { className: styles["main-navigation__mobile-level-3-list"], children: selectedColumn.links.map((link, index) => /* @__PURE__ */ jsx(
741
+ "li",
742
+ {
743
+ className: styles["main-navigation__mobile-level-3-item"],
744
+ children: renderNavigationLink({
745
+ link,
746
+ className: cn(
747
+ styles["main-navigation__mobile-level-3-link"],
748
+ focusStyles.focusableInset,
749
+ focusStyles.focusableRadiusSm
750
+ ),
751
+ children: link.label
752
+ })
753
+ },
754
+ `${selectedColumn.heading}-${index}`
755
+ )) })
756
+ ] })
757
+ }
758
+ )
759
+ ] })
760
+ }
761
+ );
762
+ }
763
+ return /* @__PURE__ */ jsx("div", { className: panelClassName, "aria-label": openItem.label, children: /* @__PURE__ */ jsxs("div", { className: styles["main-navigation__panel-content"], children: [
764
+ /* @__PURE__ */ jsx("div", { className: styles["main-navigation__panel-main"], children: /* @__PURE__ */ jsx("div", { className: styles["main-navigation__panel-columns"], children: panelColumns.map((column, columnIndex) => /* @__PURE__ */ jsxs(
765
+ "section",
766
+ {
767
+ className: cn(
768
+ styles["main-navigation__panel-column"],
769
+ column.highlighted && styles["main-navigation__panel-column--highlighted"],
770
+ column.mobileOnly && styles["main-navigation__panel-column--mobile-only"],
771
+ column.desktopOnly && styles["main-navigation__panel-column--desktop-only"],
772
+ !hasFeatureLinks && columnIndex === lastDesktopVisibleColumnIndex && styles["main-navigation__panel-column--last"]
773
+ ),
774
+ children: [
775
+ /* @__PURE__ */ jsx("h2", { className: styles["main-navigation__panel-heading"], children: getColumnHeading(column.heading, column.overflow) }),
776
+ /* @__PURE__ */ jsx("ul", { className: styles["main-navigation__panel-list"], children: column.links.map((link, index) => {
777
+ const isInCurrentPage = isLinkInCurrentPage(
778
+ link,
779
+ currentPathname
780
+ );
781
+ return /* @__PURE__ */ jsx(
782
+ "li",
783
+ {
784
+ className: styles["main-navigation__panel-list-item"],
785
+ children: renderNavigationLink({
786
+ link,
787
+ className: cn(
788
+ styles["main-navigation__panel-link"],
789
+ focusStyles.focusableInset,
790
+ focusStyles.focusableRadiusSm,
791
+ textDecorationStyles.underlineLinkOnHover,
792
+ isInCurrentPage && styles["main-navigation__panel-link--current"]
793
+ ),
794
+ ariaCurrent: isInCurrentPage ? "page" : void 0,
795
+ children: link.label
796
+ })
797
+ },
798
+ `${column.heading}-${index}`
799
+ );
800
+ }) })
801
+ ]
802
+ },
803
+ `column-${columnIndex}`
804
+ )) }) }),
805
+ /* @__PURE__ */ jsx(
806
+ "aside",
807
+ {
808
+ className: cn(
809
+ elevationStyles.elevationHigh,
810
+ styles["main-navigation__panel-column"],
811
+ styles["main-navigation__feature-links"],
812
+ styles["main-navigation__panel-column--last"],
813
+ openPanel.featureLinksHighlighted && styles["main-navigation__panel-column--highlighted"],
814
+ !hasFeatureLinks && styles["main-navigation__feature-links--empty"]
815
+ ),
816
+ children: /* @__PURE__ */ jsx("ul", { className: styles["main-navigation__feature-list"], children: (openPanel.featureLinks ?? []).map((link, index) => {
817
+ const href = toNavigableHref(link.href);
818
+ const isExternalFeatureLink = isExternalTarget(link.target);
819
+ return /* @__PURE__ */ jsx(
820
+ "li",
821
+ {
822
+ className: styles["main-navigation__panel-list-item"],
823
+ children: renderNavigationLink({
824
+ link: { ...link, href },
825
+ className: cn(
826
+ styles["main-navigation__feature-link"],
827
+ textDecorationStyles.underlineLinkOnHover,
828
+ focusStyles.focusableInset,
829
+ focusStyles.focusableRadiusSm
830
+ ),
831
+ children: /* @__PURE__ */ jsxs(Fragment$1, { children: [
832
+ isExternalFeatureLink ? /* @__PURE__ */ jsx(
833
+ Open,
834
+ {
835
+ className: styles["main-navigation__feature-link-icon"]
836
+ }
837
+ ) : /* @__PURE__ */ jsx(
838
+ ArrowRight,
839
+ {
840
+ className: styles["main-navigation__feature-link-icon"]
841
+ }
842
+ ),
843
+ /* @__PURE__ */ jsx(
844
+ "span",
845
+ {
846
+ className: styles["main-navigation__feature-link-label"],
847
+ children: link.label
848
+ }
849
+ ),
850
+ isExternalFeatureLink && externalLinkAriaLabel && /* @__PURE__ */ jsx(
851
+ "span",
852
+ {
853
+ className: styles["main-navigation__sr-only"],
854
+ children: ` (${externalLinkAriaLabel})`
855
+ }
856
+ )
857
+ ] })
858
+ })
859
+ },
860
+ `feature-${index}`
861
+ );
862
+ }) })
863
+ }
864
+ )
865
+ ] }) });
866
+ };
867
+ const renderPrimaryList = () => /* @__PURE__ */ jsx("ul", { className: styles["main-navigation__primary-list"], children: items.map((item, index) => {
868
+ const hasPanel = item.panel != null;
869
+ const isOpen = openTopLevelItemIndex === index;
870
+ const isCurrentPathItem = isItemInCurrentPath(item, currentPathname);
871
+ return /* @__PURE__ */ jsx("li", { className: styles["main-navigation__item"], children: hasPanel ? /* @__PURE__ */ jsxs(
872
+ "button",
873
+ {
874
+ ref: (node) => {
875
+ desktopPanelTriggerButtonRefs.current[index] = node;
876
+ },
877
+ type: "button",
878
+ className: cn(
879
+ styles["main-navigation__item-toggle"],
880
+ focusStyles.focusableInset,
881
+ focusStyles.focusableRadiusSm,
882
+ isCurrentPathItem && styles["main-navigation__item-toggle--current"],
883
+ isOpen && styles["main-navigation__item-toggle--open"]
884
+ ),
885
+ "aria-expanded": isOpen,
886
+ onClick: () => toggleTopLevelItem(index),
887
+ onKeyDown: (event) => {
888
+ if (event.key === "Enter" && !isDesktopViewport()) {
889
+ focusMobilePanelBackOnOpenRef.current = true;
890
+ }
891
+ },
892
+ children: [
893
+ /* @__PURE__ */ jsx("span", { className: styles["main-navigation__item-label"], children: item.label }),
894
+ /* @__PURE__ */ jsx(
895
+ ChevronRight,
896
+ {
897
+ className: styles["main-navigation__top-level-toggle-icon"]
898
+ }
899
+ )
900
+ ]
901
+ }
902
+ ) : renderNavigationLink({
903
+ link: item,
904
+ className: cn(
905
+ styles["main-navigation__item-link"],
906
+ focusStyles.focusableInset,
907
+ focusStyles.focusableRadiusSm,
908
+ isCurrentPathItem && styles["main-navigation__item-link--current"]
909
+ ),
910
+ ariaCurrent: isCurrentPathItem ? "page" : void 0,
911
+ children: /* @__PURE__ */ jsx("span", { className: styles["main-navigation__item-label"], children: item.label })
912
+ }) }, item.label);
913
+ }) });
914
+ return /* @__PURE__ */ jsxs(
915
+ "header",
916
+ {
917
+ ref: setHeaderRef,
918
+ className: cn(
919
+ styles["main-navigation"],
920
+ isDesktopHeaderOpen && styles["main-navigation--open"],
921
+ mobileMenuOpen && styles["main-navigation--menu-open"],
922
+ isMobileMenuClosing && styles["main-navigation--menu-closing"],
923
+ showPageOverlay && styles["main-navigation--overlay"],
924
+ showPageOverlay && overlayStyles.overlayStrong,
925
+ isOverlayClosingOut && overlayStyles.overlayClosing,
926
+ className
927
+ ),
928
+ ...props,
929
+ onKeyDown: (event) => {
930
+ if (event.key === "Tab" && mobileMenuOpen && !isDesktopViewport()) {
931
+ const focusableElements = getMobileFocusableElements();
932
+ if (focusableElements.length > 0) {
933
+ event.preventDefault();
934
+ const currentIndex = focusableElements.indexOf(
935
+ document.activeElement
936
+ );
937
+ const direction = event.shiftKey ? -1 : 1;
938
+ const nextIndex = currentIndex === -1 ? event.shiftKey ? focusableElements.length - 1 : 0 : (currentIndex + direction + focusableElements.length) % focusableElements.length;
939
+ focusableElements[nextIndex]?.focus();
940
+ }
941
+ return;
942
+ }
943
+ if (event.key === "Tab" && openTopLevelItemIndex != null && isDesktopViewport()) {
944
+ const focusLoopElements = getDesktopFocusLoopElements(openTopLevelItemIndex);
945
+ if (focusLoopElements.length > 0) {
946
+ event.preventDefault();
947
+ const currentIndex = focusLoopElements.indexOf(
948
+ document.activeElement
949
+ );
950
+ const direction = event.shiftKey ? -1 : 1;
951
+ const nextIndex = currentIndex === -1 ? event.shiftKey ? focusLoopElements.length - 1 : 0 : (currentIndex + direction + focusLoopElements.length) % focusLoopElements.length;
952
+ focusLoopElements[nextIndex]?.focus();
953
+ return;
954
+ }
955
+ }
956
+ if (event.key === "Escape") {
957
+ closeMenus();
958
+ }
959
+ props.onKeyDown?.(event);
960
+ },
961
+ children: [
962
+ /* @__PURE__ */ jsx(
963
+ "nav",
964
+ {
965
+ "aria-label": organizationStripAriaLabel,
966
+ className: styles["main-navigation__organization-strip"],
967
+ children: organizations.map((organization) => /* @__PURE__ */ jsx(Fragment, { children: renderNavigationLink({
968
+ link: organization,
969
+ className: cn(
970
+ styles["main-navigation__organization-link"],
971
+ focusStyles.focusable,
972
+ organization.current && styles["main-navigation__organization-link--current"]
973
+ ),
974
+ ariaCurrent: organization.current ? "page" : void 0,
975
+ children: organization.label
976
+ }) }, organization.label))
977
+ }
978
+ ),
979
+ /* @__PURE__ */ jsxs("div", { className: styles["main-navigation__navbar"], children: [
980
+ renderUtilityLink({
981
+ href: toNavigableHref(logoHref),
982
+ className: cn(
983
+ styles["main-navigation__logo"],
984
+ focusStyles.focusable,
985
+ focusStyles.focusableRadiusSm
986
+ ),
987
+ "aria-label": logoAriaLabel,
988
+ children: /* @__PURE__ */ jsx("img", { src: defaultLogoSrc, alt: "", "aria-hidden": "true" })
989
+ }),
990
+ /* @__PURE__ */ jsxs(
991
+ "nav",
992
+ {
993
+ ref: mobilePrimaryNavRef,
994
+ "aria-label": mobileMenuOpen ? mobilePrimaryNavigationAriaLabel : ariaLabel,
995
+ "data-open": mobileMenuOpen ? "true" : "false",
996
+ className: cn(
997
+ styles["main-navigation__primary"],
998
+ mobileMenuOpen && styles["main-navigation__primary--open"]
999
+ ),
1000
+ children: [
1001
+ renderPrimaryList(),
1002
+ (mobileMenuOpen || isMobileMenuClosing) && renderPanel(
1003
+ cn(
1004
+ styles["main-navigation__panel"],
1005
+ styles["main-navigation__panel--mobile"]
1006
+ ),
1007
+ true
1008
+ )
1009
+ ]
1010
+ }
1011
+ ),
1012
+ /* @__PURE__ */ jsxs("div", { className: styles["main-navigation__icon-nav"], children: [
1013
+ showLanguageSelector && /* @__PURE__ */ jsxs(
1014
+ "button",
1015
+ {
1016
+ type: "button",
1017
+ className: cn(
1018
+ styles["main-navigation__icon-nav-item"],
1019
+ focusStyles.focusableInset,
1020
+ focusStyles.focusableRadiusSm
1021
+ ),
1022
+ "aria-label": languageSelectorLabel,
1023
+ onClick: onLanguageSelectorClick,
1024
+ children: [
1025
+ /* @__PURE__ */ jsx(Globe, {}),
1026
+ /* @__PURE__ */ jsx("span", { className: styles["main-navigation__icon-nav-label"], children: languageSelectorLabel })
1027
+ ]
1028
+ }
1029
+ ),
1030
+ showSearch && /* @__PURE__ */ jsxs(
1031
+ "button",
1032
+ {
1033
+ type: "button",
1034
+ className: cn(
1035
+ styles["main-navigation__icon-nav-item"],
1036
+ focusStyles.focusableInset,
1037
+ focusStyles.focusableRadiusSm
1038
+ ),
1039
+ "aria-label": searchLabel,
1040
+ onClick: onSearchClick,
1041
+ children: [
1042
+ /* @__PURE__ */ jsx(Search, {}),
1043
+ /* @__PURE__ */ jsx("span", { className: styles["main-navigation__icon-nav-label"], children: searchLabel })
1044
+ ]
1045
+ }
1046
+ ),
1047
+ showCart && /* @__PURE__ */ jsxs(
1048
+ "button",
1049
+ {
1050
+ type: "button",
1051
+ className: cn(
1052
+ styles["main-navigation__icon-nav-item"],
1053
+ focusStyles.focusableInset,
1054
+ focusStyles.focusableRadiusSm
1055
+ ),
1056
+ "aria-label": cartAccessibleLabel,
1057
+ onClick: onCartClick,
1058
+ children: [
1059
+ /* @__PURE__ */ jsx(Cart, {}),
1060
+ /* @__PURE__ */ jsx("span", { className: styles["main-navigation__icon-nav-label"], children: cartLabel }),
1061
+ cartCounter != null && /* @__PURE__ */ jsx(
1062
+ "span",
1063
+ {
1064
+ "aria-hidden": "true",
1065
+ className: styles["main-navigation__icon-nav-item--counter"],
1066
+ children: cartCounter
1067
+ }
1068
+ )
1069
+ ]
1070
+ }
1071
+ ),
1072
+ /* @__PURE__ */ jsx(
1073
+ Button,
1074
+ {
1075
+ href: toNavigableHref(loginHref),
1076
+ size: "small",
1077
+ renderLink: renderUtilityLink,
1078
+ children: loginLabel
1079
+ }
1080
+ )
1081
+ ] }),
1082
+ /* @__PURE__ */ jsx(
1083
+ "button",
1084
+ {
1085
+ ref: mobileMenuToggleButtonRef,
1086
+ type: "button",
1087
+ className: cn(
1088
+ styles["main-navigation__menu-toggle"],
1089
+ mobileMenuOpen && styles["main-navigation__menu-toggle--open"],
1090
+ focusStyles.focusableInset,
1091
+ focusStyles.focusableRadiusSm
1092
+ ),
1093
+ "aria-label": mobileMenuOpen ? mobileMenuCloseAriaLabel : mobileMenuOpenAriaLabel,
1094
+ "aria-expanded": mobileMenuOpen,
1095
+ onClick: toggleMobileMenu,
1096
+ children: mobileMenuOpen ? /* @__PURE__ */ jsx(Close, { size: "32px" }) : /* @__PURE__ */ jsx(Menu, { size: "32px" })
1097
+ }
1098
+ )
1099
+ ] }),
1100
+ !mobileMenuOpen && renderPanel(
1101
+ cn(styles["main-navigation__panel"], styles["main-navigation__panel--desktop"])
1102
+ )
1103
+ ]
1104
+ }
1105
+ );
1106
+ };
1107
+ export {
1108
+ MainNavigation
1109
+ };
1110
+ //# sourceMappingURL=MainNavigation.js.map