UNPKG

spiritjs

Version:

The animation toolkit for the web

191 lines (183 loc) 6.37 kB
"use strict"; exports.__esModule = true; exports.emitChange = emitChange; var _events = require("./events"); var _list = _interopRequireDefault(require("../list/list")); var _is = require("./is"); function _interopRequireDefault(e) { return e && e.__esModule ? e : { "default": e }; } function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; } function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; } function _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; } function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == typeof i ? i : i + ""; } function _toPrimitive(t, r) { if ("object" != typeof t || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != typeof i) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); } /** * ------------------------------------------- * Decorator for emitting changes * ------------------------------------------- * * @example on setter: * * class Item { * * _label = null * _list = new List() * * get label() { * return this._label * } * * @emitChange() * set label(val) { * this._label = val * } * * } * * @example on class: * * @emitChange('album') * @emitChange('label', 'untitled', [ * { * validator: v => /\d+/.test(v), * message: 'Not a number' * }, * { * validator = v => typeof v === 'string', * message: 'Must be a string' * } * ]) * * class Song { * * } */ /** * Setter deco * * @param {Emitter} target * @param {string} key * @param {object} descriptor * @returns {object} */ var setter = function setter(target, key, descriptor) { var fn = descriptor.set; if (!_events.Emitter.prototype.isPrototypeOf(target) && !_events.Emitter.prototype.isPrototypeOf(target.prototype)) { throw new Error('@emitter.emitChange can only be applied to event emitters'); } return _objectSpread(_objectSpread({}, descriptor), {}, { configurable: true, set: function set(val) { var _this = this; var toObj = function toObj(v) { var _ref; return (0, _is.isFunction)(_this.toObject) ? _this.toObject() : (_ref = {}, _ref[key] = v !== undefined ? v : val, _ref); }; // get previous value var prev = this['_' + key]; if (prev && typeof prev.toArray === 'function') { prev = prev.toArray(); } else if (prev && typeof prev.toObject === 'function') { prev = prev.toObject(); } var previous; if (prev !== val) { previous = toObj(prev); } // call class setter method fn.call(this, val); // is a duplicate on list? if (this._list instanceof _list["default"] && this._list._duplicates !== true) { try { this._list.checkOnDuplicates(); } catch (err) { fn.call(this, prev); throw err; } } // only emit changes if (prev === val) { return; } var from = prev && (0, _is.isFunction)(prev.toObject) ? prev.toObject() : prev; var to = val && (0, _is.isFunction)(val.toObject) ? val.toObject() : val; var changed = { type: key, from: from, to: to }; var current; try { current = toObj(); } catch (err) { var _current; current = (_current = {}, _current[key] = val, _current); } var evtParams = { previous: previous, current: current, changed: changed }; var evtChange = ['change', evtParams]; var evtChangeProp = ["change:" + key, evtParams, val]; this.emit.apply(this, evtChange); this.emit.apply(this, evtChangeProp); if (this._list && this._list instanceof _events.Emitter) { var _this$_list, _this$_list2; (_this$_list = this._list).emit.apply(_this$_list, evtChange); (_this$_list2 = this._list).emit.apply(_this$_list2, evtChangeProp); } } }); }; /** * Decorator * * @param {string} prop (apply on classes) * @param {*} defaultValue (optional, default=null) * @param {Array} validators (optional) */ function emitChange(prop, defaultValue, validators) { if (prop === void 0) { prop = null; } if (defaultValue === void 0) { defaultValue = null; } if (validators === void 0) { validators = []; } if (prop) { // bind as class return function (target) { var _Object$definePropert; // setup class prototype Object.defineProperties(target.prototype, (_Object$definePropert = {}, _Object$definePropert["_" + prop] = { value: defaultValue, writable: true, enumerable: false, configurable: true }, _Object$definePropert[prop] = { configurable: true, get: function get() { return this["_" + prop]; }, set: function set(val) { var errors = validators.reduce(function (res, v) { if (!v.validator(val)) { res.push(v.message); } return res; }, []); if (errors.length > 0) { throw new Error("" + errors[0]); } this["_" + prop] = val; } }, _Object$definePropert)); // apply setter on it var descriptor = Object.getOwnPropertyDescriptor(target.prototype, prop); Object.defineProperty(target.prototype, prop, setter(target, prop, descriptor)); }; } // bind as setter return setter; }