///
type BasicProperties = {
[K in keyof T as T[K] extends string | number | boolean ? K : never]: T[K];
};
export type Child = Node | string | null;
export type SwelOpts = Partial<
BasicProperties
> & {
on: Partial<{
[Ev in keyof HTMLElementEventMap]: (
this: HTMLElement,
ev: HTMLElementEventMap[Ev],
) => void;
}>;
children: (Node | string)[] | null;
attributes: Record;
className: string;
style: Record | null;
};
export type Renderable = Child | Child[];
interface Swel {
(
tag: T,
opts?: Partial>,
): HTMLElementTagNameMap[T];
(
tag: T,
children?: Child[],
): HTMLElementTagNameMap[T];
(
tag: T,
child?: Child,
): HTMLElementTagNameMap[T];
(
tag: T,
opts?: Partial, "children">>,
children?: Child[],
): HTMLElementTagNameMap[T];
(
tag: T,
opts?: Partial, "children">>,
child?: Child,
): HTMLElementTagNameMap[T];
(
tag: T,
opts?: Partial, "children">>,
renderable?: Renderable,
): HTMLElementTagNameMap[T];
(
tag: T,
renderable?: Renderable,
): HTMLElementTagNameMap[T];
}
export const swel: Swel = (
tag: T,
opts?: Partial> | Renderable,
children?: Renderable,
): HTMLElementTagNameMap[T] => {
let o: Partial> | null = null;
if (children) {
let c: Child[] | null;
if (Array.isArray(children)) {
c = children;
} else {
c = [children];
}
o = {
...(opts as any),
children: c,
};
} else if (opts) {
if (Array.isArray(opts)) {
o = { children: opts } as any;
} else if (typeof opts === "string" || opts instanceof Node) {
o = { children: [opts] } as any;
} else {
o = opts;
}
} else {
o = {};
}
let o_ = o!;
if (o_.children) {
o_.children = o_.children.filter((c) => !!c) as any;
}
return swel_(tag, o);
};
const swel_ = (
tag: T,
opts: Partial> | null,
): HTMLElementTagNameMap[T] => {
const el = document.createElement(tag) as unknown as HTMLElementTagNameMap[T];
if (opts) {
const { children, on, attributes, style, ...rest } = opts;
if (children) {
el.append(...children);
}
if (on) {
Object.entries(on).forEach(([ev, h]) => {
el.addEventListener(ev, h as any);
});
}
if (attributes) {
Object.entries(attributes).map(([k, v]) => {
el.setAttribute(k, v as unknown as string);
});
}
if (style) {
Object.entries(style).map(([k, v]) => {
Reflect.set(el.style, k, v);
});
}
Object.assign(el, rest);
}
return el;
};