@otl-core/next-navigation 1.1.19 → 1.1.20

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 (70) hide show
  1. package/dist/components/icons/chevron-icon.d.ts +10 -0
  2. package/dist/components/icons/chevron-icon.js +30 -0
  3. package/dist/components/icons/chevron-icon.js.map +1 -0
  4. package/dist/components/icons/grid-icon.d.ts +12 -0
  5. package/dist/components/icons/grid-icon.js +95 -0
  6. package/dist/components/icons/grid-icon.js.map +1 -0
  7. package/dist/components/icons/hamburger-icon.d.ts +12 -0
  8. package/dist/components/icons/hamburger-icon.js +78 -0
  9. package/dist/components/icons/hamburger-icon.js.map +1 -0
  10. package/dist/components/icons/kebab-icon.d.ts +12 -0
  11. package/dist/components/icons/kebab-icon.js +81 -0
  12. package/dist/components/icons/kebab-icon.js.map +1 -0
  13. package/dist/components/icons/meatballs-icon.d.ts +12 -0
  14. package/dist/components/icons/meatballs-icon.js +81 -0
  15. package/dist/components/icons/meatballs-icon.js.map +1 -0
  16. package/dist/components/icons/plus-icon.d.ts +12 -0
  17. package/dist/components/icons/plus-icon.js +64 -0
  18. package/dist/components/icons/plus-icon.js.map +1 -0
  19. package/dist/components/icons/toggle-icon-map.d.ts +14 -0
  20. package/dist/components/icons/toggle-icon-map.js +22 -0
  21. package/dist/components/icons/toggle-icon-map.js.map +1 -0
  22. package/dist/components/icons/toggle-icon.d.ts +14 -0
  23. package/dist/components/icons/toggle-icon.js +39 -0
  24. package/dist/components/icons/toggle-icon.js.map +1 -0
  25. package/dist/components/items/animated-toggle-icon.d.ts +15 -0
  26. package/dist/components/items/animated-toggle-icon.js +39 -0
  27. package/dist/components/items/animated-toggle-icon.js.map +1 -0
  28. package/dist/components/items/dropdown-content-item.d.ts +12 -0
  29. package/dist/components/items/dropdown-content-item.js +223 -0
  30. package/dist/components/items/dropdown-content-item.js.map +1 -0
  31. package/dist/components/items/logo.d.ts +11 -0
  32. package/dist/components/items/logo.js +42 -0
  33. package/dist/components/items/logo.js.map +1 -0
  34. package/dist/components/mobile/mobile-menu-toggle.d.ts +12 -0
  35. package/dist/components/mobile/mobile-menu-toggle.js +53 -0
  36. package/dist/components/mobile/mobile-menu-toggle.js.map +1 -0
  37. package/dist/components/mobile/navigation-header-wrapper.d.ts +11 -0
  38. package/dist/components/mobile/navigation-header-wrapper.js +15 -0
  39. package/dist/components/mobile/navigation-header-wrapper.js.map +1 -0
  40. package/dist/components/navigation/dropdown.d.ts +19 -0
  41. package/dist/components/navigation/dropdown.js +258 -0
  42. package/dist/components/navigation/dropdown.js.map +1 -0
  43. package/dist/components/navigation/header.d.ts +13 -0
  44. package/dist/components/navigation/header.js +305 -0
  45. package/dist/components/navigation/header.js.map +1 -0
  46. package/dist/components/navigation/navbar.d.ts +21 -0
  47. package/dist/components/navigation/navbar.js +66 -0
  48. package/dist/components/navigation/navbar.js.map +1 -0
  49. package/dist/components/sections/navbar-sections.d.ts +23 -0
  50. package/dist/components/sections/navbar-sections.js +103 -0
  51. package/dist/components/sections/navbar-sections.js.map +1 -0
  52. package/dist/components/sections/navigation-item.d.ts +13 -0
  53. package/dist/components/sections/navigation-item.js +171 -0
  54. package/dist/components/sections/navigation-item.js.map +1 -0
  55. package/dist/components/ui/button.d.ts +14 -0
  56. package/dist/components/ui/button.js +51 -0
  57. package/dist/components/ui/button.js.map +1 -0
  58. package/dist/context/navigation-context.d.ts +17 -0
  59. package/dist/context/navigation-context.js +93 -0
  60. package/dist/context/navigation-context.js.map +1 -0
  61. package/dist/index.d.ts +12 -86
  62. package/dist/index.js +19 -2077
  63. package/dist/index.js.map +1 -1
  64. package/dist/lib/footer.utils.d.ts +20 -0
  65. package/dist/lib/footer.utils.js +84 -0
  66. package/dist/lib/footer.utils.js.map +1 -0
  67. package/dist/lib/navigation.utils.d.ts +34 -0
  68. package/dist/lib/navigation.utils.js +387 -0
  69. package/dist/lib/navigation.utils.js.map +1 -0
  70. package/package.json +5 -5
