@skatejs/val
Version:
VirtualDOM abstraction layer - give yourself better integration and full control over the DOM with any virtual DOM library that uses a Hyperscript-like API such as React and Preact.
225 lines (176 loc) • 6.06 kB
JavaScript
Object.defineProperty(exports, "__esModule", {
value: true
});
exports["default"] = val;
exports.h = void 0;
function _objectSpread(target) {
for (var i = 1; i < arguments.length; i++) {
var source = arguments[i] != null ? arguments[i] : {};
var ownKeys = Object.keys(source);
if (typeof Object.getOwnPropertySymbols === 'function') {
ownKeys = ownKeys.concat(Object.getOwnPropertySymbols(source).filter(function (sym) {
return Object.getOwnPropertyDescriptor(source, sym).enumerable;
}));
}
ownKeys.forEach(function (key) {
_defineProperty(target, key, source[key]);
});
}
return target;
}
function _defineProperty(obj, key, value) {
if (key in obj) {
Object.defineProperty(obj, key, {
value: value,
enumerable: true,
configurable: true,
writable: true
});
} else {
obj[key] = value;
}
return obj;
}
function _objectWithoutProperties(source, excluded) {
if (source == null) return {};
var target = _objectWithoutPropertiesLoose(source, excluded);
var key, i;
if (Object.getOwnPropertySymbols) {
var sourceSymbolKeys = Object.getOwnPropertySymbols(source);
for (i = 0; i < sourceSymbolKeys.length; i++) {
key = sourceSymbolKeys[i];
if (excluded.indexOf(key) >= 0) continue;
if (!Object.prototype.propertyIsEnumerable.call(source, key)) continue;
target[key] = source[key];
}
}
return target;
}
function _objectWithoutPropertiesLoose(source, excluded) {
if (source == null) return {};
var target = {};
var sourceKeys = Object.keys(source);
var key, i;
for (i = 0; i < sourceKeys.length; i++) {
key = sourceKeys[i];
if (excluded.indexOf(key) >= 0) continue;
target[key] = source[key];
}
return target;
}
var _window = window,
customElements = _window.customElements;
var cacheCtorLocalNames = new Map();
var cacheElementEventHandlers = new WeakMap(); // Override customElements.define() to cache constructor local names. This is
// required for all virtual DOM implementations that don't natively support
// custom element constructors as node names.
if (customElements) {
var define = customElements.define;
customElements.define = function (name, Ctor) {
cacheCtorLocalNames.set(Ctor, name);
return define.call(customElements, name, Ctor);
};
} // Applies attributes to the ref element. It doesn't traverse through
// existing attributes and assumes that the supplied object will supply
// all attributes that the applicator should care about, even ones that
// should be removed.
function applyAttrs(e, attrs) {
if (!attrs) return;
Object.keys(attrs).forEach(function (name) {
var value = attrs[name];
if (value == null) {
e.removeAttribute(name);
} else {
e.setAttribute(name, value);
}
});
}
function applyEvents(e) {
var events = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
var handlers = cacheElementEventHandlers.get(e) || {};
cacheElementEventHandlers.set(e, events); // Remove any old listeners that are different - or aren't specified
// in - the new set.
Object.keys(handlers).forEach(function (name) {
if (handlers[name] && handlers[name] !== events[name]) {
e.removeEventListener(name, handlers[name]);
}
}); // Bind new listeners.
Object.keys(events).forEach(function (name) {
if (events[name] !== handlers[name]) {
e.addEventListener(name, events[name]);
}
});
} // Sets props. Straight up.
function applyProps(e, props) {
Object.keys(props || {}).forEach(function (name) {
e[name] = props[name];
});
} // Ensures that if a ref was specified that it's called as normal.
function applyRef(e, ref) {
if (ref) {
ref(e);
}
} // Ensures attrs, events and props are all set as the consumer intended.
function ensureProps(objs) {
var _ref = objs || {},
attrs = _ref.attrs,
events = _ref.events,
props = _ref.props,
ref = _ref.ref,
pass = _objectWithoutProperties(_ref, ["attrs", "events", "props", "ref"]);
var newRef = ensureRef(attrs, events, props, ref);
return _objectSpread({}, pass, {
ref: newRef
});
} // Ensures a ref is supplied that set each member appropriately and that
// the original ref is called.
function ensureRef(attrs, events, props, ref) {
return function (e) {
if (e) {
applyAttrs(e, attrs);
applyEvents(e, events);
applyProps(e, props);
}
applyRef(e, ref);
};
} // Returns the custom element local name if it exists or the original
// value.
function ensureLocalName(lname) {
var temp = cacheCtorLocalNames.get(lname);
return temp || lname;
} // Default adapter for rendering DOM.
function defaultCreateElement(lname, _ref2) {
var ref = _ref2.ref,
props = _objectWithoutProperties(_ref2, ["ref"]);
var node = typeof lname === "function" ? new lname() : document.createElement(lname);
if (ref) {
ref(node);
}
for (var name in props) {
node[name] = props[name];
}
for (var _len = arguments.length, chren = new Array(_len > 2 ? _len - 2 : 0), _key = 2; _key < _len; _key++) {
chren[_key - 2] = arguments[_key];
}
chren.forEach(function (c) {
return node.appendChild(typeof c === "string" ? document.createTextNode(c) : c);
});
return node;
} // Provides a function that takes the original createElement that is being
// wrapped. It returns a function that you call like you normally would.
//
// It requires support for:
// - `ref`
function val() {
var createElement = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : defaultCreateElement;
return function (lname, props) {
lname = ensureLocalName(lname);
props = ensureProps(props);
for (var _len2 = arguments.length, chren = new Array(_len2 > 2 ? _len2 - 2 : 0), _key2 = 2; _key2 < _len2; _key2++) {
chren[_key2 - 2] = arguments[_key2];
}
return createElement.apply(void 0, [lname, props].concat(chren));
};
}
var h = val();
exports.h = h;