forked from nostr/nostrweb
refactor: type element attributes
use attributes of html element type. so that the following example is correctly typed: elem('input', { className: 'foo', hidden: false, onclick: () => alert('hi'), tabIndex: 1, valueAsNumber: 1, }); but this fails as foo is no valid attribute on div element: elem('div', {foo: 'bar'});
parent
489a260427
commit
6e404eac6b
|
@ -1,11 +1,11 @@
|
||||||
type Attributes = {
|
type DataAttributes = {
|
||||||
[key: string]: string | number;
|
data: {
|
||||||
} & {
|
|
||||||
data?: {
|
|
||||||
[key: string]: string | number;
|
[key: string]: string | number;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
type Attributes<Type> = Partial<Type & DataAttributes>;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* example usage:
|
* example usage:
|
||||||
*
|
*
|
||||||
|
@ -15,32 +15,44 @@ type Attributes = {
|
||||||
*
|
*
|
||||||
* @param {string} name
|
* @param {string} name
|
||||||
* @param {HTMLElement.prototype} props
|
* @param {HTMLElement.prototype} props
|
||||||
* @param {Array<HTMLElement|string>} children
|
* @param {Array<Node> | string | number} children
|
||||||
* @return HTMLElement
|
* @return HTMLElement
|
||||||
*/
|
*/
|
||||||
export const elem = <Name extends keyof HTMLElementTagNameMap>(
|
export const elem = <Name extends keyof HTMLElementTagNameMap>(
|
||||||
name: Extract<Name, keyof HTMLElementTagNameMap>,
|
name: Extract<Name, keyof HTMLElementTagNameMap>,
|
||||||
attrs: Attributes = {}, // TODO optional
|
attrs?: Attributes<HTMLElementTagNameMap[Name]>,
|
||||||
children: Array<Node> | string = [], // TODO optional
|
children?: Array<HTMLElement | string> | string | number,
|
||||||
): HTMLElementTagNameMap[Name] => {
|
): HTMLElementTagNameMap[Name] => {
|
||||||
const {data, ...props} = attrs;
|
|
||||||
const el = document.createElement(name);
|
const el = document.createElement(name);
|
||||||
|
if (attrs) {
|
||||||
|
const {data, ...props} = attrs;
|
||||||
Object.assign(el, props);
|
Object.assign(el, props);
|
||||||
if (Array.isArray(children)) {
|
|
||||||
el.append(...children);
|
|
||||||
} else {
|
|
||||||
const childType = typeof children;
|
|
||||||
if (childType === 'number' || childType === 'string') {
|
|
||||||
el.append(children);
|
|
||||||
} else {
|
|
||||||
console.error('call me');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (data) {
|
if (data) {
|
||||||
Object.entries(data).forEach(([key, value]) => {
|
Object.entries(data).forEach(([key, value]) => {
|
||||||
el.dataset[key] = value as string;
|
el.dataset[key] = value as string;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
if (children != null) {
|
||||||
|
if (Array.isArray(children)) {
|
||||||
|
el.append(...children);
|
||||||
|
} else {
|
||||||
|
switch (typeof children) {
|
||||||
|
case 'number':
|
||||||
|
el.append(`${children}`);
|
||||||
|
break;
|
||||||
|
case 'string':
|
||||||
|
el.append(children);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
if (children instanceof Element) {
|
||||||
|
el.append(children);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
console.error(`expected element, string or number but got ${typeof children}`, children);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
return el;
|
return el;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue