@schukai/monster 4.43.1 → 4.43.3
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/accessibility/locale-picker.mjs +538 -538
- package/source/components/accessibility/locale-select.mjs +172 -172
- package/source/components/content/viewer.mjs +823 -823
- package/source/components/datatable/constants.mjs +15 -15
- package/source/components/datatable/datatable/header.mjs +253 -253
- package/source/components/datatable/datatable.mjs +1284 -1284
- package/source/components/datatable/filter.mjs +1339 -1342
- package/source/components/datatable/pagination.mjs +502 -502
- package/source/components/datatable/stylesheet/datatable.mjs +13 -6
- package/source/components/form/quantity.mjs +229 -229
- package/source/components/form/select.mjs +2963 -2963
- package/source/components/form/stylesheet/quantity.mjs +13 -6
- package/source/components/form/stylesheet/select.mjs +13 -6
- package/source/components/navigation/site-navigation.mjs +383 -210
- package/source/components/navigation/style/site-navigation.pcss +103 -15
- package/source/components/navigation/stylesheet/site-navigation.mjs +14 -7
- package/source/components/style/typography.css +4 -2
- package/source/dom/customelement.mjs +959 -963
- package/source/dom/slotted.mjs +87 -87
- package/source/i18n/util.mjs +149 -149
- package/source/monster.mjs +3 -0
- package/source/types/is.mjs +64 -64
- package/source/types/typeof.mjs +16 -16
- package/source/types/version.mjs +1 -1
- package/test/cases/monster.mjs +1 -1
- package/test/web/test.html +2 -2
- package/test/web/tests.js +2724 -1287
@@ -12,34 +12,24 @@
|
|
12
12
|
* SPDX-License-Identifier: AGPL-3.0
|
13
13
|
*/
|
14
14
|
|
15
|
-
/**
|
16
|
-
* Copyright © schukai GmbH and all contributing authors, {{copyRightYear}}. All rights reserved.
|
17
|
-
* Node module: @schukai/monster
|
18
|
-
*
|
19
|
-
* This source code is licensed under the GNU Affero General Public License version 3 (AGPLv3).
|
20
|
-
* SPDX-License-Identifier: AGPL-3.0
|
21
|
-
*/
|
22
|
-
|
23
15
|
import {
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
16
|
+
CustomElement,
|
17
|
+
getSlottedElements,
|
18
|
+
registerCustomElement,
|
19
|
+
assembleMethodSymbol,
|
28
20
|
} from "../../dom/customelement.mjs";
|
29
21
|
import { DeadMansSwitch } from "../../util/deadmansswitch.mjs";
|
30
22
|
import { SiteNavigationStyleSheet } from "./stylesheet/site-navigation.mjs";
|
31
|
-
// --- NEW: Import Floating UI ---
|
32
23
|
import {
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
} from "
|
24
|
+
computePosition,
|
25
|
+
autoUpdate,
|
26
|
+
flip,
|
27
|
+
shift,
|
28
|
+
offset,
|
29
|
+
} from "@floating-ui/dom";
|
39
30
|
|
40
31
|
export { SiteNavigation };
|
41
32
|
|
42
|
-
// Symbols for private class members
|
43
33
|
const resizeObserverSymbol = Symbol("resizeObserver");
|
44
34
|
const timerCallbackSymbol = Symbol("timerCallback");
|
45
35
|
const navElementSymbol = Symbol("navElement");
|
@@ -48,223 +38,406 @@ const hiddenElementsSymbol = Symbol("hiddenElements");
|
|
48
38
|
const hamburgerButtonSymbol = Symbol("hamburgerButton");
|
49
39
|
const hamburgerNavSymbol = Symbol("hamburgerNav");
|
50
40
|
const instanceSymbol = Symbol("instanceSymbol");
|
41
|
+
const activeSubmenuHiderSymbol = Symbol("activeSubmenuHider");
|
51
42
|
|
52
43
|
/**
|
53
|
-
*
|
54
|
-
*
|
44
|
+
* Responsive site navigation component.
|
45
|
+
*
|
46
|
+
* @fragments /fragments/components/navigation/site-navigation/
|
47
|
+
*
|
48
|
+
* @example /examples/components/navigation/site-navigation-simple
|
49
|
+
*
|
50
|
+
* @since 4.41.0
|
51
|
+
* @copyright schukai GmbH
|
52
|
+
* @summary Responsive site navigation with hamburger menu and submenus
|
55
53
|
*/
|
56
54
|
class SiteNavigation extends CustomElement {
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
55
|
+
/**
|
56
|
+
* Returns a unique symbol for the instance.
|
57
|
+
* @returns {symbol}
|
58
|
+
*/
|
59
|
+
static get [instanceSymbol]() {
|
60
|
+
return Symbol.for("@schukai/monster/components/navigation/site@@instance");
|
61
|
+
}
|
62
|
+
|
63
|
+
/**
|
64
|
+
* Returns the default options for the component.
|
65
|
+
* @returns {object}
|
66
|
+
*/
|
67
|
+
get defaults() {
|
68
|
+
return Object.assign({}, super.defaults, {
|
69
|
+
templates: { main: getTemplate() },
|
70
|
+
});
|
71
|
+
}
|
72
|
+
|
73
|
+
/**
|
74
|
+
* Assembles the component and initializes controls and event handlers.
|
75
|
+
* @returns {void}
|
76
|
+
*/
|
77
|
+
[assembleMethodSymbol]() {
|
78
|
+
super[assembleMethodSymbol]();
|
79
|
+
initControlReferences.call(this);
|
80
|
+
initEventHandler.call(this);
|
81
|
+
}
|
82
|
+
|
83
|
+
/**
|
84
|
+
* Returns the CSS stylesheet for the component.
|
85
|
+
* @returns {Array<CSSStyleSheet>}
|
86
|
+
*/
|
87
|
+
static getCSSStyleSheet() {
|
88
|
+
return [SiteNavigationStyleSheet];
|
89
|
+
}
|
90
|
+
|
91
|
+
/**
|
92
|
+
* Returns the custom element tag name.
|
93
|
+
* @returns {string}
|
94
|
+
*/
|
95
|
+
static getTag() {
|
96
|
+
return "monster-site-navigation";
|
97
|
+
}
|
98
|
+
|
99
|
+
/**
|
100
|
+
* Called when the component is connected to the DOM.
|
101
|
+
* @returns {void}
|
102
|
+
*/
|
103
|
+
connectedCallback() {
|
104
|
+
super.connectedCallback();
|
105
|
+
attachResizeObserver.call(this);
|
106
|
+
setTimeout(() => populateTabs.call(this), 0);
|
107
|
+
}
|
108
|
+
|
109
|
+
/**
|
110
|
+
* Called when the component is disconnected from the DOM.
|
111
|
+
* @returns {void}
|
112
|
+
*/
|
113
|
+
disconnectedCallback() {
|
114
|
+
super.disconnectedCallback();
|
115
|
+
detachResizeObserver.call(this);
|
116
|
+
}
|
91
117
|
}
|
92
118
|
|
119
|
+
/**
|
120
|
+
* Initializes references to important control elements.
|
121
|
+
* @private
|
122
|
+
* @this {SiteNavigation}
|
123
|
+
* @returns {void}
|
124
|
+
*/
|
93
125
|
function initControlReferences() {
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
126
|
+
if (!this.shadowRoot) throw new Error("Component requires a shadowRoot.");
|
127
|
+
this[navElementSymbol] = this.shadowRoot.querySelector(
|
128
|
+
'[data-monster-role="navigation"]',
|
129
|
+
);
|
130
|
+
this[visibleElementsSymbol] =
|
131
|
+
this.shadowRoot.querySelector("#visible-elements");
|
132
|
+
this[hiddenElementsSymbol] =
|
133
|
+
this.shadowRoot.querySelector("#hidden-elements");
|
134
|
+
this[hamburgerButtonSymbol] =
|
135
|
+
this.shadowRoot.querySelector("#hamburger-button");
|
136
|
+
this[hamburgerNavSymbol] = this.shadowRoot.querySelector(
|
137
|
+
'[data-monster-role="hamburger-nav"]',
|
138
|
+
);
|
107
139
|
}
|
108
140
|
|
141
|
+
/**
|
142
|
+
* Initializes event handlers for hamburger menu and submenu interactions.
|
143
|
+
* @private
|
144
|
+
* @this {SiteNavigation}
|
145
|
+
* @returns {void}
|
146
|
+
*/
|
109
147
|
function initEventHandler() {
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
148
|
+
if (!this.shadowRoot) throw new Error("Component requires a shadowRoot.");
|
149
|
+
|
150
|
+
const hamburgerButton = this[hamburgerButtonSymbol];
|
151
|
+
const hamburgerNav = this[hamburgerNavSymbol];
|
152
|
+
let cleanup;
|
153
|
+
|
154
|
+
if (!hamburgerButton || !hamburgerNav) return;
|
155
|
+
|
156
|
+
const showMenu = () => {
|
157
|
+
hamburgerNav.style.display = "block";
|
158
|
+
cleanup = autoUpdate(hamburgerButton, hamburgerNav, () => {
|
159
|
+
computePosition(hamburgerButton, hamburgerNav, {
|
160
|
+
placement: "bottom-end",
|
161
|
+
middleware: [offset(8), flip(), shift({ padding: 8 })],
|
162
|
+
}).then(({ x, y }) => {
|
163
|
+
Object.assign(hamburgerNav.style, {
|
164
|
+
left: `${x}px`,
|
165
|
+
top: `${y}px`,
|
166
|
+
});
|
167
|
+
});
|
168
|
+
});
|
169
|
+
setTimeout(() => document.addEventListener("click", handleOutsideClick), 0);
|
170
|
+
};
|
171
|
+
|
172
|
+
const hideMenu = () => {
|
173
|
+
hamburgerNav.style.display = "none";
|
174
|
+
if (cleanup) {
|
175
|
+
cleanup();
|
176
|
+
}
|
177
|
+
document.removeEventListener("click", handleOutsideClick);
|
178
|
+
};
|
179
|
+
|
180
|
+
const handleOutsideClick = (event) => {
|
181
|
+
if (
|
182
|
+
!hamburgerButton.contains(event.target) &&
|
183
|
+
!hamburgerNav.contains(event.target)
|
184
|
+
) {
|
185
|
+
hideMenu();
|
186
|
+
}
|
187
|
+
};
|
188
|
+
|
189
|
+
hamburgerButton.addEventListener("click", (event) => {
|
190
|
+
event.stopPropagation();
|
191
|
+
const isVisible = hamburgerNav.style.display === "block";
|
192
|
+
if (isVisible) {
|
193
|
+
hideMenu();
|
194
|
+
} else {
|
195
|
+
showMenu();
|
196
|
+
}
|
197
|
+
});
|
117
198
|
}
|
118
199
|
|
200
|
+
/**
|
201
|
+
* Attaches a ResizeObserver to re-calculate tabs when the component's size changes.
|
202
|
+
* @private
|
203
|
+
* @this {SiteNavigation}
|
204
|
+
* @returns {void}
|
205
|
+
*/
|
119
206
|
function attachResizeObserver() {
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
207
|
+
this[resizeObserverSymbol] = new ResizeObserver(() => {
|
208
|
+
if (this[timerCallbackSymbol] instanceof DeadMansSwitch) {
|
209
|
+
try {
|
210
|
+
this[timerCallbackSymbol].touch();
|
211
|
+
return;
|
212
|
+
} catch (e) {
|
213
|
+
delete this[timerCallbackSymbol];
|
214
|
+
}
|
215
|
+
}
|
216
|
+
this[timerCallbackSymbol] = new DeadMansSwitch(200, () =>
|
217
|
+
populateTabs.call(this),
|
218
|
+
);
|
219
|
+
});
|
220
|
+
this[resizeObserverSymbol].observe(this[navElementSymbol]);
|
134
221
|
}
|
135
222
|
|
223
|
+
/**
|
224
|
+
* Detaches the ResizeObserver when the component is removed from the DOM.
|
225
|
+
* @private
|
226
|
+
* @this {SiteNavigation}
|
227
|
+
* @returns {void}
|
228
|
+
*/
|
136
229
|
function detachResizeObserver() {
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
230
|
+
if (this[resizeObserverSymbol] instanceof ResizeObserver) {
|
231
|
+
this[resizeObserverSymbol].disconnect();
|
232
|
+
delete this[resizeObserverSymbol];
|
233
|
+
}
|
141
234
|
}
|
142
235
|
|
143
236
|
/**
|
144
|
-
*
|
145
|
-
*
|
237
|
+
* Sets up a submenu based on its context (visible nav or hidden hamburger menu).
|
238
|
+
* @private
|
239
|
+
* @this {SiteNavigation}
|
146
240
|
* @param {HTMLElement} parentLi The list item that contains the submenu.
|
241
|
+
* @param {'visible' | 'hidden'} context The context in which the submenu appears.
|
242
|
+
* @returns {void}
|
147
243
|
*/
|
148
|
-
function setupSubmenu(parentLi) {
|
149
|
-
|
150
|
-
|
151
|
-
|
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
|
-
|
244
|
+
function setupSubmenu(parentLi, context = "visible") {
|
245
|
+
const submenu = parentLi.querySelector("ul");
|
246
|
+
if (!submenu) return;
|
247
|
+
|
248
|
+
submenu.setAttribute("part", "submenu");
|
249
|
+
|
250
|
+
if (context === "visible") {
|
251
|
+
const component = this;
|
252
|
+
let cleanup;
|
253
|
+
let hideTimeout;
|
254
|
+
|
255
|
+
const immediateHide = () => {
|
256
|
+
submenu.style.display = "none";
|
257
|
+
if (cleanup) {
|
258
|
+
cleanup();
|
259
|
+
cleanup = null;
|
260
|
+
}
|
261
|
+
if (component[activeSubmenuHiderSymbol] === immediateHide) {
|
262
|
+
component[activeSubmenuHiderSymbol] = null;
|
263
|
+
}
|
264
|
+
};
|
265
|
+
|
266
|
+
const show = () => {
|
267
|
+
clearTimeout(hideTimeout);
|
268
|
+
if (
|
269
|
+
component[activeSubmenuHiderSymbol] &&
|
270
|
+
component[activeSubmenuHiderSymbol] !== immediateHide
|
271
|
+
) {
|
272
|
+
component[activeSubmenuHiderSymbol]();
|
273
|
+
}
|
274
|
+
submenu.style.display = "block";
|
275
|
+
if (!cleanup) {
|
276
|
+
cleanup = autoUpdate(parentLi, submenu, () => {
|
277
|
+
computePosition(parentLi, submenu, {
|
278
|
+
placement: "bottom-start",
|
279
|
+
middleware: [offset(8), flip(), shift({ padding: 8 })],
|
280
|
+
}).then(({ x, y }) => {
|
281
|
+
Object.assign(submenu.style, { left: `${x}px`, top: `${y}px` });
|
282
|
+
});
|
283
|
+
});
|
284
|
+
}
|
285
|
+
component[activeSubmenuHiderSymbol] = immediateHide;
|
286
|
+
};
|
287
|
+
|
288
|
+
const hideWithDelay = () => {
|
289
|
+
hideTimeout = setTimeout(immediateHide, 200);
|
290
|
+
};
|
291
|
+
|
292
|
+
parentLi.addEventListener("mouseenter", show);
|
293
|
+
parentLi.addEventListener("mouseleave", hideWithDelay);
|
294
|
+
submenu.addEventListener("mouseenter", () => clearTimeout(hideTimeout));
|
295
|
+
submenu.addEventListener("mouseleave", hideWithDelay);
|
296
|
+
} else {
|
297
|
+
submenu.style.display = "none";
|
298
|
+
const anchor = parentLi.querySelector("a");
|
299
|
+
if (anchor) {
|
300
|
+
anchor.addEventListener("click", (event) => {
|
301
|
+
event.preventDefault();
|
302
|
+
event.stopPropagation();
|
303
|
+
const isVisible = submenu.style.display === "block";
|
304
|
+
submenu.style.display = isVisible ? "none" : "block";
|
305
|
+
});
|
306
|
+
}
|
307
|
+
}
|
191
308
|
}
|
192
309
|
|
310
|
+
/**
|
311
|
+
* Calculates which navigation items fit in the visible area and moves the rest
|
312
|
+
* to a hidden "hamburger" menu.
|
313
|
+
* @private
|
314
|
+
* @this {SiteNavigation}
|
315
|
+
* @returns {void}
|
316
|
+
*/
|
193
317
|
function populateTabs() {
|
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
|
-
|
318
|
+
const visibleList = this[visibleElementsSymbol];
|
319
|
+
const hiddenList = this[hiddenElementsSymbol];
|
320
|
+
const hamburgerButton = this[hamburgerButtonSymbol];
|
321
|
+
const hamburgerNav = this[hamburgerNavSymbol];
|
322
|
+
|
323
|
+
const topLevelUl = [...getSlottedElements.call(this, "ul")].find(
|
324
|
+
(ul) => ul.parentElement === this,
|
325
|
+
);
|
326
|
+
|
327
|
+
if (!topLevelUl) {
|
328
|
+
visibleList.style.visibility = "visible";
|
329
|
+
hamburgerButton.style.display = "none";
|
330
|
+
return;
|
331
|
+
}
|
332
|
+
|
333
|
+
const sourceItems = Array.from(topLevelUl.children).filter(
|
334
|
+
(item) => item.tagName === "LI",
|
335
|
+
);
|
336
|
+
|
337
|
+
visibleList.style.visibility = "hidden";
|
338
|
+
hamburgerButton.style.display = "none";
|
339
|
+
hamburgerNav.style.display = "none";
|
340
|
+
visibleList.innerHTML = "";
|
341
|
+
hiddenList.innerHTML = "";
|
342
|
+
|
343
|
+
const originalDisplay = hamburgerButton.style.display;
|
344
|
+
hamburgerButton.style.visibility = "hidden";
|
345
|
+
hamburgerButton.style.display = "flex";
|
346
|
+
const hamburgerWidth = hamburgerButton.offsetWidth;
|
347
|
+
hamburgerButton.style.display = originalDisplay;
|
348
|
+
hamburgerButton.style.visibility = "visible";
|
349
|
+
|
350
|
+
const navWidth = this[navElementSymbol].clientWidth;
|
351
|
+
if (navWidth === 0) {
|
352
|
+
visibleList.style.visibility = "visible";
|
353
|
+
return;
|
354
|
+
}
|
355
|
+
|
356
|
+
const measurementList = visibleList.cloneNode(true);
|
357
|
+
Object.assign(measurementList.style, {
|
358
|
+
position: "absolute",
|
359
|
+
left: "0",
|
360
|
+
top: "0",
|
361
|
+
width: "auto",
|
362
|
+
visibility: "hidden",
|
363
|
+
});
|
364
|
+
this.shadowRoot.appendChild(measurementList);
|
365
|
+
|
366
|
+
const itemsToMove = [];
|
367
|
+
const availableWidthForTabs = navWidth - hamburgerWidth;
|
368
|
+
|
369
|
+
for (let i = 0; i < sourceItems.length; i++) {
|
370
|
+
const item = sourceItems[i];
|
371
|
+
const itemClone = item.cloneNode(true);
|
372
|
+
const submenu = itemClone.querySelector("ul");
|
373
|
+
if (submenu) submenu.style.display = "none";
|
374
|
+
|
375
|
+
measurementList.appendChild(itemClone);
|
376
|
+
|
377
|
+
const isLastItem = i === sourceItems.length - 1;
|
378
|
+
const effectiveMaxWidth = isLastItem ? navWidth : availableWidthForTabs;
|
379
|
+
|
380
|
+
if (measurementList.scrollWidth > effectiveMaxWidth) {
|
381
|
+
break;
|
382
|
+
} else {
|
383
|
+
itemsToMove.push(item);
|
384
|
+
}
|
385
|
+
}
|
386
|
+
this.shadowRoot.removeChild(measurementList);
|
387
|
+
|
388
|
+
const visibleItems = itemsToMove;
|
389
|
+
const hiddenItems = sourceItems.slice(visibleItems.length);
|
390
|
+
|
391
|
+
if (visibleItems.length > 0) {
|
392
|
+
const clonedVisibleItems = visibleItems.map((item) => {
|
393
|
+
const liClone = item.cloneNode(true);
|
394
|
+
const aClone = liClone.querySelector("a");
|
395
|
+
|
396
|
+
liClone.setAttribute("part", "nav-item");
|
397
|
+
if (aClone) aClone.setAttribute("part", "nav-link");
|
398
|
+
|
399
|
+
if (item.classList.contains("active")) {
|
400
|
+
liClone.setAttribute("part", "nav-item nav-item-active");
|
401
|
+
if (aClone) aClone.setAttribute("part", "nav-link nav-link-active");
|
402
|
+
}
|
403
|
+
return liClone;
|
404
|
+
});
|
405
|
+
visibleList.append(...clonedVisibleItems);
|
406
|
+
visibleList
|
407
|
+
.querySelectorAll("li")
|
408
|
+
.forEach((li) => setupSubmenu.call(this, li, "visible"));
|
409
|
+
}
|
410
|
+
|
411
|
+
if (hiddenItems.length > 0) {
|
412
|
+
const clonedHiddenItems = hiddenItems.map((item) => {
|
413
|
+
const liClone = item.cloneNode(true);
|
414
|
+
const aClone = liClone.querySelector("a");
|
415
|
+
|
416
|
+
liClone.setAttribute("part", "nav-item");
|
417
|
+
if (aClone) aClone.setAttribute("part", "nav-link");
|
418
|
+
if (item.classList.contains("active")) {
|
419
|
+
liClone.setAttribute("part", "nav-item nav-item-active");
|
420
|
+
if (aClone) aClone.setAttribute("part", "nav-link nav-link-active");
|
421
|
+
}
|
422
|
+
return liClone;
|
423
|
+
});
|
424
|
+
hiddenList.append(...clonedHiddenItems);
|
425
|
+
hamburgerButton.style.display = "flex";
|
426
|
+
hiddenList
|
427
|
+
.querySelectorAll("li")
|
428
|
+
.forEach((li) => setupSubmenu.call(this, li, "hidden"));
|
429
|
+
}
|
430
|
+
|
431
|
+
visibleList.style.visibility = "visible";
|
263
432
|
}
|
264
433
|
|
434
|
+
/**
|
435
|
+
* Returns the HTML template for the component's shadow DOM.
|
436
|
+
* @private
|
437
|
+
* @returns {string}
|
438
|
+
*/
|
265
439
|
function getTemplate() {
|
266
|
-
|
267
|
-
return `
|
440
|
+
return `
|
268
441
|
<div data-monster-role="control" part="control">
|
269
442
|
<nav data-monster-role="navigation" role="navigation" part="nav">
|
270
443
|
<ul id="visible-elements" part="visible-list"></ul>
|