infamous
Version:
A CSS3D/WebGL UI library.
122 lines (102 loc) • 5.22 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.epsilon = epsilon;
exports.applyCSSLabel = applyCSSLabel;
exports.observeChildren = observeChildren;
exports.getShadowRootVersion = getShadowRootVersion;
exports.getAncestorShadowRoot = getAncestorShadowRoot;
exports.isInstanceof = isInstanceof;
exports.hasShadowDomV1 = exports.hasShadowDomV0 = void 0;
function epsilon(value) {
return Math.abs(value) < 0.000001 ? 0 : value;
}
function applyCSSLabel(value, label) {
if (value === 0) {
return '0px';
} else if (label === '%') {
return value * 100 + '%';
} else if (label === 'px') {
return value + 'px';
}
}
function observeChildren(target, onConnect, onDisconnect) {
// TODO this Map is never cleaned, leaks memory. Maybe use WeakMap
const childObserver = createChildObserver(onConnect, onDisconnect);
childObserver.observe(target, {
childList: true
});
return childObserver;
} // NOTE: If a child is disconnected then connected to the same parent in the
// same turn, then the onConnect and onDisconnect callbacks won't be called
// because the DOM tree will be back in the exact state as before (this is
// possible thanks to the logic associated with weightsPerTarget).
function createChildObserver(onConnect, onDisconnect) {
return new MutationObserver(changes => {
const weightsPerTarget = new Map(); // We're just counting how many times each child node was added and
// removed from the parent we're observing.
for (let i = 0, l = changes.length; i < l; i += 1) {
const change = changes[i];
if (change.type != 'childList') continue;
if (!weightsPerTarget.has(change.target)) weightsPerTarget.set(change.target, new Map());
const weights = weightsPerTarget.get(change.target);
const {
addedNodes
} = change;
for (let l = addedNodes.length, i = 0; i < l; i += 1) weights.set(addedNodes[i], (weights.get(addedNodes[i]) || 0) + 1);
const {
removedNodes
} = change;
for (let l = removedNodes.length, i = 0; i < l; i += 1) weights.set(removedNodes[i], (weights.get(removedNodes[i]) || 0) - 1);
}
for (const [target, weights] of Array.from(weightsPerTarget)) {
for (const [node, weight] of Array.from(weights)) {
// If the number of times a child was added is greater than the
// number of times it was removed, then the net result is that
// it was added, so we call onConnect just once.
if (weight > 0 && typeof onConnect == 'function') onConnect.call(target, node); // If the number of times a child was added is less than the
// number of times it was removed, then the net result is that
// it was removed, so we call onConnect just once.
else if (weight < 0 && typeof onDisconnect == 'function') onDisconnect.call(target, node); // If the number of times a child was added is equal to the
// number of times it was removed, then it was essentially left
// in place, so we don't call anything.
}
}
});
}
const hasShadowDomV0 = typeof Element.prototype.createShadowRoot == 'function' && typeof HTMLContentElement == 'function' ? true : false;
exports.hasShadowDomV0 = hasShadowDomV0;
const hasShadowDomV1 = typeof Element.prototype.attachShadow == 'function' && typeof HTMLSlotElement == 'function' ? true : false;
exports.hasShadowDomV1 = hasShadowDomV1;
function getShadowRootVersion(shadowRoot) {
console.log('getShadowRootVersion');
if (!shadowRoot) return null;
const slot = document.createElement('slot');
shadowRoot.appendChild(slot);
slot.appendChild(document.createElement('div'));
const assignedNodes = slot.assignedNodes({
flatten: true
});
slot.remove();
console.log('hmm', assignedNodes.length, assignedNodes.length > 0 ? 'v1' : 'v0');
return assignedNodes.length > 0 ? 'v1' : 'v0';
}
function getAncestorShadowRoot(node) {
let current = node;
while (current && !(current instanceof ShadowRoot)) {
current = current.parentNode;
}
return current;
} // helper function to use instead of instanceof for classes that implement the
// static Symbol.hasInstance method, because the behavior of instanceof isn't
// polyfillable.
function isInstanceof(lhs, rhs) {
if (typeof rhs == 'function' && rhs[Symbol.hasInstance]) return rhs[Symbol.hasInstance](lhs);else return lhs instanceof rhs;
}
function checkIsNumberArrayString(str) {
if (!str.match(/^\s*(((\s*(-|\+)?((\.\d+)|(\d+\.\d+)|(\d+)|(\d+(\.\d+)?e(-|\+)?(\d+)))\s*,){0,2}(\s*(-|\+)?((\.\d+)|(\d+\.\d+)|(\d+)|(\d+(\.\d+)?e(-|\+)?(\d+)))))|((\s*(-|\+)?((\.\d+)|(\d+\.\d+)|(\d+)|(\d+(\.\d+)?e(-|\+)?(\d+)))\s){0,2}(\s*(-|\+)?((\.\d+)|(\d+\.\d+)|(\d+)|(\d+(\.\d+)?e(-|\+)?(\d+))))))\s*$/g)) throw new Error(`Attribute must be a comma- or space-separated sequence of up to three numbers, for example "1 2.5 3". Yours was "${str}".`);
}
function checkIsSizeArrayString(str) {
if (!str.match(/^\s*(((\s*([a-zA-Z]+)\s*,){0,2}(\s*([a-zA-Z]+)))|((\s*([a-zA-Z]+)\s*){1,3}))\s*$/g)) throw new Error(`Attribute must be a comma- or space-separated sequence of up to three strings, for example "literal proportional". Yours was "${str}".`);
}