@kywi-software/js 0.6.7 → 0.7.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/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/kywi.esm.js +186 -0
- package/dist/kywi.esm.js.map +3 -3
- package/dist/kywi.js +186 -0
- package/dist/kywi.js.map +3 -3
- package/dist/nav/menu.d.ts +14 -0
- package/dist/nav/menu.d.ts.map +1 -0
- package/package.json +2 -2
package/dist/kywi.js
CHANGED
|
@@ -22,8 +22,11 @@ var Kywi = (() => {
|
|
|
22
22
|
var src_exports = {};
|
|
23
23
|
__export(src_exports, {
|
|
24
24
|
Kywi: () => Kywi,
|
|
25
|
+
NAV_BREAKPOINT: () => NAV_BREAKPOINT,
|
|
25
26
|
bootAudienceEngine: () => bootAudienceEngine,
|
|
26
27
|
bootExperiments: () => bootExperiments,
|
|
28
|
+
enhanceNav: () => enhanceNav,
|
|
29
|
+
initNavMenus: () => initNavMenus,
|
|
27
30
|
openTransparencyPanel: () => openTransparencyPanel,
|
|
28
31
|
renderTransparencyPanel: () => renderTransparencyPanel
|
|
29
32
|
});
|
|
@@ -319,6 +322,188 @@ var Kywi = (() => {
|
|
|
319
322
|
}
|
|
320
323
|
}
|
|
321
324
|
|
|
325
|
+
// src/nav/menu.ts
|
|
326
|
+
var NAV_BREAKPOINT = 860;
|
|
327
|
+
var CLOSE_DELAY_MS = 120;
|
|
328
|
+
var ITEM_CLASS = "kywi-nav-item--has-children";
|
|
329
|
+
var OPEN_CLASS = "kywi-nav-item--open";
|
|
330
|
+
var TOGGLE_CLASS = "kywi-nav-toggle";
|
|
331
|
+
var PANEL_CLASS = "kywi-nav-panel";
|
|
332
|
+
var FLIP_CLASS = "kywi-nav-panel--flip";
|
|
333
|
+
var READY_ATTRIBUTE = "data-kywi-nav-ready";
|
|
334
|
+
function directChild(parent, className) {
|
|
335
|
+
for (const child of Array.from(parent.children)) {
|
|
336
|
+
if (child instanceof HTMLElement && child.classList.contains(className)) return child;
|
|
337
|
+
}
|
|
338
|
+
return null;
|
|
339
|
+
}
|
|
340
|
+
function isDesktop() {
|
|
341
|
+
if (typeof window === "undefined") return false;
|
|
342
|
+
if (typeof window.matchMedia !== "function") return true;
|
|
343
|
+
return window.matchMedia(`(min-width: ${NAV_BREAKPOINT}px)`).matches;
|
|
344
|
+
}
|
|
345
|
+
function panelLinks(panel) {
|
|
346
|
+
return Array.from(panel.querySelectorAll("a[href], button:not([disabled])"));
|
|
347
|
+
}
|
|
348
|
+
function enhanceNav(nav) {
|
|
349
|
+
const cleanups = [];
|
|
350
|
+
const entries = [];
|
|
351
|
+
for (const item of Array.from(nav.querySelectorAll(`.${ITEM_CLASS}`))) {
|
|
352
|
+
const toggle = directChild(item, TOGGLE_CLASS);
|
|
353
|
+
const panel = directChild(item, PANEL_CLASS);
|
|
354
|
+
if (toggle && panel) entries.push({ item, toggle, panel });
|
|
355
|
+
}
|
|
356
|
+
if (entries.length === 0) return () => {
|
|
357
|
+
};
|
|
358
|
+
let closeTimer;
|
|
359
|
+
const cancelClose = () => {
|
|
360
|
+
if (closeTimer !== void 0) {
|
|
361
|
+
clearTimeout(closeTimer);
|
|
362
|
+
closeTimer = void 0;
|
|
363
|
+
}
|
|
364
|
+
};
|
|
365
|
+
function isOpen(entry) {
|
|
366
|
+
return entry.item.classList.contains(OPEN_CLASS);
|
|
367
|
+
}
|
|
368
|
+
function close(entry) {
|
|
369
|
+
entry.item.classList.remove(OPEN_CLASS);
|
|
370
|
+
entry.toggle.setAttribute("aria-expanded", "false");
|
|
371
|
+
entry.panel.classList.remove(FLIP_CLASS);
|
|
372
|
+
}
|
|
373
|
+
function closeAll(except) {
|
|
374
|
+
for (const entry of entries) {
|
|
375
|
+
if (except && (entry === except || entry.item.contains(except.item))) continue;
|
|
376
|
+
close(entry);
|
|
377
|
+
}
|
|
378
|
+
}
|
|
379
|
+
function applyEdgeFlip(entry) {
|
|
380
|
+
if (typeof entry.panel.getBoundingClientRect !== "function") return;
|
|
381
|
+
entry.panel.classList.remove(FLIP_CLASS);
|
|
382
|
+
const rect = entry.panel.getBoundingClientRect();
|
|
383
|
+
const viewport = window.innerWidth || document.documentElement.clientWidth || 0;
|
|
384
|
+
if (viewport > 0 && rect.width > 0 && rect.right > viewport - 4) {
|
|
385
|
+
entry.panel.classList.add(FLIP_CLASS);
|
|
386
|
+
}
|
|
387
|
+
}
|
|
388
|
+
function open(entry) {
|
|
389
|
+
cancelClose();
|
|
390
|
+
closeAll(entry);
|
|
391
|
+
entry.item.classList.add(OPEN_CLASS);
|
|
392
|
+
entry.toggle.setAttribute("aria-expanded", "true");
|
|
393
|
+
applyEdgeFlip(entry);
|
|
394
|
+
}
|
|
395
|
+
function on(target, type, handler, options) {
|
|
396
|
+
target.addEventListener(type, handler, options);
|
|
397
|
+
cleanups.push(() => target.removeEventListener(type, handler, options));
|
|
398
|
+
}
|
|
399
|
+
for (const entry of entries) {
|
|
400
|
+
on(entry.toggle, "click", (event) => {
|
|
401
|
+
event.preventDefault();
|
|
402
|
+
if (isOpen(entry)) {
|
|
403
|
+
close(entry);
|
|
404
|
+
} else {
|
|
405
|
+
open(entry);
|
|
406
|
+
}
|
|
407
|
+
});
|
|
408
|
+
on(entry.item, "mouseenter", () => {
|
|
409
|
+
if (!isDesktop()) return;
|
|
410
|
+
open(entry);
|
|
411
|
+
});
|
|
412
|
+
on(entry.item, "mouseleave", () => {
|
|
413
|
+
if (!isDesktop()) return;
|
|
414
|
+
cancelClose();
|
|
415
|
+
closeTimer = setTimeout(() => {
|
|
416
|
+
close(entry);
|
|
417
|
+
closeTimer = void 0;
|
|
418
|
+
}, CLOSE_DELAY_MS);
|
|
419
|
+
});
|
|
420
|
+
}
|
|
421
|
+
on(nav, "focusin", (event) => {
|
|
422
|
+
const target = event.target;
|
|
423
|
+
if (!target) return;
|
|
424
|
+
for (const entry of entries) {
|
|
425
|
+
if (entry.panel.contains(target)) {
|
|
426
|
+
open(entry);
|
|
427
|
+
return;
|
|
428
|
+
}
|
|
429
|
+
}
|
|
430
|
+
for (const entry of entries) {
|
|
431
|
+
if (!entry.item.contains(target)) close(entry);
|
|
432
|
+
}
|
|
433
|
+
});
|
|
434
|
+
on(nav, "keydown", (event) => {
|
|
435
|
+
const target = event.target;
|
|
436
|
+
if (!target) return;
|
|
437
|
+
const entry = entries.find((e) => e.item.contains(target));
|
|
438
|
+
if (!entry) return;
|
|
439
|
+
if (event.key === "Escape") {
|
|
440
|
+
const openEntry = entries.filter((e) => e.item.contains(target) && isOpen(e)).pop();
|
|
441
|
+
if (!openEntry) return;
|
|
442
|
+
event.preventDefault();
|
|
443
|
+
close(openEntry);
|
|
444
|
+
openEntry.toggle.focus();
|
|
445
|
+
return;
|
|
446
|
+
}
|
|
447
|
+
if (event.key !== "ArrowDown" && event.key !== "ArrowUp") return;
|
|
448
|
+
if (target === entry.toggle) {
|
|
449
|
+
if (event.key === "ArrowDown") {
|
|
450
|
+
event.preventDefault();
|
|
451
|
+
if (!isOpen(entry)) open(entry);
|
|
452
|
+
panelLinks(entry.panel)[0]?.focus();
|
|
453
|
+
} else if (isOpen(entry)) {
|
|
454
|
+
event.preventDefault();
|
|
455
|
+
close(entry);
|
|
456
|
+
}
|
|
457
|
+
return;
|
|
458
|
+
}
|
|
459
|
+
const owner = entries.find((e) => e.panel.contains(target));
|
|
460
|
+
if (!owner) return;
|
|
461
|
+
const links = panelLinks(owner.panel);
|
|
462
|
+
const index = links.indexOf(target);
|
|
463
|
+
if (index === -1) return;
|
|
464
|
+
event.preventDefault();
|
|
465
|
+
const next = event.key === "ArrowDown" ? links[(index + 1) % links.length] : links[(index - 1 + links.length) % links.length];
|
|
466
|
+
next?.focus();
|
|
467
|
+
});
|
|
468
|
+
on(document, "click", (event) => {
|
|
469
|
+
const target = event.target;
|
|
470
|
+
if (target && nav.contains(target)) return;
|
|
471
|
+
cancelClose();
|
|
472
|
+
closeAll();
|
|
473
|
+
});
|
|
474
|
+
if (typeof window.matchMedia === "function") {
|
|
475
|
+
const query = window.matchMedia(`(min-width: ${NAV_BREAKPOINT}px)`);
|
|
476
|
+
const onChange = () => {
|
|
477
|
+
cancelClose();
|
|
478
|
+
closeAll();
|
|
479
|
+
};
|
|
480
|
+
if (typeof query.addEventListener === "function") {
|
|
481
|
+
query.addEventListener("change", onChange);
|
|
482
|
+
cleanups.push(() => query.removeEventListener("change", onChange));
|
|
483
|
+
}
|
|
484
|
+
}
|
|
485
|
+
nav.setAttribute(READY_ATTRIBUTE, "");
|
|
486
|
+
return () => {
|
|
487
|
+
cancelClose();
|
|
488
|
+
for (const undo of cleanups) undo();
|
|
489
|
+
cleanups.length = 0;
|
|
490
|
+
closeAll();
|
|
491
|
+
nav.removeAttribute(READY_ATTRIBUTE);
|
|
492
|
+
};
|
|
493
|
+
}
|
|
494
|
+
function initNavMenus(root = document) {
|
|
495
|
+
if (typeof document === "undefined") return () => {
|
|
496
|
+
};
|
|
497
|
+
const teardowns = [];
|
|
498
|
+
for (const nav of Array.from(root.querySelectorAll("[data-kywi-nav]"))) {
|
|
499
|
+
if (nav.hasAttribute(READY_ATTRIBUTE)) continue;
|
|
500
|
+
teardowns.push(enhanceNav(nav));
|
|
501
|
+
}
|
|
502
|
+
return () => {
|
|
503
|
+
for (const undo of teardowns) undo();
|
|
504
|
+
};
|
|
505
|
+
}
|
|
506
|
+
|
|
322
507
|
// src/experiments/index.ts
|
|
323
508
|
function apiBaseFrom(ctx) {
|
|
324
509
|
return ctx.basePath && ctx.basePath !== "/" ? `${ctx.basePath}/api/v1` : "/api/v1";
|
|
@@ -1526,6 +1711,7 @@ var Kywi = (() => {
|
|
|
1526
1711
|
Kywi.renderFeed = renderFeed;
|
|
1527
1712
|
initModules();
|
|
1528
1713
|
initFormHooks();
|
|
1714
|
+
initNavMenus();
|
|
1529
1715
|
bootExperiments({ context: Kywi.context });
|
|
1530
1716
|
booted = true;
|
|
1531
1717
|
}
|