export function hasClickableParent(element: HTMLElement): boolean {
const parent = element.parentElement;
if (!parent) return false;
if (parent.dataset.n2Clickable) return true;
return hasClickableParent(element.parentElement);
}
/**
* Escape a string so it is safe to use as a CSS identifier (id/class) inside a selector.
* Prefers the native `CSS.escape` when available, falling back to a conservative
* backslash-escape for non-DOM environments (SSR, tests, older runtimes).
*/
export function cssEscapeIdent(value: string): string {
if (typeof CSS !== "undefined" && typeof CSS.escape === "function") {
return CSS.escape(value);
}
let escaped = "";
for (let i = 0; i < value.length; i += 1) {
const char = value.charAt(i);
const codeUnit = value.charCodeAt(i);
if (codeUnit === 0x0000) {
escaped += "\uFFFD";
} else if (
(codeUnit >= 0x0001 && codeUnit <= 0x001f) ||
codeUnit === 0x007f ||
(i === 0 && codeUnit >= 0x0030 && codeUnit <= 0x0039) ||
(i === 1 && codeUnit >= 0x0030 && codeUnit <= 0x0039 && value.charCodeAt(0) === 0x002d)
) {
escaped += `\\${codeUnit.toString(16)} `;
} else if (i === 0 && codeUnit === 0x002d && value.length === 1) {
escaped += "\\-";
} else if (
codeUnit >= 0x0080 ||
codeUnit === 0x002d ||
codeUnit === 0x005f ||
(codeUnit >= 0x0030 && codeUnit <= 0x0039) ||
(codeUnit >= 0x0041 && codeUnit <= 0x005a) ||
(codeUnit >= 0x0061 && codeUnit <= 0x007a)
) {
escaped += char;
} else {
escaped += `\\${char}`;
}
}
return escaped;
}