package/dist/index.js CHANGED
@@ -1,2079 +1,21 @@
1
- "use client";
2
- import { usePathname } from 'next/navigation';
3
- import { createContext, useRef, useEffect, useState, useMemo, useCallback, useContext } from 'react';
4
- import { jsxs, jsx, Fragment } from 'react/jsx-runtime';
5
- import { resolveColorToCSS, resolveColorsToCSS, cn, generateResponsiveSpacingCSS, generateToggleIconAnimations, generateMobileMenuAnimations, generateScrollbarStyles, generateDesktopDropdownAnimations, generateSameLayerDropdownAnimations, minifyCSS, resolveBorderToCSS } from '@otl-core/style-utils';
6
- import { marked } from 'marked';
7
- import { getBreakpointValue } from '@otl-core/cms-utils';
8
- import { CSSTransition } from 'react-transition-group';
9
- import Link from 'next/link';
10
- import { Slot } from '@radix-ui/react-slot';
11
- import { cva } from 'class-variance-authority';
12
-
13
- // src/context/navigation-context.tsx
14
- var NavigationContext = createContext(
15
- void 0
16
- );
17
- function NavigationProvider({
18
- children
19
- }) {
20
- const [activeDropdown, setActiveDropdown] = useState(null);
21
- const headerRef = useRef(null);
22
- const pathname = usePathname();
23
- const openDropdown = useCallback(
24
- (dropdownId) => setActiveDropdown(dropdownId),
25
- []
26
- );
27
- const closeDropdown = useCallback(() => setActiveDropdown(null), []);
28
- const toggleDropdown = useCallback(
29
- (dropdownId) => setActiveDropdown((prev) => prev === dropdownId ? null : dropdownId),
30
- []
31
- );
32
- const prevPathname = useRef(pathname);
33
- if (pathname !== prevPathname.current) {
34
- prevPathname.current = pathname;
35
- if (activeDropdown) {
36
- setActiveDropdown(null);
37
- }
38
- }
39
- useEffect(() => {
40
- const handleEscape = (e) => {
41
- if (e.key === "Escape" && activeDropdown) {
42
- closeDropdown();
43
- }
44
- };
45
- document.addEventListener("keydown", handleEscape);
46
- return () => document.removeEventListener("keydown", handleEscape);
47
- }, [activeDropdown, closeDropdown]);
48
- useEffect(() => {
49
- if (!activeDropdown) return;
50
- const handleClickOutside = (e) => {
51
- const target = e.target;
52
- if (target.closest("[data-navigation-internal]")) {
53
- return;
54
- }
55
- if (!headerRef.current?.contains(target)) {
56
- closeDropdown();
57
- }
58
- };
59
- document.addEventListener("click", handleClickOutside, true);
60
- return () => {
61
- document.removeEventListener("click", handleClickOutside, true);
62
- };
63
- }, [activeDropdown, closeDropdown]);
64
- const isDropdownOpen = useMemo(
65
- () => activeDropdown !== null,
66
- [activeDropdown]
67
- );
68
- return /* @__PURE__ */ jsx(
69
- NavigationContext.Provider,
70
- {
71
- value: {
72
- headerRef,
73
- isDropdownOpen,
74
- activeDropdown,
75
- openDropdown,
76
- closeDropdown,
77
- toggleDropdown
78
- },
79
- children
80
- }
81
- );
82
- }
83
- function useNavigation() {
84
- const context = useContext(NavigationContext);
85
- if (!context) {
86
- throw new Error("useNavigation must be used within NavigationProvider");
87
- }
88
- return context;
89
- }
90
- function calculateNavigationWidth(sections, site) {
91
- let totalWidth = 150;
92
- for (const section of sections) {
93
- for (const item of section?.items || []) {
94
- if (item.type === "logo") continue;
95
- const label = typeof item.label === "string" ? item.label : getLocalizedString(item.label, site) || "";
96
- const labelLength = label.length;
97
- if (item.type === "button") {
98
- totalWidth += labelLength * 8 + 48;
99
- } else if (item.type === "link" || item.type === "dropdown" || item.type === "markdown") {
100
- totalWidth += labelLength * 8 + 24;
101
- } else if (item.type === "image") {
102
- const imgConfig = item.config;
103
- const imgWidth = imgConfig?.width ? parseInt(imgConfig.width, 10) || 100 : 100;
104
- totalWidth += imgWidth + 16;
105
- }
106
- }
107
- }
108
- return totalWidth;
109
- }
110
- function getBreakpointForWidth(estimatedWidth) {
111
- const MAX_USABLE_WIDTH = 1400;
112
- if (estimatedWidth > MAX_USABLE_WIDTH) return null;
113
- if (estimatedWidth <= 640) return "sm";
114
- if (estimatedWidth <= 768) return "md";
115
- if (estimatedWidth <= 1024) return "lg";
116
- if (estimatedWidth <= 1280) return "xl";
117
- return "2xl";
118
- }
119
- var RESPONSIVE_BREAKPOINTS = [
120
- { key: "sm", minWidth: "640px" },
121
- { key: "md", minWidth: "768px" },
122
- { key: "lg", minWidth: "1024px" },
123
- { key: "xl", minWidth: "1280px" }
124
- ];
125
- function generateResponsiveCustomProps(className, props) {
126
- const css = [];
127
- const baseVars = [];
128
- const bpVars = {};
129
- for (const [prop, value] of Object.entries(props)) {
130
- if (!value) continue;
131
- if (typeof value === "string") {
132
- baseVars.push(`${prop}:${value}`);
133
- } else {
134
- if (value.base) baseVars.push(`${prop}:${value.base}`);
135
- for (const { key } of RESPONSIVE_BREAKPOINTS) {
136
- const bpVal = value[key];
137
- if (bpVal && typeof bpVal === "string") {
138
- if (!bpVars[key]) bpVars[key] = [];
139
- bpVars[key].push(`${prop}:${bpVal}`);
140
- }
141
- }
142
- }
143
- }
144
- const target = `.${className}`;
145
- if (baseVars.length > 0) {
146
- css.push(`${target}{${baseVars.join(";")}}`);
147
- }
148
- for (const { key, minWidth } of RESPONSIVE_BREAKPOINTS) {
149
- if (bpVars[key]?.length) {
150
- css.push(
151
- `@media(min-width:${minWidth}){${target}{${bpVars[key].join(";")}}}`
152
- );
153
- }
154
- }
155
- return css;
156
- }
157
- function generateNavigationCSS(id, navigation, resolvedColors, dropdownIds = []) {
158
- const cssBlocks = [];
159
- const isSameLayer = navigation.style?.dropdown?.layer === "same";
160
- if (navigation.style) {
161
- if (isSameLayer) {
162
- const wrapperCSS = generateResponsiveSpacingCSS(`navbar-wrapper-${id}`, {
163
- border: navigation.style.border,
164
- padding: navigation.style.layout?.padding,
165
- shadow: navigation.style.shadow
166
- });
167
- if (wrapperCSS) cssBlocks.push(wrapperCSS);
168
- } else {
169
- const navbarCSS = generateResponsiveSpacingCSS(`navbar-${id}`, {
170
- border: navigation.style.border,
171
- padding: navigation.style.layout?.padding,
172
- shadow: navigation.style.shadow
173
- });
174
- if (navbarCSS) cssBlocks.push(navbarCSS);
175
- }
176
- const navbarInnerCSS = generateResponsiveSpacingCSS(`navbar-inner-${id}`, {
177
- gap: navigation.style.layout?.sectionGap,
178
- fontSize: navigation.style.fontSize?.navbar
179
- });
180
- if (navbarInnerCSS) cssBlocks.push(navbarInnerCSS);
181
- const btnFontSize = navigation.style.fontSize?.buttonFontSize;
182
- if (btnFontSize) {
183
- cssBlocks.push(
184
- ...generateResponsiveCustomProps(`navbar-inner-${id}`, {
185
- "--btn-font-sm": btnFontSize.sm,
186
- "--btn-font-md": btnFontSize.md,
187
- "--btn-font-lg": btnFontSize.lg
188
- })
189
- );
190
- }
191
- }
192
- if (navigation.style && dropdownIds.length > 0) {
193
- dropdownIds.forEach((dropdownId) => {
194
- if (isSameLayer) {
195
- const dropdownContentCSS = generateResponsiveSpacingCSS(
196
- `dropdown-content-${dropdownId}`,
197
- {
198
- gap: navigation.style?.dropdown?.sectionGap,
199
- fontSize: navigation.style?.fontSize?.dropdown
200
- }
201
- );
202
- if (dropdownContentCSS) cssBlocks.push(dropdownContentCSS);
203
- } else {
204
- const dropdownCSS = generateResponsiveSpacingCSS(
205
- `navigation-dropdown-${dropdownId}`,
206
- {
207
- padding: navigation.style?.dropdown?.padding,
208
- border: navigation.style?.dropdown?.border,
209
- shadow: navigation.style?.dropdown?.shadow
210
- }
211
- );
212
- if (dropdownCSS) cssBlocks.push(dropdownCSS);
213
- const dropdownContentCSS = generateResponsiveSpacingCSS(
214
- `dropdown-content-${dropdownId}`,
215
- {
216
- gap: navigation.style?.dropdown?.sectionGap,
217
- fontSize: navigation.style?.fontSize?.dropdown
218
- }
219
- );
220
- if (dropdownContentCSS) cssBlocks.push(dropdownContentCSS);
221
- }
222
- const btnFontSize = navigation.style?.fontSize?.buttonFontSize;
223
- if (btnFontSize) {
224
- cssBlocks.push(
225
- ...generateResponsiveCustomProps(`dropdown-content-${dropdownId}`, {
226
- "--btn-font-sm": btnFontSize.sm,
227
- "--btn-font-md": btnFontSize.md,
228
- "--btn-font-lg": btnFontSize.lg
229
- })
230
- );
231
- }
232
- });
233
- }
234
- if (resolvedColors.burgerButtonBackgroundHover) {
235
- cssBlocks.push(
236
- `.mobile-menu-toggle-${id}:hover{background-color:${resolvedColors.burgerButtonBackgroundHover}!important}`
237
- );
238
- }
239
- if (resolvedColors.dropdownMenuLinkHoverColor || resolvedColors.dropdownMenuLinkHoverBackground) {
240
- const hoverStyles = [];
241
- if (resolvedColors.dropdownMenuLinkHoverBackground) {
242
- hoverStyles.push(
243
- `background-color:${resolvedColors.dropdownMenuLinkHoverBackground}!important`
244
- );
245
- }
246
- if (resolvedColors.dropdownMenuLinkHoverColor) {
247
- hoverStyles.push(
248
- `color:${resolvedColors.dropdownMenuLinkHoverColor}!important`
249
- );
250
- }
251
- cssBlocks.push(
252
- `#mobile-menu-dropdown-${id} a:hover{${hoverStyles.join(";")}}`
253
- );
254
- }
255
- cssBlocks.push(...generateToggleIconAnimations());
256
- cssBlocks.push(...generateMobileMenuAnimations());
257
- cssBlocks.push(...generateScrollbarStyles());
258
- cssBlocks.push(...generateDesktopDropdownAnimations());
259
- if (isSameLayer) {
260
- cssBlocks.push(...generateSameLayerDropdownAnimations());
261
- }
262
- return minifyCSS(cssBlocks.filter(Boolean).join(""));
263
- }
264
- function sectionsToDropdownContent(sections) {
265
- const result = [];
266
- let lastSectionHadContent = false;
267
- sections.forEach((section, index) => {
268
- const items = section?.items?.filter((item) => {
269
- if (item.type === "logo") return false;
270
- if (resolveItemVisibility(item) === "navbar-only") return false;
271
- return true;
272
- });
273
- if (items?.length === 0) {
274
- return;
275
- }
276
- if (lastSectionHadContent && result.length > 0) {
277
- result.push({
278
- id: `divider-${sections[index - 1].id}`,
279
- type: "divider",
280
- config: {}
281
- });
282
- }
283
- items?.forEach((item) => {
284
- if (item.type === "link") {
285
- const config = item.config;
286
- const navConfig = {
287
- label: item.label || "",
288
- href: config.href,
289
- icon: config.icon,
290
- external: config.external
291
- };
292
- result.push({
293
- id: item.id,
294
- type: "navigation-item",
295
- config: navConfig
296
- });
297
- } else if (item.type === "button") {
298
- const config = item.config;
299
- const btnConfig = {
300
- label: item.label || "",
301
- href: config.href,
302
- icon: config.icon,
303
- external: config.external,
304
- variant: config.variant,
305
- size: config.size
306
- };
307
- result.push({
308
- id: item.id,
309
- type: "button",
310
- config: btnConfig
311
- });
312
- } else if (item.type === "dropdown") {
313
- const config = item.config;
314
- result.push({
315
- id: item.id,
316
- type: "dropdown",
317
- label: item.label || "",
318
- config
319
- });
320
- } else if (item.type === "markdown") {
321
- const config = item.config;
322
- result.push({
323
- id: item.id,
324
- type: "markdown",
325
- config: { content: config.content || item.label || "" }
326
- });
327
- } else if (item.type === "image") {
328
- const config = item.config;
329
- result.push({
330
- id: item.id,
331
- type: "image",
332
- config: {
333
- src: config.src,
334
- alt: config.alt,
335
- width: config.width ? { base: config.width } : { base: "100%" },
336
- height: config.height ? { base: config.height } : { base: "auto" },
337
- objectFit: config.objectFit,
338
- href: config.href
339
- }
340
- });
341
- }
342
- });
343
- lastSectionHadContent = true;
344
- });
345
- return result;
346
- }
347
- function getBrowserPreferredLocales(options = {}) {
348
- const defaultOptions = {
349
- languageCodeOnly: false
350
- };
351
- const opt = {
352
- ...defaultOptions,
353
- ...options
354
- };
355
- const browserLocales = navigator.languages === void 0 ? [navigator.language] : navigator.languages;
356
- if (!browserLocales) {
357
- return void 0;
358
- }
359
- return browserLocales.map((locale) => {
360
- const trimmedLocale = locale.trim();
361
- return opt.languageCodeOnly ? trimmedLocale.split(/-|_/)[0] : trimmedLocale;
362
- });
363
- }
364
- function getLocalizedString(value, options) {
365
- if (value === null || value === void 0) return "";
366
- if (typeof value === "string") return value;
367
- const preferredLocale = options && "preferredLocale" in options ? options.preferredLocale : void 0;
368
- function getDefaultLocale() {
369
- if (options && "defaultLocale" in options) return options.defaultLocale;
370
- if (options && "default_locale" in options) return options.default_locale;
371
- return void 0;
372
- }
373
- function getSupportedLocales() {
374
- if (options && "supportedLocales" in options)
375
- return options.supportedLocales;
376
- if (options && "supported_locales" in options)
377
- return options.supported_locales;
378
- return void 0;
379
- }
380
- const defaultLocale = getDefaultLocale();
381
- const supportedLocales = getSupportedLocales();
382
- if (preferredLocale && preferredLocale in value && value[preferredLocale]) {
383
- return value[preferredLocale];
384
- }
385
- if (!preferredLocale) {
386
- const browserLocales = getBrowserPreferredLocales();
387
- if (browserLocales) {
388
- for (const locale of browserLocales) {
389
- if (locale in value && value[locale]) {
390
- return value[locale];
391
- }
392
- }
393
- }
394
- }
395
- if (defaultLocale && defaultLocale in value && value[defaultLocale]) {
396
- return value[defaultLocale];
397
- }
398
- if ("en" in value && value.en) {
399
- return value.en;
400
- }
401
- if (supportedLocales) {
402
- for (const locale of supportedLocales) {
403
- if (locale in value && value[locale]) {
404
- return value[locale];
405
- }
406
- }
407
- }
408
- const keys = Object.keys(value);
409
- if (keys.length > 0 && value[keys[0]]) {
410
- return value[keys[0]];
411
- }
412
- return "";
413
- }
414
- function resolveItemVisibility(item) {
415
- if (item.visibility) return item.visibility;
416
- const legacy = item.collapse;
417
- if (legacy === false) return "navbar-only";
418
- return void 0;
419
- }
420
- var VISIBILITY_CLASSES = {
421
- "navbar-only": "flex",
422
- "mobile-only": "hidden",
423
- both: "flex"
1
+ import { Header } from "./components/navigation/header";
2
+ import { ChevronIcon } from "./components/icons/chevron-icon";
3
+ import { GridIcon } from "./components/icons/grid-icon";
4
+ import { HamburgerIcon } from "./components/icons/hamburger-icon";
5
+ import { KebabIcon } from "./components/icons/kebab-icon";
6
+ import { MeatballsIcon } from "./components/icons/meatballs-icon";
7
+ import { PlusIcon } from "./components/icons/plus-icon";
8
+ import { ToggleIcon } from "./components/icons/toggle-icon";
9
+ import { toggleIconMap } from "./components/icons/toggle-icon-map";
10
+ export {
11
+ ChevronIcon,
12
+ GridIcon,
13
+ HamburgerIcon,
14
+ Header,
15
+ KebabIcon,
16
+ MeatballsIcon,
17
+ PlusIcon,
18
+ ToggleIcon,
19
+ toggleIconMap
424
20
  };
425
- function getVisibilityClass(item, fallback) {
426
- const vis = resolveItemVisibility(item);
427
- return vis && VISIBILITY_CLASSES[vis] || fallback || "";
428
- }
429
- function parseMarkdownToHTML(markdown) {
430
- const html = marked.parse(markdown, { async: false });
431
- return html.replace(/<h1>/g, '<div class="h1">').replace(/<\/h1>/g, "</div>").replace(/<h2>/g, '<div class="h2">').replace(/<\/h2>/g, "</div>").replace(/<h3>/g, '<div class="h3">').replace(/<\/h3>/g, "</div>").replace(/<h4>/g, '<div class="h4">').replace(/<\/h4>/g, "</div>").replace(/<h5>/g, '<div class="h5">').replace(/<\/h5>/g, "</div>").replace(/<h6>/g, '<div class="h6">').replace(/<\/h6>/g, "</div>");
432
- }
433
- function NavigationHeaderWrapper({
434
- children,
435
- className,
436
- style
437
- }) {
438
- const { headerRef } = useNavigation();
439
- return /* @__PURE__ */ jsx("header", { ref: headerRef, className, style, children });
440
- }
441
- var buttonVariants = cva(
442
- "inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium transition-all disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg:not([class*='size-'])]:size-4 shrink-0 [&_svg]:shrink-0 outline-none focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px] aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive",
443
- {
444
- variants: {
445
- variant: {
446
- default: "bg-primary text-primary-foreground shadow-xs hover:bg-primary/90",
447
- destructive: "bg-destructive text-white shadow-xs hover:bg-destructive/90 focus-visible:ring-destructive/20 dark:focus-visible:ring-destructive/40 dark:bg-destructive/60",
448
- outline: "border bg-surface shadow-xs hover:bg-accent hover:text-accent-foreground dark:bg-input/30 dark:border-gray-200 dark:hover:bg-input/50",
449
- secondary: "bg-secondary text-secondary-foreground shadow-xs hover:bg-secondary/80",
450
- ghost: "hover:bg-accent hover:text-accent-foreground dark:hover:bg-accent/50",
451
- link: "text-primary underline-offset-4 hover:underline"
452
- },
453
- size: {
454
- default: "h-9 px-4 py-2 has-[>svg]:px-3",
455
- sm: "h-8 rounded-md gap-1.5 px-3 has-[>svg]:px-2.5",
456
- lg: "h-10 rounded-md px-6 has-[>svg]:px-4",
457
- icon: "size-9"
458
- }
459
- },
460
- defaultVariants: {
461
- variant: "default",
462
- size: "default"
463
- }
464
- }
465
- );
466
- function Button({
467
- className,
468
- variant,
469
- size,
470
- asChild = false,
471
- ...props
472
- }) {
473
- const Comp = asChild ? Slot : "button";
474
- return /* @__PURE__ */ jsx(
475
- Comp,
476
- {
477
- "data-slot": "button",
478
- className: cn(buttonVariants({ variant, size, className })),
479
- ...props
480
- }
481
- );
482
- }
483
- var DropdownContentItem = ({
484
- content,
485
- resolvedColors,
486
- onNavigate,
487
- navigation,
488
- site
489
- }) => {
490
- if (content.type === "markdown") {
491
- const config = content.config;
492
- const markdownContent = getLocalizedString(config.content, site);
493
- const parsedHTML = parseMarkdownToHTML(markdownContent);
494
- return /* @__PURE__ */ jsx(
495
- "div",
496
- {
497
- dangerouslySetInnerHTML: { __html: parsedHTML },
498
- style: {
499
- color: resolvedColors.text
500
- },
501
- className: "[&_*]:text-inherit"
502
- }
503
- );
504
- }
505
- if (content.type === "image") {
506
- const config = content.config;
507
- const getBaseValue = (val, fallback) => {
508
- if (val === void 0 || val === null) return fallback;
509
- if (typeof val === "number") return `${val}px`;
510
- if (typeof val === "string") return val;
511
- if (typeof val === "object" && "base" in val) return val.base;
512
- return fallback;
513
- };
514
- const width = getBaseValue(config.width, "300px");
515
- const height = getBaseValue(config.height, "auto");
516
- const objectFit = config.objectFit || "cover";
517
- if (!config.src) {
518
- return null;
519
- }
520
- const imgElement = /* @__PURE__ */ jsx(
521
- "img",
522
- {
523
- src: config.src,
524
- alt: config.alt || "",
525
- style: {
526
- display: "block",
527
- width,
528
- height,
529
- objectFit
530
- }
531
- }
532
- );
533
- if (config.href) {
534
- return /* @__PURE__ */ jsx("div", { children: /* @__PURE__ */ jsx(Link, { href: config.href, children: imgElement }) });
535
- }
536
- return /* @__PURE__ */ jsx("div", { children: imgElement });
537
- }
538
- if (content.type === "navigation-item") {
539
- const config = content.config;
540
- const label = getLocalizedString(config.label, site);
541
- return /* @__PURE__ */ jsxs(
542
- Link,
543
- {
544
- href: config.href,
545
- className: "block px-3 py-2 rounded-md text-sm transition-colors whitespace-nowrap",
546
- style: {
547
- color: resolvedColors.dropdownMenuLinkColor || resolvedColors.linkColor,
548
- backgroundColor: "transparent"
549
- },
550
- target: config.external ? "_blank" : void 0,
551
- rel: config.external ? "noopener noreferrer" : void 0,
552
- children: [
553
- config.icon && /* @__PURE__ */ jsx("span", { className: "mr-2", children: config.icon }),
554
- label
555
- ]
556
- }
557
- );
558
- }
559
- if (content.type === "button") {
560
- const config = content.config;
561
- const label = getLocalizedString(config.label, site);
562
- const variantMap2 = {
563
- primary: "default",
564
- secondary: "secondary",
565
- outline: "outline",
566
- ghost: "ghost"
567
- };
568
- const sizeMap2 = {
569
- sm: "sm",
570
- md: "default",
571
- lg: "lg"
572
- };
573
- return /* @__PURE__ */ jsx(
574
- Button,
575
- {
576
- asChild: true,
577
- variant: config.variant ? variantMap2[config.variant] : "default",
578
- size: config.size ? sizeMap2[config.size] : "default",
579
- className: "w-full whitespace-nowrap",
580
- style: {
581
- fontSize: `var(--btn-font-${config.size || "md"})`
582
- },
583
- children: /* @__PURE__ */ jsxs(
584
- Link,
585
- {
586
- href: config.href,
587
- target: config.external ? "_blank" : void 0,
588
- rel: config.external ? "noopener noreferrer" : void 0,
589
- children: [
590
- config.icon && /* @__PURE__ */ jsx("span", { className: "mr-2", children: config.icon }),
591
- label
592
- ]
593
- }
594
- )
595
- }
596
- );
597
- }
598
- if (content.type === "dropdown") {
599
- const label = content.label ? getLocalizedString(content.label, site) : "Submenu";
600
- return /* @__PURE__ */ jsx(
601
- "button",
602
- {
603
- onClick: (e) => {
604
- e.preventDefault();
605
- onNavigate?.(content.id);
606
- },
607
- type: "button",
608
- "data-navigation-internal": "true",
609
- className: "block w-full text-left px-3 py-2 rounded-md text-sm transition-colors whitespace-nowrap",
610
- style: {
611
- color: resolvedColors.dropdownMenuLinkColor || resolvedColors.linkColor,
612
- backgroundColor: "transparent"
613
- },
614
- children: /* @__PURE__ */ jsxs("span", { className: "flex items-center justify-between", children: [
615
- /* @__PURE__ */ jsx("span", { children: label }),
616
- /* @__PURE__ */ jsx(
617
- "svg",
618
- {
619
- width: "16",
620
- height: "16",
621
- viewBox: "0 0 24 24",
622
- fill: "none",
623
- stroke: "currentColor",
624
- strokeWidth: "2",
625
- children: /* @__PURE__ */ jsx("polyline", { points: "9 18 15 12 9 6" })
626
- }
627
- )
628
- ] })
629
- }
630
- );
631
- }
632
- if (content.type === "section") {
633
- const config = content.config;
634
- const getLabel = (value) => {
635
- if (!value) return "";
636
- if (typeof value === "string") return value;
637
- return value.en || "";
638
- };
639
- const title = config.title ? getLabel(config.title) : void 0;
640
- return /* @__PURE__ */ jsxs(
641
- "div",
642
- {
643
- className: "flex flex-col",
644
- style: {
645
- gap: config.gap || "0.25rem",
646
- justifyContent: config.justify || "flex-start",
647
- alignItems: config.align || "flex-start"
648
- },
649
- children: [
650
- title && /* @__PURE__ */ jsx(
651
- "div",
652
- {
653
- className: "text-sm font-semibold mb-1",
654
- style: { color: resolvedColors.text },
655
- children: title
656
- }
657
- ),
658
- config.content?.map((item) => /* @__PURE__ */ jsx(
659
- DropdownContentItem,
660
- {
661
- content: item,
662
- resolvedColors,
663
- onNavigate,
664
- navigation,
665
- site
666
- },
667
- item.id
668
- ))
669
- ]
670
- }
671
- );
672
- }
673
- if (content.type === "divider") {
674
- const dividerConfig = content.config;
675
- const dividerColor = dividerConfig?.color ? resolveColorToCSS(dividerConfig.color) : resolvedColors.border;
676
- const thickness = dividerConfig?.thickness || "1px";
677
- const margin = dividerConfig?.margin || "0.5rem";
678
- const borderStyle = dividerConfig?.style || "solid";
679
- return /* @__PURE__ */ jsx(
680
- "div",
681
- {
682
- style: {
683
- borderTopWidth: thickness,
684
- borderTopStyle: borderStyle,
685
- borderTopColor: dividerColor,
686
- marginTop: margin,
687
- marginBottom: margin
688
- }
689
- }
690
- );
691
- }
692
- return null;
693
- };
694
- function getDropdownTimeout(isMobileMenu) {
695
- return isMobileMenu ? 300 : 200;
696
- }
697
- function getDropdownClassNames(isMobileMenu) {
698
- return isMobileMenu ? "mobile-menu" : "desktop-dropdown";
699
- }
700
- function getDropdownZIndex(isSameLayer, layer) {
701
- if (isSameLayer) return void 0;
702
- return layer === "above" ? 9999 : void 0;
703
- }
704
- function NavigationDropdown({
705
- itemId,
706
- config,
707
- navigation,
708
- resolvedColors,
709
- dropdownId,
710
- site,
711
- containerContent = false,
712
- isSameLayer = false
713
- }) {
714
- const { activeDropdown } = useNavigation();
715
- const [navigationStack, setNavigationStack] = useState([]);
716
- const nodeRef = useRef(null);
717
- const backButtonRef = useRef(null);
718
- const isMobileMenu = useMemo(
719
- () => itemId.startsWith("mobile-menu"),
720
- [itemId]
721
- );
722
- const isOpen = useMemo(
723
- () => activeDropdown === itemId,
724
- [activeDropdown, itemId]
725
- );
726
- const content = useMemo(
727
- () => config.content || [],
728
- [config]
729
- );
730
- const prevIsOpen = useRef(isOpen);
731
- if (prevIsOpen.current && !isOpen) {
732
- setNavigationStack([]);
733
- }
734
- prevIsOpen.current = isOpen;
735
- useEffect(() => {
736
- if (navigationStack.length > 0 && backButtonRef.current) {
737
- backButtonRef.current.focus();
738
- }
739
- }, [navigationStack.length]);
740
- const handleNavigate = (contentId) => {
741
- setNavigationStack((prev) => [...prev, contentId]);
742
- };
743
- const handleBack = () => {
744
- setNavigationStack((prev) => prev.slice(0, -1));
745
- };
746
- const findDropdownById = (contentArray, id) => {
747
- for (const item of contentArray) {
748
- if (item.id === id && item.type === "dropdown") {
749
- return item;
750
- }
751
- if (item.type === "section") {
752
- const config2 = item.config;
753
- const found = findDropdownById(config2.content, id);
754
- if (found) return found;
755
- }
756
- }
757
- return void 0;
758
- };
759
- const buildNavigationPanels = () => {
760
- const panels2 = [];
761
- panels2.push({ content, depth: 0 });
762
- let currentContent = content;
763
- for (let i = 0; i < navigationStack.length; i++) {
764
- const contentId = navigationStack[i];
765
- const dropdownItem = findDropdownById(currentContent, contentId);
766
- if (dropdownItem && dropdownItem.config) {
767
- const nestedContent = dropdownItem.config.content;
768
- panels2.push({ content: nestedContent, depth: i + 1 });
769
- currentContent = nestedContent;
770
- } else {
771
- break;
772
- }
773
- }
774
- return panels2;
775
- };
776
- const panels = buildNavigationPanels();
777
- const dropdownColors = resolveColorsToCSS({
778
- dropdownMenuBackground: navigation.style?.dropdown?.background,
779
- dropdownMenuLinkColor: navigation.style?.dropdown?.link?.color,
780
- dropdownMenuLinkHoverColor: navigation.style?.dropdown?.link?.hoverColor,
781
- dropdownMenuLinkHoverBackground: navigation.style?.dropdown?.link?.hoverBackground,
782
- dropdownMenuTextColor: navigation.style?.dropdown?.textColor
783
- });
784
- const dropdownMenuBackground = dropdownColors.dropdownMenuBackground;
785
- const dropdownMenuLinkColor = dropdownColors.dropdownMenuLinkColor;
786
- const dropdownMenuLinkHoverColor = dropdownColors.dropdownMenuLinkHoverColor;
787
- const dropdownMenuLinkHoverBackground = dropdownColors.dropdownMenuLinkHoverBackground || "transparent";
788
- const dropdownMenuTextColor = dropdownColors.dropdownMenuTextColor;
789
- const dropdownMenuBorder = useMemo(() => {
790
- if (!navigation.style?.dropdown?.border) return void 0;
791
- return resolveBorderToCSS(navigation.style.dropdown.border);
792
- }, [navigation.style?.dropdown?.border]);
793
- if (content.length === 0) return null;
794
- const dropdownResolvedColors = {
795
- ...resolvedColors,
796
- text: dropdownMenuTextColor || resolvedColors.text,
797
- dropdownMenuLinkColor
798
- };
799
- const useSameLayerMode = isSameLayer && !isMobileMenu;
800
- const dropdownStyles = {
801
- backgroundColor: useSameLayerMode ? void 0 : dropdownMenuBackground,
802
- color: dropdownMenuTextColor || dropdownMenuLinkColor,
803
- ...useSameLayerMode ? {} : dropdownMenuBorder
804
- };
805
- const linkHoverStyle = {
806
- "--dropdown-link-hover-color": dropdownMenuLinkHoverColor,
807
- "--dropdown-link-hover-background": dropdownMenuLinkHoverBackground
808
- };
809
- return /* @__PURE__ */ jsx(Fragment, { children: /* @__PURE__ */ jsx(
810
- CSSTransition,
811
- {
812
- in: isOpen,
813
- nodeRef,
814
- timeout: useSameLayerMode ? 250 : getDropdownTimeout(isMobileMenu),
815
- classNames: useSameLayerMode ? "same-layer-dropdown" : getDropdownClassNames(isMobileMenu),
816
- unmountOnExit: !useSameLayerMode,
817
- children: /* @__PURE__ */ jsx(
818
- "div",
819
- {
820
- ref: nodeRef,
821
- className: `relative w-full navigation-dropdown-${dropdownId}`,
822
- style: {
823
- ...dropdownStyles,
824
- ...useSameLayerMode ? { display: "grid", overflow: "hidden" } : { overflow: "hidden" },
825
- zIndex: getDropdownZIndex(
826
- useSameLayerMode,
827
- navigation.style?.dropdown?.layer
828
- ),
829
- marginTop: navigation.style?.dropdown?.offset?.y ? getBreakpointValue(navigation.style.dropdown.offset.y, "base") : "0",
830
- marginLeft: navigation.style?.dropdown?.offset?.left ? getBreakpointValue(
831
- navigation.style.dropdown.offset.left,
832
- "base"
833
- ) : "0",
834
- marginRight: navigation.style?.dropdown?.offset?.right ? getBreakpointValue(
835
- navigation.style.dropdown.offset.right,
836
- "base"
837
- ) : "0"
838
- },
839
- children: /* @__PURE__ */ jsx(
840
- "div",
841
- {
842
- style: useSameLayerMode ? { overflow: "hidden", minHeight: 0 } : void 0,
843
- children: /* @__PURE__ */ jsx(
844
- "div",
845
- {
846
- style: {
847
- display: "flex",
848
- width: "100%",
849
- transform: `translateX(-${navigationStack.length * 100}%)`,
850
- transition: "transform 300ms ease-in-out"
851
- },
852
- children: panels.map((panel, panelIndex) => {
853
- const isActive = panelIndex === navigationStack.length;
854
- const isToRight = panelIndex > navigationStack.length;
855
- const panelContent = /* @__PURE__ */ jsxs(Fragment, { children: [
856
- panel.depth > 0 && /* @__PURE__ */ jsxs(
857
- "button",
858
- {
859
- ref: panelIndex === navigationStack.length ? backButtonRef : null,
860
- onClick: (e) => {
861
- e.preventDefault();
862
- handleBack();
863
- },
864
- type: "button",
865
- "data-navigation-internal": "true",
866
- className: "flex items-center px-3 py-2 text-sm rounded-md transition-colors mb-2",
867
- style: {
868
- color: resolvedColors.dropdownMenuLinkColor || resolvedColors.linkColor
869
- },
870
- children: [
871
- /* @__PURE__ */ jsx(
872
- "svg",
873
- {
874
- width: "16",
875
- height: "16",
876
- viewBox: "0 0 24 24",
877
- fill: "none",
878
- stroke: "currentColor",
879
- strokeWidth: "2",
880
- className: "mr-2",
881
- children: /* @__PURE__ */ jsx("polyline", { points: "15 18 9 12 15 6" })
882
- }
883
- ),
884
- "Back"
885
- ]
886
- }
887
- ),
888
- /* @__PURE__ */ jsx("div", { className: "flex flex-wrap gap-4", children: panel.content?.map((item) => {
889
- if (item.type === "section") {
890
- return /* @__PURE__ */ jsx("div", { className: "flex-1 min-w-[200px]", children: /* @__PURE__ */ jsx(
891
- DropdownContentItem,
892
- {
893
- content: item,
894
- resolvedColors: dropdownResolvedColors,
895
- onNavigate: handleNavigate,
896
- navigation,
897
- site
898
- }
899
- ) }, item.id);
900
- }
901
- return /* @__PURE__ */ jsx("div", { className: "w-full", children: /* @__PURE__ */ jsx(
902
- DropdownContentItem,
903
- {
904
- content: item,
905
- resolvedColors: dropdownResolvedColors,
906
- onNavigate: handleNavigate,
907
- navigation,
908
- site
909
- }
910
- ) }, item.id);
911
- }) })
912
- ] });
913
- return /* @__PURE__ */ jsx(
914
- "nav",
915
- {
916
- className: `flex flex-col p-2 dropdown-content-${dropdownId}`,
917
- style: {
918
- ...linkHoverStyle,
919
- width: "100%",
920
- flexShrink: 0,
921
- transform: isToRight ? "translateX(30px)" : "translateX(0)",
922
- opacity: isActive ? 1 : 0.95,
923
- transition: "transform 300ms ease-in-out, opacity 300ms ease-in-out"
924
- },
925
- inert: !isActive ? true : void 0,
926
- children: containerContent ? /* @__PURE__ */ jsx("div", { className: "container mx-auto", children: panelContent }) : panelContent
927
- },
928
- panelIndex
929
- );
930
- })
931
- }
932
- )
933
- }
934
- )
935
- }
936
- )
937
- }
938
- ) });
939
- }
940
- function HamburgerIcon({
941
- isOpen,
942
- className = "",
943
- size = 24,
944
- animationDuration = 300,
945
- animationTiming = "ease-in-out"
946
- }) {
947
- const duration = `${animationDuration}ms`;
948
- const hasMountedRef = useRef(false);
949
- useEffect(() => {
950
- hasMountedRef.current = true;
951
- }, []);
952
- return /* @__PURE__ */ jsxs(
953
- "div",
954
- {
955
- className,
956
- style: {
957
- width: size,
958
- height: size,
959
- position: "relative"
960
- },
961
- children: [
962
- /* @__PURE__ */ jsx(
963
- "div",
964
- {
965
- style: {
966
- position: "absolute",
967
- left: 0,
968
- top: "25%",
969
- width: size,
970
- height: "12.5%",
971
- backgroundColor: "currentColor",
972
- transform: "translateY(-50%)",
973
- animation: hasMountedRef.current ? `${isOpen ? "hamburger-top-open" : "hamburger-top-close"} ${duration} ${animationTiming} forwards` : "none"
974
- }
975
- }
976
- ),
977
- /* @__PURE__ */ jsx(
978
- "div",
979
- {
980
- style: {
981
- position: "absolute",
982
- left: 0,
983
- top: "50%",
984
- width: size,
985
- height: "12.5%",
986
- backgroundColor: "currentColor",
987
- transform: "translateY(-50%)",
988
- animation: hasMountedRef.current ? `${isOpen ? "hamburger-middle-hide" : "hamburger-middle-show"} ${duration} ${animationTiming} forwards` : "none"
989
- }
990
- }
991
- ),
992
- /* @__PURE__ */ jsx(
993
- "div",
994
- {
995
- style: {
996
- position: "absolute",
997
- left: 0,
998
- top: "75%",
999
- width: size,
1000
- height: "12.5%",
1001
- backgroundColor: "currentColor",
1002
- transform: "translateY(-50%)",
1003
- animation: hasMountedRef.current ? `${isOpen ? "hamburger-bottom-open" : "hamburger-bottom-close"} ${duration} ${animationTiming} forwards` : "none"
1004
- }
1005
- }
1006
- )
1007
- ]
1008
- }
1009
- );
1010
- }
1011
- function ChevronIcon({
1012
- isOpen,
1013
- className = "",
1014
- size = 24
1015
- }) {
1016
- return /* @__PURE__ */ jsx(
1017
- "svg",
1018
- {
1019
- width: size,
1020
- height: size,
1021
- viewBox: "0 0 24 24",
1022
- fill: "none",
1023
- stroke: "currentColor",
1024
- strokeWidth: "2",
1025
- strokeLinecap: "round",
1026
- strokeLinejoin: "round",
1027
- className,
1028
- style: {
1029
- transform: isOpen ? "rotate(180deg)" : "rotate(0deg)",
1030
- transition: "transform 200ms ease-in-out"
1031
- },
1032
- children: /* @__PURE__ */ jsx("polyline", { points: "6 9 12 15 18 9" })
1033
- }
1034
- );
1035
- }
1036
- function GridIcon({
1037
- isOpen,
1038
- className = "",
1039
- size = 24,
1040
- animationDuration = 300,
1041
- animationTiming = "ease-in-out"
1042
- }) {
1043
- const duration = `${animationDuration}ms`;
1044
- const hasMountedRef = useRef(false);
1045
- useEffect(() => {
1046
- hasMountedRef.current = true;
1047
- }, []);
1048
- return /* @__PURE__ */ jsxs(
1049
- "div",
1050
- {
1051
- className,
1052
- style: {
1053
- width: size,
1054
- height: size,
1055
- position: "relative",
1056
- // @ts-expect-error - CSS custom property
1057
- "--square-size": "40%"
1058
- },
1059
- children: [
1060
- /* @__PURE__ */ jsx(
1061
- "div",
1062
- {
1063
- style: {
1064
- position: "absolute",
1065
- left: "25%",
1066
- top: "25%",
1067
- width: "40%",
1068
- height: "40%",
1069
- backgroundColor: "currentColor",
1070
- transform: "translate(-50%, -50%)",
1071
- animation: hasMountedRef.current ? `${isOpen ? "grid-tl-open" : "grid-tl-close"} ${duration} ${animationTiming} forwards` : "none"
1072
- }
1073
- }
1074
- ),
1075
- /* @__PURE__ */ jsx(
1076
- "div",
1077
- {
1078
- style: {
1079
- position: "absolute",
1080
- left: "75%",
1081
- top: "25%",
1082
- width: "40%",
1083
- height: "40%",
1084
- backgroundColor: "currentColor",
1085
- transform: "translate(-50%, -50%)",
1086
- animation: hasMountedRef.current ? `${isOpen ? "grid-tr-hide" : "grid-tr-show"} ${duration} ${animationTiming} forwards` : "none"
1087
- }
1088
- }
1089
- ),
1090
- /* @__PURE__ */ jsx(
1091
- "div",
1092
- {
1093
- style: {
1094
- position: "absolute",
1095
- left: "25%",
1096
- top: "75%",
1097
- width: "40%",
1098
- height: "40%",
1099
- backgroundColor: "currentColor",
1100
- transform: "translate(-50%, -50%)",
1101
- animation: hasMountedRef.current ? `${isOpen ? "grid-bl-hide" : "grid-bl-show"} ${duration} ${animationTiming} forwards` : "none"
1102
- }
1103
- }
1104
- ),
1105
- /* @__PURE__ */ jsx(
1106
- "div",
1107
- {
1108
- style: {
1109
- position: "absolute",
1110
- left: "75%",
1111
- top: "75%",
1112
- width: "40%",
1113
- height: "40%",
1114
- backgroundColor: "currentColor",
1115
- transform: "translate(-50%, -50%)",
1116
- animation: hasMountedRef.current ? `${isOpen ? "grid-br-open" : "grid-br-close"} ${duration} ${animationTiming} forwards` : "none"
1117
- }
1118
- }
1119
- )
1120
- ]
1121
- }
1122
- );
1123
- }
1124
- function KebabIcon({
1125
- isOpen,
1126
- className = "",
1127
- size = 24,
1128
- animationDuration = 300,
1129
- animationTiming = "ease-in-out"
1130
- }) {
1131
- const duration = `${animationDuration}ms`;
1132
- const hasMountedRef = useRef(false);
1133
- useEffect(() => {
1134
- hasMountedRef.current = true;
1135
- }, []);
1136
- const dotSize = size * 0.125;
1137
- return /* @__PURE__ */ jsxs(
1138
- "div",
1139
- {
1140
- className,
1141
- style: {
1142
- width: size,
1143
- height: size,
1144
- position: "relative",
1145
- // @ts-expect-error - CSS custom property
1146
- "--dot-width": "12.5%"
1147
- },
1148
- children: [
1149
- /* @__PURE__ */ jsx(
1150
- "div",
1151
- {
1152
- style: {
1153
- position: "absolute",
1154
- left: "50%",
1155
- top: "25%",
1156
- width: "12.5%",
1157
- height: dotSize,
1158
- backgroundColor: "currentColor",
1159
- transform: "translate(-50%, -50%)",
1160
- animation: hasMountedRef.current ? `${isOpen ? "kebab-top-open" : "kebab-top-close"} ${duration} ${animationTiming} forwards` : "none"
1161
- }
1162
- }
1163
- ),
1164
- /* @__PURE__ */ jsx(
1165
- "div",
1166
- {
1167
- style: {
1168
- position: "absolute",
1169
- left: "50%",
1170
- top: "50%",
1171
- width: "12.5%",
1172
- height: dotSize,
1173
- backgroundColor: "currentColor",
1174
- transform: "translate(-50%, -50%)",
1175
- animation: hasMountedRef.current ? `${isOpen ? "kebab-middle-hide" : "kebab-middle-show"} ${duration} ${animationTiming} forwards` : "none"
1176
- }
1177
- }
1178
- ),
1179
- /* @__PURE__ */ jsx(
1180
- "div",
1181
- {
1182
- style: {
1183
- position: "absolute",
1184
- left: "50%",
1185
- top: "75%",
1186
- width: "12.5%",
1187
- height: dotSize,
1188
- backgroundColor: "currentColor",
1189
- transform: "translate(-50%, -50%)",
1190
- animation: hasMountedRef.current ? `${isOpen ? "kebab-bottom-open" : "kebab-bottom-close"} ${duration} ${animationTiming} forwards` : "none"
1191
- }
1192
- }
1193
- )
1194
- ]
1195
- }
1196
- );
1197
- }
1198
- function MeatballsIcon({
1199
- isOpen,
1200
- className = "",
1201
- size = 24,
1202
- animationDuration = 300,
1203
- animationTiming = "ease-in-out"
1204
- }) {
1205
- const duration = `${animationDuration}ms`;
1206
- const hasMountedRef = useRef(false);
1207
- useEffect(() => {
1208
- hasMountedRef.current = true;
1209
- }, []);
1210
- const dotSize = size * 0.125;
1211
- return /* @__PURE__ */ jsxs(
1212
- "div",
1213
- {
1214
- className,
1215
- style: {
1216
- width: size,
1217
- height: size,
1218
- position: "relative",
1219
- // @ts-expect-error - CSS custom property
1220
- "--dot-height": "12.5%"
1221
- },
1222
- children: [
1223
- /* @__PURE__ */ jsx(
1224
- "div",
1225
- {
1226
- style: {
1227
- position: "absolute",
1228
- left: "25%",
1229
- top: "50%",
1230
- width: dotSize,
1231
- height: "12.5%",
1232
- backgroundColor: "currentColor",
1233
- transform: "translate(-50%, -50%)",
1234
- animation: hasMountedRef.current ? `${isOpen ? "meatballs-left-open" : "meatballs-left-close"} ${duration} ${animationTiming} forwards` : "none"
1235
- }
1236
- }
1237
- ),
1238
- /* @__PURE__ */ jsx(
1239
- "div",
1240
- {
1241
- style: {
1242
- position: "absolute",
1243
- left: "50%",
1244
- top: "50%",
1245
- width: dotSize,
1246
- height: "12.5%",
1247
- backgroundColor: "currentColor",
1248
- transform: "translate(-50%, -50%)",
1249
- animation: hasMountedRef.current ? `${isOpen ? "meatballs-middle-hide" : "meatballs-middle-show"} ${duration} ${animationTiming} forwards` : "none"
1250
- }
1251
- }
1252
- ),
1253
- /* @__PURE__ */ jsx(
1254
- "div",
1255
- {
1256
- style: {
1257
- position: "absolute",
1258
- left: "75%",
1259
- top: "50%",
1260
- width: dotSize,
1261
- height: "12.5%",
1262
- backgroundColor: "currentColor",
1263
- transform: "translate(-50%, -50%)",
1264
- animation: hasMountedRef.current ? `${isOpen ? "meatballs-right-open" : "meatballs-right-close"} ${duration} ${animationTiming} forwards` : "none"
1265
- }
1266
- }
1267
- )
1268
- ]
1269
- }
1270
- );
1271
- }
1272
- function PlusIcon({
1273
- isOpen,
1274
- className = "",
1275
- size = 24,
1276
- animationDuration = 300,
1277
- animationTiming = "ease-in-out"
1278
- }) {
1279
- const duration = `${animationDuration}ms`;
1280
- const hasMountedRef = useRef(false);
1281
- useEffect(() => {
1282
- hasMountedRef.current = true;
1283
- }, []);
1284
- const lineThickness = size * 0.125;
1285
- const lineLength = size;
1286
- return /* @__PURE__ */ jsxs(
1287
- "div",
1288
- {
1289
- className,
1290
- style: {
1291
- width: size,
1292
- height: size,
1293
- position: "relative"
1294
- },
1295
- children: [
1296
- /* @__PURE__ */ jsx(
1297
- "div",
1298
- {
1299
- style: {
1300
- position: "absolute",
1301
- left: "50%",
1302
- top: "50%",
1303
- width: lineThickness,
1304
- height: lineLength,
1305
- backgroundColor: "currentColor",
1306
- transform: isOpen ? "translate(-50%, -50%) rotate(90deg)" : "translate(-50%, -50%) rotate(0deg)",
1307
- transition: hasMountedRef.current ? `transform ${duration} ${animationTiming}` : "none"
1308
- }
1309
- }
1310
- ),
1311
- /* @__PURE__ */ jsx(
1312
- "div",
1313
- {
1314
- style: {
1315
- position: "absolute",
1316
- left: "50%",
1317
- top: "50%",
1318
- width: lineLength,
1319
- height: lineThickness,
1320
- backgroundColor: "currentColor",
1321
- transform: "translate(-50%, -50%)"
1322
- }
1323
- }
1324
- )
1325
- ]
1326
- }
1327
- );
1328
- }
1329
-
1330
- // src/components/icons/toggle-icon-map.tsx
1331
- var toggleIconMap = /* @__PURE__ */ new Map([
1332
- ["hamburger", HamburgerIcon],
1333
- ["kebab", KebabIcon],
1334
- ["meatballs", MeatballsIcon],
1335
- ["grid", GridIcon],
1336
- ["chevron", ChevronIcon],
1337
- ["plus", PlusIcon]
1338
- ]);
1339
- function ToggleIcon({
1340
- type,
1341
- isOpen,
1342
- className = "",
1343
- size = 24,
1344
- animationDuration,
1345
- animationTiming
1346
- }) {
1347
- const IconComponent = toggleIconMap.get(type);
1348
- if (!IconComponent) {
1349
- return /* @__PURE__ */ jsx(
1350
- HamburgerIcon,
1351
- {
1352
- isOpen,
1353
- className,
1354
- size,
1355
- animationDuration,
1356
- animationTiming
1357
- }
1358
- );
1359
- }
1360
- return /* @__PURE__ */ jsx(
1361
- IconComponent,
1362
- {
1363
- isOpen,
1364
- className,
1365
- size,
1366
- animationDuration,
1367
- animationTiming
1368
- }
1369
- );
1370
- }
1371
- function AnimatedToggleIcon({
1372
- type,
1373
- isOpen,
1374
- className = "",
1375
- size = 24,
1376
- iconId = "default",
1377
- animationDuration,
1378
- animationTiming
1379
- }) {
1380
- const containerStyle = {
1381
- display: "flex",
1382
- alignItems: "center",
1383
- justifyContent: "center"
1384
- };
1385
- return /* @__PURE__ */ jsx(
1386
- "div",
1387
- {
1388
- style: containerStyle,
1389
- className: `animated-toggle-icon-${iconId} ${className}`,
1390
- children: /* @__PURE__ */ jsx(
1391
- ToggleIcon,
1392
- {
1393
- type,
1394
- isOpen,
1395
- size,
1396
- animationDuration,
1397
- animationTiming
1398
- }
1399
- )
1400
- }
1401
- );
1402
- }
1403
- function MobileMenuToggle({
1404
- navigation,
1405
- resolvedColors,
1406
- toggleId,
1407
- mobileMenuId
1408
- }) {
1409
- const { activeDropdown, toggleDropdown } = useNavigation();
1410
- const buttonRef = useRef(null);
1411
- const isMobileMenuOpen = activeDropdown === mobileMenuId;
1412
- return /* @__PURE__ */ jsx(
1413
- "button",
1414
- {
1415
- ref: buttonRef,
1416
- onClick: () => toggleDropdown(mobileMenuId),
1417
- className: `mobile-menu-toggle-${toggleId} transition-colors group flex items-center justify-center`,
1418
- style: {
1419
- backgroundColor: resolvedColors.burgerButtonBackground,
1420
- color: resolvedColors.burgerIconColor,
1421
- padding: navigation.style?.burger?.toggleButton?.padding || "0.5rem",
1422
- borderRadius: navigation.style?.burger?.toggleButton?.borderRadius || "0.375rem",
1423
- fontSize: 0,
1424
- lineHeight: 0,
1425
- font: "0/0 a",
1426
- // @ts-expect-error - CSS custom properties
1427
- "--icon-hover": resolvedColors.burgerIconHover
1428
- },
1429
- "aria-label": "Toggle navigation menu",
1430
- "aria-expanded": isMobileMenuOpen,
1431
- "aria-controls": "mobile-menu-dropdown",
1432
- children: /* @__PURE__ */ jsx(
1433
- AnimatedToggleIcon,
1434
- {
1435
- type: navigation.style?.burger?.toggleIcon?.type || "hamburger",
1436
- isOpen: isMobileMenuOpen,
1437
- size: navigation.style?.burger?.toggleIcon?.size || 24,
1438
- iconId: toggleId,
1439
- animationDuration: navigation.style?.burger?.toggleIcon?.animationDuration,
1440
- animationTiming: navigation.style?.burger?.toggleIcon?.animationTiming,
1441
- className: "group-hover:text-[var(--icon-hover)]"
1442
- }
1443
- )
1444
- }
1445
- );
1446
- }
1447
- function LogoContent({ navigation, siteName, logoTextColor }) {
1448
- if (navigation.logo?.url) {
1449
- return /* @__PURE__ */ jsx(
1450
- "img",
1451
- {
1452
- src: navigation.logo.url,
1453
- alt: navigation.logo.alt || siteName,
1454
- width: navigation.logo.width,
1455
- height: navigation.logo.height,
1456
- className: "h-auto w-auto",
1457
- style: {
1458
- height: navigation.logo.height ? `${navigation.logo.height}px` : "40px"
1459
- }
1460
- }
1461
- );
1462
- }
1463
- const text = navigation.logo?.alt || siteName;
1464
- return /* @__PURE__ */ jsx(
1465
- "span",
1466
- {
1467
- className: "text-xl font-bold",
1468
- style: logoTextColor ? { color: logoTextColor } : void 0,
1469
- children: text
1470
- }
1471
- );
1472
- }
1473
- function Logo({ navigation, siteName, logoTextColor }) {
1474
- return /* @__PURE__ */ jsx(Link, { href: "/", className: "flex-shrink-0", children: /* @__PURE__ */ jsx(
1475
- LogoContent,
1476
- {
1477
- navigation,
1478
- siteName,
1479
- logoTextColor
1480
- }
1481
- ) });
1482
- }
1483
- var variantMap = {
1484
- primary: "default",
1485
- secondary: "secondary",
1486
- outline: "outline",
1487
- ghost: "ghost"
1488
- };
1489
- var sizeMap = {
1490
- sm: "sm",
1491
- md: "default",
1492
- lg: "lg"
1493
- };
1494
- var NavigationItem = ({
1495
- item,
1496
- navigation,
1497
- resolvedColors,
1498
- itemsShowClass,
1499
- site
1500
- }) => {
1501
- const label = getLocalizedString(item.label, site);
1502
- const visibilityClass = getVisibilityClass(item, itemsShowClass);
1503
- if (item.type === "logo") {
1504
- if (!navigation?.logo) return null;
1505
- return /* @__PURE__ */ jsx(
1506
- Logo,
1507
- {
1508
- navigation,
1509
- siteName: navigation.logo.alt || "Logo",
1510
- logoTextColor: resolvedColors.logoText
1511
- }
1512
- );
1513
- }
1514
- if (item.type === "link") {
1515
- const config = item.config;
1516
- const linkStyle = {
1517
- color: resolvedColors.linkColor
1518
- };
1519
- return /* @__PURE__ */ jsxs(
1520
- Link,
1521
- {
1522
- href: config.href,
1523
- style: linkStyle,
1524
- target: config.external ? "_blank" : void 0,
1525
- rel: config.external ? "noopener noreferrer" : void 0,
1526
- className: `${visibilityClass} items-center whitespace-nowrap`,
1527
- children: [
1528
- config.icon && /* @__PURE__ */ jsx("span", { children: config.icon }),
1529
- label
1530
- ]
1531
- }
1532
- );
1533
- }
1534
- if (item.type === "button") {
1535
- const config = item.config;
1536
- return /* @__PURE__ */ jsx("div", { className: `${visibilityClass} items-center`, children: /* @__PURE__ */ jsx(
1537
- Button,
1538
- {
1539
- asChild: true,
1540
- variant: config.variant ? variantMap[config.variant] : "default",
1541
- size: config.size ? sizeMap[config.size] : "default",
1542
- className: "whitespace-nowrap",
1543
- style: {
1544
- fontSize: `var(--btn-font-${config.size || "md"})`
1545
- },
1546
- children: /* @__PURE__ */ jsxs(
1547
- Link,
1548
- {
1549
- href: config.href,
1550
- target: config.external ? "_blank" : void 0,
1551
- rel: config.external ? "noopener noreferrer" : void 0,
1552
- children: [
1553
- config.icon && /* @__PURE__ */ jsx("span", { children: config.icon }),
1554
- label
1555
- ]
1556
- }
1557
- )
1558
- }
1559
- ) });
1560
- }
1561
- if (item.type === "dropdown") {
1562
- const { toggleDropdown, activeDropdown } = useNavigation();
1563
- const isOpen = activeDropdown === item.id;
1564
- const linkStyle = {
1565
- color: resolvedColors.linkColor
1566
- };
1567
- return /* @__PURE__ */ jsxs(
1568
- "button",
1569
- {
1570
- onClick: () => toggleDropdown(item.id),
1571
- style: linkStyle,
1572
- "aria-expanded": isOpen,
1573
- "aria-haspopup": "true",
1574
- className: `${visibilityClass} items-center gap-1 whitespace-nowrap`,
1575
- children: [
1576
- label,
1577
- /* @__PURE__ */ jsx(ChevronIcon, { isOpen, size: 16 })
1578
- ]
1579
- }
1580
- );
1581
- }
1582
- if (item.type === "markdown") {
1583
- const config = item.config;
1584
- const content = getLocalizedString(config.content, site);
1585
- const html = parseMarkdownToHTML(content);
1586
- const textStyle = {};
1587
- if (config.color) {
1588
- if (typeof config.color === "string") {
1589
- textStyle.color = config.color;
1590
- } else if (config.color.type === "custom" && config.color.value) {
1591
- textStyle.color = typeof config.color.value === "string" ? config.color.value : config.color.value.background;
1592
- } else if (config.color.type === "variable" && config.color.value) {
1593
- textStyle.color = `var(${config.color.value})`;
1594
- } else if (config.color.type === "theme" && config.color.value) {
1595
- textStyle.color = `var(--${config.color.value})`;
1596
- }
1597
- } else {
1598
- textStyle.color = resolvedColors.text;
1599
- }
1600
- return /* @__PURE__ */ jsx(
1601
- "div",
1602
- {
1603
- dangerouslySetInnerHTML: { __html: html },
1604
- className: `${visibilityClass} items-center whitespace-nowrap [&_*]:text-inherit`,
1605
- style: textStyle
1606
- }
1607
- );
1608
- }
1609
- if (item.type === "image") {
1610
- const config = item.config;
1611
- if (!config.src) return null;
1612
- const imgElement = /* @__PURE__ */ jsx(
1613
- "img",
1614
- {
1615
- src: config.src,
1616
- alt: config.alt || "",
1617
- style: {
1618
- display: "block",
1619
- width: config.width || "auto",
1620
- height: config.height || "auto",
1621
- objectFit: config.objectFit || "contain"
1622
- }
1623
- }
1624
- );
1625
- const wrapped = config.href ? /* @__PURE__ */ jsx(
1626
- Link,
1627
- {
1628
- href: config.href,
1629
- target: config.external ? "_blank" : void 0,
1630
- rel: config.external ? "noopener noreferrer" : void 0,
1631
- children: imgElement
1632
- }
1633
- ) : imgElement;
1634
- return /* @__PURE__ */ jsx("div", { className: `${visibilityClass} items-center`, children: wrapped });
1635
- }
1636
- return null;
1637
- };
1638
- var NavbarSections = ({
1639
- section,
1640
- navigation,
1641
- resolvedColors,
1642
- itemsShowClass,
1643
- togglerHideClass,
1644
- isTogglerSection,
1645
- site,
1646
- mobileMenuId
1647
- }) => {
1648
- const hasLogo = useMemo(() => {
1649
- return section?.items?.some(
1650
- (item) => item.type === "logo"
1651
- );
1652
- }, [section.items]);
1653
- const sectionStyle = useMemo(() => {
1654
- let flexValue = section.flex;
1655
- if (flexValue === "0" || flexValue === void 0) {
1656
- if (hasLogo) {
1657
- flexValue = "0 0 auto";
1658
- } else {
1659
- flexValue = "0 1 auto";
1660
- }
1661
- }
1662
- return {
1663
- flex: flexValue,
1664
- justifyContent: section.justify || "flex-start",
1665
- alignItems: section.align || "center",
1666
- gap: section.gap || "0",
1667
- // For non-logo sections, ensure they can shrink below content width
1668
- ...!hasLogo ? { minWidth: 0 } : {}
1669
- };
1670
- }, [section, hasLogo]);
1671
- const shouldHide = useMemo(() => {
1672
- if (!section.hideWhenEmpty) return false;
1673
- const hasLogo2 = section.items?.some(
1674
- (item) => item.type === "logo"
1675
- );
1676
- if (hasLogo2) return false;
1677
- const hasAlwaysVisibleItems = section.items?.some(
1678
- (item) => resolveItemVisibility(item) === "navbar-only" || resolveItemVisibility(item) === "both"
1679
- );
1680
- if (hasAlwaysVisibleItems) return false;
1681
- const collapsibleItems = section.items?.filter(
1682
- (item) => item.type !== "logo" && resolveItemVisibility(item) !== "navbar-only" && resolveItemVisibility(item) !== "both"
1683
- );
1684
- if (collapsibleItems && collapsibleItems.length > 0) return false;
1685
- if (isTogglerSection) return false;
1686
- return true;
1687
- }, [section.hideWhenEmpty, section.items, isTogglerSection]);
1688
- const sectionVisibilityClass = useMemo(() => {
1689
- if (!section.hideWhenEmpty) return "";
1690
- const alwaysVisibleItems = section.items?.filter(
1691
- (item) => item.type === "logo" || resolveItemVisibility(item) === "navbar-only" || resolveItemVisibility(item) === "both"
1692
- );
1693
- if (alwaysVisibleItems && alwaysVisibleItems.length > 0) return "";
1694
- return itemsShowClass;
1695
- }, [section.hideWhenEmpty, section.items, itemsShowClass]);
1696
- if (shouldHide) {
1697
- return null;
1698
- }
1699
- return /* @__PURE__ */ jsxs(
1700
- "div",
1701
- {
1702
- className: `flex flex-row ${sectionVisibilityClass}`,
1703
- style: sectionStyle,
1704
- "data-section-id": section.id,
1705
- children: [
1706
- section.items?.map((item) => {
1707
- return /* @__PURE__ */ jsx(
1708
- NavigationItem,
1709
- {
1710
- item,
1711
- navigation,
1712
- resolvedColors,
1713
- itemsShowClass,
1714
- site
1715
- },
1716
- item.id
1717
- );
1718
- }),
1719
- isTogglerSection && navigation && mobileMenuId && /* @__PURE__ */ jsx("div", { className: `flex flex-shrink-0 ${togglerHideClass}`, children: /* @__PURE__ */ jsx(
1720
- MobileMenuToggle,
1721
- {
1722
- navigation,
1723
- resolvedColors,
1724
- toggleId: `toggler-${section.id}`,
1725
- mobileMenuId
1726
- }
1727
- ) })
1728
- ]
1729
- }
1730
- );
1731
- };
1732
- function Navbar({
1733
- id,
1734
- className,
1735
- headerStyles,
1736
- sortedSections,
1737
- navigation,
1738
- resolvedColors,
1739
- itemsShowClass,
1740
- togglerHideClass,
1741
- togglerSectionId,
1742
- site,
1743
- mobileMenuId,
1744
- containerContent = false,
1745
- isSameLayer = false
1746
- }) {
1747
- const dropdownLayer = navigation.style?.dropdown?.layer || "below";
1748
- function getNavbarZ() {
1749
- if (isSameLayer) return "";
1750
- return dropdownLayer === "above" ? "z-[1]" : "z-[9999]";
1751
- }
1752
- const navbarZ = getNavbarZ();
1753
- const sectionsContent = sortedSections.map((section) => /* @__PURE__ */ jsx(
1754
- NavbarSections,
1755
- {
1756
- section,
1757
- site,
1758
- navigation,
1759
- resolvedColors,
1760
- itemsShowClass,
1761
- togglerHideClass,
1762
- isTogglerSection: section.id === togglerSectionId,
1763
- mobileMenuId
1764
- },
1765
- section.id
1766
- ));
1767
- return /* @__PURE__ */ jsx(
1768
- "div",
1769
- {
1770
- className: cn(
1771
- `navbar-${id}`,
1772
- `relative flex items-center justify-between`,
1773
- navbarZ,
1774
- !containerContent && `navbar-inner-${id}`,
1775
- className
1776
- ),
1777
- style: isSameLayer ? void 0 : headerStyles,
1778
- children: containerContent ? /* @__PURE__ */ jsx(
1779
- "div",
1780
- {
1781
- className: cn(
1782
- "container mx-auto flex items-center justify-between w-full",
1783
- `navbar-inner-${id}`
1784
- ),
1785
- children: sectionsContent
1786
- }
1787
- ) : sectionsContent
1788
- }
1789
- );
1790
- }
1791
- var SHOW_CLASSES = {
1792
- sm: "hidden sm:flex",
1793
- md: "hidden md:flex",
1794
- lg: "hidden lg:flex",
1795
- xl: "hidden xl:flex",
1796
- "2xl": "hidden 2xl:flex"
1797
- };
1798
- var HIDE_CLASSES = {
1799
- sm: "sm:hidden",
1800
- md: "md:hidden",
1801
- lg: "lg:hidden",
1802
- xl: "xl:hidden",
1803
- "2xl": "2xl:hidden"
1804
- };
1805
- var Header = ({
1806
- navigation,
1807
- site = {
1808
- default_locale: "en",
1809
- supported_locales: ["en"]
1810
- },
1811
- className = "",
1812
- siteName: _siteName = "Logo",
1813
- id = "default"
1814
- }) => {
1815
- const isFixed = navigation.style?.position === "fixed";
1816
- const containerBehavior = navigation.style?.container || "edged";
1817
- const safeZone = navigation.style?.safeZone;
1818
- const safeZoneHeight = typeof safeZone === "object" && "base" in safeZone ? safeZone.base : safeZone || "0";
1819
- const estimatedWidth = calculateNavigationWidth(
1820
- navigation.sections || [],
1821
- site
1822
- );
1823
- const breakpoint = getBreakpointForWidth(estimatedWidth);
1824
- const styleType = navigation.style?.type || "default";
1825
- const showClass = breakpoint ? SHOW_CLASSES[breakpoint] : "";
1826
- const hideClass = breakpoint ? HIDE_CLASSES[breakpoint] : "";
1827
- const resolvedColors = navigation.style ? {
1828
- ...resolveColorsToCSS(
1829
- Object.fromEntries(
1830
- Object.entries(navigation.style).filter(
1831
- ([key]) => key !== "type" && key !== "position" && key !== "container" && key !== "safeZone" && key !== "layout" && key !== "border" && key !== "shadow" && key !== "link" && key !== "burger" && key !== "dropdown" && key !== "background" && key !== "text"
1832
- )
1833
- )
1834
- ),
1835
- // Manually resolve background and text colors
1836
- background: resolveColorToCSS(navigation.style.background),
1837
- text: resolveColorToCSS(navigation.style.text),
1838
- // Manually resolve link colors
1839
- linkColor: resolveColorToCSS(navigation.style.link?.color),
1840
- linkHoverColor: resolveColorToCSS(navigation.style.link?.hoverColor),
1841
- // Manually resolve burger colors
1842
- burgerButtonBackground: resolveColorToCSS(
1843
- navigation.style.burger?.button?.background
1844
- ),
1845
- burgerButtonBackgroundHover: resolveColorToCSS(
1846
- navigation.style.burger?.button?.backgroundHover
1847
- ),
1848
- burgerIconColor: resolveColorToCSS(
1849
- navigation.style.burger?.icon?.color
1850
- ),
1851
- burgerIconHover: resolveColorToCSS(
1852
- navigation.style.burger?.icon?.hoverColor
1853
- )
1854
- } : {};
1855
- const headerStyles = {
1856
- ...resolvedColors.background && {
1857
- backgroundColor: resolvedColors.background
1858
- },
1859
- ...resolvedColors.text && {
1860
- color: resolvedColors.text
1861
- }
1862
- };
1863
- const linkStyle = {
1864
- ...resolvedColors.linkColor && { color: resolvedColors.linkColor }
1865
- };
1866
- const marginValue = typeof navigation.style?.layout?.margin === "object" && "base" in navigation.style.layout.margin ? navigation.style.layout.margin.base : navigation.style?.layout?.margin || "0";
1867
- const sortedSections = [...navigation.sections || []].sort(
1868
- (a, b) => a.order - b.order
1869
- );
1870
- let togglerSectionId = navigation.togglerSectionId;
1871
- if (togglerSectionId === "none") {
1872
- togglerSectionId = "";
1873
- } else if (!togglerSectionId) {
1874
- const hasContent = sortedSections.some(
1875
- (section) => section.items?.some((item) => item.type !== "logo")
1876
- );
1877
- if (hasContent) {
1878
- const nonLogoSections = sortedSections.filter(
1879
- (section) => !section.items?.some(
1880
- (item) => item.type === "logo"
1881
- )
1882
- );
1883
- if (nonLogoSections.length > 0) {
1884
- togglerSectionId = nonLogoSections[nonLogoSections.length - 1].id;
1885
- }
1886
- }
1887
- }
1888
- const dropdownItems = [];
1889
- sortedSections.forEach((section) => {
1890
- section.items?.forEach((item) => {
1891
- if (item.type === "dropdown") {
1892
- dropdownItems.push({
1893
- item,
1894
- config: item.config || {}
1895
- });
1896
- }
1897
- });
1898
- });
1899
- const dropdownIds = [
1900
- `mobile-menu-${id}`,
1901
- ...(dropdownItems || []).map((d) => d.item.id)
1902
- ];
1903
- const styles = generateNavigationCSS(
1904
- id,
1905
- navigation,
1906
- resolvedColors,
1907
- dropdownIds
1908
- );
1909
- const isSameLayer = navigation.style?.dropdown?.layer === "same";
1910
- if (styleType === "minimal") {
1911
- const navbarAndDropdowns = /* @__PURE__ */ jsxs(Fragment, { children: [
1912
- /* @__PURE__ */ jsx(
1913
- Navbar,
1914
- {
1915
- id,
1916
- className,
1917
- headerStyles: isSameLayer ? {} : headerStyles,
1918
- sortedSections,
1919
- navigation,
1920
- resolvedColors,
1921
- togglerSectionId: togglerSectionId || "navbar",
1922
- itemsShowClass: "hidden",
1923
- togglerHideClass: "",
1924
- site,
1925
- mobileMenuId: `mobile-menu-${id}`,
1926
- containerContent: containerBehavior === "edged",
1927
- isSameLayer
1928
- }
1929
- ),
1930
- /* @__PURE__ */ jsx(
1931
- NavigationDropdown,
1932
- {
1933
- itemId: `mobile-menu-${id}`,
1934
- config: { content: sectionsToDropdownContent(sortedSections) },
1935
- navigation,
1936
- resolvedColors,
1937
- styles: headerStyles,
1938
- linkStyle,
1939
- dropdownId: `mobile-menu-${id}`,
1940
- site,
1941
- containerContent: containerBehavior === "edged",
1942
- isSameLayer
1943
- }
1944
- ),
1945
- dropdownItems?.map(({ item, config }) => /* @__PURE__ */ jsx(
1946
- NavigationDropdown,
1947
- {
1948
- itemId: item.id,
1949
- config,
1950
- navigation,
1951
- resolvedColors,
1952
- styles: headerStyles,
1953
- linkStyle,
1954
- dropdownId: item.id,
1955
- site,
1956
- containerContent: containerBehavior === "edged",
1957
- isSameLayer
1958
- },
1959
- item.id
1960
- ))
1961
- ] });
1962
- const navbarContent2 = isSameLayer ? /* @__PURE__ */ jsx("div", { className: `navbar-wrapper-${id}`, style: headerStyles, children: navbarAndDropdowns }) : navbarAndDropdowns;
1963
- const navbarWithContainer2 = containerBehavior === "boxed" ? /* @__PURE__ */ jsx("div", { className: "container mx-auto", children: navbarContent2 }) : navbarContent2;
1964
- const headerContent2 = /* @__PURE__ */ jsx(
1965
- NavigationHeaderWrapper,
1966
- {
1967
- className: cn(
1968
- "relative",
1969
- isFixed ? "fixed top-0 left-0 right-0 z-50" : "absolute top-0 left-0 right-0 z-50"
1970
- ),
1971
- style: { margin: marginValue },
1972
- "data-container": containerBehavior,
1973
- children: navbarWithContainer2
1974
- }
1975
- );
1976
- return /* @__PURE__ */ jsxs(Fragment, { children: [
1977
- styles && /* @__PURE__ */ jsx("style", { children: styles }),
1978
- /* @__PURE__ */ jsxs(NavigationProvider, { children: [
1979
- headerContent2,
1980
- safeZoneHeight && safeZoneHeight !== "0" && /* @__PURE__ */ jsx(
1981
- "div",
1982
- {
1983
- className: "header-safe-zone bg-surface",
1984
- style: { height: safeZoneHeight },
1985
- "aria-hidden": "true"
1986
- }
1987
- )
1988
- ] })
1989
- ] });
1990
- }
1991
- const defaultNavbarAndDropdowns = /* @__PURE__ */ jsxs(Fragment, { children: [
1992
- /* @__PURE__ */ jsx(
1993
- Navbar,
1994
- {
1995
- id,
1996
- className,
1997
- headerStyles: isSameLayer ? {} : headerStyles,
1998
- sortedSections,
1999
- navigation,
2000
- resolvedColors,
2001
- togglerSectionId: togglerSectionId || "navbar",
2002
- itemsShowClass: showClass,
2003
- togglerHideClass: hideClass,
2004
- site,
2005
- mobileMenuId: `mobile-menu-${id}`,
2006
- containerContent: containerBehavior === "edged",
2007
- isSameLayer
2008
- }
2009
- ),
2010
- /* @__PURE__ */ jsx(
2011
- NavigationDropdown,
2012
- {
2013
- itemId: `mobile-menu-${id}`,
2014
- config: { content: sectionsToDropdownContent(sortedSections) },
2015
- navigation,
2016
- resolvedColors,
2017
- styles: headerStyles,
2018
- linkStyle,
2019
- dropdownId: `mobile-menu-${id}`,
2020
- site,
2021
- containerContent: containerBehavior === "edged",
2022
- isSameLayer
2023
- }
2024
- ),
2025
- dropdownItems?.map(
2026
- ({
2027
- item,
2028
- config
2029
- }) => /* @__PURE__ */ jsx(
2030
- NavigationDropdown,
2031
- {
2032
- config,
2033
- itemId: item.id,
2034
- navigation,
2035
- resolvedColors,
2036
- styles: headerStyles,
2037
- linkStyle,
2038
- dropdownId: item.id,
2039
- site,
2040
- containerContent: containerBehavior === "edged",
2041
- isSameLayer
2042
- },
2043
- item.id
2044
- )
2045
- )
2046
- ] });
2047
- const navbarContent = isSameLayer ? /* @__PURE__ */ jsx("div", { className: `navbar-wrapper-${id}`, style: headerStyles, children: defaultNavbarAndDropdowns }) : defaultNavbarAndDropdowns;
2048
- const navbarWithContainer = containerBehavior === "boxed" ? /* @__PURE__ */ jsx("div", { className: "container mx-auto", children: navbarContent }) : navbarContent;
2049
- const headerContent = /* @__PURE__ */ jsx(
2050
- NavigationHeaderWrapper,
2051
- {
2052
- className: cn(
2053
- "relative",
2054
- isFixed ? "fixed top-0 left-0 right-0 z-50" : "absolute top-0 left-0 right-0 z-50"
2055
- ),
2056
- style: { margin: marginValue },
2057
- "data-container": containerBehavior,
2058
- children: navbarWithContainer
2059
- }
2060
- );
2061
- return /* @__PURE__ */ jsxs(Fragment, { children: [
2062
- styles && /* @__PURE__ */ jsx("style", { children: styles }),
2063
- /* @__PURE__ */ jsxs(NavigationProvider, { children: [
2064
- headerContent,
2065
- safeZoneHeight && safeZoneHeight !== "0" && /* @__PURE__ */ jsx(
2066
- "div",
2067
- {
2068
- className: "header-safe-zone bg-surface",
2069
- style: { height: safeZoneHeight },
2070
- "aria-hidden": "true"
2071
- }
2072
- )
2073
- ] })
2074
- ] });
2075
- };
2076
-
2077
- export { ChevronIcon, GridIcon, HamburgerIcon, Header, KebabIcon, MeatballsIcon, PlusIcon, ToggleIcon, toggleIconMap };
2078
- //# sourceMappingURL=index.js.map
2079
21
  //# sourceMappingURL=index.js.map