You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
134 lines
3.0 KiB
TypeScript
134 lines
3.0 KiB
TypeScript
/// <reference lib="dom" />
|
|
|
|
type BasicProperties<T> = {
|
|
[K in keyof T as T[K] extends string | number | boolean ? K : never]: T[K];
|
|
};
|
|
|
|
export type Child = Node | string | null;
|
|
export type SwelOpts<T extends keyof HTMLElementTagNameMap> = Partial<
|
|
BasicProperties<HTMLElementTagNameMap[T]>
|
|
> & {
|
|
on: Partial<{
|
|
[Ev in keyof HTMLElementEventMap]: (
|
|
this: HTMLElement,
|
|
ev: HTMLElementEventMap[Ev],
|
|
) => void;
|
|
}>;
|
|
children: (Node | string)[] | null;
|
|
attributes: Record<string, string | boolean | number>;
|
|
className: string;
|
|
style: Record<string, string | boolean | number> | null;
|
|
};
|
|
|
|
export type Renderable = Child | Child[];
|
|
|
|
interface Swel {
|
|
<T extends keyof HTMLElementTagNameMap>(
|
|
tag: T,
|
|
opts?: Partial<SwelOpts<T>>,
|
|
): HTMLElementTagNameMap[T];
|
|
|
|
<T extends keyof HTMLElementTagNameMap>(
|
|
tag: T,
|
|
children?: Child[],
|
|
): HTMLElementTagNameMap[T];
|
|
|
|
<T extends keyof HTMLElementTagNameMap>(
|
|
tag: T,
|
|
child?: Child,
|
|
): HTMLElementTagNameMap[T];
|
|
|
|
<T extends keyof HTMLElementTagNameMap>(
|
|
tag: T,
|
|
opts?: Partial<Omit<SwelOpts<T>, "children">>,
|
|
children?: Child[],
|
|
): HTMLElementTagNameMap[T];
|
|
|
|
<T extends keyof HTMLElementTagNameMap>(
|
|
tag: T,
|
|
opts?: Partial<Omit<SwelOpts<T>, "children">>,
|
|
child?: Child,
|
|
): HTMLElementTagNameMap[T];
|
|
|
|
<T extends keyof HTMLElementTagNameMap>(
|
|
tag: T,
|
|
opts?: Partial<Omit<SwelOpts<T>, "children">>,
|
|
renderable?: Renderable,
|
|
): HTMLElementTagNameMap[T];
|
|
|
|
<T extends keyof HTMLElementTagNameMap>(
|
|
tag: T,
|
|
renderable?: Renderable,
|
|
): HTMLElementTagNameMap[T];
|
|
}
|
|
|
|
export const swel: Swel = <T extends keyof HTMLElementTagNameMap>(
|
|
tag: T,
|
|
opts?: Partial<SwelOpts<T>> | Renderable,
|
|
children?: Renderable,
|
|
): HTMLElementTagNameMap[T] => {
|
|
let o: Partial<SwelOpts<T>> | 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_ = <T extends keyof HTMLElementTagNameMap>(
|
|
tag: T,
|
|
opts: Partial<SwelOpts<T>> | 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;
|
|
};
|