59 lines
1.6 KiB
TypeScript
59 lines
1.6 KiB
TypeScript
type Child = Node | string | number | null | undefined | false;
|
|||
|
|
|
||
|
|
type Props<K extends keyof HTMLElementTagNameMap> = Partial<Omit<HTMLElementTagNameMap[K], "style" | "dataset">> & {
|
||
|
|
class?: string;
|
||
|
|
style?: string;
|
||
|
|
data?: Record<string, string>;
|
||
|
|
};
|
||
|
|
|
||
|
|
export function h<K extends keyof HTMLElementTagNameMap>(tag: K, props: Props<K> = {}, ...children: Child[]): HTMLElementTagNameMap[K] {
|
||
|
|
const el = document.createElement(tag);
|
||
|
|
const { class: className, style, data, ...rest } = props;
|
||
|
|
|
||
|
|
if (className) {
|
||
|
|
el.className = className;
|
||
|
|
}
|
||
|
|
if (style) {
|
||
|
|
el.setAttribute("style", style);
|
||
|
|
}
|
||
|
|
for (const [key, value] of Object.entries(data ?? {})) {
|
||
|
|
el.dataset[key] = value;
|
||
|
|
}
|
||
|
|
Object.assign(el, rest);
|
||
|
|
|
||
|
|
append(el, ...children);
|
||
|
|
return el;
|
||
|
|
}
|
||
|
|
|
||
|
|
export function append(el: Node, ...children: Child[]): void {
|
||
|
|
for (const child of children) {
|
||
|
|
if (child === null || child === undefined || child === false) {
|
||
|
|
continue;
|
||
|
|
}
|
||
|
|
el.appendChild(typeof child === "object" ? child : document.createTextNode(String(child)));
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
export function replace(el: Element, ...children: Child[]): void {
|
||
|
|
el.replaceChildren();
|
||
|
|
append(el, ...children);
|
||
|
|
}
|
||
|
|
|
||
|
|
export function ago(iso: string): string {
|
||
|
|
const seconds = Math.round((Date.now() - Date.parse(iso)) / 1000);
|
||
|
|
if (seconds < 60) {
|
||
|
|
return "just now";
|
||
|
|
}
|
||
|
|
if (seconds < 3600) {
|
||
|
|
return `${Math.floor(seconds / 60)}m ago`;
|
||
|
|
}
|
||
|
|
if (seconds < 86400) {
|
||
|
|
return `${Math.floor(seconds / 3600)}h ago`;
|
||
|
|
}
|
||
|
|
return `${Math.floor(seconds / 86400)}d ago`;
|
||
|
|
}
|
||
|
|
|
||
|
|
export function errorText(err: unknown): string {
|
||
|
|
return err instanceof Error ? err.message : String(err);
|
||
|
|
}
|