1import { $$, asElement } from "./dom";
2
3const isInteractive = (target: EventTarget | null): boolean =>
4 !!asElement(target)?.closest("a, button, input, textarea, select");
5
6/**
7 * Make [data-card-link] elements clickable/keyboard-activatable as a whole,
8 * while leaving inner interactive elements working. Internal links go through
9 * the injected navigate(); external links open in a new tab.
10 */
11export const initCards = (
12 signal: AbortSignal,
13 navigate: (url: string) => void,
14): void => {
15 $$<HTMLElement>("[data-card-link]").forEach((card) => {
16 const href = card.dataset.cardLink;
17 if (!href) return;
18 const external = card.dataset.cardExternal === "true";
19
20 const go = () => {
21 if (external) window.open(href, "_blank", "noopener,noreferrer");
22 else navigate(href);
23 };
24
25 card.addEventListener("click", (e) => {
26 if (!isInteractive(e.target)) go();
27 }, { signal });
28
29 card.addEventListener("keydown", (e) => {
30 if (isInteractive(e.target)) return;
31 if (e.key === "Enter" || e.key === " ") {
32 e.preventDefault();
33 go();
34 }
35 }, { signal });
36 });
37};