UNPKG

rvx

Version:

A signal based rendering library

62 lines (60 loc) 2.29 kB
import { Context } from "../context.js"; import { Attributes, ClassValue, EventArgs, EventListener, RefFn, StyleValue, TagNameMap, XMLNS } from "../element-common.js"; import { ENV } from "../env.js"; import { isolate } from "../isolate.js"; import { watch } from "../signals.js"; import { appendContent } from "./append-content.js"; import { setAttr } from "./set-attr.js"; import { setClass } from "./set-class.js"; import { setStyle } from "./set-style.js"; /** * Internal function to create a jsx element. * * @param tagName The tag name. * @param attrs The attributes to set with optional children. * @returns The element. */ export function createElement<K extends keyof TagNameMap>(tagName: K, attrs: Attributes<TagNameMap[K]>): TagNameMap[K]; export function createElement<E extends Element>(tagName: string, attrs: Attributes<E>): E; export function createElement(tagName: string, attrs: Attributes<TagNameMap[keyof TagNameMap]>): Element { const env = ENV.current; const elem = env.document.createElementNS(XMLNS.current, tagName); for (const name in attrs) { const value = attrs[name]; if (value !== undefined) { if (name === "children") { appendContent(elem, value, env); } else if (name.startsWith("on:")) { let listener: EventListener<Event>; let options: AddEventListenerOptions | undefined; if (Array.isArray(value)) { listener = (value as EventArgs<Event>)[0]; options = (value as EventArgs<Event>)[1]; } else { listener = value as EventListener<Event>; } const wrapped = Context.wrap(listener); elem.addEventListener(name.slice(3), event => isolate(wrapped, event), options); } else if (name.startsWith("prop:")) { const prop = name.slice(5); watch(value, value => (elem as any)[prop] = value); } else if (name.startsWith("attr:")) { const attr = name.slice(5); setAttr(elem, attr, value); } else if (name === "ref") { if (Array.isArray(value)) { value.forEach(v => (v as RefFn<Element>)(elem)); } else { (value as RefFn<Element>)(elem); } } else if (name === "style") { setStyle(elem, value as StyleValue); } else if (name === "class") { setClass(elem, value as ClassValue); } else { setAttr(elem, name, value); } } } return elem; }