@hubpav/hwio-web-runtime 0.5.0 → 0.6.1

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 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, and marks the nav link whose section is
4
- * in view ([data-hwio-scrollspy] nav with same-page anchors) with aria-current="location".
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, and marks the nav link whose section is
5
- * in view ([data-hwio-scrollspy] nav with same-page anchors) with aria-current="location".
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.5.0",
3
+ "version": "0.6.1",
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",