@hubpav/hwio-web-runtime 0.5.0 → 0.6.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/dist/forms.js +16 -0
- package/dist/nav.d.ts +5 -2
- package/dist/nav.js +53 -2
- package/package.json +1 -1
package/dist/forms.js
CHANGED
|
@@ -101,6 +101,22 @@ export function hwioFormsRuntime() {
|
|
|
101
101
|
status.hidden = true;
|
|
102
102
|
}
|
|
103
103
|
await hwioEnsureTurnstileToken(form);
|
|
104
|
+
if (form.querySelector('.cf-turnstile') && !form.querySelector('input[name="cf-turnstile-response"]')?.value) {
|
|
105
|
+
// The widget produced no token (script blocked, unsupported browser, timeout): say so instead of
|
|
106
|
+
// sending a request the endpoint has to reject.
|
|
107
|
+
hwioResetTurnstile(form);
|
|
108
|
+
if (submitBtn) {
|
|
109
|
+
submitBtn.disabled = false;
|
|
110
|
+
submitBtn.textContent = original;
|
|
111
|
+
}
|
|
112
|
+
if (status) {
|
|
113
|
+
status.hidden = false;
|
|
114
|
+
status.textContent = form.dataset.hsTurnstileMsg || error;
|
|
115
|
+
status.classList.add('hs-status-error');
|
|
116
|
+
}
|
|
117
|
+
console.error('form submission blocked: no Turnstile token');
|
|
118
|
+
return;
|
|
119
|
+
}
|
|
104
120
|
let fields = {};
|
|
105
121
|
for (const [name, value] of new FormData(form).entries())
|
|
106
122
|
if (typeof value === 'string')
|
package/dist/nav.d.ts
CHANGED
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Header behaviours: keeps aria-expanded on the DaisyUI drawer label in sync with its checkbox,
|
|
3
|
-
* closes the drawer when a link inside it is followed,
|
|
4
|
-
*
|
|
3
|
+
* closes the drawer when a link inside it is followed, opens HWioHeader's mega panels
|
|
4
|
+
* ([data-hwio-mega-trigger] buttons and their [data-hwio-mega-panel]; hover with intent on pointer
|
|
5
|
+
* devices, click, ArrowDown into the panel, Escape / outside click / focus leaving close; one at a
|
|
6
|
+
* time), and marks the nav link whose section is in view ([data-hwio-scrollspy] nav with same-page
|
|
7
|
+
* anchors) with aria-current="location".
|
|
5
8
|
*/
|
|
6
9
|
export declare function hwioNavRuntime(): import("./mount.js").HWioBinder;
|
package/dist/nav.js
CHANGED
|
@@ -1,8 +1,11 @@
|
|
|
1
1
|
import { hwioMount } from './mount.js';
|
|
2
2
|
/**
|
|
3
3
|
* Header behaviours: keeps aria-expanded on the DaisyUI drawer label in sync with its checkbox,
|
|
4
|
-
* closes the drawer when a link inside it is followed,
|
|
5
|
-
*
|
|
4
|
+
* closes the drawer when a link inside it is followed, opens HWioHeader's mega panels
|
|
5
|
+
* ([data-hwio-mega-trigger] buttons and their [data-hwio-mega-panel]; hover with intent on pointer
|
|
6
|
+
* devices, click, ArrowDown into the panel, Escape / outside click / focus leaving close; one at a
|
|
7
|
+
* time), and marks the nav link whose section is in view ([data-hwio-scrollspy] nav with same-page
|
|
8
|
+
* anchors) with aria-current="location".
|
|
6
9
|
*/
|
|
7
10
|
export function hwioNavRuntime() {
|
|
8
11
|
let controller = null;
|
|
@@ -29,6 +32,54 @@ export function hwioNavRuntime() {
|
|
|
29
32
|
sync();
|
|
30
33
|
} }, { signal });
|
|
31
34
|
});
|
|
35
|
+
const triggers = Array.from(document.querySelectorAll('[data-hwio-mega-trigger]'));
|
|
36
|
+
if (triggers.length) {
|
|
37
|
+
const panelOf = (trigger) => document.querySelector(`[data-hwio-mega-panel="${trigger.dataset.hwioMegaTrigger}"]`);
|
|
38
|
+
const pairs = triggers.map((trigger) => ({ trigger, panel: panelOf(trigger) })).filter((p) => !!p.panel);
|
|
39
|
+
const hoverable = window.matchMedia('(hover: hover)').matches;
|
|
40
|
+
let closeTimer = null;
|
|
41
|
+
const cancelClose = () => { if (closeTimer) {
|
|
42
|
+
clearTimeout(closeTimer);
|
|
43
|
+
closeTimer = null;
|
|
44
|
+
} };
|
|
45
|
+
const set = (pair, open) => { pair.trigger.setAttribute('aria-expanded', String(open)); pair.panel.hidden = !open; };
|
|
46
|
+
const closeAll = () => { cancelClose(); pairs.forEach((p) => set(p, false)); };
|
|
47
|
+
const openOne = (pair) => { cancelClose(); pairs.forEach((p) => set(p, p === pair)); };
|
|
48
|
+
const scheduleClose = () => { cancelClose(); closeTimer = setTimeout(closeAll, 180); };
|
|
49
|
+
const isOpen = (pair) => pair.trigger.getAttribute('aria-expanded') === 'true';
|
|
50
|
+
pairs.forEach((pair) => {
|
|
51
|
+
const { trigger, panel } = pair;
|
|
52
|
+
trigger.addEventListener('click', () => (isOpen(pair) ? closeAll() : openOne(pair)), { signal });
|
|
53
|
+
trigger.addEventListener('keydown', (e) => {
|
|
54
|
+
if (e.key !== 'ArrowDown')
|
|
55
|
+
return;
|
|
56
|
+
e.preventDefault();
|
|
57
|
+
openOne(pair);
|
|
58
|
+
panel.querySelector('a[href], button')?.focus();
|
|
59
|
+
}, { signal });
|
|
60
|
+
if (hoverable) {
|
|
61
|
+
trigger.addEventListener('mouseenter', () => openOne(pair), { signal });
|
|
62
|
+
trigger.addEventListener('mouseleave', scheduleClose, { signal });
|
|
63
|
+
panel.addEventListener('mouseenter', cancelClose, { signal });
|
|
64
|
+
panel.addEventListener('mouseleave', scheduleClose, { signal });
|
|
65
|
+
}
|
|
66
|
+
panel.addEventListener('keydown', (e) => { if (e.key === 'Escape') {
|
|
67
|
+
e.preventDefault();
|
|
68
|
+
closeAll();
|
|
69
|
+
trigger.focus();
|
|
70
|
+
} }, { signal });
|
|
71
|
+
panel.addEventListener('focusout', (e) => { const next = e.relatedTarget; if (next && !panel.contains(next) && next !== trigger)
|
|
72
|
+
closeAll(); }, { signal });
|
|
73
|
+
panel.querySelectorAll('a[href]').forEach((a) => a.addEventListener('click', closeAll, { signal }));
|
|
74
|
+
});
|
|
75
|
+
document.addEventListener('keydown', (e) => { if (e.key === 'Escape')
|
|
76
|
+
closeAll(); }, { signal });
|
|
77
|
+
document.addEventListener('click', (e) => {
|
|
78
|
+
const node = e.target;
|
|
79
|
+
if (!pairs.some((p) => p.trigger.contains(node) || p.panel.contains(node)))
|
|
80
|
+
closeAll();
|
|
81
|
+
}, { signal });
|
|
82
|
+
}
|
|
32
83
|
const nav = document.querySelector('[data-hwio-scrollspy]');
|
|
33
84
|
if (!nav || !('IntersectionObserver' in window))
|
|
34
85
|
return;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@hubpav/hwio-web-runtime",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.6.0",
|
|
4
4
|
"description": "Framework-free browser runtime for the HARDWARIO websites: consent (Consent Mode v2 + GTM), HubSpot forms with Turnstile, attribution, theme, CTA tracking and small behaviours. View-transition safe.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|