diff --git a/hal-core/resources/web/js/lib/bootstrap-colorpicker.LICENSE b/hal-core/resources/web/js/lib/bootstrap-colorpicker.LICENSE new file mode 100644 index 00000000..bc6fc511 --- /dev/null +++ b/hal-core/resources/web/js/lib/bootstrap-colorpicker.LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2017 Javi Aguilar + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/hal-core/resources/web/js/lib/bootstrap-switch.LICENSE b/hal-core/resources/web/js/lib/bootstrap-switch.LICENSE new file mode 100644 index 00000000..31e23cd1 --- /dev/null +++ b/hal-core/resources/web/js/lib/bootstrap-switch.LICENSE @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2013-2015 The authors of Bootstrap Switch + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/hal-core/resources/web/js/lib/c3.LICENSE b/hal-core/resources/web/js/lib/c3.LICENSE new file mode 100644 index 00000000..29ce9cb0 --- /dev/null +++ b/hal-core/resources/web/js/lib/c3.LICENSE @@ -0,0 +1,20 @@ +The MIT License (MIT) + +Copyright (c) 2013 Masayuki Tanaka + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software is furnished to do so, +subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/hal-core/resources/web/js/lib/force-graph.LICENSE.txt b/hal-core/resources/web/js/lib/force-graph.LICENSE.txt new file mode 100644 index 00000000..a36ddd4f --- /dev/null +++ b/hal-core/resources/web/js/lib/force-graph.LICENSE.txt @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2018 Vasco Asturiano + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/hal-core/resources/web/js/lib/force-graph.js b/hal-core/resources/web/js/lib/force-graph.js new file mode 100644 index 00000000..13d6e200 --- /dev/null +++ b/hal-core/resources/web/js/lib/force-graph.js @@ -0,0 +1,12201 @@ +// Version 1.43.4 force-graph - https://github.com/vasturiano/force-graph +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() : + typeof define === 'function' && define.amd ? define(factory) : + (global = typeof globalThis !== 'undefined' ? globalThis : global || self, global.ForceGraph = factory()); +})(this, (function () { 'use strict'; + + function styleInject(css, ref) { + if ( ref === void 0 ) ref = {}; + var insertAt = ref.insertAt; + + if (!css || typeof document === 'undefined') { return; } + + var head = document.head || document.getElementsByTagName('head')[0]; + var style = document.createElement('style'); + style.type = 'text/css'; + + if (insertAt === 'top') { + if (head.firstChild) { + head.insertBefore(style, head.firstChild); + } else { + head.appendChild(style); + } + } else { + head.appendChild(style); + } + + if (style.styleSheet) { + style.styleSheet.cssText = css; + } else { + style.appendChild(document.createTextNode(css)); + } + } + + var css_248z = ".force-graph-container canvas {\n display: block;\n user-select: none;\n outline: none;\n -webkit-tap-highlight-color: transparent;\n}\n\n.force-graph-container .graph-tooltip {\n position: absolute;\n top: 0;\n font-family: sans-serif;\n font-size: 16px;\n padding: 4px;\n border-radius: 3px;\n color: #eee;\n background: rgba(0,0,0,0.65);\n visibility: hidden; /* by default */\n}\n\n.force-graph-container .clickable {\n cursor: pointer;\n}\n\n.force-graph-container .grabbable {\n cursor: move;\n cursor: grab;\n cursor: -moz-grab;\n cursor: -webkit-grab;\n}\n\n.force-graph-container .grabbable:active {\n cursor: grabbing;\n cursor: -moz-grabbing;\n cursor: -webkit-grabbing;\n}\n"; + styleInject(css_248z); + + function _iterableToArrayLimit$2(arr, i) { + var _i = null == arr ? null : "undefined" != typeof Symbol && arr[Symbol.iterator] || arr["@@iterator"]; + if (null != _i) { + var _s, + _e, + _x, + _r, + _arr = [], + _n = !0, + _d = !1; + try { + if (_x = (_i = _i.call(arr)).next, 0 === i) { + if (Object(_i) !== _i) return; + _n = !1; + } else for (; !(_n = (_s = _x.call(_i)).done) && (_arr.push(_s.value), _arr.length !== i); _n = !0); + } catch (err) { + _d = !0, _e = err; + } finally { + try { + if (!_n && null != _i.return && (_r = _i.return(), Object(_r) !== _r)) return; + } finally { + if (_d) throw _e; + } + } + return _arr; + } + } + function ownKeys(object, enumerableOnly) { + var keys = Object.keys(object); + if (Object.getOwnPropertySymbols) { + var symbols = Object.getOwnPropertySymbols(object); + enumerableOnly && (symbols = symbols.filter(function (sym) { + return Object.getOwnPropertyDescriptor(object, sym).enumerable; + })), keys.push.apply(keys, symbols); + } + return keys; + } + function _objectSpread2(target) { + for (var i = 1; i < arguments.length; i++) { + var source = null != arguments[i] ? arguments[i] : {}; + i % 2 ? ownKeys(Object(source), !0).forEach(function (key) { + _defineProperty(target, key, source[key]); + }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)) : ownKeys(Object(source)).forEach(function (key) { + Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); + }); + } + return target; + } + function _typeof$1(obj) { + "@babel/helpers - typeof"; + + return _typeof$1 = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (obj) { + return typeof obj; + } : function (obj) { + return obj && "function" == typeof Symbol && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; + }, _typeof$1(obj); + } + function _defineProperty(obj, key, value) { + key = _toPropertyKey$3(key); + if (key in obj) { + Object.defineProperty(obj, key, { + value: value, + enumerable: true, + configurable: true, + writable: true + }); + } else { + obj[key] = value; + } + return obj; + } + function _setPrototypeOf(o, p) { + _setPrototypeOf = Object.setPrototypeOf ? Object.setPrototypeOf.bind() : function _setPrototypeOf(o, p) { + o.__proto__ = p; + return o; + }; + return _setPrototypeOf(o, p); + } + function _isNativeReflectConstruct() { + if (typeof Reflect === "undefined" || !Reflect.construct) return false; + if (Reflect.construct.sham) return false; + if (typeof Proxy === "function") return true; + try { + Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); + return true; + } catch (e) { + return false; + } + } + function _construct(Parent, args, Class) { + if (_isNativeReflectConstruct()) { + _construct = Reflect.construct.bind(); + } else { + _construct = function _construct(Parent, args, Class) { + var a = [null]; + a.push.apply(a, args); + var Constructor = Function.bind.apply(Parent, a); + var instance = new Constructor(); + if (Class) _setPrototypeOf(instance, Class.prototype); + return instance; + }; + } + return _construct.apply(null, arguments); + } + function _slicedToArray$2(arr, i) { + return _arrayWithHoles$2(arr) || _iterableToArrayLimit$2(arr, i) || _unsupportedIterableToArray$3(arr, i) || _nonIterableRest$2(); + } + function _toConsumableArray$2(arr) { + return _arrayWithoutHoles$2(arr) || _iterableToArray$2(arr) || _unsupportedIterableToArray$3(arr) || _nonIterableSpread$2(); + } + function _arrayWithoutHoles$2(arr) { + if (Array.isArray(arr)) return _arrayLikeToArray$3(arr); + } + function _arrayWithHoles$2(arr) { + if (Array.isArray(arr)) return arr; + } + function _iterableToArray$2(iter) { + if (typeof Symbol !== "undefined" && iter[Symbol.iterator] != null || iter["@@iterator"] != null) return Array.from(iter); + } + function _unsupportedIterableToArray$3(o, minLen) { + if (!o) return; + if (typeof o === "string") return _arrayLikeToArray$3(o, minLen); + var n = Object.prototype.toString.call(o).slice(8, -1); + if (n === "Object" && o.constructor) n = o.constructor.name; + if (n === "Map" || n === "Set") return Array.from(o); + if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray$3(o, minLen); + } + function _arrayLikeToArray$3(arr, len) { + if (len == null || len > arr.length) len = arr.length; + for (var i = 0, arr2 = new Array(len); i < len; i++) arr2[i] = arr[i]; + return arr2; + } + function _nonIterableSpread$2() { + throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); + } + function _nonIterableRest$2() { + throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); + } + function _toPrimitive$3(input, hint) { + if (typeof input !== "object" || input === null) return input; + var prim = input[Symbol.toPrimitive]; + if (prim !== undefined) { + var res = prim.call(input, hint || "default"); + if (typeof res !== "object") return res; + throw new TypeError("@@toPrimitive must return a primitive value."); + } + return (hint === "string" ? String : Number)(input); + } + function _toPropertyKey$3(arg) { + var key = _toPrimitive$3(arg, "string"); + return typeof key === "symbol" ? key : String(key); + } + + var xhtml = "http://www.w3.org/1999/xhtml"; + + var namespaces = { + svg: "http://www.w3.org/2000/svg", + xhtml: xhtml, + xlink: "http://www.w3.org/1999/xlink", + xml: "http://www.w3.org/XML/1998/namespace", + xmlns: "http://www.w3.org/2000/xmlns/" + }; + + function namespace(name) { + var prefix = name += "", i = prefix.indexOf(":"); + if (i >= 0 && (prefix = name.slice(0, i)) !== "xmlns") name = name.slice(i + 1); + return namespaces.hasOwnProperty(prefix) ? {space: namespaces[prefix], local: name} : name; // eslint-disable-line no-prototype-builtins + } + + function creatorInherit(name) { + return function() { + var document = this.ownerDocument, + uri = this.namespaceURI; + return uri === xhtml && document.documentElement.namespaceURI === xhtml + ? document.createElement(name) + : document.createElementNS(uri, name); + }; + } + + function creatorFixed(fullname) { + return function() { + return this.ownerDocument.createElementNS(fullname.space, fullname.local); + }; + } + + function creator(name) { + var fullname = namespace(name); + return (fullname.local + ? creatorFixed + : creatorInherit)(fullname); + } + + function none() {} + + function selector(selector) { + return selector == null ? none : function() { + return this.querySelector(selector); + }; + } + + function selection_select(select) { + if (typeof select !== "function") select = selector(select); + + for (var groups = this._groups, m = groups.length, subgroups = new Array(m), j = 0; j < m; ++j) { + for (var group = groups[j], n = group.length, subgroup = subgroups[j] = new Array(n), node, subnode, i = 0; i < n; ++i) { + if ((node = group[i]) && (subnode = select.call(node, node.__data__, i, group))) { + if ("__data__" in node) subnode.__data__ = node.__data__; + subgroup[i] = subnode; + } + } + } + + return new Selection$1(subgroups, this._parents); + } + + // Given something array like (or null), returns something that is strictly an + // array. This is used to ensure that array-like objects passed to d3.selectAll + // or selection.selectAll are converted into proper arrays when creating a + // selection; we don’t ever want to create a selection backed by a live + // HTMLCollection or NodeList. However, note that selection.selectAll will use a + // static NodeList as a group, since it safely derived from querySelectorAll. + function array(x) { + return x == null ? [] : Array.isArray(x) ? x : Array.from(x); + } + + function empty() { + return []; + } + + function selectorAll(selector) { + return selector == null ? empty : function() { + return this.querySelectorAll(selector); + }; + } + + function arrayAll(select) { + return function() { + return array(select.apply(this, arguments)); + }; + } + + function selection_selectAll(select) { + if (typeof select === "function") select = arrayAll(select); + else select = selectorAll(select); + + for (var groups = this._groups, m = groups.length, subgroups = [], parents = [], j = 0; j < m; ++j) { + for (var group = groups[j], n = group.length, node, i = 0; i < n; ++i) { + if (node = group[i]) { + subgroups.push(select.call(node, node.__data__, i, group)); + parents.push(node); + } + } + } + + return new Selection$1(subgroups, parents); + } + + function matcher(selector) { + return function() { + return this.matches(selector); + }; + } + + function childMatcher(selector) { + return function(node) { + return node.matches(selector); + }; + } + + var find$1 = Array.prototype.find; + + function childFind(match) { + return function() { + return find$1.call(this.children, match); + }; + } + + function childFirst() { + return this.firstElementChild; + } + + function selection_selectChild(match) { + return this.select(match == null ? childFirst + : childFind(typeof match === "function" ? match : childMatcher(match))); + } + + var filter = Array.prototype.filter; + + function children() { + return Array.from(this.children); + } + + function childrenFilter(match) { + return function() { + return filter.call(this.children, match); + }; + } + + function selection_selectChildren(match) { + return this.selectAll(match == null ? children + : childrenFilter(typeof match === "function" ? match : childMatcher(match))); + } + + function selection_filter(match) { + if (typeof match !== "function") match = matcher(match); + + for (var groups = this._groups, m = groups.length, subgroups = new Array(m), j = 0; j < m; ++j) { + for (var group = groups[j], n = group.length, subgroup = subgroups[j] = [], node, i = 0; i < n; ++i) { + if ((node = group[i]) && match.call(node, node.__data__, i, group)) { + subgroup.push(node); + } + } + } + + return new Selection$1(subgroups, this._parents); + } + + function sparse(update) { + return new Array(update.length); + } + + function selection_enter() { + return new Selection$1(this._enter || this._groups.map(sparse), this._parents); + } + + function EnterNode(parent, datum) { + this.ownerDocument = parent.ownerDocument; + this.namespaceURI = parent.namespaceURI; + this._next = null; + this._parent = parent; + this.__data__ = datum; + } + + EnterNode.prototype = { + constructor: EnterNode, + appendChild: function(child) { return this._parent.insertBefore(child, this._next); }, + insertBefore: function(child, next) { return this._parent.insertBefore(child, next); }, + querySelector: function(selector) { return this._parent.querySelector(selector); }, + querySelectorAll: function(selector) { return this._parent.querySelectorAll(selector); } + }; + + function constant$4(x) { + return function() { + return x; + }; + } + + function bindIndex(parent, group, enter, update, exit, data) { + var i = 0, + node, + groupLength = group.length, + dataLength = data.length; + + // Put any non-null nodes that fit into update. + // Put any null nodes into enter. + // Put any remaining data into enter. + for (; i < dataLength; ++i) { + if (node = group[i]) { + node.__data__ = data[i]; + update[i] = node; + } else { + enter[i] = new EnterNode(parent, data[i]); + } + } + + // Put any non-null nodes that don’t fit into exit. + for (; i < groupLength; ++i) { + if (node = group[i]) { + exit[i] = node; + } + } + } + + function bindKey(parent, group, enter, update, exit, data, key) { + var i, + node, + nodeByKeyValue = new Map, + groupLength = group.length, + dataLength = data.length, + keyValues = new Array(groupLength), + keyValue; + + // Compute the key for each node. + // If multiple nodes have the same key, the duplicates are added to exit. + for (i = 0; i < groupLength; ++i) { + if (node = group[i]) { + keyValues[i] = keyValue = key.call(node, node.__data__, i, group) + ""; + if (nodeByKeyValue.has(keyValue)) { + exit[i] = node; + } else { + nodeByKeyValue.set(keyValue, node); + } + } + } + + // Compute the key for each datum. + // If there a node associated with this key, join and add it to update. + // If there is not (or the key is a duplicate), add it to enter. + for (i = 0; i < dataLength; ++i) { + keyValue = key.call(parent, data[i], i, data) + ""; + if (node = nodeByKeyValue.get(keyValue)) { + update[i] = node; + node.__data__ = data[i]; + nodeByKeyValue.delete(keyValue); + } else { + enter[i] = new EnterNode(parent, data[i]); + } + } + + // Add any remaining nodes that were not bound to data to exit. + for (i = 0; i < groupLength; ++i) { + if ((node = group[i]) && (nodeByKeyValue.get(keyValues[i]) === node)) { + exit[i] = node; + } + } + } + + function datum(node) { + return node.__data__; + } + + function selection_data(value, key) { + if (!arguments.length) return Array.from(this, datum); + + var bind = key ? bindKey : bindIndex, + parents = this._parents, + groups = this._groups; + + if (typeof value !== "function") value = constant$4(value); + + for (var m = groups.length, update = new Array(m), enter = new Array(m), exit = new Array(m), j = 0; j < m; ++j) { + var parent = parents[j], + group = groups[j], + groupLength = group.length, + data = arraylike(value.call(parent, parent && parent.__data__, j, parents)), + dataLength = data.length, + enterGroup = enter[j] = new Array(dataLength), + updateGroup = update[j] = new Array(dataLength), + exitGroup = exit[j] = new Array(groupLength); + + bind(parent, group, enterGroup, updateGroup, exitGroup, data, key); + + // Now connect the enter nodes to their following update node, such that + // appendChild can insert the materialized enter node before this node, + // rather than at the end of the parent node. + for (var i0 = 0, i1 = 0, previous, next; i0 < dataLength; ++i0) { + if (previous = enterGroup[i0]) { + if (i0 >= i1) i1 = i0 + 1; + while (!(next = updateGroup[i1]) && ++i1 < dataLength); + previous._next = next || null; + } + } + } + + update = new Selection$1(update, parents); + update._enter = enter; + update._exit = exit; + return update; + } + + // Given some data, this returns an array-like view of it: an object that + // exposes a length property and allows numeric indexing. Note that unlike + // selectAll, this isn’t worried about “live” collections because the resulting + // array will only be used briefly while data is being bound. (It is possible to + // cause the data to change while iterating by using a key function, but please + // don’t; we’d rather avoid a gratuitous copy.) + function arraylike(data) { + return typeof data === "object" && "length" in data + ? data // Array, TypedArray, NodeList, array-like + : Array.from(data); // Map, Set, iterable, string, or anything else + } + + function selection_exit() { + return new Selection$1(this._exit || this._groups.map(sparse), this._parents); + } + + function selection_join(onenter, onupdate, onexit) { + var enter = this.enter(), update = this, exit = this.exit(); + if (typeof onenter === "function") { + enter = onenter(enter); + if (enter) enter = enter.selection(); + } else { + enter = enter.append(onenter + ""); + } + if (onupdate != null) { + update = onupdate(update); + if (update) update = update.selection(); + } + if (onexit == null) exit.remove(); else onexit(exit); + return enter && update ? enter.merge(update).order() : update; + } + + function selection_merge(context) { + var selection = context.selection ? context.selection() : context; + + for (var groups0 = this._groups, groups1 = selection._groups, m0 = groups0.length, m1 = groups1.length, m = Math.min(m0, m1), merges = new Array(m0), j = 0; j < m; ++j) { + for (var group0 = groups0[j], group1 = groups1[j], n = group0.length, merge = merges[j] = new Array(n), node, i = 0; i < n; ++i) { + if (node = group0[i] || group1[i]) { + merge[i] = node; + } + } + } + + for (; j < m0; ++j) { + merges[j] = groups0[j]; + } + + return new Selection$1(merges, this._parents); + } + + function selection_order() { + + for (var groups = this._groups, j = -1, m = groups.length; ++j < m;) { + for (var group = groups[j], i = group.length - 1, next = group[i], node; --i >= 0;) { + if (node = group[i]) { + if (next && node.compareDocumentPosition(next) ^ 4) next.parentNode.insertBefore(node, next); + next = node; + } + } + } + + return this; + } + + function selection_sort(compare) { + if (!compare) compare = ascending; + + function compareNode(a, b) { + return a && b ? compare(a.__data__, b.__data__) : !a - !b; + } + + for (var groups = this._groups, m = groups.length, sortgroups = new Array(m), j = 0; j < m; ++j) { + for (var group = groups[j], n = group.length, sortgroup = sortgroups[j] = new Array(n), node, i = 0; i < n; ++i) { + if (node = group[i]) { + sortgroup[i] = node; + } + } + sortgroup.sort(compareNode); + } + + return new Selection$1(sortgroups, this._parents).order(); + } + + function ascending(a, b) { + return a < b ? -1 : a > b ? 1 : a >= b ? 0 : NaN; + } + + function selection_call() { + var callback = arguments[0]; + arguments[0] = this; + callback.apply(null, arguments); + return this; + } + + function selection_nodes() { + return Array.from(this); + } + + function selection_node() { + + for (var groups = this._groups, j = 0, m = groups.length; j < m; ++j) { + for (var group = groups[j], i = 0, n = group.length; i < n; ++i) { + var node = group[i]; + if (node) return node; + } + } + + return null; + } + + function selection_size() { + let size = 0; + for (const node of this) ++size; // eslint-disable-line no-unused-vars + return size; + } + + function selection_empty() { + return !this.node(); + } + + function selection_each(callback) { + + for (var groups = this._groups, j = 0, m = groups.length; j < m; ++j) { + for (var group = groups[j], i = 0, n = group.length, node; i < n; ++i) { + if (node = group[i]) callback.call(node, node.__data__, i, group); + } + } + + return this; + } + + function attrRemove$1(name) { + return function() { + this.removeAttribute(name); + }; + } + + function attrRemoveNS$1(fullname) { + return function() { + this.removeAttributeNS(fullname.space, fullname.local); + }; + } + + function attrConstant$1(name, value) { + return function() { + this.setAttribute(name, value); + }; + } + + function attrConstantNS$1(fullname, value) { + return function() { + this.setAttributeNS(fullname.space, fullname.local, value); + }; + } + + function attrFunction$1(name, value) { + return function() { + var v = value.apply(this, arguments); + if (v == null) this.removeAttribute(name); + else this.setAttribute(name, v); + }; + } + + function attrFunctionNS$1(fullname, value) { + return function() { + var v = value.apply(this, arguments); + if (v == null) this.removeAttributeNS(fullname.space, fullname.local); + else this.setAttributeNS(fullname.space, fullname.local, v); + }; + } + + function selection_attr(name, value) { + var fullname = namespace(name); + + if (arguments.length < 2) { + var node = this.node(); + return fullname.local + ? node.getAttributeNS(fullname.space, fullname.local) + : node.getAttribute(fullname); + } + + return this.each((value == null + ? (fullname.local ? attrRemoveNS$1 : attrRemove$1) : (typeof value === "function" + ? (fullname.local ? attrFunctionNS$1 : attrFunction$1) + : (fullname.local ? attrConstantNS$1 : attrConstant$1)))(fullname, value)); + } + + function defaultView(node) { + return (node.ownerDocument && node.ownerDocument.defaultView) // node is a Node + || (node.document && node) // node is a Window + || node.defaultView; // node is a Document + } + + function styleRemove$1(name) { + return function() { + this.style.removeProperty(name); + }; + } + + function styleConstant$1(name, value, priority) { + return function() { + this.style.setProperty(name, value, priority); + }; + } + + function styleFunction$1(name, value, priority) { + return function() { + var v = value.apply(this, arguments); + if (v == null) this.style.removeProperty(name); + else this.style.setProperty(name, v, priority); + }; + } + + function selection_style(name, value, priority) { + return arguments.length > 1 + ? this.each((value == null + ? styleRemove$1 : typeof value === "function" + ? styleFunction$1 + : styleConstant$1)(name, value, priority == null ? "" : priority)) + : styleValue(this.node(), name); + } + + function styleValue(node, name) { + return node.style.getPropertyValue(name) + || defaultView(node).getComputedStyle(node, null).getPropertyValue(name); + } + + function propertyRemove(name) { + return function() { + delete this[name]; + }; + } + + function propertyConstant(name, value) { + return function() { + this[name] = value; + }; + } + + function propertyFunction(name, value) { + return function() { + var v = value.apply(this, arguments); + if (v == null) delete this[name]; + else this[name] = v; + }; + } + + function selection_property(name, value) { + return arguments.length > 1 + ? this.each((value == null + ? propertyRemove : typeof value === "function" + ? propertyFunction + : propertyConstant)(name, value)) + : this.node()[name]; + } + + function classArray(string) { + return string.trim().split(/^|\s+/); + } + + function classList(node) { + return node.classList || new ClassList(node); + } + + function ClassList(node) { + this._node = node; + this._names = classArray(node.getAttribute("class") || ""); + } + + ClassList.prototype = { + add: function(name) { + var i = this._names.indexOf(name); + if (i < 0) { + this._names.push(name); + this._node.setAttribute("class", this._names.join(" ")); + } + }, + remove: function(name) { + var i = this._names.indexOf(name); + if (i >= 0) { + this._names.splice(i, 1); + this._node.setAttribute("class", this._names.join(" ")); + } + }, + contains: function(name) { + return this._names.indexOf(name) >= 0; + } + }; + + function classedAdd(node, names) { + var list = classList(node), i = -1, n = names.length; + while (++i < n) list.add(names[i]); + } + + function classedRemove(node, names) { + var list = classList(node), i = -1, n = names.length; + while (++i < n) list.remove(names[i]); + } + + function classedTrue(names) { + return function() { + classedAdd(this, names); + }; + } + + function classedFalse(names) { + return function() { + classedRemove(this, names); + }; + } + + function classedFunction(names, value) { + return function() { + (value.apply(this, arguments) ? classedAdd : classedRemove)(this, names); + }; + } + + function selection_classed(name, value) { + var names = classArray(name + ""); + + if (arguments.length < 2) { + var list = classList(this.node()), i = -1, n = names.length; + while (++i < n) if (!list.contains(names[i])) return false; + return true; + } + + return this.each((typeof value === "function" + ? classedFunction : value + ? classedTrue + : classedFalse)(names, value)); + } + + function textRemove() { + this.textContent = ""; + } + + function textConstant$1(value) { + return function() { + this.textContent = value; + }; + } + + function textFunction$1(value) { + return function() { + var v = value.apply(this, arguments); + this.textContent = v == null ? "" : v; + }; + } + + function selection_text(value) { + return arguments.length + ? this.each(value == null + ? textRemove : (typeof value === "function" + ? textFunction$1 + : textConstant$1)(value)) + : this.node().textContent; + } + + function htmlRemove() { + this.innerHTML = ""; + } + + function htmlConstant(value) { + return function() { + this.innerHTML = value; + }; + } + + function htmlFunction(value) { + return function() { + var v = value.apply(this, arguments); + this.innerHTML = v == null ? "" : v; + }; + } + + function selection_html(value) { + return arguments.length + ? this.each(value == null + ? htmlRemove : (typeof value === "function" + ? htmlFunction + : htmlConstant)(value)) + : this.node().innerHTML; + } + + function raise() { + if (this.nextSibling) this.parentNode.appendChild(this); + } + + function selection_raise() { + return this.each(raise); + } + + function lower() { + if (this.previousSibling) this.parentNode.insertBefore(this, this.parentNode.firstChild); + } + + function selection_lower() { + return this.each(lower); + } + + function selection_append(name) { + var create = typeof name === "function" ? name : creator(name); + return this.select(function() { + return this.appendChild(create.apply(this, arguments)); + }); + } + + function constantNull() { + return null; + } + + function selection_insert(name, before) { + var create = typeof name === "function" ? name : creator(name), + select = before == null ? constantNull : typeof before === "function" ? before : selector(before); + return this.select(function() { + return this.insertBefore(create.apply(this, arguments), select.apply(this, arguments) || null); + }); + } + + function remove() { + var parent = this.parentNode; + if (parent) parent.removeChild(this); + } + + function selection_remove() { + return this.each(remove); + } + + function selection_cloneShallow() { + var clone = this.cloneNode(false), parent = this.parentNode; + return parent ? parent.insertBefore(clone, this.nextSibling) : clone; + } + + function selection_cloneDeep() { + var clone = this.cloneNode(true), parent = this.parentNode; + return parent ? parent.insertBefore(clone, this.nextSibling) : clone; + } + + function selection_clone(deep) { + return this.select(deep ? selection_cloneDeep : selection_cloneShallow); + } + + function selection_datum(value) { + return arguments.length + ? this.property("__data__", value) + : this.node().__data__; + } + + function contextListener(listener) { + return function(event) { + listener.call(this, event, this.__data__); + }; + } + + function parseTypenames$1(typenames) { + return typenames.trim().split(/^|\s+/).map(function(t) { + var name = "", i = t.indexOf("."); + if (i >= 0) name = t.slice(i + 1), t = t.slice(0, i); + return {type: t, name: name}; + }); + } + + function onRemove(typename) { + return function() { + var on = this.__on; + if (!on) return; + for (var j = 0, i = -1, m = on.length, o; j < m; ++j) { + if (o = on[j], (!typename.type || o.type === typename.type) && o.name === typename.name) { + this.removeEventListener(o.type, o.listener, o.options); + } else { + on[++i] = o; + } + } + if (++i) on.length = i; + else delete this.__on; + }; + } + + function onAdd(typename, value, options) { + return function() { + var on = this.__on, o, listener = contextListener(value); + if (on) for (var j = 0, m = on.length; j < m; ++j) { + if ((o = on[j]).type === typename.type && o.name === typename.name) { + this.removeEventListener(o.type, o.listener, o.options); + this.addEventListener(o.type, o.listener = listener, o.options = options); + o.value = value; + return; + } + } + this.addEventListener(typename.type, listener, options); + o = {type: typename.type, name: typename.name, value: value, listener: listener, options: options}; + if (!on) this.__on = [o]; + else on.push(o); + }; + } + + function selection_on(typename, value, options) { + var typenames = parseTypenames$1(typename + ""), i, n = typenames.length, t; + + if (arguments.length < 2) { + var on = this.node().__on; + if (on) for (var j = 0, m = on.length, o; j < m; ++j) { + for (i = 0, o = on[j]; i < n; ++i) { + if ((t = typenames[i]).type === o.type && t.name === o.name) { + return o.value; + } + } + } + return; + } + + on = value ? onAdd : onRemove; + for (i = 0; i < n; ++i) this.each(on(typenames[i], value, options)); + return this; + } + + function dispatchEvent(node, type, params) { + var window = defaultView(node), + event = window.CustomEvent; + + if (typeof event === "function") { + event = new event(type, params); + } else { + event = window.document.createEvent("Event"); + if (params) event.initEvent(type, params.bubbles, params.cancelable), event.detail = params.detail; + else event.initEvent(type, false, false); + } + + node.dispatchEvent(event); + } + + function dispatchConstant(type, params) { + return function() { + return dispatchEvent(this, type, params); + }; + } + + function dispatchFunction(type, params) { + return function() { + return dispatchEvent(this, type, params.apply(this, arguments)); + }; + } + + function selection_dispatch(type, params) { + return this.each((typeof params === "function" + ? dispatchFunction + : dispatchConstant)(type, params)); + } + + function* selection_iterator() { + for (var groups = this._groups, j = 0, m = groups.length; j < m; ++j) { + for (var group = groups[j], i = 0, n = group.length, node; i < n; ++i) { + if (node = group[i]) yield node; + } + } + } + + var root$2 = [null]; + + function Selection$1(groups, parents) { + this._groups = groups; + this._parents = parents; + } + + function selection() { + return new Selection$1([[document.documentElement]], root$2); + } + + function selection_selection() { + return this; + } + + Selection$1.prototype = selection.prototype = { + constructor: Selection$1, + select: selection_select, + selectAll: selection_selectAll, + selectChild: selection_selectChild, + selectChildren: selection_selectChildren, + filter: selection_filter, + data: selection_data, + enter: selection_enter, + exit: selection_exit, + join: selection_join, + merge: selection_merge, + selection: selection_selection, + order: selection_order, + sort: selection_sort, + call: selection_call, + nodes: selection_nodes, + node: selection_node, + size: selection_size, + empty: selection_empty, + each: selection_each, + attr: selection_attr, + style: selection_style, + property: selection_property, + classed: selection_classed, + text: selection_text, + html: selection_html, + raise: selection_raise, + lower: selection_lower, + append: selection_append, + insert: selection_insert, + remove: selection_remove, + clone: selection_clone, + datum: selection_datum, + on: selection_on, + dispatch: selection_dispatch, + [Symbol.iterator]: selection_iterator + }; + + function d3Select(selector) { + return typeof selector === "string" + ? new Selection$1([[document.querySelector(selector)]], [document.documentElement]) + : new Selection$1([[selector]], root$2); + } + + function sourceEvent(event) { + let sourceEvent; + while (sourceEvent = event.sourceEvent) event = sourceEvent; + return event; + } + + function pointer(event, node) { + event = sourceEvent(event); + if (node === undefined) node = event.currentTarget; + if (node) { + var svg = node.ownerSVGElement || node; + if (svg.createSVGPoint) { + var point = svg.createSVGPoint(); + point.x = event.clientX, point.y = event.clientY; + point = point.matrixTransform(node.getScreenCTM().inverse()); + return [point.x, point.y]; + } + if (node.getBoundingClientRect) { + var rect = node.getBoundingClientRect(); + return [event.clientX - rect.left - node.clientLeft, event.clientY - rect.top - node.clientTop]; + } + } + return [event.pageX, event.pageY]; + } + + var noop = {value: () => {}}; + + function dispatch() { + for (var i = 0, n = arguments.length, _ = {}, t; i < n; ++i) { + if (!(t = arguments[i] + "") || (t in _) || /[\s.]/.test(t)) throw new Error("illegal type: " + t); + _[t] = []; + } + return new Dispatch(_); + } + + function Dispatch(_) { + this._ = _; + } + + function parseTypenames(typenames, types) { + return typenames.trim().split(/^|\s+/).map(function(t) { + var name = "", i = t.indexOf("."); + if (i >= 0) name = t.slice(i + 1), t = t.slice(0, i); + if (t && !types.hasOwnProperty(t)) throw new Error("unknown type: " + t); + return {type: t, name: name}; + }); + } + + Dispatch.prototype = dispatch.prototype = { + constructor: Dispatch, + on: function(typename, callback) { + var _ = this._, + T = parseTypenames(typename + "", _), + t, + i = -1, + n = T.length; + + // If no callback was specified, return the callback of the given type and name. + if (arguments.length < 2) { + while (++i < n) if ((t = (typename = T[i]).type) && (t = get$1(_[t], typename.name))) return t; + return; + } + + // If a type was specified, set the callback for the given type and name. + // Otherwise, if a null callback was specified, remove callbacks of the given name. + if (callback != null && typeof callback !== "function") throw new Error("invalid callback: " + callback); + while (++i < n) { + if (t = (typename = T[i]).type) _[t] = set$1(_[t], typename.name, callback); + else if (callback == null) for (t in _) _[t] = set$1(_[t], typename.name, null); + } + + return this; + }, + copy: function() { + var copy = {}, _ = this._; + for (var t in _) copy[t] = _[t].slice(); + return new Dispatch(copy); + }, + call: function(type, that) { + if ((n = arguments.length - 2) > 0) for (var args = new Array(n), i = 0, n, t; i < n; ++i) args[i] = arguments[i + 2]; + if (!this._.hasOwnProperty(type)) throw new Error("unknown type: " + type); + for (t = this._[type], i = 0, n = t.length; i < n; ++i) t[i].value.apply(that, args); + }, + apply: function(type, that, args) { + if (!this._.hasOwnProperty(type)) throw new Error("unknown type: " + type); + for (var t = this._[type], i = 0, n = t.length; i < n; ++i) t[i].value.apply(that, args); + } + }; + + function get$1(type, name) { + for (var i = 0, n = type.length, c; i < n; ++i) { + if ((c = type[i]).name === name) { + return c.value; + } + } + } + + function set$1(type, name, callback) { + for (var i = 0, n = type.length; i < n; ++i) { + if (type[i].name === name) { + type[i] = noop, type = type.slice(0, i).concat(type.slice(i + 1)); + break; + } + } + if (callback != null) type.push({name: name, value: callback}); + return type; + } + + // These are typically used in conjunction with noevent to ensure that we can + // preventDefault on the event. + const nonpassive = {passive: false}; + const nonpassivecapture = {capture: true, passive: false}; + + function nopropagation$1(event) { + event.stopImmediatePropagation(); + } + + function noevent$1(event) { + event.preventDefault(); + event.stopImmediatePropagation(); + } + + function dragDisable(view) { + var root = view.document.documentElement, + selection = d3Select(view).on("dragstart.drag", noevent$1, nonpassivecapture); + if ("onselectstart" in root) { + selection.on("selectstart.drag", noevent$1, nonpassivecapture); + } else { + root.__noselect = root.style.MozUserSelect; + root.style.MozUserSelect = "none"; + } + } + + function yesdrag(view, noclick) { + var root = view.document.documentElement, + selection = d3Select(view).on("dragstart.drag", null); + if (noclick) { + selection.on("click.drag", noevent$1, nonpassivecapture); + setTimeout(function() { selection.on("click.drag", null); }, 0); + } + if ("onselectstart" in root) { + selection.on("selectstart.drag", null); + } else { + root.style.MozUserSelect = root.__noselect; + delete root.__noselect; + } + } + + var constant$3 = x => () => x; + + function DragEvent(type, { + sourceEvent, + subject, + target, + identifier, + active, + x, y, dx, dy, + dispatch + }) { + Object.defineProperties(this, { + type: {value: type, enumerable: true, configurable: true}, + sourceEvent: {value: sourceEvent, enumerable: true, configurable: true}, + subject: {value: subject, enumerable: true, configurable: true}, + target: {value: target, enumerable: true, configurable: true}, + identifier: {value: identifier, enumerable: true, configurable: true}, + active: {value: active, enumerable: true, configurable: true}, + x: {value: x, enumerable: true, configurable: true}, + y: {value: y, enumerable: true, configurable: true}, + dx: {value: dx, enumerable: true, configurable: true}, + dy: {value: dy, enumerable: true, configurable: true}, + _: {value: dispatch} + }); + } + + DragEvent.prototype.on = function() { + var value = this._.on.apply(this._, arguments); + return value === this._ ? this : value; + }; + + // Ignore right-click, since that should open the context menu. + function defaultFilter$1(event) { + return !event.ctrlKey && !event.button; + } + + function defaultContainer() { + return this.parentNode; + } + + function defaultSubject(event, d) { + return d == null ? {x: event.x, y: event.y} : d; + } + + function defaultTouchable$1() { + return navigator.maxTouchPoints || ("ontouchstart" in this); + } + + function d3Drag() { + var filter = defaultFilter$1, + container = defaultContainer, + subject = defaultSubject, + touchable = defaultTouchable$1, + gestures = {}, + listeners = dispatch("start", "drag", "end"), + active = 0, + mousedownx, + mousedowny, + mousemoving, + touchending, + clickDistance2 = 0; + + function drag(selection) { + selection + .on("mousedown.drag", mousedowned) + .filter(touchable) + .on("touchstart.drag", touchstarted) + .on("touchmove.drag", touchmoved, nonpassive) + .on("touchend.drag touchcancel.drag", touchended) + .style("touch-action", "none") + .style("-webkit-tap-highlight-color", "rgba(0,0,0,0)"); + } + + function mousedowned(event, d) { + if (touchending || !filter.call(this, event, d)) return; + var gesture = beforestart(this, container.call(this, event, d), event, d, "mouse"); + if (!gesture) return; + d3Select(event.view) + .on("mousemove.drag", mousemoved, nonpassivecapture) + .on("mouseup.drag", mouseupped, nonpassivecapture); + dragDisable(event.view); + nopropagation$1(event); + mousemoving = false; + mousedownx = event.clientX; + mousedowny = event.clientY; + gesture("start", event); + } + + function mousemoved(event) { + noevent$1(event); + if (!mousemoving) { + var dx = event.clientX - mousedownx, dy = event.clientY - mousedowny; + mousemoving = dx * dx + dy * dy > clickDistance2; + } + gestures.mouse("drag", event); + } + + function mouseupped(event) { + d3Select(event.view).on("mousemove.drag mouseup.drag", null); + yesdrag(event.view, mousemoving); + noevent$1(event); + gestures.mouse("end", event); + } + + function touchstarted(event, d) { + if (!filter.call(this, event, d)) return; + var touches = event.changedTouches, + c = container.call(this, event, d), + n = touches.length, i, gesture; + + for (i = 0; i < n; ++i) { + if (gesture = beforestart(this, c, event, d, touches[i].identifier, touches[i])) { + nopropagation$1(event); + gesture("start", event, touches[i]); + } + } + } + + function touchmoved(event) { + var touches = event.changedTouches, + n = touches.length, i, gesture; + + for (i = 0; i < n; ++i) { + if (gesture = gestures[touches[i].identifier]) { + noevent$1(event); + gesture("drag", event, touches[i]); + } + } + } + + function touchended(event) { + var touches = event.changedTouches, + n = touches.length, i, gesture; + + if (touchending) clearTimeout(touchending); + touchending = setTimeout(function() { touchending = null; }, 500); // Ghost clicks are delayed! + for (i = 0; i < n; ++i) { + if (gesture = gestures[touches[i].identifier]) { + nopropagation$1(event); + gesture("end", event, touches[i]); + } + } + } + + function beforestart(that, container, event, d, identifier, touch) { + var dispatch = listeners.copy(), + p = pointer(touch || event, container), dx, dy, + s; + + if ((s = subject.call(that, new DragEvent("beforestart", { + sourceEvent: event, + target: drag, + identifier, + active, + x: p[0], + y: p[1], + dx: 0, + dy: 0, + dispatch + }), d)) == null) return; + + dx = s.x - p[0] || 0; + dy = s.y - p[1] || 0; + + return function gesture(type, event, touch) { + var p0 = p, n; + switch (type) { + case "start": gestures[identifier] = gesture, n = active++; break; + case "end": delete gestures[identifier], --active; // falls through + case "drag": p = pointer(touch || event, container), n = active; break; + } + dispatch.call( + type, + that, + new DragEvent(type, { + sourceEvent: event, + subject: s, + target: drag, + identifier, + active: n, + x: p[0] + dx, + y: p[1] + dy, + dx: p[0] - p0[0], + dy: p[1] - p0[1], + dispatch + }), + d + ); + }; + } + + drag.filter = function(_) { + return arguments.length ? (filter = typeof _ === "function" ? _ : constant$3(!!_), drag) : filter; + }; + + drag.container = function(_) { + return arguments.length ? (container = typeof _ === "function" ? _ : constant$3(_), drag) : container; + }; + + drag.subject = function(_) { + return arguments.length ? (subject = typeof _ === "function" ? _ : constant$3(_), drag) : subject; + }; + + drag.touchable = function(_) { + return arguments.length ? (touchable = typeof _ === "function" ? _ : constant$3(!!_), drag) : touchable; + }; + + drag.on = function() { + var value = listeners.on.apply(listeners, arguments); + return value === listeners ? drag : value; + }; + + drag.clickDistance = function(_) { + return arguments.length ? (clickDistance2 = (_ = +_) * _, drag) : Math.sqrt(clickDistance2); + }; + + return drag; + } + + function define(constructor, factory, prototype) { + constructor.prototype = factory.prototype = prototype; + prototype.constructor = constructor; + } + + function extend(parent, definition) { + var prototype = Object.create(parent.prototype); + for (var key in definition) prototype[key] = definition[key]; + return prototype; + } + + function Color() {} + + var darker = 0.7; + var brighter = 1 / darker; + + var reI = "\\s*([+-]?\\d+)\\s*", + reN = "\\s*([+-]?(?:\\d*\\.)?\\d+(?:[eE][+-]?\\d+)?)\\s*", + reP = "\\s*([+-]?(?:\\d*\\.)?\\d+(?:[eE][+-]?\\d+)?)%\\s*", + reHex = /^#([0-9a-f]{3,8})$/, + reRgbInteger = new RegExp(`^rgb\\(${reI},${reI},${reI}\\)$`), + reRgbPercent = new RegExp(`^rgb\\(${reP},${reP},${reP}\\)$`), + reRgbaInteger = new RegExp(`^rgba\\(${reI},${reI},${reI},${reN}\\)$`), + reRgbaPercent = new RegExp(`^rgba\\(${reP},${reP},${reP},${reN}\\)$`), + reHslPercent = new RegExp(`^hsl\\(${reN},${reP},${reP}\\)$`), + reHslaPercent = new RegExp(`^hsla\\(${reN},${reP},${reP},${reN}\\)$`); + + var named = { + aliceblue: 0xf0f8ff, + antiquewhite: 0xfaebd7, + aqua: 0x00ffff, + aquamarine: 0x7fffd4, + azure: 0xf0ffff, + beige: 0xf5f5dc, + bisque: 0xffe4c4, + black: 0x000000, + blanchedalmond: 0xffebcd, + blue: 0x0000ff, + blueviolet: 0x8a2be2, + brown: 0xa52a2a, + burlywood: 0xdeb887, + cadetblue: 0x5f9ea0, + chartreuse: 0x7fff00, + chocolate: 0xd2691e, + coral: 0xff7f50, + cornflowerblue: 0x6495ed, + cornsilk: 0xfff8dc, + crimson: 0xdc143c, + cyan: 0x00ffff, + darkblue: 0x00008b, + darkcyan: 0x008b8b, + darkgoldenrod: 0xb8860b, + darkgray: 0xa9a9a9, + darkgreen: 0x006400, + darkgrey: 0xa9a9a9, + darkkhaki: 0xbdb76b, + darkmagenta: 0x8b008b, + darkolivegreen: 0x556b2f, + darkorange: 0xff8c00, + darkorchid: 0x9932cc, + darkred: 0x8b0000, + darksalmon: 0xe9967a, + darkseagreen: 0x8fbc8f, + darkslateblue: 0x483d8b, + darkslategray: 0x2f4f4f, + darkslategrey: 0x2f4f4f, + darkturquoise: 0x00ced1, + darkviolet: 0x9400d3, + deeppink: 0xff1493, + deepskyblue: 0x00bfff, + dimgray: 0x696969, + dimgrey: 0x696969, + dodgerblue: 0x1e90ff, + firebrick: 0xb22222, + floralwhite: 0xfffaf0, + forestgreen: 0x228b22, + fuchsia: 0xff00ff, + gainsboro: 0xdcdcdc, + ghostwhite: 0xf8f8ff, + gold: 0xffd700, + goldenrod: 0xdaa520, + gray: 0x808080, + green: 0x008000, + greenyellow: 0xadff2f, + grey: 0x808080, + honeydew: 0xf0fff0, + hotpink: 0xff69b4, + indianred: 0xcd5c5c, + indigo: 0x4b0082, + ivory: 0xfffff0, + khaki: 0xf0e68c, + lavender: 0xe6e6fa, + lavenderblush: 0xfff0f5, + lawngreen: 0x7cfc00, + lemonchiffon: 0xfffacd, + lightblue: 0xadd8e6, + lightcoral: 0xf08080, + lightcyan: 0xe0ffff, + lightgoldenrodyellow: 0xfafad2, + lightgray: 0xd3d3d3, + lightgreen: 0x90ee90, + lightgrey: 0xd3d3d3, + lightpink: 0xffb6c1, + lightsalmon: 0xffa07a, + lightseagreen: 0x20b2aa, + lightskyblue: 0x87cefa, + lightslategray: 0x778899, + lightslategrey: 0x778899, + lightsteelblue: 0xb0c4de, + lightyellow: 0xffffe0, + lime: 0x00ff00, + limegreen: 0x32cd32, + linen: 0xfaf0e6, + magenta: 0xff00ff, + maroon: 0x800000, + mediumaquamarine: 0x66cdaa, + mediumblue: 0x0000cd, + mediumorchid: 0xba55d3, + mediumpurple: 0x9370db, + mediumseagreen: 0x3cb371, + mediumslateblue: 0x7b68ee, + mediumspringgreen: 0x00fa9a, + mediumturquoise: 0x48d1cc, + mediumvioletred: 0xc71585, + midnightblue: 0x191970, + mintcream: 0xf5fffa, + mistyrose: 0xffe4e1, + moccasin: 0xffe4b5, + navajowhite: 0xffdead, + navy: 0x000080, + oldlace: 0xfdf5e6, + olive: 0x808000, + olivedrab: 0x6b8e23, + orange: 0xffa500, + orangered: 0xff4500, + orchid: 0xda70d6, + palegoldenrod: 0xeee8aa, + palegreen: 0x98fb98, + paleturquoise: 0xafeeee, + palevioletred: 0xdb7093, + papayawhip: 0xffefd5, + peachpuff: 0xffdab9, + peru: 0xcd853f, + pink: 0xffc0cb, + plum: 0xdda0dd, + powderblue: 0xb0e0e6, + purple: 0x800080, + rebeccapurple: 0x663399, + red: 0xff0000, + rosybrown: 0xbc8f8f, + royalblue: 0x4169e1, + saddlebrown: 0x8b4513, + salmon: 0xfa8072, + sandybrown: 0xf4a460, + seagreen: 0x2e8b57, + seashell: 0xfff5ee, + sienna: 0xa0522d, + silver: 0xc0c0c0, + skyblue: 0x87ceeb, + slateblue: 0x6a5acd, + slategray: 0x708090, + slategrey: 0x708090, + snow: 0xfffafa, + springgreen: 0x00ff7f, + steelblue: 0x4682b4, + tan: 0xd2b48c, + teal: 0x008080, + thistle: 0xd8bfd8, + tomato: 0xff6347, + turquoise: 0x40e0d0, + violet: 0xee82ee, + wheat: 0xf5deb3, + white: 0xffffff, + whitesmoke: 0xf5f5f5, + yellow: 0xffff00, + yellowgreen: 0x9acd32 + }; + + define(Color, color, { + copy(channels) { + return Object.assign(new this.constructor, this, channels); + }, + displayable() { + return this.rgb().displayable(); + }, + hex: color_formatHex, // Deprecated! Use color.formatHex. + formatHex: color_formatHex, + formatHex8: color_formatHex8, + formatHsl: color_formatHsl, + formatRgb: color_formatRgb, + toString: color_formatRgb + }); + + function color_formatHex() { + return this.rgb().formatHex(); + } + + function color_formatHex8() { + return this.rgb().formatHex8(); + } + + function color_formatHsl() { + return hslConvert(this).formatHsl(); + } + + function color_formatRgb() { + return this.rgb().formatRgb(); + } + + function color(format) { + var m, l; + format = (format + "").trim().toLowerCase(); + return (m = reHex.exec(format)) ? (l = m[1].length, m = parseInt(m[1], 16), l === 6 ? rgbn(m) // #ff0000 + : l === 3 ? new Rgb((m >> 8 & 0xf) | (m >> 4 & 0xf0), (m >> 4 & 0xf) | (m & 0xf0), ((m & 0xf) << 4) | (m & 0xf), 1) // #f00 + : l === 8 ? rgba(m >> 24 & 0xff, m >> 16 & 0xff, m >> 8 & 0xff, (m & 0xff) / 0xff) // #ff000000 + : l === 4 ? rgba((m >> 12 & 0xf) | (m >> 8 & 0xf0), (m >> 8 & 0xf) | (m >> 4 & 0xf0), (m >> 4 & 0xf) | (m & 0xf0), (((m & 0xf) << 4) | (m & 0xf)) / 0xff) // #f000 + : null) // invalid hex + : (m = reRgbInteger.exec(format)) ? new Rgb(m[1], m[2], m[3], 1) // rgb(255, 0, 0) + : (m = reRgbPercent.exec(format)) ? new Rgb(m[1] * 255 / 100, m[2] * 255 / 100, m[3] * 255 / 100, 1) // rgb(100%, 0%, 0%) + : (m = reRgbaInteger.exec(format)) ? rgba(m[1], m[2], m[3], m[4]) // rgba(255, 0, 0, 1) + : (m = reRgbaPercent.exec(format)) ? rgba(m[1] * 255 / 100, m[2] * 255 / 100, m[3] * 255 / 100, m[4]) // rgb(100%, 0%, 0%, 1) + : (m = reHslPercent.exec(format)) ? hsla(m[1], m[2] / 100, m[3] / 100, 1) // hsl(120, 50%, 50%) + : (m = reHslaPercent.exec(format)) ? hsla(m[1], m[2] / 100, m[3] / 100, m[4]) // hsla(120, 50%, 50%, 1) + : named.hasOwnProperty(format) ? rgbn(named[format]) // eslint-disable-line no-prototype-builtins + : format === "transparent" ? new Rgb(NaN, NaN, NaN, 0) + : null; + } + + function rgbn(n) { + return new Rgb(n >> 16 & 0xff, n >> 8 & 0xff, n & 0xff, 1); + } + + function rgba(r, g, b, a) { + if (a <= 0) r = g = b = NaN; + return new Rgb(r, g, b, a); + } + + function rgbConvert(o) { + if (!(o instanceof Color)) o = color(o); + if (!o) return new Rgb; + o = o.rgb(); + return new Rgb(o.r, o.g, o.b, o.opacity); + } + + function rgb(r, g, b, opacity) { + return arguments.length === 1 ? rgbConvert(r) : new Rgb(r, g, b, opacity == null ? 1 : opacity); + } + + function Rgb(r, g, b, opacity) { + this.r = +r; + this.g = +g; + this.b = +b; + this.opacity = +opacity; + } + + define(Rgb, rgb, extend(Color, { + brighter(k) { + k = k == null ? brighter : Math.pow(brighter, k); + return new Rgb(this.r * k, this.g * k, this.b * k, this.opacity); + }, + darker(k) { + k = k == null ? darker : Math.pow(darker, k); + return new Rgb(this.r * k, this.g * k, this.b * k, this.opacity); + }, + rgb() { + return this; + }, + clamp() { + return new Rgb(clampi(this.r), clampi(this.g), clampi(this.b), clampa(this.opacity)); + }, + displayable() { + return (-0.5 <= this.r && this.r < 255.5) + && (-0.5 <= this.g && this.g < 255.5) + && (-0.5 <= this.b && this.b < 255.5) + && (0 <= this.opacity && this.opacity <= 1); + }, + hex: rgb_formatHex, // Deprecated! Use color.formatHex. + formatHex: rgb_formatHex, + formatHex8: rgb_formatHex8, + formatRgb: rgb_formatRgb, + toString: rgb_formatRgb + })); + + function rgb_formatHex() { + return `#${hex(this.r)}${hex(this.g)}${hex(this.b)}`; + } + + function rgb_formatHex8() { + return `#${hex(this.r)}${hex(this.g)}${hex(this.b)}${hex((isNaN(this.opacity) ? 1 : this.opacity) * 255)}`; + } + + function rgb_formatRgb() { + const a = clampa(this.opacity); + return `${a === 1 ? "rgb(" : "rgba("}${clampi(this.r)}, ${clampi(this.g)}, ${clampi(this.b)}${a === 1 ? ")" : `, ${a})`}`; + } + + function clampa(opacity) { + return isNaN(opacity) ? 1 : Math.max(0, Math.min(1, opacity)); + } + + function clampi(value) { + return Math.max(0, Math.min(255, Math.round(value) || 0)); + } + + function hex(value) { + value = clampi(value); + return (value < 16 ? "0" : "") + value.toString(16); + } + + function hsla(h, s, l, a) { + if (a <= 0) h = s = l = NaN; + else if (l <= 0 || l >= 1) h = s = NaN; + else if (s <= 0) h = NaN; + return new Hsl(h, s, l, a); + } + + function hslConvert(o) { + if (o instanceof Hsl) return new Hsl(o.h, o.s, o.l, o.opacity); + if (!(o instanceof Color)) o = color(o); + if (!o) return new Hsl; + if (o instanceof Hsl) return o; + o = o.rgb(); + var r = o.r / 255, + g = o.g / 255, + b = o.b / 255, + min = Math.min(r, g, b), + max = Math.max(r, g, b), + h = NaN, + s = max - min, + l = (max + min) / 2; + if (s) { + if (r === max) h = (g - b) / s + (g < b) * 6; + else if (g === max) h = (b - r) / s + 2; + else h = (r - g) / s + 4; + s /= l < 0.5 ? max + min : 2 - max - min; + h *= 60; + } else { + s = l > 0 && l < 1 ? 0 : h; + } + return new Hsl(h, s, l, o.opacity); + } + + function hsl(h, s, l, opacity) { + return arguments.length === 1 ? hslConvert(h) : new Hsl(h, s, l, opacity == null ? 1 : opacity); + } + + function Hsl(h, s, l, opacity) { + this.h = +h; + this.s = +s; + this.l = +l; + this.opacity = +opacity; + } + + define(Hsl, hsl, extend(Color, { + brighter(k) { + k = k == null ? brighter : Math.pow(brighter, k); + return new Hsl(this.h, this.s, this.l * k, this.opacity); + }, + darker(k) { + k = k == null ? darker : Math.pow(darker, k); + return new Hsl(this.h, this.s, this.l * k, this.opacity); + }, + rgb() { + var h = this.h % 360 + (this.h < 0) * 360, + s = isNaN(h) || isNaN(this.s) ? 0 : this.s, + l = this.l, + m2 = l + (l < 0.5 ? l : 1 - l) * s, + m1 = 2 * l - m2; + return new Rgb( + hsl2rgb(h >= 240 ? h - 240 : h + 120, m1, m2), + hsl2rgb(h, m1, m2), + hsl2rgb(h < 120 ? h + 240 : h - 120, m1, m2), + this.opacity + ); + }, + clamp() { + return new Hsl(clamph(this.h), clampt(this.s), clampt(this.l), clampa(this.opacity)); + }, + displayable() { + return (0 <= this.s && this.s <= 1 || isNaN(this.s)) + && (0 <= this.l && this.l <= 1) + && (0 <= this.opacity && this.opacity <= 1); + }, + formatHsl() { + const a = clampa(this.opacity); + return `${a === 1 ? "hsl(" : "hsla("}${clamph(this.h)}, ${clampt(this.s) * 100}%, ${clampt(this.l) * 100}%${a === 1 ? ")" : `, ${a})`}`; + } + })); + + function clamph(value) { + value = (value || 0) % 360; + return value < 0 ? value + 360 : value; + } + + function clampt(value) { + return Math.max(0, Math.min(1, value || 0)); + } + + /* From FvD 13.37, CSS Color Module Level 3 */ + function hsl2rgb(h, m1, m2) { + return (h < 60 ? m1 + (m2 - m1) * h / 60 + : h < 180 ? m2 + : h < 240 ? m1 + (m2 - m1) * (240 - h) / 60 + : m1) * 255; + } + + var constant$2 = x => () => x; + + function linear(a, d) { + return function(t) { + return a + t * d; + }; + } + + function exponential(a, b, y) { + return a = Math.pow(a, y), b = Math.pow(b, y) - a, y = 1 / y, function(t) { + return Math.pow(a + t * b, y); + }; + } + + function gamma(y) { + return (y = +y) === 1 ? nogamma : function(a, b) { + return b - a ? exponential(a, b, y) : constant$2(isNaN(a) ? b : a); + }; + } + + function nogamma(a, b) { + var d = b - a; + return d ? linear(a, d) : constant$2(isNaN(a) ? b : a); + } + + var interpolateRgb = (function rgbGamma(y) { + var color = gamma(y); + + function rgb$1(start, end) { + var r = color((start = rgb(start)).r, (end = rgb(end)).r), + g = color(start.g, end.g), + b = color(start.b, end.b), + opacity = nogamma(start.opacity, end.opacity); + return function(t) { + start.r = r(t); + start.g = g(t); + start.b = b(t); + start.opacity = opacity(t); + return start + ""; + }; + } + + rgb$1.gamma = rgbGamma; + + return rgb$1; + })(1); + + function interpolateNumber(a, b) { + return a = +a, b = +b, function(t) { + return a * (1 - t) + b * t; + }; + } + + var reA = /[-+]?(?:\d+\.?\d*|\.?\d+)(?:[eE][-+]?\d+)?/g, + reB = new RegExp(reA.source, "g"); + + function zero(b) { + return function() { + return b; + }; + } + + function one(b) { + return function(t) { + return b(t) + ""; + }; + } + + function interpolateString(a, b) { + var bi = reA.lastIndex = reB.lastIndex = 0, // scan index for next number in b + am, // current match in a + bm, // current match in b + bs, // string preceding current number in b, if any + i = -1, // index in s + s = [], // string constants and placeholders + q = []; // number interpolators + + // Coerce inputs to strings. + a = a + "", b = b + ""; + + // Interpolate pairs of numbers in a & b. + while ((am = reA.exec(a)) + && (bm = reB.exec(b))) { + if ((bs = bm.index) > bi) { // a string precedes the next number in b + bs = b.slice(bi, bs); + if (s[i]) s[i] += bs; // coalesce with previous string + else s[++i] = bs; + } + if ((am = am[0]) === (bm = bm[0])) { // numbers in a & b match + if (s[i]) s[i] += bm; // coalesce with previous string + else s[++i] = bm; + } else { // interpolate non-matching numbers + s[++i] = null; + q.push({i: i, x: interpolateNumber(am, bm)}); + } + bi = reB.lastIndex; + } + + // Add remains of b. + if (bi < b.length) { + bs = b.slice(bi); + if (s[i]) s[i] += bs; // coalesce with previous string + else s[++i] = bs; + } + + // Special optimization for only a single match. + // Otherwise, interpolate each of the numbers and rejoin the string. + return s.length < 2 ? (q[0] + ? one(q[0].x) + : zero(b)) + : (b = q.length, function(t) { + for (var i = 0, o; i < b; ++i) s[(o = q[i]).i] = o.x(t); + return s.join(""); + }); + } + + var degrees = 180 / Math.PI; + + var identity$1 = { + translateX: 0, + translateY: 0, + rotate: 0, + skewX: 0, + scaleX: 1, + scaleY: 1 + }; + + function decompose(a, b, c, d, e, f) { + var scaleX, scaleY, skewX; + if (scaleX = Math.sqrt(a * a + b * b)) a /= scaleX, b /= scaleX; + if (skewX = a * c + b * d) c -= a * skewX, d -= b * skewX; + if (scaleY = Math.sqrt(c * c + d * d)) c /= scaleY, d /= scaleY, skewX /= scaleY; + if (a * d < b * c) a = -a, b = -b, skewX = -skewX, scaleX = -scaleX; + return { + translateX: e, + translateY: f, + rotate: Math.atan2(b, a) * degrees, + skewX: Math.atan(skewX) * degrees, + scaleX: scaleX, + scaleY: scaleY + }; + } + + var svgNode; + + /* eslint-disable no-undef */ + function parseCss(value) { + const m = new (typeof DOMMatrix === "function" ? DOMMatrix : WebKitCSSMatrix)(value + ""); + return m.isIdentity ? identity$1 : decompose(m.a, m.b, m.c, m.d, m.e, m.f); + } + + function parseSvg(value) { + if (value == null) return identity$1; + if (!svgNode) svgNode = document.createElementNS("http://www.w3.org/2000/svg", "g"); + svgNode.setAttribute("transform", value); + if (!(value = svgNode.transform.baseVal.consolidate())) return identity$1; + value = value.matrix; + return decompose(value.a, value.b, value.c, value.d, value.e, value.f); + } + + function interpolateTransform(parse, pxComma, pxParen, degParen) { + + function pop(s) { + return s.length ? s.pop() + " " : ""; + } + + function translate(xa, ya, xb, yb, s, q) { + if (xa !== xb || ya !== yb) { + var i = s.push("translate(", null, pxComma, null, pxParen); + q.push({i: i - 4, x: interpolateNumber(xa, xb)}, {i: i - 2, x: interpolateNumber(ya, yb)}); + } else if (xb || yb) { + s.push("translate(" + xb + pxComma + yb + pxParen); + } + } + + function rotate(a, b, s, q) { + if (a !== b) { + if (a - b > 180) b += 360; else if (b - a > 180) a += 360; // shortest path + q.push({i: s.push(pop(s) + "rotate(", null, degParen) - 2, x: interpolateNumber(a, b)}); + } else if (b) { + s.push(pop(s) + "rotate(" + b + degParen); + } + } + + function skewX(a, b, s, q) { + if (a !== b) { + q.push({i: s.push(pop(s) + "skewX(", null, degParen) - 2, x: interpolateNumber(a, b)}); + } else if (b) { + s.push(pop(s) + "skewX(" + b + degParen); + } + } + + function scale(xa, ya, xb, yb, s, q) { + if (xa !== xb || ya !== yb) { + var i = s.push(pop(s) + "scale(", null, ",", null, ")"); + q.push({i: i - 4, x: interpolateNumber(xa, xb)}, {i: i - 2, x: interpolateNumber(ya, yb)}); + } else if (xb !== 1 || yb !== 1) { + s.push(pop(s) + "scale(" + xb + "," + yb + ")"); + } + } + + return function(a, b) { + var s = [], // string constants and placeholders + q = []; // number interpolators + a = parse(a), b = parse(b); + translate(a.translateX, a.translateY, b.translateX, b.translateY, s, q); + rotate(a.rotate, b.rotate, s, q); + skewX(a.skewX, b.skewX, s, q); + scale(a.scaleX, a.scaleY, b.scaleX, b.scaleY, s, q); + a = b = null; // gc + return function(t) { + var i = -1, n = q.length, o; + while (++i < n) s[(o = q[i]).i] = o.x(t); + return s.join(""); + }; + }; + } + + var interpolateTransformCss = interpolateTransform(parseCss, "px, ", "px)", "deg)"); + var interpolateTransformSvg = interpolateTransform(parseSvg, ", ", ")", ")"); + + var epsilon2 = 1e-12; + + function cosh(x) { + return ((x = Math.exp(x)) + 1 / x) / 2; + } + + function sinh(x) { + return ((x = Math.exp(x)) - 1 / x) / 2; + } + + function tanh(x) { + return ((x = Math.exp(2 * x)) - 1) / (x + 1); + } + + var interpolateZoom = (function zoomRho(rho, rho2, rho4) { + + // p0 = [ux0, uy0, w0] + // p1 = [ux1, uy1, w1] + function zoom(p0, p1) { + var ux0 = p0[0], uy0 = p0[1], w0 = p0[2], + ux1 = p1[0], uy1 = p1[1], w1 = p1[2], + dx = ux1 - ux0, + dy = uy1 - uy0, + d2 = dx * dx + dy * dy, + i, + S; + + // Special case for u0 ≅ u1. + if (d2 < epsilon2) { + S = Math.log(w1 / w0) / rho; + i = function(t) { + return [ + ux0 + t * dx, + uy0 + t * dy, + w0 * Math.exp(rho * t * S) + ]; + }; + } + + // General case. + else { + var d1 = Math.sqrt(d2), + b0 = (w1 * w1 - w0 * w0 + rho4 * d2) / (2 * w0 * rho2 * d1), + b1 = (w1 * w1 - w0 * w0 - rho4 * d2) / (2 * w1 * rho2 * d1), + r0 = Math.log(Math.sqrt(b0 * b0 + 1) - b0), + r1 = Math.log(Math.sqrt(b1 * b1 + 1) - b1); + S = (r1 - r0) / rho; + i = function(t) { + var s = t * S, + coshr0 = cosh(r0), + u = w0 / (rho2 * d1) * (coshr0 * tanh(rho * s + r0) - sinh(r0)); + return [ + ux0 + u * dx, + uy0 + u * dy, + w0 * coshr0 / cosh(rho * s + r0) + ]; + }; + } + + i.duration = S * 1000 * rho / Math.SQRT2; + + return i; + } + + zoom.rho = function(_) { + var _1 = Math.max(1e-3, +_), _2 = _1 * _1, _4 = _2 * _2; + return zoomRho(_1, _2, _4); + }; + + return zoom; + })(Math.SQRT2, 2, 4); + + var frame = 0, // is an animation frame pending? + timeout$1 = 0, // is a timeout pending? + interval = 0, // are any timers active? + pokeDelay = 1000, // how frequently we check for clock skew + taskHead, + taskTail, + clockLast = 0, + clockNow = 0, + clockSkew = 0, + clock = typeof performance === "object" && performance.now ? performance : Date, + setFrame = typeof window === "object" && window.requestAnimationFrame ? window.requestAnimationFrame.bind(window) : function(f) { setTimeout(f, 17); }; + + function now$3() { + return clockNow || (setFrame(clearNow), clockNow = clock.now() + clockSkew); + } + + function clearNow() { + clockNow = 0; + } + + function Timer() { + this._call = + this._time = + this._next = null; + } + + Timer.prototype = timer.prototype = { + constructor: Timer, + restart: function(callback, delay, time) { + if (typeof callback !== "function") throw new TypeError("callback is not a function"); + time = (time == null ? now$3() : +time) + (delay == null ? 0 : +delay); + if (!this._next && taskTail !== this) { + if (taskTail) taskTail._next = this; + else taskHead = this; + taskTail = this; + } + this._call = callback; + this._time = time; + sleep(); + }, + stop: function() { + if (this._call) { + this._call = null; + this._time = Infinity; + sleep(); + } + } + }; + + function timer(callback, delay, time) { + var t = new Timer; + t.restart(callback, delay, time); + return t; + } + + function timerFlush() { + now$3(); // Get the current time, if not already set. + ++frame; // Pretend we’ve set an alarm, if we haven’t already. + var t = taskHead, e; + while (t) { + if ((e = clockNow - t._time) >= 0) t._call.call(undefined, e); + t = t._next; + } + --frame; + } + + function wake() { + clockNow = (clockLast = clock.now()) + clockSkew; + frame = timeout$1 = 0; + try { + timerFlush(); + } finally { + frame = 0; + nap(); + clockNow = 0; + } + } + + function poke() { + var now = clock.now(), delay = now - clockLast; + if (delay > pokeDelay) clockSkew -= delay, clockLast = now; + } + + function nap() { + var t0, t1 = taskHead, t2, time = Infinity; + while (t1) { + if (t1._call) { + if (time > t1._time) time = t1._time; + t0 = t1, t1 = t1._next; + } else { + t2 = t1._next, t1._next = null; + t1 = t0 ? t0._next = t2 : taskHead = t2; + } + } + taskTail = t0; + sleep(time); + } + + function sleep(time) { + if (frame) return; // Soonest alarm already set, or will be. + if (timeout$1) timeout$1 = clearTimeout(timeout$1); + var delay = time - clockNow; // Strictly less than if we recomputed clockNow. + if (delay > 24) { + if (time < Infinity) timeout$1 = setTimeout(wake, time - clock.now() - clockSkew); + if (interval) interval = clearInterval(interval); + } else { + if (!interval) clockLast = clock.now(), interval = setInterval(poke, pokeDelay); + frame = 1, setFrame(wake); + } + } + + function timeout(callback, delay, time) { + var t = new Timer; + delay = delay == null ? 0 : +delay; + t.restart(elapsed => { + t.stop(); + callback(elapsed + delay); + }, delay, time); + return t; + } + + var emptyOn = dispatch("start", "end", "cancel", "interrupt"); + var emptyTween = []; + + var CREATED = 0; + var SCHEDULED = 1; + var STARTING = 2; + var STARTED = 3; + var RUNNING = 4; + var ENDING = 5; + var ENDED = 6; + + function schedule(node, name, id, index, group, timing) { + var schedules = node.__transition; + if (!schedules) node.__transition = {}; + else if (id in schedules) return; + create(node, id, { + name: name, + index: index, // For context during callback. + group: group, // For context during callback. + on: emptyOn, + tween: emptyTween, + time: timing.time, + delay: timing.delay, + duration: timing.duration, + ease: timing.ease, + timer: null, + state: CREATED + }); + } + + function init(node, id) { + var schedule = get(node, id); + if (schedule.state > CREATED) throw new Error("too late; already scheduled"); + return schedule; + } + + function set(node, id) { + var schedule = get(node, id); + if (schedule.state > STARTED) throw new Error("too late; already running"); + return schedule; + } + + function get(node, id) { + var schedule = node.__transition; + if (!schedule || !(schedule = schedule[id])) throw new Error("transition not found"); + return schedule; + } + + function create(node, id, self) { + var schedules = node.__transition, + tween; + + // Initialize the self timer when the transition is created. + // Note the actual delay is not known until the first callback! + schedules[id] = self; + self.timer = timer(schedule, 0, self.time); + + function schedule(elapsed) { + self.state = SCHEDULED; + self.timer.restart(start, self.delay, self.time); + + // If the elapsed delay is less than our first sleep, start immediately. + if (self.delay <= elapsed) start(elapsed - self.delay); + } + + function start(elapsed) { + var i, j, n, o; + + // If the state is not SCHEDULED, then we previously errored on start. + if (self.state !== SCHEDULED) return stop(); + + for (i in schedules) { + o = schedules[i]; + if (o.name !== self.name) continue; + + // While this element already has a starting transition during this frame, + // defer starting an interrupting transition until that transition has a + // chance to tick (and possibly end); see d3/d3-transition#54! + if (o.state === STARTED) return timeout(start); + + // Interrupt the active transition, if any. + if (o.state === RUNNING) { + o.state = ENDED; + o.timer.stop(); + o.on.call("interrupt", node, node.__data__, o.index, o.group); + delete schedules[i]; + } + + // Cancel any pre-empted transitions. + else if (+i < id) { + o.state = ENDED; + o.timer.stop(); + o.on.call("cancel", node, node.__data__, o.index, o.group); + delete schedules[i]; + } + } + + // Defer the first tick to end of the current frame; see d3/d3#1576. + // Note the transition may be canceled after start and before the first tick! + // Note this must be scheduled before the start event; see d3/d3-transition#16! + // Assuming this is successful, subsequent callbacks go straight to tick. + timeout(function() { + if (self.state === STARTED) { + self.state = RUNNING; + self.timer.restart(tick, self.delay, self.time); + tick(elapsed); + } + }); + + // Dispatch the start event. + // Note this must be done before the tween are initialized. + self.state = STARTING; + self.on.call("start", node, node.__data__, self.index, self.group); + if (self.state !== STARTING) return; // interrupted + self.state = STARTED; + + // Initialize the tween, deleting null tween. + tween = new Array(n = self.tween.length); + for (i = 0, j = -1; i < n; ++i) { + if (o = self.tween[i].value.call(node, node.__data__, self.index, self.group)) { + tween[++j] = o; + } + } + tween.length = j + 1; + } + + function tick(elapsed) { + var t = elapsed < self.duration ? self.ease.call(null, elapsed / self.duration) : (self.timer.restart(stop), self.state = ENDING, 1), + i = -1, + n = tween.length; + + while (++i < n) { + tween[i].call(node, t); + } + + // Dispatch the end event. + if (self.state === ENDING) { + self.on.call("end", node, node.__data__, self.index, self.group); + stop(); + } + } + + function stop() { + self.state = ENDED; + self.timer.stop(); + delete schedules[id]; + for (var i in schedules) return; // eslint-disable-line no-unused-vars + delete node.__transition; + } + } + + function interrupt(node, name) { + var schedules = node.__transition, + schedule, + active, + empty = true, + i; + + if (!schedules) return; + + name = name == null ? null : name + ""; + + for (i in schedules) { + if ((schedule = schedules[i]).name !== name) { empty = false; continue; } + active = schedule.state > STARTING && schedule.state < ENDING; + schedule.state = ENDED; + schedule.timer.stop(); + schedule.on.call(active ? "interrupt" : "cancel", node, node.__data__, schedule.index, schedule.group); + delete schedules[i]; + } + + if (empty) delete node.__transition; + } + + function selection_interrupt(name) { + return this.each(function() { + interrupt(this, name); + }); + } + + function tweenRemove(id, name) { + var tween0, tween1; + return function() { + var schedule = set(this, id), + tween = schedule.tween; + + // If this node shared tween with the previous node, + // just assign the updated shared tween and we’re done! + // Otherwise, copy-on-write. + if (tween !== tween0) { + tween1 = tween0 = tween; + for (var i = 0, n = tween1.length; i < n; ++i) { + if (tween1[i].name === name) { + tween1 = tween1.slice(); + tween1.splice(i, 1); + break; + } + } + } + + schedule.tween = tween1; + }; + } + + function tweenFunction(id, name, value) { + var tween0, tween1; + if (typeof value !== "function") throw new Error; + return function() { + var schedule = set(this, id), + tween = schedule.tween; + + // If this node shared tween with the previous node, + // just assign the updated shared tween and we’re done! + // Otherwise, copy-on-write. + if (tween !== tween0) { + tween1 = (tween0 = tween).slice(); + for (var t = {name: name, value: value}, i = 0, n = tween1.length; i < n; ++i) { + if (tween1[i].name === name) { + tween1[i] = t; + break; + } + } + if (i === n) tween1.push(t); + } + + schedule.tween = tween1; + }; + } + + function transition_tween(name, value) { + var id = this._id; + + name += ""; + + if (arguments.length < 2) { + var tween = get(this.node(), id).tween; + for (var i = 0, n = tween.length, t; i < n; ++i) { + if ((t = tween[i]).name === name) { + return t.value; + } + } + return null; + } + + return this.each((value == null ? tweenRemove : tweenFunction)(id, name, value)); + } + + function tweenValue(transition, name, value) { + var id = transition._id; + + transition.each(function() { + var schedule = set(this, id); + (schedule.value || (schedule.value = {}))[name] = value.apply(this, arguments); + }); + + return function(node) { + return get(node, id).value[name]; + }; + } + + function interpolate(a, b) { + var c; + return (typeof b === "number" ? interpolateNumber + : b instanceof color ? interpolateRgb + : (c = color(b)) ? (b = c, interpolateRgb) + : interpolateString)(a, b); + } + + function attrRemove(name) { + return function() { + this.removeAttribute(name); + }; + } + + function attrRemoveNS(fullname) { + return function() { + this.removeAttributeNS(fullname.space, fullname.local); + }; + } + + function attrConstant(name, interpolate, value1) { + var string00, + string1 = value1 + "", + interpolate0; + return function() { + var string0 = this.getAttribute(name); + return string0 === string1 ? null + : string0 === string00 ? interpolate0 + : interpolate0 = interpolate(string00 = string0, value1); + }; + } + + function attrConstantNS(fullname, interpolate, value1) { + var string00, + string1 = value1 + "", + interpolate0; + return function() { + var string0 = this.getAttributeNS(fullname.space, fullname.local); + return string0 === string1 ? null + : string0 === string00 ? interpolate0 + : interpolate0 = interpolate(string00 = string0, value1); + }; + } + + function attrFunction(name, interpolate, value) { + var string00, + string10, + interpolate0; + return function() { + var string0, value1 = value(this), string1; + if (value1 == null) return void this.removeAttribute(name); + string0 = this.getAttribute(name); + string1 = value1 + ""; + return string0 === string1 ? null + : string0 === string00 && string1 === string10 ? interpolate0 + : (string10 = string1, interpolate0 = interpolate(string00 = string0, value1)); + }; + } + + function attrFunctionNS(fullname, interpolate, value) { + var string00, + string10, + interpolate0; + return function() { + var string0, value1 = value(this), string1; + if (value1 == null) return void this.removeAttributeNS(fullname.space, fullname.local); + string0 = this.getAttributeNS(fullname.space, fullname.local); + string1 = value1 + ""; + return string0 === string1 ? null + : string0 === string00 && string1 === string10 ? interpolate0 + : (string10 = string1, interpolate0 = interpolate(string00 = string0, value1)); + }; + } + + function transition_attr(name, value) { + var fullname = namespace(name), i = fullname === "transform" ? interpolateTransformSvg : interpolate; + return this.attrTween(name, typeof value === "function" + ? (fullname.local ? attrFunctionNS : attrFunction)(fullname, i, tweenValue(this, "attr." + name, value)) + : value == null ? (fullname.local ? attrRemoveNS : attrRemove)(fullname) + : (fullname.local ? attrConstantNS : attrConstant)(fullname, i, value)); + } + + function attrInterpolate(name, i) { + return function(t) { + this.setAttribute(name, i.call(this, t)); + }; + } + + function attrInterpolateNS(fullname, i) { + return function(t) { + this.setAttributeNS(fullname.space, fullname.local, i.call(this, t)); + }; + } + + function attrTweenNS(fullname, value) { + var t0, i0; + function tween() { + var i = value.apply(this, arguments); + if (i !== i0) t0 = (i0 = i) && attrInterpolateNS(fullname, i); + return t0; + } + tween._value = value; + return tween; + } + + function attrTween(name, value) { + var t0, i0; + function tween() { + var i = value.apply(this, arguments); + if (i !== i0) t0 = (i0 = i) && attrInterpolate(name, i); + return t0; + } + tween._value = value; + return tween; + } + + function transition_attrTween(name, value) { + var key = "attr." + name; + if (arguments.length < 2) return (key = this.tween(key)) && key._value; + if (value == null) return this.tween(key, null); + if (typeof value !== "function") throw new Error; + var fullname = namespace(name); + return this.tween(key, (fullname.local ? attrTweenNS : attrTween)(fullname, value)); + } + + function delayFunction(id, value) { + return function() { + init(this, id).delay = +value.apply(this, arguments); + }; + } + + function delayConstant(id, value) { + return value = +value, function() { + init(this, id).delay = value; + }; + } + + function transition_delay(value) { + var id = this._id; + + return arguments.length + ? this.each((typeof value === "function" + ? delayFunction + : delayConstant)(id, value)) + : get(this.node(), id).delay; + } + + function durationFunction(id, value) { + return function() { + set(this, id).duration = +value.apply(this, arguments); + }; + } + + function durationConstant(id, value) { + return value = +value, function() { + set(this, id).duration = value; + }; + } + + function transition_duration(value) { + var id = this._id; + + return arguments.length + ? this.each((typeof value === "function" + ? durationFunction + : durationConstant)(id, value)) + : get(this.node(), id).duration; + } + + function easeConstant(id, value) { + if (typeof value !== "function") throw new Error; + return function() { + set(this, id).ease = value; + }; + } + + function transition_ease(value) { + var id = this._id; + + return arguments.length + ? this.each(easeConstant(id, value)) + : get(this.node(), id).ease; + } + + function easeVarying(id, value) { + return function() { + var v = value.apply(this, arguments); + if (typeof v !== "function") throw new Error; + set(this, id).ease = v; + }; + } + + function transition_easeVarying(value) { + if (typeof value !== "function") throw new Error; + return this.each(easeVarying(this._id, value)); + } + + function transition_filter(match) { + if (typeof match !== "function") match = matcher(match); + + for (var groups = this._groups, m = groups.length, subgroups = new Array(m), j = 0; j < m; ++j) { + for (var group = groups[j], n = group.length, subgroup = subgroups[j] = [], node, i = 0; i < n; ++i) { + if ((node = group[i]) && match.call(node, node.__data__, i, group)) { + subgroup.push(node); + } + } + } + + return new Transition(subgroups, this._parents, this._name, this._id); + } + + function transition_merge(transition) { + if (transition._id !== this._id) throw new Error; + + for (var groups0 = this._groups, groups1 = transition._groups, m0 = groups0.length, m1 = groups1.length, m = Math.min(m0, m1), merges = new Array(m0), j = 0; j < m; ++j) { + for (var group0 = groups0[j], group1 = groups1[j], n = group0.length, merge = merges[j] = new Array(n), node, i = 0; i < n; ++i) { + if (node = group0[i] || group1[i]) { + merge[i] = node; + } + } + } + + for (; j < m0; ++j) { + merges[j] = groups0[j]; + } + + return new Transition(merges, this._parents, this._name, this._id); + } + + function start(name) { + return (name + "").trim().split(/^|\s+/).every(function(t) { + var i = t.indexOf("."); + if (i >= 0) t = t.slice(0, i); + return !t || t === "start"; + }); + } + + function onFunction(id, name, listener) { + var on0, on1, sit = start(name) ? init : set; + return function() { + var schedule = sit(this, id), + on = schedule.on; + + // If this node shared a dispatch with the previous node, + // just assign the updated shared dispatch and we’re done! + // Otherwise, copy-on-write. + if (on !== on0) (on1 = (on0 = on).copy()).on(name, listener); + + schedule.on = on1; + }; + } + + function transition_on(name, listener) { + var id = this._id; + + return arguments.length < 2 + ? get(this.node(), id).on.on(name) + : this.each(onFunction(id, name, listener)); + } + + function removeFunction(id) { + return function() { + var parent = this.parentNode; + for (var i in this.__transition) if (+i !== id) return; + if (parent) parent.removeChild(this); + }; + } + + function transition_remove() { + return this.on("end.remove", removeFunction(this._id)); + } + + function transition_select(select) { + var name = this._name, + id = this._id; + + if (typeof select !== "function") select = selector(select); + + for (var groups = this._groups, m = groups.length, subgroups = new Array(m), j = 0; j < m; ++j) { + for (var group = groups[j], n = group.length, subgroup = subgroups[j] = new Array(n), node, subnode, i = 0; i < n; ++i) { + if ((node = group[i]) && (subnode = select.call(node, node.__data__, i, group))) { + if ("__data__" in node) subnode.__data__ = node.__data__; + subgroup[i] = subnode; + schedule(subgroup[i], name, id, i, subgroup, get(node, id)); + } + } + } + + return new Transition(subgroups, this._parents, name, id); + } + + function transition_selectAll(select) { + var name = this._name, + id = this._id; + + if (typeof select !== "function") select = selectorAll(select); + + for (var groups = this._groups, m = groups.length, subgroups = [], parents = [], j = 0; j < m; ++j) { + for (var group = groups[j], n = group.length, node, i = 0; i < n; ++i) { + if (node = group[i]) { + for (var children = select.call(node, node.__data__, i, group), child, inherit = get(node, id), k = 0, l = children.length; k < l; ++k) { + if (child = children[k]) { + schedule(child, name, id, k, children, inherit); + } + } + subgroups.push(children); + parents.push(node); + } + } + } + + return new Transition(subgroups, parents, name, id); + } + + var Selection = selection.prototype.constructor; + + function transition_selection() { + return new Selection(this._groups, this._parents); + } + + function styleNull(name, interpolate) { + var string00, + string10, + interpolate0; + return function() { + var string0 = styleValue(this, name), + string1 = (this.style.removeProperty(name), styleValue(this, name)); + return string0 === string1 ? null + : string0 === string00 && string1 === string10 ? interpolate0 + : interpolate0 = interpolate(string00 = string0, string10 = string1); + }; + } + + function styleRemove(name) { + return function() { + this.style.removeProperty(name); + }; + } + + function styleConstant(name, interpolate, value1) { + var string00, + string1 = value1 + "", + interpolate0; + return function() { + var string0 = styleValue(this, name); + return string0 === string1 ? null + : string0 === string00 ? interpolate0 + : interpolate0 = interpolate(string00 = string0, value1); + }; + } + + function styleFunction(name, interpolate, value) { + var string00, + string10, + interpolate0; + return function() { + var string0 = styleValue(this, name), + value1 = value(this), + string1 = value1 + ""; + if (value1 == null) string1 = value1 = (this.style.removeProperty(name), styleValue(this, name)); + return string0 === string1 ? null + : string0 === string00 && string1 === string10 ? interpolate0 + : (string10 = string1, interpolate0 = interpolate(string00 = string0, value1)); + }; + } + + function styleMaybeRemove(id, name) { + var on0, on1, listener0, key = "style." + name, event = "end." + key, remove; + return function() { + var schedule = set(this, id), + on = schedule.on, + listener = schedule.value[key] == null ? remove || (remove = styleRemove(name)) : undefined; + + // If this node shared a dispatch with the previous node, + // just assign the updated shared dispatch and we’re done! + // Otherwise, copy-on-write. + if (on !== on0 || listener0 !== listener) (on1 = (on0 = on).copy()).on(event, listener0 = listener); + + schedule.on = on1; + }; + } + + function transition_style(name, value, priority) { + var i = (name += "") === "transform" ? interpolateTransformCss : interpolate; + return value == null ? this + .styleTween(name, styleNull(name, i)) + .on("end.style." + name, styleRemove(name)) + : typeof value === "function" ? this + .styleTween(name, styleFunction(name, i, tweenValue(this, "style." + name, value))) + .each(styleMaybeRemove(this._id, name)) + : this + .styleTween(name, styleConstant(name, i, value), priority) + .on("end.style." + name, null); + } + + function styleInterpolate(name, i, priority) { + return function(t) { + this.style.setProperty(name, i.call(this, t), priority); + }; + } + + function styleTween(name, value, priority) { + var t, i0; + function tween() { + var i = value.apply(this, arguments); + if (i !== i0) t = (i0 = i) && styleInterpolate(name, i, priority); + return t; + } + tween._value = value; + return tween; + } + + function transition_styleTween(name, value, priority) { + var key = "style." + (name += ""); + if (arguments.length < 2) return (key = this.tween(key)) && key._value; + if (value == null) return this.tween(key, null); + if (typeof value !== "function") throw new Error; + return this.tween(key, styleTween(name, value, priority == null ? "" : priority)); + } + + function textConstant(value) { + return function() { + this.textContent = value; + }; + } + + function textFunction(value) { + return function() { + var value1 = value(this); + this.textContent = value1 == null ? "" : value1; + }; + } + + function transition_text(value) { + return this.tween("text", typeof value === "function" + ? textFunction(tweenValue(this, "text", value)) + : textConstant(value == null ? "" : value + "")); + } + + function textInterpolate(i) { + return function(t) { + this.textContent = i.call(this, t); + }; + } + + function textTween(value) { + var t0, i0; + function tween() { + var i = value.apply(this, arguments); + if (i !== i0) t0 = (i0 = i) && textInterpolate(i); + return t0; + } + tween._value = value; + return tween; + } + + function transition_textTween(value) { + var key = "text"; + if (arguments.length < 1) return (key = this.tween(key)) && key._value; + if (value == null) return this.tween(key, null); + if (typeof value !== "function") throw new Error; + return this.tween(key, textTween(value)); + } + + function transition_transition() { + var name = this._name, + id0 = this._id, + id1 = newId(); + + for (var groups = this._groups, m = groups.length, j = 0; j < m; ++j) { + for (var group = groups[j], n = group.length, node, i = 0; i < n; ++i) { + if (node = group[i]) { + var inherit = get(node, id0); + schedule(node, name, id1, i, group, { + time: inherit.time + inherit.delay + inherit.duration, + delay: 0, + duration: inherit.duration, + ease: inherit.ease + }); + } + } + } + + return new Transition(groups, this._parents, name, id1); + } + + function transition_end() { + var on0, on1, that = this, id = that._id, size = that.size(); + return new Promise(function(resolve, reject) { + var cancel = {value: reject}, + end = {value: function() { if (--size === 0) resolve(); }}; + + that.each(function() { + var schedule = set(this, id), + on = schedule.on; + + // If this node shared a dispatch with the previous node, + // just assign the updated shared dispatch and we’re done! + // Otherwise, copy-on-write. + if (on !== on0) { + on1 = (on0 = on).copy(); + on1._.cancel.push(cancel); + on1._.interrupt.push(cancel); + on1._.end.push(end); + } + + schedule.on = on1; + }); + + // The selection was empty, resolve end immediately + if (size === 0) resolve(); + }); + } + + var id = 0; + + function Transition(groups, parents, name, id) { + this._groups = groups; + this._parents = parents; + this._name = name; + this._id = id; + } + + function newId() { + return ++id; + } + + var selection_prototype = selection.prototype; + + Transition.prototype = { + constructor: Transition, + select: transition_select, + selectAll: transition_selectAll, + selectChild: selection_prototype.selectChild, + selectChildren: selection_prototype.selectChildren, + filter: transition_filter, + merge: transition_merge, + selection: transition_selection, + transition: transition_transition, + call: selection_prototype.call, + nodes: selection_prototype.nodes, + node: selection_prototype.node, + size: selection_prototype.size, + empty: selection_prototype.empty, + each: selection_prototype.each, + on: transition_on, + attr: transition_attr, + attrTween: transition_attrTween, + style: transition_style, + styleTween: transition_styleTween, + text: transition_text, + textTween: transition_textTween, + remove: transition_remove, + tween: transition_tween, + delay: transition_delay, + duration: transition_duration, + ease: transition_ease, + easeVarying: transition_easeVarying, + end: transition_end, + [Symbol.iterator]: selection_prototype[Symbol.iterator] + }; + + function cubicInOut(t) { + return ((t *= 2) <= 1 ? t * t * t : (t -= 2) * t * t + 2) / 2; + } + + var defaultTiming = { + time: null, // Set on use. + delay: 0, + duration: 250, + ease: cubicInOut + }; + + function inherit(node, id) { + var timing; + while (!(timing = node.__transition) || !(timing = timing[id])) { + if (!(node = node.parentNode)) { + throw new Error(`transition ${id} not found`); + } + } + return timing; + } + + function selection_transition(name) { + var id, + timing; + + if (name instanceof Transition) { + id = name._id, name = name._name; + } else { + id = newId(), (timing = defaultTiming).time = now$3(), name = name == null ? null : name + ""; + } + + for (var groups = this._groups, m = groups.length, j = 0; j < m; ++j) { + for (var group = groups[j], n = group.length, node, i = 0; i < n; ++i) { + if (node = group[i]) { + schedule(node, name, id, i, group, timing || inherit(node, id)); + } + } + } + + return new Transition(groups, this._parents, name, id); + } + + selection.prototype.interrupt = selection_interrupt; + selection.prototype.transition = selection_transition; + + var constant$1 = x => () => x; + + function ZoomEvent(type, { + sourceEvent, + target, + transform, + dispatch + }) { + Object.defineProperties(this, { + type: {value: type, enumerable: true, configurable: true}, + sourceEvent: {value: sourceEvent, enumerable: true, configurable: true}, + target: {value: target, enumerable: true, configurable: true}, + transform: {value: transform, enumerable: true, configurable: true}, + _: {value: dispatch} + }); + } + + function Transform(k, x, y) { + this.k = k; + this.x = x; + this.y = y; + } + + Transform.prototype = { + constructor: Transform, + scale: function(k) { + return k === 1 ? this : new Transform(this.k * k, this.x, this.y); + }, + translate: function(x, y) { + return x === 0 & y === 0 ? this : new Transform(this.k, this.x + this.k * x, this.y + this.k * y); + }, + apply: function(point) { + return [point[0] * this.k + this.x, point[1] * this.k + this.y]; + }, + applyX: function(x) { + return x * this.k + this.x; + }, + applyY: function(y) { + return y * this.k + this.y; + }, + invert: function(location) { + return [(location[0] - this.x) / this.k, (location[1] - this.y) / this.k]; + }, + invertX: function(x) { + return (x - this.x) / this.k; + }, + invertY: function(y) { + return (y - this.y) / this.k; + }, + rescaleX: function(x) { + return x.copy().domain(x.range().map(this.invertX, this).map(x.invert, x)); + }, + rescaleY: function(y) { + return y.copy().domain(y.range().map(this.invertY, this).map(y.invert, y)); + }, + toString: function() { + return "translate(" + this.x + "," + this.y + ") scale(" + this.k + ")"; + } + }; + + var identity = new Transform(1, 0, 0); + + transform.prototype = Transform.prototype; + + function transform(node) { + while (!node.__zoom) if (!(node = node.parentNode)) return identity; + return node.__zoom; + } + + function nopropagation(event) { + event.stopImmediatePropagation(); + } + + function noevent(event) { + event.preventDefault(); + event.stopImmediatePropagation(); + } + + // Ignore right-click, since that should open the context menu. + // except for pinch-to-zoom, which is sent as a wheel+ctrlKey event + function defaultFilter(event) { + return (!event.ctrlKey || event.type === 'wheel') && !event.button; + } + + function defaultExtent() { + var e = this; + if (e instanceof SVGElement) { + e = e.ownerSVGElement || e; + if (e.hasAttribute("viewBox")) { + e = e.viewBox.baseVal; + return [[e.x, e.y], [e.x + e.width, e.y + e.height]]; + } + return [[0, 0], [e.width.baseVal.value, e.height.baseVal.value]]; + } + return [[0, 0], [e.clientWidth, e.clientHeight]]; + } + + function defaultTransform() { + return this.__zoom || identity; + } + + function defaultWheelDelta(event) { + return -event.deltaY * (event.deltaMode === 1 ? 0.05 : event.deltaMode ? 1 : 0.002) * (event.ctrlKey ? 10 : 1); + } + + function defaultTouchable() { + return navigator.maxTouchPoints || ("ontouchstart" in this); + } + + function defaultConstrain(transform, extent, translateExtent) { + var dx0 = transform.invertX(extent[0][0]) - translateExtent[0][0], + dx1 = transform.invertX(extent[1][0]) - translateExtent[1][0], + dy0 = transform.invertY(extent[0][1]) - translateExtent[0][1], + dy1 = transform.invertY(extent[1][1]) - translateExtent[1][1]; + return transform.translate( + dx1 > dx0 ? (dx0 + dx1) / 2 : Math.min(0, dx0) || Math.max(0, dx1), + dy1 > dy0 ? (dy0 + dy1) / 2 : Math.min(0, dy0) || Math.max(0, dy1) + ); + } + + function d3Zoom() { + var filter = defaultFilter, + extent = defaultExtent, + constrain = defaultConstrain, + wheelDelta = defaultWheelDelta, + touchable = defaultTouchable, + scaleExtent = [0, Infinity], + translateExtent = [[-Infinity, -Infinity], [Infinity, Infinity]], + duration = 250, + interpolate = interpolateZoom, + listeners = dispatch("start", "zoom", "end"), + touchstarting, + touchfirst, + touchending, + touchDelay = 500, + wheelDelay = 150, + clickDistance2 = 0, + tapDistance = 10; + + function zoom(selection) { + selection + .property("__zoom", defaultTransform) + .on("wheel.zoom", wheeled, {passive: false}) + .on("mousedown.zoom", mousedowned) + .on("dblclick.zoom", dblclicked) + .filter(touchable) + .on("touchstart.zoom", touchstarted) + .on("touchmove.zoom", touchmoved) + .on("touchend.zoom touchcancel.zoom", touchended) + .style("-webkit-tap-highlight-color", "rgba(0,0,0,0)"); + } + + zoom.transform = function(collection, transform, point, event) { + var selection = collection.selection ? collection.selection() : collection; + selection.property("__zoom", defaultTransform); + if (collection !== selection) { + schedule(collection, transform, point, event); + } else { + selection.interrupt().each(function() { + gesture(this, arguments) + .event(event) + .start() + .zoom(null, typeof transform === "function" ? transform.apply(this, arguments) : transform) + .end(); + }); + } + }; + + zoom.scaleBy = function(selection, k, p, event) { + zoom.scaleTo(selection, function() { + var k0 = this.__zoom.k, + k1 = typeof k === "function" ? k.apply(this, arguments) : k; + return k0 * k1; + }, p, event); + }; + + zoom.scaleTo = function(selection, k, p, event) { + zoom.transform(selection, function() { + var e = extent.apply(this, arguments), + t0 = this.__zoom, + p0 = p == null ? centroid(e) : typeof p === "function" ? p.apply(this, arguments) : p, + p1 = t0.invert(p0), + k1 = typeof k === "function" ? k.apply(this, arguments) : k; + return constrain(translate(scale(t0, k1), p0, p1), e, translateExtent); + }, p, event); + }; + + zoom.translateBy = function(selection, x, y, event) { + zoom.transform(selection, function() { + return constrain(this.__zoom.translate( + typeof x === "function" ? x.apply(this, arguments) : x, + typeof y === "function" ? y.apply(this, arguments) : y + ), extent.apply(this, arguments), translateExtent); + }, null, event); + }; + + zoom.translateTo = function(selection, x, y, p, event) { + zoom.transform(selection, function() { + var e = extent.apply(this, arguments), + t = this.__zoom, + p0 = p == null ? centroid(e) : typeof p === "function" ? p.apply(this, arguments) : p; + return constrain(identity.translate(p0[0], p0[1]).scale(t.k).translate( + typeof x === "function" ? -x.apply(this, arguments) : -x, + typeof y === "function" ? -y.apply(this, arguments) : -y + ), e, translateExtent); + }, p, event); + }; + + function scale(transform, k) { + k = Math.max(scaleExtent[0], Math.min(scaleExtent[1], k)); + return k === transform.k ? transform : new Transform(k, transform.x, transform.y); + } + + function translate(transform, p0, p1) { + var x = p0[0] - p1[0] * transform.k, y = p0[1] - p1[1] * transform.k; + return x === transform.x && y === transform.y ? transform : new Transform(transform.k, x, y); + } + + function centroid(extent) { + return [(+extent[0][0] + +extent[1][0]) / 2, (+extent[0][1] + +extent[1][1]) / 2]; + } + + function schedule(transition, transform, point, event) { + transition + .on("start.zoom", function() { gesture(this, arguments).event(event).start(); }) + .on("interrupt.zoom end.zoom", function() { gesture(this, arguments).event(event).end(); }) + .tween("zoom", function() { + var that = this, + args = arguments, + g = gesture(that, args).event(event), + e = extent.apply(that, args), + p = point == null ? centroid(e) : typeof point === "function" ? point.apply(that, args) : point, + w = Math.max(e[1][0] - e[0][0], e[1][1] - e[0][1]), + a = that.__zoom, + b = typeof transform === "function" ? transform.apply(that, args) : transform, + i = interpolate(a.invert(p).concat(w / a.k), b.invert(p).concat(w / b.k)); + return function(t) { + if (t === 1) t = b; // Avoid rounding error on end. + else { var l = i(t), k = w / l[2]; t = new Transform(k, p[0] - l[0] * k, p[1] - l[1] * k); } + g.zoom(null, t); + }; + }); + } + + function gesture(that, args, clean) { + return (!clean && that.__zooming) || new Gesture(that, args); + } + + function Gesture(that, args) { + this.that = that; + this.args = args; + this.active = 0; + this.sourceEvent = null; + this.extent = extent.apply(that, args); + this.taps = 0; + } + + Gesture.prototype = { + event: function(event) { + if (event) this.sourceEvent = event; + return this; + }, + start: function() { + if (++this.active === 1) { + this.that.__zooming = this; + this.emit("start"); + } + return this; + }, + zoom: function(key, transform) { + if (this.mouse && key !== "mouse") this.mouse[1] = transform.invert(this.mouse[0]); + if (this.touch0 && key !== "touch") this.touch0[1] = transform.invert(this.touch0[0]); + if (this.touch1 && key !== "touch") this.touch1[1] = transform.invert(this.touch1[0]); + this.that.__zoom = transform; + this.emit("zoom"); + return this; + }, + end: function() { + if (--this.active === 0) { + delete this.that.__zooming; + this.emit("end"); + } + return this; + }, + emit: function(type) { + var d = d3Select(this.that).datum(); + listeners.call( + type, + this.that, + new ZoomEvent(type, { + sourceEvent: this.sourceEvent, + target: zoom, + type, + transform: this.that.__zoom, + dispatch: listeners + }), + d + ); + } + }; + + function wheeled(event, ...args) { + if (!filter.apply(this, arguments)) return; + var g = gesture(this, args).event(event), + t = this.__zoom, + k = Math.max(scaleExtent[0], Math.min(scaleExtent[1], t.k * Math.pow(2, wheelDelta.apply(this, arguments)))), + p = pointer(event); + + // If the mouse is in the same location as before, reuse it. + // If there were recent wheel events, reset the wheel idle timeout. + if (g.wheel) { + if (g.mouse[0][0] !== p[0] || g.mouse[0][1] !== p[1]) { + g.mouse[1] = t.invert(g.mouse[0] = p); + } + clearTimeout(g.wheel); + } + + // If this wheel event won’t trigger a transform change, ignore it. + else if (t.k === k) return; + + // Otherwise, capture the mouse point and location at the start. + else { + g.mouse = [p, t.invert(p)]; + interrupt(this); + g.start(); + } + + noevent(event); + g.wheel = setTimeout(wheelidled, wheelDelay); + g.zoom("mouse", constrain(translate(scale(t, k), g.mouse[0], g.mouse[1]), g.extent, translateExtent)); + + function wheelidled() { + g.wheel = null; + g.end(); + } + } + + function mousedowned(event, ...args) { + if (touchending || !filter.apply(this, arguments)) return; + var currentTarget = event.currentTarget, + g = gesture(this, args, true).event(event), + v = d3Select(event.view).on("mousemove.zoom", mousemoved, true).on("mouseup.zoom", mouseupped, true), + p = pointer(event, currentTarget), + x0 = event.clientX, + y0 = event.clientY; + + dragDisable(event.view); + nopropagation(event); + g.mouse = [p, this.__zoom.invert(p)]; + interrupt(this); + g.start(); + + function mousemoved(event) { + noevent(event); + if (!g.moved) { + var dx = event.clientX - x0, dy = event.clientY - y0; + g.moved = dx * dx + dy * dy > clickDistance2; + } + g.event(event) + .zoom("mouse", constrain(translate(g.that.__zoom, g.mouse[0] = pointer(event, currentTarget), g.mouse[1]), g.extent, translateExtent)); + } + + function mouseupped(event) { + v.on("mousemove.zoom mouseup.zoom", null); + yesdrag(event.view, g.moved); + noevent(event); + g.event(event).end(); + } + } + + function dblclicked(event, ...args) { + if (!filter.apply(this, arguments)) return; + var t0 = this.__zoom, + p0 = pointer(event.changedTouches ? event.changedTouches[0] : event, this), + p1 = t0.invert(p0), + k1 = t0.k * (event.shiftKey ? 0.5 : 2), + t1 = constrain(translate(scale(t0, k1), p0, p1), extent.apply(this, args), translateExtent); + + noevent(event); + if (duration > 0) d3Select(this).transition().duration(duration).call(schedule, t1, p0, event); + else d3Select(this).call(zoom.transform, t1, p0, event); + } + + function touchstarted(event, ...args) { + if (!filter.apply(this, arguments)) return; + var touches = event.touches, + n = touches.length, + g = gesture(this, args, event.changedTouches.length === n).event(event), + started, i, t, p; + + nopropagation(event); + for (i = 0; i < n; ++i) { + t = touches[i], p = pointer(t, this); + p = [p, this.__zoom.invert(p), t.identifier]; + if (!g.touch0) g.touch0 = p, started = true, g.taps = 1 + !!touchstarting; + else if (!g.touch1 && g.touch0[2] !== p[2]) g.touch1 = p, g.taps = 0; + } + + if (touchstarting) touchstarting = clearTimeout(touchstarting); + + if (started) { + if (g.taps < 2) touchfirst = p[0], touchstarting = setTimeout(function() { touchstarting = null; }, touchDelay); + interrupt(this); + g.start(); + } + } + + function touchmoved(event, ...args) { + if (!this.__zooming) return; + var g = gesture(this, args).event(event), + touches = event.changedTouches, + n = touches.length, i, t, p, l; + + noevent(event); + for (i = 0; i < n; ++i) { + t = touches[i], p = pointer(t, this); + if (g.touch0 && g.touch0[2] === t.identifier) g.touch0[0] = p; + else if (g.touch1 && g.touch1[2] === t.identifier) g.touch1[0] = p; + } + t = g.that.__zoom; + if (g.touch1) { + var p0 = g.touch0[0], l0 = g.touch0[1], + p1 = g.touch1[0], l1 = g.touch1[1], + dp = (dp = p1[0] - p0[0]) * dp + (dp = p1[1] - p0[1]) * dp, + dl = (dl = l1[0] - l0[0]) * dl + (dl = l1[1] - l0[1]) * dl; + t = scale(t, Math.sqrt(dp / dl)); + p = [(p0[0] + p1[0]) / 2, (p0[1] + p1[1]) / 2]; + l = [(l0[0] + l1[0]) / 2, (l0[1] + l1[1]) / 2]; + } + else if (g.touch0) p = g.touch0[0], l = g.touch0[1]; + else return; + + g.zoom("touch", constrain(translate(t, p, l), g.extent, translateExtent)); + } + + function touchended(event, ...args) { + if (!this.__zooming) return; + var g = gesture(this, args).event(event), + touches = event.changedTouches, + n = touches.length, i, t; + + nopropagation(event); + if (touchending) clearTimeout(touchending); + touchending = setTimeout(function() { touchending = null; }, touchDelay); + for (i = 0; i < n; ++i) { + t = touches[i]; + if (g.touch0 && g.touch0[2] === t.identifier) delete g.touch0; + else if (g.touch1 && g.touch1[2] === t.identifier) delete g.touch1; + } + if (g.touch1 && !g.touch0) g.touch0 = g.touch1, delete g.touch1; + if (g.touch0) g.touch0[1] = this.__zoom.invert(g.touch0[0]); + else { + g.end(); + // If this was a dbltap, reroute to the (optional) dblclick.zoom handler. + if (g.taps === 2) { + t = pointer(t, this); + if (Math.hypot(touchfirst[0] - t[0], touchfirst[1] - t[1]) < tapDistance) { + var p = d3Select(this).on("dblclick.zoom"); + if (p) p.apply(this, arguments); + } + } + } + } + + zoom.wheelDelta = function(_) { + return arguments.length ? (wheelDelta = typeof _ === "function" ? _ : constant$1(+_), zoom) : wheelDelta; + }; + + zoom.filter = function(_) { + return arguments.length ? (filter = typeof _ === "function" ? _ : constant$1(!!_), zoom) : filter; + }; + + zoom.touchable = function(_) { + return arguments.length ? (touchable = typeof _ === "function" ? _ : constant$1(!!_), zoom) : touchable; + }; + + zoom.extent = function(_) { + return arguments.length ? (extent = typeof _ === "function" ? _ : constant$1([[+_[0][0], +_[0][1]], [+_[1][0], +_[1][1]]]), zoom) : extent; + }; + + zoom.scaleExtent = function(_) { + return arguments.length ? (scaleExtent[0] = +_[0], scaleExtent[1] = +_[1], zoom) : [scaleExtent[0], scaleExtent[1]]; + }; + + zoom.translateExtent = function(_) { + return arguments.length ? (translateExtent[0][0] = +_[0][0], translateExtent[1][0] = +_[1][0], translateExtent[0][1] = +_[0][1], translateExtent[1][1] = +_[1][1], zoom) : [[translateExtent[0][0], translateExtent[0][1]], [translateExtent[1][0], translateExtent[1][1]]]; + }; + + zoom.constrain = function(_) { + return arguments.length ? (constrain = _, zoom) : constrain; + }; + + zoom.duration = function(_) { + return arguments.length ? (duration = +_, zoom) : duration; + }; + + zoom.interpolate = function(_) { + return arguments.length ? (interpolate = _, zoom) : interpolate; + }; + + zoom.on = function() { + var value = listeners.on.apply(listeners, arguments); + return value === listeners ? zoom : value; + }; + + zoom.clickDistance = function(_) { + return arguments.length ? (clickDistance2 = (_ = +_) * _, zoom) : Math.sqrt(clickDistance2); + }; + + zoom.tapDistance = function(_) { + return arguments.length ? (tapDistance = +_, zoom) : tapDistance; + }; + + return zoom; + } + + class InternMap extends Map { + constructor(entries, key = keyof) { + super(); + Object.defineProperties(this, {_intern: {value: new Map()}, _key: {value: key}}); + if (entries != null) for (const [key, value] of entries) this.set(key, value); + } + get(key) { + return super.get(intern_get(this, key)); + } + has(key) { + return super.has(intern_get(this, key)); + } + set(key, value) { + return super.set(intern_set(this, key), value); + } + delete(key) { + return super.delete(intern_delete(this, key)); + } + } + + function intern_get({_intern, _key}, value) { + const key = _key(value); + return _intern.has(key) ? _intern.get(key) : value; + } + + function intern_set({_intern, _key}, value) { + const key = _key(value); + if (_intern.has(key)) return _intern.get(key); + _intern.set(key, value); + return value; + } + + function intern_delete({_intern, _key}, value) { + const key = _key(value); + if (_intern.has(key)) { + value = _intern.get(key); + _intern.delete(key); + } + return value; + } + + function keyof(value) { + return value !== null && typeof value === "object" ? value.valueOf() : value; + } + + function max$1(values, valueof) { + let max; + if (valueof === undefined) { + for (const value of values) { + if (value != null + && (max < value || (max === undefined && value >= value))) { + max = value; + } + } + } else { + let index = -1; + for (let value of values) { + if ((value = valueof(value, ++index, values)) != null + && (max < value || (max === undefined && value >= value))) { + max = value; + } + } + } + return max; + } + + function min$1(values, valueof) { + let min; + if (valueof === undefined) { + for (const value of values) { + if (value != null + && (min > value || (min === undefined && value >= value))) { + min = value; + } + } + } else { + let index = -1; + for (let value of values) { + if ((value = valueof(value, ++index, values)) != null + && (min > value || (min === undefined && value >= value))) { + min = value; + } + } + } + return min; + } + + /** Detect free variable `global` from Node.js. */ + var freeGlobal = typeof global == 'object' && global && global.Object === Object && global; + + var freeGlobal$1 = freeGlobal; + + /** Detect free variable `self`. */ + var freeSelf = typeof self == 'object' && self && self.Object === Object && self; + + /** Used as a reference to the global object. */ + var root = freeGlobal$1 || freeSelf || Function('return this')(); + + var root$1 = root; + + /** Built-in value references. */ + var Symbol$1 = root$1.Symbol; + + var Symbol$2 = Symbol$1; + + /** Used for built-in method references. */ + var objectProto$1 = Object.prototype; + + /** Used to check objects for own properties. */ + var hasOwnProperty = objectProto$1.hasOwnProperty; + + /** + * Used to resolve the + * [`toStringTag`](http://ecma-international.org/ecma-262/7.0/#sec-object.prototype.tostring) + * of values. + */ + var nativeObjectToString$1 = objectProto$1.toString; + + /** Built-in value references. */ + var symToStringTag$1 = Symbol$2 ? Symbol$2.toStringTag : undefined; + + /** + * A specialized version of `baseGetTag` which ignores `Symbol.toStringTag` values. + * + * @private + * @param {*} value The value to query. + * @returns {string} Returns the raw `toStringTag`. + */ + function getRawTag(value) { + var isOwn = hasOwnProperty.call(value, symToStringTag$1), + tag = value[symToStringTag$1]; + + try { + value[symToStringTag$1] = undefined; + var unmasked = true; + } catch (e) {} + + var result = nativeObjectToString$1.call(value); + if (unmasked) { + if (isOwn) { + value[symToStringTag$1] = tag; + } else { + delete value[symToStringTag$1]; + } + } + return result; + } + + /** Used for built-in method references. */ + var objectProto = Object.prototype; + + /** + * Used to resolve the + * [`toStringTag`](http://ecma-international.org/ecma-262/7.0/#sec-object.prototype.tostring) + * of values. + */ + var nativeObjectToString = objectProto.toString; + + /** + * Converts `value` to a string using `Object.prototype.toString`. + * + * @private + * @param {*} value The value to convert. + * @returns {string} Returns the converted string. + */ + function objectToString(value) { + return nativeObjectToString.call(value); + } + + /** `Object#toString` result references. */ + var nullTag = '[object Null]', + undefinedTag = '[object Undefined]'; + + /** Built-in value references. */ + var symToStringTag = Symbol$2 ? Symbol$2.toStringTag : undefined; + + /** + * The base implementation of `getTag` without fallbacks for buggy environments. + * + * @private + * @param {*} value The value to query. + * @returns {string} Returns the `toStringTag`. + */ + function baseGetTag(value) { + if (value == null) { + return value === undefined ? undefinedTag : nullTag; + } + return (symToStringTag && symToStringTag in Object(value)) + ? getRawTag(value) + : objectToString(value); + } + + /** + * Checks if `value` is object-like. A value is object-like if it's not `null` + * and has a `typeof` result of "object". + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is object-like, else `false`. + * @example + * + * _.isObjectLike({}); + * // => true + * + * _.isObjectLike([1, 2, 3]); + * // => true + * + * _.isObjectLike(_.noop); + * // => false + * + * _.isObjectLike(null); + * // => false + */ + function isObjectLike(value) { + return value != null && typeof value == 'object'; + } + + /** `Object#toString` result references. */ + var symbolTag = '[object Symbol]'; + + /** + * Checks if `value` is classified as a `Symbol` primitive or object. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a symbol, else `false`. + * @example + * + * _.isSymbol(Symbol.iterator); + * // => true + * + * _.isSymbol('abc'); + * // => false + */ + function isSymbol(value) { + return typeof value == 'symbol' || + (isObjectLike(value) && baseGetTag(value) == symbolTag); + } + + /** Used to match a single whitespace character. */ + var reWhitespace = /\s/; + + /** + * Used by `_.trim` and `_.trimEnd` to get the index of the last non-whitespace + * character of `string`. + * + * @private + * @param {string} string The string to inspect. + * @returns {number} Returns the index of the last non-whitespace character. + */ + function trimmedEndIndex(string) { + var index = string.length; + + while (index-- && reWhitespace.test(string.charAt(index))) {} + return index; + } + + /** Used to match leading whitespace. */ + var reTrimStart = /^\s+/; + + /** + * The base implementation of `_.trim`. + * + * @private + * @param {string} string The string to trim. + * @returns {string} Returns the trimmed string. + */ + function baseTrim(string) { + return string + ? string.slice(0, trimmedEndIndex(string) + 1).replace(reTrimStart, '') + : string; + } + + /** + * Checks if `value` is the + * [language type](http://www.ecma-international.org/ecma-262/7.0/#sec-ecmascript-language-types) + * of `Object`. (e.g. arrays, functions, objects, regexes, `new Number(0)`, and `new String('')`) + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is an object, else `false`. + * @example + * + * _.isObject({}); + * // => true + * + * _.isObject([1, 2, 3]); + * // => true + * + * _.isObject(_.noop); + * // => true + * + * _.isObject(null); + * // => false + */ + function isObject(value) { + var type = typeof value; + return value != null && (type == 'object' || type == 'function'); + } + + /** Used as references for various `Number` constants. */ + var NAN = 0 / 0; + + /** Used to detect bad signed hexadecimal string values. */ + var reIsBadHex = /^[-+]0x[0-9a-f]+$/i; + + /** Used to detect binary string values. */ + var reIsBinary = /^0b[01]+$/i; + + /** Used to detect octal string values. */ + var reIsOctal = /^0o[0-7]+$/i; + + /** Built-in method references without a dependency on `root`. */ + var freeParseInt = parseInt; + + /** + * Converts `value` to a number. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Lang + * @param {*} value The value to process. + * @returns {number} Returns the number. + * @example + * + * _.toNumber(3.2); + * // => 3.2 + * + * _.toNumber(Number.MIN_VALUE); + * // => 5e-324 + * + * _.toNumber(Infinity); + * // => Infinity + * + * _.toNumber('3.2'); + * // => 3.2 + */ + function toNumber(value) { + if (typeof value == 'number') { + return value; + } + if (isSymbol(value)) { + return NAN; + } + if (isObject(value)) { + var other = typeof value.valueOf == 'function' ? value.valueOf() : value; + value = isObject(other) ? (other + '') : other; + } + if (typeof value != 'string') { + return value === 0 ? value : +value; + } + value = baseTrim(value); + var isBinary = reIsBinary.test(value); + return (isBinary || reIsOctal.test(value)) + ? freeParseInt(value.slice(2), isBinary ? 2 : 8) + : (reIsBadHex.test(value) ? NAN : +value); + } + + /** + * Gets the timestamp of the number of milliseconds that have elapsed since + * the Unix epoch (1 January 1970 00:00:00 UTC). + * + * @static + * @memberOf _ + * @since 2.4.0 + * @category Date + * @returns {number} Returns the timestamp. + * @example + * + * _.defer(function(stamp) { + * console.log(_.now() - stamp); + * }, _.now()); + * // => Logs the number of milliseconds it took for the deferred invocation. + */ + var now$1 = function() { + return root$1.Date.now(); + }; + + var now$2 = now$1; + + /** Error message constants. */ + var FUNC_ERROR_TEXT$1 = 'Expected a function'; + + /* Built-in method references for those with the same name as other `lodash` methods. */ + var nativeMax = Math.max, + nativeMin = Math.min; + + /** + * Creates a debounced function that delays invoking `func` until after `wait` + * milliseconds have elapsed since the last time the debounced function was + * invoked. The debounced function comes with a `cancel` method to cancel + * delayed `func` invocations and a `flush` method to immediately invoke them. + * Provide `options` to indicate whether `func` should be invoked on the + * leading and/or trailing edge of the `wait` timeout. The `func` is invoked + * with the last arguments provided to the debounced function. Subsequent + * calls to the debounced function return the result of the last `func` + * invocation. + * + * **Note:** If `leading` and `trailing` options are `true`, `func` is + * invoked on the trailing edge of the timeout only if the debounced function + * is invoked more than once during the `wait` timeout. + * + * If `wait` is `0` and `leading` is `false`, `func` invocation is deferred + * until to the next tick, similar to `setTimeout` with a timeout of `0`. + * + * See [David Corbacho's article](https://css-tricks.com/debouncing-throttling-explained-examples/) + * for details over the differences between `_.debounce` and `_.throttle`. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Function + * @param {Function} func The function to debounce. + * @param {number} [wait=0] The number of milliseconds to delay. + * @param {Object} [options={}] The options object. + * @param {boolean} [options.leading=false] + * Specify invoking on the leading edge of the timeout. + * @param {number} [options.maxWait] + * The maximum time `func` is allowed to be delayed before it's invoked. + * @param {boolean} [options.trailing=true] + * Specify invoking on the trailing edge of the timeout. + * @returns {Function} Returns the new debounced function. + * @example + * + * // Avoid costly calculations while the window size is in flux. + * jQuery(window).on('resize', _.debounce(calculateLayout, 150)); + * + * // Invoke `sendMail` when clicked, debouncing subsequent calls. + * jQuery(element).on('click', _.debounce(sendMail, 300, { + * 'leading': true, + * 'trailing': false + * })); + * + * // Ensure `batchLog` is invoked once after 1 second of debounced calls. + * var debounced = _.debounce(batchLog, 250, { 'maxWait': 1000 }); + * var source = new EventSource('/stream'); + * jQuery(source).on('message', debounced); + * + * // Cancel the trailing debounced invocation. + * jQuery(window).on('popstate', debounced.cancel); + */ + function debounce(func, wait, options) { + var lastArgs, + lastThis, + maxWait, + result, + timerId, + lastCallTime, + lastInvokeTime = 0, + leading = false, + maxing = false, + trailing = true; + + if (typeof func != 'function') { + throw new TypeError(FUNC_ERROR_TEXT$1); + } + wait = toNumber(wait) || 0; + if (isObject(options)) { + leading = !!options.leading; + maxing = 'maxWait' in options; + maxWait = maxing ? nativeMax(toNumber(options.maxWait) || 0, wait) : maxWait; + trailing = 'trailing' in options ? !!options.trailing : trailing; + } + + function invokeFunc(time) { + var args = lastArgs, + thisArg = lastThis; + + lastArgs = lastThis = undefined; + lastInvokeTime = time; + result = func.apply(thisArg, args); + return result; + } + + function leadingEdge(time) { + // Reset any `maxWait` timer. + lastInvokeTime = time; + // Start the timer for the trailing edge. + timerId = setTimeout(timerExpired, wait); + // Invoke the leading edge. + return leading ? invokeFunc(time) : result; + } + + function remainingWait(time) { + var timeSinceLastCall = time - lastCallTime, + timeSinceLastInvoke = time - lastInvokeTime, + timeWaiting = wait - timeSinceLastCall; + + return maxing + ? nativeMin(timeWaiting, maxWait - timeSinceLastInvoke) + : timeWaiting; + } + + function shouldInvoke(time) { + var timeSinceLastCall = time - lastCallTime, + timeSinceLastInvoke = time - lastInvokeTime; + + // Either this is the first call, activity has stopped and we're at the + // trailing edge, the system time has gone backwards and we're treating + // it as the trailing edge, or we've hit the `maxWait` limit. + return (lastCallTime === undefined || (timeSinceLastCall >= wait) || + (timeSinceLastCall < 0) || (maxing && timeSinceLastInvoke >= maxWait)); + } + + function timerExpired() { + var time = now$2(); + if (shouldInvoke(time)) { + return trailingEdge(time); + } + // Restart the timer. + timerId = setTimeout(timerExpired, remainingWait(time)); + } + + function trailingEdge(time) { + timerId = undefined; + + // Only invoke if we have `lastArgs` which means `func` has been + // debounced at least once. + if (trailing && lastArgs) { + return invokeFunc(time); + } + lastArgs = lastThis = undefined; + return result; + } + + function cancel() { + if (timerId !== undefined) { + clearTimeout(timerId); + } + lastInvokeTime = 0; + lastArgs = lastCallTime = lastThis = timerId = undefined; + } + + function flush() { + return timerId === undefined ? result : trailingEdge(now$2()); + } + + function debounced() { + var time = now$2(), + isInvoking = shouldInvoke(time); + + lastArgs = arguments; + lastThis = this; + lastCallTime = time; + + if (isInvoking) { + if (timerId === undefined) { + return leadingEdge(lastCallTime); + } + if (maxing) { + // Handle invocations in a tight loop. + clearTimeout(timerId); + timerId = setTimeout(timerExpired, wait); + return invokeFunc(lastCallTime); + } + } + if (timerId === undefined) { + timerId = setTimeout(timerExpired, wait); + } + return result; + } + debounced.cancel = cancel; + debounced.flush = flush; + return debounced; + } + + /** Error message constants. */ + var FUNC_ERROR_TEXT = 'Expected a function'; + + /** + * Creates a throttled function that only invokes `func` at most once per + * every `wait` milliseconds. The throttled function comes with a `cancel` + * method to cancel delayed `func` invocations and a `flush` method to + * immediately invoke them. Provide `options` to indicate whether `func` + * should be invoked on the leading and/or trailing edge of the `wait` + * timeout. The `func` is invoked with the last arguments provided to the + * throttled function. Subsequent calls to the throttled function return the + * result of the last `func` invocation. + * + * **Note:** If `leading` and `trailing` options are `true`, `func` is + * invoked on the trailing edge of the timeout only if the throttled function + * is invoked more than once during the `wait` timeout. + * + * If `wait` is `0` and `leading` is `false`, `func` invocation is deferred + * until to the next tick, similar to `setTimeout` with a timeout of `0`. + * + * See [David Corbacho's article](https://css-tricks.com/debouncing-throttling-explained-examples/) + * for details over the differences between `_.throttle` and `_.debounce`. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Function + * @param {Function} func The function to throttle. + * @param {number} [wait=0] The number of milliseconds to throttle invocations to. + * @param {Object} [options={}] The options object. + * @param {boolean} [options.leading=true] + * Specify invoking on the leading edge of the timeout. + * @param {boolean} [options.trailing=true] + * Specify invoking on the trailing edge of the timeout. + * @returns {Function} Returns the new throttled function. + * @example + * + * // Avoid excessively updating the position while scrolling. + * jQuery(window).on('scroll', _.throttle(updatePosition, 100)); + * + * // Invoke `renewToken` when the click event is fired, but not more than once every 5 minutes. + * var throttled = _.throttle(renewToken, 300000, { 'trailing': false }); + * jQuery(element).on('click', throttled); + * + * // Cancel the trailing throttled invocation. + * jQuery(window).on('popstate', throttled.cancel); + */ + function throttle(func, wait, options) { + var leading = true, + trailing = true; + + if (typeof func != 'function') { + throw new TypeError(FUNC_ERROR_TEXT); + } + if (isObject(options)) { + leading = 'leading' in options ? !!options.leading : leading; + trailing = 'trailing' in options ? !!options.trailing : trailing; + } + return debounce(func, wait, { + 'leading': leading, + 'maxWait': wait, + 'trailing': trailing + }); + } + + /** + * The Ease class provides a collection of easing functions for use with tween.js. + */ + var Easing = Object.freeze({ + Linear: Object.freeze({ + None: function (amount) { + return amount; + }, + In: function (amount) { + return this.None(amount); + }, + Out: function (amount) { + return this.None(amount); + }, + InOut: function (amount) { + return this.None(amount); + }, + }), + Quadratic: Object.freeze({ + In: function (amount) { + return amount * amount; + }, + Out: function (amount) { + return amount * (2 - amount); + }, + InOut: function (amount) { + if ((amount *= 2) < 1) { + return 0.5 * amount * amount; + } + return -0.5 * (--amount * (amount - 2) - 1); + }, + }), + Cubic: Object.freeze({ + In: function (amount) { + return amount * amount * amount; + }, + Out: function (amount) { + return --amount * amount * amount + 1; + }, + InOut: function (amount) { + if ((amount *= 2) < 1) { + return 0.5 * amount * amount * amount; + } + return 0.5 * ((amount -= 2) * amount * amount + 2); + }, + }), + Quartic: Object.freeze({ + In: function (amount) { + return amount * amount * amount * amount; + }, + Out: function (amount) { + return 1 - --amount * amount * amount * amount; + }, + InOut: function (amount) { + if ((amount *= 2) < 1) { + return 0.5 * amount * amount * amount * amount; + } + return -0.5 * ((amount -= 2) * amount * amount * amount - 2); + }, + }), + Quintic: Object.freeze({ + In: function (amount) { + return amount * amount * amount * amount * amount; + }, + Out: function (amount) { + return --amount * amount * amount * amount * amount + 1; + }, + InOut: function (amount) { + if ((amount *= 2) < 1) { + return 0.5 * amount * amount * amount * amount * amount; + } + return 0.5 * ((amount -= 2) * amount * amount * amount * amount + 2); + }, + }), + Sinusoidal: Object.freeze({ + In: function (amount) { + return 1 - Math.sin(((1.0 - amount) * Math.PI) / 2); + }, + Out: function (amount) { + return Math.sin((amount * Math.PI) / 2); + }, + InOut: function (amount) { + return 0.5 * (1 - Math.sin(Math.PI * (0.5 - amount))); + }, + }), + Exponential: Object.freeze({ + In: function (amount) { + return amount === 0 ? 0 : Math.pow(1024, amount - 1); + }, + Out: function (amount) { + return amount === 1 ? 1 : 1 - Math.pow(2, -10 * amount); + }, + InOut: function (amount) { + if (amount === 0) { + return 0; + } + if (amount === 1) { + return 1; + } + if ((amount *= 2) < 1) { + return 0.5 * Math.pow(1024, amount - 1); + } + return 0.5 * (-Math.pow(2, -10 * (amount - 1)) + 2); + }, + }), + Circular: Object.freeze({ + In: function (amount) { + return 1 - Math.sqrt(1 - amount * amount); + }, + Out: function (amount) { + return Math.sqrt(1 - --amount * amount); + }, + InOut: function (amount) { + if ((amount *= 2) < 1) { + return -0.5 * (Math.sqrt(1 - amount * amount) - 1); + } + return 0.5 * (Math.sqrt(1 - (amount -= 2) * amount) + 1); + }, + }), + Elastic: Object.freeze({ + In: function (amount) { + if (amount === 0) { + return 0; + } + if (amount === 1) { + return 1; + } + return -Math.pow(2, 10 * (amount - 1)) * Math.sin((amount - 1.1) * 5 * Math.PI); + }, + Out: function (amount) { + if (amount === 0) { + return 0; + } + if (amount === 1) { + return 1; + } + return Math.pow(2, -10 * amount) * Math.sin((amount - 0.1) * 5 * Math.PI) + 1; + }, + InOut: function (amount) { + if (amount === 0) { + return 0; + } + if (amount === 1) { + return 1; + } + amount *= 2; + if (amount < 1) { + return -0.5 * Math.pow(2, 10 * (amount - 1)) * Math.sin((amount - 1.1) * 5 * Math.PI); + } + return 0.5 * Math.pow(2, -10 * (amount - 1)) * Math.sin((amount - 1.1) * 5 * Math.PI) + 1; + }, + }), + Back: Object.freeze({ + In: function (amount) { + var s = 1.70158; + return amount === 1 ? 1 : amount * amount * ((s + 1) * amount - s); + }, + Out: function (amount) { + var s = 1.70158; + return amount === 0 ? 0 : --amount * amount * ((s + 1) * amount + s) + 1; + }, + InOut: function (amount) { + var s = 1.70158 * 1.525; + if ((amount *= 2) < 1) { + return 0.5 * (amount * amount * ((s + 1) * amount - s)); + } + return 0.5 * ((amount -= 2) * amount * ((s + 1) * amount + s) + 2); + }, + }), + Bounce: Object.freeze({ + In: function (amount) { + return 1 - Easing.Bounce.Out(1 - amount); + }, + Out: function (amount) { + if (amount < 1 / 2.75) { + return 7.5625 * amount * amount; + } + else if (amount < 2 / 2.75) { + return 7.5625 * (amount -= 1.5 / 2.75) * amount + 0.75; + } + else if (amount < 2.5 / 2.75) { + return 7.5625 * (amount -= 2.25 / 2.75) * amount + 0.9375; + } + else { + return 7.5625 * (amount -= 2.625 / 2.75) * amount + 0.984375; + } + }, + InOut: function (amount) { + if (amount < 0.5) { + return Easing.Bounce.In(amount * 2) * 0.5; + } + return Easing.Bounce.Out(amount * 2 - 1) * 0.5 + 0.5; + }, + }), + generatePow: function (power) { + if (power === void 0) { power = 4; } + power = power < Number.EPSILON ? Number.EPSILON : power; + power = power > 10000 ? 10000 : power; + return { + In: function (amount) { + return Math.pow(amount, power); + }, + Out: function (amount) { + return 1 - Math.pow((1 - amount), power); + }, + InOut: function (amount) { + if (amount < 0.5) { + return Math.pow((amount * 2), power) / 2; + } + return (1 - Math.pow((2 - amount * 2), power)) / 2 + 0.5; + }, + }; + }, + }); + + var now = function () { return performance.now(); }; + + /** + * Controlling groups of tweens + * + * Using the TWEEN singleton to manage your tweens can cause issues in large apps with many components. + * In these cases, you may want to create your own smaller groups of tween + */ + var Group = /** @class */ (function () { + function Group() { + this._tweens = {}; + this._tweensAddedDuringUpdate = {}; + } + Group.prototype.getAll = function () { + var _this = this; + return Object.keys(this._tweens).map(function (tweenId) { + return _this._tweens[tweenId]; + }); + }; + Group.prototype.removeAll = function () { + this._tweens = {}; + }; + Group.prototype.add = function (tween) { + this._tweens[tween.getId()] = tween; + this._tweensAddedDuringUpdate[tween.getId()] = tween; + }; + Group.prototype.remove = function (tween) { + delete this._tweens[tween.getId()]; + delete this._tweensAddedDuringUpdate[tween.getId()]; + }; + Group.prototype.update = function (time, preserve) { + if (time === void 0) { time = now(); } + if (preserve === void 0) { preserve = false; } + var tweenIds = Object.keys(this._tweens); + if (tweenIds.length === 0) { + return false; + } + // Tweens are updated in "batches". If you add a new tween during an + // update, then the new tween will be updated in the next batch. + // If you remove a tween during an update, it may or may not be updated. + // However, if the removed tween was added during the current batch, + // then it will not be updated. + while (tweenIds.length > 0) { + this._tweensAddedDuringUpdate = {}; + for (var i = 0; i < tweenIds.length; i++) { + var tween = this._tweens[tweenIds[i]]; + var autoStart = !preserve; + if (tween && tween.update(time, autoStart) === false && !preserve) { + delete this._tweens[tweenIds[i]]; + } + } + tweenIds = Object.keys(this._tweensAddedDuringUpdate); + } + return true; + }; + return Group; + }()); + + /** + * + */ + var Interpolation = { + Linear: function (v, k) { + var m = v.length - 1; + var f = m * k; + var i = Math.floor(f); + var fn = Interpolation.Utils.Linear; + if (k < 0) { + return fn(v[0], v[1], f); + } + if (k > 1) { + return fn(v[m], v[m - 1], m - f); + } + return fn(v[i], v[i + 1 > m ? m : i + 1], f - i); + }, + Bezier: function (v, k) { + var b = 0; + var n = v.length - 1; + var pw = Math.pow; + var bn = Interpolation.Utils.Bernstein; + for (var i = 0; i <= n; i++) { + b += pw(1 - k, n - i) * pw(k, i) * v[i] * bn(n, i); + } + return b; + }, + CatmullRom: function (v, k) { + var m = v.length - 1; + var f = m * k; + var i = Math.floor(f); + var fn = Interpolation.Utils.CatmullRom; + if (v[0] === v[m]) { + if (k < 0) { + i = Math.floor((f = m * (1 + k))); + } + return fn(v[(i - 1 + m) % m], v[i], v[(i + 1) % m], v[(i + 2) % m], f - i); + } + else { + if (k < 0) { + return v[0] - (fn(v[0], v[0], v[1], v[1], -f) - v[0]); + } + if (k > 1) { + return v[m] - (fn(v[m], v[m], v[m - 1], v[m - 1], f - m) - v[m]); + } + return fn(v[i ? i - 1 : 0], v[i], v[m < i + 1 ? m : i + 1], v[m < i + 2 ? m : i + 2], f - i); + } + }, + Utils: { + Linear: function (p0, p1, t) { + return (p1 - p0) * t + p0; + }, + Bernstein: function (n, i) { + var fc = Interpolation.Utils.Factorial; + return fc(n) / fc(i) / fc(n - i); + }, + Factorial: (function () { + var a = [1]; + return function (n) { + var s = 1; + if (a[n]) { + return a[n]; + } + for (var i = n; i > 1; i--) { + s *= i; + } + a[n] = s; + return s; + }; + })(), + CatmullRom: function (p0, p1, p2, p3, t) { + var v0 = (p2 - p0) * 0.5; + var v1 = (p3 - p1) * 0.5; + var t2 = t * t; + var t3 = t * t2; + return (2 * p1 - 2 * p2 + v0 + v1) * t3 + (-3 * p1 + 3 * p2 - 2 * v0 - v1) * t2 + v0 * t + p1; + }, + }, + }; + + /** + * Utils + */ + var Sequence = /** @class */ (function () { + function Sequence() { + } + Sequence.nextId = function () { + return Sequence._nextId++; + }; + Sequence._nextId = 0; + return Sequence; + }()); + + var mainGroup = new Group(); + + /** + * Tween.js - Licensed under the MIT license + * https://github.com/tweenjs/tween.js + * ---------------------------------------------- + * + * See https://github.com/tweenjs/tween.js/graphs/contributors for the full list of contributors. + * Thank you all, you're awesome! + */ + var Tween = /** @class */ (function () { + function Tween(_object, _group) { + if (_group === void 0) { _group = mainGroup; } + this._object = _object; + this._group = _group; + this._isPaused = false; + this._pauseStart = 0; + this._valuesStart = {}; + this._valuesEnd = {}; + this._valuesStartRepeat = {}; + this._duration = 1000; + this._isDynamic = false; + this._initialRepeat = 0; + this._repeat = 0; + this._yoyo = false; + this._isPlaying = false; + this._reversed = false; + this._delayTime = 0; + this._startTime = 0; + this._easingFunction = Easing.Linear.None; + this._interpolationFunction = Interpolation.Linear; + // eslint-disable-next-line + this._chainedTweens = []; + this._onStartCallbackFired = false; + this._onEveryStartCallbackFired = false; + this._id = Sequence.nextId(); + this._isChainStopped = false; + this._propertiesAreSetUp = false; + this._goToEnd = false; + } + Tween.prototype.getId = function () { + return this._id; + }; + Tween.prototype.isPlaying = function () { + return this._isPlaying; + }; + Tween.prototype.isPaused = function () { + return this._isPaused; + }; + Tween.prototype.to = function (target, duration) { + if (duration === void 0) { duration = 1000; } + if (this._isPlaying) + throw new Error('Can not call Tween.to() while Tween is already started or paused. Stop the Tween first.'); + this._valuesEnd = target; + this._propertiesAreSetUp = false; + this._duration = duration; + return this; + }; + Tween.prototype.duration = function (duration) { + if (duration === void 0) { duration = 1000; } + this._duration = duration; + return this; + }; + Tween.prototype.dynamic = function (dynamic) { + if (dynamic === void 0) { dynamic = false; } + this._isDynamic = dynamic; + return this; + }; + Tween.prototype.start = function (time, overrideStartingValues) { + if (time === void 0) { time = now(); } + if (overrideStartingValues === void 0) { overrideStartingValues = false; } + if (this._isPlaying) { + return this; + } + // eslint-disable-next-line + this._group && this._group.add(this); + this._repeat = this._initialRepeat; + if (this._reversed) { + // If we were reversed (f.e. using the yoyo feature) then we need to + // flip the tween direction back to forward. + this._reversed = false; + for (var property in this._valuesStartRepeat) { + this._swapEndStartRepeatValues(property); + this._valuesStart[property] = this._valuesStartRepeat[property]; + } + } + this._isPlaying = true; + this._isPaused = false; + this._onStartCallbackFired = false; + this._onEveryStartCallbackFired = false; + this._isChainStopped = false; + this._startTime = time; + this._startTime += this._delayTime; + if (!this._propertiesAreSetUp || overrideStartingValues) { + this._propertiesAreSetUp = true; + // If dynamic is not enabled, clone the end values instead of using the passed-in end values. + if (!this._isDynamic) { + var tmp = {}; + for (var prop in this._valuesEnd) + tmp[prop] = this._valuesEnd[prop]; + this._valuesEnd = tmp; + } + this._setupProperties(this._object, this._valuesStart, this._valuesEnd, this._valuesStartRepeat, overrideStartingValues); + } + return this; + }; + Tween.prototype.startFromCurrentValues = function (time) { + return this.start(time, true); + }; + Tween.prototype._setupProperties = function (_object, _valuesStart, _valuesEnd, _valuesStartRepeat, overrideStartingValues) { + for (var property in _valuesEnd) { + var startValue = _object[property]; + var startValueIsArray = Array.isArray(startValue); + var propType = startValueIsArray ? 'array' : typeof startValue; + var isInterpolationList = !startValueIsArray && Array.isArray(_valuesEnd[property]); + // If `to()` specifies a property that doesn't exist in the source object, + // we should not set that property in the object + if (propType === 'undefined' || propType === 'function') { + continue; + } + // Check if an Array was provided as property value + if (isInterpolationList) { + var endValues = _valuesEnd[property]; + if (endValues.length === 0) { + continue; + } + // Handle an array of relative values. + // Creates a local copy of the Array with the start value at the front + var temp = [startValue]; + for (var i = 0, l = endValues.length; i < l; i += 1) { + var value = this._handleRelativeValue(startValue, endValues[i]); + if (isNaN(value)) { + isInterpolationList = false; + console.warn('Found invalid interpolation list. Skipping.'); + break; + } + temp.push(value); + } + if (isInterpolationList) { + // if (_valuesStart[property] === undefined) { // handle end values only the first time. NOT NEEDED? setupProperties is now guarded by _propertiesAreSetUp. + _valuesEnd[property] = temp; + // } + } + } + // handle the deepness of the values + if ((propType === 'object' || startValueIsArray) && startValue && !isInterpolationList) { + _valuesStart[property] = startValueIsArray ? [] : {}; + var nestedObject = startValue; + for (var prop in nestedObject) { + _valuesStart[property][prop] = nestedObject[prop]; + } + // TODO? repeat nested values? And yoyo? And array values? + _valuesStartRepeat[property] = startValueIsArray ? [] : {}; + var endValues = _valuesEnd[property]; + // If dynamic is not enabled, clone the end values instead of using the passed-in end values. + if (!this._isDynamic) { + var tmp = {}; + for (var prop in endValues) + tmp[prop] = endValues[prop]; + _valuesEnd[property] = endValues = tmp; + } + this._setupProperties(nestedObject, _valuesStart[property], endValues, _valuesStartRepeat[property], overrideStartingValues); + } + else { + // Save the starting value, but only once unless override is requested. + if (typeof _valuesStart[property] === 'undefined' || overrideStartingValues) { + _valuesStart[property] = startValue; + } + if (!startValueIsArray) { + // eslint-disable-next-line + // @ts-ignore FIXME? + _valuesStart[property] *= 1.0; // Ensures we're using numbers, not strings + } + if (isInterpolationList) { + // eslint-disable-next-line + // @ts-ignore FIXME? + _valuesStartRepeat[property] = _valuesEnd[property].slice().reverse(); + } + else { + _valuesStartRepeat[property] = _valuesStart[property] || 0; + } + } + } + }; + Tween.prototype.stop = function () { + if (!this._isChainStopped) { + this._isChainStopped = true; + this.stopChainedTweens(); + } + if (!this._isPlaying) { + return this; + } + // eslint-disable-next-line + this._group && this._group.remove(this); + this._isPlaying = false; + this._isPaused = false; + if (this._onStopCallback) { + this._onStopCallback(this._object); + } + return this; + }; + Tween.prototype.end = function () { + this._goToEnd = true; + this.update(Infinity); + return this; + }; + Tween.prototype.pause = function (time) { + if (time === void 0) { time = now(); } + if (this._isPaused || !this._isPlaying) { + return this; + } + this._isPaused = true; + this._pauseStart = time; + // eslint-disable-next-line + this._group && this._group.remove(this); + return this; + }; + Tween.prototype.resume = function (time) { + if (time === void 0) { time = now(); } + if (!this._isPaused || !this._isPlaying) { + return this; + } + this._isPaused = false; + this._startTime += time - this._pauseStart; + this._pauseStart = 0; + // eslint-disable-next-line + this._group && this._group.add(this); + return this; + }; + Tween.prototype.stopChainedTweens = function () { + for (var i = 0, numChainedTweens = this._chainedTweens.length; i < numChainedTweens; i++) { + this._chainedTweens[i].stop(); + } + return this; + }; + Tween.prototype.group = function (group) { + if (group === void 0) { group = mainGroup; } + this._group = group; + return this; + }; + Tween.prototype.delay = function (amount) { + if (amount === void 0) { amount = 0; } + this._delayTime = amount; + return this; + }; + Tween.prototype.repeat = function (times) { + if (times === void 0) { times = 0; } + this._initialRepeat = times; + this._repeat = times; + return this; + }; + Tween.prototype.repeatDelay = function (amount) { + this._repeatDelayTime = amount; + return this; + }; + Tween.prototype.yoyo = function (yoyo) { + if (yoyo === void 0) { yoyo = false; } + this._yoyo = yoyo; + return this; + }; + Tween.prototype.easing = function (easingFunction) { + if (easingFunction === void 0) { easingFunction = Easing.Linear.None; } + this._easingFunction = easingFunction; + return this; + }; + Tween.prototype.interpolation = function (interpolationFunction) { + if (interpolationFunction === void 0) { interpolationFunction = Interpolation.Linear; } + this._interpolationFunction = interpolationFunction; + return this; + }; + // eslint-disable-next-line + Tween.prototype.chain = function () { + var tweens = []; + for (var _i = 0; _i < arguments.length; _i++) { + tweens[_i] = arguments[_i]; + } + this._chainedTweens = tweens; + return this; + }; + Tween.prototype.onStart = function (callback) { + this._onStartCallback = callback; + return this; + }; + Tween.prototype.onEveryStart = function (callback) { + this._onEveryStartCallback = callback; + return this; + }; + Tween.prototype.onUpdate = function (callback) { + this._onUpdateCallback = callback; + return this; + }; + Tween.prototype.onRepeat = function (callback) { + this._onRepeatCallback = callback; + return this; + }; + Tween.prototype.onComplete = function (callback) { + this._onCompleteCallback = callback; + return this; + }; + Tween.prototype.onStop = function (callback) { + this._onStopCallback = callback; + return this; + }; + /** + * @returns true if the tween is still playing after the update, false + * otherwise (calling update on a paused tween still returns true because + * it is still playing, just paused). + */ + Tween.prototype.update = function (time, autoStart) { + if (time === void 0) { time = now(); } + if (autoStart === void 0) { autoStart = true; } + if (this._isPaused) + return true; + var property; + var elapsed; + var endTime = this._startTime + this._duration; + if (!this._goToEnd && !this._isPlaying) { + if (time > endTime) + return false; + if (autoStart) + this.start(time, true); + } + this._goToEnd = false; + if (time < this._startTime) { + return true; + } + if (this._onStartCallbackFired === false) { + if (this._onStartCallback) { + this._onStartCallback(this._object); + } + this._onStartCallbackFired = true; + } + if (this._onEveryStartCallbackFired === false) { + if (this._onEveryStartCallback) { + this._onEveryStartCallback(this._object); + } + this._onEveryStartCallbackFired = true; + } + elapsed = (time - this._startTime) / this._duration; + elapsed = this._duration === 0 || elapsed > 1 ? 1 : elapsed; + var value = this._easingFunction(elapsed); + // properties transformations + this._updateProperties(this._object, this._valuesStart, this._valuesEnd, value); + if (this._onUpdateCallback) { + this._onUpdateCallback(this._object, elapsed); + } + if (elapsed === 1) { + if (this._repeat > 0) { + if (isFinite(this._repeat)) { + this._repeat--; + } + // Reassign starting values, restart by making startTime = now + for (property in this._valuesStartRepeat) { + if (!this._yoyo && typeof this._valuesEnd[property] === 'string') { + this._valuesStartRepeat[property] = + // eslint-disable-next-line + // @ts-ignore FIXME? + this._valuesStartRepeat[property] + parseFloat(this._valuesEnd[property]); + } + if (this._yoyo) { + this._swapEndStartRepeatValues(property); + } + this._valuesStart[property] = this._valuesStartRepeat[property]; + } + if (this._yoyo) { + this._reversed = !this._reversed; + } + if (this._repeatDelayTime !== undefined) { + this._startTime = time + this._repeatDelayTime; + } + else { + this._startTime = time + this._delayTime; + } + if (this._onRepeatCallback) { + this._onRepeatCallback(this._object); + } + this._onEveryStartCallbackFired = false; + return true; + } + else { + if (this._onCompleteCallback) { + this._onCompleteCallback(this._object); + } + for (var i = 0, numChainedTweens = this._chainedTweens.length; i < numChainedTweens; i++) { + // Make the chained tweens start exactly at the time they should, + // even if the `update()` method was called way past the duration of the tween + this._chainedTweens[i].start(this._startTime + this._duration, false); + } + this._isPlaying = false; + return false; + } + } + return true; + }; + Tween.prototype._updateProperties = function (_object, _valuesStart, _valuesEnd, value) { + for (var property in _valuesEnd) { + // Don't update properties that do not exist in the source object + if (_valuesStart[property] === undefined) { + continue; + } + var start = _valuesStart[property] || 0; + var end = _valuesEnd[property]; + var startIsArray = Array.isArray(_object[property]); + var endIsArray = Array.isArray(end); + var isInterpolationList = !startIsArray && endIsArray; + if (isInterpolationList) { + _object[property] = this._interpolationFunction(end, value); + } + else if (typeof end === 'object' && end) { + // eslint-disable-next-line + // @ts-ignore FIXME? + this._updateProperties(_object[property], start, end, value); + } + else { + // Parses relative end values with start as base (e.g.: +10, -3) + end = this._handleRelativeValue(start, end); + // Protect against non numeric properties. + if (typeof end === 'number') { + // eslint-disable-next-line + // @ts-ignore FIXME? + _object[property] = start + (end - start) * value; + } + } + } + }; + Tween.prototype._handleRelativeValue = function (start, end) { + if (typeof end !== 'string') { + return end; + } + if (end.charAt(0) === '+' || end.charAt(0) === '-') { + return start + parseFloat(end); + } + return parseFloat(end); + }; + Tween.prototype._swapEndStartRepeatValues = function (property) { + var tmp = this._valuesStartRepeat[property]; + var endValue = this._valuesEnd[property]; + if (typeof endValue === 'string') { + this._valuesStartRepeat[property] = this._valuesStartRepeat[property] + parseFloat(endValue); + } + else { + this._valuesStartRepeat[property] = this._valuesEnd[property]; + } + this._valuesEnd[property] = tmp; + }; + return Tween; + }()); + /** + * Controlling groups of tweens + * + * Using the TWEEN singleton to manage your tweens can cause issues in large apps with many components. + * In these cases, you may want to create your own smaller groups of tweens. + */ + var TWEEN = mainGroup; + // This is the best way to export things in a way that's compatible with both ES + // Modules and CommonJS, without build hacks, and so as not to break the + // existing API. + // https://github.com/rollup/rollup/issues/1961#issuecomment-423037881 + TWEEN.getAll.bind(TWEEN); + TWEEN.removeAll.bind(TWEEN); + TWEEN.add.bind(TWEEN); + TWEEN.remove.bind(TWEEN); + var update = TWEEN.update.bind(TWEEN); + + function _iterableToArrayLimit$1(arr, i) { + var _i = null == arr ? null : "undefined" != typeof Symbol && arr[Symbol.iterator] || arr["@@iterator"]; + if (null != _i) { + var _s, + _e, + _x, + _r, + _arr = [], + _n = !0, + _d = !1; + try { + if (_x = (_i = _i.call(arr)).next, 0 === i) { + if (Object(_i) !== _i) return; + _n = !1; + } else for (; !(_n = (_s = _x.call(_i)).done) && (_arr.push(_s.value), _arr.length !== i); _n = !0); + } catch (err) { + _d = !0, _e = err; + } finally { + try { + if (!_n && null != _i.return && (_r = _i.return(), Object(_r) !== _r)) return; + } finally { + if (_d) throw _e; + } + } + return _arr; + } + } + function _classCallCheck$1(instance, Constructor) { + if (!(instance instanceof Constructor)) { + throw new TypeError("Cannot call a class as a function"); + } + } + function _defineProperties$1(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, _toPropertyKey$2(descriptor.key), descriptor); + } + } + function _createClass$1(Constructor, protoProps, staticProps) { + if (protoProps) _defineProperties$1(Constructor.prototype, protoProps); + if (staticProps) _defineProperties$1(Constructor, staticProps); + Object.defineProperty(Constructor, "prototype", { + writable: false + }); + return Constructor; + } + function _slicedToArray$1(arr, i) { + return _arrayWithHoles$1(arr) || _iterableToArrayLimit$1(arr, i) || _unsupportedIterableToArray$2(arr, i) || _nonIterableRest$1(); + } + function _arrayWithHoles$1(arr) { + if (Array.isArray(arr)) return arr; + } + function _unsupportedIterableToArray$2(o, minLen) { + if (!o) return; + if (typeof o === "string") return _arrayLikeToArray$2(o, minLen); + var n = Object.prototype.toString.call(o).slice(8, -1); + if (n === "Object" && o.constructor) n = o.constructor.name; + if (n === "Map" || n === "Set") return Array.from(o); + if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray$2(o, minLen); + } + function _arrayLikeToArray$2(arr, len) { + if (len == null || len > arr.length) len = arr.length; + for (var i = 0, arr2 = new Array(len); i < len; i++) arr2[i] = arr[i]; + return arr2; + } + function _nonIterableRest$1() { + throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); + } + function _toPrimitive$2(input, hint) { + if (typeof input !== "object" || input === null) return input; + var prim = input[Symbol.toPrimitive]; + if (prim !== undefined) { + var res = prim.call(input, hint || "default"); + if (typeof res !== "object") return res; + throw new TypeError("@@toPrimitive must return a primitive value."); + } + return (hint === "string" ? String : Number)(input); + } + function _toPropertyKey$2(arg) { + var key = _toPrimitive$2(arg, "string"); + return typeof key === "symbol" ? key : String(key); + } + + var Prop = /*#__PURE__*/_createClass$1(function Prop(name, _ref) { + var _ref$default = _ref["default"], + defaultVal = _ref$default === void 0 ? null : _ref$default, + _ref$triggerUpdate = _ref.triggerUpdate, + triggerUpdate = _ref$triggerUpdate === void 0 ? true : _ref$triggerUpdate, + _ref$onChange = _ref.onChange, + onChange = _ref$onChange === void 0 ? function (newVal, state) {} : _ref$onChange; + _classCallCheck$1(this, Prop); + this.name = name; + this.defaultVal = defaultVal; + this.triggerUpdate = triggerUpdate; + this.onChange = onChange; + }); + function index$3 (_ref2) { + var _ref2$stateInit = _ref2.stateInit, + stateInit = _ref2$stateInit === void 0 ? function () { + return {}; + } : _ref2$stateInit, + _ref2$props = _ref2.props, + rawProps = _ref2$props === void 0 ? {} : _ref2$props, + _ref2$methods = _ref2.methods, + methods = _ref2$methods === void 0 ? {} : _ref2$methods, + _ref2$aliases = _ref2.aliases, + aliases = _ref2$aliases === void 0 ? {} : _ref2$aliases, + _ref2$init = _ref2.init, + initFn = _ref2$init === void 0 ? function () {} : _ref2$init, + _ref2$update = _ref2.update, + updateFn = _ref2$update === void 0 ? function () {} : _ref2$update; + // Parse props into Prop instances + var props = Object.keys(rawProps).map(function (propName) { + return new Prop(propName, rawProps[propName]); + }); + return function () { + var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; + // Holds component state + var state = Object.assign({}, stateInit instanceof Function ? stateInit(options) : stateInit, + // Support plain objects for backwards compatibility + { + initialised: false + }); + + // keeps track of which props triggered an update + var changedProps = {}; + + // Component constructor + function comp(nodeElement) { + initStatic(nodeElement, options); + digest(); + return comp; + } + var initStatic = function initStatic(nodeElement, options) { + initFn.call(comp, nodeElement, state, options); + state.initialised = true; + }; + var digest = debounce(function () { + if (!state.initialised) { + return; + } + updateFn.call(comp, state, changedProps); + changedProps = {}; + }, 1); + + // Getter/setter methods + props.forEach(function (prop) { + comp[prop.name] = getSetProp(prop); + function getSetProp(_ref3) { + var prop = _ref3.name, + _ref3$triggerUpdate = _ref3.triggerUpdate, + redigest = _ref3$triggerUpdate === void 0 ? false : _ref3$triggerUpdate, + _ref3$onChange = _ref3.onChange, + onChange = _ref3$onChange === void 0 ? function (newVal, state) {} : _ref3$onChange, + _ref3$defaultVal = _ref3.defaultVal, + defaultVal = _ref3$defaultVal === void 0 ? null : _ref3$defaultVal; + return function (_) { + var curVal = state[prop]; + if (!arguments.length) { + return curVal; + } // Getter mode + + var val = _ === undefined ? defaultVal : _; // pick default if value passed is undefined + state[prop] = val; + onChange.call(comp, val, state, curVal); + + // track changed props + !changedProps.hasOwnProperty(prop) && (changedProps[prop] = curVal); + if (redigest) { + digest(); + } + return comp; + }; + } + }); + + // Other methods + Object.keys(methods).forEach(function (methodName) { + comp[methodName] = function () { + var _methods$methodName; + for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) { + args[_key] = arguments[_key]; + } + return (_methods$methodName = methods[methodName]).call.apply(_methods$methodName, [comp, state].concat(args)); + }; + }); + + // Link aliases + Object.entries(aliases).forEach(function (_ref4) { + var _ref5 = _slicedToArray$1(_ref4, 2), + alias = _ref5[0], + target = _ref5[1]; + return comp[alias] = comp[target]; + }); + + // Reset all component props to their default value + comp.resetProps = function () { + props.forEach(function (prop) { + comp[prop.name](prop.defaultVal); + }); + return comp; + }; + + // + + comp.resetProps(); // Apply all prop defaults + state._rerender = digest; // Expose digest method + + return comp; + }; + } + + var index$2 = (function (p) { + return typeof p === 'function' ? p // fn + : typeof p === 'string' ? function (obj) { + return obj[p]; + } // property name + : function (obj) { + return p; + }; + }); // constant + + // This file is autogenerated. It's used to publish ESM to npm. + function _typeof(obj) { + "@babel/helpers - typeof"; + + return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (obj) { + return typeof obj; + } : function (obj) { + return obj && "function" == typeof Symbol && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; + }, _typeof(obj); + } + + // https://github.com/bgrins/TinyColor + // Brian Grinstead, MIT License + + var trimLeft = /^\s+/; + var trimRight = /\s+$/; + function tinycolor(color, opts) { + color = color ? color : ""; + opts = opts || {}; + + // If input is already a tinycolor, return itself + if (color instanceof tinycolor) { + return color; + } + // If we are called as a function, call using new instead + if (!(this instanceof tinycolor)) { + return new tinycolor(color, opts); + } + var rgb = inputToRGB(color); + this._originalInput = color, this._r = rgb.r, this._g = rgb.g, this._b = rgb.b, this._a = rgb.a, this._roundA = Math.round(100 * this._a) / 100, this._format = opts.format || rgb.format; + this._gradientType = opts.gradientType; + + // Don't let the range of [0,255] come back in [0,1]. + // Potentially lose a little bit of precision here, but will fix issues where + // .5 gets interpreted as half of the total, instead of half of 1 + // If it was supposed to be 128, this was already taken care of by `inputToRgb` + if (this._r < 1) this._r = Math.round(this._r); + if (this._g < 1) this._g = Math.round(this._g); + if (this._b < 1) this._b = Math.round(this._b); + this._ok = rgb.ok; + } + tinycolor.prototype = { + isDark: function isDark() { + return this.getBrightness() < 128; + }, + isLight: function isLight() { + return !this.isDark(); + }, + isValid: function isValid() { + return this._ok; + }, + getOriginalInput: function getOriginalInput() { + return this._originalInput; + }, + getFormat: function getFormat() { + return this._format; + }, + getAlpha: function getAlpha() { + return this._a; + }, + getBrightness: function getBrightness() { + //http://www.w3.org/TR/AERT#color-contrast + var rgb = this.toRgb(); + return (rgb.r * 299 + rgb.g * 587 + rgb.b * 114) / 1000; + }, + getLuminance: function getLuminance() { + //http://www.w3.org/TR/2008/REC-WCAG20-20081211/#relativeluminancedef + var rgb = this.toRgb(); + var RsRGB, GsRGB, BsRGB, R, G, B; + RsRGB = rgb.r / 255; + GsRGB = rgb.g / 255; + BsRGB = rgb.b / 255; + if (RsRGB <= 0.03928) R = RsRGB / 12.92;else R = Math.pow((RsRGB + 0.055) / 1.055, 2.4); + if (GsRGB <= 0.03928) G = GsRGB / 12.92;else G = Math.pow((GsRGB + 0.055) / 1.055, 2.4); + if (BsRGB <= 0.03928) B = BsRGB / 12.92;else B = Math.pow((BsRGB + 0.055) / 1.055, 2.4); + return 0.2126 * R + 0.7152 * G + 0.0722 * B; + }, + setAlpha: function setAlpha(value) { + this._a = boundAlpha(value); + this._roundA = Math.round(100 * this._a) / 100; + return this; + }, + toHsv: function toHsv() { + var hsv = rgbToHsv(this._r, this._g, this._b); + return { + h: hsv.h * 360, + s: hsv.s, + v: hsv.v, + a: this._a + }; + }, + toHsvString: function toHsvString() { + var hsv = rgbToHsv(this._r, this._g, this._b); + var h = Math.round(hsv.h * 360), + s = Math.round(hsv.s * 100), + v = Math.round(hsv.v * 100); + return this._a == 1 ? "hsv(" + h + ", " + s + "%, " + v + "%)" : "hsva(" + h + ", " + s + "%, " + v + "%, " + this._roundA + ")"; + }, + toHsl: function toHsl() { + var hsl = rgbToHsl(this._r, this._g, this._b); + return { + h: hsl.h * 360, + s: hsl.s, + l: hsl.l, + a: this._a + }; + }, + toHslString: function toHslString() { + var hsl = rgbToHsl(this._r, this._g, this._b); + var h = Math.round(hsl.h * 360), + s = Math.round(hsl.s * 100), + l = Math.round(hsl.l * 100); + return this._a == 1 ? "hsl(" + h + ", " + s + "%, " + l + "%)" : "hsla(" + h + ", " + s + "%, " + l + "%, " + this._roundA + ")"; + }, + toHex: function toHex(allow3Char) { + return rgbToHex(this._r, this._g, this._b, allow3Char); + }, + toHexString: function toHexString(allow3Char) { + return "#" + this.toHex(allow3Char); + }, + toHex8: function toHex8(allow4Char) { + return rgbaToHex(this._r, this._g, this._b, this._a, allow4Char); + }, + toHex8String: function toHex8String(allow4Char) { + return "#" + this.toHex8(allow4Char); + }, + toRgb: function toRgb() { + return { + r: Math.round(this._r), + g: Math.round(this._g), + b: Math.round(this._b), + a: this._a + }; + }, + toRgbString: function toRgbString() { + return this._a == 1 ? "rgb(" + Math.round(this._r) + ", " + Math.round(this._g) + ", " + Math.round(this._b) + ")" : "rgba(" + Math.round(this._r) + ", " + Math.round(this._g) + ", " + Math.round(this._b) + ", " + this._roundA + ")"; + }, + toPercentageRgb: function toPercentageRgb() { + return { + r: Math.round(bound01(this._r, 255) * 100) + "%", + g: Math.round(bound01(this._g, 255) * 100) + "%", + b: Math.round(bound01(this._b, 255) * 100) + "%", + a: this._a + }; + }, + toPercentageRgbString: function toPercentageRgbString() { + return this._a == 1 ? "rgb(" + Math.round(bound01(this._r, 255) * 100) + "%, " + Math.round(bound01(this._g, 255) * 100) + "%, " + Math.round(bound01(this._b, 255) * 100) + "%)" : "rgba(" + Math.round(bound01(this._r, 255) * 100) + "%, " + Math.round(bound01(this._g, 255) * 100) + "%, " + Math.round(bound01(this._b, 255) * 100) + "%, " + this._roundA + ")"; + }, + toName: function toName() { + if (this._a === 0) { + return "transparent"; + } + if (this._a < 1) { + return false; + } + return hexNames[rgbToHex(this._r, this._g, this._b, true)] || false; + }, + toFilter: function toFilter(secondColor) { + var hex8String = "#" + rgbaToArgbHex(this._r, this._g, this._b, this._a); + var secondHex8String = hex8String; + var gradientType = this._gradientType ? "GradientType = 1, " : ""; + if (secondColor) { + var s = tinycolor(secondColor); + secondHex8String = "#" + rgbaToArgbHex(s._r, s._g, s._b, s._a); + } + return "progid:DXImageTransform.Microsoft.gradient(" + gradientType + "startColorstr=" + hex8String + ",endColorstr=" + secondHex8String + ")"; + }, + toString: function toString(format) { + var formatSet = !!format; + format = format || this._format; + var formattedString = false; + var hasAlpha = this._a < 1 && this._a >= 0; + var needsAlphaFormat = !formatSet && hasAlpha && (format === "hex" || format === "hex6" || format === "hex3" || format === "hex4" || format === "hex8" || format === "name"); + if (needsAlphaFormat) { + // Special case for "transparent", all other non-alpha formats + // will return rgba when there is transparency. + if (format === "name" && this._a === 0) { + return this.toName(); + } + return this.toRgbString(); + } + if (format === "rgb") { + formattedString = this.toRgbString(); + } + if (format === "prgb") { + formattedString = this.toPercentageRgbString(); + } + if (format === "hex" || format === "hex6") { + formattedString = this.toHexString(); + } + if (format === "hex3") { + formattedString = this.toHexString(true); + } + if (format === "hex4") { + formattedString = this.toHex8String(true); + } + if (format === "hex8") { + formattedString = this.toHex8String(); + } + if (format === "name") { + formattedString = this.toName(); + } + if (format === "hsl") { + formattedString = this.toHslString(); + } + if (format === "hsv") { + formattedString = this.toHsvString(); + } + return formattedString || this.toHexString(); + }, + clone: function clone() { + return tinycolor(this.toString()); + }, + _applyModification: function _applyModification(fn, args) { + var color = fn.apply(null, [this].concat([].slice.call(args))); + this._r = color._r; + this._g = color._g; + this._b = color._b; + this.setAlpha(color._a); + return this; + }, + lighten: function lighten() { + return this._applyModification(_lighten, arguments); + }, + brighten: function brighten() { + return this._applyModification(_brighten, arguments); + }, + darken: function darken() { + return this._applyModification(_darken, arguments); + }, + desaturate: function desaturate() { + return this._applyModification(_desaturate, arguments); + }, + saturate: function saturate() { + return this._applyModification(_saturate, arguments); + }, + greyscale: function greyscale() { + return this._applyModification(_greyscale, arguments); + }, + spin: function spin() { + return this._applyModification(_spin, arguments); + }, + _applyCombination: function _applyCombination(fn, args) { + return fn.apply(null, [this].concat([].slice.call(args))); + }, + analogous: function analogous() { + return this._applyCombination(_analogous, arguments); + }, + complement: function complement() { + return this._applyCombination(_complement, arguments); + }, + monochromatic: function monochromatic() { + return this._applyCombination(_monochromatic, arguments); + }, + splitcomplement: function splitcomplement() { + return this._applyCombination(_splitcomplement, arguments); + }, + // Disabled until https://github.com/bgrins/TinyColor/issues/254 + // polyad: function (number) { + // return this._applyCombination(polyad, [number]); + // }, + triad: function triad() { + return this._applyCombination(polyad, [3]); + }, + tetrad: function tetrad() { + return this._applyCombination(polyad, [4]); + } + }; + + // If input is an object, force 1 into "1.0" to handle ratios properly + // String input requires "1.0" as input, so 1 will be treated as 1 + tinycolor.fromRatio = function (color, opts) { + if (_typeof(color) == "object") { + var newColor = {}; + for (var i in color) { + if (color.hasOwnProperty(i)) { + if (i === "a") { + newColor[i] = color[i]; + } else { + newColor[i] = convertToPercentage(color[i]); + } + } + } + color = newColor; + } + return tinycolor(color, opts); + }; + + // Given a string or object, convert that input to RGB + // Possible string inputs: + // + // "red" + // "#f00" or "f00" + // "#ff0000" or "ff0000" + // "#ff000000" or "ff000000" + // "rgb 255 0 0" or "rgb (255, 0, 0)" + // "rgb 1.0 0 0" or "rgb (1, 0, 0)" + // "rgba (255, 0, 0, 1)" or "rgba 255, 0, 0, 1" + // "rgba (1.0, 0, 0, 1)" or "rgba 1.0, 0, 0, 1" + // "hsl(0, 100%, 50%)" or "hsl 0 100% 50%" + // "hsla(0, 100%, 50%, 1)" or "hsla 0 100% 50%, 1" + // "hsv(0, 100%, 100%)" or "hsv 0 100% 100%" + // + function inputToRGB(color) { + var rgb = { + r: 0, + g: 0, + b: 0 + }; + var a = 1; + var s = null; + var v = null; + var l = null; + var ok = false; + var format = false; + if (typeof color == "string") { + color = stringInputToObject(color); + } + if (_typeof(color) == "object") { + if (isValidCSSUnit(color.r) && isValidCSSUnit(color.g) && isValidCSSUnit(color.b)) { + rgb = rgbToRgb(color.r, color.g, color.b); + ok = true; + format = String(color.r).substr(-1) === "%" ? "prgb" : "rgb"; + } else if (isValidCSSUnit(color.h) && isValidCSSUnit(color.s) && isValidCSSUnit(color.v)) { + s = convertToPercentage(color.s); + v = convertToPercentage(color.v); + rgb = hsvToRgb(color.h, s, v); + ok = true; + format = "hsv"; + } else if (isValidCSSUnit(color.h) && isValidCSSUnit(color.s) && isValidCSSUnit(color.l)) { + s = convertToPercentage(color.s); + l = convertToPercentage(color.l); + rgb = hslToRgb(color.h, s, l); + ok = true; + format = "hsl"; + } + if (color.hasOwnProperty("a")) { + a = color.a; + } + } + a = boundAlpha(a); + return { + ok: ok, + format: color.format || format, + r: Math.min(255, Math.max(rgb.r, 0)), + g: Math.min(255, Math.max(rgb.g, 0)), + b: Math.min(255, Math.max(rgb.b, 0)), + a: a + }; + } + + // Conversion Functions + // -------------------- + + // `rgbToHsl`, `rgbToHsv`, `hslToRgb`, `hsvToRgb` modified from: + // + + // `rgbToRgb` + // Handle bounds / percentage checking to conform to CSS color spec + // + // *Assumes:* r, g, b in [0, 255] or [0, 1] + // *Returns:* { r, g, b } in [0, 255] + function rgbToRgb(r, g, b) { + return { + r: bound01(r, 255) * 255, + g: bound01(g, 255) * 255, + b: bound01(b, 255) * 255 + }; + } + + // `rgbToHsl` + // Converts an RGB color value to HSL. + // *Assumes:* r, g, and b are contained in [0, 255] or [0, 1] + // *Returns:* { h, s, l } in [0,1] + function rgbToHsl(r, g, b) { + r = bound01(r, 255); + g = bound01(g, 255); + b = bound01(b, 255); + var max = Math.max(r, g, b), + min = Math.min(r, g, b); + var h, + s, + l = (max + min) / 2; + if (max == min) { + h = s = 0; // achromatic + } else { + var d = max - min; + s = l > 0.5 ? d / (2 - max - min) : d / (max + min); + switch (max) { + case r: + h = (g - b) / d + (g < b ? 6 : 0); + break; + case g: + h = (b - r) / d + 2; + break; + case b: + h = (r - g) / d + 4; + break; + } + h /= 6; + } + return { + h: h, + s: s, + l: l + }; + } + + // `hslToRgb` + // Converts an HSL color value to RGB. + // *Assumes:* h is contained in [0, 1] or [0, 360] and s and l are contained [0, 1] or [0, 100] + // *Returns:* { r, g, b } in the set [0, 255] + function hslToRgb(h, s, l) { + var r, g, b; + h = bound01(h, 360); + s = bound01(s, 100); + l = bound01(l, 100); + function hue2rgb(p, q, t) { + if (t < 0) t += 1; + if (t > 1) t -= 1; + if (t < 1 / 6) return p + (q - p) * 6 * t; + if (t < 1 / 2) return q; + if (t < 2 / 3) return p + (q - p) * (2 / 3 - t) * 6; + return p; + } + if (s === 0) { + r = g = b = l; // achromatic + } else { + var q = l < 0.5 ? l * (1 + s) : l + s - l * s; + var p = 2 * l - q; + r = hue2rgb(p, q, h + 1 / 3); + g = hue2rgb(p, q, h); + b = hue2rgb(p, q, h - 1 / 3); + } + return { + r: r * 255, + g: g * 255, + b: b * 255 + }; + } + + // `rgbToHsv` + // Converts an RGB color value to HSV + // *Assumes:* r, g, and b are contained in the set [0, 255] or [0, 1] + // *Returns:* { h, s, v } in [0,1] + function rgbToHsv(r, g, b) { + r = bound01(r, 255); + g = bound01(g, 255); + b = bound01(b, 255); + var max = Math.max(r, g, b), + min = Math.min(r, g, b); + var h, + s, + v = max; + var d = max - min; + s = max === 0 ? 0 : d / max; + if (max == min) { + h = 0; // achromatic + } else { + switch (max) { + case r: + h = (g - b) / d + (g < b ? 6 : 0); + break; + case g: + h = (b - r) / d + 2; + break; + case b: + h = (r - g) / d + 4; + break; + } + h /= 6; + } + return { + h: h, + s: s, + v: v + }; + } + + // `hsvToRgb` + // Converts an HSV color value to RGB. + // *Assumes:* h is contained in [0, 1] or [0, 360] and s and v are contained in [0, 1] or [0, 100] + // *Returns:* { r, g, b } in the set [0, 255] + function hsvToRgb(h, s, v) { + h = bound01(h, 360) * 6; + s = bound01(s, 100); + v = bound01(v, 100); + var i = Math.floor(h), + f = h - i, + p = v * (1 - s), + q = v * (1 - f * s), + t = v * (1 - (1 - f) * s), + mod = i % 6, + r = [v, q, p, p, t, v][mod], + g = [t, v, v, q, p, p][mod], + b = [p, p, t, v, v, q][mod]; + return { + r: r * 255, + g: g * 255, + b: b * 255 + }; + } + + // `rgbToHex` + // Converts an RGB color to hex + // Assumes r, g, and b are contained in the set [0, 255] + // Returns a 3 or 6 character hex + function rgbToHex(r, g, b, allow3Char) { + var hex = [pad2(Math.round(r).toString(16)), pad2(Math.round(g).toString(16)), pad2(Math.round(b).toString(16))]; + + // Return a 3 character hex if possible + if (allow3Char && hex[0].charAt(0) == hex[0].charAt(1) && hex[1].charAt(0) == hex[1].charAt(1) && hex[2].charAt(0) == hex[2].charAt(1)) { + return hex[0].charAt(0) + hex[1].charAt(0) + hex[2].charAt(0); + } + return hex.join(""); + } + + // `rgbaToHex` + // Converts an RGBA color plus alpha transparency to hex + // Assumes r, g, b are contained in the set [0, 255] and + // a in [0, 1]. Returns a 4 or 8 character rgba hex + function rgbaToHex(r, g, b, a, allow4Char) { + var hex = [pad2(Math.round(r).toString(16)), pad2(Math.round(g).toString(16)), pad2(Math.round(b).toString(16)), pad2(convertDecimalToHex(a))]; + + // Return a 4 character hex if possible + if (allow4Char && hex[0].charAt(0) == hex[0].charAt(1) && hex[1].charAt(0) == hex[1].charAt(1) && hex[2].charAt(0) == hex[2].charAt(1) && hex[3].charAt(0) == hex[3].charAt(1)) { + return hex[0].charAt(0) + hex[1].charAt(0) + hex[2].charAt(0) + hex[3].charAt(0); + } + return hex.join(""); + } + + // `rgbaToArgbHex` + // Converts an RGBA color to an ARGB Hex8 string + // Rarely used, but required for "toFilter()" + function rgbaToArgbHex(r, g, b, a) { + var hex = [pad2(convertDecimalToHex(a)), pad2(Math.round(r).toString(16)), pad2(Math.round(g).toString(16)), pad2(Math.round(b).toString(16))]; + return hex.join(""); + } + + // `equals` + // Can be called with any tinycolor input + tinycolor.equals = function (color1, color2) { + if (!color1 || !color2) return false; + return tinycolor(color1).toRgbString() == tinycolor(color2).toRgbString(); + }; + tinycolor.random = function () { + return tinycolor.fromRatio({ + r: Math.random(), + g: Math.random(), + b: Math.random() + }); + }; + + // Modification Functions + // ---------------------- + // Thanks to less.js for some of the basics here + // + + function _desaturate(color, amount) { + amount = amount === 0 ? 0 : amount || 10; + var hsl = tinycolor(color).toHsl(); + hsl.s -= amount / 100; + hsl.s = clamp01(hsl.s); + return tinycolor(hsl); + } + function _saturate(color, amount) { + amount = amount === 0 ? 0 : amount || 10; + var hsl = tinycolor(color).toHsl(); + hsl.s += amount / 100; + hsl.s = clamp01(hsl.s); + return tinycolor(hsl); + } + function _greyscale(color) { + return tinycolor(color).desaturate(100); + } + function _lighten(color, amount) { + amount = amount === 0 ? 0 : amount || 10; + var hsl = tinycolor(color).toHsl(); + hsl.l += amount / 100; + hsl.l = clamp01(hsl.l); + return tinycolor(hsl); + } + function _brighten(color, amount) { + amount = amount === 0 ? 0 : amount || 10; + var rgb = tinycolor(color).toRgb(); + rgb.r = Math.max(0, Math.min(255, rgb.r - Math.round(255 * -(amount / 100)))); + rgb.g = Math.max(0, Math.min(255, rgb.g - Math.round(255 * -(amount / 100)))); + rgb.b = Math.max(0, Math.min(255, rgb.b - Math.round(255 * -(amount / 100)))); + return tinycolor(rgb); + } + function _darken(color, amount) { + amount = amount === 0 ? 0 : amount || 10; + var hsl = tinycolor(color).toHsl(); + hsl.l -= amount / 100; + hsl.l = clamp01(hsl.l); + return tinycolor(hsl); + } + + // Spin takes a positive or negative amount within [-360, 360] indicating the change of hue. + // Values outside of this range will be wrapped into this range. + function _spin(color, amount) { + var hsl = tinycolor(color).toHsl(); + var hue = (hsl.h + amount) % 360; + hsl.h = hue < 0 ? 360 + hue : hue; + return tinycolor(hsl); + } + + // Combination Functions + // --------------------- + // Thanks to jQuery xColor for some of the ideas behind these + // + + function _complement(color) { + var hsl = tinycolor(color).toHsl(); + hsl.h = (hsl.h + 180) % 360; + return tinycolor(hsl); + } + function polyad(color, number) { + if (isNaN(number) || number <= 0) { + throw new Error("Argument to polyad must be a positive number"); + } + var hsl = tinycolor(color).toHsl(); + var result = [tinycolor(color)]; + var step = 360 / number; + for (var i = 1; i < number; i++) { + result.push(tinycolor({ + h: (hsl.h + i * step) % 360, + s: hsl.s, + l: hsl.l + })); + } + return result; + } + function _splitcomplement(color) { + var hsl = tinycolor(color).toHsl(); + var h = hsl.h; + return [tinycolor(color), tinycolor({ + h: (h + 72) % 360, + s: hsl.s, + l: hsl.l + }), tinycolor({ + h: (h + 216) % 360, + s: hsl.s, + l: hsl.l + })]; + } + function _analogous(color, results, slices) { + results = results || 6; + slices = slices || 30; + var hsl = tinycolor(color).toHsl(); + var part = 360 / slices; + var ret = [tinycolor(color)]; + for (hsl.h = (hsl.h - (part * results >> 1) + 720) % 360; --results;) { + hsl.h = (hsl.h + part) % 360; + ret.push(tinycolor(hsl)); + } + return ret; + } + function _monochromatic(color, results) { + results = results || 6; + var hsv = tinycolor(color).toHsv(); + var h = hsv.h, + s = hsv.s, + v = hsv.v; + var ret = []; + var modification = 1 / results; + while (results--) { + ret.push(tinycolor({ + h: h, + s: s, + v: v + })); + v = (v + modification) % 1; + } + return ret; + } + + // Utility Functions + // --------------------- + + tinycolor.mix = function (color1, color2, amount) { + amount = amount === 0 ? 0 : amount || 50; + var rgb1 = tinycolor(color1).toRgb(); + var rgb2 = tinycolor(color2).toRgb(); + var p = amount / 100; + var rgba = { + r: (rgb2.r - rgb1.r) * p + rgb1.r, + g: (rgb2.g - rgb1.g) * p + rgb1.g, + b: (rgb2.b - rgb1.b) * p + rgb1.b, + a: (rgb2.a - rgb1.a) * p + rgb1.a + }; + return tinycolor(rgba); + }; + + // Readability Functions + // --------------------- + // false + // tinycolor.isReadable("#000", "#111",{level:"AA",size:"large"}) => false + tinycolor.isReadable = function (color1, color2, wcag2) { + var readability = tinycolor.readability(color1, color2); + var wcag2Parms, out; + out = false; + wcag2Parms = validateWCAG2Parms(wcag2); + switch (wcag2Parms.level + wcag2Parms.size) { + case "AAsmall": + case "AAAlarge": + out = readability >= 4.5; + break; + case "AAlarge": + out = readability >= 3; + break; + case "AAAsmall": + out = readability >= 7; + break; + } + return out; + }; + + // `mostReadable` + // Given a base color and a list of possible foreground or background + // colors for that base, returns the most readable color. + // Optionally returns Black or White if the most readable color is unreadable. + // *Example* + // tinycolor.mostReadable(tinycolor.mostReadable("#123", ["#124", "#125"],{includeFallbackColors:false}).toHexString(); // "#112255" + // tinycolor.mostReadable(tinycolor.mostReadable("#123", ["#124", "#125"],{includeFallbackColors:true}).toHexString(); // "#ffffff" + // tinycolor.mostReadable("#a8015a", ["#faf3f3"],{includeFallbackColors:true,level:"AAA",size:"large"}).toHexString(); // "#faf3f3" + // tinycolor.mostReadable("#a8015a", ["#faf3f3"],{includeFallbackColors:true,level:"AAA",size:"small"}).toHexString(); // "#ffffff" + tinycolor.mostReadable = function (baseColor, colorList, args) { + var bestColor = null; + var bestScore = 0; + var readability; + var includeFallbackColors, level, size; + args = args || {}; + includeFallbackColors = args.includeFallbackColors; + level = args.level; + size = args.size; + for (var i = 0; i < colorList.length; i++) { + readability = tinycolor.readability(baseColor, colorList[i]); + if (readability > bestScore) { + bestScore = readability; + bestColor = tinycolor(colorList[i]); + } + } + if (tinycolor.isReadable(baseColor, bestColor, { + level: level, + size: size + }) || !includeFallbackColors) { + return bestColor; + } else { + args.includeFallbackColors = false; + return tinycolor.mostReadable(baseColor, ["#fff", "#000"], args); + } + }; + + // Big List of Colors + // ------------------ + // + var names = tinycolor.names = { + aliceblue: "f0f8ff", + antiquewhite: "faebd7", + aqua: "0ff", + aquamarine: "7fffd4", + azure: "f0ffff", + beige: "f5f5dc", + bisque: "ffe4c4", + black: "000", + blanchedalmond: "ffebcd", + blue: "00f", + blueviolet: "8a2be2", + brown: "a52a2a", + burlywood: "deb887", + burntsienna: "ea7e5d", + cadetblue: "5f9ea0", + chartreuse: "7fff00", + chocolate: "d2691e", + coral: "ff7f50", + cornflowerblue: "6495ed", + cornsilk: "fff8dc", + crimson: "dc143c", + cyan: "0ff", + 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: "f0f", + 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: "789", + lightslategrey: "789", + lightsteelblue: "b0c4de", + lightyellow: "ffffe0", + lime: "0f0", + limegreen: "32cd32", + linen: "faf0e6", + magenta: "f0f", + 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: "f00", + 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: "fff", + whitesmoke: "f5f5f5", + yellow: "ff0", + yellowgreen: "9acd32" + }; + + // Make it easy to access colors via `hexNames[hex]` + var hexNames = tinycolor.hexNames = flip(names); + + // Utilities + // --------- + + // `{ 'name1': 'val1' }` becomes `{ 'val1': 'name1' }` + function flip(o) { + var flipped = {}; + for (var i in o) { + if (o.hasOwnProperty(i)) { + flipped[o[i]] = i; + } + } + return flipped; + } + + // Return a valid alpha value [0,1] with all invalid values being set to 1 + function boundAlpha(a) { + a = parseFloat(a); + if (isNaN(a) || a < 0 || a > 1) { + a = 1; + } + return a; + } + + // Take input from [0, n] and return it as [0, 1] + function bound01(n, max) { + if (isOnePointZero(n)) n = "100%"; + var processPercent = isPercentage(n); + n = Math.min(max, Math.max(0, parseFloat(n))); + + // Automatically convert percentage into number + if (processPercent) { + n = parseInt(n * max, 10) / 100; + } + + // Handle floating point rounding errors + if (Math.abs(n - max) < 0.000001) { + return 1; + } + + // Convert into [0, 1] range if it isn't already + return n % max / parseFloat(max); + } + + // Force a number between 0 and 1 + function clamp01(val) { + return Math.min(1, Math.max(0, val)); + } + + // Parse a base-16 hex value into a base-10 integer + function parseIntFromHex(val) { + return parseInt(val, 16); + } + + // Need to handle 1.0 as 100%, since once it is a number, there is no difference between it and 1 + // + function isOnePointZero(n) { + return typeof n == "string" && n.indexOf(".") != -1 && parseFloat(n) === 1; + } + + // Check to see if string passed in is a percentage + function isPercentage(n) { + return typeof n === "string" && n.indexOf("%") != -1; + } + + // Force a hex value to have 2 characters + function pad2(c) { + return c.length == 1 ? "0" + c : "" + c; + } + + // Replace a decimal with it's percentage value + function convertToPercentage(n) { + if (n <= 1) { + n = n * 100 + "%"; + } + return n; + } + + // Converts a decimal to a hex value + function convertDecimalToHex(d) { + return Math.round(parseFloat(d) * 255).toString(16); + } + // Converts a hex value to a decimal + function convertHexToDecimal(h) { + return parseIntFromHex(h) / 255; + } + var matchers = function () { + // + var CSS_INTEGER = "[-\\+]?\\d+%?"; + + // + var CSS_NUMBER = "[-\\+]?\\d*\\.\\d+%?"; + + // Allow positive/negative integer/number. Don't capture the either/or, just the entire outcome. + var CSS_UNIT = "(?:" + CSS_NUMBER + ")|(?:" + CSS_INTEGER + ")"; + + // Actual matching. + // Parentheses and commas are optional, but not required. + // Whitespace can take the place of commas or opening paren + var PERMISSIVE_MATCH3 = "[\\s|\\(]+(" + CSS_UNIT + ")[,|\\s]+(" + CSS_UNIT + ")[,|\\s]+(" + CSS_UNIT + ")\\s*\\)?"; + var PERMISSIVE_MATCH4 = "[\\s|\\(]+(" + CSS_UNIT + ")[,|\\s]+(" + CSS_UNIT + ")[,|\\s]+(" + CSS_UNIT + ")[,|\\s]+(" + CSS_UNIT + ")\\s*\\)?"; + return { + CSS_UNIT: new RegExp(CSS_UNIT), + rgb: new RegExp("rgb" + PERMISSIVE_MATCH3), + rgba: new RegExp("rgba" + PERMISSIVE_MATCH4), + hsl: new RegExp("hsl" + PERMISSIVE_MATCH3), + hsla: new RegExp("hsla" + PERMISSIVE_MATCH4), + hsv: new RegExp("hsv" + PERMISSIVE_MATCH3), + hsva: new RegExp("hsva" + PERMISSIVE_MATCH4), + hex3: /^#?([0-9a-fA-F]{1})([0-9a-fA-F]{1})([0-9a-fA-F]{1})$/, + hex6: /^#?([0-9a-fA-F]{2})([0-9a-fA-F]{2})([0-9a-fA-F]{2})$/, + hex4: /^#?([0-9a-fA-F]{1})([0-9a-fA-F]{1})([0-9a-fA-F]{1})([0-9a-fA-F]{1})$/, + hex8: /^#?([0-9a-fA-F]{2})([0-9a-fA-F]{2})([0-9a-fA-F]{2})([0-9a-fA-F]{2})$/ + }; + }(); + + // `isValidCSSUnit` + // Take in a single string / number and check to see if it looks like a CSS unit + // (see `matchers` above for definition). + function isValidCSSUnit(color) { + return !!matchers.CSS_UNIT.exec(color); + } + + // `stringInputToObject` + // Permissive string parsing. Take in a number of formats, and output an object + // based on detected format. Returns `{ r, g, b }` or `{ h, s, l }` or `{ h, s, v}` + function stringInputToObject(color) { + color = color.replace(trimLeft, "").replace(trimRight, "").toLowerCase(); + var named = false; + if (names[color]) { + color = names[color]; + named = true; + } else if (color == "transparent") { + return { + r: 0, + g: 0, + b: 0, + a: 0, + format: "name" + }; + } + + // Try to match string input using regular expressions. + // Keep most of the number bounding out of this function - don't worry about [0,1] or [0,100] or [0,360] + // Just return an object and let the conversion functions handle that. + // This way the result will be the same whether the tinycolor is initialized with string or object. + var match; + if (match = matchers.rgb.exec(color)) { + return { + r: match[1], + g: match[2], + b: match[3] + }; + } + if (match = matchers.rgba.exec(color)) { + return { + r: match[1], + g: match[2], + b: match[3], + a: match[4] + }; + } + if (match = matchers.hsl.exec(color)) { + return { + h: match[1], + s: match[2], + l: match[3] + }; + } + if (match = matchers.hsla.exec(color)) { + return { + h: match[1], + s: match[2], + l: match[3], + a: match[4] + }; + } + if (match = matchers.hsv.exec(color)) { + return { + h: match[1], + s: match[2], + v: match[3] + }; + } + if (match = matchers.hsva.exec(color)) { + return { + h: match[1], + s: match[2], + v: match[3], + a: match[4] + }; + } + if (match = matchers.hex8.exec(color)) { + return { + r: parseIntFromHex(match[1]), + g: parseIntFromHex(match[2]), + b: parseIntFromHex(match[3]), + a: convertHexToDecimal(match[4]), + format: named ? "name" : "hex8" + }; + } + if (match = matchers.hex6.exec(color)) { + return { + r: parseIntFromHex(match[1]), + g: parseIntFromHex(match[2]), + b: parseIntFromHex(match[3]), + format: named ? "name" : "hex" + }; + } + if (match = matchers.hex4.exec(color)) { + return { + r: parseIntFromHex(match[1] + "" + match[1]), + g: parseIntFromHex(match[2] + "" + match[2]), + b: parseIntFromHex(match[3] + "" + match[3]), + a: convertHexToDecimal(match[4] + "" + match[4]), + format: named ? "name" : "hex8" + }; + } + if (match = matchers.hex3.exec(color)) { + return { + r: parseIntFromHex(match[1] + "" + match[1]), + g: parseIntFromHex(match[2] + "" + match[2]), + b: parseIntFromHex(match[3] + "" + match[3]), + format: named ? "name" : "hex" + }; + } + return false; + } + function validateWCAG2Parms(parms) { + // return valid WCAG2 parms for isReadable. + // If input parms are invalid, return {"level":"AA", "size":"small"} + var level, size; + parms = parms || { + level: "AA", + size: "small" + }; + level = (parms.level || "AA").toUpperCase(); + size = (parms.size || "small").toLowerCase(); + if (level !== "AA" && level !== "AAA") { + level = "AA"; + } + if (size !== "small" && size !== "large") { + size = "small"; + } + return { + level: level, + size: size + }; + } + + function _classCallCheck(instance, Constructor) { + if (!(instance instanceof Constructor)) { + throw new TypeError("Cannot call a class as a 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, _toPropertyKey$1(descriptor.key), descriptor); + } + } + function _createClass(Constructor, protoProps, staticProps) { + if (protoProps) _defineProperties(Constructor.prototype, protoProps); + if (staticProps) _defineProperties(Constructor, staticProps); + Object.defineProperty(Constructor, "prototype", { + writable: false + }); + return Constructor; + } + function _toConsumableArray$1(arr) { + return _arrayWithoutHoles$1(arr) || _iterableToArray$1(arr) || _unsupportedIterableToArray$1(arr) || _nonIterableSpread$1(); + } + function _arrayWithoutHoles$1(arr) { + if (Array.isArray(arr)) return _arrayLikeToArray$1(arr); + } + function _iterableToArray$1(iter) { + if (typeof Symbol !== "undefined" && iter[Symbol.iterator] != null || iter["@@iterator"] != null) return Array.from(iter); + } + function _unsupportedIterableToArray$1(o, minLen) { + if (!o) return; + if (typeof o === "string") return _arrayLikeToArray$1(o, minLen); + var n = Object.prototype.toString.call(o).slice(8, -1); + if (n === "Object" && o.constructor) n = o.constructor.name; + if (n === "Map" || n === "Set") return Array.from(o); + if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray$1(o, minLen); + } + function _arrayLikeToArray$1(arr, len) { + if (len == null || len > arr.length) len = arr.length; + for (var i = 0, arr2 = new Array(len); i < len; i++) arr2[i] = arr[i]; + return arr2; + } + function _nonIterableSpread$1() { + throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); + } + function _toPrimitive$1(input, hint) { + if (typeof input !== "object" || input === null) return input; + var prim = input[Symbol.toPrimitive]; + if (prim !== undefined) { + var res = prim.call(input, hint || "default"); + if (typeof res !== "object") return res; + throw new TypeError("@@toPrimitive must return a primitive value."); + } + return (hint === "string" ? String : Number)(input); + } + function _toPropertyKey$1(arg) { + var key = _toPrimitive$1(arg, "string"); + return typeof key === "symbol" ? key : String(key); + } + + var ENTROPY = 123; // Raise numbers to prevent collisions in lower indexes + + var int2HexColor = function int2HexColor(num) { + return "#".concat(Math.min(num, Math.pow(2, 24)).toString(16).padStart(6, '0')); + }; + var rgb2Int = function rgb2Int(r, g, b) { + return (r << 16) + (g << 8) + b; + }; + var colorStr2Int = function colorStr2Int(str) { + var _tinyColor$toRgb = tinycolor(str).toRgb(), + r = _tinyColor$toRgb.r, + g = _tinyColor$toRgb.g, + b = _tinyColor$toRgb.b; + return rgb2Int(r, g, b); + }; + var checksum = function checksum(n, csBits) { + return n * ENTROPY % Math.pow(2, csBits); + }; + var _default = /*#__PURE__*/function () { + function _default() { + var csBits = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 6; + _classCallCheck(this, _default); + this.csBits = csBits; // How many bits to reserve for checksum. Will eat away into the usable size of the registry. + this.registry = ['__reserved for background__']; // indexed objects for rgb lookup; + } + _createClass(_default, [{ + key: "register", + value: function register(obj) { + if (this.registry.length >= Math.pow(2, 24 - this.csBits)) { + // color has 24 bits (-checksum) + return null; // Registry is full + } + + var idx = this.registry.length; + var cs = checksum(idx, this.csBits); + var color = int2HexColor(idx + (cs << 24 - this.csBits)); + this.registry.push(obj); + return color; + } + }, { + key: "lookup", + value: function lookup(color) { + var n = typeof color === 'string' ? colorStr2Int(color) : rgb2Int.apply(void 0, _toConsumableArray$1(color)); + if (!n) return null; // 0 index is reserved for background + + var idx = n & Math.pow(2, 24 - this.csBits) - 1; // registry index + var cs = n >> 24 - this.csBits & Math.pow(2, this.csBits) - 1; // extract bits reserved for checksum + + if (checksum(idx, this.csBits) !== cs || idx >= this.registry.length) return null; // failed checksum or registry out of bounds + + return this.registry[idx]; + } + }]); + return _default; + }(); + + function d3ForceCenter(x, y, z) { + var nodes, strength = 1; + + if (x == null) x = 0; + if (y == null) y = 0; + if (z == null) z = 0; + + function force() { + var i, + n = nodes.length, + node, + sx = 0, + sy = 0, + sz = 0; + + for (i = 0; i < n; ++i) { + node = nodes[i], sx += node.x || 0, sy += node.y || 0, sz += node.z || 0; + } + + for (sx = (sx / n - x) * strength, sy = (sy / n - y) * strength, sz = (sz / n - z) * strength, i = 0; i < n; ++i) { + node = nodes[i]; + if (sx) { node.x -= sx; } + if (sy) { node.y -= sy; } + if (sz) { node.z -= sz; } + } + } + + force.initialize = function(_) { + nodes = _; + }; + + force.x = function(_) { + return arguments.length ? (x = +_, force) : x; + }; + + force.y = function(_) { + return arguments.length ? (y = +_, force) : y; + }; + + force.z = function(_) { + return arguments.length ? (z = +_, force) : z; + }; + + force.strength = function(_) { + return arguments.length ? (strength = +_, force) : strength; + }; + + return force; + } + + function tree_add$2(d) { + const x = +this._x.call(null, d); + return add$2(this.cover(x), x, d); + } + + function add$2(tree, x, d) { + if (isNaN(x)) return tree; // ignore invalid points + + var parent, + node = tree._root, + leaf = {data: d}, + x0 = tree._x0, + x1 = tree._x1, + xm, + xp, + right, + i, + j; + + // If the tree is empty, initialize the root as a leaf. + if (!node) return tree._root = leaf, tree; + + // Find the existing leaf for the new point, or add it. + while (node.length) { + if (right = x >= (xm = (x0 + x1) / 2)) x0 = xm; else x1 = xm; + if (parent = node, !(node = node[i = +right])) return parent[i] = leaf, tree; + } + + // Is the new point is exactly coincident with the existing point? + xp = +tree._x.call(null, node.data); + if (x === xp) return leaf.next = node, parent ? parent[i] = leaf : tree._root = leaf, tree; + + // Otherwise, split the leaf node until the old and new point are separated. + do { + parent = parent ? parent[i] = new Array(2) : tree._root = new Array(2); + if (right = x >= (xm = (x0 + x1) / 2)) x0 = xm; else x1 = xm; + } while ((i = +right) === (j = +(xp >= xm))); + return parent[j] = node, parent[i] = leaf, tree; + } + + function addAll$2(data) { + if (!Array.isArray(data)) data = Array.from(data); + const n = data.length; + const xz = new Float64Array(n); + let x0 = Infinity, + x1 = -Infinity; + + // Compute the points and their extent. + for (let i = 0, x; i < n; ++i) { + if (isNaN(x = +this._x.call(null, data[i]))) continue; + xz[i] = x; + if (x < x0) x0 = x; + if (x > x1) x1 = x; + } + + // If there were no (valid) points, abort. + if (x0 > x1) return this; + + // Expand the tree to cover the new points. + this.cover(x0).cover(x1); + + // Add the new points. + for (let i = 0; i < n; ++i) { + add$2(this, xz[i], data[i]); + } + + return this; + } + + function tree_cover$2(x) { + if (isNaN(x = +x)) return this; // ignore invalid points + + var x0 = this._x0, + x1 = this._x1; + + // If the binarytree has no extent, initialize them. + // Integer extent are necessary so that if we later double the extent, + // the existing half boundaries don’t change due to floating point error! + if (isNaN(x0)) { + x1 = (x0 = Math.floor(x)) + 1; + } + + // Otherwise, double repeatedly to cover. + else { + var z = x1 - x0 || 1, + node = this._root, + parent, + i; + + while (x0 > x || x >= x1) { + i = +(x < x0); + parent = new Array(2), parent[i] = node, node = parent, z *= 2; + switch (i) { + case 0: x1 = x0 + z; break; + case 1: x0 = x1 - z; break; + } + } + + if (this._root && this._root.length) this._root = node; + } + + this._x0 = x0; + this._x1 = x1; + return this; + } + + function tree_data$2() { + var data = []; + this.visit(function(node) { + if (!node.length) do data.push(node.data); while (node = node.next) + }); + return data; + } + + function tree_extent$2(_) { + return arguments.length + ? this.cover(+_[0][0]).cover(+_[1][0]) + : isNaN(this._x0) ? undefined : [[this._x0], [this._x1]]; + } + + function Half(node, x0, x1) { + this.node = node; + this.x0 = x0; + this.x1 = x1; + } + + function tree_find$2(x, radius) { + var data, + x0 = this._x0, + x1, + x2, + x3 = this._x1, + halves = [], + node = this._root, + q, + i; + + if (node) halves.push(new Half(node, x0, x3)); + if (radius == null) radius = Infinity; + else { + x0 = x - radius; + x3 = x + radius; + } + + while (q = halves.pop()) { + + // Stop searching if this half can’t contain a closer node. + if (!(node = q.node) + || (x1 = q.x0) > x3 + || (x2 = q.x1) < x0) continue; + + // Bisect the current half. + if (node.length) { + var xm = (x1 + x2) / 2; + + halves.push( + new Half(node[1], xm, x2), + new Half(node[0], x1, xm) + ); + + // Visit the closest half first. + if (i = +(x >= xm)) { + q = halves[halves.length - 1]; + halves[halves.length - 1] = halves[halves.length - 1 - i]; + halves[halves.length - 1 - i] = q; + } + } + + // Visit this point. (Visiting coincident points isn’t necessary!) + else { + var d = Math.abs(x - +this._x.call(null, node.data)); + if (d < radius) { + radius = d; + x0 = x - d; + x3 = x + d; + data = node.data; + } + } + } + + return data; + } + + function tree_remove$2(d) { + if (isNaN(x = +this._x.call(null, d))) return this; // ignore invalid points + + var parent, + node = this._root, + retainer, + previous, + next, + x0 = this._x0, + x1 = this._x1, + x, + xm, + right, + i, + j; + + // If the tree is empty, initialize the root as a leaf. + if (!node) return this; + + // Find the leaf node for the point. + // While descending, also retain the deepest parent with a non-removed sibling. + if (node.length) while (true) { + if (right = x >= (xm = (x0 + x1) / 2)) x0 = xm; else x1 = xm; + if (!(parent = node, node = node[i = +right])) return this; + if (!node.length) break; + if (parent[(i + 1) & 1]) retainer = parent, j = i; + } + + // Find the point to remove. + while (node.data !== d) if (!(previous = node, node = node.next)) return this; + if (next = node.next) delete node.next; + + // If there are multiple coincident points, remove just the point. + if (previous) return (next ? previous.next = next : delete previous.next), this; + + // If this is the root point, remove it. + if (!parent) return this._root = next, this; + + // Remove this leaf. + next ? parent[i] = next : delete parent[i]; + + // If the parent now contains exactly one leaf, collapse superfluous parents. + if ((node = parent[0] || parent[1]) + && node === (parent[1] || parent[0]) + && !node.length) { + if (retainer) retainer[j] = node; + else this._root = node; + } + + return this; + } + + function removeAll$2(data) { + for (var i = 0, n = data.length; i < n; ++i) this.remove(data[i]); + return this; + } + + function tree_root$2() { + return this._root; + } + + function tree_size$2() { + var size = 0; + this.visit(function(node) { + if (!node.length) do ++size; while (node = node.next) + }); + return size; + } + + function tree_visit$2(callback) { + var halves = [], q, node = this._root, child, x0, x1; + if (node) halves.push(new Half(node, this._x0, this._x1)); + while (q = halves.pop()) { + if (!callback(node = q.node, x0 = q.x0, x1 = q.x1) && node.length) { + var xm = (x0 + x1) / 2; + if (child = node[1]) halves.push(new Half(child, xm, x1)); + if (child = node[0]) halves.push(new Half(child, x0, xm)); + } + } + return this; + } + + function tree_visitAfter$2(callback) { + var halves = [], next = [], q; + if (this._root) halves.push(new Half(this._root, this._x0, this._x1)); + while (q = halves.pop()) { + var node = q.node; + if (node.length) { + var child, x0 = q.x0, x1 = q.x1, xm = (x0 + x1) / 2; + if (child = node[0]) halves.push(new Half(child, x0, xm)); + if (child = node[1]) halves.push(new Half(child, xm, x1)); + } + next.push(q); + } + while (q = next.pop()) { + callback(q.node, q.x0, q.x1); + } + return this; + } + + function defaultX$2(d) { + return d[0]; + } + + function tree_x$2(_) { + return arguments.length ? (this._x = _, this) : this._x; + } + + function binarytree(nodes, x) { + var tree = new Binarytree(x == null ? defaultX$2 : x, NaN, NaN); + return nodes == null ? tree : tree.addAll(nodes); + } + + function Binarytree(x, x0, x1) { + this._x = x; + this._x0 = x0; + this._x1 = x1; + this._root = undefined; + } + + function leaf_copy$2(leaf) { + var copy = {data: leaf.data}, next = copy; + while (leaf = leaf.next) next = next.next = {data: leaf.data}; + return copy; + } + + var treeProto$2 = binarytree.prototype = Binarytree.prototype; + + treeProto$2.copy = function() { + var copy = new Binarytree(this._x, this._x0, this._x1), + node = this._root, + nodes, + child; + + if (!node) return copy; + + if (!node.length) return copy._root = leaf_copy$2(node), copy; + + nodes = [{source: node, target: copy._root = new Array(2)}]; + while (node = nodes.pop()) { + for (var i = 0; i < 2; ++i) { + if (child = node.source[i]) { + if (child.length) nodes.push({source: child, target: node.target[i] = new Array(2)}); + else node.target[i] = leaf_copy$2(child); + } + } + } + + return copy; + }; + + treeProto$2.add = tree_add$2; + treeProto$2.addAll = addAll$2; + treeProto$2.cover = tree_cover$2; + treeProto$2.data = tree_data$2; + treeProto$2.extent = tree_extent$2; + treeProto$2.find = tree_find$2; + treeProto$2.remove = tree_remove$2; + treeProto$2.removeAll = removeAll$2; + treeProto$2.root = tree_root$2; + treeProto$2.size = tree_size$2; + treeProto$2.visit = tree_visit$2; + treeProto$2.visitAfter = tree_visitAfter$2; + treeProto$2.x = tree_x$2; + + function tree_add$1(d) { + const x = +this._x.call(null, d), + y = +this._y.call(null, d); + return add$1(this.cover(x, y), x, y, d); + } + + function add$1(tree, x, y, d) { + if (isNaN(x) || isNaN(y)) return tree; // ignore invalid points + + var parent, + node = tree._root, + leaf = {data: d}, + x0 = tree._x0, + y0 = tree._y0, + x1 = tree._x1, + y1 = tree._y1, + xm, + ym, + xp, + yp, + right, + bottom, + i, + j; + + // If the tree is empty, initialize the root as a leaf. + if (!node) return tree._root = leaf, tree; + + // Find the existing leaf for the new point, or add it. + while (node.length) { + if (right = x >= (xm = (x0 + x1) / 2)) x0 = xm; else x1 = xm; + if (bottom = y >= (ym = (y0 + y1) / 2)) y0 = ym; else y1 = ym; + if (parent = node, !(node = node[i = bottom << 1 | right])) return parent[i] = leaf, tree; + } + + // Is the new point is exactly coincident with the existing point? + xp = +tree._x.call(null, node.data); + yp = +tree._y.call(null, node.data); + if (x === xp && y === yp) return leaf.next = node, parent ? parent[i] = leaf : tree._root = leaf, tree; + + // Otherwise, split the leaf node until the old and new point are separated. + do { + parent = parent ? parent[i] = new Array(4) : tree._root = new Array(4); + if (right = x >= (xm = (x0 + x1) / 2)) x0 = xm; else x1 = xm; + if (bottom = y >= (ym = (y0 + y1) / 2)) y0 = ym; else y1 = ym; + } while ((i = bottom << 1 | right) === (j = (yp >= ym) << 1 | (xp >= xm))); + return parent[j] = node, parent[i] = leaf, tree; + } + + function addAll$1(data) { + var d, i, n = data.length, + x, + y, + xz = new Array(n), + yz = new Array(n), + x0 = Infinity, + y0 = Infinity, + x1 = -Infinity, + y1 = -Infinity; + + // Compute the points and their extent. + for (i = 0; i < n; ++i) { + if (isNaN(x = +this._x.call(null, d = data[i])) || isNaN(y = +this._y.call(null, d))) continue; + xz[i] = x; + yz[i] = y; + if (x < x0) x0 = x; + if (x > x1) x1 = x; + if (y < y0) y0 = y; + if (y > y1) y1 = y; + } + + // If there were no (valid) points, abort. + if (x0 > x1 || y0 > y1) return this; + + // Expand the tree to cover the new points. + this.cover(x0, y0).cover(x1, y1); + + // Add the new points. + for (i = 0; i < n; ++i) { + add$1(this, xz[i], yz[i], data[i]); + } + + return this; + } + + function tree_cover$1(x, y) { + if (isNaN(x = +x) || isNaN(y = +y)) return this; // ignore invalid points + + var x0 = this._x0, + y0 = this._y0, + x1 = this._x1, + y1 = this._y1; + + // If the quadtree has no extent, initialize them. + // Integer extent are necessary so that if we later double the extent, + // the existing quadrant boundaries don’t change due to floating point error! + if (isNaN(x0)) { + x1 = (x0 = Math.floor(x)) + 1; + y1 = (y0 = Math.floor(y)) + 1; + } + + // Otherwise, double repeatedly to cover. + else { + var z = x1 - x0 || 1, + node = this._root, + parent, + i; + + while (x0 > x || x >= x1 || y0 > y || y >= y1) { + i = (y < y0) << 1 | (x < x0); + parent = new Array(4), parent[i] = node, node = parent, z *= 2; + switch (i) { + case 0: x1 = x0 + z, y1 = y0 + z; break; + case 1: x0 = x1 - z, y1 = y0 + z; break; + case 2: x1 = x0 + z, y0 = y1 - z; break; + case 3: x0 = x1 - z, y0 = y1 - z; break; + } + } + + if (this._root && this._root.length) this._root = node; + } + + this._x0 = x0; + this._y0 = y0; + this._x1 = x1; + this._y1 = y1; + return this; + } + + function tree_data$1() { + var data = []; + this.visit(function(node) { + if (!node.length) do data.push(node.data); while (node = node.next) + }); + return data; + } + + function tree_extent$1(_) { + return arguments.length + ? this.cover(+_[0][0], +_[0][1]).cover(+_[1][0], +_[1][1]) + : isNaN(this._x0) ? undefined : [[this._x0, this._y0], [this._x1, this._y1]]; + } + + function Quad(node, x0, y0, x1, y1) { + this.node = node; + this.x0 = x0; + this.y0 = y0; + this.x1 = x1; + this.y1 = y1; + } + + function tree_find$1(x, y, radius) { + var data, + x0 = this._x0, + y0 = this._y0, + x1, + y1, + x2, + y2, + x3 = this._x1, + y3 = this._y1, + quads = [], + node = this._root, + q, + i; + + if (node) quads.push(new Quad(node, x0, y0, x3, y3)); + if (radius == null) radius = Infinity; + else { + x0 = x - radius, y0 = y - radius; + x3 = x + radius, y3 = y + radius; + radius *= radius; + } + + while (q = quads.pop()) { + + // Stop searching if this quadrant can’t contain a closer node. + if (!(node = q.node) + || (x1 = q.x0) > x3 + || (y1 = q.y0) > y3 + || (x2 = q.x1) < x0 + || (y2 = q.y1) < y0) continue; + + // Bisect the current quadrant. + if (node.length) { + var xm = (x1 + x2) / 2, + ym = (y1 + y2) / 2; + + quads.push( + new Quad(node[3], xm, ym, x2, y2), + new Quad(node[2], x1, ym, xm, y2), + new Quad(node[1], xm, y1, x2, ym), + new Quad(node[0], x1, y1, xm, ym) + ); + + // Visit the closest quadrant first. + if (i = (y >= ym) << 1 | (x >= xm)) { + q = quads[quads.length - 1]; + quads[quads.length - 1] = quads[quads.length - 1 - i]; + quads[quads.length - 1 - i] = q; + } + } + + // Visit this point. (Visiting coincident points isn’t necessary!) + else { + var dx = x - +this._x.call(null, node.data), + dy = y - +this._y.call(null, node.data), + d2 = dx * dx + dy * dy; + if (d2 < radius) { + var d = Math.sqrt(radius = d2); + x0 = x - d, y0 = y - d; + x3 = x + d, y3 = y + d; + data = node.data; + } + } + } + + return data; + } + + function tree_remove$1(d) { + if (isNaN(x = +this._x.call(null, d)) || isNaN(y = +this._y.call(null, d))) return this; // ignore invalid points + + var parent, + node = this._root, + retainer, + previous, + next, + x0 = this._x0, + y0 = this._y0, + x1 = this._x1, + y1 = this._y1, + x, + y, + xm, + ym, + right, + bottom, + i, + j; + + // If the tree is empty, initialize the root as a leaf. + if (!node) return this; + + // Find the leaf node for the point. + // While descending, also retain the deepest parent with a non-removed sibling. + if (node.length) while (true) { + if (right = x >= (xm = (x0 + x1) / 2)) x0 = xm; else x1 = xm; + if (bottom = y >= (ym = (y0 + y1) / 2)) y0 = ym; else y1 = ym; + if (!(parent = node, node = node[i = bottom << 1 | right])) return this; + if (!node.length) break; + if (parent[(i + 1) & 3] || parent[(i + 2) & 3] || parent[(i + 3) & 3]) retainer = parent, j = i; + } + + // Find the point to remove. + while (node.data !== d) if (!(previous = node, node = node.next)) return this; + if (next = node.next) delete node.next; + + // If there are multiple coincident points, remove just the point. + if (previous) return (next ? previous.next = next : delete previous.next), this; + + // If this is the root point, remove it. + if (!parent) return this._root = next, this; + + // Remove this leaf. + next ? parent[i] = next : delete parent[i]; + + // If the parent now contains exactly one leaf, collapse superfluous parents. + if ((node = parent[0] || parent[1] || parent[2] || parent[3]) + && node === (parent[3] || parent[2] || parent[1] || parent[0]) + && !node.length) { + if (retainer) retainer[j] = node; + else this._root = node; + } + + return this; + } + + function removeAll$1(data) { + for (var i = 0, n = data.length; i < n; ++i) this.remove(data[i]); + return this; + } + + function tree_root$1() { + return this._root; + } + + function tree_size$1() { + var size = 0; + this.visit(function(node) { + if (!node.length) do ++size; while (node = node.next) + }); + return size; + } + + function tree_visit$1(callback) { + var quads = [], q, node = this._root, child, x0, y0, x1, y1; + if (node) quads.push(new Quad(node, this._x0, this._y0, this._x1, this._y1)); + while (q = quads.pop()) { + if (!callback(node = q.node, x0 = q.x0, y0 = q.y0, x1 = q.x1, y1 = q.y1) && node.length) { + var xm = (x0 + x1) / 2, ym = (y0 + y1) / 2; + if (child = node[3]) quads.push(new Quad(child, xm, ym, x1, y1)); + if (child = node[2]) quads.push(new Quad(child, x0, ym, xm, y1)); + if (child = node[1]) quads.push(new Quad(child, xm, y0, x1, ym)); + if (child = node[0]) quads.push(new Quad(child, x0, y0, xm, ym)); + } + } + return this; + } + + function tree_visitAfter$1(callback) { + var quads = [], next = [], q; + if (this._root) quads.push(new Quad(this._root, this._x0, this._y0, this._x1, this._y1)); + while (q = quads.pop()) { + var node = q.node; + if (node.length) { + var child, x0 = q.x0, y0 = q.y0, x1 = q.x1, y1 = q.y1, xm = (x0 + x1) / 2, ym = (y0 + y1) / 2; + if (child = node[0]) quads.push(new Quad(child, x0, y0, xm, ym)); + if (child = node[1]) quads.push(new Quad(child, xm, y0, x1, ym)); + if (child = node[2]) quads.push(new Quad(child, x0, ym, xm, y1)); + if (child = node[3]) quads.push(new Quad(child, xm, ym, x1, y1)); + } + next.push(q); + } + while (q = next.pop()) { + callback(q.node, q.x0, q.y0, q.x1, q.y1); + } + return this; + } + + function defaultX$1(d) { + return d[0]; + } + + function tree_x$1(_) { + return arguments.length ? (this._x = _, this) : this._x; + } + + function defaultY$1(d) { + return d[1]; + } + + function tree_y$1(_) { + return arguments.length ? (this._y = _, this) : this._y; + } + + function quadtree(nodes, x, y) { + var tree = new Quadtree(x == null ? defaultX$1 : x, y == null ? defaultY$1 : y, NaN, NaN, NaN, NaN); + return nodes == null ? tree : tree.addAll(nodes); + } + + function Quadtree(x, y, x0, y0, x1, y1) { + this._x = x; + this._y = y; + this._x0 = x0; + this._y0 = y0; + this._x1 = x1; + this._y1 = y1; + this._root = undefined; + } + + function leaf_copy$1(leaf) { + var copy = {data: leaf.data}, next = copy; + while (leaf = leaf.next) next = next.next = {data: leaf.data}; + return copy; + } + + var treeProto$1 = quadtree.prototype = Quadtree.prototype; + + treeProto$1.copy = function() { + var copy = new Quadtree(this._x, this._y, this._x0, this._y0, this._x1, this._y1), + node = this._root, + nodes, + child; + + if (!node) return copy; + + if (!node.length) return copy._root = leaf_copy$1(node), copy; + + nodes = [{source: node, target: copy._root = new Array(4)}]; + while (node = nodes.pop()) { + for (var i = 0; i < 4; ++i) { + if (child = node.source[i]) { + if (child.length) nodes.push({source: child, target: node.target[i] = new Array(4)}); + else node.target[i] = leaf_copy$1(child); + } + } + } + + return copy; + }; + + treeProto$1.add = tree_add$1; + treeProto$1.addAll = addAll$1; + treeProto$1.cover = tree_cover$1; + treeProto$1.data = tree_data$1; + treeProto$1.extent = tree_extent$1; + treeProto$1.find = tree_find$1; + treeProto$1.remove = tree_remove$1; + treeProto$1.removeAll = removeAll$1; + treeProto$1.root = tree_root$1; + treeProto$1.size = tree_size$1; + treeProto$1.visit = tree_visit$1; + treeProto$1.visitAfter = tree_visitAfter$1; + treeProto$1.x = tree_x$1; + treeProto$1.y = tree_y$1; + + function tree_add(d) { + const x = +this._x.call(null, d), + y = +this._y.call(null, d), + z = +this._z.call(null, d); + return add(this.cover(x, y, z), x, y, z, d); + } + + function add(tree, x, y, z, d) { + if (isNaN(x) || isNaN(y) || isNaN(z)) return tree; // ignore invalid points + + var parent, + node = tree._root, + leaf = {data: d}, + x0 = tree._x0, + y0 = tree._y0, + z0 = tree._z0, + x1 = tree._x1, + y1 = tree._y1, + z1 = tree._z1, + xm, + ym, + zm, + xp, + yp, + zp, + right, + bottom, + deep, + i, + j; + + // If the tree is empty, initialize the root as a leaf. + if (!node) return tree._root = leaf, tree; + + // Find the existing leaf for the new point, or add it. + while (node.length) { + if (right = x >= (xm = (x0 + x1) / 2)) x0 = xm; else x1 = xm; + if (bottom = y >= (ym = (y0 + y1) / 2)) y0 = ym; else y1 = ym; + if (deep = z >= (zm = (z0 + z1) / 2)) z0 = zm; else z1 = zm; + if (parent = node, !(node = node[i = deep << 2 | bottom << 1 | right])) return parent[i] = leaf, tree; + } + + // Is the new point is exactly coincident with the existing point? + xp = +tree._x.call(null, node.data); + yp = +tree._y.call(null, node.data); + zp = +tree._z.call(null, node.data); + if (x === xp && y === yp && z === zp) return leaf.next = node, parent ? parent[i] = leaf : tree._root = leaf, tree; + + // Otherwise, split the leaf node until the old and new point are separated. + do { + parent = parent ? parent[i] = new Array(8) : tree._root = new Array(8); + if (right = x >= (xm = (x0 + x1) / 2)) x0 = xm; else x1 = xm; + if (bottom = y >= (ym = (y0 + y1) / 2)) y0 = ym; else y1 = ym; + if (deep = z >= (zm = (z0 + z1) / 2)) z0 = zm; else z1 = zm; + } while ((i = deep << 2 | bottom << 1 | right) === (j = (zp >= zm) << 2 | (yp >= ym) << 1 | (xp >= xm))); + return parent[j] = node, parent[i] = leaf, tree; + } + + function addAll(data) { + if (!Array.isArray(data)) data = Array.from(data); + const n = data.length; + const xz = new Float64Array(n); + const yz = new Float64Array(n); + const zz = new Float64Array(n); + let x0 = Infinity, + y0 = Infinity, + z0 = Infinity, + x1 = -Infinity, + y1 = -Infinity, + z1 = -Infinity; + + // Compute the points and their extent. + for (let i = 0, d, x, y, z; i < n; ++i) { + if (isNaN(x = +this._x.call(null, d = data[i])) || isNaN(y = +this._y.call(null, d)) || isNaN(z = +this._z.call(null, d))) continue; + xz[i] = x; + yz[i] = y; + zz[i] = z; + if (x < x0) x0 = x; + if (x > x1) x1 = x; + if (y < y0) y0 = y; + if (y > y1) y1 = y; + if (z < z0) z0 = z; + if (z > z1) z1 = z; + } + + // If there were no (valid) points, abort. + if (x0 > x1 || y0 > y1 || z0 > z1) return this; + + // Expand the tree to cover the new points. + this.cover(x0, y0, z0).cover(x1, y1, z1); + + // Add the new points. + for (let i = 0; i < n; ++i) { + add(this, xz[i], yz[i], zz[i], data[i]); + } + + return this; + } + + function tree_cover(x, y, z) { + if (isNaN(x = +x) || isNaN(y = +y) || isNaN(z = +z)) return this; // ignore invalid points + + var x0 = this._x0, + y0 = this._y0, + z0 = this._z0, + x1 = this._x1, + y1 = this._y1, + z1 = this._z1; + + // If the octree has no extent, initialize them. + // Integer extent are necessary so that if we later double the extent, + // the existing octant boundaries don’t change due to floating point error! + if (isNaN(x0)) { + x1 = (x0 = Math.floor(x)) + 1; + y1 = (y0 = Math.floor(y)) + 1; + z1 = (z0 = Math.floor(z)) + 1; + } + + // Otherwise, double repeatedly to cover. + else { + var t = x1 - x0 || 1, + node = this._root, + parent, + i; + + while (x0 > x || x >= x1 || y0 > y || y >= y1 || z0 > z || z >= z1) { + i = (z < z0) << 2 | (y < y0) << 1 | (x < x0); + parent = new Array(8), parent[i] = node, node = parent, t *= 2; + switch (i) { + case 0: x1 = x0 + t, y1 = y0 + t, z1 = z0 + t; break; + case 1: x0 = x1 - t, y1 = y0 + t, z1 = z0 + t; break; + case 2: x1 = x0 + t, y0 = y1 - t, z1 = z0 + t; break; + case 3: x0 = x1 - t, y0 = y1 - t, z1 = z0 + t; break; + case 4: x1 = x0 + t, y1 = y0 + t, z0 = z1 - t; break; + case 5: x0 = x1 - t, y1 = y0 + t, z0 = z1 - t; break; + case 6: x1 = x0 + t, y0 = y1 - t, z0 = z1 - t; break; + case 7: x0 = x1 - t, y0 = y1 - t, z0 = z1 - t; break; + } + } + + if (this._root && this._root.length) this._root = node; + } + + this._x0 = x0; + this._y0 = y0; + this._z0 = z0; + this._x1 = x1; + this._y1 = y1; + this._z1 = z1; + return this; + } + + function tree_data() { + var data = []; + this.visit(function(node) { + if (!node.length) do data.push(node.data); while (node = node.next) + }); + return data; + } + + function tree_extent(_) { + return arguments.length + ? this.cover(+_[0][0], +_[0][1], +_[0][2]).cover(+_[1][0], +_[1][1], +_[1][2]) + : isNaN(this._x0) ? undefined : [[this._x0, this._y0, this._z0], [this._x1, this._y1, this._z1]]; + } + + function Octant(node, x0, y0, z0, x1, y1, z1) { + this.node = node; + this.x0 = x0; + this.y0 = y0; + this.z0 = z0; + this.x1 = x1; + this.y1 = y1; + this.z1 = z1; + } + + function tree_find(x, y, z, radius) { + var data, + x0 = this._x0, + y0 = this._y0, + z0 = this._z0, + x1, + y1, + z1, + x2, + y2, + z2, + x3 = this._x1, + y3 = this._y1, + z3 = this._z1, + octs = [], + node = this._root, + q, + i; + + if (node) octs.push(new Octant(node, x0, y0, z0, x3, y3, z3)); + if (radius == null) radius = Infinity; + else { + x0 = x - radius, y0 = y - radius, z0 = z - radius; + x3 = x + radius, y3 = y + radius, z3 = z + radius; + radius *= radius; + } + + while (q = octs.pop()) { + + // Stop searching if this octant can’t contain a closer node. + if (!(node = q.node) + || (x1 = q.x0) > x3 + || (y1 = q.y0) > y3 + || (z1 = q.z0) > z3 + || (x2 = q.x1) < x0 + || (y2 = q.y1) < y0 + || (z2 = q.z1) < z0) continue; + + // Bisect the current octant. + if (node.length) { + var xm = (x1 + x2) / 2, + ym = (y1 + y2) / 2, + zm = (z1 + z2) / 2; + + octs.push( + new Octant(node[7], xm, ym, zm, x2, y2, z2), + new Octant(node[6], x1, ym, zm, xm, y2, z2), + new Octant(node[5], xm, y1, zm, x2, ym, z2), + new Octant(node[4], x1, y1, zm, xm, ym, z2), + new Octant(node[3], xm, ym, z1, x2, y2, zm), + new Octant(node[2], x1, ym, z1, xm, y2, zm), + new Octant(node[1], xm, y1, z1, x2, ym, zm), + new Octant(node[0], x1, y1, z1, xm, ym, zm) + ); + + // Visit the closest octant first. + if (i = (z >= zm) << 2 | (y >= ym) << 1 | (x >= xm)) { + q = octs[octs.length - 1]; + octs[octs.length - 1] = octs[octs.length - 1 - i]; + octs[octs.length - 1 - i] = q; + } + } + + // Visit this point. (Visiting coincident points isn’t necessary!) + else { + var dx = x - +this._x.call(null, node.data), + dy = y - +this._y.call(null, node.data), + dz = z - +this._z.call(null, node.data), + d2 = dx * dx + dy * dy + dz * dz; + if (d2 < radius) { + var d = Math.sqrt(radius = d2); + x0 = x - d, y0 = y - d, z0 = z - d; + x3 = x + d, y3 = y + d, z3 = z + d; + data = node.data; + } + } + } + + return data; + } + + function tree_remove(d) { + if (isNaN(x = +this._x.call(null, d)) || isNaN(y = +this._y.call(null, d)) || isNaN(z = +this._z.call(null, d))) return this; // ignore invalid points + + var parent, + node = this._root, + retainer, + previous, + next, + x0 = this._x0, + y0 = this._y0, + z0 = this._z0, + x1 = this._x1, + y1 = this._y1, + z1 = this._z1, + x, + y, + z, + xm, + ym, + zm, + right, + bottom, + deep, + i, + j; + + // If the tree is empty, initialize the root as a leaf. + if (!node) return this; + + // Find the leaf node for the point. + // While descending, also retain the deepest parent with a non-removed sibling. + if (node.length) while (true) { + if (right = x >= (xm = (x0 + x1) / 2)) x0 = xm; else x1 = xm; + if (bottom = y >= (ym = (y0 + y1) / 2)) y0 = ym; else y1 = ym; + if (deep = z >= (zm = (z0 + z1) / 2)) z0 = zm; else z1 = zm; + if (!(parent = node, node = node[i = deep << 2 | bottom << 1 | right])) return this; + if (!node.length) break; + if (parent[(i + 1) & 7] || parent[(i + 2) & 7] || parent[(i + 3) & 7] || parent[(i + 4) & 7] || parent[(i + 5) & 7] || parent[(i + 6) & 7] || parent[(i + 7) & 7]) retainer = parent, j = i; + } + + // Find the point to remove. + while (node.data !== d) if (!(previous = node, node = node.next)) return this; + if (next = node.next) delete node.next; + + // If there are multiple coincident points, remove just the point. + if (previous) return (next ? previous.next = next : delete previous.next), this; + + // If this is the root point, remove it. + if (!parent) return this._root = next, this; + + // Remove this leaf. + next ? parent[i] = next : delete parent[i]; + + // If the parent now contains exactly one leaf, collapse superfluous parents. + if ((node = parent[0] || parent[1] || parent[2] || parent[3] || parent[4] || parent[5] || parent[6] || parent[7]) + && node === (parent[7] || parent[6] || parent[5] || parent[4] || parent[3] || parent[2] || parent[1] || parent[0]) + && !node.length) { + if (retainer) retainer[j] = node; + else this._root = node; + } + + return this; + } + + function removeAll(data) { + for (var i = 0, n = data.length; i < n; ++i) this.remove(data[i]); + return this; + } + + function tree_root() { + return this._root; + } + + function tree_size() { + var size = 0; + this.visit(function(node) { + if (!node.length) do ++size; while (node = node.next) + }); + return size; + } + + function tree_visit(callback) { + var octs = [], q, node = this._root, child, x0, y0, z0, x1, y1, z1; + if (node) octs.push(new Octant(node, this._x0, this._y0, this._z0, this._x1, this._y1, this._z1)); + while (q = octs.pop()) { + if (!callback(node = q.node, x0 = q.x0, y0 = q.y0, z0 = q.z0, x1 = q.x1, y1 = q.y1, z1 = q.z1) && node.length) { + var xm = (x0 + x1) / 2, ym = (y0 + y1) / 2, zm = (z0 + z1) / 2; + if (child = node[7]) octs.push(new Octant(child, xm, ym, zm, x1, y1, z1)); + if (child = node[6]) octs.push(new Octant(child, x0, ym, zm, xm, y1, z1)); + if (child = node[5]) octs.push(new Octant(child, xm, y0, zm, x1, ym, z1)); + if (child = node[4]) octs.push(new Octant(child, x0, y0, zm, xm, ym, z1)); + if (child = node[3]) octs.push(new Octant(child, xm, ym, z0, x1, y1, zm)); + if (child = node[2]) octs.push(new Octant(child, x0, ym, z0, xm, y1, zm)); + if (child = node[1]) octs.push(new Octant(child, xm, y0, z0, x1, ym, zm)); + if (child = node[0]) octs.push(new Octant(child, x0, y0, z0, xm, ym, zm)); + } + } + return this; + } + + function tree_visitAfter(callback) { + var octs = [], next = [], q; + if (this._root) octs.push(new Octant(this._root, this._x0, this._y0, this._z0, this._x1, this._y1, this._z1)); + while (q = octs.pop()) { + var node = q.node; + if (node.length) { + var child, x0 = q.x0, y0 = q.y0, z0 = q.z0, x1 = q.x1, y1 = q.y1, z1 = q.z1, xm = (x0 + x1) / 2, ym = (y0 + y1) / 2, zm = (z0 + z1) / 2; + if (child = node[0]) octs.push(new Octant(child, x0, y0, z0, xm, ym, zm)); + if (child = node[1]) octs.push(new Octant(child, xm, y0, z0, x1, ym, zm)); + if (child = node[2]) octs.push(new Octant(child, x0, ym, z0, xm, y1, zm)); + if (child = node[3]) octs.push(new Octant(child, xm, ym, z0, x1, y1, zm)); + if (child = node[4]) octs.push(new Octant(child, x0, y0, zm, xm, ym, z1)); + if (child = node[5]) octs.push(new Octant(child, xm, y0, zm, x1, ym, z1)); + if (child = node[6]) octs.push(new Octant(child, x0, ym, zm, xm, y1, z1)); + if (child = node[7]) octs.push(new Octant(child, xm, ym, zm, x1, y1, z1)); + } + next.push(q); + } + while (q = next.pop()) { + callback(q.node, q.x0, q.y0, q.z0, q.x1, q.y1, q.z1); + } + return this; + } + + function defaultX(d) { + return d[0]; + } + + function tree_x(_) { + return arguments.length ? (this._x = _, this) : this._x; + } + + function defaultY(d) { + return d[1]; + } + + function tree_y(_) { + return arguments.length ? (this._y = _, this) : this._y; + } + + function defaultZ(d) { + return d[2]; + } + + function tree_z(_) { + return arguments.length ? (this._z = _, this) : this._z; + } + + function octree(nodes, x, y, z) { + var tree = new Octree(x == null ? defaultX : x, y == null ? defaultY : y, z == null ? defaultZ : z, NaN, NaN, NaN, NaN, NaN, NaN); + return nodes == null ? tree : tree.addAll(nodes); + } + + function Octree(x, y, z, x0, y0, z0, x1, y1, z1) { + this._x = x; + this._y = y; + this._z = z; + this._x0 = x0; + this._y0 = y0; + this._z0 = z0; + this._x1 = x1; + this._y1 = y1; + this._z1 = z1; + this._root = undefined; + } + + function leaf_copy(leaf) { + var copy = {data: leaf.data}, next = copy; + while (leaf = leaf.next) next = next.next = {data: leaf.data}; + return copy; + } + + var treeProto = octree.prototype = Octree.prototype; + + treeProto.copy = function() { + var copy = new Octree(this._x, this._y, this._z, this._x0, this._y0, this._z0, this._x1, this._y1, this._z1), + node = this._root, + nodes, + child; + + if (!node) return copy; + + if (!node.length) return copy._root = leaf_copy(node), copy; + + nodes = [{source: node, target: copy._root = new Array(8)}]; + while (node = nodes.pop()) { + for (var i = 0; i < 8; ++i) { + if (child = node.source[i]) { + if (child.length) nodes.push({source: child, target: node.target[i] = new Array(8)}); + else node.target[i] = leaf_copy(child); + } + } + } + + return copy; + }; + + treeProto.add = tree_add; + treeProto.addAll = addAll; + treeProto.cover = tree_cover; + treeProto.data = tree_data; + treeProto.extent = tree_extent; + treeProto.find = tree_find; + treeProto.remove = tree_remove; + treeProto.removeAll = removeAll; + treeProto.root = tree_root; + treeProto.size = tree_size; + treeProto.visit = tree_visit; + treeProto.visitAfter = tree_visitAfter; + treeProto.x = tree_x; + treeProto.y = tree_y; + treeProto.z = tree_z; + + function constant(x) { + return function() { + return x; + }; + } + + function jiggle(random) { + return (random() - 0.5) * 1e-6; + } + + function index$1(d) { + return d.index; + } + + function find(nodeById, nodeId) { + var node = nodeById.get(nodeId); + if (!node) throw new Error("node not found: " + nodeId); + return node; + } + + function d3ForceLink(links) { + var id = index$1, + strength = defaultStrength, + strengths, + distance = constant(30), + distances, + nodes, + nDim, + count, + bias, + random, + iterations = 1; + + if (links == null) links = []; + + function defaultStrength(link) { + return 1 / Math.min(count[link.source.index], count[link.target.index]); + } + + function force(alpha) { + for (var k = 0, n = links.length; k < iterations; ++k) { + for (var i = 0, link, source, target, x = 0, y = 0, z = 0, l, b; i < n; ++i) { + link = links[i], source = link.source, target = link.target; + x = target.x + target.vx - source.x - source.vx || jiggle(random); + if (nDim > 1) { y = target.y + target.vy - source.y - source.vy || jiggle(random); } + if (nDim > 2) { z = target.z + target.vz - source.z - source.vz || jiggle(random); } + l = Math.sqrt(x * x + y * y + z * z); + l = (l - distances[i]) / l * alpha * strengths[i]; + x *= l, y *= l, z *= l; + + target.vx -= x * (b = bias[i]); + if (nDim > 1) { target.vy -= y * b; } + if (nDim > 2) { target.vz -= z * b; } + + source.vx += x * (b = 1 - b); + if (nDim > 1) { source.vy += y * b; } + if (nDim > 2) { source.vz += z * b; } + } + } + } + + function initialize() { + if (!nodes) return; + + var i, + n = nodes.length, + m = links.length, + nodeById = new Map(nodes.map((d, i) => [id(d, i, nodes), d])), + link; + + for (i = 0, count = new Array(n); i < m; ++i) { + link = links[i], link.index = i; + if (typeof link.source !== "object") link.source = find(nodeById, link.source); + if (typeof link.target !== "object") link.target = find(nodeById, link.target); + count[link.source.index] = (count[link.source.index] || 0) + 1; + count[link.target.index] = (count[link.target.index] || 0) + 1; + } + + for (i = 0, bias = new Array(m); i < m; ++i) { + link = links[i], bias[i] = count[link.source.index] / (count[link.source.index] + count[link.target.index]); + } + + strengths = new Array(m), initializeStrength(); + distances = new Array(m), initializeDistance(); + } + + function initializeStrength() { + if (!nodes) return; + + for (var i = 0, n = links.length; i < n; ++i) { + strengths[i] = +strength(links[i], i, links); + } + } + + function initializeDistance() { + if (!nodes) return; + + for (var i = 0, n = links.length; i < n; ++i) { + distances[i] = +distance(links[i], i, links); + } + } + + force.initialize = function(_nodes, ...args) { + nodes = _nodes; + random = args.find(arg => typeof arg === 'function') || Math.random; + nDim = args.find(arg => [1, 2, 3].includes(arg)) || 2; + initialize(); + }; + + force.links = function(_) { + return arguments.length ? (links = _, initialize(), force) : links; + }; + + force.id = function(_) { + return arguments.length ? (id = _, force) : id; + }; + + force.iterations = function(_) { + return arguments.length ? (iterations = +_, force) : iterations; + }; + + force.strength = function(_) { + return arguments.length ? (strength = typeof _ === "function" ? _ : constant(+_), initializeStrength(), force) : strength; + }; + + force.distance = function(_) { + return arguments.length ? (distance = typeof _ === "function" ? _ : constant(+_), initializeDistance(), force) : distance; + }; + + return force; + } + + // https://en.wikipedia.org/wiki/Linear_congruential_generator#Parameters_in_common_use + const a = 1664525; + const c = 1013904223; + const m = 4294967296; // 2^32 + + function lcg() { + let s = 1; + return () => (s = (a * s + c) % m) / m; + } + + var MAX_DIMENSIONS = 3; + + function x(d) { + return d.x; + } + + function y(d) { + return d.y; + } + + function z(d) { + return d.z; + } + + var initialRadius = 10, + initialAngleRoll = Math.PI * (3 - Math.sqrt(5)), // Golden ratio angle + initialAngleYaw = Math.PI * 20 / (9 + Math.sqrt(221)); // Markov irrational number + + function d3ForceSimulation(nodes, numDimensions) { + numDimensions = numDimensions || 2; + + var nDim = Math.min(MAX_DIMENSIONS, Math.max(1, Math.round(numDimensions))), + simulation, + alpha = 1, + alphaMin = 0.001, + alphaDecay = 1 - Math.pow(alphaMin, 1 / 300), + alphaTarget = 0, + velocityDecay = 0.6, + forces = new Map(), + stepper = timer(step), + event = dispatch("tick", "end"), + random = lcg(); + + if (nodes == null) nodes = []; + + function step() { + tick(); + event.call("tick", simulation); + if (alpha < alphaMin) { + stepper.stop(); + event.call("end", simulation); + } + } + + function tick(iterations) { + var i, n = nodes.length, node; + + if (iterations === undefined) iterations = 1; + + for (var k = 0; k < iterations; ++k) { + alpha += (alphaTarget - alpha) * alphaDecay; + + forces.forEach(function (force) { + force(alpha); + }); + + for (i = 0; i < n; ++i) { + node = nodes[i]; + if (node.fx == null) node.x += node.vx *= velocityDecay; + else node.x = node.fx, node.vx = 0; + if (nDim > 1) { + if (node.fy == null) node.y += node.vy *= velocityDecay; + else node.y = node.fy, node.vy = 0; + } + if (nDim > 2) { + if (node.fz == null) node.z += node.vz *= velocityDecay; + else node.z = node.fz, node.vz = 0; + } + } + } + + return simulation; + } + + function initializeNodes() { + for (var i = 0, n = nodes.length, node; i < n; ++i) { + node = nodes[i], node.index = i; + if (node.fx != null) node.x = node.fx; + if (node.fy != null) node.y = node.fy; + if (node.fz != null) node.z = node.fz; + if (isNaN(node.x) || (nDim > 1 && isNaN(node.y)) || (nDim > 2 && isNaN(node.z))) { + var radius = initialRadius * (nDim > 2 ? Math.cbrt(0.5 + i) : (nDim > 1 ? Math.sqrt(0.5 + i) : i)), + rollAngle = i * initialAngleRoll, + yawAngle = i * initialAngleYaw; + + if (nDim === 1) { + node.x = radius; + } else if (nDim === 2) { + node.x = radius * Math.cos(rollAngle); + node.y = radius * Math.sin(rollAngle); + } else { // 3 dimensions: use spherical distribution along 2 irrational number angles + node.x = radius * Math.sin(rollAngle) * Math.cos(yawAngle); + node.y = radius * Math.cos(rollAngle); + node.z = radius * Math.sin(rollAngle) * Math.sin(yawAngle); + } + } + if (isNaN(node.vx) || (nDim > 1 && isNaN(node.vy)) || (nDim > 2 && isNaN(node.vz))) { + node.vx = 0; + if (nDim > 1) { node.vy = 0; } + if (nDim > 2) { node.vz = 0; } + } + } + } + + function initializeForce(force) { + if (force.initialize) force.initialize(nodes, random, nDim); + return force; + } + + initializeNodes(); + + return simulation = { + tick: tick, + + restart: function() { + return stepper.restart(step), simulation; + }, + + stop: function() { + return stepper.stop(), simulation; + }, + + numDimensions: function(_) { + return arguments.length + ? (nDim = Math.min(MAX_DIMENSIONS, Math.max(1, Math.round(_))), forces.forEach(initializeForce), simulation) + : nDim; + }, + + nodes: function(_) { + return arguments.length ? (nodes = _, initializeNodes(), forces.forEach(initializeForce), simulation) : nodes; + }, + + alpha: function(_) { + return arguments.length ? (alpha = +_, simulation) : alpha; + }, + + alphaMin: function(_) { + return arguments.length ? (alphaMin = +_, simulation) : alphaMin; + }, + + alphaDecay: function(_) { + return arguments.length ? (alphaDecay = +_, simulation) : +alphaDecay; + }, + + alphaTarget: function(_) { + return arguments.length ? (alphaTarget = +_, simulation) : alphaTarget; + }, + + velocityDecay: function(_) { + return arguments.length ? (velocityDecay = 1 - _, simulation) : 1 - velocityDecay; + }, + + randomSource: function(_) { + return arguments.length ? (random = _, forces.forEach(initializeForce), simulation) : random; + }, + + force: function(name, _) { + return arguments.length > 1 ? ((_ == null ? forces.delete(name) : forces.set(name, initializeForce(_))), simulation) : forces.get(name); + }, + + find: function() { + var args = Array.prototype.slice.call(arguments); + var x = args.shift() || 0, + y = (nDim > 1 ? args.shift() : null) || 0, + z = (nDim > 2 ? args.shift() : null) || 0, + radius = args.shift() || Infinity; + + var i = 0, + n = nodes.length, + dx, + dy, + dz, + d2, + node, + closest; + + radius *= radius; + + for (i = 0; i < n; ++i) { + node = nodes[i]; + dx = x - node.x; + dy = y - (node.y || 0); + dz = z - (node.z ||0); + d2 = dx * dx + dy * dy + dz * dz; + if (d2 < radius) closest = node, radius = d2; + } + + return closest; + }, + + on: function(name, _) { + return arguments.length > 1 ? (event.on(name, _), simulation) : event.on(name); + } + }; + } + + function d3ForceManyBody() { + var nodes, + nDim, + node, + random, + alpha, + strength = constant(-30), + strengths, + distanceMin2 = 1, + distanceMax2 = Infinity, + theta2 = 0.81; + + function force(_) { + var i, + n = nodes.length, + tree = + (nDim === 1 ? binarytree(nodes, x) + :(nDim === 2 ? quadtree(nodes, x, y) + :(nDim === 3 ? octree(nodes, x, y, z) + :null + ))).visitAfter(accumulate); + + for (alpha = _, i = 0; i < n; ++i) node = nodes[i], tree.visit(apply); + } + + function initialize() { + if (!nodes) return; + var i, n = nodes.length, node; + strengths = new Array(n); + for (i = 0; i < n; ++i) node = nodes[i], strengths[node.index] = +strength(node, i, nodes); + } + + function accumulate(treeNode) { + var strength = 0, q, c, weight = 0, x, y, z, i; + var numChildren = treeNode.length; + + // For internal nodes, accumulate forces from children. + if (numChildren) { + for (x = y = z = i = 0; i < numChildren; ++i) { + if ((q = treeNode[i]) && (c = Math.abs(q.value))) { + strength += q.value, weight += c, x += c * (q.x || 0), y += c * (q.y || 0), z += c * (q.z || 0); + } + } + strength *= Math.sqrt(4 / numChildren); // scale accumulated strength according to number of dimensions + + treeNode.x = x / weight; + if (nDim > 1) { treeNode.y = y / weight; } + if (nDim > 2) { treeNode.z = z / weight; } + } + + // For leaf nodes, accumulate forces from coincident nodes. + else { + q = treeNode; + q.x = q.data.x; + if (nDim > 1) { q.y = q.data.y; } + if (nDim > 2) { q.z = q.data.z; } + do strength += strengths[q.data.index]; + while (q = q.next); + } + + treeNode.value = strength; + } + + function apply(treeNode, x1, arg1, arg2, arg3) { + if (!treeNode.value) return true; + var x2 = [arg1, arg2, arg3][nDim-1]; + + var x = treeNode.x - node.x, + y = (nDim > 1 ? treeNode.y - node.y : 0), + z = (nDim > 2 ? treeNode.z - node.z : 0), + w = x2 - x1, + l = x * x + y * y + z * z; + + // Apply the Barnes-Hut approximation if possible. + // Limit forces for very close nodes; randomize direction if coincident. + if (w * w / theta2 < l) { + if (l < distanceMax2) { + if (x === 0) x = jiggle(random), l += x * x; + if (nDim > 1 && y === 0) y = jiggle(random), l += y * y; + if (nDim > 2 && z === 0) z = jiggle(random), l += z * z; + if (l < distanceMin2) l = Math.sqrt(distanceMin2 * l); + node.vx += x * treeNode.value * alpha / l; + if (nDim > 1) { node.vy += y * treeNode.value * alpha / l; } + if (nDim > 2) { node.vz += z * treeNode.value * alpha / l; } + } + return true; + } + + // Otherwise, process points directly. + else if (treeNode.length || l >= distanceMax2) return; + + // Limit forces for very close nodes; randomize direction if coincident. + if (treeNode.data !== node || treeNode.next) { + if (x === 0) x = jiggle(random), l += x * x; + if (nDim > 1 && y === 0) y = jiggle(random), l += y * y; + if (nDim > 2 && z === 0) z = jiggle(random), l += z * z; + if (l < distanceMin2) l = Math.sqrt(distanceMin2 * l); + } + + do if (treeNode.data !== node) { + w = strengths[treeNode.data.index] * alpha / l; + node.vx += x * w; + if (nDim > 1) { node.vy += y * w; } + if (nDim > 2) { node.vz += z * w; } + } while (treeNode = treeNode.next); + } + + force.initialize = function(_nodes, ...args) { + nodes = _nodes; + random = args.find(arg => typeof arg === 'function') || Math.random; + nDim = args.find(arg => [1, 2, 3].includes(arg)) || 2; + initialize(); + }; + + force.strength = function(_) { + return arguments.length ? (strength = typeof _ === "function" ? _ : constant(+_), initialize(), force) : strength; + }; + + force.distanceMin = function(_) { + return arguments.length ? (distanceMin2 = _ * _, force) : Math.sqrt(distanceMin2); + }; + + force.distanceMax = function(_) { + return arguments.length ? (distanceMax2 = _ * _, force) : Math.sqrt(distanceMax2); + }; + + force.theta = function(_) { + return arguments.length ? (theta2 = _ * _, force) : Math.sqrt(theta2); + }; + + return force; + } + + function d3ForceRadial(radius, x, y, z) { + var nodes, + nDim, + strength = constant(0.1), + strengths, + radiuses; + + if (typeof radius !== "function") radius = constant(+radius); + if (x == null) x = 0; + if (y == null) y = 0; + if (z == null) z = 0; + + function force(alpha) { + for (var i = 0, n = nodes.length; i < n; ++i) { + var node = nodes[i], + dx = node.x - x || 1e-6, + dy = (node.y || 0) - y || 1e-6, + dz = (node.z || 0) - z || 1e-6, + r = Math.sqrt(dx * dx + dy * dy + dz * dz), + k = (radiuses[i] - r) * strengths[i] * alpha / r; + node.vx += dx * k; + if (nDim>1) { node.vy += dy * k; } + if (nDim>2) { node.vz += dz * k; } + } + } + + function initialize() { + if (!nodes) return; + var i, n = nodes.length; + strengths = new Array(n); + radiuses = new Array(n); + for (i = 0; i < n; ++i) { + radiuses[i] = +radius(nodes[i], i, nodes); + strengths[i] = isNaN(radiuses[i]) ? 0 : +strength(nodes[i], i, nodes); + } + } + + force.initialize = function(initNodes, ...args) { + nodes = initNodes; + nDim = args.find(arg => [1, 2, 3].includes(arg)) || 2; + initialize(); + }; + + force.strength = function(_) { + return arguments.length ? (strength = typeof _ === "function" ? _ : constant(+_), initialize(), force) : strength; + }; + + force.radius = function(_) { + return arguments.length ? (radius = typeof _ === "function" ? _ : constant(+_), initialize(), force) : radius; + }; + + force.x = function(_) { + return arguments.length ? (x = +_, force) : x; + }; + + force.y = function(_) { + return arguments.length ? (y = +_, force) : y; + }; + + force.z = function(_) { + return arguments.length ? (z = +_, force) : z; + }; + + return force; + } + + // math-inlining. + const { abs: abs$1, cos: cos$1, sin: sin$1, acos: acos$1, atan2, sqrt: sqrt$1, pow } = Math; + + // cube root function yielding real roots + function crt(v) { + return v < 0 ? -pow(-v, 1 / 3) : pow(v, 1 / 3); + } + + // trig constants + const pi$1 = Math.PI, + tau = 2 * pi$1, + quart = pi$1 / 2, + // float precision significant decimal + epsilon = 0.000001, + // extremas used in bbox calculation and similar algorithms + nMax = Number.MAX_SAFE_INTEGER || 9007199254740991, + nMin = Number.MIN_SAFE_INTEGER || -9007199254740991, + // a zero coordinate, which is surprisingly useful + ZERO = { x: 0, y: 0, z: 0 }; + + // Bezier utility functions + const utils = { + // Legendre-Gauss abscissae with n=24 (x_i values, defined at i=n as the roots of the nth order Legendre polynomial Pn(x)) + Tvalues: [ + -0.0640568928626056260850430826247450385909, + 0.0640568928626056260850430826247450385909, + -0.1911188674736163091586398207570696318404, + 0.1911188674736163091586398207570696318404, + -0.3150426796961633743867932913198102407864, + 0.3150426796961633743867932913198102407864, + -0.4337935076260451384870842319133497124524, + 0.4337935076260451384870842319133497124524, + -0.5454214713888395356583756172183723700107, + 0.5454214713888395356583756172183723700107, + -0.6480936519369755692524957869107476266696, + 0.6480936519369755692524957869107476266696, + -0.7401241915785543642438281030999784255232, + 0.7401241915785543642438281030999784255232, + -0.8200019859739029219539498726697452080761, + 0.8200019859739029219539498726697452080761, + -0.8864155270044010342131543419821967550873, + 0.8864155270044010342131543419821967550873, + -0.9382745520027327585236490017087214496548, + 0.9382745520027327585236490017087214496548, + -0.9747285559713094981983919930081690617411, + 0.9747285559713094981983919930081690617411, + -0.9951872199970213601799974097007368118745, + 0.9951872199970213601799974097007368118745, + ], + + // Legendre-Gauss weights with n=24 (w_i values, defined by a function linked to in the Bezier primer article) + Cvalues: [ + 0.1279381953467521569740561652246953718517, + 0.1279381953467521569740561652246953718517, + 0.1258374563468282961213753825111836887264, + 0.1258374563468282961213753825111836887264, + 0.121670472927803391204463153476262425607, + 0.121670472927803391204463153476262425607, + 0.1155056680537256013533444839067835598622, + 0.1155056680537256013533444839067835598622, + 0.1074442701159656347825773424466062227946, + 0.1074442701159656347825773424466062227946, + 0.0976186521041138882698806644642471544279, + 0.0976186521041138882698806644642471544279, + 0.086190161531953275917185202983742667185, + 0.086190161531953275917185202983742667185, + 0.0733464814110803057340336152531165181193, + 0.0733464814110803057340336152531165181193, + 0.0592985849154367807463677585001085845412, + 0.0592985849154367807463677585001085845412, + 0.0442774388174198061686027482113382288593, + 0.0442774388174198061686027482113382288593, + 0.0285313886289336631813078159518782864491, + 0.0285313886289336631813078159518782864491, + 0.0123412297999871995468056670700372915759, + 0.0123412297999871995468056670700372915759, + ], + + arcfn: function (t, derivativeFn) { + const d = derivativeFn(t); + let l = d.x * d.x + d.y * d.y; + if (typeof d.z !== "undefined") { + l += d.z * d.z; + } + return sqrt$1(l); + }, + + compute: function (t, points, _3d) { + // shortcuts + if (t === 0) { + points[0].t = 0; + return points[0]; + } + + const order = points.length - 1; + + if (t === 1) { + points[order].t = 1; + return points[order]; + } + + const mt = 1 - t; + let p = points; + + // constant? + if (order === 0) { + points[0].t = t; + return points[0]; + } + + // linear? + if (order === 1) { + const ret = { + x: mt * p[0].x + t * p[1].x, + y: mt * p[0].y + t * p[1].y, + t: t, + }; + if (_3d) { + ret.z = mt * p[0].z + t * p[1].z; + } + return ret; + } + + // quadratic/cubic curve? + if (order < 4) { + let mt2 = mt * mt, + t2 = t * t, + a, + b, + c, + d = 0; + if (order === 2) { + p = [p[0], p[1], p[2], ZERO]; + a = mt2; + b = mt * t * 2; + c = t2; + } else if (order === 3) { + a = mt2 * mt; + b = mt2 * t * 3; + c = mt * t2 * 3; + d = t * t2; + } + const ret = { + x: a * p[0].x + b * p[1].x + c * p[2].x + d * p[3].x, + y: a * p[0].y + b * p[1].y + c * p[2].y + d * p[3].y, + t: t, + }; + if (_3d) { + ret.z = a * p[0].z + b * p[1].z + c * p[2].z + d * p[3].z; + } + return ret; + } + + // higher order curves: use de Casteljau's computation + const dCpts = JSON.parse(JSON.stringify(points)); + while (dCpts.length > 1) { + for (let i = 0; i < dCpts.length - 1; i++) { + dCpts[i] = { + x: dCpts[i].x + (dCpts[i + 1].x - dCpts[i].x) * t, + y: dCpts[i].y + (dCpts[i + 1].y - dCpts[i].y) * t, + }; + if (typeof dCpts[i].z !== "undefined") { + dCpts[i].z = dCpts[i].z + (dCpts[i + 1].z - dCpts[i].z) * t; + } + } + dCpts.splice(dCpts.length - 1, 1); + } + dCpts[0].t = t; + return dCpts[0]; + }, + + computeWithRatios: function (t, points, ratios, _3d) { + const mt = 1 - t, + r = ratios, + p = points; + + let f1 = r[0], + f2 = r[1], + f3 = r[2], + f4 = r[3], + d; + + // spec for linear + f1 *= mt; + f2 *= t; + + if (p.length === 2) { + d = f1 + f2; + return { + x: (f1 * p[0].x + f2 * p[1].x) / d, + y: (f1 * p[0].y + f2 * p[1].y) / d, + z: !_3d ? false : (f1 * p[0].z + f2 * p[1].z) / d, + t: t, + }; + } + + // upgrade to quadratic + f1 *= mt; + f2 *= 2 * mt; + f3 *= t * t; + + if (p.length === 3) { + d = f1 + f2 + f3; + return { + x: (f1 * p[0].x + f2 * p[1].x + f3 * p[2].x) / d, + y: (f1 * p[0].y + f2 * p[1].y + f3 * p[2].y) / d, + z: !_3d ? false : (f1 * p[0].z + f2 * p[1].z + f3 * p[2].z) / d, + t: t, + }; + } + + // upgrade to cubic + f1 *= mt; + f2 *= 1.5 * mt; + f3 *= 3 * mt; + f4 *= t * t * t; + + if (p.length === 4) { + d = f1 + f2 + f3 + f4; + return { + x: (f1 * p[0].x + f2 * p[1].x + f3 * p[2].x + f4 * p[3].x) / d, + y: (f1 * p[0].y + f2 * p[1].y + f3 * p[2].y + f4 * p[3].y) / d, + z: !_3d + ? false + : (f1 * p[0].z + f2 * p[1].z + f3 * p[2].z + f4 * p[3].z) / d, + t: t, + }; + } + }, + + derive: function (points, _3d) { + const dpoints = []; + for (let p = points, d = p.length, c = d - 1; d > 1; d--, c--) { + const list = []; + for (let j = 0, dpt; j < c; j++) { + dpt = { + x: c * (p[j + 1].x - p[j].x), + y: c * (p[j + 1].y - p[j].y), + }; + if (_3d) { + dpt.z = c * (p[j + 1].z - p[j].z); + } + list.push(dpt); + } + dpoints.push(list); + p = list; + } + return dpoints; + }, + + between: function (v, m, M) { + return ( + (m <= v && v <= M) || + utils.approximately(v, m) || + utils.approximately(v, M) + ); + }, + + approximately: function (a, b, precision) { + return abs$1(a - b) <= (precision || epsilon); + }, + + length: function (derivativeFn) { + const z = 0.5, + len = utils.Tvalues.length; + + let sum = 0; + + for (let i = 0, t; i < len; i++) { + t = z * utils.Tvalues[i] + z; + sum += utils.Cvalues[i] * utils.arcfn(t, derivativeFn); + } + return z * sum; + }, + + map: function (v, ds, de, ts, te) { + const d1 = de - ds, + d2 = te - ts, + v2 = v - ds, + r = v2 / d1; + return ts + d2 * r; + }, + + lerp: function (r, v1, v2) { + const ret = { + x: v1.x + r * (v2.x - v1.x), + y: v1.y + r * (v2.y - v1.y), + }; + if (v1.z !== undefined && v2.z !== undefined) { + ret.z = v1.z + r * (v2.z - v1.z); + } + return ret; + }, + + pointToString: function (p) { + let s = p.x + "/" + p.y; + if (typeof p.z !== "undefined") { + s += "/" + p.z; + } + return s; + }, + + pointsToString: function (points) { + return "[" + points.map(utils.pointToString).join(", ") + "]"; + }, + + copy: function (obj) { + return JSON.parse(JSON.stringify(obj)); + }, + + angle: function (o, v1, v2) { + const dx1 = v1.x - o.x, + dy1 = v1.y - o.y, + dx2 = v2.x - o.x, + dy2 = v2.y - o.y, + cross = dx1 * dy2 - dy1 * dx2, + dot = dx1 * dx2 + dy1 * dy2; + return atan2(cross, dot); + }, + + // round as string, to avoid rounding errors + round: function (v, d) { + const s = "" + v; + const pos = s.indexOf("."); + return parseFloat(s.substring(0, pos + 1 + d)); + }, + + dist: function (p1, p2) { + const dx = p1.x - p2.x, + dy = p1.y - p2.y; + return sqrt$1(dx * dx + dy * dy); + }, + + closest: function (LUT, point) { + let mdist = pow(2, 63), + mpos, + d; + LUT.forEach(function (p, idx) { + d = utils.dist(point, p); + if (d < mdist) { + mdist = d; + mpos = idx; + } + }); + return { mdist: mdist, mpos: mpos }; + }, + + abcratio: function (t, n) { + // see ratio(t) note on http://pomax.github.io/bezierinfo/#abc + if (n !== 2 && n !== 3) { + return false; + } + if (typeof t === "undefined") { + t = 0.5; + } else if (t === 0 || t === 1) { + return t; + } + const bottom = pow(t, n) + pow(1 - t, n), + top = bottom - 1; + return abs$1(top / bottom); + }, + + projectionratio: function (t, n) { + // see u(t) note on http://pomax.github.io/bezierinfo/#abc + if (n !== 2 && n !== 3) { + return false; + } + if (typeof t === "undefined") { + t = 0.5; + } else if (t === 0 || t === 1) { + return t; + } + const top = pow(1 - t, n), + bottom = pow(t, n) + top; + return top / bottom; + }, + + lli8: function (x1, y1, x2, y2, x3, y3, x4, y4) { + const nx = + (x1 * y2 - y1 * x2) * (x3 - x4) - (x1 - x2) * (x3 * y4 - y3 * x4), + ny = (x1 * y2 - y1 * x2) * (y3 - y4) - (y1 - y2) * (x3 * y4 - y3 * x4), + d = (x1 - x2) * (y3 - y4) - (y1 - y2) * (x3 - x4); + if (d == 0) { + return false; + } + return { x: nx / d, y: ny / d }; + }, + + lli4: function (p1, p2, p3, p4) { + const x1 = p1.x, + y1 = p1.y, + x2 = p2.x, + y2 = p2.y, + x3 = p3.x, + y3 = p3.y, + x4 = p4.x, + y4 = p4.y; + return utils.lli8(x1, y1, x2, y2, x3, y3, x4, y4); + }, + + lli: function (v1, v2) { + return utils.lli4(v1, v1.c, v2, v2.c); + }, + + makeline: function (p1, p2) { + return new Bezier( + p1.x, + p1.y, + (p1.x + p2.x) / 2, + (p1.y + p2.y) / 2, + p2.x, + p2.y + ); + }, + + findbbox: function (sections) { + let mx = nMax, + my = nMax, + MX = nMin, + MY = nMin; + sections.forEach(function (s) { + const bbox = s.bbox(); + if (mx > bbox.x.min) mx = bbox.x.min; + if (my > bbox.y.min) my = bbox.y.min; + if (MX < bbox.x.max) MX = bbox.x.max; + if (MY < bbox.y.max) MY = bbox.y.max; + }); + return { + x: { min: mx, mid: (mx + MX) / 2, max: MX, size: MX - mx }, + y: { min: my, mid: (my + MY) / 2, max: MY, size: MY - my }, + }; + }, + + shapeintersections: function ( + s1, + bbox1, + s2, + bbox2, + curveIntersectionThreshold + ) { + if (!utils.bboxoverlap(bbox1, bbox2)) return []; + const intersections = []; + const a1 = [s1.startcap, s1.forward, s1.back, s1.endcap]; + const a2 = [s2.startcap, s2.forward, s2.back, s2.endcap]; + a1.forEach(function (l1) { + if (l1.virtual) return; + a2.forEach(function (l2) { + if (l2.virtual) return; + const iss = l1.intersects(l2, curveIntersectionThreshold); + if (iss.length > 0) { + iss.c1 = l1; + iss.c2 = l2; + iss.s1 = s1; + iss.s2 = s2; + intersections.push(iss); + } + }); + }); + return intersections; + }, + + makeshape: function (forward, back, curveIntersectionThreshold) { + const bpl = back.points.length; + const fpl = forward.points.length; + const start = utils.makeline(back.points[bpl - 1], forward.points[0]); + const end = utils.makeline(forward.points[fpl - 1], back.points[0]); + const shape = { + startcap: start, + forward: forward, + back: back, + endcap: end, + bbox: utils.findbbox([start, forward, back, end]), + }; + shape.intersections = function (s2) { + return utils.shapeintersections( + shape, + shape.bbox, + s2, + s2.bbox, + curveIntersectionThreshold + ); + }; + return shape; + }, + + getminmax: function (curve, d, list) { + if (!list) return { min: 0, max: 0 }; + let min = nMax, + max = nMin, + t, + c; + if (list.indexOf(0) === -1) { + list = [0].concat(list); + } + if (list.indexOf(1) === -1) { + list.push(1); + } + for (let i = 0, len = list.length; i < len; i++) { + t = list[i]; + c = curve.get(t); + if (c[d] < min) { + min = c[d]; + } + if (c[d] > max) { + max = c[d]; + } + } + return { min: min, mid: (min + max) / 2, max: max, size: max - min }; + }, + + align: function (points, line) { + const tx = line.p1.x, + ty = line.p1.y, + a = -atan2(line.p2.y - ty, line.p2.x - tx), + d = function (v) { + return { + x: (v.x - tx) * cos$1(a) - (v.y - ty) * sin$1(a), + y: (v.x - tx) * sin$1(a) + (v.y - ty) * cos$1(a), + }; + }; + return points.map(d); + }, + + roots: function (points, line) { + line = line || { p1: { x: 0, y: 0 }, p2: { x: 1, y: 0 } }; + + const order = points.length - 1; + const aligned = utils.align(points, line); + const reduce = function (t) { + return 0 <= t && t <= 1; + }; + + if (order === 2) { + const a = aligned[0].y, + b = aligned[1].y, + c = aligned[2].y, + d = a - 2 * b + c; + if (d !== 0) { + const m1 = -sqrt$1(b * b - a * c), + m2 = -a + b, + v1 = -(m1 + m2) / d, + v2 = -(-m1 + m2) / d; + return [v1, v2].filter(reduce); + } else if (b !== c && d === 0) { + return [(2 * b - c) / (2 * b - 2 * c)].filter(reduce); + } + return []; + } + + // see http://www.trans4mind.com/personal_development/mathematics/polynomials/cubicAlgebra.htm + const pa = aligned[0].y, + pb = aligned[1].y, + pc = aligned[2].y, + pd = aligned[3].y; + + let d = -pa + 3 * pb - 3 * pc + pd, + a = 3 * pa - 6 * pb + 3 * pc, + b = -3 * pa + 3 * pb, + c = pa; + + if (utils.approximately(d, 0)) { + // this is not a cubic curve. + if (utils.approximately(a, 0)) { + // in fact, this is not a quadratic curve either. + if (utils.approximately(b, 0)) { + // in fact in fact, there are no solutions. + return []; + } + // linear solution: + return [-c / b].filter(reduce); + } + // quadratic solution: + const q = sqrt$1(b * b - 4 * a * c), + a2 = 2 * a; + return [(q - b) / a2, (-b - q) / a2].filter(reduce); + } + + // at this point, we know we need a cubic solution: + + a /= d; + b /= d; + c /= d; + + const p = (3 * b - a * a) / 3, + p3 = p / 3, + q = (2 * a * a * a - 9 * a * b + 27 * c) / 27, + q2 = q / 2, + discriminant = q2 * q2 + p3 * p3 * p3; + + let u1, v1, x1, x2, x3; + if (discriminant < 0) { + const mp3 = -p / 3, + mp33 = mp3 * mp3 * mp3, + r = sqrt$1(mp33), + t = -q / (2 * r), + cosphi = t < -1 ? -1 : t > 1 ? 1 : t, + phi = acos$1(cosphi), + crtr = crt(r), + t1 = 2 * crtr; + x1 = t1 * cos$1(phi / 3) - a / 3; + x2 = t1 * cos$1((phi + tau) / 3) - a / 3; + x3 = t1 * cos$1((phi + 2 * tau) / 3) - a / 3; + return [x1, x2, x3].filter(reduce); + } else if (discriminant === 0) { + u1 = q2 < 0 ? crt(-q2) : -crt(q2); + x1 = 2 * u1 - a / 3; + x2 = -u1 - a / 3; + return [x1, x2].filter(reduce); + } else { + const sd = sqrt$1(discriminant); + u1 = crt(-q2 + sd); + v1 = crt(q2 + sd); + return [u1 - v1 - a / 3].filter(reduce); + } + }, + + droots: function (p) { + // quadratic roots are easy + if (p.length === 3) { + const a = p[0], + b = p[1], + c = p[2], + d = a - 2 * b + c; + if (d !== 0) { + const m1 = -sqrt$1(b * b - a * c), + m2 = -a + b, + v1 = -(m1 + m2) / d, + v2 = -(-m1 + m2) / d; + return [v1, v2]; + } else if (b !== c && d === 0) { + return [(2 * b - c) / (2 * (b - c))]; + } + return []; + } + + // linear roots are even easier + if (p.length === 2) { + const a = p[0], + b = p[1]; + if (a !== b) { + return [a / (a - b)]; + } + return []; + } + + return []; + }, + + curvature: function (t, d1, d2, _3d, kOnly) { + let num, + dnm, + adk, + dk, + k = 0, + r = 0; + + // + // We're using the following formula for curvature: + // + // x'y" - y'x" + // k(t) = ------------------ + // (x'² + y'²)^(3/2) + // + // from https://en.wikipedia.org/wiki/Radius_of_curvature#Definition + // + // With it corresponding 3D counterpart: + // + // sqrt( (y'z" - y"z')² + (z'x" - z"x')² + (x'y" - x"y')²) + // k(t) = ------------------------------------------------------- + // (x'² + y'² + z'²)^(3/2) + // + + const d = utils.compute(t, d1); + const dd = utils.compute(t, d2); + const qdsum = d.x * d.x + d.y * d.y; + + if (_3d) { + num = sqrt$1( + pow(d.y * dd.z - dd.y * d.z, 2) + + pow(d.z * dd.x - dd.z * d.x, 2) + + pow(d.x * dd.y - dd.x * d.y, 2) + ); + dnm = pow(qdsum + d.z * d.z, 3 / 2); + } else { + num = d.x * dd.y - d.y * dd.x; + dnm = pow(qdsum, 3 / 2); + } + + if (num === 0 || dnm === 0) { + return { k: 0, r: 0 }; + } + + k = num / dnm; + r = dnm / num; + + // We're also computing the derivative of kappa, because + // there is value in knowing the rate of change for the + // curvature along the curve. And we're just going to + // ballpark it based on an epsilon. + if (!kOnly) { + // compute k'(t) based on the interval before, and after it, + // to at least try to not introduce forward/backward pass bias. + const pk = utils.curvature(t - 0.001, d1, d2, _3d, true).k; + const nk = utils.curvature(t + 0.001, d1, d2, _3d, true).k; + dk = (nk - k + (k - pk)) / 2; + adk = (abs$1(nk - k) + abs$1(k - pk)) / 2; + } + + return { k: k, r: r, dk: dk, adk: adk }; + }, + + inflections: function (points) { + if (points.length < 4) return []; + + // FIXME: TODO: add in inflection abstraction for quartic+ curves? + + const p = utils.align(points, { p1: points[0], p2: points.slice(-1)[0] }), + a = p[2].x * p[1].y, + b = p[3].x * p[1].y, + c = p[1].x * p[2].y, + d = p[3].x * p[2].y, + v1 = 18 * (-3 * a + 2 * b + 3 * c - d), + v2 = 18 * (3 * a - b - 3 * c), + v3 = 18 * (c - a); + + if (utils.approximately(v1, 0)) { + if (!utils.approximately(v2, 0)) { + let t = -v3 / v2; + if (0 <= t && t <= 1) return [t]; + } + return []; + } + + const d2 = 2 * v1; + + if (utils.approximately(d2, 0)) return []; + + const trm = v2 * v2 - 4 * v1 * v3; + + if (trm < 0) return []; + + const sq = Math.sqrt(trm); + + return [(sq - v2) / d2, -(v2 + sq) / d2].filter(function (r) { + return 0 <= r && r <= 1; + }); + }, + + bboxoverlap: function (b1, b2) { + const dims = ["x", "y"], + len = dims.length; + + for (let i = 0, dim, l, t, d; i < len; i++) { + dim = dims[i]; + l = b1[dim].mid; + t = b2[dim].mid; + d = (b1[dim].size + b2[dim].size) / 2; + if (abs$1(l - t) >= d) return false; + } + return true; + }, + + expandbox: function (bbox, _bbox) { + if (_bbox.x.min < bbox.x.min) { + bbox.x.min = _bbox.x.min; + } + if (_bbox.y.min < bbox.y.min) { + bbox.y.min = _bbox.y.min; + } + if (_bbox.z && _bbox.z.min < bbox.z.min) { + bbox.z.min = _bbox.z.min; + } + if (_bbox.x.max > bbox.x.max) { + bbox.x.max = _bbox.x.max; + } + if (_bbox.y.max > bbox.y.max) { + bbox.y.max = _bbox.y.max; + } + if (_bbox.z && _bbox.z.max > bbox.z.max) { + bbox.z.max = _bbox.z.max; + } + bbox.x.mid = (bbox.x.min + bbox.x.max) / 2; + bbox.y.mid = (bbox.y.min + bbox.y.max) / 2; + if (bbox.z) { + bbox.z.mid = (bbox.z.min + bbox.z.max) / 2; + } + bbox.x.size = bbox.x.max - bbox.x.min; + bbox.y.size = bbox.y.max - bbox.y.min; + if (bbox.z) { + bbox.z.size = bbox.z.max - bbox.z.min; + } + }, + + pairiteration: function (c1, c2, curveIntersectionThreshold) { + const c1b = c1.bbox(), + c2b = c2.bbox(), + r = 100000, + threshold = curveIntersectionThreshold || 0.5; + + if ( + c1b.x.size + c1b.y.size < threshold && + c2b.x.size + c2b.y.size < threshold + ) { + return [ + (((r * (c1._t1 + c1._t2)) / 2) | 0) / r + + "/" + + (((r * (c2._t1 + c2._t2)) / 2) | 0) / r, + ]; + } + + let cc1 = c1.split(0.5), + cc2 = c2.split(0.5), + pairs = [ + { left: cc1.left, right: cc2.left }, + { left: cc1.left, right: cc2.right }, + { left: cc1.right, right: cc2.right }, + { left: cc1.right, right: cc2.left }, + ]; + + pairs = pairs.filter(function (pair) { + return utils.bboxoverlap(pair.left.bbox(), pair.right.bbox()); + }); + + let results = []; + + if (pairs.length === 0) return results; + + pairs.forEach(function (pair) { + results = results.concat( + utils.pairiteration(pair.left, pair.right, threshold) + ); + }); + + results = results.filter(function (v, i) { + return results.indexOf(v) === i; + }); + + return results; + }, + + getccenter: function (p1, p2, p3) { + const dx1 = p2.x - p1.x, + dy1 = p2.y - p1.y, + dx2 = p3.x - p2.x, + dy2 = p3.y - p2.y, + dx1p = dx1 * cos$1(quart) - dy1 * sin$1(quart), + dy1p = dx1 * sin$1(quart) + dy1 * cos$1(quart), + dx2p = dx2 * cos$1(quart) - dy2 * sin$1(quart), + dy2p = dx2 * sin$1(quart) + dy2 * cos$1(quart), + // chord midpoints + mx1 = (p1.x + p2.x) / 2, + my1 = (p1.y + p2.y) / 2, + mx2 = (p2.x + p3.x) / 2, + my2 = (p2.y + p3.y) / 2, + // midpoint offsets + mx1n = mx1 + dx1p, + my1n = my1 + dy1p, + mx2n = mx2 + dx2p, + my2n = my2 + dy2p, + // intersection of these lines: + arc = utils.lli8(mx1, my1, mx1n, my1n, mx2, my2, mx2n, my2n), + r = utils.dist(arc, p1); + + // arc start/end values, over mid point: + let s = atan2(p1.y - arc.y, p1.x - arc.x), + m = atan2(p2.y - arc.y, p2.x - arc.x), + e = atan2(p3.y - arc.y, p3.x - arc.x), + _; + + // determine arc direction (cw/ccw correction) + if (s < e) { + // if s m || m > e) { + s += tau; + } + if (s > e) { + _ = e; + e = s; + s = _; + } + } else { + // if e 4) { + if (arguments.length !== 1) { + throw new Error( + "Only new Bezier(point[]) is accepted for 4th and higher order curves" + ); + } + higher = true; + } + } else { + if (len !== 6 && len !== 8 && len !== 9 && len !== 12) { + if (arguments.length !== 1) { + throw new Error( + "Only new Bezier(point[]) is accepted for 4th and higher order curves" + ); + } + } + } + + const _3d = (this._3d = + (!higher && (len === 9 || len === 12)) || + (coords && coords[0] && typeof coords[0].z !== "undefined")); + + const points = (this.points = []); + for (let idx = 0, step = _3d ? 3 : 2; idx < len; idx += step) { + var point = { + x: args[idx], + y: args[idx + 1], + }; + if (_3d) { + point.z = args[idx + 2]; + } + points.push(point); + } + const order = (this.order = points.length - 1); + + const dims = (this.dims = ["x", "y"]); + if (_3d) dims.push("z"); + this.dimlen = dims.length; + + // is this curve, practically speaking, a straight line? + const aligned = utils.align(points, { p1: points[0], p2: points[order] }); + const baselength = utils.dist(points[0], points[order]); + this._linear = aligned.reduce((t, p) => t + abs(p.y), 0) < baselength / 50; + + this._lut = []; + this._t1 = 0; + this._t2 = 1; + this.update(); + } + + static quadraticFromPoints(p1, p2, p3, t) { + if (typeof t === "undefined") { + t = 0.5; + } + // shortcuts, although they're really dumb + if (t === 0) { + return new Bezier(p2, p2, p3); + } + if (t === 1) { + return new Bezier(p1, p2, p2); + } + // real fitting. + const abc = Bezier.getABC(2, p1, p2, p3, t); + return new Bezier(p1, abc.A, p3); + } + + static cubicFromPoints(S, B, E, t, d1) { + if (typeof t === "undefined") { + t = 0.5; + } + const abc = Bezier.getABC(3, S, B, E, t); + if (typeof d1 === "undefined") { + d1 = utils.dist(B, abc.C); + } + const d2 = (d1 * (1 - t)) / t; + + const selen = utils.dist(S, E), + lx = (E.x - S.x) / selen, + ly = (E.y - S.y) / selen, + bx1 = d1 * lx, + by1 = d1 * ly, + bx2 = d2 * lx, + by2 = d2 * ly; + // derivation of new hull coordinates + const e1 = { x: B.x - bx1, y: B.y - by1 }, + e2 = { x: B.x + bx2, y: B.y + by2 }, + A = abc.A, + v1 = { x: A.x + (e1.x - A.x) / (1 - t), y: A.y + (e1.y - A.y) / (1 - t) }, + v2 = { x: A.x + (e2.x - A.x) / t, y: A.y + (e2.y - A.y) / t }, + nc1 = { x: S.x + (v1.x - S.x) / t, y: S.y + (v1.y - S.y) / t }, + nc2 = { + x: E.x + (v2.x - E.x) / (1 - t), + y: E.y + (v2.y - E.y) / (1 - t), + }; + // ...done + return new Bezier(S, nc1, nc2, E); + } + + static getUtils() { + return utils; + } + + getUtils() { + return Bezier.getUtils(); + } + + static get PolyBezier() { + return PolyBezier; + } + + valueOf() { + return this.toString(); + } + + toString() { + return utils.pointsToString(this.points); + } + + toSVG() { + if (this._3d) return false; + const p = this.points, + x = p[0].x, + y = p[0].y, + s = ["M", x, y, this.order === 2 ? "Q" : "C"]; + for (let i = 1, last = p.length; i < last; i++) { + s.push(p[i].x); + s.push(p[i].y); + } + return s.join(" "); + } + + setRatios(ratios) { + if (ratios.length !== this.points.length) { + throw new Error("incorrect number of ratio values"); + } + this.ratios = ratios; + this._lut = []; // invalidate any precomputed LUT + } + + verify() { + const print = this.coordDigest(); + if (print !== this._print) { + this._print = print; + this.update(); + } + } + + coordDigest() { + return this.points + .map(function (c, pos) { + return "" + pos + c.x + c.y + (c.z ? c.z : 0); + }) + .join(""); + } + + update() { + // invalidate any precomputed LUT + this._lut = []; + this.dpoints = utils.derive(this.points, this._3d); + this.computedirection(); + } + + computedirection() { + const points = this.points; + const angle = utils.angle(points[0], points[this.order], points[1]); + this.clockwise = angle > 0; + } + + length() { + return utils.length(this.derivative.bind(this)); + } + + static getABC(order = 2, S, B, E, t = 0.5) { + const u = utils.projectionratio(t, order), + um = 1 - u, + C = { + x: u * S.x + um * E.x, + y: u * S.y + um * E.y, + }, + s = utils.abcratio(t, order), + A = { + x: B.x + (B.x - C.x) / s, + y: B.y + (B.y - C.y) / s, + }; + return { A, B, C, S, E }; + } + + getABC(t, B) { + B = B || this.get(t); + let S = this.points[0]; + let E = this.points[this.order]; + return Bezier.getABC(this.order, S, B, E, t); + } + + getLUT(steps) { + this.verify(); + steps = steps || 100; + if (this._lut.length === steps + 1) { + return this._lut; + } + this._lut = []; + // n steps means n+1 points + steps++; + this._lut = []; + for (let i = 0, p, t; i < steps; i++) { + t = i / (steps - 1); + p = this.compute(t); + p.t = t; + this._lut.push(p); + } + return this._lut; + } + + on(point, error) { + error = error || 5; + const lut = this.getLUT(), + hits = []; + for (let i = 0, c, t = 0; i < lut.length; i++) { + c = lut[i]; + if (utils.dist(c, point) < error) { + hits.push(c); + t += i / lut.length; + } + } + if (!hits.length) return false; + return (t /= hits.length); + } + + project(point) { + // step 1: coarse check + const LUT = this.getLUT(), + l = LUT.length - 1, + closest = utils.closest(LUT, point), + mpos = closest.mpos, + t1 = (mpos - 1) / l, + t2 = (mpos + 1) / l, + step = 0.1 / l; + + // step 2: fine check + let mdist = closest.mdist, + t = t1, + ft = t, + p; + mdist += 1; + for (let d; t < t2 + step; t += step) { + p = this.compute(t); + d = utils.dist(point, p); + if (d < mdist) { + mdist = d; + ft = t; + } + } + ft = ft < 0 ? 0 : ft > 1 ? 1 : ft; + p = this.compute(ft); + p.t = ft; + p.d = mdist; + return p; + } + + get(t) { + return this.compute(t); + } + + point(idx) { + return this.points[idx]; + } + + compute(t) { + if (this.ratios) { + return utils.computeWithRatios(t, this.points, this.ratios, this._3d); + } + return utils.compute(t, this.points, this._3d, this.ratios); + } + + raise() { + const p = this.points, + np = [p[0]], + k = p.length; + for (let i = 1, pi, pim; i < k; i++) { + pi = p[i]; + pim = p[i - 1]; + np[i] = { + x: ((k - i) / k) * pi.x + (i / k) * pim.x, + y: ((k - i) / k) * pi.y + (i / k) * pim.y, + }; + } + np[k] = p[k - 1]; + return new Bezier(np); + } + + derivative(t) { + return utils.compute(t, this.dpoints[0], this._3d); + } + + dderivative(t) { + return utils.compute(t, this.dpoints[1], this._3d); + } + + align() { + let p = this.points; + return new Bezier(utils.align(p, { p1: p[0], p2: p[p.length - 1] })); + } + + curvature(t) { + return utils.curvature(t, this.dpoints[0], this.dpoints[1], this._3d); + } + + inflections() { + return utils.inflections(this.points); + } + + normal(t) { + return this._3d ? this.__normal3(t) : this.__normal2(t); + } + + __normal2(t) { + const d = this.derivative(t); + const q = sqrt(d.x * d.x + d.y * d.y); + return { t, x: -d.y / q, y: d.x / q }; + } + + __normal3(t) { + // see http://stackoverflow.com/questions/25453159 + const r1 = this.derivative(t), + r2 = this.derivative(t + 0.01), + q1 = sqrt(r1.x * r1.x + r1.y * r1.y + r1.z * r1.z), + q2 = sqrt(r2.x * r2.x + r2.y * r2.y + r2.z * r2.z); + r1.x /= q1; + r1.y /= q1; + r1.z /= q1; + r2.x /= q2; + r2.y /= q2; + r2.z /= q2; + // cross product + const c = { + x: r2.y * r1.z - r2.z * r1.y, + y: r2.z * r1.x - r2.x * r1.z, + z: r2.x * r1.y - r2.y * r1.x, + }; + const m = sqrt(c.x * c.x + c.y * c.y + c.z * c.z); + c.x /= m; + c.y /= m; + c.z /= m; + // rotation matrix + const R = [ + c.x * c.x, + c.x * c.y - c.z, + c.x * c.z + c.y, + c.x * c.y + c.z, + c.y * c.y, + c.y * c.z - c.x, + c.x * c.z - c.y, + c.y * c.z + c.x, + c.z * c.z, + ]; + // normal vector: + const n = { + t, + x: R[0] * r1.x + R[1] * r1.y + R[2] * r1.z, + y: R[3] * r1.x + R[4] * r1.y + R[5] * r1.z, + z: R[6] * r1.x + R[7] * r1.y + R[8] * r1.z, + }; + return n; + } + + hull(t) { + let p = this.points, + _p = [], + q = [], + idx = 0; + q[idx++] = p[0]; + q[idx++] = p[1]; + q[idx++] = p[2]; + if (this.order === 3) { + q[idx++] = p[3]; + } + // we lerp between all points at each iteration, until we have 1 point left. + while (p.length > 1) { + _p = []; + for (let i = 0, pt, l = p.length - 1; i < l; i++) { + pt = utils.lerp(t, p[i], p[i + 1]); + q[idx++] = pt; + _p.push(pt); + } + p = _p; + } + return q; + } + + split(t1, t2) { + // shortcuts + if (t1 === 0 && !!t2) { + return this.split(t2).left; + } + if (t2 === 1) { + return this.split(t1).right; + } + + // no shortcut: use "de Casteljau" iteration. + const q = this.hull(t1); + const result = { + left: + this.order === 2 + ? new Bezier([q[0], q[3], q[5]]) + : new Bezier([q[0], q[4], q[7], q[9]]), + right: + this.order === 2 + ? new Bezier([q[5], q[4], q[2]]) + : new Bezier([q[9], q[8], q[6], q[3]]), + span: q, + }; + + // make sure we bind _t1/_t2 information! + result.left._t1 = utils.map(0, 0, 1, this._t1, this._t2); + result.left._t2 = utils.map(t1, 0, 1, this._t1, this._t2); + result.right._t1 = utils.map(t1, 0, 1, this._t1, this._t2); + result.right._t2 = utils.map(1, 0, 1, this._t1, this._t2); + + // if we have no t2, we're done + if (!t2) { + return result; + } + + // if we have a t2, split again: + t2 = utils.map(t2, t1, 1, 0, 1); + return result.right.split(t2).left; + } + + extrema() { + const result = {}; + let roots = []; + + this.dims.forEach( + function (dim) { + let mfn = function (v) { + return v[dim]; + }; + let p = this.dpoints[0].map(mfn); + result[dim] = utils.droots(p); + if (this.order === 3) { + p = this.dpoints[1].map(mfn); + result[dim] = result[dim].concat(utils.droots(p)); + } + result[dim] = result[dim].filter(function (t) { + return t >= 0 && t <= 1; + }); + roots = roots.concat(result[dim].sort(utils.numberSort)); + }.bind(this) + ); + + result.values = roots.sort(utils.numberSort).filter(function (v, idx) { + return roots.indexOf(v) === idx; + }); + + return result; + } + + bbox() { + const extrema = this.extrema(), + result = {}; + this.dims.forEach( + function (d) { + result[d] = utils.getminmax(this, d, extrema[d]); + }.bind(this) + ); + return result; + } + + overlaps(curve) { + const lbbox = this.bbox(), + tbbox = curve.bbox(); + return utils.bboxoverlap(lbbox, tbbox); + } + + offset(t, d) { + if (typeof d !== "undefined") { + const c = this.get(t), + n = this.normal(t); + const ret = { + c: c, + n: n, + x: c.x + n.x * d, + y: c.y + n.y * d, + }; + if (this._3d) { + ret.z = c.z + n.z * d; + } + return ret; + } + if (this._linear) { + const nv = this.normal(0), + coords = this.points.map(function (p) { + const ret = { + x: p.x + t * nv.x, + y: p.y + t * nv.y, + }; + if (p.z && nv.z) { + ret.z = p.z + t * nv.z; + } + return ret; + }); + return [new Bezier(coords)]; + } + return this.reduce().map(function (s) { + if (s._linear) { + return s.offset(t)[0]; + } + return s.scale(t); + }); + } + + simple() { + if (this.order === 3) { + const a1 = utils.angle(this.points[0], this.points[3], this.points[1]); + const a2 = utils.angle(this.points[0], this.points[3], this.points[2]); + if ((a1 > 0 && a2 < 0) || (a1 < 0 && a2 > 0)) return false; + } + const n1 = this.normal(0); + const n2 = this.normal(1); + let s = n1.x * n2.x + n1.y * n2.y; + if (this._3d) { + s += n1.z * n2.z; + } + return abs(acos(s)) < pi / 3; + } + + reduce() { + // TODO: examine these var types in more detail... + let i, + t1 = 0, + t2 = 0, + step = 0.01, + segment, + pass1 = [], + pass2 = []; + // first pass: split on extrema + let extrema = this.extrema().values; + if (extrema.indexOf(0) === -1) { + extrema = [0].concat(extrema); + } + if (extrema.indexOf(1) === -1) { + extrema.push(1); + } + + for (t1 = extrema[0], i = 1; i < extrema.length; i++) { + t2 = extrema[i]; + segment = this.split(t1, t2); + segment._t1 = t1; + segment._t2 = t2; + pass1.push(segment); + t1 = t2; + } + + // second pass: further reduce these segments to simple segments + pass1.forEach(function (p1) { + t1 = 0; + t2 = 0; + while (t2 <= 1) { + for (t2 = t1 + step; t2 <= 1 + step; t2 += step) { + segment = p1.split(t1, t2); + if (!segment.simple()) { + t2 -= step; + if (abs(t1 - t2) < step) { + // we can never form a reduction + return []; + } + segment = p1.split(t1, t2); + segment._t1 = utils.map(t1, 0, 1, p1._t1, p1._t2); + segment._t2 = utils.map(t2, 0, 1, p1._t1, p1._t2); + pass2.push(segment); + t1 = t2; + break; + } + } + } + if (t1 < 1) { + segment = p1.split(t1, 1); + segment._t1 = utils.map(t1, 0, 1, p1._t1, p1._t2); + segment._t2 = p1._t2; + pass2.push(segment); + } + }); + return pass2; + } + + translate(v, d1, d2) { + d2 = typeof d2 === "number" ? d2 : d1; + + // TODO: make this take curves with control points outside + // of the start-end interval into account + + const o = this.order; + let d = this.points.map((_, i) => (1 - i / o) * d1 + (i / o) * d2); + return new Bezier( + this.points.map((p, i) => ({ + x: p.x + v.x * d[i], + y: p.y + v.y * d[i], + })) + ); + } + + scale(d) { + const order = this.order; + let distanceFn = false; + if (typeof d === "function") { + distanceFn = d; + } + if (distanceFn && order === 2) { + return this.raise().scale(distanceFn); + } + + // TODO: add special handling for non-linear degenerate curves. + + const clockwise = this.clockwise; + const points = this.points; + + if (this._linear) { + return this.translate( + this.normal(0), + distanceFn ? distanceFn(0) : d, + distanceFn ? distanceFn(1) : d + ); + } + + const r1 = distanceFn ? distanceFn(0) : d; + const r2 = distanceFn ? distanceFn(1) : d; + const v = [this.offset(0, 10), this.offset(1, 10)]; + const np = []; + const o = utils.lli4(v[0], v[0].c, v[1], v[1].c); + + if (!o) { + throw new Error("cannot scale this curve. Try reducing it first."); + } + + // move all points by distance 'd' wrt the origin 'o', + // and move end points by fixed distance along normal. + [0, 1].forEach(function (t) { + const p = (np[t * order] = utils.copy(points[t * order])); + p.x += (t ? r2 : r1) * v[t].n.x; + p.y += (t ? r2 : r1) * v[t].n.y; + }); + + if (!distanceFn) { + // move control points to lie on the intersection of the offset + // derivative vector, and the origin-through-control vector + [0, 1].forEach((t) => { + if (order === 2 && !!t) return; + const p = np[t * order]; + const d = this.derivative(t); + const p2 = { x: p.x + d.x, y: p.y + d.y }; + np[t + 1] = utils.lli4(p, p2, o, points[t + 1]); + }); + return new Bezier(np); + } + + // move control points by "however much necessary to + // ensure the correct tangent to endpoint". + [0, 1].forEach(function (t) { + if (order === 2 && !!t) return; + var p = points[t + 1]; + var ov = { + x: p.x - o.x, + y: p.y - o.y, + }; + var rc = distanceFn ? distanceFn((t + 1) / order) : d; + if (distanceFn && !clockwise) rc = -rc; + var m = sqrt(ov.x * ov.x + ov.y * ov.y); + ov.x /= m; + ov.y /= m; + np[t + 1] = { + x: p.x + rc * ov.x, + y: p.y + rc * ov.y, + }; + }); + return new Bezier(np); + } + + outline(d1, d2, d3, d4) { + d2 = d2 === undefined ? d1 : d2; + + if (this._linear) { + // TODO: find the actual extrema, because they might + // be before the start, or past the end. + + const n = this.normal(0); + const start = this.points[0]; + const end = this.points[this.points.length - 1]; + let s, mid, e; + + if (d3 === undefined) { + d3 = d1; + d4 = d2; + } + + s = { x: start.x + n.x * d1, y: start.y + n.y * d1 }; + e = { x: end.x + n.x * d3, y: end.y + n.y * d3 }; + mid = { x: (s.x + e.x) / 2, y: (s.y + e.y) / 2 }; + const fline = [s, mid, e]; + + s = { x: start.x - n.x * d2, y: start.y - n.y * d2 }; + e = { x: end.x - n.x * d4, y: end.y - n.y * d4 }; + mid = { x: (s.x + e.x) / 2, y: (s.y + e.y) / 2 }; + const bline = [e, mid, s]; + + const ls = utils.makeline(bline[2], fline[0]); + const le = utils.makeline(fline[2], bline[0]); + const segments = [ls, new Bezier(fline), le, new Bezier(bline)]; + return new PolyBezier(segments); + } + + const reduced = this.reduce(), + len = reduced.length, + fcurves = []; + + let bcurves = [], + p, + alen = 0, + tlen = this.length(); + + const graduated = typeof d3 !== "undefined" && typeof d4 !== "undefined"; + + function linearDistanceFunction(s, e, tlen, alen, slen) { + return function (v) { + const f1 = alen / tlen, + f2 = (alen + slen) / tlen, + d = e - s; + return utils.map(v, 0, 1, s + f1 * d, s + f2 * d); + }; + } + + // form curve oulines + reduced.forEach(function (segment) { + const slen = segment.length(); + if (graduated) { + fcurves.push( + segment.scale(linearDistanceFunction(d1, d3, tlen, alen, slen)) + ); + bcurves.push( + segment.scale(linearDistanceFunction(-d2, -d4, tlen, alen, slen)) + ); + } else { + fcurves.push(segment.scale(d1)); + bcurves.push(segment.scale(-d2)); + } + alen += slen; + }); + + // reverse the "return" outline + bcurves = bcurves + .map(function (s) { + p = s.points; + if (p[3]) { + s.points = [p[3], p[2], p[1], p[0]]; + } else { + s.points = [p[2], p[1], p[0]]; + } + return s; + }) + .reverse(); + + // form the endcaps as lines + const fs = fcurves[0].points[0], + fe = fcurves[len - 1].points[fcurves[len - 1].points.length - 1], + bs = bcurves[len - 1].points[bcurves[len - 1].points.length - 1], + be = bcurves[0].points[0], + ls = utils.makeline(bs, fs), + le = utils.makeline(fe, be), + segments = [ls].concat(fcurves).concat([le]).concat(bcurves); + + return new PolyBezier(segments); + } + + outlineshapes(d1, d2, curveIntersectionThreshold) { + d2 = d2 || d1; + const outline = this.outline(d1, d2).curves; + const shapes = []; + for (let i = 1, len = outline.length; i < len / 2; i++) { + const shape = utils.makeshape( + outline[i], + outline[len - i], + curveIntersectionThreshold + ); + shape.startcap.virtual = i > 1; + shape.endcap.virtual = i < len / 2 - 1; + shapes.push(shape); + } + return shapes; + } + + intersects(curve, curveIntersectionThreshold) { + if (!curve) return this.selfintersects(curveIntersectionThreshold); + if (curve.p1 && curve.p2) { + return this.lineIntersects(curve); + } + if (curve instanceof Bezier) { + curve = curve.reduce(); + } + return this.curveintersects( + this.reduce(), + curve, + curveIntersectionThreshold + ); + } + + lineIntersects(line) { + const mx = min(line.p1.x, line.p2.x), + my = min(line.p1.y, line.p2.y), + MX = max(line.p1.x, line.p2.x), + MY = max(line.p1.y, line.p2.y); + return utils.roots(this.points, line).filter((t) => { + var p = this.get(t); + return utils.between(p.x, mx, MX) && utils.between(p.y, my, MY); + }); + } + + selfintersects(curveIntersectionThreshold) { + // "simple" curves cannot intersect with their direct + // neighbour, so for each segment X we check whether + // it intersects [0:x-2][x+2:last]. + + const reduced = this.reduce(), + len = reduced.length - 2, + results = []; + + for (let i = 0, result, left, right; i < len; i++) { + left = reduced.slice(i, i + 1); + right = reduced.slice(i + 2); + result = this.curveintersects(left, right, curveIntersectionThreshold); + results.push(...result); + } + return results; + } + + curveintersects(c1, c2, curveIntersectionThreshold) { + const pairs = []; + // step 1: pair off any overlapping segments + c1.forEach(function (l) { + c2.forEach(function (r) { + if (l.overlaps(r)) { + pairs.push({ left: l, right: r }); + } + }); + }); + // step 2: for each pairing, run through the convergence algorithm. + let intersections = []; + pairs.forEach(function (pair) { + const result = utils.pairiteration( + pair.left, + pair.right, + curveIntersectionThreshold + ); + if (result.length > 0) { + intersections = intersections.concat(result); + } + }); + return intersections; + } + + arcs(errorThreshold) { + errorThreshold = errorThreshold || 0.5; + return this._iterate(errorThreshold, []); + } + + _error(pc, np1, s, e) { + const q = (e - s) / 4, + c1 = this.get(s + q), + c2 = this.get(e - q), + ref = utils.dist(pc, np1), + d1 = utils.dist(pc, c1), + d2 = utils.dist(pc, c2); + return abs(d1 - ref) + abs(d2 - ref); + } + + _iterate(errorThreshold, circles) { + let t_s = 0, + t_e = 1, + safety; + // we do a binary search to find the "good `t` closest to no-longer-good" + do { + safety = 0; + + // step 1: start with the maximum possible arc + t_e = 1; + + // points: + let np1 = this.get(t_s), + np2, + np3, + arc, + prev_arc; + + // booleans: + let curr_good = false, + prev_good = false, + done; + + // numbers: + let t_m = t_e, + prev_e = 1; + + // step 2: find the best possible arc + do { + prev_good = curr_good; + prev_arc = arc; + t_m = (t_s + t_e) / 2; + + np2 = this.get(t_m); + np3 = this.get(t_e); + + arc = utils.getccenter(np1, np2, np3); + + //also save the t values + arc.interval = { + start: t_s, + end: t_e, + }; + + let error = this._error(arc, np1, t_s, t_e); + curr_good = error <= errorThreshold; + + done = prev_good && !curr_good; + if (!done) prev_e = t_e; + + // this arc is fine: we can move 'e' up to see if we can find a wider arc + if (curr_good) { + // if e is already at max, then we're done for this arc. + if (t_e >= 1) { + // make sure we cap at t=1 + arc.interval.end = prev_e = 1; + prev_arc = arc; + // if we capped the arc segment to t=1 we also need to make sure that + // the arc's end angle is correct with respect to the bezier end point. + if (t_e > 1) { + let d = { + x: arc.x + arc.r * cos(arc.e), + y: arc.y + arc.r * sin(arc.e), + }; + arc.e += utils.angle({ x: arc.x, y: arc.y }, d, this.get(1)); + } + break; + } + // if not, move it up by half the iteration distance + t_e = t_e + (t_e - t_s) / 2; + } else { + // this is a bad arc: we need to move 'e' down to find a good arc + t_e = t_m; + } + } while (!done && safety++ < 100); + + if (safety >= 100) { + break; + } + + // console.log("L835: [F] arc found", t_s, prev_e, prev_arc.x, prev_arc.y, prev_arc.s, prev_arc.e); + + prev_arc = prev_arc ? prev_arc : arc; + circles.push(prev_arc); + t_s = prev_e; + } while (t_e < 1); + return circles; + } + } + + function _iterableToArrayLimit(arr, i) { + var _i = null == arr ? null : "undefined" != typeof Symbol && arr[Symbol.iterator] || arr["@@iterator"]; + if (null != _i) { + var _s, + _e, + _x, + _r, + _arr = [], + _n = !0, + _d = !1; + try { + if (_x = (_i = _i.call(arr)).next, 0 === i) { + if (Object(_i) !== _i) return; + _n = !1; + } else for (; !(_n = (_s = _x.call(_i)).done) && (_arr.push(_s.value), _arr.length !== i); _n = !0); + } catch (err) { + _d = !0, _e = err; + } finally { + try { + if (!_n && null != _i.return && (_r = _i.return(), Object(_r) !== _r)) return; + } finally { + if (_d) throw _e; + } + } + return _arr; + } + } + 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; + } + 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 _slicedToArray(arr, i) { + return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _unsupportedIterableToArray(arr, i) || _nonIterableRest(); + } + function _toConsumableArray(arr) { + return _arrayWithoutHoles(arr) || _iterableToArray(arr) || _unsupportedIterableToArray(arr) || _nonIterableSpread(); + } + function _arrayWithoutHoles(arr) { + if (Array.isArray(arr)) return _arrayLikeToArray(arr); + } + function _arrayWithHoles(arr) { + if (Array.isArray(arr)) return arr; + } + function _iterableToArray(iter) { + if (typeof Symbol !== "undefined" && iter[Symbol.iterator] != null || iter["@@iterator"] != null) return Array.from(iter); + } + function _unsupportedIterableToArray(o, minLen) { + if (!o) return; + if (typeof o === "string") return _arrayLikeToArray(o, minLen); + var n = Object.prototype.toString.call(o).slice(8, -1); + if (n === "Object" && o.constructor) n = o.constructor.name; + if (n === "Map" || n === "Set") return Array.from(o); + if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); + } + function _arrayLikeToArray(arr, len) { + if (len == null || len > arr.length) len = arr.length; + for (var i = 0, arr2 = new Array(len); i < len; i++) arr2[i] = arr[i]; + return arr2; + } + function _nonIterableSpread() { + throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); + } + function _nonIterableRest() { + throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); + } + function _toPrimitive(input, hint) { + if (typeof input !== "object" || input === null) return input; + var prim = input[Symbol.toPrimitive]; + if (prim !== undefined) { + var res = prim.call(input, hint || "default"); + if (typeof res !== "object") return res; + throw new TypeError("@@toPrimitive must return a primitive value."); + } + return (hint === "string" ? String : Number)(input); + } + function _toPropertyKey(arg) { + var key = _toPrimitive(arg, "string"); + return typeof key === "symbol" ? key : String(key); + } + + var index = (function () { + var list = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : []; + var keyAccessors = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : []; + var multiItem = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : true; + var flattenKeys = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : false; + var keys = (keyAccessors instanceof Array ? keyAccessors.length ? keyAccessors : [undefined] : [keyAccessors]).map(function (key) { + return { + keyAccessor: key, + isProp: !(key instanceof Function) + }; + }); + var indexedResult = list.reduce(function (res, item) { + var iterObj = res; + var itemVal = item; + keys.forEach(function (_ref, idx) { + var keyAccessor = _ref.keyAccessor, + isProp = _ref.isProp; + var key; + if (isProp) { + var _itemVal = itemVal, + propVal = _itemVal[keyAccessor], + rest = _objectWithoutProperties(_itemVal, [keyAccessor].map(_toPropertyKey)); + key = propVal; + itemVal = rest; + } else { + key = keyAccessor(itemVal, idx); + } + if (idx + 1 < keys.length) { + if (!iterObj.hasOwnProperty(key)) { + iterObj[key] = {}; + } + iterObj = iterObj[key]; + } else { + // Leaf key + if (multiItem) { + if (!iterObj.hasOwnProperty(key)) { + iterObj[key] = []; + } + iterObj[key].push(itemVal); + } else { + iterObj[key] = itemVal; + } + } + }); + return res; + }, {}); + if (multiItem instanceof Function) { + // Reduce leaf multiple values + (function reduce(node) { + var level = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 1; + if (level === keys.length) { + Object.keys(node).forEach(function (k) { + return node[k] = multiItem(node[k]); + }); + } else { + Object.values(node).forEach(function (child) { + return reduce(child, level + 1); + }); + } + })(indexedResult); // IIFE + } + + var result = indexedResult; + if (flattenKeys) { + // flatten into array + result = []; + (function flatten(node) { + var accKeys = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : []; + if (accKeys.length === keys.length) { + result.push({ + keys: accKeys, + vals: node + }); + } else { + Object.entries(node).forEach(function (_ref2) { + var _ref3 = _slicedToArray(_ref2, 2), + key = _ref3[0], + val = _ref3[1]; + return flatten(val, [].concat(_toConsumableArray(accKeys), [key])); + }); + } + })(indexedResult); //IIFE + + if (keyAccessors instanceof Array && keyAccessors.length === 0 && result.length === 1) { + // clear keys if there's no key accessors (single result) + result[0].keys = []; + } + } + return result; + }); + + function initRange(domain, range) { + switch (arguments.length) { + case 0: break; + case 1: this.range(domain); break; + default: this.range(range).domain(domain); break; + } + return this; + } + + const implicit = Symbol("implicit"); + + function ordinal() { + var index = new InternMap(), + domain = [], + range = [], + unknown = implicit; + + function scale(d) { + let i = index.get(d); + if (i === undefined) { + if (unknown !== implicit) return unknown; + index.set(d, i = domain.push(d) - 1); + } + return range[i % range.length]; + } + + scale.domain = function(_) { + if (!arguments.length) return domain.slice(); + domain = [], index = new InternMap(); + for (const value of _) { + if (index.has(value)) continue; + index.set(value, domain.push(value) - 1); + } + return scale; + }; + + scale.range = function(_) { + return arguments.length ? (range = Array.from(_), scale) : range.slice(); + }; + + scale.unknown = function(_) { + return arguments.length ? (unknown = _, scale) : unknown; + }; + + scale.copy = function() { + return ordinal(domain, range).unknown(unknown); + }; + + initRange.apply(scale, arguments); + + return scale; + } + + function colors(specifier) { + var n = specifier.length / 6 | 0, colors = new Array(n), i = 0; + while (i < n) colors[i] = "#" + specifier.slice(i * 6, ++i * 6); + return colors; + } + + var schemePaired = colors("a6cee31f78b4b2df8a33a02cfb9a99e31a1cfdbf6fff7f00cab2d66a3d9affff99b15928"); + + var autoColorScale = ordinal(schemePaired); + + // Autoset attribute colorField by colorByAccessor property + // If an object has already a color, don't set it + // Objects can be nodes or links + function autoColorObjects(objects, colorByAccessor, colorField) { + if (!colorByAccessor || typeof colorField !== 'string') return; + objects.filter(function (obj) { + return !obj[colorField]; + }).forEach(function (obj) { + obj[colorField] = autoColorScale(colorByAccessor(obj)); + }); + } + + function getDagDepths (_ref, idAccessor) { + var nodes = _ref.nodes, + links = _ref.links; + var _ref2 = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {}, + _ref2$nodeFilter = _ref2.nodeFilter, + nodeFilter = _ref2$nodeFilter === void 0 ? function () { + return true; + } : _ref2$nodeFilter, + _ref2$onLoopError = _ref2.onLoopError, + onLoopError = _ref2$onLoopError === void 0 ? function (loopIds) { + throw "Invalid DAG structure! Found cycle in node path: ".concat(loopIds.join(' -> '), "."); + } : _ref2$onLoopError; + // linked graph + var graph = {}; + nodes.forEach(function (node) { + return graph[idAccessor(node)] = { + data: node, + out: [], + depth: -1, + skip: !nodeFilter(node) + }; + }); + links.forEach(function (_ref3) { + var source = _ref3.source, + target = _ref3.target; + var sourceId = getNodeId(source); + var targetId = getNodeId(target); + if (!graph.hasOwnProperty(sourceId)) throw "Missing source node with id: ".concat(sourceId); + if (!graph.hasOwnProperty(targetId)) throw "Missing target node with id: ".concat(targetId); + var sourceNode = graph[sourceId]; + var targetNode = graph[targetId]; + sourceNode.out.push(targetNode); + function getNodeId(node) { + return _typeof$1(node) === 'object' ? idAccessor(node) : node; + } + }); + var foundLoops = []; + traverse(Object.values(graph)); + var nodeDepths = Object.assign.apply(Object, [{}].concat(_toConsumableArray$2(Object.entries(graph).filter(function (_ref4) { + var _ref5 = _slicedToArray$2(_ref4, 2), + node = _ref5[1]; + return !node.skip; + }).map(function (_ref6) { + var _ref7 = _slicedToArray$2(_ref6, 2), + id = _ref7[0], + node = _ref7[1]; + return _defineProperty({}, id, node.depth); + })))); + return nodeDepths; + function traverse(nodes) { + var nodeStack = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : []; + var currentDepth = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 0; + var _loop = function _loop() { + var node = nodes[i]; + if (nodeStack.indexOf(node) !== -1) { + var loop = [].concat(_toConsumableArray$2(nodeStack.slice(nodeStack.indexOf(node))), [node]).map(function (d) { + return idAccessor(d.data); + }); + if (!foundLoops.some(function (foundLoop) { + return foundLoop.length === loop.length && foundLoop.every(function (id, idx) { + return id === loop[idx]; + }); + })) { + foundLoops.push(loop); + onLoopError(loop); + } + return 1; // continue + } + if (currentDepth > node.depth) { + // Don't unnecessarily revisit chunks of the graph + node.depth = currentDepth; + traverse(node.out, [].concat(_toConsumableArray$2(nodeStack), [node]), currentDepth + (node.skip ? 0 : 1)); + } + }; + for (var i = 0, l = nodes.length; i < l; i++) { + if (_loop()) continue; + } + } + } + + // + + var DAG_LEVEL_NODE_RATIO = 2; + + // whenever styling props are changed that require a canvas redraw + var notifyRedraw = function notifyRedraw(_, state) { + return state.onNeedsRedraw && state.onNeedsRedraw(); + }; + var updDataPhotons = function updDataPhotons(_, state) { + if (!state.isShadow) { + // Add photon particles + var linkParticlesAccessor = index$2(state.linkDirectionalParticles); + state.graphData.links.forEach(function (link) { + var numPhotons = Math.round(Math.abs(linkParticlesAccessor(link))); + if (numPhotons) { + link.__photons = _toConsumableArray$2(Array(numPhotons)).map(function () { + return {}; + }); + } else { + delete link.__photons; + } + }); + } + }; + var CanvasForceGraph = index$3({ + props: { + graphData: { + "default": { + nodes: [], + links: [] + }, + onChange: function onChange(_, state) { + state.engineRunning = false; // Pause simulation + updDataPhotons(_, state); + } + }, + dagMode: { + onChange: function onChange(dagMode, state) { + // td, bu, lr, rl, radialin, radialout + !dagMode && (state.graphData.nodes || []).forEach(function (n) { + return n.fx = n.fy = undefined; + }); // unfix nodes when disabling dag mode + } + }, + + dagLevelDistance: {}, + dagNodeFilter: { + "default": function _default(node) { + return true; + } + }, + onDagError: { + triggerUpdate: false + }, + nodeRelSize: { + "default": 4, + triggerUpdate: false, + onChange: notifyRedraw + }, + // area per val unit + nodeId: { + "default": 'id' + }, + nodeVal: { + "default": 'val', + triggerUpdate: false, + onChange: notifyRedraw + }, + nodeColor: { + "default": 'color', + triggerUpdate: false, + onChange: notifyRedraw + }, + nodeAutoColorBy: {}, + nodeCanvasObject: { + triggerUpdate: false, + onChange: notifyRedraw + }, + nodeCanvasObjectMode: { + "default": function _default() { + return 'replace'; + }, + triggerUpdate: false, + onChange: notifyRedraw + }, + nodeVisibility: { + "default": true, + triggerUpdate: false, + onChange: notifyRedraw + }, + linkSource: { + "default": 'source' + }, + linkTarget: { + "default": 'target' + }, + linkVisibility: { + "default": true, + triggerUpdate: false, + onChange: notifyRedraw + }, + linkColor: { + "default": 'color', + triggerUpdate: false, + onChange: notifyRedraw + }, + linkAutoColorBy: {}, + linkLineDash: { + triggerUpdate: false, + onChange: notifyRedraw + }, + linkWidth: { + "default": 1, + triggerUpdate: false, + onChange: notifyRedraw + }, + linkCurvature: { + "default": 0, + triggerUpdate: false, + onChange: notifyRedraw + }, + linkCanvasObject: { + triggerUpdate: false, + onChange: notifyRedraw + }, + linkCanvasObjectMode: { + "default": function _default() { + return 'replace'; + }, + triggerUpdate: false, + onChange: notifyRedraw + }, + linkDirectionalArrowLength: { + "default": 0, + triggerUpdate: false, + onChange: notifyRedraw + }, + linkDirectionalArrowColor: { + triggerUpdate: false, + onChange: notifyRedraw + }, + linkDirectionalArrowRelPos: { + "default": 0.5, + triggerUpdate: false, + onChange: notifyRedraw + }, + // value between 0<>1 indicating the relative pos along the (exposed) line + linkDirectionalParticles: { + "default": 0, + triggerUpdate: false, + onChange: updDataPhotons + }, + // animate photons travelling in the link direction + linkDirectionalParticleSpeed: { + "default": 0.01, + triggerUpdate: false + }, + // in link length ratio per frame + linkDirectionalParticleWidth: { + "default": 4, + triggerUpdate: false + }, + linkDirectionalParticleColor: { + triggerUpdate: false + }, + globalScale: { + "default": 1, + triggerUpdate: false + }, + d3AlphaMin: { + "default": 0, + triggerUpdate: false + }, + d3AlphaDecay: { + "default": 0.0228, + triggerUpdate: false, + onChange: function onChange(alphaDecay, state) { + state.forceLayout.alphaDecay(alphaDecay); + } + }, + d3AlphaTarget: { + "default": 0, + triggerUpdate: false, + onChange: function onChange(alphaTarget, state) { + state.forceLayout.alphaTarget(alphaTarget); + } + }, + d3VelocityDecay: { + "default": 0.4, + triggerUpdate: false, + onChange: function onChange(velocityDecay, state) { + state.forceLayout.velocityDecay(velocityDecay); + } + }, + warmupTicks: { + "default": 0, + triggerUpdate: false + }, + // how many times to tick the force engine at init before starting to render + cooldownTicks: { + "default": Infinity, + triggerUpdate: false + }, + cooldownTime: { + "default": 15000, + triggerUpdate: false + }, + // ms + onUpdate: { + "default": function _default() {}, + triggerUpdate: false + }, + onFinishUpdate: { + "default": function _default() {}, + triggerUpdate: false + }, + onEngineTick: { + "default": function _default() {}, + triggerUpdate: false + }, + onEngineStop: { + "default": function _default() {}, + triggerUpdate: false + }, + onNeedsRedraw: { + triggerUpdate: false + }, + isShadow: { + "default": false, + triggerUpdate: false + } + }, + methods: { + // Expose d3 forces for external manipulation + d3Force: function d3Force(state, forceName, forceFn) { + if (forceFn === undefined) { + return state.forceLayout.force(forceName); // Force getter + } + + state.forceLayout.force(forceName, forceFn); // Force setter + return this; + }, + d3ReheatSimulation: function d3ReheatSimulation(state) { + state.forceLayout.alpha(1); + this.resetCountdown(); + return this; + }, + // reset cooldown state + resetCountdown: function resetCountdown(state) { + state.cntTicks = 0; + state.startTickTime = new Date(); + state.engineRunning = true; + return this; + }, + isEngineRunning: function isEngineRunning(state) { + return !!state.engineRunning; + }, + tickFrame: function tickFrame(state) { + !state.isShadow && layoutTick(); + paintLinks(); + !state.isShadow && paintArrows(); + !state.isShadow && paintPhotons(); + paintNodes(); + return this; + + // + + function layoutTick() { + if (state.engineRunning) { + if (++state.cntTicks > state.cooldownTicks || new Date() - state.startTickTime > state.cooldownTime || state.d3AlphaMin > 0 && state.forceLayout.alpha() < state.d3AlphaMin) { + state.engineRunning = false; // Stop ticking graph + state.onEngineStop(); + } else { + state.forceLayout.tick(); // Tick it + state.onEngineTick(); + } + } + } + function paintNodes() { + var getVisibility = index$2(state.nodeVisibility); + var getVal = index$2(state.nodeVal); + var getColor = index$2(state.nodeColor); + var getNodeCanvasObjectMode = index$2(state.nodeCanvasObjectMode); + var ctx = state.ctx; + + // Draw wider nodes by 1px on shadow canvas for more precise hovering (due to boundary anti-aliasing) + var padAmount = state.isShadow / state.globalScale; + var visibleNodes = state.graphData.nodes.filter(getVisibility); + ctx.save(); + visibleNodes.forEach(function (node) { + var nodeCanvasObjectMode = getNodeCanvasObjectMode(node); + if (state.nodeCanvasObject && (nodeCanvasObjectMode === 'before' || nodeCanvasObjectMode === 'replace')) { + // Custom node before/replace paint + state.nodeCanvasObject(node, ctx, state.globalScale); + if (nodeCanvasObjectMode === 'replace') { + ctx.restore(); + return; + } + } + + // Draw wider nodes by 1px on shadow canvas for more precise hovering (due to boundary anti-aliasing) + var r = Math.sqrt(Math.max(0, getVal(node) || 1)) * state.nodeRelSize + padAmount; + ctx.beginPath(); + ctx.arc(node.x, node.y, r, 0, 2 * Math.PI, false); + ctx.fillStyle = getColor(node) || 'rgba(31, 120, 180, 0.92)'; + ctx.fill(); + if (state.nodeCanvasObject && nodeCanvasObjectMode === 'after') { + // Custom node after paint + state.nodeCanvasObject(node, state.ctx, state.globalScale); + } + }); + ctx.restore(); + } + function paintLinks() { + var getVisibility = index$2(state.linkVisibility); + var getColor = index$2(state.linkColor); + var getWidth = index$2(state.linkWidth); + var getLineDash = index$2(state.linkLineDash); + var getCurvature = index$2(state.linkCurvature); + var getLinkCanvasObjectMode = index$2(state.linkCanvasObjectMode); + var ctx = state.ctx; + + // Draw wider lines by 2px on shadow canvas for more precise hovering (due to boundary anti-aliasing) + var padAmount = state.isShadow * 2; + var visibleLinks = state.graphData.links.filter(getVisibility); + visibleLinks.forEach(calcLinkControlPoints); // calculate curvature control points for all visible links + + var beforeCustomLinks = [], + afterCustomLinks = [], + defaultPaintLinks = visibleLinks; + if (state.linkCanvasObject) { + var replaceCustomLinks = [], + otherCustomLinks = []; + visibleLinks.forEach(function (d) { + return ({ + before: beforeCustomLinks, + after: afterCustomLinks, + replace: replaceCustomLinks + }[getLinkCanvasObjectMode(d)] || otherCustomLinks).push(d); + }); + defaultPaintLinks = [].concat(_toConsumableArray$2(beforeCustomLinks), afterCustomLinks, otherCustomLinks); + beforeCustomLinks = beforeCustomLinks.concat(replaceCustomLinks); + } + + // Custom link before paints + ctx.save(); + beforeCustomLinks.forEach(function (link) { + return state.linkCanvasObject(link, ctx, state.globalScale); + }); + ctx.restore(); + + // Bundle strokes per unique color/width/dash for performance optimization + var linksPerColor = index(defaultPaintLinks, [getColor, getWidth, getLineDash]); + ctx.save(); + Object.entries(linksPerColor).forEach(function (_ref) { + var _ref2 = _slicedToArray$2(_ref, 2), + color = _ref2[0], + linksPerWidth = _ref2[1]; + var lineColor = !color || color === 'undefined' ? 'rgba(0,0,0,0.15)' : color; + Object.entries(linksPerWidth).forEach(function (_ref3) { + var _ref4 = _slicedToArray$2(_ref3, 2), + width = _ref4[0], + linesPerLineDash = _ref4[1]; + var lineWidth = (width || 1) / state.globalScale + padAmount; + Object.entries(linesPerLineDash).forEach(function (_ref5) { + var _ref6 = _slicedToArray$2(_ref5, 2); + _ref6[0]; + var links = _ref6[1]; + var lineDashSegments = getLineDash(links[0]); + ctx.beginPath(); + links.forEach(function (link) { + var start = link.source; + var end = link.target; + if (!start || !end || !start.hasOwnProperty('x') || !end.hasOwnProperty('x')) return; // skip invalid link + + ctx.moveTo(start.x, start.y); + var controlPoints = link.__controlPoints; + if (!controlPoints) { + // Straight line + ctx.lineTo(end.x, end.y); + } else { + // Use quadratic curves for regular lines and bezier for loops + ctx[controlPoints.length === 2 ? 'quadraticCurveTo' : 'bezierCurveTo'].apply(ctx, _toConsumableArray$2(controlPoints).concat([end.x, end.y])); + } + }); + ctx.strokeStyle = lineColor; + ctx.lineWidth = lineWidth; + ctx.setLineDash(lineDashSegments || []); + ctx.stroke(); + }); + }); + }); + ctx.restore(); + + // Custom link after paints + ctx.save(); + afterCustomLinks.forEach(function (link) { + return state.linkCanvasObject(link, ctx, state.globalScale); + }); + ctx.restore(); + + // + + function calcLinkControlPoints(link) { + var curvature = getCurvature(link); + if (!curvature) { + // straight line + link.__controlPoints = null; + return; + } + var start = link.source; + var end = link.target; + if (!start || !end || !start.hasOwnProperty('x') || !end.hasOwnProperty('x')) return; // skip invalid link + + var l = Math.sqrt(Math.pow(end.x - start.x, 2) + Math.pow(end.y - start.y, 2)); // line length + + if (l > 0) { + var a = Math.atan2(end.y - start.y, end.x - start.x); // line angle + var d = l * curvature; // control point distance + + var cp = { + // control point + x: (start.x + end.x) / 2 + d * Math.cos(a - Math.PI / 2), + y: (start.y + end.y) / 2 + d * Math.sin(a - Math.PI / 2) + }; + link.__controlPoints = [cp.x, cp.y]; + } else { + // Same point, draw a loop + var _d = curvature * 70; + link.__controlPoints = [end.x, end.y - _d, end.x + _d, end.y]; + } + } + } + function paintArrows() { + var ARROW_WH_RATIO = 1.6; + var ARROW_VLEN_RATIO = 0.2; + var getLength = index$2(state.linkDirectionalArrowLength); + var getRelPos = index$2(state.linkDirectionalArrowRelPos); + var getVisibility = index$2(state.linkVisibility); + var getColor = index$2(state.linkDirectionalArrowColor || state.linkColor); + var getNodeVal = index$2(state.nodeVal); + var ctx = state.ctx; + ctx.save(); + state.graphData.links.filter(getVisibility).forEach(function (link) { + var arrowLength = getLength(link); + if (!arrowLength || arrowLength < 0) return; + var start = link.source; + var end = link.target; + if (!start || !end || !start.hasOwnProperty('x') || !end.hasOwnProperty('x')) return; // skip invalid link + + var startR = Math.sqrt(Math.max(0, getNodeVal(start) || 1)) * state.nodeRelSize; + var endR = Math.sqrt(Math.max(0, getNodeVal(end) || 1)) * state.nodeRelSize; + var arrowRelPos = Math.min(1, Math.max(0, getRelPos(link))); + var arrowColor = getColor(link) || 'rgba(0,0,0,0.28)'; + var arrowHalfWidth = arrowLength / ARROW_WH_RATIO / 2; + + // Construct bezier for curved lines + var bzLine = link.__controlPoints && _construct(Bezier, [start.x, start.y].concat(_toConsumableArray$2(link.__controlPoints), [end.x, end.y])); + var getCoordsAlongLine = bzLine ? function (t) { + return bzLine.get(t); + } // get position along bezier line + : function (t) { + return { + // straight line: interpolate linearly + x: start.x + (end.x - start.x) * t || 0, + y: start.y + (end.y - start.y) * t || 0 + }; + }; + var lineLen = bzLine ? bzLine.length() : Math.sqrt(Math.pow(end.x - start.x, 2) + Math.pow(end.y - start.y, 2)); + var posAlongLine = startR + arrowLength + (lineLen - startR - endR - arrowLength) * arrowRelPos; + var arrowHead = getCoordsAlongLine(posAlongLine / lineLen); + var arrowTail = getCoordsAlongLine((posAlongLine - arrowLength) / lineLen); + var arrowTailVertex = getCoordsAlongLine((posAlongLine - arrowLength * (1 - ARROW_VLEN_RATIO)) / lineLen); + var arrowTailAngle = Math.atan2(arrowHead.y - arrowTail.y, arrowHead.x - arrowTail.x) - Math.PI / 2; + ctx.beginPath(); + ctx.moveTo(arrowHead.x, arrowHead.y); + ctx.lineTo(arrowTail.x + arrowHalfWidth * Math.cos(arrowTailAngle), arrowTail.y + arrowHalfWidth * Math.sin(arrowTailAngle)); + ctx.lineTo(arrowTailVertex.x, arrowTailVertex.y); + ctx.lineTo(arrowTail.x - arrowHalfWidth * Math.cos(arrowTailAngle), arrowTail.y - arrowHalfWidth * Math.sin(arrowTailAngle)); + ctx.fillStyle = arrowColor; + ctx.fill(); + }); + ctx.restore(); + } + function paintPhotons() { + var getNumPhotons = index$2(state.linkDirectionalParticles); + var getSpeed = index$2(state.linkDirectionalParticleSpeed); + var getDiameter = index$2(state.linkDirectionalParticleWidth); + var getVisibility = index$2(state.linkVisibility); + var getColor = index$2(state.linkDirectionalParticleColor || state.linkColor); + var ctx = state.ctx; + ctx.save(); + state.graphData.links.filter(getVisibility).forEach(function (link) { + var numCyclePhotons = getNumPhotons(link); + if (!link.hasOwnProperty('__photons') || !link.__photons.length) return; + var start = link.source; + var end = link.target; + if (!start || !end || !start.hasOwnProperty('x') || !end.hasOwnProperty('x')) return; // skip invalid link + + var particleSpeed = getSpeed(link); + var photons = link.__photons || []; + var photonR = Math.max(0, getDiameter(link) / 2) / Math.sqrt(state.globalScale); + var photonColor = getColor(link) || 'rgba(0,0,0,0.28)'; + ctx.fillStyle = photonColor; + + // Construct bezier for curved lines + var bzLine = link.__controlPoints ? _construct(Bezier, [start.x, start.y].concat(_toConsumableArray$2(link.__controlPoints), [end.x, end.y])) : null; + var cyclePhotonIdx = 0; + var needsCleanup = false; // whether some photons need to be removed from list + photons.forEach(function (photon) { + var singleHop = !!photon.__singleHop; + if (!photon.hasOwnProperty('__progressRatio')) { + photon.__progressRatio = singleHop ? 0 : cyclePhotonIdx / numCyclePhotons; + } + !singleHop && cyclePhotonIdx++; // increase regular photon index + + photon.__progressRatio += particleSpeed; + if (photon.__progressRatio >= 1) { + if (!singleHop) { + photon.__progressRatio = photon.__progressRatio % 1; + } else { + needsCleanup = true; + return; + } + } + var photonPosRatio = photon.__progressRatio; + var coords = bzLine ? bzLine.get(photonPosRatio) // get position along bezier line + : { + // straight line: interpolate linearly + x: start.x + (end.x - start.x) * photonPosRatio || 0, + y: start.y + (end.y - start.y) * photonPosRatio || 0 + }; + ctx.beginPath(); + ctx.arc(coords.x, coords.y, photonR, 0, 2 * Math.PI, false); + ctx.fill(); + }); + if (needsCleanup) { + // remove expired single hop photons + link.__photons = link.__photons.filter(function (photon) { + return !photon.__singleHop || photon.__progressRatio <= 1; + }); + } + }); + ctx.restore(); + } + }, + emitParticle: function emitParticle(state, link) { + if (link) { + !link.__photons && (link.__photons = []); + link.__photons.push({ + __singleHop: true + }); // add a single hop particle + } + + return this; + } + }, + stateInit: function stateInit() { + return { + forceLayout: d3ForceSimulation().force('link', d3ForceLink()).force('charge', d3ForceManyBody()).force('center', d3ForceCenter()).force('dagRadial', null).stop(), + engineRunning: false + }; + }, + init: function init(canvasCtx, state) { + // Main canvas object to manipulate + state.ctx = canvasCtx; + }, + update: function update(state) { + state.engineRunning = false; // Pause simulation + state.onUpdate(); + if (state.nodeAutoColorBy !== null) { + // Auto add color to uncolored nodes + autoColorObjects(state.graphData.nodes, index$2(state.nodeAutoColorBy), state.nodeColor); + } + if (state.linkAutoColorBy !== null) { + // Auto add color to uncolored links + autoColorObjects(state.graphData.links, index$2(state.linkAutoColorBy), state.linkColor); + } + + // parse links + state.graphData.links.forEach(function (link) { + link.source = link[state.linkSource]; + link.target = link[state.linkTarget]; + }); + + // Feed data to force-directed layout + state.forceLayout.stop().alpha(1) // re-heat the simulation + .nodes(state.graphData.nodes); + + // add links (if link force is still active) + var linkForce = state.forceLayout.force('link'); + if (linkForce) { + linkForce.id(function (d) { + return d[state.nodeId]; + }).links(state.graphData.links); + } + + // setup dag force constraints + var nodeDepths = state.dagMode && getDagDepths(state.graphData, function (node) { + return node[state.nodeId]; + }, { + nodeFilter: state.dagNodeFilter, + onLoopError: state.onDagError || undefined + }); + var maxDepth = Math.max.apply(Math, _toConsumableArray$2(Object.values(nodeDepths || []))); + var dagLevelDistance = state.dagLevelDistance || state.graphData.nodes.length / (maxDepth || 1) * DAG_LEVEL_NODE_RATIO * (['radialin', 'radialout'].indexOf(state.dagMode) !== -1 ? 0.7 : 1); + + // Fix nodes to x,y for dag mode + if (state.dagMode) { + var getFFn = function getFFn(fix, invert) { + return function (node) { + return !fix ? undefined : (nodeDepths[node[state.nodeId]] - maxDepth / 2) * dagLevelDistance * (invert ? -1 : 1); + }; + }; + var fxFn = getFFn(['lr', 'rl'].indexOf(state.dagMode) !== -1, state.dagMode === 'rl'); + var fyFn = getFFn(['td', 'bu'].indexOf(state.dagMode) !== -1, state.dagMode === 'bu'); + state.graphData.nodes.filter(state.dagNodeFilter).forEach(function (node) { + node.fx = fxFn(node); + node.fy = fyFn(node); + }); + } + + // Use radial force for radial dags + state.forceLayout.force('dagRadial', ['radialin', 'radialout'].indexOf(state.dagMode) !== -1 ? d3ForceRadial(function (node) { + var nodeDepth = nodeDepths[node[state.nodeId]] || -1; + return (state.dagMode === 'radialin' ? maxDepth - nodeDepth : nodeDepth) * dagLevelDistance; + }).strength(function (node) { + return state.dagNodeFilter(node) ? 1 : 0; + }) : null); + for (var i = 0; i < state.warmupTicks && !(state.d3AlphaMin > 0 && state.forceLayout.alpha() < state.d3AlphaMin); i++) { + state.forceLayout.tick(); + } // Initial ticks before starting to render + + this.resetCountdown(); + state.onFinishUpdate(); + } + }); + + function linkKapsule (kapsulePropNames, kapsuleType) { + var propNames = kapsulePropNames instanceof Array ? kapsulePropNames : [kapsulePropNames]; + var dummyK = new kapsuleType(); // To extract defaults + dummyK._destructor && dummyK._destructor(); + return { + linkProp: function linkProp(prop) { + // link property config + return { + "default": dummyK[prop](), + onChange: function onChange(v, state) { + propNames.forEach(function (propName) { + return state[propName][prop](v); + }); + }, + triggerUpdate: false + }; + }, + linkMethod: function linkMethod(method) { + // link method pass-through + return function (state) { + for (var _len = arguments.length, args = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) { + args[_key - 1] = arguments[_key]; + } + var returnVals = []; + propNames.forEach(function (propName) { + var kapsuleInstance = state[propName]; + var returnVal = kapsuleInstance[method].apply(kapsuleInstance, args); + if (returnVal !== kapsuleInstance) { + returnVals.push(returnVal); + } + }); + return returnVals.length ? returnVals[0] : this; // chain based on the parent object, not the inner kapsule + }; + } + }; + } + + var HOVER_CANVAS_THROTTLE_DELAY = 800; // ms to throttle shadow canvas updates for perf improvement + var ZOOM2NODES_FACTOR = 4; + + // Expose config from forceGraph + var bindFG = linkKapsule('forceGraph', CanvasForceGraph); + var bindBoth = linkKapsule(['forceGraph', 'shadowGraph'], CanvasForceGraph); + var linkedProps = Object.assign.apply(Object, _toConsumableArray$2(['nodeColor', 'nodeAutoColorBy', 'nodeCanvasObject', 'nodeCanvasObjectMode', 'linkColor', 'linkAutoColorBy', 'linkLineDash', 'linkWidth', 'linkCanvasObject', 'linkCanvasObjectMode', 'linkDirectionalArrowLength', 'linkDirectionalArrowColor', 'linkDirectionalArrowRelPos', 'linkDirectionalParticles', 'linkDirectionalParticleSpeed', 'linkDirectionalParticleWidth', 'linkDirectionalParticleColor', 'dagMode', 'dagLevelDistance', 'dagNodeFilter', 'onDagError', 'd3AlphaMin', 'd3AlphaDecay', 'd3VelocityDecay', 'warmupTicks', 'cooldownTicks', 'cooldownTime', 'onEngineTick', 'onEngineStop'].map(function (p) { + return _defineProperty({}, p, bindFG.linkProp(p)); + })).concat(_toConsumableArray$2(['nodeRelSize', 'nodeId', 'nodeVal', 'nodeVisibility', 'linkSource', 'linkTarget', 'linkVisibility', 'linkCurvature'].map(function (p) { + return _defineProperty({}, p, bindBoth.linkProp(p)); + })))); + var linkedMethods = Object.assign.apply(Object, _toConsumableArray$2(['d3Force', 'd3ReheatSimulation', 'emitParticle'].map(function (p) { + return _defineProperty({}, p, bindFG.linkMethod(p)); + }))); + function adjustCanvasSize(state) { + if (state.canvas) { + var curWidth = state.canvas.width; + var curHeight = state.canvas.height; + if (curWidth === 300 && curHeight === 150) { + // Default canvas dimensions + curWidth = curHeight = 0; + } + var pxScale = window.devicePixelRatio; // 2 on retina displays + curWidth /= pxScale; + curHeight /= pxScale; + + // Resize canvases + [state.canvas, state.shadowCanvas].forEach(function (canvas) { + // Element size + canvas.style.width = "".concat(state.width, "px"); + canvas.style.height = "".concat(state.height, "px"); + + // Memory size (scaled to avoid blurriness) + canvas.width = state.width * pxScale; + canvas.height = state.height * pxScale; + + // Normalize coordinate system to use css pixels (on init only) + if (!curWidth && !curHeight) { + canvas.getContext('2d').scale(pxScale, pxScale); + } + }); + + // Relative center panning based on 0,0 + var k = transform(state.canvas).k; + state.zoom.translateBy(state.zoom.__baseElem, (state.width - curWidth) / 2 / k, (state.height - curHeight) / 2 / k); + state.needsRedraw = true; + } + } + function resetTransform(ctx) { + var pxRatio = window.devicePixelRatio; + ctx.setTransform(pxRatio, 0, 0, pxRatio, 0, 0); + } + function clearCanvas(ctx, width, height) { + ctx.save(); + resetTransform(ctx); // reset transform + ctx.clearRect(0, 0, width, height); + ctx.restore(); //restore transforms + } + + // + + var forceGraph = index$3({ + props: _objectSpread2({ + width: { + "default": window.innerWidth, + onChange: function onChange(_, state) { + return adjustCanvasSize(state); + }, + triggerUpdate: false + }, + height: { + "default": window.innerHeight, + onChange: function onChange(_, state) { + return adjustCanvasSize(state); + }, + triggerUpdate: false + }, + graphData: { + "default": { + nodes: [], + links: [] + }, + onChange: function onChange(d, state) { + [{ + type: 'Node', + objs: d.nodes + }, { + type: 'Link', + objs: d.links + }].forEach(hexIndex); + state.forceGraph.graphData(d); + state.shadowGraph.graphData(d); + function hexIndex(_ref4) { + var type = _ref4.type, + objs = _ref4.objs; + objs.filter(function (d) { + if (!d.hasOwnProperty('__indexColor')) return true; + var cur = state.colorTracker.lookup(d.__indexColor); + return !cur || !cur.hasOwnProperty('d') || cur.d !== d; + }).forEach(function (d) { + // store object lookup color + d.__indexColor = state.colorTracker.register({ + type: type, + d: d + }); + }); + } + }, + triggerUpdate: false + }, + backgroundColor: { + onChange: function onChange(color, state) { + state.canvas && color && (state.canvas.style.background = color); + }, + triggerUpdate: false + }, + nodeLabel: { + "default": 'name', + triggerUpdate: false + }, + nodePointerAreaPaint: { + onChange: function onChange(paintFn, state) { + state.shadowGraph.nodeCanvasObject(!paintFn ? null : function (node, ctx, globalScale) { + return paintFn(node, node.__indexColor, ctx, globalScale); + }); + state.flushShadowCanvas && state.flushShadowCanvas(); + }, + triggerUpdate: false + }, + linkPointerAreaPaint: { + onChange: function onChange(paintFn, state) { + state.shadowGraph.linkCanvasObject(!paintFn ? null : function (link, ctx, globalScale) { + return paintFn(link, link.__indexColor, ctx, globalScale); + }); + state.flushShadowCanvas && state.flushShadowCanvas(); + }, + triggerUpdate: false + }, + linkLabel: { + "default": 'name', + triggerUpdate: false + }, + linkHoverPrecision: { + "default": 4, + triggerUpdate: false + }, + minZoom: { + "default": 0.01, + onChange: function onChange(minZoom, state) { + state.zoom.scaleExtent([minZoom, state.zoom.scaleExtent()[1]]); + }, + triggerUpdate: false + }, + maxZoom: { + "default": 1000, + onChange: function onChange(maxZoom, state) { + state.zoom.scaleExtent([state.zoom.scaleExtent()[0], maxZoom]); + }, + triggerUpdate: false + }, + enableNodeDrag: { + "default": true, + triggerUpdate: false + }, + enableZoomInteraction: { + "default": true, + triggerUpdate: false + }, + enablePanInteraction: { + "default": true, + triggerUpdate: false + }, + enableZoomPanInteraction: { + "default": true, + triggerUpdate: false + }, + // to be deprecated + enablePointerInteraction: { + "default": true, + onChange: function onChange(_, state) { + state.hoverObj = null; + }, + triggerUpdate: false + }, + autoPauseRedraw: { + "default": true, + triggerUpdate: false + }, + onNodeDrag: { + "default": function _default() {}, + triggerUpdate: false + }, + onNodeDragEnd: { + "default": function _default() {}, + triggerUpdate: false + }, + onNodeClick: { + triggerUpdate: false + }, + onNodeRightClick: { + triggerUpdate: false + }, + onNodeHover: { + triggerUpdate: false + }, + onLinkClick: { + triggerUpdate: false + }, + onLinkRightClick: { + triggerUpdate: false + }, + onLinkHover: { + triggerUpdate: false + }, + onBackgroundClick: { + triggerUpdate: false + }, + onBackgroundRightClick: { + triggerUpdate: false + }, + onZoom: { + triggerUpdate: false + }, + onZoomEnd: { + triggerUpdate: false + }, + onRenderFramePre: { + triggerUpdate: false + }, + onRenderFramePost: { + triggerUpdate: false + } + }, linkedProps), + aliases: { + // Prop names supported for backwards compatibility + stopAnimation: 'pauseAnimation' + }, + methods: _objectSpread2({ + graph2ScreenCoords: function graph2ScreenCoords(state, x, y) { + var t = transform(state.canvas); + return { + x: x * t.k + t.x, + y: y * t.k + t.y + }; + }, + screen2GraphCoords: function screen2GraphCoords(state, x, y) { + var t = transform(state.canvas); + return { + x: (x - t.x) / t.k, + y: (y - t.y) / t.k + }; + }, + centerAt: function centerAt(state, x, y, transitionDuration) { + if (!state.canvas) return null; // no canvas yet + + // setter + if (x !== undefined || y !== undefined) { + var finalPos = Object.assign({}, x !== undefined ? { + x: x + } : {}, y !== undefined ? { + y: y + } : {}); + if (!transitionDuration) { + // no animation + setCenter(finalPos); + } else { + new Tween(getCenter()).to(finalPos, transitionDuration).easing(Easing.Quadratic.Out).onUpdate(setCenter).start(); + } + return this; + } + + // getter + return getCenter(); + + // + + function getCenter() { + var t = transform(state.canvas); + return { + x: (state.width / 2 - t.x) / t.k, + y: (state.height / 2 - t.y) / t.k + }; + } + function setCenter(_ref5) { + var x = _ref5.x, + y = _ref5.y; + state.zoom.translateTo(state.zoom.__baseElem, x === undefined ? getCenter().x : x, y === undefined ? getCenter().y : y); + state.needsRedraw = true; + } + }, + zoom: function zoom(state, k, transitionDuration) { + if (!state.canvas) return null; // no canvas yet + + // setter + if (k !== undefined) { + if (!transitionDuration) { + // no animation + setZoom(k); + } else { + new Tween({ + k: getZoom() + }).to({ + k: k + }, transitionDuration).easing(Easing.Quadratic.Out).onUpdate(function (_ref6) { + var k = _ref6.k; + return setZoom(k); + }).start(); + } + return this; + } + + // getter + return getZoom(); + + // + + function getZoom() { + return transform(state.canvas).k; + } + function setZoom(k) { + state.zoom.scaleTo(state.zoom.__baseElem, k); + state.needsRedraw = true; + } + }, + zoomToFit: function zoomToFit(state) { + var transitionDuration = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 0; + var padding = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 10; + for (var _len = arguments.length, bboxArgs = new Array(_len > 3 ? _len - 3 : 0), _key = 3; _key < _len; _key++) { + bboxArgs[_key - 3] = arguments[_key]; + } + var bbox = this.getGraphBbox.apply(this, bboxArgs); + if (bbox) { + var center = { + x: (bbox.x[0] + bbox.x[1]) / 2, + y: (bbox.y[0] + bbox.y[1]) / 2 + }; + var zoomK = Math.max(1e-12, Math.min(1e12, (state.width - padding * 2) / (bbox.x[1] - bbox.x[0]), (state.height - padding * 2) / (bbox.y[1] - bbox.y[0]))); + this.centerAt(center.x, center.y, transitionDuration); + this.zoom(zoomK, transitionDuration); + } + return this; + }, + getGraphBbox: function getGraphBbox(state) { + var nodeFilter = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : function () { + return true; + }; + var getVal = index$2(state.nodeVal); + var getR = function getR(node) { + return Math.sqrt(Math.max(0, getVal(node) || 1)) * state.nodeRelSize; + }; + var nodesPos = state.graphData.nodes.filter(nodeFilter).map(function (node) { + return { + x: node.x, + y: node.y, + r: getR(node) + }; + }); + return !nodesPos.length ? null : { + x: [min$1(nodesPos, function (node) { + return node.x - node.r; + }), max$1(nodesPos, function (node) { + return node.x + node.r; + })], + y: [min$1(nodesPos, function (node) { + return node.y - node.r; + }), max$1(nodesPos, function (node) { + return node.y + node.r; + })] + }; + }, + pauseAnimation: function pauseAnimation(state) { + if (state.animationFrameRequestId) { + cancelAnimationFrame(state.animationFrameRequestId); + state.animationFrameRequestId = null; + } + return this; + }, + resumeAnimation: function resumeAnimation(state) { + if (!state.animationFrameRequestId) { + this._animationCycle(); + } + return this; + }, + _destructor: function _destructor() { + this.pauseAnimation(); + this.graphData({ + nodes: [], + links: [] + }); + } + }, linkedMethods), + stateInit: function stateInit() { + return { + lastSetZoom: 1, + zoom: d3Zoom(), + forceGraph: new CanvasForceGraph(), + shadowGraph: new CanvasForceGraph().cooldownTicks(0).nodeColor('__indexColor').linkColor('__indexColor').isShadow(true), + colorTracker: new _default() // indexed objects for rgb lookup + }; + }, + + init: function init(domNode, state) { + var _this = this; + // Wipe DOM + domNode.innerHTML = ''; + + // Container anchor for canvas and tooltip + var container = document.createElement('div'); + container.classList.add('force-graph-container'); + container.style.position = 'relative'; + domNode.appendChild(container); + state.canvas = document.createElement('canvas'); + if (state.backgroundColor) state.canvas.style.background = state.backgroundColor; + container.appendChild(state.canvas); + state.shadowCanvas = document.createElement('canvas'); + + // Show shadow canvas + //state.shadowCanvas.style.position = 'absolute'; + //state.shadowCanvas.style.top = '0'; + //state.shadowCanvas.style.left = '0'; + //container.appendChild(state.shadowCanvas); + + var ctx = state.canvas.getContext('2d'); + var shadowCtx = state.shadowCanvas.getContext('2d', { + willReadFrequently: true + }); + var pointerPos = { + x: -1e12, + y: -1e12 + }; + var getObjUnderPointer = function getObjUnderPointer() { + var obj = null; + var pxScale = window.devicePixelRatio; + var px = pointerPos.x > 0 && pointerPos.y > 0 ? shadowCtx.getImageData(pointerPos.x * pxScale, pointerPos.y * pxScale, 1, 1) : null; + // Lookup object per pixel color + px && (obj = state.colorTracker.lookup(px.data)); + return obj; + }; + + // Setup node drag interaction + d3Select(state.canvas).call(d3Drag().subject(function () { + if (!state.enableNodeDrag) { + return null; + } + var obj = getObjUnderPointer(); + return obj && obj.type === 'Node' ? obj.d : null; // Only drag nodes + }).on('start', function (ev) { + var obj = ev.subject; + obj.__initialDragPos = { + x: obj.x, + y: obj.y, + fx: obj.fx, + fy: obj.fy + }; + + // keep engine running at low intensity throughout drag + if (!ev.active) { + obj.fx = obj.x; + obj.fy = obj.y; // Fix points + } + + // drag cursor + state.canvas.classList.add('grabbable'); + }).on('drag', function (ev) { + var obj = ev.subject; + var initPos = obj.__initialDragPos; + var dragPos = ev; + var k = transform(state.canvas).k; + var translate = { + x: initPos.x + (dragPos.x - initPos.x) / k - obj.x, + y: initPos.y + (dragPos.y - initPos.y) / k - obj.y + }; + + // Move fx/fy (and x/y) of nodes based on the scaled drag distance since the drag start + ['x', 'y'].forEach(function (c) { + return obj["f".concat(c)] = obj[c] = initPos[c] + (dragPos[c] - initPos[c]) / k; + }); + + // prevent freeze while dragging + state.forceGraph.d3AlphaTarget(0.3) // keep engine running at low intensity throughout drag + .resetCountdown(); // prevent freeze while dragging + + state.isPointerDragging = true; + obj.__dragged = true; + state.onNodeDrag(obj, translate); + }).on('end', function (ev) { + var obj = ev.subject; + var initPos = obj.__initialDragPos; + var translate = { + x: obj.x - initPos.x, + y: obj.y - initPos.y + }; + if (initPos.fx === undefined) { + obj.fx = undefined; + } + if (initPos.fy === undefined) { + obj.fy = undefined; + } + delete obj.__initialDragPos; + if (state.forceGraph.d3AlphaTarget()) { + state.forceGraph.d3AlphaTarget(0) // release engine low intensity + .resetCountdown(); // let the engine readjust after releasing fixed nodes + } + + // drag cursor + state.canvas.classList.remove('grabbable'); + state.isPointerDragging = false; + if (obj.__dragged) { + delete obj.__dragged; + state.onNodeDragEnd(obj, translate); + } + })); + + // Setup zoom / pan interaction + state.zoom(state.zoom.__baseElem = d3Select(state.canvas)); // Attach controlling elem for easy access + + state.zoom.__baseElem.on('dblclick.zoom', null); // Disable double-click to zoom + + state.zoom.filter(function (ev) { + return ( + // disable zoom interaction + !ev.button && state.enableZoomPanInteraction && (state.enableZoomInteraction || ev.type !== 'wheel') && (state.enablePanInteraction || ev.type === 'wheel') + ); + }).on('zoom', function (ev) { + var t = ev.transform; + [ctx, shadowCtx].forEach(function (c) { + resetTransform(c); + c.translate(t.x, t.y); + c.scale(t.k, t.k); + }); + state.onZoom && state.onZoom(_objectSpread2(_objectSpread2({}, t), _this.centerAt())); // report x,y coordinates relative to canvas center + state.needsRedraw = true; + }).on('end', function (ev) { + return state.onZoomEnd && state.onZoomEnd(_objectSpread2(_objectSpread2({}, ev.transform), _this.centerAt())); + }); + adjustCanvasSize(state); + state.forceGraph.onNeedsRedraw(function () { + return state.needsRedraw = true; + }).onFinishUpdate(function () { + // re-zoom, if still in default position (not user modified) + if (transform(state.canvas).k === state.lastSetZoom && state.graphData.nodes.length) { + state.zoom.scaleTo(state.zoom.__baseElem, state.lastSetZoom = ZOOM2NODES_FACTOR / Math.cbrt(state.graphData.nodes.length)); + state.needsRedraw = true; + } + }); + + // Setup tooltip + var toolTipElem = document.createElement('div'); + toolTipElem.classList.add('graph-tooltip'); + container.appendChild(toolTipElem); + + // Capture pointer coords on move or touchstart + ['pointermove', 'pointerdown'].forEach(function (evType) { + return container.addEventListener(evType, function (ev) { + if (evType === 'pointerdown') { + state.isPointerPressed = true; // track click state + state.pointerDownEvent = ev; + } + + // detect pointer drag on canvas pan + !state.isPointerDragging && ev.type === 'pointermove' && state.onBackgroundClick // only bother detecting drags this way if background clicks are enabled (so they don't trigger accidentally on canvas panning) + && (ev.pressure > 0 || state.isPointerPressed) // ev.pressure always 0 on Safari, so we use the isPointerPressed tracker + && (ev.pointerType !== 'touch' || ev.movementX === undefined || [ev.movementX, ev.movementY].some(function (m) { + return Math.abs(m) > 1; + })) // relax drag trigger sensitivity on touch events + && (state.isPointerDragging = true); + + // update the pointer pos + var offset = getOffset(container); + pointerPos.x = ev.pageX - offset.left; + pointerPos.y = ev.pageY - offset.top; + + // Move tooltip + toolTipElem.style.top = "".concat(pointerPos.y, "px"); + toolTipElem.style.left = "".concat(pointerPos.x, "px"); + + // adjust horizontal position to not exceed canvas boundaries + toolTipElem.style.transform = "translate(-".concat(pointerPos.x / state.width * 100, "%, ").concat( + // flip to above if near bottom + state.height - pointerPos.y < 100 ? 'calc(-100% - 8px)' : '21px', ")"); + + // + + function getOffset(el) { + var rect = el.getBoundingClientRect(), + scrollLeft = window.pageXOffset || document.documentElement.scrollLeft, + scrollTop = window.pageYOffset || document.documentElement.scrollTop; + return { + top: rect.top + scrollTop, + left: rect.left + scrollLeft + }; + } + }, { + passive: true + }); + }); + + // Handle click/touch events on nodes/links + container.addEventListener('pointerup', function (ev) { + state.isPointerPressed = false; + if (state.isPointerDragging) { + state.isPointerDragging = false; + return; // don't trigger click events after pointer drag (pan / node drag functionality) + } + + var cbEvents = [ev, state.pointerDownEvent]; + requestAnimationFrame(function () { + // trigger click events asynchronously, to allow hoverObj to be set (on frame) + if (ev.button === 0) { + // mouse left-click or touch + if (state.hoverObj) { + var fn = state["on".concat(state.hoverObj.type, "Click")]; + fn && fn.apply(void 0, [state.hoverObj.d].concat(cbEvents)); + } else { + state.onBackgroundClick && state.onBackgroundClick.apply(state, cbEvents); + } + } + if (ev.button === 2) { + // mouse right-click + if (state.hoverObj) { + var _fn = state["on".concat(state.hoverObj.type, "RightClick")]; + _fn && _fn.apply(void 0, [state.hoverObj.d].concat(cbEvents)); + } else { + state.onBackgroundRightClick && state.onBackgroundRightClick.apply(state, cbEvents); + } + } + }); + }, { + passive: true + }); + container.addEventListener('contextmenu', function (ev) { + if (!state.onBackgroundRightClick && !state.onNodeRightClick && !state.onLinkRightClick) return true; // default contextmenu behavior + ev.preventDefault(); + return false; + }); + state.forceGraph(ctx); + state.shadowGraph(shadowCtx); + + // + + var refreshShadowCanvas = throttle(function () { + // wipe canvas + clearCanvas(shadowCtx, state.width, state.height); + + // Adjust link hover area + state.shadowGraph.linkWidth(function (l) { + return index$2(state.linkWidth)(l) + state.linkHoverPrecision; + }); + + // redraw + var t = transform(state.canvas); + state.shadowGraph.globalScale(t.k).tickFrame(); + }, HOVER_CANVAS_THROTTLE_DELAY); + state.flushShadowCanvas = refreshShadowCanvas.flush; // hook to immediately invoke shadow canvas paint + + // Kick-off renderer + (this._animationCycle = function animate() { + // IIFE + var doRedraw = !state.autoPauseRedraw || !!state.needsRedraw || state.forceGraph.isEngineRunning() || state.graphData.links.some(function (d) { + return d.__photons && d.__photons.length; + }); + state.needsRedraw = false; + if (state.enablePointerInteraction) { + // Update tooltip and trigger onHover events + var obj = !state.isPointerDragging ? getObjUnderPointer() : null; // don't hover during drag + if (obj !== state.hoverObj) { + var prevObj = state.hoverObj; + var prevObjType = prevObj ? prevObj.type : null; + var objType = obj ? obj.type : null; + if (prevObjType && prevObjType !== objType) { + // Hover out + var fn = state["on".concat(prevObjType, "Hover")]; + fn && fn(null, prevObj.d); + } + if (objType) { + // Hover in + var _fn2 = state["on".concat(objType, "Hover")]; + _fn2 && _fn2(obj.d, prevObjType === objType ? prevObj.d : null); + } + var tooltipContent = obj ? index$2(state["".concat(obj.type.toLowerCase(), "Label")])(obj.d) || '' : ''; + toolTipElem.style.visibility = tooltipContent ? 'visible' : 'hidden'; + toolTipElem.innerHTML = tooltipContent; + + // set pointer if hovered object is clickable + state.canvas.classList[obj && state["on".concat(objType, "Click")] || !obj && state.onBackgroundClick ? 'add' : 'remove']('clickable'); + state.hoverObj = obj; + } + doRedraw && refreshShadowCanvas(); + } + if (doRedraw) { + // Wipe canvas + clearCanvas(ctx, state.width, state.height); + + // Frame cycle + var globalScale = transform(state.canvas).k; + state.onRenderFramePre && state.onRenderFramePre(ctx, globalScale); + state.forceGraph.globalScale(globalScale).tickFrame(); + state.onRenderFramePost && state.onRenderFramePost(ctx, globalScale); + } + update(); // update canvas animation tweens + + state.animationFrameRequestId = requestAnimationFrame(animate); + })(); + }, + update: function updateFn(state) {} + }); + + return forceGraph; + +})); +//# sourceMappingURL=force-graph.js.map diff --git a/hal-core/resources/web/js/lib/force-graph.min.js b/hal-core/resources/web/js/lib/force-graph.min.js new file mode 100644 index 00000000..42b88f34 --- /dev/null +++ b/hal-core/resources/web/js/lib/force-graph.min.js @@ -0,0 +1,5 @@ +// Version 1.43.4 force-graph - https://github.com/vasturiano/force-graph +!function(t,n){"object"==typeof exports&&"undefined"!=typeof module?module.exports=n():"function"==typeof define&&define.amd?define(n):(t="undefined"!=typeof globalThis?globalThis:t||self).ForceGraph=n()}(this,(function(){"use strict";function n(t,n){var e=Object.keys(t);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(t);n&&(r=r.filter((function(n){return Object.getOwnPropertyDescriptor(t,n).enumerable}))),e.push.apply(e,r)}return e}function e(t){for(var e=1;et.length)&&(n=t.length);for(var e=0,r=new Array(n);e=0&&"xmlns"!==(n=t.slice(0,e))&&(t=t.slice(e+1)),f.hasOwnProperty(n)?{space:f[n],local:t}:t}function p(t){return function(){var n=this.ownerDocument,e=this.namespaceURI;return e===h&&n.documentElement.namespaceURI===h?n.createElement(t):n.createElementNS(e,t)}}function g(t){return function(){return this.ownerDocument.createElementNS(t.space,t.local)}}function y(t){var n=d(t);return(n.local?g:p)(n)}function v(){}function _(t){return null==t?v:function(){return this.querySelector(t)}}function m(){return[]}function x(t){return null==t?m:function(){return this.querySelectorAll(t)}}function b(t){return function(){return function(t){return null==t?[]:Array.isArray(t)?t:Array.from(t)}(t.apply(this,arguments))}}function w(t){return function(){return this.matches(t)}}function k(t){return function(n){return n.matches(t)}}var M=Array.prototype.find;function z(){return this.firstElementChild}var A=Array.prototype.filter;function S(){return Array.from(this.children)}function C(t){return new Array(t.length)}function E(t,n){this.ownerDocument=t.ownerDocument,this.namespaceURI=t.namespaceURI,this._next=null,this._parent=t,this.__data__=n}function O(t,n,e,r,i,o){for(var a,u=0,s=n.length,l=o.length;un?1:t>=n?0:NaN}function R(t){return function(){this.removeAttribute(t)}}function D(t){return function(){this.removeAttributeNS(t.space,t.local)}}function I(t,n){return function(){this.setAttribute(t,n)}}function U(t,n){return function(){this.setAttributeNS(t.space,t.local,n)}}function F(t,n){return function(){var e=n.apply(this,arguments);null==e?this.removeAttribute(t):this.setAttribute(t,e)}}function L(t,n){return function(){var e=n.apply(this,arguments);null==e?this.removeAttributeNS(t.space,t.local):this.setAttributeNS(t.space,t.local,e)}}function q(t){return t.ownerDocument&&t.ownerDocument.defaultView||t.document&&t||t.defaultView}function B(t){return function(){this.style.removeProperty(t)}}function $(t,n,e){return function(){this.style.setProperty(t,n,e)}}function H(t,n,e){return function(){var r=n.apply(this,arguments);null==r?this.style.removeProperty(t):this.style.setProperty(t,r,e)}}function V(t,n){return t.style.getPropertyValue(n)||q(t).getComputedStyle(t,null).getPropertyValue(n)}function X(t){return function(){delete this[t]}}function G(t,n){return function(){this[t]=n}}function Y(t,n){return function(){var e=n.apply(this,arguments);null==e?delete this[t]:this[t]=e}}function W(t){return t.trim().split(/^|\s+/)}function Z(t){return t.classList||new Q(t)}function Q(t){this._node=t,this._names=W(t.getAttribute("class")||"")}function K(t,n){for(var e=Z(t),r=-1,i=n.length;++r=0&&(this._names.splice(n,1),this._node.setAttribute("class",this._names.join(" ")))},contains:function(t){return this._names.indexOf(t)>=0}};var xt=[null];function bt(t,n){this._groups=t,this._parents=n}function wt(){return new bt([[document.documentElement]],xt)}function kt(t){return"string"==typeof t?new bt([[document.querySelector(t)]],[document.documentElement]):new bt([[t]],xt)}function Mt(t,n){if(t=function(t){let n;for(;n=t.sourceEvent;)t=n;return t}(t),void 0===n&&(n=t.currentTarget),n){var e=n.ownerSVGElement||n;if(e.createSVGPoint){var r=e.createSVGPoint();return r.x=t.clientX,r.y=t.clientY,[(r=r.matrixTransform(n.getScreenCTM().inverse())).x,r.y]}if(n.getBoundingClientRect){var i=n.getBoundingClientRect();return[t.clientX-i.left-n.clientLeft,t.clientY-i.top-n.clientTop]}}return[t.pageX,t.pageY]}bt.prototype=wt.prototype={constructor:bt,select:function(t){"function"!=typeof t&&(t=_(t));for(var n=this._groups,e=n.length,r=new Array(e),i=0;i=x&&(x=m+1);!(_=y[x])&&++x=0;)(r=i[o])&&(a&&4^r.compareDocumentPosition(a)&&a.parentNode.insertBefore(r,a),a=r);return this},sort:function(t){function n(n,e){return n&&e?t(n.__data__,e.__data__):!n-!e}t||(t=T);for(var e=this._groups,r=e.length,i=new Array(r),o=0;o1?this.each((null==n?B:"function"==typeof n?H:$)(t,n,null==e?"":e)):V(this.node(),t)},property:function(t,n){return arguments.length>1?this.each((null==n?X:"function"==typeof n?Y:G)(t,n)):this.node()[t]},classed:function(t,n){var e=W(t+"");if(arguments.length<2){for(var r=Z(this.node()),i=-1,o=e.length;++i=0&&(n=t.slice(e+1),t=t.slice(0,e)),{type:t,name:n}}))}(t+""),a=o.length;if(!(arguments.length<2)){for(u=n?yt:gt,r=0;r{}};function At(){for(var t,n=0,e=arguments.length,r={};n=0&&(n=t.slice(e+1),t=t.slice(0,e)),t&&!r.hasOwnProperty(t))throw new Error("unknown type: "+t);return{type:t,name:n}}))),a=-1,u=o.length;if(!(arguments.length<2)){if(null!=n&&"function"!=typeof n)throw new Error("invalid callback: "+n);for(;++a0)for(var e,r,i=new Array(e),o=0;o()=>t;function It(t,{sourceEvent:n,subject:e,target:r,identifier:i,active:o,x:a,y:u,dx:s,dy:l,dispatch:c}){Object.defineProperties(this,{type:{value:t,enumerable:!0,configurable:!0},sourceEvent:{value:n,enumerable:!0,configurable:!0},subject:{value:e,enumerable:!0,configurable:!0},target:{value:r,enumerable:!0,configurable:!0},identifier:{value:i,enumerable:!0,configurable:!0},active:{value:o,enumerable:!0,configurable:!0},x:{value:a,enumerable:!0,configurable:!0},y:{value:u,enumerable:!0,configurable:!0},dx:{value:s,enumerable:!0,configurable:!0},dy:{value:l,enumerable:!0,configurable:!0},_:{value:c}})}function Ut(t){return!t.ctrlKey&&!t.button}function Ft(){return this.parentNode}function Lt(t,n){return null==n?{x:t.x,y:t.y}:n}function qt(){return navigator.maxTouchPoints||"ontouchstart"in this}function Bt(t,n,e){t.prototype=n.prototype=e,e.constructor=t}function $t(t,n){var e=Object.create(t.prototype);for(var r in n)e[r]=n[r];return e}function Ht(){}It.prototype.on=function(){var t=this._.on.apply(this._,arguments);return t===this._?this:t};var Vt=.7,Xt=1/Vt,Gt="\\s*([+-]?\\d+)\\s*",Yt="\\s*([+-]?(?:\\d*\\.)?\\d+(?:[eE][+-]?\\d+)?)\\s*",Wt="\\s*([+-]?(?:\\d*\\.)?\\d+(?:[eE][+-]?\\d+)?)%\\s*",Zt=/^#([0-9a-f]{3,8})$/,Qt=new RegExp(`^rgb\\(${Gt},${Gt},${Gt}\\)$`),Kt=new RegExp(`^rgb\\(${Wt},${Wt},${Wt}\\)$`),Jt=new RegExp(`^rgba\\(${Gt},${Gt},${Gt},${Yt}\\)$`),tn=new RegExp(`^rgba\\(${Wt},${Wt},${Wt},${Yt}\\)$`),nn=new RegExp(`^hsl\\(${Yt},${Wt},${Wt}\\)$`),en=new RegExp(`^hsla\\(${Yt},${Wt},${Wt},${Yt}\\)$`),rn={aliceblue:15792383,antiquewhite:16444375,aqua:65535,aquamarine:8388564,azure:15794175,beige:16119260,bisque:16770244,black:0,blanchedalmond:16772045,blue:255,blueviolet:9055202,brown:10824234,burlywood:14596231,cadetblue:6266528,chartreuse:8388352,chocolate:13789470,coral:16744272,cornflowerblue:6591981,cornsilk:16775388,crimson:14423100,cyan:65535,darkblue:139,darkcyan:35723,darkgoldenrod:12092939,darkgray:11119017,darkgreen:25600,darkgrey:11119017,darkkhaki:12433259,darkmagenta:9109643,darkolivegreen:5597999,darkorange:16747520,darkorchid:10040012,darkred:9109504,darksalmon:15308410,darkseagreen:9419919,darkslateblue:4734347,darkslategray:3100495,darkslategrey:3100495,darkturquoise:52945,darkviolet:9699539,deeppink:16716947,deepskyblue:49151,dimgray:6908265,dimgrey:6908265,dodgerblue:2003199,firebrick:11674146,floralwhite:16775920,forestgreen:2263842,fuchsia:16711935,gainsboro:14474460,ghostwhite:16316671,gold:16766720,goldenrod:14329120,gray:8421504,green:32768,greenyellow:11403055,grey:8421504,honeydew:15794160,hotpink:16738740,indianred:13458524,indigo:4915330,ivory:16777200,khaki:15787660,lavender:15132410,lavenderblush:16773365,lawngreen:8190976,lemonchiffon:16775885,lightblue:11393254,lightcoral:15761536,lightcyan:14745599,lightgoldenrodyellow:16448210,lightgray:13882323,lightgreen:9498256,lightgrey:13882323,lightpink:16758465,lightsalmon:16752762,lightseagreen:2142890,lightskyblue:8900346,lightslategray:7833753,lightslategrey:7833753,lightsteelblue:11584734,lightyellow:16777184,lime:65280,limegreen:3329330,linen:16445670,magenta:16711935,maroon:8388608,mediumaquamarine:6737322,mediumblue:205,mediumorchid:12211667,mediumpurple:9662683,mediumseagreen:3978097,mediumslateblue:8087790,mediumspringgreen:64154,mediumturquoise:4772300,mediumvioletred:13047173,midnightblue:1644912,mintcream:16121850,mistyrose:16770273,moccasin:16770229,navajowhite:16768685,navy:128,oldlace:16643558,olive:8421376,olivedrab:7048739,orange:16753920,orangered:16729344,orchid:14315734,palegoldenrod:15657130,palegreen:10025880,paleturquoise:11529966,palevioletred:14381203,papayawhip:16773077,peachpuff:16767673,peru:13468991,pink:16761035,plum:14524637,powderblue:11591910,purple:8388736,rebeccapurple:6697881,red:16711680,rosybrown:12357519,royalblue:4286945,saddlebrown:9127187,salmon:16416882,sandybrown:16032864,seagreen:3050327,seashell:16774638,sienna:10506797,silver:12632256,skyblue:8900331,slateblue:6970061,slategray:7372944,slategrey:7372944,snow:16775930,springgreen:65407,steelblue:4620980,tan:13808780,teal:32896,thistle:14204888,tomato:16737095,turquoise:4251856,violet:15631086,wheat:16113331,white:16777215,whitesmoke:16119285,yellow:16776960,yellowgreen:10145074};function on(){return this.rgb().formatHex()}function an(){return this.rgb().formatRgb()}function un(t){var n,e;return t=(t+"").trim().toLowerCase(),(n=Zt.exec(t))?(e=n[1].length,n=parseInt(n[1],16),6===e?sn(n):3===e?new hn(n>>8&15|n>>4&240,n>>4&15|240&n,(15&n)<<4|15&n,1):8===e?ln(n>>24&255,n>>16&255,n>>8&255,(255&n)/255):4===e?ln(n>>12&15|n>>8&240,n>>8&15|n>>4&240,n>>4&15|240&n,((15&n)<<4|15&n)/255):null):(n=Qt.exec(t))?new hn(n[1],n[2],n[3],1):(n=Kt.exec(t))?new hn(255*n[1]/100,255*n[2]/100,255*n[3]/100,1):(n=Jt.exec(t))?ln(n[1],n[2],n[3],n[4]):(n=tn.exec(t))?ln(255*n[1]/100,255*n[2]/100,255*n[3]/100,n[4]):(n=nn.exec(t))?vn(n[1],n[2]/100,n[3]/100,1):(n=en.exec(t))?vn(n[1],n[2]/100,n[3]/100,n[4]):rn.hasOwnProperty(t)?sn(rn[t]):"transparent"===t?new hn(NaN,NaN,NaN,0):null}function sn(t){return new hn(t>>16&255,t>>8&255,255&t,1)}function ln(t,n,e,r){return r<=0&&(t=n=e=NaN),new hn(t,n,e,r)}function cn(t,n,e,r){return 1===arguments.length?((i=t)instanceof Ht||(i=un(i)),i?new hn((i=i.rgb()).r,i.g,i.b,i.opacity):new hn):new hn(t,n,e,null==r?1:r);var i}function hn(t,n,e,r){this.r=+t,this.g=+n,this.b=+e,this.opacity=+r}function fn(){return`#${yn(this.r)}${yn(this.g)}${yn(this.b)}`}function dn(){const t=pn(this.opacity);return`${1===t?"rgb(":"rgba("}${gn(this.r)}, ${gn(this.g)}, ${gn(this.b)}${1===t?")":`, ${t})`}`}function pn(t){return isNaN(t)?1:Math.max(0,Math.min(1,t))}function gn(t){return Math.max(0,Math.min(255,Math.round(t)||0))}function yn(t){return((t=gn(t))<16?"0":"")+t.toString(16)}function vn(t,n,e,r){return r<=0?t=n=e=NaN:e<=0||e>=1?t=n=NaN:n<=0&&(t=NaN),new mn(t,n,e,r)}function _n(t){if(t instanceof mn)return new mn(t.h,t.s,t.l,t.opacity);if(t instanceof Ht||(t=un(t)),!t)return new mn;if(t instanceof mn)return t;var n=(t=t.rgb()).r/255,e=t.g/255,r=t.b/255,i=Math.min(n,e,r),o=Math.max(n,e,r),a=NaN,u=o-i,s=(o+i)/2;return u?(a=n===o?(e-r)/u+6*(e0&&s<1?0:a,new mn(a,u,s,t.opacity)}function mn(t,n,e,r){this.h=+t,this.s=+n,this.l=+e,this.opacity=+r}function xn(t){return(t=(t||0)%360)<0?t+360:t}function bn(t){return Math.max(0,Math.min(1,t||0))}function wn(t,n,e){return 255*(t<60?n+(e-n)*t/60:t<180?e:t<240?n+(e-n)*(240-t)/60:n)}Bt(Ht,un,{copy(t){return Object.assign(new this.constructor,this,t)},displayable(){return this.rgb().displayable()},hex:on,formatHex:on,formatHex8:function(){return this.rgb().formatHex8()},formatHsl:function(){return _n(this).formatHsl()},formatRgb:an,toString:an}),Bt(hn,cn,$t(Ht,{brighter(t){return t=null==t?Xt:Math.pow(Xt,t),new hn(this.r*t,this.g*t,this.b*t,this.opacity)},darker(t){return t=null==t?Vt:Math.pow(Vt,t),new hn(this.r*t,this.g*t,this.b*t,this.opacity)},rgb(){return this},clamp(){return new hn(gn(this.r),gn(this.g),gn(this.b),pn(this.opacity))},displayable(){return-.5<=this.r&&this.r<255.5&&-.5<=this.g&&this.g<255.5&&-.5<=this.b&&this.b<255.5&&0<=this.opacity&&this.opacity<=1},hex:fn,formatHex:fn,formatHex8:function(){return`#${yn(this.r)}${yn(this.g)}${yn(this.b)}${yn(255*(isNaN(this.opacity)?1:this.opacity))}`},formatRgb:dn,toString:dn})),Bt(mn,(function(t,n,e,r){return 1===arguments.length?_n(t):new mn(t,n,e,null==r?1:r)}),$t(Ht,{brighter(t){return t=null==t?Xt:Math.pow(Xt,t),new mn(this.h,this.s,this.l*t,this.opacity)},darker(t){return t=null==t?Vt:Math.pow(Vt,t),new mn(this.h,this.s,this.l*t,this.opacity)},rgb(){var t=this.h%360+360*(this.h<0),n=isNaN(t)||isNaN(this.s)?0:this.s,e=this.l,r=e+(e<.5?e:1-e)*n,i=2*e-r;return new hn(wn(t>=240?t-240:t+120,i,r),wn(t,i,r),wn(t<120?t+240:t-120,i,r),this.opacity)},clamp(){return new mn(xn(this.h),bn(this.s),bn(this.l),pn(this.opacity))},displayable(){return(0<=this.s&&this.s<=1||isNaN(this.s))&&0<=this.l&&this.l<=1&&0<=this.opacity&&this.opacity<=1},formatHsl(){const t=pn(this.opacity);return`${1===t?"hsl(":"hsla("}${xn(this.h)}, ${100*bn(this.s)}%, ${100*bn(this.l)}%${1===t?")":`, ${t})`}`}}));var kn=t=>()=>t;function Mn(t){return 1==(t=+t)?zn:function(n,e){return e-n?function(t,n,e){return t=Math.pow(t,e),n=Math.pow(n,e)-t,e=1/e,function(r){return Math.pow(t+r*n,e)}}(n,e,t):kn(isNaN(n)?e:n)}}function zn(t,n){var e=n-t;return e?function(t,n){return function(e){return t+e*n}}(t,e):kn(isNaN(t)?n:t)}var An=function t(n){var e=Mn(n);function r(t,n){var r=e((t=cn(t)).r,(n=cn(n)).r),i=e(t.g,n.g),o=e(t.b,n.b),a=zn(t.opacity,n.opacity);return function(n){return t.r=r(n),t.g=i(n),t.b=o(n),t.opacity=a(n),t+""}}return r.gamma=t,r}(1);function Sn(t,n){return t=+t,n=+n,function(e){return t*(1-e)+n*e}}var Cn=/[-+]?(?:\d+\.?\d*|\.?\d+)(?:[eE][-+]?\d+)?/g,En=new RegExp(Cn.source,"g");function On(t,n){var e,r,i,o=Cn.lastIndex=En.lastIndex=0,a=-1,u=[],s=[];for(t+="",n+="";(e=Cn.exec(t))&&(r=En.exec(n));)(i=r.index)>o&&(i=n.slice(o,i),u[a]?u[a]+=i:u[++a]=i),(e=e[0])===(r=r[0])?u[a]?u[a]+=r:u[++a]=r:(u[++a]=null,s.push({i:a,x:Sn(e,r)})),o=En.lastIndex;return o180?n+=360:n-t>180&&(t+=360),o.push({i:e.push(i(e)+"rotate(",null,r)-2,x:Sn(t,n)})):n&&e.push(i(e)+"rotate("+n+r)}(o.rotate,a.rotate,u,s),function(t,n,e,o){t!==n?o.push({i:e.push(i(e)+"skewX(",null,r)-2,x:Sn(t,n)}):n&&e.push(i(e)+"skewX("+n+r)}(o.skewX,a.skewX,u,s),function(t,n,e,r,o,a){if(t!==e||n!==r){var u=o.push(i(o)+"scale(",null,",",null,")");a.push({i:u-4,x:Sn(t,e)},{i:u-2,x:Sn(n,r)})}else 1===e&&1===r||o.push(i(o)+"scale("+e+","+r+")")}(o.scaleX,o.scaleY,a.scaleX,a.scaleY,u,s),o=a=null,function(t){for(var n,e=-1,r=s.length;++e=0&&n._call.call(void 0,t),n=n._next;--Bn}()}finally{Bn=0,function(){var t,n,e=Fn,r=1/0;for(;e;)e._call?(r>e._time&&(r=e._time),t=e,e=e._next):(n=e._next,e._next=null,e=t?t._next=n:Fn=n);Ln=t,re(r)}(),Gn=0}}function ee(){var t=Wn.now(),n=t-Xn;n>Vn&&(Yn-=n,Xn=t)}function re(t){Bn||($n&&($n=clearTimeout($n)),t-Gn>24?(t<1/0&&($n=setTimeout(ne,t-Wn.now()-Yn)),Hn&&(Hn=clearInterval(Hn))):(Hn||(Xn=Wn.now(),Hn=setInterval(ee,Vn)),Bn=1,Zn(ne)))}function ie(t,n,e){var r=new Jn;return n=null==n?0:+n,r.restart((e=>{r.stop(),t(e+n)}),n,e),r}Jn.prototype=te.prototype={constructor:Jn,restart:function(t,n,e){if("function"!=typeof t)throw new TypeError("callback is not a function");e=(null==e?Qn():+e)+(null==n?0:+n),this._next||Ln===this||(Ln?Ln._next=this:Fn=this,Ln=this),this._call=t,this._time=e,re()},stop:function(){this._call&&(this._call=null,this._time=1/0,re())}};var oe=At("start","end","cancel","interrupt"),ae=[],ue=0,se=1,le=2,ce=3,he=4,fe=5,de=6;function pe(t,n,e,r,i,o){var a=t.__transition;if(a){if(e in a)return}else t.__transition={};!function(t,n,e){var r,i=t.__transition;function o(t){e.state=se,e.timer.restart(a,e.delay,e.time),e.delay<=t&&a(t-e.delay)}function a(o){var l,c,h,f;if(e.state!==se)return s();for(l in i)if((f=i[l]).name===e.name){if(f.state===ce)return ie(a);f.state===he?(f.state=de,f.timer.stop(),f.on.call("interrupt",t,t.__data__,f.index,f.group),delete i[l]):+lue)throw new Error("too late; already scheduled");return e}function ye(t,n){var e=ve(t,n);if(e.state>ce)throw new Error("too late; already running");return e}function ve(t,n){var e=t.__transition;if(!e||!(e=e[n]))throw new Error("transition not found");return e}function _e(t,n){var e,r,i,o=t.__transition,a=!0;if(o){for(i in n=null==n?null:n+"",o)(e=o[i]).name===n?(r=e.state>le&&e.state=0&&(t=t.slice(0,n)),!t||"start"===t}))}(n)?ge:ye;return function(){var a=o(this,t),u=a.on;u!==r&&(i=(r=u).copy()).on(n,e),a.on=i}}(e,t,n))},attr:function(t,n){var e=d(t),r="transform"===e?In:we;return this.attrTween(t,"function"==typeof n?(e.local?Ce:Se)(e,r,be(this,"attr."+t,n)):null==n?(e.local?Me:ke)(e):(e.local?Ae:ze)(e,r,n))},attrTween:function(t,n){var e="attr."+t;if(arguments.length<2)return(e=this.tween(e))&&e._value;if(null==n)return this.tween(e,null);if("function"!=typeof n)throw new Error;var r=d(t);return this.tween(e,(r.local?Ee:Oe)(r,n))},style:function(t,n,e){var r="transform"==(t+="")?Dn:we;return null==n?this.styleTween(t,function(t,n){var e,r,i;return function(){var o=V(this,t),a=(this.style.removeProperty(t),V(this,t));return o===a?null:o===e&&a===r?i:i=n(e=o,r=a)}}(t,r)).on("end.style."+t,De(t)):"function"==typeof n?this.styleTween(t,function(t,n,e){var r,i,o;return function(){var a=V(this,t),u=e(this),s=u+"";return null==u&&(this.style.removeProperty(t),s=u=V(this,t)),a===s?null:a===r&&s===i?o:(i=s,o=n(r=a,u))}}(t,r,be(this,"style."+t,n))).each(function(t,n){var e,r,i,o,a="style."+n,u="end."+a;return function(){var s=ye(this,t),l=s.on,c=null==s.value[a]?o||(o=De(n)):void 0;l===e&&i===c||(r=(e=l).copy()).on(u,i=c),s.on=r}}(this._id,t)):this.styleTween(t,function(t,n,e){var r,i,o=e+"";return function(){var a=V(this,t);return a===o?null:a===r?i:i=n(r=a,e)}}(t,r,n),e).on("end.style."+t,null)},styleTween:function(t,n,e){var r="style."+(t+="");if(arguments.length<2)return(r=this.tween(r))&&r._value;if(null==n)return this.tween(r,null);if("function"!=typeof n)throw new Error;return this.tween(r,function(t,n,e){var r,i;function o(){var o=n.apply(this,arguments);return o!==i&&(r=(i=o)&&function(t,n,e){return function(r){this.style.setProperty(t,n.call(this,r),e)}}(t,o,e)),r}return o._value=n,o}(t,n,null==e?"":e))},text:function(t){return this.tween("text","function"==typeof t?function(t){return function(){var n=t(this);this.textContent=null==n?"":n}}(be(this,"text",t)):function(t){return function(){this.textContent=t}}(null==t?"":t+""))},textTween:function(t){var n="text";if(arguments.length<1)return(n=this.tween(n))&&n._value;if(null==t)return this.tween(n,null);if("function"!=typeof t)throw new Error;return this.tween(n,function(t){var n,e;function r(){var r=t.apply(this,arguments);return r!==e&&(n=(e=r)&&function(t){return function(n){this.textContent=t.call(this,n)}}(r)),n}return r._value=t,r}(t))},remove:function(){return this.on("end.remove",function(t){return function(){var n=this.parentNode;for(var e in this.__transition)if(+e!==t)return;n&&n.removeChild(this)}}(this._id))},tween:function(t,n){var e=this._id;if(t+="",arguments.length<2){for(var r,i=ve(this.node(),e).tween,o=0,a=i.length;o()=>t;function He(t,{sourceEvent:n,target:e,transform:r,dispatch:i}){Object.defineProperties(this,{type:{value:t,enumerable:!0,configurable:!0},sourceEvent:{value:n,enumerable:!0,configurable:!0},target:{value:e,enumerable:!0,configurable:!0},transform:{value:r,enumerable:!0,configurable:!0},_:{value:i}})}function Ve(t,n,e){this.k=t,this.x=n,this.y=e}Ve.prototype={constructor:Ve,scale:function(t){return 1===t?this:new Ve(this.k*t,this.x,this.y)},translate:function(t,n){return 0===t&0===n?this:new Ve(this.k,this.x+this.k*t,this.y+this.k*n)},apply:function(t){return[t[0]*this.k+this.x,t[1]*this.k+this.y]},applyX:function(t){return t*this.k+this.x},applyY:function(t){return t*this.k+this.y},invert:function(t){return[(t[0]-this.x)/this.k,(t[1]-this.y)/this.k]},invertX:function(t){return(t-this.x)/this.k},invertY:function(t){return(t-this.y)/this.k},rescaleX:function(t){return t.copy().domain(t.range().map(this.invertX,this).map(t.invert,t))},rescaleY:function(t){return t.copy().domain(t.range().map(this.invertY,this).map(t.invert,t))},toString:function(){return"translate("+this.x+","+this.y+") scale("+this.k+")"}};var Xe=new Ve(1,0,0);function Ge(t){for(;!t.__zoom;)if(!(t=t.parentNode))return Xe;return t.__zoom}function Ye(t){t.stopImmediatePropagation()}function We(t){t.preventDefault(),t.stopImmediatePropagation()}function Ze(t){return!(t.ctrlKey&&"wheel"!==t.type||t.button)}function Qe(){var t=this;return t instanceof SVGElement?(t=t.ownerSVGElement||t).hasAttribute("viewBox")?[[(t=t.viewBox.baseVal).x,t.y],[t.x+t.width,t.y+t.height]]:[[0,0],[t.width.baseVal.value,t.height.baseVal.value]]:[[0,0],[t.clientWidth,t.clientHeight]]}function Ke(){return this.__zoom||Xe}function Je(t){return-t.deltaY*(1===t.deltaMode?.05:t.deltaMode?1:.002)*(t.ctrlKey?10:1)}function tr(){return navigator.maxTouchPoints||"ontouchstart"in this}function nr(t,n,e){var r=t.invertX(n[0][0])-e[0][0],i=t.invertX(n[1][0])-e[1][0],o=t.invertY(n[0][1])-e[0][1],a=t.invertY(n[1][1])-e[1][1];return t.translate(i>r?(r+i)/2:Math.min(0,r)||Math.max(0,i),a>o?(o+a)/2:Math.min(0,o)||Math.max(0,a))}function er(){var t,n,e,r=Ze,i=Qe,o=nr,a=Je,u=tr,s=[0,1/0],l=[[-1/0,-1/0],[1/0,1/0]],c=250,h=qn,f=At("start","zoom","end"),d=500,p=150,g=0,y=10;function v(t){t.property("__zoom",Ke).on("wheel.zoom",M,{passive:!1}).on("mousedown.zoom",z).on("dblclick.zoom",A).filter(u).on("touchstart.zoom",S).on("touchmove.zoom",C).on("touchend.zoom touchcancel.zoom",E).style("-webkit-tap-highlight-color","rgba(0,0,0,0)")}function _(t,n){return(n=Math.max(s[0],Math.min(s[1],n)))===t.k?t:new Ve(n,t.x,t.y)}function m(t,n,e){var r=n[0]-e[0]*t.k,i=n[1]-e[1]*t.k;return r===t.x&&i===t.y?t:new Ve(t.k,r,i)}function x(t){return[(+t[0][0]+ +t[1][0])/2,(+t[0][1]+ +t[1][1])/2]}function b(t,n,e,r){t.on("start.zoom",(function(){w(this,arguments).event(r).start()})).on("interrupt.zoom end.zoom",(function(){w(this,arguments).event(r).end()})).tween("zoom",(function(){var t=this,o=arguments,a=w(t,o).event(r),u=i.apply(t,o),s=null==e?x(u):"function"==typeof e?e.apply(t,o):e,l=Math.max(u[1][0]-u[0][0],u[1][1]-u[0][1]),c=t.__zoom,f="function"==typeof n?n.apply(t,o):n,d=h(c.invert(s).concat(l/c.k),f.invert(s).concat(l/f.k));return function(t){if(1===t)t=f;else{var n=d(t),e=l/n[2];t=new Ve(e,s[0]-n[0]*e,s[1]-n[1]*e)}a.zoom(null,t)}}))}function w(t,n,e){return!e&&t.__zooming||new k(t,n)}function k(t,n){this.that=t,this.args=n,this.active=0,this.sourceEvent=null,this.extent=i.apply(t,n),this.taps=0}function M(t,...n){if(r.apply(this,arguments)){var e=w(this,n).event(t),i=this.__zoom,u=Math.max(s[0],Math.min(s[1],i.k*Math.pow(2,a.apply(this,arguments)))),c=Mt(t);if(e.wheel)e.mouse[0][0]===c[0]&&e.mouse[0][1]===c[1]||(e.mouse[1]=i.invert(e.mouse[0]=c)),clearTimeout(e.wheel);else{if(i.k===u)return;e.mouse=[c,i.invert(c)],_e(this),e.start()}We(t),e.wheel=setTimeout((function(){e.wheel=null,e.end()}),p),e.zoom("mouse",o(m(_(i,u),e.mouse[0],e.mouse[1]),e.extent,l))}}function z(t,...n){if(!e&&r.apply(this,arguments)){var i=t.currentTarget,a=w(this,n,!0).event(t),u=kt(t.view).on("mousemove.zoom",(function(t){if(We(t),!a.moved){var n=t.clientX-c,e=t.clientY-h;a.moved=n*n+e*e>g}a.event(t).zoom("mouse",o(m(a.that.__zoom,a.mouse[0]=Mt(t,i),a.mouse[1]),a.extent,l))}),!0).on("mouseup.zoom",(function(t){u.on("mousemove.zoom mouseup.zoom",null),Rt(t.view,a.moved),We(t),a.event(t).end()}),!0),s=Mt(t,i),c=t.clientX,h=t.clientY;Tt(t.view),Ye(t),a.mouse=[s,this.__zoom.invert(s)],_e(this),a.start()}}function A(t,...n){if(r.apply(this,arguments)){var e=this.__zoom,a=Mt(t.changedTouches?t.changedTouches[0]:t,this),u=e.invert(a),s=e.k*(t.shiftKey?.5:2),h=o(m(_(e,s),a,u),i.apply(this,n),l);We(t),c>0?kt(this).transition().duration(c).call(b,h,a,t):kt(this).call(v.transform,h,a,t)}}function S(e,...i){if(r.apply(this,arguments)){var o,a,u,s,l=e.touches,c=l.length,h=w(this,i,e.changedTouches.length===c).event(e);for(Ye(e),a=0;a=n)&&(e=n);else{let r=-1;for(let i of t)null!=(i=n(i,++r,t))&&(e=i)&&(e=i)}return e}function ur(t,n){let e;if(void 0===n)for(const n of t)null!=n&&(e>n||void 0===e&&n>=n)&&(e=n);else{let r=-1;for(let i of t)null!=(i=n(i,++r,t))&&(e>i||void 0===e&&i>=i)&&(e=i)}return e}var sr="object"==typeof global&&global&&global.Object===Object&&global,lr="object"==typeof self&&self&&self.Object===Object&&self,cr=sr||lr||Function("return this")(),hr=cr.Symbol,fr=Object.prototype,dr=fr.hasOwnProperty,pr=fr.toString,gr=hr?hr.toStringTag:void 0;var yr=Object.prototype.toString;var vr="[object Null]",_r="[object Undefined]",mr=hr?hr.toStringTag:void 0;function xr(t){return null==t?void 0===t?_r:vr:mr&&mr in Object(t)?function(t){var n=dr.call(t,gr),e=t[gr];try{t[gr]=void 0;var r=!0}catch(t){}var i=pr.call(t);return r&&(n?t[gr]=e:delete t[gr]),i}(t):function(t){return yr.call(t)}(t)}var br="[object Symbol]";var wr=/\s/;var kr=/^\s+/;function Mr(t){return t?t.slice(0,function(t){for(var n=t.length;n--&&wr.test(t.charAt(n)););return n}(t)+1).replace(kr,""):t}function zr(t){var n=typeof t;return null!=t&&("object"==n||"function"==n)}var Ar=NaN,Sr=/^[-+]0x[0-9a-f]+$/i,Cr=/^0b[01]+$/i,Er=/^0o[0-7]+$/i,Or=parseInt;function Nr(t){if("number"==typeof t)return t;if(function(t){return"symbol"==typeof t||function(t){return null!=t&&"object"==typeof t}(t)&&xr(t)==br}(t))return Ar;if(zr(t)){var n="function"==typeof t.valueOf?t.valueOf():t;t=zr(n)?n+"":n}if("string"!=typeof t)return 0===t?t:+t;t=Mr(t);var e=Cr.test(t);return e||Er.test(t)?Or(t.slice(2),e?2:8):Sr.test(t)?Ar:+t}var Pr=function(){return cr.Date.now()},jr="Expected a function",Tr=Math.max,Rr=Math.min;function Dr(t,n,e){var r,i,o,a,u,s,l=0,c=!1,h=!1,f=!0;if("function"!=typeof t)throw new TypeError(jr);function d(n){var e=r,o=i;return r=i=void 0,l=n,a=t.apply(o,e)}function p(t){var e=t-s;return void 0===s||e>=n||e<0||h&&t-l>=o}function g(){var t=Pr();if(p(t))return y(t);u=setTimeout(g,function(t){var e=n-(t-s);return h?Rr(e,o-(t-l)):e}(t))}function y(t){return u=void 0,f&&r?d(t):(r=i=void 0,a)}function v(){var t=Pr(),e=p(t);if(r=arguments,i=this,s=t,e){if(void 0===u)return function(t){return l=t,u=setTimeout(g,n),c?d(t):a}(s);if(h)return clearTimeout(u),u=setTimeout(g,n),d(s)}return void 0===u&&(u=setTimeout(g,n)),a}return n=Nr(n)||0,zr(e)&&(c=!!e.leading,o=(h="maxWait"in e)?Tr(Nr(e.maxWait)||0,n):o,f="trailing"in e?!!e.trailing:f),v.cancel=function(){void 0!==u&&clearTimeout(u),l=0,r=s=i=u=void 0},v.flush=function(){return void 0===u?a:y(Pr())},v}var Ir=Object.freeze({Linear:Object.freeze({None:function(t){return t},In:function(t){return this.None(t)},Out:function(t){return this.None(t)},InOut:function(t){return this.None(t)}}),Quadratic:Object.freeze({In:function(t){return t*t},Out:function(t){return t*(2-t)},InOut:function(t){return(t*=2)<1?.5*t*t:-.5*(--t*(t-2)-1)}}),Cubic:Object.freeze({In:function(t){return t*t*t},Out:function(t){return--t*t*t+1},InOut:function(t){return(t*=2)<1?.5*t*t*t:.5*((t-=2)*t*t+2)}}),Quartic:Object.freeze({In:function(t){return t*t*t*t},Out:function(t){return 1- --t*t*t*t},InOut:function(t){return(t*=2)<1?.5*t*t*t*t:-.5*((t-=2)*t*t*t-2)}}),Quintic:Object.freeze({In:function(t){return t*t*t*t*t},Out:function(t){return--t*t*t*t*t+1},InOut:function(t){return(t*=2)<1?.5*t*t*t*t*t:.5*((t-=2)*t*t*t*t+2)}}),Sinusoidal:Object.freeze({In:function(t){return 1-Math.sin((1-t)*Math.PI/2)},Out:function(t){return Math.sin(t*Math.PI/2)},InOut:function(t){return.5*(1-Math.sin(Math.PI*(.5-t)))}}),Exponential:Object.freeze({In:function(t){return 0===t?0:Math.pow(1024,t-1)},Out:function(t){return 1===t?1:1-Math.pow(2,-10*t)},InOut:function(t){return 0===t?0:1===t?1:(t*=2)<1?.5*Math.pow(1024,t-1):.5*(2-Math.pow(2,-10*(t-1)))}}),Circular:Object.freeze({In:function(t){return 1-Math.sqrt(1-t*t)},Out:function(t){return Math.sqrt(1- --t*t)},InOut:function(t){return(t*=2)<1?-.5*(Math.sqrt(1-t*t)-1):.5*(Math.sqrt(1-(t-=2)*t)+1)}}),Elastic:Object.freeze({In:function(t){return 0===t?0:1===t?1:-Math.pow(2,10*(t-1))*Math.sin(5*(t-1.1)*Math.PI)},Out:function(t){return 0===t?0:1===t?1:Math.pow(2,-10*t)*Math.sin(5*(t-.1)*Math.PI)+1},InOut:function(t){return 0===t?0:1===t?1:(t*=2)<1?-.5*Math.pow(2,10*(t-1))*Math.sin(5*(t-1.1)*Math.PI):.5*Math.pow(2,-10*(t-1))*Math.sin(5*(t-1.1)*Math.PI)+1}}),Back:Object.freeze({In:function(t){var n=1.70158;return 1===t?1:t*t*((n+1)*t-n)},Out:function(t){var n=1.70158;return 0===t?0:--t*t*((n+1)*t+n)+1},InOut:function(t){var n=2.5949095;return(t*=2)<1?t*t*((n+1)*t-n)*.5:.5*((t-=2)*t*((n+1)*t+n)+2)}}),Bounce:Object.freeze({In:function(t){return 1-Ir.Bounce.Out(1-t)},Out:function(t){return t<1/2.75?7.5625*t*t:t<2/2.75?7.5625*(t-=1.5/2.75)*t+.75:t<2.5/2.75?7.5625*(t-=2.25/2.75)*t+.9375:7.5625*(t-=2.625/2.75)*t+.984375},InOut:function(t){return t<.5?.5*Ir.Bounce.In(2*t):.5*Ir.Bounce.Out(2*t-1)+.5}}),generatePow:function(t){return void 0===t&&(t=4),t=(t=t1e4?1e4:t,{In:function(n){return Math.pow(n,t)},Out:function(n){return 1-Math.pow(1-n,t)},InOut:function(n){return n<.5?Math.pow(2*n,t)/2:(1-Math.pow(2-2*n,t))/2+.5}}}}),Ur=function(){return performance.now()},Fr=function(){function t(){this._tweens={},this._tweensAddedDuringUpdate={}}return t.prototype.getAll=function(){var t=this;return Object.keys(this._tweens).map((function(n){return t._tweens[n]}))},t.prototype.removeAll=function(){this._tweens={}},t.prototype.add=function(t){this._tweens[t.getId()]=t,this._tweensAddedDuringUpdate[t.getId()]=t},t.prototype.remove=function(t){delete this._tweens[t.getId()],delete this._tweensAddedDuringUpdate[t.getId()]},t.prototype.update=function(t,n){void 0===t&&(t=Ur()),void 0===n&&(n=!1);var e=Object.keys(this._tweens);if(0===e.length)return!1;for(;e.length>0;){this._tweensAddedDuringUpdate={};for(var r=0;r1?o(t[e],t[e-1],e-r):o(t[i],t[i+1>e?e:i+1],r-i)},Bezier:function(t,n){for(var e=0,r=t.length-1,i=Math.pow,o=Lr.Utils.Bernstein,a=0;a<=r;a++)e+=i(1-n,r-a)*i(n,a)*t[a]*o(r,a);return e},CatmullRom:function(t,n){var e=t.length-1,r=e*n,i=Math.floor(r),o=Lr.Utils.CatmullRom;return t[0]===t[e]?(n<0&&(i=Math.floor(r=e*(1+n))),o(t[(i-1+e)%e],t[i],t[(i+1)%e],t[(i+2)%e],r-i)):n<0?t[0]-(o(t[0],t[0],t[1],t[1],-r)-t[0]):n>1?t[e]-(o(t[e],t[e],t[e-1],t[e-1],r-e)-t[e]):o(t[i?i-1:0],t[i],t[e1;r--)e*=r;return t[n]=e,e}}(),CatmullRom:function(t,n,e,r,i){var o=.5*(e-t),a=.5*(r-n),u=i*i;return(2*n-2*e+o+a)*(i*u)+(-3*n+3*e-2*o-a)*u+o*i+n}}},qr=function(){function t(){}return t.nextId=function(){return t._nextId++},t._nextId=0,t}(),Br=new Fr,$r=function(){function t(t,n){void 0===n&&(n=Br),this._object=t,this._group=n,this._isPaused=!1,this._pauseStart=0,this._valuesStart={},this._valuesEnd={},this._valuesStartRepeat={},this._duration=1e3,this._isDynamic=!1,this._initialRepeat=0,this._repeat=0,this._yoyo=!1,this._isPlaying=!1,this._reversed=!1,this._delayTime=0,this._startTime=0,this._easingFunction=Ir.Linear.None,this._interpolationFunction=Lr.Linear,this._chainedTweens=[],this._onStartCallbackFired=!1,this._onEveryStartCallbackFired=!1,this._id=qr.nextId(),this._isChainStopped=!1,this._propertiesAreSetUp=!1,this._goToEnd=!1}return t.prototype.getId=function(){return this._id},t.prototype.isPlaying=function(){return this._isPlaying},t.prototype.isPaused=function(){return this._isPaused},t.prototype.to=function(t,n){if(void 0===n&&(n=1e3),this._isPlaying)throw new Error("Can not call Tween.to() while Tween is already started or paused. Stop the Tween first.");return this._valuesEnd=t,this._propertiesAreSetUp=!1,this._duration=n,this},t.prototype.duration=function(t){return void 0===t&&(t=1e3),this._duration=t,this},t.prototype.dynamic=function(t){return void 0===t&&(t=!1),this._isDynamic=t,this},t.prototype.start=function(t,n){if(void 0===t&&(t=Ur()),void 0===n&&(n=!1),this._isPlaying)return this;if(this._group&&this._group.add(this),this._repeat=this._initialRepeat,this._reversed)for(var e in this._reversed=!1,this._valuesStartRepeat)this._swapEndStartRepeatValues(e),this._valuesStart[e]=this._valuesStartRepeat[e];if(this._isPlaying=!0,this._isPaused=!1,this._onStartCallbackFired=!1,this._onEveryStartCallbackFired=!1,this._isChainStopped=!1,this._startTime=t,this._startTime+=this._delayTime,!this._propertiesAreSetUp||n){if(this._propertiesAreSetUp=!0,!this._isDynamic){var r={};for(var i in this._valuesEnd)r[i]=this._valuesEnd[i];this._valuesEnd=r}this._setupProperties(this._object,this._valuesStart,this._valuesEnd,this._valuesStartRepeat,n)}return this},t.prototype.startFromCurrentValues=function(t){return this.start(t,!0)},t.prototype._setupProperties=function(t,n,e,r,i){for(var o in e){var a=t[o],u=Array.isArray(a),s=u?"array":typeof a,l=!u&&Array.isArray(e[o]);if("undefined"!==s&&"function"!==s){if(l){if(0===(y=e[o]).length)continue;for(var c=[a],h=0,f=y.length;hi)return!1;n&&this.start(t,!0)}if(this._goToEnd=!1,t1?1:r;var o=this._easingFunction(r);if(this._updateProperties(this._object,this._valuesStart,this._valuesEnd,o),this._onUpdateCallback&&this._onUpdateCallback(this._object,r),1===r){if(this._repeat>0){for(e in isFinite(this._repeat)&&this._repeat--,this._valuesStartRepeat)this._yoyo||"string"!=typeof this._valuesEnd[e]||(this._valuesStartRepeat[e]=this._valuesStartRepeat[e]+parseFloat(this._valuesEnd[e])),this._yoyo&&this._swapEndStartRepeatValues(e),this._valuesStart[e]=this._valuesStartRepeat[e];return this._yoyo&&(this._reversed=!this._reversed),void 0!==this._repeatDelayTime?this._startTime=t+this._repeatDelayTime:this._startTime=t+this._delayTime,this._onRepeatCallback&&this._onRepeatCallback(this._object),this._onEveryStartCallbackFired=!1,!0}this._onCompleteCallback&&this._onCompleteCallback(this._object);for(var a=0,u=this._chainedTweens.length;at.length)&&(n=t.length);for(var e=0,r=new Array(n);e0&&void 0!==arguments[0]?arguments[0]:{},n=Object.assign({},e instanceof Function?e(t):e,{initialised:!1}),r={};function i(n){return o(n,t),u(),i}var o=function(t,e){c.call(i,t,n,e),n.initialised=!0},u=Dr((function(){n.initialised&&(f.call(i,n,r),r={})}),1);return d.forEach((function(t){i[t.name]=function(t){var e=t.name,o=t.triggerUpdate,a=void 0!==o&&o,s=t.onChange,l=void 0===s?function(t,n){}:s,c=t.defaultVal,h=void 0===c?null:c;return function(t){var o=n[e];if(!arguments.length)return o;var s=void 0===t?h:t;return n[e]=s,l.call(i,s,n,o),!r.hasOwnProperty(e)&&(r[e]=o),a&&u(),i}}(t)})),Object.keys(a).forEach((function(t){i[t]=function(){for(var e,r=arguments.length,o=new Array(r),u=0;u1&&(e-=1),e<1/6?t+6*(n-t)*e:e<.5?n:e<2/3?t+(n-t)*(2/3-e)*6:t}if(t=wi(t,360),n=wi(n,100),e=wi(e,100),0===n)r=i=o=e;else{var u=e<.5?e*(1+n):e+n-e*n,s=2*e-u;r=a(s,u,t+1/3),i=a(s,u,t),o=a(s,u,t-1/3)}return{r:255*r,g:255*i,b:255*o}}(t.h,r,o),a=!0,u="hsl"),t.hasOwnProperty("a")&&(e=t.a));var s,l,c;return e=bi(e),{ok:a,format:t.format||u,r:Math.min(255,Math.max(n.r,0)),g:Math.min(255,Math.max(n.g,0)),b:Math.min(255,Math.max(n.b,0)),a:e}}(t);this._originalInput=t,this._r=e.r,this._g=e.g,this._b=e.b,this._a=e.a,this._roundA=Math.round(100*this._a)/100,this._format=n.format||e.format,this._gradientType=n.gradientType,this._r<1&&(this._r=Math.round(this._r)),this._g<1&&(this._g=Math.round(this._g)),this._b<1&&(this._b=Math.round(this._b)),this._ok=e.ok}function ri(t,n,e){t=wi(t,255),n=wi(n,255),e=wi(e,255);var r,i,o=Math.max(t,n,e),a=Math.min(t,n,e),u=(o+a)/2;if(o==a)r=i=0;else{var s=o-a;switch(i=u>.5?s/(2-o-a):s/(o+a),o){case t:r=(n-e)/s+(n>1)+720)%360;--n;)r.h=(r.h+i)%360,o.push(ei(r));return o}function _i(t,n){n=n||6;for(var e=ei(t).toHsv(),r=e.h,i=e.s,o=e.v,a=[],u=1/n;n--;)a.push(ei({h:r,s:i,v:o})),o=(o+u)%1;return a}ei.prototype={isDark:function(){return this.getBrightness()<128},isLight:function(){return!this.isDark()},isValid:function(){return this._ok},getOriginalInput:function(){return this._originalInput},getFormat:function(){return this._format},getAlpha:function(){return this._a},getBrightness:function(){var t=this.toRgb();return(299*t.r+587*t.g+114*t.b)/1e3},getLuminance:function(){var t,n,e,r=this.toRgb();return t=r.r/255,n=r.g/255,e=r.b/255,.2126*(t<=.03928?t/12.92:Math.pow((t+.055)/1.055,2.4))+.7152*(n<=.03928?n/12.92:Math.pow((n+.055)/1.055,2.4))+.0722*(e<=.03928?e/12.92:Math.pow((e+.055)/1.055,2.4))},setAlpha:function(t){return this._a=bi(t),this._roundA=Math.round(100*this._a)/100,this},toHsv:function(){var t=ii(this._r,this._g,this._b);return{h:360*t.h,s:t.s,v:t.v,a:this._a}},toHsvString:function(){var t=ii(this._r,this._g,this._b),n=Math.round(360*t.h),e=Math.round(100*t.s),r=Math.round(100*t.v);return 1==this._a?"hsv("+n+", "+e+"%, "+r+"%)":"hsva("+n+", "+e+"%, "+r+"%, "+this._roundA+")"},toHsl:function(){var t=ri(this._r,this._g,this._b);return{h:360*t.h,s:t.s,l:t.l,a:this._a}},toHslString:function(){var t=ri(this._r,this._g,this._b),n=Math.round(360*t.h),e=Math.round(100*t.s),r=Math.round(100*t.l);return 1==this._a?"hsl("+n+", "+e+"%, "+r+"%)":"hsla("+n+", "+e+"%, "+r+"%, "+this._roundA+")"},toHex:function(t){return oi(this._r,this._g,this._b,t)},toHexString:function(t){return"#"+this.toHex(t)},toHex8:function(t){return function(t,n,e,r,i){var o=[zi(Math.round(t).toString(16)),zi(Math.round(n).toString(16)),zi(Math.round(e).toString(16)),zi(Si(r))];if(i&&o[0].charAt(0)==o[0].charAt(1)&&o[1].charAt(0)==o[1].charAt(1)&&o[2].charAt(0)==o[2].charAt(1)&&o[3].charAt(0)==o[3].charAt(1))return o[0].charAt(0)+o[1].charAt(0)+o[2].charAt(0)+o[3].charAt(0);return o.join("")}(this._r,this._g,this._b,this._a,t)},toHex8String:function(t){return"#"+this.toHex8(t)},toRgb:function(){return{r:Math.round(this._r),g:Math.round(this._g),b:Math.round(this._b),a:this._a}},toRgbString:function(){return 1==this._a?"rgb("+Math.round(this._r)+", "+Math.round(this._g)+", "+Math.round(this._b)+")":"rgba("+Math.round(this._r)+", "+Math.round(this._g)+", "+Math.round(this._b)+", "+this._roundA+")"},toPercentageRgb:function(){return{r:Math.round(100*wi(this._r,255))+"%",g:Math.round(100*wi(this._g,255))+"%",b:Math.round(100*wi(this._b,255))+"%",a:this._a}},toPercentageRgbString:function(){return 1==this._a?"rgb("+Math.round(100*wi(this._r,255))+"%, "+Math.round(100*wi(this._g,255))+"%, "+Math.round(100*wi(this._b,255))+"%)":"rgba("+Math.round(100*wi(this._r,255))+"%, "+Math.round(100*wi(this._g,255))+"%, "+Math.round(100*wi(this._b,255))+"%, "+this._roundA+")"},toName:function(){return 0===this._a?"transparent":!(this._a<1)&&(xi[oi(this._r,this._g,this._b,!0)]||!1)},toFilter:function(t){var n="#"+ai(this._r,this._g,this._b,this._a),e=n,r=this._gradientType?"GradientType = 1, ":"";if(t){var i=ei(t);e="#"+ai(i._r,i._g,i._b,i._a)}return"progid:DXImageTransform.Microsoft.gradient("+r+"startColorstr="+n+",endColorstr="+e+")"},toString:function(t){var n=!!t;t=t||this._format;var e=!1,r=this._a<1&&this._a>=0;return n||!r||"hex"!==t&&"hex6"!==t&&"hex3"!==t&&"hex4"!==t&&"hex8"!==t&&"name"!==t?("rgb"===t&&(e=this.toRgbString()),"prgb"===t&&(e=this.toPercentageRgbString()),"hex"!==t&&"hex6"!==t||(e=this.toHexString()),"hex3"===t&&(e=this.toHexString(!0)),"hex4"===t&&(e=this.toHex8String(!0)),"hex8"===t&&(e=this.toHex8String()),"name"===t&&(e=this.toName()),"hsl"===t&&(e=this.toHslString()),"hsv"===t&&(e=this.toHsvString()),e||this.toHexString()):"name"===t&&0===this._a?this.toName():this.toRgbString()},clone:function(){return ei(this.toString())},_applyModification:function(t,n){var e=t.apply(null,[this].concat([].slice.call(n)));return this._r=e._r,this._g=e._g,this._b=e._b,this.setAlpha(e._a),this},lighten:function(){return this._applyModification(ci,arguments)},brighten:function(){return this._applyModification(hi,arguments)},darken:function(){return this._applyModification(fi,arguments)},desaturate:function(){return this._applyModification(ui,arguments)},saturate:function(){return this._applyModification(si,arguments)},greyscale:function(){return this._applyModification(li,arguments)},spin:function(){return this._applyModification(di,arguments)},_applyCombination:function(t,n){return t.apply(null,[this].concat([].slice.call(n)))},analogous:function(){return this._applyCombination(vi,arguments)},complement:function(){return this._applyCombination(pi,arguments)},monochromatic:function(){return this._applyCombination(_i,arguments)},splitcomplement:function(){return this._applyCombination(yi,arguments)},triad:function(){return this._applyCombination(gi,[3])},tetrad:function(){return this._applyCombination(gi,[4])}},ei.fromRatio=function(t,n){if("object"==Jr(t)){var e={};for(var r in t)t.hasOwnProperty(r)&&(e[r]="a"===r?t[r]:Ai(t[r]));t=e}return ei(t,n)},ei.equals=function(t,n){return!(!t||!n)&&ei(t).toRgbString()==ei(n).toRgbString()},ei.random=function(){return ei.fromRatio({r:Math.random(),g:Math.random(),b:Math.random()})},ei.mix=function(t,n,e){e=0===e?0:e||50;var r=ei(t).toRgb(),i=ei(n).toRgb(),o=e/100;return ei({r:(i.r-r.r)*o+r.r,g:(i.g-r.g)*o+r.g,b:(i.b-r.b)*o+r.b,a:(i.a-r.a)*o+r.a})}, +// =4.5;break;case"AAlarge":i=o>=3;break;case"AAAsmall":i=o>=7}return i},ei.mostReadable=function(t,n,e){var r,i,o,a,u=null,s=0;i=(e=e||{}).includeFallbackColors,o=e.level,a=e.size;for(var l=0;ls&&(s=r,u=ei(n[l]));return ei.isReadable(t,u,{level:o,size:a})||!i?u:(e.includeFallbackColors=!1,ei.mostReadable(t,["#fff","#000"],e))};var mi=ei.names={aliceblue:"f0f8ff",antiquewhite:"faebd7",aqua:"0ff",aquamarine:"7fffd4",azure:"f0ffff",beige:"f5f5dc",bisque:"ffe4c4",black:"000",blanchedalmond:"ffebcd",blue:"00f",blueviolet:"8a2be2",brown:"a52a2a",burlywood:"deb887",burntsienna:"ea7e5d",cadetblue:"5f9ea0",chartreuse:"7fff00",chocolate:"d2691e",coral:"ff7f50",cornflowerblue:"6495ed",cornsilk:"fff8dc",crimson:"dc143c",cyan:"0ff",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:"f0f",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:"789",lightslategrey:"789",lightsteelblue:"b0c4de",lightyellow:"ffffe0",lime:"0f0",limegreen:"32cd32",linen:"faf0e6",magenta:"f0f",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:"f00",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:"fff",whitesmoke:"f5f5f5",yellow:"ff0",yellowgreen:"9acd32"},xi=ei.hexNames=function(t){var n={};for(var e in t)t.hasOwnProperty(e)&&(n[t[e]]=e);return n}(mi);function bi(t){return t=parseFloat(t),(isNaN(t)||t<0||t>1)&&(t=1),t}function wi(t,n){(function(t){return"string"==typeof t&&-1!=t.indexOf(".")&&1===parseFloat(t)})(t)&&(t="100%");var e=function(t){return"string"==typeof t&&-1!=t.indexOf("%")}(t);return t=Math.min(n,Math.max(0,parseFloat(t))),e&&(t=parseInt(t*n,10)/100),Math.abs(t-n)<1e-6?1:t%n/parseFloat(n)}function ki(t){return Math.min(1,Math.max(0,t))}function Mi(t){return parseInt(t,16)}function zi(t){return 1==t.length?"0"+t:""+t}function Ai(t){return t<=1&&(t=100*t+"%"),t}function Si(t){return Math.round(255*parseFloat(t)).toString(16)}function Ci(t){return Mi(t)/255}var Ei,Oi,Ni,Pi=(Oi="[\\s|\\(]+("+(Ei="(?:[-\\+]?\\d*\\.\\d+%?)|(?:[-\\+]?\\d+%?)")+")[,|\\s]+("+Ei+")[,|\\s]+("+Ei+")\\s*\\)?",Ni="[\\s|\\(]+("+Ei+")[,|\\s]+("+Ei+")[,|\\s]+("+Ei+")[,|\\s]+("+Ei+")\\s*\\)?",{CSS_UNIT:new RegExp(Ei),rgb:new RegExp("rgb"+Oi),rgba:new RegExp("rgba"+Ni),hsl:new RegExp("hsl"+Oi),hsla:new RegExp("hsla"+Ni),hsv:new RegExp("hsv"+Oi),hsva:new RegExp("hsva"+Ni),hex3:/^#?([0-9a-fA-F]{1})([0-9a-fA-F]{1})([0-9a-fA-F]{1})$/,hex6:/^#?([0-9a-fA-F]{2})([0-9a-fA-F]{2})([0-9a-fA-F]{2})$/,hex4:/^#?([0-9a-fA-F]{1})([0-9a-fA-F]{1})([0-9a-fA-F]{1})([0-9a-fA-F]{1})$/,hex8:/^#?([0-9a-fA-F]{2})([0-9a-fA-F]{2})([0-9a-fA-F]{2})([0-9a-fA-F]{2})$/});function ji(t){return!!Pi.CSS_UNIT.exec(t)}function Ti(t,n){for(var e=0;et.length)&&(n=t.length);for(var e=0,r=new Array(n);e0&&void 0!==arguments[0]?arguments[0]:6;!function(t,n){if(!(t instanceof n))throw new TypeError("Cannot call a class as a function")}(this,t),this.csBits=n,this.registry=["__reserved for background__"]}var n,e,r;return n=t,e=[{key:"register",value:function(t){if(this.registry.length>=Math.pow(2,24-this.csBits))return null;var n,e=this.registry.length,r=Ui(e,this.csBits),i=(n=e+(r<<24-this.csBits),"#".concat(Math.min(n,Math.pow(2,24)).toString(16).padStart(6,"0")));return this.registry.push(t),i}},{key:"lookup",value:function(t){var n,e,r,i,o="string"==typeof t?(n=ei(t).toRgb(),e=n.r,r=n.g,i=n.b,Ii(e,r,i)):Ii.apply(void 0,Ri(t));if(!o)return null;var a=o&Math.pow(2,24-this.csBits)-1,u=o>>24-this.csBits&Math.pow(2,this.csBits)-1;return Ui(a,this.csBits)!==u||a>=this.registry.length?null:this.registry[a]}}],e&&Ti(n.prototype,e),r&&Ti(n,r),Object.defineProperty(n,"prototype",{writable:!1}),t}();function Li(t,n,e){var r,i=1;function o(){var o,a,u=r.length,s=0,l=0,c=0;for(o=0;o=(i=(h+f)/2))?h=i:f=i,r=l,!(l=l[u=+a]))return r[u]=c,t;if(n===(o=+t._x.call(null,l.data)))return c.next=l,r?r[u]=c:t._root=c,t;do{r=r?r[u]=new Array(2):t._root=new Array(2),(a=n>=(i=(h+f)/2))?h=i:f=i}while((u=+a)==(s=+(o>=i)));return r[s]=l,r[u]=c,t}function Bi(t,n,e){this.node=t,this.x0=n,this.x1=e}function $i(t){return t[0]}function Hi(t,n){var e=new Vi(null==n?$i:n,NaN,NaN);return null==t?e:e.addAll(t)}function Vi(t,n,e){this._x=t,this._x0=n,this._x1=e,this._root=void 0}function Xi(t){for(var n={data:t.data},e=n;t=t.next;)e=e.next={data:t.data};return n}var Gi=Hi.prototype=Vi.prototype;function Yi(t,n,e,r){if(isNaN(n)||isNaN(e))return t;var i,o,a,u,s,l,c,h,f,d=t._root,p={data:r},g=t._x0,y=t._y0,v=t._x1,_=t._y1;if(!d)return t._root=p,t;for(;d.length;)if((l=n>=(o=(g+v)/2))?g=o:v=o,(c=e>=(a=(y+_)/2))?y=a:_=a,i=d,!(d=d[h=c<<1|l]))return i[h]=p,t;if(u=+t._x.call(null,d.data),s=+t._y.call(null,d.data),n===u&&e===s)return p.next=d,i?i[h]=p:t._root=p,t;do{i=i?i[h]=new Array(4):t._root=new Array(4),(l=n>=(o=(g+v)/2))?g=o:v=o,(c=e>=(a=(y+_)/2))?y=a:_=a}while((h=c<<1|l)==(f=(s>=a)<<1|u>=o));return i[f]=d,i[h]=p,t}function Wi(t,n,e,r,i){this.node=t,this.x0=n,this.y0=e,this.x1=r,this.y1=i}function Zi(t){return t[0]}function Qi(t){return t[1]}function Ki(t,n,e){var r=new Ji(null==n?Zi:n,null==e?Qi:e,NaN,NaN,NaN,NaN);return null==t?r:r.addAll(t)}function Ji(t,n,e,r,i,o){this._x=t,this._y=n,this._x0=e,this._y0=r,this._x1=i,this._y1=o,this._root=void 0}function to(t){for(var n={data:t.data},e=n;t=t.next;)e=e.next={data:t.data};return n}Gi.copy=function(){var t,n,e=new Vi(this._x,this._x0,this._x1),r=this._root;if(!r)return e;if(!r.length)return e._root=Xi(r),e;for(t=[{source:r,target:e._root=new Array(2)}];r=t.pop();)for(var i=0;i<2;++i)(n=r.source[i])&&(n.length?t.push({source:n,target:r.target[i]=new Array(2)}):r.target[i]=Xi(n));return e},Gi.add=function(t){const n=+this._x.call(null,t);return qi(this.cover(n),n,t)},Gi.addAll=function(t){Array.isArray(t)||(t=Array.from(t));const n=t.length,e=new Float64Array(n);let r=1/0,i=-1/0;for(let o,a=0;ai&&(i=o));if(r>i)return this;this.cover(r).cover(i);for(let r=0;rt||t>=e;)switch(i=+(ts||(i=o.x1)=h))&&(o=l[l.length-1],l[l.length-1]=l[l.length-1-a],l[l.length-1-a]=o)}else{var f=Math.abs(t-+this._x.call(null,c.data));f=(a=(h+f)/2))?h=a:f=a,n=c,!(c=c[s=+u]))return this;if(!c.length)break;n[s+1&1]&&(e=n,l=s)}for(;c.data!==t;)if(r=c,!(c=c.next))return this;return(i=c.next)&&delete c.next,r?(i?r.next=i:delete r.next,this):n?(i?n[s]=i:delete n[s],(c=n[0]||n[1])&&c===(n[1]||n[0])&&!c.length&&(e?e[l]=c:this._root=c),this):(this._root=i,this)},Gi.removeAll=function(t){for(var n=0,e=t.length;n=(a=(m+w)/2))?m=a:w=a,(d=e>=(u=(x+k)/2))?x=u:k=u,(p=r>=(s=(b+M)/2))?b=s:M=s,o=v,!(v=v[g=p<<2|d<<1|f]))return o[g]=_,t;if(l=+t._x.call(null,v.data),c=+t._y.call(null,v.data),h=+t._z.call(null,v.data),n===l&&e===c&&r===h)return _.next=v,o?o[g]=_:t._root=_,t;do{o=o?o[g]=new Array(8):t._root=new Array(8),(f=n>=(a=(m+w)/2))?m=a:w=a,(d=e>=(u=(x+k)/2))?x=u:k=u,(p=r>=(s=(b+M)/2))?b=s:M=s}while((g=p<<2|d<<1|f)==(y=(h>=s)<<2|(c>=u)<<1|l>=a));return o[y]=v,o[g]=_,t}function ro(t,n,e,r,i,o,a){this.node=t,this.x0=n,this.y0=e,this.z0=r,this.x1=i,this.y1=o,this.z1=a}function io(t){return t[0]}function oo(t){return t[1]}function ao(t){return t[2]}function uo(t,n,e,r){var i=new so(null==n?io:n,null==e?oo:e,null==r?ao:r,NaN,NaN,NaN,NaN,NaN,NaN);return null==t?i:i.addAll(t)}function so(t,n,e,r,i,o,a,u,s){this._x=t,this._y=n,this._z=e,this._x0=r,this._y0=i,this._z0=o,this._x1=a,this._y1=u,this._z1=s,this._root=void 0}function lo(t){for(var n={data:t.data},e=n;t=t.next;)e=e.next={data:t.data};return n}no.copy=function(){var t,n,e=new Ji(this._x,this._y,this._x0,this._y0,this._x1,this._y1),r=this._root;if(!r)return e;if(!r.length)return e._root=to(r),e;for(t=[{source:r,target:e._root=new Array(4)}];r=t.pop();)for(var i=0;i<4;++i)(n=r.source[i])&&(n.length?t.push({source:n,target:r.target[i]=new Array(4)}):r.target[i]=to(n));return e},no.add=function(t){const n=+this._x.call(null,t),e=+this._y.call(null,t);return Yi(this.cover(n,e),n,e,t)},no.addAll=function(t){var n,e,r,i,o=t.length,a=new Array(o),u=new Array(o),s=1/0,l=1/0,c=-1/0,h=-1/0;for(e=0;ec&&(c=r),ih&&(h=i));if(s>c||l>h)return this;for(this.cover(s,l).cover(c,h),e=0;et||t>=i||r>n||n>=o;)switch(u=(nf||(o=s.y0)>d||(a=s.x1)=v)<<1|t>=y)&&(s=p[p.length-1],p[p.length-1]=p[p.length-1-l],p[p.length-1-l]=s)}else{var _=t-+this._x.call(null,g.data),m=n-+this._y.call(null,g.data),x=_*_+m*m;if(x=(u=(p+y)/2))?p=u:y=u,(c=a>=(s=(g+v)/2))?g=s:v=s,n=d,!(d=d[h=c<<1|l]))return this;if(!d.length)break;(n[h+1&3]||n[h+2&3]||n[h+3&3])&&(e=n,f=h)}for(;d.data!==t;)if(r=d,!(d=d.next))return this;return(i=d.next)&&delete d.next,r?(i?r.next=i:delete r.next,this):n?(i?n[h]=i:delete n[h],(d=n[0]||n[1]||n[2]||n[3])&&d===(n[3]||n[2]||n[1]||n[0])&&!d.length&&(e?e[f]=d:this._root=d),this):(this._root=i,this)},no.removeAll=function(t){for(var n=0,e=t.length;n1&&(v=f.y+f.vy-c.y-c.vy||fo(u)),i>2&&(_=f.z+f.vz-c.z-c.vz||fo(u)),y*=d=((d=Math.sqrt(y*y+v*v+_*_))-e[g])/d*r*n[g],v*=d,_*=d,f.vx-=y*(p=a[g]),i>1&&(f.vy-=v*p),i>2&&(f.vz-=_*p),c.vx+=y*(p=1-p),i>1&&(c.vy+=v*p),i>2&&(c.vz+=_*p)}function d(){if(r){var i,u,l=r.length,c=t.length,h=new Map(r.map(((t,n)=>[s(t,n,r),t])));for(i=0,o=new Array(l);i"function"==typeof t))||Math.random,i=n.find((t=>[1,2,3].includes(t)))||2,d()},f.links=function(n){return arguments.length?(t=n,d(),f):t},f.id=function(t){return arguments.length?(s=t,f):s},f.iterations=function(t){return arguments.length?(h=+t,f):h},f.strength=function(t){return arguments.length?(l="function"==typeof t?t:ho(+t),p(),f):l},f.distance=function(t){return arguments.length?(c="function"==typeof t?t:ho(+t),g(),f):c},f}co.copy=function(){var t,n,e=new so(this._x,this._y,this._z,this._x0,this._y0,this._z0,this._x1,this._y1,this._z1),r=this._root;if(!r)return e;if(!r.length)return e._root=lo(r),e;for(t=[{source:r,target:e._root=new Array(8)}];r=t.pop();)for(var i=0;i<8;++i)(n=r.source[i])&&(n.length?t.push({source:n,target:r.target[i]=new Array(8)}):r.target[i]=lo(n));return e},co.add=function(t){const n=+this._x.call(null,t),e=+this._y.call(null,t),r=+this._z.call(null,t);return eo(this.cover(n,e,r),n,e,r,t)},co.addAll=function(t){Array.isArray(t)||(t=Array.from(t));const n=t.length,e=new Float64Array(n),r=new Float64Array(n),i=new Float64Array(n);let o=1/0,a=1/0,u=1/0,s=-1/0,l=-1/0,c=-1/0;for(let h,f,d,p,g=0;gs&&(s=f),dl&&(l=d),pc&&(c=p));if(o>s||a>l||u>c)return this;this.cover(o,a,u).cover(s,l,c);for(let o=0;ot||t>=a||i>n||n>=u||o>e||e>=s;)switch(c=(ey||(a=h.y0)>v||(u=h.z0)>_||(s=h.x1)=k)<<2|(n>=w)<<1|t>=b)&&(h=m[m.length-1],m[m.length-1]=m[m.length-1-f],m[m.length-1-f]=h)}else{var M=t-+this._x.call(null,x.data),z=n-+this._y.call(null,x.data),A=e-+this._z.call(null,x.data),S=M*M+z*z+A*A;if(S=(s=(v+x)/2))?v=s:x=s,(f=a>=(l=(_+b)/2))?_=l:b=l,(d=u>=(c=(m+w)/2))?m=c:w=c,n=y,!(y=y[p=d<<2|f<<1|h]))return this;if(!y.length)break;(n[p+1&7]||n[p+2&7]||n[p+3&7]||n[p+4&7]||n[p+5&7]||n[p+6&7]||n[p+7&7])&&(e=n,g=p)}for(;y.data!==t;)if(r=y,!(y=y.next))return this;return(i=y.next)&&delete y.next,r?(i?r.next=i:delete r.next,this):n?(i?n[p]=i:delete n[p],(y=n[0]||n[1]||n[2]||n[3]||n[4]||n[5]||n[6]||n[7])&&y===(n[7]||n[6]||n[5]||n[4]||n[3]||n[2]||n[1]||n[0])&&!y.length&&(e?e[g]=y:this._root=y),this):(this._root=i,this)},co.removeAll=function(t){for(var n=0,e=t.length;n(t=(vo*t+_o)%mo)/mo}();function d(){p(),h.call("tick",e),i1&&(null==c.fy?c.y+=c.vy*=s:(c.y=c.fy,c.vy=0)),r>2&&(null==c.fz?c.z+=c.vz*=s:(c.z=c.fz,c.vz=0));return e}function g(){for(var n,e=0,i=t.length;e1&&isNaN(n.y)||r>2&&isNaN(n.z)){var o=10*(r>2?Math.cbrt(.5+e):r>1?Math.sqrt(.5+e):e),a=e*ko,u=e*Mo;1===r?n.x=o:2===r?(n.x=o*Math.cos(a),n.y=o*Math.sin(a)):(n.x=o*Math.sin(a)*Math.cos(u),n.y=o*Math.cos(a),n.z=o*Math.sin(a)*Math.sin(u))}(isNaN(n.vx)||r>1&&isNaN(n.vy)||r>2&&isNaN(n.vz))&&(n.vx=0,r>1&&(n.vy=0),r>2&&(n.vz=0))}}function y(n){return n.initialize&&n.initialize(t,f,r),n}return null==t&&(t=[]),g(),e={tick:p,restart:function(){return c.restart(d),e},stop:function(){return c.stop(),e},numDimensions:function(t){return arguments.length?(r=Math.min(3,Math.max(1,Math.round(t))),l.forEach(y),e):r},nodes:function(n){return arguments.length?(t=n,g(),l.forEach(y),e):t},alpha:function(t){return arguments.length?(i=+t,e):i},alphaMin:function(t){return arguments.length?(o=+t,e):o},alphaDecay:function(t){return arguments.length?(a=+t,e):+a},alphaTarget:function(t){return arguments.length?(u=+t,e):u},velocityDecay:function(t){return arguments.length?(s=1-t,e):1-s},randomSource:function(t){return arguments.length?(f=t,l.forEach(y),e):f},force:function(t,n){return arguments.length>1?(null==n?l.delete(t):l.set(t,y(n)),e):l.get(t)},find:function(){var n,e,i,o,a,u,s=Array.prototype.slice.call(arguments),l=s.shift()||0,c=(r>1?s.shift():null)||0,h=(r>2?s.shift():null)||0,f=s.shift()||1/0,d=0,p=t.length;for(f*=f,d=0;d1?(h.on(t,n),e):h.on(t)}}}function Ao(){var t,n,e,r,i,o,a=ho(-30),u=1,s=1/0,l=.81;function c(r){var o,a=t.length,u=(1===n?Hi(t,xo):2===n?Ki(t,xo,bo):3===n?uo(t,xo,bo,wo):null).visitAfter(f);for(i=r,o=0;o1&&(t.y=a/c),n>2&&(t.z=u/c)}else{(e=t).x=e.data.x,n>1&&(e.y=e.data.y),n>2&&(e.z=e.data.z);do{l+=o[e.data.index]}while(e=e.next)}t.value=l}function d(t,a,c,h,f){if(!t.value)return!0;var d=[c,h,f][n-1],p=t.x-e.x,g=n>1?t.y-e.y:0,y=n>2?t.z-e.z:0,v=d-a,_=p*p+g*g+y*y;if(v*v/l<_)return _1&&0===g&&(_+=(g=fo(r))*g),n>2&&0===y&&(_+=(y=fo(r))*y),_1&&(e.vy+=g*t.value*i/_),n>2&&(e.vz+=y*t.value*i/_)),!0;if(!(t.length||_>=s)){(t.data!==e||t.next)&&(0===p&&(_+=(p=fo(r))*p),n>1&&0===g&&(_+=(g=fo(r))*g),n>2&&0===y&&(_+=(y=fo(r))*y),_1&&(e.vy+=g*v),n>2&&(e.vz+=y*v))}while(t=t.next)}}return c.initialize=function(e,...i){t=e,r=i.find((t=>"function"==typeof t))||Math.random,n=i.find((t=>[1,2,3].includes(t)))||2,h()},c.strength=function(t){return arguments.length?(a="function"==typeof t?t:ho(+t),h(),c):a},c.distanceMin=function(t){return arguments.length?(u=t*t,c):Math.sqrt(u)},c.distanceMax=function(t){return arguments.length?(s=t*t,c):Math.sqrt(s)},c.theta=function(t){return arguments.length?(l=t*t,c):Math.sqrt(l)},c}const{abs:So,cos:Co,sin:Eo,acos:Oo,atan2:No,sqrt:Po,pow:jo}=Math;function To(t){return t<0?-jo(-t,1/3):jo(t,1/3)}const Ro=Math.PI,Do=2*Ro,Io=Ro/2,Uo=Number.MAX_SAFE_INTEGER||9007199254740991,Fo=Number.MIN_SAFE_INTEGER||-9007199254740991,Lo={x:0,y:0,z:0},qo={Tvalues:[-.06405689286260563,.06405689286260563,-.1911188674736163,.1911188674736163,-.3150426796961634,.3150426796961634,-.4337935076260451,.4337935076260451,-.5454214713888396,.5454214713888396,-.6480936519369755,.6480936519369755,-.7401241915785544,.7401241915785544,-.820001985973903,.820001985973903,-.8864155270044011,.8864155270044011,-.9382745520027328,.9382745520027328,-.9747285559713095,.9747285559713095,-.9951872199970213,.9951872199970213],Cvalues:[.12793819534675216,.12793819534675216,.1258374563468283,.1258374563468283,.12167047292780339,.12167047292780339,.1155056680537256,.1155056680537256,.10744427011596563,.10744427011596563,.09761865210411388,.09761865210411388,.08619016153195327,.08619016153195327,.0733464814110803,.0733464814110803,.05929858491543678,.05929858491543678,.04427743881741981,.04427743881741981,.028531388628933663,.028531388628933663,.0123412297999872,.0123412297999872],arcfn:function(t,n){const e=n(t);let r=e.x*e.x+e.y*e.y;return void 0!==e.z&&(r+=e.z*e.z),Po(r)},compute:function(t,n,e){if(0===t)return n[0].t=0,n[0];const r=n.length-1;if(1===t)return n[r].t=1,n[r];const i=1-t;let o=n;if(0===r)return n[0].t=t,n[0];if(1===r){const n={x:i*o[0].x+t*o[1].x,y:i*o[0].y+t*o[1].y,t:t};return e&&(n.z=i*o[0].z+t*o[1].z),n}if(r<4){let n,a,u,s=i*i,l=t*t,c=0;2===r?(o=[o[0],o[1],o[2],Lo],n=s,a=i*t*2,u=l):3===r&&(n=s*i,a=s*t*3,u=i*l*3,c=t*l);const h={x:n*o[0].x+a*o[1].x+u*o[2].x+c*o[3].x,y:n*o[0].y+a*o[1].y+u*o[2].y+c*o[3].y,t:t};return e&&(h.z=n*o[0].z+a*o[1].z+u*o[2].z+c*o[3].z),h}const a=JSON.parse(JSON.stringify(n));for(;a.length>1;){for(let n=0;n1;i--,o--){const t=[];for(let e,i=0;io.x.min&&(n=o.x.min),e>o.y.min&&(e=o.y.min),r0&&(a.c1=n,a.c2=r,a.s1=t,a.s2=e,o.push(a))}))})),o},makeshape:function(t,n,e){const r=n.points.length,i=t.points.length,o=qo.makeline(n.points[r-1],t.points[0]),a=qo.makeline(t.points[i-1],n.points[0]),u={startcap:o,forward:t,back:n,endcap:a,bbox:qo.findbbox([o,t,n,a]),intersections:function(t){return qo.shapeintersections(u,u.bbox,t,t.bbox,e)}};return u},getminmax:function(t,n,e){if(!e)return{min:0,max:0};let r,i,o=Uo,a=Fo;-1===e.indexOf(0)&&(e=[0].concat(e)),-1===e.indexOf(1)&&e.push(1);for(let u=0,s=e.length;ua&&(a=i[n]);return{min:o,mid:(o+a)/2,max:a,size:a-o}},align:function(t,n){const e=n.p1.x,r=n.p1.y,i=-No(n.p2.y-r,n.p2.x-e);return t.map((function(t){return{x:(t.x-e)*Co(i)-(t.y-r)*Eo(i),y:(t.x-e)*Eo(i)+(t.y-r)*Co(i)}}))},roots:function(t,n){n=n||{p1:{x:0,y:0},p2:{x:1,y:0}};const e=t.length-1,r=qo.align(t,n),i=function(t){return 0<=t&&t<=1};if(2===e){const t=r[0].y,n=r[1].y,e=r[2].y,o=t-2*n+e;if(0!==o){const r=-Po(n*n-t*e),a=-t+n;return[-(r+a)/o,-(-r+a)/o].filter(i)}return n!==e&&0===o?[(2*n-e)/(2*n-2*e)].filter(i):[]}const o=r[0].y,a=r[1].y,u=r[2].y;let s=3*a-o-3*u+r[3].y,l=3*o-6*a+3*u,c=-3*o+3*a,h=o;if(qo.approximately(s,0)){if(qo.approximately(l,0))return qo.approximately(c,0)?[]:[-h/c].filter(i);const t=Po(c*c-4*l*h),n=2*l;return[(t-c)/n,(-c-t)/n].filter(i)}l/=s,c/=s,h/=s;const f=(3*c-l*l)/3,d=f/3,p=(2*l*l*l-9*l*c+27*h)/27,g=p/2,y=g*g+d*d*d;let v,_,m,x,b;if(y<0){const t=-f/3,n=Po(t*t*t),e=-p/(2*n),r=Oo(e<-1?-1:e>1?1:e),o=2*To(n);return m=o*Co(r/3)-l/3,x=o*Co((r+Do)/3)-l/3,b=o*Co((r+2*Do)/3)-l/3,[m,x,b].filter(i)}if(0===y)return v=g<0?To(-g):-To(g),m=2*v-l/3,x=-v-l/3,[m,x].filter(i);{const t=Po(y);return v=To(-g+t),_=To(g+t),[v-_-l/3].filter(i)}},droots:function(t){if(3===t.length){const n=t[0],e=t[1],r=t[2],i=n-2*e+r;if(0!==i){const t=-Po(e*e-n*r),o=-n+e;return[-(t+o)/i,-(-t+o)/i]}return e!==r&&0===i?[(2*e-r)/(2*(e-r))]:[]}if(2===t.length){const n=t[0],e=t[1];return n!==e?[n/(n-e)]:[]}return[]},curvature:function(t,n,e,r,i){let o,a,u,s,l=0,c=0;const h=qo.compute(t,n),f=qo.compute(t,e),d=h.x*h.x+h.y*h.y;if(r?(o=Po(jo(h.y*f.z-f.y*h.z,2)+jo(h.z*f.x-f.z*h.x,2)+jo(h.x*f.y-f.x*h.y,2)),a=jo(d+h.z*h.z,1.5)):(o=h.x*f.y-h.y*f.x,a=jo(d,1.5)),0===o||0===a)return{k:0,r:0};if(l=o/a,c=a/o,!i){const i=qo.curvature(t-.001,n,e,r,!0).k,o=qo.curvature(t+.001,n,e,r,!0).k;s=(o-l+(l-i))/2,u=(So(o-l)+So(l-i))/2}return{k:l,r:c,dk:s,adk:u}},inflections:function(t){if(t.length<4)return[];const n=qo.align(t,{p1:t[0],p2:t.slice(-1)[0]}),e=n[2].x*n[1].y,r=n[3].x*n[1].y,i=n[1].x*n[2].y,o=18*(-3*e+2*r+3*i-n[3].x*n[2].y),a=18*(3*e-r-3*i),u=18*(i-e);if(qo.approximately(o,0)){if(!qo.approximately(a,0)){let t=-u/a;if(0<=t&&t<=1)return[t]}return[]}const s=2*o;if(qo.approximately(s,0))return[];const l=a*a-4*o*u;if(l<0)return[];const c=Math.sqrt(l);return[(c-a)/s,-(a+c)/s].filter((function(t){return 0<=t&&t<=1}))},bboxoverlap:function(t,n){const e=["x","y"],r=e.length;for(let i,o,a,u,s=0;s=u)return!1;return!0},expandbox:function(t,n){n.x.mint.x.max&&(t.x.max=n.x.max),n.y.max>t.y.max&&(t.y.max=n.y.max),n.z&&n.z.max>t.z.max&&(t.z.max=n.z.max),t.x.mid=(t.x.min+t.x.max)/2,t.y.mid=(t.y.min+t.y.max)/2,t.z&&(t.z.mid=(t.z.min+t.z.max)/2),t.x.size=t.x.max-t.x.min,t.y.size=t.y.max-t.y.min,t.z&&(t.z.size=t.z.max-t.z.min)},pairiteration:function(t,n,e){const r=t.bbox(),i=n.bbox(),o=1e5,a=e||.5;if(r.x.size+r.y.sizek||k>M)&&(w+=Do),w>M&&(b=M,M=w,w=b)):M4){if(1!==arguments.length)throw new Error("Only new Bezier(point[]) is accepted for 4th and higher order curves");r=!0}}else if(6!==i&&8!==i&&9!==i&&12!==i&&1!==arguments.length)throw new Error("Only new Bezier(point[]) is accepted for 4th and higher order curves");const o=this._3d=!r&&(9===i||12===i)||t&&t[0]&&void 0!==t[0].z,a=this.points=[];for(let t=0,e=o?3:2;tt+$o(n.y)),0)0}length(){return qo.length(this.derivative.bind(this))}static getABC(t=2,n,e,r,i=.5){const o=qo.projectionratio(i,t),a=1-o,u={x:o*n.x+a*r.x,y:o*n.y+a*r.y},s=qo.abcratio(i,t);return{A:{x:e.x+(e.x-u.x)/s,y:e.y+(e.y-u.y)/s},B:e,C:u,S:n,E:r}}getABC(t,n){n=n||this.get(t);let e=this.points[0],r=this.points[this.order];return Qo.getABC(this.order,e,n,r,t)}getLUT(t){if(this.verify(),t=t||100,this._lut.length===t+1)return this._lut;this._lut=[],t++,this._lut=[];for(let n,e,r=0;r1?1:h,s=this.compute(h),s.t=h,s.d=l,s}get(t){return this.compute(t)}point(t){return this.points[t]}compute(t){return this.ratios?qo.computeWithRatios(t,this.points,this.ratios,this._3d):qo.compute(t,this.points,this._3d,this.ratios)}raise(){const t=this.points,n=[t[0]],e=t.length;for(let r,i,o=1;o1;){e=[];for(let o,a=0,u=n.length-1;a=0&&t<=1})),n=n.concat(t[e].sort(qo.numberSort))}.bind(this)),t.values=n.sort(qo.numberSort).filter((function(t,e){return n.indexOf(t)===e})),t}bbox(){const t=this.extrema(),n={};return this.dims.forEach(function(e){n[e]=qo.getminmax(this,e,t[e])}.bind(this)),n}overlaps(t){const n=this.bbox(),e=t.bbox();return qo.bboxoverlap(n,e)}offset(t,n){if(void 0!==n){const e=this.get(t),r=this.normal(t),i={c:e,n:r,x:e.x+r.x*n,y:e.y+r.y*n};return this._3d&&(i.z=e.z+r.z*n),i}if(this._linear){const n=this.normal(0),e=this.points.map((function(e){const r={x:e.x+t*n.x,y:e.y+t*n.y};return e.z&&n.z&&(r.z=e.z+t*n.z),r}));return[new Qo(e)]}return this.reduce().map((function(n){return n._linear?n.offset(t)[0]:n.scale(t)}))}simple(){if(3===this.order){const t=qo.angle(this.points[0],this.points[3],this.points[1]),n=qo.angle(this.points[0],this.points[3],this.points[2]);if(t>0&&n<0||t<0&&n>0)return!1}const t=this.normal(0),n=this.normal(1);let e=t.x*n.x+t.y*n.y;return this._3d&&(e+=t.z*n.z),$o(Yo(e))(1-i/r)*n+i/r*e));return new Qo(this.points.map(((n,e)=>({x:n.x+t.x*i[e],y:n.y+t.y*i[e]}))))}scale(t){const n=this.order;let e=!1;if("function"==typeof t&&(e=t),e&&2===n)return this.raise().scale(e);const r=this.clockwise,i=this.points;if(this._linear)return this.translate(this.normal(0),e?e(0):t,e?e(1):t);const o=e?e(0):t,a=e?e(1):t,u=[this.offset(0,10),this.offset(1,10)],s=[],l=qo.lli4(u[0],u[0].c,u[1],u[1].c);if(!l)throw new Error("cannot scale this curve. Try reducing it first.");return[0,1].forEach((function(t){const e=s[t*n]=qo.copy(i[t*n]);e.x+=(t?a:o)*u[t].n.x,e.y+=(t?a:o)*u[t].n.y})),e?([0,1].forEach((function(o){if(2!==n||!o){var a=i[o+1],u={x:a.x-l.x,y:a.y-l.y},c=e?e((o+1)/n):t;e&&!r&&(c=-c);var h=Wo(u.x*u.x+u.y*u.y);u.x/=h,u.y/=h,s[o+1]={x:a.x+c*u.x,y:a.y+c*u.y}}})),new Qo(s)):([0,1].forEach((t=>{if(2===n&&t)return;const e=s[t*n],r=this.derivative(t),o={x:e.x+r.x,y:e.y+r.y};s[t+1]=qo.lli4(e,o,l,i[t+1])})),new Qo(s))}outline(t,n,e,r){if(n=void 0===n?t:n,this._linear){const i=this.normal(0),o=this.points[0],a=this.points[this.points.length-1];let u,s,l;void 0===e&&(e=t,r=n),u={x:o.x+i.x*t,y:o.y+i.y*t},l={x:a.x+i.x*e,y:a.y+i.y*e},s={x:(u.x+l.x)/2,y:(u.y+l.y)/2};const c=[u,s,l];u={x:o.x-i.x*n,y:o.y-i.y*n},l={x:a.x-i.x*r,y:a.y-i.y*r},s={x:(u.x+l.x)/2,y:(u.y+l.y)/2};const h=[l,s,u],f=qo.makeline(h[2],c[0]),d=qo.makeline(c[2],h[0]),p=[f,new Qo(c),d,new Qo(h)];return new Bo(p)}const i=this.reduce(),o=i.length,a=[];let u,s=[],l=0,c=this.length();const h=void 0!==e&&void 0!==r;function f(t,n,e,r,i){return function(o){const a=r/e,u=(r+i)/e,s=n-t;return qo.map(o,0,1,t+a*s,t+u*s)}}i.forEach((function(i){const o=i.length();h?(a.push(i.scale(f(t,e,c,l,o))),s.push(i.scale(f(-n,-r,c,l,o)))):(a.push(i.scale(t)),s.push(i.scale(-n))),l+=o})),s=s.map((function(t){return u=t.points,u[3]?t.points=[u[3],u[2],u[1],u[0]]:t.points=[u[2],u[1],u[0]],t})).reverse();const d=a[0].points[0],p=a[o-1].points[a[o-1].points.length-1],g=s[o-1].points[s[o-1].points.length-1],y=s[0].points[0],v=qo.makeline(g,d),_=qo.makeline(p,y),m=[v].concat(a).concat([_]).concat(s);return new Bo(m)}outlineshapes(t,n,e){n=n||t;const r=this.outline(t,n).curves,i=[];for(let t=1,n=r.length;t1,o.endcap.virtual=t{var o=this.get(t);return qo.between(o.x,n,r)&&qo.between(o.y,e,i)}))}selfintersects(t){const n=this.reduce(),e=n.length-2,r=[];for(let i,o,a,u=0;u0&&(i=i.concat(n))})),i}arcs(t){return t=t||.5,this._iterate(t,[])}_error(t,n,e,r){const i=(r-e)/4,o=this.get(e+i),a=this.get(r-i),u=qo.dist(t,n),s=qo.dist(t,o),l=qo.dist(t,a);return $o(s-u)+$o(l-u)}_iterate(t,n){let e,r=0,i=1;do{e=0,i=1;let o,a,u,s,l,c=this.get(r),h=!1,f=!1,d=i,p=1;do{if(f=h,s=u,d=(r+i)/2,o=this.get(d),a=this.get(i),u=qo.getccenter(c,o,a),u.interval={start:r,end:i},h=this._error(u,c,r,i)<=t,l=f&&!h,l||(p=i),h){if(i>=1){if(u.interval.end=p=1,s=u,i>1){let t={x:u.x+u.r*Xo(u.e),y:u.y+u.r*Go(u.e)};u.e+=qo.angle({x:u.x,y:u.y},t,this.get(1))}break}i+=(i-r)/2}else i=d}while(!l&&e++<100);if(e>=100)break;s=s||u,n.push(s),r=p}while(i<1);return n}}function Ko(t,n){if(null==t)return{};var e,r,i=function(t,n){if(null==t)return{};var e,r,i={},o=Object.keys(t);for(r=0;r=0||(i[e]=t[e]);return i}(t,n);if(Object.getOwnPropertySymbols){var o=Object.getOwnPropertySymbols(t);for(r=0;r=0||Object.prototype.propertyIsEnumerable.call(t,e)&&(i[e]=t[e])}return i}function Jo(t,n){return function(t){if(Array.isArray(t))return t}(t)||function(t,n){var e=null==t?null:"undefined"!=typeof Symbol&&t[Symbol.iterator]||t["@@iterator"];if(null!=e){var r,i,o,a,u=[],s=!0,l=!1;try{if(o=(e=e.call(t)).next,0===n){if(Object(e)!==e)return;s=!1}else for(;!(s=(r=o.call(e)).done)&&(u.push(r.value),u.length!==n);s=!0);}catch(t){l=!0,i=t}finally{try{if(!s&&null!=e.return&&(a=e.return(),Object(a)!==a))return}finally{if(l)throw i}}return u}}(t,n)||na(t,n)||function(){throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}()}function ta(t){return function(t){if(Array.isArray(t))return ea(t)}(t)||function(t){if("undefined"!=typeof Symbol&&null!=t[Symbol.iterator]||null!=t["@@iterator"])return Array.from(t)}(t)||na(t)||function(){throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}()}function na(t,n){if(t){if("string"==typeof t)return ea(t,n);var e=Object.prototype.toString.call(t).slice(8,-1);return"Object"===e&&t.constructor&&(e=t.constructor.name),"Map"===e||"Set"===e?Array.from(t):"Arguments"===e||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(e)?ea(t,n):void 0}}function ea(t,n){(null==n||n>t.length)&&(n=t.length);for(var e=0,r=new Array(n);et.cooldownTicks||new Date-t.startTickTime>t.cooldownTime||t.d3AlphaMin>0&&t.forceLayout.alpha()0){var a=Math.atan2(r.y-e.y,r.x-e.x),u=i*n,s={x:(e.x+r.x)/2+u*Math.cos(a-Math.PI/2),y:(e.y+r.y)/2+u*Math.sin(a-Math.PI/2)};t.__controlPoints=[s.x,s.y]}else{var l=70*n;t.__controlPoints=[r.x,r.y-l,r.x+l,r.y]}}));var f=[],d=[],p=h;if(t.linkCanvasObject){var g=[],y=[];h.forEach((function(t){return({before:f,after:d,replace:g}[a(t)]||y).push(t)})),p=[].concat(s(f),d,y),f=f.concat(g)}l.save(),f.forEach((function(n){return t.linkCanvasObject(n,l,t.globalScale)})),l.restore();var v=function(){var t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:[],n=arguments.length>1&&void 0!==arguments[1]?arguments[1]:[],e=!(arguments.length>2&&void 0!==arguments[2])||arguments[2],r=arguments.length>3&&void 0!==arguments[3]&&arguments[3],i=(n instanceof Array?n.length?n:[void 0]:[n]).map((function(t){return{keyAccessor:t,isProp:!(t instanceof Function)}})),o=t.reduce((function(t,n){var r=t,o=n;return i.forEach((function(t,n){var a,u=t.keyAccessor;if(t.isProp){var s=o,l=s[u],c=Ko(s,[u].map(ra));a=l,o=c}else a=u(o,n);n+11&&void 0!==arguments[1]?arguments[1]:1;r===i.length?Object.keys(n).forEach((function(t){return n[t]=e(n[t])})):Object.values(n).forEach((function(n){return t(n,r+1)}))}(o);var a=o;return r&&(a=[],function t(n){var e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:[];e.length===i.length?a.push({keys:e,vals:n}):Object.entries(n).forEach((function(n){var r=Jo(n,2),i=r[0],o=r[1];return t(o,[].concat(ta(e),[i]))}))}(o),n instanceof Array&&0===n.length&&1===a.length&&(a[0].keys=[])),a}(p,[e,r,i]);l.save(),Object.entries(v).forEach((function(n){var e=u(n,2),r=e[0],o=e[1],a=r&&"undefined"!==r?r:"rgba(0,0,0,0.15)";Object.entries(o).forEach((function(n){var e=u(n,2),r=e[0],o=e[1],h=(r||1)/t.globalScale+c;Object.entries(o).forEach((function(t){var n=u(t,2);n[0];var e=n[1],r=i(e[0]);l.beginPath(),e.forEach((function(t){var n=t.source,e=t.target;if(n&&e&&n.hasOwnProperty("x")&&e.hasOwnProperty("x")){l.moveTo(n.x,n.y);var r=t.__controlPoints;r?l[2===r.length?"quadraticCurveTo":"bezierCurveTo"].apply(l,s(r).concat([e.x,e.y])):l.lineTo(e.x,e.y)}})),l.strokeStyle=a,l.lineWidth=h,l.setLineDash(r||[]),l.stroke()}))}))})),l.restore(),l.save(),d.forEach((function(n){return t.linkCanvasObject(n,l,t.globalScale)})),l.restore()}(),!t.isShadow&&(n=Kr(t.linkDirectionalArrowLength),e=Kr(t.linkDirectionalArrowRelPos),r=Kr(t.linkVisibility),i=Kr(t.linkDirectionalArrowColor||t.linkColor),o=Kr(t.nodeVal),(l=t.ctx).save(),t.graphData.links.filter(r).forEach((function(r){var u=n(r);if(u&&!(u<0)){var c=r.source,h=r.target;if(c&&h&&c.hasOwnProperty("x")&&h.hasOwnProperty("x")){var f=Math.sqrt(Math.max(0,o(c)||1))*t.nodeRelSize,d=Math.sqrt(Math.max(0,o(h)||1))*t.nodeRelSize,p=Math.min(1,Math.max(0,e(r))),g=i(r)||"rgba(0,0,0,0.28)",y=u/1.6/2,v=r.__controlPoints&&a(Qo,[c.x,c.y].concat(s(r.__controlPoints),[h.x,h.y])),_=v?function(t){return v.get(t)}:function(t){return{x:c.x+(h.x-c.x)*t||0,y:c.y+(h.y-c.y)*t||0}},m=v?v.length():Math.sqrt(Math.pow(h.x-c.x,2)+Math.pow(h.y-c.y,2)),x=f+u+(m-f-d-u)*p,b=_(x/m),w=_((x-u)/m),k=_((x-.8*u)/m),M=Math.atan2(b.y-w.y,b.x-w.x)-Math.PI/2;l.beginPath(),l.moveTo(b.x,b.y),l.lineTo(w.x+y*Math.cos(M),w.y+y*Math.sin(M)),l.lineTo(k.x,k.y),l.lineTo(w.x-y*Math.cos(M),w.y-y*Math.sin(M)),l.fillStyle=g,l.fill()}}})),l.restore()),!t.isShadow&&function(){var n=Kr(t.linkDirectionalParticles),e=Kr(t.linkDirectionalParticleSpeed),r=Kr(t.linkDirectionalParticleWidth),i=Kr(t.linkVisibility),o=Kr(t.linkDirectionalParticleColor||t.linkColor),u=t.ctx;u.save(),t.graphData.links.filter(i).forEach((function(i){var l=n(i);if(i.hasOwnProperty("__photons")&&i.__photons.length){var c=i.source,h=i.target;if(c&&h&&c.hasOwnProperty("x")&&h.hasOwnProperty("x")){var f=e(i),d=i.__photons||[],p=Math.max(0,r(i)/2)/Math.sqrt(t.globalScale),g=o(i)||"rgba(0,0,0,0.28)";u.fillStyle=g;var y=i.__controlPoints?a(Qo,[c.x,c.y].concat(s(i.__controlPoints),[h.x,h.y])):null,v=0,_=!1;d.forEach((function(t){var n=!!t.__singleHop;if(t.hasOwnProperty("__progressRatio")||(t.__progressRatio=n?0:v/l),!n&&v++,t.__progressRatio+=f,t.__progressRatio>=1){if(n)return void(_=!0);t.__progressRatio=t.__progressRatio%1}var e=t.__progressRatio,r=y?y.get(e):{x:c.x+(h.x-c.x)*e||0,y:c.y+(h.y-c.y)*e||0};u.beginPath(),u.arc(r.x,r.y,p,0,2*Math.PI,!1),u.fill()})),_&&(i.__photons=i.__photons.filter((function(t){return!t.__singleHop||t.__progressRatio<=1})))}}})),u.restore()}(),function(){var n=Kr(t.nodeVisibility),e=Kr(t.nodeVal),r=Kr(t.nodeColor),i=Kr(t.nodeCanvasObjectMode),o=t.ctx,a=t.isShadow/t.globalScale,u=t.graphData.nodes.filter(n);o.save(),u.forEach((function(n){var u=i(n);if(!t.nodeCanvasObject||"before"!==u&&"replace"!==u||(t.nodeCanvasObject(n,o,t.globalScale),"replace"!==u)){var s=Math.sqrt(Math.max(0,e(n)||1))*t.nodeRelSize+a;o.beginPath(),o.arc(n.x,n.y,s,0,2*Math.PI,!1),o.fillStyle=r(n)||"rgba(31, 120, 180, 0.92)",o.fill(),t.nodeCanvasObject&&"after"===u&&t.nodeCanvasObject(n,t.ctx,t.globalScale)}else o.restore()})),o.restore()}(),this},emitParticle:function(t,n){return n&&(!n.__photons&&(n.__photons=[]),n.__photons.push({__singleHop:!0})),this}},stateInit:function(){return{forceLayout:zo().force("link",yo()).force("charge",Ao()).force("center",Li()).force("dagRadial",null).stop(),engineRunning:!1}},init:function(t,n){n.ctx=t},update:function(t){t.engineRunning=!1,t.onUpdate(),null!==t.nodeAutoColorBy&&sa(t.graphData.nodes,Kr(t.nodeAutoColorBy),t.nodeColor),null!==t.linkAutoColorBy&&sa(t.graphData.links,Kr(t.linkAutoColorBy),t.linkColor),t.graphData.links.forEach((function(n){n.source=n[t.linkSource],n.target=n[t.linkTarget]})),t.forceLayout.stop().alpha(1).nodes(t.graphData.nodes);var n=t.forceLayout.force("link");n&&n.id((function(n){return n[t.nodeId]})).links(t.graphData.links);var e=t.dagMode&&function(t,n){var e=t.nodes,o=t.links,a=arguments.length>2&&void 0!==arguments[2]?arguments[2]:{},l=a.nodeFilter,c=void 0===l?function(){return!0}:l,h=a.onLoopError,f=void 0===h?function(t){throw"Invalid DAG structure! Found cycle in node path: ".concat(t.join(" -> "),".")}:h,d={};e.forEach((function(t){return d[n(t)]={data:t,out:[],depth:-1,skip:!c(t)}})),o.forEach((function(t){var e=t.source,i=t.target,o=l(e),a=l(i);if(!d.hasOwnProperty(o))throw"Missing source node with id: ".concat(o);if(!d.hasOwnProperty(a))throw"Missing target node with id: ".concat(a);var u=d[o],s=d[a];function l(t){return"object"===r(t)?n(t):t}u.out.push(s)}));var p=[];return function t(e){for(var r=arguments.length>1&&void 0!==arguments[1]?arguments[1]:[],i=arguments.length>2&&void 0!==arguments[2]?arguments[2]:0,o=function(){var o=e[a];if(-1!==r.indexOf(o)){var u=[].concat(s(r.slice(r.indexOf(o))),[o]).map((function(t){return n(t.data)}));return p.some((function(t){return t.length===u.length&&t.every((function(t,n){return t===u[n]}))}))||(p.push(u),f(u)),1}i>o.depth&&(o.depth=i,t(o.out,[].concat(s(r),[o]),i+(o.skip?0:1)))},a=0,u=e.length;a1&&(c.vy+=f*g),o>2&&(c.vz+=d*g)}}function c(){if(i){var n,e=i.length;for(a=new Array(e),u=new Array(e),n=0;n[1,2,3].includes(t)))||2,c()},l.strength=function(t){return arguments.length?(s="function"==typeof t?t:ho(+t),c(),l):s},l.radius=function(n){return arguments.length?(t="function"==typeof n?n:ho(+n),c(),l):t},l.x=function(t){return arguments.length?(n=+t,l):n},l.y=function(t){return arguments.length?(e=+t,l):e},l.z=function(t){return arguments.length?(r=+t,l):r},l}((function(n){var r=e[n[t.nodeId]]||-1;return("radialin"===t.dagMode?o-r:r)*a})).strength((function(n){return t.dagNodeFilter(n)?1:0})):null);for(var f=0;f0&&t.forceLayout.alpha()1?r-1:0),o=1;o1&&void 0!==arguments[1]?arguments[1]:0,e=arguments.length>2&&void 0!==arguments[2]?arguments[2]:10,r=arguments.length,i=new Array(r>3?r-3:0),o=3;o1&&void 0!==arguments[1]?arguments[1]:function(){return!0},e=Kr(t.nodeVal),r=function(n){return Math.sqrt(Math.max(0,e(n)||1))*t.nodeRelSize},i=t.graphData.nodes.filter(n).map((function(t){return{x:t.x,y:t.y,r:r(t)}}));return i.length?{x:[ur(i,(function(t){return t.x-t.r})),ar(i,(function(t){return t.x+t.r}))],y:[ur(i,(function(t){return t.y-t.r})),ar(i,(function(t){return t.y+t.r}))]}:null},pauseAnimation:function(t){return t.animationFrameRequestId&&(cancelAnimationFrame(t.animationFrameRequestId),t.animationFrameRequestId=null),this},resumeAnimation:function(t){return t.animationFrameRequestId||this._animationCycle(),this},_destructor:function(){this.pauseAnimation(),this.graphData({nodes:[],links:[]})}},ya),stateInit:function(){return{lastSetZoom:1,zoom:er(),forceGraph:new ha,shadowGraph:(new ha).cooldownTicks(0).nodeColor("__indexColor").linkColor("__indexColor").isShadow(!0),colorTracker:new Fi}},init:function(t,n){var r=this;t.innerHTML="";var i=document.createElement("div");i.classList.add("force-graph-container"),i.style.position="relative",t.appendChild(i),n.canvas=document.createElement("canvas"),n.backgroundColor&&(n.canvas.style.background=n.backgroundColor),i.appendChild(n.canvas),n.shadowCanvas=document.createElement("canvas");var o=n.canvas.getContext("2d"),a=n.shadowCanvas.getContext("2d",{willReadFrequently:!0}),u={x:-1e12,y:-1e12},s=function(){var t=null,e=window.devicePixelRatio,r=u.x>0&&u.y>0?a.getImageData(u.x*e,u.y*e,1,1):null;return r&&(t=n.colorTracker.lookup(r.data)),t};kt(n.canvas).call(function(){var t,n,e,r,i=Ut,o=Ft,a=Lt,u=qt,s={},l=At("start","drag","end"),c=0,h=0;function f(t){t.on("mousedown.drag",d).filter(u).on("touchstart.drag",y).on("touchmove.drag",v,Ot).on("touchend.drag touchcancel.drag",_).style("touch-action","none").style("-webkit-tap-highlight-color","rgba(0,0,0,0)")}function d(a,u){if(!r&&i.call(this,a,u)){var s=m(this,o.call(this,a,u),a,u,"mouse");s&&(kt(a.view).on("mousemove.drag",p,Nt).on("mouseup.drag",g,Nt),Tt(a.view),Pt(a),e=!1,t=a.clientX,n=a.clientY,s("start",a))}}function p(r){if(jt(r),!e){var i=r.clientX-t,o=r.clientY-n;e=i*i+o*o>h}s.mouse("drag",r)}function g(t){kt(t.view).on("mousemove.drag mouseup.drag",null),Rt(t.view,e),jt(t),s.mouse("end",t)}function y(t,n){if(i.call(this,t,n)){var e,r,a=t.changedTouches,u=o.call(this,t,n),s=a.length;for(e=0;e0||n.isPointerPressed)&&("touch"!==e.pointerType||void 0===e.movementX||[e.movementX,e.movementY].some((function(t){return Math.abs(t)>1})))&&(n.isPointerDragging=!0);var r,o,a,s=(r=i.getBoundingClientRect(),o=window.pageXOffset||document.documentElement.scrollLeft,a=window.pageYOffset||document.documentElement.scrollTop,{top:r.top+a,left:r.left+o});u.x=e.pageX-s.left,u.y=e.pageY-s.top,l.style.top="".concat(u.y,"px"),l.style.left="".concat(u.x,"px"),l.style.transform="translate(-".concat(u.x/n.width*100,"%, ").concat(n.height-u.y<100?"calc(-100% - 8px)":"21px",")")}),{passive:!0})})),i.addEventListener("pointerup",(function(t){if(n.isPointerPressed=!1,n.isPointerDragging)n.isPointerDragging=!1;else{var e=[t,n.pointerDownEvent];requestAnimationFrame((function(){if(0===t.button)if(n.hoverObj){var r=n["on".concat(n.hoverObj.type,"Click")];r&&r.apply(void 0,[n.hoverObj.d].concat(e))}else n.onBackgroundClick&&n.onBackgroundClick.apply(n,e);if(2===t.button)if(n.hoverObj){var i=n["on".concat(n.hoverObj.type,"RightClick")];i&&i.apply(void 0,[n.hoverObj.d].concat(e))}else n.onBackgroundRightClick&&n.onBackgroundRightClick.apply(n,e)}))}}),{passive:!0}),i.addEventListener("contextmenu",(function(t){return!(n.onBackgroundRightClick||n.onNodeRightClick||n.onLinkRightClick)||(t.preventDefault(),!1)})),n.forceGraph(o),n.shadowGraph(a);var c=function(t,n,e){var r=!0,i=!0;if("function"!=typeof t)throw new TypeError("Expected a function");return zr(e)&&(r="leading"in e?!!e.leading:r,i="trailing"in e?!!e.trailing:i),Dr(t,n,{leading:r,maxWait:n,trailing:i})}((function(){ma(a,n.width,n.height),n.shadowGraph.linkWidth((function(t){return Kr(n.linkWidth)(t)+n.linkHoverPrecision}));var t=Ge(n.canvas);n.shadowGraph.globalScale(t.k).tickFrame()}),800);n.flushShadowCanvas=c.flush,(this._animationCycle=function t(){var e=!n.autoPauseRedraw||!!n.needsRedraw||n.forceGraph.isEngineRunning()||n.graphData.links.some((function(t){return t.__photons&&t.__photons.length}));if(n.needsRedraw=!1,n.enablePointerInteraction){var r=n.isPointerDragging?null:s();if(r!==n.hoverObj){var i=n.hoverObj,a=i?i.type:null,u=r?r.type:null;if(a&&a!==u){var h=n["on".concat(a,"Hover")];h&&h(null,i.d)}if(u){var f=n["on".concat(u,"Hover")];f&&f(r.d,a===u?i.d:null)}var d=r&&Kr(n["".concat(r.type.toLowerCase(),"Label")])(r.d)||"";l.style.visibility=d?"visible":"hidden",l.innerHTML=d,n.canvas.classList[r&&n["on".concat(u,"Click")]||!r&&n.onBackgroundClick?"add":"remove"]("clickable"),n.hoverObj=r}e&&c()}if(e){ma(o,n.width,n.height);var p=Ge(n.canvas).k;n.onRenderFramePre&&n.onRenderFramePre(o,p),n.forceGraph.globalScale(p).tickFrame(),n.onRenderFramePost&&n.onRenderFramePost(o,p)}Vr(),n.animationFrameRequestId=requestAnimationFrame(t)})()},update:function(t){}});return xa})); diff --git a/plugins/hal-zigbee/build.gradle b/plugins/hal-zigbee/build.gradle index c72615f0..d8e00e97 100644 --- a/plugins/hal-zigbee/build.gradle +++ b/plugins/hal-zigbee/build.gradle @@ -1,5 +1,5 @@ dependencies { - def ZIGBEE_LIB_VERSION = "1.4.11" + def ZIGBEE_LIB_VERSION = "1.4.13" implementation project(':hal-core') diff --git a/plugins/hal-zigbee/resources/web/zigbee_network.tmpl b/plugins/hal-zigbee/resources/web/zigbee_network.tmpl index bfd472d0..d41e7082 100644 --- a/plugins/hal-zigbee/resources/web/zigbee_network.tmpl +++ b/plugins/hal-zigbee/resources/web/zigbee_network.tmpl @@ -28,6 +28,31 @@ +

Network Graph

+ +
+ + +

Connected Nodes

{{#nodes}}