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