UNPKG

wilderness-core

Version:
1,794 lines (1,529 loc) 149 kB
(function () { 'use strict'; var _extends$1 = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; function _objectWithoutProperties(obj, keys) { var target = {}; for (var i in obj) { if (keys.indexOf(i) >= 0) continue; if (!Object.prototype.hasOwnProperty.call(obj, i)) continue; target[i] = obj[i]; } return target; } var toPoints = function toPoints(_ref) { var type = _ref.type, props = _objectWithoutProperties(_ref, ['type']); switch (type) { case 'circle': return getPointsFromCircle(props); case 'ellipse': return getPointsFromEllipse(props); case 'line': return getPointsFromLine(props); case 'path': return getPointsFromPath(props); case 'polygon': return getPointsFromPolygon(props); case 'polyline': return getPointsFromPolyline(props); case 'rect': return getPointsFromRect(props); case 'g': return getPointsFromG(props); default: throw new Error('Not a valid shape type'); } }; var getPointsFromCircle = function getPointsFromCircle(_ref2) { var cx = _ref2.cx, cy = _ref2.cy, r = _ref2.r; return [{ x: cx, y: cy - r, moveTo: true }, { x: cx, y: cy + r, curve: { type: 'arc', rx: r, ry: r, sweepFlag: 1 } }, { x: cx, y: cy - r, curve: { type: 'arc', rx: r, ry: r, sweepFlag: 1 } }]; }; var getPointsFromEllipse = function getPointsFromEllipse(_ref3) { var cx = _ref3.cx, cy = _ref3.cy, rx = _ref3.rx, ry = _ref3.ry; return [{ x: cx, y: cy - ry, moveTo: true }, { x: cx, y: cy + ry, curve: { type: 'arc', rx: rx, ry: ry, sweepFlag: 1 } }, { x: cx, y: cy - ry, curve: { type: 'arc', rx: rx, ry: ry, sweepFlag: 1 } }]; }; var getPointsFromLine = function getPointsFromLine(_ref4) { var x1 = _ref4.x1, x2 = _ref4.x2, y1 = _ref4.y1, y2 = _ref4.y2; return [{ x: x1, y: y1, moveTo: true }, { x: x2, y: y2 }]; }; var validCommands = /[MmLlHhVvCcSsQqTtAaZz]/g; var commandLengths = { A: 7, C: 6, H: 1, L: 2, M: 2, Q: 4, S: 4, T: 2, V: 1, Z: 0 }; var relativeCommands = ['a', 'c', 'h', 'l', 'm', 'q', 's', 't', 'v']; var isRelative = function isRelative(command) { return relativeCommands.indexOf(command) !== -1; }; var optionalArcKeys = ['xAxisRotation', 'largeArcFlag', 'sweepFlag']; var getCommands = function getCommands(d) { return d.match(validCommands); }; var getParams = function getParams(d) { return d.split(validCommands).map(function (v) { return v.replace(/[0-9]+-/g, function (m) { return m.slice(0, -1) + ' -'; }); }).map(function (v) { return v.replace(/\.[0-9]+/g, function (m) { return m + ' '; }); }).map(function (v) { return v.trim(); }).filter(function (v) { return v.length > 0; }).map(function (v) { return v.split(/[ ,]+/).map(parseFloat).filter(function (n) { return !isNaN(n); }); }); }; var getPointsFromPath = function getPointsFromPath(_ref5) { var d = _ref5.d; var commands = getCommands(d); var params = getParams(d); var points = []; var moveTo = void 0; for (var i = 0, l = commands.length; i < l; i++) { var command = commands[i]; var upperCaseCommand = command.toUpperCase(); var commandLength = commandLengths[upperCaseCommand]; var relative = isRelative(command); var prevPoint = i === 0 ? null : points[points.length - 1]; if (commandLength > 0) { var commandParams = params.shift(); var iterations = commandParams.length / commandLength; for (var j = 0; j < iterations; j++) { switch (upperCaseCommand) { case 'M': var x = (relative && prevPoint ? prevPoint.x : 0) + commandParams.shift(); var y = (relative && prevPoint ? prevPoint.y : 0) + commandParams.shift(); moveTo = { x: x, y: y }; points.push({ x: x, y: y, moveTo: true }); break; case 'L': points.push({ x: (relative ? prevPoint.x : 0) + commandParams.shift(), y: (relative ? prevPoint.y : 0) + commandParams.shift() }); break; case 'H': points.push({ x: (relative ? prevPoint.x : 0) + commandParams.shift(), y: prevPoint.y }); break; case 'V': points.push({ x: prevPoint.x, y: (relative ? prevPoint.y : 0) + commandParams.shift() }); break; case 'A': points.push({ curve: { type: 'arc', rx: commandParams.shift(), ry: commandParams.shift(), xAxisRotation: commandParams.shift(), largeArcFlag: commandParams.shift(), sweepFlag: commandParams.shift() }, x: (relative ? prevPoint.x : 0) + commandParams.shift(), y: (relative ? prevPoint.y : 0) + commandParams.shift() }); var _iteratorNormalCompletion = true; var _didIteratorError = false; var _iteratorError = undefined; try { for (var _iterator = optionalArcKeys[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) { var k = _step.value; if (points[points.length - 1]['curve'][k] === 0) { delete points[points.length - 1]['curve'][k]; } } } catch (err) { _didIteratorError = true; _iteratorError = err; } finally { try { if (!_iteratorNormalCompletion && _iterator.return) { _iterator.return(); } } finally { if (_didIteratorError) { throw _iteratorError; } } } break; case 'C': points.push({ curve: { type: 'cubic', x1: (relative ? prevPoint.x : 0) + commandParams.shift(), y1: (relative ? prevPoint.y : 0) + commandParams.shift(), x2: (relative ? prevPoint.x : 0) + commandParams.shift(), y2: (relative ? prevPoint.y : 0) + commandParams.shift() }, x: (relative ? prevPoint.x : 0) + commandParams.shift(), y: (relative ? prevPoint.y : 0) + commandParams.shift() }); break; case 'S': var sx2 = (relative ? prevPoint.x : 0) + commandParams.shift(); var sy2 = (relative ? prevPoint.y : 0) + commandParams.shift(); var sx = (relative ? prevPoint.x : 0) + commandParams.shift(); var sy = (relative ? prevPoint.y : 0) + commandParams.shift(); var diff = {}; var sx1 = void 0; var sy1 = void 0; if (prevPoint.curve && prevPoint.curve.type === 'cubic') { diff.x = Math.abs(prevPoint.x - prevPoint.curve.x2); diff.y = Math.abs(prevPoint.y - prevPoint.curve.y2); sx1 = prevPoint.x < prevPoint.curve.x2 ? prevPoint.x - diff.x : prevPoint.x + diff.x; sy1 = prevPoint.y < prevPoint.curve.y2 ? prevPoint.y - diff.y : prevPoint.y + diff.y; } else { diff.x = Math.abs(sx - sx2); diff.y = Math.abs(sy - sy2); sx1 = prevPoint.x; sy1 = prevPoint.y; } points.push({ curve: { type: 'cubic', x1: sx1, y1: sy1, x2: sx2, y2: sy2 }, x: sx, y: sy }); break; case 'Q': points.push({ curve: { type: 'quadratic', x1: (relative ? prevPoint.x : 0) + commandParams.shift(), y1: (relative ? prevPoint.y : 0) + commandParams.shift() }, x: (relative ? prevPoint.x : 0) + commandParams.shift(), y: (relative ? prevPoint.y : 0) + commandParams.shift() }); break; case 'T': var tx = (relative ? prevPoint.x : 0) + commandParams.shift(); var ty = (relative ? prevPoint.y : 0) + commandParams.shift(); var tx1 = void 0; var ty1 = void 0; if (prevPoint.curve && prevPoint.curve.type === 'quadratic') { var _diff = { x: Math.abs(prevPoint.x - prevPoint.curve.x1), y: Math.abs(prevPoint.y - prevPoint.curve.y1) }; tx1 = prevPoint.x < prevPoint.curve.x1 ? prevPoint.x - _diff.x : prevPoint.x + _diff.x; ty1 = prevPoint.y < prevPoint.curve.y1 ? prevPoint.y - _diff.y : prevPoint.y + _diff.y; } else { tx1 = prevPoint.x; ty1 = prevPoint.y; } points.push({ curve: { type: 'quadratic', x1: tx1, y1: ty1 }, x: tx, y: ty }); break; } } } else { if (prevPoint.x !== moveTo.x || prevPoint.y !== moveTo.y) { points.push({ x: moveTo.x, y: moveTo.y }); } } } return points; }; var getPointsFromPolygon = function getPointsFromPolygon(_ref6) { var points = _ref6.points; return getPointsFromPoints({ closed: true, points: points }); }; var getPointsFromPolyline = function getPointsFromPolyline(_ref7) { var points = _ref7.points; return getPointsFromPoints({ closed: false, points: points }); }; var getPointsFromPoints = function getPointsFromPoints(_ref8) { var closed = _ref8.closed, points = _ref8.points; var numbers = points.split(/[\s,]+/).map(function (n) { return parseFloat(n); }); var p = numbers.reduce(function (arr, point, i) { if (i % 2 === 0) { arr.push({ x: point }); } else { arr[(i - 1) / 2].y = point; } return arr; }, []); if (closed) { p.push(_extends$1({}, p[0])); } p[0].moveTo = true; return p; }; var getPointsFromRect = function getPointsFromRect(_ref9) { var height = _ref9.height, rx = _ref9.rx, ry = _ref9.ry, width = _ref9.width, x = _ref9.x, y = _ref9.y; if (rx || ry) { return getPointsFromRectWithCornerRadius({ height: height, rx: rx || ry, ry: ry || rx, width: width, x: x, y: y }); } return getPointsFromBasicRect({ height: height, width: width, x: x, y: y }); }; var getPointsFromBasicRect = function getPointsFromBasicRect(_ref10) { var height = _ref10.height, width = _ref10.width, x = _ref10.x, y = _ref10.y; return [{ x: x, y: y, moveTo: true }, { x: x + width, y: y }, { x: x + width, y: y + height }, { x: x, y: y + height }, { x: x, y: y }]; }; var getPointsFromRectWithCornerRadius = function getPointsFromRectWithCornerRadius(_ref11) { var height = _ref11.height, rx = _ref11.rx, ry = _ref11.ry, width = _ref11.width, x = _ref11.x, y = _ref11.y; var curve = { type: 'arc', rx: rx, ry: ry, sweepFlag: 1 }; return [{ x: x + rx, y: y, moveTo: true }, { x: x + width - rx, y: y }, { x: x + width, y: y + ry, curve: curve }, { x: x + width, y: y + height - ry }, { x: x + width - rx, y: y + height, curve: curve }, { x: x + rx, y: y + height }, { x: x, y: y + height - ry, curve: curve }, { x: x, y: y + ry }, { x: x + rx, y: y, curve: curve }]; }; var getPointsFromG = function getPointsFromG(_ref12) { var shapes = _ref12.shapes; return shapes.map(function (s) { return toPoints(s); }); }; var pointsToD = function pointsToD(p) { var d = ''; var i = 0; var firstPoint = void 0; var _iteratorNormalCompletion = true; var _didIteratorError = false; var _iteratorError = undefined; try { for (var _iterator = p[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) { var point = _step.value; var _point$curve = point.curve, curve = _point$curve === undefined ? false : _point$curve, moveTo = point.moveTo, x = point.x, y = point.y; var isFirstPoint = i === 0 || moveTo; var isLastPoint = i === p.length - 1 || p[i + 1].moveTo; var prevPoint = i === 0 ? null : p[i - 1]; if (isFirstPoint) { firstPoint = point; if (!isLastPoint) { d += 'M' + x + ',' + y; } } else if (curve) { switch (curve.type) { case 'arc': var _point$curve2 = point.curve, _point$curve2$largeAr = _point$curve2.largeArcFlag, largeArcFlag = _point$curve2$largeAr === undefined ? 0 : _point$curve2$largeAr, rx = _point$curve2.rx, ry = _point$curve2.ry, _point$curve2$sweepFl = _point$curve2.sweepFlag, sweepFlag = _point$curve2$sweepFl === undefined ? 0 : _point$curve2$sweepFl, _point$curve2$xAxisRo = _point$curve2.xAxisRotation, xAxisRotation = _point$curve2$xAxisRo === undefined ? 0 : _point$curve2$xAxisRo; d += 'A' + rx + ',' + ry + ',' + xAxisRotation + ',' + largeArcFlag + ',' + sweepFlag + ',' + x + ',' + y; break; case 'cubic': var _point$curve3 = point.curve, cx1 = _point$curve3.x1, cy1 = _point$curve3.y1, cx2 = _point$curve3.x2, cy2 = _point$curve3.y2; d += 'C' + cx1 + ',' + cy1 + ',' + cx2 + ',' + cy2 + ',' + x + ',' + y; break; case 'quadratic': var _point$curve4 = point.curve, qx1 = _point$curve4.x1, qy1 = _point$curve4.y1; d += 'Q' + qx1 + ',' + qy1 + ',' + x + ',' + y; break; } if (isLastPoint && x === firstPoint.x && y === firstPoint.y) { d += 'Z'; } } else if (isLastPoint && x === firstPoint.x && y === firstPoint.y) { d += 'Z'; } else if (x !== prevPoint.x && y !== prevPoint.y) { d += 'L' + x + ',' + y; } else if (x !== prevPoint.x) { d += 'H' + x; } else if (y !== prevPoint.y) { d += 'V' + y; } i++; } } catch (err) { _didIteratorError = true; _iteratorError = err; } finally { try { if (!_iteratorNormalCompletion && _iterator.return) { _iterator.return(); } } finally { if (_didIteratorError) { throw _iteratorError; } } } return d; }; var toPath = function toPath(s) { var isPoints = Array.isArray(s); var isGroup = isPoints ? Array.isArray(s[0]) : s.type === 'g'; var points = isPoints ? s : isGroup ? s.shapes.map(function (shp) { return toPoints(shp); }) : toPoints(s); if (isGroup) { return points.map(function (p) { return pointsToD(p); }); } return pointsToD(points); }; 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 getErrors = function getErrors(shape) { var rules = getRules(shape); var errors = []; rules.map(function (_ref) { var match = _ref.match, prop = _ref.prop, required = _ref.required, type = _ref.type; if (typeof shape[prop] === 'undefined') { if (required) { errors.push(prop + ' prop is required' + (prop === 'type' ? '' : ' on a ' + shape.type)); } } else { if (typeof type !== 'undefined') { if (type === 'array') { if (!Array.isArray(shape[prop])) { errors.push(prop + ' prop must be of type array'); } } else if (_typeof(shape[prop]) !== type) { // eslint-disable-line valid-typeof errors.push(prop + ' prop must be of type ' + type); } } if (Array.isArray(match)) { if (match.indexOf(shape[prop]) === -1) { errors.push(prop + ' prop must be one of ' + match.join(', ')); } } } }); if (shape.type === 'g' && Array.isArray(shape.shapes)) { var childErrors = shape.shapes.map(function (s) { return getErrors(s); }); return [].concat.apply(errors, childErrors); } return errors; }; var getRules = function getRules(shape) { var rules = [{ match: ['circle', 'ellipse', 'line', 'path', 'polygon', 'polyline', 'rect', 'g'], prop: 'type', required: true, type: 'string' }]; switch (shape.type) { case 'circle': rules.push({ prop: 'cx', required: true, type: 'number' }); rules.push({ prop: 'cy', required: true, type: 'number' }); rules.push({ prop: 'r', required: true, type: 'number' }); break; case 'ellipse': rules.push({ prop: 'cx', required: true, type: 'number' }); rules.push({ prop: 'cy', required: true, type: 'number' }); rules.push({ prop: 'rx', required: true, type: 'number' }); rules.push({ prop: 'ry', required: true, type: 'number' }); break; case 'line': rules.push({ prop: 'x1', required: true, type: 'number' }); rules.push({ prop: 'x2', required: true, type: 'number' }); rules.push({ prop: 'y1', required: true, type: 'number' }); rules.push({ prop: 'y2', required: true, type: 'number' }); break; case 'path': rules.push({ prop: 'd', required: true, type: 'string' }); break; case 'polygon': case 'polyline': rules.push({ prop: 'points', required: true, type: 'string' }); break; case 'rect': rules.push({ prop: 'height', required: true, type: 'number' }); rules.push({ prop: 'rx', type: 'number' }); rules.push({ prop: 'ry', type: 'number' }); rules.push({ prop: 'width', required: true, type: 'number' }); rules.push({ prop: 'x', required: true, type: 'number' }); rules.push({ prop: 'y', required: true, type: 'number' }); break; case 'g': rules.push({ prop: 'shapes', required: true, type: 'array' }); break; } return rules; }; var valid = function valid(shape) { var errors = getErrors(shape); return { errors: errors, valid: errors.length === 0 }; }; var _slicedToArray = function () { function sliceIterator(arr, i) { var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i["return"]) _i["return"](); } finally { if (_d) throw _e; } } return _arr; } return function (arr, i) { if (Array.isArray(arr)) { return arr; } else if (Symbol.iterator in Object(arr)) { return sliceIterator(arr, i); } else { throw new TypeError("Invalid attempt to destructure non-iterable instance"); } }; }(); var _typeof$1 = 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; }; /** * A tweenable color. * * @typedef {Object} Color * * @property {string} middleware - The name of this middleware. * @property {number} r - The hexadecimal red value. * @property {number} g - The hexadecimal green value. * @property {number} b - The hexadecimal blue value. * @property {number} a - The alpha value. */ var name = 'color'; var htmlColors = { 'aliceblue': '#F0F8FF', 'antiquewhite': '#FAEBD7', 'aqua': '#00FFFF', 'aquamarine': '#7FFFD4', 'azure': '#F0FFFF', 'beige': '#F5F5DC', 'bisque': '#FFE4C4', 'black': '#000000', 'blanchedalmond': '#FFEBCD', 'blue': '#0000FF', 'blueviolet': '#8A2BE2', 'brown': '#A52A2A', 'burlywood': '#DEB887', 'cadetblue': '#5F9EA0', 'chartreuse': '#7FFF00', 'chocolate': '#D2691E', 'coral': '#FF7F50', 'cornflowerblue': '#6495ED', 'cornsilk': '#FFF8DC', 'crimson': '#DC143C', 'cyan': '#00FFFF', 'darkblue': '#00008B', 'darkcyan': '#008B8B', 'darkgoldenrod': '#B8860B', 'darkgray': '#A9A9A9', 'darkgreen': '#006400', 'darkgrey': '#A9A9A9', 'darkkhaki': '#BDB76B', 'darkmagenta': '#8B008B', 'darkolivegreen': '#556B2F', 'darkorange': '#FF8C00', 'darkorchid': '#9932CC', 'darkred': '#8B0000', 'darksalmon': '#E9967A', 'darkseagreen': '#8FBC8F', 'darkslateblue': '#483D8B', 'darkslategray': '#2F4F4F', 'darkslategrey': '#2F4F4F', 'darkturquoise': '#00CED1', 'darkviolet': '#9400D3', 'deeppink': '#FF1493', 'deepskyblue': '#00BFFF', 'dimgray': '#696969', 'dimgrey': '#696969', 'dodgerblue': '#1E90FF', 'firebrick': '#B22222', 'floralwhite': '#FFFAF0', 'forestgreen': '#228B22', 'fuchsia': '#FF00FF', 'gainsboro': '#DCDCDC', 'ghostwhite': '#F8F8FF', 'gold': '#FFD700', 'goldenrod': '#DAA520', 'gray': '#808080', 'green': '#008000', 'greenyellow': '#ADFF2F', 'grey': '#808080', 'honeydew': '#F0FFF0', 'hotpink': '#FF69B4', 'indianred': '#CD5C5C', 'indigo': '#4B0082', 'ivory': '#FFFFF0', 'khaki': '#F0E68C', 'lavender': '#E6E6FA', 'lavenderblush': '#FFF0F5', 'lawngreen': '#7CFC00', 'lemonchiffon': '#FFFACD', 'lightblue': '#ADD8E6', 'lightcoral': '#F08080', 'lightcyan': '#E0FFFF', 'lightgoldenrodyellow': '#FAFAD2', 'lightgray': '#D3D3D3', 'lightgreen': '#90EE90', 'lightgrey': '#D3D3D3', 'lightpink': '#FFB6C1', 'lightsalmon': '#FFA07A', 'lightseagreen': '#20B2AA', 'lightskyblue': '#87CEFA', 'lightslategray': '#778899', 'lightslategrey': '#778899', 'lightsteelblue': '#B0C4DE', 'lightyellow': '#FFFFE0', 'lime': '#00FF00', 'limegreen': '#32CD32', 'linen': '#FAF0E6', 'magenta': '#FF00FF', 'maroon': '#800000', 'mediumaquamarine': '#66CDAA', 'mediumblue': '#0000CD', 'mediumorchid': '#BA55D3', 'mediumpurple': '#9370DB', 'mediumseagreen': '#3CB371', 'mediumslateblue': '#7B68EE', 'mediumspringgreen': '#00FA9A', 'mediumturquoise': '#48D1CC', 'mediumvioletred': '#C71585', 'midnightblue': '#191970', 'mintcream': '#F5FFFA', 'mistyrose': '#FFE4E1', 'moccasin': '#FFE4B5', 'navajowhite': '#FFDEAD', 'navy': '#000080', 'oldlace': '#FDF5E6', 'olive': '#808000', 'olivedrab': '#6B8E23', 'orange': '#FFA500', 'orangered': '#FF4500', 'orchid': '#DA70D6', 'palegoldenrod': '#EEE8AA', 'palegreen': '#98FB98', 'paleturquoise': '#AFEEEE', 'palevioletred': '#DB7093', 'papayawhip': '#FFEFD5', 'peachpuff': '#FFDAB9', 'peru': '#CD853F', 'pink': '#FFC0CB', 'plum': '#DDA0DD', 'powderblue': '#B0E0E6', 'purple': '#800080', 'rebeccapurple': '#663399', 'red': '#FF0000', 'rosybrown': '#BC8F8F', 'royalblue': '#4169E1', 'saddlebrown': '#8B4513', 'salmon': '#FA8072', 'sandybrown': '#F4A460', 'seagreen': '#2E8B57', 'seashell': '#FFF5EE', 'sienna': '#A0522D', 'silver': '#C0C0C0', 'skyblue': '#87CEEB', 'slateblue': '#6A5ACD', 'slategray': '#708090', 'slategrey': '#708090', 'snow': '#FFFAFA', 'springgreen': '#00FF7F', 'steelblue': '#4682B4', 'tan': '#D2B48C', 'teal': '#008080', 'thistle': '#D8BFD8', 'tomato': '#FF6347', 'turquoise': '#40E0D0', 'violet': '#EE82EE', 'wheat': '#F5DEB3', 'white': '#FFFFFF', 'whitesmoke': '#F5F5F5', 'yellow': '#FFFF00', 'yellowgreen': '#9ACD32' }; var htmlColorKeys = Object.keys(htmlColors); /** * Converts a color string to a Color. * * @param {*} x - A potential color string. * * @returns {*} * * @example * input('#FFFFFF') */ var input = function input(x) { if (typeof x === 'string') { if (hex(x)) { return hexToColor(x); } else if (rgb(x)) { return rgbToColor(x); } else if (rgba(x)) { return rgbaToColor(x); } else if (html(x)) { return htmlToColor(x); } } return x; }; /** * Converts a Color to a rgba color string. * * @param {*} x - A potential Color. * * @returns {*} * * @example * output(color) */ var output = function output(x) { if ((typeof x === 'undefined' ? 'undefined' : _typeof$1(x)) === 'object' && x.middleware === name) { return colorToRgba(x); } return x; }; /** * Is string a hex color? * * @param {string} str - A potential hex color. * * @returns {boolean} * * @example * hex('#FFFFFF') */ var hex = function hex(str) { return str.match(/^#(?:[0-9a-f]{3}){1,2}$/i) !== null; }; /** * Is string a rgba color? * * @param {string} str - A potential rgba color. * * @returns {boolean} * * @example * rgba('rgba(255,255,255,1)') */ var rgba = function rgba(str) { return str.startsWith('rgba('); }; /** * Is string a rgb color? * * @param {string} str - A potential rgb color. * * @returns {boolean} * * @example * rgb('rgb(255,255,255)') */ var rgb = function rgb(str) { return str.startsWith('rgb('); }; /** * Is string a html color? * * @param {string} str - A potential html color. * * @returns {boolean} * * @example * html('limegreen') */ var html = function html(str) { return htmlColorKeys.indexOf(str) !== -1; }; /** * Converts a hex string to a Color. * * @param {string} hex - A hex color. * * @returns {Color} * * @example * hexToColor('#FFFFFF') */ var hexToColor = function hexToColor(hex) { var x = hex.replace('#', ''); if (x.length === 3) { var y = ''; for (var i = 0; i < 3; i++) { var v = x.charAt(i); y += '' + v + v; } x = y; } return { middleware: name, r: parseInt(x.slice(0, 2), 16), g: parseInt(x.slice(2, 4), 16), b: parseInt(x.slice(4, 6), 16), a: 1 }; }; /** * Converts a rgb string to a Color. * * @param {string} rgb - A rgb color. * * @returns {Color} * * @example * rgbToColor('rgb(255,255,255)') */ var rgbToColor = function rgbToColor(rgb) { var x = rgb.replace(/\s/g, ''); var _x$substring$split = x.substring(4, x.length - 1).split(','), _x$substring$split2 = _slicedToArray(_x$substring$split, 3), r = _x$substring$split2[0], g = _x$substring$split2[1], b = _x$substring$split2[2]; return { middleware: name, r: parseFloat(r), g: parseFloat(g), b: parseFloat(b), a: 1 }; }; /** * Converts a rgba string to a Color. * * @param {string} rgba - A rgba color. * * @returns {Color} * * @example * rgbaToColor('rgba(255,255,255,1)') */ var rgbaToColor = function rgbaToColor(rgba) { var x = rgba.replace(/\s/g, ''); var _x$substring$split3 = x.substring(5, x.length - 1).split(','), _x$substring$split4 = _slicedToArray(_x$substring$split3, 4), r = _x$substring$split4[0], g = _x$substring$split4[1], b = _x$substring$split4[2], a = _x$substring$split4[3]; return { middleware: 'color', r: parseFloat(r), g: parseFloat(g), b: parseFloat(b), a: parseFloat(a) }; }; /** * Converts a html string to a Color. * * @param {string} html - An html color. * * @returns {Color} * * @example * htmlToColor('limegreen') */ var htmlToColor = function htmlToColor(html) { return hexToColor(htmlColors[html]); }; /** * Converts a Color to a rgba color string. * * @param {Color} color * * @returns {string} * * @example * colorToRgba(color) */ var colorToRgba = function colorToRgba(_ref) { var r = _ref.r, g = _ref.g, b = _ref.b, a = _ref.a; return 'rgba(' + parseInt(limit(r, 0, 255), 10) + ',' + parseInt(limit(g, 0, 255), 10) + ',' + parseInt(limit(b, 0, 255), 10) + ',' + limit(a, 0, 1) + ')'; }; /** * Find the closest number within limits. * * @param {number} num - The desired number. * @param {number} min - The minimum returned number. * @param {number} max - the maximum returned number. * * @returns {number} * * @example * limit(-1, 2, 5) */ var limit = function limit(num, min, max) { return Math.max(min, Math.min(max, num)); }; var colorMiddleware = { name: name, input: input, output: output }; var _typeof$4 = 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; }; /** * A naive, but small, clone function. * * @param {*} value * * @returns {*} * * @example * clone('hello world') */ var clone = function clone(value) { if ((typeof value === 'undefined' ? 'undefined' : _typeof$4(value)) !== 'object') { return value; } else if (Array.isArray(value)) { var arr = []; for (var i = 0, l = value.length; i < l; i++) { arr.push(clone(value[i])); } return arr; } else if (value !== null) { var obj = {}; for (var key in value) { obj[key] = clone(value[key]); } return obj; } return value; }; var _typeof$5 = 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; }; /** * A tweenable unit. * * @typedef {Object} Unit * * @property {string} middleware - The name of this middleware. * @property {string} values - The type of color string to output. */ var name$1 = 'unit'; var units = ['ch', 'cm', 'em', 'ex', 'in', 'mm', 'pc', 'pt', 'px', 'rem', 'vh', 'vmax', 'vmin', 'vw', '%']; /** * Converts a unit string to a Unit. * * @param {*} x - A potential unit string. * * @returns {*} * * @example * input('20px') */ var input$1 = function input(x) { if (typeof x === 'string') { var parts = x.split(' '); var values = []; for (var i = 0, l = parts.length; i < l; i++) { var part = parts[i]; var number = parseFloat(part); var unit = part.replace(number, ''); if (!isNaN(number) && (unit === '' || units.indexOf(unit) !== -1)) { values.push([number, unit]); } else { values.push(part); } } if (values.toString() !== parts.toString()) { return { middleware: name$1, values: values }; } } return x; }; /** * Converts a Unit to a unit string. * * @param {*} x - A potential Unit. * * @returns {*} * * @example * output(unit) */ var output$1 = function output(x) { if ((typeof x === 'undefined' ? 'undefined' : _typeof$5(x)) === 'object' && x.middleware === name$1) { var values = x.values; var result = []; for (var i = 0, l = values.length; i < l; i++) { result.push(values[i].join('')); } return result.join(' '); } return x; }; var unitMiddleware = { name: name$1, input: input$1, output: output$1 }; var config = { defaults: { keyframe: { duration: 250, easing: 'easeInOutQuad' }, motionPath: { easing: 'easeInOutQuad' }, timeline: { alternate: false, initialIterations: 0, iterations: 1, middleware: [colorMiddleware, unitMiddleware], queue: 0, reverse: false } } }; var _typeof$6 = 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; }; /** * A group of functions to transform/untransform a value. * * @typedef {Object} Middleware * * @property {string} name - The name of the middleware. * @property {function} input - Transform. * @property {function} output - Untransform. */ /** * Run every part of a value through a function. * * @param {*} value * @param {function} func * * @returns {*} * * @example * apply(2, n => n * 2) */ var apply$1 = function apply(value, func) { var v = func(value); if ((typeof v === 'undefined' ? 'undefined' : _typeof$6(v)) !== 'object') { return v; } else if (Array.isArray(v)) { var arr = []; for (var i = 0, l = v.length; i < l; i++) { arr.push(apply(v[i], func)); } return arr; } else if (v !== null) { var obj = {}; for (var k in v) { obj[k] = apply(v[k], func); } return obj; } return v; }; /** * Runs each Middleware input function in turn on a value. * * @param {*} value * @param {Middleware[]} middleware * * @returns {*} * * @example * input({ foo: 1, bar: [ 2, 3 ] }, middleware) */ var input$2 = function input(value, middleware) { var v = value; for (var i = 0, l = middleware.length; i < l; i++) { v = apply$1(v, middleware[i].input); } return v; }; /** * Runs each Middleware output function in reverse on a value. * * @param {*} value * @param {Middleware[]} middleware * * @returns {*} * * @example * output({ foo: 1, bar: [ 2, 3 ] }, middleware) */ var output$2 = function output(value, middleware) { var v = value; for (var i = middleware.length - 1; i >= 0; i--) { v = apply$1(v, middleware[i].output); } return v; }; var _extends$4 = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; var _typeof$3 = 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 _slicedToArray$1 = function () { function sliceIterator(arr, i) { var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i["return"]) _i["return"](); } finally { if (_d) throw _e; } } return _arr; } return function (arr, i) { if (Array.isArray(arr)) { return arr; } else if (Symbol.iterator in Object(arr)) { return sliceIterator(arr, i); } else { throw new TypeError("Invalid attempt to destructure non-iterable instance"); } }; }(); /* globals true */ /** * The position of an object on a Timeline * where 0 is Timeline start and 1 is Timeline finish. * * @typedef {Object} TimelinePosition * * @property {Position} start * @property {Position} finish */ /** * A Shape positioned on a Timeline. * * @typedef {Object} TimelineShape * * @property {Shape} shape * @property {TimelinePosition} timelinePosition */ /** * The position of an object on a Timeline in milliseconds. * * @typedef {Object} MsTimelinePosition * * @property {number} start. * @property {number} finish. */ /** * A Shape positioned on a Timeline (position set in milliseconds). * * @typedef {Object} MsTimelineShape * * @property {Shape} shape * @property {MsTimelinePosition} timelinePosition */ /** * A TimelineShape array and their total duration. * * @typedef {Object} TimelineShapesAndDuration * * @property {TimelineShape[]} timelineShapes * @property {number} duration */ /** * The options required to calculate the current playback Position. * * @typedef {Object} PlaybackOptions * * @property {boolean} alternate - Should the next iteration reverse current direction? * @property {number} duration - Milliseconds that each iteration lasts. * @property {number} initialIterations - The starting number of iterations. * @property {number} iterations - The number of playback interations (additional to initialIterations). * @property {boolean} reverse - Should the first iteration start in a reverse direction? * @property {number} [started] - The UNIX timestamp of playback start. */ /** * PlaybackOptions and tween middleware. * * @typedef {Object} TimelineOptions * * @extends PlaybackOptions * @property {Middleware[]} middleware */ /** * A Shape and timeline related options. * * @typedef {Object} ShapeWithOptions * * @property {(string|number)} [after] - The name of the Shape to queue after (in sequence). * @property {(string|number)} [at] - The name of the Shape to queue at (in parallel). * @property {(string|number)} name - A unique reference. * @property {number} offset - The offset in milliseconds to adjust the queuing of this shape. * @property {Shape} shape */ /** * An object containing Middlware, PlaybackOptions and ShapesWithOptions. * * @typedef {Object} SortedTimelineProps * * @property {Middleware[]} middleware * @property {PlaybackOptions} playbackOptions * @property {ShapeWithOptions[]} shapesWithOptions */ /** * A sequence of Shapes. * * @typedef {Object} Timeline * * @property {Middleware[]} middleware * @property {PlaybackOptions} playbackOptions * @property {Object} state - Holds the last known state of the timeline. * @property {TimelineShape[]} timelineShapes */ /** * Runs each Middleware input function on every Keyframe's FrameShape. * * @param {Shape} shape * @param {Middleware[]} middleware * * @example * apply(shape, middleware) */ var apply = function apply(_ref, middleware) { var keyframes = _ref.keyframes; for (var i = 0, l = keyframes.length; i < l; i++) { var keyframe = keyframes[i]; keyframe.frameShape = input$2(keyframe.frameShape, middleware); } }; /** * Is playback currently in reverse? * * @param {PlaybackOptions} playbackOptions * @param {number} complete - The number of iterations complete. * * @example * currentReverse(playbackOptions, complete) */ var currentReverse = function currentReverse(playbackOptions, complete) { var reverse = playbackOptions.reverse; if (complete === 0) { return reverse; } var alternate = playbackOptions.alternate; var initialIterations = playbackOptions.initialIterations; var initialReverse = sameDirection(alternate, initialIterations) ? reverse : !reverse; return sameDirection(alternate, initialIterations + complete) ? initialReverse : !initialReverse; }; /** * The number of iterations a Timeline has completed. * * @param {PlaybackOptions} playbackOptions * @param {number} opts.at * * @returns {number} * * @example * iterationsComplete(playbackOptions, 1000) */ var iterationsComplete = function iterationsComplete(playbackOptions, at) { var duration = playbackOptions.duration; var iterations = playbackOptions.iterations; var started = playbackOptions.started; if (typeof started === 'undefined' || at <= started) { return 0; } var ms = at - started; var maxDuration = duration * iterations; if (ms >= maxDuration) { return iterations; } return ms / duration; }; /** * Starts playback of a Timeline. * * @param {Timeline} timeline * @param {PlaybackOptions} playbackOptions * @param {number} [at] * * @example * play(timeline, { initialIterations: 0 }) */ var play$1 = function play(timeline) { var playbackOptions = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; var at = arguments[2]; timeline.playbackOptions = updatePlaybackOptions({ at: at, timeline: timeline, playbackOptions: playbackOptions }); updateState(timeline, at); }; /** * Calculate the Timeline Position. * * @param {number} totalIterations - initialIterations + iterationsComplete. * @param {boolean} reverse - Is the Timeline currently in reverse? * * @returns {Position} * * @example * position(5.43, true) */ var position = function position(totalIterations, reverse) { var i = totalIterations >= 1 && totalIterations % 1 === 0 ? 1 : totalIterations % 1; return reverse ? 1 - i : i; }; /** * Is the direction same as initial direction? * * @param {boolean} alternate - Is iteration direction alternating? * @param {number} iterations - The number of iterations complete. * * @return {boolean} * * @example * sameDirection(true, 3.25) */ var sameDirection = function sameDirection(alternate, iterations) { var x = iterations % 2; return !alternate || iterations === 0 || x <= 1 && x % 2 > 0; }; /** * Calculate the start position of a Shape on the Timeline. * * @param {Object} props * @param {(string|number)} [props.after] * @param {(string|number)} [props.at] * @param {MsTimelineShape[]} props.msTimelineShapes * @param {number} props.offset * @param {number} props.timelineFinish - The current finish of the timeline. * * @returns {number} * * @example * shapeStart({ 'foo', msTimelineShapes, 200, 2000 }) */ var shapeStart = function shapeStart(_ref2) { var after = _ref2.after, at = _ref2.at, msTimelineShapes = _ref2.msTimelineShapes, offset = _ref2.offset, timelineFinish = _ref2.timelineFinish; if (typeof after !== 'undefined' || typeof at !== 'undefined') { var reference = typeof after !== 'undefined' ? after : at; for (var i = 0; i < msTimelineShapes.length; i++) { var s = msTimelineShapes[i]; if (reference === s.shape.name) { return (typeof at !== 'undefined' ? s.timelinePosition.start : s.timelinePosition.finish) + offset; } } for (var _i = 0; _i < msTimelineShapes.length; _i++) { var _s = msTimelineShapes[_i]; for (var j = 0; j < _s.shape.keyframes.length; j++) { var keyframe = _s.shape.keyframes[j]; if (reference === keyframe.name) { return _s.timelinePosition.start + _s.shape.duration * keyframe.position + offset; } } } { throw new Error('No Shape or Keyframe matching name \'' + reference + '\''); } } return timelineFinish + offset; }; /** * Create a ShapeWithOptions from an array. * * @param {Object[]} arr * @param {Shape} arr.0 * @param {Object} arr.1 * * @returns {ShapeWithOptions} * * @example * shapeWithOptionsFromArray(arr, i) */ var shapeWithOptionsFromArray = function shapeWithOptionsFromArray(_ref3, i) { var _ref4 = _slicedToArray$1(_ref3, 2), shape = _ref4[0], options = _ref4[1]; if (true && ((typeof shape === 'undefined' ? 'undefined' : _typeof$3(shape)) !== 'object' || !shape.keyframes)) { throw new TypeError('When an array is passed to the timeline function the first item must be a Shape'); } if (true && (typeof options === 'undefined' ? 'undefined' : _typeof$3(options)) !== 'object') { throw new TypeError('When an array is passed to the timeline function the second item must be an object'); } var _options$name = options.name, name = _options$name === undefined ? i : _options$name, _options$queue = options.queue, queue = _options$queue === undefined ? config.defaults.timeline.queue : _options$queue; if (true && typeof name !== 'string' && typeof name !== 'number') { throw new TypeError('The name prop must be of type string or number'); } if ((typeof queue === 'undefined' ? 'undefined' : _typeof$3(queue)) === 'object' && !Array.isArray(queue) && queue !== null) { var after = queue.after, at = queue.at, _queue$offset = queue.offset, offset = _queue$offset === undefined ? 0 : _queue$offset; if (true && typeof offset !== 'undefined' && typeof offset !== 'number') { throw new TypeError('The queue.offset prop must be of type number'); } if (true && typeof at !== 'undefined' && typeof after !== 'undefined') { throw new TypeError('You cannot pass both queue.at and queue.after props'); } if (true && typeof at !== 'undefined' && typeof at !== 'string' && typeof at !== 'number') { throw new TypeError('The queue.at prop must be of type string or number'); } if (true && typeof after !== 'undefined' && typeof after !== 'string' && typeof after !== 'number') { throw new TypeError('The queue.after prop must be of type string or number'); } if (typeof at !== 'undefined') { return { at: at, name: name, offset: offset, shape: shape }; } if (typeof after !== 'undefined') { return { after: after, name: name, offset: offset, shape: shape }; } return { name: name, offset: offset, shape: shape }; } else if (typeof queue === 'number') { return { name: name, offset: queue, shape: shape }; } else if (typeof queue === 'string') { return { after: queue, name: name, offset: 0, shape: shape }; } { throw new TypeError('The queue prop must be of type number, string or object'); } return { name: name, offset: 0, shape: shape }; }; /** * Sorts an array of Shapes, ShapesWithOptions and TimelineOptions. * * @param {(Shape|Object[]|TimelineOptions)[]} props * * @returns {SortedTimelineProps} * * @example * sort(props) */ var sort = function sort(props) { if (true && props.length === 0) { throw new TypeError('The timeline function must be passed at least one Shape'); } var options = {}; var shapesWithOptions = []; for (var i = 0, l = props.length; i < l; i++) { var prop = props[i]; if (Array.isArray(prop)) { shapesWithOptions.push(shapeWithOptionsFromArray(prop, i)); } else { if (true && (typeof prop === 'undefined' ? 'undefined' : _typeof$3(prop)) !== 'object') { throw new TypeError('The timeline function must only be passed objects and arrays'); } if (prop.keyframes) { shapesWithOptions.push({ name: i, offset: config.defaults.timeline.queue, shape: prop }); } else { { if (i === 0) { throw new TypeError('The timeline function must receive a Shape as the first argument'); } else if (i !== props.length - 1) { throw new TypeError('The timeline function must receive options as the final argument'); } } options = clone(prop); } } } return { middleware: validMiddleware(options), playbackOptions: validPlaybackOptions(options), shapesWithOptions: shapesWithOptions }; }; /** * Creates a Timeline from one or more Shape. * Optionally can take an options object as the last argument, * as well as options for each Shape if passed in as an array. * * @param {...(Shape|Object[]|TimelineOptions)} props * * @returns {Timeline} * * @example * timeline(circle, [ square, { queue: -200 } ], { duration: 5000 }) */ var timeline = function timeline() { for (var _len = arguments.length, props = Array(_len), _key = 0; _key < _len; _key++) { props[_key] = arguments[_key]; } var _sort = sort(props), middleware = _sort.middleware, playbackOptions = _sort.playbackOptions, shapesWithOptions = _sort.shapesWithOptions; var _timelineShapesAndDur = timelineShapesAndDuration(shapesWithOptions, middleware), duration = _timelineShapesAndDur.duration, timelineShapes = _timelineShapesAndDur.timelineShapes; if (typeof playbackOptions.duration === 'undefined') { playbackOptions.duration = duration; } var t = { middleware: middleware, playbackOptions: playbackOptions, state: {}, timelineShapes: timelineShapes }; for (var i = 0, l = timelineShapes.length; i < l; i++) { var shape = timelineShapes[i].shape; shape.timeline = t; shape.timelineIndex = i; } updateState(t); t.event = event(t); return t; }; /** * Converts a set of MsTimelineShapes to a set of TimelineShapes * given the Timeline start and total duration values. * * @param {Object} props * @param {number} props.duration * @param {msTimelineShape[]} props.msTimelineShapes * @param {number} props.start * * @returns {TimelineShape[]} * * @example * timelineShapes() */ var timelineShapes = function timelineShapes(_ref5) { var duration = _ref5.duration, msTimelineShapes = _ref5.msTimelineShapes, start = _ref5.start; var s = []; for (var i = 0, l = msTimelineShapes.length; i < l; i++) { var msTimelineShape = msTimelineShapes[i]; var timelinePosition = msTimelineShape.timelinePosition; s.push({ shape: msTimelineShape.shape, timelinePosition: { start: (timelinePosition.start - start) / duration, finish: (timelinePosition.finish - start) / duration } }); } return s; }; /** * Converts an array of ShapesWithOptions into TimelineShapes * and their total duration. * * @param {ShapeWithOptions[]} shapesWithOptions * @param {Middleware[]} middleware * * @returns {TimelineShapesAndDuration} * * @example * timelineShapes(shapesWithOptions) */ var timelineShapesAndDuration = function timelineShapesAndDuration(shapesWithOptions, middleware) { var timelineStart = 0; var timelineFinish = 0; var msTimelineShapes = []; for (var i = 0, l = shapesWithOptions.length; i < l; i++) { var _shapesWithOptions$i = shapesWithOptions[i], after = _shapesWithOptions$i.after, at = _shapesWithOptions$i.at, name = _shapesWithOptions$i.name, offset = _shapesWithOptions$i.offset, shape = _shapesWithOptions$i.shape; if (true && typeof shape.timeline !== 'undefined') { throw new Error('A Shape can only be added to one timeline'); } shape.name = name; apply(shape, middleware); var start = shapeStart({ after: after, at: at, msTimelineShapes: msTimelineShapes, offset: offset, timelineFinish: timelineFinish }); var finish = start + shape.duration; timelineStart = Math.min(timelineStart, start); timelineFinish = Math.max(timelineFinish, finish); msTimelineShapes.push({ shape: shape, timelinePosition: { start: start, finish: