typed-dom
Version:
A value-level and type-level DOM builder.
367 lines (346 loc) • 13.6 kB
JavaScript
/*! typed-dom v0.0.349 https://github.com/falsandtru/typed-dom | (c) 2016, falsandtru | (Apache-2.0 AND MPL-2.0) License */
(function webpackUniversalModuleDefinition(root, factory) {
if(typeof exports === 'object' && typeof module === 'object')
module.exports = factory();
else if(typeof define === 'function' && define.amd)
define([], factory);
else if(typeof exports === 'object')
exports["typed-dom"] = factory();
else
root["typed-dom"] = factory();
})(this, () => {
return /******/ (() => { // webpackBootstrap
/******/ "use strict";
/******/ var __webpack_modules__ = ({
/***/ 5413:
/***/ ((__unused_webpack_module, exports) => {
Object.defineProperty(exports, "__esModule", ({
value: true
}));
exports.ObjectSetPrototypeOf = exports.ObjectGetPrototypeOf = exports.ObjectCreate = exports.ObjectAssign = exports.toString = exports.isEnumerable = exports.isPrototypeOf = exports.hasOwnProperty = exports.isArray = exports.sqrt = exports.log10 = exports.log2 = exports.log = exports.tan = exports.cos = exports.sign = exports.round = exports.random = exports.min = exports.max = exports.floor = exports.ceil = exports.abs = exports.PI = exports.parseInt = exports.parseFloat = exports.isSafeInteger = exports.isNaN = exports.isInteger = exports.isFinite = exports.EPSILON = exports.MIN_VALUE = exports.MIN_SAFE_INTEGER = exports.MAX_VALUE = exports.MAX_SAFE_INTEGER = void 0;
exports.MAX_SAFE_INTEGER = Number.MAX_SAFE_INTEGER, exports.MAX_VALUE = Number.MAX_VALUE, exports.MIN_SAFE_INTEGER = Number.MIN_SAFE_INTEGER, exports.MIN_VALUE = Number.MIN_VALUE, exports.EPSILON = Number.EPSILON, exports.isFinite = Number.isFinite, exports.isInteger = Number.isInteger, exports.isNaN = Number.isNaN, exports.isSafeInteger = Number.isSafeInteger, exports.parseFloat = Number.parseFloat, exports.parseInt = Number.parseInt;
exports.PI = Math.PI, exports.abs = Math.abs, exports.ceil = Math.ceil, exports.floor = Math.floor, exports.max = Math.max, exports.min = Math.min, exports.random = Math.random, exports.round = Math.round, exports.sign = Math.sign, exports.cos = Math.cos, exports.tan = Math.tan, exports.log = Math.log, exports.log2 = Math.log2, exports.log10 = Math.log10, exports.sqrt = Math.sqrt;
exports.isArray = Array.isArray;
exports.hasOwnProperty = Object.prototype.hasOwnProperty.call.bind(Object.prototype.hasOwnProperty);
exports.isPrototypeOf = Object.prototype.isPrototypeOf.call.bind(Object.prototype.isPrototypeOf);
exports.isEnumerable = Object.prototype.propertyIsEnumerable.call.bind(Object.prototype.propertyIsEnumerable);
exports.toString = Object.prototype.toString.call.bind(Object.prototype.toString);
exports.ObjectAssign = Object.assign;
exports.ObjectCreate = Object.create;
exports.ObjectGetPrototypeOf = Object.getPrototypeOf;
exports.ObjectSetPrototypeOf = Object.setPrototypeOf;
/***/ }),
/***/ 1934:
/***/ ((__unused_webpack_module, exports) => {
Object.defineProperty(exports, "__esModule", ({
value: true
}));
exports.equal = void 0;
function equal(a, b) {
return a === a ? a === b : b !== b;
}
exports.equal = equal;
/***/ }),
/***/ 6925:
/***/ ((__unused_webpack_module, exports, __webpack_require__) => {
Object.defineProperty(exports, "__esModule", ({
value: true
}));
exports.reduce = exports.memoize = void 0;
const alias_1 = __webpack_require__(5413);
const compare_1 = __webpack_require__(1934);
function memoize(f, identify, memory) {
if (typeof identify === 'object') {
memory = identify;
identify = undefined;
}
identify ??= (...as) => as[0];
switch (true) {
case (0, alias_1.isArray)(memory):
return memoizeArray(f, identify, memory);
case memory?.constructor === Object:
return memoizeObject(f, identify, memory);
default:
return memoizeDict(f, identify, memory ?? new Map());
}
}
exports.memoize = memoize;
function memoizeArray(f, identify, memory) {
return (...as) => {
const b = identify(...as);
let z = memory[b];
if (z !== undefined) return z;
z = f(...as);
memory[b] = z;
return z;
};
}
function memoizeObject(f, identify, memory) {
let nullable = false;
return (...as) => {
const b = identify(...as);
let z = memory[b];
if (z !== undefined || nullable && b in memory) return z;
z = f(...as);
nullable ||= z === undefined;
memory[b] = z;
return z;
};
}
function memoizeDict(f, identify, memory) {
let nullable = false;
return (...as) => {
const b = identify(...as);
let z = memory.get(b);
if (z !== undefined || nullable && memory.has(b)) return z;
z = f(...as);
nullable ||= z === undefined;
memory.add?.(b, z) ?? memory.set(b, z);
return z;
};
}
function reduce(f, identify = (...as) => as[0]) {
let key = {};
let val;
return (...as) => {
const b = identify(...as);
if (!(0, compare_1.equal)(key, b)) {
key = b;
val = f(...as);
}
return val;
};
}
exports.reduce = reduce;
/***/ }),
/***/ 5761:
/***/ ((__unused_webpack_module, exports, __webpack_require__) => {
Object.defineProperty(exports, "__esModule", ({
value: true
}));
exports.defrag = exports.prepend = exports.append = exports.isChildren = exports.define = exports.element = exports.text = exports.math = exports.svg = exports.html = exports.frag = exports.shadow = void 0;
const alias_1 = __webpack_require__(5413);
const memoize_1 = __webpack_require__(6925);
var caches;
(function (caches) {
// Closed only.
caches.shadows = new WeakMap();
caches.shadow = (0, memoize_1.memoize)((el, opts) => el.attachShadow(opts), caches.shadows);
caches.fragment = document.createDocumentFragment();
})(caches || (caches = {}));
function shadow(el, opts, children, factory = exports.html) {
if (typeof el === 'string') return shadow(factory(el), opts, children, factory);
if (typeof opts === 'function') return shadow(el, undefined, children, opts);
if (typeof children === 'function') return shadow(el, opts, undefined, children);
if (isChildren(opts)) return shadow(el, undefined, opts, factory);
return defineChildren(!opts ? el.shadowRoot ?? caches.shadows.get(el) ?? el.attachShadow({
mode: 'open'
}) : opts.mode === 'open' ? el.shadowRoot ?? el.attachShadow(opts) : caches.shadow(el, opts), children);
}
exports.shadow = shadow;
function frag(children) {
return defineChildren(caches.fragment.cloneNode(true), children);
}
exports.frag = frag;
exports.html = element(document, "HTML" /* NS.HTML */);
exports.svg = element(document, "SVG" /* NS.SVG */);
exports.math = element(document, "MathML" /* NS.Math */);
function text(source) {
return document.createTextNode(source);
}
exports.text = text;
function element(context, ns) {
return (tag, attrs, children) => {
return !attrs || isChildren(attrs) ? defineChildren(elem(context, ns, tag, {}), attrs ?? children) : defineChildren(defineAttrs(elem(context, ns, tag, attrs), attrs), children);
};
}
exports.element = element;
function elem(context, ns, tag, attrs) {
if (!('createElement' in context)) throw new Error(`Typed-DOM: Scoped custom elements are not supported on this browser`);
const opts = 'is' in attrs ? {
is: attrs['is']
} : undefined;
switch (ns) {
case "HTML" /* NS.HTML */:
return context.createElement(tag, opts);
case "SVG" /* NS.SVG */:
return context.createElementNS('http://www.w3.org/2000/svg', tag, opts);
case "MathML" /* NS.Math */:
return context.createElementNS('http://www.w3.org/1998/Math/MathML', tag, opts);
}
}
function define(node, attrs, children) {
// Bug: TypeScript
// Need the next type assertions to suppress an impossible type error on dependent projects.
// Probably caused by typed-query-selector.
//
// typed-dom/dom.ts(113,3): Error TS2322: Type 'ParentNode & Node' is not assignable to type 'E'.
// 'E' could be instantiated with an arbitrary type which could be unrelated to 'ParentNode & Node'.
//
return !attrs || isChildren(attrs) ? defineChildren(node, attrs ?? children) : defineChildren(defineAttrs(node, attrs), children);
}
exports.define = define;
function defineAttrs(el, attrs) {
for (const name of Object.keys(attrs)) {
switch (name) {
case 'is':
continue;
}
const value = attrs[name];
switch (typeof value) {
case 'string':
el.setAttribute(name, value);
if (name.startsWith('on')) {
const type = name.slice(2).toLowerCase();
switch (type) {
case 'mutate':
case 'connect':
case 'disconnect':
const prop = `on${type}`;
el[prop] ?? Object.defineProperty(el, prop, {
configurable: true,
enumerable: false,
writable: true,
value: prop in el && !(0, alias_1.hasOwnProperty)(el, prop) ? ev => ev.returnValue : ''
});
}
}
continue;
case 'function':
if (name.length < 3) throw new Error(`Typed-DOM: Attribute names for event listeners must have an event name but got "${name}"`);
const names = name.split(/\s+/);
for (const name of names) {
if (!name.startsWith('on')) throw new Error(`Typed-DOM: Attribute names for event listeners must start with "on" but got "${name}"`);
const type = name.slice(2).toLowerCase();
el.addEventListener(type, value, {
passive: ['wheel', 'mousewheel', 'touchstart', 'touchmove', 'touchend', 'touchcancel'].includes(type)
});
switch (type) {
case 'mutate':
case 'connect':
case 'disconnect':
const prop = `on${type}`;
el[prop] ?? Object.defineProperty(el, prop, {
configurable: true,
enumerable: false,
writable: true,
value: prop in el && !(0, alias_1.hasOwnProperty)(el, prop) ? ev => ev.returnValue : ''
});
}
}
continue;
case 'object':
el.removeAttribute(name);
continue;
default:
continue;
}
}
return el;
}
function defineChildren(node, children) {
if (children === undefined) return node;
if (typeof children === 'string') {
node.textContent = children;
} else if (((0, alias_1.isArray)(children) || !(Symbol.iterator in children)) && !node.firstChild) {
for (let i = 0; i < children.length; ++i) {
const child = children[i];
typeof child === 'object' ? node.appendChild(child) : node.append(child);
}
} else {
node.replaceChildren(...children);
}
return node;
}
function isChildren(value) {
return value?.[Symbol.iterator] !== undefined;
}
exports.isChildren = isChildren;
function append(node, children) {
if (children === undefined) return node;
if (typeof children === 'string') {
node.append(children);
} else if ((0, alias_1.isArray)(children) || !(Symbol.iterator in children)) {
for (let i = 0; i < children.length; ++i) {
const child = children[i];
typeof child === 'object' ? node.appendChild(child) : node.append(child);
}
} else {
for (const child of children) {
typeof child === 'object' ? node.appendChild(child) : node.append(child);
}
}
return node;
}
exports.append = append;
function prepend(node, children) {
if (children === undefined) return node;
if (typeof children === 'string') {
node.prepend(children);
} else if ((0, alias_1.isArray)(children) || !(Symbol.iterator in children)) {
for (let i = 0; i < children.length; ++i) {
const child = children[i];
typeof child === 'object' ? node.insertBefore(child, null) : node.prepend(child);
}
} else {
for (const child of children) {
typeof child === 'object' ? node.insertBefore(child, null) : node.prepend(child);
}
}
return node;
}
exports.prepend = prepend;
function defrag(nodes) {
const acc = [];
let appendable = false;
for (let i = 0, len = nodes.length; i < len; ++i) {
const node = nodes[i];
if (typeof node === 'object') {
acc.push(node);
appendable = false;
} else if (node !== '') {
appendable ? acc[acc.length - 1] += node : acc.push(node);
appendable = true;
}
}
return acc;
}
exports.defrag = defrag;
/***/ })
/******/ });
/************************************************************************/
/******/ // The module cache
/******/ var __webpack_module_cache__ = {};
/******/
/******/ // The require function
/******/ function __webpack_require__(moduleId) {
/******/ // Check if module is in cache
/******/ var cachedModule = __webpack_module_cache__[moduleId];
/******/ if (cachedModule !== undefined) {
/******/ return cachedModule.exports;
/******/ }
/******/ // Create a new module (and put it into the cache)
/******/ var module = __webpack_module_cache__[moduleId] = {
/******/ // no module.id needed
/******/ // no module.loaded needed
/******/ exports: {}
/******/ };
/******/
/******/ // Execute the module function
/******/ __webpack_modules__[moduleId](module, module.exports, __webpack_require__);
/******/
/******/ // Return the exports of the module
/******/ return module.exports;
/******/ }
/******/
/************************************************************************/
/******/
/******/ // startup
/******/ // Load entry module and return exports
/******/ // This entry module is referenced by other modules so it can't be inlined
/******/ var __webpack_exports__ = __webpack_require__(5761);
/******/
/******/ return __webpack_exports__;
/******/ })()
;
});