Files
bookhoard/web/src/dom.ts
T
john-okeefe 149d14f5eb refactor(ts): Add ES module exports to core utilities
Phase 0/1 of ESBuild migration: Add ES exports to all utility modules
while maintaining Alpine.js registration for template compatibility.

Core utility modules now support both:
- ES module imports for TypeScript→TypeScript dependencies
- Alpine.js global namespace for template onclick handlers

Modules updated:
- api.ts: Export apiGet, apiPost, apiPut, apiDelete, apiPatch, and handlers
- toast.ts: Export showToast function (Alpine namespace already present)
- storage.ts: Export localStorage helpers (already had exports)
- dom.ts: Export DOM manipulation helpers (already had exports)
- events.ts: Export event delegation helpers
- theme.ts: Export theme management functions
- woodPaneling.ts: Export wood paneling functions

Pattern: Each module now has dual exports
- ES module exports for internal TS dependencies
- Alpine.global() registration for template access
- Removed direct window exports where Alpine registration exists

This enables Phase 1 (converting internal window reads to imports) while
maintaining template functionality through Alpine.

Migration progress: Phase 0 complete, Phase 1 in progress
Next: Convert 193+ internal window reads across consumer modules
2026-03-08 01:14:20 -05:00

121 lines
2.8 KiB
TypeScript

function escapeHtml(text: string): string {
const div = document.createElement("div");
div.textContent = text;
return div.innerHTML;
}
function querySelector<T extends Element>(selector: string): T | null {
return document.querySelector<T>(selector);
}
function querySelectorAll<T extends Element>(selector: string): NodeListOf<T> {
return document.querySelectorAll<T>(selector);
}
function getElementById<T extends HTMLElement>(id: string): T | null {
return document.getElementById(id) as T | null;
}
function createElement<K extends keyof HTMLElementTagNameMap>(
tagName: K,
attributes?: Record<string, string>,
children?: (string | Node)[],
): HTMLElementTagNameMap[K] {
const element = document.createElement(tagName);
if (attributes) {
Object.entries(attributes).forEach(([key, value]) => {
if (key === "className") {
element.className = value;
} else if (key === "dataset") {
Object.entries(JSON.parse(value)).forEach(([dataKey, dataValue]) => {
element.dataset[dataKey] = String(dataValue);
});
} else {
element.setAttribute(key, value);
}
});
}
if (children) {
children.forEach((child) => {
if (typeof child === "string") {
element.appendChild(document.createTextNode(child));
} else {
element.appendChild(child);
}
});
}
return element;
}
function showElement(element: HTMLElement | null): void {
if (element) {
element.classList.remove("hidden");
}
}
function hideElement(element: HTMLElement | null): void {
if (element) {
element.classList.add("hidden");
}
}
function toggleElement(element: HTMLElement | null): void {
if (element) {
element.classList.toggle("hidden");
}
}
function setTextContent(element: HTMLElement | null, text: string): void {
if (element) {
element.textContent = text;
}
}
function setInnerHTML(element: HTMLElement | null, html: string): void {
if (element) {
element.innerHTML = html;
}
}
function addClass(element: HTMLElement | null, className: string): void {
if (element) {
element.classList.add(className);
}
}
function removeClass(element: HTMLElement | null, className: string): void {
if (element) {
element.classList.remove(className);
}
}
function toggleClass(element: HTMLElement | null, className: string): void {
if (element) {
element.classList.toggle(className);
}
}
function hasClass(element: HTMLElement | null, className: string): boolean {
return element ? element.classList.contains(className) : false;
}
export {
addClass,
createElement,
escapeHtml,
getElementById,
hasClass,
hideElement,
querySelector,
querySelectorAll,
removeClass,
setInnerHTML,
setTextContent,
showElement,
toggleClass,
toggleElement,
};