@schukai/monster 4.43.15 → 4.43.17
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
CHANGED
|
@@ -2,6 +2,22 @@
|
|
|
2
2
|
|
|
3
3
|
|
|
4
4
|
|
|
5
|
+
## [4.43.17] - 2025-10-27
|
|
6
|
+
|
|
7
|
+
### Bug Fixes
|
|
8
|
+
|
|
9
|
+
- remove x-default from list
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
## [4.43.16] - 2025-10-24
|
|
14
|
+
|
|
15
|
+
### Bug Fixes
|
|
16
|
+
|
|
17
|
+
- site navigation with touch devices
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
|
|
5
21
|
## [4.43.15] - 2025-10-21
|
|
6
22
|
|
|
7
23
|
### Bug Fixes
|
package/package.json
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"author":"schukai GmbH","dependencies":{"@floating-ui/dom":"^1.7.4","@popperjs/core":"^2.11.8"},"description":"Monster is a simple library for creating fast, robust and lightweight websites.","homepage":"https://monsterjs.org/","keywords":["framework","web","dom","css","sass","mobile-first","app","front-end","templates","schukai","core","shopcloud","alvine","monster","buildmap","stack","observer","observable","uuid","node","nodelist","css-in-js","logger","log","theme"],"license":"AGPL 3.0","main":"source/monster.mjs","module":"source/monster.mjs","name":"@schukai/monster","repository":{"type":"git","url":"https://gitlab.schukai.com/oss/libraries/javascript/monster.git"},"type":"module","version":"4.43.
|
|
1
|
+
{"author":"schukai GmbH","dependencies":{"@floating-ui/dom":"^1.7.4","@popperjs/core":"^2.11.8"},"description":"Monster is a simple library for creating fast, robust and lightweight websites.","homepage":"https://monsterjs.org/","keywords":["framework","web","dom","css","sass","mobile-first","app","front-end","templates","schukai","core","shopcloud","alvine","monster","buildmap","stack","observer","observable","uuid","node","nodelist","css-in-js","logger","log","theme"],"license":"AGPL 3.0","main":"source/monster.mjs","module":"source/monster.mjs","name":"@schukai/monster","repository":{"type":"git","url":"https://gitlab.schukai.com/oss/libraries/javascript/monster.git"},"type":"module","version":"4.43.17"}
|
|
@@ -13,8 +13,8 @@ import { instanceSymbol } from "../../constants.mjs";
|
|
|
13
13
|
import { ATTRIBUTE_ROLE } from "../../dom/constants.mjs";
|
|
14
14
|
import { CustomElement } from "../../dom/customelement.mjs";
|
|
15
15
|
import {
|
|
16
|
-
|
|
17
|
-
|
|
16
|
+
assembleMethodSymbol,
|
|
17
|
+
registerCustomElement,
|
|
18
18
|
} from "../../dom/customelement.mjs";
|
|
19
19
|
import { isFunction, isObject } from "../../types/is.mjs";
|
|
20
20
|
import { LocalePickerStyleSheet } from "./stylesheet/locale-picker.mjs";
|
|
@@ -43,63 +43,63 @@ const detectedLanguagesSymbol = Symbol("detectedLanguages");
|
|
|
43
43
|
* @return {string}
|
|
44
44
|
*/
|
|
45
45
|
function getLocalizedLabel() {
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
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
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
46
|
+
const lang = document.documentElement.lang || navigator.language || "en";
|
|
47
|
+
switch (lang.split("-")[0]) {
|
|
48
|
+
case "de":
|
|
49
|
+
return "Sprache wählen";
|
|
50
|
+
case "fr":
|
|
51
|
+
return "Sélectionnez une langue";
|
|
52
|
+
case "es":
|
|
53
|
+
return "Seleccione un idioma";
|
|
54
|
+
case "it":
|
|
55
|
+
return "Seleziona una lingua";
|
|
56
|
+
case "pt":
|
|
57
|
+
return "Selecione um idioma";
|
|
58
|
+
case "nl":
|
|
59
|
+
return "Selecteer een taal";
|
|
60
|
+
case "pl":
|
|
61
|
+
return "Wybierz język";
|
|
62
|
+
case "ru":
|
|
63
|
+
return "Выберите язык";
|
|
64
|
+
case "cs":
|
|
65
|
+
return "Vyberte jazyk";
|
|
66
|
+
case "sk":
|
|
67
|
+
return "Vyberte jazyk";
|
|
68
|
+
case "bg":
|
|
69
|
+
return "Изберете език";
|
|
70
|
+
case "hr":
|
|
71
|
+
return "Odaberite jezik";
|
|
72
|
+
case "fi":
|
|
73
|
+
return "Valitse kieli";
|
|
74
|
+
case "sv":
|
|
75
|
+
return "Välj ett språk";
|
|
76
|
+
case "el":
|
|
77
|
+
return "Επιλέξτε γλώσσα";
|
|
78
|
+
case "hu":
|
|
79
|
+
return "Válasszon egy nyelvet";
|
|
80
|
+
case "ro":
|
|
81
|
+
return "Selectați o limbă";
|
|
82
|
+
case "da":
|
|
83
|
+
return "Vælg et sprog";
|
|
84
|
+
case "no":
|
|
85
|
+
return "Velg et språk";
|
|
86
|
+
case "hi":
|
|
87
|
+
return "एक भाषा चुनें";
|
|
88
|
+
case "bn":
|
|
89
|
+
return "একটি ভাষা নির্বাচন করুন";
|
|
90
|
+
case "ta":
|
|
91
|
+
return "ஒரு மொழியைத் தேர்ந்தெடுக்கவும்";
|
|
92
|
+
case "te":
|
|
93
|
+
return "భాషను ఎంచుకోండి";
|
|
94
|
+
case "mr":
|
|
95
|
+
return "एक भाषा निवडा";
|
|
96
|
+
case "zh":
|
|
97
|
+
return "选择一种语言";
|
|
98
|
+
case "ja":
|
|
99
|
+
return "言語を選択してください";
|
|
100
|
+
default:
|
|
101
|
+
return "Select a language";
|
|
102
|
+
}
|
|
103
103
|
}
|
|
104
104
|
|
|
105
105
|
/**
|
|
@@ -112,92 +112,92 @@ function getLocalizedLabel() {
|
|
|
112
112
|
* @summary A simple language switcher as a select.
|
|
113
113
|
*/
|
|
114
114
|
class LocaleSelect extends CustomElement {
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
115
|
+
/**
|
|
116
|
+
* Used by the instanceof operator.
|
|
117
|
+
* @returns {symbol}
|
|
118
|
+
*/
|
|
119
|
+
static get [instanceSymbol]() {
|
|
120
|
+
return Symbol.for(
|
|
121
|
+
"@schukai/monster/components/accessibility/local-selector@@instance",
|
|
122
|
+
);
|
|
123
|
+
}
|
|
124
124
|
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
125
|
+
/**
|
|
126
|
+
* Initializes the component.
|
|
127
|
+
* @return {LocaleSelect}
|
|
128
|
+
*/
|
|
129
|
+
[assembleMethodSymbol]() {
|
|
130
|
+
super[assembleMethodSymbol]();
|
|
131
|
+
initControlReferences.call(this);
|
|
132
|
+
initSelectOptions.call(this);
|
|
133
|
+
initEventHandler.call(this);
|
|
134
|
+
return this;
|
|
135
|
+
}
|
|
136
136
|
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
137
|
+
/**
|
|
138
|
+
* Default options
|
|
139
|
+
*/
|
|
140
|
+
get defaults() {
|
|
141
|
+
return Object.assign({}, super.defaults, {
|
|
142
|
+
templates: {
|
|
143
|
+
main: getTemplate(),
|
|
144
|
+
},
|
|
145
|
+
labels: {
|
|
146
|
+
"select-an-option": getLocalizedLabel(),
|
|
147
|
+
},
|
|
148
|
+
callbacks: {},
|
|
149
|
+
disabled: false,
|
|
150
|
+
});
|
|
151
|
+
}
|
|
152
152
|
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
153
|
+
/**
|
|
154
|
+
* connectedCallback
|
|
155
|
+
*/
|
|
156
|
+
connectedCallback() {
|
|
157
|
+
super.connectedCallback();
|
|
158
|
+
this[detectedLanguagesSymbol] = detectUserLanguagePreference();
|
|
159
|
+
initSelectOptions.call(this);
|
|
160
|
+
}
|
|
161
161
|
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
162
|
+
/**
|
|
163
|
+
* @return {string}
|
|
164
|
+
*/
|
|
165
|
+
static getTag() {
|
|
166
|
+
return "monster-locale-select";
|
|
167
|
+
}
|
|
168
168
|
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
169
|
+
/**
|
|
170
|
+
* @return {CSSStyleSheet[]}
|
|
171
|
+
*/
|
|
172
|
+
static getCSSStyleSheet() {
|
|
173
|
+
return [LocalePickerStyleSheet];
|
|
174
|
+
}
|
|
175
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
|
-
|
|
176
|
+
/**
|
|
177
|
+
* Export parts from monster-select to make them available for styling outside.
|
|
178
|
+
*/
|
|
179
|
+
static get exportparts() {
|
|
180
|
+
// The parts from monster-select, as defined in source/components/form/select.mjs:
|
|
181
|
+
return [
|
|
182
|
+
"control",
|
|
183
|
+
"container",
|
|
184
|
+
"popper",
|
|
185
|
+
"option",
|
|
186
|
+
"option-label",
|
|
187
|
+
"option-control",
|
|
188
|
+
"badge",
|
|
189
|
+
"badge-label",
|
|
190
|
+
"remove-badge",
|
|
191
|
+
"summary",
|
|
192
|
+
"status-or-remove-badges",
|
|
193
|
+
"remote-info",
|
|
194
|
+
"no-options",
|
|
195
|
+
"selection",
|
|
196
|
+
"inline-filter",
|
|
197
|
+
"popper-filter",
|
|
198
|
+
"content",
|
|
199
|
+
].join(",");
|
|
200
|
+
}
|
|
201
201
|
}
|
|
202
202
|
|
|
203
203
|
/**
|
|
@@ -205,9 +205,9 @@ class LocaleSelect extends CustomElement {
|
|
|
205
205
|
* @private
|
|
206
206
|
*/
|
|
207
207
|
function initControlReferences() {
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
208
|
+
this[selectElementSymbol] = this.shadowRoot.querySelector(
|
|
209
|
+
`[${ATTRIBUTE_ROLE}="select"]`,
|
|
210
|
+
);
|
|
211
211
|
}
|
|
212
212
|
|
|
213
213
|
/**
|
|
@@ -215,29 +215,36 @@ function initControlReferences() {
|
|
|
215
215
|
* @private
|
|
216
216
|
*/
|
|
217
217
|
function initSelectOptions() {
|
|
218
|
-
|
|
219
|
-
|
|
218
|
+
const detected =
|
|
219
|
+
this[detectedLanguagesSymbol] || detectUserLanguagePreference();
|
|
220
220
|
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
221
|
+
let options = [];
|
|
222
|
+
if (Array.isArray(detected.available)) {
|
|
223
|
+
const currentLang = detected.current;
|
|
224
|
+
options = detected.available.filter(
|
|
225
|
+
(lang) => lang.baseLang !== currentLang && lang.fullLang !== currentLang,
|
|
226
|
+
);
|
|
227
|
+
} else if (Array.isArray(detected.allOfferable)) {
|
|
228
|
+
options = detected.allOfferable;
|
|
229
|
+
}
|
|
230
230
|
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
231
|
+
options = detected.allOfferable;
|
|
232
|
+
|
|
233
|
+
if (Array.isArray(options)) {
|
|
234
|
+
options = options.filter(
|
|
235
|
+
(lang) => lang.baseLang !== "x-default" && lang.fullLang !== "x-default",
|
|
236
|
+
);
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
if (this[selectElementSymbol]) {
|
|
240
|
+
this[selectElementSymbol].setOption("mapping.labelTemplate", "${label}");
|
|
241
|
+
this[selectElementSymbol].setOption("mapping.valueTemplate", "${href}");
|
|
242
|
+
this[selectElementSymbol].setOption(
|
|
243
|
+
"labels.select-an-option",
|
|
244
|
+
this.getOption("labels.select-an-option"),
|
|
245
|
+
);
|
|
246
|
+
this[selectElementSymbol].importOptions(options);
|
|
247
|
+
}
|
|
241
248
|
}
|
|
242
249
|
|
|
243
250
|
/**
|
|
@@ -245,14 +252,14 @@ function initSelectOptions() {
|
|
|
245
252
|
* @private
|
|
246
253
|
*/
|
|
247
254
|
function initEventHandler() {
|
|
248
|
-
|
|
255
|
+
if (!this[selectElementSymbol]) return;
|
|
249
256
|
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
257
|
+
this[selectElementSymbol].addEventListener("change", (event) => {
|
|
258
|
+
const selected = event.target?.value;
|
|
259
|
+
if (selected) {
|
|
260
|
+
window.location.href = selected;
|
|
261
|
+
}
|
|
262
|
+
});
|
|
256
263
|
}
|
|
257
264
|
|
|
258
265
|
/**
|
|
@@ -261,8 +268,8 @@ function initEventHandler() {
|
|
|
261
268
|
* @return {string}
|
|
262
269
|
*/
|
|
263
270
|
function getTemplate() {
|
|
264
|
-
|
|
265
|
-
|
|
271
|
+
// language=HTML
|
|
272
|
+
return `
|
|
266
273
|
<monster-select exportparts="control,container,popper,option,option-label,option-control,badge,badge-label,remove-badge,summary,status-or-remove-badges,remote-info,no-options,selection,inline-filter,popper-filter,content" data-monster-role="select"></monster-select>
|
|
267
274
|
`;
|
|
268
275
|
}
|
|
@@ -111,7 +111,6 @@ class SiteNavigation extends CustomElement {
|
|
|
111
111
|
requestAnimationFrame(() => {
|
|
112
112
|
populateTabs.call(this);
|
|
113
113
|
});
|
|
114
|
-
|
|
115
114
|
}
|
|
116
115
|
|
|
117
116
|
disconnectedCallback() {
|
|
@@ -304,7 +303,7 @@ function detachResizeObserver() {
|
|
|
304
303
|
}
|
|
305
304
|
|
|
306
305
|
/**
|
|
307
|
-
* Sets up interaction logic (hover or
|
|
306
|
+
* Sets up interaction logic (hover, click, or touch) for a submenu.
|
|
308
307
|
* This function is called recursively for nested submenus.
|
|
309
308
|
* @private
|
|
310
309
|
* @this {SiteNavigation}
|
|
@@ -323,111 +322,174 @@ function setupSubmenu(parentLi, context = "visible", level = 1) {
|
|
|
323
322
|
}
|
|
324
323
|
|
|
325
324
|
const interaction = this.getOption("interactionModel", "auto");
|
|
326
|
-
const
|
|
327
|
-
|
|
328
|
-
(interaction === "auto" && context === "visible");
|
|
325
|
+
const isTouchDevice =
|
|
326
|
+
"ontouchstart" in window || navigator.maxTouchPoints > 0;
|
|
329
327
|
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
328
|
+
const effectiveInteraction =
|
|
329
|
+
interaction === "auto"
|
|
330
|
+
? context === "visible"
|
|
331
|
+
? "hover"
|
|
332
|
+
: "click"
|
|
333
|
+
: interaction;
|
|
334
|
+
|
|
335
|
+
const component = this;
|
|
336
|
+
let cleanup;
|
|
335
337
|
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
338
|
+
const immediateHide = () => {
|
|
339
|
+
submenu.style.display = "none";
|
|
340
|
+
Object.assign(submenu.style, {
|
|
341
|
+
maxHeight: "",
|
|
342
|
+
overflowY: "",
|
|
343
|
+
});
|
|
344
|
+
submenu
|
|
345
|
+
.querySelectorAll(
|
|
346
|
+
"ul[style*='display: block'], div[part='mega-menu'][style*='display: block']",
|
|
347
|
+
)
|
|
348
|
+
.forEach((sub) => {
|
|
349
|
+
sub.style.display = "none";
|
|
341
350
|
});
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
351
|
+
fireCustomEvent(this, "monster-submenu-hide", {
|
|
352
|
+
context,
|
|
353
|
+
trigger: parentLi,
|
|
354
|
+
submenu,
|
|
355
|
+
level,
|
|
356
|
+
});
|
|
357
|
+
if (cleanup) {
|
|
358
|
+
cleanup();
|
|
359
|
+
cleanup = null;
|
|
360
|
+
}
|
|
361
|
+
if (level === 1 && component[activeSubmenuHiderSymbol] === immediateHide) {
|
|
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
|
+
});
|
|
348
423
|
});
|
|
349
|
-
fireCustomEvent(this, "monster-submenu-hide", {
|
|
350
|
-
context,
|
|
351
|
-
trigger: parentLi,
|
|
352
|
-
submenu,
|
|
353
|
-
level,
|
|
354
424
|
});
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
425
|
+
}
|
|
426
|
+
};
|
|
427
|
+
|
|
428
|
+
if (effectiveInteraction === "hover" && isTouchDevice) {
|
|
429
|
+
let lastTap = 0;
|
|
430
|
+
const DOUBLE_TAP_DELAY = 300;
|
|
431
|
+
const anchor = parentLi.querySelector(":scope > a");
|
|
432
|
+
|
|
433
|
+
if (!anchor) return;
|
|
434
|
+
|
|
435
|
+
const handleOutsideClickForSubmenu = (event) => {
|
|
359
436
|
if (
|
|
360
|
-
|
|
361
|
-
|
|
437
|
+
submenu.style.display === "block" &&
|
|
438
|
+
!parentLi.contains(event.target)
|
|
362
439
|
) {
|
|
363
|
-
|
|
440
|
+
immediateHide();
|
|
441
|
+
document.removeEventListener(
|
|
442
|
+
"click",
|
|
443
|
+
handleOutsideClickForSubmenu,
|
|
444
|
+
true,
|
|
445
|
+
);
|
|
364
446
|
}
|
|
365
447
|
};
|
|
366
448
|
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
449
|
+
anchor.addEventListener("click", (event) => {
|
|
450
|
+
const now = Date.now();
|
|
451
|
+
const timeSinceLastTap = now - lastTap;
|
|
452
|
+
lastTap = now;
|
|
453
|
+
|
|
454
|
+
if (timeSinceLastTap < DOUBLE_TAP_DELAY && timeSinceLastTap > 0) {
|
|
455
|
+
lastTap = 0;
|
|
456
|
+
document.removeEventListener(
|
|
457
|
+
"click",
|
|
458
|
+
handleOutsideClickForSubmenu,
|
|
459
|
+
true,
|
|
460
|
+
);
|
|
461
|
+
immediateHide();
|
|
377
462
|
} else {
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
}
|
|
389
|
-
submenu.style.display = "block";
|
|
390
|
-
fireCustomEvent(this, "monster-submenu-show", {
|
|
391
|
-
context,
|
|
392
|
-
trigger: parentLi,
|
|
393
|
-
submenu,
|
|
394
|
-
level,
|
|
395
|
-
});
|
|
396
|
-
if (!cleanup) {
|
|
397
|
-
cleanup = autoUpdate(parentLi, submenu, () => {
|
|
398
|
-
const middleware = [offset(8), flip(), shift({ padding: 8 })];
|
|
399
|
-
const containsSubmenus = submenu.querySelector(
|
|
400
|
-
"ul, div[part='mega-menu']",
|
|
463
|
+
event.preventDefault();
|
|
464
|
+
event.stopPropagation();
|
|
465
|
+
|
|
466
|
+
const isMenuOpen = submenu.style.display === "block";
|
|
467
|
+
|
|
468
|
+
if (isMenuOpen) {
|
|
469
|
+
document.removeEventListener(
|
|
470
|
+
"click",
|
|
471
|
+
handleOutsideClickForSubmenu,
|
|
472
|
+
true,
|
|
401
473
|
);
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
},
|
|
411
|
-
padding: 8,
|
|
412
|
-
}),
|
|
474
|
+
immediateHide();
|
|
475
|
+
} else {
|
|
476
|
+
show();
|
|
477
|
+
setTimeout(() => {
|
|
478
|
+
document.addEventListener(
|
|
479
|
+
"click",
|
|
480
|
+
handleOutsideClickForSubmenu,
|
|
481
|
+
true,
|
|
413
482
|
);
|
|
414
|
-
}
|
|
415
|
-
|
|
416
|
-
placement: level === 1 ? "bottom-start" : "right-start",
|
|
417
|
-
middleware: middleware,
|
|
418
|
-
}).then(({ x, y, strategy }) => {
|
|
419
|
-
Object.assign(submenu.style, {
|
|
420
|
-
position: strategy,
|
|
421
|
-
left: `${x}px`,
|
|
422
|
-
top: `${y}px`,
|
|
423
|
-
});
|
|
424
|
-
});
|
|
425
|
-
});
|
|
483
|
+
}, 0);
|
|
484
|
+
}
|
|
426
485
|
}
|
|
427
|
-
};
|
|
486
|
+
});
|
|
487
|
+
} else if (effectiveInteraction === "hover" && !isTouchDevice) {
|
|
488
|
+
let hideTimeout;
|
|
489
|
+
let isHovering = false;
|
|
428
490
|
|
|
429
491
|
const handleMouseEnter = () => {
|
|
430
|
-
isHovering = true;
|
|
492
|
+
isHovering = true;
|
|
431
493
|
clearTimeout(hideTimeout);
|
|
432
494
|
if (submenu.style.display !== "block") {
|
|
433
495
|
show();
|
|
@@ -435,7 +497,7 @@ function setupSubmenu(parentLi, context = "visible", level = 1) {
|
|
|
435
497
|
};
|
|
436
498
|
|
|
437
499
|
const handleMouseLeave = () => {
|
|
438
|
-
isHovering = false;
|
|
500
|
+
isHovering = false;
|
|
439
501
|
hideTimeout = setTimeout(() => {
|
|
440
502
|
if (!isHovering) {
|
|
441
503
|
immediateHide();
|
|
@@ -524,7 +586,6 @@ function cloneNavItem(item) {
|
|
|
524
586
|
* @this {SiteNavigation}
|
|
525
587
|
*/
|
|
526
588
|
function populateTabs() {
|
|
527
|
-
|
|
528
589
|
const visibleList = this[visibleElementsSymbol];
|
|
529
590
|
const hiddenList = this[hiddenElementsSymbol];
|
|
530
591
|
const hamburgerButton = this[hamburgerButtonSymbol];
|
|
@@ -551,7 +612,6 @@ function populateTabs() {
|
|
|
551
612
|
return;
|
|
552
613
|
}
|
|
553
614
|
|
|
554
|
-
|
|
555
615
|
const navWidth = navEl.clientWidth;
|
|
556
616
|
|
|
557
617
|
const originalDisplay = hamburgerButton.style.display;
|
|
@@ -607,7 +667,7 @@ function populateTabs() {
|
|
|
607
667
|
visibleList.appendChild(firstHiddenItemClone);
|
|
608
668
|
const firstHiddenItemWidth =
|
|
609
669
|
firstHiddenItemClone.getBoundingClientRect().width;
|
|
610
|
-
visibleList.removeChild(firstHiddenItemClone);
|
|
670
|
+
visibleList.removeChild(firstHiddenItemClone);
|
|
611
671
|
|
|
612
672
|
const gap = parseFloat(getComputedStyle(visibleList).gap || "0") || 0;
|
|
613
673
|
if (visibleItemsWidth + gap + firstHiddenItemWidth <= navWidth) {
|