/// 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; };