@schukai/monster 4.43.10 → 4.43.12
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.
- package/CHANGELOG.md +16 -0
- package/package.json +1 -1
- package/source/components/form/password.mjs +140 -140
- package/source/components/navigation/site-navigation.mjs +487 -487
- package/source/components/navigation/style/site-navigation.pcss +2 -0
- package/source/components/navigation/stylesheet/site-navigation.mjs +14 -7
- package/source/components/navigation/stylesheet/wizard-navigation.mjs +13 -6
- package/source/components/navigation/wizard-navigation.mjs +391 -391
|
@@ -13,20 +13,20 @@
|
|
|
13
13
|
*/
|
|
14
14
|
|
|
15
15
|
import {
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
16
|
+
CustomElement,
|
|
17
|
+
getSlottedElements,
|
|
18
|
+
registerCustomElement,
|
|
19
|
+
assembleMethodSymbol,
|
|
20
20
|
} from "../../dom/customelement.mjs";
|
|
21
21
|
import { DeadMansSwitch } from "../../util/deadmansswitch.mjs";
|
|
22
22
|
import { SiteNavigationStyleSheet } from "./stylesheet/site-navigation.mjs";
|
|
23
23
|
import {
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
24
|
+
computePosition,
|
|
25
|
+
autoUpdate,
|
|
26
|
+
flip,
|
|
27
|
+
shift,
|
|
28
|
+
offset,
|
|
29
|
+
size,
|
|
30
30
|
} from "@floating-ui/dom";
|
|
31
31
|
import { fireCustomEvent } from "../../dom/events.mjs";
|
|
32
32
|
|
|
@@ -64,59 +64,59 @@ const hamburgerCloseButtonSymbol = Symbol("hamburgerCloseButton");
|
|
|
64
64
|
* @fires monster-submenu-hide - Fired when a submenu is hidden. The event detail contains `{context, trigger, submenu, level}`.
|
|
65
65
|
*/
|
|
66
66
|
class SiteNavigation extends CustomElement {
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
67
|
+
static get [instanceSymbol]() {
|
|
68
|
+
return Symbol.for("@schukai/monster/components/navigation/site@@instance");
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
/**
|
|
72
|
+
* Configuration options for the SiteNavigation component.
|
|
73
|
+
* @see {@link https://monsterjs.org/en/doc/#configurate-a-monster-control}
|
|
74
|
+
*
|
|
75
|
+
* To set these options via an HTML tag, use the `data-monster-options` attribute.
|
|
76
|
+
* The individual configuration values are detailed in the table below.
|
|
77
|
+
*
|
|
78
|
+
* @property {Object} templates - Template definitions.
|
|
79
|
+
* @property {string} templates.main - The main HTML template for the component.
|
|
80
|
+
* @property {string} interactionModel="auto" - Defines the interaction with submenus. Possible values: `auto`, `click`, `hover`. With `auto`, `hover` is used on desktop and `click` is used in the hamburger menu.
|
|
81
|
+
* @property {Object} features - Container for additional feature flags.
|
|
82
|
+
* @property {boolean} features.resetOnClose=true - If `true`, all open submenus within the hamburger menu will be reset when it is closed.
|
|
83
|
+
*/
|
|
84
|
+
get defaults() {
|
|
85
|
+
return Object.assign({}, super.defaults, {
|
|
86
|
+
templates: { main: getTemplate() },
|
|
87
|
+
interactionModel: "auto", // 'auto', 'click', 'hover'
|
|
88
|
+
features: {
|
|
89
|
+
resetOnClose: true,
|
|
90
|
+
},
|
|
91
|
+
});
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
[assembleMethodSymbol]() {
|
|
95
|
+
super[assembleMethodSymbol]();
|
|
96
|
+
initControlReferences.call(this);
|
|
97
|
+
initEventHandler.call(this);
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
static getCSSStyleSheet() {
|
|
101
|
+
return [SiteNavigationStyleSheet];
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
static getTag() {
|
|
105
|
+
return "monster-site-navigation";
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
connectedCallback() {
|
|
109
|
+
super.connectedCallback();
|
|
110
|
+
attachResizeObserver.call(this);
|
|
111
|
+
requestAnimationFrame(() => {
|
|
112
|
+
populateTabs.call(this);
|
|
113
|
+
});
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
disconnectedCallback() {
|
|
117
|
+
super.disconnectedCallback();
|
|
118
|
+
detachResizeObserver.call(this);
|
|
119
|
+
}
|
|
120
120
|
}
|
|
121
121
|
|
|
122
122
|
/**
|
|
@@ -125,22 +125,22 @@ class SiteNavigation extends CustomElement {
|
|
|
125
125
|
* @this {SiteNavigation}
|
|
126
126
|
*/
|
|
127
127
|
function initControlReferences() {
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
128
|
+
if (!this.shadowRoot) throw new Error("Component requires a shadowRoot.");
|
|
129
|
+
this[navElementSymbol] = this.shadowRoot.querySelector(
|
|
130
|
+
'[data-monster-role="navigation"]',
|
|
131
|
+
);
|
|
132
|
+
this[visibleElementsSymbol] =
|
|
133
|
+
this.shadowRoot.querySelector("#visible-elements");
|
|
134
|
+
this[hiddenElementsSymbol] =
|
|
135
|
+
this.shadowRoot.querySelector("#hidden-elements");
|
|
136
|
+
this[hamburgerButtonSymbol] =
|
|
137
|
+
this.shadowRoot.querySelector("#hamburger-button");
|
|
138
|
+
this[hamburgerNavSymbol] = this.shadowRoot.querySelector(
|
|
139
|
+
'[data-monster-role="hamburger-nav"]',
|
|
140
|
+
);
|
|
141
|
+
this[hamburgerCloseButtonSymbol] = this.shadowRoot.querySelector(
|
|
142
|
+
'[part="hamburger-close-button"]',
|
|
143
|
+
);
|
|
144
144
|
}
|
|
145
145
|
|
|
146
146
|
/**
|
|
@@ -149,120 +149,120 @@ function initControlReferences() {
|
|
|
149
149
|
* @this {SiteNavigation}
|
|
150
150
|
*/
|
|
151
151
|
function initEventHandler() {
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
152
|
+
if (!this.shadowRoot) throw new Error("Component requires a shadowRoot.");
|
|
153
|
+
|
|
154
|
+
const hamburgerButton = this[hamburgerButtonSymbol];
|
|
155
|
+
const hamburgerNav = this[hamburgerNavSymbol];
|
|
156
|
+
const hamburgerCloseButton = this[hamburgerCloseButtonSymbol];
|
|
157
|
+
let cleanup;
|
|
158
|
+
|
|
159
|
+
if (!hamburgerButton || !hamburgerNav || !hamburgerCloseButton) return;
|
|
160
|
+
|
|
161
|
+
const getBestPositionStrategy = (element) => {
|
|
162
|
+
let parent = element.parentElement;
|
|
163
|
+
while (parent) {
|
|
164
|
+
const parentPosition = window.getComputedStyle(parent).position;
|
|
165
|
+
if (["fixed", "sticky"].includes(parentPosition)) {
|
|
166
|
+
return "fixed";
|
|
167
|
+
}
|
|
168
|
+
parent = parent.parentElement;
|
|
169
|
+
}
|
|
170
|
+
return "absolute";
|
|
171
|
+
};
|
|
172
|
+
|
|
173
|
+
const handleOutsideClick = (event) => {
|
|
174
|
+
if (
|
|
175
|
+
!hamburgerButton.contains(event.target) &&
|
|
176
|
+
!hamburgerNav.contains(event.target)
|
|
177
|
+
) {
|
|
178
|
+
hideMenu();
|
|
179
|
+
}
|
|
180
|
+
};
|
|
181
|
+
|
|
182
|
+
const hideMenu = () => {
|
|
183
|
+
hamburgerNav.style.display = "none";
|
|
184
|
+
document.body.classList.remove("monster-navigation-open");
|
|
185
|
+
|
|
186
|
+
fireCustomEvent(this, "monster-hamburger-hide", {
|
|
187
|
+
button: hamburgerButton,
|
|
188
|
+
menu: hamburgerNav,
|
|
189
|
+
});
|
|
190
|
+
|
|
191
|
+
if (this.getOption("features.resetOnClose") === true) {
|
|
192
|
+
this[hiddenElementsSymbol]
|
|
193
|
+
.querySelectorAll(".is-open")
|
|
194
|
+
.forEach((submenu) => submenu.classList.remove("is-open"));
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
if (cleanup) {
|
|
198
|
+
cleanup();
|
|
199
|
+
cleanup = undefined;
|
|
200
|
+
}
|
|
201
|
+
document.removeEventListener("click", handleOutsideClick);
|
|
202
|
+
};
|
|
203
|
+
|
|
204
|
+
this[hideHamburgerMenuSymbol] = hideMenu;
|
|
205
|
+
|
|
206
|
+
const showMenu = () => {
|
|
207
|
+
this[activeSubmenuHiderSymbol]?.();
|
|
208
|
+
hamburgerNav.style.display = "block";
|
|
209
|
+
document.body.classList.add("monster-navigation-open");
|
|
210
|
+
|
|
211
|
+
fireCustomEvent(this, "monster-hamburger-show", {
|
|
212
|
+
button: hamburgerButton,
|
|
213
|
+
menu: hamburgerNav,
|
|
214
|
+
});
|
|
215
|
+
|
|
216
|
+
cleanup = autoUpdate(hamburgerButton, hamburgerNav, () => {
|
|
217
|
+
if (window.innerWidth > 768) {
|
|
218
|
+
const strategy = getBestPositionStrategy(this);
|
|
219
|
+
|
|
220
|
+
computePosition(hamburgerButton, hamburgerNav, {
|
|
221
|
+
placement: "bottom-end",
|
|
222
|
+
strategy: strategy,
|
|
223
|
+
middleware: [
|
|
224
|
+
offset(8),
|
|
225
|
+
flip(),
|
|
226
|
+
shift({ padding: 8 }),
|
|
227
|
+
size({
|
|
228
|
+
apply: ({ availableHeight, elements }) => {
|
|
229
|
+
Object.assign(elements.floating.style, {
|
|
230
|
+
maxHeight: `${availableHeight}px`,
|
|
231
|
+
overflowY: "auto",
|
|
232
|
+
});
|
|
233
|
+
},
|
|
234
|
+
padding: 8,
|
|
235
|
+
}),
|
|
236
|
+
],
|
|
237
|
+
}).then(({ x, y, strategy }) => {
|
|
238
|
+
Object.assign(hamburgerNav.style, {
|
|
239
|
+
position: strategy,
|
|
240
|
+
left: `${x}px`,
|
|
241
|
+
top: `${y}px`,
|
|
242
|
+
});
|
|
243
|
+
});
|
|
244
|
+
} else {
|
|
245
|
+
// Mobile view (fullscreen overlay), position is handled by CSS
|
|
246
|
+
Object.assign(hamburgerNav.style, { position: "", left: "", top: "" });
|
|
247
|
+
}
|
|
248
|
+
});
|
|
249
|
+
setTimeout(() => document.addEventListener("click", handleOutsideClick), 0);
|
|
250
|
+
};
|
|
251
|
+
|
|
252
|
+
hamburgerButton.addEventListener("click", (event) => {
|
|
253
|
+
event.stopPropagation();
|
|
254
|
+
const isVisible = hamburgerNav.style.display === "block";
|
|
255
|
+
if (isVisible) {
|
|
256
|
+
hideMenu();
|
|
257
|
+
} else {
|
|
258
|
+
showMenu();
|
|
259
|
+
}
|
|
260
|
+
});
|
|
261
|
+
|
|
262
|
+
hamburgerCloseButton.addEventListener("click", (event) => {
|
|
263
|
+
event.stopPropagation();
|
|
264
|
+
hideMenu();
|
|
265
|
+
});
|
|
266
266
|
}
|
|
267
267
|
|
|
268
268
|
/**
|
|
@@ -272,22 +272,22 @@ function initEventHandler() {
|
|
|
272
272
|
* @this {SiteNavigation}
|
|
273
273
|
*/
|
|
274
274
|
function attachResizeObserver() {
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
275
|
+
this[resizeObserverSymbol] = new ResizeObserver(() => {
|
|
276
|
+
if (this[timerCallbackSymbol] instanceof DeadMansSwitch) {
|
|
277
|
+
try {
|
|
278
|
+
this[timerCallbackSymbol].touch();
|
|
279
|
+
return;
|
|
280
|
+
} catch (e) {
|
|
281
|
+
delete this[timerCallbackSymbol];
|
|
282
|
+
}
|
|
283
|
+
}
|
|
284
|
+
this[timerCallbackSymbol] = new DeadMansSwitch(200, () => {
|
|
285
|
+
requestAnimationFrame(() => {
|
|
286
|
+
populateTabs.call(this);
|
|
287
|
+
});
|
|
288
|
+
});
|
|
289
|
+
});
|
|
290
|
+
this[resizeObserverSymbol].observe(this);
|
|
291
291
|
}
|
|
292
292
|
|
|
293
293
|
/**
|
|
@@ -296,10 +296,10 @@ function attachResizeObserver() {
|
|
|
296
296
|
* @this {SiteNavigation}
|
|
297
297
|
*/
|
|
298
298
|
function detachResizeObserver() {
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
299
|
+
if (this[resizeObserverSymbol] instanceof ResizeObserver) {
|
|
300
|
+
this[resizeObserverSymbol].disconnect();
|
|
301
|
+
delete this[resizeObserverSymbol];
|
|
302
|
+
}
|
|
303
303
|
}
|
|
304
304
|
|
|
305
305
|
/**
|
|
@@ -312,177 +312,177 @@ function detachResizeObserver() {
|
|
|
312
312
|
* @param {number} level The nesting level of the submenu (starts at 1).
|
|
313
313
|
*/
|
|
314
314
|
function setupSubmenu(parentLi, context = "visible", level = 1) {
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
315
|
+
const submenu = parentLi.querySelector(
|
|
316
|
+
":scope > ul, :scope > div[part='mega-menu']",
|
|
317
|
+
);
|
|
318
|
+
if (!submenu) return;
|
|
319
|
+
|
|
320
|
+
if (submenu.tagName === "UL") {
|
|
321
|
+
submenu.setAttribute("part", "submenu");
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
const interaction = this.getOption("interactionModel", "auto");
|
|
325
|
+
const useHover =
|
|
326
|
+
interaction === "hover" ||
|
|
327
|
+
(interaction === "auto" && context === "visible");
|
|
328
|
+
|
|
329
|
+
if (useHover) {
|
|
330
|
+
const component = this;
|
|
331
|
+
let cleanup;
|
|
332
|
+
let hideTimeout;
|
|
333
|
+
let isHovering = false;
|
|
334
|
+
|
|
335
|
+
const immediateHide = () => {
|
|
336
|
+
submenu.style.display = "none";
|
|
337
|
+
Object.assign(submenu.style, {
|
|
338
|
+
maxHeight: "",
|
|
339
|
+
overflowY: "",
|
|
340
|
+
});
|
|
341
|
+
submenu
|
|
342
|
+
.querySelectorAll(
|
|
343
|
+
"ul[style*='display: block'], div[part='mega-menu'][style*='display: block']",
|
|
344
|
+
)
|
|
345
|
+
.forEach((sub) => {
|
|
346
|
+
sub.style.display = "none";
|
|
347
|
+
});
|
|
348
|
+
fireCustomEvent(this, "monster-submenu-hide", {
|
|
349
|
+
context,
|
|
350
|
+
trigger: parentLi,
|
|
351
|
+
submenu,
|
|
352
|
+
level,
|
|
353
|
+
});
|
|
354
|
+
if (cleanup) {
|
|
355
|
+
cleanup();
|
|
356
|
+
cleanup = null;
|
|
357
|
+
}
|
|
358
|
+
if (
|
|
359
|
+
level === 1 &&
|
|
360
|
+
component[activeSubmenuHiderSymbol] === immediateHide
|
|
361
|
+
) {
|
|
362
|
+
component[activeSubmenuHiderSymbol] = null;
|
|
363
|
+
}
|
|
364
|
+
};
|
|
365
|
+
|
|
366
|
+
const show = () => {
|
|
367
|
+
component[hideHamburgerMenuSymbol]?.();
|
|
368
|
+
if (level === 1) {
|
|
369
|
+
if (
|
|
370
|
+
component[activeSubmenuHiderSymbol] &&
|
|
371
|
+
component[activeSubmenuHiderSymbol] !== immediateHide
|
|
372
|
+
) {
|
|
373
|
+
component[activeSubmenuHiderSymbol]();
|
|
374
|
+
}
|
|
375
|
+
component[activeSubmenuHiderSymbol] = immediateHide;
|
|
376
|
+
} else {
|
|
377
|
+
[...parentLi.parentElement.children]
|
|
378
|
+
.filter((li) => li !== parentLi)
|
|
379
|
+
.forEach((sibling) => {
|
|
380
|
+
const siblingSubmenu = sibling.querySelector(
|
|
381
|
+
":scope > ul, :scope > div[part='mega-menu']",
|
|
382
|
+
);
|
|
383
|
+
if (siblingSubmenu) {
|
|
384
|
+
siblingSubmenu.style.display = "none";
|
|
385
|
+
}
|
|
386
|
+
});
|
|
387
|
+
}
|
|
388
|
+
submenu.style.display = "block";
|
|
389
|
+
fireCustomEvent(this, "monster-submenu-show", {
|
|
390
|
+
context,
|
|
391
|
+
trigger: parentLi,
|
|
392
|
+
submenu,
|
|
393
|
+
level,
|
|
394
|
+
});
|
|
395
|
+
if (!cleanup) {
|
|
396
|
+
cleanup = autoUpdate(parentLi, submenu, () => {
|
|
397
|
+
const middleware = [offset(8), flip(), shift({ padding: 8 })];
|
|
398
|
+
const containsSubmenus = submenu.querySelector(
|
|
399
|
+
"ul, div[part='mega-menu']",
|
|
400
|
+
);
|
|
401
|
+
if (!containsSubmenus) {
|
|
402
|
+
middleware.push(
|
|
403
|
+
size({
|
|
404
|
+
apply: ({ availableHeight, elements }) => {
|
|
405
|
+
Object.assign(elements.floating.style, {
|
|
406
|
+
maxHeight: `${availableHeight}px`,
|
|
407
|
+
overflowY: "auto",
|
|
408
|
+
});
|
|
409
|
+
},
|
|
410
|
+
padding: 8,
|
|
411
|
+
}),
|
|
412
|
+
);
|
|
413
|
+
}
|
|
414
|
+
computePosition(parentLi, submenu, {
|
|
415
|
+
placement: level === 1 ? "bottom-start" : "right-start",
|
|
416
|
+
middleware: middleware,
|
|
417
|
+
}).then(({ x, y, strategy }) => {
|
|
418
|
+
Object.assign(submenu.style, {
|
|
419
|
+
position: strategy,
|
|
420
|
+
left: `${x}px`,
|
|
421
|
+
top: `${y}px`,
|
|
422
|
+
});
|
|
423
|
+
});
|
|
424
|
+
});
|
|
425
|
+
}
|
|
426
|
+
};
|
|
427
|
+
|
|
428
|
+
const handleMouseEnter = () => {
|
|
429
|
+
isHovering = true; // Status auf "aktiv" setzen
|
|
430
|
+
clearTimeout(hideTimeout);
|
|
431
|
+
if (submenu.style.display !== "block") {
|
|
432
|
+
show();
|
|
433
|
+
}
|
|
434
|
+
};
|
|
435
|
+
|
|
436
|
+
const handleMouseLeave = () => {
|
|
437
|
+
isHovering = false; // Status auf "inaktiv" setzen
|
|
438
|
+
hideTimeout = setTimeout(() => {
|
|
439
|
+
if (!isHovering) {
|
|
440
|
+
immediateHide();
|
|
441
|
+
}
|
|
442
|
+
}, 250);
|
|
443
|
+
};
|
|
444
|
+
|
|
445
|
+
parentLi.addEventListener("mouseenter", handleMouseEnter);
|
|
446
|
+
parentLi.addEventListener("mouseleave", handleMouseLeave);
|
|
447
|
+
submenu.addEventListener("mouseenter", handleMouseEnter);
|
|
448
|
+
submenu.addEventListener("mouseleave", handleMouseLeave);
|
|
449
|
+
} else {
|
|
450
|
+
const anchor = parentLi.querySelector(":scope > a");
|
|
451
|
+
if (anchor) {
|
|
452
|
+
anchor.addEventListener("click", (event) => {
|
|
453
|
+
event.preventDefault();
|
|
454
|
+
event.stopPropagation();
|
|
455
|
+
if (!submenu.classList.contains("is-open")) {
|
|
456
|
+
[...parentLi.parentElement.children]
|
|
457
|
+
.filter((li) => li !== parentLi)
|
|
458
|
+
.forEach((sibling) => {
|
|
459
|
+
const siblingSubmenu = sibling.querySelector(
|
|
460
|
+
":scope > ul, :scope > div[part='mega-menu']",
|
|
461
|
+
);
|
|
462
|
+
if (siblingSubmenu) {
|
|
463
|
+
siblingSubmenu.classList.remove("is-open");
|
|
464
|
+
}
|
|
465
|
+
});
|
|
466
|
+
}
|
|
467
|
+
const isOpen = submenu.classList.toggle("is-open");
|
|
468
|
+
const eventName = isOpen
|
|
469
|
+
? "monster-submenu-show"
|
|
470
|
+
: "monster-submenu-hide";
|
|
471
|
+
fireCustomEvent(this, eventName, {
|
|
472
|
+
context,
|
|
473
|
+
trigger: parentLi,
|
|
474
|
+
submenu,
|
|
475
|
+
level,
|
|
476
|
+
});
|
|
477
|
+
});
|
|
478
|
+
}
|
|
479
|
+
}
|
|
480
|
+
|
|
481
|
+
if (submenu.tagName === "UL") {
|
|
482
|
+
submenu
|
|
483
|
+
.querySelectorAll(":scope > li")
|
|
484
|
+
.forEach((li) => setupSubmenu.call(this, li, context, level + 1));
|
|
485
|
+
}
|
|
486
486
|
}
|
|
487
487
|
|
|
488
488
|
/**
|
|
@@ -493,20 +493,20 @@ function setupSubmenu(parentLi, context = "visible", level = 1) {
|
|
|
493
493
|
* @returns {HTMLLIElement} The cloned and configured list item.
|
|
494
494
|
*/
|
|
495
495
|
function cloneNavItem(item) {
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
496
|
+
const liClone = item.cloneNode(true);
|
|
497
|
+
const aClone = liClone.querySelector("a");
|
|
498
|
+
let navItemPart = "nav-item";
|
|
499
|
+
let navLinkPart = "nav-link";
|
|
500
500
|
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
501
|
+
if (item.classList.contains("active")) {
|
|
502
|
+
navItemPart += " nav-item-active";
|
|
503
|
+
if (aClone) navLinkPart += " nav-link-active";
|
|
504
|
+
}
|
|
505
505
|
|
|
506
|
-
|
|
507
|
-
|
|
506
|
+
liClone.setAttribute("part", navItemPart);
|
|
507
|
+
if (aClone) aClone.setAttribute("part", navLinkPart);
|
|
508
508
|
|
|
509
|
-
|
|
509
|
+
return liClone;
|
|
510
510
|
}
|
|
511
511
|
|
|
512
512
|
/**
|
|
@@ -516,96 +516,96 @@ function cloneNavItem(item) {
|
|
|
516
516
|
* @this {SiteNavigation}
|
|
517
517
|
*/
|
|
518
518
|
function populateTabs() {
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
519
|
+
const visibleList = this[visibleElementsSymbol];
|
|
520
|
+
const hiddenList = this[hiddenElementsSymbol];
|
|
521
|
+
const hamburgerButton = this[hamburgerButtonSymbol];
|
|
522
|
+
const hamburgerNav = this[hamburgerNavSymbol];
|
|
523
|
+
const topLevelUl = [...getSlottedElements.call(this, "ul")].find(
|
|
524
|
+
(ul) => ul.parentElement === this,
|
|
525
|
+
);
|
|
526
|
+
|
|
527
|
+
if (!topLevelUl) {
|
|
528
|
+
visibleList.style.visibility = "visible";
|
|
529
|
+
hamburgerButton.style.display = "none";
|
|
530
|
+
return;
|
|
531
|
+
}
|
|
532
|
+
|
|
533
|
+
const sourceItems = Array.from(topLevelUl.children).filter(
|
|
534
|
+
(item) => item.tagName === "LI",
|
|
535
|
+
);
|
|
536
|
+
|
|
537
|
+
visibleList.style.visibility = "hidden";
|
|
538
|
+
hamburgerButton.style.display = "none";
|
|
539
|
+
hamburgerNav.style.display = "none";
|
|
540
|
+
visibleList.innerHTML = "";
|
|
541
|
+
hiddenList.innerHTML = "";
|
|
542
|
+
|
|
543
|
+
const originalDisplay = hamburgerButton.style.display;
|
|
544
|
+
hamburgerButton.style.visibility = "hidden";
|
|
545
|
+
hamburgerButton.style.display = "flex";
|
|
546
|
+
const hamburgerWidth = hamburgerButton.offsetWidth;
|
|
547
|
+
hamburgerButton.style.display = originalDisplay;
|
|
548
|
+
hamburgerButton.style.visibility = "visible";
|
|
549
|
+
|
|
550
|
+
const navWidth = this[navElementSymbol].clientWidth;
|
|
551
|
+
if (navWidth === 0) {
|
|
552
|
+
visibleList.style.visibility = "visible";
|
|
553
|
+
return;
|
|
554
|
+
}
|
|
555
|
+
|
|
556
|
+
const measurementList = visibleList.cloneNode(true);
|
|
557
|
+
Object.assign(measurementList.style, {
|
|
558
|
+
position: "absolute",
|
|
559
|
+
left: "0",
|
|
560
|
+
top: "0",
|
|
561
|
+
width: "auto",
|
|
562
|
+
visibility: "hidden",
|
|
563
|
+
});
|
|
564
|
+
this.shadowRoot.appendChild(measurementList);
|
|
565
|
+
|
|
566
|
+
const itemsToMove = [];
|
|
567
|
+
const availableWidthForTabs = navWidth - hamburgerWidth;
|
|
568
|
+
|
|
569
|
+
for (let i = 0; i < sourceItems.length; i++) {
|
|
570
|
+
const item = sourceItems[i];
|
|
571
|
+
const itemClone = item.cloneNode(true);
|
|
572
|
+
const submenu = itemClone.querySelector("ul, div[part='mega-menu']");
|
|
573
|
+
if (submenu) submenu.style.display = "none";
|
|
574
|
+
|
|
575
|
+
measurementList.appendChild(itemClone);
|
|
576
|
+
const isLastItem = i === sourceItems.length - 1;
|
|
577
|
+
const effectiveMaxWidth = isLastItem ? navWidth : availableWidthForTabs;
|
|
578
|
+
|
|
579
|
+
if (measurementList.scrollWidth > effectiveMaxWidth) {
|
|
580
|
+
break;
|
|
581
|
+
} else {
|
|
582
|
+
itemsToMove.push(item);
|
|
583
|
+
}
|
|
584
|
+
}
|
|
585
|
+
this.shadowRoot.removeChild(measurementList);
|
|
586
|
+
|
|
587
|
+
const visibleItems = itemsToMove;
|
|
588
|
+
const hiddenItems = sourceItems.slice(visibleItems.length);
|
|
589
|
+
|
|
590
|
+
if (visibleItems.length > 0) {
|
|
591
|
+
const clonedVisibleItems = visibleItems.map(cloneNavItem);
|
|
592
|
+
visibleList.append(...clonedVisibleItems);
|
|
593
|
+
visibleList
|
|
594
|
+
.querySelectorAll(":scope > li")
|
|
595
|
+
.forEach((li) => setupSubmenu.call(this, li, "visible", 1));
|
|
596
|
+
}
|
|
597
|
+
|
|
598
|
+
if (hiddenItems.length > 0) {
|
|
599
|
+
const clonedHiddenItems = hiddenItems.map(cloneNavItem);
|
|
600
|
+
hiddenList.append(...clonedHiddenItems);
|
|
601
|
+
hamburgerButton.style.display = "flex";
|
|
602
|
+
hiddenList
|
|
603
|
+
.querySelectorAll(":scope > li")
|
|
604
|
+
.forEach((li) => setupSubmenu.call(this, li, "hidden", 1));
|
|
605
|
+
}
|
|
606
|
+
|
|
607
|
+
visibleList.style.visibility = "visible";
|
|
608
|
+
fireCustomEvent(this, "monster-layout-change", { visibleItems, hiddenItems });
|
|
609
609
|
}
|
|
610
610
|
|
|
611
611
|
/**
|
|
@@ -615,7 +615,7 @@ function populateTabs() {
|
|
|
615
615
|
* @returns {string} The combined string.
|
|
616
616
|
*/
|
|
617
617
|
function html(strings) {
|
|
618
|
-
|
|
618
|
+
return strings.join("");
|
|
619
619
|
}
|
|
620
620
|
|
|
621
621
|
/**
|
|
@@ -624,7 +624,7 @@ function html(strings) {
|
|
|
624
624
|
* @returns {string} The HTML template string.
|
|
625
625
|
*/
|
|
626
626
|
function getTemplate() {
|
|
627
|
-
|
|
627
|
+
return html`<div data-monster-role="control" part="control">
|
|
628
628
|
<nav data-monster-role="navigation" role="navigation" part="nav">
|
|
629
629
|
<ul id="visible-elements" part="visible-list"></ul>
|
|
630
630
|
</nav>
|