janadom
Version:
A minimal and complete implementation of React JSX creating native DOM elements.
180 lines (176 loc) • 4.18 kB
JavaScript
var __defProp = Object.defineProperty;
var __markAsModule = (target) => __defProp(target, "__esModule", {value: true});
var __export = (target, all) => {
for (var name in all)
__defProp(target, name, {get: all[name], enumerable: true});
};
// src/index.ts
__markAsModule(exports);
__export(exports, {
createEl: () => createEl,
createRef: () => createRef
});
// src/svg-tags.ts
var svg_tags_default = [
"altGlyph",
"altGlyphDef",
"altGlyphItem",
"animate",
"animateColor",
"animateMotion",
"animateTransform",
"animation",
"circle",
"clipPath",
"color-profile",
"cursor",
"defs",
"desc",
"discard",
"ellipse",
"feBlend",
"feColorMatrix",
"feComponentTransfer",
"feComposite",
"feConvolveMatrix",
"feDiffuseLighting",
"feDisplacementMap",
"feDistantLight",
"feDropShadow",
"feFlood",
"feFuncA",
"feFuncB",
"feFuncG",
"feFuncR",
"feGaussianBlur",
"feImage",
"feMerge",
"feMergeNode",
"feMorphology",
"feOffset",
"fePointLight",
"feSpecularLighting",
"feSpotLight",
"feTile",
"feTurbulence",
"filter",
"font-face",
"font-face-format",
"font-face-name",
"font-face-src",
"font-face-uri",
"foreignObject",
"g",
"glyph",
"glyphRef",
"handler",
"hkern",
"line",
"linearGradient",
"listener",
"marker",
"mask",
"metadata",
"missing-glyph",
"mpath",
"path",
"pattern",
"polygon",
"polyline",
"prefetch",
"radialGradient",
"rect",
"set",
"solidColor",
"stop",
"switch",
"symbol",
"tbreak",
"text",
"textArea",
"textPath",
"tref",
"tspan",
"unknown",
"use",
"view",
"vkern"
];
// src/index.ts
function createRef(el = null) {
return {current: el};
}
function createEl(type, props, ...children) {
let el;
if (typeof type === "string") {
el = svg_tags_default.includes(type) ? document.createElementNS("http://www.w3.org/2000/svg", type) : document.createElement(type);
} else if (type === DocumentFragment) {
el = document.createDocumentFragment();
} else if (typeof type === "function") {
return type(props, ...children);
} else {
throw new TypeError(`invalid element type ${type}`);
}
for (const name in props) {
const value = props[name];
if (value != null && value !== false) {
if (name === "ref") {
if (typeof value === "object")
value.current = el;
else if (typeof value === "function")
value(el);
else
setAttr(el, name, value);
} else if (name === "style") {
if (typeof value !== "object")
setAttr(el, name, value);
else
Object.assign(el.style, value);
} else if (name.startsWith("on") && typeof value === "function") {
listenTo(el, name, value);
} else {
setAttr(el, name, value);
}
}
}
const parent = el instanceof HTMLTemplateElement ? el.content : el;
for (const child of children)
appendChild(parent, child);
return el;
}
function setAttr(el, name, value) {
if (typeof value === "string") {
if (name.startsWith("xlink:"))
el.setAttributeNS("http://www.w3.org/1999/xlink", name, value);
else
el.setAttribute(name, value);
} else if (typeof value === "number") {
el.setAttribute(name, value.toString());
} else if (typeof value === "boolean") {
el.setAttribute(name, "");
} else {
throw new TypeError(`invalid attribute type ${typeof value} for ${name}`);
}
}
function listenTo(el, name, listener) {
let useCapture;
if (name.endsWith("Capture")) {
name = name.substring(2, name.length - 7);
useCapture = true;
} else {
name = name.substr(2);
}
el.addEventListener(name.toLowerCase(), listener, useCapture);
}
function appendChild(parent, child) {
if (typeof child === "string")
parent.appendChild(document.createTextNode(child));
else if (typeof child === "number")
parent.appendChild(document.createTextNode(child.toString()));
else if (child instanceof Element)
parent.appendChild(child);
else if (Array.isArray(child))
for (const grandchild of child)
appendChild(parent, grandchild);
}
//# sourceMappingURL=index.js.map