@getquick/content 0.3.1 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +87 -0
- package/dist/consent-astro.js +2 -2
- package/dist/consent-client.js +19 -6
- package/dist/consent-server.js +4 -37
- package/dist/consent.js +2 -2
- package/dist/copy-DLto_bWj.js +163 -0
- package/dist/descriptor-B-e7gHi1.d.ts +143 -0
- package/dist/descriptor-x8kHFQ79.js +205 -0
- package/dist/design-client.d.ts +19 -0
- package/dist/design-client.js +519 -0
- package/dist/{dist-D4-CMkrf.js → dist-5jNKLmbn.js} +198 -3
- package/dist/{embeds-p9SyGNZI.js → embeds-CJJemAmE.js} +2 -2
- package/dist/forms-astro.d.ts +50 -0
- package/dist/forms-astro.js +193 -0
- package/dist/forms-server.d.ts +80 -0
- package/dist/forms-server.js +294 -0
- package/dist/forms-testing.d.ts +66 -0
- package/dist/forms-testing.js +334 -0
- package/dist/forms.d.ts +25 -0
- package/dist/forms.js +4 -0
- package/dist/index.d.ts +131 -12
- package/dist/index.js +9 -2
- package/dist/metadata-content.js +1 -1
- package/dist/metadata-testing.js +1 -1
- package/dist/request-guards-BUPr_vA4.js +46 -0
- package/dist/server.d.ts +1 -1
- package/dist/server.js +281 -26
- package/dist/site-language-BCGjkpWY.js +169178 -0
- package/dist/state-CsMFLUUO.d.ts +66 -0
- package/dist/validate-wRgYUNxN.js +130 -0
- package/dist/{version-ChwS3fUu.js → version-D81MsCZU.js} +1 -1
- package/dist/video-hero-D8AcMR4q.js +69 -0
- package/dist/{wordpress-D_HG2rEt.d.ts → wordpress-BvkTDMA0.d.ts} +306 -3
- package/package.json +21 -1
- package/dist/site-language-BLA2mmOw.js +0 -565
|
@@ -0,0 +1,519 @@
|
|
|
1
|
+
import { t as videoHeroFrameGeometry } from "./video-hero-D8AcMR4q.js";
|
|
2
|
+
//#region frontend/src/carousel-client.ts
|
|
3
|
+
/** Mount each Carousel once. Sites invoke on page load and call cleanup before
|
|
4
|
+
* client navigation replaces the page. DOM APIs are read only on invocation. */
|
|
5
|
+
function mountDesignCarousels(root) {
|
|
6
|
+
const scope = root ?? (typeof document === "undefined" ? void 0 : document);
|
|
7
|
+
if (!scope) return () => {};
|
|
8
|
+
const carousels = [...scope.querySelectorAll("[data-gqd-carousel]")];
|
|
9
|
+
if ("matches" in scope && typeof scope.matches === "function" && scope.matches("[data-gqd-carousel]")) carousels.unshift(scope);
|
|
10
|
+
const cleanups = [];
|
|
11
|
+
for (const carousel of carousels) {
|
|
12
|
+
if (carousel.hasAttribute("data-gqd-mounted")) continue;
|
|
13
|
+
const slides = [...carousel.children].filter((child) => child instanceof HTMLElement && child.classList.contains("wp-block-getquick-design-slider"));
|
|
14
|
+
if (!slides.length) continue;
|
|
15
|
+
carousel.setAttribute("data-gqd-mounted", "");
|
|
16
|
+
const view = carousel.ownerDocument.defaultView;
|
|
17
|
+
if (!view) continue;
|
|
18
|
+
const motion = view.matchMedia("(prefers-reduced-motion: reduce)");
|
|
19
|
+
const buttons = [...carousel.querySelectorAll("button[data-gqd-go]")].filter((node) => node.closest("[data-gqd-carousel]") === carousel);
|
|
20
|
+
const previous = slides.map((slide) => ({
|
|
21
|
+
slide,
|
|
22
|
+
hidden: slide.hidden,
|
|
23
|
+
inert: slide.inert,
|
|
24
|
+
role: slide.getAttribute("role"),
|
|
25
|
+
label: slide.getAttribute("aria-label"),
|
|
26
|
+
description: slide.getAttribute("aria-roledescription")
|
|
27
|
+
}));
|
|
28
|
+
let index = 0;
|
|
29
|
+
let timer;
|
|
30
|
+
let hovered = false;
|
|
31
|
+
let focused = false;
|
|
32
|
+
let stopped = false;
|
|
33
|
+
const listeners = [];
|
|
34
|
+
const listen = (target, name, handler) => {
|
|
35
|
+
target.addEventListener(name, handler);
|
|
36
|
+
listeners.push(() => target.removeEventListener(name, handler));
|
|
37
|
+
};
|
|
38
|
+
const cancel = () => {
|
|
39
|
+
if (timer !== void 0) clearTimeout(timer);
|
|
40
|
+
timer = void 0;
|
|
41
|
+
};
|
|
42
|
+
const schedule = () => {
|
|
43
|
+
cancel();
|
|
44
|
+
if (stopped || carousel.dataset.gqdAutoplay !== "true" || slides.length < 2 || motion.matches || hovered || focused || carousel.ownerDocument.hidden) return;
|
|
45
|
+
const seconds = Number(carousel.dataset.gqdDuration);
|
|
46
|
+
if (!Number.isInteger(seconds) || seconds < 1 || seconds > 120) return;
|
|
47
|
+
timer = setTimeout(() => {
|
|
48
|
+
if (motion.matches || hovered || focused || carousel.ownerDocument.hidden) {
|
|
49
|
+
schedule();
|
|
50
|
+
return;
|
|
51
|
+
}
|
|
52
|
+
show(index + 1);
|
|
53
|
+
}, seconds * 1e3);
|
|
54
|
+
};
|
|
55
|
+
const show = (next) => {
|
|
56
|
+
index = (next + slides.length) % slides.length;
|
|
57
|
+
slides.forEach((slide, position) => {
|
|
58
|
+
slide.dataset.gqdSlide = "";
|
|
59
|
+
slide.hidden = position !== index;
|
|
60
|
+
slide.inert = position !== index;
|
|
61
|
+
slide.setAttribute("role", "group");
|
|
62
|
+
slide.setAttribute("aria-roledescription", "slide");
|
|
63
|
+
slide.setAttribute("aria-label", `${position + 1} of ${slides.length}`);
|
|
64
|
+
});
|
|
65
|
+
buttons.forEach((button) => {
|
|
66
|
+
if (Number(button.dataset.gqdGo) === index) button.setAttribute("aria-current", "true");
|
|
67
|
+
else button.removeAttribute("aria-current");
|
|
68
|
+
});
|
|
69
|
+
schedule();
|
|
70
|
+
};
|
|
71
|
+
listen(carousel, "click", (event) => {
|
|
72
|
+
const target = event.target instanceof Element ? event.target.closest("button") : null;
|
|
73
|
+
if (!target || target.closest("[data-gqd-carousel]") !== carousel) return;
|
|
74
|
+
if (target.hasAttribute("data-gqd-next")) show(index + 1);
|
|
75
|
+
else if (target.hasAttribute("data-gqd-previous")) show(index - 1);
|
|
76
|
+
else if (target.dataset.gqdGo !== void 0) show(Number(target.dataset.gqdGo));
|
|
77
|
+
});
|
|
78
|
+
listen(carousel, "keydown", (event) => {
|
|
79
|
+
if (!(event instanceof KeyboardEvent) || event.altKey || event.ctrlKey || event.metaKey || event.shiftKey) return;
|
|
80
|
+
const target = event.target instanceof Element ? event.target : null;
|
|
81
|
+
if (!target || target.closest("[data-gqd-carousel]") !== carousel || target.closest("input,textarea,select,[contenteditable=true]")) return;
|
|
82
|
+
const control = target.closest("button[data-gqd-next],button[data-gqd-previous],button[data-gqd-go]");
|
|
83
|
+
if (!control || control.closest(".wp-block-getquick-design-carousel-navigation")?.parentElement !== carousel) return;
|
|
84
|
+
if (![
|
|
85
|
+
"ArrowLeft",
|
|
86
|
+
"ArrowRight",
|
|
87
|
+
"Home",
|
|
88
|
+
"End"
|
|
89
|
+
].includes(event.key)) return;
|
|
90
|
+
event.preventDefault();
|
|
91
|
+
const rtl = view.getComputedStyle(carousel).direction === "rtl";
|
|
92
|
+
show(event.key === "Home" ? 0 : event.key === "End" ? slides.length - 1 : index + (event.key === "ArrowRight" !== rtl ? 1 : -1));
|
|
93
|
+
});
|
|
94
|
+
listen(carousel, "mouseenter", () => {
|
|
95
|
+
hovered = true;
|
|
96
|
+
cancel();
|
|
97
|
+
});
|
|
98
|
+
listen(carousel, "mouseleave", () => {
|
|
99
|
+
hovered = false;
|
|
100
|
+
schedule();
|
|
101
|
+
});
|
|
102
|
+
listen(carousel, "focusin", () => {
|
|
103
|
+
focused = true;
|
|
104
|
+
cancel();
|
|
105
|
+
});
|
|
106
|
+
listen(carousel, "focusout", (event) => {
|
|
107
|
+
focused = event instanceof FocusEvent && event.relatedTarget instanceof Node && carousel.contains(event.relatedTarget);
|
|
108
|
+
schedule();
|
|
109
|
+
});
|
|
110
|
+
listen(motion, "change", schedule);
|
|
111
|
+
listen(carousel.ownerDocument, "visibilitychange", schedule);
|
|
112
|
+
show(0);
|
|
113
|
+
cleanups.push(() => {
|
|
114
|
+
stopped = true;
|
|
115
|
+
cancel();
|
|
116
|
+
listeners.forEach((remove) => remove());
|
|
117
|
+
carousel.removeAttribute("data-gqd-mounted");
|
|
118
|
+
for (const { slide, hidden, inert, role, label, description } of previous) {
|
|
119
|
+
slide.hidden = hidden;
|
|
120
|
+
slide.inert = inert;
|
|
121
|
+
slide.removeAttribute("data-gqd-slide");
|
|
122
|
+
for (const [name, value] of [
|
|
123
|
+
["role", role],
|
|
124
|
+
["aria-label", label],
|
|
125
|
+
["aria-roledescription", description]
|
|
126
|
+
]) if (value === null) slide.removeAttribute(name);
|
|
127
|
+
else slide.setAttribute(name, value);
|
|
128
|
+
}
|
|
129
|
+
});
|
|
130
|
+
}
|
|
131
|
+
return () => cleanups.forEach((cleanup) => cleanup());
|
|
132
|
+
}
|
|
133
|
+
//#endregion
|
|
134
|
+
/** Enhance only decorative media; nested content keeps its native interaction. */
|
|
135
|
+
function mountVideoHero(hero) {
|
|
136
|
+
const media = hero.querySelector(":scope > .gqd-video-hero__media");
|
|
137
|
+
if (!media) return () => {};
|
|
138
|
+
let frame = null;
|
|
139
|
+
let video = null;
|
|
140
|
+
const sources = /* @__PURE__ */ new WeakMap();
|
|
141
|
+
const motion = globalThis.matchMedia("(prefers-reduced-motion: reduce)");
|
|
142
|
+
const update = () => {
|
|
143
|
+
const nextFrame = media.querySelector("iframe");
|
|
144
|
+
const nextVideo = media.querySelector("video");
|
|
145
|
+
if (frame !== nextFrame) frame?.removeAttribute("src");
|
|
146
|
+
if (video !== nextVideo) video?.pause();
|
|
147
|
+
frame = nextFrame;
|
|
148
|
+
video = nextVideo;
|
|
149
|
+
if (video) {
|
|
150
|
+
if (motion.matches) video.pause();
|
|
151
|
+
else video.play().catch(() => {});
|
|
152
|
+
}
|
|
153
|
+
if (!frame) return;
|
|
154
|
+
const source = frame.dataset.src || frame.getAttribute("src") || sources.get(frame);
|
|
155
|
+
if (source) sources.set(frame, source);
|
|
156
|
+
if (motion.matches) {
|
|
157
|
+
frame.removeAttribute("src");
|
|
158
|
+
frame.hidden = true;
|
|
159
|
+
return;
|
|
160
|
+
}
|
|
161
|
+
frame.hidden = false;
|
|
162
|
+
if (source && frame.getAttribute("src") !== source) frame.setAttribute("src", source);
|
|
163
|
+
const style = globalThis.getComputedStyle(frame);
|
|
164
|
+
const [x, y] = style.objectPosition.split(" ").map((v) => Number.parseFloat(v) / 100);
|
|
165
|
+
const geometry = videoHeroFrameGeometry({
|
|
166
|
+
width: media.clientWidth,
|
|
167
|
+
height: media.clientHeight
|
|
168
|
+
}, style.objectFit, {
|
|
169
|
+
x: Number.isFinite(x) ? x : .5,
|
|
170
|
+
y: Number.isFinite(y) ? y : .5
|
|
171
|
+
});
|
|
172
|
+
for (const [property, value] of Object.entries(geometry)) frame.style.setProperty(property, `${value}px`);
|
|
173
|
+
};
|
|
174
|
+
const resize = new globalThis.ResizeObserver(update);
|
|
175
|
+
resize.observe(media);
|
|
176
|
+
const attributes = new globalThis.MutationObserver(update);
|
|
177
|
+
attributes.observe(hero, {
|
|
178
|
+
attributes: true,
|
|
179
|
+
attributeFilter: ["style", "class"]
|
|
180
|
+
});
|
|
181
|
+
const children = new globalThis.MutationObserver(update);
|
|
182
|
+
children.observe(media, {
|
|
183
|
+
childList: true,
|
|
184
|
+
subtree: true
|
|
185
|
+
});
|
|
186
|
+
globalThis.addEventListener("resize", update);
|
|
187
|
+
motion.addEventListener("change", update);
|
|
188
|
+
update();
|
|
189
|
+
return () => {
|
|
190
|
+
resize.disconnect();
|
|
191
|
+
attributes.disconnect();
|
|
192
|
+
children.disconnect();
|
|
193
|
+
globalThis.removeEventListener("resize", update);
|
|
194
|
+
motion.removeEventListener("change", update);
|
|
195
|
+
video?.pause();
|
|
196
|
+
frame?.removeAttribute("src");
|
|
197
|
+
};
|
|
198
|
+
}
|
|
199
|
+
//#endregion
|
|
200
|
+
//#region frontend/src/navigation-client.ts
|
|
201
|
+
const mounted$1 = /* @__PURE__ */ new WeakSet();
|
|
202
|
+
const inertLocks = /* @__PURE__ */ new WeakMap();
|
|
203
|
+
function inertBackground(panel) {
|
|
204
|
+
const locked = [];
|
|
205
|
+
for (let branch = panel; branch.parentElement; branch = branch.parentElement) {
|
|
206
|
+
for (const sibling of branch.parentElement.children) {
|
|
207
|
+
if (sibling === branch || !("inert" in sibling)) continue;
|
|
208
|
+
const node = sibling;
|
|
209
|
+
const lock = inertLocks.get(node) ?? {
|
|
210
|
+
count: 0,
|
|
211
|
+
original: node.inert
|
|
212
|
+
};
|
|
213
|
+
lock.count += 1;
|
|
214
|
+
inertLocks.set(node, lock);
|
|
215
|
+
node.inert = true;
|
|
216
|
+
locked.push(node);
|
|
217
|
+
}
|
|
218
|
+
if (branch.parentElement === panel.ownerDocument.body) break;
|
|
219
|
+
}
|
|
220
|
+
return () => {
|
|
221
|
+
for (const node of locked) {
|
|
222
|
+
const lock = inertLocks.get(node);
|
|
223
|
+
if (!lock || --lock.count > 0) continue;
|
|
224
|
+
node.inert = lock.original;
|
|
225
|
+
inertLocks.delete(node);
|
|
226
|
+
}
|
|
227
|
+
};
|
|
228
|
+
}
|
|
229
|
+
/** Mount the adapter's navigation markup once; cleanup restores server state.
|
|
230
|
+
* Native links retain ordinary Tab order (this is navigation, not an ARIA menu).
|
|
231
|
+
* Install navigationStyleSheet alongside the canonical presentation stylesheet. */
|
|
232
|
+
function mountDesignNavigation(root) {
|
|
233
|
+
const scope = root ?? (typeof document === "undefined" ? void 0 : document);
|
|
234
|
+
if (!scope) return () => {};
|
|
235
|
+
const cleanups = [];
|
|
236
|
+
const languageSelects = [...scope.querySelectorAll(".wp-block-polylang-language-switcher select.pll-switcher-select")];
|
|
237
|
+
if ("matches" in scope && typeof scope.matches === "function" && scope.matches(".wp-block-polylang-language-switcher select.pll-switcher-select")) languageSelects.unshift(scope);
|
|
238
|
+
for (const select of languageSelects) {
|
|
239
|
+
const view = select.ownerDocument.defaultView;
|
|
240
|
+
if (!view || mounted$1.has(select)) continue;
|
|
241
|
+
mounted$1.add(select);
|
|
242
|
+
const original = select.selectedIndex;
|
|
243
|
+
const change = (event) => {
|
|
244
|
+
event.stopImmediatePropagation();
|
|
245
|
+
const option = select.selectedOptions[0];
|
|
246
|
+
const value = option?.value.trim();
|
|
247
|
+
if (!option || option.disabled || !value || value.includes("\\")) return;
|
|
248
|
+
for (let index = 0; index < value.length; index++) if (value.charCodeAt(index) <= 32 || value.charCodeAt(index) === 127) return;
|
|
249
|
+
try {
|
|
250
|
+
const url = new URL(value, select.ownerDocument.baseURI);
|
|
251
|
+
if (!["http:", "https:"].includes(url.protocol) || url.username || url.password) return;
|
|
252
|
+
view.location.assign(url.href);
|
|
253
|
+
} catch {}
|
|
254
|
+
};
|
|
255
|
+
select.addEventListener("change", change, true);
|
|
256
|
+
cleanups.push(() => {
|
|
257
|
+
select.removeEventListener("change", change, true);
|
|
258
|
+
select.selectedIndex = original;
|
|
259
|
+
mounted$1.delete(select);
|
|
260
|
+
});
|
|
261
|
+
}
|
|
262
|
+
const languageMenus = [...scope.querySelectorAll("details[data-gqd-language-menu]")];
|
|
263
|
+
if ("matches" in scope && typeof scope.matches === "function" && scope.matches("details[data-gqd-language-menu]")) languageMenus.unshift(scope);
|
|
264
|
+
for (const menu of languageMenus) {
|
|
265
|
+
if (mounted$1.has(menu)) continue;
|
|
266
|
+
mounted$1.add(menu);
|
|
267
|
+
const original = menu.open;
|
|
268
|
+
const escape = (event) => {
|
|
269
|
+
if (event.key === "Escape" && menu.open) {
|
|
270
|
+
event.preventDefault();
|
|
271
|
+
menu.open = false;
|
|
272
|
+
menu.querySelector("summary")?.focus();
|
|
273
|
+
}
|
|
274
|
+
};
|
|
275
|
+
menu.addEventListener("keydown", escape);
|
|
276
|
+
cleanups.push(() => {
|
|
277
|
+
menu.removeEventListener("keydown", escape);
|
|
278
|
+
menu.open = original;
|
|
279
|
+
mounted$1.delete(menu);
|
|
280
|
+
});
|
|
281
|
+
}
|
|
282
|
+
const roots = [...scope.querySelectorAll("[data-gqd-navigation]")];
|
|
283
|
+
if ("matches" in scope && typeof scope.matches === "function" && scope.matches("[data-gqd-navigation]")) roots.unshift(scope);
|
|
284
|
+
for (const nav of roots) {
|
|
285
|
+
if (mounted$1.has(nav)) continue;
|
|
286
|
+
const view = nav.ownerDocument.defaultView;
|
|
287
|
+
const panel = nav.querySelector("[data-gqd-navigation-panel]");
|
|
288
|
+
const open = nav.querySelector("[data-gqd-navigation-open]");
|
|
289
|
+
const close = nav.querySelector("[data-gqd-navigation-close]");
|
|
290
|
+
if (!view || !panel || !open || !close) continue;
|
|
291
|
+
mounted$1.add(nav);
|
|
292
|
+
const buttons = [...nav.querySelectorAll("[data-gqd-submenu]")];
|
|
293
|
+
const lists = new Map(buttons.map((button) => [button, [...nav.querySelectorAll("[data-gqd-submenu-list]")].find((list) => list.id === button.getAttribute("aria-controls"))]));
|
|
294
|
+
const saved = /* @__PURE__ */ new Map();
|
|
295
|
+
const remember = (node, names) => saved.set(node, new Map(names.map((name) => [name, node.getAttribute(name)])));
|
|
296
|
+
remember(nav, ["data-gqd-navigation-enhanced", "data-gqd-overlay-active"]);
|
|
297
|
+
remember(panel, [
|
|
298
|
+
"hidden",
|
|
299
|
+
"role",
|
|
300
|
+
"aria-modal",
|
|
301
|
+
"aria-label",
|
|
302
|
+
"style"
|
|
303
|
+
]);
|
|
304
|
+
remember(open, ["aria-expanded"]);
|
|
305
|
+
buttons.forEach((button) => remember(button, ["aria-expanded"]));
|
|
306
|
+
for (const list of lists.values()) if (list) remember(list, ["hidden", "style"]);
|
|
307
|
+
const restore = (node, names) => {
|
|
308
|
+
for (const name of names) {
|
|
309
|
+
const value = saved.get(node)?.get(name);
|
|
310
|
+
if (value == null) node.removeAttribute(name);
|
|
311
|
+
else node.setAttribute(name, value);
|
|
312
|
+
}
|
|
313
|
+
};
|
|
314
|
+
const currentUrl = new URL(nav.ownerDocument.URL);
|
|
315
|
+
const path = (value) => value.replace(/\/+$/, "") || "/";
|
|
316
|
+
for (const anchor of nav.querySelectorAll("a[href]")) {
|
|
317
|
+
if (anchor.hasAttribute("aria-current")) continue;
|
|
318
|
+
try {
|
|
319
|
+
const target = new URL(anchor.getAttribute("href"), nav.ownerDocument.baseURI);
|
|
320
|
+
if (!target.hash && target.origin === currentUrl.origin && path(target.pathname) === path(currentUrl.pathname) && (!target.search || target.search === currentUrl.search)) {
|
|
321
|
+
remember(anchor, ["aria-current"]);
|
|
322
|
+
anchor.setAttribute("aria-current", "page");
|
|
323
|
+
}
|
|
324
|
+
} catch {}
|
|
325
|
+
}
|
|
326
|
+
const listeners = [];
|
|
327
|
+
const listen = (node, name, callback) => {
|
|
328
|
+
node.addEventListener(name, callback);
|
|
329
|
+
listeners.push(() => node.removeEventListener(name, callback));
|
|
330
|
+
};
|
|
331
|
+
let overlay = false;
|
|
332
|
+
let expanded = false;
|
|
333
|
+
let unlock;
|
|
334
|
+
const element = (target) => target && "nodeType" in target && target.nodeType === 1 ? target : null;
|
|
335
|
+
const setHidden = (node, hidden) => {
|
|
336
|
+
node.hidden = hidden;
|
|
337
|
+
restore(node, ["style"]);
|
|
338
|
+
if (hidden) node.style.setProperty("display", "none", "important");
|
|
339
|
+
};
|
|
340
|
+
const setSubmenu = (button, state) => {
|
|
341
|
+
const list = lists.get(button);
|
|
342
|
+
button.setAttribute("aria-expanded", String(state));
|
|
343
|
+
if (list) setHidden(list, !state);
|
|
344
|
+
if (!state && list) {
|
|
345
|
+
for (const nested of buttons) if (list.contains(nested)) {
|
|
346
|
+
nested.setAttribute("aria-expanded", "false");
|
|
347
|
+
const child = lists.get(nested);
|
|
348
|
+
if (child) setHidden(child, true);
|
|
349
|
+
}
|
|
350
|
+
}
|
|
351
|
+
};
|
|
352
|
+
const focusables = (node) => [...node.querySelectorAll("a[href],button:not([disabled]),summary,[tabindex=\"0\"]")].filter((candidate) => !candidate.closest("[hidden]") && view.getComputedStyle(candidate).visibility !== "hidden" && candidate.getClientRects().length > 0);
|
|
353
|
+
const setOverlay = (state, returnFocus = false) => {
|
|
354
|
+
expanded = state && overlay;
|
|
355
|
+
open.setAttribute("aria-expanded", String(expanded));
|
|
356
|
+
setHidden(panel, overlay && !expanded);
|
|
357
|
+
if (expanded) {
|
|
358
|
+
unlock ??= inertBackground(panel);
|
|
359
|
+
panel.setAttribute("role", "dialog");
|
|
360
|
+
panel.setAttribute("aria-modal", "true");
|
|
361
|
+
panel.setAttribute("aria-label", nav.getAttribute("aria-label") || "Navigation");
|
|
362
|
+
focusables(panel)[0]?.focus();
|
|
363
|
+
} else {
|
|
364
|
+
unlock?.();
|
|
365
|
+
unlock = void 0;
|
|
366
|
+
restore(panel, [
|
|
367
|
+
"role",
|
|
368
|
+
"aria-modal",
|
|
369
|
+
"aria-label"
|
|
370
|
+
]);
|
|
371
|
+
if (returnFocus) open.focus();
|
|
372
|
+
}
|
|
373
|
+
};
|
|
374
|
+
const threshold = view.getComputedStyle(nav).getPropertyValue("--gqd-navigation-breakpoint").trim() || "64rem";
|
|
375
|
+
const mobile = view.matchMedia(`(width < ${threshold})`);
|
|
376
|
+
const sync = () => {
|
|
377
|
+
const previous = overlay;
|
|
378
|
+
const focused = nav.ownerDocument.activeElement;
|
|
379
|
+
const panelFocused = focused !== null && panel.contains(focused);
|
|
380
|
+
overlay = nav.dataset.gqdOverlay === "always" || nav.dataset.gqdOverlay !== "never" && mobile.matches;
|
|
381
|
+
nav.toggleAttribute("data-gqd-overlay-active", overlay);
|
|
382
|
+
setOverlay(previous === overlay && expanded);
|
|
383
|
+
if (previous !== overlay) {
|
|
384
|
+
if (overlay && panelFocused) open.focus();
|
|
385
|
+
else if (!overlay && (focused === open || focused === close)) focusables(panel)[0]?.focus();
|
|
386
|
+
}
|
|
387
|
+
};
|
|
388
|
+
nav.setAttribute("data-gqd-navigation-enhanced", "");
|
|
389
|
+
for (const button of buttons) setSubmenu(button, nav.dataset.gqdSubmenuVisibility === "always");
|
|
390
|
+
sync();
|
|
391
|
+
listen(mobile, "change", sync);
|
|
392
|
+
listen(nav.ownerDocument, "focusin", (event) => {
|
|
393
|
+
const target = element(event.target);
|
|
394
|
+
if (expanded && target && !panel.contains(target)) focusables(panel)[0]?.focus();
|
|
395
|
+
});
|
|
396
|
+
listen(open, "click", () => setOverlay(true));
|
|
397
|
+
listen(close, "click", () => {
|
|
398
|
+
setOverlay(false, true);
|
|
399
|
+
});
|
|
400
|
+
for (const button of buttons) {
|
|
401
|
+
listen(button, "click", () => {
|
|
402
|
+
if (nav.dataset.gqdSubmenuVisibility !== "always") setSubmenu(button, button.getAttribute("aria-expanded") !== "true");
|
|
403
|
+
});
|
|
404
|
+
const row = button.closest("li") ?? button.parentElement;
|
|
405
|
+
const hover = () => {
|
|
406
|
+
if (nav.dataset.gqdSubmenuVisibility === "hover" && !overlay) setSubmenu(button, true);
|
|
407
|
+
};
|
|
408
|
+
listen(row, "pointerenter", hover);
|
|
409
|
+
listen(row, "pointerleave", () => {
|
|
410
|
+
if (nav.dataset.gqdSubmenuVisibility === "hover" && !row.contains(nav.ownerDocument.activeElement)) setSubmenu(button, false);
|
|
411
|
+
});
|
|
412
|
+
listen(row, "focusin", (event) => {
|
|
413
|
+
if (event.target !== button) hover();
|
|
414
|
+
});
|
|
415
|
+
listen(row, "focusout", (event) => {
|
|
416
|
+
const next = event.relatedTarget;
|
|
417
|
+
if (!next || !row.contains(next)) {
|
|
418
|
+
if (nav.dataset.gqdSubmenuVisibility !== "always") setSubmenu(button, false);
|
|
419
|
+
}
|
|
420
|
+
});
|
|
421
|
+
}
|
|
422
|
+
listen(nav, "keydown", (raw) => {
|
|
423
|
+
const event = raw;
|
|
424
|
+
const target = element(event.target);
|
|
425
|
+
if (!target || event.altKey || event.ctrlKey || event.metaKey) return;
|
|
426
|
+
const rtl = view.getComputedStyle(nav).direction === "rtl";
|
|
427
|
+
const button = target.closest("[data-gqd-submenu]");
|
|
428
|
+
if (button && ["ArrowDown", rtl ? "ArrowLeft" : "ArrowRight"].includes(event.key)) {
|
|
429
|
+
event.preventDefault();
|
|
430
|
+
setSubmenu(button, true);
|
|
431
|
+
const list = lists.get(button);
|
|
432
|
+
if (list) focusables(list)[0]?.focus();
|
|
433
|
+
return;
|
|
434
|
+
}
|
|
435
|
+
if (event.key === "Escape" || event.key === (rtl ? "ArrowRight" : "ArrowLeft")) {
|
|
436
|
+
const list = target.closest("[data-gqd-submenu-list]");
|
|
437
|
+
const row = target.closest("li");
|
|
438
|
+
const owner = (event.key === "Escape" && row ? buttons.find((candidate) => candidate.closest("li") === row && candidate.getAttribute("aria-expanded") === "true") : null) ?? (button?.getAttribute("aria-expanded") === "true" ? button : list ? buttons.find((candidate) => lists.get(candidate) === list) : null);
|
|
439
|
+
if (owner && owner.getAttribute("aria-expanded") === "true" && nav.dataset.gqdSubmenuVisibility !== "always") {
|
|
440
|
+
event.preventDefault();
|
|
441
|
+
event.stopPropagation();
|
|
442
|
+
setSubmenu(owner, false);
|
|
443
|
+
owner.focus();
|
|
444
|
+
return;
|
|
445
|
+
}
|
|
446
|
+
if (event.key === "Escape" && expanded) {
|
|
447
|
+
event.preventDefault();
|
|
448
|
+
setOverlay(false, true);
|
|
449
|
+
}
|
|
450
|
+
}
|
|
451
|
+
if (event.key === "Tab" && expanded) {
|
|
452
|
+
const candidates = focusables(panel);
|
|
453
|
+
const first = candidates[0], last = candidates.at(-1);
|
|
454
|
+
if (event.shiftKey && target === first) {
|
|
455
|
+
event.preventDefault();
|
|
456
|
+
last?.focus();
|
|
457
|
+
} else if (!event.shiftKey && target === last) {
|
|
458
|
+
event.preventDefault();
|
|
459
|
+
first?.focus();
|
|
460
|
+
}
|
|
461
|
+
}
|
|
462
|
+
});
|
|
463
|
+
listen(nav.ownerDocument, "pointerdown", (event) => {
|
|
464
|
+
const target = element(event.target);
|
|
465
|
+
if (target && !nav.contains(target) && nav.dataset.gqdSubmenuVisibility !== "always") buttons.forEach((button) => setSubmenu(button, false));
|
|
466
|
+
});
|
|
467
|
+
cleanups.push(() => {
|
|
468
|
+
listeners.forEach((remove) => remove());
|
|
469
|
+
unlock?.();
|
|
470
|
+
for (const [node, attributes] of saved) restore(node, [...attributes.keys()]);
|
|
471
|
+
mounted$1.delete(nav);
|
|
472
|
+
});
|
|
473
|
+
}
|
|
474
|
+
let disposed = false;
|
|
475
|
+
return () => {
|
|
476
|
+
if (disposed) return;
|
|
477
|
+
disposed = true;
|
|
478
|
+
cleanups.forEach((cleanup) => cleanup());
|
|
479
|
+
};
|
|
480
|
+
}
|
|
481
|
+
//#endregion
|
|
482
|
+
//#region frontend/src/cover-video-client.ts
|
|
483
|
+
const mounted = /* @__PURE__ */ new WeakSet();
|
|
484
|
+
/** Mount decorative native Cover backgrounds in neutral, saved or delivered HTML.
|
|
485
|
+
* No DOM access occurs until invocation. The Site owns mounting and cleanup. */
|
|
486
|
+
function mountDesignCoverVideos(root) {
|
|
487
|
+
const scope = root ?? document;
|
|
488
|
+
const cleanups = Array.from(scope.querySelectorAll(".wp-block-cover > video.wp-block-cover__video-background")).map((video) => {
|
|
489
|
+
const view = video.ownerDocument.defaultView;
|
|
490
|
+
if (!view || mounted.has(video)) return () => {};
|
|
491
|
+
mounted.add(video);
|
|
492
|
+
const motion = view.matchMedia("(prefers-reduced-motion: reduce)");
|
|
493
|
+
let active = true;
|
|
494
|
+
video.autoplay = false;
|
|
495
|
+
video.removeAttribute("autoplay");
|
|
496
|
+
video.muted = true;
|
|
497
|
+
const update = () => {
|
|
498
|
+
if (!active || motion.matches) {
|
|
499
|
+
video.pause();
|
|
500
|
+
return;
|
|
501
|
+
}
|
|
502
|
+
video.play().then(() => {
|
|
503
|
+
if (active && motion.matches || !active && !mounted.has(video)) video.pause();
|
|
504
|
+
}, () => {});
|
|
505
|
+
};
|
|
506
|
+
motion.addEventListener("change", update);
|
|
507
|
+
update();
|
|
508
|
+
return () => {
|
|
509
|
+
if (!active) return;
|
|
510
|
+
active = false;
|
|
511
|
+
motion.removeEventListener("change", update);
|
|
512
|
+
mounted.delete(video);
|
|
513
|
+
video.pause();
|
|
514
|
+
};
|
|
515
|
+
});
|
|
516
|
+
return () => cleanups.forEach((cleanup) => cleanup());
|
|
517
|
+
}
|
|
518
|
+
//#endregion
|
|
519
|
+
export { mountDesignCarousels, mountDesignCoverVideos, mountDesignNavigation, mountVideoHero };
|