UNPKG

hele

Version:
721 lines (665 loc) 25.5 kB
(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 }); })));