hele
Version:
A front-end UI lib.
721 lines (665 loc) • 25.5 kB
JavaScript
(function (global, factory) {
typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) :
typeof define === 'function' && define.amd ? define(['exports'], factory) :
(factory((global.HEle = {})));
}(this, (function (exports) { 'use strict';
var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) {
return typeof obj;
} : function (obj) {
return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj;
};
var classCallCheck = function (instance, Constructor) {
if (!(instance instanceof Constructor)) {
throw new TypeError("Cannot call a class as a function");
}
};
var createClass = function () {
function defineProperties(target, props) {
for (var i = 0; i < props.length; i++) {
var descriptor = props[i];
descriptor.enumerable = descriptor.enumerable || false;
descriptor.configurable = true;
if ("value" in descriptor) descriptor.writable = true;
Object.defineProperty(target, descriptor.key, descriptor);
}
}
return function (Constructor, protoProps, staticProps) {
if (protoProps) defineProperties(Constructor.prototype, protoProps);
if (staticProps) defineProperties(Constructor, staticProps);
return Constructor;
};
}();
var inherits = function (subClass, superClass) {
if (typeof superClass !== "function" && superClass !== null) {
throw new TypeError("Super expression must either be null or a function, not " + typeof superClass);
}
subClass.prototype = Object.create(superClass && superClass.prototype, {
constructor: {
value: subClass,
enumerable: false,
writable: true,
configurable: true
}
});
if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass;
};
var possibleConstructorReturn = function (self, call) {
if (!self) {
throw new ReferenceError("this hasn't been initialised - super() hasn't been called");
}
return call && (typeof call === "object" || typeof call === "function") ? call : self;
};
var toConsumableArray = function (arr) {
if (Array.isArray(arr)) {
for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) arr2[i] = arr[i];
return arr2;
} else {
return Array.from(arr);
}
};
var Reference = function Reference() {
classCallCheck(this, Reference);
this.current = undefined;
};
function isEqual(a, b) {
if (a === b || a !== a && b !== b) {
return true;
}
if (!(a instanceof Object && b instanceof Object) || String(a) !== String(b)) {
return false;
}
for (var key in a) {
if (!(key in b && isEqual(a[key], b[key]))) {
return false;
}
}
for (var _key in b) {
if (!(_key in a)) {
return false;
}
}
return true;
}
function _clrChd(node) {
var deep = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;
[].concat(toConsumableArray(node.childNodes)).forEach(function (childNode) {
if (deep) {
_clrChd(childNode, true);
}
node.removeChild(childNode);
});
}
function _flatten(array) {
var ans = new Array();
array.forEach(function (ele) {
if (ele instanceof Array) {
ele.forEach(function (e) {
ans.push(e);
});
} else {
ans.push(ele);
}
});
return ans;
}
function _copy(original) {
if (original instanceof Object) {
// @ts-ignore
return Object.create(original);
} else {
return original;
}
}
var _isNorObj = function _isNorObj(obj) {
return obj instanceof Object && String(obj) === '[object Object]';
};
var _eleMap = new Map();
var namespaces = new Map([['svg', 'http://www.w3.org/2000/svg']]);
var _nsCtxName = '_xmlns';
function _toEle(element) {
if (element instanceof HElement) {
return element;
} else {
var type = typeof element === "undefined" ? "undefined" : _typeof(element);
if (type === 'string') {
return new HElement(null, { children: [element] });
} else if (type === 'number') {
return new HElement(null, { children: [element.toString()] });
} else if (element instanceof Array) {
return element.map(_toEle);
} else {
return null;
}
}
}
function _toNode(element) {
if (element instanceof HElement) {
return element.toNode();
} else if (element instanceof Array) {
return _flatten(element.map(_toNode));
} else {
return document.createTextNode('');
}
}
var HElement = function () {
function HElement(type, props) {
classCallCheck(this, HElement);
this.type = type;
this.parent = undefined;
this.node = undefined;
this.context = undefined;
this.props = type && typeof type !== 'string' && type.prototype instanceof Component ? Object.assign({}, type.defaultProps, props) : props;
}
createClass(HElement, [{
key: "toNode",
value: function toNode() {
var _this = this;
var type = this.type,
props = this.props;
var node = void 0;
if (type === null) {
node = document.createTextNode(props.children[0]);
} else if (typeof type === 'string') {
var context = _copy(this.context),
xmlns = !props['no-xmlns'] && (props.xmlns || namespaces.get(type) || context[_nsCtxName]);
node = xmlns ? document.createElementNS(xmlns, type) : document.createElement(type);
if (xmlns) {
context[_nsCtxName] = xmlns;
}
_crtNode(props, node, context);
} else {
var _getCom2 = _getCom(type, props, _copy(this.context)),
element = _getCom2.element,
component = _getCom2.component,
parsedElement = _toEle(element);
// @ts-ignore
if (type === Context) {
this.context = component.state;
}
if (parsedElement) {
var _context = this.context;
_flatten([parsedElement]).forEach(function (ele) {
if (ele) {
ele.parent = _this;
ele.context = _copy(_context);
}
});
}
if (component) {
_eleMap.set(component, this);
}
try {
node = parsedElement instanceof Array ? _flatten(parsedElement.map(_toNode)) : _toNode(parsedElement);
if (component) {
component.onDidMount();
}
} catch (error) {
node = document.createTextNode('');
if (component) {
component.onCaughtError(error);
} else {
throw error;
}
}
}
return this.node = node;
}
}]);
return HElement;
}();
function _upCom(component) {
var oldElement = _eleMap.get(component);
if (oldElement) {
var node = oldElement.node;
if (node) {
var parent = oldElement.parent,
nodes = _flatten([node]);
nodes.forEach(function (n, i) {
var parentNode = n.parentNode;
_clrChd(n, true);
if (parentNode) {
if (i === 0) {
var newElement = component.toElement();
if (newElement instanceof HElement) {
newElement.parent = parent;
newElement.context = oldElement.context;
_eleMap.set(component, newElement);
var newNode = newElement.toNode(),
newNodes = _flatten([newNode]),
fragment = document.createDocumentFragment();
if (parent) {
if (parent.node instanceof Array) {
nodes.forEach(function (n, i) {
var index = parent.node.indexOf(n);
if (i === 0) {
var _parent$node;
(_parent$node = parent.node).splice.apply(_parent$node, [index, 1].concat(toConsumableArray(newNodes)));
} else {
parent.node.splice(index, 1);
}
});
} else {
parent.node = newNode;
}
}
newNodes.forEach(function (child) {
fragment.appendChild(child);
});
parentNode.replaceChild(fragment, n);
} else {
_eleMap.delete(component);
parentNode.removeChild(n);
}
} else {
parentNode.removeChild(n);
}
}
});
}
}
}
var _expired = new Set();
var defaultTickMethod = function defaultTickMethod(callback) {
requestAnimationFrame(callback);
};
var Ticker = {
tickMethod: defaultTickMethod,
maxUpdateTime: 12,
maxClearTime: 3,
_willTick: false,
_tick: function _tick() {
if (!Ticker._willTick) {
Ticker.tickMethod(function () {
Ticker._willTick = false;
var maxUpdateTime = Ticker.maxUpdateTime,
maxClearTime = Ticker.maxClearTime;
var startTime = Date.now();
_expired.forEach(function (component) {
if (Date.now() - startTime < maxUpdateTime) {
_expired.delete(component);
var state = component.state,
updateRequestCallbacks = component.updateRequestCallbacks,
_forceUp = component._forceUp,
callbacks = updateRequestCallbacks.slice(0),
callbackCount = callbacks.length;
var newState = _copy(state),
t = void 0;
callbacks.forEach(function (callback) {
t = callback(newState);
if (t !== undefined) {
newState = t;
}
});
component.updateRequestCallbacks = updateRequestCallbacks.slice(callbackCount);
try {
if (_forceUp || component.shouldUpdate(state, newState)) {
component._forceUp = false;
var snapshot = component.onWillUpdate(state);
component.state = newState;
_upCom(component);
component.onDidUpdate(snapshot);
}
} catch (error) {
component.onCaughtError(error);
}
}
});
if (_expired.size) {
Ticker._tick();
}
startTime = Date.now();
var hasElementDeleted = true;
while (hasElementDeleted && Date.now() - startTime < maxClearTime) {
hasElementDeleted = false;
_eleMap.forEach(function (element, component) {
var node = element.node;
if (node) {
var tempNode = node instanceof Array ? node[0] : node;
if (!tempNode || !tempNode.parentNode) {
hasElementDeleted = true;
try {
component.onWillUnmount();
_eleMap.delete(component);
component.onDidUnmount();
} catch (error) {
component.onCaughtError(error);
}
}
}
});
}
});
Ticker._willTick = true;
}
},
_mark: function _mark(component) {
_expired.add(component);
Ticker._tick();
}
};
var Component = function () {
function Component(props, context) {
classCallCheck(this, Component);
this.context = context;
this.state = {};
this.refs = new Map();
this.updateRequestCallbacks = new Array();
this._forceUp = false;
this.props = props;
}
createClass(Component, [{
key: "toElement",
value: function toElement() {
this.refs.forEach(function (ref) {
ref.current = undefined;
});
try {
var result = this.render(),
type = typeof result === "undefined" ? "undefined" : _typeof(result);
if (type === 'string') {
return new HElement(null, { children: [result] });
} else if (type === 'number') {
return new HElement(null, { children: [result.toString()] });
} else {
return result;
}
} catch (error) {
this.onCaughtError(error);
return null;
}
}
}, {
key: "onWillMount",
value: function onWillMount() {}
}, {
key: "onDidMount",
value: function onDidMount() {}
}, {
key: "shouldUpdate",
value: function shouldUpdate(oldState, newState) {
return !isEqual(oldState, newState);
}
// @ts-ignore
}, {
key: "onWillUpdate",
value: function onWillUpdate(newState) {}
}, {
key: "onDidUpdate",
value: function onDidUpdate(snapShot) {}
}, {
key: "onWillUnmount",
value: function onWillUnmount() {}
}, {
key: "onDidUnmount",
value: function onDidUnmount() {}
}, {
key: "onCaughtError",
value: function onCaughtError(error) {
throw error;
}
}, {
key: "createRef",
value: function createRef(name) {
var refs = this.refs;
if (refs.has(name)) {
return refs.get(name);
} else {
var ref = new Reference();
refs.set(name, ref);
return ref;
}
}
}, {
key: "requestUpdate",
value: function requestUpdate(callback) {
this.updateRequestCallbacks.push(callback);
Ticker._mark(this);
return this;
}
}, {
key: "update",
value: function update(newState) {
return this.requestUpdate(function (state) {
if (_isNorObj(newState) && _isNorObj(state)) {
Object.assign(state, newState);
} else {
return newState;
}
});
}
}, {
key: "forceUpdate",
value: function forceUpdate(newState) {
this._forceUp = true;
if (arguments.length) {
// @ts-ignore
this.update(newState);
} else {
Ticker._mark(this);
}
return this;
}
}]);
return Component;
}();
Component.defaultProps = {};
var Fragment = function Fragment(props) {
return _flatten(props.children);
};
var Context = function (_Component) {
inherits(Context, _Component);
function Context(props, context) {
classCallCheck(this, Context);
var _this = possibleConstructorReturn(this, (Context.__proto__ || Object.getPrototypeOf(Context)).call(this, props, context));
_this.state = Object.assign({}, context, props.value);
return _this;
}
createClass(Context, [{
key: "render",
value: function render() {
return _flatten(this.props.children);
}
}]);
return Context;
}(Component);
function render(node, root) {
var deepClear = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : true;
_clrChd(root, deepClear);
Ticker._tick();
// @ts-ignore
var context = root.context;
_flatten([node]).forEach(function (element) {
if (element instanceof HElement) {
element.context = context;
_flatten([element.toNode()]).forEach(function (child) {
root.appendChild(child);
});
} else {
var type = typeof element === "undefined" ? "undefined" : _typeof(element);
if (type === 'string') {
root.appendChild(document.createTextNode(element));
} else if (type === 'number') {
root.appendChild(document.createTextNode(element.toString()));
}
}
});
}
var specialNodePropProcessors = new Map([['children', function (children, node) {
render(children, node, false);
}], ['style', function (style, node) {
if (!(node instanceof HTMLElement)) {
return;
}
if (style instanceof Object) {
for (var key in style) {
// @ts-ignore
node.style[key] = style[key];
}
} else {
// @ts-ignore
node.style = style;
}
}], ['ref', function (ref, node) {
ref.current = node;
}], ['class', function (classNames, node) {
if ('setAttribute' in node) {
node.setAttribute('class', typeof classNames === 'string' ? classNames : classNames.filter(function (name) {
return typeof name === 'string';
}).join(' '));
}
}], ['no-xmlns', function () {}]]);
var specialComponentPropProcessors = new Map([['ref', function (ref, component) {
ref.current = component;
}]]);
var specialFactoryPropProcessors = new Map([['ref', function (ref) {
ref.current = undefined;
}]]);
var eventPattern = /^on(\w+)$/i,
captruePattern = /capture/i,
nonpassivePattern = /nonpassive/i,
oncePattern = /once/i;
function _getEName(rawEvent, useCapture, nonpassive, once) {
var t = 0;
if (useCapture) {
t += 7;
}
if (nonpassive) {
t += 7;
}
if (once) {
t += 4;
}
return t > 0 ? rawEvent.slice(0, -t) : rawEvent;
}
function _getEOpt(capture, nonpassive, once) {
return !nonpassive && !capture && !once ? false : { capture: capture, passive: !nonpassive, once: once };
}
function _crtNode(props, node, context) {
// @ts-ignore
node.context = context;
for (var key in props) {
var value = props[key],
processor = specialNodePropProcessors.get(key);
if (processor) {
processor(value, node);
} else if (key.match(eventPattern)) {
var rawEvent = RegExp.$1,
capture = captruePattern.test(rawEvent),
nonpassive = nonpassivePattern.test(rawEvent),
once = oncePattern.test(rawEvent),
event = _getEName(rawEvent, capture, nonpassive, once);
node.addEventListener(event, value, _getEOpt(capture, nonpassive, once));
} else if (!(key in node) && 'setAttribute' in node) {
node.setAttribute(key, value);
} else {
try {
// @ts-ignore
node[key] = value;
} catch (err) {
node.setAttribute(key, value);
}
}
}
}
function _getCom(componentGetter, props, context) {
var result = { element: null, component: null };
if (componentGetter.prototype instanceof Component) {
var component = result.component = new componentGetter(props, context);
for (var key in props) {
var processor = specialComponentPropProcessors.get(key);
if (processor) {
processor(props[key], component);
}
}
try {
component.onWillMount();
} catch (error) {
component.onCaughtError(error);
}
result.element = component.toElement();
} else {
for (var _key in props) {
var _processor = specialFactoryPropProcessors.get(_key);
if (_processor) {
_processor(props[_key], undefined);
}
}
var element = componentGetter(props, context);
result.element = element;
}
return result;
}
function createElement(type, props) {
for (var _len = arguments.length, children = Array(_len > 2 ? _len - 2 : 0), _key = 2; _key < _len; _key++) {
children[_key - 2] = arguments[_key];
}
return new HElement(type, Object.assign({}, props || {}, {
children: _flatten(children)
}));
}
var Portal = function (_Component) {
inherits(Portal, _Component);
function Portal(props, context) {
classCallCheck(this, Portal);
var _this = possibleConstructorReturn(this, (Portal.__proto__ || Object.getPrototypeOf(Portal)).call(this, props, context));
if (props.container) {
_this.container = props.container;
} else {
_this.container = document.createElement('div');
document.body.appendChild(_this.container);
}
return _this;
}
createClass(Portal, [{
key: "render",
value: function render$$1() {
return null;
}
}, {
key: "onWillMount",
value: function onWillMount() {
render(createElement(Context, { value: this.context }, this.props.children), this.container, this.props.deepClear);
}
}]);
return Portal;
}(Component);
function createFactory(type) {
return function ComponentFactory(props) {
for (var _len = arguments.length, children = Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
children[_key - 1] = arguments[_key];
}
return createElement.apply(undefined, [type, props].concat(children));
};
}
exports.specialNodePropProcessors = specialNodePropProcessors;
exports.specialComponentPropProcessors = specialComponentPropProcessors;
exports.specialFactoryPropProcessors = specialFactoryPropProcessors;
exports._getEName = _getEName;
exports._getEOpt = _getEOpt;
exports._crtNode = _crtNode;
exports._getCom = _getCom;
exports.isEqual = isEqual;
exports._clrChd = _clrChd;
exports._flatten = _flatten;
exports._copy = _copy;
exports._isNorObj = _isNorObj;
exports._upCom = _upCom;
exports._expired = _expired;
exports.defaultTickMethod = defaultTickMethod;
exports.Ticker = Ticker;
exports.Component = Component;
exports.Fragment = Fragment;
exports.Context = Context;
exports._eleMap = _eleMap;
exports.namespaces = namespaces;
exports._nsCtxName = _nsCtxName;
exports._toEle = _toEle;
exports._toNode = _toNode;
exports.HElement = HElement;
exports.Reference = Reference;
exports.render = render;
exports.Portal = Portal;
exports.createElement = createElement;
exports.createFactory = createFactory;
Object.defineProperty(exports, '__esModule', { value: true });
})));